summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.babelrc.js44
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml237
-rw-r--r--.gitlab/issue_templates/Coding style proposal.md16
-rw-r--r--.gitlab/issue_templates/Doc Review.md20
-rw-r--r--.gitlab/issue_templates/Documentation.md75
-rw-r--r--.gitlab/issue_templates/Feature proposal.md44
-rw-r--r--.gitlab/issue_templates/Security Release.md69
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md23
-rw-r--r--.gitlab/merge_request_templates/Change documentation location.md2
-rw-r--r--.gitlab/merge_request_templates/Database changes.md6
-rw-r--r--.gitlab/merge_request_templates/Documentation.md40
-rw-r--r--.gitlab/merge_request_templates/Security Release.md31
-rw-r--r--.rubocop.yml4
-rw-r--r--.rubocop_todo.yml28
-rw-r--r--.stylelintrc107
-rw-r--r--CHANGELOG.md605
-rw-r--r--CONTRIBUTING.md45
-rw-r--r--Dangerfile1
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--Gemfile77
-rw-r--r--Gemfile.lock300
-rw-r--r--PROCESS.md64
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/api.js24
-rw-r--r--app/assets/javascripts/awards_handler.js18
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue2
-rw-r--r--app/assets/javascripts/badges/components/badge_list_row.vue4
-rw-r--r--app/assets/javascripts/behaviors/gl_emoji.js118
-rw-r--r--app/assets/javascripts/behaviors/markdown/copy_as_gfm.js443
-rw-r--r--app/assets/javascripts/behaviors/markdown/editor_extensions.js106
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/bold.js11
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/code.js11
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/inline_diff.js41
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/inline_html.js46
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/italic.js11
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/link.js21
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/math.js41
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/strike.js15
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/blockquote.js13
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js11
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/code_block.js99
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/description_details.js28
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/description_list.js28
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/description_term.js28
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/details.js28
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/doc.js15
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/emoji.js41
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/hard_break.js10
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/heading.js13
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js11
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/image.js52
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/list_item.js11
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/ordered_list.js10
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/ordered_task_list.js28
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/paragraph.js24
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/reference.js52
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/summary.js27
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/table.js25
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/table_body.js24
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/table_cell.js35
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/table_head.js24
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js43
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js33
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/table_row.js38
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/task_list.js28
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js49
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/text.js20
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/video.js54
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js19
-rw-r--r--app/assets/javascripts/behaviors/markdown/schema.js24
-rw-r--r--app/assets/javascripts/behaviors/markdown/serializer.js24
-rw-r--r--app/assets/javascripts/behaviors/preview_markdown.js15
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js47
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js9
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js20
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue2
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue2
-rw-r--r--app/assets/javascripts/boards/components/issue_due_date.vue11
-rw-r--r--app/assets/javascripts/boards/components/modal/empty_state.vue4
-rw-r--r--app/assets/javascripts/boards/components/modal/footer.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/header.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/list.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/tabs.vue4
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue2
-rw-r--r--app/assets/javascripts/boards/index.js2
-rw-r--r--app/assets/javascripts/boards/models/list.js1
-rw-r--r--app/assets/javascripts/boards/services/board_service.js3
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js65
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue192
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue22
-rw-r--r--app/assets/javascripts/clusters/constants.js9
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js22
-rw-r--r--app/assets/javascripts/commons/jquery.js1
-rw-r--r--app/assets/javascripts/contextual_sidebar.js66
-rw-r--r--app/assets/javascripts/deploy_keys/components/key.vue2
-rw-r--r--app/assets/javascripts/diffs/components/app.vue72
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue33
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue83
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions_dropdown.vue18
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue26
-rw-r--r--app/assets/javascripts/diffs/components/diff_discussions.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue66
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue26
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_gutter_content.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue10
-rw-r--r--app/assets/javascripts/diffs/components/diff_stats.vue52
-rw-r--r--app/assets/javascripts/diffs/components/edit_button.vue7
-rw-r--r--app/assets/javascripts/diffs/components/image_diff_overlay.vue4
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_comment_row.vue1
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_view.vue9
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue1
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_view.vue10
-rw-r--r--app/assets/javascripts/diffs/components/settings_dropdown.vue92
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue165
-rw-r--r--app/assets/javascripts/diffs/constants.js10
-rw-r--r--app/assets/javascripts/diffs/index.js64
-rw-r--r--app/assets/javascripts/diffs/mixins/draft_comments.js7
-rw-r--r--app/assets/javascripts/diffs/store/actions.js56
-rw-r--r--app/assets/javascripts/diffs/store/getters.js30
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js5
-rw-r--r--app/assets/javascripts/diffs/store/mutation_types.js5
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js19
-rw-r--r--app/assets/javascripts/diffs/store/utils.js85
-rw-r--r--app/assets/javascripts/diffs/workers/tree_worker.js14
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_form.js7
-rw-r--r--app/assets/javascripts/dismissable_callout.js27
-rw-r--r--app/assets/javascripts/due_date_select.js2
-rw-r--r--app/assets/javascripts/emoji/index.js72
-rw-r--r--app/assets/javascripts/emoji/no_emoji_validator.js63
-rw-r--r--app/assets/javascripts/emoji/support/index.js3
-rw-r--r--app/assets/javascripts/environments/components/confirm_rollback_modal.vue108
-rw-r--r--app/assets/javascripts/environments/components/container.vue10
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue14
-rw-r--r--app/assets/javascripts/environments/components/environment_rollback.vue43
-rw-r--r--app/assets/javascripts/environments/components/environments_app.vue14
-rw-r--r--app/assets/javascripts/environments/components/environments_table.vue48
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_bundle.js8
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_view.vue5
-rw-r--r--app/assets/javascripts/environments/index.js2
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js40
-rw-r--r--app/assets/javascripts/environments/services/environments_service.js4
-rw-r--r--app/assets/javascripts/environments/stores/environments_store.js3
-rw-r--r--app/assets/javascripts/error_tracking/components/error_tracking_list.vue124
-rw-r--r--app/assets/javascripts/error_tracking/index.js31
-rw-r--r--app/assets/javascripts/error_tracking/services/index.js7
-rw-r--r--app/assets/javascripts/error_tracking/store/actions.js52
-rw-r--r--app/assets/javascripts/error_tracking/store/index.js19
-rw-r--r--app/assets/javascripts/error_tracking/store/mutation_types.js3
-rw-r--r--app/assets/javascripts/error_tracking/store/mutations.js14
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/app.vue129
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue91
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue82
-rw-r--r--app/assets/javascripts/error_tracking_settings/index.js27
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/actions.js91
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/getters.js44
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/index.js16
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/mutation_types.js11
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/mutations.js61
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/state.js12
-rw-r--r--app/assets/javascripts/error_tracking_settings/utils.js18
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight.js4
-rw-r--r--app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js16
-rw-r--r--app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js8
-rw-r--r--app/assets/javascripts/filtered_search/available_dropdown_mappings.js133
-rw-r--r--app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue4
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_ajax_filter.js68
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_user.js83
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js103
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_token_keys.js20
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js141
-rw-r--r--app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js22
-rw-r--r--app/assets/javascripts/filtered_search/visual_token_value.js125
-rw-r--r--app/assets/javascripts/fly_out_nav.js5
-rw-r--r--app/assets/javascripts/frequent_items/components/app.vue6
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue10
-rw-r--r--app/assets/javascripts/frequent_items/index.js6
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js61
-rw-r--r--app/assets/javascripts/gl_dropdown.js18
-rw-r--r--app/assets/javascripts/gl_form.js2
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue2
-rw-r--r--app/assets/javascripts/groups_select.js172
-rw-r--r--app/assets/javascripts/header.js6
-rw-r--r--app/assets/javascripts/ide/components/activity_bar.vue6
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/message_field.vue4
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue4
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue6
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue2
-rw-r--r--app/assets/javascripts/ide/components/editor_mode_dropdown.vue4
-rw-r--r--app/assets/javascripts/ide/components/file_finder/index.vue227
-rw-r--r--app/assets/javascripts/ide/components/file_finder/item.vue104
-rw-r--r--app/assets/javascripts/ide/components/file_templates/dropdown.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide.vue46
-rw-r--r--app/assets/javascripts/ide/components/ide_status_bar.vue15
-rw-r--r--app/assets/javascripts/ide/components/ide_tree.vue4
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue2
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/list.vue4
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/index.vue12
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue72
-rw-r--r--app/assets/javascripts/ide/components/panes/right.vue2
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue4
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue4
-rw-r--r--app/assets/javascripts/ide/components/resizable_panel.vue4
-rw-r--r--app/assets/javascripts/ide/components/shared/tokened_input.vue4
-rw-r--r--app/assets/javascripts/ide/constants.js21
-rw-r--r--app/assets/javascripts/ide/ide_router.js2
-rw-r--r--app/assets/javascripts/ide/index.js20
-rw-r--r--app/assets/javascripts/ide/lib/common/model.js6
-rw-r--r--app/assets/javascripts/ide/lib/files.js113
-rw-r--r--app/assets/javascripts/ide/services/index.js3
-rw-r--r--app/assets/javascripts/ide/stores/actions.js70
-rw-r--r--app/assets/javascripts/ide/stores/actions/merge_request.js32
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js29
-rw-r--r--app/assets/javascripts/ide/stores/actions/tree.js46
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js16
-rw-r--r--app/assets/javascripts/ide/stores/utils.js5
-rw-r--r--app/assets/javascripts/ide/stores/workers/files_decorator_worker.js100
-rw-r--r--app/assets/javascripts/import_projects/components/import_projects_table.vue101
-rw-r--r--app/assets/javascripts/import_projects/components/import_status.vue47
-rw-r--r--app/assets/javascripts/import_projects/components/imported_project_table_row.vue55
-rw-r--r--app/assets/javascripts/import_projects/components/provider_repo_table_row.vue110
-rw-r--r--app/assets/javascripts/import_projects/constants.js48
-rw-r--r--app/assets/javascripts/import_projects/event_hub.js (renamed from app/assets/javascripts/monitoring/event_hub.js)0
-rw-r--r--app/assets/javascripts/import_projects/index.js48
-rw-r--r--app/assets/javascripts/import_projects/store/actions.js106
-rw-r--r--app/assets/javascripts/import_projects/store/getters.js20
-rw-r--r--app/assets/javascripts/import_projects/store/index.js16
-rw-r--r--app/assets/javascripts/import_projects/store/mutation_types.js11
-rw-r--r--app/assets/javascripts/import_projects/store/mutations.js55
-rw-r--r--app/assets/javascripts/import_projects/store/state.js15
-rw-r--r--app/assets/javascripts/issuable/auto_width_dropdown_select.js12
-rw-r--r--app/assets/javascripts/issuable_context.js12
-rw-r--r--app/assets/javascripts/issuable_form.js63
-rw-r--r--app/assets/javascripts/issuable_suggestions/index.js4
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue62
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue24
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description.vue6
-rw-r--r--app/assets/javascripts/issue_show/components/form.vue6
-rw-r--r--app/assets/javascripts/issue_show/stores/index.js11
-rw-r--r--app/assets/javascripts/jobs/components/commit_block.vue2
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue21
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue70
-rw-r--r--app/assets/javascripts/jobs/components/stages_dropdown.vue6
-rw-r--r--app/assets/javascripts/jobs/store/getters.js27
-rw-r--r--app/assets/javascripts/label_manager.js13
-rw-r--r--app/assets/javascripts/labels_select.js32
-rw-r--r--app/assets/javascripts/layout_nav.js65
-rw-r--r--app/assets/javascripts/lazy_loader.js1
-rw-r--r--app/assets/javascripts/lib/graphql.js14
-rw-r--r--app/assets/javascripts/lib/utils/chart_utils.js83
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js87
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js164
-rw-r--r--app/assets/javascripts/lib/utils/file_upload.js3
-rw-r--r--app/assets/javascripts/lib/utils/grammar.js40
-rw-r--r--app/assets/javascripts/lib/utils/http_status.js1
-rw-r--r--app/assets/javascripts/lib/utils/icon_utils.js18
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js19
-rw-r--r--app/assets/javascripts/lib/utils/poll.js20
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js162
-rw-r--r--app/assets/javascripts/lib/utils/text_utility.js23
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js55
-rw-r--r--app/assets/javascripts/lib/utils/webpack.js10
-rw-r--r--app/assets/javascripts/locale/sprintf.js4
-rw-r--r--app/assets/javascripts/main.js128
-rw-r--r--app/assets/javascripts/member_expiration_date.js1
-rw-r--r--app/assets/javascripts/members.js27
-rw-r--r--app/assets/javascripts/merge_request.js9
-rw-r--r--app/assets/javascripts/merge_request_tabs.js2
-rw-r--r--app/assets/javascripts/monitoring/components/charts/area.vue234
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue94
-rw-r--r--app/assets/javascripts/monitoring/components/graph.vue329
-rw-r--r--app/assets/javascripts/monitoring/components/graph/axis.vue118
-rw-r--r--app/assets/javascripts/monitoring/components/graph/deployment.vue48
-rw-r--r--app/assets/javascripts/monitoring/components/graph/flag.vue151
-rw-r--r--app/assets/javascripts/monitoring/components/graph/legend.vue62
-rw-r--r--app/assets/javascripts/monitoring/components/graph/path.vue65
-rw-r--r--app/assets/javascripts/monitoring/components/graph/track_info.vue28
-rw-r--r--app/assets/javascripts/monitoring/components/graph/track_line.vue33
-rw-r--r--app/assets/javascripts/monitoring/constants.js10
-rw-r--r--app/assets/javascripts/monitoring/mixins/monitoring_mixins.js86
-rw-r--r--app/assets/javascripts/monitoring/stores/monitoring_store.js14
-rw-r--r--app/assets/javascripts/monitoring/utils/date_time_formatters.js42
-rw-r--r--app/assets/javascripts/monitoring/utils/measurements.js44
-rw-r--r--app/assets/javascripts/monitoring/utils/multiple_time_series.js223
-rw-r--r--app/assets/javascripts/mr_notes/index.js72
-rw-r--r--app/assets/javascripts/mr_notes/init_notes.js70
-rw-r--r--app/assets/javascripts/notebook/cells/code.vue15
-rw-r--r--app/assets/javascripts/notebook/cells/code/index.vue3
-rw-r--r--app/assets/javascripts/notebook/cells/output/html.vue15
-rw-r--r--app/assets/javascripts/notebook/cells/output/image.vue20
-rw-r--r--app/assets/javascripts/notebook/cells/output/index.vue104
-rw-r--r--app/assets/javascripts/notebook/cells/prompt.vue10
-rw-r--r--app/assets/javascripts/notebook/index.vue4
-rw-r--r--app/assets/javascripts/notes.js22
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue33
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue25
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue67
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter_note.vue52
-rw-r--r--app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue28
-rw-r--r--app/assets/javascripts/notes/components/discussion_reply_placeholder.vue17
-rw-r--r--app/assets/javascripts/notes/components/discussion_resolve_button.vue28
-rw-r--r--app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue34
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue31
-rw-r--r--app/assets/javascripts/notes/components/note_actions/reply_button.vue30
-rw-r--r--app/assets/javascripts/notes/components/note_awards_list.vue12
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue28
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue14
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue160
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue50
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue44
-rw-r--r--app/assets/javascripts/notes/components/toggle_replies_widget.vue8
-rw-r--r--app/assets/javascripts/notes/constants.js7
-rw-r--r--app/assets/javascripts/notes/index.js3
-rw-r--r--app/assets/javascripts/notes/mixins/diff_line_note_form.js10
-rw-r--r--app/assets/javascripts/notes/mixins/resolvable.js4
-rw-r--r--app/assets/javascripts/notes/stores/actions.js73
-rw-r--r--app/assets/javascripts/notes/stores/getters.js5
-rw-r--r--app/assets/javascripts/notes/stores/modules/index.js1
-rw-r--r--app/assets/javascripts/notes/stores/mutation_types.js2
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js23
-rw-r--r--app/assets/javascripts/notes/stores/utils.js4
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/show/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/index.js6
-rw-r--r--app/assets/javascripts/pages/dashboard/merge_requests/index.js3
-rw-r--r--app/assets/javascripts/pages/dashboard/projects/index.js2
-rw-r--r--app/assets/javascripts/pages/explore/projects/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/clusters/edit/index.js (renamed from app/assets/javascripts/pages/groups/clusters/update/index.js)0
-rw-r--r--app/assets/javascripts/pages/groups/clusters/index/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/index.js9
-rw-r--r--app/assets/javascripts/pages/groups/issues/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/merge_requests/index.js3
-rw-r--r--app/assets/javascripts/pages/import/gitea/status/index.js7
-rw-r--r--app/assets/javascripts/pages/import/github/status/index.js7
-rw-r--r--app/assets/javascripts/pages/profiles/show/index.js60
-rw-r--r--app/assets/javascripts/pages/projects/clusters/edit/index.js (renamed from app/assets/javascripts/pages/projects/clusters/update/index.js)0
-rw-r--r--app/assets/javascripts/pages/projects/clusters/index/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/environments/metrics/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/error_tracking/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/graphs/charts/index.js91
-rw-r--r--app/assets/javascripts/pages/projects/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/issues/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/form.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/index/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/issues/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/index/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue8
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/charts/index.js81
-rw-r--r--app/assets/javascripts/pages/projects/project_members/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/settings/operations/show/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue4
-rw-r--r--app/assets/javascripts/pages/projects/tags/releases/index.js8
-rw-r--r--app/assets/javascripts/pages/sessions/new/index.js7
-rw-r--r--app/assets/javascripts/pages/sessions/new/oauth_remember_me.js5
-rw-r--r--app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js32
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js23
-rw-r--r--app/assets/javascripts/pages/users/user_overview_block.js18
-rw-r--r--app/assets/javascripts/pages/users/user_tabs.js4
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue7
-rw-r--r--app/assets/javascripts/persistent_user_callout.js42
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue45
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_url.vue36
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_actions.vue18
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_artifacts.vue23
-rw-r--r--app/assets/javascripts/pipelines/components/stage.vue2
-rw-r--r--app/assets/javascripts/pipelines/mixins/graph_component_mixin.js44
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines.js9
-rw-r--r--app/assets/javascripts/project_select.js174
-rw-r--r--app/assets/javascripts/project_select_combo_button.js10
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue4
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue2
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue6
-rw-r--r--app/assets/javascripts/projects/project_new.js54
-rw-r--r--app/assets/javascripts/registry/components/table_registry.vue8
-rw-r--r--app/assets/javascripts/releases/components/app.vue6
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue6
-rw-r--r--app/assets/javascripts/releases/store/actions.js4
-rw-r--r--app/assets/javascripts/reports/components/modal_open_name.vue2
-rw-r--r--app/assets/javascripts/reports/components/test_issue_body.vue2
-rw-r--r--app/assets/javascripts/serverless/components/environment_row.vue65
-rw-r--r--app/assets/javascripts/serverless/components/function_details.vue56
-rw-r--r--app/assets/javascripts/serverless/components/function_row.vue48
-rw-r--r--app/assets/javascripts/serverless/components/functions.vue56
-rw-r--r--app/assets/javascripts/serverless/components/pod_box.vue36
-rw-r--r--app/assets/javascripts/serverless/components/url.vue38
-rw-r--r--app/assets/javascripts/serverless/serverless_bundle.js67
-rw-r--r--app/assets/javascripts/serverless/stores/serverless_details_store.js11
-rw-r--r--app/assets/javascripts/serverless/stores/serverless_store.js11
-rw-r--r--app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js3
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue30
-rw-r--r--app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue4
-rw-r--r--app/assets/javascripts/task_list.js72
-rw-r--r--app/assets/javascripts/terminal/terminal.js3
-rw-r--r--app/assets/javascripts/users_select.js217
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment.vue14
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue14
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue35
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue40
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue37
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue91
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue70
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue291
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue34
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/ee_switch_mr_widget_options.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/index.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/mr_widget_pipeline.js15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue21
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/services/ee_switch_mr_widget_service.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_get_state_key.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_mr_widget_store.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_state_maps.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/bar_chart.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/callout.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/changed_file_icon.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_icon.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/deprecated_modal.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue16
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/no_preview.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/not_diffable.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/empty_component.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/index.vue299
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/item.vue126
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue49
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row_header.vue25
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue34
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_modal.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_modal_vuex.vue69
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue116
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue23
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue38
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/navigation_tabs.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/panel_resizer.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/pikaday.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/project_avatar/default.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/recaptcha_modal.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/select2_select.vue35
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/table_pagination.vue37
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue89
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue8
-rw-r--r--app/assets/javascripts/vue_shared/mixins/is_ee.js10
-rw-r--r--app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js155
-rw-r--r--app/assets/javascripts/vuex_shared/modules/modal/actions.js20
-rw-r--r--app/assets/javascripts/vuex_shared/modules/modal/index.js10
-rw-r--r--app/assets/javascripts/vuex_shared/modules/modal/mutation_types.js4
-rw-r--r--app/assets/javascripts/vuex_shared/modules/modal/mutations.js18
-rw-r--r--app/assets/javascripts/vuex_shared/modules/modal/state.js4
-rw-r--r--app/assets/stylesheets/application.scss10
-rw-r--r--app/assets/stylesheets/bootstrap_migration.scss20
-rw-r--r--app/assets/stylesheets/components/related_items_list.scss380
-rw-r--r--app/assets/stylesheets/framework.scss3
-rw-r--r--app/assets/stylesheets/framework/animations.scss74
-rw-r--r--app/assets/stylesheets/framework/asciidoctor.scss2
-rw-r--r--app/assets/stylesheets/framework/avatar.scss88
-rw-r--r--app/assets/stylesheets/framework/awards.scss26
-rw-r--r--app/assets/stylesheets/framework/blocks.scss6
-rw-r--r--app/assets/stylesheets/framework/buttons.scss11
-rw-r--r--app/assets/stylesheets/framework/common.scss81
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss133
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss6
-rw-r--r--app/assets/stylesheets/framework/emojis.scss2
-rw-r--r--app/assets/stylesheets/framework/files.scss20
-rw-r--r--app/assets/stylesheets/framework/filters.scss11
-rw-r--r--app/assets/stylesheets/framework/forms.scss16
-rw-r--r--app/assets/stylesheets/framework/gfm.scss2
-rw-r--r--app/assets/stylesheets/framework/gitlab_theme.scss40
-rw-r--r--app/assets/stylesheets/framework/header.scss35
-rw-r--r--app/assets/stylesheets/framework/icons.scss4
-rw-r--r--app/assets/stylesheets/framework/images.scss3
-rw-r--r--app/assets/stylesheets/framework/issue_box.scss5
-rw-r--r--app/assets/stylesheets/framework/layout.scss8
-rw-r--r--app/assets/stylesheets/framework/lists.scss6
-rw-r--r--app/assets/stylesheets/framework/logo.scss35
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss20
-rw-r--r--app/assets/stylesheets/framework/mixins.scss32
-rw-r--r--app/assets/stylesheets/framework/mobile.scss88
-rw-r--r--app/assets/stylesheets/framework/modal.scss43
-rw-r--r--app/assets/stylesheets/framework/responsive_tables.scss2
-rw-r--r--app/assets/stylesheets/framework/selects.scss20
-rw-r--r--app/assets/stylesheets/framework/spinner.scss51
-rw-r--r--app/assets/stylesheets/framework/stacked_progress_bar.scss8
-rw-r--r--app/assets/stylesheets/framework/system_messages.scss110
-rw-r--r--app/assets/stylesheets/framework/tables.scss9
-rw-r--r--app/assets/stylesheets/framework/terms.scss1
-rw-r--r--app/assets/stylesheets/framework/toggle.scss14
-rw-r--r--app/assets/stylesheets/framework/typography.scss37
-rw-r--r--app/assets/stylesheets/framework/variables.scss84
-rw-r--r--app/assets/stylesheets/framework/variables_overrides.scss15
-rw-r--r--app/assets/stylesheets/highlight/common.scss18
-rw-r--r--app/assets/stylesheets/highlight/dark.scss259
-rw-r--r--app/assets/stylesheets/highlight/embedded.scss2
-rw-r--r--app/assets/stylesheets/highlight/monokai.scss257
-rw-r--r--app/assets/stylesheets/highlight/none.scss242
-rw-r--r--app/assets/stylesheets/highlight/solarized_dark.scss284
-rw-r--r--app/assets/stylesheets/highlight/solarized_light.scss292
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss261
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss259
-rw-r--r--app/assets/stylesheets/highlight/themes/none.scss238
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss286
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss294
-rw-r--r--app/assets/stylesheets/highlight/themes/white.scss3
-rw-r--r--app/assets/stylesheets/highlight/white.scss3
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss80
-rw-r--r--app/assets/stylesheets/mailers/highlighted_diff_email.scss67
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss72
-rw-r--r--app/assets/stylesheets/page_bundles/xterm.scss6
-rw-r--r--app/assets/stylesheets/pages/boards.scss47
-rw-r--r--app/assets/stylesheets/pages/branches.scss13
-rw-r--r--app/assets/stylesheets/pages/builds.scss30
-rw-r--r--app/assets/stylesheets/pages/clusters.scss14
-rw-r--r--app/assets/stylesheets/pages/commits.scss4
-rw-r--r--app/assets/stylesheets/pages/cycle_analytics.scss1
-rw-r--r--app/assets/stylesheets/pages/detail_page.scss1
-rw-r--r--app/assets/stylesheets/pages/diff.scss190
-rw-r--r--app/assets/stylesheets/pages/editor.scss7
-rw-r--r--app/assets/stylesheets/pages/environments.scss24
-rw-r--r--app/assets/stylesheets/pages/graph.scss8
-rw-r--r--app/assets/stylesheets/pages/groups.scss110
-rw-r--r--app/assets/stylesheets/pages/help.scss2
-rw-r--r--app/assets/stylesheets/pages/import.scss51
-rw-r--r--app/assets/stylesheets/pages/issuable.scss19
-rw-r--r--app/assets/stylesheets/pages/issues.scss24
-rw-r--r--app/assets/stylesheets/pages/issues/issue_count_badge.scss6
-rw-r--r--app/assets/stylesheets/pages/labels.scss16
-rw-r--r--app/assets/stylesheets/pages/login.scss3
-rw-r--r--app/assets/stylesheets/pages/members.scss1
-rw-r--r--app/assets/stylesheets/pages/merge_conflicts.scss96
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss90
-rw-r--r--app/assets/stylesheets/pages/milestone.scss9
-rw-r--r--app/assets/stylesheets/pages/note_form.scss18
-rw-r--r--app/assets/stylesheets/pages/notes.scss76
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss118
-rw-r--r--app/assets/stylesheets/pages/profile.scss12
-rw-r--r--app/assets/stylesheets/pages/profiles/preferences.scss4
-rw-r--r--app/assets/stylesheets/pages/projects.scss201
-rw-r--r--app/assets/stylesheets/pages/reports.scss2
-rw-r--r--app/assets/stylesheets/pages/search.scss6
-rw-r--r--app/assets/stylesheets/pages/serverless.scss3
-rw-r--r--app/assets/stylesheets/pages/settings.scss8
-rw-r--r--app/assets/stylesheets/pages/status.scss4
-rw-r--r--app/assets/stylesheets/pages/todos.scss18
-rw-r--r--app/assets/stylesheets/pages/tree.scss20
-rw-r--r--app/assets/stylesheets/pages/ui_dev_kit.scss2
-rw-r--r--app/controllers/admin/appearances_controller.rb5
-rw-r--r--app/controllers/admin/application_settings_controller.rb2
-rw-r--r--app/controllers/admin/requests_profiles_controller.rb2
-rw-r--r--app/controllers/admin/runners_controller.rb8
-rw-r--r--app/controllers/admin/users_controller.rb12
-rw-r--r--app/controllers/application_controller.rb35
-rw-r--r--app/controllers/clusters/clusters_controller.rb4
-rw-r--r--app/controllers/concerns/boards_responses.rb10
-rw-r--r--app/controllers/concerns/continue_params.rb2
-rw-r--r--app/controllers/concerns/issuable_actions.rb6
-rw-r--r--app/controllers/concerns/issuable_collections.rb5
-rw-r--r--app/controllers/concerns/issuable_collections_action.rb60
-rw-r--r--app/controllers/concerns/issues_action.rb33
-rw-r--r--app/controllers/concerns/lfs_request.rb2
-rw-r--r--app/controllers/concerns/membership_actions.rb4
-rw-r--r--app/controllers/concerns/merge_requests_action.rb25
-rw-r--r--app/controllers/concerns/milestone_actions.rb2
-rw-r--r--app/controllers/concerns/notes_actions.rb57
-rw-r--r--app/controllers/concerns/preview_markdown.rb2
-rw-r--r--app/controllers/concerns/record_user_last_activity.rb27
-rw-r--r--app/controllers/concerns/renders_notes.rb2
-rw-r--r--app/controllers/concerns/send_file_upload.rb19
-rw-r--r--app/controllers/concerns/service_params.rb2
-rw-r--r--app/controllers/concerns/uploads_actions.rb18
-rw-r--r--app/controllers/dashboard/application_controller.rb1
-rw-r--r--app/controllers/dashboard/milestones_controller.rb6
-rw-r--r--app/controllers/dashboard/projects_controller.rb11
-rw-r--r--app/controllers/dashboard_controller.rb3
-rw-r--r--app/controllers/explore/projects_controller.rb9
-rw-r--r--app/controllers/google_api/authorizations_controller.rb32
-rw-r--r--app/controllers/graphql_controller.rb9
-rw-r--r--app/controllers/groups/boards_controller.rb1
-rw-r--r--app/controllers/groups/children_controller.rb2
-rw-r--r--app/controllers/groups/milestones_controller.rb23
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb6
-rw-r--r--app/controllers/groups_controller.rb4
-rw-r--r--app/controllers/help_controller.rb7
-rw-r--r--app/controllers/import/base_controller.rb2
-rw-r--r--app/controllers/import/bitbucket_controller.rb4
-rw-r--r--app/controllers/import/bitbucket_server_controller.rb11
-rw-r--r--app/controllers/import/gitea_controller.rb20
-rw-r--r--app/controllers/import/github_controller.rb116
-rw-r--r--app/controllers/notification_settings_controller.rb7
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb21
-rw-r--r--app/controllers/passwords_controller.rb2
-rw-r--r--app/controllers/profiles/active_sessions_controller.rb11
-rw-r--r--app/controllers/profiles/preferences_controller.rb12
-rw-r--r--app/controllers/profiles_controller.rb1
-rw-r--r--app/controllers/projects/application_controller.rb2
-rw-r--r--app/controllers/projects/artifacts_controller.rb9
-rw-r--r--app/controllers/projects/autocomplete_sources_controller.rb2
-rw-r--r--app/controllers/projects/badges_controller.rb13
-rw-r--r--app/controllers/projects/blob_controller.rb4
-rw-r--r--app/controllers/projects/branches_controller.rb3
-rw-r--r--app/controllers/projects/build_artifacts_controller.rb9
-rw-r--r--app/controllers/projects/ci/lints_controller.rb8
-rw-r--r--app/controllers/projects/commit_controller.rb10
-rw-r--r--app/controllers/projects/discussions_controller.rb2
-rw-r--r--app/controllers/projects/environments_controller.rb40
-rw-r--r--app/controllers/projects/error_tracking_controller.rb84
-rw-r--r--app/controllers/projects/git_http_controller.rb13
-rw-r--r--app/controllers/projects/graphs_controller.rb9
-rw-r--r--app/controllers/projects/group_links_controller.rb5
-rw-r--r--app/controllers/projects/issues_controller.rb33
-rw-r--r--app/controllers/projects/jobs_controller.rb14
-rw-r--r--app/controllers/projects/lfs_locks_api_controller.rb10
-rw-r--r--app/controllers/projects/lfs_storage_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/application_controller.rb12
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb6
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb5
-rw-r--r--app/controllers/projects/merge_requests_controller.rb19
-rw-r--r--app/controllers/projects/milestones_controller.rb4
-rw-r--r--app/controllers/projects/pages_controller.rb5
-rw-r--r--app/controllers/projects/pages_domains_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_controller.rb7
-rw-r--r--app/controllers/projects/pipelines_settings_controller.rb2
-rw-r--r--app/controllers/projects/releases_controller.rb11
-rw-r--r--app/controllers/projects/serverless/functions_controller.rb31
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb2
-rw-r--r--app/controllers/projects/settings/operations_controller.rb74
-rw-r--r--app/controllers/projects/snippets_controller.rb9
-rw-r--r--app/controllers/projects/tags_controller.rb15
-rw-r--r--app/controllers/projects/tree_controller.rb14
-rw-r--r--app/controllers/projects/triggers_controller.rb7
-rw-r--r--app/controllers/projects_controller.rb18
-rw-r--r--app/controllers/sherlock/transactions_controller.rb2
-rw-r--r--app/controllers/snippets/notes_controller.rb4
-rw-r--r--app/controllers/snippets_controller.rb8
-rw-r--r--app/controllers/uploads_controller.rb10
-rw-r--r--app/finders/admin/runners_finder.rb11
-rw-r--r--app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb44
-rw-r--r--app/finders/concerns/finder_methods.rb4
-rw-r--r--app/finders/contributed_projects_finder.rb7
-rw-r--r--app/finders/group_descendants_finder.rb2
-rw-r--r--app/finders/issuable_finder.rb72
-rw-r--r--app/finders/issues_finder.rb12
-rw-r--r--app/finders/merge_requests_finder.rb10
-rw-r--r--app/finders/milestones_finder.rb21
-rw-r--r--app/finders/projects/daily_statistics_finder.rb21
-rw-r--r--app/finders/projects/serverless/functions_finder.rb31
-rw-r--r--app/finders/releases_finder.rb14
-rw-r--r--app/finders/snippets_finder.rb2
-rw-r--r--app/graphql/mutations/merge_requests/base.rb3
-rw-r--r--app/graphql/resolvers/base_resolver.rb7
-rw-r--r--app/graphql/resolvers/issues_resolver.rb32
-rw-r--r--app/graphql/resolvers/merge_request_resolver.rb25
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb36
-rw-r--r--app/graphql/resolvers/metadata_resolver.rb11
-rw-r--r--app/graphql/types/issuable_state_enum.rb12
-rw-r--r--app/graphql/types/issue_state_enum.rb8
-rw-r--r--app/graphql/types/issue_type.rb12
-rw-r--r--app/graphql/types/merge_request_state_enum.rb10
-rw-r--r--app/graphql/types/merge_request_type.rb10
-rw-r--r--app/graphql/types/metadata_type.rb10
-rw-r--r--app/graphql/types/permission_types/project.rb2
-rw-r--r--app/graphql/types/project_type.rb18
-rw-r--r--app/graphql/types/query_type.rb13
-rw-r--r--app/helpers/appearances_helper.rb38
-rw-r--r--app/helpers/application_helper.rb28
-rw-r--r--app/helpers/application_settings_helper.rb8
-rw-r--r--app/helpers/auth_helper.rb9
-rw-r--r--app/helpers/auto_devops_helper.rb37
-rw-r--r--app/helpers/blob_helper.rb38
-rw-r--r--app/helpers/ci_status_helper.rb17
-rw-r--r--app/helpers/commits_helper.rb2
-rw-r--r--app/helpers/count_helper.rb2
-rw-r--r--app/helpers/diff_helper.rb24
-rw-r--r--app/helpers/emails_helper.rb48
-rw-r--r--app/helpers/environments_helper.rb8
-rw-r--r--app/helpers/external_wiki_helper.rb12
-rw-r--r--app/helpers/import_helper.rb40
-rw-r--r--app/helpers/issuables_helper.rb8
-rw-r--r--app/helpers/labels_helper.rb4
-rw-r--r--app/helpers/markup_helper.rb8
-rw-r--r--app/helpers/members_helper.rb17
-rw-r--r--app/helpers/merge_requests_helper.rb6
-rw-r--r--app/helpers/milestones_helper.rb15
-rw-r--r--app/helpers/namespaces_helper.rb6
-rw-r--r--app/helpers/notes_helper.rb5
-rw-r--r--app/helpers/preferences_helper.rb20
-rw-r--r--app/helpers/profiles_helper.rb4
-rw-r--r--app/helpers/projects/error_tracking_helper.rb15
-rw-r--r--app/helpers/projects_helper.rb59
-rw-r--r--app/helpers/runners_helper.rb10
-rw-r--r--app/helpers/search_helper.rb4
-rw-r--r--app/helpers/snippets_helper.rb10
-rw-r--r--app/helpers/sorting_helper.rb22
-rw-r--r--app/helpers/user_callouts_helper.rb7
-rw-r--r--app/helpers/users_helper.rb9
-rw-r--r--app/helpers/workhorse_helper.rb5
-rw-r--r--app/mailers/abuse_report_mailer.rb4
-rw-r--r--app/mailers/email_rejection_mailer.rb4
-rw-r--r--app/mailers/emails/issues.rb12
-rw-r--r--app/mailers/emails/pipelines.rb2
-rw-r--r--app/mailers/previews/notify_preview.rb4
-rw-r--r--app/mailers/repository_check_mailer.rb4
-rw-r--r--app/models/active_session.rb6
-rw-r--r--app/models/appearance.rb48
-rw-r--r--app/models/application_record.rb18
-rw-r--r--app/models/application_setting.rb14
-rw-r--r--app/models/blob.rb10
-rw-r--r--app/models/blob_viewer/base.rb6
-rw-r--r--app/models/blob_viewer/gitlab_ci_yml.rb8
-rw-r--r--app/models/board.rb4
-rw-r--r--app/models/board_group_recent_visit.rb9
-rw-r--r--app/models/board_project_recent_visit.rb9
-rw-r--r--app/models/ci/bridge.rb29
-rw-r--r--app/models/ci/build.rb264
-rw-r--r--app/models/ci/build_metadata.rb14
-rw-r--r--app/models/ci/build_trace_chunk.rb4
-rw-r--r--app/models/ci/group_variable.rb1
-rw-r--r--app/models/ci/job_artifact.rb2
-rw-r--r--app/models/ci/pipeline.rb109
-rw-r--r--app/models/ci/pipeline_chat_data.rb13
-rw-r--r--app/models/ci/pipeline_enums.rb3
-rw-r--r--app/models/ci/runner.rb7
-rw-r--r--app/models/ci/stage.rb1
-rw-r--r--app/models/ci/trigger.rb3
-rw-r--r--app/models/ci/variable.rb1
-rw-r--r--app/models/clusters/applications/cert_manager.rb2
-rw-r--r--app/models/clusters/applications/ingress.rb4
-rw-r--r--app/models/clusters/applications/knative.rb42
-rw-r--r--app/models/clusters/applications/prometheus.rb35
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/clusters/cluster.rb44
-rw-r--r--app/models/clusters/concerns/application_status.rb29
-rw-r--r--app/models/clusters/concerns/application_version.rb8
-rw-r--r--app/models/clusters/platforms/kubernetes.rb11
-rw-r--r--app/models/commit.rb11
-rw-r--r--app/models/commit_collection.rb13
-rw-r--r--app/models/commit_range.rb8
-rw-r--r--app/models/commit_status.rb1
-rw-r--r--app/models/concerns/blob_language_from_git_attributes.rb2
-rw-r--r--app/models/concerns/blob_like.rb2
-rw-r--r--app/models/concerns/cache_markdown_field.rb44
-rw-r--r--app/models/concerns/cacheable_attributes.rb7
-rw-r--r--app/models/concerns/ci/contextable.rb108
-rw-r--r--app/models/concerns/ci/metadatable.rb69
-rw-r--r--app/models/concerns/ci/processable.rb31
-rw-r--r--app/models/concerns/closed_at_filterable.rb14
-rw-r--r--app/models/concerns/discussion_on_diff.rb20
-rw-r--r--app/models/concerns/fast_destroy_all.rb2
-rw-r--r--app/models/concerns/feature_gate.rb2
-rw-r--r--app/models/concerns/has_ref.rb28
-rw-r--r--app/models/concerns/has_status.rb10
-rw-r--r--app/models/concerns/has_variable.rb6
-rw-r--r--app/models/concerns/iid_routes.rb2
-rw-r--r--app/models/concerns/issuable.rb63
-rw-r--r--app/models/concerns/manual_inverse_association.rb4
-rw-r--r--app/models/concerns/maskable.rb22
-rw-r--r--app/models/concerns/milestoneish.rb25
-rw-r--r--app/models/concerns/mirror_authentication.rb2
-rw-r--r--app/models/concerns/noteable.rb19
-rw-r--r--app/models/concerns/reactive_caching.rb4
-rw-r--r--app/models/concerns/sha_attribute.rb10
-rw-r--r--app/models/concerns/taskable.rb8
-rw-r--r--app/models/concerns/token_authenticatable_strategies/base.rb16
-rw-r--r--app/models/concerns/token_authenticatable_strategies/encrypted.rb52
-rw-r--r--app/models/concerns/with_uploads.rb34
-rw-r--r--app/models/container_repository.rb11
-rw-r--r--app/models/dashboard_group_milestone.rb27
-rw-r--r--app/models/dashboard_milestone.rb10
-rw-r--r--app/models/diff_note.rb8
-rw-r--r--app/models/diff_viewer/base.rb39
-rw-r--r--app/models/diff_viewer/image.rb2
-rw-r--r--app/models/diff_viewer/rich.rb2
-rw-r--r--app/models/diff_viewer/server_side.rb12
-rw-r--r--app/models/diff_viewer/simple.rb2
-rw-r--r--app/models/discussion.rb4
-rw-r--r--app/models/email.rb2
-rw-r--r--app/models/environment.rb20
-rw-r--r--app/models/error_tracking/project_error_tracking_setting.rb157
-rw-r--r--app/models/external_issue.rb8
-rw-r--r--app/models/global_milestone.rb117
-rw-r--r--app/models/gpg_signature.rb7
-rw-r--r--app/models/group.rb8
-rw-r--r--app/models/group_milestone.rb30
-rw-r--r--app/models/identity.rb2
-rw-r--r--app/models/individual_note_discussion.rb12
-rw-r--r--app/models/internal_id.rb17
-rw-r--r--app/models/issue.rb10
-rw-r--r--app/models/label.rb1
-rw-r--r--app/models/label_note.rb2
-rw-r--r--app/models/legacy_diff_note.rb2
-rw-r--r--app/models/lfs_download_object.rb22
-rw-r--r--app/models/list.rb2
-rw-r--r--app/models/member.rb5
-rw-r--r--app/models/members/group_member.rb2
-rw-r--r--app/models/members/project_member.rb4
-rw-r--r--app/models/merge_request.rb178
-rw-r--r--app/models/merge_request_diff.rb121
-rw-r--r--app/models/merge_request_diff_file.rb14
-rw-r--r--app/models/milestone.rb67
-rw-r--r--app/models/namespace.rb4
-rw-r--r--app/models/network/graph.rb9
-rw-r--r--app/models/note.rb4
-rw-r--r--app/models/note_diff_file.rb15
-rw-r--r--app/models/notification_recipient.rb6
-rw-r--r--app/models/personal_access_token.rb5
-rw-r--r--app/models/pool_repository.rb10
-rw-r--r--app/models/programming_language.rb6
-rw-r--r--app/models/project.rb312
-rw-r--r--app/models/project_auto_devops.rb6
-rw-r--r--app/models/project_daily_statistic.rb10
-rw-r--r--app/models/project_feature.rb34
-rw-r--r--app/models/project_import_data.rb4
-rw-r--r--app/models/project_services/bamboo_service.rb32
-rw-r--r--app/models/project_services/campfire_service.rb2
-rw-r--r--app/models/project_services/deployment_service.rb2
-rw-r--r--app/models/project_services/hipchat_service.rb311
-rw-r--r--app/models/project_services/irker_service.rb4
-rw-r--r--app/models/project_services/jira_service.rb5
-rw-r--r--app/models/project_services/kubernetes_service.rb2
-rw-r--r--app/models/project_services/prometheus_service.rb6
-rw-r--r--app/models/project_services/slack_slash_commands_service.rb4
-rw-r--r--app/models/project_services/teamcity_service.rb6
-rw-r--r--app/models/project_services/youtrack_service.rb40
-rw-r--r--app/models/project_team.rb12
-rw-r--r--app/models/project_wiki.rb4
-rw-r--r--app/models/prometheus_metric.rb84
-rw-r--r--app/models/protected_branch.rb14
-rw-r--r--app/models/release.rb42
-rw-r--r--app/models/releases/link.rb22
-rw-r--r--app/models/releases/source.rb35
-rw-r--r--app/models/remote_mirror.rb14
-rw-r--r--app/models/repository.rb56
-rw-r--r--app/models/sent_notification.rb25
-rw-r--r--app/models/service.rb2
-rw-r--r--app/models/snippet.rb10
-rw-r--r--app/models/ssh_host_key.rb8
-rw-r--r--app/models/storage/hashed_project.rb2
-rw-r--r--app/models/storage/legacy_project.rb11
-rw-r--r--app/models/suggestion.rb7
-rw-r--r--app/models/todo.rb5
-rw-r--r--app/models/user.rb28
-rw-r--r--app/models/wiki_page.rb2
-rw-r--r--app/policies/base_policy.rb4
-rw-r--r--app/policies/board_policy.rb16
-rw-r--r--app/policies/ci/pipeline_policy.rb9
-rw-r--r--app/policies/concerns/clusterable_actions.rb14
-rw-r--r--app/policies/container_repository_policy.rb5
-rw-r--r--app/policies/global_policy.rb4
-rw-r--r--app/policies/group_policy.rb12
-rw-r--r--app/policies/issuable_policy.rb2
-rw-r--r--app/policies/issue_policy.rb1
-rw-r--r--app/policies/note_policy.rb1
-rw-r--r--app/policies/personal_snippet_policy.rb7
-rw-r--r--app/policies/project_policy.rb49
-rw-r--r--app/policies/project_snippet_policy.rb13
-rw-r--r--app/policies/release_policy.rb5
-rw-r--r--app/presenters/ci/build_runner_presenter.rb42
-rw-r--r--app/presenters/ci/trigger_presenter.rb19
-rw-r--r--app/presenters/clusterable_presenter.rb4
-rw-r--r--app/presenters/commit_presenter.rb13
-rw-r--r--app/presenters/merge_request_presenter.rb14
-rw-r--r--app/presenters/project_presenter.rb23
-rw-r--r--app/serializers/acts_as_taggable_on/tag_entity.rb6
-rw-r--r--app/serializers/acts_as_taggable_on/tag_serializer.rb5
-rw-r--r--app/serializers/base_serializer.rb10
-rw-r--r--app/serializers/cluster_application_entity.rb2
-rw-r--r--app/serializers/concerns/user_status_tooltip.rb2
-rw-r--r--app/serializers/container_repository_entity.rb2
-rw-r--r--app/serializers/container_tag_entity.rb2
-rw-r--r--app/serializers/deployment_entity.rb10
-rw-r--r--app/serializers/diff_file_base_entity.rb21
-rw-r--r--app/serializers/diff_file_entity.rb8
-rw-r--r--app/serializers/diff_viewer_entity.rb5
-rw-r--r--app/serializers/environment_entity.rb1
-rw-r--r--app/serializers/error_tracking/error_entity.rb10
-rw-r--r--app/serializers/error_tracking/error_serializer.rb7
-rw-r--r--app/serializers/error_tracking/project_entity.rb7
-rw-r--r--app/serializers/error_tracking/project_serializer.rb7
-rw-r--r--app/serializers/merge_request_basic_entity.rb1
-rw-r--r--app/serializers/merge_request_diff_entity.rb8
-rw-r--r--app/serializers/merge_request_for_pipeline_entity.rb17
-rw-r--r--app/serializers/merge_request_widget_commit_entity.rb7
-rw-r--r--app/serializers/merge_request_widget_entity.rb29
-rw-r--r--app/serializers/namespace_basic_entity.rb6
-rw-r--r--app/serializers/namespace_serializer.rb5
-rw-r--r--app/serializers/pipeline_entity.rb16
-rw-r--r--app/serializers/pipeline_serializer.rb1
-rw-r--r--app/serializers/project_import_entity.rb13
-rw-r--r--app/serializers/project_serializer.rb12
-rw-r--r--app/serializers/projects/serverless/service_entity.rb36
-rw-r--r--app/serializers/provider_repo_entity.rb25
-rw-r--r--app/serializers/provider_repo_serializer.rb5
-rw-r--r--app/serializers/tree_entity.rb15
-rw-r--r--app/serializers/tree_root_entity.rb27
-rw-r--r--app/serializers/tree_serializer.rb5
-rw-r--r--app/services/application_settings/update_service.rb2
-rw-r--r--app/services/applications/create_service.rb8
-rw-r--r--app/services/auth/container_registry_authentication_service.rb3
-rw-r--r--app/services/boards/issues/move_service.rb2
-rw-r--r--app/services/boards/lists/destroy_service.rb2
-rw-r--r--app/services/boards/visits/latest_service.rb14
-rw-r--r--app/services/ci/create_pipeline_service.rb25
-rw-r--r--app/services/ci/destroy_expired_job_artifacts_service.rb38
-rw-r--r--app/services/ci/destroy_pipeline_service.rb2
-rw-r--r--app/services/ci/pipeline_trigger_service.rb10
-rw-r--r--app/services/ci/process_pipeline_service.rb16
-rw-r--r--app/services/ci/retry_build_service.rb2
-rw-r--r--app/services/clusters/applications/base_helm_service.rb4
-rw-r--r--app/services/clusters/applications/check_installation_progress_service.rb23
-rw-r--r--app/services/clusters/applications/create_service.rb6
-rw-r--r--app/services/clusters/applications/schedule_installation_service.rb19
-rw-r--r--app/services/clusters/applications/upgrade_service.rb28
-rw-r--r--app/services/commits/create_service.rb13
-rw-r--r--app/services/commits/tag_service.rb3
-rw-r--r--app/services/concerns/exclusive_lease_guard.rb15
-rw-r--r--app/services/concerns/users/participable_service.rb15
-rw-r--r--app/services/create_branch_service.rb4
-rw-r--r--app/services/create_release_service.rb35
-rw-r--r--app/services/delete_branch_service.rb2
-rw-r--r--app/services/emails/base_service.rb5
-rw-r--r--app/services/emails/create_service.rb9
-rw-r--r--app/services/error_tracking/list_issues_service.rb53
-rw-r--r--app/services/error_tracking/list_projects_service.rb44
-rw-r--r--app/services/files/multi_service.rb3
-rw-r--r--app/services/git_push_service.rb11
-rw-r--r--app/services/git_tag_push_service.rb9
-rw-r--r--app/services/groups/create_service.rb6
-rw-r--r--app/services/groups/nested_create_service.rb2
-rw-r--r--app/services/groups/transfer_service.rb10
-rw-r--r--app/services/groups/update_service.rb8
-rw-r--r--app/services/import/base_service.rb35
-rw-r--r--app/services/import/github_service.rb48
-rw-r--r--app/services/issuable/common_system_notes_service.rb2
-rw-r--r--app/services/issuable_base_service.rb71
-rw-r--r--app/services/issues/build_service.rb12
-rw-r--r--app/services/issues/import_csv_service.rb53
-rw-r--r--app/services/issues/update_service.rb11
-rw-r--r--app/services/labels/create_service.rb2
-rw-r--r--app/services/labels/promote_service.rb2
-rw-r--r--app/services/labels/update_service.rb3
-rw-r--r--app/services/lfs/locks_finder_service.rb2
-rw-r--r--app/services/members/base_service.rb6
-rw-r--r--app/services/members/create_service.rb14
-rw-r--r--app/services/members/destroy_service.rb32
-rw-r--r--app/services/members/update_service.rb9
-rw-r--r--app/services/merge_requests/base_service.rb3
-rw-r--r--app/services/merge_requests/build_service.rb25
-rw-r--r--app/services/merge_requests/create_service.rb16
-rw-r--r--app/services/merge_requests/merge_base_service.rb63
-rw-r--r--app/services/merge_requests/merge_service.rb46
-rw-r--r--app/services/merge_requests/merge_to_ref_service.rb76
-rw-r--r--app/services/merge_requests/squash_service.rb33
-rw-r--r--app/services/merge_requests/update_service.rb13
-rw-r--r--app/services/milestones/promote_service.rb4
-rw-r--r--app/services/notes/build_service.rb17
-rw-r--r--app/services/notes/create_service.rb15
-rw-r--r--app/services/notes/quick_actions_service.rb33
-rw-r--r--app/services/notification_recipient_service.rb7
-rw-r--r--app/services/notification_service.rb5
-rw-r--r--app/services/preview_markdown_service.rb11
-rw-r--r--app/services/projects/after_rename_service.rb31
-rw-r--r--app/services/projects/autocomplete_service.rb2
-rw-r--r--app/services/projects/container_repository/cleanup_tags_service.rb94
-rw-r--r--app/services/projects/create_from_template_service.rb2
-rw-r--r--app/services/projects/destroy_service.rb24
-rw-r--r--app/services/projects/download_service.rb2
-rw-r--r--app/services/projects/fetch_statistics_increment_service.rb32
-rw-r--r--app/services/projects/fork_service.rb12
-rw-r--r--app/services/projects/group_links/create_service.rb10
-rw-r--r--app/services/projects/hashed_storage/base_attachment_service.rb51
-rw-r--r--app/services/projects/hashed_storage/base_repository_service.rb67
-rw-r--r--app/services/projects/hashed_storage/migrate_attachments_service.rb45
-rw-r--r--app/services/projects/hashed_storage/migrate_repository_service.rb50
-rw-r--r--app/services/projects/hashed_storage/migration_service.rb39
-rw-r--r--app/services/projects/hashed_storage/rollback_attachments_service.rb34
-rw-r--r--app/services/projects/hashed_storage/rollback_repository_service.rb40
-rw-r--r--app/services/projects/hashed_storage/rollback_service.rb37
-rw-r--r--app/services/projects/hashed_storage_migration_service.rb27
-rw-r--r--app/services/projects/import_error_filter.rb14
-rw-r--r--app/services/projects/import_service.rb22
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_link_list_service.rb13
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_service.rb102
-rw-r--r--app/services/projects/operations/update_service.rb40
-rw-r--r--app/services/projects/protect_default_branch_service.rb67
-rw-r--r--app/services/projects/update_pages_configuration_service.rb34
-rw-r--r--app/services/projects/update_pages_service.rb41
-rw-r--r--app/services/projects/update_service.rb13
-rw-r--r--app/services/prometheus/adapter_service.rb2
-rw-r--r--app/services/protected_branches/api_service.rb21
-rw-r--r--app/services/protected_branches/legacy_api_update_service.rb19
-rw-r--r--app/services/push_event_payload_service.rb2
-rw-r--r--app/services/quick_actions/interpret_service.rb46
-rw-r--r--app/services/releases/concerns.rb48
-rw-r--r--app/services/releases/create_service.rb55
-rw-r--r--app/services/releases/destroy_service.rb25
-rw-r--r--app/services/releases/update_service.rb32
-rw-r--r--app/services/search/global_service.rb14
-rw-r--r--app/services/suggestions/apply_service.rb43
-rw-r--r--app/services/suggestions/create_service.rb10
-rw-r--r--app/services/system_note_service.rb2
-rw-r--r--app/services/tags/create_service.rb7
-rw-r--r--app/services/tags/destroy_service.rb10
-rw-r--r--app/services/task_list_toggle_service.rb72
-rw-r--r--app/services/update_release_service.rb28
-rw-r--r--app/services/upload_service.rb4
-rw-r--r--app/services/users/activity_service.rb7
-rw-r--r--app/services/users/update_service.rb2
-rw-r--r--app/services/validate_new_branch_service.rb4
-rw-r--r--app/uploaders/external_diff_uploader.rb23
-rw-r--r--app/uploaders/file_mover.rb8
-rw-r--r--app/uploaders/personal_file_uploader.rb18
-rw-r--r--app/uploaders/records_uploads.rb20
-rw-r--r--app/validators/sha_validator.rb9
-rw-r--r--app/validators/url_validator.rb10
-rw-r--r--app/views/admin/appearances/_form.html.haml169
-rw-r--r--app/views/admin/appearances/_system_header_footer_form.html.haml33
-rw-r--r--app/views/admin/appearances/show.html.haml7
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml4
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml2
-rw-r--r--app/views/admin/application_settings/_localization.html.haml11
-rw-r--r--app/views/admin/application_settings/_repository_storage.html.haml1
-rw-r--r--app/views/admin/application_settings/preferences.html.haml11
-rw-r--r--app/views/admin/application_settings/show.html.haml2
-rw-r--r--app/views/admin/groups/_group.html.haml2
-rw-r--r--app/views/admin/groups/show.html.haml4
-rw-r--r--app/views/admin/projects/_projects.html.haml2
-rw-r--r--app/views/admin/runners/_runner.html.haml15
-rw-r--r--app/views/admin/runners/index.html.haml23
-rw-r--r--app/views/admin/users/_user.html.haml55
-rw-r--r--app/views/admin/users/_user_detail.html.haml17
-rw-r--r--app/views/admin/users/index.html.haml96
-rw-r--r--app/views/award_emoji/_awards_block.html.haml4
-rw-r--r--app/views/ci/status/_dropdown_graph_badge.html.haml4
-rw-r--r--app/views/ci/status/_icon.html.haml16
-rw-r--r--app/views/ci/variables/_content.html.haml2
-rw-r--r--app/views/clusters/clusters/_buttons.html.haml3
-rw-r--r--app/views/clusters/clusters/_empty_state.html.haml2
-rw-r--r--app/views/clusters/clusters/_form.html.haml46
-rw-r--r--app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml6
-rw-r--r--app/views/clusters/clusters/_integration_form.html.haml31
-rw-r--r--app/views/clusters/clusters/gcp/_show.html.haml50
-rw-r--r--app/views/clusters/clusters/index.html.haml8
-rw-r--r--app/views/clusters/clusters/new.html.haml4
-rw-r--r--app/views/clusters/clusters/show.html.haml16
-rw-r--r--app/views/clusters/clusters/user/_show.html.haml39
-rw-r--r--app/views/clusters/platforms/kubernetes/_form.html.haml58
-rw-r--r--app/views/dashboard/_activities.html.haml2
-rw-r--r--app/views/dashboard/_projects_head.html.haml2
-rw-r--r--app/views/dashboard/_snippets_head.html.haml4
-rw-r--r--app/views/dashboard/activity.html.haml3
-rw-r--r--app/views/dashboard/groups/index.html.haml4
-rw-r--r--app/views/dashboard/issues.html.haml2
-rw-r--r--app/views/dashboard/merge_requests.html.haml2
-rw-r--r--app/views/dashboard/milestones/_milestone.html.haml2
-rw-r--r--app/views/dashboard/milestones/index.html.haml2
-rw-r--r--app/views/dashboard/projects/_starred_empty_state.html.haml9
-rw-r--r--app/views/dashboard/projects/index.html.haml2
-rw-r--r--app/views/dashboard/projects/starred.html.haml11
-rw-r--r--app/views/dashboard/snippets/index.html.haml12
-rw-r--r--app/views/dashboard/todos/index.html.haml2
-rw-r--r--app/views/devise/mailer/_confirmation_instructions_secondary.html.haml2
-rw-r--r--app/views/devise/passwords/edit.html.haml2
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml2
-rw-r--r--app/views/devise/sessions/new.html.haml2
-rw-r--r--app/views/devise/sessions/two_factor.html.haml2
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml2
-rw-r--r--app/views/devise/shared/_signup_box.html.haml6
-rw-r--r--app/views/doorkeeper/authorizations/new.html.haml2
-rw-r--r--app/views/email_rejection_mailer/rejection.html.haml2
-rw-r--r--app/views/email_rejection_mailer/rejection.text.haml2
-rw-r--r--app/views/events/_events.html.haml19
-rw-r--r--app/views/events/event/_note.html.haml2
-rw-r--r--app/views/explore/groups/index.html.haml2
-rw-r--r--app/views/explore/projects/index.html.haml2
-rw-r--r--app/views/explore/projects/starred.html.haml2
-rw-r--r--app/views/explore/projects/trending.html.haml2
-rw-r--r--app/views/explore/snippets/index.html.haml2
-rw-r--r--app/views/groups/_activities.html.haml2
-rw-r--r--app/views/groups/_home_panel.html.haml71
-rw-r--r--app/views/groups/group_members/index.html.haml2
-rw-r--r--app/views/groups/labels/index.html.haml7
-rw-r--r--app/views/groups/merge_requests.html.haml2
-rw-r--r--app/views/groups/milestones/_form.html.haml17
-rw-r--r--app/views/groups/milestones/index.html.haml1
-rw-r--r--app/views/groups/runners/_group_runners.html.haml2
-rw-r--r--app/views/groups/settings/_general.html.haml2
-rw-r--r--app/views/groups/show.html.haml95
-rw-r--r--app/views/help/_shortcuts.html.haml12
-rw-r--r--app/views/ide/_show.html.haml2
-rw-r--r--app/views/import/_githubish_status.html.haml59
-rw-r--r--app/views/import/bitbucket_server/status.html.haml2
-rw-r--r--app/views/import/github/new.html.haml2
-rw-r--r--app/views/import/github/status.html.haml4
-rw-r--r--app/views/import/manifest/status.html.haml2
-rw-r--r--app/views/instance_statistics/conversational_development_index/_callout.html.haml6
-rw-r--r--app/views/instance_statistics/conversational_development_index/_card.html.haml4
-rw-r--r--app/views/instance_statistics/conversational_development_index/_no_data.html.haml6
-rw-r--r--app/views/instance_statistics/conversational_development_index/index.html.haml4
-rw-r--r--app/views/layouts/_head.html.haml30
-rw-r--r--app/views/layouts/_init_client_detection_flags.html.haml7
-rw-r--r--app/views/layouts/_mailer.html.haml6
-rw-r--r--app/views/layouts/application.html.haml7
-rw-r--r--app/views/layouts/devise.html.haml2
-rw-r--r--app/views/layouts/devise_empty.html.haml2
-rw-r--r--app/views/layouts/empty_mailer.html.haml5
-rw-r--r--app/views/layouts/empty_mailer.text.erb5
-rw-r--r--app/views/layouts/group.html.haml2
-rw-r--r--app/views/layouts/header/_empty.html.haml4
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml3
-rw-r--r--app/views/layouts/header/_new_dropdown.haml2
-rw-r--r--app/views/layouts/mailer.text.erb4
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml30
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml48
-rw-r--r--app/views/layouts/notify.html.haml2
-rw-r--r--app/views/layouts/notify.text.erb4
-rw-r--r--app/views/layouts/snippets.html.haml2
-rw-r--r--app/views/notify/_note_email.text.erb4
-rw-r--r--app/views/notify/autodevops_disabled_email.text.erb2
-rw-r--r--app/views/notify/closed_issue_email.html.haml2
-rw-r--r--app/views/notify/closed_issue_email.text.haml2
-rw-r--r--app/views/notify/closed_merge_request_email.html.haml2
-rw-r--r--app/views/notify/closed_merge_request_email.text.haml6
-rw-r--r--app/views/notify/import_issues_csv_email.html.haml18
-rw-r--r--app/views/notify/import_issues_csv_email.text.erb11
-rw-r--r--app/views/notify/issue_moved_email.html.haml11
-rw-r--r--app/views/notify/issue_moved_email.text.erb4
-rw-r--r--app/views/notify/issue_status_changed_email.html.haml2
-rw-r--r--app/views/notify/issue_status_changed_email.text.erb2
-rw-r--r--app/views/notify/member_access_requested_email.text.erb2
-rw-r--r--app/views/notify/member_invite_accepted_email.text.erb2
-rw-r--r--app/views/notify/member_invited_email.text.erb2
-rw-r--r--app/views/notify/merge_request_status_email.html.haml2
-rw-r--r--app/views/notify/merge_request_status_email.text.haml6
-rw-r--r--app/views/notify/merge_request_unmergeable_email.text.haml4
-rw-r--r--app/views/notify/merged_merge_request_email.text.haml4
-rw-r--r--app/views/notify/new_gpg_key_email.html.haml2
-rw-r--r--app/views/notify/new_gpg_key_email.text.erb2
-rw-r--r--app/views/notify/new_issue_email.text.erb2
-rw-r--r--app/views/notify/new_mention_in_issue_email.text.erb4
-rw-r--r--app/views/notify/new_mention_in_merge_request_email.text.erb4
-rw-r--r--app/views/notify/new_merge_request_email.html.haml2
-rw-r--r--app/views/notify/new_ssh_key_email.html.haml2
-rw-r--r--app/views/notify/new_ssh_key_email.text.erb2
-rw-r--r--app/views/notify/new_user_email.html.haml2
-rw-r--r--app/views/notify/new_user_email.text.erb2
-rw-r--r--app/views/notify/pipeline_failed_email.text.erb6
-rw-r--r--app/views/notify/pipeline_success_email.text.erb6
-rw-r--r--app/views/notify/push_to_merge_request_email.html.haml2
-rw-r--r--app/views/notify/push_to_merge_request_email.text.haml2
-rw-r--r--app/views/notify/reassigned_issue_email.html.haml2
-rw-r--r--app/views/notify/reassigned_issue_email.text.erb2
-rw-r--r--app/views/notify/reassigned_merge_request_email.html.haml4
-rw-r--r--app/views/notify/reassigned_merge_request_email.text.erb4
-rw-r--r--app/views/notify/resolved_all_discussions_email.html.haml2
-rw-r--r--app/views/notify/resolved_all_discussions_email.text.erb2
-rw-r--r--app/views/profiles/accounts/show.html.haml34
-rw-r--r--app/views/profiles/active_sessions/_active_session.html.haml6
-rw-r--r--app/views/profiles/passwords/new.html.haml13
-rw-r--r--app/views/profiles/preferences/show.html.haml27
-rw-r--r--app/views/profiles/show.html.haml9
-rw-r--r--app/views/projects/_activity.html.haml4
-rw-r--r--app/views/projects/_export.html.haml7
-rw-r--r--app/views/projects/_home_panel.html.haml43
-rw-r--r--app/views/projects/_issuable_by_email.html.haml9
-rw-r--r--app/views/projects/_md_preview.html.haml16
-rw-r--r--app/views/projects/_merge_request_merge_settings.html.haml1
-rw-r--r--app/views/projects/_new_project_fields.html.haml2
-rw-r--r--app/views/projects/_wiki.html.haml2
-rw-r--r--app/views/projects/artifacts/_tree_file.html.haml2
-rw-r--r--app/views/projects/badges/badge_flat-square.svg.erb17
-rw-r--r--app/views/projects/blob/_editor.html.haml4
-rw-r--r--app/views/projects/blob/_markdown_buttons.html.haml13
-rw-r--r--app/views/projects/blob/edit.html.haml2
-rw-r--r--app/views/projects/blob/preview.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_dependency_manager.html.haml5
-rw-r--r--app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_loading.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_markup.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_readme.html.haml2
-rw-r--r--app/views/projects/branches/_branch.html.haml33
-rw-r--r--app/views/projects/branches/_panel.html.haml2
-rw-r--r--app/views/projects/branches/index.html.haml2
-rw-r--r--app/views/projects/buttons/_clone.html.haml25
-rw-r--r--app/views/projects/buttons/_dropdown.html.haml4
-rw-r--r--app/views/projects/buttons/_notifications.html.haml27
-rw-r--r--app/views/projects/ci/builds/_build.html.haml22
-rw-r--r--app/views/projects/ci/lints/_create.html.haml35
-rw-r--r--app/views/projects/ci/lints/show.html.haml12
-rw-r--r--app/views/projects/cleanup/_show.html.haml2
-rw-r--r--app/views/projects/commit/_ajax_signature.html.haml2
-rw-r--r--app/views/projects/commit/_ci_menu.html.haml8
-rw-r--r--app/views/projects/commit/_commit_box.html.haml21
-rw-r--r--app/views/projects/commit/_limit_exceeded_message.html.haml4
-rw-r--r--app/views/projects/commit/_other_user_signature_badge.html.haml4
-rw-r--r--app/views/projects/commit/_same_user_different_email_signature_badge.html.haml5
-rw-r--r--app/views/projects/commit/_signature_badge.html.haml4
-rw-r--r--app/views/projects/commit/_unverified_signature_badge.html.haml4
-rw-r--r--app/views/projects/commit/_verified_signature_badge.html.haml5
-rw-r--r--app/views/projects/commit/pipelines.html.haml2
-rw-r--r--app/views/projects/commit/show.html.haml11
-rw-r--r--app/views/projects/commits/_commit.html.haml5
-rw-r--r--app/views/projects/compare/show.html.haml2
-rw-r--r--app/views/projects/deploy_keys/_index.html.haml2
-rw-r--r--app/views/projects/deployments/_actions.haml2
-rw-r--r--app/views/projects/deployments/_confirm_rollback_modal.html.haml23
-rw-r--r--app/views/projects/deployments/_rollback.haml3
-rw-r--r--app/views/projects/diffs/_diffs.html.haml4
-rw-r--r--app/views/projects/diffs/_file.html.haml4
-rw-r--r--app/views/projects/diffs/_render_error.html.haml6
-rw-r--r--app/views/projects/diffs/_warning.html.haml2
-rw-r--r--app/views/projects/edit.html.haml54
-rw-r--r--app/views/projects/environments/folder.html.haml5
-rw-r--r--app/views/projects/environments/index.html.haml1
-rw-r--r--app/views/projects/error_tracking/index.html.haml3
-rw-r--r--app/views/projects/forks/_fork_button.html.haml4
-rw-r--r--app/views/projects/graphs/charts.html.haml12
-rw-r--r--app/views/projects/issues/_discussion.html.haml2
-rw-r--r--app/views/projects/issues/_form.html.haml3
-rw-r--r--app/views/projects/issues/_issue.html.haml2
-rw-r--r--app/views/projects/issues/_merge_requests.html.haml67
-rw-r--r--app/views/projects/issues/_merge_requests_status.html.haml25
-rw-r--r--app/views/projects/issues/_nav_btns.html.haml41
-rw-r--r--app/views/projects/issues/_new_branch.html.haml2
-rw-r--r--app/views/projects/issues/_related_branches.html.haml4
-rw-r--r--app/views/projects/issues/import_csv/_button.html.haml9
-rw-r--r--app/views/projects/issues/import_csv/_modal.html.haml24
-rw-r--r--app/views/projects/issues/index.html.haml5
-rw-r--r--app/views/projects/issues/show.html.haml15
-rw-r--r--app/views/projects/jobs/index.html.haml4
-rw-r--r--app/views/projects/labels/index.html.haml7
-rw-r--r--app/views/projects/merge_requests/_form.html.haml3
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml7
-rw-r--r--app/views/projects/merge_requests/_merge_requests.html.haml2
-rw-r--r--app/views/projects/merge_requests/show.html.haml3
-rw-r--r--app/views/projects/milestones/_form.html.haml23
-rw-r--r--app/views/projects/milestones/edit.html.haml10
-rw-r--r--app/views/projects/milestones/index.html.haml9
-rw-r--r--app/views/projects/milestones/new.html.haml10
-rw-r--r--app/views/projects/milestones/show.html.haml28
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml2
-rw-r--r--app/views/projects/new.html.haml5
-rw-r--r--app/views/projects/pages/_destroy.haml2
-rw-r--r--app/views/projects/pages/_https_only.html.haml2
-rw-r--r--app/views/projects/pages_domains/_form.html.haml13
-rw-r--r--app/views/projects/pages_domains/edit.html.haml4
-rw-r--r--app/views/projects/pages_domains/new.html.haml8
-rw-r--r--app/views/projects/pages_domains/show.html.haml27
-rw-r--r--app/views/projects/pipeline_schedules/_form.html.haml2
-rw-r--r--app/views/projects/pipelines/_info.html.haml37
-rw-r--r--app/views/projects/pipelines/charts/_pipeline_times.haml6
-rw-r--r--app/views/projects/pipelines/charts/_pipelines.haml9
-rw-r--r--app/views/projects/project_members/_groups.html.haml3
-rw-r--r--app/views/projects/project_members/_new_project_group.html.haml5
-rw-r--r--app/views/projects/project_members/_new_project_member.html.haml15
-rw-r--r--app/views/projects/project_members/_team.html.haml9
-rw-r--r--app/views/projects/project_members/import.html.haml12
-rw-r--r--app/views/projects/project_members/index.html.haml23
-rw-r--r--app/views/projects/project_templates/_built_in_templates.html.haml6
-rw-r--r--app/views/projects/protected_branches/shared/_index.html.haml2
-rw-r--r--app/views/projects/protected_branches/shared/_protected_branch.html.haml2
-rw-r--r--app/views/projects/releases/index.html.haml2
-rw-r--r--app/views/projects/runners/_group_runners.html.haml2
-rw-r--r--app/views/projects/serverless/functions/index.html.haml2
-rw-r--r--app/views/projects/serverless/functions/show.html.haml16
-rw-r--r--app/views/projects/services/prometheus/_metrics.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_show.html.haml4
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml19
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml3
-rw-r--r--app/views/projects/settings/operations/_error_tracking.html.haml18
-rw-r--r--app/views/projects/settings/operations/show.html.haml6
-rw-r--r--app/views/projects/snippets/index.html.haml18
-rw-r--r--app/views/projects/snippets/new.html.haml4
-rw-r--r--app/views/projects/tags/_tag.html.haml2
-rw-r--r--app/views/projects/tags/index.html.haml2
-rw-r--r--app/views/projects/tags/releases/edit.html.haml3
-rw-r--r--app/views/projects/tags/show.html.haml4
-rw-r--r--app/views/projects/tree/_tree_header.html.haml21
-rw-r--r--app/views/projects/triggers/_trigger.html.haml2
-rw-r--r--app/views/projects/wikis/_form.html.haml16
-rw-r--r--app/views/projects/wikis/_sidebar.html.haml2
-rw-r--r--app/views/projects/wikis/edit.html.haml3
-rw-r--r--app/views/projects/wikis/pages.html.haml2
-rw-r--r--app/views/projects/wikis/show.html.haml4
-rw-r--r--app/views/search/_category.html.haml26
-rw-r--r--app/views/search/_filter.html.haml20
-rw-r--r--app/views/search/_form.html.haml6
-rw-r--r--app/views/search/_results.html.haml8
-rw-r--r--app/views/search/results/_empty.html.haml2
-rw-r--r--app/views/search/results/_issue.html.haml2
-rw-r--r--app/views/search/results/_merge_request.html.haml4
-rw-r--r--app/views/search/results/_note.html.haml8
-rw-r--r--app/views/search/results/_snippet_blob.html.haml6
-rw-r--r--app/views/search/results/_snippet_title.html.haml2
-rw-r--r--app/views/search/show.html.haml2
-rw-r--r--app/views/sent_notifications/unsubscribe.html.haml13
-rw-r--r--app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml4
-rw-r--r--app/views/shared/_flash_user_callout.html.haml11
-rw-r--r--app/views/shared/_issuable_meta_data.html.haml2
-rw-r--r--app/views/shared/_mini_pipeline_graph.html.haml1
-rw-r--r--app/views/shared/_mobile_clone_panel.html.haml1
-rw-r--r--app/views/shared/_personal_access_tokens_created_container.html.haml2
-rw-r--r--app/views/shared/_personal_access_tokens_form.html.haml4
-rw-r--r--app/views/shared/_personal_access_tokens_table.html.haml2
-rw-r--r--app/views/shared/boards/components/_board.html.haml2
-rw-r--r--app/views/shared/boards/components/_sidebar.html.haml2
-rw-r--r--app/views/shared/deploy_keys/_form.html.haml2
-rw-r--r--app/views/shared/empty_states/_issues.html.haml31
-rw-r--r--app/views/shared/empty_states/_labels.html.haml2
-rw-r--r--app/views/shared/empty_states/_merge_requests.html.haml19
-rw-r--r--app/views/shared/empty_states/_priority_labels.html.haml2
-rw-r--r--app/views/shared/empty_states/_profile_tabs.html.haml19
-rw-r--r--app/views/shared/empty_states/_snippets.html.haml20
-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.html.haml2
-rw-r--r--app/views/shared/groups/_list.html.haml14
-rw-r--r--app/views/shared/icons/_express.svg1
-rw-r--r--app/views/shared/icons/_rails.svg1
-rw-r--r--app/views/shared/icons/_spring.svg1
-rw-r--r--app/views/shared/issuable/_board_create_list_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/_bulk_update_sidebar.html.haml3
-rw-r--r--app/views/shared/issuable/_feed_buttons.html.haml4
-rw-r--r--app/views/shared/issuable/_filter.html.haml32
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml31
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml2
-rw-r--r--app/views/shared/issuable/_sidebar_assignees.html.haml2
-rw-r--r--app/views/shared/issuable/_sort_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/form/_merge_params.html.haml4
-rw-r--r--app/views/shared/labels/_nav.html.haml4
-rw-r--r--app/views/shared/members/_access_request_buttons.html.haml20
-rw-r--r--app/views/shared/members/_member.html.haml2
-rw-r--r--app/views/shared/milestones/_form_dates.html.haml6
-rw-r--r--app/views/shared/milestones/_milestone.html.haml16
-rw-r--r--app/views/shared/milestones/_search_form.html.haml8
-rw-r--r--app/views/shared/milestones/_tabs.html.haml6
-rw-r--r--app/views/shared/milestones/_top.html.haml11
-rw-r--r--app/views/shared/notes/_comment_button.html.haml19
-rw-r--r--app/views/shared/notes/_edit.html.haml2
-rw-r--r--app/views/shared/notes/_edit_form.html.haml8
-rw-r--r--app/views/shared/notes/_form.html.haml6
-rw-r--r--app/views/shared/notes/_hints.html.haml12
-rw-r--r--app/views/shared/notes/_note.html.haml6
-rw-r--r--app/views/shared/notes/_notes_with_form.html.haml14
-rw-r--r--app/views/shared/notifications/_button.html.haml2
-rw-r--r--app/views/shared/notifications/_new_button.html.haml27
-rw-r--r--app/views/shared/projects/_list.html.haml27
-rw-r--r--app/views/shared/projects/_project.html.haml47
-rw-r--r--app/views/shared/snippets/_form.html.haml3
-rw-r--r--app/views/shared/snippets/_header.html.haml2
-rw-r--r--app/views/shared/snippets/_list.html.haml12
-rw-r--r--app/views/shared/snippets/_snippet.html.haml2
-rw-r--r--app/views/shared/tokens/_scopes_form.html.haml2
-rw-r--r--app/views/snippets/_snippets.html.haml13
-rw-r--r--app/views/snippets/index.html.haml2
-rw-r--r--app/views/users/_groups.html.haml2
-rw-r--r--app/views/users/_overview.html.haml30
-rw-r--r--app/views/users/show.html.haml6
-rw-r--r--app/workers/all_queues.yml15
-rw-r--r--app/workers/build_finished_worker.rb27
-rw-r--r--app/workers/chat_notification_worker.rb33
-rw-r--r--app/workers/cleanup_container_repository_worker.rb53
-rw-r--r--app/workers/cluster_upgrade_app_worker.rb13
-rw-r--r--app/workers/delete_container_repository_worker.rb2
-rw-r--r--app/workers/expire_build_artifacts_worker.rb14
-rw-r--r--app/workers/expire_pipeline_cache_worker.rb32
-rw-r--r--app/workers/git_garbage_collect_worker.rb1
-rw-r--r--app/workers/hashed_storage/base_worker.rb21
-rw-r--r--app/workers/hashed_storage/migrator_worker.rb16
-rw-r--r--app/workers/hashed_storage/project_migrate_worker.rb26
-rw-r--r--app/workers/hashed_storage/project_rollback_worker.rb26
-rw-r--r--app/workers/hashed_storage/rollbacker_worker.rb16
-rw-r--r--app/workers/import_issues_csv_worker.rb20
-rw-r--r--app/workers/mail_scheduler/notification_service_worker.rb54
-rw-r--r--app/workers/namespaceless_project_destroy_worker.rb2
-rw-r--r--app/workers/object_pool/join_worker.rb11
-rw-r--r--app/workers/pipeline_metrics_worker.rb2
-rw-r--r--app/workers/post_receive.rb20
-rw-r--r--app/workers/project_daily_statistics_worker.rb13
-rw-r--r--app/workers/project_migrate_hashed_storage_worker.rb38
-rw-r--r--app/workers/reactive_caching_worker.rb4
-rw-r--r--app/workers/remote_mirror_notification_worker.rb3
-rw-r--r--app/workers/repository_fork_worker.rb10
-rw-r--r--app/workers/storage_migrator_worker.rb10
-rw-r--r--app/workers/update_head_pipeline_for_merge_request_worker.rb21
-rw-r--r--babel.config.js51
-rwxr-xr-xbin/background_jobs9
-rwxr-xr-xbin/changelog10
-rwxr-xr-xbin/secpick188
-rw-r--r--changelogs/README.md10
-rw-r--r--changelogs/unreleased/10095-job-getters.yml5
-rw-r--r--changelogs/unreleased/10097-number-utils.yml5
-rw-r--r--changelogs/unreleased/13784-simple-masking-of-protected-variables-in-logs.yml5
-rw-r--r--changelogs/unreleased/20084-update-the-spinner-component.yml5
-rw-r--r--changelogs/unreleased/23367-clarify-docs-allow-failure.yml5
-rw-r--r--changelogs/unreleased/24642-activity_service_optimization.yml5
-rw-r--r--changelogs/unreleased/27333-re-deploy-rollback-button-should-ask-for-confirmation-before-executing.yml5
-rw-r--r--changelogs/unreleased/2802-security-add-public-internal-groups-as-members-to-your-project-idor.yml6
-rw-r--r--changelogs/unreleased/32714-copying-comment-with-ordered-list-includes-extraneous-newlines.yml5
-rw-r--r--changelogs/unreleased/34555-empty-state-for-starred-projects.yml5
-rw-r--r--changelogs/unreleased/34758-list-ancestor-clusters.yml5
-rw-r--r--changelogs/unreleased/35638-move-language-setting-to-preferences.yml5
-rw-r--r--changelogs/unreleased/37673-minor-issue-with-apostrophe-single-quote-when-clicking-assign-to-me.yml5
-rw-r--r--changelogs/unreleased/39010-add-left-margin-to-1st-time-contributor-badge.yml5
-rw-r--r--changelogs/unreleased/39676-wiki-api-problems-on-update-parameters-and-500-error.yml5
-rw-r--r--changelogs/unreleased/40270-remove-gitlab-upgrader-completely.yml5
-rw-r--r--changelogs/unreleased/40396-sidekiq-in-process-group.yml5
-rw-r--r--changelogs/unreleased/40396-use-pgroups-for-background-jobs.yml5
-rw-r--r--changelogs/unreleased/40795-set-project-name-on-fork-api.yml5
-rw-r--r--changelogs/unreleased/41766-vue-component.yml5
-rw-r--r--changelogs/unreleased/41766-vuex-store.yml5
-rw-r--r--changelogs/unreleased/41888-access-personal-snippets-by-api.yml5
-rw-r--r--changelogs/unreleased/42086-project-fetch-statistics-api-http-only.yml5
-rw-r--r--changelogs/unreleased/42125-extend-override-check-to-also-check-arity.yml5
-rw-r--r--changelogs/unreleased/44740-api-to-verify-a-given-user-has-right-to-merge-a-given-mergerequest.yml5
-rw-r--r--changelogs/unreleased/44984-use-serializer-for-issuable-sidebar.yml5
-rw-r--r--changelogs/unreleased/45035-force-push-api.yml5
-rw-r--r--changelogs/unreleased/45305-ci-status-icon-mismatch-on-merge-requests-page-and-the-mr-itself.yml5
-rw-r--r--changelogs/unreleased/46750-ci-empty-environment-is-created-even-when-a-job-isn-t-run-when-manual.yml5
-rw-r--r--changelogs/unreleased/47052-merge-button-does-not-appear-after-rebase-ing.yml5
-rw-r--r--changelogs/unreleased/47150-update-sshkey.yml5
-rw-r--r--changelogs/unreleased/48798-keybinding-mr-diff.yml5
-rw-r--r--changelogs/unreleased/49397-move-files-in-ide.yml5
-rw-r--r--changelogs/unreleased/49502-gpg-signature-api-endpoint.yml5
-rw-r--r--changelogs/unreleased/49663-branch-to-mr-connection.yml5
-rw-r--r--changelogs/unreleased/50006-expose-textcolor-from-public-labels-api.yml5
-rw-r--r--changelogs/unreleased/50313-use-kaniko-to-build-containers-in-autodevops.yml5
-rw-r--r--changelogs/unreleased/50433-make-emoji-picker-bigger.yml5
-rw-r--r--changelogs/unreleased/51485-new-issue-labels-note.yml5
-rw-r--r--changelogs/unreleased/51606-expanding-a-diff-while-having-an-open-comment-form-will-always-scroll-down-to-the-comment.yml5
-rw-r--r--changelogs/unreleased/51668-fix-line-numbers.yml5
-rw-r--r--changelogs/unreleased/51819-show-feed-toggle-under-system-notes.yml5
-rw-r--r--changelogs/unreleased/51944-redesign-project-lists-ui.yml5
-rw-r--r--changelogs/unreleased/51971-milestones-visibility.yml5
-rw-r--r--changelogs/unreleased/51994-disable-merging-labels-in-dropdowns.yml5
-rw-r--r--changelogs/unreleased/52198-timer-is-vertically-misaligned-for-delayed-jobs-in-pipeline-actions.yml5
-rw-r--r--changelogs/unreleased/52424-goodbye-hipchat.yml5
-rw-r--r--changelogs/unreleased/52459-display-job-names-consistently-on-pipelines-and-environments-list.yml5
-rw-r--r--changelogs/unreleased/52620-fix-loader-animation-alignment.yml5
-rw-r--r--changelogs/unreleased/52734-styling-of-user-project-and-group-avatars.yml5
-rw-r--r--changelogs/unreleased/52778-don-t-display-pipeline-status-if-pipelines-are-disabled.yml5
-rw-r--r--changelogs/unreleased/52792-align-mirror-repository-button.yml5
-rw-r--r--changelogs/unreleased/52877-ios-publishing-blog-post-and-gitlab-ci-yml-template.yml5
-rw-r--r--changelogs/unreleased/53020-user-specific-profile-page-settings-fields-don-t-have-help-text-placeholders.yml5
-rw-r--r--changelogs/unreleased/53325-admin-runners-page-fails-with-an-sql-statement-timeout.yml5
-rw-r--r--changelogs/unreleased/53336-improve-web-ide-launch-performance.yml5
-rw-r--r--changelogs/unreleased/53361-fresh-protected-branches.yml5
-rw-r--r--changelogs/unreleased/53411-remove_personal_access_tokens_token.yml5
-rw-r--r--changelogs/unreleased/53413-externalize-markdown-toolbar-tooltips.yml5
-rw-r--r--changelogs/unreleased/53493-list-id-email-header.yml5
-rw-r--r--changelogs/unreleased/53861-api-promote-project-milestone-to-a-group-milestone.yml5
-rw-r--r--changelogs/unreleased/53933-include-dates-in-milestone-change-email.yml5
-rw-r--r--changelogs/unreleased/53954-resolved-non-diff-discussions-on-merge-requests-no-longer-show-who-resolved-them-and-when-at-a-glance.yml5
-rw-r--r--changelogs/unreleased/53966-make-hashed-storage-migration-safer-and-more-inviting.yml5
-rw-r--r--changelogs/unreleased/54146-fix-calendar-query.yml5
-rw-r--r--changelogs/unreleased/54643-lower_issuable_finder_complexity.yml5
-rw-r--r--changelogs/unreleased/54725-fix-emoji-button-active-state.yml5
-rw-r--r--changelogs/unreleased/54736-sign-in-bottom-margin.yml5
-rw-r--r--changelogs/unreleased/54786-mr-empty-file-display.yml5
-rw-r--r--changelogs/unreleased/54796-api-sort-tie-breaker-for-pagination.yml5
-rw-r--r--changelogs/unreleased/54814-sidebar-styling-updates.yml5
-rw-r--r--changelogs/unreleased/54850-pages-domain-show-view-is-not-protected-by-access-control.yml5
-rw-r--r--changelogs/unreleased/54924-refactor-notes-actions-params.yml5
-rw-r--r--changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml5
-rw-r--r--changelogs/unreleased/55057-system-message-to-core.yml5
-rw-r--r--changelogs/unreleased/55103-hide-group-cluster-features.yml5
-rw-r--r--changelogs/unreleased/55109-jira-integration-api-doesn-t-respect-available-format.yml5
-rw-r--r--changelogs/unreleased/55191-update-workhorse.yml5
-rw-r--r--changelogs/unreleased/55209-tool-tip-hides-menu-item.yml5
-rw-r--r--changelogs/unreleased/55293-split-bio-into-individual-line-in-extended-user-tooltips.yml5
-rw-r--r--changelogs/unreleased/55312-svg.yml5
-rw-r--r--changelogs/unreleased/55344-only-prompt-user-once-when-navigating-away-from-file-editor.yml5
-rw-r--r--changelogs/unreleased/55376-related_merge_requests-api-call-returns-merge-requests-that-are-not-related-to-the-issue.yml5
-rw-r--r--changelogs/unreleased/55447-validate-k8s-ca-cert.yml5
-rw-r--r--changelogs/unreleased/55703-md-image-borders.yml5
-rw-r--r--changelogs/unreleased/55893-artifacts-download.yml5
-rw-r--r--changelogs/unreleased/55925-if-there-is-only-one-changed-page-in-review-app-go-directly-there.yml5
-rw-r--r--changelogs/unreleased/56237-api-truncated-commit-title.yml5
-rw-r--r--changelogs/unreleased/56251-fix-issue-board-weekday-shift.yml5
-rw-r--r--changelogs/unreleased/56477-units-are-appended-to-y-axis-label-on-metrics-dashboard.yml5
-rw-r--r--changelogs/unreleased/56485-implement-graphql-mergerequestsresolver.yml5
-rw-r--r--changelogs/unreleased/56492-implement-new-arguments-state-closed_before-and-closed_after-for-issuesresolver-in-graphql.yml5
-rw-r--r--changelogs/unreleased/56694-mark-group-level-labels-in-label-api-as-such.yml5
-rw-r--r--changelogs/unreleased/56726-fix-n-1-in-issues-and-merge-requests-api.yml5
-rw-r--r--changelogs/unreleased/56787-realtime-validation-for-user-fullname-and-username.yml5
-rw-r--r--changelogs/unreleased/56809-graphql-version-api.yml5
-rw-r--r--changelogs/unreleased/56851-blank-values-in-reactive-cache.yml5
-rw-r--r--changelogs/unreleased/56851-error-tracking-page-seems-broken.yml5
-rw-r--r--changelogs/unreleased/56863-system-messages-in-email.yml5
-rw-r--r--changelogs/unreleased/56871-list-issues-error.yml5
-rw-r--r--changelogs/unreleased/56873-only-load-syntax-highlighting-css-when-selected.yml5
-rw-r--r--changelogs/unreleased/56937-edit-knative-domain-after-it-has-been-deployed.yml5
-rw-r--r--changelogs/unreleased/57085-introduce-zoom-and-scroll-functionality-on-metrics-charts.yml5
-rw-r--r--changelogs/unreleased/57101-api-docs-for-hangouts-chat-service-incorrect.yml5
-rw-r--r--changelogs/unreleased/57223-wiki-finder.yml5
-rw-r--r--changelogs/unreleased/57353-git-push-fails-on-large-lfs-files-where-the-push-take-a-long-time.yml5
-rw-r--r--changelogs/unreleased/57410-api-create-release-link-with-ftp-address-return-400-bad-request.yml5
-rw-r--r--changelogs/unreleased/57534_filter_impersonated_sessions.yml6
-rw-r--r--changelogs/unreleased/57544-web-ide-new-directory-dialog-shows-file-templates.yml5
-rw-r--r--changelogs/unreleased/57564-contributing-button-border.yml5
-rw-r--r--changelogs/unreleased/57579-gitlab-project-import-fails-sidekiq-undefined-method-import_jid.yml5
-rw-r--r--changelogs/unreleased/57582-dropdown-icon-misalignment-on-issues-list-on-mobile-screen.yml5
-rw-r--r--changelogs/unreleased/57612-github-importer-ignores-milestone-due_date.yml5
-rw-r--r--changelogs/unreleased/57671-fix_merge_request_base_pipeline.yml5
-rw-r--r--changelogs/unreleased/57712-project-import-error-user-expected-got-hash.yml5
-rw-r--r--changelogs/unreleased/57734-improve-label-dropdown-selection-performance.yml5
-rw-r--r--changelogs/unreleased/57768-remove-vertical-line.yml5
-rw-r--r--changelogs/unreleased/57784-make-closed-duplicate-and-closed-moved-button-a-link-to-target.yml5
-rw-r--r--changelogs/unreleased/57785-create-project-template-for-netlify.yml5
-rw-r--r--changelogs/unreleased/57788-project-labels-tooltip-missing.yml5
-rw-r--r--changelogs/unreleased/57794-project-template-for-net.yml5
-rw-r--r--changelogs/unreleased/57829-issuable-meta-line-ui-broken-on-mobile.yml5
-rw-r--r--changelogs/unreleased/57905-etag-caching-probably-broken-since-11-5-0.yml5
-rw-r--r--changelogs/unreleased/57991-frontend-pagination-needs-to-handle-cases-where-the-x-total-pages-header-isn-t-present.yml5
-rw-r--r--changelogs/unreleased/58020-fix-merge-api-endpoint-param.yml5
-rw-r--r--changelogs/unreleased/58023-add-Saturday-to-localization-first-day-of-the-week.yml5
-rw-r--r--changelogs/unreleased/58082-project-template-for-go-micro.yml5
-rw-r--r--changelogs/unreleased/58098-auto-devops-postgres-version-variable.yml5
-rw-r--r--changelogs/unreleased/58149-fix-read-list-board-policy.yml6
-rw-r--r--changelogs/unreleased/58274-folder-icon-in-tags-page.yml5
-rw-r--r--changelogs/unreleased/58369-hide-squash-commit.yml5
-rw-r--r--changelogs/unreleased/58570-fix-running-pipline-that-is-imported-via-dotnetcore-template.yml5
-rw-r--r--changelogs/unreleased/8711-prep-frontend-single-repo.yml5
-rw-r--r--changelogs/unreleased/9841-geo-unable-to-compare-branches-on-secondary.yml5
-rw-r--r--changelogs/unreleased/ac-releases-name-sha-author.yml5
-rw-r--r--changelogs/unreleased/add-new-nginx-metrics.yml5
-rw-r--r--changelogs/unreleased/add-project-level-config-for-prospective-merge-pipelines-ce.yml5
-rw-r--r--changelogs/unreleased/add-related-merge-request-count-to-api-response.yml5
-rw-r--r--changelogs/unreleased/add-title-attribute-to-file-row.yml5
-rw-r--r--changelogs/unreleased/add-youtrack-integration.yml5
-rw-r--r--changelogs/unreleased/add_ldap_tls_options.yml5
-rw-r--r--changelogs/unreleased/allow-maintainers-to-remove-pages.yml5
-rw-r--r--changelogs/unreleased/allow-to-recursively-include.yml5
-rw-r--r--changelogs/unreleased/an-peek-jaeger.yml5
-rw-r--r--changelogs/unreleased/auto-devops-tags.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-convert-specs-rails5-style.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-improve-encoding-helper-spec.yml5
-rw-r--r--changelogs/unreleased/bvl-graphql-csrf.yml5
-rw-r--r--changelogs/unreleased/bvl-hide-confidential-events-take2.yml5
-rw-r--r--changelogs/unreleased/change-badges-example-to-pipeline.yml5
-rw-r--r--changelogs/unreleased/changelogs-readme.yml5
-rw-r--r--changelogs/unreleased/consistent-pagination.yml5
-rw-r--r--changelogs/unreleased/depracated-migration-inheritance.yml5
-rw-r--r--changelogs/unreleased/deprecated-actiondispatch-paramsparser.yml5
-rw-r--r--changelogs/unreleased/deprecated-alias-method-chain.yml6
-rw-r--r--changelogs/unreleased/deprecated-comparing-actioncontroller-params-hash.yml6
-rw-r--r--changelogs/unreleased/deprecated-delete-all-params.yml5
-rw-r--r--changelogs/unreleased/deprecated-directly-inheriting-migration.yml5
-rw-r--r--changelogs/unreleased/deprecated-migration-inheritance.yml5
-rw-r--r--changelogs/unreleased/deprecated-passing-activerecord-objects.yml5
-rw-r--r--changelogs/unreleased/deprecated-positional-seperator-parameter.yml5
-rw-r--r--changelogs/unreleased/diff-empty-state-fixes.yml5
-rw-r--r--changelogs/unreleased/diff-tree-resizable.yml5
-rw-r--r--changelogs/unreleased/dm-note-email-image-diff-discussion.yml5
-rw-r--r--changelogs/unreleased/dz-sort-labels-alphabetically.yml5
-rw-r--r--changelogs/unreleased/enable-markup-highlighting.yml5
-rw-r--r--changelogs/unreleased/expose-additional-merge-request-pipeline-variables.yml5
-rw-r--r--changelogs/unreleased/expose-merge-ref-to-runner.yml5
-rw-r--r--changelogs/unreleased/expose-merge-request-entity-for-pipelines.yml5
-rw-r--r--changelogs/unreleased/fast-destroy-uploads.yml5
-rw-r--r--changelogs/unreleased/feature-api-delete-job-artifacts.yml5
-rw-r--r--changelogs/unreleased/feature-gb-add-serverless-cicd-template.yml5
-rw-r--r--changelogs/unreleased/feature-gb-enable-ci-persisted-stages-by-default.yml5
-rw-r--r--changelogs/unreleased/feature-option-to-make-variables-protected.yml5
-rw-r--r--changelogs/unreleased/feature-runner-tag-filter-for-admin-view.yml5
-rw-r--r--changelogs/unreleased/filter-confidential-issues.yml5
-rw-r--r--changelogs/unreleased/filter-note-parameters.yml5
-rw-r--r--changelogs/unreleased/fix-38010-sidebar-loads-and-collapses.yml5
-rw-r--r--changelogs/unreleased/fix-55448.yml5
-rw-r--r--changelogs/unreleased/fix-badges-logs.yml5
-rw-r--r--changelogs/unreleased/fix-calendar-events-fetching-error.yml5
-rw-r--r--changelogs/unreleased/fix-gb-fix-bridge-jobs-variables-policy.yml5
-rw-r--r--changelogs/unreleased/fix-group-without-owner.yml5
-rw-r--r--changelogs/unreleased/fix-n-plus-1-queries-projects.yml6
-rw-r--r--changelogs/unreleased/fix_-56347.yml5
-rw-r--r--changelogs/unreleased/force-reload-arguments-2.yml5
-rw-r--r--changelogs/unreleased/gitlab_kubernetes_helm_bump.yml5
-rw-r--r--changelogs/unreleased/gokhanap-master-patch-03762.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-projects-commit.yml5
-rw-r--r--changelogs/unreleased/gt-remove-unnecessary-line-before-reply-holder.yml5
-rw-r--r--changelogs/unreleased/gt-update-environment-breadcrumb.yml5
-rw-r--r--changelogs/unreleased/gt-update-navigation-theme-colors.yml5
-rw-r--r--changelogs/unreleased/gt-update-new-password-breadcrumb.yml5
-rw-r--r--changelogs/unreleased/gt-update-operations-settings-breadcrumb-trail.yml5
-rw-r--r--changelogs/unreleased/helm-2-12-3.yml5
-rw-r--r--changelogs/unreleased/import-go-to-project-cta.yml5
-rw-r--r--changelogs/unreleased/improve-performance-for-diverging-commit-counts.yml5
-rw-r--r--changelogs/unreleased/improve-snippets-empty-state.yml5
-rw-r--r--changelogs/unreleased/include-ci-yaml.yml5
-rw-r--r--changelogs/unreleased/jc-fix-set-project-writable.yml5
-rw-r--r--changelogs/unreleased/jej-feature-gates-can-be-set-by-group-path.yml5
-rw-r--r--changelogs/unreleased/jira-link-mention-compact.yml5
-rw-r--r--changelogs/unreleased/jlenny-CI_COMMIT_SHORT_SHA.yml5
-rw-r--r--changelogs/unreleased/kinolaev-master-patch-87865.yml5
-rw-r--r--changelogs/unreleased/markdown-toolbar-btn-fix.yml5
-rw-r--r--changelogs/unreleased/mk-avoid-read-only-error.yml5
-rw-r--r--changelogs/unreleased/move_chatops_to_core.yml5
-rw-r--r--changelogs/unreleased/none-syntax-highlighting.yml5
-rw-r--r--changelogs/unreleased/osw-create-and-store-merge-ref-for-mrs.yml5
-rw-r--r--changelogs/unreleased/osw-fetch-latest-version-when-creating-suggestions.yml5
-rw-r--r--changelogs/unreleased/osw-merge-refs-refreshing-api.yml5
-rw-r--r--changelogs/unreleased/patch-45.yml5
-rw-r--r--changelogs/unreleased/persist-source-sha-and-target-sha-for-pipelines.yml5
-rw-r--r--changelogs/unreleased/ravlen-fix-spaces-unicode.yml5
-rw-r--r--changelogs/unreleased/refactor-56367-extract-resolve-with-issue-button-component.yml5
-rw-r--r--changelogs/unreleased/refactor-merge-request-between-pipeline-and-build.yml5
-rw-r--r--changelogs/unreleased/remote-mirror-update-failed-notification.yml5
-rw-r--r--changelogs/unreleased/remove-rails4-specific-code.yml5
-rw-r--r--changelogs/unreleased/remove-rails4-support.yml5
-rw-r--r--changelogs/unreleased/remove-second-primary-button-on-wiki-edit.yml5
-rw-r--r--changelogs/unreleased/rs-admin-user-case-insensitive.yml5
-rw-r--r--changelogs/unreleased/security-2774-milestones-detail.yml5
-rw-r--r--changelogs/unreleased/security-2797-milestone-mrs.yml5
-rw-r--r--changelogs/unreleased/security-2798-fix-boards-policy.yml5
-rw-r--r--changelogs/unreleased/security-2799-emails.yml5
-rw-r--r--changelogs/unreleased/security-50334.yml5
-rw-r--r--changelogs/unreleased/security-55468-check-validity-before-querying.yml5
-rw-r--r--changelogs/unreleased/security-56348.yml5
-rw-r--r--changelogs/unreleased/security-commit-private-related-mr.yml5
-rw-r--r--changelogs/unreleased/security-fj-diff-import-file-read-fix.yml5
-rw-r--r--changelogs/unreleased/security-id-fix-mr-visibility.yml5
-rw-r--r--changelogs/unreleased/security-id-restricted-access-to-private-repo.yml5
-rw-r--r--changelogs/unreleased/security-issue_54789_2.yml5
-rw-r--r--changelogs/unreleased/security-kubernetes-google-login-csrf.yml5
-rw-r--r--changelogs/unreleased/security-kubernetes-local-ssrf.yml5
-rw-r--r--changelogs/unreleased/security-mermaid.yml5
-rw-r--r--changelogs/unreleased/security-osw-stop-linking-to-packages.yml5
-rw-r--r--changelogs/unreleased/security-protect-private-repo-information.yml5
-rw-r--r--changelogs/unreleased/security-shared-project-private-group.yml5
-rw-r--r--changelogs/unreleased/security-tags-oracle.yml5
-rw-r--r--changelogs/unreleased/sh-bump-fog-gem.yml5
-rw-r--r--changelogs/unreleased/sh-cache-avatar-paths.yml5
-rw-r--r--changelogs/unreleased/sh-carrierwave-patch-google-acl.yml5
-rw-r--r--changelogs/unreleased/sh-fix-cpp-templates-404.yml5
-rw-r--r--changelogs/unreleased/sh-fix-double-xhr-pipelines.yml5
-rw-r--r--changelogs/unreleased/sh-fix-github-import-without-oauth2-config.yml5
-rw-r--r--changelogs/unreleased/sh-fix-http-clone-panel.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-58103.yml5
-rw-r--r--changelogs/unreleased/sh-include-project-path-for-internal-api.yml5
-rw-r--r--changelogs/unreleased/sh-log-rails-queue-duration.yml5
-rw-r--r--changelogs/unreleased/sh-optimize-calendar-activities.yml5
-rw-r--r--changelogs/unreleased/sh-remove-nplusone-admin-runners-tags.yml5
-rw-r--r--changelogs/unreleased/sh-rugged-find-commit.yml5
-rw-r--r--changelogs/unreleased/sh-show-pre-receive-error-merge.yml5
-rw-r--r--changelogs/unreleased/sh-wip-fix-duplicate-env-xhr.yml5
-rw-r--r--changelogs/unreleased/shell-8-7.yml5
-rw-r--r--changelogs/unreleased/spec-positional-arguments.yml5
-rw-r--r--changelogs/unreleased/specs-positional-arguments.yml5
-rw-r--r--changelogs/unreleased/support-gitaly-tls.yml5
-rw-r--r--changelogs/unreleased/support-only-changes-on-mr-pipelines.yml5
-rw-r--r--changelogs/unreleased/table-fix-scroll-and-block.yml5
-rw-r--r--changelogs/unreleased/tr-error-tracking-project-selection.yml5
-rw-r--r--changelogs/unreleased/triggermesh-knative-version.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-2-0.yml5
-rw-r--r--changelogs/unreleased/use-encrypted-runner-tokens.yml5
-rw-r--r--changelogs/unreleased/web-ide-commit-header-icon-alignment-fix.yml5
-rw-r--r--changelogs/unreleased/web-ide-default-editor.yml5
-rw-r--r--changelogs/unreleased/winh-dropdown-title-padding.yml5
-rw-r--r--changelogs/unreleased/winh-merge-request-commit-context.yml5
-rw-r--r--changelogs/unreleased/winh-princess-mononospace.yml5
-rw-r--r--changelogs/unreleased/winh-upgrade-gitlab-ui.yml5
-rw-r--r--changelogs/unreleased/zj-backup-restore-object-pools.yml5
-rw-r--r--changelogs/unreleased/zj-load-languages-from-database.yml5
-rw-r--r--config.ru2
-rw-r--r--config/application.rb7
-rw-r--r--config/gitlab.yml.example96
-rw-r--r--config/initializers/1_settings.rb29
-rw-r--r--config/initializers/8_devise.rb2
-rw-r--r--config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb2
-rw-r--r--config/initializers/active_record_locking.rb15
-rw-r--r--config/initializers/ar_mysql_jsonb_support.rb31
-rw-r--r--config/initializers/carrierwave_patch.rb42
-rw-r--r--config/initializers/doorkeeper_openid_connect.rb23
-rw-r--r--config/initializers/fog_core_patch.rb52
-rw-r--r--config/initializers/graphql.rb4
-rw-r--r--config/initializers/hipchat_client_patch.rb14
-rw-r--r--config/initializers/kaminari_active_record_relation_methods_with_limit.rb41
-rw-r--r--config/initializers/kubeclient.rb22
-rw-r--r--config/initializers/lograge.rb3
-rw-r--r--config/initializers/new_framework_defaults.rb5
-rw-r--r--config/initializers/peek.rb1
-rw-r--r--config/initializers/postgresql_cte.rb2
-rw-r--r--config/initializers/postgresql_opclasses_support.rb12
-rw-r--r--config/initializers/sentry.rb2
-rw-r--r--config/initializers/sidekiq.rb9
-rw-r--r--config/initializers/sprockets_base_file_digest_key.rb3
-rw-r--r--config/initializers/tracing.rb37
-rw-r--r--config/initializers/zz_metrics.rb2
-rw-r--r--config/jsdocs.config.js14
-rw-r--r--config/locales/de.yml1
-rw-r--r--config/locales/doorkeeper.en.yml6
-rw-r--r--config/locales/en.yml5
-rw-r--r--config/locales/es.yml1
-rw-r--r--config/routes/admin.rb4
-rw-r--r--config/routes/git_http.rb2
-rw-r--r--config/routes/group.rb2
-rw-r--r--config/routes/import.rb13
-rw-r--r--config/routes/project.rb20
-rw-r--r--config/routes/repository.rb2
-rw-r--r--config/routes/uploads.rb3
-rw-r--r--config/sidekiq_queues.yml8
-rw-r--r--config/webpack.config.js15
-rw-r--r--danger/changelog/Dangerfile6
-rw-r--r--danger/commit_messages/Dangerfile251
-rw-r--r--danger/documentation/Dangerfile41
-rw-r--r--danger/plugins/helper.rb37
-rw-r--r--danger/roulette/Dangerfile81
-rw-r--r--db/fixtures/development/04_project.rb200
-rw-r--r--db/fixtures/development/10_merge_requests.rb3
-rw-r--r--db/fixtures/development/14_pipelines.rb5
-rw-r--r--db/migrate/20140502125220_migrate_repo_size.rb2
-rw-r--r--db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb2
-rw-r--r--db/migrate/20180209115333_create_chatops_tables.rb26
-rw-r--r--db/migrate/20180314145917_add_header_and_footer_banners_to_appearances_table.rb18
-rw-r--r--db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb2
-rw-r--r--db/migrate/20181027114222_add_first_day_of_week_to_user_preferences.rb9
-rw-r--r--db/migrate/20181028120717_add_first_day_of_week_to_application_settings.rb16
-rw-r--r--db/migrate/20181119132520_add_indexes_to_ci_builds_and_pipelines.rb44
-rw-r--r--db/migrate/20181205171941_create_project_daily_statistics.rb18
-rw-r--r--db/migrate/20181212171634_create_error_tracking_settings.rb17
-rw-r--r--db/migrate/20181219145521_add_options_to_build_metadata.rb15
-rw-r--r--db/migrate/20181228175414_create_releases_link_table.rb19
-rw-r--r--db/migrate/20190103140724_make_legacy_false_default.rb9
-rw-r--r--db/migrate/20190104182041_cleanup_legacy_artifact_migration.rb34
-rw-r--r--db/migrate/20190107151020_add_services_type_index.rb20
-rw-r--r--db/migrate/20190107151029_remove_hipchat_services.rb16
-rw-r--r--db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb18
-rw-r--r--db/migrate/20190109153125_add_merge_request_external_diffs.rb25
-rw-r--r--db/migrate/20190114172110_add_domain_to_cluster.rb9
-rw-r--r--db/migrate/20190115054216_add_error_notification_sent_to_remote_mirrors.rb11
-rw-r--r--db/migrate/20190115092821_add_columns_project_error_tracking_settings.rb16
-rw-r--r--db/migrate/20190116234221_add_sorting_fields_to_user_preference.rb21
-rw-r--r--db/migrate/20190130091630_add_local_cached_markdown_version.rb11
-rw-r--r--db/migrate/20190206193120_add_index_to_tags.rb18
-rw-r--r--db/migrate/20190215154930_add_merge_pipelines_enabled_to_ci_cd_settings.rb11
-rw-r--r--db/migrate/20190218134158_add_masked_to_ci_variables.rb21
-rw-r--r--db/migrate/20190218134209_add_masked_to_ci_group_variables.rb21
-rw-r--r--db/migrate/20190220142344_add_email_header_and_footer_enabled_flag_to_appearances_table.rb17
-rw-r--r--db/migrate/20190220150130_add_extra_shas_to_ci_pipelines.rb12
-rw-r--r--db/migrate/20190225160300_steal_encrypt_runners_tokens.rb19
-rw-r--r--db/migrate/20190225160301_add_runner_tokens_indexes.rb24
-rw-r--r--db/migrate/limits_to_mysql.rb13
-rw-r--r--db/post_migrate/20161221153951_rename_reserved_project_names.rb10
-rw-r--r--db/post_migrate/20170313133418_rename_more_reserved_project_names.rb10
-rw-r--r--db/post_migrate/20170317162059_update_upload_paths_to_system.rb2
-rw-r--r--db/post_migrate/20181101091005_steal_digest_column.rb17
-rw-r--r--db/post_migrate/20181101091124_remove_token_from_personal_access_tokens.rb11
-rw-r--r--db/post_migrate/20181218192239_backfill_project_repositories_for_legacy_storage_projects.rb26
-rw-r--r--db/post_migrate/20181219130552_update_project_import_visibility_level.rb60
-rw-r--r--db/post_migrate/20190102152410_delete_inconsistent_internal_id_records2.rb43
-rw-r--r--db/post_migrate/20190115054215_migrate_delete_container_repository_worker.rb15
-rw-r--r--db/post_migrate/20190124200344_migrate_storage_migrator_sidekiq_queue.rb18
-rw-r--r--db/post_migrate/20190131122559_fix_null_type_labels.rb23
-rw-r--r--db/post_migrate/20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb49
-rw-r--r--db/post_migrate/20190301081611_migrate_project_migrate_sidekiq_queue.rb17
-rw-r--r--db/schema.rb81
-rw-r--r--doc/README.md10
-rw-r--r--doc/administration/auth/authentiq.md3
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md6
-rw-r--r--doc/administration/auth/ldap.md64
-rw-r--r--doc/administration/auth/okta.md12
-rw-r--r--doc/administration/compliance.md10
-rw-r--r--doc/administration/container_registry.md33
-rw-r--r--doc/administration/git_protocol.md7
-rw-r--r--doc/administration/gitaly/index.md62
-rw-r--r--doc/administration/high_availability/gitlab.md16
-rw-r--r--doc/administration/high_availability/load_balancer.md54
-rw-r--r--doc/administration/high_availability/nfs.md22
-rw-r--r--doc/administration/high_availability/redis.md17
-rw-r--r--doc/administration/high_availability/redis_source.md12
-rw-r--r--doc/administration/housekeeping.md19
-rw-r--r--doc/administration/incoming_email.md433
-rw-r--r--doc/administration/index.md39
-rw-r--r--doc/administration/integration/plantuml.md1
-rw-r--r--doc/administration/integration/terminal.md44
-rw-r--r--doc/administration/invalidate_markdown_cache.md16
-rw-r--r--doc/administration/issue_closing_pattern.md2
-rw-r--r--doc/administration/job_artifacts.md14
-rw-r--r--doc/administration/logs.md7
-rw-r--r--doc/administration/merge_request_diffs.md147
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md4
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md6
-rw-r--r--doc/administration/monitoring/performance/request_profiling.md4
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md7
-rw-r--r--doc/administration/monitoring/prometheus/index.md2
-rw-r--r--doc/administration/operations/cleaning_up_redis_sessions.md1
-rw-r--r--doc/administration/operations/filesystem_benchmarking.md87
-rw-r--r--doc/administration/operations/index.md24
-rw-r--r--doc/administration/operations/sidekiq_memory_killer.md5
-rw-r--r--doc/administration/operations/unicorn.md12
-rw-r--r--doc/administration/pages/index.md38
-rw-r--r--doc/administration/pages/source.md13
-rw-r--r--doc/administration/polling.md18
-rw-r--r--doc/administration/raketasks/check.md6
-rw-r--r--doc/administration/raketasks/maintenance.md1
-rw-r--r--doc/administration/raketasks/uploads/migrate.md2
-rw-r--r--doc/administration/reply_by_email_postfix_setup.md2
-rw-r--r--doc/administration/repository_checks.md2
-rw-r--r--doc/administration/repository_storage_types.md5
-rw-r--r--doc/administration/restart_gitlab.md4
-rw-r--r--doc/administration/troubleshooting/debug.md6
-rw-r--r--doc/administration/uploads.md5
-rw-r--r--doc/api/README.md232
-rw-r--r--doc/api/access_requests.md16
-rw-r--r--doc/api/applications.md53
-rw-r--r--doc/api/avatar.md38
-rw-r--r--doc/api/award_emoji.md214
-rw-r--r--doc/api/boards.md20
-rw-r--r--doc/api/branches.md213
-rw-r--r--doc/api/broadcast_messages.md113
-rw-r--r--doc/api/commits.md68
-rw-r--r--doc/api/container_registry.md201
-rw-r--r--doc/api/custom_attributes.md8
-rw-r--r--doc/api/deploy_key_multiple_projects.md8
-rw-r--r--doc/api/deploy_keys.md14
-rw-r--r--doc/api/deployments.md4
-rw-r--r--doc/api/discussions.md55
-rw-r--r--doc/api/environments.md10
-rw-r--r--doc/api/events.md6
-rw-r--r--doc/api/features.md10
-rw-r--r--doc/api/graphql/index.md2
-rw-r--r--doc/api/group_badges.md12
-rw-r--r--doc/api/group_boards.md14
-rw-r--r--doc/api/group_labels.md207
-rw-r--r--doc/api/group_level_variables.md10
-rw-r--r--doc/api/group_milestones.md3
-rw-r--r--doc/api/groups.md8
-rw-r--r--doc/api/import.md31
-rw-r--r--doc/api/issues.md83
-rw-r--r--doc/api/jobs.md97
-rw-r--r--doc/api/labels.md45
-rw-r--r--doc/api/lint.md11
-rw-r--r--doc/api/members.md24
-rw-r--r--doc/api/merge_requests.md71
-rw-r--r--doc/api/milestones.md17
-rw-r--r--doc/api/namespaces.md8
-rw-r--r--doc/api/notes.md28
-rw-r--r--doc/api/notification_settings.md12
-rw-r--r--doc/api/oauth2.md205
-rw-r--r--doc/api/pages_domains.md30
-rw-r--r--doc/api/pipeline_triggers.md12
-rw-r--r--doc/api/pipelines.md12
-rw-r--r--doc/api/project_badges.md12
-rw-r--r--doc/api/project_clusters.md347
-rw-r--r--doc/api/project_import_export.md39
-rw-r--r--doc/api/project_level_variables.md10
-rw-r--r--doc/api/project_snippets.md3
-rw-r--r--doc/api/project_statistics.md49
-rw-r--r--doc/api/project_templates.md1
-rw-r--r--doc/api/projects.md37
-rw-r--r--doc/api/protected_branches.md9
-rw-r--r--doc/api/protected_tags.md8
-rw-r--r--doc/api/releases/index.md482
-rw-r--r--doc/api/releases/links.md178
-rw-r--r--doc/api/repositories.md12
-rw-r--r--doc/api/repository_files.md13
-rw-r--r--doc/api/repository_submodules.md2
-rw-r--r--doc/api/resource_label_events.md8
-rw-r--r--doc/api/runners.md58
-rw-r--r--doc/api/search.md36
-rw-r--r--doc/api/services.md86
-rw-r--r--doc/api/settings.md16
-rw-r--r--doc/api/sidekiq_metrics.md9
-rw-r--r--doc/api/snippets.md226
-rw-r--r--doc/api/suggestions.md2
-rw-r--r--doc/api/system_hooks.md8
-rw-r--r--doc/api/tags.md6
-rw-r--r--doc/api/templates/gitignores.md12
-rw-r--r--doc/api/templates/gitlab_ci_ymls.md2
-rw-r--r--doc/api/templates/licenses.md2
-rw-r--r--doc/api/todos.md7
-rw-r--r--doc/api/users.md32
-rw-r--r--doc/api/version.md2
-rw-r--r--doc/api/wikis.md13
-rw-r--r--doc/articles/index.md4
-rw-r--r--doc/articles/openshift_and_gitlab/index.md1
-rw-r--r--doc/ci/README.md247
-rw-r--r--doc/ci/autodeploy/img/auto_deploy_btn.pngbin16779 -> 0 bytes
-rw-r--r--doc/ci/autodeploy/img/auto_deploy_button.pngbin13321 -> 0 bytes
-rw-r--r--doc/ci/autodeploy/img/auto_deploy_dropdown.pngbin28357 -> 0 bytes
-rw-r--r--doc/ci/autodeploy/img/auto_monitoring.pngbin56765 -> 0 bytes
-rw-r--r--doc/ci/autodeploy/img/guide_connect_cluster.pngbin15225 -> 0 bytes
-rw-r--r--doc/ci/autodeploy/img/guide_integration.pngbin15042 -> 0 bytes
-rw-r--r--doc/ci/autodeploy/img/guide_secret.pngbin4803 -> 0 bytes
-rw-r--r--doc/ci/autodeploy/quick_start_guide.md96
-rw-r--r--doc/ci/caching/index.md20
-rw-r--r--doc/ci/chatops/README.md61
-rw-r--r--doc/ci/chatops/img/gitlab-chatops-icon-small.pngbin0 -> 2922 bytes
-rw-r--r--doc/ci/chatops/img/gitlab-chatops-icon.pngbin0 -> 12308 bytes
-rw-r--r--doc/ci/docker/README.md8
-rw-r--r--doc/ci/docker/using_docker_build.md10
-rw-r--r--doc/ci/docker/using_docker_images.md4
-rw-r--r--doc/ci/docker/using_kaniko.md25
-rw-r--r--doc/ci/environments.md94
-rw-r--r--doc/ci/examples/README.md1
-rw-r--r--doc/ci/examples/artifactory_and_gitlab/index.md6
-rw-r--r--doc/ci/examples/browser_performance.md2
-rw-r--r--doc/ci/examples/code_quality.md2
-rw-r--r--doc/ci/examples/container_scanning.md6
-rw-r--r--doc/ci/examples/dast.md2
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md6
-rw-r--r--doc/ci/examples/deployment/README.md4
-rw-r--r--doc/ci/examples/deployment/composer-npm-deploy.md1
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/img/deployed_dependency_update.pngbin0 -> 67788 bytes
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/index.md251
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md7
-rw-r--r--doc/ci/examples/sast_docker.md2
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md2
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md2
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md4
-rw-r--r--doc/ci/interactive_web_terminal/index.md16
-rw-r--r--doc/ci/junit_test_reports.md6
-rw-r--r--doc/ci/merge_request_pipelines/index.md47
-rw-r--r--doc/ci/pipelines.md10
-rw-r--r--doc/ci/quick_start/README.md4
-rw-r--r--doc/ci/review_apps/img/view_on_env_blob.png (renamed from doc/ci/img/view_on_env_blob.png)bin11889 -> 11889 bytes
-rw-r--r--doc/ci/review_apps/img/view_on_env_mr.png (renamed from doc/ci/img/view_on_env_mr.png)bin295181 -> 295181 bytes
-rw-r--r--doc/ci/review_apps/img/view_on_mr_widget.png (renamed from doc/ci/img/view_on_mr_widget.png)bin21942 -> 21942 bytes
-rw-r--r--doc/ci/review_apps/index.md87
-rw-r--r--doc/ci/runners/README.md75
-rw-r--r--doc/ci/services/mysql.md4
-rw-r--r--doc/ci/ssh_keys/README.md2
-rw-r--r--doc/ci/triggers/README.md2
-rw-r--r--doc/ci/variables/README.md137
-rw-r--r--doc/ci/variables/img/variables.pngbin34838 -> 0 bytes
-rw-r--r--doc/ci/yaml/README.md644
-rw-r--r--doc/customization/help_message.md13
-rw-r--r--doc/customization/help_message/help_text.pngbin0 -> 86118 bytes
-rw-r--r--doc/customization/help_message/help_text_on_help_page.pngbin0 -> 24355 bytes
-rw-r--r--doc/customization/index.md18
-rw-r--r--doc/customization/libravatar.md4
-rw-r--r--doc/customization/system_header_and_footer_messages.md22
-rw-r--r--doc/customization/system_header_and_footer_messages/appearance.pngbin0 -> 124214 bytes
-rw-r--r--doc/customization/system_header_and_footer_messages/custom_header_footer.pngbin0 -> 484001 bytes
-rw-r--r--doc/customization/system_header_and_footer_messages/sign_up_custom_header_and_footer.pngbin0 -> 360832 bytes
-rw-r--r--doc/customization/welcome_message.md13
-rw-r--r--doc/development/README.md6
-rw-r--r--doc/development/adding_database_indexes.md4
-rw-r--r--doc/development/api_graphql_styleguide.md24
-rw-r--r--doc/development/api_styleguide.md6
-rw-r--r--doc/development/architecture.md27
-rw-r--r--doc/development/automatic_ce_ee_merge.md24
-rw-r--r--doc/development/background_migrations.md6
-rw-r--r--doc/development/changelog.md22
-rw-r--r--doc/development/code_review.md18
-rw-r--r--doc/development/contributing/index.md36
-rw-r--r--doc/development/contributing/issue_workflow.md38
-rw-r--r--doc/development/contributing/merge_request_workflow.md24
-rw-r--r--doc/development/contributing/style_guides.md1
-rw-r--r--doc/development/database_debugging.md3
-rw-r--r--doc/development/diffs.md5
-rw-r--r--doc/development/distributed_tracing.md182
-rw-r--r--doc/development/documentation/feature-change-workflow.md179
-rw-r--r--doc/development/documentation/improvement-workflow.md63
-rw-r--r--doc/development/documentation/index.md232
-rw-r--r--doc/development/documentation/site_architecture/global_nav.md5
-rw-r--r--doc/development/documentation/site_architecture/index.md11
-rw-r--r--doc/development/documentation/structure.md168
-rw-r--r--doc/development/documentation/styleguide.md329
-rw-r--r--doc/development/documentation/workflow.md185
-rw-r--r--doc/development/ee_features.md135
-rw-r--r--doc/development/emails.md30
-rw-r--r--doc/development/fe_guide/accessibility.md1
-rw-r--r--doc/development/fe_guide/architecture.md7
-rw-r--r--doc/development/fe_guide/components.md7
-rw-r--r--doc/development/fe_guide/design_patterns.md1
-rw-r--r--doc/development/fe_guide/development_process.md8
-rw-r--r--doc/development/fe_guide/droplab/droplab.md37
-rw-r--r--doc/development/fe_guide/droplab/plugins/ajax.md8
-rw-r--r--doc/development/fe_guide/droplab/plugins/filter.md6
-rw-r--r--doc/development/fe_guide/droplab/plugins/input_setter.md9
-rw-r--r--doc/development/fe_guide/graphql.md30
-rw-r--r--doc/development/fe_guide/index.md31
-rw-r--r--doc/development/fe_guide/performance.md16
-rw-r--r--doc/development/fe_guide/security.md1
-rw-r--r--doc/development/fe_guide/style_guide_js.md22
-rw-r--r--doc/development/fe_guide/vue.md12
-rw-r--r--doc/development/fe_guide/vuex.md4
-rw-r--r--doc/development/feature_flags.md6
-rw-r--r--doc/development/file_storage.md19
-rw-r--r--doc/development/gitaly.md64
-rw-r--r--doc/development/github_importer.md22
-rw-r--r--doc/development/go_guide/index.md216
-rw-r--r--doc/development/gotchas.md4
-rw-r--r--doc/development/i18n/externalization.md10
-rw-r--r--doc/development/i18n/index.md2
-rw-r--r--doc/development/i18n/merging_translations.md5
-rw-r--r--doc/development/i18n/proofreader.md3
-rw-r--r--doc/development/img/distributed_tracing_jaeger_ui.pngbin0 -> 1032713 bytes
-rw-r--r--doc/development/img/distributed_tracing_performance_bar.pngbin0 -> 108809 bytes
-rw-r--r--doc/development/import_export.md351
-rw-r--r--doc/development/instrumentation.md10
-rw-r--r--doc/development/kubernetes.md126
-rw-r--r--doc/development/logging.md30
-rw-r--r--doc/development/merge_request_performance_guidelines.md4
-rw-r--r--doc/development/migration_style_guide.md36
-rw-r--r--doc/development/new_fe_guide/development/accessibility.md3
-rw-r--r--doc/development/new_fe_guide/development/components.md14
-rw-r--r--doc/development/new_fe_guide/development/performance.md8
-rw-r--r--doc/development/new_fe_guide/development/testing.md23
-rw-r--r--doc/development/new_fe_guide/event_tracking.md74
-rw-r--r--doc/development/new_fe_guide/index.md4
-rw-r--r--doc/development/new_fe_guide/modules/index.md4
-rw-r--r--doc/development/new_fe_guide/style/html.md4
-rw-r--r--doc/development/new_fe_guide/style/javascript.md42
-rw-r--r--doc/development/ordering_table_columns.md9
-rw-r--r--doc/development/performance.md43
-rw-r--r--doc/development/policies.md69
-rw-r--r--doc/development/polling.md1
-rw-r--r--doc/development/polymorphic_associations.md12
-rw-r--r--doc/development/post_deployment_migrations.md6
-rw-r--r--doc/development/profiling.md16
-rw-r--r--doc/development/rake_tasks.md10
-rw-r--r--doc/development/reusing_abstractions.md18
-rw-r--r--doc/development/rolling_out_changes_using_feature_flags.md31
-rw-r--r--doc/development/shell_commands.md5
-rw-r--r--doc/development/sidekiq_debugging.md9
-rw-r--r--doc/development/sql.md34
-rw-r--r--doc/development/testing_guide/best_practices.md28
-rw-r--r--doc/development/testing_guide/ci.md6
-rw-r--r--doc/development/testing_guide/end_to_end_tests.md16
-rw-r--r--doc/development/testing_guide/flaky_tests.md73
-rw-r--r--doc/development/testing_guide/frontend_testing.md25
-rw-r--r--doc/development/testing_guide/img/review_apps_cicd_architecture.pngbin0 -> 73240 bytes
-rw-r--r--doc/development/testing_guide/review_apps.md133
-rw-r--r--doc/development/testing_guide/testing_levels.md20
-rw-r--r--doc/development/understanding_explain_plans.md10
-rw-r--r--doc/development/utilities.md14
-rw-r--r--doc/development/verifying_database_capabilities.md6
-rw-r--r--doc/gitlab-basics/create-project.md103
-rw-r--r--doc/gitlab-basics/create-your-ssh-keys.md12
-rw-r--r--doc/gitlab-basics/img/create_new_project_button.pngbin3702 -> 0 bytes
-rw-r--r--doc/gitlab-basics/img/create_new_project_info.pngbin71608 -> 0 bytes
-rw-r--r--doc/gitlab-basics/start-using-git.md48
-rw-r--r--doc/install/README.md2
-rw-r--r--doc/install/aws/index.md11
-rw-r--r--doc/install/azure/index.md227
-rw-r--r--doc/install/docker.md2
-rw-r--r--doc/install/google_cloud_platform/index.md6
-rw-r--r--doc/install/installation.md665
-rw-r--r--doc/install/kubernetes/gitlab_chart.md2
-rw-r--r--doc/install/kubernetes/gitlab_omnibus.md16
-rw-r--r--doc/install/kubernetes/gitlab_runner_chart.md17
-rw-r--r--doc/install/kubernetes/index.md2
-rw-r--r--doc/install/kubernetes/preparation/eks.md3
-rw-r--r--doc/install/kubernetes/preparation/networking.md4
-rw-r--r--doc/install/kubernetes/preparation/tiller.md18
-rw-r--r--doc/install/kubernetes/preparation/tools_installation.md2
-rw-r--r--doc/install/openshift_and_gitlab/index.md10
-rw-r--r--doc/install/requirements.md4
-rw-r--r--doc/install/structure.md8
-rw-r--r--doc/integration/README.md7
-rw-r--r--doc/integration/akismet.md3
-rw-r--r--doc/integration/auth0.md22
-rw-r--r--doc/integration/azure.md8
-rw-r--r--doc/integration/bitbucket.md6
-rw-r--r--doc/integration/cas.md2
-rw-r--r--doc/integration/external-issue-tracker.md5
-rw-r--r--doc/integration/facebook.md2
-rw-r--r--doc/integration/github.md7
-rw-r--r--doc/integration/gmail_action_buttons_for_gitlab.md8
-rw-r--r--doc/integration/google.md1
-rw-r--r--doc/integration/oauth_provider.md9
-rw-r--r--doc/integration/omniauth.md7
-rw-r--r--doc/integration/saml.md3
-rw-r--r--doc/integration/slash_commands.md4
-rw-r--r--doc/integration/twitter.md4
-rw-r--r--doc/intro/README.md4
-rw-r--r--doc/migrate_ci_to_ce/README.md4
-rw-r--r--doc/policy/maintenance.md50
-rw-r--r--doc/project_services/bamboo.md4
-rw-r--r--doc/project_services/bugzilla.md4
-rw-r--r--doc/project_services/emails_on_push.md4
-rw-r--r--doc/project_services/hipchat.md1
-rw-r--r--doc/project_services/irker.md4
-rw-r--r--doc/project_services/jira.md4
-rw-r--r--doc/project_services/kubernetes.md4
-rw-r--r--doc/project_services/mattermost.md4
-rw-r--r--doc/project_services/mattermost_slash_commands.md4
-rw-r--r--doc/project_services/project_services.md4
-rw-r--r--doc/project_services/redmine.md4
-rw-r--r--doc/project_services/services_templates.md4
-rw-r--r--doc/project_services/slack.md4
-rw-r--r--doc/project_services/slack_slash_commands.md4
-rw-r--r--doc/public_access/public_access.md2
-rw-r--r--doc/raketasks/backup_restore.md36
-rw-r--r--doc/raketasks/user_management.md2
-rw-r--r--doc/security/README.md1
-rw-r--r--doc/security/crime_vulnerability.md10
-rw-r--r--doc/security/img/ssh_keys_restricted_key_icon.pngbin0 -> 4887 bytes
-rw-r--r--doc/security/ssh_keys_restrictions.md8
-rw-r--r--doc/security/webhooks.md6
-rw-r--r--doc/ssh/README.md31
-rw-r--r--doc/system_hooks/system_hooks.md14
-rw-r--r--doc/topics/authentication/index.md6
-rw-r--r--doc/topics/autodevops/index.md196
-rw-r--r--doc/topics/autodevops/quick_start_guide.md18
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md8
-rw-r--r--doc/university/glossary/README.md17
-rw-r--r--doc/university/high-availability/aws/README.md41
-rw-r--r--doc/university/support/README.md1
-rw-r--r--doc/university/training/end-user/README.md28
-rw-r--r--doc/university/training/topics/env_setup.md2
-rw-r--r--doc/university/training/topics/getting_started.md14
-rw-r--r--doc/university/training/topics/git_add.md10
-rw-r--r--doc/university/training/topics/git_intro.md4
-rw-r--r--doc/university/training/topics/git_log.md11
-rw-r--r--doc/university/training/topics/merge_conflicts.md9
-rw-r--r--doc/university/training/topics/rollback_commits.md15
-rw-r--r--doc/university/training/topics/stash.md17
-rw-r--r--doc/university/training/topics/subtree.md18
-rw-r--r--doc/university/training/topics/unstage.md8
-rw-r--r--doc/update/10.0-to-10.1.md359
-rw-r--r--doc/update/10.1-to-10.2.md359
-rw-r--r--doc/update/10.2-to-10.3.md358
-rw-r--r--doc/update/10.3-to-10.4.md360
-rw-r--r--doc/update/10.4-to-10.5.md360
-rw-r--r--doc/update/10.5-to-10.6.md360
-rw-r--r--doc/update/10.6-to-10.7.md360
-rw-r--r--doc/update/10.7-to-10.8.md361
-rw-r--r--doc/update/10.8-to-11.0.md360
-rw-r--r--doc/update/11.0-to-11.1.md377
-rw-r--r--doc/update/11.1-to-11.2.md377
-rw-r--r--doc/update/11.2-to-11.3.md377
-rw-r--r--doc/update/11.3-to-11.4.md377
-rw-r--r--doc/update/11.4-to-11.5.md389
-rw-r--r--doc/update/11.5-to-11.6.md389
-rw-r--r--doc/update/11.6-to-11.7.md5
-rw-r--r--doc/update/11.7-to-11.8.md5
-rw-r--r--doc/update/2.6-to-3.0.md69
-rw-r--r--doc/update/2.9-to-3.0.md45
-rw-r--r--doc/update/3.0-to-3.1.md105
-rw-r--r--doc/update/3.1-to-4.0.md98
-rw-r--r--doc/update/4.0-to-4.1.md64
-rw-r--r--doc/update/4.1-to-4.2.md47
-rw-r--r--doc/update/4.2-to-5.0.md223
-rw-r--r--doc/update/5.0-to-5.1.md104
-rw-r--r--doc/update/5.1-to-5.2.md123
-rw-r--r--doc/update/5.1-to-5.4.md119
-rw-r--r--doc/update/5.1-to-6.0.md235
-rw-r--r--doc/update/5.2-to-5.3.md105
-rw-r--r--doc/update/5.3-to-5.4.md109
-rw-r--r--doc/update/5.4-to-6.0.md168
-rw-r--r--doc/update/6.0-to-6.1.md126
-rw-r--r--doc/update/6.1-to-6.2.md140
-rw-r--r--doc/update/6.2-to-6.3.md126
-rw-r--r--doc/update/6.3-to-6.4.md108
-rw-r--r--doc/update/6.4-to-6.5.md114
-rw-r--r--doc/update/6.5-to-6.6.md116
-rw-r--r--doc/update/6.6-to-6.7.md122
-rw-r--r--doc/update/6.7-to-6.8.md125
-rw-r--r--doc/update/6.8-to-6.9.md106
-rw-r--r--doc/update/6.9-to-7.0.md144
-rw-r--r--doc/update/6.x-or-7.x-to-7.14.md316
-rw-r--r--doc/update/7.0-to-7.1.md143
-rw-r--r--doc/update/7.1-to-7.2.md142
-rw-r--r--doc/update/7.10-to-7.11.md108
-rw-r--r--doc/update/7.11-to-7.12.md134
-rw-r--r--doc/update/7.12-to-7.13.md134
-rw-r--r--doc/update/7.13-to-7.14.md134
-rw-r--r--doc/update/7.14-to-8.0.md234
-rw-r--r--doc/update/7.2-to-7.3.md150
-rw-r--r--doc/update/7.3-to-7.4.md199
-rw-r--r--doc/update/7.4-to-7.5.md115
-rw-r--r--doc/update/7.5-to-7.6.md122
-rw-r--r--doc/update/7.6-to-7.7.md127
-rw-r--r--doc/update/7.7-to-7.8.md128
-rw-r--r--doc/update/7.8-to-7.9.md130
-rw-r--r--doc/update/7.9-to-7.10.md126
-rw-r--r--doc/update/8.0-to-8.1.md180
-rw-r--r--doc/update/8.1-to-8.2.md197
-rw-r--r--doc/update/8.10-to-8.11.md204
-rw-r--r--doc/update/8.11-to-8.12.md212
-rw-r--r--doc/update/8.12-to-8.13.md212
-rw-r--r--doc/update/8.13-to-8.14.md212
-rw-r--r--doc/update/8.14-to-8.15.md242
-rw-r--r--doc/update/8.15-to-8.16.md244
-rw-r--r--doc/update/8.16-to-8.17.md271
-rw-r--r--doc/update/8.17-to-9.0.md357
-rw-r--r--doc/update/8.2-to-8.3.md226
-rw-r--r--doc/update/8.3-to-8.4.md142
-rw-r--r--doc/update/8.4-to-8.5.md163
-rw-r--r--doc/update/8.5-to-8.6.md182
-rw-r--r--doc/update/8.6-to-8.7.md171
-rw-r--r--doc/update/8.7-to-8.8.md171
-rw-r--r--doc/update/8.8-to-8.9.md200
-rw-r--r--doc/update/8.9-to-8.10.md200
-rw-r--r--doc/update/9.0-to-9.1.md406
-rw-r--r--doc/update/9.1-to-9.2.md329
-rw-r--r--doc/update/9.2-to-9.3.md347
-rw-r--r--doc/update/9.3-to-9.4.md360
-rw-r--r--doc/update/9.4-to-9.5.md359
-rw-r--r--doc/update/9.5-to-10.0.md359
-rw-r--r--doc/update/README.md45
-rw-r--r--doc/update/mysql_to_postgresql.md7
-rw-r--r--doc/update/restore_after_failure.md3
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md132
-rw-r--r--doc/update/upgrading_from_source.md390
-rw-r--r--doc/update/upgrading_postgresql_using_slony.md11
-rw-r--r--doc/user/abuse_reports.md1
-rw-r--r--doc/user/account/security.md4
-rw-r--r--doc/user/account/two_factor_authentication.md4
-rw-r--r--doc/user/admin_area/broadcast_messages.md53
-rw-r--r--doc/user/admin_area/custom_project_templates.md23
-rw-r--r--doc/user/admin_area/img/broadcast_messages.pngbin0 -> 68535 bytes
-rw-r--r--doc/user/admin_area/index.md29
-rw-r--r--doc/user/admin_area/monitoring/health_check.md25
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md6
-rw-r--r--doc/user/admin_area/settings/index.md4
-rw-r--r--doc/user/admin_area/settings/third_party_offers.md5
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md6
-rw-r--r--doc/user/award_emojis.md32
-rw-r--r--doc/user/discussions/index.md39
-rw-r--r--doc/user/gitlab_com/index.md14
-rw-r--r--doc/user/group/clusters/index.md20
-rw-r--r--doc/user/group/custom_project_templates.md23
-rw-r--r--doc/user/group/index.md19
-rw-r--r--doc/user/group/subgroups/index.md24
-rw-r--r--doc/user/index.md78
-rw-r--r--doc/user/instance_statistics/convdev.md23
-rw-r--r--doc/user/instance_statistics/user_cohorts.md5
-rw-r--r--doc/user/markdown.md45
-rw-r--r--doc/user/permissions.md24
-rw-r--r--doc/user/profile/account/index.md3
-rw-r--r--doc/user/profile/account/two_factor_authentication.md16
-rw-r--r--doc/user/profile/active_sessions.md8
-rw-r--r--doc/user/profile/img/active_sessions_list.pngbin22266 -> 19360 bytes
-rw-r--r--doc/user/profile/index.md9
-rw-r--r--doc/user/profile/preferences.md25
-rw-r--r--doc/user/project/builds/artifacts.md4
-rw-r--r--doc/user/project/clusters/eks_and_gitlab/index.md2
-rw-r--r--doc/user/project/clusters/index.md161
-rw-r--r--doc/user/project/clusters/runbooks/index.md8
-rw-r--r--doc/user/project/clusters/serverless/img/dns-entry.pngbin19583 -> 66116 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/install-knative.pngbin13003 -> 86225 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/serverless-page.pngbin194708 -> 191568 bytes
-rw-r--r--doc/user/project/clusters/serverless/index.md171
-rw-r--r--doc/user/project/container_registry.md9
-rw-r--r--doc/user/project/cycle_analytics.md5
-rw-r--r--doc/user/project/description_templates.md1
-rw-r--r--doc/user/project/gpg_signed_commits/index.md4
-rw-r--r--doc/user/project/img/issue_boards_multiple.pngbin6086 -> 68373 bytes
-rw-r--r--doc/user/project/img/releases.pngbin43612 -> 0 bytes
-rw-r--r--doc/user/project/import/bitbucket_server.md12
-rw-r--r--doc/user/project/import/fogbugz.md2
-rw-r--r--doc/user/project/import/github.md28
-rw-r--r--doc/user/project/import/index.md7
-rw-r--r--doc/user/project/import/repo_by_url.md2
-rw-r--r--doc/user/project/import/svn.md2
-rw-r--r--doc/user/project/index.md82
-rw-r--r--doc/user/project/integrations/bamboo.md3
-rw-r--r--doc/user/project/integrations/emails_on_push.md8
-rw-r--r--doc/user/project/integrations/hipchat.md53
-rw-r--r--doc/user/project/integrations/irker.md12
-rw-r--r--doc/user/project/integrations/jira.md24
-rw-r--r--doc/user/project/integrations/jira_cloud_configuration.md2
-rw-r--r--doc/user/project/integrations/kubernetes.md4
-rw-r--r--doc/user/project/integrations/mattermost.md4
-rw-r--r--doc/user/project/integrations/mattermost_slash_commands.md2
-rw-r--r--doc/user/project/integrations/project_services.md2
-rw-r--r--doc/user/project/integrations/prometheus.md23
-rw-r--r--doc/user/project/integrations/prometheus_library/index.md5
-rw-r--r--doc/user/project/integrations/prometheus_library/kubernetes.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/metrics.md4
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress.md32
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md58
-rw-r--r--doc/user/project/integrations/redmine.md6
-rw-r--r--doc/user/project/integrations/slack.md52
-rw-r--r--doc/user/project/integrations/webhooks.md34
-rw-r--r--doc/user/project/integrations/youtrack.md31
-rw-r--r--doc/user/project/issue_board.md21
-rw-r--r--doc/user/project/issues/automatic_issue_closing.md1
-rw-r--r--doc/user/project/issues/create_new_issue.md44
-rw-r--r--doc/user/project/issues/csv_import.md63
-rw-r--r--doc/user/project/issues/due_dates.md1
-rw-r--r--doc/user/project/issues/index.md19
-rw-r--r--doc/user/project/issues/issues_functionalities.md86
-rw-r--r--doc/user/project/members/index.md2
-rw-r--r--doc/user/project/merge_requests.md4
-rw-r--r--doc/user/project/merge_requests/allow_collaboration.md66
-rw-r--r--doc/user/project/merge_requests/img/allow_collaboration.pngbin21522 -> 11028 bytes
-rw-r--r--doc/user/project/merge_requests/img/allow_collaboration_after_save.pngbin0 -> 5415 bytes
-rw-r--r--doc/user/project/merge_requests/img/checkout_button.pngbin0 -> 5977 bytes
-rw-r--r--doc/user/project/merge_requests/img/create_from_email.pngbin55777 -> 112256 bytes
-rw-r--r--doc/user/project/merge_requests/img/squash_mr_message.pngbin0 -> 150302 bytes
-rw-r--r--doc/user/project/merge_requests/index.md45
-rw-r--r--doc/user/project/merge_requests/maintainer_access.md4
-rw-r--r--doc/user/project/merge_requests/merge_request_discussion_resolution.md4
-rw-r--r--doc/user/project/merge_requests/merge_when_build_succeeds.md8
-rw-r--r--doc/user/project/merge_requests/squash_and_merge.md29
-rw-r--r--doc/user/project/milestones/index.md5
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md2
-rw-r--r--doc/user/project/operations/error_tracking.md41
-rw-r--r--doc/user/project/operations/img/error_tracking_list.pngbin0 -> 230740 bytes
-rw-r--r--doc/user/project/operations/index.md11
-rw-r--r--doc/user/project/pages/getting_started_part_four.md10
-rw-r--r--doc/user/project/pages/getting_started_part_one.md44
-rw-r--r--doc/user/project/pages/getting_started_part_three.md61
-rw-r--r--doc/user/project/pages/getting_started_part_two.md54
-rw-r--r--doc/user/project/pages/index.md12
-rw-r--r--doc/user/project/pages/introduction.md74
-rw-r--r--doc/user/project/pipelines/job_artifacts.md13
-rw-r--r--doc/user/project/pipelines/schedules.md4
-rw-r--r--doc/user/project/pipelines/settings.md94
-rw-r--r--doc/user/project/protected_branches.md25
-rw-r--r--doc/user/project/protected_tags.md3
-rw-r--r--doc/user/project/quick_actions.md1
-rw-r--r--doc/user/project/releases.md15
-rw-r--r--doc/user/project/releases/img/releases.pngbin0 -> 126093 bytes
-rw-r--r--doc/user/project/releases/index.md62
-rw-r--r--doc/user/project/repository/branches/index.md16
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md65
-rw-r--r--doc/user/project/repository/index.md18
-rw-r--r--doc/user/project/repository/web_editor.md5
-rw-r--r--doc/user/project/settings/img/general_settings.pngbin35871 -> 154764 bytes
-rw-r--r--doc/user/project/settings/import_export.md3
-rw-r--r--doc/user/project/settings/index.md10
-rw-r--r--doc/user/project/slash_commands.md4
-rw-r--r--doc/user/project/web_ide/index.md34
-rw-r--r--doc/user/reserved_names.md3
-rw-r--r--doc/user/search/index.md14
-rw-r--r--doc/user/snippets.md9
-rw-r--r--doc/workflow/forking_workflow.md1
-rw-r--r--doc/workflow/gitlab_flow.md458
-rw-r--r--doc/workflow/groups.md3
-rw-r--r--doc/workflow/lfs/lfs_administration.md22
-rw-r--r--doc/workflow/lfs/manage_large_binaries_with_git_lfs.md26
-rw-r--r--doc/workflow/releases.md18
-rw-r--r--doc/workflow/repository_mirroring.md31
-rw-r--r--doc/workflow/shortcuts.md2
-rw-r--r--doc/workflow/time_tracking.md28
-rw-r--r--doc/workflow/todos.md3
-rw-r--r--jest.config.js9
-rw-r--r--lib/api/api.rb8
-rw-r--r--lib/api/branches.rb4
-rw-r--r--lib/api/commits.rb27
-rw-r--r--lib/api/container_registry.rb143
-rw-r--r--lib/api/deployments.rb2
-rw-r--r--lib/api/entities.rb214
-rw-r--r--lib/api/entities/container_registry.rb29
-rw-r--r--lib/api/environments.rb12
-rw-r--r--lib/api/features.rb16
-rw-r--r--lib/api/group_labels.rb63
-rw-r--r--lib/api/helpers.rb37
-rw-r--r--lib/api/helpers/custom_validators.rb13
-rw-r--r--lib/api/helpers/graphql_helpers.rb22
-rw-r--r--lib/api/helpers/internal_helpers.rb8
-rw-r--r--lib/api/helpers/label_helpers.rb82
-rw-r--r--lib/api/helpers/notes_helpers.rb14
-rw-r--r--lib/api/helpers/pagination.rb96
-rw-r--r--lib/api/helpers/presentable.rb29
-rw-r--r--lib/api/helpers/runner.rb2
-rw-r--r--lib/api/helpers/version.rb29
-rw-r--r--lib/api/import_github.rb46
-rw-r--r--lib/api/internal.rb12
-rw-r--r--lib/api/issues.rb32
-rw-r--r--lib/api/job_artifacts.rb23
-rw-r--r--lib/api/jobs.rb7
-rw-r--r--lib/api/labels.rb83
-rw-r--r--lib/api/lint.rb3
-rw-r--r--lib/api/merge_requests.rb45
-rw-r--r--lib/api/notes.rb2
-rw-r--r--lib/api/pipeline_schedules.rb6
-rw-r--r--lib/api/pipelines.rb12
-rw-r--r--lib/api/project_clusters.rb142
-rw-r--r--lib/api/project_milestones.rb17
-rw-r--r--lib/api/project_statistics.rb23
-rw-r--r--lib/api/project_templates.rb5
-rw-r--r--lib/api/projects.rb55
-rw-r--r--lib/api/projects_relation_builder.rb2
-rw-r--r--lib/api/release/links.rb117
-rw-r--r--lib/api/releases.rb143
-rw-r--r--lib/api/runners.rb6
-rw-r--r--lib/api/services.rb69
-rw-r--r--lib/api/settings.rb3
-rw-r--r--lib/api/snippets.rb25
-rw-r--r--lib/api/subscriptions.rb87
-rw-r--r--lib/api/tags.rb77
-rw-r--r--lib/api/todos.rb2
-rw-r--r--lib/api/triggers.rb20
-rw-r--r--lib/api/users.rb8
-rw-r--r--lib/api/validations/types/labels_list.rb24
-rw-r--r--lib/api/variables.rb2
-rw-r--r--lib/api/version.rb18
-rw-r--r--lib/api/wikis.rb19
-rw-r--r--lib/backup/files.rb10
-rw-r--r--lib/backup/manager.rb3
-rw-r--r--lib/backup/repository.rb2
-rw-r--r--lib/banzai/filter/autolink_filter.rb17
-rw-r--r--lib/banzai/filter/emoji_filter.rb1
-rw-r--r--lib/banzai/filter/external_link_filter.rb93
-rw-r--r--lib/banzai/filter/footnote_filter.rb77
-rw-r--r--lib/banzai/filter/image_lazy_load_filter.rb1
-rw-r--r--lib/banzai/filter/image_link_filter.rb1
-rw-r--r--lib/banzai/filter/inline_diff_filter.rb1
-rw-r--r--lib/banzai/filter/label_reference_filter.rb6
-rw-r--r--lib/banzai/filter/markdown_engines/common_mark.rb15
-rw-r--r--lib/banzai/filter/markdown_engines/redcarpet.rb34
-rw-r--r--lib/banzai/filter/markdown_filter.rb2
-rw-r--r--lib/banzai/filter/math_filter.rb3
-rw-r--r--lib/banzai/filter/mermaid_filter.rb1
-rw-r--r--lib/banzai/filter/milestone_reference_filter.rb4
-rw-r--r--lib/banzai/filter/reference_filter.rb1
-rw-r--r--lib/banzai/filter/relative_link_filter.rb7
-rw-r--r--lib/banzai/filter/sanitization_filter.rb32
-rw-r--r--lib/banzai/filter/spaced_link_filter.rb5
-rw-r--r--lib/banzai/filter/suggestion_filter.rb1
-rw-r--r--lib/banzai/filter/syntax_highlight_filter.rb2
-rw-r--r--lib/banzai/filter/table_of_contents_filter.rb1
-rw-r--r--lib/banzai/filter/task_list_filter.rb4
-rw-r--r--lib/banzai/filter/video_link_filter.rb1
-rw-r--r--lib/banzai/pipeline/atom_pipeline.rb3
-rw-r--r--lib/banzai/pipeline/broadcast_message_pipeline.rb6
-rw-r--r--lib/banzai/pipeline/email_pipeline.rb4
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb11
-rw-r--r--lib/banzai/pipeline/markup_pipeline.rb3
-rw-r--r--lib/banzai/pipeline/single_line_pipeline.rb6
-rw-r--r--lib/banzai/renderer/redcarpet/html.rb17
-rw-r--r--lib/bitbucket_server/client.rb14
-rw-r--r--lib/bitbucket_server/collection.rb4
-rw-r--r--lib/bitbucket_server/connection.rb18
-rw-r--r--lib/bitbucket_server/paginator.rb12
-rw-r--r--lib/constraints/project_url_constrainer.rb3
-rw-r--r--lib/container_registry/tag.rb38
-rw-r--r--lib/declarative_policy/rule.rb6
-rw-r--r--lib/feature.rb44
-rw-r--r--lib/gitlab.rb20
-rw-r--r--lib/gitlab/access/branch_protection.rb42
-rw-r--r--lib/gitlab/auth.rb5
-rw-r--r--lib/gitlab/auth/ldap/adapter.rb19
-rw-r--r--lib/gitlab/auth/ldap/config.rb59
-rw-r--r--lib/gitlab/auth/ldap/person.rb6
-rw-r--r--lib/gitlab/auth/o_auth/user.rb2
-rw-r--r--lib/gitlab/auth/omniauth_identity_linker_base.rb6
-rw-r--r--lib/gitlab/auth/saml/auth_hash.rb4
-rw-r--r--lib/gitlab/background_migration.rb28
-rw-r--r--lib/gitlab/background_migration/backfill_project_repositories.rb14
-rw-r--r--lib/gitlab/background_migration/encrypt_columns.rb3
-rw-r--r--lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb2
-rw-r--r--lib/gitlab/background_migration/migrate_stage_status.rb8
-rw-r--r--lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb2
-rw-r--r--lib/gitlab/bare_repository_import/importer.rb2
-rw-r--r--lib/gitlab/bitbucket_import/importer.rb8
-rw-r--r--lib/gitlab/bitbucket_import/wiki_formatter.rb25
-rw-r--r--lib/gitlab/bitbucket_server_import/importer.rb6
-rw-r--r--lib/gitlab/blob_helper.rb10
-rw-r--r--lib/gitlab/chat.rb10
-rw-r--r--lib/gitlab/chat/command.rb94
-rw-r--r--lib/gitlab/chat/output.rb93
-rw-r--r--lib/gitlab/chat/responder.rb22
-rw-r--r--lib/gitlab/chat/responder/base.rb40
-rw-r--r--lib/gitlab/chat/responder/slack.rb80
-rw-r--r--lib/gitlab/checks/base_checker.rb22
-rw-r--r--lib/gitlab/checks/branch_check.rb36
-rw-r--r--lib/gitlab/checks/change_access.rb5
-rw-r--r--lib/gitlab/checks/diff_check.rb26
-rw-r--r--lib/gitlab/checks/lfs_check.rb1
-rw-r--r--lib/gitlab/checks/push_check.rb4
-rw-r--r--lib/gitlab/ci/ansi2html.rb20
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata.rb2
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata/entry.rb2
-rw-r--r--lib/gitlab/ci/build/policy/changes.rb2
-rw-r--r--lib/gitlab/ci/build/policy/refs.rb8
-rw-r--r--lib/gitlab/ci/build/step.rb1
-rw-r--r--lib/gitlab/ci/config.rb18
-rw-r--r--lib/gitlab/ci/config/entry/global.rb3
-rw-r--r--lib/gitlab/ci/config/entry/include.rb23
-rw-r--r--lib/gitlab/ci/config/entry/includes.rb32
-rw-r--r--lib/gitlab/ci/config/entry/job.rb21
-rw-r--r--lib/gitlab/ci/config/entry/jobs.rb6
-rw-r--r--lib/gitlab/ci/config/entry/policy.rb5
-rw-r--r--lib/gitlab/ci/config/entry/retry.rb3
-rw-r--r--lib/gitlab/ci/config/entry/variables.rb2
-rw-r--r--lib/gitlab/ci/config/external/file/base.rb44
-rw-r--r--lib/gitlab/ci/config/external/file/local.rb16
-rw-r--r--lib/gitlab/ci/config/external/file/project.rb79
-rw-r--r--lib/gitlab/ci/config/external/file/remote.rb6
-rw-r--r--lib/gitlab/ci/config/external/file/template.rb51
-rw-r--r--lib/gitlab/ci/config/external/mapper.rb82
-rw-r--r--lib/gitlab/ci/config/external/processor.rb6
-rw-r--r--lib/gitlab/ci/config/normalizer.rb3
-rw-r--r--lib/gitlab/ci/cron_parser.rb7
-rw-r--r--lib/gitlab/ci/pipeline/chain/build.rb3
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb13
-rw-r--r--lib/gitlab/ci/pipeline/chain/limit/activity.rb21
-rw-r--r--lib/gitlab/ci/pipeline/chain/limit/size.rb21
-rw-r--r--lib/gitlab/ci/pipeline/chain/populate.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb25
-rw-r--r--lib/gitlab/ci/pipeline/chain/skip.rb7
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/repository.rb4
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb10
-rw-r--r--lib/gitlab/ci/pipeline/seed/stage.rb8
-rw-r--r--lib/gitlab/ci/status/bridge/common.rb1
-rw-r--r--lib/gitlab/ci/status/external/common.rb2
-rw-r--r--lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml121
-rw-r--r--lib/gitlab/ci/templates/Android.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml207
-rw-r--r--lib/gitlab/ci/templates/Ruby.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml44
-rw-r--r--lib/gitlab/ci/templates/Serverless.gitlab-ci.yml41
-rw-r--r--lib/gitlab/ci/templates/dotNET.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml28
-rw-r--r--lib/gitlab/ci/trace/stream.rb2
-rw-r--r--lib/gitlab/ci/variables/collection.rb2
-rw-r--r--lib/gitlab/ci/variables/collection/item.rb10
-rw-r--r--lib/gitlab/ci/yaml_processor.rb10
-rw-r--r--lib/gitlab/cleanup/remote_uploads.rb2
-rw-r--r--lib/gitlab/config/entry/configurable.rb1
-rw-r--r--lib/gitlab/config/entry/factory.rb17
-rw-r--r--lib/gitlab/config/entry/node.rb4
-rw-r--r--lib/gitlab/config/entry/simplifiable.rb7
-rw-r--r--lib/gitlab/content_disposition.rb54
-rw-r--r--lib/gitlab/contributions_calendar.rb1
-rw-r--r--lib/gitlab/current_settings.rb31
-rw-r--r--lib/gitlab/cycle_analytics/plan_event_fetcher.rb4
-rw-r--r--lib/gitlab/danger/helper.rb136
-rw-r--r--lib/gitlab/danger/teammate.rb42
-rw-r--r--lib/gitlab/data_builder/push.rb15
-rw-r--r--lib/gitlab/database/count/tablesample_count_strategy.rb2
-rw-r--r--lib/gitlab/dependency_linker/base_linker.rb18
-rw-r--r--lib/gitlab/dependency_linker/composer_json_linker.rb4
-rw-r--r--lib/gitlab/dependency_linker/gemfile_linker.rb30
-rw-r--r--lib/gitlab/dependency_linker/gemspec_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/method_linker.rb10
-rw-r--r--lib/gitlab/dependency_linker/package.rb19
-rw-r--r--lib/gitlab/dependency_linker/package_json_linker.rb21
-rw-r--r--lib/gitlab/dependency_linker/parser/gemfile.rb40
-rw-r--r--lib/gitlab/dependency_linker/podfile_linker.rb11
-rw-r--r--lib/gitlab/dependency_linker/podspec_linker.rb2
-rw-r--r--lib/gitlab/diff/file.rb60
-rw-r--r--lib/gitlab/diff/lines_unfolder.rb11
-rw-r--r--lib/gitlab/discussions_diff/file_collection.rb76
-rw-r--r--lib/gitlab/discussions_diff/highlight_cache.rb67
-rw-r--r--lib/gitlab/ee_compat_check.rb2
-rw-r--r--lib/gitlab/email/attachment_uploader.rb4
-rw-r--r--lib/gitlab/email/handler/base_handler.rb4
-rw-r--r--lib/gitlab/email/handler/create_issue_handler.rb28
-rw-r--r--lib/gitlab/email/handler/create_merge_request_handler.rb24
-rw-r--r--lib/gitlab/email/handler/create_note_handler.rb2
-rw-r--r--lib/gitlab/email/handler/reply_processing.rb21
-rw-r--r--lib/gitlab/email/handler/unsubscribe_handler.rb24
-rw-r--r--lib/gitlab/email/reply_parser.rb2
-rw-r--r--lib/gitlab/error_tracking/error.rb14
-rw-r--r--lib/gitlab/error_tracking/project.rb16
-rw-r--r--lib/gitlab/etag_caching/middleware.rb2
-rw-r--r--lib/gitlab/etag_caching/router.rb8
-rw-r--r--lib/gitlab/fogbugz_import/importer.rb2
-rw-r--r--lib/gitlab/gfm/reference_rewriter.rb2
-rw-r--r--lib/gitlab/git.rb4
-rw-r--r--lib/gitlab/git/blob.rb4
-rw-r--r--lib/gitlab/git/bundle_file.rb30
-rw-r--r--lib/gitlab/git/commit.rb21
-rw-r--r--lib/gitlab/git/object_pool.rb9
-rw-r--r--lib/gitlab/git/ref.rb1
-rw-r--r--lib/gitlab/git/repository.rb35
-rw-r--r--lib/gitlab/git/rugged_impl/commit.rb65
-rw-r--r--lib/gitlab/git/rugged_impl/ref.rb20
-rw-r--r--lib/gitlab/git/rugged_impl/repository.rb48
-rw-r--r--lib/gitlab/git/tree.rb2
-rw-r--r--lib/gitlab/git_access.rb50
-rw-r--r--lib/gitlab/git_access_wiki.rb2
-rw-r--r--lib/gitlab/git_post_receive.rb5
-rw-r--r--lib/gitlab/gitaly_client.rb52
-rw-r--r--lib/gitlab/gitaly_client/blob_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb11
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb35
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb22
-rw-r--r--lib/gitlab/gitaly_client/storage_settings.rb8
-rw-r--r--lib/gitlab/gitaly_client/util.rb8
-rw-r--r--lib/gitlab/github_import/bulk_importing.rb4
-rw-r--r--lib/gitlab/github_import/importer/issue_importer.rb6
-rw-r--r--lib/gitlab/github_import/importer/lfs_object_importer.rb8
-rw-r--r--lib/gitlab/github_import/importer/milestones_importer.rb13
-rw-r--r--lib/gitlab/github_import/importer/pull_request_importer.rb30
-rw-r--r--lib/gitlab/github_import/importer/repository_importer.rb9
-rw-r--r--lib/gitlab/github_import/representation/lfs_object.rb4
-rw-r--r--lib/gitlab/github_import/representation/pull_request.rb4
-rw-r--r--lib/gitlab/gon_helper.rb17
-rw-r--r--lib/gitlab/gpg/commit.rb7
-rw-r--r--lib/gitlab/graphql/authorize.rb15
-rw-r--r--lib/gitlab/graphql/authorize/authorize_resource.rb17
-rw-r--r--lib/gitlab/graphql/authorize/instrumentation.rb28
-rw-r--r--lib/gitlab/hashed_storage/migrator.rb56
-rw-r--r--lib/gitlab/hashed_storage/rake_helper.rb12
-rw-r--r--lib/gitlab/highlight.rb2
-rw-r--r--lib/gitlab/i18n/metadata_entry.rb2
-rw-r--r--lib/gitlab/import/merge_request_helpers.rb4
-rw-r--r--lib/gitlab/import_export/import_export.yml21
-rw-r--r--lib/gitlab/import_export/json_hash_builder.rb2
-rw-r--r--lib/gitlab/import_export/merge_request_parser.rb11
-rw-r--r--lib/gitlab/import_export/project_tree_restorer.rb9
-rw-r--r--lib/gitlab/import_export/relation_factory.rb7
-rw-r--r--lib/gitlab/import_export/shared.rb39
-rw-r--r--lib/gitlab/import_export/uploads_manager.rb2
-rw-r--r--lib/gitlab/incoming_email.rb8
-rw-r--r--lib/gitlab/json_cache.rb16
-rw-r--r--lib/gitlab/kubernetes/helm.rb4
-rw-r--r--lib/gitlab/kubernetes/helm/api.rb11
-rw-r--r--lib/gitlab/kubernetes/helm/install_command.rb34
-rw-r--r--lib/gitlab/kubernetes/helm/upgrade_command.rb65
-rw-r--r--lib/gitlab/kubernetes/kube_client.rb13
-rw-r--r--lib/gitlab/legacy_github_import/client.rb2
-rw-r--r--lib/gitlab/legacy_github_import/importer.rb2
-rw-r--r--lib/gitlab/legacy_github_import/user_formatter.rb4
-rw-r--r--lib/gitlab/legacy_github_import/wiki_formatter.rb4
-rw-r--r--lib/gitlab/lfs_token.rb17
-rw-r--r--lib/gitlab/loop_helpers.rb24
-rw-r--r--lib/gitlab/metrics/influx_db.rb4
-rw-r--r--lib/gitlab/metrics/instrumentation.rb4
-rw-r--r--lib/gitlab/metrics/method_call.rb2
-rw-r--r--lib/gitlab/metrics/methods.rb6
-rw-r--r--lib/gitlab/metrics/requests_rack_middleware.rb6
-rw-r--r--lib/gitlab/metrics/samplers/influx_sampler.rb4
-rw-r--r--lib/gitlab/metrics/samplers/ruby_sampler.rb10
-rw-r--r--lib/gitlab/metrics/samplers/unicorn_sampler.rb12
-rw-r--r--lib/gitlab/metrics/sidekiq_metrics_exporter.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/rails_cache.rb4
-rw-r--r--lib/gitlab/metrics/transaction.rb4
-rw-r--r--lib/gitlab/middleware/basic_health_check.rb2
-rw-r--r--lib/gitlab/middleware/go.rb21
-rw-r--r--lib/gitlab/middleware/multipart.rb2
-rw-r--r--lib/gitlab/middleware/rails_queue_duration.rb3
-rw-r--r--lib/gitlab/middleware/read_only/controller.rb20
-rw-r--r--lib/gitlab/pages_client.rb2
-rw-r--r--lib/gitlab/patch/sprockets_base_file_digest_key.rb22
-rw-r--r--lib/gitlab/path_regex.rb3
-rw-r--r--lib/gitlab/project_template.rb26
-rw-r--r--lib/gitlab/prometheus/metric_group.rb10
-rw-r--r--lib/gitlab/quick_actions/command_definition.rb9
-rw-r--r--lib/gitlab/repository_cache.rb4
-rw-r--r--lib/gitlab/request_context.rb2
-rw-r--r--lib/gitlab/seeder.rb13
-rw-r--r--lib/gitlab/sentry.rb8
-rw-r--r--lib/gitlab/shell.rb86
-rw-r--r--lib/gitlab/sidekiq_logging/structured_logger.rb17
-rw-r--r--lib/gitlab/sidekiq_middleware/memory_killer.rb82
-rw-r--r--lib/gitlab/sidekiq_middleware/shutdown.rb135
-rw-r--r--lib/gitlab/sidekiq_signals.rb42
-rw-r--r--lib/gitlab/slash_commands/application_help.rb25
-rw-r--r--lib/gitlab/slash_commands/command.rb3
-rw-r--r--lib/gitlab/slash_commands/presenters/error.rb17
-rw-r--r--lib/gitlab/slash_commands/presenters/run.rb33
-rw-r--r--lib/gitlab/slash_commands/run.rb44
-rw-r--r--lib/gitlab/sql/pattern.rb2
-rw-r--r--lib/gitlab/sql/recursive_cte.rb2
-rw-r--r--lib/gitlab/sql/union.rb2
-rw-r--r--lib/gitlab/task_helpers.rb8
-rw-r--r--lib/gitlab/template/gitlab_ci_yml_template.rb5
-rw-r--r--lib/gitlab/tracing.rb37
-rw-r--r--lib/gitlab/tracing/common.rb69
-rw-r--r--lib/gitlab/tracing/factory.rb61
-rw-r--r--lib/gitlab/tracing/grpc_interceptor.rb54
-rw-r--r--lib/gitlab/tracing/jaeger_factory.rb97
-rw-r--r--lib/gitlab/tracing/rack_middleware.rb46
-rw-r--r--lib/gitlab/tracing/rails/action_view_subscriber.rb75
-rw-r--r--lib/gitlab/tracing/rails/active_record_subscriber.rb49
-rw-r--r--lib/gitlab/tracing/rails/rails_common.rb24
-rw-r--r--lib/gitlab/tracing/sidekiq/client_middleware.rb26
-rw-r--r--lib/gitlab/tracing/sidekiq/server_middleware.rb26
-rw-r--r--lib/gitlab/tracing/sidekiq/sidekiq_common.rb22
-rw-r--r--lib/gitlab/tree_summary.rb2
-rw-r--r--lib/gitlab/url_blocker.rb18
-rw-r--r--lib/gitlab/usage_data.rb27
-rw-r--r--lib/gitlab/user_access.rb4
-rw-r--r--lib/gitlab/utils.rb10
-rw-r--r--lib/gitlab/utils/merge_hash.rb2
-rw-r--r--lib/gitlab/utils/override.rb2
-rw-r--r--lib/gitlab/utils/strong_memoize.rb2
-rw-r--r--lib/gitlab/wiki_file_finder.rb4
-rw-r--r--lib/json_web_token/hmac_token.rb2
-rw-r--r--lib/json_web_token/rsa_token.rb3
-rw-r--r--lib/peek/views/tracing.rb13
-rw-r--r--lib/safe_zip/entry.rb97
-rw-r--r--lib/safe_zip/extract.rb73
-rw-r--r--lib/safe_zip/extract_params.rb36
-rw-r--r--lib/sentry/client.rb140
-rw-r--r--lib/serializers/json.rb34
-rw-r--r--lib/system_check/app/git_user_default_ssh_config_check.rb2
-rw-r--r--lib/system_check/base_check.rb8
-rw-r--r--lib/tasks/dev.rake1
-rw-r--r--lib/tasks/gemojione.rake15
-rw-r--r--lib/tasks/gitlab/assets.rake18
-rw-r--r--lib/tasks/gitlab/backup.rake94
-rw-r--r--lib/tasks/gitlab/bulk_add_permission.rake6
-rw-r--r--lib/tasks/gitlab/db.rake5
-rw-r--r--lib/tasks/gitlab/features.rake24
-rw-r--r--lib/tasks/gitlab/info.rake4
-rw-r--r--lib/tasks/gitlab/setup.rake25
-rw-r--r--lib/tasks/gitlab/storage.rake50
-rw-r--r--lib/tasks/karma.rake2
-rw-r--r--locale/ar_SA/gitlab.po2360
-rw-r--r--locale/bg/gitlab.po2324
-rw-r--r--locale/ca_ES/gitlab.po2688
-rw-r--r--locale/cs_CZ/gitlab.po2336
-rw-r--r--locale/cy_GB/gitlab.po2360
-rw-r--r--locale/da_DK/gitlab.po2312
-rw-r--r--locale/de/gitlab.po2680
-rw-r--r--locale/el_GR/gitlab.po2312
-rw-r--r--locale/eo/gitlab.po2324
-rw-r--r--locale/es/gitlab.po4866
-rw-r--r--locale/et_EE/gitlab.po2312
-rw-r--r--locale/fil_PH/gitlab.po2312
-rw-r--r--locale/fr/gitlab.po2514
-rw-r--r--locale/gitlab.pot1394
-rw-r--r--locale/gl_ES/gitlab.po2312
-rw-r--r--locale/he_IL/gitlab.po2336
-rw-r--r--locale/hi_IN/gitlab.po11801
-rw-r--r--locale/hr_HR/gitlab.po11867
-rw-r--r--locale/hu_HU/gitlab.po2312
-rw-r--r--locale/id_ID/gitlab.po2300
-rw-r--r--locale/it/gitlab.po2388
-rw-r--r--locale/ja/gitlab.po2978
-rw-r--r--locale/ko/gitlab.po3292
-rw-r--r--locale/mn_MN/gitlab.po2312
-rw-r--r--locale/nb_NO/gitlab.po2312
-rw-r--r--locale/nl_NL/gitlab.po2362
-rw-r--r--locale/pa_IN/gitlab.po11801
-rw-r--r--locale/pl_PL/gitlab.po2614
-rw-r--r--locale/pt_BR/gitlab.po3396
-rw-r--r--locale/pt_PT/gitlab.po2312
-rw-r--r--locale/ro_RO/gitlab.po2324
-rw-r--r--locale/ru/gitlab.po3068
-rw-r--r--locale/sk_SK/gitlab.po2336
-rw-r--r--locale/sq_AL/gitlab.po2312
-rw-r--r--locale/sr_CS/gitlab.po2324
-rw-r--r--locale/sr_SP/gitlab.po2324
-rw-r--r--locale/sv_SE/gitlab.po11801
-rw-r--r--locale/sw_KE/gitlab.po11801
-rw-r--r--locale/tr_TR/gitlab.po2316
-rw-r--r--locale/uk/gitlab.po3092
-rw-r--r--locale/zh_CN/gitlab.po2886
-rw-r--r--locale/zh_HK/gitlab.po2312
-rw-r--r--locale/zh_TW/gitlab.po5206
-rw-r--r--package.json108
-rw-r--r--public/-/emojis/1/100.png (renamed from app/assets/images/emoji/100.png)bin793 -> 793 bytes
-rw-r--r--public/-/emojis/1/1234.png (renamed from app/assets/images/emoji/1234.png)bin676 -> 676 bytes
-rw-r--r--public/-/emojis/1/1F627.png (renamed from app/assets/images/emoji/1F627.png)bin821 -> 821 bytes
-rw-r--r--public/-/emojis/1/8ball.png (renamed from app/assets/images/emoji/8ball.png)bin810 -> 810 bytes
-rw-r--r--public/-/emojis/1/a.png (renamed from app/assets/images/emoji/a.png)bin469 -> 469 bytes
-rw-r--r--public/-/emojis/1/ab.png (renamed from app/assets/images/emoji/ab.png)bin505 -> 505 bytes
-rw-r--r--public/-/emojis/1/abc.png (renamed from app/assets/images/emoji/abc.png)bin646 -> 646 bytes
-rw-r--r--public/-/emojis/1/abcd.png (renamed from app/assets/images/emoji/abcd.png)bin670 -> 670 bytes
-rw-r--r--public/-/emojis/1/accept.png (renamed from app/assets/images/emoji/accept.png)bin491 -> 491 bytes
-rw-r--r--public/-/emojis/1/aerial_tramway.png (renamed from app/assets/images/emoji/aerial_tramway.png)bin759 -> 759 bytes
-rw-r--r--public/-/emojis/1/airplane.png (renamed from app/assets/images/emoji/airplane.png)bin1152 -> 1152 bytes
-rw-r--r--public/-/emojis/1/airplane_arriving.png (renamed from app/assets/images/emoji/airplane_arriving.png)bin1101 -> 1101 bytes
-rw-r--r--public/-/emojis/1/airplane_departure.png (renamed from app/assets/images/emoji/airplane_departure.png)bin1111 -> 1111 bytes
-rw-r--r--public/-/emojis/1/airplane_small.png (renamed from app/assets/images/emoji/airplane_small.png)bin1229 -> 1229 bytes
-rw-r--r--public/-/emojis/1/alarm_clock.png (renamed from app/assets/images/emoji/alarm_clock.png)bin1044 -> 1044 bytes
-rw-r--r--public/-/emojis/1/alembic.png (renamed from app/assets/images/emoji/alembic.png)bin953 -> 953 bytes
-rw-r--r--public/-/emojis/1/alien.png (renamed from app/assets/images/emoji/alien.png)bin839 -> 839 bytes
-rw-r--r--public/-/emojis/1/ambulance.png (renamed from app/assets/images/emoji/ambulance.png)bin1238 -> 1238 bytes
-rw-r--r--public/-/emojis/1/amphora.png (renamed from app/assets/images/emoji/amphora.png)bin1044 -> 1044 bytes
-rw-r--r--public/-/emojis/1/anchor.png (renamed from app/assets/images/emoji/anchor.png)bin779 -> 779 bytes
-rw-r--r--public/-/emojis/1/angel.png (renamed from app/assets/images/emoji/angel.png)bin2077 -> 2077 bytes
-rw-r--r--public/-/emojis/1/angel_tone1.png (renamed from app/assets/images/emoji/angel_tone1.png)bin2088 -> 2088 bytes
-rw-r--r--public/-/emojis/1/angel_tone2.png (renamed from app/assets/images/emoji/angel_tone2.png)bin2075 -> 2075 bytes
-rw-r--r--public/-/emojis/1/angel_tone3.png (renamed from app/assets/images/emoji/angel_tone3.png)bin2078 -> 2078 bytes
-rw-r--r--public/-/emojis/1/angel_tone4.png (renamed from app/assets/images/emoji/angel_tone4.png)bin2076 -> 2076 bytes
-rw-r--r--public/-/emojis/1/angel_tone5.png (renamed from app/assets/images/emoji/angel_tone5.png)bin2078 -> 2078 bytes
-rw-r--r--public/-/emojis/1/anger.png (renamed from app/assets/images/emoji/anger.png)bin594 -> 594 bytes
-rw-r--r--public/-/emojis/1/anger_right.png (renamed from app/assets/images/emoji/anger_right.png)bin551 -> 551 bytes
-rw-r--r--public/-/emojis/1/angry.png (renamed from app/assets/images/emoji/angry.png)bin845 -> 845 bytes
-rw-r--r--public/-/emojis/1/ant.png (renamed from app/assets/images/emoji/ant.png)bin1412 -> 1412 bytes
-rw-r--r--public/-/emojis/1/apple.png (renamed from app/assets/images/emoji/apple.png)bin655 -> 655 bytes
-rw-r--r--public/-/emojis/1/aquarius.png (renamed from app/assets/images/emoji/aquarius.png)bin648 -> 648 bytes
-rw-r--r--public/-/emojis/1/aries.png (renamed from app/assets/images/emoji/aries.png)bin711 -> 711 bytes
-rw-r--r--public/-/emojis/1/arrow_backward.png (renamed from app/assets/images/emoji/arrow_backward.png)bin429 -> 429 bytes
-rw-r--r--public/-/emojis/1/arrow_double_down.png (renamed from app/assets/images/emoji/arrow_double_down.png)bin543 -> 543 bytes
-rw-r--r--public/-/emojis/1/arrow_double_up.png (renamed from app/assets/images/emoji/arrow_double_up.png)bin535 -> 535 bytes
-rw-r--r--public/-/emojis/1/arrow_down.png (renamed from app/assets/images/emoji/arrow_down.png)bin512 -> 512 bytes
-rw-r--r--public/-/emojis/1/arrow_down_small.png (renamed from app/assets/images/emoji/arrow_down_small.png)bin455 -> 455 bytes
-rw-r--r--public/-/emojis/1/arrow_forward.png (renamed from app/assets/images/emoji/arrow_forward.png)bin429 -> 429 bytes
-rw-r--r--public/-/emojis/1/arrow_heading_down.png (renamed from app/assets/images/emoji/arrow_heading_down.png)bin563 -> 563 bytes
-rw-r--r--public/-/emojis/1/arrow_heading_up.png (renamed from app/assets/images/emoji/arrow_heading_up.png)bin559 -> 559 bytes
-rw-r--r--public/-/emojis/1/arrow_left.png (renamed from app/assets/images/emoji/arrow_left.png)bin471 -> 471 bytes
-rw-r--r--public/-/emojis/1/arrow_lower_left.png (renamed from app/assets/images/emoji/arrow_lower_left.png)bin520 -> 520 bytes
-rw-r--r--public/-/emojis/1/arrow_lower_right.png (renamed from app/assets/images/emoji/arrow_lower_right.png)bin526 -> 526 bytes
-rw-r--r--public/-/emojis/1/arrow_right.png (renamed from app/assets/images/emoji/arrow_right.png)bin468 -> 468 bytes
-rw-r--r--public/-/emojis/1/arrow_right_hook.png (renamed from app/assets/images/emoji/arrow_right_hook.png)bin644 -> 644 bytes
-rw-r--r--public/-/emojis/1/arrow_up.png (renamed from app/assets/images/emoji/arrow_up.png)bin507 -> 507 bytes
-rw-r--r--public/-/emojis/1/arrow_up_down.png (renamed from app/assets/images/emoji/arrow_up_down.png)bin474 -> 474 bytes
-rw-r--r--public/-/emojis/1/arrow_up_small.png (renamed from app/assets/images/emoji/arrow_up_small.png)bin454 -> 454 bytes
-rw-r--r--public/-/emojis/1/arrow_upper_left.png (renamed from app/assets/images/emoji/arrow_upper_left.png)bin521 -> 521 bytes
-rw-r--r--public/-/emojis/1/arrow_upper_right.png (renamed from app/assets/images/emoji/arrow_upper_right.png)bin524 -> 524 bytes
-rw-r--r--public/-/emojis/1/arrows_clockwise.png (renamed from app/assets/images/emoji/arrows_clockwise.png)bin519 -> 519 bytes
-rw-r--r--public/-/emojis/1/arrows_counterclockwise.png (renamed from app/assets/images/emoji/arrows_counterclockwise.png)bin693 -> 693 bytes
-rw-r--r--public/-/emojis/1/art.png (renamed from app/assets/images/emoji/art.png)bin1455 -> 1455 bytes
-rw-r--r--public/-/emojis/1/articulated_lorry.png (renamed from app/assets/images/emoji/articulated_lorry.png)bin1710 -> 1710 bytes
-rw-r--r--public/-/emojis/1/asterisk.png (renamed from app/assets/images/emoji/asterisk.png)bin627 -> 627 bytes
-rw-r--r--public/-/emojis/1/astonished.png (renamed from app/assets/images/emoji/astonished.png)bin862 -> 862 bytes
-rw-r--r--public/-/emojis/1/athletic_shoe.png (renamed from app/assets/images/emoji/athletic_shoe.png)bin1595 -> 1595 bytes
-rw-r--r--public/-/emojis/1/atm.png (renamed from app/assets/images/emoji/atm.png)bin1397 -> 1397 bytes
-rw-r--r--public/-/emojis/1/atom.png (renamed from app/assets/images/emoji/atom.png)bin912 -> 912 bytes
-rw-r--r--public/-/emojis/1/avocado.png (renamed from app/assets/images/emoji/avocado.png)bin1520 -> 1520 bytes
-rw-r--r--public/-/emojis/1/b.png (renamed from app/assets/images/emoji/b.png)bin391 -> 391 bytes
-rw-r--r--public/-/emojis/1/baby.png (renamed from app/assets/images/emoji/baby.png)bin1380 -> 1380 bytes
-rw-r--r--public/-/emojis/1/baby_bottle.png (renamed from app/assets/images/emoji/baby_bottle.png)bin818 -> 818 bytes
-rw-r--r--public/-/emojis/1/baby_chick.png (renamed from app/assets/images/emoji/baby_chick.png)bin1181 -> 1181 bytes
-rw-r--r--public/-/emojis/1/baby_symbol.png (renamed from app/assets/images/emoji/baby_symbol.png)bin665 -> 665 bytes
-rw-r--r--public/-/emojis/1/baby_tone1.png (renamed from app/assets/images/emoji/baby_tone1.png)bin1392 -> 1392 bytes
-rw-r--r--public/-/emojis/1/baby_tone2.png (renamed from app/assets/images/emoji/baby_tone2.png)bin1392 -> 1392 bytes
-rw-r--r--public/-/emojis/1/baby_tone3.png (renamed from app/assets/images/emoji/baby_tone3.png)bin1403 -> 1403 bytes
-rw-r--r--public/-/emojis/1/baby_tone4.png (renamed from app/assets/images/emoji/baby_tone4.png)bin1413 -> 1413 bytes
-rw-r--r--public/-/emojis/1/baby_tone5.png (renamed from app/assets/images/emoji/baby_tone5.png)bin1405 -> 1405 bytes
-rw-r--r--public/-/emojis/1/back.png (renamed from app/assets/images/emoji/back.png)bin562 -> 562 bytes
-rw-r--r--public/-/emojis/1/bacon.png (renamed from app/assets/images/emoji/bacon.png)bin2148 -> 2148 bytes
-rw-r--r--public/-/emojis/1/badminton.png (renamed from app/assets/images/emoji/badminton.png)bin1253 -> 1253 bytes
-rw-r--r--public/-/emojis/1/baggage_claim.png (renamed from app/assets/images/emoji/baggage_claim.png)bin490 -> 490 bytes
-rw-r--r--public/-/emojis/1/balloon.png (renamed from app/assets/images/emoji/balloon.png)bin501 -> 501 bytes
-rw-r--r--public/-/emojis/1/ballot_box.png (renamed from app/assets/images/emoji/ballot_box.png)bin1355 -> 1355 bytes
-rw-r--r--public/-/emojis/1/ballot_box_with_check.png (renamed from app/assets/images/emoji/ballot_box_with_check.png)bin639 -> 639 bytes
-rw-r--r--public/-/emojis/1/bamboo.png (renamed from app/assets/images/emoji/bamboo.png)bin1946 -> 1946 bytes
-rw-r--r--public/-/emojis/1/banana.png (renamed from app/assets/images/emoji/banana.png)bin1157 -> 1157 bytes
-rw-r--r--public/-/emojis/1/bangbang.png (renamed from app/assets/images/emoji/bangbang.png)bin390 -> 390 bytes
-rw-r--r--public/-/emojis/1/bank.png (renamed from app/assets/images/emoji/bank.png)bin1358 -> 1358 bytes
-rw-r--r--public/-/emojis/1/bar_chart.png (renamed from app/assets/images/emoji/bar_chart.png)bin408 -> 408 bytes
-rw-r--r--public/-/emojis/1/barber.png (renamed from app/assets/images/emoji/barber.png)bin820 -> 820 bytes
-rw-r--r--public/-/emojis/1/baseball.png (renamed from app/assets/images/emoji/baseball.png)bin1185 -> 1185 bytes
-rw-r--r--public/-/emojis/1/basketball.png (renamed from app/assets/images/emoji/basketball.png)bin1546 -> 1546 bytes
-rw-r--r--public/-/emojis/1/basketball_player.png (renamed from app/assets/images/emoji/basketball_player.png)bin1491 -> 1491 bytes
-rw-r--r--public/-/emojis/1/basketball_player_tone1.png (renamed from app/assets/images/emoji/basketball_player_tone1.png)bin1492 -> 1492 bytes
-rw-r--r--public/-/emojis/1/basketball_player_tone2.png (renamed from app/assets/images/emoji/basketball_player_tone2.png)bin1493 -> 1493 bytes
-rw-r--r--public/-/emojis/1/basketball_player_tone3.png (renamed from app/assets/images/emoji/basketball_player_tone3.png)bin1492 -> 1492 bytes
-rw-r--r--public/-/emojis/1/basketball_player_tone4.png (renamed from app/assets/images/emoji/basketball_player_tone4.png)bin1491 -> 1491 bytes
-rw-r--r--public/-/emojis/1/basketball_player_tone5.png (renamed from app/assets/images/emoji/basketball_player_tone5.png)bin1474 -> 1474 bytes
-rw-r--r--public/-/emojis/1/bat.png (renamed from app/assets/images/emoji/bat.png)bin1190 -> 1190 bytes
-rw-r--r--public/-/emojis/1/bath.png (renamed from app/assets/images/emoji/bath.png)bin1238 -> 1238 bytes
-rw-r--r--public/-/emojis/1/bath_tone1.png (renamed from app/assets/images/emoji/bath_tone1.png)bin1235 -> 1235 bytes
-rw-r--r--public/-/emojis/1/bath_tone2.png (renamed from app/assets/images/emoji/bath_tone2.png)bin1231 -> 1231 bytes
-rw-r--r--public/-/emojis/1/bath_tone3.png (renamed from app/assets/images/emoji/bath_tone3.png)bin1236 -> 1236 bytes
-rw-r--r--public/-/emojis/1/bath_tone4.png (renamed from app/assets/images/emoji/bath_tone4.png)bin1252 -> 1252 bytes
-rw-r--r--public/-/emojis/1/bath_tone5.png (renamed from app/assets/images/emoji/bath_tone5.png)bin1239 -> 1239 bytes
-rw-r--r--public/-/emojis/1/bathtub.png (renamed from app/assets/images/emoji/bathtub.png)bin767 -> 767 bytes
-rw-r--r--public/-/emojis/1/battery.png (renamed from app/assets/images/emoji/battery.png)bin228 -> 228 bytes
-rw-r--r--public/-/emojis/1/beach.png (renamed from app/assets/images/emoji/beach.png)bin942 -> 942 bytes
-rw-r--r--public/-/emojis/1/beach_umbrella.png (renamed from app/assets/images/emoji/beach_umbrella.png)bin1486 -> 1486 bytes
-rw-r--r--public/-/emojis/1/bear.png (renamed from app/assets/images/emoji/bear.png)bin1023 -> 1023 bytes
-rw-r--r--public/-/emojis/1/bed.png (renamed from app/assets/images/emoji/bed.png)bin1572 -> 1572 bytes
-rw-r--r--public/-/emojis/1/bee.png (renamed from app/assets/images/emoji/bee.png)bin1378 -> 1378 bytes
-rw-r--r--public/-/emojis/1/beer.png (renamed from app/assets/images/emoji/beer.png)bin1338 -> 1338 bytes
-rw-r--r--public/-/emojis/1/beers.png (renamed from app/assets/images/emoji/beers.png)bin2100 -> 2100 bytes
-rw-r--r--public/-/emojis/1/beetle.png (renamed from app/assets/images/emoji/beetle.png)bin1288 -> 1288 bytes
-rw-r--r--public/-/emojis/1/beginner.png (renamed from app/assets/images/emoji/beginner.png)bin545 -> 545 bytes
-rw-r--r--public/-/emojis/1/bell.png (renamed from app/assets/images/emoji/bell.png)bin1496 -> 1496 bytes
-rw-r--r--public/-/emojis/1/bellhop.png (renamed from app/assets/images/emoji/bellhop.png)bin891 -> 891 bytes
-rw-r--r--public/-/emojis/1/bento.png (renamed from app/assets/images/emoji/bento.png)bin1127 -> 1127 bytes
-rw-r--r--public/-/emojis/1/bicyclist.png (renamed from app/assets/images/emoji/bicyclist.png)bin1911 -> 1911 bytes
-rw-r--r--public/-/emojis/1/bicyclist_tone1.png (renamed from app/assets/images/emoji/bicyclist_tone1.png)bin1860 -> 1860 bytes
-rw-r--r--public/-/emojis/1/bicyclist_tone2.png (renamed from app/assets/images/emoji/bicyclist_tone2.png)bin1866 -> 1866 bytes
-rw-r--r--public/-/emojis/1/bicyclist_tone3.png (renamed from app/assets/images/emoji/bicyclist_tone3.png)bin1851 -> 1851 bytes
-rw-r--r--public/-/emojis/1/bicyclist_tone4.png (renamed from app/assets/images/emoji/bicyclist_tone4.png)bin1852 -> 1852 bytes
-rw-r--r--public/-/emojis/1/bicyclist_tone5.png (renamed from app/assets/images/emoji/bicyclist_tone5.png)bin1840 -> 1840 bytes
-rw-r--r--public/-/emojis/1/bike.png (renamed from app/assets/images/emoji/bike.png)bin1505 -> 1505 bytes
-rw-r--r--public/-/emojis/1/bikini.png (renamed from app/assets/images/emoji/bikini.png)bin613 -> 613 bytes
-rw-r--r--public/-/emojis/1/biohazard.png (renamed from app/assets/images/emoji/biohazard.png)bin794 -> 794 bytes
-rw-r--r--public/-/emojis/1/bird.png (renamed from app/assets/images/emoji/bird.png)bin1068 -> 1068 bytes
-rw-r--r--public/-/emojis/1/birthday.png (renamed from app/assets/images/emoji/birthday.png)bin2219 -> 2219 bytes
-rw-r--r--public/-/emojis/1/black_circle.png (renamed from app/assets/images/emoji/black_circle.png)bin374 -> 374 bytes
-rw-r--r--public/-/emojis/1/black_heart.png (renamed from app/assets/images/emoji/black_heart.png)bin435 -> 435 bytes
-rw-r--r--public/-/emojis/1/black_joker.png (renamed from app/assets/images/emoji/black_joker.png)bin1091 -> 1091 bytes
-rw-r--r--public/-/emojis/1/black_large_square.png (renamed from app/assets/images/emoji/black_large_square.png)bin110 -> 110 bytes
-rw-r--r--public/-/emojis/1/black_medium_small_square.png (renamed from app/assets/images/emoji/black_medium_small_square.png)bin110 -> 110 bytes
-rw-r--r--public/-/emojis/1/black_medium_square.png (renamed from app/assets/images/emoji/black_medium_square.png)bin108 -> 108 bytes
-rw-r--r--public/-/emojis/1/black_nib.png (renamed from app/assets/images/emoji/black_nib.png)bin620 -> 620 bytes
-rw-r--r--public/-/emojis/1/black_small_square.png (renamed from app/assets/images/emoji/black_small_square.png)bin108 -> 108 bytes
-rw-r--r--public/-/emojis/1/black_square_button.png (renamed from app/assets/images/emoji/black_square_button.png)bin122 -> 122 bytes
-rw-r--r--public/-/emojis/1/blossom.png (renamed from app/assets/images/emoji/blossom.png)bin867 -> 867 bytes
-rw-r--r--public/-/emojis/1/blowfish.png (renamed from app/assets/images/emoji/blowfish.png)bin1620 -> 1620 bytes
-rw-r--r--public/-/emojis/1/blue_book.png (renamed from app/assets/images/emoji/blue_book.png)bin1347 -> 1347 bytes
-rw-r--r--public/-/emojis/1/blue_car.png (renamed from app/assets/images/emoji/blue_car.png)bin1275 -> 1275 bytes
-rw-r--r--public/-/emojis/1/blue_heart.png (renamed from app/assets/images/emoji/blue_heart.png)bin435 -> 435 bytes
-rw-r--r--public/-/emojis/1/blush.png (renamed from app/assets/images/emoji/blush.png)bin812 -> 812 bytes
-rw-r--r--public/-/emojis/1/boar.png (renamed from app/assets/images/emoji/boar.png)bin1366 -> 1366 bytes
-rw-r--r--public/-/emojis/1/bomb.png (renamed from app/assets/images/emoji/bomb.png)bin702 -> 702 bytes
-rw-r--r--public/-/emojis/1/book.png (renamed from app/assets/images/emoji/book.png)bin1716 -> 1716 bytes
-rw-r--r--public/-/emojis/1/bookmark.png (renamed from app/assets/images/emoji/bookmark.png)bin747 -> 747 bytes
-rw-r--r--public/-/emojis/1/bookmark_tabs.png (renamed from app/assets/images/emoji/bookmark_tabs.png)bin1395 -> 1395 bytes
-rw-r--r--public/-/emojis/1/books.png (renamed from app/assets/images/emoji/books.png)bin2474 -> 2474 bytes
-rw-r--r--public/-/emojis/1/boom.png (renamed from app/assets/images/emoji/boom.png)bin1110 -> 1110 bytes
-rw-r--r--public/-/emojis/1/boot.png (renamed from app/assets/images/emoji/boot.png)bin662 -> 662 bytes
-rw-r--r--public/-/emojis/1/bouquet.png (renamed from app/assets/images/emoji/bouquet.png)bin1662 -> 1662 bytes
-rw-r--r--public/-/emojis/1/bow.png (renamed from app/assets/images/emoji/bow.png)bin1394 -> 1394 bytes
-rw-r--r--public/-/emojis/1/bow_and_arrow.png (renamed from app/assets/images/emoji/bow_and_arrow.png)bin1402 -> 1402 bytes
-rw-r--r--public/-/emojis/1/bow_tone1.png (renamed from app/assets/images/emoji/bow_tone1.png)bin1394 -> 1394 bytes
-rw-r--r--public/-/emojis/1/bow_tone2.png (renamed from app/assets/images/emoji/bow_tone2.png)bin1394 -> 1394 bytes
-rw-r--r--public/-/emojis/1/bow_tone3.png (renamed from app/assets/images/emoji/bow_tone3.png)bin1394 -> 1394 bytes
-rw-r--r--public/-/emojis/1/bow_tone4.png (renamed from app/assets/images/emoji/bow_tone4.png)bin1394 -> 1394 bytes
-rw-r--r--public/-/emojis/1/bow_tone5.png (renamed from app/assets/images/emoji/bow_tone5.png)bin1394 -> 1394 bytes
-rw-r--r--public/-/emojis/1/bowling.png (renamed from app/assets/images/emoji/bowling.png)bin1426 -> 1426 bytes
-rw-r--r--public/-/emojis/1/boxing_glove.png (renamed from app/assets/images/emoji/boxing_glove.png)bin1575 -> 1575 bytes
-rw-r--r--public/-/emojis/1/boy.png (renamed from app/assets/images/emoji/boy.png)bin881 -> 881 bytes
-rw-r--r--public/-/emojis/1/boy_tone1.png (renamed from app/assets/images/emoji/boy_tone1.png)bin876 -> 876 bytes
-rw-r--r--public/-/emojis/1/boy_tone2.png (renamed from app/assets/images/emoji/boy_tone2.png)bin876 -> 876 bytes
-rw-r--r--public/-/emojis/1/boy_tone3.png (renamed from app/assets/images/emoji/boy_tone3.png)bin876 -> 876 bytes
-rw-r--r--public/-/emojis/1/boy_tone4.png (renamed from app/assets/images/emoji/boy_tone4.png)bin870 -> 870 bytes
-rw-r--r--public/-/emojis/1/boy_tone5.png (renamed from app/assets/images/emoji/boy_tone5.png)bin873 -> 873 bytes
-rw-r--r--public/-/emojis/1/bread.png (renamed from app/assets/images/emoji/bread.png)bin1419 -> 1419 bytes
-rw-r--r--public/-/emojis/1/bride_with_veil.png (renamed from app/assets/images/emoji/bride_with_veil.png)bin2452 -> 2452 bytes
-rw-r--r--public/-/emojis/1/bride_with_veil_tone1.png (renamed from app/assets/images/emoji/bride_with_veil_tone1.png)bin2464 -> 2464 bytes
-rw-r--r--public/-/emojis/1/bride_with_veil_tone2.png (renamed from app/assets/images/emoji/bride_with_veil_tone2.png)bin2457 -> 2457 bytes
-rw-r--r--public/-/emojis/1/bride_with_veil_tone3.png (renamed from app/assets/images/emoji/bride_with_veil_tone3.png)bin2463 -> 2463 bytes
-rw-r--r--public/-/emojis/1/bride_with_veil_tone4.png (renamed from app/assets/images/emoji/bride_with_veil_tone4.png)bin2463 -> 2463 bytes
-rw-r--r--public/-/emojis/1/bride_with_veil_tone5.png (renamed from app/assets/images/emoji/bride_with_veil_tone5.png)bin2462 -> 2462 bytes
-rw-r--r--public/-/emojis/1/bridge_at_night.png (renamed from app/assets/images/emoji/bridge_at_night.png)bin637 -> 637 bytes
-rw-r--r--public/-/emojis/1/briefcase.png (renamed from app/assets/images/emoji/briefcase.png)bin1275 -> 1275 bytes
-rw-r--r--public/-/emojis/1/broken_heart.png (renamed from app/assets/images/emoji/broken_heart.png)bin556 -> 556 bytes
-rw-r--r--public/-/emojis/1/bug.png (renamed from app/assets/images/emoji/bug.png)bin1599 -> 1599 bytes
-rw-r--r--public/-/emojis/1/bulb.png (renamed from app/assets/images/emoji/bulb.png)bin805 -> 805 bytes
-rw-r--r--public/-/emojis/1/bullettrain_front.png (renamed from app/assets/images/emoji/bullettrain_front.png)bin1450 -> 1450 bytes
-rw-r--r--public/-/emojis/1/bullettrain_side.png (renamed from app/assets/images/emoji/bullettrain_side.png)bin1538 -> 1538 bytes
-rw-r--r--public/-/emojis/1/burrito.png (renamed from app/assets/images/emoji/burrito.png)bin2938 -> 2938 bytes
-rw-r--r--public/-/emojis/1/bus.png (renamed from app/assets/images/emoji/bus.png)bin1086 -> 1086 bytes
-rw-r--r--public/-/emojis/1/busstop.png (renamed from app/assets/images/emoji/busstop.png)bin626 -> 626 bytes
-rw-r--r--public/-/emojis/1/bust_in_silhouette.png (renamed from app/assets/images/emoji/bust_in_silhouette.png)bin426 -> 426 bytes
-rw-r--r--public/-/emojis/1/busts_in_silhouette.png (renamed from app/assets/images/emoji/busts_in_silhouette.png)bin526 -> 526 bytes
-rw-r--r--public/-/emojis/1/butterfly.png (renamed from app/assets/images/emoji/butterfly.png)bin1981 -> 1981 bytes
-rw-r--r--public/-/emojis/1/cactus.png (renamed from app/assets/images/emoji/cactus.png)bin628 -> 628 bytes
-rw-r--r--public/-/emojis/1/cake.png (renamed from app/assets/images/emoji/cake.png)bin2266 -> 2266 bytes
-rw-r--r--public/-/emojis/1/calendar.png (renamed from app/assets/images/emoji/calendar.png)bin2077 -> 2077 bytes
-rw-r--r--public/-/emojis/1/calendar_spiral.png (renamed from app/assets/images/emoji/calendar_spiral.png)bin1491 -> 1491 bytes
-rw-r--r--public/-/emojis/1/call_me.png (renamed from app/assets/images/emoji/call_me.png)bin894 -> 894 bytes
-rw-r--r--public/-/emojis/1/call_me_tone1.png (renamed from app/assets/images/emoji/call_me_tone1.png)bin893 -> 893 bytes
-rw-r--r--public/-/emojis/1/call_me_tone2.png (renamed from app/assets/images/emoji/call_me_tone2.png)bin891 -> 891 bytes
-rw-r--r--public/-/emojis/1/call_me_tone3.png (renamed from app/assets/images/emoji/call_me_tone3.png)bin891 -> 891 bytes
-rw-r--r--public/-/emojis/1/call_me_tone4.png (renamed from app/assets/images/emoji/call_me_tone4.png)bin891 -> 891 bytes
-rw-r--r--public/-/emojis/1/call_me_tone5.png (renamed from app/assets/images/emoji/call_me_tone5.png)bin893 -> 893 bytes
-rw-r--r--public/-/emojis/1/calling.png (renamed from app/assets/images/emoji/calling.png)bin815 -> 815 bytes
-rw-r--r--public/-/emojis/1/camel.png (renamed from app/assets/images/emoji/camel.png)bin1190 -> 1190 bytes
-rw-r--r--public/-/emojis/1/camera.png (renamed from app/assets/images/emoji/camera.png)bin1783 -> 1783 bytes
-rw-r--r--public/-/emojis/1/camera_with_flash.png (renamed from app/assets/images/emoji/camera_with_flash.png)bin2097 -> 2097 bytes
-rw-r--r--public/-/emojis/1/camping.png (renamed from app/assets/images/emoji/camping.png)bin1513 -> 1513 bytes
-rw-r--r--public/-/emojis/1/cancer.png (renamed from app/assets/images/emoji/cancer.png)bin729 -> 729 bytes
-rw-r--r--public/-/emojis/1/candle.png (renamed from app/assets/images/emoji/candle.png)bin1250 -> 1250 bytes
-rw-r--r--public/-/emojis/1/candy.png (renamed from app/assets/images/emoji/candy.png)bin1054 -> 1054 bytes
-rw-r--r--public/-/emojis/1/canoe.png (renamed from app/assets/images/emoji/canoe.png)bin1244 -> 1244 bytes
-rw-r--r--public/-/emojis/1/capital_abcd.png (renamed from app/assets/images/emoji/capital_abcd.png)bin805 -> 805 bytes
-rw-r--r--public/-/emojis/1/capricorn.png (renamed from app/assets/images/emoji/capricorn.png)bin688 -> 688 bytes
-rw-r--r--public/-/emojis/1/card_box.png (renamed from app/assets/images/emoji/card_box.png)bin1523 -> 1523 bytes
-rw-r--r--public/-/emojis/1/card_index.png (renamed from app/assets/images/emoji/card_index.png)bin1929 -> 1929 bytes
-rw-r--r--public/-/emojis/1/carousel_horse.png (renamed from app/assets/images/emoji/carousel_horse.png)bin1739 -> 1739 bytes
-rw-r--r--public/-/emojis/1/carrot.png (renamed from app/assets/images/emoji/carrot.png)bin1236 -> 1236 bytes
-rw-r--r--public/-/emojis/1/cartwheel.png (renamed from app/assets/images/emoji/cartwheel.png)bin1233 -> 1233 bytes
-rw-r--r--public/-/emojis/1/cartwheel_tone1.png (renamed from app/assets/images/emoji/cartwheel_tone1.png)bin1234 -> 1234 bytes
-rw-r--r--public/-/emojis/1/cartwheel_tone2.png (renamed from app/assets/images/emoji/cartwheel_tone2.png)bin1235 -> 1235 bytes
-rw-r--r--public/-/emojis/1/cartwheel_tone3.png (renamed from app/assets/images/emoji/cartwheel_tone3.png)bin1229 -> 1229 bytes
-rw-r--r--public/-/emojis/1/cartwheel_tone4.png (renamed from app/assets/images/emoji/cartwheel_tone4.png)bin1227 -> 1227 bytes
-rw-r--r--public/-/emojis/1/cartwheel_tone5.png (renamed from app/assets/images/emoji/cartwheel_tone5.png)bin1214 -> 1214 bytes
-rw-r--r--public/-/emojis/1/cat.png (renamed from app/assets/images/emoji/cat.png)bin1354 -> 1354 bytes
-rw-r--r--public/-/emojis/1/cat2.png (renamed from app/assets/images/emoji/cat2.png)bin1781 -> 1781 bytes
-rw-r--r--public/-/emojis/1/cd.png (renamed from app/assets/images/emoji/cd.png)bin908 -> 908 bytes
-rw-r--r--public/-/emojis/1/chains.png (renamed from app/assets/images/emoji/chains.png)bin708 -> 708 bytes
-rw-r--r--public/-/emojis/1/champagne.png (renamed from app/assets/images/emoji/champagne.png)bin1205 -> 1205 bytes
-rw-r--r--public/-/emojis/1/champagne_glass.png (renamed from app/assets/images/emoji/champagne_glass.png)bin1984 -> 1984 bytes
-rw-r--r--public/-/emojis/1/chart.png (renamed from app/assets/images/emoji/chart.png)bin724 -> 724 bytes
-rw-r--r--public/-/emojis/1/chart_with_downwards_trend.png (renamed from app/assets/images/emoji/chart_with_downwards_trend.png)bin709 -> 709 bytes
-rw-r--r--public/-/emojis/1/chart_with_upwards_trend.png (renamed from app/assets/images/emoji/chart_with_upwards_trend.png)bin688 -> 688 bytes
-rw-r--r--public/-/emojis/1/checkered_flag.png (renamed from app/assets/images/emoji/checkered_flag.png)bin787 -> 787 bytes
-rw-r--r--public/-/emojis/1/cheese.png (renamed from app/assets/images/emoji/cheese.png)bin1697 -> 1697 bytes
-rw-r--r--public/-/emojis/1/cherries.png (renamed from app/assets/images/emoji/cherries.png)bin1211 -> 1211 bytes
-rw-r--r--public/-/emojis/1/cherry_blossom.png (renamed from app/assets/images/emoji/cherry_blossom.png)bin1129 -> 1129 bytes
-rw-r--r--public/-/emojis/1/chestnut.png (renamed from app/assets/images/emoji/chestnut.png)bin1337 -> 1337 bytes
-rw-r--r--public/-/emojis/1/chicken.png (renamed from app/assets/images/emoji/chicken.png)bin1267 -> 1267 bytes
-rw-r--r--public/-/emojis/1/children_crossing.png (renamed from app/assets/images/emoji/children_crossing.png)bin778 -> 778 bytes
-rw-r--r--public/-/emojis/1/chipmunk.png (renamed from app/assets/images/emoji/chipmunk.png)bin1454 -> 1454 bytes
-rw-r--r--public/-/emojis/1/chocolate_bar.png (renamed from app/assets/images/emoji/chocolate_bar.png)bin771 -> 771 bytes
-rw-r--r--public/-/emojis/1/christmas_tree.png (renamed from app/assets/images/emoji/christmas_tree.png)bin1542 -> 1542 bytes
-rw-r--r--public/-/emojis/1/church.png (renamed from app/assets/images/emoji/church.png)bin1298 -> 1298 bytes
-rw-r--r--public/-/emojis/1/cinema.png (renamed from app/assets/images/emoji/cinema.png)bin585 -> 585 bytes
-rw-r--r--public/-/emojis/1/circus_tent.png (renamed from app/assets/images/emoji/circus_tent.png)bin1369 -> 1369 bytes
-rw-r--r--public/-/emojis/1/city_dusk.png (renamed from app/assets/images/emoji/city_dusk.png)bin431 -> 431 bytes
-rw-r--r--public/-/emojis/1/city_sunset.png (renamed from app/assets/images/emoji/city_sunset.png)bin997 -> 997 bytes
-rw-r--r--public/-/emojis/1/cityscape.png (renamed from app/assets/images/emoji/cityscape.png)bin599 -> 599 bytes
-rw-r--r--public/-/emojis/1/cl.png (renamed from app/assets/images/emoji/cl.png)bin393 -> 393 bytes
-rw-r--r--public/-/emojis/1/clap.png (renamed from app/assets/images/emoji/clap.png)bin1456 -> 1456 bytes
-rw-r--r--public/-/emojis/1/clap_tone1.png (renamed from app/assets/images/emoji/clap_tone1.png)bin1458 -> 1458 bytes
-rw-r--r--public/-/emojis/1/clap_tone2.png (renamed from app/assets/images/emoji/clap_tone2.png)bin1458 -> 1458 bytes
-rw-r--r--public/-/emojis/1/clap_tone3.png (renamed from app/assets/images/emoji/clap_tone3.png)bin1458 -> 1458 bytes
-rw-r--r--public/-/emojis/1/clap_tone4.png (renamed from app/assets/images/emoji/clap_tone4.png)bin1458 -> 1458 bytes
-rw-r--r--public/-/emojis/1/clap_tone5.png (renamed from app/assets/images/emoji/clap_tone5.png)bin1444 -> 1444 bytes
-rw-r--r--public/-/emojis/1/clapper.png (renamed from app/assets/images/emoji/clapper.png)bin1535 -> 1535 bytes
-rw-r--r--public/-/emojis/1/classical_building.png (renamed from app/assets/images/emoji/classical_building.png)bin1006 -> 1006 bytes
-rw-r--r--public/-/emojis/1/clipboard.png (renamed from app/assets/images/emoji/clipboard.png)bin1345 -> 1345 bytes
-rw-r--r--public/-/emojis/1/clock.png (renamed from app/assets/images/emoji/clock.png)bin592 -> 592 bytes
-rw-r--r--public/-/emojis/1/clock1.png (renamed from app/assets/images/emoji/clock1.png)bin586 -> 586 bytes
-rw-r--r--public/-/emojis/1/clock10.png (renamed from app/assets/images/emoji/clock10.png)bin593 -> 593 bytes
-rw-r--r--public/-/emojis/1/clock1030.png (renamed from app/assets/images/emoji/clock1030.png)bin530 -> 530 bytes
-rw-r--r--public/-/emojis/1/clock11.png (renamed from app/assets/images/emoji/clock11.png)bin590 -> 590 bytes
-rw-r--r--public/-/emojis/1/clock1130.png (renamed from app/assets/images/emoji/clock1130.png)bin583 -> 583 bytes
-rw-r--r--public/-/emojis/1/clock12.png (renamed from app/assets/images/emoji/clock12.png)bin480 -> 480 bytes
-rw-r--r--public/-/emojis/1/clock1230.png (renamed from app/assets/images/emoji/clock1230.png)bin579 -> 579 bytes
-rw-r--r--public/-/emojis/1/clock130.png (renamed from app/assets/images/emoji/clock130.png)bin526 -> 526 bytes
-rw-r--r--public/-/emojis/1/clock2.png (renamed from app/assets/images/emoji/clock2.png)bin591 -> 591 bytes
-rw-r--r--public/-/emojis/1/clock230.png (renamed from app/assets/images/emoji/clock230.png)bin576 -> 576 bytes
-rw-r--r--public/-/emojis/1/clock3.png (renamed from app/assets/images/emoji/clock3.png)bin482 -> 482 bytes
-rw-r--r--public/-/emojis/1/clock330.png (renamed from app/assets/images/emoji/clock330.png)bin568 -> 568 bytes
-rw-r--r--public/-/emojis/1/clock4.png (renamed from app/assets/images/emoji/clock4.png)bin592 -> 592 bytes
-rw-r--r--public/-/emojis/1/clock430.png (renamed from app/assets/images/emoji/clock430.png)bin531 -> 531 bytes
-rw-r--r--public/-/emojis/1/clock5.png (renamed from app/assets/images/emoji/clock5.png)bin585 -> 585 bytes
-rw-r--r--public/-/emojis/1/clock530.png (renamed from app/assets/images/emoji/clock530.png)bin552 -> 552 bytes
-rw-r--r--public/-/emojis/1/clock6.png (renamed from app/assets/images/emoji/clock6.png)bin466 -> 466 bytes
-rw-r--r--public/-/emojis/1/clock630.png (renamed from app/assets/images/emoji/clock630.png)bin536 -> 536 bytes
-rw-r--r--public/-/emojis/1/clock7.png (renamed from app/assets/images/emoji/clock7.png)bin581 -> 581 bytes
-rw-r--r--public/-/emojis/1/clock730.png (renamed from app/assets/images/emoji/clock730.png)bin531 -> 531 bytes
-rw-r--r--public/-/emojis/1/clock8.png (renamed from app/assets/images/emoji/clock8.png)bin590 -> 590 bytes
-rw-r--r--public/-/emojis/1/clock830.png (renamed from app/assets/images/emoji/clock830.png)bin570 -> 570 bytes
-rw-r--r--public/-/emojis/1/clock9.png (renamed from app/assets/images/emoji/clock9.png)bin484 -> 484 bytes
-rw-r--r--public/-/emojis/1/clock930.png (renamed from app/assets/images/emoji/clock930.png)bin576 -> 576 bytes
-rw-r--r--public/-/emojis/1/closed_book.png (renamed from app/assets/images/emoji/closed_book.png)bin1359 -> 1359 bytes
-rw-r--r--public/-/emojis/1/closed_lock_with_key.png (renamed from app/assets/images/emoji/closed_lock_with_key.png)bin1250 -> 1250 bytes
-rw-r--r--public/-/emojis/1/closed_umbrella.png (renamed from app/assets/images/emoji/closed_umbrella.png)bin1002 -> 1002 bytes
-rw-r--r--public/-/emojis/1/cloud.png (renamed from app/assets/images/emoji/cloud.png)bin626 -> 626 bytes
-rw-r--r--public/-/emojis/1/cloud_lightning.png (renamed from app/assets/images/emoji/cloud_lightning.png)bin767 -> 767 bytes
-rw-r--r--public/-/emojis/1/cloud_rain.png (renamed from app/assets/images/emoji/cloud_rain.png)bin876 -> 876 bytes
-rw-r--r--public/-/emojis/1/cloud_snow.png (renamed from app/assets/images/emoji/cloud_snow.png)bin823 -> 823 bytes
-rw-r--r--public/-/emojis/1/cloud_tornado.png (renamed from app/assets/images/emoji/cloud_tornado.png)bin1519 -> 1519 bytes
-rw-r--r--public/-/emojis/1/clown.png (renamed from app/assets/images/emoji/clown.png)bin1818 -> 1818 bytes
-rw-r--r--public/-/emojis/1/clubs.png (renamed from app/assets/images/emoji/clubs.png)bin458 -> 458 bytes
-rw-r--r--public/-/emojis/1/cocktail.png (renamed from app/assets/images/emoji/cocktail.png)bin1027 -> 1027 bytes
-rw-r--r--public/-/emojis/1/coffee.png (renamed from app/assets/images/emoji/coffee.png)bin1679 -> 1679 bytes
-rw-r--r--public/-/emojis/1/coffin.png (renamed from app/assets/images/emoji/coffin.png)bin2195 -> 2195 bytes
-rw-r--r--public/-/emojis/1/cold_sweat.png (renamed from app/assets/images/emoji/cold_sweat.png)bin971 -> 971 bytes
-rw-r--r--public/-/emojis/1/comet.png (renamed from app/assets/images/emoji/comet.png)bin1819 -> 1819 bytes
-rw-r--r--public/-/emojis/1/compression.png (renamed from app/assets/images/emoji/compression.png)bin1612 -> 1612 bytes
-rw-r--r--public/-/emojis/1/computer.png (renamed from app/assets/images/emoji/computer.png)bin369 -> 369 bytes
-rw-r--r--public/-/emojis/1/confetti_ball.png (renamed from app/assets/images/emoji/confetti_ball.png)bin1703 -> 1703 bytes
-rw-r--r--public/-/emojis/1/confounded.png (renamed from app/assets/images/emoji/confounded.png)bin844 -> 844 bytes
-rw-r--r--public/-/emojis/1/confused.png (renamed from app/assets/images/emoji/confused.png)bin647 -> 647 bytes
-rw-r--r--public/-/emojis/1/congratulations.png (renamed from app/assets/images/emoji/congratulations.png)bin729 -> 729 bytes
-rw-r--r--public/-/emojis/1/construction.png (renamed from app/assets/images/emoji/construction.png)bin1083 -> 1083 bytes
-rw-r--r--public/-/emojis/1/construction_site.png (renamed from app/assets/images/emoji/construction_site.png)bin668 -> 668 bytes
-rw-r--r--public/-/emojis/1/construction_worker.png (renamed from app/assets/images/emoji/construction_worker.png)bin1126 -> 1126 bytes
-rw-r--r--public/-/emojis/1/construction_worker_tone1.png (renamed from app/assets/images/emoji/construction_worker_tone1.png)bin1102 -> 1102 bytes
-rw-r--r--public/-/emojis/1/construction_worker_tone2.png (renamed from app/assets/images/emoji/construction_worker_tone2.png)bin1102 -> 1102 bytes
-rw-r--r--public/-/emojis/1/construction_worker_tone3.png (renamed from app/assets/images/emoji/construction_worker_tone3.png)bin1102 -> 1102 bytes
-rw-r--r--public/-/emojis/1/construction_worker_tone4.png (renamed from app/assets/images/emoji/construction_worker_tone4.png)bin1095 -> 1095 bytes
-rw-r--r--public/-/emojis/1/construction_worker_tone5.png (renamed from app/assets/images/emoji/construction_worker_tone5.png)bin1119 -> 1119 bytes
-rw-r--r--public/-/emojis/1/control_knobs.png (renamed from app/assets/images/emoji/control_knobs.png)bin1104 -> 1104 bytes
-rw-r--r--public/-/emojis/1/convenience_store.png (renamed from app/assets/images/emoji/convenience_store.png)bin528 -> 528 bytes
-rw-r--r--public/-/emojis/1/cookie.png (renamed from app/assets/images/emoji/cookie.png)bin1351 -> 1351 bytes
-rw-r--r--public/-/emojis/1/cooking.png (renamed from app/assets/images/emoji/cooking.png)bin764 -> 764 bytes
-rw-r--r--public/-/emojis/1/cool.png (renamed from app/assets/images/emoji/cool.png)bin396 -> 396 bytes
-rw-r--r--public/-/emojis/1/cop.png (renamed from app/assets/images/emoji/cop.png)bin1440 -> 1440 bytes
-rw-r--r--public/-/emojis/1/cop_tone1.png (renamed from app/assets/images/emoji/cop_tone1.png)bin1421 -> 1421 bytes
-rw-r--r--public/-/emojis/1/cop_tone2.png (renamed from app/assets/images/emoji/cop_tone2.png)bin1424 -> 1424 bytes
-rw-r--r--public/-/emojis/1/cop_tone3.png (renamed from app/assets/images/emoji/cop_tone3.png)bin1419 -> 1419 bytes
-rw-r--r--public/-/emojis/1/cop_tone4.png (renamed from app/assets/images/emoji/cop_tone4.png)bin1417 -> 1417 bytes
-rw-r--r--public/-/emojis/1/cop_tone5.png (renamed from app/assets/images/emoji/cop_tone5.png)bin1433 -> 1433 bytes
-rw-r--r--public/-/emojis/1/copyright.png (renamed from app/assets/images/emoji/copyright.png)bin530 -> 530 bytes
-rw-r--r--public/-/emojis/1/corn.png (renamed from app/assets/images/emoji/corn.png)bin1547 -> 1547 bytes
-rw-r--r--public/-/emojis/1/couch.png (renamed from app/assets/images/emoji/couch.png)bin1362 -> 1362 bytes
-rw-r--r--public/-/emojis/1/couple.png (renamed from app/assets/images/emoji/couple.png)bin1537 -> 1537 bytes
-rw-r--r--public/-/emojis/1/couple_mm.png (renamed from app/assets/images/emoji/couple_mm.png)bin1091 -> 1091 bytes
-rw-r--r--public/-/emojis/1/couple_with_heart.png (renamed from app/assets/images/emoji/couple_with_heart.png)bin1285 -> 1285 bytes
-rw-r--r--public/-/emojis/1/couple_ww.png (renamed from app/assets/images/emoji/couple_ww.png)bin1034 -> 1034 bytes
-rw-r--r--public/-/emojis/1/couplekiss.png (renamed from app/assets/images/emoji/couplekiss.png)bin1380 -> 1380 bytes
-rw-r--r--public/-/emojis/1/cow.png (renamed from app/assets/images/emoji/cow.png)bin1640 -> 1640 bytes
-rw-r--r--public/-/emojis/1/cow2.png (renamed from app/assets/images/emoji/cow2.png)bin1810 -> 1810 bytes
-rw-r--r--public/-/emojis/1/cowboy.png (renamed from app/assets/images/emoji/cowboy.png)bin1353 -> 1353 bytes
-rw-r--r--public/-/emojis/1/crab.png (renamed from app/assets/images/emoji/crab.png)bin1475 -> 1475 bytes
-rw-r--r--public/-/emojis/1/crayon.png (renamed from app/assets/images/emoji/crayon.png)bin633 -> 633 bytes
-rw-r--r--public/-/emojis/1/credit_card.png (renamed from app/assets/images/emoji/credit_card.png)bin1012 -> 1012 bytes
-rw-r--r--public/-/emojis/1/crescent_moon.png (renamed from app/assets/images/emoji/crescent_moon.png)bin446 -> 446 bytes
-rw-r--r--public/-/emojis/1/cricket.png (renamed from app/assets/images/emoji/cricket.png)bin1060 -> 1060 bytes
-rw-r--r--public/-/emojis/1/crocodile.png (renamed from app/assets/images/emoji/crocodile.png)bin2408 -> 2408 bytes
-rw-r--r--public/-/emojis/1/croissant.png (renamed from app/assets/images/emoji/croissant.png)bin1313 -> 1313 bytes
-rw-r--r--public/-/emojis/1/cross.png (renamed from app/assets/images/emoji/cross.png)bin408 -> 408 bytes
-rw-r--r--public/-/emojis/1/crossed_flags.png (renamed from app/assets/images/emoji/crossed_flags.png)bin1239 -> 1239 bytes
-rw-r--r--public/-/emojis/1/crossed_swords.png (renamed from app/assets/images/emoji/crossed_swords.png)bin1591 -> 1591 bytes
-rw-r--r--public/-/emojis/1/crown.png (renamed from app/assets/images/emoji/crown.png)bin1534 -> 1534 bytes
-rw-r--r--public/-/emojis/1/cruise_ship.png (renamed from app/assets/images/emoji/cruise_ship.png)bin2272 -> 2272 bytes
-rw-r--r--public/-/emojis/1/cry.png (renamed from app/assets/images/emoji/cry.png)bin1123 -> 1123 bytes
-rw-r--r--public/-/emojis/1/crying_cat_face.png (renamed from app/assets/images/emoji/crying_cat_face.png)bin1875 -> 1875 bytes
-rw-r--r--public/-/emojis/1/crystal_ball.png (renamed from app/assets/images/emoji/crystal_ball.png)bin1913 -> 1913 bytes
-rw-r--r--public/-/emojis/1/cucumber.png (renamed from app/assets/images/emoji/cucumber.png)bin1357 -> 1357 bytes
-rw-r--r--public/-/emojis/1/cupid.png (renamed from app/assets/images/emoji/cupid.png)bin846 -> 846 bytes
-rw-r--r--public/-/emojis/1/curly_loop.png (renamed from app/assets/images/emoji/curly_loop.png)bin545 -> 545 bytes
-rw-r--r--public/-/emojis/1/currency_exchange.png (renamed from app/assets/images/emoji/currency_exchange.png)bin576 -> 576 bytes
-rw-r--r--public/-/emojis/1/curry.png (renamed from app/assets/images/emoji/curry.png)bin1754 -> 1754 bytes
-rw-r--r--public/-/emojis/1/custard.png (renamed from app/assets/images/emoji/custard.png)bin1273 -> 1273 bytes
-rw-r--r--public/-/emojis/1/customs.png (renamed from app/assets/images/emoji/customs.png)bin648 -> 648 bytes
-rw-r--r--public/-/emojis/1/cyclone.png (renamed from app/assets/images/emoji/cyclone.png)bin797 -> 797 bytes
-rw-r--r--public/-/emojis/1/dagger.png (renamed from app/assets/images/emoji/dagger.png)bin916 -> 916 bytes
-rw-r--r--public/-/emojis/1/dancer.png (renamed from app/assets/images/emoji/dancer.png)bin1405 -> 1405 bytes
-rw-r--r--public/-/emojis/1/dancer_tone1.png (renamed from app/assets/images/emoji/dancer_tone1.png)bin1420 -> 1420 bytes
-rw-r--r--public/-/emojis/1/dancer_tone2.png (renamed from app/assets/images/emoji/dancer_tone2.png)bin1423 -> 1423 bytes
-rw-r--r--public/-/emojis/1/dancer_tone3.png (renamed from app/assets/images/emoji/dancer_tone3.png)bin1429 -> 1429 bytes
-rw-r--r--public/-/emojis/1/dancer_tone4.png (renamed from app/assets/images/emoji/dancer_tone4.png)bin1428 -> 1428 bytes
-rw-r--r--public/-/emojis/1/dancer_tone5.png (renamed from app/assets/images/emoji/dancer_tone5.png)bin1418 -> 1418 bytes
-rw-r--r--public/-/emojis/1/dancers.png (renamed from app/assets/images/emoji/dancers.png)bin1872 -> 1872 bytes
-rw-r--r--public/-/emojis/1/dango.png (renamed from app/assets/images/emoji/dango.png)bin802 -> 802 bytes
-rw-r--r--public/-/emojis/1/dark_sunglasses.png (renamed from app/assets/images/emoji/dark_sunglasses.png)bin829 -> 829 bytes
-rw-r--r--public/-/emojis/1/dart.png (renamed from app/assets/images/emoji/dart.png)bin1374 -> 1374 bytes
-rw-r--r--public/-/emojis/1/dash.png (renamed from app/assets/images/emoji/dash.png)bin840 -> 840 bytes
-rw-r--r--public/-/emojis/1/date.png (renamed from app/assets/images/emoji/date.png)bin788 -> 788 bytes
-rw-r--r--public/-/emojis/1/deciduous_tree.png (renamed from app/assets/images/emoji/deciduous_tree.png)bin1267 -> 1267 bytes
-rw-r--r--public/-/emojis/1/deer.png (renamed from app/assets/images/emoji/deer.png)bin1606 -> 1606 bytes
-rw-r--r--public/-/emojis/1/department_store.png (renamed from app/assets/images/emoji/department_store.png)bin673 -> 673 bytes
-rw-r--r--public/-/emojis/1/desert.png (renamed from app/assets/images/emoji/desert.png)bin1443 -> 1443 bytes
-rw-r--r--public/-/emojis/1/desktop.png (renamed from app/assets/images/emoji/desktop.png)bin311 -> 311 bytes
-rw-r--r--public/-/emojis/1/diamond_shape_with_a_dot_inside.png (renamed from app/assets/images/emoji/diamond_shape_with_a_dot_inside.png)bin693 -> 693 bytes
-rw-r--r--public/-/emojis/1/diamonds.png (renamed from app/assets/images/emoji/diamonds.png)bin247 -> 247 bytes
-rw-r--r--public/-/emojis/1/disappointed.png (renamed from app/assets/images/emoji/disappointed.png)bin757 -> 757 bytes
-rw-r--r--public/-/emojis/1/disappointed_relieved.png (renamed from app/assets/images/emoji/disappointed_relieved.png)bin835 -> 835 bytes
-rw-r--r--public/-/emojis/1/dividers.png (renamed from app/assets/images/emoji/dividers.png)bin810 -> 810 bytes
-rw-r--r--public/-/emojis/1/dizzy.png (renamed from app/assets/images/emoji/dizzy.png)bin795 -> 795 bytes
-rw-r--r--public/-/emojis/1/dizzy_face.png (renamed from app/assets/images/emoji/dizzy_face.png)bin710 -> 710 bytes
-rw-r--r--public/-/emojis/1/do_not_litter.png (renamed from app/assets/images/emoji/do_not_litter.png)bin1010 -> 1010 bytes
-rw-r--r--public/-/emojis/1/dog.png (renamed from app/assets/images/emoji/dog.png)bin1674 -> 1674 bytes
-rw-r--r--public/-/emojis/1/dog2.png (renamed from app/assets/images/emoji/dog2.png)bin2085 -> 2085 bytes
-rw-r--r--public/-/emojis/1/dollar.png (renamed from app/assets/images/emoji/dollar.png)bin405 -> 405 bytes
-rw-r--r--public/-/emojis/1/dolls.png (renamed from app/assets/images/emoji/dolls.png)bin2249 -> 2249 bytes
-rw-r--r--public/-/emojis/1/dolphin.png (renamed from app/assets/images/emoji/dolphin.png)bin1697 -> 1697 bytes
-rw-r--r--public/-/emojis/1/door.png (renamed from app/assets/images/emoji/door.png)bin1105 -> 1105 bytes
-rw-r--r--public/-/emojis/1/doughnut.png (renamed from app/assets/images/emoji/doughnut.png)bin1322 -> 1322 bytes
-rw-r--r--public/-/emojis/1/dove.png (renamed from app/assets/images/emoji/dove.png)bin967 -> 967 bytes
-rw-r--r--public/-/emojis/1/dragon.png (renamed from app/assets/images/emoji/dragon.png)bin1574 -> 1574 bytes
-rw-r--r--public/-/emojis/1/dragon_face.png (renamed from app/assets/images/emoji/dragon_face.png)bin1769 -> 1769 bytes
-rw-r--r--public/-/emojis/1/dress.png (renamed from app/assets/images/emoji/dress.png)bin1001 -> 1001 bytes
-rw-r--r--public/-/emojis/1/dromedary_camel.png (renamed from app/assets/images/emoji/dromedary_camel.png)bin1515 -> 1515 bytes
-rw-r--r--public/-/emojis/1/drooling_face.png (renamed from app/assets/images/emoji/drooling_face.png)bin1049 -> 1049 bytes
-rw-r--r--public/-/emojis/1/droplet.png (renamed from app/assets/images/emoji/droplet.png)bin411 -> 411 bytes
-rw-r--r--public/-/emojis/1/drum.png (renamed from app/assets/images/emoji/drum.png)bin1870 -> 1870 bytes
-rw-r--r--public/-/emojis/1/duck.png (renamed from app/assets/images/emoji/duck.png)bin1729 -> 1729 bytes
-rw-r--r--public/-/emojis/1/dvd.png (renamed from app/assets/images/emoji/dvd.png)bin933 -> 933 bytes
-rw-r--r--public/-/emojis/1/e-mail.png (renamed from app/assets/images/emoji/e-mail.png)bin1196 -> 1196 bytes
-rw-r--r--public/-/emojis/1/eagle.png (renamed from app/assets/images/emoji/eagle.png)bin2222 -> 2222 bytes
-rw-r--r--public/-/emojis/1/ear.png (renamed from app/assets/images/emoji/ear.png)bin860 -> 860 bytes
-rw-r--r--public/-/emojis/1/ear_of_rice.png (renamed from app/assets/images/emoji/ear_of_rice.png)bin1422 -> 1422 bytes
-rw-r--r--public/-/emojis/1/ear_tone1.png (renamed from app/assets/images/emoji/ear_tone1.png)bin860 -> 860 bytes
-rw-r--r--public/-/emojis/1/ear_tone2.png (renamed from app/assets/images/emoji/ear_tone2.png)bin860 -> 860 bytes
-rw-r--r--public/-/emojis/1/ear_tone3.png (renamed from app/assets/images/emoji/ear_tone3.png)bin860 -> 860 bytes
-rw-r--r--public/-/emojis/1/ear_tone4.png (renamed from app/assets/images/emoji/ear_tone4.png)bin860 -> 860 bytes
-rw-r--r--public/-/emojis/1/ear_tone5.png (renamed from app/assets/images/emoji/ear_tone5.png)bin860 -> 860 bytes
-rw-r--r--public/-/emojis/1/earth_africa.png (renamed from app/assets/images/emoji/earth_africa.png)bin978 -> 978 bytes
-rw-r--r--public/-/emojis/1/earth_americas.png (renamed from app/assets/images/emoji/earth_americas.png)bin1031 -> 1031 bytes
-rw-r--r--public/-/emojis/1/earth_asia.png (renamed from app/assets/images/emoji/earth_asia.png)bin966 -> 966 bytes
-rw-r--r--public/-/emojis/1/egg.png (renamed from app/assets/images/emoji/egg.png)bin710 -> 710 bytes
-rw-r--r--public/-/emojis/1/eggplant.png (renamed from app/assets/images/emoji/eggplant.png)bin773 -> 773 bytes
-rw-r--r--public/-/emojis/1/eight.png (renamed from app/assets/images/emoji/eight.png)bin608 -> 608 bytes
-rw-r--r--public/-/emojis/1/eight_pointed_black_star.png (renamed from app/assets/images/emoji/eight_pointed_black_star.png)bin493 -> 493 bytes
-rw-r--r--public/-/emojis/1/eight_spoked_asterisk.png (renamed from app/assets/images/emoji/eight_spoked_asterisk.png)bin493 -> 493 bytes
-rw-r--r--public/-/emojis/1/eject.png (renamed from app/assets/images/emoji/eject.png)bin548 -> 548 bytes
-rw-r--r--public/-/emojis/1/electric_plug.png (renamed from app/assets/images/emoji/electric_plug.png)bin548 -> 548 bytes
-rw-r--r--public/-/emojis/1/elephant.png (renamed from app/assets/images/emoji/elephant.png)bin1293 -> 1293 bytes
-rw-r--r--public/-/emojis/1/emojis.json10760
-rw-r--r--public/-/emojis/1/end.png (renamed from app/assets/images/emoji/end.png)bin393 -> 393 bytes
-rw-r--r--public/-/emojis/1/envelope.png (renamed from app/assets/images/emoji/envelope.png)bin916 -> 916 bytes
-rw-r--r--public/-/emojis/1/envelope_with_arrow.png (renamed from app/assets/images/emoji/envelope_with_arrow.png)bin1062 -> 1062 bytes
-rw-r--r--public/-/emojis/1/euro.png (renamed from app/assets/images/emoji/euro.png)bin460 -> 460 bytes
-rw-r--r--public/-/emojis/1/european_castle.png (renamed from app/assets/images/emoji/european_castle.png)bin965 -> 965 bytes
-rw-r--r--public/-/emojis/1/european_post_office.png (renamed from app/assets/images/emoji/european_post_office.png)bin551 -> 551 bytes
-rw-r--r--public/-/emojis/1/evergreen_tree.png (renamed from app/assets/images/emoji/evergreen_tree.png)bin719 -> 719 bytes
-rw-r--r--public/-/emojis/1/exclamation.png (renamed from app/assets/images/emoji/exclamation.png)bin354 -> 354 bytes
-rw-r--r--public/-/emojis/1/expressionless.png (renamed from app/assets/images/emoji/expressionless.png)bin438 -> 438 bytes
-rw-r--r--public/-/emojis/1/eye.png (renamed from app/assets/images/emoji/eye.png)bin664 -> 664 bytes
-rw-r--r--public/-/emojis/1/eye_in_speech_bubble.png (renamed from app/assets/images/emoji/eye_in_speech_bubble.png)bin698 -> 698 bytes
-rw-r--r--public/-/emojis/1/eyeglasses.png (renamed from app/assets/images/emoji/eyeglasses.png)bin577 -> 577 bytes
-rw-r--r--public/-/emojis/1/eyes.png (renamed from app/assets/images/emoji/eyes.png)bin791 -> 791 bytes
-rw-r--r--public/-/emojis/1/face_palm.png (renamed from app/assets/images/emoji/face_palm.png)bin1523 -> 1523 bytes
-rw-r--r--public/-/emojis/1/face_palm_tone1.png (renamed from app/assets/images/emoji/face_palm_tone1.png)bin1563 -> 1563 bytes
-rw-r--r--public/-/emojis/1/face_palm_tone2.png (renamed from app/assets/images/emoji/face_palm_tone2.png)bin1547 -> 1547 bytes
-rw-r--r--public/-/emojis/1/face_palm_tone3.png (renamed from app/assets/images/emoji/face_palm_tone3.png)bin1550 -> 1550 bytes
-rw-r--r--public/-/emojis/1/face_palm_tone4.png (renamed from app/assets/images/emoji/face_palm_tone4.png)bin1553 -> 1553 bytes
-rw-r--r--public/-/emojis/1/face_palm_tone5.png (renamed from app/assets/images/emoji/face_palm_tone5.png)bin1532 -> 1532 bytes
-rw-r--r--public/-/emojis/1/factory.png (renamed from app/assets/images/emoji/factory.png)bin936 -> 936 bytes
-rw-r--r--public/-/emojis/1/fallen_leaf.png (renamed from app/assets/images/emoji/fallen_leaf.png)bin951 -> 951 bytes
-rw-r--r--public/-/emojis/1/family.png (renamed from app/assets/images/emoji/family.png)bin1433 -> 1433 bytes
-rw-r--r--public/-/emojis/1/family_mmb.png (renamed from app/assets/images/emoji/family_mmb.png)bin1206 -> 1206 bytes
-rw-r--r--public/-/emojis/1/family_mmbb.png (renamed from app/assets/images/emoji/family_mmbb.png)bin1349 -> 1349 bytes
-rw-r--r--public/-/emojis/1/family_mmg.png (renamed from app/assets/images/emoji/family_mmg.png)bin1361 -> 1361 bytes
-rw-r--r--public/-/emojis/1/family_mmgb.png (renamed from app/assets/images/emoji/family_mmgb.png)bin1626 -> 1626 bytes
-rw-r--r--public/-/emojis/1/family_mmgg.png (renamed from app/assets/images/emoji/family_mmgg.png)bin1448 -> 1448 bytes
-rw-r--r--public/-/emojis/1/family_mwbb.png (renamed from app/assets/images/emoji/family_mwbb.png)bin1638 -> 1638 bytes
-rw-r--r--public/-/emojis/1/family_mwg.png (renamed from app/assets/images/emoji/family_mwg.png)bin1554 -> 1554 bytes
-rw-r--r--public/-/emojis/1/family_mwgb.png (renamed from app/assets/images/emoji/family_mwgb.png)bin1837 -> 1837 bytes
-rw-r--r--public/-/emojis/1/family_mwgg.png (renamed from app/assets/images/emoji/family_mwgg.png)bin1738 -> 1738 bytes
-rw-r--r--public/-/emojis/1/family_wwb.png (renamed from app/assets/images/emoji/family_wwb.png)bin1155 -> 1155 bytes
-rw-r--r--public/-/emojis/1/family_wwbb.png (renamed from app/assets/images/emoji/family_wwbb.png)bin1289 -> 1289 bytes
-rw-r--r--public/-/emojis/1/family_wwg.png (renamed from app/assets/images/emoji/family_wwg.png)bin1286 -> 1286 bytes
-rw-r--r--public/-/emojis/1/family_wwgb.png (renamed from app/assets/images/emoji/family_wwgb.png)bin1550 -> 1550 bytes
-rw-r--r--public/-/emojis/1/family_wwgg.png (renamed from app/assets/images/emoji/family_wwgg.png)bin1374 -> 1374 bytes
-rw-r--r--public/-/emojis/1/fast_forward.png (renamed from app/assets/images/emoji/fast_forward.png)bin523 -> 523 bytes
-rw-r--r--public/-/emojis/1/fax.png (renamed from app/assets/images/emoji/fax.png)bin1188 -> 1188 bytes
-rw-r--r--public/-/emojis/1/fearful.png (renamed from app/assets/images/emoji/fearful.png)bin1002 -> 1002 bytes
-rw-r--r--public/-/emojis/1/feet.png (renamed from app/assets/images/emoji/feet.png)bin603 -> 603 bytes
-rw-r--r--public/-/emojis/1/fencer.png (renamed from app/assets/images/emoji/fencer.png)bin1342 -> 1342 bytes
-rw-r--r--public/-/emojis/1/ferris_wheel.png (renamed from app/assets/images/emoji/ferris_wheel.png)bin2185 -> 2185 bytes
-rw-r--r--public/-/emojis/1/ferry.png (renamed from app/assets/images/emoji/ferry.png)bin528 -> 528 bytes
-rw-r--r--public/-/emojis/1/field_hockey.png (renamed from app/assets/images/emoji/field_hockey.png)bin947 -> 947 bytes
-rw-r--r--public/-/emojis/1/file_cabinet.png (renamed from app/assets/images/emoji/file_cabinet.png)bin1420 -> 1420 bytes
-rw-r--r--public/-/emojis/1/file_folder.png (renamed from app/assets/images/emoji/file_folder.png)bin1445 -> 1445 bytes
-rw-r--r--public/-/emojis/1/film_frames.png (renamed from app/assets/images/emoji/film_frames.png)bin560 -> 560 bytes
-rw-r--r--public/-/emojis/1/fingers_crossed.png (renamed from app/assets/images/emoji/fingers_crossed.png)bin1050 -> 1050 bytes
-rw-r--r--public/-/emojis/1/fingers_crossed_tone1.png (renamed from app/assets/images/emoji/fingers_crossed_tone1.png)bin1047 -> 1047 bytes
-rw-r--r--public/-/emojis/1/fingers_crossed_tone2.png (renamed from app/assets/images/emoji/fingers_crossed_tone2.png)bin1050 -> 1050 bytes
-rw-r--r--public/-/emojis/1/fingers_crossed_tone3.png (renamed from app/assets/images/emoji/fingers_crossed_tone3.png)bin1050 -> 1050 bytes
-rw-r--r--public/-/emojis/1/fingers_crossed_tone4.png (renamed from app/assets/images/emoji/fingers_crossed_tone4.png)bin1046 -> 1046 bytes
-rw-r--r--public/-/emojis/1/fingers_crossed_tone5.png (renamed from app/assets/images/emoji/fingers_crossed_tone5.png)bin1050 -> 1050 bytes
-rw-r--r--public/-/emojis/1/fire.png (renamed from app/assets/images/emoji/fire.png)bin1020 -> 1020 bytes
-rw-r--r--public/-/emojis/1/fire_engine.png (renamed from app/assets/images/emoji/fire_engine.png)bin1656 -> 1656 bytes
-rw-r--r--public/-/emojis/1/fireworks.png (renamed from app/assets/images/emoji/fireworks.png)bin1364 -> 1364 bytes
-rw-r--r--public/-/emojis/1/first_place.png (renamed from app/assets/images/emoji/first_place.png)bin1419 -> 1419 bytes
-rw-r--r--public/-/emojis/1/first_quarter_moon.png (renamed from app/assets/images/emoji/first_quarter_moon.png)bin1152 -> 1152 bytes
-rw-r--r--public/-/emojis/1/first_quarter_moon_with_face.png (renamed from app/assets/images/emoji/first_quarter_moon_with_face.png)bin1068 -> 1068 bytes
-rw-r--r--public/-/emojis/1/fish.png (renamed from app/assets/images/emoji/fish.png)bin1080 -> 1080 bytes
-rw-r--r--public/-/emojis/1/fish_cake.png (renamed from app/assets/images/emoji/fish_cake.png)bin1245 -> 1245 bytes
-rw-r--r--public/-/emojis/1/fishing_pole_and_fish.png (renamed from app/assets/images/emoji/fishing_pole_and_fish.png)bin1442 -> 1442 bytes
-rw-r--r--public/-/emojis/1/fist.png (renamed from app/assets/images/emoji/fist.png)bin1014 -> 1014 bytes
-rw-r--r--public/-/emojis/1/fist_tone1.png (renamed from app/assets/images/emoji/fist_tone1.png)bin1014 -> 1014 bytes
-rw-r--r--public/-/emojis/1/fist_tone2.png (renamed from app/assets/images/emoji/fist_tone2.png)bin1014 -> 1014 bytes
-rw-r--r--public/-/emojis/1/fist_tone3.png (renamed from app/assets/images/emoji/fist_tone3.png)bin1014 -> 1014 bytes
-rw-r--r--public/-/emojis/1/fist_tone4.png (renamed from app/assets/images/emoji/fist_tone4.png)bin1014 -> 1014 bytes
-rw-r--r--public/-/emojis/1/fist_tone5.png (renamed from app/assets/images/emoji/fist_tone5.png)bin1014 -> 1014 bytes
-rw-r--r--public/-/emojis/1/five.png (renamed from app/assets/images/emoji/five.png)bin577 -> 577 bytes
-rw-r--r--public/-/emojis/1/flag_ac.png (renamed from app/assets/images/emoji/flag_ac.png)bin1934 -> 1934 bytes
-rw-r--r--public/-/emojis/1/flag_ad.png (renamed from app/assets/images/emoji/flag_ad.png)bin1285 -> 1285 bytes
-rw-r--r--public/-/emojis/1/flag_ae.png (renamed from app/assets/images/emoji/flag_ae.png)bin544 -> 544 bytes
-rw-r--r--public/-/emojis/1/flag_af.png (renamed from app/assets/images/emoji/flag_af.png)bin942 -> 942 bytes
-rw-r--r--public/-/emojis/1/flag_ag.png (renamed from app/assets/images/emoji/flag_ag.png)bin913 -> 913 bytes
-rw-r--r--public/-/emojis/1/flag_ai.png (renamed from app/assets/images/emoji/flag_ai.png)bin1056 -> 1056 bytes
-rw-r--r--public/-/emojis/1/flag_al.png (renamed from app/assets/images/emoji/flag_al.png)bin905 -> 905 bytes
-rw-r--r--public/-/emojis/1/flag_am.png (renamed from app/assets/images/emoji/flag_am.png)bin514 -> 514 bytes
-rw-r--r--public/-/emojis/1/flag_ao.png (renamed from app/assets/images/emoji/flag_ao.png)bin997 -> 997 bytes
-rw-r--r--public/-/emojis/1/flag_aq.png (renamed from app/assets/images/emoji/flag_aq.png)bin657 -> 657 bytes
-rw-r--r--public/-/emojis/1/flag_ar.png (renamed from app/assets/images/emoji/flag_ar.png)bin975 -> 975 bytes
-rw-r--r--public/-/emojis/1/flag_as.png (renamed from app/assets/images/emoji/flag_as.png)bin1489 -> 1489 bytes
-rw-r--r--public/-/emojis/1/flag_at.png (renamed from app/assets/images/emoji/flag_at.png)bin430 -> 430 bytes
-rw-r--r--public/-/emojis/1/flag_au.png (renamed from app/assets/images/emoji/flag_au.png)bin962 -> 962 bytes
-rw-r--r--public/-/emojis/1/flag_aw.png (renamed from app/assets/images/emoji/flag_aw.png)bin709 -> 709 bytes
-rw-r--r--public/-/emojis/1/flag_ax.png (renamed from app/assets/images/emoji/flag_ax.png)bin496 -> 496 bytes
-rw-r--r--public/-/emojis/1/flag_az.png (renamed from app/assets/images/emoji/flag_az.png)bin709 -> 709 bytes
-rw-r--r--public/-/emojis/1/flag_ba.png (renamed from app/assets/images/emoji/flag_ba.png)bin848 -> 848 bytes
-rw-r--r--public/-/emojis/1/flag_bb.png (renamed from app/assets/images/emoji/flag_bb.png)bin789 -> 789 bytes
-rw-r--r--public/-/emojis/1/flag_bd.png (renamed from app/assets/images/emoji/flag_bd.png)bin490 -> 490 bytes
-rw-r--r--public/-/emojis/1/flag_be.png (renamed from app/assets/images/emoji/flag_be.png)bin444 -> 444 bytes
-rw-r--r--public/-/emojis/1/flag_bf.png (renamed from app/assets/images/emoji/flag_bf.png)bin717 -> 717 bytes
-rw-r--r--public/-/emojis/1/flag_bg.png (renamed from app/assets/images/emoji/flag_bg.png)bin513 -> 513 bytes
-rw-r--r--public/-/emojis/1/flag_bh.png (renamed from app/assets/images/emoji/flag_bh.png)bin593 -> 593 bytes
-rw-r--r--public/-/emojis/1/flag_bi.png (renamed from app/assets/images/emoji/flag_bi.png)bin795 -> 795 bytes
-rw-r--r--public/-/emojis/1/flag_bj.png (renamed from app/assets/images/emoji/flag_bj.png)bin554 -> 554 bytes
-rw-r--r--public/-/emojis/1/flag_bl.png (renamed from app/assets/images/emoji/flag_bl.png)bin1691 -> 1691 bytes
-rw-r--r--public/-/emojis/1/flag_black.png (renamed from app/assets/images/emoji/flag_black.png)bin702 -> 702 bytes
-rw-r--r--public/-/emojis/1/flag_bm.png (renamed from app/assets/images/emoji/flag_bm.png)bin1374 -> 1374 bytes
-rw-r--r--public/-/emojis/1/flag_bn.png (renamed from app/assets/images/emoji/flag_bn.png)bin1355 -> 1355 bytes
-rw-r--r--public/-/emojis/1/flag_bo.png (renamed from app/assets/images/emoji/flag_bo.png)bin1132 -> 1132 bytes
-rw-r--r--public/-/emojis/1/flag_bq.png (renamed from app/assets/images/emoji/flag_bq.png)bin1144 -> 1144 bytes
-rw-r--r--public/-/emojis/1/flag_br.png (renamed from app/assets/images/emoji/flag_br.png)bin819 -> 819 bytes
-rw-r--r--public/-/emojis/1/flag_bs.png (renamed from app/assets/images/emoji/flag_bs.png)bin448 -> 448 bytes
-rw-r--r--public/-/emojis/1/flag_bt.png (renamed from app/assets/images/emoji/flag_bt.png)bin1213 -> 1213 bytes
-rw-r--r--public/-/emojis/1/flag_bv.png (renamed from app/assets/images/emoji/flag_bv.png)bin495 -> 495 bytes
-rw-r--r--public/-/emojis/1/flag_bw.png (renamed from app/assets/images/emoji/flag_bw.png)bin391 -> 391 bytes
-rw-r--r--public/-/emojis/1/flag_by.png (renamed from app/assets/images/emoji/flag_by.png)bin1120 -> 1120 bytes
-rw-r--r--public/-/emojis/1/flag_bz.png (renamed from app/assets/images/emoji/flag_bz.png)bin1595 -> 1595 bytes
-rw-r--r--public/-/emojis/1/flag_ca.png (renamed from app/assets/images/emoji/flag_ca.png)bin755 -> 755 bytes
-rw-r--r--public/-/emojis/1/flag_cc.png (renamed from app/assets/images/emoji/flag_cc.png)bin851 -> 851 bytes
-rw-r--r--public/-/emojis/1/flag_cd.png (renamed from app/assets/images/emoji/flag_cd.png)bin707 -> 707 bytes
-rw-r--r--public/-/emojis/1/flag_cf.png (renamed from app/assets/images/emoji/flag_cf.png)bin673 -> 673 bytes
-rw-r--r--public/-/emojis/1/flag_cg.png (renamed from app/assets/images/emoji/flag_cg.png)bin586 -> 586 bytes
-rw-r--r--public/-/emojis/1/flag_ch.png (renamed from app/assets/images/emoji/flag_ch.png)bin390 -> 390 bytes
-rw-r--r--public/-/emojis/1/flag_ci.png (renamed from app/assets/images/emoji/flag_ci.png)bin440 -> 440 bytes
-rw-r--r--public/-/emojis/1/flag_ck.png (renamed from app/assets/images/emoji/flag_ck.png)bin1083 -> 1083 bytes
-rw-r--r--public/-/emojis/1/flag_cl.png (renamed from app/assets/images/emoji/flag_cl.png)bin748 -> 748 bytes
-rw-r--r--public/-/emojis/1/flag_cm.png (renamed from app/assets/images/emoji/flag_cm.png)bin627 -> 627 bytes
-rw-r--r--public/-/emojis/1/flag_cn.png (renamed from app/assets/images/emoji/flag_cn.png)bin676 -> 676 bytes
-rw-r--r--public/-/emojis/1/flag_co.png (renamed from app/assets/images/emoji/flag_co.png)bin524 -> 524 bytes
-rw-r--r--public/-/emojis/1/flag_cp.png (renamed from app/assets/images/emoji/flag_cp.png)bin443 -> 443 bytes
-rw-r--r--public/-/emojis/1/flag_cr.png (renamed from app/assets/images/emoji/flag_cr.png)bin419 -> 419 bytes
-rw-r--r--public/-/emojis/1/flag_cu.png (renamed from app/assets/images/emoji/flag_cu.png)bin586 -> 586 bytes
-rw-r--r--public/-/emojis/1/flag_cv.png (renamed from app/assets/images/emoji/flag_cv.png)bin642 -> 642 bytes
-rw-r--r--public/-/emojis/1/flag_cw.png (renamed from app/assets/images/emoji/flag_cw.png)bin665 -> 665 bytes
-rw-r--r--public/-/emojis/1/flag_cx.png (renamed from app/assets/images/emoji/flag_cx.png)bin1142 -> 1142 bytes
-rw-r--r--public/-/emojis/1/flag_cy.png (renamed from app/assets/images/emoji/flag_cy.png)bin830 -> 830 bytes
-rw-r--r--public/-/emojis/1/flag_cz.png (renamed from app/assets/images/emoji/flag_cz.png)bin600 -> 600 bytes
-rw-r--r--public/-/emojis/1/flag_de.png (renamed from app/assets/images/emoji/flag_de.png)bin502 -> 502 bytes
-rw-r--r--public/-/emojis/1/flag_dg.png (renamed from app/assets/images/emoji/flag_dg.png)bin1911 -> 1911 bytes
-rw-r--r--public/-/emojis/1/flag_dj.png (renamed from app/assets/images/emoji/flag_dj.png)bin753 -> 753 bytes
-rw-r--r--public/-/emojis/1/flag_dk.png (renamed from app/assets/images/emoji/flag_dk.png)bin450 -> 450 bytes
-rw-r--r--public/-/emojis/1/flag_dm.png (renamed from app/assets/images/emoji/flag_dm.png)bin1075 -> 1075 bytes
-rw-r--r--public/-/emojis/1/flag_do.png (renamed from app/assets/images/emoji/flag_do.png)bin1135 -> 1135 bytes
-rw-r--r--public/-/emojis/1/flag_dz.png (renamed from app/assets/images/emoji/flag_dz.png)bin734 -> 734 bytes
-rw-r--r--public/-/emojis/1/flag_ea.png (renamed from app/assets/images/emoji/flag_ea.png)bin1337 -> 1337 bytes
-rw-r--r--public/-/emojis/1/flag_ec.png (renamed from app/assets/images/emoji/flag_ec.png)bin1431 -> 1431 bytes
-rw-r--r--public/-/emojis/1/flag_ee.png (renamed from app/assets/images/emoji/flag_ee.png)bin512 -> 512 bytes
-rw-r--r--public/-/emojis/1/flag_eg.png (renamed from app/assets/images/emoji/flag_eg.png)bin818 -> 818 bytes
-rw-r--r--public/-/emojis/1/flag_eh.png (renamed from app/assets/images/emoji/flag_eh.png)bin742 -> 742 bytes
-rw-r--r--public/-/emojis/1/flag_er.png (renamed from app/assets/images/emoji/flag_er.png)bin1218 -> 1218 bytes
-rw-r--r--public/-/emojis/1/flag_es.png (renamed from app/assets/images/emoji/flag_es.png)bin1337 -> 1337 bytes
-rw-r--r--public/-/emojis/1/flag_et.png (renamed from app/assets/images/emoji/flag_et.png)bin947 -> 947 bytes
-rw-r--r--public/-/emojis/1/flag_eu.png (renamed from app/assets/images/emoji/flag_eu.png)bin760 -> 760 bytes
-rw-r--r--public/-/emojis/1/flag_fi.png (renamed from app/assets/images/emoji/flag_fi.png)bin487 -> 487 bytes
-rw-r--r--public/-/emojis/1/flag_fj.png (renamed from app/assets/images/emoji/flag_fj.png)bin1381 -> 1381 bytes
-rw-r--r--public/-/emojis/1/flag_fk.png (renamed from app/assets/images/emoji/flag_fk.png)bin1558 -> 1558 bytes
-rw-r--r--public/-/emojis/1/flag_fm.png (renamed from app/assets/images/emoji/flag_fm.png)bin554 -> 554 bytes
-rw-r--r--public/-/emojis/1/flag_fo.png (renamed from app/assets/images/emoji/flag_fo.png)bin495 -> 495 bytes
-rw-r--r--public/-/emojis/1/flag_fr.png (renamed from app/assets/images/emoji/flag_fr.png)bin443 -> 443 bytes
-rw-r--r--public/-/emojis/1/flag_ga.png (renamed from app/assets/images/emoji/flag_ga.png)bin512 -> 512 bytes
-rw-r--r--public/-/emojis/1/flag_gb.png (renamed from app/assets/images/emoji/flag_gb.png)bin919 -> 919 bytes
-rw-r--r--public/-/emojis/1/flag_gd.png (renamed from app/assets/images/emoji/flag_gd.png)bin1017 -> 1017 bytes
-rw-r--r--public/-/emojis/1/flag_ge.png (renamed from app/assets/images/emoji/flag_ge.png)bin583 -> 583 bytes
-rw-r--r--public/-/emojis/1/flag_gf.png (renamed from app/assets/images/emoji/flag_gf.png)bin865 -> 865 bytes
-rw-r--r--public/-/emojis/1/flag_gg.png (renamed from app/assets/images/emoji/flag_gg.png)bin521 -> 521 bytes
-rw-r--r--public/-/emojis/1/flag_gh.png (renamed from app/assets/images/emoji/flag_gh.png)bin723 -> 723 bytes
-rw-r--r--public/-/emojis/1/flag_gi.png (renamed from app/assets/images/emoji/flag_gi.png)bin1053 -> 1053 bytes
-rw-r--r--public/-/emojis/1/flag_gl.png (renamed from app/assets/images/emoji/flag_gl.png)bin700 -> 700 bytes
-rw-r--r--public/-/emojis/1/flag_gm.png (renamed from app/assets/images/emoji/flag_gm.png)bin501 -> 501 bytes
-rw-r--r--public/-/emojis/1/flag_gn.png (renamed from app/assets/images/emoji/flag_gn.png)bin434 -> 434 bytes
-rw-r--r--public/-/emojis/1/flag_gp.png (renamed from app/assets/images/emoji/flag_gp.png)bin1587 -> 1587 bytes
-rw-r--r--public/-/emojis/1/flag_gq.png (renamed from app/assets/images/emoji/flag_gq.png)bin1132 -> 1132 bytes
-rw-r--r--public/-/emojis/1/flag_gr.png (renamed from app/assets/images/emoji/flag_gr.png)bin549 -> 549 bytes
-rw-r--r--public/-/emojis/1/flag_gs.png (renamed from app/assets/images/emoji/flag_gs.png)bin2115 -> 2115 bytes
-rw-r--r--public/-/emojis/1/flag_gt.png (renamed from app/assets/images/emoji/flag_gt.png)bin1087 -> 1087 bytes
-rw-r--r--public/-/emojis/1/flag_gu.png (renamed from app/assets/images/emoji/flag_gu.png)bin1045 -> 1045 bytes
-rw-r--r--public/-/emojis/1/flag_gw.png (renamed from app/assets/images/emoji/flag_gw.png)bin705 -> 705 bytes
-rw-r--r--public/-/emojis/1/flag_gy.png (renamed from app/assets/images/emoji/flag_gy.png)bin690 -> 690 bytes
-rw-r--r--public/-/emojis/1/flag_hk.png (renamed from app/assets/images/emoji/flag_hk.png)bin759 -> 759 bytes
-rw-r--r--public/-/emojis/1/flag_hm.png (renamed from app/assets/images/emoji/flag_hm.png)bin1036 -> 1036 bytes
-rw-r--r--public/-/emojis/1/flag_hn.png (renamed from app/assets/images/emoji/flag_hn.png)bin513 -> 513 bytes
-rw-r--r--public/-/emojis/1/flag_hr.png (renamed from app/assets/images/emoji/flag_hr.png)bin1411 -> 1411 bytes
-rw-r--r--public/-/emojis/1/flag_ht.png (renamed from app/assets/images/emoji/flag_ht.png)bin1205 -> 1205 bytes
-rw-r--r--public/-/emojis/1/flag_hu.png (renamed from app/assets/images/emoji/flag_hu.png)bin513 -> 513 bytes
-rw-r--r--public/-/emojis/1/flag_ic.png (renamed from app/assets/images/emoji/flag_ic.png)bin1330 -> 1330 bytes
-rw-r--r--public/-/emojis/1/flag_id.png (renamed from app/assets/images/emoji/flag_id.png)bin498 -> 498 bytes
-rw-r--r--public/-/emojis/1/flag_ie.png (renamed from app/assets/images/emoji/flag_ie.png)bin478 -> 478 bytes
-rw-r--r--public/-/emojis/1/flag_il.png (renamed from app/assets/images/emoji/flag_il.png)bin658 -> 658 bytes
-rw-r--r--public/-/emojis/1/flag_im.png (renamed from app/assets/images/emoji/flag_im.png)bin976 -> 976 bytes
-rw-r--r--public/-/emojis/1/flag_in.png (renamed from app/assets/images/emoji/flag_in.png)bin773 -> 773 bytes
-rw-r--r--public/-/emojis/1/flag_io.png (renamed from app/assets/images/emoji/flag_io.png)bin1911 -> 1911 bytes
-rw-r--r--public/-/emojis/1/flag_iq.png (renamed from app/assets/images/emoji/flag_iq.png)bin811 -> 811 bytes
-rw-r--r--public/-/emojis/1/flag_ir.png (renamed from app/assets/images/emoji/flag_ir.png)bin1036 -> 1036 bytes
-rw-r--r--public/-/emojis/1/flag_is.png (renamed from app/assets/images/emoji/flag_is.png)bin491 -> 491 bytes
-rw-r--r--public/-/emojis/1/flag_it.png (renamed from app/assets/images/emoji/flag_it.png)bin472 -> 472 bytes
-rw-r--r--public/-/emojis/1/flag_je.png (renamed from app/assets/images/emoji/flag_je.png)bin956 -> 956 bytes
-rw-r--r--public/-/emojis/1/flag_jm.png (renamed from app/assets/images/emoji/flag_jm.png)bin837 -> 837 bytes
-rw-r--r--public/-/emojis/1/flag_jo.png (renamed from app/assets/images/emoji/flag_jo.png)bin740 -> 740 bytes
-rw-r--r--public/-/emojis/1/flag_jp.png (renamed from app/assets/images/emoji/flag_jp.png)bin455 -> 455 bytes
-rw-r--r--public/-/emojis/1/flag_ke.png (renamed from app/assets/images/emoji/flag_ke.png)bin1160 -> 1160 bytes
-rw-r--r--public/-/emojis/1/flag_kg.png (renamed from app/assets/images/emoji/flag_kg.png)bin1080 -> 1080 bytes
-rw-r--r--public/-/emojis/1/flag_kh.png (renamed from app/assets/images/emoji/flag_kh.png)bin872 -> 872 bytes
-rw-r--r--public/-/emojis/1/flag_ki.png (renamed from app/assets/images/emoji/flag_ki.png)bin1369 -> 1369 bytes
-rw-r--r--public/-/emojis/1/flag_km.png (renamed from app/assets/images/emoji/flag_km.png)bin783 -> 783 bytes
-rw-r--r--public/-/emojis/1/flag_kn.png (renamed from app/assets/images/emoji/flag_kn.png)bin1316 -> 1316 bytes
-rw-r--r--public/-/emojis/1/flag_kp.png (renamed from app/assets/images/emoji/flag_kp.png)bin696 -> 696 bytes
-rw-r--r--public/-/emojis/1/flag_kr.png (renamed from app/assets/images/emoji/flag_kr.png)bin967 -> 967 bytes
-rw-r--r--public/-/emojis/1/flag_kw.png (renamed from app/assets/images/emoji/flag_kw.png)bin560 -> 560 bytes
-rw-r--r--public/-/emojis/1/flag_ky.png (renamed from app/assets/images/emoji/flag_ky.png)bin1671 -> 1671 bytes
-rw-r--r--public/-/emojis/1/flag_kz.png (renamed from app/assets/images/emoji/flag_kz.png)bin1136 -> 1136 bytes
-rw-r--r--public/-/emojis/1/flag_la.png (renamed from app/assets/images/emoji/flag_la.png)bin479 -> 479 bytes
-rw-r--r--public/-/emojis/1/flag_lb.png (renamed from app/assets/images/emoji/flag_lb.png)bin740 -> 740 bytes
-rw-r--r--public/-/emojis/1/flag_lc.png (renamed from app/assets/images/emoji/flag_lc.png)bin561 -> 561 bytes
-rw-r--r--public/-/emojis/1/flag_li.png (renamed from app/assets/images/emoji/flag_li.png)bin946 -> 946 bytes
-rw-r--r--public/-/emojis/1/flag_lk.png (renamed from app/assets/images/emoji/flag_lk.png)bin974 -> 974 bytes
-rw-r--r--public/-/emojis/1/flag_lr.png (renamed from app/assets/images/emoji/flag_lr.png)bin772 -> 772 bytes
-rw-r--r--public/-/emojis/1/flag_ls.png (renamed from app/assets/images/emoji/flag_ls.png)bin775 -> 775 bytes
-rw-r--r--public/-/emojis/1/flag_lt.png (renamed from app/assets/images/emoji/flag_lt.png)bin510 -> 510 bytes
-rw-r--r--public/-/emojis/1/flag_lu.png (renamed from app/assets/images/emoji/flag_lu.png)bin512 -> 512 bytes
-rw-r--r--public/-/emojis/1/flag_lv.png (renamed from app/assets/images/emoji/flag_lv.png)bin388 -> 388 bytes
-rw-r--r--public/-/emojis/1/flag_ly.png (renamed from app/assets/images/emoji/flag_ly.png)bin685 -> 685 bytes
-rw-r--r--public/-/emojis/1/flag_ma.png (renamed from app/assets/images/emoji/flag_ma.png)bin626 -> 626 bytes
-rw-r--r--public/-/emojis/1/flag_mc.png (renamed from app/assets/images/emoji/flag_mc.png)bin528 -> 528 bytes
-rw-r--r--public/-/emojis/1/flag_md.png (renamed from app/assets/images/emoji/flag_md.png)bin1170 -> 1170 bytes
-rw-r--r--public/-/emojis/1/flag_me.png (renamed from app/assets/images/emoji/flag_me.png)bin1074 -> 1074 bytes
-rw-r--r--public/-/emojis/1/flag_mf.png (renamed from app/assets/images/emoji/flag_mf.png)bin443 -> 443 bytes
-rw-r--r--public/-/emojis/1/flag_mg.png (renamed from app/assets/images/emoji/flag_mg.png)bin556 -> 556 bytes
-rw-r--r--public/-/emojis/1/flag_mh.png (renamed from app/assets/images/emoji/flag_mh.png)bin1138 -> 1138 bytes
-rw-r--r--public/-/emojis/1/flag_mk.png (renamed from app/assets/images/emoji/flag_mk.png)bin1023 -> 1023 bytes
-rw-r--r--public/-/emojis/1/flag_ml.png (renamed from app/assets/images/emoji/flag_ml.png)bin440 -> 440 bytes
-rw-r--r--public/-/emojis/1/flag_mm.png (renamed from app/assets/images/emoji/flag_mm.png)bin937 -> 937 bytes
-rw-r--r--public/-/emojis/1/flag_mn.png (renamed from app/assets/images/emoji/flag_mn.png)bin698 -> 698 bytes
-rw-r--r--public/-/emojis/1/flag_mo.png (renamed from app/assets/images/emoji/flag_mo.png)bin792 -> 792 bytes
-rw-r--r--public/-/emojis/1/flag_mp.png (renamed from app/assets/images/emoji/flag_mp.png)bin1797 -> 1797 bytes
-rw-r--r--public/-/emojis/1/flag_mq.png (renamed from app/assets/images/emoji/flag_mq.png)bin780 -> 780 bytes
-rw-r--r--public/-/emojis/1/flag_mr.png (renamed from app/assets/images/emoji/flag_mr.png)bin657 -> 657 bytes
-rw-r--r--public/-/emojis/1/flag_ms.png (renamed from app/assets/images/emoji/flag_ms.png)bin1477 -> 1477 bytes
-rw-r--r--public/-/emojis/1/flag_mt.png (renamed from app/assets/images/emoji/flag_mt.png)bin799 -> 799 bytes
-rw-r--r--public/-/emojis/1/flag_mu.png (renamed from app/assets/images/emoji/flag_mu.png)bin544 -> 544 bytes
-rw-r--r--public/-/emojis/1/flag_mv.png (renamed from app/assets/images/emoji/flag_mv.png)bin598 -> 598 bytes
-rw-r--r--public/-/emojis/1/flag_mw.png (renamed from app/assets/images/emoji/flag_mw.png)bin825 -> 825 bytes
-rw-r--r--public/-/emojis/1/flag_mx.png (renamed from app/assets/images/emoji/flag_mx.png)bin951 -> 951 bytes
-rw-r--r--public/-/emojis/1/flag_my.png (renamed from app/assets/images/emoji/flag_my.png)bin775 -> 775 bytes
-rw-r--r--public/-/emojis/1/flag_mz.png (renamed from app/assets/images/emoji/flag_mz.png)bin1159 -> 1159 bytes
-rw-r--r--public/-/emojis/1/flag_na.png (renamed from app/assets/images/emoji/flag_na.png)bin1249 -> 1249 bytes
-rw-r--r--public/-/emojis/1/flag_nc.png (renamed from app/assets/images/emoji/flag_nc.png)bin1148 -> 1148 bytes
-rw-r--r--public/-/emojis/1/flag_ne.png (renamed from app/assets/images/emoji/flag_ne.png)bin593 -> 593 bytes
-rw-r--r--public/-/emojis/1/flag_nf.png (renamed from app/assets/images/emoji/flag_nf.png)bin877 -> 877 bytes
-rw-r--r--public/-/emojis/1/flag_ng.png (renamed from app/assets/images/emoji/flag_ng.png)bin438 -> 438 bytes
-rw-r--r--public/-/emojis/1/flag_ni.png (renamed from app/assets/images/emoji/flag_ni.png)bin823 -> 823 bytes
-rw-r--r--public/-/emojis/1/flag_nl.png (renamed from app/assets/images/emoji/flag_nl.png)bin499 -> 499 bytes
-rw-r--r--public/-/emojis/1/flag_no.png (renamed from app/assets/images/emoji/flag_no.png)bin484 -> 484 bytes
-rw-r--r--public/-/emojis/1/flag_np.png (renamed from app/assets/images/emoji/flag_np.png)bin802 -> 802 bytes
-rw-r--r--public/-/emojis/1/flag_nr.png (renamed from app/assets/images/emoji/flag_nr.png)bin529 -> 529 bytes
-rw-r--r--public/-/emojis/1/flag_nu.png (renamed from app/assets/images/emoji/flag_nu.png)bin1128 -> 1128 bytes
-rw-r--r--public/-/emojis/1/flag_nz.png (renamed from app/assets/images/emoji/flag_nz.png)bin1099 -> 1099 bytes
-rw-r--r--public/-/emojis/1/flag_om.png (renamed from app/assets/images/emoji/flag_om.png)bin754 -> 754 bytes
-rw-r--r--public/-/emojis/1/flag_pa.png (renamed from app/assets/images/emoji/flag_pa.png)bin830 -> 830 bytes
-rw-r--r--public/-/emojis/1/flag_pe.png (renamed from app/assets/images/emoji/flag_pe.png)bin439 -> 439 bytes
-rw-r--r--public/-/emojis/1/flag_pf.png (renamed from app/assets/images/emoji/flag_pf.png)bin1091 -> 1091 bytes
-rw-r--r--public/-/emojis/1/flag_pg.png (renamed from app/assets/images/emoji/flag_pg.png)bin1076 -> 1076 bytes
-rw-r--r--public/-/emojis/1/flag_ph.png (renamed from app/assets/images/emoji/flag_ph.png)bin867 -> 867 bytes
-rw-r--r--public/-/emojis/1/flag_pk.png (renamed from app/assets/images/emoji/flag_pk.png)bin753 -> 753 bytes
-rw-r--r--public/-/emojis/1/flag_pl.png (renamed from app/assets/images/emoji/flag_pl.png)bin522 -> 522 bytes
-rw-r--r--public/-/emojis/1/flag_pm.png (renamed from app/assets/images/emoji/flag_pm.png)bin2314 -> 2314 bytes
-rw-r--r--public/-/emojis/1/flag_pn.png (renamed from app/assets/images/emoji/flag_pn.png)bin1895 -> 1895 bytes
-rw-r--r--public/-/emojis/1/flag_pr.png (renamed from app/assets/images/emoji/flag_pr.png)bin605 -> 605 bytes
-rw-r--r--public/-/emojis/1/flag_ps.png (renamed from app/assets/images/emoji/flag_ps.png)bin574 -> 574 bytes
-rw-r--r--public/-/emojis/1/flag_pt.png (renamed from app/assets/images/emoji/flag_pt.png)bin1055 -> 1055 bytes
-rw-r--r--public/-/emojis/1/flag_pw.png (renamed from app/assets/images/emoji/flag_pw.png)bin475 -> 475 bytes
-rw-r--r--public/-/emojis/1/flag_py.png (renamed from app/assets/images/emoji/flag_py.png)bin1085 -> 1085 bytes
-rw-r--r--public/-/emojis/1/flag_qa.png (renamed from app/assets/images/emoji/flag_qa.png)bin657 -> 657 bytes
-rw-r--r--public/-/emojis/1/flag_re.png (renamed from app/assets/images/emoji/flag_re.png)bin837 -> 837 bytes
-rw-r--r--public/-/emojis/1/flag_ro.png (renamed from app/assets/images/emoji/flag_ro.png)bin441 -> 441 bytes
-rw-r--r--public/-/emojis/1/flag_rs.png (renamed from app/assets/images/emoji/flag_rs.png)bin1237 -> 1237 bytes
-rw-r--r--public/-/emojis/1/flag_ru.png (renamed from app/assets/images/emoji/flag_ru.png)bin496 -> 496 bytes
-rw-r--r--public/-/emojis/1/flag_rw.png (renamed from app/assets/images/emoji/flag_rw.png)bin940 -> 940 bytes
-rw-r--r--public/-/emojis/1/flag_sa.png (renamed from app/assets/images/emoji/flag_sa.png)bin781 -> 781 bytes
-rw-r--r--public/-/emojis/1/flag_sb.png (renamed from app/assets/images/emoji/flag_sb.png)bin1102 -> 1102 bytes
-rw-r--r--public/-/emojis/1/flag_sc.png (renamed from app/assets/images/emoji/flag_sc.png)bin1073 -> 1073 bytes
-rw-r--r--public/-/emojis/1/flag_sd.png (renamed from app/assets/images/emoji/flag_sd.png)bin578 -> 578 bytes
-rw-r--r--public/-/emojis/1/flag_se.png (renamed from app/assets/images/emoji/flag_se.png)bin455 -> 455 bytes
-rw-r--r--public/-/emojis/1/flag_sg.png (renamed from app/assets/images/emoji/flag_sg.png)bin730 -> 730 bytes
-rw-r--r--public/-/emojis/1/flag_sh.png (renamed from app/assets/images/emoji/flag_sh.png)bin1369 -> 1369 bytes
-rw-r--r--public/-/emojis/1/flag_si.png (renamed from app/assets/images/emoji/flag_si.png)bin1030 -> 1030 bytes
-rw-r--r--public/-/emojis/1/flag_sj.png (renamed from app/assets/images/emoji/flag_sj.png)bin495 -> 495 bytes
-rw-r--r--public/-/emojis/1/flag_sk.png (renamed from app/assets/images/emoji/flag_sk.png)bin780 -> 780 bytes
-rw-r--r--public/-/emojis/1/flag_sl.png (renamed from app/assets/images/emoji/flag_sl.png)bin510 -> 510 bytes
-rw-r--r--public/-/emojis/1/flag_sm.png (renamed from app/assets/images/emoji/flag_sm.png)bin2000 -> 2000 bytes
-rw-r--r--public/-/emojis/1/flag_sn.png (renamed from app/assets/images/emoji/flag_sn.png)bin621 -> 621 bytes
-rw-r--r--public/-/emojis/1/flag_so.png (renamed from app/assets/images/emoji/flag_so.png)bin609 -> 609 bytes
-rw-r--r--public/-/emojis/1/flag_sr.png (renamed from app/assets/images/emoji/flag_sr.png)bin650 -> 650 bytes
-rw-r--r--public/-/emojis/1/flag_ss.png (renamed from app/assets/images/emoji/flag_ss.png)bin722 -> 722 bytes
-rw-r--r--public/-/emojis/1/flag_st.png (renamed from app/assets/images/emoji/flag_st.png)bin562 -> 562 bytes
-rw-r--r--public/-/emojis/1/flag_sv.png (renamed from app/assets/images/emoji/flag_sv.png)bin1125 -> 1125 bytes
-rw-r--r--public/-/emojis/1/flag_sx.png (renamed from app/assets/images/emoji/flag_sx.png)bin1195 -> 1195 bytes
-rw-r--r--public/-/emojis/1/flag_sy.png (renamed from app/assets/images/emoji/flag_sy.png)bin696 -> 696 bytes
-rw-r--r--public/-/emojis/1/flag_sz.png (renamed from app/assets/images/emoji/flag_sz.png)bin1102 -> 1102 bytes
-rw-r--r--public/-/emojis/1/flag_ta.png (renamed from app/assets/images/emoji/flag_ta.png)bin1907 -> 1907 bytes
-rw-r--r--public/-/emojis/1/flag_tc.png (renamed from app/assets/images/emoji/flag_tc.png)bin1538 -> 1538 bytes
-rw-r--r--public/-/emojis/1/flag_td.png (renamed from app/assets/images/emoji/flag_td.png)bin443 -> 443 bytes
-rw-r--r--public/-/emojis/1/flag_tf.png (renamed from app/assets/images/emoji/flag_tf.png)bin857 -> 857 bytes
-rw-r--r--public/-/emojis/1/flag_tg.png (renamed from app/assets/images/emoji/flag_tg.png)bin790 -> 790 bytes
-rw-r--r--public/-/emojis/1/flag_th.png (renamed from app/assets/images/emoji/flag_th.png)bin421 -> 421 bytes
-rw-r--r--public/-/emojis/1/flag_tj.png (renamed from app/assets/images/emoji/flag_tj.png)bin906 -> 906 bytes
-rw-r--r--public/-/emojis/1/flag_tk.png (renamed from app/assets/images/emoji/flag_tk.png)bin835 -> 835 bytes
-rw-r--r--public/-/emojis/1/flag_tl.png (renamed from app/assets/images/emoji/flag_tl.png)bin849 -> 849 bytes
-rw-r--r--public/-/emojis/1/flag_tm.png (renamed from app/assets/images/emoji/flag_tm.png)bin1178 -> 1178 bytes
-rw-r--r--public/-/emojis/1/flag_tn.png (renamed from app/assets/images/emoji/flag_tn.png)bin625 -> 625 bytes
-rw-r--r--public/-/emojis/1/flag_to.png (renamed from app/assets/images/emoji/flag_to.png)bin553 -> 553 bytes
-rw-r--r--public/-/emojis/1/flag_tr.png (renamed from app/assets/images/emoji/flag_tr.png)bin576 -> 576 bytes
-rw-r--r--public/-/emojis/1/flag_tt.png (renamed from app/assets/images/emoji/flag_tt.png)bin604 -> 604 bytes
-rw-r--r--public/-/emojis/1/flag_tv.png (renamed from app/assets/images/emoji/flag_tv.png)bin1120 -> 1120 bytes
-rw-r--r--public/-/emojis/1/flag_tw.png (renamed from app/assets/images/emoji/flag_tw.png)bin761 -> 761 bytes
-rw-r--r--public/-/emojis/1/flag_tz.png (renamed from app/assets/images/emoji/flag_tz.png)bin1061 -> 1061 bytes
-rw-r--r--public/-/emojis/1/flag_ua.png (renamed from app/assets/images/emoji/flag_ua.png)bin528 -> 528 bytes
-rw-r--r--public/-/emojis/1/flag_ug.png (renamed from app/assets/images/emoji/flag_ug.png)bin887 -> 887 bytes
-rw-r--r--public/-/emojis/1/flag_um.png (renamed from app/assets/images/emoji/flag_um.png)bin776 -> 776 bytes
-rw-r--r--public/-/emojis/1/flag_us.png (renamed from app/assets/images/emoji/flag_us.png)bin776 -> 776 bytes
-rw-r--r--public/-/emojis/1/flag_uy.png (renamed from app/assets/images/emoji/flag_uy.png)bin966 -> 966 bytes
-rw-r--r--public/-/emojis/1/flag_uz.png (renamed from app/assets/images/emoji/flag_uz.png)bin750 -> 750 bytes
-rw-r--r--public/-/emojis/1/flag_va.png (renamed from app/assets/images/emoji/flag_va.png)bin1331 -> 1331 bytes
-rw-r--r--public/-/emojis/1/flag_vc.png (renamed from app/assets/images/emoji/flag_vc.png)bin897 -> 897 bytes
-rw-r--r--public/-/emojis/1/flag_ve.png (renamed from app/assets/images/emoji/flag_ve.png)bin748 -> 748 bytes
-rw-r--r--public/-/emojis/1/flag_vg.png (renamed from app/assets/images/emoji/flag_vg.png)bin1789 -> 1789 bytes
-rw-r--r--public/-/emojis/1/flag_vi.png (renamed from app/assets/images/emoji/flag_vi.png)bin1378 -> 1378 bytes
-rw-r--r--public/-/emojis/1/flag_vn.png (renamed from app/assets/images/emoji/flag_vn.png)bin583 -> 583 bytes
-rw-r--r--public/-/emojis/1/flag_vu.png (renamed from app/assets/images/emoji/flag_vu.png)bin844 -> 844 bytes
-rw-r--r--public/-/emojis/1/flag_wf.png (renamed from app/assets/images/emoji/flag_wf.png)bin443 -> 443 bytes
-rw-r--r--public/-/emojis/1/flag_white.png (renamed from app/assets/images/emoji/flag_white.png)bin699 -> 699 bytes
-rw-r--r--public/-/emojis/1/flag_ws.png (renamed from app/assets/images/emoji/flag_ws.png)bin634 -> 634 bytes
-rw-r--r--public/-/emojis/1/flag_xk.png (renamed from app/assets/images/emoji/flag_xk.png)bin722 -> 722 bytes
-rw-r--r--public/-/emojis/1/flag_ye.png (renamed from app/assets/images/emoji/flag_ye.png)bin507 -> 507 bytes
-rw-r--r--public/-/emojis/1/flag_yt.png (renamed from app/assets/images/emoji/flag_yt.png)bin1623 -> 1623 bytes
-rw-r--r--public/-/emojis/1/flag_za.png (renamed from app/assets/images/emoji/flag_za.png)bin676 -> 676 bytes
-rw-r--r--public/-/emojis/1/flag_zm.png (renamed from app/assets/images/emoji/flag_zm.png)bin881 -> 881 bytes
-rw-r--r--public/-/emojis/1/flag_zw.png (renamed from app/assets/images/emoji/flag_zw.png)bin993 -> 993 bytes
-rw-r--r--public/-/emojis/1/flags.png (renamed from app/assets/images/emoji/flags.png)bin1722 -> 1722 bytes
-rw-r--r--public/-/emojis/1/flashlight.png (renamed from app/assets/images/emoji/flashlight.png)bin964 -> 964 bytes
-rw-r--r--public/-/emojis/1/fleur-de-lis.png (renamed from app/assets/images/emoji/fleur-de-lis.png)bin632 -> 632 bytes
-rw-r--r--public/-/emojis/1/floppy_disk.png (renamed from app/assets/images/emoji/floppy_disk.png)bin258 -> 258 bytes
-rw-r--r--public/-/emojis/1/flower_playing_cards.png (renamed from app/assets/images/emoji/flower_playing_cards.png)bin449 -> 449 bytes
-rw-r--r--public/-/emojis/1/flushed.png (renamed from app/assets/images/emoji/flushed.png)bin1127 -> 1127 bytes
-rw-r--r--public/-/emojis/1/fog.png (renamed from app/assets/images/emoji/fog.png)bin713 -> 713 bytes
-rw-r--r--public/-/emojis/1/foggy.png (renamed from app/assets/images/emoji/foggy.png)bin1069 -> 1069 bytes
-rw-r--r--public/-/emojis/1/football.png (renamed from app/assets/images/emoji/football.png)bin956 -> 956 bytes
-rw-r--r--public/-/emojis/1/footprints.png (renamed from app/assets/images/emoji/footprints.png)bin621 -> 621 bytes
-rw-r--r--public/-/emojis/1/fork_and_knife.png (renamed from app/assets/images/emoji/fork_and_knife.png)bin668 -> 668 bytes
-rw-r--r--public/-/emojis/1/fork_knife_plate.png (renamed from app/assets/images/emoji/fork_knife_plate.png)bin976 -> 976 bytes
-rw-r--r--public/-/emojis/1/fountain.png (renamed from app/assets/images/emoji/fountain.png)bin1768 -> 1768 bytes
-rw-r--r--public/-/emojis/1/four.png (renamed from app/assets/images/emoji/four.png)bin497 -> 497 bytes
-rw-r--r--public/-/emojis/1/four_leaf_clover.png (renamed from app/assets/images/emoji/four_leaf_clover.png)bin1156 -> 1156 bytes
-rw-r--r--public/-/emojis/1/fox.png (renamed from app/assets/images/emoji/fox.png)bin1556 -> 1556 bytes
-rw-r--r--public/-/emojis/1/frame_photo.png (renamed from app/assets/images/emoji/frame_photo.png)bin514 -> 514 bytes
-rw-r--r--public/-/emojis/1/free.png (renamed from app/assets/images/emoji/free.png)bin370 -> 370 bytes
-rw-r--r--public/-/emojis/1/french_bread.png (renamed from app/assets/images/emoji/french_bread.png)bin1551 -> 1551 bytes
-rw-r--r--public/-/emojis/1/fried_shrimp.png (renamed from app/assets/images/emoji/fried_shrimp.png)bin1241 -> 1241 bytes
-rw-r--r--public/-/emojis/1/fries.png (renamed from app/assets/images/emoji/fries.png)bin1873 -> 1873 bytes
-rw-r--r--public/-/emojis/1/frog.png (renamed from app/assets/images/emoji/frog.png)bin897 -> 897 bytes
-rw-r--r--public/-/emojis/1/frowning.png (renamed from app/assets/images/emoji/frowning.png)bin633 -> 633 bytes
-rw-r--r--public/-/emojis/1/frowning2.png (renamed from app/assets/images/emoji/frowning2.png)bin589 -> 589 bytes
-rw-r--r--public/-/emojis/1/fuelpump.png (renamed from app/assets/images/emoji/fuelpump.png)bin864 -> 864 bytes
-rw-r--r--public/-/emojis/1/full_moon.png (renamed from app/assets/images/emoji/full_moon.png)bin841 -> 841 bytes
-rw-r--r--public/-/emojis/1/full_moon_with_face.png (renamed from app/assets/images/emoji/full_moon_with_face.png)bin1186 -> 1186 bytes
-rw-r--r--public/-/emojis/1/game_die.png (renamed from app/assets/images/emoji/game_die.png)bin1136 -> 1136 bytes
-rw-r--r--public/-/emojis/1/gay_pride_flag.png (renamed from app/assets/images/emoji/gay_pride_flag.png)bin2340 -> 2340 bytes
-rw-r--r--public/-/emojis/1/gear.png (renamed from app/assets/images/emoji/gear.png)bin747 -> 747 bytes
-rw-r--r--public/-/emojis/1/gem.png (renamed from app/assets/images/emoji/gem.png)bin715 -> 715 bytes
-rw-r--r--public/-/emojis/1/gemini.png (renamed from app/assets/images/emoji/gemini.png)bin547 -> 547 bytes
-rw-r--r--public/-/emojis/1/ghost.png (renamed from app/assets/images/emoji/ghost.png)bin1465 -> 1465 bytes
-rw-r--r--public/-/emojis/1/gift.png (renamed from app/assets/images/emoji/gift.png)bin1966 -> 1966 bytes
-rw-r--r--public/-/emojis/1/gift_heart.png (renamed from app/assets/images/emoji/gift_heart.png)bin1141 -> 1141 bytes
-rw-r--r--public/-/emojis/1/girl.png (renamed from app/assets/images/emoji/girl.png)bin1261 -> 1261 bytes
-rw-r--r--public/-/emojis/1/girl_tone1.png (renamed from app/assets/images/emoji/girl_tone1.png)bin1259 -> 1259 bytes
-rw-r--r--public/-/emojis/1/girl_tone2.png (renamed from app/assets/images/emoji/girl_tone2.png)bin1255 -> 1255 bytes
-rw-r--r--public/-/emojis/1/girl_tone3.png (renamed from app/assets/images/emoji/girl_tone3.png)bin1255 -> 1255 bytes
-rw-r--r--public/-/emojis/1/girl_tone4.png (renamed from app/assets/images/emoji/girl_tone4.png)bin1241 -> 1241 bytes
-rw-r--r--public/-/emojis/1/girl_tone5.png (renamed from app/assets/images/emoji/girl_tone5.png)bin1245 -> 1245 bytes
-rw-r--r--public/-/emojis/1/globe_with_meridians.png (renamed from app/assets/images/emoji/globe_with_meridians.png)bin796 -> 796 bytes
-rw-r--r--public/-/emojis/1/goal.png (renamed from app/assets/images/emoji/goal.png)bin1242 -> 1242 bytes
-rw-r--r--public/-/emojis/1/goat.png (renamed from app/assets/images/emoji/goat.png)bin981 -> 981 bytes
-rw-r--r--public/-/emojis/1/golf.png (renamed from app/assets/images/emoji/golf.png)bin823 -> 823 bytes
-rw-r--r--public/-/emojis/1/golfer.png (renamed from app/assets/images/emoji/golfer.png)bin1189 -> 1189 bytes
-rw-r--r--public/-/emojis/1/gorilla.png (renamed from app/assets/images/emoji/gorilla.png)bin1090 -> 1090 bytes
-rw-r--r--public/-/emojis/1/grapes.png (renamed from app/assets/images/emoji/grapes.png)bin1552 -> 1552 bytes
-rw-r--r--public/-/emojis/1/green_apple.png (renamed from app/assets/images/emoji/green_apple.png)bin656 -> 656 bytes
-rw-r--r--public/-/emojis/1/green_book.png (renamed from app/assets/images/emoji/green_book.png)bin1366 -> 1366 bytes
-rw-r--r--public/-/emojis/1/green_heart.png (renamed from app/assets/images/emoji/green_heart.png)bin435 -> 435 bytes
-rw-r--r--public/-/emojis/1/grey_exclamation.png (renamed from app/assets/images/emoji/grey_exclamation.png)bin354 -> 354 bytes
-rw-r--r--public/-/emojis/1/grey_question.png (renamed from app/assets/images/emoji/grey_question.png)bin449 -> 449 bytes
-rw-r--r--public/-/emojis/1/grimacing.png (renamed from app/assets/images/emoji/grimacing.png)bin694 -> 694 bytes
-rw-r--r--public/-/emojis/1/grin.png (renamed from app/assets/images/emoji/grin.png)bin767 -> 767 bytes
-rw-r--r--public/-/emojis/1/grinning.png (renamed from app/assets/images/emoji/grinning.png)bin810 -> 810 bytes
-rw-r--r--public/-/emojis/1/guardsman.png (renamed from app/assets/images/emoji/guardsman.png)bin1140 -> 1140 bytes
-rw-r--r--public/-/emojis/1/guardsman_tone1.png (renamed from app/assets/images/emoji/guardsman_tone1.png)bin1122 -> 1122 bytes
-rw-r--r--public/-/emojis/1/guardsman_tone2.png (renamed from app/assets/images/emoji/guardsman_tone2.png)bin1160 -> 1160 bytes
-rw-r--r--public/-/emojis/1/guardsman_tone3.png (renamed from app/assets/images/emoji/guardsman_tone3.png)bin1160 -> 1160 bytes
-rw-r--r--public/-/emojis/1/guardsman_tone4.png (renamed from app/assets/images/emoji/guardsman_tone4.png)bin1157 -> 1157 bytes
-rw-r--r--public/-/emojis/1/guardsman_tone5.png (renamed from app/assets/images/emoji/guardsman_tone5.png)bin1165 -> 1165 bytes
-rw-r--r--public/-/emojis/1/guitar.png (renamed from app/assets/images/emoji/guitar.png)bin1056 -> 1056 bytes
-rw-r--r--public/-/emojis/1/gun.png (renamed from app/assets/images/emoji/gun.png)bin1859 -> 1859 bytes
-rw-r--r--public/-/emojis/1/haircut.png (renamed from app/assets/images/emoji/haircut.png)bin1935 -> 1935 bytes
-rw-r--r--public/-/emojis/1/haircut_tone1.png (renamed from app/assets/images/emoji/haircut_tone1.png)bin1945 -> 1945 bytes
-rw-r--r--public/-/emojis/1/haircut_tone2.png (renamed from app/assets/images/emoji/haircut_tone2.png)bin1935 -> 1935 bytes
-rw-r--r--public/-/emojis/1/haircut_tone3.png (renamed from app/assets/images/emoji/haircut_tone3.png)bin1923 -> 1923 bytes
-rw-r--r--public/-/emojis/1/haircut_tone4.png (renamed from app/assets/images/emoji/haircut_tone4.png)bin1904 -> 1904 bytes
-rw-r--r--public/-/emojis/1/haircut_tone5.png (renamed from app/assets/images/emoji/haircut_tone5.png)bin1920 -> 1920 bytes
-rw-r--r--public/-/emojis/1/hamburger.png (renamed from app/assets/images/emoji/hamburger.png)bin1973 -> 1973 bytes
-rw-r--r--public/-/emojis/1/hammer.png (renamed from app/assets/images/emoji/hammer.png)bin834 -> 834 bytes
-rw-r--r--public/-/emojis/1/hammer_pick.png (renamed from app/assets/images/emoji/hammer_pick.png)bin1068 -> 1068 bytes
-rw-r--r--public/-/emojis/1/hamster.png (renamed from app/assets/images/emoji/hamster.png)bin1279 -> 1279 bytes
-rw-r--r--public/-/emojis/1/hand_splayed.png (renamed from app/assets/images/emoji/hand_splayed.png)bin1081 -> 1081 bytes
-rw-r--r--public/-/emojis/1/hand_splayed_tone1.png (renamed from app/assets/images/emoji/hand_splayed_tone1.png)bin1081 -> 1081 bytes
-rw-r--r--public/-/emojis/1/hand_splayed_tone2.png (renamed from app/assets/images/emoji/hand_splayed_tone2.png)bin1081 -> 1081 bytes
-rw-r--r--public/-/emojis/1/hand_splayed_tone3.png (renamed from app/assets/images/emoji/hand_splayed_tone3.png)bin1081 -> 1081 bytes
-rw-r--r--public/-/emojis/1/hand_splayed_tone4.png (renamed from app/assets/images/emoji/hand_splayed_tone4.png)bin1081 -> 1081 bytes
-rw-r--r--public/-/emojis/1/hand_splayed_tone5.png (renamed from app/assets/images/emoji/hand_splayed_tone5.png)bin1081 -> 1081 bytes
-rw-r--r--public/-/emojis/1/handbag.png (renamed from app/assets/images/emoji/handbag.png)bin1285 -> 1285 bytes
-rw-r--r--public/-/emojis/1/handball.png (renamed from app/assets/images/emoji/handball.png)bin1634 -> 1634 bytes
-rw-r--r--public/-/emojis/1/handball_tone1.png (renamed from app/assets/images/emoji/handball_tone1.png)bin1645 -> 1645 bytes
-rw-r--r--public/-/emojis/1/handball_tone2.png (renamed from app/assets/images/emoji/handball_tone2.png)bin1628 -> 1628 bytes
-rw-r--r--public/-/emojis/1/handball_tone3.png (renamed from app/assets/images/emoji/handball_tone3.png)bin1639 -> 1639 bytes
-rw-r--r--public/-/emojis/1/handball_tone4.png (renamed from app/assets/images/emoji/handball_tone4.png)bin1634 -> 1634 bytes
-rw-r--r--public/-/emojis/1/handball_tone5.png (renamed from app/assets/images/emoji/handball_tone5.png)bin1606 -> 1606 bytes
-rw-r--r--public/-/emojis/1/handshake.png (renamed from app/assets/images/emoji/handshake.png)bin1366 -> 1366 bytes
-rw-r--r--public/-/emojis/1/handshake_tone1.png (renamed from app/assets/images/emoji/handshake_tone1.png)bin1381 -> 1381 bytes
-rw-r--r--public/-/emojis/1/handshake_tone2.png (renamed from app/assets/images/emoji/handshake_tone2.png)bin1381 -> 1381 bytes
-rw-r--r--public/-/emojis/1/handshake_tone3.png (renamed from app/assets/images/emoji/handshake_tone3.png)bin1381 -> 1381 bytes
-rw-r--r--public/-/emojis/1/handshake_tone4.png (renamed from app/assets/images/emoji/handshake_tone4.png)bin1381 -> 1381 bytes
-rw-r--r--public/-/emojis/1/handshake_tone5.png (renamed from app/assets/images/emoji/handshake_tone5.png)bin1381 -> 1381 bytes
-rw-r--r--public/-/emojis/1/hash.png (renamed from app/assets/images/emoji/hash.png)bin604 -> 604 bytes
-rw-r--r--public/-/emojis/1/hatched_chick.png (renamed from app/assets/images/emoji/hatched_chick.png)bin1174 -> 1174 bytes
-rw-r--r--public/-/emojis/1/hatching_chick.png (renamed from app/assets/images/emoji/hatching_chick.png)bin1598 -> 1598 bytes
-rw-r--r--public/-/emojis/1/head_bandage.png (renamed from app/assets/images/emoji/head_bandage.png)bin1199 -> 1199 bytes
-rw-r--r--public/-/emojis/1/headphones.png (renamed from app/assets/images/emoji/headphones.png)bin1202 -> 1202 bytes
-rw-r--r--public/-/emojis/1/hear_no_evil.png (renamed from app/assets/images/emoji/hear_no_evil.png)bin1210 -> 1210 bytes
-rw-r--r--public/-/emojis/1/heart.png (renamed from app/assets/images/emoji/heart.png)bin435 -> 435 bytes
-rw-r--r--public/-/emojis/1/heart_decoration.png (renamed from app/assets/images/emoji/heart_decoration.png)bin557 -> 557 bytes
-rw-r--r--public/-/emojis/1/heart_exclamation.png (renamed from app/assets/images/emoji/heart_exclamation.png)bin471 -> 471 bytes
-rw-r--r--public/-/emojis/1/heart_eyes.png (renamed from app/assets/images/emoji/heart_eyes.png)bin1069 -> 1069 bytes
-rw-r--r--public/-/emojis/1/heart_eyes_cat.png (renamed from app/assets/images/emoji/heart_eyes_cat.png)bin1512 -> 1512 bytes
-rw-r--r--public/-/emojis/1/heartbeat.png (renamed from app/assets/images/emoji/heartbeat.png)bin699 -> 699 bytes
-rw-r--r--public/-/emojis/1/heartpulse.png (renamed from app/assets/images/emoji/heartpulse.png)bin675 -> 675 bytes
-rw-r--r--public/-/emojis/1/hearts.png (renamed from app/assets/images/emoji/hearts.png)bin449 -> 449 bytes
-rw-r--r--public/-/emojis/1/heavy_check_mark.png (renamed from app/assets/images/emoji/heavy_check_mark.png)bin438 -> 438 bytes
-rw-r--r--public/-/emojis/1/heavy_division_sign.png (renamed from app/assets/images/emoji/heavy_division_sign.png)bin204 -> 204 bytes
-rw-r--r--public/-/emojis/1/heavy_dollar_sign.png (renamed from app/assets/images/emoji/heavy_dollar_sign.png)bin429 -> 429 bytes
-rw-r--r--public/-/emojis/1/heavy_minus_sign.png (renamed from app/assets/images/emoji/heavy_minus_sign.png)bin108 -> 108 bytes
-rw-r--r--public/-/emojis/1/heavy_multiplication_x.png (renamed from app/assets/images/emoji/heavy_multiplication_x.png)bin298 -> 298 bytes
-rw-r--r--public/-/emojis/1/heavy_plus_sign.png (renamed from app/assets/images/emoji/heavy_plus_sign.png)bin115 -> 115 bytes
-rw-r--r--public/-/emojis/1/helicopter.png (renamed from app/assets/images/emoji/helicopter.png)bin1098 -> 1098 bytes
-rw-r--r--public/-/emojis/1/helmet_with_cross.png (renamed from app/assets/images/emoji/helmet_with_cross.png)bin1014 -> 1014 bytes
-rw-r--r--public/-/emojis/1/herb.png (renamed from app/assets/images/emoji/herb.png)bin886 -> 886 bytes
-rw-r--r--public/-/emojis/1/hibiscus.png (renamed from app/assets/images/emoji/hibiscus.png)bin1815 -> 1815 bytes
-rw-r--r--public/-/emojis/1/high_brightness.png (renamed from app/assets/images/emoji/high_brightness.png)bin474 -> 474 bytes
-rw-r--r--public/-/emojis/1/high_heel.png (renamed from app/assets/images/emoji/high_heel.png)bin1008 -> 1008 bytes
-rw-r--r--public/-/emojis/1/hockey.png (renamed from app/assets/images/emoji/hockey.png)bin1010 -> 1010 bytes
-rw-r--r--public/-/emojis/1/hole.png (renamed from app/assets/images/emoji/hole.png)bin1390 -> 1390 bytes
-rw-r--r--public/-/emojis/1/homes.png (renamed from app/assets/images/emoji/homes.png)bin981 -> 981 bytes
-rw-r--r--public/-/emojis/1/honey_pot.png (renamed from app/assets/images/emoji/honey_pot.png)bin1217 -> 1217 bytes
-rw-r--r--public/-/emojis/1/horse.png (renamed from app/assets/images/emoji/horse.png)bin1694 -> 1694 bytes
-rw-r--r--public/-/emojis/1/horse_racing.png (renamed from app/assets/images/emoji/horse_racing.png)bin2096 -> 2096 bytes
-rw-r--r--public/-/emojis/1/horse_racing_tone1.png (renamed from app/assets/images/emoji/horse_racing_tone1.png)bin2099 -> 2099 bytes
-rw-r--r--public/-/emojis/1/horse_racing_tone2.png (renamed from app/assets/images/emoji/horse_racing_tone2.png)bin2103 -> 2103 bytes
-rw-r--r--public/-/emojis/1/horse_racing_tone3.png (renamed from app/assets/images/emoji/horse_racing_tone3.png)bin2090 -> 2090 bytes
-rw-r--r--public/-/emojis/1/horse_racing_tone4.png (renamed from app/assets/images/emoji/horse_racing_tone4.png)bin2090 -> 2090 bytes
-rw-r--r--public/-/emojis/1/horse_racing_tone5.png (renamed from app/assets/images/emoji/horse_racing_tone5.png)bin2085 -> 2085 bytes
-rw-r--r--public/-/emojis/1/hospital.png (renamed from app/assets/images/emoji/hospital.png)bin530 -> 530 bytes
-rw-r--r--public/-/emojis/1/hot_pepper.png (renamed from app/assets/images/emoji/hot_pepper.png)bin677 -> 677 bytes
-rw-r--r--public/-/emojis/1/hotdog.png (renamed from app/assets/images/emoji/hotdog.png)bin1770 -> 1770 bytes
-rw-r--r--public/-/emojis/1/hotel.png (renamed from app/assets/images/emoji/hotel.png)bin1322 -> 1322 bytes
-rw-r--r--public/-/emojis/1/hotsprings.png (renamed from app/assets/images/emoji/hotsprings.png)bin733 -> 733 bytes
-rw-r--r--public/-/emojis/1/hourglass.png (renamed from app/assets/images/emoji/hourglass.png)bin800 -> 800 bytes
-rw-r--r--public/-/emojis/1/hourglass_flowing_sand.png (renamed from app/assets/images/emoji/hourglass_flowing_sand.png)bin847 -> 847 bytes
-rw-r--r--public/-/emojis/1/house.png (renamed from app/assets/images/emoji/house.png)bin863 -> 863 bytes
-rw-r--r--public/-/emojis/1/house_abandoned.png (renamed from app/assets/images/emoji/house_abandoned.png)bin1606 -> 1606 bytes
-rw-r--r--public/-/emojis/1/house_with_garden.png (renamed from app/assets/images/emoji/house_with_garden.png)bin1613 -> 1613 bytes
-rw-r--r--public/-/emojis/1/hugging.png (renamed from app/assets/images/emoji/hugging.png)bin1425 -> 1425 bytes
-rw-r--r--public/-/emojis/1/hushed.png (renamed from app/assets/images/emoji/hushed.png)bin634 -> 634 bytes
-rw-r--r--public/-/emojis/1/ice_cream.png (renamed from app/assets/images/emoji/ice_cream.png)bin1779 -> 1779 bytes
-rw-r--r--public/-/emojis/1/ice_skate.png (renamed from app/assets/images/emoji/ice_skate.png)bin1574 -> 1574 bytes
-rw-r--r--public/-/emojis/1/icecream.png (renamed from app/assets/images/emoji/icecream.png)bin1496 -> 1496 bytes
-rw-r--r--public/-/emojis/1/id.png (renamed from app/assets/images/emoji/id.png)bin348 -> 348 bytes
-rw-r--r--public/-/emojis/1/ideograph_advantage.png (renamed from app/assets/images/emoji/ideograph_advantage.png)bin716 -> 716 bytes
-rw-r--r--public/-/emojis/1/imp.png (renamed from app/assets/images/emoji/imp.png)bin1988 -> 1988 bytes
-rw-r--r--public/-/emojis/1/inbox_tray.png (renamed from app/assets/images/emoji/inbox_tray.png)bin1029 -> 1029 bytes
-rw-r--r--public/-/emojis/1/incoming_envelope.png (renamed from app/assets/images/emoji/incoming_envelope.png)bin1129 -> 1129 bytes
-rw-r--r--public/-/emojis/1/information_desk_person.png (renamed from app/assets/images/emoji/information_desk_person.png)bin1580 -> 1580 bytes
-rw-r--r--public/-/emojis/1/information_desk_person_tone1.png (renamed from app/assets/images/emoji/information_desk_person_tone1.png)bin1597 -> 1597 bytes
-rw-r--r--public/-/emojis/1/information_desk_person_tone2.png (renamed from app/assets/images/emoji/information_desk_person_tone2.png)bin1590 -> 1590 bytes
-rw-r--r--public/-/emojis/1/information_desk_person_tone3.png (renamed from app/assets/images/emoji/information_desk_person_tone3.png)bin1580 -> 1580 bytes
-rw-r--r--public/-/emojis/1/information_desk_person_tone4.png (renamed from app/assets/images/emoji/information_desk_person_tone4.png)bin1572 -> 1572 bytes
-rw-r--r--public/-/emojis/1/information_desk_person_tone5.png (renamed from app/assets/images/emoji/information_desk_person_tone5.png)bin1588 -> 1588 bytes
-rw-r--r--public/-/emojis/1/information_source.png (renamed from app/assets/images/emoji/information_source.png)bin506 -> 506 bytes
-rw-r--r--public/-/emojis/1/innocent.png (renamed from app/assets/images/emoji/innocent.png)bin935 -> 935 bytes
-rw-r--r--public/-/emojis/1/interrobang.png (renamed from app/assets/images/emoji/interrobang.png)bin601 -> 601 bytes
-rw-r--r--public/-/emojis/1/iphone.png (renamed from app/assets/images/emoji/iphone.png)bin695 -> 695 bytes
-rw-r--r--public/-/emojis/1/island.png (renamed from app/assets/images/emoji/island.png)bin1273 -> 1273 bytes
-rw-r--r--public/-/emojis/1/izakaya_lantern.png (renamed from app/assets/images/emoji/izakaya_lantern.png)bin1227 -> 1227 bytes
-rw-r--r--public/-/emojis/1/jack_o_lantern.png (renamed from app/assets/images/emoji/jack_o_lantern.png)bin2289 -> 2289 bytes
-rw-r--r--public/-/emojis/1/japan.png (renamed from app/assets/images/emoji/japan.png)bin539 -> 539 bytes
-rw-r--r--public/-/emojis/1/japanese_castle.png (renamed from app/assets/images/emoji/japanese_castle.png)bin1404 -> 1404 bytes
-rw-r--r--public/-/emojis/1/japanese_goblin.png (renamed from app/assets/images/emoji/japanese_goblin.png)bin1561 -> 1561 bytes
-rw-r--r--public/-/emojis/1/japanese_ogre.png (renamed from app/assets/images/emoji/japanese_ogre.png)bin1864 -> 1864 bytes
-rw-r--r--public/-/emojis/1/jeans.png (renamed from app/assets/images/emoji/jeans.png)bin1158 -> 1158 bytes
-rw-r--r--public/-/emojis/1/joy.png (renamed from app/assets/images/emoji/joy.png)bin1136 -> 1136 bytes
-rw-r--r--public/-/emojis/1/joy_cat.png (renamed from app/assets/images/emoji/joy_cat.png)bin1633 -> 1633 bytes
-rw-r--r--public/-/emojis/1/joystick.png (renamed from app/assets/images/emoji/joystick.png)bin1039 -> 1039 bytes
-rw-r--r--public/-/emojis/1/juggling.png (renamed from app/assets/images/emoji/juggling.png)bin1165 -> 1165 bytes
-rw-r--r--public/-/emojis/1/juggling_tone1.png (renamed from app/assets/images/emoji/juggling_tone1.png)bin1171 -> 1171 bytes
-rw-r--r--public/-/emojis/1/juggling_tone2.png (renamed from app/assets/images/emoji/juggling_tone2.png)bin1160 -> 1160 bytes
-rw-r--r--public/-/emojis/1/juggling_tone3.png (renamed from app/assets/images/emoji/juggling_tone3.png)bin1170 -> 1170 bytes
-rw-r--r--public/-/emojis/1/juggling_tone4.png (renamed from app/assets/images/emoji/juggling_tone4.png)bin1167 -> 1167 bytes
-rw-r--r--public/-/emojis/1/juggling_tone5.png (renamed from app/assets/images/emoji/juggling_tone5.png)bin1161 -> 1161 bytes
-rw-r--r--public/-/emojis/1/kaaba.png (renamed from app/assets/images/emoji/kaaba.png)bin1251 -> 1251 bytes
-rw-r--r--public/-/emojis/1/key.png (renamed from app/assets/images/emoji/key.png)bin770 -> 770 bytes
-rw-r--r--public/-/emojis/1/key2.png (renamed from app/assets/images/emoji/key2.png)bin593 -> 593 bytes
-rw-r--r--public/-/emojis/1/keyboard.png (renamed from app/assets/images/emoji/keyboard.png)bin429 -> 429 bytes
-rw-r--r--public/-/emojis/1/kimono.png (renamed from app/assets/images/emoji/kimono.png)bin1527 -> 1527 bytes
-rw-r--r--public/-/emojis/1/kiss.png (renamed from app/assets/images/emoji/kiss.png)bin842 -> 842 bytes
-rw-r--r--public/-/emojis/1/kiss_mm.png (renamed from app/assets/images/emoji/kiss_mm.png)bin1269 -> 1269 bytes
-rw-r--r--public/-/emojis/1/kiss_ww.png (renamed from app/assets/images/emoji/kiss_ww.png)bin1149 -> 1149 bytes
-rw-r--r--public/-/emojis/1/kissing.png (renamed from app/assets/images/emoji/kissing.png)bin738 -> 738 bytes
-rw-r--r--public/-/emojis/1/kissing_cat.png (renamed from app/assets/images/emoji/kissing_cat.png)bin1468 -> 1468 bytes
-rw-r--r--public/-/emojis/1/kissing_closed_eyes.png (renamed from app/assets/images/emoji/kissing_closed_eyes.png)bin888 -> 888 bytes
-rw-r--r--public/-/emojis/1/kissing_heart.png (renamed from app/assets/images/emoji/kissing_heart.png)bin843 -> 843 bytes
-rw-r--r--public/-/emojis/1/kissing_smiling_eyes.png (renamed from app/assets/images/emoji/kissing_smiling_eyes.png)bin648 -> 648 bytes
-rw-r--r--public/-/emojis/1/kiwi.png (renamed from app/assets/images/emoji/kiwi.png)bin1892 -> 1892 bytes
-rw-r--r--public/-/emojis/1/knife.png (renamed from app/assets/images/emoji/knife.png)bin616 -> 616 bytes
-rw-r--r--public/-/emojis/1/koala.png (renamed from app/assets/images/emoji/koala.png)bin1428 -> 1428 bytes
-rw-r--r--public/-/emojis/1/koko.png (renamed from app/assets/images/emoji/koko.png)bin266 -> 266 bytes
-rw-r--r--public/-/emojis/1/label.png (renamed from app/assets/images/emoji/label.png)bin669 -> 669 bytes
-rw-r--r--public/-/emojis/1/large_blue_circle.png (renamed from app/assets/images/emoji/large_blue_circle.png)bin371 -> 371 bytes
-rw-r--r--public/-/emojis/1/large_blue_diamond.png (renamed from app/assets/images/emoji/large_blue_diamond.png)bin245 -> 245 bytes
-rw-r--r--public/-/emojis/1/large_orange_diamond.png (renamed from app/assets/images/emoji/large_orange_diamond.png)bin248 -> 248 bytes
-rw-r--r--public/-/emojis/1/last_quarter_moon.png (renamed from app/assets/images/emoji/last_quarter_moon.png)bin1180 -> 1180 bytes
-rw-r--r--public/-/emojis/1/last_quarter_moon_with_face.png (renamed from app/assets/images/emoji/last_quarter_moon_with_face.png)bin1030 -> 1030 bytes
-rw-r--r--public/-/emojis/1/laughing.png (renamed from app/assets/images/emoji/laughing.png)bin901 -> 901 bytes
-rw-r--r--public/-/emojis/1/leaves.png (renamed from app/assets/images/emoji/leaves.png)bin993 -> 993 bytes
-rw-r--r--public/-/emojis/1/ledger.png (renamed from app/assets/images/emoji/ledger.png)bin1528 -> 1528 bytes
-rw-r--r--public/-/emojis/1/left_facing_fist.png (renamed from app/assets/images/emoji/left_facing_fist.png)bin972 -> 972 bytes
-rw-r--r--public/-/emojis/1/left_facing_fist_tone1.png (renamed from app/assets/images/emoji/left_facing_fist_tone1.png)bin960 -> 960 bytes
-rw-r--r--public/-/emojis/1/left_facing_fist_tone2.png (renamed from app/assets/images/emoji/left_facing_fist_tone2.png)bin972 -> 972 bytes
-rw-r--r--public/-/emojis/1/left_facing_fist_tone3.png (renamed from app/assets/images/emoji/left_facing_fist_tone3.png)bin960 -> 960 bytes
-rw-r--r--public/-/emojis/1/left_facing_fist_tone4.png (renamed from app/assets/images/emoji/left_facing_fist_tone4.png)bin960 -> 960 bytes
-rw-r--r--public/-/emojis/1/left_facing_fist_tone5.png (renamed from app/assets/images/emoji/left_facing_fist_tone5.png)bin976 -> 976 bytes
-rw-r--r--public/-/emojis/1/left_luggage.png (renamed from app/assets/images/emoji/left_luggage.png)bin576 -> 576 bytes
-rw-r--r--public/-/emojis/1/left_right_arrow.png (renamed from app/assets/images/emoji/left_right_arrow.png)bin495 -> 495 bytes
-rw-r--r--public/-/emojis/1/leftwards_arrow_with_hook.png (renamed from app/assets/images/emoji/leftwards_arrow_with_hook.png)bin643 -> 643 bytes
-rw-r--r--public/-/emojis/1/lemon.png (renamed from app/assets/images/emoji/lemon.png)bin1033 -> 1033 bytes
-rw-r--r--public/-/emojis/1/leo.png (renamed from app/assets/images/emoji/leo.png)bin745 -> 745 bytes
-rw-r--r--public/-/emojis/1/leopard.png (renamed from app/assets/images/emoji/leopard.png)bin2222 -> 2222 bytes
-rw-r--r--public/-/emojis/1/level_slider.png (renamed from app/assets/images/emoji/level_slider.png)bin454 -> 454 bytes
-rw-r--r--public/-/emojis/1/levitate.png (renamed from app/assets/images/emoji/levitate.png)bin914 -> 914 bytes
-rw-r--r--public/-/emojis/1/libra.png (renamed from app/assets/images/emoji/libra.png)bin657 -> 657 bytes
-rw-r--r--public/-/emojis/1/lifter.png (renamed from app/assets/images/emoji/lifter.png)bin1356 -> 1356 bytes
-rw-r--r--public/-/emojis/1/lifter_tone1.png (renamed from app/assets/images/emoji/lifter_tone1.png)bin1346 -> 1346 bytes
-rw-r--r--public/-/emojis/1/lifter_tone2.png (renamed from app/assets/images/emoji/lifter_tone2.png)bin1347 -> 1347 bytes
-rw-r--r--public/-/emojis/1/lifter_tone3.png (renamed from app/assets/images/emoji/lifter_tone3.png)bin1339 -> 1339 bytes
-rw-r--r--public/-/emojis/1/lifter_tone4.png (renamed from app/assets/images/emoji/lifter_tone4.png)bin1343 -> 1343 bytes
-rw-r--r--public/-/emojis/1/lifter_tone5.png (renamed from app/assets/images/emoji/lifter_tone5.png)bin1337 -> 1337 bytes
-rw-r--r--public/-/emojis/1/light_rail.png (renamed from app/assets/images/emoji/light_rail.png)bin902 -> 902 bytes
-rw-r--r--public/-/emojis/1/link.png (renamed from app/assets/images/emoji/link.png)bin477 -> 477 bytes
-rw-r--r--public/-/emojis/1/lion_face.png (renamed from app/assets/images/emoji/lion_face.png)bin1728 -> 1728 bytes
-rw-r--r--public/-/emojis/1/lips.png (renamed from app/assets/images/emoji/lips.png)bin599 -> 599 bytes
-rw-r--r--public/-/emojis/1/lipstick.png (renamed from app/assets/images/emoji/lipstick.png)bin549 -> 549 bytes
-rw-r--r--public/-/emojis/1/lizard.png (renamed from app/assets/images/emoji/lizard.png)bin1709 -> 1709 bytes
-rw-r--r--public/-/emojis/1/lock.png (renamed from app/assets/images/emoji/lock.png)bin986 -> 986 bytes
-rw-r--r--public/-/emojis/1/lock_with_ink_pen.png (renamed from app/assets/images/emoji/lock_with_ink_pen.png)bin1123 -> 1123 bytes
-rw-r--r--public/-/emojis/1/lollipop.png (renamed from app/assets/images/emoji/lollipop.png)bin2164 -> 2164 bytes
-rw-r--r--public/-/emojis/1/loop.png (renamed from app/assets/images/emoji/loop.png)bin550 -> 550 bytes
-rw-r--r--public/-/emojis/1/loud_sound.png (renamed from app/assets/images/emoji/loud_sound.png)bin977 -> 977 bytes
-rw-r--r--public/-/emojis/1/loudspeaker.png (renamed from app/assets/images/emoji/loudspeaker.png)bin1316 -> 1316 bytes
-rw-r--r--public/-/emojis/1/love_hotel.png (renamed from app/assets/images/emoji/love_hotel.png)bin372 -> 372 bytes
-rw-r--r--public/-/emojis/1/love_letter.png (renamed from app/assets/images/emoji/love_letter.png)bin923 -> 923 bytes
-rw-r--r--public/-/emojis/1/low_brightness.png (renamed from app/assets/images/emoji/low_brightness.png)bin431 -> 431 bytes
-rw-r--r--public/-/emojis/1/lying_face.png (renamed from app/assets/images/emoji/lying_face.png)bin1103 -> 1103 bytes
-rw-r--r--public/-/emojis/1/m.png (renamed from app/assets/images/emoji/m.png)bin500 -> 500 bytes
-rw-r--r--public/-/emojis/1/mag.png (renamed from app/assets/images/emoji/mag.png)bin1240 -> 1240 bytes
-rw-r--r--public/-/emojis/1/mag_right.png (renamed from app/assets/images/emoji/mag_right.png)bin1251 -> 1251 bytes
-rw-r--r--public/-/emojis/1/mahjong.png (renamed from app/assets/images/emoji/mahjong.png)bin951 -> 951 bytes
-rw-r--r--public/-/emojis/1/mailbox.png (renamed from app/assets/images/emoji/mailbox.png)bin1166 -> 1166 bytes
-rw-r--r--public/-/emojis/1/mailbox_closed.png (renamed from app/assets/images/emoji/mailbox_closed.png)bin1192 -> 1192 bytes
-rw-r--r--public/-/emojis/1/mailbox_with_mail.png (renamed from app/assets/images/emoji/mailbox_with_mail.png)bin1307 -> 1307 bytes
-rw-r--r--public/-/emojis/1/mailbox_with_no_mail.png (renamed from app/assets/images/emoji/mailbox_with_no_mail.png)bin960 -> 960 bytes
-rw-r--r--public/-/emojis/1/man.png (renamed from app/assets/images/emoji/man.png)bin1092 -> 1092 bytes
-rw-r--r--public/-/emojis/1/man_dancing.png (renamed from app/assets/images/emoji/man_dancing.png)bin1400 -> 1400 bytes
-rw-r--r--public/-/emojis/1/man_dancing_tone1.png (renamed from app/assets/images/emoji/man_dancing_tone1.png)bin1404 -> 1404 bytes
-rw-r--r--public/-/emojis/1/man_dancing_tone2.png (renamed from app/assets/images/emoji/man_dancing_tone2.png)bin1402 -> 1402 bytes
-rw-r--r--public/-/emojis/1/man_dancing_tone3.png (renamed from app/assets/images/emoji/man_dancing_tone3.png)bin1409 -> 1409 bytes
-rw-r--r--public/-/emojis/1/man_dancing_tone4.png (renamed from app/assets/images/emoji/man_dancing_tone4.png)bin1421 -> 1421 bytes
-rw-r--r--public/-/emojis/1/man_dancing_tone5.png (renamed from app/assets/images/emoji/man_dancing_tone5.png)bin1418 -> 1418 bytes
-rw-r--r--public/-/emojis/1/man_in_tuxedo.png (renamed from app/assets/images/emoji/man_in_tuxedo.png)bin1307 -> 1307 bytes
-rw-r--r--public/-/emojis/1/man_in_tuxedo_tone1.png (renamed from app/assets/images/emoji/man_in_tuxedo_tone1.png)bin1307 -> 1307 bytes
-rw-r--r--public/-/emojis/1/man_in_tuxedo_tone2.png (renamed from app/assets/images/emoji/man_in_tuxedo_tone2.png)bin1307 -> 1307 bytes
-rw-r--r--public/-/emojis/1/man_in_tuxedo_tone3.png (renamed from app/assets/images/emoji/man_in_tuxedo_tone3.png)bin1307 -> 1307 bytes
-rw-r--r--public/-/emojis/1/man_in_tuxedo_tone4.png (renamed from app/assets/images/emoji/man_in_tuxedo_tone4.png)bin1307 -> 1307 bytes
-rw-r--r--public/-/emojis/1/man_in_tuxedo_tone5.png (renamed from app/assets/images/emoji/man_in_tuxedo_tone5.png)bin1302 -> 1302 bytes
-rw-r--r--public/-/emojis/1/man_tone1.png (renamed from app/assets/images/emoji/man_tone1.png)bin1069 -> 1069 bytes
-rw-r--r--public/-/emojis/1/man_tone2.png (renamed from app/assets/images/emoji/man_tone2.png)bin1069 -> 1069 bytes
-rw-r--r--public/-/emojis/1/man_tone3.png (renamed from app/assets/images/emoji/man_tone3.png)bin1069 -> 1069 bytes
-rw-r--r--public/-/emojis/1/man_tone4.png (renamed from app/assets/images/emoji/man_tone4.png)bin1069 -> 1069 bytes
-rw-r--r--public/-/emojis/1/man_tone5.png (renamed from app/assets/images/emoji/man_tone5.png)bin1087 -> 1087 bytes
-rw-r--r--public/-/emojis/1/man_with_gua_pi_mao.png (renamed from app/assets/images/emoji/man_with_gua_pi_mao.png)bin1339 -> 1339 bytes
-rw-r--r--public/-/emojis/1/man_with_gua_pi_mao_tone1.png (renamed from app/assets/images/emoji/man_with_gua_pi_mao_tone1.png)bin1328 -> 1328 bytes
-rw-r--r--public/-/emojis/1/man_with_gua_pi_mao_tone2.png (renamed from app/assets/images/emoji/man_with_gua_pi_mao_tone2.png)bin1332 -> 1332 bytes
-rw-r--r--public/-/emojis/1/man_with_gua_pi_mao_tone3.png (renamed from app/assets/images/emoji/man_with_gua_pi_mao_tone3.png)bin1329 -> 1329 bytes
-rw-r--r--public/-/emojis/1/man_with_gua_pi_mao_tone4.png (renamed from app/assets/images/emoji/man_with_gua_pi_mao_tone4.png)bin1325 -> 1325 bytes
-rw-r--r--public/-/emojis/1/man_with_gua_pi_mao_tone5.png (renamed from app/assets/images/emoji/man_with_gua_pi_mao_tone5.png)bin1337 -> 1337 bytes
-rw-r--r--public/-/emojis/1/man_with_turban.png (renamed from app/assets/images/emoji/man_with_turban.png)bin1618 -> 1618 bytes
-rw-r--r--public/-/emojis/1/man_with_turban_tone1.png (renamed from app/assets/images/emoji/man_with_turban_tone1.png)bin1584 -> 1584 bytes
-rw-r--r--public/-/emojis/1/man_with_turban_tone2.png (renamed from app/assets/images/emoji/man_with_turban_tone2.png)bin1588 -> 1588 bytes
-rw-r--r--public/-/emojis/1/man_with_turban_tone3.png (renamed from app/assets/images/emoji/man_with_turban_tone3.png)bin1584 -> 1584 bytes
-rw-r--r--public/-/emojis/1/man_with_turban_tone4.png (renamed from app/assets/images/emoji/man_with_turban_tone4.png)bin1583 -> 1583 bytes
-rw-r--r--public/-/emojis/1/man_with_turban_tone5.png (renamed from app/assets/images/emoji/man_with_turban_tone5.png)bin1605 -> 1605 bytes
-rw-r--r--public/-/emojis/1/mans_shoe.png (renamed from app/assets/images/emoji/mans_shoe.png)bin1649 -> 1649 bytes
-rw-r--r--public/-/emojis/1/map.png (renamed from app/assets/images/emoji/map.png)bin2352 -> 2352 bytes
-rw-r--r--public/-/emojis/1/maple_leaf.png (renamed from app/assets/images/emoji/maple_leaf.png)bin1117 -> 1117 bytes
-rw-r--r--public/-/emojis/1/martial_arts_uniform.png (renamed from app/assets/images/emoji/martial_arts_uniform.png)bin1412 -> 1412 bytes
-rw-r--r--public/-/emojis/1/mask.png (renamed from app/assets/images/emoji/mask.png)bin1322 -> 1322 bytes
-rw-r--r--public/-/emojis/1/massage.png (renamed from app/assets/images/emoji/massage.png)bin1571 -> 1571 bytes
-rw-r--r--public/-/emojis/1/massage_tone1.png (renamed from app/assets/images/emoji/massage_tone1.png)bin1578 -> 1578 bytes
-rw-r--r--public/-/emojis/1/massage_tone2.png (renamed from app/assets/images/emoji/massage_tone2.png)bin1565 -> 1565 bytes
-rw-r--r--public/-/emojis/1/massage_tone3.png (renamed from app/assets/images/emoji/massage_tone3.png)bin1553 -> 1553 bytes
-rw-r--r--public/-/emojis/1/massage_tone4.png (renamed from app/assets/images/emoji/massage_tone4.png)bin1546 -> 1546 bytes
-rw-r--r--public/-/emojis/1/massage_tone5.png (renamed from app/assets/images/emoji/massage_tone5.png)bin1557 -> 1557 bytes
-rw-r--r--public/-/emojis/1/meat_on_bone.png (renamed from app/assets/images/emoji/meat_on_bone.png)bin1465 -> 1465 bytes
-rw-r--r--public/-/emojis/1/medal.png (renamed from app/assets/images/emoji/medal.png)bin1700 -> 1700 bytes
-rw-r--r--public/-/emojis/1/mega.png (renamed from app/assets/images/emoji/mega.png)bin1751 -> 1751 bytes
-rw-r--r--public/-/emojis/1/melon.png (renamed from app/assets/images/emoji/melon.png)bin2005 -> 2005 bytes
-rw-r--r--public/-/emojis/1/menorah.png (renamed from app/assets/images/emoji/menorah.png)bin1279 -> 1279 bytes
-rw-r--r--public/-/emojis/1/mens.png (renamed from app/assets/images/emoji/mens.png)bin561 -> 561 bytes
-rw-r--r--public/-/emojis/1/metal.png (renamed from app/assets/images/emoji/metal.png)bin894 -> 894 bytes
-rw-r--r--public/-/emojis/1/metal_tone1.png (renamed from app/assets/images/emoji/metal_tone1.png)bin894 -> 894 bytes
-rw-r--r--public/-/emojis/1/metal_tone2.png (renamed from app/assets/images/emoji/metal_tone2.png)bin888 -> 888 bytes
-rw-r--r--public/-/emojis/1/metal_tone3.png (renamed from app/assets/images/emoji/metal_tone3.png)bin894 -> 894 bytes
-rw-r--r--public/-/emojis/1/metal_tone4.png (renamed from app/assets/images/emoji/metal_tone4.png)bin888 -> 888 bytes
-rw-r--r--public/-/emojis/1/metal_tone5.png (renamed from app/assets/images/emoji/metal_tone5.png)bin894 -> 894 bytes
-rw-r--r--public/-/emojis/1/metro.png (renamed from app/assets/images/emoji/metro.png)bin1020 -> 1020 bytes
-rw-r--r--public/-/emojis/1/microphone.png (renamed from app/assets/images/emoji/microphone.png)bin1165 -> 1165 bytes
-rw-r--r--public/-/emojis/1/microphone2.png (renamed from app/assets/images/emoji/microphone2.png)bin839 -> 839 bytes
-rw-r--r--public/-/emojis/1/microscope.png (renamed from app/assets/images/emoji/microscope.png)bin1113 -> 1113 bytes
-rw-r--r--public/-/emojis/1/middle_finger.png (renamed from app/assets/images/emoji/middle_finger.png)bin893 -> 893 bytes
-rw-r--r--public/-/emojis/1/middle_finger_tone1.png (renamed from app/assets/images/emoji/middle_finger_tone1.png)bin892 -> 892 bytes
-rw-r--r--public/-/emojis/1/middle_finger_tone2.png (renamed from app/assets/images/emoji/middle_finger_tone2.png)bin892 -> 892 bytes
-rw-r--r--public/-/emojis/1/middle_finger_tone3.png (renamed from app/assets/images/emoji/middle_finger_tone3.png)bin892 -> 892 bytes
-rw-r--r--public/-/emojis/1/middle_finger_tone4.png (renamed from app/assets/images/emoji/middle_finger_tone4.png)bin892 -> 892 bytes
-rw-r--r--public/-/emojis/1/middle_finger_tone5.png (renamed from app/assets/images/emoji/middle_finger_tone5.png)bin892 -> 892 bytes
-rw-r--r--public/-/emojis/1/military_medal.png (renamed from app/assets/images/emoji/military_medal.png)bin949 -> 949 bytes
-rw-r--r--public/-/emojis/1/milk.png (renamed from app/assets/images/emoji/milk.png)bin1224 -> 1224 bytes
-rw-r--r--public/-/emojis/1/milky_way.png (renamed from app/assets/images/emoji/milky_way.png)bin622 -> 622 bytes
-rw-r--r--public/-/emojis/1/minibus.png (renamed from app/assets/images/emoji/minibus.png)bin1256 -> 1256 bytes
-rw-r--r--public/-/emojis/1/minidisc.png (renamed from app/assets/images/emoji/minidisc.png)bin522 -> 522 bytes
-rw-r--r--public/-/emojis/1/mobile_phone_off.png (renamed from app/assets/images/emoji/mobile_phone_off.png)bin621 -> 621 bytes
-rw-r--r--public/-/emojis/1/money_mouth.png (renamed from app/assets/images/emoji/money_mouth.png)bin967 -> 967 bytes
-rw-r--r--public/-/emojis/1/money_with_wings.png (renamed from app/assets/images/emoji/money_with_wings.png)bin2327 -> 2327 bytes
-rw-r--r--public/-/emojis/1/moneybag.png (renamed from app/assets/images/emoji/moneybag.png)bin2310 -> 2310 bytes
-rw-r--r--public/-/emojis/1/monkey.png (renamed from app/assets/images/emoji/monkey.png)bin1348 -> 1348 bytes
-rw-r--r--public/-/emojis/1/monkey_face.png (renamed from app/assets/images/emoji/monkey_face.png)bin1022 -> 1022 bytes
-rw-r--r--public/-/emojis/1/monorail.png (renamed from app/assets/images/emoji/monorail.png)bin1068 -> 1068 bytes
-rw-r--r--public/-/emojis/1/mortar_board.png (renamed from app/assets/images/emoji/mortar_board.png)bin710 -> 710 bytes
-rw-r--r--public/-/emojis/1/mosque.png (renamed from app/assets/images/emoji/mosque.png)bin984 -> 984 bytes
-rw-r--r--public/-/emojis/1/motor_scooter.png (renamed from app/assets/images/emoji/motor_scooter.png)bin1207 -> 1207 bytes
-rw-r--r--public/-/emojis/1/motorboat.png (renamed from app/assets/images/emoji/motorboat.png)bin990 -> 990 bytes
-rw-r--r--public/-/emojis/1/motorcycle.png (renamed from app/assets/images/emoji/motorcycle.png)bin2081 -> 2081 bytes
-rw-r--r--public/-/emojis/1/motorway.png (renamed from app/assets/images/emoji/motorway.png)bin1102 -> 1102 bytes
-rw-r--r--public/-/emojis/1/mount_fuji.png (renamed from app/assets/images/emoji/mount_fuji.png)bin881 -> 881 bytes
-rw-r--r--public/-/emojis/1/mountain.png (renamed from app/assets/images/emoji/mountain.png)bin1409 -> 1409 bytes
-rw-r--r--public/-/emojis/1/mountain_bicyclist.png (renamed from app/assets/images/emoji/mountain_bicyclist.png)bin2288 -> 2288 bytes
-rw-r--r--public/-/emojis/1/mountain_bicyclist_tone1.png (renamed from app/assets/images/emoji/mountain_bicyclist_tone1.png)bin2294 -> 2294 bytes
-rw-r--r--public/-/emojis/1/mountain_bicyclist_tone2.png (renamed from app/assets/images/emoji/mountain_bicyclist_tone2.png)bin2298 -> 2298 bytes
-rw-r--r--public/-/emojis/1/mountain_bicyclist_tone3.png (renamed from app/assets/images/emoji/mountain_bicyclist_tone3.png)bin2284 -> 2284 bytes
-rw-r--r--public/-/emojis/1/mountain_bicyclist_tone4.png (renamed from app/assets/images/emoji/mountain_bicyclist_tone4.png)bin2288 -> 2288 bytes
-rw-r--r--public/-/emojis/1/mountain_bicyclist_tone5.png (renamed from app/assets/images/emoji/mountain_bicyclist_tone5.png)bin2281 -> 2281 bytes
-rw-r--r--public/-/emojis/1/mountain_cableway.png (renamed from app/assets/images/emoji/mountain_cableway.png)bin811 -> 811 bytes
-rw-r--r--public/-/emojis/1/mountain_railway.png (renamed from app/assets/images/emoji/mountain_railway.png)bin1317 -> 1317 bytes
-rw-r--r--public/-/emojis/1/mountain_snow.png (renamed from app/assets/images/emoji/mountain_snow.png)bin1193 -> 1193 bytes
-rw-r--r--public/-/emojis/1/mouse.png (renamed from app/assets/images/emoji/mouse.png)bin1245 -> 1245 bytes
-rw-r--r--public/-/emojis/1/mouse2.png (renamed from app/assets/images/emoji/mouse2.png)bin1324 -> 1324 bytes
-rw-r--r--public/-/emojis/1/mouse_three_button.png (renamed from app/assets/images/emoji/mouse_three_button.png)bin934 -> 934 bytes
-rw-r--r--public/-/emojis/1/movie_camera.png (renamed from app/assets/images/emoji/movie_camera.png)bin576 -> 576 bytes
-rw-r--r--public/-/emojis/1/moyai.png (renamed from app/assets/images/emoji/moyai.png)bin1593 -> 1593 bytes
-rw-r--r--public/-/emojis/1/mrs_claus.png (renamed from app/assets/images/emoji/mrs_claus.png)bin3338 -> 3338 bytes
-rw-r--r--public/-/emojis/1/mrs_claus_tone1.png (renamed from app/assets/images/emoji/mrs_claus_tone1.png)bin1999 -> 1999 bytes
-rw-r--r--public/-/emojis/1/mrs_claus_tone2.png (renamed from app/assets/images/emoji/mrs_claus_tone2.png)bin2006 -> 2006 bytes
-rw-r--r--public/-/emojis/1/mrs_claus_tone3.png (renamed from app/assets/images/emoji/mrs_claus_tone3.png)bin2017 -> 2017 bytes
-rw-r--r--public/-/emojis/1/mrs_claus_tone4.png (renamed from app/assets/images/emoji/mrs_claus_tone4.png)bin2016 -> 2016 bytes
-rw-r--r--public/-/emojis/1/mrs_claus_tone5.png (renamed from app/assets/images/emoji/mrs_claus_tone5.png)bin2016 -> 2016 bytes
-rw-r--r--public/-/emojis/1/muscle.png (renamed from app/assets/images/emoji/muscle.png)bin1012 -> 1012 bytes
-rw-r--r--public/-/emojis/1/muscle_tone1.png (renamed from app/assets/images/emoji/muscle_tone1.png)bin1012 -> 1012 bytes
-rw-r--r--public/-/emojis/1/muscle_tone2.png (renamed from app/assets/images/emoji/muscle_tone2.png)bin1012 -> 1012 bytes
-rw-r--r--public/-/emojis/1/muscle_tone3.png (renamed from app/assets/images/emoji/muscle_tone3.png)bin1012 -> 1012 bytes
-rw-r--r--public/-/emojis/1/muscle_tone4.png (renamed from app/assets/images/emoji/muscle_tone4.png)bin1012 -> 1012 bytes
-rw-r--r--public/-/emojis/1/muscle_tone5.png (renamed from app/assets/images/emoji/muscle_tone5.png)bin1012 -> 1012 bytes
-rw-r--r--public/-/emojis/1/mushroom.png (renamed from app/assets/images/emoji/mushroom.png)bin1024 -> 1024 bytes
-rw-r--r--public/-/emojis/1/musical_keyboard.png (renamed from app/assets/images/emoji/musical_keyboard.png)bin1695 -> 1695 bytes
-rw-r--r--public/-/emojis/1/musical_note.png (renamed from app/assets/images/emoji/musical_note.png)bin419 -> 419 bytes
-rw-r--r--public/-/emojis/1/musical_score.png (renamed from app/assets/images/emoji/musical_score.png)bin1289 -> 1289 bytes
-rw-r--r--public/-/emojis/1/mute.png (renamed from app/assets/images/emoji/mute.png)bin823 -> 823 bytes
-rw-r--r--public/-/emojis/1/nail_care.png (renamed from app/assets/images/emoji/nail_care.png)bin1639 -> 1639 bytes
-rw-r--r--public/-/emojis/1/nail_care_tone1.png (renamed from app/assets/images/emoji/nail_care_tone1.png)bin1712 -> 1712 bytes
-rw-r--r--public/-/emojis/1/nail_care_tone2.png (renamed from app/assets/images/emoji/nail_care_tone2.png)bin1711 -> 1711 bytes
-rw-r--r--public/-/emojis/1/nail_care_tone3.png (renamed from app/assets/images/emoji/nail_care_tone3.png)bin1727 -> 1727 bytes
-rw-r--r--public/-/emojis/1/nail_care_tone4.png (renamed from app/assets/images/emoji/nail_care_tone4.png)bin1728 -> 1728 bytes
-rw-r--r--public/-/emojis/1/nail_care_tone5.png (renamed from app/assets/images/emoji/nail_care_tone5.png)bin1716 -> 1716 bytes
-rw-r--r--public/-/emojis/1/name_badge.png (renamed from app/assets/images/emoji/name_badge.png)bin632 -> 632 bytes
-rw-r--r--public/-/emojis/1/nauseated_face.png (renamed from app/assets/images/emoji/nauseated_face.png)bin965 -> 965 bytes
-rw-r--r--public/-/emojis/1/necktie.png (renamed from app/assets/images/emoji/necktie.png)bin995 -> 995 bytes
-rw-r--r--public/-/emojis/1/negative_squared_cross_mark.png (renamed from app/assets/images/emoji/negative_squared_cross_mark.png)bin370 -> 370 bytes
-rw-r--r--public/-/emojis/1/nerd.png (renamed from app/assets/images/emoji/nerd.png)bin975 -> 975 bytes
-rw-r--r--public/-/emojis/1/neutral_face.png (renamed from app/assets/images/emoji/neutral_face.png)bin517 -> 517 bytes
-rw-r--r--public/-/emojis/1/new.png (renamed from app/assets/images/emoji/new.png)bin486 -> 486 bytes
-rw-r--r--public/-/emojis/1/new_moon.png (renamed from app/assets/images/emoji/new_moon.png)bin829 -> 829 bytes
-rw-r--r--public/-/emojis/1/new_moon_with_face.png (renamed from app/assets/images/emoji/new_moon_with_face.png)bin975 -> 975 bytes
-rw-r--r--public/-/emojis/1/newspaper.png (renamed from app/assets/images/emoji/newspaper.png)bin1178 -> 1178 bytes
-rw-r--r--public/-/emojis/1/newspaper2.png (renamed from app/assets/images/emoji/newspaper2.png)bin1046 -> 1046 bytes
-rw-r--r--public/-/emojis/1/ng.png (renamed from app/assets/images/emoji/ng.png)bin445 -> 445 bytes
-rw-r--r--public/-/emojis/1/night_with_stars.png (renamed from app/assets/images/emoji/night_with_stars.png)bin835 -> 835 bytes
-rw-r--r--public/-/emojis/1/nine.png (renamed from app/assets/images/emoji/nine.png)bin607 -> 607 bytes
-rw-r--r--public/-/emojis/1/no_bell.png (renamed from app/assets/images/emoji/no_bell.png)bin823 -> 823 bytes
-rw-r--r--public/-/emojis/1/no_bicycles.png (renamed from app/assets/images/emoji/no_bicycles.png)bin998 -> 998 bytes
-rw-r--r--public/-/emojis/1/no_entry.png (renamed from app/assets/images/emoji/no_entry.png)bin377 -> 377 bytes
-rw-r--r--public/-/emojis/1/no_entry_sign.png (renamed from app/assets/images/emoji/no_entry_sign.png)bin555 -> 555 bytes
-rw-r--r--public/-/emojis/1/no_good.png (renamed from app/assets/images/emoji/no_good.png)bin1750 -> 1750 bytes
-rw-r--r--public/-/emojis/1/no_good_tone1.png (renamed from app/assets/images/emoji/no_good_tone1.png)bin1767 -> 1767 bytes
-rw-r--r--public/-/emojis/1/no_good_tone2.png (renamed from app/assets/images/emoji/no_good_tone2.png)bin1756 -> 1756 bytes
-rw-r--r--public/-/emojis/1/no_good_tone3.png (renamed from app/assets/images/emoji/no_good_tone3.png)bin1766 -> 1766 bytes
-rw-r--r--public/-/emojis/1/no_good_tone4.png (renamed from app/assets/images/emoji/no_good_tone4.png)bin1782 -> 1782 bytes
-rw-r--r--public/-/emojis/1/no_good_tone5.png (renamed from app/assets/images/emoji/no_good_tone5.png)bin1784 -> 1784 bytes
-rw-r--r--public/-/emojis/1/no_mobile_phones.png (renamed from app/assets/images/emoji/no_mobile_phones.png)bin790 -> 790 bytes
-rw-r--r--public/-/emojis/1/no_mouth.png (renamed from app/assets/images/emoji/no_mouth.png)bin465 -> 465 bytes
-rw-r--r--public/-/emojis/1/no_pedestrians.png (renamed from app/assets/images/emoji/no_pedestrians.png)bin875 -> 875 bytes
-rw-r--r--public/-/emojis/1/no_smoking.png (renamed from app/assets/images/emoji/no_smoking.png)bin1136 -> 1136 bytes
-rw-r--r--public/-/emojis/1/non-potable_water.png (renamed from app/assets/images/emoji/non-potable_water.png)bin827 -> 827 bytes
-rw-r--r--public/-/emojis/1/nose.png (renamed from app/assets/images/emoji/nose.png)bin703 -> 703 bytes
-rw-r--r--public/-/emojis/1/nose_tone1.png (renamed from app/assets/images/emoji/nose_tone1.png)bin703 -> 703 bytes
-rw-r--r--public/-/emojis/1/nose_tone2.png (renamed from app/assets/images/emoji/nose_tone2.png)bin703 -> 703 bytes
-rw-r--r--public/-/emojis/1/nose_tone3.png (renamed from app/assets/images/emoji/nose_tone3.png)bin703 -> 703 bytes
-rw-r--r--public/-/emojis/1/nose_tone4.png (renamed from app/assets/images/emoji/nose_tone4.png)bin703 -> 703 bytes
-rw-r--r--public/-/emojis/1/nose_tone5.png (renamed from app/assets/images/emoji/nose_tone5.png)bin703 -> 703 bytes
-rw-r--r--public/-/emojis/1/notebook.png (renamed from app/assets/images/emoji/notebook.png)bin1215 -> 1215 bytes
-rw-r--r--public/-/emojis/1/notebook_with_decorative_cover.png (renamed from app/assets/images/emoji/notebook_with_decorative_cover.png)bin1782 -> 1782 bytes
-rw-r--r--public/-/emojis/1/notepad_spiral.png (renamed from app/assets/images/emoji/notepad_spiral.png)bin1377 -> 1377 bytes
-rw-r--r--public/-/emojis/1/notes.png (renamed from app/assets/images/emoji/notes.png)bin501 -> 501 bytes
-rw-r--r--public/-/emojis/1/nut_and_bolt.png (renamed from app/assets/images/emoji/nut_and_bolt.png)bin899 -> 899 bytes
-rw-r--r--public/-/emojis/1/o.png (renamed from app/assets/images/emoji/o.png)bin475 -> 475 bytes
-rw-r--r--public/-/emojis/1/o2.png (renamed from app/assets/images/emoji/o2.png)bin425 -> 425 bytes
-rw-r--r--public/-/emojis/1/ocean.png (renamed from app/assets/images/emoji/ocean.png)bin1018 -> 1018 bytes
-rw-r--r--public/-/emojis/1/octagonal_sign.png (renamed from app/assets/images/emoji/octagonal_sign.png)bin260 -> 260 bytes
-rw-r--r--public/-/emojis/1/octopus.png (renamed from app/assets/images/emoji/octopus.png)bin1188 -> 1188 bytes
-rw-r--r--public/-/emojis/1/oden.png (renamed from app/assets/images/emoji/oden.png)bin794 -> 794 bytes
-rw-r--r--public/-/emojis/1/office.png (renamed from app/assets/images/emoji/office.png)bin524 -> 524 bytes
-rw-r--r--public/-/emojis/1/oil.png (renamed from app/assets/images/emoji/oil.png)bin674 -> 674 bytes
-rw-r--r--public/-/emojis/1/ok.png (renamed from app/assets/images/emoji/ok.png)bin511 -> 511 bytes
-rw-r--r--public/-/emojis/1/ok_hand.png (renamed from app/assets/images/emoji/ok_hand.png)bin979 -> 979 bytes
-rw-r--r--public/-/emojis/1/ok_hand_tone1.png (renamed from app/assets/images/emoji/ok_hand_tone1.png)bin979 -> 979 bytes
-rw-r--r--public/-/emojis/1/ok_hand_tone2.png (renamed from app/assets/images/emoji/ok_hand_tone2.png)bin979 -> 979 bytes
-rw-r--r--public/-/emojis/1/ok_hand_tone3.png (renamed from app/assets/images/emoji/ok_hand_tone3.png)bin979 -> 979 bytes
-rw-r--r--public/-/emojis/1/ok_hand_tone4.png (renamed from app/assets/images/emoji/ok_hand_tone4.png)bin979 -> 979 bytes
-rw-r--r--public/-/emojis/1/ok_hand_tone5.png (renamed from app/assets/images/emoji/ok_hand_tone5.png)bin979 -> 979 bytes
-rw-r--r--public/-/emojis/1/ok_woman.png (renamed from app/assets/images/emoji/ok_woman.png)bin1696 -> 1696 bytes
-rw-r--r--public/-/emojis/1/ok_woman_tone1.png (renamed from app/assets/images/emoji/ok_woman_tone1.png)bin1696 -> 1696 bytes
-rw-r--r--public/-/emojis/1/ok_woman_tone2.png (renamed from app/assets/images/emoji/ok_woman_tone2.png)bin1694 -> 1694 bytes
-rw-r--r--public/-/emojis/1/ok_woman_tone3.png (renamed from app/assets/images/emoji/ok_woman_tone3.png)bin1675 -> 1675 bytes
-rw-r--r--public/-/emojis/1/ok_woman_tone4.png (renamed from app/assets/images/emoji/ok_woman_tone4.png)bin1684 -> 1684 bytes
-rw-r--r--public/-/emojis/1/ok_woman_tone5.png (renamed from app/assets/images/emoji/ok_woman_tone5.png)bin1696 -> 1696 bytes
-rw-r--r--public/-/emojis/1/older_man.png (renamed from app/assets/images/emoji/older_man.png)bin1253 -> 1253 bytes
-rw-r--r--public/-/emojis/1/older_man_tone1.png (renamed from app/assets/images/emoji/older_man_tone1.png)bin1253 -> 1253 bytes
-rw-r--r--public/-/emojis/1/older_man_tone2.png (renamed from app/assets/images/emoji/older_man_tone2.png)bin1253 -> 1253 bytes
-rw-r--r--public/-/emojis/1/older_man_tone3.png (renamed from app/assets/images/emoji/older_man_tone3.png)bin1253 -> 1253 bytes
-rw-r--r--public/-/emojis/1/older_man_tone4.png (renamed from app/assets/images/emoji/older_man_tone4.png)bin1254 -> 1254 bytes
-rw-r--r--public/-/emojis/1/older_man_tone5.png (renamed from app/assets/images/emoji/older_man_tone5.png)bin1254 -> 1254 bytes
-rw-r--r--public/-/emojis/1/older_woman.png (renamed from app/assets/images/emoji/older_woman.png)bin1472 -> 1472 bytes
-rw-r--r--public/-/emojis/1/older_woman_tone1.png (renamed from app/assets/images/emoji/older_woman_tone1.png)bin1562 -> 1562 bytes
-rw-r--r--public/-/emojis/1/older_woman_tone2.png (renamed from app/assets/images/emoji/older_woman_tone2.png)bin1564 -> 1564 bytes
-rw-r--r--public/-/emojis/1/older_woman_tone3.png (renamed from app/assets/images/emoji/older_woman_tone3.png)bin1555 -> 1555 bytes
-rw-r--r--public/-/emojis/1/older_woman_tone4.png (renamed from app/assets/images/emoji/older_woman_tone4.png)bin1562 -> 1562 bytes
-rw-r--r--public/-/emojis/1/older_woman_tone5.png (renamed from app/assets/images/emoji/older_woman_tone5.png)bin1544 -> 1544 bytes
-rw-r--r--public/-/emojis/1/om_symbol.png (renamed from app/assets/images/emoji/om_symbol.png)bin773 -> 773 bytes
-rw-r--r--public/-/emojis/1/on.png (renamed from app/assets/images/emoji/on.png)bin459 -> 459 bytes
-rw-r--r--public/-/emojis/1/oncoming_automobile.png (renamed from app/assets/images/emoji/oncoming_automobile.png)bin1238 -> 1238 bytes
-rw-r--r--public/-/emojis/1/oncoming_bus.png (renamed from app/assets/images/emoji/oncoming_bus.png)bin964 -> 964 bytes
-rw-r--r--public/-/emojis/1/oncoming_police_car.png (renamed from app/assets/images/emoji/oncoming_police_car.png)bin1547 -> 1547 bytes
-rw-r--r--public/-/emojis/1/oncoming_taxi.png (renamed from app/assets/images/emoji/oncoming_taxi.png)bin1405 -> 1405 bytes
-rw-r--r--public/-/emojis/1/one.png (renamed from app/assets/images/emoji/one.png)bin442 -> 442 bytes
-rw-r--r--public/-/emojis/1/open_file_folder.png (renamed from app/assets/images/emoji/open_file_folder.png)bin755 -> 755 bytes
-rw-r--r--public/-/emojis/1/open_hands.png (renamed from app/assets/images/emoji/open_hands.png)bin1053 -> 1053 bytes
-rw-r--r--public/-/emojis/1/open_hands_tone1.png (renamed from app/assets/images/emoji/open_hands_tone1.png)bin1053 -> 1053 bytes
-rw-r--r--public/-/emojis/1/open_hands_tone2.png (renamed from app/assets/images/emoji/open_hands_tone2.png)bin1053 -> 1053 bytes
-rw-r--r--public/-/emojis/1/open_hands_tone3.png (renamed from app/assets/images/emoji/open_hands_tone3.png)bin1053 -> 1053 bytes
-rw-r--r--public/-/emojis/1/open_hands_tone4.png (renamed from app/assets/images/emoji/open_hands_tone4.png)bin1053 -> 1053 bytes
-rw-r--r--public/-/emojis/1/open_hands_tone5.png (renamed from app/assets/images/emoji/open_hands_tone5.png)bin1053 -> 1053 bytes
-rw-r--r--public/-/emojis/1/open_mouth.png (renamed from app/assets/images/emoji/open_mouth.png)bin575 -> 575 bytes
-rw-r--r--public/-/emojis/1/ophiuchus.png (renamed from app/assets/images/emoji/ophiuchus.png)bin723 -> 723 bytes
-rw-r--r--public/-/emojis/1/orange_book.png (renamed from app/assets/images/emoji/orange_book.png)bin1329 -> 1329 bytes
-rw-r--r--public/-/emojis/1/orthodox_cross.png (renamed from app/assets/images/emoji/orthodox_cross.png)bin239 -> 239 bytes
-rw-r--r--public/-/emojis/1/outbox_tray.png (renamed from app/assets/images/emoji/outbox_tray.png)bin1002 -> 1002 bytes
-rw-r--r--public/-/emojis/1/owl.png (renamed from app/assets/images/emoji/owl.png)bin2045 -> 2045 bytes
-rw-r--r--public/-/emojis/1/ox.png (renamed from app/assets/images/emoji/ox.png)bin1436 -> 1436 bytes
-rw-r--r--public/-/emojis/1/package.png (renamed from app/assets/images/emoji/package.png)bin950 -> 950 bytes
-rw-r--r--public/-/emojis/1/page_facing_up.png (renamed from app/assets/images/emoji/page_facing_up.png)bin1110 -> 1110 bytes
-rw-r--r--public/-/emojis/1/page_with_curl.png (renamed from app/assets/images/emoji/page_with_curl.png)bin1157 -> 1157 bytes
-rw-r--r--public/-/emojis/1/pager.png (renamed from app/assets/images/emoji/pager.png)bin553 -> 553 bytes
-rw-r--r--public/-/emojis/1/paintbrush.png (renamed from app/assets/images/emoji/paintbrush.png)bin950 -> 950 bytes
-rw-r--r--public/-/emojis/1/palm_tree.png (renamed from app/assets/images/emoji/palm_tree.png)bin1450 -> 1450 bytes
-rw-r--r--public/-/emojis/1/pancakes.png (renamed from app/assets/images/emoji/pancakes.png)bin3661 -> 3661 bytes
-rw-r--r--public/-/emojis/1/panda_face.png (renamed from app/assets/images/emoji/panda_face.png)bin1478 -> 1478 bytes
-rw-r--r--public/-/emojis/1/paperclip.png (renamed from app/assets/images/emoji/paperclip.png)bin439 -> 439 bytes
-rw-r--r--public/-/emojis/1/paperclips.png (renamed from app/assets/images/emoji/paperclips.png)bin642 -> 642 bytes
-rw-r--r--public/-/emojis/1/park.png (renamed from app/assets/images/emoji/park.png)bin929 -> 929 bytes
-rw-r--r--public/-/emojis/1/parking.png (renamed from app/assets/images/emoji/parking.png)bin385 -> 385 bytes
-rw-r--r--public/-/emojis/1/part_alternation_mark.png (renamed from app/assets/images/emoji/part_alternation_mark.png)bin521 -> 521 bytes
-rw-r--r--public/-/emojis/1/partly_sunny.png (renamed from app/assets/images/emoji/partly_sunny.png)bin977 -> 977 bytes
-rw-r--r--public/-/emojis/1/passport_control.png (renamed from app/assets/images/emoji/passport_control.png)bin683 -> 683 bytes
-rw-r--r--public/-/emojis/1/pause_button.png (renamed from app/assets/images/emoji/pause_button.png)bin395 -> 395 bytes
-rw-r--r--public/-/emojis/1/peace.png (renamed from app/assets/images/emoji/peace.png)bin933 -> 933 bytes
-rw-r--r--public/-/emojis/1/peach.png (renamed from app/assets/images/emoji/peach.png)bin1189 -> 1189 bytes
-rw-r--r--public/-/emojis/1/peanuts.png (renamed from app/assets/images/emoji/peanuts.png)bin3266 -> 3266 bytes
-rw-r--r--public/-/emojis/1/pear.png (renamed from app/assets/images/emoji/pear.png)bin747 -> 747 bytes
-rw-r--r--public/-/emojis/1/pen_ballpoint.png (renamed from app/assets/images/emoji/pen_ballpoint.png)bin696 -> 696 bytes
-rw-r--r--public/-/emojis/1/pen_fountain.png (renamed from app/assets/images/emoji/pen_fountain.png)bin623 -> 623 bytes
-rw-r--r--public/-/emojis/1/pencil.png (renamed from app/assets/images/emoji/pencil.png)bin1624 -> 1624 bytes
-rw-r--r--public/-/emojis/1/pencil2.png (renamed from app/assets/images/emoji/pencil2.png)bin654 -> 654 bytes
-rw-r--r--public/-/emojis/1/penguin.png (renamed from app/assets/images/emoji/penguin.png)bin1034 -> 1034 bytes
-rw-r--r--public/-/emojis/1/pensive.png (renamed from app/assets/images/emoji/pensive.png)bin718 -> 718 bytes
-rw-r--r--public/-/emojis/1/performing_arts.png (renamed from app/assets/images/emoji/performing_arts.png)bin1971 -> 1971 bytes
-rw-r--r--public/-/emojis/1/persevere.png (renamed from app/assets/images/emoji/persevere.png)bin891 -> 891 bytes
-rw-r--r--public/-/emojis/1/person_frowning.png (renamed from app/assets/images/emoji/person_frowning.png)bin1148 -> 1148 bytes
-rw-r--r--public/-/emojis/1/person_frowning_tone1.png (renamed from app/assets/images/emoji/person_frowning_tone1.png)bin1141 -> 1141 bytes
-rw-r--r--public/-/emojis/1/person_frowning_tone2.png (renamed from app/assets/images/emoji/person_frowning_tone2.png)bin1141 -> 1141 bytes
-rw-r--r--public/-/emojis/1/person_frowning_tone3.png (renamed from app/assets/images/emoji/person_frowning_tone3.png)bin1141 -> 1141 bytes
-rw-r--r--public/-/emojis/1/person_frowning_tone4.png (renamed from app/assets/images/emoji/person_frowning_tone4.png)bin1109 -> 1109 bytes
-rw-r--r--public/-/emojis/1/person_frowning_tone5.png (renamed from app/assets/images/emoji/person_frowning_tone5.png)bin1114 -> 1114 bytes
-rw-r--r--public/-/emojis/1/person_with_blond_hair.png (renamed from app/assets/images/emoji/person_with_blond_hair.png)bin1205 -> 1205 bytes
-rw-r--r--public/-/emojis/1/person_with_blond_hair_tone1.png (renamed from app/assets/images/emoji/person_with_blond_hair_tone1.png)bin1181 -> 1181 bytes
-rw-r--r--public/-/emojis/1/person_with_blond_hair_tone2.png (renamed from app/assets/images/emoji/person_with_blond_hair_tone2.png)bin1181 -> 1181 bytes
-rw-r--r--public/-/emojis/1/person_with_blond_hair_tone3.png (renamed from app/assets/images/emoji/person_with_blond_hair_tone3.png)bin1181 -> 1181 bytes
-rw-r--r--public/-/emojis/1/person_with_blond_hair_tone4.png (renamed from app/assets/images/emoji/person_with_blond_hair_tone4.png)bin1189 -> 1189 bytes
-rw-r--r--public/-/emojis/1/person_with_blond_hair_tone5.png (renamed from app/assets/images/emoji/person_with_blond_hair_tone5.png)bin1214 -> 1214 bytes
-rw-r--r--public/-/emojis/1/person_with_pouting_face.png (renamed from app/assets/images/emoji/person_with_pouting_face.png)bin1297 -> 1297 bytes
-rw-r--r--public/-/emojis/1/person_with_pouting_face_tone1.png (renamed from app/assets/images/emoji/person_with_pouting_face_tone1.png)bin1309 -> 1309 bytes
-rw-r--r--public/-/emojis/1/person_with_pouting_face_tone2.png (renamed from app/assets/images/emoji/person_with_pouting_face_tone2.png)bin1292 -> 1292 bytes
-rw-r--r--public/-/emojis/1/person_with_pouting_face_tone3.png (renamed from app/assets/images/emoji/person_with_pouting_face_tone3.png)bin1305 -> 1305 bytes
-rw-r--r--public/-/emojis/1/person_with_pouting_face_tone4.png (renamed from app/assets/images/emoji/person_with_pouting_face_tone4.png)bin1296 -> 1296 bytes
-rw-r--r--public/-/emojis/1/person_with_pouting_face_tone5.png (renamed from app/assets/images/emoji/person_with_pouting_face_tone5.png)bin1303 -> 1303 bytes
-rw-r--r--public/-/emojis/1/pick.png (renamed from app/assets/images/emoji/pick.png)bin1023 -> 1023 bytes
-rw-r--r--public/-/emojis/1/pig.png (renamed from app/assets/images/emoji/pig.png)bin1138 -> 1138 bytes
-rw-r--r--public/-/emojis/1/pig2.png (renamed from app/assets/images/emoji/pig2.png)bin1548 -> 1548 bytes
-rw-r--r--public/-/emojis/1/pig_nose.png (renamed from app/assets/images/emoji/pig_nose.png)bin820 -> 820 bytes
-rw-r--r--public/-/emojis/1/pill.png (renamed from app/assets/images/emoji/pill.png)bin442 -> 442 bytes
-rw-r--r--public/-/emojis/1/pineapple.png (renamed from app/assets/images/emoji/pineapple.png)bin1642 -> 1642 bytes
-rw-r--r--public/-/emojis/1/ping_pong.png (renamed from app/assets/images/emoji/ping_pong.png)bin823 -> 823 bytes
-rw-r--r--public/-/emojis/1/pisces.png (renamed from app/assets/images/emoji/pisces.png)bin678 -> 678 bytes
-rw-r--r--public/-/emojis/1/pizza.png (renamed from app/assets/images/emoji/pizza.png)bin2008 -> 2008 bytes
-rw-r--r--public/-/emojis/1/place_of_worship.png (renamed from app/assets/images/emoji/place_of_worship.png)bin487 -> 487 bytes
-rw-r--r--public/-/emojis/1/play_pause.png (renamed from app/assets/images/emoji/play_pause.png)bin509 -> 509 bytes
-rw-r--r--public/-/emojis/1/point_down.png (renamed from app/assets/images/emoji/point_down.png)bin853 -> 853 bytes
-rw-r--r--public/-/emojis/1/point_down_tone1.png (renamed from app/assets/images/emoji/point_down_tone1.png)bin856 -> 856 bytes
-rw-r--r--public/-/emojis/1/point_down_tone2.png (renamed from app/assets/images/emoji/point_down_tone2.png)bin856 -> 856 bytes
-rw-r--r--public/-/emojis/1/point_down_tone3.png (renamed from app/assets/images/emoji/point_down_tone3.png)bin858 -> 858 bytes
-rw-r--r--public/-/emojis/1/point_down_tone4.png (renamed from app/assets/images/emoji/point_down_tone4.png)bin856 -> 856 bytes
-rw-r--r--public/-/emojis/1/point_down_tone5.png (renamed from app/assets/images/emoji/point_down_tone5.png)bin856 -> 856 bytes
-rw-r--r--public/-/emojis/1/point_left.png (renamed from app/assets/images/emoji/point_left.png)bin825 -> 825 bytes
-rw-r--r--public/-/emojis/1/point_left_tone1.png (renamed from app/assets/images/emoji/point_left_tone1.png)bin832 -> 832 bytes
-rw-r--r--public/-/emojis/1/point_left_tone2.png (renamed from app/assets/images/emoji/point_left_tone2.png)bin830 -> 830 bytes
-rw-r--r--public/-/emojis/1/point_left_tone3.png (renamed from app/assets/images/emoji/point_left_tone3.png)bin830 -> 830 bytes
-rw-r--r--public/-/emojis/1/point_left_tone4.png (renamed from app/assets/images/emoji/point_left_tone4.png)bin830 -> 830 bytes
-rw-r--r--public/-/emojis/1/point_left_tone5.png (renamed from app/assets/images/emoji/point_left_tone5.png)bin832 -> 832 bytes
-rw-r--r--public/-/emojis/1/point_right.png (renamed from app/assets/images/emoji/point_right.png)bin805 -> 805 bytes
-rw-r--r--public/-/emojis/1/point_right_tone1.png (renamed from app/assets/images/emoji/point_right_tone1.png)bin805 -> 805 bytes
-rw-r--r--public/-/emojis/1/point_right_tone2.png (renamed from app/assets/images/emoji/point_right_tone2.png)bin805 -> 805 bytes
-rw-r--r--public/-/emojis/1/point_right_tone3.png (renamed from app/assets/images/emoji/point_right_tone3.png)bin805 -> 805 bytes
-rw-r--r--public/-/emojis/1/point_right_tone4.png (renamed from app/assets/images/emoji/point_right_tone4.png)bin805 -> 805 bytes
-rw-r--r--public/-/emojis/1/point_right_tone5.png (renamed from app/assets/images/emoji/point_right_tone5.png)bin805 -> 805 bytes
-rw-r--r--public/-/emojis/1/point_up.png (renamed from app/assets/images/emoji/point_up.png)bin819 -> 819 bytes
-rw-r--r--public/-/emojis/1/point_up_2.png (renamed from app/assets/images/emoji/point_up_2.png)bin822 -> 822 bytes
-rw-r--r--public/-/emojis/1/point_up_2_tone1.png (renamed from app/assets/images/emoji/point_up_2_tone1.png)bin822 -> 822 bytes
-rw-r--r--public/-/emojis/1/point_up_2_tone2.png (renamed from app/assets/images/emoji/point_up_2_tone2.png)bin822 -> 822 bytes
-rw-r--r--public/-/emojis/1/point_up_2_tone3.png (renamed from app/assets/images/emoji/point_up_2_tone3.png)bin871 -> 871 bytes
-rw-r--r--public/-/emojis/1/point_up_2_tone4.png (renamed from app/assets/images/emoji/point_up_2_tone4.png)bin822 -> 822 bytes
-rw-r--r--public/-/emojis/1/point_up_2_tone5.png (renamed from app/assets/images/emoji/point_up_2_tone5.png)bin822 -> 822 bytes
-rw-r--r--public/-/emojis/1/point_up_tone1.png (renamed from app/assets/images/emoji/point_up_tone1.png)bin820 -> 820 bytes
-rw-r--r--public/-/emojis/1/point_up_tone2.png (renamed from app/assets/images/emoji/point_up_tone2.png)bin820 -> 820 bytes
-rw-r--r--public/-/emojis/1/point_up_tone3.png (renamed from app/assets/images/emoji/point_up_tone3.png)bin820 -> 820 bytes
-rw-r--r--public/-/emojis/1/point_up_tone4.png (renamed from app/assets/images/emoji/point_up_tone4.png)bin820 -> 820 bytes
-rw-r--r--public/-/emojis/1/point_up_tone5.png (renamed from app/assets/images/emoji/point_up_tone5.png)bin820 -> 820 bytes
-rw-r--r--public/-/emojis/1/police_car.png (renamed from app/assets/images/emoji/police_car.png)bin1431 -> 1431 bytes
-rw-r--r--public/-/emojis/1/poodle.png (renamed from app/assets/images/emoji/poodle.png)bin1531 -> 1531 bytes
-rw-r--r--public/-/emojis/1/poop.png (renamed from app/assets/images/emoji/poop.png)bin1273 -> 1273 bytes
-rw-r--r--public/-/emojis/1/popcorn.png (renamed from app/assets/images/emoji/popcorn.png)bin1843 -> 1843 bytes
-rw-r--r--public/-/emojis/1/post_office.png (renamed from app/assets/images/emoji/post_office.png)bin676 -> 676 bytes
-rw-r--r--public/-/emojis/1/postal_horn.png (renamed from app/assets/images/emoji/postal_horn.png)bin809 -> 809 bytes
-rw-r--r--public/-/emojis/1/postbox.png (renamed from app/assets/images/emoji/postbox.png)bin1077 -> 1077 bytes
-rw-r--r--public/-/emojis/1/potable_water.png (renamed from app/assets/images/emoji/potable_water.png)bin633 -> 633 bytes
-rw-r--r--public/-/emojis/1/potato.png (renamed from app/assets/images/emoji/potato.png)bin1246 -> 1246 bytes
-rw-r--r--public/-/emojis/1/pouch.png (renamed from app/assets/images/emoji/pouch.png)bin1259 -> 1259 bytes
-rw-r--r--public/-/emojis/1/poultry_leg.png (renamed from app/assets/images/emoji/poultry_leg.png)bin925 -> 925 bytes
-rw-r--r--public/-/emojis/1/pound.png (renamed from app/assets/images/emoji/pound.png)bin452 -> 452 bytes
-rw-r--r--public/-/emojis/1/pouting_cat.png (renamed from app/assets/images/emoji/pouting_cat.png)bin1675 -> 1675 bytes
-rw-r--r--public/-/emojis/1/pray.png (renamed from app/assets/images/emoji/pray.png)bin1122 -> 1122 bytes
-rw-r--r--public/-/emojis/1/pray_tone1.png (renamed from app/assets/images/emoji/pray_tone1.png)bin1131 -> 1131 bytes
-rw-r--r--public/-/emojis/1/pray_tone2.png (renamed from app/assets/images/emoji/pray_tone2.png)bin1134 -> 1134 bytes
-rw-r--r--public/-/emojis/1/pray_tone3.png (renamed from app/assets/images/emoji/pray_tone3.png)bin1137 -> 1137 bytes
-rw-r--r--public/-/emojis/1/pray_tone4.png (renamed from app/assets/images/emoji/pray_tone4.png)bin1126 -> 1126 bytes
-rw-r--r--public/-/emojis/1/pray_tone5.png (renamed from app/assets/images/emoji/pray_tone5.png)bin1117 -> 1117 bytes
-rw-r--r--public/-/emojis/1/prayer_beads.png (renamed from app/assets/images/emoji/prayer_beads.png)bin1059 -> 1059 bytes
-rw-r--r--public/-/emojis/1/pregnant_woman.png (renamed from app/assets/images/emoji/pregnant_woman.png)bin1252 -> 1252 bytes
-rw-r--r--public/-/emojis/1/pregnant_woman_tone1.png (renamed from app/assets/images/emoji/pregnant_woman_tone1.png)bin1255 -> 1255 bytes
-rw-r--r--public/-/emojis/1/pregnant_woman_tone2.png (renamed from app/assets/images/emoji/pregnant_woman_tone2.png)bin1246 -> 1246 bytes
-rw-r--r--public/-/emojis/1/pregnant_woman_tone3.png (renamed from app/assets/images/emoji/pregnant_woman_tone3.png)bin1237 -> 1237 bytes
-rw-r--r--public/-/emojis/1/pregnant_woman_tone4.png (renamed from app/assets/images/emoji/pregnant_woman_tone4.png)bin1246 -> 1246 bytes
-rw-r--r--public/-/emojis/1/pregnant_woman_tone5.png (renamed from app/assets/images/emoji/pregnant_woman_tone5.png)bin1235 -> 1235 bytes
-rw-r--r--public/-/emojis/1/prince.png (renamed from app/assets/images/emoji/prince.png)bin1616 -> 1616 bytes
-rw-r--r--public/-/emojis/1/prince_tone1.png (renamed from app/assets/images/emoji/prince_tone1.png)bin1618 -> 1618 bytes
-rw-r--r--public/-/emojis/1/prince_tone2.png (renamed from app/assets/images/emoji/prince_tone2.png)bin1621 -> 1621 bytes
-rw-r--r--public/-/emojis/1/prince_tone3.png (renamed from app/assets/images/emoji/prince_tone3.png)bin1619 -> 1619 bytes
-rw-r--r--public/-/emojis/1/prince_tone4.png (renamed from app/assets/images/emoji/prince_tone4.png)bin1619 -> 1619 bytes
-rw-r--r--public/-/emojis/1/prince_tone5.png (renamed from app/assets/images/emoji/prince_tone5.png)bin1616 -> 1616 bytes
-rw-r--r--public/-/emojis/1/princess.png (renamed from app/assets/images/emoji/princess.png)bin1812 -> 1812 bytes
-rw-r--r--public/-/emojis/1/princess_tone1.png (renamed from app/assets/images/emoji/princess_tone1.png)bin1812 -> 1812 bytes
-rw-r--r--public/-/emojis/1/princess_tone2.png (renamed from app/assets/images/emoji/princess_tone2.png)bin1805 -> 1805 bytes
-rw-r--r--public/-/emojis/1/princess_tone3.png (renamed from app/assets/images/emoji/princess_tone3.png)bin1805 -> 1805 bytes
-rw-r--r--public/-/emojis/1/princess_tone4.png (renamed from app/assets/images/emoji/princess_tone4.png)bin1813 -> 1813 bytes
-rw-r--r--public/-/emojis/1/princess_tone5.png (renamed from app/assets/images/emoji/princess_tone5.png)bin1812 -> 1812 bytes
-rw-r--r--public/-/emojis/1/printer.png (renamed from app/assets/images/emoji/printer.png)bin926 -> 926 bytes
-rw-r--r--public/-/emojis/1/projector.png (renamed from app/assets/images/emoji/projector.png)bin943 -> 943 bytes
-rw-r--r--public/-/emojis/1/punch.png (renamed from app/assets/images/emoji/punch.png)bin838 -> 838 bytes
-rw-r--r--public/-/emojis/1/punch_tone1.png (renamed from app/assets/images/emoji/punch_tone1.png)bin838 -> 838 bytes
-rw-r--r--public/-/emojis/1/punch_tone2.png (renamed from app/assets/images/emoji/punch_tone2.png)bin838 -> 838 bytes
-rw-r--r--public/-/emojis/1/punch_tone3.png (renamed from app/assets/images/emoji/punch_tone3.png)bin838 -> 838 bytes
-rw-r--r--public/-/emojis/1/punch_tone4.png (renamed from app/assets/images/emoji/punch_tone4.png)bin838 -> 838 bytes
-rw-r--r--public/-/emojis/1/punch_tone5.png (renamed from app/assets/images/emoji/punch_tone5.png)bin838 -> 838 bytes
-rw-r--r--public/-/emojis/1/purple_heart.png (renamed from app/assets/images/emoji/purple_heart.png)bin435 -> 435 bytes
-rw-r--r--public/-/emojis/1/purse.png (renamed from app/assets/images/emoji/purse.png)bin1558 -> 1558 bytes
-rw-r--r--public/-/emojis/1/pushpin.png (renamed from app/assets/images/emoji/pushpin.png)bin640 -> 640 bytes
-rw-r--r--public/-/emojis/1/put_litter_in_its_place.png (renamed from app/assets/images/emoji/put_litter_in_its_place.png)bin650 -> 650 bytes
-rw-r--r--public/-/emojis/1/question.png (renamed from app/assets/images/emoji/question.png)bin449 -> 449 bytes
-rw-r--r--public/-/emojis/1/rabbit.png (renamed from app/assets/images/emoji/rabbit.png)bin1660 -> 1660 bytes
-rw-r--r--public/-/emojis/1/rabbit2.png (renamed from app/assets/images/emoji/rabbit2.png)bin1805 -> 1805 bytes
-rw-r--r--public/-/emojis/1/race_car.png (renamed from app/assets/images/emoji/race_car.png)bin2140 -> 2140 bytes
-rw-r--r--public/-/emojis/1/racehorse.png (renamed from app/assets/images/emoji/racehorse.png)bin1401 -> 1401 bytes
-rw-r--r--public/-/emojis/1/radio.png (renamed from app/assets/images/emoji/radio.png)bin851 -> 851 bytes
-rw-r--r--public/-/emojis/1/radio_button.png (renamed from app/assets/images/emoji/radio_button.png)bin674 -> 674 bytes
-rw-r--r--public/-/emojis/1/radioactive.png (renamed from app/assets/images/emoji/radioactive.png)bin858 -> 858 bytes
-rw-r--r--public/-/emojis/1/rage.png (renamed from app/assets/images/emoji/rage.png)bin845 -> 845 bytes
-rw-r--r--public/-/emojis/1/railway_car.png (renamed from app/assets/images/emoji/railway_car.png)bin847 -> 847 bytes
-rw-r--r--public/-/emojis/1/railway_track.png (renamed from app/assets/images/emoji/railway_track.png)bin1550 -> 1550 bytes
-rw-r--r--public/-/emojis/1/rainbow.png (renamed from app/assets/images/emoji/rainbow.png)bin1299 -> 1299 bytes
-rw-r--r--public/-/emojis/1/raised_back_of_hand.png (renamed from app/assets/images/emoji/raised_back_of_hand.png)bin848 -> 848 bytes
-rw-r--r--public/-/emojis/1/raised_back_of_hand_tone1.png (renamed from app/assets/images/emoji/raised_back_of_hand_tone1.png)bin848 -> 848 bytes
-rw-r--r--public/-/emojis/1/raised_back_of_hand_tone2.png (renamed from app/assets/images/emoji/raised_back_of_hand_tone2.png)bin848 -> 848 bytes
-rw-r--r--public/-/emojis/1/raised_back_of_hand_tone3.png (renamed from app/assets/images/emoji/raised_back_of_hand_tone3.png)bin848 -> 848 bytes
-rw-r--r--public/-/emojis/1/raised_back_of_hand_tone4.png (renamed from app/assets/images/emoji/raised_back_of_hand_tone4.png)bin848 -> 848 bytes
-rw-r--r--public/-/emojis/1/raised_back_of_hand_tone5.png (renamed from app/assets/images/emoji/raised_back_of_hand_tone5.png)bin848 -> 848 bytes
-rw-r--r--public/-/emojis/1/raised_hand.png (renamed from app/assets/images/emoji/raised_hand.png)bin791 -> 791 bytes
-rw-r--r--public/-/emojis/1/raised_hand_tone1.png (renamed from app/assets/images/emoji/raised_hand_tone1.png)bin791 -> 791 bytes
-rw-r--r--public/-/emojis/1/raised_hand_tone2.png (renamed from app/assets/images/emoji/raised_hand_tone2.png)bin791 -> 791 bytes
-rw-r--r--public/-/emojis/1/raised_hand_tone3.png (renamed from app/assets/images/emoji/raised_hand_tone3.png)bin791 -> 791 bytes
-rw-r--r--public/-/emojis/1/raised_hand_tone4.png (renamed from app/assets/images/emoji/raised_hand_tone4.png)bin791 -> 791 bytes
-rw-r--r--public/-/emojis/1/raised_hand_tone5.png (renamed from app/assets/images/emoji/raised_hand_tone5.png)bin791 -> 791 bytes
-rw-r--r--public/-/emojis/1/raised_hands.png (renamed from app/assets/images/emoji/raised_hands.png)bin1098 -> 1098 bytes
-rw-r--r--public/-/emojis/1/raised_hands_tone1.png (renamed from app/assets/images/emoji/raised_hands_tone1.png)bin1098 -> 1098 bytes
-rw-r--r--public/-/emojis/1/raised_hands_tone2.png (renamed from app/assets/images/emoji/raised_hands_tone2.png)bin1098 -> 1098 bytes
-rw-r--r--public/-/emojis/1/raised_hands_tone3.png (renamed from app/assets/images/emoji/raised_hands_tone3.png)bin1098 -> 1098 bytes
-rw-r--r--public/-/emojis/1/raised_hands_tone4.png (renamed from app/assets/images/emoji/raised_hands_tone4.png)bin1098 -> 1098 bytes
-rw-r--r--public/-/emojis/1/raised_hands_tone5.png (renamed from app/assets/images/emoji/raised_hands_tone5.png)bin1098 -> 1098 bytes
-rw-r--r--public/-/emojis/1/raising_hand.png (renamed from app/assets/images/emoji/raising_hand.png)bin1664 -> 1664 bytes
-rw-r--r--public/-/emojis/1/raising_hand_tone1.png (renamed from app/assets/images/emoji/raising_hand_tone1.png)bin1678 -> 1678 bytes
-rw-r--r--public/-/emojis/1/raising_hand_tone2.png (renamed from app/assets/images/emoji/raising_hand_tone2.png)bin1665 -> 1665 bytes
-rw-r--r--public/-/emojis/1/raising_hand_tone3.png (renamed from app/assets/images/emoji/raising_hand_tone3.png)bin1657 -> 1657 bytes
-rw-r--r--public/-/emojis/1/raising_hand_tone4.png (renamed from app/assets/images/emoji/raising_hand_tone4.png)bin1657 -> 1657 bytes
-rw-r--r--public/-/emojis/1/raising_hand_tone5.png (renamed from app/assets/images/emoji/raising_hand_tone5.png)bin1661 -> 1661 bytes
-rw-r--r--public/-/emojis/1/ram.png (renamed from app/assets/images/emoji/ram.png)bin1951 -> 1951 bytes
-rw-r--r--public/-/emojis/1/ramen.png (renamed from app/assets/images/emoji/ramen.png)bin1992 -> 1992 bytes
-rw-r--r--public/-/emojis/1/rat.png (renamed from app/assets/images/emoji/rat.png)bin1193 -> 1193 bytes
-rw-r--r--public/-/emojis/1/record_button.png (renamed from app/assets/images/emoji/record_button.png)bin475 -> 475 bytes
-rw-r--r--public/-/emojis/1/recycle.png (renamed from app/assets/images/emoji/recycle.png)bin914 -> 914 bytes
-rw-r--r--public/-/emojis/1/red_car.png (renamed from app/assets/images/emoji/red_car.png)bin1065 -> 1065 bytes
-rw-r--r--public/-/emojis/1/red_circle.png (renamed from app/assets/images/emoji/red_circle.png)bin374 -> 374 bytes
-rw-r--r--public/-/emojis/1/registered.png (renamed from app/assets/images/emoji/registered.png)bin547 -> 547 bytes
-rw-r--r--public/-/emojis/1/relaxed.png (renamed from app/assets/images/emoji/relaxed.png)bin636 -> 636 bytes
-rw-r--r--public/-/emojis/1/relieved.png (renamed from app/assets/images/emoji/relieved.png)bin785 -> 785 bytes
-rw-r--r--public/-/emojis/1/reminder_ribbon.png (renamed from app/assets/images/emoji/reminder_ribbon.png)bin921 -> 921 bytes
-rw-r--r--public/-/emojis/1/repeat.png (renamed from app/assets/images/emoji/repeat.png)bin644 -> 644 bytes
-rw-r--r--public/-/emojis/1/repeat_one.png (renamed from app/assets/images/emoji/repeat_one.png)bin688 -> 688 bytes
-rw-r--r--public/-/emojis/1/restroom.png (renamed from app/assets/images/emoji/restroom.png)bin676 -> 676 bytes
-rw-r--r--public/-/emojis/1/revolving_hearts.png (renamed from app/assets/images/emoji/revolving_hearts.png)bin920 -> 920 bytes
-rw-r--r--public/-/emojis/1/rewind.png (renamed from app/assets/images/emoji/rewind.png)bin523 -> 523 bytes
-rw-r--r--public/-/emojis/1/rhino.png (renamed from app/assets/images/emoji/rhino.png)bin1558 -> 1558 bytes
-rw-r--r--public/-/emojis/1/ribbon.png (renamed from app/assets/images/emoji/ribbon.png)bin968 -> 968 bytes
-rw-r--r--public/-/emojis/1/rice.png (renamed from app/assets/images/emoji/rice.png)bin1195 -> 1195 bytes
-rw-r--r--public/-/emojis/1/rice_ball.png (renamed from app/assets/images/emoji/rice_ball.png)bin1091 -> 1091 bytes
-rw-r--r--public/-/emojis/1/rice_cracker.png (renamed from app/assets/images/emoji/rice_cracker.png)bin1443 -> 1443 bytes
-rw-r--r--public/-/emojis/1/rice_scene.png (renamed from app/assets/images/emoji/rice_scene.png)bin1349 -> 1349 bytes
-rw-r--r--public/-/emojis/1/right_facing_fist.png (renamed from app/assets/images/emoji/right_facing_fist.png)bin975 -> 975 bytes
-rw-r--r--public/-/emojis/1/right_facing_fist_tone1.png (renamed from app/assets/images/emoji/right_facing_fist_tone1.png)bin964 -> 964 bytes
-rw-r--r--public/-/emojis/1/right_facing_fist_tone2.png (renamed from app/assets/images/emoji/right_facing_fist_tone2.png)bin964 -> 964 bytes
-rw-r--r--public/-/emojis/1/right_facing_fist_tone3.png (renamed from app/assets/images/emoji/right_facing_fist_tone3.png)bin964 -> 964 bytes
-rw-r--r--public/-/emojis/1/right_facing_fist_tone4.png (renamed from app/assets/images/emoji/right_facing_fist_tone4.png)bin964 -> 964 bytes
-rw-r--r--public/-/emojis/1/right_facing_fist_tone5.png (renamed from app/assets/images/emoji/right_facing_fist_tone5.png)bin964 -> 964 bytes
-rw-r--r--public/-/emojis/1/ring.png (renamed from app/assets/images/emoji/ring.png)bin1113 -> 1113 bytes
-rw-r--r--public/-/emojis/1/robot.png (renamed from app/assets/images/emoji/robot.png)bin1228 -> 1228 bytes
-rw-r--r--public/-/emojis/1/rocket.png (renamed from app/assets/images/emoji/rocket.png)bin1639 -> 1639 bytes
-rw-r--r--public/-/emojis/1/rofl.png (renamed from app/assets/images/emoji/rofl.png)bin1760 -> 1760 bytes
-rw-r--r--public/-/emojis/1/roller_coaster.png (renamed from app/assets/images/emoji/roller_coaster.png)bin1723 -> 1723 bytes
-rw-r--r--public/-/emojis/1/rolling_eyes.png (renamed from app/assets/images/emoji/rolling_eyes.png)bin743 -> 743 bytes
-rw-r--r--public/-/emojis/1/rooster.png (renamed from app/assets/images/emoji/rooster.png)bin1333 -> 1333 bytes
-rw-r--r--public/-/emojis/1/rose.png (renamed from app/assets/images/emoji/rose.png)bin1182 -> 1182 bytes
-rw-r--r--public/-/emojis/1/rosette.png (renamed from app/assets/images/emoji/rosette.png)bin1023 -> 1023 bytes
-rw-r--r--public/-/emojis/1/rotating_light.png (renamed from app/assets/images/emoji/rotating_light.png)bin1969 -> 1969 bytes
-rw-r--r--public/-/emojis/1/round_pushpin.png (renamed from app/assets/images/emoji/round_pushpin.png)bin455 -> 455 bytes
-rw-r--r--public/-/emojis/1/rowboat.png (renamed from app/assets/images/emoji/rowboat.png)bin1963 -> 1963 bytes
-rw-r--r--public/-/emojis/1/rowboat_tone1.png (renamed from app/assets/images/emoji/rowboat_tone1.png)bin1971 -> 1971 bytes
-rw-r--r--public/-/emojis/1/rowboat_tone2.png (renamed from app/assets/images/emoji/rowboat_tone2.png)bin1972 -> 1972 bytes
-rw-r--r--public/-/emojis/1/rowboat_tone3.png (renamed from app/assets/images/emoji/rowboat_tone3.png)bin1967 -> 1967 bytes
-rw-r--r--public/-/emojis/1/rowboat_tone4.png (renamed from app/assets/images/emoji/rowboat_tone4.png)bin1974 -> 1974 bytes
-rw-r--r--public/-/emojis/1/rowboat_tone5.png (renamed from app/assets/images/emoji/rowboat_tone5.png)bin1971 -> 1971 bytes
-rw-r--r--public/-/emojis/1/rugby_football.png (renamed from app/assets/images/emoji/rugby_football.png)bin1618 -> 1618 bytes
-rw-r--r--public/-/emojis/1/runner.png (renamed from app/assets/images/emoji/runner.png)bin1161 -> 1161 bytes
-rw-r--r--public/-/emojis/1/runner_tone1.png (renamed from app/assets/images/emoji/runner_tone1.png)bin1163 -> 1163 bytes
-rw-r--r--public/-/emojis/1/runner_tone2.png (renamed from app/assets/images/emoji/runner_tone2.png)bin1162 -> 1162 bytes
-rw-r--r--public/-/emojis/1/runner_tone3.png (renamed from app/assets/images/emoji/runner_tone3.png)bin1151 -> 1151 bytes
-rw-r--r--public/-/emojis/1/runner_tone4.png (renamed from app/assets/images/emoji/runner_tone4.png)bin1156 -> 1156 bytes
-rw-r--r--public/-/emojis/1/runner_tone5.png (renamed from app/assets/images/emoji/runner_tone5.png)bin1145 -> 1145 bytes
-rw-r--r--public/-/emojis/1/running_shirt_with_sash.png (renamed from app/assets/images/emoji/running_shirt_with_sash.png)bin784 -> 784 bytes
-rw-r--r--public/-/emojis/1/sa.png (renamed from app/assets/images/emoji/sa.png)bin420 -> 420 bytes
-rw-r--r--public/-/emojis/1/sagittarius.png (renamed from app/assets/images/emoji/sagittarius.png)bin602 -> 602 bytes
-rw-r--r--public/-/emojis/1/sailboat.png (renamed from app/assets/images/emoji/sailboat.png)bin1274 -> 1274 bytes
-rw-r--r--public/-/emojis/1/sake.png (renamed from app/assets/images/emoji/sake.png)bin826 -> 826 bytes
-rw-r--r--public/-/emojis/1/salad.png (renamed from app/assets/images/emoji/salad.png)bin2398 -> 2398 bytes
-rw-r--r--public/-/emojis/1/sandal.png (renamed from app/assets/images/emoji/sandal.png)bin1180 -> 1180 bytes
-rw-r--r--public/-/emojis/1/santa.png (renamed from app/assets/images/emoji/santa.png)bin1585 -> 1585 bytes
-rw-r--r--public/-/emojis/1/santa_tone1.png (renamed from app/assets/images/emoji/santa_tone1.png)bin1585 -> 1585 bytes
-rw-r--r--public/-/emojis/1/santa_tone2.png (renamed from app/assets/images/emoji/santa_tone2.png)bin1578 -> 1578 bytes
-rw-r--r--public/-/emojis/1/santa_tone3.png (renamed from app/assets/images/emoji/santa_tone3.png)bin1578 -> 1578 bytes
-rw-r--r--public/-/emojis/1/santa_tone4.png (renamed from app/assets/images/emoji/santa_tone4.png)bin1578 -> 1578 bytes
-rw-r--r--public/-/emojis/1/santa_tone5.png (renamed from app/assets/images/emoji/santa_tone5.png)bin1578 -> 1578 bytes
-rw-r--r--public/-/emojis/1/satellite.png (renamed from app/assets/images/emoji/satellite.png)bin1173 -> 1173 bytes
-rw-r--r--public/-/emojis/1/satellite_orbital.png (renamed from app/assets/images/emoji/satellite_orbital.png)bin762 -> 762 bytes
-rw-r--r--public/-/emojis/1/saxophone.png (renamed from app/assets/images/emoji/saxophone.png)bin1442 -> 1442 bytes
-rw-r--r--public/-/emojis/1/scales.png (renamed from app/assets/images/emoji/scales.png)bin1181 -> 1181 bytes
-rw-r--r--public/-/emojis/1/school.png (renamed from app/assets/images/emoji/school.png)bin1234 -> 1234 bytes
-rw-r--r--public/-/emojis/1/school_satchel.png (renamed from app/assets/images/emoji/school_satchel.png)bin1490 -> 1490 bytes
-rw-r--r--public/-/emojis/1/scissors.png (renamed from app/assets/images/emoji/scissors.png)bin937 -> 937 bytes
-rw-r--r--public/-/emojis/1/scooter.png (renamed from app/assets/images/emoji/scooter.png)bin1228 -> 1228 bytes
-rw-r--r--public/-/emojis/1/scorpion.png (renamed from app/assets/images/emoji/scorpion.png)bin1503 -> 1503 bytes
-rw-r--r--public/-/emojis/1/scorpius.png (renamed from app/assets/images/emoji/scorpius.png)bin612 -> 612 bytes
-rw-r--r--public/-/emojis/1/scream.png (renamed from app/assets/images/emoji/scream.png)bin1583 -> 1583 bytes
-rw-r--r--public/-/emojis/1/scream_cat.png (renamed from app/assets/images/emoji/scream_cat.png)bin2120 -> 2120 bytes
-rw-r--r--public/-/emojis/1/scroll.png (renamed from app/assets/images/emoji/scroll.png)bin989 -> 989 bytes
-rw-r--r--public/-/emojis/1/seat.png (renamed from app/assets/images/emoji/seat.png)bin884 -> 884 bytes
-rw-r--r--public/-/emojis/1/second_place.png (renamed from app/assets/images/emoji/second_place.png)bin1511 -> 1511 bytes
-rw-r--r--public/-/emojis/1/secret.png (renamed from app/assets/images/emoji/secret.png)bin857 -> 857 bytes
-rw-r--r--public/-/emojis/1/see_no_evil.png (renamed from app/assets/images/emoji/see_no_evil.png)bin1227 -> 1227 bytes
-rw-r--r--public/-/emojis/1/seedling.png (renamed from app/assets/images/emoji/seedling.png)bin749 -> 749 bytes
-rw-r--r--public/-/emojis/1/selfie.png (renamed from app/assets/images/emoji/selfie.png)bin1160 -> 1160 bytes
-rw-r--r--public/-/emojis/1/selfie_tone1.png (renamed from app/assets/images/emoji/selfie_tone1.png)bin1166 -> 1166 bytes
-rw-r--r--public/-/emojis/1/selfie_tone2.png (renamed from app/assets/images/emoji/selfie_tone2.png)bin1167 -> 1167 bytes
-rw-r--r--public/-/emojis/1/selfie_tone3.png (renamed from app/assets/images/emoji/selfie_tone3.png)bin1154 -> 1154 bytes
-rw-r--r--public/-/emojis/1/selfie_tone4.png (renamed from app/assets/images/emoji/selfie_tone4.png)bin1153 -> 1153 bytes
-rw-r--r--public/-/emojis/1/selfie_tone5.png (renamed from app/assets/images/emoji/selfie_tone5.png)bin1148 -> 1148 bytes
-rw-r--r--public/-/emojis/1/seven.png (renamed from app/assets/images/emoji/seven.png)bin522 -> 522 bytes
-rw-r--r--public/-/emojis/1/shallow_pan_of_food.png (renamed from app/assets/images/emoji/shallow_pan_of_food.png)bin1738 -> 1738 bytes
-rw-r--r--public/-/emojis/1/shamrock.png (renamed from app/assets/images/emoji/shamrock.png)bin1023 -> 1023 bytes
-rw-r--r--public/-/emojis/1/shark.png (renamed from app/assets/images/emoji/shark.png)bin1811 -> 1811 bytes
-rw-r--r--public/-/emojis/1/shaved_ice.png (renamed from app/assets/images/emoji/shaved_ice.png)bin997 -> 997 bytes
-rw-r--r--public/-/emojis/1/sheep.png (renamed from app/assets/images/emoji/sheep.png)bin1372 -> 1372 bytes
-rw-r--r--public/-/emojis/1/shell.png (renamed from app/assets/images/emoji/shell.png)bin1497 -> 1497 bytes
-rw-r--r--public/-/emojis/1/shield.png (renamed from app/assets/images/emoji/shield.png)bin1602 -> 1602 bytes
-rw-r--r--public/-/emojis/1/shinto_shrine.png (renamed from app/assets/images/emoji/shinto_shrine.png)bin579 -> 579 bytes
-rw-r--r--public/-/emojis/1/ship.png (renamed from app/assets/images/emoji/ship.png)bin1405 -> 1405 bytes
-rw-r--r--public/-/emojis/1/shirt.png (renamed from app/assets/images/emoji/shirt.png)bin670 -> 670 bytes
-rw-r--r--public/-/emojis/1/shopping_bags.png (renamed from app/assets/images/emoji/shopping_bags.png)bin1234 -> 1234 bytes
-rw-r--r--public/-/emojis/1/shopping_cart.png (renamed from app/assets/images/emoji/shopping_cart.png)bin1072 -> 1072 bytes
-rw-r--r--public/-/emojis/1/shower.png (renamed from app/assets/images/emoji/shower.png)bin2537 -> 2537 bytes
-rw-r--r--public/-/emojis/1/shrimp.png (renamed from app/assets/images/emoji/shrimp.png)bin1376 -> 1376 bytes
-rw-r--r--public/-/emojis/1/shrug.png (renamed from app/assets/images/emoji/shrug.png)bin1671 -> 1671 bytes
-rw-r--r--public/-/emojis/1/shrug_tone1.png (renamed from app/assets/images/emoji/shrug_tone1.png)bin1676 -> 1676 bytes
-rw-r--r--public/-/emojis/1/shrug_tone2.png (renamed from app/assets/images/emoji/shrug_tone2.png)bin1671 -> 1671 bytes
-rw-r--r--public/-/emojis/1/shrug_tone3.png (renamed from app/assets/images/emoji/shrug_tone3.png)bin1675 -> 1675 bytes
-rw-r--r--public/-/emojis/1/shrug_tone4.png (renamed from app/assets/images/emoji/shrug_tone4.png)bin1641 -> 1641 bytes
-rw-r--r--public/-/emojis/1/shrug_tone5.png (renamed from app/assets/images/emoji/shrug_tone5.png)bin1634 -> 1634 bytes
-rw-r--r--public/-/emojis/1/signal_strength.png (renamed from app/assets/images/emoji/signal_strength.png)bin445 -> 445 bytes
-rw-r--r--public/-/emojis/1/six.png (renamed from app/assets/images/emoji/six.png)bin612 -> 612 bytes
-rw-r--r--public/-/emojis/1/six_pointed_star.png (renamed from app/assets/images/emoji/six_pointed_star.png)bin540 -> 540 bytes
-rw-r--r--public/-/emojis/1/ski.png (renamed from app/assets/images/emoji/ski.png)bin1762 -> 1762 bytes
-rw-r--r--public/-/emojis/1/skier.png (renamed from app/assets/images/emoji/skier.png)bin1539 -> 1539 bytes
-rw-r--r--public/-/emojis/1/skull.png (renamed from app/assets/images/emoji/skull.png)bin628 -> 628 bytes
-rw-r--r--public/-/emojis/1/skull_crossbones.png (renamed from app/assets/images/emoji/skull_crossbones.png)bin726 -> 726 bytes
-rw-r--r--public/-/emojis/1/sleeping.png (renamed from app/assets/images/emoji/sleeping.png)bin1075 -> 1075 bytes
-rw-r--r--public/-/emojis/1/sleeping_accommodation.png (renamed from app/assets/images/emoji/sleeping_accommodation.png)bin926 -> 926 bytes
-rw-r--r--public/-/emojis/1/sleepy.png (renamed from app/assets/images/emoji/sleepy.png)bin1185 -> 1185 bytes
-rw-r--r--public/-/emojis/1/slight_frown.png (renamed from app/assets/images/emoji/slight_frown.png)bin580 -> 580 bytes
-rw-r--r--public/-/emojis/1/slight_smile.png (renamed from app/assets/images/emoji/slight_smile.png)bin600 -> 600 bytes
-rw-r--r--public/-/emojis/1/slot_machine.png (renamed from app/assets/images/emoji/slot_machine.png)bin1648 -> 1648 bytes
-rw-r--r--public/-/emojis/1/small_blue_diamond.png (renamed from app/assets/images/emoji/small_blue_diamond.png)bin191 -> 191 bytes
-rw-r--r--public/-/emojis/1/small_orange_diamond.png (renamed from app/assets/images/emoji/small_orange_diamond.png)bin194 -> 194 bytes
-rw-r--r--public/-/emojis/1/small_red_triangle.png (renamed from app/assets/images/emoji/small_red_triangle.png)bin273 -> 273 bytes
-rw-r--r--public/-/emojis/1/small_red_triangle_down.png (renamed from app/assets/images/emoji/small_red_triangle_down.png)bin291 -> 291 bytes
-rw-r--r--public/-/emojis/1/smile.png (renamed from app/assets/images/emoji/smile.png)bin737 -> 737 bytes
-rw-r--r--public/-/emojis/1/smile_cat.png (renamed from app/assets/images/emoji/smile_cat.png)bin1405 -> 1405 bytes
-rw-r--r--public/-/emojis/1/smiley.png (renamed from app/assets/images/emoji/smiley.png)bin686 -> 686 bytes
-rw-r--r--public/-/emojis/1/smiley_cat.png (renamed from app/assets/images/emoji/smiley_cat.png)bin1669 -> 1669 bytes
-rw-r--r--public/-/emojis/1/smiling_imp.png (renamed from app/assets/images/emoji/smiling_imp.png)bin1078 -> 1078 bytes
-rw-r--r--public/-/emojis/1/smirk.png (renamed from app/assets/images/emoji/smirk.png)bin775 -> 775 bytes
-rw-r--r--public/-/emojis/1/smirk_cat.png (renamed from app/assets/images/emoji/smirk_cat.png)bin1663 -> 1663 bytes
-rw-r--r--public/-/emojis/1/smoking.png (renamed from app/assets/images/emoji/smoking.png)bin417 -> 417 bytes
-rw-r--r--public/-/emojis/1/snail.png (renamed from app/assets/images/emoji/snail.png)bin1731 -> 1731 bytes
-rw-r--r--public/-/emojis/1/snake.png (renamed from app/assets/images/emoji/snake.png)bin1575 -> 1575 bytes
-rw-r--r--public/-/emojis/1/sneezing_face.png (renamed from app/assets/images/emoji/sneezing_face.png)bin1289 -> 1289 bytes
-rw-r--r--public/-/emojis/1/snowboarder.png (renamed from app/assets/images/emoji/snowboarder.png)bin2020 -> 2020 bytes
-rw-r--r--public/-/emojis/1/snowflake.png (renamed from app/assets/images/emoji/snowflake.png)bin691 -> 691 bytes
-rw-r--r--public/-/emojis/1/snowman.png (renamed from app/assets/images/emoji/snowman.png)bin1481 -> 1481 bytes
-rw-r--r--public/-/emojis/1/snowman2.png (renamed from app/assets/images/emoji/snowman2.png)bin2176 -> 2176 bytes
-rw-r--r--public/-/emojis/1/sob.png (renamed from app/assets/images/emoji/sob.png)bin1236 -> 1236 bytes
-rw-r--r--public/-/emojis/1/soccer.png (renamed from app/assets/images/emoji/soccer.png)bin1034 -> 1034 bytes
-rw-r--r--public/-/emojis/1/soon.png (renamed from app/assets/images/emoji/soon.png)bin483 -> 483 bytes
-rw-r--r--public/-/emojis/1/sos.png (renamed from app/assets/images/emoji/sos.png)bin604 -> 604 bytes
-rw-r--r--public/-/emojis/1/sound.png (renamed from app/assets/images/emoji/sound.png)bin690 -> 690 bytes
-rw-r--r--public/-/emojis/1/space_invader.png (renamed from app/assets/images/emoji/space_invader.png)bin1325 -> 1325 bytes
-rw-r--r--public/-/emojis/1/spades.png (renamed from app/assets/images/emoji/spades.png)bin454 -> 454 bytes
-rw-r--r--public/-/emojis/1/spaghetti.png (renamed from app/assets/images/emoji/spaghetti.png)bin1796 -> 1796 bytes
-rw-r--r--public/-/emojis/1/sparkle.png (renamed from app/assets/images/emoji/sparkle.png)bin663 -> 663 bytes
-rw-r--r--public/-/emojis/1/sparkler.png (renamed from app/assets/images/emoji/sparkler.png)bin910 -> 910 bytes
-rw-r--r--public/-/emojis/1/sparkles.png (renamed from app/assets/images/emoji/sparkles.png)bin651 -> 651 bytes
-rw-r--r--public/-/emojis/1/sparkling_heart.png (renamed from app/assets/images/emoji/sparkling_heart.png)bin821 -> 821 bytes
-rw-r--r--public/-/emojis/1/speak_no_evil.png (renamed from app/assets/images/emoji/speak_no_evil.png)bin1497 -> 1497 bytes
-rw-r--r--public/-/emojis/1/speaker.png (renamed from app/assets/images/emoji/speaker.png)bin575 -> 575 bytes
-rw-r--r--public/-/emojis/1/speaking_head.png (renamed from app/assets/images/emoji/speaking_head.png)bin531 -> 531 bytes
-rw-r--r--public/-/emojis/1/speech_balloon.png (renamed from app/assets/images/emoji/speech_balloon.png)bin384 -> 384 bytes
-rw-r--r--public/-/emojis/1/speech_left.png (renamed from app/assets/images/emoji/speech_left.png)bin390 -> 390 bytes
-rw-r--r--public/-/emojis/1/speedboat.png (renamed from app/assets/images/emoji/speedboat.png)bin1255 -> 1255 bytes
-rw-r--r--public/-/emojis/1/spider.png (renamed from app/assets/images/emoji/spider.png)bin1724 -> 1724 bytes
-rw-r--r--public/-/emojis/1/spider_web.png (renamed from app/assets/images/emoji/spider_web.png)bin929 -> 929 bytes
-rw-r--r--public/-/emojis/1/spoon.png (renamed from app/assets/images/emoji/spoon.png)bin700 -> 700 bytes
-rw-r--r--public/-/emojis/1/spy.png (renamed from app/assets/images/emoji/spy.png)bin1650 -> 1650 bytes
-rw-r--r--public/-/emojis/1/spy_tone1.png (renamed from app/assets/images/emoji/spy_tone1.png)bin1639 -> 1639 bytes
-rw-r--r--public/-/emojis/1/spy_tone2.png (renamed from app/assets/images/emoji/spy_tone2.png)bin1632 -> 1632 bytes
-rw-r--r--public/-/emojis/1/spy_tone3.png (renamed from app/assets/images/emoji/spy_tone3.png)bin1645 -> 1645 bytes
-rw-r--r--public/-/emojis/1/spy_tone4.png (renamed from app/assets/images/emoji/spy_tone4.png)bin1639 -> 1639 bytes
-rw-r--r--public/-/emojis/1/spy_tone5.png (renamed from app/assets/images/emoji/spy_tone5.png)bin1639 -> 1639 bytes
-rw-r--r--public/-/emojis/1/squid.png (renamed from app/assets/images/emoji/squid.png)bin1394 -> 1394 bytes
-rw-r--r--public/-/emojis/1/stadium.png (renamed from app/assets/images/emoji/stadium.png)bin1515 -> 1515 bytes
-rw-r--r--public/-/emojis/1/star.png (renamed from app/assets/images/emoji/star.png)bin456 -> 456 bytes
-rw-r--r--public/-/emojis/1/star2.png (renamed from app/assets/images/emoji/star2.png)bin732 -> 732 bytes
-rw-r--r--public/-/emojis/1/star_and_crescent.png (renamed from app/assets/images/emoji/star_and_crescent.png)bin490 -> 490 bytes
-rw-r--r--public/-/emojis/1/star_of_david.png (renamed from app/assets/images/emoji/star_of_david.png)bin491 -> 491 bytes
-rw-r--r--public/-/emojis/1/stars.png (renamed from app/assets/images/emoji/stars.png)bin1048 -> 1048 bytes
-rw-r--r--public/-/emojis/1/station.png (renamed from app/assets/images/emoji/station.png)bin1336 -> 1336 bytes
-rw-r--r--public/-/emojis/1/statue_of_liberty.png (renamed from app/assets/images/emoji/statue_of_liberty.png)bin1145 -> 1145 bytes
-rw-r--r--public/-/emojis/1/steam_locomotive.png (renamed from app/assets/images/emoji/steam_locomotive.png)bin1736 -> 1736 bytes
-rw-r--r--public/-/emojis/1/stew.png (renamed from app/assets/images/emoji/stew.png)bin1960 -> 1960 bytes
-rw-r--r--public/-/emojis/1/stop_button.png (renamed from app/assets/images/emoji/stop_button.png)bin385 -> 385 bytes
-rw-r--r--public/-/emojis/1/stopwatch.png (renamed from app/assets/images/emoji/stopwatch.png)bin1329 -> 1329 bytes
-rw-r--r--public/-/emojis/1/straight_ruler.png (renamed from app/assets/images/emoji/straight_ruler.png)bin1406 -> 1406 bytes
-rw-r--r--public/-/emojis/1/strawberry.png (renamed from app/assets/images/emoji/strawberry.png)bin1206 -> 1206 bytes
-rw-r--r--public/-/emojis/1/stuck_out_tongue.png (renamed from app/assets/images/emoji/stuck_out_tongue.png)bin752 -> 752 bytes
-rw-r--r--public/-/emojis/1/stuck_out_tongue_closed_eyes.png (renamed from app/assets/images/emoji/stuck_out_tongue_closed_eyes.png)bin867 -> 867 bytes
-rw-r--r--public/-/emojis/1/stuck_out_tongue_winking_eye.png (renamed from app/assets/images/emoji/stuck_out_tongue_winking_eye.png)bin1061 -> 1061 bytes
-rw-r--r--public/-/emojis/1/stuffed_flatbread.png (renamed from app/assets/images/emoji/stuffed_flatbread.png)bin2160 -> 2160 bytes
-rw-r--r--public/-/emojis/1/sun_with_face.png (renamed from app/assets/images/emoji/sun_with_face.png)bin741 -> 741 bytes
-rw-r--r--public/-/emojis/1/sunflower.png (renamed from app/assets/images/emoji/sunflower.png)bin1915 -> 1915 bytes
-rw-r--r--public/-/emojis/1/sunglasses.png (renamed from app/assets/images/emoji/sunglasses.png)bin824 -> 824 bytes
-rw-r--r--public/-/emojis/1/sunny.png (renamed from app/assets/images/emoji/sunny.png)bin746 -> 746 bytes
-rw-r--r--public/-/emojis/1/sunrise.png (renamed from app/assets/images/emoji/sunrise.png)bin812 -> 812 bytes
-rw-r--r--public/-/emojis/1/sunrise_over_mountains.png (renamed from app/assets/images/emoji/sunrise_over_mountains.png)bin1576 -> 1576 bytes
-rw-r--r--public/-/emojis/1/surfer.png (renamed from app/assets/images/emoji/surfer.png)bin1777 -> 1777 bytes
-rw-r--r--public/-/emojis/1/surfer_tone1.png (renamed from app/assets/images/emoji/surfer_tone1.png)bin1781 -> 1781 bytes
-rw-r--r--public/-/emojis/1/surfer_tone2.png (renamed from app/assets/images/emoji/surfer_tone2.png)bin1769 -> 1769 bytes
-rw-r--r--public/-/emojis/1/surfer_tone3.png (renamed from app/assets/images/emoji/surfer_tone3.png)bin1777 -> 1777 bytes
-rw-r--r--public/-/emojis/1/surfer_tone4.png (renamed from app/assets/images/emoji/surfer_tone4.png)bin1784 -> 1784 bytes
-rw-r--r--public/-/emojis/1/surfer_tone5.png (renamed from app/assets/images/emoji/surfer_tone5.png)bin1782 -> 1782 bytes
-rw-r--r--public/-/emojis/1/sushi.png (renamed from app/assets/images/emoji/sushi.png)bin2101 -> 2101 bytes
-rw-r--r--public/-/emojis/1/suspension_railway.png (renamed from app/assets/images/emoji/suspension_railway.png)bin927 -> 927 bytes
-rw-r--r--public/-/emojis/1/sweat.png (renamed from app/assets/images/emoji/sweat.png)bin861 -> 861 bytes
-rw-r--r--public/-/emojis/1/sweat_drops.png (renamed from app/assets/images/emoji/sweat_drops.png)bin549 -> 549 bytes
-rw-r--r--public/-/emojis/1/sweat_smile.png (renamed from app/assets/images/emoji/sweat_smile.png)bin851 -> 851 bytes
-rw-r--r--public/-/emojis/1/sweet_potato.png (renamed from app/assets/images/emoji/sweet_potato.png)bin951 -> 951 bytes
-rw-r--r--public/-/emojis/1/swimmer.png (renamed from app/assets/images/emoji/swimmer.png)bin1184 -> 1184 bytes
-rw-r--r--public/-/emojis/1/swimmer_tone1.png (renamed from app/assets/images/emoji/swimmer_tone1.png)bin1184 -> 1184 bytes
-rw-r--r--public/-/emojis/1/swimmer_tone2.png (renamed from app/assets/images/emoji/swimmer_tone2.png)bin1184 -> 1184 bytes
-rw-r--r--public/-/emojis/1/swimmer_tone3.png (renamed from app/assets/images/emoji/swimmer_tone3.png)bin1184 -> 1184 bytes
-rw-r--r--public/-/emojis/1/swimmer_tone4.png (renamed from app/assets/images/emoji/swimmer_tone4.png)bin1184 -> 1184 bytes
-rw-r--r--public/-/emojis/1/swimmer_tone5.png (renamed from app/assets/images/emoji/swimmer_tone5.png)bin1184 -> 1184 bytes
-rw-r--r--public/-/emojis/1/symbols.png (renamed from app/assets/images/emoji/symbols.png)bin746 -> 746 bytes
-rw-r--r--public/-/emojis/1/synagogue.png (renamed from app/assets/images/emoji/synagogue.png)bin1309 -> 1309 bytes
-rw-r--r--public/-/emojis/1/syringe.png (renamed from app/assets/images/emoji/syringe.png)bin737 -> 737 bytes
-rw-r--r--public/-/emojis/1/taco.png (renamed from app/assets/images/emoji/taco.png)bin3045 -> 3045 bytes
-rw-r--r--public/-/emojis/1/tada.png (renamed from app/assets/images/emoji/tada.png)bin1778 -> 1778 bytes
-rw-r--r--public/-/emojis/1/tanabata_tree.png (renamed from app/assets/images/emoji/tanabata_tree.png)bin1479 -> 1479 bytes
-rw-r--r--public/-/emojis/1/tangerine.png (renamed from app/assets/images/emoji/tangerine.png)bin1184 -> 1184 bytes
-rw-r--r--public/-/emojis/1/taurus.png (renamed from app/assets/images/emoji/taurus.png)bin701 -> 701 bytes
-rw-r--r--public/-/emojis/1/taxi.png (renamed from app/assets/images/emoji/taxi.png)bin1230 -> 1230 bytes
-rw-r--r--public/-/emojis/1/tea.png (renamed from app/assets/images/emoji/tea.png)bin1297 -> 1297 bytes
-rw-r--r--public/-/emojis/1/telephone.png (renamed from app/assets/images/emoji/telephone.png)bin1760 -> 1760 bytes
-rw-r--r--public/-/emojis/1/telephone_receiver.png (renamed from app/assets/images/emoji/telephone_receiver.png)bin941 -> 941 bytes
-rw-r--r--public/-/emojis/1/telescope.png (renamed from app/assets/images/emoji/telescope.png)bin1256 -> 1256 bytes
-rw-r--r--public/-/emojis/1/ten.png (renamed from app/assets/images/emoji/ten.png)bin621 -> 621 bytes
-rw-r--r--public/-/emojis/1/tennis.png (renamed from app/assets/images/emoji/tennis.png)bin1561 -> 1561 bytes
-rw-r--r--public/-/emojis/1/tent.png (renamed from app/assets/images/emoji/tent.png)bin1684 -> 1684 bytes
-rw-r--r--public/-/emojis/1/thermometer.png (renamed from app/assets/images/emoji/thermometer.png)bin759 -> 759 bytes
-rw-r--r--public/-/emojis/1/thermometer_face.png (renamed from app/assets/images/emoji/thermometer_face.png)bin1503 -> 1503 bytes
-rw-r--r--public/-/emojis/1/thinking.png (renamed from app/assets/images/emoji/thinking.png)bin1345 -> 1345 bytes
-rw-r--r--public/-/emojis/1/third_place.png (renamed from app/assets/images/emoji/third_place.png)bin1529 -> 1529 bytes
-rw-r--r--public/-/emojis/1/thought_balloon.png (renamed from app/assets/images/emoji/thought_balloon.png)bin489 -> 489 bytes
-rw-r--r--public/-/emojis/1/three.png (renamed from app/assets/images/emoji/three.png)bin602 -> 602 bytes
-rw-r--r--public/-/emojis/1/thumbsdown.png (renamed from app/assets/images/emoji/thumbsdown.png)bin815 -> 815 bytes
-rw-r--r--public/-/emojis/1/thumbsdown_tone1.png (renamed from app/assets/images/emoji/thumbsdown_tone1.png)bin815 -> 815 bytes
-rw-r--r--public/-/emojis/1/thumbsdown_tone2.png (renamed from app/assets/images/emoji/thumbsdown_tone2.png)bin815 -> 815 bytes
-rw-r--r--public/-/emojis/1/thumbsdown_tone3.png (renamed from app/assets/images/emoji/thumbsdown_tone3.png)bin815 -> 815 bytes
-rw-r--r--public/-/emojis/1/thumbsdown_tone4.png (renamed from app/assets/images/emoji/thumbsdown_tone4.png)bin815 -> 815 bytes
-rw-r--r--public/-/emojis/1/thumbsdown_tone5.png (renamed from app/assets/images/emoji/thumbsdown_tone5.png)bin815 -> 815 bytes
-rw-r--r--public/-/emojis/1/thumbsup.png (renamed from app/assets/images/emoji/thumbsup.png)bin814 -> 814 bytes
-rw-r--r--public/-/emojis/1/thumbsup_tone1.png (renamed from app/assets/images/emoji/thumbsup_tone1.png)bin814 -> 814 bytes
-rw-r--r--public/-/emojis/1/thumbsup_tone2.png (renamed from app/assets/images/emoji/thumbsup_tone2.png)bin814 -> 814 bytes
-rw-r--r--public/-/emojis/1/thumbsup_tone3.png (renamed from app/assets/images/emoji/thumbsup_tone3.png)bin814 -> 814 bytes
-rw-r--r--public/-/emojis/1/thumbsup_tone4.png (renamed from app/assets/images/emoji/thumbsup_tone4.png)bin814 -> 814 bytes
-rw-r--r--public/-/emojis/1/thumbsup_tone5.png (renamed from app/assets/images/emoji/thumbsup_tone5.png)bin814 -> 814 bytes
-rw-r--r--public/-/emojis/1/thunder_cloud_rain.png (renamed from app/assets/images/emoji/thunder_cloud_rain.png)bin1020 -> 1020 bytes
-rw-r--r--public/-/emojis/1/ticket.png (renamed from app/assets/images/emoji/ticket.png)bin763 -> 763 bytes
-rw-r--r--public/-/emojis/1/tickets.png (renamed from app/assets/images/emoji/tickets.png)bin1750 -> 1750 bytes
-rw-r--r--public/-/emojis/1/tiger.png (renamed from app/assets/images/emoji/tiger.png)bin2104 -> 2104 bytes
-rw-r--r--public/-/emojis/1/tiger2.png (renamed from app/assets/images/emoji/tiger2.png)bin2623 -> 2623 bytes
-rw-r--r--public/-/emojis/1/timer.png (renamed from app/assets/images/emoji/timer.png)bin1897 -> 1897 bytes
-rw-r--r--public/-/emojis/1/tired_face.png (renamed from app/assets/images/emoji/tired_face.png)bin1126 -> 1126 bytes
-rw-r--r--public/-/emojis/1/tm.png (renamed from app/assets/images/emoji/tm.png)bin300 -> 300 bytes
-rw-r--r--public/-/emojis/1/toilet.png (renamed from app/assets/images/emoji/toilet.png)bin726 -> 726 bytes
-rw-r--r--public/-/emojis/1/tokyo_tower.png (renamed from app/assets/images/emoji/tokyo_tower.png)bin765 -> 765 bytes
-rw-r--r--public/-/emojis/1/tomato.png (renamed from app/assets/images/emoji/tomato.png)bin1055 -> 1055 bytes
-rw-r--r--public/-/emojis/1/tone1.png (renamed from app/assets/images/emoji/tone1.png)bin372 -> 372 bytes
-rw-r--r--public/-/emojis/1/tone2.png (renamed from app/assets/images/emoji/tone2.png)bin372 -> 372 bytes
-rw-r--r--public/-/emojis/1/tone3.png (renamed from app/assets/images/emoji/tone3.png)bin375 -> 375 bytes
-rw-r--r--public/-/emojis/1/tone4.png (renamed from app/assets/images/emoji/tone4.png)bin374 -> 374 bytes
-rw-r--r--public/-/emojis/1/tone5.png (renamed from app/assets/images/emoji/tone5.png)bin374 -> 374 bytes
-rw-r--r--public/-/emojis/1/tongue.png (renamed from app/assets/images/emoji/tongue.png)bin599 -> 599 bytes
-rw-r--r--public/-/emojis/1/tools.png (renamed from app/assets/images/emoji/tools.png)bin1225 -> 1225 bytes
-rw-r--r--public/-/emojis/1/top.png (renamed from app/assets/images/emoji/top.png)bin389 -> 389 bytes
-rw-r--r--public/-/emojis/1/tophat.png (renamed from app/assets/images/emoji/tophat.png)bin845 -> 845 bytes
-rw-r--r--public/-/emojis/1/track_next.png (renamed from app/assets/images/emoji/track_next.png)bin551 -> 551 bytes
-rw-r--r--public/-/emojis/1/track_previous.png (renamed from app/assets/images/emoji/track_previous.png)bin549 -> 549 bytes
-rw-r--r--public/-/emojis/1/trackball.png (renamed from app/assets/images/emoji/trackball.png)bin892 -> 892 bytes
-rw-r--r--public/-/emojis/1/tractor.png (renamed from app/assets/images/emoji/tractor.png)bin1192 -> 1192 bytes
-rw-r--r--public/-/emojis/1/traffic_light.png (renamed from app/assets/images/emoji/traffic_light.png)bin590 -> 590 bytes
-rw-r--r--public/-/emojis/1/train.png (renamed from app/assets/images/emoji/train.png)bin1031 -> 1031 bytes
-rw-r--r--public/-/emojis/1/train2.png (renamed from app/assets/images/emoji/train2.png)bin1499 -> 1499 bytes
-rw-r--r--public/-/emojis/1/tram.png (renamed from app/assets/images/emoji/tram.png)bin1065 -> 1065 bytes
-rw-r--r--public/-/emojis/1/triangular_flag_on_post.png (renamed from app/assets/images/emoji/triangular_flag_on_post.png)bin415 -> 415 bytes
-rw-r--r--public/-/emojis/1/triangular_ruler.png (renamed from app/assets/images/emoji/triangular_ruler.png)bin369 -> 369 bytes
-rw-r--r--public/-/emojis/1/trident.png (renamed from app/assets/images/emoji/trident.png)bin668 -> 668 bytes
-rw-r--r--public/-/emojis/1/triumph.png (renamed from app/assets/images/emoji/triumph.png)bin1529 -> 1529 bytes
-rw-r--r--public/-/emojis/1/trolleybus.png (renamed from app/assets/images/emoji/trolleybus.png)bin1168 -> 1168 bytes
-rw-r--r--public/-/emojis/1/trophy.png (renamed from app/assets/images/emoji/trophy.png)bin863 -> 863 bytes
-rw-r--r--public/-/emojis/1/tropical_drink.png (renamed from app/assets/images/emoji/tropical_drink.png)bin1428 -> 1428 bytes
-rw-r--r--public/-/emojis/1/tropical_fish.png (renamed from app/assets/images/emoji/tropical_fish.png)bin1676 -> 1676 bytes
-rw-r--r--public/-/emojis/1/truck.png (renamed from app/assets/images/emoji/truck.png)bin1366 -> 1366 bytes
-rw-r--r--public/-/emojis/1/trumpet.png (renamed from app/assets/images/emoji/trumpet.png)bin1281 -> 1281 bytes
-rw-r--r--public/-/emojis/1/tulip.png (renamed from app/assets/images/emoji/tulip.png)bin1065 -> 1065 bytes
-rw-r--r--public/-/emojis/1/tumbler_glass.png (renamed from app/assets/images/emoji/tumbler_glass.png)bin2312 -> 2312 bytes
-rw-r--r--public/-/emojis/1/turkey.png (renamed from app/assets/images/emoji/turkey.png)bin1240 -> 1240 bytes
-rw-r--r--public/-/emojis/1/turtle.png (renamed from app/assets/images/emoji/turtle.png)bin1515 -> 1515 bytes
-rw-r--r--public/-/emojis/1/tv.png (renamed from app/assets/images/emoji/tv.png)bin776 -> 776 bytes
-rw-r--r--public/-/emojis/1/twisted_rightwards_arrows.png (renamed from app/assets/images/emoji/twisted_rightwards_arrows.png)bin574 -> 574 bytes
-rw-r--r--public/-/emojis/1/two.png (renamed from app/assets/images/emoji/two.png)bin567 -> 567 bytes
-rw-r--r--public/-/emojis/1/two_hearts.png (renamed from app/assets/images/emoji/two_hearts.png)bin493 -> 493 bytes
-rw-r--r--public/-/emojis/1/two_men_holding_hands.png (renamed from app/assets/images/emoji/two_men_holding_hands.png)bin1347 -> 1347 bytes
-rw-r--r--public/-/emojis/1/two_women_holding_hands.png (renamed from app/assets/images/emoji/two_women_holding_hands.png)bin1544 -> 1544 bytes
-rw-r--r--public/-/emojis/1/u5272.png (renamed from app/assets/images/emoji/u5272.png)bin411 -> 411 bytes
-rw-r--r--public/-/emojis/1/u5408.png (renamed from app/assets/images/emoji/u5408.png)bin484 -> 484 bytes
-rw-r--r--public/-/emojis/1/u55b6.png (renamed from app/assets/images/emoji/u55b6.png)bin460 -> 460 bytes
-rw-r--r--public/-/emojis/1/u6307.png (renamed from app/assets/images/emoji/u6307.png)bin504 -> 504 bytes
-rw-r--r--public/-/emojis/1/u6708.png (renamed from app/assets/images/emoji/u6708.png)bin409 -> 409 bytes
-rw-r--r--public/-/emojis/1/u6709.png (renamed from app/assets/images/emoji/u6709.png)bin434 -> 434 bytes
-rw-r--r--public/-/emojis/1/u6e80.png (renamed from app/assets/images/emoji/u6e80.png)bin564 -> 564 bytes
-rw-r--r--public/-/emojis/1/u7121.png (renamed from app/assets/images/emoji/u7121.png)bin534 -> 534 bytes
-rw-r--r--public/-/emojis/1/u7533.png (renamed from app/assets/images/emoji/u7533.png)bin306 -> 306 bytes
-rw-r--r--public/-/emojis/1/u7981.png (renamed from app/assets/images/emoji/u7981.png)bin584 -> 584 bytes
-rw-r--r--public/-/emojis/1/u7a7a.png (renamed from app/assets/images/emoji/u7a7a.png)bin456 -> 456 bytes
-rw-r--r--public/-/emojis/1/umbrella.png (renamed from app/assets/images/emoji/umbrella.png)bin1229 -> 1229 bytes
-rw-r--r--public/-/emojis/1/umbrella2.png (renamed from app/assets/images/emoji/umbrella2.png)bin897 -> 897 bytes
-rw-r--r--public/-/emojis/1/unamused.png (renamed from app/assets/images/emoji/unamused.png)bin632 -> 632 bytes
-rw-r--r--public/-/emojis/1/underage.png (renamed from app/assets/images/emoji/underage.png)bin863 -> 863 bytes
-rw-r--r--public/-/emojis/1/unicorn.png (renamed from app/assets/images/emoji/unicorn.png)bin2107 -> 2107 bytes
-rw-r--r--public/-/emojis/1/unlock.png (renamed from app/assets/images/emoji/unlock.png)bin856 -> 856 bytes
-rw-r--r--public/-/emojis/1/up.png (renamed from app/assets/images/emoji/up.png)bin405 -> 405 bytes
-rw-r--r--public/-/emojis/1/upside_down.png (renamed from app/assets/images/emoji/upside_down.png)bin602 -> 602 bytes
-rw-r--r--public/-/emojis/1/urn.png (renamed from app/assets/images/emoji/urn.png)bin742 -> 742 bytes
-rw-r--r--public/-/emojis/1/v.png (renamed from app/assets/images/emoji/v.png)bin1009 -> 1009 bytes
-rw-r--r--public/-/emojis/1/v_tone1.png (renamed from app/assets/images/emoji/v_tone1.png)bin1009 -> 1009 bytes
-rw-r--r--public/-/emojis/1/v_tone2.png (renamed from app/assets/images/emoji/v_tone2.png)bin1009 -> 1009 bytes
-rw-r--r--public/-/emojis/1/v_tone3.png (renamed from app/assets/images/emoji/v_tone3.png)bin1009 -> 1009 bytes
-rw-r--r--public/-/emojis/1/v_tone4.png (renamed from app/assets/images/emoji/v_tone4.png)bin1009 -> 1009 bytes
-rw-r--r--public/-/emojis/1/v_tone5.png (renamed from app/assets/images/emoji/v_tone5.png)bin1009 -> 1009 bytes
-rw-r--r--public/-/emojis/1/vertical_traffic_light.png (renamed from app/assets/images/emoji/vertical_traffic_light.png)bin752 -> 752 bytes
-rw-r--r--public/-/emojis/1/vhs.png (renamed from app/assets/images/emoji/vhs.png)bin632 -> 632 bytes
-rw-r--r--public/-/emojis/1/vibration_mode.png (renamed from app/assets/images/emoji/vibration_mode.png)bin683 -> 683 bytes
-rw-r--r--public/-/emojis/1/video_camera.png (renamed from app/assets/images/emoji/video_camera.png)bin1611 -> 1611 bytes
-rw-r--r--public/-/emojis/1/video_game.png (renamed from app/assets/images/emoji/video_game.png)bin765 -> 765 bytes
-rw-r--r--public/-/emojis/1/violin.png (renamed from app/assets/images/emoji/violin.png)bin1156 -> 1156 bytes
-rw-r--r--public/-/emojis/1/virgo.png (renamed from app/assets/images/emoji/virgo.png)bin618 -> 618 bytes
-rw-r--r--public/-/emojis/1/volcano.png (renamed from app/assets/images/emoji/volcano.png)bin1257 -> 1257 bytes
-rw-r--r--public/-/emojis/1/volleyball.png (renamed from app/assets/images/emoji/volleyball.png)bin1202 -> 1202 bytes
-rw-r--r--public/-/emojis/1/vs.png (renamed from app/assets/images/emoji/vs.png)bin604 -> 604 bytes
-rw-r--r--public/-/emojis/1/vulcan.png (renamed from app/assets/images/emoji/vulcan.png)bin1083 -> 1083 bytes
-rw-r--r--public/-/emojis/1/vulcan_tone1.png (renamed from app/assets/images/emoji/vulcan_tone1.png)bin1083 -> 1083 bytes
-rw-r--r--public/-/emojis/1/vulcan_tone2.png (renamed from app/assets/images/emoji/vulcan_tone2.png)bin1083 -> 1083 bytes
-rw-r--r--public/-/emojis/1/vulcan_tone3.png (renamed from app/assets/images/emoji/vulcan_tone3.png)bin1083 -> 1083 bytes
-rw-r--r--public/-/emojis/1/vulcan_tone4.png (renamed from app/assets/images/emoji/vulcan_tone4.png)bin1083 -> 1083 bytes
-rw-r--r--public/-/emojis/1/vulcan_tone5.png (renamed from app/assets/images/emoji/vulcan_tone5.png)bin1083 -> 1083 bytes
-rw-r--r--public/-/emojis/1/walking.png (renamed from app/assets/images/emoji/walking.png)bin1082 -> 1082 bytes
-rw-r--r--public/-/emojis/1/walking_tone1.png (renamed from app/assets/images/emoji/walking_tone1.png)bin1084 -> 1084 bytes
-rw-r--r--public/-/emojis/1/walking_tone2.png (renamed from app/assets/images/emoji/walking_tone2.png)bin1084 -> 1084 bytes
-rw-r--r--public/-/emojis/1/walking_tone3.png (renamed from app/assets/images/emoji/walking_tone3.png)bin1066 -> 1066 bytes
-rw-r--r--public/-/emojis/1/walking_tone4.png (renamed from app/assets/images/emoji/walking_tone4.png)bin1075 -> 1075 bytes
-rw-r--r--public/-/emojis/1/walking_tone5.png (renamed from app/assets/images/emoji/walking_tone5.png)bin1065 -> 1065 bytes
-rw-r--r--public/-/emojis/1/waning_crescent_moon.png (renamed from app/assets/images/emoji/waning_crescent_moon.png)bin1213 -> 1213 bytes
-rw-r--r--public/-/emojis/1/waning_gibbous_moon.png (renamed from app/assets/images/emoji/waning_gibbous_moon.png)bin1208 -> 1208 bytes
-rw-r--r--public/-/emojis/1/warning.png (renamed from app/assets/images/emoji/warning.png)bin565 -> 565 bytes
-rw-r--r--public/-/emojis/1/wastebasket.png (renamed from app/assets/images/emoji/wastebasket.png)bin2414 -> 2414 bytes
-rw-r--r--public/-/emojis/1/watch.png (renamed from app/assets/images/emoji/watch.png)bin785 -> 785 bytes
-rw-r--r--public/-/emojis/1/water_buffalo.png (renamed from app/assets/images/emoji/water_buffalo.png)bin1536 -> 1536 bytes
-rw-r--r--public/-/emojis/1/water_polo.png (renamed from app/assets/images/emoji/water_polo.png)bin1755 -> 1755 bytes
-rw-r--r--public/-/emojis/1/water_polo_tone1.png (renamed from app/assets/images/emoji/water_polo_tone1.png)bin1758 -> 1758 bytes
-rw-r--r--public/-/emojis/1/water_polo_tone2.png (renamed from app/assets/images/emoji/water_polo_tone2.png)bin1756 -> 1756 bytes
-rw-r--r--public/-/emojis/1/water_polo_tone3.png (renamed from app/assets/images/emoji/water_polo_tone3.png)bin1760 -> 1760 bytes
-rw-r--r--public/-/emojis/1/water_polo_tone4.png (renamed from app/assets/images/emoji/water_polo_tone4.png)bin1749 -> 1749 bytes
-rw-r--r--public/-/emojis/1/water_polo_tone5.png (renamed from app/assets/images/emoji/water_polo_tone5.png)bin1748 -> 1748 bytes
-rw-r--r--public/-/emojis/1/watermelon.png (renamed from app/assets/images/emoji/watermelon.png)bin1275 -> 1275 bytes
-rw-r--r--public/-/emojis/1/wave.png (renamed from app/assets/images/emoji/wave.png)bin1300 -> 1300 bytes
-rw-r--r--public/-/emojis/1/wave_tone1.png (renamed from app/assets/images/emoji/wave_tone1.png)bin1300 -> 1300 bytes
-rw-r--r--public/-/emojis/1/wave_tone2.png (renamed from app/assets/images/emoji/wave_tone2.png)bin1300 -> 1300 bytes
-rw-r--r--public/-/emojis/1/wave_tone3.png (renamed from app/assets/images/emoji/wave_tone3.png)bin1295 -> 1295 bytes
-rw-r--r--public/-/emojis/1/wave_tone4.png (renamed from app/assets/images/emoji/wave_tone4.png)bin1300 -> 1300 bytes
-rw-r--r--public/-/emojis/1/wave_tone5.png (renamed from app/assets/images/emoji/wave_tone5.png)bin1300 -> 1300 bytes
-rw-r--r--public/-/emojis/1/wavy_dash.png (renamed from app/assets/images/emoji/wavy_dash.png)bin359 -> 359 bytes
-rw-r--r--public/-/emojis/1/waxing_crescent_moon.png (renamed from app/assets/images/emoji/waxing_crescent_moon.png)bin1199 -> 1199 bytes
-rw-r--r--public/-/emojis/1/waxing_gibbous_moon.png (renamed from app/assets/images/emoji/waxing_gibbous_moon.png)bin1229 -> 1229 bytes
-rw-r--r--public/-/emojis/1/wc.png (renamed from app/assets/images/emoji/wc.png)bin752 -> 752 bytes
-rw-r--r--public/-/emojis/1/weary.png (renamed from app/assets/images/emoji/weary.png)bin871 -> 871 bytes
-rw-r--r--public/-/emojis/1/wedding.png (renamed from app/assets/images/emoji/wedding.png)bin1260 -> 1260 bytes
-rw-r--r--public/-/emojis/1/whale.png (renamed from app/assets/images/emoji/whale.png)bin1572 -> 1572 bytes
-rw-r--r--public/-/emojis/1/whale2.png (renamed from app/assets/images/emoji/whale2.png)bin1196 -> 1196 bytes
-rw-r--r--public/-/emojis/1/wheel_of_dharma.png (renamed from app/assets/images/emoji/wheel_of_dharma.png)bin666 -> 666 bytes
-rw-r--r--public/-/emojis/1/wheelchair.png (renamed from app/assets/images/emoji/wheelchair.png)bin683 -> 683 bytes
-rw-r--r--public/-/emojis/1/white_check_mark.png (renamed from app/assets/images/emoji/white_check_mark.png)bin547 -> 547 bytes
-rw-r--r--public/-/emojis/1/white_circle.png (renamed from app/assets/images/emoji/white_circle.png)bin351 -> 351 bytes
-rw-r--r--public/-/emojis/1/white_flower.png (renamed from app/assets/images/emoji/white_flower.png)bin941 -> 941 bytes
-rw-r--r--public/-/emojis/1/white_large_square.png (renamed from app/assets/images/emoji/white_large_square.png)bin110 -> 110 bytes
-rw-r--r--public/-/emojis/1/white_medium_small_square.png (renamed from app/assets/images/emoji/white_medium_small_square.png)bin110 -> 110 bytes
-rw-r--r--public/-/emojis/1/white_medium_square.png (renamed from app/assets/images/emoji/white_medium_square.png)bin108 -> 108 bytes
-rw-r--r--public/-/emojis/1/white_small_square.png (renamed from app/assets/images/emoji/white_small_square.png)bin108 -> 108 bytes
-rw-r--r--public/-/emojis/1/white_square_button.png (renamed from app/assets/images/emoji/white_square_button.png)bin122 -> 122 bytes
-rw-r--r--public/-/emojis/1/white_sun_cloud.png (renamed from app/assets/images/emoji/white_sun_cloud.png)bin968 -> 968 bytes
-rw-r--r--public/-/emojis/1/white_sun_rain_cloud.png (renamed from app/assets/images/emoji/white_sun_rain_cloud.png)bin1161 -> 1161 bytes
-rw-r--r--public/-/emojis/1/white_sun_small_cloud.png (renamed from app/assets/images/emoji/white_sun_small_cloud.png)bin989 -> 989 bytes
-rw-r--r--public/-/emojis/1/wilted_rose.png (renamed from app/assets/images/emoji/wilted_rose.png)bin1349 -> 1349 bytes
-rw-r--r--public/-/emojis/1/wind_blowing_face.png (renamed from app/assets/images/emoji/wind_blowing_face.png)bin1827 -> 1827 bytes
-rw-r--r--public/-/emojis/1/wind_chime.png (renamed from app/assets/images/emoji/wind_chime.png)bin1046 -> 1046 bytes
-rw-r--r--public/-/emojis/1/wine_glass.png (renamed from app/assets/images/emoji/wine_glass.png)bin655 -> 655 bytes
-rw-r--r--public/-/emojis/1/wink.png (renamed from app/assets/images/emoji/wink.png)bin746 -> 746 bytes
-rw-r--r--public/-/emojis/1/wolf.png (renamed from app/assets/images/emoji/wolf.png)bin1528 -> 1528 bytes
-rw-r--r--public/-/emojis/1/woman.png (renamed from app/assets/images/emoji/woman.png)bin1212 -> 1212 bytes
-rw-r--r--public/-/emojis/1/woman_tone1.png (renamed from app/assets/images/emoji/woman_tone1.png)bin1212 -> 1212 bytes
-rw-r--r--public/-/emojis/1/woman_tone2.png (renamed from app/assets/images/emoji/woman_tone2.png)bin1212 -> 1212 bytes
-rw-r--r--public/-/emojis/1/woman_tone3.png (renamed from app/assets/images/emoji/woman_tone3.png)bin1202 -> 1202 bytes
-rw-r--r--public/-/emojis/1/woman_tone4.png (renamed from app/assets/images/emoji/woman_tone4.png)bin1195 -> 1195 bytes
-rw-r--r--public/-/emojis/1/woman_tone5.png (renamed from app/assets/images/emoji/woman_tone5.png)bin1202 -> 1202 bytes
-rw-r--r--public/-/emojis/1/womans_clothes.png (renamed from app/assets/images/emoji/womans_clothes.png)bin1042 -> 1042 bytes
-rw-r--r--public/-/emojis/1/womans_hat.png (renamed from app/assets/images/emoji/womans_hat.png)bin1553 -> 1553 bytes
-rw-r--r--public/-/emojis/1/womens.png (renamed from app/assets/images/emoji/womens.png)bin577 -> 577 bytes
-rw-r--r--public/-/emojis/1/worried.png (renamed from app/assets/images/emoji/worried.png)bin715 -> 715 bytes
-rw-r--r--public/-/emojis/1/wrench.png (renamed from app/assets/images/emoji/wrench.png)bin418 -> 418 bytes
-rw-r--r--public/-/emojis/1/wrestlers.png (renamed from app/assets/images/emoji/wrestlers.png)bin2556 -> 2556 bytes
-rw-r--r--public/-/emojis/1/wrestlers_tone1.png (renamed from app/assets/images/emoji/wrestlers_tone1.png)bin2563 -> 2563 bytes
-rw-r--r--public/-/emojis/1/wrestlers_tone2.png (renamed from app/assets/images/emoji/wrestlers_tone2.png)bin2553 -> 2553 bytes
-rw-r--r--public/-/emojis/1/wrestlers_tone3.png (renamed from app/assets/images/emoji/wrestlers_tone3.png)bin2541 -> 2541 bytes
-rw-r--r--public/-/emojis/1/wrestlers_tone4.png (renamed from app/assets/images/emoji/wrestlers_tone4.png)bin2553 -> 2553 bytes
-rw-r--r--public/-/emojis/1/wrestlers_tone5.png (renamed from app/assets/images/emoji/wrestlers_tone5.png)bin2542 -> 2542 bytes
-rw-r--r--public/-/emojis/1/writing_hand.png (renamed from app/assets/images/emoji/writing_hand.png)bin1001 -> 1001 bytes
-rw-r--r--public/-/emojis/1/writing_hand_tone1.png (renamed from app/assets/images/emoji/writing_hand_tone1.png)bin988 -> 988 bytes
-rw-r--r--public/-/emojis/1/writing_hand_tone2.png (renamed from app/assets/images/emoji/writing_hand_tone2.png)bin987 -> 987 bytes
-rw-r--r--public/-/emojis/1/writing_hand_tone3.png (renamed from app/assets/images/emoji/writing_hand_tone3.png)bin977 -> 977 bytes
-rw-r--r--public/-/emojis/1/writing_hand_tone4.png (renamed from app/assets/images/emoji/writing_hand_tone4.png)bin973 -> 973 bytes
-rw-r--r--public/-/emojis/1/writing_hand_tone5.png (renamed from app/assets/images/emoji/writing_hand_tone5.png)bin970 -> 970 bytes
-rw-r--r--public/-/emojis/1/x.png (renamed from app/assets/images/emoji/x.png)bin298 -> 298 bytes
-rw-r--r--public/-/emojis/1/yellow_heart.png (renamed from app/assets/images/emoji/yellow_heart.png)bin435 -> 435 bytes
-rw-r--r--public/-/emojis/1/yen.png (renamed from app/assets/images/emoji/yen.png)bin421 -> 421 bytes
-rw-r--r--public/-/emojis/1/yin_yang.png (renamed from app/assets/images/emoji/yin_yang.png)bin776 -> 776 bytes
-rw-r--r--public/-/emojis/1/yum.png (renamed from app/assets/images/emoji/yum.png)bin896 -> 896 bytes
-rw-r--r--public/-/emojis/1/zap.png (renamed from app/assets/images/emoji/zap.png)bin413 -> 413 bytes
-rw-r--r--public/-/emojis/1/zero.png (renamed from app/assets/images/emoji/zero.png)bin560 -> 560 bytes
-rw-r--r--public/-/emojis/1/zipper_mouth.png (renamed from app/assets/images/emoji/zipper_mouth.png)bin722 -> 722 bytes
-rw-r--r--public/-/emojis/1/zzz.png (renamed from app/assets/images/emoji/zzz.png)bin540 -> 540 bytes
-rw-r--r--qa/.gitignore1
-rw-r--r--qa/Dockerfile2
-rw-r--r--qa/Gemfile5
-rw-r--r--qa/Gemfile.lock23
-rw-r--r--qa/README.md40
-rw-r--r--qa/Rakefile18
-rw-r--r--qa/qa.rb36
-rw-r--r--qa/qa/ce/strategy.rb5
-rw-r--r--qa/qa/fixtures/auto_devops_rack/config.ru2
-rw-r--r--qa/qa/git/repository.rb150
-rw-r--r--qa/qa/page/admin/menu.rb9
-rw-r--r--qa/qa/page/admin/settings/component/account_and_limit.rb26
-rw-r--r--qa/qa/page/admin/settings/general.rb23
-rw-r--r--qa/qa/page/alert/auto_devops_alert.rb13
-rw-r--r--qa/qa/page/base.rb57
-rw-r--r--qa/qa/page/component/clone_panel.rb5
-rw-r--r--qa/qa/page/component/lazy_loader.rb15
-rw-r--r--qa/qa/page/component/legacy_clone_panel.rb5
-rw-r--r--qa/qa/page/component/note.rb55
-rw-r--r--qa/qa/page/component/select2.rb6
-rw-r--r--qa/qa/page/group/show.rb18
-rw-r--r--qa/qa/page/label/index.rb21
-rw-r--r--qa/qa/page/main/login.rb38
-rw-r--r--qa/qa/page/main/menu.rb8
-rw-r--r--qa/qa/page/main/sign_up.rb2
-rw-r--r--qa/qa/page/merge_request/show.rb69
-rw-r--r--qa/qa/page/profile/personal_access_tokens.rb38
-rw-r--r--qa/qa/page/project/branches/show.rb64
-rw-r--r--qa/qa/page/project/import/github.rb30
-rw-r--r--qa/qa/page/project/issue/show.rb30
-rw-r--r--qa/qa/page/project/job/show.rb27
-rw-r--r--qa/qa/page/project/menu.rb153
-rw-r--r--qa/qa/page/project/new.rb12
-rw-r--r--qa/qa/page/project/operations/kubernetes/add_existing.rb4
-rw-r--r--qa/qa/page/project/operations/kubernetes/show.rb15
-rw-r--r--qa/qa/page/project/pipeline/show.rb16
-rw-r--r--qa/qa/page/project/settings/ci_cd.rb5
-rw-r--r--qa/qa/page/project/settings/deploy_keys.rb33
-rw-r--r--qa/qa/page/project/settings/mirroring_repositories.rb2
-rw-r--r--qa/qa/page/project/show.rb10
-rw-r--r--qa/qa/page/project/sub_menus/ci_cd.rb25
-rw-r--r--qa/qa/page/project/sub_menus/common.rb23
-rw-r--r--qa/qa/page/project/sub_menus/issues.rb52
-rw-r--r--qa/qa/page/project/sub_menus/operations.rb47
-rw-r--r--qa/qa/page/project/sub_menus/repository.rb44
-rw-r--r--qa/qa/page/project/sub_menus/settings.rb61
-rw-r--r--qa/qa/page/project/web_ide/edit.rb22
-rw-r--r--qa/qa/page/project/wiki/new.rb40
-rw-r--r--qa/qa/page/settings/common.rb2
-rw-r--r--qa/qa/resource/base.rb20
-rw-r--r--qa/qa/resource/deploy_key.rb6
-rw-r--r--qa/qa/resource/events/base.rb37
-rw-r--r--qa/qa/resource/events/project.rb25
-rw-r--r--qa/qa/resource/fork.rb15
-rw-r--r--qa/qa/resource/group.rb2
-rw-r--r--qa/qa/resource/kubernetes_cluster.rb10
-rw-r--r--qa/qa/resource/merge_request.rb5
-rw-r--r--qa/qa/resource/merge_request_from_fork.rb2
-rw-r--r--qa/qa/resource/project.rb14
-rw-r--r--qa/qa/resource/project_imported_from_github.rb2
-rw-r--r--qa/qa/resource/repository/project_push.rb4
-rw-r--r--qa/qa/resource/repository/push.rb27
-rw-r--r--qa/qa/resource/user.rb19
-rw-r--r--qa/qa/runtime/browser.rb64
-rw-r--r--qa/qa/runtime/env.rb46
-rw-r--r--qa/qa/runtime/namespace.rb4
-rw-r--r--qa/qa/runtime/user.rb4
-rw-r--r--qa/qa/scenario/test/integration/oauth.rb13
-rw-r--r--qa/qa/service/kubernetes_cluster.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb29
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb37
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb34
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb93
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb18
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb5
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb72
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb5
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb68
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb61
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb13
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb20
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb236
-rw-r--r--qa/qa/support/api.rb28
-rw-r--r--qa/qa/support/page/logging.rb55
-rw-r--r--qa/qa/support/retrier.rb28
-rw-r--r--qa/qa/support/waiter.rb31
-rw-r--r--qa/qa/tools/delete_subgroups.rb66
-rw-r--r--qa/qa/tools/generate_perf_testdata.rb141
-rw-r--r--qa/qa/tools/revoke_all_personal_access_tokens.rb44
-rw-r--r--qa/qa/vendor/github/page/base.rb14
-rw-r--r--qa/qa/vendor/github/page/login.rb23
-rw-r--r--qa/spec/git/repository_spec.rb136
-rw-r--r--qa/spec/helpers/stub_env.rb40
-rw-r--r--qa/spec/page/base_spec.rb30
-rw-r--r--qa/spec/page/logging_spec.rb55
-rw-r--r--qa/spec/resource/base_spec.rb42
-rw-r--r--qa/spec/resource/events/base_spec.rb29
-rw-r--r--qa/spec/resource/events/project_spec.rb69
-rw-r--r--qa/spec/resource/user_spec.rb118
-rw-r--r--qa/spec/runtime/api/client_spec.rb2
-rw-r--r--qa/spec/runtime/env_spec.rb61
-rw-r--r--qa/spec/scenario/test/integration/oauth_spec.rb9
-rw-r--r--qa/spec/shared_examples/scenario_shared_examples.rb (renamed from qa/spec/support/shared_examples/scenario_shared_examples.rb)0
-rw-r--r--qa/spec/spec_helper.rb63
-rw-r--r--qa/spec/spec_helper_spec.rb355
-rw-r--r--qa/spec/support/stub_env.rb40
-rw-r--r--qa/spec/support/waiter_spec.rb37
-rw-r--r--rubocop/cop/inject_enterprise_edition_module.rb10
-rw-r--r--rubocop/spec_helpers.rb11
-rwxr-xr-xscripts/build_assets_image4
-rwxr-xr-xscripts/clean-old-cached-assets6
-rwxr-xr-xscripts/lint-changelog-yaml2
-rwxr-xr-xscripts/lint-doc.sh2
-rwxr-xr-xscripts/lint-rugged8
-rw-r--r--scripts/prepare_build.sh2
-rwxr-xr-xscripts/review_apps/review-apps.sh46
-rwxr-xr-xscripts/security-harness2
-rwxr-xr-xscripts/static-analysis1
-rwxr-xr-xscripts/trigger-build6
-rw-r--r--spec/bin/changelog_spec.rb2
-rw-r--r--spec/config/application_spec.rb34
-rw-r--r--spec/controllers/admin/appearances_controller_spec.rb91
-rw-r--r--spec/controllers/admin/requests_profiles_controller_spec.rb47
-rw-r--r--spec/controllers/admin/runners_controller_spec.rb19
-rw-r--r--spec/controllers/admin/users_controller_spec.rb25
-rw-r--r--spec/controllers/application_controller_spec.rb12
-rw-r--r--spec/controllers/boards/issues_controller_spec.rb12
-rw-r--r--spec/controllers/boards/lists_controller_spec.rb7
-rw-r--r--spec/controllers/concerns/checks_collaboration_spec.rb2
-rw-r--r--spec/controllers/concerns/issuable_collections_spec.rb49
-rw-r--r--spec/controllers/concerns/send_file_upload_spec.rb42
-rw-r--r--spec/controllers/dashboard/milestones_controller_spec.rb31
-rw-r--r--spec/controllers/google_api/authorizations_controller_spec.rb60
-rw-r--r--spec/controllers/graphql_controller_spec.rb112
-rw-r--r--spec/controllers/groups/children_controller_spec.rb6
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb21
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb2
-rw-r--r--spec/controllers/groups/milestones_controller_spec.rb33
-rw-r--r--spec/controllers/groups/settings/ci_cd_controller_spec.rb55
-rw-r--r--spec/controllers/groups/shared_projects_controller_spec.rb2
-rw-r--r--spec/controllers/groups_controller_spec.rb4
-rw-r--r--spec/controllers/help_controller_spec.rb40
-rw-r--r--spec/controllers/import/bitbucket_controller_spec.rb11
-rw-r--r--spec/controllers/import/bitbucket_server_controller_spec.rb24
-rw-r--r--spec/controllers/import/gitea_controller_spec.rb8
-rw-r--r--spec/controllers/import/github_controller_spec.rb12
-rw-r--r--spec/controllers/omniauth_callbacks_controller_spec.rb59
-rw-r--r--spec/controllers/profiles/avatars_controller_spec.rb2
-rw-r--r--spec/controllers/profiles/preferences_controller_spec.rb4
-rw-r--r--spec/controllers/projects/artifacts_controller_spec.rb16
-rw-r--r--spec/controllers/projects/autocomplete_sources_controller_spec.rb69
-rw-r--r--spec/controllers/projects/avatars_controller_spec.rb36
-rw-r--r--spec/controllers/projects/badges_controller_spec.rb41
-rw-r--r--spec/controllers/projects/branches_controller_spec.rb6
-rw-r--r--spec/controllers/projects/ci/lints_controller_spec.rb1
-rw-r--r--spec/controllers/projects/commit_controller_spec.rb2
-rw-r--r--spec/controllers/projects/environments_controller_spec.rb120
-rw-r--r--spec/controllers/projects/error_tracking_controller_spec.rb240
-rw-r--r--spec/controllers/projects/graphs_controller_spec.rb16
-rw-r--r--spec/controllers/projects/group_links_controller_spec.rb37
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb79
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb79
-rw-r--r--spec/controllers/projects/merge_requests/creations_controller_spec.rb2
-rw-r--r--spec/controllers/projects/merge_requests/diffs_controller_spec.rb13
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb94
-rw-r--r--spec/controllers/projects/milestones_controller_spec.rb12
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb20
-rw-r--r--spec/controllers/projects/pages_controller_spec.rb16
-rw-r--r--spec/controllers/projects/pages_domains_controller_spec.rb17
-rw-r--r--spec/controllers/projects/pipeline_schedules_controller_spec.rb11
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb49
-rw-r--r--spec/controllers/projects/raw_controller_spec.rb75
-rw-r--r--spec/controllers/projects/registry/tags_controller_spec.rb2
-rw-r--r--spec/controllers/projects/releases_controller_spec.rb16
-rw-r--r--spec/controllers/projects/serverless/functions_controller_spec.rb40
-rw-r--r--spec/controllers/projects/services_controller_spec.rb10
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb174
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb42
-rw-r--r--spec/controllers/projects/wikis_controller_spec.rb85
-rw-r--r--spec/controllers/projects_controller_spec.rb79
-rw-r--r--spec/controllers/search_controller_spec.rb2
-rw-r--r--spec/controllers/snippets_controller_spec.rb45
-rw-r--r--spec/controllers/uploads_controller_spec.rb16
-rw-r--r--spec/controllers/users_controller_spec.rb66
-rw-r--r--spec/db/importers/common_metrics_importer_spec.rb8
-rw-r--r--spec/db/schema_spec.rb7
-rw-r--r--spec/factories/appearances.rb4
-rw-r--r--spec/factories/ci/bridge.rb12
-rw-r--r--spec/factories/ci/builds.rb58
-rw-r--r--spec/factories/ci/group_variables.rb1
-rw-r--r--spec/factories/ci/variables.rb1
-rw-r--r--spec/factories/clusters/clusters.rb8
-rw-r--r--spec/factories/clusters/platforms/kubernetes.rb4
-rw-r--r--spec/factories/commits.rb10
-rw-r--r--spec/factories/container_repositories.rb2
-rw-r--r--spec/factories/error_tracking/error.rb24
-rw-r--r--spec/factories/error_tracking/project.rb15
-rw-r--r--spec/factories/group_members.rb2
-rw-r--r--spec/factories/import_states.rb (renamed from spec/factories/import_state.rb)0
-rw-r--r--spec/factories/merge_requests.rb9
-rw-r--r--spec/factories/personal_access_tokens.rb5
-rw-r--r--spec/factories/project_daily_statistics.rb8
-rw-r--r--spec/factories/project_error_tracking_settings.rb12
-rw-r--r--spec/factories/projects.rb20
-rw-r--r--spec/factories/releases.rb7
-rw-r--r--spec/factories/releases/link.rb9
-rw-r--r--spec/factories/services.rb12
-rw-r--r--spec/factories/users.rb11
-rw-r--r--spec/factories/wiki_pages.rb2
-rw-r--r--spec/features/admin/admin_abuse_reports_spec.rb2
-rw-r--r--spec/features/admin/admin_appearance_spec.rb44
-rw-r--r--spec/features/admin/admin_projects_spec.rb2
-rw-r--r--spec/features/admin/admin_runners_spec.rb50
-rw-r--r--spec/features/admin/admin_settings_spec.rb2
-rw-r--r--spec/features/admin/admin_users_spec.rb42
-rw-r--r--spec/features/atom/dashboard_issues_spec.rb2
-rw-r--r--spec/features/atom/dashboard_spec.rb2
-rw-r--r--spec/features/atom/issues_spec.rb2
-rw-r--r--spec/features/atom/users_spec.rb2
-rw-r--r--spec/features/boards/boards_spec.rb8
-rw-r--r--spec/features/boards/modal_filter_spec.rb6
-rw-r--r--spec/features/boards/new_issue_spec.rb21
-rw-r--r--spec/features/clusters/cluster_detail_page_spec.rb69
-rw-r--r--spec/features/container_registry_spec.rb2
-rw-r--r--spec/features/cycle_analytics_spec.rb2
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb4
-rw-r--r--spec/features/dashboard/help_spec.rb14
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb1
-rw-r--r--spec/features/dashboard/projects_spec.rb35
-rw-r--r--spec/features/dashboard/root_explore_spec.rb33
-rw-r--r--spec/features/dashboard/shortcuts_spec.rb4
-rw-r--r--spec/features/dashboard/snippets_spec.rb15
-rw-r--r--spec/features/dashboard/todos/todos_spec.rb20
-rw-r--r--spec/features/dashboard/user_filters_projects_spec.rb2
-rw-r--r--spec/features/display_system_header_and_footer_bar_spec.rb137
-rw-r--r--spec/features/explore/user_explores_projects_spec.rb18
-rw-r--r--spec/features/group_variables_spec.rb4
-rw-r--r--spec/features/groups/empty_states_spec.rb44
-rw-r--r--spec/features/groups/group_settings_spec.rb8
-rw-r--r--spec/features/groups/labels/create_spec.rb23
-rw-r--r--spec/features/groups/labels/index_spec.rb14
-rw-r--r--spec/features/groups/milestone_spec.rb5
-rw-r--r--spec/features/groups/milestones_sorting_spec.rb1
-rw-r--r--spec/features/groups_spec.rb14
-rw-r--r--spec/features/ics/dashboard_issues_spec.rb2
-rw-r--r--spec/features/ics/group_issues_spec.rb2
-rw-r--r--spec/features/ics/project_issues_spec.rb2
-rw-r--r--spec/features/issuables/issuable_list_spec.rb24
-rw-r--r--spec/features/issuables/markdown_references/internal_references_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb6
-rw-r--r--spec/features/issues/filtered_search/dropdown_author_spec.rb2
-rw-r--r--spec/features/issues/filtered_search/dropdown_emoji_spec.rb6
-rw-r--r--spec/features/issues/filtered_search/dropdown_hint_spec.rb11
-rw-r--r--spec/features/issues/filtered_search/dropdown_label_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/dropdown_milestone_spec.rb10
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb10
-rw-r--r--spec/features/issues/filtered_search/search_bar_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/visual_tokens_spec.rb27
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb48
-rw-r--r--spec/features/issues/resource_label_events_spec.rb2
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb2
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb18
-rw-r--r--spec/features/issues/user_uses_quick_actions_spec.rb4
-rw-r--r--spec/features/issues_spec.rb4
-rw-r--r--spec/features/labels_hierarchy_spec.rb4
-rw-r--r--spec/features/markdown/copy_as_gfm_spec.rb266
-rw-r--r--spec/features/markdown/markdown_spec.rb27
-rw-r--r--spec/features/markdown/math_spec.rb22
-rw-r--r--spec/features/merge_request/maintainer_edits_fork_spec.rb2
-rw-r--r--spec/features/merge_request/user_accepts_merge_request_spec.rb8
-rw-r--r--spec/features/merge_request/user_comments_on_diff_spec.rb1
-rw-r--r--spec/features/merge_request/user_creates_image_diff_notes_spec.rb38
-rw-r--r--spec/features/merge_request/user_creates_merge_request_spec.rb2
-rw-r--r--spec/features/merge_request/user_creates_mr_spec.rb2
-rw-r--r--spec/features/merge_request/user_customizes_merge_commit_message_spec.rb10
-rw-r--r--spec/features/merge_request/user_merges_immediately_spec.rb2
-rw-r--r--spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb10
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb2
-rw-r--r--spec/features/merge_request/user_posts_notes_spec.rb32
-rw-r--r--spec/features/merge_request/user_resolves_conflicts_spec.rb2
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb1
-rw-r--r--spec/features/merge_request/user_sees_diff_spec.rb70
-rw-r--r--spec/features/merge_request/user_sees_discussions_spec.rb12
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb8
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb48
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb48
-rw-r--r--spec/features/merge_request/user_toggles_whitespace_changes_spec.rb12
-rw-r--r--spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb37
-rw-r--r--spec/features/merge_request/user_views_diffs_spec.rb4
-rw-r--r--spec/features/merge_requests/user_lists_merge_requests_spec.rb4
-rw-r--r--spec/features/merge_requests/user_mass_updates_spec.rb2
-rw-r--r--spec/features/merge_requests/user_squashes_merge_request_spec.rb4
-rw-r--r--spec/features/milestone_spec.rb2
-rw-r--r--spec/features/profiles/active_sessions_spec.rb48
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb77
-rw-r--r--spec/features/profiles/user_visits_profile_preferences_page_spec.rb24
-rw-r--r--spec/features/project_variables_spec.rb2
-rw-r--r--spec/features/projects/artifacts/user_browses_artifacts_spec.rb4
-rw-r--r--spec/features/projects/artifacts/user_downloads_artifacts_spec.rb2
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb24
-rw-r--r--spec/features/projects/blobs/edit_spec.rb17
-rw-r--r--spec/features/projects/branches/user_views_branches_spec.rb2
-rw-r--r--spec/features/projects/branches_spec.rb32
-rw-r--r--spec/features/projects/clusters/applications_spec.rb38
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb56
-rw-r--r--spec/features/projects/clusters/user_spec.rb36
-rw-r--r--spec/features/projects/commit/builds_spec.rb2
-rw-r--r--spec/features/projects/commit/cherry_pick_spec.rb4
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb2
-rw-r--r--spec/features/projects/compare_spec.rb15
-rw-r--r--spec/features/projects/deploy_keys_spec.rb2
-rw-r--r--spec/features/projects/environments/environment_spec.rb6
-rw-r--r--spec/features/projects/environments/environments_spec.rb31
-rw-r--r--spec/features/projects/files/undo_template_spec.rb2
-rw-r--r--spec/features/projects/files/user_browses_lfs_files_spec.rb4
-rw-r--r--spec/features/projects/files/user_creates_files_spec.rb2
-rw-r--r--spec/features/projects/files/user_edits_files_spec.rb2
-rw-r--r--spec/features/projects/jobs_spec.rb33
-rw-r--r--spec/features/projects/labels/update_prioritization_spec.rb2
-rw-r--r--spec/features/projects/members/invite_group_spec.rb2
-rw-r--r--spec/features/projects/pages_spec.rb107
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb54
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb19
-rw-r--r--spec/features/projects/releases/user_views_releases_spec.rb46
-rw-r--r--spec/features/projects/serverless/functions_spec.rb9
-rw-r--r--spec/features/projects/services/disable_triggers_spec.rb5
-rw-r--r--spec/features/projects/services/user_activates_hipchat_spec.rb38
-rw-r--r--spec/features/projects/services/user_activates_issue_tracker_spec.rb35
-rw-r--r--spec/features/projects/services/user_activates_youtrack_spec.rb89
-rw-r--r--spec/features/projects/services/user_views_services_spec.rb3
-rw-r--r--spec/features/projects/settings/forked_project_settings_spec.rb1
-rw-r--r--spec/features/projects/settings/operations_settings_spec.rb100
-rw-r--r--spec/features/projects/settings/pipelines_settings_spec.rb25
-rw-r--r--spec/features/projects/settings/project_settings_spec.rb43
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb10
-rw-r--r--spec/features/projects/settings/user_changes_default_branch_spec.rb3
-rw-r--r--spec/features/projects/settings/user_manages_group_links_spec.rb1
-rw-r--r--spec/features/projects/settings/user_tags_project_spec.rb6
-rw-r--r--spec/features/projects/snippets/user_comments_on_snippet_spec.rb2
-rw-r--r--spec/features/projects/tags/user_edits_tags_spec.rb82
-rw-r--r--spec/features/projects/user_sees_sidebar_spec.rb102
-rw-r--r--spec/features/projects/wiki/markdown_preview_spec.rb21
-rw-r--r--spec/features/projects/wiki/user_creates_wiki_page_spec.rb8
-rw-r--r--spec/features/projects/wiki/user_updates_wiki_page_spec.rb7
-rw-r--r--spec/features/projects/wiki/user_views_wiki_page_spec.rb7
-rw-r--r--spec/features/projects_spec.rb51
-rw-r--r--spec/features/protected_branches_spec.rb2
-rw-r--r--spec/features/runners_spec.rb7
-rw-r--r--spec/features/security/admin_access_spec.rb2
-rw-r--r--spec/features/security/dashboard_access_spec.rb2
-rw-r--r--spec/features/security/group/private_access_spec.rb32
-rw-r--r--spec/features/security/profile_access_spec.rb2
-rw-r--r--spec/features/security/project/internal_access_spec.rb8
-rw-r--r--spec/features/security/project/private_access_spec.rb4
-rw-r--r--spec/features/security/project/public_access_spec.rb12
-rw-r--r--spec/features/security/project/snippet/internal_access_spec.rb2
-rw-r--r--spec/features/security/project/snippet/private_access_spec.rb4
-rw-r--r--spec/features/security/project/snippet/public_access_spec.rb2
-rw-r--r--spec/features/snippets/show_spec.rb29
-rw-r--r--spec/features/task_lists_spec.rb66
-rw-r--r--spec/features/users/overview_spec.rb5
-rw-r--r--spec/features/users/signup_spec.rb28
-rw-r--r--spec/features/users/terms_spec.rb2
-rw-r--r--spec/finders/admin/runners_finder_spec.rb8
-rw-r--r--spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb66
-rw-r--r--spec/finders/concerns/finder_methods_spec.rb22
-rw-r--r--spec/finders/contributed_projects_finder_spec.rb12
-rw-r--r--spec/finders/groups_finder_spec.rb20
-rw-r--r--spec/finders/issues_finder_spec.rb140
-rw-r--r--spec/finders/merge_request_target_project_finder_spec.rb2
-rw-r--r--spec/finders/merge_requests_finder_spec.rb512
-rw-r--r--spec/finders/milestones_finder_spec.rb6
-rw-r--r--spec/finders/notes_finder_spec.rb2
-rw-r--r--spec/finders/projects/serverless/functions_finder_spec.rb25
-rw-r--r--spec/finders/projects_finder_spec.rb2
-rw-r--r--spec/finders/releases_finder_spec.rb42
-rw-r--r--spec/finders/snippets_finder_spec.rb2
-rw-r--r--spec/fixtures/api/schemas/cluster_status.json4
-rw-r--r--spec/fixtures/api/schemas/entities/diff_viewer.json27
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_basic.json3
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_widget.json10
-rw-r--r--spec/fixtures/api/schemas/environment.json1
-rw-r--r--spec/fixtures/api/schemas/error_tracking/error.json21
-rw-r--r--spec/fixtures/api/schemas/error_tracking/index.json15
-rw-r--r--spec/fixtures/api/schemas/error_tracking/list_projects.json13
-rw-r--r--spec/fixtures/api/schemas/error_tracking/project.json19
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/group_labels.json19
-rw-r--r--spec/fixtures/api/schemas/registry/repository.json9
-rw-r--r--spec/fixtures/api/schemas/registry/tag.json7
-rw-r--r--spec/fixtures/api/schemas/release.json29
-rw-r--r--spec/fixtures/api/schemas/release/link.json11
-rw-r--r--spec/fixtures/api/schemas/release/links.json4
-rw-r--r--spec/fixtures/api/schemas/releases.json4
-rw-r--r--spec/fixtures/clusters/sample_cert.pem2
-rw-r--r--spec/fixtures/csv_comma.csv4
-rw-r--r--spec/fixtures/csv_semicolon.csv5
-rw-r--r--spec/fixtures/csv_tab.csv4
-rw-r--r--spec/fixtures/emails/merge_request_multiple_patches.eml2
-rw-r--r--spec/fixtures/emails/merge_request_with_conflicting_patch.eml2
-rw-r--r--spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml2
-rw-r--r--spec/fixtures/emails/valid_merge_request_with_patch.eml2
-rw-r--r--spec/fixtures/emails/valid_new_issue.eml4
-rw-r--r--spec/fixtures/emails/valid_new_issue_empty.eml4
-rw-r--r--spec/fixtures/emails/valid_new_issue_legacy.eml23
-rw-r--r--spec/fixtures/emails/valid_new_issue_with_quote.eml4
-rw-r--r--spec/fixtures/emails/valid_new_merge_request.eml6
-rw-r--r--spec/fixtures/emails/valid_new_merge_request_legacy.eml20
-rw-r--r--spec/fixtures/emails/valid_new_merge_request_no_description.eml4
-rw-r--r--spec/fixtures/emails/valid_new_merge_request_no_subject.eml4
-rw-r--r--spec/fixtures/emails/wrong_incoming_email_token.eml18
-rw-r--r--spec/fixtures/emails/wrong_issue_incoming_email_token.eml18
-rw-r--r--spec/fixtures/emails/wrong_merge_request_incoming_email_token.eml18
-rw-r--r--spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml1
-rw-r--r--spec/fixtures/malicious.bundle1
-rw-r--r--spec/fixtures/markdown.md.erb2
-rw-r--r--spec/fixtures/pages_non_writeable.zipbin0 -> 727 bytes
-rw-r--r--spec/fixtures/safe_zip/invalid-symlink-does-not-exist.zipbin0 -> 1183 bytes
-rw-r--r--spec/fixtures/safe_zip/invalid-symlinks-outside.zipbin0 -> 1309 bytes
-rw-r--r--spec/fixtures/safe_zip/valid-non-writeable.zipbin0 -> 727 bytes
-rw-r--r--spec/fixtures/safe_zip/valid-simple.zipbin0 -> 1144 bytes
-rw-r--r--spec/fixtures/safe_zip/valid-symlinks-first.zipbin0 -> 528 bytes
-rw-r--r--spec/fixtures/security-reports/deprecated/gl-dependency-scanning-report.json178
-rw-r--r--spec/fixtures/security-reports/deprecated/gl-sast-report.json944
-rw-r--r--spec/fixtures/security-reports/feature-branch.zipbin7163 -> 7140 bytes
-rw-r--r--spec/fixtures/security-reports/feature-branch/gl-container-scanning-report.json30
-rw-r--r--spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json337
-rw-r--r--spec/fixtures/security-reports/feature-branch/gl-license-management-report.json222
-rw-r--r--spec/fixtures/security-reports/feature-branch/gl-sast-report.json1825
-rw-r--r--spec/fixtures/security-reports/master.zipbin6710 -> 9413 bytes
-rw-r--r--spec/fixtures/security-reports/master/gl-container-scanning-report.json119
-rw-r--r--spec/fixtures/security-reports/master/gl-dependency-scanning-report.json337
-rw-r--r--spec/fixtures/security-reports/master/gl-license-management-report.json705
-rw-r--r--spec/fixtures/security-reports/master/gl-sast-report.json1825
-rw-r--r--spec/fixtures/security-reports/remediations/gl-dependency-scanning-report.json104
-rw-r--r--spec/fixtures/security-reports/remediations/remediation.patch180
-rw-r--r--spec/fixtures/security-reports/remediations/yarn.lock104
-rw-r--r--spec/fixtures/sentry/issues_sample_response.json42
-rw-r--r--spec/fixtures/sentry/list_projects_sample_response.json81
-rw-r--r--spec/fixtures/trace/sample_trace18
-rw-r--r--spec/frontend/__mocks__/file_mock.js1
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js253
-rw-r--r--spec/frontend/issuable_suggestions/components/app_spec.js (renamed from spec/javascripts/issuable_suggestions/components/app_spec.js)0
-rw-r--r--spec/frontend/issuable_suggestions/components/item_spec.js (renamed from spec/javascripts/issuable_suggestions/components/item_spec.js)0
-rw-r--r--spec/frontend/issuable_suggestions/mock_data.js (renamed from spec/javascripts/issuable_suggestions/mock_data.js)0
-rw-r--r--spec/frontend/lib/utils/ajax_cache_spec.js161
-rw-r--r--spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap20
-rw-r--r--spec/frontend/notes/components/discussion_jump_to_next_button_spec.js30
-rw-r--r--spec/frontend/test_setup.js18
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap37
-rw-r--r--spec/frontend/vue_shared/components/file_row_header_spec.js36
-rw-r--r--spec/graphql/features/authorization_spec.rb106
-rw-r--r--spec/graphql/resolvers/base_resolver_spec.rb31
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb81
-rw-r--r--spec/graphql/resolvers/merge_request_resolver_spec.rb45
-rw-r--r--spec/graphql/resolvers/merge_requests_resolver_spec.rb61
-rw-r--r--spec/graphql/resolvers/metadata_resolver_spec.rb11
-rw-r--r--spec/graphql/resolvers/project_pipelines_resolver_spec.rb2
-rw-r--r--spec/graphql/types/issuable_state_enum_spec.rb9
-rw-r--r--spec/graphql/types/issue_state_enum_spec.rb9
-rw-r--r--spec/graphql/types/merge_request_state_enum_spec.rb13
-rw-r--r--spec/graphql/types/metadata_type_spec.rb5
-rw-r--r--spec/graphql/types/permission_types/base_permission_type_spec.rb2
-rw-r--r--spec/graphql/types/permission_types/project_spec.rb2
-rw-r--r--spec/graphql/types/project_type_spec.rb8
-rw-r--r--spec/graphql/types/query_type_spec.rb15
-rw-r--r--spec/helpers/appearances_helper_spec.rb76
-rw-r--r--spec/helpers/application_helper_spec.rb15
-rw-r--r--spec/helpers/application_settings_helper_spec.rb39
-rw-r--r--spec/helpers/auto_devops_helper_spec.rb35
-rw-r--r--spec/helpers/blob_helper_spec.rb8
-rw-r--r--spec/helpers/commits_helper_spec.rb2
-rw-r--r--spec/helpers/diff_helper_spec.rb37
-rw-r--r--spec/helpers/emails_helper_spec.rb68
-rw-r--r--spec/helpers/import_helper_spec.rb61
-rw-r--r--spec/helpers/issuables_helper_spec.rb9
-rw-r--r--spec/helpers/issues_helper_spec.rb2
-rw-r--r--spec/helpers/labels_helper_spec.rb13
-rw-r--r--spec/helpers/markup_helper_spec.rb21
-rw-r--r--spec/helpers/members_helper_spec.rb4
-rw-r--r--spec/helpers/notes_helper_spec.rb4
-rw-r--r--spec/helpers/preferences_helper_spec.rb39
-rw-r--r--spec/helpers/projects/error_tracking_helper_spec.rb58
-rw-r--r--spec/helpers/projects_helper_spec.rb192
-rw-r--r--spec/helpers/runners_helper_spec.rb36
-rw-r--r--spec/helpers/search_helper_spec.rb2
-rw-r--r--spec/helpers/submodule_helper_spec.rb2
-rw-r--r--spec/helpers/user_callouts_helper_spec.rb9
-rw-r--r--spec/helpers/users_helper_spec.rb70
-rw-r--r--spec/initializers/active_record_locking_spec.rb44
-rw-r--r--spec/javascripts/api_spec.js50
-rw-r--r--spec/javascripts/awards_handler_spec.js11
-rw-r--r--spec/javascripts/badges/store/actions_spec.js4
-rw-r--r--spec/javascripts/behaviors/copy_as_gfm_spec.js33
-rw-r--r--spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js126
-rw-r--r--spec/javascripts/blob_edit/blob_bundle_spec.js13
-rw-r--r--spec/javascripts/boards/components/issue_due_date_spec.js4
-rw-r--r--spec/javascripts/clusters/clusters_bundle_spec.js57
-rw-r--r--spec/javascripts/clusters/components/application_row_spec.js187
-rw-r--r--spec/javascripts/clusters/stores/clusters_store_spec.js4
-rw-r--r--spec/javascripts/commit/pipelines/pipelines_spec.js2
-rw-r--r--spec/javascripts/diffs/components/app_spec.js332
-rw-r--r--spec/javascripts/diffs/components/changed_files_dropdown_spec.js1
-rw-r--r--spec/javascripts/diffs/components/commit_item_spec.js2
-rw-r--r--spec/javascripts/diffs/components/compare_versions_dropdown_spec.js162
-rw-r--r--spec/javascripts/diffs/components/compare_versions_spec.js41
-rw-r--r--spec/javascripts/diffs/components/diff_content_spec.js28
-rw-r--r--spec/javascripts/diffs/components/diff_file_header_spec.js108
-rw-r--r--spec/javascripts/diffs/components/diff_file_spec.js37
-rw-r--r--spec/javascripts/diffs/components/diff_stats_spec.js33
-rw-r--r--spec/javascripts/diffs/components/edit_button_spec.js62
-rw-r--r--spec/javascripts/diffs/components/hidden_files_warning_spec.js49
-rw-r--r--spec/javascripts/diffs/components/inline_diff_view_spec.js2
-rw-r--r--spec/javascripts/diffs/components/parallel_diff_view_spec.js6
-rw-r--r--spec/javascripts/diffs/components/settings_dropdown_spec.js167
-rw-r--r--spec/javascripts/diffs/components/tree_list_spec.js82
-rw-r--r--spec/javascripts/diffs/mock_data/diff_discussions.js8
-rw-r--r--spec/javascripts/diffs/mock_data/diff_file.js2
-rw-r--r--spec/javascripts/diffs/mock_data/merge_request_diffs.js52
-rw-r--r--spec/javascripts/diffs/store/actions_spec.js91
-rw-r--r--spec/javascripts/diffs/store/getters_spec.js47
-rw-r--r--spec/javascripts/diffs/store/mutations_spec.js56
-rw-r--r--spec/javascripts/diffs/store/utils_spec.js218
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_collection_spec.js6
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_form_spec.js30
-rw-r--r--spec/javascripts/dirty_submit/helper.js29
-rw-r--r--spec/javascripts/emoji_spec.js189
-rw-r--r--spec/javascripts/environments/confirm_rollback_modal_spec.js70
-rw-r--r--spec/javascripts/environments/environment_item_spec.js2
-rw-r--r--spec/javascripts/environments/environment_rollback_spec.js32
-rw-r--r--spec/javascripts/environments/environment_table_spec.js221
-rw-r--r--spec/javascripts/environments/environments_app_spec.js3
-rw-r--r--spec/javascripts/environments/folder/environments_folder_view_spec.js3
-rw-r--r--spec/javascripts/error_tracking/components/error_tracking_list_spec.js118
-rw-r--r--spec/javascripts/error_tracking/store/mutation_spec.js36
-rw-r--r--spec/javascripts/error_tracking_settings/components/app_spec.js63
-rw-r--r--spec/javascripts/error_tracking_settings/components/error_tracking_form_spec.js91
-rw-r--r--spec/javascripts/error_tracking_settings/components/project_dropdown_spec.js109
-rw-r--r--spec/javascripts/error_tracking_settings/mock.js92
-rw-r--r--spec/javascripts/error_tracking_settings/store/actions_spec.js191
-rw-r--r--spec/javascripts/error_tracking_settings/store/getters_spec.js93
-rw-r--r--spec/javascripts/error_tracking_settings/store/mutation_spec.js82
-rw-r--r--spec/javascripts/error_tracking_settings/utils_spec.js29
-rw-r--r--spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js324
-rw-r--r--spec/javascripts/filtered_search/visual_token_value_spec.js361
-rw-r--r--spec/javascripts/fixtures/blob.rb1
-rw-r--r--spec/javascripts/fixtures/commit.rb1
-rw-r--r--spec/javascripts/fixtures/deploy_keys.rb2
-rw-r--r--spec/javascripts/fixtures/emojis.rb16
-rw-r--r--spec/javascripts/fixtures/groups.rb2
-rw-r--r--spec/javascripts/fixtures/issues.rb2
-rw-r--r--spec/javascripts/fixtures/jobs.rb3
-rw-r--r--spec/javascripts/fixtures/merge_requests.rb7
-rw-r--r--spec/javascripts/fixtures/oauth_remember_me.html.haml1
-rw-r--r--spec/javascripts/fixtures/projects.rb12
-rw-r--r--spec/javascripts/fixtures/sessions.rb26
-rw-r--r--spec/javascripts/fixtures/snippet.rb4
-rw-r--r--spec/javascripts/fixtures/u2f.rb3
-rw-r--r--spec/javascripts/gfm_auto_complete_spec.js208
-rw-r--r--spec/javascripts/helpers/vue_test_utils_helper.js19
-rw-r--r--spec/javascripts/helpers/vue_test_utils_helper_spec.js48
-rw-r--r--spec/javascripts/helpers/vuex_action_helper.js5
-rw-r--r--spec/javascripts/ide/components/file_finder/index_spec.js305
-rw-r--r--spec/javascripts/ide/components/file_finder/item_spec.js140
-rw-r--r--spec/javascripts/ide/components/ide_spec.js68
-rw-r--r--spec/javascripts/ide/components/ide_status_bar_spec.js3
-rw-r--r--spec/javascripts/ide/components/new_dropdown/modal_spec.js64
-rw-r--r--spec/javascripts/ide/lib/decorations/controller_spec.js4
-rw-r--r--spec/javascripts/ide/lib/files_spec.js77
-rw-r--r--spec/javascripts/ide/stores/actions/merge_request_spec.js93
-rw-r--r--spec/javascripts/ide/stores/actions/project_spec.js1
-rw-r--r--spec/javascripts/ide/stores/actions/tree_spec.js7
-rw-r--r--spec/javascripts/ide/stores/actions_spec.js28
-rw-r--r--spec/javascripts/ide/stores/mutations_spec.js14
-rw-r--r--spec/javascripts/import_projects/components/import_projects_table_spec.js188
-rw-r--r--spec/javascripts/import_projects/components/imported_project_table_row_spec.js51
-rw-r--r--spec/javascripts/import_projects/components/provider_repo_table_row_spec.js96
-rw-r--r--spec/javascripts/import_projects/store/actions_spec.js284
-rw-r--r--spec/javascripts/import_projects/store/getters_spec.js83
-rw-r--r--spec/javascripts/import_projects/store/mutations_spec.js34
-rw-r--r--spec/javascripts/issue_show/components/app_spec.js194
-rw-r--r--spec/javascripts/issue_show/components/description_spec.js23
-rw-r--r--spec/javascripts/issue_show/mock_data.js2
-rw-r--r--spec/javascripts/jobs/components/sidebar_spec.js4
-rw-r--r--spec/javascripts/jobs/store/getters_spec.js79
-rw-r--r--spec/javascripts/lib/utils/ajax_cache_spec.js184
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js253
-rw-r--r--spec/javascripts/lib/utils/datetime_utility_spec.js40
-rw-r--r--spec/javascripts/lib/utils/file_upload_spec.js44
-rw-r--r--spec/javascripts/lib/utils/grammar_spec.js35
-rw-r--r--spec/javascripts/lib/utils/icon_utils_spec.js67
-rw-r--r--spec/javascripts/lib/utils/number_utility_spec.js11
-rw-r--r--spec/javascripts/lib/utils/poll_spec.js32
-rw-r--r--spec/javascripts/lib/utils/text_markdown_spec.js387
-rw-r--r--spec/javascripts/lib/utils/text_utility_spec.js16
-rw-r--r--spec/javascripts/lib/utils/url_utility_spec.js81
-rw-r--r--spec/javascripts/matchers.js39
-rw-r--r--spec/javascripts/merge_request_spec.js56
-rw-r--r--spec/javascripts/monitoring/charts/area_spec.js224
-rw-r--r--spec/javascripts/monitoring/dashboard_spec.js28
-rw-r--r--spec/javascripts/monitoring/graph/axis_spec.js65
-rw-r--r--spec/javascripts/monitoring/graph/deployment_spec.js53
-rw-r--r--spec/javascripts/monitoring/graph/flag_spec.js133
-rw-r--r--spec/javascripts/monitoring/graph/legend_spec.js44
-rw-r--r--spec/javascripts/monitoring/graph/track_info_spec.js44
-rw-r--r--spec/javascripts/monitoring/graph/track_line_spec.js52
-rw-r--r--spec/javascripts/monitoring/graph_path_spec.js56
-rw-r--r--spec/javascripts/monitoring/graph_spec.js127
-rw-r--r--spec/javascripts/monitoring/mock_data.js81
-rw-r--r--spec/javascripts/monitoring/utils/multiple_time_series_spec.js22
-rw-r--r--spec/javascripts/notebook/cells/output/html_spec.js2
-rw-r--r--spec/javascripts/notebook/cells/output/index_spec.js27
-rw-r--r--spec/javascripts/notes/components/comment_form_spec.js1
-rw-r--r--spec/javascripts/notes/components/discussion_counter_spec.js2
-rw-r--r--spec/javascripts/notes/components/discussion_filter_note_spec.js93
-rw-r--r--spec/javascripts/notes/components/discussion_filter_spec.js102
-rw-r--r--spec/javascripts/notes/components/discussion_reply_placeholder_spec.js34
-rw-r--r--spec/javascripts/notes/components/discussion_resolve_button_spec.js74
-rw-r--r--spec/javascripts/notes/components/discussion_resolve_with_issue_button_spec.js31
-rw-r--r--spec/javascripts/notes/components/note_actions/reply_button_spec.js32
-rw-r--r--spec/javascripts/notes/components/note_actions_spec.js197
-rw-r--r--spec/javascripts/notes/components/note_app_spec.js184
-rw-r--r--spec/javascripts/notes/components/note_form_spec.js157
-rw-r--r--spec/javascripts/notes/components/noteable_discussion_spec.js196
-rw-r--r--spec/javascripts/notes/components/noteable_note_spec.js118
-rw-r--r--spec/javascripts/notes/mock_data.js1
-rw-r--r--spec/javascripts/notes/stores/actions_spec.js166
-rw-r--r--spec/javascripts/notes/stores/getters_spec.js8
-rw-r--r--spec/javascripts/notes/stores/mutation_spec.js67
-rw-r--r--spec/javascripts/notes_spec.js19
-rw-r--r--spec/javascripts/oauth_remember_me_spec.js7
-rw-r--r--spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js61
-rw-r--r--spec/javascripts/persistent_user_callout_spec.js88
-rw-r--r--spec/javascripts/pipelines/pipelines_spec.js2
-rw-r--r--spec/javascripts/releases/components/release_block_spec.js16
-rw-r--r--spec/javascripts/serverless/components/environment_row_spec.js81
-rw-r--r--spec/javascripts/serverless/components/function_row_spec.js33
-rw-r--r--spec/javascripts/serverless/components/functions_spec.js68
-rw-r--r--spec/javascripts/serverless/components/url_spec.js28
-rw-r--r--spec/javascripts/serverless/mock_data.js79
-rw-r--r--spec/javascripts/serverless/stores/serverless_store_spec.js36
-rw-r--r--spec/javascripts/task_list_spec.js156
-rw-r--r--spec/javascripts/test_bundle.js14
-rw-r--r--spec/javascripts/user_popovers_spec.js25
-rw-r--r--spec/javascripts/vue_mr_widget/components/deployment_spec.js81
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/commit_edit_spec.js85
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js61
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_commits_header_spec.js110
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js131
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js14
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js20
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js211
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js100
-rw-r--r--spec/javascripts/vue_mr_widget/mock_data.js6
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js79
-rw-r--r--spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js24
-rw-r--r--spec/javascripts/vue_shared/components/callout_spec.js65
-rw-r--r--spec/javascripts/vue_shared/components/changed_file_icon_spec.js21
-rw-r--r--spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/file_finder/index_spec.js368
-rw-r--r--spec/javascripts/vue_shared/components/file_finder/item_spec.js140
-rw-r--r--spec/javascripts/vue_shared/components/file_row_spec.js43
-rw-r--r--spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js99
-rw-r--r--spec/javascripts/vue_shared/components/gl_modal_vuex_spec.js151
-rw-r--r--spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js194
-rw-r--r--spec/javascripts/vue_shared/components/issue/related_issuable_mock_data.js111
-rw-r--r--spec/javascripts/vue_shared/components/markdown/suggestion_diff_header_spec.js6
-rw-r--r--spec/javascripts/vue_shared/components/markdown/suggestion_diff_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/markdown/suggestions_spec.js6
-rw-r--r--spec/javascripts/vue_shared/components/panel_resizer_spec.js9
-rw-r--r--spec/javascripts/vue_shared/components/table_pagination_spec.js194
-rw-r--r--spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js18
-rw-r--r--spec/javascripts/vue_shared/components/user_avatar/user_avatar_list_spec.js156
-rw-r--r--spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js15
-rw-r--r--spec/javascripts/vuex_shared/modules/modal/actions_spec.js31
-rw-r--r--spec/javascripts/vuex_shared/modules/modal/mutations_spec.js49
-rw-r--r--spec/lib/api/api_spec.rb21
-rw-r--r--spec/lib/api/helpers/custom_validators_spec.rb23
-rw-r--r--spec/lib/api/helpers/pagination_spec.rb238
-rw-r--r--spec/lib/api/helpers/version_spec.rb26
-rw-r--r--spec/lib/api/helpers_spec.rb36
-rw-r--r--spec/lib/backup/manager_spec.rb1
-rw-r--r--spec/lib/banzai/color_parser_spec.rb2
-rw-r--r--spec/lib/banzai/filter/autolink_filter_spec.rb23
-rw-r--r--spec/lib/banzai/filter/commit_range_reference_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/external_issue_reference_filter_spec.rb36
-rw-r--r--spec/lib/banzai/filter/external_link_filter_spec.rb73
-rw-r--r--spec/lib/banzai/filter/footnote_filter_spec.rb50
-rw-r--r--spec/lib/banzai/filter/issue_reference_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/label_reference_filter_spec.rb18
-rw-r--r--spec/lib/banzai/filter/markdown_filter_spec.rb38
-rw-r--r--spec/lib/banzai/filter/milestone_reference_filter_spec.rb30
-rw-r--r--spec/lib/banzai/filter/project_reference_filter_spec.rb8
-rw-r--r--spec/lib/banzai/filter/relative_link_filter_spec.rb54
-rw-r--r--spec/lib/banzai/filter/sanitization_filter_spec.rb52
-rw-r--r--spec/lib/banzai/filter/spaced_link_filter_spec.rb5
-rw-r--r--spec/lib/banzai/object_renderer_spec.rb2
-rw-r--r--spec/lib/banzai/pipeline/description_pipeline_spec.rb4
-rw-r--r--spec/lib/banzai/pipeline/email_pipeline_spec.rb14
-rw-r--r--spec/lib/banzai/pipeline/full_pipeline_spec.rb72
-rw-r--r--spec/lib/bitbucket_server/client_spec.rb10
-rw-r--r--spec/lib/bitbucket_server/connection_spec.rb18
-rw-r--r--spec/lib/bitbucket_server/paginator_spec.rb11
-rw-r--r--spec/lib/constraints/project_url_constrainer_spec.rb4
-rw-r--r--spec/lib/feature_spec.rb15
-rw-r--r--spec/lib/gitlab/access/branch_protection_spec.rb54
-rw-r--r--spec/lib/gitlab/auth/ldap/config_spec.rb153
-rw-r--r--spec/lib/gitlab/auth/o_auth/identity_linker_spec.rb2
-rw-r--r--spec/lib/gitlab/auth/user_auth_finders_spec.rb2
-rw-r--r--spec/lib/gitlab/auth_spec.rb4
-rw-r--r--spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb18
-rw-r--r--spec/lib/gitlab/background_migration/create_gpg_key_subkeys_from_gpg_keys_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/delete_diff_files_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/digest_column_spec.rb4
-rw-r--r--spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/move_personal_snippet_files_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb63
-rw-r--r--spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb7
-rw-r--r--spec/lib/gitlab/background_migration/populate_import_state_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/populate_merge_request_metrics_with_events_data_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/rollback_import_state_data_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration_spec.rb76
-rw-r--r--spec/lib/gitlab/bare_repository_import/repository_spec.rb2
-rw-r--r--spec/lib/gitlab/bitbucket_import/importer_spec.rb10
-rw-r--r--spec/lib/gitlab/bitbucket_import/wiki_formatter_spec.rb29
-rw-r--r--spec/lib/gitlab/bitbucket_server_import/importer_spec.rb17
-rw-r--r--spec/lib/gitlab/blob_helper_spec.rb4
-rw-r--r--spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb2
-rw-r--r--spec/lib/gitlab/chat/command_spec.rb77
-rw-r--r--spec/lib/gitlab/chat/output_spec.rb101
-rw-r--r--spec/lib/gitlab/chat/responder/base_spec.rb48
-rw-r--r--spec/lib/gitlab/chat/responder/slack_spec.rb77
-rw-r--r--spec/lib/gitlab/chat/responder_spec.rb32
-rw-r--r--spec/lib/gitlab/chat_spec.rb23
-rw-r--r--spec/lib/gitlab/checks/branch_check_spec.rb124
-rw-r--r--spec/lib/gitlab/checks/diff_check_spec.rb38
-rw-r--r--spec/lib/gitlab/checks/push_check_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/policy/changes_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/build/policy/refs_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/build/policy/variables_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/build/step_spec.rb9
-rw-r--r--spec/lib/gitlab/ci/config/entry/global_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/config/entry/jobs_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/entry/policy_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/config/external/file/base_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/config/external/file/local_spec.rb68
-rw-r--r--spec/lib/gitlab/ci/config/external/file/project_spec.rb162
-rw-r--r--spec/lib/gitlab/ci/config/external/file/remote_spec.rb41
-rw-r--r--spec/lib/gitlab/ci/config/external/file/template_spec.rb106
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb150
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb92
-rw-r--r--spec/lib/gitlab/ci/config/normalizer_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb30
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/build_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/command_spec.rb68
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb37
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb33
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/config_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb50
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/status/external/common_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/templates/templates_spec.rb37
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/variables/collection_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb140
-rw-r--r--spec/lib/gitlab/cleanup/remote_uploads_spec.rb2
-rw-r--r--spec/lib/gitlab/config/entry/configurable_spec.rb10
-rw-r--r--spec/lib/gitlab/current_settings_spec.rb80
-rw-r--r--spec/lib/gitlab/danger/helper_spec.rb303
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb2
-rw-r--r--spec/lib/gitlab/data_builder/push_spec.rb4
-rw-r--r--spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb2
-rw-r--r--spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb4
-rw-r--r--spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb9
-rw-r--r--spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb4
-rw-r--r--spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb18
-rw-r--r--spec/lib/gitlab/dependency_linker/parser/gemfile_spec.rb44
-rw-r--r--spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb5
-rw-r--r--spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb4
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb8
-rw-r--r--spec/lib/gitlab/diff/lines_unfolder_spec.rb117
-rw-r--r--spec/lib/gitlab/diff/position_tracer_spec.rb18
-rw-r--r--spec/lib/gitlab/discussions_diff/file_collection_spec.rb61
-rw-r--r--spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb102
-rw-r--r--spec/lib/gitlab/email/handler/create_issue_handler_spec.rb65
-rw-r--r--spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb75
-rw-r--r--spec/lib/gitlab/email/handler/create_note_handler_spec.rb57
-rw-r--r--spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb38
-rw-r--r--spec/lib/gitlab/email/handler_spec.rb3
-rw-r--r--spec/lib/gitlab/git/blame_spec.rb2
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb10
-rw-r--r--spec/lib/gitlab/git/branch_spec.rb4
-rw-r--r--spec/lib/gitlab/git/bundle_file_spec.rb26
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb20
-rw-r--r--spec/lib/gitlab/git/compare_spec.rb4
-rw-r--r--spec/lib/gitlab/git/diff_spec.rb2
-rw-r--r--spec/lib/gitlab/git/merge_base_spec.rb2
-rw-r--r--spec/lib/gitlab/git/remote_repository_spec.rb16
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb229
-rw-r--r--spec/lib/gitlab/git/tag_spec.rb2
-rw-r--r--spec/lib/gitlab/git/tree_spec.rb2
-rw-r--r--spec/lib/gitlab/git_access_spec.rb59
-rw-r--r--spec/lib/gitlab/git_access_wiki_spec.rb2
-rw-r--r--spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb4
-rw-r--r--spec/lib/gitlab/gitaly_client/remote_service_spec.rb2
-rw-r--r--spec/lib/gitlab/gitaly_client/storage_settings_spec.rb10
-rw-r--r--spec/lib/gitlab/gitaly_client/util_spec.rb4
-rw-r--r--spec/lib/gitlab/gitaly_client_spec.rb9
-rw-r--r--spec/lib/gitlab/github_import/bulk_importing_spec.rb12
-rw-r--r--spec/lib/gitlab/github_import/importer/issue_importer_spec.rb22
-rw-r--r--spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb22
-rw-r--r--spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb14
-rw-r--r--spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb38
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb48
-rw-r--r--spec/lib/gitlab/github_import/importer/repository_importer_spec.rb14
-rw-r--r--spec/lib/gitlab/github_import/representation/pull_request_spec.rb2
-rw-r--r--spec/lib/gitlab/gon_helper_spec.rb9
-rw-r--r--spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb18
-rw-r--r--spec/lib/gitlab/graphql/authorize/instrumentation_spec.rb67
-rw-r--r--spec/lib/gitlab/graphql/authorize_spec.rb20
-rw-r--r--spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb2
-rw-r--r--spec/lib/gitlab/hashed_storage/migrator_spec.rb156
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml13
-rw-r--r--spec/lib/gitlab/import_export/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/merge_request_parser_spec.rb16
-rw-r--r--spec/lib/gitlab/import_export/project.json42
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb65
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb8
-rw-r--r--spec/lib/gitlab/import_export/reader_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml15
-rw-r--r--spec/lib/gitlab/import_export/shared_spec.rb41
-rw-r--r--spec/lib/gitlab/import_export/version_checker_spec.rb2
-rw-r--r--spec/lib/gitlab/incoming_email_spec.rb2
-rw-r--r--spec/lib/gitlab/issuable_metadata_spec.rb8
-rw-r--r--spec/lib/gitlab/json_cache_spec.rb28
-rw-r--r--spec/lib/gitlab/kubernetes/helm/api_spec.rb45
-rw-r--r--spec/lib/gitlab/kubernetes/helm/install_command_spec.rb84
-rw-r--r--spec/lib/gitlab/kubernetes/helm/pod_spec.rb6
-rw-r--r--spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb140
-rw-r--r--spec/lib/gitlab/kubernetes/kube_client_spec.rb62
-rw-r--r--spec/lib/gitlab/legacy_github_import/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/legacy_github_import/wiki_formatter_spec.rb8
-rw-r--r--spec/lib/gitlab/lfs_token_spec.rb36
-rw-r--r--spec/lib/gitlab/loop_helpers_spec.rb45
-rw-r--r--spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb4
-rw-r--r--spec/lib/gitlab/middleware/go_spec.rb43
-rw-r--r--spec/lib/gitlab/middleware/multipart_spec.rb24
-rw-r--r--spec/lib/gitlab/middleware/read_only_spec.rb34
-rw-r--r--spec/lib/gitlab/path_regex_spec.rb2
-rw-r--r--spec/lib/gitlab/profiler_spec.rb8
-rw-r--r--spec/lib/gitlab/project_template_spec.rb14
-rw-r--r--spec/lib/gitlab/prometheus/metric_group_spec.rb7
-rw-r--r--spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb4
-rw-r--r--spec/lib/gitlab/quick_actions/command_definition_spec.rb7
-rw-r--r--spec/lib/gitlab/repository_cache_spec.rb22
-rw-r--r--spec/lib/gitlab/request_context_spec.rb2
-rw-r--r--spec/lib/gitlab/serializer/pagination_spec.rb10
-rw-r--r--spec/lib/gitlab/shell_spec.rb18
-rw-r--r--spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb33
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/memory_killer_spec.rb74
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/shutdown_spec.rb88
-rw-r--r--spec/lib/gitlab/sidekiq_signals_spec.rb69
-rw-r--r--spec/lib/gitlab/slash_commands/application_help_spec.rb19
-rw-r--r--spec/lib/gitlab/slash_commands/issue_new_spec.rb2
-rw-r--r--spec/lib/gitlab/slash_commands/presenters/error_spec.rb15
-rw-r--r--spec/lib/gitlab/slash_commands/presenters/run_spec.rb79
-rw-r--r--spec/lib/gitlab/slash_commands/run_spec.rb123
-rw-r--r--spec/lib/gitlab/sql/recursive_cte_spec.rb9
-rw-r--r--spec/lib/gitlab/tracing/factory_spec.rb43
-rw-r--r--spec/lib/gitlab/tracing/grpc_interceptor_spec.rb47
-rw-r--r--spec/lib/gitlab/tracing/jaeger_factory_spec.rb71
-rw-r--r--spec/lib/gitlab/tracing/rack_middleware_spec.rb62
-rw-r--r--spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb147
-rw-r--r--spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb73
-rw-r--r--spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb43
-rw-r--r--spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb43
-rw-r--r--spec/lib/gitlab/tracing_spec.rb69
-rw-r--r--spec/lib/gitlab/tree_summary_spec.rb2
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb10
-rw-r--r--spec/lib/gitlab/utils_spec.rb16
-rw-r--r--spec/lib/gitlab_spec.rb15
-rw-r--r--spec/lib/json_web_token/rsa_token_spec.rb4
-rw-r--r--spec/lib/object_storage/direct_upload_spec.rb2
-rw-r--r--spec/lib/omni_auth/strategies/jwt_spec.rb2
-rw-r--r--spec/lib/safe_zip/entry_spec.rb196
-rw-r--r--spec/lib/safe_zip/extract_params_spec.rb54
-rw-r--r--spec/lib/safe_zip/extract_spec.rb80
-rw-r--r--spec/lib/sentry/client_spec.rb218
-rw-r--r--spec/lib/serializers/json_spec.rb102
-rw-r--r--spec/mailers/abuse_report_mailer_spec.rb25
-rw-r--r--spec/mailers/email_rejection_mailer_spec.rb16
-rw-r--r--spec/mailers/emails/auto_devops_spec.rb3
-rw-r--r--spec/mailers/emails/issues_spec.rb42
-rw-r--r--spec/mailers/emails/pages_domains_spec.rb2
-rw-r--r--spec/mailers/notify_spec.rb172
-rw-r--r--spec/mailers/repository_check_mailer_spec.rb7
-rw-r--r--spec/migrations/README.md76
-rw-r--r--spec/migrations/add_foreign_keys_to_todos_spec.rb6
-rw-r--r--spec/migrations/clean_up_for_members_spec.rb4
-rw-r--r--spec/migrations/cleanup_legacy_artifact_migration_spec.rb52
-rw-r--r--spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb12
-rw-r--r--spec/migrations/delete_inconsistent_internal_id_records_spec.rb9
-rw-r--r--spec/migrations/fix_null_type_labels_spec.rb36
-rw-r--r--spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb114
-rw-r--r--spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb47
-rw-r--r--spec/migrations/rename_more_reserved_project_names_spec.rb5
-rw-r--r--spec/migrations/rename_reserved_project_names_spec.rb5
-rw-r--r--spec/migrations/update_project_import_visibility_level_spec.rb86
-rw-r--r--spec/models/ability_spec.rb1
-rw-r--r--spec/models/active_session_spec.rb5
-rw-r--r--spec/models/appearance_spec.rb70
-rw-r--r--spec/models/application_record_spec.rb36
-rw-r--r--spec/models/application_setting_spec.rb7
-rw-r--r--spec/models/blob_spec.rb22
-rw-r--r--spec/models/blob_viewer/gitlab_ci_yml_spec.rb10
-rw-r--r--spec/models/board_group_recent_visit_spec.rb22
-rw-r--r--spec/models/board_project_recent_visit_spec.rb22
-rw-r--r--spec/models/ci/bridge_spec.rb15
-rw-r--r--spec/models/ci/build_metadata_spec.rb4
-rw-r--r--spec/models/ci/build_spec.rb673
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb4
-rw-r--r--spec/models/ci/group_variable_spec.rb1
-rw-r--r--spec/models/ci/pipeline_spec.rb346
-rw-r--r--spec/models/ci/runner_spec.rb9
-rw-r--r--spec/models/ci/variable_spec.rb1
-rw-r--r--spec/models/clusters/applications/cert_manager_spec.rb29
-rw-r--r--spec/models/clusters/applications/helm_spec.rb17
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb40
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb24
-rw-r--r--spec/models/clusters/applications/knative_spec.rb94
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb171
-rw-r--r--spec/models/clusters/applications/runner_spec.rb40
-rw-r--r--spec/models/clusters/cluster_spec.rb133
-rw-r--r--spec/models/clusters/kubernetes_namespace_spec.rb4
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb76
-rw-r--r--spec/models/clusters/providers/gcp_spec.rb12
-rw-r--r--spec/models/commit_collection_spec.rb36
-rw-r--r--spec/models/commit_spec.rb1
-rw-r--r--spec/models/concerns/cache_markdown_field_spec.rb232
-rw-r--r--spec/models/concerns/cacheable_attributes_spec.rb12
-rw-r--r--spec/models/concerns/discussion_on_diff_spec.rb2
-rw-r--r--spec/models/concerns/has_ref_spec.rb79
-rw-r--r--spec/models/concerns/has_variable_spec.rb2
-rw-r--r--spec/models/concerns/issuable_spec.rb171
-rw-r--r--spec/models/concerns/manual_inverse_association_spec.rb4
-rw-r--r--spec/models/concerns/maskable_spec.rb76
-rw-r--r--spec/models/concerns/milestoneish_spec.rb142
-rw-r--r--spec/models/concerns/reactive_caching_spec.rb12
-rw-r--r--spec/models/concerns/redactable_spec.rb4
-rw-r--r--spec/models/concerns/sortable_spec.rb2
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb235
-rw-r--r--spec/models/concerns/token_authenticatable_strategies/base_spec.rb32
-rw-r--r--spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb28
-rw-r--r--spec/models/diff_viewer/base_spec.rb23
-rw-r--r--spec/models/diff_viewer/server_side_spec.rb20
-rw-r--r--spec/models/environment_spec.rb92
-rw-r--r--spec/models/error_tracking/project_error_tracking_setting_spec.rb332
-rw-r--r--spec/models/event_spec.rb23
-rw-r--r--spec/models/external_issue_spec.rb2
-rw-r--r--spec/models/global_milestone_spec.rb125
-rw-r--r--spec/models/gpg_key_spec.rb2
-rw-r--r--spec/models/gpg_signature_spec.rb35
-rw-r--r--spec/models/group_milestone_spec.rb27
-rw-r--r--spec/models/group_spec.rb36
-rw-r--r--spec/models/identity_spec.rb34
-rw-r--r--spec/models/internal_id_spec.rb23
-rw-r--r--spec/models/issue/metrics_spec.rb6
-rw-r--r--spec/models/issue_spec.rb54
-rw-r--r--spec/models/label_note_spec.rb4
-rw-r--r--spec/models/lfs_download_object_spec.rb68
-rw-r--r--spec/models/lfs_file_lock_spec.rb2
-rw-r--r--spec/models/members/project_member_spec.rb2
-rw-r--r--spec/models/merge_request_diff_commit_spec.rb2
-rw-r--r--spec/models/merge_request_diff_spec.rb203
-rw-r--r--spec/models/merge_request_spec.rb206
-rw-r--r--spec/models/milestone_spec.rb139
-rw-r--r--spec/models/note_spec.rb15
-rw-r--r--spec/models/project_daily_statistic_spec.rb7
-rw-r--r--spec/models/project_import_data_spec.rb11
-rw-r--r--spec/models/project_services/bamboo_service_spec.rb26
-rw-r--r--spec/models/project_services/drone_ci_service_spec.rb2
-rw-r--r--spec/models/project_services/external_wiki_service_spec.rb21
-rw-r--r--spec/models/project_services/hipchat_service_spec.rb408
-rw-r--r--spec/models/project_services/jira_service_spec.rb3
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb61
-rw-r--r--spec/models/project_services/slack_slash_commands_service_spec.rb7
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb2
-rw-r--r--spec/models/project_services/youtrack_service_spec.rb38
-rw-r--r--spec/models/project_spec.rb757
-rw-r--r--spec/models/project_team_spec.rb15
-rw-r--r--spec/models/project_wiki_spec.rb4
-rw-r--r--spec/models/prometheus_metric_spec.rb67
-rw-r--r--spec/models/protected_branch_spec.rb28
-rw-r--r--spec/models/release_spec.rb29
-rw-r--r--spec/models/releases/link_spec.rb104
-rw-r--r--spec/models/releases/source_spec.rb41
-rw-r--r--spec/models/remote_mirror_spec.rb33
-rw-r--r--spec/models/repository_spec.rb125
-rw-r--r--spec/models/resource_label_event_spec.rb6
-rw-r--r--spec/models/sent_notification_spec.rb34
-rw-r--r--spec/models/snippet_spec.rb37
-rw-r--r--spec/models/ssh_host_key_spec.rb29
-rw-r--r--spec/models/user_preference_spec.rb25
-rw-r--r--spec/models/user_spec.rb56
-rw-r--r--spec/policies/board_policy_spec.rb67
-rw-r--r--spec/policies/ci/pipeline_policy_spec.rb8
-rw-r--r--spec/policies/commit_policy_spec.rb55
-rw-r--r--spec/policies/global_policy_spec.rb12
-rw-r--r--spec/policies/group_policy_spec.rb53
-rw-r--r--spec/policies/issuable_policy_spec.rb27
-rw-r--r--spec/policies/note_policy_spec.rb96
-rw-r--r--spec/policies/personal_snippet_policy_spec.rb38
-rw-r--r--spec/policies/project_policy_spec.rb131
-rw-r--r--spec/policies/project_snippet_policy_spec.rb20
-rw-r--r--spec/presenters/blob_presenter_spec.rb2
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb68
-rw-r--r--spec/presenters/ci/trigger_presenter_spec.rb51
-rw-r--r--spec/presenters/clusterable_presenter_spec.rb64
-rw-r--r--spec/presenters/commit_presenter_spec.rb54
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb23
-rw-r--r--spec/presenters/projects/settings/deploy_keys_presenter_spec.rb2
-rw-r--r--spec/requests/api/avatar_spec.rb2
-rw-r--r--spec/requests/api/award_emoji_spec.rb4
-rw-r--r--spec/requests/api/boards_spec.rb2
-rw-r--r--spec/requests/api/branches_spec.rb12
-rw-r--r--spec/requests/api/commits_spec.rb55
-rw-r--r--spec/requests/api/container_registry_spec.rb224
-rw-r--r--spec/requests/api/discussions_spec.rb2
-rw-r--r--spec/requests/api/features_spec.rb68
-rw-r--r--spec/requests/api/files_spec.rb5
-rw-r--r--spec/requests/api/graphql/metadata_query_spec.rb32
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb34
-rw-r--r--spec/requests/api/graphql_spec.rb86
-rw-r--r--spec/requests/api/group_labels_spec.rb258
-rw-r--r--spec/requests/api/group_milestones_spec.rb2
-rw-r--r--spec/requests/api/group_variables_spec.rb4
-rw-r--r--spec/requests/api/groups_spec.rb14
-rw-r--r--spec/requests/api/import_github_spec.rb56
-rw-r--r--spec/requests/api/internal_spec.rb23
-rw-r--r--spec/requests/api/issues_spec.rb722
-rw-r--r--spec/requests/api/jobs_spec.rb79
-rw-r--r--spec/requests/api/keys_spec.rb2
-rw-r--r--spec/requests/api/labels_spec.rb10
-rw-r--r--spec/requests/api/markdown_spec.rb2
-rw-r--r--spec/requests/api/merge_request_diffs_spec.rb4
-rw-r--r--spec/requests/api/merge_requests_spec.rb391
-rw-r--r--spec/requests/api/namespaces_spec.rb2
-rw-r--r--spec/requests/api/notes_spec.rb4
-rw-r--r--spec/requests/api/pages/private_access_spec.rb2
-rw-r--r--spec/requests/api/pages/public_access_spec.rb2
-rw-r--r--spec/requests/api/pipelines_spec.rb4
-rw-r--r--spec/requests/api/project_clusters_spec.rb467
-rw-r--r--spec/requests/api/project_milestones_spec.rb76
-rw-r--r--spec/requests/api/project_statistics_spec.rb62
-rw-r--r--spec/requests/api/project_templates_spec.rb28
-rw-r--r--spec/requests/api/projects_spec.rb247
-rw-r--r--spec/requests/api/release/links_spec.rb375
-rw-r--r--spec/requests/api/releases_spec.rb628
-rw-r--r--spec/requests/api/repositories_spec.rb5
-rw-r--r--spec/requests/api/resource_label_events_spec.rb2
-rw-r--r--spec/requests/api/runner_spec.rb121
-rw-r--r--spec/requests/api/runners_spec.rb45
-rw-r--r--spec/requests/api/search_spec.rb4
-rw-r--r--spec/requests/api/settings_spec.rb6
-rw-r--r--spec/requests/api/snippets_spec.rb76
-rw-r--r--spec/requests/api/submodules_spec.rb4
-rw-r--r--spec/requests/api/tags_spec.rb45
-rw-r--r--spec/requests/api/triggers_spec.rb14
-rw-r--r--spec/requests/api/users_spec.rb32
-rw-r--r--spec/requests/api/variables_spec.rb4
-rw-r--r--spec/requests/api/version_spec.rb18
-rw-r--r--spec/requests/api/wikis_spec.rb42
-rw-r--r--spec/requests/git_http_spec.rb138
-rw-r--r--spec/requests/lfs_http_spec.rb25
-rw-r--r--spec/requests/lfs_locks_api_spec.rb15
-rw-r--r--spec/requests/openid_connect_spec.rb44
-rw-r--r--spec/requests/projects/cycle_analytics_events_spec.rb2
-rw-r--r--spec/requests/request_profiler_spec.rb2
-rw-r--r--spec/requests/user_activity_spec.rb114
-rw-r--r--spec/routing/import_routing_spec.rb15
-rw-r--r--spec/routing/project_routing_spec.rb4
-rw-r--r--spec/rubocop/cop/inject_enterprise_edition_module_spec.rb35
-rw-r--r--spec/serializers/cluster_application_entity_spec.rb14
-rw-r--r--spec/serializers/container_repository_entity_spec.rb2
-rw-r--r--spec/serializers/container_tag_entity_spec.rb2
-rw-r--r--spec/serializers/deployment_entity_spec.rb32
-rw-r--r--spec/serializers/diff_file_entity_spec.rb8
-rw-r--r--spec/serializers/environment_serializer_spec.rb13
-rw-r--r--spec/serializers/group_child_entity_spec.rb1
-rw-r--r--spec/serializers/merge_request_for_pipeline_entity_spec.rb29
-rw-r--r--spec/serializers/merge_request_widget_commit_entity_spec.rb21
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb61
-rw-r--r--spec/serializers/namespace_basic_entity_spec.rb18
-rw-r--r--spec/serializers/namespace_serializer_spec.rb9
-rw-r--r--spec/serializers/pipeline_entity_spec.rb45
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb54
-rw-r--r--spec/serializers/project_import_entity_spec.rb22
-rw-r--r--spec/serializers/project_serializer_spec.rb44
-rw-r--r--spec/serializers/provider_repo_entity_spec.rb24
-rw-r--r--spec/serializers/provider_repo_serializer_spec.rb9
-rw-r--r--spec/services/application_settings/update_service_spec.rb4
-rw-r--r--spec/services/auth/container_registry_authentication_service_spec.rb2
-rw-r--r--spec/services/boards/issues/list_service_spec.rb4
-rw-r--r--spec/services/boards/issues/move_service_spec.rb4
-rw-r--r--spec/services/boards/visits/latest_service_spec.rb12
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb71
-rw-r--r--spec/services/ci/destroy_expired_job_artifacts_service_spec.rb104
-rw-r--r--spec/services/ci/destroy_pipeline_service_spec.rb4
-rw-r--r--spec/services/ci/process_pipeline_service_spec.rb8
-rw-r--r--spec/services/ci/register_job_service_spec.rb11
-rw-r--r--spec/services/ci/retry_pipeline_service_spec.rb2
-rw-r--r--spec/services/clusters/applications/check_installation_progress_service_spec.rb123
-rw-r--r--spec/services/clusters/applications/create_service_spec.rb229
-rw-r--r--spec/services/clusters/applications/schedule_installation_service_spec.rb53
-rw-r--r--spec/services/clusters/applications/upgrade_service_spec.rb128
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb2
-rw-r--r--spec/services/create_release_service_spec.rb39
-rw-r--r--spec/services/error_tracking/list_issues_service_spec.rb107
-rw-r--r--spec/services/error_tracking/list_projects_service_spec.rb149
-rw-r--r--spec/services/event_create_service_spec.rb2
-rw-r--r--spec/services/files/multi_service_spec.rb16
-rw-r--r--spec/services/git_push_service_spec.rb4
-rw-r--r--spec/services/groups/transfer_service_spec.rb29
-rw-r--r--spec/services/groups/update_service_spec.rb2
-rw-r--r--spec/services/issuable/bulk_update_service_spec.rb27
-rw-r--r--spec/services/issuable/common_system_notes_service_spec.rb4
-rw-r--r--spec/services/issues/build_service_spec.rb76
-rw-r--r--spec/services/issues/create_service_spec.rb2
-rw-r--r--spec/services/issues/import_csv_service_spec.rb64
-rw-r--r--spec/services/issues/update_service_spec.rb10
-rw-r--r--spec/services/labels/find_or_create_service_spec.rb2
-rw-r--r--spec/services/labels/promote_service_spec.rb4
-rw-r--r--spec/services/lfs/unlock_file_service_spec.rb2
-rw-r--r--spec/services/members/create_service_spec.rb9
-rw-r--r--spec/services/members/destroy_service_spec.rb62
-rw-r--r--spec/services/members/update_service_spec.rb17
-rw-r--r--spec/services/merge_requests/build_service_spec.rb64
-rw-r--r--spec/services/merge_requests/create_service_spec.rb53
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb16
-rw-r--r--spec/services/merge_requests/merge_to_ref_service_spec.rb201
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb14
-rw-r--r--spec/services/merge_requests/squash_service_spec.rb71
-rw-r--r--spec/services/merge_requests/update_service_spec.rb8
-rw-r--r--spec/services/notes/build_service_spec.rb49
-rw-r--r--spec/services/notes/create_service_spec.rb61
-rw-r--r--spec/services/notes/quick_actions_service_spec.rb24
-rw-r--r--spec/services/notification_service_spec.rb31
-rw-r--r--spec/services/preview_markdown_service_spec.rb19
-rw-r--r--spec/services/projects/after_rename_service_spec.rb124
-rw-r--r--spec/services/projects/container_repository/cleanup_tags_service_spec.rb162
-rw-r--r--spec/services/projects/create_service_spec.rb12
-rw-r--r--spec/services/projects/destroy_service_spec.rb34
-rw-r--r--spec/services/projects/fetch_statistics_increment_service_spec.rb36
-rw-r--r--spec/services/projects/fork_service_spec.rb2
-rw-r--r--spec/services/projects/group_links/create_service_spec.rb8
-rw-r--r--spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb40
-rw-r--r--spec/services/projects/hashed_storage/migrate_repository_service_spec.rb56
-rw-r--r--spec/services/projects/hashed_storage/migration_service_spec.rb52
-rw-r--r--spec/services/projects/hashed_storage/rollback_attachments_service_spec.rb100
-rw-r--r--spec/services/projects/hashed_storage/rollback_repository_service_spec.rb111
-rw-r--r--spec/services/projects/hashed_storage/rollback_service_spec.rb57
-rw-r--r--spec/services/projects/hashed_storage_migration_service_spec.rb52
-rw-r--r--spec/services/projects/import_error_filter_spec.rb17
-rw-r--r--spec/services/projects/import_service_spec.rb13
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb18
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_service_spec.rb187
-rw-r--r--spec/services/projects/operations/update_service_spec.rb124
-rw-r--r--spec/services/projects/protect_default_branch_service_spec.rb242
-rw-r--r--spec/services/projects/transfer_service_spec.rb2
-rw-r--r--spec/services/projects/update_pages_configuration_service_spec.rb32
-rw-r--r--spec/services/projects/update_pages_service_spec.rb35
-rw-r--r--spec/services/projects/update_service_spec.rb6
-rw-r--r--spec/services/prometheus/adapter_service_spec.rb10
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb10
-rw-r--r--spec/services/releases/create_service_spec.rb72
-rw-r--r--spec/services/releases/destroy_service_spec.rb61
-rw-r--r--spec/services/releases/update_service_spec.rb50
-rw-r--r--spec/services/resource_events/change_labels_service_spec.rb2
-rw-r--r--spec/services/resource_events/merge_into_notes_service_spec.rb8
-rw-r--r--spec/services/suggestions/apply_service_spec.rb183
-rw-r--r--spec/services/suggestions/create_service_spec.rb47
-rw-r--r--spec/services/system_note_service_spec.rb17
-rw-r--r--spec/services/task_list_toggle_service_spec.rb116
-rw-r--r--spec/services/todo_service_spec.rb3
-rw-r--r--spec/services/todos/destroy/entity_leave_service_spec.rb8
-rw-r--r--spec/services/todos/destroy/group_private_service_spec.rb2
-rw-r--r--spec/services/update_release_service_spec.rb34
-rw-r--r--spec/services/upload_service_spec.rb4
-rw-r--r--spec/services/users/activity_service_spec.rb12
-rw-r--r--spec/services/users/migrate_to_ghost_user_service_spec.rb2
-rw-r--r--spec/services/web_hook_service_spec.rb6
-rw-r--r--spec/sidekiq/cron/job_gem_dependency_spec.rb4
-rw-r--r--spec/simplecov_env.rb6
-rw-r--r--spec/spec_helper.rb20
-rw-r--r--spec/support/controllers/githubish_import_controller_shared_examples.rb103
-rw-r--r--spec/support/features/reportable_note_shared_examples.rb2
-rw-r--r--spec/support/features/resolving_discussions_in_issues_shared_examples.rb2
-rw-r--r--spec/support/features/variable_list_shared_examples.rb8
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci.yml3
-rw-r--r--spec/support/helpers/api_helpers.rb7
-rw-r--r--spec/support/helpers/fake_blob_helpers.rb2
-rw-r--r--spec/support/helpers/features/responsive_table_helpers.rb32
-rw-r--r--spec/support/helpers/file_mover_helpers.rb12
-rw-r--r--spec/support/helpers/graphql_helpers.rb35
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb66
-rw-r--r--spec/support/helpers/login_helpers.rb15
-rw-r--r--spec/support/helpers/migrations_helpers.rb16
-rw-r--r--spec/support/helpers/rake_helpers.rb2
-rw-r--r--spec/support/helpers/reactive_caching_helpers.rb2
-rw-r--r--spec/support/helpers/select2_helper.rb6
-rw-r--r--spec/support/helpers/stub_configuration.rb4
-rw-r--r--spec/support/helpers/stub_env.rb2
-rw-r--r--spec/support/helpers/stub_feature_flags.rb27
-rw-r--r--spec/support/helpers/stub_gitlab_calls.rb34
-rw-r--r--spec/support/helpers/stub_object_storage.rb7
-rw-r--r--spec/support/helpers/test_env.rb23
-rw-r--r--spec/support/import_export/export_file_helper.rb2
-rw-r--r--spec/support/matchers/graphql_matchers.rb4
-rw-r--r--spec/support/matchers/not_changed_matcher.rb3
-rw-r--r--spec/support/migrations_helpers/cluster_helpers.rb71
-rw-r--r--spec/support/pg_stat_activity.rb19
-rw-r--r--spec/support/redis/redis_shared_examples.rb4
-rw-r--r--spec/support/shared_contexts/email_shared_context.rb (renamed from spec/support/shared_contexts/email_shared_blocks.rb)0
-rw-r--r--spec/support/shared_contexts/services_shared_context.rb2
-rw-r--r--spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb22
-rw-r--r--spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb10
-rw-r--r--spec/support/shared_examples/controllers/set_sort_order_from_user_preference_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/dirty_submit_form_shared_examples.rb26
-rw-r--r--spec/support/shared_examples/features/editable_merge_request_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/graphql/issuable_state_shared_examples.rb5
-rw-r--r--spec/support/shared_examples/issuable_shared_examples.rb75
-rw-r--r--spec/support/shared_examples/lib/gitlab/background_migration/backfill_project_repositories_examples.rb4
-rw-r--r--spec/support/shared_examples/malicious_regexp_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/mentionable_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/models/cluster_application_initial_status.rb29
-rw-r--r--spec/support/shared_examples/models/cluster_application_status_shared_examples.rb90
-rw-r--r--spec/support/shared_examples/models/cluster_application_version_shared_examples.rb20
-rw-r--r--spec/support/shared_examples/models/with_uploads_shared_examples.rb20
-rw-r--r--spec/support/shared_examples/notify_shared_examples.rb28
-rw-r--r--spec/support/shared_examples/policies/clusterable_shared_examples.rb37
-rw-r--r--spec/support/shared_examples/project_list_shared_examples.rb19
-rw-r--r--spec/support/shared_examples/requests/api/discussions.rb31
-rw-r--r--spec/support/shared_examples/requests/api/merge_requests_list.rb63
-rw-r--r--spec/support/shared_examples/requests/api/notes.rb42
-rw-r--r--spec/support/shared_examples/serializers/diff_file_entity_examples.rb8
-rw-r--r--spec/support/shared_examples/services/boards/issues_move_service.rb16
-rw-r--r--spec/support/shared_examples/url_validator_examples.rb2
-rw-r--r--spec/support/shared_examples/views/nav_sidebar.rb11
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb38
-rw-r--r--spec/tasks/gitlab/shell_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/storage_rake_spec.rb10
-rw-r--r--spec/uploaders/external_diff_uploader_spec.rb67
-rw-r--r--spec/uploaders/file_mover_spec.rb33
-rw-r--r--spec/uploaders/file_uploader_spec.rb4
-rw-r--r--spec/uploaders/import_export_uploader_spec.rb2
-rw-r--r--spec/uploaders/object_storage_spec.rb2
-rw-r--r--spec/uploaders/personal_file_uploader_spec.rb32
-rw-r--r--spec/validators/js_regex_validator_spec.rb2
-rw-r--r--spec/validators/sha_validator_spec.rb42
-rw-r--r--spec/validators/url_validator_spec.rb51
-rw-r--r--spec/views/ci/status/_icon.html.haml_spec.rb89
-rw-r--r--spec/views/help/instance_configuration.html.haml_spec.rb6
-rw-r--r--spec/views/layouts/_head.html.haml_spec.rb8
-rw-r--r--spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb2
-rw-r--r--spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb13
-rw-r--r--spec/views/layouts/nav/sidebar/_instance_statistics.html.haml_spec.rb7
-rw-r--r--spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb13
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb58
-rw-r--r--spec/views/projects/_home_panel.html.haml_spec.rb2
-rw-r--r--spec/views/projects/commit/_commit_box.html.haml_spec.rb6
-rw-r--r--spec/views/projects/commit/show.html.haml_spec.rb4
-rw-r--r--spec/views/projects/commits/_commit.html.haml_spec.rb59
-rw-r--r--spec/views/projects/deployments/_confirm_rollback_modal_spec.html.rb63
-rw-r--r--spec/views/projects/issues/_merge_requests_status.html.haml_spec.rb28
-rw-r--r--spec/views/projects/issues/_related_branches.html.haml_spec.rb4
-rw-r--r--spec/views/projects/issues/show.html.haml_spec.rb63
-rw-r--r--spec/views/projects/merge_requests/show.html.haml_spec.rb39
-rw-r--r--spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb53
-rw-r--r--spec/views/projects/settings/operations/show.html.haml_spec.rb36
-rw-r--r--spec/workers/build_finished_worker_spec.rb19
-rw-r--r--spec/workers/chat_notification_worker_spec.rb91
-rw-r--r--spec/workers/cleanup_container_repository_worker_spec.rb47
-rw-r--r--spec/workers/expire_build_artifacts_worker_spec.rb14
-rw-r--r--spec/workers/git_garbage_collect_worker_spec.rb11
-rw-r--r--spec/workers/hashed_storage/migrator_worker_spec.rb25
-rw-r--r--spec/workers/hashed_storage/project_migrate_worker_spec.rb48
-rw-r--r--spec/workers/hashed_storage/project_rollback_worker_spec.rb50
-rw-r--r--spec/workers/hashed_storage/rollbacker_worker_spec.rb27
-rw-r--r--spec/workers/import_issues_csv_worker_spec.rb21
-rw-r--r--spec/workers/mail_scheduler/notification_service_worker_spec.rb66
-rw-r--r--spec/workers/post_receive_spec.rb15
-rw-r--r--spec/workers/project_daily_statistics_worker_spec.rb35
-rw-r--r--spec/workers/project_migrate_hashed_storage_worker_spec.rb47
-rw-r--r--spec/workers/prune_old_events_worker_spec.rb4
-rw-r--r--spec/workers/remote_mirror_notification_worker_spec.rb39
-rw-r--r--spec/workers/repository_fork_worker_spec.rb7
-rw-r--r--spec/workers/repository_update_remote_mirror_worker_spec.rb7
-rw-r--r--spec/workers/storage_migrator_worker_spec.rb25
-rw-r--r--spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb14
-rw-r--r--vendor/licenses.csv1
-rw-r--r--vendor/project_templates/dotnetcore.tar.gzbin0 -> 7027 bytes
-rw-r--r--vendor/project_templates/express.tar.gzbin4894 -> 16098 bytes
-rw-r--r--vendor/project_templates/gitbook.tar.gzbin0 -> 13068 bytes
-rw-r--r--vendor/project_templates/gomicro.tar.gzbin0 -> 5388 bytes
-rw-r--r--vendor/project_templates/hexo.tar.gzbin0 -> 547220 bytes
-rw-r--r--vendor/project_templates/hugo.tar.gzbin0 -> 1047952 bytes
-rw-r--r--vendor/project_templates/jekyll.tar.gzbin0 -> 60086 bytes
-rw-r--r--vendor/project_templates/nfgitbook.tar.gzbin0 -> 122562 bytes
-rw-r--r--vendor/project_templates/nfhexo.tar.gzbin0 -> 655028 bytes
-rw-r--r--vendor/project_templates/nfhugo.tar.gzbin0 -> 1159251 bytes
-rw-r--r--vendor/project_templates/nfjekyll.tar.gzbin0 -> 132262 bytes
-rw-r--r--vendor/project_templates/nfplainhtml.tar.gzbin0 -> 122392 bytes
-rw-r--r--vendor/project_templates/plainhtml.tar.gzbin0 -> 11389 bytes
-rw-r--r--vendor/project_templates/rails.tar.gzbin25182 -> 25490 bytes
-rw-r--r--vendor/project_templates/spring.tar.gzbin49476 -> 49518 bytes
-rw-r--r--vendor/prometheus/values.yaml102
-rw-r--r--yarn.lock4633
5888 files changed, 248664 insertions, 66422 deletions
diff --git a/.babelrc.js b/.babelrc.js
deleted file mode 100644
index bfcc7d96634..00000000000
--- a/.babelrc.js
+++ /dev/null
@@ -1,44 +0,0 @@
-const BABEL_ENV = process.env.BABEL_ENV || process.env.NODE_ENV || null;
-
-const presets = [
- [
- '@babel/preset-env',
- {
- modules: false,
- targets: {
- ie: '11',
- },
- },
- ],
-];
-
-// include stage 3 proposals
-const plugins = [
- '@babel/plugin-syntax-dynamic-import',
- '@babel/plugin-syntax-import-meta',
- '@babel/plugin-proposal-class-properties',
- '@babel/plugin-proposal-json-strings',
-];
-
-// add code coverage tooling if necessary
-if (BABEL_ENV === 'coverage') {
- plugins.push([
- 'babel-plugin-istanbul',
- {
- exclude: ['spec/javascripts/**/*', 'app/assets/javascripts/locale/**/app.js'],
- },
- ]);
-}
-
-// add rewire support when running tests
-if (BABEL_ENV === 'karma' || BABEL_ENV === 'coverage') {
- plugins.push('babel-plugin-rewire');
-}
-
-// Jest is running in node environment
-if (BABEL_ENV === 'jest') {
- plugins.push('transform-es2015-modules-commonjs');
- plugins.push('dynamic-import-node');
-}
-
-module.exports = { presets, plugins };
diff --git a/.gitignore b/.gitignore
index 65f61e1fade..0696dd217af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,3 +80,4 @@ eslint-report.html
package-lock.json
/junit_*.xml
/coverage-frontend/
+jsdoc/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3d12f4142ba..17189727d1f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.9-git-2.18-chrome-69.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29"
+image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.11-git-2.18-chrome-71.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29"
.dedicated-runner: &dedicated-runner
retry: 1
@@ -120,9 +120,8 @@ stages:
variables: &single-script-job-variables
GIT_STRATEGY: none
before_script:
- # We need to download the script rather than clone the repo since the
- # package-and-qa job will not be able to run when the branch gets
- # deleted (when merging the MR).
+ # We don't clone the repo by using GIT_STRATEGY: none and only download the
+ # single script we need here so it's much faster than cloning.
- export SCRIPT_NAME="${SCRIPT_NAME:-$CI_JOB_NAME}"
- apk add --update openssl
- wget $CI_PROJECT_URL/raw/$CI_COMMIT_SHA/scripts/$SCRIPT_NAME
@@ -228,20 +227,21 @@ stages:
# Trigger a package build in omnibus-gitlab repository
#
package-and-qa:
- <<: *single-script-job
+ image: ruby:2.5-alpine
+ stage: test
+ before_script: []
+ dependencies: []
+ cache: {}
variables:
- <<: *single-script-job-variables
+ GIT_DEPTH: "1"
API_TOKEN: "${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}"
- SCRIPT_NAME: trigger-build
retry: 0
script:
- - gem install gitlab --no-document
- apk add --update openssl curl jq
- - wget $CI_PROJECT_URL/raw/$CI_COMMIT_SHA/scripts/review_apps/review-apps.sh
- - chmod 755 review-apps.sh
- - source ./review-apps.sh
+ - gem install gitlab --no-document
+ - source ./scripts/review_apps/review-apps.sh
- wait_for_job_to_be_done "gitlab:assets:compile"
- - ./$SCRIPT_NAME omnibus
+ - ./scripts/trigger-build omnibus
when: manual
only:
- //@gitlab-org/gitlab-ce
@@ -315,6 +315,7 @@ cloud-native-image:
variables:
GIT_DEPTH: "1"
cache: {}
+ when: always
script:
- gem install gitlab --no-document
- CNG_PROJECT_PATH="gitlab-org/build/CNG" BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN ./scripts/trigger-build cng
@@ -385,20 +386,25 @@ flaky-examples-check:
- scripts/merge-reports ${NEW_FLAKY_SPECS_REPORT} rspec_flaky/new_*_*.json
- scripts/detect-new-flaky-examples $NEW_FLAKY_SPECS_REPORT
+.assets-compile-cache: &assets-compile-cache
+ cache:
+ key: "assets-compile:vendor_ruby:.yarn-cache:tmp_cache_assets_sprockets:v5"
+ paths:
+ - vendor/ruby/
+ - .yarn-cache/
+ - tmp/cache/assets/sprockets
+
compile-assets:
<<: *dedicated-runner
<<: *except-docs
<<: *use-pg
stage: prepare
- cache:
- <<: *default-cache
script:
- node --version
- - date
- yarn install --frozen-lockfile --cache-folder .yarn-cache
- - date
- free -m
- bundle exec rake gitlab:assets:compile
+ - scripts/clean-old-cached-assets
variables:
# we override the max_old_space_size to prevent OOM errors
NODE_OPTIONS: --max_old_space_size=3584
@@ -407,6 +413,7 @@ compile-assets:
paths:
- node_modules
- public/assets
+ <<: *assets-compile-cache
setup-test-env:
<<: *dedicated-runner
@@ -426,15 +433,7 @@ setup-test-env:
- vendor/gitaly-ruby
# GitLab Review apps
-.review-base: &review-base
- <<: *dedicated-no-docs-no-db-pull-cache-job
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base
- stage: test
- cache: {}
- dependencies: []
- environment: &review-environment
- name: review/${CI_COMMIT_REF_NAME}
- url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
+.review-only: &review-only
only:
refs:
- branches@gitlab-org/gitlab-ce
@@ -444,6 +443,28 @@ setup-test-env:
refs:
- master
- /(^docs[\/-].*|.*-docs$)/
+
+.review-schedules-only: &review-schedules-only
+ only:
+ refs:
+ - schedules@gitlab-org/gitlab-ce
+ - schedules@gitlab-org/gitlab-ee
+ kubernetes: active
+ except:
+ refs:
+ - tags
+ - /(^docs[\/-].*|.*-docs$)/
+
+.review-base: &review-base
+ <<: *dedicated-no-docs-no-db-pull-cache-job
+ <<: *review-only
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base
+ stage: test
+ cache: {}
+ dependencies: []
+ environment: &review-environment
+ name: review/${CI_COMMIT_REF_NAME}
+ url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
before_script: []
.review-docker: &review-docker
@@ -498,6 +519,23 @@ rspec-mysql:
<<: *rspec-metadata-mysql
parallel: 50
+.rspec-quarantine: &rspec-quarantine
+ retry: 0
+ script:
+ - export CACHE_CLASSES=true
+ - scripts/gitaly-test-spawn
+ - bin/rspec --color --format documentation --tag quarantine spec/
+
+rspec-pg-quarantine:
+ <<: *rspec-metadata-pg
+ <<: *rspec-quarantine
+ allow_failure: true
+
+rspec-mysql-quarantine:
+ <<: *rspec-metadata-mysql
+ <<: *rspec-quarantine
+ allow_failure: true
+
static-analysis:
<<: *dedicated-no-docs-no-db-pull-cache-job
dependencies:
@@ -526,7 +564,7 @@ docs lint:
script:
- scripts/lint-doc.sh
- scripts/lint-changelog-yaml
- - mv doc/ /tmp/gitlab-docs/content/
+ - mv doc/ /tmp/gitlab-docs/content/$DOCS_GITLAB_REPO_SUFFIX
- cd /tmp/gitlab-docs
# Build HTML from Markdown
- bundle exec nanoc
@@ -607,8 +645,9 @@ gitlab:setup-mysql:
# Frontend-related jobs
gitlab:assets:compile:
<<: *dedicated-no-docs-pull-cache-job
- image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-git-2.18-chrome-69.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1
- dependencies: []
+ image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-git-2.18-chrome-71.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1
+ dependencies:
+ - setup-test-env
services:
- docker:stable-dind
variables:
@@ -622,26 +661,51 @@ gitlab:assets:compile:
DOCKER_DRIVER: overlay2
DOCKER_HOST: tcp://docker:2375
script:
- - date
+ - node --version
- yarn install --frozen-lockfile --production --cache-folder .yarn-cache
- - date
- free -m
- bundle exec rake gitlab:assets:compile
- - scripts/build_assets_image
+ - time scripts/build_assets_image
+ - scripts/clean-old-cached-assets
artifacts:
name: webpack-report
expire_in: 31d
paths:
- webpack-report/
- public/assets/
+ <<: *assets-compile-cache
only:
- //@gitlab-org/gitlab-ce
- //@gitlab-org/gitlab-ee
- //@gitlab/gitlabhq
- //@gitlab/gitlab-ee
tags:
- - gitlab-org-delivery
- - high-cpu
+ - docker
+ - gitlab-org
+
+gitlab:ui:visual:
+ <<: *except-docs
+ tags:
+ - gitlab-org
+ before_script: []
+ dependencies:
+ - compile-assets
+ script:
+ # Remove node modules from GitLab that may conflict with gitlab-ui
+ - rm -r node_modules
+ - git clone https://gitlab.com/gitlab-org/gitlab-ui.git
+ - cp public/assets/application-*.css gitlab-ui/styles/application.css
+ - cd gitlab-ui
+ - yarn install
+ - CSS_URL=./application.css yarn test
+ only:
+ changes:
+ - app/assets/stylesheets/*.scss
+ - app/assets/stylesheets/**/*.scss
+ - app/assets/stylesheets/**/**/*.scss
+ artifacts:
+ paths:
+ - tests/__image_snapshots__/
karma:
<<: *dedicated-no-docs-pull-cache-job
@@ -787,6 +851,7 @@ qa:selectors:
- bundle exec bin/qa Test::Sanity::Selectors
.qa-frontend-node: &qa-frontend-node
+ <<: *dedicated-no-docs-no-db-pull-cache-job
stage: test
variables:
NODE_OPTIONS: --max_old_space_size=3584
@@ -801,11 +866,6 @@ qa:selectors:
- yarn install --frozen-lockfile --cache-folder .yarn-cache
- date
- yarn run webpack-prod
- <<: *except-docs
-
-qa-frontend-node:6:
- <<: *qa-frontend-node
- image: node:6-alpine
qa-frontend-node:8:
<<: *qa-frontend-node
@@ -853,6 +913,21 @@ lint:javascript:report:
paths:
- eslint-report.html
+jsdoc:
+ <<: *dedicated-no-docs-pull-cache-job
+ stage: post-test
+ dependencies:
+ - compile-assets
+ before_script: []
+ script:
+ - date
+ - yarn run jsdoc || true # ignore exit code
+ artifacts:
+ name: jsdoc
+ expire_in: 31d
+ paths:
+ - jsdoc/
+
pages:
<<: *dedicated-no-docs-no-db-pull-cache-job
before_script: []
@@ -862,6 +937,7 @@ pages:
- karma
- gitlab:assets:compile
- lint:javascript:report
+ - jsdoc
script:
- mv public/ .public/
- mkdir public/
@@ -871,6 +947,7 @@ pages:
- mv webpack-report/ public/webpack-report/ || true
- cp .public/assets/application-*.css public/application.css || true
- cp .public/assets/application-*.css.gz public/application.css.gz || true
+ - mv jsdoc/ public/jsdoc/ || true
artifacts:
paths:
- public
@@ -917,7 +994,31 @@ no_ee_check:
- //@gitlab-org/gitlab-ce
# GitLab Review apps
-review-deploy:
+.review-build-cng-base: &review-build-cng-base
+ image: ruby:2.5-alpine
+ stage: test
+ before_script: []
+ dependencies: []
+ cache: {}
+ variables:
+ GIT_DEPTH: "1"
+ API_TOKEN: "${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}"
+ script:
+ - apk add --update openssl curl jq
+ - gem install gitlab --no-document
+ - source ./scripts/review_apps/review-apps.sh
+ - wait_for_job_to_be_done "gitlab:assets:compile"
+ - BUILD_TRIGGER_TOKEN=$REVIEW_APPS_BUILD_TRIGGER_TOKEN ./scripts/trigger-build cng
+
+review-build-cng:
+ <<: *review-only
+ <<: *review-build-cng-base
+
+schedule:review-build-cng:
+ <<: *review-schedules-only
+ <<: *review-build-cng-base
+
+.review-deploy-base: &review-deploy-base
<<: *review-base
retry: 2
allow_failure: true
@@ -931,15 +1032,15 @@ review-deploy:
<<: *review-environment
on_stop: review-stop
before_script:
- - apk update && apk add jq
- - gem install gitlab --no-document
- script:
- export GITLAB_SHELL_VERSION=$(<GITLAB_SHELL_VERSION)
- export GITALY_VERSION=$(<GITALY_SERVER_VERSION)
- export GITLAB_WORKHORSE_VERSION=$(<GITLAB_WORKHORSE_VERSION)
+ - apk update && apk add jq
+ - gem install gitlab --no-document
- source ./scripts/review_apps/review-apps.sh
- - wait_for_job_to_be_done "gitlab:assets:compile"
- - BUILD_TRIGGER_TOKEN=$REVIEW_APPS_BUILD_TRIGGER_TOKEN ./scripts/trigger-build cng
+ script:
+ - wait_for_job_to_be_done "review-build-cng"
+ after_script:
- check_kube_domain
- download_gitlab_chart
- ensure_namespace
@@ -948,9 +1049,17 @@ review-deploy:
- time deploy
- add_license
+review-deploy:
+ <<: *review-deploy-base
+
+schedule:review-deploy:
+ <<: *review-deploy-base
+ <<: *review-schedules-only
+ script:
+ - wait_for_job_to_be_done "schedule:review-build-cng"
+
.review-qa-base: &review-qa-base
<<: *review-docker
- retry: 2
allow_failure: true
variables:
<<: *review-docker-variables
@@ -975,19 +1084,40 @@ review-deploy:
- apk update && apk add curl jq
- source ./scripts/review_apps/review-apps.sh
- gem install gitlab-qa --no-document ${GITLAB_QA_VERSION:+ --version ${GITLAB_QA_VERSION}}
- - wait_for_job_to_be_done "review-deploy"
review-qa-smoke:
<<: *review-qa-base
script:
+ - wait_for_job_to_be_done "review-deploy"
- gitlab-qa Test::Instance::Smoke "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}"
review-qa-all:
<<: *review-qa-base
script:
+ - wait_for_job_to_be_done "review-deploy"
- gitlab-qa Test::Instance::Any "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}"
when: manual
+
+.review-performance-base: &review-performance-base
+ <<: *review-qa-base
+ script:
+ - wait_for_job_to_be_done "review-deploy"
+ after_script:
+ - mkdir gitlab-exporter
+ - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js
+ - mkdir sitespeed-results
+ - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL"
+ - mv sitespeed-results/data/performance.json performance.json
+ artifacts:
+ paths:
+ - sitespeed-results/
+ reports:
+ performance: performance.json
+
+review-performance:
+ <<: *review-performance-base
+
review-stop:
<<: *review-base
<<: *single-script-job
@@ -1007,21 +1137,20 @@ review-stop:
schedule:review-cleanup:
<<: *review-base
+ <<: *review-schedules-only
stage: build
allow_failure: true
variables:
GIT_DEPTH: "1"
environment:
name: review/auto-cleanup
- only:
- refs:
- - schedules@gitlab-org/gitlab-ce
- - schedules@gitlab-org/gitlab-ee
- kubernetes: active
- except:
- - tags
- - /(^docs[\/-].*|.*-docs$)/
before_script:
- gem install gitlab --no-document
script:
- ruby -rrubygems scripts/review_apps/automated_cleanup.rb
+
+schedule:review-performance:
+ <<: *review-performance-base
+ <<: *review-schedules-only
+ script:
+ - wait_for_job_to_be_done "schedule:review-deploy"
diff --git a/.gitlab/issue_templates/Coding style proposal.md b/.gitlab/issue_templates/Coding style proposal.md
new file mode 100644
index 00000000000..1a3be44bea0
--- /dev/null
+++ b/.gitlab/issue_templates/Coding style proposal.md
@@ -0,0 +1,16 @@
+## Description of the proposal
+
+<!--
+Please describe the proposal and add a link to the source (for example, http://www.betterspecs.org/).
+-->
+
+- [ ] Mention the proposal in the next backend weekly call and the #backend channel to encourage contribution
+- [ ] Proceed with the proposal once 50% of the maintainers have weighed in, and 80% of the votes are :+1:
+- [ ] Once approved, mention it again in the next backend weekly call and the #backend channel
+
+
+/label ~"development guidelines"
+/label ~"Style decision"
+/label ~Documentation
+
+/cc @gitlab-org/maintainers/rails-backend
diff --git a/.gitlab/issue_templates/Doc Review.md b/.gitlab/issue_templates/Doc Review.md
new file mode 100644
index 00000000000..14ab0c82d59
--- /dev/null
+++ b/.gitlab/issue_templates/Doc Review.md
@@ -0,0 +1,20 @@
+<!-- This issue requests a technical writer review as required for documentation
+ content that was merged without one. -->
+
+<!-- NOTE: Please add a DevOps stage label (format `devops:<stage_name>`)
+ and assign the technical writer who is
+ [listed for that stage](https://about.gitlab.com/handbook/product/categories/#devops-stages). -->
+
+
+## References
+
+Merged MR that introduced documentation requiring review:
+
+Related issue(s):
+
+## Further Details
+
+<!-- Any additional context, questions, or notes for the technical writer. -->
+
+
+/label ~Documentation ~docs-review
diff --git a/.gitlab/issue_templates/Documentation.md b/.gitlab/issue_templates/Documentation.md
index b33ed5bcaa8..c0919aeeda4 100644
--- a/.gitlab/issue_templates/Documentation.md
+++ b/.gitlab/issue_templates/Documentation.md
@@ -1,54 +1,53 @@
-<!--See the general documentation guidelines https://docs.gitlab.com/ee/development/documentation -->
+<!--
-<!-- Mention "documentation" or "docs" in the issue title -->
+* Use this issue template for suggesting new docs or updates to existing docs.
+ Note: Doc work as part of feature development is covered in the Feature Request template.
+
+* For issues related to features of the docs.gitlab.com site, see
+ https://gitlab.com/gitlab-com/gitlab-docs/issues/
-<!-- Use this description template for new docs or updates to existing docs. -->
+* For information about documentation content and process, see
+ https://docs.gitlab.com/ee/development/documentation/ -->
-<!-- Check the documentation structure guidelines for guidance: https://docs.gitlab.com/ee/development/documentation/structure.html-->
+### Type of issue
-- [ ] Documents Feature A <!-- feature name -->
-- [ ] Follow-up from: #XXX, !YYY <!-- Mention related issues, MRs, and epics when available -->
+<!-- Un-comment the line for the applicable doc issue type to add its label.
+ Note that all text on that line is deleted upon issue creation. -->
+<!-- /label ~"docs:fix" - Correction or clarification needed. -->
+<!-- /label ~"docs:new" - New doc needed to cover a new topic or use case. -->
+<!-- /label ~"docs:improvement" - Improving an existing doc; e.g. adding a diagram, adding or rewording text, resolving redundancies, cross-linking, etc. -->
+<!-- /label ~"docs:revamp" - Review a page or group of pages in order to plan and implement major improvements/rewrites. -->
+<!-- /label ~"docs:other" - Anything else. -->
-## New doc or update?
+### Problem to solve
-<!-- Mark either of these boxes: -->
+<!-- Include the following detail as necessary:
+* What product or feature(s) affected?
+* What docs or doc section affected? Include links or paths.
+* Is there a problem with a specific document, or a feature/process that's not addressed sufficiently in docs?
+* Any other ideas or requests?
+-->
-- [ ] New documentation
-- [ ] Update existing documentation
+### Further details
-## Checklists
+<!--
+* Any concepts, procedures, reference info we could add to make it easier to successfully use GitLab?
+* Include use cases, benefits, and/or goals for this work.
+* If adding content: What audience is it intended for? (What roles and scenarios?)
+ For ideas, see personas at https://design.gitlab.com/research/personas or the persona labels at
+ https://gitlab.com/groups/gitlab-org/-/labels?utf8=%E2%9C%93&subscribed=&search=persona%3A
+-->
-### Product Manager
+### Proposal
-<!-- Reference: https://docs.gitlab.com/ee/development/documentation/workflow.html#1-product-manager-s-role-in-the-documentation-process -->
+<!-- Further specifics for how can we solve the problem. -->
-- [ ] Add the correct labels
-- [ ] Add the correct milestone
-- [ ] Indicate the correct document/directory for this feature <!-- (ping the tech writers for help if you're not sure) -->
-- [ ] Fill the doc blurb below
+### Who can address the issue
-#### Documentation blurb
+<!-- What if any special expertise is required to resolve this issue? -->
-<!-- Documentation template: https://docs.gitlab.com/ee/development/documentation/structure.html#documentation-template-for-new-docs -->
+### Other links/references
-- Doc **title**
-
- <!-- write the doc title here -->
-
-- Feature **overview/description**
-
- <!-- Write the feature overview here -->
-
-- Feature **use cases**
-
- <!-- Write the use cases here -->
-
-### Developer
-
-<!-- Reference: https://docs.gitlab.com/ee/development/documentation/workflow.html#2-developer-s-role-in-the-documentation-process -->
-
-- [ ] Copy the doc blurb above and paste it into the doc
-- [ ] Write the tutorial - explain how to use the feature
-- [ ] Submit the MR using the appropriate MR description template
+<!-- E.g. related GitLab issues/MRs -->
/label ~Documentation
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index 639a236631d..eef1e877ff2 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -1,23 +1,55 @@
### Problem to solve
-<!--- What problem do we solve? -->
+<!-- What problem do we solve? -->
### Target audience
-<!--- For whom are we doing this? Include either a persona from https://design.gitlab.com/getting-started/personas or define a specific company role. e.a. "Release Manager" or "Security Analyst" -->
+<!--- For whom are we doing this? Include a [persona](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/)
+listed below, if applicable, along with its [label](https://gitlab.com/groups/gitlab-org/-/labels?utf8=%E2%9C%93&subscribed=&search=persona%3A),
+or define a specific company role, e.g. "Release Manager".
+
+Existing personas are: (copy relevant personas out of this comment, and delete any persona that does not apply)
+
+- Parker, Product Manager, https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas#parker-product-manager
+/label ~"Persona: Product Manager"
+
+- Delaney, Development Team Lead, https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas#delaney-development-team-lead
+/label ~"Persona: Development Team Lead"
+
+- Sasha, Software Developer, https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas#sasha-software-developer
+/label ~"Persona: Software developer"
+
+- Devon, DevOps Engineer, https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas#devon-devops-engineer
+/label ~"Persona: DevOps Engineer"
+
+- Sidney, Systems Administrator, https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas#sidney-systems-administrator
+/label ~"Persona: Systems Administrator"
+
+- Sam, Security Analyst, https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas#sam-security-analyst
+/label ~"Persona: Security Analyst"
+-->
### Further details
-<!--- Include use cases, benefits, and/or goals (contributes to our vision?) -->
+<!-- Include use cases, benefits, and/or goals (contributes to our vision?) -->
### Proposal
-<!--- How are we going to solve the problem? -->
+<!-- How are we going to solve the problem? Try to include the user journey! https://about.gitlab.com/handbook/journeys/#user-journey -->
+
+### Permissions and Security
+
+<!-- What permissions are required to perform the described actions? Are they consistent with the existing permissions as documented for users, groups, and projects as appropriate? Is the proposed behavior consistent between the UI, API, and other access methods (e.g. email replies)? -->
+
+### Documentation
+
+<!-- See the Feature Change Documentation Workflow https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html
+Add all known Documentation Requirements here, per https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html#documentation-requirements -->
### What does success look like, and how can we measure that?
-<!--- If no way to measure success, link to an issue that will implement a way to measure this -->
+<!-- Define both the success metrics and acceptance criteria. Note that success metrics indicate the desired business outcomes, while acceptance criteria indicate when the solution is working correctly. If there is no way to measure success, link to an issue that will implement a way to measure this. -->
### Links / references
-/label ~"feature proposal"
+/label ~feature
diff --git a/.gitlab/issue_templates/Security Release.md b/.gitlab/issue_templates/Security Release.md
new file mode 100644
index 00000000000..ae469d3b125
--- /dev/null
+++ b/.gitlab/issue_templates/Security Release.md
@@ -0,0 +1,69 @@
+<!--
+# Read me first!
+
+Set the title to: `Security Release: 11.4.X, 11.3.X, and 11.2.X`
+-->
+
+## Releases tasks
+
+- https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/release-manager.md
+- https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md
+- https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/security-engineer.md
+
+## Version issues:
+
+* 11.4.X: {release task link}
+* 11.3.X: {release task link}
+* 11.2.X: {release task link}
+
+## Security Issues:
+
+### CE
+
+* {https://gitlab.com/gitlab-org/gitlab-ce/issues link}
+
+### EE
+
+* {https://gitlab.com/gitlab-org/gitlab-ee/issues link}
+
+## Security Issues in dev.gitlab.org:
+
+### CE
+
+- {https://dev.gitlab.org/gitlab/gitlabhq/issues link}
+
+| Version | MR |
+|---------|----|
+| 11.4 | {https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/ link} |
+| 11.3 | {https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/ link} |
+| 11.2 | {https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/ link} |
+| master | {https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/ link} |
+
+
+
+### EE
+
+* {https://dev.gitlab.org/gitlab/gitlabhq/issues/ link}
+
+
+| Version | MR |
+|---------|----|
+| 11.4| {https://dev.gitlab.org/gitlab/gitlab-ee/merge_requests/ link} |
+| 11.3 | {https://dev.gitlab.org/gitlab/gitlab-ee/merge_requests/ link} |
+| 11.2 | {https://dev.gitlab.org/gitlab/gitlab-ee/merge_requests/ link} |
+| master | {https://dev.gitlab.org/gitlab/gitlab-ee/merge_requests/ link} |
+
+
+## QA
+{QA issue link}
+
+## Blog post
+
+Dev: {https://dev.gitlab.org/gitlab/www-gitlab-com/merge_requests/ link}<br/>
+gitlab.com: {https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/ link}
+
+## Email notification
+{https://gitlab.com/gitlab-com/marketing/general/issues/ link}
+
+/label ~security
+/confidential
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index 08651195d98..9946651075f 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -3,30 +3,26 @@
Create this issue under https://dev.gitlab.org/gitlab/gitlabhq
-Set the title to: `[Security] Description of the original issue`
+Set the title to: `Description of the original issue`
-->
-### Prior to the security release
+### Prior to starting the security release work
- [ ] Read the [security process for developers] if you are not familiar with it.
- [ ] Link to the original issue adding it to the [links section](#links)
- [ ] Run `scripts/security-harness` in the CE, EE, and/or Omnibus to prevent pushing to any remote besides `dev.gitlab.org`
-- [ ] Create an MR targetting `org` `master`, prefixing your branch with `security-`
-- [ ] Label your MR with the ~security label, prefix the title with `WIP: [master]`
-- [ ] Add a link to the MR to the [links section](#links)
-- [ ] Add a link to an EE MR if required
-- [ ] Make sure the MR remains in-progress and gets approved after the review cycle, **but never merged**.
-- [ ] Add a link to this issue on the original security issue.
+- [ ] Create a new branch prefixing it with `security-`
+- [ ] Create a MR targeting `dev.gitlab.org` `master`
+- [ ] Add a link to this issue in the original security issue on `gitlab.com`.
#### Backports
-- [ ] Once the MR is ready to be merged, create MRs targetting the last 3 releases
+- [ ] Once the MR is ready to be merged, create MRs targetting the last 3 releases, plus the current RC if between the 7th and 22nd of the month.
- [ ] At this point, it might be easy to squash the commits from the MR into one
- You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation]
- - [ ] Create the branch `security-X-Y` from `X-Y-stable` if it doesn't exist (and make sure it's up to date with stable)
- - [ ] Create each MR targetting the security branch `security-X-Y`
- - [ ] Add the ~security label and prefix with the version `WIP: [X.Y]` the title of the MR
-- [ ] Add the ~"Merge into Security" label to all of the MRs.
+ - [ ] Create each MR targetting the stable branch `X-Y-stable`, using the "Security Release" merge request template.
+ - Every merge request will have its own set of TODOs, so make sure to
+ complete those.
- [ ] Make sure all MRs have a link in the [links section](#links)
[secpick documentation]: https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#secpick-script
@@ -34,6 +30,7 @@ Set the title to: `[Security] Description of the original issue`
#### Documentation and final details
- [ ] Check the topic on #security to see when the next release is going to happen and add a link to the [links section](#links)
+- [ ] Add links to this issue and your MRs in the description of the security release issue
- [ ] Find out the versions affected (the Git history of the files affected may help you with this) and add them to the [details section](#details)
- [ ] Fill in any upgrade notes that users may need to take into account in the [details section](#details)
- [ ] Add Yes/No and further details if needed to the migration and settings columns in the [details section](#details)
diff --git a/.gitlab/merge_request_templates/Change documentation location.md b/.gitlab/merge_request_templates/Change documentation location.md
index b4a6d2bd3b4..c80af95d5e5 100644
--- a/.gitlab/merge_request_templates/Change documentation location.md
+++ b/.gitlab/merge_request_templates/Change documentation location.md
@@ -26,7 +26,7 @@ https://docs.gitlab.com/ce/development/documentation/index.html#changing-documen
to the new document if there are any Disqus comments on the old document thread.
- [ ] Update the link in `features.yml` (if applicable)
- [ ] If working on CE and the `ee-compat-check` jobs fails, submit an MR to EE
- with the changes as well (https://docs.gitlab.com/ce/development/writing_documentation.html#cherry-picking-from-ce-to-ee).
+ with the changes as well (https://docs.gitlab.com/ce/development/documentation/index.html#cherry-picking-from-ce-to-ee).
- [ ] Ping one of the technical writers for review.
/label ~Documentation
diff --git a/.gitlab/merge_request_templates/Database changes.md b/.gitlab/merge_request_templates/Database changes.md
index 354393b60e0..3f457174492 100644
--- a/.gitlab/merge_request_templates/Database changes.md
+++ b/.gitlab/merge_request_templates/Database changes.md
@@ -16,7 +16,7 @@ Add a description of your merge request here.
## Database checklist
-- [ ] Conforms to the [database guides](https://docs.gitlab.com/ee/development/README.html#databases-guides)
+- [ ] Conforms to the [database guides](https://docs.gitlab.com/ee/development/README.html#database-guides)
When adding migrations:
@@ -49,10 +49,10 @@ When removing columns, tables, indexes or other structures:
## General checklist
- [ ] [Changelog entry](https://docs.gitlab.com/ee/development/changelog.html) added, if necessary
-- [ ] [Documentation created/updated](https://docs.gitlab.com/ee/development/documentation/index.html#contributing-to-docs)
+- [ ] [Documentation created/updated](https://docs.gitlab.com/ee/development/documentation/)
- [ ] [Tests added for this feature/bug](https://docs.gitlab.com/ee/development/testing_guide/index.html)
- [ ] Conforms to the [code review guidelines](https://docs.gitlab.com/ee/development/code_review.html)
- [ ] Conforms to the [merge request performance guidelines](https://docs.gitlab.com/ee/development/merge_request_performance_guidelines.html)
-- [ ] Conforms to the [style guides](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/CONTRIBUTING.md#style-guides)
+- [ ] Conforms to the [style guides](https://docs.gitlab.com/ee/development/contributing/style_guides.html)
/label ~database
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index 8b7e7119790..ba9624aeeab 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -1,33 +1,39 @@
-<!--See the general documentation guidelines https://docs.gitlab.com/ee/development/documentation -->
+<!-- Follow the documentation workflow https://docs.gitlab.com/ee/development/documentation/workflow.html -->
+<!-- Additional information is located at https://docs.gitlab.com/ee/development/documentation/ -->
<!-- Mention "documentation" or "docs" in the MR title -->
-
-<!-- Use this description template for new docs or updates to existing docs. For changing documentation location use the "Change documentation location" template -->
+<!-- For changing documentation location use the "Change documentation location" template -->
## What does this MR do?
-<!-- Briefly describe what this MR is about -->
+<!-- Briefly describe what this MR is about. -->
## Related issues
-<!-- Mention the issue(s) this MR closes or is related to -->
-
-Closes
+<!-- Link related issues below. Insert the issue link or reference after the word "Closes" if merging this should automatically close it. -->
## Author's checklist
-- [ ] [Apply the correct labels and milestone](https://docs.gitlab.com/ee/development/documentation/workflow.html#2-developer-s-role-in-the-documentation-process)
-- [ ] Crosslink the document from the higher-level index
-- [ ] Crosslink the document from other subject-related docs
-- [ ] Feature moving tiers? Make sure the change is also reflected in [`features.yml`](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml)
-- [ ] Correctly apply the product [badges](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) and [tiers](https://docs.gitlab.com/ee/development/documentation/styleguide.html#gitlab-versions-and-tiers)
-- [ ] [Port the MR to EE (or backport from CE)](https://docs.gitlab.com/ee/development/documentation/index.html#cherry-picking-from-ce-to-ee): _always recommended, required when the `ee-compat-check` job fails_
+- [ ] Follow the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide.html).
+- [ ] Link docs to and from the higher-level index page, plus other related docs where helpful.
+- [ ] Apply the ~Documentation label.
## Review checklist
-- [ ] Your team's review (required)
-- [ ] PM's review (recommended, but not a blocker)
-- [ ] Technical writer's review (required)
-- [ ] Merge the EE-MR first, CE-MR afterwards
+All reviewers can help ensure accuracy, clarity, completeness, and adherence to the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide.html).
+
+**1. Primary Reviewer**
+
+* [ ] Review by a code reviewer or other selected colleague to confirm accuracy, clarity, and completeness. This can be skipped for minor fixes without substantive content changes.
+
+**2. Technical Writer**
+
+* [ ] Optional: Technical writer review. If not requested for this MR, must be scheduled post-merge. To request for this MR, assign the writer listed for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages).
+
+**3. Maintainer**
+
+1. [ ] Review by assigned maintainer, who can always request/require the above reviews. Maintainer's review can occur before or after a technical writer review.
+1. [ ] Ensure a release milestone is set and that you merge the equivalent EE MR before the CE MR if both exist.
+1. [ ] If there has not been a technical writer review, [create an issue for one using the Doc Review template](https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issuable_template=Doc%20Review).
/label ~Documentation
diff --git a/.gitlab/merge_request_templates/Security Release.md b/.gitlab/merge_request_templates/Security Release.md
new file mode 100644
index 00000000000..246f2dae009
--- /dev/null
+++ b/.gitlab/merge_request_templates/Security Release.md
@@ -0,0 +1,31 @@
+<!--
+# README first!
+This MR should be created on `dev.gitlab.org`.
+
+See [the general developer security release guidelines](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md).
+
+This merge request _must not_ close the corresponding security issue _unless_ it
+targets master.
+
+-->
+## Related issues
+
+<!-- Mention the issue(s) this MR is related to -->
+
+## Developer checklist
+
+- [ ] Link to the developer security workflow issue on `dev.gitlab.org`
+- [ ] MR targets `master`, or `X-Y-stable` for backports
+- [ ] Milestone is set for the version this MR applies to
+- [ ] Title of this MR is the same as for all backports
+- [ ] A [CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html) is added without a `merge_request` value, with `type` set to `security`
+- [ ] Add a link to this MR in the `links` section of related issue
+- [ ] Add a link to an EE MR if required
+- [ ] Assign to a reviewer
+
+## Reviewer checklist
+
+- [ ] Correct milestone is applied and the title is matching across all backports
+- [ ] Assigned to `@gitlab-release-tools-bot` with passing CI pipelines
+
+/label ~security
diff --git a/.rubocop.yml b/.rubocop.yml
index e8e550fdbde..2985c1446e4 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -143,6 +143,7 @@ Naming/FileName:
- XMPP
- XSRF
- XSS
+ - GRPC
# GitLab ###################################################################
@@ -180,3 +181,6 @@ Cop/InjectEnterpriseEditionModule:
Exclude:
- 'spec/**/*'
- 'ee/spec/**/*'
+
+Style/ReturnNil:
+ Enabled: true
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 847a0f74aa2..97e39ce99cb 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -15,12 +15,6 @@ Capybara/CurrentPathExpectation:
Layout/EmptyLinesAroundArguments:
Enabled: false
-# Offense count: 253
-# Cop supports --auto-correct.
-# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment.
-Layout/ExtraSpacing:
- Enabled: false
-
# Offense count: 83
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
@@ -86,11 +80,6 @@ Lint/InterpolationCheck:
Lint/MissingCopEnableDirective:
Enabled: false
-# Offense count: 1
-Lint/ReturnInVoidContext:
- Exclude:
- - 'app/models/project.rb'
-
# Offense count: 9
Lint/UriEscapeUnescape:
Exclude:
@@ -279,7 +268,6 @@ Rails/Presence:
- 'app/models/clusters/platforms/kubernetes.rb'
- 'app/models/concerns/mentionable.rb'
- 'app/models/concerns/token_authenticatable.rb'
- - 'app/models/project_services/hipchat_service.rb'
- 'app/models/project_services/irker_service.rb'
- 'app/models/project_services/jira_service.rb'
- 'app/models/project_services/kubernetes_service.rb'
@@ -443,11 +431,6 @@ Style/LineEndConcatenation:
- 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
- 'spec/lib/gitlab/incoming_email_spec.rb'
-# Offense count: 39
-# Cop supports --auto-correct.
-Style/MethodCallWithoutArgsParentheses:
- Enabled: false
-
# Offense count: 18
Style/MethodMissing:
Enabled: false
@@ -686,17 +669,6 @@ Style/TrailingUnderscoreVariable:
- 'spec/lib/gitlab/etag_caching/middleware_spec.rb'
- 'spec/services/quick_actions/interpret_service_spec.rb'
-# Offense count: 5
-# Cop supports --auto-correct.
-# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
-# Whitelist: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym
-Style/TrivialAccessors:
- Exclude:
- - 'app/models/external_issue.rb'
- - 'app/serializers/base_serializer.rb'
- - 'lib/gitlab/auth/ldap/person.rb'
- - 'lib/system_check/base_check.rb'
-
# Offense count: 4
# Cop supports --auto-correct.
Style/UnlessElse:
diff --git a/.stylelintrc b/.stylelintrc
new file mode 100644
index 00000000000..04784a0a11a
--- /dev/null
+++ b/.stylelintrc
@@ -0,0 +1,107 @@
+{
+ "plugins":[
+ "stylelint-scss"
+ ],
+ "rules":{
+ "at-rule-blacklist":[
+ "debug"
+ ],
+ "at-rule-no-unknown":null,
+ "at-rule-no-vendor-prefix":true,
+ "block-no-empty":true,
+ "block-opening-brace-space-before":"always",
+ "color-hex-case":"lower",
+ "color-hex-length":"short",
+ "color-named":"never",
+ "color-no-invalid-hex":true,
+ "declaration-bang-space-after":"never",
+ "declaration-bang-space-before":"always",
+ "declaration-block-semicolon-newline-after":"always",
+ "declaration-block-semicolon-space-before":"never",
+ "declaration-block-single-line-max-declarations":1,
+ "declaration-block-trailing-semicolon":"always",
+ "declaration-colon-space-after":"always-single-line",
+ "declaration-colon-space-before":"never",
+ "declaration-property-value-blacklist":{
+ "border":[
+ "none"
+ ],
+ "border-top":[
+ "none"
+ ],
+ "border-right":[
+ "none"
+ ],
+ "border-bottom":[
+ "none"
+ ],
+ "border-left":[
+ "none"
+ ]
+ },
+ "function-comma-space-after":"always-single-line",
+ "function-parentheses-space-inside":"never",
+ "function-url-quotes":"always",
+ "indentation":2,
+ "length-zero-no-unit":true,
+ "max-nesting-depth":[
+ 3,
+ {
+ "ignoreAtRules":[
+ "each",
+ "media",
+ "supports",
+ "include"
+ ],
+ "severity":"warning"
+ }
+ ],
+ "media-feature-name-no-vendor-prefix":true,
+ "media-feature-parentheses-space-inside":"never",
+ "no-missing-end-of-source-newline":true,
+ "number-leading-zero":"always",
+ "number-no-trailing-zeros":true,
+ "property-no-unknown":true,
+ "property-no-vendor-prefix":true,
+ "rule-empty-line-before":[
+ "always-multi-line",
+ {
+ "except":[
+ "first-nested"
+ ],
+ "ignore":[
+ "after-comment"
+ ]
+ }
+ ],
+ "scss/at-extend-no-missing-placeholder":[true,{ "severity": "warning" }],
+ "scss/at-function-pattern":"^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
+ "scss/at-import-no-partial-leading-underscore":true,
+ "scss/at-import-partial-extension-blacklist":[
+ "scss"
+ ],
+ "scss/at-mixin-pattern":"^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
+ "scss/at-rule-no-unknown":true,
+ "scss/dollar-variable-colon-space-after":"always",
+ "scss/dollar-variable-colon-space-before":"never",
+ "scss/dollar-variable-pattern":"^[_]?[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
+ "scss/percent-placeholder-pattern":"^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
+ "scss/selector-no-redundant-nesting-selector":true,
+ "selector-class-pattern":[
+ "^[a-z0-9\\-]+$",
+ {
+ "message":"Selector should be written in lowercase with hyphens (selector-class-pattern)",
+ "severity": "warning"
+ },
+ ],
+ "selector-list-comma-newline-after":"always",
+ "selector-max-compound-selectors":[5, { "severity": "warning" }],
+ "selector-max-id":1,
+ "selector-no-vendor-prefix":true,
+ "selector-pseudo-element-colon-notation":"double",
+ "selector-pseudo-element-no-unknown":true,
+ "shorthand-property-no-redundant-values":true,
+ "string-quotes":"single",
+ "value-no-vendor-prefix":true
+ }
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b4fa22ad70e..8a4a6c9ff13 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,584 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 11.8.0 (2019-02-22)
+
+### Security (7 changes, 1 of them is from the community)
+
+- Sanitize user full name to clean up any URL to prevent mail clients from auto-linking URLs. !2793
+- Update Helm to 2.12.2 to address Helm client vulnerability. !24418 (Takuya Noguchi)
+- Use sanitized user status message for user popover.
+- Validate bundle files before unpacking them.
+- Alias GitHub and BitBucket OAuth2 callback URLs.
+- Fixed XSS content in KaTex links.
+- Disallows unauthorized users from accessing the pipelines section.
+
+### Removed (2 changes, 1 of them is from the community)
+
+- Removed deprecated Redcarpet markdown engine.
+- Remove Cancel all jobs button in general jobs list view. (Jordi Llull)
+
+### Fixed (84 changes, 20 of them are from the community)
+
+- Fix ambiguous brackets in task lists. !18514 (Jared Deckard <jared.deckard@gmail.com>)
+- Fix lost line number when navigating to a specific line in a protected file before authenticating. !19165 (Scott Escue)
+- Fix suboptimal handling of checkbox and radio input events causing group general settings submit button to stay disabled after changing its visibility. !23022
+- Fix upcoming milestones filter not including group milestones. !23098 (Heinrich Lee Yu)
+- Update runner admin page to make description field larger. !23593 (Sascha Reynolds)
+- Fix Bitbucket Server import not allowing personal projects. !23601
+- Fix bug causing repository mirror settings UI to break. !23712
+- Fix foreground color for labels to ensure consistency of label appearance. !23873 (Nathan Friend)
+- Resolve In Merge Request diff screen, master is not a hyperlink. !23874
+- Show the correct error page when access is denied. !23932
+- Increase reliability and performance of toggling task items. !23938
+- Modify file restore to rectify tar issue. !24000
+- Fix default visibility_level for new projects. !24120 (Fabian Schneider @fabsrc)
+- Footnotes now render properly in markdown. !24168
+- Emoji and cancel button are taller than input in set user status modal. !24173 (Dhiraj Bodicherla)
+- Adjusts duplicated line when commenting on unfolded diff lines (in the bottom). !24201
+- Adjust height of "Add list" dropdown in issue boards. !24227
+- Improves restriction of multiple Kubernetes clusters through API. !24251
+- Fix files/blob api endpoints content disposition. !24267
+- Cleanup stale +deleted repo paths on project removal (adjusts project removal bug). !24269
+- Handle regular job dependencies next to parallelized job dependencies. !24273
+- Proper align Projects dropdown on issue boards page. !24277 (Johann Hubert Sonntagbauer)
+- Resolve When merging an MR, the squash checkbox isnt always supported. !24296
+- Fix Bitbucket Server importer error handling. !24343
+- Fix syntax highlighting for suggested changes preview. !24358
+- API: Support dots in wiki slugs. !24383 (Robert Schilling)
+- Show CI artifact file size with 3 significant digits on 'browse job artifacts' page. !24387
+- API: Support username with dots. !24395 (Robert Schilling)
+- API: Fix default_branch_protection admin setting. !24398 (Robert Schilling)
+- Remove unwanted margin above suggested changes. !24419
+- Prevent checking protected_ref? for ambiguous refs. !24437
+- Update metrics environment dropdown to show complete option set. !24441
+- Fix empty labels of CI builds for gitlab-pages on pipeline page. !24451
+- Do not run spam checks on confidential issues. !24453
+- Upgrade KaTeX to version 0.10.0. !24478 (Andrew Harmon)
+- Avoid overwriting default jaeger values with nil. !24482
+- Display SAML failure messages instead of expecting CSRF token. !24509
+- Adjust vertical alignment for project visibility icons. !24511 (Martin Hobert)
+- Load initUserInternalRegexPlaceholder only when required. !24522
+- Hashed Storage: `AfterRenameService` was receiving the wrong `old_path` under some circunstances. !24526
+- Resolve Runners IPv6 address overlaps other values. !24531
+- Fix 404s with snippet uploads in object storage. !24550
+- Fixed oversized custom project notification selector dropdown. !24557
+- Allow users with full private access to read private personal snippets. !24560
+- Resolve Pipeline stages job action button icon is not aligned. !24577
+- Fix cluster page non-interactive on form validation error. !24583
+- Fix 404s for snippet uploads when relative URL root used. !24588
+- Fix markdown table border. !24601
+- Fix CSS grid on a new Project/Group Milestone. !24614 (Takuya Noguchi)
+- Prevent unload when Recaptcha is open. !24625
+- Clean up unicorn sampler metric labels. !24626 (bjk-gitlab)
+- Support bamboo api polymorphism. !24680 (Alex Lossent)
+- Ensure Cert Manager works with Auto DevOps URLs greater than 64 bytes. !24683
+- Fix failed LDAP logins when nil user_id present. !24749
+- fix display comment avatars issue in IE 11. !24777 (Gokhan Apaydin)
+- Fix template labels not being created on new projects. !24803
+- Fix cluster installation processing spinner. !24814
+- Append prioritized label before pagination. !24815
+- Resolve UI bug adding group members with lower permissions. !24820
+- Make `ActionController::Parameters` serializable for sidekiq jobs. !24864
+- Fix Jira Service password validation on project integration services. !24896 (Daniel Juarez)
+- Fix potential Addressable::URI::InvalidURIError. !24908
+- Update Workhorse to v8.2.0. !24909
+- Encode Content-Disposition filenames. !24919
+- Avoid race conditions when creating GpgSignature. !24939
+- Create the source branch for a GitHub import. !25064
+- Fix suggested changes syntax highlighting. !25116
+- Fix counts in milestones dashboard. !25230
+- Fixes incorrect TLD validation errors for Kubernetes cluster domain. !25262
+- Fix 403 errors when adding an assignee list in project boards. !25263
+- Prevent Auto DevOps from trying to deploy without a domain name. !25308
+- Fix uninitialized constant with GitLab Pages.
+- Increase line height of project summaries. (gfyoung)
+- Remove extra space between MR tab bar and sticky file headers.
+- Correct spacing for comparison page.
+- Update CI YAML param table with include.
+- Return bottom border on MR Tabs.
+- Fixes z-index and margins of archived alert in job page.
+- Fixes archived sticky top bar without perfomance bar.
+- Fixed rebase button not showing in merge request widget.
+- Fixed double tooltips on note awards buttons.
+- Allow suggestions to be copied and pasted as GFM.
+- Fix bug that caused Suggestion Markdown toolbar button to insert snippet with leading +/-/<space>.
+- Moved primary button for labels to follow the design patterns used on rest of the site. (Martin Hobert)
+
+### Changed (37 changes, 11 of them are from the community)
+
+- Change spawning of tooltips to be top by default. !21223
+- Standardize filter value capitlization in filter bar in both issues and boards pages. !23846 (obahareth)
+- Refresh group overview to match project overview. !23866
+- Build number does not need to be tweaked anymore for the TeamCity integration to work properly. !23898
+- Added empty project illustration and updated text to user profile overview. !23973 (Fernando Arias)
+- Modified Knative list view to provide more details. !24072 (Chris Baumbauer)
+- Move cancel & new issue button on job page. !24074
+- Make issuable empty states actionable. !24077
+- Fix code search when text is larger than max gRPC message size. !24111
+- Update string structure for available group runners. !24187 (George Tsiolis)
+- Remove multilingual translation from the word "in" in the job details sidebar. !24192 (Nathan Friend)
+- Fix duplicate project disk path in BackfillLegacyProjectRepositories. !24213
+- Ensured links to a comment or system note anchor resolves to the right note if a user has a discussion filter. !24228
+- Remove expansion hover animation from pipeline status icon buttons. !24268 (Nathan Friend)
+- Redesigned related merge requests in issue page. !24270
+- Return the maximum group access level in the projects API. !24403
+- Update project topics styling to use badges design. !24415
+- Display "commented" only for commit discussions on merge requests. !24427
+- Upgrade js-regex gem to version 3.1. !24433 (rroger)
+- Prevent Sidekiq arguments over 10 KB in size from being logged to JSON. !24493
+- Added Avatar in the settings sidebar. !24515 (Yoginth)
+- Refresh empty states for profile page tabs. !24549
+- remove red/green colors from diff view of no-color syntax theme. !24582 (khm)
+- Get remote IP address of runner. !24624
+- Update last_activity_on for Users on some main GET endpoints. !24642
+- Update metrics dashboard graph design. !24653
+- Update to GitLab SVG icon from Font Awesome in profile for location and work. !24671 (Yoginth)
+- Add template for Android with Fastlane. !24722
+- Display timestamps to messages printed by gitlab:backup:restore rake tasks. (Will Chandler)
+- Show MR statistics in diff comparisons.
+- Make possible to toggle file tree while scrolling through diffs.
+- Use delete instead of remove when referring to `git branch -D`.
+- Add folder header to files in merge request tree list.
+- Added fuzzy file finder to merge requests.
+- Collapse directory structure in merge request file tree.
+- Adds skeleton loading to releases page.
+- Support multiple outputs in jupyter notebooks.
+
+### Performance (8 changes, 1 of them is from the community)
+
+- Remove unused button classes `btn-create` and `comment-btn`. !23232 (George Tsiolis)
+- [API] Omit `X-Total` and `X-Total-Pages` headers when items count is more than 10,000. !23931
+- Improve efficiency of GitHub importer by reducing amount of locks needed. !24102
+- Improve milestone queries using subqueries instead of separate queries for ids. !24325
+- Efficiently remove expired artifacts in `ExpireBuildArtifactsWorker`. !24450
+- Eliminate N+1 queries in /api/groups/:id. !24513
+- Use deployment relation to get an environment name. !24890
+- Do not reload daemon if configuration file of pages does not change.
+
+### Added (35 changes, 18 of them are from the community)
+
+- Add badge count to projects. !18425 (George Tsiolis)
+- API: Add support for group labels. !21368 (Robert Schilling)
+- Add setting for first day of the week. !22755 (Fabian Schneider @fabsrc)
+- Pages for subgroups. !23505
+- Add support for customer provided encryption keys for Amazon S3 remote backups. !23797 (Pepijn Van Eeckhoudt)
+- Add Knative detailed view. !23863 (Chris Baumbauer)
+- Add group full path to project's shared_with_groups. !24052 (Mathieu Parent)
+- Added feature to specify a custom Auto DevOps chart repository. !24162 (walkafwalka)
+- Add flat-square badge style. !24172 (Fabian Schneider @fabsrc)
+- Display last activity and created at datetimes for users. !24181
+- Allow setting of feature gates per project. !24184
+- Save issues/merge request sorting options to backend. !24198
+- Added support for custom hosts/domains to Auto DevOps. !24248 (walkafwalka)
+- Adds milestone search. !24265 (Jacopo Beschi @jacopo-beschi)
+- Allow merge request diffs to be placed into an object store. !24276
+- Add Container Registry API with cleanup function. !24303
+- GitLab now supports the profile and email scopes from OpenID Connect. !24335 (Goten Xiao)
+- Add 'in' filter that modifies scope of 'search' filter to issues and merge requests API. !24350 (Hiroyuki Sato)
+- Add `with_programming_language` filter for projects to API. !24377 (Dylan MacKenzie)
+- API: Support searching for tags. !24385 (Robert Schilling)
+- Document graphicsmagick installation for source installation. !24404 (Alexis Reigel)
+- Redirect GET projects/:id to project page. !24467
+- Indicate on Issue Status if an Issue was Moved. !24470
+- Redeploy Auto DevOps deployment on variable updates. !24498 (walkafwalka)
+- Don't create new merge request pipeline without commits. !24503 (Hiroyuki Sato)
+- Add GitLab Pages predefined CI variables 'CI_PAGES_DOMAIN' and 'CI_PAGES_URL'. !24504 (Adrian Moisey)
+- Moves domain setting from Auto DevOps to Cluster's page. !24580
+- API allows setting the squash commit message when squashing a merge request. !24784
+- Added ability to upgrade cluster applications. !24789
+- Add argument iids for issues in GraphQL. !24802
+- Add repositories count to usage ping data. !24823
+- Add support for extensionless pages URLs. !24876
+- Add templates for most popular Pages templates. !24906
+- Introduce Internal API for searching environment names. !24923
+- Allow admins to invalidate markdown texts by setting local markdown version.
+
+### Other (50 changes, 18 of them are from the community)
+
+- Externalize strings from `/app/views/projects/project_members`. !23227 (Tao Wang)
+- Add CSS & JS global flags to represent browser and platform. !24017
+- Fix deprecation: Passing an argument to force an association to reload is now deprecated. !24136 (Jasper Maes)
+- Cleanup legacy artifact background migration. !24144
+- Bump kubectl in Auto DevOps to 1.11.6. !24176
+- Conditionally initialize the global opentracing tracer. !24186
+- Remove horizontal whitespace on user profile overview on small breakpoints. !24189
+- Bump nginx-ingress chart to 1.1.2. !24203
+- Use monospace font for registry table tag id and tag name. !24205
+- Rename project tags to project topics. !24219
+- Add uniqueness validation to url column in Releases::Link model. !24223
+- Update sidekiq-cron to 1.0.4 and use fugit to replace rufus-scheduler to parse cron syntax. !24235
+- Adds inter-service OpenTracing propagation. !24239
+- Fixes Auto DevOps title on CI/CD admin settings. !24249
+- Upgrade kubeclient to 4.2.2 and swap out monkey-patch to disallow redirects. !24284
+- i18n: externalize strings from 'app/views/search'. !24297 (Tao Wang)
+- Fix several ActionController::Parameters deprecations. !24332 (Jasper Maes)
+- Remove all `$theme-gray-{weight}` variables in favor of `$gray-{weight}`. !24333 (George Tsiolis)
+- Update gitlab-styles to 2.5.1. !24336 (Jasper Maes)
+- Modifies environment scope UI on cluster page. !24376
+- Extract process_name from GitLab::Sentry. !24422
+- Upgrade Gitaly to 1.13.0. !24429
+- Actually set raise_on_unfiltered_parameters to true. !24443 (Jasper Maes)
+- Refactored NoteableDiscussion by extracting ResolveDiscussionButton. !24505 (Martin Hobert)
+- Extracted JumpToNextDiscussionButton to its own component. !24506 (Martin Hobert)
+- Extracted ReplyPlaceholder to its own component. !24507 (Martin Hobert)
+- Block emojis and symbol characters from users full names. !24523
+- Update GitLab Runner Helm Chart to 0.1.45. !24564
+- Updated docs for fields in pushing mirror from GitLab to GitHub. !24566 (Joseph Yu)
+- Upgrade gitlab-workhorse to 8.1.0. !24571
+- Externalize strings from `/app/views/sent_notifications`. !24576 (George Tsiolis)
+- Adds tracing support for ActiveRecord notifications. !24604
+- Externalize strings from `/app/views/projects/ci`. !24617 (George Tsiolis)
+- Move permission check of manual actions of deployments. !24660
+- Externalize strings from `/app/views/clusters`. !24666 (George Tsiolis)
+- Update UI for admin appearance settings. !24685
+- Externalize strings from `/app/views/projects/pages_domains`. !24723 (George Tsiolis)
+- Externalize strings from `/app/views/projects/milestones`. !24726 (George Tsiolis)
+- Add OpenTracing instrumentation for Action View Render events. !24728
+- Expose version for each application in cluster_status JSON endpoint. !24791
+- Externalize strings from `/app/views/instance_statistics`. !24809 (George Tsiolis)
+- Update cluster application version on updated and installed status. !24810
+- Project list UI improvements. !24855
+- Externalize strings from `/app/views/email_rejection_mailer`. !24869 (George Tsiolis)
+- Update Gitaly to v1.17.0. !24873
+- Update Workhorse to v8.3.0. !24959
+- Upgrade gitaly to 1.18.0. !24981
+- Update Workhorse to v8.3.1.
+- Upgraded Codesandbox smooshpack package.
+- Creates mixin to reduce code duplication between CE and EE in graph component.
+
+
+## 11.7.5 (2019-02-06)
+
+### Fixed (8 changes)
+
+- Fix import handling errors in Bitbucket Server importer. !24499
+- Adjusts suggestions unable to be applied. !24603
+- Fix 500 errors with legacy appearance logos. !24615
+- Fix form functionality for edit tag page. !24645
+- Update Workhorse to v8.0.2. !24870
+- Downcase aliased OAuth2 callback providers. !24877
+- Fix Detect Host Keys not working. !24884
+- Changed external wiki query method to prevent attribute caching. !24907
+
+
+## 11.7.2 (2019-01-29)
+
+### Fixed (1 change)
+
+- Fix uninitialized constant with GitLab Pages.
+
+
+## 11.7.1 (2019-01-28)
+
+### Security (24 changes)
+
+- Make potentially malicious links more visible in the UI and scrub RTLO chars from links. !2770
+- Don't process MR refs for guests in the notes. !2771
+- Sanitize user full name to clean up any URL to prevent mail clients from auto-linking URLs. !2828
+- Fixed XSS content in KaTex links.
+- Disallows unauthorized users from accessing the pipelines section.
+- Verify that LFS upload requests are genuine.
+- Extract GitLab Pages using RubyZip.
+- Prevent awarding emojis to notes whose parent is not visible to user.
+- Prevent unauthorized replies when discussion is locked or confidential.
+- Disable git v2 protocol temporarily.
+- Fix showing ci status for guest users when public pipline are not set.
+- Fix contributed projects info still visible when user enable private profile.
+- Add subresources removal to member destroy service.
+- Add more LFS validations to prevent forgery.
+- Use common error for unauthenticated users when creating issues.
+- Fix slow regex in project reference pattern.
+- Fix private user email being visible in push (and tag push) webhooks.
+- Fix wiki access rights when external wiki is enabled.
+- Group guests are no longer able to see merge requests they don't have access to at group level.
+- Fix path disclosure on project import error.
+- Restrict project import visibility based on its group.
+- Expose CI/CD trigger token only to the trigger owner.
+- Notify only users who can access the project on project move.
+- Alias GitHub and BitBucket OAuth2 callback URLs.
+
+
+## 11.7.0 (2019-01-22)
+
+### Security (14 changes, 1 of them is from the community)
+
+- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2693
+- Bump Ruby on Rails to 5.0.7.1. !23396 (@blackst0ne)
+- Delete confidential todos for user when downgraded to Guest.
+- Project guests no longer are able to see refs page.
+- Set URL rel attribute for broken URLs.
+- Prevent leaking protected variables for ambiguous refs.
+- Authorize before reading job information via API.
+- Allow changing group CI/CD settings only for owners.
+- Fix SSRF with import_url and remote mirror url.
+- Don't expose cross project repositories through diffs when creating merge reqeusts.
+- Validate bundle files before unpacking them.
+- Issuable no longer is visible to users when project can't be viewed.
+- Escape html entities in LabelReferenceFilter when no label found.
+- Prevent private snippets from being embeddable.
+
+### Removed (3 changes, 1 of them is from the community)
+
+- Removes all instances of deprecated Gitlab Upgrader calls. !23603 (@jwolen)
+- Removed discard draft comment button form notes. !24185
+- Remove migration to backfill project_repositories for legacy storage projects. !24299
+
+### Fixed (42 changes, 7 of them are from the community)
+
+- Prevent awards emoji being updated when updating status. !23470
+- Allow merge after rebase without page refresh on FF repositories. !23572
+- Prevent admins from attempting hashed storage migration on read only DB. !23597
+- Correct the ordering of metrics on the performance dashboard. !23630
+- Display empty files properly on MR diffs. !23671 (Sean Nichols)
+- Allow GitHub imports via token even if OAuth2 provider not configured. !23703
+- Update header navigation theme colors. !23734 (George Tsiolis)
+- Fix login box bottom margins on signin page. !23739 (@gear54)
+- Return an ApplicationSetting in CurrentSettings. !23766
+- Fix bug commenting on LFS images. !23812
+- Only prompt user once when navigating away from file editor. !23820 (Sam Bigelow)
+- Display commit ID for discussions made on merge request commits. !23837
+- Stop autofocusing on diff comment after initial mount. !23849
+- Fix object storage not working properly with Google S3 compatibility. !23858
+- Fix project calendar feed when sorted by priority. !23870
+- Fix edit button disappearing in issue title. !23948 (Ruben Moya)
+- Aligns build loader animation with the job log. !23959
+- Allow 'rake gitlab:cleanup:remote_upload_files' to read bucket files without having permissions to see all buckets. !23981
+- Correctly externalize pipeline tags. !24028
+- Fix error when creating labels in a new issue in the boards page. !24039 (Ruben Moya)
+- Use 'parsePikadayDate' to parse due date string. !24045
+- Fix commit SHA not showing in merge request compare dropdown. !24084
+- Remove top margin in modal header titles. !24108
+- Drop Webhooks from project import/export config. !24121
+- Only validate project visibility when it has changed. !24142
+- Resolve About this feature link should open in new window. !24149
+- Add syntax highlighting to suggestion diff. !24156
+- Fix Bitbucket Server import only including first 25 pull requests. !24178
+- Enable caching for records which primary key is not `id`. !24245
+- Adjust applied suggestion reverting previous changes. !24250
+- Fix unexpected exception by failure of finding an actual head pipeline. !24257
+- Fix broken templated "Too many changes to show" text. !24282
+- Fix requests profiler in admin page not rendering HTML properly. !24291
+- Fix no avatar not showing in user selection box. !24346
+- Upgrade to gitaly 1.12.1. !24361
+- Fix runner eternal loop when update job result. !24481
+- Fix notification email for image diff notes.
+- Fixed merge request diffs empty states.
+- Fixed diff suggestions removing dashes.
+- Don't hide CI dropdown behind diff summary. (gfyoung)
+- Fix spacing on discussions.
+- Fixes missing margin in releases block.
+
+### Changed (22 changes, 8 of them are from the community)
+
+- Show clusters of ancestors in cluster list page. !22996
+- Remove unnecessary line before reply holder. !23092 (George Tsiolis)
+- Make the Pages permission setting more clear. !23146
+- Disable merging of labels with same names. !23265
+- Allow basic authentication on go get middleware. !23497 (Morty Choi @mortyccp)
+- No longer require email subaddressing for issue creation by email. !23523
+- Adjust padding of .dropdown-title to comply with design specs. !23546
+- Make commit IDs in merge request discussion header monospace. !23562
+- Update environments breadcrumb. !23751 (George Tsiolis)
+- Add date range in milestone change email notifications. !23762
+- Require Knative to be installed only on an RBAC kubernetes cluster. !23807 (Chris Baumbauer)
+- Fix label and header styles in the job details sidebar. !23816 (Nathan Friend)
+- Add % prefix to milestone reference links. !23928
+- Reorder sidebar menu item for group clusters. !24001 (George Tsiolis)
+- Support CURD operation for Links as one of the Release assets. !24056
+- Upgrade Omniauth and JWT gems to switch away from Google+ API. !24068
+- Renames Milestone sort into Milestone due date. !24080 (Jacopo Beschi @jacopo-beschi)
+- Discussion filter only displayed in discussions tab for merge requests. !24082
+- Make RBAC enabled default for new clusters. !24119
+- Hashed Storage: Only set as `read_only` when starting the per-project migration. !24128
+- Knative version bump 0.1.3 -> 0.2.2. (Chris Baumbauer)
+- Show message on non-diff discussions.
+
+### Performance (7 changes)
+
+- Fix some N+1 queries related to Admin Dashboard, User Dashboards and Activity Stream. !23034
+- Add indexes to speed up CI query. !23188
+- Improve the loading time on merge request's discussion page by caching diff highlight. !23857
+- Cache avatar URLs and paths within a request. !23950
+- Improve snippet search performance by removing duplicate counts. !23952
+- Skip per-commit validations already evaluated. !23984
+- Fix timeout issues retrieving branches via API. !24034
+
+### Added (29 changes, 6 of them are from the community)
+
+- Handle ci.skip push option. !15643 (Jonathon Reinhart)
+- Add NGINX 0.16.0 and above metrics. !22133
+- Add project milestone link. !22552
+- Support tls communication in gitaly. !22602
+- Add option to make ci variables protected by default. !22744 (Alexis Reigel)
+- Add project identifier as List-Id email Header to ease filtering. !22817 (Olivier Crête)
+- Add markdown helper buttons to file editor. !23480
+- Allow to include templates in gitlab-ci.yml. !23495
+- Extend override check to also check arity. !23498 (Jacopo Beschi @jacopo-beschi)
+- Add importing of issues from CSV file. !23532
+- Add submit feedback link to help dropdown. !23547
+- Send a notification email to project maintainers when a mirror update fails. !23595
+- Restore Object Pools when restoring an object pool. !23682
+- Creates component for release block. !23697
+- Configure Auto DevOps deployed applications with secrets from prefixed CI variables. !23719
+- Add name, author_id, and sha to releases table. !23763
+- Display a list of Sentry Issues in GitLab. !23770
+- Releases API. !23795
+- Creates frontend app for releases. !23796
+- Add new pipeline variable CI_COMMIT_SHORT_SHA. !23822
+- Create system notes on issue / MR creation when labels, milestone, or due date is set. !23859
+- Adds API documentation for releases. !23901
+- Add API Support for Kubernetes integration. !23922
+- Expose CI/CD predefined variable `CI_API_V4_URL`. !23936
+- Add Knative metrics to Prometheus. !23972 (Chris Baumbauer)
+- Use reports syntax for Dependency scanning in Auto DevOps. !24081
+- Allow to include files from another projects in gitlab-ci.yml. !24101
+- User Popovers for Commit Infos, Member Lists and Snippets. !24132
+- Add no-color theme for syntax highlighting. (khm)
+
+### Other (45 changes, 30 of them are from the community)
+
+- Redesign project lists UI. !22682
+- [Rails5.1] Update functional specs to use new keyword format. !23095 (@blackst0ne)
+- Update a condition to visibility a merge request collaboration message. !23104 (Harry Kiselev)
+- Remove framework/mobile.scss. !23301 (Takuya Noguchi)
+- Passing the separator argument as a positional parameter is deprecated. !23334 (Jasper Maes)
+- Clarifies docs about CI `allow_failure`. !23367 (C.J. Jameson)
+- Refactor issuable sidebar to use serializer. !23379
+- Refactor the logic of updating head pipelines for merge requests. !23502
+- Allow user to add Kubernetes cluster for clusterable when there are ancestor clusters. !23569
+- Adds explanatory text to input fields on user profile settings page. !23673
+- Externalize strings from `/app/views/shared/notes`. !23696 (Tao Wang)
+- Remove rails 4 support in CI, Gemfiles, bin/ and config/. !23717 (Jasper Maes)
+- Fix calendar events fetching error on private profile page. !23718 (Harry Kiselev)
+- Update GitLab Workhorse to v8.0.0. !23740
+- Hide confidential events in the API. !23746
+- Changed Userpopover Fixtures and shadow color. !23768
+- Fix deprecation: Passing conditions to delete_all is deprecated. !23817 (Jasper Maes)
+- Fix deprecation: Passing ActiveRecord::Base objects to sanitize_sql_hash_for_assignment. !23818 (Jasper Maes)
+- Remove rails4 specific code. !23847 (Jasper Maes)
+- Remove deprecated ActionDispatch::ParamsParser. !23848 (Jasper Maes)
+- Fix deprecation: Comparing equality between ActionController::Parameters and a Hash is deprecated. !23855 (Jasper Maes)
+- Fix deprecation: Directly inheriting from ActiveRecord::Migration is deprecated. !23884 (Jasper Maes)
+- Fix deprecation: alias_method_chain is deprecated. Please, use Module#prepend instead. !23887 (Jasper Maes)
+- Update specs to exclude possible false positive pass. !23893 (@blackst0ne)
+- Passing an argument to force an association to reload is now deprecated. !23894 (Jasper Maes)
+- ActiveRecord::Migration -> ActiveRecord::Migration[5.0]. !23910 (Jasper Maes)
+- Split bio into individual line in extended user tooltips. !23940
+- Fix deprecation: redirect_to :back is deprecated. !23943 (Jasper Maes)
+- Fix deprecation: insert_sql is deprecated and will be removed. !23944 (Jasper Maes)
+- Upgrade @gitlab/ui to 1.16.2. !23946
+- convert specs in javascripts/ and support/ to new syntax. !23947 (Jasper Maes)
+- Remove deprecated xhr from specs. !23949 (Jasper Maes)
+- Remove app/views/shared/issuable/_filter.html.haml. !24008 (Takuya Noguchi)
+- Fix deprecation: Using positional arguments in integration tests. !24009 (Jasper Maes)
+- UI improvements for redesigned project lists. !24011
+- Update cert-manager chart from v0.5.0 to v0.5.2. !24025 (Takuya Noguchi)
+- Hide spinner on empty activites list on user profile overview. !24063
+- Don't show Auto DevOps enabled banner for projects with CI file or CI disabled. !24067
+- Update GitLab Runner Helm Chart to 0.1.43. !24083
+- Fix navigation style in docs. !24090 (Takuya Noguchi)
+- Remove gem install bundler from Docker-based Ruby environments. !24093 (Takuya Noguchi)
+- Fix deprecation: Using positional arguments in integration tests. !24110 (Jasper Maes)
+- Fix deprecation: returning false in Active Record and Active Model callbacks will not implicitly halt a callback chain. !24134 (Jasper Maes)
+- ActiveRecord::Migration -> ActiveRecord::Migration[5.0] for AddIndexesToCiBuildsAndPipelines. !24167 (Jasper Maes)
+- Update url placeholder for the sentry configuration page. !24338
+
+
+## 11.6.10 (2019-02-28)
+
+### Security (21 changes)
+
+- Stop linking to unrecognized package sources. !55518
+- Check snippet attached file to be moved is within designated directory.
+- Fix potential Addressable::URI::InvalidURIError.
+- Do not display impersonated sessions under active sessions and remove ability to revoke session.
+- Display only information visible to current user on the Milestone page.
+- Show only merge requests visible to user on milestone detail page.
+- Disable issue boards API when issues are disabled.
+- Don't show new issue link after move when a user does not have permissions.
+- Fix git clone revealing private repo's presence.
+- Fix blind SSRF in Prometheus integration by checking URL before querying.
+- Check if desired milestone for an issue is available.
+- Don't allow non-members to see private related MRs.
+- Fix arbitrary file read via diffs during import.
+- Display the correct number of MRs a user has access to.
+- Forbid creating discussions for users with restricted access.
+- Do not disclose milestone titles for unauthorized users.
+- Validate session key when authorizing with GCP to create a cluster.
+- Block local URLs for Kubernetes integration.
+- Limit mermaid rendering to 5K characters.
+- Remove the possibility to share a project with a group that a user is not a member of.
+- Fix leaking private repository information in API.
+
+
+## 11.6.8 (2019-01-30)
+
+- No changes.
+
+## 11.6.5 (2019-01-17)
+
+### Fixed (5 changes)
+
+- Add syntax highlighting to suggestion diff. !24156
+- Fix broken templated "Too many changes to show" text. !24282
+- Fix requests profiler in admin page not rendering HTML properly. !24291
+- Fix no avatar not showing in user selection box. !24346
+- Fixed diff suggestions removing dashes.
+
+
+## 11.6.4 (2019-01-15)
+
+### Security (1 change)
+
+- Validate bundle files before unpacking them.
+
+
+## 11.6.3 (2019-01-04)
+
+### Fixed (1 change)
+
+- Fix clone URL not showing if protocol is HTTPS. !24131
+
+
+## 11.6.2 (2019-01-02)
+
+### Fixed (7 changes)
+
+- Hide cluster features that don't work yet with Group Clusters. !23935
+- Fix a 500 error that could occur until all migrations are done. !23939
+- Fix missing Git clone button when protocol restriction setting enabled. !24015
+- Fix clone dropdown parent inheritance issues in HAML. !24029
+- Fix content-disposition in blobs and files API endpoint. !24078
+- Fixed markdown toolbar buttons.
+- Adjust line-height of blame view line numbers.
+
+
+## 11.6.1 (2018-12-28)
+
+### Security (15 changes)
+
+- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740
+- Prevent private snippets from being embeddable.
+- Add subresources removal to member destroy service.
+- Escape html entities in LabelReferenceFilter when no label found.
+- Allow changing group CI/CD settings only for owners.
+- Authorize before reading job information via API.
+- Prevent leaking protected variables for ambiguous refs.
+- Ensure that build token is only used when running.
+- Issuable no longer is visible to users when project can't be viewed.
+- Don't expose cross project repositories through diffs when creating merge reqeusts.
+- Fix SSRF with import_url and remote mirror url.
+- Fix persistent symlink in project import.
+- Set URL rel attribute for broken URLs.
+- Project guests no longer are able to see refs page.
+- Delete confidential todos for user when downgraded to Guest.
+
+### Other (1 change)
+
+- Fix due date test. !23845
+
+
## 11.6.0 (2018-12-22)
### Security (24 changes, 1 of them is from the community)
@@ -279,6 +857,33 @@ entry.
- Enable Rubocop on lib/gitlab. (gfyoung)
+## 11.5.8 (2019-01-28)
+
+### Security (21 changes)
+
+- Make potentially malicious links more visible in the UI and scrub RTLO chars from links. !2770
+- Don't process MR refs for guests in the notes. !2771
+- Fixed XSS content in KaTex links.
+- Verify that LFS upload requests are genuine.
+- Extract GitLab Pages using RubyZip.
+- Prevent awarding emojis to notes whose parent is not visible to user.
+- Prevent unauthorized replies when discussion is locked or confidential.
+- Disable git v2 protocol temporarily.
+- Fix showing ci status for guest users when public pipline are not set.
+- Fix contributed projects info still visible when user enable private profile.
+- Disallows unauthorized users from accessing the pipelines section.
+- Add more LFS validations to prevent forgery.
+- Use common error for unauthenticated users when creating issues.
+- Fix slow regex in project reference pattern.
+- Fix private user email being visible in push (and tag push) webhooks.
+- Fix wiki access rights when external wiki is enabled.
+- Fix path disclosure on project import error.
+- Restrict project import visibility based on its group.
+- Expose CI/CD trigger token only to the trigger owner.
+- Notify only users who can access the project on project move.
+- Alias GitHub and BitBucket OAuth2 callback URLs.
+
+
## 11.5.5 (2018-12-20)
### Security (1 change)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4304f6c8744..97dbe2f512b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -15,48 +15,6 @@ repository is licensed under Creative Commons:
_This notice should stay as the first item in the CONTRIBUTING.md file._
----
-
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Contributing Documentation has been moved](#contributing-documentation-has-been-moved)
-- [Contribute to GitLab](#contribute-to-gitlab)
-- [Security vulnerability disclosure](#security-vulnerability-disclosure)
-- [Code of conduct](#code-of-conduct)
-- [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests)
-- [Helping others](#helping-others)
-- [I want to contribute!](#i-want-to-contribute)
-- [Contribution Flow](#contribution-flow)
-- [Workflow labels](#workflow-labels)
- - [Type labels](#type-labels)
- - [Subject labels](#subject-labels)
- - [Team labels](#team-labels)
- - [Release Scoping labels](#release-scoping-labels)
- - [Priority labels](#priority-labels)
- - [Severity labels](#severity-labels)
- - [Severity impact guidance](#severity-impact-guidance)
- - [Label for community contributors](#label-for-community-contributors)
-- [Implement design & UI elements](#implement-design--ui-elements)
-- [Issue tracker](#issue-tracker)
- - [Issue triaging](#issue-triaging)
- - [Feature proposals](#feature-proposals)
- - [Issue tracker guidelines](#issue-tracker-guidelines)
- - [Issue weight](#issue-weight)
- - [Regression issues](#regression-issues)
- - [Technical and UX debt](#technical-and-ux-debt)
- - [Stewardship](#stewardship)
-- [Merge requests](#merge-requests)
- - [Merge request guidelines](#merge-request-guidelines)
- - [Contribution acceptance criteria](#contribution-acceptance-criteria)
-- [Definition of done](#definition-of-done)
-- [Style guides](#style-guides)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
----
-
## Contributing Documentation has been moved
As of July 2018, all the documentation for contributing to the GitLab project has been moved to a new location.
@@ -92,7 +50,7 @@ This [documentation](doc/development/contributing/index.md) has been moved.
## Workflow labels
-This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
+This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
### Type labels
@@ -170,7 +128,6 @@ This [documentation](doc/development/contributing/merge_request_workflow.md) has
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
-
### Contribution acceptance criteria
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
diff --git a/Dangerfile b/Dangerfile
index 6a2c5cf2773..715a2bcbbae 100644
--- a/Dangerfile
+++ b/Dangerfile
@@ -11,3 +11,4 @@ danger.import_dangerfile(path: 'danger/commit_messages')
danger.import_dangerfile(path: 'danger/duplicate_yarn_dependencies')
danger.import_dangerfile(path: 'danger/prettier')
danger.import_dangerfile(path: 'danger/eslint')
+danger.import_dangerfile(path: 'danger/roulette')
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 0eed1a29efd..53cc1a6f929 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-1.12.0
+1.24.0
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 3a3cd8cc8b0..bc80560fad6 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.3.1
+1.5.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 016dac34bf9..d139a75408e 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-8.4.3
+8.7.1
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index ae9a76b9249..56b6be4ebb2 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-8.0.0
+8.3.1
diff --git a/Gemfile b/Gemfile
index 5ddd1f614f1..2e465f8ced7 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,6 @@
source 'https://rubygems.org'
-gem 'rails', '5.0.7'
+gem 'rails', '5.0.7.1'
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
# Improves copy-on-write performance for MRI
@@ -16,7 +16,7 @@ gem 'gitlab-default_value_for', '~> 3.1.1', require: 'default_value_for'
# Supported DBs
gem 'mysql2', '~> 0.4.10', group: :mysql
-gem 'pg', '~> 0.18.2', group: :postgres
+gem 'pg', '~> 1.1', group: :postgres
gem 'rugged', '~> 0.27'
gem 'grape-path-helpers', '~> 1.0'
@@ -34,7 +34,7 @@ gem 'omniauth-cas3', '~> 1.1.4'
gem 'omniauth-facebook', '~> 4.0.0'
gem 'omniauth-github', '~> 1.3'
gem 'omniauth-gitlab', '~> 1.0.2'
-gem 'omniauth-google-oauth2', '~> 0.5.3'
+gem 'omniauth-google-oauth2', '~> 0.6.0'
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
gem 'omniauth-oauth2-generic', '~> 0.2.2'
gem 'omniauth-saml', '~> 1.10'
@@ -43,7 +43,7 @@ gem 'omniauth-twitter', '~> 1.4'
gem 'omniauth_crowd', '~> 2.2.0'
gem 'omniauth-authentiq', '~> 0.3.3'
gem 'rack-oauth2', '~> 1.2.1'
-gem 'jwt', '~> 1.5.6'
+gem 'jwt', '~> 2.1.0'
# Spam and anti-bot protection
gem 'recaptcha', '~> 3.0', require: 'recaptcha/rails'
@@ -57,6 +57,7 @@ gem 'u2f', '~> 0.2.1'
# GitLab Pages
gem 'validates_hostname', '~> 1.0.6'
+gem 'rubyzip', '~> 1.2.2', require: 'zip'
# Browser detection
gem 'browser', '~> 2.5'
@@ -67,7 +68,7 @@ gem 'gpgme', '~> 2.0.18'
# LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
-gem 'gitlab_omniauth-ldap', '~> 2.0.4', require: 'omniauth-ldap'
+gem 'gitlab_omniauth-ldap', '~> 2.1.1', require: 'omniauth-ldap'
gem 'net-ldap'
# API
@@ -89,20 +90,19 @@ gem 'kaminari', '~> 1.0'
gem 'hamlit', '~> 2.8.8'
# Files attachments
-# Locked until https://github.com/carrierwaveuploader/carrierwave/pull/2332 and
-# https://github.com/carrierwaveuploader/carrierwave/pull/2356 are merged.
-# config/initializers/carrierwave_patch.rb can be removed once both changes are released.
-gem 'carrierwave', '= 1.2.3'
+gem 'carrierwave', '~> 1.3'
gem 'mini_magick'
# for backups
-gem 'fog-aws', '~> 2.0.1'
-gem 'fog-core', '~> 1.44'
-gem 'fog-google', '~> 1.7.1'
-gem 'fog-local', '~> 0.3'
-gem 'fog-openstack', '~> 0.1'
+gem 'fog-aws', '~> 3.3'
+# Locked until fog-google resolves https://github.com/fog/fog-google/issues/421.
+# Also see config/initializers/fog_core_patch.rb.
+gem 'fog-core', '= 2.1.0'
+gem 'fog-google', '~> 1.8'
+gem 'fog-local', '~> 0.6'
+gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1'
-gem 'fog-aliyun', '~> 0.2.0'
+gem 'fog-aliyun', '~> 0.3'
# for Google storage
gem 'google-api-client', '~> 0.23'
@@ -115,10 +115,9 @@ gem 'seed-fu', '~> 2.3.7'
# Markdown and HTML processing
gem 'html-pipeline', '~> 2.8'
-gem 'deckar01-task_list', '2.0.0'
+gem 'deckar01-task_list', '2.2.0'
gem 'gitlab-markup', '~> 1.6.5'
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
-gem 'redcarpet', '~> 3.4'
gem 'commonmarker', '~> 0.17'
gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~> 6.0'
@@ -128,9 +127,9 @@ gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.8'
gem 'asciidoctor-plantuml', '0.0.8'
gem 'rouge', '~> 3.1'
-gem 'truncato', '~> 0.7.9'
+gem 'truncato', '~> 0.7.11'
gem 'bootstrap_form', '~> 2.7.0'
-gem 'nokogiri', '~> 1.8.4'
+gem 'nokogiri', '~> 1.10.1'
gem 'escape_utils', '~> 1.1'
# Calendar rendering
@@ -146,7 +145,7 @@ gem 'diffy', '~> 3.1.0'
gem 'rack', '2.0.6'
group :unicorn do
- gem 'unicorn', '~> 5.1.0'
+ gem 'unicorn', '~> 5.4.1'
gem 'unicorn-worker-killer', '~> 0.4.4'
end
@@ -163,12 +162,12 @@ gem 'acts-as-taggable-on', '~> 5.0'
# Background jobs
gem 'sidekiq', '~> 5.2.1'
-gem 'sidekiq-cron', '~> 0.6.0'
+gem 'sidekiq-cron', '~> 1.0'
gem 'redis-namespace', '~> 1.6.0'
gem 'gitlab-sidekiq-fetcher', '~> 0.4.0', require: 'sidekiq-reliable-fetch'
# Cron Parser
-gem 'rufus-scheduler', '~> 3.4'
+gem 'fugit', '~> 1.1'
# HTTP requests
gem 'httparty', '~> 0.13.3'
@@ -187,10 +186,10 @@ gem 're2', '~> 1.1.1'
# Misc
-gem 'version_sorter', '~> 2.1.0'
+gem 'version_sorter', '~> 2.2.4'
# Export Ruby Regex to Javascript
-gem 'js_regex', '~> 2.2.1'
+gem 'js_regex', '~> 3.1'
# User agent parsing
gem 'device_detector'
@@ -205,9 +204,6 @@ gem 'connection_pool', '~> 2.0'
# Discord integration
gem 'discordrb-webhooks-blackst0ne', '~> 3.3', require: false
-# HipChat integration
-gem 'hipchat', '~> 1.5.0'
-
# JIRA integration
gem 'jira-ruby', '~> 1.4'
@@ -227,7 +223,7 @@ gem 'asana', '~> 0.8.1'
gem 'ruby-fogbugz', '~> 0.2.1'
# Kubernetes integration
-gem 'kubeclient', '~> 4.0.0'
+gem 'kubeclient', '~> 4.2.2'
# Sanitize user input
gem 'sanitize', '~> 4.6'
@@ -307,6 +303,12 @@ group :metrics do
gem 'raindrops', '~> 0.18'
end
+group :tracing do
+ # OpenTracing
+ gem 'opentracing', '~> 0.4.3'
+ gem 'jaeger-client', '~> 0.10.0'
+end
+
group :development do
gem 'foreman', '~> 0.84.0'
gem 'brakeman', '~> 4.2', require: false
@@ -323,15 +325,15 @@ group :development do
end
group :development, :test do
- gem 'bootsnap', '~> 1.3'
+ gem 'bootsnap', '~> 1.4'
gem 'bullet', '~> 5.5.0', require: !!ENV['ENABLE_BULLET']
- gem 'pry-byebug', '~> 3.4.1', platform: :mri
+ gem 'pry-byebug', '~> 3.5.1', platform: :mri
gem 'pry-rails', '~> 0.3.4'
gem 'awesome_print', require: false
gem 'fuubar', '~> 2.2.0'
- gem 'database_cleaner', '~> 1.5.0'
+ gem 'database_cleaner', '~> 1.7.0'
gem 'factory_bot_rails', '~> 4.8.2'
gem 'rspec-rails', '~> 3.7.0'
gem 'rspec-retry', '~> 0.4.5'
@@ -340,13 +342,13 @@ group :development, :test do
gem 'rspec-parameterized', require: false
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
- gem 'minitest', '~> 5.7.0'
+ gem 'minitest', '~> 5.11.0'
# Generate Fake data
gem 'ffaker', '~> 2.10'
- gem 'capybara', '~> 2.15'
- gem 'capybara-screenshot', '~> 1.0.0'
+ gem 'capybara', '~> 2.16.1'
+ gem 'capybara-screenshot', '~> 1.0.18'
gem 'selenium-webdriver', '~> 3.12'
gem 'spring', '~> 2.0.0'
@@ -380,7 +382,7 @@ group :test do
gem 'shoulda-matchers', '~> 3.1.2', require: false
gem 'email_spec', '~> 2.2.0'
gem 'json-schema', '~> 2.8.0'
- gem 'webmock', '~> 2.3.2'
+ gem 'webmock', '~> 3.5.1'
gem 'rails-controller-testing'
gem 'sham_rack', '~> 1.3.6'
gem 'concurrent-ruby', '~> 1.1'
@@ -410,7 +412,7 @@ gem 'sys-filesystem', '~> 1.1.6'
# SSH host key support
gem 'net-ssh', '~> 5.0'
-gem 'sshkey', '~> 1.9.0'
+gem 'sshkey', '~> 2.0'
# Required for ED25519 SSH host key support
group :ed25519 do
@@ -419,7 +421,8 @@ group :ed25519 do
end
# Gitaly GRPC client
-gem 'gitaly-proto', '~> 1.5.0', require: 'gitaly'
+gem 'gitaly-proto', '~> 1.13.0', require: 'gitaly'
+
gem 'grpc', '~> 1.15.0'
gem 'google-protobuf', '~> 3.6'
diff --git a/Gemfile.lock b/Gemfile.lock
index f2d265d835c..4d37075cdfa 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -4,41 +4,41 @@ GEM
RedCloth (4.3.2)
abstract_type (0.0.7)
ace-rails-ap (4.1.2)
- actioncable (5.0.7)
- actionpack (= 5.0.7)
+ actioncable (5.0.7.1)
+ actionpack (= 5.0.7.1)
nio4r (>= 1.2, < 3.0)
websocket-driver (~> 0.6.1)
- actionmailer (5.0.7)
- actionpack (= 5.0.7)
- actionview (= 5.0.7)
- activejob (= 5.0.7)
+ actionmailer (5.0.7.1)
+ actionpack (= 5.0.7.1)
+ actionview (= 5.0.7.1)
+ activejob (= 5.0.7.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (5.0.7)
- actionview (= 5.0.7)
- activesupport (= 5.0.7)
+ actionpack (5.0.7.1)
+ actionview (= 5.0.7.1)
+ activesupport (= 5.0.7.1)
rack (~> 2.0)
rack-test (~> 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (5.0.7)
- activesupport (= 5.0.7)
+ actionview (5.0.7.1)
+ activesupport (= 5.0.7.1)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
- activejob (5.0.7)
- activesupport (= 5.0.7)
+ activejob (5.0.7.1)
+ activesupport (= 5.0.7.1)
globalid (>= 0.3.6)
- activemodel (5.0.7)
- activesupport (= 5.0.7)
- activerecord (5.0.7)
- activemodel (= 5.0.7)
- activesupport (= 5.0.7)
+ activemodel (5.0.7.1)
+ activesupport (= 5.0.7.1)
+ activerecord (5.0.7.1)
+ activemodel (= 5.0.7.1)
+ activesupport (= 5.0.7.1)
arel (~> 7.0)
activerecord_sane_schema_dumper (1.0)
rails (>= 5, < 6)
- activesupport (5.0.7)
+ activesupport (5.0.7.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@@ -85,7 +85,7 @@ GEM
binding_ninja (0.2.2)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
- bootsnap (1.3.2)
+ bootsnap (1.4.1)
msgpack (~> 1.0)
bootstrap_form (2.7.0)
brakeman (4.2.1)
@@ -97,22 +97,23 @@ GEM
bundler-audit (0.5.0)
bundler (~> 1.2)
thor (~> 0.18)
- byebug (9.0.6)
- capybara (2.15.1)
+ byebug (9.1.0)
+ capybara (2.16.1)
addressable
mini_mime (>= 0.1.3)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
- capybara-screenshot (1.0.14)
- capybara (>= 1.0, < 3)
+ capybara-screenshot (1.0.22)
+ capybara (>= 1.0, < 4)
launchy
- carrierwave (1.2.3)
+ carrierwave (1.3.1)
activemodel (>= 4.0.0)
activesupport (>= 4.0.0)
mime-types (>= 1.16)
cause (0.1)
+ character_set (1.1.2)
charlock_holmes (0.7.6)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
@@ -140,10 +141,10 @@ GEM
css_parser (1.5.0)
addressable
daemons (1.2.6)
- database_cleaner (1.5.3)
+ database_cleaner (1.7.0)
debug_inspector (0.0.3)
debugger-ruby_core_source (1.3.8)
- deckar01-task_list (2.0.0)
+ deckar01-task_list (2.2.0)
html-pipeline
declarative (0.0.10)
declarative-option (0.1.0)
@@ -185,7 +186,7 @@ GEM
erubi (1.7.1)
erubis (2.7.0)
escape_utils (1.2.1)
- et-orbi (1.0.3)
+ et-orbi (1.1.7)
tzinfo
eventmachine (1.2.7)
excon (0.62.0)
@@ -206,7 +207,7 @@ GEM
fast_blank (1.0.0)
fast_gettext (1.6.0)
ffaker (2.10.0)
- ffi (1.9.25)
+ ffi (1.10.0)
flipper (0.13.0)
flipper-active_record (0.13.0)
activerecord (>= 3.2, < 6)
@@ -217,32 +218,33 @@ GEM
flowdock (0.7.1)
httparty (~> 0.7)
multi_json
- fog-aliyun (0.2.0)
- fog-core (~> 1.27)
- fog-json (~> 1.0)
+ fog-aliyun (0.3.3)
+ fog-core
+ fog-json
ipaddress (~> 0.8)
xml-simple (~> 1.1)
- fog-aws (2.0.1)
- fog-core (~> 1.38)
- fog-json (~> 1.0)
+ fog-aws (3.3.0)
+ fog-core (~> 2.1)
+ fog-json (~> 1.1)
fog-xml (~> 0.1)
ipaddress (~> 0.8)
- fog-core (1.45.0)
+ fog-core (2.1.0)
builder
excon (~> 0.58)
formatador (~> 0.2)
- fog-google (1.7.1)
- fog-core
- fog-json
- fog-xml
+ mime-types
+ fog-google (1.8.2)
+ fog-core (<= 2.1.0)
+ fog-json (~> 1.2)
+ fog-xml (~> 0.1.0)
google-api-client (~> 0.23.0)
- fog-json (1.0.2)
- fog-core (~> 1.0)
+ fog-json (1.2.0)
+ fog-core
multi_json (~> 1.10)
- fog-local (0.3.1)
- fog-core (~> 1.27)
- fog-openstack (0.1.21)
- fog-core (>= 1.40)
+ fog-local (0.6.0)
+ fog-core (>= 1.27, < 3.0)
+ fog-openstack (1.0.8)
+ fog-core (~> 2.1)
fog-json (>= 1.0)
ipaddress (>= 0.8)
fog-rackspace (0.1.1)
@@ -258,6 +260,9 @@ GEM
foreman (0.84.0)
thor (~> 0.19.1)
formatador (0.2.5)
+ fugit (1.1.7)
+ et-orbi (~> 1.1, >= 1.1.7)
+ raabro (~> 1.1)
fuubar (2.2.0)
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
@@ -274,7 +279,7 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
- gitaly-proto (1.5.0)
+ gitaly-proto (1.13.0)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab-default_value_for (3.1.1)
@@ -282,11 +287,11 @@ GEM
gitlab-markup (1.6.5)
gitlab-sidekiq-fetcher (0.4.0)
sidekiq (~> 5)
- gitlab-styles (2.4.1)
+ gitlab-styles (2.5.1)
rubocop (~> 0.54.0)
rubocop-gitlab-security (~> 0.1.0)
rubocop-rspec (~> 1.19)
- gitlab_omniauth-ldap (2.0.4)
+ gitlab_omniauth-ldap (2.1.1)
net-ldap (~> 0.16)
omniauth (~> 1.3)
pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
@@ -305,7 +310,7 @@ GEM
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
google-protobuf (3.6.1)
- googleapis-common-protos-types (1.0.2)
+ googleapis-common-protos-types (1.0.3)
google-protobuf (~> 3.0)
googleauth (0.6.6)
faraday (~> 0.12)
@@ -353,15 +358,12 @@ GEM
thor
tilt
hangouts-chat (0.0.5)
- hashdiff (0.3.4)
+ hashdiff (0.3.8)
hashie (3.5.7)
hashie-forbidden_attributes (0.1.1)
hashie (>= 3.0)
health_check (2.6.0)
rails (>= 4.0)
- hipchat (1.5.2)
- httparty
- mimemagic
html-pipeline (2.8.4)
activesupport (>= 2)
nokogiri (>= 1.4)
@@ -381,7 +383,7 @@ GEM
json (~> 1.8)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (1.1.1)
+ i18n (1.2.0)
concurrent-ruby (~> 1.0)
icalendar (2.4.1)
ice_nine (0.11.2)
@@ -389,13 +391,18 @@ GEM
cause
json
ipaddress (0.8.3)
+ jaeger-client (0.10.0)
+ opentracing (~> 0.3)
+ thrift
jira-ruby (1.4.1)
activesupport
multipart-post
oauth (~> 0.5, >= 0.5.0)
jquery-atwho-rails (1.3.2)
- js_regex (2.2.1)
- regexp_parser (>= 0.4.11, <= 0.5.0)
+ js_regex (3.1.1)
+ character_set (~> 1.1)
+ regexp_parser (~> 1.1)
+ regexp_property_values (~> 0.3)
json (1.8.6)
json-jwt (1.9.4)
activesupport
@@ -403,7 +410,7 @@ GEM
bindata
json-schema (2.8.0)
addressable (>= 2.4)
- jwt (1.5.6)
+ jwt (2.1.0)
kaminari (1.0.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.0.1)
@@ -416,10 +423,10 @@ GEM
activerecord
kaminari-core (= 1.0.1)
kaminari-core (1.0.1)
- kgio (2.10.0)
+ kgio (2.11.2)
knapsack (1.17.0)
rake
- kubeclient (4.0.0)
+ kubeclient (4.2.2)
http (~> 3.0)
recursive-open-struct (~> 1.0, >= 1.0.4)
rest-client (~> 2.0)
@@ -449,7 +456,7 @@ GEM
loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
- mail (2.7.0)
+ mail (2.7.1)
mini_mime (>= 0.1.1)
mail_room (0.9.1)
memoist (0.16.0)
@@ -462,9 +469,9 @@ GEM
mimemagic (0.3.2)
mini_magick (4.8.0)
mini_mime (1.0.1)
- mini_portile2 (2.3.0)
- minitest (5.7.0)
- msgpack (1.2.4)
+ mini_portile2 (2.4.0)
+ minitest (5.11.3)
+ msgpack (1.2.6)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
@@ -477,30 +484,30 @@ GEM
net-ssh (5.0.1)
netrc (0.11.0)
nio4r (2.3.1)
- nokogiri (1.8.5)
- mini_portile2 (~> 2.3.0)
+ nokogiri (1.10.1)
+ mini_portile2 (~> 2.4.0)
nokogumbo (1.5.0)
nokogiri
numerizer (0.1.1)
oauth (0.5.4)
- oauth2 (1.4.0)
- faraday (>= 0.8, < 0.13)
- jwt (~> 1.0)
+ oauth2 (1.4.1)
+ faraday (>= 0.8, < 0.16.0)
+ jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
octokit (4.9.0)
sawyer (~> 0.8.0, >= 0.5.3)
- omniauth (1.8.1)
- hashie (>= 3.4.6, < 3.6.0)
+ omniauth (1.9.0)
+ hashie (>= 3.4.6, < 3.7.0)
rack (>= 1.6.2, < 3)
omniauth-auth0 (2.0.0)
omniauth-oauth2 (~> 1.4)
omniauth-authentiq (0.3.3)
jwt (>= 1.5)
omniauth-oauth2 (>= 1.5)
- omniauth-azure-oauth2 (0.0.9)
- jwt (~> 1.0)
+ omniauth-azure-oauth2 (0.0.10)
+ jwt (>= 1.0, < 3.0)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.4)
omniauth-cas3 (1.1.4)
@@ -515,8 +522,8 @@ GEM
omniauth-gitlab (1.0.3)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0)
- omniauth-google-oauth2 (0.5.3)
- jwt (>= 1.5)
+ omniauth-google-oauth2 (0.6.0)
+ jwt (>= 2.0)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.5)
omniauth-kerberos (0.3.0)
@@ -527,9 +534,9 @@ GEM
omniauth-oauth (1.1.0)
oauth
omniauth (~> 1.0)
- omniauth-oauth2 (1.5.0)
+ omniauth-oauth2 (1.6.0)
oauth2 (~> 1.1)
- omniauth (~> 1.2)
+ omniauth (~> 1.9)
omniauth-oauth2-generic (0.2.2)
omniauth-oauth2 (~> 1.0)
omniauth-saml (1.10.0)
@@ -544,6 +551,8 @@ GEM
activesupport
nokogiri (>= 1.4.4)
omniauth (~> 1.0)
+ opentracing (0.4.3)
+ optimist (3.0.0)
org-ruby (0.9.12)
rubypants (~> 0.2)
orm_adapter (0.5.0)
@@ -575,7 +584,7 @@ GEM
atomic (>= 1.0.0)
peek
redis
- pg (0.18.4)
+ pg (1.1.3)
po_to_json (1.0.1)
json (>= 1.6.0)
powerpack (0.1.1)
@@ -595,8 +604,8 @@ GEM
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
- pry-byebug (3.4.3)
- byebug (>= 9.0, < 9.1)
+ pry-byebug (3.5.1)
+ byebug (~> 9.1)
pry (~> 0.10)
pry-rails (0.3.6)
pry (>= 0.10.4)
@@ -606,6 +615,7 @@ GEM
get_process_mem (~> 0.2)
puma (>= 2.7, < 4)
pyu-ruby-sasl (0.0.3.3)
+ raabro (1.1.6)
rack (2.0.6)
rack-accept (0.4.5)
rack (>= 0.4)
@@ -618,23 +628,23 @@ GEM
httpclient (>= 2.4)
multi_json (>= 1.3.6)
rack (>= 1.1)
- rack-protection (2.0.4)
+ rack-protection (2.0.5)
rack
rack-proxy (0.6.0)
rack
rack-test (0.6.3)
rack (>= 1.0)
- rails (5.0.7)
- actioncable (= 5.0.7)
- actionmailer (= 5.0.7)
- actionpack (= 5.0.7)
- actionview (= 5.0.7)
- activejob (= 5.0.7)
- activemodel (= 5.0.7)
- activerecord (= 5.0.7)
- activesupport (= 5.0.7)
+ rails (5.0.7.1)
+ actioncable (= 5.0.7.1)
+ actionmailer (= 5.0.7.1)
+ actionpack (= 5.0.7.1)
+ actionview (= 5.0.7.1)
+ activejob (= 5.0.7.1)
+ activemodel (= 5.0.7.1)
+ activerecord (= 5.0.7.1)
+ activesupport (= 5.0.7.1)
bundler (>= 1.3.0)
- railties (= 5.0.7)
+ railties (= 5.0.7.1)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.2)
actionpack (~> 5.x, >= 5.0.1)
@@ -650,30 +660,29 @@ GEM
rails-i18n (5.1.1)
i18n (>= 0.7, < 2)
railties (>= 5.0, < 6)
- railties (5.0.7)
- actionpack (= 5.0.7)
- activesupport (= 5.0.7)
+ railties (5.0.7.1)
+ actionpack (= 5.0.7.1)
+ activesupport (= 5.0.7.1)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (3.0.0)
- raindrops (0.18.0)
- rake (12.3.1)
+ raindrops (0.19.0)
+ rake (12.3.2)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rblineprof (0.3.6)
debugger-ruby_core_source (~> 1.3)
- rbtrace (0.4.10)
+ rbtrace (0.4.11)
ffi (>= 1.0.6)
msgpack (>= 0.4.3)
- trollop (>= 1.16.2)
+ optimist (>= 3.0.0)
rdoc (6.0.4)
re2 (1.1.1)
recaptcha (3.0.0)
json
recursive-open-struct (1.1.0)
- redcarpet (3.4.0)
redis (3.3.5)
redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6)
@@ -693,7 +702,8 @@ GEM
redis-store (>= 1.2, < 2)
redis-store (1.6.0)
redis (>= 2.2, < 5)
- regexp_parser (0.5.0)
+ regexp_parser (1.3.0)
+ regexp_property_values (0.3.4)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
@@ -775,8 +785,6 @@ GEM
rubyntlm (0.6.2)
rubypants (0.2.0)
rubyzip (1.2.2)
- rufus-scheduler (3.4.0)
- et-orbi (~> 1.0)
rugged (0.27.5)
safe_yaml (1.0.4)
sanitize (4.6.6)
@@ -816,12 +824,13 @@ GEM
rack
shoulda-matchers (3.1.2)
activesupport (>= 4.0.0)
- sidekiq (5.2.3)
+ sidekiq (5.2.5)
connection_pool (~> 2.2, >= 2.2.2)
+ rack (>= 1.5.0)
rack-protection (>= 1.5.0)
redis (>= 3.3.5, < 5)
- sidekiq-cron (0.6.0)
- rufus-scheduler (>= 3.3.0)
+ sidekiq-cron (1.0.4)
+ fugit (~> 1.1)
sidekiq (>= 4.2.1)
signet (0.11.0)
addressable (~> 2.3)
@@ -847,7 +856,7 @@ GEM
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.13)
- sshkey (1.9.0)
+ sshkey (2.0.0)
stackprof (0.2.10)
state_machines (0.5.0)
state_machines-activemodel (0.5.1)
@@ -868,6 +877,7 @@ GEM
rack (>= 1, < 3)
thor (0.19.4)
thread_safe (0.3.6)
+ thrift (0.11.0.0)
tilt (2.0.8)
timecop (0.8.1)
timfel-krb5-auth (0.8.3)
@@ -875,10 +885,9 @@ GEM
parslet (~> 1.8.0)
toml-rb (1.0.0)
citrus (~> 3.0, > 3.0)
- trollop (2.1.3)
- truncato (0.7.10)
+ truncato (0.7.11)
htmlentities (~> 4.3.1)
- nokogiri (~> 1.8.0, >= 1.7.0)
+ nokogiri (>= 1.7.0, <= 2.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
u2f (0.2.1)
@@ -890,7 +899,7 @@ GEM
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.3.2)
- unicorn (5.1.0)
+ unicorn (5.4.1)
kgio (~> 2.6)
raindrops (~> 0.7)
unicorn-worker-killer (0.4.4)
@@ -908,7 +917,7 @@ GEM
validates_hostname (1.0.6)
activerecord (>= 3.0)
activesupport (>= 3.0)
- version_sorter (2.1.0)
+ version_sorter (2.2.4)
virtus (1.0.5)
axiom-types (~> 0.1)
coercible (~> 1.0)
@@ -917,7 +926,7 @@ GEM
vmstat (2.3.0)
warden (1.2.7)
rack (>= 1.0)
- webmock (2.3.2)
+ webmock (3.5.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
@@ -957,15 +966,15 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0)
better_errors (~> 2.5.0)
binding_of_caller (~> 0.8.0)
- bootsnap (~> 1.3)
+ bootsnap (~> 1.4)
bootstrap_form (~> 2.7.0)
brakeman (~> 4.2)
browser (~> 2.5)
bullet (~> 5.5.0)
bundler-audit (~> 0.5.0)
- capybara (~> 2.15)
- capybara-screenshot (~> 1.0.0)
- carrierwave (= 1.2.3)
+ capybara (~> 2.16.1)
+ capybara-screenshot (~> 1.0.18)
+ carrierwave (~> 1.3)
charlock_holmes (~> 0.7.5)
chronic (~> 0.10.2)
chronic_duration (~> 0.10.6)
@@ -973,8 +982,8 @@ DEPENDENCIES
concurrent-ruby (~> 1.1)
connection_pool (~> 2.0)
creole (~> 0.5.0)
- database_cleaner (~> 1.5.0)
- deckar01-task_list (= 2.0.0)
+ database_cleaner (~> 1.7.0)
+ deckar01-task_list (= 2.2.0)
device_detector
devise (~> 4.4)
devise-two-factor (~> 3.0.0)
@@ -994,27 +1003,28 @@ DEPENDENCIES
flipper-active_record (~> 0.13.0)
flipper-active_support_cache_store (~> 0.13.0)
flowdock (~> 0.7)
- fog-aliyun (~> 0.2.0)
- fog-aws (~> 2.0.1)
- fog-core (~> 1.44)
- fog-google (~> 1.7.1)
- fog-local (~> 0.3)
- fog-openstack (~> 0.1)
+ fog-aliyun (~> 0.3)
+ fog-aws (~> 3.3)
+ fog-core (= 2.1.0)
+ fog-google (~> 1.8)
+ fog-local (~> 0.6)
+ fog-openstack (~> 1.0)
fog-rackspace (~> 0.1.1)
font-awesome-rails (~> 4.7)
foreman (~> 0.84.0)
+ fugit (~> 1.1)
fuubar (~> 2.2.0)
gemojione (~> 3.3)
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly-proto (~> 1.5.0)
+ gitaly-proto (~> 1.13.0)
github-markup (~> 1.7.0)
gitlab-default_value_for (~> 3.1.1)
gitlab-markup (~> 1.6.5)
gitlab-sidekiq-fetcher (~> 0.4.0)
gitlab-styles (~> 2.4)
- gitlab_omniauth-ldap (~> 2.0.4)
+ gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.2)
google-api-client (~> 0.23)
google-protobuf (~> 3.6)
@@ -1031,20 +1041,20 @@ DEPENDENCIES
hangouts-chat (~> 0.0.5)
hashie-forbidden_attributes
health_check (~> 2.6.0)
- hipchat (~> 1.5.0)
html-pipeline (~> 2.8)
html2text
httparty (~> 0.13.3)
icalendar
influxdb (~> 0.2)
+ jaeger-client (~> 0.10.0)
jira-ruby (~> 1.4)
jquery-atwho-rails (~> 1.3.2)
- js_regex (~> 2.2.1)
+ js_regex (~> 3.1)
json-schema (~> 2.8.0)
- jwt (~> 1.5.6)
+ jwt (~> 2.1.0)
kaminari (~> 1.0)
knapsack (~> 1.17)
- kubeclient (~> 4.0.0)
+ kubeclient (~> 4.2.2)
letter_opener_web (~> 1.3.0)
license_finder (~> 5.4)
licensee (~> 8.9)
@@ -1054,12 +1064,12 @@ DEPENDENCIES
method_source (~> 0.8)
mimemagic (~> 0.3.2)
mini_magick
- minitest (~> 5.7.0)
+ minitest (~> 5.11.0)
mysql2 (~> 0.4.10)
nakayoshi_fork (~> 0.0.4)
net-ldap
net-ssh (~> 5.0)
- nokogiri (~> 1.8.4)
+ nokogiri (~> 1.10.1)
oauth2 (~> 1.4)
octokit (~> 4.9)
omniauth (~> 1.8)
@@ -1070,13 +1080,14 @@ DEPENDENCIES
omniauth-facebook (~> 4.0.0)
omniauth-github (~> 1.3)
omniauth-gitlab (~> 1.0.2)
- omniauth-google-oauth2 (~> 0.5.3)
+ omniauth-google-oauth2 (~> 0.6.0)
omniauth-kerberos (~> 0.3.0)
omniauth-oauth2-generic (~> 0.2.2)
omniauth-saml (~> 1.10)
omniauth-shibboleth (~> 1.3.0)
omniauth-twitter (~> 1.4)
omniauth_crowd (~> 2.2.0)
+ opentracing (~> 0.4.3)
org-ruby (~> 0.9.12)
peek (~> 1.0.1)
peek-gc (~> 0.0.2)
@@ -1084,10 +1095,10 @@ DEPENDENCIES
peek-pg (~> 1.3.0)
peek-rblineprof (~> 0.2.0)
peek-redis (~> 1.2.0)
- pg (~> 0.18.2)
+ pg (~> 1.1)
premailer-rails (~> 1.9.7)
prometheus-client-mmap (~> 0.9.4)
- pry-byebug (~> 3.4.1)
+ pry-byebug (~> 3.5.1)
pry-rails (~> 0.3.4)
puma (~> 3.12)
puma_worker_killer
@@ -1096,7 +1107,7 @@ DEPENDENCIES
rack-cors (~> 1.0.0)
rack-oauth2 (~> 1.2.1)
rack-proxy (~> 0.6.0)
- rails (= 5.0.7)
+ rails (= 5.0.7.1)
rails-controller-testing
rails-deprecated_sanitizer (~> 1.0.3)
rails-i18n (~> 5.1)
@@ -1107,7 +1118,6 @@ DEPENDENCIES
rdoc (~> 6.0)
re2 (~> 1.1.1)
recaptcha (~> 3.0)
- redcarpet (~> 3.4)
redis (~> 3.2)
redis-namespace (~> 1.6.0)
redis-rails (~> 5.0.2)
@@ -1127,7 +1137,7 @@ DEPENDENCIES
ruby-prof (~> 0.17.0)
ruby-progressbar
ruby_parser (~> 3.8)
- rufus-scheduler (~> 3.4)
+ rubyzip (~> 1.2.2)
rugged (~> 0.27)
sanitize (~> 4.6)
sass (~> 3.5)
@@ -1141,14 +1151,14 @@ DEPENDENCIES
sham_rack (~> 1.3.6)
shoulda-matchers (~> 3.1.2)
sidekiq (~> 5.2.1)
- sidekiq-cron (~> 0.6.0)
+ sidekiq-cron (~> 1.0)
simple_po_parser (~> 1.1.2)
simplecov (~> 0.14.0)
slack-notifier (~> 1.5.1)
spring (~> 2.0.0)
spring-commands-rspec (~> 1.0.4)
sprockets (~> 3.7.0)
- sshkey (~> 1.9.0)
+ sshkey (~> 2.0)
stackprof (~> 0.2.10)
state_machines-activerecord (~> 0.5.1)
sys-filesystem (~> 1.1.6)
@@ -1156,19 +1166,19 @@ DEPENDENCIES
thin (~> 1.7.0)
timecop (~> 0.8.0)
toml-rb (~> 1.0.0)
- truncato (~> 0.7.9)
+ truncato (~> 0.7.11)
u2f (~> 0.2.1)
uglifier (~> 2.7.2)
unf (~> 0.1.4)
- unicorn (~> 5.1.0)
+ unicorn (~> 5.4.1)
unicorn-worker-killer (~> 0.4.4)
validates_hostname (~> 1.0.6)
- version_sorter (~> 2.1.0)
+ version_sorter (~> 2.2.4)
virtus (~> 1.0.1)
vmstat (~> 2.3.0)
- webmock (~> 2.3.2)
+ webmock (~> 3.5.1)
webpack-rails (~> 0.9.10)
wikicloth (= 0.8.1)
BUNDLED WITH
- 1.17.1
+ 1.17.3
diff --git a/PROCESS.md b/PROCESS.md
index 5aafbd33daf..1f99cebe081 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -56,7 +56,7 @@ Below we describe the contributing process to GitLab for two reasons:
Several people from the [GitLab team][team] are helping community members to get
their contributions accepted by meeting our [Definition of done][done].
-What you can expect from them is described at https://about.gitlab.com/roles/merge-request-coach/.
+What you can expect from them is described at https://about.gitlab.com/job-families/expert/merge-request-coach/.
### Milestones on community contribution issues
@@ -86,10 +86,13 @@ star, smile, etc.). Some good tips about code reviews can be found in our
## Feature freeze on the 7th for the release on the 22nd
-After 7th at 23:59 (Pacific Time Zone) of each month, RC1 of the upcoming
-release (to be shipped on the 22nd) is created and deployed to GitLab.com and
-the stable branch for this release is frozen, which means master is no longer
-merged into it. Merge requests may still be merged into master during this
+After 7th at 23:59 (Pacific Time Zone) of each month, stable branch and RC1
+of the upcoming release (to be shipped on the 22nd) is created and deployed to GitLab.com.
+The stable branch is frozen at the most recent "qualifying commit" on master.
+A "qualifying commit" is one that is pushed before the feature freeze cutoff time
+and that passes all CI jobs (green pipeline).
+
+Merge requests may still be merged into master during this
period, but they will go into the _next_ release, unless they are manually
cherry-picked into the stable branch.
@@ -105,7 +108,19 @@ Merge requests that make changes hidden behind a feature flag, or remove an
existing feature flag because a feature is deemed stable, may be merged (and
picked into the stable branches) up to the 19th of the month. Such merge
requests should have the ~"feature flag" label assigned, and don't require a
-corresponding exception request to be created.
+corresponding exception request to be created.
+
+A level of common sense should be applied when deciding whether to have a feature
+behind a feature flag off or on by default.
+
+The following guideliness can be applied to help make this decision:
+
+* If the feature is not fully ready or functioning, the feature flag should be disabled by default.
+* If the feature is ready but there are concerns about performance or impact, the feature flag should be enabled by default, but
+disabled via chatops before deployment on GitLab.com environments. If the performance concern is confirmed, the final release should have the feature flag disabled by default.
+* In most other cases, the feature flag can be enabled by default.
+
+For more information on rolling out changes using feature flags, read [through the documentation](https://docs.gitlab.com/ee/development/rolling_out_changes_using_feature_flags.html).
In order to build the final package and present the feature for self-hosted
customers, the feature flag should be removed. This should happen before the
@@ -153,8 +168,12 @@ on behalf of the community member.
Every new feature or change should be shipped with its corresponding documentation
in accordance with the
-[documentation process](https://docs.gitlab.com/ee/development/documentation/workflow.html)
-and [structure](https://docs.gitlab.com/ee/development/documentation/structure.html).
+[documentation process](https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html)
+and [structure](https://docs.gitlab.com/ee/development/documentation/structure.html) guides.
+Note that a technical writer will review all changes to documentation. This can occur
+in the same MR as the feature code, but [if there is not sufficient time or need,
+it can be planned via a follow-up issue for doc review](https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html#1-product-managers-role),
+and another MR, if needed. Regardless, complete docs must be merged with code by the freeze.
#### What happens if these deadlines are missed?
@@ -183,8 +202,6 @@ and to prevent any last minute surprises.
Merge requests should still be complete, following the [definition of done][done].
-#### Feature merge requests
-
If a merge request is not ready, but the developers and Product Manager
responsible for the feature think it is essential that it is in the release,
they can [ask for an exception](#asking-for-an-exception) in advance. This is
@@ -199,34 +216,17 @@ information, see
[Automatic CE->EE merge][automatic_ce_ee_merge] and
[Guidelines for implementing Enterprise Edition features][ee_features].
-#### Documentation merge requests
-
-Documentation is part of the product and must be shipped with the feature.
-
-The single exception for the feature freeze is documentation, and it can
-be left to be **merged up to the 14th** if:
-
-* There is a follow-up issue to add documentation.
-* It is assigned to the developer writing documentation for this feature, and they
- are aware of it.
-* It is in the correct milestone, with the labels ~Documentation, ~Deliverable,
-~missed-deliverable, and "pick into X.Y" applied.
-* It must be reviewed and approved by a technical writer.
-
-For more information read the process for
-[documentation shipped late](https://docs.gitlab.com/ee/development/documentation/workflow.html#documentation-shipped-late).
-
### After the 7th
Once the stable branch is frozen, the only MRs that can be cherry-picked into
the stable branch are:
* Fixes for [regressions](#regressions) where the affected version `xx.x` in `regression:xx.x` is the current release. See [Managing bugs](#managing-bugs) section.
-* Fixes for security issues
-* Fixes or improvements to automated QA scenarios
-* [Documentation updates](https://docs.gitlab.com/ee/development/documentation/workflow.html#documentation-shipped-late) for changes in the same release
-* New or updated translations (as long as they do not touch application code)
-* Changes that are behind a feature flag and have the ~"feature flag" label
+* Fixes for security issues.
+* Fixes or improvements to automated QA scenarios.
+* [Documentation improvements](https://docs.gitlab.com/ee/development/documentation/workflow.html) for feature changes made in the same release, though initial docs for these features should have already been merged by the freeze, as required.
+* New or updated translations (as long as they do not touch application code).
+* Changes that are behind a feature flag and have the ~"feature flag" label.
During the feature freeze all merge requests that are meant to go into the
upcoming release should have the correct milestone assigned _and_ the
diff --git a/VERSION b/VERSION
index 74f35bff618..00a946e3be3 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-11.7.0-pre
+11.9.0-pre
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index d1396b6c4bc..8754c253881 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -5,12 +5,14 @@ import axios from './lib/utils/axios_utils';
const Api = {
groupsPath: '/api/:version/groups.json',
groupPath: '/api/:version/groups/:id',
+ groupMembersPath: '/api/:version/groups/:id/members',
subgroupsPath: '/api/:version/groups/:id/subgroups',
namespacesPath: '/api/:version/namespaces.json',
groupProjectsPath: '/api/:version/groups/:id/projects.json',
projectsPath: '/api/:version/projects.json',
projectPath: '/api/:version/projects/:id',
projectLabelsPath: '/:namespace_path/:project_path/labels',
+ projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests',
projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
projectMergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes',
projectMergeRequestVersionsPath: '/api/:version/projects/:id/merge_requests/:mrid/versions',
@@ -40,6 +42,12 @@ const Api = {
});
},
+ groupMembers(id) {
+ const url = Api.buildUrl(this.groupMembersPath).replace(':id', encodeURIComponent(id));
+
+ return axios.get(url);
+ },
+
// Return groups list. Filtered by query
groups(query, options, callback = $.noop) {
const url = Api.buildUrl(Api.groupsPath);
@@ -104,6 +112,22 @@ const Api = {
return axios.get(url);
},
+ /**
+ * Get all Merge Requests for a project, eventually filtering based on
+ * supplied parameters
+ * @param projectPath
+ * @param params
+ * @returns {Promise}
+ */
+ projectMergeRequests(projectPath, params = {}) {
+ const url = Api.buildUrl(Api.projectMergeRequestsPath).replace(
+ ':id',
+ encodeURIComponent(projectPath),
+ );
+
+ return axios.get(url, { params });
+ },
+
// Return Merge Request for project
projectMergeRequest(projectPath, mergeRequestId, params = {}) {
const url = Api.buildUrl(Api.projectMergeRequestPath)
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index cace8bb9dba..aeb88715c11 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -437,7 +437,7 @@ export class AwardsHandler {
createAwardButtonForVotesBlock(votesBlock, emojiName) {
const buttonHtml = `
- <button class="btn award-control js-emoji-btn has-tooltip active" title="You" data-placement="bottom">
+ <button class="btn award-control js-emoji-btn has-tooltip active" title="You">
${this.emoji.glEmojiTag(emojiName)}
<span class="award-control-text js-counter">1</span>
</button>
@@ -615,10 +615,18 @@ export class AwardsHandler {
let awardsHandlerPromise = null;
export default function loadAwardsHandler(reload = false) {
if (!awardsHandlerPromise || reload) {
- awardsHandlerPromise = import(/* webpackChunkName: 'emoji' */ './emoji').then(Emoji => {
- const awardsHandler = new AwardsHandler(Emoji);
- awardsHandler.bindEvents();
- return awardsHandler;
+ awardsHandlerPromise = new Promise((resolve, reject) => {
+ import(/* webpackChunkName: 'emoji' */ './emoji')
+ .then(Emoji => {
+ Emoji.initEmojiMap()
+ .then(() => {
+ const awardsHandler = new AwardsHandler(Emoji);
+ awardsHandler.bindEvents();
+ resolve(awardsHandler);
+ })
+ .catch(() => reject);
+ })
+ .catch(() => reject);
});
}
return awardsHandlerPromise;
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index 85a15b38de1..df74eb2c2f7 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -90,7 +90,7 @@ export default {
},
badgeImageUrlExample() {
const exampleUrl =
- 'https://example.gitlab.com/%{project_path}/badges/%{default_branch}/badge.svg';
+ 'https://example.gitlab.com/%{project_path}/badges/%{default_branch}/pipeline.svg';
return sprintf(s__('Badges|e.g. %{exampleUrl}'), {
exampleUrl,
});
diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue
index 9051be1e102..cad5611c8c5 100644
--- a/app/assets/javascripts/badges/components/badge_list_row.vue
+++ b/app/assets/javascripts/badges/components/badge_list_row.vue
@@ -55,7 +55,7 @@ export default {
:disabled="badge.isDeleting"
class="btn btn-default append-right-8"
type="button"
- @click="editBadge(badge);"
+ @click="editBadge(badge)"
>
<icon :size="16" :aria-label="__('Edit')" name="pencil" />
</button>
@@ -65,7 +65,7 @@ export default {
type="button"
data-toggle="modal"
data-target="#delete-badge-modal"
- @click="updateBadgeInModal(badge);"
+ @click="updateBadgeInModal(badge)"
>
<icon :size="16" :aria-label="__('Delete')" name="remove" />
</button>
diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js
index 56293d5f96f..9034563d9b3 100644
--- a/app/assets/javascripts/behaviors/gl_emoji.js
+++ b/app/assets/javascripts/behaviors/gl_emoji.js
@@ -1,51 +1,79 @@
-import installCustomElements from 'document-register-element';
+import 'document-register-element';
import isEmojiUnicodeSupported from '../emoji/support';
+import { initEmojiMap, getEmojiInfo, emojiFallbackImageSrc, emojiImageTag } from '../emoji';
-installCustomElements(window);
+class GlEmoji extends HTMLElement {
+ constructor() {
+ super();
-export default function installGlEmojiElement() {
- const GlEmojiElementProto = Object.create(HTMLElement.prototype);
- GlEmojiElementProto.createdCallback = function createdCallback() {
- const emojiUnicode = this.textContent.trim();
- const { name, unicodeVersion, fallbackSrc, fallbackSpriteClass } = this.dataset;
-
- const isEmojiUnicode =
- this.childNodes &&
- Array.prototype.every.call(this.childNodes, childNode => childNode.nodeType === 3);
- const hasImageFallback = fallbackSrc && fallbackSrc.length > 0;
- const hasCssSpriteFalback = fallbackSpriteClass && fallbackSpriteClass.length > 0;
-
- if (emojiUnicode && isEmojiUnicode && !isEmojiUnicodeSupported(emojiUnicode, unicodeVersion)) {
- // CSS sprite fallback takes precedence over image fallback
- if (hasCssSpriteFalback) {
- if (!gon.emoji_sprites_css_added && gon.emoji_sprites_css_path) {
- const emojiSpriteLinkTag = document.createElement('link');
- emojiSpriteLinkTag.setAttribute('rel', 'stylesheet');
- emojiSpriteLinkTag.setAttribute('href', gon.emoji_sprites_css_path);
- document.head.appendChild(emojiSpriteLinkTag);
- gon.emoji_sprites_css_added = true;
- }
- // IE 11 doesn't like adding multiple at once :(
- this.classList.add('emoji-icon');
- this.classList.add(fallbackSpriteClass);
- } else {
- import(/* webpackChunkName: 'emoji' */ '../emoji')
- .then(({ emojiImageTag, emojiFallbackImageSrc }) => {
- if (hasImageFallback) {
- this.innerHTML = emojiImageTag(name, fallbackSrc);
+ let emojiUnicode = this.textContent.trim();
+ const { fallbackSpriteClass, fallbackSrc, forceFallback } = this.dataset;
+ let { name, unicodeVersion } = this.dataset;
+
+ initEmojiMap()
+ .then(() => {
+ if (!unicodeVersion) {
+ const emojiInfo = getEmojiInfo(name);
+
+ if (emojiInfo) {
+ if (name !== emojiInfo.name) {
+ ({ name } = emojiInfo);
+ this.dataset.name = emojiInfo.name;
+ }
+ unicodeVersion = emojiInfo.u;
+ this.dataset.uni = unicodeVersion;
+
+ if (forceFallback === 'true' && !fallbackSpriteClass) {
+ this.innerHTML = emojiImageTag(name, emojiFallbackImageSrc(name));
} else {
- const src = emojiFallbackImageSrc(name);
- this.innerHTML = emojiImageTag(name, src);
+ emojiUnicode = emojiInfo.e;
+ this.innerHTML = emojiInfo.e;
}
- })
- .catch(() => {
- // do nothing
- });
- }
- }
- };
-
- document.registerElement('gl-emoji', {
- prototype: GlEmojiElementProto,
- });
+
+ this.title = emojiInfo.d;
+ }
+ }
+
+ const isEmojiUnicode =
+ this.childNodes &&
+ Array.prototype.every.call(this.childNodes, childNode => childNode.nodeType === 3);
+ const hasImageFallback = fallbackSrc && fallbackSrc.length > 0;
+ const hasCssSpriteFalback = fallbackSpriteClass && fallbackSpriteClass.length > 0;
+
+ if (
+ emojiUnicode &&
+ isEmojiUnicode &&
+ !isEmojiUnicodeSupported(emojiUnicode, unicodeVersion)
+ ) {
+ // CSS sprite fallback takes precedence over image fallback
+ if (hasCssSpriteFalback) {
+ if (!gon.emoji_sprites_css_added && gon.emoji_sprites_css_path) {
+ const emojiSpriteLinkTag = document.createElement('link');
+ emojiSpriteLinkTag.setAttribute('rel', 'stylesheet');
+ emojiSpriteLinkTag.setAttribute('href', gon.emoji_sprites_css_path);
+ document.head.appendChild(emojiSpriteLinkTag);
+ gon.emoji_sprites_css_added = true;
+ }
+ // IE 11 doesn't like adding multiple at once :(
+ this.classList.add('emoji-icon');
+ this.classList.add(fallbackSpriteClass);
+ } else if (hasImageFallback) {
+ this.innerHTML = emojiImageTag(name, fallbackSrc);
+ } else {
+ const src = emojiFallbackImageSrc(name);
+ this.innerHTML = emojiImageTag(name, src);
+ }
+ }
+ })
+ .catch(error => {
+ // Only reject is already handled in initEmojiMap
+ throw error;
+ });
+ }
+}
+
+export default function installGlEmojiElement() {
+ if (!customElements.get('gl-emoji')) {
+ customElements.define('gl-emoji', GlEmoji);
+ }
}
diff --git a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
index fe02096d903..58cf057b2c2 100644
--- a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
@@ -1,320 +1,5 @@
-/* eslint-disable object-shorthand, no-unused-vars, no-use-before-define, no-restricted-syntax, guard-for-in, no-continue */
-
import $ from 'jquery';
-import _ from 'underscore';
-import { insertText, getSelectedFragment, nodeMatchesSelector } from '~/lib/utils/common_utils';
-import { placeholderImage } from '~/lazy_loader';
-
-const gfmRules = {
- // The filters referenced in lib/banzai/pipeline/gfm_pipeline.rb convert
- // GitLab Flavored Markdown (GFM) to HTML.
- // These handlers consequently convert that same HTML to GFM to be copied to the clipboard.
- // Every filter in lib/banzai/pipeline/gfm_pipeline.rb that generates HTML
- // from GFM should have a handler here, in reverse order.
- // The GFM-to-HTML-to-GFM cycle is tested in spec/features/copy_as_gfm_spec.rb.
- InlineDiffFilter: {
- 'span.idiff.addition'(el, text) {
- return `{+${text}+}`;
- },
- 'span.idiff.deletion'(el, text) {
- return `{-${text}-}`;
- },
- },
- TaskListFilter: {
- 'input[type=checkbox].task-list-item-checkbox'(el) {
- return `[${el.checked ? 'x' : ' '}]`;
- },
- },
- ReferenceFilter: {
- '.tooltip'(el) {
- return '';
- },
- 'a.gfm:not([data-link=true])'(el, text) {
- return el.dataset.original || text;
- },
- },
- AutolinkFilter: {
- a(el, text) {
- // Fallback on the regular MarkdownFilter's `a` handler.
- if (text !== el.getAttribute('href')) return false;
-
- return text;
- },
- },
- TableOfContentsFilter: {
- 'ul.section-nav'(el) {
- return '[[_TOC_]]';
- },
- },
- EmojiFilter: {
- 'img.emoji'(el) {
- return el.getAttribute('alt');
- },
- 'gl-emoji'(el) {
- return `:${el.getAttribute('data-name')}:`;
- },
- },
- ImageLinkFilter: {
- 'a.no-attachment-icon'(el, text) {
- return text;
- },
- },
- ImageLazyLoadFilter: {
- img(el, text) {
- return `![${el.getAttribute('alt')}](${el.getAttribute('src')})`;
- },
- },
- VideoLinkFilter: {
- '.video-container'(el) {
- const videoEl = el.querySelector('video');
- if (!videoEl) return false;
-
- return CopyAsGFM.nodeToGFM(videoEl);
- },
- video(el) {
- return `![${el.dataset.title}](${el.getAttribute('src')})`;
- },
- },
- MermaidFilter: {
- 'svg.mermaid'(el, text) {
- const sourceEl = el.querySelector('text.source');
- if (!sourceEl) return false;
-
- return `\`\`\`mermaid\n${CopyAsGFM.nodeToGFM(sourceEl)}\n\`\`\``;
- },
- 'svg.mermaid style, svg.mermaid g'(el, text) {
- // We don't want to include the content of these elements in the copied text.
- return '';
- },
- },
- MathFilter: {
- 'pre.code.math[data-math-style=display]'(el, text) {
- return `\`\`\`math\n${text.trim()}\n\`\`\``;
- },
- 'code.code.math[data-math-style=inline]'(el, text) {
- return `$\`${text}\`$`;
- },
- 'span.katex-display span.katex-mathml'(el) {
- const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]');
- if (!mathAnnotation) return false;
-
- return `\`\`\`math\n${CopyAsGFM.nodeToGFM(mathAnnotation)}\n\`\`\``;
- },
- 'span.katex-mathml'(el) {
- const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]');
- if (!mathAnnotation) return false;
-
- return `$\`${CopyAsGFM.nodeToGFM(mathAnnotation)}\`$`;
- },
- 'span.katex-html'(el) {
- // We don't want to include the content of this element in the copied text.
- return '';
- },
- 'annotation[encoding="application/x-tex"]'(el, text) {
- return text.trim();
- },
- },
- SanitizationFilter: {
- 'a[name]:not([href]):empty'(el) {
- return el.outerHTML;
- },
- dl(el, text) {
- let lines = text
- .replace(/\n\n/g, '\n')
- .trim()
- .split('\n');
- // Add two spaces to the front of subsequent list items lines,
- // or leave the line entirely blank.
- lines = lines.map(l => {
- const line = l.trim();
- if (line.length === 0) return '';
-
- return ` ${line}`;
- });
-
- return `<dl>\n${lines.join('\n')}\n</dl>\n`;
- },
- 'dt, dd, summary, details'(el, text) {
- const tag = el.nodeName.toLowerCase();
- return `<${tag}>${text}</${tag}>\n`;
- },
- 'sup, sub, kbd, q, samp, var, ruby, rt, rp, abbr'(el, text) {
- const tag = el.nodeName.toLowerCase();
- return `<${tag}>${text}</${tag}>`;
- },
- },
- SyntaxHighlightFilter: {
- 'pre.code.highlight'(el, t) {
- const text = t.trimRight();
-
- let lang = el.getAttribute('lang');
- if (!lang || lang === 'plaintext') {
- lang = '';
- }
-
- // Prefixes lines with 4 spaces if the code contains triple backticks
- if (lang === '' && text.match(/^```/gm)) {
- return text
- .split('\n')
- .map(l => {
- const line = l.trim();
- if (line.length === 0) return '';
-
- return ` ${line}`;
- })
- .join('\n');
- }
-
- return `\`\`\`${lang}\n${text}\n\`\`\``;
- },
- 'pre > code'(el, text) {
- // Don't wrap code blocks in ``
- return text;
- },
- },
- MarkdownFilter: {
- br(el) {
- // Two spaces at the end of a line are turned into a BR
- return ' ';
- },
- code(el, text) {
- let backtickCount = 1;
- const backtickMatch = text.match(/`+/);
- if (backtickMatch) {
- backtickCount = backtickMatch[0].length + 1;
- }
-
- const backticks = Array(backtickCount + 1).join('`');
- const spaceOrNoSpace = backtickCount > 1 ? ' ' : '';
-
- return backticks + spaceOrNoSpace + text.trim() + spaceOrNoSpace + backticks;
- },
- blockquote(el, text) {
- return text
- .trim()
- .split('\n')
- .map(s => `> ${s}`.trim())
- .join('\n');
- },
- img(el) {
- const imageSrc = el.src;
- const imageUrl = imageSrc && imageSrc !== placeholderImage ? imageSrc : el.dataset.src || '';
- return `![${el.getAttribute('alt')}](${imageUrl})`;
- },
- 'a.anchor'(el, text) {
- // Don't render a Markdown link for the anchor link inside a heading
- return text;
- },
- a(el, text) {
- return `[${text}](${el.getAttribute('href')})`;
- },
- li(el, text) {
- const lines = text.trim().split('\n');
- const firstLine = `- ${lines.shift()}`;
- // Add four spaces to the front of subsequent list items lines,
- // or leave the line entirely blank.
- const nextLines = lines.map(s => {
- if (s.trim().length === 0) return '';
-
- return ` ${s}`;
- });
-
- return `${firstLine}\n${nextLines.join('\n')}`;
- },
- ul(el, text) {
- return text;
- },
- ol(el, text) {
- // LIs get a `- ` prefix by default, which we replace by `1. ` for ordered lists.
- return text.replace(/^- /gm, '1. ');
- },
- h1(el, text) {
- return `# ${text.trim()}\n`;
- },
- h2(el, text) {
- return `## ${text.trim()}\n`;
- },
- h3(el, text) {
- return `### ${text.trim()}\n`;
- },
- h4(el, text) {
- return `#### ${text.trim()}\n`;
- },
- h5(el, text) {
- return `##### ${text.trim()}\n`;
- },
- h6(el, text) {
- return `###### ${text.trim()}\n`;
- },
- strong(el, text) {
- return `**${text}**`;
- },
- em(el, text) {
- return `_${text}_`;
- },
- del(el, text) {
- return `~~${text}~~`;
- },
- hr(el) {
- // extra leading \n is to ensure that there is a blank line between
- // a list followed by an hr, otherwise this breaks old redcarpet rendering
- return '\n-----\n';
- },
- p(el, text) {
- return `${text.trim()}\n`;
- },
- table(el) {
- const theadEl = el.querySelector('thead');
- const tbodyEl = el.querySelector('tbody');
- if (!theadEl || !tbodyEl) return false;
-
- const theadText = CopyAsGFM.nodeToGFM(theadEl);
- const tbodyText = CopyAsGFM.nodeToGFM(tbodyEl);
-
- return [theadText, tbodyText].join('\n');
- },
- thead(el, text) {
- const cells = _.map(el.querySelectorAll('th'), cell => {
- let chars = CopyAsGFM.nodeToGFM(cell).length + 2;
-
- let before = '';
- let after = '';
- const alignment = cell.align || cell.style.textAlign;
-
- switch (alignment) {
- case 'center':
- before = ':';
- after = ':';
- chars -= 2;
- break;
- case 'right':
- after = ':';
- chars -= 1;
- break;
- default:
- break;
- }
-
- chars = Math.max(chars, 3);
-
- const middle = Array(chars + 1).join('-');
-
- return before + middle + after;
- });
-
- const separatorRow = `|${cells.join('|')}|`;
-
- return [text, separatorRow].join('\n');
- },
- tr(el) {
- const cellEls = el.querySelectorAll('td, th');
- if (cellEls.length === 0) return false;
-
- const cells = _.map(cellEls, cell => CopyAsGFM.nodeToGFM(cell));
- return `| ${cells.join(' | ')} |`;
- },
- },
-};
+import { getSelectedFragment } from '~/lib/utils/common_utils';
export class CopyAsGFM {
constructor() {
@@ -347,8 +32,24 @@ export class CopyAsGFM {
e.preventDefault();
e.stopPropagation();
+ const div = document.createElement('div');
+ div.appendChild(el.cloneNode(true));
+ const html = div.innerHTML;
+
clipboardData.setData('text/plain', el.textContent);
- clipboardData.setData('text/x-gfm', this.nodeToGFM(el));
+ clipboardData.setData('text/html', html);
+ // We are also setting this as fallback to transform the selection to gfm on paste
+ clipboardData.setData('text/x-gfm-html', html);
+
+ CopyAsGFM.nodeToGFM(el)
+ .then(res => {
+ clipboardData.setData('text/x-gfm', res);
+ })
+ .catch(() => {
+ // Not showing the error as Firefox might doesn't allow
+ // it or other browsers who have a time limit on the execution
+ // of the copy event
+ });
}
static pasteGFM(e) {
@@ -357,11 +58,28 @@ export class CopyAsGFM {
const text = clipboardData.getData('text/plain');
const gfm = clipboardData.getData('text/x-gfm');
- if (!gfm) return;
+ const gfmHtml = clipboardData.getData('text/x-gfm-html');
+ if (!gfm && !gfmHtml) return;
e.preventDefault();
- window.gl.utils.insertText(e.target, (textBefore, textAfter) => {
+ // We have the original selection already converted to gfm
+ if (gfm) {
+ CopyAsGFM.insertPastedText(e.target, text, gfm);
+ } else {
+ // Due to the async copy call we are not able to produce gfm so we transform the cached HTML
+ const div = document.createElement('div');
+ div.innerHTML = gfmHtml;
+ CopyAsGFM.nodeToGFM(div)
+ .then(transformedGfm => {
+ CopyAsGFM.insertPastedText(e.target, text, transformedGfm);
+ })
+ .catch(() => {});
+ }
+ }
+
+ static insertPastedText(target, text, gfm) {
+ window.gl.utils.insertText(target, textBefore => {
// If the text before the cursor contains an odd number of backticks,
// we are either inside an inline code span that starts with 1 backtick
// or a code block that starts with 3 backticks.
@@ -443,75 +161,24 @@ export class CopyAsGFM {
return codeElement;
}
- static nodeToGFM(node, respectWhitespaceParam = false) {
- if (node.nodeType === Node.COMMENT_NODE) {
- return '';
- }
-
- if (node.nodeType === Node.TEXT_NODE) {
- return node.textContent;
- }
-
- const respectWhitespace =
- respectWhitespaceParam || (node.nodeName === 'PRE' || node.nodeName === 'CODE');
-
- const text = this.innerGFM(node, respectWhitespace);
-
- if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
- return text;
- }
-
- for (const filter in gfmRules) {
- const rules = gfmRules[filter];
-
- for (const selector in rules) {
- const func = rules[selector];
-
- if (!nodeMatchesSelector(node, selector)) continue;
-
- let result;
- if (func.length === 2) {
- // if `func` takes 2 arguments, it depends on text.
- // if there is no text, we don't need to generate GFM for this node.
- if (text.length === 0) continue;
-
- result = func(node, text);
- } else {
- result = func(node);
- }
-
- if (result === false) continue;
-
- return result;
- }
- }
-
- return text;
- }
-
- static innerGFM(parentNode, respectWhitespace = false) {
- const nodes = parentNode.childNodes;
-
- const clonedParentNode = parentNode.cloneNode(true);
- const clonedNodes = Array.prototype.slice.call(clonedParentNode.childNodes, 0);
-
- for (let i = 0; i < nodes.length; i += 1) {
- const node = nodes[i];
- const clonedNode = clonedNodes[i];
-
- const text = this.nodeToGFM(node, respectWhitespace);
-
- // `clonedNode.replaceWith(text)` is not yet widely supported
- clonedNode.parentNode.replaceChild(document.createTextNode(text), clonedNode);
- }
-
- let nodeText = clonedParentNode.innerText || clonedParentNode.textContent;
-
- if (!respectWhitespace) {
- nodeText = nodeText.trim();
- }
-
- return nodeText;
+ static nodeToGFM(node) {
+ return Promise.all([
+ import(/* webpackChunkName: 'gfm_copy_extra' */ 'prosemirror-model'),
+ import(/* webpackChunkName: 'gfm_copy_extra' */ './schema'),
+ import(/* webpackChunkName: 'gfm_copy_extra' */ './serializer'),
+ ])
+ .then(([prosemirrorModel, schema, markdownSerializer]) => {
+ const { DOMParser } = prosemirrorModel;
+ const wrapEl = document.createElement('div');
+ wrapEl.appendChild(node.cloneNode(true));
+ const doc = DOMParser.fromSchema(schema.default).parse(wrapEl);
+
+ const res = markdownSerializer.default.serialize(doc, {
+ tightLists: true,
+ });
+ return res;
+ })
+ .catch(() => {});
}
}
diff --git a/app/assets/javascripts/behaviors/markdown/editor_extensions.js b/app/assets/javascripts/behaviors/markdown/editor_extensions.js
new file mode 100644
index 00000000000..47e5fc65c48
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/editor_extensions.js
@@ -0,0 +1,106 @@
+import Doc from './nodes/doc';
+import Paragraph from './nodes/paragraph';
+import Text from './nodes/text';
+
+import Blockquote from './nodes/blockquote';
+import CodeBlock from './nodes/code_block';
+import HardBreak from './nodes/hard_break';
+import Heading from './nodes/heading';
+import HorizontalRule from './nodes/horizontal_rule';
+import Image from './nodes/image';
+
+import Table from './nodes/table';
+import TableHead from './nodes/table_head';
+import TableBody from './nodes/table_body';
+import TableHeaderRow from './nodes/table_header_row';
+import TableRow from './nodes/table_row';
+import TableCell from './nodes/table_cell';
+
+import Emoji from './nodes/emoji';
+import Reference from './nodes/reference';
+
+import TableOfContents from './nodes/table_of_contents';
+import Video from './nodes/video';
+
+import BulletList from './nodes/bullet_list';
+import OrderedList from './nodes/ordered_list';
+import ListItem from './nodes/list_item';
+
+import DescriptionList from './nodes/description_list';
+import DescriptionTerm from './nodes/description_term';
+import DescriptionDetails from './nodes/description_details';
+
+import TaskList from './nodes/task_list';
+import OrderedTaskList from './nodes/ordered_task_list';
+import TaskListItem from './nodes/task_list_item';
+
+import Summary from './nodes/summary';
+import Details from './nodes/details';
+
+import Bold from './marks/bold';
+import Italic from './marks/italic';
+import Strike from './marks/strike';
+import InlineDiff from './marks/inline_diff';
+
+import Link from './marks/link';
+import Code from './marks/code';
+import MathMark from './marks/math';
+import InlineHTML from './marks/inline_html';
+
+// The filters referenced in lib/banzai/pipeline/gfm_pipeline.rb transform
+// GitLab Flavored Markdown (GFM) to HTML.
+// The nodes and marks referenced here transform that same HTML to GFM to be copied to the clipboard.
+// Every filter in lib/banzai/pipeline/gfm_pipeline.rb that generates HTML
+// from GFM should have a node or mark here.
+// The GFM-to-HTML-to-GFM cycle is tested in spec/features/copy_as_gfm_spec.rb.
+
+export default [
+ new Doc(),
+ new Paragraph(),
+ new Text(),
+
+ new Blockquote(),
+ new CodeBlock(),
+ new HardBreak(),
+ new Heading({ maxLevel: 6 }),
+ new HorizontalRule(),
+ new Image(),
+
+ new Table(),
+ new TableHead(),
+ new TableBody(),
+ new TableHeaderRow(),
+ new TableRow(),
+ new TableCell(),
+
+ new Emoji(),
+ new Reference(),
+
+ new TableOfContents(),
+ new Video(),
+
+ new BulletList(),
+ new OrderedList(),
+ new ListItem(),
+
+ new DescriptionList(),
+ new DescriptionTerm(),
+ new DescriptionDetails(),
+
+ new TaskList(),
+ new OrderedTaskList(),
+ new TaskListItem(),
+
+ new Summary(),
+ new Details(),
+
+ new Bold(),
+ new Italic(),
+ new Strike(),
+ new InlineDiff(),
+
+ new Link(),
+ new Code(),
+ new MathMark(),
+ new InlineHTML(),
+];
diff --git a/app/assets/javascripts/behaviors/markdown/marks/bold.js b/app/assets/javascripts/behaviors/markdown/marks/bold.js
new file mode 100644
index 00000000000..b537954c1cb
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/marks/bold.js
@@ -0,0 +1,11 @@
+/* eslint-disable class-methods-use-this */
+
+import { Bold as BaseBold } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Bold extends BaseBold {
+ get toMarkdown() {
+ return defaultMarkdownSerializer.marks.strong;
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/marks/code.js b/app/assets/javascripts/behaviors/markdown/marks/code.js
new file mode 100644
index 00000000000..a760ee80dd0
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/marks/code.js
@@ -0,0 +1,11 @@
+/* eslint-disable class-methods-use-this */
+
+import { Code as BaseCode } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Code extends BaseCode {
+ get toMarkdown() {
+ return defaultMarkdownSerializer.marks.code;
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/marks/inline_diff.js b/app/assets/javascripts/behaviors/markdown/marks/inline_diff.js
new file mode 100644
index 00000000000..ce425e80cd3
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/marks/inline_diff.js
@@ -0,0 +1,41 @@
+/* eslint-disable class-methods-use-this */
+
+import { Mark } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::InlineDiffFilter
+export default class InlineDiff extends Mark {
+ get name() {
+ return 'inline_diff';
+ }
+
+ get schema() {
+ return {
+ attrs: {
+ addition: {
+ default: true,
+ },
+ },
+ parseDOM: [
+ { tag: 'span.idiff.addition', attrs: { addition: true } },
+ { tag: 'span.idiff.deletion', attrs: { addition: false } },
+ ],
+ toDOM: node => [
+ 'span',
+ { class: `idiff left right ${node.attrs.addition ? 'addition' : 'deletion'}` },
+ 0,
+ ],
+ };
+ }
+
+ get toMarkdown() {
+ return {
+ mixable: true,
+ open(state, mark) {
+ return mark.attrs.addition ? '{+' : '{-';
+ },
+ close(state, mark) {
+ return mark.attrs.addition ? '+}' : '-}';
+ },
+ };
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/marks/inline_html.js b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
new file mode 100644
index 00000000000..ebed8698e21
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
@@ -0,0 +1,46 @@
+/* eslint-disable class-methods-use-this */
+
+import { Mark } from 'tiptap';
+import _ from 'underscore';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class InlineHTML extends Mark {
+ get name() {
+ return 'inline_html';
+ }
+
+ get schema() {
+ return {
+ excludes: '',
+ attrs: {
+ tag: {},
+ title: { default: null },
+ },
+ parseDOM: [
+ {
+ tag: 'sup, sub, kbd, q, samp, var',
+ getAttrs: el => ({ tag: el.nodeName.toLowerCase() }),
+ },
+ {
+ tag: 'abbr',
+ getAttrs: el => ({ tag: 'abbr', title: el.getAttribute('title') }),
+ },
+ ],
+ toDOM: node => [node.attrs.tag, { title: node.attrs.title }, 0],
+ };
+ }
+
+ get toMarkdown() {
+ return {
+ mixable: true,
+ open(state, mark) {
+ return `<${mark.attrs.tag}${
+ mark.attrs.title ? ` title="${state.esc(_.escape(mark.attrs.title))}"` : ''
+ }>`;
+ },
+ close(state, mark) {
+ return `</${mark.attrs.tag}>`;
+ },
+ };
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/marks/italic.js b/app/assets/javascripts/behaviors/markdown/marks/italic.js
new file mode 100644
index 00000000000..44b35c97739
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/marks/italic.js
@@ -0,0 +1,11 @@
+/* eslint-disable class-methods-use-this */
+
+import { Italic as BaseItalic } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Italic extends BaseItalic {
+ get toMarkdown() {
+ return defaultMarkdownSerializer.marks.em;
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/marks/link.js b/app/assets/javascripts/behaviors/markdown/marks/link.js
new file mode 100644
index 00000000000..5c23d6a5ceb
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/marks/link.js
@@ -0,0 +1,21 @@
+/* eslint-disable class-methods-use-this */
+
+import { Link as BaseLink } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Link extends BaseLink {
+ get toMarkdown() {
+ return {
+ mixable: true,
+ open(state, mark, parent, index) {
+ const open = defaultMarkdownSerializer.marks.link.open(state, mark, parent, index);
+ return open === '<' ? '' : open;
+ },
+ close(state, mark, parent, index) {
+ const close = defaultMarkdownSerializer.marks.link.close(state, mark, parent, index);
+ return close === '>' ? '' : close;
+ },
+ };
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/marks/math.js b/app/assets/javascripts/behaviors/markdown/marks/math.js
new file mode 100644
index 00000000000..e582fb18f15
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/marks/math.js
@@ -0,0 +1,41 @@
+/* eslint-disable class-methods-use-this */
+
+import { Mark } from 'tiptap';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MathFilter
+export default class MathMark extends Mark {
+ get name() {
+ return 'math';
+ }
+
+ get schema() {
+ return {
+ parseDOM: [
+ // Matches HTML generated by Banzai::Filter::MathFilter
+ {
+ tag: 'code.code.math[data-math-style=inline]',
+ priority: 51,
+ },
+ // Matches HTML after being transformed by app/assets/javascripts/behaviors/markdown/render_math.js
+ {
+ tag: 'span.katex',
+ contentElement: 'annotation[encoding="application/x-tex"]',
+ },
+ ],
+ toDOM: () => ['code', { class: 'code math', 'data-math-style': 'inline' }, 0],
+ };
+ }
+
+ get toMarkdown() {
+ return {
+ escape: false,
+ open(state, mark, parent, index) {
+ return `$${defaultMarkdownSerializer.marks.code.open(state, mark, parent, index)}`;
+ },
+ close(state, mark, parent, index) {
+ return `${defaultMarkdownSerializer.marks.code.close(state, mark, parent, index)}$`;
+ },
+ };
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/marks/strike.js b/app/assets/javascripts/behaviors/markdown/marks/strike.js
new file mode 100644
index 00000000000..c2951a40a4b
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/marks/strike.js
@@ -0,0 +1,15 @@
+/* eslint-disable class-methods-use-this */
+
+import { Strike as BaseStrike } from 'tiptap-extensions';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Strike extends BaseStrike {
+ get toMarkdown() {
+ return {
+ open: '~~',
+ close: '~~',
+ mixable: true,
+ expelEnclosingWhitespace: true,
+ };
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js b/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js
new file mode 100644
index 00000000000..b0bc8f79643
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js
@@ -0,0 +1,13 @@
+/* eslint-disable class-methods-use-this */
+
+import { Blockquote as BaseBlockquote } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Blockquote extends BaseBlockquote {
+ toMarkdown(state, node) {
+ if (!node.childCount) return;
+
+ defaultMarkdownSerializer.nodes.blockquote(state, node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js b/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js
new file mode 100644
index 00000000000..3b0792e1af8
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js
@@ -0,0 +1,11 @@
+/* eslint-disable class-methods-use-this */
+
+import { BulletList as BaseBulletList } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class BulletList extends BaseBulletList {
+ toMarkdown(state, node) {
+ defaultMarkdownSerializer.nodes.bullet_list(state, node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/code_block.js b/app/assets/javascripts/behaviors/markdown/nodes/code_block.js
new file mode 100644
index 00000000000..1e0c05eff08
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/code_block.js
@@ -0,0 +1,99 @@
+/* eslint-disable class-methods-use-this */
+
+import { CodeBlock as BaseCodeBlock } from 'tiptap-extensions';
+
+const PLAINTEXT_LANG = 'plaintext';
+
+// Transforms generated HTML back to GFM for:
+// - Banzai::Filter::SyntaxHighlightFilter
+// - Banzai::Filter::MathFilter
+// - Banzai::Filter::MermaidFilter
+// - Banzai::Filter::SuggestionFilter
+export default class CodeBlock extends BaseCodeBlock {
+ get schema() {
+ return {
+ content: 'text*',
+ marks: '',
+ group: 'block',
+ code: true,
+ defining: true,
+ attrs: {
+ lang: { default: PLAINTEXT_LANG },
+ },
+ parseDOM: [
+ // Matches HTML generated by Banzai::Filter::SyntaxHighlightFilter, Banzai::Filter::MathFilter, Banzai::Filter::MermaidFilter, or Banzai::Filter::SuggestionFilter
+ {
+ tag: 'pre.code.highlight',
+ preserveWhitespace: 'full',
+ getAttrs: el => {
+ const lang = el.getAttribute('lang');
+ if (!lang || lang === '') return {};
+
+ return { lang };
+ },
+ },
+ // Matches HTML generated by Banzai::Filter::MathFilter,
+ // after being transformed by app/assets/javascripts/behaviors/markdown/render_math.js
+ {
+ tag: 'span.katex-display',
+ preserveWhitespace: 'full',
+ contentElement: 'annotation[encoding="application/x-tex"]',
+ attrs: { lang: 'math' },
+ },
+ // Matches HTML generated by Banzai::Filter::MermaidFilter,
+ // after being transformed by app/assets/javascripts/behaviors/markdown/render_mermaid.js
+ {
+ tag: 'svg.mermaid',
+ preserveWhitespace: 'full',
+ contentElement: 'text.source',
+ attrs: { lang: 'mermaid' },
+ },
+ // Matches HTML generated by Banzai::Filter::SuggestionFilter,
+ // after being transformed by app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+ {
+ tag: '.md-suggestion',
+ skip: true,
+ },
+ {
+ tag: '.md-suggestion-header',
+ ignore: true,
+ },
+ {
+ tag: '.md-suggestion-diff',
+ preserveWhitespace: 'full',
+ getContent: (el, schema) =>
+ [...el.querySelectorAll('.line_content.new span')].map(span =>
+ schema.text(span.innerText),
+ ),
+ attrs: { lang: 'suggestion' },
+ },
+ ],
+ toDOM: node => ['pre', { class: 'code highlight', lang: node.attrs.lang }, ['code', 0]],
+ };
+ }
+
+ toMarkdown(state, node) {
+ if (!node.childCount) return;
+
+ const {
+ textContent: text,
+ attrs: { lang },
+ } = node;
+
+ // Prefixes lines with 4 spaces if the code contains a line that starts with triple backticks
+ if (lang === PLAINTEXT_LANG && text.match(/^```/gm)) {
+ state.wrapBlock(' ', null, node, () => state.text(text, false));
+ return;
+ }
+
+ state.write('```');
+ if (lang !== PLAINTEXT_LANG) state.write(lang);
+
+ state.ensureNewLine();
+ state.text(text, false);
+ state.ensureNewLine();
+
+ state.write('```');
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/description_details.js b/app/assets/javascripts/behaviors/markdown/nodes/description_details.js
new file mode 100644
index 00000000000..a4451d8ce8d
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/description_details.js
@@ -0,0 +1,28 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class DescriptionDetails extends Node {
+ get name() {
+ return 'description_details';
+ }
+
+ get schema() {
+ return {
+ content: 'text*',
+ marks: '',
+ defining: true,
+ parseDOM: [{ tag: 'dd' }],
+ toDOM: () => ['dd', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.flushClose(1);
+ state.write('<dd>');
+ state.text(node.textContent, false);
+ state.write('</dd>');
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/description_list.js b/app/assets/javascripts/behaviors/markdown/nodes/description_list.js
new file mode 100644
index 00000000000..6aa1aca29d7
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/description_list.js
@@ -0,0 +1,28 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class DescriptionList extends Node {
+ get name() {
+ return 'description_list';
+ }
+
+ get schema() {
+ return {
+ content: '(description_term+ description_details+)+',
+ group: 'block',
+ parseDOM: [{ tag: 'dl' }],
+ toDOM: () => ['dl', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.write('<dl>\n');
+ state.wrapBlock(' ', null, node, () => state.renderContent(node));
+ state.flushClose(1);
+ state.ensureNewLine();
+ state.write('</dl>');
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/description_term.js b/app/assets/javascripts/behaviors/markdown/nodes/description_term.js
new file mode 100644
index 00000000000..89057ec6444
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/description_term.js
@@ -0,0 +1,28 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class DescriptionTerm extends Node {
+ get name() {
+ return 'description_term';
+ }
+
+ get schema() {
+ return {
+ content: 'text*',
+ marks: '',
+ defining: true,
+ parseDOM: [{ tag: 'dt' }],
+ toDOM: () => ['dt', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.flushClose(state.closed && state.closed.type === node.type ? 1 : 2);
+ state.write('<dt>');
+ state.text(node.textContent, false);
+ state.write('</dt>');
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/details.js b/app/assets/javascripts/behaviors/markdown/nodes/details.js
new file mode 100644
index 00000000000..1c40dbb8168
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/details.js
@@ -0,0 +1,28 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Details extends Node {
+ get name() {
+ return 'details';
+ }
+
+ get schema() {
+ return {
+ content: 'summary block*',
+ group: 'block',
+ parseDOM: [{ tag: 'details' }],
+ toDOM: () => ['details', { open: true, onclick: 'return false', tabindex: '-1' }, 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.write('<details>\n');
+ state.renderContent(node);
+ state.flushClose(1);
+ state.ensureNewLine();
+ state.write('</details>');
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/doc.js b/app/assets/javascripts/behaviors/markdown/nodes/doc.js
new file mode 100644
index 00000000000..88b16fd85da
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/doc.js
@@ -0,0 +1,15 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+export default class Doc extends Node {
+ get name() {
+ return 'doc';
+ }
+
+ get schema() {
+ return {
+ content: 'block+',
+ };
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/emoji.js b/app/assets/javascripts/behaviors/markdown/nodes/emoji.js
new file mode 100644
index 00000000000..a7cc3e828f5
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/emoji.js
@@ -0,0 +1,41 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::EmojiFilter
+export default class Emoji extends Node {
+ get name() {
+ return 'emoji';
+ }
+
+ get schema() {
+ return {
+ inline: true,
+ group: 'inline',
+ attrs: {
+ name: {},
+ title: {},
+ moji: {},
+ },
+ parseDOM: [
+ {
+ tag: 'gl-emoji',
+ getAttrs: el => ({
+ name: el.dataset.name,
+ title: el.getAttribute('title'),
+ moji: el.textContent,
+ }),
+ },
+ ],
+ toDOM: node => [
+ 'gl-emoji',
+ { 'data-name': node.attrs.name, title: node.attrs.title },
+ node.attrs.moji,
+ ],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.write(`:${node.attrs.name}:`);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/hard_break.js b/app/assets/javascripts/behaviors/markdown/nodes/hard_break.js
new file mode 100644
index 00000000000..59e5d8ab3e2
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/hard_break.js
@@ -0,0 +1,10 @@
+/* eslint-disable class-methods-use-this */
+
+import { HardBreak as BaseHardBreak } from 'tiptap-extensions';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class HardBreak extends BaseHardBreak {
+ toMarkdown(state) {
+ if (!state.atBlank()) state.write(' \n');
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/heading.js b/app/assets/javascripts/behaviors/markdown/nodes/heading.js
new file mode 100644
index 00000000000..fec8608cf5d
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/heading.js
@@ -0,0 +1,13 @@
+/* eslint-disable class-methods-use-this */
+
+import { Heading as BaseHeading } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Heading extends BaseHeading {
+ toMarkdown(state, node) {
+ if (!node.childCount) return;
+
+ defaultMarkdownSerializer.nodes.heading(state, node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js b/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js
new file mode 100644
index 00000000000..695c7160bde
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js
@@ -0,0 +1,11 @@
+/* eslint-disable class-methods-use-this */
+
+import { HorizontalRule as BaseHorizontalRule } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class HorizontalRule extends BaseHorizontalRule {
+ toMarkdown(state, node) {
+ defaultMarkdownSerializer.nodes.horizontal_rule(state, node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/image.js b/app/assets/javascripts/behaviors/markdown/nodes/image.js
new file mode 100644
index 00000000000..c225a5ed876
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/image.js
@@ -0,0 +1,52 @@
+/* eslint-disable class-methods-use-this */
+
+import { Image as BaseImage } from 'tiptap-extensions';
+import { placeholderImage } from '~/lazy_loader';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+export default class Image extends BaseImage {
+ get schema() {
+ return {
+ attrs: {
+ src: {},
+ alt: {
+ default: null,
+ },
+ title: {
+ default: null,
+ },
+ },
+ group: 'inline',
+ inline: true,
+ draggable: true,
+ parseDOM: [
+ // Matches HTML generated by Banzai::Filter::ImageLinkFilter
+ {
+ tag: 'a.no-attachment-icon',
+ priority: 51,
+ skip: true,
+ },
+ // Matches HTML generated by Banzai::Filter::ImageLazyLoadFilter
+ {
+ tag: 'img[src]',
+ getAttrs: el => {
+ const imageSrc = el.src;
+ const imageUrl =
+ imageSrc && imageSrc !== placeholderImage ? imageSrc : el.dataset.src || '';
+
+ return {
+ src: imageUrl,
+ title: el.getAttribute('title'),
+ alt: el.getAttribute('alt'),
+ };
+ },
+ },
+ ],
+ toDOM: node => ['img', node.attrs],
+ };
+ }
+
+ toMarkdown(state, node) {
+ defaultMarkdownSerializer.nodes.image(state, node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/list_item.js b/app/assets/javascripts/behaviors/markdown/nodes/list_item.js
new file mode 100644
index 00000000000..4237637ed9a
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/list_item.js
@@ -0,0 +1,11 @@
+/* eslint-disable class-methods-use-this */
+
+import { ListItem as BaseListItem } from 'tiptap-extensions';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class ListItem extends BaseListItem {
+ toMarkdown(state, node) {
+ defaultMarkdownSerializer.nodes.list_item(state, node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/ordered_list.js b/app/assets/javascripts/behaviors/markdown/nodes/ordered_list.js
new file mode 100644
index 00000000000..4c1542d14ea
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/ordered_list.js
@@ -0,0 +1,10 @@
+/* eslint-disable class-methods-use-this */
+
+import { OrderedList as BaseOrderedList } from 'tiptap-extensions';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class OrderedList extends BaseOrderedList {
+ toMarkdown(state, node) {
+ state.renderList(node, ' ', () => '1. ');
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/ordered_task_list.js b/app/assets/javascripts/behaviors/markdown/nodes/ordered_task_list.js
new file mode 100644
index 00000000000..25c4976a1bc
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/ordered_task_list.js
@@ -0,0 +1,28 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::TaskListFilter
+export default class OrderedTaskList extends Node {
+ get name() {
+ return 'ordered_task_list';
+ }
+
+ get schema() {
+ return {
+ group: 'block',
+ content: '(task_list_item|list_item)+',
+ parseDOM: [
+ {
+ priority: 51,
+ tag: 'ol.task-list',
+ },
+ ],
+ toDOM: () => ['ol', { class: 'task-list' }, 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.renderList(node, ' ', () => '1. ');
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js b/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js
new file mode 100644
index 00000000000..dec3207b1bb
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js
@@ -0,0 +1,24 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Paragraph extends Node {
+ get name() {
+ return 'paragraph';
+ }
+
+ get schema() {
+ return {
+ content: 'inline*',
+ group: 'block',
+ parseDOM: [{ tag: 'p' }],
+ toDOM: () => ['p', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ defaultMarkdownSerializer.nodes.paragraph(state, node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/reference.js b/app/assets/javascripts/behaviors/markdown/nodes/reference.js
new file mode 100644
index 00000000000..5d6bbeca833
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/reference.js
@@ -0,0 +1,52 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::ReferenceFilter and subclasses
+export default class Reference extends Node {
+ get name() {
+ return 'reference';
+ }
+
+ get schema() {
+ return {
+ inline: true,
+ group: 'inline',
+ atom: true,
+ attrs: {
+ className: {},
+ referenceType: {},
+ originalText: { default: null },
+ href: {},
+ text: {},
+ },
+ parseDOM: [
+ {
+ tag: 'a.gfm:not([data-link=true])',
+ priority: 51,
+ getAttrs: el => ({
+ className: el.className,
+ referenceType: el.dataset.referenceType,
+ originalText: el.dataset.original,
+ href: el.getAttribute('href'),
+ text: el.textContent,
+ }),
+ },
+ ],
+ toDOM: node => [
+ 'a',
+ {
+ class: node.attrs.className,
+ href: node.attrs.href,
+ 'data-reference-type': node.attrs.referenceType,
+ 'data-original': node.attrs.originalText,
+ },
+ node.attrs.text,
+ ],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.write(node.attrs.originalText || node.attrs.text);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/summary.js b/app/assets/javascripts/behaviors/markdown/nodes/summary.js
new file mode 100644
index 00000000000..2e36e316d71
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/summary.js
@@ -0,0 +1,27 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Summary extends Node {
+ get name() {
+ return 'summary';
+ }
+
+ get schema() {
+ return {
+ content: 'text*',
+ marks: '',
+ defining: true,
+ parseDOM: [{ tag: 'summary' }],
+ toDOM: () => ['summary', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.write('<summary>');
+ state.text(node.textContent, false);
+ state.write('</summary>');
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table.js b/app/assets/javascripts/behaviors/markdown/nodes/table.js
new file mode 100644
index 00000000000..a7fcb9227cd
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table.js
@@ -0,0 +1,25 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class Table extends Node {
+ get name() {
+ return 'table';
+ }
+
+ get schema() {
+ return {
+ content: 'table_head table_body',
+ group: 'block',
+ isolating: true,
+ parseDOM: [{ tag: 'table' }],
+ toDOM: () => ['table', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.renderContent(node);
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_body.js b/app/assets/javascripts/behaviors/markdown/nodes/table_body.js
new file mode 100644
index 00000000000..403556dc0c8
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table_body.js
@@ -0,0 +1,24 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class TableBody extends Node {
+ get name() {
+ return 'table_body';
+ }
+
+ get schema() {
+ return {
+ content: 'table_row+',
+ parseDOM: [{ tag: 'tbody' }],
+ toDOM: () => ['tbody', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.flushClose(1);
+ state.renderContent(node);
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_cell.js b/app/assets/javascripts/behaviors/markdown/nodes/table_cell.js
new file mode 100644
index 00000000000..c63bfe10e39
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table_cell.js
@@ -0,0 +1,35 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class TableCell extends Node {
+ get name() {
+ return 'table_cell';
+ }
+
+ get schema() {
+ return {
+ attrs: {
+ header: { default: false },
+ align: { default: null },
+ },
+ content: 'inline*',
+ isolating: true,
+ parseDOM: [
+ {
+ tag: 'td, th',
+ getAttrs: el => ({
+ header: el.tagName === 'TH',
+ align: el.getAttribute('align') || el.style.textAlign,
+ }),
+ },
+ ],
+ toDOM: node => [node.attrs.header ? 'th' : 'td', { align: node.attrs.align }, 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.renderInline(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_head.js b/app/assets/javascripts/behaviors/markdown/nodes/table_head.js
new file mode 100644
index 00000000000..4cb94bf088c
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table_head.js
@@ -0,0 +1,24 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class TableHead extends Node {
+ get name() {
+ return 'table_head';
+ }
+
+ get schema() {
+ return {
+ content: 'table_header_row',
+ parseDOM: [{ tag: 'thead' }],
+ toDOM: () => ['thead', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.flushClose(1);
+ state.renderContent(node);
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js b/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js
new file mode 100644
index 00000000000..e7eee636402
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js
@@ -0,0 +1,43 @@
+/* eslint-disable class-methods-use-this */
+
+import TableRow from './table_row';
+
+const CENTER_ALIGN = 'center';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class TableHeaderRow extends TableRow {
+ get name() {
+ return 'table_header_row';
+ }
+
+ get schema() {
+ return {
+ content: 'table_cell+',
+ parseDOM: [
+ {
+ tag: 'thead tr',
+ priority: 51,
+ },
+ ],
+ toDOM: () => ['tr', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ const cellWidths = super.toMarkdown(state, node);
+
+ state.flushClose(1);
+
+ state.write('|');
+ node.forEach((cell, _, i) => {
+ if (i) state.write('|');
+
+ state.write(cell.attrs.align === CENTER_ALIGN ? ':' : '-');
+ state.write(state.repeat('-', cellWidths[i]));
+ state.write(cell.attrs.align === CENTER_ALIGN || cell.attrs.align === 'right' ? ':' : '-');
+ });
+ state.write('|');
+
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js b/app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js
new file mode 100644
index 00000000000..20c7fa8a9ab
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js
@@ -0,0 +1,33 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::TableOfContentsFilter
+export default class TableOfContents extends Node {
+ get name() {
+ return 'table_of_contents';
+ }
+
+ get schema() {
+ return {
+ group: 'block',
+ atom: true,
+ parseDOM: [
+ {
+ tag: 'ul.section-nav',
+ priority: 51,
+ },
+ {
+ tag: 'p.table-of-contents',
+ priority: 51,
+ },
+ ],
+ toDOM: () => ['p', { class: 'table-of-contents' }, 'Table of Contents'],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.write('[[_TOC_]]');
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_row.js b/app/assets/javascripts/behaviors/markdown/nodes/table_row.js
new file mode 100644
index 00000000000..5852502773a
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table_row.js
@@ -0,0 +1,38 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
+export default class TableRow extends Node {
+ get name() {
+ return 'table_row';
+ }
+
+ get schema() {
+ return {
+ content: 'table_cell+',
+ parseDOM: [{ tag: 'tr' }],
+ toDOM: () => ['tr', 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ const cellWidths = [];
+
+ state.flushClose(1);
+
+ state.write('| ');
+ node.forEach((cell, _, i) => {
+ if (i) state.write(' | ');
+
+ const { length } = state.out;
+ state.render(cell, node, i);
+ cellWidths.push(state.out.length - length);
+ });
+ state.write(' |');
+
+ state.closeBlock(node);
+
+ return cellWidths;
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/task_list.js b/app/assets/javascripts/behaviors/markdown/nodes/task_list.js
new file mode 100644
index 00000000000..ab33bc21502
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/task_list.js
@@ -0,0 +1,28 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::TaskListFilter
+export default class TaskList extends Node {
+ get name() {
+ return 'task_list';
+ }
+
+ get schema() {
+ return {
+ group: 'block',
+ content: '(task_list_item|list_item)+',
+ parseDOM: [
+ {
+ priority: 51,
+ tag: 'ul.task-list',
+ },
+ ],
+ toDOM: () => ['ul', { class: 'task-list' }, 0],
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.renderList(node, ' ', () => '* ');
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js b/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
new file mode 100644
index 00000000000..d0ee7333d5e
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
@@ -0,0 +1,49 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::TaskListFilter
+export default class TaskListItem extends Node {
+ get name() {
+ return 'task_list_item';
+ }
+
+ get schema() {
+ return {
+ attrs: {
+ done: {
+ default: false,
+ },
+ },
+ defining: true,
+ draggable: false,
+ content: 'paragraph block*',
+ parseDOM: [
+ {
+ priority: 51,
+ tag: 'li.task-list-item',
+ getAttrs: el => {
+ const checkbox = el.querySelector('input[type=checkbox].task-list-item-checkbox');
+ return { done: checkbox && checkbox.checked };
+ },
+ },
+ ],
+ toDOM(node) {
+ return [
+ 'li',
+ { class: 'task-list-item' },
+ [
+ 'input',
+ { type: 'checkbox', class: 'task-list-item-checkbox', checked: node.attrs.done },
+ ],
+ ['div', { class: 'todo-content' }, 0],
+ ];
+ },
+ };
+ }
+
+ toMarkdown(state, node) {
+ state.write(`[${node.attrs.done ? 'x' : ' '}] `);
+ state.renderContent(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/text.js b/app/assets/javascripts/behaviors/markdown/nodes/text.js
new file mode 100644
index 00000000000..84838c14999
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/text.js
@@ -0,0 +1,20 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+export default class Text extends Node {
+ get name() {
+ return 'text';
+ }
+
+ get schema() {
+ return {
+ group: 'inline',
+ };
+ }
+
+ toMarkdown(state, node) {
+ defaultMarkdownSerializer.nodes.text(state, node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/video.js b/app/assets/javascripts/behaviors/markdown/nodes/video.js
new file mode 100644
index 00000000000..516f983397d
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/nodes/video.js
@@ -0,0 +1,54 @@
+/* eslint-disable class-methods-use-this */
+
+import { Node } from 'tiptap';
+import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+
+// Transforms generated HTML back to GFM for Banzai::Filter::VideoLinkFilter
+export default class Video extends Node {
+ get name() {
+ return 'video';
+ }
+
+ get schema() {
+ return {
+ attrs: {
+ src: {},
+ alt: {
+ default: null,
+ },
+ },
+ group: 'block',
+ draggable: true,
+ parseDOM: [
+ {
+ tag: '.video-container',
+ skip: true,
+ },
+ {
+ tag: '.video-container p',
+ priority: 51,
+ ignore: true,
+ },
+ {
+ tag: 'video[src]',
+ getAttrs: el => ({ src: el.getAttribute('src'), alt: el.dataset.title }),
+ },
+ ],
+ toDOM: node => [
+ 'video',
+ {
+ src: node.attrs.src,
+ width: '400',
+ controls: true,
+ 'data-setup': '{}',
+ 'data-title': node.attrs.alt,
+ },
+ ],
+ };
+ }
+
+ toMarkdown(state, node) {
+ defaultMarkdownSerializer.nodes.image(state, node);
+ state.closeBlock(node);
+ }
+}
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index 35380ca49fb..798114b4b0b 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -1,4 +1,5 @@
import flash from '~/flash';
+import { sprintf, __ } from '../../locale';
// Renders diagrams and flowcharts from text using Mermaid in any element with the
// `js-render-mermaid` class.
@@ -14,6 +15,9 @@ import flash from '~/flash';
// </pre>
//
+// This is an arbitary number; Can be iterated upon when suitable.
+const MAX_CHAR_LIMIT = 5000;
+
export default function renderMermaid($els) {
if (!$els.length) return;
@@ -34,6 +38,21 @@ export default function renderMermaid($els) {
$els.each((i, el) => {
const source = el.textContent;
+ /**
+ * Restrict the rendering to a certain amount of character to
+ * prevent mermaidjs from hanging up the entire thread and
+ * causing a DoS.
+ */
+ if (source && source.length > MAX_CHAR_LIMIT) {
+ el.textContent = sprintf(
+ __(
+ 'Cannot render the image. Maximum character count (%{charLimit}) has been exceeded.',
+ ),
+ { charLimit: MAX_CHAR_LIMIT },
+ );
+ return;
+ }
+
// Remove any extra spans added by the backend syntax highlighting.
Object.assign(el, { textContent: source });
diff --git a/app/assets/javascripts/behaviors/markdown/schema.js b/app/assets/javascripts/behaviors/markdown/schema.js
new file mode 100644
index 00000000000..163182ab778
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/schema.js
@@ -0,0 +1,24 @@
+import { Schema } from 'prosemirror-model';
+import editorExtensions from './editor_extensions';
+
+const nodes = editorExtensions
+ .filter(extension => extension.type === 'node')
+ .reduce(
+ (ns, { name, schema }) => ({
+ ...ns,
+ [name]: schema,
+ }),
+ {},
+ );
+
+const marks = editorExtensions
+ .filter(extension => extension.type === 'mark')
+ .reduce(
+ (ms, { name, schema }) => ({
+ ...ms,
+ [name]: schema,
+ }),
+ {},
+ );
+
+export default new Schema({ nodes, marks });
diff --git a/app/assets/javascripts/behaviors/markdown/serializer.js b/app/assets/javascripts/behaviors/markdown/serializer.js
new file mode 100644
index 00000000000..70dbd8bd206
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/serializer.js
@@ -0,0 +1,24 @@
+import { MarkdownSerializer } from 'prosemirror-markdown';
+import editorExtensions from './editor_extensions';
+
+const nodes = editorExtensions
+ .filter(extension => extension.type === 'node')
+ .reduce(
+ (ns, { name, toMarkdown }) => ({
+ ...ns,
+ [name]: toMarkdown,
+ }),
+ {},
+ );
+
+const marks = editorExtensions
+ .filter(extension => extension.type === 'mark')
+ .reduce(
+ (ms, { name, toMarkdown }) => ({
+ ...ms,
+ [name]: toMarkdown,
+ }),
+ {},
+ );
+
+export default new MarkdownSerializer(nodes, marks);
diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js
index 35f1bb6b080..7adccbb062f 100644
--- a/app/assets/javascripts/behaviors/preview_markdown.js
+++ b/app/assets/javascripts/behaviors/preview_markdown.js
@@ -28,16 +28,13 @@ MarkdownPreview.prototype.ajaxCache = {};
MarkdownPreview.prototype.showPreview = function($form) {
var mdText;
- var markdownVersion;
- var url;
var preview = $form.find('.js-md-preview');
+ var url = preview.data('url');
if (preview.hasClass('md-preview-loading')) {
return;
}
mdText = $form.find('textarea.markdown-area').val();
- markdownVersion = $form.attr('data-markdown-version');
- url = this.versionedPreviewPath(preview.data('url'), markdownVersion);
if (mdText.trim().length === 0) {
preview.text(this.emptyMessage);
@@ -67,16 +64,6 @@ MarkdownPreview.prototype.showPreview = function($form) {
}
};
-MarkdownPreview.prototype.versionedPreviewPath = function(markdownPreviewPath, markdownVersion) {
- if (typeof markdownVersion === 'undefined') {
- return markdownPreviewPath;
- }
-
- return `${markdownPreviewPath}${
- markdownPreviewPath.indexOf('?') === -1 ? '?' : '&'
- }markdown_version=${markdownVersion}`;
-};
-
MarkdownPreview.prototype.fetchMarkdownPreview = function(text, url, success) {
if (!url) {
return;
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
index 2918e1486a7..680f2031409 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
@@ -1,6 +1,5 @@
import $ from 'jquery';
import Mousetrap from 'mousetrap';
-import _ from 'underscore';
import Sidebar from '../../right_sidebar';
import Shortcuts from './shortcuts';
import { CopyAsGFM } from '../markdown/copy_as_gfm';
@@ -63,28 +62,32 @@ export default class ShortcutsIssuable extends Shortcuts {
}
const el = CopyAsGFM.transformGFMSelection(documentFragment.cloneNode(true));
- const selected = CopyAsGFM.nodeToGFM(el);
-
- if (selected.trim() === '') {
- return false;
- }
-
- const quote = _.map(selected.split('\n'), val => `${`> ${val}`.trim()}\n`);
-
- // If replyField already has some content, add a newline before our quote
- const separator = ($replyField.val().trim() !== '' && '\n\n') || '';
- $replyField
- .val((a, current) => `${current}${separator}${quote.join('')}\n`)
- .trigger('input')
- .trigger('change');
-
- // Trigger autosize
- const event = document.createEvent('Event');
- event.initEvent('autosize:update', true, false);
- $replyField.get(0).dispatchEvent(event);
+ const blockquoteEl = document.createElement('blockquote');
+ blockquoteEl.appendChild(el);
+ CopyAsGFM.nodeToGFM(blockquoteEl)
+ .then(text => {
+ if (text.trim() === '') {
+ return false;
+ }
+
+ // If replyField already has some content, add a newline before our quote
+ const separator = ($replyField.val().trim() !== '' && '\n\n') || '';
+ $replyField
+ .val((a, current) => `${current}${separator}${text}\n\n`)
+ .trigger('input')
+ .trigger('change');
+
+ // Trigger autosize
+ const event = document.createEvent('Event');
+ event.initEvent('autosize:update', true, false);
+ $replyField.get(0).dispatchEvent(event);
+
+ // Focus the input field
+ $replyField.focus();
- // Focus the input field
- $replyField.focus();
+ return false;
+ })
+ .catch(() => {});
return false;
}
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index b07f951346e..5f64175362d 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -16,6 +16,7 @@ export default () => {
const filePath = editBlobForm.data('blobFilename');
const currentAction = $('.js-file-title').data('currentAction');
const projectId = editBlobForm.data('project-id');
+ const isMarkdown = editBlobForm.data('is-markdown');
const commitButton = $('.js-commit-button');
const cancelLink = $('.btn.btn-cancel');
@@ -27,7 +28,13 @@ export default () => {
window.onbeforeunload = null;
});
- new EditBlob(`${urlRoot}${assetsPath}`, filePath, currentAction, projectId);
+ new EditBlob({
+ assetsPath: `${urlRoot}${assetsPath}`,
+ filePath,
+ currentAction,
+ projectId,
+ isMarkdown,
+ });
new NewCommitForm(editBlobForm);
// returning here blocks page navigation
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index 6e19548eed2..011898a5e7a 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -6,22 +6,31 @@ import createFlash from '~/flash';
import { __ } from '~/locale';
import TemplateSelectorMediator from '../blob/file_template_mediator';
import getModeByFileExtension from '~/lib/utils/ace_utils';
+import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown';
export default class EditBlob {
- constructor(assetsPath, aceMode, currentAction, projectId) {
- this.configureAceEditor(aceMode, assetsPath);
+ // The options object has:
+ // assetsPath, filePath, currentAction, projectId, isMarkdown
+ constructor(options) {
+ this.options = options;
+ this.configureAceEditor();
this.initModePanesAndLinks();
this.initSoftWrap();
- this.initFileSelectors(currentAction, projectId);
+ this.initFileSelectors();
}
- configureAceEditor(filePath, assetsPath) {
+ configureAceEditor() {
+ const { filePath, assetsPath, isMarkdown } = this.options;
ace.config.set('modePath', `${assetsPath}/ace`);
ace.config.loadModule('ace/ext/searchbox');
ace.config.loadModule('ace/ext/modelist');
this.editor = ace.edit('editor');
+ if (isMarkdown) {
+ addEditorMarkdownListeners(this.editor);
+ }
+
// This prevents warnings re: automatic scrolling being logged
this.editor.$blockScrolling = Infinity;
@@ -32,7 +41,8 @@ export default class EditBlob {
}
}
- initFileSelectors(currentAction, projectId) {
+ initFileSelectors() {
+ const { currentAction, projectId } = this.options;
this.fileTemplateMediator = new TemplateSelectorMediator({
currentAction,
editor: this.editor,
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 30fbdb9e97f..f569322ab70 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -86,7 +86,7 @@ export default {
class="board-card"
@mousedown="mouseDown"
@mousemove="mouseMove"
- @mouseup="showIssue($event);"
+ @mouseup="showIssue($event)"
>
<issue-card-inner
:list="list"
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 93bcb4e129e..28d96dab605 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -96,7 +96,7 @@ export default {
<template>
<div class="board-new-issue-form">
<div class="board-card">
- <form @submit="submit($event);">
+ <form @submit="submit($event)">
<div v-if="error" class="flash-container">
<div class="flash-alert">An error occurred. Please try again.</div>
</div>
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index 0f581c3d37d..90ab3a76342 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -184,7 +184,7 @@ export default {
:title="label.description"
class="badge color-label append-right-4 prepend-top-4"
type="button"
- @click="filterByLabel(label);"
+ @click="filterByLabel(label)"
>
{{ label.title }}
</button>
diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue
index e038198e6f0..9bc66978198 100644
--- a/app/assets/javascripts/boards/components/issue_due_date.vue
+++ b/app/assets/javascripts/boards/components/issue_due_date.vue
@@ -3,7 +3,12 @@ import dateFormat from 'dateformat';
import { GlTooltip } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { __ } from '~/locale';
-import { getDayDifference, getTimeago, dateInWords } from '~/lib/utils/datetime_utility';
+import {
+ getDayDifference,
+ getTimeago,
+ dateInWords,
+ parsePikadayDate,
+} from '~/lib/utils/datetime_utility';
export default {
components: {
@@ -48,13 +53,13 @@ export default {
} else if (timeDifference === -1) {
return __('Yesterday');
} else if (timeDifference > 0 && timeDifference < 7) {
- return dateFormat(issueDueDate, 'dddd', true);
+ return dateFormat(issueDueDate, 'dddd');
}
return standardDateFormat;
},
issueDueDate() {
- return new Date(this.date);
+ return parsePikadayDate(this.date);
},
timeDifference() {
const today = new Date();
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue
index 08408eb0b52..2a0008467c4 100644
--- a/app/assets/javascripts/boards/components/modal/empty_state.vue
+++ b/app/assets/javascripts/boards/components/modal/empty_state.vue
@@ -45,7 +45,7 @@ export default {
<section class="empty-state">
<div class="row">
<div class="col-12 col-md-6 order-md-last">
- <aside class="svg-content"><img :src="emptyStateSvg" /></aside>
+ <aside class="svg-content d-none d-md-block"><img :src="emptyStateSvg" /></aside>
</div>
<div class="col-12 col-md-6 order-md-first">
<div class="text-content">
@@ -58,7 +58,7 @@ export default {
v-if="activeTab === 'selected'"
class="btn btn-default"
type="button"
- @click="changeTab('all');"
+ @click="changeTab('all')"
>
Open issues
</button>
diff --git a/app/assets/javascripts/boards/components/modal/footer.vue b/app/assets/javascripts/boards/components/modal/footer.vue
index b1bc7d87086..d4afd9d59da 100644
--- a/app/assets/javascripts/boards/components/modal/footer.vue
+++ b/app/assets/javascripts/boards/components/modal/footer.vue
@@ -71,7 +71,7 @@ export default {
<span class="inline add-issues-footer-to-list"> to list </span>
<lists-dropdown />
</div>
- <button class="btn btn-default float-right" type="button" @click="toggleModal(false);">
+ <button class="btn btn-default float-right" type="button" @click="toggleModal(false)">
Cancel
</button>
</footer>
diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue
index d0e285a149e..1f0961e02d8 100644
--- a/app/assets/javascripts/boards/components/modal/header.vue
+++ b/app/assets/javascripts/boards/components/modal/header.vue
@@ -58,7 +58,7 @@ export default {
class="close"
data-dismiss="modal"
aria-label="Close"
- @click="toggleModal(false);"
+ @click="toggleModal(false)"
>
<span aria-hidden="true">×</span>
</button>
diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue
index 878bb002c6c..e9ed2de859d 100644
--- a/app/assets/javascripts/boards/components/modal/list.vue
+++ b/app/assets/javascripts/boards/components/modal/list.vue
@@ -130,7 +130,7 @@ export default {
<div
:class="{ 'is-active': issue.selected }"
class="board-card"
- @click="toggleIssue($event, issue);"
+ @click="toggleIssue($event, issue)"
>
<issue-card-inner :issue="issue" :issue-link-base="issueLinkBase" :root-path="rootPath" />
<icon
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
index 820d0679df5..3fbe8fe1be7 100644
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
+++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
@@ -38,7 +38,7 @@ export default {
:class="{ 'is-active': list.id == selected.id }"
href="#"
role="button"
- @click.prevent="modal.selectedList = list;"
+ @click.prevent="modal.selectedList = list"
>
<span :style="{ backgroundColor: list.label.color }" class="dropdown-label-box"> </span>
{{ list.title }}
diff --git a/app/assets/javascripts/boards/components/modal/tabs.vue b/app/assets/javascripts/boards/components/modal/tabs.vue
index 7b800a6ab97..2d2920e312e 100644
--- a/app/assets/javascripts/boards/components/modal/tabs.vue
+++ b/app/assets/javascripts/boards/components/modal/tabs.vue
@@ -21,12 +21,12 @@ export default {
<div class="top-area prepend-top-10 append-bottom-10">
<ul class="nav-links issues-state-filters">
<li :class="{ active: activeTab == 'all' }">
- <a href="#" role="button" @click.prevent="changeTab('all');">
+ <a href="#" role="button" @click.prevent="changeTab('all')">
Open issues <span class="badge badge-pill"> {{ issuesCount }} </span>
</a>
</li>
<li :class="{ active: activeTab == 'selected' }">
- <a href="#" role="button" @click.prevent="changeTab('selected');">
+ <a href="#" role="button" @click.prevent="changeTab('selected')">
Selected issues <span class="badge badge-pill"> {{ selectedCount }} </span>
</a>
</li>
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index d899b7fbd8c..8274647744f 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -82,7 +82,7 @@ export default {
<template>
<div>
<label class="label-bold prepend-top-10"> Project </label>
- <div ref="projectsDropdown" class="dropdown">
+ <div ref="projectsDropdown" class="dropdown dropdown-projects">
<button
class="dropdown-menu-toggle wide"
type="button"
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index f88e9b55988..c4c5fedc615 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -58,6 +58,7 @@ export default () => {
state: boardsStore.state,
loading: true,
boardsEndpoint: $boardApp.dataset.boardsEndpoint,
+ recentBoardsEndpoint: $boardApp.dataset.recentBoardsEndpoint,
listsEndpoint: $boardApp.dataset.listsEndpoint,
boardId: $boardApp.dataset.boardId,
disabled: parseBoolean($boardApp.dataset.disabled),
@@ -75,6 +76,7 @@ export default () => {
created() {
gl.boardService = new BoardService({
boardsEndpoint: this.boardsEndpoint,
+ recentBoardsEndpoint: this.recentBoardsEndpoint,
listsEndpoint: this.listsEndpoint,
bulkUpdatePath: this.bulkUpdatePath,
boardId: this.boardId,
diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js
index dd3feedbc0e..9f6d9a853da 100644
--- a/app/assets/javascripts/boards/models/list.js
+++ b/app/assets/javascripts/boards/models/list.js
@@ -244,6 +244,7 @@ class List {
issue.project = data.project;
issue.path = data.real_path;
issue.referencePath = data.reference_path;
+ issue.assignableLabelsEndpoint = data.assignable_labels_endpoint;
if (this.issuesSize > 1) {
const moveBeforeId = this.issues[1].id;
diff --git a/app/assets/javascripts/boards/services/board_service.js b/app/assets/javascripts/boards/services/board_service.js
index 3de6eb056c2..7d463f17ab1 100644
--- a/app/assets/javascripts/boards/services/board_service.js
+++ b/app/assets/javascripts/boards/services/board_service.js
@@ -2,12 +2,13 @@ import axios from '../../lib/utils/axios_utils';
import { mergeUrlParams } from '../../lib/utils/url_utility';
export default class BoardService {
- constructor({ boardsEndpoint, listsEndpoint, bulkUpdatePath, boardId }) {
+ constructor({ boardsEndpoint, listsEndpoint, bulkUpdatePath, boardId, recentBoardsEndpoint }) {
this.boardsEndpoint = boardsEndpoint;
this.boardId = boardId;
this.listsEndpoint = listsEndpoint;
this.listsEndpointGenerate = `${listsEndpoint}/generate.json`;
this.bulkUpdatePath = bulkUpdatePath;
+ this.recentBoardsEndpoint = `${recentBoardsEndpoint}.json`;
}
generateBoardsPath(id) {
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index cf70a48f076..c59fac42038 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -1,12 +1,18 @@
import Visibility from 'visibilityjs';
import Vue from 'vue';
-import initDismissableCallout from '~/dismissable_callout';
+import PersistentUserCallout from '../persistent_user_callout';
import { s__, sprintf } from '../locale';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
import initSettingsPanels from '../settings_panels';
import eventHub from './event_hub';
-import { APPLICATION_STATUS, REQUEST_LOADING, REQUEST_SUCCESS, REQUEST_FAILURE } from './constants';
+import {
+ APPLICATION_STATUS,
+ REQUEST_SUBMITTED,
+ REQUEST_FAILURE,
+ UPGRADE_REQUESTED,
+ UPGRADE_REQUEST_FAILURE,
+} from './constants';
import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store';
import Applications from './components/applications.vue';
@@ -32,6 +38,7 @@ export default class Clusters {
installKnativePath,
installPrometheusPath,
managePrometheusPath,
+ hasRbac,
clusterType,
clusterStatus,
clusterStatusReason,
@@ -45,6 +52,7 @@ export default class Clusters {
this.store.setManagePrometheusPath(managePrometheusPath);
this.store.updateStatus(clusterStatus);
this.store.updateStatusReason(clusterStatusReason);
+ this.store.updateRbac(hasRbac);
this.service = new ClustersService({
endpoint: statusPath,
installHelmEndpoint: installHelmPath,
@@ -67,7 +75,7 @@ export default class Clusters {
this.showTokenButton = document.querySelector('.js-show-cluster-token');
this.tokenField = document.querySelector('.js-cluster-token');
- initDismissableCallout('.js-cluster-security-warning');
+ Clusters.initDismissableCallout();
initSettingsPanels();
setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area'));
this.initApplications(clusterType);
@@ -102,20 +110,32 @@ export default class Clusters {
ingressHelpPath: this.state.ingressHelpPath,
managePrometheusPath: this.state.managePrometheusPath,
ingressDnsHelpPath: this.state.ingressDnsHelpPath,
+ rbac: this.state.rbac,
},
});
},
});
}
+ static initDismissableCallout() {
+ const callout = document.querySelector('.js-cluster-security-warning');
+ PersistentUserCallout.factory(callout);
+ }
+
addListeners() {
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
eventHub.$on('installApplication', this.installApplication);
+ eventHub.$on('upgradeApplication', data => this.upgradeApplication(data));
+ eventHub.$on('upgradeFailed', appId => this.upgradeFailed(appId));
+ eventHub.$on('dismissUpgradeSuccess', appId => this.dismissUpgradeSuccess(appId));
}
removeListeners() {
if (this.showTokenButton) this.showTokenButton.removeEventListener('click', this.showToken);
eventHub.$off('installApplication', this.installApplication);
+ eventHub.$off('upgradeApplication', this.upgradeApplication);
+ eventHub.$off('upgradeFailed', this.upgradeFailed);
+ eventHub.$off('dismissUpgradeSuccess', this.dismissUpgradeSuccess);
}
initPolling() {
@@ -222,22 +242,33 @@ export default class Clusters {
installApplication(data) {
const appId = data.id;
- this.store.updateAppProperty(appId, 'requestStatus', REQUEST_LOADING);
+ this.store.updateAppProperty(appId, 'requestStatus', REQUEST_SUBMITTED);
this.store.updateAppProperty(appId, 'requestReason', null);
+ this.store.updateAppProperty(appId, 'statusReason', null);
+
+ this.service.installApplication(appId, data.params).catch(() => {
+ this.store.updateAppProperty(appId, 'requestStatus', REQUEST_FAILURE);
+ this.store.updateAppProperty(
+ appId,
+ 'requestReason',
+ s__('ClusterIntegration|Request to begin installing failed'),
+ );
+ });
+ }
+
+ upgradeApplication(data) {
+ const appId = data.id;
+ this.store.updateAppProperty(appId, 'requestStatus', UPGRADE_REQUESTED);
+ this.store.updateAppProperty(appId, 'status', APPLICATION_STATUS.UPDATING);
+ this.service.installApplication(appId, data.params).catch(() => this.upgradeFailed(appId));
+ }
+
+ upgradeFailed(appId) {
+ this.store.updateAppProperty(appId, 'requestStatus', UPGRADE_REQUEST_FAILURE);
+ }
- this.service
- .installApplication(appId, data.params)
- .then(() => {
- this.store.updateAppProperty(appId, 'requestStatus', REQUEST_SUCCESS);
- })
- .catch(() => {
- this.store.updateAppProperty(appId, 'requestStatus', REQUEST_FAILURE);
- this.store.updateAppProperty(
- appId,
- 'requestReason',
- s__('ClusterIntegration|Request to begin installing failed'),
- );
- });
+ dismissUpgradeSuccess(appId) {
+ this.store.updateAppProperty(appId, 'requestStatus', null);
}
destroy() {
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index d4354dcfebd..5952e93b9a7 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -1,20 +1,24 @@
<script>
/* eslint-disable vue/require-default-prop */
+import { GlLink } from '@gitlab/ui';
+import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
import { s__, sprintf } from '../../locale';
import eventHub from '../event_hub';
import identicon from '../../vue_shared/components/identicon.vue';
import loadingButton from '../../vue_shared/components/loading_button.vue';
import {
APPLICATION_STATUS,
- REQUEST_LOADING,
- REQUEST_SUCCESS,
+ REQUEST_SUBMITTED,
REQUEST_FAILURE,
+ UPGRADE_REQUESTED,
} from '../constants';
export default {
components: {
loadingButton,
identicon,
+ TimeagoTooltip,
+ GlLink,
},
props: {
id: {
@@ -59,6 +63,18 @@ export default {
type: String,
required: false,
},
+ version: {
+ type: String,
+ required: false,
+ },
+ chartRepo: {
+ type: String,
+ required: false,
+ },
+ upgradeAvailable: {
+ type: Boolean,
+ required: false,
+ },
installApplicationRequestParams: {
type: Object,
required: false,
@@ -72,11 +88,31 @@ export default {
isKnownStatus() {
return Object.values(APPLICATION_STATUS).includes(this.status);
},
+ isInstalling() {
+ return (
+ this.status === APPLICATION_STATUS.SCHEDULED ||
+ this.status === APPLICATION_STATUS.INSTALLING ||
+ (this.requestStatus === REQUEST_SUBMITTED && !this.statusReason && !this.isInstalled)
+ );
+ },
isInstalled() {
return (
this.status === APPLICATION_STATUS.INSTALLED ||
this.status === APPLICATION_STATUS.UPDATED ||
- this.status === APPLICATION_STATUS.UPDATING
+ this.status === APPLICATION_STATUS.UPDATING ||
+ this.status === APPLICATION_STATUS.UPDATE_ERRORED
+ );
+ },
+ canInstall() {
+ if (this.isInstalling) {
+ return false;
+ }
+
+ return (
+ this.status === APPLICATION_STATUS.NOT_INSTALLABLE ||
+ this.status === APPLICATION_STATUS.INSTALLABLE ||
+ this.status === APPLICATION_STATUS.ERROR ||
+ this.isUnknownStatus
);
},
hasLogo() {
@@ -90,12 +126,7 @@ export default {
return `js-cluster-application-row-${this.id}`;
},
installButtonLoading() {
- return (
- !this.status ||
- this.status === APPLICATION_STATUS.SCHEDULED ||
- this.status === APPLICATION_STATUS.INSTALLING ||
- this.requestStatus === REQUEST_LOADING
- );
+ return !this.status || this.status === APPLICATION_STATUS.SCHEDULED || this.isInstalling;
},
installButtonDisabled() {
// Avoid the potential for the real-time data to say APPLICATION_STATUS.INSTALLABLE but
@@ -104,30 +135,17 @@ export default {
return (
((this.status !== APPLICATION_STATUS.INSTALLABLE &&
this.status !== APPLICATION_STATUS.ERROR) ||
- this.requestStatus === REQUEST_LOADING ||
- this.requestStatus === REQUEST_SUCCESS) &&
+ this.isInstalling) &&
this.isKnownStatus
);
},
installButtonLabel() {
let label;
- if (
- this.status === APPLICATION_STATUS.NOT_INSTALLABLE ||
- this.status === APPLICATION_STATUS.INSTALLABLE ||
- this.status === APPLICATION_STATUS.ERROR ||
- this.isUnknownStatus
- ) {
+ if (this.canInstall) {
label = s__('ClusterIntegration|Install');
- } else if (
- this.status === APPLICATION_STATUS.SCHEDULED ||
- this.status === APPLICATION_STATUS.INSTALLING
- ) {
+ } else if (this.isInstalling) {
label = s__('ClusterIntegration|Installing');
- } else if (
- this.status === APPLICATION_STATUS.INSTALLED ||
- this.status === APPLICATION_STATUS.UPDATED ||
- this.status === APPLICATION_STATUS.UPDATING
- ) {
+ } else if (this.isInstalled) {
label = s__('ClusterIntegration|Installed');
}
@@ -140,13 +158,79 @@ export default {
return s__('ClusterIntegration|Manage');
},
hasError() {
- return this.status === APPLICATION_STATUS.ERROR || this.requestStatus === REQUEST_FAILURE;
+ return (
+ !this.isInstalling &&
+ (this.status === APPLICATION_STATUS.ERROR || this.requestStatus === REQUEST_FAILURE)
+ );
},
generalErrorDescription() {
return sprintf(s__('ClusterIntegration|Something went wrong while installing %{title}'), {
title: this.title,
});
},
+ versionLabel() {
+ if (this.upgradeFailed) {
+ return s__('ClusterIntegration|Upgrade failed');
+ } else if (this.isUpgrading) {
+ return s__('ClusterIntegration|Upgrading');
+ }
+
+ return s__('ClusterIntegration|Upgraded');
+ },
+ upgradeRequested() {
+ return this.requestStatus === UPGRADE_REQUESTED;
+ },
+ upgradeSuccessful() {
+ return this.status === APPLICATION_STATUS.UPDATED;
+ },
+ upgradeFailed() {
+ if (this.isUpgrading) {
+ return false;
+ }
+
+ return this.status === APPLICATION_STATUS.UPDATE_ERRORED;
+ },
+ upgradeFailureDescription() {
+ return sprintf(
+ s__(
+ 'ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again.',
+ ),
+ {
+ title: this.title,
+ },
+ );
+ },
+ upgradeSuccessDescription() {
+ return sprintf(s__('ClusterIntegration|%{title} upgraded successfully.'), {
+ title: this.title,
+ });
+ },
+ upgradeButtonLabel() {
+ let label;
+ if (this.upgradeAvailable && !this.upgradeFailed && !this.isUpgrading) {
+ label = s__('ClusterIntegration|Upgrade');
+ } else if (this.isUpgrading) {
+ label = s__('ClusterIntegration|Upgrading');
+ } else if (this.upgradeFailed) {
+ label = s__('ClusterIntegration|Retry upgrade');
+ }
+
+ return label;
+ },
+ isUpgrading() {
+ // Since upgrading is handled asynchronously on the backend we need this check to prevent any delay on the frontend
+ return (
+ this.status === APPLICATION_STATUS.UPDATING ||
+ (this.upgradeRequested && !this.upgradeSuccessful)
+ );
+ },
+ },
+ watch: {
+ status() {
+ if (this.status === APPLICATION_STATUS.UPDATE_ERRORED) {
+ eventHub.$emit('upgradeFailed', this.id);
+ }
+ },
},
methods: {
installClicked() {
@@ -155,6 +239,15 @@ export default {
params: this.installApplicationRequestParams,
});
},
+ upgradeClicked() {
+ eventHub.$emit('upgradeApplication', {
+ id: this.id,
+ params: this.installApplicationRequestParams,
+ });
+ },
+ dismissUpgradeSuccess() {
+ eventHub.$emit('dismissUpgradeSuccess', this.id);
+ },
},
};
</script>
@@ -208,6 +301,51 @@ export default {
</li>
</ul>
</div>
+
+ <div
+ v-if="(upgradeSuccessful || upgradeFailed) && !upgradeAvailable"
+ class="form-text text-muted label p-0 js-cluster-application-upgrade-details"
+ >
+ {{ versionLabel }}
+
+ <span v-if="upgradeSuccessful"> to</span>
+
+ <gl-link
+ v-if="upgradeSuccessful"
+ :href="chartRepo"
+ target="_blank"
+ class="js-cluster-application-upgrade-version"
+ >
+ chart v{{ version }}
+ </gl-link>
+ </div>
+
+ <div
+ v-if="upgradeFailed && !isUpgrading"
+ class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-upgrade-failure-message"
+ >
+ {{ upgradeFailureDescription }}
+ </div>
+
+ <div
+ v-if="upgradeRequested && upgradeSuccessful"
+ class="bs-callout bs-callout-success cluster-application-banner mt-2 mb-0 p-0 pl-3"
+ >
+ {{ upgradeSuccessDescription }}
+
+ <button class="close cluster-application-banner-close" @click="dismissUpgradeSuccess">
+ &times;
+ </button>
+ </div>
+
+ <loading-button
+ v-if="upgradeAvailable || upgradeFailed || isUpgrading"
+ class="btn btn-primary js-cluster-application-upgrade-button mt-2"
+ :loading="isUpgrading"
+ :disabled="isUpgrading"
+ :label="upgradeButtonLabel"
+ @click="upgradeClicked"
+ />
</div>
<div
:class="{ 'section-25': showManageButton, 'section-15': !showManageButton }"
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index 489615f1f78..0cf187d4189 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -52,6 +52,11 @@ export default {
required: false,
default: '',
},
+ rbac: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data: () => ({
elasticsearchLogo,
@@ -357,6 +362,9 @@ export default {
:status-reason="applications.runner.statusReason"
:request-status="applications.runner.requestStatus"
:request-reason="applications.runner.requestReason"
+ :version="applications.runner.version"
+ :chart-repo="applications.runner.chartRepo"
+ :upgrade-available="applications.runner.upgradeAvailable"
:disabled="!helmInstalled"
title-link="https://docs.gitlab.com/runner/"
>
@@ -442,6 +450,18 @@ export default {
title-link="https://github.com/knative/docs"
>
<div slot="description">
+ <span v-if="!rbac">
+ <p v-if="!rbac" class="bs-callout bs-callout-info append-bottom-0">
+ {{
+ s__(`ClusterIntegration|You must have an RBAC-enabled cluster
+ to install Knative.`)
+ }}
+ <a :href="helpPath" target="_blank" rel="noopener noreferrer">
+ {{ __('More information') }}
+ </a>
+ </p>
+ <br />
+ </span>
<p>
{{
s__(`ClusterIntegration|Knative extends Kubernetes to provide
@@ -465,7 +485,7 @@ export default {
/>
</div>
</template>
- <template v-else-if="helmInstalled">
+ <template v-else-if="helmInstalled && rbac">
<div class="form-group">
<label for="knative-domainname">
{{ s__('ClusterIntegration|Knative Domain Name:') }}
diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js
index e31afadf186..39022879d91 100644
--- a/app/assets/javascripts/clusters/constants.js
+++ b/app/assets/javascripts/clusters/constants.js
@@ -12,16 +12,19 @@ export const APPLICATION_STATUS = {
SCHEDULED: 'scheduled',
INSTALLING: 'installing',
INSTALLED: 'installed',
- UPDATED: 'updated',
UPDATING: 'updating',
+ UPDATED: 'updated',
+ UPDATE_ERRORED: 'update_errored',
ERROR: 'errored',
};
// These are only used client-side
-export const REQUEST_LOADING = 'request-loading';
-export const REQUEST_SUCCESS = 'request-success';
+export const REQUEST_SUBMITTED = 'request-submitted';
export const REQUEST_FAILURE = 'request-failure';
+export const UPGRADE_REQUESTED = 'upgrade-requested';
+export const UPGRADE_REQUEST_FAILURE = 'upgrade-request-failure';
export const INGRESS = 'ingress';
export const JUPYTER = 'jupyter';
export const KNATIVE = 'knative';
+export const RUNNER = 'runner';
export const CERT_MANAGER = 'cert_manager';
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index c750daab112..d309678be27 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -1,5 +1,6 @@
import { s__ } from '../../locale';
-import { INGRESS, JUPYTER, KNATIVE, CERT_MANAGER } from '../constants';
+import { parseBoolean } from '../../lib/utils/common_utils';
+import { INGRESS, JUPYTER, KNATIVE, CERT_MANAGER, RUNNER } from '../constants';
export default class ClusterStore {
constructor() {
@@ -7,6 +8,7 @@ export default class ClusterStore {
helpPath: null,
ingressHelpPath: null,
status: null,
+ rbac: false,
statusReason: null,
applications: {
helm: {
@@ -38,6 +40,9 @@ export default class ClusterStore {
statusReason: null,
requestStatus: null,
requestReason: null,
+ version: null,
+ chartRepo: 'https://gitlab.com/charts/gitlab-runner',
+ upgradeAvailable: null,
},
prometheus: {
title: s__('ClusterIntegration|Prometheus'),
@@ -81,6 +86,10 @@ export default class ClusterStore {
this.state.status = status;
}
+ updateRbac(rbac) {
+ this.state.rbac = parseBoolean(rbac);
+ }
+
updateStatusReason(reason) {
this.state.statusReason = reason;
}
@@ -94,7 +103,13 @@ export default class ClusterStore {
this.state.statusReason = serverState.status_reason;
serverState.applications.forEach(serverAppEntry => {
- const { name: appId, status, status_reason: statusReason } = serverAppEntry;
+ const {
+ name: appId,
+ status,
+ status_reason: statusReason,
+ version,
+ update_available: upgradeAvailable,
+ } = serverAppEntry;
this.state.applications[appId] = {
...(this.state.applications[appId] || {}),
@@ -118,6 +133,9 @@ export default class ClusterStore {
serverAppEntry.hostname || this.state.applications.knative.hostname;
this.state.applications.knative.externalIp =
serverAppEntry.external_ip || this.state.applications.knative.externalIp;
+ } else if (appId === RUNNER) {
+ this.state.applications.runner.version = version;
+ this.state.applications.runner.upgradeAvailable = upgradeAvailable;
}
});
}
diff --git a/app/assets/javascripts/commons/jquery.js b/app/assets/javascripts/commons/jquery.js
index a7ed175f7a4..009153d0703 100644
--- a/app/assets/javascripts/commons/jquery.js
+++ b/app/assets/javascripts/commons/jquery.js
@@ -7,4 +7,3 @@ import 'vendor/jquery.caret';
import 'vendor/jquery.atwho';
import 'vendor/jquery.scrollTo';
import 'jquery.waitforimages';
-import 'select2/select2';
diff --git a/app/assets/javascripts/contextual_sidebar.js b/app/assets/javascripts/contextual_sidebar.js
index 10f02739ec8..67fcdd082a2 100644
--- a/app/assets/javascripts/contextual_sidebar.js
+++ b/app/assets/javascripts/contextual_sidebar.js
@@ -4,6 +4,10 @@ import _ from 'underscore';
import bp from './breakpoints';
import { parseBoolean } from '~/lib/utils/common_utils';
+// NOTE: at 1200px nav sidebar should not overlap the content
+// https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24555#note_134136110
+const NAV_SIDEBAR_BREAKPOINT = 1200;
+
export default class ContextualSidebar {
constructor() {
this.initDomElements();
@@ -13,6 +17,9 @@ export default class ContextualSidebar {
initDomElements() {
this.$page = $('.layout-page');
this.$sidebar = $('.nav-sidebar');
+
+ if (!this.$sidebar.length) return;
+
this.$innerScroll = $('.nav-sidebar-inner-scroll', this.$sidebar);
this.$overlay = $('.mobile-overlay');
this.$openSidebar = $('.toggle-mobile-nav');
@@ -21,48 +28,63 @@ export default class ContextualSidebar {
}
bindEvents() {
- document.addEventListener('click', e => {
- if (
- !e.target.closest('.nav-sidebar') &&
- (bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md')
- ) {
- this.toggleCollapsedSidebar(true);
- }
- });
+ if (!this.$sidebar.length) return;
+
this.$openSidebar.on('click', () => this.toggleSidebarNav(true));
this.$closeSidebar.on('click', () => this.toggleSidebarNav(false));
this.$overlay.on('click', () => this.toggleSidebarNav(false));
this.$sidebarToggle.on('click', () => {
- const value = !this.$sidebar.hasClass('sidebar-collapsed-desktop');
- this.toggleCollapsedSidebar(value);
+ if (!ContextualSidebar.isDesktopBreakpoint()) {
+ this.toggleSidebarNav(!this.$sidebar.hasClass('sidebar-expanded-mobile'));
+ } else {
+ const value = !this.$sidebar.hasClass('sidebar-collapsed-desktop');
+ this.toggleCollapsedSidebar(value, true);
+ }
});
$(window).on('resize', () => _.debounce(this.render(), 100));
}
+ // TODO: use the breakpoints from breakpoints.js once they have been updated for bootstrap 4
+ // See documentation: https://design.gitlab.com/regions/navigation#contextual-navigation
+ static isDesktopBreakpoint = () => bp.windowWidth() >= NAV_SIDEBAR_BREAKPOINT;
static setCollapsedCookie(value) {
- if (bp.getBreakpointSize() !== 'lg') {
+ if (!ContextualSidebar.isDesktopBreakpoint()) {
return;
}
Cookies.set('sidebar_collapsed', value, { expires: 365 * 10 });
}
toggleSidebarNav(show) {
- this.$sidebar.toggleClass('sidebar-expanded-mobile', show);
- this.$overlay.toggleClass('mobile-nav-open', show);
+ const breakpoint = bp.getBreakpointSize();
+ const dbp = ContextualSidebar.isDesktopBreakpoint();
+
+ this.$sidebar.toggleClass('sidebar-expanded-mobile', !dbp ? show : false);
+ this.$overlay.toggleClass(
+ 'mobile-nav-open',
+ breakpoint === 'xs' || breakpoint === 'sm' ? show : false,
+ );
this.$sidebar.removeClass('sidebar-collapsed-desktop');
}
- toggleCollapsedSidebar(collapsed) {
+ toggleCollapsedSidebar(collapsed, saveCookie) {
const breakpoint = bp.getBreakpointSize();
+ const dbp = ContextualSidebar.isDesktopBreakpoint();
if (this.$sidebar.length) {
this.$sidebar.toggleClass('sidebar-collapsed-desktop', collapsed);
- this.$page.toggleClass('page-with-icon-sidebar', breakpoint === 'sm' ? true : collapsed);
+ this.$sidebar.toggleClass('sidebar-expanded-mobile', !dbp ? !collapsed : false);
+ this.$page.toggleClass(
+ 'page-with-icon-sidebar',
+ breakpoint === 'xs' || breakpoint === 'sm' ? true : collapsed,
+ );
+ }
+
+ if (saveCookie) {
+ ContextualSidebar.setCollapsedCookie(collapsed);
}
- ContextualSidebar.setCollapsedCookie(collapsed);
- this.toggleSidebarOverflow();
+ requestIdleCallback(() => this.toggleSidebarOverflow());
}
toggleSidebarOverflow() {
@@ -74,13 +96,13 @@ export default class ContextualSidebar {
}
render() {
- const breakpoint = bp.getBreakpointSize();
+ if (!this.$sidebar.length) return;
- if (breakpoint === 'sm' || breakpoint === 'md') {
- this.toggleCollapsedSidebar(true);
- } else if (breakpoint === 'lg') {
+ if (!ContextualSidebar.isDesktopBreakpoint()) {
+ this.toggleSidebarNav(false);
+ } else {
const collapse = parseBoolean(Cookies.get('sidebar_collapsed'));
- this.toggleCollapsedSidebar(collapse);
+ this.toggleCollapsedSidebar(collapse, true);
}
}
}
diff --git a/app/assets/javascripts/deploy_keys/components/key.vue b/app/assets/javascripts/deploy_keys/components/key.vue
index f01e6f2a639..6ffb8c4e1c0 100644
--- a/app/assets/javascripts/deploy_keys/components/key.vue
+++ b/app/assets/javascripts/deploy_keys/components/key.vue
@@ -113,7 +113,7 @@ export default {
<div class="gl-responsive-table-row deploy-key">
<div class="table-section section-40">
<div role="rowheader" class="table-mobile-header">{{ s__('DeployKeys|Deploy key') }}</div>
- <div class="table-mobile-content">
+ <div class="table-mobile-content qa-key">
<strong class="title qa-key-title"> {{ deployKey.title }} </strong>
<div class="fingerprint qa-key-fingerprint">{{ deployKey.fingerprint }}</div>
</div>
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index d4c1b07093d..1fc2b7fe859 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -4,6 +4,8 @@ import Icon from '~/vue_shared/components/icon.vue';
import { __ } from '~/locale';
import createFlash from '~/flash';
import { GlLoadingIcon } from '@gitlab/ui';
+import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
+import Mousetrap from 'mousetrap';
import eventHub from '../../notes/event_hub';
import CompareVersions from './compare_versions.vue';
import DiffFile from './diff_file.vue';
@@ -11,6 +13,13 @@ import NoChanges from './no_changes.vue';
import HiddenFilesWarning from './hidden_files_warning.vue';
import CommitWidget from './commit_widget.vue';
import TreeList from './tree_list.vue';
+import {
+ TREE_LIST_WIDTH_STORAGE_KEY,
+ INITIAL_TREE_WIDTH,
+ MIN_TREE_WIDTH,
+ MAX_TREE_WIDTH,
+ TREE_HIDE_STATS_WIDTH,
+} from '../constants';
export default {
name: 'DiffsApp',
@@ -23,6 +32,7 @@ export default {
CommitWidget,
TreeList,
GlLoadingIcon,
+ PanelResizer,
},
props: {
endpoint: {
@@ -54,8 +64,12 @@ export default {
},
},
data() {
+ const treeWidth =
+ parseInt(localStorage.getItem(TREE_LIST_WIDTH_STORAGE_KEY), 10) || INITIAL_TREE_WIDTH;
+
return {
assignedDiscussions: false,
+ treeWidth,
};
},
computed: {
@@ -74,7 +88,7 @@ export default {
emailPatchPath: state => state.diffs.emailPatchPath,
}),
...mapState('diffs', ['showTreeList', 'isLoading', 'startVersion']),
- ...mapGetters('diffs', ['isParallelView']),
+ ...mapGetters('diffs', ['isParallelView', 'currentDiffIndex']),
...mapGetters(['isNotesFetched', 'getNoteableData']),
targetBranch() {
return {
@@ -96,6 +110,9 @@ export default {
this.startVersion.version_index === this.mergeRequestDiff.version_index)
);
},
+ hideFileStats() {
+ return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
+ },
},
watch: {
diffViewType() {
@@ -129,6 +146,11 @@ export default {
created() {
this.adjustView();
eventHub.$once('fetchedNotesData', this.setDiscussions);
+ eventHub.$once('fetchDiffData', this.fetchData);
+ },
+ beforeDestroy() {
+ eventHub.$off('fetchDiffData', this.fetchData);
+ this.removeEventListeners();
},
methods: {
...mapActions(['startTaskList']),
@@ -138,6 +160,8 @@ export default {
'startRenderDiffsQueue',
'assignDiscussionsToDiff',
'setHighlightedRow',
+ 'cacheTreeListWidth',
+ 'scrollToFile',
]),
fetchData() {
this.fetchDiffFiles()
@@ -176,10 +200,40 @@ export default {
this.$nextTick(() => {
window.mrTabs.resetViewContainer();
window.mrTabs.expandViewContainer(this.showTreeList);
+ this.setEventListeners();
});
+ } else {
+ this.removeEventListeners();
+ }
+ },
+ setEventListeners() {
+ Mousetrap.bind(['[', 'k', ']', 'j'], (e, combo) => {
+ switch (combo) {
+ case '[':
+ case 'k':
+ this.jumpToFile(-1);
+ break;
+ case ']':
+ case 'j':
+ this.jumpToFile(+1);
+ break;
+ default:
+ break;
+ }
+ });
+ },
+ removeEventListeners() {
+ Mousetrap.unbind(['[', 'k', ']', 'j']);
+ },
+ jumpToFile(step) {
+ const targetIndex = this.currentDiffIndex + step;
+ if (targetIndex >= 0 && targetIndex < this.diffFiles.length) {
+ this.scrollToFile(this.diffFiles[targetIndex].file_path);
}
},
},
+ minTreeWidth: MIN_TREE_WIDTH,
+ maxTreeWidth: MAX_TREE_WIDTH,
};
</script>
@@ -205,7 +259,21 @@ export default {
:data-can-create-note="getNoteableData.current_user.can_create_note"
class="files d-flex prepend-top-default"
>
- <div v-show="showTreeList" class="diff-tree-list"><tree-list /></div>
+ <div
+ v-show="showTreeList"
+ :style="{ width: `${treeWidth}px` }"
+ class="diff-tree-list js-diff-tree-list"
+ >
+ <panel-resizer
+ :size.sync="treeWidth"
+ :start-size="treeWidth"
+ :min-size="$options.minTreeWidth"
+ :max-size="$options.maxTreeWidth"
+ side="right"
+ @resize-end="cacheTreeListWidth"
+ />
+ <tree-list :hide-file-stats="hideFileStats" />
+ </div>
<div class="diff-files-holder">
<commit-widget v-if="commit" :commit="commit" />
<template v-if="renderDiffFiles">
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index ebc4a83af4d..c02a8740a42 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -5,6 +5,7 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CIIcon from '~/vue_shared/components/ci_icon.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
+import initUserPopovers from '../../user_popovers';
/**
* CommitItem
@@ -35,20 +36,30 @@ export default {
},
},
computed: {
+ author() {
+ return this.commit.author || {};
+ },
authorName() {
- return (this.commit.author && this.commit.author.name) || this.commit.author_name;
+ return this.author.name || this.commit.author_name;
+ },
+ authorClass() {
+ return this.author.name ? 'js-user-link' : '';
+ },
+ authorId() {
+ return this.author.id ? this.author.id : '';
},
authorUrl() {
- return (
- (this.commit.author && this.commit.author.web_url) || `mailto:${this.commit.author_email}`
- );
+ return this.author.web_url || `mailto:${this.commit.author_email}`;
},
authorAvatar() {
- return (
- (this.commit.author && this.commit.author.avatar_url) || this.commit.author_gravatar_url
- );
+ return this.author.avatar_url || this.commit.author_gravatar_url;
},
},
+ created() {
+ this.$nextTick(() => {
+ initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
+ });
+ },
};
</script>
@@ -81,7 +92,13 @@ export default {
</button>
<div class="commiter">
- <a :href="authorUrl" v-text="authorName"></a> {{ s__('CommitWidget|authored') }}
+ <a
+ :href="authorUrl"
+ :class="authorClass"
+ :data-user-id="authorId"
+ v-text="authorName"
+ ></a>
+ {{ s__('CommitWidget|authored') }}
<time-ago-tooltip :time="commit.authored_date" />
</div>
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index f75345d31f8..0bf2dde8b96 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -2,9 +2,11 @@
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
-import { getParameterValues, mergeUrlParams } from '~/lib/utils/url_utility';
+import { polyfillSticky } from '~/lib/utils/sticky';
import Icon from '~/vue_shared/components/icon.vue';
import CompareVersionsDropdown from './compare_versions_dropdown.vue';
+import SettingsDropdown from './settings_dropdown.vue';
+import DiffStats from './diff_stats.vue';
export default {
components: {
@@ -12,6 +14,8 @@ export default {
Icon,
GlLink,
GlButton,
+ SettingsDropdown,
+ DiffStats,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -33,27 +37,33 @@ export default {
},
},
computed: {
- ...mapState('diffs', ['commit', 'showTreeList', 'startVersion', 'latestVersionPath']),
- ...mapGetters('diffs', ['isInlineView', 'isParallelView', 'hasCollapsedFile']),
+ ...mapGetters('diffs', ['hasCollapsedFile', 'diffFilesLength']),
+ ...mapState('diffs', [
+ 'commit',
+ 'showTreeList',
+ 'startVersion',
+ 'latestVersionPath',
+ 'addedLines',
+ 'removedLines',
+ ]),
comparableDiffs() {
return this.mergeRequestDiffs.slice(1);
},
- toggleWhitespaceText() {
- if (this.isWhitespaceVisible()) {
- return __('Hide whitespace changes');
- }
- return __('Show whitespace changes');
- },
- toggleWhitespacePath() {
- if (this.isWhitespaceVisible()) {
- return mergeUrlParams({ w: 1 }, window.location.href);
- }
-
- return mergeUrlParams({ w: 0 }, window.location.href);
- },
showDropdowns() {
return !this.commit && this.mergeRequestDiffs.length;
},
+ fileTreeIcon() {
+ return this.showTreeList ? 'collapse-left' : 'expand-left';
+ },
+ toggleFileBrowserTitle() {
+ return this.showTreeList ? __('Hide file browser') : __('Show file browser');
+ },
+ baseVersionPath() {
+ return this.mergeRequestDiff.base_version_path;
+ },
+ },
+ mounted() {
+ polyfillSticky(this.$el);
},
methods: {
...mapActions('diffs', [
@@ -62,15 +72,12 @@ export default {
'expandAllFiles',
'toggleShowTreeList',
]),
- isWhitespaceVisible() {
- return getParameterValues('w')[0] !== '1';
- },
},
};
</script>
<template>
- <div class="mr-version-controls">
+ <div class="mr-version-controls" :class="{ 'is-fileTreeOpen': showTreeList }">
<div class="mr-version-menus-container content-block">
<button
v-gl-tooltip.hover
@@ -79,10 +86,10 @@ export default {
:class="{
active: showTreeList,
}"
- :title="__('Toggle file browser')"
+ :title="toggleFileBrowserTitle"
@click="toggleShowTreeList"
>
- <icon name="hamburger" />
+ <icon :name="fileTreeIcon" />
</button>
<div v-if="showDropdowns" class="d-flex align-items-center compare-versions-container">
Changes between
@@ -95,6 +102,7 @@ export default {
and
<compare-versions-dropdown
:other-versions="comparableDiffs"
+ :base-version-path="baseVersionPath"
:start-version="startVersion"
:target-branch="targetBranch"
class="mr-version-compare-dropdown"
@@ -105,6 +113,11 @@ export default {
<gl-link :href="commit.commit_url" class="monospace">{{ commit.short_id }}</gl-link>
</div>
<div class="inline-parallel-buttons d-none d-md-flex ml-auto">
+ <diff-stats
+ :diff-files-length="diffFilesLength"
+ :added-lines="addedLines"
+ :removed-lines="removedLines"
+ />
<gl-button
v-if="commit || startVersion"
:href="latestVersionPath"
@@ -115,31 +128,7 @@ export default {
<a v-show="hasCollapsedFile" class="btn btn-default append-right-8" @click="expandAllFiles">
{{ __('Expand all') }}
</a>
- <a :href="toggleWhitespacePath" class="btn btn-default qa-toggle-whitespace">
- {{ toggleWhitespaceText }}
- </a>
- <div class="btn-group prepend-left-8">
- <button
- id="inline-diff-btn"
- :class="{ active: isInlineView }"
- type="button"
- class="btn js-inline-diff-button"
- data-view-type="inline"
- @click="setInlineDiffViewType"
- >
- {{ __('Inline') }}
- </button>
- <button
- id="parallel-diff-btn"
- :class="{ active: isParallelView }"
- type="button"
- class="btn js-parallel-diff-button"
- data-view-type="parallel"
- @click="setParallelDiffViewType"
- >
- {{ __('Side-by-side') }}
- </button>
- </div>
+ <settings-dropdown />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue b/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
index 8da02ed0b7c..80aec84f574 100644
--- a/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
@@ -34,14 +34,13 @@ export default {
required: false,
default: false,
},
+ baseVersionPath: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
computed: {
- baseVersion() {
- return {
- name: 'hii',
- versionIndex: -1,
- };
- },
targetVersions() {
if (this.mergeRequestVersion) {
return this.otherVersions;
@@ -62,6 +61,9 @@ export default {
);
},
href(version) {
+ if (this.isBase(version)) {
+ return this.baseVersionPath;
+ }
if (this.showCommitCount) {
return version.version_path;
}
@@ -129,7 +131,7 @@ export default {
</strong>
</div>
<div>
- <small class="commit-sha"> {{ version.truncated_commit_sha }} </small>
+ <small class="commit-sha"> {{ version.short_commit_sha }} </small>
</div>
<div>
<small>
@@ -139,7 +141,7 @@ export default {
<time-ago
v-if="version.created_at"
:time="version.created_at"
- class="js-timeago js-timeago-render"
+ class="js-timeago"
/>
</small>
</div>
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index 42d09e44768..cb92093db32 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -1,7 +1,8 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
-import EmptyFileViewer from '~/vue_shared/components/diff_viewer/viewers/empty_file.vue';
+import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
+import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
import InlineDiffView from './inline_diff_view.vue';
import ParallelDiffView from './parallel_diff_view.vue';
import NoteForm from '../../notes/components/note_form.vue';
@@ -9,6 +10,7 @@ import ImageDiffOverlay from './image_diff_overlay.vue';
import DiffDiscussions from './diff_discussions.vue';
import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
import { getDiffMode } from '../store/utils';
+import { diffViewerModes } from '~/ide/constants';
export default {
components: {
@@ -18,7 +20,8 @@ export default {
NoteForm,
DiffDiscussions,
ImageDiffOverlay,
- EmptyFileViewer,
+ NotDiffableViewer,
+ NoPreviewViewer,
},
props: {
diffFile: {
@@ -42,8 +45,17 @@ export default {
diffMode() {
return getDiffMode(this.diffFile);
},
+ diffViewerMode() {
+ return this.diffFile.viewer.name;
+ },
isTextFile() {
- return this.diffFile.viewer.name === 'text';
+ return this.diffViewerMode === diffViewerModes.text;
+ },
+ noPreview() {
+ return this.diffViewerMode === diffViewerModes.no_preview;
+ },
+ notDiffable() {
+ return this.diffViewerMode === diffViewerModes.not_diffable;
},
diffFileCommentForm() {
return this.getCommentFormForDiffFile(this.diffFile.file_hash);
@@ -77,9 +89,8 @@ export default {
<div class="diff-content">
<div class="diff-viewer">
<template v-if="isTextFile">
- <empty-file-viewer v-if="diffFile.empty" />
<inline-diff-view
- v-else-if="isInlineView"
+ v-if="isInlineView"
:diff-file="diffFile"
:diff-lines="diffFile.highlighted_diff_lines || []"
:help-page-path="helpPagePath"
@@ -91,9 +102,12 @@ export default {
:help-page-path="helpPagePath"
/>
</template>
+ <not-diffable-viewer v-else-if="notDiffable" />
+ <no-preview-viewer v-else-if="noPreview" />
<diff-viewer
v-else
:diff-mode="diffMode"
+ :diff-viewer-mode="diffViewerMode"
:new-path="diffFile.new_path"
:new-sha="diffFile.diff_refs.head_sha"
:old-path="diffFile.old_path"
@@ -124,7 +138,7 @@ export default {
:save-button-title="__('Comment')"
class="diff-comment-form new-note discussion-form discussion-form-container"
@handleFormUpdate="handleSaveNote"
- @cancelForm="closeDiffFileCommentForm(diffFile.file_hash);"
+ @cancelForm="closeDiffFileCommentForm(diffFile.file_hash)"
/>
</div>
</diff-viewer>
diff --git a/app/assets/javascripts/diffs/components/diff_discussions.vue b/app/assets/javascripts/diffs/components/diff_discussions.vue
index b2021cd6061..4c73eea4049 100644
--- a/app/assets/javascripts/diffs/components/diff_discussions.vue
+++ b/app/assets/javascripts/diffs/components/diff_discussions.vue
@@ -68,7 +68,7 @@ export default {
}"
type="button"
class="js-diff-notes-toggle"
- @click="toggleDiscussion({ discussionId: discussion.id });"
+ @click="toggleDiscussion({ discussionId: discussion.id })"
>
<icon v-if="discussion.expanded" name="collapse" class="collapse-icon" />
<template v-else>
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index 449f7007077..1141a197c6a 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -7,6 +7,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../../notes/event_hub';
import DiffFileHeader from './diff_file_header.vue';
import DiffContent from './diff_content.vue';
+import { diffViewerErrors } from '~/ide/constants';
export default {
components: {
@@ -33,15 +34,13 @@ export default {
return {
isLoadingCollapsedDiff: false,
forkMessageVisible: false,
+ isCollapsed: this.file.viewer.collapsed || false,
};
},
computed: {
...mapState('diffs', ['currentDiffFileId']),
...mapGetters(['isNotesFetched']),
...mapGetters('diffs', ['getDiffFileDiscussions']),
- isCollapsed() {
- return this.file.collapsed || false;
- },
viewBlobLink() {
return sprintf(
__('You can %{linkStart}view the blob%{linkEnd} instead.'),
@@ -52,17 +51,6 @@ export default {
false,
);
},
- showExpandMessage() {
- return (
- this.isCollapsed ||
- (!this.file.highlighted_diff_lines &&
- !this.isLoadingCollapsedDiff &&
- !this.file.too_large &&
- this.file.text &&
- !this.file.renamed_file &&
- !this.file.mode_changed)
- );
- },
showLoadingIcon() {
return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed);
},
@@ -73,9 +61,15 @@ export default {
this.file.parallel_diff_lines.length > 0
);
},
+ isFileTooLarge() {
+ return this.file.viewer.error === diffViewerErrors.too_large;
+ },
+ errorMessage() {
+ return this.file.viewer.error_message;
+ },
},
watch: {
- 'file.collapsed': function fileCollapsedWatch(newVal, oldVal) {
+ isCollapsed: function fileCollapsedWatch(newVal, oldVal) {
if (!newVal && oldVal && !this.hasDiffLines) {
this.handleLoadCollapsedDiff();
}
@@ -85,13 +79,13 @@ export default {
eventHub.$on(`loadCollapsedDiff/${this.file.file_hash}`, this.handleLoadCollapsedDiff);
},
methods: {
- ...mapActions('diffs', ['loadCollapsedDiff', 'assignDiscussionsToDiff']),
+ ...mapActions('diffs', ['loadCollapsedDiff', 'assignDiscussionsToDiff', 'setRenderIt']),
handleToggle() {
if (!this.hasDiffLines) {
this.handleLoadCollapsedDiff();
} else {
- this.file.collapsed = !this.file.collapsed;
- this.file.renderIt = true;
+ this.isCollapsed = !this.isCollapsed;
+ this.setRenderIt(this.file);
}
},
handleLoadCollapsedDiff() {
@@ -100,8 +94,8 @@ export default {
this.loadCollapsedDiff(this.file)
.then(() => {
this.isLoadingCollapsedDiff = false;
- this.file.collapsed = false;
- this.file.renderIt = true;
+ this.isCollapsed = false;
+ this.setRenderIt(this.file);
})
.then(() => {
requestIdleCallback(
@@ -164,21 +158,25 @@ export default {
Cancel
</button>
</div>
-
- <diff-content
- v-if="!isCollapsed && file.renderIt"
- :class="{ hidden: isCollapsed || file.too_large }"
- :diff-file="file"
- :help-page-path="helpPagePath"
- />
<gl-loading-icon v-if="showLoadingIcon" class="diff-content loading" />
- <div v-else-if="showExpandMessage" class="nothing-here-block diff-collapsed">
- {{ __('This diff is collapsed.') }}
- <a class="click-to-expand js-click-to-expand" href="#" @click.prevent="handleToggle">{{
- __('Click to expand it.')
- }}</a>
- </div>
- <div v-if="file.too_large" class="nothing-here-block diff-collapsed js-too-large-diff">
+ <template v-else>
+ <div v-if="errorMessage" class="diff-viewer">
+ <div class="nothing-here-block" v-html="errorMessage"></div>
+ </div>
+ <div v-else-if="isCollapsed" class="nothing-here-block diff-collapsed">
+ {{ __('This diff is collapsed.') }}
+ <a class="click-to-expand js-click-to-expand" href="#" @click.prevent="handleToggle">{{
+ __('Click to expand it.')
+ }}</a>
+ </div>
+ <diff-content
+ v-else
+ :class="{ hidden: isCollapsed || isFileTooLarge }"
+ :diff-file="file"
+ :help-page-path="helpPagePath"
+ />
+ </template>
+ <div v-if="isFileTooLarge" class="nothing-here-block diff-collapsed js-too-large-diff">
{{ __('This source diff could not be displayed because it is too large.') }}
<span v-html="viewBlobLink"></span>
</div>
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index f75a01b023b..4d33ad23f39 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -8,7 +8,9 @@ import FileIcon from '~/vue_shared/components/file_icon.vue';
import { GlTooltipDirective } from '@gitlab/ui';
import { truncateSha } from '~/lib/utils/text_utility';
import { __, s__, sprintf } from '~/locale';
+import { diffViewerModes } from '~/ide/constants';
import EditButton from './edit_button.vue';
+import DiffStats from './diff_stats.vue';
export default {
components: {
@@ -16,6 +18,7 @@ export default {
EditButton,
Icon,
FileIcon,
+ DiffStats,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -116,6 +119,12 @@ export default {
gfmCopyText() {
return `\`${this.diffFile.file_path}\``;
},
+ isFileRenamed() {
+ return this.diffFile.viewer.name === diffViewerModes.renamed;
+ },
+ isModeChanged() {
+ return this.diffFile.viewer.name === diffViewerModes.mode_changed;
+ },
},
mounted() {
polyfillSticky(this.$refs.header);
@@ -145,7 +154,7 @@ export default {
<div
ref="header"
class="js-file-title file-title file-title-flex-parent"
- @click="handleToggleFile($event, true);"
+ @click="handleToggleFile($event, true)"
>
<div class="file-header-content">
<icon
@@ -163,7 +172,7 @@ export default {
aria-hidden="true"
css-classes="js-file-icon append-right-5"
/>
- <span v-if="diffFile.renamed_file">
+ <span v-if="isFileRenamed">
<strong
v-gl-tooltip
:title="diffFile.old_path"
@@ -191,7 +200,7 @@ export default {
css-class="btn-default btn-transparent btn-clipboard"
/>
- <small v-if="diffFile.mode_changed" ref="fileMode">
+ <small v-if="isModeChanged" ref="fileMode">
{{ diffFile.a_mode }} → {{ diffFile.b_mode }}
</small>
@@ -202,6 +211,7 @@ export default {
v-if="!diffFile.submodule && addMergeRequestButtons"
class="file-actions d-none d-sm-block"
>
+ <diff-stats :added-lines="diffFile.added_lines" :removed-lines="diffFile.removed_lines" />
<template v-if="diffFile.blob && diffFile.blob.readable_text">
<button
:disabled="!diffHasDiscussions(diffFile)"
@@ -226,11 +236,15 @@ export default {
<a
v-if="diffFile.replaced_view_path"
:href="diffFile.replaced_view_path"
- class="btn view-file js-view-file"
+ class="btn view-file js-view-replaced-file"
v-html="viewReplacedFileButtonText"
>
</a>
- <a :href="diffFile.view_path" class="btn view-file js-view-file" v-html="viewFileButtonText">
+ <a
+ :href="diffFile.view_path"
+ class="btn view-file js-view-file-button"
+ v-html="viewFileButtonText"
+ >
</a>
<a
@@ -240,7 +254,7 @@ export default {
:title="`View on ${diffFile.formatted_external_url}`"
target="_blank"
rel="noopener noreferrer"
- class="btn btn-file-option"
+ class="btn btn-file-option js-external-url"
>
<icon name="external-link" />
</a>
diff --git a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
index c0613d80d37..6709df48637 100644
--- a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
@@ -179,7 +179,7 @@ export default {
v-if="lineNumber"
:data-linenumber="lineNumber"
:href="lineHref"
- @click="setHighlightedRow(lineCode);"
+ @click="setHighlightedRow(lineCode)"
>
</a>
<diff-gutter-avatars v-if="shouldShowAvatarsOnGutter" :discussions="line.discussions" />
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
index e7569ba7b84..bb66ab36283 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -1,6 +1,7 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
import { s__ } from '~/locale';
+import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form';
import noteForm from '../../notes/components/note_form.vue';
import autosave from '../../notes/mixins/autosave';
import { DIFF_NOTE_TYPE } from '../constants';
@@ -9,7 +10,7 @@ export default {
components: {
noteForm,
},
- mixins: [autosave],
+ mixins: [autosave, diffLineNoteFormMixin],
props: {
diffFileHash: {
type: String,
@@ -28,6 +29,11 @@ export default {
type: Object,
required: true,
},
+ helpPagePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
...mapState({
@@ -95,8 +101,10 @@ export default {
:is-editing="true"
:line-code="line.line_code"
:line="line"
+ :help-page-path="helpPagePath"
save-button-title="Comment"
class="diff-comment-form"
+ @handleFormUpdateAddToReview="addToReview"
@cancelForm="handleCancelCommentForm"
@handleFormUpdate="handleSaveNote"
/>
diff --git a/app/assets/javascripts/diffs/components/diff_stats.vue b/app/assets/javascripts/diffs/components/diff_stats.vue
new file mode 100644
index 00000000000..2e5855380af
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/diff_stats.vue
@@ -0,0 +1,52 @@
+<script>
+import Icon from '~/vue_shared/components/icon.vue';
+import { n__ } from '~/locale';
+
+export default {
+ components: { Icon },
+ props: {
+ addedLines: {
+ type: Number,
+ required: true,
+ },
+ removedLines: {
+ type: Number,
+ required: true,
+ },
+ diffFilesLength: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ filesText() {
+ return n__('File', 'Files', this.diffFilesLength);
+ },
+ isCompareVersionsHeader() {
+ return Boolean(this.diffFilesLength);
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="diff-stats"
+ :class="{
+ 'is-compare-versions-header d-none d-lg-inline-flex': isCompareVersionsHeader,
+ 'd-inline-flex': !isCompareVersionsHeader,
+ }"
+ >
+ <div v-if="diffFilesLength !== null" class="diff-stats-group">
+ <icon name="doc-code" class="diff-stats-icon text-secondary" />
+ <strong>{{ diffFilesLength }} {{ filesText }}</strong>
+ </div>
+ <div class="diff-stats-group cgreen">
+ <icon name="file-addition" class="diff-stats-icon" /> <strong>{{ addedLines }}</strong>
+ </div>
+ <div class="diff-stats-group cred">
+ <icon name="file-deletion" class="diff-stats-icon" /> <strong>{{ removedLines }}</strong>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/components/edit_button.vue b/app/assets/javascripts/diffs/components/edit_button.vue
index 5d38d545ce8..803f23b9170 100644
--- a/app/assets/javascripts/diffs/components/edit_button.vue
+++ b/app/assets/javascripts/diffs/components/edit_button.vue
@@ -17,12 +17,7 @@ export default {
},
methods: {
handleEditClick(evt) {
- if (!this.canCurrentUserFork || this.canModifyBlob) {
- // if we can Edit, do default Edit button behavior
- return;
- }
-
- if (this.canCurrentUserFork) {
+ if (this.canCurrentUserFork && !this.canModifyBlob) {
evt.preventDefault();
this.$emit('showForkMessage');
}
diff --git a/app/assets/javascripts/diffs/components/image_diff_overlay.vue b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
index d30e64312aa..4a83c5a72a5 100644
--- a/app/assets/javascripts/diffs/components/image_diff_overlay.vue
+++ b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
@@ -97,7 +97,7 @@ export default {
v-if="canComment"
type="button"
class="btn-transparent position-absolute image-diff-overlay-add-comment w-100 h-100 js-add-image-diff-note-button"
- @click="clickedImage($event.offsetX, $event.offsetY);"
+ @click="clickedImage($event.offsetX, $event.offsetY)"
>
<span class="sr-only"> {{ __('Add image comment') }} </span>
</button>
@@ -109,7 +109,7 @@ export default {
:disabled="!shouldToggleDiscussion"
class="js-image-badge"
type="button"
- @click="toggleDiscussion({ discussionId: discussion.id });"
+ @click="toggleDiscussion({ discussionId: discussion.id })"
>
<icon v-if="showCommentIcon" name="image-comment-dark" />
<template v-else>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
index 814ee0b7c02..69146f1f6fd 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
@@ -54,6 +54,7 @@ export default {
:diff-file-hash="diffFileHash"
:line="line"
:note-target-line="line"
+ :help-page-path="helpPagePath"
/>
</div>
</td>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_view.vue b/app/assets/javascripts/diffs/components/inline_diff_view.vue
index e781397214d..8c76a555b62 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_view.vue
@@ -1,5 +1,6 @@
<script>
import { mapGetters } from 'vuex';
+import draftCommentsMixin from 'ee_else_ce/diffs/mixins/draft_comments';
import inlineDiffTableRow from './inline_diff_table_row.vue';
import inlineDiffCommentRow from './inline_diff_comment_row.vue';
@@ -7,7 +8,10 @@ export default {
components: {
inlineDiffCommentRow,
inlineDiffTableRow,
+ InlineDraftCommentRow: () =>
+ import('ee_component/batch_comments/components/inline_draft_comment_row.vue'),
},
+ mixins: [draftCommentsMixin],
props: {
diffFile: {
type: Object,
@@ -54,6 +58,11 @@ export default {
:line="line"
:help-page-path="helpPagePath"
/>
+ <inline-draft-comment-row
+ v-if="shouldRenderDraftRow(diffFile.file_hash, line)"
+ :key="`draft_${index}`"
+ :draft="draftForLine(diffFile.file_hash, line)"
+ />
</template>
</tbody>
</table>
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
index a65cf025cde..370cb6e339a 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
@@ -101,6 +101,7 @@ export default {
:diff-file-hash="diffFileHash"
:line="line.left"
:note-target-line="line.left"
+ :help-page-path="helpPagePath"
line-position="left"
/>
</td>
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_view.vue b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
index 1bf693380db..93e754fa896 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
@@ -1,5 +1,6 @@
<script>
import { mapGetters } from 'vuex';
+import draftCommentsMixin from 'ee_else_ce/diffs/mixins/draft_comments';
import parallelDiffTableRow from './parallel_diff_table_row.vue';
import parallelDiffCommentRow from './parallel_diff_comment_row.vue';
@@ -7,7 +8,10 @@ export default {
components: {
parallelDiffTableRow,
parallelDiffCommentRow,
+ ParallelDraftCommentRow: () =>
+ import('ee_component/batch_comments/components/parallel_draft_comment_row.vue'),
},
+ mixins: [draftCommentsMixin],
props: {
diffFile: {
type: Object,
@@ -56,6 +60,12 @@ export default {
:line-index="index"
:help-page-path="helpPagePath"
/>
+ <parallel-draft-comment-row
+ v-if="shouldRenderParallelDraftRow(diffFile.file_hash, line)"
+ :key="`drafts-${index}`"
+ :line="line"
+ :diff-file-content-sha="diffFile.file_hash"
+ />
</template>
</tbody>
</table>
diff --git a/app/assets/javascripts/diffs/components/settings_dropdown.vue b/app/assets/javascripts/diffs/components/settings_dropdown.vue
new file mode 100644
index 00000000000..0129763161a
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/settings_dropdown.vue
@@ -0,0 +1,92 @@
+<script>
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { GlButton } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ components: {
+ GlButton,
+ Icon,
+ },
+ computed: {
+ ...mapGetters('diffs', ['isInlineView', 'isParallelView']),
+ ...mapState('diffs', ['renderTreeList', 'showWhitespace']),
+ },
+ methods: {
+ ...mapActions('diffs', [
+ 'setInlineDiffViewType',
+ 'setParallelDiffViewType',
+ 'setRenderTreeList',
+ 'setShowWhitespace',
+ ]),
+ },
+};
+</script>
+
+<template>
+ <div class="dropdown">
+ <button
+ type="button"
+ class="btn btn-default js-show-diff-settings"
+ data-toggle="dropdown"
+ data-display="static"
+ >
+ <icon name="settings" /> <icon name="arrow-down" />
+ </button>
+ <div class="dropdown-menu dropdown-menu-right p-2 pt-3 pb-3">
+ <div>
+ <span class="bold d-block mb-1">{{ __('File browser') }}</span>
+ <div class="btn-group d-flex">
+ <gl-button
+ :class="{ active: !renderTreeList }"
+ class="w-100 js-list-view"
+ @click="setRenderTreeList(false)"
+ >
+ {{ __('List view') }}
+ </gl-button>
+ <gl-button
+ :class="{ active: renderTreeList }"
+ class="w-100 js-tree-view"
+ @click="setRenderTreeList(true)"
+ >
+ {{ __('Tree view') }}
+ </gl-button>
+ </div>
+ </div>
+ <div class="mt-2">
+ <span class="bold d-block mb-1">{{ __('Compare changes') }}</span>
+ <div class="btn-group d-flex js-diff-view-buttons">
+ <gl-button
+ id="inline-diff-btn"
+ :class="{ active: isInlineView }"
+ class="w-100 js-inline-diff-button"
+ data-view-type="inline"
+ @click="setInlineDiffViewType"
+ >
+ {{ __('Inline') }}
+ </gl-button>
+ <gl-button
+ id="parallel-diff-btn"
+ :class="{ active: isParallelView }"
+ class="w-100 js-parallel-diff-button"
+ data-view-type="parallel"
+ @click="setParallelDiffViewType"
+ >
+ {{ __('Side-by-side') }}
+ </gl-button>
+ </div>
+ </div>
+ <div class="mt-2">
+ <label class="mb-0">
+ <input
+ id="show-whitespace"
+ type="checkbox"
+ :checked="showWhitespace"
+ @change="setShowWhitespace({ showWhitespace: $event.target.checked, pushState: true })"
+ />
+ {{ __('Show whitespace changes') }}
+ </label>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
index f40a7b25fde..8fc3af15bea 100644
--- a/app/assets/javascripts/diffs/components/tree_list.vue
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -1,13 +1,10 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective } from '@gitlab/ui';
-import { parseBoolean } from '~/lib/utils/common_utils';
import Icon from '~/vue_shared/components/icon.vue';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowStats from './file_row_stats.vue';
-const treeListStorageKey = 'mr_diff_tree_list';
-
export default {
directives: {
GlTooltip: GlTooltipDirective,
@@ -16,54 +13,51 @@ export default {
Icon,
FileRow,
},
+ props: {
+ hideFileStats: {
+ type: Boolean,
+ required: true,
+ },
+ },
data() {
- const treeListStored = localStorage.getItem(treeListStorageKey);
- const renderTreeList = treeListStored !== null ? parseBoolean(treeListStored) : true;
-
return {
search: '',
- renderTreeList,
- focusSearch: false,
};
},
computed: {
- ...mapState('diffs', ['tree', 'addedLines', 'removedLines']),
- ...mapGetters('diffs', ['allBlobs', 'diffFilesLength']),
+ ...mapState('diffs', ['tree', 'renderTreeList']),
+ ...mapGetters('diffs', ['allBlobs']),
filteredTreeList() {
const search = this.search.toLowerCase().trim();
- if (search === '') return this.renderTreeList ? this.tree : this.allBlobs;
+ if (search === '' || this.$options.fuzzyFileFinderEnabled)
+ return this.renderTreeList ? this.tree : this.allBlobs;
- return this.allBlobs.filter(f => f.path.toLowerCase().indexOf(search) >= 0);
- },
- rowDisplayTextKey() {
- if (this.renderTreeList && this.search.trim() === '') {
- return 'name';
- }
+ return this.allBlobs.reduce((acc, folder) => {
+ const tree = folder.tree.filter(f => f.path.toLowerCase().indexOf(search) >= 0);
- return 'path';
+ if (tree.length) {
+ return acc.concat({
+ ...folder,
+ tree,
+ });
+ }
+
+ return acc;
+ }, []);
+ },
+ fileRowExtraComponent() {
+ return this.hideFileStats ? null : FileRowStats;
},
},
methods: {
- ...mapActions('diffs', ['toggleTreeOpen', 'scrollToFile']),
+ ...mapActions('diffs', ['toggleTreeOpen', 'scrollToFile', 'toggleFileFinder']),
clearSearch() {
this.search = '';
- this.toggleFocusSearch(false);
- },
- toggleRenderTreeList(toggle) {
- this.renderTreeList = toggle;
- localStorage.setItem(treeListStorageKey, this.renderTreeList);
- },
- toggleFocusSearch(toggle) {
- this.focusSearch = toggle;
- },
- blurSearch() {
- if (this.search.trim() === '') {
- this.toggleFocusSearch(false);
- }
},
},
- FileRowStats,
+ shortcutKeyCharacter: `${/Mac/i.test(navigator.userAgent) ? '&#8984;' : 'Ctrl'}+P`,
+ diffTreeFiltering: gon.features && gon.features.diffTreeFiltering,
};
</script>
@@ -72,54 +66,39 @@ export default {
<div class="append-bottom-8 position-relative tree-list-search d-flex">
<div class="flex-fill d-flex">
<icon name="search" class="position-absolute tree-list-icon" />
- <input
- v-model="search"
- :placeholder="s__('MergeRequest|Filter files')"
- type="search"
- class="form-control"
- @focus="toggleFocusSearch(true);"
- @blur="blurSearch"
- />
- <button
- v-show="search"
- :aria-label="__('Clear search')"
- type="button"
- class="position-absolute bg-transparent tree-list-icon tree-list-clear-icon border-0 p-0"
- @click="clearSearch"
- >
- <icon name="close" />
- </button>
- </div>
- <div v-show="!focusSearch" class="btn-group prepend-left-8 tree-list-view-toggle">
- <button
- v-gl-tooltip.hover
- :aria-label="__('List view')"
- :title="__('List view')"
- :class="{
- active: !renderTreeList,
- }"
- class="btn btn-default pt-0 pb-0 d-flex align-items-center"
- type="button"
- @click="toggleRenderTreeList(false);"
- >
- <icon name="hamburger" />
- </button>
- <button
- v-gl-tooltip.hover
- :aria-label="__('Tree view')"
- :title="__('Tree view')"
- :class="{
- active: renderTreeList,
- }"
- class="btn btn-default pt-0 pb-0 d-flex align-items-center"
- type="button"
- @click="toggleRenderTreeList(true);"
- >
- <icon name="file-tree" />
- </button>
+ <template v-if="$options.diffTreeFiltering">
+ <input
+ v-model="search"
+ :placeholder="s__('MergeRequest|Filter files')"
+ type="search"
+ class="form-control"
+ />
+ <button
+ v-show="search"
+ :aria-label="__('Clear search')"
+ type="button"
+ class="position-absolute bg-transparent tree-list-icon tree-list-clear-icon border-0 p-0"
+ @click="clearSearch"
+ >
+ <icon name="close" />
+ </button>
+ </template>
+ <template v-else>
+ <button
+ type="button"
+ class="form-control text-left text-secondary"
+ @click="toggleFileFinder(true)"
+ >
+ {{ s__('MergeRequest|Search files') }}
+ </button>
+ <span
+ class="position-absolute text-secondary diff-tree-search-shortcut"
+ v-html="$options.shortcutKeyCharacter"
+ ></span>
+ </template>
</div>
</div>
- <div class="tree-list-scroll">
+ <div :class="{ 'pt-0 tree-list-blobs': !renderTreeList }" class="tree-list-scroll">
<template v-if="filteredTreeList.length">
<file-row
v-for="file in filteredTreeList"
@@ -127,10 +106,8 @@ export default {
:file="file"
:level="0"
:hide-extra-on-tree="true"
- :extra-component="$options.FileRowStats"
+ :extra-component="fileRowExtraComponent"
:show-changed-icon="true"
- :display-text-key="rowDisplayTextKey"
- :should-truncate-start="true"
@toggleTreeOpen="toggleTreeOpen"
@clickFile="scrollToFile"
/>
@@ -139,12 +116,22 @@ export default {
{{ s__('MergeRequest|No files found') }}
</p>
</div>
- <div v-once class="pt-3 pb-3 text-center">
- {{ n__('%d changed file', '%d changed files', diffFilesLength) }}
- <div>
- <span class="cgreen"> {{ n__('%d addition', '%d additions', addedLines) }} </span>
- <span class="cred"> {{ n__('%d deleted', '%d deletions', removedLines) }} </span>
- </div>
- </div>
</div>
</template>
+
+<style>
+.tree-list-blobs .file-row-name {
+ margin-left: 12px;
+}
+
+.diff-tree-search-shortcut {
+ top: 50%;
+ right: 10px;
+ transform: translateY(-50%);
+ pointer-events: none;
+}
+
+.tree-list-icon:not(button) {
+ pointer-events: none;
+}
+</style>
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index 78a39baa4cb..7002655ea49 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -32,3 +32,13 @@ export const LINES_TO_BE_RENDERED_DIRECTLY = 100;
export const MAX_LINES_TO_BE_RENDERED = 2000;
export const MR_TREE_SHOW_KEY = 'mr_tree_show';
+
+export const TREE_TYPE = 'tree';
+export const TREE_LIST_STORAGE_KEY = 'mr_diff_tree_list';
+export const WHITESPACE_STORAGE_KEY = 'mr_show_whitespace';
+export const TREE_LIST_WIDTH_STORAGE_KEY = 'mr_tree_list_width';
+
+export const INITIAL_TREE_WIDTH = 320;
+export const MIN_TREE_WIDTH = 240;
+export const MAX_TREE_WIDTH = 400;
+export const TREE_HIDE_STATS_WIDTH = 260;
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index b130cedc24c..63954d9d412 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -1,8 +1,60 @@
import Vue from 'vue';
-import { mapState } from 'vuex';
+import { mapActions, mapState, mapGetters } from 'vuex';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import { getParameterValues } from '~/lib/utils/url_utility';
+import FindFile from '~/vue_shared/components/file_finder/index.vue';
+import eventHub from '../notes/event_hub';
import diffsApp from './components/app.vue';
+import { TREE_LIST_STORAGE_KEY } from './constants';
export default function initDiffsApp(store) {
+ const fileFinderEl = document.getElementById('js-diff-file-finder');
+
+ if (fileFinderEl) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: fileFinderEl,
+ store,
+ computed: {
+ ...mapState('diffs', ['fileFinderVisible', 'isLoading']),
+ ...mapGetters('diffs', ['flatBlobsList']),
+ },
+ watch: {
+ fileFinderVisible(newVal, oldVal) {
+ if (newVal && !oldVal && !this.flatBlobsList.length) {
+ eventHub.$emit('fetchDiffData');
+ }
+ },
+ },
+ methods: {
+ ...mapActions('diffs', ['toggleFileFinder', 'scrollToFile']),
+ openFile(file) {
+ window.mrTabs.tabShown('diffs');
+ this.scrollToFile(file.path);
+ },
+ },
+ render(createElement) {
+ return createElement(FindFile, {
+ props: {
+ files: this.flatBlobsList,
+ visible: this.fileFinderVisible,
+ loading: this.isLoading,
+ showDiffStats: true,
+ clearSearchOnClose: false,
+ },
+ on: {
+ toggle: this.toggleFileFinder,
+ click: this.openFile,
+ },
+ class: ['diff-file-finder'],
+ style: {
+ display: this.fileFinderVisible ? '' : 'none',
+ },
+ });
+ },
+ });
+ }
+
return new Vue({
el: '#js-diffs-app',
name: 'MergeRequestDiffs',
@@ -26,6 +78,16 @@ export default function initDiffsApp(store) {
activeTab: state => state.page.activeTab,
}),
},
+ created() {
+ const treeListStored = localStorage.getItem(TREE_LIST_STORAGE_KEY);
+ const renderTreeList = treeListStored !== null ? parseBoolean(treeListStored) : true;
+
+ this.setRenderTreeList(renderTreeList);
+ this.setShowWhitespace({ showWhitespace: getParameterValues('w')[0] !== '1' });
+ },
+ methods: {
+ ...mapActions('diffs', ['setRenderTreeList', 'setShowWhitespace']),
+ },
render(createElement) {
return createElement('diffs-app', {
props: {
diff --git a/app/assets/javascripts/diffs/mixins/draft_comments.js b/app/assets/javascripts/diffs/mixins/draft_comments.js
new file mode 100644
index 00000000000..cfa722b27f1
--- /dev/null
+++ b/app/assets/javascripts/diffs/mixins/draft_comments.js
@@ -0,0 +1,7 @@
+export default {
+ computed: {
+ shouldRenderDraftRow: () => () => false,
+ shouldRenderParallelDraftRow: () => () => false,
+ draftForLine: () => () => ({}),
+ },
+};
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 00a4bb6d3a3..c40775c3259 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -5,6 +5,7 @@ import createFlash from '~/flash';
import { s__ } from '~/locale';
import { handleLocationHash, historyPushState, scrollToElement } from '~/lib/utils/common_utils';
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
+import TreeWorker from '../workers/tree_worker';
import eventHub from '../../notes/event_hub';
import { getDiffPositionByLineCode, getNoteFormData } from './utils';
import * as types from './mutation_types';
@@ -13,7 +14,11 @@ import {
INLINE_DIFF_VIEW_TYPE,
DIFF_VIEW_COOKIE_NAME,
MR_TREE_SHOW_KEY,
+ TREE_LIST_STORAGE_KEY,
+ WHITESPACE_STORAGE_KEY,
+ TREE_LIST_WIDTH_STORAGE_KEY,
} from '../constants';
+import { diffViewerModes } from '~/ide/constants';
export const setBaseConfig = ({ commit }, options) => {
const { endpoint, projectPath } = options;
@@ -21,21 +26,35 @@ export const setBaseConfig = ({ commit }, options) => {
};
export const fetchDiffFiles = ({ state, commit }) => {
+ const worker = new TreeWorker();
+
commit(types.SET_LOADING, true);
+ worker.addEventListener('message', ({ data }) => {
+ commit(types.SET_TREE_DATA, data);
+
+ worker.terminate();
+ });
+
return axios
- .get(state.endpoint)
+ .get(state.endpoint, { params: { w: state.showWhitespace ? null : '1' } })
.then(res => {
commit(types.SET_LOADING, false);
commit(types.SET_MERGE_REQUEST_DIFFS, res.data.merge_request_diffs || []);
commit(types.SET_DIFF_DATA, res.data);
+
+ worker.postMessage(state.diffFiles);
+
return Vue.nextTick();
})
- .then(handleLocationHash);
+ .then(handleLocationHash)
+ .catch(() => worker.terminate());
};
export const setHighlightedRow = ({ commit }, lineCode) => {
+ const fileHash = lineCode.split('_')[0];
commit(types.SET_HIGHLIGHTED_ROW, lineCode);
+ commit(types.UPDATE_CURRENT_DIFF_FILE_ID, fileHash);
};
// This is adding line discussions to the actual lines in the diff tree
@@ -76,7 +95,7 @@ export const renderFileForDiscussionId = ({ commit, rootState, state }, discussi
commit(types.RENDER_FILE, file);
}
- if (file.collapsed) {
+ if (file.viewer.collapsed) {
eventHub.$emit(`loadCollapsedDiff/${file.file_hash}`);
scrollToElement(document.getElementById(file.file_hash));
} else {
@@ -90,7 +109,8 @@ export const startRenderDiffsQueue = ({ state, commit }) => {
const checkItem = () =>
new Promise(resolve => {
const nextFile = state.diffFiles.find(
- file => !file.renderIt && (!file.collapsed || !file.text),
+ file =>
+ !file.renderIt && (!file.viewer.collapsed || !file.viewer.name === diffViewerModes.text),
);
if (nextFile) {
@@ -113,6 +133,8 @@ export const startRenderDiffsQueue = ({ state, commit }) => {
return checkItem();
};
+export const setRenderIt = ({ commit }, file) => commit(types.RENDER_FILE, file);
+
export const setInlineDiffViewType = ({ commit }) => {
commit(types.SET_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE);
@@ -242,8 +264,6 @@ export const scrollToFile = ({ state, commit }, path) => {
document.location.hash = fileHash;
commit(types.UPDATE_CURRENT_DIFF_FILE_ID, fileHash);
-
- setTimeout(() => commit(types.UPDATE_CURRENT_DIFF_FILE_ID, ''), 1000);
};
export const toggleShowTreeList = ({ commit, state }) => {
@@ -265,5 +285,29 @@ export const closeDiffFileCommentForm = ({ commit }, fileHash) => {
commit(types.CLOSE_DIFF_FILE_COMMENT_FORM, fileHash);
};
+export const setRenderTreeList = ({ commit }, renderTreeList) => {
+ commit(types.SET_RENDER_TREE_LIST, renderTreeList);
+
+ localStorage.setItem(TREE_LIST_STORAGE_KEY, renderTreeList);
+};
+
+export const setShowWhitespace = ({ commit }, { showWhitespace, pushState = false }) => {
+ commit(types.SET_SHOW_WHITESPACE, showWhitespace);
+
+ localStorage.setItem(WHITESPACE_STORAGE_KEY, showWhitespace);
+
+ if (pushState) {
+ historyPushState(showWhitespace ? '?w=0' : '?w=1');
+ }
+};
+
+export const toggleFileFinder = ({ commit }, visible) => {
+ commit(types.TOGGLE_FILE_FINDER_VISIBLE, visible);
+};
+
+export const cacheTreeListWidth = (_, size) => {
+ localStorage.setItem(TREE_LIST_WIDTH_STORAGE_KEY, size);
+};
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index fdf1efbb10e..bc27e263bff 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -4,7 +4,8 @@ export const isParallelView = state => state.diffViewType === PARALLEL_DIFF_VIEW
export const isInlineView = state => state.diffViewType === INLINE_DIFF_VIEW_TYPE;
-export const hasCollapsedFile = state => state.diffFiles.some(file => file.collapsed);
+export const hasCollapsedFile = state =>
+ state.diffFiles.some(file => file.viewer && file.viewer.collapsed);
export const commitId = state => (state.commit && state.commit.id ? state.commit.id : null);
@@ -74,12 +75,37 @@ export const getDiffFileDiscussions = (state, getters, rootState, rootGetters) =
export const getDiffFileByHash = state => fileHash =>
state.diffFiles.find(file => file.file_hash === fileHash);
-export const allBlobs = state => Object.values(state.treeEntries).filter(f => f.type === 'blob');
+export const flatBlobsList = state =>
+ Object.values(state.treeEntries).filter(f => f.type === 'blob');
+
+export const allBlobs = (state, getters) =>
+ getters.flatBlobsList.reduce((acc, file) => {
+ const { parentPath } = file;
+
+ if (parentPath && !acc.some(f => f.path === parentPath)) {
+ acc.push({
+ path: parentPath,
+ isHeader: true,
+ tree: [],
+ });
+ }
+
+ acc.find(f => f.path === parentPath).tree.push(file);
+
+ return acc;
+ }, []);
export const diffFilesLength = state => state.diffFiles.length;
export const getCommentFormForDiffFile = state => fileHash =>
state.commentForms.find(form => form.fileHash === fileHash);
+/**
+ * Returns index of a currently selected diff in diffFiles
+ * @returns {number}
+ */
+export const currentDiffIndex = state =>
+ Math.max(0, state.diffFiles.findIndex(diff => diff.file_hash === state.currentDiffFileId));
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index 98e57d52d77..47f78a5db54 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -11,6 +11,8 @@ const storedTreeShow = localStorage.getItem(MR_TREE_SHOW_KEY);
export default () => ({
isLoading: true,
+ addedLines: null,
+ removedLines: null,
endpoint: '',
basePath: '',
commit: null,
@@ -27,4 +29,7 @@ export default () => ({
projectPath: '',
commentForms: [],
highlightedRow: null,
+ renderTreeList: true,
+ showWhitespace: true,
+ fileFinderVisible: false,
});
diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js
index 0338cde3658..71ad108ce88 100644
--- a/app/assets/javascripts/diffs/store/mutation_types.js
+++ b/app/assets/javascripts/diffs/store/mutation_types.js
@@ -18,3 +18,8 @@ export const OPEN_DIFF_FILE_COMMENT_FORM = 'OPEN_DIFF_FILE_COMMENT_FORM';
export const UPDATE_DIFF_FILE_COMMENT_FORM = 'UPDATE_DIFF_FILE_COMMENT_FORM';
export const CLOSE_DIFF_FILE_COMMENT_FORM = 'CLOSE_DIFF_FILE_COMMENT_FORM';
export const SET_HIGHLIGHTED_ROW = 'SET_HIGHLIGHTED_ROW';
+
+export const SET_TREE_DATA = 'SET_TREE_DATA';
+export const SET_RENDER_TREE_LIST = 'SET_RENDER_TREE_LIST';
+export const SET_SHOW_WHITESPACE = 'SET_SHOW_WHITESPACE';
+export const TOGGLE_FILE_FINDER_VISIBLE = 'TOGGLE_FILE_FINDER_VISIBLE';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index ed4203cf5e0..5a27388863c 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -1,5 +1,4 @@
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { sortTree } from '~/ide/stores/utils';
import {
findDiffFile,
addLineReferences,
@@ -7,7 +6,6 @@ import {
addContextLines,
prepareDiffData,
isDiscussionApplicableToLine,
- generateTreeList,
} from './utils';
import * as types from './mutation_types';
@@ -23,12 +21,9 @@ export default {
[types.SET_DIFF_DATA](state, data) {
prepareDiffData(data);
- const { tree, treeEntries } = generateTreeList(data.diff_files);
Object.assign(state, {
...convertObjectPropsToCamelCase(data),
- tree: sortTree(tree),
- treeEntries,
});
},
@@ -149,6 +144,7 @@ export default {
if (left || right) {
return {
+ ...line,
left: line.left ? mapDiscussions(line.left) : null,
right: line.right ? mapDiscussions(line.right, () => !left) : null,
};
@@ -239,4 +235,17 @@ export default {
[types.SET_HIGHLIGHTED_ROW](state, lineCode) {
state.highlightedRow = lineCode;
},
+ [types.SET_TREE_DATA](state, { treeEntries, tree }) {
+ state.treeEntries = treeEntries;
+ state.tree = tree;
+ },
+ [types.SET_RENDER_TREE_LIST](state, renderTreeList) {
+ state.renderTreeList = renderTreeList;
+ },
+ [types.SET_SHOW_WHITESPACE](state, showWhitespace) {
+ state.showWhitespace = showWhitespace;
+ },
+ [types.TOGGLE_FILE_FINDER_VISIBLE](state, visible) {
+ state.fileFinderVisible = visible;
+ },
};
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index 2fe20551642..247d1e65fea 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -1,5 +1,6 @@
import _ from 'underscore';
-import { diffModes } from '~/ide/constants';
+import { truncatePathMiddleToLength } from '~/lib/utils/text_utility';
+import { diffModes, diffViewerModes } from '~/ide/constants';
import {
LINE_POSITION_LEFT,
LINE_POSITION_RIGHT,
@@ -11,6 +12,7 @@ import {
MATCH_LINE_TYPE,
LINES_TO_BE_RENDERED_DIRECTLY,
MAX_LINES_TO_BE_RENDERED,
+ TREE_TYPE,
} from '../constants';
export function findDiffFile(files, hash) {
@@ -159,6 +161,7 @@ export function addContextLines(options) {
const normalizedParallelLines = contextLines.map(line => ({
left: line,
right: line,
+ line_code: line.line_code,
}));
if (options.bottom) {
@@ -180,8 +183,6 @@ export function addContextLines(options) {
export function trimFirstCharOfLineContent(line = {}) {
// eslint-disable-next-line no-param-reassign
delete line.text;
- // eslint-disable-next-line no-param-reassign
- line.discussions = [];
const parsedLine = Object.assign({}, line);
@@ -221,10 +222,12 @@ export function prepareDiffData(diffData) {
line.line_code = getLineCode(line, u);
if (line.left) {
line.left = trimFirstCharOfLineContent(line.left);
+ line.left.discussions = [];
line.left.hasForm = false;
}
if (line.right) {
line.right = trimFirstCharOfLineContent(line.right);
+ line.right.discussions = [];
line.right.hasForm = false;
}
}
@@ -234,14 +237,19 @@ export function prepareDiffData(diffData) {
const linesLength = file.highlighted_diff_lines.length;
for (let u = 0; u < linesLength; u += 1) {
const line = file.highlighted_diff_lines[u];
- Object.assign(line, { ...trimFirstCharOfLineContent(line), hasForm: false });
+ Object.assign(line, {
+ ...trimFirstCharOfLineContent(line),
+ discussions: [],
+ hasForm: false,
+ });
}
showingLines += file.parallel_diff_lines.length;
}
Object.assign(file, {
renderIt: showingLines < LINES_TO_BE_RENDERED_DIRECTLY,
- collapsed: file.text && showingLines > MAX_LINES_TO_BE_RENDERED,
+ collapsed:
+ file.viewer.name === diffViewerModes.text && showingLines > MAX_LINES_TO_BE_RENDERED,
discussions: [],
});
}
@@ -289,8 +297,63 @@ export function isDiscussionApplicableToLine({ discussion, diffPosition, latestD
return latestDiff && discussion.active && line_code === discussion.line_code;
}
-export const generateTreeList = files =>
- files.reduce(
+export const getLowestSingleFolder = folder => {
+ const getFolder = (blob, start = []) =>
+ blob.tree.reduce(
+ (acc, file) => {
+ const shouldGetFolder = file.tree.length === 1 && file.tree[0].type === TREE_TYPE;
+ const currentFileTypeTree = file.type === TREE_TYPE;
+ const path = shouldGetFolder || currentFileTypeTree ? acc.path.concat(file.name) : acc.path;
+ const tree = shouldGetFolder || currentFileTypeTree ? acc.tree.concat(file) : acc.tree;
+
+ if (shouldGetFolder) {
+ const firstFolder = getFolder(file);
+
+ path.push(...firstFolder.path);
+ tree.push(...firstFolder.tree);
+ }
+
+ return {
+ ...acc,
+ path,
+ tree,
+ };
+ },
+ { path: start, tree: [] },
+ );
+ const { path, tree } = getFolder(folder, [folder.name]);
+
+ return {
+ path: truncatePathMiddleToLength(path.join('/'), 40),
+ treeAcc: tree.length ? tree[tree.length - 1].tree : null,
+ };
+};
+
+export const flattenTree = tree => {
+ const flatten = blobTree =>
+ blobTree.reduce((acc, file) => {
+ const blob = file;
+ let treeToFlatten = blob.tree;
+
+ if (file.type === TREE_TYPE && file.tree.length === 1) {
+ const { treeAcc, path } = getLowestSingleFolder(file);
+
+ if (treeAcc) {
+ blob.name = path;
+ treeToFlatten = flatten(treeAcc);
+ }
+ }
+
+ blob.tree = flatten(treeToFlatten);
+
+ return acc.concat(blob);
+ }, []);
+
+ return flatten(tree);
+};
+
+export const generateTreeList = files => {
+ const { treeEntries, tree } = files.reduce(
(acc, file) => {
const split = file.new_path.split('/');
@@ -318,6 +381,7 @@ export const generateTreeList = files =>
fileHash: file.file_hash,
addedLines: file.added_lines,
removedLines: file.removed_lines,
+ parentPath: parent ? `${parent.path}/` : '/',
});
} else {
Object.assign(entry, {
@@ -334,11 +398,16 @@ export const generateTreeList = files =>
{ treeEntries: {}, tree: [] },
);
+ return { treeEntries, tree: flattenTree(tree) };
+};
+
export const getDiffMode = diffFile => {
const diffModeKey = Object.keys(diffModes).find(key => diffFile[`${key}_file`]);
return (
diffModes[diffModeKey] ||
- (diffFile.mode_changed && diffModes.mode_changed) ||
+ (diffFile.viewer &&
+ diffFile.viewer.name === diffViewerModes.mode_changed &&
+ diffViewerModes.mode_changed) ||
diffModes.replaced
);
};
diff --git a/app/assets/javascripts/diffs/workers/tree_worker.js b/app/assets/javascripts/diffs/workers/tree_worker.js
new file mode 100644
index 00000000000..534d737c77e
--- /dev/null
+++ b/app/assets/javascripts/diffs/workers/tree_worker.js
@@ -0,0 +1,14 @@
+import { sortTree } from '~/ide/stores/utils';
+import { generateTreeList } from '../store/utils';
+
+// eslint-disable-next-line no-restricted-globals
+self.addEventListener('message', e => {
+ const { data } = e;
+ const { treeEntries, tree } = generateTreeList(data);
+
+ // eslint-disable-next-line no-restricted-globals
+ self.postMessage({
+ treeEntries,
+ tree: sortTree(tree),
+ });
+});
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_form.js b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
index d8d0fa1fac4..00e41dd0301 100644
--- a/app/assets/javascripts/dirty_submit/dirty_submit_form.js
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
@@ -25,15 +25,16 @@ class DirtySubmitForm {
DirtySubmitForm.THROTTLE_DURATION,
);
this.form.addEventListener('input', throttledUpdateDirtyInput);
+ this.form.addEventListener('change', throttledUpdateDirtyInput);
this.form.addEventListener('submit', event => this.formSubmit(event));
}
updateDirtyInput(event) {
- const input = event.target;
+ const { target } = event;
- if (!input.dataset.isDirtySubmitInput) return;
+ if (!target.dataset.isDirtySubmitInput) return;
- this.updateDirtyInputs(input);
+ this.updateDirtyInputs(target);
this.toggleSubmission();
}
diff --git a/app/assets/javascripts/dismissable_callout.js b/app/assets/javascripts/dismissable_callout.js
deleted file mode 100644
index 5185b019376..00000000000
--- a/app/assets/javascripts/dismissable_callout.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import $ from 'jquery';
-import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
-import Flash from '~/flash';
-
-export default function initDismissableCallout(alertSelector) {
- const alertEl = document.querySelector(alertSelector);
- if (!alertEl) {
- return;
- }
-
- const closeButtonEl = alertEl.getElementsByClassName('close')[0];
- const { dismissEndpoint, featureId } = closeButtonEl.dataset;
-
- closeButtonEl.addEventListener('click', () => {
- axios
- .post(dismissEndpoint, {
- feature_name: featureId,
- })
- .then(() => {
- $(alertEl).alert('close');
- })
- .catch(() => {
- Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
- });
- });
-}
diff --git a/app/assets/javascripts/due_date_select.js b/app/assets/javascripts/due_date_select.js
index dbfcf8cc921..cb1b1173190 100644
--- a/app/assets/javascripts/due_date_select.js
+++ b/app/assets/javascripts/due_date_select.js
@@ -64,6 +64,7 @@ class DueDateSelect {
this.saveDueDate(true);
}
},
+ firstDay: gon.first_day_of_week,
});
calendar.setDate(parsePikadayDate($dueDateInput.val()));
@@ -183,6 +184,7 @@ export default class DueDateSelectors {
onSelect(dateText) {
$datePicker.val(calendar.toString(dateText));
},
+ firstDay: gon.first_day_of_week,
});
calendar.setDate(parsePikadayDate(datePickerVal));
diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js
index cd8dff40b88..36542315c4c 100644
--- a/app/assets/javascripts/emoji/index.js
+++ b/app/assets/javascripts/emoji/index.js
@@ -1,13 +1,58 @@
import _ from 'underscore';
-import emojiMap from 'emojis/digests.json';
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
import emojiAliases from 'emojis/aliases.json';
+import axios from '../lib/utils/axios_utils';
-export const validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)];
+import AccessorUtilities from '../lib/utils/accessor';
+
+let emojiMap = null;
+let validEmojiNames = null;
+
+export const EMOJI_VERSION = '1';
+const EMOJI_VERSION_LOCALSTORAGE = `EMOJIS_${EMOJI_VERSION}`;
+
+const isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe();
+
+export function initEmojiMap() {
+ return new Promise((resolve, reject) => {
+ if (emojiMap) {
+ resolve(emojiMap);
+ } else if (isLocalStorageAvailable && window.localStorage.getItem(EMOJI_VERSION_LOCALSTORAGE)) {
+ emojiMap = JSON.parse(window.localStorage.getItem(EMOJI_VERSION_LOCALSTORAGE));
+ validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)];
+ resolve(emojiMap);
+ } else {
+ // We load the JSON from server
+ axios
+ .get(
+ `${gon.asset_host || ''}${gon.relative_url_root ||
+ ''}/-/emojis/${EMOJI_VERSION}/emojis.json`,
+ )
+ .then(({ data }) => {
+ emojiMap = data;
+ validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)];
+ resolve(emojiMap);
+ if (isLocalStorageAvailable) {
+ window.localStorage.setItem(EMOJI_VERSION_LOCALSTORAGE, JSON.stringify(emojiMap));
+ }
+ })
+ .catch(err => {
+ createFlash(s__('Emojis|Something went wrong while loading emojis.'));
+ reject(err);
+ });
+ }
+ });
+}
export function normalizeEmojiName(name) {
return Object.prototype.hasOwnProperty.call(emojiAliases, name) ? emojiAliases[name] : name;
}
+export function getValidEmojiNames() {
+ return validEmojiNames;
+}
+
export function isEmojiNameValid(name) {
return validEmojiNames.indexOf(name) >= 0;
}
@@ -36,8 +81,8 @@ export function getEmojiCategoryMap() {
};
Object.keys(emojiMap).forEach(name => {
const emoji = emojiMap[name];
- if (emojiCategoryMap[emoji.category]) {
- emojiCategoryMap[emoji.category].push(name);
+ if (emojiCategoryMap[emoji.c]) {
+ emojiCategoryMap[emoji.c].push(name);
}
});
}
@@ -58,8 +103,9 @@ export function getEmojiInfo(query) {
}
export function emojiFallbackImageSrc(inputName) {
- const { name, digest } = getEmojiInfo(inputName);
- return `${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/emoji/${name}-${digest}.png`;
+ const { name } = getEmojiInfo(inputName);
+ return `${gon.asset_host || ''}${gon.relative_url_root ||
+ ''}/-/emojis/${EMOJI_VERSION}/${name}.png`;
}
export function emojiImageTag(name, src) {
@@ -68,9 +114,8 @@ export function emojiImageTag(name, src) {
export function glEmojiTag(inputName, options) {
const opts = { sprite: false, forceFallback: false, ...options };
- const { name, ...emojiInfo } = getEmojiInfo(inputName);
+ const name = normalizeEmojiName(inputName);
- const fallbackImageSrc = emojiFallbackImageSrc(name);
const fallbackSpriteClass = `emoji-${name}`;
const classList = [];
@@ -79,24 +124,19 @@ export function glEmojiTag(inputName, options) {
classList.push(fallbackSpriteClass);
}
const classAttribute = classList.length > 0 ? `class="${classList.join(' ')}"` : '';
+
const fallbackSpriteAttribute = opts.sprite
? `data-fallback-sprite-class="${fallbackSpriteClass}"`
: '';
- let contents = emojiInfo.moji;
- if (opts.forceFallback && !opts.sprite) {
- contents = emojiImageTag(name, fallbackImageSrc);
- }
+ const forceFallbackAttribute = opts.forceFallback ? 'data-force-fallback="true"' : '';
return `
<gl-emoji
${classAttribute}
data-name="${name}"
- data-fallback-src="${fallbackImageSrc}"
${fallbackSpriteAttribute}
- data-unicode-version="${emojiInfo.unicodeVersion}"
- title="${emojiInfo.description}"
+ ${forceFallbackAttribute}
>
- ${contents}
</gl-emoji>
`;
}
diff --git a/app/assets/javascripts/emoji/no_emoji_validator.js b/app/assets/javascripts/emoji/no_emoji_validator.js
new file mode 100644
index 00000000000..0fd4dd74953
--- /dev/null
+++ b/app/assets/javascripts/emoji/no_emoji_validator.js
@@ -0,0 +1,63 @@
+import { __ } from '~/locale';
+import emojiRegex from 'emoji-regex';
+
+const invalidInputClass = 'gl-field-error-outline';
+
+export default class NoEmojiValidator {
+ constructor(opts = {}) {
+ const container = opts.container || '';
+ this.noEmojiEmelents = document.querySelectorAll(`${container} .js-block-emoji`);
+
+ this.noEmojiEmelents.forEach(element =>
+ element.addEventListener('input', this.eventHandler.bind(this)),
+ );
+ }
+
+ eventHandler(event) {
+ this.inputDomElement = event.target;
+ this.inputErrorMessage = this.inputDomElement.nextSibling;
+
+ const { value } = this.inputDomElement;
+
+ this.validatePattern(value);
+ this.setValidationStateAndMessage();
+ }
+
+ validatePattern(value) {
+ const pattern = emojiRegex();
+ this.hasEmojis = new RegExp(pattern).test(value);
+
+ if (this.hasEmojis) {
+ this.inputDomElement.setCustomValidity(__('Invalid input, please avoid emojis'));
+ } else {
+ this.inputDomElement.setCustomValidity('');
+ }
+ }
+
+ setValidationStateAndMessage() {
+ if (!this.inputDomElement.checkValidity()) {
+ this.setInvalidState();
+ } else {
+ this.clearFieldValidationState();
+ }
+ }
+
+ clearFieldValidationState() {
+ this.inputDomElement.classList.remove(invalidInputClass);
+ this.inputErrorMessage.classList.add('hide');
+ }
+
+ setInvalidState() {
+ this.inputDomElement.classList.add(invalidInputClass);
+ this.setErrorMessage();
+ }
+
+ setErrorMessage() {
+ if (this.hasEmojis) {
+ this.inputErrorMessage.innerHTML = this.inputDomElement.validationMessage;
+ } else {
+ this.inputErrorMessage.innerHTML = this.inputDomElement.title;
+ }
+ this.inputErrorMessage.classList.remove('hide');
+ }
+}
diff --git a/app/assets/javascripts/emoji/support/index.js b/app/assets/javascripts/emoji/support/index.js
index 1f7852dd487..ed9bfb8bc78 100644
--- a/app/assets/javascripts/emoji/support/index.js
+++ b/app/assets/javascripts/emoji/support/index.js
@@ -5,6 +5,9 @@ import getUnicodeSupportMap from './unicode_support_map';
let browserUnicodeSupportMap;
export default function isEmojiUnicodeSupportedByBrowser(emojiUnicode, unicodeVersion) {
+ // Our Spec browser would fail producing emoji maps
+ if (/\bHeadlessChrome\//.test(navigator.userAgent)) return true;
+
browserUnicodeSupportMap = browserUnicodeSupportMap || getUnicodeSupportMap();
return isEmojiUnicodeSupported(browserUnicodeSupportMap, emojiUnicode, unicodeVersion);
}
diff --git a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
new file mode 100644
index 00000000000..a8ee3f4ac10
--- /dev/null
+++ b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
@@ -0,0 +1,108 @@
+<script>
+/**
+ * Render modal to confirm rollback/redeploy.
+ */
+
+import _ from 'underscore';
+import { GlModal } from '@gitlab/ui';
+import { s__, sprintf } from '~/locale';
+
+import eventHub from '../event_hub';
+
+export default {
+ name: 'ConfirmRollbackModal',
+
+ components: {
+ GlModal,
+ },
+
+ props: {
+ environment: {
+ type: Object,
+ required: true,
+ },
+ },
+
+ computed: {
+ modalTitle() {
+ const title = this.environment.isLastDeployment
+ ? s__('Environments|Re-deploy environment %{name}?')
+ : s__('Environments|Rollback environment %{name}?');
+
+ return sprintf(title, {
+ name: _.escape(this.environment.name),
+ });
+ },
+
+ commitShortSha() {
+ const { last_deployment } = this.environment;
+ return this.commitData(last_deployment, 'short_id');
+ },
+
+ commitUrl() {
+ const { last_deployment } = this.environment;
+ return this.commitData(last_deployment, 'commit_path');
+ },
+
+ commitTitle() {
+ const { last_deployment } = this.environment;
+ return this.commitData(last_deployment, 'title');
+ },
+
+ modalText() {
+ const linkStart = `<a class="commit-sha" href="${_.escape(this.commitUrl)}">`;
+ const commitId = _.escape(this.commitShortSha);
+ const linkEnd = '</a>';
+ const name = _.escape(this.name);
+ const body = this.environment.isLastDeployment
+ ? s__(
+ 'Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?',
+ )
+ : s__(
+ 'Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?',
+ );
+ return sprintf(
+ body,
+ {
+ commitId,
+ linkStart,
+ linkEnd,
+ name,
+ },
+ false,
+ );
+ },
+
+ modalActionText() {
+ return this.environment.isLastDeployment
+ ? s__('Environments|Re-deploy')
+ : s__('Environments|Rollback');
+ },
+ },
+
+ methods: {
+ onOk() {
+ eventHub.$emit('rollbackEnvironment', this.environment);
+ },
+
+ commitData(lastDeployment, key) {
+ if (lastDeployment && lastDeployment.commit) {
+ return lastDeployment.commit[key];
+ }
+
+ return '';
+ },
+ },
+};
+</script>
+<template>
+ <gl-modal
+ :title="modalTitle"
+ modal-id="confirm-rollback-modal"
+ :ok-title="modalActionText"
+ ok-variant="danger"
+ @ok="onOk"
+ >
+ <p v-html="modalText"></p>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue
index bd402c0eea5..6ece8b92a30 100644
--- a/app/assets/javascripts/environments/components/container.vue
+++ b/app/assets/javascripts/environments/components/container.vue
@@ -22,10 +22,6 @@ export default {
type: Object,
required: true,
},
- canCreateDeployment: {
- type: Boolean,
- required: true,
- },
canReadEnvironment: {
type: Boolean,
required: true,
@@ -51,11 +47,7 @@ export default {
<slot name="emptyState"></slot>
<div v-if="!isLoading && environments.length > 0" class="table-holder">
- <environment-table
- :environments="environments"
- :can-create-deployment="canCreateDeployment"
- :can-read-environment="canReadEnvironment"
- />
+ <environment-table :environments="environments" :can-read-environment="canReadEnvironment" />
<table-pagination
v-if="pagination && pagination.totalPages > 1"
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue
index 1f7dab9fbd2..208bd19f6b0 100644
--- a/app/assets/javascripts/environments/components/environment_actions.vue
+++ b/app/assets/javascripts/environments/components/environment_actions.vue
@@ -92,7 +92,7 @@ export default {
:disabled="isActionDisabled(action)"
type="button"
class="js-manual-action-link no-btn btn d-flex align-items-center"
- @click="onClickAction(action);"
+ @click="onClickAction(action)"
>
<span class="flex-fill"> {{ action.name }} </span>
<span v-if="action.scheduledAt" class="text-secondary">
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index f44806d82a6..1e89dce69cb 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -3,7 +3,6 @@ import Timeago from 'timeago.js';
import _ from 'underscore';
import { GlTooltipDirective } from '@gitlab/ui';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import { humanize } from '~/lib/utils/text_utility';
import Icon from '~/vue_shared/components/icon.vue';
import ActionsComponent from './environment_actions.vue';
import ExternalUrlComponent from './environment_external_url.vue';
@@ -47,12 +46,6 @@ export default {
default: () => ({}),
},
- canCreateDeployment: {
- type: Boolean,
- required: false,
- default: false,
- },
-
canReadEnvironment: {
type: Boolean,
required: false,
@@ -151,7 +144,7 @@ export default {
},
actions() {
- if (!this.model || !this.model.last_deployment || !this.canCreateDeployment) {
+ if (!this.model || !this.model.last_deployment) {
return [];
}
@@ -162,7 +155,7 @@ export default {
const combinedActions = (manualActions || []).concat(scheduledActions || []);
return combinedActions.map(action => ({
...action,
- name: humanize(action.name),
+ name: action.name,
}));
},
@@ -561,7 +554,8 @@ export default {
/>
<rollback-component
- v-if="canRetry && canCreateDeployment"
+ v-if="canRetry"
+ :environment="model"
:is-last-deployment="isLastDeployment"
:retry-url="retryUrl"
/>
diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue
index 50c86af057c..266cdc42518 100644
--- a/app/assets/javascripts/environments/components/environment_rollback.vue
+++ b/app/assets/javascripts/environments/components/environment_rollback.vue
@@ -5,29 +5,38 @@
*
* Makes a post request when the button is clicked.
*/
+import { GlTooltipDirective, GlLoadingIcon, GlModalDirective, GlButton } from '@gitlab/ui';
import { s__ } from '~/locale';
-import { GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
+import ConfirmRollbackModal from './confirm_rollback_modal.vue';
import eventHub from '../event_hub';
export default {
components: {
Icon,
GlLoadingIcon,
+ GlButton,
+ ConfirmRollbackModal,
},
directives: {
GlTooltip: GlTooltipDirective,
+ GlModal: GlModalDirective,
},
props: {
- retryUrl: {
- type: String,
- default: '',
- },
-
isLastDeployment: {
type: Boolean,
default: true,
},
+
+ environment: {
+ type: Object,
+ required: true,
+ },
+
+ retryUrl: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
@@ -45,23 +54,31 @@ export default {
methods: {
onClick() {
- this.isLoading = true;
-
- eventHub.$emit('postAction', { endpoint: this.retryUrl });
+ eventHub.$emit('requestRollbackEnvironment', {
+ ...this.environment,
+ retryUrl: this.retryUrl,
+ isLastDeployment: this.isLastDeployment,
+ });
+ eventHub.$on('rollbackEnvironment', environment => {
+ if (environment.id === this.environment.id) {
+ this.isLoading = true;
+ }
+ });
},
},
};
</script>
<template>
- <button
+ <gl-button
v-gl-tooltip
+ v-gl-modal.confirm-rollback-modal
+ variant="secondary"
:disabled="isLoading"
:title="title"
- type="button"
- class="btn d-none d-sm-none d-md-block"
+ class="d-none d-md-block"
@click="onClick"
>
<icon v-if="isLastDeployment" name="repeat" /> <icon v-else name="redo" />
<gl-loading-icon v-if="isLoading" />
- </button>
+ </gl-button>
</template>
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue
index ae9459a2482..6e55c3f901a 100644
--- a/app/assets/javascripts/environments/components/environments_app.vue
+++ b/app/assets/javascripts/environments/components/environments_app.vue
@@ -6,11 +6,13 @@ import eventHub from '../event_hub';
import environmentsMixin from '../mixins/environments_mixin';
import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
import StopEnvironmentModal from './stop_environment_modal.vue';
+import ConfirmRollbackModal from './confirm_rollback_modal.vue';
export default {
components: {
emptyState,
StopEnvironmentModal,
+ ConfirmRollbackModal,
},
mixins: [CIPaginationMixin, environmentsMixin],
@@ -24,10 +26,6 @@ export default {
type: Boolean,
required: true,
},
- canCreateDeployment: {
- type: Boolean,
- required: true,
- },
canReadEnvironment: {
type: Boolean,
required: true,
@@ -91,14 +89,15 @@ export default {
<template>
<div :class="cssContainerClass">
<stop-environment-modal :environment="environmentInStopModal" />
+ <confirm-rollback-modal :environment="environmentInRollbackModal" />
<div class="top-area">
<tabs :tabs="tabs" scope="environments" @onChangeTab="onChangeTab" />
<div v-if="canCreateEnvironment && !isLoading" class="nav-controls">
- <a :href="newEnvironmentPath" class="btn btn-success">
- {{ s__('Environments|New environment') }}
- </a>
+ <a :href="newEnvironmentPath" class="btn btn-success">{{
+ s__('Environments|New environment')
+ }}</a>
</div>
</div>
@@ -106,7 +105,6 @@ export default {
:is-loading="isLoading"
:environments="state.environments"
:pagination="state.paginationInformation"
- :can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"
@onChangePage="onChangePage"
>
diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue
index 533e90e2222..eef141a07ba 100644
--- a/app/assets/javascripts/environments/components/environments_table.vue
+++ b/app/assets/javascripts/environments/components/environments_table.vue
@@ -3,6 +3,7 @@
* Render environments table.
*/
import { GlLoadingIcon } from '@gitlab/ui';
+import _ from 'underscore';
import environmentItem from './environment_item.vue';
export default {
@@ -23,11 +24,14 @@ export default {
required: false,
default: false,
},
-
- canCreateDeployment: {
- type: Boolean,
- required: false,
- default: false,
+ },
+ computed: {
+ sortedEnvironments() {
+ return this.sortEnvironments(this.environments).map(env =>
+ this.shouldRenderFolderContent(env)
+ ? { ...env, children: this.sortEnvironments(env.children) }
+ : env,
+ );
},
},
methods: {
@@ -37,6 +41,30 @@ export default {
shouldRenderFolderContent(env) {
return env.isFolder && env.isOpen && env.children && env.children.length > 0;
},
+ sortEnvironments(environments) {
+ /*
+ * The sorting algorithm should sort in the following priorities:
+ *
+ * 1. folders first,
+ * 2. last updated descending,
+ * 3. by name ascending,
+ *
+ * the sorting algorithm must:
+ *
+ * 1. Sort by name ascending,
+ * 2. Reverse (sort by name descending),
+ * 3. Sort by last deployment ascending,
+ * 4. Reverse (last deployment descending, name ascending),
+ * 5. Put folders first.
+ */
+ return _.chain(environments)
+ .sortBy(env => (env.isFolder ? env.folderName : env.name))
+ .reverse()
+ .sortBy(env => (env.last_deployment ? env.last_deployment.created_at : '0000'))
+ .reverse()
+ .sortBy(env => (env.isFolder ? -1 : 1))
+ .value();
+ },
},
};
</script>
@@ -59,12 +87,11 @@ export default {
{{ s__('Environments|Updated') }}
</div>
</div>
- <template v-for="(model, i) in environments" :model="model">
+ <template v-for="(model, i) in sortedEnvironments" :model="model">
<div
is="environment-item"
:key="`environment-item-${i}`"
:model="model"
- :can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"
/>
@@ -79,15 +106,14 @@ export default {
v-for="(children, index) in model.children"
:key="`env-item-${i}-${index}`"
:model="children"
- :can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"
/>
<div :key="`sub-div-${i}`">
<div class="text-center prepend-top-10">
- <a :href="folderUrl(model)" class="btn btn-default">
- {{ s__('Environments|Show all') }}
- </a>
+ <a :href="folderUrl(model)" class="btn btn-default">{{
+ s__('Environments|Show all')
+ }}</a>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
index 3cf6e4ad14d..56e7f69cad6 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js
+++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
@@ -15,11 +15,10 @@ export default () =>
const environmentsData = document.querySelector(this.$options.el).dataset;
return {
- endpoint: environmentsData.endpoint,
- folderName: environmentsData.folderName,
+ endpoint: environmentsData.environmentsDataEndpoint,
+ folderName: environmentsData.environmentsDataFolderName,
cssContainerClass: environmentsData.cssClass,
- canCreateDeployment: parseBoolean(environmentsData.canCreateDeployment),
- canReadEnvironment: parseBoolean(environmentsData.canReadEnvironment),
+ canReadEnvironment: parseBoolean(environmentsData.environmentsDataCanReadEnvironment),
};
},
render(createElement) {
@@ -28,7 +27,6 @@ export default () =>
endpoint: this.endpoint,
folderName: this.folderName,
cssContainerClass: this.cssContainerClass,
- canCreateDeployment: this.canCreateDeployment,
canReadEnvironment: this.canReadEnvironment,
},
});
diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue
index d6f0b6115a6..80f0e00400b 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_view.vue
+++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue
@@ -23,10 +23,6 @@ export default {
type: String,
required: true,
},
- canCreateDeployment: {
- type: Boolean,
- required: true,
- },
canReadEnvironment: {
type: Boolean,
required: true,
@@ -55,7 +51,6 @@ export default {
:is-loading="isLoading"
:environments="state.environments"
:pagination="state.paginationInformation"
- :can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"
@onChangePage="onChangePage"
/>
diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js
index d366e7550b7..6af66d0f86e 100644
--- a/app/assets/javascripts/environments/index.js
+++ b/app/assets/javascripts/environments/index.js
@@ -20,7 +20,6 @@ export default () =>
helpPagePath: environmentsData.helpPagePath,
cssContainerClass: environmentsData.cssClass,
canCreateEnvironment: parseBoolean(environmentsData.canCreateEnvironment),
- canCreateDeployment: parseBoolean(environmentsData.canCreateDeployment),
canReadEnvironment: parseBoolean(environmentsData.canReadEnvironment),
};
},
@@ -32,7 +31,6 @@ export default () =>
helpPagePath: this.helpPagePath,
cssContainerClass: this.cssContainerClass,
canCreateEnvironment: this.canCreateEnvironment,
- canCreateDeployment: this.canCreateDeployment,
canReadEnvironment: this.canReadEnvironment,
},
});
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index 96dc1f07cb9..71b6b578196 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -36,6 +36,7 @@ export default {
page: getParameterByName('page') || '1',
requestData: {},
environmentInStopModal: {},
+ environmentInRollbackModal: {},
};
},
@@ -43,7 +44,11 @@ export default {
saveData(resp) {
this.isLoading = false;
- if (_.isEqual(resp.config.params, this.requestData)) {
+ // Prevent the absence of the nested flag from causing mismatches
+ const response = this.filterNilValues(resp.config.params);
+ const request = this.filterNilValues(this.requestData);
+
+ if (_.isEqual(response, request)) {
this.store.storeAvailableCount(resp.data.available_count);
this.store.storeStoppedCount(resp.data.stopped_count);
this.store.storeEnvironments(resp.data.environments);
@@ -51,6 +56,10 @@ export default {
}
},
+ filterNilValues(obj) {
+ return _.omit(obj, value => _.isUndefined(value) || _.isNull(value));
+ },
+
/**
* Handles URL and query parameter changes.
* When the user uses the pagination or the tabs,
@@ -64,10 +73,9 @@ export default {
// fetch new data
return this.service
.fetchEnvironments(this.requestData)
- .then(response => this.successCallback(response))
- .then(() => {
- // restart polling
- this.poll.restart({ data: this.requestData });
+ .then(response => {
+ this.successCallback(response);
+ this.poll.enable({ data: this.requestData, response });
})
.catch(() => {
this.errorCallback();
@@ -109,6 +117,10 @@ export default {
this.environmentInStopModal = environment;
},
+ updateRollbackModal(environment) {
+ this.environmentInRollbackModal = environment;
+ },
+
stopEnvironment(environment) {
const endpoint = environment.stop_path;
const errorMessage = s__(
@@ -116,6 +128,16 @@ export default {
);
this.postAction({ endpoint, errorMessage });
},
+
+ rollbackEnvironment(environment) {
+ const { retryUrl, isLastDeployment } = environment;
+ const errorMessage = isLastDeployment
+ ? s__('Environments|An error occurred while re-deploying the environment, please try again')
+ : s__(
+ 'Environments|An error occurred while rolling back the environment, please try again',
+ );
+ this.postAction({ endpoint: retryUrl, errorMessage });
+ },
},
computed: {
@@ -143,7 +165,7 @@ export default {
*/
created() {
this.service = new EnvironmentsService(this.endpoint);
- this.requestData = { page: this.page, scope: this.scope };
+ this.requestData = { page: this.page, scope: this.scope, nested: true };
this.poll = new Poll({
resource: this.service,
@@ -174,11 +196,17 @@ export default {
eventHub.$on('postAction', this.postAction);
eventHub.$on('requestStopEnvironment', this.updateStopModal);
eventHub.$on('stopEnvironment', this.stopEnvironment);
+
+ eventHub.$on('requestRollbackEnvironment', this.updateRollbackModal);
+ eventHub.$on('rollbackEnvironment', this.rollbackEnvironment);
},
beforeDestroy() {
eventHub.$off('postAction', this.postAction);
eventHub.$off('requestStopEnvironment', this.updateStopModal);
eventHub.$off('stopEnvironment', this.stopEnvironment);
+
+ eventHub.$off('requestRollbackEnvironment', this.updateRollbackModal);
+ eventHub.$off('rollbackEnvironment', this.rollbackEnvironment);
},
};
diff --git a/app/assets/javascripts/environments/services/environments_service.js b/app/assets/javascripts/environments/services/environments_service.js
index 4e07ccba91a..cb4ff6856db 100644
--- a/app/assets/javascripts/environments/services/environments_service.js
+++ b/app/assets/javascripts/environments/services/environments_service.js
@@ -7,8 +7,8 @@ export default class EnvironmentsService {
}
fetchEnvironments(options = {}) {
- const { scope, page } = options;
- return axios.get(this.environmentsEndpoint, { params: { scope, page } });
+ const { scope, page, nested } = options;
+ return axios.get(this.environmentsEndpoint, { params: { scope, page, nested } });
}
// eslint-disable-next-line class-methods-use-this
diff --git a/app/assets/javascripts/environments/stores/environments_store.js b/app/assets/javascripts/environments/stores/environments_store.js
index 5808a2d4afa..ac9a31c202c 100644
--- a/app/assets/javascripts/environments/stores/environments_store.js
+++ b/app/assets/javascripts/environments/stores/environments_store.js
@@ -20,7 +20,8 @@ export default class EnvironmentsStore {
*
* Stores the received environments.
*
- * In the main environments endpoint, each environment has the following schema
+ * In the main environments endpoint (with { nested: true } in params), each folder
+ * has the following schema:
* { name: String, size: Number, latest: Object }
* In the endpoint to retrieve environments from each folder, the environment does
* not have the `latest` key and the data is all in the root level.
diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
new file mode 100644
index 00000000000..43ae54133af
--- /dev/null
+++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
@@ -0,0 +1,124 @@
+<script>
+import { mapActions, mapState } from 'vuex';
+import { GlEmptyState, GlButton, GlLink, GlLoadingIcon, GlTable } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import { __ } from '~/locale';
+
+export default {
+ fields: [
+ { key: 'error', label: __('Open errors') },
+ { key: 'events', label: __('Events') },
+ { key: 'users', label: __('Users') },
+ { key: 'lastSeen', label: __('Last seen') },
+ ],
+ components: {
+ GlEmptyState,
+ GlButton,
+ GlLink,
+ GlLoadingIcon,
+ GlTable,
+ Icon,
+ TimeAgo,
+ },
+ props: {
+ indexPath: {
+ type: String,
+ required: true,
+ },
+ enableErrorTrackingLink: {
+ type: String,
+ required: true,
+ },
+ errorTrackingEnabled: {
+ type: Boolean,
+ required: true,
+ },
+ illustrationPath: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(['errors', 'externalUrl', 'loading']),
+ },
+ created() {
+ if (this.errorTrackingEnabled) {
+ this.startPolling(this.indexPath);
+ }
+ },
+ methods: {
+ ...mapActions(['startPolling', 'restartPolling']),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div v-if="errorTrackingEnabled">
+ <div v-if="loading" class="py-3">
+ <gl-loading-icon :size="3" />
+ </div>
+ <div v-else>
+ <div class="d-flex justify-content-end">
+ <gl-button class="my-3 ml-auto" variant="primary" :href="externalUrl" target="_blank">
+ {{ __('View in Sentry') }}
+ <icon name="external-link" />
+ </gl-button>
+ </div>
+ <gl-table :items="errors" :fields="$options.fields" :show-empty="true">
+ <template slot="HEAD_events" slot-scope="data">
+ <div class="text-right">{{ data.label }}</div>
+ </template>
+ <template slot="HEAD_users" slot-scope="data">
+ <div class="text-right">{{ data.label }}</div>
+ </template>
+ <template slot="error" slot-scope="errors">
+ <div class="d-flex flex-column">
+ <div class="d-flex">
+ <gl-link :href="errors.item.externalUrl" class="d-flex text-dark" target="_blank">
+ <strong>{{ errors.item.title.trim() }}</strong>
+ <icon name="external-link" class="ml-1" />
+ </gl-link>
+ <span class="text-secondary ml-2">{{ errors.item.culprit }}</span>
+ </div>
+ {{ errors.item.message || __('No details available') }}
+ </div>
+ </template>
+
+ <template slot="events" slot-scope="errors">
+ <div class="text-right">{{ errors.item.count }}</div>
+ </template>
+
+ <template slot="users" slot-scope="errors">
+ <div class="text-right">{{ errors.item.userCount }}</div>
+ </template>
+
+ <template slot="lastSeen" slot-scope="errors">
+ <div class="d-flex align-items-center">
+ <icon name="calendar" css-classes="text-secondary mr-1" />
+ <time-ago :time="errors.item.lastSeen" class="text-secondary" />
+ </div>
+ </template>
+ <template slot="empty">
+ <div ref="empty">
+ {{ __('No errors to display.') }}
+ <gl-link class="js-try-again" @click="restartPolling">
+ {{ __('Check again') }}
+ </gl-link>
+ </div>
+ </template>
+ </gl-table>
+ </div>
+ </div>
+ <div v-else>
+ <gl-empty-state
+ :title="__('Get started with error tracking')"
+ :description="__('Monitor your errors by integrating with Sentry')"
+ :primary-button-text="__('Enable error tracking')"
+ :primary-button-link="enableErrorTrackingLink"
+ :svg-path="illustrationPath"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/error_tracking/index.js b/app/assets/javascripts/error_tracking/index.js
new file mode 100644
index 00000000000..3d609448efe
--- /dev/null
+++ b/app/assets/javascripts/error_tracking/index.js
@@ -0,0 +1,31 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import store from './store';
+import ErrorTrackingList from './components/error_tracking_list.vue';
+
+export default () => {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: '#js-error_tracking',
+ components: {
+ ErrorTrackingList,
+ },
+ store,
+ render(createElement) {
+ const domEl = document.querySelector(this.$options.el);
+ const { indexPath, enableErrorTrackingLink, illustrationPath } = domEl.dataset;
+ let { errorTrackingEnabled } = domEl.dataset;
+
+ errorTrackingEnabled = parseBoolean(errorTrackingEnabled);
+
+ return createElement('error-tracking-list', {
+ props: {
+ indexPath,
+ enableErrorTrackingLink,
+ errorTrackingEnabled,
+ illustrationPath,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/error_tracking/services/index.js b/app/assets/javascripts/error_tracking/services/index.js
new file mode 100644
index 00000000000..ab89521dc46
--- /dev/null
+++ b/app/assets/javascripts/error_tracking/services/index.js
@@ -0,0 +1,7 @@
+import axios from '~/lib/utils/axios_utils';
+
+export default {
+ getErrorList({ endpoint }) {
+ return axios.get(endpoint);
+ },
+};
diff --git a/app/assets/javascripts/error_tracking/store/actions.js b/app/assets/javascripts/error_tracking/store/actions.js
new file mode 100644
index 00000000000..d42e4f145dc
--- /dev/null
+++ b/app/assets/javascripts/error_tracking/store/actions.js
@@ -0,0 +1,52 @@
+import Service from '../services';
+import * as types from './mutation_types';
+import createFlash from '~/flash';
+import Poll from '~/lib/utils/poll';
+import { __, sprintf } from '~/locale';
+
+let eTagPoll;
+
+export function startPolling({ commit, dispatch }, endpoint) {
+ eTagPoll = new Poll({
+ resource: Service,
+ method: 'getErrorList',
+ data: { endpoint },
+ successCallback: ({ data }) => {
+ if (!data) {
+ return;
+ }
+ commit(types.SET_ERRORS, data.errors);
+ commit(types.SET_EXTERNAL_URL, data.external_url);
+ commit(types.SET_LOADING, false);
+ dispatch('stopPolling');
+ },
+ errorCallback: response => {
+ let errorMessage = '';
+ if (response && response.data && response.data.message) {
+ errorMessage = response.data.message;
+ }
+ commit(types.SET_LOADING, false);
+ createFlash(
+ sprintf(__(`Failed to load errors from Sentry. Error message: %{errorMessage}`), {
+ errorMessage,
+ }),
+ );
+ },
+ });
+
+ eTagPoll.makeRequest();
+}
+
+export const stopPolling = () => {
+ if (eTagPoll) eTagPoll.stop();
+};
+
+export function restartPolling({ commit }) {
+ commit(types.SET_ERRORS, []);
+ commit(types.SET_EXTERNAL_URL, '');
+ commit(types.SET_LOADING, true);
+
+ if (eTagPoll) eTagPoll.restart();
+}
+
+export default () => {};
diff --git a/app/assets/javascripts/error_tracking/store/index.js b/app/assets/javascripts/error_tracking/store/index.js
new file mode 100644
index 00000000000..3136682fb64
--- /dev/null
+++ b/app/assets/javascripts/error_tracking/store/index.js
@@ -0,0 +1,19 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import * as actions from './actions';
+import mutations from './mutations';
+
+Vue.use(Vuex);
+
+export const createStore = () =>
+ new Vuex.Store({
+ state: {
+ errors: [],
+ externalUrl: '',
+ loading: true,
+ },
+ actions,
+ mutations,
+ });
+
+export default createStore();
diff --git a/app/assets/javascripts/error_tracking/store/mutation_types.js b/app/assets/javascripts/error_tracking/store/mutation_types.js
new file mode 100644
index 00000000000..f9d77a6b08e
--- /dev/null
+++ b/app/assets/javascripts/error_tracking/store/mutation_types.js
@@ -0,0 +1,3 @@
+export const SET_ERRORS = 'SET_ERRORS';
+export const SET_EXTERNAL_URL = 'SET_EXTERNAL_URL';
+export const SET_LOADING = 'SET_LOADING';
diff --git a/app/assets/javascripts/error_tracking/store/mutations.js b/app/assets/javascripts/error_tracking/store/mutations.js
new file mode 100644
index 00000000000..e4bd81db9c9
--- /dev/null
+++ b/app/assets/javascripts/error_tracking/store/mutations.js
@@ -0,0 +1,14 @@
+import * as types from './mutation_types';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
+export default {
+ [types.SET_ERRORS](state, data) {
+ state.errors = convertObjectPropsToCamelCase(data, { deep: true });
+ },
+ [types.SET_EXTERNAL_URL](state, url) {
+ state.externalUrl = url;
+ },
+ [types.SET_LOADING](state, loading) {
+ state.loading = loading;
+ },
+};
diff --git a/app/assets/javascripts/error_tracking_settings/components/app.vue b/app/assets/javascripts/error_tracking_settings/components/app.vue
new file mode 100644
index 00000000000..50eb3e63b7c
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/components/app.vue
@@ -0,0 +1,129 @@
+<script>
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { GlButton } from '@gitlab/ui';
+import ProjectDropdown from './project_dropdown.vue';
+import ErrorTrackingForm from './error_tracking_form.vue';
+
+export default {
+ components: { ProjectDropdown, ErrorTrackingForm, GlButton },
+ props: {
+ initialApiHost: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialEnabled: {
+ type: String,
+ required: true,
+ },
+ initialProject: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ initialToken: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ listProjectsEndpoint: {
+ type: String,
+ required: true,
+ },
+ operationsSettingsEndpoint: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapGetters([
+ 'dropdownLabel',
+ 'hasProjects',
+ 'invalidProjectLabel',
+ 'isProjectInvalid',
+ 'projectSelectionLabel',
+ ]),
+ ...mapState([
+ 'apiHost',
+ 'connectError',
+ 'connectSuccessful',
+ 'enabled',
+ 'projects',
+ 'selectedProject',
+ 'settingsLoading',
+ 'token',
+ ]),
+ },
+ created() {
+ this.setInitialState({
+ apiHost: this.initialApiHost,
+ enabled: this.initialEnabled,
+ project: this.initialProject,
+ token: this.initialToken,
+ listProjectsEndpoint: this.listProjectsEndpoint,
+ operationsSettingsEndpoint: this.operationsSettingsEndpoint,
+ });
+ },
+ methods: {
+ ...mapActions([
+ 'fetchProjects',
+ 'setInitialState',
+ 'updateApiHost',
+ 'updateEnabled',
+ 'updateSelectedProject',
+ 'updateSettings',
+ 'updateToken',
+ ]),
+ handleSubmit() {
+ this.updateSettings();
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="form-check form-group">
+ <input
+ id="error-tracking-enabled"
+ :checked="enabled"
+ class="form-check-input"
+ type="checkbox"
+ @change="updateEnabled($event.target.checked)"
+ />
+ <label class="form-check-label" for="error-tracking-enabled">{{
+ s__('ErrorTracking|Active')
+ }}</label>
+ </div>
+ <error-tracking-form
+ :api-host="apiHost"
+ :connect-error="connectError"
+ :connect-successful="connectSuccessful"
+ :token="token"
+ @handle-connect="fetchProjects"
+ @update-api-host="updateApiHost"
+ @update-token="updateToken"
+ />
+ <div class="form-group">
+ <project-dropdown
+ :has-projects="hasProjects"
+ :invalid-project-label="invalidProjectLabel"
+ :is-project-invalid="isProjectInvalid"
+ :dropdown-label="dropdownLabel"
+ :project-selection-label="projectSelectionLabel"
+ :projects="projects"
+ :selected-project="selectedProject"
+ :token="token"
+ @select-project="updateSelectedProject"
+ />
+ </div>
+ <gl-button
+ :disabled="settingsLoading"
+ class="js-error-tracking-button"
+ variant="success"
+ @click="handleSubmit"
+ >
+ {{ __('Save changes') }}
+ </gl-button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
new file mode 100644
index 00000000000..060d8e25227
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
@@ -0,0 +1,91 @@
+<script>
+import { GlButton, GlFormInput } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ components: { GlButton, GlFormInput, Icon },
+ props: {
+ apiHost: {
+ type: String,
+ required: true,
+ },
+ connectError: {
+ type: Boolean,
+ required: true,
+ },
+ connectSuccessful: {
+ type: Boolean,
+ required: true,
+ },
+ token: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ tokenInputState() {
+ return this.connectError ? false : null;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="form-group">
+ <label class="label-bold" for="error-tracking-api-host">{{ __('Sentry API URL') }}</label>
+ <div class="row">
+ <div class="col-8 col-md-9 gl-pr-0">
+ <gl-form-input
+ id="error-tracking-api-host"
+ :value="apiHost"
+ placeholder="https://mysentryserver.com"
+ @input="$emit('update-api-host', $event)"
+ />
+ </div>
+ </div>
+ <p class="form-text text-muted">
+ {{ s__('ErrorTracking|Find your hostname in your Sentry account settings page') }}
+ </p>
+ </div>
+ <div class="form-group" :class="{ 'gl-show-field-errors': connectError }">
+ <label class="label-bold" for="error-tracking-token">{{
+ s__('ErrorTracking|Auth Token')
+ }}</label>
+ <div class="row">
+ <div class="col-8 col-md-9 gl-pr-0">
+ <gl-form-input
+ id="error-tracking-token"
+ :value="token"
+ :state="tokenInputState"
+ @input="$emit('update-token', $event)"
+ />
+ </div>
+ <div class="col-4 col-md-3 gl-pl-0">
+ <gl-button
+ class="js-error-tracking-connect prepend-left-5"
+ @click="$emit('handle-connect')"
+ >
+ {{ __('Connect') }}
+ </gl-button>
+ <icon
+ v-show="connectSuccessful"
+ class="js-error-tracking-connect-success prepend-left-5 text-success align-middle"
+ :aria-label="__('Projects Successfully Retrieved')"
+ name="check-circle"
+ />
+ </div>
+ </div>
+ <p v-if="connectError" class="gl-field-error">
+ {{ s__('ErrorTracking|Connection has failed. Re-check Auth Token and try again.') }}
+ </p>
+ <p v-else class="form-text text-muted">
+ {{
+ s__(
+ "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects",
+ )
+ }}
+ </p>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue b/app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue
new file mode 100644
index 00000000000..82df02afafd
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue
@@ -0,0 +1,82 @@
+<script>
+import { GlDropdown, GlDropdownHeader, GlDropdownItem } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+import { getDisplayName } from '../utils';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownHeader,
+ GlDropdownItem,
+ Icon,
+ },
+ props: {
+ dropdownLabel: {
+ type: String,
+ required: true,
+ },
+ hasProjects: {
+ type: Boolean,
+ required: true,
+ },
+ invalidProjectLabel: {
+ type: String,
+ required: true,
+ },
+ isProjectInvalid: {
+ type: Boolean,
+ required: true,
+ },
+ projects: {
+ type: Array,
+ required: true,
+ },
+ selectedProject: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ projectSelectionLabel: {
+ type: String,
+ required: true,
+ },
+ token: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ getDisplayName,
+ },
+};
+</script>
+
+<template>
+ <div :class="{ 'gl-show-field-errors': isProjectInvalid }">
+ <label class="label-bold" for="project-dropdown">{{ __('Project') }}</label>
+ <div class="row">
+ <gl-dropdown
+ id="project-dropdown"
+ class="col-8 col-md-9 gl-pr-0"
+ :disabled="!hasProjects"
+ menu-class="w-100 mw-100"
+ toggle-class="dropdown-menu-toggle w-100 gl-field-error-outline"
+ :text="dropdownLabel"
+ >
+ <gl-dropdown-item
+ v-for="project in projects"
+ :key="`${project.organizationSlug}.${project.slug}`"
+ class="w-100"
+ @click="$emit('select-project', project)"
+ >{{ getDisplayName(project) }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
+ <p v-if="isProjectInvalid" class="js-project-dropdown-error gl-field-error">
+ {{ invalidProjectLabel }}
+ </p>
+ <p v-else-if="!hasProjects" class="js-project-dropdown-label form-text text-muted">
+ {{ projectSelectionLabel }}
+ </p>
+ </div>
+</template>
diff --git a/app/assets/javascripts/error_tracking_settings/index.js b/app/assets/javascripts/error_tracking_settings/index.js
new file mode 100644
index 00000000000..ce315963723
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/index.js
@@ -0,0 +1,27 @@
+import Vue from 'vue';
+import ErrorTrackingSettings from './components/app.vue';
+import createStore from './store';
+
+export default () => {
+ const formContainerEl = document.querySelector('.js-error-tracking-form');
+ const {
+ dataset: { apiHost, enabled, project, token, listProjectsEndpoint, operationsSettingsEndpoint },
+ } = formContainerEl;
+
+ return new Vue({
+ el: formContainerEl,
+ store: createStore(),
+ render(createElement) {
+ return createElement(ErrorTrackingSettings, {
+ props: {
+ initialApiHost: apiHost,
+ initialEnabled: enabled,
+ initialProject: project,
+ initialToken: token,
+ listProjectsEndpoint,
+ operationsSettingsEndpoint,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/error_tracking_settings/store/actions.js b/app/assets/javascripts/error_tracking_settings/store/actions.js
new file mode 100644
index 00000000000..95105797807
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/store/actions.js
@@ -0,0 +1,91 @@
+import { __ } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
+import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import createFlash from '~/flash';
+import { transformFrontendSettings } from '../utils';
+import * as types from './mutation_types';
+
+export const requestProjects = ({ commit }) => {
+ commit(types.RESET_CONNECT);
+};
+
+export const receiveProjectsSuccess = ({ commit }, projects) => {
+ commit(types.UPDATE_CONNECT_SUCCESS);
+ commit(types.RECEIVE_PROJECTS, projects);
+};
+
+export const receiveProjectsError = ({ commit }) => {
+ commit(types.UPDATE_CONNECT_ERROR);
+ commit(types.CLEAR_PROJECTS);
+};
+
+export const fetchProjects = ({ dispatch, state }) => {
+ dispatch('requestProjects');
+ return axios
+ .post(state.listProjectsEndpoint, {
+ error_tracking_setting: {
+ api_host: state.apiHost,
+ token: state.token,
+ },
+ })
+ .then(({ data: { projects } }) => {
+ dispatch('receiveProjectsSuccess', projects);
+ })
+ .catch(() => {
+ dispatch('receiveProjectsError');
+ });
+};
+
+export const requestSettings = ({ commit }) => {
+ commit(types.UPDATE_SETTINGS_LOADING, true);
+};
+
+export const receiveSettingsError = ({ commit }, { response = {} }) => {
+ const message = response.data && response.data.message ? response.data.message : '';
+
+ createFlash(`${__('There was an error saving your changes.')} ${message}`, 'alert');
+ commit(types.UPDATE_SETTINGS_LOADING, false);
+};
+
+export const updateSettings = ({ dispatch, state }) => {
+ dispatch('requestSettings');
+ return axios
+ .patch(state.operationsSettingsEndpoint, {
+ project: {
+ error_tracking_setting_attributes: {
+ ...transformFrontendSettings(state),
+ },
+ },
+ })
+ .then(() => {
+ refreshCurrentPage();
+ })
+ .catch(err => {
+ dispatch('receiveSettingsError', err);
+ });
+};
+
+export const updateApiHost = ({ commit }, apiHost) => {
+ commit(types.UPDATE_API_HOST, apiHost);
+ commit(types.RESET_CONNECT);
+};
+
+export const updateEnabled = ({ commit }, enabled) => {
+ commit(types.UPDATE_ENABLED, enabled);
+};
+
+export const updateToken = ({ commit }, token) => {
+ commit(types.UPDATE_TOKEN, token);
+ commit(types.RESET_CONNECT);
+};
+
+export const updateSelectedProject = ({ commit }, selectedProject) => {
+ commit(types.UPDATE_SELECTED_PROJECT, selectedProject);
+};
+
+export const setInitialState = ({ commit }, data) => {
+ commit(types.SET_INITIAL_STATE, data);
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/error_tracking_settings/store/getters.js b/app/assets/javascripts/error_tracking_settings/store/getters.js
new file mode 100644
index 00000000000..a008b181907
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/store/getters.js
@@ -0,0 +1,44 @@
+import _ from 'underscore';
+import { __, s__, sprintf } from '~/locale';
+import { getDisplayName } from '../utils';
+
+export const hasProjects = state => !!state.projects && state.projects.length > 0;
+
+export const isProjectInvalid = (state, getters) =>
+ !!state.selectedProject &&
+ getters.hasProjects &&
+ !state.projects.some(project => _.isMatch(state.selectedProject, project));
+
+export const dropdownLabel = (state, getters) => {
+ if (state.selectedProject !== null) {
+ return getDisplayName(state.selectedProject);
+ }
+ if (!getters.hasProjects) {
+ return s__('ErrorTracking|No projects available');
+ }
+ return s__('ErrorTracking|Select project');
+};
+
+export const invalidProjectLabel = state => {
+ if (state.selectedProject) {
+ return sprintf(
+ __('Project "%{name}" is no longer available. Select another project to continue.'),
+ {
+ name: state.selectedProject.name,
+ },
+ );
+ }
+ return '';
+};
+
+export const projectSelectionLabel = state => {
+ if (state.token) {
+ return s__(
+ "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown.",
+ );
+ }
+ return s__('ErrorTracking|To enable project selection, enter a valid Auth Token');
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/error_tracking_settings/store/index.js b/app/assets/javascripts/error_tracking_settings/store/index.js
new file mode 100644
index 00000000000..560f265a2ea
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/store/index.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import createState from './state';
+import * as actions from './actions';
+import * as getters from './getters';
+import mutations from './mutations';
+
+Vue.use(Vuex);
+
+export default () =>
+ new Vuex.Store({
+ state: createState(),
+ actions,
+ getters,
+ mutations,
+ });
diff --git a/app/assets/javascripts/error_tracking_settings/store/mutation_types.js b/app/assets/javascripts/error_tracking_settings/store/mutation_types.js
new file mode 100644
index 00000000000..b4f8a237947
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/store/mutation_types.js
@@ -0,0 +1,11 @@
+export const CLEAR_PROJECTS = 'CLEAR_PROJECTS';
+export const SET_INITIAL_STATE = 'SET_INITIAL_STATE';
+export const RECEIVE_PROJECTS = 'RECEIVE_PROJECTS';
+export const RESET_CONNECT = 'RESET_CONNECT';
+export const UPDATE_API_HOST = 'UPDATE_API_HOST';
+export const UPDATE_CONNECT_ERROR = 'UPDATE_CONNECT_ERROR';
+export const UPDATE_CONNECT_SUCCESS = 'UPDATE_CONNECT_SUCCESS';
+export const UPDATE_ENABLED = 'UPDATE_ENABLED';
+export const UPDATE_SELECTED_PROJECT = 'UPDATE_SELECTED_PROJECT';
+export const UPDATE_SETTINGS_LOADING = 'UPDATE_SETTINGS_LOADING';
+export const UPDATE_TOKEN = 'UPDATE_TOKEN';
diff --git a/app/assets/javascripts/error_tracking_settings/store/mutations.js b/app/assets/javascripts/error_tracking_settings/store/mutations.js
new file mode 100644
index 00000000000..4089d1ee94e
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/store/mutations.js
@@ -0,0 +1,61 @@
+import _ from 'underscore';
+import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
+import * as types from './mutation_types';
+import { projectKeys } from '../utils';
+
+export default {
+ [types.CLEAR_PROJECTS](state) {
+ state.projects = [];
+ },
+ [types.RECEIVE_PROJECTS](state, projects) {
+ state.projects = projects
+ .map(convertObjectPropsToCamelCase)
+ // The `pick` strips out extra properties returned from Sentry.
+ // Such properties could be problematic later, e.g. when checking whether `projects` contains `selectedProject`
+ .map(project => _.pick(project, projectKeys));
+ },
+ [types.RESET_CONNECT](state) {
+ state.connectSuccessful = false;
+ state.connectError = false;
+ },
+ [types.SET_INITIAL_STATE](
+ state,
+ { apiHost, enabled, project, token, listProjectsEndpoint, operationsSettingsEndpoint },
+ ) {
+ state.enabled = parseBoolean(enabled);
+ state.apiHost = apiHost;
+ state.token = token;
+ state.listProjectsEndpoint = listProjectsEndpoint;
+ state.operationsSettingsEndpoint = operationsSettingsEndpoint;
+
+ if (project) {
+ state.selectedProject = _.pick(
+ convertObjectPropsToCamelCase(JSON.parse(project)),
+ projectKeys,
+ );
+ }
+ },
+ [types.UPDATE_API_HOST](state, apiHost) {
+ state.apiHost = apiHost;
+ },
+ [types.UPDATE_ENABLED](state, enabled) {
+ state.enabled = enabled;
+ },
+ [types.UPDATE_TOKEN](state, token) {
+ state.token = token;
+ },
+ [types.UPDATE_SELECTED_PROJECT](state, selectedProject) {
+ state.selectedProject = selectedProject;
+ },
+ [types.UPDATE_SETTINGS_LOADING](state, settingsLoading) {
+ state.settingsLoading = settingsLoading;
+ },
+ [types.UPDATE_CONNECT_SUCCESS](state) {
+ state.connectSuccessful = true;
+ state.connectError = false;
+ },
+ [types.UPDATE_CONNECT_ERROR](state) {
+ state.connectSuccessful = false;
+ state.connectError = true;
+ },
+};
diff --git a/app/assets/javascripts/error_tracking_settings/store/state.js b/app/assets/javascripts/error_tracking_settings/store/state.js
new file mode 100644
index 00000000000..98219d33f4d
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/store/state.js
@@ -0,0 +1,12 @@
+export default () => ({
+ apiHost: '',
+ enabled: false,
+ token: '',
+ projects: [],
+ selectedProject: null,
+ settingsLoading: false,
+ connectSuccessful: false,
+ connectError: false,
+ listProjectsEndpoint: '',
+ operationsSettingsEndpoint: '',
+});
diff --git a/app/assets/javascripts/error_tracking_settings/utils.js b/app/assets/javascripts/error_tracking_settings/utils.js
new file mode 100644
index 00000000000..6613e04ee0e
--- /dev/null
+++ b/app/assets/javascripts/error_tracking_settings/utils.js
@@ -0,0 +1,18 @@
+export const projectKeys = ['name', 'organizationName', 'organizationSlug', 'slug'];
+
+export const transformFrontendSettings = ({ apiHost, enabled, token, selectedProject }) => {
+ const project = selectedProject
+ ? {
+ slug: selectedProject.slug,
+ name: selectedProject.name,
+ organization_name: selectedProject.organizationName,
+ organization_slug: selectedProject.organizationSlug,
+ }
+ : null;
+
+ return { api_host: apiHost || null, enabled, token: token || null, project };
+};
+
+export const getDisplayName = project => `${project.organizationName} | ${project.name}`;
+
+export default () => {};
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight.js b/app/assets/javascripts/feature_highlight/feature_highlight.js
index 173fe7c69de..be55e6923c6 100644
--- a/app/assets/javascripts/feature_highlight/feature_highlight.js
+++ b/app/assets/javascripts/feature_highlight/feature_highlight.js
@@ -31,12 +31,14 @@ export function setupFeatureHighlightPopover(id, debounceTimeout = 300) {
.removeAttr('disabled');
}
+const getPriority = e => parseInt(e.dataset.highlightPriority, 10) || 0;
+
export function findHighestPriorityFeature() {
let priorityFeature;
const sortedFeatureEls = [].slice
.call(document.querySelectorAll('.js-feature-highlight'))
- .sort((a, b) => (a.dataset.highlightPriority || 0) < (b.dataset.highlightPriority || 0));
+ .sort((a, b) => getPriority(b) - getPriority(a));
const [priorityFeatureEl] = sortedFeatureEls;
if (priorityFeatureEl) {
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
new file mode 100644
index 00000000000..54ea936252e
--- /dev/null
+++ b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
@@ -0,0 +1,16 @@
+export default IssuableTokenKeys => {
+ const wipToken = {
+ key: 'wip',
+ type: 'string',
+ param: '',
+ symbol: '',
+ icon: 'admin',
+ tag: 'Yes or No',
+ lowercaseValueOnSubmit: true,
+ uppercaseTokenName: true,
+ capitalizeTokenValue: true,
+ };
+
+ IssuableTokenKeys.tokenKeys.push(wipToken);
+ IssuableTokenKeys.tokenKeysWithAlternative.push(wipToken);
+};
diff --git a/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js
index 934375023ba..691d165c585 100644
--- a/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js
@@ -17,6 +17,14 @@ const tokenKeys = [
icon: 'cube',
tag: 'type',
},
+ {
+ key: 'tag',
+ type: 'array',
+ param: 'name[]',
+ symbol: '~',
+ icon: 'tag',
+ tag: '~tag',
+ },
];
const AdminRunnersFilteredSearchTokenKeys = new FilteredSearchTokenKeys(tokenKeys);
diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
new file mode 100644
index 00000000000..e2f9c03ee65
--- /dev/null
+++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
@@ -0,0 +1,133 @@
+import DropdownHint from './dropdown_hint';
+import DropdownUser from './dropdown_user';
+import DropdownNonUser from './dropdown_non_user';
+import DropdownEmoji from './dropdown_emoji';
+import NullDropdown from './null_dropdown';
+import DropdownAjaxFilter from './dropdown_ajax_filter';
+import DropdownUtils from './dropdown_utils';
+
+export default class AvailableDropdownMappings {
+ constructor(container, baseEndpoint, groupsOnly, includeAncestorGroups, includeDescendantGroups) {
+ this.container = container;
+ this.baseEndpoint = baseEndpoint;
+ this.groupsOnly = groupsOnly;
+ this.includeAncestorGroups = includeAncestorGroups;
+ this.includeDescendantGroups = includeDescendantGroups;
+ }
+
+ getAllowedMappings(supportedTokens) {
+ return this.buildMappings(supportedTokens, this.getMappings());
+ }
+
+ buildMappings(supportedTokens, availableMappings) {
+ const allowedMappings = {
+ hint: {
+ reference: null,
+ gl: DropdownHint,
+ element: this.container.querySelector('#js-dropdown-hint'),
+ },
+ };
+
+ supportedTokens.forEach(type => {
+ if (availableMappings[type]) {
+ allowedMappings[type] = availableMappings[type];
+ }
+ });
+
+ return allowedMappings;
+ }
+
+ getMappings() {
+ return {
+ author: {
+ reference: null,
+ gl: DropdownUser,
+ element: this.container.querySelector('#js-dropdown-author'),
+ },
+ assignee: {
+ reference: null,
+ gl: DropdownUser,
+ element: this.container.querySelector('#js-dropdown-assignee'),
+ },
+ milestone: {
+ reference: null,
+ gl: DropdownNonUser,
+ extraArguments: {
+ endpoint: this.getMilestoneEndpoint(),
+ symbol: '%',
+ },
+ element: this.container.querySelector('#js-dropdown-milestone'),
+ },
+ label: {
+ reference: null,
+ gl: DropdownNonUser,
+ extraArguments: {
+ endpoint: this.getLabelsEndpoint(),
+ symbol: '~',
+ preprocessing: DropdownUtils.duplicateLabelPreprocessing,
+ },
+ element: this.container.querySelector('#js-dropdown-label'),
+ },
+ 'my-reaction': {
+ reference: null,
+ gl: DropdownEmoji,
+ element: this.container.querySelector('#js-dropdown-my-reaction'),
+ },
+ wip: {
+ reference: null,
+ gl: DropdownNonUser,
+ element: this.container.querySelector('#js-dropdown-wip'),
+ },
+ confidential: {
+ reference: null,
+ gl: DropdownNonUser,
+ element: this.container.querySelector('#js-dropdown-confidential'),
+ },
+ status: {
+ reference: null,
+ gl: NullDropdown,
+ element: this.container.querySelector('#js-dropdown-admin-runner-status'),
+ },
+ type: {
+ reference: null,
+ gl: NullDropdown,
+ element: this.container.querySelector('#js-dropdown-admin-runner-type'),
+ },
+ tag: {
+ reference: null,
+ gl: DropdownAjaxFilter,
+ extraArguments: {
+ endpoint: this.getRunnerTagsEndpoint(),
+ symbol: '~',
+ },
+ element: this.container.querySelector('#js-dropdown-runner-tag'),
+ },
+ };
+ }
+
+ getMilestoneEndpoint() {
+ return `${this.baseEndpoint}/milestones.json`;
+ }
+
+ getLabelsEndpoint() {
+ let endpoint = `${this.baseEndpoint}/labels.json?`;
+
+ if (this.groupsOnly) {
+ endpoint = `${endpoint}only_group_labels=true&`;
+ }
+
+ if (this.includeAncestorGroups) {
+ endpoint = `${endpoint}include_ancestor_groups=true&`;
+ }
+
+ if (this.includeDescendantGroups) {
+ endpoint = `${endpoint}include_descendant_groups=true`;
+ }
+
+ return endpoint;
+ }
+
+ getRunnerTagsEndpoint() {
+ return `${this.baseEndpoint}/admin/runners/tag_list.json`;
+ }
+}
diff --git a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
index 6b1a934d3fe..19bc3313373 100644
--- a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
+++ b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
@@ -66,7 +66,7 @@ export default {
<button
type="button"
class="filtered-search-history-dropdown-item"
- @click="onItemActivated(item.text);"
+ @click="onItemActivated(item.text)"
>
<span>
<span
@@ -88,7 +88,7 @@ export default {
<button
type="button"
class="filtered-search-history-clear-button"
- @click="onRequestClearRecentSearches($event);"
+ @click="onRequestClearRecentSearches($event)"
>
Clear recent searches
</button>
diff --git a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
new file mode 100644
index 00000000000..b27bb63c220
--- /dev/null
+++ b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
@@ -0,0 +1,68 @@
+import createFlash from '../flash';
+import AjaxFilter from '../droplab/plugins/ajax_filter';
+import FilteredSearchDropdown from './filtered_search_dropdown';
+import DropdownUtils from './dropdown_utils';
+import FilteredSearchTokenizer from './filtered_search_tokenizer';
+import { __ } from '~/locale';
+
+export default class DropdownAjaxFilter extends FilteredSearchDropdown {
+ constructor(options = {}) {
+ const { tokenKeys, endpoint, symbol } = options;
+
+ super(options);
+
+ this.tokenKeys = tokenKeys;
+ this.endpoint = endpoint;
+ this.symbol = symbol;
+
+ this.config = {
+ AjaxFilter: this.ajaxFilterConfig(),
+ };
+ }
+
+ ajaxFilterConfig() {
+ return {
+ endpoint: `${gon.relative_url_root || ''}${this.endpoint}`,
+ searchKey: 'search',
+ searchValueFunction: this.getSearchInput.bind(this),
+ loadingTemplate: this.loadingTemplate,
+ onError() {
+ createFlash(__('An error occurred fetching the dropdown data.'));
+ },
+ };
+ }
+
+ itemClicked(e) {
+ super.itemClicked(e, selected =>
+ selected.querySelector('.dropdown-light-content').innerText.trim(),
+ );
+ }
+
+ renderContent(forceShowList = false) {
+ this.droplab.changeHookList(this.hookId, this.dropdown, [AjaxFilter], this.config);
+ super.renderContent(forceShowList);
+ }
+
+ getSearchInput() {
+ const query = DropdownUtils.getSearchInput(this.input);
+ const { lastToken } = FilteredSearchTokenizer.processTokens(query, this.tokenKeys.get());
+
+ let value = lastToken || '';
+
+ if (value[0] === this.symbol) {
+ value = value.slice(1);
+ }
+
+ // Removes the first character if it is a quotation so that we can search
+ // with multiple words
+ if (value[0] === '"' || value[0] === "'") {
+ value = value.slice(1);
+ }
+
+ return value;
+ }
+
+ init() {
+ this.droplab.addHook(this.input, this.dropdown, [AjaxFilter], this.config).init();
+ }
+}
diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js
index d5027590bb7..f1e7be6bde1 100644
--- a/app/assets/javascripts/filtered_search/dropdown_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_user.js
@@ -1,54 +1,34 @@
-import Flash from '../flash';
-import AjaxFilter from '../droplab/plugins/ajax_filter';
-import FilteredSearchDropdown from './filtered_search_dropdown';
import { addClassIfElementExists } from '../lib/utils/dom_utils';
-import DropdownUtils from './dropdown_utils';
-import FilteredSearchTokenizer from './filtered_search_tokenizer';
+import DropdownAjaxFilter from './dropdown_ajax_filter';
-export default class DropdownUser extends FilteredSearchDropdown {
+export default class DropdownUser extends DropdownAjaxFilter {
constructor(options = {}) {
- const { tokenKeys } = options;
- super(options);
- this.config = {
- AjaxFilter: {
- endpoint: `${gon.relative_url_root || ''}/autocomplete/users.json`,
- searchKey: 'search',
- params: {
- active: true,
- group_id: this.getGroupId(),
- project_id: this.getProjectId(),
- current_user: true,
- },
- searchValueFunction: this.getSearchInput.bind(this),
- loadingTemplate: this.loadingTemplate,
- onLoadingFinished: () => {
- this.hideCurrentUser();
- },
- onError() {
- /* eslint-disable no-new */
- new Flash('An error occurred fetching the dropdown data.');
- /* eslint-enable no-new */
- },
+ super({
+ ...options,
+ endpoint: '/autocomplete/users.json',
+ symbol: '@',
+ });
+ }
+
+ ajaxFilterConfig() {
+ return {
+ ...super.ajaxFilterConfig(),
+ params: {
+ active: true,
+ group_id: this.getGroupId(),
+ project_id: this.getProjectId(),
+ current_user: true,
+ },
+ onLoadingFinished: () => {
+ this.hideCurrentUser();
},
};
- this.tokenKeys = tokenKeys;
}
hideCurrentUser() {
addClassIfElementExists(this.dropdown.querySelector('.js-current-user'), 'hidden');
}
- itemClicked(e) {
- super.itemClicked(e, selected =>
- selected.querySelector('.dropdown-light-content').innerText.trim(),
- );
- }
-
- renderContent(forceShowList = false) {
- this.droplab.changeHookList(this.hookId, this.dropdown, [AjaxFilter], this.config);
- super.renderContent(forceShowList);
- }
-
getGroupId() {
return this.input.getAttribute('data-group-id');
}
@@ -56,27 +36,4 @@ export default class DropdownUser extends FilteredSearchDropdown {
getProjectId() {
return this.input.getAttribute('data-project-id');
}
-
- getSearchInput() {
- const query = DropdownUtils.getSearchInput(this.input);
- const { lastToken } = FilteredSearchTokenizer.processTokens(query, this.tokenKeys.get());
-
- let value = lastToken || '';
-
- if (value[0] === '@') {
- value = value.slice(1);
- }
-
- // Removes the first character if it is a quotation so that we can search
- // with multiple words
- if (value[0] === '"' || value[0] === "'") {
- value = value.slice(1);
- }
-
- return value;
- }
-
- init() {
- this.droplab.addHook(this.input, this.dropdown, [AjaxFilter], this.config).init();
- }
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
index 57ec6603d80..cb0a84b490b 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
@@ -1,13 +1,9 @@
+import AvailableDropdownMappings from 'ee_else_ce/filtered_search/available_dropdown_mappings';
import _ from 'underscore';
import DropLab from '~/droplab/drop_lab';
import FilteredSearchContainer from './container';
import FilteredSearchTokenKeys from './filtered_search_token_keys';
import DropdownUtils from './dropdown_utils';
-import DropdownHint from './dropdown_hint';
-import DropdownEmoji from './dropdown_emoji';
-import DropdownNonUser from './dropdown_non_user';
-import DropdownUser from './dropdown_user';
-import NullDropdown from './null_dropdown';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
export default class FilteredSearchDropdownManager {
@@ -49,96 +45,15 @@ export default class FilteredSearchDropdownManager {
setupMapping() {
const supportedTokens = this.filteredSearchTokenKeys.getKeys();
- const allowedMappings = {
- hint: {
- reference: null,
- gl: DropdownHint,
- element: this.container.querySelector('#js-dropdown-hint'),
- },
- };
- const availableMappings = {
- author: {
- reference: null,
- gl: DropdownUser,
- element: this.container.querySelector('#js-dropdown-author'),
- },
- assignee: {
- reference: null,
- gl: DropdownUser,
- element: this.container.querySelector('#js-dropdown-assignee'),
- },
- milestone: {
- reference: null,
- gl: DropdownNonUser,
- extraArguments: {
- endpoint: this.getMilestoneEndpoint(),
- symbol: '%',
- },
- element: this.container.querySelector('#js-dropdown-milestone'),
- },
- label: {
- reference: null,
- gl: DropdownNonUser,
- extraArguments: {
- endpoint: this.getLabelsEndpoint(),
- symbol: '~',
- preprocessing: DropdownUtils.duplicateLabelPreprocessing,
- },
- element: this.container.querySelector('#js-dropdown-label'),
- },
- 'my-reaction': {
- reference: null,
- gl: DropdownEmoji,
- element: this.container.querySelector('#js-dropdown-my-reaction'),
- },
- wip: {
- reference: null,
- gl: DropdownNonUser,
- element: this.container.querySelector('#js-dropdown-wip'),
- },
- status: {
- reference: null,
- gl: NullDropdown,
- element: this.container.querySelector('#js-dropdown-admin-runner-status'),
- },
- type: {
- reference: null,
- gl: NullDropdown,
- element: this.container.querySelector('#js-dropdown-admin-runner-type'),
- },
- };
-
- supportedTokens.forEach(type => {
- if (availableMappings[type]) {
- allowedMappings[type] = availableMappings[type];
- }
- });
-
- this.mapping = allowedMappings;
- }
-
- getMilestoneEndpoint() {
- const endpoint = `${this.baseEndpoint}/milestones.json`;
-
- return endpoint;
- }
-
- getLabelsEndpoint() {
- let endpoint = `${this.baseEndpoint}/labels.json?`;
-
- if (this.groupsOnly) {
- endpoint = `${endpoint}only_group_labels=true&`;
- }
-
- if (this.includeAncestorGroups) {
- endpoint = `${endpoint}include_ancestor_groups=true&`;
- }
-
- if (this.includeDescendantGroups) {
- endpoint = `${endpoint}include_descendant_groups=true`;
- }
+ const availableMappings = new AvailableDropdownMappings(
+ this.container,
+ this.baseEndpoint,
+ this.groupsOnly,
+ this.includeAncestorGroups,
+ this.includeDescendantGroups,
+ );
- return endpoint;
+ this.mapping = availableMappings.getAllowedMappings(supportedTokens);
}
static addWordToInput(tokenName, tokenValue = '', clicked = false, options = {}) {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index 4a2af02b40a..33c82778c79 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -593,7 +593,7 @@ export default class FilteredSearchManager {
tokens.forEach(token => {
const condition = this.filteredSearchTokenKeys.searchByConditionKeyValue(
token.key,
- token.value.toLowerCase(),
+ token.value,
);
const tokenConfig = this.filteredSearchTokenKeys.searchByKey(token.key) || {};
const { param } = tokenConfig;
diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
index e01dedbb57c..11ed85504ec 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
@@ -65,25 +65,27 @@ export default class FilteredSearchTokenKeys {
searchByConditionKeyValue(key, value) {
return (
- this.conditions.find(condition => condition.tokenKey === key && condition.value === value) ||
- null
+ this.conditions.find(
+ condition =>
+ condition.tokenKey === key && condition.value.toLowerCase() === value.toLowerCase(),
+ ) || null
);
}
- addExtraTokensForMergeRequests() {
- const wipToken = {
- key: 'wip',
+ addExtraTokensForIssues() {
+ const confidentialToken = {
+ key: 'confidential',
type: 'string',
param: '',
symbol: '',
- icon: 'admin',
+ icon: 'eye-slash',
tag: 'Yes or No',
lowercaseValueOnSubmit: true,
- uppercaseTokenName: true,
+ uppercaseTokenName: false,
capitalizeTokenValue: true,
};
- this.tokenKeys.push(wipToken);
- this.tokenKeysWithAlternative.push(wipToken);
+ this.tokenKeys.push(confidentialToken);
+ this.tokenKeysWithAlternative.push(confidentialToken);
}
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
index fba31f16d65..7746908714e 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
@@ -1,10 +1,6 @@
-import _ from 'underscore';
-import AjaxCache from '~/lib/utils/ajax_cache';
+import VisualTokenValue from 'ee_else_ce/filtered_search/visual_token_value';
import { objectToQueryString } from '~/lib/utils/common_utils';
-import Flash from '../flash';
import FilteredSearchContainer from './container';
-import UsersCache from '../lib/utils/users_cache';
-import DropdownUtils from './dropdown_utils';
export default class FilteredSearchVisualTokens {
static getLastVisualTokenBeforeInput() {
@@ -20,21 +16,6 @@ export default class FilteredSearchVisualTokens {
};
}
- /**
- * Returns a computed API endpoint
- * and query string composed of values from endpointQueryParams
- * @param {String} endpoint
- * @param {String} endpointQueryParams
- */
- static getEndpointWithQueryParams(endpoint, endpointQueryParams) {
- if (!endpointQueryParams) {
- return endpoint;
- }
-
- const queryString = objectToQueryString(JSON.parse(endpointQueryParams));
- return `${endpoint}?${queryString}`;
- }
-
static unselectTokens() {
const otherTokens = FilteredSearchContainer.container.querySelectorAll(
'.js-visual-token .selectable.selected',
@@ -76,114 +57,15 @@ export default class FilteredSearchVisualTokens {
`;
}
- static setTokenStyle(tokenContainer, backgroundColor, textColor) {
- const token = tokenContainer;
-
- token.style.backgroundColor = backgroundColor;
- token.style.color = textColor;
-
- if (textColor === '#FFFFFF') {
- const removeToken = token.querySelector('.remove-token');
- removeToken.classList.add('inverted');
- }
-
- return token;
- }
-
- static updateLabelTokenColor(tokenValueContainer, tokenValue) {
- const filteredSearchInput = FilteredSearchContainer.container.querySelector('.filtered-search');
- const { baseEndpoint } = filteredSearchInput.dataset;
- const labelsEndpoint = FilteredSearchVisualTokens.getEndpointWithQueryParams(
- `${baseEndpoint}/labels.json`,
- filteredSearchInput.dataset.endpointQueryParams,
- );
-
- return AjaxCache.retrieve(labelsEndpoint)
- .then(labels => {
- const matchingLabel = (labels || []).find(
- label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue,
- );
-
- if (!matchingLabel) {
- return;
- }
-
- FilteredSearchVisualTokens.setTokenStyle(
- tokenValueContainer,
- matchingLabel.color,
- matchingLabel.text_color,
- );
- })
- .catch(() => new Flash('An error occurred while fetching label colors.'));
- }
-
- static updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue) {
- const username = tokenValue.replace(/^@/, '');
- return (
- UsersCache.retrieve(username)
- .then(user => {
- if (!user) {
- return;
- }
-
- /* eslint-disable no-param-reassign */
- tokenValueContainer.dataset.originalValue = tokenValue;
- tokenValueElement.innerHTML = `
- <img class="avatar s20" src="${user.avatar_url}" alt="">
- ${_.escape(user.name)}
- `;
- /* eslint-enable no-param-reassign */
- })
- // ignore error and leave username in the search bar
- .catch(() => {})
- );
- }
-
- static updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue) {
- const container = tokenValueContainer;
- const element = tokenValueElement;
-
- return (
- import(/* webpackChunkName: 'emoji' */ '../emoji')
- .then(Emoji => {
- if (!Emoji.isEmojiNameValid(tokenValue)) {
- return;
- }
-
- container.dataset.originalValue = tokenValue;
- element.innerHTML = Emoji.glEmojiTag(tokenValue);
- })
- // ignore error and leave emoji name in the search bar
- .catch(() => {})
- );
- }
-
static renderVisualTokenValue(parentElement, tokenName, tokenValue) {
+ const tokenType = tokenName.toLowerCase();
const tokenValueContainer = parentElement.querySelector('.value-container');
const tokenValueElement = tokenValueContainer.querySelector('.value');
tokenValueElement.innerText = tokenValue;
- if (tokenValue === 'none' || tokenValue === 'any') {
- return;
- }
+ const visualTokenValue = new VisualTokenValue(tokenValue, tokenType);
- const tokenType = tokenName.toLowerCase();
-
- if (tokenType === 'label') {
- FilteredSearchVisualTokens.updateLabelTokenColor(tokenValueContainer, tokenValue);
- } else if (tokenType === 'author' || tokenType === 'assignee') {
- FilteredSearchVisualTokens.updateUserTokenAppearance(
- tokenValueContainer,
- tokenValueElement,
- tokenValue,
- );
- } else if (tokenType === 'my-reaction') {
- FilteredSearchVisualTokens.updateEmojiTokenAppearance(
- tokenValueContainer,
- tokenValueElement,
- tokenValue,
- );
- }
+ visualTokenValue.render(tokenValueContainer, tokenValueElement);
}
static addVisualTokenElement(name, value, options = {}) {
@@ -318,6 +200,21 @@ export default class FilteredSearchVisualTokens {
}
}
+ /**
+ * Returns a computed API endpoint
+ * and query string composed of values from endpointQueryParams
+ * @param {String} endpoint
+ * @param {String} endpointQueryParams
+ */
+ static getEndpointWithQueryParams(endpoint, endpointQueryParams) {
+ if (!endpointQueryParams) {
+ return endpoint;
+ }
+
+ const queryString = objectToQueryString(JSON.parse(endpointQueryParams));
+ return `${endpoint}?${queryString}`;
+ }
+
static editToken(token) {
const input = FilteredSearchContainer.container.querySelector('.filtered-search');
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 b494b7e2de0..fd61030eb13 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
@@ -60,52 +60,52 @@ export const conditions = [
{
url: 'assignee_id=None',
tokenKey: 'assignee',
- value: 'none',
+ value: 'None',
},
{
url: 'assignee_id=Any',
tokenKey: 'assignee',
- value: 'any',
+ value: 'Any',
},
{
url: 'milestone_title=None',
tokenKey: 'milestone',
- value: 'none',
+ value: 'None',
},
{
url: 'milestone_title=Any',
tokenKey: 'milestone',
- value: 'any',
+ value: 'Any',
},
{
url: 'milestone_title=%23upcoming',
tokenKey: 'milestone',
- value: 'upcoming',
+ value: 'Upcoming',
},
{
url: 'milestone_title=%23started',
tokenKey: 'milestone',
- value: 'started',
+ value: 'Started',
},
{
url: 'label_name[]=None',
tokenKey: 'label',
- value: 'none',
+ value: 'None',
},
{
url: 'label_name[]=Any',
- tokenKey: 'any',
- value: 'any',
+ tokenKey: 'label',
+ value: 'Any',
},
{
url: 'my_reaction_emoji=None',
tokenKey: 'my-reaction',
- value: 'none',
+ value: 'None',
},
{
url: 'my_reaction_emoji=Any',
tokenKey: 'my-reaction',
- value: 'any',
+ value: 'Any',
},
];
diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js
new file mode 100644
index 00000000000..7f6f41c18f7
--- /dev/null
+++ b/app/assets/javascripts/filtered_search/visual_token_value.js
@@ -0,0 +1,125 @@
+import _ from 'underscore';
+import FilteredSearchContainer from '~/filtered_search/container';
+import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
+import AjaxCache from '~/lib/utils/ajax_cache';
+import DropdownUtils from '~/filtered_search/dropdown_utils';
+import Flash from '~/flash';
+import UsersCache from '~/lib/utils/users_cache';
+
+export default class VisualTokenValue {
+ constructor(tokenValue, tokenType) {
+ this.tokenValue = tokenValue;
+ this.tokenType = tokenType;
+ }
+
+ render(tokenValueContainer, tokenValueElement) {
+ const { tokenType } = this;
+
+ if (['none', 'any'].includes(tokenType)) {
+ return;
+ }
+
+ if (tokenType === 'label') {
+ this.updateLabelTokenColor(tokenValueContainer);
+ } else if (tokenType === 'author' || tokenType === 'assignee') {
+ this.updateUserTokenAppearance(tokenValueContainer, tokenValueElement);
+ } else if (tokenType === 'my-reaction') {
+ this.updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement);
+ }
+ }
+
+ updateUserTokenAppearance(tokenValueContainer, tokenValueElement) {
+ const { tokenValue } = this;
+ const username = this.tokenValue.replace(/^@/, '');
+
+ return (
+ UsersCache.retrieve(username)
+ .then(user => {
+ if (!user) {
+ return;
+ }
+
+ /* eslint-disable no-param-reassign */
+ tokenValueContainer.dataset.originalValue = tokenValue;
+ tokenValueElement.innerHTML = `
+ <img class="avatar s20" src="${user.avatar_url}" alt="">
+ ${_.escape(user.name)}
+ `;
+ /* eslint-enable no-param-reassign */
+ })
+ // ignore error and leave username in the search bar
+ .catch(() => {})
+ );
+ }
+
+ updateLabelTokenColor(tokenValueContainer) {
+ const { tokenValue } = this;
+ const filteredSearchInput = FilteredSearchContainer.container.querySelector('.filtered-search');
+ const { baseEndpoint } = filteredSearchInput.dataset;
+ const labelsEndpoint = FilteredSearchVisualTokens.getEndpointWithQueryParams(
+ `${baseEndpoint}/labels.json`,
+ filteredSearchInput.dataset.endpointQueryParams,
+ );
+
+ return AjaxCache.retrieve(labelsEndpoint)
+ .then(labels => {
+ const matchingLabel = (labels || []).find(
+ label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue,
+ );
+
+ if (!matchingLabel) {
+ return;
+ }
+
+ VisualTokenValue.setTokenStyle(
+ tokenValueContainer,
+ matchingLabel.color,
+ matchingLabel.text_color,
+ );
+ })
+ .catch(() => new Flash('An error occurred while fetching label colors.'));
+ }
+
+ static setTokenStyle(tokenValueContainer, backgroundColor, textColor) {
+ const token = tokenValueContainer;
+
+ token.style.backgroundColor = backgroundColor;
+ token.style.color = textColor;
+
+ if (textColor === '#FFFFFF') {
+ const removeToken = token.querySelector('.remove-token');
+ removeToken.classList.add('inverted');
+ }
+
+ return token;
+ }
+
+ updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement) {
+ const container = tokenValueContainer;
+ const element = tokenValueElement;
+ const value = this.tokenValue;
+
+ return (
+ import(/* webpackChunkName: 'emoji' */ '../emoji')
+ .then(Emoji => {
+ Emoji.initEmojiMap()
+ .then(() => {
+ if (!Emoji.isEmojiNameValid(value)) {
+ return;
+ }
+
+ container.dataset.originalValue = value;
+ element.innerHTML = Emoji.glEmojiTag(value);
+ })
+ // ignore error and leave emoji name in the search bar
+ .catch(err => {
+ throw err;
+ });
+ })
+ // ignore error and leave emoji name in the search bar
+ .catch(importError => {
+ throw importError;
+ })
+ );
+ }
+}
diff --git a/app/assets/javascripts/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js
index 3ac00c51df4..2b6af9060d1 100644
--- a/app/assets/javascripts/fly_out_nav.js
+++ b/app/assets/javascripts/fly_out_nav.js
@@ -24,6 +24,9 @@ export const slope = (a, b) => (b.y - a.y) / (b.x - a.x);
let headerHeight = 50;
export const getHeaderHeight = () => headerHeight;
+const setHeaderHeight = () => {
+ headerHeight = sidebar.offsetTop;
+};
export const isSidebarCollapsed = () =>
sidebar && sidebar.classList.contains('sidebar-collapsed-desktop');
@@ -186,7 +189,7 @@ export default () => {
});
}
- headerHeight = document.querySelector('.nav-sidebar').offsetTop;
+ requestIdleCallback(setHeaderHeight);
items.forEach(el => {
const subItems = el.querySelector('.sidebar-sub-level-items');
diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue
index 63531f1f246..968e255e1fc 100644
--- a/app/assets/javascripts/frequent_items/components/app.vue
+++ b/app/assets/javascripts/frequent_items/components/app.vue
@@ -47,6 +47,12 @@ export default {
}
eventHub.$on(`${this.namespace}-dropdownOpen`, this.dropdownOpenHandler);
+
+ // As we init it through requestIdleCallback it could be that the dropdown is already open
+ const namespaceDropdown = document.getElementById(`nav-${this.namespace}-dropdown`);
+ if (namespaceDropdown && namespaceDropdown.classList.contains('show')) {
+ this.dropdownOpenHandler();
+ }
},
beforeDestroy() {
eventHub.$off(`${this.namespace}-dropdownOpen`, this.dropdownOpenHandler);
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 2cbc7c7077b..42d14b65b3a 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
@@ -82,8 +82,14 @@ export default {
<li class="frequent-items-list-item-container">
<a :href="webUrl" class="clearfix">
<div class="frequent-items-item-avatar-container">
- <img v-if="hasAvatar" :src="avatarUrl" class="avatar s32" />
- <identicon v-else :entity-id="itemId" :entity-name="itemName" size-class="s32" />
+ <img v-if="hasAvatar" :src="avatarUrl" class="avatar rect-avatar s32" />
+ <identicon
+ v-else
+ :entity-id="itemId"
+ :entity-name="itemName"
+ size-class="s32"
+ class="rect-avatar"
+ />
</div>
<div class="frequent-items-item-metadata-container">
<div :title="itemName" class="frequent-items-item-title" v-html="highlightedItemName"></div>
diff --git a/app/assets/javascripts/frequent_items/index.js b/app/assets/javascripts/frequent_items/index.js
index 5157ff211dc..6263acbab8e 100644
--- a/app/assets/javascripts/frequent_items/index.js
+++ b/app/assets/javascripts/frequent_items/index.js
@@ -17,7 +17,7 @@ const frequentItemDropdowns = [
},
];
-document.addEventListener('DOMContentLoaded', () => {
+const initFrequentItemDropdowns = () => {
frequentItemDropdowns.forEach(dropdown => {
const { namespace, key } = dropdown;
const el = document.getElementById(`js-${namespace}-dropdown`);
@@ -66,4 +66,8 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
});
+};
+
+document.addEventListener('DOMContentLoaded', () => {
+ requestIdleCallback(initFrequentItemDropdowns);
});
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index c14eb936930..50ea13edf63 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -195,11 +195,15 @@ class GfmAutoComplete {
title += ` (${m.count})`;
}
+ const GROUP_TYPE = 'Group';
+
const autoCompleteAvatar = m.avatar_url || m.username.charAt(0).toUpperCase();
+
+ const rectAvatarClass = m.type === GROUP_TYPE ? 'rect-avatar' : '';
const imgAvatar = `<img src="${m.avatar_url}" alt="${
m.username
- }" class="avatar avatar-inline center s26"/>`;
- const txtAvatar = `<div class="avatar center avatar-inline s26">${autoCompleteAvatar}</div>`;
+ }" class="avatar ${rectAvatarClass} avatar-inline center s26"/>`;
+ const txtAvatar = `<div class="avatar ${rectAvatarClass} center avatar-inline s26">${autoCompleteAvatar}</div>`;
return {
username: m.username,
@@ -221,13 +225,13 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Issues.templateFunction(value.id, value.title);
+ tmpl = GfmAutoComplete.Issues.templateFunction(value);
}
return tmpl;
},
data: GfmAutoComplete.defaultLoadingData,
- // eslint-disable-next-line no-template-curly-in-string
- insertTpl: '${atwho-at}${id}',
+ insertTpl: GfmAutoComplete.Issues.insertTemplateFunction,
+ skipSpecialCharacterTest: true,
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(issues) {
@@ -238,6 +242,7 @@ class GfmAutoComplete {
return {
id: i.iid,
title: sanitize(i.title),
+ reference: i.reference,
search: `${i.iid} ${i.title}`,
};
});
@@ -256,7 +261,7 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Milestones.template;
+ tmpl = GfmAutoComplete.Milestones.templateFunction(value.title);
}
return tmpl;
},
@@ -287,13 +292,13 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Issues.templateFunction(value.id, value.title);
+ tmpl = GfmAutoComplete.Issues.templateFunction(value);
}
return tmpl;
},
data: GfmAutoComplete.defaultLoadingData,
- // eslint-disable-next-line no-template-curly-in-string
- insertTpl: '${atwho-at}${id}',
+ insertTpl: GfmAutoComplete.Issues.insertTemplateFunction,
+ skipSpecialCharacterTest: true,
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(merges) {
@@ -304,6 +309,7 @@ class GfmAutoComplete {
return {
id: m.iid,
title: sanitize(m.title),
+ reference: m.reference,
search: `${m.iid} ${m.title}`,
};
});
@@ -323,7 +329,7 @@ class GfmAutoComplete {
searchKey: 'search',
data: GfmAutoComplete.defaultLoadingData,
displayTpl(value) {
- let tmpl = GfmAutoComplete.Labels.template;
+ let tmpl = GfmAutoComplete.Labels.templateFunction(value.color, value.title);
if (GfmAutoComplete.isLoading(value)) {
tmpl = GfmAutoComplete.Loading.template;
}
@@ -397,7 +403,7 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Issues.templateFunction(value.id, value.title);
+ tmpl = GfmAutoComplete.Issues.templateFunction(value);
}
return tmpl;
},
@@ -481,9 +487,15 @@ class GfmAutoComplete {
this.loadData($input, at, this.cachedData[at]);
} else if (GfmAutoComplete.atTypeMap[at] === 'emojis') {
import(/* webpackChunkName: 'emoji' */ './emoji')
- .then(({ validEmojiNames, glEmojiTag }) => {
- this.loadData($input, at, validEmojiNames);
- GfmAutoComplete.glEmojiTag = glEmojiTag;
+ .then(({ initEmojiMap, getValidEmojiNames, glEmojiTag }) => {
+ initEmojiMap()
+ .then(() => {
+ this.loadData($input, at, getValidEmojiNames());
+ GfmAutoComplete.glEmojiTag = glEmojiTag;
+ })
+ .catch(() => {
+ this.isLoadingData[at] = false;
+ });
})
.catch(() => {
this.isLoadingData[at] = false;
@@ -588,20 +600,27 @@ GfmAutoComplete.Members = {
},
};
GfmAutoComplete.Labels = {
- template:
- // eslint-disable-next-line no-template-curly-in-string
- '<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>',
+ templateFunction(color, title) {
+ return `<li><span class="dropdown-label-box" style="background: ${_.escape(
+ color,
+ )}"></span> ${_.escape(title)}</li>`;
+ },
};
// Issues, MergeRequests and Snippets
GfmAutoComplete.Issues = {
- templateFunction(id, title) {
- return `<li><small>${id}</small> ${_.escape(title)}</li>`;
+ insertTemplateFunction(value) {
+ // eslint-disable-next-line no-template-curly-in-string
+ return value.reference || '${atwho-at}${id}';
+ },
+ templateFunction({ id, title, reference }) {
+ return `<li><small>${reference || id}</small> ${_.escape(title)}</li>`;
},
};
// Milestones
GfmAutoComplete.Milestones = {
- // eslint-disable-next-line no-template-curly-in-string
- template: '<li>${title}</li>',
+ templateFunction(title) {
+ return `<li>${_.escape(title)}</li>`;
+ },
};
GfmAutoComplete.Loading = {
template:
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
index a8ac2f510a4..27d8669b256 100644
--- a/app/assets/javascripts/gl_dropdown.js
+++ b/app/assets/javascripts/gl_dropdown.js
@@ -656,23 +656,7 @@ GitLabDropdown = (function() {
if (this.options.renderMenu) {
return this.options.renderMenu(html);
} else {
- var ul = document.createElement('ul');
-
- for (var i = 0; i < html.length; i += 1) {
- var el = html[i];
-
- if (el instanceof $) {
- el = el.get(0);
- }
-
- if (typeof el === 'string') {
- ul.innerHTML += el;
- } else {
- ul.appendChild(el);
- }
- }
-
- return ul;
+ return $('<ul>').append(html);
}
};
diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js
index f842d2d74db..f5e2e46237f 100644
--- a/app/assets/javascripts/gl_form.js
+++ b/app/assets/javascripts/gl_form.js
@@ -51,8 +51,6 @@ export default class GLForm {
// form and textarea event listeners
this.addEventListeners();
addMarkdownListeners(this.form);
- // hide discard button
- this.form.find('.js-note-discard').hide();
this.form.show();
if (this.isAutosizeable) this.setupAutosize();
}
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index 688bd37cc56..d5130cd331d 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -88,7 +88,7 @@ export default {
</div>
<div
:class="{ 'content-loading': group.isChildrenLoading }"
- class="avatar-container s24 d-none d-sm-flex"
+ class="avatar-container rect-avatar s24 d-none d-sm-flex"
>
<a :href="group.relativePath" class="no-expand">
<img v-if="hasAvatar" :src="group.avatarUrl" class="avatar s24" />
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index 2049760fe29..bdadbb1bb2a 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -4,93 +4,97 @@ import Api from './api';
import { normalizeHeaders } from './lib/utils/common_utils';
export default function groupsSelect() {
- // Needs to be accessible in rspec
- window.GROUP_SELECT_PER_PAGE = 20;
- $('.ajax-groups-select').each(function setAjaxGroupsSelect2() {
- const $select = $(this);
- const allAvailable = $select.data('allAvailable');
- const skipGroups = $select.data('skipGroups') || [];
- const parentGroupID = $select.data('parentId');
- const groupsPath = parentGroupID
- ? Api.subgroupsPath.replace(':id', parentGroupID)
- : Api.groupsPath;
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ // Needs to be accessible in rspec
+ window.GROUP_SELECT_PER_PAGE = 20;
+ $('.ajax-groups-select').each(function setAjaxGroupsSelect2() {
+ const $select = $(this);
+ const allAvailable = $select.data('allAvailable');
+ const skipGroups = $select.data('skipGroups') || [];
+ const parentGroupID = $select.data('parentId');
+ const groupsPath = parentGroupID
+ ? Api.subgroupsPath.replace(':id', parentGroupID)
+ : Api.groupsPath;
- $select.select2({
- placeholder: 'Search for a group',
- allowClear: $select.hasClass('allowClear'),
- multiple: $select.hasClass('multiselect'),
- minimumInputLength: 0,
- ajax: {
- url: Api.buildUrl(groupsPath),
- dataType: 'json',
- quietMillis: 250,
- transport(params) {
- axios[params.type.toLowerCase()](params.url, {
- params: params.data,
- })
- .then(res => {
- const results = res.data || [];
- const headers = normalizeHeaders(res.headers);
- const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
- const totalPages = parseInt(headers['X-TOTAL-PAGES'], 10) || 0;
- const more = currentPage < totalPages;
+ $select.select2({
+ placeholder: 'Search for a group',
+ allowClear: $select.hasClass('allowClear'),
+ multiple: $select.hasClass('multiselect'),
+ minimumInputLength: 0,
+ ajax: {
+ url: Api.buildUrl(groupsPath),
+ dataType: 'json',
+ quietMillis: 250,
+ transport(params) {
+ axios[params.type.toLowerCase()](params.url, {
+ params: params.data,
+ })
+ .then(res => {
+ const results = res.data || [];
+ const headers = normalizeHeaders(res.headers);
+ const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
+ const totalPages = parseInt(headers['X-TOTAL-PAGES'], 10) || 0;
+ const more = currentPage < totalPages;
- params.success({
- results,
- pagination: {
- more,
- },
- });
- })
- .catch(params.error);
- },
- data(search, page) {
- return {
- search,
- page,
- per_page: window.GROUP_SELECT_PER_PAGE,
- all_available: allAvailable,
- };
- },
- results(data, page) {
- if (data.length) return { results: [] };
+ params.success({
+ results,
+ pagination: {
+ more,
+ },
+ });
+ })
+ .catch(params.error);
+ },
+ data(search, page) {
+ return {
+ search,
+ page,
+ per_page: window.GROUP_SELECT_PER_PAGE,
+ all_available: allAvailable,
+ };
+ },
+ results(data, page) {
+ if (data.length) return { results: [] };
- const groups = data.length ? data : data.results || [];
- const more = data.pagination ? data.pagination.more : false;
- const results = groups.filter(group => skipGroups.indexOf(group.id) === -1);
+ const groups = data.length ? data : data.results || [];
+ const more = data.pagination ? data.pagination.more : false;
+ const results = groups.filter(group => skipGroups.indexOf(group.id) === -1);
- return {
- results,
- page,
- more,
- };
- },
- },
- // eslint-disable-next-line consistent-return
- initSelection(element, callback) {
- const id = $(element).val();
- if (id !== '') {
- return Api.group(id, callback);
- }
- },
- formatResult(object) {
- return `<div class='group-result'> <div class='group-name'>${
- object.full_name
- }</div> <div class='group-path'>${object.full_path}</div> </div>`;
- },
- formatSelection(object) {
- return object.full_name;
- },
- dropdownCssClass: 'ajax-groups-dropdown select2-infinite',
- // we do not want to escape markup since we are displaying html in results
- escapeMarkup(m) {
- return m;
- },
- });
+ return {
+ results,
+ page,
+ more,
+ };
+ },
+ },
+ // eslint-disable-next-line consistent-return
+ initSelection(element, callback) {
+ const id = $(element).val();
+ if (id !== '') {
+ return Api.group(id, callback);
+ }
+ },
+ formatResult(object) {
+ return `<div class='group-result'> <div class='group-name'>${
+ object.full_name
+ }</div> <div class='group-path'>${object.full_path}</div> </div>`;
+ },
+ formatSelection(object) {
+ return object.full_name;
+ },
+ dropdownCssClass: 'ajax-groups-dropdown select2-infinite',
+ // we do not want to escape markup since we are displaying html in results
+ escapeMarkup(m) {
+ return m;
+ },
+ });
- $select.on('select2-loaded', () => {
- const dropdown = document.querySelector('.select2-infinite .select2-results');
- dropdown.style.height = `${Math.floor(dropdown.scrollHeight)}px`;
- });
- });
+ $select.on('select2-loaded', () => {
+ const dropdown = document.querySelector('.select2-infinite .select2-results');
+ dropdown.style.height = `${Math.floor(dropdown.scrollHeight)}px`;
+ });
+ });
+ })
+ .catch(() => {});
}
diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js
index 2fa7a219ea8..3d846310008 100644
--- a/app/assets/javascripts/header.js
+++ b/app/assets/javascripts/header.js
@@ -23,7 +23,7 @@ export default function initTodoToggle() {
});
}
-document.addEventListener('DOMContentLoaded', () => {
+function initStatusTriggers() {
const setStatusModalTriggerEl = document.querySelector('.js-set-status-modal-trigger');
const setStatusModalWrapperEl = document.querySelector('.js-set-status-modal-wrapper');
@@ -72,4 +72,8 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
}
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ requestIdleCallback(initStatusTriggers);
});
diff --git a/app/assets/javascripts/ide/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue
index a1f66ff764d..7c769ab7fa0 100644
--- a/app/assets/javascripts/ide/components/activity_bar.vue
+++ b/app/assets/javascripts/ide/components/activity_bar.vue
@@ -45,7 +45,7 @@ export default {
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-edit-mode"
- @click.prevent="changedActivityView($event, $options.activityBarViews.edit);"
+ @click.prevent="changedActivityView($event, $options.activityBarViews.edit)"
>
<icon name="code" />
</button>
@@ -62,7 +62,7 @@ export default {
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-review-mode"
- @click.prevent="changedActivityView($event, $options.activityBarViews.review);"
+ @click.prevent="changedActivityView($event, $options.activityBarViews.review)"
>
<icon name="file-modified" />
</button>
@@ -79,7 +79,7 @@ export default {
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-commit-mode"
- @click.prevent="changedActivityView($event, $options.activityBarViews.commit);"
+ @click.prevent="changedActivityView($event, $options.activityBarViews.commit)"
>
<icon name="commit" />
</button>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
index 5119dbf32eb..11d5d9639b6 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
@@ -44,7 +44,7 @@ export default {
<div class="d-flex ide-commit-editor-header align-items-center">
<file-icon :file-name="activeFile.name" :size="16" class="mr-2" />
<strong class="mr-2"> {{ activeFile.path }} </strong>
- <changed-file-icon :file="activeFile" class="ml-0" />
+ <changed-file-icon :file="activeFile" :is-centered="false" />
<div class="ml-auto">
<button
v-if="!isStaged"
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
index a1094570275..4f1260de0bc 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -87,7 +87,7 @@ export default {
},
},
discardModalText: __(
- "You will loose all the unstaged changes you've made in this project. This action cannot be undone.",
+ "You will lose all the unstaged changes you've made in this project. This action cannot be undone.",
),
};
</script>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
index 6f1ded91753..00b2d236da3 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
@@ -111,8 +111,8 @@ export default {
name="commit-message"
@scroll="handleScroll"
@input="onInput"
- @focus="updateIsFocused(true);"
- @blur="updateIsFocused(false);"
+ @focus="updateIsFocused(true)"
+ @blur="updateIsFocused(false)"
@keydown.ctrl.enter="onCtrlEnter"
@keydown.meta.enter="onCtrlEnter"
>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
index 3525084b1cb..2b44438f849 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
@@ -65,7 +65,7 @@ export default {
:disabled="disabled"
type="radio"
name="commit-action"
- @change="updateCommitAction($event.target.value);"
+ @change="updateCommitAction($event.target.value)"
/>
<span class="prepend-left-10">
<span v-if="label" class="ide-radio-label"> {{ label }} </span> <slot v-else></slot>
@@ -76,7 +76,7 @@ export default {
:placeholder="newBranchName"
type="text"
class="form-control monospace"
- @input="updateBranchName($event.target.value);"
+ @input="updateBranchName($event.target.value)"
/>
</div>
</fieldset>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue b/app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue
index 02c2004d495..09c9d135614 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue
@@ -48,7 +48,7 @@ export default {
data-container="body"
data-boundary="viewport"
data-placement="bottom"
- @click.stop.prevent="stageChange(path);"
+ @click.stop.prevent="stageChange(path)"
>
<icon :size="16" name="mobile-issue-close" class="ml-auto mr-auto" />
</button>
@@ -70,9 +70,9 @@ export default {
:header-title-text="modalTitle"
:footer-primary-button-text="__('Discard changes')"
footer-primary-button-variant="danger"
- @submit="discardFileChanges(path);"
+ @submit="discardFileChanges(path)"
>
- {{ __("You will loose all changes you've made to this file. This action cannot be undone.") }}
+ {{ __("You will lose all changes you've made to this file. This action cannot be undone.") }}
</gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue b/app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue
index ce41fcdb087..0567ef54ff3 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue
@@ -33,7 +33,7 @@ export default {
data-container="body"
data-boundary="viewport"
data-placement="bottom"
- @click.stop.prevent="unstageChange(path);"
+ @click.stop.prevent="unstageChange(path)"
>
<icon :size="16" name="redo" class="ml-auto mr-auto" />
</button>
diff --git a/app/assets/javascripts/ide/components/editor_mode_dropdown.vue b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
index 5f99261ec39..732fa0786b0 100644
--- a/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
+++ b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
@@ -40,7 +40,7 @@ export default {
'is-active': viewer === $options.viewerTypes.mr,
}"
href="#"
- @click.prevent="changeMode($options.viewerTypes.mr);"
+ @click.prevent="changeMode($options.viewerTypes.mr)"
>
<strong class="dropdown-menu-inner-title"> {{ mergeReviewLine }} </strong>
<span class="dropdown-menu-inner-content">
@@ -54,7 +54,7 @@ export default {
'is-active': viewer === $options.viewerTypes.diff,
}"
href="#"
- @click.prevent="changeMode($options.viewerTypes.diff);"
+ @click.prevent="changeMode($options.viewerTypes.diff)"
>
<strong class="dropdown-menu-inner-title">{{ __('Reviewing') }}</strong>
<span class="dropdown-menu-inner-content">
diff --git a/app/assets/javascripts/ide/components/file_finder/index.vue b/app/assets/javascripts/ide/components/file_finder/index.vue
deleted file mode 100644
index bb391912572..00000000000
--- a/app/assets/javascripts/ide/components/file_finder/index.vue
+++ /dev/null
@@ -1,227 +0,0 @@
-<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
-import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import VirtualList from 'vue-virtual-scroll-list';
-import Item from './item.vue';
-import router from '../../ide_router';
-import {
- MAX_FILE_FINDER_RESULTS,
- FILE_FINDER_ROW_HEIGHT,
- FILE_FINDER_EMPTY_ROW_HEIGHT,
-} from '../../constants';
-import {
- UP_KEY_CODE,
- DOWN_KEY_CODE,
- ENTER_KEY_CODE,
- ESC_KEY_CODE,
-} from '../../../lib/utils/keycodes';
-
-export default {
- components: {
- Item,
- VirtualList,
- },
- data() {
- return {
- focusedIndex: 0,
- searchText: '',
- mouseOver: false,
- cancelMouseOver: false,
- };
- },
- computed: {
- ...mapGetters(['allBlobs']),
- ...mapState(['fileFindVisible', 'loading']),
- filteredBlobs() {
- const searchText = this.searchText.trim();
-
- if (searchText === '') {
- return this.allBlobs.slice(0, MAX_FILE_FINDER_RESULTS);
- }
-
- return fuzzaldrinPlus.filter(this.allBlobs, searchText, {
- key: 'path',
- maxResults: MAX_FILE_FINDER_RESULTS,
- });
- },
- filteredBlobsLength() {
- return this.filteredBlobs.length;
- },
- listShowCount() {
- return this.filteredBlobsLength ? Math.min(this.filteredBlobsLength, 5) : 1;
- },
- listHeight() {
- return this.filteredBlobsLength ? FILE_FINDER_ROW_HEIGHT : FILE_FINDER_EMPTY_ROW_HEIGHT;
- },
- showClearInputButton() {
- return this.searchText.trim() !== '';
- },
- },
- watch: {
- fileFindVisible() {
- this.$nextTick(() => {
- if (!this.fileFindVisible) {
- this.searchText = '';
- } else {
- this.focusedIndex = 0;
-
- if (this.$refs.searchInput) {
- this.$refs.searchInput.focus();
- }
- }
- });
- },
- searchText() {
- this.focusedIndex = 0;
- },
- focusedIndex() {
- if (!this.mouseOver) {
- this.$nextTick(() => {
- const el = this.$refs.virtualScrollList.$el;
- const scrollTop = this.focusedIndex * FILE_FINDER_ROW_HEIGHT;
- const bottom = this.listShowCount * FILE_FINDER_ROW_HEIGHT;
-
- if (this.focusedIndex === 0) {
- // if index is the first index, scroll straight to start
- el.scrollTop = 0;
- } else if (this.focusedIndex === this.filteredBlobsLength - 1) {
- // if index is the last index, scroll to the end
- el.scrollTop = this.filteredBlobsLength * FILE_FINDER_ROW_HEIGHT;
- } else if (scrollTop >= bottom + el.scrollTop) {
- // if element is off the bottom of the scroll list, scroll down one item
- el.scrollTop = scrollTop - bottom + FILE_FINDER_ROW_HEIGHT;
- } else if (scrollTop < el.scrollTop) {
- // if element is off the top of the scroll list, scroll up one item
- el.scrollTop = scrollTop;
- }
- });
- }
- },
- },
- methods: {
- ...mapActions(['toggleFileFinder']),
- clearSearchInput() {
- this.searchText = '';
-
- this.$nextTick(() => {
- this.$refs.searchInput.focus();
- });
- },
- onKeydown(e) {
- switch (e.keyCode) {
- case UP_KEY_CODE:
- e.preventDefault();
- this.mouseOver = false;
- this.cancelMouseOver = true;
- if (this.focusedIndex > 0) {
- this.focusedIndex -= 1;
- } else {
- this.focusedIndex = this.filteredBlobsLength - 1;
- }
- break;
- case DOWN_KEY_CODE:
- e.preventDefault();
- this.mouseOver = false;
- this.cancelMouseOver = true;
- if (this.focusedIndex < this.filteredBlobsLength - 1) {
- this.focusedIndex += 1;
- } else {
- this.focusedIndex = 0;
- }
- break;
- default:
- break;
- }
- },
- onKeyup(e) {
- switch (e.keyCode) {
- case ENTER_KEY_CODE:
- this.openFile(this.filteredBlobs[this.focusedIndex]);
- break;
- case ESC_KEY_CODE:
- this.toggleFileFinder(false);
- break;
- default:
- break;
- }
- },
- openFile(file) {
- this.toggleFileFinder(false);
- router.push(`/project${file.url}`);
- },
- onMouseOver(index) {
- if (!this.cancelMouseOver) {
- this.mouseOver = true;
- this.focusedIndex = index;
- }
- },
- onMouseMove(index) {
- this.cancelMouseOver = false;
- this.onMouseOver(index);
- },
- },
-};
-</script>
-
-<template>
- <div class="ide-file-finder-overlay" @mousedown.self="toggleFileFinder(false);">
- <div class="dropdown-menu diff-file-changes ide-file-finder show">
- <div class="dropdown-input">
- <input
- ref="searchInput"
- v-model="searchText"
- :placeholder="__('Search files')"
- type="search"
- class="dropdown-input-field"
- autocomplete="off"
- @keydown="onKeydown($event);"
- @keyup="onKeyup($event);"
- />
- <i
- :class="{
- hidden: showClearInputButton,
- }"
- aria-hidden="true"
- class="fa fa-search dropdown-input-search"
- ></i>
- <i
- :aria-label="__('Clear search input')"
- :class="{
- show: showClearInputButton,
- }"
- role="button"
- class="fa fa-times dropdown-input-clear"
- @click="clearSearchInput"
- ></i>
- </div>
- <div>
- <virtual-list ref="virtualScrollList" :size="listHeight" :remain="listShowCount" wtag="ul">
- <template v-if="filteredBlobsLength">
- <li v-for="(file, index) in filteredBlobs" :key="file.key">
- <item
- :file="file"
- :search-text="searchText"
- :focused="index === focusedIndex"
- :index="index"
- class="disable-hover"
- @click="openFile"
- @mouseover="onMouseOver"
- @mousemove="onMouseMove"
- />
- </li>
- </template>
- <li v-else class="dropdown-menu-empty-item">
- <div class="append-right-default prepend-left-default prepend-top-8 append-bottom-8">
- <template v-if="loading">
- {{ __('Loading...') }}
- </template>
- <template v-else>
- {{ __('No files found.') }}
- </template>
- </div>
- </li>
- </virtual-list>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/ide/components/file_finder/item.vue b/app/assets/javascripts/ide/components/file_finder/item.vue
deleted file mode 100644
index 83e80d50aff..00000000000
--- a/app/assets/javascripts/ide/components/file_finder/item.vue
+++ /dev/null
@@ -1,104 +0,0 @@
-<script>
-import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import FileIcon from '../../../vue_shared/components/file_icon.vue';
-import ChangedFileIcon from '../../../vue_shared/components/changed_file_icon.vue';
-
-const MAX_PATH_LENGTH = 60;
-
-export default {
- components: {
- ChangedFileIcon,
- FileIcon,
- },
- props: {
- file: {
- type: Object,
- required: true,
- },
- focused: {
- type: Boolean,
- required: true,
- },
- searchText: {
- type: String,
- required: true,
- },
- index: {
- type: Number,
- required: true,
- },
- },
- computed: {
- pathWithEllipsis() {
- const { path } = this.file;
-
- return path.length < MAX_PATH_LENGTH
- ? path
- : `...${path.substr(path.length - MAX_PATH_LENGTH)}`;
- },
- nameSearchTextOccurences() {
- return fuzzaldrinPlus.match(this.file.name, this.searchText);
- },
- pathSearchTextOccurences() {
- return fuzzaldrinPlus.match(this.pathWithEllipsis, this.searchText);
- },
- },
- methods: {
- clickRow() {
- this.$emit('click', this.file);
- },
- mouseOverRow() {
- this.$emit('mouseover', this.index);
- },
- mouseMove() {
- this.$emit('mousemove', this.index);
- },
- },
-};
-</script>
-
-<template>
- <button
- :class="{
- 'is-focused': focused,
- }"
- type="button"
- class="diff-changed-file"
- @click.prevent="clickRow"
- @mouseover="mouseOverRow"
- @mousemove="mouseMove"
- >
- <file-icon
- :file-name="file.name"
- :size="16"
- css-classes="diff-file-changed-icon append-right-8"
- />
- <span class="diff-changed-file-content append-right-8">
- <strong class="diff-changed-file-name">
- <span
- v-for="(char, charIndex) in file.name.split('')"
- :key="charIndex + char"
- :class="{
- highlighted: nameSearchTextOccurences.indexOf(charIndex) >= 0,
- }"
- v-text="char"
- >
- </span>
- </strong>
- <span class="diff-changed-file-path prepend-top-5">
- <span
- v-for="(char, charIndex) in pathWithEllipsis.split('')"
- :key="charIndex + char"
- :class="{
- highlighted: pathSearchTextOccurences.indexOf(charIndex) >= 0,
- }"
- v-text="char"
- >
- </span>
- </span>
- </span>
- <span v-if="file.changed || file.tempFile" class="diff-changed-stats">
- <changed-file-icon :file="file" />
- </span>
- </button>
-</template>
diff --git a/app/assets/javascripts/ide/components/file_templates/dropdown.vue b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
index 414ea9c7d4d..343e0cca672 100644
--- a/app/assets/javascripts/ide/components/file_templates/dropdown.vue
+++ b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
@@ -91,7 +91,7 @@ export default {
<gl-loading-icon v-if="showLoading" :size="2" />
<ul v-else>
<li v-for="(item, index) in outputData" :key="index">
- <button type="button" @click="clickItem(item);">{{ item.name }}</button>
+ <button type="button" @click="clickItem(item)">{{ item.name }}</button>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index caec8779cac..9894ebb0624 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,20 +1,17 @@
<script>
import Vue from 'vue';
-import Mousetrap from 'mousetrap';
import { mapActions, mapState, mapGetters } from 'vuex';
import { __ } from '~/locale';
+import FindFile from '~/vue_shared/components/file_finder/index.vue';
import NewModal from './new_dropdown/modal.vue';
import IdeSidebar from './ide_side_bar.vue';
import RepoTabs from './repo_tabs.vue';
import IdeStatusBar from './ide_status_bar.vue';
import RepoEditor from './repo_editor.vue';
-import FindFile from './file_finder/index.vue';
import RightPane from './panes/right.vue';
import ErrorMessage from './error_message.vue';
import CommitEditorHeader from './commit_sidebar/editor_header.vue';
-const originalStopCallback = Mousetrap.stopCallback;
-
export default {
components: {
NewModal,
@@ -42,21 +39,18 @@ export default {
'emptyStateSvgPath',
'currentProjectId',
'errorMessage',
+ 'loading',
+ ]),
+ ...mapGetters([
+ 'activeFile',
+ 'hasChanges',
+ 'someUncommittedChanges',
+ 'isCommitModeActive',
+ 'allBlobs',
]),
- ...mapGetters(['activeFile', 'hasChanges', 'someUncommittedChanges', 'isCommitModeActive']),
},
mounted() {
window.onbeforeunload = e => this.onBeforeUnload(e);
-
- Mousetrap.bind(['t', 'command+p', 'ctrl+p'], e => {
- if (e.preventDefault) {
- e.preventDefault();
- }
-
- this.toggleFileFinder(!this.fileFindVisible);
- });
-
- Mousetrap.stopCallback = (e, el, combo) => this.mousetrapStopCallback(e, el, combo);
},
methods: {
...mapActions(['toggleFileFinder']),
@@ -70,17 +64,8 @@ export default {
});
return returnValue;
},
- mousetrapStopCallback(e, el, combo) {
- if (
- (combo === 't' && el.classList.contains('dropdown-input-field')) ||
- el.classList.contains('inputarea')
- ) {
- return true;
- } else if (combo === 'command+p' || combo === 'ctrl+p') {
- return false;
- }
-
- return originalStopCallback(e, el, combo);
+ openFile(file) {
+ this.$router.push(`/project${file.url}`);
},
},
};
@@ -90,7 +75,14 @@ export default {
<article class="ide position-relative d-flex flex-column align-items-stretch">
<error-message v-if="errorMessage" :message="errorMessage" />
<div class="ide-view flex-grow d-flex">
- <find-file v-show="fileFindVisible" />
+ <find-file
+ v-show="fileFindVisible"
+ :files="allBlobs"
+ :visible="fileFindVisible"
+ :loading="loading"
+ @toggle="toggleFileFinder"
+ @click="openFile"
+ />
<ide-sidebar />
<div class="multi-file-edit-pane">
<template v-if="activeFile">
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
index e2e0acc22b1..ce577ae85b0 100644
--- a/app/assets/javascripts/ide/components/ide_status_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -84,7 +84,7 @@ export default {
<button
type="button"
class="p-0 border-0 h-50"
- @click="openRightPane($options.rightSidebarViews.pipelines);"
+ @click="openRightPane($options.rightSidebarViews.pipelines)"
>
<ci-icon
v-tooltip
@@ -107,16 +107,23 @@ export default {
class="commit-sha"
>{{ lastCommit.short_id }}</a
>
- by {{ lastCommit.author_name }}
+ by
+ <user-avatar-image
+ css-classes="ide-status-avatar"
+ :size="18"
+ :img-src="latestPipeline && latestPipeline.commit.author_gravatar_url"
+ :img-alt="lastCommit.author_name"
+ :tooltip-text="lastCommit.author_name"
+ />
+ {{ lastCommit.author_name }}
<time
v-tooltip
:datetime="lastCommit.committed_date"
:title="tooltipTitle(lastCommit.committed_date)"
data-placement="top"
data-container="body"
+ >{{ lastCommitFormatedAge }}</time
>
- {{ lastCommitFormatedAge }}
- </time>
</div>
<div v-if="file" class="ide-status-file">{{ file.name }}</div>
<div v-if="file" class="ide-status-file">{{ file.eol }}</div>
diff --git a/app/assets/javascripts/ide/components/ide_tree.vue b/app/assets/javascripts/ide/components/ide_tree.vue
index 9fc21adae7c..f93496132a4 100644
--- a/app/assets/javascripts/ide/components/ide_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_tree.vue
@@ -43,7 +43,7 @@ export default {
:show-label="false"
class="d-flex border-0 p-0 mr-3 qa-new-file"
icon="doc-new"
- @click="openNewEntryModal({ type: 'blob' });"
+ @click="openNewEntryModal({ type: 'blob' })"
/>
<upload
:show-label="false"
@@ -56,7 +56,7 @@ export default {
:show-label="false"
class="d-flex border-0 p-0"
icon="folder-new"
- @click="openNewEntryModal({ type: 'tree' });"
+ @click="openNewEntryModal({ type: 'tree' })"
/>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index e8fe5fc696d..7710bfb49ec 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -75,7 +75,7 @@ export default {
<template>
<div class="ide-pipeline build-page d-flex flex-column flex-fill">
<header class="ide-job-header d-flex align-items-center">
- <button class="btn btn-default btn-sm d-flex" @click="setDetailJob(null);">
+ <button class="btn btn-default btn-sm d-flex" @click="setDetailJob(null)">
<icon name="chevron-left" /> {{ __('View jobs') }}
</button>
</header>
diff --git a/app/assets/javascripts/ide/components/merge_requests/list.vue b/app/assets/javascripts/ide/components/merge_requests/list.vue
index ac2b0eddfb4..2d55ffb3c65 100644
--- a/app/assets/javascripts/ide/components/merge_requests/list.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/list.vue
@@ -84,7 +84,7 @@ export default {
:placeholder="__('Search merge requests')"
@focus="onSearchFocus"
@input="searchMergeRequests"
- @removeToken="setSearchType(null);"
+ @removeToken="setSearchType(null)"
/>
<icon :size="18" name="search" class="input-icon" />
</div>
@@ -102,7 +102,7 @@ export default {
<button
type="button"
class="btn-link d-flex align-items-center"
- @click.stop="setSearchType(searchType);"
+ @click.stop="setSearchType(searchType)"
>
<span class="d-flex append-right-default ide-search-list-current-icon">
<icon :size="18" name="search" />
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
index a50d729036f..593a9162a06 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -1,7 +1,6 @@
<script>
import { mapActions } from 'vuex';
import icon from '~/vue_shared/components/icon.vue';
-import newModal from './modal.vue';
import upload from './upload.vue';
import ItemButton from './button.vue';
import { modalTypes } from '../../constants';
@@ -9,7 +8,6 @@ import { modalTypes } from '../../constants';
export default {
components: {
icon,
- newModal,
upload,
ItemButton,
},
@@ -73,7 +71,7 @@ export default {
:aria-label="__('Create new file or directory')"
type="button"
class="rounded border-0 d-flex ide-entry-dropdown-toggle"
- @click.stop="openDropdown();"
+ @click.stop="openDropdown()"
>
<icon name="ellipsis_v" /> <icon name="arrow-down" />
</button>
@@ -85,7 +83,7 @@ export default {
class="d-flex"
icon="doc-new"
icon-classes="mr-2"
- @click="createNewItem('blob');"
+ @click="createNewItem('blob')"
/>
</li>
<li><upload :path="path" @create="createTempEntry" /></li>
@@ -95,7 +93,7 @@ export default {
class="d-flex"
icon="folder-new"
icon-classes="mr-2"
- @click="createNewItem($options.modalTypes.tree);"
+ @click="createNewItem($options.modalTypes.tree)"
/>
</li>
<li class="divider"></li>
@@ -106,7 +104,7 @@ export default {
class="d-flex"
icon="pencil"
icon-classes="mr-2"
- @click="createNewItem($options.modalTypes.rename);"
+ @click="createNewItem($options.modalTypes.rename)"
/>
</li>
<li>
@@ -115,7 +113,7 @@ export default {
class="d-flex"
icon="remove"
icon-classes="mr-2"
- @click="deleteEntry(path);"
+ @click="deleteEntry(path)"
/>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index 63cbf41b89b..ba6bbdfef4b 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -1,6 +1,7 @@
<script>
import $ from 'jquery';
-import { __ } from '~/locale';
+import flash from '~/flash';
+import { __, sprintf, s__ } from '~/locale';
import { mapActions, mapState, mapGetters } from 'vuex';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import { modalTypes } from '../../constants';
@@ -15,15 +16,17 @@ export default {
};
},
computed: {
- ...mapState(['entryModal']),
+ ...mapState(['entries', 'entryModal']),
...mapGetters('fileTemplates', ['templateTypes']),
entryName: {
get() {
+ const entryPath = this.entryModal.entry.path;
+
if (this.entryModal.type === modalTypes.rename) {
- return this.name || this.entryModal.entry.name;
+ return this.name || entryPath;
}
- return this.name || (this.entryModal.path !== '' ? `${this.entryModal.path}/` : '');
+ return this.name || (entryPath ? `${entryPath}/` : '');
},
set(val) {
this.name = val;
@@ -51,18 +54,51 @@ export default {
return __('Create file');
},
- isCreatingNew() {
- return this.entryModal.type !== modalTypes.rename;
+ isCreatingNewFile() {
+ return this.entryModal.type === 'blob';
+ },
+ placeholder() {
+ return this.isCreatingNewFile ? 'dir/file_name' : 'dir/';
},
},
methods: {
...mapActions(['createTempEntry', 'renameEntry']),
submitForm() {
if (this.entryModal.type === modalTypes.rename) {
- this.renameEntry({
- path: this.entryModal.entry.path,
- name: this.entryName,
- });
+ if (this.entries[this.entryName] && !this.entries[this.entryName].deleted) {
+ flash(
+ sprintf(s__('The name %{entryName} is already taken in this directory.'), {
+ entryName: this.entryName,
+ }),
+ 'alert',
+ document,
+ null,
+ false,
+ true,
+ );
+ } else {
+ let parentPath = this.entryName.split('/');
+ const entryName = parentPath.pop();
+ parentPath = parentPath.join('/');
+
+ const createPromise =
+ parentPath && !this.entries[parentPath]
+ ? this.createTempEntry({ name: parentPath, type: 'tree' })
+ : Promise.resolve();
+
+ createPromise
+ .then(() =>
+ this.renameEntry({
+ path: this.entryModal.entry.path,
+ name: entryName,
+ entryPath: null,
+ parentPath,
+ }),
+ )
+ .catch(() =>
+ flash(__('Error creating a new path'), 'alert', document, null, false, true),
+ );
+ }
} else {
this.createTempEntry({
name: this.name,
@@ -79,7 +115,14 @@ export default {
$('#ide-new-entry').modal('toggle');
},
focusInput() {
+ const name = this.entries[this.entryName] ? this.entries[this.entryName].name : null;
+ const inputValue = this.$refs.fieldName.value;
+
this.$refs.fieldName.focus();
+
+ if (name) {
+ this.$refs.fieldName.setSelectionRange(inputValue.indexOf(name), inputValue.length);
+ }
},
closedModal() {
this.name = '';
@@ -107,14 +150,17 @@ export default {
v-model="entryName"
type="text"
class="form-control qa-full-file-path"
- placeholder="/dir/file_name"
+ :placeholder="placeholder"
/>
- <ul v-if="isCreatingNew" class="prepend-top-default list-inline qa-template-list">
+ <ul
+ v-if="isCreatingNewFile"
+ class="file-templates prepend-top-default list-inline qa-template-list"
+ >
<li v-for="(template, index) in templateTypes" :key="index" class="list-inline-item">
<button
type="button"
class="btn btn-missing p-1 pr-2 pl-2"
- @click="createFromTemplate(template);"
+ @click="createFromTemplate(template)"
>
{{ template.name }}
</button>
diff --git a/app/assets/javascripts/ide/components/panes/right.vue b/app/assets/javascripts/ide/components/panes/right.vue
index 7a57ccf2dd3..2e6bd85feec 100644
--- a/app/assets/javascripts/ide/components/panes/right.vue
+++ b/app/assets/javascripts/ide/components/panes/right.vue
@@ -122,7 +122,7 @@ export default {
data-placement="left"
class="ide-sidebar-link is-right"
type="button"
- @click="clickTab($event, tab);"
+ @click="clickTab($event, tab)"
>
<icon :size="16" :name="tab.icon" />
</button>
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index c13d3ec094b..94a9e87369c 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -219,7 +219,7 @@ export default {
<a
href="javascript:void(0);"
role="button"
- @click.prevent="setFileViewMode({ file, viewMode: 'editor' });"
+ @click.prevent="setFileViewMode({ file, viewMode: 'editor' })"
>
<template v-if="viewer === $options.viewerTypes.edit">
{{ __('Edit') }}
@@ -233,7 +233,7 @@ export default {
<a
href="javascript:void(0);"
role="button"
- @click.prevent="setFileViewMode({ file, viewMode: 'preview' });"
+ @click.prevent="setFileViewMode({ file, viewMode: 'preview' })"
>
{{ file.previewMode.previewTitle }}
</a>
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
index 4b87b83db8a..f6aa2295844 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -74,7 +74,7 @@ export default {
active: tab.active,
disabled: tab.pending,
}"
- @click="clickFile(tab);"
+ @click="clickFile(tab)"
@mouseover="mouseOverTab"
@mouseout="mouseOutTab"
>
@@ -88,7 +88,7 @@ export default {
:disabled="tab.pending"
type="button"
class="multi-file-tab-close"
- @click.stop.prevent="closeFile(tab);"
+ @click.stop.prevent="closeFile(tab)"
>
<icon v-if="!showChangedIcon" :size="12" name="close" />
<changed-file-icon v-else :file="tab" />
diff --git a/app/assets/javascripts/ide/components/resizable_panel.vue b/app/assets/javascripts/ide/components/resizable_panel.vue
index a89de56ab5c..7277fcb7617 100644
--- a/app/assets/javascripts/ide/components/resizable_panel.vue
+++ b/app/assets/javascripts/ide/components/resizable_panel.vue
@@ -78,8 +78,8 @@ export default {
:min-size="minSize"
:max-size="$options.maxSize"
:side="side === 'right' ? 'left' : 'right'"
- @resize-start="setResizingStatus(true);"
- @resize-end="setResizingStatus(false);"
+ @resize-start="setResizingStatus(true)"
+ @resize-end="setResizingStatus(false)"
/>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/shared/tokened_input.vue b/app/assets/javascripts/ide/components/shared/tokened_input.vue
index f58e08c2cc9..de3e71dad92 100644
--- a/app/assets/javascripts/ide/components/shared/tokened_input.vue
+++ b/app/assets/javascripts/ide/components/shared/tokened_input.vue
@@ -76,8 +76,8 @@ export default {
<button
class="selectable btn-blank"
type="button"
- @click.stop="removeToken(token);"
- @keyup.delete="removeToken(token);"
+ @click.stop="removeToken(token)"
+ @keyup.delete="removeToken(token)"
>
<div class="value-container rounded">
<div class="value">{{ token.label }}</div>
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 09245ed0296..7c560c89695 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -1,8 +1,3 @@
-// Fuzzy file finder
-export const MAX_FILE_FINDER_RESULTS = 40;
-export const FILE_FINDER_ROW_HEIGHT = 55;
-export const FILE_FINDER_EMPTY_ROW_HEIGHT = 33;
-
export const MAX_WINDOW_HEIGHT_COMPACT = 750;
// Commit message textarea
@@ -29,6 +24,22 @@ export const diffModes = {
mode_changed: 'mode_changed',
};
+export const diffViewerModes = Object.freeze({
+ not_diffable: 'not_diffable',
+ no_preview: 'no_preview',
+ added: 'added',
+ deleted: 'deleted',
+ renamed: 'renamed',
+ mode_changed: 'mode_changed',
+ text: 'text',
+ image: 'image',
+});
+
+export const diffViewerErrors = Object.freeze({
+ too_large: 'too_large',
+ stored_externally: 'server_side_but_stored_externally',
+});
+
export const rightSidebarViews = {
pipelines: { name: 'pipelines-list', keepAlive: true },
jobsDetail: { name: 'jobs-detail', keepAlive: false },
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index 3f6101e58f4..229ef168926 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -73,7 +73,7 @@ router.beforeEach((to, from, next) => {
projectId: to.params.project,
})
.then(() => {
- const basePath = to.params[0] || '';
+ const basePath = to.params.pathMatch || '';
const projectId = `${to.params.namespace}/${to.params.project}`;
const branchId = to.params.branchid;
const mergeRequestId = to.params.mrid;
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index 6351948f750..cdfebd19fa4 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -6,17 +6,25 @@ import ide from './components/ide.vue';
import store from './stores';
import router from './ide_router';
import { parseBoolean } from '../lib/utils/common_utils';
+import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
Vue.use(Translate);
/**
+ * Function that receives the default store and returns an extended one.
+ * @callback extendStoreCallback
+ * @param {Vuex.Store} store
+ * @param {Element} el
+ */
+
+/**
* Initialize the IDE on the given element.
*
* @param {Element} el - The element that will contain the IDE.
* @param {Object} options - Extra options for the IDE (Used by EE).
* @param {Component} options.rootComponent -
* Component that overrides the root component.
- * @param {(store:Vuex.Store, el:Element) => Vuex.Store} options.extendStore -
+ * @param {extendStoreCallback} options.extendStore -
* Function that receives the default store and returns an extended one.
*/
export function initIde(el, options = {}) {
@@ -53,16 +61,6 @@ export function initIde(el, options = {}) {
});
}
-// tell webpack to load assets from origin so that web workers don't break
-export function resetServiceWorkersPublicPath() {
- // __webpack_public_path__ is a global variable that can be used to adjust
- // the webpack publicPath setting at runtime.
- // see: https://webpack.js.org/guides/public-path/
- const relativeRootPath = (gon && gon.relative_url_root) || '';
- const webpackAssetPath = `${relativeRootPath}/assets/webpack/`;
- __webpack_public_path__ = webpackAssetPath; // eslint-disable-line camelcase
-}
-
/**
* Start the IDE.
*
diff --git a/app/assets/javascripts/ide/lib/common/model.js b/app/assets/javascripts/ide/lib/common/model.js
index 60bddb34977..a15f04075d9 100644
--- a/app/assets/javascripts/ide/lib/common/model.js
+++ b/app/assets/javascripts/ide/lib/common/model.js
@@ -13,12 +13,12 @@ export default class Model {
(this.originalModel = monacoEditor.createModel(
head ? head.content : this.file.raw,
undefined,
- new Uri(false, false, `original/${this.path}`),
+ new Uri('gitlab', false, `original/${this.path}`),
)),
(this.model = monacoEditor.createModel(
this.content,
undefined,
- new Uri(false, false, this.path),
+ new Uri('gitlab', false, this.path),
)),
);
if (this.file.mrChange) {
@@ -26,7 +26,7 @@ export default class Model {
(this.baseModel = monacoEditor.createModel(
this.file.baseRaw,
undefined,
- new Uri(false, false, `target/${this.path}`),
+ new Uri('gitlab', false, `target/${this.path}`),
)),
);
}
diff --git a/app/assets/javascripts/ide/lib/files.js b/app/assets/javascripts/ide/lib/files.js
new file mode 100644
index 00000000000..5dfba8fe531
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/files.js
@@ -0,0 +1,113 @@
+import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
+import { decorateData, sortTree } from '../stores/utils';
+
+export const splitParent = path => {
+ const idx = path.lastIndexOf('/');
+
+ return {
+ parent: idx >= 0 ? path.substring(0, idx) : null,
+ name: idx >= 0 ? path.substring(idx + 1) : path,
+ };
+};
+
+/**
+ * Create file objects from a list of file paths.
+ */
+export const decorateFiles = ({
+ data,
+ projectId,
+ branchId,
+ tempFile = false,
+ content = '',
+ base64 = false,
+}) => {
+ const treeList = [];
+ const entries = {};
+
+ // These mutable variable references end up being exported and used by `createTempEntry`
+ let file;
+ let parentPath;
+
+ const insertParent = path => {
+ if (!path) {
+ return null;
+ } else if (entries[path]) {
+ return entries[path];
+ }
+
+ const { parent, name } = splitParent(path);
+ const parentFolder = parent && insertParent(parent);
+ parentPath = parentFolder && parentFolder.path;
+
+ const tree = decorateData({
+ projectId,
+ branchId,
+ id: path,
+ name,
+ path,
+ url: `/${projectId}/tree/${branchId}/-/${path}/`,
+ type: 'tree',
+ parentTreeUrl: parentFolder ? parentFolder.url : `/${projectId}/tree/${branchId}/`,
+ tempFile,
+ changed: tempFile,
+ opened: tempFile,
+ parentPath,
+ });
+
+ Object.assign(entries, {
+ [path]: tree,
+ });
+
+ if (parentFolder) {
+ parentFolder.tree.push(tree);
+ } else {
+ treeList.push(tree);
+ }
+
+ return tree;
+ };
+
+ data.forEach(path => {
+ const { parent, name } = splitParent(path);
+
+ const fileFolder = parent && insertParent(parent);
+
+ if (name) {
+ parentPath = fileFolder && fileFolder.path;
+
+ file = decorateData({
+ projectId,
+ branchId,
+ id: path,
+ name,
+ path,
+ url: `/${projectId}/blob/${branchId}/-/${path}`,
+ type: 'blob',
+ parentTreeUrl: fileFolder ? fileFolder.url : `/${projectId}/blob/${branchId}`,
+ tempFile,
+ changed: tempFile,
+ content,
+ base64,
+ previewMode: viewerInformationForPath(name),
+ parentPath,
+ });
+
+ Object.assign(entries, {
+ [path]: file,
+ });
+
+ if (fileFolder) {
+ fileFolder.tree.push(file);
+ } else {
+ treeList.push(file);
+ }
+ }
+ });
+
+ return {
+ entries,
+ treeList: sortTree(treeList),
+ file,
+ parentPath,
+ };
+};
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index 13449592e62..ba33b6826d6 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -40,6 +40,9 @@ export default {
getProjectData(namespace, project) {
return Api.project(`${namespace}/${project}`);
},
+ getProjectMergeRequests(projectId, params = {}) {
+ return Api.projectMergeRequests(projectId, params);
+ },
getProjectMergeRequestData(projectId, mergeRequestId, params = {}) {
return Api.projectMergeRequest(projectId, mergeRequestId, params);
},
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index e10a132ab4b..7b660bda081 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -3,7 +3,7 @@ import Vue from 'vue';
import { visitUrl } from '~/lib/utils/url_utility';
import flash from '~/flash';
import * as types from './mutation_types';
-import FilesDecoratorWorker from './workers/files_decorator_worker';
+import { decorateFiles } from '../lib/files';
import { stageKeys } from '../constants';
export const redirectToUrl = (_, url) => visitUrl(url);
@@ -56,7 +56,6 @@ export const createTempEntry = (
{ name, type, content = '', base64 = false },
) =>
new Promise(resolve => {
- const worker = new FilesDecoratorWorker();
const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
if (state.entries[name]) {
@@ -74,31 +73,7 @@ export const createTempEntry = (
return null;
}
- worker.addEventListener('message', ({ data }) => {
- const { file, parentPath } = data;
-
- worker.terminate();
-
- commit(types.CREATE_TMP_ENTRY, {
- data,
- projectId: state.currentProjectId,
- branchId: state.currentBranchId,
- });
-
- if (type === 'blob') {
- commit(types.TOGGLE_FILE_OPEN, file.path);
- commit(types.ADD_FILE_TO_CHANGED, file.path);
- dispatch('setFileActive', file.path);
- }
-
- if (parentPath && !state.entries[parentPath].opened) {
- commit(types.TOGGLE_TREE_OPEN, parentPath);
- }
-
- resolve(file);
- });
-
- worker.postMessage({
+ const data = decorateFiles({
data: [fullName],
projectId: state.currentProjectId,
branchId: state.currentBranchId,
@@ -107,6 +82,25 @@ export const createTempEntry = (
base64,
content,
});
+ const { file, parentPath } = data;
+
+ commit(types.CREATE_TMP_ENTRY, {
+ data,
+ projectId: state.currentProjectId,
+ branchId: state.currentBranchId,
+ });
+
+ if (type === 'blob') {
+ commit(types.TOGGLE_FILE_OPEN, file.path);
+ commit(types.ADD_FILE_TO_CHANGED, file.path);
+ dispatch('setFileActive', file.path);
+ }
+
+ if (parentPath && !state.entries[parentPath].opened) {
+ commit(types.TOGGLE_TREE_OPEN, parentPath);
+ }
+
+ resolve(file);
return null;
});
@@ -215,15 +209,27 @@ export const deleteEntry = ({ commit, dispatch, state }, path) => {
export const resetOpenFiles = ({ commit }) => commit(types.RESET_OPEN_FILES);
-export const renameEntry = ({ dispatch, commit, state }, { path, name, entryPath = null }) => {
+export const renameEntry = (
+ { dispatch, commit, state },
+ { path, name, entryPath = null, parentPath },
+) => {
const entry = state.entries[entryPath || path];
- commit(types.RENAME_ENTRY, { path, name, entryPath });
+ commit(types.RENAME_ENTRY, { path, name, entryPath, parentPath });
if (entry.type === 'tree') {
- state.entries[entryPath || path].tree.forEach(f =>
- dispatch('renameEntry', { path, name, entryPath: f.path }),
- );
+ const slashedParentPath = parentPath ? `${parentPath}/` : '';
+ const targetEntry = entryPath ? entryPath.split('/').pop() : name;
+ const newParentPath = `${slashedParentPath}${targetEntry}`;
+
+ state.entries[entryPath || path].tree.forEach(f => {
+ dispatch('renameEntry', {
+ path,
+ name,
+ entryPath: f.path,
+ parentPath: newParentPath,
+ });
+ });
}
if (!entryPath && !entry.tempFile) {
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
index 18c24369996..362ced248a1 100644
--- a/app/assets/javascripts/ide/stores/actions/merge_request.js
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -4,6 +4,38 @@ import service from '../../services';
import * as types from '../mutation_types';
import { activityBarViews } from '../../constants';
+export const getMergeRequestsForBranch = ({ commit }, { projectId, branchId } = {}) =>
+ service
+ .getProjectMergeRequests(`${projectId}`, {
+ source_branch: branchId,
+ order_by: 'created_at',
+ per_page: 1,
+ })
+ .then(({ data }) => {
+ if (data.length > 0) {
+ const currentMR = data[0];
+
+ commit(types.SET_MERGE_REQUEST, {
+ projectPath: projectId,
+ mergeRequestId: currentMR.iid,
+ mergeRequest: currentMR,
+ });
+
+ commit(types.SET_CURRENT_MERGE_REQUEST, `${currentMR.iid}`);
+ }
+ })
+ .catch(e => {
+ flash(
+ __(`Error fetching merge requests for ${branchId}`),
+ 'alert',
+ document,
+ null,
+ false,
+ true,
+ );
+ throw e;
+ });
+
export const getMergeRequestData = (
{ commit, dispatch, state },
{ projectId, mergeRequestId, targetProjectId = null, force = false } = {},
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index b65f631c99c..06ed5c0b572 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -136,17 +136,24 @@ export const openBranch = ({ dispatch, state }, { projectId, branchId, basePath
return dispatch('getFiles', {
projectId,
branchId,
- }).then(() => {
- if (basePath) {
- const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath;
- const treeEntryKey = Object.keys(state.entries).find(
- key => key === path && !state.entries[key].pending,
- );
- const treeEntry = state.entries[treeEntryKey];
+ })
+ .then(() => {
+ if (basePath) {
+ const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath;
+ const treeEntryKey = Object.keys(state.entries).find(
+ key => key === path && !state.entries[key].pending,
+ );
+ const treeEntry = state.entries[treeEntryKey];
- if (treeEntry) {
- dispatch('handleTreeEntryAction', treeEntry);
+ if (treeEntry) {
+ dispatch('handleTreeEntryAction', treeEntry);
+ }
}
- }
- });
+ })
+ .then(() => {
+ dispatch('getMergeRequestsForBranch', {
+ projectId,
+ branchId,
+ });
+ });
};
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
index de5f6050074..3d83e4a9ba5 100644
--- a/app/assets/javascripts/ide/stores/actions/tree.js
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -1,7 +1,8 @@
+import _ from 'underscore';
import { __ } from '../../../locale';
import service from '../../services';
import * as types from '../mutation_types';
-import FilesDecoratorWorker from '../workers/files_decorator_worker';
+import { decorateFiles } from '../../lib/files';
export const toggleTreeOpen = ({ commit }, path) => {
commit(types.TOGGLE_TREE_OPEN, path);
@@ -32,6 +33,19 @@ export const handleTreeEntryAction = ({ commit, dispatch }, row) => {
dispatch('showTreeEntry', row.path);
};
+export const setDirectoryData = ({ state, commit }, { projectId, branchId, treeList }) => {
+ const selectedTree = state.trees[`${projectId}/${branchId}`];
+
+ commit(types.SET_DIRECTORY_DATA, {
+ treePath: `${projectId}/${branchId}`,
+ data: treeList,
+ });
+ commit(types.TOGGLE_LOADING, {
+ entry: selectedTree,
+ forceValue: false,
+ });
+};
+
export const getFiles = ({ state, commit, dispatch }, { projectId, branchId } = {}) =>
new Promise((resolve, reject) => {
if (
@@ -45,31 +59,19 @@ export const getFiles = ({ state, commit, dispatch }, { projectId, branchId } =
service
.getFiles(selectedProject.web_url, branchId)
.then(({ data }) => {
- const worker = new FilesDecoratorWorker();
- worker.addEventListener('message', e => {
- const { entries, treeList } = e.data;
- const selectedTree = state.trees[`${projectId}/${branchId}`];
-
- commit(types.SET_ENTRIES, entries);
- commit(types.SET_DIRECTORY_DATA, {
- treePath: `${projectId}/${branchId}`,
- data: treeList,
- });
- commit(types.TOGGLE_LOADING, {
- entry: selectedTree,
- forceValue: false,
- });
-
- worker.terminate();
-
- resolve();
- });
-
- worker.postMessage({
+ const { entries, treeList } = decorateFiles({
data,
projectId,
branchId,
});
+
+ commit(types.SET_ENTRIES, entries);
+
+ // Defer setting the directory data because this triggers some intense rendering.
+ // The entries is all we need to load the file editor.
+ _.defer(() => dispatch('setDirectoryData', { projectId, branchId, treeList }));
+
+ resolve();
})
.catch(e => {
if (e.response.status === 404) {
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index d97a950a8b2..24c2f71ae2b 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -202,7 +202,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
dispatch(
'setErrorMessage',
{
- text: __('An error accured whilst committing your changes.'),
+ text: __('An error occurred whilst committing your changes.'),
action: () =>
dispatch('commitChanges').then(() =>
dispatch('setErrorMessage', null, { root: true }),
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 78cdfda74f0..9b9f4b21f1c 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -206,19 +206,17 @@ export default {
}
}
},
- [types.RENAME_ENTRY](state, { path, name, entryPath = null }) {
+ [types.RENAME_ENTRY](state, { path, name, entryPath = null, parentPath }) {
const oldEntry = state.entries[entryPath || path];
- const nameRegex =
- !entryPath && oldEntry.type === 'blob'
- ? new RegExp(`${oldEntry.name}$`)
- : new RegExp(`^${path}`);
- const newPath = oldEntry.path.replace(nameRegex, name);
- const parentPath = oldEntry.parentPath ? oldEntry.parentPath.replace(nameRegex, name) : '';
+ const slashedParentPath = parentPath ? `${parentPath}/` : '';
+ const newPath = entryPath
+ ? `${slashedParentPath}${oldEntry.name}`
+ : `${slashedParentPath}${name}`;
state.entries[newPath] = {
...oldEntry,
id: newPath,
- key: `${name}-${oldEntry.type}-${oldEntry.id}`,
+ key: `${newPath}-${oldEntry.type}-${oldEntry.id}`,
path: newPath,
name: entryPath ? oldEntry.name : name,
tempFile: true,
@@ -228,6 +226,7 @@ export default {
parentPath,
raw: '',
};
+
oldEntry.moved = true;
oldEntry.movedPath = newPath;
@@ -256,6 +255,7 @@ export default {
Vue.delete(state.entries, oldEntry.path);
}
},
+
...projectMutations,
...mergeRequestMutation,
...fileMutations,
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index 0ede76fd1e0..0b2a18e9c8a 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -75,8 +75,7 @@ export const decorateData = entity => {
parentPath = '',
} = entity;
- return {
- ...dataStructure(),
+ return Object.assign(dataStructure(), {
id,
projectId,
branchId,
@@ -97,7 +96,7 @@ export const decorateData = entity => {
file_lock,
html,
parentPath,
- };
+ });
};
export const findEntry = (tree, type, name, prop = 'name') =>
diff --git a/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js b/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js
deleted file mode 100644
index fa35c215880..00000000000
--- a/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
-import { decorateData, sortTree } from '../utils';
-
-// eslint-disable-next-line no-restricted-globals
-self.addEventListener('message', e => {
- const { data, projectId, branchId, tempFile = false, content = '', base64 = false } = e.data;
-
- const treeList = [];
- let file;
- let parentPath;
- const entries = data.reduce((acc, path) => {
- const pathSplit = path.split('/');
- const blobName = pathSplit.pop().trim();
-
- if (pathSplit.length > 0) {
- pathSplit.reduce((pathAcc, folderName) => {
- const parentFolder = acc[pathAcc[pathAcc.length - 1]];
- const folderPath = `${parentFolder ? `${parentFolder.path}/` : ''}${folderName}`;
- const foundEntry = acc[folderPath];
-
- if (!foundEntry) {
- parentPath = parentFolder ? parentFolder.path : null;
-
- const tree = decorateData({
- projectId,
- branchId,
- id: folderPath,
- name: folderName,
- path: folderPath,
- url: `/${projectId}/tree/${branchId}/-/${folderPath}/`,
- type: 'tree',
- parentTreeUrl: parentFolder ? parentFolder.url : `/${projectId}/tree/${branchId}/`,
- tempFile,
- changed: tempFile,
- opened: tempFile,
- parentPath,
- });
-
- Object.assign(acc, {
- [folderPath]: tree,
- });
-
- if (parentFolder) {
- parentFolder.tree.push(tree);
- } else {
- treeList.push(tree);
- }
-
- pathAcc.push(tree.path);
- } else {
- pathAcc.push(foundEntry.path);
- }
-
- return pathAcc;
- }, []);
- }
-
- if (blobName !== '') {
- const fileFolder = acc[pathSplit.join('/')];
- parentPath = fileFolder ? fileFolder.path : null;
-
- file = decorateData({
- projectId,
- branchId,
- id: path,
- name: blobName,
- path,
- url: `/${projectId}/blob/${branchId}/-/${path}`,
- type: 'blob',
- parentTreeUrl: fileFolder ? fileFolder.url : `/${projectId}/blob/${branchId}`,
- tempFile,
- changed: tempFile,
- content,
- base64,
- previewMode: viewerInformationForPath(blobName),
- parentPath,
- });
-
- Object.assign(acc, {
- [path]: file,
- });
-
- if (fileFolder) {
- fileFolder.tree.push(file);
- } else {
- treeList.push(file);
- }
- }
-
- return acc;
- }, {});
-
- // eslint-disable-next-line no-restricted-globals
- self.postMessage({
- entries,
- treeList: sortTree(treeList),
- file,
- parentPath,
- });
-});
diff --git a/app/assets/javascripts/import_projects/components/import_projects_table.vue b/app/assets/javascripts/import_projects/components/import_projects_table.vue
new file mode 100644
index 00000000000..777f8fa6691
--- /dev/null
+++ b/app/assets/javascripts/import_projects/components/import_projects_table.vue
@@ -0,0 +1,101 @@
+<script>
+import { mapActions, mapState, mapGetters } from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import { __, sprintf } from '~/locale';
+import ImportedProjectTableRow from './imported_project_table_row.vue';
+import ProviderRepoTableRow from './provider_repo_table_row.vue';
+import eventHub from '../event_hub';
+
+export default {
+ name: 'ImportProjectsTable',
+ components: {
+ ImportedProjectTableRow,
+ ProviderRepoTableRow,
+ LoadingButton,
+ GlLoadingIcon,
+ },
+ props: {
+ providerTitle: {
+ type: String,
+ required: true,
+ },
+ },
+
+ computed: {
+ ...mapState(['importedProjects', 'providerRepos', 'isLoadingRepos']),
+ ...mapGetters(['isImportingAnyRepo', 'hasProviderRepos', 'hasImportedProjects']),
+
+ emptyStateText() {
+ return sprintf(__('No %{providerTitle} repositories available to import'), {
+ providerTitle: this.providerTitle,
+ });
+ },
+
+ fromHeaderText() {
+ return sprintf(__('From %{providerTitle}'), { providerTitle: this.providerTitle });
+ },
+ },
+
+ mounted() {
+ return this.fetchRepos();
+ },
+
+ beforeDestroy() {
+ this.stopJobsPolling();
+ this.clearJobsEtagPoll();
+ },
+
+ methods: {
+ ...mapActions(['fetchRepos', 'fetchJobs', 'stopJobsPolling', 'clearJobsEtagPoll']),
+
+ importAll() {
+ eventHub.$emit('importAll');
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="d-flex justify-content-between align-items-end flex-wrap mb-3">
+ <p class="light text-nowrap mt-2 my-sm-0">
+ {{ s__('ImportProjects|Select the projects you want to import') }}
+ </p>
+ <loading-button
+ container-class="btn btn-success js-import-all"
+ :loading="isImportingAnyRepo"
+ :label="__('Import all repositories')"
+ :disabled="!hasProviderRepos"
+ type="button"
+ @click="importAll"
+ />
+ </div>
+ <gl-loading-icon
+ v-if="isLoadingRepos"
+ class="js-loading-button-icon import-projects-loading-icon"
+ :size="4"
+ />
+ <div v-else-if="hasProviderRepos || hasImportedProjects" class="table-responsive">
+ <table class="table import-table">
+ <thead>
+ <th class="import-jobs-from-col">{{ fromHeaderText }}</th>
+ <th class="import-jobs-to-col">{{ __('To GitLab') }}</th>
+ <th class="import-jobs-status-col">{{ __('Status') }}</th>
+ <th class="import-jobs-cta-col"></th>
+ </thead>
+ <tbody>
+ <imported-project-table-row
+ v-for="project in importedProjects"
+ :key="project.id"
+ :project="project"
+ />
+ <provider-repo-table-row v-for="repo in providerRepos" :key="repo.id" :repo="repo" />
+ </tbody>
+ </table>
+ </div>
+ <div v-else class="text-center">
+ <strong>{{ emptyStateText }}</strong>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/import_projects/components/import_status.vue b/app/assets/javascripts/import_projects/components/import_status.vue
new file mode 100644
index 00000000000..9e3347a657f
--- /dev/null
+++ b/app/assets/javascripts/import_projects/components/import_status.vue
@@ -0,0 +1,47 @@
+<script>
+import { GlLoadingIcon } from '@gitlab/ui';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import STATUS_MAP from '../constants';
+
+export default {
+ name: 'ImportStatus',
+ components: {
+ CiIcon,
+ GlLoadingIcon,
+ },
+ props: {
+ status: {
+ type: String,
+ required: true,
+ },
+ },
+
+ computed: {
+ mappedStatus() {
+ return STATUS_MAP[this.status];
+ },
+
+ ciIconStatus() {
+ const { icon } = this.mappedStatus;
+
+ return {
+ icon: `status_${icon}`,
+ group: icon,
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-loading-icon
+ v-if="mappedStatus.loadingIcon"
+ :inline="true"
+ :class="mappedStatus.textClass"
+ class="align-middle mr-2"
+ />
+ <ci-icon v-else css-classes="align-middle mr-2" :status="ciIconStatus" />
+ <span :class="mappedStatus.textClass">{{ mappedStatus.text }}</span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/import_projects/components/imported_project_table_row.vue b/app/assets/javascripts/import_projects/components/imported_project_table_row.vue
new file mode 100644
index 00000000000..ab2bd87ee9f
--- /dev/null
+++ b/app/assets/javascripts/import_projects/components/imported_project_table_row.vue
@@ -0,0 +1,55 @@
+<script>
+import ImportStatus from './import_status.vue';
+import { STATUSES } from '../constants';
+
+export default {
+ name: 'ImportedProjectTableRow',
+ components: {
+ ImportStatus,
+ },
+ props: {
+ project: {
+ type: Object,
+ required: true,
+ },
+ },
+
+ computed: {
+ displayFullPath() {
+ return this.project.fullPath.replace(/^\//, '');
+ },
+
+ isFinished() {
+ return this.project.importStatus === STATUSES.FINISHED;
+ },
+ },
+};
+</script>
+
+<template>
+ <tr class="js-imported-project import-row">
+ <td>
+ <a
+ :href="project.providerLink"
+ rel="noreferrer noopener"
+ target="_blank"
+ class="js-provider-link"
+ >
+ {{ project.importSource }}
+ </a>
+ </td>
+ <td class="js-full-path">{{ displayFullPath }}</td>
+ <td><import-status :status="project.importStatus" /></td>
+ <td>
+ <a
+ v-if="isFinished"
+ class="btn btn-default js-go-to-project"
+ :href="project.fullPath"
+ rel="noreferrer noopener"
+ target="_blank"
+ >
+ {{ __('Go to project') }}
+ </a>
+ </td>
+ </tr>
+</template>
diff --git a/app/assets/javascripts/import_projects/components/provider_repo_table_row.vue b/app/assets/javascripts/import_projects/components/provider_repo_table_row.vue
new file mode 100644
index 00000000000..7cc29fa1b91
--- /dev/null
+++ b/app/assets/javascripts/import_projects/components/provider_repo_table_row.vue
@@ -0,0 +1,110 @@
+<script>
+import { mapState, mapGetters, mapActions } from 'vuex';
+import Select2Select from '~/vue_shared/components/select2_select.vue';
+import { __ } from '~/locale';
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import eventHub from '../event_hub';
+import { STATUSES } from '../constants';
+import ImportStatus from './import_status.vue';
+
+export default {
+ name: 'ProviderRepoTableRow',
+ components: {
+ Select2Select,
+ LoadingButton,
+ ImportStatus,
+ },
+ props: {
+ repo: {
+ type: Object,
+ required: true,
+ },
+ },
+
+ data() {
+ return {
+ targetNamespace: this.$store.state.defaultTargetNamespace,
+ newName: this.repo.sanitizedName,
+ };
+ },
+
+ computed: {
+ ...mapState(['namespaces', 'reposBeingImported', 'ciCdOnly']),
+
+ ...mapGetters(['namespaceSelectOptions']),
+
+ importButtonText() {
+ return this.ciCdOnly ? __('Connect') : __('Import');
+ },
+
+ select2Options() {
+ return {
+ data: this.namespaceSelectOptions,
+ containerCssClass:
+ 'import-namespace-select js-namespace-select qa-project-namespace-select',
+ };
+ },
+
+ isLoadingImport() {
+ return this.reposBeingImported.includes(this.repo.id);
+ },
+
+ status() {
+ return this.isLoadingImport ? STATUSES.SCHEDULING : STATUSES.NONE;
+ },
+ },
+
+ created() {
+ eventHub.$on('importAll', () => this.importRepo());
+ },
+
+ methods: {
+ ...mapActions(['fetchImport']),
+
+ importRepo() {
+ return this.fetchImport({
+ newName: this.newName,
+ targetNamespace: this.targetNamespace,
+ repo: this.repo,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <tr class="qa-project-import-row js-provider-repo import-row">
+ <td>
+ <a
+ :href="repo.providerLink"
+ rel="noreferrer noopener"
+ target="_blank"
+ class="js-provider-link"
+ >
+ {{ repo.fullName }}
+ </a>
+ </td>
+ <td class="d-flex flex-wrap flex-lg-nowrap">
+ <select2-select v-model="targetNamespace" :options="select2Options" />
+ <span class="px-2 import-slash-divider d-flex justify-content-center align-items-center"
+ >/</span
+ >
+ <input
+ v-model="newName"
+ type="text"
+ class="form-control import-project-name-input js-new-name qa-project-path-field"
+ />
+ </td>
+ <td><import-status :status="status" /></td>
+ <td>
+ <button
+ v-if="!isLoadingImport"
+ type="button"
+ class="qa-import-button js-import-button btn btn-default"
+ @click="importRepo"
+ >
+ {{ importButtonText }}
+ </button>
+ </td>
+ </tr>
+</template>
diff --git a/app/assets/javascripts/import_projects/constants.js b/app/assets/javascripts/import_projects/constants.js
new file mode 100644
index 00000000000..ad33ca158d2
--- /dev/null
+++ b/app/assets/javascripts/import_projects/constants.js
@@ -0,0 +1,48 @@
+import { __ } from '../locale';
+
+// The `scheduling` status is only present on the client-side,
+// it is used as the status when we are requesting to start an import.
+
+export const STATUSES = {
+ FINISHED: 'finished',
+ FAILED: 'failed',
+ SCHEDULED: 'scheduled',
+ STARTED: 'started',
+ NONE: 'none',
+ SCHEDULING: 'scheduling',
+};
+
+const STATUS_MAP = {
+ [STATUSES.FINISHED]: {
+ icon: 'success',
+ text: __('Done'),
+ textClass: 'text-success',
+ },
+ [STATUSES.FAILED]: {
+ icon: 'failed',
+ text: __('Failed'),
+ textClass: 'text-danger',
+ },
+ [STATUSES.SCHEDULED]: {
+ icon: 'pending',
+ text: __('Scheduled'),
+ textClass: 'text-warning',
+ },
+ [STATUSES.STARTED]: {
+ icon: 'running',
+ text: __('Running…'),
+ textClass: 'text-info',
+ },
+ [STATUSES.NONE]: {
+ icon: 'created',
+ text: __('Not started'),
+ textClass: 'text-muted',
+ },
+ [STATUSES.SCHEDULING]: {
+ loadingIcon: true,
+ text: __('Scheduling'),
+ textClass: 'text-warning',
+ },
+};
+
+export default STATUS_MAP;
diff --git a/app/assets/javascripts/monitoring/event_hub.js b/app/assets/javascripts/import_projects/event_hub.js
index 0948c2e5352..0948c2e5352 100644
--- a/app/assets/javascripts/monitoring/event_hub.js
+++ b/app/assets/javascripts/import_projects/event_hub.js
diff --git a/app/assets/javascripts/import_projects/index.js b/app/assets/javascripts/import_projects/index.js
new file mode 100644
index 00000000000..2d99d716609
--- /dev/null
+++ b/app/assets/javascripts/import_projects/index.js
@@ -0,0 +1,48 @@
+import Vue from 'vue';
+import { mapActions } from 'vuex';
+import Translate from '../vue_shared/translate';
+import ImportProjectsTable from './components/import_projects_table.vue';
+import { parseBoolean } from '../lib/utils/common_utils';
+import createStore from './store';
+
+Vue.use(Translate);
+
+export default function mountImportProjectsTable(mountElement) {
+ if (!mountElement) return undefined;
+
+ const {
+ reposPath,
+ provider,
+ providerTitle,
+ canSelectNamespace,
+ jobsPath,
+ importPath,
+ ciCdOnly,
+ } = mountElement.dataset;
+
+ const store = createStore();
+ return new Vue({
+ el: mountElement,
+ store,
+
+ created() {
+ this.setInitialData({
+ reposPath,
+ provider,
+ jobsPath,
+ importPath,
+ defaultTargetNamespace: gon.current_username,
+ ciCdOnly: parseBoolean(ciCdOnly),
+ canSelectNamespace: parseBoolean(canSelectNamespace),
+ });
+ },
+
+ methods: {
+ ...mapActions(['setInitialData']),
+ },
+
+ render(createElement) {
+ return createElement(ImportProjectsTable, { props: { providerTitle } });
+ },
+ });
+}
diff --git a/app/assets/javascripts/import_projects/store/actions.js b/app/assets/javascripts/import_projects/store/actions.js
new file mode 100644
index 00000000000..c44500937cc
--- /dev/null
+++ b/app/assets/javascripts/import_projects/store/actions.js
@@ -0,0 +1,106 @@
+import Visibility from 'visibilityjs';
+import * as types from './mutation_types';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import Poll from '~/lib/utils/poll';
+import createFlash from '~/flash';
+import { s__, sprintf } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
+
+let eTagPoll;
+
+export const clearJobsEtagPoll = () => {
+ eTagPoll = null;
+};
+export const stopJobsPolling = () => {
+ if (eTagPoll) eTagPoll.stop();
+};
+export const restartJobsPolling = () => {
+ if (eTagPoll) eTagPoll.restart();
+};
+
+export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
+
+export const requestRepos = ({ commit }, repos) => commit(types.REQUEST_REPOS, repos);
+export const receiveReposSuccess = ({ commit }, repos) =>
+ commit(types.RECEIVE_REPOS_SUCCESS, repos);
+export const receiveReposError = ({ commit }) => commit(types.RECEIVE_REPOS_ERROR);
+export const fetchRepos = ({ state, dispatch }) => {
+ dispatch('requestRepos');
+
+ return axios
+ .get(state.reposPath)
+ .then(({ data }) =>
+ dispatch('receiveReposSuccess', convertObjectPropsToCamelCase(data, { deep: true })),
+ )
+ .then(() => dispatch('fetchJobs'))
+ .catch(() => {
+ createFlash(
+ sprintf(s__('ImportProjects|Requesting your %{provider} repositories failed'), {
+ provider: state.provider,
+ }),
+ );
+
+ dispatch('receiveReposError');
+ });
+};
+
+export const requestImport = ({ commit, state }, repoId) => {
+ if (!state.reposBeingImported.includes(repoId)) commit(types.REQUEST_IMPORT, repoId);
+};
+export const receiveImportSuccess = ({ commit }, { importedProject, repoId }) =>
+ commit(types.RECEIVE_IMPORT_SUCCESS, { importedProject, repoId });
+export const receiveImportError = ({ commit }, repoId) =>
+ commit(types.RECEIVE_IMPORT_ERROR, repoId);
+export const fetchImport = ({ state, dispatch }, { newName, targetNamespace, repo }) => {
+ dispatch('requestImport', repo.id);
+
+ return axios
+ .post(state.importPath, {
+ ci_cd_only: state.ciCdOnly,
+ new_name: newName,
+ repo_id: repo.id,
+ target_namespace: targetNamespace,
+ })
+ .then(({ data }) =>
+ dispatch('receiveImportSuccess', {
+ importedProject: convertObjectPropsToCamelCase(data, { deep: true }),
+ repoId: repo.id,
+ }),
+ )
+ .catch(() => {
+ createFlash(s__('ImportProjects|Importing the project failed'));
+
+ dispatch('receiveImportError', { repoId: repo.id });
+ });
+};
+
+export const receiveJobsSuccess = ({ commit }, updatedProjects) =>
+ commit(types.RECEIVE_JOBS_SUCCESS, updatedProjects);
+export const fetchJobs = ({ state, dispatch }) => {
+ if (eTagPoll) return;
+
+ eTagPoll = new Poll({
+ resource: {
+ fetchJobs: () => axios.get(state.jobsPath),
+ },
+ method: 'fetchJobs',
+ successCallback: ({ data }) =>
+ dispatch('receiveJobsSuccess', convertObjectPropsToCamelCase(data, { deep: true })),
+ errorCallback: () => createFlash(s__('ImportProjects|Updating the imported projects failed')),
+ });
+
+ if (!Visibility.hidden()) {
+ eTagPoll.makeRequest();
+ }
+
+ Visibility.change(() => {
+ if (!Visibility.hidden()) {
+ dispatch('restartJobsPolling');
+ } else {
+ dispatch('stopJobsPolling');
+ }
+ });
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/import_projects/store/getters.js b/app/assets/javascripts/import_projects/store/getters.js
new file mode 100644
index 00000000000..f03474a8404
--- /dev/null
+++ b/app/assets/javascripts/import_projects/store/getters.js
@@ -0,0 +1,20 @@
+export const namespaceSelectOptions = state => {
+ const serializedNamespaces = state.namespaces.map(({ fullPath }) => ({
+ id: fullPath,
+ text: fullPath,
+ }));
+
+ return [
+ { text: 'Groups', children: serializedNamespaces },
+ {
+ text: 'Users',
+ children: [{ id: state.defaultTargetNamespace, text: state.defaultTargetNamespace }],
+ },
+ ];
+};
+
+export const isImportingAnyRepo = state => state.reposBeingImported.length > 0;
+
+export const hasProviderRepos = state => state.providerRepos.length > 0;
+
+export const hasImportedProjects = state => state.importedProjects.length > 0;
diff --git a/app/assets/javascripts/import_projects/store/index.js b/app/assets/javascripts/import_projects/store/index.js
new file mode 100644
index 00000000000..f666e2ebf33
--- /dev/null
+++ b/app/assets/javascripts/import_projects/store/index.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import state from './state';
+import * as actions from './actions';
+import * as getters from './getters';
+import mutations from './mutations';
+
+Vue.use(Vuex);
+
+export default () =>
+ new Vuex.Store({
+ state: state(),
+ actions,
+ mutations,
+ getters,
+ });
diff --git a/app/assets/javascripts/import_projects/store/mutation_types.js b/app/assets/javascripts/import_projects/store/mutation_types.js
new file mode 100644
index 00000000000..6ba3fd6f29e
--- /dev/null
+++ b/app/assets/javascripts/import_projects/store/mutation_types.js
@@ -0,0 +1,11 @@
+export const SET_INITIAL_DATA = 'SET_INITIAL_DATA';
+
+export const REQUEST_REPOS = 'REQUEST_REPOS';
+export const RECEIVE_REPOS_SUCCESS = 'RECEIVE_REPOS_SUCCESS';
+export const RECEIVE_REPOS_ERROR = 'RECEIVE_REPOS_ERROR';
+
+export const REQUEST_IMPORT = 'REQUEST_IMPORT';
+export const RECEIVE_IMPORT_SUCCESS = 'RECEIVE_IMPORT_SUCCESS';
+export const RECEIVE_IMPORT_ERROR = 'RECEIVE_IMPORT_ERROR';
+
+export const RECEIVE_JOBS_SUCCESS = 'RECEIVE_JOBS_SUCCESS';
diff --git a/app/assets/javascripts/import_projects/store/mutations.js b/app/assets/javascripts/import_projects/store/mutations.js
new file mode 100644
index 00000000000..b88de0268e7
--- /dev/null
+++ b/app/assets/javascripts/import_projects/store/mutations.js
@@ -0,0 +1,55 @@
+import Vue from 'vue';
+import * as types from './mutation_types';
+
+export default {
+ [types.SET_INITIAL_DATA](state, data) {
+ Object.assign(state, data);
+ },
+
+ [types.REQUEST_REPOS](state) {
+ state.isLoadingRepos = true;
+ },
+
+ [types.RECEIVE_REPOS_SUCCESS](state, { importedProjects, providerRepos, namespaces }) {
+ state.isLoadingRepos = false;
+
+ state.importedProjects = importedProjects;
+ state.providerRepos = providerRepos;
+ state.namespaces = namespaces;
+ },
+
+ [types.RECEIVE_REPOS_ERROR](state) {
+ state.isLoadingRepos = false;
+ },
+
+ [types.REQUEST_IMPORT](state, repoId) {
+ state.reposBeingImported.push(repoId);
+ },
+
+ [types.RECEIVE_IMPORT_SUCCESS](state, { importedProject, repoId }) {
+ const existingRepoIndex = state.reposBeingImported.indexOf(repoId);
+ if (state.reposBeingImported.includes(repoId))
+ state.reposBeingImported.splice(existingRepoIndex, 1);
+
+ const providerRepoIndex = state.providerRepos.findIndex(
+ providerRepo => providerRepo.id === repoId,
+ );
+ state.providerRepos.splice(providerRepoIndex, 1);
+ state.importedProjects.unshift(importedProject);
+ },
+
+ [types.RECEIVE_IMPORT_ERROR](state, repoId) {
+ const repoIndex = state.reposBeingImported.indexOf(repoId);
+ if (state.reposBeingImported.includes(repoId)) state.reposBeingImported.splice(repoIndex, 1);
+ },
+
+ [types.RECEIVE_JOBS_SUCCESS](state, updatedProjects) {
+ updatedProjects.forEach(updatedProject => {
+ const existingProject = state.importedProjects.find(
+ importedProject => importedProject.id === updatedProject.id,
+ );
+
+ Vue.set(existingProject, 'importStatus', updatedProject.importStatus);
+ });
+ },
+};
diff --git a/app/assets/javascripts/import_projects/store/state.js b/app/assets/javascripts/import_projects/store/state.js
new file mode 100644
index 00000000000..637fef6e53c
--- /dev/null
+++ b/app/assets/javascripts/import_projects/store/state.js
@@ -0,0 +1,15 @@
+export default () => ({
+ reposPath: '',
+ importPath: '',
+ jobsPath: '',
+ currentProjectId: '',
+ provider: '',
+ currentUsername: '',
+ importedProjects: [],
+ providerRepos: [],
+ namespaces: [],
+ reposBeingImported: [],
+ isLoadingRepos: false,
+ canSelectNamespace: false,
+ ciCdOnly: false,
+});
diff --git a/app/assets/javascripts/issuable/auto_width_dropdown_select.js b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
index 612c524ca1c..e0fb58ef195 100644
--- a/app/assets/javascripts/issuable/auto_width_dropdown_select.js
+++ b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
@@ -11,10 +11,14 @@ class AutoWidthDropdownSelect {
init() {
const { dropdownClass } = this;
- this.$selectElement.select2({
- dropdownCssClass: dropdownClass,
- ...AutoWidthDropdownSelect.selectOptions(this.dropdownClass),
- });
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ this.$selectElement.select2({
+ dropdownCssClass: dropdownClass,
+ ...AutoWidthDropdownSelect.selectOptions(this.dropdownClass),
+ });
+ })
+ .catch(() => {});
return this;
}
diff --git a/app/assets/javascripts/issuable_context.js b/app/assets/javascripts/issuable_context.js
index f3d722409b0..48e7ed1318d 100644
--- a/app/assets/javascripts/issuable_context.js
+++ b/app/assets/javascripts/issuable_context.js
@@ -7,10 +7,14 @@ export default class IssuableContext {
constructor(currentUser) {
this.userSelect = new UsersSelect(currentUser);
- $('select.select2').select2({
- width: 'resolve',
- dropdownAutoWidth: true,
- });
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ $('select.select2').select2({
+ width: 'resolve',
+ dropdownAutoWidth: true,
+ });
+ })
+ .catch(() => {});
$('.issuable-sidebar .inline-update').on('change', 'select', function onClickSelect() {
return $(this).submit();
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
index c81a2230310..9336b71cfd7 100644
--- a/app/assets/javascripts/issuable_form.js
+++ b/app/assets/javascripts/issuable_form.js
@@ -44,6 +44,7 @@ export default class IssuableForm {
parse: dateString => parsePikadayDate(dateString),
toString: date => pikadayToString(date),
onSelect: dateText => $issuableDueDate.val(calendar.toString(dateText)),
+ firstDay: gon.first_day_of_week,
});
calendar.setDate(parsePikadayDate($issuableDueDate.val()));
}
@@ -120,35 +121,39 @@ export default class IssuableForm {
}
initTargetBranchDropdown() {
- this.$targetBranchSelect.select2({
- ...AutoWidthDropdownSelect.selectOptions('js-target-branch-select'),
- ajax: {
- url: this.$targetBranchSelect.data('endpoint'),
- dataType: 'JSON',
- quietMillis: 250,
- data(search) {
- return {
- search,
- };
- },
- results(data) {
- return {
- // `data` keys are translated so we can't just access them with a string based key
- results: data[Object.keys(data)[0]].map(name => ({
- id: name,
- text: name,
- })),
- };
- },
- },
- initSelection(el, callback) {
- const val = el.val();
-
- callback({
- id: val,
- text: val,
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ this.$targetBranchSelect.select2({
+ ...AutoWidthDropdownSelect.selectOptions('js-target-branch-select'),
+ ajax: {
+ url: this.$targetBranchSelect.data('endpoint'),
+ dataType: 'JSON',
+ quietMillis: 250,
+ data(search) {
+ return {
+ search,
+ };
+ },
+ results(data) {
+ return {
+ // `data` keys are translated so we can't just access them with a string based key
+ results: data[Object.keys(data)[0]].map(name => ({
+ id: name,
+ text: name,
+ })),
+ };
+ },
+ },
+ initSelection(el, callback) {
+ const val = el.val();
+
+ callback({
+ id: val,
+ text: val,
+ });
+ },
});
- },
- });
+ })
+ .catch(() => {});
}
}
diff --git a/app/assets/javascripts/issuable_suggestions/index.js b/app/assets/javascripts/issuable_suggestions/index.js
index 2c80cf1797a..40916c9d27f 100644
--- a/app/assets/javascripts/issuable_suggestions/index.js
+++ b/app/assets/javascripts/issuable_suggestions/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import defaultClient from '~/lib/graphql';
+import createDefaultClient from '~/lib/graphql';
import App from './components/app.vue';
Vue.use(VueApollo);
@@ -10,7 +10,7 @@ export default function() {
const issueTitle = document.getElementById('issue_title');
const { projectPath } = el.dataset;
const apolloProvider = new VueApollo({
- defaultClient,
+ defaultClient: createDefaultClient(),
});
return new Vue({
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index e4e2eab2acd..bd757a76ee7 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -1,5 +1,7 @@
<script>
import Visibility from 'visibilityjs';
+import { __, s__, sprintf } from '~/locale';
+import createFlash from '~/flash';
import { visitUrl } from '../../lib/utils/url_utility';
import Poll from '../../lib/utils/poll';
import eventHub from '../event_hub';
@@ -106,11 +108,6 @@ export default {
type: String,
required: true,
},
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
projectPath: {
type: String,
required: true,
@@ -129,6 +126,11 @@ export default {
required: false,
default: true,
},
+ lockVersion: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
},
data() {
const store = new Store({
@@ -140,6 +142,7 @@ export default {
updatedByName: this.updatedByName,
updatedByPath: this.updatedByPath,
taskStatus: this.initialTaskStatus,
+ lock_version: this.lockVersion,
});
return {
@@ -160,6 +163,9 @@ export default {
const titleChanged = this.initialTitleText !== this.store.formState.title;
return descriptionChanged || titleChanged;
},
+ defaultErrorMessage() {
+ return sprintf(s__('Error updating %{issuableType}'), { issuableType: this.issuableType });
+ },
},
created() {
this.service = new Service(this.endpoint);
@@ -201,11 +207,22 @@ export default {
methods: {
handleBeforeUnloadEvent(e) {
const event = e;
- if (this.showForm && this.issueChanged) {
- event.returnValue = 'Are you sure you want to lose your issue information?';
+ if (this.showForm && this.issueChanged && !this.showRecaptcha) {
+ event.returnValue = __('Are you sure you want to lose your issue information?');
}
return undefined;
},
+ updateStoreState() {
+ return this.service
+ .getData()
+ .then(res => res.data)
+ .then(data => {
+ this.store.updateState(data);
+ })
+ .catch(() => {
+ createFlash(this.defaultErrorMessage);
+ });
+ },
openForm() {
if (!this.showForm) {
@@ -213,6 +230,7 @@ export default {
this.store.setFormState({
title: this.state.titleText,
description: this.state.descriptionText,
+ lock_version: this.state.lock_version,
lockedWarningVisible: false,
updateLoading: false,
});
@@ -231,20 +249,24 @@ export default {
if (window.location.pathname !== data.web_url) {
visitUrl(data.web_url);
}
-
- return this.service.getData();
})
- .then(res => res.data)
- .then(data => {
- this.store.updateState(data);
+ .then(this.updateStoreState)
+ .then(() => {
eventHub.$emit('close.form');
})
- .catch(error => {
- if (error && error.name === 'SpamError') {
+ .catch((error = {}) => {
+ const { name, response = {} } = error;
+
+ if (name === 'SpamError') {
this.openRecaptcha();
} else {
- eventHub.$emit('close.form');
- window.Flash(`Error updating ${this.issuableType}`);
+ let errMsg = this.defaultErrorMessage;
+
+ if (response.data && response.data.errors) {
+ errMsg += `. ${response.data.errors.join(' ')}`;
+ }
+
+ createFlash(errMsg);
}
});
},
@@ -268,8 +290,9 @@ export default {
visitUrl(data.web_url);
})
.catch(() => {
- eventHub.$emit('close.form');
- window.Flash(`Error deleting ${this.issuableType}`);
+ createFlash(
+ sprintf(s__('Error deleting %{issuableType}'), { issuableType: this.issuableType }),
+ );
});
},
},
@@ -285,7 +308,6 @@ export default {
:issuable-templates="issuableTemplates"
:markdown-docs-path="markdownDocsPath"
:markdown-preview-path="markdownPreviewPath"
- :markdown-version="markdownVersion"
:project-path="projectPath"
:project-namespace="projectNamespace"
:show-delete-button="showDeleteButton"
@@ -313,6 +335,8 @@ export default {
:task-status="state.taskStatus"
:issuable-type="issuableType"
:update-url="updateEndpoint"
+ :lock-version="state.lock_version"
+ @taskListUpdateFailed="updateStoreState"
/>
<edited-component
v-if="hasUpdated"
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index 5ca88d75063..58f14bac8c8 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -1,5 +1,7 @@
<script>
import $ from 'jquery';
+import { s__, sprintf } from '~/locale';
+import createFlash from '~/flash';
import animateMixin from '../mixins/animate';
import TaskList from '../../task_list';
import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
@@ -35,6 +37,11 @@ export default {
required: false,
default: null,
},
+ lockVersion: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
},
data() {
return {
@@ -67,8 +74,10 @@ export default {
new TaskList({
dataType: this.issuableType,
fieldName: 'description',
+ lockVersion: this.lockVersion,
selector: '.detail-page-description',
onSuccess: this.taskListUpdateSuccess.bind(this),
+ onError: this.taskListUpdateError.bind(this),
});
}
},
@@ -82,6 +91,21 @@ export default {
}
},
+ taskListUpdateError() {
+ createFlash(
+ sprintf(
+ s__(
+ 'Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again.',
+ ),
+ {
+ issueType: this.issuableType,
+ },
+ ),
+ );
+
+ this.$emit('taskListUpdateFailed');
+ },
+
updateTaskStatusText() {
const taskRegexMatches = this.taskStatus.match(/(\d+) of ((?!0)\d+)/);
const $issuableHeader = $('.issuable-meta');
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue
index 90258c0e044..299130e56ae 100644
--- a/app/assets/javascripts/issue_show/components/fields/description.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description.vue
@@ -20,11 +20,6 @@ export default {
type: String,
required: true,
},
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
canAttachFile: {
type: Boolean,
required: false,
@@ -48,7 +43,6 @@ export default {
<markdown-field
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath"
- :markdown-version="markdownVersion"
:can-attach-file="canAttachFile"
:enable-autocomplete="enableAutocomplete"
>
diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue
index 45b60bc3392..eade31f1d14 100644
--- a/app/assets/javascripts/issue_show/components/form.vue
+++ b/app/assets/javascripts/issue_show/components/form.vue
@@ -39,11 +39,6 @@ export default {
type: String,
required: true,
},
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
projectPath: {
type: String,
required: true,
@@ -101,7 +96,6 @@ export default {
:form-state="formState"
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath"
- :markdown-version="markdownVersion"
:can-attach-file="canAttachFile"
:enable-autocomplete="enableAutocomplete"
/>
diff --git a/app/assets/javascripts/issue_show/stores/index.js b/app/assets/javascripts/issue_show/stores/index.js
index 32044d6da25..3c17e73ccec 100644
--- a/app/assets/javascripts/issue_show/stores/index.js
+++ b/app/assets/javascripts/issue_show/stores/index.js
@@ -1,3 +1,5 @@
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
export default class Store {
constructor(initialState) {
this.state = initialState;
@@ -6,6 +8,7 @@ export default class Store {
description: '',
lockedWarningVisible: false,
updateLoading: false,
+ lock_version: 0,
};
}
@@ -14,14 +17,10 @@ export default class Store {
this.formState.lockedWarningVisible = true;
}
+ Object.assign(this.state, convertObjectPropsToCamelCase(data));
this.state.titleHtml = data.title;
- this.state.titleText = data.title_text;
this.state.descriptionHtml = data.description;
- this.state.descriptionText = data.description_text;
- this.state.taskStatus = data.task_status;
- this.state.updatedAt = data.updated_at;
- this.state.updatedByName = data.updated_by_name;
- this.state.updatedByPath = data.updated_by_path;
+ this.state.lock_version = data.lock_version;
}
stateShouldUpdate(data) {
diff --git a/app/assets/javascripts/jobs/components/commit_block.vue b/app/assets/javascripts/jobs/components/commit_block.vue
index e0f55518eef..7076a79dd5d 100644
--- a/app/assets/javascripts/jobs/components/commit_block.vue
+++ b/app/assets/javascripts/jobs/components/commit_block.vue
@@ -45,7 +45,7 @@ export default {
/>
<span v-if="mergeRequest">
- {{ __('in') }}
+ in
<gl-link :href="mergeRequest.path" class="js-link-commit link-commit"
>!{{ mergeRequest.iid }}</gl-link
>
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index 786ab16992d..dbadd224251 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -34,6 +34,7 @@ export default {
StuckBlock,
Sidebar,
GlLoadingIcon,
+ SharedRunner: () => import('ee_component/jobs/components/shared_runner_limit_block.vue'),
},
mixins: [delayedJobMixin],
props: {
@@ -80,11 +81,11 @@ export default {
'hasError',
]),
...mapGetters([
- 'headerActions',
'headerTime',
'shouldRenderCalloutMessage',
'shouldRenderTriggeredLabel',
'hasEnvironment',
+ 'shouldRenderSharedRunnerLimitWarning',
'hasTrace',
'emptyStateIllustration',
'isScrollingDown',
@@ -202,7 +203,6 @@ export default {
:item-id="job.id"
:time="headerTime"
:user="job.user"
- :actions="headerActions"
:has-sidebar-button="true"
:should-render-triggered-label="shouldRenderTriggeredLabel"
:item-name="__('Job')"
@@ -223,6 +223,14 @@ export default {
:runners-path="runnerSettingsUrl"
/>
+ <shared-runner
+ v-if="shouldRenderSharedRunnerLimitWarning"
+ class="js-shared-runner-limit"
+ :quota-used="job.runners.quota.used"
+ :quota-limit="job.runners.quota.limit"
+ :runners-path="runnerHelpUrl"
+ />
+
<environments-block
v-if="hasEnvironment"
class="js-job-environment"
@@ -240,14 +248,19 @@ export default {
<div
v-if="job.archived"
ref="sticky"
- class="js-archived-job prepend-top-default archived-sticky sticky-top"
+ class="js-archived-job prepend-top-default archived-job"
+ :class="{ 'sticky-top border-bottom-0': hasTrace }"
>
<icon name="lock" class="align-text-bottom" />
{{ __('This job is archived. Only the complete pipeline can be retried.') }}
</div>
<!-- job log -->
- <div v-if="hasTrace" class="build-trace-container">
+ <div
+ v-if="hasTrace"
+ class="build-trace-container"
+ :class="{ 'prepend-top-default': !job.archived }"
+ >
<log-top-bar
:class="{
'sidebar-expanded': isSidebarOpen,
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index ad3e7dabc79..1691ac62100 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -48,8 +48,7 @@ export default {
return `${this.job.runner.description} (#${this.job.runner.id})`;
},
retryButtonClass() {
- let className =
- 'js-retry-button float-right btn btn-retry d-none d-md-block d-lg-block d-xl-block';
+ let className = 'js-retry-button btn btn-retry';
className +=
this.job.status && this.job.recoverable ? ' btn-primary' : ' btn-inverted-secondary';
return className;
@@ -110,24 +109,27 @@ export default {
<aside class="right-sidebar build-sidebar" data-offset-top="101" data-spy="affix">
<div class="sidebar-container">
<div class="blocks-container">
- <div class="block d-flex align-items-center">
- <h4 class="flex-grow-1 prepend-top-8 m-0">{{ job.name }}</h4>
- <gl-link
- v-if="job.retry_path"
- :class="retryButtonClass"
- :href="job.retry_path"
- data-method="post"
- rel="nofollow"
- >{{ __('Retry') }}</gl-link
- >
- <gl-link
- v-if="job.terminal_path"
- :href="job.terminal_path"
- class="js-terminal-link pull-right btn btn-primary btn-inverted visible-md-block visible-lg-block"
- target="_blank"
- >
- {{ __('Debug') }} <icon name="external-link" />
- </gl-link>
+ <div class="block d-flex flex-nowrap align-items-center">
+ <h4 class="my-0 mr-2 text-break-word">{{ job.name }}</h4>
+ <div class="flex-grow-1 flex-shrink-0 text-right">
+ <gl-link
+ v-if="job.retry_path"
+ :class="retryButtonClass"
+ :href="job.retry_path"
+ data-method="post"
+ rel="nofollow"
+ >{{ __('Retry') }}</gl-link
+ >
+ <gl-link
+ v-if="job.cancel_path"
+ :href="job.cancel_path"
+ class="js-cancel-job btn btn-default"
+ data-method="post"
+ rel="nofollow"
+ >{{ __('Cancel') }}</gl-link
+ >
+ </div>
+
<gl-button
:aria-label="__('Toggle Sidebar')"
type="button"
@@ -137,22 +139,24 @@ export default {
<i aria-hidden="true" data-hidden="true" class="fa fa-angle-double-right"></i>
</gl-button>
</div>
- <div v-if="job.retry_path || job.new_issue_path" class="block retry-link">
+
+ <div v-if="job.terminal_path || job.new_issue_path" class="block retry-link">
<gl-link
v-if="job.new_issue_path"
:href="job.new_issue_path"
- class="js-new-issue btn btn-success btn-inverted"
+ class="js-new-issue btn btn-success btn-inverted float-left mr-2"
>{{ __('New issue') }}</gl-link
>
<gl-link
- v-if="job.retry_path"
- :href="job.retry_path"
- class="js-retry-job btn btn-inverted-secondary"
- data-method="post"
- rel="nofollow"
- >{{ __('Retry') }}</gl-link
+ v-if="job.terminal_path"
+ :href="job.terminal_path"
+ class="js-terminal-link btn btn-primary btn-inverted visible-md-block visible-lg-block float-left"
+ target="_blank"
>
+ {{ __('Debug') }} <icon name="external-link" :size="14" />
+ </gl-link>
</div>
+
<div :class="{ block: renderBlock }">
<detail-row
v-if="job.duration"
@@ -193,16 +197,6 @@ export default {
tag
}}</span>
</p>
-
- <div v-if="job.cancel_path" class="btn-group prepend-top-5" role="group">
- <gl-link
- :href="job.cancel_path"
- class="js-cancel-job btn btn-sm btn-default"
- data-method="post"
- rel="nofollow"
- >{{ __('Cancel') }}</gl-link
- >
- </div>
</div>
<artifacts-block v-if="hasArtifact" :artifact="job.artifact" />
diff --git a/app/assets/javascripts/jobs/components/stages_dropdown.vue b/app/assets/javascripts/jobs/components/stages_dropdown.vue
index 7f79e92067f..c5076d65ff9 100644
--- a/app/assets/javascripts/jobs/components/stages_dropdown.vue
+++ b/app/assets/javascripts/jobs/components/stages_dropdown.vue
@@ -39,7 +39,9 @@ export default {
<ci-icon :status="pipeline.details.status" class="vertical-align-middle" />
<span class="font-weight-bold">{{ __('Pipeline') }}</span>
- <a :href="pipeline.path" class="js-pipeline-path link-commit">#{{ pipeline.id }}</a>
+ <a :href="pipeline.path" class="js-pipeline-path link-commit qa-pipeline-path"
+ >#{{ pipeline.id }}</a
+ >
<template v-if="hasRef">
{{ __('from') }}
<a :href="pipeline.ref.path" class="link-commit ref-name">{{ pipeline.ref.name }}</a>
@@ -55,7 +57,7 @@ export default {
<ul class="dropdown-menu">
<li v-for="stage in stages" :key="stage.name">
- <button type="button" class="js-stage-item stage-item" @click="onStageClick(stage);">
+ <button type="button" class="js-stage-item stage-item" @click="onStageClick(stage)">
{{ stage.name }}
</button>
</li>
diff --git a/app/assets/javascripts/jobs/store/getters.js b/app/assets/javascripts/jobs/store/getters.js
index 35e92b0b5d9..73c1cbc3a99 100644
--- a/app/assets/javascripts/jobs/store/getters.js
+++ b/app/assets/javascripts/jobs/store/getters.js
@@ -1,22 +1,6 @@
import _ from 'underscore';
-import { __ } from '~/locale';
import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
-export const headerActions = state => {
- if (state.job.new_issue_path) {
- return [
- {
- label: __('New issue'),
- path: state.job.new_issue_path,
- cssClass:
- 'js-new-issue btn btn-success btn-inverted d-none d-md-block d-lg-block d-xl-block',
- type: 'link',
- },
- ];
- }
- return [];
-};
-
export const headerTime = state => (state.job.started ? state.job.started : state.job.created_at);
export const shouldRenderCalloutMessage = state =>
@@ -44,6 +28,17 @@ export const emptyStateIllustration = state =>
export const emptyStateAction = state =>
(state.job && state.job.status && state.job.status.action) || null;
+/**
+ * Shared runners limit is only rendered when
+ * used quota is bigger or equal than the limit
+ *
+ * @returns {Boolean}
+ */
+export const shouldRenderSharedRunnerLimitWarning = state =>
+ !_.isEmpty(state.job.runners) &&
+ !_.isEmpty(state.job.runners.quota) &&
+ state.job.runners.quota.used >= state.job.runners.quota.limit;
+
export const isScrollingDown = state => isScrolledToBottom() && !state.isTraceComplete;
export const hasRunnersForProject = state =>
diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js
index 062501d1d04..f134a54dd53 100644
--- a/app/assets/javascripts/label_manager.js
+++ b/app/assets/javascripts/label_manager.js
@@ -70,7 +70,18 @@ export default class LabelManager {
const $detachedLabel = $label.detach();
this.toggleLabelPriorityBadge($detachedLabel, action);
- $detachedLabel.appendTo($target);
+
+ const $labelEls = $target.find('li.label-list-item');
+
+ /*
+ * If there is a label element in the target, we'd want to
+ * append the new label just right next to it.
+ */
+ if ($labelEls.length) {
+ $labelEls.last().after($detachedLabel);
+ } else {
+ $detachedLabel.appendTo($target);
+ }
if ($from.find('li').length) {
$from.find('.empty-message').removeClass('hidden');
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index f7a611fbca0..cca4927c115 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -199,8 +199,8 @@ export default class LabelsSelect {
.catch(() => flash(__('Error fetching labels.')));
},
renderRow: function(label, instance) {
- var $a,
- $li,
+ var linkEl,
+ listItemEl,
color,
colorEl,
indeterminate,
@@ -209,12 +209,11 @@ export default class LabelsSelect {
spacing,
i,
marked,
- dropdownName,
dropdownValue;
- $li = $('<li>');
- $a = $('<a href="#">');
+
selectedClass = [];
removesAll = label.id <= 0 || label.id == null;
+
if ($dropdown.hasClass('js-filter-bulk-update')) {
indeterminate = $dropdown.data('indeterminate') || [];
marked = $dropdown.data('marked') || [];
@@ -233,7 +232,6 @@ export default class LabelsSelect {
}
} else {
if (this.id(label)) {
- dropdownName = $dropdown.data('fieldName');
dropdownValue = this.id(label)
.toString()
.replace(/'/g, "\\'");
@@ -241,7 +239,7 @@ export default class LabelsSelect {
if (
$form.find(
"input[type='hidden'][name='" +
- dropdownName +
+ this.fieldName +
"'][value='" +
dropdownValue +
"']",
@@ -251,24 +249,34 @@ export default class LabelsSelect {
}
}
- if ($dropdown.hasClass('js-multiselect') && removesAll) {
+ if (this.multiSelect && removesAll) {
selectedClass.push('dropdown-clear-active');
}
}
+
if (label.color) {
colorEl =
"<span class='dropdown-label-box' style='background: " + label.color + "'></span>";
} else {
colorEl = '';
}
+
+ linkEl = document.createElement('a');
+ linkEl.href = '#';
+
// We need to identify which items are actually labels
if (label.id) {
selectedClass.push('label-item');
- $a.attr('data-label-id', label.id);
+ linkEl.dataset.labelId = label.id;
}
- $a.addClass(selectedClass.join(' ')).html(`${colorEl} ${_.escape(label.title)}`);
- // Return generated html
- return $li.html($a).prop('outerHTML');
+
+ linkEl.className = selectedClass.join(' ');
+ linkEl.innerHTML = `${colorEl} ${_.escape(label.title)}`;
+
+ listItemEl = document.createElement('li');
+ listItemEl.appendChild(linkEl);
+
+ return listItemEl;
},
search: {
fields: ['title'],
diff --git a/app/assets/javascripts/layout_nav.js b/app/assets/javascripts/layout_nav.js
index b8c3c237eb3..4314e5e1afb 100644
--- a/app/assets/javascripts/layout_nav.js
+++ b/app/assets/javascripts/layout_nav.js
@@ -11,48 +11,53 @@ function hideEndFade($scrollingTabs) {
});
}
+function initDeferred() {
+ $(document).trigger('init.scrolling-tabs');
+}
+
export default function initLayoutNav() {
const contextualSidebar = new ContextualSidebar();
contextualSidebar.bindEvents();
initFlyOutNav();
- $(document)
- .on('init.scrolling-tabs', () => {
- const $scrollingTabs = $('.scrolling-tabs').not('.is-initialized');
- $scrollingTabs.addClass('is-initialized');
+ // We need to init it on DomContentLoaded as others could also call it
+ $(document).on('init.scrolling-tabs', () => {
+ const $scrollingTabs = $('.scrolling-tabs').not('.is-initialized');
+ $scrollingTabs.addClass('is-initialized');
- $(window)
- .on('resize.nav', () => {
- hideEndFade($scrollingTabs);
- })
- .trigger('resize.nav');
+ $(window)
+ .on('resize.nav', () => {
+ hideEndFade($scrollingTabs);
+ })
+ .trigger('resize.nav');
- $scrollingTabs.on('scroll', function tabsScrollEvent() {
- const $this = $(this);
- const currentPosition = $this.scrollLeft();
- const maxPosition = $this.prop('scrollWidth') - $this.outerWidth();
+ $scrollingTabs.on('scroll', function tabsScrollEvent() {
+ const $this = $(this);
+ const currentPosition = $this.scrollLeft();
+ const maxPosition = $this.prop('scrollWidth') - $this.outerWidth();
- $this.siblings('.fade-left').toggleClass('scrolling', currentPosition > 0);
- $this.siblings('.fade-right').toggleClass('scrolling', currentPosition < maxPosition - 1);
- });
+ $this.siblings('.fade-left').toggleClass('scrolling', currentPosition > 0);
+ $this.siblings('.fade-right').toggleClass('scrolling', currentPosition < maxPosition - 1);
+ });
- $scrollingTabs.each(function scrollTabsEachLoop() {
- const $this = $(this);
- const scrollingTabWidth = $this.width();
- const $active = $this.find('.active');
- const activeWidth = $active.width();
+ $scrollingTabs.each(function scrollTabsEachLoop() {
+ const $this = $(this);
+ const scrollingTabWidth = $this.width();
+ const $active = $this.find('.active');
+ const activeWidth = $active.width();
- if ($active.length) {
- const offset = $active.offset().left + activeWidth;
+ if ($active.length) {
+ const offset = $active.offset().left + activeWidth;
- if (offset > scrollingTabWidth - 30) {
- const scrollLeft = offset - scrollingTabWidth / 2 - activeWidth / 2;
+ if (offset > scrollingTabWidth - 30) {
+ const scrollLeft = offset - scrollingTabWidth / 2 - activeWidth / 2;
- $this.scrollLeft(scrollLeft);
- }
+ $this.scrollLeft(scrollLeft);
}
- });
- })
- .trigger('init.scrolling-tabs');
+ }
+ });
+ });
+
+ requestIdleCallback(initDeferred);
}
diff --git a/app/assets/javascripts/lazy_loader.js b/app/assets/javascripts/lazy_loader.js
index ee01a73a6e8..66f25b622e0 100644
--- a/app/assets/javascripts/lazy_loader.js
+++ b/app/assets/javascripts/lazy_loader.js
@@ -163,6 +163,7 @@ export default class LazyLoader {
img.removeAttribute('data-src');
img.classList.remove('lazy');
img.classList.add('js-lazy-loaded');
+ img.classList.add('qa-js-lazy-loaded');
}
}
}
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index 20a0f142d9e..64e4e899f44 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -1,9 +1,11 @@
import ApolloClient from 'apollo-boost';
import csrf from '~/lib/utils/csrf';
-export default new ApolloClient({
- uri: `${gon.relative_url_root}/api/graphql`,
- headers: {
- [csrf.headerKey]: csrf.token,
- },
-});
+export default (clientState = {}) =>
+ new ApolloClient({
+ uri: `${gon.relative_url_root}/api/graphql`,
+ headers: {
+ [csrf.headerKey]: csrf.token,
+ },
+ clientState,
+ });
diff --git a/app/assets/javascripts/lib/utils/chart_utils.js b/app/assets/javascripts/lib/utils/chart_utils.js
new file mode 100644
index 00000000000..0f78756aac8
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/chart_utils.js
@@ -0,0 +1,83 @@
+const commonTooltips = () => ({
+ mode: 'x',
+ intersect: false,
+});
+
+const adjustedFontScale = () => ({
+ fontSize: 8,
+});
+
+const yAxesConfig = (shouldAdjustFontSize = false) => ({
+ yAxes: [
+ {
+ ticks: {
+ beginAtZero: true,
+ ...(shouldAdjustFontSize ? adjustedFontScale() : {}),
+ },
+ },
+ ],
+});
+
+const xAxesConfig = (shouldAdjustFontSize = false) => ({
+ xAxes: [
+ {
+ ticks: {
+ ...(shouldAdjustFontSize ? adjustedFontScale() : {}),
+ },
+ },
+ ],
+});
+
+const commonChartOptions = () => ({
+ responsive: true,
+ maintainAspectRatio: false,
+ legend: false,
+});
+
+export const barChartOptions = shouldAdjustFontSize => ({
+ ...commonChartOptions(),
+ scales: {
+ ...yAxesConfig(shouldAdjustFontSize),
+ ...xAxesConfig(shouldAdjustFontSize),
+ },
+ tooltips: {
+ ...commonTooltips(),
+ displayColors: false,
+ callbacks: {
+ title() {
+ return '';
+ },
+ label({ xLabel, yLabel }) {
+ return `${xLabel}: ${yLabel}`;
+ },
+ },
+ },
+});
+
+export const pieChartOptions = commonChartOptions;
+
+export const lineChartOptions = ({ width, numberOfPoints, shouldAdjustFontSize }) => ({
+ ...commonChartOptions(),
+ scales: {
+ ...yAxesConfig(shouldAdjustFontSize),
+ ...xAxesConfig(shouldAdjustFontSize),
+ },
+ elements: {
+ point: {
+ hitRadius: width / (numberOfPoints * 2),
+ },
+ },
+ tooltips: {
+ ...commonTooltips(),
+ caretSize: 0,
+ multiKeyBackground: 'rgba(0,0,0,0)',
+ callbacks: {
+ labelColor({ datasetIndex }, { config }) {
+ return {
+ backgroundColor: config.data.datasets[datasetIndex].backgroundColor,
+ borderColor: 'rgba(0,0,0,0)',
+ };
+ },
+ },
+ },
+});
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 9e22cdc04e9..1af6b63efc9 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -1,3 +1,7 @@
+/**
+ * @module common-utils
+ */
+
import $ from 'jquery';
import axios from './axios_utils';
import { getLocationHash } from './url_utility';
@@ -118,14 +122,15 @@ export const handleLocationHash = () => {
// Check if element scrolled into viewport from above or below
// Courtesy http://stackoverflow.com/a/7557433/414749
-export const isInViewport = el => {
+export const isInViewport = (el, offset = {}) => {
const rect = el.getBoundingClientRect();
+ const { top, left } = offset;
return (
- rect.top >= 0 &&
- rect.left >= 0 &&
+ rect.top >= (top || 0) &&
+ rect.left >= (left || 0) &&
rect.bottom <= window.innerHeight &&
- rect.right <= window.innerWidth
+ parseInt(rect.right, 10) <= window.innerWidth
);
};
@@ -216,6 +221,22 @@ export const scrollToElement = element => {
};
/**
+ * Returns a function that can only be invoked once between
+ * each browser screen repaint.
+ * @param {Function} fn
+ */
+export const debounceByAnimationFrame = fn => {
+ let requestId;
+
+ return function debounced(...args) {
+ if (requestId) {
+ window.cancelAnimationFrame(requestId);
+ }
+ requestId = window.requestAnimationFrame(() => fn.apply(this, args));
+ };
+};
+
+/**
this will take in the `name` of the param you want to parse in the url
if the name does not exist this function will return `null`
otherwise it will return the value of the param key provided
@@ -425,34 +446,26 @@ export const historyPushState = newUrl => {
};
/**
- * Returns true for a String "true" and false otherwise.
- * This is the opposite of Boolean(...).toString()
+ * Returns true for a String value of "true" and false otherwise.
+ * This is the opposite of Boolean(...).toString().
+ * `parseBoolean` is idempotent.
*
* @param {String} value
* @returns {Boolean}
*/
-export const parseBoolean = value => value === 'true';
+export const parseBoolean = value => (value && value.toString()) === 'true';
/**
- * Converts permission provided as strings to booleans.
- *
- * @param {String} string
- * @returns {Boolean}
+ * @callback backOffCallback
+ * @param {Function} next
+ * @param {Function} stop
*/
-export const convertPermissionToBoolean = permission => {
- if (process.env.NODE_ENV !== 'production') {
- // eslint-disable-next-line no-console
- console.warn('convertPermissionToBoolean is deprecated! Please use parseBoolean instead.');
- }
-
- return parseBoolean(permission);
-};
/**
* Back Off exponential algorithm
* backOff :: (Function<next, stop>, Number) -> Promise<Any, Error>
*
- * @param {Function<next, stop>} fn function to be called
+ * @param {backOffCallback} fn function to be called
* @param {Number} timeout
* @return {Promise<Any, Error>}
* @example
@@ -602,10 +615,18 @@ export const spriteIcon = (icon, className = '') => {
/**
* This method takes in object with snake_case property names
- * and returns new object with camelCase property names
+ * and returns a new object with camelCase property names
*
* Reasoning for this method is to ensure consistent property
* naming conventions across JS code.
+ *
+ * This method also supports additional params in `options` object
+ *
+ * @param {Object} obj - Object to be converted.
+ * @param {Object} options - Object containing additional options.
+ * @param {boolean} options.deep - FLag to allow deep object converting
+ * @param {Array[]} dropKeys - List of properties to discard while building new object
+ * @param {Array[]} ignoreKeyNames - List of properties to leave intact (as snake_case) while building new object
*/
export const convertObjectPropsToCamelCase = (obj = {}, options = {}) => {
if (obj === null) {
@@ -613,12 +634,26 @@ export const convertObjectPropsToCamelCase = (obj = {}, options = {}) => {
}
const initial = Array.isArray(obj) ? [] : {};
+ const { deep = false, dropKeys = [], ignoreKeyNames = [] } = options;
return Object.keys(obj).reduce((acc, prop) => {
const result = acc;
const val = obj[prop];
- if (options.deep && (isObject(val) || Array.isArray(val))) {
+ // Drop properties from new object if
+ // there are any mentioned in options
+ if (dropKeys.indexOf(prop) > -1) {
+ return acc;
+ }
+
+ // Skip converting properties in new object
+ // if there are any mentioned in options
+ if (ignoreKeyNames.indexOf(prop) > -1) {
+ result[prop] = obj[prop];
+ return acc;
+ }
+
+ if (deep && (isObject(val) || Array.isArray(val))) {
result[convertToCamelCase(prop)] = convertObjectPropsToCamelCase(val, options);
} else {
result[convertToCamelCase(prop)] = obj[prop];
@@ -673,6 +708,14 @@ export const NavigationType = {
TYPE_RESERVED: 255,
};
+/**
+ * Returns the value of `gon.ee`
+ * Used to check if it's the EE codebase or the CE one.
+ *
+ * @returns Boolean
+ */
+export const isEE = () => window.gon && window.gon.ee;
+
window.gl = window.gl || {};
window.gl.utils = {
...(window.gl.utils || {}),
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index 59007d5950e..d3fe8f77bd4 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -8,6 +8,14 @@ import { languageCode, s__ } from '../../locale';
window.timeago = timeago;
/**
+ * This method allows you to create new Date instance from existing
+ * date instance without keeping the reference.
+ *
+ * @param {Date} date
+ */
+export const newDate = date => (date instanceof Date ? new Date(date.getTime()) : new Date());
+
+/**
* Returns i18n month names array.
* If `abbreviated` is provided, returns abbreviated
* name.
@@ -79,44 +87,67 @@ let timeagoInstance;
*/
export const getTimeago = () => {
if (!timeagoInstance) {
- const localeRemaining = (number, index) =>
- [
- [s__('Timeago|just now'), s__('Timeago|right now')],
- [s__('Timeago|%s seconds ago'), s__('Timeago|%s seconds remaining')],
- [s__('Timeago|1 minute ago'), s__('Timeago|1 minute remaining')],
- [s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')],
- [s__('Timeago|1 hour ago'), s__('Timeago|1 hour remaining')],
- [s__('Timeago|%s hours ago'), s__('Timeago|%s hours remaining')],
- [s__('Timeago|1 day ago'), s__('Timeago|1 day remaining')],
- [s__('Timeago|%s days ago'), s__('Timeago|%s days remaining')],
- [s__('Timeago|1 week ago'), s__('Timeago|1 week remaining')],
- [s__('Timeago|%s weeks ago'), s__('Timeago|%s weeks remaining')],
- [s__('Timeago|1 month ago'), s__('Timeago|1 month remaining')],
- [s__('Timeago|%s months ago'), s__('Timeago|%s months remaining')],
- [s__('Timeago|1 year ago'), s__('Timeago|1 year remaining')],
- [s__('Timeago|%s years ago'), s__('Timeago|%s years remaining')],
- ][index];
-
- const locale = (number, index) =>
- [
- [s__('Timeago|just now'), s__('Timeago|right now')],
- [s__('Timeago|%s seconds ago'), s__('Timeago|in %s seconds')],
- [s__('Timeago|1 minute ago'), s__('Timeago|in 1 minute')],
- [s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')],
- [s__('Timeago|1 hour ago'), s__('Timeago|in 1 hour')],
- [s__('Timeago|%s hours ago'), s__('Timeago|in %s hours')],
- [s__('Timeago|1 day ago'), s__('Timeago|in 1 day')],
- [s__('Timeago|%s days ago'), s__('Timeago|in %s days')],
- [s__('Timeago|1 week ago'), s__('Timeago|in 1 week')],
- [s__('Timeago|%s weeks ago'), s__('Timeago|in %s weeks')],
- [s__('Timeago|1 month ago'), s__('Timeago|in 1 month')],
- [s__('Timeago|%s months ago'), s__('Timeago|in %s months')],
- [s__('Timeago|1 year ago'), s__('Timeago|in 1 year')],
- [s__('Timeago|%s years ago'), s__('Timeago|in %s years')],
- ][index];
-
- timeago.register(timeagoLanguageCode, locale);
- timeago.register(`${timeagoLanguageCode}-remaining`, localeRemaining);
+ const memoizedLocaleRemaining = () => {
+ const cache = [];
+
+ const timeAgoLocaleRemaining = [
+ () => [s__('Timeago|just now'), s__('Timeago|right now')],
+ () => [s__('Timeago|%s seconds ago'), s__('Timeago|%s seconds remaining')],
+ () => [s__('Timeago|1 minute ago'), s__('Timeago|1 minute remaining')],
+ () => [s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')],
+ () => [s__('Timeago|1 hour ago'), s__('Timeago|1 hour remaining')],
+ () => [s__('Timeago|%s hours ago'), s__('Timeago|%s hours remaining')],
+ () => [s__('Timeago|1 day ago'), s__('Timeago|1 day remaining')],
+ () => [s__('Timeago|%s days ago'), s__('Timeago|%s days remaining')],
+ () => [s__('Timeago|1 week ago'), s__('Timeago|1 week remaining')],
+ () => [s__('Timeago|%s weeks ago'), s__('Timeago|%s weeks remaining')],
+ () => [s__('Timeago|1 month ago'), s__('Timeago|1 month remaining')],
+ () => [s__('Timeago|%s months ago'), s__('Timeago|%s months remaining')],
+ () => [s__('Timeago|1 year ago'), s__('Timeago|1 year remaining')],
+ () => [s__('Timeago|%s years ago'), s__('Timeago|%s years remaining')],
+ ];
+
+ return (number, index) => {
+ if (cache[index]) {
+ return cache[index];
+ }
+ cache[index] = timeAgoLocaleRemaining[index] && timeAgoLocaleRemaining[index]();
+ return cache[index];
+ };
+ };
+
+ const memoizedLocale = () => {
+ const cache = [];
+
+ const timeAgoLocale = [
+ () => [s__('Timeago|just now'), s__('Timeago|right now')],
+ () => [s__('Timeago|%s seconds ago'), s__('Timeago|in %s seconds')],
+ () => [s__('Timeago|1 minute ago'), s__('Timeago|in 1 minute')],
+ () => [s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')],
+ () => [s__('Timeago|1 hour ago'), s__('Timeago|in 1 hour')],
+ () => [s__('Timeago|%s hours ago'), s__('Timeago|in %s hours')],
+ () => [s__('Timeago|1 day ago'), s__('Timeago|in 1 day')],
+ () => [s__('Timeago|%s days ago'), s__('Timeago|in %s days')],
+ () => [s__('Timeago|1 week ago'), s__('Timeago|in 1 week')],
+ () => [s__('Timeago|%s weeks ago'), s__('Timeago|in %s weeks')],
+ () => [s__('Timeago|1 month ago'), s__('Timeago|in 1 month')],
+ () => [s__('Timeago|%s months ago'), s__('Timeago|in %s months')],
+ () => [s__('Timeago|1 year ago'), s__('Timeago|in 1 year')],
+ () => [s__('Timeago|%s years ago'), s__('Timeago|in %s years')],
+ ];
+
+ return (number, index) => {
+ if (cache[index]) {
+ return cache[index];
+ }
+ cache[index] = timeAgoLocale[index] && timeAgoLocale[index]();
+ return cache[index];
+ };
+ };
+
+ timeago.register(timeagoLanguageCode, memoizedLocale());
+ timeago.register(`${timeagoLanguageCode}-remaining`, memoizedLocaleRemaining());
+
timeagoInstance = timeago();
}
@@ -124,35 +155,28 @@ export const getTimeago = () => {
};
/**
- * For the given element, renders a timeago instance.
- * @param {jQuery} $els
- */
-export const renderTimeago = $els => {
- const timeagoEls = $els || document.querySelectorAll('.js-timeago-render');
-
- // timeago.js sets timeouts internally for each timeago value to be updated in real time
- getTimeago().render(timeagoEls, timeagoLanguageCode);
-};
-
-/**
* For the given elements, sets a tooltip with a formatted date.
- * @param {jQuery}
+ * @param {JQuery} $timeagoEls
* @param {Boolean} setTimeago
*/
export const localTimeAgo = ($timeagoEls, setTimeago = true) => {
- $timeagoEls.each((i, el) => {
- if (setTimeago) {
+ getTimeago().render($timeagoEls, timeagoLanguageCode);
+
+ if (!setTimeago) {
+ return;
+ }
+
+ function addTimeAgoTooltip() {
+ $timeagoEls.each((i, el) => {
// Recreate with custom template
$(el).tooltip({
template:
'<div class="tooltip local-timeago" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',
});
- }
-
- el.classList.add('js-timeago-render');
- });
+ });
+ }
- renderTimeago($timeagoEls);
+ requestIdleCallback(addTimeAgoTooltip);
};
/**
@@ -321,23 +345,35 @@ export const getSundays = date => {
/**
* Returns list of Dates representing a timeframe of months from startDate and length
+ * This method also supports going back in time when `length` is negative number
*
- * @param {Date} startDate
+ * @param {Date} initialStartDate
* @param {Number} length
*/
-export const getTimeframeWindowFrom = (startDate, length) => {
- if (!(startDate instanceof Date) || !length) {
+export const getTimeframeWindowFrom = (initialStartDate, length) => {
+ if (!(initialStartDate instanceof Date) || !length) {
return [];
}
+ const startDate = newDate(initialStartDate);
+ const moveMonthBy = length > 0 ? 1 : -1;
+
+ startDate.setDate(1);
+ startDate.setHours(0, 0, 0, 0);
+
// Iterate and set date for the size of length
// and push date reference to timeframe list
- const timeframe = new Array(length)
- .fill()
- .map((val, i) => new Date(startDate.getFullYear(), startDate.getMonth() + i, 1));
+ const timeframe = new Array(Math.abs(length)).fill().map(() => {
+ const currentMonth = startDate.getTime();
+ startDate.setMonth(startDate.getMonth() + moveMonthBy);
+ return new Date(currentMonth);
+ });
// Change date of last timeframe item to last date of the month
- timeframe[length - 1].setDate(totalDaysInMonth(timeframe[length - 1]));
+ // when length is positive
+ if (length > 0) {
+ timeframe[timeframe.length - 1].setDate(totalDaysInMonth(timeframe[timeframe.length - 1]));
+ }
return timeframe;
};
diff --git a/app/assets/javascripts/lib/utils/file_upload.js b/app/assets/javascripts/lib/utils/file_upload.js
index b41ffb44971..82ee83e4348 100644
--- a/app/assets/javascripts/lib/utils/file_upload.js
+++ b/app/assets/javascripts/lib/utils/file_upload.js
@@ -1,6 +1,9 @@
export default (buttonSelector, fileSelector) => {
const btn = document.querySelector(buttonSelector);
const fileInput = document.querySelector(fileSelector);
+
+ if (!btn || !fileInput) return;
+
const form = btn.closest('form');
btn.addEventListener('click', () => {
diff --git a/app/assets/javascripts/lib/utils/grammar.js b/app/assets/javascripts/lib/utils/grammar.js
new file mode 100644
index 00000000000..18f9e2ed846
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/grammar.js
@@ -0,0 +1,40 @@
+import { sprintf, s__ } from '~/locale';
+
+/**
+ * Combines each given item into a noun series sentence fragment. It does this
+ * in a way that supports i18n by giving context and punctuation to the locale
+ * functions.
+ *
+ * **Examples:**
+ *
+ * - `["A", "B"] => "A and B"`
+ * - `["A", "B", "C"] => "A, B, and C"`
+ *
+ * **Why only nouns?**
+ *
+ * Some languages need a bit more context to translate other series.
+ *
+ * @param {String[]} items
+ */
+export const toNounSeriesText = items => {
+ if (items.length === 0) {
+ return '';
+ } else if (items.length === 1) {
+ return items[0];
+ } else if (items.length === 2) {
+ return sprintf(s__('nounSeries|%{firstItem} and %{lastItem}'), {
+ firstItem: items[0],
+ lastItem: items[1],
+ });
+ }
+
+ return items.reduce((item, nextItem, idx) =>
+ idx === items.length - 1
+ ? sprintf(s__('nounSeries|%{item}, and %{lastItem}'), { item, lastItem: nextItem })
+ : sprintf(s__('nounSeries|%{item}, %{nextItem}'), { item, nextItem }),
+ );
+};
+
+export default {
+ toNounSeriesText,
+};
diff --git a/app/assets/javascripts/lib/utils/http_status.js b/app/assets/javascripts/lib/utils/http_status.js
index 14c02218990..37ad1676f7a 100644
--- a/app/assets/javascripts/lib/utils/http_status.js
+++ b/app/assets/javascripts/lib/utils/http_status.js
@@ -16,6 +16,7 @@ const httpStatusCodes = {
IM_USED: 226,
MULTIPLE_CHOICES: 300,
BAD_REQUEST: 400,
+ UNAUTHORIZED: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
UNPROCESSABLE_ENTITY: 422,
diff --git a/app/assets/javascripts/lib/utils/icon_utils.js b/app/assets/javascripts/lib/utils/icon_utils.js
new file mode 100644
index 00000000000..7b8dd9bbef7
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/icon_utils.js
@@ -0,0 +1,18 @@
+/* eslint-disable import/prefer-default-export */
+
+import axios from '~/lib/utils/axios_utils';
+
+/**
+ * Retrieve SVG icon path content from gitlab/svg sprite icons
+ * @param {String} name
+ */
+export const getSvgIconPathContent = name =>
+ axios
+ .get(gon.sprite_icons)
+ .then(({ data: svgs }) =>
+ new DOMParser()
+ .parseFromString(svgs, 'text/xml')
+ .querySelector(`#${name} path`)
+ .getAttribute('d'),
+ )
+ .catch(() => null);
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index 2ccc51c35f7..19c4de6083d 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -80,3 +80,22 @@ export function numberToHumanSize(size) {
}
return `${bytesToGiB(size).toFixed(2)} GiB`;
}
+
+/**
+ * A simple method that returns the value of a + b
+ * It seems unessesary, but when combined with a reducer it
+ * adds up all the values in an array.
+ *
+ * e.g. `[1, 2, 3, 4, 5].reduce(sum) // => 15`
+ *
+ * @param {Float} a
+ * @param {Float} b
+ * @example
+ * // return 15
+ * [1, 2, 3, 4, 5].reduce(sum);
+ *
+ * // returns 6
+ * Object.values([{a: 1, b: 2, c: 3].reduce(sum);
+ * @returns {Float} The summed value
+ */
+export const sum = (a = 0, b = 0) => a + b;
diff --git a/app/assets/javascripts/lib/utils/poll.js b/app/assets/javascripts/lib/utils/poll.js
index 198711cf427..a900ff34bf5 100644
--- a/app/assets/javascripts/lib/utils/poll.js
+++ b/app/assets/javascripts/lib/utils/poll.js
@@ -63,6 +63,10 @@ export default class Poll {
const headers = normalizeHeaders(response.headers);
const pollInterval = parseInt(headers[this.intervalHeader], 10);
if (pollInterval > 0 && successCodes.indexOf(response.status) !== -1 && this.canPoll) {
+ if (this.timeoutID) {
+ clearTimeout(this.timeoutID);
+ }
+
this.timeoutID = setTimeout(() => {
this.makeRequest();
}, pollInterval);
@@ -101,15 +105,25 @@ export default class Poll {
}
/**
- * Restarts polling after it has been stoped
+ * Enables polling after it has been stopped
*/
- restart(options) {
- // update data
+ enable(options) {
if (options && options.data) {
this.options.data = options.data;
}
this.canPoll = true;
+
+ if (options && options.response) {
+ this.checkConditions(options.response);
+ }
+ }
+
+ /**
+ * Restarts polling after it has been stopped and makes a request
+ */
+ restart(options) {
+ this.enable(options);
this.makeRequest();
}
}
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 1254ec798a6..84a617acb42 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -8,6 +8,10 @@ function selectedText(text, textarea) {
return text.substring(textarea.selectionStart, textarea.selectionEnd);
}
+function addBlockTags(blockTag, selected) {
+ return `${blockTag}\n${selected}\n${blockTag}`;
+}
+
function lineBefore(text, textarea) {
var split;
split = text
@@ -24,19 +28,45 @@ function lineAfter(text, textarea) {
.split('\n')[0];
}
+function editorBlockTagText(text, blockTag, selected, editor) {
+ const lines = text.split('\n');
+ const selectionRange = editor.getSelectionRange();
+ const shouldRemoveBlock =
+ lines[selectionRange.start.row - 1] === blockTag &&
+ lines[selectionRange.end.row + 1] === blockTag;
+
+ if (shouldRemoveBlock) {
+ if (blockTag !== null) {
+ // ace is globally defined
+ // eslint-disable-next-line no-undef
+ const { Range } = ace.require('ace/range');
+ const lastLine = lines[selectionRange.end.row + 1];
+ const rangeWithBlockTags = new Range(
+ lines[selectionRange.start.row - 1],
+ 0,
+ selectionRange.end.row + 1,
+ lastLine.length,
+ );
+ editor.getSelection().setSelectionRange(rangeWithBlockTags);
+ }
+ return selected;
+ }
+ return addBlockTags(blockTag, selected);
+}
+
function blockTagText(text, textArea, blockTag, selected) {
- const before = lineBefore(text, textArea);
- const after = lineAfter(text, textArea);
- if (before === blockTag && after === blockTag) {
+ const shouldRemoveBlock =
+ lineBefore(text, textArea) === blockTag && lineAfter(text, textArea) === blockTag;
+
+ if (shouldRemoveBlock) {
// To remove the block tag we have to select the line before & after
if (blockTag != null) {
textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1);
textArea.selectionEnd = textArea.selectionEnd + (blockTag.length + 1);
}
return selected;
- } else {
- return blockTag + '\n' + selected + '\n' + blockTag;
}
+ return addBlockTags(blockTag, selected);
}
function moveCursor({
@@ -46,33 +76,48 @@ function moveCursor({
positionBetweenTags,
removedLastNewLine,
select,
+ editor,
+ editorSelectionStart,
+ editorSelectionEnd,
}) {
var pos;
- if (!textArea.setSelectionRange) {
+ if (textArea && !textArea.setSelectionRange) {
return;
}
if (select && select.length > 0) {
- // calculate the part of the text to be selected
- const startPosition = textArea.selectionStart - (tag.length - tag.indexOf(select));
- const endPosition = startPosition + select.length;
- return textArea.setSelectionRange(startPosition, endPosition);
- }
- if (textArea.selectionStart === textArea.selectionEnd) {
- if (positionBetweenTags) {
- pos = textArea.selectionStart - tag.length;
- } else {
- pos = textArea.selectionStart;
+ if (textArea) {
+ // calculate the part of the text to be selected
+ const startPosition = textArea.selectionStart - (tag.length - tag.indexOf(select));
+ const endPosition = startPosition + select.length;
+ return textArea.setSelectionRange(startPosition, endPosition);
+ } else if (editor) {
+ editor.navigateLeft(tag.length - tag.indexOf(select));
+ editor.getSelection().selectAWord();
+ return;
}
+ }
+ if (textArea) {
+ if (textArea.selectionStart === textArea.selectionEnd) {
+ if (positionBetweenTags) {
+ pos = textArea.selectionStart - tag.length;
+ } else {
+ pos = textArea.selectionStart;
+ }
- if (removedLastNewLine) {
- pos -= 1;
- }
+ if (removedLastNewLine) {
+ pos -= 1;
+ }
- if (cursorOffset) {
- pos -= cursorOffset;
- }
+ if (cursorOffset) {
+ pos -= cursorOffset;
+ }
- return textArea.setSelectionRange(pos, pos);
+ return textArea.setSelectionRange(pos, pos);
+ }
+ } else if (editor && editorSelectionStart.row === editorSelectionEnd.row) {
+ if (positionBetweenTags) {
+ editor.navigateLeft(tag.length);
+ }
}
}
@@ -85,6 +130,7 @@ export function insertMarkdownText({
selected = '',
wrap,
select,
+ editor,
}) {
var textToInsert,
selectedSplit,
@@ -92,11 +138,20 @@ export function insertMarkdownText({
removedLastNewLine,
removedFirstNewLine,
currentLineEmpty,
- lastNewLine;
+ lastNewLine,
+ editorSelectionStart,
+ editorSelectionEnd;
removedLastNewLine = false;
removedFirstNewLine = false;
currentLineEmpty = false;
+ if (editor) {
+ const selectionRange = editor.getSelectionRange();
+
+ editorSelectionStart = selectionRange.start;
+ editorSelectionEnd = selectionRange.end;
+ }
+
// check for link pattern and selected text is an URL
// if so fill in the url part instead of the text part of the pattern.
if (tag === LINK_TAG_PATTERN) {
@@ -119,14 +174,27 @@ export function insertMarkdownText({
}
// Remove the last newline
- if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) {
- removedLastNewLine = true;
- selected = selected.replace(/\n$/, '');
+ if (textArea) {
+ if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) {
+ removedLastNewLine = true;
+ selected = selected.replace(/\n$/, '');
+ }
+ } else if (editor) {
+ if (editorSelectionStart.row !== editorSelectionEnd.row) {
+ removedLastNewLine = true;
+ selected = selected.replace(/\n$/, '');
+ }
}
selectedSplit = selected.split('\n');
- if (!wrap) {
+ if (editor && !wrap) {
+ lastNewLine = editor.getValue().split('\n')[editorSelectionStart.row];
+
+ if (/^\s*$/.test(lastNewLine)) {
+ currentLineEmpty = true;
+ }
+ } else if (textArea && !wrap) {
lastNewLine = textArea.value.substr(0, textArea.selectionStart).lastIndexOf('\n');
// Check whether the current line is empty or consists only of spaces(=handle as empty)
@@ -135,13 +203,19 @@ export function insertMarkdownText({
}
}
- startChar = !wrap && !currentLineEmpty && textArea.selectionStart > 0 ? '\n' : '';
+ const isBeginning =
+ (textArea && textArea.selectionStart === 0) ||
+ (editor && editorSelectionStart.column === 0 && editorSelectionStart.row === 0);
+
+ startChar = !wrap && !currentLineEmpty && !isBeginning ? '\n' : '';
const textPlaceholder = '{text}';
if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) {
if (blockTag != null && blockTag !== '') {
- textToInsert = blockTagText(text, textArea, blockTag, selected);
+ textToInsert = editor
+ ? editorBlockTagText(text, blockTag, selected, editor)
+ : blockTagText(text, textArea, blockTag, selected);
} else {
textToInsert = selectedSplit
.map(function(val) {
@@ -170,7 +244,11 @@ export function insertMarkdownText({
textToInsert += '\n';
}
- insertText(textArea, textToInsert);
+ if (editor) {
+ editor.insert(textToInsert);
+ } else {
+ insertText(textArea, textToInsert);
+ }
return moveCursor({
textArea,
tag: tag.replace(textPlaceholder, selected),
@@ -178,6 +256,9 @@ export function insertMarkdownText({
positionBetweenTags: wrap && selected.length === 0,
removedLastNewLine,
select,
+ editor,
+ editorSelectionStart,
+ editorSelectionEnd,
});
}
@@ -217,6 +298,25 @@ export function addMarkdownListeners(form) {
});
}
+export function addEditorMarkdownListeners(editor) {
+ $('.js-md')
+ .off('click')
+ .on('click', function(e) {
+ const { mdTag, mdBlock, mdPrepend, mdSelect } = $(e.currentTarget).data();
+
+ insertMarkdownText({
+ tag: mdTag,
+ blockTag: mdBlock,
+ wrap: !mdPrepend,
+ select: mdSelect,
+ selected: editor.getSelectedText(),
+ text: editor.getValue(),
+ editor,
+ });
+ editor.focus();
+ });
+}
+
export function removeMarkdownListeners(form) {
return $('.js-md', form).off('click');
}
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js
index 7cc7cd6d20e..c49b1bb5a2f 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js
+++ b/app/assets/javascripts/lib/utils/text_utility.js
@@ -72,6 +72,29 @@ export const truncate = (string, maxLength) => `${string.substr(0, maxLength - 3
*/
export const truncateSha = sha => sha.substr(0, 8);
+const ELLIPSIS_CHAR = '…';
+export const truncatePathMiddleToLength = (text, maxWidth) => {
+ let returnText = text;
+ let ellipsisCount = 0;
+
+ while (returnText.length >= maxWidth) {
+ const textSplit = returnText.split('/').filter(s => s !== ELLIPSIS_CHAR);
+ const middleIndex = Math.floor(textSplit.length / 2);
+
+ returnText = textSplit
+ .slice(0, middleIndex)
+ .concat(
+ new Array(ellipsisCount + 1).fill().map(() => ELLIPSIS_CHAR),
+ textSplit.slice(middleIndex + 1),
+ )
+ .join('/');
+
+ ellipsisCount += 1;
+ }
+
+ return returnText;
+};
+
/**
* Capitalizes first character
*
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index 9850f7ce782..4ba84589705 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -42,22 +42,35 @@ export function mergeUrlParams(params, url) {
return `${urlparts[1]}?${query}${urlparts[3]}`;
}
-export function removeParamQueryString(url, param) {
- const decodedUrl = decodeURIComponent(url);
- const urlVariables = decodedUrl.split('&');
-
- return urlVariables.filter(variable => variable.indexOf(param) === -1).join('&');
-}
-
-export function removeParams(params, source = window.location.href) {
- const url = document.createElement('a');
- url.href = source;
+/**
+ * Removes specified query params from the url by returning a new url string that no longer
+ * includes the param/value pair. If no url is provided, `window.location.href` is used as
+ * the default value.
+ *
+ * @param {string[]} params - the query param names to remove
+ * @param {string} [url=windowLocation().href] - url from which the query param will be removed
+ * @returns {string} A copy of the original url but without the query param
+ */
+export function removeParams(params, url = window.location.href) {
+ const [rootAndQuery, fragment] = url.split('#');
+ const [root, query] = rootAndQuery.split('?');
+
+ if (!query) {
+ return url;
+ }
- params.forEach(param => {
- url.search = removeParamQueryString(url.search, param);
- });
+ const encodedParams = params.map(param => encodeURIComponent(param));
+ const updatedQuery = query
+ .split('&')
+ .filter(paramPair => {
+ const [foundParam] = paramPair.split('=');
+ return encodedParams.indexOf(foundParam) < 0;
+ })
+ .join('&');
- return url.href;
+ const writableQuery = updatedQuery.length > 0 ? `?${updatedQuery}` : '';
+ const writableFragment = fragment ? `#${fragment}` : '';
+ return `${root}${writableQuery}${writableFragment}`;
}
export function getLocationHash(url = window.location.href) {
@@ -66,6 +79,20 @@ export function getLocationHash(url = window.location.href) {
return hashIndex === -1 ? null : url.substring(hashIndex + 1);
}
+/**
+ * Apply the fragment to the given url by returning a new url string that includes
+ * the fragment. If the given url already contains a fragment, the original fragment
+ * will be removed.
+ *
+ * @param {string} url - url to which the fragment will be applied
+ * @param {string} fragment - fragment to append
+ */
+export const setUrlFragment = (url, fragment) => {
+ const [rootUrl] = url.split('#');
+ const encodedFragment = encodeURIComponent(fragment.replace(/^#/, ''));
+ return `${rootUrl}#${encodedFragment}`;
+};
+
export function visitUrl(url, external = false) {
if (external) {
// Simulate `target="blank" rel="noopener noreferrer"`
diff --git a/app/assets/javascripts/lib/utils/webpack.js b/app/assets/javascripts/lib/utils/webpack.js
new file mode 100644
index 00000000000..308ad9784e4
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/webpack.js
@@ -0,0 +1,10 @@
+// tell webpack to load assets from origin so that web workers don't break
+// eslint-disable-next-line import/prefer-default-export
+export function resetServiceWorkersPublicPath() {
+ // __webpack_public_path__ is a global variable that can be used to adjust
+ // the webpack publicPath setting at runtime.
+ // see: https://webpack.js.org/guides/public-path/
+ const relativeRootPath = (gon && gon.relative_url_root) || '';
+ const webpackAssetPath = `${relativeRootPath}/assets/webpack/`;
+ __webpack_public_path__ = webpackAssetPath; // eslint-disable-line camelcase
+}
diff --git a/app/assets/javascripts/locale/sprintf.js b/app/assets/javascripts/locale/sprintf.js
index 5246c49842e..68b64a3a16a 100644
--- a/app/assets/javascripts/locale/sprintf.js
+++ b/app/assets/javascripts/locale/sprintf.js
@@ -4,8 +4,8 @@ import _ from 'underscore';
Very limited implementation of sprintf supporting only named parameters.
@param input (translated) text with parameters (e.g. '%{num_users} users use us')
- @param parameters object mapping parameter names to values (e.g. { num_users: 5 })
- @param escapeParameters whether parameter values should be escaped (see http://underscorejs.org/#escape)
+ @param {Object} parameters object mapping parameter names to values (e.g. { num_users: 5 })
+ @param {Boolean} escapeParameters whether parameter values should be escaped (see http://underscorejs.org/#escape)
@returns {String} the text with parameters replaces (e.g. '5 users use us')
@see https://ruby-doc.org/core-2.3.3/Kernel.html#method-i-sprintf
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index c866e8d180a..1b722c0505a 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -66,15 +66,11 @@ gl.lazyLoader = new LazyLoader({
observerNode: '#content-body',
});
-document.addEventListener('DOMContentLoaded', () => {
+// Put all initialisations here that can also wait after everything is rendered and ready
+function deferredInitialisation() {
const $body = $('body');
- const $document = $(document);
- const $window = $(window);
- const $sidebarGutterToggle = $('.js-sidebar-toggle');
- let bootstrapBreakpoint = bp.getBreakpointSize();
initBreadcrumbs();
- initLayoutNav();
initImporterStatus();
initTodoToggle();
initLogoAnimation();
@@ -82,35 +78,6 @@ document.addEventListener('DOMContentLoaded', () => {
initUserPopovers();
if (document.querySelector('.search')) initSearchAutocomplete();
- if (document.querySelector('#js-peek')) initPerformanceBar({ container: '#js-peek' });
-
- // Set the default path for all cookies to GitLab's root directory
- Cookies.defaults.path = gon.relative_url_root || '/';
-
- // `hashchange` is not triggered when link target is already in window.location
- $body.on('click', 'a[href^="#"]', function clickHashLinkCallback() {
- const href = this.getAttribute('href');
- if (href.substr(1) === getLocationHash()) {
- setTimeout(handleLocationHash, 1);
- }
- });
-
- if (bootstrapBreakpoint === 'xs') {
- const $rightSidebar = $('aside.right-sidebar, .layout-page');
-
- $rightSidebar.removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
- }
-
- // prevent default action for disabled buttons
- $('.btn').click(function clickDisabledButtonCallback(e) {
- if ($(this).hasClass('disabled')) {
- e.preventDefault();
- e.stopImmediatePropagation();
- return false;
- }
-
- return true;
- });
addSelectOnFocusBehaviour('.js-select-on-focus');
@@ -132,27 +99,30 @@ document.addEventListener('DOMContentLoaded', () => {
});
// Initialize select2 selects
- $('select.select2').select2({
- width: 'resolve',
- dropdownAutoWidth: true,
- });
-
- // Close select2 on escape
- $('.js-select2').on('select2-close', () => {
- setTimeout(() => {
- $('.select2-container-active').removeClass('select2-container-active');
- $(':focus').blur();
- }, 1);
- });
+ if ($('select.select2').length) {
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ $('select.select2').select2({
+ width: 'resolve',
+ dropdownAutoWidth: true,
+ });
+
+ // Close select2 on escape
+ $('.js-select2').on('select2-close', () => {
+ setTimeout(() => {
+ $('.select2-container-active').removeClass('select2-container-active');
+ $(':focus').blur();
+ }, 1);
+ });
+ })
+ .catch(() => {});
+ }
// Initialize tooltips
$body.tooltip({
selector: '.has-tooltip, [data-toggle="tooltip"]',
trigger: 'hover',
boundary: 'viewport',
- placement(tip, el) {
- return $(el).data('placement') || 'bottom';
- },
});
// Initialize popovers
@@ -164,6 +134,50 @@ document.addEventListener('DOMContentLoaded', () => {
viewport: '.layout-page',
});
+ loadAwardsHandler();
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ const $body = $('body');
+ const $document = $(document);
+ const $window = $(window);
+ const $sidebarGutterToggle = $('.js-sidebar-toggle');
+ let bootstrapBreakpoint = bp.getBreakpointSize();
+
+ if (document.querySelector('#js-peek')) initPerformanceBar({ container: '#js-peek' });
+
+ initLayoutNav();
+
+ // Set the default path for all cookies to GitLab's root directory
+ Cookies.defaults.path = gon.relative_url_root || '/';
+
+ // `hashchange` is not triggered when link target is already in window.location
+ $body.on('click', 'a[href^="#"]', function clickHashLinkCallback() {
+ const href = this.getAttribute('href');
+ if (href.substr(1) === getLocationHash()) {
+ setTimeout(handleLocationHash, 1);
+ }
+ });
+
+ if (bootstrapBreakpoint === 'xs') {
+ const $rightSidebar = $('aside.right-sidebar, .layout-page');
+
+ $rightSidebar.removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
+ }
+
+ // prevent default action for disabled buttons
+ $('.btn').click(function clickDisabledButtonCallback(e) {
+ if ($(this).hasClass('disabled')) {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ return false;
+ }
+
+ return true;
+ });
+
+ localTimeAgo($('abbr.timeago, .js-timeago'), true);
+
// Form submitter
$('.trigger-submit').on('change', function triggerSubmitCallback() {
$(this)
@@ -171,8 +185,6 @@ document.addEventListener('DOMContentLoaded', () => {
.submit();
});
- localTimeAgo($('abbr.timeago, .js-timeago'), true);
-
// Disable form buttons while a form is submitting
$body.on('ajax:complete, ajax:beforeSend, submit', 'form', function ajaxCompleteCallback(e) {
const $buttons = $('[type="submit"], .js-disable-on-submit', this);
@@ -195,6 +207,10 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
+ $('.navbar-toggler').on('click', () => {
+ $('.header-content').toggleClass('menu-expanded');
+ });
+
// Commit show suppressed diff
$document.on('click', '.diff-content .js-show-suppressed-diff', function showDiffCallback() {
const $container = $(this).parent();
@@ -202,10 +218,6 @@ document.addEventListener('DOMContentLoaded', () => {
$container.remove();
});
- $('.navbar-toggler').on('click', () => {
- $('.header-content').toggleClass('menu-expanded');
- });
-
// Show/hide comments on diff
$body.on('click', '.js-toggle-diff-comments', function toggleDiffCommentsCallback(e) {
const $this = $(this);
@@ -250,8 +262,6 @@ document.addEventListener('DOMContentLoaded', () => {
$window.on('resize.app', fitSidebarForSize);
- loadAwardsHandler();
-
$('form.filter-form').on('submit', function filterFormSubmitCallback(event) {
const link = document.createElement('a');
link.href = this.action;
@@ -274,4 +284,6 @@ document.addEventListener('DOMContentLoaded', () => {
// initialize field errors
$('.gl-show-field-errors').each((i, form) => new GlFieldErrors(form));
+
+ requestIdleCallback(deferredInitialisation);
});
diff --git a/app/assets/javascripts/member_expiration_date.js b/app/assets/javascripts/member_expiration_date.js
index 0beedcacf33..0dabb28ea66 100644
--- a/app/assets/javascripts/member_expiration_date.js
+++ b/app/assets/javascripts/member_expiration_date.js
@@ -33,6 +33,7 @@ export default function memberExpirationDate(selector = '.js-access-expiration-d
toggleClearInput.call($input);
},
+ firstDay: gon.first_day_of_week,
});
calendar.setDate(parsePikadayDate($input.val()));
diff --git a/app/assets/javascripts/members.js b/app/assets/javascripts/members.js
index bd263c75a3d..af2697444f2 100644
--- a/app/assets/javascripts/members.js
+++ b/app/assets/javascripts/members.js
@@ -16,25 +16,33 @@ export default class Members {
gl.utils.disableButtonIfEmptyField('#user_ids', 'input[name=commit]', 'change');
}
+ dropdownClicked(options) {
+ this.formSubmit(null, options.$el);
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ dropdownToggleLabel(selected, $el) {
+ return $el.text();
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ dropdownIsSelectable(selected, $el) {
+ return !$el.hasClass('is-active');
+ }
+
initGLDropdown() {
$('.js-member-permissions-dropdown').each((i, btn) => {
const $btn = $(btn);
$btn.glDropdown({
selectable: true,
- isSelectable(selected, $el) {
- return !$el.hasClass('is-active');
- },
+ isSelectable: (selected, $el) => this.dropdownIsSelectable(selected, $el),
fieldName: $btn.data('fieldName'),
id(selected, $el) {
return $el.data('id');
},
- toggleLabel(selected, $el) {
- return $el.text();
- },
- clicked: options => {
- this.formSubmit(null, options.$el);
- },
+ toggleLabel: (selected, $el) => this.dropdownToggleLabel(selected, $el, $btn),
+ clicked: options => this.dropdownClicked(options),
});
});
}
@@ -55,6 +63,7 @@ export default class Members {
$toggle.enable();
$dateInput.enable();
}
+
// eslint-disable-next-line class-methods-use-this
getMemberListItems($el) {
const $memberListItem = $el.is('.member') ? $el : $(`#${$el.data('elId')}`);
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index 0deae478deb..3b42a154af8 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -2,6 +2,7 @@
import $ from 'jquery';
import { __ } from '~/locale';
+import createFlash from '~/flash';
import TaskList from './task_list';
import MergeRequestTabs from './merge_request_tabs';
import IssuablesHelper from './helpers/issuables_helper';
@@ -35,10 +36,18 @@ function MergeRequest(opts) {
dataType: 'merge_request',
fieldName: 'description',
selector: '.detail-page-description',
+ lockVersion: this.$el.data('lockVersion'),
onSuccess: result => {
document.querySelector('#task_status').innerText = result.task_status;
document.querySelector('#task_status_short').innerText = result.task_status_short;
},
+ onError: () => {
+ createFlash(
+ __(
+ 'Someone edited this merge request at the same time you did. Please refresh the page to see changes.',
+ ),
+ );
+ },
});
}
}
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index b0dc5697018..2f15da42271 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -428,7 +428,7 @@ export default class MergeRequestTabs {
}
diffViewType() {
- return $('.inline-parallel-buttons button.active').data('viewType');
+ return $('.js-diff-view-buttons button.active').data('viewType');
}
isDiffAction(action) {
diff --git a/app/assets/javascripts/monitoring/components/charts/area.vue b/app/assets/javascripts/monitoring/components/charts/area.vue
index 12224e36ba2..41783d311ef 100644
--- a/app/assets/javascripts/monitoring/components/charts/area.vue
+++ b/app/assets/javascripts/monitoring/components/charts/area.vue
@@ -1,18 +1,25 @@
<script>
-import { GlAreaChart } from '@gitlab/ui';
+import { GlAreaChart } from '@gitlab/ui/dist/charts';
import dateFormat from 'dateformat';
+import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
+import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
+import Icon from '~/vue_shared/components/icon.vue';
+import { chartHeight, graphTypes, lineTypes } from '../../constants';
+
+let debouncedResize;
export default {
components: {
GlAreaChart,
+ Icon,
},
+ inheritAttrs: false,
props: {
graphData: {
type: Object,
required: true,
validator(data) {
return (
- data.queries &&
Array.isArray(data.queries) &&
data.queries.filter(query => {
if (Array.isArray(query.result)) {
@@ -25,19 +32,63 @@ export default {
);
},
},
+ containerWidth: {
+ type: Number,
+ required: true,
+ },
+ deploymentData: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ alertData: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ },
+ data() {
+ return {
+ tooltip: {
+ title: '',
+ content: [],
+ isDeployment: false,
+ sha: '',
+ },
+ width: 0,
+ height: chartHeight,
+ svgs: {},
+ primaryColor: null,
+ };
},
computed: {
chartData() {
- return this.graphData.queries.reduce((accumulator, query) => {
- const xLabel = `${query.unit}`;
- accumulator[xLabel] = {};
- query.result.forEach(res =>
- res.values.forEach(v => {
- accumulator[xLabel][v.time.toISOString()] = v.value;
- }),
- );
- return accumulator;
- }, {});
+ return this.graphData.queries.map(query => {
+ const { appearance } = query;
+ const lineType =
+ appearance && appearance.line && appearance.line.type
+ ? appearance.line.type
+ : lineTypes.default;
+ const lineColor = lineType === lineTypes.threshold ? this.primaryColor : undefined;
+
+ return {
+ name: this.formatLegendLabel(query),
+ data: this.concatenateResults(query.result),
+ lineStyle: {
+ type: lineType,
+ color: lineColor,
+ },
+ itemStyle: {
+ color: lineColor,
+ },
+ areaStyle: {
+ opacity:
+ appearance && appearance.area && typeof appearance.area.opacity === 'number'
+ ? appearance.area.opacity
+ : undefined,
+ },
+ };
+ });
},
chartOptions() {
return {
@@ -45,53 +96,172 @@ export default {
name: 'Time',
type: 'time',
axisLabel: {
- formatter: date => dateFormat(date, 'h:MMtt'),
+ formatter: date => dateFormat(date, 'h:MM TT'),
},
- nameTextStyle: {
- padding: [18, 0, 0, 0],
+ axisPointer: {
+ snap: true,
},
},
yAxis: {
- name: this.graphData.y_label,
+ name: this.yAxisLabel,
axisLabel: {
formatter: value => value.toFixed(3),
},
- nameTextStyle: {
- padding: [0, 0, 36, 0],
- },
},
- legend: {
- formatter: this.xAxisLabel,
+ series: this.scatterSeries,
+ dataZoom: this.dataZoomConfig,
+ };
+ },
+ dataZoomConfig() {
+ const handleIcon = this.svgs['scroll-handle'];
+
+ return handleIcon ? { handleIcon } : {};
+ },
+ earliestDatapoint() {
+ return this.chartData.reduce((acc, series) => {
+ const [[timestamp]] = series.data.sort(([a], [b]) => {
+ if (a < b) {
+ return -1;
+ }
+ return a > b ? 1 : 0;
+ });
+
+ return timestamp < acc || acc === null ? timestamp : acc;
+ }, null);
+ },
+ recentDeployments() {
+ return this.deploymentData.reduce((acc, deployment) => {
+ if (deployment.created_at >= this.earliestDatapoint) {
+ acc.push({
+ id: deployment.id,
+ createdAt: deployment.created_at,
+ sha: deployment.sha,
+ commitUrl: `${this.projectPath}/commit/${deployment.sha}`,
+ tag: deployment.tag,
+ tagUrl: deployment.tag ? `${this.tagsPath}/${deployment.ref.name}` : null,
+ ref: deployment.ref.name,
+ showDeploymentFlag: false,
+ });
+ }
+
+ return acc;
+ }, []);
+ },
+ scatterSeries() {
+ return {
+ type: graphTypes.deploymentData,
+ data: this.recentDeployments.map(deployment => [deployment.createdAt, 0]),
+ symbol: this.svgs.rocket,
+ symbolSize: 14,
+ itemStyle: {
+ color: this.primaryColor,
},
};
},
- xAxisLabel() {
- return this.graphData.queries.map(query => query.label).join(', ');
+ yAxisLabel() {
+ return `${this.graphData.y_label}`;
},
},
+ watch: {
+ containerWidth: 'onResize',
+ },
+ beforeDestroy() {
+ window.removeEventListener('resize', debouncedResize);
+ },
+ created() {
+ debouncedResize = debounceByAnimationFrame(this.onResize);
+ window.addEventListener('resize', debouncedResize);
+ this.setSvg('rocket');
+ this.setSvg('scroll-handle');
+ },
methods: {
+ concatenateResults(results) {
+ return results.reduce((acc, result) => acc.concat(result.values), []);
+ },
+ formatLegendLabel(query) {
+ return `${query.label}`;
+ },
formatTooltipText(params) {
- const [date, value] = params;
- return [dateFormat(date, 'dd mmm yyyy, h:MMtt'), value.toFixed(3)];
+ this.tooltip.title = dateFormat(params.value, 'dd mmm yyyy, h:MMTT');
+ this.tooltip.content = [];
+ params.seriesData.forEach(seriesData => {
+ if (seriesData.componentSubType === graphTypes.deploymentData) {
+ this.tooltip.isDeployment = true;
+ const [deploy] = this.recentDeployments.filter(
+ deployment => deployment.createdAt === seriesData.value[0],
+ );
+ this.tooltip.sha = deploy.sha.substring(0, 8);
+ } else {
+ const { seriesName } = seriesData;
+ // seriesData.value contains the chart's [x, y] value pair
+ // seriesData.value[1] is threfore the chart y value
+ const value = seriesData.value[1].toFixed(3);
+
+ this.tooltip.content.push({
+ name: seriesName,
+ value,
+ });
+ }
+ });
+ },
+ setSvg(name) {
+ getSvgIconPathContent(name)
+ .then(path => {
+ if (path) {
+ this.$set(this.svgs, name, `path://${path}`);
+ }
+ })
+ .catch(() => {});
+ },
+ onChartUpdated(chart) {
+ [this.primaryColor] = chart.getOption().color;
},
- onCreated(chart) {
- this.$emit('created', chart);
+ onResize() {
+ const { width } = this.$refs.areaChart.$el.getBoundingClientRect();
+ this.width = width;
},
},
};
</script>
<template>
- <div class="prometheus-graph">
+ <div class="prometheus-graph col-12 col-lg-6">
<div class="prometheus-graph-header">
- <h5 class="prometheus-graph-title">{{ graphData.title }}</h5>
- <div class="prometheus-graph-widgets"><slot></slot></div>
+ <h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5>
+ <div ref="graphWidgets" class="prometheus-graph-widgets"><slot></slot></div>
</div>
<gl-area-chart
+ ref="areaChart"
+ v-bind="$attrs"
:data="chartData"
:option="chartOptions"
:format-tooltip-text="formatTooltipText"
- @created="onCreated"
- />
+ :thresholds="alertData"
+ :width="width"
+ :height="height"
+ @updated="onChartUpdated"
+ >
+ <template slot="tooltipTitle">
+ <div v-if="tooltip.isDeployment">
+ {{ __('Deployed') }}
+ </div>
+ {{ tooltip.title }}
+ </template>
+ <template slot="tooltipContent">
+ <div v-if="tooltip.isDeployment" class="d-flex align-items-center">
+ <icon name="commit" class="mr-2" />
+ {{ tooltip.sha }}
+ </div>
+ <template v-else>
+ <div
+ v-for="(content, key) in tooltip.content"
+ :key="key"
+ class="d-flex justify-content-between"
+ >
+ {{ content.name }} {{ content.value }}
+ </div>
+ </template>
+ </template>
+ </gl-area-chart>
</div>
</template>
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 2d9c5050c9b..895a57785bc 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,20 +1,19 @@
<script>
-import _ from 'underscore';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import Flash from '../../flash';
import MonitoringService from '../services/monitoring_service';
import MonitorAreaChart from './charts/area.vue';
import GraphGroup from './graph_group.vue';
-import Graph from './graph.vue';
import EmptyState from './empty_state.vue';
import MonitoringStore from '../stores/monitoring_store';
-import eventHub from '../event_hub';
+
+const sidebarAnimationDuration = 150;
+let sidebarMutationObserver;
export default {
components: {
MonitorAreaChart,
- Graph,
GraphGroup,
EmptyState,
Icon,
@@ -25,21 +24,11 @@ export default {
required: false,
default: true,
},
- showLegend: {
- type: Boolean,
- required: false,
- default: true,
- },
showPanels: {
type: Boolean,
required: false,
default: true,
},
- forceSmallGraph: {
- type: Boolean,
- required: false,
- default: false,
- },
documentationPath: {
type: String,
required: true,
@@ -99,51 +88,38 @@ export default {
store: new MonitoringStore(),
state: 'gettingStarted',
showEmptyState: true,
- hoverData: {},
elWidth: 0,
};
},
- computed: {
- graphComponent() {
- return gon.features && gon.features.areaChart ? MonitorAreaChart : Graph;
- },
- forceRedraw() {
- return this.elWidth;
- },
- },
created() {
this.service = new MonitoringService({
metricsEndpoint: this.metricsEndpoint,
deploymentEndpoint: this.deploymentEndpoint,
environmentsEndpoint: this.environmentsEndpoint,
});
- this.mutationObserverConfig = {
- attributes: true,
- childList: false,
- subtree: false,
- };
- eventHub.$on('hoverChanged', this.hoverChanged);
},
beforeDestroy() {
- eventHub.$off('hoverChanged', this.hoverChanged);
- window.removeEventListener('resize', this.resizeThrottled, false);
- this.sidebarMutationObserver.disconnect();
+ if (sidebarMutationObserver) {
+ sidebarMutationObserver.disconnect();
+ }
},
mounted() {
- this.resizeThrottled = _.debounce(this.resize, 100);
if (!this.hasMetrics) {
this.state = 'gettingStarted';
} else {
this.getGraphsData();
- window.addEventListener('resize', this.resizeThrottled, false);
-
- const sidebarEl = document.querySelector('.nav-sidebar');
- // The sidebar listener
- this.sidebarMutationObserver = new MutationObserver(this.resizeThrottled);
- this.sidebarMutationObserver.observe(sidebarEl, this.mutationObserverConfig);
+ sidebarMutationObserver = new MutationObserver(this.onSidebarMutation);
+ sidebarMutationObserver.observe(document.querySelector('.layout-page'), {
+ attributes: true,
+ childList: false,
+ subtree: false,
+ });
}
},
methods: {
+ getGraphAlerts(graphId) {
+ return this.alertData ? this.alertData[graphId] || {} : {};
+ },
getGraphsData() {
this.state = 'loading';
Promise.all([
@@ -165,42 +141,40 @@ export default {
this.showEmptyState = false;
})
- .then(this.resize)
.catch(() => {
this.state = 'unableToConnect';
});
},
- resize() {
- this.elWidth = this.$el.clientWidth;
- },
- hoverChanged(data) {
- this.hoverData = data;
+ onSidebarMutation() {
+ setTimeout(() => {
+ this.elWidth = this.$el.clientWidth;
+ }, sidebarAnimationDuration);
},
},
};
</script>
<template>
- <div v-if="!showEmptyState" :key="forceRedraw" class="prometheus-graphs prepend-top-default">
+ <div v-if="!showEmptyState" class="prometheus-graphs prepend-top-default">
<div class="environments d-flex align-items-center">
{{ s__('Metrics|Environment') }}
<div class="dropdown prepend-left-10">
<button class="dropdown-menu-toggle" data-toggle="dropdown" type="button">
- <span> {{ currentEnvironmentName }} </span> <icon name="chevron-down" />
+ <span>{{ currentEnvironmentName }}</span>
+ <icon name="chevron-down" />
</button>
<div
v-if="store.environmentsData.length > 0"
class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up"
>
<ul>
- <li v-for="environment in store.environmentsData" :key="environment.latest.id">
+ <li v-for="environment in store.environmentsData" :key="environment.id">
<a
- :href="environment.latest.metrics_path"
- :class="{ 'is-active': environment.latest.name == currentEnvironmentName }"
+ :href="environment.metrics_path"
+ :class="{ 'is-active': environment.name == currentEnvironmentName }"
class="dropdown-item"
+ >{{ environment.name }}</a
>
- {{ environment.latest.name }}
- </a>
</li>
</ul>
</div>
@@ -212,21 +186,15 @@ export default {
:name="groupData.group"
:show-panels="showPanels"
>
- <component
- :is="graphComponent"
+ <monitor-area-chart
v-for="(graphData, graphIndex) in groupData.metrics"
:key="graphIndex"
:graph-data="graphData"
- :hover-data="hoverData"
:deployment-data="store.deploymentData"
- :project-path="projectPath"
- :tags-path="tagsPath"
- :show-legend="showLegend"
- :small-graph="forceSmallGraph"
- >
- <!-- EE content -->
- {{ null }}
- </component>
+ :alert-data="getGraphAlerts(graphData.id)"
+ :container-width="elWidth"
+ group-id="monitor-area-chart"
+ />
</graph-group>
</div>
<empty-state
diff --git a/app/assets/javascripts/monitoring/components/graph.vue b/app/assets/javascripts/monitoring/components/graph.vue
deleted file mode 100644
index 64a1df80a8e..00000000000
--- a/app/assets/javascripts/monitoring/components/graph.vue
+++ /dev/null
@@ -1,329 +0,0 @@
-<script>
-import { scaleLinear, scaleTime } from 'd3-scale';
-import { axisLeft, axisBottom } from 'd3-axis';
-import _ from 'underscore';
-import { max, extent } from 'd3-array';
-import { select } from 'd3-selection';
-import GraphAxis from './graph/axis.vue';
-import GraphLegend from './graph/legend.vue';
-import GraphFlag from './graph/flag.vue';
-import GraphDeployment from './graph/deployment.vue';
-import GraphPath from './graph/path.vue';
-import MonitoringMixin from '../mixins/monitoring_mixins';
-import eventHub from '../event_hub';
-import measurements from '../utils/measurements';
-import { bisectDate, timeScaleFormat } from '../utils/date_time_formatters';
-import createTimeSeries from '../utils/multiple_time_series';
-import bp from '../../breakpoints';
-
-const d3 = { scaleLinear, scaleTime, axisLeft, axisBottom, max, extent, select };
-
-export default {
- components: {
- GraphAxis,
- GraphFlag,
- GraphDeployment,
- GraphPath,
- GraphLegend,
- },
- mixins: [MonitoringMixin],
- props: {
- graphData: {
- type: Object,
- required: true,
- },
- deploymentData: {
- type: Array,
- required: true,
- },
- hoverData: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- projectPath: {
- type: String,
- required: true,
- },
- tagsPath: {
- type: String,
- required: true,
- },
- showLegend: {
- type: Boolean,
- required: false,
- default: true,
- },
- smallGraph: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- data() {
- return {
- baseGraphHeight: 450,
- baseGraphWidth: 600,
- graphHeight: 450,
- graphWidth: 600,
- graphHeightOffset: 120,
- margin: {},
- unitOfDisplay: '',
- yAxisLabel: '',
- legendTitle: '',
- reducedDeploymentData: [],
- measurements: measurements.large,
- currentData: {
- time: new Date(),
- value: 0,
- },
- currentXCoordinate: 0,
- currentCoordinates: {},
- showFlag: false,
- showFlagContent: false,
- timeSeries: [],
- graphDrawData: {},
- realPixelRatio: 1,
- seriesUnderMouse: [],
- };
- },
- computed: {
- outerViewBox() {
- return `0 0 ${this.baseGraphWidth} ${this.baseGraphHeight}`;
- },
- innerViewBox() {
- return `0 0 ${this.baseGraphWidth - 150} ${this.baseGraphHeight}`;
- },
- axisTransform() {
- return `translate(70, ${this.graphHeight - 100})`;
- },
- paddingBottomRootSvg() {
- return {
- paddingBottom: `${Math.ceil(this.baseGraphHeight * 100) / this.baseGraphWidth || 0}%`,
- };
- },
- deploymentFlagData() {
- return this.reducedDeploymentData.find(deployment => deployment.showDeploymentFlag);
- },
- shouldRenderData() {
- return this.graphData.queries.filter(s => s.result.length > 0).length > 0;
- },
- },
- watch: {
- hoverData() {
- this.positionFlag();
- },
- },
- mounted() {
- this.draw();
- },
- methods: {
- showDot(path) {
- return this.showFlagContent && this.seriesUnderMouse.includes(path);
- },
- draw() {
- const breakpointSize = bp.getBreakpointSize();
- const svgWidth = this.$refs.baseSvg.getBoundingClientRect().width;
-
- this.margin = measurements.large.margin;
-
- if (this.smallGraph || breakpointSize === 'xs' || breakpointSize === 'sm') {
- this.graphHeight = 300;
- this.margin = measurements.small.margin;
- this.measurements = measurements.small;
- }
-
- this.yAxisLabel = this.graphData.y_label || 'Values';
- this.graphWidth = svgWidth - this.margin.left - this.margin.right;
- this.graphHeight = this.graphHeight - this.margin.top - this.margin.bottom;
- this.baseGraphHeight = this.graphHeight - 50;
- this.baseGraphWidth = this.graphWidth;
-
- // pixel offsets inside the svg and outside are not 1:1
- this.realPixelRatio = svgWidth / this.baseGraphWidth;
-
- // set the legends on the axes
- const [query] = this.graphData.queries;
- this.legendTitle = query ? query.label : 'Average';
- this.unitOfDisplay = query ? query.unit : '';
-
- if (this.shouldRenderData) {
- this.renderAxesPaths();
- this.formatDeployments();
- }
- },
- handleMouseOverGraph(e) {
- let point = this.$refs.graphData.createSVGPoint();
- point.x = e.clientX;
- point.y = e.clientY;
- point = point.matrixTransform(this.$refs.graphData.getScreenCTM().inverse());
- point.x += 7;
-
- this.seriesUnderMouse = this.timeSeries.filter(series => {
- const mouseX = series.timeSeriesScaleX.invert(point.x);
- let minDistance = Infinity;
-
- const closestTickMark = Object.keys(this.allXAxisValues).reduce((closest, x) => {
- const distance = Math.abs(Number(new Date(x)) - Number(mouseX));
- if (distance < minDistance) {
- minDistance = distance;
- return x;
- }
- return closest;
- });
-
- return series.values.find(v => v.time.toString() === closestTickMark);
- });
-
- const firstTimeSeries = this.seriesUnderMouse[0];
- const timeValueOverlay = firstTimeSeries.timeSeriesScaleX.invert(point.x);
- const overlayIndex = bisectDate(firstTimeSeries.values, timeValueOverlay, 1);
- const d0 = firstTimeSeries.values[overlayIndex - 1];
- const d1 = firstTimeSeries.values[overlayIndex];
- if (d0 === undefined || d1 === undefined) return;
- const evalTime = timeValueOverlay - d0[0] > d1[0] - timeValueOverlay;
- const hoveredDataIndex = evalTime ? overlayIndex : overlayIndex - 1;
- const hoveredDate = firstTimeSeries.values[hoveredDataIndex].time;
- const currentDeployXPos = this.mouseOverDeployInfo(point.x);
-
- eventHub.$emit('hoverChanged', {
- hoveredDate,
- currentDeployXPos,
- });
- },
- renderAxesPaths() {
- ({ timeSeries: this.timeSeries, graphDrawData: this.graphDrawData } = createTimeSeries(
- this.graphData.queries,
- this.graphWidth,
- this.graphHeight,
- this.graphHeightOffset,
- ));
-
- if (_.findWhere(this.timeSeries, { renderCanary: true })) {
- this.timeSeries = this.timeSeries.map(series => ({ ...series, renderCanary: true }));
- }
-
- const axisXScale = d3.scaleTime().range([0, this.graphWidth - 70]);
- const axisYScale = d3.scaleLinear().range([this.graphHeight - this.graphHeightOffset, 0]);
-
- const allValues = this.timeSeries.reduce((all, { values }) => all.concat(values), []);
- axisXScale.domain(d3.extent(allValues, d => d.time));
- axisYScale.domain([0, d3.max(allValues.map(d => d.value))]);
-
- this.allXAxisValues = this.timeSeries.reduce((obj, series) => {
- const seriesKeys = {};
- series.values.forEach(v => {
- seriesKeys[v.time] = true;
- });
- return {
- ...obj,
- ...seriesKeys,
- };
- }, {});
-
- const xAxis = d3
- .axisBottom()
- .scale(axisXScale)
- .ticks(this.graphWidth / 120)
- .tickFormat(timeScaleFormat);
-
- const yAxis = d3
- .axisLeft()
- .scale(axisYScale)
- .ticks(measurements.yTicks);
-
- d3.select(this.$refs.baseSvg)
- .select('.x-axis')
- .call(xAxis);
-
- const width = this.graphWidth;
- d3.select(this.$refs.baseSvg)
- .select('.y-axis')
- .call(yAxis)
- .selectAll('.tick')
- .each(function createTickLines(d, i) {
- if (i > 0) {
- d3.select(this)
- .select('line')
- .attr('x2', width)
- .attr('class', 'axis-tick');
- } // Avoid adding the class to the first tick, to prevent coloring
- }); // This will select all of the ticks once they're rendered
- },
- },
-};
-</script>
-
-<template>
- <div
- class="prometheus-graph"
- @mouseover="showFlagContent = true;"
- @mouseleave="showFlagContent = false;"
- >
- <div class="prometheus-graph-header">
- <h5 class="prometheus-graph-title">{{ graphData.title }}</h5>
- <div class="prometheus-graph-widgets"><slot></slot></div>
- </div>
- <div :style="paddingBottomRootSvg" class="prometheus-svg-container">
- <svg ref="baseSvg" :viewBox="outerViewBox">
- <g :transform="axisTransform" class="x-axis" />
- <g class="y-axis" transform="translate(70, 20)" />
- <graph-axis
- :graph-width="graphWidth"
- :graph-height="graphHeight"
- :margin="margin"
- :measurements="measurements"
- :y-axis-label="yAxisLabel"
- :unit-of-display="unitOfDisplay"
- />
- <svg v-if="shouldRenderData" ref="graphData" :viewBox="innerViewBox" class="graph-data">
- <slot name="additionalSvgContent" :graphDrawData="graphDrawData" />
- <graph-path
- v-for="(path, index) in timeSeries"
- :key="index"
- :generated-line-path="path.linePath"
- :generated-area-path="path.areaPath"
- :line-style="path.lineStyle"
- :line-color="path.lineColor"
- :area-color="path.areaColor"
- :current-coordinates="currentCoordinates[path.metricTag]"
- :show-dot="showDot(path)"
- />
- <graph-deployment
- :deployment-data="reducedDeploymentData"
- :graph-height="graphHeight"
- :graph-height-offset="graphHeightOffset"
- />
- <rect
- ref="graphOverlay"
- :width="graphWidth - 70"
- :height="graphHeight - 100"
- class="prometheus-graph-overlay"
- transform="translate(-5, 20)"
- @mousemove="handleMouseOverGraph($event);"
- />
- </svg>
- <svg v-else :viewBox="innerViewBox" class="js-no-data-to-display">
- <text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">
- {{ s__('Metrics|No data to display') }}
- </text>
- </svg>
- </svg>
- <graph-flag
- v-if="shouldRenderData"
- :real-pixel-ratio="realPixelRatio"
- :current-x-coordinate="currentXCoordinate"
- :current-data="currentData"
- :graph-height="graphHeight"
- :graph-height-offset="graphHeightOffset"
- :show-flag-content="showFlagContent"
- :time-series="seriesUnderMouse"
- :unit-of-display="unitOfDisplay"
- :legend-title="legendTitle"
- :deployment-flag-data="deploymentFlagData"
- :current-coordinates="currentCoordinates"
- />
- </div>
- <graph-legend v-if="showLegend" :legend-title="legendTitle" :time-series="timeSeries" />
- </div>
-</template>
diff --git a/app/assets/javascripts/monitoring/components/graph/axis.vue b/app/assets/javascripts/monitoring/components/graph/axis.vue
deleted file mode 100644
index 8f046857a20..00000000000
--- a/app/assets/javascripts/monitoring/components/graph/axis.vue
+++ /dev/null
@@ -1,118 +0,0 @@
-<script>
-import { convertToSentenceCase } from '~/lib/utils/text_utility';
-import { s__ } from '~/locale';
-
-export default {
- props: {
- graphWidth: {
- type: Number,
- required: true,
- },
- graphHeight: {
- type: Number,
- required: true,
- },
- margin: {
- type: Object,
- required: true,
- },
- measurements: {
- type: Object,
- required: true,
- },
- yAxisLabel: {
- type: String,
- required: true,
- },
- unitOfDisplay: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- yLabelWidth: 0,
- yLabelHeight: 0,
- };
- },
- computed: {
- textTransform() {
- const yCoordinate =
- (this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset) / 2 || 0;
-
- return `translate(15, ${yCoordinate}) rotate(-90)`;
- },
-
- rectTransform() {
- const yCoordinate =
- (this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset) / 2 +
- this.yLabelWidth / 2 || 0;
-
- return `translate(0, ${yCoordinate}) rotate(-90)`;
- },
-
- xPosition() {
- return (this.graphWidth + this.measurements.axisLabelLineOffset) / 2 - this.margin.right || 0;
- },
-
- yPosition() {
- return this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset || 0;
- },
-
- yAxisLabelSentenceCase() {
- return `${convertToSentenceCase(this.yAxisLabel)} (${this.unitOfDisplay})`;
- },
-
- timeString() {
- return s__('PrometheusDashboard|Time');
- },
- },
- mounted() {
- this.$nextTick(() => {
- const bbox = this.$refs.ylabel.getBBox();
- this.yLabelWidth = bbox.width + 10; // Added some padding
- this.yLabelHeight = bbox.height + 5;
- });
- },
-};
-</script>
-<template>
- <g class="axis-label-container">
- <line
- :y1="yPosition"
- :x2="graphWidth + 20"
- :y2="yPosition"
- class="label-x-axis-line"
- stroke="#000000"
- stroke-width="1"
- x1="10"
- />
- <line
- :x2="10"
- :y2="yPosition"
- class="label-y-axis-line"
- stroke="#000000"
- stroke-width="1"
- x1="10"
- y1="0"
- />
- <rect
- :transform="rectTransform"
- :width="yLabelWidth"
- :height="yLabelHeight"
- class="rect-axis-text"
- />
- <text
- ref="ylabel"
- :transform="textTransform"
- class="label-axis-text y-label-text"
- text-anchor="middle"
- >
- {{ yAxisLabelSentenceCase }}
- </text>
- <rect :x="xPosition + 60" :y="graphHeight - 80" class="rect-axis-text" width="35" height="50" />
- <text :x="xPosition + 60" :y="yPosition" class="label-axis-text x-label-text" dy=".35em">
- {{ timeString }}
- </text>
- </g>
-</template>
diff --git a/app/assets/javascripts/monitoring/components/graph/deployment.vue b/app/assets/javascripts/monitoring/components/graph/deployment.vue
deleted file mode 100644
index bee9784692c..00000000000
--- a/app/assets/javascripts/monitoring/components/graph/deployment.vue
+++ /dev/null
@@ -1,48 +0,0 @@
-<script>
-export default {
- props: {
- deploymentData: {
- type: Array,
- required: true,
- },
- graphHeight: {
- type: Number,
- required: true,
- },
- graphHeightOffset: {
- type: Number,
- required: true,
- },
- },
- computed: {
- calculatedHeight() {
- return this.graphHeight - this.graphHeightOffset;
- },
- },
- methods: {
- transformDeploymentGroup(deployment) {
- return `translate(${Math.floor(deployment.xPos) - 5}, 20)`;
- },
- },
-};
-</script>
-<template>
- <g class="deploy-info">
- <g
- v-for="(deployment, index) in deploymentData"
- :key="index"
- :transform="transformDeploymentGroup(deployment)"
- >
- <rect :height="calculatedHeight" x="0" y="0" width="3" fill="url(#shadow-gradient)" />
- <line :y2="calculatedHeight" class="deployment-line" x1="0" y1="0" x2="0" stroke="#000" />
- </g>
- <svg height="0" width="0">
- <defs>
- <linearGradient id="shadow-gradient">
- <stop offset="0%" stop-color="#000" stop-opacity="0.4" />
- <stop offset="100%" stop-color="#000" stop-opacity="0" />
- </linearGradient>
- </defs>
- </svg>
- </g>
-</template>
diff --git a/app/assets/javascripts/monitoring/components/graph/flag.vue b/app/assets/javascripts/monitoring/components/graph/flag.vue
deleted file mode 100644
index 9d6d1caef80..00000000000
--- a/app/assets/javascripts/monitoring/components/graph/flag.vue
+++ /dev/null
@@ -1,151 +0,0 @@
-<script>
-import { dateFormat, timeFormat } from '../../utils/date_time_formatters';
-import { formatRelevantDigits } from '../../../lib/utils/number_utils';
-import Icon from '../../../vue_shared/components/icon.vue';
-import TrackLine from './track_line.vue';
-
-export default {
- components: {
- Icon,
- TrackLine,
- },
- props: {
- currentXCoordinate: {
- type: Number,
- required: true,
- },
- currentData: {
- type: Object,
- required: true,
- },
- deploymentFlagData: {
- type: Object,
- required: false,
- default: null,
- },
- graphHeight: {
- type: Number,
- required: true,
- },
- graphHeightOffset: {
- type: Number,
- required: true,
- },
- realPixelRatio: {
- type: Number,
- required: true,
- },
- showFlagContent: {
- type: Boolean,
- required: true,
- },
- timeSeries: {
- type: Array,
- required: true,
- },
- unitOfDisplay: {
- type: String,
- required: true,
- },
- legendTitle: {
- type: String,
- required: true,
- },
- currentCoordinates: {
- type: Object,
- required: true,
- },
- },
- computed: {
- formatTime() {
- return this.deploymentFlagData
- ? timeFormat(this.deploymentFlagData.time)
- : timeFormat(this.currentData.time);
- },
- formatDate() {
- return this.deploymentFlagData
- ? dateFormat(this.deploymentFlagData.time)
- : dateFormat(this.currentData.time);
- },
- cursorStyle() {
- const xCoordinate = this.deploymentFlagData
- ? this.deploymentFlagData.xPos
- : this.currentXCoordinate;
-
- const offsetTop = 20 * this.realPixelRatio;
- const offsetLeft = (70 + xCoordinate) * this.realPixelRatio;
- const height = (this.graphHeight - this.graphHeightOffset) * this.realPixelRatio;
-
- return {
- top: `${offsetTop}px`,
- left: `${offsetLeft}px`,
- height: `${height}px`,
- };
- },
- flagOrientation() {
- if (this.currentXCoordinate * this.realPixelRatio > 120) {
- return 'left';
- }
- return 'right';
- },
- },
- methods: {
- seriesMetricValue(seriesIndex, series) {
- const indexFromCoordinates = this.currentCoordinates[series.metricTag]
- ? this.currentCoordinates[series.metricTag].currentDataIndex
- : 0;
- const index = this.deploymentFlagData
- ? this.deploymentFlagData.seriesIndex
- : indexFromCoordinates;
- const value = series.values[index] && series.values[index].value;
- if (Number.isNaN(value)) {
- return '-';
- }
- return `${formatRelevantDigits(value)}${this.unitOfDisplay}`;
- },
- seriesMetricLabel(index, series) {
- if (this.timeSeries.length < 2) {
- return this.legendTitle;
- }
- if (series.metricTag) {
- return series.metricTag;
- }
- return `series ${index + 1}`;
- },
- },
-};
-</script>
-
-<template>
- <div :style="cursorStyle" class="prometheus-graph-cursor">
- <div v-if="showFlagContent" :class="flagOrientation" class="prometheus-graph-flag popover">
- <div class="arrow-shadow"></div>
- <div class="arrow"></div>
- <div class="popover-title">
- <h5 v-if="deploymentFlagData">Deployed</h5>
- {{ formatDate }} <strong>{{ formatTime }}</strong>
- </div>
- <div v-if="deploymentFlagData" class="popover-content deploy-meta-content">
- <div>
- <icon :size="12" name="commit" />
- <a :href="deploymentFlagData.commitUrl"> {{ deploymentFlagData.sha.slice(0, 8) }} </a>
- </div>
- <div v-if="deploymentFlagData.tag">
- <icon :size="12" name="label" />
- <a :href="deploymentFlagData.tagUrl"> {{ deploymentFlagData.ref }} </a>
- </div>
- </div>
- <div class="popover-content">
- <table class="prometheus-table">
- <tr v-for="(series, index) in timeSeries" :key="index">
- <track-line :track="series" />
- <td>{{ series.track }} {{ seriesMetricLabel(index, series) }}</td>
- <td>
- <strong>{{ seriesMetricValue(index, series) }}</strong>
- </td>
- </tr>
- </table>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/monitoring/components/graph/legend.vue b/app/assets/javascripts/monitoring/components/graph/legend.vue
deleted file mode 100644
index b5211c306a3..00000000000
--- a/app/assets/javascripts/monitoring/components/graph/legend.vue
+++ /dev/null
@@ -1,62 +0,0 @@
-<script>
-import TrackLine from './track_line.vue';
-import TrackInfo from './track_info.vue';
-
-export default {
- components: {
- TrackLine,
- TrackInfo,
- },
- props: {
- legendTitle: {
- type: String,
- required: true,
- },
- timeSeries: {
- type: Array,
- required: true,
- },
- },
- methods: {
- isStable(track) {
- return {
- 'prometheus-table-row-highlight': track.trackName !== 'Canary' && track.renderCanary,
- };
- },
- },
-};
-</script>
-<template>
- <div class="prometheus-graph-legends prepend-left-10">
- <table class="prometheus-table">
- <tr
- v-for="(series, index) in timeSeries"
- v-if="series.shouldRenderLegend"
- :key="index"
- :class="isStable(series)"
- >
- <td>
- <strong v-if="series.renderCanary">{{ series.trackName }}</strong>
- </td>
- <track-line :track="series" />
- <td v-if="timeSeries.length > 1" class="legend-metric-title">
- <track-info v-if="series.metricTag" :track="series" />
- <track-info v-else :track="series">
- <strong>{{ legendTitle }}</strong> series {{ index + 1 }}
- </track-info>
- </td>
- <td v-else>
- <track-info :track="series">
- <strong>{{ legendTitle }}</strong>
- </track-info>
- </td>
- <template v-for="(track, trackIndex) in series.tracksLegend">
- <track-line :key="`track-line-${trackIndex}`" :track="track" />
- <td :key="`track-info-${trackIndex}`">
- <track-info :track="track" class="legend-metric-title" />
- </td>
- </template>
- </tr>
- </table>
- </div>
-</template>
diff --git a/app/assets/javascripts/monitoring/components/graph/path.vue b/app/assets/javascripts/monitoring/components/graph/path.vue
deleted file mode 100644
index f2c237ec391..00000000000
--- a/app/assets/javascripts/monitoring/components/graph/path.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<script>
-export default {
- props: {
- generatedLinePath: {
- type: String,
- required: true,
- },
- generatedAreaPath: {
- type: String,
- required: true,
- },
- lineStyle: {
- type: String,
- required: false,
- default: '',
- },
- lineColor: {
- type: String,
- required: true,
- },
- areaColor: {
- type: String,
- required: true,
- },
- currentCoordinates: {
- type: Object,
- required: false,
- default: () => ({ currentX: 0, currentY: 0 }),
- },
- showDot: {
- type: Boolean,
- required: true,
- },
- },
- computed: {
- strokeDashArray() {
- if (this.lineStyle === 'dashed') return '3, 1';
- if (this.lineStyle === 'dotted') return '1, 1';
- return null;
- },
- },
-};
-</script>
-<template>
- <g transform="translate(-5, 20)">
- <circle
- v-if="showDot"
- :cx="currentCoordinates.currentX"
- :cy="currentCoordinates.currentY"
- :fill="lineColor"
- :stroke="lineColor"
- class="circle-path"
- r="3"
- />
- <path :d="generatedAreaPath" :fill="areaColor" class="metric-area" />
- <path
- :d="generatedLinePath"
- :stroke="lineColor"
- :stroke-dasharray="strokeDashArray"
- class="metric-line"
- fill="none"
- stroke-width="1"
- />
- </g>
-</template>
diff --git a/app/assets/javascripts/monitoring/components/graph/track_info.vue b/app/assets/javascripts/monitoring/components/graph/track_info.vue
deleted file mode 100644
index 3464067834f..00000000000
--- a/app/assets/javascripts/monitoring/components/graph/track_info.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-<script>
-import { formatRelevantDigits } from '~/lib/utils/number_utils';
-
-export default {
- name: 'TrackInfo',
- props: {
- track: {
- type: Object,
- required: true,
- },
- },
- computed: {
- summaryMetrics() {
- return `Avg: ${formatRelevantDigits(this.track.average)} · Max: ${formatRelevantDigits(
- this.track.max,
- )}`;
- },
- },
-};
-</script>
-<template>
- <span>
- <slot>
- <strong> {{ track.metricTag }} </strong>
- </slot>
- {{ summaryMetrics }}
- </span>
-</template>
diff --git a/app/assets/javascripts/monitoring/components/graph/track_line.vue b/app/assets/javascripts/monitoring/components/graph/track_line.vue
deleted file mode 100644
index d2ed1ba113e..00000000000
--- a/app/assets/javascripts/monitoring/components/graph/track_line.vue
+++ /dev/null
@@ -1,33 +0,0 @@
-<script>
-export default {
- name: 'TrackLine',
- props: {
- track: {
- type: Object,
- required: true,
- },
- },
- computed: {
- stylizedLine() {
- if (this.track.lineStyle === 'dashed') return '6, 3';
- if (this.track.lineStyle === 'dotted') return '3, 3';
- return null;
- },
- },
-};
-</script>
-<template>
- <td>
- <svg width="16" height="8">
- <line
- :stroke-dasharray="stylizedLine"
- :stroke="track.lineColor"
- :x1="0"
- :x2="16"
- :y1="4"
- :y2="4"
- stroke-width="4"
- />
- </svg>
- </td>
-</template>
diff --git a/app/assets/javascripts/monitoring/constants.js b/app/assets/javascripts/monitoring/constants.js
new file mode 100644
index 00000000000..869173b6572
--- /dev/null
+++ b/app/assets/javascripts/monitoring/constants.js
@@ -0,0 +1,10 @@
+export const chartHeight = 300;
+
+export const graphTypes = {
+ deploymentData: 'scatter',
+};
+
+export const lineTypes = {
+ default: 'solid',
+ threshold: 'dashed',
+};
diff --git a/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js b/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js
deleted file mode 100644
index 87c3d969de4..00000000000
--- a/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import { bisectDate } from '../utils/date_time_formatters';
-
-const mixins = {
- methods: {
- mouseOverDeployInfo(mouseXPos) {
- if (!this.reducedDeploymentData) return false;
-
- let dataFound = false;
- this.reducedDeploymentData = this.reducedDeploymentData.map(d => {
- const deployment = d;
- if (d.xPos >= mouseXPos - 10 && d.xPos <= mouseXPos + 10 && !dataFound) {
- dataFound = d.xPos + 1;
-
- deployment.showDeploymentFlag = true;
- } else {
- deployment.showDeploymentFlag = false;
- }
- return deployment;
- });
-
- return dataFound;
- },
-
- formatDeployments() {
- this.reducedDeploymentData = this.deploymentData.reduce((deploymentDataArray, deployment) => {
- const time = new Date(deployment.created_at);
- const xPos = Math.floor(this.timeSeries[0].timeSeriesScaleX(time));
-
- time.setSeconds(this.timeSeries[0].values[0].time.getSeconds());
-
- if (xPos >= 0) {
- const seriesIndex = bisectDate(this.timeSeries[0].values, time, 1);
-
- deploymentDataArray.push({
- id: deployment.id,
- time,
- sha: deployment.sha,
- commitUrl: `${this.projectPath}/commit/${deployment.sha}`,
- tag: deployment.tag,
- tagUrl: deployment.tag ? `${this.tagsPath}/${deployment.ref.name}` : null,
- ref: deployment.ref.name,
- xPos,
- seriesIndex,
- showDeploymentFlag: false,
- });
- }
-
- return deploymentDataArray;
- }, []);
- },
-
- positionFlag() {
- const timeSeries = this.seriesUnderMouse[0];
- if (!timeSeries) {
- return;
- }
- const hoveredDataIndex = bisectDate(timeSeries.values, this.hoverData.hoveredDate);
-
- this.currentData = timeSeries.values[hoveredDataIndex];
- this.currentXCoordinate = Math.floor(timeSeries.timeSeriesScaleX(this.currentData.time));
-
- this.currentCoordinates = {};
-
- this.seriesUnderMouse.forEach(series => {
- const currentDataIndex = bisectDate(series.values, this.hoverData.hoveredDate);
- const currentData = series.values[currentDataIndex];
- const currentX = Math.floor(series.timeSeriesScaleX(currentData.time));
- const currentY = Math.floor(series.timeSeriesScaleY(currentData.value));
-
- this.currentCoordinates[series.metricTag] = {
- currentX,
- currentY,
- currentDataIndex,
- };
- });
-
- if (this.hoverData.currentDeployXPos) {
- this.showFlag = false;
- } else {
- this.showFlag = true;
- }
- },
- },
-};
-
-export default mixins;
diff --git a/app/assets/javascripts/monitoring/stores/monitoring_store.js b/app/assets/javascripts/monitoring/stores/monitoring_store.js
index 8692c873a41..70635059bd9 100644
--- a/app/assets/javascripts/monitoring/stores/monitoring_store.js
+++ b/app/assets/javascripts/monitoring/stores/monitoring_store.js
@@ -13,7 +13,7 @@ function checkQueryEmptyData(query) {
result: query.result.filter(timeSeries => {
const newTimeSeries = timeSeries;
const hasValue = series =>
- !Number.isNaN(series.value) && (series.value !== null || series.value !== undefined);
+ !Number.isNaN(series[1]) && (series[1] !== null || series[1] !== undefined);
const hasNonNullValue = timeSeries.values.find(hasValue);
newTimeSeries.values = hasNonNullValue ? newTimeSeries.values : [];
@@ -33,10 +33,10 @@ function normalizeMetrics(metrics) {
...query,
result: query.result.map(result => ({
...result,
- values: result.values.map(([timestamp, value]) => ({
- time: new Date(timestamp * 1000),
- value: Number(value),
- })),
+ values: result.values.map(([timestamp, value]) => [
+ new Date(timestamp * 1000).toISOString(),
+ Number(value),
+ ]),
})),
}));
@@ -66,9 +66,7 @@ export default class MonitoringStore {
}
storeEnvironmentsData(environmentsData = []) {
- this.environmentsData = environmentsData.filter(
- environment => !!environment.latest.last_deployment,
- );
+ this.environmentsData = environmentsData.filter(environment => !!environment.last_deployment);
}
getMetricsCount() {
diff --git a/app/assets/javascripts/monitoring/utils/date_time_formatters.js b/app/assets/javascripts/monitoring/utils/date_time_formatters.js
deleted file mode 100644
index d88c13609dc..00000000000
--- a/app/assets/javascripts/monitoring/utils/date_time_formatters.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { timeFormat as time } from 'd3-time-format';
-import { timeSecond, timeMinute, timeHour, timeDay, timeWeek, timeMonth, timeYear } from 'd3-time';
-import { bisector } from 'd3-array';
-
-const d3 = {
- time,
- bisector,
- timeSecond,
- timeMinute,
- timeHour,
- timeDay,
- timeWeek,
- timeMonth,
- timeYear,
-};
-
-export const dateFormat = d3.time('%d %b %Y, ');
-export const timeFormat = d3.time('%-I:%M%p');
-export const dateFormatWithName = d3.time('%a, %b %-d');
-export const bisectDate = d3.bisector(d => d.time).left;
-
-export function timeScaleFormat(date) {
- let formatFunction;
- if (d3.timeSecond(date) < date) {
- formatFunction = d3.time('.%L');
- } else if (d3.timeMinute(date) < date) {
- formatFunction = d3.time(':%S');
- } else if (d3.timeHour(date) < date) {
- formatFunction = d3.time('%-I:%M');
- } else if (d3.timeDay(date) < date) {
- formatFunction = d3.time('%-I %p');
- } else if (d3.timeWeek(date) < date) {
- formatFunction = d3.time('%a %d');
- } else if (d3.timeMonth(date) < date) {
- formatFunction = d3.time('%b %d');
- } else if (d3.timeYear(date) < date) {
- formatFunction = d3.time('%B');
- } else {
- formatFunction = d3.time('%Y');
- }
- return formatFunction(date);
-}
diff --git a/app/assets/javascripts/monitoring/utils/measurements.js b/app/assets/javascripts/monitoring/utils/measurements.js
deleted file mode 100644
index 7c771f43eee..00000000000
--- a/app/assets/javascripts/monitoring/utils/measurements.js
+++ /dev/null
@@ -1,44 +0,0 @@
-export default {
- small: {
- // Covers both xs and sm screen sizes
- margin: {
- top: 40,
- right: 40,
- bottom: 50,
- left: 40,
- },
- legends: {
- width: 15,
- height: 3,
- offsetX: 20,
- offsetY: 32,
- },
- backgroundLegend: {
- width: 30,
- height: 50,
- },
- axisLabelLineOffset: -20,
- },
- large: {
- // This covers both md and lg screen sizes
- margin: {
- top: 80,
- right: 80,
- bottom: 100,
- left: 80,
- },
- legends: {
- width: 15,
- height: 3,
- offsetX: 20,
- offsetY: 34,
- },
- backgroundLegend: {
- width: 30,
- height: 150,
- },
- axisLabelLineOffset: 20,
- },
- xTicks: 8,
- yTicks: 3,
-};
diff --git a/app/assets/javascripts/monitoring/utils/multiple_time_series.js b/app/assets/javascripts/monitoring/utils/multiple_time_series.js
deleted file mode 100644
index 50ba14dfb2e..00000000000
--- a/app/assets/javascripts/monitoring/utils/multiple_time_series.js
+++ /dev/null
@@ -1,223 +0,0 @@
-import _ from 'underscore';
-import { scaleLinear, scaleTime } from 'd3-scale';
-import { line, area, curveLinear } from 'd3-shape';
-import { extent, max, sum } from 'd3-array';
-import { timeMinute, timeSecond } from 'd3-time';
-import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
-
-const d3 = {
- scaleLinear,
- scaleTime,
- line,
- area,
- curveLinear,
- extent,
- max,
- timeMinute,
- timeSecond,
- sum,
-};
-
-const defaultColorPalette = {
- blue: ['#1f78d1', '#8fbce8'],
- orange: ['#fc9403', '#feca81'],
- red: ['#db3b21', '#ed9d90'],
- green: ['#1aaa55', '#8dd5aa'],
- purple: ['#6666c4', '#d1d1f0'],
-};
-
-const defaultColorOrder = ['blue', 'orange', 'red', 'green', 'purple'];
-
-const defaultStyleOrder = ['solid', 'dashed', 'dotted'];
-
-function queryTimeSeries(query, graphDrawData, lineStyle) {
- let usedColors = [];
- let renderCanary = false;
- const timeSeriesParsed = [];
-
- function pickColor(name) {
- let pick;
- if (name && defaultColorPalette[name]) {
- pick = name;
- } else {
- const unusedColors = _.difference(defaultColorOrder, usedColors);
- if (unusedColors.length > 0) {
- [pick] = unusedColors;
- } else {
- usedColors = [];
- [pick] = defaultColorOrder;
- }
- }
- usedColors.push(pick);
- return defaultColorPalette[pick];
- }
-
- function findByDate(series, time) {
- const val = series.find(v => Math.abs(d3.timeSecond.count(time, v.time)) < 60);
- if (val) {
- return val.value;
- }
- return NaN;
- }
-
- // The timeseries data may have gaps in it
- // but we need a regularly-spaced set of time/value pairs
- // this gives us a complete range of one minute intervals
- // offset the same amount as the original data
- const [minX, maxX] = graphDrawData.xDom;
- const offset = d3.timeMinute(minX) - Number(minX);
- const datesWithoutGaps = d3.timeSecond
- .every(60)
- .range(d3.timeMinute.offset(minX, -1), maxX)
- .map(d => d - offset);
-
- query.result.forEach((timeSeries, timeSeriesNumber) => {
- let metricTag = '';
- let lineColor = '';
- let areaColor = '';
- let shouldRenderLegend = true;
- const timeSeriesValues = timeSeries.values.map(d => d.value);
- const maximumValue = d3.max(timeSeriesValues);
- const accum = d3.sum(timeSeriesValues);
- const trackName = capitalizeFirstCharacter(query.track ? query.track : 'Stable');
-
- if (trackName === 'Canary') {
- renderCanary = true;
- }
-
- const timeSeriesMetricLabel = timeSeries.metric[Object.keys(timeSeries.metric)[0]];
- const seriesCustomizationData =
- query.series != null && _.findWhere(query.series[0].when, { value: timeSeriesMetricLabel });
-
- if (seriesCustomizationData) {
- metricTag = seriesCustomizationData.value || timeSeriesMetricLabel;
- [lineColor, areaColor] = pickColor(seriesCustomizationData.color);
- if (timeSeriesParsed.length > 0) {
- shouldRenderLegend = false;
- } else {
- shouldRenderLegend = true;
- }
- } else {
- metricTag = timeSeriesMetricLabel || query.label || `series ${timeSeriesNumber + 1}`;
- [lineColor, areaColor] = pickColor();
- if (timeSeriesParsed.length > 1) {
- shouldRenderLegend = false;
- }
- }
-
- const values = datesWithoutGaps.map(time => ({
- time,
- value: findByDate(timeSeries.values, time),
- }));
-
- timeSeriesParsed.push({
- linePath: graphDrawData.lineFunction(values),
- areaPath: graphDrawData.areaBelowLine(values),
- timeSeriesScaleX: graphDrawData.timeSeriesScaleX,
- timeSeriesScaleY: graphDrawData.timeSeriesScaleY,
- values: timeSeries.values,
- max: maximumValue,
- average: accum / timeSeries.values.length,
- lineStyle,
- lineColor,
- areaColor,
- metricTag,
- trackName,
- shouldRenderLegend,
- renderCanary,
- });
-
- if (!shouldRenderLegend) {
- if (!timeSeriesParsed[0].tracksLegend) {
- timeSeriesParsed[0].tracksLegend = [];
- }
- timeSeriesParsed[0].tracksLegend.push({
- max: maximumValue,
- average: accum / timeSeries.values.length,
- lineStyle,
- lineColor,
- metricTag,
- });
- }
- });
-
- return timeSeriesParsed;
-}
-
-function xyDomain(queries) {
- const allValues = queries.reduce(
- (allQueryResults, query) =>
- allQueryResults.concat(
- query.result.reduce((allResults, result) => allResults.concat(result.values), []),
- ),
- [],
- );
-
- const xDom = d3.extent(allValues, d => d.time);
- const yDom = [0, d3.max(allValues.map(d => d.value))];
-
- return {
- xDom,
- yDom,
- };
-}
-
-export function generateGraphDrawData(queries, graphWidth, graphHeight, graphHeightOffset) {
- const { xDom, yDom } = xyDomain(queries);
-
- const timeSeriesScaleX = d3.scaleTime().range([0, graphWidth - 70]);
- const timeSeriesScaleY = d3.scaleLinear().range([graphHeight - graphHeightOffset, 0]);
-
- timeSeriesScaleX.domain(xDom);
- timeSeriesScaleX.ticks(d3.timeMinute, 60);
- timeSeriesScaleY.domain(yDom);
-
- const defined = d => !Number.isNaN(d.value) && d.value != null;
-
- const lineFunction = d3
- .line()
- .defined(defined)
- .curve(d3.curveLinear) // d3 v4 uses curbe instead of interpolate
- .x(d => timeSeriesScaleX(d.time))
- .y(d => timeSeriesScaleY(d.value));
-
- const areaBelowLine = d3
- .area()
- .defined(defined)
- .curve(d3.curveLinear)
- .x(d => timeSeriesScaleX(d.time))
- .y0(graphHeight - graphHeightOffset)
- .y1(d => timeSeriesScaleY(d.value));
-
- const areaAboveLine = d3
- .area()
- .defined(defined)
- .curve(d3.curveLinear)
- .x(d => timeSeriesScaleX(d.time))
- .y0(0)
- .y1(d => timeSeriesScaleY(d.value));
-
- return {
- lineFunction,
- areaBelowLine,
- areaAboveLine,
- xDom,
- yDom,
- timeSeriesScaleX,
- timeSeriesScaleY,
- };
-}
-
-export default function createTimeSeries(queries, graphWidth, graphHeight, graphHeightOffset) {
- const graphDrawData = generateGraphDrawData(queries, graphWidth, graphHeight, graphHeightOffset);
-
- const timeSeries = queries.reduce((series, query, index) => {
- const lineStyle = defaultStyleOrder[index % defaultStyleOrder.length];
- return series.concat(queryTimeSeries(query, graphDrawData, lineStyle));
- }, []);
-
- return {
- timeSeries,
- graphDrawData,
- };
-}
diff --git a/app/assets/javascripts/mr_notes/index.js b/app/assets/javascripts/mr_notes/index.js
index e4d72eb8318..8eccba07c38 100644
--- a/app/assets/javascripts/mr_notes/index.js
+++ b/app/assets/javascripts/mr_notes/index.js
@@ -1,82 +1,22 @@
-import $ from 'jquery';
import Vue from 'vue';
-import { mapActions, mapState, mapGetters } from 'vuex';
+import store from 'ee_else_ce/mr_notes/stores';
+import initNotesApp from './init_notes';
import initDiffsApp from '../diffs';
-import notesApp from '../notes/components/notes_app.vue';
import discussionCounter from '../notes/components/discussion_counter.vue';
import initDiscussionFilters from '../notes/discussion_filters';
-import store from './stores';
import MergeRequest from '../merge_request';
+import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
export default function initMrNotes() {
+ resetServiceWorkersPublicPath();
+
const mrShowNode = document.querySelector('.merge-request');
// eslint-disable-next-line no-new
new MergeRequest({
action: mrShowNode.dataset.mrAction,
});
- // eslint-disable-next-line no-new
- new Vue({
- el: '#js-vue-mr-discussions',
- name: 'MergeRequestDiscussions',
- components: {
- notesApp,
- },
- store,
- data() {
- const notesDataset = document.getElementById('js-vue-mr-discussions').dataset;
- const noteableData = JSON.parse(notesDataset.noteableData);
- noteableData.noteableType = notesDataset.noteableType;
- noteableData.targetType = notesDataset.targetType;
-
- return {
- noteableData,
- currentUserData: JSON.parse(notesDataset.currentUserData),
- notesData: JSON.parse(notesDataset.notesData),
- helpPagePath: notesDataset.helpPagePath,
- };
- },
- computed: {
- ...mapGetters(['discussionTabCounter']),
- ...mapState({
- activeTab: state => state.page.activeTab,
- }),
- },
- watch: {
- discussionTabCounter() {
- this.updateDiscussionTabCounter();
- },
- },
- created() {
- this.setActiveTab(window.mrTabs.getCurrentAction());
- },
- mounted() {
- this.notesCountBadge = $('.issuable-details').find('.notes-tab .badge');
- $(document).on('visibilitychange', this.updateDiscussionTabCounter);
- window.mrTabs.eventHub.$on('MergeRequestTabChange', this.setActiveTab);
- },
- beforeDestroy() {
- $(document).off('visibilitychange', this.updateDiscussionTabCounter);
- window.mrTabs.eventHub.$off('MergeRequestTabChange', this.setActiveTab);
- },
- methods: {
- ...mapActions(['setActiveTab']),
- updateDiscussionTabCounter() {
- this.notesCountBadge.text(this.discussionTabCounter);
- },
- },
- render(createElement) {
- return createElement('notes-app', {
- props: {
- noteableData: this.noteableData,
- notesData: this.notesData,
- userData: this.currentUserData,
- shouldShow: this.activeTab === 'show',
- helpPagePath: this.helpPagePath,
- },
- });
- },
- });
+ initNotesApp();
// eslint-disable-next-line no-new
new Vue({
diff --git a/app/assets/javascripts/mr_notes/init_notes.js b/app/assets/javascripts/mr_notes/init_notes.js
new file mode 100644
index 00000000000..842a209a545
--- /dev/null
+++ b/app/assets/javascripts/mr_notes/init_notes.js
@@ -0,0 +1,70 @@
+import $ from 'jquery';
+import Vue from 'vue';
+import { mapActions, mapState, mapGetters } from 'vuex';
+import store from 'ee_else_ce/mr_notes/stores';
+import notesApp from '../notes/components/notes_app.vue';
+
+export default () => {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: '#js-vue-mr-discussions',
+ name: 'MergeRequestDiscussions',
+ components: {
+ notesApp,
+ },
+ store,
+ data() {
+ const notesDataset = document.getElementById('js-vue-mr-discussions').dataset;
+ const noteableData = JSON.parse(notesDataset.noteableData);
+ noteableData.noteableType = notesDataset.noteableType;
+ noteableData.targetType = notesDataset.targetType;
+
+ return {
+ noteableData,
+ currentUserData: JSON.parse(notesDataset.currentUserData),
+ notesData: JSON.parse(notesDataset.notesData),
+ helpPagePath: notesDataset.helpPagePath,
+ };
+ },
+ computed: {
+ ...mapGetters(['discussionTabCounter']),
+ ...mapState({
+ activeTab: state => state.page.activeTab,
+ }),
+ },
+ watch: {
+ discussionTabCounter() {
+ this.updateDiscussionTabCounter();
+ },
+ },
+ created() {
+ this.setActiveTab(window.mrTabs.getCurrentAction());
+ },
+ mounted() {
+ this.notesCountBadge = $('.issuable-details').find('.notes-tab .badge');
+ $(document).on('visibilitychange', this.updateDiscussionTabCounter);
+ window.mrTabs.eventHub.$on('MergeRequestTabChange', this.setActiveTab);
+ },
+ beforeDestroy() {
+ $(document).off('visibilitychange', this.updateDiscussionTabCounter);
+ window.mrTabs.eventHub.$off('MergeRequestTabChange', this.setActiveTab);
+ },
+ methods: {
+ ...mapActions(['setActiveTab']),
+ updateDiscussionTabCounter() {
+ this.notesCountBadge.text(this.discussionTabCounter);
+ },
+ },
+ render(createElement) {
+ return createElement('notes-app', {
+ props: {
+ noteableData: this.noteableData,
+ notesData: this.notesData,
+ userData: this.currentUserData,
+ shouldShow: this.activeTab === 'show',
+ helpPagePath: this.helpPagePath,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/notebook/cells/code.vue b/app/assets/javascripts/notebook/cells/code.vue
index bd6736152f5..eefc801ed7a 100644
--- a/app/assets/javascripts/notebook/cells/code.vue
+++ b/app/assets/javascripts/notebook/cells/code.vue
@@ -1,11 +1,12 @@
<script>
-import CodeCell from './code/index.vue';
+import CodeOutput from './code/index.vue';
import OutputCell from './output/index.vue';
export default {
+ name: 'CodeCell',
components: {
- 'code-cell': CodeCell,
- 'output-cell': OutputCell,
+ CodeOutput,
+ OutputCell,
},
props: {
cell: {
@@ -29,8 +30,8 @@ export default {
hasOutput() {
return this.cell.outputs.length;
},
- output() {
- return this.cell.outputs[0];
+ outputs() {
+ return this.cell.outputs;
},
},
};
@@ -38,7 +39,7 @@ export default {
<template>
<div class="cell">
- <code-cell
+ <code-output
:raw-code="rawInputCode"
:count="cell.execution_count"
:code-css-class="codeCssClass"
@@ -47,7 +48,7 @@ export default {
<output-cell
v-if="hasOutput"
:count="cell.execution_count"
- :output="output"
+ :outputs="outputs"
:code-css-class="codeCssClass"
/>
</div>
diff --git a/app/assets/javascripts/notebook/cells/code/index.vue b/app/assets/javascripts/notebook/cells/code/index.vue
index 8bf2431c4c6..98b6cdd0944 100644
--- a/app/assets/javascripts/notebook/cells/code/index.vue
+++ b/app/assets/javascripts/notebook/cells/code/index.vue
@@ -3,8 +3,9 @@ import Prism from '../../lib/highlight';
import Prompt from '../prompt.vue';
export default {
+ name: 'CodeOutput',
components: {
- prompt: Prompt,
+ Prompt,
},
props: {
count: {
diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue
index c6fc786fa76..8dc2d73af9b 100644
--- a/app/assets/javascripts/notebook/cells/output/html.vue
+++ b/app/assets/javascripts/notebook/cells/output/html.vue
@@ -4,13 +4,21 @@ import Prompt from '../prompt.vue';
export default {
components: {
- prompt: Prompt,
+ Prompt,
},
props: {
+ count: {
+ type: Number,
+ required: true,
+ },
rawCode: {
type: String,
required: true,
},
+ index: {
+ type: Number,
+ required: true,
+ },
},
computed: {
sanitizedOutput() {
@@ -21,13 +29,16 @@ export default {
},
});
},
+ showOutput() {
+ return this.index === 0;
+ },
},
};
</script>
<template>
<div class="output">
- <prompt />
+ <prompt type="Out" :count="count" :show-output="showOutput" />
<div v-html="sanitizedOutput"></div>
</div>
</template>
diff --git a/app/assets/javascripts/notebook/cells/output/image.vue b/app/assets/javascripts/notebook/cells/output/image.vue
index fe8c81398fb..f1130275525 100644
--- a/app/assets/javascripts/notebook/cells/output/image.vue
+++ b/app/assets/javascripts/notebook/cells/output/image.vue
@@ -6,6 +6,10 @@ export default {
prompt: Prompt,
},
props: {
+ count: {
+ type: Number,
+ required: true,
+ },
outputType: {
type: String,
required: true,
@@ -14,10 +18,24 @@ export default {
type: String,
required: true,
},
+ index: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ imgSrc() {
+ return `data:${this.outputType};base64,${this.rawCode}`;
+ },
+ showOutput() {
+ return this.index === 0;
+ },
},
};
</script>
<template>
- <div class="output"><prompt /> <img :src="'data:' + outputType + ';base64,' + rawCode" /></div>
+ <div class="output">
+ <prompt type="out" :count="count" :show-output="showOutput" /> <img :src="imgSrc" />
+ </div>
</template>
diff --git a/app/assets/javascripts/notebook/cells/output/index.vue b/app/assets/javascripts/notebook/cells/output/index.vue
index bd0bcc0d819..c5ae7e7ee10 100644
--- a/app/assets/javascripts/notebook/cells/output/index.vue
+++ b/app/assets/javascripts/notebook/cells/output/index.vue
@@ -1,14 +1,9 @@
<script>
-import CodeCell from '../code/index.vue';
-import Html from './html.vue';
-import Image from './image.vue';
+import CodeOutput from '../code/index.vue';
+import HtmlOutput from './html.vue';
+import ImageOutput from './image.vue';
export default {
- components: {
- 'code-cell': CodeCell,
- 'html-output': Html,
- 'image-output': Image,
- },
props: {
codeCssClass: {
type: String,
@@ -20,68 +15,69 @@ export default {
required: false,
default: 0,
},
- output: {
- type: Object,
+ outputs: {
+ type: Array,
required: true,
- default: () => ({}),
},
},
- computed: {
- componentName() {
- if (this.output.text) {
- return 'code-cell';
- } else if (this.output.data['image/png']) {
- return 'image-output';
- } else if (this.output.data['text/html']) {
- return 'html-output';
- } else if (this.output.data['image/svg+xml']) {
- return 'html-output';
- }
+ data() {
+ return {
+ outputType: '',
+ };
+ },
+ methods: {
+ dataForType(output, type) {
+ let data = output.data[type];
- return 'code-cell';
- },
- rawCode() {
- if (this.output.text) {
- return this.output.text.join('');
+ if (typeof data === 'object') {
+ data = data.join('');
}
- return this.dataForType(this.outputType);
+ return data;
},
- outputType() {
- if (this.output.text) {
- return '';
- } else if (this.output.data['image/png']) {
- return 'image/png';
- } else if (this.output.data['text/html']) {
- return 'text/html';
- } else if (this.output.data['image/svg+xml']) {
- return 'image/svg+xml';
+ getComponent(output) {
+ if (output.text) {
+ return CodeOutput;
+ } else if (output.data['image/png']) {
+ this.outputType = 'image/png';
+
+ return ImageOutput;
+ } else if (output.data['text/html']) {
+ this.outputType = 'text/html';
+
+ return HtmlOutput;
+ } else if (output.data['image/svg+xml']) {
+ this.outputType = 'image/svg+xml';
+
+ return HtmlOutput;
}
- return 'text/plain';
+ this.outputType = 'text/plain';
+ return CodeOutput;
},
- },
- methods: {
- dataForType(type) {
- let data = this.output.data[type];
-
- if (typeof data === 'object') {
- data = data.join('');
+ rawCode(output) {
+ if (output.text) {
+ return output.text.join('');
}
- return data;
+ return this.dataForType(output, this.outputType);
},
},
};
</script>
<template>
- <component
- :is="componentName"
- :output-type="outputType"
- :count="count"
- :raw-code="rawCode"
- :code-css-class="codeCssClass"
- type="output"
- />
+ <div>
+ <component
+ :is="getComponent(output)"
+ v-for="(output, index) in outputs"
+ :key="index"
+ type="output"
+ :output-type="outputType"
+ :count="count"
+ :index="index"
+ :raw-code="rawCode(output)"
+ :code-css-class="codeCssClass"
+ />
+ </div>
</template>
diff --git a/app/assets/javascripts/notebook/cells/prompt.vue b/app/assets/javascripts/notebook/cells/prompt.vue
index 3f1f239a806..1eeb61844a4 100644
--- a/app/assets/javascripts/notebook/cells/prompt.vue
+++ b/app/assets/javascripts/notebook/cells/prompt.vue
@@ -11,18 +11,26 @@ export default {
required: false,
default: 0,
},
+ showOutput: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
computed: {
hasKeys() {
return this.type !== '' && this.count;
},
+ showTypeText() {
+ return this.type && this.count && this.showOutput;
+ },
},
};
</script>
<template>
<div class="prompt">
- <span v-if="hasKeys"> {{ type }} [{{ count }}]: </span>
+ <span v-if="showTypeText"> {{ type }} [{{ count }}]: </span>
</div>
</template>
diff --git a/app/assets/javascripts/notebook/index.vue b/app/assets/javascripts/notebook/index.vue
index 6a54d0b3823..e7056c03e4a 100644
--- a/app/assets/javascripts/notebook/index.vue
+++ b/app/assets/javascripts/notebook/index.vue
@@ -3,8 +3,8 @@ import { MarkdownCell, CodeCell } from './cells';
export default {
components: {
- 'code-cell': CodeCell,
- 'markdown-cell': MarkdownCell,
+ CodeCell,
+ MarkdownCell,
},
props: {
notebook: {
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index dfb53c986fc..c9c01354333 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -138,8 +138,6 @@ export default class Notes {
this.$wrapperEl.on('click', '.js-note-delete', this.removeNote);
// delete note attachment
this.$wrapperEl.on('click', '.js-note-attachment-delete', this.removeAttachment);
- // reset main target form when clicking discard
- this.$wrapperEl.on('click', '.js-note-discard', this.resetMainTargetForm);
// update the file name when an attachment is selected
this.$wrapperEl.on('change', '.js-note-attachment-input', this.updateFormAttachment);
// reply to diff/discussion notes
@@ -191,7 +189,6 @@ export default class Notes {
this.$wrapperEl.off('keyup input', '.js-note-text');
this.$wrapperEl.off('click', '.js-note-target-reopen');
this.$wrapperEl.off('click', '.js-note-target-close');
- this.$wrapperEl.off('click', '.js-note-discard');
this.$wrapperEl.off('keydown', '.js-note-text');
this.$wrapperEl.off('click', '.js-comment-resolve-button');
this.$wrapperEl.off('click', '.system-note-commit-list-toggler');
@@ -986,11 +983,9 @@ export default class Notes {
form.find('#note_position').val(dataHolder.attr('data-position'));
form
- .find('.js-note-discard')
+ .find('.js-close-discussion-note-form')
.show()
- .removeClass('js-note-discard')
- .addClass('js-close-discussion-note-form')
- .text(form.find('.js-close-discussion-note-form').data('cancelText'));
+ .removeClass('hide');
form.find('.js-note-target-close').remove();
form.find('.js-note-new-discussion').remove();
this.setupNoteForm(form);
@@ -1194,12 +1189,11 @@ export default class Notes {
}
updateTargetButtons(e) {
- var closebtn, closetext, discardbtn, form, reopenbtn, reopentext, textarea;
+ var closebtn, closetext, form, reopenbtn, reopentext, textarea;
textarea = $(e.target);
form = textarea.parents('form');
reopenbtn = form.find('.js-note-target-reopen');
closebtn = form.find('.js-note-target-close');
- discardbtn = form.find('.js-note-discard');
if (textarea.val().trim().length > 0) {
reopentext = reopenbtn.attr('data-alternative-text');
@@ -1216,9 +1210,6 @@ export default class Notes {
if (closebtn.is(':not(.btn-comment-and-close)')) {
closebtn.addClass('btn-comment-and-close');
}
- if (discardbtn.is(':hidden')) {
- return discardbtn.show();
- }
} else {
reopentext = reopenbtn.data('originalText');
closetext = closebtn.data('originalText');
@@ -1234,9 +1225,6 @@ export default class Notes {
if (closebtn.is('.btn-comment-and-close')) {
closebtn.removeClass('btn-comment-and-close');
}
- if (discardbtn.is(':visible')) {
- return discardbtn.hide();
- }
}
}
@@ -1251,15 +1239,13 @@ export default class Notes {
var postUrl = $originalContentEl.data('postUrl');
var targetId = $originalContentEl.data('targetId');
var targetType = $originalContentEl.data('targetType');
- var markdownVersion = $originalContentEl.data('markdownVersion');
this.glForm = new GLForm($editForm.find('form'), this.enableGFM);
$editForm
.find('form')
.attr('action', `${postUrl}?html=true`)
- .attr('data-remote', 'true')
- .attr('data-markdown-version', markdownVersion);
+ .attr('data-remote', 'true');
$editForm.find('.js-form-target-id').val(targetId);
$editForm.find('.js-form-target-type').val(targetType);
$editForm
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index ce56beb1e6b..1d6cb9485f7 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -39,11 +39,6 @@ export default {
type: String,
required: true,
},
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
},
data() {
return {
@@ -342,7 +337,6 @@ Please check your network connection and try again.`;
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath"
:quick-actions-docs-path="quickActionsDocsPath"
- :markdown-version="markdownVersion"
:add-spacing-classes="false"
>
<textarea
@@ -357,9 +351,9 @@ js-gfm-input js-autosize markdown-area js-vue-textarea qa-comment-input"
data-supports-quick-actions="true"
aria-label="Description"
placeholder="Write a comment or drag your files here…"
- @keydown.up="editCurrentUserLastNote();"
- @keydown.meta.enter="handleSave();"
- @keydown.ctrl.enter="handleSave();"
+ @keydown.up="editCurrentUserLastNote()"
+ @keydown.meta.enter="handleSave()"
+ @keydown.ctrl.enter="handleSave()"
>
</textarea>
</markdown-field>
@@ -370,10 +364,10 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
>
<button
:disabled="isSubmitButtonDisabled"
- class="btn btn-create comment-btn js-comment-button js-comment-submit-button
+ class="btn btn-success js-comment-button js-comment-submit-button
qa-comment-button"
type="submit"
- @click.prevent="handleSave();"
+ @click.prevent="handleSave()"
>
{{ __(commentButtonTitle) }}
</button>
@@ -381,7 +375,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
:disabled="isSubmitButtonDisabled"
name="button"
type="button"
- class="btn comment-btn note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown"
+ class="btn btn-success note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown"
data-display="static"
data-toggle="dropdown"
aria-label="Open comment type dropdown"
@@ -394,7 +388,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
<button
type="button"
class="btn btn-transparent"
- @click.prevent="setNoteType('comment');"
+ @click.prevent="setNoteType('comment')"
>
<i aria-hidden="true" class="fa fa-check icon"> </i>
<div class="description">
@@ -408,7 +402,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
<button
type="button"
class="btn btn-transparent qa-discussion-option"
- @click.prevent="setNoteType('discussion');"
+ @click.prevent="setNoteType('discussion')"
>
<i aria-hidden="true" class="fa fa-check icon"> </i>
<div class="description">
@@ -429,17 +423,8 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
]"
:disabled="isToggleStateButtonLoading || isSubmitting"
:label="issueActionButtonTitle"
- @click="handleSave(true);"
+ @click="handleSave(true)"
/>
-
- <button
- v-if="note.length"
- type="button"
- class="btn btn-cancel js-note-discard"
- @click="discard"
- >
- Discard draft
- </button>
</div>
</form>
</div>
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index af821df0fd2..d8947e8ca50 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -5,8 +5,7 @@ import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
import { GlSkeletonLoading } from '@gitlab/ui';
import { getDiffMode } from '~/diffs/store/utils';
-
-const FIRST_CHAR_REGEX = /^(\+|-| )/;
+import { diffViewerModes } from '~/ide/constants';
export default {
components: {
@@ -33,6 +32,12 @@ export default {
diffMode() {
return getDiffMode(this.discussion.diff_file);
},
+ diffViewerMode() {
+ return this.discussion.diff_file.viewer.name;
+ },
+ isTextFile() {
+ return this.diffViewerMode === diffViewerModes.text;
+ },
hasTruncatedDiffLines() {
return (
this.discussion.truncated_diff_lines && this.discussion.truncated_diff_lines.length !== 0
@@ -54,27 +59,20 @@ export default {
this.error = true;
});
},
- trimChar(line) {
- return line.replace(FIRST_CHAR_REGEX, '');
- },
},
userColorSchemeClass: window.gon.user_color_scheme,
};
</script>
<template>
- <div :class="{ 'text-file': discussion.diff_file.text }" class="diff-file file-holder">
+ <div :class="{ 'text-file': isTextFile }" class="diff-file file-holder">
<diff-file-header
:discussion-path="discussion.discussion_path"
:diff-file="discussion.diff_file"
:can-current-user-fork="false"
- :expanded="!discussion.diff_file.collapsed"
+ :expanded="!discussion.diff_file.viewer.collapsed"
/>
- <div
- v-if="discussion.diff_file.text"
- :class="$options.userColorSchemeClass"
- class="diff-content code"
- >
+ <div v-if="isTextFile" :class="$options.userColorSchemeClass" class="diff-content code">
<table>
<template v-if="hasTruncatedDiffLines">
<tr
@@ -85,7 +83,7 @@ export default {
>
<td class="diff-line-num old_line">{{ line.old_line }}</td>
<td class="diff-line-num new_line">{{ line.new_line }}</td>
- <td :class="line.type" class="line_content" v-html="trimChar(line.rich_text)"></td>
+ <td :class="line.type" class="line_content" v-html="line.rich_text"></td>
</tr>
</template>
<tr v-if="!hasTruncatedDiffLines" class="line_holder line-holder-placeholder">
@@ -114,6 +112,7 @@ export default {
<div v-else>
<diff-viewer
:diff-mode="diffMode"
+ :diff-viewer-mode="diffViewerMode"
:new-path="discussion.diff_file.new_path"
:new-sha="discussion.diff_file.diff_refs.head_sha"
:old-path="discussion.diff_file.old_path"
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index 86c114a761a..31164f74201 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -1,8 +1,15 @@
<script>
import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
+import { getLocationHash } from '../../lib/utils/url_utility';
import Icon from '~/vue_shared/components/icon.vue';
-import { DISCUSSION_FILTERS_DEFAULT_VALUE, HISTORY_ONLY_FILTER_VALUE } from '../constants';
+import {
+ DISCUSSION_FILTERS_DEFAULT_VALUE,
+ HISTORY_ONLY_FILTER_VALUE,
+ DISCUSSION_TAB_LABEL,
+ DISCUSSION_FILTER_TYPES,
+} from '../constants';
+import notesEventHub from '../event_hub';
export default {
components: {
@@ -23,6 +30,7 @@ export default {
return {
currentValue: this.selectedValue,
defaultValue: DISCUSSION_FILTERS_DEFAULT_VALUE,
+ displayFilters: true,
};
},
computed: {
@@ -32,31 +40,73 @@ export default {
return this.filters.find(filter => filter.value === this.currentValue);
},
},
+ created() {
+ if (window.mrTabs) {
+ const { eventHub, currentTab } = window.mrTabs;
+
+ eventHub.$on('MergeRequestTabChange', this.toggleFilters);
+ this.toggleFilters(currentTab);
+ }
+
+ notesEventHub.$on('dropdownSelect', this.selectFilter);
+ window.addEventListener('hashchange', this.handleLocationHash);
+ this.handleLocationHash();
+ },
mounted() {
this.toggleCommentsForm();
},
+ destroyed() {
+ notesEventHub.$off('dropdownSelect', this.selectFilter);
+ window.removeEventListener('hashchange', this.handleLocationHash);
+ },
methods: {
- ...mapActions(['filterDiscussion', 'setCommentsDisabled']),
+ ...mapActions(['filterDiscussion', 'setCommentsDisabled', 'setTargetNoteHash']),
selectFilter(value) {
const filter = parseInt(value, 10);
// close dropdown
- $(this.$refs.dropdownToggle).dropdown('toggle');
+ this.toggleDropdown();
if (filter === this.currentValue) return;
this.currentValue = filter;
this.filterDiscussion({ path: this.getNotesDataByProp('discussionsPath'), filter });
this.toggleCommentsForm();
},
+ toggleDropdown() {
+ $(this.$refs.dropdownToggle).dropdown('toggle');
+ },
toggleCommentsForm() {
this.setCommentsDisabled(this.currentValue === HISTORY_ONLY_FILTER_VALUE);
},
+ toggleFilters(tab) {
+ this.displayFilters = tab === DISCUSSION_TAB_LABEL;
+ },
+ handleLocationHash() {
+ const hash = getLocationHash();
+
+ if (/^note_/.test(hash) && this.currentValue !== DISCUSSION_FILTERS_DEFAULT_VALUE) {
+ this.selectFilter(this.defaultValue);
+ this.toggleDropdown(); // close dropdown
+ this.setTargetNoteHash(hash);
+ }
+ },
+ filterType(value) {
+ if (value === 0) {
+ return DISCUSSION_FILTER_TYPES.ALL;
+ } else if (value === 1) {
+ return DISCUSSION_FILTER_TYPES.COMMENTS;
+ }
+ return DISCUSSION_FILTER_TYPES.HISTORY;
+ },
},
};
</script>
<template>
- <div class="discussion-filter-container d-inline-block align-bottom">
+ <div
+ v-if="displayFilters"
+ class="discussion-filter-container js-discussion-filter-container d-inline-block align-bottom"
+ >
<button
id="discussion-filter-dropdown"
ref="dropdownToggle"
@@ -67,17 +117,22 @@ export default {
{{ currentFilter.title }} <icon name="chevron-down" />
</button>
<div
+ ref="dropdownMenu"
class="dropdown-menu dropdown-menu-selectable dropdown-menu-right"
aria-labelledby="discussion-filter-dropdown"
>
<div class="dropdown-content">
<ul>
- <li v-for="filter in filters" :key="filter.value">
+ <li
+ v-for="filter in filters"
+ :key="filter.value"
+ :data-filter-type="filterType(filter.value)"
+ >
<button
:class="{ 'is-active': filter.value === currentValue }"
class="qa-filter-options"
type="button"
- @click="selectFilter(filter.value);"
+ @click="selectFilter(filter.value)"
>
{{ filter.title }}
</button>
diff --git a/app/assets/javascripts/notes/components/discussion_filter_note.vue b/app/assets/javascripts/notes/components/discussion_filter_note.vue
new file mode 100644
index 00000000000..46661e06f6d
--- /dev/null
+++ b/app/assets/javascripts/notes/components/discussion_filter_note.vue
@@ -0,0 +1,52 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+import { __, sprintf } from '~/locale';
+
+import notesEventHub from '../event_hub';
+
+export default {
+ components: {
+ GlButton,
+ Icon,
+ },
+ computed: {
+ timelineContent() {
+ return sprintf(
+ __(
+ "You're only seeing %{startTag}other activity%{endTag} in the feed. To add a comment, switch to one of the following options.",
+ ),
+ {
+ startTag: `<b>`,
+ endTag: `</b>`,
+ },
+ false,
+ );
+ },
+ },
+ methods: {
+ selectFilter(value) {
+ notesEventHub.$emit('dropdownSelect', value);
+ },
+ },
+};
+</script>
+
+<template>
+ <li class="timeline-entry note note-wrapper discussion-filter-note js-discussion-filter-note">
+ <div class="timeline-icon">
+ <icon name="comment" />
+ </div>
+ <div class="timeline-content">
+ <div v-html="timelineContent"></div>
+ <div class="discussion-filter-actions mt-2">
+ <gl-button variant="default" @click="selectFilter(0)">
+ {{ __('Show all activity') }}
+ </gl-button>
+ <gl-button variant="default" @click="selectFilter(1)">
+ {{ __('Show comments only') }}
+ </gl-button>
+ </div>
+ </div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue b/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue
new file mode 100644
index 00000000000..07a5bda6bcb
--- /dev/null
+++ b/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue
@@ -0,0 +1,28 @@
+<script>
+import icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective } from '@gitlab/ui';
+
+export default {
+ name: 'JumpToNextDiscussionButton',
+ components: {
+ icon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+};
+</script>
+
+<template>
+ <div class="btn-group" role="group">
+ <button
+ ref="button"
+ v-gl-tooltip
+ class="btn btn-default discussion-next-btn"
+ :title="s__('MergeRequests|Jump to next unresolved discussion')"
+ @click="$emit('onClick')"
+ >
+ <icon name="comment-next" />
+ </button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/discussion_reply_placeholder.vue b/app/assets/javascripts/notes/components/discussion_reply_placeholder.vue
new file mode 100644
index 00000000000..ea590905e3c
--- /dev/null
+++ b/app/assets/javascripts/notes/components/discussion_reply_placeholder.vue
@@ -0,0 +1,17 @@
+<script>
+export default {
+ name: 'ReplyPlaceholder',
+};
+</script>
+
+<template>
+ <button
+ ref="button"
+ type="button"
+ class="js-vue-discussion-reply btn btn-text-field"
+ :title="s__('MergeRequests|Add a reply')"
+ @click="$emit('onClick')"
+ >
+ {{ s__('MergeRequests|Reply...') }}
+ </button>
+</template>
diff --git a/app/assets/javascripts/notes/components/discussion_resolve_button.vue b/app/assets/javascripts/notes/components/discussion_resolve_button.vue
new file mode 100644
index 00000000000..2b29d710236
--- /dev/null
+++ b/app/assets/javascripts/notes/components/discussion_resolve_button.vue
@@ -0,0 +1,28 @@
+<script>
+export default {
+ name: 'ResolveDiscussionButton',
+ props: {
+ isResolving: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ buttonTitle: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <button ref="button" type="button" class="btn btn-default ml-sm-2" @click="$emit('onClick')">
+ <i
+ v-if="isResolving"
+ ref="isResolvingIcon"
+ aria-hidden="true"
+ class="fa fa-spinner fa-spin"
+ ></i>
+ {{ buttonTitle }}
+ </button>
+</template>
diff --git a/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue b/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue
new file mode 100644
index 00000000000..e413398696a
--- /dev/null
+++ b/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue
@@ -0,0 +1,34 @@
+<script>
+import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlButton } from '@gitlab/ui';
+
+export default {
+ name: 'ResolveWithIssueButton',
+ components: {
+ Icon,
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ url: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="btn-group" role="group">
+ <gl-button
+ v-gl-tooltip
+ :href="url"
+ :title="s__('MergeRequests|Resolve this discussion in a new issue')"
+ class="new-issue-for-discussion discussion-create-issue-btn"
+ >
+ <icon name="issue-new" />
+ </gl-button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index d99694b06e9..de1ea0f58d6 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -2,11 +2,13 @@
import { mapGetters } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
+import ReplyButton from './note_actions/reply_button.vue';
export default {
name: 'NoteActions',
components: {
Icon,
+ ReplyButton,
GlLoadingIcon,
},
directives: {
@@ -36,6 +38,10 @@ export default {
required: false,
default: null,
},
+ showReply: {
+ type: Boolean,
+ required: true,
+ },
canEdit: {
type: Boolean,
required: true,
@@ -80,6 +86,9 @@ export default {
},
computed: {
...mapGetters(['getUserDataByProp']),
+ showReplyButton() {
+ return gon.features && gon.features.replyToIndividualNotes && this.showReply;
+ },
shouldShowActionsDropdown() {
return this.currentUserId && (this.canEdit || this.canReportAsAbuse);
},
@@ -112,6 +121,11 @@ export default {
onResolve() {
this.$emit('handleResolve');
},
+ closeTooltip() {
+ this.$nextTick(() => {
+ this.$root.$emit('bv::hide::tooltip');
+ });
+ },
},
};
</script>
@@ -121,6 +135,7 @@ export default {
<span v-if="accessLevel" class="note-role user-access-role">{{ accessLevel }}</span>
<div v-if="canResolve" class="note-actions-item">
<button
+ ref="resolveButton"
v-gl-tooltip
:class="{ 'is-disabled': !resolvable, 'is-active': isResolved }"
:title="resolveButtonTitle"
@@ -137,10 +152,9 @@ export default {
</div>
<div v-if="canAwardEmoji" class="note-actions-item">
<a
- v-gl-tooltip.bottom
+ v-gl-tooltip
:class="{ 'js-user-authored': isAuthoredByCurrentUser }"
class="note-action-button note-emoji-button js-add-award js-note-emoji"
- data-position="right"
href="#"
title="Add reaction"
>
@@ -153,9 +167,15 @@ export default {
<icon css-classes="link-highlight award-control-icon-super-positive" name="emoji_smiley" />
</a>
</div>
+ <reply-button
+ v-if="showReplyButton"
+ ref="replyButton"
+ class="js-reply-button"
+ @startReplying="$emit('startReplying')"
+ />
<div v-if="canEdit" class="note-actions-item">
<button
- v-gl-tooltip.bottom
+ v-gl-tooltip
type="button"
title="Edit comment"
class="note-action-button js-note-edit btn btn-transparent"
@@ -166,7 +186,7 @@ export default {
</div>
<div v-if="showDeleteAction" class="note-actions-item">
<button
- v-gl-tooltip.bottom
+ v-gl-tooltip
type="button"
title="Delete comment"
class="note-action-button js-note-delete btn btn-transparent"
@@ -177,11 +197,12 @@ export default {
</div>
<div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions note-actions-item">
<button
- v-gl-tooltip.bottom
+ v-gl-tooltip
type="button"
title="More actions"
class="note-action-button more-actions-toggle btn btn-transparent"
data-toggle="dropdown"
+ @click="closeTooltip"
>
<icon css-classes="icon" name="ellipsis_v" />
</button>
diff --git a/app/assets/javascripts/notes/components/note_actions/reply_button.vue b/app/assets/javascripts/notes/components/note_actions/reply_button.vue
new file mode 100644
index 00000000000..f50cab81efe
--- /dev/null
+++ b/app/assets/javascripts/notes/components/note_actions/reply_button.vue
@@ -0,0 +1,30 @@
+<script>
+import { GlTooltipDirective, GlButton } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ name: 'ReplyButton',
+ components: {
+ Icon,
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+};
+</script>
+
+<template>
+ <div class="note-actions-item">
+ <gl-button
+ ref="button"
+ v-gl-tooltip.bottom
+ class="note-action-button"
+ variant="transparent"
+ :title="__('Reply to comment')"
+ @click="$emit('startReplying')"
+ >
+ <icon name="comment" css-classes="link-highlight" />
+ </gl-button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue
index 3d60eb02db8..17e5fcab5b7 100644
--- a/app/assets/javascripts/notes/components/note_awards_list.vue
+++ b/app/assets/javascripts/notes/components/note_awards_list.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters } from 'vuex';
-import { GlTooltipDirective } from '@gitlab/ui';
+import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import Flash from '../../flash';
import { glEmojiTag } from '../../emoji';
@@ -10,7 +10,7 @@ export default {
Icon,
},
directives: {
- GlTooltip: GlTooltipDirective,
+ tooltip,
},
props: {
awards: {
@@ -167,25 +167,25 @@ export default {
<button
v-for="(awardList, awardName, index) in groupedAwards"
:key="index"
- v-gl-tooltip.bottom="{ boundary: 'viewport' }"
+ v-tooltip
:class="getAwardClassBindings(awardList)"
:title="awardTitle(awardList)"
+ data-boundary="viewport"
class="btn award-control"
type="button"
- @click="handleAward(awardName);"
+ @click="handleAward(awardName)"
>
<span v-html="getAwardHTML(awardName)"></span>
<span class="award-control-text js-counter">{{ awardList.length }}</span>
</button>
<div v-if="canAwardEmoji" class="award-menu-holder">
<button
- v-gl-tooltip
+ v-tooltip
:class="{ 'js-user-authored': isAuthoredByMe }"
class="award-control btn js-add-award"
title="Add reaction"
aria-label="Add reaction"
data-boundary="viewport"
- data-placement="bottom"
type="button"
>
<span class="award-control-icon award-control-icon-neutral">
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index bcf5d334da4..fb1d98355b3 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -95,6 +95,7 @@ export default {
<div ref="note-body" :class="{ 'js-task-list-container': canEdit }" class="note-body">
<suggestions
v-if="hasSuggestion && !isEditing"
+ class="note-text md"
:suggestions="note.suggestions"
:note-html="note.note_html"
:line-type="lineType"
@@ -111,7 +112,6 @@ export default {
:line="line"
:note="note"
:help-page-path="helpPagePath"
- :markdown-version="note.cached_markdown_version"
@handleFormUpdate="handleFormUpdate"
@cancelForm="formCancelHandler"
/>
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 9b7f3d3588d..92258a25438 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -6,6 +6,7 @@ import issueWarning from '../../vue_shared/components/issue/issue_warning.vue';
import markdownField from '../../vue_shared/components/markdown/field.vue';
import issuableStateMixin from '../mixins/issuable_state';
import resolvable from '../mixins/resolvable';
+import { __ } from '~/locale';
export default {
name: 'NoteForm',
@@ -25,15 +26,10 @@ export default {
required: false,
default: '',
},
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
saveButtonTitle: {
type: String,
required: false,
- default: 'Save comment',
+ default: __('Save comment'),
},
discussion: {
type: Object,
@@ -149,6 +145,9 @@ export default {
return shouldResolve || shouldToggleState;
},
+ handleKeySubmit() {
+ this.handleUpdate();
+ },
handleUpdate(shouldResolve) {
const beforeSubmitDiscussionState = this.discussionResolved;
this.isSubmitting = true;
@@ -198,7 +197,6 @@ export default {
<markdown-field
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath"
- :markdown-version="markdownVersion"
:quick-actions-docs-path="quickActionsDocsPath"
:line="line"
:note="discussionNote"
@@ -216,32 +214,32 @@ export default {
class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form js-vue-textarea qa-reply-input"
aria-label="Description"
placeholder="Write a comment or drag your files here…"
- @keydown.meta.enter="handleUpdate();"
- @keydown.ctrl.enter="handleUpdate();"
- @keydown.up="editMyLastNote();"
- @keydown.esc="cancelHandler(true);"
+ @keydown.meta.enter="handleKeySubmit()"
+ @keydown.ctrl.enter="handleKeySubmit()"
+ @keydown.up="editMyLastNote()"
+ @keydown.esc="cancelHandler(true)"
></textarea>
</markdown-field>
<div class="note-form-actions clearfix">
<button
:disabled="isDisabled"
type="button"
- class="js-vue-issue-save btn btn-success js-comment-button"
- @click="handleUpdate();"
+ class="js-vue-issue-save btn btn-success js-comment-button qa-reply-comment-button"
+ @click="handleUpdate()"
>
{{ saveButtonTitle }}
</button>
<button
v-if="discussion.resolvable"
class="btn btn-nr btn-default append-right-10 js-comment-resolve-button"
- @click.prevent="handleUpdate(true);"
+ @click.prevent="handleUpdate(true)"
>
{{ resolveButtonTitle }}
</button>
<button
class="btn btn-cancel note-edit-cancel js-close-discussion-note-form"
type="button"
- @click="cancelHandler();"
+ @click="cancelHandler()"
>
Cancel
</button>
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index 7b39901024d..68b753a4abf 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -69,7 +69,7 @@ export default {
type="button"
@click="handleToggle"
>
- <i :class="toggleChevronClass" class="fa" aria-hidden="true"> </i>
+ <i :class="toggleChevronClass" class="fa" aria-hidden="true"></i>
{{ __('Toggle discussion') }}
</button>
</div>
@@ -81,19 +81,18 @@ export default {
:data-user-id="author.id"
:data-username="author.username"
>
+ <slot name="note-header-info"></slot>
<span class="note-header-author-name">{{ author.name }}</span>
<span v-if="author.status_tooltip_html" v-html="author.status_tooltip_html"></span>
- <span class="note-headline-light"> @{{ author.username }} </span>
+ <span class="note-headline-light">@{{ author.username }}</span>
</a>
- <span v-else> {{ __('A deleted user') }} </span>
+ <span v-else>{{ __('A deleted user') }}</span>
<span class="note-headline-light">
<span class="note-headline-meta">
<span class="system-note-message"> <slot></slot> </span>
<template v-if="createdAt">
<span class="system-note-separator">
- <template v-if="actionText">
- {{ actionText }}
- </template>
+ <template v-if="actionText">{{ actionText }}</template>
</span>
<a
:href="noteTimestampLink"
@@ -107,8 +106,7 @@ export default {
class="fa fa-spinner fa-spin editing-spinner"
aria-label="Comment is being updated"
aria-hidden="true"
- >
- </i>
+ ></i>
</span>
</span>
</div>
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index 7c3f5d00308..fc51998935d 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -6,12 +6,14 @@ import { truncateSha } from '~/lib/utils/text_utility';
import { s__, __, sprintf } from '~/locale';
import systemNote from '~/vue_shared/components/notes/system_note.vue';
import icon from '~/vue_shared/components/icon.vue';
+import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import Flash from '../../flash';
import { SYSTEM_NOTE } from '../constants';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import noteableNote from './noteable_note.vue';
import noteHeader from './note_header.vue';
+import resolveDiscussionButton from './discussion_resolve_button.vue';
import toggleRepliesWidget from './toggle_replies_widget.vue';
import noteSignedOutWidget from './note_signed_out_widget.vue';
import noteEditedText from './note_edited_text.vue';
@@ -23,6 +25,10 @@ import autosave from '../mixins/autosave';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
import discussionNavigation from '../mixins/discussion_navigation';
+import ReplyPlaceholder from './discussion_reply_placeholder.vue';
+import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue';
+import jumpToNextDiscussionButton from './discussion_jump_to_next_button.vue';
+import eventHub from '../event_hub';
export default {
name: 'NoteableDiscussion',
@@ -34,16 +40,21 @@ export default {
noteSignedOutWidget,
noteEditedText,
noteForm,
+ resolveDiscussionButton,
+ jumpToNextDiscussionButton,
toggleRepliesWidget,
+ ReplyPlaceholder,
placeholderNote,
placeholderSystemNote,
+ ResolveWithIssueButton,
systemNote,
+ DraftNote: () => import('ee_component/batch_comments/components/draft_note.vue'),
TimelineEntryItem,
},
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [autosave, noteable, resolvable, discussionNavigation],
+ mixins: [autosave, noteable, resolvable, discussionNavigation, diffLineNoteFormMixin],
props: {
discussion: {
type: Object,
@@ -87,6 +98,7 @@ export default {
},
computed: {
...mapGetters([
+ 'convertedDisscussionIds',
'getNoteableData',
'nextUnresolvedDiscussionId',
'unresolvedDiscussionsCount',
@@ -206,11 +218,28 @@ export default {
return sprintf(text, { commitId, linkStart, linkEnd }, false);
},
diffLine() {
+ if (this.line) {
+ return this.line;
+ }
+
if (this.discussion.diff_discussion && this.discussion.truncated_diff_lines) {
return this.discussion.truncated_diff_lines.slice(-1)[0];
}
- return this.line;
+ return null;
+ },
+ commit() {
+ if (!this.discussion.for_commit) {
+ return null;
+ }
+
+ return {
+ id: this.discussion.commit_id,
+ url: this.discussion.discussion_path,
+ };
+ },
+ resolveWithIssuePath() {
+ return !this.discussionResolved && this.discussion.resolve_with_issue_path;
},
},
watch: {
@@ -225,6 +254,12 @@ export default {
}
},
},
+ created() {
+ eventHub.$on('startReplying', this.onStartReplying);
+ },
+ beforeDestroy() {
+ eventHub.$off('startReplying', this.onStartReplying);
+ },
methods: {
...mapActions([
'saveNote',
@@ -232,6 +267,7 @@ export default {
'removePlaceholderNotes',
'toggleResolveNote',
'expandDiscussion',
+ 'removeConvertedDiscussion',
]),
truncateSha,
componentName(note) {
@@ -271,6 +307,10 @@ export default {
}
}
+ if (this.convertedDisscussionIds.includes(this.discussion.id)) {
+ this.removeConvertedDiscussion(this.discussion.id);
+ }
+
this.isReplying = false;
this.resetAutoSave();
},
@@ -281,6 +321,10 @@ export default {
note: { note: noteText },
};
+ if (this.convertedDisscussionIds.includes(this.discussion.id)) {
+ postData.return_discussion = true;
+ }
+
if (this.discussion.for_commit) {
postData.note_project_id = this.discussion.project_id;
}
@@ -320,6 +364,11 @@ Please check your network connection and try again.`;
deleteNoteHandler(note) {
this.$emit('noteDeleted', this.discussion, note);
},
+ onStartReplying(discussionId) {
+ if (this.discussion.id === discussionId) {
+ this.showReplyForm();
+ }
+ },
},
};
</script>
@@ -338,30 +387,32 @@ Please check your network connection and try again.`;
:img-size="40"
/>
</div>
- <note-header
- :author="author"
- :created-at="initialDiscussion.created_at"
- :note-id="initialDiscussion.id"
- :include-toggle="true"
- :expanded="discussion.expanded"
- @toggleHandler="toggleDiscussionHandler"
- >
- <span v-html="actionText"></span>
- </note-header>
- <note-edited-text
- v-if="discussion.resolved"
- :edited-at="discussion.resolved_at"
- :edited-by="discussion.resolved_by"
- :action-text="resolvedText"
- class-name="discussion-headline-light js-discussion-headline"
- />
- <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"
- />
+ <div class="timeline-content">
+ <note-header
+ :author="author"
+ :created-at="initialDiscussion.created_at"
+ :note-id="initialDiscussion.id"
+ :include-toggle="true"
+ :expanded="discussion.expanded"
+ @toggleHandler="toggleDiscussionHandler"
+ >
+ <span v-html="actionText"></span>
+ </note-header>
+ <note-edited-text
+ v-if="discussion.resolved"
+ :edited-at="discussion.resolved_at"
+ :edited-by="discussion.resolved_by"
+ :action-text="resolvedText"
+ class-name="discussion-headline-light js-discussion-headline"
+ />
+ <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"
+ />
+ </div>
</div>
<div v-if="shouldShowDiscussions" class="discussion-body">
<component
@@ -376,8 +427,11 @@ Please check your network connection and try again.`;
:is="componentName(initialDiscussion)"
:note="componentData(initialDiscussion)"
:line="line"
+ :commit="commit"
:help-page-path="helpPagePath"
+ :show-reply-button="canReply"
@handleDeleteNote="deleteNoteHandler"
+ @startReplying="showReplyForm"
>
<note-edited-text
v-if="discussion.resolved"
@@ -428,49 +482,26 @@ Please check your network connection and try again.`;
>
<template v-if="!isReplying && canReply">
<div class="discussion-with-resolve-btn">
- <button
- type="button"
- class="js-vue-discussion-reply btn btn-text-field qa-discussion-reply"
- title="Add a reply"
- @click="showReplyForm"
- >
- Reply...
- </button>
- <div v-if="discussion.resolvable">
- <button
- type="button"
- class="btn btn-default ml-sm-2"
- @click="resolveHandler();"
- >
- <i v-if="isResolving" aria-hidden="true" class="fa fa-spinner fa-spin"></i>
- {{ resolveButtonTitle }}
- </button>
- </div>
+ <reply-placeholder class="qa-discussion-reply" @onClick="showReplyForm" />
+ <resolve-discussion-button
+ v-if="discussion.resolvable"
+ :is-resolving="isResolving"
+ :button-title="resolveButtonTitle"
+ @onClick="resolveHandler"
+ />
<div
v-if="discussion.resolvable"
class="btn-group discussion-actions ml-sm-2"
role="group"
>
- <div v-if="!discussionResolved" class="btn-group" role="group">
- <a
- v-gl-tooltip
- :href="discussion.resolve_with_issue_path"
- :title="s__('MergeRequests|Resolve this discussion in a new issue')"
- class="new-issue-for-discussion btn btn-default discussion-create-issue-btn"
- >
- <icon name="issue-new" />
- </a>
- </div>
- <div v-if="shouldShowJumpToNextDiscussion" class="btn-group" role="group">
- <button
- v-gl-tooltip
- class="btn btn-default discussion-next-btn"
- title="Jump to next unresolved discussion"
- @click="jumpToNextDiscussion"
- >
- <icon name="comment-next" />
- </button>
- </div>
+ <resolve-with-issue-button
+ v-if="resolveWithIssuePath"
+ :url="resolveWithIssuePath"
+ />
+ <jump-to-next-discussion-button
+ v-if="shouldShowJumpToNextDiscussion"
+ @onClick="jumpToNextDiscussion"
+ />
</div>
</div>
</template>
@@ -481,6 +512,7 @@ Please check your network connection and try again.`;
:is-editing="false"
:line="diffLine"
save-button-title="Comment"
+ @handleFormUpdateAddToReview="addReplyToReview"
@handleFormUpdate="saveReply"
@cancelForm="cancelReplyForm"
/>
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 4c02588127e..5fa0ab3de98 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -2,7 +2,9 @@
import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
import { escape } from 'underscore';
+import { truncateSha } from '~/lib/utils/text_utility';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
+import { s__, sprintf } from '../../locale';
import Flash from '../../flash';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import noteHeader from './note_header.vue';
@@ -37,6 +39,16 @@ export default {
required: false,
default: '',
},
+ commit: {
+ type: Object,
+ required: false,
+ default: () => null,
+ },
+ showReplyButton: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -47,7 +59,7 @@ export default {
};
},
computed: {
- ...mapGetters(['targetNoteHash', 'getNoteableData', 'getUserData']),
+ ...mapGetters(['targetNoteHash', 'getNoteableData', 'getUserData', 'commentsDisabled']),
author() {
return this.note.author;
},
@@ -73,6 +85,27 @@ export default {
isTarget() {
return this.targetNoteHash === this.noteAnchorId;
},
+ discussionId() {
+ if (this.discussion) {
+ return this.discussion.id;
+ }
+ return '';
+ },
+ actionText() {
+ if (!this.commit) {
+ return '';
+ }
+
+ // We need to do this to ensure we have the currect sentence order
+ // when translating this as the sentence order may change from one
+ // language to the next. See:
+ // https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24427#note_133713771
+ const { id, url } = this.commit;
+ const commitLink = `<a class="commit-sha monospace" href="${escape(url)}">${truncateSha(
+ id,
+ )}</a>`;
+ return sprintf(s__('MergeRequests|commented on commit %{commitLink}'), { commitLink }, false);
+ },
},
created() {
@@ -186,7 +219,7 @@ export default {
:class="classNameBindings"
:data-award-url="note.toggle_award_path"
:data-note-id="note.id"
- class="note note-wrapper"
+ class="note note-wrapper qa-noteable-note-item"
>
<div v-once class="timeline-icon">
<user-avatar-link
@@ -200,18 +233,16 @@ export default {
</div>
<div class="timeline-content">
<div class="note-header">
- <note-header
- v-once
- :author="author"
- :created-at="note.created_at"
- :note-id="note.id"
- action-text="commented"
- />
+ <note-header v-once :author="author" :created-at="note.created_at" :note-id="note.id">
+ <span v-if="commit" v-html="actionText"></span>
+ <span v-else class="d-none d-sm-inline">&middot;</span>
+ </note-header>
<note-actions
:author-id="author.id"
:note-id="note.id"
:note-url="note.noteable_note_url"
:access-level="note.human_access"
+ :show-reply="showReplyButton"
:can-edit="note.current_user.can_edit"
:can-award-emoji="note.current_user.can_award_emoji"
:can-delete="note.current_user.can_edit"
@@ -225,6 +256,7 @@ export default {
@handleEdit="editHandler"
@handleDelete="deleteHandler"
@handleResolve="resolveHandler"
+ @startReplying="$emit('startReplying')"
/>
</div>
<div class="timeline-discussion-body">
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index f3fcfdfda05..e2bd59f7631 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -6,6 +6,7 @@ import * as constants from '../constants';
import eventHub from '../event_hub';
import noteableNote from './noteable_note.vue';
import noteableDiscussion from './noteable_discussion.vue';
+import discussionFilterNote from './discussion_filter_note.vue';
import systemNote from '../../vue_shared/components/notes/system_note.vue';
import commentForm from './comment_form.vue';
import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
@@ -24,6 +25,7 @@ export default {
placeholderNote,
placeholderSystemNote,
skeletonLoadingContainer,
+ discussionFilterNote,
},
props: {
noteableData: {
@@ -44,11 +46,6 @@ export default {
required: false,
default: true,
},
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
helpPagePath: {
type: String,
required: false,
@@ -65,9 +62,11 @@ export default {
...mapGetters([
'isNotesFetched',
'discussions',
+ 'convertedDisscussionIds',
'getNotesDataByProp',
'isLoading',
'commentsDisabled',
+ 'getNoteableData',
]),
noteableType() {
return this.noteableData.noteableType;
@@ -83,6 +82,9 @@ export default {
return this.discussions;
},
+ canReply() {
+ return this.getNoteableData.current_user.can_create_note && !this.commentsDisabled;
+ },
},
watch: {
shouldShow() {
@@ -90,8 +92,15 @@ export default {
this.fetchNotes();
}
},
+ allDiscussions() {
+ if (this.discussonsCount) {
+ this.discussonsCount.textContent = this.allDiscussions.length;
+ }
+ },
},
created() {
+ this.discussonsCount = document.querySelector('.js-discussions-count');
+
this.setNotesData(this.notesData);
this.setNoteableData(this.noteableData);
this.setUserData(this.userData);
@@ -133,6 +142,7 @@ export default {
'setNotesFetchedState',
'expandDiscussion',
'startTaskList',
+ 'convertToDiscussion',
]),
fetchNotes() {
if (this.isFetching) return null;
@@ -180,6 +190,11 @@ export default {
}
}
},
+ startReplying(discussionId) {
+ return this.convertToDiscussion(discussionId)
+ .then(() => this.$nextTick())
+ .then(() => eventHub.$emit('startReplying', discussionId));
+ },
},
systemNote: constants.SYSTEM_NOTE,
};
@@ -198,13 +213,21 @@ export default {
/>
<placeholder-note v-else :key="discussion.id" :note="discussion.notes[0]" />
</template>
- <template v-else-if="discussion.individual_note">
+ <template
+ v-else-if="discussion.individual_note && !convertedDisscussionIds.includes(discussion.id)"
+ >
<system-note
v-if="discussion.notes[0].system"
:key="discussion.id"
:note="discussion.notes[0]"
/>
- <noteable-note v-else :key="discussion.id" :note="discussion.notes[0]" />
+ <noteable-note
+ v-else
+ :key="discussion.id"
+ :note="discussion.notes[0]"
+ :show-reply-button="canReply"
+ @startReplying="startReplying(discussion.id)"
+ />
</template>
<noteable-discussion
v-else
@@ -214,12 +237,9 @@ export default {
:help-page-path="helpPagePath"
/>
</template>
+ <discussion-filter-note v-show="commentsDisabled" />
</ul>
- <comment-form
- v-if="!commentsDisabled"
- :noteable-type="noteableType"
- :markdown-version="markdownVersion"
- />
+ <comment-form v-if="!commentsDisabled" :noteable-type="noteableType" />
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
index 72a8ff28466..f1b0b12bdce 100644
--- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue
+++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
@@ -57,7 +57,7 @@ export default {
tooltip-placement="bottom"
/>
</div>
- <button class="btn btn-link js-replies-text" type="button" @click="toggle">
+ <button class="btn btn-link js-replies-text qa-expand-replies" type="button" @click="toggle">
{{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
</button>
{{ __('Last reply by') }}
@@ -66,7 +66,11 @@ export default {
</a>
<time-ago-tooltip :time="lastReply.created_at" tooltip-placement="bottom" />
</template>
- <span v-else class="collapse-replies-btn js-collapse-replies" @click="toggle">
+ <span
+ v-else
+ class="collapse-replies-btn js-collapse-replies qa-collapse-replies"
+ @click="toggle"
+ >
<icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}
</span>
</li>
diff --git a/app/assets/javascripts/notes/constants.js b/app/assets/javascripts/notes/constants.js
index 3147dc64c27..fba3db8542c 100644
--- a/app/assets/javascripts/notes/constants.js
+++ b/app/assets/javascripts/notes/constants.js
@@ -17,9 +17,16 @@ export const RESOLVE_NOTE_METHOD_NAME = 'post';
export const DESCRIPTION_TYPE = 'changed the description';
export const HISTORY_ONLY_FILTER_VALUE = 2;
export const DISCUSSION_FILTERS_DEFAULT_VALUE = 0;
+export const DISCUSSION_TAB_LABEL = 'show';
export const NOTEABLE_TYPE_MAPPING = {
Issue: ISSUE_NOTEABLE_TYPE,
MergeRequest: MERGE_REQUEST_NOTEABLE_TYPE,
Epic: EPIC_NOTEABLE_TYPE,
};
+
+export const DISCUSSION_FILTER_TYPES = {
+ ALL: 'all',
+ COMMENTS: 'comments',
+ HISTORY: 'history',
+};
diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js
index 2f715c85fa6..4883266dae5 100644
--- a/app/assets/javascripts/notes/index.js
+++ b/app/assets/javascripts/notes/index.js
@@ -18,7 +18,6 @@ document.addEventListener('DOMContentLoaded', () => {
const notesDataset = document.getElementById('js-vue-notes').dataset;
const parsedUserData = JSON.parse(notesDataset.currentUserData);
const noteableData = JSON.parse(notesDataset.noteableData);
- const markdownVersion = parseInt(notesDataset.markdownVersion, 10);
let currentUserData = {};
noteableData.noteableType = notesDataset.noteableType;
@@ -37,7 +36,6 @@ document.addEventListener('DOMContentLoaded', () => {
return {
noteableData,
currentUserData,
- markdownVersion,
notesData: JSON.parse(notesDataset.notesData),
};
},
@@ -47,7 +45,6 @@ document.addEventListener('DOMContentLoaded', () => {
noteableData: this.noteableData,
notesData: this.notesData,
userData: this.currentUserData,
- markdownVersion: this.markdownVersion,
},
});
},
diff --git a/app/assets/javascripts/notes/mixins/diff_line_note_form.js b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
new file mode 100644
index 00000000000..188556e8921
--- /dev/null
+++ b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
@@ -0,0 +1,10 @@
+export default {
+ computed: {
+ draftForDiscussion: () => () => ({}),
+ },
+ methods: {
+ showDraft: () => false,
+ addReplyToReview: () => {},
+ addToReview: () => {},
+ },
+};
diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js
index 8edf3d088bb..2329727bca2 100644
--- a/app/assets/javascripts/notes/mixins/resolvable.js
+++ b/app/assets/javascripts/notes/mixins/resolvable.js
@@ -31,6 +31,10 @@ export default {
},
methods: {
resolveHandler(resolvedState = false) {
+ if (this.note && this.note.isDraft) {
+ return this.$emit('toggleResolveStatus');
+ }
+
this.isResolving = true;
const isResolved = this.discussionResolved || resolvedState;
const discussion = this.resolveAsThread;
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index 65f85314fa0..1a0dba69a7c 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -83,12 +83,44 @@ export const updateNote = ({ commit, dispatch }, { endpoint, note }) =>
dispatch('startTaskList');
});
-export const replyToDiscussion = ({ commit }, { endpoint, data }) =>
+export const updateOrCreateNotes = ({ commit, state, getters, dispatch }, notes) => {
+ const { notesById } = getters;
+
+ notes.forEach(note => {
+ if (notesById[note.id]) {
+ commit(types.UPDATE_NOTE, note);
+ } else if (note.type === constants.DISCUSSION_NOTE || note.type === constants.DIFF_NOTE) {
+ const discussion = utils.findNoteObjectById(state.discussions, note.discussion_id);
+
+ if (discussion) {
+ commit(types.ADD_NEW_REPLY_TO_DISCUSSION, note);
+ } else if (note.type === constants.DIFF_NOTE) {
+ dispatch('fetchDiscussions', { path: state.notesData.discussionsPath });
+ } else {
+ commit(types.ADD_NEW_NOTE, note);
+ }
+ } else {
+ commit(types.ADD_NEW_NOTE, note);
+ }
+ });
+};
+
+export const replyToDiscussion = ({ commit, state, getters, dispatch }, { endpoint, data }) =>
service
.replyToDiscussion(endpoint, data)
.then(res => res.json())
.then(res => {
- commit(types.ADD_NEW_REPLY_TO_DISCUSSION, res);
+ if (res.discussion) {
+ commit(types.UPDATE_DISCUSSION, res.discussion);
+
+ updateOrCreateNotes({ commit, state, getters, dispatch }, res.discussion.notes);
+
+ dispatch('updateMergeRequestWidget');
+ dispatch('startTaskList');
+ dispatch('updateResolvableDiscussonsCounts');
+ } else {
+ commit(types.ADD_NEW_REPLY_TO_DISCUSSION, res);
+ }
return res;
});
@@ -262,25 +294,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
const pollSuccessCallBack = (resp, commit, state, getters, dispatch) => {
if (resp.notes && resp.notes.length) {
- const { notesById } = getters;
-
- resp.notes.forEach(note => {
- if (notesById[note.id]) {
- commit(types.UPDATE_NOTE, note);
- } else if (note.type === constants.DISCUSSION_NOTE || note.type === constants.DIFF_NOTE) {
- const discussion = utils.findNoteObjectById(state.discussions, note.discussion_id);
-
- if (discussion) {
- commit(types.ADD_NEW_REPLY_TO_DISCUSSION, note);
- } else if (note.type === constants.DIFF_NOTE) {
- dispatch('fetchDiscussions', { path: state.notesData.discussionsPath });
- } else {
- commit(types.ADD_NEW_NOTE, note);
- }
- } else {
- commit(types.ADD_NEW_NOTE, note);
- }
- });
+ updateOrCreateNotes({ commit, state, getters, dispatch }, resp.notes);
dispatch('startTaskList');
}
@@ -415,15 +429,22 @@ export const submitSuggestion = (
commit(types.APPLY_SUGGESTION, { discussionId, noteId, suggestionId });
callback();
})
- .catch(() => {
- Flash(
- __('Something went wrong while applying the suggestion. Please try again.'),
- 'alert',
- flashContainer,
+ .catch(err => {
+ const defaultMessage = __(
+ 'Something went wrong while applying the suggestion. Please try again.',
);
+ const flashMessage = err.response.data ? `${err.response.data.message}.` : defaultMessage;
+
+ Flash(__(flashMessage), 'alert', flashContainer);
callback();
});
};
+export const convertToDiscussion = ({ commit }, noteId) =>
+ commit(types.CONVERT_TO_DISCUSSION, noteId);
+
+export const removeConvertedDiscussion = ({ commit }, noteId) =>
+ commit(types.REMOVE_CONVERTED_DISCUSSION, noteId);
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js
index 0ffc0cb2593..fcc8889b0c7 100644
--- a/app/assets/javascripts/notes/stores/getters.js
+++ b/app/assets/javascripts/notes/stores/getters.js
@@ -4,6 +4,8 @@ import { collapseSystemNotes } from './collapse_utils';
export const discussions = state => collapseSystemNotes(state.discussions);
+export const convertedDisscussionIds = state => state.convertedDisscussionIds;
+
export const targetNoteHash = state => state.targetNoteHash;
export const getNotesData = state => state.notesData;
@@ -189,6 +191,9 @@ export const firstUnresolvedDiscussionId = (state, getters) => diffOrder => {
return getters.unresolvedDiscussionsIdsByDate[0];
};
+export const getDiscussion = state => discussionId =>
+ state.discussions.find(discussion => discussion.id === discussionId);
+
export const commentsDisabled = state => state.commentsDisabled;
// prevent babel-plugin-rewire from generating an invalid default during karma tests
diff --git a/app/assets/javascripts/notes/stores/modules/index.js b/app/assets/javascripts/notes/stores/modules/index.js
index 887e6d22b06..6168aeae35d 100644
--- a/app/assets/javascripts/notes/stores/modules/index.js
+++ b/app/assets/javascripts/notes/stores/modules/index.js
@@ -5,6 +5,7 @@ import mutations from '../mutations';
export default () => ({
state: {
discussions: [],
+ convertedDisscussionIds: [],
targetNoteHash: null,
lastFetchedAt: null,
diff --git a/app/assets/javascripts/notes/stores/mutation_types.js b/app/assets/javascripts/notes/stores/mutation_types.js
index df943c155f4..796370920bb 100644
--- a/app/assets/javascripts/notes/stores/mutation_types.js
+++ b/app/assets/javascripts/notes/stores/mutation_types.js
@@ -17,6 +17,8 @@ export const SET_NOTES_FETCHED_STATE = 'SET_NOTES_FETCHED_STATE';
export const SET_NOTES_LOADING_STATE = 'SET_NOTES_LOADING_STATE';
export const DISABLE_COMMENTS = 'DISABLE_COMMENTS';
export const APPLY_SUGGESTION = 'APPLY_SUGGESTION';
+export const CONVERT_TO_DISCUSSION = 'CONVERT_TO_DISCUSSION';
+export const REMOVE_CONVERTED_DISCUSSION = 'REMOVE_CONVERTED_DISCUSSION';
// DISCUSSION
export const COLLAPSE_DISCUSSION = 'COLLAPSE_DISCUSSION';
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index 8992454be2e..fa44ef2d057 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -105,7 +105,10 @@ export default {
if (discussion.diff_file) {
diffData.file_hash = discussion.diff_file.file_hash;
- diffData.truncated_diff_lines = discussion.truncated_diff_lines || [];
+
+ diffData.truncated_diff_lines = utils.prepareDiffLines(
+ discussion.truncated_diff_lines || [],
+ );
}
// To support legacy notes, should be very rare case.
@@ -190,6 +193,10 @@ export default {
const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id);
if (noteObj.individual_note) {
+ if (note.type === constants.DISCUSSION_NOTE) {
+ noteObj.individual_note = false;
+ }
+
noteObj.notes.splice(0, 1, note);
} else {
const comment = utils.findNoteObjectById(noteObj.notes, note.id);
@@ -243,7 +250,7 @@ export default {
[types.SET_DISCUSSION_DIFF_LINES](state, { discussionId, diffLines }) {
const discussion = utils.findNoteObjectById(state.discussions, discussionId);
- discussion.truncated_diff_lines = diffLines;
+ discussion.truncated_diff_lines = utils.prepareDiffLines(diffLines);
},
[types.DISABLE_COMMENTS](state, value) {
@@ -261,4 +268,16 @@ export default {
).length;
state.hasUnresolvedDiscussions = state.unresolvedDiscussionsCount > 1;
},
+
+ [types.CONVERT_TO_DISCUSSION](state, discussionId) {
+ const convertedDisscussionIds = [...state.convertedDisscussionIds, discussionId];
+ Object.assign(state, { convertedDisscussionIds });
+ },
+
+ [types.REMOVE_CONVERTED_DISCUSSION](state, discussionId) {
+ const convertedDisscussionIds = [...state.convertedDisscussionIds];
+
+ convertedDisscussionIds.splice(convertedDisscussionIds.indexOf(discussionId), 1);
+ Object.assign(state, { convertedDisscussionIds });
+ },
};
diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js
index dd57539e4d8..4b0feb0f94d 100644
--- a/app/assets/javascripts/notes/stores/utils.js
+++ b/app/assets/javascripts/notes/stores/utils.js
@@ -1,4 +1,5 @@
import AjaxCache from '~/lib/utils/ajax_cache';
+import { trimFirstCharOfLineContent } from '~/diffs/store/utils';
const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
@@ -28,3 +29,6 @@ export const getQuickActionText = note => {
export const hasQuickActions = note => REGEX_QUICK_ACTIONS.test(note);
export const stripQuickActions = note => note.replace(REGEX_QUICK_ACTIONS, '').trim();
+
+export const prepareDiffLines = diffLines =>
+ diffLines.map(line => ({ ...trimFirstCharOfLineContent(line) }));
diff --git a/app/assets/javascripts/pages/admin/application_settings/show/index.js b/app/assets/javascripts/pages/admin/application_settings/show/index.js
new file mode 100644
index 00000000000..5ec9688a6e4
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/show/index.js
@@ -0,0 +1,3 @@
+import initUserInternalRegexPlaceholder from '../../application_settings/account_and_limits';
+
+document.addEventListener('DOMContentLoaded', initUserInternalRegexPlaceholder());
diff --git a/app/assets/javascripts/pages/admin/index.js b/app/assets/javascripts/pages/admin/index.js
index 3aa793e47b9..8a32556f06c 100644
--- a/app/assets/javascripts/pages/admin/index.js
+++ b/app/assets/javascripts/pages/admin/index.js
@@ -1,7 +1,3 @@
import initAdmin from './admin';
-import initUserInternalRegexPlaceholder from './application_settings/account_and_limits';
-document.addEventListener('DOMContentLoaded', () => {
- initAdmin();
- initUserInternalRegexPlaceholder();
-});
+document.addEventListener('DOMContentLoaded', initAdmin());
diff --git a/app/assets/javascripts/pages/dashboard/merge_requests/index.js b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
index 260484726f3..ff758fcb4fe 100644
--- a/app/assets/javascripts/pages/dashboard/merge_requests/index.js
+++ b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
@@ -1,10 +1,11 @@
import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
+import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
document.addEventListener('DOMContentLoaded', () => {
- IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests();
+ addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
diff --git a/app/assets/javascripts/pages/dashboard/projects/index.js b/app/assets/javascripts/pages/dashboard/projects/index.js
index 8f98be79640..01001d4f3ff 100644
--- a/app/assets/javascripts/pages/dashboard/projects/index.js
+++ b/app/assets/javascripts/pages/dashboard/projects/index.js
@@ -1,7 +1,5 @@
import ProjectsList from '~/projects_list';
-import Star from '../../../star';
document.addEventListener('DOMContentLoaded', () => {
new ProjectsList(); // eslint-disable-line no-new
- new Star('.project-row'); // eslint-disable-line no-new
});
diff --git a/app/assets/javascripts/pages/explore/projects/index.js b/app/assets/javascripts/pages/explore/projects/index.js
index 0c585e162cb..01001d4f3ff 100644
--- a/app/assets/javascripts/pages/explore/projects/index.js
+++ b/app/assets/javascripts/pages/explore/projects/index.js
@@ -1,3 +1,5 @@
import ProjectsList from '~/projects_list';
-document.addEventListener('DOMContentLoaded', () => new ProjectsList());
+document.addEventListener('DOMContentLoaded', () => {
+ new ProjectsList(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/groups/clusters/update/index.js b/app/assets/javascripts/pages/groups/clusters/edit/index.js
index 8001d2dd1da..8001d2dd1da 100644
--- a/app/assets/javascripts/pages/groups/clusters/update/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/edit/index.js
diff --git a/app/assets/javascripts/pages/groups/clusters/index/index.js b/app/assets/javascripts/pages/groups/clusters/index/index.js
index 845a5f7042c..30d519d0e37 100644
--- a/app/assets/javascripts/pages/groups/clusters/index/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/index/index.js
@@ -1,5 +1,6 @@
-import initDismissableCallout from '~/dismissable_callout';
+import PersistentUserCallout from '~/persistent_user_callout';
document.addEventListener('DOMContentLoaded', () => {
- initDismissableCallout('.gcp-signup-offer');
+ const callout = document.querySelector('.gcp-signup-offer');
+ PersistentUserCallout.factory(callout);
});
diff --git a/app/assets/javascripts/pages/groups/group_members/index/index.js b/app/assets/javascripts/pages/groups/group_members/index/index.js
index c22a164cd4e..e4f4c3b574e 100644
--- a/app/assets/javascripts/pages/groups/group_members/index/index.js
+++ b/app/assets/javascripts/pages/groups/group_members/index/index.js
@@ -1,7 +1,7 @@
/* eslint-disable no-new */
import memberExpirationDate from '~/member_expiration_date';
-import Members from '~/members';
+import Members from 'ee_else_ce/members';
import UsersSelect from '~/users_select';
document.addEventListener('DOMContentLoaded', () => {
diff --git a/app/assets/javascripts/pages/groups/index.js b/app/assets/javascripts/pages/groups/index.js
index bf80d8b8193..451be6497de 100644
--- a/app/assets/javascripts/pages/groups/index.js
+++ b/app/assets/javascripts/pages/groups/index.js
@@ -1,6 +1,11 @@
-import initDismissableCallout from '~/dismissable_callout';
+import PersistentUserCallout from '~/persistent_user_callout';
import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
+function initGcpSignupCallout() {
+ const callout = document.querySelector('.gcp-signup-offer');
+ PersistentUserCallout.factory(callout);
+}
+
document.addEventListener('DOMContentLoaded', () => {
const { page } = document.body.dataset;
const newClusterViews = [
@@ -10,7 +15,7 @@ document.addEventListener('DOMContentLoaded', () => {
];
if (newClusterViews.indexOf(page) > -1) {
- initDismissableCallout('.gcp-signup-offer');
+ initGcpSignupCallout();
initGkeDropdowns();
}
});
diff --git a/app/assets/javascripts/pages/groups/issues/index.js b/app/assets/javascripts/pages/groups/issues/index.js
index 736c6a62610..35d4b034654 100644
--- a/app/assets/javascripts/pages/groups/issues/index.js
+++ b/app/assets/javascripts/pages/groups/issues/index.js
@@ -1,9 +1,11 @@
import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
document.addEventListener('DOMContentLoaded', () => {
+ IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
+
initFilteredSearch({
page: FILTERED_SEARCH.ISSUES,
isGroupDecendent: true,
diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js
index 339ce67438a..12a26fd88fa 100644
--- a/app/assets/javascripts/pages/groups/merge_requests/index.js
+++ b/app/assets/javascripts/pages/groups/merge_requests/index.js
@@ -1,10 +1,11 @@
import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import { FILTERED_SEARCH } from '~/pages/constants';
document.addEventListener('DOMContentLoaded', () => {
- IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests();
+ addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
diff --git a/app/assets/javascripts/pages/import/gitea/status/index.js b/app/assets/javascripts/pages/import/gitea/status/index.js
new file mode 100644
index 00000000000..dcd84f0faf9
--- /dev/null
+++ b/app/assets/javascripts/pages/import/gitea/status/index.js
@@ -0,0 +1,7 @@
+import mountImportProjectsTable from '~/import_projects';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const mountElement = document.getElementById('import-projects-mount-element');
+
+ mountImportProjectsTable(mountElement);
+});
diff --git a/app/assets/javascripts/pages/import/github/status/index.js b/app/assets/javascripts/pages/import/github/status/index.js
new file mode 100644
index 00000000000..dcd84f0faf9
--- /dev/null
+++ b/app/assets/javascripts/pages/import/github/status/index.js
@@ -0,0 +1,7 @@
+import mountImportProjectsTable from '~/import_projects';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const mountElement = document.getElementById('import-projects-mount-element');
+
+ mountImportProjectsTable(mountElement);
+});
diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js
index c7ce4675573..c9d3bbc8c39 100644
--- a/app/assets/javascripts/pages/profiles/show/index.js
+++ b/app/assets/javascripts/pages/profiles/show/index.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import createFlash from '~/flash';
import GfmAutoComplete from '~/gfm_auto_complete';
+import emojiRegex from 'emoji-regex';
import EmojiMenu from './emoji_menu';
const defaultStatusEmoji = 'speech_balloon';
@@ -42,32 +43,47 @@ document.addEventListener('DOMContentLoaded', () => {
const emojiAutocomplete = new GfmAutoComplete();
emojiAutocomplete.setup($(statusMessageField), { emojis: true });
+ const userNameInput = document.getElementById('user_name');
+ userNameInput.addEventListener('input', () => {
+ const EMOJI_REGEX = emojiRegex();
+ if (EMOJI_REGEX.test(userNameInput.value)) {
+ // set field to invalid so it gets detected by GlFieldErrors
+ userNameInput.setCustomValidity('Invalid field');
+ } else {
+ userNameInput.setCustomValidity('');
+ }
+ });
+
import(/* webpackChunkName: 'emoji' */ '~/emoji')
.then(Emoji => {
- const emojiMenu = new EmojiMenu(
- Emoji,
- toggleEmojiMenuButtonSelector,
- 'js-status-emoji-menu',
- selectEmojiCallback,
- );
- emojiMenu.bindEvents();
+ Emoji.initEmojiMap()
+ .then(() => {
+ const emojiMenu = new EmojiMenu(
+ Emoji,
+ toggleEmojiMenuButtonSelector,
+ 'js-status-emoji-menu',
+ selectEmojiCallback,
+ );
+ emojiMenu.bindEvents();
- const defaultEmojiTag = Emoji.glEmojiTag(defaultStatusEmoji);
- statusMessageField.addEventListener('input', () => {
- const hasStatusMessage = statusMessageField.value.trim() !== '';
- const statusEmoji = findStatusEmoji();
- if (hasStatusMessage && statusEmoji) {
- return;
- }
+ const defaultEmojiTag = Emoji.glEmojiTag(defaultStatusEmoji);
+ statusMessageField.addEventListener('input', () => {
+ const hasStatusMessage = statusMessageField.value.trim() !== '';
+ const statusEmoji = findStatusEmoji();
+ if (hasStatusMessage && statusEmoji) {
+ return;
+ }
- if (hasStatusMessage) {
- toggleNoEmojiPlaceholder(false);
- toggleEmojiMenuButton.innerHTML += defaultEmojiTag;
- } else if (statusEmoji.dataset.name === defaultStatusEmoji) {
- toggleNoEmojiPlaceholder(true);
- removeStatusEmoji();
- }
- });
+ if (hasStatusMessage) {
+ toggleNoEmojiPlaceholder(false);
+ toggleEmojiMenuButton.innerHTML += defaultEmojiTag;
+ } else if (statusEmoji.dataset.name === defaultStatusEmoji) {
+ toggleNoEmojiPlaceholder(true);
+ removeStatusEmoji();
+ }
+ });
+ })
+ .catch(() => createFlash('Failed to load emoji list.'));
})
.catch(() => createFlash('Failed to load emoji list.'));
});
diff --git a/app/assets/javascripts/pages/projects/clusters/update/index.js b/app/assets/javascripts/pages/projects/clusters/edit/index.js
index 8001d2dd1da..8001d2dd1da 100644
--- a/app/assets/javascripts/pages/projects/clusters/update/index.js
+++ b/app/assets/javascripts/pages/projects/clusters/edit/index.js
diff --git a/app/assets/javascripts/pages/projects/clusters/index/index.js b/app/assets/javascripts/pages/projects/clusters/index/index.js
index 845a5f7042c..30d519d0e37 100644
--- a/app/assets/javascripts/pages/projects/clusters/index/index.js
+++ b/app/assets/javascripts/pages/projects/clusters/index/index.js
@@ -1,5 +1,6 @@
-import initDismissableCallout from '~/dismissable_callout';
+import PersistentUserCallout from '~/persistent_user_callout';
document.addEventListener('DOMContentLoaded', () => {
- initDismissableCallout('.gcp-signup-offer');
+ const callout = document.querySelector('.gcp-signup-offer');
+ PersistentUserCallout.factory(callout);
});
diff --git a/app/assets/javascripts/pages/projects/environments/metrics/index.js b/app/assets/javascripts/pages/projects/environments/metrics/index.js
index 0b644780ad4..0d69a689316 100644
--- a/app/assets/javascripts/pages/projects/environments/metrics/index.js
+++ b/app/assets/javascripts/pages/projects/environments/metrics/index.js
@@ -1,3 +1,3 @@
-import monitoringBundle from '~/monitoring/monitoring_bundle';
+import monitoringBundle from 'ee_else_ce/monitoring/monitoring_bundle';
document.addEventListener('DOMContentLoaded', monitoringBundle);
diff --git a/app/assets/javascripts/pages/projects/error_tracking/index.js b/app/assets/javascripts/pages/projects/error_tracking/index.js
new file mode 100644
index 00000000000..5a8fe137e9a
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/error_tracking/index.js
@@ -0,0 +1,5 @@
+import ErrorTracking from '~/error_tracking';
+
+document.addEventListener('DOMContentLoaded', () => {
+ ErrorTracking();
+});
diff --git a/app/assets/javascripts/pages/projects/graphs/charts/index.js b/app/assets/javascripts/pages/projects/graphs/charts/index.js
index 3ccad513c05..314519ee442 100644
--- a/app/assets/javascripts/pages/projects/graphs/charts/index.js
+++ b/app/assets/javascripts/pages/projects/graphs/charts/index.js
@@ -2,65 +2,86 @@ import $ from 'jquery';
import Chart from 'chart.js';
import _ from 'underscore';
+import { barChartOptions, pieChartOptions } from '~/lib/utils/chart_utils';
+
document.addEventListener('DOMContentLoaded', () => {
const projectChartData = JSON.parse(document.getElementById('projectChartData').innerHTML);
- const responsiveChart = (selector, data) => {
- const options = {
- scaleOverlay: true,
- responsive: true,
- pointHitDetectionRadius: 2,
- maintainAspectRatio: false,
- };
+ const barChart = (selector, data) => {
// get selector by context
const ctx = selector.get(0).getContext('2d');
// pointing parent container to make chart.js inherit its width
const container = $(selector).parent();
- const generateChart = () => {
- selector.attr('width', $(container).width());
- if (window.innerWidth < 768) {
- // Scale fonts if window width lower than 768px (iPad portrait)
- options.scaleFontSize = 8;
- }
- return new Chart(ctx).Bar(data, options);
- };
- // enabling auto-resizing
- $(window).resize(generateChart);
- return generateChart();
+ selector.attr('width', $(container).width());
+
+ // Scale fonts if window width lower than 768px (iPad portrait)
+ const shouldAdjustFontSize = window.innerWidth < 768;
+ return new Chart(ctx, {
+ type: 'bar',
+ data,
+ options: barChartOptions(shouldAdjustFontSize),
+ });
+ };
+
+ const pieChart = (context, data) => {
+ const options = pieChartOptions();
+
+ return new Chart(context, {
+ type: 'pie',
+ data,
+ options,
+ });
};
const chartData = data => ({
labels: Object.keys(data),
datasets: [
{
- fillColor: 'rgba(220,220,220,0.5)',
- strokeColor: 'rgba(220,220,220,1)',
- barStrokeWidth: 1,
- barValueSpacing: 1,
- barDatasetSpacing: 1,
+ backgroundColor: 'rgba(220,220,220,0.5)',
+ borderColor: 'rgba(220,220,220,1)',
+ borderWidth: 1,
data: _.values(data),
},
],
});
+ const reorderWeekDays = (weekDays, firstDayOfWeek = 0) => {
+ if (firstDayOfWeek === 0) {
+ return weekDays;
+ }
+
+ return Object.keys(weekDays).reduce((acc, dayName, idx, arr) => {
+ const reorderedDayName = arr[(idx + firstDayOfWeek) % arr.length];
+
+ return {
+ ...acc,
+ [reorderedDayName]: weekDays[reorderedDayName],
+ };
+ }, {});
+ };
+
const hourData = chartData(projectChartData.hour);
- responsiveChart($('#hour-chart'), hourData);
+ barChart($('#hour-chart'), hourData);
- const dayData = chartData(projectChartData.weekDays);
- responsiveChart($('#weekday-chart'), dayData);
+ const weekDays = reorderWeekDays(projectChartData.weekDays, gon.first_day_of_week);
+ const dayData = chartData(weekDays);
+ barChart($('#weekday-chart'), dayData);
const monthData = chartData(projectChartData.month);
- responsiveChart($('#month-chart'), monthData);
+ barChart($('#month-chart'), monthData);
- const data = projectChartData.languages;
+ const data = {
+ datasets: [
+ {
+ data: projectChartData.languages.map(x => x.value),
+ backgroundColor: projectChartData.languages.map(x => x.color),
+ hoverBackgroundColor: projectChartData.languages.map(x => x.highlight),
+ },
+ ],
+ labels: projectChartData.languages.map(x => x.label),
+ };
const ctx = $('#languages-chart')
.get(0)
.getContext('2d');
- const options = {
- scaleOverlay: true,
- responsive: true,
- maintainAspectRatio: false,
- };
-
- new Chart(ctx).Pie(data, options);
+ pieChart(ctx, data);
});
diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js
index 5659e13981a..d4bd02c14e9 100644
--- a/app/assets/javascripts/pages/projects/index.js
+++ b/app/assets/javascripts/pages/projects/index.js
@@ -1,5 +1,5 @@
-import initDismissableCallout from '~/dismissable_callout';
import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
+import PersistentUserCallout from '../../persistent_user_callout';
import Project from './project';
import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation';
@@ -12,7 +12,9 @@ document.addEventListener('DOMContentLoaded', () => {
];
if (newClusterViews.indexOf(page) > -1) {
- initDismissableCallout('.gcp-signup-offer');
+ const callout = document.querySelector('.gcp-signup-offer');
+ PersistentUserCallout.factory(callout);
+
initGkeDropdowns();
}
diff --git a/app/assets/javascripts/pages/projects/issues/edit/index.js b/app/assets/javascripts/pages/projects/issues/edit/index.js
index ffc84dc106b..aecc6484b26 100644
--- a/app/assets/javascripts/pages/projects/issues/edit/index.js
+++ b/app/assets/javascripts/pages/projects/issues/edit/index.js
@@ -1,3 +1,3 @@
-import initForm from '../form';
+import initForm from 'ee_else_ce/pages/projects/issues/form';
document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js
index f99023ad8e7..941c4552579 100644
--- a/app/assets/javascripts/pages/projects/issues/form.js
+++ b/app/assets/javascripts/pages/projects/issues/form.js
@@ -2,7 +2,7 @@
import $ from 'jquery';
import GLForm from '~/gl_form';
-import IssuableForm from '~/issuable_form';
+import IssuableForm from 'ee_else_ce/issuable_form';
import LabelsSelect from '~/labels_select';
import MilestoneSelect from '~/milestone_select';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
diff --git a/app/assets/javascripts/pages/projects/issues/index/index.js b/app/assets/javascripts/pages/projects/issues/index/index.js
index a56c0bb6be8..8bf0c2edc71 100644
--- a/app/assets/javascripts/pages/projects/issues/index/index.js
+++ b/app/assets/javascripts/pages/projects/issues/index/index.js
@@ -4,11 +4,13 @@ import IssuableIndex from '~/issuable_index';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import UsersSelect from '~/users_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
document.addEventListener('DOMContentLoaded', () => {
+ IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
+
initFilteredSearch({
page: FILTERED_SEARCH.ISSUES,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
diff --git a/app/assets/javascripts/pages/projects/issues/new/index.js b/app/assets/javascripts/pages/projects/issues/new/index.js
index ffc84dc106b..aecc6484b26 100644
--- a/app/assets/javascripts/pages/projects/issues/new/index.js
+++ b/app/assets/javascripts/pages/projects/issues/new/index.js
@@ -1,3 +1,3 @@
-import initForm from '../form';
+import initForm from 'ee_else_ce/pages/projects/issues/form';
document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/merge_requests/index/index.js b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
index ec39db12e74..0bcca22e40f 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/index/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
@@ -2,12 +2,13 @@ import IssuableIndex from '~/issuable_index';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import UsersSelect from '~/users_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
+import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
document.addEventListener('DOMContentLoaded', () => {
- IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests();
+ addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js
index e3971618da5..8f0dc8554e2 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js
@@ -4,7 +4,7 @@ import $ from 'jquery';
import Diff from '~/diff';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GLForm from '~/gl_form';
-import IssuableForm from '~/issuable_form';
+import IssuableForm from 'ee_else_ce/issuable_form';
import LabelsSelect from '~/labels_select';
import MilestoneSelect from '~/milestone_select';
import IssuableTemplateSelectors from '~/templates/issuable_template_selectors';
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
index db2a4041ec0..bd4309e47ad 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -70,7 +70,7 @@ export default {
:checked="isEditable"
class="label-bold"
type="radio"
- @click="toggleCustomInput(true);"
+ @click="toggleCustomInput(true)"
/>
<label for="custom"> {{ s__('PipelineSheduleIntervalPattern|Custom') }} </label>
@@ -88,7 +88,7 @@ export default {
:value="cronIntervalPresets.everyDay"
class="label-bold"
type="radio"
- @click="toggleCustomInput(false);"
+ @click="toggleCustomInput(false)"
/>
<label class="label-bold" for="every-day"> {{ __('Every day (at 4:00am)') }} </label>
@@ -102,7 +102,7 @@ export default {
:value="cronIntervalPresets.everyWeek"
class="label-bold"
type="radio"
- @click="toggleCustomInput(false);"
+ @click="toggleCustomInput(false)"
/>
<label class="label-bold" for="every-week">
@@ -118,7 +118,7 @@ export default {
:value="cronIntervalPresets.everyMonth"
class="label-bold"
type="radio"
- @click="toggleCustomInput(false);"
+ @click="toggleCustomInput(false)"
/>
<label class="label-bold" for="every-month">
diff --git a/app/assets/javascripts/pages/projects/pipelines/charts/index.js b/app/assets/javascripts/pages/projects/pipelines/charts/index.js
index 48353f3b4ef..9fa580d2ba9 100644
--- a/app/assets/javascripts/pages/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/charts/index.js
@@ -1,29 +1,31 @@
import $ from 'jquery';
import Chart from 'chart.js';
-const options = {
- scaleOverlay: true,
- responsive: true,
- maintainAspectRatio: false,
-};
+import { barChartOptions, lineChartOptions } from '~/lib/utils/chart_utils';
+
+const SUCCESS_LINE_COLOR = '#1aaa55';
+
+const TOTAL_LINE_COLOR = '#707070';
-const buildChart = chartScope => {
+const buildChart = (chartScope, shouldAdjustFontSize) => {
const data = {
labels: chartScope.labels,
datasets: [
{
- fillColor: '#707070',
- strokeColor: '#707070',
- pointColor: '#707070',
- pointStrokeColor: '#EEE',
- data: chartScope.totalValues,
+ backgroundColor: SUCCESS_LINE_COLOR,
+ borderColor: SUCCESS_LINE_COLOR,
+ pointBackgroundColor: SUCCESS_LINE_COLOR,
+ pointBorderColor: '#fff',
+ data: chartScope.successValues,
+ fill: 'origin',
},
{
- fillColor: '#1aaa55',
- strokeColor: '#1aaa55',
- pointColor: '#1aaa55',
- pointStrokeColor: '#fff',
- data: chartScope.successValues,
+ backgroundColor: TOTAL_LINE_COLOR,
+ borderColor: TOTAL_LINE_COLOR,
+ pointBackgroundColor: TOTAL_LINE_COLOR,
+ pointBorderColor: '#EEE',
+ data: chartScope.totalValues,
+ fill: '-1',
},
],
};
@@ -31,36 +33,51 @@ const buildChart = chartScope => {
.get(0)
.getContext('2d');
- new Chart(ctx).Line(data, options);
+ return new Chart(ctx, {
+ type: 'line',
+ data,
+ options: lineChartOptions({
+ width: ctx.canvas.width,
+ numberOfPoints: chartScope.totalValues.length,
+ shouldAdjustFontSize,
+ }),
+ });
};
-document.addEventListener('DOMContentLoaded', () => {
- const chartTimesData = JSON.parse(document.getElementById('pipelinesTimesChartsData').innerHTML);
- const chartsData = JSON.parse(document.getElementById('pipelinesChartsData').innerHTML);
+const buildBarChart = (chartTimesData, shouldAdjustFontSize) => {
const data = {
labels: chartTimesData.labels,
datasets: [
{
- fillColor: 'rgba(220,220,220,0.5)',
- strokeColor: 'rgba(220,220,220,1)',
- barStrokeWidth: 1,
+ backgroundColor: 'rgba(220,220,220,0.5)',
+ borderColor: 'rgba(220,220,220,1)',
+ borderWidth: 1,
barValueSpacing: 1,
barDatasetSpacing: 1,
data: chartTimesData.values,
},
],
};
-
- if (window.innerWidth < 768) {
- // Scale fonts if window width lower than 768px (iPad portrait)
- options.scaleFontSize = 8;
- }
-
- new Chart(
+ return new Chart(
$('#build_timesChart')
.get(0)
.getContext('2d'),
- ).Bar(data, options);
+ {
+ type: 'bar',
+ data,
+ options: barChartOptions(shouldAdjustFontSize),
+ },
+ );
+};
+
+document.addEventListener('DOMContentLoaded', () => {
+ const chartTimesData = JSON.parse(document.getElementById('pipelinesTimesChartsData').innerHTML);
+ const chartsData = JSON.parse(document.getElementById('pipelinesChartsData').innerHTML);
+
+ // Scale fonts if window width lower than 768px (iPad portrait)
+ const shouldAdjustFontSize = window.innerWidth < 768;
+
+ buildBarChart(chartTimesData, shouldAdjustFontSize);
- chartsData.forEach(scope => buildChart(scope));
+ chartsData.forEach(scope => buildChart(scope, shouldAdjustFontSize));
});
diff --git a/app/assets/javascripts/pages/projects/project_members/index.js b/app/assets/javascripts/pages/projects/project_members/index.js
index adbe744290a..f39765818e7 100644
--- a/app/assets/javascripts/pages/projects/project_members/index.js
+++ b/app/assets/javascripts/pages/projects/project_members/index.js
@@ -1,7 +1,7 @@
+import Members from 'ee_else_ce/members';
import memberExpirationDate from '../../../member_expiration_date';
import UsersSelect from '../../../users_select';
import groupsSelect from '../../../groups_select';
-import Members from '../../../members';
document.addEventListener('DOMContentLoaded', () => {
memberExpirationDate('.js-access-expiration-date-groups');
diff --git a/app/assets/javascripts/pages/projects/settings/operations/show/index.js b/app/assets/javascripts/pages/projects/settings/operations/show/index.js
new file mode 100644
index 00000000000..73c745179be
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/settings/operations/show/index.js
@@ -0,0 +1,5 @@
+import mountErrorTrackingForm from '~/error_tracking_settings';
+
+document.addEventListener('DOMContentLoaded', () => {
+ mountErrorTrackingForm();
+});
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 08c7719dcf2..19d9903c988 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
@@ -325,8 +325,8 @@ export default {
<project-setting-row
v-if="pagesAvailable && pagesAccessControlEnabled"
:help-path="pagesHelpPath"
- label="Pages"
- help-text="Static website for the project."
+ label="Pages access control"
+ help-text="Access control for the project's static website"
>
<project-feature-setting
v-model="pagesAccessLevel"
diff --git a/app/assets/javascripts/pages/projects/tags/releases/index.js b/app/assets/javascripts/pages/projects/tags/releases/index.js
new file mode 100644
index 00000000000..d6afc71fb03
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/tags/releases/index.js
@@ -0,0 +1,8 @@
+import $ from 'jquery';
+import ZenMode from '~/zen_mode';
+import GLForm from '~/gl_form';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ZenMode(); // eslint-disable-line no-new
+ new GLForm($('.release-form')); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/sessions/new/index.js b/app/assets/javascripts/pages/sessions/new/index.js
index 07f32210d93..e1a3f42a71f 100644
--- a/app/assets/javascripts/pages/sessions/new/index.js
+++ b/app/assets/javascripts/pages/sessions/new/index.js
@@ -1,13 +1,20 @@
import $ from 'jquery';
import UsernameValidator from './username_validator';
+import NoEmojiValidator from '../../../emoji/no_emoji_validator';
import SigninTabsMemoizer from './signin_tabs_memoizer';
import OAuthRememberMe from './oauth_remember_me';
+import preserveUrlFragment from './preserve_url_fragment';
document.addEventListener('DOMContentLoaded', () => {
new UsernameValidator(); // eslint-disable-line no-new
new SigninTabsMemoizer(); // eslint-disable-line no-new
+ new NoEmojiValidator(); // eslint-disable-line no-new
new OAuthRememberMe({
container: $('.omniauth-container'),
}).bindEvents();
+
+ // Save the URL fragment from the current window location. This will be present if the user was
+ // redirected to sign-in after attempting to access a protected URL that included a fragment.
+ preserveUrlFragment(window.location.hash);
});
diff --git a/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js b/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js
index 761618109a4..191221a48cd 100644
--- a/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js
+++ b/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import { mergeUrlParams, removeParams } from '~/lib/utils/url_utility';
/**
* OAuth-based login buttons have a separate "remember me" checkbox.
@@ -24,9 +25,9 @@ export default class OAuthRememberMe {
const href = $(element).attr('href');
if (rememberMe) {
- $(element).attr('href', `${href}?remember_me=1`);
+ $(element).attr('href', mergeUrlParams({ remember_me: 1 }, href));
} else {
- $(element).attr('href', href.replace('?remember_me=1', ''));
+ $(element).attr('href', removeParams(['remember_me'], href));
}
});
}
diff --git a/app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js b/app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js
new file mode 100644
index 00000000000..e617fecaa0f
--- /dev/null
+++ b/app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js
@@ -0,0 +1,32 @@
+import { mergeUrlParams, setUrlFragment } from '~/lib/utils/url_utility';
+
+/**
+ * Ensure the given URL fragment is preserved by appending it to sign-in/sign-up form actions and
+ * OAuth/SAML login links.
+ *
+ * @param fragment {string} - url fragment to be preserved
+ */
+export default function preserveUrlFragment(fragment = '') {
+ if (fragment) {
+ const normalFragment = fragment.replace(/^#/, '');
+
+ // Append the fragment to all sign-in/sign-up form actions so it is preserved when the user is
+ // eventually redirected back to the originally requested URL.
+ const forms = document.querySelectorAll('#signin-container form');
+ Array.prototype.forEach.call(forms, form => {
+ const actionWithFragment = setUrlFragment(form.getAttribute('action'), `#${normalFragment}`);
+ form.setAttribute('action', actionWithFragment);
+ });
+
+ // Append a redirect_fragment query param to all oauth provider links. The redirect_fragment
+ // query param will be available in the omniauth callback upon successful authentication
+ const anchors = document.querySelectorAll('#signin-container a.oauth-login');
+ Array.prototype.forEach.call(anchors, anchor => {
+ const newHref = mergeUrlParams(
+ { redirect_fragment: normalFragment },
+ anchor.getAttribute('href'),
+ );
+ anchor.setAttribute('href', newHref);
+ });
+ }
+}
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index 8a84ac37dab..61204c37307 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -10,6 +10,12 @@ import { __ } from '~/locale';
const d3 = { select, scaleLinear, scaleThreshold };
+const firstDayOfWeekChoices = Object.freeze({
+ sunday: 0,
+ monday: 1,
+ saturday: 6,
+});
+
const LOADING_HTML = `
<div class="text-center">
<i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i>
@@ -49,7 +55,7 @@ export default class ActivityCalendar {
timestamps,
calendarActivitiesPath,
utcOffset = 0,
- firstDayOfWeek = 0,
+ firstDayOfWeek = firstDayOfWeekChoices.sunday,
monthsAgo = 12,
) {
this.calendarActivitiesPath = calendarActivitiesPath;
@@ -159,7 +165,7 @@ export default class ActivityCalendar {
.append('g')
.attr('transform', (group, i) => {
_.each(group, (stamp, a) => {
- if (a === 0 && stamp.day === 0) {
+ if (a === 0 && stamp.day === this.firstDayOfWeek) {
const month = stamp.date.getMonth();
const x = this.daySizeWithSpace * i + 1 + this.daySizeWithSpace;
const lastMonth = _.last(this.months);
@@ -205,6 +211,19 @@ export default class ActivityCalendar {
y: 29 + this.dayYPos(5),
},
];
+
+ if (this.firstDayOfWeek === firstDayOfWeekChoices.monday) {
+ days.push({
+ text: 'S',
+ y: 29 + this.dayYPos(7),
+ });
+ } else if (this.firstDayOfWeek === firstDayOfWeekChoices.saturday) {
+ days.push({
+ text: 'S',
+ y: 29 + this.dayYPos(6),
+ });
+ }
+
this.svg
.append('g')
.selectAll('text')
diff --git a/app/assets/javascripts/pages/users/user_overview_block.js b/app/assets/javascripts/pages/users/user_overview_block.js
index eec2b5ca8e5..a7c3c9d104d 100644
--- a/app/assets/javascripts/pages/users/user_overview_block.js
+++ b/app/assets/javascripts/pages/users/user_overview_block.js
@@ -15,7 +15,8 @@ export default class UserOverviewBlock {
}
loadData() {
- const loadingEl = document.querySelector(`${this.container} .loading`);
+ const containerEl = document.querySelector(this.container);
+ const loadingEl = containerEl.querySelector(`.loading`);
loadingEl.classList.remove('hide');
@@ -29,18 +30,21 @@ export default class UserOverviewBlock {
render(data) {
const { html, count } = data;
- const contentList = document.querySelector(`${this.container} .overview-content-list`);
+ const containerEl = document.querySelector(this.container);
+ const contentList = containerEl.querySelector('.overview-content-list');
contentList.innerHTML += html;
- const loadingEl = document.querySelector(`${this.container} .loading`);
+ const loadingEl = containerEl.querySelector('.loading');
if (count && count > 0) {
- document.querySelector(`${this.container} .js-view-all`).classList.remove('hide');
+ containerEl.querySelector('.js-view-all').classList.remove('hide');
} else {
- document
- .querySelector(`${this.container} .nothing-here-block`)
- .classList.add('text-left', 'p-0');
+ const nothingHereBlock = containerEl.querySelector('.nothing-here-block');
+
+ if (nothingHereBlock) {
+ nothingHereBlock.classList.add('p-5');
+ }
}
loadingEl.classList.add('hide');
diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js
index 1c3fd58ca74..636308c5401 100644
--- a/app/assets/javascripts/pages/users/user_tabs.js
+++ b/app/assets/javascripts/pages/users/user_tabs.js
@@ -221,7 +221,7 @@ export default class UserTabs {
const monthsAgo = UserTabs.getVisibleCalendarPeriod($calendarWrap);
const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath');
const utcOffset = $calendarWrap.data('utcOffset');
- const calendarHint = __('Issues, merge requests, pushes and comments.');
+ const calendarHint = __('Issues, merge requests, pushes, and comments.');
$calendarWrap.html(CALENDAR_TEMPLATE);
@@ -234,7 +234,7 @@ export default class UserTabs {
data,
calendarActivitiesPath,
utcOffset,
- 0,
+ gon.first_day_of_week,
monthsAgo,
);
}
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index 74faa35358d..1ec2784cc5a 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -134,6 +134,13 @@ export default {
>ms / <span title="Invoke Count">{{ currentRequest.details.gc.invokes }}</span> gc
</span>
</div>
+ <div
+ v-if="currentRequest.details && currentRequest.details.tracing"
+ id="peek-view-trace"
+ class="view"
+ >
+ <a :href="currentRequest.details.tracing.tracing_url"> trace </a>
+ </div>
<request-selector
v-if="currentRequest"
:current-request="currentRequest"
diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js
new file mode 100644
index 00000000000..4a08e158f6b
--- /dev/null
+++ b/app/assets/javascripts/persistent_user_callout.js
@@ -0,0 +1,42 @@
+import axios from './lib/utils/axios_utils';
+import { __ } from './locale';
+import Flash from './flash';
+
+export default class PersistentUserCallout {
+ constructor(container) {
+ const { dismissEndpoint, featureId } = container.dataset;
+ this.container = container;
+ this.dismissEndpoint = dismissEndpoint;
+ this.featureId = featureId;
+
+ this.init();
+ }
+
+ init() {
+ const closeButton = this.container.querySelector('.js-close');
+ closeButton.addEventListener('click', event => this.dismiss(event));
+ }
+
+ dismiss(event) {
+ event.preventDefault();
+
+ axios
+ .post(this.dismissEndpoint, {
+ feature_name: this.featureId,
+ })
+ .then(() => {
+ this.container.remove();
+ })
+ .catch(() => {
+ Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
+ });
+ }
+
+ static factory(container) {
+ if (!container) {
+ return undefined;
+ }
+
+ return new PersistentUserCallout(container);
+ }
+}
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index 59cebaba717..a49dc311bd0 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -1,59 +1,20 @@
<script>
-import _ from 'underscore';
import { GlLoadingIcon } from '@gitlab/ui';
import StageColumnComponent from './stage_column_component.vue';
+import GraphMixin from '../../mixins/graph_component_mixin';
export default {
components: {
StageColumnComponent,
GlLoadingIcon,
},
- props: {
- isLoading: {
- type: Boolean,
- required: true,
- },
- pipeline: {
- type: Object,
- required: true,
- },
- },
- computed: {
- graph() {
- return this.pipeline.details && this.pipeline.details.stages;
- },
- },
- methods: {
- capitalizeStageName(name) {
- const escapedName = _.escape(name);
- return escapedName.charAt(0).toUpperCase() + escapedName.slice(1);
- },
- isFirstColumn(index) {
- return index === 0;
- },
- stageConnectorClass(index, stage) {
- let className;
-
- // If it's the first stage column and only has one job
- if (index === 0 && stage.groups.length === 1) {
- className = 'no-margin';
- } else if (index > 0) {
- // If it is not the first column
- className = 'left-margin';
- }
-
- return className;
- },
- refreshPipelineGraph() {
- this.$emit('refreshPipelineGraph');
- },
- },
+ mixins: [GraphMixin],
};
</script>
<template>
<div class="build-content middle-block js-pipeline-graph">
<div class="pipeline-visualization pipeline-graph pipeline-tab-content">
- <div class="text-center"><gl-loading-icon v-if="isLoading" :size="3" /></div>
+ <div v-if="isLoading" class="m-auto"><gl-loading-icon :size="3" /></div>
<ul v-if="!isLoading" class="stage-column-list">
<stage-column-component
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index cf9db89e32b..2b32a6e4a98 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -108,7 +108,7 @@ export default {
:href="status.details_path"
:title="tooltipText"
:class="cssClassJobName"
- class="js-pipeline-graph-job-link"
+ class="js-pipeline-graph-job-link qa-job-link"
>
<job-name-component :name="job.name" :status="job.status" />
</gl-link>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue
index 30a5bbf92ce..918622ef8dc 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue
@@ -1,8 +1,20 @@
<script>
import { GlLink, GlTooltipDirective } from '@gitlab/ui';
+import _ from 'underscore';
+import { __, sprintf } from '~/locale';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import popover from '~/vue_shared/directives/popover';
+const popoverTitle = sprintf(
+ _.escape(
+ __(
+ `This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}`,
+ ),
+ ),
+ { strongStart: '<b>', strongEnd: '</b>' },
+ false,
+);
+
export default {
components: {
UserAvatarLink,
@@ -32,14 +44,14 @@ export default {
trigger: 'focus',
placement: 'top',
title: `<div class="autodevops-title">
- This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>
+ ${popoverTitle}
</div>`,
content: `<a
class="autodevops-link"
href="${this.autoDevopsHelpPath}"
target="_blank"
rel="noopener noreferrer nofollow">
- Learn more about Auto DevOps
+ ${_.escape(__('Learn more about Auto DevOps'))}
</a>`,
};
},
@@ -54,9 +66,9 @@ export default {
<span>by</span>
<user-avatar-link
v-if="user"
- :link-href="pipeline.user.path"
- :img-src="pipeline.user.avatar_url"
- :tooltip-text="pipeline.user.name"
+ :link-href="user.path"
+ :img-src="user.avatar_url"
+ :tooltip-text="user.name"
class="js-pipeline-url-user"
/>
<span v-if="!user" class="js-pipeline-url-api api"> API </span>
@@ -64,10 +76,10 @@ export default {
<span
v-if="pipeline.flags.latest"
v-gl-tooltip
+ :title="__('Latest pipeline for this branch')"
class="js-pipeline-url-latest badge badge-success"
- title="__('Latest pipeline for this branch')"
>
- latest
+ {{ __('latest') }}
</span>
<span
v-if="pipeline.flags.yaml_errors"
@@ -75,7 +87,7 @@ export default {
:title="pipeline.yaml_errors"
class="js-pipeline-url-yaml badge badge-danger"
>
- yaml invalid
+ {{ __('yaml invalid') }}
</span>
<span
v-if="pipeline.flags.failure_reason"
@@ -83,7 +95,7 @@ export default {
:title="pipeline.failure_reason"
class="js-pipeline-url-failure badge badge-danger"
>
- error
+ {{ __('error') }}
</span>
<gl-link
v-if="pipeline.flags.auto_devops"
@@ -95,15 +107,15 @@ export default {
Auto DevOps
</gl-link>
<span v-if="pipeline.flags.stuck" class="js-pipeline-url-stuck badge badge-warning">
- stuck
+ {{ __('stuck') }}
</span>
<span
v-if="pipeline.flags.merge_request"
v-gl-tooltip
- title="__('This pipeline is run in a merge request context')"
+ :title="__('This pipeline is run in a merge request context')"
class="js-pipeline-url-mergerequest badge badge-info"
>
- merge request
+ {{ __('merge request') }}
</span>
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
index 2e9f2519fcb..244d332f38f 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
@@ -59,28 +59,30 @@ export default {
</script>
<template>
<div class="btn-group">
- <gl-button
+ <button
v-gl-tooltip
+ type="button"
:disabled="isLoading"
class="dropdown-new btn btn-default js-pipeline-dropdown-manual-actions"
- title="Manual job"
+ :title="__('Manual job')"
data-toggle="dropdown"
- aria-label="Manual job"
+ :aria-label="__('Manual job')"
>
- <icon name="play" class="icon-play" /> <i class="fa fa-caret-down" aria-hidden="true"> </i>
+ <icon name="play" class="icon-play" />
+ <i class="fa fa-caret-down" aria-hidden="true"></i>
<gl-loading-icon v-if="isLoading" />
- </gl-button>
+ </button>
<ul class="dropdown-menu dropdown-menu-right">
<li v-for="action in actions" :key="action.path">
<gl-button
:class="{ disabled: isActionDisabled(action) }"
:disabled="isActionDisabled(action)"
- class="js-pipeline-action-link no-btn btn"
- @click="onClickAction(action);"
+ class="js-pipeline-action-link no-btn btn d-flex align-items-center justify-content-between flex-wrap"
+ @click="onClickAction(action)"
>
{{ action.name }}
- <span v-if="action.scheduled_at" class="pull-right">
+ <span v-if="action.scheduled_at">
<icon name="clock" />
<gl-countdown :end-date-string="action.scheduled_at" />
</span>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue b/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
index 908b10afee6..2ab0ad4d013 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink, GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
export default {
@@ -9,7 +9,6 @@ export default {
components: {
Icon,
GlLink,
- GlButton,
},
props: {
artifacts: {
@@ -21,20 +20,22 @@ export default {
</script>
<template>
<div class="btn-group" role="group">
- <gl-button
+ <button
v-gl-tooltip
- class="dropdown-toggle build-artifacts js-pipeline-dropdown-download"
- title="Artifacts"
+ type="button"
+ class="dropdown-toggle build-artifacts btn btn-default js-pipeline-dropdown-download"
+ :title="__('Artifacts')"
data-toggle="dropdown"
- aria-label="Artifacts"
+ :aria-label="__('Artifacts')"
>
- <icon name="download" /> <i class="fa fa-caret-down" aria-hidden="true"> </i>
- </gl-button>
+ <icon name="download" />
+ <i class="fa fa-caret-down" aria-hidden="true"></i>
+ </button>
<ul class="dropdown-menu dropdown-menu-right">
<li v-for="(artifact, i) in artifacts" :key="i">
- <gl-link :href="artifact.path" rel="nofollow" download>
- Download {{ artifact.name }} artifacts
- </gl-link>
+ <gl-link :href="artifact.path" rel="nofollow" download
+ >Download {{ artifact.name }} artifacts</gl-link
+ >
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue
index 2d3f667e73e..7426936515a 100644
--- a/app/assets/javascripts/pipelines/components/stage.vue
+++ b/app/assets/javascripts/pipelines/components/stage.vue
@@ -172,8 +172,6 @@ export default {
<span :aria-label="stage.title" aria-hidden="true" class="no-pointer-events">
<icon :name="borderlessIcon" />
</span>
-
- <i class="fa fa-caret-down" aria-hidden="true"> </i>
</button>
<div
diff --git a/app/assets/javascripts/pipelines/mixins/graph_component_mixin.js b/app/assets/javascripts/pipelines/mixins/graph_component_mixin.js
new file mode 100644
index 00000000000..66e9476dadf
--- /dev/null
+++ b/app/assets/javascripts/pipelines/mixins/graph_component_mixin.js
@@ -0,0 +1,44 @@
+import _ from 'underscore';
+
+export default {
+ props: {
+ isLoading: {
+ type: Boolean,
+ required: true,
+ },
+ pipeline: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ graph() {
+ return this.pipeline.details && this.pipeline.details.stages;
+ },
+ },
+ methods: {
+ capitalizeStageName(name) {
+ const escapedName = _.escape(name);
+ return escapedName.charAt(0).toUpperCase() + escapedName.slice(1);
+ },
+ isFirstColumn(index) {
+ return index === 0;
+ },
+ stageConnectorClass(index, stage) {
+ let className;
+
+ // If it's the first stage column and only has one job
+ if (index === 0 && stage.groups.length === 1) {
+ className = 'no-margin';
+ } else if (index > 0) {
+ // If it is not the first column
+ className = 'left-margin';
+ }
+
+ return className;
+ },
+ refreshPipelineGraph() {
+ this.$emit('refreshPipelineGraph');
+ },
+ },
+};
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js
index 32bfa47e5f2..3cc9d0a3a4e 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines.js
@@ -27,11 +27,7 @@ export default {
},
computed: {
shouldRenderPagination() {
- return (
- !this.isLoading &&
- this.state.pipelines.length &&
- this.state.pageInfo.total > this.state.pageInfo.perPage
- );
+ return !this.isLoading;
},
},
beforeMount() {
@@ -94,8 +90,7 @@ export default {
this.isLoading = false;
this.successCallback(response);
- // restart polling
- this.poll.restart({ data: this.requestData });
+ this.poll.enable({ data: this.requestData, response });
})
.catch(() => {
this.isLoading = false;
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
index a33835472bb..5ee510eb11d 100644
--- a/app/assets/javascripts/project_select.js
+++ b/app/assets/javascripts/project_select.js
@@ -5,97 +5,101 @@ import Api from './api';
import ProjectSelectComboButton from './project_select_combo_button';
export default function projectSelect() {
- $('.ajax-project-select').each(function(i, select) {
- var placeholder;
- const simpleFilter = $(select).data('simpleFilter') || false;
- this.groupId = $(select).data('groupId');
- this.includeGroups = $(select).data('includeGroups');
- this.allProjects = $(select).data('allProjects') || false;
- this.orderBy = $(select).data('orderBy') || 'id';
- this.withIssuesEnabled = $(select).data('withIssuesEnabled');
- this.withMergeRequestsEnabled = $(select).data('withMergeRequestsEnabled');
- this.withShared =
- $(select).data('withShared') === undefined ? true : $(select).data('withShared');
- this.includeProjectsInSubgroups = $(select).data('includeProjectsInSubgroups') || false;
- this.allowClear = $(select).data('allowClear') || false;
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ $('.ajax-project-select').each(function(i, select) {
+ var placeholder;
+ const simpleFilter = $(select).data('simpleFilter') || false;
+ this.groupId = $(select).data('groupId');
+ this.includeGroups = $(select).data('includeGroups');
+ this.allProjects = $(select).data('allProjects') || false;
+ this.orderBy = $(select).data('orderBy') || 'id';
+ this.withIssuesEnabled = $(select).data('withIssuesEnabled');
+ this.withMergeRequestsEnabled = $(select).data('withMergeRequestsEnabled');
+ this.withShared =
+ $(select).data('withShared') === undefined ? true : $(select).data('withShared');
+ this.includeProjectsInSubgroups = $(select).data('includeProjectsInSubgroups') || false;
+ this.allowClear = $(select).data('allowClear') || false;
- placeholder = 'Search for project';
- if (this.includeGroups) {
- placeholder += ' or group';
- }
+ placeholder = 'Search for project';
+ if (this.includeGroups) {
+ placeholder += ' or group';
+ }
- $(select).select2({
- placeholder: placeholder,
- minimumInputLength: 0,
- query: (function(_this) {
- return function(query) {
- var finalCallback, projectsCallback;
- finalCallback = function(projects) {
- var data;
- data = {
- results: projects,
- };
- return query.callback(data);
- };
- if (_this.includeGroups) {
- projectsCallback = function(projects) {
- var groupsCallback;
- groupsCallback = function(groups) {
+ $(select).select2({
+ placeholder: placeholder,
+ minimumInputLength: 0,
+ query: (function(_this) {
+ return function(query) {
+ var finalCallback, projectsCallback;
+ finalCallback = function(projects) {
var data;
- data = groups.concat(projects);
- return finalCallback(data);
+ data = {
+ results: projects,
+ };
+ return query.callback(data);
};
- return Api.groups(query.term, {}, groupsCallback);
+ if (_this.includeGroups) {
+ projectsCallback = function(projects) {
+ var groupsCallback;
+ groupsCallback = function(groups) {
+ var data;
+ data = groups.concat(projects);
+ return finalCallback(data);
+ };
+ return Api.groups(query.term, {}, groupsCallback);
+ };
+ } else {
+ projectsCallback = finalCallback;
+ }
+ if (_this.groupId) {
+ return Api.groupProjects(
+ _this.groupId,
+ query.term,
+ {
+ with_issues_enabled: _this.withIssuesEnabled,
+ with_merge_requests_enabled: _this.withMergeRequestsEnabled,
+ with_shared: _this.withShared,
+ include_subgroups: _this.includeProjectsInSubgroups,
+ },
+ projectsCallback,
+ );
+ } else {
+ return Api.projects(
+ query.term,
+ {
+ order_by: _this.orderBy,
+ with_issues_enabled: _this.withIssuesEnabled,
+ with_merge_requests_enabled: _this.withMergeRequestsEnabled,
+ membership: !_this.allProjects,
+ },
+ projectsCallback,
+ );
+ }
};
- } else {
- projectsCallback = finalCallback;
- }
- if (_this.groupId) {
- return Api.groupProjects(
- _this.groupId,
- query.term,
- {
- with_issues_enabled: _this.withIssuesEnabled,
- with_merge_requests_enabled: _this.withMergeRequestsEnabled,
- with_shared: _this.withShared,
- include_subgroups: _this.includeProjectsInSubgroups,
- },
- projectsCallback,
- );
- } else {
- return Api.projects(
- query.term,
- {
- order_by: _this.orderBy,
- with_issues_enabled: _this.withIssuesEnabled,
- with_merge_requests_enabled: _this.withMergeRequestsEnabled,
- membership: !_this.allProjects,
- },
- projectsCallback,
- );
- }
- };
- })(this),
- id: function(project) {
- if (simpleFilter) return project.id;
- return JSON.stringify({
- name: project.name,
- url: project.web_url,
- });
- },
- text: function(project) {
- return project.name_with_namespace || project.name;
- },
+ })(this),
+ id: function(project) {
+ if (simpleFilter) return project.id;
+ return JSON.stringify({
+ name: project.name,
+ url: project.web_url,
+ });
+ },
+ text: function(project) {
+ return project.name_with_namespace || project.name;
+ },
- initSelection: function(el, callback) {
- return Api.project(el.val()).then(({ data }) => callback(data));
- },
+ initSelection: function(el, callback) {
+ return Api.project(el.val()).then(({ data }) => callback(data));
+ },
- allowClear: this.allowClear,
+ allowClear: this.allowClear,
- dropdownCssClass: 'ajax-project-dropdown',
- });
- if (simpleFilter) return select;
- return new ProjectSelectComboButton(select);
- });
+ dropdownCssClass: 'ajax-project-dropdown',
+ });
+ if (simpleFilter) return select;
+ return new ProjectSelectComboButton(select);
+ });
+ })
+ .catch(() => {});
}
diff --git a/app/assets/javascripts/project_select_combo_button.js b/app/assets/javascripts/project_select_combo_button.js
index 3dbac3ff942..d3b5f532dc1 100644
--- a/app/assets/javascripts/project_select_combo_button.js
+++ b/app/assets/javascripts/project_select_combo_button.js
@@ -44,9 +44,13 @@ export default class ProjectSelectComboButton {
// eslint-disable-next-line class-methods-use-this
openDropdown(event) {
- $(event.currentTarget)
- .siblings('.project-item-select')
- .select2('open');
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ $(event.currentTarget)
+ .siblings('.project-item-select')
+ .select2('open');
+ })
+ .catch(() => {});
}
selectProject() {
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue
index 21095fcba16..83811ab489a 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue
@@ -108,9 +108,7 @@ export default {
</span>
</li>
<li v-for="result in results" :key="result.id">
- <button type="button" @click.prevent="setItem(result.name);">
- {{ result.name }}
- </button>
+ <button type="button" @click.prevent="setItem(result.name)">{{ result.name }}</button>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue
index 056584c8865..a2eb79af4f9 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue
@@ -169,7 +169,7 @@ export default {
</span>
</li>
<li v-for="result in results" :key="result.project_number">
- <button type="button" @click.prevent="setItem(result);">{{ result.name }}</button>
+ <button type="button" @click.prevent="setItem(result)">{{ result.name }}</button>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue
index 728616a441f..fd5d5f86401 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue
@@ -34,7 +34,7 @@ export default {
},
errorMessage() {
return sprintf(
- s__('ClusterIntegration|An error occured while trying to fetch project zones: %{error}'),
+ s__('ClusterIntegration|An error occurred while trying to fetch project zones: %{error}'),
{ error: this.gapiError },
);
},
@@ -82,9 +82,7 @@ export default {
</span>
</li>
<li v-for="result in results" :key="result.id">
- <button type="button" @click.prevent="setItem(result.name);">
- {{ result.name }}
- </button>
+ <button type="button" @click.prevent="setItem(result.name)">{{ result.name }}</button>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index 998554d1be5..1ade1811033 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -115,15 +115,63 @@ const bindEvents = () => {
const templates = {
rails: {
text: 'Ruby on Rails',
- icon: '.template-option svg.icon-rails',
+ icon: '.template-option .icon-rails',
},
express: {
text: 'NodeJS Express',
- icon: '.template-option svg.icon-node-express',
+ icon: '.template-option .icon-express',
},
spring: {
text: 'Spring',
- icon: '.template-option svg.icon-java-spring',
+ icon: '.template-option .icon-spring',
+ },
+ dotnetcore: {
+ text: '.NET Core',
+ icon: '.template-option .icon-dotnet',
+ },
+ gomicro: {
+ text: 'Go Micro',
+ icon: '.template-option .icon-gomicro',
+ },
+ hugo: {
+ text: 'Pages/Hugo',
+ icon: '.template-option .icon-hugo',
+ },
+ jekyll: {
+ text: 'Pages/Jekyll',
+ icon: '.template-option .icon-jekyll',
+ },
+ plainhtml: {
+ text: 'Pages/Plain HTML',
+ icon: '.template-option .icon-plainhtml',
+ },
+ gitbook: {
+ text: 'Pages/GitBook',
+ icon: '.template-option .icon-gitbook',
+ },
+ hexo: {
+ text: 'Pages/Hexo',
+ icon: '.template-option .icon-hexo',
+ },
+ nfhugo: {
+ text: 'Netlify/Hugo',
+ icon: '.template-option .icon-netlify',
+ },
+ nfjekyll: {
+ text: 'Netlify/Jekyll',
+ icon: '.template-option .icon-netlify',
+ },
+ nfplainhtml: {
+ text: 'Netlify/Plain HTML',
+ icon: '.template-option .icon-netlify',
+ },
+ nfgitbook: {
+ text: 'Netlify/GitBook',
+ icon: '.template-option .icon-netlify',
+ },
+ nfhexo: {
+ text: 'Netlify/Hexo',
+ icon: '.template-option .icon-netlify',
},
};
diff --git a/app/assets/javascripts/registry/components/table_registry.vue b/app/assets/javascripts/registry/components/table_registry.vue
index 78c7671856a..81fe0a48c06 100644
--- a/app/assets/javascripts/registry/components/table_registry.vue
+++ b/app/assets/javascripts/registry/components/table_registry.vue
@@ -70,7 +70,7 @@ export default {
</thead>
<tbody>
<tr v-for="item in repo.list" :key="item.tag">
- <td>
+ <td class="monospace">
{{ item.tag }}
<clipboard-button
v-if="item.location"
@@ -80,7 +80,9 @@ export default {
/>
</td>
<td>
- <span v-gl-tooltip.bottom :title="item.revision">{{ item.shortRevision }}</span>
+ <span v-gl-tooltip.bottom class="monospace" :title="item.revision">{{
+ item.shortRevision
+ }}</span>
</td>
<td>
{{ formatSize(item.size) }}
@@ -104,7 +106,7 @@ export default {
:aria-label="s__('ContainerRegistry|Remove tag')"
variant="danger"
class="js-delete-registry d-none d-sm-block float-right"
- @click="handleDeleteRegistry(item);"
+ @click="handleDeleteRegistry(item)"
>
<icon name="remove" />
</gl-button>
diff --git a/app/assets/javascripts/releases/components/app.vue b/app/assets/javascripts/releases/components/app.vue
index 0ad5ee2915c..5a06c4fec58 100644
--- a/app/assets/javascripts/releases/components/app.vue
+++ b/app/assets/javascripts/releases/components/app.vue
@@ -1,12 +1,12 @@
<script>
import { mapState, mapActions } from 'vuex';
-import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
+import { GlSkeletonLoading, GlEmptyState } from '@gitlab/ui';
import ReleaseBlock from './release_block.vue';
export default {
name: 'ReleasesApp',
components: {
- GlLoadingIcon,
+ GlSkeletonLoading,
GlEmptyState,
ReleaseBlock,
},
@@ -43,7 +43,7 @@ export default {
</script>
<template>
<div class="prepend-top-default">
- <gl-loading-icon v-if="isLoading" :size="2" class="js-loading prepend-top-20" />
+ <gl-skeleton-loading v-if="isLoading" class="js-loading" />
<gl-empty-state
v-else-if="shouldRenderEmptyState"
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index 34b97826cdb..7ed1b407ddd 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -45,7 +45,7 @@ export default {
return this.release.author || {};
},
hasAuthor() {
- return _.isEmpty(this.author);
+ return !_.isEmpty(this.author);
},
},
};
@@ -87,7 +87,7 @@ export default {
<div
v-if="assets.links.length || assets.sources.length"
- Sclass="card-text prepend-top-default"
+ class="card-text prepend-top-default"
>
<b>
{{ __('Assets') }}
@@ -98,7 +98,7 @@ export default {
<li v-for="link in assets.links" :key="link.name" class="append-bottom-8">
<gl-link v-gl-tooltip.bottom :title="__('Download asset')" :href="link.url">
<icon name="package" class="align-middle append-right-4 align-text-bottom" />
- {{ link.name }}
+ {{ link.name }} <span v-if="link.external"> {{ __('(external source)') }}</span>
</gl-link>
</li>
</ul>
diff --git a/app/assets/javascripts/releases/store/actions.js b/app/assets/javascripts/releases/store/actions.js
index baa2251403e..e0a922d5ef6 100644
--- a/app/assets/javascripts/releases/store/actions.js
+++ b/app/assets/javascripts/releases/store/actions.js
@@ -11,7 +11,7 @@ export const requestReleases = ({ commit }) => commit(types.REQUEST_RELEASES);
/**
* Fetches the main endpoint.
* Will dispatch requestNamespace action before starting the request.
- * Will dispatch receiveNamespaceSuccess if the request is successfull
+ * Will dispatch receiveNamespaceSuccess if the request is successful
* Will dispatch receiveNamesapceError if the request returns an error
*
* @param {String} projectId
@@ -30,7 +30,7 @@ export const receiveReleasesSuccess = ({ commit }, data) =>
export const receiveReleasesError = ({ commit }) => {
commit(types.RECEIVE_RELEASES_ERROR);
- createFlash(__('An error occured while fetching the releases. Please try again.'));
+ createFlash(__('An error occurred while fetching the releases. Please try again.'));
};
// prevent babel-plugin-rewire from generating an invalid default during karma tests
diff --git a/app/assets/javascripts/reports/components/modal_open_name.vue b/app/assets/javascripts/reports/components/modal_open_name.vue
index 118e4b02c46..4f81cee2a38 100644
--- a/app/assets/javascripts/reports/components/modal_open_name.vue
+++ b/app/assets/javascripts/reports/components/modal_open_name.vue
@@ -26,7 +26,7 @@ export default {
<button
type="button"
class="btn-link btn-blank text-left break-link vulnerability-name-button"
- @click="handleIssueClick();"
+ @click="handleIssueClick()"
>
{{ issue.title }}
</button>
diff --git a/app/assets/javascripts/reports/components/test_issue_body.vue b/app/assets/javascripts/reports/components/test_issue_body.vue
index 938e83de546..7700f49bf7d 100644
--- a/app/assets/javascripts/reports/components/test_issue_body.vue
+++ b/app/assets/javascripts/reports/components/test_issue_body.vue
@@ -30,7 +30,7 @@ export default {
<button
type="button"
class="btn-link btn-blank text-left break-link vulnerability-name-button"
- @click="openModal({ issue });"
+ @click="openModal({ issue })"
>
<div v-if="isNew" class="badge badge-danger append-right-5">{{ s__('New') }}</div>
{{ issue.name }}
diff --git a/app/assets/javascripts/serverless/components/environment_row.vue b/app/assets/javascripts/serverless/components/environment_row.vue
new file mode 100644
index 00000000000..4d18c5c4bdd
--- /dev/null
+++ b/app/assets/javascripts/serverless/components/environment_row.vue
@@ -0,0 +1,65 @@
+<script>
+import FunctionRow from './function_row.vue';
+import ItemCaret from '~/groups/components/item_caret.vue';
+
+export default {
+ components: {
+ ItemCaret,
+ FunctionRow,
+ },
+ props: {
+ env: {
+ type: Array,
+ required: true,
+ },
+ envName: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isOpen: true,
+ };
+ },
+ computed: {
+ envId() {
+ if (this.envName === '*') {
+ return 'env-global';
+ }
+
+ return `env-${this.envName}`;
+ },
+ isOpenClass() {
+ return {
+ 'is-open': this.isOpen,
+ };
+ },
+ },
+ methods: {
+ toggleOpen() {
+ this.isOpen = !this.isOpen;
+ },
+ },
+};
+</script>
+
+<template>
+ <li :id="envId" :class="isOpenClass" class="group-row has-children">
+ <div
+ class="group-row-contents d-flex justify-content-end align-items-center"
+ role="button"
+ @click.stop="toggleOpen"
+ >
+ <div class="folder-toggle-wrap d-flex align-items-center">
+ <item-caret :is-group-open="isOpen" />
+ </div>
+ <div class="group-text flex-grow title namespace-title prepend-left-default">
+ {{ envName }}
+ </div>
+ </div>
+ <ul v-if="isOpen" class="content-list group-list-tree">
+ <function-row v-for="(f, index) in env" :key="f.name" :index="index" :func="f" />
+ </ul>
+ </li>
+</template>
diff --git a/app/assets/javascripts/serverless/components/function_details.vue b/app/assets/javascripts/serverless/components/function_details.vue
new file mode 100644
index 00000000000..4f89ad69129
--- /dev/null
+++ b/app/assets/javascripts/serverless/components/function_details.vue
@@ -0,0 +1,56 @@
+<script>
+import PodBox from './pod_box.vue';
+import Url from './url.vue';
+
+export default {
+ components: {
+ PodBox,
+ Url,
+ },
+ props: {
+ func: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ name() {
+ return this.func.name;
+ },
+ description() {
+ return this.func.description;
+ },
+ funcUrl() {
+ return this.func.url;
+ },
+ podCount() {
+ return this.func.podcount || 0;
+ },
+ },
+};
+</script>
+
+<template>
+ <section id="serverless-function-details">
+ <h3>{{ name }}</h3>
+ <div class="append-bottom-default">
+ <div v-for="(line, index) in description.split('\n')" :key="index">{{ line }}</div>
+ </div>
+ <url :uri="funcUrl" />
+
+ <h4>{{ s__('ServerlessDetails|Kubernetes Pods') }}</h4>
+ <div v-if="podCount > 0">
+ <p>
+ <b v-if="podCount == 1">{{ podCount }} {{ s__('ServerlessDetails|pod in use') }}</b>
+ <b v-else>{{ podCount }} {{ s__('ServerlessDetails|pods in use') }}</b>
+ </p>
+ <pod-box :count="podCount" />
+ <p>
+ {{
+ s__('ServerlessDetails|Number of Kubernetes pods in use over time based on necessity.')
+ }}
+ </p>
+ </div>
+ <div v-else><p>No pods loaded at this time.</p></div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/serverless/components/function_row.vue b/app/assets/javascripts/serverless/components/function_row.vue
index 31f5427c771..773d18781fd 100644
--- a/app/assets/javascripts/serverless/components/function_row.vue
+++ b/app/assets/javascripts/serverless/components/function_row.vue
@@ -1,9 +1,12 @@
<script>
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
+import Url from './url.vue';
+import { visitUrl } from '~/lib/utils/url_utility';
export default {
components: {
Timeago,
+ Url,
},
props: {
func: {
@@ -15,7 +18,18 @@ export default {
name() {
return this.func.name;
},
- url() {
+ description() {
+ const desc = this.func.description.split('\n');
+ if (desc.length > 1) {
+ return desc[1];
+ }
+
+ return desc[0];
+ },
+ detailUrl() {
+ return this.func.detail_url;
+ },
+ targetUrl() {
return this.func.url;
},
image() {
@@ -25,16 +39,34 @@ export default {
return this.func.created_at;
},
},
+ methods: {
+ checkClass(element) {
+ if (element.closest('.no-expand') === null) {
+ return true;
+ }
+
+ return false;
+ },
+ openDetails(e) {
+ if (this.checkClass(e.target)) {
+ visitUrl(this.detailUrl);
+ }
+ },
+ },
};
</script>
<template>
- <div class="gl-responsive-table-row">
- <div class="table-section section-20">{{ name }}</div>
- <div class="table-section section-50">
- <a :href="url">{{ url }}</a>
+ <li :id="name" class="group-row">
+ <div class="group-row-contents" role="button" @click="openDetails">
+ <p class="float-right text-right">
+ <span>{{ image }}</span
+ ><br />
+ <timeago :time="timestamp" />
+ </p>
+ <b>{{ name }}</b>
+ <div v-for="line in description.split('\n')" :key="line">{{ line }}</div>
+ <url :uri="targetUrl" class="prepend-top-8 no-expand" />
</div>
- <div class="table-section section-20">{{ image }}</div>
- <div class="table-section section-10"><timeago :time="timestamp" /></div>
- </div>
+ </li>
</template>
diff --git a/app/assets/javascripts/serverless/components/functions.vue b/app/assets/javascripts/serverless/components/functions.vue
index 349e14670b1..4bde409f906 100644
--- a/app/assets/javascripts/serverless/components/functions.vue
+++ b/app/assets/javascripts/serverless/components/functions.vue
@@ -1,19 +1,21 @@
<script>
import { GlSkeletonLoading } from '@gitlab/ui';
import FunctionRow from './function_row.vue';
+import EnvironmentRow from './environment_row.vue';
import EmptyState from './empty_state.vue';
export default {
components: {
+ EnvironmentRow,
FunctionRow,
EmptyState,
GlSkeletonLoading,
},
props: {
functions: {
- type: Array,
+ type: Object,
required: true,
- default: () => [],
+ default: () => ({}),
},
installed: {
type: Boolean,
@@ -45,30 +47,21 @@ export default {
<section id="serverless-functions">
<div v-if="installed">
<div v-if="hasFunctionData">
- <div class="ci-table js-services-list function-element">
- <div class="gl-responsive-table-row table-row-header" role="row">
- <div class="table-section section-20" role="rowheader">
- {{ s__('Serverless|Function') }}
- </div>
- <div class="table-section section-50" role="rowheader">
- {{ s__('Serverless|Domain') }}
- </div>
- <div class="table-section section-20" role="rowheader">
- {{ s__('Serverless|Runtime') }}
- </div>
- <div class="table-section section-10" role="rowheader">
- {{ s__('Serverless|Last Update') }}
- </div>
+ <template v-if="loadingData">
+ <div v-for="j in 3" :key="j" class="gl-responsive-table-row"><gl-skeleton-loading /></div>
+ </template>
+ <template v-else>
+ <div class="groups-list-tree-container">
+ <ul class="content-list group-list-tree">
+ <environment-row
+ v-for="(env, index) in functions"
+ :key="index"
+ :env="env"
+ :env-name="index"
+ />
+ </ul>
</div>
- <template v-if="loadingData">
- <div v-for="j in 3" :key="j" class="gl-responsive-table-row">
- <gl-skeleton-loading />
- </div>
- </template>
- <template v-else>
- <function-row v-for="f in functions" :key="f.name" :func="f" />
- </template>
- </div>
+ </template>
</div>
<div v-else class="empty-state js-empty-state">
<div class="text-content">
@@ -108,16 +101,3 @@ export default {
<empty-state v-else :clusters-path="clustersPath" :help-path="helpPath" />
</section>
</template>
-
-<style>
-.top-area {
- border-bottom: 0;
-}
-
-.function-element {
- border-bottom: 1px solid #e5e5e5;
- border-bottom-color: rgb(229, 229, 229);
- border-bottom-style: solid;
- border-bottom-width: 1px;
-}
-</style>
diff --git a/app/assets/javascripts/serverless/components/pod_box.vue b/app/assets/javascripts/serverless/components/pod_box.vue
new file mode 100644
index 00000000000..04d3641bce3
--- /dev/null
+++ b/app/assets/javascripts/serverless/components/pod_box.vue
@@ -0,0 +1,36 @@
+<script>
+export default {
+ props: {
+ count: {
+ type: Number,
+ required: true,
+ },
+ color: {
+ type: String,
+ required: false,
+ default: 'green',
+ },
+ },
+ methods: {
+ boxOffset(i) {
+ return 20 * (i - 1);
+ },
+ },
+};
+</script>
+
+<template>
+ <svg :width="boxOffset(count + 1)" :height="20">
+ <rect
+ v-for="i in count"
+ :key="i"
+ width="15"
+ height="15"
+ rx="5"
+ ry="5"
+ :fill="color"
+ :x="boxOffset(i)"
+ y="0"
+ />
+ </svg>
+</template>
diff --git a/app/assets/javascripts/serverless/components/url.vue b/app/assets/javascripts/serverless/components/url.vue
new file mode 100644
index 00000000000..ca53bf6c52a
--- /dev/null
+++ b/app/assets/javascripts/serverless/components/url.vue
@@ -0,0 +1,38 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ components: {
+ Icon,
+ GlButton,
+ ClipboardButton,
+ },
+ props: {
+ uri: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="clipboard-group">
+ <div class="url-text-field label label-monospace">{{ uri }}</div>
+ <clipboard-button
+ :text="uri"
+ :title="s__('ServerlessURL|Copy URL to clipboard')"
+ class="input-group-text js-clipboard-btn"
+ />
+ <gl-button
+ :href="uri"
+ target="_blank"
+ rel="noopener noreferrer nofollow"
+ class="input-group-text btn btn-default"
+ >
+ <icon name="external-link" />
+ </gl-button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/serverless/serverless_bundle.js b/app/assets/javascripts/serverless/serverless_bundle.js
index 3e3b81ba247..47a510d5fb5 100644
--- a/app/assets/javascripts/serverless/serverless_bundle.js
+++ b/app/assets/javascripts/serverless/serverless_bundle.js
@@ -4,23 +4,65 @@ import { s__ } from '../locale';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
import ServerlessStore from './stores/serverless_store';
+import ServerlessDetailsStore from './stores/serverless_details_store';
import GetFunctionsService from './services/get_functions_service';
import Functions from './components/functions.vue';
+import FunctionDetails from './components/function_details.vue';
export default class Serverless {
constructor() {
- const { statusPath, clustersPath, helpPath, installed } = document.querySelector(
- '.js-serverless-functions-page',
- ).dataset;
+ if (document.querySelector('.js-serverless-function-details-page') != null) {
+ const {
+ serviceName,
+ serviceDescription,
+ serviceEnvironment,
+ serviceUrl,
+ serviceNamespace,
+ servicePodcount,
+ } = document.querySelector('.js-serverless-function-details-page').dataset;
+ const el = document.querySelector('#js-serverless-function-details');
+ this.store = new ServerlessDetailsStore();
+ const { store } = this;
- this.service = new GetFunctionsService(statusPath);
- this.knativeInstalled = installed !== undefined;
- this.store = new ServerlessStore(this.knativeInstalled, clustersPath, helpPath);
- this.initServerless();
- this.functionLoadCount = 0;
+ const service = {
+ name: serviceName,
+ description: serviceDescription,
+ environment: serviceEnvironment,
+ url: serviceUrl,
+ namespace: serviceNamespace,
+ podcount: servicePodcount,
+ };
- if (statusPath && this.knativeInstalled) {
- this.initPolling();
+ this.store.updateDetailedFunction(service);
+ this.functionDetails = new Vue({
+ el,
+ data() {
+ return {
+ state: store.state,
+ };
+ },
+ render(createElement) {
+ return createElement(FunctionDetails, {
+ props: {
+ func: this.state.functionDetail,
+ },
+ });
+ },
+ });
+ } else {
+ const { statusPath, clustersPath, helpPath, installed } = document.querySelector(
+ '.js-serverless-functions-page',
+ ).dataset;
+
+ this.service = new GetFunctionsService(statusPath);
+ this.knativeInstalled = installed !== undefined;
+ this.store = new ServerlessStore(this.knativeInstalled, clustersPath, helpPath);
+ this.initServerless();
+ this.functionLoadCount = 0;
+
+ if (statusPath && this.knativeInstalled) {
+ this.initPolling();
+ }
}
}
@@ -55,7 +97,7 @@ export default class Serverless {
resource: this.service,
method: 'fetchData',
successCallback: data => this.handleSuccess(data),
- errorCallback: () => this.handleError(),
+ errorCallback: () => Serverless.handleError(),
});
if (!Visibility.hidden()) {
@@ -64,7 +106,7 @@ export default class Serverless {
this.service
.fetchData()
.then(data => this.handleSuccess(data))
- .catch(() => this.handleError());
+ .catch(() => Serverless.handleError());
}
Visibility.change(() => {
@@ -102,5 +144,6 @@ export default class Serverless {
}
this.functions.$destroy();
+ this.functionDetails.$destroy();
}
}
diff --git a/app/assets/javascripts/serverless/stores/serverless_details_store.js b/app/assets/javascripts/serverless/stores/serverless_details_store.js
new file mode 100644
index 00000000000..5394d2cded1
--- /dev/null
+++ b/app/assets/javascripts/serverless/stores/serverless_details_store.js
@@ -0,0 +1,11 @@
+export default class ServerlessDetailsStore {
+ constructor() {
+ this.state = {
+ functionDetail: {},
+ };
+ }
+
+ updateDetailedFunction(func) {
+ this.state.functionDetail = func;
+ }
+}
diff --git a/app/assets/javascripts/serverless/stores/serverless_store.js b/app/assets/javascripts/serverless/stores/serverless_store.js
index 774c15b5b12..816d55a03f9 100644
--- a/app/assets/javascripts/serverless/stores/serverless_store.js
+++ b/app/assets/javascripts/serverless/stores/serverless_store.js
@@ -1,7 +1,7 @@
export default class ServerlessStore {
constructor(knativeInstalled = false, clustersPath, helpPath) {
this.state = {
- functions: [],
+ functions: {},
hasFunctionData: true,
loadingData: true,
installed: knativeInstalled,
@@ -10,8 +10,13 @@ export default class ServerlessStore {
};
}
- updateFunctionsFromServer(functions = []) {
- this.state.functions = functions;
+ updateFunctionsFromServer(upstreamFunctions = []) {
+ this.state.functions = upstreamFunctions.reduce((rv, func) => {
+ const envs = rv;
+ envs[func.environment_scope] = (rv[func.environment_scope] || []).concat([func]);
+
+ return envs;
+ }, {});
}
updateLoadingState(loadingData) {
diff --git a/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js b/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js
index 14a89ef9293..3a8631a196f 100644
--- a/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js
+++ b/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js
@@ -12,9 +12,8 @@ class EmojiMenuInModal extends AwardsHandler {
this.bindEvents();
}
- postEmoji($emojiButton, awardUrl, selectedEmoji, callback) {
+ postEmoji($emojiButton, awardUrl, selectedEmoji) {
this.selectEmojiCallback(selectedEmoji, this.emoji.glEmojiTag(selectedEmoji));
- callback();
}
}
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 f04f7606976..e9ed05e30cd 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
@@ -66,19 +66,23 @@ export default {
import(/* webpackChunkName: 'emoji' */ '~/emoji')
.then(Emoji => {
- if (this.emoji) {
- this.emojiTag = Emoji.glEmojiTag(this.emoji);
- }
- this.noEmoji = this.emoji === '';
- this.defaultEmojiTag = Emoji.glEmojiTag('speech_balloon');
+ Emoji.initEmojiMap()
+ .then(() => {
+ if (this.emoji) {
+ this.emojiTag = Emoji.glEmojiTag(this.emoji);
+ }
+ this.noEmoji = this.emoji === '';
+ this.defaultEmojiTag = Emoji.glEmojiTag('speech_balloon');
- this.emojiMenu = new EmojiMenuInModal(
- Emoji,
- toggleEmojiMenuButtonSelector,
- emojiMenuClass,
- this.setEmoji,
- this.$refs.userStatusForm,
- );
+ this.emojiMenu = new EmojiMenuInModal(
+ Emoji,
+ toggleEmojiMenuButtonSelector,
+ emojiMenuClass,
+ this.setEmoji,
+ this.$refs.userStatusForm,
+ );
+ })
+ .catch(() => createFlash(__('Failed to load emoji list.')));
})
.catch(() => createFlash(__('Failed to load emoji list.')));
},
@@ -219,7 +223,7 @@ export default {
name="button"
type="button"
class="js-clear-user-status-button clear-user-status btn"
- @click="clearStatusInputs();"
+ @click="clearStatusInputs()"
>
<icon name="close" />
</button>
diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
index faea64c9841..c5cfa92f3c8 100644
--- a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
@@ -104,9 +104,7 @@ export default {
</div>
<div class="title hide-collapsed">
- {{
- sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName })
- }}
+ {{ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) }}
<button
v-if="isEditable"
class="float-right lock-edit"
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index d3a4f9c81e0..c03b2a68c78 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -102,13 +102,13 @@ export default {
/>
<div class="title hide-collapsed">
{{ __('Time tracking') }}
- <div v-if="!showHelpState" class="help-button float-right" @click="toggleHelpState(true);">
+ <div v-if="!showHelpState" class="help-button float-right" @click="toggleHelpState(true)">
<i class="fa fa-question-circle" aria-hidden="true"> </i>
</div>
<div
v-if="showHelpState"
class="close-help-button float-right"
- @click="toggleHelpState(false);"
+ @click="toggleHelpState(false)"
>
<i class="fa fa-close" aria-hidden="true"> </i>
</div>
diff --git a/app/assets/javascripts/task_list.js b/app/assets/javascripts/task_list.js
index edefb3735d7..5172a1ef3d6 100644
--- a/app/assets/javascripts/task_list.js
+++ b/app/assets/javascripts/task_list.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import 'deckar01-task_list';
+import { __ } from '~/locale';
import axios from './lib/utils/axios_utils';
import Flash from './flash';
@@ -8,46 +9,79 @@ export default class TaskList {
this.selector = options.selector;
this.dataType = options.dataType;
this.fieldName = options.fieldName;
+ this.lockVersion = options.lockVersion;
+ this.taskListContainerSelector = `${this.selector} .js-task-list-container`;
+ this.updateHandler = this.update.bind(this);
this.onSuccess = options.onSuccess || (() => {});
- this.onError = function showFlash(e) {
- let errorMessages = '';
+ this.onError =
+ options.onError ||
+ function showFlash(e) {
+ let errorMessages = '';
- if (e.response.data && typeof e.response.data === 'object') {
- errorMessages = e.response.data.errors.join(' ');
- }
+ if (e.response.data && typeof e.response.data === 'object') {
+ errorMessages = e.response.data.errors.join(' ');
+ }
- return new Flash(errorMessages || 'Update failed', 'alert');
- };
+ return new Flash(errorMessages || __('Update failed'), 'alert');
+ };
this.init();
}
init() {
- // Prevent duplicate event bindings
- this.disable();
- $(`${this.selector} .js-task-list-container`).taskList('enable');
- $(document).on(
- 'tasklist:changed',
- `${this.selector} .js-task-list-container`,
- this.update.bind(this),
- );
+ this.disable(); // Prevent duplicate event bindings
+
+ $(this.taskListContainerSelector).taskList('enable');
+ $(document).on('tasklist:changed', this.taskListContainerSelector, this.updateHandler);
+ }
+
+ getTaskListTarget(e) {
+ return e && e.currentTarget ? $(e.currentTarget) : $(this.taskListContainerSelector);
+ }
+
+ disableTaskListItems(e) {
+ this.getTaskListTarget(e).taskList('disable');
+ }
+
+ enableTaskListItems(e) {
+ this.getTaskListTarget(e).taskList('enable');
}
disable() {
- $(`${this.selector} .js-task-list-container`).taskList('disable');
- $(document).off('tasklist:changed', `${this.selector} .js-task-list-container`);
+ this.disableTaskListItems();
+ $(document).off('tasklist:changed', this.taskListContainerSelector);
}
update(e) {
const $target = $(e.target);
+ const { index, checked, lineNumber, lineSource } = e.detail;
const patchData = {};
+
patchData[this.dataType] = {
[this.fieldName]: $target.val(),
+ lock_version: this.lockVersion,
+ update_task: {
+ index,
+ checked,
+ line_number: lineNumber,
+ line_source: lineSource,
+ },
};
+ this.disableTaskListItems(e);
+
return axios
.patch($target.data('updateUrl') || $('form.js-issuable-update').attr('action'), patchData)
- .then(({ data }) => this.onSuccess(data))
- .catch(err => this.onError(err));
+ .then(({ data }) => {
+ this.lockVersion = data.lock_version;
+ this.enableTaskListItems(e);
+
+ return this.onSuccess(data);
+ })
+ .catch(({ response }) => {
+ this.enableTaskListItems(e);
+
+ return this.onError(response.data);
+ });
}
}
diff --git a/app/assets/javascripts/terminal/terminal.js b/app/assets/javascripts/terminal/terminal.js
index 560f50ebf8f..e5dd7a465ea 100644
--- a/app/assets/javascripts/terminal/terminal.js
+++ b/app/assets/javascripts/terminal/terminal.js
@@ -2,11 +2,13 @@ import _ from 'underscore';
import $ from 'jquery';
import { Terminal } from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit';
+import * as webLinks from 'xterm/lib/addons/webLinks/webLinks';
import { canScrollUp, canScrollDown } from '~/lib/utils/dom_utils';
const SCROLL_MARGIN = 5;
Terminal.applyAddon(fit);
+Terminal.applyAddon(webLinks);
export default class GLTerminal {
constructor(element, options = {}) {
@@ -48,6 +50,7 @@ export default class GLTerminal {
this.terminal.open(this.container);
this.terminal.fit();
+ this.terminal.webLinksInit();
this.terminal.focus();
this.socket.onopen = () => {
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index ce051582299..8c71615dff2 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -93,23 +93,22 @@ function UsersSelect(currentUser, els, options = {}) {
}
// Save current selected user to the DOM
- const input = document.createElement('input');
- input.type = 'hidden';
- input.name = $dropdown.data('fieldName');
-
- const currentUserInfo = $dropdown.data('currentUserInfo');
-
- if (currentUserInfo) {
- input.value = currentUserInfo.id;
- input.dataset.meta = _.escape(currentUserInfo.name);
- } else if (_this.currentUser) {
- input.value = _this.currentUser.id;
- }
+ const currentUserInfo = $dropdown.data('currentUserInfo') || {};
+ const currentUser = _this.currentUser || {};
+ const fieldName = $dropdown.data('fieldName');
+ const userName = currentUserInfo.name;
+ const userId = currentUserInfo.id || currentUser.id;
+
+ const inputHtmlString = _.template(`
+ <input type="hidden" name="<%- fieldName %>"
+ data-meta="<%- userName %>"
+ value="<%- userId %>" />
+ `)({ fieldName, userName, userId });
if ($selectbox) {
- $dropdown.parent().before(input);
+ $dropdown.parent().before(inputHtmlString);
} else {
- $dropdown.after(input);
+ $dropdown.after(inputHtmlString);
}
};
@@ -579,101 +578,109 @@ function UsersSelect(currentUser, els, options = {}) {
};
})(this),
);
- $('.ajax-users-select').each(
- (function(_this) {
- return function(i, select) {
- var firstUser, showAnyUser, showEmailUser, showNullUser;
- var options = {};
- options.skipLdap = $(select).hasClass('skip_ldap');
- options.projectId = $(select).data('projectId');
- options.groupId = $(select).data('groupId');
- options.showCurrentUser = $(select).data('currentUser');
- options.authorId = $(select).data('authorId');
- options.skipUsers = $(select).data('skipUsers');
- showNullUser = $(select).data('nullUser');
- showAnyUser = $(select).data('anyUser');
- showEmailUser = $(select).data('emailUser');
- firstUser = $(select).data('firstUser');
- return $(select).select2({
- placeholder: 'Search for a user',
- multiple: $(select).hasClass('multiselect'),
- minimumInputLength: 0,
- query: function(query) {
- return _this.users(query.term, options, function(users) {
- var anyUser, data, emailUser, index, len, name, nullUser, obj, ref;
- data = {
- results: users,
- };
- if (query.term.length === 0) {
- if (firstUser) {
- // Move current user to the front of the list
- ref = data.results;
-
- for (index = 0, len = ref.length; index < len; index += 1) {
- obj = ref[index];
- if (obj.username === firstUser) {
- data.results.splice(index, 1);
- data.results.unshift(obj);
- break;
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ $('.ajax-users-select').each(
+ (function(_this) {
+ return function(i, select) {
+ var firstUser, showAnyUser, showEmailUser, showNullUser;
+ var options = {};
+ options.skipLdap = $(select).hasClass('skip_ldap');
+ options.projectId = $(select).data('projectId');
+ options.groupId = $(select).data('groupId');
+ options.showCurrentUser = $(select).data('currentUser');
+ options.authorId = $(select).data('authorId');
+ options.skipUsers = $(select).data('skipUsers');
+ showNullUser = $(select).data('nullUser');
+ showAnyUser = $(select).data('anyUser');
+ showEmailUser = $(select).data('emailUser');
+ firstUser = $(select).data('firstUser');
+ return $(select).select2({
+ placeholder: 'Search for a user',
+ multiple: $(select).hasClass('multiselect'),
+ minimumInputLength: 0,
+ query: function(query) {
+ return _this.users(query.term, options, function(users) {
+ var anyUser, data, emailUser, index, len, name, nullUser, obj, ref;
+ data = {
+ results: users,
+ };
+ if (query.term.length === 0) {
+ if (firstUser) {
+ // Move current user to the front of the list
+ ref = data.results;
+
+ for (index = 0, len = ref.length; index < len; index += 1) {
+ obj = ref[index];
+ if (obj.username === firstUser) {
+ data.results.splice(index, 1);
+ data.results.unshift(obj);
+ break;
+ }
+ }
+ }
+ if (showNullUser) {
+ nullUser = {
+ name: 'Unassigned',
+ id: 0,
+ };
+ data.results.unshift(nullUser);
+ }
+ if (showAnyUser) {
+ name = showAnyUser;
+ if (name === true) {
+ name = 'Any User';
+ }
+ anyUser = {
+ name: name,
+ id: null,
+ };
+ data.results.unshift(anyUser);
}
}
- }
- if (showNullUser) {
- nullUser = {
- name: 'Unassigned',
- id: 0,
- };
- data.results.unshift(nullUser);
- }
- if (showAnyUser) {
- name = showAnyUser;
- if (name === true) {
- name = 'Any User';
+ if (
+ showEmailUser &&
+ data.results.length === 0 &&
+ query.term.match(/^[^@]+@[^@]+$/)
+ ) {
+ var trimmed = query.term.trim();
+ emailUser = {
+ name: 'Invite "' + trimmed + '" by email',
+ username: trimmed,
+ id: trimmed,
+ invite: true,
+ };
+ data.results.unshift(emailUser);
}
- anyUser = {
- name: name,
- id: null,
- };
- data.results.unshift(anyUser);
- }
- }
- if (showEmailUser && data.results.length === 0 && query.term.match(/^[^@]+@[^@]+$/)) {
- var trimmed = query.term.trim();
- emailUser = {
- name: 'Invite "' + trimmed + '" by email',
- username: trimmed,
- id: trimmed,
- invite: true,
- };
- data.results.unshift(emailUser);
- }
- return query.callback(data);
+ return query.callback(data);
+ });
+ },
+ initSelection: function() {
+ var args;
+ args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
+ return _this.initSelection.apply(_this, args);
+ },
+ formatResult: function() {
+ var args;
+ args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
+ return _this.formatResult.apply(_this, args);
+ },
+ formatSelection: function() {
+ var args;
+ args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
+ return _this.formatSelection.apply(_this, args);
+ },
+ dropdownCssClass: 'ajax-users-dropdown',
+ // we do not want to escape markup since we are displaying html in results
+ escapeMarkup: function(m) {
+ return m;
+ },
});
- },
- initSelection: function() {
- var args;
- args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
- return _this.initSelection.apply(_this, args);
- },
- formatResult: function() {
- var args;
- args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
- return _this.formatResult.apply(_this, args);
- },
- formatSelection: function() {
- var args;
- args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
- return _this.formatSelection.apply(_this, args);
- },
- dropdownCssClass: 'ajax-users-dropdown',
- // we do not want to escape markup since we are displaying html in results
- escapeMarkup: function(m) {
- return m;
- },
- });
- };
- })(this),
- );
+ };
+ })(this),
+ );
+ })
+ .catch(() => {});
}
UsersSelect.prototype.initSelection = function(element, callback) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
index 2f2a37347af..da0a9483f8e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
@@ -54,6 +54,12 @@ export default {
deployTimeago() {
return this.timeFormated(this.deployment.deployed_at);
},
+ deploymentExternalUrl() {
+ if (this.deployment.changes && this.deployment.changes.length === 1) {
+ return this.deployment.changes[0].external_url;
+ }
+ return this.deployment.external_url;
+ },
hasExternalUrls() {
return !!(this.deployment.external_url && this.deployment.external_url_formatted);
},
@@ -78,7 +84,7 @@ export default {
: '';
},
shouldRenderDropdown() {
- return this.deployment.changes && this.deployment.changes.length > 0;
+ return this.deployment.changes && this.deployment.changes.length > 1;
},
showMemoryUsage() {
return this.hasMetrics && this.showMetrics;
@@ -154,12 +160,12 @@ export default {
v-if="shouldRenderDropdown"
class="js-mr-wigdet-deployment-dropdown inline"
:items="deployment.changes"
- :main-action-link="deployment.external_url"
+ :main-action-link="deploymentExternalUrl"
filter-key="path"
>
<template slot="mainAction" slot-scope="slotProps">
<review-app-link
- :link="deployment.external_url"
+ :link="deploymentExternalUrl"
:css-class="`deploy-link js-deploy-url inline ${slotProps.className}`"
/>
</template>
@@ -183,7 +189,7 @@ export default {
</filtered-search-dropdown>
<review-app-link
v-else
- :link="deployment.external_url"
+ :link="deploymentExternalUrl"
css-class="js-deploy-url js-deploy-url-feature-flag deploy-link btn btn-default btn-sm inlin"
/>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 3b9fc2661ef..50ab7ead582 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -135,7 +135,7 @@ export default {
<span class="dropdown">
<button
type="button"
- class="btn dropdown-toggle"
+ class="btn dropdown-toggle qa-dropdown-toggle"
data-toggle="dropdown"
aria-label="Download as"
aria-haspopup="true"
@@ -145,12 +145,20 @@ export default {
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li>
- <a :href="mr.emailPatchesPath" class="js-download-email-patches" download>
+ <a
+ :href="mr.emailPatchesPath"
+ class="js-download-email-patches qa-download-email-patches"
+ download
+ >
{{ s__('mrWidget|Email patches') }}
</a>
</li>
<li>
- <a :href="mr.plainDiffPath" class="js-download-plain-diff" download>
+ <a
+ :href="mr.plainDiffPath"
+ class="js-download-plain-diff qa-download-plain-diff"
+ download
+ >
{{ s__('mrWidget|Plain diff') }}
</a>
</li>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index f11cf21b0ca..9e63aa00341 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -5,6 +5,7 @@ import PipelineStage from '~/pipelines/components/stage.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import Icon from '~/vue_shared/components/icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import mrWidgetPipelineMixin from 'ee_else_ce/vue_merge_request_widget/mixins/mr_widget_pipeline';
export default {
name: 'MRWidgetPipeline',
@@ -13,7 +14,10 @@ export default {
CiIcon,
Icon,
TooltipOnTruncate,
+ LinkedPipelinesMiniList: () =>
+ import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'),
},
+ mixins: [mrWidgetPipelineMixin],
props: {
pipeline: {
type: Object,
@@ -82,8 +86,7 @@ export default {
<div v-if="hasPipeline || hasCIError" class="ci-widget media">
<template v-if="hasCIError">
<div
- class="add-border ci-status-icon ci-status-icon-failed ci-error
- js-ci-error append-right-default"
+ class="add-border ci-status-icon ci-status-icon-failed ci-error js-ci-error append-right-default"
>
<icon :size="32" name="status_failed_borderless" />
</div>
@@ -101,16 +104,13 @@ export default {
<a :href="pipeline.path" class="pipeline-id font-weight-normal pipeline-number"
>#{{ pipeline.id }}</a
>
-
{{ pipeline.details.status.label }}
-
<template v-if="hasCommitInfo">
for
<a
:href="pipeline.commit.commit_path"
class="commit-sha js-commit-link font-weight-normal"
- >
- {{ pipeline.commit.short_id }}</a
+ >{{ pipeline.commit.short_id }}</a
>
on
<tooltip-on-truncate
@@ -126,15 +126,22 @@ export default {
</div>
<div>
<span class="mr-widget-pipeline-graph">
- <span v-if="hasStages" class="stage-cell">
- <div
- v-for="(stage, i) in pipeline.details.stages"
- :key="i"
- class="stage-container dropdown js-mini-pipeline-graph mr-widget-pipeline-stages"
- >
- <pipeline-stage :stage="stage" />
- </div>
+ <span class="stage-cell">
+ <linked-pipelines-mini-list v-if="triggeredBy.length" :triggered-by="triggeredBy" />
+ <template v-if="hasStages">
+ <div
+ v-for="(stage, i) in pipeline.details.stages"
+ :key="i"
+ :class="{
+ 'has-downstream': hasDownstream(i),
+ }"
+ class="stage-container dropdown js-mini-pipeline-graph mr-widget-pipeline-stages"
+ >
+ <pipeline-stage :stage="stage" />
+ </div>
+ </template>
</span>
+ <linked-pipelines-mini-list v-if="triggered.length" :triggered="triggered" />
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
index dd940548e30..780ecdcdac4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
@@ -7,7 +7,7 @@ export default {
tooltip,
},
created() {
- this.removesBranchText = __('<strong>Removes</strong> source branch');
+ this.removesBranchText = __('<strong>Deletes</strong> source branch');
this.tooltipTitle = __('A user with write access to the source branch selected this option');
},
};
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
new file mode 100644
index 00000000000..a38f25cce35
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
@@ -0,0 +1,40 @@
+<script>
+export default {
+ props: {
+ value: {
+ type: String,
+ required: true,
+ },
+ label: {
+ type: String,
+ required: true,
+ },
+ inputId: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <li>
+ <div class="commit-message-editor">
+ <div class="d-flex flex-wrap align-items-center justify-content-between">
+ <label class="col-form-label" :for="inputId">
+ <strong>{{ label }}</strong>
+ </label>
+ <slot name="header"></slot>
+ </div>
+ <textarea
+ :id="inputId"
+ :value="value"
+ class="form-control js-gfm-input append-bottom-default commit-message-edit"
+ required="required"
+ rows="7"
+ @input="$emit('input', $event.target.value)"
+ ></textarea>
+ <slot name="checkbox"></slot>
+ </div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
new file mode 100644
index 00000000000..b6722de5277
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
@@ -0,0 +1,37 @@
+<script>
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ props: {
+ commits: {
+ type: Array,
+ required: true,
+ default: () => [],
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-dropdown
+ right
+ text="Use an existing commit message"
+ variant="link"
+ class="mr-commit-dropdown"
+ >
+ <gl-dropdown-item
+ v-for="commit in commits"
+ :key="commit.short_id"
+ class="text-nowrap text-truncate"
+ @click="$emit('input', commit.message)"
+ >
+ <span class="monospace mr-2">{{ commit.short_id }}</span> {{ commit.title }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
new file mode 100644
index 00000000000..33963d5e1e6
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
@@ -0,0 +1,91 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import _ from 'underscore';
+import { __, n__, sprintf, s__ } from '~/locale';
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ components: {
+ Icon,
+ GlButton,
+ },
+ props: {
+ isSquashEnabled: {
+ type: Boolean,
+ required: true,
+ },
+ commitsCount: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ targetBranch: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ expanded: false,
+ };
+ },
+ computed: {
+ collapseIcon() {
+ return this.expanded ? 'chevron-down' : 'chevron-right';
+ },
+ commitsCountMessage() {
+ return n__(__('%d commit'), __('%d commits'), this.isSquashEnabled ? 1 : this.commitsCount);
+ },
+ modifyLinkMessage() {
+ return this.isSquashEnabled ? __('Modify commit messages') : __('Modify merge commit');
+ },
+ ariaLabel() {
+ return this.expanded ? __('Collapse') : __('Expand');
+ },
+ message() {
+ return sprintf(
+ s__(
+ 'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}.',
+ ),
+ {
+ commitCount: `<strong class="commits-count-message">${this.commitsCountMessage}</strong>`,
+ mergeCommitCount: `<strong>${s__('mrWidgetCommitsAdded|1 merge commit')}</strong>`,
+ targetBranch: `<span class="label-branch">${_.escape(this.targetBranch)}</span>`,
+ },
+ false,
+ );
+ },
+ },
+ methods: {
+ toggle() {
+ this.expanded = !this.expanded;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div
+ class="js-mr-widget-commits-count mr-widget-extension clickable d-flex align-items-center px-3 py-2"
+ @click="toggle()"
+ >
+ <gl-button
+ :aria-label="ariaLabel"
+ variant="blank"
+ class="commit-edit-toggle square s24 mr-2"
+ @click.stop="toggle()"
+ >
+ <icon :name="collapseIcon" :size="16" />
+ </gl-button>
+ <span v-if="expanded">{{ __('Collapse') }}</span>
+ <span v-else>
+ <span class="vertical-align-middle" v-html="message"></span>
+ <gl-button variant="link" class="modify-message-button">
+ {{ modifyLinkMessage }}
+ </gl-button>
+ </span>
+ </div>
+ <div v-show="expanded"><slot></slot></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 27352e0b2b1..f6f445c1cef 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
@@ -1,10 +1,14 @@
<script>
-import statusIcon from '../mr_widget_status_icon.vue';
+import $ from 'jquery';
+import _ from 'underscore';
+import { s__, sprintf } from '~/locale';
+import { mouseenter, debouncedMouseleave, togglePopover } from '~/shared/popover';
+import StatusIcon from '../mr_widget_status_icon.vue';
export default {
name: 'MRWidgetConflicts',
components: {
- statusIcon,
+ StatusIcon,
},
props: {
/* TODO: This is providing all store and service down when it
@@ -15,6 +19,52 @@ export default {
default: () => ({}),
},
},
+ computed: {
+ popoverTitle() {
+ return s__(
+ 'mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected.',
+ );
+ },
+ showResolveButton() {
+ return this.mr.conflictResolutionPath && this.mr.canMerge;
+ },
+ showPopover() {
+ return this.showResolveButton && this.mr.sourceBranchProtected;
+ },
+ },
+ mounted() {
+ if (this.showPopover) {
+ const $el = $(this.$refs.popover);
+
+ $el
+ .popover({
+ html: true,
+ trigger: 'focus',
+ container: 'body',
+ placement: 'top',
+ template:
+ '<div class="popover" role="tooltip"><div class="arrow"></div><p class="popover-header"></p><div class="popover-body"></div></div>',
+ title: s__(
+ 'mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected.',
+ ),
+ content: sprintf(
+ s__('mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}'),
+ {
+ link_start: `<a href="${_.escape(
+ this.mr.conflictsDocsPath,
+ )}" target="_blank" rel="noopener noreferrer">`,
+ link_end: '</a>',
+ },
+ false,
+ ),
+ })
+ .on('mouseenter', mouseenter)
+ .on('mouseleave', debouncedMouseleave(300))
+ .on('show.bs.popover', () => {
+ window.addEventListener('scroll', togglePopover.bind($el, false), { once: true });
+ });
+ }
+ },
};
</script>
<template>
@@ -38,13 +88,15 @@ To merge this request, first rebase locally.`)
}}
</span>
</span>
- <a
- v-if="mr.canMerge && mr.conflictResolutionPath"
- :href="mr.conflictResolutionPath"
- class="js-resolve-conflicts-button btn btn-default btn-sm"
- >
- {{ s__('mrWidget|Resolve conflicts') }}
- </a>
+ <span v-if="showResolveButton" ref="popover">
+ <a
+ :href="mr.conflictResolutionPath"
+ :disabled="mr.sourceBranchProtected"
+ class="js-resolve-conflicts-button btn btn-default btn-sm"
+ >
+ {{ s__('mrWidget|Resolve conflicts') }}
+ </a>
+ </span>
<button
v-if="mr.canMerge"
class="js-merge-locally-button btn btn-default btn-sm"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue
index 02c76db4a50..1b3af2fccf2 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue
@@ -106,11 +106,11 @@ export default {
<a :href="mr.targetBranchPath" class="label-branch"> {{ mr.targetBranch }} </a>
</p>
<p v-if="mr.shouldRemoveSourceBranch">
- {{ s__('mrWidget|The source branch will be removed') }}
+ {{ s__('mrWidget|The source branch will be deleted') }}
</p>
<p v-else class="d-flex align-items-start">
<span class="append-right-10">
- {{ s__('mrWidget|The source branch will not be removed') }}
+ {{ s__('mrWidget|The source branch will not be deleted') }}
</span>
<a
v-if="canRemoveSourceBranch"
@@ -121,7 +121,7 @@ export default {
@click.prevent="removeSourceBranch"
>
<i v-if="isRemovingSourceBranch" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
- {{ s__('mrWidget|Remove source branch') }}
+ {{ s__('mrWidget|Delete source branch') }}
</a>
</p>
</section>
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 fe83fe58b67..b9562fbc260 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
@@ -84,7 +84,7 @@ export default {
.removeSourceBranch()
.then(res => res.data)
.then(data => {
- if (data.message === 'Branch was removed') {
+ if (data.message === 'Branch was deleted') {
eventHub.$emit('MRWidgetUpdateRequested', () => {
this.isMakingRequest = false;
});
@@ -174,22 +174,22 @@ export default {
</template>
</p>
<p v-if="mr.sourceBranchRemoved">
- {{ s__('mrWidget|The source branch has been removed') }}
+ {{ s__('mrWidget|The source branch has been deleted') }}
</p>
<p v-if="shouldShowRemoveSourceBranch" class="space-children">
- <span>{{ s__('mrWidget|You can remove source branch now') }}</span>
+ <span>{{ s__('mrWidget|You can delete the source branch now') }}</span>
<button
:disabled="isMakingRequest"
type="button"
class="btn btn-sm btn-default js-remove-branch-button"
@click="removeSourceBranch"
>
- {{ s__('mrWidget|Remove Source Branch') }}
+ {{ s__('mrWidget|Delete source branch') }}
</button>
</p>
<p v-if="shouldShowSourceBranchRemoving">
<gl-loading-icon :inline="true" />
- <span> {{ s__('mrWidget|The source branch is being removed') }} </span>
+ <span> {{ s__('mrWidget|The source branch is being deleted') }} </span>
</p>
</section>
</div>
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 84c8a3464a5..9b4e80ee3a3 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
@@ -2,17 +2,24 @@
import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg';
import simplePoll from '~/lib/utils/simple_poll';
+import { __ } from '~/locale';
import MergeRequest from '../../../merge_request';
import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon.vue';
import eventHub from '../../event_hub';
import SquashBeforeMerge from './squash_before_merge.vue';
+import CommitsHeader from './commits_header.vue';
+import CommitEdit from './commit_edit.vue';
+import CommitMessageDropdown from './commit_message_dropdown.vue';
export default {
name: 'ReadyToMerge',
components: {
statusIcon,
- 'squash-before-merge': SquashBeforeMerge,
+ SquashBeforeMerge,
+ CommitsHeader,
+ CommitEdit,
+ CommitMessageDropdown,
},
props: {
mr: { type: Object, required: true },
@@ -22,26 +29,20 @@ export default {
return {
removeSourceBranch: this.mr.shouldRemoveSourceBranch,
mergeWhenBuildSucceeds: false,
- useCommitMessageWithDescription: false,
setToMergeWhenPipelineSucceeds: false,
- showCommitMessageEditor: false,
isMakingRequest: false,
isMergingImmediately: false,
commitMessage: this.mr.commitMessage,
+ squashBeforeMerge: this.mr.squash,
successSvg,
warningSvg,
+ squashCommitMessage: this.mr.squashCommitMessage,
};
},
computed: {
shouldShowMergeWhenPipelineSucceedsText() {
return this.mr.isPipelineActive;
},
- commitMessageLinkTitle() {
- const withDesc = 'Include description in commit message';
- const withoutDesc = "Don't include description in commit message";
-
- return this.useCommitMessageWithDescription ? withoutDesc : withDesc;
- },
status() {
const { pipeline, isPipelineActive, isPipelineFailed, hasCI, ciStatus } = this.mr;
@@ -83,9 +84,9 @@ export default {
},
mergeButtonText() {
if (this.isMergingImmediately) {
- return 'Merge in progress';
+ return __('Merge in progress');
} else if (this.shouldShowMergeWhenPipelineSucceedsText) {
- return 'Merge when pipeline succeeds';
+ return __('Merge when pipeline succeeds');
}
return 'Merge';
@@ -97,7 +98,7 @@ export default {
const { commitMessage } = this;
return Boolean(
!commitMessage.length ||
- !this.shouldShowMergeControls() ||
+ !this.shouldShowMergeControls ||
this.isMakingRequest ||
this.mr.preventMerge,
);
@@ -109,24 +110,14 @@ export default {
const { commitsCount, enableSquashBeforeMerge } = this.mr;
return enableSquashBeforeMerge && commitsCount > 1;
},
- },
- created() {
- eventHub.$on('MRWidgetUpdateSquash', this.handleUpdateSquash);
- },
- beforeDestroy() {
- eventHub.$off('MRWidgetUpdateSquash', this.handleUpdateSquash);
- },
- methods: {
shouldShowMergeControls() {
return this.mr.isMergeAllowed || this.shouldShowMergeWhenPipelineSucceedsText;
},
- updateCommitMessage() {
- const cmwd = this.mr.commitMessageWithDescription;
- this.useCommitMessageWithDescription = !this.useCommitMessageWithDescription;
- this.commitMessage = this.useCommitMessageWithDescription ? cmwd : this.mr.commitMessage;
- },
- toggleCommitMessageEditor() {
- this.showCommitMessageEditor = !this.showCommitMessageEditor;
+ },
+ methods: {
+ updateMergeCommitMessage(includeDescription) {
+ const { commitMessageWithDescription, commitMessage } = this.mr;
+ this.commitMessage = includeDescription ? commitMessageWithDescription : commitMessage;
},
handleMergeButtonClick(mergeWhenBuildSucceeds, mergeImmediately) {
// TODO: Remove no-param-reassign
@@ -143,7 +134,8 @@ export default {
commit_message: this.commitMessage,
merge_when_pipeline_succeeds: this.setToMergeWhenPipelineSucceeds,
should_remove_source_branch: this.removeSourceBranch === true,
- squash: this.mr.squash,
+ squash: this.squashBeforeMerge,
+ squash_commit_message: this.squashCommitMessage,
};
this.isMakingRequest = true;
@@ -163,12 +155,9 @@ export default {
})
.catch(() => {
this.isMakingRequest = false;
- new Flash('Something went wrong. Please try again.'); // eslint-disable-line
+ new Flash(__('Something went wrong. Please try again.')); // eslint-disable-line
});
},
- handleUpdateSquash(val) {
- this.mr.squash = val;
- },
initiateMergePolling() {
simplePoll((continuePolling, stopPolling) => {
this.handleMergePolling(continuePolling, stopPolling);
@@ -202,7 +191,7 @@ export default {
}
})
.catch(() => {
- new Flash('Something went wrong while merging this merge request. Please try again.'); // eslint-disable-line
+ new Flash(__('Something went wrong while merging this merge request. Please try again.')); // eslint-disable-line
});
},
initiateRemoveSourceBranchPolling() {
@@ -231,7 +220,7 @@ export default {
}
})
.catch(() => {
- new Flash('Something went wrong while removing the source branch. Please try again.'); // eslint-disable-line
+ new Flash(__('Something went wrong while deleting the source branch. Please try again.')); // eslint-disable-line
});
},
},
@@ -239,126 +228,136 @@ export default {
</script>
<template>
- <div class="mr-widget-body media">
- <status-icon :status="iconClass" />
- <div class="media-body">
- <div class="mr-widget-body-controls media space-children">
- <span class="btn-group">
- <button
- :disabled="isMergeButtonDisabled"
- :class="mergeButtonClass"
- type="button"
- class="qa-merge-button"
- @click="handleMergeButtonClick();"
- >
- <i v-if="isMakingRequest" class="fa fa-spinner fa-spin" aria-hidden="true"></i>
- {{ mergeButtonText }}
- </button>
- <button
- v-if="shouldShowMergeOptionsDropdown"
- :disabled="isMergeButtonDisabled"
- type="button"
- class="btn btn-sm btn-info dropdown-toggle js-merge-moment"
- data-toggle="dropdown"
- aria-label="Select merge moment"
- >
- <i class="fa fa-chevron-down qa-merge-moment-dropdown" aria-hidden="true"></i>
- </button>
- <ul
- v-if="shouldShowMergeOptionsDropdown"
- class="dropdown-menu dropdown-menu-right"
- role="menu"
- >
- <li>
- <a
- class="merge_when_pipeline_succeeds qa-merge-when-pipeline-succeeds-option"
- href="#"
- @click.prevent="handleMergeButtonClick(true);"
- >
- <span class="media">
- <span class="merge-opt-icon" aria-hidden="true" v-html="successSvg"></span>
- <span class="media-body merge-opt-title">Merge when pipeline succeeds</span>
- </span>
- </a>
- </li>
- <li>
- <a
- class="accept-merge-request qa-merge-immediately-option"
- href="#"
- @click.prevent="handleMergeButtonClick(false, true);"
- >
- <span class="media">
- <span class="merge-opt-icon" aria-hidden="true" v-html="warningSvg"></span>
- <span class="media-body merge-opt-title">Merge immediately</span>
- </span>
- </a>
- </li>
- </ul>
- </span>
- <div class="media-body-wrap space-children">
- <template v-if="shouldShowMergeControls()">
- <label v-if="mr.canRemoveSourceBranch">
- <input
- id="remove-source-branch-input"
- v-model="removeSourceBranch"
- :disabled="isRemoveSourceBranchButtonDisabled"
- class="js-remove-source-branch-checkbox"
- type="checkbox"
- />
- Remove source branch
- </label>
-
- <!-- Placeholder for EE extension of this component -->
- <squash-before-merge
- v-if="shouldShowSquashBeforeMerge"
- :mr="mr"
- :is-merge-button-disabled="isMergeButtonDisabled"
- />
-
- <span v-if="mr.ffOnlyEnabled" class="js-fast-forward-message">
- Fast-forward merge without a merge commit
- </span>
+ <div>
+ <div class="mr-widget-body media">
+ <status-icon :status="iconClass" />
+ <div class="media-body">
+ <div class="mr-widget-body-controls media space-children">
+ <span class="btn-group">
<button
- v-else
:disabled="isMergeButtonDisabled"
- class="js-modify-commit-message-button btn btn-default btn-sm"
+ :class="mergeButtonClass"
type="button"
- @click="toggleCommitMessageEditor"
+ class="qa-merge-button"
+ @click="handleMergeButtonClick()"
>
- Modify commit message
+ <i v-if="isMakingRequest" class="fa fa-spinner fa-spin" aria-hidden="true"></i>
+ {{ mergeButtonText }}
</button>
- </template>
- <template v-else>
- <span class="bold js-resolve-mr-widget-items-message">
- You can only merge once the items above are resolved
- </span>
- </template>
- </div>
- </div>
- <div v-if="showCommitMessageEditor" class="prepend-top-default commit-message-editor">
- <div class="form-group clearfix">
- <label class="col-form-label" for="commit-message"> Commit message </label>
- <div class="col-sm-10">
- <div class="commit-message-container">
- <div class="max-width-marker"></div>
- <textarea
- id="commit-message"
- v-model="commitMessage"
- class="form-control js-commit-message"
- required="required"
- rows="14"
- name="Commit message"
- ></textarea>
- </div>
- <p class="hint">
- Try to keep the first line under 52 characters and the others under 72
- </p>
- <div class="hint">
- <a href="#" @click.prevent="updateCommitMessage"> {{ commitMessageLinkTitle }} </a>
- </div>
+ <button
+ v-if="shouldShowMergeOptionsDropdown"
+ :disabled="isMergeButtonDisabled"
+ type="button"
+ class="btn btn-sm btn-info dropdown-toggle js-merge-moment"
+ data-toggle="dropdown"
+ aria-label="Select merge moment"
+ >
+ <i class="fa fa-chevron-down qa-merge-moment-dropdown" aria-hidden="true"></i>
+ </button>
+ <ul
+ v-if="shouldShowMergeOptionsDropdown"
+ class="dropdown-menu dropdown-menu-right"
+ role="menu"
+ >
+ <li>
+ <a
+ class="merge_when_pipeline_succeeds qa-merge-when-pipeline-succeeds-option"
+ href="#"
+ @click.prevent="handleMergeButtonClick(true)"
+ >
+ <span class="media">
+ <span class="merge-opt-icon" aria-hidden="true" v-html="successSvg"></span>
+ <span class="media-body merge-opt-title">{{
+ __('Merge when pipeline succeeds')
+ }}</span>
+ </span>
+ </a>
+ </li>
+ <li>
+ <a
+ class="accept-merge-request qa-merge-immediately-option"
+ href="#"
+ @click.prevent="handleMergeButtonClick(false, true)"
+ >
+ <span class="media">
+ <span class="merge-opt-icon" aria-hidden="true" v-html="warningSvg"></span>
+ <span class="media-body merge-opt-title">{{ __('Merge immediately') }}</span>
+ </span>
+ </a>
+ </li>
+ </ul>
+ </span>
+ <div class="media-body-wrap space-children">
+ <template v-if="shouldShowMergeControls">
+ <label v-if="mr.canRemoveSourceBranch">
+ <input
+ id="remove-source-branch-input"
+ v-model="removeSourceBranch"
+ :disabled="isRemoveSourceBranchButtonDisabled"
+ class="js-remove-source-branch-checkbox"
+ type="checkbox"
+ />
+ {{ __('Delete source branch') }}
+ </label>
+
+ <!-- Placeholder for EE extension of this component -->
+ <squash-before-merge
+ v-if="shouldShowSquashBeforeMerge"
+ v-model="squashBeforeMerge"
+ :help-path="mr.squashBeforeMergeHelpPath"
+ :is-disabled="isMergeButtonDisabled"
+ />
+ </template>
+ <template v-else>
+ <span class="bold js-resolve-mr-widget-items-message">
+ {{ __('You can only merge once the items above are resolved') }}
+ </span>
+ </template>
</div>
</div>
</div>
</div>
+ <template v-if="shouldShowMergeControls">
+ <div v-if="mr.ffOnlyEnabled" class="mr-fast-forward-message">
+ {{ __('Fast-forward merge without a merge commit') }}
+ </div>
+ <template v-else>
+ <commits-header
+ :is-squash-enabled="squashBeforeMerge"
+ :commits-count="mr.commitsCount"
+ :target-branch="mr.targetBranch"
+ >
+ <ul class="border-top content-list commits-list flex-list">
+ <commit-edit
+ v-if="squashBeforeMerge && shouldShowSquashBeforeMerge"
+ v-model="squashCommitMessage"
+ :label="__('Squash commit message')"
+ input-id="squash-message-edit"
+ squash
+ >
+ <commit-message-dropdown
+ slot="header"
+ v-model="squashCommitMessage"
+ :commits="mr.commits"
+ />
+ </commit-edit>
+ <commit-edit
+ v-model="commitMessage"
+ :label="__('Merge commit message')"
+ input-id="merge-message-edit"
+ >
+ <label slot="checkbox">
+ <input
+ id="include-description"
+ type="checkbox"
+ @change="updateMergeCommitMessage($event.target.checked)"
+ />
+ {{ __('Include merge request description') }}
+ </label>
+ </commit-edit>
+ </ul>
+ </commits-header>
+ </template>
+ </template>
</div>
</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 e71acf0d7dd..b1f5655a15a 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 Icon from '~/vue_shared/components/icon.vue';
-import eventHub from '~/vue_merge_request_widget/event_hub';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
@@ -11,23 +10,19 @@ export default {
tooltip,
},
props: {
- mr: {
- type: Object,
- required: true,
- },
- isMergeButtonDisabled: {
+ value: {
type: Boolean,
required: true,
},
- },
- data() {
- return {
- squashBeforeMerge: this.mr.squash,
- };
- },
- methods: {
- updateSquashModel() {
- eventHub.$emit('MRWidgetUpdateSquash', this.squashBeforeMerge);
+ helpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ isDisabled: {
+ type: Boolean,
+ required: false,
+ default: false,
},
},
};
@@ -37,18 +32,19 @@ export default {
<div class="accept-control inline">
<label class="merge-param-checkbox">
<input
- v-model="squashBeforeMerge"
- :disabled="isMergeButtonDisabled"
+ :checked="value"
+ :disabled="isDisabled"
type="checkbox"
name="squash"
class="qa-squash-checkbox"
- @change="updateSquashModel"
+ @change="$emit('input', $event.target.checked)"
/>
{{ __('Squash commits') }}
</label>
<a
+ v-if="helpPath"
v-tooltip
- :href="mr.squashBeforeMergeHelpPath"
+ :href="helpPath"
data-title="About this feature"
data-placement="bottom"
target="_blank"
diff --git a/app/assets/javascripts/vue_merge_request_widget/ee_switch_mr_widget_options.js b/app/assets/javascripts/vue_merge_request_widget/ee_switch_mr_widget_options.js
deleted file mode 100644
index 8780aa4bd1c..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/ee_switch_mr_widget_options.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import MRWidgetOptions from './mr_widget_options.vue';
-
-export default MRWidgetOptions;
diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js
index 60cebbfc2b2..0cedbdbdfef 100644
--- a/app/assets/javascripts/vue_merge_request_widget/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/index.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import MrWidgetOptions from './ee_switch_mr_widget_options';
+import MrWidgetOptions from 'ee_else_ce/vue_merge_request_widget/mr_widget_options.vue';
import Translate from '../vue_shared/translate';
Vue.use(Translate);
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/mr_widget_pipeline.js b/app/assets/javascripts/vue_merge_request_widget/mixins/mr_widget_pipeline.js
new file mode 100644
index 00000000000..96e8bb45e34
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/mr_widget_pipeline.js
@@ -0,0 +1,15 @@
+export default {
+ computed: {
+ triggered() {
+ return [];
+ },
+ triggeredBy() {
+ return [];
+ },
+ },
+ methods: {
+ hasDownstream() {
+ return false;
+ },
+ },
+};
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 d8a75388e84..57c4dfbe3b7 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
@@ -3,6 +3,9 @@ import _ from 'underscore';
import { __ } from '~/locale';
import Project from '~/pages/projects/project';
import SmartInterval from '~/smart_interval';
+import MRWidgetStore from 'ee_else_ce/vue_merge_request_widget/stores/mr_widget_store';
+import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service';
+import stateMaps from 'ee_else_ce/vue_merge_request_widget/stores/state_maps';
import createFlash from '../flash';
import WidgetHeader from './components/mr_widget_header.vue';
import WidgetMergeHelp from './components/mr_widget_merge_help.vue';
@@ -28,11 +31,7 @@ import FailedToMerge from './components/states/mr_widget_failed_to_merge.vue';
import MergeWhenPipelineSucceedsState from './components/states/mr_widget_merge_when_pipeline_succeeds.vue';
import AutoMergeFailed from './components/states/mr_widget_auto_merge_failed.vue';
import CheckingState from './components/states/mr_widget_checking.vue';
-import MRWidgetStore from './stores/ee_switch_mr_widget_store';
-import MRWidgetService from './services/ee_switch_mr_widget_service';
import eventHub from './event_hub';
-import stateMaps from './stores/ee_switch_state_maps';
-import SquashBeforeMerge from './components/states/squash_before_merge.vue';
import notify from '~/lib/utils/notify';
import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
import GroupedTestReportsApp from '../reports/components/grouped_test_reports_app.vue';
@@ -59,7 +58,6 @@ export default {
'mr-widget-missing-branch': MissingBranchState,
'mr-widget-ready-to-merge': ReadyToMergeState,
'sha-mismatch': ShaMismatchState,
- 'mr-widget-squash-before-merge': SquashBeforeMerge,
'mr-widget-checking': CheckingState,
'mr-widget-unresolved-discussions': UnresolvedDiscussionsState,
'mr-widget-pipeline-blocked': PipelineBlockedState,
@@ -106,6 +104,9 @@ export default {
(!this.mr.isNothingToMergeState && !this.mr.isMergedState)
);
},
+ shouldRenderCollaborationStatus() {
+ return this.mr.allowCollaboration && this.mr.isOpen;
+ },
shouldRenderMergedPipeline() {
return this.mr.state === 'merged' && !_.isEmpty(this.mr.mergePipeline);
},
@@ -141,8 +142,8 @@ export default {
}
},
methods: {
- createService(store) {
- const endpoints = {
+ getServiceEndpoints(store) {
+ return {
mergePath: store.mergePath,
mergeCheckPath: store.mergeCheckPath,
cancelAutoMergePath: store.cancelAutoMergePath,
@@ -153,7 +154,9 @@ export default {
mergeActionsContentPath: store.mergeActionsContentPath,
rebasePath: store.rebasePath,
};
- return new MRWidgetService(endpoints);
+ },
+ createService(store) {
+ return new MRWidgetService(this.getServiceEndpoints(store));
},
checkStatus(cb, isRebased) {
return this.service
@@ -315,7 +318,7 @@ export default {
<div class="mr-widget-section">
<component :is="componentName" :mr="mr" :service="service" />
- <section v-if="mr.allowCollaboration" class="mr-info-list mr-links">
+ <section v-if="shouldRenderCollaborationStatus" class="mr-info-list mr-links">
{{ s__('mrWidget|Allows commits from members who can merge to the target branch') }}
</section>
diff --git a/app/assets/javascripts/vue_merge_request_widget/services/ee_switch_mr_widget_service.js b/app/assets/javascripts/vue_merge_request_widget/services/ee_switch_mr_widget_service.js
deleted file mode 100644
index ea2aabb78fe..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/services/ee_switch_mr_widget_service.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import MRWidgetService from './mr_widget_service';
-
-export default MRWidgetService;
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_get_state_key.js
deleted file mode 100644
index ebef30e3eab..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_get_state_key.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import getStateKey from './get_state_key';
-
-export default getStateKey;
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_mr_widget_store.js
deleted file mode 100644
index 92a07c53f2d..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_mr_widget_store.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import MergeRequestStore from './mr_widget_store';
-
-export default MergeRequestStore;
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_state_maps.js b/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_state_maps.js
deleted file mode 100644
index 50cf9503ea7..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_state_maps.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import stateMaps from './state_maps';
-
-export default stateMaps;
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 066a3b833d7..0cc4fd59f5e 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
@@ -13,6 +13,8 @@ export default function deviseState(data) {
return stateKey.conflicts;
} else if (data.work_in_progress) {
return stateKey.workInProgress;
+ } else if (this.shouldBeRebased) {
+ return stateKey.rebase;
} else if (this.onlyAllowMergeIfPipelineSucceeds && this.isPipelineFailed) {
return stateKey.pipelineFailed;
} else if (this.hasMergeableDiscussionsState) {
@@ -25,8 +27,6 @@ export default function deviseState(data) {
return this.mergeError ? stateKey.autoMergeFailed : stateKey.mergeWhenPipelineSucceeds;
} else if (!this.canMerge) {
return stateKey.notAllowedToMerge;
- } else if (this.shouldBeRebased) {
- return stateKey.rebase;
} 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 c777bcca0fa..58363f632a9 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
@@ -1,5 +1,5 @@
import Timeago from 'timeago.js';
-import getStateKey from './ee_switch_get_state_key';
+import getStateKey from 'ee_else_ce/vue_merge_request_widget/stores/get_state_key';
import { stateKey } from './state_maps';
import { formatDate } from '../../lib/utils/datetime_utility';
@@ -29,17 +29,21 @@ export default class MergeRequestStore {
this.title = data.title;
this.targetBranch = data.target_branch;
this.sourceBranch = data.source_branch;
+ this.sourceBranchProtected = data.source_branch_protected;
+ this.conflictsDocsPath = data.conflicts_docs_path;
this.mergeStatus = data.merge_status;
- this.commitMessage = data.merge_commit_message;
+ this.commitMessage = data.default_merge_commit_message;
this.shortMergeCommitSha = data.short_merge_commit_sha;
this.mergeCommitSha = data.merge_commit_sha;
- this.commitMessageWithDescription = data.merge_commit_message_with_description;
+ this.commitMessageWithDescription = data.default_merge_commit_message_with_description;
this.commitsCount = data.commits_count;
this.divergedCommitsCount = data.diverged_commits_count;
this.pipeline = data.pipeline || {};
this.mergePipeline = data.merge_pipeline || {};
this.deployments = this.deployments || data.deployments || [];
this.postMergeDeployments = this.postMergeDeployments || [];
+ this.commits = data.commits_without_merge_commits || [];
+ this.squashCommitMessage = data.default_squash_commit_message;
this.initRebase(data);
if (data.issues_links) {
diff --git a/app/assets/javascripts/vue_shared/components/bar_chart.vue b/app/assets/javascripts/vue_shared/components/bar_chart.vue
index 4abf795f7bd..eabf5d4bf60 100644
--- a/app/assets/javascripts/vue_shared/components/bar_chart.vue
+++ b/app/assets/javascripts/vue_shared/components/bar_chart.vue
@@ -293,8 +293,8 @@ export default {
:title="setTooltipTitle(data)"
class="bar-rect"
data-placement="top"
- @mouseover="barHoveredIn(index);"
- @mouseout="barHoveredOut(index);"
+ @mouseover="barHoveredIn(index)"
+ @mouseout="barHoveredOut(index)"
/>
</template>
</g>
diff --git a/app/assets/javascripts/vue_shared/components/callout.vue b/app/assets/javascripts/vue_shared/components/callout.vue
index ddbb14ae812..56bafebf4ce 100644
--- a/app/assets/javascripts/vue_shared/components/callout.vue
+++ b/app/assets/javascripts/vue_shared/components/callout.vue
@@ -11,13 +11,14 @@ export default {
},
message: {
type: String,
- required: true,
+ required: false,
+ default: '',
},
},
};
</script>
<template>
<div :class="`bs-callout bs-callout-${category}`" role="alert" aria-live="assertive">
- {{ message }}
+ {{ message }} <slot></slot>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
index bb7710f708e..e9ab6f5ba7a 100644
--- a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
@@ -37,6 +37,11 @@ export default {
required: false,
default: 12,
},
+ isCentered: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
computed: {
changedIcon() {
@@ -78,7 +83,12 @@ export default {
</script>
<template>
- <span v-gl-tooltip.right :title="tooltipTitle" class="file-changed-icon ml-auto">
+ <span
+ v-gl-tooltip.right
+ :title="tooltipTitle"
+ :class="{ 'ml-auto': isCentered }"
+ class="file-changed-icon"
+ >
<icon v-if="showIcon" :name="changedIcon" :size="size" :css-classes="changedIconClass" />
</span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/ci_icon.vue b/app/assets/javascripts/vue_shared/components/ci_icon.vue
index b8eb555106f..e6f0a1c69cd 100644
--- a/app/assets/javascripts/vue_shared/components/ci_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_icon.vue
@@ -21,6 +21,7 @@ import Icon from '../../vue_shared/components/icon.vue';
* - Jobs table
* - Jobs show view header
* - Jobs show view sidebar
+ * - Linked pipelines
*/
const validSizes = [8, 12, 16, 18, 24, 32, 48, 72];
@@ -46,6 +47,11 @@ export default {
required: false,
default: false,
},
+ cssClasses: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
cssClass() {
@@ -59,5 +65,5 @@ export default {
};
</script>
<template>
- <span :class="cssClass"> <icon :name="icon" :size="size" /> </span>
+ <span :class="cssClass"> <icon :name="icon" :size="size" :css-classes="cssClasses" /> </span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/deprecated_modal.vue b/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
index 2129f90d497..36b3ee05456 100644
--- a/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
@@ -95,7 +95,7 @@ export default {
class="close float-right"
data-dismiss="modal"
aria-label="Close"
- @click="emitCancel($event);"
+ @click="emitCancel($event)"
>
<span aria-hidden="true">&times;</span>
</button>
@@ -112,7 +112,7 @@ export default {
type="button"
class="btn"
data-dismiss="modal"
- @click="emitCancel($event);"
+ @click="emitCancel($event)"
>
{{ closeButtonLabel }}
</button>
@@ -130,7 +130,7 @@ export default {
type="button"
class="btn js-primary-button"
data-dismiss="modal"
- @click="emitSubmit($event);"
+ @click="emitSubmit($event)"
>
{{ primaryButtonLabel }}
</button>
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
index 75c66ed850b..ebb253ff422 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
@@ -1,6 +1,5 @@
<script>
-import { diffModes } from '~/ide/constants';
-import { viewerInformationForPath } from '../content_viewer/lib/viewer_utils';
+import { diffViewerModes, diffModes } from '~/ide/constants';
import ImageDiffViewer from './viewers/image_diff_viewer.vue';
import DownloadDiffViewer from './viewers/download_diff_viewer.vue';
import RenamedFile from './viewers/renamed.vue';
@@ -12,6 +11,10 @@ export default {
type: String,
required: true,
},
+ diffViewerMode: {
+ type: String,
+ required: true,
+ },
newPath: {
type: String,
required: true,
@@ -46,7 +49,7 @@ export default {
},
computed: {
viewer() {
- if (this.diffMode === diffModes.renamed) {
+ if (this.diffViewerMode === diffViewerModes.renamed) {
return RenamedFile;
} else if (this.diffMode === diffModes.mode_changed) {
return ModeChanged;
@@ -54,11 +57,8 @@ export default {
if (!this.newPath) return null;
- const previewInfo = viewerInformationForPath(this.newPath);
- if (!previewInfo) return DownloadDiffViewer;
-
- switch (previewInfo.id) {
- case 'image':
+ switch (this.diffViewerMode) {
+ case diffViewerModes.image:
return ImageDiffViewer;
default:
return DownloadDiffViewer;
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
index d5fda7e4ed3..cab92297ca7 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
@@ -75,7 +75,7 @@ export default {
:class="{
active: mode === $options.imageViewMode.twoup,
}"
- @click="changeMode($options.imageViewMode.twoup);"
+ @click="changeMode($options.imageViewMode.twoup)"
>
{{ s__('ImageDiffViewer|2-up') }}
</li>
@@ -83,7 +83,7 @@ export default {
:class="{
active: mode === $options.imageViewMode.swipe,
}"
- @click="changeMode($options.imageViewMode.swipe);"
+ @click="changeMode($options.imageViewMode.swipe)"
>
{{ s__('ImageDiffViewer|Swipe') }}
</li>
@@ -91,7 +91,7 @@ export default {
:class="{
active: mode === $options.imageViewMode.onion,
}"
- @click="changeMode($options.imageViewMode.onion);"
+ @click="changeMode($options.imageViewMode.onion)"
>
{{ s__('ImageDiffViewer|Onion skin') }}
</li>
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/no_preview.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/no_preview.vue
new file mode 100644
index 00000000000..c5cdddf2f64
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/no_preview.vue
@@ -0,0 +1,5 @@
+<template>
+ <div class="nothing-here-block">
+ {{ __('No preview for this file type') }}
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/not_diffable.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/not_diffable.vue
new file mode 100644
index 00000000000..d4d3038f066
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/not_diffable.vue
@@ -0,0 +1,5 @@
+<template>
+ <div class="nothing-here-block">
+ {{ __('This diff was suppressed by a .gitattributes entry.') }}
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/empty_component.js b/app/assets/javascripts/vue_shared/components/empty_component.js
new file mode 100644
index 00000000000..e4402020096
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/empty_component.js
@@ -0,0 +1,3 @@
+export default {
+ render: () => null,
+};
diff --git a/app/assets/javascripts/vue_shared/components/file_finder/index.vue b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
new file mode 100644
index 00000000000..b57455adaad
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
@@ -0,0 +1,299 @@
+<script>
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import Mousetrap from 'mousetrap';
+import VirtualList from 'vue-virtual-scroll-list';
+import Item from './item.vue';
+import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
+
+export const MAX_FILE_FINDER_RESULTS = 40;
+export const FILE_FINDER_ROW_HEIGHT = 55;
+export const FILE_FINDER_EMPTY_ROW_HEIGHT = 33;
+
+const originalStopCallback = Mousetrap.stopCallback;
+
+export default {
+ components: {
+ Item,
+ VirtualList,
+ },
+ props: {
+ files: {
+ type: Array,
+ required: true,
+ },
+ visible: {
+ type: Boolean,
+ required: true,
+ },
+ loading: {
+ type: Boolean,
+ required: true,
+ },
+ showDiffStats: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ clearSearchOnClose: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ focusedIndex: -1,
+ searchText: '',
+ mouseOver: false,
+ cancelMouseOver: false,
+ };
+ },
+ computed: {
+ filteredBlobs() {
+ const searchText = this.searchText.trim();
+
+ if (searchText === '') {
+ return this.files.slice(0, MAX_FILE_FINDER_RESULTS);
+ }
+
+ return fuzzaldrinPlus.filter(this.files, searchText, {
+ key: 'path',
+ maxResults: MAX_FILE_FINDER_RESULTS,
+ });
+ },
+ filteredBlobsLength() {
+ return this.filteredBlobs.length;
+ },
+ listShowCount() {
+ return this.filteredBlobsLength ? Math.min(this.filteredBlobsLength, 5) : 1;
+ },
+ listHeight() {
+ return this.filteredBlobsLength ? FILE_FINDER_ROW_HEIGHT : FILE_FINDER_EMPTY_ROW_HEIGHT;
+ },
+ showClearInputButton() {
+ return this.searchText.trim() !== '';
+ },
+ },
+ watch: {
+ visible() {
+ this.$nextTick(() => {
+ if (!this.visible) {
+ if (this.clearSearchOnClose) {
+ this.searchText = '';
+ }
+ } else {
+ this.focusedIndex = 0;
+
+ if (this.$refs.searchInput) {
+ this.$refs.searchInput.focus();
+ }
+ }
+ });
+ },
+ searchText() {
+ this.focusedIndex = -1;
+
+ this.$nextTick(() => {
+ this.focusedIndex = 0;
+ });
+ },
+ focusedIndex() {
+ if (!this.mouseOver) {
+ this.$nextTick(() => {
+ const el = this.$refs.virtualScrollList.$el;
+ const scrollTop = this.focusedIndex * FILE_FINDER_ROW_HEIGHT;
+ const bottom = this.listShowCount * FILE_FINDER_ROW_HEIGHT;
+
+ if (this.focusedIndex === 0) {
+ // if index is the first index, scroll straight to start
+ el.scrollTop = 0;
+ } else if (this.focusedIndex === this.filteredBlobsLength - 1) {
+ // if index is the last index, scroll to the end
+ el.scrollTop = this.filteredBlobsLength * FILE_FINDER_ROW_HEIGHT;
+ } else if (scrollTop >= bottom + el.scrollTop) {
+ // if element is off the bottom of the scroll list, scroll down one item
+ el.scrollTop = scrollTop - bottom + FILE_FINDER_ROW_HEIGHT;
+ } else if (scrollTop < el.scrollTop) {
+ // if element is off the top of the scroll list, scroll up one item
+ el.scrollTop = scrollTop;
+ }
+ });
+ }
+ },
+ },
+ mounted() {
+ if (this.files.length) {
+ this.focusedIndex = 0;
+ }
+
+ Mousetrap.bind(['t', 'command+p', 'ctrl+p'], e => {
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+
+ this.toggle(!this.visible);
+ });
+
+ Mousetrap.stopCallback = (e, el, combo) => this.mousetrapStopCallback(e, el, combo);
+ },
+ methods: {
+ toggle(visible) {
+ this.$emit('toggle', visible);
+ },
+ clearSearchInput() {
+ this.searchText = '';
+
+ this.$nextTick(() => {
+ this.$refs.searchInput.focus();
+ });
+ },
+ onKeydown(e) {
+ switch (e.keyCode) {
+ case UP_KEY_CODE:
+ e.preventDefault();
+ this.mouseOver = false;
+ this.cancelMouseOver = true;
+ if (this.focusedIndex > 0) {
+ this.focusedIndex -= 1;
+ } else {
+ this.focusedIndex = this.filteredBlobsLength - 1;
+ }
+ break;
+ case DOWN_KEY_CODE:
+ e.preventDefault();
+ this.mouseOver = false;
+ this.cancelMouseOver = true;
+ if (this.focusedIndex < this.filteredBlobsLength - 1) {
+ this.focusedIndex += 1;
+ } else {
+ this.focusedIndex = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ },
+ onKeyup(e) {
+ switch (e.keyCode) {
+ case ENTER_KEY_CODE:
+ this.openFile(this.filteredBlobs[this.focusedIndex]);
+ break;
+ case ESC_KEY_CODE:
+ this.toggle(false);
+ break;
+ default:
+ break;
+ }
+ },
+ openFile(file) {
+ this.toggle(false);
+ this.$emit('click', file);
+ },
+ onMouseOver(index) {
+ if (!this.cancelMouseOver) {
+ this.mouseOver = true;
+ this.focusedIndex = index;
+ }
+ },
+ onMouseMove(index) {
+ this.cancelMouseOver = false;
+ this.onMouseOver(index);
+ },
+ mousetrapStopCallback(e, el, combo) {
+ if (
+ (combo === 't' && el.classList.contains('dropdown-input-field')) ||
+ el.classList.contains('inputarea')
+ ) {
+ return true;
+ } else if (combo === 'command+p' || combo === 'ctrl+p') {
+ return false;
+ }
+
+ return originalStopCallback(e, el, combo);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="file-finder-overlay" @mousedown.self="toggle(false)">
+ <div class="dropdown-menu diff-file-changes file-finder show">
+ <div :class="{ 'has-value': showClearInputButton }" class="dropdown-input">
+ <input
+ ref="searchInput"
+ v-model="searchText"
+ :placeholder="__('Search files')"
+ type="search"
+ class="dropdown-input-field"
+ autocomplete="off"
+ @keydown="onKeydown($event)"
+ @keyup="onKeyup($event)"
+ />
+ <i
+ :class="{
+ hidden: showClearInputButton,
+ }"
+ aria-hidden="true"
+ class="fa fa-search dropdown-input-search"
+ ></i>
+ <i
+ :aria-label="__('Clear search input')"
+ role="button"
+ class="fa fa-times dropdown-input-clear"
+ @click="clearSearchInput"
+ ></i>
+ </div>
+ <div>
+ <virtual-list ref="virtualScrollList" :size="listHeight" :remain="listShowCount" wtag="ul">
+ <template v-if="filteredBlobsLength">
+ <li v-for="(file, index) in filteredBlobs" :key="file.key">
+ <item
+ :file="file"
+ :search-text="searchText"
+ :focused="index === focusedIndex"
+ :index="index"
+ :show-diff-stats="showDiffStats"
+ class="disable-hover"
+ @click="openFile"
+ @mouseover="onMouseOver"
+ @mousemove="onMouseMove"
+ />
+ </li>
+ </template>
+ <li v-else class="dropdown-menu-empty-item">
+ <div class="append-right-default prepend-left-default prepend-top-8 append-bottom-8">
+ <template v-if="loading">
+ {{ __('Loading...') }}
+ </template>
+ <template v-else>
+ {{ __('No files found.') }}
+ </template>
+ </div>
+ </li>
+ </virtual-list>
+ </div>
+ </div>
+ </div>
+</template>
+
+<style scoped>
+.file-finder-overlay {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 200;
+}
+
+.file-finder {
+ top: 10px;
+ left: 50%;
+ transform: translateX(-50%);
+}
+
+.diff-file-changes {
+ top: 50px;
+ max-height: 327px;
+}
+</style>
diff --git a/app/assets/javascripts/vue_shared/components/file_finder/item.vue b/app/assets/javascripts/vue_shared/components/file_finder/item.vue
new file mode 100644
index 00000000000..73511879ff2
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/file_finder/item.vue
@@ -0,0 +1,126 @@
+<script>
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import Icon from '~/vue_shared/components/icon.vue';
+import FileIcon from '../../../vue_shared/components/file_icon.vue';
+import ChangedFileIcon from '../../../vue_shared/components/changed_file_icon.vue';
+
+const MAX_PATH_LENGTH = 60;
+
+export default {
+ components: {
+ Icon,
+ ChangedFileIcon,
+ FileIcon,
+ },
+ props: {
+ file: {
+ type: Object,
+ required: true,
+ },
+ focused: {
+ type: Boolean,
+ required: true,
+ },
+ searchText: {
+ type: String,
+ required: true,
+ },
+ index: {
+ type: Number,
+ required: true,
+ },
+ showDiffStats: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ pathWithEllipsis() {
+ const { path } = this.file;
+
+ return path.length < MAX_PATH_LENGTH
+ ? path
+ : `...${path.substr(path.length - MAX_PATH_LENGTH)}`;
+ },
+ nameSearchTextOccurences() {
+ return fuzzaldrinPlus.match(this.file.name, this.searchText);
+ },
+ pathSearchTextOccurences() {
+ return fuzzaldrinPlus.match(this.pathWithEllipsis, this.searchText);
+ },
+ },
+ methods: {
+ clickRow() {
+ this.$emit('click', this.file);
+ },
+ mouseOverRow() {
+ this.$emit('mouseover', this.index);
+ },
+ mouseMove() {
+ this.$emit('mousemove', this.index);
+ },
+ },
+};
+</script>
+
+<template>
+ <button
+ :class="{
+ 'is-focused': focused,
+ }"
+ type="button"
+ class="diff-changed-file"
+ @click.prevent="clickRow"
+ @mouseover="mouseOverRow"
+ @mousemove="mouseMove"
+ >
+ <file-icon
+ :file-name="file.name"
+ :size="16"
+ css-classes="diff-file-changed-icon append-right-8"
+ />
+ <span class="diff-changed-file-content append-right-8">
+ <strong class="diff-changed-file-name">
+ <span
+ v-for="(char, charIndex) in file.name.split('')"
+ :key="charIndex + char"
+ :class="{
+ highlighted: nameSearchTextOccurences.indexOf(charIndex) >= 0,
+ }"
+ v-text="char"
+ >
+ </span>
+ </strong>
+ <span class="diff-changed-file-path prepend-top-5">
+ <span
+ v-for="(char, charIndex) in pathWithEllipsis.split('')"
+ :key="charIndex + char"
+ :class="{
+ highlighted: pathSearchTextOccurences.indexOf(charIndex) >= 0,
+ }"
+ v-text="char"
+ >
+ </span>
+ </span>
+ </span>
+ <span v-if="file.changed || file.tempFile" v-once class="diff-changed-stats">
+ <span v-if="showDiffStats">
+ <span class="cgreen bold">
+ <icon name="file-addition" class="align-text-top" /> {{ file.addedLines }}
+ </span>
+ <span class="cred bold ml-1">
+ <icon name="file-deletion" class="align-text-top" /> {{ file.removedLines }}
+ </span>
+ </span>
+ <changed-file-icon v-else :file="file" />
+ </span>
+ </button>
+</template>
+
+<style scoped>
+.highlighted {
+ color: #1f78d1;
+ font-weight: 600;
+}
+</style>
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index 9e713673678..0cbcdbf2eb4 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -1,11 +1,13 @@
<script>
import Icon from '~/vue_shared/components/icon.vue';
+import FileHeader from '~/vue_shared/components/file_row_header.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
export default {
name: 'FileRow',
components: {
+ FileHeader,
FileIcon,
Icon,
ChangedFileIcon,
@@ -34,21 +36,10 @@ export default {
required: false,
default: false,
},
- displayTextKey: {
- type: String,
- required: false,
- default: 'name',
- },
- shouldTruncateStart: {
- type: Boolean,
- required: false,
- default: false,
- },
},
data() {
return {
mouseOver: false,
- truncateStart: 0,
};
},
computed: {
@@ -60,7 +51,7 @@ export default {
},
levelIndentation() {
return {
- marginLeft: `${this.level * 16}px`,
+ marginLeft: this.level ? `${this.level * 16}px` : null,
};
},
fileClass() {
@@ -71,14 +62,8 @@ export default {
'is-open': this.file.opened,
};
},
- outputText() {
- const text = this.file[this.displayTextKey];
-
- if (this.truncateStart === 0) {
- return text;
- }
-
- return `...${text.substring(this.truncateStart, text.length)}`;
+ childFilesLevel() {
+ return this.file.isHeader ? 0 : this.level + 1;
},
},
watch: {
@@ -92,15 +77,6 @@ export default {
if (this.hasPathAtCurrentRoute()) {
this.scrollIntoView(true);
}
-
- if (this.shouldTruncateStart) {
- const { scrollWidth, offsetWidth } = this.$refs.textOutput;
- const textOverflow = scrollWidth - offsetWidth;
-
- if (textOverflow > 0) {
- this.truncateStart = Math.ceil(textOverflow / 5) + 3;
- }
- }
},
methods: {
toggleTreeOpen(path) {
@@ -156,13 +132,16 @@ export default {
<template>
<div>
+ <file-header v-if="file.isHeader" :path="file.path" />
<div
+ v-else
:class="fileClass"
+ :title="file.name"
class="file-row"
role="button"
@click="clickFile"
- @mouseover="toggleHover(true);"
- @mouseout="toggleHover(false);"
+ @mouseover="toggleHover(true)"
+ @mouseout="toggleHover(false)"
>
<div class="file-row-name-container">
<span ref="textOutput" :style="levelIndentation" class="file-row-name str-truncated">
@@ -175,7 +154,7 @@ export default {
:size="16"
/>
<changed-file-icon v-else :file="file" :size="16" class="append-right-5" />
- {{ outputText }}
+ {{ file.name }}
</span>
<component
:is="extraComponent"
@@ -185,17 +164,15 @@ export default {
/>
</div>
</div>
- <template v-if="file.opened">
+ <template v-if="file.opened || file.isHeader">
<file-row
v-for="childFile in file.tree"
:key="childFile.key"
:file="childFile"
- :level="level + 1"
+ :level="childFilesLevel"
:hide-extra-on-tree="hideExtraOnTree"
:extra-component="extraComponent"
:show-changed-icon="showChangedIcon"
- :display-text-key="displayTextKey"
- :should-truncate-start="shouldTruncateStart"
@toggleTreeOpen="toggleTreeOpen"
@clickFile="clickedFile"
/>
diff --git a/app/assets/javascripts/vue_shared/components/file_row_header.vue b/app/assets/javascripts/vue_shared/components/file_row_header.vue
new file mode 100644
index 00000000000..301fd8116a9
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/file_row_header.vue
@@ -0,0 +1,25 @@
+<script>
+import { truncatePathMiddleToLength } from '~/lib/utils/text_utility';
+
+const MAX_PATH_LENGTH = 40;
+
+export default {
+ props: {
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ truncatedPath() {
+ return truncatePathMiddleToLength(this.path, MAX_PATH_LENGTH);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="file-row-header bg-white sticky-top p-2 js-file-row-header">
+ <span class="bold">{{ truncatedPath }}</span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue b/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
index 834c39a5ee0..4e5dfbf3bf8 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
@@ -1,15 +1,21 @@
<script>
import $ from 'jquery';
+import { GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
/**
* Renders a split dropdown with
* an input that allows to search through the given
* array of options.
+ *
+ * When there are no results and `showCreateMode` is true
+ * it renders a create button with the value typed.
*/
export default {
name: 'FilteredSearchDropdown',
components: {
Icon,
+ GlButton,
},
props: {
title: {
@@ -43,6 +49,16 @@ export default {
type: String,
required: true,
},
+ showCreateMode: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ createButtonText: {
+ type: String,
+ required: false,
+ default: __('Create'),
+ },
},
data() {
return {
@@ -64,6 +80,12 @@ export default {
return this.items.slice(0, this.visibleItems);
},
+ computedCreateButtonText() {
+ return `${this.createButtonText} ${this.filter}`;
+ },
+ shouldRenderCreateButton() {
+ return this.showCreateMode && this.filteredResults.length === 0 && this.filter !== '';
+ },
},
mounted() {
/**
@@ -112,10 +134,20 @@ export default {
<div class="dropdown-content">
<ul>
<li v-for="(result, i) in filteredResults" :key="i" class="js-filtered-dropdown-result">
- <slot name="result" :result="result"> {{ result[filterKey] }} </slot>
+ <slot name="result" :result="result">{{ result[filterKey] }}</slot>
</li>
</ul>
</div>
+
+ <div v-if="shouldRenderCreateButton" class="dropdown-footer">
+ <slot name="footer" :filter="filter">
+ <gl-button
+ class="js-dropdown-create-button btn-transparent"
+ @click="$emit('createItem', filter)"
+ >{{ computedCreateButtonText }}</gl-button
+ >
+ </slot>
+ </div>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/gl_modal.vue b/app/assets/javascripts/vue_shared/components/gl_modal.vue
index faf4181bbaf..438851e5ac7 100644
--- a/app/assets/javascripts/vue_shared/components/gl_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/gl_modal.vue
@@ -81,7 +81,7 @@ export default {
type="button"
class="close js-modal-close-action"
data-dismiss="modal"
- @click="emitCancel($event);"
+ @click="emitCancel($event)"
>
<span aria-hidden="true">&times;</span>
</button>
@@ -96,7 +96,7 @@ export default {
type="button"
class="btn js-modal-cancel-action qa-modal-cancel-button"
data-dismiss="modal"
- @click="emitCancel($event);"
+ @click="emitCancel($event)"
>
{{ s__('Modal|Cancel') }}
</button>
@@ -105,7 +105,7 @@ export default {
type="button"
class="btn js-modal-primary-action qa-modal-primary-button"
data-dismiss="modal"
- @click="emitSubmit($event);"
+ @click="emitSubmit($event)"
>
{{ footerPrimaryButtonText }}
</button>
diff --git a/app/assets/javascripts/vue_shared/components/gl_modal_vuex.vue b/app/assets/javascripts/vue_shared/components/gl_modal_vuex.vue
new file mode 100644
index 00000000000..df6fadf10cd
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/gl_modal_vuex.vue
@@ -0,0 +1,69 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { GlModal } from '@gitlab/ui';
+
+/**
+ * This component keeps the GlModal's visibility in sync with the given vuex module.
+ */
+export default {
+ components: {
+ GlModal,
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: true,
+ },
+ modalModule: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState({
+ isVisible(state) {
+ return state[this.modalModule].isVisible;
+ },
+ }),
+ attrs() {
+ const { modalId, modalModule, ...attrs } = this.$attrs;
+
+ return attrs;
+ },
+ },
+ watch: {
+ isVisible(val) {
+ return val ? this.bsShow() : this.bsHide();
+ },
+ },
+ methods: {
+ ...mapActions({
+ syncShow(dispatch) {
+ return dispatch(`${this.modalModule}/show`);
+ },
+ syncHide(dispatch) {
+ return dispatch(`${this.modalModule}/hide`);
+ },
+ }),
+ bsShow() {
+ this.$root.$emit('bv::show::modal', this.modalId);
+ },
+ bsHide() {
+ // $root.$emit is a workaround because other b-modal approaches don't work yet with gl-modal
+ this.$root.$emit('bv::hide::modal', this.modalId);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-modal
+ v-bind="attrs"
+ :modal-id="modalId"
+ v-on="$listeners"
+ @shown="syncShow"
+ @hidden="syncHide"
+ >
+ <slot></slot>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index c830f5b49b6..3f45dc7853b 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -148,7 +148,7 @@ export default {
:class="action.cssClass"
container-class="d-inline"
:label="action.label"
- @click="onClickAction(action);"
+ @click="onClickAction(action)"
/>
</template>
</section>
diff --git a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
new file mode 100644
index 00000000000..27cfa8abb24
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
@@ -0,0 +1,116 @@
+<script>
+import { GlTooltipDirective } from '@gitlab/ui';
+import { __, sprintf } from '~/locale';
+import IssueMilestone from '~/vue_shared/components/issue/issue_milestone.vue';
+import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+import relatedIssuableMixin from '~/vue_shared/mixins/related_issuable_mixin';
+
+export default {
+ name: 'IssueItem',
+ components: {
+ IssueMilestone,
+ IssueAssignees,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [relatedIssuableMixin],
+ props: {
+ canReorder: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ stateTitle() {
+ return sprintf(
+ '<span class="bold">%{state}</span> %{timeInWords}<br/><span class="text-tertiary">%{timestamp}</span>',
+ {
+ state: this.isOpen ? __('Opened') : __('Closed'),
+ timeInWords: this.isOpen ? this.createdAtInWords : this.closedAtInWords,
+ timestamp: this.isOpen ? this.createdAtTimestamp : this.closedAtTimestamp,
+ },
+ );
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ :class="{
+ 'issuable-info-container': !canReorder,
+ 'card-body': canReorder,
+ }"
+ class="item-body"
+ >
+ <div class="item-contents">
+ <div class="item-title d-flex align-items-center">
+ <icon
+ v-if="hasState"
+ v-tooltip
+ :css-classes="iconClass"
+ :name="iconName"
+ :size="16"
+ :title="stateTitle"
+ :aria-label="state"
+ data-html="true"
+ />
+ <icon
+ v-if="confidential"
+ v-gl-tooltip
+ name="eye-slash"
+ :size="16"
+ :title="__('Confidential')"
+ class="confidential-icon append-right-4"
+ :aria-label="__('Confidential')"
+ />
+ <a :href="computedPath" class="sortable-link">{{ title }}</a>
+ </div>
+ <div class="item-meta">
+ <div class="d-flex align-items-center item-path-id">
+ <icon
+ v-if="hasState"
+ v-tooltip
+ :css-classes="iconClass"
+ :name="iconName"
+ :size="16"
+ :title="stateTitle"
+ :aria-label="state"
+ data-html="true"
+ />
+ <span v-tooltip :title="itemPath" class="path-id-text">{{ itemPath }}</span>
+ {{ pathIdSeparator }}{{ itemId }}
+ </div>
+ <div class="item-meta-child d-flex align-items-center">
+ <issue-milestone
+ v-if="hasMilestone"
+ :milestone="milestone"
+ class="d-flex align-items-center item-milestone"
+ />
+ <slot name="dueDate"></slot>
+ <slot name="weight"></slot>
+ </div>
+ <issue-assignees
+ v-if="assignees.length"
+ :assignees="assignees"
+ class="item-assignees d-inline-flex"
+ />
+ </div>
+ </div>
+ <button
+ v-if="canRemove"
+ ref="removeButton"
+ v-tooltip
+ :disabled="removeDisabled"
+ type="button"
+ class="btn btn-default btn-svg btn-item-remove js-issue-item-remove-button qa-remove-issue-button"
+ title="Remove"
+ aria-label="Remove"
+ @click="onRemoveRequest"
+ >
+ <icon :size="16" class="btn-item-remove-icon" name="close" />
+ </button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 2f7ed4a982c..3f607aa2a0a 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -27,11 +27,6 @@ export default {
type: String,
required: true,
},
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
addSpacingClasses: {
type: Boolean,
required: false,
@@ -89,7 +84,6 @@ export default {
return this.referencedUsers.length >= referencedUsersThreshold;
},
lineContent() {
- const FIRST_CHAR_REGEX = /^(\+|-)/;
const [firstSuggestion] = this.suggestions;
if (firstSuggestion) {
return firstSuggestion.from_content;
@@ -99,7 +93,7 @@ export default {
const { rich_text: richText, text } = this.line;
if (text) {
- return text.replace(FIRST_CHAR_REGEX, '');
+ return text;
}
return _.unescape(stripHtml(richText).replace(/\n/g, ''));
@@ -159,7 +153,7 @@ export default {
this.markdownPreviewLoading = true;
this.markdownPreview = __('Loading…');
this.$http
- .post(this.versionedPreviewPath(), { text })
+ .post(this.markdownPreviewPath, { text })
.then(resp => resp.json())
.then(data => this.renderMarkdown(data))
.catch(() => new Flash(__('Error loading markdown preview')));
@@ -183,16 +177,9 @@ export default {
this.hasSuggestion = data.references.suggestions && data.references.suggestions.length;
}
- this.$nextTick(() => {
- $(this.$refs['markdown-preview']).renderGFM();
- });
- },
-
- versionedPreviewPath() {
- const { markdownPreviewPath, markdownVersion } = this;
- return `${markdownPreviewPath}${
- markdownPreviewPath.indexOf('?') === -1 ? '?' : '&'
- }markdown_version=${markdownVersion}`;
+ this.$nextTick()
+ .then(() => $(this.$refs['markdown-preview']).renderGFM())
+ .catch(() => new Flash(__('Error rendering markdown preview')));
},
},
};
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index bf4d42670ee..cc6ecdb0395 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -78,13 +78,8 @@ export default {
<div class="md-header">
<ul class="nav-links clearfix">
<li :class="{ active: !previewMarkdown }" class="md-header-tab">
- <button
- class="js-write-link"
- tabindex="-1"
- type="button"
- @click="writeMarkdownTab($event);"
- >
- Write
+ <button class="js-write-link" tabindex="-1" type="button" @click="writeMarkdownTab($event)">
+ {{ __('Write') }}
</button>
</li>
<li :class="{ active: previewMarkdown }" class="md-header-tab">
@@ -92,38 +87,43 @@ export default {
class="js-preview-link js-md-preview-button"
tabindex="-1"
type="button"
- @click="previewMarkdownTab($event);"
+ @click="previewMarkdownTab($event)"
>
- Preview
+ {{ __('Preview') }}
</button>
</li>
<li :class="{ active: !previewMarkdown }" class="md-header-toolbar">
- <toolbar-button tag="**" button-title="Add bold text" icon="bold" />
- <toolbar-button tag="*" button-title="Add italic text" icon="italic" />
- <toolbar-button :prepend="true" tag="> " button-title="Insert a quote" icon="quote" />
- <toolbar-button tag="`" tag-block="```" button-title="Insert code" icon="code" />
+ <toolbar-button tag="**" :button-title="__('Add bold text')" icon="bold" />
+ <toolbar-button tag="*" :button-title="__('Add italic text')" icon="italic" />
+ <toolbar-button
+ :prepend="true"
+ tag="> "
+ :button-title="__('Insert a quote')"
+ icon="quote"
+ />
+ <toolbar-button tag="`" tag-block="```" :button-title="__('Insert code')" icon="code" />
<toolbar-button
tag="[{text}](url)"
tag-select="url"
- button-title="Add a link"
+ :button-title="__('Add a link')"
icon="link"
/>
<toolbar-button
:prepend="true"
tag="* "
- button-title="Add a bullet list"
+ :button-title="__('Add a bullet list')"
icon="list-bulleted"
/>
<toolbar-button
:prepend="true"
tag="1. "
- button-title="Add a numbered list"
+ :button-title="__('Add a numbered list')"
icon="list-numbered"
/>
<toolbar-button
:prepend="true"
tag="* [ ] "
- button-title="Add a task list"
+ :button-title="__('Add a task list')"
icon="task-done"
/>
<toolbar-button
@@ -144,11 +144,11 @@ export default {
/>
<button
v-gl-tooltip
- aria-label="Go full screen"
+ :aria-label="__('Go full screen')"
class="toolbar-btn toolbar-fullscreen-btn js-zen-enter"
data-container="body"
tabindex="-1"
- title="Go full screen"
+ :title="__('Go full screen')"
type="button"
>
<icon name="screen-full" />
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
index f98560f7336..a351ca62c94 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
@@ -42,7 +42,7 @@ export default {
</script>
<template>
- <div>
+ <div class="md-suggestion">
<suggestion-diff-header
class="qa-suggestion-diff-header"
:can-apply="suggestion.appliable && suggestion.current_user.can_apply && !disabled"
@@ -50,7 +50,7 @@ export default {
:help-page-path="helpPagePath"
@apply="applySuggestion"
/>
- <table class="mb-3 md-suggestion-diff">
+ <table class="mb-3 md-suggestion-diff js-syntax-highlight code">
<tbody>
<!-- Old Line -->
<tr class="line_holder old">
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
index 563e2f94fcc..c5a2aa1f2af 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
@@ -42,7 +42,7 @@ export default {
<div class="md-suggestion-header border-bottom-0 mt-2">
<div class="qa-suggestion-diff-header font-weight-bold">
{{ __('Suggested change') }}
- <a v-if="helpPagePath" :href="helpPagePath" :aria-label="__('Help')">
+ <a v-if="helpPagePath" :href="helpPagePath" :aria-label="__('Help')" class="js-help-btn">
<icon name="question-o" css-classes="link-highlight" />
</a>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index 7c6dbee3e19..dcda701f049 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -82,13 +82,12 @@ export default {
// extracts the suggested lines from the markdown
// calculates a line number for each line
- const FIRST_CHAR_REGEX = /^(\+|-)/;
const newLines = suggestionEl.querySelectorAll('.line');
const fromLine = this.suggestions.length ? this.suggestions[0].from_line : this.fromLine;
const lines = [];
newLines.forEach((line, i) => {
- const content = `${line.innerText.replace(FIRST_CHAR_REGEX, '')}\n`;
+ const content = `${line.innerText}\n`;
const lineNumber = fromLine + i;
lines.push({ content, lineNumber });
});
@@ -130,7 +129,7 @@ export default {
<template>
<div>
- <div class="flash-container mt-3"></div>
+ <div class="flash-container js-suggestions-flash"></div>
<div v-show="isRendered" ref="container" v-html="noteHtml"></div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
index 09a64502819..f8983a3d29a 100644
--- a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
@@ -58,7 +58,7 @@ export default {
active: tab.isActive,
}"
>
- <a :class="`js-${scope}-tab-${tab.scope}`" role="button" @click="onTabClick(tab);">
+ <a :class="`js-${scope}-tab-${tab.scope}`" role="button" @click="onTabClick(tab)">
{{ tab.name }}
<span v-if="shouldRenderBadge(tab.count)" class="badge badge-pill"> {{ tab.count }} </span>
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index 31df26f7b05..b0af8399955 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -97,7 +97,7 @@ export default {
v-html="note.note_html"
></div>
<div v-if="hasMoreCommits" class="flex-list">
- <div class="system-note-commit-list-toggler flex-row" @click="expanded = !expanded;">
+ <div class="system-note-commit-list-toggler flex-row" @click="expanded = !expanded">
<icon :name="toggleIcon" :size="8" class="append-right-5" />
<span>Toggle commit list</span>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/panel_resizer.vue b/app/assets/javascripts/vue_shared/components/panel_resizer.vue
index bf736a378dd..8d81940eb91 100644
--- a/app/assets/javascripts/vue_shared/components/panel_resizer.vue
+++ b/app/assets/javascripts/vue_shared/components/panel_resizer.vue
@@ -28,11 +28,12 @@ export default {
data() {
return {
size: this.startSize,
+ isDragging: false,
};
},
computed: {
className() {
- return `drag-${this.side}`;
+ return [`position-${this.side}-0`, { 'is-dragging': this.isDragging }];
},
cursorStyle() {
if (this.enabled) {
@@ -57,6 +58,7 @@ export default {
startDrag(e) {
if (this.enabled) {
e.preventDefault();
+ this.isDragging = true;
this.startPos = e.clientX;
this.currentStartSize = this.size;
document.addEventListener('mousemove', this.drag);
@@ -80,6 +82,7 @@ export default {
},
endDrag(e) {
e.preventDefault();
+ this.isDragging = false;
document.removeEventListener('mousemove', this.drag);
this.$emit('resize-end', this.size);
},
@@ -91,7 +94,7 @@ export default {
<div
:class="className"
:style="cursorStyle"
- class="drag-handle"
+ class="position-absolute position-top-0 position-bottom-0 drag-handle"
@mousedown="startDrag"
@dblclick="resetSize"
></div>
diff --git a/app/assets/javascripts/vue_shared/components/pikaday.vue b/app/assets/javascripts/vue_shared/components/pikaday.vue
index 8bdb5bf22c2..fa502b9beb9 100644
--- a/app/assets/javascripts/vue_shared/components/pikaday.vue
+++ b/app/assets/javascripts/vue_shared/components/pikaday.vue
@@ -1,6 +1,7 @@
<script>
import Pikaday from 'pikaday';
import { parsePikadayDate, pikadayToString } from '~/lib/utils/datetime_utility';
+import { __ } from '~/locale';
export default {
name: 'DatePicker',
@@ -8,7 +9,7 @@ export default {
label: {
type: String,
required: false,
- default: 'Date picker',
+ default: __('Date picker'),
},
selectedDate: {
type: Date,
@@ -40,6 +41,7 @@ export default {
toString: date => pikadayToString(date),
onSelect: this.selected.bind(this),
onClose: this.toggled.bind(this),
+ firstDay: gon.first_day_of_week,
});
this.$el.append(this.calendar.el);
diff --git a/app/assets/javascripts/vue_shared/components/project_avatar/default.vue b/app/assets/javascripts/vue_shared/components/project_avatar/default.vue
index b399c232937..881b5059d2a 100644
--- a/app/assets/javascripts/vue_shared/components/project_avatar/default.vue
+++ b/app/assets/javascripts/vue_shared/components/project_avatar/default.vue
@@ -26,7 +26,7 @@ export default {
</script>
<template>
- <span :class="sizeClass" class="avatar-container project-avatar">
+ <span :class="sizeClass" class="avatar-container rect-avatar project-avatar">
<project-avatar-image
v-if="project.avatar_url"
:link-href="project.path"
@@ -34,6 +34,12 @@ export default {
:img-alt="project.name"
:img-size="size"
/>
- <identicon v-else :entity-id="project.id" :entity-name="project.name" :size-class="sizeClass" />
+ <identicon
+ v-else
+ :entity-id="project.id"
+ :entity-name="project.name"
+ :size-class="sizeClass"
+ class="rect-avatar"
+ />
</span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
index 1c6c3fc4734..df19906309c 100644
--- a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
@@ -19,7 +19,7 @@ export default {
data() {
return {
script: {},
- scriptSrc: 'https://www.google.com/recaptcha/api.js',
+ scriptSrc: 'https://www.recaptcha.net/recaptcha/api.js',
};
},
diff --git a/app/assets/javascripts/vue_shared/components/select2_select.vue b/app/assets/javascripts/vue_shared/components/select2_select.vue
new file mode 100644
index 00000000000..3074ea859cc
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/select2_select.vue
@@ -0,0 +1,35 @@
+<script>
+import $ from 'jquery';
+import 'select2/select2';
+
+export default {
+ name: 'Select2Select',
+ props: {
+ options: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ value: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+
+ mounted() {
+ $(this.$refs.dropdownInput)
+ .val(this.value)
+ .select2(this.options)
+ .on('change', event => this.$emit('input', event.target.value));
+ },
+
+ beforeDestroy() {
+ $(this.$refs.dropdownInput).select2('destroy');
+ },
+};
+</script>
+
+<template>
+ <input ref="dropdownInput" type="hidden" />
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
index 82067129c57..45f01a6fced 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
@@ -4,6 +4,7 @@ import datePicker from '../pikaday.vue';
import toggleSidebar from './toggle_sidebar.vue';
import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
import { dateInWords } from '../../../lib/utils/datetime_utility';
+import { __ } from '~/locale';
export default {
name: 'SidebarDatePicker',
@@ -42,7 +43,7 @@ export default {
label: {
type: String,
required: false,
- default: 'Date picker',
+ default: __('Date picker'),
},
selectedDate: {
type: Date,
@@ -134,7 +135,7 @@ export default {
<button
type="button"
class="btn-blank btn-link btn-secondary-hover-link"
- @click="newDateSelected(null);"
+ @click="newDateSelected(null)"
>
remove
</button>
diff --git a/app/assets/javascripts/vue_shared/components/table_pagination.vue b/app/assets/javascripts/vue_shared/components/table_pagination.vue
index 01e655d27e5..8e0b08032f7 100644
--- a/app/assets/javascripts/vue_shared/components/table_pagination.vue
+++ b/app/assets/javascripts/vue_shared/components/table_pagination.vue
@@ -54,15 +54,14 @@ export default {
return this.pageInfo.nextPage;
},
getItems() {
- const total = this.pageInfo.totalPages;
- const { page } = this.pageInfo;
+ const { totalPages, nextPage, previousPage, page } = this.pageInfo;
const items = [];
if (page > 1) {
items.push({ title: FIRST, first: true });
}
- if (page > 1) {
+ if (previousPage) {
items.push({ title: PREV, prev: true });
} else {
items.push({ title: PREV, disabled: true, prev: true });
@@ -70,32 +69,34 @@ export default {
if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true });
- const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1);
- const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, total);
+ if (totalPages) {
+ const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1);
+ const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, totalPages);
- for (let i = start; i <= end; i += 1) {
- const isActive = i === page;
- items.push({ title: i, active: isActive, page: true });
- }
+ for (let i = start; i <= end; i += 1) {
+ const isActive = i === page;
+ items.push({ title: i, active: isActive, page: true });
+ }
- if (total - page > PAGINATION_UI_BUTTON_LIMIT) {
- items.push({ title: SPREAD, separator: true, page: true });
+ if (totalPages - page > PAGINATION_UI_BUTTON_LIMIT) {
+ items.push({ title: SPREAD, separator: true, page: true });
+ }
}
- if (page === total) {
- items.push({ title: NEXT, disabled: true, next: true });
- } else if (total - page >= 1) {
+ if (nextPage) {
items.push({ title: NEXT, next: true });
+ } else {
+ items.push({ title: NEXT, disabled: true, next: true });
}
- if (total - page >= 1) {
+ if (totalPages && totalPages - page >= 1) {
items.push({ title: LAST, last: true });
}
return items;
},
showPagination() {
- return this.pageInfo.totalPages > 1;
+ return this.pageInfo.nextPage || this.pageInfo.previousPage;
},
},
methods: {
@@ -149,9 +150,9 @@ export default {
}"
class="page-item"
>
- <a class="page-link" @click.prevent="changePage(item.title, item.disabled);">
+ <button type="button" class="page-link" @click="changePage(item.title, item.disabled)">
{{ item.title }}
- </a>
+ </button>
</li>
</ul>
</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 e833a8e0483..a6c1737dcab 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
@@ -67,7 +67,9 @@ export default {
// In both cases we should render the defaultAvatarUrl
sanitizedSource() {
let baseSrc = this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
- if (!baseSrc.startsWith('data:') && !baseSrc.includes('?')) baseSrc += `?width=${this.size}`;
+ // Only adds the width to the URL if its not a base64 data image
+ if (!(baseSrc.indexOf('data:') === 0) && !baseSrc.includes('?'))
+ baseSrc += `?width=${this.size}`;
return baseSrc;
},
resultantSrcAttribute() {
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
new file mode 100644
index 00000000000..8eaf8386b99
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue
@@ -0,0 +1,89 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { sprintf, __ } from '~/locale';
+import UserAvatarLink from './user_avatar_link.vue';
+
+export default {
+ components: {
+ UserAvatarLink,
+ GlButton,
+ },
+ props: {
+ items: {
+ type: Array,
+ required: true,
+ },
+ breakpoint: {
+ type: Number,
+ required: false,
+ default: 10,
+ },
+ imgSize: {
+ type: Number,
+ required: false,
+ default: 20,
+ },
+ emptyText: {
+ type: String,
+ required: false,
+ default: __('None'),
+ },
+ },
+ data() {
+ return {
+ isExpanded: false,
+ };
+ },
+ computed: {
+ visibleItems() {
+ if (!this.hasHiddenItems) {
+ return this.items;
+ }
+
+ return this.items.slice(0, this.breakpoint);
+ },
+ hasHiddenItems() {
+ return this.hasBreakpoint && !this.isExpanded && this.items.length > this.breakpoint;
+ },
+ hasBreakpoint() {
+ return this.breakpoint > 0 && this.items.length > this.breakpoint;
+ },
+ expandText() {
+ if (!this.hasHiddenItems) {
+ return '';
+ }
+
+ const count = this.items.length - this.breakpoint;
+
+ return sprintf(__('%{count} more'), { count });
+ },
+ },
+ methods: {
+ expand() {
+ this.isExpanded = true;
+ },
+ collapse() {
+ this.isExpanded = false;
+ },
+ },
+};
+</script>
+
+<template>
+ <div v-if="!items.length">{{ emptyText }}</div>
+ <div v-else>
+ <user-avatar-link
+ v-for="item in visibleItems"
+ :key="item.id"
+ :link-href="item.web_url"
+ :img-src="item.avatar_url"
+ :img-alt="item.name"
+ :tooltip-text="item.name"
+ :img-size="imgSize"
+ />
+ <template v-if="hasBreakpoint">
+ <gl-button v-if="hasHiddenItems" variant="link" @click="expand"> {{ expandText }} </gl-button>
+ <gl-button v-else variant="link" @click="collapse"> {{ __('show less') }} </gl-button>
+ </template>
+ </div>
+</template>
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 d24fe1b547e..f9773622001 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
@@ -28,10 +28,10 @@ export default {
},
computed: {
statusHtml() {
- if (this.user.status.emoji && this.user.status.message) {
- return `${glEmojiTag(this.user.status.emoji)} ${this.user.status.message}`;
- } else if (this.user.status.message) {
- return this.user.status.message;
+ if (this.user.status.emoji && this.user.status.message_html) {
+ return `${glEmojiTag(this.user.status.emoji)} ${this.user.status.message_html}`;
+ } else if (this.user.status.message_html) {
+ return this.user.status.message_html;
}
return '';
},
diff --git a/app/assets/javascripts/vue_shared/mixins/is_ee.js b/app/assets/javascripts/vue_shared/mixins/is_ee.js
new file mode 100644
index 00000000000..8e00d93ef18
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/mixins/is_ee.js
@@ -0,0 +1,10 @@
+import Vue from 'vue';
+import { isEE } from '~/lib/utils/common_utils';
+
+Vue.mixin({
+ computed: {
+ isEE() {
+ return isEE();
+ },
+ },
+});
diff --git a/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js b/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
new file mode 100644
index 00000000000..455ae832234
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
@@ -0,0 +1,155 @@
+import _ from 'underscore';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import tooltip from '~/vue_shared/directives/tooltip';
+import icon from '~/vue_shared/components/icon.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+
+const mixins = {
+ data() {
+ return {
+ removeDisabled: false,
+ };
+ },
+ props: {
+ idKey: {
+ type: Number,
+ required: true,
+ },
+ displayReference: {
+ type: String,
+ required: true,
+ },
+ pathIdSeparator: {
+ type: String,
+ required: true,
+ },
+ eventNamespace: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ confidential: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ path: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ state: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ createdAt: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ closedAt: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ milestone: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ dueDate: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ assignees: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ weight: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ canRemove: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ components: {
+ icon,
+ },
+ directives: {
+ tooltip,
+ },
+ mixins: [timeagoMixin],
+ computed: {
+ hasState() {
+ return this.state && this.state.length > 0;
+ },
+ isOpen() {
+ return this.state === 'opened';
+ },
+ isClosed() {
+ return this.state === 'closed';
+ },
+ hasTitle() {
+ return this.title.length > 0;
+ },
+ hasMilestone() {
+ return !_.isEmpty(this.milestone);
+ },
+ iconName() {
+ return this.isOpen ? 'issue-open-m' : 'issue-close';
+ },
+ iconClass() {
+ return this.isOpen ? 'issue-token-state-icon-open' : 'issue-token-state-icon-closed';
+ },
+ computedLinkElementType() {
+ return this.path.length > 0 ? 'a' : 'span';
+ },
+ computedPath() {
+ return this.path.length ? this.path : null;
+ },
+ itemPath() {
+ return this.displayReference.split(this.pathIdSeparator)[0];
+ },
+ itemId() {
+ return this.displayReference.split(this.pathIdSeparator).pop();
+ },
+ createdAtInWords() {
+ return this.createdAt ? this.timeFormated(this.createdAt) : '';
+ },
+ createdAtTimestamp() {
+ return this.createdAt ? formatDate(new Date(this.createdAt)) : '';
+ },
+ closedAtInWords() {
+ return this.closedAt ? this.timeFormated(this.closedAt) : '';
+ },
+ closedAtTimestamp() {
+ return this.closedAt ? formatDate(new Date(this.closedAt)) : '';
+ },
+ },
+ methods: {
+ onRemoveRequest() {
+ let namespacePrefix = '';
+ if (this.eventNamespace && this.eventNamespace.length > 0) {
+ namespacePrefix = `${this.eventNamespace}`;
+ }
+
+ this.$emit(`${namespacePrefix}RemoveRequest`, this.idKey);
+
+ this.removeDisabled = true;
+ },
+ },
+};
+
+export default mixins;
diff --git a/app/assets/javascripts/vuex_shared/modules/modal/actions.js b/app/assets/javascripts/vuex_shared/modules/modal/actions.js
new file mode 100644
index 00000000000..7b209909f69
--- /dev/null
+++ b/app/assets/javascripts/vuex_shared/modules/modal/actions.js
@@ -0,0 +1,20 @@
+import * as types from './mutation_types';
+
+export const open = ({ commit }, data) => {
+ commit(types.OPEN, data);
+};
+
+export const close = ({ commit }) => {
+ commit(types.CLOSE);
+};
+
+export const show = ({ commit }) => {
+ commit(types.SHOW);
+};
+
+export const hide = ({ commit }) => {
+ commit(types.HIDE);
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/vuex_shared/modules/modal/index.js b/app/assets/javascripts/vuex_shared/modules/modal/index.js
new file mode 100644
index 00000000000..c349d875c24
--- /dev/null
+++ b/app/assets/javascripts/vuex_shared/modules/modal/index.js
@@ -0,0 +1,10 @@
+import state from './state';
+import mutations from './mutations';
+import * as actions from './actions';
+
+export default () => ({
+ namespaced: true,
+ state: state(),
+ mutations,
+ actions,
+});
diff --git a/app/assets/javascripts/vuex_shared/modules/modal/mutation_types.js b/app/assets/javascripts/vuex_shared/modules/modal/mutation_types.js
new file mode 100644
index 00000000000..f8259736009
--- /dev/null
+++ b/app/assets/javascripts/vuex_shared/modules/modal/mutation_types.js
@@ -0,0 +1,4 @@
+export const HIDE = 'HIDE';
+export const SHOW = 'SHOW';
+export const OPEN = 'OPEN';
+export const CLOSE = 'CLOSE';
diff --git a/app/assets/javascripts/vuex_shared/modules/modal/mutations.js b/app/assets/javascripts/vuex_shared/modules/modal/mutations.js
new file mode 100644
index 00000000000..9e96ae8b5a9
--- /dev/null
+++ b/app/assets/javascripts/vuex_shared/modules/modal/mutations.js
@@ -0,0 +1,18 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.SHOW](state) {
+ state.isVisible = true;
+ },
+ [types.HIDE](state) {
+ state.isVisible = false;
+ },
+ [types.OPEN](state, data) {
+ state.data = data;
+ state.isVisible = true;
+ },
+ [types.CLOSE](state) {
+ state.data = null;
+ state.isVisible = false;
+ },
+};
diff --git a/app/assets/javascripts/vuex_shared/modules/modal/state.js b/app/assets/javascripts/vuex_shared/modules/modal/state.js
new file mode 100644
index 00000000000..5d0955aa9b0
--- /dev/null
+++ b/app/assets/javascripts/vuex_shared/modules/modal/state.js
@@ -0,0 +1,4 @@
+export default () => ({
+ isVisible: false,
+ data: null,
+});
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index bdf20866197..83ad8766cb5 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -40,16 +40,6 @@
@import "components/**/*";
/*
- * Code highlight
- */
-@import "highlight/dark";
-@import "highlight/monokai";
-@import "highlight/solarized_dark";
-@import "highlight/solarized_light";
-@import "highlight/white";
-@import "highlight/none";
-
-/*
* Styles for JS behaviors.
*/
@import "behaviors";
diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss
index f0671e36130..c8357f7751c 100644
--- a/app/assets/stylesheets/bootstrap_migration.scss
+++ b/app/assets/stylesheets/bootstrap_migration.scss
@@ -70,6 +70,17 @@ h6,
margin-bottom: 10px;
}
+/* Our adjustments to hx & .hx above add unnecessary margins to modal-title
+ and page-title in modals, so we set them to 0 in order to have properly
+ formatted modal headers. */
+.modal-header {
+ .modal-title,
+ .page-title {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+}
+
h5,
.h5 {
font-size: $gl-font-size;
@@ -134,7 +145,8 @@ table {
pointer-events: none;
}
-.popover {
+.popover,
+.popover-header {
font-size: 14px;
}
@@ -142,7 +154,9 @@ table {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
- .d#{$infix}-table-header-group { display: table-header-group !important; }
+ .d#{$infix}-table-header-group {
+ display: table-header-group !important;
+ }
}
}
@@ -211,7 +225,7 @@ h3.popover-header {
}
.info-well {
- background: $theme-gray-50;
+ background: $gray-50;
color: $gl-text-color;
border: 1px solid $border-color;
border-radius: 4px;
diff --git a/app/assets/stylesheets/components/related_items_list.scss b/app/assets/stylesheets/components/related_items_list.scss
new file mode 100644
index 00000000000..edf7b26ebaa
--- /dev/null
+++ b/app/assets/stylesheets/components/related_items_list.scss
@@ -0,0 +1,380 @@
+$item-path-max-width: 160px;
+$item-milestone-max-width: 120px;
+$item-weight-max-width: 48px;
+
+.related-items-list {
+ padding: $gl-padding-4;
+
+ &,
+ .list-item:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.item-body {
+ display: flex;
+ position: relative;
+ align-items: center;
+ padding: $gl-padding-8;
+ line-height: $gl-line-height;
+
+ .item-contents {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ flex-grow: 1;
+ }
+
+ .issue-token-state-icon-open,
+ .issue-token-state-icon-closed,
+ .confidential-icon,
+ .item-milestone .icon,
+ .item-weight .board-card-info-icon {
+ min-width: $gl-padding;
+ cursor: help;
+ }
+
+ .issue-token-state-icon-open,
+ .issue-token-state-icon-closed {
+ margin-right: $gl-padding-4;
+ }
+
+ .confidential-icon {
+ align-self: baseline;
+ color: $orange-600;
+ margin-right: $gl-padding-4;
+ }
+
+ .item-title {
+ flex-basis: 100%;
+ margin-bottom: $gl-padding-8;
+ font-size: $gl-font-size-small;
+
+ &.mr-title {
+ font-weight: $gl-font-weight-bold;
+ }
+
+ .sortable-link {
+ max-width: 85%;
+ }
+
+ .issue-token-state-icon-open,
+ .issue-token-state-icon-closed {
+ display: none;
+ }
+ }
+
+ .item-meta {
+ display: flex;
+ flex-wrap: wrap;
+ flex-basis: 100%;
+ font-size: $gl-font-size-small;
+ color: $gl-text-color-secondary;
+
+ .item-meta-child {
+ order: 0;
+ display: flex;
+ flex-wrap: wrap;
+ flex-basis: 100%;
+
+ .item-due-date,
+ .item-weight {
+ margin-left: $gl-padding-8;
+ }
+
+ .item-milestone,
+ .item-weight {
+ cursor: help;
+ }
+
+ .item-milestone {
+ text-decoration: none;
+ max-width: $item-milestone-max-width;
+ }
+
+ .item-due-date {
+ margin-right: 0;
+ }
+
+ .item-weight {
+ margin-right: 0;
+ max-width: $item-weight-max-width;
+ }
+ }
+
+ .item-path-id .path-id-text,
+ .item-milestone .milestone-title,
+ .item-due-date,
+ .item-weight .board-card-info-text {
+ color: $gl-text-color-secondary;
+ display: inline-block;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+
+ .item-path-id {
+ margin-top: $gl-padding-4;
+ font-size: $gl-font-size-xs;
+ white-space: nowrap;
+
+ .path-id-text {
+ font-weight: $gl-font-weight-bold;
+ max-width: $item-path-max-width;
+ }
+
+ .issue-token-state-icon-open,
+ .issue-token-state-icon-closed {
+ display: block;
+ }
+
+ &:not(.mr-item-path) {
+ order: 1;
+ }
+ }
+
+ .item-milestone .ic-clock {
+ color: $gl-text-color-tertiary;
+ margin-right: $gl-padding-4;
+ }
+
+ .item-assignees {
+ order: 2;
+ align-self: flex-end;
+ align-items: center;
+ margin-left: auto;
+
+ .user-avatar-link {
+ margin-right: -$gl-padding-4;
+
+ &:nth-of-type(1) {
+ z-index: 2;
+ }
+
+ &:nth-of-type(2) {
+ z-index: 1;
+ }
+
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+
+ .avatar {
+ height: $gl-padding;
+ width: $gl-padding;
+ margin-right: 0;
+ vertical-align: bottom;
+ }
+
+ .avatar-counter {
+ height: $gl-padding;
+ border: 1px solid transparent;
+ background-color: $gl-text-color-tertiary;
+ font-weight: $gl-font-weight-bold;
+ padding: 0 $gl-padding-4;
+ line-height: $gl-padding;
+ }
+ }
+ }
+
+ .btn-item-remove {
+ position: absolute;
+ right: 0;
+ top: $gl-padding-4 / 2;
+ padding: $gl-padding-4;
+ margin-right: $gl-padding-4 / 2;
+ line-height: 0;
+ border-color: transparent;
+ color: $gl-text-color-secondary;
+
+ &:hover {
+ color: $gl-text-color;
+ }
+ }
+}
+
+.mr-status-wrapper,
+.mr-ci-status {
+ line-height: 0;
+}
+
+@include media-breakpoint-up(sm) {
+ .item-body {
+ .item-contents .item-title {
+ .mr-title-link,
+ .sortable-link {
+ max-width: 90%;
+ }
+ }
+ }
+}
+
+/* Small devices (landscape phones, 768px and up) */
+@include media-breakpoint-up(md) {
+ .item-body {
+ .item-contents {
+ min-width: 0;
+
+ .item-title {
+ flex-basis: unset;
+ // 95% because we compensate
+ // for remove button which is
+ // positioned absolutely
+ width: 95%;
+ margin-bottom: $gl-padding-4;
+
+ .mr-title-link,
+ .sortable-link {
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ max-width: 100%;
+ }
+ }
+
+ .item-meta {
+ .item-path-id {
+ order: 0;
+ margin-top: 0;
+ }
+
+ .item-meta-child {
+ flex-basis: unset;
+ margin-left: auto;
+ margin-right: $gl-padding-4;
+
+ ~ .item-assignees {
+ margin-left: $gl-padding-4;
+ }
+ }
+
+ .item-assignees {
+ margin-bottom: 0;
+ margin-left: 0;
+ order: 2;
+ }
+ }
+ }
+
+ .btn-item-remove {
+ order: 1;
+ }
+ }
+}
+
+/* Medium devices (desktops, 992px and up) */
+@include media-breakpoint-up(lg) {
+ .item-body {
+ padding: $gl-padding;
+
+ .item-title {
+ font-size: $gl-font-size;
+ }
+
+ .item-meta .item-path-id {
+ font-size: inherit; // Base size given to `item-meta` is `$gl-font-size-small`
+ }
+
+ .issue-token-state-icon-open,
+ .issue-token-state-icon-closed {
+ margin-right: $gl-padding-4;
+ }
+ }
+}
+
+/* Large devices (large desktops, 1200px and up) */
+@include media-breakpoint-up(xl) {
+ .item-body {
+ padding: $gl-padding-8;
+ padding-left: $gl-padding;
+
+ .item-contents {
+ flex-wrap: nowrap;
+ overflow: hidden;
+
+ .item-title {
+ display: flex;
+ margin-bottom: 0;
+ min-width: 0;
+ width: auto;
+ flex-basis: unset;
+ font-weight: $gl-font-weight-normal;
+
+ .mr-title-link,
+ .sortable-link {
+ display: block;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+
+ .issue-token-state-icon-open,
+ .issue-token-state-icon-closed {
+ display: block;
+ margin-right: $gl-padding-8;
+ }
+
+ .confidential-icon {
+ align-self: auto;
+ margin-top: 0;
+ }
+ }
+
+ .item-meta {
+ margin-top: 0;
+ justify-content: flex-end;
+ flex: 1;
+ flex-wrap: nowrap;
+
+ .item-path-id {
+ order: 0;
+ margin-top: 0;
+ margin-left: $gl-padding-8;
+ margin-right: auto;
+
+ .issue-token-state-icon-open,
+ .issue-token-state-icon-closed {
+ display: none;
+ }
+ }
+
+ .item-meta-child {
+ margin-left: $gl-padding-8;
+ flex-wrap: nowrap;
+ }
+
+ .item-assignees {
+ flex-grow: 0;
+ margin-top: 0;
+ margin-right: $gl-padding-4;
+
+ .avatar {
+ height: $gl-padding-24;
+ width: $gl-padding-24;
+ }
+
+ .avatar-counter {
+ height: $gl-padding-24;
+ min-width: $gl-padding-24;
+ line-height: $gl-padding-24;
+ border-radius: $gl-padding-24;
+ }
+ }
+ }
+ }
+
+ .btn-item-remove {
+ position: relative;
+ align-self: center;
+ top: initial;
+ right: 0;
+ margin-right: 0;
+ padding: $btn-sm-side-margin;
+
+ &:hover {
+ border-color: $border-color;
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 834e7ffce81..216877a4461 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -31,7 +31,6 @@
@import 'framework/logo';
@import 'framework/markdown_area';
@import 'framework/media_object';
-@import 'framework/mobile';
@import 'framework/modal';
@import 'framework/pagination';
@import 'framework/panels';
@@ -66,3 +65,5 @@
@import 'framework/terms';
@import 'framework/read_more';
@import 'framework/flex_grid';
+@import 'framework/system_messages';
+@import "framework/spinner";
diff --git a/app/assets/stylesheets/framework/animations.scss b/app/assets/stylesheets/framework/animations.scss
index 549a8730301..257d788873c 100644
--- a/app/assets/stylesheets/framework/animations.scss
+++ b/app/assets/stylesheets/framework/animations.scss
@@ -27,7 +27,7 @@
&.flipOutY,
&.bounceIn,
&.bounceOut {
- @include webkit-prefix(animation-duration, .75s);
+ @include webkit-prefix(animation-duration, 0.75s);
}
&.short {
@@ -63,56 +63,44 @@
//
// Pass in any number of transitions
@mixin transition($transitions...) {
- $unfoldedTransitions: ();
+ $unfolded-transitions: ();
@each $transition in $transitions {
- $unfoldedTransitions: append($unfoldedTransitions, unfoldTransition($transition), comma);
+ $unfolded-transitions: append($unfolded-transitions, unfold-transition($transition), comma);
}
- transition: $unfoldedTransitions;
+ transition: $unfolded-transitions;
}
-@mixin disableAllAnimation {
+@mixin disable-all-animation {
/*CSS transitions*/
- -o-transition-property: none !important;
- -moz-transition-property: none !important;
- -ms-transition-property: none !important;
- -webkit-transition-property: none !important;
transition-property: none !important;
/*CSS transforms*/
- -o-transform: none !important;
- -moz-transform: none !important;
- -ms-transform: none !important;
- -webkit-transform: none !important;
transform: none !important;
/*CSS animations*/
- -webkit-animation: none !important;
- -moz-animation: none !important;
- -o-animation: none !important;
- -ms-animation: none !important;
animation: none !important;
}
-@function unfoldTransition ($transition) {
+@function unfold-transition ($transition) {
// Default values
$property: all;
$duration: $general-hover-transition-duration;
$easing: $general-hover-transition-curve; // Browser default is ease, which is what we want
$delay: null; // Browser default is 0, which is what we want
- $defaultProperties: ($property, $duration, $easing, $delay);
+ $default-properties: ($property, $duration, $easing, $delay);
// Grab transition properties if they exist
- $unfoldedTransition: ();
- @for $i from 1 through length($defaultProperties) {
+ $unfolded-transition: ();
+ @for $i from 1 through length($default-properties) {
$p: null;
@if $i <= length($transition) {
$p: nth($transition, $i);
} @else {
- $p: nth($defaultProperties, $i);
+ $p: nth($default-properties, $i);
}
- $unfoldedTransition: append($unfoldedTransition, $p);
+ $unfolded-transition: append($unfolded-transition, $p);
}
- @return $unfoldedTransition;
+ @return $unfolded-transition;
}
.btn {
@@ -202,9 +190,9 @@ a {
}
}
- [class^="skeleton-line-"] {
+ [class^='skeleton-line-'] {
position: relative;
- background-color: $theme-gray-100;
+ background-color: $gray-100;
height: 10px;
overflow: hidden;
@@ -218,13 +206,11 @@ a {
animation: blockTextShine 1s linear infinite forwards;
background-repeat: no-repeat;
background-size: cover;
- background-image: linear-gradient(
- to right,
- $theme-gray-100 0%,
- $theme-gray-50 20%,
- $theme-gray-100 40%,
- $theme-gray-100 100%
- );
+ background-image: linear-gradient(to right,
+ $gray-100 0%,
+ $gray-50 20%,
+ $gray-100 40%,
+ $gray-100 100%);
height: 10px;
}
}
@@ -260,3 +246,25 @@ $skeleton-line-widths: (
.slide-down-leave-to {
transform: translateY(-30%);
}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg);}
+ 100% { transform: rotate(360deg);}
+}
+
+/** COMMON ANIMATION CLASSES **/
+.transform-origin-center { @include webkit-prefix(transform-origin, 50% 50%); }
+.animate-n-spin { @include webkit-prefix(animation-name, spin); }
+.animate-c-infinite { @include webkit-prefix(animation-iteration-count, infinite); }
+.animate-t-linear { @include webkit-prefix(animation-timing-function, linear); }
+.animate-d-1 { @include webkit-prefix(animation-duration, 1s); }
+.animate-d-2 { @include webkit-prefix(animation-duration, 2s); }
+
+/** COMPOSITE ANIMATION CLASSES **/
+.gl-spinner {
+ @include webkit-prefix(animation-name, spin);
+ @include webkit-prefix(animation-iteration-count, infinite);
+ @include webkit-prefix(animation-timing-function, linear);
+ @include webkit-prefix(animation-duration, 1s);
+ transform-origin: 50% 50%;
+}
diff --git a/app/assets/stylesheets/framework/asciidoctor.scss b/app/assets/stylesheets/framework/asciidoctor.scss
index 62493c32833..1586265d40e 100644
--- a/app/assets/stylesheets/framework/asciidoctor.scss
+++ b/app/assets/stylesheets/framework/asciidoctor.scss
@@ -1,7 +1,7 @@
.admonitionblock td.icon {
width: 1%;
- [class^="fa icon-"] {
+ [class^='fa icon-'] {
@extend .fa-2x;
}
diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
index e132aa4c216..af79a4d9392 100644
--- a/app/assets/stylesheets/framework/avatar.scss
+++ b/app/assets/stylesheets/framework/avatar.scss
@@ -45,7 +45,6 @@
display: inline-block;
margin-left: 2px;
flex-shrink: 0;
- -webkit-flex-shrink: 0;
&.s16 { margin-right: 4px; }
&.s24 { margin-right: 4px; }
@@ -74,20 +73,48 @@
background-color: $gray-darker;
// Sizes
- &.s16 { font-size: 12px; line-height: 1.33; }
- &.s24 { font-size: 13px; line-height: 1.8; }
- &.s26 { font-size: 20px; line-height: 1.33; }
- &.s32 { font-size: 20px; line-height: 30px; }
- &.s40 { font-size: 16px; line-height: 38px; }
- &.s48 { font-size: 20px; line-height: 46px; }
- &.s60 { font-size: 32px; line-height: 58px; }
- &.s64 { font-size: 32px; line-height: 64px; }
- &.s70 { font-size: 34px; line-height: 70px; }
- &.s90 { font-size: 36px; line-height: 88px; }
- &.s100 { font-size: 36px; line-height: 98px; }
- &.s110 { font-size: 40px; line-height: 108px; font-weight: $gl-font-weight-normal; }
- &.s140 { font-size: 72px; line-height: 138px; }
- &.s160 { font-size: 96px; line-height: 158px; }
+ &.s16 { font-size: 12px;
+ line-height: 1.33; }
+
+ &.s24 { font-size: 13px;
+ line-height: 1.8; }
+
+ &.s26 { font-size: 20px;
+ line-height: 1.33; }
+
+ &.s32 { font-size: 20px;
+ line-height: 30px; }
+
+ &.s40 { font-size: 16px;
+ line-height: 38px; }
+
+ &.s48 { font-size: 20px;
+ line-height: 46px; }
+
+ &.s60 { font-size: 32px;
+ line-height: 58px; }
+
+ &.s64 { font-size: 32px;
+ line-height: 64px; }
+
+ &.s70 { font-size: 34px;
+ line-height: 70px; }
+
+ &.s90 { font-size: 36px;
+ line-height: 88px; }
+
+ &.s100 { font-size: 36px;
+ line-height: 98px; }
+
+ &.s110 { font-size: 40px;
+ line-height: 108px;
+ font-weight: $gl-font-weight-normal; }
+
+ &.s140 { font-size: 72px;
+ line-height: 138px; }
+
+ &.s160 { font-size: 96px;
+ line-height: 158px; }
// Background colors
&.bg1 { background-color: $identicon-red; }
@@ -120,8 +147,35 @@
align-self: center;
}
- &.s40 { min-width: 40px; min-height: 40px; }
- &.s64 { min-width: 64px; min-height: 64px; }
+ &.s40 { min-width: 40px;
+ min-height: 40px; }
+
+ &.s64 { min-width: 64px;
+ min-height: 64px; }
+}
+
+.rect-avatar {
+ border-radius: $border-radius-small;
+ &.s16 { border-radius: $border-radius-small; }
+ &.s18 { border-radius: $border-radius-small; }
+ &.s19 { border-radius: $border-radius-small; }
+ &.s20 { border-radius: $border-radius-small; }
+ &.s24 { border-radius: $border-radius-default; }
+ &.s26 { border-radius: $border-radius-default; }
+ &.s32 { border-radius: $border-radius-default; }
+ &.s36 { border-radius: $border-radius-default; }
+ &.s40 { border-radius: $border-radius-default; }
+ &.s46 { border-radius: $border-radius-default; }
+ &.s48 { border-radius: $border-radius-large; }
+ &.s60 { border-radius: $border-radius-large; }
+ &.s64 { border-radius: $border-radius-large; }
+ &.s70 { border-radius: $border-radius-large; }
+ &.s90 { border-radius: $border-radius-large; }
+ &.s96 { border-radius: $border-radius-large; }
+ &.s100 { border-radius: $border-radius-large; }
+ &.s110 { border-radius: $border-radius-large; }
+ &.s140 { border-radius: $border-radius-large; }
+ &.s160 { border-radius: $border-radius-large; }
}
.avatar-counter {
diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss
index 7a95db5976d..648e1944388 100644
--- a/app/assets/stylesheets/framework/awards.scss
+++ b/app/assets/stylesheets/framework/awards.scss
@@ -15,7 +15,7 @@
margin-top: 3px;
padding: $gl-padding;
z-index: 300;
- width: 300px;
+ width: $award-emoji-width;
font-size: 14px;
background-color: $white-light;
border: 1px solid $border-white-light;
@@ -23,9 +23,9 @@
box-shadow: 0 6px 12px $award-emoji-menu-shadow;
pointer-events: none;
opacity: 0;
- transform: scale(.2);
+ transform: scale(0.2);
transform-origin: 0 -45px;
- transition: .3s cubic-bezier(.67, .06, .19, 1.44);
+ transition: 0.3s cubic-bezier(0.67, 0.06, 0.19, 1.44);
transition-property: transform, opacity;
&.is-rendered {
@@ -55,10 +55,14 @@
transform: none;
}
}
+
+ @include media-breakpoint-down(xs) {
+ width: $award-emoji-width-xs;
+ }
}
.emoji-search {
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAFu0lEQVRIia1WTahkVxH+quqce7vf6zdvJpHoIlkYJ2SiJiIokmQjgoGgIAaEIYuYXWICgojiwkmC4taFwhjcyIDusogEIwwiSSCKPwsdwzAg0SjJ9Izzk5n3+nXfe8+pqizOvd395scfsJqi6dPnnDr11Vc/NJ1OwUTosqJLCmYCHCAC2mSHs+ojZv6AO46Y+20AhIneJsafhPhXVZSXDk7qi+aOLhtQNuBmQtcarAKjTXpn2+l3u2yPunvZSABRucjcAV/eMZuM48/Go/g1d19kc4wq+e8MZjWkbI/P5t2P3RFFbv7SQdyBlBUx8N8OTuqjMcof+N94yMPrY2DMm/ytnb32J0QrY+6AqsHM4Q64O9SKDmerKDD3Oy/tNL9vk342CC8RuU6n0ymCMHb22scu7zQngtASOjUHE1BX4UUAv4b7Ow6qiXCXuz/UdvogAAweDY943/b4cAz0ZlYHXeMsnT07RVb7wMUr8ykI4H5HVkMd5Rcb4/jNURVOL5qErAaAUUdCCIJ5kx5q2nw8m39ImEAAsjpE6PStB0YfMcd1wqqG3Xn7A3PfZyyKnNjaqD4fmE/fCNKshirIyY1xvI+Av6g5QIAIIWX7cJPssboSiBBEeKmsZne0Sb8kzAUWNYyq8NvbDo0fZ6beqxuLmqOOMr/lwOh+YXpXtbjERGja9JyZ9+HxpXKb9Gj5oywRESbj+Cj1ENG1QViTGBl1FbC1We1tbVRfHWIoQkhqH9xbpE92XUbb6VJZ1R4crjRz1JWcDMJvLdoMcyAEhjuwHo8Bfndg3mbszhOY+adVlMtD3po51OwzIQiEaams7oeJhxRw1FFOVpFRRUYIhMBAFRnjOsC8IFHHUA4TQQhgAqpAiIFfGbxkIqj54ayGbL7UoOqHCniAEKHLNr26l+D9wQJzeUwMAnfHvEnLECzZRwRV++d60ptjW9VLZeolEJG6GwCCE0CFVNB+Ay0NEqoQYG4YYFu7B8IEVRt3uRzy/osIoLV9QZimWXGHUMFdmI6M64DUF2Je88R9VZqCSP+QlcF5k+4tCzSsXaqjINuK6UyE0+s/mk6/qFq8oAIL9pqMLhkGsNrOyoOIlszust3aJv0U9+kFdwjTGwWl1YdF+KWlQSZ0Se/psj8yGVdg5tJyfH96EBWmLtoEMwMzMFt031NzGWLLzKhC+KV7H5ZeeaMOPxemma2x68puc0LN3+/u6LJiePS6MKHvn4wu6cPzJj0hsioeMfDrEvjv5r6W9gBvjKJujuKzQ0URIZj75NylvT+mbHfXQa4rwAMaVRTMm/SFyzvNy0yF6+4AM+1ubcSnqkAIUjQKl1RKSbE5jt+vovx1MBqF0WW7/d1Z80ab9BtmuJ3Xk5cJKds9TZt/uLPXvtiTrQ+dIwqfAejUvM1os6FNikXKUHfQ+ekUsXT5u85enJ0CaBSkkGEo1syUQ+DfMdE/4GA1uzupf9zdbzhOmLsF4efHVXjaHHAzmDtGdQRd/Nc5wAEJjNki3XfhyvwVNz80xANrht3LsENY9cBBdN1L9GUyyvFRFZ42t75sBvCQRykbRlU4tT2pPxoCvzx09d4GmPs200M6wKdWSDGK8mppYSWdhAlt0qeaLv+IadXU9/Evq4FAZ8ej+LmtcTxaRX4NWI0Uag5Vg1p5MYg8BnlhXIdPHDow+vTWZvVMVttXDLqkTzZdPj6Qii6cP1cSvIdl3iQkNYyi9HH0I22y+93tY3DcQkTZgQtM+POoCr8x97eylkmtrgKuztrvXJ21x/aNKuqIkZ/fntRfCdcTfhUTAIhRzoDojJD0aSNLLwMzmpT7+JaLtyf1MwDo6qz9djFaUq3t9MlFmy/c1OCSceY9fMsVaL9mvH9ocXdkdWxv1scAePG0THAhMOaLdOw/Gvxfxb1w4eCapyIENUcV5M3/u8FitAxZ25P6GAHT3UX39Srw+QOb1ZffA98Dl2Wy1BYkAAAAAElFTkSuQmCC");
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAFu0lEQVRIia1WTahkVxH+quqce7vf6zdvJpHoIlkYJ2SiJiIokmQjgoGgIAaEIYuYXWICgojiwkmC4taFwhjcyIDusogEIwwiSSCKPwsdwzAg0SjJ9Izzk5n3+nXfe8+pqizOvd395scfsJqi6dPnnDr11Vc/NJ1OwUTosqJLCmYCHCAC2mSHs+ojZv6AO46Y+20AhIneJsafhPhXVZSXDk7qi+aOLhtQNuBmQtcarAKjTXpn2+l3u2yPunvZSABRucjcAV/eMZuM48/Go/g1d19kc4wq+e8MZjWkbI/P5t2P3RFFbv7SQdyBlBUx8N8OTuqjMcof+N94yMPrY2DMm/ytnb32J0QrY+6AqsHM4Q64O9SKDmerKDD3Oy/tNL9vk342CC8RuU6n0ymCMHb22scu7zQngtASOjUHE1BX4UUAv4b7Ow6qiXCXuz/UdvogAAweDY943/b4cAz0ZlYHXeMsnT07RVb7wMUr8ykI4H5HVkMd5Rcb4/jNURVOL5qErAaAUUdCCIJ5kx5q2nw8m39ImEAAsjpE6PStB0YfMcd1wqqG3Xn7A3PfZyyKnNjaqD4fmE/fCNKshirIyY1xvI+Av6g5QIAIIWX7cJPssboSiBBEeKmsZne0Sb8kzAUWNYyq8NvbDo0fZ6beqxuLmqOOMr/lwOh+YXpXtbjERGja9JyZ9+HxpXKb9Gj5oywRESbj+Cj1ENG1QViTGBl1FbC1We1tbVRfHWIoQkhqH9xbpE92XUbb6VJZ1R4crjRz1JWcDMJvLdoMcyAEhjuwHo8Bfndg3mbszhOY+adVlMtD3po51OwzIQiEaams7oeJhxRw1FFOVpFRRUYIhMBAFRnjOsC8IFHHUA4TQQhgAqpAiIFfGbxkIqj54ayGbL7UoOqHCniAEKHLNr26l+D9wQJzeUwMAnfHvEnLECzZRwRV++d60ptjW9VLZeolEJG6GwCCE0CFVNB+Ay0NEqoQYG4YYFu7B8IEVRt3uRzy/osIoLV9QZimWXGHUMFdmI6M64DUF2Je88R9VZqCSP+QlcF5k+4tCzSsXaqjINuK6UyE0+s/mk6/qFq8oAIL9pqMLhkGsNrOyoOIlszust3aJv0U9+kFdwjTGwWl1YdF+KWlQSZ0Se/psj8yGVdg5tJyfH96EBWmLtoEMwMzMFt031NzGWLLzKhC+KV7H5ZeeaMOPxemma2x68puc0LN3+/u6LJiePS6MKHvn4wu6cPzJj0hsioeMfDrEvjv5r6W9gBvjKJujuKzQ0URIZj75NylvT+mbHfXQa4rwAMaVRTMm/SFyzvNy0yF6+4AM+1ubcSnqkAIUjQKl1RKSbE5jt+vovx1MBqF0WW7/d1Z80ab9BtmuJ3Xk5cJKds9TZt/uLPXvtiTrQ+dIwqfAejUvM1os6FNikXKUHfQ+ekUsXT5u85enJ0CaBSkkGEo1syUQ+DfMdE/4GA1uzupf9zdbzhOmLsF4efHVXjaHHAzmDtGdQRd/Nc5wAEJjNki3XfhyvwVNz80xANrht3LsENY9cBBdN1L9GUyyvFRFZ42t75sBvCQRykbRlU4tT2pPxoCvzx09d4GmPs200M6wKdWSDGK8mppYSWdhAlt0qeaLv+IadXU9/Evq4FAZ8ej+LmtcTxaRX4NWI0Uag5Vg1p5MYg8BnlhXIdPHDow+vTWZvVMVttXDLqkTzZdPj6Qii6cP1cSvIdl3iQkNYyi9HH0I22y+93tY3DcQkTZgQtM+POoCr8x97eylkmtrgKuztrvXJ21x/aNKuqIkZ/fntRfCdcTfhUTAIhRzoDojJD0aSNLLwMzmpT7+JaLtyf1MwDo6qz9djFaUq3t9MlFmy/c1OCSceY9fMsVaL9mvH9ocXdkdWxv1scAePG0THAhMOaLdOw/Gvxfxb1w4eCapyIENUcV5M3/u8FitAxZ25P6GAHT3UX39Srw+QOb1ZffA98Dl2Wy1BYkAAAAAElFTkSuQmCC');
background-repeat: no-repeat;
background-position: right 5px center;
background-size: 16px;
@@ -86,7 +90,7 @@
background: none;
border: 0;
border-radius: $border-radius-base;
- transition: transform .15s cubic-bezier(.3, 0, .2, 2);
+ transition: transform 0.15s cubic-bezier(0.3, 0, 0.2, 2);
&:hover {
background-color: transparent;
@@ -176,7 +180,7 @@
&.user-authored {
cursor: default;
background-color: $gray-light;
- border-color: $theme-gray-200;
+ border-color: $gray-200;
color: $gl-text-color-disabled;
gl-emoji {
@@ -229,10 +233,10 @@
height: $default-icon-size;
width: $default-icon-size;
border-radius: 50%;
+ }
- path {
- fill: $border-gray-normal;
- }
+ path {
+ fill: $border-gray-normal;
}
}
@@ -243,6 +247,10 @@
left: 10px;
bottom: 6px;
opacity: 0;
+
+ path {
+ fill: $award-emoji-positive-add-lines;
+ }
}
.award-control-text {
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 43b7c26b272..e6c55252b24 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -86,11 +86,8 @@
}
.block-controls {
- display: -webkit-flex;
display: flex;
- -webkit-justify-content: flex-end;
justify-content: flex-end;
- -webkit-flex: 1;
flex: 1;
.control {
@@ -153,7 +150,7 @@
display: inline-block;
margin-left: 5px;
font-size: 18px;
- color: color("gray");
+ color: color('gray');
}
p {
@@ -228,7 +225,6 @@
}
.group-info {
-
h1 {
display: inline;
font-weight: $gl-font-weight-normal;
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index a4a9276c580..a4af84f8d27 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -42,6 +42,10 @@
color: $text;
border-color: $border;
+ &.btn-border-color {
+ border-color: $border-color;
+ }
+
> .icon {
color: $text;
}
@@ -162,7 +166,8 @@
@include btn-outline($white-light, $green-600, $green-500, $green-500, $white-light, $green-600, $green-600, $green-700);
}
- &.btn-remove {
+ &.btn-remove,
+ &.btn-danger {
@include btn-outline($white-light, $red-500, $red-500, $red-500, $white-light, $red-600, $red-600, $red-700);
}
@@ -390,8 +395,6 @@
cursor: default;
&:active {
- -moz-box-shadow: inset 0 0 0 $white-light;
- -webkit-box-shadow: inset 0 0 0 $white-light;
box-shadow: inset 0 0 0 $white-light;
}
}
@@ -483,7 +486,7 @@
// All disabled buttons, regardless of color, type, etc
%disabled {
background-color: $gray-light !important;
- border-color: $theme-gray-200 !important;
+ border-color: $gray-200 !important;
color: $gl-text-color-disabled !important;
opacity: 1 !important;
cursor: default !important;
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index e037b02a30c..aad5150c0b5 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -48,7 +48,20 @@
color: $brand-info;
}
-.hint { font-style: italic; color: $gl-gray-400; }
+.text-break-word {
+ word-break: break-all;
+}
+
+.text-underline,
+.text-underline:hover {
+ text-decoration: underline;
+}
+
+.hint {
+ font-style: italic;
+ color: $gl-gray-400;
+}
+
.light { color: $gl-text-color; }
.slead {
@@ -89,6 +102,10 @@ hr {
.str-truncated {
@include str-truncated;
+ &-30 {
+ @include str-truncated(30%);
+ }
+
&-60 {
@include str-truncated(60%);
}
@@ -145,13 +162,14 @@ p.time {
text-shadow: none;
}
-.thin_area {
+.thin-area {
height: 150px;
}
// Fix issue with notes & lists creating a bunch of bottom borders.
li.note {
img { max-width: 100%; }
+
.note-title {
li {
border-bottom: 0 !important;
@@ -322,7 +340,7 @@ img.emoji {
.disabled-content {
pointer-events: none;
- opacity: .5;
+ opacity: 0.5;
}
.break-word {
@@ -381,13 +399,35 @@ img.emoji {
.inline { display: inline-block; }
.center { text-align: center; }
.vertical-align-middle { vertical-align: middle; }
+.vertical-align-sub { vertical-align: sub; }
.flex-align-self-center { align-self: center; }
.flex-grow { flex-grow: 1; }
.flex-no-shrink { flex-shrink: 0; }
-.mw-460 { max-width: 460px; }
.ws-initial { white-space: initial; }
+.ws-normal { white-space: normal; }
+.overflow-auto { overflow: auto; }
+
+.d-flex-center {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/** COMMON SIZING CLASSES **/
+.w-0 { width: 0; }
+
+.h-12em { height: 12em; }
+
+.mw-460 { max-width: 460px; }
+.mw-6em { max-width: 6em; }
+
.min-height-0 { min-height: 0; }
+.w-3 { width: #{3 * $grid-size}; }
+
+.h-3 { width: #{3 * $grid-size}; }
+
+/** COMMON SPACING CLASSES **/
.gl-pl-0 { padding-left: 0; }
.gl-pl-1 { padding-left: #{0.5 * $grid-size}; }
.gl-pl-2 { padding-left: $grid-size; }
@@ -401,3 +441,36 @@ img.emoji {
.gl-pr-3 { padding-right: #{2 * $grid-size}; }
.gl-pr-4 { padding-right: #{3 * $grid-size}; }
.gl-pr-5 { padding-right: #{4 * $grid-size}; }
+
+/**
+ * Removes browser specific clear icon from input fields in
+ * Internet Explorer 10, Internet Explorer 11, and Microsoft Edge.
+ * This is intended for elements which add a customized clear icon.
+ *
+ * see also https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-clear
+ */
+.ms-no-clear ::-ms-clear {
+ display: none;
+}
+
+/** COMMON POSITIONING CLASSES */
+.position-bottom-0 { bottom: 0; }
+.position-left-0 { left: 0; }
+.position-right-0 { right: 0; }
+.position-top-0 { top: 0; }
+
+.drag-handle {
+ width: 4px;
+
+ &:hover {
+ background-color: $white-normal;
+ }
+
+ &.is-dragging {
+ background-color: $gray-600;
+ }
+}
+
+.cursor-pointer {
+ cursor: pointer;
+}
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index 8b6a7017c47..3238b01c6c0 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -5,7 +5,7 @@
padding-left: $contextual-sidebar-collapsed-width;
}
- @include media-breakpoint-up(lg) {
+ @include media-breakpoint-up(xl) {
padding-left: $contextual-sidebar-width;
}
@@ -15,7 +15,7 @@
}
.page-with-icon-sidebar {
- @include media-breakpoint-up(sm) {
+ @include media-breakpoint-up(md) {
padding-left: $contextual-sidebar-collapsed-width;
}
}
@@ -71,6 +71,44 @@
}
}
+@mixin collapse-contextual-sidebar-content {
+ .context-header {
+ height: 60px;
+ width: $contextual-sidebar-collapsed-width;
+
+ a {
+ padding: 10px 4px;
+ }
+ }
+
+ .sidebar-top-level-items > li {
+ .sidebar-sub-level-items {
+ &:not(.flyout-list) {
+ display: none;
+ }
+ }
+ }
+
+ .nav-icon-container {
+ margin-right: 0;
+ }
+
+ .toggle-sidebar-button {
+ padding: 16px;
+ width: $contextual-sidebar-collapsed-width - 1px;
+
+ .collapse-text,
+ .icon-angle-double-left {
+ display: none;
+ }
+
+ .icon-angle-double-right {
+ display: block;
+ margin: 0;
+ }
+ }
+}
+
.nav-sidebar {
transition: width $sidebar-transition-duration, left $sidebar-transition-duration;
position: fixed;
@@ -89,7 +127,7 @@
}
}
- &.sidebar-collapsed-desktop {
+ @mixin collapse-contextual-sidebar {
width: $contextual-sidebar-collapsed-width;
.nav-sidebar-inner-scroll {
@@ -115,6 +153,10 @@
}
}
+ &.sidebar-collapsed-desktop {
+ @include collapse-contextual-sidebar;
+ }
+
&.sidebar-expanded-mobile {
left: 0;
}
@@ -150,7 +192,7 @@
}
}
- @include media-breakpoint-down(xs) {
+ @include media-breakpoint-down(sm) {
left: (-$contextual-sidebar-width);
}
@@ -167,16 +209,19 @@
height: 16px;
width: 16px;
}
+
+ @media (min-width: map-get($grid-breakpoints, md)) and (max-width: map-get($grid-breakpoints, xl) - 1px) {
+ &:not(.sidebar-expanded-mobile) {
+ @include collapse-contextual-sidebar;
+ @include collapse-contextual-sidebar-content;
+ }
+ }
}
.nav-sidebar-inner-scroll {
height: 100%;
width: 100%;
overflow: auto;
-
- @include media-breakpoint-up(sm) {
- overflow: hidden;
- }
}
.with-performance-bar .nav-sidebar {
@@ -346,53 +391,13 @@
}
}
-.toggle-sidebar-button {
- @include media-breakpoint-down(xs) {
- display: none;
- }
-}
-
.collapse-text {
white-space: nowrap;
overflow: hidden;
}
.sidebar-collapsed-desktop {
- .context-header {
- height: 60px;
- width: $contextual-sidebar-collapsed-width;
-
- a {
- padding: 10px 4px;
- }
- }
-
- .sidebar-top-level-items > li {
- .sidebar-sub-level-items {
- &:not(.flyout-list) {
- display: none;
- }
- }
- }
-
- .nav-icon-container {
- margin-right: 0;
- }
-
- .toggle-sidebar-button {
- padding: 16px;
- width: $contextual-sidebar-collapsed-width - 1px;
-
- .collapse-text,
- .icon-angle-double-left {
- display: none;
- }
-
- .icon-angle-double-right {
- display: block;
- margin: 0;
- }
- }
+ @include collapse-contextual-sidebar-content;
}
.fly-out-top-item {
@@ -428,16 +433,14 @@
color: $gl-text-color-secondary;
}
- @include media-breakpoint-down(xs) {
+ @include media-breakpoint-down(sm) {
display: flex;
align-items: center;
i {
font-size: 18px;
}
- }
- @include media-breakpoint-down(xs) {
+ .breadcrumbs-links {
padding-left: $gl-padding;
border-left: 1px solid $gl-text-color-quaternary;
@@ -445,21 +448,25 @@
}
}
-@include media-breakpoint-down(xs) {
+@include media-breakpoint-down(sm) {
.close-nav-button {
display: flex;
}
-}
-.mobile-overlay {
- display: none;
+ .toggle-sidebar-button {
+ display: none;
+ }
- &.mobile-nav-open {
- display: block;
- position: fixed;
- background-color: $black-transparent;
- height: 100%;
- width: 100%;
- z-index: 300;
+ .mobile-overlay {
+ display: none;
+
+ &.mobile-nav-open {
+ display: block;
+ position: fixed;
+ background-color: $black-transparent;
+ height: 100%;
+ width: 100%;
+ z-index: 300;
+ }
}
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index afcb230797a..b90db135b4a 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -32,6 +32,10 @@
max-height: $dropdown-max-height;
overflow-y: auto;
+ &.dropdown-extended-height {
+ max-height: 400px;
+ }
+
@include media-breakpoint-down(xs) {
width: 100%;
}
@@ -125,7 +129,7 @@
@extend .dropdown-toggle;
padding-right: 25px;
position: relative;
- width: 163px;
+ width: 160px;
text-overflow: ellipsis;
overflow: hidden;
diff --git a/app/assets/stylesheets/framework/emojis.scss b/app/assets/stylesheets/framework/emojis.scss
index be85e03430e..13c5541da92 100644
--- a/app/assets/stylesheets/framework/emojis.scss
+++ b/app/assets/stylesheets/framework/emojis.scss
@@ -2,7 +2,7 @@ gl-emoji {
font-style: normal;
display: inline-flex;
vertical-align: middle;
- font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-size: 1.4em;
line-height: 1em;
}
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 037a5adfb7e..6108eaa1ad0 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -4,6 +4,7 @@
*/
.file-holder {
border: 1px solid $border-color;
+ border-top: 0;
border-radius: $border-radius-default;
&.file-holder-no-border {
@@ -51,6 +52,7 @@
position: absolute;
top: 5px;
right: 15px;
+ margin-left: auto;
.btn {
padding: 0 10px;
@@ -324,10 +326,12 @@ span.idiff {
&,
.file-holder & {
display: flex;
+ flex-wrap: wrap;
align-items: center;
justify-content: space-between;
background-color: $gray-light;
border-bottom: 1px solid $border-color;
+ border-top: 1px solid $border-color;
padding: 5px $gl-padding;
margin: 0;
border-radius: $border-radius-default $border-radius-default 0 0;
@@ -365,16 +369,12 @@ span.idiff {
margin: 0 10px 0 0;
}
- .file-actions {
- white-space: nowrap;
-
- .btn {
- padding: 0 10px;
- font-size: 13px;
- line-height: 28px;
- display: inline-block;
- float: none;
- }
+ .file-actions .btn {
+ padding: 0 10px;
+ font-size: 13px;
+ line-height: 28px;
+ display: inline-block;
+ float: none;
}
@include media-breakpoint-down(xs) {
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index f48b3ddc912..e5b529ae11d 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -50,19 +50,15 @@
}
.filtered-search-wrapper {
- display: -webkit-flex;
display: flex;
@include media-breakpoint-down(xs) {
- -webkit-flex-direction: column;
flex-direction: column;
}
.tokens-container {
- display: -webkit-flex;
display: flex;
flex: 1;
- -webkit-flex: 1;
padding-left: 12px;
position: relative;
margin-bottom: 0;
@@ -82,21 +78,18 @@
.input-token:only-child,
.input-token:last-child {
flex: 1;
- -webkit-flex: 1;
max-width: inherit;
}
}
.filtered-search-token,
.filtered-search-term {
- display: -webkit-flex;
display: flex;
flex-shrink: 0;
margin-top: 4px;
margin-bottom: 4px;
.selectable {
- display: -webkit-flex;
display: flex;
}
@@ -176,7 +169,6 @@
}
.scroll-container {
- display: -webkit-flex;
display: flex;
overflow-x: auto;
white-space: nowrap;
@@ -186,7 +178,6 @@
.filtered-search-box {
position: relative;
flex: 1;
- display: -webkit-flex;
display: flex;
width: 100%;
min-width: 0;
@@ -194,7 +185,6 @@
background-color: $white-light;
@include media-breakpoint-down(xs) {
- -webkit-flex: 1 1 auto;
flex: 1 1 auto;
margin-bottom: 10px;
}
@@ -349,7 +339,6 @@
}
.filter-dropdown-container {
- display: -webkit-flex;
display: flex;
.dropdown-toggle {
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index 4da2243981e..3b1d1d67509 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -36,6 +36,15 @@ label {
}
}
+.label-wrapper {
+ display: block;
+ margin: 0;
+}
+
+.form-label {
+ @extend label;
+}
+
.form-control-label {
@extend .col-md-2;
}
@@ -147,8 +156,6 @@ label {
.select-control {
padding-left: 10px;
padding-right: 10px;
- -webkit-appearance: none;
- -moz-appearance: none;
appearance: none;
&::-ms-expand {
@@ -169,7 +176,8 @@ label {
font-weight: $gl-font-weight-normal;
}
-.form-control::-webkit-input-placeholder {
+
+.form-control::placeholder {
color: $gl-text-color-tertiary;
}
@@ -252,7 +260,7 @@ label {
right: 0.8em;
top: 50%;
transform: translateY(-50%);
- color: $theme-gray-600;
+ color: $gray-600;
}
}
diff --git a/app/assets/stylesheets/framework/gfm.scss b/app/assets/stylesheets/framework/gfm.scss
index 50d4298d418..6943bfbc3d0 100644
--- a/app/assets/stylesheets/framework/gfm.scss
+++ b/app/assets/stylesheets/framework/gfm.scss
@@ -32,7 +32,7 @@
height: $chip-size;
background: $white-light;
background-image: linear-gradient(135deg, $gray-dark 25%, transparent 0%, transparent 75%, $gray-dark 0%),
- linear-gradient(135deg, $gray-dark 25%, transparent 0%, transparent 75%, $gray-dark 0%);
+ linear-gradient(135deg, $gray-dark 25%, transparent 0%, transparent 75%, $gray-dark 0%);
background-size: $bg-size $bg-size;
background-position: 0 0, $bg-pos $bg-pos;
diff --git a/app/assets/stylesheets/framework/gitlab_theme.scss b/app/assets/stylesheets/framework/gitlab_theme.scss
index 0ef50e139f2..418eafa153c 100644
--- a/app/assets/stylesheets/framework/gitlab_theme.scss
+++ b/app/assets/stylesheets/framework/gitlab_theme.scss
@@ -282,31 +282,31 @@ body {
&.ui-dark {
@include gitlab-theme(
- $theme-gray-200,
- $theme-gray-500,
- $theme-gray-700,
- $theme-gray-800,
- $theme-gray-900,
+ $gray-200,
+ $gray-500,
+ $gray-700,
+ $gray-800,
+ $gray-900,
$white-light
);
}
&.ui-light {
@include gitlab-theme(
- $theme-gray-700,
- $theme-gray-800,
- $theme-gray-700,
- $theme-gray-700,
- $theme-gray-100,
- $theme-gray-700
+ $gray-700,
+ $gray-800,
+ $gray-700,
+ $gray-700,
+ $gray-100,
+ $gray-700
);
.navbar-gitlab {
- background-color: $theme-gray-100;
+ background-color: $gray-100;
box-shadow: 0 1px 0 0 $border-color;
.logo-text svg {
- fill: $theme-gray-900;
+ fill: $gray-900;
}
.navbar-sub-nav,
@@ -315,7 +315,7 @@ body {
> a:hover,
> a:focus,
> button:hover {
- color: $theme-gray-900;
+ color: $gray-900;
}
&.active > a,
@@ -329,8 +329,8 @@ body {
.container-fluid {
.navbar-toggler,
.navbar-toggler:hover {
- color: $theme-gray-700;
- border-left: 1px solid $theme-gray-200;
+ color: $gray-700;
+ border-left: 1px solid $gray-200;
}
}
}
@@ -348,7 +348,7 @@ body {
.search-input-wrap {
.search-icon {
- fill: $theme-gray-200;
+ fill: $gray-200;
}
.search-input {
@@ -359,16 +359,16 @@ body {
.nav-sidebar li.active {
> a {
- color: $theme-gray-900;
+ color: $gray-900;
}
svg {
- fill: $theme-gray-900;
+ fill: $gray-900;
}
}
.sidebar-top-level-items > li.active .badge.badge-pill {
- color: $theme-gray-900;
+ color: $gray-900;
}
}
}
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 7d283dcfb71..f5ed6621c55 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -39,7 +39,6 @@
.header-content {
width: 100%;
- display: -webkit-flex;
display: flex;
justify-content: space-between;
position: relative;
@@ -47,11 +46,8 @@
padding-left: 0;
.title-container {
- display: -webkit-flex;
display: flex;
- -webkit-align-items: stretch;
align-items: stretch;
- -webkit-flex: 1 1 auto;
flex: 1 1 auto;
padding-top: 0;
overflow: visible;
@@ -60,7 +56,6 @@
.title {
padding-right: 0;
color: currentColor;
- display: -webkit-flex;
display: flex;
position: relative;
margin: 0;
@@ -85,7 +80,6 @@
}
a {
- display: -webkit-flex;
display: flex;
align-items: center;
padding: 2px 8px;
@@ -173,7 +167,6 @@
.navbar-nav {
@include media-breakpoint-down(xs) {
- display: -webkit-flex;
display: flex;
padding-right: 10px;
flex-direction: row;
@@ -258,7 +251,6 @@
> li {
> a,
> button {
- display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
@@ -294,7 +286,6 @@
}
.navbar-sub-nav {
- display: -webkit-flex;
display: flex;
margin: 0 0 0 6px;
@@ -326,14 +317,12 @@
}
.breadcrumbs {
- display: -webkit-flex;
display: flex;
min-height: $breadcrumb-min-height;
color: $gl-text-color;
}
.breadcrumbs-container {
- display: -webkit-flex;
display: flex;
width: 100%;
position: relative;
@@ -344,7 +333,6 @@
}
.breadcrumbs-links {
- -webkit-flex: 1;
flex: 1;
min-width: 0;
align-self: center;
@@ -379,7 +367,6 @@
}
.breadcrumbs-list {
- display: -webkit-flex;
display: flex;
margin-bottom: 0;
line-height: 16px;
@@ -430,7 +417,6 @@
}
.breadcrumbs-extra {
- display: -webkit-flex;
display: flex;
flex: 0 0 auto;
margin-left: auto;
@@ -565,15 +551,14 @@
}
.navbar-empty {
+ justify-content: center;
height: $header-height;
background: $white-light;
border-bottom: 1px solid $white-normal;
- .mx-auto {
- .tanuki-logo,
- img {
- height: 36px;
- }
+ .tanuki-logo,
+ .brand-header-logo {
+ max-height: 100%;
}
}
@@ -596,4 +581,16 @@
.emoji-menu-toggle-button {
@include emoji-menu-toggle-button;
}
+
+ .input-group {
+ height: 34px;
+ }
+}
+
+.nav-links > li > a {
+ .badge.badge-pill {
+ @include media-breakpoint-down(xs) { display: none; }
+ }
+
+ @include media-breakpoint-down(xs) { margin-right: 3px; }
}
diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss
index 8db7d63266e..49b9b7014ae 100644
--- a/app/assets/stylesheets/framework/icons.scss
+++ b/app/assets/stylesheets/framework/icons.scss
@@ -87,8 +87,8 @@
display: flex;
align-items: center;
justify-content: center;
- border: $border-size solid $theme-gray-400;
+ border: $border-size solid $gray-400;
border-radius: 50%;
padding: $gl-padding-8 - $border-size;
- color: $theme-gray-700;
+ color: $gray-700;
}
diff --git a/app/assets/stylesheets/framework/images.scss b/app/assets/stylesheets/framework/images.scss
index a20920e2503..d78c707192f 100644
--- a/app/assets/stylesheets/framework/images.scss
+++ b/app/assets/stylesheets/framework/images.scss
@@ -38,7 +38,10 @@
svg {
fill: currentColor;
+}
+.square,
+svg {
$svg-sizes: 8 10 12 14 16 18 24 32 48 72;
@each $svg-size in $svg-sizes {
&.s#{$svg-size} {
diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss
index a66604e56ff..e51f230a680 100644
--- a/app/assets/stylesheets/framework/issue_box.scss
+++ b/app/assets/stylesheets/framework/issue_box.scss
@@ -45,9 +45,4 @@
&.status-box-upcoming {
background: $gl-text-color-secondary;
}
-
- &.status-box-milestone {
- color: $gl-text-color;
- background: $gray-darker;
- }
}
diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss
index 9218df9b40f..97cb9d90ff0 100644
--- a/app/assets/stylesheets/framework/layout.scss
+++ b/app/assets/stylesheets/framework/layout.scss
@@ -40,6 +40,14 @@ body {
.content {
margin: 0;
+
+ @include media-breakpoint-down(xs) { margin-top: 20px; }
+ }
+
+ @include media-breakpoint-down(xs) {
+ .container .title {
+ padding-left: 15px !important;
+ }
}
}
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index d9d4a210f5f..1a74e06a75d 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -15,7 +15,7 @@
word-wrap: break-word;
&::after {
- content: " ";
+ content: ' ';
display: table;
clear: both;
}
@@ -167,7 +167,7 @@ ul.content-list {
}
.no-comments {
- opacity: .5;
+ opacity: 0.5;
}
}
@@ -196,8 +196,6 @@ ul.content-list {
// Content list using flexbox
.flex-list {
.flex-row {
- display: -webkit-flex;
- display: -ms-flexbox;
display: flex;
align-items: center;
white-space: nowrap;
diff --git a/app/assets/stylesheets/framework/logo.scss b/app/assets/stylesheets/framework/logo.scss
index 429cfbe7235..c5feefb8c54 100644
--- a/app/assets/stylesheets/framework/logo.scss
+++ b/app/assets/stylesheets/framework/logo.scss
@@ -9,7 +9,6 @@
}
.tanuki-logo {
-
.tanuki-left-ear,
.tanuki-right-ear,
.tanuki-nose {
@@ -34,7 +33,9 @@
.tanuki-left-cheek {
@include include-keyframes(animate-tanuki-left-cheek) {
- 0%, 10%, 100% {
+ 0%,
+ 10%,
+ 100% {
fill: lighten($tanuki-yellow, 25%);
}
@@ -46,11 +47,13 @@
.tanuki-left-eye {
@include include-keyframes(animate-tanuki-left-eye) {
- 10%, 80% {
+ 10%,
+ 80% {
fill: $tanuki-orange;
}
- 20%, 90% {
+ 20%,
+ 90% {
fill: lighten($tanuki-orange, 25%);
}
}
@@ -58,11 +61,13 @@
.tanuki-left-ear {
@include include-keyframes(animate-tanuki-left-ear) {
- 10%, 80% {
+ 10%,
+ 80% {
fill: $tanuki-red;
}
- 20%, 90% {
+ 20%,
+ 90% {
fill: lighten($tanuki-red, 25%);
}
}
@@ -70,11 +75,13 @@
.tanuki-nose {
@include include-keyframes(animate-tanuki-nose) {
- 20%, 70% {
+ 20%,
+ 70% {
fill: $tanuki-red;
}
- 30%, 80% {
+ 30%,
+ 80% {
fill: lighten($tanuki-red, 25%);
}
}
@@ -82,11 +89,13 @@
.tanuki-right-eye {
@include include-keyframes(animate-tanuki-right-eye) {
- 30%, 60% {
+ 30%,
+ 60% {
fill: $tanuki-orange;
}
- 40%, 70% {
+ 40%,
+ 70% {
fill: lighten($tanuki-orange, 25%);
}
}
@@ -94,11 +103,13 @@
.tanuki-right-ear {
@include include-keyframes(animate-tanuki-right-ear) {
- 30%, 60% {
+ 30%,
+ 60% {
fill: $tanuki-red;
}
- 40%, 70% {
+ 40%,
+ 70% {
fill: lighten($tanuki-red, 25%);
}
}
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index 5609a2086e6..d6c4e68f68f 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -149,16 +149,8 @@
margin: 10px 0;
}
- // Border around images in issue and MR comments.
- img:not(.emoji) {
- border: 1px solid $white-normal;
- padding: 5px;
- margin: 5px 0;
- // Ensure that image does not exceed viewport
- max-height: calc(100vh - 100px);
- }
- table {
+ table:not(.js-syntax-highlight) {
@include markdown-table;
}
}
@@ -173,7 +165,7 @@
svg {
width: 14px;
height: 14px;
- margin-top: 3px;
+ vertical-align: middle;
fill: $gl-text-color-secondary;
}
@@ -228,7 +220,7 @@
.cur {
.avatar {
- @include disableAllAnimation;
+ @include disable-all-animation;
border: 1px solid $white-light;
}
}
@@ -280,6 +272,8 @@
.md-suggestion-diff {
display: table !important;
border: 1px solid $border-color !important;
+ width: 100% !important;
+ font-family: $monospace-font !important;
}
.md-suggestion-header {
@@ -307,4 +301,8 @@
overflow: hidden;
text-overflow: ellipsis;
}
+
+ .referenced-users {
+ margin-right: 0;
+ }
}
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 9837b1a6bd0..ba3b0906e28 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -26,20 +26,11 @@
*/
@mixin markdown-table {
width: auto;
- display: inline-block;
+ display: block;
overflow-x: auto;
border: 0;
border-color: $gl-gray-100;
- @supports (width: fit-content) {
- display: block;
- width: fit-content;
- }
-
- tbody {
- background-color: $white-light;
- }
-
tr {
th {
border-bottom: solid 2px $gl-gray-100;
@@ -117,11 +108,6 @@
}
}
-@mixin dark-diff-match-line {
- color: $dark-diff-match-bg;
- background: $dark-diff-match-color;
-}
-
@mixin webkit-prefix($property, $value) {
#{'-webkit-' + $property}: $value;
#{$property}: $value;
@@ -129,16 +115,13 @@
/* http://phrappe.com/css/conditional-css-for-webkit-based-browsers/ */
@mixin on-webkit-only {
+ /* stylelint-disable-next-line media-feature-name-no-vendor-prefix */
@media screen and (-webkit-min-device-pixel-ratio: 0) {
@content;
}
}
@mixin keyframes($animation-name) {
- @-webkit-keyframes #{$animation-name} {
- @content;
- }
-
@keyframes #{$animation-name} {
@content;
}
@@ -178,12 +161,10 @@
width: 43px;
height: 30px;
transition-duration: 0.3s;
- -webkit-transform: translateZ(0);
- background: linear-gradient(
- to $gradient-direction,
- $gradient-color 45%,
- rgba($gradient-color, 0.4)
- );
+ transform: translateZ(0);
+ background: linear-gradient(to $gradient-direction,
+ $gradient-color 45%,
+ rgba($gradient-color, 0.4));
&.scrolling {
visibility: visible;
@@ -279,7 +260,6 @@
border: 1px solid $border-color;
color: $gl-text-color;
position: sticky;
- position: -webkit-sticky;
top: $header-height;
padding: $grid-size;
diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
deleted file mode 100644
index 3bb046d0e51..00000000000
--- a/app/assets/stylesheets/framework/mobile.scss
+++ /dev/null
@@ -1,88 +0,0 @@
-/** Common mobile (screen XS, SM) styles **/
-@include media-breakpoint-down(xs) {
- .container .content {
- margin-top: 20px;
- }
-
- .nav-links > li > a {
- padding: 10px;
- font-size: 12px;
- margin-right: 3px;
-
- .badge.badge-pill {
- display: none;
- }
- }
-
- .referenced-users {
- margin-right: 0;
- }
-
- .issues-details-filters:not(.filtered-search-block),
- .dash-projects-filters,
- .check-all-holder {
- display: none;
- }
-
- .rss-btn {
- display: none;
- }
-
- .project-home-links {
- display: none;
- }
-
- .project-home-panel {
- padding-left: 0 !important;
-
- .project-repo-buttons,
- .git-clone-holder {
- display: none;
- }
- }
-
- .group-buttons {
- display: none;
- }
-
- .container .title {
- padding-left: 15px !important;
- }
-
- .nav-links,
- .nav-links {
- li a {
- font-size: 14px;
- padding: 19px 10px;
- }
- }
-
- .activity-filter-block {
- display: none;
- }
-
- .projects-search-form {
- .btn {
- display: none;
- }
- }
-}
-
-@include media-breakpoint-down(sm) {
- .issues-filters {
- .milestone-filter {
- display: none;
- }
- }
-
- .page-title {
- .note-created-ago,
- .new-issue-link {
- display: none;
- }
- }
-
- aside:not(.right-sidebar) {
- display: none;
- }
-}
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index 95291b4a9ad..3703b7568c8 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -29,10 +29,6 @@
padding-right: 28px;
}
}
-
- .page-title {
- margin-top: 0;
- }
}
.modal-body {
@@ -105,3 +101,42 @@ body.modal-open {
margin: 0;
}
}
+
+.issues-import-modal,
+.issues-export-modal {
+ .modal-header {
+ justify-content: flex-start;
+
+ .import-export-svg-container {
+ flex-grow: 1;
+ height: 56px;
+ padding: $gl-btn-padding $gl-btn-padding 0;
+ text-align: right;
+
+ .illustration {
+ height: inherit;
+ width: initial;
+ }
+ }
+ }
+
+ .modal-body {
+ padding: 0;
+
+ .modal-subheader {
+ justify-content: flex-start;
+ align-items: center;
+ border-bottom: 1px solid $modal-border-color;
+ padding: 14px;
+ }
+
+ .modal-text {
+ padding: $gl-padding-24 $gl-padding;
+ min-height: $modal-body-height;
+ }
+ }
+
+ .checkmark {
+ color: $green-400;
+ }
+}
diff --git a/app/assets/stylesheets/framework/responsive_tables.scss b/app/assets/stylesheets/framework/responsive_tables.scss
index 29a9c076cdf..6bd44ee19bd 100644
--- a/app/assets/stylesheets/framework/responsive_tables.scss
+++ b/app/assets/stylesheets/framework/responsive_tables.scss
@@ -39,7 +39,7 @@
.table-section {
white-space: nowrap;
- $section-widths: 5 10 15 20 25 30 40 50 60 100;
+ $section-widths: 5 10 15 20 25 30 40 50 60 70 80 100;
@each $width in $section-widths {
&.section-#{$width} {
flex: 0 0 #{$width + '%'};
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index a68f1e4e570..ac673eafdc7 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -32,7 +32,7 @@
}
&::after {
- content: "\f078";
+ content: '\f078';
position: absolute;
z-index: 1;
text-align: center;
@@ -57,6 +57,16 @@
color: $gl-text-color;
}
}
+
+ &.is-invalid {
+ ~ .invalid-feedback {
+ display: block;
+ }
+
+ .select2-choices {
+ border-color: $red-500;
+ }
+ }
}
.select2-drop,
@@ -67,10 +77,18 @@
min-width: 175px;
color: $gl-text-color;
z-index: 999;
+
+ .modal-open & {
+ z-index: $zindex-modal + 200;
+ }
}
.select2-drop-mask {
z-index: 998;
+
+ .modal-open & {
+ z-index: $zindex-modal + 100;
+ }
}
.select2-drop.select2-drop-above.select2-drop-active {
diff --git a/app/assets/stylesheets/framework/spinner.scss b/app/assets/stylesheets/framework/spinner.scss
new file mode 100644
index 00000000000..91fe75075dc
--- /dev/null
+++ b/app/assets/stylesheets/framework/spinner.scss
@@ -0,0 +1,51 @@
+@mixin spinner-color($color) {
+ border-color: rgba($color, 0.25);
+ border-top-color: $color;
+}
+
+@mixin spinner-size($size, $border-width) {
+ width: $size;
+ height: $size;
+ border-width: $border-width;
+ @include webkit-prefix(transform-origin, 50% 50% calc((#{$size} / 2) + #{$border-width}));
+}
+
+@keyframes spinner-rotate {
+ 0% {
+ transform: rotate(0);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+.spinner {
+ border-radius: 50%;
+ position: relative;
+ margin: 0 auto;
+ animation-name: spinner-rotate;
+ animation-duration: 0.6s;
+ animation-timing-function: linear;
+ animation-iteration-count: infinite;
+ border-style: solid;
+ display: inline-flex;
+ @include spinner-size(16px, 2px);
+ @include spinner-color($orange-600);
+
+ &.spinner-md {
+ @include spinner-size(32px, 3px);
+ }
+
+ &.spinner-lg {
+ @include spinner-size(64px, 4px);
+ }
+
+ &.spinner-dark {
+ @include spinner-color($gray-700);
+ }
+
+ &.spinner-light {
+ @include spinner-color($white);
+ }
+}
diff --git a/app/assets/stylesheets/framework/stacked_progress_bar.scss b/app/assets/stylesheets/framework/stacked_progress_bar.scss
index 29a2d5881f7..2255d3be75b 100644
--- a/app/assets/stylesheets/framework/stacked_progress_bar.scss
+++ b/app/assets/stylesheets/framework/stacked_progress_bar.scss
@@ -3,7 +3,7 @@
height: 16px;
border-radius: 10px;
overflow: hidden;
- background-color: $theme-gray-100;
+ background-color: $gray-100;
.status-unavailable,
.status-green,
@@ -24,7 +24,7 @@
.status-unavailable {
padding: 0 10px;
- color: $theme-gray-700;
+ color: $gray-700;
}
.status-green {
@@ -36,11 +36,11 @@
}
.status-neutral {
- background-color: $theme-gray-200;
+ background-color: $gray-200;
color: $gl-gray-dark;
&:hover {
- background-color: $theme-gray-300;
+ background-color: $gray-300;
}
}
diff --git a/app/assets/stylesheets/framework/system_messages.scss b/app/assets/stylesheets/framework/system_messages.scss
new file mode 100644
index 00000000000..3d66136938f
--- /dev/null
+++ b/app/assets/stylesheets/framework/system_messages.scss
@@ -0,0 +1,110 @@
+.header-message,
+.footer-message {
+ padding: 0 15px;
+ border: 1px solid transparent;
+ border-radius: 0;
+ position: fixed;
+ left: 0;
+ width: 100%;
+ text-align: center;
+ margin: 0;
+ z-index: 1000;
+
+ p {
+ @include str-truncated(100%);
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+}
+
+.header-message {
+ top: 0;
+ height: $system-header-height;
+ line-height: $system-header-height;
+}
+
+.footer-message {
+ bottom: 0;
+ height: $system-footer-height;
+ line-height: $system-footer-height;
+}
+
+.with-performance-bar {
+ .header-message {
+ top: $performance-bar-height;
+ }
+}
+
+// System Header
+.with-system-header {
+ // main navigation
+ // login page
+ .navbar-gitlab,
+ .fixed-top {
+ top: $system-header-height;
+ }
+
+ // left sidebar eg: project page
+ // right sidebar eg: MR page
+ .nav-sidebar,
+ .right-sidebar {
+ top: $system-header-height + $header-height;
+ }
+
+ .content-wrapper {
+ margin-top: $system-header-height + $header-height;
+ }
+
+ // Performance Bar
+ // System Header
+ &.with-performance-bar {
+ // main navigation
+ header.navbar-gitlab {
+ top: $performance-bar-height + $system-header-height;
+ }
+
+ .layout-page {
+ margin-top: $header-height + $performance-bar-height + $system-header-height;
+ }
+
+ // left sidebar eg: project page
+ // right sidebar eg: MR page
+ .nav-sidebar,
+ .right-sidebar {
+ top: $header-height + $performance-bar-height + $system-header-height;
+ }
+ }
+}
+
+// System Footer
+.with-system-footer {
+ // left sidebar eg: project page
+ // right sidebar eg: mr page
+ .nav-sidebar,
+ .right-sidebar,
+ // navless pages' footer eg: login page
+ // navless pages' footer border eg: login page
+ &.devise-layout-html body .footer-container,
+ &.devise-layout-html body hr.footer-fixed {
+ bottom: $system-footer-height;
+ }
+}
+
+.fullscreen-layout {
+ .header-message,
+ .footer-message {
+ position: static;
+ top: auto;
+ bottom: auto;
+ }
+
+ .content-wrapper {
+ .with-system-header & {
+ margin-top: 0;
+ }
+
+ .with-system-footer & {
+ margin-top: 0;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index 6954e6599b1..295a5b5ee7a 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -50,6 +50,14 @@ table {
border-color: $white-normal;
}
}
+
+ .thead-white {
+ th {
+ background-color: $white-light;
+ color: $gl-text-color-secondary;
+ border-top: 0;
+ }
+ }
}
&.responsive-table {
@@ -153,3 +161,4 @@ table {
border-top: 0;
}
}
+
diff --git a/app/assets/stylesheets/framework/terms.scss b/app/assets/stylesheets/framework/terms.scss
index 3f4be8829d7..b07d6023127 100644
--- a/app/assets/stylesheets/framework/terms.scss
+++ b/app/assets/stylesheets/framework/terms.scss
@@ -13,7 +13,6 @@
.card {
.card-header {
- display: -webkit-flex;
display: flex;
align-items: center;
justify-content: space-between;
diff --git a/app/assets/stylesheets/framework/toggle.scss b/app/assets/stylesheets/framework/toggle.scss
index 8258da07e4d..5f8ac3b7e37 100644
--- a/app/assets/stylesheets/framework/toggle.scss
+++ b/app/assets/stylesheets/framework/toggle.scss
@@ -34,7 +34,7 @@
background: $gl-gray-400;
border-radius: 12px;
padding: 3px;
- transition: all .4s ease;
+ transition: all 0.4s ease;
&::selection,
&::before::selection,
@@ -52,7 +52,7 @@
left: 0;
border-radius: 9px;
background: $feature-toggle-color;
- transition: all .2s ease;
+ transition: all 0.2s ease;
&,
.toggle-icon-svg {
@@ -135,12 +135,18 @@
}
@keyframes animate-enabled {
- 0%, 35% { opacity: 0; }
+ 0%,
+
+ 35% { opacity: 0; }
+
100% { opacity: 1; }
}
@keyframes animate-disabled {
- 0%, 35% { opacity: 0; }
+ 0%,
+
+ 35% { opacity: 0; }
+
100% { opacity: 1; }
}
}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 0c81dc2e156..55ce0d7004e 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -2,7 +2,7 @@
color: $gl-text-color;
word-wrap: break-word;
- [dir="auto"] {
+ [dir='auto'] {
text-align: initial;
}
@@ -49,13 +49,6 @@
word-wrap: normal;
}
- // Multi-line code blocks should scroll horizontally
- pre {
- code {
- white-space: pre;
- }
- }
-
kbd {
display: inline-block;
padding: 3px 5px;
@@ -143,11 +136,12 @@
margin: 0 0 16px;
}
- table {
+ table:not(.js-syntax-highlight) {
@extend .table;
@extend .table-bordered;
margin: 16px 0;
color: $gl-text-color;
+ border: 0;
th {
background: $label-gray-bg;
@@ -165,6 +159,10 @@
overflow-x: auto;
border-radius: 2px;
+ // Multi-line code blocks should scroll horizontally
+ code {
+ white-space: pre;
+ }
&.plain-readme {
background: none;
@@ -226,8 +224,8 @@
}
}
- a[href*="/uploads/"],
- a[href*="storage.googleapis.com/google-code-attachments/"] {
+ a[href*='/uploads/'],
+ a[href*='storage.googleapis.com/google-code-attachments/'] {
&::before {
margin-right: 4px;
@@ -235,7 +233,7 @@
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
- content: "\f0c6";
+ content: '\f0c6';
}
&:hover::before {
@@ -302,11 +300,10 @@ body {
}
.page-title-empty {
- margin-top: 0;
+ margin: 12px 0;
line-height: 1.3;
font-size: 1.25em;
font-weight: $gl-font-weight-bold;
- margin: 12px 0;
}
h1,
@@ -374,6 +371,16 @@ code {
.md:not(.use-csslab) {
@include md-typography;
+
+ &:not(.wiki) {
+ img:not(.emoji) {
+ border: 1px solid $white-normal;
+ padding: 5px;
+ margin: 5px 0;
+ // Ensure that image does not exceed viewport
+ max-height: calc(100vh - 100px);
+ }
+ }
}
/**
@@ -416,6 +423,7 @@ h4 {
/**
* form text input i.e. search bar, comments, forms, etc.
*/
+/* stylelint-disable selector-no-vendor-prefix */
input,
textarea {
&::-webkit-input-placeholder {
@@ -440,5 +448,6 @@ textarea {
color: $gl-text-color-tertiary;
}
}
+/* stylelint-enable */
.lh-100 { line-height: 1; }
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 343c09b4a3e..0333b9445c5 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -32,13 +32,22 @@ $gray-dark: darken($gray-light, $darken-dark-factor);
$gray-darker: #eee;
$gray-darkest: #c4c4c4;
-$gl-gray-100: #dddddd;
-$gl-gray-200: #cccccc;
-$gl-gray-350: #aaaaaa;
-$gl-gray-400: #999999;
-$gl-gray-500: #777777;
-$gl-gray-600: #666666;
-$gl-gray-700: #555555;
+$black: #000;
+$black-transparent: rgba(0, 0, 0, 0.3);
+$almost-black: #242424;
+
+$t-gray-a-02: rgba($black, 0.02);
+$t-gray-a-04: rgba($black, 0.04);
+$t-gray-a-06: rgba($black, 0.06);
+$t-gray-a-08: rgba($black, 0.08);
+
+$gl-gray-100: #ddd;
+$gl-gray-200: #ccc;
+$gl-gray-350: #aaa;
+$gl-gray-400: #999;
+$gl-gray-500: #777;
+$gl-gray-600: #666;
+$gl-gray-700: #555;
$green-50: #f1fdf6;
$green-100: #dcf5e7;
@@ -88,6 +97,18 @@ $red-800: #8b2615;
$red-900: #711e11;
$red-950: #4b140b;
+$gray-50: #fafafa;
+$gray-100: #f2f2f2;
+$gray-200: #dfdfdf;
+$gray-300: #ccc;
+$gray-400: #bababa;
+$gray-500: #a7a7a7;
+$gray-600: #919191;
+$gray-700: #707070;
+$gray-800: #4f4f4f;
+$gray-900: #2e2e2e;
+$gray-950: #1f1f1f;
+
// GitLab themes
$indigo-50: #f7f7ff;
@@ -102,18 +123,6 @@ $indigo-800: #393982;
$indigo-900: #292961;
$indigo-950: #1a1a40;
-$theme-gray-50: #fafafa;
-$theme-gray-100: #f2f2f2;
-$theme-gray-200: #dfdfdf;
-$theme-gray-300: #cccccc;
-$theme-gray-400: #bababa;
-$theme-gray-500: #a7a7a7;
-$theme-gray-600: #919191;
-$theme-gray-700: #707070;
-$theme-gray-800: #4f4f4f;
-$theme-gray-900: #2e2e2e;
-$theme-gray-950: #1f1f1f;
-
$theme-blue-50: #f4f8fc;
$theme-blue-100: #e6edf5;
$theme-blue-200: #c8d7e6;
@@ -170,11 +179,6 @@ $theme-light-red-500: #c24b38;
$theme-light-red-600: #b03927;
$theme-light-red-700: #a62e21;
-$black: #000;
-$black-transparent: rgba(0, 0, 0, 0.3);
-$shadow-color: rgba($black, 0.1);
-$almost-black: #242424;
-
$border-white-light: darken($white-light, $darken-border-factor);
$border-white-normal: darken($white-normal, $darken-border-factor);
@@ -187,6 +191,7 @@ $border-gray-dark: darken($white-normal, $darken-border-factor);
* UI elements
*/
$border-color: #e5e5e5;
+$shadow-color: $t-gray-a-08;
$well-expand-item: #e8f2f7;
$well-inner-border: #eef0f2;
$well-light-border: #f1f1f1;
@@ -198,7 +203,6 @@ $well-light-text-color: #5b6169;
$gl-font-size: 14px;
$gl-font-size-xs: 11px;
$gl-font-size-small: 12px;
-$gl-font-size-medium: 20px;
$gl-font-size-large: 16px;
$gl-font-weight-normal: 400;
$gl-font-weight-bold: 600;
@@ -239,6 +243,7 @@ $gl-padding-8: 8px;
$gl-padding: 16px;
$gl-padding-24: 24px;
$gl-padding-32: 32px;
+$gl-padding-50: 50px;
$gl-col-padding: 15px;
$gl-input-padding: 10px;
$gl-vert-padding: 6px;
@@ -246,7 +251,7 @@ $gl-padding-top: 10px;
$gl-sidebar-padding: 22px;
$gl-bar-padding: 3px;
$input-horizontal-padding: 12px;
-$browserScrollbarSize: 10px;
+$browser-scrollbar-size: 10px;
/*
* Misc
@@ -260,6 +265,7 @@ $container-text-max-width: 540px;
$gl-avatar-size: 40px;
$border-radius-default: 4px;
$border-radius-small: 2px;
+$border-radius-large: 8px;
$default-icon-size: 18px;
$layout-link-gray: #7e7c7c;
$btn-side-margin: 10px;
@@ -271,11 +277,13 @@ $general-hover-transition-duration: 100ms;
$general-hover-transition-curve: linear;
$highlight-changes-color: rgb(235, 255, 232);
$performance-bar-height: 35px;
+$system-header-height: 35px;
+$system-footer-height: $system-header-height;
$flash-height: 52px;
$context-header-height: 60px;
$breadcrumb-min-height: 48px;
-$project-title-row-height: 64px;
-$project-avatar-mobile-size: 24px;
+$home-panel-title-row-height: 64px;
+$home-panel-avatar-mobile-size: 24px;
$gl-line-height: 16px;
$gl-line-height-24: 24px;
$gl-line-height-14: 14px;
@@ -315,8 +323,8 @@ $line-select-yellow: #fcf8e7;
$line-select-yellow-dark: #f0e2bd;
$dark-diff-match-bg: rgba(255, 255, 255, 0.3);
$dark-diff-match-color: rgba(255, 255, 255, 0.1);
-$diff-image-info-color: gray;
-$diff-view-modes-color: gray;
+$diff-image-info-color: #808080;
+$diff-view-modes-color: #808080;
$diff-view-modes-border: #c1c1c1;
$diff-jagged-border-gradient-color: darken($white-normal, 8%);
@@ -335,6 +343,7 @@ $regular-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-San
$dropdown-width: 300px;
$dropdown-min-height: 40px;
$dropdown-max-height: 312px;
+$dropdown-max-height-lg: 445px;
$dropdown-vertical-offset: 4px;
$dropdown-empty-row-bg: rgba(#000, 0.04);
$dropdown-shadow-color: rgba(#000, 0.1);
@@ -400,6 +409,8 @@ $status-icon-size: 22px;
$award-emoji-menu-shadow: rgba(0, 0, 0, 0.175);
$award-emoji-positive-add-bg: #fed159;
$award-emoji-positive-add-lines: #bb9c13;
+$award-emoji-width: 376px;
+$award-emoji-width-xs: 300px;
/*
* Search Box
@@ -486,6 +497,7 @@ $builds-trace-bg: #111;
*/
$commit-max-width-marker-color: rgba(0, 0, 0, 0);
$commit-message-text-area-bg: rgba(0, 0, 0, 0);
+$commit-stat-summary-height: 36px;
/*
* Common
@@ -652,6 +664,7 @@ $border-color-settings: #e1e1e1;
Modals
*/
$modal-body-height: 134px;
+$modal-border-color: #e9ecef;
$priority-label-empty-state-width: 114px;
@@ -659,3 +672,14 @@ $priority-label-empty-state-width: 114px;
Issues Analytics
*/
$issues-analytics-popover-boarder-color: rgba(0, 0, 0, 0.15);
+
+/*
+Merge Requests
+*/
+$mr-tabs-height: 51px;
+$mr-version-controls-height: 56px;
+
+/*
+Compare Branches
+*/
+$compare-branches-sticky-header-height: 68px;
diff --git a/app/assets/stylesheets/framework/variables_overrides.scss b/app/assets/stylesheets/framework/variables_overrides.scss
index 069f45bff49..79d52932719 100644
--- a/app/assets/stylesheets/framework/variables_overrides.scss
+++ b/app/assets/stylesheets/framework/variables_overrides.scss
@@ -5,7 +5,7 @@
$secondary: $gray-light;
$input-disabled-bg: $gray-light;
-$input-border-color: $theme-gray-200;
+$input-border-color: $gray-200;
$input-color: $gl-text-color;
$font-family-sans-serif: $regular-font;
$font-family-monospace: $monospace-font;
@@ -20,7 +20,7 @@ $warning: $orange-500;
$danger: $red-500;
$zindex-modal-backdrop: 1040;
$nav-divider-margin-y: ($grid-size / 2);
-$dropdown-divider-bg: $theme-gray-200;
+$dropdown-divider-bg: $gray-200;
$dropdown-item-padding-y: 8px;
$dropdown-item-padding-x: 12px;
$popover-max-width: 300px;
@@ -34,3 +34,14 @@ $h3-font-size: 14px * 1.75;
$h4-font-size: 14px * 1.5;
$h5-font-size: 14px * 1.25;
$h6-font-size: 14px;
+$spacer: $grid-size;
+$spacers: (
+ 0: 0,
+ 1: ($spacer * 0.5),
+ 2: ($spacer),
+ 3: ($spacer * 2),
+ 4: ($spacer * 3),
+ 5: ($spacer * 4),
+ 6: ($spacer * 8)
+);
+$pagination-color: $gl-text-color;
diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss
new file mode 100644
index 00000000000..ac3214a07d9
--- /dev/null
+++ b/app/assets/stylesheets/highlight/common.scss
@@ -0,0 +1,18 @@
+@import '../framework/variables';
+
+@mixin diff-background($background, $idiff, $border) {
+ background: $background;
+
+ &.line_content span.idiff {
+ background: $idiff;
+ }
+
+ &.diff-line-num {
+ border-color: $border;
+ }
+}
+
+@mixin dark-diff-match-line {
+ color: $dark-diff-match-bg;
+ background: $dark-diff-match-color;
+}
diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss
deleted file mode 100644
index 604f806dc58..00000000000
--- a/app/assets/stylesheets/highlight/dark.scss
+++ /dev/null
@@ -1,259 +0,0 @@
-/* https://github.com/MozMorris/tomorrow-pygments */
-
-/*
-* Dark syntax colors
-*/
-$dark-new-bg: rgba(51, 255, 51, 0.1);
-$dark-new-idiff: rgba(51, 255, 51, 0.2);
-$dark-old-bg: rgba(255, 51, 51, 0.2);
-$dark-old-idiff: rgba(255, 51, 51, 0.25);
-$dark-border: #808080;
-$dark-code-border: #666;
-$dark-main-bg: #1d1f21;
-$dark-main-color: #1d1f21;
-$dark-line-color: #c5c8c6;
-$dark-line-num-color: rgba(255, 255, 255, 0.3);
-$dark-line-num-color-new: #627165;
-$dark-line-num-color-old: #806565;
-$dark-diff-not-empty-bg: #557;
-$dark-highlight-bg: #ffe792;
-$dark-highlight-color: $black;
-$dark-pre-hll-bg: #373b41;
-$dark-hll-bg: #373b41;
-$dark-over-bg: #9f9ab5;
-$dark-expanded-bg: #3e3e3e;
-$dark-c: #969896;
-$dark-err: #c66;
-$dark-k: #b294bb;
-$dark-l: #de935f;
-$dark-n: #c5c8c6;
-$dark-o: #8abeb7;
-$dark-p: #c5c8c6;
-$dark-cm: #969896;
-$dark-cp: #969896;
-$dark-c1: #969896;
-$dark-cs: #969896;
-$dark-gd: #c66;
-$dark-gh: #c5c8c6;
-$dark-gi: #b5bd68;
-$dark-gp: #969896;
-$dark-gu: #8abeb7;
-$dark-kc: #b294bb;
-$dark-kd: #b294bb;
-$dark-kn: #8abeb7;
-$dark-kp: #b294bb;
-$dark-kr: #b294bb;
-$dark-kt: #f0c674;
-$dark-ld: #b5bd68;
-$dark-m: #de935f;
-$dark-s: #b5bd68;
-$dark-na: #81a2be;
-$dark-nb: #c5c8c6;
-$dark-nc: #f0c674;
-$dark-no: #c66;
-$dark-nd: #8abeb7;
-$dark-ni: #c5c8c6;
-$dark-ne: #c66;
-$dark-nf: #81a2be;
-$dark-nl: #c5c8c6;
-$dark-nn: #f0c674;
-$dark-nx: #81a2be;
-$dark-py: #c5c8c6;
-$dark-nt: #8abeb7;
-$dark-nv: #c66;
-$dark-ow: #8abeb7;
-$dark-w: #c5c8c6;
-$dark-mf: #de935f;
-$dark-mh: #de935f;
-$dark-mi: #de935f;
-$dark-mo: #de935f;
-$dark-sb: #b5bd68;
-$dark-sc: #c5c8c6;
-$dark-sd: #969896;
-$dark-s2: #b5bd68;
-$dark-se: #de935f;
-$dark-sh: #b5bd68;
-$dark-si: #de935f;
-$dark-sx: #b5bd68;
-$dark-sr: #b5bd68;
-$dark-s1: #b5bd68;
-$dark-ss: #b5bd68;
-$dark-bp: #c5c8c6;
-$dark-vc: #c66;
-$dark-vg: #c66;
-$dark-vi: #c66;
-$dark-il: #de935f;
-
-.code.dark {
- // Line numbers
- .line-numbers,
- .diff-line-num {
- background-color: $dark-main-bg;
- }
-
- .diff-line-num,
- .diff-line-num a {
- color: $dark-line-num-color;
- }
-
- // Code itself
- pre.code,
- .diff-line-num {
- border-color: $dark-code-border;
- }
-
- &,
- pre.code,
- .line_holder .line_content {
- background-color: $dark-main-bg;
- color: $dark-line-color;
- }
-
- // Diff line
- .line_holder {
- &.match .line_content,
- &.old-nonewline .line_content,
- &.new-nonewline .line_content {
- @include dark-diff-match-line;
- }
-
- td.diff-line-num.hll:not(.empty-cell),
- td.line_content.hll:not(.empty-cell) {
- background-color: $dark-diff-not-empty-bg;
- border-color: darken($dark-diff-not-empty-bg, 15%);
- }
-
- .diff-line-num.new,
- .line_content.new {
- @include diff_background($dark-new-bg, $dark-new-idiff, $dark-border);
-
- &::before,
- a {
- color: $dark-line-num-color-new;
- }
- }
-
- .diff-line-num.old,
- .line_content.old {
- @include diff_background($dark-old-bg, $dark-old-idiff, $dark-border);
-
- &::before,
- a {
- color: $dark-line-num-color-old;
- }
- }
-
- .diff-line-num {
- &.is-over,
- &.hll:not(.empty-cell).is-over {
- background-color: $dark-over-bg;
- border-color: darken($dark-over-bg, 5%);
-
- a {
- color: darken($dark-over-bg, 15%);
- }
- }
- }
-
- .line_content.match {
- @include dark-diff-match-line;
- }
-
- &:not(.diff-expanded) + .diff-expanded,
- &.diff-expanded + .line_holder:not(.diff-expanded) {
- > .diff-line-num,
- > .line_content {
- border-top: 1px solid $black;
- }
- }
-
- &.diff-expanded {
- > .diff-line-num,
- > .line_content {
- background: $dark-expanded-bg;
- border-color: $dark-expanded-bg;
- }
- }
- }
-
- // highlight line via anchor
- pre .hll {
- background-color: $dark-pre-hll-bg !important;
- }
-
- // Search result highlight
- span.highlight_word {
- background-color: $dark-highlight-bg !important;
- color: $dark-highlight-color !important;
- }
-
- // Links to URLs, emails, or dependencies
- .line a {
- color: $dark-na;
- }
-
- .hll { background-color: $dark-hll-bg; }
- .c { color: $dark-c; } /* Comment */
- .err { color: $dark-err; } /* Error */
- .k { color: $dark-k; } /* Keyword */
- .l { color: $dark-l; } /* Literal */
- .n { color: $dark-n; } /* Name */
- .o { color: $dark-o; } /* Operator */
- .p { color: $dark-p; } /* Punctuation */
- .cm { color: $dark-cm; } /* Comment.Multiline */
- .cp { color: $dark-cp; } /* Comment.Preproc */
- .c1 { color: $dark-c1; } /* Comment.Single */
- .cs { color: $dark-cs; } /* Comment.Special */
- .gd { color: $dark-gd; } /* Generic.Deleted */
- .ge { font-style: italic; } /* Generic.Emph */
- .gh { color: $dark-gh; font-weight: $gl-font-weight-bold; } /* Generic.Heading */
- .gi { color: $dark-gi; } /* Generic.Inserted */
- .gp { color: $dark-gp; font-weight: $gl-font-weight-bold; } /* Generic.Prompt */
- .gs { font-weight: $gl-font-weight-bold; } /* Generic.Strong */
- .gu { color: $dark-gu; font-weight: $gl-font-weight-bold; } /* Generic.Subheading */
- .kc { color: $dark-kc; } /* Keyword.Constant */
- .kd { color: $dark-kd; } /* Keyword.Declaration */
- .kn { color: $dark-kn; } /* Keyword.Namespace */
- .kp { color: $dark-kp; } /* Keyword.Pseudo */
- .kr { color: $dark-kr; } /* Keyword.Reserved */
- .kt { color: $dark-kt; } /* Keyword.Type */
- .ld { color: $dark-ld; } /* Literal.Date */
- .m { color: $dark-m; } /* Literal.Number */
- .s { color: $dark-s; } /* Literal.String */
- .na { color: $dark-na; } /* Name.Attribute */
- .nb { color: $dark-nb; } /* Name.Builtin */
- .nc { color: $dark-nc; } /* Name.Class */
- .no { color: $dark-no; } /* Name.Constant */
- .nd { color: $dark-nd; } /* Name.Decorator */
- .ni { color: $dark-ni; } /* Name.Entity */
- .ne { color: $dark-ne; } /* Name.Exception */
- .nf { color: $dark-nf; } /* Name.Function */
- .nl { color: $dark-nl; } /* Name.Label */
- .nn { color: $dark-nn; } /* Name.Namespace */
- .nx { color: $dark-nx; } /* Name.Other */
- .py { color: $dark-py; } /* Name.Property */
- .nt { color: $dark-nt; } /* Name.Tag */
- .nv { color: $dark-nv; } /* Name.Variable */
- .ow { color: $dark-ow; } /* Operator.Word */
- .w { color: $dark-w; } /* Text.Whitespace */
- .mf { color: $dark-mf; } /* Literal.Number.Float */
- .mh { color: $dark-mh; } /* Literal.Number.Hex */
- .mi { color: $dark-mi; } /* Literal.Number.Integer */
- .mo { color: $dark-mo; } /* Literal.Number.Oct */
- .sb { color: $dark-sb; } /* Literal.String.Backtick */
- .sc { color: $dark-sc; } /* Literal.String.Char */
- .sd { color: $dark-sd; } /* Literal.String.Doc */
- .s2 { color: $dark-s2; } /* Literal.String.Double */
- .se { color: $dark-se; } /* Literal.String.Escape */
- .sh { color: $dark-sh; } /* Literal.String.Heredoc */
- .si { color: $dark-si; } /* Literal.String.Interpol */
- .sx { color: $dark-sx; } /* Literal.String.Other */
- .sr { color: $dark-sr; } /* Literal.String.Regex */
- .s1 { color: $dark-s1; } /* Literal.String.Single */
- .ss { color: $dark-ss; } /* Literal.String.Symbol */
- .bp { color: $dark-bp; } /* Name.Builtin.Pseudo */
- .vc { color: $dark-vc; } /* Name.Variable.Class */
- .vg { color: $dark-vg; } /* Name.Variable.Global */
- .vi { color: $dark-vi; } /* Name.Variable.Instance */
- .il { color: $dark-il; } /* Literal.Number.Integer.Long */
-}
diff --git a/app/assets/stylesheets/highlight/embedded.scss b/app/assets/stylesheets/highlight/embedded.scss
index 44c8a1d39ec..74364ee4ddb 100644
--- a/app/assets/stylesheets/highlight/embedded.scss
+++ b/app/assets/stylesheets/highlight/embedded.scss
@@ -1,3 +1,3 @@
.code {
- @import "white_base";
+ @import 'white_base';
}
diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss
deleted file mode 100644
index 8e2720511da..00000000000
--- a/app/assets/stylesheets/highlight/monokai.scss
+++ /dev/null
@@ -1,257 +0,0 @@
-/* https://github.com/richleland/pygments-css/blob/master/monokai.css */
-
-/*
-* Monokai Colors
-*/
-$monokai-bg: #272822;
-$monokai-border: #555;
-$monokai-text-color: #f8f8f2;
-$monokai-line-num-color: rgba(255, 255, 255, 0.3);
-$monokai-line-num-color-new: #707565;
-$monokai-line-num-color-old: #7e736f;
-$monokai-line-empty-bg: #49483e;
-$monokai-line-empty-border: darken($monokai-line-empty-bg, 15%);
-$monokai-diff-border: #808080;
-$monokai-highlight-bg: #ffe792;
-$monokai-over-bg: #9f9ab5;
-$monokai-expanded-bg: #3e3e3e;
-
-$monokai-new-bg: rgba(166, 226, 46, 0.1);
-$monokai-new-idiff: rgba(166, 226, 46, 0.15);
-
-$monokai-old-bg: rgba(254, 147, 140, 0.15);
-$monokai-old-idiff: rgba(254, 147, 140, 0.2);
-
-$monokai-hll: #49483e;
-$monokai-c: #75715e;
-$monokai-err-color: #960050;
-$monokai-err-bg: #1e0010;
-$monokai-k: #66d9ef;
-$monokai-l: #ae81ff;
-$monokai-n: #f8f8f2;
-$monokai-o: #f92672;
-$monokai-p: #f8f8f2;
-$monokai-cm: #75715e;
-$monokai-cp: #75715e;
-$monokai-c1: #75715e;
-$monokai-cs: #75715e;
-$monokai-kc: #66d9ef;
-$monokai-kd: #66d9ef;
-$monokai-kn: #f92672;
-$monokai-kp: #66d9ef;
-$monokai-kr: #66d9ef;
-$monokai-kt: #66d9ef;
-$monokai-ld: #e6db74;
-$monokai-m: #ae81ff;
-$monokai-s: #e6db74;
-$monokai-na: #a6e22e;
-$monokai-nb: #f8f8f2;
-$monokai-nc: #a6e22e;
-$monokai-no: #66d9ef;
-$monokai-nd: #a6e22e;
-$monokai-ni: #f8f8f2;
-$monokai-ne: #a6e22e;
-$monokai-nf: #a6e22e;
-$monokai-nl: #f8f8f2;
-$monokai-nn: #f8f8f2;
-$monokai-nx: #a6e22e;
-$monokai-py: #f8f8f2;
-$monokai-nt: #f92672;
-$monokai-nv: #f8f8f2;
-$monokai-ow: #f92672;
-$monokai-w: #f8f8f2;
-$monokai-mf: #ae81ff;
-$monokai-mh: #ae81ff;
-$monokai-mi: #ae81ff;
-$monokai-mo: #ae81ff;
-$monokai-sb: #e6db74;
-$monokai-sc: #e6db74;
-$monokai-sd: #e6db74;
-$monokai-s2: #e6db74;
-$monokai-se: #ae81ff;
-$monokai-sh: #e6db74;
-$monokai-si: #e6db74;
-$monokai-sx: #e6db74;
-$monokai-sr: #e6db74;
-$monokai-s1: #e6db74;
-$monokai-ss: #e6db74;
-$monokai-bp: #f8f8f2;
-$monokai-vc: #f8f8f2;
-$monokai-vg: #f8f8f2;
-$monokai-vi: #f8f8f2;
-$monokai-il: #ae81ff;
-$monokai-gu: #75715e;
-$monokai-gd: #f92672;
-$monokai-gi: #a6e22e;
-
-.code.monokai {
- // Line numbers
- .line-numbers,
- .diff-line-num {
- background-color: $monokai-bg;
- }
-
- .diff-line-num,
- .diff-line-num a {
- color: $monokai-line-num-color;
- }
-
- // Code itself
- pre.code,
- .diff-line-num {
- border-color: $monokai-border;
- }
-
- &,
- pre.code,
- .line_holder .line_content {
- background-color: $monokai-bg;
- color: $monokai-text-color;
- }
-
- // Diff line
- .line_holder {
- &.match .line_content,
- &.old-nonewline .line_content,
- &.new-nonewline .line_content {
- @include dark-diff-match-line;
- }
-
- td.diff-line-num.hll:not(.empty-cell),
- td.line_content.hll:not(.empty-cell) {
- background-color: $monokai-line-empty-bg;
- border-color: $monokai-line-empty-border;
- }
-
- .diff-line-num.new,
- .line_content.new {
- @include diff_background($monokai-new-bg, $monokai-new-idiff, $monokai-diff-border);
-
- &::before,
- a {
- color: $monokai-line-num-color-new;
- }
- }
-
- .diff-line-num.old,
- .line_content.old {
- @include diff_background($monokai-old-bg, $monokai-old-idiff, $monokai-diff-border);
-
- &::before,
- a {
- color: $monokai-line-num-color-old;
- }
- }
-
- .diff-line-num {
- &.is-over,
- &.hll:not(.empty-cell).is-over {
- background-color: $monokai-over-bg;
- border-color: darken($monokai-over-bg, 5%);
-
- a {
- color: darken($monokai-over-bg, 15%);
- }
- }
- }
-
- .line_content.match {
- @include dark-diff-match-line;
- }
-
- &:not(.diff-expanded) + .diff-expanded,
- &.diff-expanded + .line_holder:not(.diff-expanded) {
- > .diff-line-num,
- > .line_content {
- border-top: 1px solid $black;
- }
- }
-
- &.diff-expanded {
- > .diff-line-num,
- > .line_content {
- background: $monokai-expanded-bg;
- border-color: $monokai-expanded-bg;
- }
- }
- }
-
- // highlight line via anchor
- pre .hll {
- background-color: $monokai-hll !important;
- }
-
- // Search result highlight
- span.highlight_word {
- background-color: $monokai-highlight-bg !important;
- color: $black !important;
- }
-
- // Links to URLs, emails, or dependencies
- .line a {
- color: $monokai-k;
- }
-
- .hll { background-color: $monokai-hll; }
- .c { color: $monokai-c; } /* Comment */
- .err { color: $monokai-err-color; background-color: $monokai-err-bg; } /* Error */
- .k { color: $monokai-k; } /* Keyword */
- .l { color: $monokai-l; } /* Literal */
- .n { color: $monokai-n; } /* Name */
- .o { color: $monokai-o; } /* Operator */
- .p { color: $monokai-p; } /* Punctuation */
- .cm { color: $monokai-cm; } /* Comment.Multiline */
- .cp { color: $monokai-cp; } /* Comment.Preproc */
- .c1 { color: $monokai-c1; } /* Comment.Single */
- .cs { color: $monokai-cs; } /* Comment.Special */
- .ge { font-style: italic; } /* Generic.Emph */
- .gs { font-weight: $gl-font-weight-bold; } /* Generic.Strong */
- .kc { color: $monokai-kc; } /* Keyword.Constant */
- .kd { color: $monokai-kd; } /* Keyword.Declaration */
- .kn { color: $monokai-kn; } /* Keyword.Namespace */
- .kp { color: $monokai-kp; } /* Keyword.Pseudo */
- .kr { color: $monokai-kr; } /* Keyword.Reserved */
- .kt { color: $monokai-kt; } /* Keyword.Type */
- .ld { color: $monokai-ld; } /* Literal.Date */
- .m { color: $monokai-m; } /* Literal.Number */
- .s { color: $monokai-s; } /* Literal.String */
- .na { color: $monokai-na; } /* Name.Attribute */
- .nb { color: $monokai-nb; } /* Name.Builtin */
- .nc { color: $monokai-nc; } /* Name.Class */
- .no { color: $monokai-no; } /* Name.Constant */
- .nd { color: $monokai-nd; } /* Name.Decorator */
- .ni { color: $monokai-ni; } /* Name.Entity */
- .ne { color: $monokai-ne; } /* Name.Exception */
- .nf { color: $monokai-nf; } /* Name.Function */
- .nl { color: $monokai-nl; } /* Name.Label */
- .nn { color: $monokai-nn; } /* Name.Namespace */
- .nx { color: $monokai-nx; } /* Name.Other */
- .py { color: $monokai-py; } /* Name.Property */
- .nt { color: $monokai-nt; } /* Name.Tag */
- .nv { color: $monokai-nv; } /* Name.Variable */
- .ow { color: $monokai-ow; } /* Operator.Word */
- .w { color: $monokai-w; } /* Text.Whitespace */
- .mf { color: $monokai-mf; } /* Literal.Number.Float */
- .mh { color: $monokai-mh; } /* Literal.Number.Hex */
- .mi { color: $monokai-mi; } /* Literal.Number.Integer */
- .mo { color: $monokai-mo; } /* Literal.Number.Oct */
- .sb { color: $monokai-sb; } /* Literal.String.Backtick */
- .sc { color: $monokai-sc; } /* Literal.String.Char */
- .sd { color: $monokai-sd; } /* Literal.String.Doc */
- .s2 { color: $monokai-s2; } /* Literal.String.Double */
- .se { color: $monokai-se; } /* Literal.String.Escape */
- .sh { color: $monokai-sh; } /* Literal.String.Heredoc */
- .si { color: $monokai-si; } /* Literal.String.Interpol */
- .sx { color: $monokai-sx; } /* Literal.String.Other */
- .sr { color: $monokai-sr; } /* Literal.String.Regex */
- .s1 { color: $monokai-s1; } /* Literal.String.Single */
- .ss { color: $monokai-ss; } /* Literal.String.Symbol */
- .bp { color: $monokai-bp; } /* Name.Builtin.Pseudo */
- .vc { color: $monokai-vc; } /* Name.Variable.Class */
- .vg { color: $monokai-vg; } /* Name.Variable.Global */
- .vi { color: $monokai-vi; } /* Name.Variable.Instance */
- .il { color: $monokai-il; } /* Literal.Number.Integer.Long */
- .gu { color: $monokai-gu; } /* Generic.Subheading & Diff Unified/Comment? */
- .gd { color: $monokai-gd; } /* Generic.Deleted & Diff Deleted */
- .gi { color: $monokai-gi; } /* Generic.Inserted & Diff Inserted */
-}
diff --git a/app/assets/stylesheets/highlight/none.scss b/app/assets/stylesheets/highlight/none.scss
deleted file mode 100644
index 7d692a87e33..00000000000
--- a/app/assets/stylesheets/highlight/none.scss
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
-* None Syntax Colors
-*/
-
-
-
-@mixin matchLine {
- color: $black-transparent;
- background-color: $white-normal;
-}
-
-.code.none {
- // Line numbers
- .line-numbers,
- .diff-line-num {
- background-color: $gray-light;
- }
-
- .diff-line-num,
- .diff-line-num a {
- color: $black-transparent;
- }
-
- // Code itself
- pre.code,
- .diff-line-num {
- border-color: $white-normal;
- }
-
- &,
- pre.code,
- .line_holder .line_content {
- background-color: $white-light;
- color: $gl-text-color;
- }
-
-// Diff line
-
- $none-over-bg: #ded7fc;
- $none-expanded-border: #e0e0e0;
- $none-expanded-bg: #f7f7f7;
-
- .line_holder {
-
- &.match .line_content,
- .new-nonewline.line_content,
- .old-nonewline.line_content {
- @include matchLine;
- }
-
- .diff-line-num {
- &.old {
- background-color: $line-number-old;
- border-color: $line-removed-dark;
-
- a {
- color: scale-color($line-number-old, $red: -30%, $green: -30%, $blue: -30%);
- }
- }
-
- &.new {
- background-color: $line-number-new;
- border-color: $line-added-dark;
-
- a {
- color: scale-color($line-number-new, $red: -30%, $green: -30%, $blue: -30%);
- }
- }
-
- &.is-over,
- &.hll:not(.empty-cell).is-over {
- background-color: $none-over-bg;
- border-color: darken($none-over-bg, 5%);
-
- a {
- color: darken($none-over-bg, 15%);
- }
- }
-
- &.hll:not(.empty-cell) {
- background-color: $line-number-select;
- border-color: $line-select-yellow-dark;
- }
- }
-
- &:not(.diff-expanded) + .diff-expanded,
- &.diff-expanded + .line_holder:not(.diff-expanded) {
- > .diff-line-num,
- > .line_content {
- border-top: 1px solid $none-expanded-border;
- }
- }
-
- &.diff-expanded {
- > .diff-line-num,
- > .line_content {
- background: $none-expanded-bg;
- border-color: $none-expanded-bg;
- }
- }
-
- .line_content {
- &.old {
- background-color: $line-removed;
-
- &::before {
- color: scale-color($line-number-old, $red: -30%, $green: -30%, $blue: -30%);
- }
-
- span.idiff {
- background-color: $line-removed-dark;
- }
- }
-
- &.new {
- background-color: $line-added;
-
- &::before {
- color: scale-color($line-number-new, $red: -30%, $green: -30%, $blue: -30%);
- }
-
- span.idiff {
- background-color: $line-added-dark;
- }
- }
-
- &.match {
- @include matchLine;
- }
-
- &.hll:not(.empty-cell) {
- background-color: $line-select-yellow;
- }
- }
- }
-
- // highlight line via anchor
- pre .hll {
- background-color: $white-normal;
- }
-
- // Search result highlight
- span.highlight_word {
- background-color: $white-normal;
- }
-
- // Links to URLs, emails, or dependencies
- .line a {
- color: $gl-text-color;
- text-decoration: underline;
- }
-
- .hll { background-color: $white-light; }
-
- .gd {
- color: $gl-text-color;
- background-color: $white-light;
-
- .x {
- color: $gl-text-color;
- background-color: $white-light;
- }
- }
-
- .gi {
- color: $gl-text-color;
- background-color: $white-light;
-
- .x {
- color: $gl-text-color;
- background-color: $white-light;
- }
- }
-
- .c { color: $gl-text-color; } /* Comment */
- .err { color: $gl-text-color; } /* Error */
- .g { color: $gl-text-color; } /* Generic */
- .k { color: $gl-text-color; } /* Keyword */
- .l { color: $gl-text-color; } /* Literal */
- .n { color: $gl-text-color; } /* Name */
- .o { color: $gl-text-color; } /* Operator */
- .x { color: $gl-text-color; } /* Other */
- .p { color: $gl-text-color; } /* Punctuation */
- .cm { color: $gl-text-color; } /* Comment.Multiline */
- .cp { color: $gl-text-color; } /* Comment.Preproc */
- .c1 { color: $gl-text-color; } /* Comment.Single */
- .cs { color: $gl-text-color; } /* Comment.Special */
- .ge { color: $gl-text-color; } /* Generic.Emph */
- .gr { color: $gl-text-color; } /* Generic.Error */
- .gh { color: $gl-text-color; } /* Generic.Heading */
- .go { color: $gl-text-color; } /* Generic.Output */
- .gp { color: $gl-text-color; } /* Generic.Prompt */
- .gs { color: $gl-text-color; } /* Generic.Strong */
- .gu { color: $gl-text-color; } /* Generic.Subheading */
- .gt { color: $gl-text-color; } /* Generic.Traceback */
- .kc { color: $gl-text-color; } /* Keyword.Constant */
- .kd { color: $gl-text-color; } /* Keyword.Declaration */
- .kn { color: $gl-text-color; } /* Keyword.Namespace */
- .kp { color: $gl-text-color; } /* Keyword.Pseudo */
- .kr { color: $gl-text-color; } /* Keyword.Reserved */
- .kt { color: $gl-text-color; } /* Keyword.Type */
- .ld { color: $gl-text-color; } /* Literal.Date */
- .m { color: $gl-text-color; } /* Literal.Number */
- .s { color: $gl-text-color; } /* Literal.String */
- .na { color: $gl-text-color; } /* Name.Attribute */
- .nb { color: $gl-text-color; } /* Name.Builtin */
- .nc { color: $gl-text-color; } /* Name.Class */
- .no { color: $gl-text-color; } /* Name.Constant */
- .nd { color: $gl-text-color; } /* Name.Decorator */
- .ni { color: $gl-text-color; } /* Name.Entity */
- .ne { color: $gl-text-color; } /* Name.Exception */
- .nf { color: $gl-text-color; } /* Name.Function */
- .nl { color: $gl-text-color; } /* Name.Label */
- .nn { color: $gl-text-color; } /* Name.Namespace */
- .nx { color: $gl-text-color; } /* Name.Other */
- .py { color: $gl-text-color; } /* Name.Property */
- .nt { color: $gl-text-color; } /* Name.Tag */
- .nv { color: $gl-text-color; } /* Name.Variable */
- .ow { color: $gl-text-color; } /* Operator.Word */
- .w { color: $gl-text-color; } /* Text.Whitespace */
- .mf { color: $gl-text-color; } /* Literal.Number.Float */
- .mh { color: $gl-text-color; } /* Literal.Number.Hex */
- .mi { color: $gl-text-color; } /* Literal.Number.Integer */
- .mo { color: $gl-text-color; } /* Literal.Number.Oct */
- .sb { color: $gl-text-color; } /* Literal.String.Backtick */
- .sc { color: $gl-text-color; } /* Literal.String.Char */
- .sd { color: $gl-text-color; } /* Literal.String.Doc */
- .s2 { color: $gl-text-color; } /* Literal.String.Double */
- .se { color: $gl-text-color; } /* Literal.String.Escape */
- .sh { color: $gl-text-color; } /* Literal.String.Heredoc */
- .si { color: $gl-text-color; } /* Literal.String.Interpol */
- .sx { color: $gl-text-color; } /* Literal.String.Other */
- .sr { color: $gl-text-color; } /* Literal.String.Regex */
- .s1 { color: $gl-text-color; } /* Literal.String.Single */
- .ss { color: $gl-text-color; } /* Literal.String.Symbol */
- .bp { color: $gl-text-color; } /* Name.Builtin.Pseudo */
- .vc { color: $gl-text-color; } /* Name.Variable.Class */
- .vg { color: $gl-text-color; } /* Name.Variable.Global */
- .vi { color: $gl-text-color; } /* Name.Variable.Instance */
- .il { color: $gl-text-color; } /* Literal.Number.Integer.Long */
-
-}
diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss
deleted file mode 100644
index cd1f0f6650f..00000000000
--- a/app/assets/stylesheets/highlight/solarized_dark.scss
+++ /dev/null
@@ -1,284 +0,0 @@
-/* https://gist.github.com/qguv/7936275 */
-
-/*
-* Solarized dark colors
-*/
-$solarized-dark-new-bg: rgba(133, 153, 0, 0.15);
-$solarized-dark-new-idiff: rgba(133, 153, 0, 0.25);
-$solarized-dark-old-bg: rgba(220, 50, 47, 0.3);
-$solarized-dark-old-idiff: rgba(220, 50, 47, 0.25);
-$solarized-dark-border: #113b46;
-$solarized-dark-pre-bg: #002b36;
-$solarized-dark-pre-color: #93a1a1;
-$solarized-dark-pre-border: #113b46;
-$solarized-dark-line-bg: #002b36;
-$solarized-dark-line-color: rgba(255, 255, 255, 0.3);
-$solarized-dark-line-color-new: #5a766c;
-$solarized-dark-line-color-old: #7a6c71;
-$solarized-dark-highlight: #094554;
-$solarized-dark-hll-bg: #174652;
-$solarized-dark-over-bg: #9f9ab5;
-$solarized-dark-expanded-bg: #010d10;
-$solarized-dark-c: #586e75;
-$solarized-dark-err: #93a1a1;
-$solarized-dark-g: #93a1a1;
-$solarized-dark-k: #859900;
-$solarized-dark-l: #93a1a1;
-$solarized-dark-n: #93a1a1;
-$solarized-dark-o: #859900;
-$solarized-dark-x: #cb4b16;
-$solarized-dark-p: #93a1a1;
-$solarized-dark-cm: #586e75;
-$solarized-dark-cp: #859900;
-$solarized-dark-c1: #586e75;
-$solarized-dark-cs: #859900;
-$solarized-dark-gd: #2aa198;
-$solarized-dark-ge: #93a1a1;
-$solarized-dark-gr: #dc322f;
-$solarized-dark-gh: #cb4b16;
-$solarized-dark-gi: #859900;
-$solarized-dark-go: #93a1a1;
-$solarized-dark-gp: #93a1a1;
-$solarized-dark-gs: #93a1a1;
-$solarized-dark-gu: #cb4b16;
-$solarized-dark-gt: #93a1a1;
-$solarized-dark-kc: #cb4b16;
-$solarized-dark-kd: #268bd2;
-$solarized-dark-kn: #859900;
-$solarized-dark-kp: #859900;
-$solarized-dark-kr: #268bd2;
-$solarized-dark-kt: #dc322f;
-$solarized-dark-ld: #93a1a1;
-$solarized-dark-m: #2aa198;
-$solarized-dark-s: #2aa198;
-$solarized-dark-na: #93a1a1;
-$solarized-dark-nb: #b58900;
-$solarized-dark-nc: #268bd2;
-$solarized-dark-no: #cb4b16;
-$solarized-dark-nd: #268bd2;
-$solarized-dark-ni: #cb4b16;
-$solarized-dark-ne: #cb4b16;
-$solarized-dark-nf: #268bd2;
-$solarized-dark-nl: #93a1a1;
-$solarized-dark-nn: #93a1a1;
-$solarized-dark-nx: #93a1a1;
-$solarized-dark-py: #93a1a1;
-$solarized-dark-nt: #268bd2;
-$solarized-dark-nv: #268bd2;
-$solarized-dark-ow: #859900;
-$solarized-dark-w: #93a1a1;
-$solarized-dark-mf: #2aa198;
-$solarized-dark-mh: #2aa198;
-$solarized-dark-mi: #2aa198;
-$solarized-dark-mo: #2aa198;
-$solarized-dark-sb: #586e75;
-$solarized-dark-sc: #2aa198;
-$solarized-dark-sd: #93a1a1;
-$solarized-dark-s2: #2aa198;
-$solarized-dark-se: #cb4b16;
-$solarized-dark-sh: #93a1a1;
-$solarized-dark-si: #2aa198;
-$solarized-dark-sx: #2aa198;
-$solarized-dark-sr: #dc322f;
-$solarized-dark-s1: #2aa198;
-$solarized-dark-ss: #2aa198;
-$solarized-dark-bp: #268bd2;
-$solarized-dark-vc: #268bd2;
-$solarized-dark-vg: #268bd2;
-$solarized-dark-vi: #268bd2;
-$solarized-dark-il: #2aa198;
-
-.code.solarized-dark {
- // Line numbers
- .line-numbers,
- .diff-line-num {
- background-color: $solarized-dark-line-bg;
- }
-
- .diff-line-num,
- .diff-line-num a {
- color: $solarized-dark-line-color;
- }
-
- // Code itself
- pre.code,
- .diff-line-num {
- border-color: $solarized-dark-pre-border;
- }
-
- &,
- pre.code,
- .line_holder .line_content {
- background-color: $solarized-dark-pre-bg;
- color: $solarized-dark-pre-color;
- }
-
- // Diff line
- .line_holder {
- &.match .line_content,
- &.old-nonewline .line_content,
- &.new-nonewline .line_content {
- @include dark-diff-match-line;
- }
-
- td.diff-line-num.hll:not(.empty-cell),
- td.line_content.hll:not(.empty-cell) {
- background-color: $solarized-dark-hll-bg;
- border-color: darken($solarized-dark-hll-bg, 15%);
- }
-
- .diff-line-num.new,
- .line_content.new {
- @include diff_background($solarized-dark-new-bg, $solarized-dark-new-idiff, $solarized-dark-border);
-
- &::before,
- a {
- color: $solarized-dark-line-color-new;
- }
- }
-
- .diff-line-num.old,
- .line_content.old {
- @include diff_background($solarized-dark-old-bg, $solarized-dark-old-idiff, $solarized-dark-border);
-
- &::before,
- a {
- color: $solarized-dark-line-color-old;
- }
- }
-
- .diff-line-num {
- &.is-over,
- &.hll:not(.empty-cell).is-over {
- background-color: $solarized-dark-over-bg;
- border-color: darken($solarized-dark-over-bg, 5%);
-
- a {
- color: darken($solarized-dark-over-bg, 15%);
- }
- }
- }
-
- .line_content.match {
- @include dark-diff-match-line;
- }
-
- &:not(.diff-expanded) + .diff-expanded,
- &.diff-expanded + .line_holder:not(.diff-expanded) {
- > .diff-line-num,
- > .line_content {
- border-top: 1px solid $black;
- }
- }
-
- &.diff-expanded {
- > .diff-line-num,
- > .line_content {
- background: $solarized-dark-expanded-bg;
- border-color: $solarized-dark-expanded-bg;
- }
- }
- }
-
- // highlight line via anchor
- pre .hll {
- background-color: $solarized-dark-hll-bg !important;
- }
-
- // Search result highlight
- span.highlight_word {
- background-color: $solarized-dark-highlight !important;
- }
-
- // Links to URLs, emails, or dependencies
- .line a {
- color: $solarized-dark-kd;
- }
-
- /* Solarized Dark
-
- For use with Jekyll and Pygments
-
- http://ethanschoonover.com/solarized
-
- SOLARIZED HEX ROLE
- --------- -------- ------------------------------------------
- base03 #002b36 background
- base01 #586e75 comments / secondary content
- base1 #93a1a1 body text / default code / primary content
- orange #cb4b16 constants
- red #dc322f regex, special keywords
- blue #268bd2 reserved keywords
- cyan #2aa198 strings, numbers
- green #859900 operators, other keywords
- */
-
- .c { color: $solarized-dark-c; } /* Comment */
- .err { color: $solarized-dark-err; } /* Error */
- .g { color: $solarized-dark-g; } /* Generic */
- .k { color: $solarized-dark-k; } /* Keyword */
- .l { color: $solarized-dark-l; } /* Literal */
- .n { color: $solarized-dark-n; } /* Name */
- .o { color: $solarized-dark-o; } /* Operator */
- .x { color: $solarized-dark-x; } /* Other */
- .p { color: $solarized-dark-p; } /* Punctuation */
- .cm { color: $solarized-dark-cm; } /* Comment.Multiline */
- .cp { color: $solarized-dark-cp; } /* Comment.Preproc */
- .c1 { color: $solarized-dark-c1; } /* Comment.Single */
- .cs { color: $solarized-dark-cs; } /* Comment.Special */
- .gd { color: $solarized-dark-gd; } /* Generic.Deleted */
- .ge { color: $solarized-dark-ge; font-style: italic; } /* Generic.Emph */
- .gr { color: $solarized-dark-gr; } /* Generic.Error */
- .gh { color: $solarized-dark-gh; } /* Generic.Heading */
- .gi { color: $solarized-dark-gi; } /* Generic.Inserted */
- .go { color: $solarized-dark-go; } /* Generic.Output */
- .gp { color: $solarized-dark-gp; } /* Generic.Prompt */
- .gs { color: $solarized-dark-gs; font-weight: $gl-font-weight-bold; } /* Generic.Strong */
- .gu { color: $solarized-dark-gu; } /* Generic.Subheading */
- .gt { color: $solarized-dark-gt; } /* Generic.Traceback */
- .kc { color: $solarized-dark-kc; } /* Keyword.Constant */
- .kd { color: $solarized-dark-kd; } /* Keyword.Declaration */
- .kn { color: $solarized-dark-kn; } /* Keyword.Namespace */
- .kp { color: $solarized-dark-kp; } /* Keyword.Pseudo */
- .kr { color: $solarized-dark-kr; } /* Keyword.Reserved */
- .kt { color: $solarized-dark-kt; } /* Keyword.Type */
- .ld { color: $solarized-dark-ld; } /* Literal.Date */
- .m { color: $solarized-dark-m; } /* Literal.Number */
- .s { color: $solarized-dark-s; } /* Literal.String */
- .na { color: $solarized-dark-na; } /* Name.Attribute */
- .nb { color: $solarized-dark-nb; } /* Name.Builtin */
- .nc { color: $solarized-dark-nc; } /* Name.Class */
- .no { color: $solarized-dark-no; } /* Name.Constant */
- .nd { color: $solarized-dark-nd; } /* Name.Decorator */
- .ni { color: $solarized-dark-ni; } /* Name.Entity */
- .ne { color: $solarized-dark-ne; } /* Name.Exception */
- .nf { color: $solarized-dark-nf; } /* Name.Function */
- .nl { color: $solarized-dark-nl; } /* Name.Label */
- .nn { color: $solarized-dark-nn; } /* Name.Namespace */
- .nx { color: $solarized-dark-nx; } /* Name.Other */
- .py { color: $solarized-dark-py; } /* Name.Property */
- .nt { color: $solarized-dark-nt; } /* Name.Tag */
- .nv { color: $solarized-dark-nv; } /* Name.Variable */
- .ow { color: $solarized-dark-ow; } /* Operator.Word */
- .w { color: $solarized-dark-w; } /* Text.Whitespace */
- .mf { color: $solarized-dark-mf; } /* Literal.Number.Float */
- .mh { color: $solarized-dark-mh; } /* Literal.Number.Hex */
- .mi { color: $solarized-dark-mi; } /* Literal.Number.Integer */
- .mo { color: $solarized-dark-mo; } /* Literal.Number.Oct */
- .sb { color: $solarized-dark-sb; } /* Literal.String.Backtick */
- .sc { color: $solarized-dark-sc; } /* Literal.String.Char */
- .sd { color: $solarized-dark-sd; } /* Literal.String.Doc */
- .s2 { color: $solarized-dark-s2; } /* Literal.String.Double */
- .se { color: $solarized-dark-se; } /* Literal.String.Escape */
- .sh { color: $solarized-dark-sh; } /* Literal.String.Heredoc */
- .si { color: $solarized-dark-si; } /* Literal.String.Interpol */
- .sx { color: $solarized-dark-sx; } /* Literal.String.Other */
- .sr { color: $solarized-dark-sr; } /* Literal.String.Regex */
- .s1 { color: $solarized-dark-s1; } /* Literal.String.Single */
- .ss { color: $solarized-dark-ss; } /* Literal.String.Symbol */
- .bp { color: $solarized-dark-bp; } /* Name.Builtin.Pseudo */
- .vc { color: $solarized-dark-vc; } /* Name.Variable.Class */
- .vg { color: $solarized-dark-vg; } /* Name.Variable.Global */
- .vi { color: $solarized-dark-vi; } /* Name.Variable.Instance */
- .il { color: $solarized-dark-il; } /* Literal.Number.Integer.Long */
-}
diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss
deleted file mode 100644
index 09c3ea36414..00000000000
--- a/app/assets/stylesheets/highlight/solarized_light.scss
+++ /dev/null
@@ -1,292 +0,0 @@
-/* https://gist.github.com/qguv/7936275 */
-
-/*
-* Solarized light syntax colors
-*/
-$solarized-light-matchline-bg: rgba(255, 255, 255, 0.4);
-$solarized-light-new-bg: rgba(133, 153, 0, 0.2);
-$solarized-light-new-idiff: rgba(133, 153, 0, 0.25);
-$solarized-light-old-bg: rgba(220, 50, 47, 0.2);
-$solarized-light-old-idiff: rgba(220, 50, 47, 0.25);
-$solarized-light-border: #c5d0d4;
-$solarized-light-pre-bg: #002b36;
-$solarized-light-pre-bg: #fdf6e3;
-$solarized-light-pre-color: #586e75;
-$solarized-light-line-bg: #fdf6e3;
-$solarized-light-line-color: rgba(0, 0, 0, 0.3);
-$solarized-light-line-color-new: #a1a080;
-$solarized-light-line-color-old: #ad9186;
-$solarized-light-highlight: #eee8d5;
-$solarized-light-hll-bg: #ddd8c5;
-$solarized-light-over-bg: #ded7fc;
-$solarized-light-expanded-border: #d2cdbd;
-$solarized-light-expanded-bg: #ece6d4;
-$solarized-light-c: #93a1a1;
-$solarized-light-err: #586e75;
-$solarized-light-g: #586e75;
-$solarized-light-k: #859900;
-$solarized-light-l: #586e75;
-$solarized-light-n: #586e75;
-$solarized-light-o: #859900;
-$solarized-light-x: #cb4b16;
-$solarized-light-p: #586e75;
-$solarized-light-cm: #93a1a1;
-$solarized-light-cp: #859900;
-$solarized-light-c1: #93a1a1;
-$solarized-light-cs: #859900;
-$solarized-light-gd: #2aa198;
-$solarized-light-ge: #586e75;
-$solarized-light-gr: #dc322f;
-$solarized-light-gh: #cb4b16;
-$solarized-light-gi: #859900;
-$solarized-light-go: #586e75;
-$solarized-light-gp: #586e75;
-$solarized-light-gs: #586e75;
-$solarized-light-gu: #cb4b16;
-$solarized-light-gt: #586e75;
-$solarized-light-kc: #cb4b16;
-$solarized-light-kd: #268bd2;
-$solarized-light-kn: #859900;
-$solarized-light-kp: #859900;
-$solarized-light-kr: #268bd2;
-$solarized-light-kt: #dc322f;
-$solarized-light-ld: #586e75;
-$solarized-light-m: #2aa198;
-$solarized-light-s: #2aa198;
-$solarized-light-na: #586e75;
-$solarized-light-nb: #b58900;
-$solarized-light-nc: #268bd2;
-$solarized-light-no: #cb4b16;
-$solarized-light-nd: #268bd2;
-$solarized-light-ni: #cb4b16;
-$solarized-light-ne: #cb4b16;
-$solarized-light-nf: #268bd2;
-$solarized-light-nl: #586e75;
-$solarized-light-nn: #586e75;
-$solarized-light-nx: #586e75;
-$solarized-light-py: #586e75;
-$solarized-light-nt: #268bd2;
-$solarized-light-nv: #268bd2;
-$solarized-light-ow: #859900;
-$solarized-light-w: #586e75;
-$solarized-light-mf: #2aa198;
-$solarized-light-mh: #2aa198;
-$solarized-light-mi: #2aa198;
-$solarized-light-mo: #2aa198;
-$solarized-light-sb: #93a1a1;
-$solarized-light-sc: #2aa198;
-$solarized-light-sd: #586e75;
-$solarized-light-s2: #2aa198;
-$solarized-light-se: #cb4b16;
-$solarized-light-sh: #586e75;
-$solarized-light-si: #2aa198;
-$solarized-light-sx: #2aa198;
-$solarized-light-sr: #dc322f;
-$solarized-light-s1: #2aa198;
-$solarized-light-ss: #2aa198;
-$solarized-light-bp: #268bd2;
-$solarized-light-vc: #268bd2;
-$solarized-light-vg: #268bd2;
-$solarized-light-vi: #268bd2;
-$solarized-light-il: #2aa198;
-
-@mixin matchLine {
- color: $black-transparent;
- background: $solarized-light-matchline-bg;
-}
-
-.code.solarized-light {
- // Line numbers
- .line-numbers,
- .diff-line-num {
- background-color: $solarized-light-line-bg;
- }
-
- .diff-line-num,
- .diff-line-num a {
- color: $solarized-light-line-color;
- }
-
- // Code itself
- pre.code,
- .diff-line-num {
- border-color: $solarized-light-border;
- }
-
- &,
- pre.code,
- .line_holder .line_content {
- background-color: $solarized-light-pre-bg;
- color: $solarized-light-pre-color;
- }
-
- // Diff line
- .line_holder {
- &.match .line_content,
- &.old-nonewline .line_content,
- &.new-nonewline .line_content {
- @include matchLine;
- }
-
- td.diff-line-num.hll:not(.empty-cell),
- td.line_content.hll:not(.empty-cell) {
- background-color: $solarized-light-hll-bg;
- border-color: darken($solarized-light-hll-bg, 15%);
- }
-
- .diff-line-num.new,
- .line_content.new {
- @include diff_background($solarized-light-new-bg,
- $solarized-light-new-idiff, $solarized-light-border);
-
- &::before,
- a {
- color: $solarized-light-line-color-new;
- }
- }
-
- .diff-line-num.old,
- .line_content.old {
- @include diff_background($solarized-light-old-bg, $solarized-light-old-idiff, $solarized-light-border);
-
- &::before,
- a {
- color: $solarized-light-line-color-old;
- }
- }
-
- .diff-line-num {
- &.is-over,
- &.hll:not(.empty-cell).is-over {
- background-color: $solarized-light-over-bg;
- border-color: darken($solarized-light-over-bg, 5%);
-
- a {
- color: darken($solarized-light-over-bg, 15%);
- }
- }
- }
-
- .line_content.match {
- @include matchLine;
- }
-
- &:not(.diff-expanded) + .diff-expanded,
- &.diff-expanded + .line_holder:not(.diff-expanded) {
- > .diff-line-num,
- > .line_content {
- border-top: 1px solid $solarized-light-expanded-border;
- }
- }
-
- &.diff-expanded {
- > .diff-line-num,
- > .line_content {
- background: $solarized-light-expanded-bg;
- border-color: $solarized-light-expanded-bg;
- }
- }
- }
-
- // highlight line via anchor
- pre .hll {
- background-color: $solarized-light-hll-bg !important;
- }
-
- // Search result highlight
- span.highlight_word {
- background-color: $solarized-light-highlight !important;
- }
-
- // Links to URLs, emails, or dependencies
- .line a {
- color: $solarized-light-kd;
- }
-
- /* Solarized Light
-
- For use with Jekyll and Pygments
-
- http://ethanschoonover.com/solarized
-
- SOLARIZED HEX ROLE
- --------- -------- ------------------------------------------
- base01 #586e75 body text / default code / primary content
- base1 #93a1a1 comments / secondary content
- base3 #fdf6e3 background
- orange #cb4b16 constants
- red #dc322f regex, special keywords
- blue #268bd2 reserved keywords
- cyan #2aa198 strings, numbers
- green #859900 operators, other keywords
- */
-
- .c { color: $solarized-light-c; } /* Comment */
- .err { color: $solarized-light-err; } /* Error */
- .g { color: $solarized-light-g; } /* Generic */
- .k { color: $solarized-light-k; } /* Keyword */
- .l { color: $solarized-light-l; } /* Literal */
- .n { color: $solarized-light-n; } /* Name */
- .o { color: $solarized-light-o; } /* Operator */
- .x { color: $solarized-light-x; } /* Other */
- .p { color: $solarized-light-p; } /* Punctuation */
- .cm { color: $solarized-light-cm; } /* Comment.Multiline */
- .cp { color: $solarized-light-cp; } /* Comment.Preproc */
- .c1 { color: $solarized-light-c1; } /* Comment.Single */
- .cs { color: $solarized-light-cs; } /* Comment.Special */
- .gd { color: $solarized-light-gd; } /* Generic.Deleted */
- .ge { color: $solarized-light-ge; font-style: italic; } /* Generic.Emph */
- .gr { color: $solarized-light-gr; } /* Generic.Error */
- .gh { color: $solarized-light-gh; } /* Generic.Heading */
- .gi { color: $solarized-light-gi; } /* Generic.Inserted */
- .go { color: $solarized-light-go; } /* Generic.Output */
- .gp { color: $solarized-light-gp; } /* Generic.Prompt */
- .gs { color: $solarized-light-gs; font-weight: $gl-font-weight-bold; } /* Generic.Strong */
- .gu { color: $solarized-light-gu; } /* Generic.Subheading */
- .gt { color: $solarized-light-gt; } /* Generic.Traceback */
- .kc { color: $solarized-light-kc; } /* Keyword.Constant */
- .kd { color: $solarized-light-kd; } /* Keyword.Declaration */
- .kn { color: $solarized-light-kn; } /* Keyword.Namespace */
- .kp { color: $solarized-light-kp; } /* Keyword.Pseudo */
- .kr { color: $solarized-light-kr; } /* Keyword.Reserved */
- .kt { color: $solarized-light-kt; } /* Keyword.Type */
- .ld { color: $solarized-light-ld; } /* Literal.Date */
- .m { color: $solarized-light-m; } /* Literal.Number */
- .s { color: $solarized-light-s; } /* Literal.String */
- .na { color: $solarized-light-na; } /* Name.Attribute */
- .nb { color: $solarized-light-nb; } /* Name.Builtin */
- .nc { color: $solarized-light-nc; } /* Name.Class */
- .no { color: $solarized-light-no; } /* Name.Constant */
- .nd { color: $solarized-light-nd; } /* Name.Decorator */
- .ni { color: $solarized-light-ni; } /* Name.Entity */
- .ne { color: $solarized-light-ne; } /* Name.Exception */
- .nf { color: $solarized-light-nf; } /* Name.Function */
- .nl { color: $solarized-light-nl; } /* Name.Label */
- .nn { color: $solarized-light-nn; } /* Name.Namespace */
- .nx { color: $solarized-light-nx; } /* Name.Other */
- .py { color: $solarized-light-py; } /* Name.Property */
- .nt { color: $solarized-light-nt; } /* Name.Tag */
- .nv { color: $solarized-light-nv; } /* Name.Variable */
- .ow { color: $solarized-light-ow; } /* Operator.Word */
- .w { color: $solarized-light-w; } /* Text.Whitespace */
- .mf { color: $solarized-light-mf; } /* Literal.Number.Float */
- .mh { color: $solarized-light-mh; } /* Literal.Number.Hex */
- .mi { color: $solarized-light-mi; } /* Literal.Number.Integer */
- .mo { color: $solarized-light-mo; } /* Literal.Number.Oct */
- .sb { color: $solarized-light-sb; } /* Literal.String.Backtick */
- .sc { color: $solarized-light-sc; } /* Literal.String.Char */
- .sd { color: $solarized-light-sd; } /* Literal.String.Doc */
- .s2 { color: $solarized-light-s2; } /* Literal.String.Double */
- .se { color: $solarized-light-se; } /* Literal.String.Escape */
- .sh { color: $solarized-light-sh; } /* Literal.String.Heredoc */
- .si { color: $solarized-light-si; } /* Literal.String.Interpol */
- .sx { color: $solarized-light-sx; } /* Literal.String.Other */
- .sr { color: $solarized-light-sr; } /* Literal.String.Regex */
- .s1 { color: $solarized-light-s1; } /* Literal.String.Single */
- .ss { color: $solarized-light-ss; } /* Literal.String.Symbol */
- .bp { color: $solarized-light-bp; } /* Name.Builtin.Pseudo */
- .vc { color: $solarized-light-vc; } /* Name.Variable.Class */
- .vg { color: $solarized-light-vg; } /* Name.Variable.Global */
- .vi { color: $solarized-light-vi; } /* Name.Variable.Instance */
- .il { color: $solarized-light-il; } /* Literal.Number.Integer.Long */
-}
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
new file mode 100644
index 00000000000..16893dd047e
--- /dev/null
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -0,0 +1,261 @@
+/* https://github.com/MozMorris/tomorrow-pygments */
+
+@import "../common";
+
+/*
+* Dark syntax colors
+*/
+$dark-new-bg: rgba(51, 255, 51, 0.1);
+$dark-new-idiff: rgba(51, 255, 51, 0.2);
+$dark-old-bg: rgba(255, 51, 51, 0.2);
+$dark-old-idiff: rgba(255, 51, 51, 0.25);
+$dark-border: #808080;
+$dark-code-border: #666;
+$dark-main-bg: #1d1f21;
+$dark-main-color: #1d1f21;
+$dark-line-color: #c5c8c6;
+$dark-line-num-color: rgba(255, 255, 255, 0.3);
+$dark-line-num-color-new: #627165;
+$dark-line-num-color-old: #806565;
+$dark-diff-not-empty-bg: #557;
+$dark-highlight-bg: #ffe792;
+$dark-highlight-color: $black;
+$dark-pre-hll-bg: #373b41;
+$dark-hll-bg: #373b41;
+$dark-over-bg: #9f9ab5;
+$dark-expanded-bg: #3e3e3e;
+$dark-c: #969896;
+$dark-err: #c66;
+$dark-k: #b294bb;
+$dark-l: #de935f;
+$dark-n: #c5c8c6;
+$dark-o: #8abeb7;
+$dark-p: #c5c8c6;
+$dark-cm: #969896;
+$dark-cp: #969896;
+$dark-c1: #969896;
+$dark-cs: #969896;
+$dark-gd: #c66;
+$dark-gh: #c5c8c6;
+$dark-gi: #b5bd68;
+$dark-gp: #969896;
+$dark-gu: #8abeb7;
+$dark-kc: #b294bb;
+$dark-kd: #b294bb;
+$dark-kn: #8abeb7;
+$dark-kp: #b294bb;
+$dark-kr: #b294bb;
+$dark-kt: #f0c674;
+$dark-ld: #b5bd68;
+$dark-m: #de935f;
+$dark-s: #b5bd68;
+$dark-na: #81a2be;
+$dark-nb: #c5c8c6;
+$dark-nc: #f0c674;
+$dark-no: #c66;
+$dark-nd: #8abeb7;
+$dark-ni: #c5c8c6;
+$dark-ne: #c66;
+$dark-nf: #81a2be;
+$dark-nl: #c5c8c6;
+$dark-nn: #f0c674;
+$dark-nx: #81a2be;
+$dark-py: #c5c8c6;
+$dark-nt: #8abeb7;
+$dark-nv: #c66;
+$dark-ow: #8abeb7;
+$dark-w: #c5c8c6;
+$dark-mf: #de935f;
+$dark-mh: #de935f;
+$dark-mi: #de935f;
+$dark-mo: #de935f;
+$dark-sb: #b5bd68;
+$dark-sc: #c5c8c6;
+$dark-sd: #969896;
+$dark-s2: #b5bd68;
+$dark-se: #de935f;
+$dark-sh: #b5bd68;
+$dark-si: #de935f;
+$dark-sx: #b5bd68;
+$dark-sr: #b5bd68;
+$dark-s1: #b5bd68;
+$dark-ss: #b5bd68;
+$dark-bp: #c5c8c6;
+$dark-vc: #c66;
+$dark-vg: #c66;
+$dark-vi: #c66;
+$dark-il: #de935f;
+
+.code.dark {
+ // Line numbers
+ .line-numbers,
+ .diff-line-num {
+ background-color: $dark-main-bg;
+ }
+
+ .diff-line-num,
+ .diff-line-num a {
+ color: $dark-line-num-color;
+ }
+
+ // Code itself
+ pre.code,
+ .diff-line-num {
+ border-color: $dark-code-border;
+ }
+
+ &,
+ pre.code,
+ .line_holder .line_content {
+ background-color: $dark-main-bg;
+ color: $dark-line-color;
+ }
+
+ // Diff line
+ .line_holder {
+ &.match .line_content,
+ &.old-nonewline .line_content,
+ &.new-nonewline .line_content {
+ @include dark-diff-match-line;
+ }
+
+ td.diff-line-num.hll:not(.empty-cell),
+ td.line_content.hll:not(.empty-cell) {
+ background-color: $dark-diff-not-empty-bg;
+ border-color: darken($dark-diff-not-empty-bg, 15%);
+ }
+
+ .diff-line-num.new,
+ .line_content.new {
+ @include diff-background($dark-new-bg, $dark-new-idiff, $dark-border);
+
+ &::before,
+ a {
+ color: $dark-line-num-color-new;
+ }
+ }
+
+ .diff-line-num.old,
+ .line_content.old {
+ @include diff-background($dark-old-bg, $dark-old-idiff, $dark-border);
+
+ &::before,
+ a {
+ color: $dark-line-num-color-old;
+ }
+ }
+
+ .diff-line-num {
+ &.is-over,
+ &.hll:not(.empty-cell).is-over {
+ background-color: $dark-over-bg;
+ border-color: darken($dark-over-bg, 5%);
+
+ a {
+ color: darken($dark-over-bg, 15%);
+ }
+ }
+ }
+
+ .line_content.match {
+ @include dark-diff-match-line;
+ }
+
+ &:not(.diff-expanded) + .diff-expanded,
+ &.diff-expanded + .line_holder:not(.diff-expanded) {
+ > .diff-line-num,
+ > .line_content {
+ border-top: 1px solid $black;
+ }
+ }
+
+ &.diff-expanded {
+ > .diff-line-num,
+ > .line_content {
+ background: $dark-expanded-bg;
+ border-color: $dark-expanded-bg;
+ }
+ }
+ }
+
+ // highlight line via anchor
+ pre .hll {
+ background-color: $dark-pre-hll-bg !important;
+ }
+
+ // Search result highlight
+ span.highlight_word {
+ background-color: $dark-highlight-bg !important;
+ color: $dark-highlight-color !important;
+ }
+
+ // Links to URLs, emails, or dependencies
+ .line a {
+ color: $dark-na;
+ }
+
+ .hll { background-color: $dark-hll-bg; }
+ .c { color: $dark-c; } /* Comment */
+ .err { color: $dark-err; } /* Error */
+ .k { color: $dark-k; } /* Keyword */
+ .l { color: $dark-l; } /* Literal */
+ .n { color: $dark-n; } /* Name */
+ .o { color: $dark-o; } /* Operator */
+ .p { color: $dark-p; } /* Punctuation */
+ .cm { color: $dark-cm; } /* Comment.Multiline */
+ .cp { color: $dark-cp; } /* Comment.Preproc */
+ .c1 { color: $dark-c1; } /* Comment.Single */
+ .cs { color: $dark-cs; } /* Comment.Special */
+ .gd { color: $dark-gd; } /* Generic.Deleted */
+ .ge { font-style: italic; } /* Generic.Emph */
+ .gh { color: $dark-gh; font-weight: $gl-font-weight-bold; } /* Generic.Heading */
+ .gi { color: $dark-gi; } /* Generic.Inserted */
+ .gp { color: $dark-gp; font-weight: $gl-font-weight-bold; } /* Generic.Prompt */
+ .gs { font-weight: $gl-font-weight-bold; } /* Generic.Strong */
+ .gu { color: $dark-gu; font-weight: $gl-font-weight-bold; } /* Generic.Subheading */
+ .kc { color: $dark-kc; } /* Keyword.Constant */
+ .kd { color: $dark-kd; } /* Keyword.Declaration */
+ .kn { color: $dark-kn; } /* Keyword.Namespace */
+ .kp { color: $dark-kp; } /* Keyword.Pseudo */
+ .kr { color: $dark-kr; } /* Keyword.Reserved */
+ .kt { color: $dark-kt; } /* Keyword.Type */
+ .ld { color: $dark-ld; } /* Literal.Date */
+ .m { color: $dark-m; } /* Literal.Number */
+ .s { color: $dark-s; } /* Literal.String */
+ .na { color: $dark-na; } /* Name.Attribute */
+ .nb { color: $dark-nb; } /* Name.Builtin */
+ .nc { color: $dark-nc; } /* Name.Class */
+ .no { color: $dark-no; } /* Name.Constant */
+ .nd { color: $dark-nd; } /* Name.Decorator */
+ .ni { color: $dark-ni; } /* Name.Entity */
+ .ne { color: $dark-ne; } /* Name.Exception */
+ .nf { color: $dark-nf; } /* Name.Function */
+ .nl { color: $dark-nl; } /* Name.Label */
+ .nn { color: $dark-nn; } /* Name.Namespace */
+ .nx { color: $dark-nx; } /* Name.Other */
+ .py { color: $dark-py; } /* Name.Property */
+ .nt { color: $dark-nt; } /* Name.Tag */
+ .nv { color: $dark-nv; } /* Name.Variable */
+ .ow { color: $dark-ow; } /* Operator.Word */
+ .w { color: $dark-w; } /* Text.Whitespace */
+ .mf { color: $dark-mf; } /* Literal.Number.Float */
+ .mh { color: $dark-mh; } /* Literal.Number.Hex */
+ .mi { color: $dark-mi; } /* Literal.Number.Integer */
+ .mo { color: $dark-mo; } /* Literal.Number.Oct */
+ .sb { color: $dark-sb; } /* Literal.String.Backtick */
+ .sc { color: $dark-sc; } /* Literal.String.Char */
+ .sd { color: $dark-sd; } /* Literal.String.Doc */
+ .s2 { color: $dark-s2; } /* Literal.String.Double */
+ .se { color: $dark-se; } /* Literal.String.Escape */
+ .sh { color: $dark-sh; } /* Literal.String.Heredoc */
+ .si { color: $dark-si; } /* Literal.String.Interpol */
+ .sx { color: $dark-sx; } /* Literal.String.Other */
+ .sr { color: $dark-sr; } /* Literal.String.Regex */
+ .s1 { color: $dark-s1; } /* Literal.String.Single */
+ .ss { color: $dark-ss; } /* Literal.String.Symbol */
+ .bp { color: $dark-bp; } /* Name.Builtin.Pseudo */
+ .vc { color: $dark-vc; } /* Name.Variable.Class */
+ .vg { color: $dark-vg; } /* Name.Variable.Global */
+ .vi { color: $dark-vi; } /* Name.Variable.Instance */
+ .il { color: $dark-il; } /* Literal.Number.Integer.Long */
+}
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
new file mode 100644
index 00000000000..37fe61b925c
--- /dev/null
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -0,0 +1,259 @@
+/* https://github.com/richleland/pygments-css/blob/master/monokai.css */
+
+@import "../common";
+
+/*
+* Monokai Colors
+*/
+$monokai-bg: #272822;
+$monokai-border: #555;
+$monokai-text-color: #f8f8f2;
+$monokai-line-num-color: rgba(255, 255, 255, 0.3);
+$monokai-line-num-color-new: #707565;
+$monokai-line-num-color-old: #7e736f;
+$monokai-line-empty-bg: #49483e;
+$monokai-line-empty-border: darken($monokai-line-empty-bg, 15%);
+$monokai-diff-border: #808080;
+$monokai-highlight-bg: #ffe792;
+$monokai-over-bg: #9f9ab5;
+$monokai-expanded-bg: #3e3e3e;
+
+$monokai-new-bg: rgba(166, 226, 46, 0.1);
+$monokai-new-idiff: rgba(166, 226, 46, 0.15);
+
+$monokai-old-bg: rgba(254, 147, 140, 0.15);
+$monokai-old-idiff: rgba(254, 147, 140, 0.2);
+
+$monokai-hll: #49483e;
+$monokai-c: #75715e;
+$monokai-err-color: #960050;
+$monokai-err-bg: #1e0010;
+$monokai-k: #66d9ef;
+$monokai-l: #ae81ff;
+$monokai-n: #f8f8f2;
+$monokai-o: #f92672;
+$monokai-p: #f8f8f2;
+$monokai-cm: #75715e;
+$monokai-cp: #75715e;
+$monokai-c1: #75715e;
+$monokai-cs: #75715e;
+$monokai-kc: #66d9ef;
+$monokai-kd: #66d9ef;
+$monokai-kn: #f92672;
+$monokai-kp: #66d9ef;
+$monokai-kr: #66d9ef;
+$monokai-kt: #66d9ef;
+$monokai-ld: #e6db74;
+$monokai-m: #ae81ff;
+$monokai-s: #e6db74;
+$monokai-na: #a6e22e;
+$monokai-nb: #f8f8f2;
+$monokai-nc: #a6e22e;
+$monokai-no: #66d9ef;
+$monokai-nd: #a6e22e;
+$monokai-ni: #f8f8f2;
+$monokai-ne: #a6e22e;
+$monokai-nf: #a6e22e;
+$monokai-nl: #f8f8f2;
+$monokai-nn: #f8f8f2;
+$monokai-nx: #a6e22e;
+$monokai-py: #f8f8f2;
+$monokai-nt: #f92672;
+$monokai-nv: #f8f8f2;
+$monokai-ow: #f92672;
+$monokai-w: #f8f8f2;
+$monokai-mf: #ae81ff;
+$monokai-mh: #ae81ff;
+$monokai-mi: #ae81ff;
+$monokai-mo: #ae81ff;
+$monokai-sb: #e6db74;
+$monokai-sc: #e6db74;
+$monokai-sd: #e6db74;
+$monokai-s2: #e6db74;
+$monokai-se: #ae81ff;
+$monokai-sh: #e6db74;
+$monokai-si: #e6db74;
+$monokai-sx: #e6db74;
+$monokai-sr: #e6db74;
+$monokai-s1: #e6db74;
+$monokai-ss: #e6db74;
+$monokai-bp: #f8f8f2;
+$monokai-vc: #f8f8f2;
+$monokai-vg: #f8f8f2;
+$monokai-vi: #f8f8f2;
+$monokai-il: #ae81ff;
+$monokai-gu: #75715e;
+$monokai-gd: #f92672;
+$monokai-gi: #a6e22e;
+
+.code.monokai {
+ // Line numbers
+ .line-numbers,
+ .diff-line-num {
+ background-color: $monokai-bg;
+ }
+
+ .diff-line-num,
+ .diff-line-num a {
+ color: $monokai-line-num-color;
+ }
+
+ // Code itself
+ pre.code,
+ .diff-line-num {
+ border-color: $monokai-border;
+ }
+
+ &,
+ pre.code,
+ .line_holder .line_content {
+ background-color: $monokai-bg;
+ color: $monokai-text-color;
+ }
+
+ // Diff line
+ .line_holder {
+ &.match .line_content,
+ &.old-nonewline .line_content,
+ &.new-nonewline .line_content {
+ @include dark-diff-match-line;
+ }
+
+ td.diff-line-num.hll:not(.empty-cell),
+ td.line_content.hll:not(.empty-cell) {
+ background-color: $monokai-line-empty-bg;
+ border-color: $monokai-line-empty-border;
+ }
+
+ .diff-line-num.new,
+ .line_content.new {
+ @include diff-background($monokai-new-bg, $monokai-new-idiff, $monokai-diff-border);
+
+ &::before,
+ a {
+ color: $monokai-line-num-color-new;
+ }
+ }
+
+ .diff-line-num.old,
+ .line_content.old {
+ @include diff-background($monokai-old-bg, $monokai-old-idiff, $monokai-diff-border);
+
+ &::before,
+ a {
+ color: $monokai-line-num-color-old;
+ }
+ }
+
+ .diff-line-num {
+ &.is-over,
+ &.hll:not(.empty-cell).is-over {
+ background-color: $monokai-over-bg;
+ border-color: darken($monokai-over-bg, 5%);
+
+ a {
+ color: darken($monokai-over-bg, 15%);
+ }
+ }
+ }
+
+ .line_content.match {
+ @include dark-diff-match-line;
+ }
+
+ &:not(.diff-expanded) + .diff-expanded,
+ &.diff-expanded + .line_holder:not(.diff-expanded) {
+ > .diff-line-num,
+ > .line_content {
+ border-top: 1px solid $black;
+ }
+ }
+
+ &.diff-expanded {
+ > .diff-line-num,
+ > .line_content {
+ background: $monokai-expanded-bg;
+ border-color: $monokai-expanded-bg;
+ }
+ }
+ }
+
+ // highlight line via anchor
+ pre .hll {
+ background-color: $monokai-hll !important;
+ }
+
+ // Search result highlight
+ span.highlight_word {
+ background-color: $monokai-highlight-bg !important;
+ color: $black !important;
+ }
+
+ // Links to URLs, emails, or dependencies
+ .line a {
+ color: $monokai-k;
+ }
+
+ .hll { background-color: $monokai-hll; }
+ .c { color: $monokai-c; } /* Comment */
+ .err { color: $monokai-err-color; background-color: $monokai-err-bg; } /* Error */
+ .k { color: $monokai-k; } /* Keyword */
+ .l { color: $monokai-l; } /* Literal */
+ .n { color: $monokai-n; } /* Name */
+ .o { color: $monokai-o; } /* Operator */
+ .p { color: $monokai-p; } /* Punctuation */
+ .cm { color: $monokai-cm; } /* Comment.Multiline */
+ .cp { color: $monokai-cp; } /* Comment.Preproc */
+ .c1 { color: $monokai-c1; } /* Comment.Single */
+ .cs { color: $monokai-cs; } /* Comment.Special */
+ .ge { font-style: italic; } /* Generic.Emph */
+ .gs { font-weight: $gl-font-weight-bold; } /* Generic.Strong */
+ .kc { color: $monokai-kc; } /* Keyword.Constant */
+ .kd { color: $monokai-kd; } /* Keyword.Declaration */
+ .kn { color: $monokai-kn; } /* Keyword.Namespace */
+ .kp { color: $monokai-kp; } /* Keyword.Pseudo */
+ .kr { color: $monokai-kr; } /* Keyword.Reserved */
+ .kt { color: $monokai-kt; } /* Keyword.Type */
+ .ld { color: $monokai-ld; } /* Literal.Date */
+ .m { color: $monokai-m; } /* Literal.Number */
+ .s { color: $monokai-s; } /* Literal.String */
+ .na { color: $monokai-na; } /* Name.Attribute */
+ .nb { color: $monokai-nb; } /* Name.Builtin */
+ .nc { color: $monokai-nc; } /* Name.Class */
+ .no { color: $monokai-no; } /* Name.Constant */
+ .nd { color: $monokai-nd; } /* Name.Decorator */
+ .ni { color: $monokai-ni; } /* Name.Entity */
+ .ne { color: $monokai-ne; } /* Name.Exception */
+ .nf { color: $monokai-nf; } /* Name.Function */
+ .nl { color: $monokai-nl; } /* Name.Label */
+ .nn { color: $monokai-nn; } /* Name.Namespace */
+ .nx { color: $monokai-nx; } /* Name.Other */
+ .py { color: $monokai-py; } /* Name.Property */
+ .nt { color: $monokai-nt; } /* Name.Tag */
+ .nv { color: $monokai-nv; } /* Name.Variable */
+ .ow { color: $monokai-ow; } /* Operator.Word */
+ .w { color: $monokai-w; } /* Text.Whitespace */
+ .mf { color: $monokai-mf; } /* Literal.Number.Float */
+ .mh { color: $monokai-mh; } /* Literal.Number.Hex */
+ .mi { color: $monokai-mi; } /* Literal.Number.Integer */
+ .mo { color: $monokai-mo; } /* Literal.Number.Oct */
+ .sb { color: $monokai-sb; } /* Literal.String.Backtick */
+ .sc { color: $monokai-sc; } /* Literal.String.Char */
+ .sd { color: $monokai-sd; } /* Literal.String.Doc */
+ .s2 { color: $monokai-s2; } /* Literal.String.Double */
+ .se { color: $monokai-se; } /* Literal.String.Escape */
+ .sh { color: $monokai-sh; } /* Literal.String.Heredoc */
+ .si { color: $monokai-si; } /* Literal.String.Interpol */
+ .sx { color: $monokai-sx; } /* Literal.String.Other */
+ .sr { color: $monokai-sr; } /* Literal.String.Regex */
+ .s1 { color: $monokai-s1; } /* Literal.String.Single */
+ .ss { color: $monokai-ss; } /* Literal.String.Symbol */
+ .bp { color: $monokai-bp; } /* Name.Builtin.Pseudo */
+ .vc { color: $monokai-vc; } /* Name.Variable.Class */
+ .vg { color: $monokai-vg; } /* Name.Variable.Global */
+ .vi { color: $monokai-vi; } /* Name.Variable.Instance */
+ .il { color: $monokai-il; } /* Literal.Number.Integer.Long */
+ .gu { color: $monokai-gu; } /* Generic.Subheading & Diff Unified/Comment? */
+ .gd { color: $monokai-gd; } /* Generic.Deleted & Diff Deleted */
+ .gi { color: $monokai-gi; } /* Generic.Inserted & Diff Inserted */
+}
diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss
new file mode 100644
index 00000000000..b4217aac37a
--- /dev/null
+++ b/app/assets/stylesheets/highlight/themes/none.scss
@@ -0,0 +1,238 @@
+/*
+* None Syntax Colors
+*/
+
+@import "../common";
+
+@mixin match-line {
+ color: $black-transparent;
+ background-color: $white-normal;
+}
+
+.code.none {
+ // Line numbers
+ .line-numbers,
+ .diff-line-num {
+ background-color: $gray-light;
+ }
+
+ .diff-line-num,
+ .diff-line-num a {
+ color: $black-transparent;
+ }
+
+ // Code itself
+ pre.code,
+ .diff-line-num {
+ border-color: $white-normal;
+ }
+
+ &,
+ pre.code,
+ .line_holder .line_content {
+ background-color: $white-light;
+ color: $gl-text-color;
+ }
+
+// Diff line
+
+ $none-over-bg: #ded7fc;
+ $none-expanded-border: #e0e0e0;
+ $none-expanded-bg: #e0e0e0;
+
+ .line_holder {
+
+ &.match .line_content,
+ .new-nonewline.line_content,
+ .old-nonewline.line_content {
+ @include match-line;
+ }
+
+ .diff-line-num {
+ &.old {
+ a {
+ color: scale-color($line-number-old, $red: -30%, $green: -30%, $blue: -30%);
+ }
+ }
+
+ &.new {
+ a {
+ color: scale-color($line-number-new, $red: -30%, $green: -30%, $blue: -30%);
+ }
+ }
+
+ &.is-over,
+ &.hll:not(.empty-cell).is-over {
+ background-color: $none-over-bg;
+ border-color: darken($none-over-bg, 5%);
+
+ a {
+ color: darken($none-over-bg, 15%);
+ }
+ }
+
+ &.hll:not(.empty-cell) {
+ background-color: $white-light;
+ border-color: $white-normal;
+ }
+ }
+
+ &:not(.diff-expanded) + .diff-expanded,
+ &.diff-expanded + .line_holder:not(.diff-expanded) {
+ > .diff-line-num,
+ > .line_content {
+ border-top: 1px solid $none-expanded-border;
+ }
+ }
+
+ &.diff-expanded {
+ > .diff-line-num,
+ > .line_content {
+ background: $none-expanded-bg;
+ border-color: $none-expanded-bg;
+ }
+ }
+
+ .line_content {
+ &.old {
+ background-color: $white-normal;
+
+ &::before {
+ color: $gl-text-color;
+ }
+
+ span.idiff {
+ background-color: $white-normal;
+ text-decoration: underline;
+ }
+ }
+
+ &.new {
+ background-color: $white-normal;
+
+ &::before {
+ color: $gl-text-color;
+ }
+
+ span.idiff {
+ background-color: $white-normal;
+ text-decoration: underline;
+ }
+ }
+
+ &.match {
+ @include match-line;
+ }
+
+ &.hll:not(.empty-cell) {
+ background-color: $white-normal;
+ }
+ }
+ }
+
+ // highlight line via anchor
+ pre .hll {
+ background-color: $white-normal;
+ }
+
+ // Search result highlight
+ span.highlight_word {
+ background-color: $white-normal;
+ }
+
+ // Links to URLs, emails, or dependencies
+ .line a {
+ color: $gl-text-color;
+ text-decoration: underline;
+ }
+
+ .hll { background-color: $white-light; }
+
+ .gd {
+ color: $gl-text-color;
+ background-color: $white-light;
+
+ .x {
+ color: $gl-text-color;
+ background-color: $white-light;
+ }
+ }
+
+ .gi {
+ color: $gl-text-color;
+ background-color: $white-light;
+
+ .x {
+ color: $gl-text-color;
+ background-color: $white-light;
+ }
+ }
+
+ .c { color: $gl-text-color; } /* Comment */
+ .err { color: $gl-text-color; } /* Error */
+ .g { color: $gl-text-color; } /* Generic */
+ .k { color: $gl-text-color; } /* Keyword */
+ .l { color: $gl-text-color; } /* Literal */
+ .n { color: $gl-text-color; } /* Name */
+ .o { color: $gl-text-color; } /* Operator */
+ .x { color: $gl-text-color; } /* Other */
+ .p { color: $gl-text-color; } /* Punctuation */
+ .cm { color: $gl-text-color; } /* Comment.Multiline */
+ .cp { color: $gl-text-color; } /* Comment.Preproc */
+ .c1 { color: $gl-text-color; } /* Comment.Single */
+ .cs { color: $gl-text-color; } /* Comment.Special */
+ .ge { color: $gl-text-color; } /* Generic.Emph */
+ .gr { color: $gl-text-color; } /* Generic.Error */
+ .gh { color: $gl-text-color; } /* Generic.Heading */
+ .go { color: $gl-text-color; } /* Generic.Output */
+ .gp { color: $gl-text-color; } /* Generic.Prompt */
+ .gs { color: $gl-text-color; } /* Generic.Strong */
+ .gu { color: $gl-text-color; } /* Generic.Subheading */
+ .gt { color: $gl-text-color; } /* Generic.Traceback */
+ .kc { color: $gl-text-color; } /* Keyword.Constant */
+ .kd { color: $gl-text-color; } /* Keyword.Declaration */
+ .kn { color: $gl-text-color; } /* Keyword.Namespace */
+ .kp { color: $gl-text-color; } /* Keyword.Pseudo */
+ .kr { color: $gl-text-color; } /* Keyword.Reserved */
+ .kt { color: $gl-text-color; } /* Keyword.Type */
+ .ld { color: $gl-text-color; } /* Literal.Date */
+ .m { color: $gl-text-color; } /* Literal.Number */
+ .s { color: $gl-text-color; } /* Literal.String */
+ .na { color: $gl-text-color; } /* Name.Attribute */
+ .nb { color: $gl-text-color; } /* Name.Builtin */
+ .nc { color: $gl-text-color; } /* Name.Class */
+ .no { color: $gl-text-color; } /* Name.Constant */
+ .nd { color: $gl-text-color; } /* Name.Decorator */
+ .ni { color: $gl-text-color; } /* Name.Entity */
+ .ne { color: $gl-text-color; } /* Name.Exception */
+ .nf { color: $gl-text-color; } /* Name.Function */
+ .nl { color: $gl-text-color; } /* Name.Label */
+ .nn { color: $gl-text-color; } /* Name.Namespace */
+ .nx { color: $gl-text-color; } /* Name.Other */
+ .py { color: $gl-text-color; } /* Name.Property */
+ .nt { color: $gl-text-color; } /* Name.Tag */
+ .nv { color: $gl-text-color; } /* Name.Variable */
+ .ow { color: $gl-text-color; } /* Operator.Word */
+ .w { color: $gl-text-color; } /* Text.Whitespace */
+ .mf { color: $gl-text-color; } /* Literal.Number.Float */
+ .mh { color: $gl-text-color; } /* Literal.Number.Hex */
+ .mi { color: $gl-text-color; } /* Literal.Number.Integer */
+ .mo { color: $gl-text-color; } /* Literal.Number.Oct */
+ .sb { color: $gl-text-color; } /* Literal.String.Backtick */
+ .sc { color: $gl-text-color; } /* Literal.String.Char */
+ .sd { color: $gl-text-color; } /* Literal.String.Doc */
+ .s2 { color: $gl-text-color; } /* Literal.String.Double */
+ .se { color: $gl-text-color; } /* Literal.String.Escape */
+ .sh { color: $gl-text-color; } /* Literal.String.Heredoc */
+ .si { color: $gl-text-color; } /* Literal.String.Interpol */
+ .sx { color: $gl-text-color; } /* Literal.String.Other */
+ .sr { color: $gl-text-color; } /* Literal.String.Regex */
+ .s1 { color: $gl-text-color; } /* Literal.String.Single */
+ .ss { color: $gl-text-color; } /* Literal.String.Symbol */
+ .bp { color: $gl-text-color; } /* Name.Builtin.Pseudo */
+ .vc { color: $gl-text-color; } /* Name.Variable.Class */
+ .vg { color: $gl-text-color; } /* Name.Variable.Global */
+ .vi { color: $gl-text-color; } /* Name.Variable.Instance */
+ .il { color: $gl-text-color; } /* Literal.Number.Integer.Long */
+
+}
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
new file mode 100644
index 00000000000..a4e9eda22c9
--- /dev/null
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -0,0 +1,286 @@
+/* https://gist.github.com/qguv/7936275 */
+
+@import "../common";
+
+/*
+* Solarized dark colors
+*/
+$solarized-dark-new-bg: rgba(133, 153, 0, 0.15);
+$solarized-dark-new-idiff: rgba(133, 153, 0, 0.25);
+$solarized-dark-old-bg: rgba(220, 50, 47, 0.3);
+$solarized-dark-old-idiff: rgba(220, 50, 47, 0.25);
+$solarized-dark-border: #113b46;
+$solarized-dark-pre-bg: #002b36;
+$solarized-dark-pre-color: #93a1a1;
+$solarized-dark-pre-border: #113b46;
+$solarized-dark-line-bg: #002b36;
+$solarized-dark-line-color: rgba(255, 255, 255, 0.3);
+$solarized-dark-line-color-new: #5a766c;
+$solarized-dark-line-color-old: #7a6c71;
+$solarized-dark-highlight: #094554;
+$solarized-dark-hll-bg: #174652;
+$solarized-dark-over-bg: #9f9ab5;
+$solarized-dark-expanded-bg: #010d10;
+$solarized-dark-c: #586e75;
+$solarized-dark-err: #93a1a1;
+$solarized-dark-g: #93a1a1;
+$solarized-dark-k: #859900;
+$solarized-dark-l: #93a1a1;
+$solarized-dark-n: #93a1a1;
+$solarized-dark-o: #859900;
+$solarized-dark-x: #cb4b16;
+$solarized-dark-p: #93a1a1;
+$solarized-dark-cm: #586e75;
+$solarized-dark-cp: #859900;
+$solarized-dark-c1: #586e75;
+$solarized-dark-cs: #859900;
+$solarized-dark-gd: #2aa198;
+$solarized-dark-ge: #93a1a1;
+$solarized-dark-gr: #dc322f;
+$solarized-dark-gh: #cb4b16;
+$solarized-dark-gi: #859900;
+$solarized-dark-go: #93a1a1;
+$solarized-dark-gp: #93a1a1;
+$solarized-dark-gs: #93a1a1;
+$solarized-dark-gu: #cb4b16;
+$solarized-dark-gt: #93a1a1;
+$solarized-dark-kc: #cb4b16;
+$solarized-dark-kd: #268bd2;
+$solarized-dark-kn: #859900;
+$solarized-dark-kp: #859900;
+$solarized-dark-kr: #268bd2;
+$solarized-dark-kt: #dc322f;
+$solarized-dark-ld: #93a1a1;
+$solarized-dark-m: #2aa198;
+$solarized-dark-s: #2aa198;
+$solarized-dark-na: #93a1a1;
+$solarized-dark-nb: #b58900;
+$solarized-dark-nc: #268bd2;
+$solarized-dark-no: #cb4b16;
+$solarized-dark-nd: #268bd2;
+$solarized-dark-ni: #cb4b16;
+$solarized-dark-ne: #cb4b16;
+$solarized-dark-nf: #268bd2;
+$solarized-dark-nl: #93a1a1;
+$solarized-dark-nn: #93a1a1;
+$solarized-dark-nx: #93a1a1;
+$solarized-dark-py: #93a1a1;
+$solarized-dark-nt: #268bd2;
+$solarized-dark-nv: #268bd2;
+$solarized-dark-ow: #859900;
+$solarized-dark-w: #93a1a1;
+$solarized-dark-mf: #2aa198;
+$solarized-dark-mh: #2aa198;
+$solarized-dark-mi: #2aa198;
+$solarized-dark-mo: #2aa198;
+$solarized-dark-sb: #586e75;
+$solarized-dark-sc: #2aa198;
+$solarized-dark-sd: #93a1a1;
+$solarized-dark-s2: #2aa198;
+$solarized-dark-se: #cb4b16;
+$solarized-dark-sh: #93a1a1;
+$solarized-dark-si: #2aa198;
+$solarized-dark-sx: #2aa198;
+$solarized-dark-sr: #dc322f;
+$solarized-dark-s1: #2aa198;
+$solarized-dark-ss: #2aa198;
+$solarized-dark-bp: #268bd2;
+$solarized-dark-vc: #268bd2;
+$solarized-dark-vg: #268bd2;
+$solarized-dark-vi: #268bd2;
+$solarized-dark-il: #2aa198;
+
+.code.solarized-dark {
+ // Line numbers
+ .line-numbers,
+ .diff-line-num {
+ background-color: $solarized-dark-line-bg;
+ }
+
+ .diff-line-num,
+ .diff-line-num a {
+ color: $solarized-dark-line-color;
+ }
+
+ // Code itself
+ pre.code,
+ .diff-line-num {
+ border-color: $solarized-dark-pre-border;
+ }
+
+ &,
+ pre.code,
+ .line_holder .line_content {
+ background-color: $solarized-dark-pre-bg;
+ color: $solarized-dark-pre-color;
+ }
+
+ // Diff line
+ .line_holder {
+ &.match .line_content,
+ &.old-nonewline .line_content,
+ &.new-nonewline .line_content {
+ @include dark-diff-match-line;
+ }
+
+ td.diff-line-num.hll:not(.empty-cell),
+ td.line_content.hll:not(.empty-cell) {
+ background-color: $solarized-dark-hll-bg;
+ border-color: darken($solarized-dark-hll-bg, 15%);
+ }
+
+ .diff-line-num.new,
+ .line_content.new {
+ @include diff-background($solarized-dark-new-bg, $solarized-dark-new-idiff, $solarized-dark-border);
+
+ &::before,
+ a {
+ color: $solarized-dark-line-color-new;
+ }
+ }
+
+ .diff-line-num.old,
+ .line_content.old {
+ @include diff-background($solarized-dark-old-bg, $solarized-dark-old-idiff, $solarized-dark-border);
+
+ &::before,
+ a {
+ color: $solarized-dark-line-color-old;
+ }
+ }
+
+ .diff-line-num {
+ &.is-over,
+ &.hll:not(.empty-cell).is-over {
+ background-color: $solarized-dark-over-bg;
+ border-color: darken($solarized-dark-over-bg, 5%);
+
+ a {
+ color: darken($solarized-dark-over-bg, 15%);
+ }
+ }
+ }
+
+ .line_content.match {
+ @include dark-diff-match-line;
+ }
+
+ &:not(.diff-expanded) + .diff-expanded,
+ &.diff-expanded + .line_holder:not(.diff-expanded) {
+ > .diff-line-num,
+ > .line_content {
+ border-top: 1px solid $black;
+ }
+ }
+
+ &.diff-expanded {
+ > .diff-line-num,
+ > .line_content {
+ background: $solarized-dark-expanded-bg;
+ border-color: $solarized-dark-expanded-bg;
+ }
+ }
+ }
+
+ // highlight line via anchor
+ pre .hll {
+ background-color: $solarized-dark-hll-bg !important;
+ }
+
+ // Search result highlight
+ span.highlight_word {
+ background-color: $solarized-dark-highlight !important;
+ }
+
+ // Links to URLs, emails, or dependencies
+ .line a {
+ color: $solarized-dark-kd;
+ }
+
+ /* Solarized Dark
+
+ For use with Jekyll and Pygments
+
+ http://ethanschoonover.com/solarized
+
+ SOLARIZED HEX ROLE
+ --------- -------- ------------------------------------------
+ base03 #002b36 background
+ base01 #586e75 comments / secondary content
+ base1 #93a1a1 body text / default code / primary content
+ orange #cb4b16 constants
+ red #dc322f regex, special keywords
+ blue #268bd2 reserved keywords
+ cyan #2aa198 strings, numbers
+ green #859900 operators, other keywords
+ */
+
+ .c { color: $solarized-dark-c; } /* Comment */
+ .err { color: $solarized-dark-err; } /* Error */
+ .g { color: $solarized-dark-g; } /* Generic */
+ .k { color: $solarized-dark-k; } /* Keyword */
+ .l { color: $solarized-dark-l; } /* Literal */
+ .n { color: $solarized-dark-n; } /* Name */
+ .o { color: $solarized-dark-o; } /* Operator */
+ .x { color: $solarized-dark-x; } /* Other */
+ .p { color: $solarized-dark-p; } /* Punctuation */
+ .cm { color: $solarized-dark-cm; } /* Comment.Multiline */
+ .cp { color: $solarized-dark-cp; } /* Comment.Preproc */
+ .c1 { color: $solarized-dark-c1; } /* Comment.Single */
+ .cs { color: $solarized-dark-cs; } /* Comment.Special */
+ .gd { color: $solarized-dark-gd; } /* Generic.Deleted */
+ .ge { color: $solarized-dark-ge; font-style: italic; } /* Generic.Emph */
+ .gr { color: $solarized-dark-gr; } /* Generic.Error */
+ .gh { color: $solarized-dark-gh; } /* Generic.Heading */
+ .gi { color: $solarized-dark-gi; } /* Generic.Inserted */
+ .go { color: $solarized-dark-go; } /* Generic.Output */
+ .gp { color: $solarized-dark-gp; } /* Generic.Prompt */
+ .gs { color: $solarized-dark-gs; font-weight: $gl-font-weight-bold; } /* Generic.Strong */
+ .gu { color: $solarized-dark-gu; } /* Generic.Subheading */
+ .gt { color: $solarized-dark-gt; } /* Generic.Traceback */
+ .kc { color: $solarized-dark-kc; } /* Keyword.Constant */
+ .kd { color: $solarized-dark-kd; } /* Keyword.Declaration */
+ .kn { color: $solarized-dark-kn; } /* Keyword.Namespace */
+ .kp { color: $solarized-dark-kp; } /* Keyword.Pseudo */
+ .kr { color: $solarized-dark-kr; } /* Keyword.Reserved */
+ .kt { color: $solarized-dark-kt; } /* Keyword.Type */
+ .ld { color: $solarized-dark-ld; } /* Literal.Date */
+ .m { color: $solarized-dark-m; } /* Literal.Number */
+ .s { color: $solarized-dark-s; } /* Literal.String */
+ .na { color: $solarized-dark-na; } /* Name.Attribute */
+ .nb { color: $solarized-dark-nb; } /* Name.Builtin */
+ .nc { color: $solarized-dark-nc; } /* Name.Class */
+ .no { color: $solarized-dark-no; } /* Name.Constant */
+ .nd { color: $solarized-dark-nd; } /* Name.Decorator */
+ .ni { color: $solarized-dark-ni; } /* Name.Entity */
+ .ne { color: $solarized-dark-ne; } /* Name.Exception */
+ .nf { color: $solarized-dark-nf; } /* Name.Function */
+ .nl { color: $solarized-dark-nl; } /* Name.Label */
+ .nn { color: $solarized-dark-nn; } /* Name.Namespace */
+ .nx { color: $solarized-dark-nx; } /* Name.Other */
+ .py { color: $solarized-dark-py; } /* Name.Property */
+ .nt { color: $solarized-dark-nt; } /* Name.Tag */
+ .nv { color: $solarized-dark-nv; } /* Name.Variable */
+ .ow { color: $solarized-dark-ow; } /* Operator.Word */
+ .w { color: $solarized-dark-w; } /* Text.Whitespace */
+ .mf { color: $solarized-dark-mf; } /* Literal.Number.Float */
+ .mh { color: $solarized-dark-mh; } /* Literal.Number.Hex */
+ .mi { color: $solarized-dark-mi; } /* Literal.Number.Integer */
+ .mo { color: $solarized-dark-mo; } /* Literal.Number.Oct */
+ .sb { color: $solarized-dark-sb; } /* Literal.String.Backtick */
+ .sc { color: $solarized-dark-sc; } /* Literal.String.Char */
+ .sd { color: $solarized-dark-sd; } /* Literal.String.Doc */
+ .s2 { color: $solarized-dark-s2; } /* Literal.String.Double */
+ .se { color: $solarized-dark-se; } /* Literal.String.Escape */
+ .sh { color: $solarized-dark-sh; } /* Literal.String.Heredoc */
+ .si { color: $solarized-dark-si; } /* Literal.String.Interpol */
+ .sx { color: $solarized-dark-sx; } /* Literal.String.Other */
+ .sr { color: $solarized-dark-sr; } /* Literal.String.Regex */
+ .s1 { color: $solarized-dark-s1; } /* Literal.String.Single */
+ .ss { color: $solarized-dark-ss; } /* Literal.String.Symbol */
+ .bp { color: $solarized-dark-bp; } /* Name.Builtin.Pseudo */
+ .vc { color: $solarized-dark-vc; } /* Name.Variable.Class */
+ .vg { color: $solarized-dark-vg; } /* Name.Variable.Global */
+ .vi { color: $solarized-dark-vi; } /* Name.Variable.Instance */
+ .il { color: $solarized-dark-il; } /* Literal.Number.Integer.Long */
+}
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
new file mode 100644
index 00000000000..b604d1ccb6c
--- /dev/null
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -0,0 +1,294 @@
+/* https://gist.github.com/qguv/7936275 */
+
+@import "../common";
+
+/*
+* Solarized light syntax colors
+*/
+$solarized-light-matchline-bg: rgba(255, 255, 255, 0.4);
+$solarized-light-new-bg: rgba(133, 153, 0, 0.2);
+$solarized-light-new-idiff: rgba(133, 153, 0, 0.25);
+$solarized-light-old-bg: rgba(220, 50, 47, 0.2);
+$solarized-light-old-idiff: rgba(220, 50, 47, 0.25);
+$solarized-light-border: #c5d0d4;
+$solarized-light-pre-bg: #002b36;
+$solarized-light-pre-bg: #fdf6e3;
+$solarized-light-pre-color: #586e75;
+$solarized-light-line-bg: #fdf6e3;
+$solarized-light-line-color: rgba(0, 0, 0, 0.3);
+$solarized-light-line-color-new: #a1a080;
+$solarized-light-line-color-old: #ad9186;
+$solarized-light-highlight: #eee8d5;
+$solarized-light-hll-bg: #ddd8c5;
+$solarized-light-over-bg: #ded7fc;
+$solarized-light-expanded-border: #d2cdbd;
+$solarized-light-expanded-bg: #ece6d4;
+$solarized-light-c: #93a1a1;
+$solarized-light-err: #586e75;
+$solarized-light-g: #586e75;
+$solarized-light-k: #859900;
+$solarized-light-l: #586e75;
+$solarized-light-n: #586e75;
+$solarized-light-o: #859900;
+$solarized-light-x: #cb4b16;
+$solarized-light-p: #586e75;
+$solarized-light-cm: #93a1a1;
+$solarized-light-cp: #859900;
+$solarized-light-c1: #93a1a1;
+$solarized-light-cs: #859900;
+$solarized-light-gd: #2aa198;
+$solarized-light-ge: #586e75;
+$solarized-light-gr: #dc322f;
+$solarized-light-gh: #cb4b16;
+$solarized-light-gi: #859900;
+$solarized-light-go: #586e75;
+$solarized-light-gp: #586e75;
+$solarized-light-gs: #586e75;
+$solarized-light-gu: #cb4b16;
+$solarized-light-gt: #586e75;
+$solarized-light-kc: #cb4b16;
+$solarized-light-kd: #268bd2;
+$solarized-light-kn: #859900;
+$solarized-light-kp: #859900;
+$solarized-light-kr: #268bd2;
+$solarized-light-kt: #dc322f;
+$solarized-light-ld: #586e75;
+$solarized-light-m: #2aa198;
+$solarized-light-s: #2aa198;
+$solarized-light-na: #586e75;
+$solarized-light-nb: #b58900;
+$solarized-light-nc: #268bd2;
+$solarized-light-no: #cb4b16;
+$solarized-light-nd: #268bd2;
+$solarized-light-ni: #cb4b16;
+$solarized-light-ne: #cb4b16;
+$solarized-light-nf: #268bd2;
+$solarized-light-nl: #586e75;
+$solarized-light-nn: #586e75;
+$solarized-light-nx: #586e75;
+$solarized-light-py: #586e75;
+$solarized-light-nt: #268bd2;
+$solarized-light-nv: #268bd2;
+$solarized-light-ow: #859900;
+$solarized-light-w: #586e75;
+$solarized-light-mf: #2aa198;
+$solarized-light-mh: #2aa198;
+$solarized-light-mi: #2aa198;
+$solarized-light-mo: #2aa198;
+$solarized-light-sb: #93a1a1;
+$solarized-light-sc: #2aa198;
+$solarized-light-sd: #586e75;
+$solarized-light-s2: #2aa198;
+$solarized-light-se: #cb4b16;
+$solarized-light-sh: #586e75;
+$solarized-light-si: #2aa198;
+$solarized-light-sx: #2aa198;
+$solarized-light-sr: #dc322f;
+$solarized-light-s1: #2aa198;
+$solarized-light-ss: #2aa198;
+$solarized-light-bp: #268bd2;
+$solarized-light-vc: #268bd2;
+$solarized-light-vg: #268bd2;
+$solarized-light-vi: #268bd2;
+$solarized-light-il: #2aa198;
+
+@mixin match-line {
+ color: $black-transparent;
+ background: $solarized-light-matchline-bg;
+}
+
+.code.solarized-light {
+ // Line numbers
+ .line-numbers,
+ .diff-line-num {
+ background-color: $solarized-light-line-bg;
+ }
+
+ .diff-line-num,
+ .diff-line-num a {
+ color: $solarized-light-line-color;
+ }
+
+ // Code itself
+ pre.code,
+ .diff-line-num {
+ border-color: $solarized-light-border;
+ }
+
+ &,
+ pre.code,
+ .line_holder .line_content {
+ background-color: $solarized-light-pre-bg;
+ color: $solarized-light-pre-color;
+ }
+
+ // Diff line
+ .line_holder {
+ &.match .line_content,
+ &.old-nonewline .line_content,
+ &.new-nonewline .line_content {
+ @include match-line;
+ }
+
+ td.diff-line-num.hll:not(.empty-cell),
+ td.line_content.hll:not(.empty-cell) {
+ background-color: $solarized-light-hll-bg;
+ border-color: darken($solarized-light-hll-bg, 15%);
+ }
+
+ .diff-line-num.new,
+ .line_content.new {
+ @include diff-background($solarized-light-new-bg,
+ $solarized-light-new-idiff, $solarized-light-border);
+
+ &::before,
+ a {
+ color: $solarized-light-line-color-new;
+ }
+ }
+
+ .diff-line-num.old,
+ .line_content.old {
+ @include diff-background($solarized-light-old-bg, $solarized-light-old-idiff, $solarized-light-border);
+
+ &::before,
+ a {
+ color: $solarized-light-line-color-old;
+ }
+ }
+
+ .diff-line-num {
+ &.is-over,
+ &.hll:not(.empty-cell).is-over {
+ background-color: $solarized-light-over-bg;
+ border-color: darken($solarized-light-over-bg, 5%);
+
+ a {
+ color: darken($solarized-light-over-bg, 15%);
+ }
+ }
+ }
+
+ .line_content.match {
+ @include match-line;
+ }
+
+ &:not(.diff-expanded) + .diff-expanded,
+ &.diff-expanded + .line_holder:not(.diff-expanded) {
+ > .diff-line-num,
+ > .line_content {
+ border-top: 1px solid $solarized-light-expanded-border;
+ }
+ }
+
+ &.diff-expanded {
+ > .diff-line-num,
+ > .line_content {
+ background: $solarized-light-expanded-bg;
+ border-color: $solarized-light-expanded-bg;
+ }
+ }
+ }
+
+ // highlight line via anchor
+ pre .hll {
+ background-color: $solarized-light-hll-bg !important;
+ }
+
+ // Search result highlight
+ span.highlight_word {
+ background-color: $solarized-light-highlight !important;
+ }
+
+ // Links to URLs, emails, or dependencies
+ .line a {
+ color: $solarized-light-kd;
+ }
+
+ /* Solarized Light
+
+ For use with Jekyll and Pygments
+
+ http://ethanschoonover.com/solarized
+
+ SOLARIZED HEX ROLE
+ --------- -------- ------------------------------------------
+ base01 #586e75 body text / default code / primary content
+ base1 #93a1a1 comments / secondary content
+ base3 #fdf6e3 background
+ orange #cb4b16 constants
+ red #dc322f regex, special keywords
+ blue #268bd2 reserved keywords
+ cyan #2aa198 strings, numbers
+ green #859900 operators, other keywords
+ */
+
+ .c { color: $solarized-light-c; } /* Comment */
+ .err { color: $solarized-light-err; } /* Error */
+ .g { color: $solarized-light-g; } /* Generic */
+ .k { color: $solarized-light-k; } /* Keyword */
+ .l { color: $solarized-light-l; } /* Literal */
+ .n { color: $solarized-light-n; } /* Name */
+ .o { color: $solarized-light-o; } /* Operator */
+ .x { color: $solarized-light-x; } /* Other */
+ .p { color: $solarized-light-p; } /* Punctuation */
+ .cm { color: $solarized-light-cm; } /* Comment.Multiline */
+ .cp { color: $solarized-light-cp; } /* Comment.Preproc */
+ .c1 { color: $solarized-light-c1; } /* Comment.Single */
+ .cs { color: $solarized-light-cs; } /* Comment.Special */
+ .gd { color: $solarized-light-gd; } /* Generic.Deleted */
+ .ge { color: $solarized-light-ge; font-style: italic; } /* Generic.Emph */
+ .gr { color: $solarized-light-gr; } /* Generic.Error */
+ .gh { color: $solarized-light-gh; } /* Generic.Heading */
+ .gi { color: $solarized-light-gi; } /* Generic.Inserted */
+ .go { color: $solarized-light-go; } /* Generic.Output */
+ .gp { color: $solarized-light-gp; } /* Generic.Prompt */
+ .gs { color: $solarized-light-gs; font-weight: $gl-font-weight-bold; } /* Generic.Strong */
+ .gu { color: $solarized-light-gu; } /* Generic.Subheading */
+ .gt { color: $solarized-light-gt; } /* Generic.Traceback */
+ .kc { color: $solarized-light-kc; } /* Keyword.Constant */
+ .kd { color: $solarized-light-kd; } /* Keyword.Declaration */
+ .kn { color: $solarized-light-kn; } /* Keyword.Namespace */
+ .kp { color: $solarized-light-kp; } /* Keyword.Pseudo */
+ .kr { color: $solarized-light-kr; } /* Keyword.Reserved */
+ .kt { color: $solarized-light-kt; } /* Keyword.Type */
+ .ld { color: $solarized-light-ld; } /* Literal.Date */
+ .m { color: $solarized-light-m; } /* Literal.Number */
+ .s { color: $solarized-light-s; } /* Literal.String */
+ .na { color: $solarized-light-na; } /* Name.Attribute */
+ .nb { color: $solarized-light-nb; } /* Name.Builtin */
+ .nc { color: $solarized-light-nc; } /* Name.Class */
+ .no { color: $solarized-light-no; } /* Name.Constant */
+ .nd { color: $solarized-light-nd; } /* Name.Decorator */
+ .ni { color: $solarized-light-ni; } /* Name.Entity */
+ .ne { color: $solarized-light-ne; } /* Name.Exception */
+ .nf { color: $solarized-light-nf; } /* Name.Function */
+ .nl { color: $solarized-light-nl; } /* Name.Label */
+ .nn { color: $solarized-light-nn; } /* Name.Namespace */
+ .nx { color: $solarized-light-nx; } /* Name.Other */
+ .py { color: $solarized-light-py; } /* Name.Property */
+ .nt { color: $solarized-light-nt; } /* Name.Tag */
+ .nv { color: $solarized-light-nv; } /* Name.Variable */
+ .ow { color: $solarized-light-ow; } /* Operator.Word */
+ .w { color: $solarized-light-w; } /* Text.Whitespace */
+ .mf { color: $solarized-light-mf; } /* Literal.Number.Float */
+ .mh { color: $solarized-light-mh; } /* Literal.Number.Hex */
+ .mi { color: $solarized-light-mi; } /* Literal.Number.Integer */
+ .mo { color: $solarized-light-mo; } /* Literal.Number.Oct */
+ .sb { color: $solarized-light-sb; } /* Literal.String.Backtick */
+ .sc { color: $solarized-light-sc; } /* Literal.String.Char */
+ .sd { color: $solarized-light-sd; } /* Literal.String.Doc */
+ .s2 { color: $solarized-light-s2; } /* Literal.String.Double */
+ .se { color: $solarized-light-se; } /* Literal.String.Escape */
+ .sh { color: $solarized-light-sh; } /* Literal.String.Heredoc */
+ .si { color: $solarized-light-si; } /* Literal.String.Interpol */
+ .sx { color: $solarized-light-sx; } /* Literal.String.Other */
+ .sr { color: $solarized-light-sr; } /* Literal.String.Regex */
+ .s1 { color: $solarized-light-s1; } /* Literal.String.Single */
+ .ss { color: $solarized-light-ss; } /* Literal.String.Symbol */
+ .bp { color: $solarized-light-bp; } /* Name.Builtin.Pseudo */
+ .vc { color: $solarized-light-vc; } /* Name.Variable.Class */
+ .vg { color: $solarized-light-vg; } /* Name.Variable.Global */
+ .vi { color: $solarized-light-vi; } /* Name.Variable.Instance */
+ .il { color: $solarized-light-il; } /* Literal.Number.Integer.Long */
+}
diff --git a/app/assets/stylesheets/highlight/themes/white.scss b/app/assets/stylesheets/highlight/themes/white.scss
new file mode 100644
index 00000000000..7239086f649
--- /dev/null
+++ b/app/assets/stylesheets/highlight/themes/white.scss
@@ -0,0 +1,3 @@
+.code.white {
+ @import "../white_base";
+}
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
deleted file mode 100644
index 355c8d223f7..00000000000
--- a/app/assets/stylesheets/highlight/white.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.code.white {
- @import "white_base";
-}
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index 90a5250c247..ee0ec94c636 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -1,5 +1,7 @@
/* https://github.com/aahan/pygments-github-style */
+@import './common';
+
/*
* White Syntax Colors
*/
@@ -35,16 +37,16 @@ $white-kt: #458;
$white-m: #099;
$white-s: #d14;
$white-n: #333;
-$white-na: teal;
+$white-na: #008080;
$white-nb: #0086b3;
$white-nc: #458;
-$white-no: teal;
-$white-ni: purple;
+$white-no: #008080;
+$white-ni: #800080;
$white-ne: #900;
$white-nf: #900;
$white-nn: #555;
-$white-nt: navy;
-$white-nv: teal;
+$white-nt: #000080;
+$white-nv: #008080;
$white-w: #bbb;
$white-mf: #099;
$white-mh: #099;
@@ -62,20 +64,20 @@ $white-sr: #009926;
$white-s1: #d14;
$white-ss: #990073;
$white-bp: #999;
-$white-vc: teal;
-$white-vg: teal;
-$white-vi: teal;
+$white-vc: #008080;
+$white-vg: #008080;
+$white-vi: #008080;
$white-il: #099;
$white-gc-color: #999;
$white-gc-bg: #eaf2f5;
-@mixin matchLine {
+@mixin match-line {
color: $black-transparent;
background-color: $gray-light;
}
- // Line numbers
+// Line numbers
.line-numbers,
.diff-line-num {
background-color: $gray-light;
@@ -101,11 +103,10 @@ pre.code,
// Diff line
.line_holder {
-
&.match .line_content,
.new-nonewline.line_content,
.old-nonewline.line_content {
- @include matchLine;
+ @include match-line;
}
.diff-line-num {
@@ -185,7 +186,7 @@ pre.code,
}
&.match {
- @include matchLine;
+ @include match-line;
}
&.hll:not(.empty-cell) {
@@ -199,25 +200,38 @@ pre .hll {
background-color: $white-pre-hll-bg !important;
}
- // Search result highlight
+// Search result highlight
span.highlight_word {
background-color: $white-highlight !important;
}
- // Links to URLs, emails, or dependencies
+// Links to URLs, emails, or dependencies
.line a {
color: $white-nb;
}
.hll { background-color: $white-hll-bg; }
-.c { color: $white-c; font-style: italic; }
-.err { color: $white-err; background-color: $white-err-bg; }
+
+.c { color: $white-c;
+ font-style: italic; }
+
+.err { color: $white-err;
+ background-color: $white-err-bg; }
.k { font-weight: $gl-font-weight-bold; }
.o { font-weight: $gl-font-weight-bold; }
-.cm { color: $white-cm; font-style: italic; }
-.cp { color: $white-cp; font-weight: $gl-font-weight-bold; }
-.c1 { color: $white-c1; font-style: italic; }
-.cs { color: $white-cs; font-weight: $gl-font-weight-bold; font-style: italic; }
+
+.cm { color: $white-cm;
+ font-style: italic; }
+
+.cp { color: $white-cp;
+ font-weight: $gl-font-weight-bold; }
+
+.c1 { color: $white-c1;
+ font-style: italic; }
+
+.cs { color: $white-cs;
+ font-weight: $gl-font-weight-bold;
+ font-style: italic; }
.gd {
color: $white-gd;
@@ -246,24 +260,34 @@ span.highlight_word {
.go { color: $white-go; }
.gp { color: $white-gp; }
.gs { font-weight: $gl-font-weight-bold; }
-.gu { color: $white-gu; font-weight: $gl-font-weight-bold; }
+
+.gu { color: $white-gu;
+ font-weight: $gl-font-weight-bold; }
.gt { color: $white-gt; }
.kc { font-weight: $gl-font-weight-bold; }
.kd { font-weight: $gl-font-weight-bold; }
.kn { font-weight: $gl-font-weight-bold; }
.kp { font-weight: $gl-font-weight-bold; }
.kr { font-weight: $gl-font-weight-bold; }
-.kt { color: $white-kt; font-weight: $gl-font-weight-bold; }
+
+.kt { color: $white-kt;
+ font-weight: $gl-font-weight-bold; }
.m { color: $white-m; }
.s { color: $white-s; }
.n { color: $white-n; }
.na { color: $white-na; }
.nb { color: $white-nb; }
-.nc { color: $white-nc; font-weight: $gl-font-weight-bold; }
+
+.nc { color: $white-nc;
+ font-weight: $gl-font-weight-bold; }
.no { color: $white-no; }
.ni { color: $white-ni; }
-.ne { color: $white-ne; font-weight: $gl-font-weight-bold; }
-.nf { color: $white-nf; font-weight: $gl-font-weight-bold; }
+
+.ne { color: $white-ne;
+ font-weight: $gl-font-weight-bold; }
+
+.nf { color: $white-nf;
+ font-weight: $gl-font-weight-bold; }
.nn { color: $white-nn; }
.nt { color: $white-nt; }
.nv { color: $white-nv; }
@@ -289,4 +313,6 @@ span.highlight_word {
.vg { color: $white-vg; }
.vi { color: $white-vi; }
.il { color: $white-il; }
-.gc { color: $white-gc-color; background-color: $white-gc-bg; }
+
+.gc { color: $white-gc-color;
+ background-color: $white-gc-bg; }
diff --git a/app/assets/stylesheets/mailers/highlighted_diff_email.scss b/app/assets/stylesheets/mailers/highlighted_diff_email.scss
index 8b234a5a656..33c114838c2 100644
--- a/app/assets/stylesheets/mailers/highlighted_diff_email.scss
+++ b/app/assets/stylesheets/mailers/highlighted_diff_email.scss
@@ -1,4 +1,4 @@
-@import "framework/variables";
+@import 'framework/variables';
// This file is largely copied from `highlight/white.scss`, but modified to
// avoid all descendant selectors (`table td`). This is because the CSS inlining
@@ -40,16 +40,16 @@ $highlighted-kt: #458;
$highlighted-m: #099;
$highlighted-s: #d14;
$highlighted-n: #333;
-$highlighted-na: teal;
+$highlighted-na: #008080;
$highlighted-nb: #0086b3;
$highlighted-nc: #458;
-$highlighted-no: teal;
-$highlighted-ni: purple;
+$highlighted-no: #008080;
+$highlighted-ni: #800080;
$highlighted-ne: #900;
$highlighted-nf: #900;
$highlighted-nn: #555;
-$highlighted-nt: navy;
-$highlighted-nv: teal;
+$highlighted-nt: #000080;
+$highlighted-nv: #008080;
$highlighted-w: #bbb;
$highlighted-mf: #099;
$highlighted-mh: #099;
@@ -67,9 +67,9 @@ $highlighted-sr: #009926;
$highlighted-s1: #d14;
$highlighted-ss: #990073;
$highlighted-bp: #999;
-$highlighted-vc: teal;
-$highlighted-vg: teal;
-$highlighted-vi: teal;
+$highlighted-vc: #008080;
+$highlighted-vg: #008080;
+$highlighted-vi: #008080;
$highlighted-il: #099;
$highlighted-gc: #999;
$highlighted-gc-bg: #eaf2f5;
@@ -151,14 +151,27 @@ span.highlight_word {
}
.hll { background-color: $highlighted-hll-bg; }
-.c { color: $highlighted-c; font-style: italic; }
-.err { color: $highlighted-err; background-color: $highlighted-err-bg; }
+
+.c { color: $highlighted-c;
+ font-style: italic; }
+
+.err { color: $highlighted-err;
+ background-color: $highlighted-err-bg; }
.k { font-weight: $gl-font-weight-bold; }
.o { font-weight: $gl-font-weight-bold; }
-.cm { color: $highlighted-cm; font-style: italic; }
-.cp { color: $highlighted-cp; font-weight: $gl-font-weight-bold; }
-.c1 { color: $highlighted-c1; font-style: italic; }
-.cs { color: $highlighted-cs; font-weight: $gl-font-weight-bold; font-style: italic; }
+
+.cm { color: $highlighted-cm;
+ font-style: italic; }
+
+.cp { color: $highlighted-cp;
+ font-weight: $gl-font-weight-bold; }
+
+.c1 { color: $highlighted-c1;
+ font-style: italic; }
+
+.cs { color: $highlighted-cs;
+ font-weight: $gl-font-weight-bold;
+ font-style: italic; }
.gd {
color: $highlighted-gd;
@@ -187,24 +200,34 @@ span.highlight_word {
.go { color: $highlighted-go; }
.gp { color: $highlighted-gp; }
.gs { font-weight: $gl-font-weight-bold; }
-.gu { color: $highlighted-gu; font-weight: $gl-font-weight-bold; }
+
+.gu { color: $highlighted-gu;
+ font-weight: $gl-font-weight-bold; }
.gt { color: $highlighted-gt; }
.kc { font-weight: $gl-font-weight-bold; }
.kd { font-weight: $gl-font-weight-bold; }
.kn { font-weight: $gl-font-weight-bold; }
.kp { font-weight: $gl-font-weight-bold; }
.kr { font-weight: $gl-font-weight-bold; }
-.kt { color: $highlighted-kt; font-weight: $gl-font-weight-bold; }
+
+.kt { color: $highlighted-kt;
+ font-weight: $gl-font-weight-bold; }
.m { color: $highlighted-m; }
.s { color: $highlighted-s; }
.n { color: $highlighted-n; }
.na { color: $highlighted-na; }
.nb { color: $highlighted-nb; }
-.nc { color: $highlighted-nc; font-weight: $gl-font-weight-bold; }
+
+.nc { color: $highlighted-nc;
+ font-weight: $gl-font-weight-bold; }
.no { color: $highlighted-no; }
.ni { color: $highlighted-ni; }
-.ne { color: $highlighted-ne; font-weight: $gl-font-weight-bold; }
-.nf { color: $highlighted-nf; font-weight: $gl-font-weight-bold; }
+
+.ne { color: $highlighted-ne;
+ font-weight: $gl-font-weight-bold; }
+
+.nf { color: $highlighted-nf;
+ font-weight: $gl-font-weight-bold; }
.nn { color: $highlighted-nn; }
.nt { color: $highlighted-nt; }
.nv { color: $highlighted-nv; }
@@ -230,4 +253,6 @@ span.highlight_word {
.vg { color: $highlighted-vg; }
.vi { color: $highlighted-vi; }
.il { color: $highlighted-il; }
-.gc { color: $highlighted-gc; background-color: $highlighted-gc-bg; }
+
+.gc { color: $highlighted-gc;
+ background-color: $highlighted-gc-bg; }
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index 98d0a2d43ea..a80158943c6 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -130,7 +130,7 @@ $ide-commit-header-height: 48px;
background: none;
border: 0;
border-radius: $border-radius-default;
- color: $theme-gray-900;
+ color: $gray-900;
svg {
position: relative;
@@ -145,7 +145,7 @@ $ide-commit-header-height: 48px;
}
&:not([disabled]):hover {
- background-color: $theme-gray-200;
+ background-color: $gray-200;
}
&:not([disabled]):focus {
@@ -265,7 +265,7 @@ $ide-commit-header-height: 48px;
.margin {
background-color: $white-light;
- border-right: 1px solid $theme-gray-100;
+ border-right: 1px solid $gray-100;
.line-insert {
border-right: 1px solid $line-added-dark;
@@ -292,7 +292,7 @@ $ide-commit-header-height: 48px;
.monaco-editor,
.monaco-editor-background,
.monaco-editor .inputarea.ime-input {
- background-color: $theme-gray-50;
+ background-color: $gray-50;
}
}
}
@@ -395,6 +395,11 @@ $ide-commit-header-height: 48px;
svg {
vertical-align: sub;
}
+
+ .ide-status-avatar {
+ float: none;
+ margin: 0 0 1px;
+ }
}
.ide-status-file {
@@ -527,7 +532,7 @@ $ide-commit-header-height: 48px;
display: block;
margin-left: auto;
margin-right: auto;
- color: $theme-gray-700;
+ color: $gray-700;
}
.file-status-icon {
@@ -551,7 +556,7 @@ $ide-commit-header-height: 48px;
&:hover,
&:focus {
- background: $theme-gray-100;
+ background: $gray-100;
outline: 0;
@@ -563,7 +568,7 @@ $ide-commit-header-height: 48px;
}
&:active {
- background: $theme-gray-200;
+ background: $gray-200;
}
&.is-active {
@@ -677,25 +682,6 @@ $ide-commit-header-height: 48px;
flex: 1;
}
-.drag-handle {
- position: absolute;
- top: 0;
- bottom: 0;
- width: 4px;
-
- &:hover {
- background-color: $white-normal;
- }
-
- &.drag-right {
- right: 0;
- }
-
- &.drag-left {
- left: 0;
- }
-}
-
.ide-commit-list-container {
display: flex;
flex: 1;
@@ -767,12 +753,12 @@ $ide-commit-header-height: 48px;
&:hover {
color: $gl-text-color;
- background-color: $theme-gray-100;
+ background-color: $gray-100;
}
&:focus {
color: $gl-text-color;
- background-color: $theme-gray-200;
+ background-color: $gray-200;
}
&.active {
@@ -811,26 +797,6 @@ $ide-commit-header-height: 48px;
z-index: 1;
}
-.ide-file-finder-overlay {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 100;
-}
-
-.ide-file-finder {
- top: 10px;
- left: 50%;
- transform: translateX(-50%);
-
- .highlighted {
- color: $blue-500;
- font-weight: $gl-font-weight-bold;
- }
-}
-
.ide-commit-message-field {
height: 200px;
background-color: $white-light;
@@ -1273,10 +1239,10 @@ $ide-commit-header-height: 48px;
.ide-entry-dropdown-toggle {
padding: $gl-padding-4;
color: $gl-text-color;
- background-color: $theme-gray-100;
+ background-color: $gray-100;
&:hover {
- background-color: $theme-gray-200;
+ background-color: $gray-200;
}
&:active,
@@ -1331,7 +1297,7 @@ $ide-commit-header-height: 48px;
&:focus {
outline: 0;
box-shadow: none;
- border-color: $theme-gray-200;
+ border-color: $gray-200;
}
}
@@ -1358,7 +1324,7 @@ $ide-commit-header-height: 48px;
.ide-commit-editor-header {
height: 65px;
padding: 8px 16px;
- background-color: $theme-gray-50;
+ background-color: $gray-50;
box-shadow: inset 0 -1px $white-dark;
}
@@ -1370,7 +1336,7 @@ $ide-commit-header-height: 48px;
.ide-file-icon-holder {
display: flex;
align-items: center;
- color: $theme-gray-700;
+ color: $gray-700;
}
.file-row:hover,
diff --git a/app/assets/stylesheets/page_bundles/xterm.scss b/app/assets/stylesheets/page_bundles/xterm.scss
index 7f040ac9b96..de3f2a1177d 100644
--- a/app/assets/stylesheets/page_bundles/xterm.scss
+++ b/app/assets/stylesheets/page_bundles/xterm.scss
@@ -6,11 +6,11 @@
$black: #000;
$red: #ea1010;
- $green: #009900;
- $yellow: #999900;
+ $green: #090;
+ $yellow: #990;
$blue: #0073e6;
$magenta: #d411d4;
- $cyan: #009999;
+ $cyan: #099;
$white: #ccc;
$l-black: #373b41;
$l-red: #ff6161;
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index 37984a8666f..81216b2b98e 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -3,7 +3,6 @@
}
.user-can-drag {
- cursor: -webkit-grab;
cursor: grab;
}
@@ -12,12 +11,8 @@
opacity: 1 !important;
* {
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
user-select: none;
// !important to make sure no style can override this when dragging
- cursor: -webkit-grabbing !important;
cursor: grabbing !important;
}
}
@@ -26,13 +21,15 @@
opacity: 0.3;
}
+.dropdown-projects {
+ .dropdown-content {
+ max-height: 200px;
+ }
+}
+
.dropdown-menu-issues-board-new {
width: 320px;
- .open & {
- max-height: 400px;
- }
-
.dropdown-content {
max-height: 162px;
}
@@ -162,6 +159,13 @@
display: none;
}
}
+
+ &:not(.is-collapsed) {
+ .board-list-component {
+ display: flex;
+ flex-direction: column;
+ }
+ }
}
.board-inner {
@@ -171,6 +175,7 @@
background: $gray-light;
border: 1px solid $border-color;
border-radius: $border-radius-default;
+ flex: 1;
}
.board-header {
@@ -232,9 +237,11 @@
}
.board-blank-state {
- height: calc(100% - 49px);
padding: $gl-padding;
background-color: $white-light;
+ flex: 1;
+ overflow-y: auto;
+ overflow-x: hidden;
}
.board-blank-state-list {
@@ -256,9 +263,9 @@
}
.board-list-component {
- height: calc(100% - 49px);
- overflow: hidden;
position: relative;
+ flex: 1;
+ min-height: 0; // firefox fix
}
.board-list {
@@ -281,7 +288,7 @@
padding: $gl-padding;
background: $white-light;
border-radius: $border-radius-default;
- border: 1px solid $theme-gray-200;
+ border: 1px solid $gray-200;
box-shadow: 0 1px 2px $issue-boards-card-shadow;
list-style: none;
line-height: $gl-padding;
@@ -489,7 +496,6 @@
}
.add-issues-modal {
- display: -webkit-flex;
display: flex;
position: fixed;
top: 0;
@@ -501,9 +507,7 @@
}
.add-issues-container {
- display: -webkit-flex;
display: flex;
- -webkit-flex-direction: column;
flex-direction: column;
width: 90vw;
height: 85vh;
@@ -516,16 +520,12 @@
box-shadow: 0 2px 12px rgba($black, 0.5);
.empty-state {
- display: -webkit-flex;
display: flex;
- -webkit-flex: 1;
flex: 1;
margin-top: 0;
&.add-issues-empty-state-filter {
- -webkit-flex-direction: column;
flex-direction: column;
- -webkit-justify-content: center;
justify-content: center;
}
@@ -554,11 +554,9 @@
}
.add-issues-search {
- display: -webkit-flex;
display: flex;
.issues-filters {
- -webkit-flex: 1;
flex: 1;
}
}
@@ -576,9 +574,7 @@
}
.add-issues-list {
- display: -webkit-flex;
display: flex;
- -webkit-flex: 1;
flex: 1;
padding-top: 3px;
margin-left: -$gl-vert-padding;
@@ -597,7 +593,6 @@
}
.add-issues-list-loading {
- -webkit-align-self: center;
align-self: center;
width: 100%;
padding-left: $gl-vert-padding;
@@ -673,7 +668,7 @@
}
.board-card-info-icon {
- color: $theme-gray-600;
+ color: $gray-600;
margin-right: $gl-padding-4;
}
diff --git a/app/assets/stylesheets/pages/branches.scss b/app/assets/stylesheets/pages/branches.scss
index 38fec3f0aa8..ce0622b3d48 100644
--- a/app/assets/stylesheets/pages/branches.scss
+++ b/app/assets/stylesheets/pages/branches.scss
@@ -11,15 +11,24 @@
}
.divergence-graph {
+ $graph-side-width: 80px;
+ $graph-separator-width: 1px;
+
padding: 0 6px;
.graph-side {
position: relative;
- width: 80px;
+ width: $graph-side-width;
height: 22px;
padding: 5px 0 13px;
float: left;
+ &.full {
+ width: $graph-side-width * 2 + $graph-separator-width;
+ display: flex;
+ justify-content: center;
+ }
+
.bar {
position: absolute;
height: 4px;
@@ -57,7 +66,7 @@
.graph-separator {
position: relative;
- width: 1px;
+ width: $graph-separator-width;
height: 18px;
margin: 5px 0 0;
float: left;
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index 09235661cea..fa5a182243c 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -55,16 +55,16 @@
@include build-trace();
}
- .archived-sticky {
+ .archived-job {
top: $header-height;
border-radius: 2px 2px 0 0;
color: $orange-600;
background-color: $orange-100;
border: 1px solid $border-gray-normal;
- border-bottom: 0;
padding: 3px 12px;
margin: auto;
align-items: center;
+ z-index: 1;
.with-performance-bar & {
top: $header-height + $performance-bar-height;
@@ -75,7 +75,11 @@
@include build-trace-top-bar(35px);
&.has-archived-block {
- top: $header-height + $performance-bar-height + 28px;
+ top: $header-height + 28px;
+
+ .with-performance-bar & {
+ top: $header-height + $performance-bar-height + 28px;
+ }
}
&.affix {
@@ -261,7 +265,7 @@
.trigger-variables-table-cell {
font-size: $gl-font-size-small;
line-height: $gl-line-height;
- border: 1px solid $theme-gray-200;
+ border: 1px solid $gray-200;
padding: $gl-padding-4 6px;
width: 50%;
vertical-align: top;
@@ -272,7 +276,13 @@
}
.retry-link {
- display: none;
+ display: block;
+
+ .btn {
+ i {
+ margin-left: 5px;
+ }
+ }
.btn-inverted-secondary {
color: $blue-500;
@@ -281,16 +291,6 @@
color: $white-light;
}
}
-
- @include media-breakpoint-down(sm) {
- display: block;
-
- .btn {
- i {
- margin-left: 5px;
- }
- }
- }
}
.stage-item {
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
index ad12cd101b6..809ba6d4953 100644
--- a/app/assets/stylesheets/pages/clusters.scss
+++ b/app/assets/stylesheets/pages/clusters.scss
@@ -58,6 +58,20 @@
}
}
+.cluster-application-banner {
+ height: 45px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.cluster-application-banner-close {
+ align-self: flex-start;
+ font-weight: 500;
+ font-size: 20px;
+ margin: $gl-padding-8 14px 0 0;
+}
+
.cluster-application-description {
flex: 1;
}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 11966931a6c..670e320dbc2 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -342,11 +342,11 @@
}
&.invalid {
- @include status-color($gray-dark, color("gray"), $gray-darkest);
+ @include status-color($gray-dark, color('gray'), $gray-darkest);
border-color: $gray-darkest;
&:not(span):hover {
- color: color("gray");
+ color: color('gray');
}
}
}
diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss
index ec2108b15be..2b932d164a5 100644
--- a/app/assets/stylesheets/pages/cycle_analytics.scss
+++ b/app/assets/stylesheets/pages/cycle_analytics.scss
@@ -330,7 +330,6 @@
// Custom Styles for stage items
.item-build-component {
-
.item-title {
.icon-build-status {
float: left;
diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss
index 37ed5ae674a..cb5f1a84005 100644
--- a/app/assets/stylesheets/pages/detail_page.scss
+++ b/app/assets/stylesheets/pages/detail_page.scss
@@ -34,7 +34,6 @@
.detail-page-header-actions {
align-self: center;
- flex-shrink: 0;
flex: 0 0 auto;
@include media-breakpoint-down(xs) {
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 18c62cb4f1e..0dbbe9e4c25 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -7,21 +7,12 @@
cursor: pointer;
@media (min-width: map-get($grid-breakpoints, md)) {
- position: -webkit-sticky;
+ $mr-file-header-top: $mr-version-controls-height + $header-height + $mr-tabs-height;
+
position: sticky;
- top: 92px;
- margin-left: -1px;
- border-left: 1px solid $border-color;
+ top: $mr-file-header-top;
z-index: 102;
- &.is-commit {
- top: $header-height + 36px;
-
- .with-performance-bar & {
- top: $header-height + 36px + $performance-bar-height;
- }
- }
-
&::before {
content: '';
position: absolute;
@@ -34,7 +25,23 @@
}
.with-performance-bar & {
- top: 127px;
+ top: $mr-file-header-top + $performance-bar-height;
+ }
+
+ &.is-commit {
+ top: $header-height + $commit-stat-summary-height;
+
+ .with-performance-bar & {
+ top: $header-height + $commit-stat-summary-height + $performance-bar-height;
+ }
+ }
+
+ &.is-compare {
+ top: $header-height + $compare-branches-sticky-header-height;
+
+ .with-performance-bar & {
+ top: $performance-bar-height + $header-height + $compare-branches-sticky-header-height;
+ }
}
}
@@ -231,22 +238,18 @@
img {
border: 1px solid $white-light;
- background-image: linear-gradient(
- 45deg,
- $border-color 25%,
- transparent 25%,
- transparent 75%,
- $border-color 75%,
- $border-color 100%
- ),
- linear-gradient(
- 45deg,
- $border-color 25%,
- transparent 25%,
- transparent 75%,
- $border-color 75%,
- $border-color 100%
- );
+ background-image: linear-gradient(45deg,
+ $border-color 25%,
+ transparent 25%,
+ transparent 75%,
+ $border-color 75%,
+ $border-color 100%),
+ linear-gradient(45deg,
+ $border-color 25%,
+ transparent 25%,
+ transparent 75%,
+ $border-color 75%,
+ $border-color 100%);
background-size: 10px 10px;
background-position: 0 0, 5px 5px;
max-width: 100%;
@@ -500,6 +503,25 @@
}
}
+.diff-stats {
+ align-items: center;
+ padding: 0 0.25rem;
+
+ .diff-stats-group {
+ padding: 0 0.25rem;
+ }
+
+ svg.diff-stats-icon {
+ vertical-align: text-bottom;
+ }
+
+ &.is-compare-versions-header {
+ .diff-stats-group {
+ padding: 0 0.5rem;
+ }
+ }
+}
+
.file-content .diff-file {
margin: 0;
border: 0;
@@ -575,18 +597,6 @@
}
}
-@mixin diff_background($background, $idiff, $border) {
- background: $background;
-
- &.line_content span.idiff {
- background: $idiff;
- }
-
- &.diff-line-num {
- border-color: $border;
- }
-}
-
.files {
.diff-file:last-child {
margin-bottom: 0;
@@ -711,7 +721,6 @@
}
@include media-breakpoint-up(sm) {
- position: -webkit-sticky;
position: sticky;
top: $header-height;
background-color: $white-light;
@@ -819,34 +828,26 @@
width: 100%;
height: 10px;
background-color: $white-light;
- background-image: linear-gradient(
- 45deg,
- transparent,
- transparent 73%,
- $diff-jagged-border-gradient-color 75%,
- $white-light 80%
- ),
- linear-gradient(
- 225deg,
- transparent,
- transparent 73%,
- $diff-jagged-border-gradient-color 75%,
- $white-light 80%
- ),
- linear-gradient(
- 135deg,
- transparent,
- transparent 73%,
- $diff-jagged-border-gradient-color 75%,
- $white-light 80%
- ),
- linear-gradient(
- -45deg,
- transparent,
- transparent 73%,
- $diff-jagged-border-gradient-color 75%,
- $white-light 80%
- );
+ background-image: linear-gradient(45deg,
+ transparent,
+ transparent 73%,
+ $diff-jagged-border-gradient-color 75%,
+ $white-light 80%),
+ linear-gradient(225deg,
+ transparent,
+ transparent 73%,
+ $diff-jagged-border-gradient-color 75%,
+ $white-light 80%),
+ linear-gradient(135deg,
+ transparent,
+ transparent 73%,
+ $diff-jagged-border-gradient-color 75%,
+ $white-light 80%),
+ linear-gradient(-45deg,
+ transparent,
+ transparent 73%,
+ $diff-jagged-border-gradient-color 75%,
+ $white-light 80%);
background-position: 5px 5px, 0 5px, 0 5px, 5px 5px;
background-size: 10px 10px;
background-repeat: repeat;
@@ -889,7 +890,7 @@
}
}
-.files:not([data-can-create-note="true"]) .frame {
+.files:not([data-can-create-note='true']) .frame {
cursor: auto;
}
@@ -898,15 +899,14 @@
.btn-transparent.image-diff-overlay-add-comment {
position: relative;
cursor: image-url('illustrations/image_comment_light_cursor.svg')
- $image-comment-cursor-left-offset $image-comment-cursor-top-offset,
+ $image-comment-cursor-left-offset $image-comment-cursor-top-offset,
auto;
// Retina cursor
- cursor: -webkit-image-set(
- image-url('illustrations/image_comment_light_cursor.svg') 1x,
- image-url('illustrations/image_comment_light_cursor@2x.svg') 2x
- )
- $image-comment-cursor-left-offset $image-comment-cursor-top-offset,
+ // scss-lint:disable DuplicateProperty
+ cursor: image-set(image-url('illustrations/image_comment_light_cursor.svg') 1x,
+ image-url('illustrations/image_comment_light_cursor@2x.svg') 2x)
+ $image-comment-cursor-left-offset $image-comment-cursor-top-offset,
auto;
.comment-indicator {
@@ -1011,12 +1011,29 @@
}
.diff-tree-list {
- width: 320px;
+ position: sticky;
+ $top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + 10px;
+ top: $header-height + $mr-tabs-height + $mr-version-controls-height + 10px;
+ max-height: calc(100vh - #{$top-pos});
+ padding-right: $gl-padding;
+ z-index: 202;
+
+ .with-performance-bar & {
+ $performance-bar-top-pos: $performance-bar-height + $top-pos;
+ top: $performance-bar-top-pos;
+ max-height: calc(100vh - #{$performance-bar-top-pos});
+ }
+
+ .drag-handle {
+ bottom: 16px;
+ transform: translateX(-6px);
+ }
}
.diff-files-holder {
flex: 1;
min-width: 0;
+ z-index: 201;
}
.compare-versions-container {
@@ -1024,21 +1041,12 @@
}
.tree-list-holder {
- position: -webkit-sticky;
- position: sticky;
- top: 100px;
- max-height: calc(100vh - 100px);
- padding-right: $gl-padding;
+ height: 100%;
.file-row {
margin-left: 0;
margin-right: 0;
}
-
- .with-performance-bar & {
- top: 135px;
- max-height: calc(100vh - 135px);
- }
}
.tree-list-scroll {
@@ -1092,12 +1100,6 @@
}
}
-.tree-list-view-toggle {
- svg {
- top: 0;
- }
-}
-
.image-diff-overlay,
.image-diff-overlay-add-comment {
top: 0;
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index f46ff360496..655b297295a 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -128,6 +128,10 @@
width: 100%;
}
}
+
+ @media(max-width: map-get($grid-breakpoints, md)-1) {
+ clear: both;
+ }
}
.editor-ref {
@@ -178,9 +182,8 @@
.template-selector-dropdowns-wrap {
display: inline-block;
- margin-left: 8px;
- vertical-align: top;
margin: 5px 0 0 8px;
+ vertical-align: top;
@media(max-width: map-get($grid-breakpoints, md)-1) {
display: block;
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index 75166ffcada..61ecf133b02 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -240,18 +240,7 @@
}
.prometheus-graph {
- flex: 1 0 auto;
- min-width: 450px;
- max-width: 100%;
padding: $gl-padding / 2;
-
- h5 {
- font-size: 16px;
- }
-
- @include media-breakpoint-down(sm) {
- min-width: 100%;
- }
}
.prometheus-graph-header {
@@ -261,13 +250,14 @@
margin-bottom: $gl-padding-8;
h5 {
+ font-size: $gl-font-size-large;
margin: 0;
}
}
.prometheus-graph-cursor {
position: absolute;
- background: $theme-gray-600;
+ background: $gray-600;
width: 1px;
}
@@ -309,7 +299,7 @@
> .arrow::after {
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
- border-left: 4px solid $theme-gray-50;
+ border-left: 4px solid $gray-50;
}
.arrow-shadow {
@@ -331,7 +321,7 @@
> .arrow::after {
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
- border-right: 4px solid $theme-gray-50;
+ border-right: 4px solid $gray-50;
}
.arrow-shadow {
@@ -364,7 +354,7 @@
}
> .popover-title {
- background-color: $theme-gray-50;
+ background-color: $gray-50;
border-radius: $border-radius-default $border-radius-default 0 0;
}
}
@@ -439,7 +429,7 @@
}
> text {
- fill: $theme-gray-600;
+ fill: $gray-600;
font-size: 10px;
}
}
@@ -482,5 +472,5 @@
}
.prometheus-table-row-highlight {
- background-color: $theme-gray-100;
+ background-color: $gray-100;
}
diff --git a/app/assets/stylesheets/pages/graph.scss b/app/assets/stylesheets/pages/graph.scss
index 4fb1a956fab..3febf4cf826 100644
--- a/app/assets/stylesheets/pages/graph.scss
+++ b/app/assets/stylesheets/pages/graph.scss
@@ -44,7 +44,7 @@
}
.x-axis-text {
- fill: $theme-gray-900;
+ fill: $gray-900;
}
.bar-rect {
@@ -64,19 +64,17 @@
text {
font-weight: bold;
font-size: 12px;
- fill: $theme-gray-800;
+ fill: $gray-800;
}
}
}
.svg-graph-container-with-grab {
cursor: grab;
- cursor: -webkit-grab;
}
.svg-graph-container-grabbed {
cursor: grabbing;
- cursor: -webkit-grabbing;
}
@keyframes flickerAnimation {
@@ -87,5 +85,5 @@
.animate-flicker {
animation: flickerAnimation 1.5s infinite;
- fill: $theme-gray-500;
+ fill: $gray-500;
}
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index f0cb81e0bc3..8ade995525a 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -29,9 +29,7 @@
}
}
-.group-nav-container .group-search,
.group-nav-container .nav-controls {
- display: flex;
align-items: flex-start;
padding: $gl-padding-top 0 0;
@@ -44,6 +42,52 @@
margin-top: 0;
}
+ @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%;
+ }
+
+ .dropdown .dropdown-toggle .fa-chevron-down {
+ position: absolute;
+ top: 11px;
+ right: 8px;
+ }
+ }
+}
+
+.home-panel-buttons {
+ .home-panel-action-button {
+ vertical-align: top;
+ }
+
+
+ .notification-dropdown {
+ .dropdown-menu {
+ @extend .dropdown-menu-right;
+ }
+
+ .icon {
+ fill: $gl-text-color-secondary;
+ }
+ }
+
.new-project-subgroup {
.dropdown-primary {
min-width: 115px;
@@ -78,7 +122,7 @@
&:hover {
background-color: $gray-darker;
- color: $theme-gray-900;
+ color: $gray-900;
}
}
@@ -99,61 +143,29 @@
font-weight: $gl-font-weight-bold;
}
}
- }
- }
-
- @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,
- .dropdown .dropdown-toggle,
- .btn-success {
- width: 100%;
- }
-
- .dropdown .dropdown-toggle .fa-chevron-down {
- position: absolute;
- top: 11px;
- right: 8px;
- }
-
- .new-project-subgroup {
- display: flex;
- align-items: flex-start;
+ @include media-breakpoint-down(sm) {
+ display: flex;
+ align-items: flex-start;
- .dropdown-primary {
- flex: 1;
- }
+ .dropdown-primary {
+ flex: 1;
+ }
- .dropdown-toggle {
- width: auto;
- }
+ .dropdown-toggle {
+ width: auto;
+ }
- .dropdown-menu {
- width: 100%;
- max-width: inherit;
- min-width: inherit;
+ .dropdown-menu {
+ width: 100%;
+ max-width: inherit;
+ min-width: inherit;
+ }
}
}
}
}
-.group-nav-container .group-search {
- padding: $gl-padding 0;
- border-bottom: 1px solid $border-color;
-}
-
.groups-listing {
.group-list-tree .group-row:first-child {
border-top: 0;
diff --git a/app/assets/stylesheets/pages/help.scss b/app/assets/stylesheets/pages/help.scss
index 2c23f31c240..161d4dbfb22 100644
--- a/app/assets/stylesheets/pages/help.scss
+++ b/app/assets/stylesheets/pages/help.scss
@@ -30,7 +30,7 @@
.key {
@extend .badge.badge-pill;
background-color: $label-inverse-bg;
- font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ font: 11px Consolas, 'Liberation Mono', Menlo, Courier, monospace;
padding: 3px 5px;
}
}
diff --git a/app/assets/stylesheets/pages/import.scss b/app/assets/stylesheets/pages/import.scss
index a4f76a9495a..7f800367cad 100644
--- a/app/assets/stylesheets/pages/import.scss
+++ b/app/assets/stylesheets/pages/import.scss
@@ -1,20 +1,51 @@
-.import-jobs-from-col,
.import-jobs-to-col {
- width: 40%;
+ width: 39%;
}
.import-jobs-status-col {
- width: 20%;
+ width: 15%;
}
-.btn-import {
- .loading-icon {
- display: none;
+.import-jobs-cta-col {
+ width: 1%;
+}
+
+.import-project-name-input {
+ border-radius: 0 $border-radius-default $border-radius-default 0;
+ position: relative;
+ left: -1px;
+ max-width: 300px;
+}
+
+.import-namespace-select {
+ width: auto !important;
+
+ > .select2-choice {
+ border-radius: $border-radius-default 0 0 $border-radius-default;
+ position: relative;
+ left: 1px;
}
+}
- &.is-loading {
- .loading-icon {
- display: inline-block;
- }
+.import-slash-divider {
+ background-color: $gray-lightest;
+ border: 1px solid $border-color;
+}
+
+.import-row {
+ height: 55px;
+}
+
+.import-table {
+ .import-jobs-from-col,
+ .import-jobs-to-col,
+ .import-jobs-status-col,
+ .import-jobs-cta-col {
+ border-bottom-width: 1px;
+ padding-left: $gl-padding;
}
}
+
+.import-projects-loading-icon {
+ margin-top: $gl-padding-32;
+}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 5b5f486ea63..623fa485ba6 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -22,6 +22,7 @@
.detail-page-header,
.page-content-header,
.commit-box,
+ .info-well,
.commit-ci-menu,
.files-changed-inner,
.limited-header-width,
@@ -60,6 +61,10 @@
padding: 0;
margin-bottom: $gl-padding;
border-bottom: 0;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ min-width: 0;
+ width: 100%;
}
.btn-edit {
@@ -132,7 +137,7 @@
color: $blue-800;
.avatar {
- border-color: rgba($gray-normal, .2);
+ border-color: rgba($gray-normal, 0.2);
}
}
@@ -219,7 +224,7 @@
}
a.edit-link:not([href]):hover {
- color: rgba($gray-normal, .2);
+ color: rgba($gray-normal, 0.2);
}
.lock-edit, // uses same style, different js behaviour
@@ -707,14 +712,11 @@
.issuable-list {
li {
-
.issue-box {
- display: -webkit-flex;
display: flex;
}
.issuable-info-container {
- -webkit-flex: 1;
flex: 1;
display: flex;
padding-right: $gl-padding;
@@ -809,7 +811,6 @@
.sidebar-collapsed-icon {
-
> .stopwatch-svg {
display: inline-block;
}
@@ -867,11 +868,11 @@
}
.help-state-toggle-enter-active {
- transition: all .8s ease;
+ transition: all 0.8s ease;
}
.help-state-toggle-leave-active {
- transition: all .5s ease;
+ transition: all 0.5s ease;
}
.help-state-toggle-enter,
@@ -930,7 +931,7 @@
.sidebar-collapsed-divider {
line-height: 5px;
font-size: 12px;
- color: $theme-gray-700;
+ color: $gray-700;
+ .sidebar-collapsed-icon {
padding-top: 0;
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index bb6b6f84849..9f30495a7ef 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -58,8 +58,6 @@ form.edit-issue {
}
ul.related-merge-requests > li {
- display: -ms-flexbox;
- display: -webkit-flex;
display: flex;
align-items: center;
@@ -80,7 +78,6 @@ ul.related-merge-requests > li {
}
}
-.merge-requests-title,
.related-branches-title {
font-size: 16px;
font-weight: $gl-font-weight-bold;
@@ -91,23 +88,16 @@ ul.related-merge-requests > li {
}
.merge-request-status {
- font-size: 13px;
- padding: 0 5px;
- color: $white-light;
- height: 20px;
- border-radius: 3px;
- line-height: 18px;
-
&.merged {
- background: $blue-500;
+ color: $blue-500;
}
&.closed {
- background: $red-500;
+ color: $red-500;
}
&.open {
- background: $green-500;
+ color: $green-500;
}
}
@@ -155,6 +145,14 @@ ul.related-merge-requests > li {
}
}
+.issues-nav-controls {
+ font-size: 0;
+
+ .btn-group:empty {
+ display: none;
+ }
+}
+
.issuable-email-modal-btn {
padding: 0;
color: $blue-600;
diff --git a/app/assets/stylesheets/pages/issues/issue_count_badge.scss b/app/assets/stylesheets/pages/issues/issue_count_badge.scss
index 4fba89e956b..64ca61f7094 100644
--- a/app/assets/stylesheets/pages/issues/issue_count_badge.scss
+++ b/app/assets/stylesheets/pages/issues/issue_count_badge.scss
@@ -1,11 +1,13 @@
-.issue-count-badge {
+.issue-count-badge,
+.mr-count-badge {
display: inline-flex;
border-radius: $border-radius-base;
border: 1px solid $border-color;
padding: 5px $gl-padding-8;
}
-.issue-count-badge-count {
+.issue-count-badge-count,
+.mr-count-badge-count {
display: inline-flex;
align-items: center;
}
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index d2b9470be69..75d219320ef 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -82,7 +82,7 @@
justify-content: space-between;
padding: $gl-padding;
border-radius: $border-radius-default;
- border: 1px solid $theme-gray-100;
+ border: 1px solid $gray-100;
&:last-child {
margin-bottom: 0;
@@ -95,13 +95,11 @@
.prioritized-labels & {
box-shadow: 0 1px 2px $issue-boards-card-shadow;
cursor: move;
- cursor: -webkit-grab;
- cursor: -moz-grab;
+ cursor: grab;
border: 0;
&:active {
- cursor: -webkit-grabbing;
- cursor: -moz-grabbing;
+ cursor: grabbing;
}
}
}
@@ -257,7 +255,7 @@
}
.label-badge {
- color: $theme-gray-900;
+ color: $gray-900;
font-weight: $gl-font-weight-normal;
padding: $gl-padding-4 $gl-padding-8;
border-radius: $border-radius-default;
@@ -269,7 +267,7 @@
}
.label-badge-gray {
- background-color: $theme-gray-100;
+ background-color: $gray-100;
}
.label-links {
@@ -326,11 +324,11 @@
}
.label-action {
- color: $theme-gray-800;
+ color: $gray-800;
cursor: pointer;
svg {
- fill: $theme-gray-800;
+ fill: $gray-800;
}
&:hover {
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 67d7a8175ac..22a515cbdaa 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -120,7 +120,6 @@
}
.new-session-tabs {
- display: -webkit-flex;
display: flex;
box-shadow: 0 0 0 1px $border-color;
border-top-right-radius: $border-radius-default;
@@ -190,7 +189,7 @@
margin-top: 16px;
}
- input[type="submit"] {
+ input[type='submit'] {
@extend .btn-block;
margin-bottom: 0;
}
diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss
index 99609a96976..eb32beb0972 100644
--- a/app/assets/stylesheets/pages/members.scss
+++ b/app/assets/stylesheets/pages/members.scss
@@ -27,7 +27,6 @@
.controls {
@include media-breakpoint-up(sm) {
- display: -webkit-flex;
display: flex;
}
diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss
index e0f7d075fc7..278a9014458 100644
--- a/app/assets/stylesheets/pages/merge_conflicts.scss
+++ b/app/assets/stylesheets/pages/merge_conflicts.scss
@@ -20,81 +20,81 @@ $colors: (
white-header-not-chosen : #f0f0f0,
white-line-not-chosen : $gray-light,
- dark-header-head-neutral : rgba(#3f3, .2),
- dark-line-head-neutral : rgba(#3f3, .1),
+ dark-header-head-neutral : rgba(#3f3, 0.2),
+ dark-line-head-neutral : rgba(#3f3, 0.1),
dark-button-head-neutral : #40874f,
- dark-header-head-chosen : rgba(#3f3, .33),
- dark-line-head-chosen : rgba(#3f3, .2),
+ dark-header-head-chosen : rgba(#3f3, 0.33),
+ dark-line-head-chosen : rgba(#3f3, 0.2),
dark-button-head-chosen : #258537,
- dark-header-origin-neutral : rgba(#2878c9, .4),
- dark-line-origin-neutral : rgba(#2878c9, .3),
+ dark-header-origin-neutral : rgba(#2878c9, 0.4),
+ dark-line-origin-neutral : rgba(#2878c9, 0.3),
dark-button-origin-neutral : #2a5c8c,
- dark-header-origin-chosen : rgba(#2878c9, .6),
- dark-line-origin-chosen : rgba(#2878c9, .4),
+ dark-header-origin-chosen : rgba(#2878c9, 0.6),
+ dark-line-origin-chosen : rgba(#2878c9, 0.4),
dark-button-origin-chosen : #1d6cbf,
- dark-header-not-chosen : rgba(#fff, .25),
- dark-line-not-chosen : rgba(#fff, .1),
+ dark-header-not-chosen : rgba(#fff, 0.25),
+ dark-line-not-chosen : rgba(#fff, 0.1),
- monokai-header-head-neutral : rgba(#a6e22e, .25),
- monokai-line-head-neutral : rgba(#a6e22e, .1),
+ monokai-header-head-neutral : rgba(#a6e22e, 0.25),
+ monokai-line-head-neutral : rgba(#a6e22e, 0.1),
monokai-button-head-neutral : #376b20,
- monokai-header-head-chosen : rgba(#a6e22e, .4),
- monokai-line-head-chosen : rgba(#a6e22e, .25),
+ monokai-header-head-chosen : rgba(#a6e22e, 0.4),
+ monokai-line-head-chosen : rgba(#a6e22e, 0.25),
monokai-button-head-chosen : #39800d,
- monokai-header-origin-neutral : rgba(#60d9f1, .35),
- monokai-line-origin-neutral : rgba(#60d9f1, .15),
+ monokai-header-origin-neutral : rgba(#60d9f1, 0.35),
+ monokai-line-origin-neutral : rgba(#60d9f1, 0.15),
monokai-button-origin-neutral : #38848c,
- monokai-header-origin-chosen : rgba(#60d9f1, .5),
- monokai-line-origin-chosen : rgba(#60d9f1, .35),
+ monokai-header-origin-chosen : rgba(#60d9f1, 0.5),
+ monokai-line-origin-chosen : rgba(#60d9f1, 0.35),
monokai-button-origin-chosen : #3ea4b2,
- monokai-header-not-chosen : rgba(#76715d, .24),
- monokai-line-not-chosen : rgba(#76715d, .1),
+ monokai-header-not-chosen : rgba(#76715d, 0.24),
+ monokai-line-not-chosen : rgba(#76715d, 0.1),
- solarized-light-header-head-neutral : rgba(#859900, .37),
- solarized-light-line-head-neutral : rgba(#859900, .2),
+ solarized-light-header-head-neutral : rgba(#859900, 0.37),
+ solarized-light-line-head-neutral : rgba(#859900, 0.2),
solarized-light-button-head-neutral : #afb262,
- solarized-light-header-head-chosen : rgba(#859900, .5),
- solarized-light-line-head-chosen : rgba(#859900, .37),
+ solarized-light-header-head-chosen : rgba(#859900, 0.5),
+ solarized-light-line-head-chosen : rgba(#859900, 0.37),
solarized-light-button-head-chosen : #94993d,
- solarized-light-header-origin-neutral : rgba(#2878c9, .37),
- solarized-light-line-origin-neutral : rgba(#2878c9, .15),
+ solarized-light-header-origin-neutral : rgba(#2878c9, 0.37),
+ solarized-light-line-origin-neutral : rgba(#2878c9, 0.15),
solarized-light-button-origin-neutral : #60a1bf,
- solarized-light-header-origin-chosen : rgba(#2878c9, .6),
- solarized-light-line-origin-chosen : rgba(#2878c9, .37),
+ solarized-light-header-origin-chosen : rgba(#2878c9, 0.6),
+ solarized-light-line-origin-chosen : rgba(#2878c9, 0.37),
solarized-light-button-origin-chosen : #2482b2,
- solarized-light-header-not-chosen : rgba(#839496, .37),
- solarized-light-line-not-chosen : rgba(#839496, .2),
+ solarized-light-header-not-chosen : rgba(#839496, 0.37),
+ solarized-light-line-not-chosen : rgba(#839496, 0.2),
- solarized-dark-header-head-neutral : rgba(#859900, .35),
- solarized-dark-line-head-neutral : rgba(#859900, .15),
+ solarized-dark-header-head-neutral : rgba(#859900, 0.35),
+ solarized-dark-line-head-neutral : rgba(#859900, 0.15),
solarized-dark-button-head-neutral : #376b20,
- solarized-dark-header-head-chosen : rgba(#859900, .5),
- solarized-dark-line-head-chosen : rgba(#859900, .35),
+ solarized-dark-header-head-chosen : rgba(#859900, 0.5),
+ solarized-dark-line-head-chosen : rgba(#859900, 0.35),
solarized-dark-button-head-chosen : #39800d,
- solarized-dark-header-origin-neutral : rgba(#2878c9, .35),
- solarized-dark-line-origin-neutral : rgba(#2878c9, .15),
+ solarized-dark-header-origin-neutral : rgba(#2878c9, 0.35),
+ solarized-dark-line-origin-neutral : rgba(#2878c9, 0.15),
solarized-dark-button-origin-neutral : #086799,
- solarized-dark-header-origin-chosen : rgba(#2878c9, .6),
- solarized-dark-line-origin-chosen : rgba(#2878c9, .35),
+ solarized-dark-header-origin-chosen : rgba(#2878c9, 0.6),
+ solarized-dark-line-origin-chosen : rgba(#2878c9, 0.35),
solarized-dark-button-origin-chosen : #0082cc,
- solarized_dark_header_not_chosen : rgba(#839496, .25),
- solarized_dark_line_not_chosen : rgba(#839496, .15),
+ solarized_dark_header_not_chosen : rgba(#839496, 0.25),
+ solarized_dark_line_not_chosen : rgba(#839496, 0.15),
none_header_head_neutral : $gray-normal,
none_line_head_neutral : $gray-normal,
@@ -210,26 +210,20 @@ $colors: (
}
#conflicts {
-
.white {
- @include color-scheme('white')
- }
+ @include color-scheme('white'); }
.dark {
- @include color-scheme('dark')
- }
+ @include color-scheme('dark'); }
.monokai {
- @include color-scheme('monokai')
- }
+ @include color-scheme('monokai'); }
.solarized-light {
- @include color-scheme('solarized-light')
- }
+ @include color-scheme('solarized-light'); }
.solarized-dark {
- @include color-scheme('solarized-dark')
- }
+ @include color-scheme('solarized-dark'); }
.diff-wrap-lines .line_content {
white-space: normal;
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 221b4e934ff..e73d1a1289d 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -38,9 +38,7 @@
}
.mr-widget-section {
- .media {
- align-items: center;
- }
+ border-radius: $border-radius-default $border-radius-default 0 0;
.code-text {
flex: 1;
@@ -56,6 +54,11 @@
.mr-widget-extension {
border-top: 1px solid $border-color;
background-color: $gray-light;
+
+ &.clickable:hover {
+ background-color: $gl-gray-200;
+ cursor: pointer;
+ }
}
.mr-widget-workflow {
@@ -64,7 +67,7 @@
&::before {
content: '';
- border-left: 1px solid $theme-gray-200;
+ border-left: 1px solid $gray-200;
position: absolute;
left: 32px;
top: -17px;
@@ -78,7 +81,7 @@
border-top: 0;
}
-.mr-widget-section,
+.mr-widget-body,
.mr-widget-content,
.mr-widget-footer {
padding: $gl-padding;
@@ -87,11 +90,38 @@
.mr-state-widget {
color: $gl-text-color;
+ .commit-message-edit {
+ border-radius: $border-radius-default;
+ }
+
.mr-widget-section,
.mr-widget-footer {
border-top: solid 1px $border-color;
}
+ .mr-fast-forward-message {
+ padding-left: $gl-padding-50;
+ padding-bottom: $gl-padding;
+ }
+
+ .commits-list {
+ > li {
+ padding: $gl-padding;
+
+ @include media-breakpoint-up(md) {
+ padding-left: $gl-padding-50;
+ }
+ }
+ }
+
+ .mr-commit-dropdown {
+ .dropdown-menu {
+ @include media-breakpoint-up(md) {
+ width: 150%;
+ }
+ }
+ }
+
.mr-widget-footer {
padding: 0;
}
@@ -405,7 +435,7 @@
}
.mr-widget-help {
- padding: 10px 16px 10px 48px;
+ padding: 10px 16px 10px $gl-padding-50;
font-style: italic;
}
@@ -423,10 +453,6 @@
}
}
-.mr-widget-body-controls {
- flex-wrap: wrap;
-}
-
.mr_source_commit,
.mr_target_commit {
margin-bottom: 0;
@@ -465,11 +491,9 @@
.merge-request {
padding: 10px 0 10px 15px;
position: relative;
- display: -webkit-flex;
display: flex;
.issuable-info-container {
- -webkit-flex: 1;
flex: 1;
}
@@ -708,8 +732,11 @@
.mr-version-controls {
position: relative;
+ z-index: 203;
background: $gray-light;
color: $gl-text-color;
+ margin-top: -1px;
+ border-top: 1px solid $border-color;
.mr-version-menus-container {
display: flex;
@@ -755,17 +782,35 @@
color: $orange-500;
padding-right: 5px;
}
+
+ @include media-breakpoint-up(md) {
+ position: sticky;
+ top: $header-height + $mr-tabs-height;
+ width: 100%;
+
+ &.is-fileTreeOpen {
+ margin-left: -16px;
+ width: calc(100% + 32px);
+ }
+
+ .mr-version-menus-container {
+ flex-wrap: nowrap;
+ }
+
+ .with-performance-bar & {
+ top: $header-height + $performance-bar-height + $mr-tabs-height;
+ }
+ }
}
.merge-request-tabs-holder {
top: $header-height;
- z-index: 200;
+ z-index: 300;
background-color: $white-light;
border-bottom: 1px solid $border-color;
@include media-breakpoint-up(sm) {
position: sticky;
- position: -webkit-sticky;
}
&.affix {
@@ -816,7 +861,7 @@
display: flex;
justify-content: space-between;
- @include media-breakpoint-down(md) {
+ @include media-breakpoint-down(sm) {
flex-direction: column-reverse;
}
@@ -907,7 +952,7 @@
}
.btn svg {
- fill: $theme-gray-700;
+ fill: $gray-700;
}
.dropdown-menu {
@@ -951,7 +996,7 @@
.coverage {
font-size: 12px;
- color: $theme-gray-700;
+ color: $gray-700;
line-height: initial;
}
@@ -961,3 +1006,14 @@
width: $ci-action-icon-size-lg;
}
}
+
+.merge-request-details .file-finder-overlay.diff-file-finder {
+ position: fixed;
+ z-index: 99999;
+ background: $black-transparent;
+}
+
+.source-branch-removal-status {
+ padding-left: 50px;
+ padding-bottom: $gl-padding;
+}
diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss
index 1e92582d6d9..3ca8e943a3a 100644
--- a/app/assets/stylesheets/pages/milestone.scss
+++ b/app/assets/stylesheets/pages/milestone.scss
@@ -1,3 +1,5 @@
+$status-box-line-height: 26px;
+
.issues-sortable-list .str-truncated {
max-width: 90%;
}
@@ -6,7 +8,7 @@
padding: $gl-padding-8;
margin-top: $gl-padding-8;
border-radius: $border-radius-default;
- background-color: $theme-gray-100;
+ background-color: $gray-100;
.milestone {
border: 0;
@@ -38,6 +40,7 @@
font-size: $tooltip-font-size;
margin-top: 0;
margin-right: $gl-padding-4;
+ line-height: $status-box-line-height;
@include media-breakpoint-down(xs) {
line-height: unset;
@@ -64,18 +67,14 @@
.card-header {
line-height: $line-height-base;
padding: 14px 16px;
- display: -webkit-flex;
display: flex;
.title {
- -webkit-flex: 1;
- -webkit-flex-grow: 1;
flex: 1;
flex-grow: 2;
}
.counter {
- -webkit-flex: 1;
flex: 0;
padding-left: 16px;
}
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 5b30295adf9..3343b55d24b 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -1,10 +1,6 @@
/**
* Note Form
*/
-.comment-btn {
- @extend .btn-success;
-}
-
.diff-file .diff-content {
tr.line_holder:hover > td .line_note_link {
opacity: 1;
@@ -62,7 +58,7 @@
border: 1px solid $border-color;
border-radius: $border-radius-base;
transition: border-color ease-in-out 0.15s,
- box-shadow ease-in-out 0.15s;
+ box-shadow ease-in-out 0.15s;
&.is-focused {
@extend .form-control:focus;
@@ -76,7 +72,7 @@
&.is-dropzone-hover {
border-color: $green-500;
box-shadow: 0 0 2px $black-transparent,
- 0 0 4px $green-500-focus;
+ 0 0 4px $green-500-focus;
.comment-toolbar,
.nav-links {
@@ -88,9 +84,7 @@
.md-header .nav-links {
display: flex;
- display: -webkit-flex;
flex-flow: row wrap;
- -webkit-flex-flow: row wrap;
width: 100%;
.float-right {
@@ -151,7 +145,7 @@
}
.sidebar-item-value & {
- fill: $theme-gray-700;
+ fill: $gray-700;
}
}
@@ -386,7 +380,7 @@ table {
}
.comment-type-dropdown {
- .comment-btn {
+ .btn-success {
width: auto;
}
@@ -417,7 +411,7 @@ table {
width: 100%;
margin-bottom: 10px;
- .comment-btn {
+ .btn-success {
flex-grow: 1;
flex-shrink: 0;
width: auto;
@@ -448,7 +442,7 @@ table {
.uploading-error-message {
@include media-breakpoint-down(xs) {
&::after {
- content: "\a";
+ content: '\a';
white-space: pre;
}
}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index a5b1eff3e1d..72f48e98c24 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -5,7 +5,7 @@ $note-form-margin-left: 72px;
@mixin vertical-line($left) {
&::before {
content: '';
- border-left: 2px solid $theme-gray-100;
+ border-left: 2px solid $gray-100;
position: absolute;
top: 0;
bottom: 0;
@@ -153,12 +153,12 @@ $note-form-margin-left: 72px;
position: relative;
.timeline-discussion-body {
- margin-top: -8px;
+ margin-top: -$gl-padding-8;
overflow-x: auto;
overflow-y: hidden;
- .discussion-resolved-text {
- margin-bottom: 8px;
+ .note-body {
+ margin-top: $gl-padding-8;
}
}
@@ -303,26 +303,6 @@ $note-form-margin-left: 72px;
}
}
- .timeline-icon {
- float: left;
- display: flex;
- align-items: center;
- background-color: $white-light;
- width: $system-note-icon-size;
- height: $system-note-icon-size;
- border: 1px solid $border-color;
- border-radius: $system-note-icon-size;
- margin: -6px $gl-padding 0 0;
-
- svg {
- width: $system-note-svg-size;
- height: $system-note-svg-size;
- fill: $gray-darkest;
- display: block;
- margin: 0 auto;
- }
- }
-
.timeline-content {
@include notes-media('min', map-get($grid-breakpoints, sm)) {
margin-left: 30px;
@@ -380,6 +360,37 @@ $note-form-margin-left: 72px;
}
}
}
+
+ .system-note,
+ .discussion-filter-note {
+ .timeline-icon {
+ float: left;
+ display: flex;
+ align-items: center;
+ background-color: $white-light;
+ width: $system-note-icon-size;
+ height: $system-note-icon-size;
+ border: 1px solid $border-color;
+ border-radius: $system-note-icon-size;
+ margin: -6px $gl-padding 0 0;
+
+ svg {
+ width: $system-note-svg-size;
+ height: $system-note-svg-size;
+ fill: $gray-darkest;
+ display: block;
+ margin: 0 auto;
+ }
+ }
+ }
+
+ .discussion-filter-note {
+ .timeline-icon {
+ width: $system-note-icon-size + 6;
+ height: $system-note-icon-size + 6;
+ margin-top: -8px;
+ }
+ }
}
// Diff code in discussion view
@@ -494,11 +505,6 @@ $note-form-margin-left: 72px;
.discussion-notes {
margin-left: 0;
border-left: 0;
-
- .notes {
- position: relative;
- @include vertical-line(52px);
- }
}
.note-wrapper {
@@ -550,6 +556,11 @@ $note-form-margin-left: 72px;
.note-header-info {
padding-bottom: 0;
}
+
+ .timeline-content {
+ overflow-x: auto;
+ overflow-y: hidden;
+ }
}
.unresolved {
@@ -597,7 +608,6 @@ $note-form-margin-left: 72px;
.note-headline-meta {
display: inline-block;
- white-space: nowrap;
.system-note-message {
white-space: normal;
@@ -607,6 +617,10 @@ $note-form-margin-left: 72px;
color: $gl-text-color-disabled;
}
+ .note-timestamp {
+ white-space: nowrap;
+ }
+
a:hover {
text-decoration: underline;
}
@@ -902,7 +916,6 @@ $note-form-margin-left: 72px;
}
.discussion-filter-container {
-
.btn > svg {
width: $gl-col-padding;
height: $gl-col-padding;
@@ -924,7 +937,6 @@ $note-form-margin-left: 72px;
//This needs to be deleted when Snippet/Commit comments are convered to Vue
// See https://gitlab.com/gitlab-org/gitlab-ce/issues/53918#note_117038785
.unstyled-comments {
-
.discussion-header {
padding: $gl-padding;
border-bottom: 1px solid $border-color;
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index fdd17af35fb..acc562f0769 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -256,14 +256,25 @@
}
}
- .mini-pipeline-graph-dropdown-toggle svg {
- height: $ci-action-icon-size;
- width: $ci-action-icon-size;
- position: absolute;
- top: -1px;
- left: -1px;
- z-index: 2;
- overflow: visible;
+ .mini-pipeline-graph-dropdown-toggle {
+ svg {
+ height: $ci-action-icon-size;
+ width: $ci-action-icon-size;
+ position: absolute;
+ top: -1px;
+ left: -1px;
+ z-index: 2;
+ overflow: visible;
+ }
+
+ &:hover,
+ &:active,
+ &:focus {
+ svg {
+ top: -2px;
+ left: -2px;
+ }
+ }
}
.stage-container {
@@ -293,7 +304,7 @@
width: 7px;
position: absolute;
right: -7px;
- top: 10px;
+ top: 11px;
border-bottom: 2px solid $border-color;
}
}
@@ -433,6 +444,7 @@
}
.pipeline-tab-content {
+ display: flex;
width: 100%;
background-color: $gray-light;
padding: $gl-padding;
@@ -707,21 +719,43 @@
font-weight: $gl-font-weight-normal;
}
-@mixin mini-pipeline-graph-color($color-light, $color-main, $color-dark) {
- border-color: $color-main;
- color: $color-main;
+@mixin mini-pipeline-graph-color(
+ $color-background-default,
+ $color-background-hover-focus,
+ $color-background-active,
+ $color-foreground-default,
+ $color-foreground-hover-focus,
+ $color-foreground-active
+) {
+ background-color: $color-background-default;
+ border-color: $color-foreground-default;
+
+ svg {
+ fill: $color-foreground-default;
+ }
&:hover,
- &:focus,
+ &:focus {
+ background-color: $color-background-hover-focus;
+ border-color: $color-foreground-hover-focus;
+
+ svg {
+ fill: $color-foreground-hover-focus;
+ }
+ }
+
&:active {
- background-color: $color-light;
- border-color: $color-dark;
- color: $color-dark;
+ background-color: $color-background-active;
+ border-color: $color-foreground-active;
svg {
- fill: $color-dark;
+ fill: $color-foreground-active;
}
}
+
+ &:focus {
+ box-shadow: 0 0 4px 1px $blue-300;
+ }
}
@mixin mini-pipeline-item() {
@@ -733,26 +767,32 @@
height: $ci-action-icon-size;
margin: 0;
padding: 0;
- transition: all 0.2s linear;
position: relative;
vertical-align: middle;
+ &:hover,
+ &:active,
+ &:focus {
+ outline: none;
+ border-width: 2px;
+ }
+
// Dropdown button animation in mini pipeline graph
&.ci-status-icon-success {
- @include mini-pipeline-graph-color($green-100, $green-500, $green-600);
+ @include mini-pipeline-graph-color($white, $green-100, $green-200, $green-500, $green-600, $green-700);
}
&.ci-status-icon-failed {
- @include mini-pipeline-graph-color($red-100, $red-500, $red-600);
+ @include mini-pipeline-graph-color($white, $red-100, $red-200, $red-500, $red-600, $red-700);
}
&.ci-status-icon-pending,
&.ci-status-icon-success_with_warnings {
- @include mini-pipeline-graph-color($orange-100, $orange-500, $orange-600);
+ @include mini-pipeline-graph-color($white, $orange-100, $orange-200, $orange-500, $orange-600, $orange-700);
}
&.ci-status-icon-running {
- @include mini-pipeline-graph-color($blue-100, $blue-400, $blue-600);
+ @include mini-pipeline-graph-color($white, $blue-100, $blue-200, $blue-500, $blue-600, $blue-700);
}
&.ci-status-icon-canceled,
@@ -760,42 +800,18 @@
&.ci-status-icon-disabled,
&.ci-status-icon-not-found,
&.ci-status-icon-manual {
- @include mini-pipeline-graph-color(rgba($gl-text-color, 0.1), $gl-text-color, $gl-text-color);
+ @include mini-pipeline-graph-color($white, $gray-700, $gray-800, $gray-900, $gray-950, $black);
}
&.ci-status-icon-created,
&.ci-status-icon-skipped {
- @include mini-pipeline-graph-color(rgba($gray-darkest, 0.1), $gray-darkest, $gray-darkest);
+ @include mini-pipeline-graph-color($white, $gray-200, $gray-300, $gray-500, $gray-600, $gray-700);
}
}
// Dropdown button in mini pipeline graph
button.mini-pipeline-graph-dropdown-toggle {
@include mini-pipeline-item();
-
- > .fa.fa-caret-down {
- position: absolute;
- left: 20px;
- top: 5px;
- display: inline-block;
- visibility: hidden;
- opacity: 0;
- color: inherit;
- font-size: 12px;
- transition: visibility 0.1s, opacity 0.1s linear;
- }
-
- &:active,
- &:focus,
- &:hover {
- outline: none;
- width: 35px;
-
- .fa.fa-caret-down {
- visibility: visible;
- opacity: 1;
- }
- }
}
/**
@@ -845,7 +861,7 @@ button.mini-pipeline-graph-dropdown-toggle {
height: $ci-action-dropdown-svg-size;
fill: $gl-text-color-secondary;
position: relative;
- top: 0;
+ top: 1px;
vertical-align: initial;
}
}
@@ -853,7 +869,7 @@ button.mini-pipeline-graph-dropdown-toggle {
// SVGs in the commit widget and mr widget
a.ci-action-icon-container.ci-action-icon-wrapper svg {
- top: 2px;
+ top: 4px;
}
.scrollable-menu {
@@ -978,8 +994,6 @@ button.mini-pipeline-graph-dropdown-toggle {
* Top arrow in the dropdown in the mini pipeline graph
*/
.mini-pipeline-graph-dropdown-menu {
- z-index: 200;
-
&::before,
&::after {
content: '';
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index b813eb16dad..ab26259c007 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -249,6 +249,16 @@
.event-item {
padding-left: 40px;
}
+
+ @include media-breakpoint-up(lg) {
+ margin-right: 5px;
+ }
+ }
+
+ .projects-block {
+ @include media-breakpoint-up(lg) {
+ margin-left: 5px;
+ }
}
@include media-breakpoint-down(xs) {
@@ -260,11 +270,9 @@
position: static;
padding: 0 16px;
margin-bottom: 20px;
- display: -webkit-flex;
display: flex;
.btn {
- -webkit-flex-grow: 1;
flex-grow: 1;
&:first-child {
diff --git a/app/assets/stylesheets/pages/profiles/preferences.scss b/app/assets/stylesheets/pages/profiles/preferences.scss
index a353f301d07..45e62913f37 100644
--- a/app/assets/stylesheets/pages/profiles/preferences.scss
+++ b/app/assets/stylesheets/pages/profiles/preferences.scss
@@ -60,11 +60,11 @@
}
&.ui-dark {
- background-color: $theme-gray-900;
+ background-color: $gray-900;
}
&.ui-light {
- background-color: $theme-gray-200;
+ background-color: $gray-200;
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 0ce0db038a7..1349845f300 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -140,73 +140,19 @@
}
}
-.project-home-panel,
-.group-home-panel {
- padding-top: 24px;
- padding-bottom: 24px;
-
- .group-avatar {
- float: none;
- margin: 0 auto;
-
- &.identicon {
- border-radius: 50%;
- }
- }
-
- .group-title {
- margin-top: 10px;
- margin-bottom: 10px;
- font-size: 24px;
- font-weight: $gl-font-weight-normal;
- line-height: 1;
- word-wrap: break-word;
-
- .fa {
- margin-left: 2px;
- font-size: 12px;
- vertical-align: middle;
- }
- }
-
- .group-home-desc {
- margin-left: auto;
- margin-right: auto;
- margin-bottom: 0;
- max-width: 700px;
-
- > p {
- margin-bottom: 0;
- }
- }
-
- .notifications-btn {
- .fa-bell,
- .fa-spinner {
- margin-right: 6px;
- }
-
- .fa-angle-down {
- margin-left: 6px;
- }
- }
-}
-
+.group-home-panel,
.project-home-panel {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
- .project-avatar {
- width: $project-title-row-height;
- height: $project-title-row-height;
+ .home-panel-avatar {
+ width: $home-panel-title-row-height;
+ height: $home-panel-title-row-height;
flex-shrink: 0;
- flex-basis: $project-title-row-height;
- margin: 0 $gl-padding 0 0;
+ flex-basis: $home-panel-title-row-height;
}
- .project-title {
- margin-top: 8px;
- margin-bottom: 5px;
+ .home-panel-title {
font-size: 20px;
line-height: $gl-line-height-24;
font-weight: bold;
@@ -215,11 +161,7 @@
font-size: $gl-font-size-large;
}
- .project-visibility {
- color: $gl-text-color-secondary;
- }
-
- .project-tag-list {
+ .home-panel-topic-list {
font-size: $gl-font-size;
font-weight: $gl-font-weight-normal;
@@ -231,12 +173,12 @@
}
}
- .project-title-row {
+ .home-panel-title-row {
@include media-breakpoint-down(sm) {
- .project-avatar {
- width: $project-avatar-mobile-size;
- height: $project-avatar-mobile-size;
- flex-basis: $project-avatar-mobile-size;
+ .home-panel-avatar {
+ width: $home-panel-avatar-mobile-size;
+ height: $home-panel-avatar-mobile-size;
+ flex-basis: $home-panel-avatar-mobile-size;
.avatar {
font-size: 20px;
@@ -244,28 +186,26 @@
}
}
- .project-title {
+ .home-panel-title {
margin-top: 4px;
margin-bottom: 2px;
font-size: $gl-font-size;
line-height: $gl-font-size-large;
}
- .project-tag-list,
- .project-metadata {
+ .home-panel-topic-list,
+ .home-panel-metadata {
font-size: $gl-font-size-small;
}
}
}
- .project-metadata {
+ .home-panel-metadata {
font-weight: normal;
font-size: 14px;
line-height: $gl-btn-line-height;
- color: $gl-text-color-secondary;
-
- .project-license {
+ .home-panel-license {
.btn {
line-height: 0;
border-width: 0;
@@ -273,13 +213,13 @@
}
.access-request-link,
- .project-tag-list {
+ .home-panel-topic-list {
padding-left: $gl-padding-8;
border-left: 1px solid $gl-text-color-secondary;
}
}
- .project-description {
+ .home-panel-description {
@include media-breakpoint-up(md) {
font-size: $gl-font-size-large;
}
@@ -292,12 +232,11 @@
}
}
-.nav > .project-repo-buttons {
+.nav > .project-buttons {
margin-top: 0;
}
-.project-repo-buttons,
-.group-buttons {
+.project-repo-buttons {
.btn {
&:last-child {
margin-left: 0;
@@ -318,8 +257,30 @@
margin-left: 0;
}
}
+
+ .notifications-icon {
+ top: 1px;
+ margin-right: 0;
+ }
+ }
+
+ .icon {
+ top: 0;
+ }
+
+ .count-badge,
+ .btn-xs {
+ height: 24px;
+ }
+
+ .dropdown-toggle,
+ .clone-dropdown-btn {
+ .fa {
+ color: unset;
+ }
}
+ .home-panel-action-button,
.project-action-button {
margin: $gl-padding $gl-padding-8 0 0;
vertical-align: top;
@@ -385,31 +346,6 @@
}
}
-.project-repo-buttons {
- .icon {
- top: 0;
- }
-
- .count-badge,
- .btn-xs {
- height: 24px;
- }
-
- .dropdown-toggle,
- .clone-dropdown-btn {
- .fa {
- color: unset;
- }
- }
-
- .btn {
- .notifications-icon {
- top: 1px;
- margin-right: 0;
- }
- }
-}
-
.split-one {
display: inline-table;
margin-right: 12px;
@@ -459,7 +395,7 @@
margin-right: $gl-padding-4;
margin-bottom: $gl-padding-4;
color: $gl-text-color-secondary;
- background-color: $theme-gray-100;
+ background-color: $gray-100;
line-height: $gl-btn-line-height;
&:hover {
@@ -571,12 +507,6 @@
}
.template-option {
- .logo {
- .btn-template-icon {
- width: 40px !important;
- }
- }
-
padding: 16px 0;
&:not(:first-child) {
@@ -615,9 +545,8 @@
}
.selected-icon {
- svg {
+ img {
display: none;
- top: 7px;
height: 20px;
width: 20px;
}
@@ -642,9 +571,7 @@
.import-buttons {
padding-left: 0;
- display: -webkit-flex;
display: flex;
- -webkit-flex-wrap: wrap;
flex-wrap: wrap;
.btn {
@@ -772,14 +699,11 @@
.project-stats,
.project-buttons {
- font-size: 0;
- text-align: center;
-
.scrolling-tabs-container {
.scrolling-tabs {
margin-top: $gl-padding-8;
- margin-bottom: $gl-padding-8 - $browserScrollbarSize;
- padding-bottom: $browserScrollbarSize;
+ margin-bottom: $gl-padding-8 - $browser-scrollbar-size;
+ padding-bottom: $browser-scrollbar-size;
flex-wrap: wrap;
border-bottom: 0;
}
@@ -787,7 +711,7 @@
.fade-left,
.fade-right {
top: 0;
- height: calc(100% - #{$browserScrollbarSize});
+ height: calc(100% - #{$browser-scrollbar-size});
.fa {
top: 50%;
@@ -914,7 +838,7 @@
}
.repository-language-bar-tooltip-share {
- color: $theme-gray-400;
+ color: $gray-400;
}
pre.light-well {
@@ -973,7 +897,7 @@ pre.light-well {
padding: $gl-padding 0;
@include media-breakpoint-up(lg) {
- padding: $gl-padding-24 0;
+ padding: $gl-padding 0;
}
&.no-description {
@@ -990,7 +914,7 @@ pre.light-well {
}
h2 {
- font-size: $gl-font-size-medium;
+ font-size: $gl-font-size-large;
font-weight: $gl-font-weight-bold;
margin-bottom: 0;
@@ -1013,6 +937,11 @@ pre.light-well {
.flex-wrapper {
min-width: 0;
margin-top: -$gl-padding-8; // negative margin required for flex-wrap
+ flex: 1 1 100%;
+
+ .project-title {
+ line-height: 20px;
+ }
}
p,
@@ -1025,8 +954,10 @@ pre.light-well {
margin: 0;
}
- @include media-breakpoint-up(md) {
- .description {
+ .description {
+ line-height: 1.5;
+
+ @include media-breakpoint-up(md) {
color: $gl-text-color;
}
}
@@ -1049,14 +980,16 @@ pre.light-well {
}
.controls {
- margin-top: $gl-padding;
+ @include media-breakpoint-down(xs) {
+ margin-top: $gl-padding-8;
+ }
- @include media-breakpoint-down(md) {
+ @include media-breakpoint-up(sm) {
margin-top: 0;
}
- @include media-breakpoint-down(xs) {
- margin-top: $gl-padding-8;
+ @include media-breakpoint-up(lg) {
+ flex: 1 1 40%;
}
.icon-wrapper {
@@ -1106,7 +1039,7 @@ pre.light-well {
min-height: 40px;
min-width: 40px;
- .identicon.s64 {
+ .identicon.s48 {
font-size: 16px;
}
}
diff --git a/app/assets/stylesheets/pages/reports.scss b/app/assets/stylesheets/pages/reports.scss
index ecd51aa06a4..f7619ccbd20 100644
--- a/app/assets/stylesheets/pages/reports.scss
+++ b/app/assets/stylesheets/pages/reports.scss
@@ -96,7 +96,7 @@
}
&.neutral svg {
- color: $theme-gray-700;
+ color: $gray-700;
}
.ci-status-icon {
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index 149c3254d84..20bdc6596e9 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -84,9 +84,7 @@ input[type='checkbox']:hover {
.search-icon {
transition: color $default-transition-duration;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
+ user-select: none;
}
.clear-icon {
@@ -185,13 +183,11 @@ input[type='checkbox']:hover {
.search-holder {
@include media-breakpoint-up(sm) {
- display: -webkit-flex;
display: flex;
}
.search-field-holder,
.project-filter-form {
- -webkit-flex: 1 0 auto;
flex: 1 0 auto;
position: relative;
margin-right: 0;
diff --git a/app/assets/stylesheets/pages/serverless.scss b/app/assets/stylesheets/pages/serverless.scss
new file mode 100644
index 00000000000..a5b73492380
--- /dev/null
+++ b/app/assets/stylesheets/pages/serverless.scss
@@ -0,0 +1,3 @@
+.url-text-field {
+ cursor: text;
+}
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index ccfa4e00a5b..4f9d96da4bd 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -167,12 +167,14 @@
font-weight: $gl-font-weight-normal;
display: inline-block;
color: $gl-text-color;
+ vertical-align: top;
}
.option-description,
.option-disabled-reason {
margin-left: 30px;
color: $project-option-descr-color;
+ margin-top: -5px;
}
.option-disabled-reason {
@@ -297,7 +299,7 @@
.btn-clipboard {
background-color: $white-light;
- border: 1px solid $theme-gray-200;
+ border: 1px solid $gray-200;
}
.deploy-token-help-block {
@@ -314,8 +316,4 @@
.push-pull-table {
margin-top: 1em;
-
- .mirror-action-buttons {
- padding-right: 0;
- }
}
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index 7d59dd3b5d1..f4d568d02ac 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -33,7 +33,7 @@
border-color: $gl-text-color;
&:not(span):hover {
- background-color: rgba($gl-text-color, .07);
+ background-color: rgba($gl-text-color, 0.07);
}
}
@@ -54,7 +54,7 @@
border-color: $gl-text-color-secondary;
&:not(span):hover {
- background-color: rgba($gl-text-color-secondary, .07);
+ background-color: rgba($gl-text-color-secondary, 0.07);
}
}
}
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index 3fc37e20c36..2a1e8345755 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -6,9 +6,7 @@
.todos-list > .todo {
// workaround because we cannot use border-colapse
border-top: 1px solid transparent;
- display: -webkit-flex;
display: flex;
- -webkit-flex-direction: row;
flex-direction: row;
&:hover {
@@ -29,23 +27,18 @@
.todo-avatar,
.todo-actions {
@include transition(opacity);
- -webkit-flex: 0 0 auto;
flex: 0 0 auto;
}
.todo-actions {
- display: -webkit-flex;
display: flex;
- -webkit-justify-content: center;
justify-content: center;
- -webkit-flex-direction: column;
flex-direction: column;
margin-left: 10px;
min-width: 55px;
}
.todo-item {
- -webkit-flex: 0 1 100%;
flex: 0 1 100%;
min-width: 0;
}
@@ -60,13 +53,13 @@
.todo-avatar,
.todo-item {
- opacity: .6;
+ opacity: 0.6;
}
}
.todo-avatar,
.todo-item {
- opacity: .2;
+ opacity: 0.2;
}
.btn {
@@ -82,7 +75,6 @@
display: flex;
> .title-item {
- -webkit-flex: 0 0 auto;
flex: 0 0 auto;
margin: 0 2px;
@@ -96,7 +88,6 @@
}
.todo-label {
- -webkit-flex: 0 1 auto;
flex: 0 1 auto;
overflow: hidden;
text-overflow: ellipsis;
@@ -222,23 +213,19 @@
}
.todos-empty {
- display: -webkit-flex;
display: flex;
- -webkit-flex-direction: column;
flex-direction: column;
max-width: 900px;
margin-left: auto;
margin-right: auto;
@include media-breakpoint-up(sm) {
- -webkit-flex-direction: row;
flex-direction: row;
padding-top: 80px;
}
}
.todos-empty-content {
- -webkit-align-self: center;
align-self: center;
max-width: 480px;
margin-right: 20px;
@@ -252,7 +239,6 @@
@include media-breakpoint-up(sm) {
width: 300px;
margin-right: 0;
- -webkit-order: 2;
order: 2;
}
}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index a46b8679a42..5664f46484e 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -172,26 +172,6 @@
text-decoration: inherit;
}
}
-
- .tree_commit {
- max-width: 320px;
-
- .str-truncated {
- max-width: 100%;
- }
- }
-
- .tree_time_ago {
- min-width: 135px;
- }
- }
-
- .tree_author {
- padding-right: 8px;
-
- .commit-author-name {
- color: $gl-text-color;
- }
}
.tree-truncated-warning {
diff --git a/app/assets/stylesheets/pages/ui_dev_kit.scss b/app/assets/stylesheets/pages/ui_dev_kit.scss
index 84c617c7ec0..7744fd814d0 100644
--- a/app/assets/stylesheets/pages/ui_dev_kit.scss
+++ b/app/assets/stylesheets/pages/ui_dev_kit.scss
@@ -10,7 +10,7 @@
margin-bottom: 15px;
&::before {
- content: "Example";
+ content: 'Example';
color: $ui-dev-kit-example-color;
}
}
diff --git a/app/controllers/admin/appearances_controller.rb b/app/controllers/admin/appearances_controller.rb
index e3226c86b0b..189fee98aa0 100644
--- a/app/controllers/admin/appearances_controller.rb
+++ b/app/controllers/admin/appearances_controller.rb
@@ -74,6 +74,11 @@ class Admin::AppearancesController < Admin::ApplicationController
favicon_cache
new_project_guidelines
updated_by
+ header_message
+ footer_message
+ message_background_color
+ message_font_color
+ email_header_and_footer_enabled
]
end
end
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 8f683ca06ad..8f267eccc8a 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -77,7 +77,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def reset_health_check_token
@application_setting.reset_health_check_access_token!
flash[:notice] = 'New health check access token has been generated!'
- redirect_to :back
+ redirect_back_or_default
end
def clear_repository_check_states
diff --git a/app/controllers/admin/requests_profiles_controller.rb b/app/controllers/admin/requests_profiles_controller.rb
index 57f7d3e3951..89d4c4f18d9 100644
--- a/app/controllers/admin/requests_profiles_controller.rb
+++ b/app/controllers/admin/requests_profiles_controller.rb
@@ -11,7 +11,7 @@ class Admin::RequestsProfilesController < Admin::ApplicationController
profile = Gitlab::RequestProfiler::Profile.find(clean_name)
if profile
- render html: profile.content
+ render html: profile.content.html_safe
else
redirect_to admin_requests_profiles_path, alert: 'Profile not found'
end
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index 0b6ff491c66..8a00408001e 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Admin::RunnersController < Admin::ApplicationController
- before_action :runner, except: :index
+ before_action :runner, except: [:index, :tag_list]
def index
finder = Admin::RunnersFinder.new(params: params)
@@ -48,6 +48,12 @@ class Admin::RunnersController < Admin::ApplicationController
end
end
+ def tag_list
+ tags = Autocomplete::ActsAsTaggableOn::TagsFinder.new(params: params).execute
+
+ render json: ActsAsTaggableOn::TagSerializer.new.represent(tags)
+ end
+
private
def runner
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index e93be1c1ba2..bfa7c7d0109 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: true
class Admin::UsersController < Admin::ApplicationController
+ include RoutableActions
+
before_action :user, except: [:index, :new, :create]
before_action :check_impersonation_availability, only: :impersonate
def index
- @users = User.order_name_asc.filter(params[:filter])
+ @users = User.filter_items(params[:filter]).order_name_asc
@users = @users.search_with_secondary_emails(params[:search_query]) if params[:search_query].present?
@users = @users.sort_by_attribute(@sort = params[:sort])
@users = @users.page(params[:page])
@@ -177,11 +179,13 @@ class Admin::UsersController < Admin::ApplicationController
user == current_user
end
- # rubocop: disable CodeReuse/ActiveRecord
def user
- @user ||= User.find_by!(username: params[:id])
+ @user ||= find_routable!(User, params[:id])
+ end
+
+ def build_canonical_path(user)
+ url_for(safe_params.merge(id: user.to_param))
end
- # rubocop: enable CodeReuse/ActiveRecord
def redirect_back_or_admin_user(options = {})
redirect_back_or_default(default: default_route, options: options)
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 140a625d333..b7eb6af6d67 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -43,7 +43,10 @@ class ApplicationController < ActionController::Base
:git_import_enabled?, :gitlab_project_import_enabled?,
:manifest_import_enabled?
+ # Adds `no-store` to the DEFAULT_CACHE_CONTROL, to prevent security
+ # concerns due to caching private data.
DEFAULT_GITLAB_CACHE_CONTROL = "#{ActionDispatch::Http::Cache::Response::DEFAULT_CACHE_CONTROL}, no-store".freeze
+ DEFAULT_GITLAB_CONTROL_NO_CACHE = "#{DEFAULT_GITLAB_CACHE_CONTROL}, no-cache".freeze
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
@@ -76,7 +79,7 @@ class ApplicationController < ActionController::Base
end
def redirect_back_or_default(default: root_path, options: {})
- redirect_to request.referer.present? ? :back : default, options
+ redirect_back(fallback_location: default, **options)
end
def not_found
@@ -137,6 +140,8 @@ class ApplicationController < ActionController::Base
if response.status == 422 && response.body.present? && response.content_type == 'application/json'.freeze
payload[:response] = response.body
end
+
+ payload[:queue_duration] = request.env[::Gitlab::Middleware::RailsQueueDuration::GITLAB_RAILS_QUEUE_DURATION_KEY]
end
##
@@ -177,11 +182,17 @@ class ApplicationController < ActionController::Base
# hide existence of the resource, rather tell them they cannot access it using
# the provided message
status ||= message.present? ? :forbidden : :not_found
+ template =
+ if status == :not_found
+ "errors/not_found"
+ else
+ "errors/access_denied"
+ end
respond_to do |format|
format.any { head status }
format.html do
- render "errors/access_denied",
+ render template,
layout: "errors",
status: status,
locals: { message: message }
@@ -227,9 +238,9 @@ class ApplicationController < ActionController::Base
end
def no_cache_headers
- response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
- response.headers["Pragma"] = "no-cache"
- response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
+ headers['Cache-Control'] = DEFAULT_GITLAB_CONTROL_NO_CACHE
+ headers['Pragma'] = 'no-cache' # HTTP 1.0 compatibility
+ headers['Expires'] = 'Fri, 01 Jan 1990 00:00:00 GMT'
end
def default_headers
@@ -239,10 +250,16 @@ class ApplicationController < ActionController::Base
headers['X-Content-Type-Options'] = 'nosniff'
if current_user
- # Adds `no-store` to the DEFAULT_CACHE_CONTROL, to prevent security
- # concerns due to caching private data.
- headers['Cache-Control'] = DEFAULT_GITLAB_CACHE_CONTROL
- headers["Pragma"] = "no-cache" # HTTP 1.0 compatibility
+ headers['Cache-Control'] = default_cache_control
+ headers['Pragma'] = 'no-cache' # HTTP 1.0 compatibility
+ end
+ end
+
+ def default_cache_control
+ if request.xhr?
+ ActionDispatch::Http::Cache::Response::DEFAULT_CACHE_CONTROL
+ else
+ DEFAULT_GITLAB_CACHE_CONTROL
end
end
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index b9717b97640..68a2a83f0de 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -24,7 +24,7 @@ class Clusters::ClustersController < Clusters::BaseController
# Note: We are paginating through an array here but this should OK as:
#
# In CE, we can have a maximum group nesting depth of 21, so including
- # project cluster, we can have max 22 clusters for a group hierachy.
+ # project cluster, we can have max 22 clusters for a group hierarchy.
# In EE (Premium) we can have any number, as multiple clusters are
# supported, but the number of clusters are fairly low currently.
#
@@ -127,6 +127,7 @@ class Clusters::ClustersController < Clusters::BaseController
params.require(:cluster).permit(
:enabled,
:environment_scope,
+ :base_domain,
platform_kubernetes_attributes: [
:namespace
]
@@ -136,6 +137,7 @@ class Clusters::ClustersController < Clusters::BaseController
:enabled,
:name,
:environment_scope,
+ :base_domain,
platform_kubernetes_attributes: [
:api_url,
:token,
diff --git a/app/controllers/concerns/boards_responses.rb b/app/controllers/concerns/boards_responses.rb
index 3cdf4ddf8bb..8b191c86397 100644
--- a/app/controllers/concerns/boards_responses.rb
+++ b/app/controllers/concerns/boards_responses.rb
@@ -34,15 +34,11 @@ module BoardsResponses
end
def authorize_read_list
- ability = board.group_board? ? :read_group : :read_list
-
- authorize_action_for!(board.parent, ability)
+ authorize_action_for!(board, :read_list)
end
def authorize_read_issue
- ability = board.group_board? ? :read_group : :read_issue
-
- authorize_action_for!(board.parent, ability)
+ authorize_action_for!(board, :read_issue)
end
def authorize_update_issue
@@ -57,7 +53,7 @@ module BoardsResponses
end
def authorize_admin_list
- authorize_action_for!(board.parent, :admin_list)
+ authorize_action_for!(board, :admin_list)
end
def authorize_action_for!(resource, ability)
diff --git a/app/controllers/concerns/continue_params.rb b/app/controllers/concerns/continue_params.rb
index f0e6adf4dec..54c0510497f 100644
--- a/app/controllers/concerns/continue_params.rb
+++ b/app/controllers/concerns/continue_params.rb
@@ -6,7 +6,7 @@ module ContinueParams
def continue_params
continue_params = params[:continue]
- return nil unless continue_params
+ return unless continue_params
continue_params = continue_params.permit(:to, :notice, :notice_now)
continue_params[:to] = safe_redirect_path(continue_params[:to])
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index 3d64ae8b775..cd3fa641e89 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -7,6 +7,9 @@ module IssuableActions
included do
before_action :authorize_destroy_issuable!, only: :destroy
before_action :authorize_admin_issuable!, only: :bulk_update
+ before_action only: :show do
+ push_frontend_feature_flag(:reply_to_individual_notes)
+ end
end
def permitted_keys
@@ -58,7 +61,8 @@ module IssuableActions
title_text: issuable.title,
description: view_context.markdown_field(issuable, :description),
description_text: issuable.description,
- task_status: issuable.task_status
+ task_status: issuable.task_status,
+ lock_version: issuable.lock_version
}
if issuable.edited?
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index 789e0dc736e..c529aabf797 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -91,6 +91,7 @@ module IssuableCollections
options = {
scope: params[:scope],
state: params[:state],
+ confidential: Gitlab::Utils.to_boolean(params[:confidential]),
sort: set_sort_order
}
@@ -129,13 +130,13 @@ module IssuableCollections
return sort_param if Gitlab::Database.read_only?
if user_preference[issuable_sorting_field] != sort_param
- user_preference.update_attribute(issuable_sorting_field, sort_param)
+ user_preference.update(issuable_sorting_field => sort_param)
end
sort_param
end
- # Implement default_sorting_field method on controllers
+ # Implement issuable_sorting_field method on controllers
# to choose which column to store the sorting parameter.
def issuable_sorting_field
nil
diff --git a/app/controllers/concerns/issuable_collections_action.rb b/app/controllers/concerns/issuable_collections_action.rb
new file mode 100644
index 00000000000..18ed4027eac
--- /dev/null
+++ b/app/controllers/concerns/issuable_collections_action.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module IssuableCollectionsAction
+ extend ActiveSupport::Concern
+ include IssuableCollections
+ include IssuesCalendar
+
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ def issues
+ @issues = issuables_collection
+ .non_archived
+ .page(params[:page])
+
+ @issuable_meta_data = issuable_meta_data(@issues, collection_type)
+
+ respond_to do |format|
+ format.html
+ format.atom { render layout: 'xml.atom' }
+ end
+ end
+
+ def merge_requests
+ @merge_requests = issuables_collection.page(params[:page])
+
+ @issuable_meta_data = issuable_meta_data(@merge_requests, collection_type)
+ end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
+
+ def issues_calendar
+ render_issues_calendar(issuables_collection)
+ end
+
+ private
+
+ def issuable_sorting_field
+ case action_name
+ when 'issues'
+ Issue::SORTING_PREFERENCE_FIELD
+ when 'merge_requests'
+ MergeRequest::SORTING_PREFERENCE_FIELD
+ else
+ nil
+ end
+ end
+
+ def finder_type
+ case action_name
+ when 'issues', 'issues_calendar'
+ IssuesFinder
+ when 'merge_requests'
+ MergeRequestsFinder
+ else
+ nil
+ end
+ end
+
+ def finder_options
+ super.merge(non_archived: true)
+ end
+end
diff --git a/app/controllers/concerns/issues_action.rb b/app/controllers/concerns/issues_action.rb
deleted file mode 100644
index a75590457d6..00000000000
--- a/app/controllers/concerns/issues_action.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module IssuesAction
- extend ActiveSupport::Concern
- include IssuableCollections
- include IssuesCalendar
-
- # rubocop:disable Gitlab/ModuleWithInstanceVariables
- def issues
- @issues = issuables_collection
- .non_archived
- .page(params[:page])
-
- @issuable_meta_data = issuable_meta_data(@issues, collection_type)
-
- respond_to do |format|
- format.html
- format.atom { render layout: 'xml.atom' }
- end
- end
- # rubocop:enable Gitlab/ModuleWithInstanceVariables
-
- def issues_calendar
- render_issues_calendar(issuables_collection)
- end
-
- private
-
- def finder_type
- (super if defined?(super)) ||
- (IssuesFinder if %w(issues issues_calendar).include?(action_name))
- end
-end
diff --git a/app/controllers/concerns/lfs_request.rb b/app/controllers/concerns/lfs_request.rb
index 5572c3cee2d..57e444319e0 100644
--- a/app/controllers/concerns/lfs_request.rb
+++ b/app/controllers/concerns/lfs_request.rb
@@ -123,7 +123,7 @@ module LfsRequest
(authentication_abilities || []).include?(capability)
end
- # Overriden in EE
+ # Overridden in EE
def limit_exceeded?
false
end
diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index ca713192c9e..6402e01ddc0 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -35,7 +35,9 @@ module MembershipActions
respond_to do |format|
format.html do
- message = "User was successfully removed from #{source_type}."
+ source = source_type == 'group' ? 'group and any subresources' : source_type
+
+ message = "User was successfully removed from #{source}."
redirect_to members_page_url, notice: message
end
diff --git a/app/controllers/concerns/merge_requests_action.rb b/app/controllers/concerns/merge_requests_action.rb
deleted file mode 100644
index ed10f32512e..00000000000
--- a/app/controllers/concerns/merge_requests_action.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module MergeRequestsAction
- extend ActiveSupport::Concern
- include IssuableCollections
-
- # rubocop:disable Gitlab/ModuleWithInstanceVariables
- def merge_requests
- @merge_requests = issuables_collection.page(params[:page])
-
- @issuable_meta_data = issuable_meta_data(@merge_requests, collection_type)
- end
- # rubocop:enable Gitlab/ModuleWithInstanceVariables
-
- private
-
- def finder_type
- (super if defined?(super)) ||
- (MergeRequestsFinder if action_name == 'merge_requests')
- end
-
- def finder_options
- super.merge(non_archived: true)
- end
-end
diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb
index eccbe35577b..c0c0160a827 100644
--- a/app/controllers/concerns/milestone_actions.rb
+++ b/app/controllers/concerns/milestone_actions.rb
@@ -8,7 +8,7 @@ module MilestoneActions
format.html { redirect_to milestone_redirect_path }
format.json do
render json: tabs_json("shared/milestones/_merge_requests_tab", {
- merge_requests: @milestone.sorted_merge_requests, # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ merge_requests: @milestone.sorted_merge_requests(current_user), # rubocop:disable Gitlab/ModuleWithInstanceVariables
show_project_name: true
})
end
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index 0319948a12f..b4fee93713b 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -6,7 +6,6 @@ module NotesActions
extend ActiveSupport::Concern
included do
- prepend_before_action :normalize_create_params, only: [:create]
before_action :set_polling_interval_header, only: [:index]
before_action :require_noteable!, only: [:index, :create]
before_action :authorize_admin_note!, only: [:update, :destroy]
@@ -44,12 +43,7 @@ module NotesActions
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def create
- create_params = note_params.merge(
- merge_request_diff_head_sha: params[:merge_request_diff_head_sha],
- in_reply_to_discussion_id: params[:in_reply_to_discussion_id]
- )
-
- @note = Notes::CreateService.new(note_project, current_user, create_params).execute
+ @note = Notes::CreateService.new(note_project, current_user, create_note_params).execute
respond_to do |format|
format.json do
@@ -78,7 +72,7 @@ module NotesActions
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def update
- @note = Notes::UpdateService.new(project, current_user, note_params).execute(note)
+ @note = Notes::UpdateService.new(project, current_user, update_note_params).execute(note)
prepare_notes_for_rendering([@note])
respond_to do |format|
@@ -196,24 +190,36 @@ module NotesActions
return access_denied! unless can?(current_user, :admin_note, note)
end
- def note_params
+ def create_note_params
params.require(:note).permit(
- :project_id,
- :noteable_type,
- :noteable_id,
- :commit_id,
- :noteable,
:type,
-
:note,
- :attachment,
+ :line_code, # LegacyDiffNote
+ :position # DiffNote
+ ).tap do |create_params|
+ create_params.merge!(
+ params.permit(:merge_request_diff_head_sha, :in_reply_to_discussion_id)
+ )
- # LegacyDiffNote
- :line_code,
+ # These params are also sent by the client but we need to set these based on
+ # target_type and target_id because we're checking permissions based on that
+ create_params[:noteable_type] = params[:target_type].classify
+
+ case params[:target_type]
+ when 'commit'
+ create_params[:commit_id] = params[:target_id]
+ when 'merge_request'
+ create_params[:noteable_id] = params[:target_id]
+ # Notes on MergeRequest can have an extra `commit_id` context
+ create_params[:commit_id] = params.dig(:note, :commit_id)
+ else
+ create_params[:noteable_id] = params[:target_id]
+ end
+ end
+ end
- # DiffNote
- :position
- )
+ def update_note_params
+ params.require(:note).permit(:note)
end
def set_polling_interval_header
@@ -248,15 +254,6 @@ module NotesActions
DiscussionSerializer.new(project: project, noteable: noteable, current_user: current_user, note_entity: ProjectNoteEntity)
end
- # Avoids checking permissions in the wrong object - this ensures that the object we checked permissions for
- # is the object we're actually creating a note in.
- def normalize_create_params
- params[:note].try do |note|
- note[:noteable_id] = params[:target_id]
- note[:noteable_type] = params[:target_type].classify
- end
- end
-
def note_project
strong_memoize(:note_project) do
next nil unless project
diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb
index 4b0f0b8255c..f72d25fc54c 100644
--- a/app/controllers/concerns/preview_markdown.rb
+++ b/app/controllers/concerns/preview_markdown.rb
@@ -16,8 +16,6 @@ module PreviewMarkdown
else {}
end
- markdown_params[:markdown_engine] = result[:markdown_engine]
-
render json: {
body: view_context.markdown(result[:text], markdown_params),
references: {
diff --git a/app/controllers/concerns/record_user_last_activity.rb b/app/controllers/concerns/record_user_last_activity.rb
new file mode 100644
index 00000000000..372c803278d
--- /dev/null
+++ b/app/controllers/concerns/record_user_last_activity.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# == RecordUserLastActivity
+#
+# Controller concern that updates the `last_activity_on` field of `users`
+# for any authenticated GET request. The DB update will only happen once per day.
+#
+# In order to determine if you should include this concern or not, please check the
+# description and discussion on this issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/54947
+module RecordUserLastActivity
+ include CookiesHelper
+ extend ActiveSupport::Concern
+
+ included do
+ before_action :set_user_last_activity
+ end
+
+ def set_user_last_activity
+ return unless request.get?
+ return unless Feature.enabled?(:set_user_last_activity, default_enabled: true)
+ return if Gitlab::Database.read_only?
+
+ if current_user && current_user.last_activity_on != Date.today
+ Users::ActivityService.new(current_user, "visited #{request.path}").execute
+ end
+ end
+end
diff --git a/app/controllers/concerns/renders_notes.rb b/app/controllers/concerns/renders_notes.rb
index ce36da6b715..18015b1de88 100644
--- a/app/controllers/concerns/renders_notes.rb
+++ b/app/controllers/concerns/renders_notes.rb
@@ -16,7 +16,7 @@ module RendersNotes
private
def preload_max_access_for_authors(notes, project)
- return nil unless project
+ return unless project
user_ids = notes.map(&:author_id)
project.team.max_member_access_for_user_ids(user_ids)
diff --git a/app/controllers/concerns/send_file_upload.rb b/app/controllers/concerns/send_file_upload.rb
index 515a9eede8e..28e4cece548 100644
--- a/app/controllers/concerns/send_file_upload.rb
+++ b/app/controllers/concerns/send_file_upload.rb
@@ -3,16 +3,19 @@
module SendFileUpload
def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, proxy: false, disposition: 'attachment')
if attachment
+ response_disposition = ::Gitlab::ContentDisposition.format(disposition: disposition, filename: attachment)
+
# Response-Content-Type will not override an existing Content-Type in
# Google Cloud Storage, so the metadata needs to be cleared on GCS for
# this to work. However, this override works with AWS.
- redirect_params[:query] = { "response-content-disposition" => "#{disposition};filename=#{attachment.inspect}",
+ redirect_params[:query] = { "response-content-disposition" => response_disposition,
"response-content-type" => guess_content_type(attachment) }
# By default, Rails will send uploads with an extension of .js with a
# content-type of text/javascript, which will trigger Rails'
# cross-origin JavaScript protection.
send_params[:content_type] = 'text/plain' if File.extname(attachment) == '.js'
- send_params.merge!(filename: attachment, disposition: disposition)
+
+ send_params.merge!(filename: attachment, disposition: utf8_encoded_disposition(disposition, attachment))
end
if file_upload.file_storage?
@@ -25,6 +28,18 @@ module SendFileUpload
end
end
+ # Since Rails 5 doesn't properly support support non-ASCII filenames,
+ # we have to add our own to ensure RFC 5987 compliance. However, Rails
+ # 5 automatically appends `filename#{filename}` here:
+ # https://github.com/rails/rails/blob/v5.0.7/actionpack/lib/action_controller/metal/data_streaming.rb#L137
+ # Rails 6 will have https://github.com/rails/rails/pull/33829, so we
+ # can get rid of this special case handling when we upgrade.
+ def utf8_encoded_disposition(disposition, filename)
+ content = ::Gitlab::ContentDisposition.new(disposition: disposition, filename: filename)
+
+ "#{disposition}; #{content.utf8_filename}"
+ end
+
def guess_content_type(filename)
types = MIME::Types.type_for(filename)
diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb
index c6ae4fe15bf..48451bedcc2 100644
--- a/app/controllers/concerns/service_params.rb
+++ b/app/controllers/concerns/service_params.rb
@@ -72,7 +72,7 @@ module ServiceParams
dynamic_params = @service.event_channel_names + @service.event_names # rubocop:disable Gitlab/ModuleWithInstanceVariables
service_params = params.permit(:id, service: allowed_service_params + dynamic_params)
- if service_params[:service].is_a?(Hash)
+ if service_params[:service].is_a?(ActionController::Parameters)
FILTER_BLANK_PARAMS.each do |param|
service_params[:service].delete(param) if service_params[:service][param].blank?
end
diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb
index 0eea0cdd50f..4ec0e94df9a 100644
--- a/app/controllers/concerns/uploads_actions.rb
+++ b/app/controllers/concerns/uploads_actions.rb
@@ -7,12 +7,12 @@ module UploadsActions
UPLOAD_MOUNTS = %w(avatar attachment file logo header_logo favicon).freeze
def create
- link_to_file = UploadService.new(model, params[:file], uploader_class).execute
+ uploader = UploadService.new(model, params[:file], uploader_class).execute
respond_to do |format|
- if link_to_file
+ if uploader
format.json do
- render json: { link: link_to_file }
+ render json: { link: uploader.to_h }
end
else
format.json do
@@ -29,7 +29,13 @@ module UploadsActions
def show
return render_404 unless uploader&.exists?
- expires_in 0.seconds, must_revalidate: true, private: true
+ if cache_publicly?
+ # We need to reset caching from the applications controller to get rid of the no-store value
+ headers['Cache-Control'] = ''
+ expires_in 5.minutes, public: true, must_revalidate: false
+ else
+ expires_in 0.seconds, must_revalidate: true, private: true
+ end
disposition = uploader.image_or_video? ? 'inline' : 'attachment'
@@ -114,6 +120,10 @@ module UploadsActions
nil
end
+ def cache_publicly?
+ false
+ end
+
def model
strong_memoize(:model) { find_model }
end
diff --git a/app/controllers/dashboard/application_controller.rb b/app/controllers/dashboard/application_controller.rb
index cee0753a021..0e9fdc60363 100644
--- a/app/controllers/dashboard/application_controller.rb
+++ b/app/controllers/dashboard/application_controller.rb
@@ -2,6 +2,7 @@
class Dashboard::ApplicationController < ApplicationController
include ControllerWithCrossProjectAccessCheck
+ include RecordUserLastActivity
layout 'dashboard'
diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb
index 3802aa5f40f..912036da0ea 100644
--- a/app/controllers/dashboard/milestones_controller.rb
+++ b/app/controllers/dashboard/milestones_controller.rb
@@ -25,9 +25,7 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController
private
def group_milestones
- groups = GroupsFinder.new(current_user, all_available: false).execute
-
- DashboardGroupMilestone.build_collection(groups)
+ DashboardGroupMilestone.build_collection(groups, params)
end
# See [#39545](https://gitlab.com/gitlab-org/gitlab-ce/issues/39545) for info about the deprecation of dynamic milestones
@@ -45,6 +43,6 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController
end
def groups
- @groups ||= GroupsFinder.new(current_user, state_all: true).execute
+ @groups ||= GroupsFinder.new(current_user, all_available: false).execute
end
end
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
index f073b6de444..b044affd4e8 100644
--- a/app/controllers/dashboard/projects_controller.rb
+++ b/app/controllers/dashboard/projects_controller.rb
@@ -13,7 +13,13 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@projects = load_projects(params.merge(non_public: true))
respond_to do |format|
- format.html
+ format.html do
+ # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/37434
+ # Also https://gitlab.com/gitlab-org/gitlab-ce/issues/40260
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ render
+ end
+ end
format.atom do
load_events
render layout: 'xml.atom'
@@ -53,6 +59,9 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def load_projects(finder_params)
+ @total_user_projects_count = ProjectsFinder.new(params: { non_public: true }, current_user: current_user).execute
+ @total_starred_projects_count = ProjectsFinder.new(params: { starred: true }, current_user: current_user).execute
+
projects = ProjectsFinder
.new(params: finder_params, current_user: current_user)
.execute
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index be2d9512c01..75329b05a6f 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
class DashboardController < Dashboard::ApplicationController
- include IssuesAction
- include MergeRequestsAction
+ include IssuableCollectionsAction
prepend_before_action(only: [:issues]) { authenticate_sessionless_user!(:rss) }
prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) }
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index 778fdda8dbd..f3d76c5a478 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -15,7 +15,7 @@ class Explore::ProjectsController < Explore::ApplicationController
format.html
format.json do
render json: {
- html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
+ html: view_to_html_string("explore/projects/_projects", locals: { projects: @projects })
}
end
end
@@ -30,7 +30,7 @@ class Explore::ProjectsController < Explore::ApplicationController
format.html
format.json do
render json: {
- html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
+ html: view_to_html_string("explore/projects/_projects", locals: { projects: @projects })
}
end
end
@@ -44,7 +44,7 @@ class Explore::ProjectsController < Explore::ApplicationController
format.html
format.json do
render json: {
- html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
+ html: view_to_html_string("explore/projects/_projects", locals: { projects: @projects })
}
end
end
@@ -55,6 +55,9 @@ class Explore::ProjectsController < Explore::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def load_projects
+ @total_user_projects_count = ProjectsFinder.new(params: { non_public: true }, current_user: current_user).execute
+ @total_starred_projects_count = ProjectsFinder.new(params: { starred: true }, current_user: current_user).execute
+
projects = ProjectsFinder.new(current_user: current_user, params: params)
.execute
.includes(:route, :creator, :group, namespace: [:route, :owner])
diff --git a/app/controllers/google_api/authorizations_controller.rb b/app/controllers/google_api/authorizations_controller.rb
index dd9f5af61b3..ed0995e7ffd 100644
--- a/app/controllers/google_api/authorizations_controller.rb
+++ b/app/controllers/google_api/authorizations_controller.rb
@@ -2,6 +2,10 @@
module GoogleApi
class AuthorizationsController < ApplicationController
+ include Gitlab::Utils::StrongMemoize
+
+ before_action :validate_session_key!
+
def callback
token, expires_at = GoogleApi::CloudPlatform::Client
.new(nil, callback_google_api_auth_url)
@@ -11,21 +15,27 @@ module GoogleApi
session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] =
expires_at.to_s
- state_redirect_uri = redirect_uri_from_session_key(params[:state])
-
- if state_redirect_uri
- redirect_to state_redirect_uri
- else
- redirect_to root_path
- end
+ redirect_to redirect_uri_from_session
end
private
- def redirect_uri_from_session_key(state)
- key = GoogleApi::CloudPlatform::Client
- .session_key_for_redirect_uri(params[:state])
- session[key] if key
+ def validate_session_key!
+ access_denied! unless redirect_uri_from_session.present?
+ end
+
+ def redirect_uri_from_session
+ strong_memoize(:redirect_uri_from_session) do
+ if params[:state].present?
+ session[session_key_for_redirect_uri(params[:state])]
+ else
+ nil
+ end
+ end
+ end
+
+ def session_key_for_redirect_uri(state)
+ GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(state)
end
end
end
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index 3ef03bc9622..e147d32be2e 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -3,9 +3,16 @@
class GraphqlController < ApplicationController
# Unauthenticated users have access to the API for public data
skip_before_action :authenticate_user!
- prepend_before_action(only: [:execute]) { authenticate_sessionless_user!(:api) }
+
+ # Allow missing CSRF tokens, this would mean that if a CSRF is invalid or missing,
+ # the user won't be authenticated but can proceed as an anonymous user.
+ #
+ # If a CSRF is valid, the user is authenticated. This makes it easier to play
+ # around in GraphiQL.
+ protect_from_forgery with: :null_session, only: :execute
before_action :check_graphql_feature_flag!
+ before_action(only: [:execute]) { authenticate_sessionless_user!(:api) }
def execute
variables = Gitlab::Graphql::Variables.new(params[:variables]).to_h
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index cdc6f53df8e..51fdb6c05fb 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -2,6 +2,7 @@
class Groups::BoardsController < Groups::ApplicationController
include BoardsResponses
+ include RecordUserLastActivity
before_action :assign_endpoint_vars
before_action :boards, only: :index
diff --git a/app/controllers/groups/children_controller.rb b/app/controllers/groups/children_controller.rb
index d549f793ad7..236a19a8dc4 100644
--- a/app/controllers/groups/children_controller.rb
+++ b/app/controllers/groups/children_controller.rb
@@ -35,7 +35,7 @@ module Groups
def setup_children(parent)
@children = GroupDescendantsFinder.new(current_user: current_user,
parent_group: parent,
- params: params).execute
+ params: params.to_unsafe_h).execute
@children = @children.page(params[:page])
end
end
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index b42116b0f36..7ed4384089b 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -43,14 +43,7 @@ class Groups::MilestonesController < Groups::ApplicationController
def update
# Keep this compatible with legacy group milestones where we have to update
# all projects milestones states at once.
- if @milestone.legacy_group_milestone?
- update_params = milestone_params.select { |key| key == "state_event" }
- milestones = @milestone.milestones
- else
- update_params = milestone_params
- milestones = [@milestone]
- end
-
+ milestones, update_params = get_milestones_for_update
milestones.each do |milestone|
Milestones::UpdateService.new(milestone.parent, current_user, update_params).execute(milestone)
end
@@ -71,6 +64,14 @@ class Groups::MilestonesController < Groups::ApplicationController
private
+ def get_milestones_for_update
+ if @milestone.legacy_group_milestone?
+ [@milestone.milestones, legacy_milestone_params]
+ else
+ [[@milestone], milestone_params]
+ end
+ end
+
def authorize_admin_milestones!
return render_404 unless can?(current_user, :admin_milestone, group)
end
@@ -79,6 +80,10 @@ class Groups::MilestonesController < Groups::ApplicationController
params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event)
end
+ def legacy_milestone_params
+ params.require(:milestone).permit(:state_event)
+ end
+
def milestone_path
if @milestone.legacy_group_milestone?
group_milestone_path(group, @milestone.safe_title, title: @milestone.title)
@@ -110,6 +115,6 @@ class Groups::MilestonesController < Groups::ApplicationController
end
def search_params
- params.permit(:state).merge(group_ids: group.id)
+ params.permit(:state, :search_title).merge(group_ids: group.id)
end
end
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index c1dcc463de7..f476f428fdb 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -4,7 +4,7 @@ module Groups
module Settings
class CiCdController < Groups::ApplicationController
skip_cross_project_access_check :show
- before_action :authorize_admin_pipeline!
+ before_action :authorize_admin_group!
def show
define_ci_variables
@@ -26,8 +26,8 @@ module Groups
.map { |variable| variable.present(current_user: current_user) }
end
- def authorize_admin_pipeline!
- return render_404 unless can?(current_user, :admin_pipeline, group)
+ def authorize_admin_group!
+ return render_404 unless can?(current_user, :admin_group, group)
end
end
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index c5d8ac2ed77..4e50106398a 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -2,10 +2,10 @@
class GroupsController < Groups::ApplicationController
include API::Helpers::RelatedResourcesHelpers
- include IssuesAction
- include MergeRequestsAction
+ include IssuableCollectionsAction
include ParamsBackwardCompatibility
include PreviewMarkdown
+ include RecordUserLastActivity
respond_to :html
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
index e5a1fc9d6ff..a9d6addd4a4 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -13,9 +13,10 @@ class HelpController < ApplicationController
# Remove YAML frontmatter so that it doesn't look weird
@help_index = File.read(Rails.root.join('doc', 'README.md')).sub(YAML_FRONT_MATTER_REGEXP, '')
- # Prefix Markdown links with `help/` unless they are external links
- # See http://rubular.com/r/X3baHTbPO2
- @help_index.gsub!(%r{(?<delim>\]\()(?!.+://)(?!/)(?<link>[^\)\(]+\))}) do
+ # Prefix Markdown links with `help/` unless they are external links.
+ # '//' not necessarily part of URL, e.g., mailto:mail@example.com
+ # See https://rubular.com/r/DFHZl5w8d3bpzV
+ @help_index.gsub!(%r{(?<delim>\]\()(?!\w+:)(?!/)(?<link>[^\)\(]+\))}) do
"#{$~[:delim]}#{Gitlab.config.gitlab.relative_url_root}/help/#{$~[:link]}"
end
end
diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb
index 042b6b1264f..9b45be6db99 100644
--- a/app/controllers/import/base_controller.rb
+++ b/app/controllers/import/base_controller.rb
@@ -18,6 +18,7 @@ class Import::BaseController < ApplicationController
end
# rubocop: enable CodeReuse/ActiveRecord
+ # deprecated: being replaced by app/services/import/base_service.rb
def find_or_create_namespace(names, owner)
names = params[:target_namespace].presence || names
@@ -32,6 +33,7 @@ class Import::BaseController < ApplicationController
current_user.namespace
end
+ # deprecated: being replaced by app/services/import/base_service.rb
def project_save_error(project)
project.errors.full_messages.join(', ')
end
diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb
index 1b30b4dda36..2b1395f364f 100644
--- a/app/controllers/import/bitbucket_controller.rb
+++ b/app/controllers/import/bitbucket_controller.rb
@@ -8,7 +8,7 @@ class Import::BitbucketController < Import::BaseController
rescue_from Bitbucket::Error::Unauthorized, with: :bitbucket_unauthorized
def callback
- response = client.auth_code.get_token(params[:code], redirect_uri: callback_import_bitbucket_url)
+ response = client.auth_code.get_token(params[:code], redirect_uri: users_import_bitbucket_callback_url)
session[:bitbucket_token] = response.token
session[:bitbucket_expires_at] = response.expires_at
@@ -89,7 +89,7 @@ class Import::BitbucketController < Import::BaseController
end
def go_to_bitbucket_for_permissions
- redirect_to client.auth_code.authorize_url(redirect_uri: callback_import_bitbucket_url)
+ redirect_to client.auth_code.authorize_url(redirect_uri: users_import_bitbucket_callback_url)
end
def bitbucket_unauthorized
diff --git a/app/controllers/import/bitbucket_server_controller.rb b/app/controllers/import/bitbucket_server_controller.rb
index 575c40d5f6f..f333e43b892 100644
--- a/app/controllers/import/bitbucket_server_controller.rb
+++ b/app/controllers/import/bitbucket_server_controller.rb
@@ -13,7 +13,10 @@ class Import::BitbucketServerController < Import::BaseController
# Repository names are limited to 128 characters. They must start with a
# letter or number and may contain spaces, hyphens, underscores, and periods.
# (https://community.atlassian.com/t5/Answers-Developer-Questions/stash-repository-names/qaq-p/499054)
- VALID_BITBUCKET_CHARS = /\A[\w\-_\.\s]+\z/
+ #
+ # Bitbucket Server starts personal project names with a tilde.
+ VALID_BITBUCKET_PROJECT_CHARS = /\A~?[\w\-\.\s]+\z/
+ VALID_BITBUCKET_CHARS = /\A[\w\-\.\s]+\z/
def new
end
@@ -40,7 +43,7 @@ class Import::BitbucketServerController < Import::BaseController
else
render json: { errors: 'This namespace has already been taken! Please choose another one.' }, status: :unprocessable_entity
end
- rescue BitbucketServer::Client::ServerError => e
+ rescue BitbucketServer::Connection::ConnectionError => e
render json: { errors: "Unable to connect to server: #{e}" }, status: :unprocessable_entity
end
@@ -62,7 +65,7 @@ class Import::BitbucketServerController < Import::BaseController
already_added_projects_names = @already_added_projects.pluck(:import_source)
@repos.reject! { |repo| already_added_projects_names.include?(repo.browse_url) }
- rescue BitbucketServer::Connection::ConnectionError, BitbucketServer::Client::ServerError => e
+ rescue BitbucketServer::Connection::ConnectionError => e
flash[:alert] = "Unable to connect to server: #{e}"
clear_session_data
redirect_to new_import_bitbucket_server_path
@@ -91,7 +94,7 @@ class Import::BitbucketServerController < Import::BaseController
return render_validation_error('Missing project key') unless @project_key.present? && @repo_slug.present?
return render_validation_error('Missing repository slug') unless @repo_slug.present?
- return render_validation_error('Invalid project key') unless @project_key =~ VALID_BITBUCKET_CHARS
+ return render_validation_error('Invalid project key') unless @project_key =~ VALID_BITBUCKET_PROJECT_CHARS
return render_validation_error('Invalid repository slug') unless @repo_slug =~ VALID_BITBUCKET_CHARS
end
diff --git a/app/controllers/import/gitea_controller.rb b/app/controllers/import/gitea_controller.rb
index f067ef625aa..68ad8650dba 100644
--- a/app/controllers/import/gitea_controller.rb
+++ b/app/controllers/import/gitea_controller.rb
@@ -1,8 +1,10 @@
# frozen_string_literal: true
class Import::GiteaController < Import::GithubController
+ extend ::Gitlab::Utils::Override
+
def new
- if session[access_token_key].present? && session[host_key].present?
+ if session[access_token_key].present? && provider_url.present?
redirect_to status_import_url
end
end
@@ -12,8 +14,8 @@ class Import::GiteaController < Import::GithubController
super
end
+ # Must be defined or it will 404
def status
- @gitea_host_url = session[host_key]
super
end
@@ -23,25 +25,33 @@ class Import::GiteaController < Import::GithubController
:"#{provider}_host_url"
end
- # Overridden methods
+ override :provider
def provider
:gitea
end
+ override :provider_url
+ def provider_url
+ session[host_key]
+ end
+
# Gitea is not yet an OAuth provider
# See https://github.com/go-gitea/gitea/issues/27
+ override :logged_in_with_provider?
def logged_in_with_provider?
false
end
+ override :provider_auth
def provider_auth
- if session[access_token_key].blank? || session[host_key].blank?
+ if session[access_token_key].blank? || provider_url.blank?
redirect_to new_import_gitea_url,
alert: 'You need to specify both an Access Token and a Host URL.'
end
end
+ override :client_options
def client_options
- { host: session[host_key], api_version: 'v1' }
+ { host: provider_url, api_version: 'v1' }
end
end
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index d4c26fa0709..aa4aa0fbdac 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -1,8 +1,11 @@
# frozen_string_literal: true
class Import::GithubController < Import::BaseController
+ include ImportHelper
+
before_action :verify_import_enabled
- before_action :provider_auth, only: [:status, :jobs, :create]
+ before_action :provider_auth, only: [:status, :realtime_changes, :create]
+ before_action :expire_etag_cache, only: [:status, :create]
rescue_from Octokit::Unauthorized, with: :provider_unauthorized
@@ -24,47 +27,86 @@ class Import::GithubController < Import::BaseController
redirect_to status_import_url
end
- # rubocop: disable CodeReuse/ActiveRecord
def status
- @repos = client.repos
- @already_added_projects = find_already_added_projects(provider)
- already_added_projects_names = @already_added_projects.pluck(:import_source)
-
- @repos.reject! { |repo| already_added_projects_names.include? repo.full_name }
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def jobs
- render json: find_jobs(provider)
+ # Request repos to display error page if provider token is invalid
+ # Improving in https://gitlab.com/gitlab-org/gitlab-ce/issues/55585
+ client_repos
+
+ respond_to do |format|
+ format.json do
+ render json: { imported_projects: serialized_imported_projects,
+ provider_repos: serialized_provider_repos,
+ namespaces: serialized_namespaces }
+ end
+ format.html
+ end
end
def create
- repo = client.repo(params[:repo_id].to_i)
- project_name = params[:new_name].presence || repo.name
- namespace_path = params[:target_namespace].presence || current_user.namespace_path
- target_namespace = find_or_create_namespace(namespace_path, current_user.namespace_path)
-
- if can?(current_user, :create_projects, target_namespace)
- project = Gitlab::LegacyGithubImport::ProjectCreator
- .new(repo, project_name, target_namespace, current_user, access_params, type: provider)
- .execute(extra_project_attrs)
-
- if project.persisted?
- render json: ProjectSerializer.new.represent(project)
- else
- render json: { errors: project_save_error(project) }, status: :unprocessable_entity
- end
+ result = Import::GithubService.new(client, current_user, import_params).execute(access_params, provider)
+
+ if result[:status] == :success
+ render json: serialized_imported_projects(result[:project])
else
- render json: { errors: 'This namespace has already been taken! Please choose another one.' }, status: :unprocessable_entity
+ render json: { errors: result[:message] }, status: result[:http_status]
end
end
+ def realtime_changes
+ Gitlab::PollingInterval.set_header(response, interval: 3_000)
+
+ render json: find_jobs(provider)
+ end
+
private
+ def import_params
+ params.permit(permitted_import_params)
+ end
+
+ def permitted_import_params
+ [:repo_id, :new_name, :target_namespace]
+ end
+
+ def serialized_imported_projects(projects = already_added_projects)
+ ProjectSerializer.new.represent(projects, serializer: :import, provider_url: provider_url)
+ end
+
+ def serialized_provider_repos
+ repos = client_repos.reject { |repo| already_added_project_names.include? repo.full_name }
+ ProviderRepoSerializer.new(current_user: current_user).represent(repos, provider: provider, provider_url: provider_url)
+ end
+
+ def serialized_namespaces
+ NamespaceSerializer.new.represent(namespaces)
+ end
+
+ def already_added_projects
+ @already_added_projects ||= find_already_added_projects(provider)
+ end
+
+ def already_added_project_names
+ @already_added_projects_names ||= already_added_projects.pluck(:import_source) # rubocop:disable CodeReuse/ActiveRecord
+ end
+
+ def namespaces
+ current_user.manageable_groups_with_routes
+ end
+
+ def expire_etag_cache
+ Gitlab::EtagCaching::Store.new.tap do |store|
+ store.touch(realtime_changes_path)
+ end
+ end
+
def client
@client ||= Gitlab::LegacyGithubImport::Client.new(session[access_token_key], client_options)
end
+ def client_repos
+ @client_repos ||= client.repos
+ end
+
def verify_import_enabled
render_404 unless import_enabled?
end
@@ -77,6 +119,10 @@ class Import::GithubController < Import::BaseController
__send__("#{provider}_import_enabled?") # rubocop:disable GitlabSecurity/PublicSend
end
+ def realtime_changes_path
+ public_send("realtime_changes_import_#{provider}_path", format: :json) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
def new_import_url
public_send("new_import_#{provider}_url", extra_import_params) # rubocop:disable GitlabSecurity/PublicSend
end
@@ -86,7 +132,7 @@ class Import::GithubController < Import::BaseController
end
def callback_import_url
- public_send("callback_import_#{provider}_url", extra_import_params) # rubocop:disable GitlabSecurity/PublicSend
+ public_send("users_import_#{provider}_callback_url", extra_import_params) # rubocop:disable GitlabSecurity/PublicSend
end
def provider_unauthorized
@@ -108,6 +154,14 @@ class Import::GithubController < Import::BaseController
:github
end
+ def provider_url
+ strong_memoize(:provider_url) do
+ provider = Gitlab::Auth::OAuth::Provider.config_for('github')
+
+ provider&.dig('url').presence || 'https://github.com'
+ end
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def logged_in_with_provider?
current_user.identities.exists?(provider: provider)
@@ -124,10 +178,6 @@ class Import::GithubController < Import::BaseController
{}
end
- def extra_project_attrs
- {}
- end
-
def extra_import_params
{}
end
diff --git a/app/controllers/notification_settings_controller.rb b/app/controllers/notification_settings_controller.rb
index 384f308269a..43c4f4d220e 100644
--- a/app/controllers/notification_settings_controller.rb
+++ b/app/controllers/notification_settings_controller.rb
@@ -17,7 +17,8 @@ class NotificationSettingsController < ApplicationController
@saved = @notification_setting.update(notification_setting_params_for(@notification_setting.source))
if params[:hide_label].present?
- render_response("projects/buttons/_notifications")
+ btn_class = params[:project_id].present? ? 'btn-xs' : ''
+ render_response("shared/notifications/_new_button", btn_class)
else
render_response
end
@@ -41,9 +42,9 @@ class NotificationSettingsController < ApplicationController
can?(current_user, ability_name, resource)
end
- def render_response(response_template = "shared/notifications/_button")
+ def render_response(response_template = "shared/notifications/_button", btn_class = nil)
render json: {
- html: view_to_html_string(response_template, notification_setting: @notification_setting),
+ html: view_to_html_string(response_template, notification_setting: @notification_setting, btn_class: btn_class),
saved: @saved
}
end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 30be50d4595..cc2bb99f55b 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -4,7 +4,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
include AuthenticatesWithTwoFactor
include Devise::Controllers::Rememberable
- protect_from_forgery except: [:kerberos, :saml, :cas3], prepend: true
+ protect_from_forgery except: [:kerberos, :saml, :cas3, :failure], with: :exception, prepend: true
def handle_omniauth
omniauth_flow(Gitlab::Auth::OAuth)
@@ -75,6 +75,10 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
private
def omniauth_flow(auth_module, identity_linker: nil)
+ if fragment = request.env.dig('omniauth.params', 'redirect_fragment').presence
+ store_redirect_fragment(fragment)
+ end
+
if current_user
log_audit_event(current_user, with: oauth['provider'])
@@ -112,8 +116,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
session[:service_tickets][provider] = ticket
end
+ def build_auth_user(auth_user_class)
+ auth_user_class.new(oauth)
+ end
+
def sign_in_user_flow(auth_user_class)
- auth_user = auth_user_class.new(oauth)
+ auth_user = build_auth_user(auth_user_class)
user = auth_user.find_and_update!
if auth_user.valid_sign_in?
@@ -189,4 +197,13 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
request_params = request.env['omniauth.params']
(request_params['remember_me'] == '1') if request_params.present?
end
+
+ def store_redirect_fragment(redirect_fragment)
+ key = stored_location_key_for(:user)
+ location = session[key]
+ if uri = parse_uri(location)
+ uri.fragment = redirect_fragment
+ store_location_for(:user, uri.to_s)
+ end
+ end
end
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
index 2912a22411e..28f113b5cbe 100644
--- a/app/controllers/passwords_controller.rb
+++ b/app/controllers/passwords_controller.rb
@@ -5,7 +5,7 @@ class PasswordsController < Devise::PasswordsController
before_action :resource_from_email, only: [:create]
before_action :check_password_authentication_available, only: [:create]
- before_action :throttle_reset, only: [:create]
+ before_action :throttle_reset, only: [:create]
# rubocop: disable CodeReuse/ActiveRecord
def edit
diff --git a/app/controllers/profiles/active_sessions_controller.rb b/app/controllers/profiles/active_sessions_controller.rb
index efe7ede5efa..c473023cacb 100644
--- a/app/controllers/profiles/active_sessions_controller.rb
+++ b/app/controllers/profiles/active_sessions_controller.rb
@@ -2,15 +2,6 @@
class Profiles::ActiveSessionsController < Profiles::ApplicationController
def index
- @sessions = ActiveSession.list(current_user)
- end
-
- def destroy
- ActiveSession.destroy(current_user, params[:id])
-
- respond_to do |format|
- format.html { redirect_to profile_active_sessions_url, status: :found }
- format.js { head :ok }
- end
+ @sessions = ActiveSession.list(current_user).reject(&:is_impersonated)
end
end
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index 37ac11dc6a1..0227af2c266 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -33,12 +33,18 @@ class Profiles::PreferencesController < Profiles::ApplicationController
end
def preferences_params
- params.require(:user).permit(
+ params.require(:user).permit(preferences_param_names)
+ end
+
+ def preferences_param_names
+ [
:color_scheme_id,
:layout,
:dashboard,
:project_view,
- :theme_id
- )
+ :theme_id,
+ :first_day_of_week,
+ :preferred_language
+ ]
end
end
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 15248d2d08f..b9c52618d4b 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -104,7 +104,6 @@ class ProfilesController < Profiles::ApplicationController
:username,
:website_url,
:organization,
- :preferred_language,
:private_profile,
:include_private_contributions,
status: [:emoji, :message]
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index e0677ce3fbc..6504fd6c08a 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -17,7 +17,7 @@ class Projects::ApplicationController < ApplicationController
def project
return @project if @project
- return nil unless params[:project_id] || params[:id]
+ return unless params[:project_id] || params[:id]
path = File.join(params[:namespace_id], params[:project_id] || params[:id])
auth_proc = ->(project) { !project.pending_delete? }
diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb
index 1a91e07b97f..2ef18d900f2 100644
--- a/app/controllers/projects/artifacts_controller.rb
+++ b/app/controllers/projects/artifacts_controller.rb
@@ -85,20 +85,15 @@ class Projects::ArtifactsController < Projects::ApplicationController
end
end
- # rubocop: disable CodeReuse/ActiveRecord
def build_from_id
- project.builds.find_by(id: params[:job_id]) if params[:job_id]
+ project.builds.find_by_id(params[:job_id]) if params[:job_id]
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def build_from_ref
return unless @ref_name
- builds = project.latest_successful_builds_for(@ref_name)
- builds.find_by(name: params[:job])
+ project.latest_successful_build_for(params[:job], @ref_name)
end
- # rubocop: enable CodeReuse/ActiveRecord
def artifacts_file
@artifacts_file ||= build&.artifacts_file_for_type(params[:file_type] || :archive)
diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb
index 9c130af8394..0e3f13045ce 100644
--- a/app/controllers/projects/autocomplete_sources_controller.rb
+++ b/app/controllers/projects/autocomplete_sources_controller.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Projects::AutocompleteSourcesController < Projects::ApplicationController
+ before_action :authorize_read_milestone!, only: :milestones
+
def members
render json: ::Projects::ParticipantsService.new(@project, current_user).execute(target)
end
diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb
index c24bf211760..09a384e89ab 100644
--- a/app/controllers/projects/badges_controller.rb
+++ b/app/controllers/projects/badges_controller.rb
@@ -21,11 +21,22 @@ class Projects::BadgesController < Projects::ApplicationController
private
+ def badge_layout
+ case params[:style]
+ when 'flat'
+ 'badge'
+ when 'flat-square'
+ 'badge_flat-square'
+ else
+ 'badge'
+ end
+ end
+
def render_badge(badge)
respond_to do |format|
format.html { render_404 }
format.svg do
- render 'badge', locals: { badge: badge.template }
+ render badge_layout, locals: { badge: badge.template }
end
end
end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 60fabd15333..77672e7d9fc 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -93,7 +93,7 @@ class Projects::BlobController < Projects::ApplicationController
@blob.load_all_data!
@lines = @blob.present.highlight.lines
- @form = UnfoldForm.new(params)
+ @form = UnfoldForm.new(params.to_unsafe_h)
@lines = @lines[@form.since - 1..@form.to - 1].map(&:html_safe)
@@ -260,7 +260,7 @@ class Projects::BlobController < Projects::ApplicationController
extension: blob.extension,
size: blob.raw_size,
mime_type: blob.mime_type,
- binary: blob.raw_binary?,
+ binary: blob.binary?,
simple_viewer: blob.simple_viewer&.class&.partial_name,
rich_viewer: blob.rich_viewer&.class&.partial_name,
show_viewer_switcher: !!blob.show_viewer_switcher?,
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index a6bfb913900..32b7f3207ef 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -29,7 +29,8 @@ class Projects::BranchesController < Projects::ApplicationController
Gitlab::GitalyClient.allow_n_plus_1_calls do
@max_commits = @branches.reduce(0) do |memo, branch|
diverging_commit_counts = repository.diverging_commit_counts(branch)
- [memo, diverging_commit_counts[:behind], diverging_commit_counts[:ahead]].max
+ [memo, diverging_commit_counts.values_at(:behind, :ahead, :distance)]
+ .flatten.compact.max
end
end
diff --git a/app/controllers/projects/build_artifacts_controller.rb b/app/controllers/projects/build_artifacts_controller.rb
index 7d4d566499c..4274c356227 100644
--- a/app/controllers/projects/build_artifacts_controller.rb
+++ b/app/controllers/projects/build_artifacts_controller.rb
@@ -44,18 +44,13 @@ class Projects::BuildArtifactsController < Projects::ApplicationController
@job ||= job_from_id || job_from_ref
end
- # rubocop: disable CodeReuse/ActiveRecord
def job_from_id
- project.builds.find_by(id: params[:build_id]) if params[:build_id]
+ project.builds.find_by_id(params[:build_id]) if params[:build_id]
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def job_from_ref
return unless @ref_name
- jobs = project.latest_successful_builds_for(@ref_name)
- jobs.find_by(name: params[:job])
+ project.latest_successful_build_for(params[:job], @ref_name)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/projects/ci/lints_controller.rb b/app/controllers/projects/ci/lints_controller.rb
index 2090af0a111..d7a0b7ece14 100644
--- a/app/controllers/projects/ci/lints_controller.rb
+++ b/app/controllers/projects/ci/lints_controller.rb
@@ -8,7 +8,7 @@ class Projects::Ci::LintsController < Projects::ApplicationController
def create
@content = params[:content]
- @error = Gitlab::Ci::YamlProcessor.validation_message(@content, yaml_processor_options)
+ @error = Gitlab::Ci::YamlProcessor.validation_message(@content, yaml_processor_options)
@status = @error.blank?
if @error.blank?
@@ -24,6 +24,10 @@ class Projects::Ci::LintsController < Projects::ApplicationController
private
def yaml_processor_options
- { project: @project, sha: project.repository.commit.sha }
+ {
+ project: @project,
+ user: current_user,
+ sha: project.repository.commit.sha
+ }
end
end
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 32fc5140366..939a09d4fd2 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -24,10 +24,10 @@ class Projects::CommitController < Projects::ApplicationController
apply_diff_view_cookie!
respond_to do |format|
- format.html do
+ format.html do
render
end
- format.diff do
+ format.diff do
send_git_diff(@project.repository, @commit.diff_refs)
end
format.patch do
@@ -65,7 +65,11 @@ class Projects::CommitController < Projects::ApplicationController
# rubocop: enable CodeReuse/ActiveRecord
def merge_requests
- @merge_requests = @commit.merge_requests.map do |mr|
+ @merge_requests = MergeRequestsFinder.new(
+ current_user,
+ project_id: @project.id,
+ commit_sha: @commit.sha
+ ).execute.map do |mr|
{ iid: mr.iid, path: merge_request_path(mr), title: mr.title }
end
diff --git a/app/controllers/projects/discussions_controller.rb b/app/controllers/projects/discussions_controller.rb
index b62606067c0..028390c7e2a 100644
--- a/app/controllers/projects/discussions_controller.rb
+++ b/app/controllers/projects/discussions_controller.rb
@@ -40,7 +40,7 @@ class Projects::DiscussionsController < Projects::ApplicationController
def render_json_with_discussions_serializer
render json:
- DiscussionSerializer.new(project: project, noteable: discussion.noteable, current_user: current_user, note_entity: ProjectNoteEntity)
+ DiscussionSerializer.new(project: project, noteable: discussion.noteable, current_user: current_user, note_entity: ProjectNoteEntity)
.represent(discussion, context: self, render_truncated_diff_lines: true)
end
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index a63eea0ca0e..e9cd475a199 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -11,10 +11,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
before_action :verify_api_request!, only: :terminal_websocket_authorize
before_action :expire_etag_cache, only: [:index]
- before_action do
- push_frontend_feature_flag(:area_chart, project)
- end
-
def index
@environments = project.environments
.with_state(params[:scope] || :available)
@@ -25,11 +21,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
Gitlab::PollingInterval.set_header(response, interval: 3_000)
render json: {
- environments: EnvironmentSerializer
- .new(project: @project, current_user: @current_user)
- .with_pagination(request, response)
- .within_folders
- .represent(@environments),
+ environments: serialize_environments(request, response, params[:nested]),
available_count: project.environments.available.count,
stopped_count: project.environments.stopped.count
}
@@ -37,6 +29,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
end
end
+ # Returns all environments for a given folder
# rubocop: disable CodeReuse/ActiveRecord
def folder
folder_environments = project.environments.where(environment_type: params[:id])
@@ -48,10 +41,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
format.html
format.json do
render json: {
- environments: EnvironmentSerializer
- .new(project: @project, current_user: @current_user)
- .with_pagination(request, response)
- .represent(@environments),
+ environments: serialize_environments(request, response),
available_count: folder_environments.available.count,
stopped_count: folder_environments.stopped.count
}
@@ -163,6 +153,16 @@ class Projects::EnvironmentsController < Projects::ApplicationController
end
end
+ def search
+ respond_to do |format|
+ format.json do
+ environment_names = search_environment_names
+
+ render json: environment_names, status: environment_names.any? ? :ok : :no_content
+ end
+ end
+ end
+
private
def verify_api_request!
@@ -186,6 +186,20 @@ class Projects::EnvironmentsController < Projects::ApplicationController
@environment ||= project.environments.find(params[:id])
end
+ def search_environment_names
+ return [] unless params[:query]
+
+ project.environments.for_name_like(params[:query]).pluck_names
+ end
+
+ def serialize_environments(request, response, nested = false)
+ EnvironmentSerializer
+ .new(project: @project, current_user: @current_user)
+ .tap { |serializer| serializer.within_folders if nested }
+ .with_pagination(request, response)
+ .represent(@environments)
+ end
+
def authorize_stop_environment!
access_denied! unless can?(current_user, :stop_environment, environment)
end
diff --git a/app/controllers/projects/error_tracking_controller.rb b/app/controllers/projects/error_tracking_controller.rb
new file mode 100644
index 00000000000..88d0755f41f
--- /dev/null
+++ b/app/controllers/projects/error_tracking_controller.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+class Projects::ErrorTrackingController < Projects::ApplicationController
+ before_action :authorize_read_sentry_issue!
+
+ POLLING_INTERVAL = 10_000
+
+ def index
+ respond_to do |format|
+ format.html
+ format.json do
+ set_polling_interval
+ render_index_json
+ end
+ end
+ end
+
+ def list_projects
+ respond_to do |format|
+ format.json do
+ render_project_list_json
+ end
+ end
+ end
+
+ private
+
+ def render_index_json
+ service = ErrorTracking::ListIssuesService.new(project, current_user)
+ result = service.execute
+
+ unless result[:status] == :success
+ return render json: { message: result[:message] },
+ status: result[:http_status] || :bad_request
+ end
+
+ render json: {
+ errors: serialize_errors(result[:issues]),
+ external_url: service.external_url
+ }
+ end
+
+ def render_project_list_json
+ service = ErrorTracking::ListProjectsService.new(
+ project,
+ current_user,
+ list_projects_params
+ )
+ result = service.execute
+
+ if result[:status] == :success
+ render json: {
+ projects: serialize_projects(result[:projects])
+ }
+ else
+ return render(
+ status: result[:http_status] || :bad_request,
+ json: {
+ message: result[:message]
+ }
+ )
+ end
+ end
+
+ def list_projects_params
+ params.require(:error_tracking_setting).permit([:api_host, :token])
+ end
+
+ def set_polling_interval
+ Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL)
+ end
+
+ def serialize_errors(errors)
+ ErrorTracking::ErrorSerializer
+ .new(project: project, user: current_user)
+ .represent(errors)
+ end
+
+ def serialize_projects(projects)
+ ErrorTracking::ProjectSerializer
+ .new(project: project, user: current_user)
+ .represent(projects)
+ end
+end
diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb
index c0aa39d87c6..0c5328fc941 100644
--- a/app/controllers/projects/git_http_controller.rb
+++ b/app/controllers/projects/git_http_controller.rb
@@ -20,6 +20,8 @@ class Projects::GitHttpController < Projects::GitHttpClientController
# POST /foo/bar.git/git-upload-pack (git pull)
def git_upload_pack
+ enqueue_fetch_statistics_update
+
render_ok
end
@@ -67,6 +69,13 @@ class Projects::GitHttpController < Projects::GitHttpClientController
render plain: exception.message, status: :service_unavailable
end
+ def enqueue_fetch_statistics_update
+ return if wiki?
+ return unless project.daily_statistics_enabled?
+
+ ProjectDailyStatisticsWorker.perform_async(project.id)
+ end
+
def access
@access ||= access_klass.new(access_actor, project,
'http', authentication_abilities: authentication_abilities,
@@ -80,9 +89,7 @@ class Projects::GitHttpController < Projects::GitHttpClientController
end
def access_check
- # Use the magic string '_any' to indicate we do not know what the
- # changes are. This is also what gitlab-shell does.
- access.check(git_command, '_any')
+ access.check(git_command, Gitlab::GitAccess::ANY)
@project ||= access.project
end
diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb
index 925b6ed9bfd..c80fce513f6 100644
--- a/app/controllers/projects/graphs_controller.rb
+++ b/app/controllers/projects/graphs_controller.rb
@@ -45,7 +45,14 @@ class Projects::GraphsController < Projects::ApplicationController
end
def get_languages
- @languages = @project.repository.languages
+ @languages =
+ if @project.repository_languages.present?
+ @project.repository_languages.map do |lang|
+ { value: lang.share, label: lang.name, color: lang.color, highlight: lang.color }
+ end
+ else
+ @project.repository.languages
+ end
end
def fetch_graph
diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb
index 7c713c19762..bc942ba9288 100644
--- a/app/controllers/projects/group_links_controller.rb
+++ b/app/controllers/projects/group_links_controller.rb
@@ -13,9 +13,10 @@ class Projects::GroupLinksController < Projects::ApplicationController
group = Group.find(params[:link_group_id]) if params[:link_group_id].present?
if group
- return render_404 unless can?(current_user, :read_group, group)
+ result = Projects::GroupLinks::CreateService.new(project, current_user, group_link_create_params).execute(group)
+ return render_404 if result[:http_status] == 404
- Projects::GroupLinks::CreateService.new(project, current_user, group_link_create_params).execute(group)
+ flash[:alert] = result[:message] if result[:http_status] == 409
else
flash[:alert] = 'Please select a group.'
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 5ed46fc0545..b9d02a62fc3 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -8,9 +8,10 @@ class Projects::IssuesController < Projects::ApplicationController
include IssuableCollections
include IssuesCalendar
include SpammableActions
+ include RecordUserLastActivity
def self.issue_except_actions
- %i[index calendar new create bulk_update]
+ %i[index calendar new create bulk_update import_csv]
end
def self.set_issuables_index_only_actions
@@ -19,7 +20,7 @@ class Projects::IssuesController < Projects::ApplicationController
prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) }
- prepend_before_action :authenticate_new_issue!, only: [:new]
+ prepend_before_action :authenticate_user!, only: [:new]
prepend_before_action :store_uri, only: [:new, :show]
before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update]
@@ -37,6 +38,8 @@ class Projects::IssuesController < Projects::ApplicationController
# Allow create a new branch and empty WIP merge request from current issue
before_action :authorize_create_merge_request_from!, only: [:create_merge_request]
+ before_action :authorize_import_issues!, only: [:import_csv]
+
before_action :set_suggested_issues_feature_flags, only: [:new]
respond_to :html
@@ -175,8 +178,24 @@ class Projects::IssuesController < Projects::ApplicationController
end
end
+ def import_csv
+ if uploader = UploadService.new(project, params[:file]).execute
+ ImportIssuesCsvWorker.perform_async(current_user.id, project.id, uploader.upload.id)
+
+ flash[:notice] = _("Your issues are being imported. Once finished, you'll get a confirmation email.")
+ else
+ flash[:alert] = _("File upload error.")
+ end
+
+ redirect_to project_issues_path(project)
+ end
+
protected
+ def issuable_sorting_field
+ Issue::SORTING_PREFERENCE_FIELD
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def issue
return @issue if defined?(@issue)
@@ -228,15 +247,7 @@ class Projects::IssuesController < Projects::ApplicationController
task_num
lock_version
discussion_locked
- ] + [{ label_ids: [], assignee_ids: [] }]
- end
-
- def authenticate_new_issue!
- return if current_user
-
- notice = "Please sign in to create the new issue."
-
- redirect_to new_user_session_path, notice: notice
+ ] + [{ label_ids: [], assignee_ids: [], update_task: [:index, :checked, :line_number, :line_source] }]
end
def store_uri
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index bfbbcba883f..d5ce790e2d9 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -4,10 +4,10 @@ class Projects::JobsController < Projects::ApplicationController
include SendFileUpload
include ContinueParams
- before_action :build, except: [:index, :cancel_all]
+ before_action :build, except: [:index]
before_action :authorize_read_build!
before_action :authorize_update_build!,
- except: [:index, :show, :status, :raw, :trace, :cancel_all, :erase]
+ except: [:index, :show, :status, :raw, :trace, :erase]
before_action :authorize_erase_build!, only: [:erase]
before_action :authorize_use_build_terminal!, only: [:terminal, :terminal_websocket_authorize]
before_action :verify_api_request!, only: :terminal_websocket_authorize
@@ -39,16 +39,6 @@ class Projects::JobsController < Projects::ApplicationController
end
# rubocop: enable CodeReuse/ActiveRecord
- def cancel_all
- return access_denied! unless can?(current_user, :update_build, project)
-
- @project.builds.running_or_pending.each do |build|
- build.cancel if can?(current_user, :update_build, build)
- end
-
- redirect_to project_jobs_path(project)
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def show
@pipeline = @build.pipeline
diff --git a/app/controllers/projects/lfs_locks_api_controller.rb b/app/controllers/projects/lfs_locks_api_controller.rb
index fc67cd72faa..6aacb9d9a56 100644
--- a/app/controllers/projects/lfs_locks_api_controller.rb
+++ b/app/controllers/projects/lfs_locks_api_controller.rb
@@ -4,19 +4,19 @@ class Projects::LfsLocksApiController < Projects::GitHttpClientController
include LfsRequest
def create
- @result = Lfs::LockFileService.new(project, user, params).execute
+ @result = Lfs::LockFileService.new(project, user, lfs_params).execute
render_json(@result[:lock])
end
def unlock
- @result = Lfs::UnlockFileService.new(project, user, params).execute
+ @result = Lfs::UnlockFileService.new(project, user, lfs_params).execute
render_json(@result[:lock])
end
def index
- @result = Lfs::LocksFinderService.new(project, user, params).execute
+ @result = Lfs::LocksFinderService.new(project, user, lfs_params).execute
render_json(@result[:locks])
end
@@ -69,4 +69,8 @@ class Projects::LfsLocksApiController < Projects::GitHttpClientController
def upload_request?
%w(create unlock verify).include?(params[:action])
end
+
+ def lfs_params
+ params.permit(:id, :path, :force)
+ end
end
diff --git a/app/controllers/projects/lfs_storage_controller.rb b/app/controllers/projects/lfs_storage_controller.rb
index babeee48ef3..013e01b82aa 100644
--- a/app/controllers/projects/lfs_storage_controller.rb
+++ b/app/controllers/projects/lfs_storage_controller.rb
@@ -5,7 +5,7 @@ class Projects::LfsStorageController < Projects::GitHttpClientController
include WorkhorseRequest
include SendFileUpload
- skip_before_action :verify_workhorse_api!, only: [:download, :upload_finalize]
+ skip_before_action :verify_workhorse_api!, only: :download
def download
lfs_object = LfsObject.find_by_oid(oid)
diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb
index 368ee89ff5c..6045ee4e171 100644
--- a/app/controllers/projects/merge_requests/application_controller.rb
+++ b/app/controllers/projects/merge_requests/application_controller.rb
@@ -34,13 +34,17 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
:task_num,
:title,
:discussion_locked,
- label_ids: []
+ label_ids: [],
+ update_task: [:index, :checked, :line_number, :line_source]
]
end
def set_pipeline_variables
- @pipelines = @merge_request.all_pipelines
- @pipeline = @merge_request.head_pipeline
- @statuses_count = @pipeline.present? ? @pipeline.statuses.relevant.count : 0
+ @pipelines =
+ if can?(current_user, :read_pipeline, @project)
+ @merge_request.all_pipelines
+ else
+ Ci::Pipeline.none
+ end
end
end
diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb
index 5639402a1e9..32cefe54613 100644
--- a/app/controllers/projects/merge_requests/creations_controller.rb
+++ b/app/controllers/projects/merge_requests/creations_controller.rb
@@ -89,7 +89,11 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
def build_merge_request
params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
- @merge_request = ::MergeRequests::BuildService.new(project, current_user, merge_request_params.merge(diff_options: diff_options)).execute
+
+ # Gitaly N+1 issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/58096
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ @merge_request = ::MergeRequests::BuildService.new(project, current_user, merge_request_params.merge(diff_options: diff_options)).execute
+ end
end
def define_new_vars
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index ddffbb17ace..456d2c34768 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Projects::MergeRequests::DiffsController < Projects::MergeRequests::ApplicationController
- include DiffForPath
include DiffHelper
include RendersNotes
@@ -47,8 +46,8 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
# rubocop: disable CodeReuse/ActiveRecord
def commit
- return nil unless commit_id = params[:commit_id].presence
- return nil unless @merge_request.all_commits.exists?(sha: commit_id)
+ return unless commit_id = params[:commit_id].presence
+ return unless @merge_request.all_commits.exists?(sha: commit_id)
@commit ||= @project.commit(commit_id)
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 8b8eac7ff8e..46a44841c31 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -7,6 +7,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
include RendersCommits
include ToggleAwardEmoji
include IssuableCollections
+ include RecordUserLastActivity
skip_before_action :merge_request, only: [:index, :bulk_update]
before_action :whitelist_query_limiting, only: [:assign_related_issues, :update]
@@ -15,6 +16,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :authenticate_user!, only: [:assign_related_issues]
before_action :check_user_can_push_to_source_branch!, only: [:rebase]
+ before_action only: [:show] do
+ push_frontend_feature_flag(:diff_tree_filtering, default_enabled: true)
+ end
+
def index
@merge_requests = @issuables
@@ -55,7 +60,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
render json: serializer.represent(@merge_request, serializer: params[:serializer])
end
- format.patch do
+ format.patch do
break render_404 unless @merge_request.diff_refs
send_git_patch @project.repository, @merge_request.diff_refs
@@ -218,18 +223,28 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
head :ok
end
+ def discussions
+ merge_request.preload_discussions_diff_highlight
+
+ super
+ end
+
protected
alias_method :subscribable_resource, :merge_request
alias_method :issuable, :merge_request
alias_method :awardable, :merge_request
+ def issuable_sorting_field
+ MergeRequest::SORTING_PREFERENCE_FIELD
+ end
+
def merge_params
params.permit(merge_params_attributes)
end
def merge_params_attributes
- [:should_remove_source_branch, :commit_message, :squash]
+ [:should_remove_source_branch, :commit_message, :squash_commit_message, :squash]
end
def merge_when_pipeline_succeeds_active?
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index 8e68014a30d..f6f61b6e5fb 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -144,9 +144,9 @@ class Projects::MilestonesController < Projects::ApplicationController
def search_params
if request.format.json? && project_group && can?(current_user, :read_group, project_group)
- groups = project_group.self_and_ancestors_ids
+ groups = project_group.self_and_ancestors.select(:id)
end
- params.permit(:state).merge(project_ids: @project.id, group_ids: groups)
+ params.permit(:state, :search_title).merge(project_ids: @project.id, group_ids: groups)
end
end
diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb
index c1ad6707c97..73e629ab7c3 100644
--- a/app/controllers/projects/pages_controller.rb
+++ b/app/controllers/projects/pages_controller.rb
@@ -5,7 +5,8 @@ class Projects::PagesController < Projects::ApplicationController
before_action :require_pages_enabled!
before_action :authorize_read_pages!, only: [:show]
- before_action :authorize_update_pages!, except: [:show]
+ before_action :authorize_update_pages!, except: [:show, :destroy]
+ before_action :authorize_remove_pages!, only: [:destroy]
# rubocop: disable CodeReuse/ActiveRecord
def show
@@ -18,7 +19,7 @@ class Projects::PagesController < Projects::ApplicationController
project.pages_domains.destroy_all # rubocop: disable DestroyAll
respond_to do |format|
- format.html do
+ format.html do
redirect_to project_pages_path(@project),
status: 302,
notice: 'Pages were removed'
diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb
index 439ec9b1731..58b1bc54181 100644
--- a/app/controllers/projects/pages_domains_controller.rb
+++ b/app/controllers/projects/pages_domains_controller.rb
@@ -4,7 +4,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController
layout 'project_settings'
before_action :require_pages_enabled!
- before_action :authorize_update_pages!, except: [:show]
+ before_action :authorize_update_pages!
before_action :domain, except: [:new, :create]
def show
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 67827b1d3bb..6a86f8ca729 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -4,6 +4,7 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :whitelist_query_limiting, only: [:create, :retry]
before_action :pipeline, except: [:index, :new, :create, :charts]
before_action :authorize_read_pipeline!
+ before_action :authorize_read_build!, only: [:index]
before_action :authorize_create_pipeline!, only: [:new, :create]
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
@@ -69,7 +70,7 @@ class Projects::PipelinesController < Projects::ApplicationController
render json: PipelineSerializer
.new(project: @project, current_user: @current_user)
- .represent(@pipeline, grouped: true)
+ .represent(@pipeline, show_represent_params)
end
end
end
@@ -157,6 +158,10 @@ class Projects::PipelinesController < Projects::ApplicationController
end
end
+ def show_represent_params
+ { grouped: true }
+ end
+
def create_params
params.require(:pipeline).permit(:ref, variables_attributes: %i[key secret_value])
end
diff --git a/app/controllers/projects/pipelines_settings_controller.rb b/app/controllers/projects/pipelines_settings_controller.rb
index 192e6d38f36..7f988110977 100644
--- a/app/controllers/projects/pipelines_settings_controller.rb
+++ b/app/controllers/projects/pipelines_settings_controller.rb
@@ -4,6 +4,6 @@ class Projects::PipelinesSettingsController < Projects::ApplicationController
before_action :authorize_admin_pipeline!
def show
- redirect_to project_settings_ci_cd_path(@project, params: params)
+ redirect_to project_settings_ci_cd_path(@project, params: params.to_unsafe_h)
end
end
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
index 58d5ea4762f..4c39ee4045f 100644
--- a/app/controllers/projects/releases_controller.rb
+++ b/app/controllers/projects/releases_controller.rb
@@ -3,17 +3,8 @@
class Projects::ReleasesController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
- before_action :authorize_download_code!
- before_action :check_releases_page_feature_flag
+ before_action :authorize_read_release!
def index
end
-
- private
-
- def check_releases_page_feature_flag
- return render_404 unless Feature.enabled?(:releases_page)
-
- push_frontend_feature_flag(:releases_page)
- end
end
diff --git a/app/controllers/projects/serverless/functions_controller.rb b/app/controllers/projects/serverless/functions_controller.rb
index 0af2b7ef343..39eca10134f 100644
--- a/app/controllers/projects/serverless/functions_controller.rb
+++ b/app/controllers/projects/serverless/functions_controller.rb
@@ -7,19 +7,17 @@ module Projects
before_action :authorize_read_cluster!
- INDEX_PRIMING_INTERVAL = 10_000
- INDEX_POLLING_INTERVAL = 30_000
+ INDEX_PRIMING_INTERVAL = 15_000
+ INDEX_POLLING_INTERVAL = 60_000
def index
- finder = Projects::Serverless::FunctionsFinder.new(project.clusters)
-
respond_to do |format|
format.json do
functions = finder.execute
if functions.any?
Gitlab::PollingInterval.set_header(response, interval: INDEX_POLLING_INTERVAL)
- render json: Projects::Serverless::ServiceSerializer.new(current_user: @current_user).represent(functions)
+ render json: serialize_function(functions)
else
Gitlab::PollingInterval.set_header(response, interval: INDEX_PRIMING_INTERVAL)
head :no_content
@@ -32,6 +30,29 @@ module Projects
end
end
end
+
+ def show
+ @service = serialize_function(finder.service(params[:environment_id], params[:id]))
+ return not_found if @service.nil?
+
+ respond_to do |format|
+ format.json do
+ render json: @service
+ end
+
+ format.html
+ end
+ end
+
+ private
+
+ def finder
+ Projects::Serverless::FunctionsFinder.new(project.clusters)
+ end
+
+ def serialize_function(function)
+ Projects::Serverless::ServiceSerializer.new(current_user: @current_user, project: project).represent(function)
+ end
end
end
end
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 75e590f3f33..f2f63e986bb 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -99,7 +99,9 @@ module Projects
def define_triggers_variables
@triggers = @project.triggers
+ .present(current_user: current_user)
@trigger = ::Ci::Trigger.new
+ .present(current_user: current_user)
end
def define_badges_variables
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
new file mode 100644
index 00000000000..7276964b6e1
--- /dev/null
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module Projects
+ module Settings
+ class OperationsController < Projects::ApplicationController
+ before_action :check_license
+ before_action :authorize_update_environment!
+
+ helper_method :error_tracking_setting
+
+ def show
+ end
+
+ def update
+ result = ::Projects::Operations::UpdateService.new(project, current_user, update_params).execute
+
+ render_update_response(result)
+ end
+
+ private
+
+ # overridden in EE
+ def render_update_response(result)
+ respond_to do |format|
+ format.json do
+ render_update_json_response(result)
+ end
+ end
+ end
+
+ def render_update_json_response(result)
+ if result[:status] == :success
+ flash[:notice] = _('Your changes have been saved')
+ render json: {
+ status: result[:status]
+ }
+ else
+ render(
+ status: result[:http_status] || :bad_request,
+ json: {
+ status: result[:status],
+ message: result[:message]
+ }
+ )
+ end
+ end
+
+ def error_tracking_setting
+ @error_tracking_setting ||= project.error_tracking_setting ||
+ project.build_error_tracking_setting
+ end
+
+ def update_params
+ params.require(:project).permit(permitted_project_params)
+ end
+
+ # overridden in EE
+ def permitted_project_params
+ {
+ error_tracking_setting_attributes: [
+ :enabled,
+ :api_host,
+ :token,
+ project: [:slug, :name, :organization_slug, :organization_name]
+ ]
+ }
+ end
+
+ def check_license
+ render_404 unless helpers.settings_operations_available?
+ end
+ end
+ end
+end
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index a44acb12bdf..255f1f3569a 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -75,7 +75,14 @@ class Projects::SnippetsController < Projects::ApplicationController
format.json do
render_blob_json(blob)
end
- format.js { render 'shared/snippets/show'}
+
+ format.js do
+ if @snippet.embeddable?
+ render 'shared/snippets/show'
+ else
+ head :not_found
+ end
+ end
end
end
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index a50a1475eb2..a17c050b696 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -43,9 +43,22 @@ class Projects::TagsController < Projects::ApplicationController
def create
result = ::Tags::CreateService.new(@project, current_user)
- .execute(params[:tag_name], params[:ref], params[:message], params[:release_description])
+ .execute(params[:tag_name], params[:ref], params[:message])
if result[:status] == :success
+ # Release creation with Tags was deprecated in GitLab 11.7
+ if params[:release_description].present?
+ release_params = {
+ tag: params[:tag_name],
+ name: params[:tag_name],
+ description: params[:release_description]
+ }
+
+ Releases::CreateService
+ .new(@project, current_user, release_params)
+ .execute
+ end
+
@tag = result[:tag]
redirect_to project_tag_path(@project, @tag.name)
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index 3fe300dcfc0..edebfc55c17 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -31,20 +31,6 @@ class Projects::TreeController < Projects::ApplicationController
lfs_blob_ids
@last_commit = @repository.last_commit_for_path(@commit.id, @tree.path) || @commit
end
-
- format.js do
- # Disable cache so browser history works
- no_cache_headers
- end
-
- format.json do
- page_title @path.presence || _("Files"), @ref, @project.full_name
-
- # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/38261
- Gitlab::GitalyClient.allow_n_plus_1_calls do
- render json: TreeSerializer.new(project: @project, repository: @repository, ref: @ref).represent(@tree)
- end
- end
end
end
diff --git a/app/controllers/projects/triggers_controller.rb b/app/controllers/projects/triggers_controller.rb
index f5fdfb8accc..c7b4ebb2b24 100644
--- a/app/controllers/projects/triggers_controller.rb
+++ b/app/controllers/projects/triggers_controller.rb
@@ -66,12 +66,11 @@ class Projects::TriggersController < Projects::ApplicationController
end
def trigger
- @trigger ||= project.triggers.find(params[:id]) || render_404
+ @trigger ||= project.triggers.find(params[:id])
+ .present(current_user: current_user)
end
def trigger_params
- params.require(:trigger).permit(
- :description
- )
+ params.require(:trigger).permit(:description)
end
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 8bf93bfd68d..33c6608d321 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -6,19 +6,21 @@ class ProjectsController < Projects::ApplicationController
include ExtractsPath
include PreviewMarkdown
include SendFileUpload
+ include RecordUserLastActivity
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
before_action :whitelist_query_limiting, only: [:create]
- before_action :authenticate_user!, except: [:index, :show, :activity, :refs]
+ before_action :authenticate_user!, except: [:index, :show, :activity, :refs, :resolve]
before_action :redirect_git_extension, only: [:show]
- before_action :project, except: [:index, :new, :create]
- before_action :repository, except: [:index, :new, :create]
+ before_action :project, except: [:index, :new, :create, :resolve]
+ before_action :repository, except: [:index, :new, :create, :resolve]
before_action :assign_ref_vars, only: [:show], if: :repo_exists?
before_action :tree, only: [:show], if: [:repo_exists?, :project_view_files?]
before_action :lfs_blob_ids, only: [:show], if: [:repo_exists?, :project_view_files?]
before_action :project_export_enabled, only: [:export, :download_export, :remove_export, :generate_new_export]
before_action :present_project, only: [:edit]
+ before_action :authorize_download_code!, only: [:refs]
# Authorize
before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export]
@@ -441,4 +443,14 @@ class ProjectsController < Projects::ApplicationController
def present_project
@project = @project.present(current_user: current_user)
end
+
+ def resolve
+ @project = Project.find(params[:id])
+
+ if can?(current_user, :read_project, @project)
+ redirect_to @project
+ else
+ render_404
+ end
+ end
end
diff --git a/app/controllers/sherlock/transactions_controller.rb b/app/controllers/sherlock/transactions_controller.rb
index 46e382e594e..8d1847507cc 100644
--- a/app/controllers/sherlock/transactions_controller.rb
+++ b/app/controllers/sherlock/transactions_controller.rb
@@ -15,7 +15,7 @@ module Sherlock
def destroy_all
Gitlab::Sherlock.collection.clear
- redirect_to :back, status: :found
+ redirect_back_or_default(options: { status: :found })
end
end
end
diff --git a/app/controllers/snippets/notes_controller.rb b/app/controllers/snippets/notes_controller.rb
index 091bcb1253d..eee14b0faf4 100644
--- a/app/controllers/snippets/notes_controller.rb
+++ b/app/controllers/snippets/notes_controller.rb
@@ -26,10 +26,6 @@ class Snippets::NotesController < ApplicationController
# rubocop: enable CodeReuse/ActiveRecord
alias_method :noteable, :snippet
- def note_params
- super.merge(noteable_id: params[:snippet_id])
- end
-
def finder_params
params.merge(last_fetched_at: last_fetched_at, target_id: snippet.id, target_type: 'personal_snippet')
end
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index dd9bf17cf0c..8ea5450b4e8 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -80,7 +80,13 @@ class SnippetsController < ApplicationController
render_blob_json(blob)
end
- format.js { render 'shared/snippets/show' }
+ format.js do
+ if @snippet.embeddable?
+ render 'shared/snippets/show'
+ else
+ head :not_found
+ end
+ end
end
end
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index fa5d84633b5..568c6e2a852 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -28,13 +28,13 @@ class UploadsController < ApplicationController
end
def find_model
- return nil unless params[:id]
+ return unless params[:id]
upload_model_class.find(params[:id])
end
def authorize_access!
- return nil unless model
+ return unless model
authorized =
case model
@@ -54,7 +54,7 @@ class UploadsController < ApplicationController
end
def authorize_create_access!
- return nil unless model
+ return unless model
# for now we support only personal snippets comments
authorized = can?(current_user, :comment_personal_snippet, model)
@@ -70,6 +70,10 @@ class UploadsController < ApplicationController
end
end
+ def cache_publicly?
+ User === model || Appearance === model
+ end
+
def upload_model_class
MODEL_CLASSES[params[:model]] || raise(UnknownUploadModelError)
end
diff --git a/app/finders/admin/runners_finder.rb b/app/finders/admin/runners_finder.rb
index fbb1cfc5c66..b2799565f57 100644
--- a/app/finders/admin/runners_finder.rb
+++ b/app/finders/admin/runners_finder.rb
@@ -11,10 +11,11 @@ class Admin::RunnersFinder < UnionFinder
search!
filter_by_status!
filter_by_runner_type!
+ filter_by_tag_list!
sort!
paginate!
- @runners
+ @runners.with_tags
end
def sort_key
@@ -44,6 +45,14 @@ class Admin::RunnersFinder < UnionFinder
filter_by!(:type_type, Ci::Runner::AVAILABLE_TYPES)
end
+ def filter_by_tag_list!
+ tag_list = @params[:tag_name].presence
+
+ if tag_list
+ @runners = @runners.tagged_with(tag_list)
+ end
+ end
+
def sort!
@runners = @runners.order_by(sort_key)
end
diff --git a/app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb b/app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb
new file mode 100644
index 00000000000..f38c187799c
--- /dev/null
+++ b/app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Autocomplete
+ module ActsAsTaggableOn
+ class TagsFinder
+ LIMIT = 20
+
+ def initialize(params:)
+ @params = params
+ end
+
+ def execute
+ tags = all_tags
+ tags = filter_by_name(tags)
+ limit(tags)
+ end
+
+ private
+
+ def all_tags
+ ::ActsAsTaggableOn::Tag.all
+ end
+
+ def filter_by_name(tags)
+ return tags unless search
+ return tags.none if search.empty?
+
+ if search.length >= Gitlab::SQL::Pattern::MIN_CHARS_FOR_PARTIAL_MATCHING
+ tags.named_like(search)
+ else
+ tags.named(search)
+ end
+ end
+
+ def limit(tags)
+ tags.limit(LIMIT) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def search
+ @params[:search]
+ end
+ end
+ end
+end
diff --git a/app/finders/concerns/finder_methods.rb b/app/finders/concerns/finder_methods.rb
index 5290313585f..8de3276184d 100644
--- a/app/finders/concerns/finder_methods.rb
+++ b/app/finders/concerns/finder_methods.rb
@@ -3,13 +3,13 @@
module FinderMethods
# rubocop: disable CodeReuse/ActiveRecord
def find_by!(*args)
- raise_not_found_unless_authorized execute.find_by!(*args)
+ raise_not_found_unless_authorized execute.reorder(nil).find_by!(*args)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def find_by(*args)
- if_authorized execute.find_by(*args)
+ if_authorized execute.reorder(nil).find_by(*args)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/finders/contributed_projects_finder.rb b/app/finders/contributed_projects_finder.rb
index c1ef9dfefa7..f8c7f0c3167 100644
--- a/app/finders/contributed_projects_finder.rb
+++ b/app/finders/contributed_projects_finder.rb
@@ -14,6 +14,9 @@ class ContributedProjectsFinder < UnionFinder
# Returns an ActiveRecord::Relation.
# rubocop: disable CodeReuse/ActiveRecord
def execute(current_user = nil)
+ # Do not show contributed projects if the user profile is private.
+ return Project.none unless can_read_profile?(current_user)
+
segments = all_projects(current_user)
find_union(segments, Project).includes(:namespace).order_id_desc
@@ -22,6 +25,10 @@ class ContributedProjectsFinder < UnionFinder
private
+ def can_read_profile?(current_user)
+ Ability.allowed?(current_user, :read_user_profile, @user)
+ end
+
def all_projects(current_user)
projects = []
diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb
index 96a36db7ec8..ec340f38450 100644
--- a/app/finders/group_descendants_finder.rb
+++ b/app/finders/group_descendants_finder.rb
@@ -134,7 +134,7 @@ class GroupDescendantsFinder
def subgroups
return Group.none unless Group.supports_nested_objects?
- # When filtering subgroups, we want to find all matches withing the tree of
+ # When filtering subgroups, we want to find all matches within the tree of
# descendants to show to the user
groups = if params[:filter]
subgroups_matching_filter
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index b73a3fa6e01..072d07e0ed2 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -18,6 +18,7 @@
# assignee_id: integer or 'None' or 'Any'
# assignee_username: string
# search: string
+# in: 'title', 'description', or a string joining them with comma
# label_name: string
# sort: string
# non_archived: boolean
@@ -56,6 +57,7 @@ class IssuableFinder
milestone_title
my_reaction_emoji
search
+ in
]
end
@@ -76,13 +78,15 @@ class IssuableFinder
items = init_collection
items = filter_items(items)
- # This has to be last as we may use a CTE as an optimization fence
- # by passing the attempt_group_search_optimizations param and
- # enabling the use_cte_for_group_issues_search feature flag
+ # This has to be last as we use a CTE as an optimization fence
+ # for counts by passing the force_cte param and enabling the
+ # attempt_group_search_optimizations feature flag
# https://www.postgresql.org/docs/current/static/queries-with.html
items = by_search(items)
- sort(items)
+ items = sort(items) unless use_cte_for_count?
+
+ items
end
def filter_items(items)
@@ -92,6 +96,7 @@ class IssuableFinder
items = by_scope(items)
items = by_created_at(items)
items = by_updated_at(items)
+ items = by_closed_at(items)
items = by_state(items)
items = by_group(items)
items = by_assignee(items)
@@ -114,8 +119,9 @@ class IssuableFinder
#
# rubocop: disable CodeReuse/ActiveRecord
def count_by_state
- count_params = params.merge(state: nil, sort: nil)
+ count_params = params.merge(state: nil, sort: nil, force_cte: true)
finder = self.class.new(current_user, count_params)
+
counts = Hash.new(0)
# Searching by label includes a GROUP BY in the query, but ours will be last
@@ -125,8 +131,11 @@ class IssuableFinder
#
# This does not apply when we are using a CTE for the search, as the labels
# GROUP BY is inside the subquery in that case, so we set labels_count to 1.
+ #
+ # We always use CTE when searching in Groups if the feature flag is enabled,
+ # but never when searching in Projects.
labels_count = label_names.any? ? label_names.count : 1
- labels_count = 1 if use_cte_for_search?
+ labels_count = 1 if use_cte_for_count?
finder.execute.reorder(nil).group(:state).count.each do |key, value|
counts[count_key(key)] += value / labels_count
@@ -149,6 +158,18 @@ class IssuableFinder
end
end
+ def related_groups
+ if project? && project && project.group && Ability.allowed?(current_user, :read_group, project.group)
+ project.group.self_and_ancestors
+ elsif group
+ [group]
+ elsif current_user
+ Gitlab::ObjectHierarchy.new(current_user.authorized_groups, current_user.groups).all_objects
+ else
+ []
+ end
+ end
+
def project?
params[:project_id].present?
end
@@ -163,8 +184,10 @@ class IssuableFinder
end
# rubocop: disable CodeReuse/ActiveRecord
- def projects(items = nil)
- return @projects = project if project?
+ def projects
+ return @projects if defined?(@projects)
+
+ return @projects = [project] if project?
projects =
if current_user && params[:authorized_only].presence && !current_user_related?
@@ -288,27 +311,31 @@ class IssuableFinder
def use_subquery_for_search?
strong_memoize(:use_subquery_for_search) do
- attempt_group_search_optimizations? &&
- Feature.enabled?(:use_subquery_for_group_issues_search, default_enabled: false)
+ !force_cte? && attempt_group_search_optimizations?
end
end
- def use_cte_for_search?
- strong_memoize(:use_cte_for_search) do
- attempt_group_search_optimizations? &&
- !use_subquery_for_search? &&
- Feature.enabled?(:use_cte_for_group_issues_search, default_enabled: true)
+ def use_cte_for_count?
+ strong_memoize(:use_cte_for_count) do
+ force_cte? && attempt_group_search_optimizations?
end
end
private
+ def force_cte?
+ !!params[:force_cte]
+ end
+
def init_collection
klass.all
end
def attempt_group_search_optimizations?
- search && Gitlab::Database.postgresql? && params[:attempt_group_search_optimizations]
+ search &&
+ Gitlab::Database.postgresql? &&
+ params[:attempt_group_search_optimizations] &&
+ Feature.enabled?(:attempt_group_search_optimizations, default_enabled: true)
end
def count_key(value)
@@ -337,6 +364,13 @@ class IssuableFinder
items
end
+ def by_closed_at(items)
+ items = items.closed_after(params[:closed_after]) if params[:closed_after].present?
+ items = items.closed_before(params[:closed_before]) if params[:closed_before].present?
+
+ items
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def by_state(items)
case params[:state].to_s
@@ -387,14 +421,14 @@ class IssuableFinder
def by_search(items)
return items unless search
- if use_cte_for_search?
+ if use_cte_for_count?
cte = Gitlab::SQL::RecursiveCTE.new(klass.table_name)
cte << items
items = klass.with(cte.to_arel).from(klass.table_name)
end
- items.full_search(search)
+ items.full_search(search, matched_columns: params[:in])
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -459,7 +493,7 @@ class IssuableFinder
elsif filter_by_any_milestone?
items = items.any_milestone
elsif filter_by_upcoming_milestone?
- upcoming_ids = Milestone.upcoming_ids_by_projects(projects(items))
+ upcoming_ids = Milestone.upcoming_ids(projects, related_groups)
items = items.left_joins_milestones.where(milestone_id: upcoming_ids)
elsif filter_by_started_milestone?
items = items.left_joins_milestones.where('milestones.start_date <= NOW()')
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index 45e494725d7..cb44575d6f1 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -14,6 +14,7 @@
# milestone_title: string
# assignee_id: integer
# search: string
+# in: 'title', 'description', or a string joining them with comma
# label_name: string
# sort: string
# my_reaction_emoji: string
@@ -68,7 +69,16 @@ class IssuesFinder < IssuableFinder
end
def filter_items(items)
- by_due_date(super)
+ issues = super
+ issues = by_due_date(issues)
+ issues = by_confidential(issues)
+ issues
+ end
+
+ def by_confidential(items)
+ return items if params[:confidential].nil?
+
+ params[:confidential] ? items.confidential_only : items.public_only
end
def by_due_date(items)
diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb
index e190d5d90c9..93bee3f1488 100644
--- a/app/finders/merge_requests_finder.rb
+++ b/app/finders/merge_requests_finder.rb
@@ -15,6 +15,7 @@
# author_id: integer
# assignee_id: integer
# search: string
+# in: 'title', 'description', or a string joining them with comma
# label_name: string
# sort: string
# non_archived: boolean
@@ -36,13 +37,20 @@ class MergeRequestsFinder < IssuableFinder
end
def filter_items(_items)
- items = by_source_branch(super)
+ items = by_commit(super)
+ items = by_source_branch(items)
items = by_wip(items)
by_target_branch(items)
end
private
+ def by_commit(items)
+ return items unless params[:commit_sha].presence
+
+ items.by_commit_sha(params[:commit_sha])
+ end
+
def source_branch
@source_branch ||= params[:source_branch].presence
end
diff --git a/app/finders/milestones_finder.rb b/app/finders/milestones_finder.rb
index 9c477978f60..77b55cbb838 100644
--- a/app/finders/milestones_finder.rb
+++ b/app/finders/milestones_finder.rb
@@ -3,8 +3,8 @@
# Search for milestones
#
# params - Hash
-# project_ids: Array of project ids or single project id.
-# group_ids: Array of group ids or single group id.
+# project_ids: Array of project ids or single project id or ActiveRecord relation.
+# group_ids: Array of group ids or single group id or ActiveRecord relation.
# order - Orders by field default due date asc.
# title - filter by title.
# state - filters by state.
@@ -12,20 +12,17 @@
class MilestonesFinder
include FinderMethods
- attr_reader :params, :project_ids, :group_ids
+ attr_reader :params
def initialize(params = {})
- @project_ids = Array(params[:project_ids])
- @group_ids = Array(params[:group_ids])
@params = params
end
def execute
- return Milestone.none if project_ids.empty? && group_ids.empty?
-
items = Milestone.all
items = by_groups_and_projects(items)
items = by_title(items)
+ items = by_search_title(items)
items = by_state(items)
order(items)
@@ -34,7 +31,7 @@ class MilestonesFinder
private
def by_groups_and_projects(items)
- items.for_projects_and_groups(project_ids, group_ids)
+ items.for_projects_and_groups(params[:project_ids], params[:group_ids])
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -47,6 +44,14 @@ class MilestonesFinder
end
# rubocop: enable CodeReuse/ActiveRecord
+ def by_search_title(items)
+ if params[:search_title].present?
+ items.search_title(params[:search_title])
+ else
+ items
+ end
+ end
+
def by_state(items)
Milestone.filter_by_state(items, params[:state])
end
diff --git a/app/finders/projects/daily_statistics_finder.rb b/app/finders/projects/daily_statistics_finder.rb
new file mode 100644
index 00000000000..912c23107bc
--- /dev/null
+++ b/app/finders/projects/daily_statistics_finder.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Projects
+ class DailyStatisticsFinder
+ attr_reader :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ def fetches
+ ProjectDailyStatistic.of_project(project)
+ .of_last_30_days
+ .sorted_by_date_desc
+ end
+
+ def total_fetch_count
+ fetches.sum_fetch_count
+ end
+ end
+end
diff --git a/app/finders/projects/serverless/functions_finder.rb b/app/finders/projects/serverless/functions_finder.rb
index 2b5d67e79d7..2f2816a4a08 100644
--- a/app/finders/projects/serverless/functions_finder.rb
+++ b/app/finders/projects/serverless/functions_finder.rb
@@ -15,11 +15,40 @@ module Projects
clusters_with_knative_installed.exists?
end
+ def service(environment_scope, name)
+ knative_service(environment_scope, name)&.first
+ end
+
private
+ def knative_service(environment_scope, name)
+ clusters_with_knative_installed.preload_knative.map do |cluster|
+ next if environment_scope != cluster.environment_scope
+
+ services = cluster.application_knative.services_for(ns: cluster.platform_kubernetes&.actual_namespace)
+ .select { |svc| svc["metadata"]["name"] == name }
+
+ add_metadata(cluster, services).first unless services.nil?
+ end
+ end
+
def knative_services
clusters_with_knative_installed.preload_knative.map do |cluster|
- cluster.application_knative.services_for(ns: cluster.platform_kubernetes&.actual_namespace)
+ services = cluster.application_knative.services_for(ns: cluster.platform_kubernetes&.actual_namespace)
+ add_metadata(cluster, services) unless services.nil?
+ end
+ end
+
+ def add_metadata(cluster, services)
+ services.each do |s|
+ s["environment_scope"] = cluster.environment_scope
+ s["cluster_id"] = cluster.id
+
+ if services.length == 1
+ s["podcount"] = cluster.application_knative.service_pod_details(
+ cluster.platform_kubernetes&.actual_namespace,
+ s["metadata"]["name"]).length
+ end
end
end
diff --git a/app/finders/releases_finder.rb b/app/finders/releases_finder.rb
new file mode 100644
index 00000000000..59e84198fde
--- /dev/null
+++ b/app/finders/releases_finder.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class ReleasesFinder
+ def initialize(project, current_user = nil)
+ @project = project
+ @current_user = current_user
+ end
+
+ def execute
+ return Release.none unless Ability.allowed?(@current_user, :read_release, @project)
+
+ @project.releases.sorted
+ end
+end
diff --git a/app/finders/snippets_finder.rb b/app/finders/snippets_finder.rb
index d3774746cb8..bf29f15642d 100644
--- a/app/finders/snippets_finder.rb
+++ b/app/finders/snippets_finder.rb
@@ -69,6 +69,8 @@ class SnippetsFinder < UnionFinder
base.with_optional_visibility(visibility_from_scope).fresh
end
+ private
+
# Produces a query that retrieves snippets from multiple projects.
#
# The resulting query will, depending on the user's permissions, include the
diff --git a/app/graphql/mutations/merge_requests/base.rb b/app/graphql/mutations/merge_requests/base.rb
index 54f01c99d78..7d0cb777ad1 100644
--- a/app/graphql/mutations/merge_requests/base.rb
+++ b/app/graphql/mutations/merge_requests/base.rb
@@ -25,7 +25,8 @@ module Mutations
def find_object(project_path:, iid:)
project = resolve_project(full_path: project_path)
- resolver = Resolvers::MergeRequestResolver.new(object: project, context: context)
+ resolver = Resolvers::MergeRequestsResolver
+ .single.new(object: project, context: context)
resolver.resolve(iid: iid)
end
diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb
index 459933af9d3..063def75d38 100644
--- a/app/graphql/resolvers/base_resolver.rb
+++ b/app/graphql/resolvers/base_resolver.rb
@@ -2,5 +2,12 @@
module Resolvers
class BaseResolver < GraphQL::Schema::Resolver
+ def self.single
+ @single ||= Class.new(self) do
+ def resolve(**args)
+ super.first
+ end
+ end
+ end
end
end
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index 4ab3c13787a..b98d8bd1fff 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -2,8 +2,37 @@
module Resolvers
class IssuesResolver < BaseResolver
- extend ActiveSupport::Concern
+ argument :iid, GraphQL::ID_TYPE,
+ required: false,
+ description: 'The IID of the issue, e.g., "1"'
+ argument :iids, [GraphQL::ID_TYPE],
+ required: false,
+ description: 'The list of IIDs of issues, e.g., [1, 2]'
+ argument :state, Types::IssuableStateEnum,
+ required: false,
+ description: "Current state of Issue"
+ argument :label_name, GraphQL::STRING_TYPE.to_list_type,
+ required: false,
+ description: "Labels applied to the Issue"
+ argument :created_before, Types::TimeType,
+ required: false,
+ description: "Issues created before this date"
+ argument :created_after, Types::TimeType,
+ required: false,
+ description: "Issues created after this date"
+ argument :updated_before, Types::TimeType,
+ required: false,
+ description: "Issues updated before this date"
+ argument :updated_after, Types::TimeType,
+ required: false,
+ description: "Issues updated after this date"
+ argument :closed_before, Types::TimeType,
+ required: false,
+ description: "Issues closed before this date"
+ argument :closed_after, Types::TimeType,
+ required: false,
+ description: "Issues closed after this date"
argument :search, GraphQL::STRING_TYPE,
required: false
argument :sort, Types::Sort,
@@ -18,6 +47,7 @@ module Resolvers
# Will need to be be made group & namespace aware with
# https://gitlab.com/gitlab-org/gitlab-ce/issues/54520
args[:project_id] = project.id
+ args[:iids] ||= [args[:iid]].compact
IssuesFinder.new(context[:current_user], args).execute
end
diff --git a/app/graphql/resolvers/merge_request_resolver.rb b/app/graphql/resolvers/merge_request_resolver.rb
deleted file mode 100644
index d047ce9e3a1..00000000000
--- a/app/graphql/resolvers/merge_request_resolver.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module Resolvers
- class MergeRequestResolver < BaseResolver
- argument :iid, GraphQL::ID_TYPE,
- required: true,
- description: 'The IID of the merge request, e.g., "1"'
-
- type Types::MergeRequestType, null: true
-
- alias_method :project, :object
-
- # rubocop: disable CodeReuse/ActiveRecord
- def resolve(iid:)
- return unless project.present?
-
- BatchLoader.for(iid.to_s).batch(key: project) do |iids, loader, args|
- args[:key].merge_requests.where(iid: iids).each do |mr|
- loader.call(mr.iid.to_s, mr)
- end
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
-end
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
new file mode 100644
index 00000000000..90795c797ac
--- /dev/null
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class MergeRequestsResolver < BaseResolver
+ argument :iid, GraphQL::ID_TYPE,
+ required: false,
+ description: 'The IID of the merge request, e.g., "1"'
+
+ argument :iids, [GraphQL::ID_TYPE],
+ required: false,
+ description: 'The list of IIDs of issues, e.g., [1, 2]'
+
+ type Types::MergeRequestType, null: true
+
+ alias_method :project, :object
+
+ def resolve(**args)
+ return unless project.present?
+
+ args[:iids] ||= [args[:iid]].compact
+
+ args[:iids].map { |iid| batch_load(iid) }
+ .select(&:itself) # .compact doesn't work on BatchLoader
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def batch_load(iid)
+ BatchLoader.for(iid.to_s).batch(key: project) do |iids, loader, args|
+ args[:key].merge_requests.where(iid: iids).each do |mr|
+ loader.call(mr.iid.to_s, mr)
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/graphql/resolvers/metadata_resolver.rb b/app/graphql/resolvers/metadata_resolver.rb
new file mode 100644
index 00000000000..3a79e6434fb
--- /dev/null
+++ b/app/graphql/resolvers/metadata_resolver.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class MetadataResolver < BaseResolver
+ type Types::MetadataType, null: false
+
+ def resolve(**args)
+ { version: Gitlab::VERSION, revision: Gitlab.revision }
+ end
+ end
+end
diff --git a/app/graphql/types/issuable_state_enum.rb b/app/graphql/types/issuable_state_enum.rb
new file mode 100644
index 00000000000..f2f6d6c6cab
--- /dev/null
+++ b/app/graphql/types/issuable_state_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ class IssuableStateEnum < BaseEnum
+ graphql_name 'IssuableState'
+ description 'State of a GitLab issue or merge request'
+
+ value 'opened'
+ value 'closed'
+ value 'locked'
+ end
+end
diff --git a/app/graphql/types/issue_state_enum.rb b/app/graphql/types/issue_state_enum.rb
new file mode 100644
index 00000000000..6521407fc9d
--- /dev/null
+++ b/app/graphql/types/issue_state_enum.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module Types
+ class IssueStateEnum < IssuableStateEnum
+ graphql_name 'IssueState'
+ description 'State of a GitLab issue'
+ end
+end
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index a8f2f7914a8..5ad3ea52930 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -11,22 +11,20 @@ module Types
field :iid, GraphQL::ID_TYPE, null: false
field :title, GraphQL::STRING_TYPE, null: false
field :description, GraphQL::STRING_TYPE, null: true
- field :state, GraphQL::STRING_TYPE, null: false
+ field :state, IssueStateEnum, null: false
field :author, Types::UserType,
null: false,
- resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, obj.author_id).find } do
- authorize :read_user
- end
+ resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, obj.author_id).find },
+ authorize: :read_user
field :assignees, Types::UserType.connection_type, null: true
field :labels, Types::LabelType.connection_type, null: true
field :milestone, Types::MilestoneType,
null: true,
- resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Milestone, obj.milestone_id).find } do
- authorize :read_milestone
- end
+ resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Milestone, obj.milestone_id).find },
+ authorize: :read_milestone
field :due_date, Types::TimeType, null: true
field :confidential, GraphQL::BOOLEAN_TYPE, null: false
diff --git a/app/graphql/types/merge_request_state_enum.rb b/app/graphql/types/merge_request_state_enum.rb
new file mode 100644
index 00000000000..92f52726ab3
--- /dev/null
+++ b/app/graphql/types/merge_request_state_enum.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Types
+ class MergeRequestStateEnum < IssuableStateEnum
+ graphql_name 'MergeRequestState'
+ description 'State of a GitLab merge request'
+
+ value 'merged'
+ end
+end
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index fb740b6fb1c..1ed27a14e33 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -12,7 +12,7 @@ module Types
field :iid, GraphQL::ID_TYPE, null: false
field :title, GraphQL::STRING_TYPE, null: false
field :description, GraphQL::STRING_TYPE, null: true
- field :state, GraphQL::STRING_TYPE, null: true
+ field :state, MergeRequestStateEnum, null: false
field :created_at, Types::TimeType, null: false
field :updated_at, Types::TimeType, null: false
field :source_project, Types::ProjectType, null: true
@@ -38,8 +38,8 @@ module Types
field :should_be_rebased, GraphQL::BOOLEAN_TYPE, method: :should_be_rebased?, null: false
field :rebase_commit_sha, GraphQL::STRING_TYPE, null: true
field :rebase_in_progress, GraphQL::BOOLEAN_TYPE, method: :rebase_in_progress?, null: false
- field :diff_head_sha, GraphQL::STRING_TYPE, null: true
- field :merge_commit_message, GraphQL::STRING_TYPE, null: true
+ field :merge_commit_message, GraphQL::STRING_TYPE, method: :default_merge_commit_message, null: true, deprecation_reason: "Renamed to defaultMergeCommitMessage"
+ field :default_merge_commit_message, GraphQL::STRING_TYPE, null: true
field :merge_ongoing, GraphQL::BOOLEAN_TYPE, method: :merge_ongoing?, null: false
field :source_branch_exists, GraphQL::BOOLEAN_TYPE, method: :source_branch_exists?, null: false
field :mergeable_discussions_state, GraphQL::BOOLEAN_TYPE, null: true
@@ -48,9 +48,7 @@ module Types
field :downvotes, GraphQL::INT_TYPE, null: false
field :subscribed, GraphQL::BOOLEAN_TYPE, method: :subscribed?, null: false
- field :head_pipeline, Types::Ci::PipelineType, null: true, method: :actual_head_pipeline do
- authorize :read_pipeline
- end
+ field :head_pipeline, Types::Ci::PipelineType, null: true, method: :actual_head_pipeline, authorize: :read_pipeline
field :pipelines, Types::Ci::PipelineType.connection_type,
resolver: Resolvers::MergeRequestPipelinesResolver
end
diff --git a/app/graphql/types/metadata_type.rb b/app/graphql/types/metadata_type.rb
new file mode 100644
index 00000000000..2d8bad0614b
--- /dev/null
+++ b/app/graphql/types/metadata_type.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Types
+ class MetadataType < ::Types::BaseObject
+ graphql_name 'Metadata'
+
+ field :version, GraphQL::STRING_TYPE, null: false
+ field :revision, GraphQL::STRING_TYPE, null: false
+ end
+end
diff --git a/app/graphql/types/permission_types/project.rb b/app/graphql/types/permission_types/project.rb
index ab37c282fe5..e9a4ea9157b 100644
--- a/app/graphql/types/permission_types/project.rb
+++ b/app/graphql/types/permission_types/project.rb
@@ -8,7 +8,7 @@ module Types
abilities :change_namespace, :change_visibility_level, :rename_project,
:remove_project, :archive_project, :remove_fork_project,
:remove_pages, :read_project, :create_merge_request_in,
- :read_wiki, :read_project_member, :create_issue, :upload_file,
+ :read_wiki, :read_project_member, :create_issue, :upload_file,
:read_cycle_analytics, :download_code, :download_wiki_code,
:fork_project, :create_project_snippet, :read_commit_status,
:request_access, :create_pipeline, :create_pipeline_schedule,
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 050706f97be..b96c2f3afb2 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -16,7 +16,6 @@ module Types
field :description, GraphQL::STRING_TYPE, null: true
- field :default_branch, GraphQL::STRING_TYPE, null: true
field :tag_list, GraphQL::STRING_TYPE, null: true
field :ssh_url_to_repo, GraphQL::STRING_TYPE, null: true
@@ -59,25 +58,34 @@ module Types
end
field :import_status, GraphQL::STRING_TYPE, null: true
- field :ci_config_path, GraphQL::STRING_TYPE, null: true
field :only_allow_merge_if_pipeline_succeeds, GraphQL::BOOLEAN_TYPE, null: true
field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true
field :only_allow_merge_if_all_discussions_are_resolved, GraphQL::BOOLEAN_TYPE, null: true
field :printing_merge_request_link_enabled, GraphQL::BOOLEAN_TYPE, null: true
+ field :merge_requests,
+ Types::MergeRequestType.connection_type,
+ null: true,
+ resolver: Resolvers::MergeRequestsResolver,
+ authorize: :read_merge_request
+
field :merge_request,
Types::MergeRequestType,
null: true,
- resolver: Resolvers::MergeRequestResolver do
- authorize :read_merge_request
- end
+ resolver: Resolvers::MergeRequestsResolver.single,
+ authorize: :read_merge_request
field :issues,
Types::IssueType.connection_type,
null: true,
resolver: Resolvers::IssuesResolver
+ field :issue,
+ Types::IssueType,
+ null: true,
+ resolver: Resolvers::IssuesResolver.single
+
field :pipelines,
Types::Ci::PipelineType.connection_type,
null: false,
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 7c41716b82a..472fe5d6ec2 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -1,14 +1,21 @@
# frozen_string_literal: true
module Types
- class QueryType < BaseObject
+ class QueryType < ::Types::BaseObject
graphql_name 'Query'
field :project, Types::ProjectType,
null: true,
resolver: Resolvers::ProjectResolver,
- description: "Find a project" do
- authorize :read_project
+ description: "Find a project",
+ authorize: :read_project
+
+ field :metadata, Types::MetadataType,
+ null: true,
+ resolver: Resolvers::MetadataResolver,
+ description: 'Metadata about GitLab' do |*args|
+
+ authorize :read_instance_metadata
end
field :echo, GraphQL::STRING_TYPE, null: false, function: Functions::Echo.new
diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb
index 3f69af50f25..c0db9910143 100644
--- a/app/helpers/appearances_helper.rb
+++ b/app/helpers/appearances_helper.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module AppearancesHelper
+ include MarkupHelper
+
def brand_title
current_appearance&.title.presence || default_brand_title
end
@@ -11,7 +13,7 @@ module AppearancesHelper
end
def brand_image
- image_tag(current_appearance.logo) if current_appearance&.logo?
+ image_tag(current_appearance.logo_path) if current_appearance&.logo?
end
def brand_text
@@ -28,7 +30,7 @@ module AppearancesHelper
def brand_header_logo
if current_appearance&.header_logo?
- image_tag current_appearance.header_logo
+ image_tag current_appearance.header_logo_path, class: 'brand-header-logo'
else
render 'shared/logo.svg'
end
@@ -40,4 +42,36 @@ module AppearancesHelper
render 'shared/logo_type.svg'
end
end
+
+ def header_message
+ return unless current_appearance&.show_header?
+
+ class_names = []
+ class_names << 'with-performance-bar' if performance_bar_enabled?
+
+ render_message(:header_message, class_names: class_names)
+ end
+
+ def footer_message
+ return unless current_appearance&.show_footer?
+
+ render_message(:footer_message)
+ end
+
+ private
+
+ def render_message(field_sym, class_names: [], style: message_style)
+ class_names << field_sym.to_s.dasherize
+
+ content_tag :div, class: class_names, style: style do
+ markdown_field(current_appearance, field_sym)
+ end
+ end
+
+ def message_style
+ style = []
+ style << "background-color: #{current_appearance.message_background_color};"
+ style << "color: #{current_appearance.message_font_color}"
+ style.join
+ end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 82bb2d1a805..ffa5719fefb 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -214,12 +214,19 @@ module ApplicationHelper
class_names = []
class_names << 'issue-boards-page' if current_controller?(:boards)
class_names << 'with-performance-bar' if performance_bar_enabled?
-
+ class_names << system_message_class
class_names
end
- # EE feature: System header and footer, unavailable in CE
def system_message_class
+ class_names = []
+
+ return class_names unless appearance
+
+ class_names << 'with-system-header' if appearance.show_header?
+ class_names << 'with-system-footer' if appearance.show_footer?
+
+ class_names
end
# Returns active css class when condition returns true
@@ -268,6 +275,17 @@ module ApplicationHelper
_('You are on a read-only GitLab instance.')
end
+ def client_class_list
+ "gl-browser-#{browser.id} gl-platform-#{browser.platform.id}"
+ end
+
+ def client_js_flags
+ {
+ "is#{browser.id.to_s.titlecase}": true,
+ "is#{browser.platform.id.to_s.titlecase}": true
+ }
+ end
+
def autocomplete_data_sources(object, noteable_type)
return {} unless object && noteable_type
@@ -281,4 +299,10 @@ module ApplicationHelper
snippets: snippets_project_autocomplete_sources_path(object)
}
end
+
+ private
+
+ def appearance
+ ::Appearance.current
+ end
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 5a7c005fd06..e635f608237 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -20,7 +20,7 @@ module ApplicationSettingsHelper
def enabled_protocol
case Gitlab::CurrentSettings.enabled_git_access_protocol
when 'http'
- gitlab_config.protocol
+ Gitlab.config.gitlab.protocol
when 'ssh'
'ssh'
end
@@ -35,7 +35,7 @@ module ApplicationSettingsHelper
end
def http_enabled?
- all_protocols_enabled? || enabled_protocol == 'http'
+ all_protocols_enabled? || Gitlab::CurrentSettings.enabled_git_access_protocol == 'http'
end
def enabled_project_button(project, protocol)
@@ -150,6 +150,7 @@ module ApplicationSettingsHelper
:email_author_in_body,
:enabled_git_access_protocol,
:enforce_terms,
+ :first_day_of_week,
:gitaly_timeout_default,
:gitaly_timeout_medium,
:gitaly_timeout_fast,
@@ -231,7 +232,8 @@ module ApplicationSettingsHelper
:web_ide_clientside_preview_enabled,
:diff_max_patch_bytes,
:commit_email_hostname,
- :protected_ci_variables
+ :protected_ci_variables,
+ :local_markdown_version
]
end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index 654fb9d9987..2b1d6f49878 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -16,6 +16,13 @@ module AuthHelper
PROVIDERS_WITH_ICONS.include?(name.to_s)
end
+ def qa_class_for_provider(provider)
+ {
+ saml: 'qa-saml-login-button',
+ github: 'qa-github-login-button'
+ }[provider.to_sym]
+ end
+
def auth_providers
Gitlab::Auth::OAuth::Provider.providers
end
@@ -31,7 +38,7 @@ module AuthHelper
def form_based_provider_with_highest_priority
@form_based_provider_with_highest_priority ||= begin
form_based_provider_priority.each do |provider_regexp|
- highest_priority = form_based_providers.find { |provider| provider.match?(provider_regexp) }
+ highest_priority = form_based_providers.find { |provider| provider.match?(provider_regexp) }
break highest_priority unless highest_priority.nil?
end
end
diff --git a/app/helpers/auto_devops_helper.rb b/app/helpers/auto_devops_helper.rb
index 516c8a353ea..67e7e475920 100644
--- a/app/helpers/auto_devops_helper.rb
+++ b/app/helpers/auto_devops_helper.rb
@@ -9,41 +9,4 @@ module AutoDevopsHelper
!project.repository.gitlab_ci_yml &&
!project.ci_service
end
-
- def auto_devops_warning_message(project)
- if missing_auto_devops_service?(project)
- params = {
- kubernetes: link_to('Kubernetes cluster', project_clusters_path(project))
- }
-
- if missing_auto_devops_domain?(project)
- _('Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly.') % params
- else
- _('Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly.') % params
- end
- elsif missing_auto_devops_domain?(project)
- _('Auto Review Apps and Auto Deploy need a domain name to work correctly.')
- end
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def cluster_ingress_ip(project)
- project
- .cluster_ingresses
- .where("external_ip is not null")
- .limit(1)
- .pluck(:external_ip)
- .first
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- private
-
- def missing_auto_devops_domain?(project)
- !(project.auto_devops || project.build_auto_devops)&.has_domain?
- end
-
- def missing_auto_devops_service?(project)
- !project.deployment_platform&.active?
- end
end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index bd42f00944f..3e1bb9af5cc 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -31,12 +31,13 @@ module BlobHelper
edit_button_tag(blob,
common_classes,
_('Edit'),
- edit_blob_path(project, ref, path, options),
+ Feature.enabled?(:web_ide_default) ? ide_edit_path(project, ref, path, options) : edit_blob_path(project, ref, path, options),
project,
ref)
end
def ide_edit_button(project = @project, ref = @ref, path = @path, options = {})
+ return if Feature.enabled?(:web_ide_default)
return unless blob = readable_blob(options, path, project, ref)
edit_button_tag(blob,
@@ -140,36 +141,6 @@ module BlobHelper
Gitlab::Sanitizers::SVG.clean(data)
end
- # Remove once https://gitlab.com/gitlab-org/gitlab-ce/issues/36103 is closed
- # and :workhorse_set_content_type flag is removed
- # If we blindly set the 'real' content type when serving a Git blob we
- # are enabling XSS attacks. An attacker could upload e.g. a Javascript
- # file to a Git repository, trick the browser of a victim into
- # downloading the blob, and then the 'application/javascript' content
- # type would tell the browser to execute the attacker's Javascript. By
- # overriding the content type and setting it to 'text/plain' (in the
- # example of Javascript) we tell the browser of the victim not to
- # execute untrusted data.
- def safe_content_type(blob)
- if blob.extension == 'svg'
- blob.mime_type
- elsif blob.text?
- 'text/plain; charset=utf-8'
- elsif blob.image?
- blob.content_type
- else
- 'application/octet-stream'
- end
- end
-
- def content_disposition(blob, inline)
- # Remove the following line when https://gitlab.com/gitlab-org/gitlab-ce/issues/36103
- # is closed and :workhorse_set_content_type flag is removed
- return 'attachment' if blob.extension == 'svg'
-
- inline ? 'inline' : 'attachment'
- end
-
def ref_project
@ref_project ||= @target_project || @project
end
@@ -207,7 +178,8 @@ module BlobHelper
'relative-url-root' => Rails.application.config.relative_url_root,
'assets-prefix' => Gitlab::Application.config.assets.prefix,
'blob-filename' => @blob && @blob.path,
- 'project-id' => project.id
+ 'project-id' => project.id,
+ 'is-markdown' => @blob && @blob.path && Gitlab::MarkupHelper.gitlab_markdown?(@blob.path)
}
end
@@ -223,7 +195,7 @@ module BlobHelper
def open_raw_blob_button(blob)
return if blob.empty?
- return if blob.raw_binary? || blob.stored_externally?
+ return if blob.binary? || blob.stored_externally?
title = 'Open raw'
link_to icon('file-code-o'), blob_raw_path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: title, data: { container: 'body' }
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index 923a06a0512..355b91a8661 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -100,17 +100,6 @@ module CiStatusHelper
"pipeline-status/#{pipeline_status.sha}-#{pipeline_status.status}"
end
- def render_project_pipeline_status(pipeline_status, tooltip_placement: 'left')
- project = pipeline_status.project
- path = pipelines_project_commit_path(project, pipeline_status.sha, ref: pipeline_status.ref)
-
- render_status_with_link(
- 'commit',
- pipeline_status.status,
- path,
- tooltip_placement: tooltip_placement)
- end
-
def render_commit_status(commit, ref: nil, tooltip_placement: 'left')
project = commit.project
path = pipelines_project_commit_path(project, commit, ref: ref)
@@ -123,12 +112,6 @@ module CiStatusHelper
icon_size: 24)
end
- def render_pipeline_status(pipeline, tooltip_placement: 'left')
- project = pipeline.project
- path = project_pipeline_path(project, pipeline)
- render_status_with_link('pipeline', pipeline.status, path, tooltip_placement: tooltip_placement)
- end
-
def render_status_with_link(type, status, path = nil, tooltip_placement: 'left', cssclass: '', container: 'body', icon_size: 16)
klass = "ci-status-link ci-status-icon-#{status.dasherize} #{cssclass}"
title = "#{type.titleize}: #{ci_label_for_status(status)}"
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index d52cfd6e37a..d58f634425b 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -154,7 +154,7 @@ module CommitsHelper
if user.nil?
mail_to(source_email, text, link_options)
else
- link_to(text, user_path(user), link_options)
+ link_to(text, user_path(user), { class: "commit-#{options[:source]}-link js-user-link", data: { user_id: user.id } })
end
end
diff --git a/app/helpers/count_helper.rb b/app/helpers/count_helper.rb
index 13839474e1f..62bb2e4da23 100644
--- a/app/helpers/count_helper.rb
+++ b/app/helpers/count_helper.rb
@@ -13,7 +13,7 @@ module CountHelper
# memberships, and deducting 1 for each root of the fork network.
# This might be inacurate as the root of the fork network might have been deleted.
#
- # This makes querying this information a lot more effecient and it should be
+ # This makes querying this information a lot more efficient and it should be
# accurate enough for the instance wide statistics
def approximate_fork_count_with_delimiters(count_data)
fork_network_count = count_data[ForkNetwork]
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index b6844d36052..32431959851 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -138,30 +138,6 @@ module DiffHelper
!diff_file.deleted_file? && @merge_request && @merge_request.source_project
end
- def diff_render_error_reason(viewer)
- case viewer.render_error
- when :too_large
- "it is too large"
- when :server_side_but_stored_externally
- case viewer.diff_file.external_storage
- when :lfs
- 'it is stored in LFS'
- else
- 'it is stored externally'
- end
- end
- end
-
- def diff_render_error_options(viewer)
- diff_file = viewer.diff_file
- options = []
-
- blob_url = project_blob_path(@project, tree_join(diff_file.content_sha, diff_file.file_path))
- options << link_to('view the blob', blob_url)
-
- options
- end
-
def diff_file_changed_icon(diff_file)
if diff_file.deleted_file?
"file-deletion"
diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb
index e4c46ceeaa2..96471d15aac 100644
--- a/app/helpers/emails_helper.rb
+++ b/app/helpers/emails_helper.rb
@@ -36,6 +36,14 @@ module EmailsHelper
nil
end
+ def sanitize_name(name)
+ if name =~ URI::DEFAULT_PARSER.regexp[:URI_REF]
+ name.tr('.', '_')
+ else
+ name
+ end
+ end
+
def password_reset_token_valid_time
valid_hours = Devise.reset_password_within / 60 / 60
if valid_hours >= 24
@@ -58,7 +66,7 @@ module EmailsHelper
def header_logo
if current_appearance&.header_logo?
image_tag(
- current_appearance.header_logo,
+ current_appearance.header_logo_path,
style: 'height: 50px'
)
else
@@ -123,4 +131,42 @@ module EmailsHelper
project.id.to_s + "." + project_path_as_domain + "." + Gitlab.config.gitlab.host
end
+
+ def html_header_message
+ return unless show_header?
+
+ render_message(:header_message, style: '')
+ end
+
+ def html_footer_message
+ return unless show_footer?
+
+ render_message(:footer_message, style: '')
+ end
+
+ def text_header_message
+ return unless show_header?
+
+ strip_tags(render_message(:header_message, style: ''))
+ end
+
+ def text_footer_message
+ return unless show_footer?
+
+ strip_tags(render_message(:footer_message, style: ''))
+ end
+
+ private
+
+ def show_footer?
+ email_header_and_footer_enabled? && current_appearance&.show_footer?
+ end
+
+ def show_header?
+ email_header_and_footer_enabled? && current_appearance&.show_header?
+ end
+
+ def email_header_and_footer_enabled?
+ current_appearance&.email_header_and_footer_enabled?
+ end
end
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 7b22bc8f98f..365b94f5a3e 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -7,6 +7,14 @@ module EnvironmentsHelper
}
end
+ def environments_folder_list_view_data
+ {
+ "endpoint" => folder_project_environments_path(@project, @folder, format: :json),
+ "folder-name" => @folder,
+ "can-read-environment" => can?(current_user, :read_environment, @project).to_s
+ }
+ end
+
def metrics_data(project, environment)
{
"settings-path" => edit_project_service_path(project, 'prometheus'),
diff --git a/app/helpers/external_wiki_helper.rb b/app/helpers/external_wiki_helper.rb
deleted file mode 100644
index e36d63b2946..00000000000
--- a/app/helpers/external_wiki_helper.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module ExternalWikiHelper
- def get_project_wiki_path(project)
- external_wiki_service = project.external_wiki
- if external_wiki_service
- external_wiki_service.properties['external_wiki_url']
- else
- project_wiki_path(project, :home)
- end
- end
-end
diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb
index 49171df1433..3d494c3de6a 100644
--- a/app/helpers/import_helper.rb
+++ b/app/helpers/import_helper.rb
@@ -8,7 +8,9 @@ module ImportHelper
end
def sanitize_project_name(name)
- name.gsub(/[^\w\-]/, '-')
+ # For personal projects in Bitbucket in the form ~username, we can
+ # just drop that leading tilde.
+ name.gsub(/\A~+/, '').gsub(/[^\w\-]/, '-')
end
def import_project_target(owner, name)
@@ -16,10 +18,8 @@ module ImportHelper
"#{namespace}/#{name}"
end
- def provider_project_link(provider, full_path)
- url = __send__("#{provider}_project_url", full_path) # rubocop:disable GitlabSecurity/PublicSend
-
- link_to full_path, url, target: '_blank', rel: 'noopener noreferrer'
+ def provider_project_link_url(provider_url, full_path)
+ Gitlab::Utils.append_path(provider_url, full_path)
end
def import_will_timeout_message(_ci_cd_only)
@@ -44,10 +44,6 @@ module ImportHelper
_('Please wait while we import the repository for you. Refresh at will.')
end
- def import_github_title
- _('Import repositories from GitHub')
- end
-
def import_github_authorize_message
_('To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:')
end
@@ -71,30 +67,4 @@ module ImportHelper
_('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.').html_safe % { github_integration_link: github_integration_link }
end
end
-
- def import_githubish_choose_repository_message
- _('Choose which repositories you want to import.')
- end
-
- def import_all_githubish_repositories_button_label
- _('Import all repositories')
- end
-
- private
-
- def github_project_url(full_path)
- Gitlab::Utils.append_path(github_root_url, full_path)
- end
-
- def github_root_url
- strong_memoize(:github_url) do
- provider = Gitlab::Auth::OAuth::Provider.config_for('github')
-
- provider&.dig('url').presence || 'https://github.com'
- end
- end
-
- def gitea_project_url(full_path)
- Gitlab::Utils.append_path(@gitea_host_url, full_path)
- end
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 5f7147508c7..0622cdfc196 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -191,7 +191,7 @@ module IssuablesHelper
output << content_tag(:strong) do
author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "d-none d-sm-inline")
- author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "d-block d-sm-none")
+ author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "d-inline d-sm-none")
if status = user_status(issuable.author)
author_output << "#{status}".html_safe
@@ -200,7 +200,7 @@ module IssuablesHelper
author_output
end
- output << content_tag(:span, (issuable_first_contribution_icon if issuable.first_contribution?), class: 'has-tooltip', title: _('1st contribution!'))
+ output << content_tag(:span, (issuable_first_contribution_icon if issuable.first_contribution?), class: 'has-tooltip prepend-left-4', title: _('1st contribution!'))
output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-sm-none d-md-inline-block prepend-left-8")
output << content_tag(:span, (issuable.task_status_short if issuable.tasks?), id: "task_status_short", class: "d-md-none")
@@ -209,7 +209,7 @@ module IssuablesHelper
end
def issuable_labels_tooltip(labels, limit: 5)
- first, last = labels.partition.with_index { |_, i| i < limit }
+ first, last = labels.partition.with_index { |_, i| i < limit }
if labels && labels.any?
label_names = first.collect { |label| label.fetch(:title) }
@@ -268,7 +268,7 @@ module IssuablesHelper
issuableRef: issuable.to_reference,
markdownPreviewPath: preview_markdown_path(parent),
markdownDocsPath: help_page_path('user/markdown'),
- markdownVersion: issuable.cached_markdown_version,
+ lockVersion: issuable.lock_version,
issuableTemplates: issuable_templates(issuable),
initialTitleHtml: markdown_field(issuable, :title),
initialTitleText: issuable.title,
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 39f661b5f0c..bd53add80ca 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -227,6 +227,10 @@ module LabelsHelper
"#{action} at #{level} level"
end
+ def labels_sorted_by_title(labels)
+ labels.sort_by(&:title)
+ end
+
# Required for Banzai::Filter::LabelReferenceFilter
module_function :render_colored_label, :text_color_for_bg, :escape_once
end
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index 0d638b850b4..d83c69603a9 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -74,7 +74,7 @@ module MarkupHelper
# the tag contents are truncated without removing the closing tag.
def first_line_in_markdown(object, attribute, max_chars = nil, options = {})
md = markdown_field(object, attribute, options)
- return nil unless md.present?
+ return unless md.present?
tags = %w(a gl-emoji b pre code p span)
tags << 'img' if options[:allow_images]
@@ -116,7 +116,6 @@ module MarkupHelper
def markup(file_name, text, context = {})
context[:project] ||= @project
- context[:markdown_engine] ||= :redcarpet unless commonmark_for_repositories_enabled?
html = context.delete(:rendered) || markup_unsafe(file_name, text, context)
prepare_for_rendering(html, context)
end
@@ -132,7 +131,6 @@ module MarkupHelper
page_slug: wiki_page.slug,
issuable_state_filter_enabled: true
)
- context[:markdown_engine] ||= :redcarpet unless commonmark_for_repositories_enabled?
html =
case wiki_page.format
@@ -187,10 +185,6 @@ module MarkupHelper
end
end
- def commonmark_for_repositories_enabled?
- Feature.enabled?(:commonmark_for_repositories, default_enabled: true)
- end
-
private
# Return +text+, truncated to +max_chars+ characters, excluding any HTML
diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb
index 5a21403bc5e..11d5591d509 100644
--- a/app/helpers/members_helper.rb
+++ b/app/helpers/members_helper.rb
@@ -18,12 +18,13 @@ module MembersHelper
"remove #{member.user.name} from"
end
- "#{text} #{action} the #{member.source.human_name} #{member.real_source_type.humanize(capitalize: false)}?"
+ "#{text} #{action} the #{member.source.human_name} #{source_text(member)}?"
end
def remove_member_title(member)
action = member.request? ? 'Deny access request' : 'Remove user'
- "#{action} from #{member.real_source_type.humanize(capitalize: false)}"
+
+ "#{action} from #{source_text(member)}"
end
def leave_confirmation_message(member_source)
@@ -32,7 +33,17 @@ module MembersHelper
end
def filter_group_project_member_path(options = {})
- options = params.slice(:search, :sort).merge(options)
+ options = params.slice(:search, :sort).merge(options).permit!
"#{request.path}?#{options.to_param}"
end
+
+ private
+
+ def source_text(member)
+ type = member.real_source_type.humanize(capitalize: false)
+
+ return type if member.request? || member.invite? || type != 'group'
+
+ 'group and any subresources'
+ end
end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 23d7aa427bb..991ca42c445 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -29,7 +29,7 @@ module MergeRequestsHelper
def ci_build_details_path(merge_request)
build_url = merge_request.source_project.ci_service.build_page(merge_request.diff_head_sha, merge_request.source_branch)
- return nil unless build_url
+ return unless build_url
parsed_url = URI.parse(build_url)
@@ -92,7 +92,7 @@ module MergeRequestsHelper
end
def version_index(merge_request_diff)
- return nil if @merge_request_diffs.empty?
+ return if @merge_request_diffs.empty?
@merge_request_diffs.size - @merge_request_diffs.index(merge_request_diff)
end
@@ -149,7 +149,7 @@ module MergeRequestsHelper
def merge_request_source_project_for_project(project = @project)
unless can?(current_user, :create_merge_request_in, project)
- return nil
+ return
end
if can?(current_user, :create_merge_request_from, project)
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 327b69e5110..50aec83b867 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -231,12 +231,15 @@ module MilestonesHelper
end
end
- def group_or_dashboard_milestone_path(milestone)
- if milestone.group_milestone?
- group_milestone_path(milestone.group, milestone.iid, milestone: { title: milestone.title })
- else
- dashboard_milestone_path(milestone.safe_title, title: milestone.title)
- end
+ def group_or_project_milestone_path(milestone)
+ params =
+ if milestone.group_milestone?
+ { milestone: { title: milestone.title } }
+ else
+ { title: milestone.title }
+ end
+
+ milestone_path(milestone.milestone, params)
end
def can_admin_project_milestones?
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index 6c65e573307..ea3bcfc791a 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -5,11 +5,8 @@ module NamespacesHelper
params.dig(:project, :namespace_id) || params[:namespace_id]
end
- # rubocop: disable CodeReuse/ActiveRecord
def namespaces_options(selected = :current_user, display_path: false, groups: nil, extra_group: nil, groups_only: false)
- groups ||= current_user.manageable_groups
- .eager_load(:route)
- .order('routes.path')
+ groups ||= current_user.manageable_groups_with_routes
users = [current_user.namespace]
selected_id = selected
@@ -43,7 +40,6 @@ module NamespacesHelper
grouped_options_for_select(options, selected_id)
end
- # rubocop: enable CodeReuse/ActiveRecord
def namespace_icon(namespace, size = 40)
if namespace.is_a?(Group)
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 033686823a2..a50137bea3d 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -85,7 +85,7 @@ module NotesHelper
diffs_project_merge_request_path(discussion.project, discussion.noteable, path_params)
elsif discussion.for_commit?
- anchor = discussion.line_code if discussion.diff_discussion?
+ anchor = discussion.diff_discussion? ? discussion.line_code : "note_#{discussion.first_note.id}"
project_commit_path(discussion.project, discussion.noteable, anchor: anchor)
end
@@ -122,7 +122,7 @@ module NotesHelper
end
def new_form_url
- return nil unless @snippet.is_a?(PersonalSnippet)
+ return unless @snippet.is_a?(PersonalSnippet)
snippet_notes_path(@snippet)
end
@@ -171,7 +171,6 @@ module NotesHelper
registerPath: new_session_path(:user, redirect_to_referer: 'yes', anchor: 'register-pane'),
newSessionPath: new_session_path(:user, redirect_to_referer: 'yes'),
markdownDocsPath: help_page_path('user/markdown'),
- markdownVersion: issuable.cached_markdown_version,
quickActionsDocsPath: help_page_path('user/project/quick_actions'),
closePath: close_issuable_path(issuable),
reopenPath: reopen_issuable_path(issuable),
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index f4f46b0fe96..766508b6609 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -43,6 +43,18 @@ module PreferencesHelper
]
end
+ def first_day_of_week_choices
+ [
+ [_('Sunday'), 0],
+ [_('Monday'), 1],
+ [_('Saturday'), 6]
+ ]
+ end
+
+ def first_day_of_week_choices_with_default
+ first_day_of_week_choices.unshift([_('System default (%{default})') % { default: default_first_day_of_week }, nil])
+ end
+
def user_application_theme
@user_application_theme ||= Gitlab::Themes.for_user(current_user).css_class
end
@@ -51,6 +63,10 @@ module PreferencesHelper
Gitlab::ColorSchemes.for_user(current_user).css_class
end
+ def language_choices
+ Gitlab::I18n::AVAILABLE_LANGUAGES.map { |value, label| [label, value] }
+ end
+
private
# Ensure that anyone adding new options updates `DASHBOARD_CHOICES` too
@@ -66,4 +82,8 @@ module PreferencesHelper
def excluded_dashboard_choices
['operations']
end
+
+ def default_first_day_of_week
+ first_day_of_week_choices.rassoc(Gitlab::CurrentSettings.first_day_of_week).first
+ end
end
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index df318de740a..5a42e581867 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -25,4 +25,8 @@ module ProfilesHelper
end
end
end
+
+ def user_profile?
+ params[:controller] == 'users'
+ end
end
diff --git a/app/helpers/projects/error_tracking_helper.rb b/app/helpers/projects/error_tracking_helper.rb
new file mode 100644
index 00000000000..6daf2e21ca2
--- /dev/null
+++ b/app/helpers/projects/error_tracking_helper.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Projects::ErrorTrackingHelper
+ def error_tracking_data(project)
+ error_tracking_enabled = !!project.error_tracking_setting&.enabled?
+
+ {
+ 'index-path' => project_error_tracking_index_path(project,
+ format: :json),
+ 'enable-error-tracking-link' => project_settings_operations_path(project),
+ 'error-tracking-enabled' => error_tracking_enabled.to_s,
+ 'illustration-path' => image_path('illustrations/cluster_popover.svg')
+ }
+ end
+end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 0cfc2db3285..2ac8ddc5244 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -204,12 +204,10 @@ module ProjectsHelper
current_user.require_extra_setup_for_git_auth?
end
- def show_auto_devops_implicitly_enabled_banner?(project)
- cookie_key = "hide_auto_devops_implicitly_enabled_banner_#{project.id}"
+ def show_auto_devops_implicitly_enabled_banner?(project, user)
+ return false unless user_can_see_auto_devops_implicitly_enabled_banner?(project, user)
- project.has_auto_devops_implicitly_enabled? &&
- cookies[cookie_key.to_sym].blank? &&
- (project.owner == current_user || project.team.maintainer?(current_user))
+ cookies["hide_auto_devops_implicitly_enabled_banner_#{project.id}".to_sym].blank?
end
def link_to_set_password
@@ -267,10 +265,6 @@ module ProjectsHelper
link_to 'BFG', 'https://rtyley.github.io/bfg-repo-cleaner/', target: '_blank', rel: 'noopener noreferrer'
end
- def legacy_render_context(params)
- params[:legacy_render] ? { markdown_engine: :redcarpet } : {}
- end
-
def explore_projects_tab?
current_page?(explore_projects_path) ||
current_page?(trending_explore_projects_path) ||
@@ -285,6 +279,25 @@ module ProjectsHelper
!disabled && !compact_mode && Feature.enabled?(:project_list_show_issue_count, default_enabled: true)
end
+ # overridden in EE
+ def settings_operations_available?
+ can?(current_user, :read_environment, @project)
+ end
+
+ def error_tracking_setting_project_json
+ setting = @project.error_tracking_setting
+
+ return if setting.blank? || setting.project_slug.blank? ||
+ setting.organization_slug.blank?
+
+ {
+ name: setting.project_name,
+ organization_name: setting.organization_name,
+ organization_slug: setting.organization_slug,
+ slug: setting.project_slug
+ }.to_json
+ end
+
private
def get_project_nav_tabs(project, current_user)
@@ -302,7 +315,8 @@ module ProjectsHelper
nav_tabs << :container_registry
end
- if project.builds_enabled? && can?(current_user, :read_pipeline, project)
+ # Pipelines feature is tied to presence of builds
+ if can?(current_user, :read_build, project)
nav_tabs << :pipelines
end
@@ -310,19 +324,24 @@ module ProjectsHelper
nav_tabs << :operations
end
- if project.external_issue_tracker
- nav_tabs << :external_issue_tracker
- end
-
tab_ability_map.each do |tab, ability|
if can?(current_user, ability, project)
nav_tabs << tab
end
end
+ nav_tabs << external_nav_tabs(project)
+
nav_tabs.flatten
end
+ def external_nav_tabs(project)
+ [].tap do |tabs|
+ tabs << :external_issue_tracker if project.external_issue_tracker
+ tabs << :external_wiki if project.external_wiki
+ end
+ end
+
def tab_ability_map
{
environments: :read_environment,
@@ -332,6 +351,7 @@ module ProjectsHelper
builds: :read_build,
clusters: :read_cluster,
serverless: :read_cluster,
+ error_tracking: :read_sentry_issue,
labels: :read_label,
issues: :read_issue,
project_members: :read_project_member,
@@ -485,7 +505,7 @@ module ProjectsHelper
lfsHelpPath: help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs'),
pagesAvailable: Gitlab.config.pages.enabled,
pagesAccessControlEnabled: Gitlab.config.pages.access_control,
- pagesHelpPath: help_page_path('user/project/pages/index.md')
+ pagesHelpPath: help_page_path('user/project/pages/introduction', anchor: 'gitlab-pages-access-control-core-only')
}
end
@@ -546,6 +566,7 @@ module ProjectsHelper
services#edit
repository#show
ci_cd#show
+ operations#show
badges#index
pages#show
]
@@ -575,8 +596,16 @@ module ProjectsHelper
environments
clusters
functions
+ error_tracking
user
gcp
]
end
+
+ def user_can_see_auto_devops_implicitly_enabled_banner?(project, user)
+ Ability.allowed?(user, :admin_project, project) &&
+ project.has_auto_devops_implicitly_enabled? &&
+ project.builds_enabled? &&
+ !project.repository.gitlab_ci_yml
+ end
end
diff --git a/app/helpers/runners_helper.rb b/app/helpers/runners_helper.rb
index cb21f922401..0d880c38a7b 100644
--- a/app/helpers/runners_helper.rb
+++ b/app/helpers/runners_helper.rb
@@ -28,4 +28,14 @@ module RunnersHelper
display_name + id
end
end
+
+ # Due to inability of performing sorting of runners by cached "contacted_at" values we have to show uncached values if sorting by "contacted_asc" is requested.
+ # Please refer to the following issue for more details: https://gitlab.com/gitlab-org/gitlab-ce/issues/55920
+ def runner_contacted_at(runner)
+ if params[:sort] == 'contacted_asc'
+ runner.uncached_contacted_at
+ else
+ runner.contacted_at
+ end
+ end
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 80cc568820a..0ee76a51f7d 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -24,10 +24,10 @@ module SearchHelper
end
def search_entries_info(collection, scope, term)
- return unless collection.count > 0
+ return if collection.to_a.empty?
from = collection.offset_value + 1
- to = collection.offset_value + collection.count
+ to = collection.offset_value + collection.to_a.size
count = collection.total_count
"Showing #{from} - #{to} of #{count} #{scope.humanize(capitalize: false)} for \"#{term}\""
diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb
index c7d31f3469d..ecb2b2d707b 100644
--- a/app/helpers/snippets_helper.rb
+++ b/app/helpers/snippets_helper.rb
@@ -110,7 +110,7 @@ module SnippetsHelper
def embedded_snippet_raw_button
blob = @snippet.blob
- return if blob.empty? || blob.raw_binary? || blob.stored_externally?
+ return if blob.empty? || blob.binary? || blob.stored_externally?
snippet_raw_url = if @snippet.is_a?(PersonalSnippet)
raw_snippet_url(@snippet)
@@ -130,12 +130,4 @@ module SnippetsHelper
link_to external_snippet_icon('download'), download_url, class: 'btn', target: '_blank', title: 'Download', rel: 'noopener noreferrer'
end
-
- def public_snippet?
- if @snippet.project_id?
- can?(nil, :read_project_snippet, @snippet)
- else
- can?(nil, :read_personal_snippet, @snippet)
- end
- end
end
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 6ac1f42c321..07ec129dea3 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -128,7 +128,9 @@ module SortingHelper
sort_value_recently_created => sort_title_recently_created,
sort_value_oldest_created => sort_title_oldest_created,
sort_value_recently_updated => sort_title_recently_updated,
- sort_value_oldest_updated => sort_title_oldest_updated
+ sort_value_oldest_updated => sort_title_oldest_updated,
+ sort_value_recently_last_activity => sort_title_recently_last_activity,
+ sort_value_oldest_last_activity => sort_title_oldest_last_activity
}
end
@@ -234,7 +236,7 @@ module SortingHelper
end
def sort_title_milestone
- s_('SortOptions|Milestone')
+ s_('SortOptions|Milestone due date')
end
def sort_title_milestone_later
@@ -317,6 +319,14 @@ module SortingHelper
s_('SortOptions|Most stars')
end
+ def sort_title_oldest_last_activity
+ s_('SortOptions|Oldest last activity')
+ end
+
+ def sort_title_recently_last_activity
+ s_('SortOptions|Recent last activity')
+ end
+
# Values.
def sort_value_access_level_asc
'access_level_asc'
@@ -445,4 +455,12 @@ module SortingHelper
def sort_value_most_stars
'stars_desc'
end
+
+ def sort_value_oldest_last_activity
+ 'last_activity_on_asc'
+ end
+
+ def sort_value_recently_last_activity
+ 'last_activity_on_desc'
+ end
end
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index 4aba48061ba..5d658d35107 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -13,6 +13,13 @@ module UserCalloutsHelper
!user_dismissed?(GCP_SIGNUP_OFFER)
end
+ def render_flash_user_callout(flash_type, message, feature_name)
+ render 'shared/flash_user_callout', flash_type: flash_type, message: message, feature_name: feature_name
+ end
+
+ def render_dashboard_gold_trial(user)
+ end
+
private
def user_dismissed?(feature_name)
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 73c1402eae5..73ca17c6605 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -74,6 +74,15 @@ module UsersHelper
Gitlab.config.gitlab.impersonation_enabled
end
+ def user_badges_in_admin_section(user)
+ [].tap do |badges|
+ badges << { text: s_('AdminUsers|Blocked'), variant: 'danger' } if user.blocked?
+ badges << { text: s_('AdminUsers|Admin'), variant: 'success' } if user.admin?
+ badges << { text: s_('AdminUsers|External'), variant: 'secondary' } if user.external?
+ badges << { text: s_("AdminUsers|It's you!"), variant: nil } if current_user == user
+ end
+ end
+
private
def get_profile_tabs
diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb
index e9fc39e451b..bb5b1555dc4 100644
--- a/app/helpers/workhorse_helper.rb
+++ b/app/helpers/workhorse_helper.rb
@@ -7,8 +7,7 @@ module WorkhorseHelper
def send_git_blob(repository, blob, inline: true)
headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob))
- headers['Content-Disposition'] = content_disposition(blob, inline)
- headers['Content-Type'] = safe_content_type(blob)
+ headers['Content-Disposition'] = inline ? 'inline' : 'attachment'
# If enabled, this will override the values set above
workhorse_set_content_type!
@@ -47,6 +46,6 @@ module WorkhorseHelper
end
def workhorse_set_content_type!
- headers[Gitlab::Workhorse::DETECT_HEADER] = "true" if Feature.enabled?(:workhorse_set_content_type)
+ headers[Gitlab::Workhorse::DETECT_HEADER] = "true"
end
end
diff --git a/app/mailers/abuse_report_mailer.rb b/app/mailers/abuse_report_mailer.rb
index e032f568913..e0aa66e6de3 100644
--- a/app/mailers/abuse_report_mailer.rb
+++ b/app/mailers/abuse_report_mailer.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
class AbuseReportMailer < BaseMailer
+ layout 'empty_mailer'
+
+ helper EmailsHelper
+
def notify(abuse_report_id)
return unless deliverable?
diff --git a/app/mailers/email_rejection_mailer.rb b/app/mailers/email_rejection_mailer.rb
index 45fc5a6c383..d743533b1bc 100644
--- a/app/mailers/email_rejection_mailer.rb
+++ b/app/mailers/email_rejection_mailer.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
class EmailRejectionMailer < BaseMailer
+ layout 'empty_mailer'
+
+ helper EmailsHelper
+
def rejection(reason, original_raw, can_retry = false)
@reason = reason
@original_message = Mail::Message.new(original_raw)
diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb
index 370e6d2f90b..d2e334fb856 100644
--- a/app/mailers/emails/issues.rb
+++ b/app/mailers/emails/issues.rb
@@ -74,9 +74,21 @@ module Emails
@new_issue = new_issue
@new_project = new_issue.project
+ @can_access_project = recipient.can?(:read_project, @new_project)
mail_answer_thread(issue, issue_thread_options(updated_by_user.id, recipient.id, reason))
end
+ def import_issues_csv_email(user_id, project_id, results)
+ @user = User.find(user_id)
+ @project = Project.find(project_id)
+ @results = results
+
+ mail(to: @user.notification_email, subject: subject('Imported issues')) do |format|
+ format.html { render layout: 'mailer' }
+ format.text { render layout: 'mailer' }
+ end
+ end
+
private
def setup_issue_mail(issue_id, recipient_id)
diff --git a/app/mailers/emails/pipelines.rb b/app/mailers/emails/pipelines.rb
index 31e183640ad..fb57c0da34d 100644
--- a/app/mailers/emails/pipelines.rb
+++ b/app/mailers/emails/pipelines.rb
@@ -15,7 +15,7 @@ module Emails
def pipeline_mail(pipeline, recipients, status)
@project = pipeline.project
@pipeline = pipeline
- @merge_request = pipeline.merge_requests.first
+ @merge_request = pipeline.merge_requests_as_head_pipeline.first
add_headers
# We use bcc here because we don't want to generate this emails for a
diff --git a/app/mailers/previews/notify_preview.rb b/app/mailers/previews/notify_preview.rb
index 2ac4610967d..80e0a17c312 100644
--- a/app/mailers/previews/notify_preview.rb
+++ b/app/mailers/previews/notify_preview.rb
@@ -76,6 +76,10 @@ class NotifyPreview < ActionMailer::Preview
Notify.changed_milestone_issue_email(user.id, issue.id, milestone, user.id)
end
+ def import_issues_csv_email
+ Notify.import_issues_csv_email(user, project, { success: 3, errors: [5, 6, 7], valid_file: true })
+ end
+
def closed_merge_request_email
Notify.closed_merge_request_email(user.id, issue.id, user.id).message
end
diff --git a/app/mailers/repository_check_mailer.rb b/app/mailers/repository_check_mailer.rb
index 145169be8a6..a24d3476d0e 100644
--- a/app/mailers/repository_check_mailer.rb
+++ b/app/mailers/repository_check_mailer.rb
@@ -2,6 +2,10 @@
class RepositoryCheckMailer < BaseMailer
# rubocop: disable CodeReuse/ActiveRecord
+ layout 'empty_mailer'
+
+ helper EmailsHelper
+
def notify(failed_count)
@message =
if failed_count == 1
diff --git a/app/models/active_session.rb b/app/models/active_session.rb
index 0d9c6a4a1f0..1e01f1d17e6 100644
--- a/app/models/active_session.rb
+++ b/app/models/active_session.rb
@@ -5,7 +5,8 @@ class ActiveSession
attr_accessor :created_at, :updated_at,
:session_id, :ip_address,
- :browser, :os, :device_name, :device_type
+ :browser, :os, :device_name, :device_type,
+ :is_impersonated
def current?(session)
return false if session_id.nil? || session.id.nil?
@@ -31,7 +32,8 @@ class ActiveSession
device_type: client.device_type,
created_at: user.current_sign_in_at || timestamp,
updated_at: timestamp,
- session_id: session_id
+ session_id: session_id,
+ is_impersonated: request.session[:impersonator_id].present?
)
redis.pipelined do
diff --git a/app/models/appearance.rb b/app/models/appearance.rb
index bffba3e13fa..bdee9b2b73c 100644
--- a/app/models/appearance.rb
+++ b/app/models/appearance.rb
@@ -8,12 +8,20 @@ class Appearance < ActiveRecord::Base
cache_markdown_field :description
cache_markdown_field :new_project_guidelines
+ cache_markdown_field :header_message, pipeline: :broadcast_message
+ cache_markdown_field :footer_message, pipeline: :broadcast_message
validates :logo, file_size: { maximum: 1.megabyte }
validates :header_logo, file_size: { maximum: 1.megabyte }
+ validates :message_background_color, allow_blank: true, color: true
+ validates :message_font_color, allow_blank: true, color: true
validate :single_appearance_row, on: :create
+ default_value_for :message_background_color, '#E75E40'
+ default_value_for :message_font_color, '#FFFFFF'
+ default_value_for :email_header_and_footer_enabled, false
+
mount_uploader :logo, AttachmentUploader
mount_uploader :header_logo, AttachmentUploader
mount_uploader :favicon, FaviconUploader
@@ -28,4 +36,44 @@ class Appearance < ActiveRecord::Base
errors.add(:single_appearance_row, 'Only 1 appearances row can exist')
end
end
+
+ def logo_path
+ logo_system_path(logo, 'logo')
+ end
+
+ def header_logo_path
+ logo_system_path(header_logo, 'header_logo')
+ end
+
+ def favicon_path
+ logo_system_path(favicon, 'favicon')
+ end
+
+ def show_header?
+ header_message.present?
+ end
+
+ def show_footer?
+ footer_message.present?
+ end
+
+ private
+
+ def logo_system_path(logo, mount_type)
+ # Legacy attachments may not have have an associated Upload record,
+ # so fallback to the AttachmentUploader#url if this is the
+ # case. AttachmentUploader#path doesn't work because for a local
+ # file, this is an absolute path to the file.
+ return logo&.url unless logo&.upload
+
+ # If we're using a CDN, we need to use the full URL
+ asset_host = ActionController::Base.asset_host
+ local_path = Gitlab::Routing.url_helpers.appearance_upload_path(
+ filename: logo.filename,
+ id: logo.upload.model_id,
+ model: 'appearance',
+ mounted_as: mount_type)
+
+ Gitlab::Utils.append_path(asset_host, local_path)
+ end
end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index 71fbba5b328..a3d662d8250 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -2,4 +2,22 @@
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
+
+ def self.id_in(ids)
+ where(id: ids)
+ end
+
+ def self.safe_find_or_create_by!(*args)
+ safe_find_or_create_by(*args).tap do |record|
+ record.validate! unless record.persisted?
+ end
+ end
+
+ def self.safe_find_or_create_by(*args)
+ transaction(requires_new: true) do
+ find_or_create_by(*args)
+ end
+ rescue ActiveRecord::RecordNotUnique
+ retry
+ end
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 73be94eade6..c5035797621 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -7,7 +7,7 @@ class ApplicationSetting < ActiveRecord::Base
include IgnorableColumn
include ChronicDurationAttribute
- add_authentication_token_field :runners_registration_token, encrypted: true, fallback: true
+ add_authentication_token_field :runners_registration_token, encrypted: -> { Feature.enabled?(:application_settings_tokens_optional_encryption) ? :optional : :required }
add_authentication_token_field :health_check_access_token
DOMAIN_LIST_SEPARATOR = %r{\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace
@@ -193,6 +193,10 @@ class ApplicationSetting < ActiveRecord::Base
allow_nil: true,
numericality: { only_integer: true, greater_than_or_equal_to: 1.day.seconds }
+ validates :local_markdown_version,
+ allow_nil: true,
+ numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than: 65536 }
+
SUPPORTED_KEY_TYPES.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
@@ -246,6 +250,7 @@ class ApplicationSetting < ActiveRecord::Base
dsa_key_restriction: 0,
ecdsa_key_restriction: 0,
ed25519_key_restriction: 0,
+ first_day_of_week: 0,
gitaly_timeout_default: 55,
gitaly_timeout_fast: 10,
gitaly_timeout_medium: 30,
@@ -303,7 +308,8 @@ class ApplicationSetting < ActiveRecord::Base
usage_stats_set_by_user_id: nil,
diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
commit_email_hostname: default_commit_email_hostname,
- protected_ci_variables: false
+ protected_ci_variables: false,
+ local_markdown_version: 0
}
end
@@ -312,7 +318,7 @@ class ApplicationSetting < ActiveRecord::Base
end
def self.create_from_defaults
- create(defaults)
+ build_from_defaults.tap(&:save)
end
def self.human_attribute_name(attr, _options = {})
@@ -383,7 +389,7 @@ class ApplicationSetting < ActiveRecord::Base
end
def restricted_visibility_levels=(levels)
- super(levels.map { |level| Gitlab::VisibilityLevel.level_value(level) })
+ super(levels&.map { |level| Gitlab::VisibilityLevel.level_value(level) })
end
def strip_sentry_values
diff --git a/app/models/blob.rb b/app/models/blob.rb
index 66a0925c495..c5766eb0327 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -102,7 +102,7 @@ class Blob < SimpleDelegator
# If the blob is a text based blob the content is converted to UTF-8 and any
# invalid byte sequences are replaced.
def data
- if binary?
+ if binary_in_repo?
super
else
@data ||= super.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
@@ -149,7 +149,7 @@ class Blob < SimpleDelegator
# an LFS pointer, we assume the file stored in LFS is binary, unless a
# text-based rich blob viewer matched on the file's extension. Otherwise, this
# depends on the type of the blob itself.
- def raw_binary?
+ def binary?
if stored_externally?
if rich_viewer
rich_viewer.binary?
@@ -161,7 +161,7 @@ class Blob < SimpleDelegator
true
end
else
- binary?
+ binary_in_repo?
end
end
@@ -180,7 +180,7 @@ class Blob < SimpleDelegator
end
def readable_text?
- text? && !stored_externally? && !truncated?
+ text_in_repo? && !stored_externally? && !truncated?
end
def simple_viewer
@@ -220,7 +220,7 @@ class Blob < SimpleDelegator
def simple_viewer_class
if empty?
BlobViewer::Empty
- elsif raw_binary?
+ elsif binary?
BlobViewer::Download
else # text
BlobViewer::Text
diff --git a/app/models/blob_viewer/base.rb b/app/models/blob_viewer/base.rb
index eaaf9af1330..df6b9bb2f0b 100644
--- a/app/models/blob_viewer/base.rb
+++ b/app/models/blob_viewer/base.rb
@@ -16,7 +16,7 @@ module BlobViewer
def initialize(blob)
@blob = blob
- @initially_binary = blob.binary?
+ @initially_binary = blob.binary_in_repo?
end
def self.partial_path
@@ -52,7 +52,7 @@ module BlobViewer
end
def self.can_render?(blob, verify_binary: true)
- return false if verify_binary && binary? != blob.binary?
+ return false if verify_binary && binary? != blob.binary_in_repo?
return true if extensions&.include?(blob.extension)
return true if file_types&.include?(blob.file_type)
@@ -72,7 +72,7 @@ module BlobViewer
end
def binary_detected_after_load?
- !@initially_binary && blob.binary?
+ !@initially_binary && blob.binary_in_repo?
end
# This method is used on the server side to check whether we can attempt to
diff --git a/app/models/blob_viewer/gitlab_ci_yml.rb b/app/models/blob_viewer/gitlab_ci_yml.rb
index 655241c2808..11228e620c9 100644
--- a/app/models/blob_viewer/gitlab_ci_yml.rb
+++ b/app/models/blob_viewer/gitlab_ci_yml.rb
@@ -10,16 +10,16 @@ module BlobViewer
self.file_types = %i(gitlab_ci)
self.binary = false
- def validation_message(project, sha)
+ def validation_message(opts)
return @validation_message if defined?(@validation_message)
prepare!
- @validation_message = Gitlab::Ci::YamlProcessor.validation_message(blob.data, { project: project, sha: sha })
+ @validation_message = Gitlab::Ci::YamlProcessor.validation_message(blob.data, opts)
end
- def valid?(project, sha)
- validation_message(project, sha).blank?
+ def valid?(opts)
+ validation_message(opts).blank?
end
end
end
diff --git a/app/models/board.rb b/app/models/board.rb
index a137863456c..758a71d6903 100644
--- a/app/models/board.rb
+++ b/app/models/board.rb
@@ -21,6 +21,10 @@ class Board < ActiveRecord::Base
group_id.present?
end
+ def project_board?
+ project_id.present?
+ end
+
def backlog_list
lists.merge(List.backlog).take
end
diff --git a/app/models/board_group_recent_visit.rb b/app/models/board_group_recent_visit.rb
index 92abbb67222..f5b75270595 100644
--- a/app/models/board_group_recent_visit.rb
+++ b/app/models/board_group_recent_visit.rb
@@ -10,7 +10,7 @@ class BoardGroupRecentVisit < ActiveRecord::Base
validates :group, presence: true
validates :board, presence: true
- scope :by_user_group, -> (user, group) { where(user: user, group: group).order(:updated_at) }
+ scope :by_user_group, -> (user, group) { where(user: user, group: group) }
def self.visited!(user, board)
visit = find_or_create_by(user: user, group: board.group, board: board)
@@ -19,7 +19,10 @@ class BoardGroupRecentVisit < ActiveRecord::Base
retry
end
- def self.latest(user, group)
- by_user_group(user, group).last
+ def self.latest(user, group, count: nil)
+ visits = by_user_group(user, group).order(updated_at: :desc)
+ visits = visits.preload(:board) if count && count > 1
+
+ visits.first(count)
end
end
diff --git a/app/models/board_project_recent_visit.rb b/app/models/board_project_recent_visit.rb
index 7cffff906d8..2a1b14b3ae0 100644
--- a/app/models/board_project_recent_visit.rb
+++ b/app/models/board_project_recent_visit.rb
@@ -10,7 +10,7 @@ class BoardProjectRecentVisit < ActiveRecord::Base
validates :project, presence: true
validates :board, presence: true
- scope :by_user_project, -> (user, project) { where(user: user, project: project).order(:updated_at) }
+ scope :by_user_project, -> (user, project) { where(user: user, project: project) }
def self.visited!(user, board)
visit = find_or_create_by(user: user, project: board.project, board: board)
@@ -19,7 +19,10 @@ class BoardProjectRecentVisit < ActiveRecord::Base
retry
end
- def self.latest(user, project)
- by_user_project(user, project).last
+ def self.latest(user, project, count: nil)
+ visits = by_user_project(user, project).order(updated_at: :desc)
+ visits = visits.preload(:board) if count && count > 1
+
+ visits.first(count)
end
end
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb
index 29aa00a66d9..0d8d7d95791 100644
--- a/app/models/ci/bridge.rb
+++ b/app/models/ci/bridge.rb
@@ -2,13 +2,19 @@
module Ci
class Bridge < CommitStatus
+ include Ci::Processable
+ include Ci::Contextable
include Importable
include AfterCommitQueue
+ include HasRef
include Gitlab::Utils::StrongMemoize
belongs_to :project
+ belongs_to :trigger_request
validates :ref, presence: true
+ delegate :merge_request_event?, to: :pipeline
+
def self.retry(bridge, current_user)
raise NotImplementedError
end
@@ -23,12 +29,31 @@ module Ci
.fabricate!
end
- def predefined_variables
- raise NotImplementedError
+ def schedulable?
+ false
+ end
+
+ def action?
+ false
+ end
+
+ def artifacts?
+ false
+ end
+
+ def runnable?
+ false
+ end
+
+ def expanded_environment_name
end
def execute_hooks
raise NotImplementedError
end
+
+ def to_partial_path
+ 'projects/generic_commit_statuses/generic_commit_status'
+ end
end
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 16a72c680fa..a64c6051f95 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -3,13 +3,22 @@
module Ci
class Build < CommitStatus
prepend ArtifactMigratable
+ include Ci::Processable
+ include Ci::Metadatable
+ include Ci::Contextable
include TokenAuthenticatable
include AfterCommitQueue
include ObjectStorage::BackgroundMove
include Presentable
include Importable
+ include IgnorableColumn
include Gitlab::Utils::StrongMemoize
include Deployable
+ include HasRef
+
+ BuildArchivedError = Class.new(StandardError)
+
+ ignore_column :commands
belongs_to :project, inverse_of: :builds
belongs_to :runner
@@ -30,25 +39,34 @@ module Ci
has_one :"job_artifacts_#{key}", -> { where(file_type: value) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
end
- has_one :metadata, class_name: 'Ci::BuildMetadata'
has_one :runner_session, class_name: 'Ci::BuildRunnerSession', validate: true, inverse_of: :build
accepts_nested_attributes_for :runner_session
- delegate :timeout, to: :metadata, prefix: true, allow_nil: true
delegate :url, to: :runner_session, prefix: true, allow_nil: true
delegate :terminal_specification, to: :runner_session, allow_nil: true
delegate :gitlab_deploy_token, to: :project
delegate :trigger_short_token, to: :trigger_request, allow_nil: true
+ delegate :merge_request_event?, to: :pipeline
##
- # The "environment" field for builds is a String, and is the unexpanded name!
+ # Since Gitlab 11.5, deployments records started being created right after
+ # `ci_builds` creation. We can look up a relevant `environment` through
+ # `deployment` relation today. This is much more efficient than expanding
+ # environment name with variables.
+ # (See more https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22380)
#
+ # However, we have to still expand environment name if it's a stop action,
+ # because `deployment` persists information for start action only.
+ #
+ # We will follow up this by persisting expanded name in build metadata or
+ # persisting stop action in database.
def persisted_environment
return unless has_environment?
strong_memoize(:persisted_environment) do
- Environment.find_by(name: expanded_environment_name, project: project)
+ deployment&.environment ||
+ Environment.find_by(name: expanded_environment_name, project: project)
end
end
@@ -120,13 +138,12 @@ module Ci
acts_as_taggable
- add_authentication_token_field :token, encrypted: true, fallback: true
+ add_authentication_token_field :token, encrypted: :optional
before_save :update_artifacts_size, if: :artifacts_file_changed?
before_save :ensure_token
before_destroy { unscoped_project }
- before_create :ensure_metadata
after_create unless: :importing? do |build|
run_after_commit { BuildHooksWorker.perform_async(build.id) }
end
@@ -218,8 +235,19 @@ module Ci
before_transition any => [:failed] do |build|
next unless build.project
+ next unless build.deployment
+
+ begin
+ build.deployment.drop!
+ rescue => e
+ Gitlab::Sentry.track_exception(e, extra: { build_id: build.id })
+ end
+
+ true
+ end
- build.deployment&.drop
+ after_transition any => [:failed] do |build|
+ next unless build.project
if build.retry_failure?
begin
@@ -243,10 +271,6 @@ module Ci
end
end
- def ensure_metadata
- metadata || build_metadata(project: project)
- end
-
def detailed_status(current_user)
Gitlab::Ci::Status::Build::Factory
.new(self, current_user)
@@ -266,13 +290,8 @@ module Ci
self.name == 'pages'
end
- # degenerated build is one that cannot be run by Runner
- def degenerated?
- self.options.nil?
- end
-
- def degenerate!
- self.update!(options: nil, yaml_variables: nil, commands: nil)
+ def runnable?
+ true
end
def archived?
@@ -384,63 +403,59 @@ module Ci
options&.dig(:environment, :on_stop)
end
- # A slugified version of the build ref, suitable for inclusion in URLs and
- # domain names. Rules:
+ ##
+ # All variables, including persisted environment variables.
#
- # * Lowercased
- # * Anything not matching [a-z0-9-] is replaced with a -
- # * Maximum length is 63 bytes
- # * First/Last Character is not a hyphen
- def ref_slug
- Gitlab::Utils.slugify(ref.to_s)
+ def variables
+ strong_memoize(:variables) do
+ Gitlab::Ci::Variables::Collection.new
+ .concat(persisted_variables)
+ .concat(scoped_variables)
+ .concat(persisted_environment_variables)
+ .to_runner_variables
+ end
end
- ##
- # Variables in the environment name scope.
- #
- def scoped_variables(environment: expanded_environment_name)
+ CI_REGISTRY_USER = 'gitlab-ci-token'.freeze
+
+ def persisted_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
- variables.concat(predefined_variables)
- variables.concat(project.predefined_variables)
- variables.concat(pipeline.predefined_variables)
- variables.concat(runner.predefined_variables) if runner
- variables.concat(project.deployment_variables(environment: environment)) if environment
- variables.concat(yaml_variables)
- variables.concat(user_variables)
- variables.concat(secret_group_variables)
- variables.concat(secret_project_variables(environment: environment))
- variables.concat(trigger_request.user_variables) if trigger_request
- variables.concat(pipeline.variables)
- variables.concat(pipeline.pipeline_schedule.job_variables) if pipeline.pipeline_schedule
+ break variables unless persisted?
+
+ variables
+ .concat(pipeline.persisted_variables)
+ .append(key: 'CI_JOB_ID', value: id.to_s)
+ .append(key: 'CI_JOB_URL', value: Gitlab::Routing.url_helpers.project_job_url(project, self))
+ .append(key: 'CI_JOB_TOKEN', value: token.to_s, public: false)
+ .append(key: 'CI_BUILD_ID', value: id.to_s)
+ .append(key: 'CI_BUILD_TOKEN', value: token.to_s, public: false)
+ .append(key: 'CI_REGISTRY_USER', value: CI_REGISTRY_USER)
+ .append(key: 'CI_REGISTRY_PASSWORD', value: token.to_s, public: false)
+ .append(key: 'CI_REPOSITORY_URL', value: repo_url.to_s, public: false)
+ .concat(deploy_token_variables)
end
end
- ##
- # Variables that do not depend on the environment name.
- #
- def simple_variables
- strong_memoize(:simple_variables) do
- scoped_variables(environment: nil).to_runner_variables
+ def persisted_environment_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ break variables unless persisted? && persisted_environment.present?
+
+ variables.concat(persisted_environment.predefined_variables)
+
+ # Here we're passing unexpanded environment_url for runner to expand,
+ # and we need to make sure that CI_ENVIRONMENT_NAME and
+ # CI_ENVIRONMENT_SLUG so on are available for the URL be expanded.
+ variables.append(key: 'CI_ENVIRONMENT_URL', value: environment_url) if environment_url
end
end
- ##
- # All variables, including persisted environment variables.
- #
- def variables
- Gitlab::Ci::Variables::Collection.new
- .concat(persisted_variables)
- .concat(scoped_variables)
- .concat(persisted_environment_variables)
- .to_runner_variables
- end
+ def deploy_token_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ break variables unless gitlab_deploy_token
- ##
- # Regular Ruby hash of scoped variables, without duplicates that are
- # possible to be present in an array of hashes returned from `variables`.
- #
- def scoped_variables_hash
- scoped_variables.to_hash
+ variables.append(key: 'CI_DEPLOY_USER', value: gitlab_deploy_token.username)
+ variables.append(key: 'CI_DEPLOY_PASSWORD', value: gitlab_deploy_token.token, public: false)
+ end
end
def features
@@ -618,35 +633,6 @@ module Ci
super || project.try(:build_coverage_regex)
end
- def when
- read_attribute(:when) || build_attributes_from_config[:when] || 'on_success'
- end
-
- def yaml_variables
- read_attribute(:yaml_variables) || build_attributes_from_config[:yaml_variables] || []
- end
-
- def user_variables
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- break variables if user.blank?
-
- variables.append(key: 'GITLAB_USER_ID', value: user.id.to_s)
- variables.append(key: 'GITLAB_USER_EMAIL', value: user.email)
- variables.append(key: 'GITLAB_USER_LOGIN', value: user.username)
- variables.append(key: 'GITLAB_USER_NAME', value: user.name)
- end
- end
-
- def secret_group_variables
- return [] unless project.group
-
- project.group.ci_variables_for(ref, project)
- end
-
- def secret_project_variables(environment: persisted_environment)
- project.ci_variables_for(ref: ref, environment: environment)
- end
-
def steps
[Gitlab::Ci::Build::Step.from_commands(self),
Gitlab::Ci::Build::Step.from_after_script(self)].compact
@@ -749,7 +735,7 @@ module Ci
# Virtual deployment status depending on the environment status.
def deployment_status
- return nil unless starts_environment?
+ return unless starts_environment?
if success?
return successful_deployment_status
@@ -806,89 +792,6 @@ module Ci
@unscoped_project ||= Project.unscoped.find_by(id: project_id)
end
- CI_REGISTRY_USER = 'gitlab-ci-token'.freeze
-
- def persisted_variables
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- break variables unless persisted?
-
- variables
- .concat(pipeline.persisted_variables)
- .append(key: 'CI_JOB_ID', value: id.to_s)
- .append(key: 'CI_JOB_URL', value: Gitlab::Routing.url_helpers.project_job_url(project, self))
- .append(key: 'CI_JOB_TOKEN', value: token.to_s, public: false)
- .append(key: 'CI_BUILD_ID', value: id.to_s)
- .append(key: 'CI_BUILD_TOKEN', value: token.to_s, public: false)
- .append(key: 'CI_REGISTRY_USER', value: CI_REGISTRY_USER)
- .append(key: 'CI_REGISTRY_PASSWORD', value: token.to_s, public: false)
- .append(key: 'CI_REPOSITORY_URL', value: repo_url.to_s, public: false)
- .concat(deploy_token_variables)
- end
- end
-
- def predefined_variables # rubocop:disable Metrics/AbcSize
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- variables.append(key: 'CI', value: 'true')
- variables.append(key: 'GITLAB_CI', value: 'true')
- variables.append(key: 'GITLAB_FEATURES', value: project.licensed_features.join(','))
- variables.append(key: 'CI_SERVER_NAME', value: 'GitLab')
- variables.append(key: 'CI_SERVER_VERSION', value: Gitlab::VERSION)
- variables.append(key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s)
- variables.append(key: 'CI_SERVER_VERSION_MINOR', value: Gitlab.version_info.minor.to_s)
- variables.append(key: 'CI_SERVER_VERSION_PATCH', value: Gitlab.version_info.patch.to_s)
- variables.append(key: 'CI_SERVER_REVISION', value: Gitlab.revision)
- variables.append(key: 'CI_JOB_NAME', value: name)
- variables.append(key: 'CI_JOB_STAGE', value: stage)
- variables.append(key: 'CI_COMMIT_SHA', value: sha)
- variables.append(key: 'CI_COMMIT_SHORT_SHA', value: short_sha)
- variables.append(key: 'CI_COMMIT_BEFORE_SHA', value: before_sha)
- variables.append(key: 'CI_COMMIT_REF_NAME', value: ref)
- variables.append(key: 'CI_COMMIT_REF_SLUG', value: ref_slug)
- variables.append(key: "CI_COMMIT_TAG", value: ref) if tag?
- variables.append(key: "CI_PIPELINE_TRIGGERED", value: 'true') if trigger_request
- variables.append(key: "CI_JOB_MANUAL", value: 'true') if action?
- variables.append(key: "CI_NODE_INDEX", value: self.options[:instance].to_s) if self.options&.include?(:instance)
- variables.append(key: "CI_NODE_TOTAL", value: (self.options&.dig(:parallel) || 1).to_s)
- variables.concat(legacy_variables)
- end
- end
-
- def legacy_variables
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- variables.append(key: 'CI_BUILD_REF', value: sha)
- variables.append(key: 'CI_BUILD_BEFORE_SHA', value: before_sha)
- variables.append(key: 'CI_BUILD_REF_NAME', value: ref)
- variables.append(key: 'CI_BUILD_REF_SLUG', value: ref_slug)
- variables.append(key: 'CI_BUILD_NAME', value: name)
- variables.append(key: 'CI_BUILD_STAGE', value: stage)
- variables.append(key: "CI_BUILD_TAG", value: ref) if tag?
- variables.append(key: "CI_BUILD_TRIGGERED", value: 'true') if trigger_request
- variables.append(key: "CI_BUILD_MANUAL", value: 'true') if action?
- end
- end
-
- def persisted_environment_variables
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- break variables unless persisted? && persisted_environment.present?
-
- variables.concat(persisted_environment.predefined_variables)
-
- # Here we're passing unexpanded environment_url for runner to expand,
- # and we need to make sure that CI_ENVIRONMENT_NAME and
- # CI_ENVIRONMENT_SLUG so on are available for the URL be expanded.
- variables.append(key: 'CI_ENVIRONMENT_URL', value: environment_url) if environment_url
- end
- end
-
- def deploy_token_variables
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- break variables unless gitlab_deploy_token
-
- variables.append(key: 'CI_DEPLOY_USER', value: gitlab_deploy_token.username)
- variables.append(key: 'CI_DEPLOY_PASSWORD', value: gitlab_deploy_token.token, public: false)
- end
- end
-
def environment_url
options&.dig(:environment, :url) || persisted_environment&.external_url
end
@@ -899,8 +802,11 @@ module Ci
# have the old integer only format. This method returns the retry option
# normalized as a hash in 11.5+ format.
def normalized_retry
- value = options&.dig(:retry)
- value.is_a?(Integer) ? { max: value } : value.to_h
+ strong_memoize(:normalized_retry) do
+ value = options&.dig(:retry)
+ value = value.is_a?(Integer) ? { max: value } : value.to_h
+ value.with_indifferent_access
+ end
end
def build_attributes_from_config
diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb
index 9d588b862bd..cd8eb774cf5 100644
--- a/app/models/ci/build_metadata.rb
+++ b/app/models/ci/build_metadata.rb
@@ -10,11 +10,15 @@ module Ci
self.table_name = 'ci_builds_metadata'
- belongs_to :build, class_name: 'Ci::Build'
+ belongs_to :build, class_name: 'CommitStatus'
belongs_to :project
+ before_create :set_build_project
+
validates :build, presence: true
- validates :project, presence: true
+
+ serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :config_variables, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
chronic_duration_attr_reader :timeout_human_readable, :timeout
@@ -33,5 +37,11 @@ module Ci
update(timeout: timeout, timeout_source: timeout_source)
end
+
+ private
+
+ def set_build_project
+ self.project_id ||= self.build.project_id
+ end
end
end
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index da08214963f..75017f224a0 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -18,7 +18,7 @@ module Ci
FailedToPersistDataError = Class.new(StandardError)
# Note: The ordering of this enum is related to the precedence of persist store.
- # The bottom item takes the higest precedence, and the top item takes the lowest precedence.
+ # The bottom item takes the highest precedence, and the top item takes the lowest precedence.
enum data_store: {
redis: 1,
database: 2,
@@ -115,7 +115,7 @@ module Ci
current_data = get_data
unless current_data&.bytesize.to_i == CHUNK_SIZE
- raise FailedToPersistDataError, 'Data is not fullfilled in a bucket'
+ raise FailedToPersistDataError, 'Data is not fulfilled in a bucket'
end
old_store_class = self.class.get_store_class(data_store)
diff --git a/app/models/ci/group_variable.rb b/app/models/ci/group_variable.rb
index 492d1d0329e..323ff560564 100644
--- a/app/models/ci/group_variable.rb
+++ b/app/models/ci/group_variable.rb
@@ -5,6 +5,7 @@ module Ci
extend Gitlab::Ci::Model
include HasVariable
include Presentable
+ include Maskable
belongs_to :group, class_name: "::Group"
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index 11c88200c37..789bb293811 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -73,6 +73,8 @@ module Ci
where(file_type: types)
end
+ scope :expired, -> (limit) { where('expire_at < ?', Time.now).limit(limit) }
+
delegate :filename, :exists?, :open, to: :file
enum file_type: {
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 25937065011..ca9725f7a04 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -11,6 +11,11 @@ module Ci
include Gitlab::Utils::StrongMemoize
include AtomicInternalId
include EnumWithNil
+ include HasRef
+ include ShaAttribute
+
+ sha_attribute :source_sha
+ sha_attribute :target_sha
belongs_to :project, inverse_of: :all_pipelines
belongs_to :user
@@ -24,6 +29,8 @@ module Ci
has_many :stages, -> { order(position: :asc) }, inverse_of: :pipeline
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
+ has_many :processables, -> { processables },
+ class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent
has_many :variables, class_name: 'Ci::PipelineVariable'
@@ -32,7 +39,7 @@ module Ci
# Merge requests for which the current pipeline is running against
# the merge request's latest commit.
- has_many :merge_requests, foreign_key: "head_pipeline_id"
+ has_many :merge_requests_as_head_pipeline, foreign_key: "head_pipeline_id", class_name: 'MergeRequest'
has_many :pending_builds, -> { pending }, foreign_key: :commit_id, class_name: 'Ci::Build'
has_many :retryable_builds, -> { latest.failed_or_canceled.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
@@ -44,6 +51,8 @@ module Ci
has_many :auto_canceled_pipelines, class_name: 'Ci::Pipeline', foreign_key: 'auto_canceled_by_id'
has_many :auto_canceled_jobs, class_name: 'CommitStatus', foreign_key: 'auto_canceled_by_id'
+ has_one :chat_data, class_name: 'Ci::PipelineChatData'
+
accepts_nested_attributes_for :variables, reject_if: :persisted?
delegate :id, to: :project, prefix: true
@@ -51,9 +60,9 @@ module Ci
validates :sha, presence: { unless: :importing? }
validates :ref, presence: { unless: :importing? }
- validates :merge_request, presence: { if: :merge_request? }
- validates :merge_request, absence: { unless: :merge_request? }
- validates :tag, inclusion: { in: [false], if: :merge_request? }
+ validates :merge_request, presence: { if: :merge_request_event? }
+ validates :merge_request, absence: { unless: :merge_request_event? }
+ validates :tag, inclusion: { in: [false], if: :merge_request_event? }
validates :status, presence: { unless: :importing? }
validate :valid_commit_sha, unless: :importing?
validates :source, exclusion: { in: %w(unknown), unless: :importing? }, on: :create
@@ -170,13 +179,38 @@ module Ci
scope :sort_by_merge_request_pipelines, -> do
sql = 'CASE ci_pipelines.source WHEN (?) THEN 0 ELSE 1 END, ci_pipelines.id DESC'
- query = ActiveRecord::Base.send(:sanitize_sql_array, [sql, sources[:merge_request]]) # rubocop:disable GitlabSecurity/PublicSend
+ query = ActiveRecord::Base.send(:sanitize_sql_array, [sql, sources[:merge_request_event]]) # rubocop:disable GitlabSecurity/PublicSend
order(query)
end
scope :for_user, -> (user) { where(user: user) }
+ scope :for_merge_request, -> (merge_request, ref, sha) do
+ ##
+ # We have to filter out unrelated MR pipelines.
+ # When merge request is empty, it selects general pipelines, such as push sourced pipelines.
+ # When merge request is matched, it selects MR pipelines.
+ where(merge_request: [nil, merge_request], ref: ref, sha: sha)
+ .sort_by_merge_request_pipelines
+ end
+
+ scope :triggered_by_merge_request, -> (merge_request) do
+ where(source: :merge_request_event, merge_request: merge_request)
+ end
+
+ scope :detached_merge_request_pipelines, -> (merge_request) do
+ triggered_by_merge_request(merge_request).where(target_sha: nil)
+ end
+
+ scope :merge_request_pipelines, -> (merge_request) do
+ triggered_by_merge_request(merge_request).where.not(target_sha: nil)
+ end
+
+ scope :mergeable_merge_request_pipelines, -> (merge_request) do
+ triggered_by_merge_request(merge_request).where(target_sha: merge_request.target_branch_sha)
+ end
+
# Returns the pipelines in descending order (= newest first), optionally
# limited to a number of references.
#
@@ -264,6 +298,10 @@ module Ci
sources.reject { |source| source == "external" }.values
end
+ def self.latest_for_merge_request(merge_request, ref, sha)
+ for_merge_request(merge_request, ref, sha).first
+ end
+
def self.ci_sources_values
config_sources.values_at(:repository_source, :auto_devops_source, :unknown_source)
end
@@ -299,7 +337,7 @@ module Ci
def ordered_stages
return legacy_stages unless complete?
- if Feature.enabled?('ci_pipeline_persisted_stages')
+ if Feature.enabled?('ci_pipeline_persisted_stages', default_enabled: true)
stages
else
legacy_stages
@@ -379,10 +417,6 @@ module Ci
@commit ||= Commit.lazy(project, sha)
end
- def branch?
- !tag? && !merge_request?
- end
-
def stuck?
pending_builds.any?(&:stuck?)
end
@@ -495,7 +529,7 @@ module Ci
return @config_processor if defined?(@config_processor)
@config_processor ||= begin
- ::Gitlab::Ci::YamlProcessor.new(ci_yaml_file, { project: project, sha: sha })
+ ::Gitlab::Ci::YamlProcessor.new(ci_yaml_file, { project: project, sha: sha, user: user })
rescue Gitlab::Ci::YamlProcessor::ValidationError => e
self.yaml_errors = e.message
nil
@@ -580,7 +614,7 @@ module Ci
end
def protected_ref?
- strong_memoize(:protected_ref) { project.protected_for?(ref) }
+ strong_memoize(:protected_ref) { project.protected_for?(git_ref) }
end
def legacy_trigger
@@ -605,7 +639,9 @@ module Ci
variables.append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title.to_s)
variables.append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
- if merge_request? && merge_request
+ if merge_request_event? && merge_request
+ variables.append(key: 'CI_MERGE_REQUEST_SOURCE_BRANCH_SHA', value: source_sha.to_s)
+ variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_SHA', value: target_sha.to_s)
variables.concat(merge_request.predefined_variables)
end
end
@@ -633,10 +669,10 @@ module Ci
# All the merge requests for which the current pipeline runs/ran against
def all_merge_requests
@all_merge_requests ||=
- if merge_request?
- project.merge_requests.where(id: merge_request.id)
+ if merge_request_event?
+ MergeRequest.where(id: merge_request_id)
else
- project.merge_requests.where(source_branch: ref)
+ MergeRequest.where(source_project_id: project_id, source_branch: ref)
end
end
@@ -671,9 +707,18 @@ module Ci
end
end
+ # Returns the modified paths.
+ #
+ # The returned value is
+ # * Array: List of modified paths that should be evaluated
+ # * nil: Modified path can not be evaluated
def modified_paths
strong_memoize(:modified_paths) do
- push_details.modified_paths
+ if merge_request_event?
+ merge_request.modified_paths
+ elsif branch_updated?
+ push_details.modified_paths
+ end
end
end
@@ -681,6 +726,22 @@ module Ci
ref == project.default_branch
end
+ def triggered_by_merge_request?
+ merge_request_event? && merge_request_id.present?
+ end
+
+ def detached_merge_request_pipeline?
+ triggered_by_merge_request? && target_sha.nil?
+ end
+
+ def merge_request_pipeline?
+ triggered_by_merge_request? && target_sha.present?
+ end
+
+ def mergeable_merge_request_pipeline?
+ triggered_by_merge_request? && target_sha == merge_request.target_branch_sha
+ end
+
private
def ci_yaml_from_repo
@@ -712,14 +773,16 @@ module Ci
end
def git_ref
- if branch?
- Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
- elsif merge_request?
+ if merge_request_event?
+ ##
+ # In the future, we're going to change this ref to
+ # merge request's merged reference, such as "refs/merge-requests/:iid/merge".
+ # In order to do that, we have to update GitLab-Runner's source pulling
+ # logic.
+ # See https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1092
Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
- elsif tag?
- Gitlab::Git::TAG_REF_PREFIX + ref.to_s
else
- raise ArgumentError, 'Invalid pipeline type!'
+ super
end
end
diff --git a/app/models/ci/pipeline_chat_data.rb b/app/models/ci/pipeline_chat_data.rb
new file mode 100644
index 00000000000..8d37500fec5
--- /dev/null
+++ b/app/models/ci/pipeline_chat_data.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Ci
+ class PipelineChatData < ActiveRecord::Base
+ self.table_name = 'ci_pipeline_chat_data'
+
+ belongs_to :chat_name
+
+ validates :pipeline_id, presence: true
+ validates :chat_name_id, presence: true
+ validates :response_url, presence: true
+ end
+end
diff --git a/app/models/ci/pipeline_enums.rb b/app/models/ci/pipeline_enums.rb
index 2994aaae4aa..571c4271475 100644
--- a/app/models/ci/pipeline_enums.rb
+++ b/app/models/ci/pipeline_enums.rb
@@ -22,7 +22,8 @@ module Ci
schedule: 4,
api: 5,
external: 6,
- merge_request: 10
+ chat: 8,
+ merge_request_event: 10
}
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 8249199e76f..ce26ee168ef 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -10,7 +10,7 @@ module Ci
include FromUnion
include TokenAuthenticatable
- add_authentication_token_field :token, encrypted: true, migrating: true
+ add_authentication_token_field :token, encrypted: -> { Feature.enabled?(:ci_runners_tokens_optional_encryption) ? :optional : :required }
enum access_level: {
not_protected: 0,
@@ -97,6 +97,7 @@ module Ci
scope :order_contacted_at_asc, -> { order(contacted_at: :asc) }
scope :order_created_at_desc, -> { order(created_at: :desc) }
+ scope :with_tags, -> { preload(:tags) }
validate :tag_constraints
validates :access_level, presence: true
@@ -256,6 +257,10 @@ module Ci
end
end
+ def uncached_contacted_at
+ read_attribute(:contacted_at)
+ end
+
private
def cleanup_runner_queue
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index 58f3fe2460a..0389945191e 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -14,6 +14,7 @@ module Ci
has_many :statuses, class_name: 'CommitStatus', foreign_key: :stage_id
has_many :builds, foreign_key: :stage_id
+ has_many :bridges, foreign_key: :stage_id
with_options unless: :importing? do
validates :project, presence: true
diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb
index 55db42162ca..637148c4ce4 100644
--- a/app/models/ci/trigger.rb
+++ b/app/models/ci/trigger.rb
@@ -4,6 +4,7 @@ module Ci
class Trigger < ActiveRecord::Base
extend Gitlab::Ci::Model
include IgnorableColumn
+ include Presentable
ignore_column :deleted_at
@@ -29,7 +30,7 @@ module Ci
end
def short_token
- token[0...4]
+ token[0...4] if token.present?
end
def legacy?
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index 524d79014f8..64836ea4fa4 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -5,6 +5,7 @@ module Ci
extend Gitlab::Ci::Model
include HasVariable
include Presentable
+ include Maskable
belongs_to :project
diff --git a/app/models/clusters/applications/cert_manager.rb b/app/models/clusters/applications/cert_manager.rb
index 74ef7c7e145..c758577815a 100644
--- a/app/models/clusters/applications/cert_manager.rb
+++ b/app/models/clusters/applications/cert_manager.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class CertManager < ActiveRecord::Base
- VERSION = 'v0.5.0'.freeze
+ VERSION = 'v0.5.2'.freeze
self.table_name = 'clusters_applications_cert_managers'
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index 8f8790585a3..7c15aaa4825 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Ingress < ActiveRecord::Base
- VERSION = '0.23.0'.freeze
+ VERSION = '1.1.2'.freeze
self.table_name = 'clusters_applications_ingress'
@@ -23,7 +23,7 @@ module Clusters
FETCH_IP_ADDRESS_DELAY = 30.seconds
state_machine :status do
- before_transition any => [:installed] do |application|
+ after_transition any => [:installed] do |application|
application.run_after_commit do
ClusterWaitForIngressIpAddressWorker.perform_in(
FETCH_IP_ADDRESS_DELAY, application.name, application.id)
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 0c72d7d8340..8d79b041b64 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -5,7 +5,7 @@ module Clusters
class Knative < ActiveRecord::Base
VERSION = '0.2.2'.freeze
REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze
-
+ METRICS_CONFIG = 'https://storage.googleapis.com/triggermesh-charts/istio-metrics.yaml'.freeze
FETCH_IP_ADDRESS_DELAY = 30.seconds
self.table_name = 'clusters_applications_knative'
@@ -19,8 +19,15 @@ module Clusters
self.reactive_cache_key = ->(knative) { [knative.class.model_name.singular, knative.id] }
+ def set_initial_status
+ return unless not_installable?
+ return unless verify_cluster?
+
+ self.status = 'installable'
+ end
+
state_machine :status do
- before_transition any => [:installed] do |application|
+ after_transition any => [:installed] do |application|
application.run_after_commit do
ClusterWaitForIngressIpAddressWorker.perform_in(
FETCH_IP_ADDRESS_DELAY, application.name, application.id)
@@ -34,6 +41,8 @@ module Clusters
scope :for_cluster, -> (cluster) { where(cluster: cluster) }
+ after_save :clear_reactive_cache!
+
def chart
'knative/knative'
end
@@ -49,7 +58,8 @@ module Clusters
rbac: cluster.platform_kubernetes_rbac?,
chart: chart,
files: files,
- repository: REPOSITORY
+ repository: REPOSITORY,
+ postinstall: install_knative_metrics
)
end
@@ -71,7 +81,7 @@ module Clusters
end
def calculate_reactive_cache
- { services: read_services }
+ { services: read_services, pods: read_pods }
end
def ingress_service
@@ -79,7 +89,7 @@ module Clusters
end
def services_for(ns: namespace)
- return unless services
+ return [] unless services
return [] unless ns
services.select do |service|
@@ -87,13 +97,35 @@ module Clusters
end
end
+ def service_pod_details(ns, service)
+ with_reactive_cache do |data|
+ data[:pods].select { |pod| filter_pods(pod, ns, service) }
+ end
+ end
+
private
+ def read_pods
+ cluster.kubeclient.core_client.get_pods.as_json
+ end
+
+ def filter_pods(pod, namespace, service)
+ pod["metadata"]["namespace"] == namespace && pod["metadata"]["labels"]["serving.knative.dev/service"] == service
+ end
+
def read_services
client.get_services.as_json
rescue Kubeclient::ResourceNotFoundError
[]
end
+
+ def install_knative_metrics
+ ["kubectl apply -f #{METRICS_CONFIG}"] if cluster.application_prometheus_available?
+ end
+
+ def verify_cluster?
+ cluster&.application_helm_available? && cluster&.platform_kubernetes_rbac?
+ end
end
end
end
diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb
index 46d0388a464..fa7ce363531 100644
--- a/app/models/clusters/applications/prometheus.rb
+++ b/app/models/clusters/applications/prometheus.rb
@@ -5,7 +5,7 @@ module Clusters
class Prometheus < ActiveRecord::Base
include PrometheusAdapter
- VERSION = '6.7.3'.freeze
+ VERSION = '6.7.3'
self.table_name = 'clusters_applications_prometheus'
@@ -24,14 +24,6 @@ module Clusters
end
end
- def ready_status
- [:installed]
- end
-
- def ready?
- ready_status.include?(status_name)
- end
-
def chart
'stable/prometheus'
end
@@ -50,10 +42,29 @@ module Clusters
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,
chart: chart,
- files: files
+ files: files,
+ postinstall: install_knative_metrics
)
end
+ def upgrade_command(values)
+ ::Gitlab::Kubernetes::Helm::InstallCommand.new(
+ name: name,
+ version: VERSION,
+ rbac: cluster.platform_kubernetes_rbac?,
+ chart: chart,
+ files: files_with_replaced_values(values)
+ )
+ end
+
+ # Returns a copy of files where the values of 'values.yaml'
+ # are replaced by the argument.
+ #
+ # See #values for the data format required
+ def files_with_replaced_values(replaced_values)
+ files.merge('values.yaml': replaced_values)
+ end
+
def prometheus_client
return unless kube_client
@@ -74,6 +85,10 @@ module Clusters
def kube_client
cluster&.kubeclient&.core_client
end
+
+ def install_knative_metrics
+ ["kubectl apply -f #{Clusters::Applications::Knative::METRICS_CONFIG}"] if cluster.application_knative_available?
+ end
end
end
end
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index c931b340b24..941551dadaa 100644
--- a/app/models/clusters/applications/runner.rb
+++ b/app/models/clusters/applications/runner.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Runner < ActiveRecord::Base
- VERSION = '0.1.39'.freeze
+ VERSION = '0.2.0'.freeze
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 7fe43cd2de0..be3e6a05e1e 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -18,6 +18,7 @@ module Clusters
Applications::Knative.application_name => Applications::Knative
}.freeze
DEFAULT_ENVIRONMENT = '*'.freeze
+ KUBE_INGRESS_BASE_DOMAIN = 'KUBE_INGRESS_BASE_DOMAIN'.freeze
belongs_to :user
@@ -49,8 +50,9 @@ module Clusters
validates :name, cluster_name: true
validates :cluster_type, presence: true
- validate :restrict_modification, on: :update
+ validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true }
+ validate :restrict_modification, on: :update
validate :no_groups, unless: :group_type?
validate :no_projects, unless: :project_type?
@@ -63,6 +65,10 @@ module Clusters
delegate :available?, to: :application_helm, prefix: true, allow_nil: true
delegate :available?, to: :application_ingress, prefix: true, allow_nil: true
delegate :available?, to: :application_prometheus, prefix: true, allow_nil: true
+ delegate :available?, to: :application_knative, prefix: true, allow_nil: true
+ delegate :external_ip, to: :application_ingress, prefix: true, allow_nil: true
+
+ alias_attribute :base_domain, :domain
enum cluster_type: {
instance_type: 1,
@@ -93,7 +99,7 @@ module Clusters
where('NOT EXISTS (?)', subquery)
end
- scope :with_knative_installed, -> { joins(:application_knative).merge(Clusters::Applications::Knative.installed) }
+ scope :with_knative_installed, -> { joins(:application_knative).merge(Clusters::Applications::Knative.available) }
scope :preload_knative, -> {
preload(
@@ -191,8 +197,42 @@ module Clusters
project_type?
end
+ def kube_ingress_domain
+ @kube_ingress_domain ||= domain.presence || instance_domain || legacy_auto_devops_domain
+ end
+
+ def predefined_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ break variables unless kube_ingress_domain
+
+ variables.append(key: KUBE_INGRESS_BASE_DOMAIN, value: kube_ingress_domain)
+ end
+ end
+
private
+ def instance_domain
+ @instance_domain ||= Gitlab::CurrentSettings.auto_devops_domain
+ end
+
+ # To keep backward compatibility with AUTO_DEVOPS_DOMAIN
+ # environment variable, we need to ensure KUBE_INGRESS_BASE_DOMAIN
+ # is set if AUTO_DEVOPS_DOMAIN is set on any of the following options:
+ # ProjectAutoDevops#Domain, project variables or group variables,
+ # as the AUTO_DEVOPS_DOMAIN is needed for CI_ENVIRONMENT_URL
+ #
+ # This method should is scheduled to be removed on
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/56959
+ def legacy_auto_devops_domain
+ if project_type?
+ project&.auto_devops&.domain.presence ||
+ project.variables.find_by(key: 'AUTO_DEVOPS_DOMAIN')&.value.presence ||
+ project.group&.variables&.find_by(key: 'AUTO_DEVOPS_DOMAIN')&.value.presence
+ elsif group_type?
+ group.variables.find_by(key: 'AUTO_DEVOPS_DOMAIN')&.value.presence
+ end
+ end
+
def restrict_modification
if provider&.on_creation?
errors.add(:base, "cannot modify during creation")
diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb
index 0e74cce29b7..1273ed83abe 100644
--- a/app/models/clusters/concerns/application_status.rb
+++ b/app/models/clusters/concerns/application_status.rb
@@ -6,7 +6,14 @@ module Clusters
extend ActiveSupport::Concern
included do
- scope :installed, -> { where(status: self.state_machines[:status].states[:installed].value) }
+ scope :available, -> do
+ where(
+ status: [
+ self.state_machines[:status].states[:installed].value,
+ self.state_machines[:status].states[:updated].value
+ ]
+ )
+ end
state_machine :status, initial: :not_installable do
state :not_installable, value: -2
@@ -20,7 +27,7 @@ module Clusters
state :update_errored, value: 6
event :make_scheduled do
- transition [:installable, :errored] => :scheduled
+ transition [:installable, :errored, :installed, :updated, :update_errored] => :scheduled
end
event :make_installing do
@@ -29,18 +36,16 @@ module Clusters
event :make_installed do
transition [:installing] => :installed
+ transition [:updating] => :updated
end
event :make_errored do
- transition any => :errored
+ transition any - [:updating] => :errored
+ transition [:updating] => :update_errored
end
event :make_updating do
- transition [:installed, :updated, :update_errored] => :updating
- end
-
- event :make_updated do
- transition [:updating] => :updated
+ transition [:installed, :updated, :update_errored, :scheduled] => :updating
end
event :make_update_errored do
@@ -74,9 +79,17 @@ module Clusters
end
end
+ def updateable?
+ installed? || updated? || update_errored?
+ end
+
def available?
installed? || updated?
end
+
+ def update_in_progress?
+ updating?
+ end
end
end
end
diff --git a/app/models/clusters/concerns/application_version.rb b/app/models/clusters/concerns/application_version.rb
index ccad74dc35a..db94e8e08c9 100644
--- a/app/models/clusters/concerns/application_version.rb
+++ b/app/models/clusters/concerns/application_version.rb
@@ -7,11 +7,15 @@ module Clusters
included do
state_machine :status do
- after_transition any => [:installing] do |application|
- application.update(version: application.class.const_get(:VERSION))
+ before_transition any => [:installed, :updated] do |application|
+ application.version = application.class.const_get(:VERSION)
end
end
end
+
+ def update_available?
+ version != self.class.const_get(:VERSION)
+ end
end
end
end
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 6cec497b4e4..814fc591408 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -41,8 +41,9 @@ module Clusters
validate :no_namespace, unless: :allow_user_defined_namespace?
# We expect to be `active?` only when enabled and cluster is created (the api_url is assigned)
- validates :api_url, url: true, presence: true
+ validates :api_url, public_url: true, presence: true
validates :token, presence: true
+ validates :ca_cert, certificate: true, allow_blank: true, if: :ca_cert_changed?
validate :prevent_modification, on: :update
@@ -65,6 +66,8 @@ module Clusters
abac: 2
}
+ default_value_for :authorization_type, :rbac
+
def actual_namespace
if namespace.present?
namespace
@@ -96,6 +99,8 @@ module Clusters
.append(key: 'KUBE_NAMESPACE', value: actual_namespace)
.append(key: 'KUBECONFIG', value: kubeconfig, public: false, file: true)
end
+
+ variables.concat(cluster.predefined_variables)
end
end
@@ -106,7 +111,7 @@ module Clusters
def terminals(environment)
with_reactive_cache do |data|
pods = filter_by_label(data[:pods], app: environment.slug)
- terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) }
+ terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) }.compact
terminals.each { |terminal| add_terminal_auth(terminal, terminal_auth) }
end
end
@@ -152,7 +157,7 @@ module Clusters
def build_kube_client!
raise "Incomplete settings" unless api_url
- raise "No namespace" if cluster.project_type? && actual_namespace.empty? # can probably remove this line once we remove #actual_namespace
+ raise "No namespace" if cluster.project_type? && actual_namespace.empty? # can probably remove this line once we remove #actual_namespace
unless (username && password) || token
raise "Either username/password or token is required to access API"
diff --git a/app/models/commit.rb b/app/models/commit.rb
index a422a0995ff..f412d252e5c 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -11,6 +11,7 @@ class Commit
include Mentionable
include Referable
include StaticModel
+ include Presentable
include ::Gitlab::Utils::StrongMemoize
attr_mentionable :safe_message, pipeline: :single_line
@@ -304,7 +305,9 @@ class Commit
end
def last_pipeline
- @last_pipeline ||= pipelines.last
+ strong_memoize(:last_pipeline) do
+ pipelines.last
+ end
end
def status(ref = nil)
@@ -376,7 +379,7 @@ class Commit
end
def merge_commit?
- parents.size > 1
+ parent_ids.size > 1
end
def merged_merge_request(current_user)
@@ -469,6 +472,10 @@ class Commit
!!merged_merge_request(user)
end
+ def cache_key
+ "commit:#{sha}"
+ end
+
private
def commit_reference(from, referable_commit_id, full: false)
diff --git a/app/models/commit_collection.rb b/app/models/commit_collection.rb
index e349f0fe971..a9a2e9c81eb 100644
--- a/app/models/commit_collection.rb
+++ b/app/models/commit_collection.rb
@@ -3,6 +3,7 @@
# A collection of Commit instances for a specific project and Git reference.
class CommitCollection
include Enumerable
+ include Gitlab::Utils::StrongMemoize
attr_reader :project, :ref, :commits
@@ -19,6 +20,18 @@ class CommitCollection
commits.each(&block)
end
+ def authors
+ emails = without_merge_commits.map(&:author_email).uniq
+
+ User.by_any_email(emails)
+ end
+
+ def without_merge_commits
+ strong_memoize(:without_merge_commits) do
+ commits.reject(&:merge_commit?)
+ end
+ end
+
# Sets the pipeline status for every commit.
#
# Setting this status ahead of time removes the need for running a query for
diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb
index 094747ee48d..920b1d092dd 100644
--- a/app/models/commit_range.rb
+++ b/app/models/commit_range.rb
@@ -134,25 +134,25 @@ class CommitRange
end
def sha_from
- return nil unless @commit_from
+ return unless @commit_from
@commit_from.id
end
def sha_to
- return nil unless @commit_to
+ return unless @commit_to
@commit_to.id
end
def sha_start
- return nil unless sha_from
+ return unless sha_from
exclude_start? ? sha_from + '^' : sha_from
end
def commit_start
- return nil unless sha_start
+ return unless sha_start
if exclude_start?
@commit_start ||= project.commit(sha_start)
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 0f50bd39131..7f6562b63e5 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -41,6 +41,7 @@ class CommitStatus < ActiveRecord::Base
scope :latest_ordered, -> { latest.ordered.includes(project: :namespace) }
scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) }
scope :after_stage, -> (index) { where('stage_idx > ?', index) }
+ scope :processables, -> { where(type: %w[Ci::Build Ci::Bridge]) }
# We use `CommitStatusEnums.failure_reasons` here so that EE can more easily
# extend this `Hash` with new values.
diff --git a/app/models/concerns/blob_language_from_git_attributes.rb b/app/models/concerns/blob_language_from_git_attributes.rb
index 70213d22147..56e1276a220 100644
--- a/app/models/concerns/blob_language_from_git_attributes.rb
+++ b/app/models/concerns/blob_language_from_git_attributes.rb
@@ -5,7 +5,7 @@ module BlobLanguageFromGitAttributes
extend ActiveSupport::Concern
def language_from_gitattributes
- return nil unless project
+ return unless project
repository = project.repository
repository.gitattribute(path, 'gitlab-language')
diff --git a/app/models/concerns/blob_like.rb b/app/models/concerns/blob_like.rb
index f20f01486a5..dc80f8d62f4 100644
--- a/app/models/concerns/blob_like.rb
+++ b/app/models/concerns/blob_like.rb
@@ -28,7 +28,7 @@ module BlobLike
nil
end
- def binary?
+ def binary_in_repo?
false
end
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index a8c9e54f00c..1a8570b80c3 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -13,9 +13,8 @@ module CacheMarkdownField
extend ActiveSupport::Concern
# Increment this number every time the renderer changes its output
- CACHE_REDCARPET_VERSION = 3
CACHE_COMMONMARK_VERSION_START = 10
- CACHE_COMMONMARK_VERSION = 12
+ CACHE_COMMONMARK_VERSION = 14
# changes to these attributes cause the cache to be invalidates
INVALIDATED_BY = %w[author project].freeze
@@ -42,18 +41,6 @@ module CacheMarkdownField
end
end
- class MarkdownEngine
- def self.from_version(version = nil)
- return :common_mark if version.nil? || version == 0
-
- if version < CacheMarkdownField::CACHE_COMMONMARK_VERSION_START
- :redcarpet
- else
- :common_mark
- end
- end
- end
-
def skip_project_check?
false
end
@@ -71,7 +58,7 @@ module CacheMarkdownField
# Banzai is less strict about authors, so don't always have an author key
context[:author] = self.author if self.respond_to?(:author)
- context[:markdown_engine] = MarkdownEngine.from_version(latest_cached_markdown_version)
+ context[:markdown_engine] = :common_mark
context
end
@@ -128,12 +115,27 @@ module CacheMarkdownField
end
def latest_cached_markdown_version
- return CacheMarkdownField::CACHE_COMMONMARK_VERSION unless cached_markdown_version
+ @latest_cached_markdown_version ||= (CacheMarkdownField::CACHE_COMMONMARK_VERSION << 16) | local_version
+ end
- if cached_markdown_version < CacheMarkdownField::CACHE_COMMONMARK_VERSION_START
- CacheMarkdownField::CACHE_REDCARPET_VERSION
+ def local_version
+ # because local_markdown_version is stored in application_settings which
+ # uses cached_markdown_version too, we check explicitly to avoid
+ # endless loop
+ return local_markdown_version if has_attribute?(:local_markdown_version)
+
+ settings = Gitlab::CurrentSettings.current_application_settings
+
+ # Following migrations are not properly isolated and
+ # use real models (by calling .ghost method), in these migrations
+ # local_markdown_version attribute doesn't exist yet, so we
+ # use a default value:
+ # db/migrate/20170825104051_migrate_issues_to_ghost_user.rb
+ # db/migrate/20171114150259_merge_requests_author_id_foreign_key.rb
+ if settings.respond_to?(:local_markdown_version)
+ settings.local_markdown_version
else
- CacheMarkdownField::CACHE_COMMONMARK_VERSION
+ 0
end
end
@@ -178,7 +180,9 @@ module CacheMarkdownField
# author and project invalidate the cache in all circumstances.
define_method(invalidation_method) do
changed_fields = changed_attributes.keys
- invalidations = changed_fields & [markdown_field.to_s, *INVALIDATED_BY]
+ invalidations = changed_fields & [markdown_field.to_s, *INVALIDATED_BY]
+ invalidations.delete(markdown_field.to_s) if changed_fields.include?("#{markdown_field}_html")
+
!invalidations.empty? || !cached_html_up_to_date?(markdown_field)
end
end
diff --git a/app/models/concerns/cacheable_attributes.rb b/app/models/concerns/cacheable_attributes.rb
index 75592bb63e2..3d60f6924c1 100644
--- a/app/models/concerns/cacheable_attributes.rb
+++ b/app/models/concerns/cacheable_attributes.rb
@@ -23,7 +23,12 @@ module CacheableAttributes
end
def build_from_defaults(attributes = {})
- new(defaults.merge(attributes))
+ final_attributes = defaults
+ .merge(attributes)
+ .stringify_keys
+ .slice(*column_names)
+
+ new(final_attributes)
end
def cached
diff --git a/app/models/concerns/ci/contextable.rb b/app/models/concerns/ci/contextable.rb
new file mode 100644
index 00000000000..4986a42dbd2
--- /dev/null
+++ b/app/models/concerns/ci/contextable.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+module Ci
+ ##
+ # This module implements methods that provide context in form of
+ # essential CI/CD variables that can be used by a build / bridge job.
+ #
+ module Contextable
+ ##
+ # Variables in the environment name scope.
+ #
+ def scoped_variables(environment: expanded_environment_name)
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.concat(predefined_variables)
+ variables.concat(project.predefined_variables)
+ variables.concat(pipeline.predefined_variables)
+ variables.concat(runner.predefined_variables) if runnable? && runner
+ variables.concat(project.deployment_variables(environment: environment)) if environment
+ variables.concat(yaml_variables)
+ variables.concat(user_variables)
+ variables.concat(secret_group_variables)
+ variables.concat(secret_project_variables(environment: environment))
+ variables.concat(trigger_request.user_variables) if trigger_request
+ variables.concat(pipeline.variables)
+ variables.concat(pipeline.pipeline_schedule.job_variables) if pipeline.pipeline_schedule
+ end
+ end
+
+ ##
+ # Regular Ruby hash of scoped variables, without duplicates that are
+ # possible to be present in an array of hashes returned from `variables`.
+ #
+ def scoped_variables_hash
+ scoped_variables.to_hash
+ end
+
+ ##
+ # Variables that do not depend on the environment name.
+ #
+ def simple_variables
+ strong_memoize(:simple_variables) do
+ scoped_variables(environment: nil).to_runner_variables
+ end
+ end
+
+ def user_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ break variables if user.blank?
+
+ variables.append(key: 'GITLAB_USER_ID', value: user.id.to_s)
+ variables.append(key: 'GITLAB_USER_EMAIL', value: user.email)
+ variables.append(key: 'GITLAB_USER_LOGIN', value: user.username)
+ variables.append(key: 'GITLAB_USER_NAME', value: user.name)
+ end
+ end
+
+ def predefined_variables # rubocop:disable Metrics/AbcSize
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.append(key: 'CI', value: 'true')
+ variables.append(key: 'GITLAB_CI', value: 'true')
+ variables.append(key: 'GITLAB_FEATURES', value: project.licensed_features.join(','))
+ variables.append(key: 'CI_SERVER_NAME', value: 'GitLab')
+ variables.append(key: 'CI_SERVER_VERSION', value: Gitlab::VERSION)
+ variables.append(key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s)
+ variables.append(key: 'CI_SERVER_VERSION_MINOR', value: Gitlab.version_info.minor.to_s)
+ variables.append(key: 'CI_SERVER_VERSION_PATCH', value: Gitlab.version_info.patch.to_s)
+ variables.append(key: 'CI_SERVER_REVISION', value: Gitlab.revision)
+ variables.append(key: 'CI_JOB_NAME', value: name)
+ variables.append(key: 'CI_JOB_STAGE', value: stage)
+ variables.append(key: 'CI_COMMIT_SHA', value: sha)
+ variables.append(key: 'CI_COMMIT_SHORT_SHA', value: short_sha)
+ variables.append(key: 'CI_COMMIT_BEFORE_SHA', value: before_sha)
+ variables.append(key: 'CI_COMMIT_REF_NAME', value: ref)
+ variables.append(key: 'CI_COMMIT_REF_SLUG', value: ref_slug)
+ variables.append(key: "CI_COMMIT_TAG", value: ref) if tag?
+ variables.append(key: "CI_PIPELINE_TRIGGERED", value: 'true') if trigger_request
+ variables.append(key: "CI_JOB_MANUAL", value: 'true') if action?
+ variables.append(key: "CI_NODE_INDEX", value: self.options[:instance].to_s) if self.options&.include?(:instance)
+ variables.append(key: "CI_NODE_TOTAL", value: (self.options&.dig(:parallel) || 1).to_s)
+ variables.concat(legacy_variables)
+ end
+ end
+
+ def legacy_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.append(key: 'CI_BUILD_REF', value: sha)
+ variables.append(key: 'CI_BUILD_BEFORE_SHA', value: before_sha)
+ variables.append(key: 'CI_BUILD_REF_NAME', value: ref)
+ variables.append(key: 'CI_BUILD_REF_SLUG', value: ref_slug)
+ variables.append(key: 'CI_BUILD_NAME', value: name)
+ variables.append(key: 'CI_BUILD_STAGE', value: stage)
+ variables.append(key: "CI_BUILD_TAG", value: ref) if tag?
+ variables.append(key: "CI_BUILD_TRIGGERED", value: 'true') if trigger_request
+ variables.append(key: "CI_BUILD_MANUAL", value: 'true') if action?
+ end
+ end
+
+ def secret_group_variables
+ return [] unless project.group
+
+ project.group.ci_variables_for(git_ref, project)
+ end
+
+ def secret_project_variables(environment: persisted_environment)
+ project.ci_variables_for(ref: git_ref, environment: environment)
+ end
+ end
+end
diff --git a/app/models/concerns/ci/metadatable.rb b/app/models/concerns/ci/metadatable.rb
new file mode 100644
index 00000000000..9eed9492b37
--- /dev/null
+++ b/app/models/concerns/ci/metadatable.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+module Ci
+ ##
+ # This module implements methods that need to read and write
+ # metadata for CI/CD entities.
+ #
+ module Metadatable
+ extend ActiveSupport::Concern
+
+ included do
+ has_one :metadata, class_name: 'Ci::BuildMetadata',
+ foreign_key: :build_id,
+ inverse_of: :build,
+ autosave: true
+
+ delegate :timeout, to: :metadata, prefix: true, allow_nil: true
+ before_create :ensure_metadata
+ end
+
+ def ensure_metadata
+ metadata || build_metadata(project: project)
+ end
+
+ def degenerated?
+ self.options.blank?
+ end
+
+ def degenerate!
+ self.class.transaction do
+ self.update!(options: nil, yaml_variables: nil)
+ self.metadata&.destroy
+ end
+ end
+
+ def options
+ read_metadata_attribute(:options, :config_options, {})
+ end
+
+ def yaml_variables
+ read_metadata_attribute(:yaml_variables, :config_variables, [])
+ end
+
+ def options=(value)
+ write_metadata_attribute(:options, :config_options, value)
+ end
+
+ def yaml_variables=(value)
+ write_metadata_attribute(:yaml_variables, :config_variables, value)
+ end
+
+ private
+
+ def read_metadata_attribute(legacy_key, metadata_key, default_value = nil)
+ read_attribute(legacy_key) || metadata&.read_attribute(metadata_key) || default_value
+ end
+
+ def write_metadata_attribute(legacy_key, metadata_key, value)
+ # save to metadata or this model depending on the state of feature flag
+ if Feature.enabled?(:ci_build_metadata_config)
+ ensure_metadata.write_attribute(metadata_key, value)
+ write_attribute(legacy_key, nil)
+ else
+ write_attribute(legacy_key, value)
+ metadata&.write_attribute(metadata_key, nil)
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/ci/processable.rb b/app/models/concerns/ci/processable.rb
new file mode 100644
index 00000000000..268fa8ec692
--- /dev/null
+++ b/app/models/concerns/ci/processable.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Ci
+ ##
+ # This module implements methods that need to be implemented by CI/CD
+ # entities that are supposed to go through pipeline processing
+ # services.
+ #
+ #
+ module Processable
+ def schedulable?
+ raise NotImplementedError
+ end
+
+ def action?
+ raise NotImplementedError
+ end
+
+ def when
+ read_attribute(:when) || 'on_success'
+ end
+
+ def expanded_environment_name
+ raise NotImplementedError
+ end
+
+ def scoped_variables_hash
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/app/models/concerns/closed_at_filterable.rb b/app/models/concerns/closed_at_filterable.rb
new file mode 100644
index 00000000000..239c2e47611
--- /dev/null
+++ b/app/models/concerns/closed_at_filterable.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module ClosedAtFilterable
+ extend ActiveSupport::Concern
+
+ included do
+ scope :closed_before, ->(date) { where(scoped_table[:closed_at].lteq(date)) }
+ scope :closed_after, ->(date) { where(scoped_table[:closed_at].gteq(date)) }
+
+ def self.scoped_table
+ arel_table.alias(table_name)
+ end
+ end
+end
diff --git a/app/models/concerns/discussion_on_diff.rb b/app/models/concerns/discussion_on_diff.rb
index 86b61248534..e4e5928f5cf 100644
--- a/app/models/concerns/discussion_on_diff.rb
+++ b/app/models/concerns/discussion_on_diff.rb
@@ -9,7 +9,7 @@ module DiscussionOnDiff
included do
delegate :line_code,
:original_line_code,
- :diff_file,
+ :note_diff_file,
:diff_line,
:active?,
:created_at_diff?,
@@ -60,6 +60,13 @@ module DiscussionOnDiff
prev_lines
end
+ def diff_file
+ strong_memoize(:diff_file) do
+ # Falling back here is important as `note_diff_files` are created async.
+ fetch_preloaded_diff_file || first_note.diff_file
+ end
+ end
+
def line_code_in_diffs(diff_refs)
if active?(diff_refs)
line_code
@@ -67,4 +74,15 @@ module DiscussionOnDiff
original_line_code
end
end
+
+ private
+
+ def fetch_preloaded_diff_file
+ fetch_preloaded_diff =
+ context_noteable &&
+ context_noteable.preloads_discussion_diff_highlighting? &&
+ note_diff_file
+
+ context_noteable.discussions_diffs.find_by_id(note_diff_file.id) if fetch_preloaded_diff
+ end
end
diff --git a/app/models/concerns/fast_destroy_all.rb b/app/models/concerns/fast_destroy_all.rb
index 1e3afd641ed..f862031bce0 100644
--- a/app/models/concerns/fast_destroy_all.rb
+++ b/app/models/concerns/fast_destroy_all.rb
@@ -11,7 +11,7 @@
# it is difficult to accomplish it.
#
# This module defines a format to use `delete_all` and delete associated external data.
-# Here is an exmaple
+# Here is an example
#
# Situation
# - `Project` has many `Ci::BuildTraceChunk` through `Ci::Build`
diff --git a/app/models/concerns/feature_gate.rb b/app/models/concerns/feature_gate.rb
index 3f84de54ad5..bb095f113e2 100644
--- a/app/models/concerns/feature_gate.rb
+++ b/app/models/concerns/feature_gate.rb
@@ -2,7 +2,7 @@
module FeatureGate
def flipper_id
- return nil if new_record?
+ return if new_record?
"#{self.class.name}:#{id}"
end
diff --git a/app/models/concerns/has_ref.rb b/app/models/concerns/has_ref.rb
new file mode 100644
index 00000000000..413cd36dcaa
--- /dev/null
+++ b/app/models/concerns/has_ref.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module HasRef
+ extend ActiveSupport::Concern
+
+ def branch?
+ !tag? && !merge_request_event?
+ end
+
+ def git_ref
+ if branch?
+ Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
+ elsif tag?
+ Gitlab::Git::TAG_REF_PREFIX + ref.to_s
+ end
+ end
+
+ # A slugified version of the build ref, suitable for inclusion in URLs and
+ # domain names. Rules:
+ #
+ # * Lowercased
+ # * Anything not matching [a-z0-9-] is replaced with a -
+ # * Maximum length is 63 bytes
+ # * First/Last Character is not a hyphen
+ def ref_slug
+ Gitlab::Utils.slugify(ref.to_s)
+ end
+end
diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb
index b92643f87f8..0d2be4c61ab 100644
--- a/app/models/concerns/has_status.rb
+++ b/app/models/concerns/has_status.rb
@@ -85,11 +85,11 @@ module HasStatus
scope :running, -> { where(status: 'running') }
scope :pending, -> { where(status: 'pending') }
scope :success, -> { where(status: 'success') }
- scope :failed, -> { where(status: 'failed') }
- scope :canceled, -> { where(status: 'canceled') }
- scope :skipped, -> { where(status: 'skipped') }
- scope :manual, -> { where(status: 'manual') }
- scope :scheduled, -> { where(status: 'scheduled') }
+ scope :failed, -> { where(status: 'failed') }
+ scope :canceled, -> { where(status: 'canceled') }
+ scope :skipped, -> { where(status: 'skipped') }
+ scope :manual, -> { where(status: 'manual') }
+ scope :scheduled, -> { where(status: 'scheduled') }
scope :alive, -> { where(status: [:created, :pending, :running]) }
scope :created_or_pending, -> { where(status: [:created, :pending]) }
scope :running_or_pending, -> { where(status: [:running, :pending]) }
diff --git a/app/models/concerns/has_variable.rb b/app/models/concerns/has_variable.rb
index dfbe413a878..2ec42a1029b 100644
--- a/app/models/concerns/has_variable.rb
+++ b/app/models/concerns/has_variable.rb
@@ -21,9 +21,9 @@ module HasVariable
def key=(new_key)
super(new_key.to_s.strip)
end
+ end
- def to_runner_variable
- { key: key, value: value, public: false }
- end
+ def to_runner_variable
+ { key: key, value: value, public: false }
end
end
diff --git a/app/models/concerns/iid_routes.rb b/app/models/concerns/iid_routes.rb
index b7f99e845ca..3eeb29b6595 100644
--- a/app/models/concerns/iid_routes.rb
+++ b/app/models/concerns/iid_routes.rb
@@ -4,7 +4,7 @@ module IidRoutes
##
# This automagically enforces all related routes to use `iid` instead of `id`
# If you want to use `iid` for some routes and `id` for other routes, this module should not to be included,
- # instead you should define `iid` or `id` explictly at each route generators. e.g. pipeline_path(project.id, pipeline.iid)
+ # instead you should define `iid` or `id` explicitly at each route generators. e.g. pipeline_path(project.id, pipeline.iid)
def to_param
iid.to_s
end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 0d363ec68b7..c7ad182ab82 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -23,11 +23,12 @@ module Issuable
include Sortable
include CreatedAtFilterable
include UpdatedAtFilterable
+ include ClosedAtFilterable
# This object is used to gather issuable meta data for displaying
# upvotes, downvotes, notes and closing merge requests count for issues and merge requests
# lists avoiding n+1 queries and improving performance.
- IssuableMeta = Struct.new(:upvotes, :downvotes, :notes_count, :merge_requests_count)
+ IssuableMeta = Struct.new(:upvotes, :downvotes, :user_notes_count, :merge_requests_count)
included do
cache_markdown_field :title, pipeline: :single_line
@@ -35,8 +36,8 @@ module Issuable
redact_field :description
- belongs_to :author, class_name: "User"
- belongs_to :updated_by, class_name: "User"
+ belongs_to :author, class_name: 'User'
+ belongs_to :updated_by, class_name: 'User'
belongs_to :last_edited_by, class_name: 'User'
belongs_to :milestone
@@ -74,6 +75,7 @@ module Issuable
validates :author, presence: true
validates :title, presence: true, length: { maximum: 255 }
+ validate :milestone_is_valid
scope :authored, ->(user) { where(author_id: user) }
scope :recent, -> { reorder(id: :desc) }
@@ -117,6 +119,16 @@ module Issuable
def has_multiple_assignees?
assignees.count > 1
end
+
+ def milestone_available?
+ project_id == milestone&.project_id || project.ancestors_upto.compact.include?(milestone&.group)
+ end
+
+ private
+
+ def milestone_is_valid
+ errors.add(:milestone_id, message: "is invalid") if milestone_id.present? && !milestone_available?
+ end
end
class_methods do
@@ -136,10 +148,18 @@ module Issuable
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
#
# query - The search query as a String
+ # matched_columns - Modify the scope of the query. 'title', 'description' or joining them with a comma.
#
# Returns an ActiveRecord::Relation.
- def full_search(query)
- fuzzy_search(query, [:title, :description])
+ def full_search(query, matched_columns: 'title,description')
+ allowed_columns = [:title, :description]
+ matched_columns = matched_columns.to_s.split(',').map(&:to_sym)
+ matched_columns &= allowed_columns
+
+ # Matching title or description if the matched_columns did not contain any allowed columns.
+ matched_columns = [:title, :description] if matched_columns.empty?
+
+ fuzzy_search(query, matched_columns)
end
def sort_by_attribute(method, excluded_labels: [])
@@ -270,26 +290,29 @@ module Issuable
def to_hook_data(user, old_associations: {})
changes = previous_changes
- old_labels = old_associations.fetch(:labels, [])
- old_assignees = old_associations.fetch(:assignees, [])
- if old_labels != labels
- changes[:labels] = [old_labels.map(&:hook_attrs), labels.map(&:hook_attrs)]
- end
+ if old_associations
+ old_labels = old_associations.fetch(:labels, [])
+ old_assignees = old_associations.fetch(:assignees, [])
- if old_assignees != assignees
- if self.is_a?(Issue)
- changes[:assignees] = [old_assignees.map(&:hook_attrs), assignees.map(&:hook_attrs)]
- else
- changes[:assignee] = [old_assignees&.first&.hook_attrs, assignee&.hook_attrs]
+ if old_labels != labels
+ changes[:labels] = [old_labels.map(&:hook_attrs), labels.map(&:hook_attrs)]
end
- end
- if self.respond_to?(:total_time_spent)
- old_total_time_spent = old_associations.fetch(:total_time_spent, nil)
+ if old_assignees != assignees
+ if self.is_a?(Issue)
+ changes[:assignees] = [old_assignees.map(&:hook_attrs), assignees.map(&:hook_attrs)]
+ else
+ changes[:assignee] = [old_assignees&.first&.hook_attrs, assignee&.hook_attrs]
+ end
+ end
+
+ if self.respond_to?(:total_time_spent)
+ old_total_time_spent = old_associations.fetch(:total_time_spent, nil)
- if old_total_time_spent != total_time_spent
- changes[:total_time_spent] = [old_total_time_spent, total_time_spent]
+ if old_total_time_spent != total_time_spent
+ changes[:total_time_spent] = [old_total_time_spent, total_time_spent]
+ end
end
end
diff --git a/app/models/concerns/manual_inverse_association.rb b/app/models/concerns/manual_inverse_association.rb
index e18edd33ba7..ff61412767e 100644
--- a/app/models/concerns/manual_inverse_association.rb
+++ b/app/models/concerns/manual_inverse_association.rb
@@ -5,8 +5,8 @@ module ManualInverseAssociation
class_methods do
def manual_inverse_association(association, inverse)
- define_method(association) do |*args|
- super(*args).tap do |value|
+ define_method(association) do
+ super().tap do |value|
next unless value
child_association = value.association(inverse)
diff --git a/app/models/concerns/maskable.rb b/app/models/concerns/maskable.rb
new file mode 100644
index 00000000000..8793f0ec965
--- /dev/null
+++ b/app/models/concerns/maskable.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Maskable
+ extend ActiveSupport::Concern
+
+ # * Single line
+ # * No escape characters
+ # * No variables
+ # * No spaces
+ # * Minimal length of 8 characters
+ # * Absolutely no fun is allowed
+ REGEX = /\A\w{8,}\z/
+
+ included do
+ validates :masked, inclusion: { in: [true, false] }
+ validates :value, format: { with: REGEX }, if: :masked?
+ end
+
+ def to_runner_variable
+ super.merge(masked: masked?)
+ end
+end
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index e44a069b730..e65bbb8ca07 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -42,16 +42,35 @@ module Milestoneish
def issues_visible_to_user(user)
memoize_per_user(user, :issues_visible_to_user) do
IssuesFinder.new(user, issues_finder_params)
- .execute.preload(:assignees).where(milestone_id: milestoneish_ids)
+ .execute.preload(:assignees).where(milestone_id: milestoneish_id)
end
end
+ def issue_participants_visible_by_user(user)
+ User.joins(:issue_assignees)
+ .where('issue_assignees.issue_id' => issues_visible_to_user(user).select(:id))
+ .distinct
+ end
+
+ def issue_labels_visible_by_user(user)
+ Label.joins(:label_links)
+ .where('label_links.target_id' => issues_visible_to_user(user).select(:id), 'label_links.target_type' => 'Issue')
+ .distinct
+ end
+
def sorted_issues(user)
issues_visible_to_user(user).preload_associations.sort_by_attribute('label_priority')
end
- def sorted_merge_requests
- merge_requests.sort_by_attribute('label_priority')
+ def sorted_merge_requests(user)
+ merge_requests_visible_to_user(user).sort_by_attribute('label_priority')
+ end
+
+ def merge_requests_visible_to_user(user)
+ memoize_per_user(user, :merge_requests_visible_to_user) do
+ MergeRequestsFinder.new(user, issues_finder_params)
+ .execute.where(milestone_id: milestoneish_id)
+ end
end
def upcoming?
diff --git a/app/models/concerns/mirror_authentication.rb b/app/models/concerns/mirror_authentication.rb
index e3e1a0441f8..948094221e5 100644
--- a/app/models/concerns/mirror_authentication.rb
+++ b/app/models/concerns/mirror_authentication.rb
@@ -79,7 +79,7 @@ module MirrorAuthentication
end
def ssh_public_key
- return nil if ssh_private_key.blank?
+ return if ssh_private_key.blank?
comment = "git@#{::Gitlab.config.gitlab.host}"
::SSHKey.new(ssh_private_key, comment: comment).ssh_public_key
diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb
index f2cad09e779..3c74034b527 100644
--- a/app/models/concerns/noteable.rb
+++ b/app/models/concerns/noteable.rb
@@ -1,9 +1,18 @@
# frozen_string_literal: true
module Noteable
- # Names of all implementers of `Noteable` that support resolvable notes.
+ extend ActiveSupport::Concern
+
+ # `Noteable` class names that support resolvable notes.
RESOLVABLE_TYPES = %w(MergeRequest).freeze
+ class_methods do
+ # `Noteable` class names that support replying to individual notes.
+ def replyable_types
+ %w(Issue MergeRequest)
+ end
+ end
+
def base_class_name
self.class.base_class.name
end
@@ -26,6 +35,10 @@ module Noteable
DiscussionNote.noteable_types.include?(base_class_name)
end
+ def supports_replying_to_individual_notes?
+ supports_discussions? && self.class.replyable_types.include?(base_class_name)
+ end
+
def supports_suggestion?
false
end
@@ -34,6 +47,10 @@ module Noteable
false
end
+ def preloads_discussion_diff_highlighting?
+ false
+ end
+
def discussion_notes
notes
end
diff --git a/app/models/concerns/reactive_caching.rb b/app/models/concerns/reactive_caching.rb
index d3572875fb3..d2ead7130e5 100644
--- a/app/models/concerns/reactive_caching.rb
+++ b/app/models/concerns/reactive_caching.rb
@@ -69,14 +69,14 @@ module ReactiveCaching
def with_reactive_cache(*args, &blk)
unless within_reactive_cache_lifetime?(*args)
refresh_reactive_cache!(*args)
- return nil
+ return
end
keep_alive_reactive_cache!(*args)
begin
data = Rails.cache.read(full_reactive_cache_key(*args))
- yield data if data.present?
+ yield data unless data.nil?
rescue InvalidateReactiveCache
refresh_reactive_cache!(*args)
nil
diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb
index e51b4e22c96..a479bef993c 100644
--- a/app/models/concerns/sha_attribute.rb
+++ b/app/models/concerns/sha_attribute.rb
@@ -16,6 +16,8 @@ module ShaAttribute
# the column is the correct type. In production it should behave like any other attribute.
# See https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5502 for more discussion
def validate_binary_column_exists!(name)
+ return unless database_exists?
+
unless table_exists?
warn "WARNING: sha_attribute #{name.inspect} is invalid since the table doesn't exist - you may need to run database migrations"
return
@@ -35,5 +37,13 @@ module ShaAttribute
Gitlab::AppLogger.error "ShaAttribute initialization: #{error.message}"
raise
end
+
+ def database_exists?
+ ActiveRecord::Base.connection
+
+ true
+ rescue
+ false
+ end
end
end
diff --git a/app/models/concerns/taskable.rb b/app/models/concerns/taskable.rb
index 603d4d62578..f147ce8ad6b 100644
--- a/app/models/concerns/taskable.rb
+++ b/app/models/concerns/taskable.rb
@@ -9,9 +9,11 @@ require 'task_list/filter'
#
# Used by MergeRequest and Issue
module Taskable
- COMPLETED = 'completed'.freeze
- INCOMPLETE = 'incomplete'.freeze
- ITEM_PATTERN = %r{
+ COMPLETED = 'completed'.freeze
+ INCOMPLETE = 'incomplete'.freeze
+ COMPLETE_PATTERN = /(\[[xX]\])/.freeze
+ INCOMPLETE_PATTERN = /(\[[\s]\])/.freeze
+ ITEM_PATTERN = %r{
^
\s*(?:[-+*]|(?:\d+\.)) # list prefix required - task item has to be always in a list
\s+ # whitespace prefix has to be always presented for a list item
diff --git a/app/models/concerns/token_authenticatable_strategies/base.rb b/app/models/concerns/token_authenticatable_strategies/base.rb
index 01fb194281a..df14e6e4754 100644
--- a/app/models/concerns/token_authenticatable_strategies/base.rb
+++ b/app/models/concerns/token_authenticatable_strategies/base.rb
@@ -39,22 +39,6 @@ module TokenAuthenticatableStrategies
instance.save! if Gitlab::Database.read_write?
end
- def fallback?
- unless options[:fallback].in?([true, false, nil])
- raise ArgumentError, 'fallback: needs to be a boolean value!'
- end
-
- options[:fallback] == true
- end
-
- def migrating?
- unless options[:migrating].in?([true, false, nil])
- raise ArgumentError, 'migrating: needs to be a boolean value!'
- end
-
- options[:migrating] == true
- end
-
def self.fabricate(model, field, options)
if options[:digest] && options[:encrypted]
raise ArgumentError, 'Incompatible options set!'
diff --git a/app/models/concerns/token_authenticatable_strategies/encrypted.rb b/app/models/concerns/token_authenticatable_strategies/encrypted.rb
index 152491aa6e9..2c7fa2c5b3c 100644
--- a/app/models/concerns/token_authenticatable_strategies/encrypted.rb
+++ b/app/models/concerns/token_authenticatable_strategies/encrypted.rb
@@ -2,28 +2,18 @@
module TokenAuthenticatableStrategies
class Encrypted < Base
- def initialize(*)
- super
-
- if migrating? && fallback?
- raise ArgumentError, '`fallback` and `migrating` options are not compatible!'
- end
- end
-
def find_token_authenticatable(token, unscoped = false)
return if token.blank?
- if fully_encrypted?
- return find_by_encrypted_token(token, unscoped)
- end
-
- if fallback?
+ if required?
+ find_by_encrypted_token(token, unscoped)
+ elsif optional?
find_by_encrypted_token(token, unscoped) ||
find_by_plaintext_token(token, unscoped)
elsif migrating?
find_by_plaintext_token(token, unscoped)
else
- raise ArgumentError, 'Unknown encryption phase!'
+ raise ArgumentError, "Unknown encryption strategy: #{encrypted_strategy}!"
end
end
@@ -41,8 +31,8 @@ module TokenAuthenticatableStrategies
return super if instance.has_attribute?(encrypted_field)
- if fully_encrypted?
- raise ArgumentError, 'Using encrypted strategy when encrypted field is missing!'
+ if required?
+ raise ArgumentError, 'Using required encryption strategy when encrypted field is missing!'
else
insecure_strategy.ensure_token(instance)
end
@@ -53,8 +43,7 @@ module TokenAuthenticatableStrategies
encrypted_token = instance.read_attribute(encrypted_field)
token = Gitlab::CryptoHelper.aes256_gcm_decrypt(encrypted_token)
-
- token || (insecure_strategy.get_token(instance) if fallback?)
+ token || (insecure_strategy.get_token(instance) if optional?)
end
def set_token(instance, token)
@@ -62,16 +51,35 @@ module TokenAuthenticatableStrategies
instance[encrypted_field] = Gitlab::CryptoHelper.aes256_gcm_encrypt(token)
instance[token_field] = token if migrating?
- instance[token_field] = nil if fallback?
+ instance[token_field] = nil if optional?
token
end
- def fully_encrypted?
- !migrating? && !fallback?
+ def required?
+ encrypted_strategy == :required
+ end
+
+ def migrating?
+ encrypted_strategy == :migrating
+ end
+
+ def optional?
+ encrypted_strategy == :optional
end
protected
+ def encrypted_strategy
+ value = options[:encrypted]
+ value = value.call if value.is_a?(Proc)
+
+ unless value.in?([:required, :optional, :migrating])
+ raise ArgumentError, 'encrypted: needs to be a :required, :optional or :migrating!'
+ end
+
+ value
+ end
+
def find_by_plaintext_token(token, unscoped)
insecure_strategy.find_token_authenticatable(token, unscoped)
end
@@ -89,7 +97,7 @@ module TokenAuthenticatableStrategies
def token_set?(instance)
raw_token = instance.read_attribute(encrypted_field)
- unless fully_encrypted?
+ unless required?
raw_token ||= insecure_strategy.get_token(instance)
end
diff --git a/app/models/concerns/with_uploads.rb b/app/models/concerns/with_uploads.rb
index d79c0eae77e..6c6febd186c 100644
--- a/app/models/concerns/with_uploads.rb
+++ b/app/models/concerns/with_uploads.rb
@@ -27,40 +27,14 @@ module WithUploads
included do
has_many :uploads, as: :model
- has_many :file_uploads, -> { where(uploader: FILE_UPLOADERS) }, class_name: 'Upload', as: :model
+ has_many :file_uploads, -> { where(uploader: FILE_UPLOADERS) },
+ class_name: 'Upload', as: :model,
+ dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
- # TODO: when feature flag is removed, we can use just dependent: destroy
- # option on :file_uploads
- before_destroy :remove_file_uploads
-
- use_fast_destroy :file_uploads, if: :fast_destroy_enabled?
+ use_fast_destroy :file_uploads
end
def retrieve_upload(_identifier, paths)
uploads.find_by(path: paths)
end
-
- private
-
- # mounted uploads are deleted in carrierwave's after_commit hook,
- # but FileUploaders which are not mounted must be deleted explicitly and
- # it can not be done in after_commit because FileUploader requires loads
- # associated model on destroy (which is already deleted in after_commit)
- def remove_file_uploads
- fast_destroy_enabled? ? delete_uploads : destroy_uploads
- end
-
- def delete_uploads
- file_uploads.delete_all(:delete_all)
- end
-
- def destroy_uploads
- file_uploads.find_each do |upload|
- upload.destroy
- end
- end
-
- def fast_destroy_enabled?
- Feature.enabled?(:fast_destroy_uploads, self)
- end
end
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index 2c08a8e1acf..cf057d774cf 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class ContainerRepository < ActiveRecord::Base
+ include Gitlab::Utils::StrongMemoize
+
belongs_to :project
validates :name, length: { minimum: 0, allow_nil: false }
@@ -8,6 +10,8 @@ class ContainerRepository < ActiveRecord::Base
delegate :client, to: :registry
+ scope :ordered, -> { order(:name) }
+
# rubocop: disable CodeReuse/ServiceClass
def registry
@registry ||= begin
@@ -39,11 +43,12 @@ class ContainerRepository < ActiveRecord::Base
end
def tags
- return @tags if defined?(@tags)
return [] unless manifest && manifest['tags']
- @tags = manifest['tags'].map do |tag|
- ContainerRegistry::Tag.new(self, tag)
+ strong_memoize(:tags) do
+ manifest['tags'].sort.map do |tag|
+ ContainerRegistry::Tag.new(self, tag)
+ end
end
end
diff --git a/app/models/dashboard_group_milestone.rb b/app/models/dashboard_group_milestone.rb
index ad0bb55f0a7..74aa04ab7d0 100644
--- a/app/models/dashboard_group_milestone.rb
+++ b/app/models/dashboard_group_milestone.rb
@@ -6,34 +6,17 @@ class DashboardGroupMilestone < GlobalMilestone
attr_reader :group_name
def initialize(milestone)
- super(milestone.title, Array(milestone))
+ super
@group_name = milestone.group.full_name
end
- def self.build_collection(groups)
- Milestone.of_groups(groups.select(:id))
+ def self.build_collection(groups, params)
+ milestones = Milestone.of_groups(groups.select(:id))
.reorder_by_due_date_asc
.order_by_name_asc
.active
- .map { |m| new(m) }
- end
-
- override :group_milestone?
- def group_milestone?
- @first_milestone.group_milestone?
- end
-
- override :milestoneish_ids
- def milestoneish_ids
- milestones.map(&:id)
- end
-
- def group
- @first_milestone.group
- end
-
- def iid
- @first_milestone.iid
+ milestones = milestones.search_title(params[:search_title]) if params[:search_title].present?
+ milestones.map { |m| new(m) }
end
end
diff --git a/app/models/dashboard_milestone.rb b/app/models/dashboard_milestone.rb
index 96bc8090b81..9b377b70e5b 100644
--- a/app/models/dashboard_milestone.rb
+++ b/app/models/dashboard_milestone.rb
@@ -1,11 +1,15 @@
# frozen_string_literal: true
class DashboardMilestone < GlobalMilestone
- def issues_finder_params
- { authorized_only: true }
+ attr_reader :project_name
+
+ def initialize(milestone)
+ super
+
+ @project_name = milestone.project.full_name
end
- def dashboard_milestone?
+ def project_milestone?
true
end
end
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
index 279603496b0..805092e527a 100644
--- a/app/models/diff_note.rb
+++ b/app/models/diff_note.rb
@@ -41,6 +41,14 @@ class DiffNote < Note
create_note_diff_file(creation_params)
end
+ # Returns the diff file from `position`
+ def latest_diff_file
+ strong_memoize(:latest_diff_file) do
+ position.diff_file(project.repository)
+ end
+ end
+
+ # Returns the diff file from `original_position`
def diff_file
strong_memoize(:diff_file) do
enqueue_diff_file_creation_job if should_create_diff_file?
diff --git a/app/models/diff_viewer/base.rb b/app/models/diff_viewer/base.rb
index 1176861a827..527ee33b83b 100644
--- a/app/models/diff_viewer/base.rb
+++ b/app/models/diff_viewer/base.rb
@@ -18,7 +18,7 @@ module DiffViewer
def initialize(diff_file)
@diff_file = diff_file
- @initially_binary = diff_file.binary?
+ @initially_binary = diff_file.binary_in_repo?
end
def self.partial_path
@@ -48,7 +48,7 @@ module DiffViewer
def self.can_render_blob?(blob, verify_binary: true)
return true if blob.nil?
- return false if verify_binary && binary? != blob.binary?
+ return false if verify_binary && binary? != blob.binary_in_repo?
return true if extensions&.include?(blob.extension)
return true if file_types&.include?(blob.file_type)
@@ -70,20 +70,49 @@ module DiffViewer
end
def binary_detected_after_load?
- !@initially_binary && diff_file.binary?
+ !@initially_binary && diff_file.binary_in_repo?
end
# This method is used on the server side to check whether we can attempt to
- # render the diff_file at all. Human-readable error messages are found in the
- # `BlobHelper#diff_render_error_reason` helper.
+ # render the diff_file at all. The human-readable error message can be
+ # retrieved by #render_error_message.
def render_error
if too_large?
:too_large
end
end
+ def render_error_message
+ return unless render_error
+
+ _("This %{viewer} could not be displayed because %{reason}. You can %{options} instead.") %
+ {
+ viewer: switcher_title,
+ reason: render_error_reason,
+ options: render_error_options.to_sentence(two_words_connector: _(' or '), last_word_connector: _(', or '))
+ }
+ end
+
def prepare!
# To be overridden by subclasses
end
+
+ private
+
+ def render_error_options
+ options = []
+
+ blob_url = Gitlab::Routing.url_helpers.project_blob_path(diff_file.repository.project,
+ File.join(diff_file.content_sha, diff_file.file_path))
+ options << ActionController::Base.helpers.link_to(_('view the blob'), blob_url)
+
+ options
+ end
+
+ def render_error_reason
+ if render_error == :too_large
+ _("it is too large")
+ end
+ end
end
end
diff --git a/app/models/diff_viewer/image.rb b/app/models/diff_viewer/image.rb
index c356c2ca50e..350bef1d42a 100644
--- a/app/models/diff_viewer/image.rb
+++ b/app/models/diff_viewer/image.rb
@@ -9,6 +9,6 @@ module DiffViewer
self.extensions = UploaderHelper::IMAGE_EXT
self.binary = true
self.switcher_icon = 'picture-o'
- self.switcher_title = 'image diff'
+ self.switcher_title = _('image diff')
end
end
diff --git a/app/models/diff_viewer/rich.rb b/app/models/diff_viewer/rich.rb
index 2faa1be6567..5caefa2031c 100644
--- a/app/models/diff_viewer/rich.rb
+++ b/app/models/diff_viewer/rich.rb
@@ -7,7 +7,7 @@ module DiffViewer
included do
self.type = :rich
self.switcher_icon = 'file-text-o'
- self.switcher_title = 'rendered diff'
+ self.switcher_title = _('rendered diff')
end
end
end
diff --git a/app/models/diff_viewer/server_side.rb b/app/models/diff_viewer/server_side.rb
index 977204e6c97..0877c9dddec 100644
--- a/app/models/diff_viewer/server_side.rb
+++ b/app/models/diff_viewer/server_side.rb
@@ -24,5 +24,17 @@ module DiffViewer
super
end
+
+ private
+
+ def render_error_reason
+ return super unless render_error == :server_side_but_stored_externally
+
+ if diff_file.external_storage == :lfs
+ _('it is stored in LFS')
+ else
+ _('it is stored externally')
+ end
+ end
end
end
diff --git a/app/models/diff_viewer/simple.rb b/app/models/diff_viewer/simple.rb
index 8d28ca5239a..929d8ad5a7e 100644
--- a/app/models/diff_viewer/simple.rb
+++ b/app/models/diff_viewer/simple.rb
@@ -7,7 +7,7 @@ module DiffViewer
included do
self.type = :simple
self.switcher_icon = 'code'
- self.switcher_title = 'source diff'
+ self.switcher_title = _('source diff')
end
end
end
diff --git a/app/models/discussion.rb b/app/models/discussion.rb
index dbc7b6e67be..32529ebf71d 100644
--- a/app/models/discussion.rb
+++ b/app/models/discussion.rb
@@ -116,6 +116,10 @@ class Discussion
false
end
+ def can_convert_to_discussion?
+ false
+ end
+
def new_discussion?
notes.length == 1
end
diff --git a/app/models/email.rb b/app/models/email.rb
index b6a977dfa22..3ce6e792fa8 100644
--- a/app/models/email.rb
+++ b/app/models/email.rb
@@ -15,7 +15,7 @@ class Email < ActiveRecord::Base
after_commit :update_invalid_gpg_signatures, if: -> { previous_changes.key?('confirmed_at') }
devise :confirmable
- self.reconfirmable = false # currently email can't be changed, no need to reconfirm
+ self.reconfirmable = false # currently email can't be changed, no need to reconfirm
delegate :username, to: :user
diff --git a/app/models/environment.rb b/app/models/environment.rb
index cdfe3b7c023..3d909cc8e5c 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -50,6 +50,14 @@ class Environment < ActiveRecord::Base
end
scope :in_review_folder, -> { where(environment_type: "review") }
scope :for_name, -> (name) { where(name: name) }
+
+ ##
+ # Search environments which have names like the given query.
+ # Do not set a large limit unless you've confirmed that it works on gitlab.com scale.
+ scope :for_name_like, -> (query, limit: 5) do
+ where('name LIKE ?', "#{sanitize_sql_like(query)}%").limit(limit)
+ end
+
scope :for_project, -> (project) { where(project_id: project) }
scope :with_deployment, -> (sha) { where('EXISTS (?)', Deployment.select(1).where('deployments.environment_id = environments.id').where(sha: sha)) }
@@ -70,6 +78,10 @@ class Environment < ActiveRecord::Base
end
end
+ def self.pluck_names
+ pluck(:name)
+ end
+
def predefined_variables
Gitlab::Ci::Variables::Collection.new
.append(key: 'CI_ENVIRONMENT_NAME', value: name)
@@ -107,7 +119,7 @@ class Environment < ActiveRecord::Base
def first_deployment_for(commit_sha)
ref = project.repository.ref_name_for_sha(ref_path, commit_sha)
- return nil unless ref
+ return unless ref
deployment_iid = ref.split('/').last
deployments.find_by(iid: deployment_iid)
@@ -118,7 +130,7 @@ class Environment < ActiveRecord::Base
end
def formatted_external_url
- return nil unless external_url
+ return unless external_url
external_url.gsub(%r{\A.*?://}, '')
end
@@ -231,6 +243,10 @@ class Environment < ActiveRecord::Base
self.environment_type || self.name
end
+ def name_without_type
+ @name_without_type ||= name.delete_prefix("#{environment_type}/")
+ end
+
def deployment_platform
strong_memoize(:deployment_platform) do
project.deployment_platform(environment: self.name)
diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb
new file mode 100644
index 00000000000..1e2bd3bda7f
--- /dev/null
+++ b/app/models/error_tracking/project_error_tracking_setting.rb
@@ -0,0 +1,157 @@
+# frozen_string_literal: true
+
+module ErrorTracking
+ class ProjectErrorTrackingSetting < ActiveRecord::Base
+ include Gitlab::Utils::StrongMemoize
+ include ReactiveCaching
+
+ API_URL_PATH_REGEXP = %r{
+ \A
+ (?<prefix>/api/0/projects/+)
+ (?:
+ (?<organization>[^/]+)/+
+ (?<project>[^/]+)/*
+ )?
+ \z
+ }x
+
+ self.reactive_cache_key = ->(setting) { [setting.class.model_name.singular, setting.project_id] }
+
+ belongs_to :project
+
+ validates :api_url, length: { maximum: 255 }, public_url: true, url: { enforce_sanitization: true, ascii_only: true }, allow_nil: true
+
+ validates :api_url, presence: { message: 'is a required field' }, if: :enabled
+
+ validate :validate_api_url_path, if: :enabled
+
+ validates :token, presence: { message: 'is a required field' }, if: :enabled
+
+ attr_encrypted :token,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-gcm'
+
+ after_save :clear_reactive_cache!
+
+ def api_url=(value)
+ super
+ clear_memoization(:api_url_slugs)
+ end
+
+ def project_name
+ super || project_name_from_slug
+ end
+
+ def organization_name
+ super || organization_name_from_slug
+ end
+
+ def project_slug
+ project_slug_from_api_url
+ end
+
+ def organization_slug
+ organization_slug_from_api_url
+ end
+
+ def self.build_api_url_from(api_host:, project_slug:, organization_slug:)
+ return if api_host.blank?
+
+ uri = Addressable::URI.parse("#{api_host}/api/0/projects/#{organization_slug}/#{project_slug}/")
+ uri.path = uri.path.squeeze('/')
+
+ uri.to_s
+ rescue Addressable::URI::InvalidURIError
+ api_host
+ end
+
+ def sentry_client
+ Sentry::Client.new(api_url, token)
+ end
+
+ def sentry_external_url
+ self.class.extract_sentry_external_url(api_url)
+ end
+
+ def list_sentry_issues(opts = {})
+ with_reactive_cache('list_issues', opts.stringify_keys) do |result|
+ result
+ end
+ end
+
+ def list_sentry_projects
+ { projects: sentry_client.list_projects }
+ end
+
+ def calculate_reactive_cache(request, opts)
+ case request
+ when 'list_issues'
+ { issues: sentry_client.list_issues(**opts.symbolize_keys) }
+ end
+ rescue Sentry::Client::Error => e
+ { error: e.message }
+ end
+
+ # http://HOST/api/0/projects/ORG/PROJECT
+ # ->
+ # http://HOST/ORG/PROJECT
+ def self.extract_sentry_external_url(url)
+ url.sub('api/0/projects/', '')
+ end
+
+ def api_host
+ return if api_url.blank?
+
+ # This returns http://example.com/
+ Addressable::URI.join(api_url, '/').to_s
+ end
+
+ private
+
+ def project_name_from_slug
+ @project_name_from_slug ||= project_slug_from_api_url&.titleize
+ end
+
+ def organization_name_from_slug
+ @organization_name_from_slug ||= organization_slug_from_api_url&.titleize
+ end
+
+ def project_slug_from_api_url
+ api_url_slug(:project)
+ end
+
+ def organization_slug_from_api_url
+ api_url_slug(:organization)
+ end
+
+ def api_url_slug(capture)
+ slugs = strong_memoize(:api_url_slugs) { extract_api_url_slugs || {} }
+ slugs[capture]
+ end
+
+ def extract_api_url_slugs
+ return if api_url.blank?
+
+ begin
+ url = Addressable::URI.parse(api_url)
+ rescue Addressable::URI::InvalidURIError
+ return
+ end
+
+ url.path.match(API_URL_PATH_REGEXP)
+ end
+
+ def validate_api_url_path
+ return if api_url.blank?
+
+ unless api_url_slug(:prefix)
+ return errors.add(:api_url, 'is invalid')
+ end
+
+ unless api_url_slug(:organization)
+ errors.add(:project, 'is a required field')
+ end
+ end
+ end
+end
diff --git a/app/models/external_issue.rb b/app/models/external_issue.rb
index 4f73beaafc5..68b2353556e 100644
--- a/app/models/external_issue.rb
+++ b/app/models/external_issue.rb
@@ -3,6 +3,8 @@
class ExternalIssue
include Referable
+ attr_reader :project
+
def initialize(issue_identifier, project)
@issue_identifier, @project = issue_identifier, project
end
@@ -32,12 +34,8 @@ class ExternalIssue
[self.class, to_s].hash
end
- def project
- @project
- end
-
def project_id
- @project.id
+ project.id
end
def to_reference(_from = nil, full: nil)
diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb
index 085ffd16c6a..fd17745b035 100644
--- a/app/models/global_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -3,69 +3,79 @@
class GlobalMilestone
include Milestoneish
- EPOCH = DateTime.parse('1970-01-01')
STATE_COUNT_HASH = { opened: 0, closed: 0, all: 0 }.freeze
- attr_accessor :title, :milestones
+ attr_reader :milestone
alias_attribute :name, :title
+ delegate :title, :state, :due_date, :start_date, :participants, :project, :group, :expires_at, :closed?, :iid, :group_milestone?, :safe_title, :milestoneish_id, to: :milestone
+
+ def to_hash
+ {
+ name: title,
+ title: title,
+ group_name: group&.full_name,
+ project_name: project&.full_name
+ }
+ end
+
def for_display
- @first_milestone
+ @milestone
end
def self.build_collection(projects, params)
- params =
- { project_ids: projects.map(&:id), state: params[:state] }
-
- child_milestones = MilestonesFinder.new(params).execute # rubocop: disable CodeReuse/Finder
-
- milestones = child_milestones.select(:id, :title).group_by(&:title).map do |title, grouped|
- milestones_relation = Milestone.where(id: grouped.map(&:id))
- new(title, milestones_relation)
- end
+ items = Milestone.of_projects(projects)
+ .reorder_by_due_date_asc
+ .order_by_name_asc
+ items = items.search_title(params[:search_title]) if params[:search_title].present?
- milestones.sort_by { |milestone| milestone.due_date || EPOCH }
+ Milestone.filter_by_state(items, params[:state]).map { |m| new(m) }
end
+ # necessary for legacy milestones
def self.build(projects, title)
- child_milestones = Milestone.of_projects(projects).where(title: title)
- return if child_milestones.blank?
+ milestones = Milestone.of_projects(projects).where(title: title)
+ return if milestones.blank?
- new(title, child_milestones)
+ new(milestones.first)
end
- def self.count_by_state(milestones_by_state_and_title, state)
- milestones_by_state_and_title.count do |(milestone_state, _), _|
- milestone_state == state
+ def self.states_count(projects, group = nil)
+ legacy_group_milestones_count = legacy_group_milestone_states_count(projects)
+ group_milestones_count = group_milestones_states_count(group)
+
+ legacy_group_milestones_count.merge(group_milestones_count) do |k, legacy_group_milestones_count, group_milestones_count|
+ legacy_group_milestones_count + group_milestones_count
end
end
- private_class_method :count_by_state
- def initialize(title, milestones)
- @title = title
- @name = title
- @milestones = milestones
- @first_milestone = milestones.find {|m| m.description.present? } || milestones.first
- end
+ def self.group_milestones_states_count(group)
+ return STATE_COUNT_HASH unless group
- def milestoneish_ids
- milestones.select(:id)
- end
+ counts_by_state = Milestone.of_groups(group).count_by_state
- def safe_title
- @title.to_slug.normalize.to_s
+ {
+ opened: counts_by_state['active'] || 0,
+ closed: counts_by_state['closed'] || 0,
+ all: counts_by_state.values.sum
+ }
end
- def projects
- @projects ||= Project.for_milestones(milestoneish_ids)
- end
+ def self.legacy_group_milestone_states_count(projects)
+ return STATE_COUNT_HASH unless projects
- def state
- milestones.each do |milestone|
- return 'active' if milestone.state != 'closed'
- end
+ # We need to reorder(nil) on the projects, because the controller passes them in sorted.
+ relation = Milestone.of_projects(projects.reorder(nil)).count_by_state
- 'closed'
+ {
+ opened: relation['active'] || 0,
+ closed: relation['closed'] || 0,
+ all: relation.values.sum
+ }
+ end
+
+ def initialize(milestone)
+ @milestone = milestone
end
def active?
@@ -77,37 +87,14 @@ class GlobalMilestone
end
def issues
- @issues ||= Issue.of_milestones(milestoneish_ids).includes(:project, :assignees, :labels)
+ @issues ||= Issue.of_milestones(milestone).includes(:project, :assignees, :labels)
end
def merge_requests
- @merge_requests ||= MergeRequest.of_milestones(milestoneish_ids).includes(:target_project, :assignee, :labels)
- end
-
- def participants
- @participants ||= milestones.map(&:participants).flatten.uniq
+ @merge_requests ||= MergeRequest.of_milestones(milestone).includes(:target_project, :assignee, :labels)
end
def labels
- @labels ||= GlobalLabel.build_collection(milestones.includes(:labels).map(&:labels).flatten)
- .sort_by!(&:title)
- end
-
- def due_date
- return @due_date if defined?(@due_date)
-
- @due_date =
- if @milestones.all? { |x| x.due_date == @milestones.first.due_date }
- @milestones.first.due_date
- end
- end
-
- def start_date
- return @start_date if defined?(@start_date)
-
- @start_date =
- if @milestones.all? { |x| x.start_date == @milestones.first.start_date }
- @milestones.first.start_date
- end
+ @labels ||= GlobalLabel.build_collection(milestone.labels).sort_by!(&:title)
end
end
diff --git a/app/models/gpg_signature.rb b/app/models/gpg_signature.rb
index 0816778deae..7f9ff7bbda6 100644
--- a/app/models/gpg_signature.rb
+++ b/app/models/gpg_signature.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class GpgSignature < ActiveRecord::Base
+class GpgSignature < ApplicationRecord
include ShaAttribute
sha_attribute :commit_sha
@@ -33,6 +33,11 @@ class GpgSignature < ActiveRecord::Base
)
end
+ def self.safe_create!(attributes)
+ create_with(attributes)
+ .safe_find_or_create_by!(commit_sha: attributes[:commit_sha])
+ end
+
def gpg_key=(model)
case model
when GpgKey
diff --git a/app/models/group.rb b/app/models/group.rb
index edac2444c4d..495bfe04499 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -56,7 +56,7 @@ class Group < Namespace
validates :two_factor_grace_period, presence: true, numericality: { greater_than_or_equal_to: 0 }
- add_authentication_token_field :runners_token, encrypted: true, migrating: true
+ add_authentication_token_field :runners_token, encrypted: -> { Feature.enabled?(:groups_tokens_optional_encryption) ? :optional : :required }
after_create :post_create_hook
after_destroy :post_destroy_hook
@@ -98,7 +98,7 @@ class Group < Namespace
def select_for_project_authorization
if current_scope.joins_values.include?(:shared_projects)
joins('INNER JOIN namespaces project_namespace ON project_namespace.id = projects.namespace_id')
- .where('project_namespace.share_with_group_lock = ?', false)
+ .where('project_namespace.share_with_group_lock = ?', false)
.select("projects.id AS project_id, LEAST(project_group_links.group_access, members.access_level) AS access_level")
else
super
@@ -382,6 +382,10 @@ class Group < Namespace
end
end
+ def highest_group_member(user)
+ GroupMember.where(source_id: self_and_ancestors_ids, user_id: user.id).order(:access_level).last
+ end
+
def hashed_storage?(_feature)
false
end
diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb
index 9dfaebacc83..97cb26c6ea9 100644
--- a/app/models/group_milestone.rb
+++ b/app/models/group_milestone.rb
@@ -1,18 +1,36 @@
# frozen_string_literal: true
# Group Milestones are milestones that can be shared among many projects within the same group
class GroupMilestone < GlobalMilestone
- attr_accessor :group
+ attr_reader :group, :milestones
def self.build_collection(group, projects, params)
- super(projects, params).each do |milestone|
- milestone.group = group
+ params =
+ { state: params[:state], search_title: params[:search_title] }
+
+ project_milestones = Milestone.of_projects(projects)
+ project_milestones = project_milestones.search_title(params[:search_title]) if params[:search_title].present?
+ child_milestones = Milestone.filter_by_state(project_milestones, params[:state])
+ grouped_milestones = child_milestones.group_by(&:title)
+
+ grouped_milestones.map do |title, grouped|
+ new(title, grouped, group)
end
end
def self.build(group, projects, title)
- super(projects, title).tap do |milestone|
- milestone&.group = group
- end
+ child_milestones = Milestone.of_projects(projects).where(title: title)
+ return if child_milestones.blank?
+
+ new(title, child_milestones, group)
+ end
+
+ def initialize(title, milestones, group)
+ @milestones = milestones
+ @group = group
+ end
+
+ def milestone
+ @milestone ||= milestones.find { |m| m.description.present? } || milestones.first
end
def issues_finder_params
diff --git a/app/models/identity.rb b/app/models/identity.rb
index d63dd432426..acdde4f296b 100644
--- a/app/models/identity.rb
+++ b/app/models/identity.rb
@@ -8,7 +8,7 @@ class Identity < ActiveRecord::Base
validates :provider, presence: true
validates :extern_uid, allow_blank: true, uniqueness: { scope: UniquenessScopes.scopes, case_sensitive: false }
- validates :user_id, uniqueness: { scope: UniquenessScopes.scopes }
+ validates :user, uniqueness: { scope: UniquenessScopes.scopes }
before_save :ensure_normalized_extern_uid, if: :extern_uid_changed?
after_destroy :clear_user_synced_attributes, if: :user_synced_attributes_metadata_from_provider?
diff --git a/app/models/individual_note_discussion.rb b/app/models/individual_note_discussion.rb
index 07ee7470ea2..b4a661ae5b4 100644
--- a/app/models/individual_note_discussion.rb
+++ b/app/models/individual_note_discussion.rb
@@ -13,6 +13,18 @@ class IndividualNoteDiscussion < Discussion
true
end
+ def can_convert_to_discussion?
+ noteable.supports_replying_to_individual_notes? && Feature.enabled?(:reply_to_individual_notes)
+ end
+
+ def convert_to_discussion!(save: false)
+ first_note.becomes!(Discussion.note_class).to_discussion.tap do
+ # Save needs to be called on first_note instead of the transformed note
+ # because of https://gitlab.com/gitlab-org/gitlab-ce/issues/57324
+ first_note.save if save
+ end
+ end
+
def reply_attributes
super.tap { |attrs| attrs.delete(:discussion_id) }
end
diff --git a/app/models/internal_id.rb b/app/models/internal_id.rb
index e7168d49db9..e75c6eb2331 100644
--- a/app/models/internal_id.rb
+++ b/app/models/internal_id.rb
@@ -66,6 +66,17 @@ class InternalId < ActiveRecord::Base
InternalIdGenerator.new(subject, scope, usage, init).generate
end
+ # Flushing records is generally safe in a sense that those
+ # records are going to be re-created when needed.
+ #
+ # A filter condition has to be provided to not accidentally flush
+ # records for all projects.
+ def flush_records!(filter)
+ raise ArgumentError, "filter cannot be empty" if filter.blank?
+
+ where(filter).delete_all
+ end
+
def available?
@available_flag ||= ActiveRecord::Migrator.current_version >= REQUIRED_SCHEMA_VERSION # rubocop:disable Gitlab/PredicateMemoization
end
@@ -111,7 +122,7 @@ class InternalId < ActiveRecord::Base
# Generates next internal id and returns it
def generate
- InternalId.transaction do
+ subject.transaction do
# Create a record in internal_ids if one does not yet exist
# and increment its last value
#
@@ -125,7 +136,7 @@ class InternalId < ActiveRecord::Base
#
# Note this will acquire a ROW SHARE lock on the InternalId record
def track_greatest(new_value)
- InternalId.transaction do
+ subject.transaction do
(lookup || create_record).track_greatest_and_save!(new_value)
end
end
@@ -148,7 +159,7 @@ class InternalId < ActiveRecord::Base
# violation. We can safely roll-back the nested transaction and perform
# a lookup instead to retrieve the record.
def create_record
- InternalId.transaction(requires_new: true) do
+ subject.transaction(requires_new: true) do
InternalId.create!(
**scope,
usage: usage_value,
diff --git a/app/models/issue.rb b/app/models/issue.rb
index b7e13bcbccf..071ad50fddc 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -26,6 +26,8 @@ class Issue < ActiveRecord::Base
DueThisMonth = DueDateStruct.new('Due This Month', 'month').freeze
DueNextMonthAndPreviousTwoWeeks = DueDateStruct.new('Due Next Month And Previous Two Weeks', 'next_month_and_previous_two_weeks').freeze
+ SORTING_PREFERENCE_FIELD = :issues_sort
+
belongs_to :project
belongs_to :moved_to, class_name: 'Issue'
belongs_to :closed_by, class_name: 'User'
@@ -64,6 +66,7 @@ class Issue < ActiveRecord::Base
scope :preload_associations, -> { preload(:labels, project: :namespace) }
scope :public_only, -> { where(confidential: false) }
+ scope :confidential_only, -> { where(confidential: true) }
after_save :expire_etag_cache
after_save :ensure_metrics, unless: :imported?
@@ -230,7 +233,8 @@ class Issue < ActiveRecord::Base
end
def check_for_spam?
- project.public? && (title_changed? || description_changed?)
+ publicly_visible? &&
+ (title_changed? || description_changed? || confidential_changed?)
end
def as_json(options = {})
@@ -259,6 +263,10 @@ class Issue < ActiveRecord::Base
end
# rubocop: enable CodeReuse/ServiceClass
+ def merge_requests_count
+ merge_requests_closing_issues.count
+ end
+
private
def ensure_metrics
diff --git a/app/models/label.rb b/app/models/label.rb
index 5d2d1afd1d9..1c3db3eb35d 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -214,6 +214,7 @@ class Label < ActiveRecord::Base
super(options).tap do |json|
json[:type] = self.try(:type)
json[:priority] = priority(options[:project]) if options.key?(:project)
+ json[:textColor] = text_color
end
end
diff --git a/app/models/label_note.rb b/app/models/label_note.rb
index 680952cf421..d6814f4a948 100644
--- a/app/models/label_note.rb
+++ b/app/models/label_note.rb
@@ -81,7 +81,7 @@ class LabelNote < Note
deleted = label_refs.count - existing_refs.count
deleted_str = deleted == 0 ? nil : "#{deleted} deleted"
- return nil unless refs_str || deleted_str
+ return unless refs_str || deleted_str
label_list_str = [refs_str, deleted_str].compact.join(' + ')
suffix = 'label'.pluralize(deleted > 0 ? deleted : existing_refs.count)
diff --git a/app/models/legacy_diff_note.rb b/app/models/legacy_diff_note.rb
index 00dec6bb92b..e2c75bc7ee9 100644
--- a/app/models/legacy_diff_note.rb
+++ b/app/models/legacy_diff_note.rb
@@ -73,7 +73,7 @@ class LegacyDiffNote < Note
private
def find_diff
- return nil unless noteable
+ return unless noteable
return @diff if defined?(@diff)
@diff = noteable.raw_diffs(Commit.max_diff_options).find do |d|
diff --git a/app/models/lfs_download_object.rb b/app/models/lfs_download_object.rb
new file mode 100644
index 00000000000..6383f95d546
--- /dev/null
+++ b/app/models/lfs_download_object.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class LfsDownloadObject
+ include ActiveModel::Validations
+
+ attr_accessor :oid, :size, :link
+ delegate :sanitized_url, :credentials, to: :sanitized_uri
+
+ validates :oid, format: { with: /\A\h{64}\z/ }
+ validates :size, numericality: { greater_than_or_equal_to: 0 }
+ validates :link, public_url: { protocols: %w(http https) }
+
+ def initialize(oid:, size:, link:)
+ @oid = oid
+ @size = size
+ @link = link
+ end
+
+ def sanitized_uri
+ @sanitized_uri ||= Gitlab::UrlSanitizer.new(link)
+ end
+end
diff --git a/app/models/list.rb b/app/models/list.rb
index 029685be927..682af761ba0 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -54,6 +54,6 @@ class List < ActiveRecord::Base
private
def can_be_destroyed
- destroyable?
+ throw(:abort) unless destroyable?
end
end
diff --git a/app/models/member.rb b/app/models/member.rb
index 9fc95ea00c3..8e071a8ff21 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -76,14 +76,17 @@ class Member < ActiveRecord::Base
scope :maintainers, -> { active.where(access_level: MAINTAINER) }
scope :masters, -> { maintainers } # @deprecated
scope :owners, -> { active.where(access_level: OWNER) }
- scope :owners_and_maintainers, -> { active.where(access_level: [OWNER, MAINTAINER]) }
+ scope :owners_and_maintainers, -> { active.where(access_level: [OWNER, MAINTAINER]) }
scope :owners_and_masters, -> { owners_and_maintainers } # @deprecated
+ scope :with_user, -> (user) { where(user: user) }
scope :order_name_asc, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.name', 'ASC')) }
scope :order_name_desc, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.name', 'DESC')) }
scope :order_recent_sign_in, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.last_sign_in_at', 'DESC')) }
scope :order_oldest_sign_in, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.last_sign_in_at', 'ASC')) }
+ scope :on_project_and_ancestors, ->(project) { where(source: [project] + project.ancestors) }
+
before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? }
after_create :send_invite, if: :invite?, unless: :importing?
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index fc49ee7ac8c..2c9e1ba1d80 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -12,6 +12,8 @@ class GroupMember < Member
validates :source_type, format: { with: /\ANamespace\z/ }
default_scope { where(source_type: SOURCE_TYPE) }
+ scope :in_groups, ->(groups) { where(source_id: groups.select(:id)) }
+
after_create :update_two_factor_requirement, unless: :invite?
after_destroy :update_two_factor_requirement, unless: :invite?
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 016c18ce6c8..5372c6084f4 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -12,6 +12,10 @@ class ProjectMember < Member
default_scope { where(source_type: SOURCE_TYPE) }
scope :in_project, ->(project) { where(source_id: project.id) }
+ scope :in_namespaces, ->(groups) do
+ joins('INNER JOIN projects ON projects.id = members.source_id')
+ .where('projects.namespace_id in (?)', groups.select(:id))
+ end
class << self
# Add users to projects with passed access option
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 944b9f72396..b67797f5404 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -21,6 +21,8 @@ class MergeRequest < ActiveRecord::Base
self.reactive_cache_refresh_interval = 10.minutes
self.reactive_cache_lifetime = 10.minutes
+ SORTING_PREFERENCE_FIELD = :merge_requests_sort
+
ignore_column :locked_at,
:ref_fetched,
:deleted_at
@@ -69,7 +71,7 @@ class MergeRequest < ActiveRecord::Base
serialize :merge_params, Hash # rubocop:disable Cop/ActiveRecordSerialize
- after_create :ensure_merge_request_diff, unless: :importing?
+ after_create :ensure_merge_request_diff
after_update :clear_memoized_shas
after_update :reload_diff_if_branch_changed
after_save :ensure_metrics
@@ -105,7 +107,9 @@ class MergeRequest < ActiveRecord::Base
before_transition any => :opened do |merge_request|
merge_request.merge_jid = nil
+ end
+ after_transition any => :opened do |merge_request|
merge_request.run_after_commit do
UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
end
@@ -185,6 +189,9 @@ class MergeRequest < ActiveRecord::Base
after_save :keep_around_commit
+ alias_attribute :project, :target_project
+ alias_attribute :project_id, :target_project_id
+
def self.reference_prefix
'!'
end
@@ -282,6 +289,14 @@ class MergeRequest < ActiveRecord::Base
work_in_progress?(title) ? title : "WIP: #{title}"
end
+ def commit_authors
+ @commit_authors ||= commits.authors
+ end
+
+ def authors
+ User.from_union([commit_authors, User.where(id: self.author_id)])
+ end
+
# Verifies if title has changed not taking into account WIP prefix
# for merge requests.
def wipless_title_changed(old_title)
@@ -325,13 +340,15 @@ class MergeRequest < ActiveRecord::Base
end
def commits
- if persisted?
- merge_request_diff.commits
- elsif compare_commits
- compare_commits.reverse
- else
- []
- end
+ return merge_request_diff.commits if persisted?
+
+ commits_arr = if compare_commits
+ compare_commits.reverse
+ else
+ []
+ end
+
+ CommitCollection.new(source_project, commits_arr, source_branch)
end
def commits_count
@@ -408,6 +425,28 @@ class MergeRequest < ActiveRecord::Base
merge_request_diffs.where.not(id: merge_request_diff.id)
end
+ def preloads_discussion_diff_highlighting?
+ true
+ end
+
+ def preload_discussions_diff_highlight
+ preloadable_files = note_diff_files.for_commit_or_unresolved
+
+ discussions_diffs.load_highlight(preloadable_files.pluck(:id))
+ end
+
+ def discussions_diffs
+ strong_memoize(:discussions_diffs) do
+ Gitlab::DiscussionsDiff::FileCollection.new(note_diff_files.to_a)
+ end
+ end
+
+ def note_diff_files
+ NoteDiffFile
+ .where(diff_note: discussion_notes)
+ .includes(diff_note: :project)
+ end
+
def diff_size
# Calling `merge_request_diff.diffs.real_size` will also perform
# highlighting, which we don't need here.
@@ -526,15 +565,19 @@ class MergeRequest < ActiveRecord::Base
end
def diff_refs
- if persisted?
- merge_request_diff.diff_refs
- else
- Gitlab::Diff::DiffRefs.new(
- base_sha: diff_base_sha,
- start_sha: diff_start_sha,
- head_sha: diff_head_sha
- )
- end
+ persisted? ? merge_request_diff.diff_refs : repository_diff_refs
+ end
+
+ # Instead trying to fetch the
+ # persisted diff_refs, this method goes
+ # straight to the repository to get the
+ # most recent data possible.
+ def repository_diff_refs
+ Gitlab::Diff::DiffRefs.new(
+ base_sha: branch_merge_base_sha,
+ start_sha: target_branch_sha,
+ head_sha: source_branch_sha
+ )
end
def branch_merge_base_sha
@@ -724,6 +767,16 @@ class MergeRequest < ActiveRecord::Base
true
end
+ def mergeable_to_ref?
+ return false if merged?
+ return false if broken?
+
+ # Given the `merge_ref_path` will have the same
+ # state the `target_branch` would have. Ideally
+ # we need to check if it can be merged to it.
+ project.repository.can_be_merged?(diff_head_sha, target_branch)
+ end
+
def ff_merge_possible?
project.repository.ancestor?(target_branch_sha, diff_head_sha)
end
@@ -797,10 +850,6 @@ class MergeRequest < ActiveRecord::Base
target_project != source_project
end
- def project
- target_project
- end
-
# If the merge request closes any issues, save this information in the
# `MergeRequestsClosingIssues` model. This is a performance optimization.
# Calculating this information for a number of merge requests requires
@@ -899,7 +948,7 @@ class MergeRequest < ActiveRecord::Base
self.target_project.repository.branch_exists?(self.target_branch)
end
- def merge_commit_message(include_description: false)
+ def default_merge_commit_message(include_description: false)
closes_issues_references = visible_closing_issues_for.map do |issue|
issue.to_reference(target_project)
end
@@ -919,6 +968,13 @@ class MergeRequest < ActiveRecord::Base
message.join("\n\n")
end
+ # Returns the oldest multi-line commit message, or the MR title if none found
+ def default_squash_commit_message
+ strong_memoize(:default_squash_commit_message) do
+ commits.without_merge_commits.reverse.find(&:description?)&.safe_message || title
+ end
+ end
+
def reset_merge_when_pipeline_succeeds
return unless merge_when_pipeline_succeeds?
@@ -927,6 +983,7 @@ class MergeRequest < ActiveRecord::Base
if merge_params
merge_params.delete('should_remove_source_branch')
merge_params.delete('commit_message')
+ merge_params.delete('squash_commit_message')
end
self.save
@@ -1029,6 +1086,10 @@ class MergeRequest < ActiveRecord::Base
"refs/#{Repository::REF_MERGE_REQUEST}/#{iid}/head"
end
+ def merge_ref_path
+ "refs/#{Repository::REF_MERGE_REQUEST}/#{iid}/merge"
+ end
+
def in_locked_state
begin
lock_mr
@@ -1068,10 +1129,16 @@ class MergeRequest < ActiveRecord::Base
def all_pipelines(shas: all_commit_shas)
return Ci::Pipeline.none unless source_project
- @all_pipelines ||= source_project.ci_pipelines
- .where(sha: shas, ref: source_branch)
- .where(merge_request: [nil, self])
- .sort_by_merge_request_pipelines
+ @all_pipelines ||=
+ source_project.ci_pipelines
+ .for_merge_request(self, source_branch, all_commit_shas)
+ end
+
+ def update_head_pipeline
+ find_actual_head_pipeline.try do |pipeline|
+ self.head_pipeline = pipeline
+ update_column(:head_pipeline_id, head_pipeline.id) if head_pipeline_id_changed?
+ end
end
def merge_request_pipeline_exists?
@@ -1086,35 +1153,16 @@ class MergeRequest < ActiveRecord::Base
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI_MERGE_REQUEST_ID', value: id.to_s)
variables.append(key: 'CI_MERGE_REQUEST_IID', value: iid.to_s)
-
- variables.append(key: 'CI_MERGE_REQUEST_REF_PATH',
- value: ref_path.to_s)
-
- variables.append(key: 'CI_MERGE_REQUEST_PROJECT_ID',
- value: project.id.to_s)
-
- variables.append(key: 'CI_MERGE_REQUEST_PROJECT_PATH',
- value: project.full_path)
-
- variables.append(key: 'CI_MERGE_REQUEST_PROJECT_URL',
- value: project.web_url)
-
- variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_NAME',
- value: target_branch.to_s)
-
- if source_project
- variables.append(key: 'CI_MERGE_REQUEST_SOURCE_PROJECT_ID',
- value: source_project.id.to_s)
-
- variables.append(key: 'CI_MERGE_REQUEST_SOURCE_PROJECT_PATH',
- value: source_project.full_path)
-
- variables.append(key: 'CI_MERGE_REQUEST_SOURCE_PROJECT_URL',
- value: source_project.web_url)
-
- variables.append(key: 'CI_MERGE_REQUEST_SOURCE_BRANCH_NAME',
- value: source_branch.to_s)
- end
+ variables.append(key: 'CI_MERGE_REQUEST_REF_PATH', value: ref_path.to_s)
+ variables.append(key: 'CI_MERGE_REQUEST_PROJECT_ID', value: project.id.to_s)
+ variables.append(key: 'CI_MERGE_REQUEST_PROJECT_PATH', value: project.full_path)
+ variables.append(key: 'CI_MERGE_REQUEST_PROJECT_URL', value: project.web_url)
+ variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_NAME', value: target_branch.to_s)
+ variables.append(key: 'CI_MERGE_REQUEST_TITLE', value: title)
+ variables.append(key: 'CI_MERGE_REQUEST_ASSIGNEES', value: assignee.username) if assignee
+ variables.append(key: 'CI_MERGE_REQUEST_MILESTONE', value: milestone.title) if milestone
+ variables.append(key: 'CI_MERGE_REQUEST_LABELS', value: label_names.join(',')) if labels.present?
+ variables.concat(source_project_variables)
end
end
@@ -1268,7 +1316,7 @@ class MergeRequest < ActiveRecord::Base
def base_pipeline
@base_pipeline ||= project.ci_pipelines
.order(id: :desc)
- .find_by(sha: diff_base_sha)
+ .find_by(sha: diff_base_sha, ref: target_branch)
end
def discussions_rendered_on_frontend?
@@ -1314,4 +1362,22 @@ class MergeRequest < ActiveRecord::Base
source_project.repository.squash_in_progress?(id)
end
+
+ private
+
+ def find_actual_head_pipeline
+ source_project&.ci_pipelines
+ &.latest_for_merge_request(self, source_branch, diff_head_sha)
+ end
+
+ def source_project_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ break variables unless source_project
+
+ variables.append(key: 'CI_MERGE_REQUEST_SOURCE_PROJECT_ID', value: source_project.id.to_s)
+ variables.append(key: 'CI_MERGE_REQUEST_SOURCE_PROJECT_PATH', value: source_project.full_path)
+ variables.append(key: 'CI_MERGE_REQUEST_SOURCE_PROJECT_URL', value: source_project.web_url)
+ variables.append(key: 'CI_MERGE_REQUEST_SOURCE_BRANCH_NAME', value: source_branch.to_s)
+ end
+ end
end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index a3029a54604..351a662ae83 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -7,19 +7,23 @@ class MergeRequestDiff < ActiveRecord::Base
include IgnorableColumn
include EachBatch
include Gitlab::Utils::StrongMemoize
+ include ObjectStorage::BackgroundMove
# Don't display more than 100 commits at once
COMMITS_SAFE_SIZE = 100
- ignore_column :st_commits,
- :st_diffs
-
belongs_to :merge_request
+
manual_inverse_association :merge_request, :merge_request_diff
- has_many :merge_request_diff_files, -> { order(:merge_request_diff_id, :relative_order) }
+ has_many :merge_request_diff_files,
+ -> { order(:merge_request_diff_id, :relative_order) },
+ inverse_of: :merge_request_diff
+
has_many :merge_request_diff_commits, -> { order(:merge_request_diff_id, :relative_order) }
+ validates :base_commit_sha, :head_commit_sha, :start_commit_sha, sha: true
+
state_machine :state, initial: :empty do
event :clean do
transition any => :without_files
@@ -45,10 +49,14 @@ class MergeRequestDiff < ActiveRecord::Base
scope :recent, -> { order(id: :desc).limit(100) }
+ mount_uploader :external_diff, ExternalDiffUploader
+
# All diff information is collected from repository after object is created.
# It allows you to override variables like head_commit_sha before getting diff.
after_create :save_git_content, unless: :importing?
+ after_save :update_external_diff_store, if: :external_diff_changed?
+
def self.find_by_diff_refs(diff_refs)
find_by(start_commit_sha: diff_refs.start_sha, head_commit_sha: diff_refs.head_sha, base_commit_sha: diff_refs.base_sha)
end
@@ -241,10 +249,97 @@ class MergeRequestDiff < ActiveRecord::Base
end
end
+ # Carrierwave defines `write_uploader` dynamically on this class, so `super`
+ # does not work. Alias the carrierwave method so we can call it when needed
+ alias_method :carrierwave_write_uploader, :write_uploader
+
+ # The `external_diff`, `external_diff_store`, and `stored_externally`
+ # columns were introduced in GitLab 11.8, but some background migration specs
+ # use factories that rely on current code with an old schema. Without these
+ # `has_attribute?` guards, they fail with a `MissingAttributeError`.
+ #
+ # For more details, see: https://gitlab.com/gitlab-org/gitlab-ce/issues/44990
+
+ def write_uploader(column, identifier)
+ carrierwave_write_uploader(column, identifier) if has_attribute?(column)
+ end
+
+ def update_external_diff_store
+ update_column(:external_diff_store, external_diff.object_store) if
+ has_attribute?(:external_diff_store)
+ end
+
+ def external_diff_changed?
+ super if has_attribute?(:external_diff)
+ end
+
+ def stored_externally
+ super if has_attribute?(:stored_externally)
+ end
+ alias_method :stored_externally?, :stored_externally
+
+ # If enabled, yields the external file containing the diff. Otherwise, yields
+ # nil. This method is not thread-safe, but it *is* re-entrant, which allows
+ # multiple merge_request_diff_files to load their data efficiently
+ def opening_external_diff
+ return yield(nil) unless stored_externally?
+ return yield(@external_diff_file) if @external_diff_file
+
+ external_diff.open do |file|
+ begin
+ @external_diff_file = file
+
+ yield(@external_diff_file)
+ ensure
+ @external_diff_file = nil
+ end
+ end
+ end
+
private
def create_merge_request_diff_files(diffs)
- rows = diffs.map.with_index do |diff, index|
+ rows =
+ if has_attribute?(:external_diff) && Gitlab.config.external_diffs.enabled
+ build_external_merge_request_diff_files(diffs)
+ else
+ build_merge_request_diff_files(diffs)
+ end
+
+ # Faster inserts
+ Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
+ end
+
+ def build_external_merge_request_diff_files(diffs)
+ rows = build_merge_request_diff_files(diffs)
+ tempfile = build_external_diff_tempfile(rows)
+
+ self.external_diff = tempfile
+ self.stored_externally = true
+
+ rows
+ ensure
+ tempfile&.unlink
+ end
+
+ def build_external_diff_tempfile(rows)
+ Tempfile.open(external_diff.filename) do |file|
+ rows.inject(0) do |offset, row|
+ data = row.delete(:diff)
+ row[:external_diff_offset] = offset
+ row[:external_diff_size] = data.size
+
+ file.write(data)
+
+ offset + data.size
+ end
+
+ file
+ end
+ end
+
+ def build_merge_request_diff_files(diffs)
+ diffs.map.with_index do |diff, index|
diff_hash = diff.to_hash.merge(
binary: false,
merge_request_diff_id: self.id,
@@ -261,18 +356,20 @@ class MergeRequestDiff < ActiveRecord::Base
end
end
end
-
- Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
end
def load_diffs(options)
- collection = merge_request_diff_files
+ # Ensure all diff files operate on the same external diff file instance if
+ # present. This reduces file open/close overhead.
+ opening_external_diff do
+ collection = merge_request_diff_files
- if paths = options[:paths]
- collection = collection.where('old_path IN (?) OR new_path IN (?)', paths, paths)
- end
+ if paths = options[:paths]
+ collection = collection.where('old_path IN (?) OR new_path IN (?)', paths, paths)
+ end
- Gitlab::Git::DiffCollection.new(collection.map(&:to_hash), options)
+ Gitlab::Git::DiffCollection.new(collection.map(&:to_hash), options)
+ end
end
def load_commits
diff --git a/app/models/merge_request_diff_file.rb b/app/models/merge_request_diff_file.rb
index a9f110bec5c..e8d936e265c 100644
--- a/app/models/merge_request_diff_file.rb
+++ b/app/models/merge_request_diff_file.rb
@@ -4,7 +4,7 @@ class MergeRequestDiffFile < ActiveRecord::Base
include Gitlab::EncodingHelper
include DiffFile
- belongs_to :merge_request_diff
+ belongs_to :merge_request_diff, inverse_of: :merge_request_diff_files
def utf8_diff
return '' if diff.blank?
@@ -13,6 +13,16 @@ class MergeRequestDiffFile < ActiveRecord::Base
end
def diff
- binary? ? super.unpack('m0').first : super
+ content =
+ if merge_request_diff&.stored_externally?
+ merge_request_diff.opening_external_diff do |file|
+ file.seek(external_diff_offset)
+ file.read(external_diff_size)
+ end
+ else
+ super
+ end
+
+ binary? ? content.unpack('m0').first : content
end
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 3cc8e2c44bb..26cfdc5ef30 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -28,7 +28,7 @@ class Milestone < ActiveRecord::Base
has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.milestones&.maximum(:iid) }
has_many :issues
- has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues
+ has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues
has_many :merge_requests
has_many :events, as: :target, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
@@ -38,12 +38,14 @@ class Milestone < ActiveRecord::Base
scope :closed, -> { with_state(:closed) }
scope :for_projects, -> { where(group: nil).includes(:project) }
- scope :for_projects_and_groups, -> (project_ids, group_ids) do
- conditions = []
- conditions << arel_table[:project_id].in(project_ids) if project_ids&.compact&.any?
- conditions << arel_table[:group_id].in(group_ids) if group_ids&.compact&.any?
+ scope :for_projects_and_groups, -> (projects, groups) do
+ projects = projects.compact if projects.is_a? Array
+ projects = [] if projects.nil?
- where(conditions.reduce(:or))
+ groups = groups.compact if groups.is_a? Array
+ groups = [] if groups.nil?
+
+ where(project_id: projects).or(where(group_id: groups))
end
scope :order_by_name_asc, -> { order(Arel::Nodes::Ascending.new(arel_table[:title].lower)) }
@@ -75,7 +77,7 @@ class Milestone < ActiveRecord::Base
alias_attribute :name, :title
class << self
- # Searches for milestones matching the given query.
+ # Searches for milestones with a matching title or description.
#
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
#
@@ -86,6 +88,17 @@ class Milestone < ActiveRecord::Base
fuzzy_search(query, [:title, :description])
end
+ # Searches for milestones with a matching title.
+ #
+ # This method uses ILIKE on PostgreSQL and LIKE on MySQL.
+ #
+ # query - The search query as a String
+ #
+ # Returns an ActiveRecord::Relation.
+ def search_title(query)
+ fuzzy_search(query, [:title])
+ end
+
def filter_by_state(milestones, state)
case state
when 'closed' then milestones.closed
@@ -94,6 +107,10 @@ class Milestone < ActiveRecord::Base
end
end
+ def count_by_state
+ reorder(nil).group(:state).count
+ end
+
def predefined?(milestone)
milestone == Any ||
milestone == None ||
@@ -129,18 +146,29 @@ class Milestone < ActiveRecord::Base
@link_reference_pattern ||= super("milestones", /(?<milestone>\d+)/)
end
- def self.upcoming_ids_by_projects(projects)
- rel = unscoped.of_projects(projects).active.where('due_date > ?', Time.now)
+ def self.upcoming_ids(projects, groups)
+ rel = unscoped
+ .for_projects_and_groups(projects, groups)
+ .active.where('milestones.due_date > NOW()')
if Gitlab::Database.postgresql?
- rel.order(:project_id, :due_date).select('DISTINCT ON (project_id) id')
+ rel.order(:project_id, :group_id, :due_date).select('DISTINCT ON (project_id, group_id) id')
else
+ # We need to use MySQL's NULL-safe comparison operator `<=>` here
+ # because one of `project_id` or `group_id` is always NULL
+ join_clause = <<~HEREDOC
+ LEFT OUTER JOIN milestones earlier_milestones
+ ON milestones.project_id <=> earlier_milestones.project_id
+ AND milestones.group_id <=> earlier_milestones.group_id
+ AND milestones.due_date > earlier_milestones.due_date
+ AND earlier_milestones.due_date > NOW()
+ AND earlier_milestones.state = 'active'
+ HEREDOC
+
rel
- .group(:project_id, :due_date, :id)
- .having('due_date = MIN(due_date)')
- .pluck(:id, :project_id, :due_date)
- .uniq(&:second)
- .map(&:first)
+ .joins(join_clause)
+ .where('earlier_milestones.id IS NULL')
+ .select(:id)
end
end
@@ -174,7 +202,7 @@ class Milestone < ActiveRecord::Base
return STATE_COUNT_HASH unless projects || groups
counts = Milestone
- .for_projects_and_groups(projects&.map(&:id), groups&.map(&:id))
+ .for_projects_and_groups(projects, groups)
.reorder(nil)
.group(:state)
.count
@@ -212,10 +240,10 @@ class Milestone < ActiveRecord::Base
end
def reference_link_text(from = nil)
- self.title
+ self.class.reference_prefix + self.title
end
- def milestoneish_ids
+ def milestoneish_id
id
end
@@ -258,8 +286,7 @@ class Milestone < ActiveRecord::Base
if project
relation = Milestone.for_projects_and_groups([project_id], [project.group&.id])
elsif group
- project_ids = group.projects.map(&:id)
- relation = Milestone.for_projects_and_groups(project_ids, [group.id])
+ relation = Milestone.for_projects_and_groups(group.projects.select(:id), [group.id])
end
title_exists = relation.find_by_title(title)
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index a0bebc5e9a2..a5c479bdc0c 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Namespace < ActiveRecord::Base
+class Namespace < ApplicationRecord
include CacheMarkdownField
include Sortable
include Gitlab::VisibilityLevel
@@ -149,7 +149,7 @@ class Namespace < ActiveRecord::Base
end
def find_fork_of(project)
- return nil unless project.fork_network
+ return unless project.fork_network
if Gitlab::SafeRequestStore.active?
forks_in_namespace = Gitlab::SafeRequestStore.fetch("namespaces:#{id}:forked_projects") do
diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb
index 6da3bb7bfb7..ecbeb24ee0a 100644
--- a/app/models/network/graph.rb
+++ b/app/models/network/graph.rb
@@ -40,9 +40,12 @@ module Network
# Get commits from repository
#
def collect_commits
- find_commits(count_to_display_commit_in_center).map do |commit|
- # Decorate with app/model/network/commit.rb
- Network::Commit.new(commit)
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/58013
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ find_commits(count_to_display_commit_in_center).map do |commit|
+ # Decorate with app/model/network/commit.rb
+ Network::Commit.new(commit)
+ end
end
end
diff --git a/app/models/note.rb b/app/models/note.rb
index becf14e9785..1578ae9c4cc 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -456,6 +456,10 @@ class Note < ActiveRecord::Base
Upload.find_by(model: self, path: paths)
end
+ def parent
+ project
+ end
+
private
def keep_around_commit
diff --git a/app/models/note_diff_file.rb b/app/models/note_diff_file.rb
index 27aef7adc48..e369122003e 100644
--- a/app/models/note_diff_file.rb
+++ b/app/models/note_diff_file.rb
@@ -3,7 +3,22 @@
class NoteDiffFile < ActiveRecord::Base
include DiffFile
+ scope :for_commit_or_unresolved, -> do
+ joins(:diff_note).where("resolved_at IS NULL OR noteable_type = 'Commit'")
+ end
+
+ delegate :original_position, :project, to: :diff_note
+
belongs_to :diff_note, inverse_of: :note_diff_file
validates :diff_note, presence: true
+
+ def raw_diff_file
+ raw_diff = Gitlab::Git::Diff.new(to_hash)
+
+ Gitlab::Diff::File.new(raw_diff,
+ repository: project.repository,
+ diff_refs: original_position.diff_refs,
+ unique_identifier: id)
+ end
end
diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb
index 9f16eefe074..793cce191fa 100644
--- a/app/models/notification_recipient.rb
+++ b/app/models/notification_recipient.rb
@@ -119,7 +119,7 @@ class NotificationRecipient
private
def read_ability
- return nil if @skip_read_ability
+ return if @skip_read_ability
return @read_ability if instance_variable_defined?(:@read_ability)
@read_ability =
@@ -136,7 +136,7 @@ class NotificationRecipient
end
def default_project
- return nil if @target.nil?
+ return if @target.nil?
return @target if @target.is_a?(Project)
return @target.project if @target.respond_to?(:project)
end
@@ -153,7 +153,7 @@ class NotificationRecipient
user.global_notification_setting
end
- # Returns the notificaton_setting of the lowest group in hierarchy with non global level
+ # Returns the notification_setting of the lowest group in hierarchy with non global level
def closest_non_global_group_notification_settting
return unless @group
return if indexed_group_notification_settings.empty?
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index 73a58f2420e..ed78a46eaf3 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -2,8 +2,11 @@
class PersonalAccessToken < ActiveRecord::Base
include Expirable
+ include IgnorableColumn
include TokenAuthenticatable
- add_authentication_token_field :token, digest: true, fallback: true
+
+ add_authentication_token_field :token, digest: true
+ ignore_column :token
REDIS_EXPIRY_TIME = 3.minutes
diff --git a/app/models/pool_repository.rb b/app/models/pool_repository.rb
index ad6a008dee8..4635fc72dc7 100644
--- a/app/models/pool_repository.rb
+++ b/app/models/pool_repository.rb
@@ -85,14 +85,20 @@ class PoolRepository < ActiveRecord::Base
def unlink_repository(repository)
object_pool.unlink_repository(repository.raw)
- mark_obsolete unless member_projects.where.not(id: repository.project.id).exists?
+ if member_projects.where.not(id: repository.project.id).exists?
+ true
+ else
+ mark_obsolete
+ end
end
def object_pool
@object_pool ||= Gitlab::Git::ObjectPool.new(
shard.name,
disk_path + '.git',
- source_project.repository.raw)
+ source_project.repository.raw,
+ source_project.full_path
+ )
end
def inspect
diff --git a/app/models/programming_language.rb b/app/models/programming_language.rb
index 0e667dac21e..5f0f313b7f9 100644
--- a/app/models/programming_language.rb
+++ b/app/models/programming_language.rb
@@ -3,4 +3,10 @@
class ProgrammingLanguage < ActiveRecord::Base
validates :name, presence: true
validates :color, allow_blank: false, color: true
+
+ # Returns all programming languages which match the given name (case
+ # insensitively).
+ scope :with_name_case_insensitive, ->(name) do
+ where(arel_table[:name].matches(sanitize_sql_like(name)))
+ end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 09e2a6114fe..4cc13f372c1 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -73,7 +73,7 @@ class Project < ActiveRecord::Base
delegate :no_import?, to: :import_state, allow_nil: true
default_value_for :archived, false
- default_value_for :visibility_level, gitlab_config_features.visibility_level
+ default_value_for(:visibility_level) { Gitlab::CurrentSettings.default_project_visibility }
default_value_for :resolve_outdated_diff_discussions, false
default_value_for :container_registry_enabled, gitlab_config_features.container_registry
default_value_for(:repository_storage) { Gitlab::CurrentSettings.pick_repository_storage }
@@ -85,7 +85,7 @@ class Project < ActiveRecord::Base
default_value_for :snippets_enabled, gitlab_config_features.snippets
default_value_for :only_allow_merge_if_all_discussions_are_resolved, false
- add_authentication_token_field :runners_token, encrypted: true, migrating: true
+ add_authentication_token_field :runners_token, encrypted: -> { Feature.enabled?(:projects_tokens_optional_encryption) ? :optional : :required }
before_validation :mark_remote_mirrors_for_removal, if: -> { RemoteMirror.table_exists? }
@@ -147,7 +147,6 @@ class Project < ActiveRecord::Base
has_one :pipelines_email_service
has_one :irker_service
has_one :pivotaltracker_service
- has_one :hipchat_service
has_one :flowdock_service
has_one :assembla_service
has_one :asana_service
@@ -161,6 +160,7 @@ class Project < ActiveRecord::Base
has_one :pushover_service
has_one :jira_service
has_one :redmine_service
+ has_one :youtrack_service
has_one :custom_issue_tracker_service
has_one :bugzilla_service
has_one :gitlab_issue_tracker_service, inverse_of: :project
@@ -187,6 +187,7 @@ class Project < ActiveRecord::Base
has_one :import_state, autosave: true, class_name: 'ProjectImportState', inverse_of: :project
has_one :import_export_upload, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :project_repository, inverse_of: :project
+ has_one :error_tracking_setting, inverse_of: :project, class_name: 'ErrorTracking::ProjectErrorTrackingSetting'
# Merge Requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
@@ -248,10 +249,10 @@ class Project < ActiveRecord::Base
has_many :container_repositories, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :commit_statuses
- # The relation :all_pipelines is intented to be used when we want to get the
+ # The relation :all_pipelines is intended to be used when we want to get the
# whole list of pipelines associated to the project
has_many :all_pipelines, class_name: 'Ci::Pipeline', inverse_of: :project
- # The relation :ci_pipelines is intented to be used when we want to get only
+ # The relation :ci_pipelines is intended to be used when we want to get only
# those pipeline which are directly related to CI. There are
# other pipelines, like webide ones, that we won't retrieve
# if we use this relation.
@@ -295,6 +296,8 @@ class Project < ActiveRecord::Base
allow_destroy: true,
reject_if: ->(attrs) { attrs[:id].blank? && attrs[:url].blank? }
+ accepts_nested_attributes_for :error_tracking_setting, update_only: true
+
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
delegate :add_user, :add_users, to: :team
@@ -303,6 +306,7 @@ class Project < ActiveRecord::Base
delegate :group_runners_enabled, :group_runners_enabled=, :group_runners_enabled?, to: :ci_cd_settings
delegate :group_clusters_enabled?, to: :group, allow_nil: true
delegate :root_ancestor, to: :namespace, allow_nil: true
+ delegate :last_pipeline, to: :commit, allow_nil: true
# Validations
validates :creator, presence: true, on: :create
@@ -324,15 +328,14 @@ class Project < ActiveRecord::Base
validates :namespace, presence: true
validates :name, uniqueness: { scope: :namespace_id }
- validates :import_url, url: { protocols: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS },
- ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS },
- allow_localhost: false,
- enforce_user: true }, if: [:external_import?, :import_url_changed?]
+ validates :import_url, public_url: { protocols: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS },
+ ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS },
+ enforce_user: true }, if: [:external_import?, :import_url_changed?]
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
- validate :check_limit, on: :create
+ validate :check_personal_projects_limit, on: :create
validate :check_repository_path_availability, on: :update, if: ->(project) { project.renamed? }
- validate :visibility_level_allowed_by_group
- validate :visibility_level_allowed_as_fork
+ validate :visibility_level_allowed_by_group, if: -> { changes.has_key?(:visibility_level) }
+ validate :visibility_level_allowed_as_fork, if: -> { changes.has_key?(:visibility_level) }
validate :check_wiki_path_conflict
validate :validate_pages_https_only, if: -> { changes.has_key?(:pages_https_only) }
validates :repository_storage,
@@ -375,8 +378,10 @@ class Project < ActiveRecord::Base
# "enabled" here means "not disabled". It includes private features!
scope :with_feature_enabled, ->(feature) {
- access_level_attribute = ProjectFeature.access_level_attribute(feature)
- with_project_feature.where(project_features: { access_level_attribute => [nil, ProjectFeature::PRIVATE, ProjectFeature::ENABLED, ProjectFeature::PUBLIC] })
+ access_level_attribute = ProjectFeature.arel_table[ProjectFeature.access_level_attribute(feature)]
+ enabled_feature = access_level_attribute.gt(ProjectFeature::DISABLED).or(access_level_attribute.eq(nil))
+
+ with_project_feature.where(enabled_feature)
}
# Picks a feature where the level is exactly that given.
@@ -385,6 +390,16 @@ class Project < ActiveRecord::Base
with_project_feature.where(project_features: { access_level_attribute => level })
}
+ # Picks projects which use the given programming language
+ scope :with_programming_language, ->(language_name) do
+ lang_id_query = ProgrammingLanguage
+ .with_name_case_insensitive(language_name)
+ .select(:id)
+
+ joins(:repository_languages)
+ .where(repository_languages: { programming_language_id: lang_id_query })
+ end
+
scope :with_builds_enabled, -> { with_feature_enabled(:builds) }
scope :with_issues_enabled, -> { with_feature_enabled(:issues) }
scope :with_issues_available_for_user, ->(current_user) { with_feature_available_for_user(:issues, current_user) }
@@ -463,7 +478,8 @@ class Project < ActiveRecord::Base
# logged in users to more efficiently get private projects with the given
# feature.
def self.with_feature_available_for_user(feature, user)
- visible = [nil, ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
+ visible = [ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
+ min_access_level = ProjectFeature.required_minimum_access_level(feature)
if user&.admin?
with_feature_enabled(feature)
@@ -471,10 +487,15 @@ class Project < ActiveRecord::Base
column = ProjectFeature.quoted_access_level_column(feature)
with_project_feature
- .where("#{column} IN (?) OR (#{column} = ? AND EXISTS (?))",
- visible,
- ProjectFeature::PRIVATE,
- user.authorizations_for_projects)
+ .where(
+ "(projects.visibility_level > :private AND (#{column} IS NULL OR #{column} >= (:public_visible) OR (#{column} = :private_visible AND EXISTS(:authorizations))))"\
+ " OR (projects.visibility_level = :private AND (#{column} IS NULL OR #{column} >= :private_visible) AND EXISTS(:authorizations))",
+ {
+ private: Gitlab::VisibilityLevel::PRIVATE,
+ public_visible: ProjectFeature::ENABLED,
+ private_visible: ProjectFeature::PRIVATE,
+ authorizations: user.authorizations_for_projects(min_access_level: min_access_level)
+ })
else
with_feature_access_level(feature, visible)
end
@@ -528,6 +549,7 @@ class Project < ActiveRecord::Base
def reference_pattern
%r{
+ (?<!#{Gitlab::PathRegex::PATH_START_CHAR})
((?<namespace>#{Gitlab::PathRegex::FULL_NAMESPACE_FORMAT_REGEX})\/)?
(?<project>#{Gitlab::PathRegex::PROJECT_PATH_FORMAT_REGEX})
}x
@@ -567,6 +589,22 @@ class Project < ActiveRecord::Base
end
end
+ def all_pipelines
+ if builds_enabled?
+ super
+ else
+ super.external
+ end
+ end
+
+ def ci_pipelines
+ if builds_enabled?
+ super
+ else
+ super.external
+ end
+ end
+
# returns all ancestor-groups upto but excluding the given namespace
# when no namespace is given, all ancestors upto the top are returned
def ancestors_upto(top = nil, hierarchy_order: nil)
@@ -601,6 +639,10 @@ class Project < ActiveRecord::Base
auto_devops&.enabled.nil? && !(Gitlab::CurrentSettings.auto_devops_enabled? || Feature.enabled?(:force_autodevops_on_by_default, self))
end
+ def daily_statistics_enabled?
+ Feature.enabled?(:project_daily_statistics, self, default_enabled: true)
+ end
+
def empty_repo?
repository.empty?
end
@@ -645,19 +687,15 @@ class Project < ActiveRecord::Base
end
# ref can't be HEAD, can only be branch/tag name or SHA
- def latest_successful_builds_for(ref = default_branch)
+ def latest_successful_build_for(job_name, ref = default_branch)
latest_pipeline = ci_pipelines.latest_successful_for(ref)
+ return unless latest_pipeline
- if latest_pipeline
- latest_pipeline.builds.latest.with_artifacts_archive
- else
- builds.none
- end
+ latest_pipeline.builds.latest.with_artifacts_archive.find_by(name: job_name)
end
- def latest_successful_build_for(job_name, ref = default_branch)
- builds = latest_successful_builds_for(ref)
- builds.find_by!(name: job_name)
+ def latest_successful_build_for!(job_name, ref = default_branch)
+ latest_successful_build_for(job_name, ref) || raise(ActiveRecord::RecordNotFound.new("Couldn't find job #{job_name}"))
end
def merge_base_commit(first_commit_id, second_commit_id)
@@ -723,11 +761,13 @@ class Project < ActiveRecord::Base
end
def import_url=(value)
- return super(value) unless Gitlab::UrlSanitizer.valid?(value)
-
- import_url = Gitlab::UrlSanitizer.new(value)
- super(import_url.sanitized_url)
- create_or_update_import_data(credentials: import_url.credentials)
+ if Gitlab::UrlSanitizer.valid?(value)
+ import_url = Gitlab::UrlSanitizer.new(value)
+ super(import_url.sanitized_url)
+ create_or_update_import_data(credentials: import_url.credentials)
+ else
+ super(value)
+ end
end
def import_url
@@ -811,18 +851,22 @@ class Project < ActiveRecord::Base
::Gitlab::CurrentSettings.mirror_available
end
- def check_limit
- unless creator.can_create_project? || namespace.kind == 'group'
- projects_limit = creator.projects_limit
+ def check_personal_projects_limit
+ # Since this method is called as validation hook, `creator` might not be
+ # present. Since the validation for that will fail, we can just return
+ # early.
+ return if !creator || creator.can_create_project? ||
+ namespace.kind == 'group'
- if projects_limit == 0
- self.errors.add(:limit_reached, "Personal project creation is not allowed. Please contact your administrator with questions")
+ limit = creator.projects_limit
+ error =
+ if limit.zero?
+ _('Personal project creation is not allowed. Please contact your administrator with questions')
else
- self.errors.add(:limit_reached, "Your project limit is #{projects_limit} projects! Please contact your administrator to increase it")
+ _('Your project limit is %{limit} projects! Please contact your administrator to increase it')
end
- end
- rescue
- self.errors.add(:base, "Can't check your ability to create project")
+
+ self.errors.add(:limit_reached, error % { limit: limit })
end
def visibility_level_allowed_by_group
@@ -913,11 +957,16 @@ class Project < ActiveRecord::Base
def new_issuable_address(author, address_type)
return unless Gitlab::IncomingEmail.supports_issue_creation? && author
+ # check since this can come from a request parameter
+ return unless %w(issue merge_request).include?(address_type)
+
author.ensure_incoming_email_token!
- suffix = address_type == 'merge_request' ? '+merge-request' : ''
- Gitlab::IncomingEmail.reply_address(
- "#{full_path}#{suffix}+#{author.incoming_email_token}")
+ suffix = address_type.dasherize
+
+ # example: incoming+h5bp-html5-boilerplate-8-1234567890abcdef123456789-issue@localhost.com
+ # example: incoming+h5bp-html5-boilerplate-8-1234567890abcdef123456789-merge-request@localhost.com
+ Gitlab::IncomingEmail.reply_address("#{full_path_slug}-#{project_id}-#{author.incoming_email_token}-#{suffix}")
end
def build_commit_note(commit)
@@ -1042,7 +1091,7 @@ class Project < ActiveRecord::Base
# rubocop: disable CodeReuse/ServiceClass
def create_labels
Label.templates.each do |label|
- params = label.attributes.except('id', 'template', 'created_at', 'updated_at')
+ params = label.attributes.except('id', 'template', 'created_at', 'updated_at', 'type')
Labels::FindOrCreateService.new(nil, self, params).execute(skip_authorization: true)
end
end
@@ -1171,7 +1220,7 @@ class Project < ActiveRecord::Base
"#{web_url}.git"
end
- # Is overriden in EE
+ # Is overridden in EE
def lfs_http_url_to_repo(_)
http_url_to_repo
end
@@ -1181,7 +1230,7 @@ class Project < ActiveRecord::Base
end
def fork_source
- return nil unless forked?
+ return unless forked?
forked_from_project || fork_network&.root_project
end
@@ -1252,7 +1301,7 @@ class Project < ActiveRecord::Base
# Forked import is handled asynchronously
return if forked? && !force
- if gitlab_shell.create_repository(repository_storage, disk_path)
+ if gitlab_shell.create_project_repository(self)
repository.after_create
true
else
@@ -1528,7 +1577,7 @@ class Project < ActiveRecord::Base
end
def pages_available?
- Gitlab.config.pages.enabled && !namespace.subgroup?
+ Gitlab.config.pages.enabled
end
def remove_private_deploy_keys
@@ -1578,6 +1627,13 @@ class Project < ActiveRecord::Base
def after_import
repository.after_import
wiki.repository.after_import
+
+ # The import assigns iid values on its own, e.g. by re-using GitHub ids.
+ # Flush existing InternalId records for this project for consistency reasons.
+ # Those records are going to be recreated with the next normal creation
+ # of a model instance (e.g. an Issue).
+ InternalId.flush_records!(project: self)
+
import_state.finish
import_state.remove_jid
update_project_counter_caches
@@ -1599,24 +1655,7 @@ class Project < ActiveRecord::Base
# rubocop: disable CodeReuse/ServiceClass
def after_create_default_branch
- return unless default_branch
-
- # Ensure HEAD points to the default branch in case it is not master
- change_head(default_branch)
-
- if Gitlab::CurrentSettings.default_branch_protection != Gitlab::Access::PROTECTION_NONE && !ProtectedBranch.protected?(self, default_branch)
- params = {
- name: default_branch,
- push_access_levels_attributes: [{
- access_level: Gitlab::CurrentSettings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_PUSH ? Gitlab::Access::DEVELOPER : Gitlab::Access::MAINTAINER
- }],
- merge_access_levels_attributes: [{
- access_level: Gitlab::CurrentSettings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE ? Gitlab::Access::DEVELOPER : Gitlab::Access::MAINTAINER
- }]
- }
-
- ProtectedBranches::CreateService.new(self, creator, params).execute(skip_authorization: true)
- end
+ Projects::ProtectDefaultBranchService.new(self).execute
end
# rubocop: enable CodeReuse/ServiceClass
@@ -1640,7 +1679,7 @@ class Project < ActiveRecord::Base
end
def export_path
- return nil unless namespace.present? || hashed_storage?(:repository)
+ return unless namespace.present? || hashed_storage?(:repository)
import_export_shared.archive_path
end
@@ -1699,8 +1738,23 @@ class Project < ActiveRecord::Base
.append(key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path)
.append(key: 'CI_PROJECT_URL', value: web_url)
.append(key: 'CI_PROJECT_VISIBILITY', value: visibility)
+ .concat(pages_variables)
.concat(container_registry_variables)
.concat(auto_devops_variables)
+ .concat(api_variables)
+ end
+
+ def pages_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.append(key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host)
+ variables.append(key: 'CI_PAGES_URL', value: pages_url)
+ end
+ end
+
+ def api_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.append(key: 'CI_API_V4_URL', value: API::Helpers::Version.new('v4').root_url)
+ end
end
def container_registry_variables
@@ -1734,10 +1788,21 @@ class Project < ActiveRecord::Base
end
def protected_for?(ref)
- if repository.branch_exists?(ref)
- ProtectedBranch.protected?(self, ref)
- elsif repository.tag_exists?(ref)
- ProtectedTag.protected?(self, ref)
+ raise Repository::AmbiguousRefError if repository.ambiguous_ref?(ref)
+
+ resolved_ref = repository.expand_ref(ref) || ref
+ return false unless Gitlab::Git.tag_ref?(resolved_ref) || Gitlab::Git.branch_ref?(resolved_ref)
+
+ ref_name = if resolved_ref == ref
+ Gitlab::Git.ref_name(resolved_ref)
+ else
+ ref
+ end
+
+ if Gitlab::Git.branch_ref?(resolved_ref)
+ ProtectedBranch.protected?(self, ref_name)
+ elsif Gitlab::Git.tag_ref?(resolved_ref)
+ ProtectedTag.protected?(self, ref_name)
end
end
@@ -1764,6 +1829,24 @@ class Project < ActiveRecord::Base
handle_update_attribute_error(e, value)
end
+ # Tries to set repository as read_only, checking for existing Git transfers in progress beforehand
+ #
+ # @return [Boolean] true when set to read_only or false when an existing git transfer is in progress
+ def set_repository_read_only!
+ with_lock do
+ break false if git_transfer_in_progress?
+
+ update_column(:repository_read_only, true)
+ end
+ end
+
+ # Set repository as writable again
+ def set_repository_writable!
+ with_lock do
+ update_column(:repository_read_only, false)
+ end
+ end
+
def pushes_since_gc
Gitlab::Redis::SharedState.with { |redis| redis.get(pushes_since_gc_redis_shared_state_key).to_i }
end
@@ -1847,6 +1930,14 @@ class Project < ActiveRecord::Base
persisted? && path_changed?
end
+ def human_merge_method
+ if merge_method == :ff
+ 'Fast-forward'
+ else
+ merge_method.to_s.humanize
+ end
+ end
+
def merge_method
if self.merge_requests_ff_only_enabled
:ff
@@ -1878,15 +1969,27 @@ class Project < ActiveRecord::Base
def migrate_to_hashed_storage!
return unless storage_upgradable?
- update!(repository_read_only: true)
+ if git_transfer_in_progress?
+ HashedStorage::ProjectMigrateWorker.perform_in(Gitlab::ReferenceCounter::REFERENCE_EXPIRE_TIME, id)
+ else
+ HashedStorage::ProjectMigrateWorker.perform_async(id)
+ end
+ end
+
+ def rollback_to_legacy_storage!
+ return if legacy_storage?
- if repo_reference_count > 0 || wiki_reference_count > 0
- ProjectMigrateHashedStorageWorker.perform_in(Gitlab::ReferenceCounter::REFERENCE_EXPIRE_TIME, id)
+ if git_transfer_in_progress?
+ HashedStorage::ProjectRollbackWorker.perform_in(Gitlab::ReferenceCounter::REFERENCE_EXPIRE_TIME, id)
else
- ProjectMigrateHashedStorageWorker.perform_async(id)
+ HashedStorage::ProjectRollbackWorker.perform_async(id)
end
end
+ def git_transfer_in_progress?
+ repo_reference_count > 0 || wiki_reference_count > 0
+ end
+
def storage_version=(value)
super
@@ -1918,23 +2021,15 @@ class Project < ActiveRecord::Base
.where('project_authorizations.project_id = merge_requests.target_project_id')
.limit(1)
.select(1)
- source_of_merge_requests.opened
- .where(allow_collaboration: true)
- .where('EXISTS (?)', developer_access_exists)
+ merge_requests_allowing_collaboration.where('EXISTS (?)', developer_access_exists)
end
- def branch_allows_collaboration?(user, branch_name)
- return false unless user
-
- cache_key = "user:#{user.id}:#{branch_name}:branch_allows_push"
-
- memoized_results = strong_memoize(:branch_allows_collaboration) do
- Hash.new do |result, cache_key|
- result[cache_key] = fetch_branch_allows_collaboration?(user, branch_name)
- end
- end
+ def any_branch_allows_collaboration?(user)
+ fetch_branch_allows_collaboration(user)
+ end
- memoized_results[cache_key]
+ def branch_allows_collaboration?(user, branch_name)
+ fetch_branch_allows_collaboration(user, branch_name)
end
def licensed_features
@@ -2003,11 +2098,25 @@ class Project < ActiveRecord::Base
end
def leave_pool_repository
- pool_repository&.unlink_repository(repository)
+ pool_repository&.unlink_repository(repository) && update_column(:pool_repository_id, nil)
+ end
+
+ def link_pool_repository
+ pool_repository&.link_repository(repository)
+ end
+
+ def has_pool_repository?
+ pool_repository.present?
end
private
+ def merge_requests_allowing_collaboration(source_branch = nil)
+ relation = source_of_merge_requests.opened.where(allow_collaboration: true)
+ relation = relation.where(source_branch: source_branch) if source_branch
+ relation
+ end
+
def create_new_pool_repository
pool = begin
create_pool_repository!(shard: Shard.by_name(repository_storage), source_project: self)
@@ -2132,26 +2241,19 @@ class Project < ActiveRecord::Base
raise ex
end
- def fetch_branch_allows_collaboration?(user, branch_name)
- check_access = -> do
- next false if empty_repo?
+ def fetch_branch_allows_collaboration(user, branch_name = nil)
+ return false unless user
- merge_requests = source_of_merge_requests.opened
- .where(allow_collaboration: true)
+ Gitlab::SafeRequestStore.fetch("project-#{id}:branch-#{branch_name}:user-#{user.id}:branch_allows_collaboration") do
+ next false if empty_repo?
# Issue for N+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/49322
Gitlab::GitalyClient.allow_n_plus_1_calls do
- if branch_name
- merge_requests.find_by(source_branch: branch_name)&.can_be_merged_by?(user)
- else
- merge_requests.any? { |merge_request| merge_request.can_be_merged_by?(user) }
+ merge_requests_allowing_collaboration(branch_name).any? do |merge_request|
+ merge_request.can_be_merged_by?(user)
end
end
end
-
- Gitlab::SafeRequestStore.fetch("project-#{id}:branch-#{branch_name}:user-#{user.id}:branch_allows_collaboration") do
- check_access.call
- end
end
def services_templates
diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb
index 2253ad7b543..e353a6443c4 100644
--- a/app/models/project_auto_devops.rb
+++ b/app/models/project_auto_devops.rb
@@ -24,6 +24,12 @@ class ProjectAutoDevops < ActiveRecord::Base
domain.present? || instance_domain.present?
end
+ # From 11.8, AUTO_DEVOPS_DOMAIN has been replaced by KUBE_INGRESS_BASE_DOMAIN.
+ # See Clusters::Cluster#predefined_variables and https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24580
+ # for more info.
+ #
+ # Suppport AUTO_DEVOPS_DOMAIN is scheduled to be removed on
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/52363
def predefined_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
if has_domain?
diff --git a/app/models/project_daily_statistic.rb b/app/models/project_daily_statistic.rb
new file mode 100644
index 00000000000..ff115dd010f
--- /dev/null
+++ b/app/models/project_daily_statistic.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class ProjectDailyStatistic < ActiveRecord::Base
+ belongs_to :project
+
+ scope :of_project, -> (project) { where(project: project) }
+ scope :of_last_30_days, -> { where('date >= ?', 29.days.ago.utc.to_date) }
+ scope :sorted_by_date_desc, -> { order(project_id: :desc, date: :desc) }
+ scope :sum_fetch_count, -> { sum(:fetch_count) }
+end
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index 39f2b8fe0de..e6787236c4e 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -23,11 +23,11 @@ class ProjectFeature < ActiveRecord::Base
PUBLIC = 30
FEATURES = %i(issues merge_requests wiki snippets builds repository pages).freeze
+ PRIVATE_FEATURES_MIN_ACCESS_LEVEL = { merge_requests: Gitlab::Access::REPORTER }.freeze
class << self
def access_level_attribute(feature)
- feature = feature.model_name.plural.to_sym if feature.respond_to?(:model_name)
- raise ArgumentError, "invalid project feature: #{feature}" unless FEATURES.include?(feature)
+ feature = ensure_feature!(feature)
"#{feature}_access_level".to_sym
end
@@ -38,6 +38,21 @@ class ProjectFeature < ActiveRecord::Base
"#{table}.#{attribute}"
end
+
+ def required_minimum_access_level(feature)
+ feature = ensure_feature!(feature)
+
+ PRIVATE_FEATURES_MIN_ACCESS_LEVEL.fetch(feature, Gitlab::Access::GUEST)
+ end
+
+ private
+
+ def ensure_feature!(feature)
+ feature = feature.model_name.plural.to_sym if feature.respond_to?(:model_name)
+ raise ArgumentError, "invalid project feature: #{feature}" unless FEATURES.include?(feature)
+
+ feature
+ end
end
# Default scopes force us to unscope here since a service may need to check
@@ -61,7 +76,7 @@ class ProjectFeature < ActiveRecord::Base
# This feature might not be behind a feature flag at all, so default to true
return false unless ::Feature.enabled?(feature, user, default_enabled: true)
- get_permission(user, access_level(feature))
+ get_permission(user, feature)
end
def access_level(feature)
@@ -119,12 +134,12 @@ class ProjectFeature < ActiveRecord::Base
(FEATURES - %i(pages)).each {|f| validator.call("#{f}_access_level")}
end
- def get_permission(user, level)
- case level
+ def get_permission(user, feature)
+ case access_level(feature)
when DISABLED
false
when PRIVATE
- user && (project.team.member?(user) || user.full_private_access?)
+ team_access?(user, feature)
when ENABLED
true
when PUBLIC
@@ -133,4 +148,11 @@ class ProjectFeature < ActiveRecord::Base
true
end
end
+
+ def team_access?(user, feature)
+ return unless user
+ return true if user.full_private_access?
+
+ project.team.member?(user, ProjectFeature.required_minimum_access_level(feature))
+ end
end
diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb
index 525725034a5..aa0c121fe99 100644
--- a/app/models/project_import_data.rb
+++ b/app/models/project_import_data.rb
@@ -30,4 +30,8 @@ class ProjectImportData < ActiveRecord::Base
def merge_credentials(hash)
self.credentials = credentials.to_h.merge(hash) unless hash.empty?
end
+
+ def clear_credentials
+ self.credentials = {}
+ end
end
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index a252052200a..71f5607dbdb 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -80,19 +80,27 @@ class BambooService < CiService
private
- def get_build_result_index
- # When Bamboo returns multiple results for a given changeset, arbitrarily assume the most relevant result to be the last one.
- -1
+ def get_build_result(response)
+ return if response.code != 200
+
+ # May be nil if no result, a single result hash, or an array if multiple results for a given changeset.
+ result = response.dig('results', 'results', 'result')
+
+ # In case of multiple results, arbitrarily assume the last one is the most relevant.
+ return result.last if result.is_a?(Array)
+
+ result
end
def read_build_page(response)
+ result = get_build_result(response)
key =
- if response.code != 200 || response.dig('results', 'results', 'size') == '0'
+ if result.blank?
# If actual build link can't be determined, send user to build summary page.
build_key
else
# If actual build link is available, go to build result page.
- response.dig('results', 'results', 'result', get_build_result_index, 'planResultKey', 'key')
+ result.dig('planResultKey', 'key')
end
build_url("browse/#{key}")
@@ -101,11 +109,15 @@ class BambooService < CiService
def read_commit_status(response)
return :error unless response.code == 200 || response.code == 404
- status = if response.code == 404 || response.dig('results', 'results', 'size') == '0'
- 'Pending'
- else
- response.dig('results', 'results', 'result', get_build_result_index, 'buildState')
- end
+ result = get_build_result(response)
+ status =
+ if result.blank?
+ 'Pending'
+ else
+ result.dig('buildState')
+ end
+
+ return :error unless status.present?
if status.include?('Success')
'success'
diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb
index 1d7877a1fb5..ad26e42a21b 100644
--- a/app/models/project_services/campfire_service.rb
+++ b/app/models/project_services/campfire_service.rb
@@ -57,7 +57,7 @@ class CampfireService < Service
# https://github.com/basecamp/campfire-api/blob/master/sections/messages.md#create-message
def speak(room_name, message, auth)
room = rooms(auth).find { |r| r["name"] == room_name }
- return nil unless room
+ return unless room
path = "/room/#{room["id"]}/speak.json"
body = {
diff --git a/app/models/project_services/deployment_service.rb b/app/models/project_services/deployment_service.rb
index 6dae4f3a4a6..80aa2101509 100644
--- a/app/models/project_services/deployment_service.rb
+++ b/app/models/project_services/deployment_service.rb
@@ -11,7 +11,7 @@ class DeploymentService < Service
%w()
end
- def predefined_variables
+ def predefined_variables(project:)
[]
end
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
deleted file mode 100644
index a69b7b4c4b6..00000000000
--- a/app/models/project_services/hipchat_service.rb
+++ /dev/null
@@ -1,311 +0,0 @@
-# frozen_string_literal: true
-
-class HipchatService < Service
- include ActionView::Helpers::SanitizeHelper
-
- MAX_COMMITS = 3
- HIPCHAT_ALLOWED_TAGS = %w[
- a b i strong em br img pre code
- table th tr td caption colgroup col thead tbody tfoot
- ul ol li dl dt dd
- ].freeze
-
- prop_accessor :token, :room, :server, :color, :api_version
- boolean_accessor :notify_only_broken_pipelines, :notify
- validates :token, presence: true, if: :activated?
-
- def initialize_properties
- if properties.nil?
- self.properties = {}
- self.notify_only_broken_pipelines = true
- end
- end
-
- def title
- 'HipChat'
- end
-
- def description
- 'Private group chat and IM'
- end
-
- def self.to_param
- 'hipchat'
- end
-
- def fields
- [
- { type: 'text', name: 'token', placeholder: 'Room token', required: true },
- { type: 'text', name: 'room', placeholder: 'Room name or ID' },
- { type: 'checkbox', name: 'notify' },
- { type: 'select', name: 'color', choices: %w(yellow red green purple gray random) },
- { type: 'text', name: 'api_version',
- placeholder: 'Leave blank for default (v2)' },
- { type: 'text', name: 'server',
- placeholder: 'Leave blank for default. https://hipchat.example.com' },
- { type: 'checkbox', name: 'notify_only_broken_pipelines' }
- ]
- end
-
- def self.supported_events
- %w(push issue confidential_issue merge_request note confidential_note tag_push pipeline)
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- message = create_message(data)
- return unless message.present?
-
- gate[room].send('GitLab', message, message_options(data)) # rubocop:disable GitlabSecurity/PublicSend
- end
-
- def test(data)
- begin
- result = execute(data)
- rescue StandardError => error
- return { success: false, result: error }
- end
-
- { success: true, result: result }
- end
-
- private
-
- def gate
- options = { api_version: api_version.present? ? api_version : 'v2' }
- options[:server_url] = server unless server.blank?
- @gate ||= HipChat::Client.new(token, options)
- end
-
- def message_options(data = nil)
- { notify: notify.present? && Gitlab::Utils.to_boolean(notify), color: message_color(data) }
- end
-
- def create_message(data)
- object_kind = data[:object_kind]
-
- case object_kind
- when "push", "tag_push"
- create_push_message(data)
- when "issue"
- create_issue_message(data) unless update?(data)
- when "merge_request"
- create_merge_request_message(data) unless update?(data)
- when "note"
- create_note_message(data)
- when "pipeline"
- create_pipeline_message(data) if should_pipeline_be_notified?(data)
- end
- end
-
- def render_line(text)
- markdown(text.lines.first.chomp, pipeline: :single_line) if text
- end
-
- def create_push_message(push)
- ref_type = Gitlab::Git.tag_ref?(push[:ref]) ? 'tag' : 'branch'
- ref = Gitlab::Git.ref_name(push[:ref])
-
- before = push[:before]
- after = push[:after]
-
- message = []
- message << "#{push[:user_name]} "
-
- if Gitlab::Git.blank_ref?(before)
- message << "pushed new #{ref_type} <a href=\""\
- "#{project_url}/commits/#{CGI.escape(ref)}\">#{ref}</a>"\
- " to #{project_link}\n"
- elsif Gitlab::Git.blank_ref?(after)
- message << "removed #{ref_type} <b>#{ref}</b> from <a href=\"#{project.web_url}\">#{project_name}</a> \n"
- else
- message << "pushed to #{ref_type} <a href=\""\
- "#{project.web_url}/commits/#{CGI.escape(ref)}\">#{ref}</a> "
- message << "of <a href=\"#{project.web_url}\">#{project.full_name.gsub!(/\s/, '')}</a> "
- message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)"
-
- push[:commits].take(MAX_COMMITS).each do |commit|
- message << "<br /> - #{render_line(commit[:message])} (<a href=\"#{commit[:url]}\">#{commit[:id][0..5]}</a>)"
- end
-
- if push[:commits].count > MAX_COMMITS
- message << "<br />... #{push[:commits].count - MAX_COMMITS} more commits"
- end
- end
-
- message.join
- end
-
- def markdown(text, options = {})
- return "" unless text
-
- context = {
- project: project,
- pipeline: :email
- }
-
- Banzai.render(text, context)
-
- context.merge!(options)
-
- html = Banzai.render_and_post_process(text, context)
- sanitized_html = sanitize(html, tags: HIPCHAT_ALLOWED_TAGS, attributes: %w[href title alt])
-
- sanitized_html.truncate(200, separator: ' ', omission: '...')
- end
-
- def create_issue_message(data)
- user_name = data[:user][:name]
-
- obj_attr = data[:object_attributes]
- obj_attr = HashWithIndifferentAccess.new(obj_attr)
- title = render_line(obj_attr[:title])
- state = obj_attr[:state]
- issue_iid = obj_attr[:iid]
- issue_url = obj_attr[:url]
- description = obj_attr[:description]
-
- issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>"
-
- message = ["#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"]
- message << "<pre>#{markdown(description)}</pre>"
-
- message.join
- end
-
- def create_merge_request_message(data)
- user_name = data[:user][:name]
-
- obj_attr = data[:object_attributes]
- obj_attr = HashWithIndifferentAccess.new(obj_attr)
- merge_request_id = obj_attr[:iid]
- state = obj_attr[:state]
- description = obj_attr[:description]
- title = render_line(obj_attr[:title])
-
- merge_request_url = "#{project_url}/merge_requests/#{merge_request_id}"
- merge_request_link = "<a href=\"#{merge_request_url}\">merge request !#{merge_request_id}</a>"
- message = ["#{user_name} #{state} #{merge_request_link} in " \
- "#{project_link}: <b>#{title}</b>"]
-
- message << "<pre>#{markdown(description)}</pre>"
- message.join
- end
-
- def format_title(title)
- "<b>#{render_line(title)}</b>"
- end
-
- def create_note_message(data)
- data = HashWithIndifferentAccess.new(data)
- user_name = data[:user][:name]
-
- obj_attr = HashWithIndifferentAccess.new(data[:object_attributes])
- note = obj_attr[:note]
- note_url = obj_attr[:url]
- noteable_type = obj_attr[:noteable_type]
- commit_id = nil
-
- case noteable_type
- when "Commit"
- commit_attr = HashWithIndifferentAccess.new(data[:commit])
- commit_id = commit_attr[:id]
- subject_desc = commit_id
- subject_desc = Commit.truncate_sha(subject_desc)
- subject_type = "commit"
- title = format_title(commit_attr[:message])
- when "Issue"
- subj_attr = HashWithIndifferentAccess.new(data[:issue])
- subject_id = subj_attr[:iid]
- subject_desc = "##{subject_id}"
- subject_type = "issue"
- title = format_title(subj_attr[:title])
- when "MergeRequest"
- subj_attr = HashWithIndifferentAccess.new(data[:merge_request])
- subject_id = subj_attr[:iid]
- subject_desc = "!#{subject_id}"
- subject_type = "merge request"
- title = format_title(subj_attr[:title])
- when "Snippet"
- subj_attr = HashWithIndifferentAccess.new(data[:snippet])
- subject_id = subj_attr[:id]
- subject_desc = "##{subject_id}"
- subject_type = "snippet"
- title = format_title(subj_attr[:title])
- end
-
- subject_html = "<a href=\"#{note_url}\">#{subject_type} #{subject_desc}</a>"
- message = ["#{user_name} commented on #{subject_html} in #{project_link}: "]
- message << title
-
- message << "<pre>#{markdown(note, ref: commit_id)}</pre>"
- message.join
- end
-
- def create_pipeline_message(data)
- pipeline_attributes = data[:object_attributes]
- pipeline_id = pipeline_attributes[:id]
- ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch'
- ref = pipeline_attributes[:ref]
- user_name = (data[:user] && data[:user][:name]) || 'API'
- status = pipeline_attributes[:status]
- duration = pipeline_attributes[:duration]
-
- branch_link = "<a href=\"#{project_url}/commits/#{CGI.escape(ref)}\">#{ref}</a>"
- pipeline_url = "<a href=\"#{project_url}/pipelines/#{pipeline_id}\">##{pipeline_id}</a>"
-
- "#{project_link}: Pipeline #{pipeline_url} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status(status)} in #{duration} second(s)"
- end
-
- def message_color(data)
- pipeline_status_color(data) || color || 'yellow'
- end
-
- def pipeline_status_color(data)
- return unless data && data[:object_kind] == 'pipeline'
-
- case data[:object_attributes][:status]
- when 'success'
- 'green'
- else
- 'red'
- end
- end
-
- def project_name
- project.full_name.gsub(/\s/, '')
- end
-
- def project_url
- project.web_url
- end
-
- def project_link
- "<a href=\"#{project_url}\">#{project_name}</a>"
- end
-
- def update?(data)
- data[:object_attributes][:action] == 'update'
- end
-
- def humanized_status(status)
- case status
- when 'success'
- 'passed'
- else
- status
- end
- end
-
- def should_pipeline_be_notified?(data)
- case data[:object_attributes][:status]
- when 'success'
- !notify_only_broken_pipelines?
- when 'failed'
- true
- else
- false
- end
- end
-end
diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb
index a15780c14f9..fb76bc89c98 100644
--- a/app/models/project_services/irker_service.rb
+++ b/app/models/project_services/irker_service.rb
@@ -59,7 +59,7 @@ class IrkerService < Service
' append "?key=secretpassword" to the URI (Note that due to a bug, if you ' \
' want to use a password, you have to omit the "#" on the channel). If you ' \
' specify a default IRC URI to prepend before each recipient, you can just ' \
- ' give a channel name.' },
+ ' give a channel name.' },
{ type: 'checkbox', name: 'colorize_messages' }
]
end
@@ -112,7 +112,7 @@ class IrkerService < Service
end
def consider_uri(uri)
- return nil if uri.scheme.nil?
+ return if uri.scheme.nil?
# Authorize both irc://domain.com/#chan and irc://domain.com/chan
if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil?
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 9066a0b7f1d..f7064d5aaea 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -215,7 +215,7 @@ class JiraService < IssueTrackerService
end
def add_issue_solved_comment(issue, commit_id, commit_url)
- link_title = "GitLab: Solved by commit #{commit_id}."
+ link_title = "Solved by commit #{commit_id}."
comment = "Issue solved with [#{commit_id}|#{commit_url}]."
link_props = build_remote_link_props(url: commit_url, title: link_title, resolved: true)
send_message(issue, comment, link_props)
@@ -230,7 +230,7 @@ class JiraService < IssueTrackerService
project_name = data[:project][:name]
message = "[#{user_name}|#{user_url}] mentioned this issue in [a #{entity_name} of #{project_name}|#{entity_url}]:\n'#{entity_title.chomp}'"
- link_title = "GitLab: Mentioned on #{entity_name} - #{entity_title}"
+ link_title = "#{entity_name.capitalize} - #{entity_title}"
link_props = build_remote_link_props(url: entity_url, title: link_title)
unless comment_exists?(issue, message)
@@ -278,6 +278,7 @@ class JiraService < IssueTrackerService
{
GlobalID: 'GitLab',
+ relationship: 'mentioned on',
object: {
url: url,
title: title,
diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb
index b801fd84a07..f69edd60003 100644
--- a/app/models/project_services/kubernetes_service.rb
+++ b/app/models/project_services/kubernetes_service.rb
@@ -53,7 +53,7 @@ class KubernetesService < DeploymentService
end
def description
- 'Kubernetes / Openshift integration'
+ 'Kubernetes / OpenShift integration'
end
def help
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index 60cb2d380d5..c68a9d923c8 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -71,7 +71,7 @@ class PrometheusService < MonitoringService
end
def prometheus_client
- RestClient::Resource.new(api_url, max_redirects: 0) if api_url && manual_configuration? && active?
+ RestClient::Resource.new(api_url, max_redirects: 0) if should_return_client?
end
def prometheus_available?
@@ -83,6 +83,10 @@ class PrometheusService < MonitoringService
private
+ def should_return_client?
+ api_url && manual_configuration? && active? && valid?
+ end
+
def synchronize_service_state
self.active = prometheus_available? || manual_configuration?
diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb
index 6c82e088231..6a454070fe2 100644
--- a/app/models/project_services/slack_slash_commands_service.rb
+++ b/app/models/project_services/slack_slash_commands_service.rb
@@ -22,6 +22,10 @@ class SlackSlashCommandsService < SlashCommandsService
end
end
+ def chat_responder
+ ::Gitlab::Chat::Responder::Slack
+ end
+
private
def format(text)
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index b8e17087db5..3245cd22e73 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -39,9 +39,7 @@ class TeamcityService < CiService
end
def help
- 'The build configuration in Teamcity must use the build format '\
- 'number %build.vcs.number% '\
- 'you will also want to configure monitoring of all branches so merge '\
+ 'You will want to configure monitoring of all branches so merge '\
'requests build, that setting is in the vsc root advanced settings.'
end
@@ -70,7 +68,7 @@ class TeamcityService < CiService
end
def calculate_reactive_cache(sha, ref)
- response = get_path("httpAuth/app/rest/builds/branch:unspecified:any,number:#{sha}")
+ response = get_path("httpAuth/app/rest/builds/branch:unspecified:any,revision:#{sha}")
{ build_page: read_build_page(response), commit_status: read_commit_status(response) }
end
diff --git a/app/models/project_services/youtrack_service.rb b/app/models/project_services/youtrack_service.rb
new file mode 100644
index 00000000000..957be685aea
--- /dev/null
+++ b/app/models/project_services/youtrack_service.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class YoutrackService < IssueTrackerService
+ validates :project_url, :issues_url, presence: true, public_url: true, if: :activated?
+
+ prop_accessor :description, :project_url, :issues_url
+
+ # {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1
+ def self.reference_pattern(only_long: false)
+ if only_long
+ /(?<issue>\b[A-Z][A-Za-z0-9_]*-\d+)/
+ else
+ /(?<issue>\b[A-Z][A-Za-z0-9_]*-\d+)|(#{Issue.reference_prefix}(?<issue>\d+))/
+ end
+ end
+
+ def title
+ 'YouTrack'
+ end
+
+ def description
+ if self.properties && self.properties['description'].present?
+ self.properties['description']
+ else
+ 'YouTrack issue tracker'
+ end
+ end
+
+ def self.to_param
+ 'youtrack'
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'description', placeholder: description },
+ { type: 'text', name: 'project_url', placeholder: 'Project url', required: true },
+ { type: 'text', name: 'issues_url', placeholder: 'Issue url', required: true }
+ ]
+ end
+end
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 33bc6a561f9..aeba2843e5d 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -74,6 +74,14 @@ class ProjectTeam
end
alias_method :users, :members
+ # `members` method uses project_authorizations table which
+ # is updated asynchronously, on project move it still contains
+ # old members who may not have access to the new location,
+ # so we filter out only members of project or project's group
+ def members_in_project_and_ancestors
+ members.where(id: member_user_ids)
+ end
+
def guests
@guests ||= fetch_members(Gitlab::Access::GUEST)
end
@@ -191,4 +199,8 @@ class ProjectTeam
def group
project.group
end
+
+ def member_user_ids
+ Member.on_project_and_ancestors(project).select(:user_id)
+ end
end
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 559e4f99294..c43bd45a62f 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -60,7 +60,7 @@ class ProjectWiki
def wiki
@wiki ||= begin
gl_repository = Gitlab::GlRepository.gl_repository(project, true)
- raw_repository = Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', gl_repository)
+ raw_repository = Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', gl_repository, full_path)
create_repo!(raw_repository) unless raw_repository.exists?
@@ -175,7 +175,7 @@ class ProjectWiki
private
def create_repo!(raw_repository)
- gitlab_shell.create_repository(project.repository_storage, disk_path)
+ gitlab_shell.create_wiki_repository(project)
raise CouldNotCreateWikiError unless raw_repository.exists?
diff --git a/app/models/prometheus_metric.rb b/app/models/prometheus_metric.rb
index defbade1ed6..5594594a48d 100644
--- a/app/models/prometheus_metric.rb
+++ b/app/models/prometheus_metric.rb
@@ -18,6 +18,54 @@ class PrometheusMetric < ActiveRecord::Base
system: 2
}
+ GROUP_DETAILS = {
+ # built-in groups
+ nginx_ingress_vts: {
+ group_title: _('Response metrics (NGINX Ingress VTS)'),
+ required_metrics: %w(nginx_upstream_responses_total nginx_upstream_response_msecs_avg),
+ priority: 10
+ }.freeze,
+ nginx_ingress: {
+ group_title: _('Response metrics (NGINX Ingress)'),
+ required_metrics: %w(nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum),
+ priority: 10
+ }.freeze,
+ ha_proxy: {
+ group_title: _('Response metrics (HA Proxy)'),
+ required_metrics: %w(haproxy_frontend_http_requests_total haproxy_frontend_http_responses_total),
+ priority: 10
+ }.freeze,
+ aws_elb: {
+ group_title: _('Response metrics (AWS ELB)'),
+ required_metrics: %w(aws_elb_request_count_sum aws_elb_latency_average aws_elb_httpcode_backend_5_xx_sum),
+ priority: 10
+ }.freeze,
+ nginx: {
+ group_title: _('Response metrics (NGINX)'),
+ required_metrics: %w(nginx_server_requests nginx_server_requestMsec),
+ priority: 10
+ }.freeze,
+ kubernetes: {
+ group_title: _('System metrics (Kubernetes)'),
+ required_metrics: %w(container_memory_usage_bytes container_cpu_usage_seconds_total),
+ priority: 5
+ }.freeze,
+
+ # custom/user groups
+ business: {
+ group_title: _('Business metrics (Custom)'),
+ priority: 0
+ }.freeze,
+ response: {
+ group_title: _('Response metrics (Custom)'),
+ priority: -5
+ }.freeze,
+ system: {
+ group_title: _('System metrics (Custom)'),
+ priority: -10
+ }.freeze
+ }.freeze
+
validates :title, presence: true
validates :query, presence: true
validates :group, presence: true
@@ -29,36 +77,16 @@ class PrometheusMetric < ActiveRecord::Base
scope :common, -> { where(common: true) }
- GROUP_TITLES = {
- # built-in groups
- nginx_ingress_vts: _('Response metrics (NGINX Ingress VTS)'),
- nginx_ingress: _('Response metrics (NGINX Ingress)'),
- ha_proxy: _('Response metrics (HA Proxy)'),
- aws_elb: _('Response metrics (AWS ELB)'),
- nginx: _('Response metrics (NGINX)'),
- kubernetes: _('System metrics (Kubernetes)'),
-
- # custom/user groups
- business: _('Business metrics (Custom)'),
- response: _('Response metrics (Custom)'),
- system: _('System metrics (Custom)')
- }.freeze
-
- REQUIRED_METRICS = {
- nginx_ingress_vts: %w(nginx_upstream_responses_total nginx_upstream_response_msecs_avg),
- nginx_ingress: %w(nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum),
- ha_proxy: %w(haproxy_frontend_http_requests_total haproxy_frontend_http_responses_total),
- aws_elb: %w(aws_elb_request_count_sum aws_elb_latency_average aws_elb_httpcode_backend_5_xx_sum),
- nginx: %w(nginx_server_requests nginx_server_requestMsec),
- kubernetes: %w(container_memory_usage_bytes container_cpu_usage_seconds_total)
- }.freeze
+ def priority
+ group_details(group).fetch(:priority)
+ end
def group_title
- GROUP_TITLES[group.to_sym]
+ group_details(group).fetch(:group_title)
end
def required_metrics
- REQUIRED_METRICS[group.to_sym].to_a.map(&:to_s)
+ group_details(group).fetch(:required_metrics, []).map(&:to_s)
end
def to_query_metric
@@ -89,4 +117,10 @@ class PrometheusMetric < ActiveRecord::Base
}]
end
end
+
+ private
+
+ def group_details(group)
+ GROUP_DETAILS.fetch(group.to_sym)
+ end
end
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index d075440b147..597431be65a 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -18,13 +18,23 @@ class ProtectedBranch < ActiveRecord::Base
def self.protected?(project, ref_name)
return true if project.empty_repo? && default_branch_protected?
- refs = project.protected_branches.select(:name)
+ self.matching(ref_name, protected_refs: protected_refs(project)).present?
+ end
- self.matching(ref_name, protected_refs: refs).present?
+ def self.any_protected?(project, ref_names)
+ protected_refs(project).any? do |protected_ref|
+ ref_names.any? do |ref_name|
+ protected_ref.matches?(ref_name)
+ end
+ end
end
def self.default_branch_protected?
Gitlab::CurrentSettings.default_branch_protection == Gitlab::Access::PROTECTION_FULL ||
Gitlab::CurrentSettings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE
end
+
+ def self.protected_refs(project)
+ project.protected_branches.select(:name)
+ end
end
diff --git a/app/models/release.rb b/app/models/release.rb
index 7a09ee459a6..0dae5c90394 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -2,11 +2,53 @@
class Release < ActiveRecord::Base
include CacheMarkdownField
+ include Gitlab::Utils::StrongMemoize
cache_markdown_field :description
belongs_to :project
+ # releases prior to 11.7 have no author
belongs_to :author, class_name: 'User'
+ has_many :links, class_name: 'Releases::Link'
+
+ accepts_nested_attributes_for :links, allow_destroy: true
+
validates :description, :project, :tag, presence: true
+
+ scope :sorted, -> { order(created_at: :desc) }
+
+ delegate :repository, to: :project
+
+ def commit
+ strong_memoize(:commit) do
+ repository.commit(actual_sha)
+ end
+ end
+
+ def tag_missing?
+ actual_tag.nil?
+ end
+
+ def assets_count
+ links.count + sources.count
+ end
+
+ def sources
+ strong_memoize(:sources) do
+ Releases::Source.all(project, tag)
+ end
+ end
+
+ private
+
+ def actual_sha
+ sha || actual_tag&.dereferenced_target
+ end
+
+ def actual_tag
+ strong_memoize(:actual_tag) do
+ repository.find_tag(tag)
+ end
+ end
end
diff --git a/app/models/releases/link.rb b/app/models/releases/link.rb
new file mode 100644
index 00000000000..6c507c47752
--- /dev/null
+++ b/app/models/releases/link.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Releases
+ class Link < ActiveRecord::Base
+ self.table_name = 'release_links'
+
+ belongs_to :release
+
+ validates :url, presence: true, url: { protocols: %w(http https ftp) }, uniqueness: { scope: :release }
+ validates :name, presence: true, uniqueness: { scope: :release }
+
+ scope :sorted, -> { order(created_at: :desc) }
+
+ def internal?
+ url.start_with?(release.project.web_url)
+ end
+
+ def external?
+ !internal?
+ end
+ end
+end
diff --git a/app/models/releases/source.rb b/app/models/releases/source.rb
new file mode 100644
index 00000000000..4d3d54457af
--- /dev/null
+++ b/app/models/releases/source.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Releases
+ class Source
+ include ActiveModel::Model
+
+ attr_accessor :project, :tag_name, :format
+
+ FORMATS = %w(zip tar.gz tar.bz2 tar).freeze
+
+ class << self
+ def all(project, tag_name)
+ Releases::Source::FORMATS.map do |format|
+ Releases::Source.new(project: project,
+ tag_name: tag_name,
+ format: format)
+ end
+ end
+ end
+
+ def url
+ Gitlab::Routing
+ .url_helpers
+ .project_archive_url(project,
+ id: File.join(tag_name, archive_prefix),
+ format: format)
+ end
+
+ private
+
+ def archive_prefix
+ "#{project.path}-#{tag_name.tr('/', '-')}"
+ end
+ end
+end
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index 5a6895aefab..5eba7ddd75c 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -17,7 +17,7 @@ class RemoteMirror < ActiveRecord::Base
belongs_to :project, inverse_of: :remote_mirrors
- validates :url, presence: true, url: { protocols: %w(ssh git http https), allow_blank: true, enforce_user: true }
+ validates :url, presence: true, public_url: { protocols: %w(ssh git http https), allow_blank: true, enforce_user: true }
before_save :set_new_remote_name, if: :mirror_url_changed?
@@ -61,7 +61,10 @@ class RemoteMirror < ActiveRecord::Base
timestamp = Time.now
remote_mirror.update!(
- last_update_at: timestamp, last_successful_update_at: timestamp, last_error: nil
+ last_update_at: timestamp,
+ last_successful_update_at: timestamp,
+ last_error: nil,
+ error_notification_sent: false
)
end
@@ -179,6 +182,10 @@ class RemoteMirror < ActiveRecord::Base
project.repository.add_remote(remote_name, remote_url)
end
+ def after_sent_notification
+ update_column(:error_notification_sent, true)
+ end
+
private
def store_credentials
@@ -221,7 +228,8 @@ class RemoteMirror < ActiveRecord::Base
last_error: nil,
last_update_at: nil,
last_successful_update_at: nil,
- update_status: 'finished'
+ update_status: 'finished',
+ error_notification_sent: false
)
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 015a179f374..851175a61b7 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -25,6 +25,7 @@ class Repository
delegate :bundle_to_disk, to: :raw_repository
CreateTreeError = Class.new(StandardError)
+ AmbiguousRefError = Class.new(StandardError)
# Methods that cache data from the Git repository.
#
@@ -78,7 +79,7 @@ class Repository
end
def raw_repository
- return nil unless full_path
+ return unless full_path
@raw_repository ||= initialize_raw_repository
end
@@ -102,7 +103,7 @@ class Repository
end
def commit(ref = nil)
- return nil unless exists?
+ return unless exists?
return ref if ref.is_a?(::Commit)
find_commit(ref || root_ref)
@@ -181,6 +182,18 @@ class Repository
tags.find { |tag| tag.name == name }
end
+ def ambiguous_ref?(ref)
+ tag_exists?(ref) && branch_exists?(ref)
+ end
+
+ def expand_ref(ref)
+ if tag_exists?(ref)
+ Gitlab::Git::TAG_REF_PREFIX + ref
+ elsif branch_exists?(ref)
+ Gitlab::Git::BRANCH_REF_PREFIX + ref
+ end
+ end
+
def add_branch(user, branch_name, ref)
branch = raw_repository.add_branch(branch_name, user: user, target: ref)
@@ -275,13 +288,16 @@ class Repository
# Rugged seems to throw a `ReferenceError` when given branch_names rather
# than SHA-1 hashes
number_commits_behind, number_commits_ahead =
- raw_repository.count_commits_between(
+ raw_repository.diverging_commit_count(
@root_ref_hash,
branch.dereferenced_target.sha,
- left_right: true,
max_count: MAX_DIVERGING_COUNT)
- { behind: number_commits_behind, ahead: number_commits_ahead }
+ if number_commits_behind + number_commits_ahead >= MAX_DIVERGING_COUNT
+ { distance: MAX_DIVERGING_COUNT }
+ else
+ { behind: number_commits_behind, ahead: number_commits_ahead }
+ end
end
end
@@ -512,6 +528,8 @@ class Repository
# items is an Array like: [[oid, path], [oid1, path1]]
def blobs_at(items)
+ return [] unless exists?
+
raw_repository.batch_blobs(items).map { |blob| Blob.decorate(blob, project) }
end
@@ -599,7 +617,6 @@ class Repository
return unless readme
context = { project: project }
- context[:markdown_engine] = :redcarpet unless MarkupHelper.commonmark_for_repositories_enabled?
MarkupHelper.markup_unsafe(readme.name, readme.data, context)
end
@@ -837,6 +854,12 @@ class Repository
end
end
+ def merge_to_ref(user, source_sha, merge_request, target_ref, message)
+ branch = merge_request.target_branch
+
+ raw.merge_to_ref(user, source_sha, branch, target_ref, message)
+ end
+
def ff_merge(user, source, target_branch, merge_request: nil)
their_commit_id = commit(source)&.id
raise 'Invalid merge source' if their_commit_id.nil?
@@ -1016,12 +1039,12 @@ class Repository
remote_branch: merge_request.target_branch)
end
- def squash(user, merge_request)
+ def squash(user, merge_request, message)
raw.squash(user, merge_request.id, branch: merge_request.target_branch,
start_sha: merge_request.diff_start_sha,
end_sha: merge_request.diff_head_sha,
author: merge_request.author,
- message: merge_request.title)
+ message: message)
end
def update_submodule(user, submodule, commit_sha, message:, branch:)
@@ -1059,19 +1082,11 @@ class Repository
end
def cache
- @cache ||= if is_wiki
- Gitlab::RepositoryCache.new(self, extra_namespace: 'wiki')
- else
- Gitlab::RepositoryCache.new(self)
- end
+ @cache ||= Gitlab::RepositoryCache.new(self)
end
def request_store_cache
- @request_store_cache ||= if is_wiki
- Gitlab::RepositoryCache.new(self, extra_namespace: 'wiki', backend: Gitlab::SafeRequestStore)
- else
- Gitlab::RepositoryCache.new(self, backend: Gitlab::SafeRequestStore)
- end
+ @request_store_cache ||= Gitlab::RepositoryCache.new(self, backend: Gitlab::SafeRequestStore)
end
def tags_sorted_by_committed_date
@@ -1098,6 +1113,9 @@ class Repository
end
def initialize_raw_repository
- Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', Gitlab::GlRepository.gl_repository(project, is_wiki))
+ Gitlab::Git::Repository.new(project.repository_storage,
+ disk_path + '.git',
+ Gitlab::GlRepository.gl_repository(project, is_wiki),
+ project.full_path)
end
end
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index e65b3df0fb6..6caab24143b 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -48,7 +48,7 @@ class SentNotification < ActiveRecord::Base
end
def record_note(note, recipient_id, reply_key = self.reply_key, attrs = {})
- attrs[:in_reply_to_discussion_id] = note.discussion_id
+ attrs[:in_reply_to_discussion_id] = note.discussion_id if note.part_of_discussion?
record(note.noteable, recipient_id, reply_key, attrs)
end
@@ -99,29 +99,12 @@ class SentNotification < ActiveRecord::Base
private
def reply_params
- attrs = {
+ {
noteable_type: self.noteable_type,
noteable_id: self.noteable_id,
- commit_id: self.commit_id
+ commit_id: self.commit_id,
+ in_reply_to_discussion_id: self.in_reply_to_discussion_id
}
-
- if self.in_reply_to_discussion_id.present?
- attrs[:in_reply_to_discussion_id] = self.in_reply_to_discussion_id
- else
- # Remove in GitLab 10.0, when we will not support replying to SentNotifications
- # that don't have `in_reply_to_discussion_id` anymore.
- attrs.merge!(
- type: self.note_type,
-
- # LegacyDiffNote
- line_code: self.line_code,
-
- # DiffNote
- position: self.position.to_json
- )
- end
-
- attrs
end
def note_valid
diff --git a/app/models/service.rb b/app/models/service.rb
index 9dcb0aab0a3..da523bfa426 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -255,7 +255,6 @@ class Service < ActiveRecord::Base
external_wiki
flowdock
hangouts_chat
- hipchat
irker
jira
kubernetes
@@ -267,6 +266,7 @@ class Service < ActiveRecord::Base
prometheus
pushover
redmine
+ youtrack
slack_slash_commands
slack
teamcity
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 11856b55902..f23ddd64fe3 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -50,11 +50,11 @@ class Snippet < ActiveRecord::Base
validates :visibility_level, inclusion: { in: Gitlab::VisibilityLevel.values }
# Scopes
- scope :are_internal, -> { where(visibility_level: Snippet::INTERNAL) }
+ scope :are_internal, -> { where(visibility_level: Snippet::INTERNAL) }
scope :are_private, -> { where(visibility_level: Snippet::PRIVATE) }
scope :are_public, -> { where(visibility_level: Snippet::PUBLIC) }
scope :public_and_internal, -> { where(visibility_level: [Snippet::PUBLIC, Snippet::INTERNAL]) }
- scope :fresh, -> { order("created_at DESC") }
+ scope :fresh, -> { order("created_at DESC") }
scope :inc_relations_for_view, -> { includes(author: :status) }
participant :author
@@ -175,6 +175,12 @@ class Snippet < ActiveRecord::Base
:visibility_level
end
+ def embeddable?
+ ability = project_id? ? :read_project_snippet : :read_personal_snippet
+
+ Ability.allowed?(nil, ability, self)
+ end
+
def notes_with_associations
notes.includes(:author)
end
diff --git a/app/models/ssh_host_key.rb b/app/models/ssh_host_key.rb
index b6844dbe870..b6fb39ee81f 100644
--- a/app/models/ssh_host_key.rb
+++ b/app/models/ssh_host_key.rb
@@ -26,7 +26,8 @@ class SshHostKey
self.reactive_cache_lifetime = 10.minutes
def self.find_by(opts = {})
- return nil unless opts.key?(:id)
+ opts = HashWithIndifferentAccess.new(opts)
+ return unless opts.key?(:id)
project_id, url = opts[:id].split(':', 2)
project = Project.find_by(id: project_id)
@@ -52,6 +53,11 @@ class SshHostKey
@compare_host_keys = compare_host_keys
end
+ # Needed for reactive caching
+ def self.primary_key
+ :id
+ end
+
def id
[project.id, url].join(':')
end
diff --git a/app/models/storage/hashed_project.rb b/app/models/storage/hashed_project.rb
index 911fb7e9ce9..f5d0d6fab3b 100644
--- a/app/models/storage/hashed_project.rb
+++ b/app/models/storage/hashed_project.rb
@@ -31,7 +31,7 @@ module Storage
gitlab_shell.add_namespace(repository_storage, base_dir)
end
- def rename_repo
+ def rename_repo(old_full_path: nil, new_full_path: nil)
true
end
diff --git a/app/models/storage/legacy_project.rb b/app/models/storage/legacy_project.rb
index 9f6f19acb41..76ac5c13c18 100644
--- a/app/models/storage/legacy_project.rb
+++ b/app/models/storage/legacy_project.rb
@@ -29,18 +29,19 @@ module Storage
gitlab_shell.add_namespace(repository_storage, base_dir)
end
- def rename_repo
- new_full_path = project.build_full_path
+ def rename_repo(old_full_path: nil, new_full_path: nil)
+ old_full_path ||= project.full_path_was
+ new_full_path ||= project.build_full_path
- if gitlab_shell.mv_repository(repository_storage, project.full_path_was, new_full_path)
+ if gitlab_shell.mv_repository(repository_storage, old_full_path, new_full_path)
# If repository moved successfully we need to send update instructions to users.
# However we cannot allow rollback since we moved repository
# So we basically we mute exceptions in next actions
begin
- gitlab_shell.mv_repository(repository_storage, "#{project.full_path_was}.wiki", "#{new_full_path}.wiki")
+ gitlab_shell.mv_repository(repository_storage, "#{old_full_path}.wiki", "#{new_full_path}.wiki")
return true
rescue => e
- Rails.logger.error "Exception renaming #{project.full_path_was} -> #{new_full_path}: #{e}"
+ Rails.logger.error "Exception renaming #{old_full_path} -> #{new_full_path}: #{e}"
# Returning false does not rollback after_* transaction but gives
# us information about failing some of tasks
return false
diff --git a/app/models/suggestion.rb b/app/models/suggestion.rb
index c76b8e71507..09034646bff 100644
--- a/app/models/suggestion.rb
+++ b/app/models/suggestion.rb
@@ -5,8 +5,7 @@ class Suggestion < ApplicationRecord
validates :note, presence: true
validates :commit_id, presence: true, if: :applied?
- delegate :original_position, :position, :diff_file,
- :noteable, to: :note
+ delegate :original_position, :position, :noteable, to: :note
def project
noteable.source_project
@@ -16,6 +15,10 @@ class Suggestion < ApplicationRecord
noteable.source_branch
end
+ def file_path
+ position.file_path
+ end
+
# For now, suggestions only serve as a way to send patches that
# will change a single line (being able to apply multiple in the same place),
# which explains `from_line` and `to_line` being the same line.
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 7b64615f699..d9b86d941b6 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -4,6 +4,11 @@ class Todo < ActiveRecord::Base
include Sortable
include FromUnion
+ # Time to wait for todos being removed when not visible for user anymore.
+ # Prevents TODOs being removed by mistake, for example, removing access from a user
+ # and giving it back again.
+ WAIT_FOR_DELETE = 1.hour
+
ASSIGNED = 1
MENTIONED = 2
BUILD_FAILED = 3
diff --git a/app/models/user.rb b/app/models/user.rb
index 26fd2d903a1..778c9e631bd 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2,7 +2,7 @@
require 'carrierwave/orm/activerecord'
-class User < ActiveRecord::Base
+class User < ApplicationRecord
extend Gitlab::ConfigHelper
include Gitlab::ConfigHelper
@@ -145,7 +145,7 @@ class User < ActiveRecord::Base
has_many :issue_assignees
has_many :assigned_issues, class_name: "Issue", through: :issue_assignees, source: :issue
- has_many :assigned_merge_requests, dependent: :nullify, foreign_key: :assignee_id, class_name: "MergeRequest" # rubocop:disable Cop/ActiveRecordDependent
+ has_many :assigned_merge_requests, dependent: :nullify, foreign_key: :assignee_id, class_name: "MergeRequest" # rubocop:disable Cop/ActiveRecordDependent
has_many :custom_attributes, class_name: 'UserCustomAttribute'
has_many :callouts, class_name: 'UserCallout'
@@ -228,6 +228,9 @@ class User < ActiveRecord::Base
delegate :path, to: :namespace, allow_nil: true, prefix: true
delegate :notes_filter_for, to: :user_preference
delegate :set_notes_filter, to: :user_preference
+ delegate :first_day_of_week, :first_day_of_week=, to: :user_preference
+
+ accepts_nested_attributes_for :user_preference, update_only: true
state_machine :state, initial: :active do
event :block do
@@ -267,9 +270,12 @@ class User < ActiveRecord::Base
scope :without_projects, -> { joins('LEFT JOIN project_authorizations ON users.id = project_authorizations.user_id').where(project_authorizations: { user_id: nil }) }
scope :order_recent_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'DESC')) }
scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'ASC')) }
+ scope :order_recent_last_activity, -> { reorder(Gitlab::Database.nulls_last_order('last_activity_on', 'DESC')) }
+ scope :order_oldest_last_activity, -> { reorder(Gitlab::Database.nulls_first_order('last_activity_on', 'ASC')) }
scope :confirmed, -> { where.not(confirmed_at: nil) }
scope :by_username, -> (usernames) { iwhere(username: Array(usernames).map(&:to_s)) }
scope :for_todos, -> (todos) { where(id: todos.select(:user_id)) }
+ scope :with_emails, -> { preload(:emails) }
# Limits the users to those that have TODOs, optionally in the given state.
#
@@ -337,6 +343,8 @@ class User < ActiveRecord::Base
case order_method.to_s
when 'recent_sign_in' then order_recent_sign_in
when 'oldest_sign_in' then order_oldest_sign_in
+ when 'last_activity_on_desc' then order_recent_last_activity
+ when 'last_activity_on_asc' then order_oldest_last_activity
else
order_by(order_method)
end
@@ -380,7 +388,7 @@ class User < ActiveRecord::Base
find_by(id: user_id)
end
- def filter(filter_name)
+ def filter_items(filter_name)
case filter_name
when 'admins'
admins
@@ -462,7 +470,7 @@ class User < ActiveRecord::Base
end
def by_login(login)
- return nil unless login
+ return unless login
if login.include?('@'.freeze)
unscoped.iwhere(email: login).take
@@ -754,8 +762,12 @@ class User < ActiveRecord::Base
#
# Example use:
# `Project.where('EXISTS(?)', user.authorizations_for_projects)`
- def authorizations_for_projects
- project_authorizations.select(1).where('project_authorizations.project_id = projects.id')
+ def authorizations_for_projects(min_access_level: nil)
+ authorizations = project_authorizations.select(1).where('project_authorizations.project_id = projects.id')
+
+ return authorizations unless min_access_level.present?
+
+ authorizations.where('project_authorizations.access_level >= ?', min_access_level)
end
# Returns the projects this user has reporter (or greater) access to, limited
@@ -1156,6 +1168,10 @@ class User < ActiveRecord::Base
Gitlab::ObjectHierarchy.new(owned_or_maintainers_groups).base_and_descendants
end
+ def manageable_groups_with_routes
+ manageable_groups.eager_load(:route).order('routes.path')
+ end
+
def namespaces
namespace_ids = groups.pluck(:id)
namespace_ids.push(namespace.id)
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index b1d6d461928..64daba81dcf 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -132,7 +132,7 @@ class WikiPage
# The GitLab Commit instance for this page.
def version
- return nil unless persisted?
+ return unless persisted?
@version ||= @page.version
end
diff --git a/app/policies/base_policy.rb b/app/policies/base_policy.rb
index 0d0f1c28bad..72de04203a6 100644
--- a/app/policies/base_policy.rb
+++ b/app/policies/base_policy.rb
@@ -7,6 +7,10 @@ class BasePolicy < DeclarativePolicy::Base
with_options scope: :user, score: 0
condition(:admin) { @user&.admin? }
+ desc "User has access to all private groups & projects"
+ with_options scope: :user, score: 0
+ condition(:full_private_access) { @user&.full_private_access? }
+
with_options scope: :user, score: 0
condition(:external_user) { @user.nil? || @user.external? }
diff --git a/app/policies/board_policy.rb b/app/policies/board_policy.rb
new file mode 100644
index 00000000000..4bf1e7bd3e1
--- /dev/null
+++ b/app/policies/board_policy.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class BoardPolicy < BasePolicy
+ delegate { @subject.parent }
+
+ condition(:is_group_board) { @subject.group_board? }
+ condition(:is_project_board) { @subject.project_board? }
+
+ rule { is_project_board & can?(:read_project) }.enable :read_parent
+
+ rule { is_group_board & can?(:read_group) }.policy do
+ enable :read_parent
+ enable :read_milestone
+ enable :read_issue
+ end
+end
diff --git a/app/policies/ci/pipeline_policy.rb b/app/policies/ci/pipeline_policy.rb
index e42d78f47c5..2c90b8a73cd 100644
--- a/app/policies/ci/pipeline_policy.rb
+++ b/app/policies/ci/pipeline_policy.rb
@@ -10,6 +10,15 @@ module Ci
@subject.project.branch_allows_collaboration?(@user, @subject.ref)
end
+ condition(:external_pipeline, scope: :subject, score: 0) do
+ @subject.external?
+ end
+
+ # Disallow users without permissions from accessing internal pipelines
+ rule { ~can?(:read_build) & ~external_pipeline }.policy do
+ prevent :read_pipeline
+ end
+
rule { protected_ref }.prevent :update_pipeline
rule { can?(:public_access) & branch_allows_collaboration }.policy do
diff --git a/app/policies/concerns/clusterable_actions.rb b/app/policies/concerns/clusterable_actions.rb
new file mode 100644
index 00000000000..08ddd742ea9
--- /dev/null
+++ b/app/policies/concerns/clusterable_actions.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module ClusterableActions
+ private
+
+ # Overridden on EE module
+ def multiple_clusters_available?
+ false
+ end
+
+ def clusterable_has_clusters?
+ !subject.clusters.empty?
+ end
+end
diff --git a/app/policies/container_repository_policy.rb b/app/policies/container_repository_policy.rb
new file mode 100644
index 00000000000..6781c845142
--- /dev/null
+++ b/app/policies/container_repository_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class ContainerRepositoryPolicy < BasePolicy
+ delegate { @subject.project }
+end
diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb
index 16c58730878..d412a591fdc 100644
--- a/app/policies/global_policy.rb
+++ b/app/policies/global_policy.rb
@@ -68,6 +68,10 @@ class GlobalPolicy < BasePolicy
enable :read_users_list
end
+ rule { ~anonymous }.policy do
+ enable :read_instance_metadata
+ end
+
rule { admin }.policy do
enable :read_custom_attribute
enable :update_custom_attribute
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index f07bb188265..e74e5f008d7 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class GroupPolicy < BasePolicy
+ include ClusterableActions
+
desc "Group is public"
with_options scope: :subject, score: 0
condition(:public_group) { @subject.public? }
@@ -27,6 +29,9 @@ class GroupPolicy < BasePolicy
GroupProjectsFinder.new(group: @subject, current_user: @user, options: { include_subgroups: true }).execute.any?
end
+ condition(:has_clusters, scope: :subject) { clusterable_has_clusters? }
+ condition(:can_have_multiple_clusters) { multiple_clusters_available? }
+
with_options scope: :subject, score: 0
condition(:request_access_enabled) { @subject.request_access_enabled }
@@ -45,10 +50,10 @@ class GroupPolicy < BasePolicy
enable :read_label
end
- rule { admin } .enable :read_group
+ rule { admin }.enable :read_group
rule { has_projects }.policy do
- enable :read_group
+ enable :read_list
enable :read_label
end
@@ -67,6 +72,7 @@ class GroupPolicy < BasePolicy
enable :admin_pipeline
enable :admin_build
enable :read_cluster
+ enable :add_cluster
enable :create_cluster
enable :update_cluster
enable :admin_cluster
@@ -106,6 +112,8 @@ class GroupPolicy < BasePolicy
rule { owner & (~share_with_group_locked | ~has_parent | ~parent_share_with_group_locked | can_change_parent_share_with_group_lock) }.enable :change_share_with_group_lock
+ rule { ~can_have_multiple_clusters & has_clusters }.prevent :add_cluster
+
def access_level
return GroupMember::NO_ACCESS if @user.nil?
diff --git a/app/policies/issuable_policy.rb b/app/policies/issuable_policy.rb
index 6d8b575102e..ecb2797d1d9 100644
--- a/app/policies/issuable_policy.rb
+++ b/app/policies/issuable_policy.rb
@@ -11,7 +11,7 @@ class IssuablePolicy < BasePolicy
@user && @subject.assignee_or_author?(@user)
end
- rule { assignee_or_author }.policy do
+ rule { can?(:guest_access) & assignee_or_author }.policy do
enable :read_issue
enable :update_issue
enable :reopen_issue
diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb
index a0706eaa46c..dd8c5d49cf4 100644
--- a/app/policies/issue_policy.rb
+++ b/app/policies/issue_policy.rb
@@ -18,6 +18,7 @@ class IssuePolicy < IssuablePolicy
prevent :read_issue_iid
prevent :update_issue
prevent :admin_issue
+ prevent :create_note
end
rule { locked }.policy do
diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb
index f22843b6463..8d23e3abed3 100644
--- a/app/policies/note_policy.rb
+++ b/app/policies/note_policy.rb
@@ -18,6 +18,7 @@ class NotePolicy < BasePolicy
prevent :read_note
prevent :admin_note
prevent :resolve_note
+ prevent :award_emoji
end
rule { is_author }.policy do
diff --git a/app/policies/personal_snippet_policy.rb b/app/policies/personal_snippet_policy.rb
index 777f933cdcd..2b5cca76c20 100644
--- a/app/policies/personal_snippet_policy.rb
+++ b/app/policies/personal_snippet_policy.rb
@@ -28,5 +28,10 @@ class PersonalSnippetPolicy < BasePolicy
rule { anonymous }.prevent :comment_personal_snippet
- rule { can?(:comment_personal_snippet) }.enable :award_emoji
+ rule { can?(:comment_personal_snippet) }.policy do
+ enable :create_note
+ enable :award_emoji
+ end
+
+ rule { full_private_access }.enable :read_personal_snippet
end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 1c082945299..cf257ed47c8 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -2,6 +2,7 @@
class ProjectPolicy < BasePolicy
extend ClassMethods
+ include ClusterableActions
READONLY_FEATURES_WHEN_ARCHIVED = %i[
issue
@@ -22,6 +23,7 @@ class ProjectPolicy < BasePolicy
container_image
pages
cluster
+ release
].freeze
desc "User is a project owner"
@@ -103,6 +105,13 @@ class ProjectPolicy < BasePolicy
@subject.feature_available?(:merge_requests, @user)
end
+ condition(:has_clusters, scope: :subject) { clusterable_has_clusters? }
+ condition(:can_have_multiple_clusters) { multiple_clusters_available? }
+
+ condition(:internal_builds_disabled) do
+ !@subject.builds_enabled?
+ end
+
features = %w[
merge_requests
issues
@@ -143,7 +152,6 @@ class ProjectPolicy < BasePolicy
enable :remove_fork_project
enable :destroy_merge_request
enable :destroy_issue
- enable :remove_pages
enable :set_issue_iid
enable :set_issue_created_at
@@ -169,6 +177,7 @@ class ProjectPolicy < BasePolicy
enable :read_cycle_analytics
enable :award_emoji
enable :read_pages_content
+ enable :read_release
end
# These abilities are not allowed to admins that are not members of the project,
@@ -190,10 +199,10 @@ class ProjectPolicy < BasePolicy
enable :read_build
enable :read_container_image
enable :read_pipeline
- enable :read_pipeline_schedule
enable :read_environment
enable :read_deployment
enable :read_merge_request
+ enable :read_sentry_issue
end
# We define `:public_user_access` separately because there are cases in gitlab-ee
@@ -216,6 +225,8 @@ class ProjectPolicy < BasePolicy
rule { owner | admin | guest | group_member }.prevent :request_access
rule { ~request_access_enabled }.prevent :request_access
+ rule { can?(:developer_access) & can?(:create_issue) }.enable :import_issues
+
rule { can?(:developer_access) }.policy do
enable :admin_merge_request
enable :admin_milestone
@@ -226,6 +237,7 @@ class ProjectPolicy < BasePolicy
enable :update_build
enable :create_pipeline
enable :update_pipeline
+ enable :read_pipeline_schedule
enable :create_pipeline_schedule
enable :create_merge_request_from
enable :create_wiki
@@ -235,6 +247,8 @@ class ProjectPolicy < BasePolicy
enable :update_container_image
enable :create_environment
enable :create_deployment
+ enable :create_release
+ enable :update_release
end
rule { can?(:maintainer_access) }.policy do
@@ -256,11 +270,16 @@ class ProjectPolicy < BasePolicy
enable :admin_pages
enable :read_pages
enable :update_pages
+ enable :remove_pages
enable :read_cluster
+ enable :add_cluster
enable :create_cluster
enable :update_cluster
enable :admin_cluster
enable :create_environment_terminal
+ enable :destroy_release
+ enable :destroy_artifacts
+ enable :daily_statistics
end
rule { (mirror_available & can?(:admin_project)) | admin }.enable :admin_remote_mirror
@@ -282,6 +301,8 @@ class ProjectPolicy < BasePolicy
rule { issues_disabled }.policy do
prevent(*create_read_update_admin_destroy(:issue))
+ prevent(*create_read_update_admin_destroy(:board))
+ prevent(*create_read_update_admin_destroy(:list))
end
rule { merge_requests_disabled | repository_disabled }.policy do
@@ -301,13 +322,12 @@ class ProjectPolicy < BasePolicy
prevent(*create_read_update_admin_destroy(:project_snippet))
end
- rule { wiki_disabled & ~has_external_wiki }.policy do
+ rule { wiki_disabled }.policy do
prevent(*create_read_update_admin_destroy(:wiki))
prevent(:download_wiki_code)
end
rule { builds_disabled | repository_disabled }.policy do
- prevent(*create_update_admin_destroy(:pipeline))
prevent(*create_read_update_admin_destroy(:build))
prevent(*create_read_update_admin_destroy(:pipeline_schedule))
prevent(*create_read_update_admin_destroy(:environment))
@@ -315,11 +335,23 @@ class ProjectPolicy < BasePolicy
prevent(*create_read_update_admin_destroy(:deployment))
end
+ # There's two separate cases when builds_disabled is true:
+ # 1. When internal CI is disabled - builds_disabled && internal_builds_disabled
+ # - We do not prevent the user from accessing Pipelines to allow him to access external CI
+ # 2. When the user is not allowed to access CI - builds_disabled && ~internal_builds_disabled
+ # - We prevent the user from accessing Pipelines
+ rule { (builds_disabled & ~internal_builds_disabled) | repository_disabled }.policy do
+ prevent(*create_read_update_admin_destroy(:pipeline))
+ prevent(*create_read_update_admin_destroy(:commit_status))
+ end
+
rule { repository_disabled }.policy do
prevent :push_code
prevent :download_code
prevent :fork_project
prevent :read_commit_status
+ prevent :read_pipeline
+ prevent(*create_read_update_admin_destroy(:release))
end
rule { container_registry_disabled }.policy do
@@ -345,10 +377,10 @@ class ProjectPolicy < BasePolicy
enable :read_merge_request
enable :read_note
enable :read_pipeline
- enable :read_pipeline_schedule
enable :read_commit_status
enable :read_container_image
enable :download_code
+ enable :read_release
enable :download_wiki_code
enable :read_cycle_analytics
enable :read_pages_content
@@ -363,7 +395,6 @@ class ProjectPolicy < BasePolicy
rule { public_builds & can?(:guest_access) }.policy do
enable :read_pipeline
- enable :read_pipeline_schedule
end
# These rules are included to allow maintainers of projects to push to certain
@@ -378,9 +409,11 @@ class ProjectPolicy < BasePolicy
end.enable :read_issue_iid
rule do
- (can?(:read_project_for_iids) & merge_requests_visible_to_user) | can?(:read_merge_request)
+ (~guest & can?(:read_project_for_iids) & merge_requests_visible_to_user) | can?(:read_merge_request)
end.enable :read_merge_request_iid
+ rule { ~can_have_multiple_clusters & has_clusters }.prevent :add_cluster
+
private
def team_member?
@@ -433,7 +466,7 @@ class ProjectPolicy < BasePolicy
when ProjectFeature::DISABLED
false
when ProjectFeature::PRIVATE
- guest? || admin?
+ admin? || team_access_level >= ProjectFeature.required_minimum_access_level(feature)
else
true
end
diff --git a/app/policies/project_snippet_policy.rb b/app/policies/project_snippet_policy.rb
index 288bf070cfc..e5e005cee6d 100644
--- a/app/policies/project_snippet_policy.rb
+++ b/app/policies/project_snippet_policy.rb
@@ -5,13 +5,12 @@ class ProjectSnippetPolicy < BasePolicy
desc "Snippet is public"
condition(:public_snippet, scope: :subject) { @subject.public? }
+ condition(:internal_snippet, scope: :subject) { @subject.internal? }
condition(:private_snippet, scope: :subject) { @subject.private? }
condition(:public_project, scope: :subject) { @subject.project.public? }
condition(:is_author) { @user && @subject.author == @user }
- condition(:internal, scope: :subject) { @subject.internal? }
-
# We have to check both project feature visibility and a snippet visibility and take the stricter one
# This will be simplified - check https://gitlab.com/gitlab-org/gitlab-ce/issues/27573
rule { ~can?(:read_project) }.policy do
@@ -26,13 +25,13 @@ class ProjectSnippetPolicy < BasePolicy
# is used to hide/show various snippet-related controls, so we can't just move
# all of the handling here.
rule do
- all?(private_snippet | (internal & external_user),
+ all?(private_snippet | (internal_snippet & external_user),
~project.guest,
- ~admin,
- ~is_author)
+ ~is_author,
+ ~full_private_access)
end.prevent :read_project_snippet
- rule { internal & ~is_author & ~admin }.policy do
+ rule { internal_snippet & ~is_author & ~admin }.policy do
prevent :update_project_snippet
prevent :admin_project_snippet
end
@@ -44,4 +43,6 @@ class ProjectSnippetPolicy < BasePolicy
enable :update_project_snippet
enable :admin_project_snippet
end
+
+ rule { ~can?(:read_project_snippet) }.prevent :create_note
end
diff --git a/app/policies/release_policy.rb b/app/policies/release_policy.rb
new file mode 100644
index 00000000000..d7f9e5d7445
--- /dev/null
+++ b/app/policies/release_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class ReleasePolicy < BasePolicy
+ delegate { @subject.project }
+end
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index 300f85e1e9d..29656b17183 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -2,6 +2,11 @@
module Ci
class BuildRunnerPresenter < SimpleDelegator
+ include Gitlab::Utils::StrongMemoize
+
+ RUNNER_REMOTE_TAG_PREFIX = 'refs/tags/'.freeze
+ RUNNER_REMOTE_BRANCH_PREFIX = 'refs/remotes/origin/'.freeze
+
def artifacts
return unless options[:artifacts]
@@ -11,6 +16,35 @@ module Ci
list.flatten.compact
end
+ def ref_type
+ if tag
+ 'tag'
+ else
+ 'branch'
+ end
+ end
+
+ def git_depth
+ strong_memoize(:git_depth) do
+ git_depth = variables&.find { |variable| variable[:key] == 'GIT_DEPTH' }&.dig(:value)
+ git_depth.to_i
+ end
+ end
+
+ def refspecs
+ specs = []
+
+ if git_depth > 0
+ specs << refspec_for_branch(ref) if branch? || merge_request_event?
+ specs << refspec_for_tag(ref) if tag?
+ else
+ specs << refspec_for_branch
+ specs << refspec_for_tag
+ end
+
+ specs
+ end
+
private
def create_archive(artifacts)
@@ -41,5 +75,13 @@ module Ci
}
end
end
+
+ def refspec_for_branch(ref = '*')
+ "+#{Gitlab::Git::BRANCH_REF_PREFIX}#{ref}:#{RUNNER_REMOTE_BRANCH_PREFIX}#{ref}"
+ end
+
+ def refspec_for_tag(ref = '*')
+ "+#{Gitlab::Git::TAG_REF_PREFIX}#{ref}:#{RUNNER_REMOTE_TAG_PREFIX}#{ref}"
+ end
end
end
diff --git a/app/presenters/ci/trigger_presenter.rb b/app/presenters/ci/trigger_presenter.rb
new file mode 100644
index 00000000000..605c8f328a4
--- /dev/null
+++ b/app/presenters/ci/trigger_presenter.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Ci
+ class TriggerPresenter < Gitlab::View::Presenter::Delegated
+ presents :trigger
+
+ def has_token_exposed?
+ can?(current_user, :admin_trigger, trigger)
+ end
+
+ def token
+ if has_token_exposed?
+ trigger.token
+ else
+ trigger.short_token
+ end
+ end
+ end
+end
diff --git a/app/presenters/clusterable_presenter.rb b/app/presenters/clusterable_presenter.rb
index 9cc137aa3bd..d94d9118eee 100644
--- a/app/presenters/clusterable_presenter.rb
+++ b/app/presenters/clusterable_presenter.rb
@@ -12,6 +12,10 @@ class ClusterablePresenter < Gitlab::View::Presenter::Delegated
.fabricate!
end
+ def can_add_cluster?
+ can?(current_user, :add_cluster, clusterable)
+ end
+
def can_create_cluster?
can?(current_user, :create_cluster, clusterable)
end
diff --git a/app/presenters/commit_presenter.rb b/app/presenters/commit_presenter.rb
new file mode 100644
index 00000000000..05adbe1d4f5
--- /dev/null
+++ b/app/presenters/commit_presenter.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CommitPresenter < Gitlab::View::Presenter::Simple
+ presents :commit
+
+ def status_for(ref)
+ can?(current_user, :read_commit_status, commit.project) && commit.status(ref)
+ end
+
+ def any_pipelines?
+ can?(current_user, :read_pipeline, commit.project) && commit.pipelines.any?
+ end
+end
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index 1db6c9eff36..af164858408 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -98,6 +98,12 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end
end
+ def target_branch_path
+ if target_branch_exists?
+ project_branch_path(project, target_branch)
+ end
+ end
+
def source_branch_path
if source_branch_exists?
project_branch_path(source_project, source_branch)
@@ -170,6 +176,10 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
source_branch_exists? && merge_request.can_remove_source_branch?(current_user)
end
+ def can_read_pipeline?
+ pipeline && can?(current_user, :read_pipeline, pipeline)
+ end
+
def mergeable_discussions_state
# This avoids calling MergeRequest#mergeable_discussions_state without
# considering the state of the MR first. If a MR isn't mergeable, we can
@@ -189,6 +199,10 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
merge_request.subscribed?(current_user, merge_request.target_project)
end
+ def conflicts_docs_path
+ help_page_path('user/project/merge_requests/resolve_conflicts.md')
+ end
+
private
def cached_can_be_reverted?
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 9bd64ea217e..000b7c433a2 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -13,7 +13,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
presents :project
AnchorData = Struct.new(:is_link, :label, :link, :class_modifier, :icon)
- MAX_TAGS_TO_SHOW = 3
+ MAX_TOPICS_TO_SHOW = 3
def statistic_icon(icon_name = 'plus-square-o')
sprite_icon(icon_name, size: 16, css_class: 'icon append-right-4')
@@ -256,7 +256,8 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
elsif repository.contribution_guide.present?
AnchorData.new(false,
statistic_icon('doc-text') + _('CONTRIBUTING'),
- contribution_guide_path)
+ contribution_guide_path,
+ 'default')
end
end
@@ -310,20 +311,24 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
end
- def tags_to_show
- project.tag_list.take(MAX_TAGS_TO_SHOW) # rubocop: disable CodeReuse/ActiveRecord
+ def topics_to_show
+ project.tag_list.take(MAX_TOPICS_TO_SHOW) # rubocop: disable CodeReuse/ActiveRecord
end
- def count_of_extra_tags_not_shown
- if project.tag_list.count > MAX_TAGS_TO_SHOW
- project.tag_list.count - MAX_TAGS_TO_SHOW
+ def topics_not_shown
+ project.tag_list - topics_to_show
+ end
+
+ def count_of_extra_topics_not_shown
+ if project.tag_list.count > MAX_TOPICS_TO_SHOW
+ project.tag_list.count - MAX_TOPICS_TO_SHOW
else
0
end
end
- def has_extra_tags?
- count_of_extra_tags_not_shown > 0
+ def has_extra_topics?
+ count_of_extra_topics_not_shown > 0
end
private
diff --git a/app/serializers/acts_as_taggable_on/tag_entity.rb b/app/serializers/acts_as_taggable_on/tag_entity.rb
new file mode 100644
index 00000000000..d4e4b69f8fa
--- /dev/null
+++ b/app/serializers/acts_as_taggable_on/tag_entity.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class ActsAsTaggableOn::TagEntity < Grape::Entity
+ expose :id
+ expose :name
+end
diff --git a/app/serializers/acts_as_taggable_on/tag_serializer.rb b/app/serializers/acts_as_taggable_on/tag_serializer.rb
new file mode 100644
index 00000000000..87f53606aa1
--- /dev/null
+++ b/app/serializers/acts_as_taggable_on/tag_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class ActsAsTaggableOn::TagSerializer < BaseSerializer
+ entity ActsAsTaggableOn::TagEntity
+end
diff --git a/app/serializers/base_serializer.rb b/app/serializers/base_serializer.rb
index 7b65bd22f54..4744a7c1cc8 100644
--- a/app/serializers/base_serializer.rb
+++ b/app/serializers/base_serializer.rb
@@ -16,11 +16,11 @@ class BaseSerializer
.as_json
end
- def self.entity(entity_class)
- @entity_class ||= entity_class
- end
+ class << self
+ attr_reader :entity_class
- def self.entity_class
- @entity_class
+ def entity(entity_class)
+ @entity_class ||= entity_class
+ end
end
end
diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb
index 7b1a0be75ca..02df1480828 100644
--- a/app/serializers/cluster_application_entity.rb
+++ b/app/serializers/cluster_application_entity.rb
@@ -4,7 +4,9 @@ class ClusterApplicationEntity < Grape::Entity
expose :name
expose :status_name, as: :status
expose :status_reason
+ expose :version
expose :external_ip, if: -> (e, _) { e.respond_to?(:external_ip) }
expose :hostname, if: -> (e, _) { e.respond_to?(:hostname) }
expose :email, if: -> (e, _) { e.respond_to?(:email) }
+ expose :update_available?, as: :update_available, if: -> (e, _) { e.respond_to?(:update_available?) }
end
diff --git a/app/serializers/concerns/user_status_tooltip.rb b/app/serializers/concerns/user_status_tooltip.rb
index aa6e67e3351..633b117d392 100644
--- a/app/serializers/concerns/user_status_tooltip.rb
+++ b/app/serializers/concerns/user_status_tooltip.rb
@@ -11,7 +11,7 @@ module UserStatusTooltip
expose :user_status_if_loaded, as: :status_tooltip_html
def user_status_if_loaded
- return nil unless object.association(:status).loaded?
+ return unless object.association(:status).loaded?
user_status(object)
end
diff --git a/app/serializers/container_repository_entity.rb b/app/serializers/container_repository_entity.rb
index 59bf35f5aff..cc746698a05 100644
--- a/app/serializers/container_repository_entity.rb
+++ b/app/serializers/container_repository_entity.rb
@@ -3,7 +3,7 @@
class ContainerRepositoryEntity < Grape::Entity
include RequestAwareEntity
- expose :id, :path, :location
+ expose :id, :name, :path, :location, :created_at
expose :tags_path do |repository|
project_registry_repository_tags_path(project, repository, format: :json)
diff --git a/app/serializers/container_tag_entity.rb b/app/serializers/container_tag_entity.rb
index 637294877f8..361c073e22e 100644
--- a/app/serializers/container_tag_entity.rb
+++ b/app/serializers/container_tag_entity.rb
@@ -3,7 +3,7 @@
class ContainerTagEntity < Grape::Entity
include RequestAwareEntity
- expose :name, :location, :revision, :short_revision, :total_size, :created_at
+ expose :name, :path, :location, :digest, :revision, :short_revision, :total_size, :created_at
expose :destroy_path, if: -> (*) { can_destroy? } do |tag|
project_registry_repository_tag_path(project, tag.repository, tag.name)
diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb
index aa1d9e6292c..34ae06278c8 100644
--- a/app/serializers/deployment_entity.rb
+++ b/app/serializers/deployment_entity.rb
@@ -24,6 +24,12 @@ class DeploymentEntity < Grape::Entity
expose :user, using: UserEntity
expose :commit, using: CommitEntity
expose :deployable, using: JobEntity
- expose :manual_actions, using: JobEntity
- expose :scheduled_actions, using: JobEntity
+ expose :manual_actions, using: JobEntity, if: -> (*) { can_create_deployment? }
+ expose :scheduled_actions, using: JobEntity, if: -> (*) { can_create_deployment? }
+
+ private
+
+ def can_create_deployment?
+ can?(request.current_user, :create_deployment, request.project)
+ end
end
diff --git a/app/serializers/diff_file_base_entity.rb b/app/serializers/diff_file_base_entity.rb
index 06a8db78476..d8630165e49 100644
--- a/app/serializers/diff_file_base_entity.rb
+++ b/app/serializers/diff_file_base_entity.rb
@@ -27,9 +27,13 @@ class DiffFileBaseEntity < Grape::Entity
next unless merge_request.source_project
- project_edit_blob_path(merge_request.source_project,
- tree_join(merge_request.source_branch, diff_file.new_path),
- options)
+ if Feature.enabled?(:web_ide_default)
+ ide_edit_path(merge_request.source_project, merge_request.source_branch, diff_file.new_path)
+ else
+ project_edit_blob_path(merge_request.source_project,
+ tree_join(merge_request.source_branch, diff_file.new_path),
+ options)
+ end
end
expose :old_path_html do |diff_file|
@@ -72,17 +76,20 @@ class DiffFileBaseEntity < Grape::Entity
expose :old_path
expose :new_path
expose :new_file?, as: :new_file
- expose :collapsed?, as: :collapsed
- expose :text?, as: :text
+ expose :renamed_file?, as: :renamed_file
+ expose :deleted_file?, as: :deleted_file
+
expose :diff_refs
+
expose :stored_externally?, as: :stored_externally
expose :external_storage
- expose :renamed_file?, as: :renamed_file
- expose :deleted_file?, as: :deleted_file
+
expose :mode_changed?, as: :mode_changed
expose :a_mode
expose :b_mode
+ expose :viewer, using: DiffViewerEntity
+
private
def memoized_submodule_links(diff_file)
diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb
index b0aaec3326d..01ee7af37ed 100644
--- a/app/serializers/diff_file_entity.rb
+++ b/app/serializers/diff_file_entity.rb
@@ -4,12 +4,10 @@ class DiffFileEntity < DiffFileBaseEntity
include CommitsHelper
include IconsHelper
- expose :too_large?, as: :too_large
- expose :empty?, as: :empty
expose :added_lines
expose :removed_lines
- expose :load_collapsed_diff_url, if: -> (diff_file, options) { diff_file.text? && options[:merge_request] } do |diff_file|
+ expose :load_collapsed_diff_url, if: -> (diff_file, options) { diff_file.viewer.collapsed? && options[:merge_request] } do |diff_file|
merge_request = options[:merge_request]
project = merge_request.target_project
@@ -36,10 +34,6 @@ class DiffFileEntity < DiffFileBaseEntity
project_blob_path(project, tree_join(diff_file.content_sha, diff_file.new_path))
end
- expose :viewer, using: DiffViewerEntity do |diff_file|
- diff_file.rich_viewer || diff_file.simple_viewer
- end
-
expose :replaced_view_path, if: -> (_, options) { options[:merge_request] } do |diff_file|
image_diff = diff_file.rich_viewer && diff_file.rich_viewer.partial_name == 'image'
image_replaced = diff_file.old_content_sha && diff_file.old_content_sha != diff_file.content_sha
diff --git a/app/serializers/diff_viewer_entity.rb b/app/serializers/diff_viewer_entity.rb
index 27fba03cb3f..45faca6cb2f 100644
--- a/app/serializers/diff_viewer_entity.rb
+++ b/app/serializers/diff_viewer_entity.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
class DiffViewerEntity < Grape::Entity
- # Partial name refers directly to a Rails feature, let's avoid
- # using this on the frontend.
expose :partial_name, as: :name
+ expose :render_error, as: :error
+ expose :render_error_message, as: :error_message
+ expose :collapsed?, as: :collapsed
end
diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb
index 4a7d13915dd..76248e6470e 100644
--- a/app/serializers/environment_entity.rb
+++ b/app/serializers/environment_entity.rb
@@ -8,6 +8,7 @@ class EnvironmentEntity < Grape::Entity
expose :state
expose :external_url
expose :environment_type
+ expose :name_without_type
expose :last_deployment, using: DeploymentEntity
expose :stop_action_available?, as: :has_stop_action
diff --git a/app/serializers/error_tracking/error_entity.rb b/app/serializers/error_tracking/error_entity.rb
new file mode 100644
index 00000000000..91388e7c3ad
--- /dev/null
+++ b/app/serializers/error_tracking/error_entity.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module ErrorTracking
+ class ErrorEntity < Grape::Entity
+ expose :id, :title, :type, :user_count, :count,
+ :first_seen, :last_seen, :message, :culprit,
+ :external_url, :project_id, :project_name, :project_slug,
+ :short_id, :status, :frequency
+ end
+end
diff --git a/app/serializers/error_tracking/error_serializer.rb b/app/serializers/error_tracking/error_serializer.rb
new file mode 100644
index 00000000000..ff9a645eb16
--- /dev/null
+++ b/app/serializers/error_tracking/error_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module ErrorTracking
+ class ErrorSerializer < BaseSerializer
+ entity ErrorEntity
+ end
+end
diff --git a/app/serializers/error_tracking/project_entity.rb b/app/serializers/error_tracking/project_entity.rb
new file mode 100644
index 00000000000..405d87ca0d0
--- /dev/null
+++ b/app/serializers/error_tracking/project_entity.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module ErrorTracking
+ class ProjectEntity < Grape::Entity
+ expose(*Gitlab::ErrorTracking::Project::ACCESSORS)
+ end
+end
diff --git a/app/serializers/error_tracking/project_serializer.rb b/app/serializers/error_tracking/project_serializer.rb
new file mode 100644
index 00000000000..68724088fff
--- /dev/null
+++ b/app/serializers/error_tracking/project_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module ErrorTracking
+ class ProjectSerializer < BaseSerializer
+ entity ErrorTracking::ProjectEntity
+ end
+end
diff --git a/app/serializers/merge_request_basic_entity.rb b/app/serializers/merge_request_basic_entity.rb
index 084627f9dbe..178e72f4f0a 100644
--- a/app/serializers/merge_request_basic_entity.rb
+++ b/app/serializers/merge_request_basic_entity.rb
@@ -11,4 +11,5 @@ class MergeRequestBasicEntity < Grape::Entity
expose :labels, using: LabelEntity
expose :assignee, using: API::Entities::UserBasic
expose :task_status, :task_status_short
+ expose :lock_version, :lock_version
end
diff --git a/app/serializers/merge_request_diff_entity.rb b/app/serializers/merge_request_diff_entity.rb
index 433bfe60474..7e3053e5881 100644
--- a/app/serializers/merge_request_diff_entity.rb
+++ b/app/serializers/merge_request_diff_entity.rb
@@ -24,6 +24,14 @@ class MergeRequestDiffEntity < Grape::Entity
short_sha(merge_request_diff.head_commit_sha)
end
+ expose :base_version_path do |merge_request_diff|
+ project = merge_request.target_project
+
+ next unless project
+
+ merge_request_version_path(project, merge_request, merge_request_diff)
+ end
+
expose :version_path do |merge_request_diff|
start_sha = options[:start_sha]
project = merge_request.target_project
diff --git a/app/serializers/merge_request_for_pipeline_entity.rb b/app/serializers/merge_request_for_pipeline_entity.rb
new file mode 100644
index 00000000000..7779ddfd65a
--- /dev/null
+++ b/app/serializers/merge_request_for_pipeline_entity.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class MergeRequestForPipelineEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :iid
+
+ expose :path do |merge_request|
+ project_merge_request_path(merge_request.project, merge_request)
+ end
+
+ expose :title
+ expose :source_branch
+ expose :source_branch_path
+ expose :target_branch
+ expose :target_branch_path
+end
diff --git a/app/serializers/merge_request_widget_commit_entity.rb b/app/serializers/merge_request_widget_commit_entity.rb
new file mode 100644
index 00000000000..50a5c44a6ad
--- /dev/null
+++ b/app/serializers/merge_request_widget_commit_entity.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class MergeRequestWidgetCommitEntity < Grape::Entity
+ expose :safe_message, as: :message
+ expose :short_id
+ expose :title
+end
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index 9731b52f1ad..2142ceb6122 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -11,6 +11,9 @@ class MergeRequestWidgetEntity < IssuableEntity
expose :merge_user_id
expose :merge_when_pipeline_succeeds
expose :source_branch
+ expose :source_branch_protected do |merge_request|
+ merge_request.source_project.present? && ProtectedBranch.protected?(merge_request.source_project, merge_request.source_branch)
+ end
expose :source_project_id
expose :source_project_full_path do |merge_request|
merge_request.source_project&.full_path
@@ -53,10 +56,23 @@ class MergeRequestWidgetEntity < IssuableEntity
merge_request.diff_head_sha.presence
end
- expose :merge_commit_message
- expose :actual_head_pipeline, with: PipelineDetailsEntity, as: :pipeline
+ expose :actual_head_pipeline, with: PipelineDetailsEntity, as: :pipeline, if: -> (mr, _) { presenter(mr).can_read_pipeline? }
+
expose :merge_pipeline, with: PipelineDetailsEntity, if: ->(mr, _) { mr.merged? && can?(request.current_user, :read_pipeline, mr.target_project)}
+ expose :default_squash_commit_message
+ expose :default_merge_commit_message
+
+ expose :default_merge_commit_message_with_description do |merge_request|
+ merge_request.default_merge_commit_message(include_description: true)
+ end
+
+ expose :commits_without_merge_commits, using: MergeRequestWidgetCommitEntity do |merge_request|
+ merge_request.commits.without_merge_commits
+ end
+
+ expose :commits_count
+
# Booleans
expose :merge_ongoing?, as: :merge_ongoing
expose :work_in_progress?, as: :work_in_progress
@@ -74,7 +90,6 @@ class MergeRequestWidgetEntity < IssuableEntity
end
expose :branch_missing?, as: :branch_missing
- expose :commits_count
expose :cannot_be_merged?, as: :has_conflicts
expose :can_be_merged?, as: :can_be_merged
expose :mergeable?, as: :mergeable
@@ -202,10 +217,6 @@ class MergeRequestWidgetEntity < IssuableEntity
ci_environments_status_project_merge_request_path(merge_request.project, merge_request)
end
- expose :merge_commit_message_with_description do |merge_request|
- merge_request.merge_commit_message(include_description: true)
- end
-
expose :diverged_commits_count do |merge_request|
if merge_request.open? && merge_request.diverged_from_target_branch?
merge_request.diverged_commits_count
@@ -240,6 +251,10 @@ class MergeRequestWidgetEntity < IssuableEntity
expose :supports_suggestion?, as: :can_receive_suggestion
+ expose :conflicts_docs_path do |merge_request|
+ presenter(merge_request).conflicts_docs_path
+ end
+
private
delegate :current_user, to: :request
diff --git a/app/serializers/namespace_basic_entity.rb b/app/serializers/namespace_basic_entity.rb
new file mode 100644
index 00000000000..8bcbb2bca60
--- /dev/null
+++ b/app/serializers/namespace_basic_entity.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class NamespaceBasicEntity < Grape::Entity
+ expose :id
+ expose :full_path
+end
diff --git a/app/serializers/namespace_serializer.rb b/app/serializers/namespace_serializer.rb
new file mode 100644
index 00000000000..bf3f154b558
--- /dev/null
+++ b/app/serializers/namespace_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class NamespaceSerializer < BaseSerializer
+ entity NamespaceBasicEntity
+end
diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb
index c9669e59199..5ac1e590d39 100644
--- a/app/serializers/pipeline_entity.rb
+++ b/app/serializers/pipeline_entity.rb
@@ -23,11 +23,12 @@ class PipelineEntity < Grape::Entity
expose :latest?, as: :latest
expose :stuck?, as: :stuck
expose :auto_devops_source?, as: :auto_devops
- expose :merge_request?, as: :merge_request
+ expose :merge_request_event?, as: :merge_request
expose :has_yaml_errors?, as: :yaml_errors
expose :can_retry?, as: :retryable
expose :can_cancel?, as: :cancelable
expose :failure_reason?, as: :failure_reason
+ expose :detached_merge_request_pipeline?, as: :detached
end
expose :details do
@@ -36,6 +37,10 @@ class PipelineEntity < Grape::Entity
expose :finished_at
end
+ expose :merge_request, if: -> (*) { has_presentable_merge_request? }, with: MergeRequestForPipelineEntity do |pipeline|
+ pipeline.merge_request.present(current_user: request.current_user)
+ end
+
expose :ref do
expose :name do |pipeline|
pipeline.ref
@@ -49,7 +54,7 @@ class PipelineEntity < Grape::Entity
expose :tag?, as: :tag
expose :branch?, as: :branch
- expose :merge_request?, as: :merge_request
+ expose :merge_request_event?, as: :merge_request
end
expose :commit, using: CommitEntity
@@ -59,7 +64,7 @@ class PipelineEntity < Grape::Entity
pipeline.present.failure_reason
end
- expose :retry_path, if: -> (*) { can_retry? } do |pipeline|
+ expose :retry_path, if: -> (*) { can_retry? } do |pipeline|
retry_project_pipeline_path(pipeline.project, pipeline)
end
@@ -81,6 +86,11 @@ class PipelineEntity < Grape::Entity
pipeline.cancelable?
end
+ def has_presentable_merge_request?
+ pipeline.triggered_by_merge_request? &&
+ can?(request.current_user, :read_merge_request, pipeline.merge_request)
+ end
+
def detailed_status
pipeline.detailed_status(request.current_user)
end
diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb
index 7451433a841..dbbeca9431d 100644
--- a/app/serializers/pipeline_serializer.rb
+++ b/app/serializers/pipeline_serializer.rb
@@ -15,6 +15,7 @@ class PipelineSerializer < BaseSerializer
:manual_actions,
:scheduled_actions,
:artifacts,
+ :merge_request,
{
pending_builds: :project,
project: [:route, { namespace: :route }],
diff --git a/app/serializers/project_import_entity.rb b/app/serializers/project_import_entity.rb
new file mode 100644
index 00000000000..9b51af685e7
--- /dev/null
+++ b/app/serializers/project_import_entity.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class ProjectImportEntity < ProjectEntity
+ include ImportHelper
+
+ expose :import_source
+ expose :import_status
+ expose :human_import_status_name
+
+ expose :provider_link do |project, options|
+ provider_project_link_url(options[:provider_url], project[:import_source])
+ end
+end
diff --git a/app/serializers/project_serializer.rb b/app/serializers/project_serializer.rb
index 23b96c2fc9e..52ac2fa0e09 100644
--- a/app/serializers/project_serializer.rb
+++ b/app/serializers/project_serializer.rb
@@ -1,5 +1,15 @@
# frozen_string_literal: true
class ProjectSerializer < BaseSerializer
- entity ProjectEntity
+ def represent(project, opts = {})
+ entity =
+ case opts[:serializer]
+ when :import
+ ProjectImportEntity
+ else
+ ProjectEntity
+ end
+
+ super(project, opts, entity)
+ end
end
diff --git a/app/serializers/projects/serverless/service_entity.rb b/app/serializers/projects/serverless/service_entity.rb
index 4f1f62d145b..c98dc1a1c4a 100644
--- a/app/serializers/projects/serverless/service_entity.rb
+++ b/app/serializers/projects/serverless/service_entity.rb
@@ -13,6 +13,25 @@ module Projects
service.dig('metadata', 'namespace')
end
+ expose :environment_scope do |service|
+ service.dig('environment_scope')
+ end
+
+ expose :cluster_id do |service|
+ service.dig('cluster_id')
+ end
+
+ expose :detail_url do |service|
+ project_serverless_path(
+ request.project,
+ service.dig('environment_scope'),
+ service.dig('metadata', 'name'))
+ end
+
+ expose :podcount do |service|
+ service.dig('podcount')
+ end
+
expose :created_at do |service|
service.dig('metadata', 'creationTimestamp')
end
@@ -22,11 +41,24 @@ module Projects
end
expose :description do |service|
- service.dig('spec', 'runLatest', 'configuration', 'revisionTemplate', 'metadata', 'annotations', 'Description')
+ service.dig(
+ 'spec',
+ 'runLatest',
+ 'configuration',
+ 'revisionTemplate',
+ 'metadata',
+ 'annotations',
+ 'Description')
end
expose :image do |service|
- service.dig('spec', 'runLatest', 'configuration', 'build', 'template', 'name')
+ service.dig(
+ 'spec',
+ 'runLatest',
+ 'configuration',
+ 'build',
+ 'template',
+ 'name')
end
end
end
diff --git a/app/serializers/provider_repo_entity.rb b/app/serializers/provider_repo_entity.rb
new file mode 100644
index 00000000000..d70aaa91324
--- /dev/null
+++ b/app/serializers/provider_repo_entity.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class ProviderRepoEntity < Grape::Entity
+ include ImportHelper
+
+ expose :id
+ expose :full_name
+ expose :owner_name do |provider_repo, options|
+ owner_name(provider_repo, options[:provider])
+ end
+
+ expose :sanitized_name do |provider_repo|
+ sanitize_project_name(provider_repo[:name])
+ end
+
+ expose :provider_link do |provider_repo, options|
+ provider_project_link_url(options[:provider_url], provider_repo[:full_name])
+ end
+
+ private
+
+ def owner_name(provider_repo, provider)
+ provider_repo.dig(:owner, :login) if provider == :github
+ end
+end
diff --git a/app/serializers/provider_repo_serializer.rb b/app/serializers/provider_repo_serializer.rb
new file mode 100644
index 00000000000..8a73f6fe6df
--- /dev/null
+++ b/app/serializers/provider_repo_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class ProviderRepoSerializer < BaseSerializer
+ entity ProviderRepoEntity
+end
diff --git a/app/serializers/tree_entity.rb b/app/serializers/tree_entity.rb
deleted file mode 100644
index 9b7dc80e1d9..00000000000
--- a/app/serializers/tree_entity.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class TreeEntity < Grape::Entity
- include RequestAwareEntity
-
- expose :id, :path, :name, :mode
-
- expose :icon do |tree|
- IconsHelper.file_type_icon_class('folder', tree.mode, tree.name)
- end
-
- expose :url do |tree|
- project_tree_path(request.project, File.join(request.ref, tree.path))
- end
-end
diff --git a/app/serializers/tree_root_entity.rb b/app/serializers/tree_root_entity.rb
deleted file mode 100644
index f1cfcd943d8..00000000000
--- a/app/serializers/tree_root_entity.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-# TODO: Inherit from TreeEntity, when `Tree` implements `id` and `name` like `Gitlab::Git::Tree`.
-class TreeRootEntity < Grape::Entity
- include RequestAwareEntity
-
- expose :path
-
- expose :trees, using: TreeEntity
- expose :blobs, using: BlobEntity
- expose :submodules, using: SubmoduleEntity
-
- expose :parent_tree_url do |tree|
- path = tree.path.sub(%r{\A/}, '')
- next unless path.present?
-
- path_segments = path.split('/')
- path_segments.pop
- parent_tree_path = path_segments.join('/')
-
- project_tree_path(request.project, File.join(request.ref, parent_tree_path))
- end
-
- expose :last_commit_path do |tree|
- logs_file_project_ref_path(request.project, request.ref, tree.path)
- end
-end
diff --git a/app/serializers/tree_serializer.rb b/app/serializers/tree_serializer.rb
deleted file mode 100644
index 536b8ab1ae2..00000000000
--- a/app/serializers/tree_serializer.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class TreeSerializer < BaseSerializer
- entity TreeRootEntity
-end
diff --git a/app/services/application_settings/update_service.rb b/app/services/application_settings/update_service.rb
index 2e4643ed668..9146eb96533 100644
--- a/app/services/application_settings/update_service.rb
+++ b/app/services/application_settings/update_service.rb
@@ -38,7 +38,7 @@ module ApplicationSettings
def performance_bar_allowed_group_id
performance_bar_enabled = !params.key?(:performance_bar_enabled) || params.delete(:performance_bar_enabled)
group_full_path = params.delete(:performance_bar_allowed_group_path)
- return nil unless Gitlab::Utils.to_boolean(performance_bar_enabled)
+ return unless Gitlab::Utils.to_boolean(performance_bar_enabled)
Group.find_by_full_path(group_full_path)&.id if group_full_path.present?
end
diff --git a/app/services/applications/create_service.rb b/app/services/applications/create_service.rb
index b6c30da4d3a..dff0d9696f8 100644
--- a/app/services/applications/create_service.rb
+++ b/app/services/applications/create_service.rb
@@ -2,16 +2,16 @@
module Applications
class CreateService
- # rubocop: disable CodeReuse/ActiveRecord
+ attr_reader :current_user, :params
+
def initialize(current_user, params)
@current_user = current_user
- @params = params.except(:ip_address)
+ @params = params.except(:ip_address) # rubocop: disable CodeReuse/ActiveRecord
end
- # rubocop: enable CodeReuse/ActiveRecord
# EE would override and use `request` arg
def execute(request)
- Doorkeeper::Application.create(@params)
+ Doorkeeper::Application.create(params)
end
end
end
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index f764536e762..e95ba09c006 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -160,7 +160,8 @@ module Auth
##
# We still support legacy pipeline triggers which do not have associated
# actor. New permissions model and new triggers are always associated with
- # an actor, so this should be improved in 10.0 version of GitLab.
+ # an actor. So this should be improved once
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/37452 is resolved.
#
def build_can_push?(requested_project)
# Build can push only to the project from which it originates
diff --git a/app/services/boards/issues/move_service.rb b/app/services/boards/issues/move_service.rb
index 43a26f4264e..834baeb9643 100644
--- a/app/services/boards/issues/move_service.rb
+++ b/app/services/boards/issues/move_service.rb
@@ -50,7 +50,7 @@ module Boards
if move_between_ids
attrs[:move_between_ids] = move_between_ids
- attrs[:board_group_id] = board.group&.id
+ attrs[:board_group_id] = board.group&.id
end
attrs
diff --git a/app/services/boards/lists/destroy_service.rb b/app/services/boards/lists/destroy_service.rb
index 609c430caed..e20805d0405 100644
--- a/app/services/boards/lists/destroy_service.rb
+++ b/app/services/boards/lists/destroy_service.rb
@@ -20,7 +20,7 @@ module Boards
# rubocop: disable CodeReuse/ActiveRecord
def decrement_higher_lists(list)
- board.lists.movable.where('position > ?', list.position)
+ board.lists.movable.where('position > ?', list.position)
.update_all('position = position - 1')
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/boards/visits/latest_service.rb b/app/services/boards/visits/latest_service.rb
index 9e4c77a6317..d13e25b4f12 100644
--- a/app/services/boards/visits/latest_service.rb
+++ b/app/services/boards/visits/latest_service.rb
@@ -4,13 +4,15 @@ module Boards
module Visits
class LatestService < Boards::BaseService
def execute
- return nil unless current_user
+ return unless current_user
- if parent.is_a?(Group)
- BoardGroupRecentVisit.latest(current_user, parent)
- else
- BoardProjectRecentVisit.latest(current_user, parent)
- end
+ recent_visit_model.latest(current_user, parent, count: params[:count])
+ end
+
+ private
+
+ def recent_visit_model
+ parent.is_a?(Group) ? BoardGroupRecentVisit : BoardProjectRecentVisit
end
end
end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 19b5552887f..8973c5ffc9e 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -7,14 +7,17 @@ module Ci
CreateError = Class.new(StandardError)
SEQUENCE = [Gitlab::Ci::Pipeline::Chain::Build,
+ Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs,
Gitlab::Ci::Pipeline::Chain::Validate::Abilities,
Gitlab::Ci::Pipeline::Chain::Validate::Repository,
Gitlab::Ci::Pipeline::Chain::Validate::Config,
Gitlab::Ci::Pipeline::Chain::Skip,
+ Gitlab::Ci::Pipeline::Chain::Limit::Size,
Gitlab::Ci::Pipeline::Chain::Populate,
- Gitlab::Ci::Pipeline::Chain::Create].freeze
+ Gitlab::Ci::Pipeline::Chain::Create,
+ Gitlab::Ci::Pipeline::Chain::Limit::Activity].freeze
- def execute(source, ignore_skip_ci: false, save_on_errors: true, trigger_request: nil, schedule: nil, merge_request: nil, &block)
+ def execute(source, ignore_skip_ci: false, save_on_errors: true, trigger_request: nil, schedule: nil, merge_request: nil, **options, &block)
@pipeline = Ci::Pipeline.new
command = Gitlab::Ci::Pipeline::Chain::Command.new(
@@ -22,7 +25,9 @@ module Ci
origin_ref: params[:ref],
checkout_sha: params[:checkout_sha],
after_sha: params[:after],
- before_sha: params[:before],
+ before_sha: params[:before], # The base SHA of the source branch (i.e merge_request.diff_base_sha).
+ source_sha: params[:source_sha], # The HEAD SHA of the source branch (i.e merge_request.diff_head_sha).
+ target_sha: params[:target_sha], # The HEAD SHA of the target branch.
trigger_request: trigger_request,
schedule: schedule,
merge_request: merge_request,
@@ -31,7 +36,10 @@ module Ci
seeds_block: block,
variables_attributes: params[:variables_attributes],
project: project,
- current_user: current_user)
+ current_user: current_user,
+ push_options: params[:push_options],
+ chat_data: params[:chat_data],
+ **extra_options(options))
sequence = Gitlab::Ci::Pipeline::Chain::Sequence
.new(pipeline, command, SEQUENCE)
@@ -102,5 +110,14 @@ module Ci
pipeline.project.source_of_merge_requests.opened.where(source_branch: pipeline.ref)
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def extra_options(options = {})
+ # In Ruby 2.4, even when options is empty, f(**options) doesn't work when f
+ # doesn't have any parameters. We reproduce the Ruby 2.5 behavior by
+ # checking explicitly that no arguments are given.
+ raise ArgumentError if options.any?
+
+ {} # overridden in EE
+ end
end
end
diff --git a/app/services/ci/destroy_expired_job_artifacts_service.rb b/app/services/ci/destroy_expired_job_artifacts_service.rb
new file mode 100644
index 00000000000..7d2f5d33fed
--- /dev/null
+++ b/app/services/ci/destroy_expired_job_artifacts_service.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Ci
+ class DestroyExpiredJobArtifactsService
+ include ::Gitlab::ExclusiveLeaseHelpers
+ include ::Gitlab::LoopHelpers
+
+ BATCH_SIZE = 100
+ LOOP_TIMEOUT = 45.minutes
+ LOOP_LIMIT = 1000
+ EXCLUSIVE_LOCK_KEY = 'expired_job_artifacts:destroy:lock'
+ LOCK_TIMEOUT = 50.minutes
+
+ ##
+ # Destroy expired job artifacts on GitLab instance
+ #
+ # This destroy process cannot run for more than 45 minutes. This is for
+ # preventing multiple `ExpireBuildArtifactsWorker` CRON jobs run concurrently,
+ # which is scheduled at every hour.
+ def execute
+ in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
+ loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
+ destroy_batch
+ end
+ end
+ end
+
+ private
+
+ def destroy_batch
+ artifacts = Ci::JobArtifact.expired(BATCH_SIZE).to_a
+
+ return false if artifacts.empty?
+
+ artifacts.each(&:destroy!)
+ end
+ end
+end
diff --git a/app/services/ci/destroy_pipeline_service.rb b/app/services/ci/destroy_pipeline_service.rb
index 13f892aabb8..5c4a34043c1 100644
--- a/app/services/ci/destroy_pipeline_service.rb
+++ b/app/services/ci/destroy_pipeline_service.rb
@@ -5,8 +5,6 @@ module Ci
def execute(pipeline)
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :destroy_pipeline, pipeline)
- AuditEventService.new(current_user, pipeline).security_event
-
pipeline.destroy!
end
end
diff --git a/app/services/ci/pipeline_trigger_service.rb b/app/services/ci/pipeline_trigger_service.rb
index f54574b026b..2dbb7c3917d 100644
--- a/app/services/ci/pipeline_trigger_service.rb
+++ b/app/services/ci/pipeline_trigger_service.rb
@@ -7,6 +7,8 @@ module Ci
def execute
if trigger_from_token
create_pipeline_from_trigger(trigger_from_token)
+ elsif job_from_token
+ create_pipeline_from_job(job_from_token)
end
end
@@ -35,6 +37,14 @@ module Ci
end
end
+ def create_pipeline_from_job(job)
+ # overridden in EE
+ end
+
+ def job_from_token
+ # overridden in EE
+ end
+
def variables
params[:variables].to_h.map do |key, value|
{ key: key, value: value }
diff --git a/app/services/ci/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb
index 446188347df..4a7ce00b8e2 100644
--- a/app/services/ci/process_pipeline_service.rb
+++ b/app/services/ci/process_pipeline_service.rb
@@ -10,7 +10,7 @@ module Ci
update_retried
new_builds =
- stage_indexes_of_created_builds.map do |index|
+ stage_indexes_of_created_processables.map do |index|
process_stage(index)
end
@@ -27,7 +27,7 @@ module Ci
return if HasStatus::BLOCKED_STATUS.include?(current_status)
if HasStatus::COMPLETED_STATUSES.include?(current_status)
- created_builds_in_stage(index).select do |build|
+ created_processables_in_stage(index).select do |build|
Gitlab::OptimisticLocking.retry_lock(build) do |subject|
Ci::ProcessBuildService.new(project, @user)
.execute(build, current_status)
@@ -43,19 +43,19 @@ module Ci
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def stage_indexes_of_created_builds
- created_builds.order(:stage_idx).pluck('distinct stage_idx')
+ def stage_indexes_of_created_processables
+ created_processables.order(:stage_idx).pluck('distinct stage_idx')
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def created_builds_in_stage(index)
- created_builds.where(stage_idx: index)
+ def created_processables_in_stage(index)
+ created_processables.where(stage_idx: index)
end
# rubocop: enable CodeReuse/ActiveRecord
- def created_builds
- pipeline.builds.created
+ def created_processables
+ pipeline.processables.created
end
# This method is for compatibility and data consistency and should be removed with 9.3 version of GitLab
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index 218f1e63d08..fab8a179843 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -2,7 +2,7 @@
module Ci
class RetryBuildService < ::BaseService
- CLONE_ACCESSORS = %i[pipeline project ref tag options commands name
+ CLONE_ACCESSORS = %i[pipeline project ref tag options name
allow_failure stage stage_id stage_idx trigger_request
yaml_variables when environment coverage_regex
description tag_list protected].freeze
diff --git a/app/services/clusters/applications/base_helm_service.rb b/app/services/clusters/applications/base_helm_service.rb
index e86ca8cf1d0..8a71730d5ec 100644
--- a/app/services/clusters/applications/base_helm_service.rb
+++ b/app/services/clusters/applications/base_helm_service.rb
@@ -45,6 +45,10 @@ module Clusters
def install_command
@install_command ||= app.install_command
end
+
+ def upgrade_command(new_values = "")
+ app.upgrade_command(new_values)
+ end
end
end
end
diff --git a/app/services/clusters/applications/check_installation_progress_service.rb b/app/services/clusters/applications/check_installation_progress_service.rb
index 21ec26ea233..c592d608b89 100644
--- a/app/services/clusters/applications/check_installation_progress_service.rb
+++ b/app/services/clusters/applications/check_installation_progress_service.rb
@@ -4,7 +4,7 @@ module Clusters
module Applications
class CheckInstallationProgressService < BaseHelmService
def execute
- return unless app.installing?
+ return unless operation_in_progress?
case installation_phase
when Gitlab::Kubernetes::Pod::SUCCEEDED
@@ -16,11 +16,16 @@ module Clusters
end
rescue Kubeclient::HttpError => e
log_error(e)
- app.make_errored!("Kubernetes error: #{e.error_code}") unless app.errored?
+
+ app.make_errored!("Kubernetes error: #{e.error_code}")
end
private
+ def operation_in_progress?
+ app.installing? || app.updating?
+ end
+
def on_success
app.make_installed!
ensure
@@ -28,13 +33,13 @@ module Clusters
end
def on_failed
- app.make_errored!("Installation failed. Check pod logs for #{install_command.pod_name} for more details.")
+ app.make_errored!("Operation failed. Check pod logs for #{pod_name} for more details.")
end
def check_timeout
if timeouted?
begin
- app.make_errored!("Installation timed out. Check pod logs for #{install_command.pod_name} for more details.")
+ app.make_errored!("Operation timed out. Check pod logs for #{pod_name} for more details.")
end
else
ClusterWaitForAppInstallationWorker.perform_in(
@@ -42,20 +47,24 @@ module Clusters
end
end
+ def pod_name
+ install_command.pod_name
+ end
+
def timeouted?
Time.now.utc - app.updated_at.to_time.utc > ClusterWaitForAppInstallationWorker::TIMEOUT
end
def remove_installation_pod
- helm_api.delete_pod!(install_command.pod_name)
+ helm_api.delete_pod!(pod_name)
end
def installation_phase
- helm_api.status(install_command.pod_name)
+ helm_api.status(pod_name)
end
def installation_errors
- helm_api.log(install_command.pod_name)
+ helm_api.log(pod_name)
end
end
end
diff --git a/app/services/clusters/applications/create_service.rb b/app/services/clusters/applications/create_service.rb
index 92c2c1b9834..12f8c849d41 100644
--- a/app/services/clusters/applications/create_service.rb
+++ b/app/services/clusters/applications/create_service.rb
@@ -27,9 +27,11 @@ module Clusters
application.oauth_application = create_oauth_application(application, request)
end
- application.save!
+ worker = application.updateable? ? ClusterUpgradeAppWorker : ClusterInstallAppWorker
- Clusters::Applications::ScheduleInstallationService.new(application).execute
+ application.make_scheduled!
+
+ worker.perform_async(application.name, application.id)
end
end
diff --git a/app/services/clusters/applications/schedule_installation_service.rb b/app/services/clusters/applications/schedule_installation_service.rb
deleted file mode 100644
index d75ba70c27e..00000000000
--- a/app/services/clusters/applications/schedule_installation_service.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module Clusters
- module Applications
- class ScheduleInstallationService
- attr_reader :application
-
- def initialize(application)
- @application = application
- end
-
- def execute
- application.make_scheduled!
-
- ClusterInstallAppWorker.perform_async(application.name, application.id)
- end
- end
- end
-end
diff --git a/app/services/clusters/applications/upgrade_service.rb b/app/services/clusters/applications/upgrade_service.rb
new file mode 100644
index 00000000000..a0ece1d2635
--- /dev/null
+++ b/app/services/clusters/applications/upgrade_service.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class UpgradeService < BaseHelmService
+ def execute
+ return unless app.scheduled?
+
+ begin
+ app.make_updating!
+
+ # install_command works with upgrades too
+ # as it basically does `helm upgrade --install`
+ helm_api.update(install_command)
+
+ ClusterWaitForAppInstallationWorker.perform_in(
+ ClusterWaitForAppInstallationWorker::INTERVAL, app.name, app.id)
+ rescue Kubeclient::HttpError => e
+ log_error(e)
+ app.make_update_errored!("Kubernetes error: #{e.error_code}")
+ rescue StandardError => e
+ log_error(e)
+ app.make_update_errored!("Can't start upgrade process.")
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/commits/create_service.rb b/app/services/commits/create_service.rb
index 34593e12bd5..bb34a3d3352 100644
--- a/app/services/commits/create_service.rb
+++ b/app/services/commits/create_service.rb
@@ -11,6 +11,7 @@ module Commits
@start_project = params[:start_project] || @project
@start_branch = params[:start_branch]
@branch_name = params[:branch_name]
+ @force = params[:force] || false
end
def execute
@@ -42,10 +43,14 @@ module Commits
@start_branch != @branch_name || @start_project != @project
end
+ def force?
+ !!@force
+ end
+
def validate!
validate_permissions!
validate_on_branch!
- validate_branch_existance!
+ validate_branch_existence!
validate_new_branch_name! if different_branch?
end
@@ -64,14 +69,14 @@ module Commits
end
end
- def validate_branch_existance!
- if !project.empty_repo? && different_branch? && repository.branch_exists?(@branch_name)
+ def validate_branch_existence!
+ if !project.empty_repo? && different_branch? && repository.branch_exists?(@branch_name) && !force?
raise_error("A branch called '#{@branch_name}' already exists. Switch to that branch in order to make changes")
end
end
def validate_new_branch_name!
- result = ValidateNewBranchService.new(project, current_user).execute(@branch_name)
+ result = ValidateNewBranchService.new(project, current_user).execute(@branch_name, force: force?)
if result[:status] == :error
raise_error("Something went wrong when we tried to create '#{@branch_name}' for you: #{result[:message]}")
diff --git a/app/services/commits/tag_service.rb b/app/services/commits/tag_service.rb
index 7961ba4d3c4..bb8cfb63f98 100644
--- a/app/services/commits/tag_service.rb
+++ b/app/services/commits/tag_service.rb
@@ -9,11 +9,10 @@ module Commits
tag_name = params[:tag_name]
message = params[:tag_message]
- release_description = nil
result = Tags::CreateService
.new(commit.project, current_user)
- .execute(tag_name, commit.sha, message, release_description)
+ .execute(tag_name, commit.sha, message)
if result[:status] == :success
tag = result[:tag]
diff --git a/app/services/concerns/exclusive_lease_guard.rb b/app/services/concerns/exclusive_lease_guard.rb
index f102e00d150..2cb73555d85 100644
--- a/app/services/concerns/exclusive_lease_guard.rb
+++ b/app/services/concerns/exclusive_lease_guard.rb
@@ -6,9 +6,14 @@
#
# `#try_obtain_lease` takes a block which will be run if it was able to
# obtain the lease. Implement `#lease_timeout` to configure the timeout
-# for the exclusive lease. Optionally override `#lease_key` to set the
+# for the exclusive lease.
+#
+# Optionally override `#lease_key` to set the
# lease key, it defaults to the class name with underscores.
#
+# Optionally override `#lease_release?` to prevent the job to
+# be re-executed more often than LEASE_TIMEOUT.
+#
module ExclusiveLeaseGuard
extend ActiveSupport::Concern
@@ -23,7 +28,7 @@ module ExclusiveLeaseGuard
begin
yield lease
ensure
- release_lease(lease)
+ release_lease(lease) if lease_release?
end
end
@@ -37,7 +42,11 @@ module ExclusiveLeaseGuard
def lease_timeout
raise NotImplementedError,
- "#{self.class.name} does not implement #{__method__}"
+ "#{self.class.name} does not implement #{__method__}"
+ end
+
+ def lease_release?
+ true
end
def release_lease(uuid)
diff --git a/app/services/concerns/users/participable_service.rb b/app/services/concerns/users/participable_service.rb
index 5b408bd96c7..6713b6617ae 100644
--- a/app/services/concerns/users/participable_service.rb
+++ b/app/services/concerns/users/participable_service.rb
@@ -11,7 +11,7 @@ module Users
def noteable_owner
return [] unless noteable && noteable.author.present?
- [as_hash(noteable.author)]
+ [user_as_hash(noteable.author)]
end
def participants_in_noteable
@@ -23,21 +23,24 @@ module Users
def sorted(users)
users.uniq.to_a.compact.sort_by(&:username).map do |user|
- as_hash(user)
+ user_as_hash(user)
end
end
def groups
current_user.authorized_groups.sort_by(&:path).map do |group|
- count = group.users.count
- { username: group.full_path, name: group.full_name, count: count, avatar_url: group.avatar_url }
+ group_as_hash(group)
end
end
private
- def as_hash(user)
- { username: user.username, name: user.name, avatar_url: user.avatar_url }
+ def user_as_hash(user)
+ { type: user.class.name, username: user.username, name: user.name, avatar_url: user.avatar_url }
+ end
+
+ def group_as_hash(group)
+ { type: group.class.name, username: group.full_path, name: group.full_name, avatar_url: group.avatar_url, count: group.users.count }
end
end
end
diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb
index 65208b07e27..110e589e30d 100644
--- a/app/services/create_branch_service.rb
+++ b/app/services/create_branch_service.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
class CreateBranchService < BaseService
- def execute(branch_name, ref)
- create_master_branch if project.empty_repo?
+ def execute(branch_name, ref, create_master_if_empty: true)
+ create_master_branch if create_master_if_empty && project.empty_repo?
result = ValidateNewBranchService.new(project, current_user)
.execute(branch_name)
diff --git a/app/services/create_release_service.rb b/app/services/create_release_service.rb
deleted file mode 100644
index ab2dc5337aa..00000000000
--- a/app/services/create_release_service.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class CreateReleaseService < BaseService
- # rubocop: disable CodeReuse/ActiveRecord
- def execute(tag_name, release_description)
- repository = project.repository
- existing_tag = repository.find_tag(tag_name)
-
- # Only create a release if the tag exists
- if existing_tag
- release = project.releases.find_by(tag: tag_name)
-
- if release
- error('Release already exists', 409)
- else
- release = project.releases.create!(
- tag: tag_name,
- name: tag_name,
- sha: existing_tag.dereferenced_target.sha,
- author: current_user,
- description: release_description
- )
-
- success(release)
- end
- else
- error('Tag does not exist', 404)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def success(release)
- super().merge(release: release)
- end
-end
diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb
index 44252f7b0a6..8322a3d74f4 100644
--- a/app/services/delete_branch_service.rb
+++ b/app/services/delete_branch_service.rb
@@ -14,7 +14,7 @@ class DeleteBranchService < BaseService
end
if repository.rm_branch(current_user, branch_name)
- success('Branch was removed')
+ success('Branch was deleted')
else
error('Failed to remove branch')
end
diff --git a/app/services/emails/base_service.rb b/app/services/emails/base_service.rb
index 988215ffc78..99324638300 100644
--- a/app/services/emails/base_service.rb
+++ b/app/services/emails/base_service.rb
@@ -2,10 +2,11 @@
module Emails
class BaseService
- attr_reader :current_user
+ attr_reader :current_user, :params, :user
def initialize(current_user, params = {})
- @current_user, @params = current_user, params.dup
+ @current_user = current_user
+ @params = params.dup
@user = params.delete(:user)
end
end
diff --git a/app/services/emails/create_service.rb b/app/services/emails/create_service.rb
index 56925a724fe..dc06a5caa40 100644
--- a/app/services/emails/create_service.rb
+++ b/app/services/emails/create_service.rb
@@ -3,12 +3,11 @@
module Emails
class CreateService < ::Emails::BaseService
def execute(extra_params = {})
- skip_confirmation = @params.delete(:skip_confirmation)
+ skip_confirmation = params.delete(:skip_confirmation)
- email = @user.emails.create(@params.merge(extra_params))
-
- email&.confirm if skip_confirmation && current_user.admin?
- email
+ user.emails.create(params.merge(extra_params)).tap do |email|
+ email&.confirm if skip_confirmation && current_user.admin?
+ end
end
end
end
diff --git a/app/services/error_tracking/list_issues_service.rb b/app/services/error_tracking/list_issues_service.rb
new file mode 100644
index 00000000000..a6c6bec9598
--- /dev/null
+++ b/app/services/error_tracking/list_issues_service.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module ErrorTracking
+ class ListIssuesService < ::BaseService
+ DEFAULT_ISSUE_STATUS = 'unresolved'
+ DEFAULT_LIMIT = 20
+
+ def execute
+ return error('Error Tracking is not enabled') unless enabled?
+ return error('Access denied', :unauthorized) unless can_read?
+
+ result = project_error_tracking_setting
+ .list_sentry_issues(issue_status: issue_status, limit: limit)
+
+ # our results are not yet ready
+ unless result
+ return error('Not ready. Try again later', :no_content)
+ end
+
+ if result[:error].present?
+ return error(result[:error], :bad_request)
+ end
+
+ success(issues: result[:issues])
+ end
+
+ def external_url
+ project_error_tracking_setting&.sentry_external_url
+ end
+
+ private
+
+ def project_error_tracking_setting
+ project.error_tracking_setting
+ end
+
+ def issue_status
+ params[:issue_status] || DEFAULT_ISSUE_STATUS
+ end
+
+ def limit
+ params[:limit] || DEFAULT_LIMIT
+ end
+
+ def enabled?
+ project_error_tracking_setting&.enabled?
+ end
+
+ def can_read?
+ can?(current_user, :read_sentry_issue, project)
+ end
+ end
+end
diff --git a/app/services/error_tracking/list_projects_service.rb b/app/services/error_tracking/list_projects_service.rb
new file mode 100644
index 00000000000..4e92353a13c
--- /dev/null
+++ b/app/services/error_tracking/list_projects_service.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module ErrorTracking
+ class ListProjectsService < ::BaseService
+ def execute
+ return error('access denied') unless can_read?
+
+ setting = project_error_tracking_setting
+
+ unless setting.valid?
+ return error(setting.errors.full_messages.join(', '), :bad_request)
+ end
+
+ begin
+ result = setting.list_sentry_projects
+ rescue Sentry::Client::Error => e
+ return error(e.message, :bad_request)
+ rescue Sentry::Client::SentryError => e
+ return error(e.message, :unprocessable_entity)
+ end
+
+ success(projects: result[:projects])
+ end
+
+ private
+
+ def project_error_tracking_setting
+ (project.error_tracking_setting || project.build_error_tracking_setting).tap do |setting|
+ setting.api_url = ErrorTracking::ProjectErrorTrackingSetting.build_api_url_from(
+ api_host: params[:api_host],
+ organization_slug: 'org',
+ project_slug: 'proj'
+ )
+
+ setting.token = params[:token]
+ setting.enabled = true
+ end
+ end
+
+ def can_read?
+ can?(current_user, :read_sentry_issue, project)
+ end
+ end
+end
diff --git a/app/services/files/multi_service.rb b/app/services/files/multi_service.rb
index 927634c2159..c1bc26c330a 100644
--- a/app/services/files/multi_service.rb
+++ b/app/services/files/multi_service.rb
@@ -46,7 +46,8 @@ module Files
author_email: @author_email,
author_name: @author_name,
start_project: @start_project,
- start_branch_name: @start_branch
+ start_branch_name: @start_branch,
+ force: force?
)
rescue ArgumentError => e
raise_error(e)
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index f1883877d56..f387c749a21 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -140,7 +140,7 @@ class GitPushService < BaseService
.perform_async(project.id, current_user.id, params[:oldrev], params[:newrev], params[:ref])
EventCreateService.new.push(project, current_user, build_push_data)
- Ci::CreatePipelineService.new(project, current_user, build_push_data).execute(:push)
+ Ci::CreatePipelineService.new(project, current_user, build_push_data).execute(:push, pipeline_options)
project.execute_hooks(build_push_data.dup, :push_hooks)
project.execute_services(build_push_data.dup, :push_hooks)
@@ -174,7 +174,8 @@ class GitPushService < BaseService
params[:newrev],
params[:ref],
@push_commits,
- commits_count: commits_count)
+ commits_count: commits_count,
+ push_options: params[:push_options] || [])
end
def push_to_existing_branch?
@@ -230,4 +231,10 @@ class GitPushService < BaseService
def last_pushed_commits
@last_pushed_commits ||= @push_commits.last(PROCESS_COMMIT_LIMIT)
end
+
+ private
+
+ def pipeline_options
+ {} # to be overridden in EE
+ end
end
diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb
index dbadafc0f52..e39b3603c6c 100644
--- a/app/services/git_tag_push_service.rb
+++ b/app/services/git_tag_push_service.rb
@@ -10,7 +10,7 @@ class GitTagPushService < BaseService
@push_data = build_push_data
EventCreateService.new.push(project, current_user, push_data)
- Ci::CreatePipelineService.new(project, current_user, push_data).execute(:push)
+ Ci::CreatePipelineService.new(project, current_user, push_data).execute(:push, pipeline_options)
SystemHooksService.new.execute_hooks(build_system_push_data, :tag_push_hooks)
project.execute_hooks(push_data.dup, :tag_push_hooks)
@@ -45,7 +45,8 @@ class GitTagPushService < BaseService
params[:newrev],
params[:ref],
commits,
- message)
+ message,
+ push_options: params[:push_options] || [])
end
def build_system_push_data
@@ -58,4 +59,8 @@ class GitTagPushService < BaseService
[],
'')
end
+
+ def pipeline_options
+ {} # to be overridden in EE
+ end
end
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index 24d8400c625..99ead467f74 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -10,6 +10,8 @@ module Groups
def execute
@group = Group.new(params)
+ after_build_hook(@group, params)
+
unless can_use_visibility_level? && can_create_group?
return @group
end
@@ -30,6 +32,10 @@ module Groups
private
+ def after_build_hook(group, params)
+ # overridden in EE
+ end
+
def create_chat_team?
Gitlab.config.mattermost.enabled && @chat_team && group.chat_team.nil?
end
diff --git a/app/services/groups/nested_create_service.rb b/app/services/groups/nested_create_service.rb
index f01f5656296..01bd685712b 100644
--- a/app/services/groups/nested_create_service.rb
+++ b/app/services/groups/nested_create_service.rb
@@ -12,7 +12,7 @@ module Groups
end
def execute
- return nil unless group_path
+ return unless group_path
if namespace = namespace_or_group(group_path)
return namespace
diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb
index f64e327416a..94185605ab9 100644
--- a/app/services/groups/transfer_service.rb
+++ b/app/services/groups/transfer_service.rb
@@ -35,7 +35,10 @@ module Groups
def proceed_to_transfer
Group.transaction do
update_group_attributes
+ ensure_ownership
end
+
+ true
end
def ensure_allowed_transfer
@@ -95,6 +98,13 @@ module Groups
end
# rubocop: enable CodeReuse/ActiveRecord
+ def ensure_ownership
+ return if @new_parent_group
+ return unless @group.owners.empty?
+
+ @group.add_owner(current_user)
+ end
+
def raise_transfer_error(message)
raise TransferError, ERROR_MESSAGES[message]
end
diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb
index 31d3c844ad5..787445180f0 100644
--- a/app/services/groups/update_service.rb
+++ b/app/services/groups/update_service.rb
@@ -11,6 +11,8 @@ module Groups
return false unless valid_share_with_group_lock_change?
+ before_assignment_hook(group, params)
+
group.assign_attributes(params)
begin
@@ -28,10 +30,14 @@ module Groups
private
+ def before_assignment_hook(group, params)
+ # overridden in EE
+ end
+
def after_update
if group.previous_changes.include?(:visibility_level) && group.private?
# don't enqueue immediately to prevent todos removal in case of a mistake
- TodosDestroyer::GroupPrivateWorker.perform_in(1.hour, group.id)
+ TodosDestroyer::GroupPrivateWorker.perform_in(Todo::WAIT_FOR_DELETE, group.id)
end
end
diff --git a/app/services/import/base_service.rb b/app/services/import/base_service.rb
new file mode 100644
index 00000000000..2683c75e41f
--- /dev/null
+++ b/app/services/import/base_service.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Import
+ class BaseService < ::BaseService
+ def initialize(client, user, params)
+ @client = client
+ @current_user = user
+ @params = params
+ end
+
+ private
+
+ def find_or_create_namespace(namespace, owner)
+ namespace = params[:target_namespace].presence || namespace
+
+ return current_user.namespace if namespace == owner
+
+ group = Groups::NestedCreateService.new(current_user, group_path: namespace).execute
+
+ group.errors.any? ? current_user.namespace : group
+ rescue => e
+ Gitlab::AppLogger.error(e)
+
+ current_user.namespace
+ end
+
+ def project_save_error(project)
+ project.errors.full_messages.join(', ')
+ end
+
+ def success(project)
+ super().merge(project: project, status: :success)
+ end
+ end
+end
diff --git a/app/services/import/github_service.rb b/app/services/import/github_service.rb
new file mode 100644
index 00000000000..a2533683da9
--- /dev/null
+++ b/app/services/import/github_service.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Import
+ class GithubService < Import::BaseService
+ attr_accessor :client
+ attr_reader :params, :current_user
+
+ def execute(access_params, provider)
+ unless authorized?
+ return error('This namespace has already been taken! Please choose another one.', :unprocessable_entity)
+ end
+
+ project = Gitlab::LegacyGithubImport::ProjectCreator
+ .new(repo, project_name, target_namespace, current_user, access_params, type: provider)
+ .execute(extra_project_attrs)
+
+ if project.persisted?
+ success(project)
+ else
+ error(project_save_error(project), :unprocessable_entity)
+ end
+ end
+
+ def repo
+ @repo ||= client.repo(params[:repo_id].to_i)
+ end
+
+ def project_name
+ @project_name ||= params[:new_name].presence || repo.name
+ end
+
+ def namespace_path
+ @namespace_path ||= params[:target_namespace].presence || current_user.namespace_path
+ end
+
+ def target_namespace
+ @target_namespace ||= find_or_create_namespace(namespace_path, current_user.namespace_path)
+ end
+
+ def extra_project_attrs
+ {}
+ end
+
+ def authorized?
+ can?(current_user, :create_projects, target_namespace)
+ end
+ end
+end
diff --git a/app/services/issuable/common_system_notes_service.rb b/app/services/issuable/common_system_notes_service.rb
index 885e14bba8f..77f38f8882e 100644
--- a/app/services/issuable/common_system_notes_service.rb
+++ b/app/services/issuable/common_system_notes_service.rb
@@ -20,7 +20,7 @@ module Issuable
create_due_date_note if issuable.previous_changes.include?('due_date')
create_milestone_note if issuable.previous_changes.include?('milestone_id')
- create_labels_note(old_labels) if issuable.labels != old_labels
+ create_labels_note(old_labels) if old_labels && issuable.labels != old_labels
end
private
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index c7e7bb55e4b..f35ad2a9d8b 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -61,10 +61,10 @@ class IssuableBaseService < BaseService
return unless milestone_id
params[:milestone_id] = '' if milestone_id == IssuableFinder::NONE
- group_ids = project.group&.self_and_ancestors&.pluck(:id)
+ groups = project.group&.self_and_ancestors&.select(:id)
milestone =
- Milestone.for_projects_and_groups([project.id], group_ids).find_by_id(milestone_id)
+ Milestone.for_projects_and_groups([project.id], groups).find_by_id(milestone_id)
params[:milestone_id] = '' unless milestone
end
@@ -89,7 +89,7 @@ class IssuableBaseService < BaseService
return unless labels
- params[:label_ids] = labels.split(",").map do |label_name|
+ params[:label_ids] = labels.map do |label_name|
label = Labels::FindOrCreateService.new(
current_user,
parent,
@@ -235,6 +235,61 @@ class IssuableBaseService < BaseService
issuable
end
+ def update_task(issuable)
+ filter_params(issuable)
+
+ if issuable.changed? || params.present?
+ issuable.assign_attributes(params.merge(updated_by: current_user,
+ last_edited_at: Time.now,
+ last_edited_by: current_user))
+
+ before_update(issuable)
+
+ if issuable.with_transaction_returning_status { issuable.save }
+ # We do not touch as it will affect a update on updated_at field
+ ActiveRecord::Base.no_touching do
+ Issuable::CommonSystemNotesService.new(project, current_user).execute(issuable, old_labels: nil)
+ end
+
+ handle_task_changes(issuable)
+ invalidate_cache_counts(issuable, users: issuable.assignees.to_a)
+ after_update(issuable)
+ execute_hooks(issuable, 'update', old_associations: nil)
+ end
+ end
+
+ issuable
+ end
+
+ # Handle the `update_task` event sent from UI. Attempts to update a specific
+ # line in the markdown and cached html, bypassing any unnecessary updates or checks.
+ def update_task_event(issuable)
+ update_task_params = params.delete(:update_task)
+ return unless update_task_params
+
+ tasklist_toggler = TaskListToggleService.new(issuable.description, issuable.description_html,
+ line_source: update_task_params[:line_source],
+ line_number: update_task_params[:line_number].to_i,
+ toggle_as_checked: update_task_params[:checked])
+
+ unless tasklist_toggler.execute
+ # if we make it here, the data is much newer than we thought it was - fail fast
+ raise ActiveRecord::StaleObjectError
+ end
+
+ # by updating the description_html field at the same time,
+ # the markdown cache won't be considered invalid
+ params[:description] = tasklist_toggler.updated_markdown
+ params[:description_html] = tasklist_toggler.updated_markdown_html
+
+ # since we're updating a very specific line, we don't care whether
+ # the `lock_version` sent from the FE is the same or not. Just
+ # make sure the data hasn't changed since we queried it
+ params[:lock_version] = issuable.lock_version
+
+ update_task(issuable)
+ end
+
def labels_changing?(old_label_ids, new_label_ids)
old_label_ids.sort != new_label_ids.sort
end
@@ -318,6 +373,10 @@ class IssuableBaseService < BaseService
end
# override if needed
+ def handle_task_changes(issuable)
+ end
+
+ # override if needed
def execute_hooks(issuable, action = 'open', params = {})
end
@@ -328,4 +387,10 @@ class IssuableBaseService < BaseService
def parent
project
end
+
+ # we need to check this because milestone from milestone_id param is displayed on "new" page
+ # where private project milestone could leak without this check
+ def ensure_milestone_available(issuable)
+ issuable.milestone_id = nil unless issuable.milestone_available?
+ end
end
diff --git a/app/services/issues/build_service.rb b/app/services/issues/build_service.rb
index 52b45f1b2ce..61615ac2058 100644
--- a/app/services/issues/build_service.rb
+++ b/app/services/issues/build_service.rb
@@ -6,7 +6,9 @@ module Issues
def execute
filter_resolve_discussion_params
- @issue = project.issues.new(issue_params)
+ @issue = project.issues.new(issue_params).tap do |issue|
+ ensure_milestone_available(issue)
+ end
end
def issue_params_with_info_from_discussions
@@ -57,9 +59,11 @@ module Issues
end
def issue_params
- @issue_params ||= issue_params_with_info_from_discussions.merge(whitelisted_issue_params)
+ @issue_params ||= build_issue_params
end
+ private
+
def whitelisted_issue_params
if can?(current_user, :admin_issue, project)
params.slice(:title, :description, :milestone_id)
@@ -67,5 +71,9 @@ module Issues
params.slice(:title, :description)
end
end
+
+ def build_issue_params
+ issue_params_with_info_from_discussions.merge(whitelisted_issue_params)
+ end
end
end
diff --git a/app/services/issues/import_csv_service.rb b/app/services/issues/import_csv_service.rb
new file mode 100644
index 00000000000..ef08fafa7cc
--- /dev/null
+++ b/app/services/issues/import_csv_service.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module Issues
+ class ImportCsvService
+ def initialize(user, project, csv_io)
+ @user = user
+ @project = project
+ @csv_io = csv_io
+ @results = { success: 0, error_lines: [], parse_error: false }
+ end
+
+ def execute
+ process_csv
+ email_results_to_user
+
+ @results
+ end
+
+ private
+
+ def process_csv
+ csv_data = @csv_io.open(&:read).force_encoding(Encoding::UTF_8)
+
+ CSV.new(csv_data, col_sep: detect_col_sep(csv_data.lines.first), headers: true).each.with_index(2) do |row, line_no|
+ issue = Issues::CreateService.new(@project, @user, title: row[0], description: row[1]).execute
+
+ if issue.persisted?
+ @results[:success] += 1
+ else
+ @results[:error_lines].push(line_no)
+ end
+ end
+ rescue ArgumentError, CSV::MalformedCSVError
+ @results[:parse_error] = true
+ end
+
+ def email_results_to_user
+ Notify.import_issues_csv_email(@user.id, @project.id, @results).deliver_now
+ end
+
+ def detect_col_sep(header)
+ if header.include?(",")
+ ","
+ elsif header.include?(";")
+ ";"
+ elsif header.include?("\t")
+ "\t"
+ else
+ raise CSV::MalformedCSVError
+ end
+ end
+ end
+end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index a1d0cc0e568..cec5b5734c0 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -8,7 +8,7 @@ module Issues
handle_move_between_ids(issue)
filter_spam_check_params
change_issue_duplicate(issue)
- move_issue_to_new_project(issue) || update(issue)
+ move_issue_to_new_project(issue) || update_task_event(issue) || update(issue)
end
def update(issue)
@@ -44,7 +44,7 @@ module Issues
if issue.previous_changes.include?('confidential')
# don't enqueue immediately to prevent todos removal in case of a mistake
- TodosDestroyer::ConfidentialIssueWorker.perform_in(1.hour, issue.id) if issue.confidential?
+ TodosDestroyer::ConfidentialIssueWorker.perform_in(Todo::WAIT_FOR_DELETE, issue.id) if issue.confidential?
create_confidentiality_note(issue)
end
@@ -63,6 +63,11 @@ module Issues
end
end
+ def handle_task_changes(issuable)
+ todo_service.mark_pending_todos_as_done(issuable, current_user)
+ todo_service.update_issue(issuable, current_user)
+ end
+
def handle_move_between_ids(issue)
return unless params[:move_between_ids]
@@ -78,6 +83,8 @@ module Issues
# rubocop: disable CodeReuse/ActiveRecord
def change_issue_duplicate(issue)
canonical_issue_id = params.delete(:canonical_issue_id)
+ return unless canonical_issue_id
+
canonical_issue = IssuesFinder.new(current_user).find_by(id: canonical_issue_id)
if canonical_issue
diff --git a/app/services/labels/create_service.rb b/app/services/labels/create_service.rb
index fe34be41ac1..db710bac900 100644
--- a/app/services/labels/create_service.rb
+++ b/app/services/labels/create_service.rb
@@ -3,7 +3,7 @@
module Labels
class CreateService < Labels::BaseService
def initialize(params = {})
- @params = params.dup.with_indifferent_access
+ @params = params.to_h.dup.with_indifferent_access
end
# returns the created label
diff --git a/app/services/labels/promote_service.rb b/app/services/labels/promote_service.rb
index 3c0e6196d4f..e73e6476c12 100644
--- a/app/services/labels/promote_service.rb
+++ b/app/services/labels/promote_service.rb
@@ -49,7 +49,7 @@ module Labels
.new(current_user, title: new_label.title, group_id: project.group.id)
.execute(skip_authorization: true)
.where.not(id: new_label)
- .select(:id) # Can't use pluck() to avoid object-creation because of the batching
+ .select(:id) # Can't use pluck() to avoid object-creation because of the batching
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/labels/update_service.rb b/app/services/labels/update_service.rb
index c3a720a1c66..be33947d0eb 100644
--- a/app/services/labels/update_service.rb
+++ b/app/services/labels/update_service.rb
@@ -3,11 +3,12 @@
module Labels
class UpdateService < Labels::BaseService
def initialize(params = {})
- @params = params.dup.with_indifferent_access
+ @params = params.to_h.dup.with_indifferent_access
end
# returns the updated label
def execute(label)
+ params[:name] = params.delete(:new_name) if params.key?(:new_name)
params[:color] = convert_color_name_to_hex if params[:color].present?
label.update(params)
diff --git a/app/services/lfs/locks_finder_service.rb b/app/services/lfs/locks_finder_service.rb
index 4a5b2a52921..192ce3d3c2a 100644
--- a/app/services/lfs/locks_finder_service.rb
+++ b/app/services/lfs/locks_finder_service.rb
@@ -12,7 +12,7 @@ module Lfs
# rubocop: disable CodeReuse/ActiveRecord
def find_locks
- options = params.slice(:id, :path).compact.symbolize_keys
+ options = params.slice(:id, :path).to_h.compact.symbolize_keys
project.lfs_file_locks.where(options)
end
diff --git a/app/services/members/base_service.rb b/app/services/members/base_service.rb
index d734571f835..e78affff797 100644
--- a/app/services/members/base_service.rb
+++ b/app/services/members/base_service.rb
@@ -47,5 +47,11 @@ module Members
raise "Unknown action '#{action}' on #{member}!"
end
end
+
+ def enqueue_delete_todos(member)
+ type = member.is_a?(GroupMember) ? 'Group' : 'Project'
+ # don't enqueue immediately to prevent todos removal in case of a mistake
+ TodosDestroyer::EntityLeaveWorker.perform_in(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, type)
+ end
end
end
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index 714b8586737..cf710fef52b 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -19,9 +19,19 @@ module Members
current_user: current_user
)
- members.each { |member| after_execute(member: member) }
+ errors = []
- success
+ members.each do |member|
+ if member.errors.any?
+ errors << "#{member.user.username}: #{member.errors.full_messages.to_sentence}"
+ else
+ after_execute(member: member)
+ end
+ end
+
+ return success unless errors.any?
+
+ error(errors.to_sentence)
end
private
diff --git a/app/services/members/destroy_service.rb b/app/services/members/destroy_service.rb
index c186a5971dc..f9717a9426b 100644
--- a/app/services/members/destroy_service.rb
+++ b/app/services/members/destroy_service.rb
@@ -2,9 +2,11 @@
module Members
class DestroyService < Members::BaseService
- def execute(member, skip_authorization: false)
+ def execute(member, skip_authorization: false, skip_subresources: false)
raise Gitlab::Access::AccessDeniedError unless skip_authorization || can_destroy_member?(member)
+ @skip_auth = skip_authorization
+
return member if member.is_a?(GroupMember) && member.source.last_owner?(member.user)
member.destroy
@@ -15,7 +17,8 @@ module Members
notification_service.decline_access_request(member)
end
- enqeue_delete_todos(member)
+ delete_subresources(member) unless skip_subresources
+ enqueue_delete_todos(member)
after_execute(member: member)
@@ -24,10 +27,27 @@ module Members
private
- def enqeue_delete_todos(member)
- type = member.is_a?(GroupMember) ? 'Group' : 'Project'
- # don't enqueue immediately to prevent todos removal in case of a mistake
- TodosDestroyer::EntityLeaveWorker.perform_in(1.hour, member.user_id, member.source_id, type)
+ def delete_subresources(member)
+ return unless member.is_a?(GroupMember) && member.user && member.group
+
+ delete_project_members(member)
+ delete_subgroup_members(member) if Group.supports_nested_objects?
+ end
+
+ def delete_project_members(member)
+ groups = member.group.self_and_descendants
+
+ ProjectMember.in_namespaces(groups).with_user(member.user).each do |project_member|
+ self.class.new(current_user).execute(project_member, skip_authorization: @skip_auth)
+ end
+ end
+
+ def delete_subgroup_members(member)
+ groups = member.group.descendants
+
+ GroupMember.in_groups(groups).with_user(member.user).each do |group_member|
+ self.class.new(current_user).execute(group_member, skip_authorization: @skip_auth, skip_subresources: true)
+ end
end
def can_destroy_member?(member)
diff --git a/app/services/members/update_service.rb b/app/services/members/update_service.rb
index 1f5618dae53..ff8d5c1d8c9 100644
--- a/app/services/members/update_service.rb
+++ b/app/services/members/update_service.rb
@@ -10,9 +10,18 @@ module Members
if member.update(params)
after_execute(action: permission, old_access_level: old_access_level, member: member)
+
+ # Deletes only confidential issues todos for guests
+ enqueue_delete_todos(member) if downgrading_to_guest?
end
member
end
+
+ private
+
+ def downgrading_to_guest?
+ params[:access_level] == Gitlab::Access::GUEST
+ end
end
end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index fe19abf50f6..11ede5223e5 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -63,10 +63,11 @@ module MergeRequests
# UpdateMergeRequestsWorker could be retried by an exception.
# MR pipelines should not be recreated in such case.
return if merge_request.merge_request_pipeline_exists?
+ return if merge_request.has_no_commits?
Ci::CreatePipelineService
.new(merge_request.source_project, user, ref: merge_request.source_branch)
- .execute(:merge_request,
+ .execute(:merge_request_event,
ignore_skip_ci: true,
save_on_errors: false,
merge_request: merge_request)
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 36767621d74..109c964e577 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -18,7 +18,8 @@ module MergeRequests
merge_request.source_project = find_source_project
merge_request.target_project = find_target_project
merge_request.target_branch = find_target_branch
- merge_request.can_be_created = branches_valid?
+ merge_request.can_be_created = projects_and_branches_valid?
+ ensure_milestone_available(merge_request)
# compare branches only if branches are valid, otherwise
# compare_branches may raise an error
@@ -49,15 +50,19 @@ module MergeRequests
to: :merge_request
def find_source_project
- return source_project if source_project.present? && can?(current_user, :read_project, source_project)
+ return source_project if source_project.present? && can?(current_user, :create_merge_request_from, source_project)
project
end
def find_target_project
- return target_project if target_project.present? && can?(current_user, :read_project, target_project)
+ return target_project if target_project.present? && can?(current_user, :create_merge_request_in, target_project)
- project.default_merge_request_target
+ target_project = project.default_merge_request_target
+
+ return target_project if target_project.present? && can?(current_user, :create_merge_request_in, target_project)
+
+ project
end
def find_target_branch
@@ -72,10 +77,11 @@ module MergeRequests
params[:target_branch].present?
end
- def branches_valid?
+ def projects_and_branches_valid?
+ return false if source_project.nil? || target_project.nil?
return false unless source_branch_specified? || target_branch_specified?
- validate_branches
+ validate_projects_and_branches
errors.blank?
end
@@ -94,7 +100,12 @@ module MergeRequests
end
end
- def validate_branches
+ def validate_projects_and_branches
+ merge_request.validate_target_project
+ merge_request.validate_fork
+
+ return if errors.any?
+
add_error('You must select source and target branch') unless branches_present?
add_error('You must select different branches') if same_source_and_target?
add_error("Source branch \"#{source_branch}\" does not exist") unless source_branch_exists?
diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb
index 7bb9fa60515..02c2388c05c 100644
--- a/app/services/merge_requests/create_service.rb
+++ b/app/services/merge_requests/create_service.rb
@@ -26,7 +26,7 @@ module MergeRequests
todo_service.new_merge_request(issuable, current_user)
issuable.cache_merge_request_closes_issues!(current_user)
create_merge_request_pipeline(issuable, current_user)
- update_merge_requests_head_pipeline(issuable)
+ issuable.update_head_pipeline
super
end
@@ -45,20 +45,6 @@ module MergeRequests
private
- def update_merge_requests_head_pipeline(merge_request)
- pipeline = head_pipeline_for(merge_request)
- merge_request.update(head_pipeline_id: pipeline.id) if pipeline
- end
-
- def head_pipeline_for(merge_request)
- return unless merge_request.source_project
-
- sha = merge_request.source_branch_sha
- return unless sha
-
- merge_request.all_pipelines(shas: sha).first
- end
-
def set_projects!
# @project is used to determine whether the user can set the merge request's
# assignee, milestone and labels. Whether they can depends on their
diff --git a/app/services/merge_requests/merge_base_service.rb b/app/services/merge_requests/merge_base_service.rb
new file mode 100644
index 00000000000..095bdca5472
--- /dev/null
+++ b/app/services/merge_requests/merge_base_service.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class MergeBaseService < MergeRequests::BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ MergeError = Class.new(StandardError)
+
+ attr_reader :merge_request
+
+ # Overridden in EE.
+ def hooks_validation_pass?(_merge_request)
+ true
+ end
+
+ # Overridden in EE.
+ def hooks_validation_error(_merge_request)
+ # No-op
+ end
+
+ def source
+ if merge_request.squash
+ squash_sha!
+ else
+ merge_request.diff_head_sha
+ end
+ end
+
+ private
+
+ # Overridden in EE.
+ def error_check!
+ # No-op
+ end
+
+ def raise_error(message)
+ raise MergeError, message
+ end
+
+ def handle_merge_error(*args)
+ # No-op
+ end
+
+ def commit_message
+ params[:commit_message] ||
+ merge_request.default_merge_commit_message
+ end
+
+ def squash_sha!
+ strong_memoize(:squash_sha) do
+ params[:merge_request] = merge_request
+ squash_result = ::MergeRequests::SquashService.new(project, current_user, params).execute
+
+ case squash_result[:status]
+ when :success
+ squash_result[:squash_sha]
+ when :error
+ raise ::MergeRequests::MergeService::MergeError, squash_result[:message]
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index 70a67baa01c..b29e0b1759e 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -7,11 +7,7 @@ module MergeRequests
# mark merge request as merged and execute all hooks and notifications
# Executed when you do merge via GitLab UI
#
- class MergeService < MergeRequests::BaseService
- MergeError = Class.new(StandardError)
-
- attr_reader :merge_request, :source
-
+ class MergeService < MergeRequests::MergeBaseService
delegate :merge_jid, :state, to: :@merge_request
def execute(merge_request)
@@ -22,7 +18,7 @@ module MergeRequests
@merge_request = merge_request
- error_check!
+ validate!
merge_request.in_locked_state do
if commit
@@ -36,27 +32,22 @@ module MergeRequests
handle_merge_error(log_message: e.message, save_message_on_model: true)
end
- def source
- return merge_request.diff_head_sha unless merge_request.squash
-
- squash_result = ::MergeRequests::SquashService.new(project, current_user, params).execute(merge_request)
+ private
- case squash_result[:status]
- when :success
- squash_result[:squash_sha]
- when :error
- raise ::MergeRequests::MergeService::MergeError, squash_result[:message]
- end
+ def validate!
+ authorization_check!
+ error_check!
end
- # Overridden in EE.
- def hooks_validation_pass?(_merge_request)
- true
+ def authorization_check!
+ unless @merge_request.can_be_merged_by?(current_user)
+ raise_error('You are not allowed to merge this merge request')
+ end
end
- private
-
def error_check!
+ super
+
error =
if @merge_request.should_be_rebased?
'Only fast-forward merge is allowed for your project. Please update your source branch'
@@ -66,7 +57,7 @@ module MergeRequests
'No source for merge'
end
- raise MergeError, error if error
+ raise_error(error) if error
end
def commit
@@ -76,22 +67,19 @@ module MergeRequests
if commit_id
log_info("Git merge finished on JID #{merge_jid} commit #{commit_id}")
else
- raise MergeError, 'Conflicts detected during merge'
+ raise_error('Conflicts detected during merge')
end
merge_request.update!(merge_commit_sha: commit_id)
end
def try_merge
- message = params[:commit_message] || merge_request.merge_commit_message
-
- repository.merge(current_user, source, merge_request, message)
+ repository.merge(current_user, source, merge_request, commit_message)
rescue Gitlab::Git::PreReceiveError => e
- handle_merge_error(log_message: e.message)
- raise MergeError, 'Something went wrong during merge pre-receive hook'
+ raise_error("Something went wrong during merge pre-receive hook: #{e.message}")
rescue => e
handle_merge_error(log_message: e.message)
- raise MergeError, 'Something went wrong during merge'
+ raise_error('Something went wrong during merge')
ensure
merge_request.update!(in_progress_merge_commit_sha: nil)
end
diff --git a/app/services/merge_requests/merge_to_ref_service.rb b/app/services/merge_requests/merge_to_ref_service.rb
new file mode 100644
index 00000000000..586652ae44e
--- /dev/null
+++ b/app/services/merge_requests/merge_to_ref_service.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ # Performs the merge between source SHA and the target branch. Instead
+ # of writing the result to the MR target branch, it targets the `target_ref`.
+ #
+ # Ideally this should leave the `target_ref` state with the same state the
+ # target branch would have if we used the regular `MergeService`, but without
+ # every side-effect that comes with it (MR updates, mails, source branch
+ # deletion, etc). This service should be kept idempotent (i.e. can
+ # be executed regardless of the `target_ref` current state).
+ #
+ class MergeToRefService < MergeRequests::MergeBaseService
+ def execute(merge_request)
+ @merge_request = merge_request
+
+ validate!
+
+ commit_id = commit
+
+ raise_error('Conflicts detected during merge') unless commit_id
+
+ success(commit_id: commit_id)
+ rescue MergeError => error
+ error(error.message)
+ end
+
+ private
+
+ def validate!
+ authorization_check!
+ error_check!
+ end
+
+ def error_check!
+ super
+
+ error =
+ if Feature.disabled?(:merge_to_tmp_merge_ref_path, project)
+ 'Feature is not enabled'
+ elsif !merge_method_supported?
+ "#{project.human_merge_method} to #{target_ref} is currently not supported."
+ elsif !hooks_validation_pass?(merge_request)
+ hooks_validation_error(merge_request)
+ elsif @merge_request.should_be_rebased?
+ 'Fast-forward merge is not possible. Please update your source branch.'
+ elsif !@merge_request.mergeable_to_ref?
+ "Merge request is not mergeable to #{target_ref}"
+ elsif !source
+ 'No source for merge'
+ end
+
+ raise_error(error) if error
+ end
+
+ def authorization_check!
+ unless Ability.allowed?(current_user, :admin_merge_request, project)
+ raise_error("You are not allowed to merge to this ref")
+ end
+ end
+
+ def target_ref
+ merge_request.merge_ref_path
+ end
+
+ def commit
+ repository.merge_to_ref(current_user, source, merge_request, target_ref, commit_message)
+ rescue Gitlab::Git::PreReceiveError => error
+ raise MergeError, error.message
+ end
+
+ def merge_method_supported?
+ [:merge, :rebase_merge].include?(project.merge_method)
+ end
+ end
+end
diff --git a/app/services/merge_requests/squash_service.rb b/app/services/merge_requests/squash_service.rb
index a439a380255..9d1a5d5e6d4 100644
--- a/app/services/merge_requests/squash_service.rb
+++ b/app/services/merge_requests/squash_service.rb
@@ -2,15 +2,10 @@
module MergeRequests
class SquashService < MergeRequests::WorkingCopyBaseService
- def execute(merge_request)
- @merge_request = merge_request
- @repository = target_project.repository
-
- squash || error('Failed to squash. Should be done manually.')
- end
-
- def squash
- if merge_request.commits_count < 2
+ def execute
+ # If performing a squash would result in no change, then
+ # immediately return a success message without performing a squash
+ if merge_request.commits_count < 2 && message.nil?
return success(squash_sha: merge_request.diff_head_sha)
end
@@ -18,7 +13,13 @@ module MergeRequests
return error('Squash task canceled: another squash is already in progress.')
end
- squash_sha = repository.squash(current_user, merge_request)
+ squash! || error('Failed to squash. Should be done manually.')
+ end
+
+ private
+
+ def squash!
+ squash_sha = repository.squash(current_user, merge_request, message || merge_request.default_squash_commit_message)
success(squash_sha: squash_sha)
rescue => e
@@ -26,5 +27,17 @@ module MergeRequests
log_error(e.message)
false
end
+
+ def repository
+ target_project.repository
+ end
+
+ def merge_request
+ params[:merge_request]
+ end
+
+ def message
+ params[:squash_commit_message].presence
+ end
end
end
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 33d8299c8b6..8112c2a4299 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -21,7 +21,7 @@ module MergeRequests
end
handle_wip_event(merge_request)
- update(merge_request)
+ update_task_event(merge_request) || update(merge_request)
end
# rubocop:disable Metrics/AbcSize
@@ -46,11 +46,13 @@ module MergeRequests
end
if merge_request.previous_changes.include?('assignee_id')
+ reassigned_merge_request_args = [merge_request, current_user]
+
old_assignee_id = merge_request.previous_changes['assignee_id'].first
- old_assignee = User.find(old_assignee_id) if old_assignee_id
+ reassigned_merge_request_args << User.find(old_assignee_id) if old_assignee_id
create_assignee_note(merge_request)
- notification_service.async.reassigned_merge_request(merge_request, current_user, old_assignee)
+ notification_service.async.reassigned_merge_request(*reassigned_merge_request_args)
todo_service.reassigned_merge_request(merge_request, current_user)
end
@@ -81,6 +83,11 @@ module MergeRequests
end
# rubocop:enable Metrics/AbcSize
+ def handle_task_changes(merge_request)
+ todo_service.mark_pending_todos_as_done(merge_request, current_user)
+ todo_service.update_merge_request(merge_request, current_user)
+ end
+
def merge_from_quick_action(merge_request)
last_diff_sha = params.delete(:merge)
return unless merge_request.mergeable_with_quick_action?(current_user, last_diff_sha: last_diff_sha)
diff --git a/app/services/milestones/promote_service.rb b/app/services/milestones/promote_service.rb
index 39071b5dc14..cbe5996e8ca 100644
--- a/app/services/milestones/promote_service.rb
+++ b/app/services/milestones/promote_service.rb
@@ -82,11 +82,9 @@ module Milestones
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def group_project_ids
- @group_project_ids ||= group.projects.pluck(:id)
+ group.projects.select(:id)
end
- # rubocop: enable CodeReuse/ActiveRecord
def raise_error(message)
raise PromoteMilestoneError, "Promotion failed - #{message}"
diff --git a/app/services/notes/build_service.rb b/app/services/notes/build_service.rb
index 7b92fe6fe14..541f3e0d23c 100644
--- a/app/services/notes/build_service.rb
+++ b/app/services/notes/build_service.rb
@@ -9,12 +9,14 @@ module Notes
if in_reply_to_discussion_id.present?
discussion = find_discussion(in_reply_to_discussion_id)
- unless discussion
+ unless discussion && can?(current_user, :create_note, discussion.noteable)
note = Note.new
note.errors.add(:base, 'Discussion to reply to cannot be found')
return note
end
+ discussion = discussion.convert_to_discussion! if discussion.can_convert_to_discussion?
+
params.merge!(discussion.reply_attributes)
should_resolve = discussion.resolved?
end
@@ -34,19 +36,8 @@ module Notes
if project
project.notes.find_discussion(discussion_id)
else
- discussion = Note.find_discussion(discussion_id)
- noteable = discussion.noteable
-
- return nil unless noteable_without_project?(noteable)
-
- discussion
+ Note.find_discussion(discussion_id)
end
end
-
- def noteable_without_project?(noteable)
- return true if noteable.is_a?(PersonalSnippet) && can?(current_user, :comment_personal_snippet, noteable)
-
- false
- end
end
end
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index c4546f30235..1b46f6d8a72 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -21,7 +21,7 @@ module Notes
if quick_actions_service.supported?(note)
options = { merge_request_diff_head_sha: merge_request_diff_head_sha }
- content, command_params = quick_actions_service.extract_commands(note, options)
+ content, update_params = quick_actions_service.execute(note, options)
only_commands = content.empty?
@@ -34,21 +34,26 @@ module Notes
end
if !only_commands && note.save
+ if note.part_of_discussion? && note.discussion.can_convert_to_discussion?
+ note.discussion.convert_to_discussion!(save: true)
+ end
+
todo_service.new_note(note, current_user)
clear_noteable_diffs_cache(note)
Suggestions::CreateService.new(note).execute
end
- if command_params.present?
- quick_actions_service.execute(command_params, note)
+ 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
+ end
# We must add the error after we call #save because errors are reset
# when #save is called
if only_commands
note.errors.add(:commands_only, 'Commands applied')
end
-
- note.commands_changes = command_params
end
note
diff --git a/app/services/notes/quick_actions_service.rb b/app/services/notes/quick_actions_service.rb
index 4c14d834949..0852a708240 100644
--- a/app/services/notes/quick_actions_service.rb
+++ b/app/services/notes/quick_actions_service.rb
@@ -1,15 +1,31 @@
# frozen_string_literal: true
+# QuickActionsService class
+#
+# Executes quick actions commands extracted from note text
+#
+# Most commands returns parameters to be applied later
+# using QuickActionService#apply_updates
+#
module Notes
class QuickActionsService < BaseService
+ attr_reader :interpret_service
+
+ delegate :commands_executed_count, to: :interpret_service, allow_nil: true
+
UPDATE_SERVICES = {
'Issue' => Issues::UpdateService,
'MergeRequest' => MergeRequests::UpdateService,
'Commit' => Commits::TagService
}.freeze
+ private_constant :UPDATE_SERVICES
+
+ def self.update_services
+ UPDATE_SERVICES
+ end
def self.noteable_update_service(note)
- UPDATE_SERVICES[note.noteable_type]
+ update_services[note.noteable_type]
end
def self.supported?(note)
@@ -20,18 +36,21 @@ module Notes
self.class.supported?(note)
end
- def extract_commands(note, options = {})
+ def execute(note, options = {})
return [note.note, {}] unless supported?(note)
- QuickActions::InterpretService.new(project, current_user, options)
- .execute(note.note, note.noteable)
+ @interpret_service = QuickActions::InterpretService.new(project, current_user, options)
+
+ @interpret_service.execute(note.note, note.noteable)
end
- def execute(command_params, note)
- return if command_params.empty?
+ # Applies updates extracted to note#noteable
+ # The update parameters are extracted on self#execute
+ def apply_updates(update_params, note)
+ return if update_params.empty?
return unless supported?(note)
- self.class.noteable_update_service(note).new(project, current_user, command_params).execute(note.noteable)
+ self.class.noteable_update_service(note).new(note.parent, current_user, update_params).execute(note.noteable)
end
end
end
diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb
index 68cdc69023a..56f11b31110 100644
--- a/app/services/notification_recipient_service.rb
+++ b/app/services/notification_recipient_service.rb
@@ -249,6 +249,7 @@ module NotificationRecipientService
attr_reader :action
attr_reader :previous_assignee
attr_reader :skip_current_user
+
def initialize(target, current_user, action:, custom_action: nil, previous_assignee: nil, skip_current_user: true)
@target = target
@current_user = current_user
@@ -258,9 +259,13 @@ module NotificationRecipientService
@skip_current_user = skip_current_user
end
+ def add_watchers
+ add_project_watchers
+ end
+
def build!
add_participants(current_user)
- add_project_watchers
+ add_watchers
add_custom_notifications
# Re-assign is considered as a mention of the new assignee
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index ff035fea216..1a65561dd70 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -188,7 +188,7 @@ class NotificationService
# * merge_request assignee if their notification level is not Disabled
# * users with custom level checked with "reassign merge request"
#
- def reassigned_merge_request(merge_request, current_user, previous_assignee)
+ def reassigned_merge_request(merge_request, current_user, previous_assignee = nil)
recipients = NotificationRecipientService.build_recipients(
merge_request,
current_user,
@@ -373,7 +373,8 @@ class NotificationService
end
def project_was_moved(project, old_path_with_namespace)
- recipients = notifiable_users(project.team.members, :mention, project: project)
+ recipients = project.private? ? project.team.members_in_project_and_ancestors : project.team.members
+ recipients = notifiable_users(recipients, :mention, project: project)
recipients.each do |recipient|
mailer.project_was_moved_email(
diff --git a/app/services/preview_markdown_service.rb b/app/services/preview_markdown_service.rb
index a449a5dc3e9..c1655c38095 100644
--- a/app/services/preview_markdown_service.rb
+++ b/app/services/preview_markdown_service.rb
@@ -10,8 +10,7 @@ class PreviewMarkdownService < BaseService
text: text,
users: users,
suggestions: suggestions,
- commands: commands.join(' '),
- markdown_engine: markdown_engine
+ commands: commands.join(' ')
)
end
@@ -49,12 +48,4 @@ class PreviewMarkdownService < BaseService
def commands_target_id
params[:quick_actions_target_id]
end
-
- def markdown_engine
- if params[:legacy_render]
- :redcarpet
- else
- CacheMarkdownField::MarkdownEngine.from_version(params[:markdown_version].to_i)
- end
- end
end
diff --git a/app/services/projects/after_rename_service.rb b/app/services/projects/after_rename_service.rb
index aa9b253eb20..fafdecb3222 100644
--- a/app/services/projects/after_rename_service.rb
+++ b/app/services/projects/after_rename_service.rb
@@ -12,22 +12,27 @@ module Projects
#
# Projects::AfterRenameService.new(project).execute
class AfterRenameService
- attr_reader :project, :full_path_before, :full_path_after, :path_before
+ # @return [String] The Project being renamed.
+ attr_reader :project
- RenameFailedError = Class.new(StandardError)
+ # @return [String] The path slug the project was using, before the rename took place.
+ attr_reader :path_before
- # @param [Project] project The Project of the repository to rename.
- def initialize(project)
- @project = project
+ # @return [String] The full path of the namespace + project, before the rename took place.
+ attr_reader :full_path_before
- # The full path of the namespace + project, before the rename took place.
- @full_path_before = project.full_path_was
+ # @return [String] The full path of the namespace + project, after the rename took place.
+ attr_reader :full_path_after
- # The full path of the namespace + project, after the rename took place.
- @full_path_after = project.build_full_path
+ RenameFailedError = Class.new(StandardError)
- # The path of just the project, before the rename took place.
- @path_before = project.path_was
+ # @param [Project] project The Project being renamed.
+ # @param [String] path_before The path slug the project was using, before the rename took place.
+ def initialize(project, path_before:, full_path_before:)
+ @project = project
+ @path_before = path_before
+ @full_path_before = full_path_before
+ @full_path_after = project.full_path
end
def execute
@@ -57,11 +62,11 @@ module Projects
def rename_or_migrate_repository!
success =
if migrate_to_hashed_storage?
- ::Projects::HashedStorageMigrationService
+ ::Projects::HashedStorage::MigrationService
.new(project, full_path_before)
.execute
else
- project.storage.rename_repo
+ project.storage.rename_repo(old_full_path: full_path_before, new_full_path: full_path_after)
end
rename_failed! unless success
diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb
index 61f6402a810..3dad90188cf 100644
--- a/app/services/projects/autocomplete_service.rb
+++ b/app/services/projects/autocomplete_service.rb
@@ -14,7 +14,7 @@ module Projects
order: { due_date: :asc, title: :asc }
}
- finder_params[:group_ids] = @project.group.self_and_ancestors_ids if @project.group
+ finder_params[:group_ids] = @project.group.self_and_ancestors.select(:id) if @project.group
MilestonesFinder.new(finder_params).execute.select([:iid, :title])
end
diff --git a/app/services/projects/container_repository/cleanup_tags_service.rb b/app/services/projects/container_repository/cleanup_tags_service.rb
new file mode 100644
index 00000000000..488290db824
--- /dev/null
+++ b/app/services/projects/container_repository/cleanup_tags_service.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+module Projects
+ module ContainerRepository
+ class CleanupTagsService < BaseService
+ def execute(container_repository)
+ return error('feature disabled') unless can_use?
+ return error('access denied') unless can_admin?
+
+ tags = container_repository.tags
+ tags_by_digest = group_by_digest(tags)
+
+ tags = without_latest(tags)
+ tags = filter_by_name(tags)
+ tags = with_manifest(tags)
+ tags = order_by_date(tags)
+ tags = filter_keep_n(tags)
+ tags = filter_by_older_than(tags)
+
+ deleted_tags = delete_tags(tags, tags_by_digest)
+
+ success(deleted: deleted_tags.map(&:name))
+ end
+
+ private
+
+ def delete_tags(tags_to_delete, tags_by_digest)
+ deleted_digests = group_by_digest(tags_to_delete).select do |digest, tags|
+ delete_tag_digest(digest, tags, tags_by_digest[digest])
+ end
+
+ deleted_digests.values.flatten
+ end
+
+ def delete_tag_digest(digest, tags, other_tags)
+ # Issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/21405
+ # we have to remove all tags due
+ # to Docker Distribution bug unable
+ # to delete single tag
+ return unless tags.count == other_tags.count
+
+ # delete all tags
+ tags.map(&:delete)
+ end
+
+ def group_by_digest(tags)
+ tags.group_by(&:digest)
+ end
+
+ def without_latest(tags)
+ tags.reject(&:latest?)
+ end
+
+ def with_manifest(tags)
+ tags.select(&:valid?)
+ end
+
+ def order_by_date(tags)
+ now = DateTime.now
+ tags.sort_by { |tag| tag.created_at || now }.reverse
+ end
+
+ def filter_by_name(tags)
+ regex = Gitlab::UntrustedRegexp.new("\\A#{params['name_regex']}\\z")
+
+ tags.select do |tag|
+ regex.scan(tag.name).any?
+ end
+ end
+
+ def filter_keep_n(tags)
+ tags.drop(params['keep_n'].to_i)
+ end
+
+ def filter_by_older_than(tags)
+ return tags unless params['older_than']
+
+ older_than = ChronicDuration.parse(params['older_than']).seconds.ago
+
+ tags.select do |tag|
+ tag.created_at && tag.created_at < older_than
+ end
+ end
+
+ def can_admin?
+ can?(current_user, :admin_container_image, project)
+ end
+
+ def can_use?
+ Feature.enabled?(:container_registry_cleanup, project, default_enabled: true)
+ end
+ end
+ end
+end
diff --git a/app/services/projects/create_from_template_service.rb b/app/services/projects/create_from_template_service.rb
index 8306d43ca7c..678bc0d24c3 100644
--- a/app/services/projects/create_from_template_service.rb
+++ b/app/services/projects/create_from_template_service.rb
@@ -5,7 +5,7 @@ module Projects
include Gitlab::Utils::StrongMemoize
def initialize(user, params)
- @current_user, @params = user, params.dup
+ @current_user, @params = user, params.to_h.dup
end
def execute
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 336d029d330..b14b31302f5 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -7,9 +7,16 @@ module Projects
DestroyError = Class.new(StandardError)
DELETED_FLAG = '+deleted'.freeze
+ REPO_REMOVAL_DELAY = 5.minutes.to_i
def async_execute
project.update_attribute(:pending_delete, true)
+
+ # Ensure no repository +deleted paths are kept,
+ # regardless of any issue with the ProjectDestroyWorker
+ # job process.
+ schedule_stale_repos_removal
+
job_id = ProjectDestroyWorker.perform_async(project.id, current_user.id, params)
Rails.logger.info("User #{current_user.id} scheduled destruction of project #{project.full_path} with job ID #{job_id}")
end
@@ -92,14 +99,23 @@ module Projects
log_info(%Q{Repository "#{path}" moved to "#{new_path}" for project "#{project.full_path}"})
project.run_after_commit do
- # self is now project
- GitlabShellWorker.perform_in(5.minutes, :remove_repository, self.repository_storage, new_path)
+ GitlabShellWorker.perform_in(REPO_REMOVAL_DELAY, :remove_repository, self.repository_storage, new_path)
end
else
false
end
end
+ def schedule_stale_repos_removal
+ repo_paths = [removal_path(repo_path), removal_path(wiki_path)]
+
+ # Ideally it should wait until the regular removal phase finishes,
+ # so let's delay it a bit further.
+ repo_paths.each do |path|
+ GitlabShellWorker.perform_in(REPO_REMOVAL_DELAY * 2, :remove_repository, project.repository_storage, path)
+ end
+ end
+
def rollback_repository(old_path, new_path)
# There is a possibility project does not have repository or wiki
return true unless repo_exists?(old_path)
@@ -113,13 +129,11 @@ module Projects
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def mv_repository(from_path, to_path)
- return true unless gitlab_shell.exists?(project.repository_storage, from_path + '.git')
+ return true unless repo_exists?(from_path)
gitlab_shell.mv_repository(project.repository_storage, from_path, to_path)
end
- # rubocop: enable CodeReuse/ActiveRecord
def attempt_rollback(project, message)
return unless project
diff --git a/app/services/projects/download_service.rb b/app/services/projects/download_service.rb
index dd297c9ba43..aba175eb79b 100644
--- a/app/services/projects/download_service.rb
+++ b/app/services/projects/download_service.rb
@@ -11,7 +11,7 @@ module Projects
end
def execute
- return nil unless valid_url?(@url)
+ return unless valid_url?(@url)
uploader = FileUploader.new(@project)
uploader.download!(@url)
diff --git a/app/services/projects/fetch_statistics_increment_service.rb b/app/services/projects/fetch_statistics_increment_service.rb
new file mode 100644
index 00000000000..8644e6bf313
--- /dev/null
+++ b/app/services/projects/fetch_statistics_increment_service.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Projects
+ class FetchStatisticsIncrementService
+ attr_reader :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ def execute
+ increment_fetch_count_sql = <<~SQL
+ INSERT INTO #{table_name} (project_id, date, fetch_count)
+ VALUES (#{project.id}, '#{Date.today}', 1)
+ SQL
+
+ increment_fetch_count_sql += if Gitlab::Database.postgresql?
+ "ON CONFLICT (project_id, date) DO UPDATE SET fetch_count = #{table_name}.fetch_count + 1"
+ else
+ "ON DUPLICATE KEY UPDATE fetch_count = #{table_name}.fetch_count + 1"
+ end
+
+ ActiveRecord::Base.connection.execute(increment_fetch_count_sql)
+ end
+
+ private
+
+ def table_name
+ ProjectDailyStatistic.table_name
+ end
+ end
+end
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index 91091c4393d..fc234bafc57 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -38,8 +38,8 @@ module Projects
new_params = {
visibility_level: allowed_visibility_level,
description: @project.description,
- name: @project.name,
- path: @project.path,
+ name: target_name,
+ path: target_path,
shared_runners_enabled: @project.shared_runners_enabled,
namespace_id: target_namespace.id,
fork_network: fork_network,
@@ -94,6 +94,14 @@ module Projects
Projects::ForksCountService.new(@project).refresh_cache
end
+ def target_path
+ @target_path ||= @params[:path] || @project.path
+ end
+
+ def target_name
+ @target_name ||= @params[:name] || @project.name
+ end
+
def target_namespace
@target_namespace ||= @params[:namespace] || current_user.namespace
end
diff --git a/app/services/projects/group_links/create_service.rb b/app/services/projects/group_links/create_service.rb
index 1392775f805..e3d5bea0852 100644
--- a/app/services/projects/group_links/create_service.rb
+++ b/app/services/projects/group_links/create_service.rb
@@ -4,13 +4,19 @@ module Projects
module GroupLinks
class CreateService < BaseService
def execute(group)
- return false unless group
+ return error('Not Found', 404) unless group && can?(current_user, :read_namespace, group)
- project.project_group_links.create(
+ link = project.project_group_links.new(
group: group,
group_access: params[:link_group_access],
expires_at: params[:expires_at]
)
+
+ if link.save
+ success(link: link)
+ else
+ error(link.errors.full_messages.to_sentence, 409)
+ end
end
end
end
diff --git a/app/services/projects/hashed_storage/base_attachment_service.rb b/app/services/projects/hashed_storage/base_attachment_service.rb
new file mode 100644
index 00000000000..828ab616bab
--- /dev/null
+++ b/app/services/projects/hashed_storage/base_attachment_service.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Projects
+ module HashedStorage
+ AttachmentMigrationError = Class.new(StandardError)
+
+ AttachmentCannotMoveError = Class.new(StandardError)
+
+ class BaseAttachmentService < BaseService
+ # Returns the disk_path value before the execution
+ attr_reader :old_disk_path
+
+ # Returns the disk_path value after the execution
+ attr_reader :new_disk_path
+
+ # Returns the logger currently in use
+ attr_reader :logger
+
+ # Return whether this operation was skipped or not
+ #
+ # @return [Boolean] true if skipped of false otherwise
+ def skipped?
+ @skipped
+ end
+
+ protected
+
+ def move_folder!(old_path, new_path)
+ unless File.directory?(old_path)
+ logger.info("Skipped attachments move from '#{old_path}' to '#{new_path}', source path doesn't exist or is not a directory (PROJECT_ID=#{project.id})")
+ @skipped = true
+
+ return true
+ end
+
+ if File.exist?(new_path)
+ logger.error("Cannot move attachments from '#{old_path}' to '#{new_path}', target path already exist (PROJECT_ID=#{project.id})")
+ raise AttachmentCannotMoveError, "Target path '#{new_path}' already exists"
+ end
+
+ # Create base path folder on the new storage layout
+ FileUtils.mkdir_p(File.dirname(new_path))
+
+ FileUtils.mv(old_path, new_path)
+ logger.info("Project attachments moved from '#{old_path}' to '#{new_path}' (PROJECT_ID=#{project.id})")
+
+ true
+ end
+ end
+ end
+end
diff --git a/app/services/projects/hashed_storage/base_repository_service.rb b/app/services/projects/hashed_storage/base_repository_service.rb
new file mode 100644
index 00000000000..f97a28b8c3b
--- /dev/null
+++ b/app/services/projects/hashed_storage/base_repository_service.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Projects
+ module HashedStorage
+ # Returned when repository can't be made read-only because there is already a git transfer in progress
+ RepositoryInUseError = Class.new(StandardError)
+
+ class BaseRepositoryService < BaseService
+ include Gitlab::ShellAdapter
+
+ attr_reader :old_disk_path, :new_disk_path, :old_wiki_disk_path, :old_storage_version, :logger, :move_wiki
+
+ def initialize(project, old_disk_path, logger: nil)
+ @project = project
+ @logger = logger || Gitlab::AppLogger
+ @old_disk_path = old_disk_path
+ @old_wiki_disk_path = "#{old_disk_path}.wiki"
+ @move_wiki = has_wiki?
+ end
+
+ protected
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def has_wiki?
+ gitlab_shell.exists?(project.repository_storage, "#{old_wiki_disk_path}.git")
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def move_repository(from_name, to_name)
+ from_exists = gitlab_shell.exists?(project.repository_storage, "#{from_name}.git")
+ to_exists = gitlab_shell.exists?(project.repository_storage, "#{to_name}.git")
+
+ # If we don't find the repository on either original or target we should log that as it could be an issue if the
+ # project was not originally empty.
+ if !from_exists && !to_exists
+ logger.warn "Can't find a repository on either source or target paths for #{project.full_path} (ID=#{project.id}) ..."
+
+ # We return true so we still reflect the change in the database.
+ # Next time the repository is (re)created it will be under the new storage layout
+ return true
+ elsif !from_exists
+ # Repository have been moved already.
+ return true
+ end
+
+ gitlab_shell.mv_repository(project.repository_storage, from_name, to_name)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def rollback_folder_move
+ move_repository(new_disk_path, old_disk_path)
+ move_repository("#{new_disk_path}.wiki", old_wiki_disk_path)
+ end
+
+ def try_to_set_repository_read_only!
+ # Mitigate any push operation to start during migration
+ unless project.set_repository_read_only!
+ migration_error = "Target repository '#{old_disk_path}' cannot be made read-only as there is a git transfer in progress"
+ logger.error migration_error
+
+ raise RepositoryInUseError, migration_error
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/projects/hashed_storage/migrate_attachments_service.rb b/app/services/projects/hashed_storage/migrate_attachments_service.rb
index a1f0302aeb7..9eaeb6eb4e7 100644
--- a/app/services/projects/hashed_storage/migrate_attachments_service.rb
+++ b/app/services/projects/hashed_storage/migrate_attachments_service.rb
@@ -2,56 +2,37 @@
module Projects
module HashedStorage
- AttachmentMigrationError = Class.new(StandardError)
-
- class MigrateAttachmentsService < BaseService
- attr_reader :logger, :old_disk_path, :new_disk_path
-
+ class MigrateAttachmentsService < BaseAttachmentService
def initialize(project, old_disk_path, logger: nil)
@project = project
@logger = logger || Rails.logger
@old_disk_path = old_disk_path
- @new_disk_path = project.disk_path
+ @skipped = false
end
def execute
origin = FileUploader.absolute_base_dir(project)
- # It's possible that old_disk_path does not match project.disk_path. For example, that happens when we rename a project
+ # It's possible that old_disk_path does not match project.disk_path.
+ # For example, that happens when we rename a project
origin.sub!(/#{Regexp.escape(project.full_path)}\z/, old_disk_path)
project.storage_version = ::Project::HASHED_STORAGE_FEATURES[:attachments]
target = FileUploader.absolute_base_dir(project)
- result = move_folder!(origin, target)
- project.save!
-
- if result && block_given?
- yield
- end
-
- result
- end
+ @new_disk_path = project.disk_path
- private
+ result = move_folder!(origin, target)
- def move_folder!(old_disk_path, new_disk_path)
- unless File.directory?(old_disk_path)
- logger.info("Skipped attachments migration from '#{old_disk_path}' to '#{new_disk_path}', source path doesn't exist or is not a directory (PROJECT_ID=#{project.id})")
- return
- end
+ if result
+ project.save!
- if File.exist?(new_disk_path)
- logger.error("Cannot migrate attachments from '#{old_disk_path}' to '#{new_disk_path}', target path already exist (PROJECT_ID=#{project.id})")
- raise AttachmentMigrationError, "Target path '#{new_disk_path}' already exist"
+ yield if block_given?
+ else
+ # Rollback changes
+ project.rollback!
end
- # Create hashed storage base path folder
- FileUtils.mkdir_p(File.dirname(new_disk_path))
-
- FileUtils.mv(old_disk_path, new_disk_path)
- logger.info("Migrated project attachments from '#{old_disk_path}' to '#{new_disk_path}' (PROJECT_ID=#{project.id})")
-
- true
+ result
end
end
end
diff --git a/app/services/projects/hashed_storage/migrate_repository_service.rb b/app/services/projects/hashed_storage/migrate_repository_service.rb
index f3e026ba38c..5afa8732c0a 100644
--- a/app/services/projects/hashed_storage/migrate_repository_service.rb
+++ b/app/services/projects/hashed_storage/migrate_repository_service.rb
@@ -2,20 +2,10 @@
module Projects
module HashedStorage
- class MigrateRepositoryService < BaseService
- include Gitlab::ShellAdapter
-
- attr_reader :old_disk_path, :new_disk_path, :old_wiki_disk_path, :old_storage_version, :logger, :move_wiki
-
- def initialize(project, old_disk_path, logger: nil)
- @project = project
- @logger = logger || Rails.logger
- @old_disk_path = old_disk_path
- @old_wiki_disk_path = "#{old_disk_path}.wiki"
- @move_wiki = has_wiki?
- end
-
+ class MigrateRepositoryService < BaseRepositoryService
def execute
+ try_to_set_repository_read_only!
+
@old_storage_version = project.storage_version
project.storage_version = ::Project::HASHED_STORAGE_FEATURES[:repository]
project.ensure_storage_path_exists
@@ -25,7 +15,7 @@ module Projects
result = move_repository(old_disk_path, new_disk_path)
if move_wiki
- result &&= move_repository("#{old_wiki_disk_path}", "#{new_disk_path}.wiki")
+ result &&= move_repository(old_wiki_disk_path, "#{new_disk_path}.wiki")
end
if result
@@ -45,38 +35,6 @@ module Projects
result
end
-
- private
-
- # rubocop: disable CodeReuse/ActiveRecord
- def has_wiki?
- gitlab_shell.exists?(project.repository_storage, "#{old_wiki_disk_path}.git")
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
- def move_repository(from_name, to_name)
- from_exists = gitlab_shell.exists?(project.repository_storage, "#{from_name}.git")
- to_exists = gitlab_shell.exists?(project.repository_storage, "#{to_name}.git")
-
- # If we don't find the repository on either original or target we should log that as it could be an issue if the
- # project was not originally empty.
- if !from_exists && !to_exists
- logger.warn "Can't find a repository on either source or target paths for #{project.full_path} (ID=#{project.id}) ..."
- return false
- elsif !from_exists
- # Repository have been moved already.
- return true
- end
-
- gitlab_shell.mv_repository(project.repository_storage, from_name, to_name)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def rollback_folder_move
- move_repository(new_disk_path, old_disk_path)
- move_repository("#{new_disk_path}.wiki", old_wiki_disk_path)
- end
end
end
end
diff --git a/app/services/projects/hashed_storage/migration_service.rb b/app/services/projects/hashed_storage/migration_service.rb
new file mode 100644
index 00000000000..f132dca61c9
--- /dev/null
+++ b/app/services/projects/hashed_storage/migration_service.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Projects
+ module HashedStorage
+ class MigrationService < BaseService
+ attr_reader :logger, :old_disk_path
+
+ def initialize(project, old_disk_path, logger: nil)
+ @project = project
+ @old_disk_path = old_disk_path
+ @logger = logger || Gitlab::AppLogger
+ end
+
+ def execute
+ # Migrate repository from Legacy to Hashed Storage
+ unless project.hashed_storage?(:repository)
+ return false unless migrate_repository
+ end
+
+ # Migrate attachments from Legacy to Hashed Storage
+ unless project.hashed_storage?(:attachments)
+ return false unless migrate_attachments
+ end
+
+ true
+ end
+
+ private
+
+ def migrate_repository
+ HashedStorage::MigrateRepositoryService.new(project, old_disk_path, logger: logger).execute
+ end
+
+ def migrate_attachments
+ HashedStorage::MigrateAttachmentsService.new(project, old_disk_path, logger: logger).execute
+ end
+ end
+ end
+end
diff --git a/app/services/projects/hashed_storage/rollback_attachments_service.rb b/app/services/projects/hashed_storage/rollback_attachments_service.rb
new file mode 100644
index 00000000000..6c370ac47e9
--- /dev/null
+++ b/app/services/projects/hashed_storage/rollback_attachments_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Projects
+ module HashedStorage
+ class RollbackAttachmentsService < BaseAttachmentService
+ def initialize(project, logger: nil)
+ @project = project
+ @logger = logger || Rails.logger
+ @old_disk_path = project.disk_path
+ end
+
+ def execute
+ origin = FileUploader.absolute_base_dir(project)
+ project.storage_version = ::Project::HASHED_STORAGE_FEATURES[:repository]
+ target = FileUploader.absolute_base_dir(project)
+
+ @new_disk_path = FileUploader.base_dir(project)
+
+ result = move_folder!(origin, target)
+
+ if result
+ project.save!
+
+ yield if block_given?
+ else
+ # Rollback changes
+ project.rollback!
+ end
+
+ result
+ end
+ end
+ end
+end
diff --git a/app/services/projects/hashed_storage/rollback_repository_service.rb b/app/services/projects/hashed_storage/rollback_repository_service.rb
new file mode 100644
index 00000000000..b5c971c70a5
--- /dev/null
+++ b/app/services/projects/hashed_storage/rollback_repository_service.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Projects
+ module HashedStorage
+ class RollbackRepositoryService < BaseRepositoryService
+ def execute
+ try_to_set_repository_read_only!
+
+ @old_storage_version = project.storage_version
+ project.storage_version = nil
+ project.ensure_storage_path_exists
+
+ @new_disk_path = project.disk_path
+
+ result = move_repository(old_disk_path, new_disk_path)
+
+ if move_wiki
+ result &&= move_repository(old_wiki_disk_path, "#{new_disk_path}.wiki")
+ end
+
+ if result
+ project.write_repository_config
+ project.track_project_repository
+ else
+ rollback_folder_move
+ project.storage_version = ::Project::HASHED_STORAGE_FEATURES[:repository]
+ end
+
+ project.repository_read_only = false
+ project.save!
+
+ if result && block_given?
+ yield
+ end
+
+ result
+ end
+ end
+ end
+end
diff --git a/app/services/projects/hashed_storage/rollback_service.rb b/app/services/projects/hashed_storage/rollback_service.rb
new file mode 100644
index 00000000000..25767f5de5e
--- /dev/null
+++ b/app/services/projects/hashed_storage/rollback_service.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Projects
+ module HashedStorage
+ class RollbackService < BaseService
+ attr_reader :logger, :old_disk_path
+
+ def initialize(project, old_disk_path, logger: nil)
+ @project = project
+ @old_disk_path = old_disk_path
+ @logger = logger || Rails.logger
+ end
+
+ def execute
+ # Rollback attachments from Hashed Storage to Legacy
+ if project.hashed_storage?(:attachments)
+ return false unless rollback_attachments
+ end
+
+ # Rollback repository from Hashed Storage to Legacy
+ if project.hashed_storage?(:repository)
+ rollback_repository
+ end
+ end
+
+ private
+
+ def rollback_attachments
+ HashedStorage::RollbackAttachmentsService.new(project, logger: logger).execute
+ end
+
+ def rollback_repository
+ HashedStorage::RollbackRepositoryService.new(project, old_disk_path, logger: logger).execute
+ end
+ end
+ end
+end
diff --git a/app/services/projects/hashed_storage_migration_service.rb b/app/services/projects/hashed_storage_migration_service.rb
deleted file mode 100644
index a0e734005f8..00000000000
--- a/app/services/projects/hashed_storage_migration_service.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module Projects
- class HashedStorageMigrationService < BaseService
- attr_reader :logger, :old_disk_path
-
- def initialize(project, old_disk_path, logger: nil)
- @project = project
- @old_disk_path = old_disk_path
- @logger = logger || Rails.logger
- end
-
- def execute
- # Migrate repository from Legacy to Hashed Storage
- unless project.hashed_storage?(:repository)
- return unless HashedStorage::MigrateRepositoryService.new(project, old_disk_path, logger: logger).execute
- end
-
- # Migrate attachments from Legacy to Hashed Storage
- unless project.hashed_storage?(:attachments)
- HashedStorage::MigrateAttachmentsService.new(project, old_disk_path, logger: logger).execute
- end
-
- true
- end
- end
-end
diff --git a/app/services/projects/import_error_filter.rb b/app/services/projects/import_error_filter.rb
new file mode 100644
index 00000000000..a0fc5149bb4
--- /dev/null
+++ b/app/services/projects/import_error_filter.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Projects
+ # Used by project imports, it removes any potential paths
+ # included in an error message that could be stored in the DB
+ class ImportErrorFilter
+ ERROR_MESSAGE_FILTER = /[^\s]*#{File::SEPARATOR}[^\s]*(?=(\s|\z))/
+ FILTER_MESSAGE = '[FILTERED]'
+
+ def self.filter_message(message)
+ message.gsub(ERROR_MESSAGE_FILTER, FILTER_MESSAGE)
+ end
+ end
+end
diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb
index 0c426faa22d..7214e9efaf6 100644
--- a/app/services/projects/import_service.rb
+++ b/app/services/projects/import_service.rb
@@ -24,8 +24,16 @@ module Projects
import_data
success
- rescue => e
+ rescue Gitlab::UrlBlocker::BlockedUrlError => e
+ Gitlab::Sentry.track_acceptable_exception(e, extra: { project_path: project.full_path, importer: project.import_type })
+
error("Error importing repository #{project.safe_import_url} into #{project.full_path} - #{e.message}")
+ rescue => e
+ message = Projects::ImportErrorFilter.filter_message(e.message)
+
+ Gitlab::Sentry.track_acceptable_exception(e, extra: { project_path: project.full_path, importer: project.import_type })
+
+ error("Error importing repository #{project.safe_import_url} into #{project.full_path} - #{message}")
end
private
@@ -35,7 +43,7 @@ module Projects
begin
Gitlab::UrlBlocker.validate!(project.import_url, ports: Project::VALID_IMPORT_PORTS)
rescue Gitlab::UrlBlocker::BlockedUrlError => e
- raise Error, "Blocked import URL: #{e.message}"
+ raise e, "Blocked import URL: #{e.message}"
end
end
@@ -65,7 +73,7 @@ module Projects
project.ensure_repository
project.repository.fetch_as_mirror(project.import_url, refmap: refmap)
else
- gitlab_shell.import_repository(project.repository_storage, project.disk_path, project.import_url)
+ gitlab_shell.import_project_repository(project)
end
rescue Gitlab::Shell::Error => e
# Expire cache to prevent scenarios such as:
@@ -86,11 +94,11 @@ module Projects
return unless project.lfs_enabled?
- oids_to_download = Projects::LfsPointers::LfsImportService.new(project).execute
- download_service = Projects::LfsPointers::LfsDownloadService.new(project)
+ lfs_objects_to_download = Projects::LfsPointers::LfsImportService.new(project).execute
- oids_to_download.each do |oid, link|
- download_service.execute(oid, link)
+ lfs_objects_to_download.each do |lfs_download_object|
+ Projects::LfsPointers::LfsDownloadService.new(project, lfs_download_object)
+ .execute
end
rescue => e
# Right now, to avoid aborting the importing process, we silently fail
diff --git a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
index a837ea82e38..7998976b00a 100644
--- a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
@@ -41,16 +41,17 @@ module Projects
end
def parse_response_links(objects_response)
- objects_response.each_with_object({}) do |entry, link_list|
+ objects_response.each_with_object([]) do |entry, link_list|
begin
- oid = entry['oid']
link = entry.dig('actions', DOWNLOAD_ACTION, 'href')
raise DownloadLinkNotFound unless link
- link_list[oid] = add_credentials(link)
- rescue DownloadLinkNotFound, URI::InvalidURIError
- Rails.logger.error("Link for Lfs Object with oid #{oid} not found or invalid.")
+ link_list << LfsDownloadObject.new(oid: entry['oid'],
+ size: entry['size'],
+ link: add_credentials(link))
+ rescue DownloadLinkNotFound, Addressable::URI::InvalidURIError
+ log_error("Link for Lfs Object with oid #{entry['oid']} not found or invalid.")
end
end
end
@@ -70,7 +71,7 @@ module Projects
end
def add_credentials(link)
- uri = URI.parse(link)
+ uri = Addressable::URI.parse(link)
if should_add_credentials?(uri)
uri.user = remote_uri.user
diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb
index f9b9781ad5f..398f00a598d 100644
--- a/app/services/projects/lfs_pointers/lfs_download_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_service.rb
@@ -4,49 +4,93 @@
module Projects
module LfsPointers
class LfsDownloadService < BaseService
- VALID_PROTOCOLS = %w[http https].freeze
+ SizeError = Class.new(StandardError)
+ OidError = Class.new(StandardError)
- # rubocop: disable CodeReuse/ActiveRecord
- def execute(oid, url)
- return unless project&.lfs_enabled? && oid.present? && url.present?
+ attr_reader :lfs_download_object
+ delegate :oid, :size, :credentials, :sanitized_url, to: :lfs_download_object, prefix: :lfs
- return if LfsObject.exists?(oid: oid)
+ def initialize(project, lfs_download_object)
+ super(project)
- sanitized_uri = Gitlab::UrlSanitizer.new(url)
- Gitlab::UrlBlocker.validate!(sanitized_uri.sanitized_url, protocols: VALID_PROTOCOLS)
+ @lfs_download_object = lfs_download_object
+ end
- with_tmp_file(oid) do |file|
- size = download_and_save_file(file, sanitized_uri)
- lfs_object = LfsObject.new(oid: oid, size: size, file: file)
+ # rubocop: disable CodeReuse/ActiveRecord
+ def execute
+ return unless project&.lfs_enabled? && lfs_download_object
+ return error("LFS file with oid #{lfs_oid} has invalid attributes") unless lfs_download_object.valid?
+ return if LfsObject.exists?(oid: lfs_oid)
- project.all_lfs_objects << lfs_object
+ wrap_download_errors do
+ download_lfs_file!
end
- rescue StandardError => e
- Rails.logger.error("LFS file with oid #{oid} could't be downloaded from #{sanitized_uri.sanitized_url}: #{e.message}")
end
# rubocop: enable CodeReuse/ActiveRecord
private
- def download_and_save_file(file, sanitized_uri)
- IO.copy_stream(open(sanitized_uri.sanitized_url, headers(sanitized_uri)), file) # rubocop:disable Security/Open
+ def wrap_download_errors(&block)
+ yield
+ rescue SizeError, OidError, StandardError => e
+ error("LFS file with oid #{lfs_oid} could't be downloaded from #{lfs_sanitized_url}: #{e.message}")
+ end
+
+ def download_lfs_file!
+ with_tmp_file do |tmp_file|
+ download_and_save_file!(tmp_file)
+ project.all_lfs_objects << LfsObject.new(oid: lfs_oid,
+ size: lfs_size,
+ file: tmp_file)
+
+ success
+ end
end
- def headers(sanitized_uri)
- {}.tap do |headers|
- credentials = sanitized_uri.credentials
+ def download_and_save_file!(file)
+ digester = Digest::SHA256.new
+ response = Gitlab::HTTP.get(lfs_sanitized_url, download_headers) do |fragment|
+ digester << fragment
+ file.write(fragment)
+
+ raise_size_error! if file.size > lfs_size
+ end
+
+ raise StandardError, "Received error code #{response.code}" unless response.success?
+
+ raise_size_error! if file.size != lfs_size
+ raise_oid_error! if digester.hexdigest != lfs_oid
+ end
- if credentials[:user].present? || credentials[:password].present?
+ def download_headers
+ { stream_body: true }.tap do |headers|
+ if lfs_credentials[:user].present? || lfs_credentials[:password].present?
# Using authentication headers in the request
- headers[:http_basic_authentication] = [credentials[:user], credentials[:password]]
+ headers[:basic_auth] = { username: lfs_credentials[:user], password: lfs_credentials[:password] }
end
end
end
- def with_tmp_file(oid)
+ def with_tmp_file
create_tmp_storage_dir
- File.open(File.join(tmp_storage_dir, oid), 'w') { |file| yield file }
+ File.open(tmp_filename, 'wb') do |file|
+ begin
+ yield file
+ rescue StandardError => e
+ # If the lfs file is successfully downloaded it will be removed
+ # when it is added to the project's lfs files.
+ # Nevertheless if any excetion raises the file would remain
+ # in the file system. Here we ensure to remove it
+ File.unlink(file) if File.exist?(file)
+
+ raise e
+ end
+ end
+ end
+
+ def tmp_filename
+ File.join(tmp_storage_dir, lfs_oid)
end
def create_tmp_storage_dir
@@ -60,6 +104,20 @@ module Projects
def storage_dir
@storage_dir ||= Gitlab.config.lfs.storage_path
end
+
+ def raise_size_error!
+ raise SizeError, 'Size mistmatch'
+ end
+
+ def raise_oid_error!
+ raise OidError, 'Oid mismatch'
+ end
+
+ def error(message, http_status = nil)
+ log_error(message)
+
+ super
+ end
end
end
end
diff --git a/app/services/projects/operations/update_service.rb b/app/services/projects/operations/update_service.rb
new file mode 100644
index 00000000000..aedf79c86d7
--- /dev/null
+++ b/app/services/projects/operations/update_service.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Projects
+ module Operations
+ class UpdateService < BaseService
+ def execute
+ Projects::UpdateService
+ .new(project, current_user, project_update_params)
+ .execute
+ end
+
+ private
+
+ def project_update_params
+ error_tracking_params
+ end
+
+ def error_tracking_params
+ settings = params[:error_tracking_setting_attributes]
+ return {} if settings.blank?
+
+ api_url = ErrorTracking::ProjectErrorTrackingSetting.build_api_url_from(
+ api_host: settings[:api_host],
+ project_slug: settings.dig(:project, :slug),
+ organization_slug: settings.dig(:project, :organization_slug)
+ )
+
+ {
+ error_tracking_setting_attributes: {
+ api_url: api_url,
+ token: settings[:token],
+ enabled: settings[:enabled],
+ project_name: settings.dig(:project, :name),
+ organization_name: settings.dig(:project, :organization_name)
+ }
+ }
+ end
+ end
+ end
+end
diff --git a/app/services/projects/protect_default_branch_service.rb b/app/services/projects/protect_default_branch_service.rb
new file mode 100644
index 00000000000..245490791bf
--- /dev/null
+++ b/app/services/projects/protect_default_branch_service.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Projects
+ # Service class that can be used to execute actions necessary after creating a
+ # default branch.
+ class ProtectDefaultBranchService
+ attr_reader :project, :default_branch_protection
+
+ # @param [Project] project
+ def initialize(project)
+ @project = project
+
+ @default_branch_protection = Gitlab::Access::BranchProtection
+ .new(Gitlab::CurrentSettings.default_branch_protection)
+ end
+
+ def execute
+ protect_default_branch if default_branch
+ end
+
+ def protect_default_branch
+ # Ensure HEAD points to the default branch in case it is not master
+ project.change_head(default_branch)
+
+ create_protected_branch if protect_branch?
+ end
+
+ def create_protected_branch
+ params = {
+ name: default_branch,
+ push_access_levels_attributes: [{ access_level: push_access_level }],
+ merge_access_levels_attributes: [{ access_level: merge_access_level }]
+ }
+
+ # The creator of the project is always allowed to create protected
+ # branches, so we skip the authorization check in this service class.
+ ProtectedBranches::CreateService
+ .new(project, project.creator, params)
+ .execute(skip_authorization: true)
+ end
+
+ def protect_branch?
+ default_branch_protection.any? &&
+ !ProtectedBranch.protected?(project, default_branch)
+ end
+
+ def default_branch
+ project.default_branch
+ end
+
+ def push_access_level
+ if default_branch_protection.developer_can_push?
+ Gitlab::Access::DEVELOPER
+ else
+ Gitlab::Access::MAINTAINER
+ end
+ end
+
+ def merge_access_level
+ if default_branch_protection.developer_can_merge?
+ Gitlab::Access::DEVELOPER
+ else
+ Gitlab::Access::MAINTAINER
+ end
+ end
+ end
+end
diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb
index abf40b3ad7a..674071ad92a 100644
--- a/app/services/projects/update_pages_configuration_service.rb
+++ b/app/services/projects/update_pages_configuration_service.rb
@@ -2,6 +2,8 @@
module Projects
class UpdatePagesConfigurationService < BaseService
+ include Gitlab::Utils::StrongMemoize
+
attr_reader :project
def initialize(project)
@@ -9,15 +11,25 @@ module Projects
end
def execute
- update_file(pages_config_file, pages_config.to_json)
+ if file_equals?(pages_config_file, pages_config_json)
+ return success(reload: false)
+ end
+
+ update_file(pages_config_file, pages_config_json)
reload_daemon
- success
+ success(reload: true)
rescue => e
error(e.message)
end
private
+ def pages_config_json
+ strong_memoize(:pages_config_json) do
+ pages_config.to_json
+ end
+ end
+
def pages_config
{
domains: pages_domains_config,
@@ -67,11 +79,6 @@ module Projects
end
def update_file(file, data)
- unless data
- FileUtils.remove(file, force: true)
- return
- end
-
temp_file = "#{file}.#{SecureRandom.hex(16)}"
File.open(temp_file, 'w') do |f|
f.write(data)
@@ -81,5 +88,18 @@ module Projects
# In case if the updating fails
FileUtils.remove(temp_file, force: true)
end
+
+ def file_equals?(file, data)
+ existing_data = read_file(file)
+ data == existing_data.to_s
+ end
+
+ def read_file(file)
+ File.open(file, 'r') do |f|
+ f.read
+ end
+ rescue
+ nil
+ end
end
end
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index eb2478be3cf..5caeb4cfa5f 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -7,7 +7,11 @@ module Projects
BLOCK_SIZE = 32.kilobytes
MAX_SIZE = 1.terabyte
- SITE_PATH = 'public/'.freeze
+ PUBLIC_DIR = 'public'.freeze
+
+ # this has to be invalid group name,
+ # as it shares the namespace with groups
+ TMP_EXTRACT_PATH = '@pages.tmp'.freeze
attr_reader :build
@@ -27,12 +31,11 @@ module Projects
raise InvalidStateError, 'pages are outdated' unless latest?
# Create temporary directory in which we will extract the artifacts
- FileUtils.mkdir_p(tmp_path)
- Dir.mktmpdir(nil, tmp_path) do |archive_path|
+ make_secure_tmp_dir(tmp_path) do |archive_path|
extract_archive!(archive_path)
# Check if we did extract public directory
- archive_public_path = File.join(archive_path, 'public')
+ archive_public_path = File.join(archive_path, PUBLIC_DIR)
raise InvalidStateError, 'pages miss the public folder' unless Dir.exist?(archive_public_path)
raise InvalidStateError, 'pages are outdated' unless latest?
@@ -85,22 +88,18 @@ module Projects
raise InvalidStateError, 'missing artifacts metadata' unless build.artifacts_metadata?
# Calculate page size after extract
- public_entry = build.artifacts_metadata_entry(SITE_PATH, recursive: true)
+ public_entry = build.artifacts_metadata_entry(PUBLIC_DIR + '/', recursive: true)
if public_entry.total_size > max_size
raise InvalidStateError, "artifacts for pages are too large: #{public_entry.total_size}"
end
- # Requires UnZip at least 6.00 Info-ZIP.
- # -qq be (very) quiet
- # -n never overwrite existing files
- # We add * to end of SITE_PATH, because we want to extract SITE_PATH and all subdirectories
- site_path = File.join(SITE_PATH, '*')
build.artifacts_file.use_file do |artifacts_path|
- unless system(*%W(unzip -n #{artifacts_path} #{site_path} -d #{temp_path}))
- raise FailedToExtractError, 'pages failed to extract'
- end
+ SafeZip::Extract.new(artifacts_path)
+ .extract(directories: [PUBLIC_DIR], to: temp_path)
end
+ rescue SafeZip::Extract::Error => e
+ raise FailedToExtractError, e.message
end
def deploy_page!(archive_public_path)
@@ -139,7 +138,7 @@ module Projects
end
def tmp_path
- @tmp_path ||= File.join(::Settings.pages.path, 'tmp')
+ @tmp_path ||= File.join(::Settings.pages.path, TMP_EXTRACT_PATH)
end
def pages_path
@@ -147,11 +146,11 @@ module Projects
end
def public_path
- @public_path ||= File.join(pages_path, 'public')
+ @public_path ||= File.join(pages_path, PUBLIC_DIR)
end
def previous_public_path
- @previous_public_path ||= File.join(pages_path, "public.#{SecureRandom.hex}")
+ @previous_public_path ||= File.join(pages_path, "#{PUBLIC_DIR}.#{SecureRandom.hex}")
end
def ref
@@ -188,5 +187,15 @@ module Projects
def pages_deployments_failed_total_counter
@pages_deployments_failed_total_counter ||= Gitlab::Metrics.counter(:pages_deployments_failed_total, "Counter of GitLab Pages deployments which failed")
end
+
+ def make_secure_tmp_dir(tmp_path)
+ FileUtils.mkdir_p(tmp_path)
+ path = Dir.mktmpdir(nil, tmp_path)
+ begin
+ yield(path)
+ ensure
+ FileUtils.remove_entry_secure(path)
+ end
+ end
end
end
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 93e48fc0199..6856009b395 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -61,13 +61,13 @@ module Projects
if project.previous_changes.include?(:visibility_level) && project.private?
# don't enqueue immediately to prevent todos removal in case of a mistake
- TodosDestroyer::ProjectPrivateWorker.perform_in(1.hour, project.id)
+ TodosDestroyer::ProjectPrivateWorker.perform_in(Todo::WAIT_FOR_DELETE, project.id)
elsif (project_changed_feature_keys & todos_features_changes).present?
- TodosDestroyer::PrivateFeaturesWorker.perform_in(1.hour, project.id)
+ TodosDestroyer::PrivateFeaturesWorker.perform_in(Todo::WAIT_FOR_DELETE, project.id)
end
if project.previous_changes.include?('path')
- AfterRenameService.new(project).execute
+ after_rename_service(project).execute
else
system_hook_service.execute_hooks_for(project, :update)
end
@@ -75,6 +75,13 @@ module Projects
update_pages_config if changing_pages_related_config?
end
+ def after_rename_service(project)
+ # The path slug the project was using, before the rename took place.
+ path_before = project.previous_changes['path'].first
+
+ AfterRenameService.new(project, path_before: path_before, full_path_before: project.full_path_was)
+ end
+
def changing_pages_related_config?
changing_pages_https_only? || changing_pages_access_level?
end
diff --git a/app/services/prometheus/adapter_service.rb b/app/services/prometheus/adapter_service.rb
index a791845ba20..3be958e1613 100644
--- a/app/services/prometheus/adapter_service.rb
+++ b/app/services/prometheus/adapter_service.rb
@@ -30,7 +30,7 @@ module Prometheus
return unless deployment_platform.respond_to?(:cluster)
cluster = deployment_platform.cluster
- return unless cluster.application_prometheus&.ready?
+ return unless cluster.application_prometheus&.available?
cluster.application_prometheus
end
diff --git a/app/services/protected_branches/api_service.rb b/app/services/protected_branches/api_service.rb
index 4340d3e8260..1b13dace5f2 100644
--- a/app/services/protected_branches/api_service.rb
+++ b/app/services/protected_branches/api_service.rb
@@ -3,24 +3,15 @@
module ProtectedBranches
class ApiService < BaseService
def create
- @push_params = AccessLevelParams.new(:push, params)
- @merge_params = AccessLevelParams.new(:merge, params)
-
- verify_params!
-
- protected_branch_params = {
- name: params[:name],
- push_access_levels_attributes: @push_params.access_levels,
- merge_access_levels_attributes: @merge_params.access_levels
- }
-
::ProtectedBranches::CreateService.new(@project, @current_user, protected_branch_params).execute
end
- private
-
- def verify_params!
- # EE-only
+ def protected_branch_params
+ {
+ name: params[:name],
+ push_access_levels_attributes: AccessLevelParams.new(:push, params).access_levels,
+ merge_access_levels_attributes: AccessLevelParams.new(:merge, params).access_levels
+ }
end
end
end
diff --git a/app/services/protected_branches/legacy_api_update_service.rb b/app/services/protected_branches/legacy_api_update_service.rb
index da8bf2ce02a..7cb8d41818f 100644
--- a/app/services/protected_branches/legacy_api_update_service.rb
+++ b/app/services/protected_branches/legacy_api_update_service.rb
@@ -6,30 +6,31 @@
# lives in this service.
module ProtectedBranches
class LegacyApiUpdateService < BaseService
+ attr_reader :protected_branch, :developers_can_push, :developers_can_merge
+
def execute(protected_branch)
+ @protected_branch = protected_branch
@developers_can_push = params.delete(:developers_can_push)
@developers_can_merge = params.delete(:developers_can_merge)
- @protected_branch = protected_branch
-
protected_branch.transaction do
delete_redundant_access_levels
- case @developers_can_push
+ case developers_can_push
when true
params[:push_access_levels_attributes] = [{ access_level: Gitlab::Access::DEVELOPER }]
when false
params[:push_access_levels_attributes] = [{ access_level: Gitlab::Access::MAINTAINER }]
end
- case @developers_can_merge
+ case developers_can_merge
when true
params[:merge_access_levels_attributes] = [{ access_level: Gitlab::Access::DEVELOPER }]
when false
params[:merge_access_levels_attributes] = [{ access_level: Gitlab::Access::MAINTAINER }]
end
- service = ProtectedBranches::UpdateService.new(@project, @current_user, @params)
+ service = ProtectedBranches::UpdateService.new(project, current_user, params)
service.execute(protected_branch)
end
end
@@ -37,12 +38,12 @@ module ProtectedBranches
private
def delete_redundant_access_levels
- unless @developers_can_merge.nil?
- @protected_branch.merge_access_levels.destroy_all # rubocop: disable DestroyAll
+ unless developers_can_merge.nil?
+ protected_branch.merge_access_levels.destroy_all # rubocop: disable DestroyAll
end
- unless @developers_can_push.nil?
- @protected_branch.push_access_levels.destroy_all # rubocop: disable DestroyAll
+ unless developers_can_push.nil?
+ protected_branch.push_access_levels.destroy_all # rubocop: disable DestroyAll
end
end
end
diff --git a/app/services/push_event_payload_service.rb b/app/services/push_event_payload_service.rb
index bb1259787af..fe366ac225b 100644
--- a/app/services/push_event_payload_service.rb
+++ b/app/services/push_event_payload_service.rb
@@ -46,7 +46,7 @@ class PushEventPayloadService
def commit_title
commit = @push_data.fetch(:commits).last
- return nil unless commit && commit[:message]
+ return unless commit && commit[:message]
raw_msg = commit[:message]
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index d248b10f41e..131efb8925e 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -2,10 +2,16 @@
module QuickActions
class InterpretService < BaseService
+ include Gitlab::Utils::StrongMemoize
include Gitlab::QuickActions::Dsl
attr_reader :issuable
+ # Counts how many commands have been executed.
+ # Used to display relevant feedback on UI when a note
+ # with only commands has been processed.
+ attr_accessor :commands_executed_count
+
SHRUG = '¯\\_(ツ)_/¯'.freeze
TABLEFLIP = '(╯°□°)╯︵ â”»â”â”»'.freeze
@@ -210,15 +216,9 @@ module QuickActions
end
params '~label1 ~"label 2"'
condition do
- if project
- available_labels = LabelsFinder
- .new(current_user, project_id: project.id, include_ancestor_groups: true)
- .execute
- end
-
- project &&
- current_user.can?(:"admin_#{issuable.to_ability_name}", project) &&
- available_labels.any?
+ parent &&
+ current_user.can?(:"admin_#{issuable.to_ability_name}", parent) &&
+ find_labels.any?
end
command :label do |labels_param|
label_ids = find_label_ids(labels_param)
@@ -245,7 +245,7 @@ module QuickActions
issuable.is_a?(Issuable) &&
issuable.persisted? &&
issuable.labels.any? &&
- current_user.can?(:"admin_#{issuable.to_ability_name}", project)
+ current_user.can?(:"admin_#{issuable.to_ability_name}", parent)
end
command :unlabel do |labels_param = nil|
if labels_param.present?
@@ -674,9 +674,25 @@ module QuickActions
MilestonesFinder.new(params.merge(project_ids: [project.id], group_ids: [project.group&.id])).execute
end
- def find_labels(labels_param)
- extract_references(labels_param, :label) |
- LabelsFinder.new(current_user, project_id: project.id, name: labels_param.split, include_ancestor_groups: true).execute
+ def parent
+ project || group
+ end
+
+ def group
+ strong_memoize(:group) do
+ issuable.group if issuable.respond_to?(:group)
+ end
+ end
+
+ def find_labels(labels_params = nil)
+ finder_params = { include_ancestor_groups: true }
+ finder_params[:project_id] = project.id if project
+ finder_params[:group_id] = group.id if group
+ finder_params[:name] = labels_params.split if labels_params
+
+ result = LabelsFinder.new(current_user, finder_params).execute
+
+ extract_references(labels_params, :label) | result
end
def find_label_references(labels_param)
@@ -707,9 +723,11 @@ module QuickActions
# rubocop: disable CodeReuse/ActiveRecord
def extract_references(arg, type)
+ return [] unless arg
+
ext = Gitlab::ReferenceExtractor.new(project, current_user)
- ext.analyze(arg, author: current_user)
+ ext.analyze(arg, author: current_user, group: group)
ext.references(type)
end
diff --git a/app/services/releases/concerns.rb b/app/services/releases/concerns.rb
new file mode 100644
index 00000000000..a04bb8f9e14
--- /dev/null
+++ b/app/services/releases/concerns.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Releases
+ module Concerns
+ extend ActiveSupport::Concern
+ include Gitlab::Utils::StrongMemoize
+
+ included do
+ def tag_name
+ params[:tag]
+ end
+
+ def ref
+ params[:ref]
+ end
+
+ def name
+ params[:name]
+ end
+
+ def description
+ params[:description]
+ end
+
+ def release
+ strong_memoize(:release) do
+ project.releases.find_by_tag(tag_name)
+ end
+ end
+
+ def existing_tag
+ strong_memoize(:existing_tag) do
+ repository.find_tag(tag_name)
+ end
+ end
+
+ def tag_exist?
+ existing_tag.present?
+ end
+
+ def repository
+ strong_memoize(:repository) do
+ project.repository
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/releases/create_service.rb b/app/services/releases/create_service.rb
new file mode 100644
index 00000000000..c6e143d440d
--- /dev/null
+++ b/app/services/releases/create_service.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module Releases
+ class CreateService < BaseService
+ include Releases::Concerns
+
+ def execute
+ return error('Access Denied', 403) unless allowed?
+ return error('Release already exists', 409) if release
+
+ tag = ensure_tag
+
+ return tag unless tag.is_a?(Gitlab::Git::Tag)
+
+ create_release(tag)
+ end
+
+ private
+
+ def ensure_tag
+ existing_tag || create_tag
+ end
+
+ def create_tag
+ return error('Ref is not specified', 422) unless ref
+
+ result = Tags::CreateService
+ .new(project, current_user)
+ .execute(tag_name, ref, nil)
+
+ return result unless result[:status] == :success
+
+ result[:tag]
+ end
+
+ def allowed?
+ Ability.allowed?(current_user, :create_release, project)
+ end
+
+ def create_release(tag)
+ release = project.releases.create!(
+ name: name,
+ description: description,
+ author: current_user,
+ tag: tag.name,
+ sha: tag.dereferenced_target.sha,
+ links_attributes: params.dig(:assets, 'links') || []
+ )
+
+ success(tag: tag, release: release)
+ rescue => e
+ error(e.message, 400)
+ end
+ end
+end
diff --git a/app/services/releases/destroy_service.rb b/app/services/releases/destroy_service.rb
new file mode 100644
index 00000000000..8c2bc3b4e6e
--- /dev/null
+++ b/app/services/releases/destroy_service.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Releases
+ class DestroyService < BaseService
+ include Releases::Concerns
+
+ def execute
+ return error('Tag does not exist', 404) unless existing_tag
+ return error('Release does not exist', 404) unless release
+ return error('Access Denied', 403) unless allowed?
+
+ if release.destroy
+ success(tag: existing_tag, release: release)
+ else
+ error(release.errors.messages || '400 Bad request', 400)
+ end
+ end
+
+ private
+
+ def allowed?
+ Ability.allowed?(current_user, :destroy_release, release)
+ end
+ end
+end
diff --git a/app/services/releases/update_service.rb b/app/services/releases/update_service.rb
new file mode 100644
index 00000000000..fabfa398c59
--- /dev/null
+++ b/app/services/releases/update_service.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Releases
+ class UpdateService < BaseService
+ include Releases::Concerns
+
+ def execute
+ return error('Tag does not exist', 404) unless existing_tag
+ return error('Release does not exist', 404) unless release
+ return error('Access Denied', 403) unless allowed?
+ return error('params is empty', 400) if empty_params?
+
+ if release.update(params)
+ success(tag: existing_tag, release: release)
+ else
+ error(release.errors.messages || '400 Bad request', 400)
+ end
+ end
+
+ private
+
+ def allowed?
+ Ability.allowed?(current_user, :update_release, release)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def empty_params?
+ params.except(:tag).empty?
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index cb1bf0a03a5..d6af26d949d 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -2,6 +2,8 @@
module Search
class GlobalService
+ include Gitlab::Utils::StrongMemoize
+
attr_accessor :current_user, :params
attr_reader :default_project_filter
@@ -19,11 +21,15 @@ module Search
@projects ||= ProjectsFinder.new(current_user: current_user).execute
end
- def scope
- @scope ||= begin
- allowed_scopes = %w[issues merge_requests milestones]
+ def allowed_scopes
+ strong_memoize(:allowed_scopes) do
+ %w[issues merge_requests milestones]
+ end
+ end
- allowed_scopes.delete(params[:scope]) { 'projects' }
+ def scope
+ strong_memoize(:scope) do
+ allowed_scopes.include?(params[:scope]) ? params[:scope] : 'projects'
end
end
end
diff --git a/app/services/suggestions/apply_service.rb b/app/services/suggestions/apply_service.rb
index d931d528c86..f778c5aa5f5 100644
--- a/app/services/suggestions/apply_service.rb
+++ b/app/services/suggestions/apply_service.rb
@@ -11,7 +11,17 @@ module Suggestions
return error('Suggestion is not appliable')
end
- params = file_update_params(suggestion)
+ unless latest_source_head?(suggestion)
+ return error('The file has been changed')
+ end
+
+ diff_file = suggestion.note.latest_diff_file
+
+ unless diff_file
+ return error('The file was not found')
+ end
+
+ params = file_update_params(suggestion, diff_file)
result = ::Files::UpdateService.new(suggestion.project, @current_user, params).execute
if result[:status] == :success
@@ -19,30 +29,45 @@ module Suggestions
end
result
+ rescue Files::UpdateService::FileChangedError
+ error('The file has been changed')
end
private
- def file_update_params(suggestion)
- diff_file = suggestion.diff_file
+ # Checks whether the latest source branch HEAD matches with
+ # the position HEAD we're using to update the file content. Since
+ # the persisted HEAD is updated async (for MergeRequest),
+ # it's more consistent to fetch this data directly from the
+ # repository.
+ def latest_source_head?(suggestion)
+ suggestion.position.head_sha == suggestion.noteable.source_branch_sha
+ end
- file_path = diff_file.file_path
- branch_name = suggestion.noteable.source_branch
- file_content = new_file_content(suggestion)
+ def file_update_params(suggestion, diff_file)
+ blob = diff_file.new_blob
+ file_path = suggestion.file_path
+ branch_name = suggestion.branch
+ file_content = new_file_content(suggestion, blob)
commit_message = "Apply suggestion to #{file_path}"
+ file_last_commit =
+ Gitlab::Git::Commit.last_for_path(suggestion.project.repository,
+ blob.commit_id,
+ blob.path)
+
{
file_path: file_path,
branch_name: branch_name,
start_branch: branch_name,
commit_message: commit_message,
- file_content: file_content
+ file_content: file_content,
+ last_commit_sha: file_last_commit&.id
}
end
- def new_file_content(suggestion)
+ def new_file_content(suggestion, blob)
range = suggestion.from_line_index..suggestion.to_line_index
- blob = suggestion.diff_file.new_blob
blob.load_all_data!
content = blob.data.lines
diff --git a/app/services/suggestions/create_service.rb b/app/services/suggestions/create_service.rb
index 77e958cbe0c..c7ac2452c53 100644
--- a/app/services/suggestions/create_service.rb
+++ b/app/services/suggestions/create_service.rb
@@ -9,6 +9,10 @@ module Suggestions
def execute
return unless @note.supports_suggestion?
+ diff_file = @note.latest_diff_file
+
+ return unless diff_file
+
suggestions = Banzai::SuggestionsParser.parse(@note.note)
# For single line suggestion we're only looking forward to
@@ -20,7 +24,7 @@ module Suggestions
rows =
suggestions.map.with_index do |suggestion, index|
- from_content = changing_lines(comment_line, comment_line)
+ from_content = changing_lines(diff_file, comment_line, comment_line)
# The parsed suggestion doesn't have information about the correct
# ending characters (we may have a line break, or not), so we take
@@ -44,8 +48,8 @@ module Suggestions
private
- def changing_lines(from_line, to_line)
- @note.diff_file.new_blob_lines_between(from_line, to_line).join
+ def changing_lines(diff_file, from_line, to_line)
+ diff_file.new_blob_lines_between(from_line, to_line).join
end
def line_break_chars(line)
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index ec6c306227b..ea8ac7e4656 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -360,7 +360,7 @@ module SystemNoteService
# author - User performing the change
# branch_type - 'source' or 'target'
# old_branch - old branch name
- # new_branch - new branch nmae
+ # new_branch - new branch name
#
# Example Note text:
#
diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb
index 6bb9bb3988e..4de6b2d2774 100644
--- a/app/services/tags/create_service.rb
+++ b/app/services/tags/create_service.rb
@@ -2,7 +2,7 @@
module Tags
class CreateService < BaseService
- def execute(tag_name, target, message, release_description = nil)
+ def execute(tag_name, target, message)
valid_tag = Gitlab::GitRefValidator.validate(tag_name)
return error('Tag name invalid') unless valid_tag
@@ -20,10 +20,7 @@ module Tags
end
if new_tag
- if release_description.present?
- CreateReleaseService.new(@project, @current_user)
- .execute(tag_name, release_description)
- end
+ repository.expire_tags_cache
success.merge(tag: new_tag)
else
diff --git a/app/services/tags/destroy_service.rb b/app/services/tags/destroy_service.rb
index 6bfef09ac54..cab507946b4 100644
--- a/app/services/tags/destroy_service.rb
+++ b/app/services/tags/destroy_service.rb
@@ -2,7 +2,6 @@
module Tags
class DestroyService < BaseService
- # rubocop: disable CodeReuse/ActiveRecord
def execute(tag_name)
repository = project.repository
tag = repository.find_tag(tag_name)
@@ -12,8 +11,12 @@ module Tags
end
if repository.rm_tag(current_user, tag_name)
- release = project.releases.find_by(tag: tag_name)
- release&.destroy
+ ##
+ # When a tag in a repository is destroyed,
+ # release assets will be destroyed too.
+ Releases::DestroyService
+ .new(project, current_user, tag: tag_name)
+ .execute
push_data = build_push_data(tag)
EventCreateService.new.push(project, current_user, push_data)
@@ -27,7 +30,6 @@ module Tags
rescue Gitlab::Git::PreReceiveError => ex
error(ex.message)
end
- # rubocop: enable CodeReuse/ActiveRecord
def error(message, return_code = 400)
super(message).merge(return_code: return_code)
diff --git a/app/services/task_list_toggle_service.rb b/app/services/task_list_toggle_service.rb
new file mode 100644
index 00000000000..f6602a35033
--- /dev/null
+++ b/app/services/task_list_toggle_service.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+# Finds the correct checkbox in the passed in markdown/html and toggles it's state,
+# returning the updated markdown/html.
+# We don't care if the text has changed above or below the specific checkbox, as long
+# the checkbox still exists at exactly the same line number and the text is equal.
+# If successful, new values are available in `updated_markdown` and `updated_markdown_html`
+class TaskListToggleService
+ attr_reader :updated_markdown, :updated_markdown_html
+
+ def initialize(markdown, markdown_html, line_source:, line_number:, toggle_as_checked:)
+ @markdown, @markdown_html = markdown, markdown_html
+ @line_source, @line_number = line_source, line_number
+ @toggle_as_checked = toggle_as_checked
+
+ @updated_markdown, @updated_markdown_html = nil
+ end
+
+ def execute
+ return false unless markdown && markdown_html
+
+ toggle_markdown && toggle_markdown_html
+ end
+
+ private
+
+ attr_reader :markdown, :markdown_html, :toggle_as_checked
+ attr_reader :line_source, :line_number
+
+ def toggle_markdown
+ source_lines = markdown.split("\n")
+ source_line_index = line_number - 1
+ markdown_task = source_lines[source_line_index]
+
+ # The source in the DB could be using either \n or \r\n line endings
+ return unless markdown_task.chomp == line_source
+ return unless source_checkbox = Taskable::ITEM_PATTERN.match(markdown_task)
+
+ currently_checked = TaskList::Item.new(source_checkbox[1]).complete?
+
+ # Check `toggle_as_checked` to make sure we don't accidentally replace
+ # any `[ ]` or `[x]` in the middle of the text
+ if currently_checked
+ markdown_task.sub!(Taskable::COMPLETE_PATTERN, '[ ]') unless toggle_as_checked
+ else
+ markdown_task.sub!(Taskable::INCOMPLETE_PATTERN, '[x]') if toggle_as_checked
+ end
+
+ source_lines[source_line_index] = markdown_task
+ @updated_markdown = source_lines.join("\n")
+ end
+
+ def toggle_markdown_html
+ html = Nokogiri::HTML.fragment(markdown_html)
+ html_checkbox = get_html_checkbox(html)
+ return unless html_checkbox
+
+ if toggle_as_checked
+ html_checkbox[:checked] = 'checked'
+ else
+ html_checkbox.remove_attribute('checked')
+ end
+
+ @updated_markdown_html = html.to_html
+ end
+
+ # When using CommonMark, we should be able to use the embedded `sourcepos` attribute to
+ # target the exact line in the DOM.
+ def get_html_checkbox(html)
+ html.css(".task-list-item[data-sourcepos^='#{line_number}:'] input.task-list-item-checkbox").first
+ end
+end
diff --git a/app/services/update_release_service.rb b/app/services/update_release_service.rb
deleted file mode 100644
index e2228ca026c..00000000000
--- a/app/services/update_release_service.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateReleaseService < BaseService
- # rubocop: disable CodeReuse/ActiveRecord
- def execute(tag_name, release_description)
- repository = project.repository
- existing_tag = repository.find_tag(tag_name)
-
- if existing_tag
- release = project.releases.find_by(tag: tag_name)
-
- if release
- release.update(description: release_description)
-
- success(release)
- else
- error('Release does not exist', 404)
- end
- else
- error('Tag does not exist', 404)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def success(release)
- super().merge(release: release)
- end
-end
diff --git a/app/services/upload_service.rb b/app/services/upload_service.rb
index 39909ee4f82..403944557a2 100644
--- a/app/services/upload_service.rb
+++ b/app/services/upload_service.rb
@@ -6,12 +6,12 @@ class UploadService
end
def execute
- return nil unless @file && @file.size <= max_attachment_size
+ return unless @file && @file.size <= max_attachment_size
uploader = @uploader_class.new(@model, nil, @uploader_context)
uploader.store!(@file)
- uploader.to_h
+ uploader
end
private
diff --git a/app/services/users/activity_service.rb b/app/services/users/activity_service.rb
index db03ba8756f..e50840a9158 100644
--- a/app/services/users/activity_service.rb
+++ b/app/services/users/activity_service.rb
@@ -26,12 +26,15 @@ module Users
def record_activity
return if Gitlab::Database.read_only?
+ today = Date.today
+
+ return if @user.last_activity_on == today
+
lease = Gitlab::ExclusiveLease.new("acitvity_service:#{@user.id}",
timeout: LEASE_TIMEOUT)
return unless lease.try_obtain
- @user.update_attribute(:last_activity_on, Date.today)
- Rails.logger.debug("Recorded activity: #{@activity} for User ID: #{@user.id} (username: #{@user.username})")
+ @user.update_attribute(:last_activity_on, today)
end
end
end
diff --git a/app/services/users/update_service.rb b/app/services/users/update_service.rb
index af4fe1aebb9..0b00bd135eb 100644
--- a/app/services/users/update_service.rb
+++ b/app/services/users/update_service.rb
@@ -55,7 +55,7 @@ module Users
params.reject! { |key, _| read_only.include?(key.to_sym) }
end
- @user.assign_attributes(params) if params.any?
+ @user.assign_attributes(params) unless params.empty?
end
end
end
diff --git a/app/services/validate_new_branch_service.rb b/app/services/validate_new_branch_service.rb
index c19e2ec2043..3f4a59e5cee 100644
--- a/app/services/validate_new_branch_service.rb
+++ b/app/services/validate_new_branch_service.rb
@@ -3,14 +3,14 @@
require_relative 'base_service'
class ValidateNewBranchService < BaseService
- def execute(branch_name)
+ def execute(branch_name, force: false)
valid_branch = Gitlab::GitRefValidator.validate(branch_name)
unless valid_branch
return error('Branch name is invalid')
end
- if project.repository.branch_exists?(branch_name)
+ if project.repository.branch_exists?(branch_name) && !force
return error('Branch already exists')
end
diff --git a/app/uploaders/external_diff_uploader.rb b/app/uploaders/external_diff_uploader.rb
new file mode 100644
index 00000000000..d2707cd0777
--- /dev/null
+++ b/app/uploaders/external_diff_uploader.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class ExternalDiffUploader < GitlabUploader
+ include ObjectStorage::Concern
+
+ storage_options Gitlab.config.external_diffs
+
+ alias_method :upload, :model
+
+ def filename
+ "diff-#{model.id}"
+ end
+
+ def store_dir
+ dynamic_segment
+ end
+
+ private
+
+ def dynamic_segment
+ File.join(model.model_name.plural, "mr-#{model.merge_request_id}")
+ end
+end
diff --git a/app/uploaders/file_mover.rb b/app/uploaders/file_mover.rb
index a7f8615e9ba..236b7ed2b3d 100644
--- a/app/uploaders/file_mover.rb
+++ b/app/uploaders/file_mover.rb
@@ -11,6 +11,8 @@ class FileMover
end
def execute
+ return unless valid?
+
move
if update_markdown
@@ -21,6 +23,12 @@ class FileMover
private
+ def valid?
+ Pathname.new(temp_file_path).realpath.to_path.start_with?(
+ (Pathname(temp_file_uploader.root) + temp_file_uploader.base_dir).to_path
+ )
+ end
+
def move
FileUtils.mkdir_p(File.dirname(file_path))
FileUtils.move(temp_file_path, file_path)
diff --git a/app/uploaders/personal_file_uploader.rb b/app/uploaders/personal_file_uploader.rb
index 25474b494ff..272837aa6ce 100644
--- a/app/uploaders/personal_file_uploader.rb
+++ b/app/uploaders/personal_file_uploader.rb
@@ -6,8 +6,15 @@ class PersonalFileUploader < FileUploader
options.storage_path
end
- def self.base_dir(model, _store = nil)
- File.join(options.base_dir, model_path_segment(model))
+ def self.base_dir(model, store = nil)
+ base_dirs(model)[store || Store::LOCAL]
+ end
+
+ def self.base_dirs(model)
+ {
+ Store::LOCAL => File.join(options.base_dir, model_path_segment(model)),
+ Store::REMOTE => model_path_segment(model)
+ }
end
def self.model_path_segment(model)
@@ -33,13 +40,6 @@ class PersonalFileUploader < FileUploader
store_dirs[object_store]
end
- def store_dirs
- {
- Store::LOCAL => File.join(base_dir, dynamic_segment),
- Store::REMOTE => File.join(self.class.model_path_segment(model), dynamic_segment)
- }
- end
-
private
def secure_url
diff --git a/app/uploaders/records_uploads.rb b/app/uploaders/records_uploads.rb
index 0efca895a50..9a243e07936 100644
--- a/app/uploaders/records_uploads.rb
+++ b/app/uploaders/records_uploads.rb
@@ -23,13 +23,23 @@ module RecordsUploads
return unless model
return unless file && file.exists?
- Upload.transaction do
- uploads.where(path: upload_path).delete_all
- upload.delete if upload
-
- self.upload = build_upload.tap(&:save!)
+ # MySQL InnoDB may encounter a deadlock if a deletion and an
+ # insert is in the same transaction due to its next-key locking
+ # algorithm, so we need to skip the transaction.
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/55161#note_131556351
+ if Gitlab::Database.mysql?
+ readd_upload
+ else
+ Upload.transaction { readd_upload }
end
end
+
+ def readd_upload
+ uploads.where(path: upload_path).delete_all
+ upload.delete if upload
+
+ self.upload = build_upload.tap(&:save!)
+ end
# rubocop: enable CodeReuse/ActiveRecord
def upload_path
diff --git a/app/validators/sha_validator.rb b/app/validators/sha_validator.rb
new file mode 100644
index 00000000000..085fca4d65d
--- /dev/null
+++ b/app/validators/sha_validator.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class ShaValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ return if value.blank? || value.match(/\A\h{40}\z/)
+
+ record.errors.add(attribute, 'is not a valid SHA')
+ end
+end
diff --git a/app/validators/url_validator.rb b/app/validators/url_validator.rb
index 5feb0b0f05b..3fd015c3cf5 100644
--- a/app/validators/url_validator.rb
+++ b/app/validators/url_validator.rb
@@ -26,6 +26,7 @@
# - allow_local_network: Allow urls pointing to private network addresses. Default: true
# - ports: Allowed ports. Default: all.
# - enforce_user: Validate user format. Default: false
+# - enforce_sanitization: Validate that there are no html/css/js tags. Default: false
#
# Example:
# class User < ActiveRecord::Base
@@ -70,7 +71,8 @@ class UrlValidator < ActiveModel::EachValidator
allow_localhost: true,
allow_local_network: true,
ascii_only: false,
- enforce_user: false
+ enforce_user: false,
+ enforce_sanitization: false
}
end
@@ -91,6 +93,12 @@ class UrlValidator < ActiveModel::EachValidator
end
def allow_setting_local_requests?
+ # We cannot use Gitlab::CurrentSettings as ApplicationSetting itself
+ # uses UrlValidator to validate urls. This ends up in a cycle
+ # when Gitlab::CurrentSettings creates an ApplicationSetting which then
+ # calls this validator.
+ #
+ # See https://gitlab.com/gitlab-org/gitlab-ee/issues/9833
ApplicationSetting.current&.allow_local_requests_from_hooks_and_services?
end
end
diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml
index cb67079853e..a5f34d0dab2 100644
--- a/app/views/admin/appearances/_form.html.haml
+++ b/app/views/admin/appearances/_form.html.haml
@@ -1,86 +1,97 @@
-= form_for @appearance, url: admin_appearances_path do |f|
+= form_for @appearance, url: admin_appearances_path, html: { class: 'prepend-top-default' } do |f|
= form_errors(@appearance)
- %fieldset.app_logo
- %legend
- Navigation bar:
- .form-group.row
- = f.label :header_logo, 'Header logo', class: 'col-sm-2 col-form-label pt-0'
- .col-sm-10
- - if @appearance.header_logo?
- = image_tag @appearance.header_logo_url, class: 'appearance-light-logo-preview'
- - if @appearance.persisted?
- %br
- = link_to 'Remove header logo', header_logos_admin_appearances_path, data: { confirm: "Header logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-inverted btn-remove btn-sm remove-logo"
- %hr
- = f.hidden_field :header_logo_cache
- = f.file_field :header_logo, class: ""
- .hint
- Maximum file size is 1MB. Pages are optimized for a 28px tall header logo
- %fieldset.app_logo
- %legend
- Favicon:
- .form-group.row
- = f.label :favicon, 'Favicon', class: 'col-sm-2 col-form-label pt-0'
- .col-sm-10
- - if @appearance.favicon?
- = image_tag @appearance.favicon_url, class: 'appearance-light-logo-preview'
- - if @appearance.persisted?
- %br
- = link_to 'Remove favicon', favicon_admin_appearances_path, data: { confirm: "Favicon will be removed. Are you sure?"}, method: :delete, class: "btn btn-inverted btn-remove btn-sm remove-logo"
- %hr
- = f.hidden_field :favicon_cache
- = f.file_field :favicon, class: ''
- .hint
- Maximum file size is 1MB. Image size must be 32x32px. Allowed image formats are #{favicon_extension_whitelist}.
- %br
- Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior.
+ .row
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0 Navigation bar
- %fieldset.sign-in
- %legend
- Sign in/Sign up pages:
- .form-group.row
- = f.label :title, class: 'col-sm-2 col-form-label'
- .col-sm-10
- = f.text_field :title, class: "form-control"
- .form-group.row
- = f.label :description, class: 'col-sm-2 col-form-label'
- .col-sm-10
- = f.text_area :description, class: "form-control", rows: 10
- .hint
- Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('user/markdown'), target: '_blank'}.
- .form-group.row
- = f.label :logo, class: 'col-sm-2 col-form-label pt-0'
- .col-sm-10
- - if @appearance.logo?
- = image_tag @appearance.logo_url, class: 'appearance-logo-preview'
- - if @appearance.persisted?
- %br
- = link_to 'Remove logo', logo_admin_appearances_path, data: { confirm: "Logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-inverted btn-remove btn-sm remove-logo"
- %hr
- = f.hidden_field :logo_cache
- = f.file_field :logo, class: ""
- .hint
- Maximum file size is 1MB. Pages are optimized for a 640x360 px logo.
+ .col-lg-8
+ .form-group
+ = f.label :header_logo, 'Header logo', class: 'col-form-label label-bold pt-0'
+ %p
+ - if @appearance.header_logo?
+ = image_tag @appearance.header_logo_path, class: 'appearance-light-logo-preview'
+ - if @appearance.persisted?
+ %br
+ = link_to 'Remove header logo', header_logos_admin_appearances_path, data: { confirm: "Header logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-inverted btn-remove btn-sm remove-logo"
+ %hr
+ = f.hidden_field :header_logo_cache
+ = f.file_field :header_logo, class: ""
+ .hint
+ Maximum file size is 1MB. Pages are optimized for a 28px tall header logo
+ %hr
+ .row
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0 Favicon
+
+ .col-lg-8
+ .form-group
+ = f.label :favicon, 'Favicon', class: 'col-form-label label-bold pt-0'
+ %p
+ - if @appearance.favicon?
+ = image_tag @appearance.favicon_path, class: 'appearance-light-logo-preview'
+ - if @appearance.persisted?
+ %br
+ = link_to 'Remove favicon', favicon_admin_appearances_path, data: { confirm: "Favicon will be removed. Are you sure?"}, method: :delete, class: "btn btn-inverted btn-remove btn-sm remove-logo"
+ %hr
+ = f.hidden_field :favicon_cache
+ = f.file_field :favicon, class: ''
+ .hint
+ Maximum file size is 1MB. Image size must be 32x32px. Allowed image formats are #{favicon_extension_whitelist}.
+ %br
+ Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior.
+
+ = render partial: 'admin/appearances/system_header_footer_form', locals: { form: f }
- %fieldset
- %legend
- New project pages:
- .form-group.row
- = f.label :new_project_guidelines, class: 'col-sm-2 col-form-label'
- .col-sm-10
- = f.text_area :new_project_guidelines, class: "form-control", rows: 10
- .hint
- Guidelines parsed with #{link_to "GitLab Flavored Markdown", help_page_path('user/markdown'), target: '_blank'}.
+ %hr
+ .row
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0 Sign in/Sign up pages
- .form-actions
- = f.submit 'Save', class: 'btn btn-success append-right-10'
- - if @appearance.persisted?
- Preview last save:
- = link_to 'Sign-in page', preview_sign_in_admin_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
- = link_to 'New project page', new_project_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
+ .col-lg-8
+ .form-group
+ = f.label :title, class: 'col-form-label label-bold'
+ = f.text_field :title, class: "form-control"
+ .form-group
+ = f.label :description, class: 'col-form-label label-bold'
+ = f.text_area :description, class: "form-control", rows: 10
+ .hint
+ Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('user/markdown'), target: '_blank'}.
+ .form-group
+ = f.label :logo, class: 'col-form-label label-bold pt-0'
+ %p
+ - if @appearance.logo?
+ = image_tag @appearance.logo_path, class: 'appearance-logo-preview'
+ - if @appearance.persisted?
+ %br
+ = link_to 'Remove logo', logo_admin_appearances_path, data: { confirm: "Logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-inverted btn-remove btn-sm remove-logo"
+ %hr
+ = f.hidden_field :logo_cache
+ = f.file_field :logo, class: ""
+ .hint
+ Maximum file size is 1MB. Pages are optimized for a 640x360 px logo.
+
+ %hr
+ .row
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0 New project pages
+
+ .col-lg-8
+ .form-group
+ = f.label :new_project_guidelines, class: 'col-form-label label-bold'
+ %p
+ = f.text_area :new_project_guidelines, class: "form-control", rows: 10
+ .hint
+ Guidelines parsed with #{link_to "GitLab Flavored Markdown", help_page_path('user/markdown'), target: '_blank'}.
+
+ .prepend-top-default.append-bottom-default
+ = f.submit 'Update appearance settings', class: 'btn btn-success'
+ - if @appearance.persisted?
+ Preview last save:
+ = link_to 'Sign-in page', preview_sign_in_admin_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
+ = link_to 'New project page', new_project_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
- - if @appearance.updated_at
- %span.float-right
- Last edit #{time_ago_with_tooltip(@appearance.updated_at)}
+ - if @appearance.updated_at
+ %span.float-right
+ Last edit #{time_ago_with_tooltip(@appearance.updated_at)}
diff --git a/app/views/admin/appearances/_system_header_footer_form.html.haml b/app/views/admin/appearances/_system_header_footer_form.html.haml
new file mode 100644
index 00000000000..4301ebd05af
--- /dev/null
+++ b/app/views/admin/appearances/_system_header_footer_form.html.haml
@@ -0,0 +1,33 @@
+- form = local_assigns.fetch(:form)
+
+%hr
+.row
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0
+ = _('System header and footer')
+
+ .col-lg-8
+ .form-group
+ = form.label :header_message, _('Header message'), class: 'col-form-label label-bold'
+ = form.text_area :header_message, placeholder: _('State your message to activate'), class: "form-control js-autosize"
+ .form-group
+ = form.label :footer_message, _('Footer message'), class: 'col-form-label label-bold'
+ = form.text_area :footer_message, placeholder: _('State your message to activate'), class: "form-control js-autosize"
+ .form-group
+ .form-check
+ = form.check_box :email_header_and_footer_enabled, class: 'form-check-input'
+ = form.label :email_header_and_footer_enabled, class: 'label-bold' do
+ = _('Enable header and footer in emails')
+
+ .hint
+ = _('Add header and footer to emails. Please note that color settings will only be applied within the application interface')
+
+ .form-group.js-toggle-colors-container
+ %button.btn.btn-link.js-toggle-colors-link{ type: 'button' }
+ = _('Customize colors')
+ .form-group.js-toggle-colors-container.hide
+ = form.label :message_background_color, _('Background Color'), class: 'col-form-label label-bold'
+ = form.color_field :message_background_color, class: "form-control"
+ .form-group.js-toggle-colors-container.hide
+ = form.label :message_font_color, _('Font Color'), class: 'col-form-label label-bold'
+ = form.color_field :message_font_color, class: "form-control"
diff --git a/app/views/admin/appearances/show.html.haml b/app/views/admin/appearances/show.html.haml
index 454b779842c..ccf6f960cf2 100644
--- a/app/views/admin/appearances/show.html.haml
+++ b/app/views/admin/appearances/show.html.haml
@@ -1,9 +1,4 @@
- page_title "Appearance"
-
-%h3.page-title
- Appearance settings
-%p.light
- You can modify the look and feel of GitLab here
-%hr
+- @content_class = "limit-container-width" unless fluid_layout
= render 'form'
diff --git a/app/views/admin/application_settings/_account_and_limit.html.haml b/app/views/admin/application_settings/_account_and_limit.html.haml
index 10bc3452d8b..65a24854583 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -15,7 +15,7 @@
= f.number_field :max_attachment_size, class: 'form-control'
.form-group
= f.label :receive_max_input_size, 'Maximum push size (MB)', class: 'label-light'
- = f.number_field :receive_max_input_size, class: 'form-control'
+ = f.number_field :receive_max_input_size, class: 'form-control qa-receive-max-input-size-field'
.form-group
= f.label :session_expire_delay, 'Session duration (minutes)', class: 'label-light'
= f.number_field :session_expire_delay, class: 'form-control'
@@ -46,4 +46,4 @@
= f.label :user_show_add_ssh_key_message, class: 'form-check-label' do
Inform users without uploaded SSH keys that they can't push over SSH until one is added
- = f.submit 'Save changes', class: 'btn btn-success'
+ = f.submit 'Save changes', class: 'btn btn-success qa-save-changes-button'
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index fdaad1cf181..c99d7e9b8e9 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -13,7 +13,7 @@
= s_('CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found.')
= link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank'
.form-group
- = f.label :auto_devops_domain, class: 'label-bold'
+ = f.label :auto_devops_domain, s_('AdminSettings|Auto DevOps domain'), class: 'label-bold'
= f.text_field :auto_devops_domain, class: 'form-control', placeholder: 'domain.com'
.form-text.text-muted
= s_("AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages.")
diff --git a/app/views/admin/application_settings/_localization.html.haml b/app/views/admin/application_settings/_localization.html.haml
new file mode 100644
index 00000000000..95d016a94a5
--- /dev/null
+++ b/app/views/admin/application_settings/_localization.html.haml
@@ -0,0 +1,11 @@
+= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-localization-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@application_setting)
+
+ %fieldset
+ .form-group
+ = f.label :first_day_of_week, _('Default first day of the week'), class: 'label-bold'
+ = f.select :first_day_of_week, first_day_of_week_choices, {}, class: 'form-control'
+ .form-text.text-muted
+ = _('Default first day of the week in calendars and date pickers.')
+
+ = f.submit _('Save changes'), class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml
index c6c29ed1f21..7a2bbfcdc4d 100644
--- a/app/views/admin/application_settings/_repository_storage.html.haml
+++ b/app/views/admin/application_settings/_repository_storage.html.haml
@@ -11,7 +11,6 @@
.form-text.text-muted
Enable immutable, hash-based paths and repository names to store repositories on disk. This prevents
repositories from having to be moved or renamed when the Project URL changes and may improve disk I/O performance.
- %em (EXPERIMENTAL)
.form-group
= f.label :repository_storages, 'Storage paths for new projects', class: 'label-bold'
= f.select :repository_storages, repository_storages_options_for_select(@application_setting.repository_storages),
diff --git a/app/views/admin/application_settings/preferences.html.haml b/app/views/admin/application_settings/preferences.html.haml
index 00000b86ab7..c468d69d7b8 100644
--- a/app/views/admin/application_settings/preferences.html.haml
+++ b/app/views/admin/application_settings/preferences.html.haml
@@ -56,3 +56,14 @@
= _('Configure Gitaly timeouts.')
.settings-content
= render 'gitaly'
+
+%section.settings.as-localization.no-animate#js-localization-settings{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4
+ = _('Localization')
+ %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Various localization settings.')
+ .settings-content
+ = render 'localization'
diff --git a/app/views/admin/application_settings/show.html.haml b/app/views/admin/application_settings/show.html.haml
index 65e4723afe6..fc9dd29b8ca 100644
--- a/app/views/admin/application_settings/show.html.haml
+++ b/app/views/admin/application_settings/show.html.haml
@@ -13,7 +13,7 @@
.settings-content
= render 'visibility_and_access'
-%section.settings.as-account-limit.no-animate#js-account-settings{ class: ('expanded' if expanded_by_default?) }
+%section.settings.qa-account-and-limit-settings.as-account-limit.no-animate#js-account-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
= _('Account and limit')
diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml
index 0a688b90f3a..395c469255e 100644
--- a/app/views/admin/groups/_group.html.haml
+++ b/app/views/admin/groups/_group.html.haml
@@ -22,7 +22,7 @@
%span.visibility-icon.has-tooltip{ data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group) }
= visibility_level_icon(group.visibility_level, fw: false)
- .avatar-container.s40
+ .avatar-container.rect-avatar.s40
= group_icon(group, class: "avatar s40 d-none d-sm-block")
.title
= link_to [:admin, group], class: 'group-name' do
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index da2ebb08405..00d255846f9 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -15,7 +15,7 @@
= _('Group info:')
%ul.content-list
%li
- .avatar-container.s60
+ .avatar-container.rect-avatar.s60
= group_icon(@group, class: "avatar s60")
%li
%span.light= _('Name:')
@@ -104,7 +104,7 @@
- link_to_help = link_to(_("here"), help_page_path("user/permissions"))
= _('Read more about project permissions <strong>%{link_to_help}</strong>').html_safe % { link_to_help: link_to_help }
- = form_tag admin_group_members_update_path(@group), id: "new_project_member", class: "bulk_import", method: :put do
+ = form_tag admin_group_members_update_path(@group), id: "new_project_member", class: "bulk_import", method: :put do
%div
= users_select_tag(:user_ids, multiple: true, email_user: true, skip_ldap: @group.ldap_synced?, scope: :all)
.prepend-top-10
diff --git a/app/views/admin/projects/_projects.html.haml b/app/views/admin/projects/_projects.html.haml
index 50296a2afe7..5bc695aa7b5 100644
--- a/app/views/admin/projects/_projects.html.haml
+++ b/app/views/admin/projects/_projects.html.haml
@@ -19,7 +19,7 @@
.title
= link_to(admin_namespace_project_path(project.namespace, project)) do
.dash-project-avatar
- .avatar-container.s40
+ .avatar-container.rect-avatar.s40
= project_icon(project, alt: '', class: 'avatar project-avatar s40', width: 40, height: 40)
%span.project-full-name
%span.namespace-name
diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml
index e4fc2985087..ecf2b1d60ba 100644
--- a/app/views/admin/runners/_runner.html.haml
+++ b/app/views/admin/runners/_runner.html.haml
@@ -18,19 +18,19 @@
.table-mobile-content
= link_to runner.short_sha, admin_runner_path(runner)
- .table-section.section-15
+ .table-section.section-20
.table-mobile-header{ role: 'rowheader' }= _('Description')
.table-mobile-content.str-truncated.has-tooltip{ title: runner.description }
= runner.description
- .table-section.section-15
+ .table-section.section-10
.table-mobile-header{ role: 'rowheader' }= _('Version')
.table-mobile-content.str-truncated.has-tooltip{ title: runner.version }
= runner.version
.table-section.section-10
.table-mobile-header{ role: 'rowheader' }= _('IP Address')
- .table-mobile-content
+ .table-mobile-content.str-truncated.has-tooltip{ title: runner.ip_address }
= runner.ip_address
.table-section.section-5
@@ -44,20 +44,21 @@
.table-section.section-5
.table-mobile-header{ role: 'rowheader' }= _('Jobs')
.table-mobile-content
- = runner.builds.count(:all)
+ = limited_counter_with_delimiter(runner.builds)
.table-section.section-10.section-wrap
.table-mobile-header{ role: 'rowheader' }= _('Tags')
.table-mobile-content
- - runner.tag_list.sort.each do |tag|
+ - runner.tags.map(&:name).sort.each do |tag|
%span.badge.badge-primary
= tag
.table-section.section-10
.table-mobile-header{ role: 'rowheader' }= _('Last contact')
.table-mobile-content
- - if runner.contacted_at
- = time_ago_with_tooltip runner.contacted_at
+ - contacted_at = runner_contacted_at(runner)
+ - if contacted_at
+ = time_ago_with_tooltip contacted_at
- else
= _('Never')
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index e9e4e0847d3..2e23b748edb 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -92,6 +92,25 @@
= button_tag class: %w[btn btn-link] do
= runner_type.titleize
+ #js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ - Ci::Runner::AVAILABLE_TYPES.each do |runner_type|
+ %li.filter-dropdown-item{ data: { value: runner_type } }
+ = button_tag class: %w[btn btn-link] do
+ = runner_type.titleize
+
+ #js-dropdown-runner-tag.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'none' } }
+ %button.btn.btn-link
+ = _('No Tag')
+ %li.divider.droplab-item-ignore
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ %button.btn.btn-link.js-data-value
+ %span.dropdown-light-content
+ {{name}}
+
= button_tag class: %w[clear-search hidden] do
= icon('times')
.filter-dropdown-container
@@ -106,8 +125,8 @@
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-10{ role: 'rowheader' }= _('Type')
.table-section.section-10{ role: 'rowheader' }= _('Runner token')
- .table-section.section-15{ role: 'rowheader' }= _('Description')
- .table-section.section-15{ role: 'rowheader' }= _('Version')
+ .table-section.section-20{ role: 'rowheader' }= _('Description')
+ .table-section.section-10{ role: 'rowheader' }= _('Version')
.table-section.section-10{ role: 'rowheader' }= _('IP Address')
.table-section.section-5{ role: 'rowheader' }= _('Projects')
.table-section.section-5{ role: 'rowheader' }= _('Jobs')
diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml
index b2163ee85fa..be7bfa958b2 100644
--- a/app/views/admin/users/_user.html.haml
+++ b/app/views/admin/users/_user.html.haml
@@ -1,36 +1,37 @@
-%li.flex-row
- .user-avatar
- = image_tag avatar_icon_for_user(user), class: "avatar", alt: ''
- .row-main-content
- .user-name.row-title.str-truncated-100
- = link_to user.name, [:admin, user]
- - if user.blocked?
- %span.badge.badge-danger blocked
- - if user.admin?
- %span.badge.badge-success Admin
- - if user.external?
- %span.badge.badge-secondary External
- - if user == current_user
- %span It's you!
- .row-second-line.str-truncated-100
- = mail_to user.email, user.email
- .controls
- = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn'
- - unless user == current_user
- .dropdown.inline
- %a.dropdown-new.btn.btn-default#project-settings-button{ href: '#', data: { toggle: 'dropdown' } }
+.gl-responsive-table-row{ role: 'row' }
+ .table-section.section-40
+ .table-mobile-header{ role: 'rowheader' }
+ = _('Name')
+ .table-mobile-content
+ = render 'user_detail', user: user
+ .table-section.section-25
+ .table-mobile-header{ role: 'rowheader' }
+ = _('Created on')
+ .table-mobile-content
+ = l(user.created_at.to_date, format: :admin)
+ .table-section.section-15
+ .table-mobile-header{ role: 'rowheader' }
+ = _('Last activity')
+ .table-mobile-content
+ = user.last_activity_on.nil? ? _('Never') : l(user.last_activity_on, format: :admin)
+ .table-section.section-20.table-button-footer
+ .table-action-buttons
+ = link_to _('Edit'), edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn btn-default'
+ - unless user == current_user
+ %button.dropdown-new.btn.btn-default{ type: 'button', data: { toggle: 'dropdown' } }
= icon('cog')
= icon('caret-down')
%ul.dropdown-menu.dropdown-menu-right
%li.dropdown-header
- Settings
+ = _('Settings')
%li
- if user.ldap_blocked?
- %span.small Cannot unblock LDAP blocked users
+ %span.small
+ = s_('AdminUsers|Cannot unblock LDAP blocked users')
- elsif user.blocked?
- = link_to 'Unblock', unblock_admin_user_path(user), method: :put
+ = link_to _('Unblock'), unblock_admin_user_path(user), method: :put
- else
- = link_to 'Block', block_admin_user_path(user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put
+ = link_to _('Block'), block_admin_user_path(user), data: { confirm: "#{s_('AdminUsers|User will be blocked').upcase}! #{_('Are you sure')}?" }, method: :put
- if user.access_locked?
%li
= link_to _('Unlock'), unlock_admin_user_path(user), method: :put, data: { confirm: _('Are you sure?') }
@@ -42,7 +43,7 @@
target: '#delete-user-modal',
delete_user_url: admin_user_path(user),
block_user_url: block_admin_user_path(user),
- username: user.name,
+ username: sanitize_name(user.name),
delete_contributions: false }, type: 'button' }
= s_('AdminUsers|Delete user')
@@ -51,6 +52,6 @@
target: '#delete-user-modal',
delete_user_url: admin_user_path(user, hard_delete: true),
block_user_url: block_admin_user_path(user),
- username: user.name,
+ username: sanitize_name(user.name),
delete_contributions: true }, type: 'button' }
= s_('AdminUsers|Delete user and contributions')
diff --git a/app/views/admin/users/_user_detail.html.haml b/app/views/admin/users/_user_detail.html.haml
new file mode 100644
index 00000000000..3319b4bad3a
--- /dev/null
+++ b/app/views/admin/users/_user_detail.html.haml
@@ -0,0 +1,17 @@
+.flex-list
+ .flex-row
+ = image_tag avatar_icon_for_user(user), class: 'avatar s32 d-none d-md-flex', alt: _('Avatar for %{name}') % { name: sanitize_name(user.name) }
+ .row-main-content
+ .row-title.str-truncated-100
+ = image_tag avatar_icon_for_user(user), class: 'avatar s16 d-xs-flex d-md-none mr-1 prepend-top-2', alt: _('Avatar for %{name}') % { name: sanitize_name(user.name) }
+ = link_to user.name, admin_user_path(user), class: 'text-plain js-user-link', data: { user_id: user.id }
+
+ = render_if_exists 'admin/users/user_detail_note', user: user
+
+ - user_badges_in_admin_section(user).each do |badge|
+ - css_badge = "badge badge-#{badge[:variant]}" if badge[:variant].present?
+ %span{ class: css_badge }
+ = badge[:text]
+
+ .row-second-line.str-truncated-100
+ = mail_to user.email, user.email, class: 'text-secondary'
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index 600120c4f05..c3d5ce0fe70 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -2,72 +2,78 @@
- page_title "Users"
%div{ class: container_class }
- .prepend-top-default
+ .top-area.scrolling-tabs-container.inner-page-scroll-tabs
+ .fade-left
+ = icon('angle-left')
+ .fade-right
+ = icon('angle-right')
+ %ul.nav-links.nav.nav-tabs.scrolling-tabs
+ = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do
+ = link_to admin_users_path do
+ = s_('AdminUsers|Active')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.active)
+ = nav_link(html_options: { class: active_when(params[:filter] == 'admins') }) do
+ = link_to admin_users_path(filter: "admins") do
+ = s_('AdminUsers|Admins')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.admins)
+ = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_enabled')} filter-two-factor-enabled" }) do
+ = link_to admin_users_path(filter: 'two_factor_enabled') do
+ = s_('AdminUsers|2FA Enabled')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.with_two_factor)
+ = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_disabled')} filter-two-factor-disabled" }) do
+ = link_to admin_users_path(filter: 'two_factor_disabled') do
+ = s_('AdminUsers|2FA Disabled')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.without_two_factor)
+ = nav_link(html_options: { class: active_when(params[:filter] == 'external') }) do
+ = link_to admin_users_path(filter: 'external') do
+ = s_('AdminUsers|External')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.external)
+ = nav_link(html_options: { class: active_when(params[:filter] == 'blocked') }) do
+ = link_to admin_users_path(filter: "blocked") do
+ = s_('AdminUsers|Blocked')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked)
+ = nav_link(html_options: { class: active_when(params[:filter] == 'wop') }) do
+ = link_to admin_users_path(filter: "wop") do
+ = s_('AdminUsers|Without projects')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.without_projects)
+ .nav-controls
+ = render_if_exists 'admin/users/admin_email_users'
+ = link_to s_('AdminUsers|New user'), new_admin_user_path, class: 'btn btn-success btn-search float-right'
+
+ .filtered-search-block.row-content-block.border-top-0
= form_tag admin_users_path, method: :get do
- if params[:filter].present?
= hidden_field_tag "filter", h(params[:filter])
.search-holder
.search-field-holder
- = search_field_tag :search_query, params[:search_query], placeholder: 'Search by name, email or username', class: 'form-control search-text-input js-search-input', spellcheck: false
+ = search_field_tag :search_query, params[:search_query], placeholder: s_('AdminUsers|Search by name, email or username'), class: 'form-control search-text-input js-search-input', spellcheck: false
- if @sort.present?
= hidden_field_tag :sort, @sort
= icon("search", class: "search-icon")
- = button_tag 'Search users' if Rails.env.test?
+ = button_tag s_('AdminUsers|Search users') if Rails.env.test?
.dropdown.user-sort-dropdown
- toggle_text = if @sort.present? then users_sort_options_hash[@sort] else sort_title_name end
= dropdown_toggle(toggle_text, { toggle: 'dropdown' })
%ul.dropdown-menu.dropdown-menu-right
%li.dropdown-header
- Sort by
+ = s_('AdminUsers|Sort by')
%li
- users_sort_options_hash.each do |value, title|
= link_to admin_users_path(sort: value, filter: params[:filter], search_query: params[:search_query]) do
= title
- = link_to 'New user', new_admin_user_path, class: 'btn btn-success btn-search'
- .top-area.scrolling-tabs-container.inner-page-scroll-tabs
- .fade-left
- = icon('angle-left')
- .fade-right
- = icon('angle-right')
- %ul.nav-links.nav.nav-tabs.scrolling-tabs
- = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do
- = link_to admin_users_path do
- Active
- %small.badge.badge-pill= limited_counter_with_delimiter(User.active)
- = nav_link(html_options: { class: active_when(params[:filter] == 'admins') }) do
- = link_to admin_users_path(filter: "admins") do
- Admins
- %small.badge.badge-pill= limited_counter_with_delimiter(User.admins)
- = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_enabled')} filter-two-factor-enabled" }) do
- = link_to admin_users_path(filter: 'two_factor_enabled') do
- 2FA Enabled
- %small.badge.badge-pill= limited_counter_with_delimiter(User.with_two_factor)
- = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_disabled')} filter-two-factor-disabled" }) do
- = link_to admin_users_path(filter: 'two_factor_disabled') do
- 2FA Disabled
- %small.badge.badge-pill= limited_counter_with_delimiter(User.without_two_factor)
- = nav_link(html_options: { class: active_when(params[:filter] == 'external') }) do
- = link_to admin_users_path(filter: 'external') do
- External
- %small.badge.badge-pill= limited_counter_with_delimiter(User.external)
- = nav_link(html_options: { class: active_when(params[:filter] == 'blocked') }) do
- = link_to admin_users_path(filter: "blocked") do
- Blocked
- %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked)
- = nav_link(html_options: { class: active_when(params[:filter] == 'wop') }) do
- = link_to admin_users_path(filter: "wop") do
- Without projects
- %small.badge.badge-pill= limited_counter_with_delimiter(User.without_projects)
+ - if @users.empty?
+ .nothing-here-block.border-top-0
+ = s_('AdminUsers|No users found')
+ - else
+ .table-holder
+ .thead-white.text-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' }
+ .table-section.section-40{ role: 'rowheader' }= _('Name')
+ .table-section.section-25{ role: 'rowheader' }= _('Created on')
+ .table-section.section-15{ role: 'rowheader' }= _('Last activity')
- %ul.flex-list.content-list
- - if @users.empty?
- %li
- .nothing-here-block No users found.
- - else
= render partial: 'admin/users/user', collection: @users
= paginate @users, theme: "gitlab"
#delete-user-modal
-
diff --git a/app/views/award_emoji/_awards_block.html.haml b/app/views/award_emoji/_awards_block.html.haml
index a758a63dfb3..8d9c083d223 100644
--- a/app/views/award_emoji/_awards_block.html.haml
+++ b/app/views/award_emoji/_awards_block.html.haml
@@ -3,7 +3,7 @@
- awards_sort(grouped_emojis).each do |emoji, awards|
%button.btn.award-control.js-emoji-btn.has-tooltip{ type: "button",
class: [(award_state_class(awardable, awards, current_user))],
- data: { placement: "bottom", title: award_user_list(awards, current_user) } }
+ data: { title: award_user_list(awards, current_user) } }
= emoji_icon(emoji)
%span.award-control-text.js-counter
= awards.count
@@ -12,7 +12,7 @@
.award-menu-holder.js-award-holder
%button.btn.award-control.has-tooltip.js-add-award{ type: 'button',
'aria-label': _('Add reaction'),
- data: { title: _('Add reaction'), placement: "bottom" } }
+ data: { title: _('Add reaction') } }
%span{ class: "award-control-icon award-control-icon-neutral" }= custom_icon('emoji_slightly_smiling_face')
%span{ class: "award-control-icon award-control-icon-positive" }= custom_icon('emoji_smiley')
%span{ class: "award-control-icon award-control-icon-super-positive" }= custom_icon('emoji_smile')
diff --git a/app/views/ci/status/_dropdown_graph_badge.html.haml b/app/views/ci/status/_dropdown_graph_badge.html.haml
index 9de9143e8b1..c787d7420b7 100644
--- a/app/views/ci/status/_dropdown_graph_badge.html.haml
+++ b/app/views/ci/status/_dropdown_graph_badge.html.haml
@@ -6,7 +6,7 @@
- tooltip = "#{subject.name} - #{status.status_tooltip}"
- if status.has_details?
- = link_to status.details_path, class: 'mini-pipeline-graph-dropdown-item', data: { toggle: 'tooltip', title: tooltip, container: 'body' } do
+ = link_to status.details_path, class: 'mini-pipeline-graph-dropdown-item', data: { toggle: 'tooltip', title: tooltip, container: 'body' } do
%span{ class: klass }= sprite_icon(status.icon)
%span.ci-build-text= subject.name
@@ -16,5 +16,5 @@
%span.ci-build-text= subject.name
- if status.has_action?
- = link_to status.action_path, class: "ci-action-icon-container ci-action-icon-wrapper js-ci-action-icon", method: status.action_method, data: { toggle: 'tooltip', title: status.action_title, container: 'body' } do
+ = link_to status.action_path, class: "ci-action-icon-container ci-action-icon-wrapper js-ci-action-icon", method: status.action_method, data: { toggle: 'tooltip', title: status.action_title, container: 'body' } do
= sprite_icon(status.action_icon, css_class: "icon-action-#{status.action_icon}")
diff --git a/app/views/ci/status/_icon.html.haml b/app/views/ci/status/_icon.html.haml
new file mode 100644
index 00000000000..f38bdb2e5ed
--- /dev/null
+++ b/app/views/ci/status/_icon.html.haml
@@ -0,0 +1,16 @@
+- status = local_assigns.fetch(:status)
+- size = local_assigns.fetch(:size, 16)
+- type = local_assigns.fetch(:type, 'pipeline')
+- tooltip_placement = local_assigns.fetch(:tooltip_placement, "left")
+- path = local_assigns.fetch(:path, status.has_details? ? status.details_path : nil)
+- css_classes = "ci-status-link ci-status-icon ci-status-icon-#{status.group} has-tooltip"
+- title = s_("PipelineStatusTooltip|Pipeline: %{ci_status}") % {ci_status: status.label}
+- if type == 'commit'
+ - title = s_("PipelineStatusTooltip|Commit: %{ci_status}") % {ci_status: status.label}
+
+- if path
+ = link_to path, class: css_classes, title: title, data: { placement: tooltip_placement } do
+ = sprite_icon(status.icon, size: size)
+- else
+ %span{ class: css_classes, title: title, data: { placement: tooltip_placement } }
+ = sprite_icon(status.icon, size: size)
diff --git a/app/views/ci/variables/_content.html.haml b/app/views/ci/variables/_content.html.haml
index fa82611d9c1..90c59bec975 100644
--- a/app/views/ci/variables/_content.html.haml
+++ b/app/views/ci/variables/_content.html.haml
@@ -1 +1,3 @@
= _('Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want.')
+= _('You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>.').html_safe
+= link_to _('More information'), help_page_path('ci/variables/README', anchor: 'variables')
diff --git a/app/views/clusters/clusters/_buttons.html.haml b/app/views/clusters/clusters/_buttons.html.haml
index 9238903aa10..c81d1d5b05a 100644
--- a/app/views/clusters/clusters/_buttons.html.haml
+++ b/app/views/clusters/clusters/_buttons.html.haml
@@ -1,6 +1,5 @@
--# This partial is overridden in EE
.nav-controls
- - if clusterable.can_create_cluster? && clusterable.clusters.empty?
+ - if clusterable.can_add_cluster?
= link_to s_('ClusterIntegration|Add Kubernetes cluster'), clusterable.new_path, class: 'btn btn-success js-add-cluster'
- else
%span.btn.btn-add-cluster.disabled.js-add-cluster
diff --git a/app/views/clusters/clusters/_empty_state.html.haml b/app/views/clusters/clusters/_empty_state.html.haml
index c926ec258f0..cfdbfe2dea1 100644
--- a/app/views/clusters/clusters/_empty_state.html.haml
+++ b/app/views/clusters/clusters/_empty_state.html.haml
@@ -9,6 +9,6 @@
= clusterable.empty_state_help_text
= clusterable.learn_more_link
- - if clusterable.can_create_cluster?
+ - if clusterable.can_add_cluster?
.text-center
= link_to s_('ClusterIntegration|Add Kubernetes cluster'), clusterable.new_path, class: 'btn btn-success'
diff --git a/app/views/clusters/clusters/_form.html.haml b/app/views/clusters/clusters/_form.html.haml
new file mode 100644
index 00000000000..9fb91a39387
--- /dev/null
+++ b/app/views/clusters/clusters/_form.html.haml
@@ -0,0 +1,46 @@
+= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster do |field|
+ = form_errors(@cluster)
+ .form-group
+ %h5= s_('ClusterIntegration|Integration status')
+ %label.append-bottom-0.js-cluster-enable-toggle-area
+ %button{ type: 'button',
+ class: "js-project-feature-toggle project-feature-toggle #{'is-checked' if @cluster.enabled?} #{'is-disabled' unless can?(current_user, :update_cluster, @cluster)}",
+ "aria-label": s_("ClusterIntegration|Toggle Kubernetes cluster"),
+ disabled: !can?(current_user, :update_cluster, @cluster) }
+ = field.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
+ %span.toggle-icon
+ = sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
+ = sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
+ .form-text.text-muted= s_('ClusterIntegration|Enable or disable GitLab\'s connection to your Kubernetes cluster.')
+
+ .form-group
+ %h5= s_('ClusterIntegration|Environment scope')
+ - if has_multiple_clusters?
+ = field.text_field :environment_scope, class: 'col-md-6 form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Environment scope')
+ .form-text.text-muted= s_("ClusterIntegration|Choose which of your environments will use this cluster.")
+ - else
+ = text_field_tag :environment_scope, '*', class: 'col-md-6 form-control disabled', placeholder: s_('ClusterIntegration|Environment scope'), disabled: true
+ - environment_scope_url = help_page_path('user/project/clusters/index', anchor: 'base-domain')
+ - environment_scope_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: environment_scope_url }
+ .form-text.text-muted
+ %code *
+ = s_("ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}").html_safe % { environment_scope_start: environment_scope_start, environment_scope_end: '</a>'.html_safe }
+
+ .form-group
+ %h5= s_('ClusterIntegration|Base domain')
+ = field.text_field :base_domain, class: 'col-md-6 form-control js-select-on-focus qa-base-domain'
+ .form-text.text-muted
+ - auto_devops_url = help_page_path('topics/autodevops/index')
+ - auto_devops_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: auto_devops_url }
+ = s_('ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain.').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe }
+ - if @cluster.application_ingress_external_ip.present?
+ = s_('ClusterIntegration|Alternatively')
+ %code #{@cluster.application_ingress_external_ip}.nip.io
+ = s_('ClusterIntegration| can be used instead of a custom domain.')
+ - custom_domain_url = help_page_path('user/project/clusters/index', anchor: 'pointing-your-dns-at-the-cluster-ip')
+ - custom_domain_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: custom_domain_url }
+ = s_('ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}.').html_safe % { custom_domain_start: custom_domain_start, custom_domain_end: '</a>'.html_safe }
+
+ - if can?(current_user, :update_cluster, @cluster)
+ .form-group
+ = field.submit _('Save changes'), class: 'btn btn-success qa-save-domain'
diff --git a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
index 73b11d509d3..a9299af8d78 100644
--- a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
+++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
@@ -1,6 +1,6 @@
- link = link_to(s_('ClusterIntegration|sign up'), 'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral', target: '_blank', rel: 'noopener noreferrer')
-.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert' }
- %button.close{ type: "button", data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } } &times;
+.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert', data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } }
+ %button.close.js-close{ type: "button" } &times;
.gcp-signup-offer--content
.gcp-signup-offer--icon.append-right-8
= sprite_icon("information", size: 16)
@@ -8,5 +8,5 @@
%h4= s_('ClusterIntegration|Did you know?')
%p= s_('ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab\'s Google Kubernetes Engine Integration.').html_safe % { sign_up_link: link }
%a.btn.btn-default{ href: 'https://goo.gl/AaJzRW', target: '_blank', rel: 'noopener noreferrer' }
- Apply for credit
+ = s_("ClusterIntegration|Apply for credit")
diff --git a/app/views/clusters/clusters/_integration_form.html.haml b/app/views/clusters/clusters/_integration_form.html.haml
deleted file mode 100644
index 5e451f60c9d..00000000000
--- a/app/views/clusters/clusters/_integration_form.html.haml
+++ /dev/null
@@ -1,31 +0,0 @@
-= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster do |field|
- = form_errors(@cluster)
- .form-group
- %h5= s_('ClusterIntegration|Integration status')
- %label.append-bottom-0.js-cluster-enable-toggle-area
- %button{ type: 'button',
- class: "js-project-feature-toggle project-feature-toggle #{'is-checked' if @cluster.enabled?} #{'is-disabled' unless can?(current_user, :update_cluster, @cluster)}",
- "aria-label": s_("ClusterIntegration|Toggle Kubernetes cluster"),
- disabled: !can?(current_user, :update_cluster, @cluster) }
- = field.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
- %span.toggle-icon
- = sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
- = sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
- .form-text.text-muted= s_('ClusterIntegration|Enable or disable GitLab\'s connection to your Kubernetes cluster.')
-
- - if has_multiple_clusters?
- .form-group
- %h5= s_('ClusterIntegration|Environment scope')
- = field.text_field :environment_scope, class: 'col-md-6 form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Environment scope')
- .form-text.text-muted= s_("ClusterIntegration|Choose which of your environments will use this cluster.")
-
- - if can?(current_user, :update_cluster, @cluster)
- .form-group
- = field.submit _('Save changes'), class: 'btn btn-success'
-
- - unless has_multiple_clusters?
- %h5= s_('ClusterIntegration|Environment scope')
- %p
- %code *
- is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster.
- = link_to 'More information', ('https://docs.gitlab.com/ee/user/project/clusters/#setting-the-environment-scope')
diff --git a/app/views/clusters/clusters/gcp/_show.html.haml b/app/views/clusters/clusters/gcp/_show.html.haml
deleted file mode 100644
index e9f05eaf453..00000000000
--- a/app/views/clusters/clusters/gcp/_show.html.haml
+++ /dev/null
@@ -1,50 +0,0 @@
-.form-group
- %label.append-bottom-10{ for: 'cluster-name' }
- = s_('ClusterIntegration|Kubernetes cluster name')
- .input-group
- %input.form-control.cluster-name.js-select-on-focus{ value: @cluster.name, readonly: true }
- %span.input-group-append
- = clipboard_button(text: @cluster.name, title: s_('ClusterIntegration|Copy Kubernetes cluster name'), class: 'input-group-text btn-default')
-
-= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster do |field|
- = form_errors(@cluster)
-
- = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
- .form-group
- = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
- .input-group
- = platform_kubernetes_field.text_field :api_url, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|API URL'), readonly: true
- %span.input-group-append
- = clipboard_button(text: @cluster.platform_kubernetes.api_url, title: s_('ClusterIntegration|Copy API URL'), class: 'input-group-text btn-default')
-
- .form-group
- = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate')
- .input-group
- = platform_kubernetes_field.text_area :ca_cert, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'), readonly: true
- %span.input-group-append.clipboard-addon
- = clipboard_button(text: @cluster.platform_kubernetes.ca_cert, title: s_('ClusterIntegration|Copy CA Certificate'), class: 'input-group-text btn-blank')
-
- .form-group
- = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token')
- .input-group
- = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token js-select-on-focus', type: 'password', placeholder: s_('ClusterIntegration|Token'), readonly: true
- %span.input-group-append
- %button.btn.btn-default.input-group-text.js-show-cluster-token{ type: 'button' }
- = s_('ClusterIntegration|Show')
- = clipboard_button(text: @cluster.platform_kubernetes.token, title: s_('ClusterIntegration|Copy Token'), class: 'btn-default')
-
- - if @cluster.allow_user_defined_namespace?
- .form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
- = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
-
- .form-group
- .form-check
- = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
- = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
- .form-text.text-muted
- = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
- = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
-
- .form-group
- = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/clusters/clusters/index.html.haml b/app/views/clusters/clusters/index.html.haml
index 58d0a304363..9bab3bf56aa 100644
--- a/app/views/clusters/clusters/index.html.haml
+++ b/app/views/clusters/clusters/index.html.haml
@@ -1,5 +1,5 @@
-- breadcrumb_title 'Kubernetes'
-- page_title "Kubernetes Clusters"
+- breadcrumb_title _('Kubernetes')
+- page_title _('Kubernetes Clusters')
= render_gcp_signup_offer
@@ -9,12 +9,12 @@
- else
.top-area.adjust
.nav-text
- = s_("ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project")
+ = s_('ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project')
= render 'clusters/clusters/buttons'
- if @has_ancestor_clusters
.bs-callout.bs-callout-info
- = s_("ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters.")
+ = s_('ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters.')
%strong
= link_to _('More information'), help_page_path('user/group/clusters/', anchor: 'cluster-precedence')
diff --git a/app/views/clusters/clusters/new.html.haml b/app/views/clusters/clusters/new.html.haml
index eeeef6bd824..6a8af23e5e8 100644
--- a/app/views/clusters/clusters/new.html.haml
+++ b/app/views/clusters/clusters/new.html.haml
@@ -1,5 +1,5 @@
-- breadcrumb_title 'Kubernetes'
-- page_title _("Kubernetes Cluster")
+- breadcrumb_title _('Kubernetes')
+- page_title _('Kubernetes Cluster')
- active_tab = local_assigns.fetch(:active_tab, 'gcp')
= javascript_include_tag 'https://apis.google.com/js/api.js'
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index b1aa8e5d477..1ef76ef801e 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -1,7 +1,7 @@
- @content_class = "limit-container-width" unless fluid_layout
-- add_to_breadcrumbs "Kubernetes Clusters", clusterable.index_path
+- add_to_breadcrumbs _('Kubernetes Clusters'), clusterable.index_path
- breadcrumb_title @cluster.name
-- page_title _("Kubernetes Cluster")
+- page_title _('Kubernetes Cluster')
- manage_prometheus_path = edit_project_service_path(@cluster.project, 'prometheus') if @project
- expanded = Rails.env.test?
@@ -16,6 +16,7 @@
install_jupyter_path: clusterable.install_applications_cluster_path(@cluster, :jupyter),
install_knative_path: clusterable.install_applications_cluster_path(@cluster, :knative),
toggle_status: @cluster.enabled? ? 'true': 'false',
+ has_rbac: @cluster.platform_kubernetes_rbac? ? 'true': 'false',
cluster_type: @cluster.cluster_type,
cluster_status: @cluster.status_name,
cluster_status_reason: @cluster.status_reason,
@@ -30,7 +31,7 @@
%section#cluster-integration
%h4= @cluster.name
= render 'banner'
- = render 'integration_form'
+ = render 'form'
.cluster-applications-table#js-cluster-applications
@@ -38,19 +39,16 @@
.settings-header
%h4= s_('ClusterIntegration|Kubernetes cluster details')
%button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? 'Collapse' : 'Expand'
+ = expanded ? _('Collapse') : _('Expand')
%p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster')
.settings-content
- - if @cluster.managed?
- = render 'clusters/clusters/gcp/show'
- - else
- = render 'clusters/clusters/user/show'
+ = render 'clusters/platforms/kubernetes/form', cluster: @cluster, platform: @cluster.platform_kubernetes, update_cluster_url_path: clusterable.cluster_path(@cluster)
%section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
%h4= _('Advanced settings')
%button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? 'Collapse' : 'Expand'
+ = expanded ? _('Collapse') : _('Expand')
%p= s_("ClusterIntegration|Advanced options on this Kubernetes cluster's integration")
.settings-content
= render 'advanced_settings'
diff --git a/app/views/clusters/clusters/user/_show.html.haml b/app/views/clusters/clusters/user/_show.html.haml
deleted file mode 100644
index cac8e72edd3..00000000000
--- a/app/views/clusters/clusters/user/_show.html.haml
+++ /dev/null
@@ -1,39 +0,0 @@
-= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster do |field|
- = form_errors(@cluster)
- .form-group
- = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
- = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
-
- = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
- .form-group
- = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-bold'
- = platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
-
- .form-group
- = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-bold'
- = platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
-
- .form-group
- = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-bold'
- .input-group
- = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token', type: 'password', placeholder: s_('ClusterIntegration|Token'), autocomplete: 'off'
- %span.input-group-append.clipboard-addon
- .input-group-text
- %button.js-show-cluster-token.btn-blank{ type: 'button' }
- = s_('ClusterIntegration|Show')
-
- - if @cluster.allow_user_defined_namespace?
- .form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-bold'
- = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
-
- .form-group
- .form-check
- = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
- = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
- .form-text.text-muted
- = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
- = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
-
- .form-group
- = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/clusters/platforms/kubernetes/_form.html.haml b/app/views/clusters/platforms/kubernetes/_form.html.haml
new file mode 100644
index 00000000000..4a452b83112
--- /dev/null
+++ b/app/views/clusters/platforms/kubernetes/_form.html.haml
@@ -0,0 +1,58 @@
+= form_for cluster, url: update_cluster_url_path, as: :cluster do |field|
+ = form_errors(cluster)
+
+ .form-group
+ - if cluster.managed?
+ %label.append-bottom-10{ for: 'cluster-name' }
+ = s_('ClusterIntegration|Kubernetes cluster name')
+ .input-group
+ %input.form-control.cluster-name.js-select-on-focus{ value: cluster.name, readonly: true }
+ %span.input-group-append
+ = clipboard_button(text: cluster.name, title: s_('ClusterIntegration|Copy Kubernetes cluster name'), class: 'input-group-text btn-default')
+ - else
+ = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
+ .input-group
+ = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
+
+ = field.fields_for :platform_kubernetes, platform do |platform_field|
+ .form-group
+ = platform_field.label :api_url, s_('ClusterIntegration|API URL')
+ .input-group
+ = platform_field.text_field :api_url, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|API URL'), readonly: cluster.managed?
+ - if cluster.managed?
+ %span.input-group-append
+ = clipboard_button(text: platform.api_url, title: s_('ClusterIntegration|Copy API URL'), class: 'input-group-text btn-default')
+
+ .form-group
+ = platform_field.label :ca_cert, s_('ClusterIntegration|CA Certificate')
+ .input-group
+ = platform_field.text_area :ca_cert, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'), readonly: cluster.managed?
+ - if cluster.managed?
+ %span.input-group-append.clipboard-addon
+ = clipboard_button(text: platform.ca_cert, title: s_('ClusterIntegration|Copy CA Certificate'), class: 'input-group-text btn-blank')
+
+ .form-group
+ = platform_field.label :token, s_('ClusterIntegration|Token')
+ .input-group
+ = platform_field.text_field :token, class: 'form-control js-cluster-token js-select-on-focus', type: 'password', placeholder: s_('ClusterIntegration|Token'), readonly: cluster.managed?
+ %span.input-group-append
+ %button.btn.btn-default.input-group-text.js-show-cluster-token{ type: 'button' }
+ = s_('ClusterIntegration|Show')
+ - if cluster.managed?
+ = clipboard_button(text: platform.token, title: s_('ClusterIntegration|Copy Token'), class: 'btn-default')
+
+ - if cluster.allow_user_defined_namespace?
+ .form-group
+ = platform_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
+ = platform_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
+
+ .form-group
+ .form-check
+ = platform_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
+ = platform_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
+ .form-text.text-muted
+ = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
+ = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/dashboard/_activities.html.haml b/app/views/dashboard/_activities.html.haml
index 9c246e19faa..4359a2c3c2b 100644
--- a/app/views/dashboard/_activities.html.haml
+++ b/app/views/dashboard/_activities.html.haml
@@ -1,7 +1,7 @@
.nav-block.activities
= render 'shared/event_filter'
.controls
- = link_to dashboard_projects_path(rss_url_options), class: 'btn rss-btn has-tooltip', title: 'Subscribe' do
+ = link_to dashboard_projects_path(rss_url_options), class: 'btn d-none d-sm-inline-block has-tooltip', title: 'Subscribe' do
%i.fa.fa-rss
.content_list
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index 1050945b15a..ae67192cbcd 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -15,9 +15,11 @@
= nav_link(page: [dashboard_projects_path, root_path]) do
= link_to dashboard_projects_path, class: 'shortcuts-activity', data: {placement: 'right'} do
Your projects
+ %span.badge.badge-pill= limited_counter_with_delimiter(@total_user_projects_count)
= nav_link(page: starred_dashboard_projects_path) do
= link_to starred_dashboard_projects_path, data: {placement: 'right'} do
Starred projects
+ %span.badge.badge-pill= limited_counter_with_delimiter(@total_starred_projects_count)
= nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path]) do
= link_to explore_root_path, data: {placement: 'right'} do
Explore projects
diff --git a/app/views/dashboard/_snippets_head.html.haml b/app/views/dashboard/_snippets_head.html.haml
index 8d99f84755a..a05d0190efb 100644
--- a/app/views/dashboard/_snippets_head.html.haml
+++ b/app/views/dashboard/_snippets_head.html.haml
@@ -1,9 +1,9 @@
.page-title-holder
%h1.page-title= _('Snippets')
- - if current_user
+ - if current_user && current_user.snippets.any? || @snippets.any?
.page-title-controls
- = link_to "New snippet", new_snippet_path, class: "btn btn-success", title: "New snippet"
+ = link_to _("New snippet"), new_snippet_path, class: "btn btn-success", title: _("New snippet")
.top-area
%ul.nav-links.nav.nav-tabs
diff --git a/app/views/dashboard/activity.html.haml b/app/views/dashboard/activity.html.haml
index 31d4b3da4f1..4dbda5c754b 100644
--- a/app/views/dashboard/activity.html.haml
+++ b/app/views/dashboard/activity.html.haml
@@ -4,6 +4,9 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
+
+= render_if_exists "shared/gold_trial_callout"
+
- page_title "Activity"
- header_title "Activity", activity_dashboard_path
diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml
index 50f39f93283..19b06ba5cdd 100644
--- a/app/views/dashboard/groups/index.html.haml
+++ b/app/views/dashboard/groups/index.html.haml
@@ -1,6 +1,8 @@
- @hide_top_links = true
- page_title "Groups"
-- header_title "Groups", dashboard_groups_path
+- header_title "Groups", dashboard_groups_path
+
+= render_if_exists "shared/gold_trial_callout"
= render 'dashboard/groups_head'
- if params[:filter].blank? && @groups.empty?
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index fdd5c19d562..afd46412fab 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -4,6 +4,8 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{current_user.name} issues")
+= render_if_exists "shared/gold_trial_callout"
+
.page-title-holder
%h1.page-title= _('Issues')
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index 77cfa1271df..3e5f13b92e3 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -2,6 +2,8 @@
- page_title _("Merge Requests")
- @breadcrumb_link = merge_requests_dashboard_path(assignee_username: current_user.username)
+= render_if_exists "shared/gold_trial_callout"
+
.page-title-holder
%h1.page-title= _('Merge Requests')
diff --git a/app/views/dashboard/milestones/_milestone.html.haml b/app/views/dashboard/milestones/_milestone.html.haml
index b876d6fd1f3..89212eb6bf9 100644
--- a/app/views/dashboard/milestones/_milestone.html.haml
+++ b/app/views/dashboard/milestones/_milestone.html.haml
@@ -1,5 +1,5 @@
= render 'shared/milestones/milestone',
- milestone_path: group_or_dashboard_milestone_path(milestone),
+ milestone_path: group_or_project_milestone_path(milestone),
issues_path: issues_dashboard_path(milestone_title: milestone.title),
merge_requests_path: merge_requests_dashboard_path(milestone_title: milestone.title),
milestone: milestone,
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index ae0e38bf0ee..13822d36f15 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -13,6 +13,8 @@
.top-area
= render 'shared/milestones_filter', counts: @milestone_states
+ .nav-controls
+ = render 'shared/milestones/search_form'
.milestones
%ul.content-list
diff --git a/app/views/dashboard/projects/_starred_empty_state.html.haml b/app/views/dashboard/projects/_starred_empty_state.html.haml
new file mode 100644
index 00000000000..bea27f1a456
--- /dev/null
+++ b/app/views/dashboard/projects/_starred_empty_state.html.haml
@@ -0,0 +1,9 @@
+.row.empty-state
+ .col-12
+ .svg-content.svg-250
+ = image_tag 'illustrations/starred_empty.svg'
+ .text-content
+ %h4.text-center
+ = s_("StarredProjectsEmptyState|You don't have starred projects yet.")
+ %p.text-secondary
+ = s_("StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page.")
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index deed774a4a5..446b4715b2d 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -4,6 +4,8 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
+= render_if_exists "shared/gold_trial_callout"
+
- page_title "Projects"
- header_title "Projects", dashboard_projects_path
diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml
index 8933d9e31ff..3a45f6df017 100644
--- a/app/views/dashboard/projects/starred.html.haml
+++ b/app/views/dashboard/projects/starred.html.haml
@@ -1,8 +1,10 @@
- @hide_top_links = true
- @no_container = true
-- breadcrumb_title "Projects"
-- page_title "Starred Projects"
-- header_title "Projects", dashboard_projects_path
+- breadcrumb_title _("Projects")
+- page_title _("Starred Projects")
+- header_title _("Projects"), dashboard_projects_path
+
+= render_if_exists "shared/gold_trial_callout"
%div{ class: container_class }
= render "projects/last_push"
@@ -11,5 +13,4 @@
- if params[:filter_projects] || any_projects?(@projects)
= render 'projects'
- else
- %h3.page-title You don't have starred projects yet
- %p.slead Visit project page and press on star icon and it will appear on this page.
+ = render 'starred_empty_state'
diff --git a/app/views/dashboard/snippets/index.html.haml b/app/views/dashboard/snippets/index.html.haml
index 6eb067da95c..b649fe91c24 100644
--- a/app/views/dashboard/snippets/index.html.haml
+++ b/app/views/dashboard/snippets/index.html.haml
@@ -3,6 +3,14 @@
- header_title "Snippets", dashboard_snippets_path
= render 'dashboard/snippets_head'
-= render partial: 'snippets/snippets_scope_menu', locals: { include_private: true }
+- if current_user.snippets.exists?
+ = render partial: 'snippets/snippets_scope_menu', locals: { include_private: true }
-= render partial: 'snippets/snippets', locals: { link_project: true }
+.d-block.d-sm-none
+ &nbsp;
+ = link_to _("New snippet"), new_snippet_path, class: "btn btn-success btn-block", title: _("New snippet")
+
+- if current_user.snippets.exists?
+ = render partial: 'shared/snippets/list', locals: { link_project: true }
+- else
+ = render 'shared/empty_states/snippets', button_path: new_snippet_path
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index d2593179f17..47729321961 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -2,6 +2,8 @@
- page_title "Todos"
- header_title "Todos", dashboard_todos_path
+= render_if_exists "shared/gold_trial_callout"
+
.page-title-holder
%h1.page-title= _('Todos')
diff --git a/app/views/devise/mailer/_confirmation_instructions_secondary.html.haml b/app/views/devise/mailer/_confirmation_instructions_secondary.html.haml
index 3d0a1f622a5..ccc3e734276 100644
--- a/app/views/devise/mailer/_confirmation_instructions_secondary.html.haml
+++ b/app/views/devise/mailer/_confirmation_instructions_secondary.html.haml
@@ -1,5 +1,5 @@
#content
- = email_default_heading("#{@resource.user.name}, you've added an additional email!")
+ = email_default_heading("#{sanitize_name(@resource.user.name)}, you've added an additional email!")
%p Click the link below to confirm your email address (#{@resource.email})
#cta
= link_to 'Confirm your email address', confirmation_url(@resource, confirmation_token: @token)
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index 4b8ad5acd5b..dd1edb5fdc9 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -7,7 +7,7 @@
= f.hidden_field :reset_password_token
.form-group
= f.label 'New password', for: "user_password"
- = f.password_field :password, class: "form-control top qa-password-field", required: true, title: 'This field is required'
+ = f.password_field :password, class: "form-control top qa-password-field", required: true, title: 'This field is required'
.form-group
= f.label 'Confirm new password', for: "user_password_confirmation"
= f.password_field :password_confirmation, class: "form-control bottom qa-password-confirmation", title: 'This field is required', required: true
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 796c0cadda8..f856773526d 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -1,3 +1,5 @@
+- server = local_assigns.fetch(:server)
+
= form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user', class: "gl-show-field-errors") do
.form-group
= label_tag :username, "#{server['label']} Username"
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 34d4293bd45..30ed7ed6b29 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,6 +1,6 @@
- page_title "Sign in"
-%div
+#signin-container
- if form_based_providers.any?
= render 'devise/shared/tabs_ldap'
- else
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index fefdf5f9531..f49cdfbf8da 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -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
= f.text_field :otp_attempt, class: 'form-control', required: true, autofocus: true, autocomplete: 'off', title: 'This field is required.'
%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/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 12271ee5adb..1b583ea85d6 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -5,7 +5,7 @@
.d-flex.justify-content-between.flex-wrap
- providers.each do |provider|
- has_icon = provider_has_icon?(provider)
- = link_to omniauth_authorize_path(:user, provider), method: :post, class: 'btn d-flex align-items-center omniauth-btn text-left oauth-login qa-saml-login-button', id: "oauth-login-#{provider}" do
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn d-flex align-items-center omniauth-btn text-left oauth-login #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
- if has_icon
= provider_image_tag(provider)
%span
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 004a3528d4b..9c7ca6ebbd4 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -3,12 +3,12 @@
= form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f|
.devise-errors
= devise_error_messages!
- .form-group
+ .name.form-group
= f.label :name, 'Full name', class: 'label-bold'
- = f.text_field :name, class: "form-control top qa-new-user-name", required: true, title: "This field is required."
+ = f.text_field :name, class: "form-control top qa-new-user-name js-block-emoji", required: true, title: _("This field is required.")
.username.form-group
= f.label :username, class: 'label-bold'
- = f.text_field :username, class: "form-control middle qa-new-user-username", pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: 'Please create a username with only alphanumeric characters.'
+ = f.text_field :username, class: "form-control middle qa-new-user-username js-block-emoji", pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
%p.validation-error.hide Username is already taken.
%p.validation-success.hide Username is available.
%p.validation-pending.hide Checking username availability...
diff --git a/app/views/doorkeeper/authorizations/new.html.haml b/app/views/doorkeeper/authorizations/new.html.haml
index 74791b81ccd..dae9a7acf6b 100644
--- a/app/views/doorkeeper/authorizations/new.html.haml
+++ b/app/views/doorkeeper/authorizations/new.html.haml
@@ -31,7 +31,7 @@
%strong= t scope, scope: [:doorkeeper, :scopes]
.text-secondary= t scope, scope: [:doorkeeper, :scope_desc]
.form-actions.text-right
- = form_tag oauth_authorization_path, method: :delete, class: 'inline' do
+ = form_tag oauth_authorization_path, method: :delete, class: 'inline' do
= hidden_field_tag :client_id, @pre_auth.client.uid
= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
= hidden_field_tag :state, @pre_auth.state
diff --git a/app/views/email_rejection_mailer/rejection.html.haml b/app/views/email_rejection_mailer/rejection.html.haml
index c4ae7befe4e..666dab61f40 100644
--- a/app/views/email_rejection_mailer/rejection.html.haml
+++ b/app/views/email_rejection_mailer/rejection.html.haml
@@ -1,5 +1,5 @@
%p
- Unfortunately, your email message to GitLab could not be processed.
+ = _("Unfortunately, your email message to GitLab could not be processed.")
= markdown @reason
= render_if_exists 'shared/additional_email_text'
diff --git a/app/views/email_rejection_mailer/rejection.text.haml b/app/views/email_rejection_mailer/rejection.text.haml
index 0e13b2a6473..8d940ef1293 100644
--- a/app/views/email_rejection_mailer/rejection.text.haml
+++ b/app/views/email_rejection_mailer/rejection.text.haml
@@ -1,4 +1,4 @@
-Unfortunately, your email message to GitLab could not be processed.
+= _("Unfortunately, your email message to GitLab could not be processed.")
\
= @reason
= render_if_exists 'shared/additional_email_text'
diff --git a/app/views/events/_events.html.haml b/app/views/events/_events.html.haml
index 68c19df092d..e1b7804c5a7 100644
--- a/app/views/events/_events.html.haml
+++ b/app/views/events/_events.html.haml
@@ -1 +1,18 @@
-= render partial: 'events/event', collection: @events
+- illustration_path = 'illustrations/profile-page/activity.svg'
+- current_user_empty_message_header = s_('UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!')
+- primary_button_label = _('New group')
+- primary_button_link = new_group_path
+- secondary_button_label = _('Explore groups')
+- secondary_button_link = explore_groups_path
+- visitor_empty_message = _('No activities found')
+
+- if @events.present?
+ = render partial: 'events/event', collection: @events
+- else
+ = render partial: 'shared/empty_states/profile_tabs', locals: { illustration_path: illustration_path,
+ current_user_empty_message_header: current_user_empty_message_header,
+ primary_button_label: primary_button_label,
+ primary_button_link: primary_button_link,
+ secondary_button_label: secondary_button_label,
+ secondary_button_link: secondary_button_link,
+ visitor_empty_message: visitor_empty_message }
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index fb0d2c3b8b0..90ed8e41d32 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -21,6 +21,6 @@
= link_to note.attachment.url, target: '_blank' do
= image_tag note.attachment.url, class: 'note-image-attach'
- else
- = link_to note.attachment.url, target: '_blank', class: 'note-file-attach' do
+ = link_to note.attachment.url, target: '_blank', class: 'note-file-attach' do
%i.fa.fa-paperclip
= note.attachment_identifier
diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml
index a3eafc61d0a..869be4e8581 100644
--- a/app/views/explore/groups/index.html.haml
+++ b/app/views/explore/groups/index.html.haml
@@ -2,6 +2,8 @@
- page_title _("Groups")
- header_title _("Groups"), dashboard_groups_path
+= render_if_exists "shared/gold_trial_callout"
+
- if current_user
= render 'dashboard/groups_head'
- else
diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml
index 452f390695c..d18dec7bd8e 100644
--- a/app/views/explore/projects/index.html.haml
+++ b/app/views/explore/projects/index.html.haml
@@ -2,6 +2,8 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
+= render_if_exists "shared/gold_trial_callout"
+
- if current_user
= render 'dashboard/projects_head'
- else
diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml
index 452f390695c..d18dec7bd8e 100644
--- a/app/views/explore/projects/starred.html.haml
+++ b/app/views/explore/projects/starred.html.haml
@@ -2,6 +2,8 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
+= render_if_exists "shared/gold_trial_callout"
+
- if current_user
= render 'dashboard/projects_head'
- else
diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml
index 452f390695c..d18dec7bd8e 100644
--- a/app/views/explore/projects/trending.html.haml
+++ b/app/views/explore/projects/trending.html.haml
@@ -2,6 +2,8 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
+= render_if_exists "shared/gold_trial_callout"
+
- if current_user
= render 'dashboard/projects_head'
- else
diff --git a/app/views/explore/snippets/index.html.haml b/app/views/explore/snippets/index.html.haml
index 94fc4ac21d2..d23c8301b10 100644
--- a/app/views/explore/snippets/index.html.haml
+++ b/app/views/explore/snippets/index.html.haml
@@ -7,4 +7,4 @@
- else
= render 'explore/head'
-= render partial: 'snippets/snippets', locals: { link_project: true }
+= render partial: 'shared/snippets/list', locals: { link_project: true }
diff --git a/app/views/groups/_activities.html.haml b/app/views/groups/_activities.html.haml
index 82a497289f3..13df1e57125 100644
--- a/app/views/groups/_activities.html.haml
+++ b/app/views/groups/_activities.html.haml
@@ -1,7 +1,7 @@
.nav-block.activities
= render 'shared/event_filter'
.controls
- = link_to group_path(@group, rss_url_options), class: 'btn rss-btn has-tooltip' , title: 'Subscribe' do
+ = link_to group_path(@group, rss_url_options), class: 'btn d-none d-sm-inline-block has-tooltip' , title: 'Subscribe' do
%i.fa.fa-rss
.content_list
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index 6219da2c715..39c0c113793 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -1,17 +1,58 @@
-.group-home-panel.text-center.border-bottom
- %div{ class: container_class }
- .avatar-container.s70.group-avatar
- = group_icon(@group, class: "avatar s70 avatar-tile")
- %h1.group-title
- = @group.name
- %span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
- = visibility_level_icon(@group.visibility_level, fw: false)
+- can_create_subgroups = can?(current_user, :create_subgroup, @group)
- - if @group.description.present?
- .group-home-desc
- = markdown_field(@group, :description)
+.group-home-panel
+ .row.mb-3
+ .home-panel-title-row.col-md-12.col-lg-6.d-flex
+ .avatar-container.rect-avatar.s64.home-panel-avatar.append-right-default.float-none
+ = group_icon(@group, class: 'avatar avatar-tile s64', width: 64, height: 64)
+ .d-flex.flex-column.flex-wrap.align-items-baseline
+ .d-inline-flex.align-items-baseline
+ %h1.home-panel-title.prepend-top-8.append-bottom-5
+ = @group.name
+ %span.visibility-icon.text-secondary.prepend-left-4.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
+ = visibility_level_icon(@group.visibility_level, fw: false, options: {class: 'icon'})
+ .home-panel-metadata.d-flex.align-items-center.text-secondary
+ %span
+ = _("Group")
+ - if current_user
+ %span.access-request-links.prepend-left-8
+ = render 'shared/members/access_request_links', source: @group
- - if current_user
- .group-buttons
- = render 'shared/members/access_request_buttons', source: @group
- = render 'shared/notifications/button', notification_setting: @notification_setting
+ .home-panel-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end
+ - if current_user
+ .group-buttons
+ = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn'
+ - if can? current_user, :create_projects, @group
+ - new_project_label = _("New project")
+ - new_subgroup_label = _("New subgroup")
+ - if can_create_subgroups
+ .btn-group.new-project-subgroup.droplab-dropdown.home-panel-action-button.prepend-top-default.js-new-project-subgroup.qa-new-project-or-subgroup-dropdown{ data: { project_path: new_project_path(namespace_id: @group.id), subgroup_path: new_group_path(parent_id: @group.id) } }
+ %input.btn.btn-success.dropdown-primary.js-new-group-child.qa-new-in-group-button{ type: "button", value: new_project_label, data: { action: "new-project" } }
+ %button.btn.btn-success.dropdown-toggle.js-dropdown-toggle.qa-new-project-or-subgroup-dropdown-toggle{ type: "button", data: { "dropdown-trigger" => "#new-project-or-subgroup-dropdown", 'display' => 'static' } }
+ = sprite_icon("arrow-down", css_class: "icon dropdown-btn-icon")
+ %ul#new-project-or-subgroup-dropdown.dropdown-menu.dropdown-menu-right{ data: { dropdown: true } }
+ %li.droplab-item-selected.qa-new-project-option{ role: "button", data: { value: "new-project", text: new_project_label } }
+ .menu-item
+ .icon-container
+ = icon("check", class: "list-item-checkmark")
+ .description
+ %strong= new_project_label
+ %span= s_("GroupsTree|Create a project in this group.")
+ %li.divider.droplap-item-ignore
+ %li.qa-new-subgroup-option{ role: "button", data: { value: "new-subgroup", text: new_subgroup_label } }
+ .menu-item
+ .icon-container
+ = icon("check", class: "list-item-checkmark")
+ .description
+ %strong= new_subgroup_label
+ %span= s_("GroupsTree|Create a subgroup in this group.")
+ - else
+ = link_to new_project_label, new_project_path(namespace_id: @group.id), class: "btn btn-success"
+
+ - if @group.description.present?
+ .group-home-desc.mt-1
+ .home-panel-description
+ .home-panel-description-markdown.read-more-container
+ = markdown_field(@group, :description)
+ %button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
+ = _("Read more")
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 13d584f5f1d..2af3e861587 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -23,7 +23,7 @@
Members with access to
%strong= @group.name
%span.badge= @members.total_count
- = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form flex-project-members-form' do
+ = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form flex-project-members-form' do
.form-group
.position-relative.append-right-8
= search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false }
diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml
index 4df3d831942..5cf3193bc62 100644
--- a/app/views/groups/labels/index.html.haml
+++ b/app/views/groups/labels/index.html.haml
@@ -6,15 +6,10 @@
- subscribed = params[:subscribed]
- labels_or_filters = @labels.exists? || search.present? || subscribed.present?
-- if @labels.present? && can_admin_label
- - content_for(:header_content) do
- .nav-controls
- = link_to _('New label'), new_group_label_path(@group), class: "btn btn-success"
-
- if labels_or_filters
#promote-label-modal
%div{ class: container_class }
- = render 'shared/labels/nav'
+ = render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label
.labels-container.prepend-top-5
- if @labels.any?
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index a9ce2fe5ab0..808bb1309b1 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -7,7 +7,7 @@
= render 'shared/issuable/nav', type: :merge_requests
- if current_user
.nav-controls
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests, with_feature_enabled: 'merge_requests', with_shared: false, include_projects_in_subgroups: true
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests, with_feature_enabled: 'merge_requests', with_shared: false, include_projects_in_subgroups: true
= render 'shared/issuable/search_bar', type: :merge_requests
diff --git a/app/views/groups/milestones/_form.html.haml b/app/views/groups/milestones/_form.html.haml
index 39e3af5f6d2..b0ba846f204 100644
--- a/app/views/groups/milestones/_form.html.haml
+++ b/app/views/groups/milestones/_form.html.haml
@@ -1,20 +1,20 @@
-= form_for [@group, @milestone], html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
+= form_for [@group, @milestone], html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
+ = form_errors(@milestone)
.row
- = form_errors(@milestone)
-
.col-md-6
.form-group.row
- = f.label :title, "Title", class: "col-form-label col-sm-2"
+ .col-form-label.col-sm-2
+ = f.label :title, "Title"
.col-sm-10
= f.text_field :title, maxlength: 255, class: "form-control", required: true, autofocus: true
.form-group.row.milestone-description
- = f.label :description, "Description", class: "col-form-label col-sm-2"
+ .col-form-label.col-sm-2
+ = f.label :description, "Description"
.col-sm-10
= render layout: 'projects/md_preview', locals: { url: group_preview_markdown_path } do
= render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: 'Write milestone description...', supports_autocomplete: false
- .clearfix
- .error-alert
-
+ .clearfix
+ .error-alert
= render "shared/milestones/form_dates", f: f
.form-actions
@@ -24,4 +24,3 @@
- else
= f.submit 'Update milestone', class: "btn-success btn"
= link_to "Cancel", group_milestone_path(@group, @milestone), class: "btn btn-cancel"
-
diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml
index af4fe8f2ef8..b6fb908c8f6 100644
--- a/app/views/groups/milestones/index.html.haml
+++ b/app/views/groups/milestones/index.html.haml
@@ -4,6 +4,7 @@
= render 'shared/milestones_filter', counts: @milestone_states
.nav-controls
+ = render 'shared/milestones/search_form'
= render 'shared/milestones_sort_dropdown'
- if can?(current_user, :admin_milestone, @group)
= link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-success"
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index bcfb6d99716..806a24e2bbc 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -21,6 +21,6 @@
- else
%h4.underlined-title
- = _('Available group Runners : %{runners}.').html_safe % { runners: @group.runners.count }
+ = _('Available group Runners: %{runners}').html_safe % { runners: @group.runners.count }
%ul.bordered-list
= render partial: 'groups/runners/runner', collection: @group.runners, as: :runner
diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml
index 0424ece037d..9ed71d19d32 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -20,7 +20,7 @@
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
.form-group.prepend-top-default.append-bottom-20
- .avatar-container.s90
+ .avatar-container.rect-avatar.s90
= group_icon(@group, alt: '', class: 'avatar group-avatar s90')
= f.label :avatar, _('Group avatar'), class: 'label-bold d-block'
= render 'shared/choose_group_avatar_button', f: f
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index cc294f6a931..77fe88dacb7 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -1,66 +1,41 @@
- @no_container = true
- breadcrumb_title _("Details")
-- can_create_subgroups = can?(current_user, :create_subgroup, @group)
+- @content_class = "limit-container-width" unless fluid_layout
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
-= render 'groups/home_panel'
-
-.groups-listing{ class: container_class, data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
- .top-area.group-nav-container
- .group-search
- = render "shared/groups/search_form"
- - if can? current_user, :create_projects, @group
- - new_project_label = _("New project")
- - new_subgroup_label = _("New subgroup")
- - if can_create_subgroups
- .btn-group.new-project-subgroup.droplab-dropdown.js-new-project-subgroup.qa-new-project-or-subgroup-dropdown{ data: { project_path: new_project_path(namespace_id: @group.id), subgroup_path: new_group_path(parent_id: @group.id) } }
- %input.btn.btn-success.dropdown-primary.js-new-group-child.qa-new-in-group-button{ type: "button", value: new_project_label, data: { action: "new-project" } }
- %button.btn.btn-success.dropdown-toggle.js-dropdown-toggle.qa-new-project-or-subgroup-dropdown-toggle{ type: "button", data: { "dropdown-trigger" => "#new-project-or-subgroup-dropdown", 'display' => 'static' } }
- = icon("caret-down", class: "dropdown-btn-icon")
- %ul#new-project-or-subgroup-dropdown.dropdown-menu.dropdown-menu-right{ data: { dropdown: true } }
- %li.droplab-item-selected.qa-new-project-option{ role: "button", data: { value: "new-project", text: new_project_label } }
- .menu-item
- .icon-container
- = icon("check", class: "list-item-checkmark")
- .description
- %strong= new_project_label
- %span= s_("GroupsTree|Create a project in this group.")
- %li.divider.droplap-item-ignore
- %li.qa-new-subgroup-option{ role: "button", data: { value: "new-subgroup", text: new_subgroup_label } }
- .menu-item
- .icon-container
- = icon("check", class: "list-item-checkmark")
- .description
- %strong= new_subgroup_label
- %span= s_("GroupsTree|Create a subgroup in this group.")
- - else
- = link_to new_project_label, new_project_path(namespace_id: @group.id), class: "btn btn-success"
-
- .scrolling-tabs-container.inner-page-scroll-tabs
- .fade-left= icon('angle-left')
- .fade-right= icon('angle-right')
- %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
- %li.js-subgroups_and_projects-tab
- = link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do
- = _("Subgroups and projects")
- %li.js-shared-tab
- = link_to group_shared_path, data: { target: 'div#shared', action: 'shared', toggle: 'tab'} do
- = _("Shared projects")
- %li.js-archived-tab
- = link_to group_archived_path, data: { target: 'div#archived', action: 'archived', toggle: 'tab'} do
- = _("Archived projects")
-
- .nav-controls
- = render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
-
- .tab-content
- #subgroups_and_projects.tab-pane
- = render "subgroups_and_projects", group: @group
-
- #shared.tab-pane
- = render "shared_projects", group: @group
-
- #archived.tab-pane
- = render "archived_projects", group: @group
+%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
+ = render 'groups/home_panel'
+
+ .groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
+ .top-area.group-nav-container
+ .scrolling-tabs-container.inner-page-scroll-tabs
+ .fade-left= icon('angle-left')
+ .fade-right= icon('angle-right')
+ %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
+ %li.js-subgroups_and_projects-tab
+ = link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do
+ = _("Subgroups and projects")
+ %li.js-shared-tab
+ = link_to group_shared_path, data: { target: 'div#shared', action: 'shared', toggle: 'tab'} do
+ = _("Shared projects")
+ %li.js-archived-tab
+ = link_to group_archived_path, data: { target: 'div#archived', action: 'archived', toggle: 'tab'} do
+ = _("Archived projects")
+
+ .nav-controls.d-block.d-md-flex
+ .group-search
+ = render "shared/groups/search_form"
+
+ = render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
+
+ .tab-content
+ #subgroups_and_projects.tab-pane
+ = render "subgroups_and_projects", group: @group
+
+ #shared.tab-pane
+ = render "shared_projects", group: @group
+
+ #archived.tab-pane
+ = render "archived_projects", group: @group
diff --git a/app/views/help/_shortcuts.html.haml b/app/views/help/_shortcuts.html.haml
index 28ffb2dd63c..efb3815b257 100644
--- a/app/views/help/_shortcuts.html.haml
+++ b/app/views/help/_shortcuts.html.haml
@@ -356,6 +356,18 @@
%td.shortcut
%kbd l
%td Change Label
+ %tr
+ %td.shortcut
+ %kbd ]
+ \/
+ %kbd j
+ %td Move to next file
+ %tr
+ %td.shortcut
+ %kbd [
+ \/
+ %kbd k
+ %td Move to previous file
%tbody.hidden-shortcut{ style: 'display:none' }
%tr
%th
diff --git a/app/views/ide/_show.html.haml b/app/views/ide/_show.html.haml
index b24d6e27536..057225d021f 100644
--- a/app/views/ide/_show.html.haml
+++ b/app/views/ide/_show.html.haml
@@ -4,7 +4,7 @@
- content_for :page_specific_javascripts do
= stylesheet_link_tag 'page_bundles/ide'
-#ide.ide-loading{ data: ide_data() }
+#ide.ide-loading{ data: ide_data }
.text-center
= icon('spinner spin 2x')
%h2.clgray= _('Loading the GitLab IDE...')
diff --git a/app/views/import/_githubish_status.html.haml b/app/views/import/_githubish_status.html.haml
index f4a29ed18dc..b05c039c85c 100644
--- a/app/views/import/_githubish_status.html.haml
+++ b/app/views/import/_githubish_status.html.haml
@@ -1,56 +1,9 @@
- provider = local_assigns.fetch(:provider)
- provider_title = Gitlab::ImportSources.title(provider)
-%p.light
- = import_githubish_choose_repository_message
-%hr
-%p
- = button_tag class: "btn btn-import btn-success js-import-all" do
- = import_all_githubish_repositories_button_label
- = icon("spinner spin", class: "loading-icon")
-
-.table-responsive
- %table.table.import-jobs
- %colgroup.import-jobs-from-col
- %colgroup.import-jobs-to-col
- %colgroup.import-jobs-status-col
- %thead
- %tr
- %th= _('From %{provider_title}') % { provider_title: provider_title }
- %th= _('To GitLab')
- %th= _('Status')
- %tbody
- - @already_added_projects.each do |project|
- %tr{ id: "project_#{project.id}", class: project_status_css_class(project.import_status) }
- %td
- = provider_project_link(provider, project.import_source)
- %td
- = link_to project.full_path, [project.namespace.becomes(Namespace), project]
- %td.job-status
- = render 'import/project_status', project: project
-
- - @repos.each do |repo|
- %tr{ id: "repo_#{repo.id}", data: { qa: { repo_path: repo.full_name } } }
- %td
- = provider_project_link(provider, repo.full_name)
- %td.import-target
- %fieldset.row
- .input-group
- .project-path.input-group-prepend
- - if current_user.can_select_namespace?
- - selected = params[:namespace_id] || :current_user
- - opts = current_user.can_create_group? ? { extra_group: Group.new(name: repo.owner.login, path: repo.owner.login) } : {}
- = select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'input-group-text select2 js-select-namespace qa-project-namespace-select', tabindex: 1 }
- - else
- = text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true
- %span.input-group-prepend
- .input-group-text /
- = text_field_tag :path, sanitize_project_name(repo.name), class: "input-mini form-control", tabindex: 2, autofocus: true, required: true
- %td.import-actions.job-status
- = button_tag class: "btn btn-import js-add-to-import" do
- = has_ci_cd_only_params? ? _('Connect') : _('Import')
- = icon("spinner spin", class: "loading-icon")
-
-.js-importer-status{ data: { jobs_import_path: url_for([:jobs, :import, provider]),
- import_path: url_for([:import, provider]),
- ci_cd_only: has_ci_cd_only_params?.to_s } }
+#import-projects-mount-element{ data: { provider: provider, provider_title: provider_title,
+ can_select_namespace: current_user.can_select_namespace?.to_s,
+ ci_cd_only: has_ci_cd_only_params?.to_s,
+ repos_path: url_for([:status, :import, provider, format: :json]),
+ jobs_path: url_for([:realtime_changes, :import, provider, format: :json]),
+ import_path: url_for([:import, provider, format: :json]) } }
diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml
index ef69197e453..9280f12e187 100644
--- a/app/views/import/bitbucket_server/status.html.haml
+++ b/app/views/import/bitbucket_server/status.html.haml
@@ -56,7 +56,7 @@
.project-path.input-group-prepend
- if current_user.can_select_namespace?
- selected = params[:namespace_id] || :extra_group
- - opts = current_user.can_create_group? ? { extra_group: Group.new(name: repo.project_key, path: repo.project_key) } : {}
+ - opts = current_user.can_create_group? ? { extra_group: Group.new(name: sanitize_project_name(repo.project_key), path: sanitize_project_name(repo.project_key)) } : {}
= select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'input-group-text select2 js-select-namespace', tabindex: 1 }
- else
= text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true
diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml
index 6ff25f2c842..cf32c5c9387 100644
--- a/app/views/import/github/new.html.haml
+++ b/app/views/import/github/new.html.haml
@@ -4,7 +4,7 @@
- header_title _("Projects"), root_path
%h3.page-title
- = icon 'github', text: import_github_title
+ = icon 'github', text: _('Import repositories from GitHub')
- if github_import_configured?
%p
diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml
index be057be6d1a..ee295e70cce 100644
--- a/app/views/import/github/status.html.haml
+++ b/app/views/import/github/status.html.haml
@@ -2,7 +2,7 @@
- page_title title
- breadcrumb_title title
- header_title _("Projects"), root_path
-%h3.page-title
- = icon 'github', text: import_github_title
+%h3.page-title.mb-0
+ = icon 'github', class: 'fa-2x', text: _('Import repositories from GitHub')
= render 'import/githubish_status', provider: 'github'
diff --git a/app/views/import/manifest/status.html.haml b/app/views/import/manifest/status.html.haml
index 5b2e1005398..3d4abc32b88 100644
--- a/app/views/import/manifest/status.html.haml
+++ b/app/views/import/manifest/status.html.haml
@@ -7,7 +7,7 @@
%p
= button_tag class: "btn btn-import btn-success js-import-all" do
- = import_all_githubish_repositories_button_label
+ = _('Import all repositories')
= icon("spinner spin", class: "loading-icon")
.table-responsive
diff --git a/app/views/instance_statistics/conversational_development_index/_callout.html.haml b/app/views/instance_statistics/conversational_development_index/_callout.html.haml
index 33a4dab1e00..a4256e23979 100644
--- a/app/views/instance_statistics/conversational_development_index/_callout.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/_callout.html.haml
@@ -2,12 +2,12 @@
.user-callout{ data: { uid: 'convdev_intro_callout_dismissed' } }
.bordered-box.landing.content-block
%button.btn.btn-default.close.js-close-callout{ type: 'button',
- 'aria-label' => 'Dismiss ConvDev introduction' }
+ 'aria-label' => _('Dismiss ConvDev introduction') }
= icon('times', class: 'dismiss-icon', 'aria-hidden' => 'true')
.user-callout-copy
%h4
- Introducing Your Conversational Development Index
+ = _('Introducing Your Conversational Development Index')
%p
- Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers.
+ = _('Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers.')
.svg-container.convdev
= custom_icon('convdev_overview')
diff --git a/app/views/instance_statistics/conversational_development_index/_card.html.haml b/app/views/instance_statistics/conversational_development_index/_card.html.haml
index 57eda06630b..76af55dcf7a 100644
--- a/app/views/instance_statistics/conversational_development_index/_card.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/_card.html.haml
@@ -9,11 +9,11 @@
.board-card-score
.board-card-score-value
= format_score(card.instance_score)
- .board-card-score-name You
+ .board-card-score-name= _('You')
.board-card-score
.board-card-score-value
= format_score(card.leader_score)
- .board-card-score-name Lead
+ .board-card-score-name= _('Lead')
.board-card-score-big
= number_to_percentage(card.percentage_score, precision: 1)
.board-card-buttons
diff --git a/app/views/instance_statistics/conversational_development_index/_no_data.html.haml b/app/views/instance_statistics/conversational_development_index/_no_data.html.haml
index dd795aee135..4e8f34cd574 100644
--- a/app/views/instance_statistics/conversational_development_index/_no_data.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/_no_data.html.haml
@@ -1,7 +1,7 @@
.container.convdev-empty
.col-sm-12.justify-content-center.text-center
= custom_icon('convdev_no_data')
- %h4 Data is still calculating...
+ %h4= _('Data is still calculating...')
%p
- In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index.
- = link_to 'Learn more', help_page_path('user/instance_statistics/convdev'), target: '_blank'
+ = _('In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index.')
+ = link_to _('Learn more'), help_page_path('user/instance_statistics/convdev'), target: '_blank'
diff --git a/app/views/instance_statistics/conversational_development_index/index.html.haml b/app/views/instance_statistics/conversational_development_index/index.html.haml
index 1e7db4982d6..23f90b876a0 100644
--- a/app/views/instance_statistics/conversational_development_index/index.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/index.html.haml
@@ -17,9 +17,9 @@
%h2.convdev-header-title{ class: "convdev-#{score_level(@metric.average_percentage_score)}-score" }
= number_to_percentage(@metric.average_percentage_score, precision: 1)
.convdev-header-subtitle
- index
+ = _('index')
%br
- score
+ = _('score')
= link_to icon('question-circle', 'aria-hidden' => 'true'), help_page_path('user/instance_statistics/convdev')
.convdev-cards.board-card-container
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 08a6359f777..11e83ddfe64 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -11,20 +11,20 @@
%meta{ 'http-equiv' => 'X-UA-Compatible', content: 'IE=edge' }
-# Open Graph - http://ogp.me/
- %meta{ property: 'og:type', content: "object" }
- %meta{ property: 'og:site_name', content: site_name }
- %meta{ property: 'og:title', content: page_title }
+ %meta{ property: 'og:type', content: "object" }
+ %meta{ property: 'og:site_name', content: site_name }
+ %meta{ property: 'og:title', content: page_title }
%meta{ property: 'og:description', content: page_description }
- %meta{ property: 'og:image', content: page_image }
+ %meta{ property: 'og:image', content: page_image }
%meta{ property: 'og:image:width', content: '64' }
%meta{ property: 'og:image:height', content: '64' }
- %meta{ property: 'og:url', content: request.base_url + request.fullpath }
+ %meta{ property: 'og:url', content: request.base_url + request.fullpath }
-# Twitter Card - https://dev.twitter.com/cards/types/summary
- %meta{ property: 'twitter:card', content: "summary" }
- %meta{ property: 'twitter:title', content: page_title }
- %meta{ property: 'twitter:description', content: page_description }
- %meta{ property: 'twitter:image', content: page_image }
+ %meta{ property: 'twitter:card', content: "summary" }
+ %meta{ property: 'twitter:title', content: page_title }
+ %meta{ property: 'twitter:description', content: page_description }
+ %meta{ property: 'twitter:image', content: page_image }
= page_card_meta_tags
%title= page_title(site_name)
@@ -33,11 +33,13 @@
= favicon_link_tag favicon, id: 'favicon', data: { original_href: favicon }, type: 'image/png'
= stylesheet_link_tag "application", media: "all"
- = stylesheet_link_tag "print", media: "print"
- = stylesheet_link_tag "test", media: "all" if Rails.env.test?
+ = stylesheet_link_tag "print", media: "print"
+ = stylesheet_link_tag "test", media: "all" if Rails.env.test?
= stylesheet_link_tag 'performance_bar' if performance_bar_enabled?
= stylesheet_link_tag 'csslab' if Feature.enabled?(:csslab)
+ = stylesheet_link_tag "highlight/themes/#{user_color_scheme}", media: "all"
+
= Gon::Base.render_data
- if content_for?(:library_javascripts)
@@ -61,10 +63,10 @@
%meta{ name: 'theme-color', content: '#474D57' }
-# Apple Safari/iOS home screen icons
- = favicon_link_tag 'touch-icon-iphone.png', rel: 'apple-touch-icon'
- = favicon_link_tag 'touch-icon-ipad.png', rel: 'apple-touch-icon', sizes: '76x76'
+ = favicon_link_tag 'touch-icon-iphone.png', rel: 'apple-touch-icon'
+ = favicon_link_tag 'touch-icon-ipad.png', rel: 'apple-touch-icon', sizes: '76x76'
= favicon_link_tag 'touch-icon-iphone-retina.png', rel: 'apple-touch-icon', sizes: '120x120'
- = favicon_link_tag 'touch-icon-ipad-retina.png', rel: 'apple-touch-icon', sizes: '152x152'
+ = favicon_link_tag 'touch-icon-ipad-retina.png', rel: 'apple-touch-icon', sizes: '152x152'
%link{ rel: 'mask-icon', href: image_path('logo.svg'), color: 'rgb(226, 67, 41)' }
-# Windows 8 pinned site tile
diff --git a/app/views/layouts/_init_client_detection_flags.html.haml b/app/views/layouts/_init_client_detection_flags.html.haml
new file mode 100644
index 00000000000..c729f8aa696
--- /dev/null
+++ b/app/views/layouts/_init_client_detection_flags.html.haml
@@ -0,0 +1,7 @@
+- client = client_js_flags
+
+- if client
+ -# haml-lint:disable InlineJavaScript
+ :javascript
+ gl = window.gl || {};
+ gl.client = #{client.to_json};
diff --git a/app/views/layouts/_mailer.html.haml b/app/views/layouts/_mailer.html.haml
index ddc1cdb24b5..e13490ed410 100644
--- a/app/views/layouts/_mailer.html.haml
+++ b/app/views/layouts/_mailer.html.haml
@@ -49,9 +49,10 @@
%table#body{ border: "0", cellpadding: "0", cellspacing: "0", style: "background-color:#fafafa;margin:0;padding:0;text-align:center;min-width:640px;width:100%;" }
%tbody
%tr.line
- %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#6b4fbb;height:4px;font-size:4px;line-height:4px;" }  
+ %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#6b4fbb;height:4px;font-size:4px;line-height:4px;" }
%tr.header
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
+ = html_header_message
= header_logo
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" }
@@ -72,3 +73,6 @@
= _("You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}").html_safe % { host: Gitlab.config.gitlab.host, manage_notifications_link: manage_notifications_link, help_link: help_link }
= yield :additional_footer
+ %tr
+ %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
+ = html_footer_message
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 1f4d24d996c..043cca6ad38 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -1,10 +1,13 @@
!!! 5
%html{ lang: I18n.locale, class: page_class }
= render "layouts/head"
- %body{ class: "#{user_application_theme} #{@body_class}", data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}", find_file: find_file_path } }
+ %body{ class: "#{user_application_theme} #{@body_class} #{client_class_list}", data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}", find_file: find_file_path } }
= render "layouts/init_auto_complete" if @gfm_form
+ = render "layouts/init_client_detection_flags"
= render 'peek/bar'
- = render partial: "layouts/header/default", locals: { project: @project, group: @group }
+ = header_message
+ = render partial: "layouts/header/default", locals: { project: @project, group: @group }
= render 'layouts/page', sidebar: sidebar, nav: nav
+ = footer_message
= yield :scripts_body
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 6003d973c88..2f3c13aaf6e 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -2,6 +2,7 @@
%html.devise-layout-html{ class: system_message_class }
= render "layouts/head"
%body.ui-indigo.login-page.application.navless.qa-login-page{ data: { page: body_data_page } }
+ = header_message
.page-wrap
= render "layouts/header/empty"
.login-page-broadcast
@@ -34,3 +35,4 @@
= link_to _("Explore"), explore_root_path
= link_to _("Help"), help_path
= link_to _("About GitLab"), "https://about.gitlab.com/"
+ = footer_message
diff --git a/app/views/layouts/devise_empty.html.haml b/app/views/layouts/devise_empty.html.haml
index 663e5b24368..6c9c8aa4431 100644
--- a/app/views/layouts/devise_empty.html.haml
+++ b/app/views/layouts/devise_empty.html.haml
@@ -2,6 +2,7 @@
%html{ lang: "en", class: system_message_class }
= render "layouts/head"
%body.ui-indigo.login-page.application.navless
+ = header_message
= render "layouts/header/empty"
= render "layouts/broadcast"
.container.navless-container
@@ -15,3 +16,4 @@
= link_to _("Explore"), explore_root_path
= link_to _("Help"), help_path
= link_to _("About GitLab"), "https://about.gitlab.com/"
+ = footer_message
diff --git a/app/views/layouts/empty_mailer.html.haml b/app/views/layouts/empty_mailer.html.haml
new file mode 100644
index 00000000000..a25dcefd445
--- /dev/null
+++ b/app/views/layouts/empty_mailer.html.haml
@@ -0,0 +1,5 @@
+= html_header_message
+
+= yield
+
+= html_footer_message
diff --git a/app/views/layouts/empty_mailer.text.erb b/app/views/layouts/empty_mailer.text.erb
new file mode 100644
index 00000000000..6ab0dbead07
--- /dev/null
+++ b/app/views/layouts/empty_mailer.text.erb
@@ -0,0 +1,5 @@
+<%= text_header_message %>
+
+<%= yield -%>
+
+<%= text_footer_message %>
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index bfbfeee7c4b..1d40b78fa83 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -1,7 +1,7 @@
- page_title @group.name
- page_description @group.description unless page_description
- header_title group_title(@group) unless header_title
-- nav "group"
+- nav "group"
- @left_sidebar = true
- content_for :page_specific_javascripts do
diff --git a/app/views/layouts/header/_empty.html.haml b/app/views/layouts/header/_empty.html.haml
index 2dfc787b7a8..348ce18b122 100644
--- a/app/views/layouts/header/_empty.html.haml
+++ b/app/views/layouts/header/_empty.html.haml
@@ -1,4 +1,2 @@
%header.navbar.fixed-top.navbar-empty
- .container
- .mx-auto
- = brand_header_logo
+ = brand_header_logo
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index 953c0e7f46c..cd9128c452b 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -2,5 +2,8 @@
- if current_user_menu?(:help)
%li
= link_to _("Help"), help_path
+ %li.divider
+ %li
+ = link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
- if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
= render 'shared/user_dropdown_contributing_link'
diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml
index e42251f9ec8..5a66b02c048 100644
--- a/app/views/layouts/header/_new_dropdown.haml
+++ b/app/views/layouts/header/_new_dropdown.haml
@@ -1,4 +1,4 @@
-%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown" } }
+%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown" } }
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
= sprite_icon('plus-square', size: 16)
= sprite_icon('angle-down', css_class: 'caret-down')
diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb
index 8e11174f8d7..f8032f3262b 100644
--- a/app/views/layouts/mailer.text.erb
+++ b/app/views/layouts/mailer.text.erb
@@ -1,4 +1,8 @@
+<%= text_header_message %>
+
<%= yield -%>
-- <%# signature marker %>
<%= _("You're receiving this email because of your account on %{host}.") % { host: Gitlab.config.gitlab.host } %>
+
+<%= text_footer_message %>
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index ddd30efe062..f659c89dd30 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -10,7 +10,7 @@
= render "layouts/nav/projects_dropdown/show"
- if dashboard_nav_link?(:groups)
- = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "home dropdown header-groups qa-groups-dropdown", data: { track_label: "groups_dropdown", track_event: "click_dropdown" } }) do
+ = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "home dropdown header-groups qa-groups-dropdown", data: { track_label: "groups_dropdown", track_event: "click_dropdown" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Groups')
= sprite_icon('angle-down', css_class: 'caret-down')
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 5f15ba87729..2fdd65f639b 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -207,7 +207,7 @@
= _('Settings')
%li.divider.fly-out-top-item
= nav_link(path: 'application_settings#show') do
- = link_to admin_application_settings_path, title: _('General') do
+ = link_to admin_application_settings_path, title: _('General'), class: 'qa-admin-settings-general-item' do
%span
= _('General')
= nav_link(path: 'application_settings#integrations') do
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 477030a20c1..21ea9f3b2f3 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -6,7 +6,7 @@
.nav-sidebar-inner-scroll
.context-header
= link_to group_path(@group), title: @group.name do
- .avatar-container.s40.group-avatar
+ .avatar-container.rect-avatar.s40.group-avatar
= group_icon(@group, class: "avatar s40 avatar-tile")
.sidebar-context-title
= @group.name
@@ -36,7 +36,7 @@
%span
= _('Activity')
- = render_if_exists 'groups/sidebar/security_dashboard'
+ = render_if_exists 'groups/sidebar/security_dashboard' # EE-specific
- if group_sidebar_link?(:contribution_analytics)
= nav_link(path: 'analytics#show') do
@@ -103,19 +103,6 @@
= _('Merge Requests')
%span.badge.badge-pill.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(merge_requests_count)
- - if group_sidebar_link?(:group_members)
- = nav_link(path: 'group_members#index') do
- = link_to group_group_members_path(@group) do
- .nav-icon-container
- = sprite_icon('users')
- %span.nav-item-name.qa-group-members-item
- = _('Members')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(path: 'group_members#index', html_options: { class: "fly-out-top-item" } ) do
- = link_to group_group_members_path(@group) do
- %strong.fly-out-top-item-name
- = _('Members')
-
- if group_sidebar_link?(:kubernetes)
= nav_link(controller: [:clusters]) do
= link_to group_clusters_path(@group) do
@@ -129,6 +116,19 @@
%strong.fly-out-top-item-name
= _('Kubernetes')
+ - if group_sidebar_link?(:group_members)
+ = nav_link(path: 'group_members#index') do
+ = link_to group_group_members_path(@group) do
+ .nav-icon-container
+ = sprite_icon('users')
+ %span.nav-item-name.qa-group-members-item
+ = _('Members')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(path: 'group_members#index', html_options: { class: "fly-out-top-item" } ) do
+ = link_to group_group_members_path(@group) do
+ %strong.fly-out-top-item-name
+ = _('Members')
+
- if group_sidebar_link?(:settings)
= nav_link(path: group_nav_link_paths) do
= link_to edit_group_path(@group) do
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 69167edb1df..1e3bb8f1224 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') do
.avatar-container.s40.settings-avatar
- = sprite_icon('user', size: 24)
+ = image_tag avatar_icon_for_user(current_user, 40), class: "avatar s40 avatar-tile", alt: current_user.name
.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/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 59557c70904..7b492efeb09 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -3,7 +3,7 @@
- can_edit = can?(current_user, :admin_project, @project)
.context-header
= link_to project_path(@project), title: @project.name do
- .avatar-container.s40.project-avatar
+ .avatar-container.rect-avatar.s40.project-avatar
= project_icon(@project, alt: @project.name, class: 'avatar s40 avatar-tile', width: 40, height: 40)
.sidebar-context-title
= @project.name
@@ -26,10 +26,10 @@
%span= _('Details')
= nav_link(path: 'projects#activity') do
- = link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do
+ = link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity qa-activity-link' do
%span= _('Activity')
- - if project_nav_tab?(:releases) && Feature.enabled?(:releases_page)
+ - if project_nav_tab?(:releases)
= nav_link(controller: :releases) do
= link_to project_releases_path(@project), title: _('Releases'), class: 'shortcuts-project-releases' do
%span= _('Releases')
@@ -43,7 +43,7 @@
- if project_nav_tab? :files
= nav_link(controller: sidebar_repository_paths) do
- = link_to project_tree_path(@project), class: 'shortcuts-tree' do
+ = link_to project_tree_path(@project), class: 'shortcuts-tree qa-project-menu-repo' do
.nav-icon-container
= sprite_icon('doc-text')
%span.nav-item-name
@@ -64,7 +64,7 @@
= _('Commits')
= nav_link(html_options: {class: branches_tab_class}) do
- = link_to project_branches_path(@project) do
+ = link_to project_branches_path(@project), class: 'qa-branches-link' do
= _('Branches')
= nav_link(controller: [:tags]) do
@@ -146,7 +146,7 @@
- if project_nav_tab? :merge_requests
= nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :labels, :milestones]) do
- = link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests' do
+ = link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests qa-merge-requests-link' do
.nav-icon-container
= sprite_icon('git-merge')
%span.nav-item-name
@@ -170,7 +170,7 @@
= _('CI / CD')
%ul.sidebar-sub-level-items
- = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts], html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts], html_options: { class: "fly-out-top-item" }) do
= link_to project_pipelines_path(@project) do
%strong.fly-out-top-item-name
= _('CI / CD')
@@ -201,7 +201,7 @@
- if project_nav_tab? :operations
= nav_link(controller: sidebar_operations_paths) do
- = link_to sidebar_operations_link_path, class: 'shortcuts-operations' do
+ = link_to sidebar_operations_link_path, class: 'shortcuts-operations qa-link-operations' do
.nav-icon-container
= sprite_icon('cloud-gear')
%span.nav-item-name
@@ -227,6 +227,12 @@
%span
= _('Environments')
+ - if project_nav_tab?(:error_tracking)
+ = nav_link(controller: :error_tracking) do
+ = link_to project_error_tracking_index_path(@project), title: _('Error Tracking'), class: 'shortcuts-tracking qa-operations-tracking-link' do
+ %span
+ = _('Error Tracking')
+
- if project_nav_tab? :serverless
= nav_link(controller: :functions) do
= link_to project_serverless_functions_path(@project), title: _('Serverless') do
@@ -275,19 +281,34 @@
%strong.fly-out-top-item-name
= _('Registry')
- - if project_nav_tab? :wiki
+ - if project_nav_tab?(:wiki)
+ - wiki_url = project_wiki_path(@project, :home)
= nav_link(controller: :wikis) do
- = link_to get_project_wiki_path(@project), class: 'shortcuts-wiki' do
+ = link_to wiki_url, class: 'shortcuts-wiki qa-wiki-link' do
.nav-icon-container
= sprite_icon('book')
%span.nav-item-name
= _('Wiki')
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(controller: :wikis, html_options: { class: "fly-out-top-item" } ) do
- = link_to get_project_wiki_path(@project) do
+ = link_to wiki_url do
%strong.fly-out-top-item-name
= _('Wiki')
+ - if project_nav_tab?(:external_wiki)
+ - external_wiki_url = @project.external_wiki.external_wiki_url
+ = nav_link do
+ = link_to external_wiki_url, class: 'shortcuts-external_wiki' do
+ .nav-icon-container
+ = sprite_icon('issue-external')
+ %span.nav-item-name
+ = _('External Wiki')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(html_options: { class: "fly-out-top-item" } ) do
+ = link_to external_wiki_url do
+ %strong.fly-out-top-item-name
+ = _('External Wiki')
+
- if project_nav_tab? :snippets
= nav_link(controller: :snippets) do
= link_to project_snippets_path(@project), class: 'shortcuts-snippets' do
@@ -339,7 +360,10 @@
= link_to project_settings_ci_cd_path(@project), title: _('CI / CD') do
%span
= _('CI / CD')
- = render_if_exists 'projects/sidebar/settings_operations'
+ - if settings_operations_available?
+ = nav_link(controller: [:operations]) do
+ = link_to project_settings_operations_path(@project), title: _('Operations') do
+ = _('Operations')
- if @project.pages_available?
= nav_link(controller: :pages) do
= link_to project_pages_path(@project), title: _('Pages') do
diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml
index 1c3e05e07f4..8dff12c1b7f 100644
--- a/app/views/layouts/notify.html.haml
+++ b/app/views/layouts/notify.html.haml
@@ -7,6 +7,7 @@
= yield :head
%body
.content
+ = html_header_message
= yield
.footer{ style: "margin-top: 10px;" }
%p
@@ -30,3 +31,4 @@
adjust your notification settings.
= email_action @target_url
+ = html_footer_message
diff --git a/app/views/layouts/notify.text.erb b/app/views/layouts/notify.text.erb
index 9dc490efa9a..248916fba63 100644
--- a/app/views/layouts/notify.text.erb
+++ b/app/views/layouts/notify.text.erb
@@ -1,3 +1,5 @@
+<%= text_header_message %>
+
<%= yield -%>
-- <%# signature marker %>
@@ -10,3 +12,5 @@
<% end -%>
<%= "You're receiving this email because #{notification_reason_text(@reason)}." %>
+
+<%= text_footer_message -%>
diff --git a/app/views/layouts/snippets.html.haml b/app/views/layouts/snippets.html.haml
index 6418500d5d1..5f986c81ff4 100644
--- a/app/views/layouts/snippets.html.haml
+++ b/app/views/layouts/snippets.html.haml
@@ -1,4 +1,4 @@
-- header_title _("Snippets"), snippets_path
+- header_title _("Snippets"), snippets_path
- content_for :page_specific_javascripts do
- if @snippet && current_user
diff --git a/app/views/notify/_note_email.text.erb b/app/views/notify/_note_email.text.erb
index 50209c46ed1..5a67214059c 100644
--- a/app/views/notify/_note_email.text.erb
+++ b/app/views/notify/_note_email.text.erb
@@ -3,7 +3,7 @@
<% discussion = note.discussion if note.part_of_discussion? -%>
<% if discussion && !discussion.individual_note? -%>
-<%= note.author_name -%>
+<%= sanitize_name(note.author_name) -%>
<% if discussion.new_discussion? -%>
<%= " started a new discussion" -%>
<% else -%>
@@ -16,7 +16,7 @@
<% elsif Gitlab::CurrentSettings.email_author_in_body -%>
-<%= "#{note.author_name} commented:" -%>
+<%= "#{sanitize_name(note.author_name)} commented:" -%>
<% end -%>
diff --git a/app/views/notify/autodevops_disabled_email.text.erb b/app/views/notify/autodevops_disabled_email.text.erb
index 695780c3145..bf863952478 100644
--- a/app/views/notify/autodevops_disabled_email.text.erb
+++ b/app/views/notify/autodevops_disabled_email.text.erb
@@ -3,7 +3,7 @@ Auto DevOps pipeline was disabled for <%= @project.name %>
The Auto DevOps pipeline failed for pipeline <%= @pipeline.iid %> (<%= pipeline_url(@pipeline) %>) and has been disabled for <%= @project.name %>. In order to use the Auto DevOps pipeline with your project, please review the currently supported languagues (https://docs.gitlab.com/ee/topics/autodevops/#currently-supported-languages), adjust your project accordingly, and turn on the Auto DevOps pipeline within your CI/CD project settings (<%= project_settings_ci_cd_url(@project) %>).
<% if @pipeline.user -%>
- Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by <%= @pipeline.user.name %> ( <%= user_url(@pipeline.user) %> )
+ Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by <%= sanitize_name(@pipeline.user.name) %> ( <%= user_url(@pipeline.user) %> )
<% else -%>
Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by API
<% end -%>
diff --git a/app/views/notify/closed_issue_email.html.haml b/app/views/notify/closed_issue_email.html.haml
index b7284dd819b..eb148d72da1 100644
--- a/app/views/notify/closed_issue_email.html.haml
+++ b/app/views/notify/closed_issue_email.html.haml
@@ -1,2 +1,2 @@
%p
- Issue was closed by #{@updated_by.name}
+ Issue was closed by #{sanitize_name(@updated_by.name)}
diff --git a/app/views/notify/closed_issue_email.text.haml b/app/views/notify/closed_issue_email.text.haml
index b35d4b7502d..b1f0a3f37ec 100644
--- a/app/views/notify/closed_issue_email.text.haml
+++ b/app/views/notify/closed_issue_email.text.haml
@@ -1,3 +1,3 @@
-Issue was closed by #{@updated_by.name}
+Issue was closed by #{sanitize_name(@updated_by.name)}
Issue ##{@issue.iid}: #{project_issue_url(@issue.project, @issue)}
diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml
index 44e018304e1..2aa753e0d55 100644
--- a/app/views/notify/closed_merge_request_email.html.haml
+++ b/app/views/notify/closed_merge_request_email.html.haml
@@ -1,2 +1,2 @@
%p
- Merge Request #{@merge_request.to_reference} was closed by #{@updated_by.name}
+ Merge Request #{@merge_request.to_reference} was closed by #{sanitize_name(@updated_by.name)}
diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml
index c4e06cb3cb1..1094d584a1c 100644
--- a/app/views/notify/closed_merge_request_email.text.haml
+++ b/app/views/notify/closed_merge_request_email.text.haml
@@ -1,8 +1,8 @@
-Merge Request #{@merge_request.to_reference} was closed by #{@updated_by.name}
+Merge Request #{@merge_request.to_reference} was closed by #{sanitize_name(@updated_by.name)}
Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
-Author: #{@merge_request.author_name}
-Assignee: #{@merge_request.assignee_name}
+Author: #{sanitize_name(@merge_request.author_name)}
+Assignee: #{sanitize_name(@merge_request.assignee_name)}
diff --git a/app/views/notify/import_issues_csv_email.html.haml b/app/views/notify/import_issues_csv_email.html.haml
new file mode 100644
index 00000000000..f30d2b5f078
--- /dev/null
+++ b/app/views/notify/import_issues_csv_email.html.haml
@@ -0,0 +1,18 @@
+- text_style = 'font-size:16px; text-align:center; line-height:30px;'
+
+%p{ style: text_style }
+ Your CSV import for project
+ %a{ href: project_url(@project), style: "color:#3777b0; text-decoration:none;" }
+ = @project.full_name
+ has been completed.
+
+%p{ style: text_style }
+ #{pluralize(@results[:success], 'issue')} imported.
+
+- if @results[:error_lines].present?
+ %p{ style: text_style }
+ Errors found on line #{'number'.pluralize(@results[:error_lines].size)}: #{@results[:error_lines].join(', ')}. Please check if these lines have an issue title.
+
+- if @results[:parse_error]
+ %p{ style: text_style }
+ Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values.
diff --git a/app/views/notify/import_issues_csv_email.text.erb b/app/views/notify/import_issues_csv_email.text.erb
new file mode 100644
index 00000000000..1117f90714d
--- /dev/null
+++ b/app/views/notify/import_issues_csv_email.text.erb
@@ -0,0 +1,11 @@
+Your CSV import for project <%= @project.full_name %> (<%= project_url(@project) %>) has been completed.
+
+<%= pluralize(@results[:success], 'issue') %> imported.
+
+<% if @results[:error_lines].present? %>
+Errors found on line <%= 'number'.pluralize(@results[:error_lines].size) %>: <%= @results[:error_lines].join(', ') %>. Please check if these lines have an issue title.
+<% end %>
+
+<% if @results[:parse_error] %>
+Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values.
+<% end %>
diff --git a/app/views/notify/issue_moved_email.html.haml b/app/views/notify/issue_moved_email.html.haml
index 472c31e9a5e..b766cb1a523 100644
--- a/app/views/notify/issue_moved_email.html.haml
+++ b/app/views/notify/issue_moved_email.html.haml
@@ -1,6 +1,9 @@
%p
Issue was moved to another project.
-%p
- New issue:
- = link_to project_issue_url(@new_project, @new_issue) do
- = @new_issue.title
+- if @can_access_project
+ %p
+ New issue:
+ = link_to project_issue_url(@new_project, @new_issue) do
+ = @new_issue.title
+- else
+ You don't have access to the project.
diff --git a/app/views/notify/issue_moved_email.text.erb b/app/views/notify/issue_moved_email.text.erb
index 66ede43635b..985e689aa9d 100644
--- a/app/views/notify/issue_moved_email.text.erb
+++ b/app/views/notify/issue_moved_email.text.erb
@@ -1,4 +1,8 @@
Issue was moved to another project.
+<% if @can_access_project %>
New issue location:
<%= project_issue_url(@new_project, @new_issue) %>
+<% else %>
+You don't have access to the project.
+<% end %>
diff --git a/app/views/notify/issue_status_changed_email.html.haml b/app/views/notify/issue_status_changed_email.html.haml
index b6051b11cea..66e73a9b03f 100644
--- a/app/views/notify/issue_status_changed_email.html.haml
+++ b/app/views/notify/issue_status_changed_email.html.haml
@@ -1,2 +1,2 @@
%p
- Issue was #{@issue_status} by #{@updated_by.name}
+ Issue was #{@issue_status} by #{sanitize_name(@updated_by.name)}
diff --git a/app/views/notify/issue_status_changed_email.text.erb b/app/views/notify/issue_status_changed_email.text.erb
index 4200881f7e8..f38b09e9820 100644
--- a/app/views/notify/issue_status_changed_email.text.erb
+++ b/app/views/notify/issue_status_changed_email.text.erb
@@ -1,4 +1,4 @@
-Issue was <%= @issue_status %> by <%= @updated_by.name %>
+Issue was <%= @issue_status %> by <%= sanitize_name(@updated_by.name) %>
Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
diff --git a/app/views/notify/member_access_requested_email.text.erb b/app/views/notify/member_access_requested_email.text.erb
index 9c5ee0eaf26..ddb4a7b3d2c 100644
--- a/app/views/notify/member_access_requested_email.text.erb
+++ b/app/views/notify/member_access_requested_email.text.erb
@@ -1,3 +1,3 @@
-<%= member.user.name %> (<%= user_url(member.user) %>) requested <%= member.human_access %> access to the <%= member_source.human_name %> <%= member_source.model_name.singular %>.
+<%= sanitize_name(member.user.name) %> (<%= user_url(member.user) %>) requested <%= member.human_access %> access to the <%= member_source.human_name %> <%= member_source.model_name.singular %>.
<%= polymorphic_url([member_source, :members]) %>
diff --git a/app/views/notify/member_invite_accepted_email.text.erb b/app/views/notify/member_invite_accepted_email.text.erb
index cef87101427..c824533eac2 100644
--- a/app/views/notify/member_invite_accepted_email.text.erb
+++ b/app/views/notify/member_invite_accepted_email.text.erb
@@ -1,3 +1,3 @@
-<%= member.invite_email %>, now known as <%= member.user.name %>, has accepted your invitation to join the <%= member_source.human_name %> <%= member_source.model_name.singular %>.
+<%= 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 %>.
<%= member_source.web_url %>
diff --git a/app/views/notify/member_invited_email.text.erb b/app/views/notify/member_invited_email.text.erb
index 0a6393355be..d944c3b4a50 100644
--- a/app/views/notify/member_invited_email.text.erb
+++ b/app/views/notify/member_invited_email.text.erb
@@ -1,4 +1,4 @@
-You have been invited <%= "by #{member.created_by.name} " if member.created_by %>to join the <%= member_source.human_name %> <%= member_source.model_name.singular %> as <%= member.human_access %>.
+You have been invited <%= "by #{sanitize_name(member.created_by.name)} " if member.created_by %>to join the <%= member_source.human_name %> <%= member_source.model_name.singular %> as <%= member.human_access %>.
Accept invitation: <%= invite_url(@token) %>
Decline invitation: <%= decline_invite_url(@token) %>
diff --git a/app/views/notify/merge_request_status_email.html.haml b/app/views/notify/merge_request_status_email.html.haml
index b487e26b122..ffb416abf72 100644
--- a/app/views/notify/merge_request_status_email.html.haml
+++ b/app/views/notify/merge_request_status_email.html.haml
@@ -1,2 +1,2 @@
%p
- Merge Request #{@merge_request.to_reference} was #{@mr_status} by #{@updated_by.name}
+ Merge Request #{@merge_request.to_reference} was #{@mr_status} by #{sanitize_name(@updated_by.name)}
diff --git a/app/views/notify/merge_request_status_email.text.haml b/app/views/notify/merge_request_status_email.text.haml
index ae2a2933865..b9b9e0c3ad7 100644
--- a/app/views/notify/merge_request_status_email.text.haml
+++ b/app/views/notify/merge_request_status_email.text.haml
@@ -1,8 +1,8 @@
-Merge Request #{@merge_request.to_reference} was #{@mr_status} by #{@updated_by.name}
+Merge Request #{@merge_request.to_reference} was #{@mr_status} by #{sanitize_name(@updated_by.name)}
Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
-Author: #{@merge_request.author_name}
-Assignee: #{@merge_request.assignee_name}
+Author: #{sanitize_name(@merge_request.author_name)}
+Assignee: #{sanitize_name(@merge_request.assignee_name)}
diff --git a/app/views/notify/merge_request_unmergeable_email.text.haml b/app/views/notify/merge_request_unmergeable_email.text.haml
index dcdd6db69d6..0c7bf1bb044 100644
--- a/app/views/notify/merge_request_unmergeable_email.text.haml
+++ b/app/views/notify/merge_request_unmergeable_email.text.haml
@@ -4,5 +4,5 @@ Merge Request url: #{project_merge_request_url(@merge_request.target_project, @m
= merge_path_description(@merge_request, 'to')
-Author: #{@merge_request.author_name}
-Assignee: #{@merge_request.assignee_name}
+Author: #{sanitize_name(@merge_request.author_name)}
+Assignee: #{sanitize_name(@merge_request.assignee_name)}
diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml
index 661c23bcbe2..045a43cbc84 100644
--- a/app/views/notify/merged_merge_request_email.text.haml
+++ b/app/views/notify/merged_merge_request_email.text.haml
@@ -4,5 +4,5 @@ Merge Request url: #{project_merge_request_url(@merge_request.target_project, @m
= merge_path_description(@merge_request, 'to')
-Author: #{@merge_request.author_name}
-Assignee: #{@merge_request.assignee_name}
+Author: #{sanitize_name(@merge_request.author_name)}
+Assignee: #{sanitize_name(@merge_request.assignee_name)}
diff --git a/app/views/notify/new_gpg_key_email.html.haml b/app/views/notify/new_gpg_key_email.html.haml
index 4b9350c4e88..b857705e01f 100644
--- a/app/views/notify/new_gpg_key_email.html.haml
+++ b/app/views/notify/new_gpg_key_email.html.haml
@@ -1,5 +1,5 @@
%p
- Hi #{@user.name}!
+ Hi #{sanitize_name(@user.name)}!
%p
A new GPG key was added to your account:
%p
diff --git a/app/views/notify/new_gpg_key_email.text.erb b/app/views/notify/new_gpg_key_email.text.erb
index 80b5a1fd7ff..92ea851eee4 100644
--- a/app/views/notify/new_gpg_key_email.text.erb
+++ b/app/views/notify/new_gpg_key_email.text.erb
@@ -1,4 +1,4 @@
-Hi <%= @user.name %>!
+Hi <%= sanitize_name(@user.name) %>!
A new GPG key was added to your account:
diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb
index 3c716f77296..58a2bcbe5eb 100644
--- a/app/views/notify/new_issue_email.text.erb
+++ b/app/views/notify/new_issue_email.text.erb
@@ -1,7 +1,7 @@
New Issue was created.
Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
-Author: <%= @issue.author_name %>
+Author: <%= sanitize_name(@issue.author_name) %>
Assignee: <%= @issue.assignee_list %>
<%= @issue.description %>
diff --git a/app/views/notify/new_mention_in_issue_email.text.erb b/app/views/notify/new_mention_in_issue_email.text.erb
index 23213106c5b..173091e4a80 100644
--- a/app/views/notify/new_mention_in_issue_email.text.erb
+++ b/app/views/notify/new_mention_in_issue_email.text.erb
@@ -1,7 +1,7 @@
You have been mentioned in an issue.
Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
-Author: <%= @issue.author_name %>
-Assignee: <%= @issue.assignee_list %>
+Author: <%= sanitize_name(@issue.author_name) %>
+Assignee: <%= sanitize_name(@issue.assignee_list) %>
<%= @issue.description %>
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 6fcebb22fc4..96a4f3f9eac 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
@@ -3,7 +3,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') %>
-Author: <%= @merge_request.author_name %>
-Assignee: <%= @merge_request.assignee_name %>
+Author: <%= sanitize_name(@merge_request.author_name) %>
+Assignee: <%= sanitize_name(@merge_request.assignee_name) %>
<%= @merge_request.description %>
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index 5acd45b74a7..db23447dd39 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -7,7 +7,7 @@
- if @merge_request.assignee_id.present?
%p
- Assignee: #{@merge_request.assignee_name}
+ Assignee: #{sanitize_name(@merge_request.assignee_name)}
= render_if_exists 'notify/merge_request_approvers', presenter: @mr_presenter
diff --git a/app/views/notify/new_ssh_key_email.html.haml b/app/views/notify/new_ssh_key_email.html.haml
index 63b0cbbd205..d031842be95 100644
--- a/app/views/notify/new_ssh_key_email.html.haml
+++ b/app/views/notify/new_ssh_key_email.html.haml
@@ -1,5 +1,5 @@
%p
- Hi #{@user.name}!
+ Hi #{sanitize_name(@user.name)}!
%p
A new public key was added to your account:
%p
diff --git a/app/views/notify/new_ssh_key_email.text.erb b/app/views/notify/new_ssh_key_email.text.erb
index 05b551c89a0..690357d69ed 100644
--- a/app/views/notify/new_ssh_key_email.text.erb
+++ b/app/views/notify/new_ssh_key_email.text.erb
@@ -1,4 +1,4 @@
-Hi <%= @user.name %>!
+Hi <%= sanitize_name(@user.name) %>!
A new public key was added to your account:
diff --git a/app/views/notify/new_user_email.html.haml b/app/views/notify/new_user_email.html.haml
index db4424a01f9..dfbb5c75bd3 100644
--- a/app/views/notify/new_user_email.html.haml
+++ b/app/views/notify/new_user_email.html.haml
@@ -1,5 +1,5 @@
%p
- Hi #{@user['name']}!
+ Hi #{sanitize_name(@user['name'])}!
%p
- if Gitlab::CurrentSettings.allow_signup?
Your account has been created successfully.
diff --git a/app/views/notify/new_user_email.text.erb b/app/views/notify/new_user_email.text.erb
index dd9b71e3b84..f3f20f3bfba 100644
--- a/app/views/notify/new_user_email.text.erb
+++ b/app/views/notify/new_user_email.text.erb
@@ -1,4 +1,4 @@
-Hi <%= @user.name %>!
+Hi <%= sanitize_name(@user.name) %>!
The Administrator created an account for you. Now you are a member of the company GitLab application.
diff --git a/app/views/notify/pipeline_failed_email.text.erb b/app/views/notify/pipeline_failed_email.text.erb
index 294238eee51..722eedf90be 100644
--- a/app/views/notify/pipeline_failed_email.text.erb
+++ b/app/views/notify/pipeline_failed_email.text.erb
@@ -10,20 +10,20 @@ Commit: <%= @pipeline.short_sha %> ( <%= commit_url(@pipeline) %> )
Commit Message: <%= @pipeline.git_commit_message.truncate(50) %>
<% commit = @pipeline.commit -%>
<% if commit.author -%>
-Commit Author: <%= commit.author.name %> ( <%= user_url(commit.author) %> )
+Commit Author: <%= sanitize_name(commit.author.name) %> ( <%= user_url(commit.author) %> )
<% else -%>
Commit Author: <%= commit.author_name %>
<% end -%>
<% if commit.different_committer? -%>
<% if commit.committer -%>
-Committed by: <%= commit.committer.name %> ( <%= user_url(commit.committer) %> )
+Committed by: <%= sanitize_name(commit.committer.name) %> ( <%= user_url(commit.committer) %> )
<% else -%>
Committed by: <%= commit.committer_name %>
<% end -%>
<% end -%>
<% if @pipeline.user -%>
-Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by <%= @pipeline.user.name %> ( <%= user_url(@pipeline.user) %> )
+Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by <%= sanitize_name(@pipeline.user.name) %> ( <%= user_url(@pipeline.user) %> )
<% else -%>
Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by API
<% end -%>
diff --git a/app/views/notify/pipeline_success_email.text.erb b/app/views/notify/pipeline_success_email.text.erb
index 39622cf7f02..9aadf380f79 100644
--- a/app/views/notify/pipeline_success_email.text.erb
+++ b/app/views/notify/pipeline_success_email.text.erb
@@ -10,13 +10,13 @@ Commit: <%= @pipeline.short_sha %> ( <%= commit_url(@pipeline) %> )
Commit Message: <%= @pipeline.git_commit_message.truncate(50) %>
<% commit = @pipeline.commit -%>
<% if commit.author -%>
-Commit Author: <%= commit.author.name %> ( <%= user_url(commit.author) %> )
+Commit Author: <%= sanitize_name(commit.author.name) %> ( <%= user_url(commit.author) %> )
<% else -%>
Commit Author: <%= commit.author_name %>
<% end -%>
<% if commit.different_committer? -%>
<% if commit.committer -%>
-Committed by: <%= commit.committer.name %> ( <%= user_url(commit.committer) %> )
+Committed by: <%= sanitize_name(commit.committer.name) %> ( <%= user_url(commit.committer) %> )
<% else -%>
Committed by: <%= commit.committer_name %>
<% end -%>
@@ -25,7 +25,7 @@ Committed by: <%= commit.committer_name %>
<% job_count = @pipeline.total_size -%>
<% stage_count = @pipeline.stages_count -%>
<% if @pipeline.user -%>
-Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by <%= @pipeline.user.name %> ( <%= user_url(@pipeline.user) %> )
+Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by <%= sanitize_name(@pipeline.user.name) %> ( <%= user_url(@pipeline.user) %> )
<% else -%>
Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by API
<% end -%>
diff --git a/app/views/notify/push_to_merge_request_email.html.haml b/app/views/notify/push_to_merge_request_email.html.haml
index 67744ec1cee..97258833cfc 100644
--- a/app/views/notify/push_to_merge_request_email.html.haml
+++ b/app/views/notify/push_to_merge_request_email.html.haml
@@ -1,5 +1,5 @@
%h3
- = @updated_by_user.name
+ = sanitize_name(@updated_by_user.name)
pushed new commits to merge request
= link_to(@merge_request.to_reference, project_merge_request_url(@merge_request.target_project, @merge_request))
diff --git a/app/views/notify/push_to_merge_request_email.text.haml b/app/views/notify/push_to_merge_request_email.text.haml
index 95759d127e2..10c8e158846 100644
--- a/app/views/notify/push_to_merge_request_email.text.haml
+++ b/app/views/notify/push_to_merge_request_email.text.haml
@@ -1,4 +1,4 @@
-#{@updated_by_user.name} pushed new commits to merge request #{@merge_request.to_reference}
+#{sanitize_name(@updated_by_user.name)} pushed new commits to merge request #{@merge_request.to_reference}
\
#{url_for(project_merge_request_url(@merge_request.target_project, @merge_request))}
\
diff --git a/app/views/notify/reassigned_issue_email.html.haml b/app/views/notify/reassigned_issue_email.html.haml
index ee2f40e1683..6d25488a7e2 100644
--- a/app/views/notify/reassigned_issue_email.html.haml
+++ b/app/views/notify/reassigned_issue_email.html.haml
@@ -2,7 +2,7 @@
Assignee changed
- if @previous_assignees.any?
from
- %strong= @previous_assignees.map(&:name).to_sentence
+ %strong= sanitize_name(@previous_assignees.map(&:name).to_sentence)
to
- if @issue.assignees.any?
%strong= @issue.assignee_list
diff --git a/app/views/notify/reassigned_issue_email.text.erb b/app/views/notify/reassigned_issue_email.text.erb
index 6c357f1074a..7bf2e8e6ce3 100644
--- a/app/views/notify/reassigned_issue_email.text.erb
+++ b/app/views/notify/reassigned_issue_email.text.erb
@@ -2,5 +2,5 @@ Reassigned Issue <%= @issue.iid %>
<%= url_for([@issue.project.namespace.becomes(Namespace), @issue.project, @issue, { only_path: false }]) %>
-Assignee changed <%= "from #{@previous_assignees.map(&:name).to_sentence}" if @previous_assignees.any? -%>
+Assignee changed <%= "from #{sanitize_name(@previous_assignees.map(&:name).to_sentence)}" if @previous_assignees.any? -%>
to <%= "#{@issue.assignees.any? ? @issue.assignee_list : 'Unassigned'}" %>
diff --git a/app/views/notify/reassigned_merge_request_email.html.haml b/app/views/notify/reassigned_merge_request_email.html.haml
index 24c2b08810b..e4f19bc3200 100644
--- a/app/views/notify/reassigned_merge_request_email.html.haml
+++ b/app/views/notify/reassigned_merge_request_email.html.haml
@@ -2,9 +2,9 @@
Assignee changed
- if @previous_assignee
from
- %strong= @previous_assignee.name
+ %strong= sanitize_name(@previous_assignee.name)
to
- if @merge_request.assignee_id
- %strong= @merge_request.assignee_name
+ %strong= sanitize_name(@merge_request.assignee_name)
- else
%strong Unassigned
diff --git a/app/views/notify/reassigned_merge_request_email.text.erb b/app/views/notify/reassigned_merge_request_email.text.erb
index 998a40fefde..96c770b5219 100644
--- a/app/views/notify/reassigned_merge_request_email.text.erb
+++ b/app/views/notify/reassigned_merge_request_email.text.erb
@@ -2,5 +2,5 @@ Reassigned Merge Request <%= @merge_request.iid %>
<%= url_for([@merge_request.project.namespace.becomes(Namespace), @merge_request.project, @merge_request, { only_path: false }]) %>
-Assignee changed <%= "from #{@previous_assignee.name}" if @previous_assignee -%>
- to <%= "#{@merge_request.assignee_id ? @merge_request.assignee_name : 'Unassigned'}" %>
+Assignee changed <%= "from #{sanitize_name(@previous_assignee.name)}" if @previous_assignee -%>
+ to <%= "#{@merge_request.assignee_id ? sanitize_name(@merge_request.assignee_name) : 'Unassigned'}" %>
diff --git a/app/views/notify/resolved_all_discussions_email.html.haml b/app/views/notify/resolved_all_discussions_email.html.haml
index 522421b7cc3..502b8f21e35 100644
--- a/app/views/notify/resolved_all_discussions_email.html.haml
+++ b/app/views/notify/resolved_all_discussions_email.html.haml
@@ -1,2 +1,2 @@
%p
- All discussions on Merge Request #{@merge_request.to_reference} were resolved by #{@resolved_by.name}
+ All discussions on Merge Request #{@merge_request.to_reference} were resolved by #{sanitize_name(@resolved_by.name)}
diff --git a/app/views/notify/resolved_all_discussions_email.text.erb b/app/views/notify/resolved_all_discussions_email.text.erb
index 2881f3e699e..c4b36bfe1a8 100644
--- a/app/views/notify/resolved_all_discussions_email.text.erb
+++ b/app/views/notify/resolved_all_discussions_email.text.erb
@@ -1,3 +1,3 @@
-All discussions on Merge Request <%= @merge_request.to_reference %> were resolved by <%= @resolved_by.name %>
+All discussions on Merge Request <%= @merge_request.to_reference %> were resolved by <%= sanitize_name(@resolved_by.name) %>
<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index e167e094240..ee2c5a13b8a 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -1,37 +1,37 @@
-- page_title "Account"
+- page_title _('Account')
- @content_class = "limit-container-width" unless fluid_layout
- if current_user.ldap_user?
.alert.alert-info
- Some options are unavailable for LDAP accounts
+ = s_('Profiles|Some options are unavailable for LDAP accounts')
.row.prepend-top-default
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
- Two-Factor Authentication
+ = s_('Profiles|Two-Factor Authentication')
%p
- Increase your account's security by enabling Two-Factor Authentication (2FA).
+ = s_("Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)")
.col-lg-8
%p
- Status: #{current_user.two_factor_enabled? ? 'Enabled' : 'Disabled'}
+ #{_('Status')}: #{current_user.two_factor_enabled? ? _('Enabled') : _('Disabled')}
- if current_user.two_factor_enabled?
- = link_to 'Manage two-factor authentication', profile_two_factor_auth_path, class: 'btn btn-info'
+ = link_to _('Manage two-factor authentication'), profile_two_factor_auth_path, class: 'btn btn-info'
- else
.append-bottom-10
- = link_to 'Enable two-factor authentication', profile_two_factor_auth_path, class: 'btn btn-success'
+ = link_to _('Enable two-factor authentication'), profile_two_factor_auth_path, class: 'btn btn-success'
%hr
- if display_providers_on_profile?
.row.prepend-top-default
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
- Social sign-in
+ = s_('Profiles|Social sign-in')
%p
- Activate signin with one of the following services
+ = s_('Profiles|Activate signin with one of the following services')
.col-lg-8
%label.label-bold
- Connected Accounts
- %p Click on icon to activate signin with one of the following services
+ = s_('Profiles|Connected Accounts')
+ %p= s_('Profiles|Click on icon to activate signin with one of the following services')
- button_based_providers.each do |provider|
.provider-btn-group
.provider-btn-image
@@ -39,24 +39,24 @@
- if auth_active?(provider)
- if unlink_allowed?(provider)
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'provider-btn' do
- Disconnect
+ = s_('Profiles|Disconnect')
- else
%a.provider-btn
- Active
+ = s_('Profiles|Active')
- else
= link_to omniauth_authorize_path(:user, provider), method: :post, class: 'provider-btn not-active' do
- Connect
+ = s_('Profiles|Connect')
= render_if_exists 'profiles/accounts/group_saml_unlink_buttons', group_saml_identities: local_assigns[:group_saml_identities]
%hr
- if current_user.can_change_username?
.row.prepend-top-default
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0.warning-title
- Change username
+ = s_('Profiles|Change username')
%p
- Changing your username can have unintended side effects.
+ = s_('Profiles|Changing your username can have unintended side effects.')
= succeed '.' do
- = link_to 'Learn more', help_page_path('user/profile/index', anchor: 'changing-your-username'), target: '_blank'
+ = link_to s_('Profiles|Learn more'), help_page_path('user/profile/index', anchor: 'changing-your-username'), target: '_blank'
.col-lg-8
- data = { initial_username: current_user.username, root_url: root_url, action_url: update_username_profile_path(format: :json) }
#update-username{ data: data }
diff --git a/app/views/profiles/active_sessions/_active_session.html.haml b/app/views/profiles/active_sessions/_active_session.html.haml
index 23ef31a0c85..2bf514d72a5 100644
--- a/app/views/profiles/active_sessions/_active_session.html.haml
+++ b/app/views/profiles/active_sessions/_active_session.html.haml
@@ -23,9 +23,3 @@
%strong Signed in
on
= l(active_session.created_at, format: :short)
-
- - unless is_current_session
- .float-right
- = link_to profile_active_session_path(active_session.session_id), data: { confirm: 'Are you sure? The device will be signed out of GitLab.' }, method: :delete, class: "btn btn-danger prepend-left-10" do
- %span.sr-only Revoke
- Revoke
diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml
index d265f3c44ba..4b84835429c 100644
--- a/app/views/profiles/passwords/new.html.haml
+++ b/app/views/profiles/passwords/new.html.haml
@@ -1,12 +1,13 @@
-- page_title "New Password"
-- header_title "New Password"
-%h3.page-title Set up new password
+- page_title _('New Password')
+- breadcrumb_title _('New Password')
+
+%h3.page-title= _('Set up new password')
%hr
= form_for @user, url: profile_password_path, method: :post do |f|
%p.slead
- Please set a new password before proceeding.
+ = _('Please set a new password before proceeding.')
%br
- After a successful password update you will be redirected to login screen.
+ = _('After a successful password update you will be redirected to login screen.')
= form_errors(@user)
@@ -22,4 +23,4 @@
.col-sm-10
= f.password_field :password_confirmation, required: true, class: 'form-control'
.form-actions
- = f.submit 'Set new password', class: "btn btn-success"
+ = f.submit _('Set new password'), class: 'btn btn-success'
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 7c378633667..bfe1c3ddf33 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -51,11 +51,36 @@
= f.label :dashboard, class: 'label-bold' do
Default dashboard
= f.select :dashboard, dashboard_choices, {}, class: 'form-control'
+
+ = render_if_exists 'profiles/preferences/group_overview_selector', f: f # EE-specific
+
.form-group
= f.label :project_view, class: 'label-bold' do
Project overview content
= f.select :project_view, project_view_choices, {}, class: 'form-control'
.form-text.text-muted
Choose what content you want to see on a project’s overview page.
+
+ .col-sm-12
+ %hr
+
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0
+ = _('Localization')
+ %p
+ = _('Customize language and region related settings.')
+ = succeed '.' do
+ = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'localization'), target: '_blank'
+ .col-lg-8
+ .form-group
+ = f.label :preferred_language, class: 'label-bold' do
+ = _('Language')
+ = f.select :preferred_language, language_choices, {}, class: 'select2'
+ .form-text.text-muted
+ = s_('Preferences|This feature is experimental and translations are not complete yet')
+ .form-group
+ = f.label :first_day_of_week, class: 'label-bold' do
+ = _('First day of the week')
+ = f.select :first_day_of_week, first_day_of_week_choices_with_default, {}, class: 'form-control'
.form-group
- = f.submit 'Save changes', class: 'btn btn-success'
+ = f.submit _('Save changes'), class: 'btn btn-success'
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 2629b374e7c..4d3d92d09c0 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -2,7 +2,7 @@
- @content_class = "limit-container-width" unless fluid_layout
- gravatar_link = link_to Gitlab.config.gravatar.host, 'https://' + Gitlab.config.gravatar.host
-= bootstrap_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user prepend-top-default js-quick-submit' }, authenticity_token: true do |f|
+= bootstrap_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user prepend-top-default js-quick-submit gl-show-field-errors' }, authenticity_token: true do |f|
= form_errors(@user)
.row
@@ -77,10 +77,10 @@
.col-lg-8
.row
- if @user.read_only_attribute?(:name)
- = f.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9' },
+ = f.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name' },
help: s_("Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you") % { provider_label: attribute_provider_label(:name) }
- else
- = f.text_field :name, label: 'Full name', required: true, wrapper: { class: 'col-md-9' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
+ = f.text_field :name, label: 'Full name', required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
= f.text_field :id, readonly: true, label: 'User ID', wrapper: { class: 'col-md-3' }
- if @user.read_only_attribute?(:email)
@@ -95,9 +95,6 @@
= f.select :commit_email, options_for_select(commit_email_select_options(@user), selected: selected_commit_email(@user)),
{ help: s_("Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}").html_safe % { learn_more: commit_email_docs_link } },
control_class: 'select2 input-lg'
- = f.select :preferred_language, Gitlab::I18n::AVAILABLE_LANGUAGES.map { |value, label| [label, value] },
- { help: s_("Profiles|This feature is experimental and translations are not complete yet") },
- control_class: 'select2 input-lg'
= f.text_field :skype, class: 'input-md', placeholder: s_("Profiles|username")
= f.text_field :linkedin, class: 'input-md', help: s_("Profiles|Your LinkedIn profile name from linkedin.com/in/profilename")
= f.text_field :twitter, class: 'input-md', placeholder: s_("Profiles|@username")
diff --git a/app/views/projects/_activity.html.haml b/app/views/projects/_activity.html.haml
index 6bf21570d41..12da62f4c64 100644
--- a/app/views/projects/_activity.html.haml
+++ b/app/views/projects/_activity.html.haml
@@ -1,8 +1,8 @@
%div{ class: container_class }
- .nav-block.activity-filter-block.activities
+ .nav-block.d-none.d-sm-flex.activities
= render 'shared/event_filter'
.controls
- = link_to project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: 'btn rss-btn has-tooltip' do
+ = link_to project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: 'btn d-none d-sm-inline-block has-tooltip' do
= icon('rss')
.content_list.project-activity{ :"data-href" => activity_project_path(@project) }
diff --git a/app/views/projects/_export.html.haml b/app/views/projects/_export.html.haml
index aa980da7e95..409b6dba9ca 100644
--- a/app/views/projects/_export.html.haml
+++ b/app/views/projects/_export.html.haml
@@ -19,7 +19,7 @@
%ul
%li Project and wiki repositories
%li Project uploads
- %li Project configuration including web hooks and services
+ %li Project configuration, including services
%li Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities
%li LFS objects
%p
@@ -28,13 +28,14 @@
%li Job traces and artifacts
%li Container registry images
%li CI variables
+ %li Webhooks
%li Any encrypted tokens
%p
Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page.
- if project.export_status == :finished
- = link_to 'Download export', download_export_project_path(project),
+ = link_to 'Download export', download_export_project_path(project),
rel: 'nofollow', download: '', method: :get, class: "btn btn-default"
- = link_to 'Generate new export', generate_new_export_project_path(project),
+ = link_to 'Generate new export', generate_new_export_project_path(project),
method: :post, class: "btn btn-default"
- else
= link_to 'Export project', export_project_path(project),
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 82b2ab64a5d..1d7287410ea 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -1,17 +1,18 @@
- empty_repo = @project.empty_repo?
- show_auto_devops_callout = show_auto_devops_callout?(@project)
+- max_project_topic_length = 15
.project-home-panel{ class: ("empty-project" if empty_repo) }
- .project-header.row.append-bottom-8
- .project-title-row.col-md-12.col-lg-6.d-flex
- .avatar-container.project-avatar.float-none
+ .row.append-bottom-8
+ .home-panel-title-row.col-md-12.col-lg-6.d-flex
+ .avatar-container.rect-avatar.s64.home-panel-avatar.append-right-default.float-none
= project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64)
.d-flex.flex-column.flex-wrap.align-items-baseline
.d-inline-flex.align-items-baseline
- %h1.project-title.qa-project-name
+ %h1.home-panel-title.prepend-top-8.append-bottom-5.qa-project-name
= @project.name
- %span.project-visibility.prepend-left-8.d-inline-flex.align-items-baseline.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
+ %span.visibility-icon.text-secondary.prepend-left-4.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
= visibility_level_icon(@project.visibility_level, fw: false, options: {class: 'icon'})
- .project-metadata.d-flex.align-items-center
+ .home-panel-metadata.d-flex.align-items-center.text-secondary
- if can?(current_user, :read_project, @project)
%span.text-secondary
= s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
@@ -19,16 +20,28 @@
%span.access-request-links.prepend-left-8
= render 'shared/members/access_request_links', source: @project
- if @project.tag_list.present?
- %span.project-tag-list.d-inline-flex.prepend-left-8.has-tooltip{ data: { container: 'body' }, title: @project.has_extra_tags? ? @project.tag_list.join(', ') : nil }
+ %span.home-panel-topic-list.d-inline-flex.prepend-left-8
= sprite_icon('tag', size: 16, css_class: 'icon append-right-4')
- = @project.tags_to_show
- - if @project.has_extra_tags?
- = _("+ %{count} more") % { count: @project.count_of_extra_tags_not_shown }
+
+ - @project.topics_to_show.each do |topic|
+ - project_topics_classes = "badge badge-pill badge-secondary append-right-5"
+ - explore_project_topic_path = explore_projects_path(tag: topic)
+ - if topic.length > max_project_topic_length
+ %a{ class: "#{ project_topics_classes } str-truncated-30 has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path }
+ = topic.titleize
+ - else
+ %a{ class: project_topics_classes, href: explore_project_topic_path }
+ = topic.titleize
+
+ - if @project.has_extra_topics?
+ .text-nowrap.has-tooltip{ data: { container: 'body' }, title: @project.has_extra_topics? ? @project.topics_not_shown.join(', ') : nil }
+ = _("+ %{count} more") % { count: @project.count_of_extra_topics_not_shown }
+
.project-repo-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end
- if current_user
.d-inline-flex
- = render 'projects/buttons/notifications', notification_setting: @notification_setting, btn_class: 'btn-xs'
+ = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn-xs'
.count-buttons.d-inline-flex
= render 'projects/buttons/star'
@@ -43,13 +56,13 @@
- if can?(current_user, :download_code, @project)
%nav.project-stats
- .nav-links.quick-links.mt-3
+ .nav-links.quick-links
= render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
- .project-home-desc.mt-1
+ .home-panel-home-desc.mt-1
- if @project.description.present?
- .project-description
- .project-description-markdown.read-more-container
+ .home-panel-description
+ .home-panel-description-markdown.read-more-container
= markdown_field(@project, :description)
%button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
= _("Read more")
diff --git a/app/views/projects/_issuable_by_email.html.haml b/app/views/projects/_issuable_by_email.html.haml
index d59191a6f87..0b2d179456d 100644
--- a/app/views/projects/_issuable_by_email.html.haml
+++ b/app/views/projects/_issuable_by_email.html.haml
@@ -21,7 +21,7 @@
= clipboard_button(target: '#issuable_email', class: 'btn btn-clipboard input-group-text btn-transparent d-none d-sm-block')
- if issuable_type == 'issue'
- - enter_title_text = _('Enter the issue title')
+ - enter_title_text = _('Enter the issue title')
- enter_description_text = _('Enter the issue description')
- else
- enter_title_text = _('Enter the merge request title')
@@ -36,7 +36,12 @@
%p
= render 'by_email_description'
%p
- This is a private email address, generated just for you.
+ This is a private email address
+
+ %a{ href: 'https://docs.gitlab.com/ee/development/emails.html#email-namespace', target: "_blank", rel: "noopener" }
+ %i.fa.fa-question-circle{ 'aria-label': "Learn more about incoming email addresses" }
+
+ generated just for you.
Anyone who gets ahold of it can create issues or merge requests as if they were you.
You should
diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml
index 0f709c65d0e..830cfa80d58 100644
--- a/app/views/projects/_md_preview.html.haml
+++ b/app/views/projects/_md_preview.html.haml
@@ -12,23 +12,13 @@
%ul.nav.nav-tabs.nav-links.clearfix
%li.md-header-tab.active
%button.js-md-write-button{ tabindex: -1 }
- Write
+ = _("Write")
%li.md-header-tab
%button.js-md-preview-button{ tabindex: -1 }
- Preview
+ = _("Preview")
%li.md-header-toolbar.active
- = markdown_toolbar_button({ icon: "bold", data: { "md-tag" => "**" }, title: s_("MarkdownToolbar|Add bold text") })
- = markdown_toolbar_button({ icon: "italic", data: { "md-tag" => "*" }, title: s_("MarkdownToolbar|Add italic text") })
- = markdown_toolbar_button({ icon: "quote", data: { "md-tag" => "> ", "md-prepend" => true }, title: s_("MarkdownToolbar|Insert a quote") })
- = markdown_toolbar_button({ icon: "code", data: { "md-tag" => "`", "md-block" => "```" }, title: s_("MarkdownToolbar|Insert code") })
- = markdown_toolbar_button({ icon: "link", data: { "md-tag" => "[{text}](url)", "md-select" => "url" }, title: s_("MarkdownToolbar|Add a link") })
- = markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "* ", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a bullet list") })
- = markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a numbered list") })
- = markdown_toolbar_button({ icon: "task-done", data: { "md-tag" => "* [ ] ", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a task list") })
- = markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a table") })
- %button.toolbar-btn.toolbar-fullscreen-btn.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, "aria-label": "Go full screen", title: s_("MarkdownToolbar|Go full screen"), data: { container: "body" } }
- = sprite_icon("screen-full")
+ = render 'projects/blob/markdown_buttons', show_fullscreen_button: true
.md-write-holder
= yield
diff --git a/app/views/projects/_merge_request_merge_settings.html.haml b/app/views/projects/_merge_request_merge_settings.html.haml
index f178c94e008..6ac2e06afa5 100644
--- a/app/views/projects/_merge_request_merge_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_settings.html.haml
@@ -9,6 +9,7 @@
%span.descr
Pipelines need to be configured to enable this feature.
= link_to icon('question-circle'), help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds', anchor: 'only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds'), target: '_blank'
+ = render_if_exists 'projects/merge_pipelines_settings', form: form
.form-check
= form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input'
= form.label :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-label' do
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index ba7d3154326..276363df7da 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -43,7 +43,7 @@
= f.label :description, class: 'label-bold' do
Project description
%span (optional)
- = f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250, data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_description", track_value: "" }
+ = f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250, data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_description", track_value: "" }
= f.label :visibility_level, class: 'label-bold' do
Visibility Level
diff --git a/app/views/projects/_wiki.html.haml b/app/views/projects/_wiki.html.haml
index 45e1d32980c..de4653dad2c 100644
--- a/app/views/projects/_wiki.html.haml
+++ b/app/views/projects/_wiki.html.haml
@@ -2,7 +2,7 @@
%div{ class: container_class }
.prepend-top-default.append-bottom-default
.wiki
- = render_wiki_content(@wiki_home, legacy_render_context(params))
+ = render_wiki_content(@wiki_home)
- else
- can_create_wiki = can?(current_user, :create_wiki, @project)
.landing{ class: [('row-content-block row p-0 align-items-center' if can_create_wiki), ('content-block' unless can_create_wiki)] }
diff --git a/app/views/projects/artifacts/_tree_file.html.haml b/app/views/projects/artifacts/_tree_file.html.haml
index cfb91568061..f42d5128715 100644
--- a/app/views/projects/artifacts/_tree_file.html.haml
+++ b/app/views/projects/artifacts/_tree_file.html.haml
@@ -14,4 +14,4 @@
= link_to path_to_file, class: 'str-truncated' do
%span= blob.name
%td
- = number_to_human_size(blob.size, precision: 2)
+ = number_to_human_size(blob.size)
diff --git a/app/views/projects/badges/badge_flat-square.svg.erb b/app/views/projects/badges/badge_flat-square.svg.erb
new file mode 100644
index 00000000000..5b90da15ef5
--- /dev/null
+++ b/app/views/projects/badges/badge_flat-square.svg.erb
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="<%= badge.width %>" height="20">
+ <g shape-rendering="crispEdges">
+ <path fill="<%= badge.key_color %>" d="M0 0 h<%= badge.key_width %> v20 H0 z"/>
+ <path fill="<%= badge.value_color %>" d="M<%= badge.key_width %> 0 h<%= badge.value_width %> v20 H<%= badge.key_width %> z"/>
+ </g>
+
+ <g fill="#fff" text-anchor="middle">
+ <g font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
+ <text x="<%= badge.key_text_anchor %>" y="14">
+ <%= badge.key_text %>
+ </text>
+ <text x="<%= badge.value_text_anchor %>" y="14">
+ <%= badge.value_text %>
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 3c1f33ea95e..a54460f1196 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -1,4 +1,6 @@
- action = current_action?(:edit) || current_action?(:update) ? 'edit' : 'create'
+- file_name = params[:id].split("/").last ||= ""
+- is_markdown = Gitlab::MarkupHelper.gitlab_markdown?(file_name)
.file-holder-bottom-radius.file-holder.file.append-bottom-default
.js-file-title.file-title.clearfix{ data: { current_action: action } }
@@ -17,6 +19,8 @@
required: true, class: 'form-control new-file-name js-file-path-name-input'
.file-buttons
+ - if is_markdown
+ = render 'projects/blob/markdown_buttons', show_fullscreen_button: false
= button_tag class: 'soft-wrap-toggle btn', type: 'button', tabindex: '-1' do
%span.no-wrap
= custom_icon('icon_no_wrap')
diff --git a/app/views/projects/blob/_markdown_buttons.html.haml b/app/views/projects/blob/_markdown_buttons.html.haml
new file mode 100644
index 00000000000..28d1ff97825
--- /dev/null
+++ b/app/views/projects/blob/_markdown_buttons.html.haml
@@ -0,0 +1,13 @@
+.md-header-toolbar.active
+ = markdown_toolbar_button({ icon: "bold", data: { "md-tag" => "**" }, title: _("Add bold text") })
+ = markdown_toolbar_button({ icon: "italic", data: { "md-tag" => "*" }, title: _("Add italic text") })
+ = markdown_toolbar_button({ icon: "quote", data: { "md-tag" => "> ", "md-prepend" => true }, title: _("Insert a quote") })
+ = markdown_toolbar_button({ icon: "code", data: { "md-tag" => "`", "md-block" => "```" }, title: _("Insert code") })
+ = markdown_toolbar_button({ icon: "link", data: { "md-tag" => "[{text}](url)", "md-select" => "url" }, title: _("Add a link") })
+ = 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: "task-done", data: { "md-tag" => "* [ ] ", "md-prepend" => true }, title: _("Add a task list") })
+ = markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |", "md-prepend" => true }, title: _("Add a table") })
+ - if show_fullscreen_button
+ %button.toolbar-btn.toolbar-fullscreen-btn.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, "aria-label": "Go full screen", title: _("Go full screen"), data: { container: "body" } }
+ = sprite_icon("screen-full")
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index 3f2d96b70e5..4520cca8cf5 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -21,7 +21,7 @@
Write
%li
- = link_to '#preview', 'data-preview-url' => project_preview_blob_path(@project, @id, legacy_render: params[:legacy_render]) do
+ = link_to '#preview', 'data-preview-url' => project_preview_blob_path(@project, @id) do
= editing_preview_title(@blob.name)
= form_tag(project_update_blob_path(@project, @id), method: :put, class: 'js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths(@project)) do
diff --git a/app/views/projects/blob/preview.html.haml b/app/views/projects/blob/preview.html.haml
index ff460a3831c..66687f087ff 100644
--- a/app/views/projects/blob/preview.html.haml
+++ b/app/views/projects/blob/preview.html.haml
@@ -2,7 +2,7 @@
.diff-content
- if markup?(@blob.name)
.file-content.wiki.md{ class: ('use-csslab' if Feature.enabled?(:csslab)) }
- = markup(@blob.name, @content, legacy_render_context(params))
+ = markup(@blob.name, @content)
- else
.file-content.code.js-syntax-highlight
- unless @diff_lines.empty?
diff --git a/app/views/projects/blob/viewers/_dependency_manager.html.haml b/app/views/projects/blob/viewers/_dependency_manager.html.haml
index 87aa7c1dbf8..5970d41fdab 100644
--- a/app/views/projects/blob/viewers/_dependency_manager.html.haml
+++ b/app/views/projects/blob/viewers/_dependency_manager.html.haml
@@ -3,9 +3,4 @@
This project manages its dependencies using
%strong= viewer.manager_name
- - if viewer.package_name
- and defines a #{viewer.package_type} named
- %strong<
- = link_to_if viewer.package_url.present?, viewer.package_name, viewer.package_url, target: '_blank', rel: 'noopener noreferrer'
-
= link_to 'Learn more', viewer.manager_url, target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
index 5be7cc7f25a..61d67a88a5a 100644
--- a/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
+++ b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
@@ -1,9 +1,9 @@
-- if viewer.valid?(@project, @commit.sha)
+- if viewer.valid?(project: @project, sha: @commit.sha, user: @current_user)
= icon('check fw')
This GitLab CI configuration is valid.
- else
= icon('warning fw')
This GitLab CI configuration is invalid:
- = viewer.validation_message(@project, @commit.sha)
+ = viewer.validation_message(project: @project, sha: @commit.sha, user: @current_user)
= link_to 'Learn more', help_page_path('ci/yaml/README')
diff --git a/app/views/projects/blob/viewers/_loading.html.haml b/app/views/projects/blob/viewers/_loading.html.haml
index 120c0540335..df1f3e4e01b 100644
--- a/app/views/projects/blob/viewers/_loading.html.haml
+++ b/app/views/projects/blob/viewers/_loading.html.haml
@@ -1,2 +1,2 @@
.text-center.prepend-top-default.append-bottom-default
- = icon('spinner spin 2x', 'aria-hidden' => 'true', 'aria-label' => 'Loading content…')
+ = icon('spinner spin 2x', 'aria-hidden' => 'true', 'aria-label' => 'Loading content…', class: 'qa-spinner')
diff --git a/app/views/projects/blob/viewers/_markup.html.haml b/app/views/projects/blob/viewers/_markup.html.haml
index 6edbfd91b21..1a77eb078be 100644
--- a/app/views/projects/blob/viewers/_markup.html.haml
+++ b/app/views/projects/blob/viewers/_markup.html.haml
@@ -1,6 +1,4 @@
- blob = viewer.blob
-- context = legacy_render_context(params)
-- unless context[:markdown_engine] == :redcarpet
- - context[:rendered] = blob.rendered_markup if blob.respond_to?(:rendered_markup)
+- context = blob.respond_to?(:rendered_markup) ? { rendered: blob.rendered_markup } : {}
.file-content.wiki.md{ class: ('use-csslab' if Feature.enabled?(:csslab)) }
= markup(blob.name, blob.data, context)
diff --git a/app/views/projects/blob/viewers/_readme.html.haml b/app/views/projects/blob/viewers/_readme.html.haml
index d8492abc638..c2329a7aa66 100644
--- a/app/views/projects/blob/viewers/_readme.html.haml
+++ b/app/views/projects/blob/viewers/_readme.html.haml
@@ -1,4 +1,4 @@
= icon('info-circle fw')
= succeed '.' do
To learn more about this project, read
- = link_to "the wiki", get_project_wiki_path(viewer.project)
+ = link_to "the wiki", project_wiki_path(viewer.project, :home)
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 88f9b7dfc9f..91c51d5e091 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -2,6 +2,7 @@
- commit = @repository.commit(branch.dereferenced_target)
- bar_graph_width_factor = @max_commits > 0 ? 100.0/@max_commits : 0
- diverging_commit_counts = @repository.diverging_commit_counts(branch)
+- number_commits_distance = diverging_commit_counts[:distance]
- number_commits_behind = diverging_commit_counts[:behind]
- number_commits_ahead = diverging_commit_counts[:ahead]
- merge_project = merge_request_source_project_for_project(@project)
@@ -28,16 +29,23 @@
= s_('Branches|Cant find HEAD commit for this branch')
- if branch.name != @repository.root_ref
- .divergence-graph.d-none.d-md-block{ title: s_('%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead') % { number_commits_behind: diverging_count_label(number_commits_behind),
- default_branch: @repository.root_ref,
- number_commits_ahead: diverging_count_label(number_commits_ahead) } }
- .graph-side
- .bar.bar-behind{ style: "width: #{number_commits_behind * bar_graph_width_factor}%" }
- %span.count.count-behind= diverging_count_label(number_commits_behind)
- .graph-separator
- .graph-side
- .bar.bar-ahead{ style: "width: #{number_commits_ahead * bar_graph_width_factor}%" }
- %span.count.count-ahead= diverging_count_label(number_commits_ahead)
+ - if number_commits_distance.nil?
+ .divergence-graph.d-none.d-md-block{ title: s_('%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead') % { number_commits_behind: diverging_count_label(number_commits_behind),
+ default_branch: @repository.root_ref,
+ number_commits_ahead: diverging_count_label(number_commits_ahead) } }
+ .graph-side
+ .bar.bar-behind{ style: "width: #{number_commits_behind * bar_graph_width_factor}%" }
+ %span.count.count-behind= diverging_count_label(number_commits_behind)
+ .graph-separator
+ .graph-side
+ .bar.bar-ahead{ style: "width: #{number_commits_ahead * bar_graph_width_factor}%" }
+ %span.count.count-ahead= diverging_count_label(number_commits_ahead)
+ - else
+ .divergence-graph.d-none.d-md-block{ title: s_('More than %{number_commits_distance} commits different with %{default_branch}') % { number_commits_distance: diverging_count_label(number_commits_distance),
+ default_branch: @repository.root_ref} }
+ .graph-side.full
+ .bar{ style: "width: #{number_commits_distance * bar_graph_width_factor}%" }
+ %span.count= diverging_count_label(number_commits_distance)
.controls.d-none.d-md-block<
- if merge_project && create_mr_button?(@repository.root_ref, branch.name)
@@ -45,9 +53,8 @@
= _('Merge request')
- if branch.name != @repository.root_ref
- = link_to project_compare_index_path(@project, from: @repository.root_ref, to: branch.name),
+ = link_to project_compare_path(@project, @repository.root_ref, branch.name),
class: "btn btn-default #{'prepend-left-10' unless merge_project}",
- method: :post,
title: s_('Branches|Compare') do
= s_('Branches|Compare')
@@ -76,7 +83,7 @@
= icon("trash-o")
- else
= link_to project_branch_path(@project, branch.name),
- class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
+ class: "btn btn-remove remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip",
title: s_('Branches|Delete branch'),
method: :delete,
data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
diff --git a/app/views/projects/branches/_panel.html.haml b/app/views/projects/branches/_panel.html.haml
index 0e4b119bb54..93061452e12 100644
--- a/app/views/projects/branches/_panel.html.haml
+++ b/app/views/projects/branches/_panel.html.haml
@@ -10,7 +10,7 @@
.card.prepend-top-10
.card-header
= panel_title
- %ul.content-list.all-branches
+ %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)
- if branches.size > overview_max_branches
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index ca867961f6b..43f1cd01b67 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -35,7 +35,7 @@
- if can? current_user, :push_code, @project
= link_to project_merged_branches_path(@project),
- class: 'btn btn-inverted btn-remove has-tooltip',
+ class: 'btn btn-inverted btn-remove has-tooltip qa-delete-merged-branches',
title: s_("Branches|Delete all branches that are merged into '%{default_branch}'") % { default_branch: @project.repository.root_ref },
method: :delete,
data: { confirm: s_('Branches|Deleting the merged branches cannot be undone. Are you sure?'),
diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml
index 53d427ec40a..09f05b30433 100644
--- a/app/views/projects/buttons/_clone.html.haml
+++ b/app/views/projects/buttons/_clone.html.haml
@@ -5,18 +5,18 @@
%span.append-right-4.js-clone-dropdown-label
= _('Clone')
= sprite_icon("arrow-down", css_class: "icon")
- %form.p-3.dropdown-menu.dropdown-menu-right.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options
- - if ssh_enabled?
- %li.pb-2
- %label.label-bold
- = _('Clone with SSH')
- .input-group
- = text_field_tag :ssh_project_clone, project.ssh_url_to_repo, class: "js-select-on-focus form-control qa-ssh-clone-url", readonly: true, aria: { label: 'Project clone URL' }
- .input-group-append
- = clipboard_button(target: '#ssh_project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard")
- = render_if_exists 'projects/buttons/geo'
- %li
- - if http_enabled?
+ %ul.p-3.dropdown-menu.dropdown-menu-right.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options
+ - if ssh_enabled?
+ %li
+ %label.label-bold
+ = _('Clone with SSH')
+ .input-group
+ = text_field_tag :ssh_project_clone, project.ssh_url_to_repo, class: "js-select-on-focus form-control qa-ssh-clone-url", readonly: true, aria: { label: 'Project clone URL' }
+ .input-group-append
+ = clipboard_button(target: '#ssh_project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard")
+ = render_if_exists 'projects/buttons/geo'
+ - if http_enabled?
+ %li.pt-2
%label.label-bold
= _('Clone with %{http_label}') % { http_label: gitlab_config.protocol.upcase }
.input-group
@@ -24,5 +24,6 @@
.input-group-append
= clipboard_button(target: '#http_project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard")
= render_if_exists 'projects/buttons/geo'
+ = render_if_exists 'projects/buttons/kerberos_clone_field'
= render_if_exists 'shared/geo_info_modal', project: project
diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml
index 45515fb492f..bbe0a2c97fd 100644
--- a/app/views/projects/buttons/_dropdown.html.haml
+++ b/app/views/projects/buttons/_dropdown.html.haml
@@ -35,8 +35,8 @@
- elsif can_collaborate_with_project?(@project)
%li= link_to _('New file'), project_new_blob_path(@project, @project.default_branch || 'master')
- elsif create_mr_from_new_fork
- - continue_params = { to: project_new_blob_path(@project, @project.default_branch || 'master'),
- notice: edit_in_new_fork_notice,
+ - continue_params = { to: project_new_blob_path(@project, @project.default_branch || 'master'),
+ notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now }
- fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
%li= link_to _('New file'), fork_path, method: :post
diff --git a/app/views/projects/buttons/_notifications.html.haml b/app/views/projects/buttons/_notifications.html.haml
deleted file mode 100644
index 745983ace7e..00000000000
--- a/app/views/projects/buttons/_notifications.html.haml
+++ /dev/null
@@ -1,27 +0,0 @@
-- btn_class = local_assigns.fetch(:btn_class, "btn-xs")
-
-- if notification_setting
- .js-notification-dropdown.notification-dropdown.project-action-button.dropdown.inline
- = form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f|
- = hidden_setting_source_input(notification_setting)
- = hidden_field_tag "hide_label", true
- = f.hidden_field :level, class: "notification_setting_level"
- .js-notification-toggle-btns
- %div{ class: ("btn-group" if notification_setting.custom?) }
- - if notification_setting.custom?
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
- = sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
- %span.js-notification-loading.fa.hidden
- %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
- = sprite_icon("arrow-down", css_class: "icon")
- .sr-only Toggle dropdown
- - else
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting - #{notification_title(notification_setting.level)}", class: "#{btn_class}", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
- = sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
- %span.js-notification-loading.fa.hidden
- = sprite_icon("arrow-down", css_class: "icon")
-
- = render "shared/notifications/notification_dropdown", notification_setting: notification_setting
-
- = content_for :scripts_body do
- = render "shared/notifications/custom_notifications", notification_setting: notification_setting
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 44e9cb84341..9d069c025ba 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -25,7 +25,7 @@
= job.tag? ? icon('tag') : sprite_icon('fork', css_class: 'sprite')
= link_to job.ref, project_ref_path(job.project, job.ref), class: "ref-name"
- else
- .light none
+ .light= _('none')
.icon-container.commit-icon
= custom_icon("icon_commit")
@@ -33,10 +33,10 @@
= link_to job.short_sha, project_commit_path(job.project, job.sha), class: "commit-sha"
- if job.stuck?
- = icon('warning', class: 'text-warning has-tooltip', title: 'Job is stuck. Check runners.')
+ = icon('warning', class: 'text-warning has-tooltip', title: _('Job is stuck. Check runners.'))
- if retried
- = icon('refresh', class: 'text-warning has-tooltip', title: 'Job was retried')
+ = icon('refresh', class: 'text-warning has-tooltip', title: _('Job was retried'))
.label-container
- if job.tags.any?
@@ -44,13 +44,13 @@
%span.badge.badge-primary
= tag
- if job.try(:trigger_request)
- %span.badge.badge-info triggered
+ %span.badge.badge-info= _('triggered')
- if job.try(:allow_failure)
- %span.badge.badge-danger allowed to fail
+ %span.badge.badge-danger= _('allowed to fail')
- if job.schedulable?
%span.badge.badge-info= s_('DelayedJobs|delayed')
- elsif job.action?
- %span.badge.badge-info manual
+ %span.badge.badge-info= _('manual')
- if pipeline_link
%td
@@ -70,7 +70,7 @@
- if job.try(:runner)
= runner_link(job.runner)
- else
- .light none
+ .light= _('none')
- if stage
%td
@@ -97,11 +97,11 @@
%td
.float-right
- if can?(current_user, :read_build, job) && job.artifacts?
- = link_to download_project_job_artifacts_path(job.project, job), rel: 'nofollow', download: '', title: 'Download artifacts', class: 'btn btn-build' do
+ = link_to download_project_job_artifacts_path(job.project, job), rel: 'nofollow', download: '', title: _('Download artifacts'), class: 'btn btn-build' do
= sprite_icon('download')
- if can?(current_user, :update_build, job)
- if job.active?
- = link_to cancel_project_job_path(job.project, job, continue: { to: request.fullpath }), method: :post, title: 'Cancel', class: 'btn btn-build' do
+ = link_to cancel_project_job_path(job.project, job, continue: { to: request.fullpath }), method: :post, title: _('Cancel'), class: 'btn btn-build' do
= icon('remove', class: 'cred')
- elsif job.scheduled?
.btn-group
@@ -123,8 +123,8 @@
= sprite_icon('time-out')
- elsif allow_retry
- if job.playable? && !admin && can?(current_user, :update_build, job)
- = link_to play_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: 'Play', class: 'btn btn-build' do
+ = link_to play_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: _('Play'), class: 'btn btn-build' do
= custom_icon('icon_play')
- elsif job.retryable?
- = link_to retry_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do
+ = link_to retry_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: _('Retry'), class: 'btn btn-build' do
= icon('repeat')
diff --git a/app/views/projects/ci/lints/_create.html.haml b/app/views/projects/ci/lints/_create.html.haml
index 30bf1384b22..59b5b9f8a30 100644
--- a/app/views/projects/ci/lints/_create.html.haml
+++ b/app/views/projects/ci/lints/_create.html.haml
@@ -1,45 +1,48 @@
- if @status
%p
- %b Status:
- syntax is correct
+ %b= _("Status:")
+ = _("syntax is correct")
%i.fa.fa-ok.correct-syntax
.table-holder
%table.table.table-bordered
%thead
%tr
- %th Parameter
- %th Value
+ %th= _("Parameter")
+ %th= _("Value")
%tbody
- @stages.each do |stage|
- @builds.select { |build| build[:stage] == stage }.each do |build|
+ - job = @jobs[build[:name].to_sym]
%tr
%td #{stage.capitalize} Job - #{build[:name]}
%td
- %pre= build[:commands]
+ %pre= job[:before_script].to_a.join('\n')
+ %pre= job[:script].to_a.join('\n')
+ %pre= job[:after_script].to_a.join('\n')
%br
- %b Tag list:
+ %b= _("Tag list:")
= build[:tag_list].to_a.join(", ")
%br
- %b Only policy:
- = @jobs[build[:name].to_sym][:only].to_a.join(", ")
+ %b= _("Only policy:")
+ = job[:only].to_a.join(", ")
%br
- %b Except policy:
- = @jobs[build[:name].to_sym][:except].to_a.join(", ")
+ %b= _("Except policy:")
+ = job[:except].to_a.join(", ")
%br
- %b Environment:
+ %b= _("Environment:")
= build[:environment]
%br
- %b When:
+ %b= _("When:")
= build[:when]
- if build[:allow_failure]
- %b Allowed to fail
+ %b= _("Allowed to fail")
- else
%p
- %b Status:
- syntax is incorrect
+ %b= _("Status:")
+ = _("syntax is incorrect")
%i.fa.fa-remove.incorrect-syntax
- %b Error:
+ %b= _("Error:")
= @error
diff --git a/app/views/projects/ci/lints/show.html.haml b/app/views/projects/ci/lints/show.html.haml
index cbda6bf2107..7b87664961e 100644
--- a/app/views/projects/ci/lints/show.html.haml
+++ b/app/views/projects/ci/lints/show.html.haml
@@ -1,9 +1,9 @@
-- page_title "CI Lint"
-- page_description "Validate your GitLab CI configuration file"
+- page_title _("CI Lint")
+- page_description _("Validate your GitLab CI configuration file")
- content_for :library_javascripts do
= page_specific_javascript_tag('lib/ace.js')
-%h2.pt-3.pb-3 Check your .gitlab-ci.yml
+%h2.pt-3.pb-3= _("Check your .gitlab-ci.yml")
.project-ci-linter
= form_tag project_ci_lint_path(@project), method: :post do
@@ -11,14 +11,14 @@
.col-sm-12
.file-holder
.js-file-title.file-title.clearfix
- Content of .gitlab-ci.yml
+ = _("Contents of .gitlab-ci.yml")
#ci-editor.ci-editor= @content
= text_area_tag(:content, @content, class: 'hidden form-control span1', rows: 7, require: true)
.col-sm-12
.float-left.prepend-top-10
- = submit_tag('Validate', class: 'btn btn-success submit-yml')
+ = submit_tag(_('Validate'), class: 'btn btn-success submit-yml')
.float-right.prepend-top-10
- = button_tag('Clear', type: 'button', class: 'btn btn-default clear-yml')
+ = button_tag(_('Clear'), type: 'button', class: 'btn btn-default clear-yml')
.row.prepend-top-20
.col-sm-12
diff --git a/app/views/projects/cleanup/_show.html.haml b/app/views/projects/cleanup/_show.html.haml
index cecc139b183..888be4ee282 100644
--- a/app/views/projects/cleanup/_show.html.haml
+++ b/app/views/projects/cleanup/_show.html.haml
@@ -24,6 +24,6 @@
= _("No file selected")
= f.file_field :bfg_object_map, accept: 'text/plain', class: "hidden js-object-map-input", required: true
.form-text.text-muted
- = _("The maximum file size allowed is %{max_attachment_size}mb") % { max_attachment_size: Gitlab::CurrentSettings.max_attachment_size }
+ = _("The maximum file size allowed is %{size}.") % { size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) }
= f.submit _('Start cleanup'), class: 'btn btn-success'
diff --git a/app/views/projects/commit/_ajax_signature.html.haml b/app/views/projects/commit/_ajax_signature.html.haml
index eb677cff5f0..ae9aef5a9b0 100644
--- a/app/views/projects/commit/_ajax_signature.html.haml
+++ b/app/views/projects/commit/_ajax_signature.html.haml
@@ -1,2 +1,2 @@
- if commit.has_signature?
- %a{ href: 'javascript:void(0)', tabindex: 0, class: commit_signature_badge_classes('js-loading-gpg-badge'), data: { toggle: 'tooltip', placement: 'top', title: 'GPG signature (loading...)', 'commit-sha' => commit.sha } }
+ %a{ href: 'javascript:void(0)', tabindex: 0, class: commit_signature_badge_classes('js-loading-gpg-badge'), data: { toggle: 'tooltip', placement: 'top', title: _('GPG signature (loading...)'), 'commit-sha' => commit.sha } }
diff --git a/app/views/projects/commit/_ci_menu.html.haml b/app/views/projects/commit/_ci_menu.html.haml
index f6666921a25..41f5fb3dcbd 100644
--- a/app/views/projects/commit/_ci_menu.html.haml
+++ b/app/views/projects/commit/_ci_menu.html.haml
@@ -1,10 +1,12 @@
+- any_pipelines = @commit.present(current_user: current_user).any_pipelines?
+
%ul.nav-links.no-top.no-bottom.commit-ci-menu.nav.nav-tabs
= nav_link(path: 'commit#show') do
= link_to project_commit_path(@project, @commit.id) do
- Changes
+ = _('Changes')
%span.badge.badge-pill= @diffs.size
- - if can?(current_user, :read_pipeline, @project)
+ - if any_pipelines
= nav_link(path: 'commit#pipelines') do
= link_to pipelines_project_commit_path(@project, @commit.id) do
- Pipelines
+ = _('Pipelines')
%span.badge.badge-pill.js-pipelines-mr-count= @commit.pipelines.size
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 2a919a767c0..a0db48bf8ff 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -6,8 +6,8 @@
%strong
#{ s_('CommitBoxTitle|Commit') }
%span.commit-sha= @commit.short_id
- = clipboard_button(text: @commit.id, title: _("Copy commit SHA to clipboard"))
- %span.d-none.d-sm-inline authored
+ = clipboard_button(text: @commit.id, title: _('Copy commit SHA to clipboard'))
+ %span.d-none.d-sm-inline= _('authored')
#{time_ago_with_tooltip(@commit.authored_date)}
%span= s_('ByAuthor|by')
= author_avatar(@commit, size: 24, has_tooltip: false)
@@ -43,13 +43,13 @@
= cherry_pick_commit_link(@commit, project_commit_path(@project, @commit.id), has_tooltip: false)
- if can?(current_user, :push_code, @project)
%li.clearfix
- = link_to s_("CreateTag|Tag"), new_project_tag_path(@project, ref: @commit)
+ = link_to s_('CreateTag|Tag'), new_project_tag_path(@project, ref: @commit)
%li.divider
%li.dropdown-header
#{ _('Download') }
- unless @commit.parents.length > 1
- %li= link_to s_("DownloadCommit|Email Patches"), project_commit_path(@project, @commit, format: :patch), class: "qa-email-patches"
- %li= link_to s_("DownloadCommit|Plain Diff"), project_commit_path(@project, @commit, format: :diff), class: "qa-plain-diff"
+ %li= link_to s_('DownloadCommit|Email Patches'), project_commit_path(@project, @commit, format: :patch), class: "qa-email-patches"
+ %li= link_to s_('DownloadCommit|Plain Diff'), project_commit_path(@project, @commit, format: :diff), class: "qa-plain-diff"
.commit-box{ data: { project_path: project_path(@project) } }
%h3.commit-title
@@ -74,8 +74,8 @@
%span.commit-info.merge-requests{ 'data-project-commit-path' => merge_requests_project_commit_path(@project, @commit.id, format: :json) }
= icon('spinner spin')
- - if @commit.last_pipeline
- - last_pipeline = @commit.last_pipeline
+ - last_pipeline = @commit.last_pipeline
+ - if can?(current_user, :read_pipeline, last_pipeline)
.well-segment.pipeline-info
.status-icon-container
= link_to project_pipeline_path(@project, last_pipeline.id), class: "ci-status-icon-#{last_pipeline.status}" do
@@ -95,8 +95,5 @@
.well-segment
= icon('info-circle fw')
- This commit is part of merge request
- = succeed '.' do
- = link_to @merge_request.to_reference, diffs_project_merge_request_path(@project, @merge_request, commit_id: @commit.id)
-
- Comments created here will be created in the context of that merge request.
+ - link_to_merge_request = link_to(@merge_request.to_reference, diffs_project_merge_request_path(@project, @merge_request, commit_id: @commit.id))
+ = _('This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request.').html_safe % { link_to_merge_request: link_to_merge_request }
diff --git a/app/views/projects/commit/_limit_exceeded_message.html.haml b/app/views/projects/commit/_limit_exceeded_message.html.haml
index a264f3517c4..7d3c0582d0b 100644
--- a/app/views/projects/commit/_limit_exceeded_message.html.haml
+++ b/app/views/projects/commit/_limit_exceeded_message.html.haml
@@ -1,8 +1,8 @@
-.has-tooltip{ class: "limit-box limit-box-#{objects} prepend-left-5", data: { title: "Project has too many #{label_for_message} to search"} }
+.has-tooltip{ class: "limit-box limit-box-#{objects} prepend-left-5", data: { title: _('Project has too many %{label_for_message} to search') % { label_for_message: label_for_message } } }
.limit-icon
- if objects == :branch
= sprite_icon('fork', size: 12)
- else
= icon('tag')
.limit-message
- %span #{label_for_message.capitalize} unavailable
+ %span= _('%{label_for_message} unavailable') % { label_for_message: label_for_message.capitalize }
diff --git a/app/views/projects/commit/_other_user_signature_badge.html.haml b/app/views/projects/commit/_other_user_signature_badge.html.haml
index d7bf2dc0cb6..bb843bee7c9 100644
--- a/app/views/projects/commit/_other_user_signature_badge.html.haml
+++ b/app/views/projects/commit/_other_user_signature_badge.html.haml
@@ -1,6 +1,6 @@
- title = capture do
- This commit was signed with a different user's verified signature.
+ = _("This commit was signed with a different user's verified signature.")
-- locals = { signature: signature, title: title, label: 'Unverified', css_class: 'invalid', icon: 'status_notfound_borderless', show_user: true }
+- locals = { signature: signature, title: title, label: _('Unverified'), css_class: 'invalid', icon: 'status_notfound_borderless', show_user: true }
= render partial: 'projects/commit/signature_badge', locals: locals
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 22ffd66ff8e..d282ab4f520 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,7 +1,6 @@
- title = capture do
- This commit was signed with a verified signature, but the committer email
- is <strong>not verified</strong> to belong to the same user.
+ = _('This commit was signed with a verified signature, but the committer email is <strong>not verified</strong> to belong to the same user.').html_safe
-- locals = { signature: signature, title: title, label: 'Unverified', css_class: ['invalid'], icon: 'status_notfound_borderless', show_user: true }
+- locals = { signature: signature, title: title, label: _('Unverified'), css_class: ['invalid'], icon: 'status_notfound_borderless', show_user: true }
= render partial: 'projects/commit/signature_badge', locals: locals
diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml
index c4d986ef742..1331fa179fc 100644
--- a/app/views/projects/commit/_signature_badge.html.haml
+++ b/app/views/projects/commit/_signature_badge.html.haml
@@ -19,10 +19,10 @@
.clearfix
= render partial: 'projects/commit/signature_badge_user', locals: { signature: signature }
- GPG Key ID:
+ = _('GPG Key ID:')
%span.monospace= signature.gpg_key_primary_keyid
- = link_to('Learn more about signing commits', help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
+ = link_to(_('Learn more about signing commits'), help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
%a{ href: 'javascript:void(0)', tabindex: 0, class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'top', title: title, content: content } }
= label
diff --git a/app/views/projects/commit/_unverified_signature_badge.html.haml b/app/views/projects/commit/_unverified_signature_badge.html.haml
index 00e1efe0582..294f916d18f 100644
--- a/app/views/projects/commit/_unverified_signature_badge.html.haml
+++ b/app/views/projects/commit/_unverified_signature_badge.html.haml
@@ -1,6 +1,6 @@
- title = capture do
- This commit was signed with an <strong>unverified</strong> signature.
+ = _('This commit was signed with an <strong>unverified</strong> signature.').html_safe
-- locals = { signature: signature, title: title, label: 'Unverified', css_class: 'invalid', icon: 'status_notfound_borderless' }
+- locals = { signature: signature, title: title, label: _('Unverified'), css_class: 'invalid', icon: 'status_notfound_borderless' }
= render partial: 'projects/commit/signature_badge', locals: locals
diff --git a/app/views/projects/commit/_verified_signature_badge.html.haml b/app/views/projects/commit/_verified_signature_badge.html.haml
index 31408806be7..4964b1b8ee7 100644
--- a/app/views/projects/commit/_verified_signature_badge.html.haml
+++ b/app/views/projects/commit/_verified_signature_badge.html.haml
@@ -1,7 +1,6 @@
- title = capture do
- This commit was signed with a <strong>verified</strong> signature and the
- committer email is verified to belong to the same user.
+ = _('This commit was signed with a <strong>verified</strong> signature and the committer email is verified to belong to the same user.').html_safe
-- locals = { signature: signature, title: title, label: 'Verified', css_class: 'valid', icon: 'status_success_borderless', show_user: true }
+- locals = { signature: signature, title: title, label: _('Verified'), css_class: 'valid', icon: 'status_success_borderless', show_user: true }
= render partial: 'projects/commit/signature_badge', locals: locals
diff --git a/app/views/projects/commit/pipelines.html.haml b/app/views/projects/commit/pipelines.html.haml
index c66ea873dba..f8c27f4c026 100644
--- a/app/views/projects/commit/pipelines.html.haml
+++ b/app/views/projects/commit/pipelines.html.haml
@@ -1,4 +1,4 @@
-- page_title 'Pipelines', "#{@commit.title} (#{@commit.short_id})", 'Commits'
+- page_title _('Pipelines'), "#{@commit.title} (#{@commit.short_id})", _('Commits')
= render 'commit_box'
= render 'ci_menu'
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index 79e32949db9..34226167288 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -1,19 +1,16 @@
- @no_container = true
-- add_to_breadcrumbs "Commits", project_commits_path(@project)
+- add_to_breadcrumbs _('Commits'), project_commits_path(@project)
- breadcrumb_title @commit.short_id
- container_class = !fluid_layout && diff_view == :inline ? 'container-limited' : ''
- limited_container_width = fluid_layout ? '' : 'limit-container-width'
- @content_class = limited_container_width
-- page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
+- page_title "#{@commit.title} (#{@commit.short_id})", _('Commits')
- page_description @commit.description
.container-fluid{ class: [limited_container_width, container_class] }
= render "commit_box"
- - if @commit.status
- = render "ci_menu"
- - else
- .block-connector
- = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, is_commit: true
+ = render "ci_menu"
+ = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, diff_page_context: "is-commit"
.limited-width-notes
= render "shared/notes/notes_with_form", :autocomplete => true
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 1a74b120c26..0d3c6e7027c 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -6,6 +6,7 @@
- merge_request = local_assigns.fetch(:merge_request, nil)
- project = local_assigns.fetch(:project) { merge_request&.project }
- ref = local_assigns.fetch(:ref) { merge_request&.source_branch }
+- commit_status = commit.present(current_user: current_user).status_for(ref)
- link = commit_path(project, commit, merge_request: merge_request)
%li.commit.flex-row.js-toggle-container{ id: "commit-#{commit.short_id}" }
@@ -22,7 +23,7 @@
%span.commit-row-message.d-block.d-sm-none
&middot;
= commit.short_id
- - if commit.status(ref)
+ - if commit_status
.d-block.d-sm-none
= render_commit_status(commit, ref: ref)
- if commit.description?
@@ -45,7 +46,7 @@
- else
= render partial: 'projects/commit/ajax_signature', locals: { commit: commit }
- - if commit.status(ref)
+ - if commit_status
= render_commit_status(commit, ref: ref)
.js-commit-pipeline-status{ data: { endpoint: pipelines_project_commit_path(project, commit.id, ref: ref) } }
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index b6bebbabed0..5774b48a054 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -8,7 +8,7 @@
- if @commits.present?
= render "projects/commits/commit_list"
- = render "projects/diffs/diffs", diffs: @diffs, environment: @environment
+ = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, diff_page_context: "is-compare"
- else
.card.bg-light
.center
diff --git a/app/views/projects/deploy_keys/_index.html.haml b/app/views/projects/deploy_keys/_index.html.haml
index 062aa423bde..24d665761cc 100644
--- a/app/views/projects/deploy_keys/_index.html.haml
+++ b/app/views/projects/deploy_keys/_index.html.haml
@@ -3,7 +3,7 @@
.settings-header
%h4
Deploy Keys
- %button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
+ %button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
Deploy keys allow read-only or read-write (if enabled) access to your repository. Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one.
diff --git a/app/views/projects/deployments/_actions.haml b/app/views/projects/deployments/_actions.haml
index f4c91377ecb..e45c5be76de 100644
--- a/app/views/projects/deployments/_actions.haml
+++ b/app/views/projects/deployments/_actions.haml
@@ -11,4 +11,4 @@
- next unless can?(current_user, :update_build, action)
%li
= link_to [:play, @project.namespace.becomes(Namespace), @project, action], method: :post, rel: 'nofollow', class: 'btn' do
- %span= action.name.humanize
+ %span= action.name
diff --git a/app/views/projects/deployments/_confirm_rollback_modal.html.haml b/app/views/projects/deployments/_confirm_rollback_modal.html.haml
new file mode 100644
index 00000000000..ff40e404e5f
--- /dev/null
+++ b/app/views/projects/deployments/_confirm_rollback_modal.html.haml
@@ -0,0 +1,23 @@
+- commit_sha = link_to deployment.short_sha, project_commit_path(@project, deployment.sha), class: "commit-sha has-tooltip", title: h(deployment.commit_title)
+.modal.ws-normal.fade{ tabindex: -1, id: "confirm-rollback-modal-#{deployment.id}" }
+ .modal-dialog
+ .modal-content
+ .modal-header
+ %h4.modal-title.d-flex.mw-100
+ - if deployment.last?
+ = s_("Environments|Re-deploy environment %{environment_name}?") % {environment_name: @environment.name}
+ - else
+ = s_("Environments|Rollback environment %{environment_name}?") % {environment_name: @environment.name}
+ .modal-body
+ - if deployment.last?
+ %p= s_('Environments|This action will relaunch the job for commit %{commit_id}, putting the environment in a previous version. Are you sure you want to continue?').html_safe % {commit_id: commit_sha}
+ - else
+ %p
+ = s_('Environments|This action will run the job defined by staging for commit %{commit_id}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?').html_safe % {commit_id: commit_sha}
+ .modal-footer
+ = button_tag _('Cancel'), type: 'button', class: 'btn btn-cancel', data: { dismiss: 'modal' }
+ = link_to [:retry, @project.namespace.becomes(Namespace), @project, deployment.deployable], method: :post, class: 'btn btn-danger' do
+ - if deployment.last?
+ = s_('Environments|Re-deploy')
+ - else
+ = s_('Environments|Rollback')
diff --git a/app/views/projects/deployments/_rollback.haml b/app/views/projects/deployments/_rollback.haml
index 1bd538a08ff..d6bf8d564de 100644
--- a/app/views/projects/deployments/_rollback.haml
+++ b/app/views/projects/deployments/_rollback.haml
@@ -1,7 +1,8 @@
- if can?(current_user, :create_deployment, deployment)
- tooltip = deployment.last? ? s_('Environments|Re-deploy to environment') : s_('Environments|Rollback environment')
- = link_to [:retry, @project.namespace.becomes(Namespace), @project, deployment.deployable], method: :post, class: 'btn btn-build has-tooltip', title: tooltip do
+ = button_tag class: 'btn btn-default btn-build has-tooltip', type: 'button', data: { toggle: 'modal', target: "#confirm-rollback-modal-#{deployment.id}" }, title: tooltip do
- if deployment.last?
= sprite_icon('repeat')
- else
= sprite_icon('redo')
+ = render 'projects/deployments/confirm_rollback_modal', deployment: deployment
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index cc2d0d3b2d8..2dba3fcd664 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -2,7 +2,7 @@
- show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true)
- can_create_note = !@diff_notes_disabled && can?(current_user, :create_note, diffs.project)
- diff_files = diffs.diff_files
-- is_commit = local_assigns.fetch(:is_commit, false)
+- diff_page_context = local_assigns.fetch(:diff_page_context, nil)
.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed
.files-changed-inner
@@ -25,4 +25,4 @@
= render 'projects/diffs/warning', diff_files: diffs
.files{ data: { can_create_note: can_create_note } }
- = render partial: 'projects/diffs/file', collection: diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, is_commit: is_commit }
+ = render partial: 'projects/diffs/file', collection: diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, diff_page_context: diff_page_context }
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 5565ae1d98b..855b719dc45 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -1,11 +1,11 @@
- environment = local_assigns.fetch(:environment, nil)
-- is_commit = local_assigns.fetch(:is_commit, false)
+- diff_page_context = local_assigns.fetch(:diff_page_context, nil)
- file_hash = hexdigest(diff_file.file_path)
- image_diff = diff_file.rich_viewer && diff_file.rich_viewer.partial_name == 'image'
- image_replaced = diff_file.old_content_sha && diff_file.old_content_sha != diff_file.content_sha
.diff-file.file-holder{ id: file_hash, data: diff_file_html_data(project, diff_file.file_path, diff_file.content_sha) }
- .js-file-title.file-title-flex-parent{ class: is_commit ? "is-commit" : "" }
+ .js-file-title.file-title-flex-parent{ class: diff_page_context }
.file-header-content
= render "projects/diffs/file_header", diff_file: diff_file, url: "##{file_hash}"
diff --git a/app/views/projects/diffs/_render_error.html.haml b/app/views/projects/diffs/_render_error.html.haml
index c3dc47a56a7..7dbd9897e83 100644
--- a/app/views/projects/diffs/_render_error.html.haml
+++ b/app/views/projects/diffs/_render_error.html.haml
@@ -1,6 +1,2 @@
.nothing-here-block
- = _("This %{viewer} could not be displayed because %{reason}.") % { viewer: viewer.switcher_title, reason: diff_render_error_reason(viewer) }
-
- You can
- = diff_render_error_options(viewer).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ').html_safe
- instead.
+ = viewer.render_error_message.html_safe
diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml
index 2eef599cf84..2cc3d921abc 100644
--- a/app/views/projects/diffs/_warning.html.haml
+++ b/app/views/projects/diffs/_warning.html.haml
@@ -9,4 +9,4 @@
= link_to _("Plain diff"), merge_request_path(@merge_request, format: :diff), class: "btn btn-sm"
= link_to _("Email patch"), merge_request_path(@merge_request, format: :patch), class: "btn btn-sm"
%p
- = _("To preserve performance only <strong>%{display_size} of ${real_size}</strong> files are displayed.").html_safe % { display_size: diff_files.size, real_size: diff_files.real_size }
+ = _("To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed.").html_safe % { display_size: diff_files.size, real_size: diff_files.real_size }
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 1b52821af15..a6a8ca489a9 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -1,17 +1,15 @@
-- breadcrumb_title "General Settings"
-- page_title "General"
+- breadcrumb_title _("General Settings")
+- page_title _("General")
- @content_class = "limit-container-width" unless fluid_layout
- expanded = Rails.env.test?
.project-edit-container
%section.settings.general-settings.no-animate#js-general-project-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4
- General project
- %button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? 'Collapse' : 'Expand'
- %p
- Update your project name, description, avatar, and other general settings.
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Naming, tags, avatar')
+ %button.btn.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %p= _('Update your project name, tags, description and avatar.')
+
.settings-content
.project-edit-errors
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project" }, authenticity_token: true do |f|
@@ -39,14 +37,14 @@
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
.form-group
- = f.label :tag_list, "Tags", class: 'label-bold'
+ = f.label :tag_list, "Topics", class: 'label-bold'
= f.text_field :tag_list, value: @project.tag_list.join(', '), maxlength: 2000, class: "form-control"
- %p.form-text.text-muted Separate tags with commas.
+ %p.form-text.text-muted Separate topics with commas.
%fieldset.features
%h5.prepend-top-0= _("Project avatar")
.form-group
- if @project.avatar?
- .avatar-container.s160.append-bottom-15
+ .avatar-container.rect-avatar.s160.append-bottom-15
= project_icon(@project, alt: '', class: 'avatar project-avatar s160', width: 160, height: 160)
- if @project.avatar_in_git
%p.light
@@ -63,12 +61,10 @@
%section.settings.sharing-permissions.no-animate#js-shared-permissions{ class: ('expanded' if expanded) }
.settings-header
- %h4
- Permissions
- %button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? 'Collapse' : 'Expand'
- %p
- Enable or disable certain project features and choose access levels.
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Visibility, project features, permissions')
+ %button.btn.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %p= _('Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions.')
+
.settings-content
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-shared-permissions' }
@@ -81,12 +77,10 @@
%section.qa-merge-request-settings.settings.merge-requests-feature.no-animate#js-merge-request-settings{ class: [('expanded' if expanded), ('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)] }
.settings-header
- %h4
- Merge request
- %button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? 'Collapse' : 'Expand'
- %p
- Customize your merge request restrictions.
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Merge requests')
+ %button.btn.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %p= _('Choose your merge method, set up a default merge request description template.')
+
.settings-content
= render_if_exists 'shared/promotions/promote_mr_features'
@@ -97,11 +91,10 @@
= render_if_exists 'projects/merge_request_approvals_settings', expanded: expanded
- = render_if_exists 'projects/service_desk_settings'
%section.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('ProjectSettings|Badges')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
@@ -111,16 +104,15 @@
.settings-content
= render 'shared/badges/badge_settings'
+ = render_if_exists 'projects/service_desk_settings'
= render 'export', project: @project
%section.qa-advanced-settings.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4
- Advanced
- %button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? 'Collapse' : 'Expand'
- %p
- Perform advanced options such as housekeeping, archiving, renaming, transferring, or removing your project.
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Advanced')
+ %button.btn.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %p= _('Housekeeping, export, path, transfer, remove, archive.')
+
.settings-content
.sub-section
%h4 Housekeeping
diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml
index b7e1cf85cb7..aebd176af9b 100644
--- a/app/views/projects/environments/folder.html.haml
+++ b/app/views/projects/environments/folder.html.haml
@@ -1,8 +1,5 @@
- @no_container = true
- page_title _("Environments")
-#environments-folder-list-view{ data: { endpoint: folder_project_environments_path(@project, @folder, format: :json),
- "folder-name" => @folder,
- "can-create-deployment" => can?(current_user, :create_deployment, @project).to_s,
- "can-read-environment" => can?(current_user, :read_environment, @project).to_s,
+#environments-folder-list-view{ data: { environments_data: environments_folder_list_view_data,
"css-class" => container_class } }
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index d66de7ab698..99cbbc11acd 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -2,7 +2,6 @@
- page_title _("Environments")
#environments-list-view{ data: { environments_data: environments_list_data,
- "can-create-deployment" => can?(current_user, :create_deployment, @project).to_s,
"can-read-environment" => can?(current_user, :read_environment, @project).to_s,
"can-create-environment" => can?(current_user, :create_environment, @project).to_s,
"new-environment-path" => new_project_environment_path(@project),
diff --git a/app/views/projects/error_tracking/index.html.haml b/app/views/projects/error_tracking/index.html.haml
new file mode 100644
index 00000000000..bc02c5f0e5a
--- /dev/null
+++ b/app/views/projects/error_tracking/index.html.haml
@@ -0,0 +1,3 @@
+- page_title _('Errors')
+
+#js-error_tracking{ data: error_tracking_data(@project) }
diff --git a/app/views/projects/forks/_fork_button.html.haml b/app/views/projects/forks/_fork_button.html.haml
index a69146513d8..3f0798a898d 100644
--- a/app/views/projects/forks/_fork_button.html.haml
+++ b/app/views/projects/forks/_fork_button.html.haml
@@ -5,7 +5,7 @@
.bordered-box.fork-thumbnail.text-center.prepend-left-default.append-right-default.prepend-top-default.append-bottom-default.forked
= link_to project_path(forked_project) do
- if /no_((\w*)_)*avatar/.match(avatar)
- = group_icon(namespace, class: "avatar s100 identicon")
+ = group_icon(namespace, class: "avatar rect-avatar s100 identicon")
- else
.avatar-container.s100
= image_tag(avatar, class: "avatar s100")
@@ -18,7 +18,7 @@
class: ("disabled has-tooltip" unless can_create_project),
title: (_('You have reached your project limit') unless can_create_project) do
- if /no_((\w*)_)*avatar/.match(avatar)
- = group_icon(namespace, class: "avatar s100 identicon")
+ = group_icon(namespace, class: "avatar rect-avatar s100 identicon")
- else
.avatar-container.s100
= image_tag(avatar, class: "avatar s100")
diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml
index b0e22a35fe1..60160f521ad 100644
--- a/app/views/projects/graphs/charts.html.haml
+++ b/app/views/projects/graphs/charts.html.haml
@@ -55,23 +55,23 @@
#{@commits_graph.authors}
= (_("Authors: %{authors}") % { authors: "<strong>#{authors}</strong>" }).html_safe
.col-md-6
+ %p.slead
+ = _("Commits per day of month")
%div
- %p.slead
- = _("Commits per day of month")
%canvas#month-chart
.row
.col-md-6
.col-md-6
+ %p.slead
+ = _("Commits per weekday")
%div
- %p.slead
- = _("Commits per weekday")
%canvas#weekday-chart
.row
.col-md-6
.col-md-6
+ %p.slead
+ = _("Commits per day hour (UTC)")
%div
- %p.slead
- = _("Commits per day hour (UTC)")
%canvas#hour-chart
-# haml-lint:disable InlineJavaScript
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index 4917f4b8903..42b6aaa2634 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -5,7 +5,7 @@
= link_to 'Reopen issue', issue_path(@issue, issue: {state_event: :reopen}, format: 'json'), data: {original_text: "Reopen issue", alternative_text: "Comment & reopen issue"}, class: "btn btn-nr btn-reopen btn-comment js-note-target-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
= link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, format: 'json'), data: {original_text: "Close issue", alternative_text: "Comment & close issue"}, class: "btn btn-nr btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
-%section.js-vue-notes-event
+%section.issuable-discussion.js-vue-notes-event
#js-vue-notes{ data: { notes_data: notes_data(@issue).to_json,
noteable_data: serialize_issuable(@issue),
noteable_type: 'Issue',
diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml
index 1e4e9450ffa..1be1087b36f 100644
--- a/app/views/projects/issues/_form.html.haml
+++ b/app/views/projects/issues/_form.html.haml
@@ -1,4 +1,3 @@
= form_for [@project.namespace.becomes(Namespace), @project, @issue],
- html: { class: 'issue-form common-note-form js-quick-submit js-requires-input' },
- data: { markdown_version: @issue.cached_markdown_version } do |f|
+ html: { class: 'issue-form common-note-form js-quick-submit js-requires-input' } do |f|
= render 'shared/issuable/form', f: f, issuable: @issue
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 31c72f2f759..ce7c7091c93 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -36,7 +36,7 @@
= issue.due_date.to_s(:medium)
- if issue.labels.any?
&nbsp;
- - issue.labels.each do |label|
+ - labels_sorted_by_title(issue.labels).each do |label|
= link_to_label(label, subject: issue.project, css_class: 'label-link')
.issuable-meta
diff --git a/app/views/projects/issues/_merge_requests.html.haml b/app/views/projects/issues/_merge_requests.html.haml
index 5c36d2202a6..6a66c2e57cc 100644
--- a/app/views/projects/issues/_merge_requests.html.haml
+++ b/app/views/projects/issues/_merge_requests.html.haml
@@ -1,35 +1,36 @@
- if @merge_requests.any?
- %h2.merge-requests-title
- = pluralize(@merge_requests.count, 'Related Merge Request')
- %ul.unstyled-list.related-merge-requests
- - has_any_head_pipeline = @merge_requests.any?(&:head_pipeline_id)
- - @merge_requests.each do |merge_request|
- %li
- %span.merge-request-ci-status
- - if merge_request.head_pipeline
- = render_pipeline_status(merge_request.head_pipeline)
- - elsif has_any_head_pipeline
- = icon('blank fw')
- %span.merge-request-id
- = merge_request.to_reference
- %span.merge-request-info
- %strong
- = link_to merge_request.title, merge_request_path(merge_request), class: "row_title"
- - unless @issue.project.id == merge_request.target_project.id
- in
- - project = merge_request.target_project
- = link_to project.full_name, project_path(project)
+ .card-slim.mt-3
+ .card-header
+ %h2.card-title.mt-0.mb-0.h5.merge-requests-title
+ %span.mr-1.bold
+ = _('Related merge requests')
+ .d-inline-flex.lh-100.align-middle
+ .mr-count-badge
+ .mr-count-badge-count
+ = sprite_icon('merge-request', size: 16, css_class: 'mr-1 text-secondary')
+ = @merge_requests.count
+ %ul.content-list.related-items-list
+ - has_any_head_pipeline = @merge_requests.any?(&:head_pipeline_id)
+ - @merge_requests.each do |merge_request|
+ - merge_request = merge_request.present(current_user: current_user)
+ %li.list-item.py-0.px-0
+ .item-body.issuable-info-container.py-lg-3.px-lg-3.pl-md-3
+ .item-contents
+ .item-title.d-flex.align-items-center.mr-title
+ = render partial: 'projects/issues/merge_requests_status', locals: { merge_request: merge_request, css_class: 'd-none d-xl-block append-right-8' }
+ = link_to merge_request.title, merge_request_path(merge_request), { class: 'mr-title-link'}
+ .item-meta
+ = render partial: 'projects/issues/merge_requests_status', locals: { merge_request: merge_request, css_class: 'd-xl-none d-lg-block append-right-5' }
+ %span.d-flex.align-items-center.append-right-8.mr-item-path.item-path-id.mt-0
+ %span.path-id-text.bold.text-truncate{ data: { toggle: 'tooltip'}, title: merge_request.target_project.full_path }
+ = merge_request.target_project.full_path
+ = merge_request.to_reference
+ %span.mr-ci-status.flex-md-grow-1.justify-content-end.d-flex.ml-md-2
+ - if merge_request.can_read_pipeline?
+ = render 'ci/status/icon', status: merge_request.head_pipeline.detailed_status(current_user), tooltip_placement: 'bottom'
+ - elsif has_any_head_pipeline
+ = icon('blank fw')
- - if merge_request.merged?
- %span.merge-request-status.prepend-left-10.merged
- Merged
- - elsif merge_request.closed?
- %span.merge-request-status.prepend-left-10.closed
- Closed
- - else
- %span.merge-request-status.prepend-left-10.open
- Open
-
- - if @closed_by_merge_requests.present?
- %li
- = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count}
+ - if @closed_by_merge_requests.present?
+ %p
+ = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count}
diff --git a/app/views/projects/issues/_merge_requests_status.html.haml b/app/views/projects/issues/_merge_requests_status.html.haml
new file mode 100644
index 00000000000..90838a75214
--- /dev/null
+++ b/app/views/projects/issues/_merge_requests_status.html.haml
@@ -0,0 +1,25 @@
+- time_format = '%b %e, %Y %l:%M%P %Z%z'
+
+- if merge_request.merged?
+ - mr_status_date = merge_request.merged_at
+ - mr_status_title = _('Merged')
+ - mr_status_icon = 'merge'
+ - mr_status_class = 'merged'
+- elsif merge_request.closed?
+ - mr_status_date = merge_request.closed_event&.created_at
+ - mr_status_title = _('Closed')
+ - mr_status_icon = 'issue-close'
+ - mr_status_class = 'closed'
+- else
+ - mr_status_date = merge_request.created_at
+ - mr_status_title = mr_status_date ? _('Opened') : _('Open')
+ - mr_status_icon = 'issue-open-m'
+ - mr_status_class = 'open'
+
+- if mr_status_date
+ - mr_status_tooltip = "<div><span class=\"bold\">#{mr_status_title}</span> #{time_ago_in_words(mr_status_date)} ago</div><span class=\"text-tertiary\">#{l(mr_status_date.to_time, format: time_format)}</span>"
+- else
+ - mr_status_tooltip = "<div><span class=\"bold\">#{mr_status_title}</span></div>"
+
+%span.mr-status-wrapper.suggestion-help-hover{ class: css_class, data: { toggle: 'tooltip', placement: 'bottom', html: 'true', title: mr_status_tooltip } }
+ = sprite_icon(mr_status_icon, size: 16, css_class: "merge-request-status #{mr_status_class}")
diff --git a/app/views/projects/issues/_nav_btns.html.haml b/app/views/projects/issues/_nav_btns.html.haml
index e4a0d4b8479..329efa0cdbf 100644
--- a/app/views/projects/issues/_nav_btns.html.haml
+++ b/app/views/projects/issues/_nav_btns.html.haml
@@ -1,11 +1,30 @@
-= render 'shared/issuable/feed_buttons'
-
-- if @can_bulk_update
- = button_tag "Edit issues", class: "btn btn-default append-right-10 js-bulk-update-toggle"
-- if show_new_issue_link?(@project)
- = link_to "New issue", new_project_issue_path(@project,
- issue: { assignee_id: finder.assignee.try(:id),
- milestone_id: finder.milestones.first.try(:id) }),
- class: "btn btn-success",
- title: "New issue",
- id: "new_issue_link"
+- show_feed_buttons = local_assigns.fetch(:show_feed_buttons, true)
+- show_import_button = local_assigns.fetch(:show_import_button, true) && can?(current_user, :import_issues, @project)
+- show_export_button = local_assigns.fetch(:show_export_button, true)
+
+.nav-controls.issues-nav-controls
+ - if show_feed_buttons
+ = render 'shared/issuable/feed_buttons'
+
+ .btn-group.append-right-10<
+ - if show_export_button
+ = render_if_exists 'projects/issues/export_csv/button'
+
+ - if show_import_button
+ = render 'projects/issues/import_csv/button'
+
+ - if @can_bulk_update
+ = button_tag _("Edit issues"), class: "btn btn-default append-right-10 js-bulk-update-toggle"
+ - if show_new_issue_link?(@project)
+ = link_to _("New issue"), new_project_issue_path(@project,
+ issue: { assignee_id: finder.assignee.try(:id),
+ milestone_id: finder.milestones.first.try(:id) }),
+ class: "btn btn-success",
+ title: _("New issue"),
+ id: "new_issue_link"
+
+- if show_export_button
+ = render_if_exists 'projects/issues/export_csv/modal'
+
+- if show_import_button
+ = render 'projects/issues/import_csv/modal'
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index 5374f4a1de0..fbd70cd1906 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -30,7 +30,7 @@
= icon('check', class: 'icon')
= _('Create merge request and branch')
- %li{ class: [!can_create_merge_request && 'droplab-item-selected'], role: 'button', data: { value: 'create-branch', text: _('Create branch') } }
+ %li{ class: [!can_create_merge_request && 'droplab-item-selected'], role: 'button', data: { value: 'create-branch', text: _('Create branch') } }
.menu-item
= icon('check', class: 'icon')
= _('Create branch')
diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml
index 1df38db9fd4..6da4956a036 100644
--- a/app/views/projects/issues/_related_branches.html.haml
+++ b/app/views/projects/issues/_related_branches.html.haml
@@ -6,9 +6,9 @@
%li
- target = @project.repository.find_branch(branch).dereferenced_target
- pipeline = @project.pipeline_for(branch, target.sha) if target
- - if pipeline
+ - if can?(current_user, :read_pipeline, pipeline)
%span.related-branch-ci-status
- = render_pipeline_status(pipeline)
+ = render 'ci/status/icon', status: pipeline.detailed_status(current_user)
%span.related-branch-info
%strong
= link_to branch, project_compare_path(@project, from: @project.default_branch, to: branch), class: "ref-name"
diff --git a/app/views/projects/issues/import_csv/_button.html.haml b/app/views/projects/issues/import_csv/_button.html.haml
new file mode 100644
index 00000000000..acc2c50294f
--- /dev/null
+++ b/app/views/projects/issues/import_csv/_button.html.haml
@@ -0,0 +1,9 @@
+- type = local_assigns.fetch(:type, :icon)
+
+%button.csv-import-button.btn{ title: _('Import CSV'), class: ('has-tooltip' if type == :icon),
+ data: { toggle: 'modal', target: '.issues-import-modal' } }
+ - if type == :icon
+ = sprite_icon('upload')
+ - else
+ = _('Import CSV')
+
diff --git a/app/views/projects/issues/import_csv/_modal.html.haml b/app/views/projects/issues/import_csv/_modal.html.haml
new file mode 100644
index 00000000000..86bc54786ad
--- /dev/null
+++ b/app/views/projects/issues/import_csv/_modal.html.haml
@@ -0,0 +1,24 @@
+.issues-import-modal.modal
+ .modal-dialog
+ .modal-content
+ = form_tag import_csv_namespace_project_issues_path, multipart: true do
+ .modal-header
+ %h3
+ = _('Import issues')
+ .svg-content.import-export-svg-container
+ = image_tag 'illustrations/export-import.svg', alt: _('Import/Export illustration'), class: 'illustration'
+ %a.close{ href: '#', 'data-dismiss' => 'modal' } ×
+ .modal-body
+ .modal-text
+ %p
+ = _("Your issues will be imported in the background. Once finished, you'll get a confirmation email.")
+ .form-group
+ = label_tag :file, _('Upload CSV file'), class: 'label-bold'
+ %div
+ = file_field_tag :file, accept: '.csv,text/csv', required: true
+ %p.text-secondary
+ = _('It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected.')
+ = _('The maximum file size allowed is %{size}.') % { size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) }
+ .modal-footer
+ %button{ type: 'submit', class: 'btn btn-success', title: _('Import issues'), data: { track_label: "export_issues_csv", track_event: "click_button"} }
+ = _('Import issues')
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 1e7737aeb97..39e9e9171cf 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -11,8 +11,7 @@
%div{ class: (container_class) }
.top-area
= render 'shared/issuable/nav', type: :issues
- .nav-controls
- = render "projects/issues/nav_btns"
+ = render "projects/issues/nav_btns"
= render 'shared/issuable/search_bar', type: :issues
- if @can_bulk_update
@@ -23,4 +22,4 @@
- if new_issue_email
= render 'projects/issuable_by_email', email: new_issue_email, issuable_type: 'issue'
- else
- = render 'shared/empty_states/issues', button_path: new_project_issue_path(@project)
+ = render 'shared/empty_states/issues', button_path: new_project_issue_path(@project), show_import_button: true
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 8c2fe2625c7..3a674da6e87 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -14,8 +14,14 @@
.detail-page-header-body
.issuable-status-box.status-box.status-box-issue-closed{ class: issue_button_visibility(@issue, false) }
= sprite_icon('mobile-issue-close', size: 16, css_class: 'd-block d-sm-none')
- %span.d-none.d-sm-block
- Closed
+ .d-none.d-sm-block
+ - if @issue.moved?
+ - moved_link_start = "<a href=\"#{issue_path(@issue.moved_to)}\" class=\"text-white text-underline\">".html_safe
+ - moved_link_end = '</a>'.html_safe
+ = s_('IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})').html_safe % {moved_link_start: moved_link_start,
+ moved_link_end: moved_link_end}
+ - else
+ = _("Closed")
.issuable-status-box.status-box.status-box-open{ class: issue_button_visibility(@issue, true) }
= sprite_icon('issue-open-m', size: 16, css_class: 'd-block d-sm-none')
%span.d-none.d-sm-block Open
@@ -55,7 +61,7 @@
- if can_report_spam
= link_to 'Submit as spam', mark_as_spam_project_issue_path(@project, @issue), method: :post, class: 'd-none d-sm-none d-md-block btn btn-grouped btn-spam', title: 'Submit as spam'
- if can_create_issue
- = link_to new_project_issue_path(@project), class: 'd-none d-sm-none d-md-block btn btn-grouped new-issue-link btn-success btn-inverted', title: 'New issue', id: 'new_issue_link' do
+ = link_to new_project_issue_path(@project), class: 'd-none d-sm-none d-md-block btn btn-grouped btn-success btn-inverted', title: 'New issue', id: 'new_issue_link' do
New issue
.issue-details.issuable-details
@@ -85,7 +91,6 @@
#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@issue), notes_filters: UserPreference.notes_filters.to_json } }
= render 'new_branch' unless @issue.confidential?
- %section.issuable-discussion
- = render 'projects/issues/discussion'
+ = render_if_exists 'projects/issues/discussion'
= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @issue.assignees
diff --git a/app/views/projects/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml
index 59592abcf6a..afea5268006 100644
--- a/app/views/projects/jobs/index.html.haml
+++ b/app/views/projects/jobs/index.html.haml
@@ -8,10 +8,6 @@
.nav-controls
- if can?(current_user, :update_build, @project)
- - if @all_builds.running_or_pending.limit(1).any? # rubocop: disable CodeReuse/ActiveRecord
- = link_to 'Cancel running', cancel_all_project_jobs_path(@project),
- data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
-
- unless @repository.gitlab_ci_yml
= link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info'
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 56b06374d6d..bb7c297ba1f 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -5,15 +5,10 @@
- subscribed = params[:subscribed]
- labels_or_filters = @labels.exists? || @prioritized_labels.exists? || search.present? || subscribed.present?
-- if labels_or_filters && can_admin_label
- - content_for(:header_content) do
- .nav-controls
- = link_to _('New label'), new_project_label_path(@project), class: "btn btn-success qa-label-create-new"
-
- if labels_or_filters
#promote-label-modal
%div{ class: container_class }
- = render 'shared/labels/nav'
+ = render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label
.labels-container.prepend-top-10
- if can_admin_label
diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml
index 13b967beba1..a7c9e54506d 100644
--- a/app/views/projects/merge_requests/_form.html.haml
+++ b/app/views/projects/merge_requests/_form.html.haml
@@ -1,4 +1,3 @@
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request],
- html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' },
- data: { markdown_version: @merge_request.cached_markdown_version } do |f|
+ html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' } do |f|
= render 'shared/issuable/form', f: f, issuable: @merge_request, presenter: @mr_presenter
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index faa070d0389..b8e0b66e277 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -34,7 +34,7 @@
= merge_request.target_branch
- if merge_request.labels.any?
&nbsp;
- - merge_request.labels.each do |label|
+ - labels_sorted_by_title(merge_request.labels).each do |label|
= link_to_label(label, subject: merge_request.project, type: :merge_request, css_class: 'label-link')
.issuable-meta
@@ -46,9 +46,9 @@
%li.issuable-status.d-none.d-sm-inline-block
= icon('ban')
CLOSED
- - if merge_request.head_pipeline
+ - if can?(current_user, :read_pipeline, merge_request.head_pipeline)
%li.issuable-pipeline-status.d-none.d-sm-inline-block
- = render_pipeline_status(merge_request.head_pipeline)
+ = render 'ci/status/icon', status: merge_request.head_pipeline.detailed_status(current_user)
- if merge_request.open? && merge_request.broken?
%li.issuable-pipeline-broken.d-none.d-sm-inline-block
= link_to merge_request_path(merge_request), class: "has-tooltip", title: _('Cannot be merged automatically') do
@@ -56,6 +56,7 @@
- if merge_request.assignee
%li
= link_to_member(merge_request.source_project, merge_request.assignee, name: false, title: _('Assigned to :name'))
+ = render_if_exists 'projects/merge_requests/approvals_count', merge_request: merge_request
= render 'shared/issuable_meta_data', issuable: merge_request
diff --git a/app/views/projects/merge_requests/_merge_requests.html.haml b/app/views/projects/merge_requests/_merge_requests.html.haml
index bd6f1c05949..57fbd360d46 100644
--- a/app/views/projects/merge_requests/_merge_requests.html.haml
+++ b/app/views/projects/merge_requests/_merge_requests.html.haml
@@ -1,5 +1,5 @@
%ul.content-list.mr-list.issuable-list
- - if @merge_requests.exists?
+ - if @merge_requests.present?
= render @merge_requests
- else
= render 'shared/empty_states/merge_requests'
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index d6f340d0ee2..5111c9fab8d 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -7,7 +7,7 @@
- page_card_attributes @merge_request.card_attributes
- suggest_changes_help_path = help_page_path('user/discussions/index.md', anchor: 'suggest-changes')
-.merge-request{ data: { mr_action: j(params[:tab].presence || 'show'), url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project) } }
+.merge-request{ data: { mr_action: j(params[:tab].presence || 'show'), url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project), lock_version: @merge_request.lock_version } }
= render "projects/merge_requests/mr_title"
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
@@ -59,6 +59,7 @@
#js-vue-discussion-counter
.tab-content#diff-notes-app
+ #js-diff-file-finder
#notes.notes.tab-pane.voting_notes
.row
%section.col-md-12
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index ebd3229e42b..5cc6b5a173b 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -1,27 +1,28 @@
= form_for [@project.namespace.becomes(Namespace), @project, @milestone],
- html: {class: 'milestone-form common-note-form js-quick-submit js-requires-input'},
- data: { markdown_version: @milestone.cached_markdown_version } do |f|
+ html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
= form_errors(@milestone)
.row
.col-md-6
.form-group.row
- = f.label :title, "Title", class: "col-form-label col-sm-2"
+ .col-form-label.col-sm-2
+ = f.label :title, _('Title')
.col-sm-10
- = f.text_field :title, maxlength: 255, class: "qa-milestone-title form-control", required: true, autofocus: true
+ = f.text_field :title, maxlength: 255, class: 'qa-milestone-title form-control', required: true, autofocus: true
.form-group.row.milestone-description
- = f.label :description, "Description", class: "col-form-label col-sm-2"
+ .col-form-label.col-sm-2
+ = f.label :description, _('Description')
.col-sm-10
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project) } do
- = render 'projects/zen', f: f, attr: :description, classes: 'qa-milestone-description note-textarea', placeholder: 'Write milestone description...'
+ = render 'projects/zen', f: f, attr: :description, classes: 'qa-milestone-description note-textarea', placeholder: _('Write milestone description...')
= render 'shared/notes/hints'
.clearfix
.error-alert
- = render "shared/milestones/form_dates", f: f
+ = render 'shared/milestones/form_dates', f: f
.form-actions
- if @milestone.new_record?
- = f.submit 'Create milestone', class: "btn-success btn qa-milestone-create-button"
- = link_to "Cancel", project_milestones_path(@project), class: "btn btn-cancel"
+ = f.submit _('Create milestone'), class: 'btn-create btn qa-milestone-create-button'
+ = link_to _('Cancel'), project_milestones_path(@project), class: 'btn btn-cancel'
- else
- = f.submit 'Save changes', class: "btn-success btn"
- = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn btn-cancel"
+ = f.submit _('Save changes'), class: 'btn-success btn'
+ = link_to _('Cancel'), project_milestone_path(@project, @milestone), class: 'btn btn-cancel'
diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml
index 4006a468792..aa564e00af9 100644
--- a/app/views/projects/milestones/edit.html.haml
+++ b/app/views/projects/milestones/edit.html.haml
@@ -1,14 +1,14 @@
- @no_container = true
-- breadcrumb_title "Edit"
-- add_to_breadcrumbs "Milestones", project_milestones_path(@project)
-- page_title "Edit", @milestone.title, "Milestones"
+- breadcrumb_title _('Edit')
+- add_to_breadcrumbs _('Milestones'), project_milestones_path(@project)
+- page_title _('Edit'), @milestone.title, _('Milestones')
%div{ class: container_class }
%h3.page-title
- Edit Milestone
+ = _('Edit Milestone')
%hr
- = render "form"
+ = render 'form'
diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml
index 57f3c640696..a3414c16d73 100644
--- a/app/views/projects/milestones/index.html.haml
+++ b/app/views/projects/milestones/index.html.haml
@@ -1,15 +1,16 @@
- @no_container = true
-- page_title 'Milestones'
+- page_title _('Milestones')
%div{ class: container_class }
.top-area
= render 'shared/milestones_filter', counts: milestone_counts(@project.milestones)
.nav-controls
+ = render 'shared/milestones/search_form'
= render 'shared/milestones_sort_dropdown'
- if can?(current_user, :admin_milestone, @project)
- = link_to new_project_milestone_path(@project), class: "btn btn-success qa-new-project-milestone", title: 'New milestone' do
- New milestone
+ = link_to new_project_milestone_path(@project), class: 'btn btn-success qa-new-project-milestone', title: _('New milestone') do
+ = _('New milestone')
.milestones
#delete-milestone-modal
@@ -20,6 +21,6 @@
- if @milestones.blank?
%li
- .nothing-here-block No milestones to show
+ .nothing-here-block= _('No milestones to show')
= paginate @milestones, theme: 'gitlab'
diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml
index 01cc951e8c2..79207fd70b5 100644
--- a/app/views/projects/milestones/new.html.haml
+++ b/app/views/projects/milestones/new.html.haml
@@ -1,12 +1,12 @@
- @no_container = true
-- add_to_breadcrumbs "Milestones", project_milestones_path(@project)
-- breadcrumb_title "New"
-- page_title "New Milestone"
+- add_to_breadcrumbs _('Milestones'), project_milestones_path(@project)
+- breadcrumb_title _('New')
+- page_title _('New Milestone')
%div{ class: container_class }
%h3.page-title
- New Milestone
+ = _('New Milestone')
%hr
- = render "form"
+ = render 'form'
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 5859de61d71..0542b349e44 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -1,30 +1,30 @@
- @no_container = true
-- add_to_breadcrumbs "Milestones", project_milestones_path(@project)
+- add_to_breadcrumbs _('Milestones'), project_milestones_path(@project)
- breadcrumb_title @milestone.title
-- page_title @milestone.title, "Milestones"
+- page_title @milestone.title, _('Milestones')
- page_description @milestone.description
%div{ class: container_class }
.detail-page-header.milestone-page-header
.status-box{ class: status_box_class(@milestone) }
- if @milestone.closed?
- Closed
+ = _('Closed')
- elsif @milestone.expired?
- Past due
+ = _('Past due')
- elsif @milestone.upcoming?
- Upcoming
+ = _('Upcoming')
- else
- Open
+ = _('Open')
.header-text-content
%span.identifier
%strong
- Milestone
+ = _('Milestone')
- if @milestone.due_date || @milestone.start_date
= milestone_date_range(@milestone)
.milestone-buttons
- if can?(current_user, :admin_milestone, @project)
- = link_to edit_project_milestone_path(@project, @milestone), class: "btn btn-grouped btn-nr" do
- Edit
+ = link_to edit_project_milestone_path(@project, @milestone), class: 'btn btn-grouped btn-nr' do
+ = _('Edit')
- if @project.group
%button.js-promote-project-milestone-button.btn.btn-grouped{ data: { toggle: 'modal',
@@ -39,13 +39,13 @@
#promote-milestone-modal
- if @milestone.active?
- = link_to 'Close milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-nr btn-grouped"
+ = link_to _('Close milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: 'btn btn-close btn-nr btn-grouped'
- else
- = link_to 'Reopen milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-nr btn-grouped"
+ = link_to _('Reopen milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: 'btn btn-reopen btn-nr btn-grouped'
= render 'shared/milestones/delete_button'
- %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: "#" }
+ %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: '#' }
= icon('angle-double-left')
.detail-page-description.milestone-detail
@@ -62,10 +62,10 @@
- if can?(current_user, :read_issue, @project) && @milestone.total_items_count(current_user).zero?
.alert.alert-success.prepend-top-default
- %span Assign some issues to this milestone.
+ %span= _('Assign some issues to this milestone.')
- elsif @milestone.complete?(current_user) && @milestone.active?
.alert.alert-success.prepend-top-default
- %span All issues for this milestone are closed. You may close this milestone now.
+ %span= _('All issues for this milestone are closed. You may close this milestone now.')
= render 'deprecation_message'
= render 'shared/milestones/tabs', milestone: @milestone
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 21b105e6f80..c031815200b 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -57,7 +57,7 @@
%td
- if mirror.last_error.present?
.badge.mirror-error-badge{ data: { toggle: 'tooltip', html: 'true' }, title: html_escape(mirror.last_error.try(:strip)) }= _('Error')
- %td.mirror-action-buttons
+ %td
.btn-group.mirror-actions-group.pull-right{ role: 'group' }
- if mirror.ssh_key_auth?
= clipboard_button(text: mirror.ssh_public_key, class: 'btn btn-default', title: _('Copy SSH public key'))
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index a760d02c4c3..ff7c36c2d5b 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -16,6 +16,9 @@
= _('A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}.').html_safe % { among_other_things_link: among_other_things_link }
%p
= _('All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings.')
+ %p
+ - pages_getting_started_guide = link_to _('Pages getting started guide'), help_page_path("user/project/pages/getting_started_part_two", anchor: "fork-a-project-to-get-started-from"), target: '_blank'
+ = _('Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}.').html_safe % { pages_getting_started_guide: pages_getting_started_guide }
.md
= brand_new_project_guidelines
%p
@@ -33,7 +36,7 @@
%span.d-block.d-sm-none Blank
%li.nav-item{ role: 'presentation' }
%a.nav-link{ href: '#create-from-template-pane', id: 'create-from-template-tab', data: { toggle: 'tab', track_label: 'create_from_template', track_event: "click_tab" }, role: 'tab' }
- %span.d-none.d-sm-block Create from template
+ %span.d-none.d-sm-block.qa-project-create-from-template-tab Create from template
%span.d-block.d-sm-none Template
%li.nav-item{ role: 'presentation' }
%a.nav-link{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab', track_label: 'import_project', track_event: "click_tab" }, role: 'tab' }
diff --git a/app/views/projects/pages/_destroy.haml b/app/views/projects/pages/_destroy.haml
index ae8c801b705..138e2864bad 100644
--- a/app/views/projects/pages/_destroy.haml
+++ b/app/views/projects/pages/_destroy.haml
@@ -9,4 +9,4 @@
.form-actions
= link_to 'Remove pages', project_pages_path(@project), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove"
- else
- .nothing-here-block Only the project owner can remove pages
+ .nothing-here-block Only project maintainers can remove pages
diff --git a/app/views/projects/pages/_https_only.html.haml b/app/views/projects/pages/_https_only.html.haml
index ce3ef29c32e..74478ee011c 100644
--- a/app/views/projects/pages/_https_only.html.haml
+++ b/app/views/projects/pages/_https_only.html.haml
@@ -3,7 +3,7 @@
.form-check
= f.check_box :pages_https_only, class: 'form-check-input', disabled: pages_https_only_disabled?
= f.label :pages_https_only, class: pages_https_only_label_class do
- %strong Force domains with SSL certificates to use HTTPS
+ %strong Force HTTPS (requires valid certificates)
- unless pages_https_only_disabled?
.prepend-top-10
diff --git a/app/views/projects/pages_domains/_form.html.haml b/app/views/projects/pages_domains/_form.html.haml
index 0d848f7899c..b7b46c56c37 100644
--- a/app/views/projects/pages_domains/_form.html.haml
+++ b/app/views/projects/pages_domains/_form.html.haml
@@ -6,25 +6,24 @@
.form-group.row
= f.label :domain, class: 'col-form-label col-sm-2' do
- Domain
+ = _("Domain")
.col-sm-10
= f.text_field :domain, required: true, autocomplete: 'off', class: 'form-control', disabled: @domain.persisted?
- if Gitlab.config.pages.external_https
.form-group.row
= f.label :certificate, class: 'col-form-label col-sm-2' do
- Certificate (PEM)
+ = _("Certificate (PEM)")
.col-sm-10
= f.text_area :certificate, rows: 5, class: 'form-control'
- %span.help-inline Upload a certificate for your domain with all intermediates
+ %span.help-inline= _("Upload a certificate for your domain with all intermediates")
.form-group.row
= f.label :key, class: 'col-form-label col-sm-2' do
- Key (PEM)
+ = _("Key (PEM)")
.col-sm-10
= f.text_area :key, rows: 5, class: 'form-control'
- %span.help-inline Upload a private key for your certificate
+ %span.help-inline= _("Upload a private key for your certificate")
- else
.nothing-here-block
- Support for custom certificates is disabled.
- Ask your system's administrator to enable it.
+ = _("Support for custom certificates is disabled. Ask your system's administrator to enable it.")
diff --git a/app/views/projects/pages_domains/edit.html.haml b/app/views/projects/pages_domains/edit.html.haml
index 342b1482df7..e11387ae742 100644
--- a/app/views/projects/pages_domains/edit.html.haml
+++ b/app/views/projects/pages_domains/edit.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs "Pages", project_pages_path(@project)
+- add_to_breadcrumbs _("Pages"), project_pages_path(@project)
- breadcrumb_title @domain.domain
- page_title @domain.domain
%h3.page-title
@@ -8,4 +8,4 @@
= form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'fieldset-form' } do |f|
= render 'form', { f: f }
.form-actions
- = f.submit 'Save Changes', class: "btn btn-success"
+ = f.submit _('Save Changes'), class: "btn btn-success"
diff --git a/app/views/projects/pages_domains/new.html.haml b/app/views/projects/pages_domains/new.html.haml
index 94ad1470052..c7cefa87c76 100644
--- a/app/views/projects/pages_domains/new.html.haml
+++ b/app/views/projects/pages_domains/new.html.haml
@@ -1,12 +1,12 @@
-- add_to_breadcrumbs "Pages", project_pages_path(@project)
-- page_title 'New Pages Domain'
+- add_to_breadcrumbs _("Pages"), project_pages_path(@project)
+- page_title _('New Pages Domain')
%h3.page-title
- New Pages Domain
+ = _("New Pages Domain")
%hr.clearfix
%div
= form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'fieldset-form' } do |f|
= render 'form', { f: f }
.form-actions
- = f.submit 'Create New Domain', class: "btn btn-success"
+ = f.submit _('Create New Domain'), class: "btn btn-success"
.float-right
= link_to _('Cancel'), project_pages_path(@project), class: 'btn btn-cancel'
diff --git a/app/views/projects/pages_domains/show.html.haml b/app/views/projects/pages_domains/show.html.haml
index a8484187493..82147568981 100644
--- a/app/views/projects/pages_domains/show.html.haml
+++ b/app/views/projects/pages_domains/show.html.haml
@@ -1,6 +1,6 @@
-- add_to_breadcrumbs "Pages", project_pages_path(@project)
+- add_to_breadcrumbs _("Pages"), project_pages_path(@project)
- breadcrumb_title @domain.domain
-- page_title "#{@domain.domain}", 'Pages Domains'
+- page_title "#{@domain.domain}", _('Pages Domains')
- dns_record = "#{@domain.domain} CNAME #{@domain.project.pages_subdomain}.#{Settings.pages.host}."
- verification_enabled = Gitlab::CurrentSettings.pages_domain_verification_enabled?
@@ -9,37 +9,37 @@
= content_for :flash_message do
.alert.alert-warning
.container-fluid.container-limited
- This domain is not verified. You will need to verify ownership before access is enabled.
+ = _("This domain is not verified. You will need to verify ownership before access is enabled.")
%h3.page-title.with-button
- = link_to 'Edit', edit_project_pages_domain_path(@project, @domain), class: 'btn btn-success float-right'
- Pages Domain
+ = link_to _('Edit'), edit_project_pages_domain_path(@project, @domain), class: 'btn btn-success float-right'
+ = _("Pages Domain")
.table-holder
%table.table
%tr
%td
- Domain
+ = _("Domain")
%td
= link_to @domain.url do
= @domain.url
= icon('external-link')
%tr
%td
- DNS
+ = _("DNS")
%td
.input-group
= text_field_tag :domain_dns, dns_record , class: "monospace js-select-on-focus form-control", readonly: true
.input-group-append
= clipboard_button(target: '#domain_dns', class: 'btn-default input-group-text d-none d-sm-block')
%p.form-text.text-muted
- To access this domain create a new DNS record
+ = _("To access this domain create a new DNS record")
- if verification_enabled
- verification_record = "#{@domain.verification_domain} TXT #{@domain.keyed_verification_code}"
%tr
%td
- Verification status
+ = _("Verification status")
%td
= form_tag verify_project_pages_domain_path(@project, @domain) do
.status-badge
@@ -53,17 +53,16 @@
.input-group-append
= clipboard_button(target: '#domain_verification', class: 'btn-default d-none d-sm-block')
%p.form-text.text-muted
- - help_link = help_page_path('user/project/pages/getting_started_part_three.md', anchor: 'dns-txt-record')
- To #{link_to 'verify ownership', help_link} of your domain,
- add the above key to a TXT record within to your DNS configuration.
+ - link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/getting_started_part_three.md', anchor: 'dns-txt-record'))
+ = _("To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration.").html_safe % { link_to_help: link_to_help }
%tr
%td
- Certificate
+ = _("Certificate")
%td
- if @domain.certificate_text
%pre
= @domain.certificate_text
- else
.light
- missing
+ = _("missing")
diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml
index 259979417e0..1121cf06b5c 100644
--- a/app/views/projects/pipeline_schedules/_form.html.haml
+++ b/app/views/projects/pipeline_schedules/_form.html.haml
@@ -34,7 +34,7 @@
= n_('Reveal value', 'Reveal values', @schedule.variables.size)
.form-group.row
.col-md-9
- = f.label :active, s_('PipelineSchedules|Activated'), class: 'label-bold'
+ = f.label :active, s_('PipelineSchedules|Activated'), class: 'label-bold'
%div
= f.check_box :active, required: false, value: @schedule.active?
= _('Active')
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 0f0114d513c..55adeb345ab 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -6,25 +6,24 @@
= preserve(markdown(commit.description, pipeline: :single_line))
.info-well
- - if commit.status
- .well-segment.pipeline-info
- .icon-container
- = icon('clock-o')
- = pluralize @pipeline.total_size, "job"
- - if @pipeline.ref
- from
- - if @pipeline.ref_exists?
- = link_to @pipeline.ref, project_ref_path(@project, @pipeline.ref), class: "ref-name"
- - else
- %span.ref-name
- = @pipeline.ref
- - if @pipeline.duration
- in
- = time_interval_in_words(@pipeline.duration)
- - if @pipeline.queued_duration
- = "(queued for #{time_interval_in_words(@pipeline.queued_duration)})"
+ .well-segment.pipeline-info
+ .icon-container
+ = icon('clock-o')
+ = pluralize @pipeline.total_size, "job"
+ - if @pipeline.ref
+ from
+ - if @pipeline.ref_exists?
+ = link_to @pipeline.ref, project_ref_path(@project, @pipeline.ref), class: "ref-name"
+ - else
+ %span.ref-name
+ = @pipeline.ref
+ - if @pipeline.duration
+ in
+ = time_interval_in_words(@pipeline.duration)
+ - if @pipeline.queued_duration
+ = "(queued for #{time_interval_in_words(@pipeline.queued_duration)})"
- .well-segment
+ .well-segment.qa-pipeline-badges
.icon-container
= sprite_icon('flag')
- if @pipeline.latest?
@@ -49,7 +48,7 @@
content: "<a class='autodevops-link' href='#{popover_content_url}' target='_blank' rel='noopener noreferrer nofollow'>#{popover_content_text}</a>",
} }
Auto DevOps
- - if @pipeline.merge_request?
+ - if @pipeline.merge_request_event?
%span.js-pipeline-url-mergerequest.badge.badge-info.has-tooltip{ title: "This pipeline is run in a merge request context" }
merge request
- if @pipeline.stuck?
diff --git a/app/views/projects/pipelines/charts/_pipeline_times.haml b/app/views/projects/pipelines/charts/_pipeline_times.haml
index c23fe6ff170..c0ac79ed5f8 100644
--- a/app/views/projects/pipelines/charts/_pipeline_times.haml
+++ b/app/views/projects/pipelines/charts/_pipeline_times.haml
@@ -1,7 +1,7 @@
-%div
- %p.light
- = _("Commit duration in minutes for last 30 commits")
+%p.light
+ = _("Commit duration in minutes for last 30 commits")
+%div
%canvas#build_timesChart{ height: 200 }
-# haml-lint:disable InlineJavaScript
diff --git a/app/views/projects/pipelines/charts/_pipelines.haml b/app/views/projects/pipelines/charts/_pipelines.haml
index 14b3d47a9c2..47f1f074210 100644
--- a/app/views/projects/pipelines/charts/_pipelines.haml
+++ b/app/views/projects/pipelines/charts/_pipelines.haml
@@ -13,18 +13,21 @@
%p.light
= _("Pipelines for last week")
(#{date_from_to(Date.today - 7.days, Date.today)})
- %canvas#weekChart{ height: 200 }
+ %div
+ %canvas#weekChart{ height: 200 }
.prepend-top-default
%p.light
= _("Pipelines for last month")
(#{date_from_to(Date.today - 30.days, Date.today)})
- %canvas#monthChart{ height: 200 }
+ %div
+ %canvas#monthChart{ height: 200 }
.prepend-top-default
%p.light
= _("Pipelines for last year")
- %canvas#yearChart.padded{ height: 250 }
+ %div
+ %canvas#yearChart.padded{ height: 250 }
-# haml-lint:disable InlineJavaScript
%script#pipelinesChartsData{ type: "application/json" }
diff --git a/app/views/projects/project_members/_groups.html.haml b/app/views/projects/project_members/_groups.html.haml
index 3f05e06b0c6..b5d397e3065 100644
--- a/app/views/projects/project_members/_groups.html.haml
+++ b/app/views/projects/project_members/_groups.html.haml
@@ -1,7 +1,6 @@
.card.project-members-groups
.card-header
- Groups with access to
- %strong= @project.name
+ = _("Groups with access to <strong>%{project_name}</strong>").html_safe % { project_name: sanitize_project_name(@project.name) }
%span.badge.badge-pill= group_links.size
%ul.content-list.members-list
= render partial: 'shared/members/group', collection: group_links, as: :group_link
diff --git a/app/views/projects/project_members/_new_project_group.html.haml b/app/views/projects/project_members/_new_project_group.html.haml
index 88e68f89024..079811e4e79 100644
--- a/app/views/projects/project_members/_new_project_group.html.haml
+++ b/app/views/projects/project_members/_new_project_group.html.haml
@@ -10,8 +10,9 @@
= select_tag :link_group_access, options_for_select(ProjectGroupLink.access_options, ProjectGroupLink.default_access), class: "form-control select-control"
= icon('chevron-down')
.form-text.text-muted.append-bottom-10
- = link_to _("Read more"), help_page_path("user/permissions")
- about role permissions
+ - permissions_docs_path = help_page_path('user/permissions')
+ - link_start = %q{<a href="%{url}">}.html_safe % { url: permissions_docs_path }
+ = _("%{link_start}Read more%{link_end} about role permissions").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.form-group
= label_tag :expires_at, _('Access expiration date'), class: 'label-bold'
.clearable-input
diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml
index 1de7d9c6957..0590578c3fe 100644
--- a/app/views/projects/project_members/_new_project_member.html.haml
+++ b/app/views/projects/project_members/_new_project_member.html.haml
@@ -2,20 +2,21 @@
.col-sm-12
= form_for @project_member, as: :project_member, url: project_project_members_path(@project), html: { class: 'users-project-form' } do |f|
.form-group
- = label_tag :user_ids, "Select members to invite", class: "label-bold"
+ = label_tag :user_ids, _("Select members to invite"), class: "label-bold"
= users_select_tag(:user_ids, multiple: true, class: "input-clamp qa-member-select-input", scope: :all, email_user: true, placeholder: "Search for members to update or invite")
.form-group
- = label_tag :access_level, "Choose a role permission", class: "label-bold"
+ = label_tag :access_level, _("Choose a role permission"), class: "label-bold"
.select-wrapper
= select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "form-control project-access-select select-control"
= icon('chevron-down')
.form-text.text-muted.append-bottom-10
- = link_to "Read more", help_page_path("user/permissions")
- about role permissions
+ - permissions_docs_path = help_page_path('user/permissions')
+ - link_start = %q{<a href="%{url}">}.html_safe % { url: permissions_docs_path }
+ = _("%{link_start}Read more%{link_end} about role permissions").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.form-group
.clearable-input
- = label_tag :expires_at, 'Access expiration date', class: 'label-bold'
+ = label_tag :expires_at, _('Access expiration date'), class: 'label-bold'
= text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
%i.clear-icon.js-clear-input
- = f.submit "Add to project", class: "btn btn-success qa-add-member-button"
- = link_to "Import", import_project_project_members_path(@project), class: "btn btn-default", title: "Import members from another project"
+ = f.submit _("Add to project"), class: "btn btn-success qa-add-member-button"
+ = link_to _("Import"), import_project_project_members_path(@project), class: "btn btn-default", title: _("Import members from another project")
diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml
index 9682f8ac922..e0dd386fc5d 100644
--- a/app/views/projects/project_members/_team.html.haml
+++ b/app/views/projects/project_members/_team.html.haml
@@ -4,14 +4,13 @@
.card
.card-header.flex-project-members-panel
%span.flex-project-title
- Members of
- %strong= project.name
+ = _("Members of <strong>%{project_name}</strong>").html_safe % { project_name: sanitize_project_name(project.name) }
%span.badge.badge-pill= members.total_count
- = form_tag project_project_members_path(project), method: :get, class: 'form-inline member-search-form flex-project-members-form' do
+ = form_tag project_project_members_path(project), method: :get, class: 'form-inline member-search-form flex-project-members-form' do
.form-group
.position-relative
- = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false }
- %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" }
+ = search_field_tag :search, params[:search], { placeholder: _('Find existing members by name'), class: 'form-control', spellcheck: false }
+ %button.member-search-btn{ type: "submit", "aria-label" => _("Submit search") }
= icon("search")
= render 'shared/members/sort_dropdown'
%ul.content-list.members-list.qa-members-list
diff --git a/app/views/projects/project_members/import.html.haml b/app/views/projects/project_members/import.html.haml
index 8b93e81cd31..bcca943de6a 100644
--- a/app/views/projects/project_members/import.html.haml
+++ b/app/views/projects/project_members/import.html.haml
@@ -1,15 +1,15 @@
-- page_title "Import members"
+- page_title _("Import members")
%h3.page-title
- Import members from another project
+ = _("Import members from another project")
%p.light
- Only project members will be imported. Group members will be skipped.
+ = _("Only project members will be imported. Group members will be skipped.")
%hr
= form_tag apply_import_project_project_members_path(@project), method: 'post' do
.form-group.row
- = label_tag :source_project_id, "Project", class: 'col-form-label col-sm-2'
+ = label_tag :source_project_id, _("Project"), class: 'col-form-label col-sm-2'
.col-sm-10= select_tag(:source_project_id, options_from_collection_for_select(@projects, :id, :name_with_namespace), prompt: "Select project", class: "select2 lg", required: true)
.form-actions
- = button_tag 'Import project members', class: "btn btn-success"
- = link_to "Cancel", project_project_members_path(@project), class: "btn btn-cancel"
+ = button_tag _('Import project members'), class: "btn btn-success"
+ = link_to _("Cancel"), project_project_members_path(@project), class: "btn btn-cancel"
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 14ed3345765..242ff91f539 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -1,39 +1,34 @@
-- page_title "Members"
+- page_title _("Members")
.row.prepend-top-default
.col-lg-12
%h4
- Project members
+ = _("Project members")
- if can?(current_user, :admin_project_member, @project)
%p
- You can invite a new member to
- %strong= @project.name
- or invite another group.
+ = _("You can invite a new member to <strong>%{project_name}</strong> or invite another group.").html_safe % { project_name: sanitize_project_name(@project.name) }
- else
%p
- Members can be added by project
- %i Maintainers
- or
- %i Owners
+ = _("Members can be added by project <i>Maintainers</i> or <i>Owners</i>").html_safe
.light
- if can?(current_user, :admin_project_member, @project)
%ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
%li.nav-tab{ role: 'presentation' }
- %a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' } Invite member
+ %a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' }= _("Invite member")
- if @project.allowed_to_share_with_group?
%li.nav-tab{ role: 'presentation' }
- %a.nav-link{ href: '#invite-group-pane', id: 'invite-group-tab', data: { toggle: 'tab' }, role: 'tab' } Invite group
+ %a.nav-link{ href: '#invite-group-pane', id: 'invite-group-tab', data: { toggle: 'tab' }, role: 'tab' }= _("Invite group")
.tab-content.gitlab-tab-content
.tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
- = render 'projects/project_members/new_project_member', tab_title: 'Invite member'
+ = render 'projects/project_members/new_project_member', tab_title: _('Invite member')
.tab-pane{ id: 'invite-group-pane', role: 'tabpanel' }
- = render 'projects/project_members/new_project_group', tab_title: 'Invite group'
+ = render 'projects/project_members/new_project_group', tab_title: _('Invite group')
= render 'shared/members/requests', membership_source: @project, requesters: @requesters
.clearfix
%h5.member.existing-title
- Existing members and groups
+ = _("Existing members and groups")
- if @group_links.any?
= render 'projects/project_members/groups', group_links: @group_links
diff --git a/app/views/projects/project_templates/_built_in_templates.html.haml b/app/views/projects/project_templates/_built_in_templates.html.haml
index 5b4d8927045..6159f1c3542 100644
--- a/app/views/projects/project_templates/_built_in_templates.html.haml
+++ b/app/views/projects/project_templates/_built_in_templates.html.haml
@@ -1,7 +1,7 @@
- Gitlab::ProjectTemplate.all.each do |template|
.template-option.d-flex.align-items-center
- .logo.append-right-10
- = custom_icon(template.logo, size: 40)
+ .logo.append-right-10.px-1
+ = image_tag template.logo, size: 32, class: "btn-template-icon icon-#{template.name}"
.description
%strong
= template.title
@@ -12,6 +12,6 @@
%a.btn.btn-default.append-right-10{ href: template.preview, rel: 'noopener noreferrer', target: '_blank', data: { track_label: "create_from_template", track_property: "template_preview", track_event: "click_button", track_value: template.name } }
= _("Preview")
%label.btn.btn-success.template-button.choose-template.append-bottom-0{ for: template.name }
- %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name, data: { track_label: "create_from_template", track_property: "template_use", track_event: "click_button" } }
+ %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name, data: { track_label: "create_from_template", track_property: "template_use", track_event: "click_button" } }
%span
= _("Use template")
diff --git a/app/views/projects/protected_branches/shared/_index.html.haml b/app/views/projects/protected_branches/shared/_index.html.haml
index 539b184e5c2..4997770321e 100644
--- a/app/views/projects/protected_branches/shared/_index.html.haml
+++ b/app/views/projects/protected_branches/shared/_index.html.haml
@@ -12,7 +12,7 @@
%p
By default, protected branches are designed to:
%ul
- %li prevent their creation, if not already created, from everybody except Maintainers
+ %li prevent their creation, if not already created, from everybody except users who are allowed to merge
%li prevent pushes from everybody except Maintainers
%li prevent <strong>anyone</strong> from force pushing to the branch
%li prevent <strong>anyone</strong> from deleting the branch
diff --git a/app/views/projects/protected_branches/shared/_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_protected_branch.html.haml
index 81b07af22ad..bb7998f739d 100644
--- a/app/views/projects/protected_branches/shared/_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_protected_branch.html.haml
@@ -15,7 +15,7 @@
= link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit-sha')
= time_ago_with_tooltip(commit.committed_date)
- else
- (branch was removed from repository)
+ (branch was deleted from repository)
= yield
diff --git a/app/views/projects/releases/index.html.haml b/app/views/projects/releases/index.html.haml
index f01d4e826b9..28bb4e032eb 100644
--- a/app/views/projects/releases/index.html.haml
+++ b/app/views/projects/releases/index.html.haml
@@ -2,4 +2,4 @@
- page_title _('Releases')
%div{ class: container_class }
- #js-releases-page{ data: { project_id: @project.id, illustration_path: image_path('illustrations/releases.svg'), documentation_path: help_page_path('user/project/releases') } }
+ #js-releases-page{ data: { project_id: @project.id, illustration_path: image_path('illustrations/releases.svg'), documentation_path: help_page_path('user/project/releases/index') } }
diff --git a/app/views/projects/runners/_group_runners.html.haml b/app/views/projects/runners/_group_runners.html.haml
index a6c16c70313..a24ada53bac 100644
--- a/app/views/projects/runners/_group_runners.html.haml
+++ b/app/views/projects/runners/_group_runners.html.haml
@@ -32,6 +32,6 @@
- else
%h4.underlined-title
- = _('Available group Runners : %{runners}').html_safe % { runners: @group_runners.count }
+ = _('Available group Runners: %{runners}').html_safe % { runners: @group_runners.count }
%ul.bordered-list
= render partial: 'projects/runners/runner', collection: @group_runners, as: :runner
diff --git a/app/views/projects/serverless/functions/index.html.haml b/app/views/projects/serverless/functions/index.html.haml
index f650fa0f38f..635580eac5c 100644
--- a/app/views/projects/serverless/functions/index.html.haml
+++ b/app/views/projects/serverless/functions/index.html.haml
@@ -5,7 +5,7 @@
- status_path = project_serverless_functions_path(@project, format: :json)
- clusters_path = project_clusters_path(@project)
-.serverless-functions-page.js-serverless-functions-page{ data: { status_path: status_path, installed: @installed, clusters_path: clusters_path, help_path: help_page_path('user/project/clusters/serverless/index') } }
+.serverless-functions-page.js-serverless-functions-page{ data: { status_path: status_path, installed: @installed, clusters_path: clusters_path, help_path: help_page_path('user/project/clusters/serverless/index') } }
%div{ class: [container_class, ('limit-container-width' unless fluid_layout)] }
.js-serverless-functions-notice
diff --git a/app/views/projects/serverless/functions/show.html.haml b/app/views/projects/serverless/functions/show.html.haml
new file mode 100644
index 00000000000..29737b7014a
--- /dev/null
+++ b/app/views/projects/serverless/functions/show.html.haml
@@ -0,0 +1,16 @@
+- @no_container = true
+- @content_class = "limit-container-width" unless fluid_layout
+
+- add_to_breadcrumbs('Serverless', project_serverless_functions_path(@project))
+
+- page_title @service[:name]
+
+.serverless-function-details-page.js-serverless-function-details-page{ data: { service: @service.as_json } }
+%div{ class: [container_class, ('limit-container-width' unless fluid_layout)] }
+ .top-area.adjust
+ .serverless-function-details#js-serverless-function-details
+
+ .js-serverless-function-notice
+ .flash-container
+
+ .function-holder.js-function-holder.input-group
diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml
index 597c029f755..a1d74b91002 100644
--- a/app/views/projects/services/prometheus/_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_metrics.html.haml
@@ -1,6 +1,6 @@
- project = local_assigns.fetch(:project)
-.card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/metrics') } }
+.card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/index') } }
.card-header
= s_('PrometheusService|Common metrics')
%span.badge.badge-pill.js-monitored-count 0
diff --git a/app/views/projects/services/prometheus/_show.html.haml b/app/views/projects/services/prometheus/_show.html.haml
index 1d0b0265bb7..6aafa85e99a 100644
--- a/app/views/projects/services/prometheus/_show.html.haml
+++ b/app/views/projects/services/prometheus/_show.html.haml
@@ -4,7 +4,9 @@
= s_('PrometheusService|Metrics')
%p
= s_('PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters.')
- = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus_library/metrics'), target: '_blank', rel: "noopener noreferrer"
+ = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus_library/index'), target: '_blank', rel: "noopener noreferrer"
.col-lg-9
= render 'projects/services/prometheus/metrics', project: @project
+
+= render_if_exists 'projects/services/prometheus/external_alerts', project: @project
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 5ec5a06396e..8c4d1c32ebe 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -4,10 +4,6 @@
= form_errors(@project)
%fieldset.builds-feature.js-auto-devops-settings
.form-group
- - message = auto_devops_warning_message(@project)
- - if message
- %p.auto-devops-warning-message.settings-message.text-center
- = message.html_safe
= f.fields_for :auto_devops_attributes, @auto_devops do |form|
.card.auto-devops-card
.card-body
@@ -21,19 +17,12 @@
= s_('CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found.')
= link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank'
.card-footer.js-extra-settings{ class: @project.auto_devops_enabled? || 'hidden' }
- = form.label :domain do
- %strong= _('Domain')
- = form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
- .form-text.text-muted
- = s_('CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.')
- - if cluster_ingress_ip = cluster_ingress_ip(@project)
- = s_('%{nip_domain} can be used as an alternative to a custom domain.').html_safe % { nip_domain: "<code>#{cluster_ingress_ip}.nip.io</code>".html_safe }
- = link_to icon('question-circle'), help_page_path('topics/autodevops/index.md', anchor: 'auto-devops-base-domain'), target: '_blank'
-
+ %p.settings-message.text-center
+ - kubernetes_cluster_link = help_page_path('user/project/clusters/index')
+ - kubernetes_cluster_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: kubernetes_cluster_link }
+ = s_('CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly.').html_safe % { kubernetes_cluster_start: kubernetes_cluster_start, kubernetes_cluster_end: '</a>'.html_safe }
%label.prepend-top-10
%strong= s_('CICD|Deployment strategy')
- %p.settings-message.text-center
- = s_('CICD|Deployment strategy needs a domain name to work correctly.')
.form-check
= form.radio_button :deploy_strategy, 'continuous', class: 'form-check-input'
= form.label :deploy_strategy_continuous, class: 'form-check-label' do
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index bb328f5344c..bfb275b9ef5 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -110,6 +110,9 @@
%li
go test -cover (Go)
%code coverage: \d+.\d+% of statements
+ %li
+ nyc npm test (NodeJS) -
+ %code All files[^|]*\|[^|]*\s+([\d\.]+)
= f.submit _('Save changes'), class: "btn btn-success"
diff --git a/app/views/projects/settings/operations/_error_tracking.html.haml b/app/views/projects/settings/operations/_error_tracking.html.haml
new file mode 100644
index 00000000000..6b15331db01
--- /dev/null
+++ b/app/views/projects/settings/operations/_error_tracking.html.haml
@@ -0,0 +1,18 @@
+- return unless can?(current_user, :read_environment, @project)
+
+- setting = error_tracking_setting
+
+%section.settings.expanded.border-0.no-animate
+ .settings-header
+ %h4
+ = _('Error Tracking')
+ %p
+ = _('To link Sentry to GitLab, enter your Sentry URL and Auth Token.')
+ = link_to _('More information'), help_page_path('user/project/operations/error_tracking'), target: '_blank', rel: 'noopener noreferrer'
+ .settings-content
+ .js-error-tracking-form{ data: { list_projects_endpoint: list_projects_project_error_tracking_index_path(@project, format: :json),
+ operations_settings_endpoint: project_settings_operations_path(@project),
+ project: error_tracking_setting_project_json,
+ api_host: setting.api_host,
+ enabled: setting.enabled.to_json,
+ token: setting.token } }
diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml
new file mode 100644
index 00000000000..2822debe426
--- /dev/null
+++ b/app/views/projects/settings/operations/show.html.haml
@@ -0,0 +1,6 @@
+- @content_class = 'limit-container-width' unless fluid_layout
+- page_title _('Operations Settings')
+- breadcrumb_title _('Operations Settings')
+
+= render 'projects/settings/operations/error_tracking', expanded: true
+= render_if_exists 'projects/settings/operations/tracing'
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index a4974d89c1a..7682d01a5a1 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -1,12 +1,16 @@
- page_title _("Snippets")
-- if current_user
- .top-area
- - include_private = @project.team.member?(current_user) || current_user.admin?
- = render partial: 'snippets/snippets_scope_menu', locals: { subject: @project, include_private: include_private }
+- if @snippets.exists?
+ - if current_user
+ .top-area
+ - include_private = @project.team.member?(current_user) || current_user.admin?
+ = render partial: 'snippets/snippets_scope_menu', locals: { subject: @project, include_private: include_private }
- .nav-controls
- if can?(current_user, :create_project_snippet, @project)
- = link_to _("New snippet"), new_project_snippet_path(@project), class: "btn btn-success", title: _("New snippet")
+ .nav-controls
+ - if can?(current_user, :create_project_snippet, @project)
+ = link_to _("New snippet"), new_project_snippet_path(@project), class: "btn btn-success", title: _("New snippet")
-= render 'snippets/snippets'
+ = render 'shared/snippets/list'
+- else
+ = render 'shared/empty_states/snippets', button_path: new_namespace_project_snippet_path(@project.namespace, @project)
diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml
index 26b333d4ecf..d64e3a49a81 100644
--- a/app/views/projects/snippets/new.html.haml
+++ b/app/views/projects/snippets/new.html.haml
@@ -1,8 +1,8 @@
- add_to_breadcrumbs _("Snippets"), project_snippets_path(@project)
- breadcrumb_title _("New")
-- page_title _("New Snippets")
+- page_title _("New Snippet")
%h3.page-title
- = _('New Snippet')
+ = _("New Snippet")
%hr
= render "shared/snippets/form", url: project_snippets_path(@project, @snippet)
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index f55202c2c5f..cc203cfad86 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -28,7 +28,7 @@
= render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
- if can?(current_user, :push_code, @project)
- = link_to edit_project_tag_release_path(@project, tag.name), class: 'btn has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
+ = link_to edit_project_tag_release_path(@project, tag.name), class: 'btn btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
= icon("pencil")
- if can?(current_user, :admin_project, @project)
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 026bc44a05f..458096f9dd6 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -27,7 +27,7 @@
- if can?(current_user, :push_code, @project)
= link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn' do
= s_('TagsPage|New tag')
- = link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn rss-btn has-tooltip' do
+ = link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn d-none d-sm-inline-block has-tooltip' do
= icon("rss")
= render_if_exists 'projects/commits/mirror_status'
diff --git a/app/views/projects/tags/releases/edit.html.haml b/app/views/projects/tags/releases/edit.html.haml
index 52c6c7ec424..e4efeed04f0 100644
--- a/app/views/projects/tags/releases/edit.html.haml
+++ b/app/views/projects/tags/releases/edit.html.haml
@@ -12,8 +12,7 @@
= form_for(@release, method: :put, url: project_tag_release_path(@project, @tag.name),
- html: { class: 'common-note-form release-form js-quick-submit' },
- data: { markdown_version: @release.cached_markdown_version }) do |f|
+ html: { class: 'common-note-form release-form js-quick-submit' }) do |f|
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do
= render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here…"
= render 'shared/notes/hints'
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index 15a960f81b8..8ee1407d9d9 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -20,10 +20,10 @@
.nav-controls.controls-flex
- if can?(current_user, :push_code, @project)
- = link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
+ = link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-edit controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
= icon("pencil")
= link_to project_tree_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse files') do
- = icon('files-o')
+ = sprite_icon('folder-open')
= link_to project_commits_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse commits') do
= icon('history')
.btn-container.controls-item
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index 4e9a119ac66..ec8e5234bd4 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -40,27 +40,24 @@
#{ _('New directory') }
- elsif can?(current_user, :fork_project, @project) && can?(current_user, :create_merge_request_in, @project)
%li
- - continue_params = { to: project_new_blob_path(@project, @id),
- notice: edit_in_new_fork_notice,
+ - continue_params = { to: project_new_blob_path(@project, @id),
+ notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now }
- - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id,
- continue: continue_params)
+ - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
= link_to fork_path, method: :post do
#{ _('New file') }
%li
- - continue_params = { to: request.fullpath,
- notice: edit_in_new_fork_notice + " Try to upload a file again.",
+ - continue_params = { to: request.fullpath,
+ notice: edit_in_new_fork_notice + " Try to upload a file again.",
notice_now: edit_in_new_fork_notice_now }
- - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id,
- continue: continue_params)
+ - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
= link_to fork_path, method: :post do
#{ _('Upload file') }
%li
- - continue_params = { to: request.fullpath,
- notice: edit_in_new_fork_notice + " Try to create a new directory again.",
+ - continue_params = { to: request.fullpath,
+ notice: edit_in_new_fork_notice + " Try to create a new directory again.",
notice_now: edit_in_new_fork_notice_now }
- - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id,
- continue: continue_params)
+ - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
= link_to fork_path, method: :post do
#{ _('New directory') }
diff --git a/app/views/projects/triggers/_trigger.html.haml b/app/views/projects/triggers/_trigger.html.haml
index 7e4618e1a88..6f6f1e5e0c5 100644
--- a/app/views/projects/triggers/_trigger.html.haml
+++ b/app/views/projects/triggers/_trigger.html.haml
@@ -1,6 +1,6 @@
%tr
%td
- - if can?(current_user, :admin_trigger, trigger)
+ - if trigger.has_token_exposed?
%span= trigger.token
= clipboard_button(text: trigger.token, title: "Copy trigger token to clipboard")
- else
diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml
index 7d8826e540c..5bb69563b51 100644
--- a/app/views/projects/wikis/_form.html.haml
+++ b/app/views/projects/wikis/_form.html.haml
@@ -1,13 +1,9 @@
- commit_message = @page.persisted? ? s_("WikiPageEdit|Update %{page_title}") : s_("WikiPageCreate|Create %{page_title}")
- commit_message = commit_message % { page_title: @page.title }
-- if params[:legacy_render] || !commonmark_for_repositories_enabled?
- - markdown_version = CacheMarkdownField::CACHE_REDCARPET_VERSION
-- else
- - markdown_version = 0
= form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post,
html: { class: 'wiki-form common-note-form prepend-top-default js-quick-submit' },
- data: { markdown_version: markdown_version, uploads_path: uploads_path } do |f|
+ data: { uploads_path: uploads_path } do |f|
= form_errors(@page)
- if @page.persisted?
@@ -16,7 +12,7 @@
.form-group.row
.col-sm-12= f.label :title, class: 'control-label-full-width'
.col-sm-12
- = f.text_field :title, class: 'form-control', value: @page.title
+ = f.text_field :title, class: 'form-control qa-wiki-title-textbox', value: @page.title
- if @page.persisted?
%span.edit-wiki-page-slug-tip
= icon('lightbulb-o')
@@ -31,7 +27,7 @@
.col-sm-12= f.label :content, class: 'control-label-full-width'
.col-sm-12
= render layout: 'projects/md_preview', locals: { url: project_wiki_preview_markdown_path(@project, @page.slug) } do
- = render 'projects/zen', f: f, attr: :content, classes: 'note-textarea', placeholder: s_("WikiPage|Write your content or drag files here…")
+ = render 'projects/zen', f: f, attr: :content, classes: 'note-textarea qa-wiki-content-textarea', placeholder: s_("WikiPage|Write your content or drag files here…")
= render 'shared/notes/hints'
.clearfix
@@ -47,14 +43,14 @@
.form-group.row
.col-sm-12= f.label :commit_message, class: 'control-label-full-width'
- .col-sm-12= f.text_field :message, class: 'form-control', rows: 18, value: commit_message
+ .col-sm-12= f.text_field :message, class: 'form-control qa-wiki-message-textbox', rows: 18, value: commit_message
.form-actions
- if @page && @page.persisted?
- = f.submit _("Save changes"), class: 'btn-success btn'
+ = f.submit _("Save changes"), class: 'btn-success btn qa-save-changes-button'
.float-right
= link_to _("Cancel"), project_wiki_path(@project, @page), class: 'btn btn-cancel btn-grouped'
- else
- = f.submit s_("Wiki|Create page"), class: 'btn-success btn'
+ = f.submit s_("Wiki|Create page"), class: 'btn-success btn qa-create-page-button'
.float-right
= link_to _("Cancel"), project_wiki_path(@project, :home), class: 'btn btn-cancel'
diff --git a/app/views/projects/wikis/_sidebar.html.haml b/app/views/projects/wikis/_sidebar.html.haml
index 02c5a6ea55c..28353927135 100644
--- a/app/views/projects/wikis/_sidebar.html.haml
+++ b/app/views/projects/wikis/_sidebar.html.haml
@@ -12,7 +12,7 @@
.blocks-container
.block.block-first
- if @sidebar_page
- = render_wiki_content(@sidebar_page, legacy_render_context(params))
+ = render_wiki_content(@sidebar_page)
- else
%ul.wiki-pages
= render @sidebar_wiki_entries, context: 'sidebar'
diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml
index 26671a7b7d2..1277ea6c743 100644
--- a/app/views/projects/wikis/edit.html.haml
+++ b/app/views/projects/wikis/edit.html.haml
@@ -23,9 +23,6 @@
= s_("Wiki|Create Page")
.nav-controls
- - if can?(current_user, :create_wiki, @project)
- = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-success", "data-toggle" => "modal" do
- = s_("Wiki|New page")
- if @page.persisted?
= link_to project_wiki_history_path(@project, @page), class: "btn" do
= s_("Wiki|Page history")
diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml
index aeef64fd7eb..94267b6e0cf 100644
--- a/app/views/projects/wikis/pages.html.haml
+++ b/app/views/projects/wikis/pages.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- add_to_breadcrumbs "Wiki", get_project_wiki_path(@project)
+- add_to_breadcrumbs "Wiki", project_wiki_path(@project, :home)
- breadcrumb_title s_("Wiki|Pages")
- page_title s_("Wiki|Pages"), _("Wiki")
diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml
index 4d5fd55364c..8e1c054b50c 100644
--- a/app/views/projects/wikis/show.html.haml
+++ b/app/views/projects/wikis/show.html.haml
@@ -2,7 +2,7 @@
- breadcrumb_title @page.human_title
- wiki_breadcrumb_dropdown_links(@page.slug)
- page_title @page.human_title, _("Wiki")
-- add_to_breadcrumbs _("Wiki"), get_project_wiki_path(@project)
+- add_to_breadcrumbs _("Wiki"), project_wiki_path(@project, :home)
.wiki-page-header.has-sidebar-toggle
%button.btn.btn-default.sidebar-toggle.js-sidebar-wiki-toggle{ role: "button", type: "button" }
@@ -27,6 +27,6 @@
.prepend-top-default.append-bottom-default
.wiki.md{ class: ('use-csslab' if Feature.enabled?(:csslab)) }
- = render_wiki_content(@page, legacy_render_context(params))
+ = render_wiki_content(@page)
= render 'sidebar'
diff --git a/app/views/search/_category.html.haml b/app/views/search/_category.html.haml
index ff9a7b53a86..aaf9b973cda 100644
--- a/app/views/search/_category.html.haml
+++ b/app/views/search/_category.html.haml
@@ -6,75 +6,75 @@
- if project_search_tabs?(:blobs)
%li{ class: active_when(@scope == 'blobs') }
= link_to search_filter_path(scope: 'blobs') do
- Code
+ = _("Code")
%span.badge.badge-pill
= @search_results.blobs_count
- if project_search_tabs?(:issues)
%li{ class: active_when(@scope == 'issues') }
= link_to search_filter_path(scope: 'issues') do
- Issues
+ = _("Issues")
%span.badge.badge-pill
= limited_count(@search_results.limited_issues_count)
- if project_search_tabs?(:merge_requests)
%li{ class: active_when(@scope == 'merge_requests') }
= link_to search_filter_path(scope: 'merge_requests') do
- Merge requests
+ = _("Merge requests")
%span.badge.badge-pill
= limited_count(@search_results.limited_merge_requests_count)
- if project_search_tabs?(:milestones)
%li{ class: active_when(@scope == 'milestones') }
= link_to search_filter_path(scope: 'milestones') do
- Milestones
+ = _("Milestones")
%span.badge.badge-pill
= limited_count(@search_results.limited_milestones_count)
- if project_search_tabs?(:notes)
%li{ class: active_when(@scope == 'notes') }
= link_to search_filter_path(scope: 'notes') do
- Comments
+ = _("Comments")
%span.badge.badge-pill
= limited_count(@search_results.limited_notes_count)
- if project_search_tabs?(:wiki)
%li{ class: active_when(@scope == 'wiki_blobs') }
= link_to search_filter_path(scope: 'wiki_blobs') do
- Wiki
+ = _("Wiki")
%span.badge.badge-pill
= @search_results.wiki_blobs_count
- if project_search_tabs?(:commits)
%li{ class: active_when(@scope == 'commits') }
= link_to search_filter_path(scope: 'commits') do
- Commits
+ = _("Commits")
%span.badge.badge-pill
= @search_results.commits_count
- elsif @show_snippets
%li{ class: active_when(@scope == 'snippet_blobs') }
= link_to search_filter_path(scope: 'snippet_blobs', snippets: true, group_id: nil, project_id: nil) do
- Snippet Contents
+ = _("Snippet Contents")
%span.badge.badge-pill
= @search_results.snippet_blobs_count
%li{ class: active_when(@scope == 'snippet_titles') }
= link_to search_filter_path(scope: 'snippet_titles', snippets: true, group_id: nil, project_id: nil) do
- Titles and Filenames
+ = _("Titles and Filenames")
%span.badge.badge-pill
= @search_results.snippet_titles_count
- else
%li{ class: active_when(@scope == 'projects') }
= link_to search_filter_path(scope: 'projects') do
- Projects
+ = _("Projects")
%span.badge.badge-pill
= limited_count(@search_results.limited_projects_count)
%li{ class: active_when(@scope == 'issues') }
= link_to search_filter_path(scope: 'issues') do
- Issues
+ = _("Issues")
%span.badge.badge-pill
= limited_count(@search_results.limited_issues_count)
%li{ class: active_when(@scope == 'merge_requests') }
= link_to search_filter_path(scope: 'merge_requests') do
- Merge requests
+ = _("Merge requests")
%span.badge.badge-pill
= limited_count(@search_results.limited_merge_requests_count)
%li{ class: active_when(@scope == 'milestones') }
= link_to search_filter_path(scope: 'milestones') do
- Milestones
+ = _("Milestones")
%span.badge.badge-pill
= limited_count(@search_results.limited_milestones_count)
diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml
index 6837f64f132..c8b6a3258ab 100644
--- a/app/views/search/_filter.html.haml
+++ b/app/views/search/_filter.html.haml
@@ -3,31 +3,31 @@
- if params[:project_id].present?
= hidden_field_tag :project_id, params[:project_id]
.dropdown
- %button.dropdown-menu-toggle.js-search-group-dropdown{ type: "button", data: { toggle: "dropdown", default_label: "Group:", group_id: params[:group_id] } }
+ %button.dropdown-menu-toggle.js-search-group-dropdown{ type: "button", data: { toggle: "dropdown", default_label: _('Group:'), group_id: params[:group_id] } }
%span.dropdown-toggle-text
- Group:
+ = _("Group:")
- if @group.present?
= @group.name
- else
- Any
+ = _("Any")
= icon("chevron-down")
.dropdown-menu.dropdown-select.dropdown-menu-selectable.dropdown-menu-right
- = dropdown_title("Filter results by group")
- = dropdown_filter("Search groups")
+ = dropdown_title(_("Filter results by group"))
+ = dropdown_filter(_("Search groups"))
= dropdown_content
= dropdown_loading
.dropdown.project-filter
- %button.dropdown-menu-toggle.js-search-project-dropdown{ type: "button", data: { toggle: "dropdown", default_label: "Project:" } }
+ %button.dropdown-menu-toggle.js-search-project-dropdown{ type: "button", data: { toggle: "dropdown", default_label: _('Project:') } }
%span.dropdown-toggle-text
- Project:
+ = _("Project:")
- if @project.present?
= @project.full_name
- else
- Any
+ = _("Any")
= icon("chevron-down")
.dropdown-menu.dropdown-select.dropdown-menu-selectable.dropdown-menu-right
- = dropdown_title("Filter results by project")
- = dropdown_filter("Search projects")
+ = dropdown_title(_("Filter results by project"))
+ = dropdown_filter(_("Search projects"))
= dropdown_content
= dropdown_loading
diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml
index a4a5cec1314..4af0c6bf84a 100644
--- a/app/views/search/_form.html.haml
+++ b/app/views/search/_form.html.haml
@@ -4,12 +4,12 @@
.search-holder
.search-field-holder
- = search_field_tag :search, params[:search], placeholder: "Search for projects, issues etc", class: "form-control search-text-input js-search-input", id: "dashboard_search", autofocus: true, spellcheck: false
+ = search_field_tag :search, params[:search], placeholder: _("Search for projects, issues, etc."), class: "form-control search-text-input js-search-input", id: "dashboard_search", autofocus: true, spellcheck: false
= icon("search", class: "search-icon")
%button.search-clear.js-search-clear{ class: ("hidden" if !params[:search].present?), type: "button", tabindex: "-1" }
= icon("times-circle")
%span.sr-only
- Clear search
+ = _("Clear search")
- unless params[:snippets].eql? 'true'
= render 'filter'
- = button_tag "Search", class: "btn btn-success btn-search"
+ = button_tag _("Search"), class: "btn btn-success btn-search"
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index ab56f48ba4d..be7a2436d16 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -1,4 +1,4 @@
-- if @search_objects.empty?
+- if @search_objects.to_a.empty?
= render partial: "search/results/empty"
- else
.row-content-block
@@ -6,9 +6,11 @@
= search_entries_info(@search_objects, @scope, @search_term)
- unless @show_snippets
- if @project
- in project #{link_to @project.full_name, [@project.namespace.becomes(Namespace), @project]}
+ - link_to_project = link_to(@project.full_name, [@project.namespace.becomes(Namespace), @project])
+ = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project }
- elsif @group
- in group #{link_to @group.name, @group}
+ - link_to_group = link_to(@group.name, @group)
+ = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
.results.prepend-top-10
- if @scope == 'commits'
diff --git a/app/views/search/results/_empty.html.haml b/app/views/search/results/_empty.html.haml
index 821a39d61f5..9d15995bb51 100644
--- a/app/views/search/results/_empty.html.haml
+++ b/app/views/search/results/_empty.html.haml
@@ -2,5 +2,5 @@
.search_glyph
%h4
= icon('search')
- We couldn't find any results matching
+ = _("We couldn't find any results matching")
%code= @search_term
diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml
index c413c3d4abb..796782035f2 100644
--- a/app/views/search/results/_issue.html.haml
+++ b/app/views/search/results/_issue.html.haml
@@ -4,7 +4,7 @@
= link_to [issue.project.namespace.becomes(Namespace), issue.project, issue] do
%span.term.str-truncated= issue.title
- if issue.closed?
- %span.badge.badge-danger.prepend-left-5 Closed
+ %span.badge.badge-danger.prepend-left-5= _("Closed")
.float-right ##{issue.iid}
- if issue.description.present?
.description.term
diff --git a/app/views/search/results/_merge_request.html.haml b/app/views/search/results/_merge_request.html.haml
index 519176af108..f0e0af11f27 100644
--- a/app/views/search/results/_merge_request.html.haml
+++ b/app/views/search/results/_merge_request.html.haml
@@ -3,9 +3,9 @@
= link_to [merge_request.target_project.namespace.becomes(Namespace), merge_request.target_project, merge_request] do
%span.term.str-truncated= merge_request.title
- if merge_request.merged?
- %span.badge.badge-primary.prepend-left-5 Merged
+ %span.badge.badge-primary.prepend-left-5= _("Merged")
- elsif merge_request.closed?
- %span.badge.badge-danger.prepend-left-5 Closed
+ %span.badge.badge-danger.prepend-left-5= _("Closed")
.float-right= merge_request.to_reference
- if merge_request.description.present?
.description.term
diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml
index e4ab7b0541f..6717939d034 100644
--- a/app/views/search/results/_note.html.haml
+++ b/app/views/search/results/_note.html.haml
@@ -6,14 +6,14 @@
%h5.note-search-caption.str-truncated
%i.fa.fa-comment
= link_to_member(project, note.author, avatar: false)
- commented on
- = link_to project.full_name, project
+ - link_to_project = link_to(project.full_name, project)
+ = _("commented on %{link_to_project}").html_safe % { link_to_project: link_to_project }
&middot;
- if note.for_commit?
- = link_to_if(noteable_identifier, "Commit #{truncate_sha(note.commit_id)}", note_url) do
+ = link_to_if(noteable_identifier, _("Commit %{commit_id}") % { commit_id: truncate_sha(note.commit_id) }, note_url) do
= truncate_sha(note.commit_id)
- %span.light Commit deleted
+ %span.light= _("Commit deleted")
- else
%span #{note.noteable_type.titleize} ##{noteable_identifier}
diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml
index b4ecd7bbae9..a60a4501557 100644
--- a/app/views/search/results/_snippet_blob.html.haml
+++ b/app/views/search/results/_snippet_blob.html.haml
@@ -21,10 +21,10 @@
.file-content.wiki
- snippet_chunks.each do |chunk|
- unless chunk[:data].empty?
- = markup(snippet.file_name, chunk[:data], legacy_render_context(params))
+ = markup(snippet.file_name, chunk[:data])
- else
.file-content.code
- .nothing-here-block Empty file
+ .nothing-here-block= _("Empty file")
- else
.file-content.code.js-syntax-highlight
.line-numbers
@@ -42,4 +42,4 @@
= highlight(snippet.file_name, chunk[:data])
- else
.file-content.code
- .nothing-here-block Empty file
+ .nothing-here-block= _("Empty file")
diff --git a/app/views/search/results/_snippet_title.html.haml b/app/views/search/results/_snippet_title.html.haml
index 9c8afb2165b..1e01088d9e6 100644
--- a/app/views/search/results/_snippet_title.html.haml
+++ b/app/views/search/results/_snippet_title.html.haml
@@ -5,7 +5,7 @@
- if snippet_title.private?
%span.badge.badge-gray
%i.fa.fa-lock
- private
+ = _("private")
%span.cgray.monospace.tiny.float-right.term
= snippet_title.file_name
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index 499697f2777..3260d05f509 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -1,5 +1,5 @@
- @hide_top_links = true
-- breadcrumb_title "Search"
+- breadcrumb_title _("Search")
- page_title @search_term
.prepend-top-default
diff --git a/app/views/sent_notifications/unsubscribe.html.haml b/app/views/sent_notifications/unsubscribe.html.haml
index 7d3e243495f..ca392e1adfc 100644
--- a/app/views/sent_notifications/unsubscribe.html.haml
+++ b/app/views/sent_notifications/unsubscribe.html.haml
@@ -1,17 +1,16 @@
- noteable = @sent_notification.noteable
- noteable_type = @sent_notification.noteable_type.titleize.downcase
- noteable_text = %(#{noteable.title} (#{noteable.to_reference}))
-- page_title "Unsubscribe", noteable_text, noteable_type.pluralize, @sent_notification.project.full_name
+- page_title _("Unsubscribe"), noteable_text, noteable_type.pluralize, @sent_notification.project.full_name
%h3.page-title
- Unsubscribe from #{noteable_type}
+ = _("Unsubscribe from %{type}") % { type: noteable_type }
%p
- = succeed '?' do
- Are you sure you want to unsubscribe from the #{noteable_type}:
- = link_to noteable_text, url_for([@sent_notification.project.namespace.becomes(Namespace), @sent_notification.project, noteable])
+ - link_to_noteable_text = link_to(noteable_text, url_for([@sent_notification.project.namespace.becomes(Namespace), @sent_notification.project, noteable]))
+ = _("Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?").html_safe % { type: noteable_type, link_to_noteable_text: link_to_noteable_text }
%p
- = link_to 'Unsubscribe', unsubscribe_sent_notification_path(@sent_notification, force: true),
+ = link_to _('Unsubscribe'), unsubscribe_sent_notification_path(@sent_notification, force: true),
class: 'btn btn-primary append-right-10'
- = link_to 'Cancel', new_user_session_path, class: 'btn append-right-10'
+ = link_to _('Cancel'), new_user_session_path, class: 'btn append-right-10'
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 0d0a3c1aa64..755fd3a17d3 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)
- .auto-devops-implicitly-enabled-banner.alert.alert-warning
+- if show_auto_devops_implicitly_enabled_banner?(project, current_user)
+ .qa-auto-devops-banner.auto-devops-implicitly-enabled-banner.alert.alert-warning
- more_information_link = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank', class: 'alert-link'
- auto_devops_message = s_("AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}") % { more_information_link: more_information_link }
= auto_devops_message.html_safe
diff --git a/app/views/shared/_flash_user_callout.html.haml b/app/views/shared/_flash_user_callout.html.haml
new file mode 100644
index 00000000000..fe175195e66
--- /dev/null
+++ b/app/views/shared/_flash_user_callout.html.haml
@@ -0,0 +1,11 @@
+- callout_data = { uid: "callout_feature_#{feature_name}_dismissed", feature_id: feature_name, dismiss_endpoint: user_callouts_path }
+- extra_flash_class = local_assigns.fetch(:extra_flash_class, nil)
+
+.flash-container.flash-container-page.user-callout{ data: callout_data }
+ -# We currently only support `alert`, `warning`, `notice`, `success`
+ %div{ class: "flash-#{flash_type}" }
+ %div{ class: "#{(container_class unless fluid_layout)} #{(extra_flash_class unless @no_container)} #{@content_class}" }
+ %span= message
+ %button.btn.btn-default.close.js-close{ type: 'button',
+ 'aria-label' => _('Dismiss') }
+ = sprite_icon('close', css_class: 'dismiss-icon')
diff --git a/app/views/shared/_issuable_meta_data.html.haml b/app/views/shared/_issuable_meta_data.html.haml
index 6cc8c485666..31a5370a5f8 100644
--- a/app/views/shared/_issuable_meta_data.html.haml
+++ b/app/views/shared/_issuable_meta_data.html.haml
@@ -1,4 +1,4 @@
-- note_count = @issuable_meta_data[issuable.id].notes_count
+- note_count = @issuable_meta_data[issuable.id].user_notes_count
- issue_votes = @issuable_meta_data[issuable.id]
- upvotes, downvotes = issue_votes.upvotes, issue_votes.downvotes
- issuable_url = @collection_type == "Issue" ? issue_path(issuable, anchor: 'notes') : merge_request_path(issuable, anchor: 'notes')
diff --git a/app/views/shared/_mini_pipeline_graph.html.haml b/app/views/shared/_mini_pipeline_graph.html.haml
index 28b34e38b15..8607f87ce0b 100644
--- a/app/views/shared/_mini_pipeline_graph.html.haml
+++ b/app/views/shared/_mini_pipeline_graph.html.haml
@@ -7,7 +7,6 @@
.stage-container.dropdown{ class: klass }
%button.mini-pipeline-graph-dropdown-toggle.has-tooltip.js-builds-dropdown-button{ class: "ci-status-icon-#{detailed_status.group}", type: 'button', data: { toggle: 'dropdown', title: "#{stage.name}: #{detailed_status.label}", placement: 'top', "stage-endpoint" => stage_ajax_project_pipeline_path(pipeline.project, pipeline, stage: stage.name) } }
= sprite_icon(icon_status)
- = icon('caret-down')
%ul.dropdown-menu.mini-pipeline-graph-dropdown-menu.js-builds-dropdown-container
%li.js-builds-dropdown-list.scrollable-menu
diff --git a/app/views/shared/_mobile_clone_panel.html.haml b/app/views/shared/_mobile_clone_panel.html.haml
index 6e2527bd1a1..1e6b6f7c79b 100644
--- a/app/views/shared/_mobile_clone_panel.html.haml
+++ b/app/views/shared/_mobile_clone_panel.html.haml
@@ -13,3 +13,4 @@
- if http_enabled?
%li
= dropdown_item_with_description(http_copy_label, project.http_url_to_repo, href: project.http_url_to_repo, data: { clone_type: 'http' })
+ = render_if_exists 'shared/mobile_kerberos_clone'
diff --git a/app/views/shared/_personal_access_tokens_created_container.html.haml b/app/views/shared/_personal_access_tokens_created_container.html.haml
index 3150d39b84a..a8d3de66418 100644
--- a/app/views/shared/_personal_access_tokens_created_container.html.haml
+++ b/app/views/shared/_personal_access_tokens_created_container.html.haml
@@ -6,7 +6,7 @@
= container_title
.form-group
.input-group
- = text_field_tag 'created-personal-access-token', new_token_value, readonly: true, class: "form-control js-select-on-focus", 'aria-describedby' => "created-token-help-block"
+ = text_field_tag 'created-personal-access-token', new_token_value, readonly: true, class: "qa-created-personal-access-token form-control js-select-on-focus", 'aria-describedby' => "created-token-help-block"
%span.input-group-append
= clipboard_button(text: new_token_value, title: clipboard_button_title, placement: "left", class: "input-group-text btn-default btn-clipboard")
%span#created-token-help-block.form-text.text-muted.text-danger Make sure you save it - you won't be able to access it again.
diff --git a/app/views/shared/_personal_access_tokens_form.html.haml b/app/views/shared/_personal_access_tokens_form.html.haml
index f4df7bdcd83..0891b3459ec 100644
--- a/app/views/shared/_personal_access_tokens_form.html.haml
+++ b/app/views/shared/_personal_access_tokens_form.html.haml
@@ -12,7 +12,7 @@
.row
.form-group.col-md-6
= f.label :name, class: 'label-bold'
- = f.text_field :name, class: "form-control", required: true
+ = f.text_field :name, class: "form-control qa-personal-access-token-name-field", required: true
.row
.form-group.col-md-6
@@ -26,4 +26,4 @@
= render 'shared/tokens/scopes_form', prefix: 'personal_access_token', token: token, scopes: scopes
.prepend-top-default
- = f.submit "Create #{type} token", class: "btn btn-success"
+ = f.submit "Create #{type} token", class: "btn btn-success qa-create-token-button"
diff --git a/app/views/shared/_personal_access_tokens_table.html.haml b/app/views/shared/_personal_access_tokens_table.html.haml
index 2efd03d4867..49f3aae0f98 100644
--- a/app/views/shared/_personal_access_tokens_table.html.haml
+++ b/app/views/shared/_personal_access_tokens_table.html.haml
@@ -29,7 +29,7 @@
%span.token-never-expires-label Never
%td= token.scopes.present? ? token.scopes.join(", ") : "<no scopes selected>"
- path = impersonation ? revoke_admin_user_impersonation_token_path(token.user, token) : revoke_profile_personal_access_token_path(token)
- %td= link_to "Revoke", path, method: :put, class: "btn btn-danger float-right", data: { confirm: "Are you sure you want to revoke this #{type} Token? This action cannot be undone." }
+ %td= link_to "Revoke", path, method: :put, class: "btn btn-danger float-right qa-revoke-button", data: { confirm: "Are you sure you want to revoke this #{type} Token? This action cannot be undone." }
- else
.settings-message.text-center
This user has no active #{type} Tokens.
diff --git a/app/views/shared/boards/components/_board.html.haml b/app/views/shared/boards/components/_board.html.haml
index c6c5cadc3f5..307a0919a4c 100644
--- a/app/views/shared/boards/components/_board.html.haml
+++ b/app/views/shared/boards/components/_board.html.haml
@@ -1,6 +1,6 @@
.board{ ":class" => '{ "is-draggable": !list.preset, "is-expandable": list.isExpandable, "is-collapsed": !list.isExpanded, "board-type-assignee": list.type === "assignee" }',
":data-id" => "list.id" }
- .board-inner
+ .board-inner.d-flex.flex-column
%header.board-header{ ":class" => '{ "has-border": list.label && list.label.color }', ":style" => "{ borderTopColor: (list.label && list.label.color ? list.label.color : null) }", "@click" => "toggleExpanded($event)" }
%h3.board-title.js-board-handle{ ":class" => '{ "user-can-drag": (!disabled && !list.preset) }' }
%i.fa.fa-fw.board-title-expandable-toggle{ "v-if": "list.isExpandable",
diff --git a/app/views/shared/boards/components/_sidebar.html.haml b/app/views/shared/boards/components/_sidebar.html.haml
index 1ff956649ed..c9ff63f8c45 100644
--- a/app/views/shared/boards/components/_sidebar.html.haml
+++ b/app/views/shared/boards/components/_sidebar.html.haml
@@ -1,4 +1,4 @@
-%board-sidebar{ "inline-template" => true, ":current-user" => (UserSerializer.new.represent(current_user) || {}).to_json }
+%board-sidebar{ "inline-template" => true, ":current-user" => (UserSerializer.new.represent(current_user) || {}).to_json }
%transition{ name: "boards-sidebar-slide" }
%aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar" }
.issuable-sidebar
diff --git a/app/views/shared/deploy_keys/_form.html.haml b/app/views/shared/deploy_keys/_form.html.haml
index 913c065e188..eb7808573b9 100644
--- a/app/views/shared/deploy_keys/_form.html.haml
+++ b/app/views/shared/deploy_keys/_form.html.haml
@@ -15,7 +15,7 @@
%p.light
Paste a machine public key here. Read more about how to generate it
= link_to 'here', help_page_path('ssh/README')
- = form.text_area :key, class: 'form-control thin_area', rows: 5
+ = form.text_area :key, class: 'form-control thin-area', rows: 5
- else
= form.label :fingerprint, class: 'col-form-label col-sm-2'
.col-sm-10
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index 0ddc56dc6c3..9173b802dd4 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -1,6 +1,11 @@
- button_path = local_assigns.fetch(:button_path, false)
- project_select_button = local_assigns.fetch(:project_select_button, false)
+- show_import_button = local_assigns.fetch(:show_import_button, false) && can?(current_user, :import_issues, @project)
- has_button = button_path || project_select_button
+- closed_issues_count = issuables_count_for_state(:issues, :closed)
+- opened_issues_count = issuables_count_for_state(:issues, :opened)
+- is_opened_state = params[:state] == 'opened'
+- is_closed_state = params[:state] == 'closed'
.row.empty-state
.col-12
@@ -13,6 +18,20 @@
= _("Sorry, your filter produced no results")
%p.text-center
= _("To widen your search, change or remove filters above")
+ - if show_new_issue_link?(@project)
+ .text-center
+ = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success", title: _("New issue"), id: "new_issue_body_link"
+ - elsif is_opened_state && opened_issues_count == 0 && closed_issues_count > 0
+ %h4.text-center
+ = _("There are no open issues")
+ %p.text-center
+ = _("To keep this project going, create a new issue")
+ - if show_new_issue_link?(@project)
+ .text-center
+ = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success", title: _("New issue"), id: "new_issue_body_link"
+ - elsif is_closed_state && opened_issues_count > 0 && closed_issues_count == 0
+ %h4.text-center
+ = _("There are no closed issues")
- elsif current_user
%h4
= _("The Issue Tracker is the place to add things that need to be improved or solved in a project")
@@ -21,12 +40,20 @@
- if has_button
.text-center
- if project_select_button
- = render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue', type: :issues, with_feature_enabled: 'issues'
+ = render 'shared/new_project_item_select', path: 'issues/new', label: _('New issue'), type: :issues, with_feature_enabled: 'issues'
- else
- = link_to 'New issue', button_path, class: 'btn btn-success', title: 'New issue', id: 'new_issue_link'
+ = link_to _('New issue'), button_path, class: 'btn btn-success', title: _('New issue'), id: 'new_issue_link'
+
+ - if show_import_button
+ = render 'projects/issues/import_csv/button', type: :text
+
- else
%h4.text-center= _("There are no issues to show")
%p
= _("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.")
.text-center
= link_to _('Register / Sign In'), new_user_session_path, class: 'btn btn-success'
+
+- if show_import_button
+ = render 'projects/issues/import_csv/modal'
+
diff --git a/app/views/shared/empty_states/_labels.html.haml b/app/views/shared/empty_states/_labels.html.haml
index bee26cd8312..a739103641e 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
+ .svg-content.qa-label-svg
= image_tag 'illustrations/labels.svg'
.col-12
.text-content
diff --git a/app/views/shared/empty_states/_merge_requests.html.haml b/app/views/shared/empty_states/_merge_requests.html.haml
index 06ceb9738bc..be5b1c6b6ce 100644
--- a/app/views/shared/empty_states/_merge_requests.html.haml
+++ b/app/views/shared/empty_states/_merge_requests.html.haml
@@ -1,6 +1,11 @@
- button_path = local_assigns.fetch(:button_path, false)
- project_select_button = local_assigns.fetch(:project_select_button, false)
- has_button = button_path || project_select_button
+- closed_merged_count = issuables_count_for_state(:merged, :closed)
+- opened_merged_count = issuables_count_for_state(:merged, :opened)
+- is_opened_state = params[:state] == 'opened'
+- is_closed_state = params[:state] == 'closed'
+- can_create_merge_request = merge_request_source_project_for_project(@project)
.row.empty-state.merge-requests
.col-12
@@ -13,6 +18,20 @@
= _("Sorry, your filter produced no results")
%p.text-center
= _("To widen your search, change or remove filters above")
+ .text-center
+ - if can_create_merge_request
+ = link_to _("New merge request"), project_new_merge_request_path(@project), class: "btn btn-success", title: _("New merge request"), id: "new_merge_request_body_link"
+ - elsif is_opened_state && opened_merged_count == 0 && closed_merged_count > 0
+ %h4.text-center
+ = _("There are no open merge requests")
+ %p.text-center
+ = _("To keep this project going, create a new merge request")
+ .text-center
+ - if can_create_merge_request
+ = link_to _("New merge request"), project_new_merge_request_path(@project), class: "btn btn-success", title: _("New merge request"), id: "new_merge_request_body_link"
+ - elsif is_closed_state && opened_merged_count > 0 && closed_merged_count == 0
+ %h4.text-center
+ = _("There are no closed merge requests")
- else
%h4
= _("Merge requests are a place to propose changes you've made to a project and discuss those changes with others")
diff --git a/app/views/shared/empty_states/_priority_labels.html.haml b/app/views/shared/empty_states/_priority_labels.html.haml
index 555cb4f4af9..bba3475d244 100644
--- a/app/views/shared/empty_states/_priority_labels.html.haml
+++ b/app/views/shared/empty_states/_priority_labels.html.haml
@@ -1,4 +1,4 @@
.text-center
- .svg-content
+ .svg-content.qa-label-svg
= image_tag 'illustrations/priority_labels.svg'
%p Star labels to start sorting by priority
diff --git a/app/views/shared/empty_states/_profile_tabs.html.haml b/app/views/shared/empty_states/_profile_tabs.html.haml
new file mode 100644
index 00000000000..6da40e1b059
--- /dev/null
+++ b/app/views/shared/empty_states/_profile_tabs.html.haml
@@ -0,0 +1,19 @@
+- current_user_empty_message_description = local_assigns.fetch(:current_user_empty_message_description, nil)
+- secondary_button_link = local_assigns.fetch(:secondary_button_link, nil)
+
+.nothing-here-block
+ .svg-content
+ = image_tag illustration_path, size: '75'
+ .text-content
+ - if user_profile? and current_user.present? and current_user.username == params[:username]
+ %h5= current_user_empty_message_header
+
+ - if current_user_empty_message_description.present?
+ %p= current_user_empty_message_description
+
+ - if secondary_button_link.present?
+ = link_to secondary_button_label, secondary_button_link, class: 'btn btn-create btn-inverted'
+
+ = link_to primary_button_label, primary_button_link, class: 'btn btn-success'
+ - else
+ %h5= visitor_empty_message
diff --git a/app/views/shared/empty_states/_snippets.html.haml b/app/views/shared/empty_states/_snippets.html.haml
new file mode 100644
index 00000000000..a1a16b9d067
--- /dev/null
+++ b/app/views/shared/empty_states/_snippets.html.haml
@@ -0,0 +1,20 @@
+- button_path = local_assigns.fetch(:button_path, false)
+
+.row.empty-state
+ .col-12
+ .svg-content
+ = image_tag 'illustrations/snippets_empty.svg'
+ .text-content
+ - if current_user
+ %h4
+ = s_('SnippetsEmptyState|Snippets are small pieces of code or notes that you want to keep.')
+ %p
+ = s_('SnippetsEmptyState|They can be either public or private.')
+ .text-center
+ = link_to s_('SnippetsEmptyState|New snippet'), button_path, class: 'btn btn-success', title: s_('SnippetsEmptyState|New snippet'), id: 'new_snippet_link'
+ - unless current_page?(dashboard_snippets_path)
+ = link_to s_('SnippetsEmptyState|Explore public snippets'), explore_snippets_path, class: 'btn btn-default', title: s_('SnippetsEmptyState|Explore public snippets')
+ - else
+ %h4.text-center= s_('SnippetsEmptyState|There are no snippets to show.')
+
+
diff --git a/app/views/shared/empty_states/_wikis.html.haml b/app/views/shared/empty_states/_wikis.html.haml
index df3308abe0d..73eedcc1dc9 100644
--- a/app/views/shared/empty_states/_wikis.html.haml
+++ b/app/views/shared/empty_states/_wikis.html.haml
@@ -2,7 +2,7 @@
- if can?(current_user, :create_wiki, @project)
- create_path = project_wiki_path(@project, params[:id], { view: 'create' })
- - create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn btn-success', title: s_('WikiEmpty|Create your first page')
+ - create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn btn-success qa-create-first-page-link', title: s_('WikiEmpty|Create your first page')
= 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 a5f100e3469..d44017299b8 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
.col-12
- .svg-content
+ .svg-content.qa-svg-content
= image_tag image_path
.col-12
.text-content.text-center
diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml
index a1b901aaffa..609b8dce21a 100644
--- a/app/views/shared/groups/_group.html.haml
+++ b/app/views/shared/groups/_group.html.haml
@@ -14,7 +14,7 @@
%span.visibility-icon.has-tooltip{ data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group) }
= visibility_level_icon(group.visibility_level, fw: false)
- .avatar-container.s40
+ .avatar-container.rect-avatar.s40
= link_to group do
= group_icon(group, class: "avatar s40 d-none d-sm-block")
.title
diff --git a/app/views/shared/groups/_list.html.haml b/app/views/shared/groups/_list.html.haml
index f50a6bd4d6a..c5b39c7db08 100644
--- a/app/views/shared/groups/_list.html.haml
+++ b/app/views/shared/groups/_list.html.haml
@@ -1,3 +1,10 @@
+- illustration_path = 'illustrations/profile-page/groups.svg'
+- current_user_empty_message_header = s_('UserProfile|You can create a group for several dependent projects.')
+- current_user_empty_message_description = s_('UserProfile|Groups are the best way to manage projects and members.')
+- primary_button_label = _('New group')
+- primary_button_link = new_group_path
+- visitor_empty_message = s_('GroupsEmptyState|No groups found')
+
- if groups.any?
- user = local_assigns[:user]
@@ -5,4 +12,9 @@
- groups.each_with_index do |group, i|
= render "shared/groups/group", group: group, user: user
- else
- .nothing-here-block= s_("GroupsEmptyState|No groups found")
+ = render partial: 'shared/empty_states/profile_tabs', locals: { illustration_path: illustration_path,
+ current_user_empty_message_header: current_user_empty_message_header,
+ current_user_empty_message_description: current_user_empty_message_description,
+ primary_button_label: primary_button_label,
+ primary_button_link: primary_button_link,
+ visitor_empty_message: visitor_empty_message }
diff --git a/app/views/shared/icons/_express.svg b/app/views/shared/icons/_express.svg
deleted file mode 100644
index a51e81e5568..00000000000
--- a/app/views/shared/icons/_express.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="27" height="32" viewBox="0 0 27 32" class="btn-template-icon icon-node-express"><g fill="none" fill-rule="evenodd"><path d="M-3 0h32v32H-3z"/><path fill="#353535" d="M1.192 16.267c.04 2.065.288 3.982.745 5.75.456 1.767 1.16 3.307 2.115 4.618.953 1.31 2.185 2.343 3.694 3.098 1.51.755 3.357 1.132 5.54 1.132 3.22 0 5.89-.844 8.016-2.532 2.125-1.69 3.446-4.22 3.962-7.597h1.192c-.437 3.575-1.847 6.345-4.23 8.312-2.384 1.966-5.324 2.95-8.82 2.95-2.383.04-4.42-.338-6.107-1.133-1.69-.794-3.07-1.917-4.142-3.367-1.073-1.45-1.867-3.158-2.383-5.124C.258 20.408 0 18.294 0 16.028c0-2.542.377-4.806 1.132-6.792C1.887 7.25 2.88 5.57 4.112 4.2 5.34 2.83 6.77 1.79 8.4 1.074 10.03.358 11.698 0 13.406 0c2.383 0 4.44.457 6.167 1.37 1.728.914 3.138 2.126 4.23 3.635 1.093 1.51 1.887 3.238 2.384 5.184.496 1.945.705 3.97.625 6.077H1.193zm24.43-1.192c0-1.867-.26-3.645-.775-5.333-.516-1.688-1.28-3.168-2.294-4.44-1.013-1.27-2.274-2.273-3.784-3.008-1.51-.735-3.258-1.102-5.244-1.102-1.67 0-3.228.317-4.678.953-1.45.636-2.72 1.56-3.813 2.77-1.092 1.212-1.976 2.672-2.652 4.38-.675 1.708-1.072 3.635-1.19 5.78h24.43z"/></g></svg>
diff --git a/app/views/shared/icons/_rails.svg b/app/views/shared/icons/_rails.svg
deleted file mode 100644
index 852bd183cc7..00000000000
--- a/app/views/shared/icons/_rails.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="32" height="20" viewBox="0 0 32 20" class="btn-template-icon icon-rails"><g fill="none" fill-rule="evenodd"><path d="M0-6h32v32H0z"/><path fill="#c00" fill-rule="nonzero" d="M.985 19.636s.422-4.163 3.375-9.087c2.954-4.924 7.99-8.65 12.083-9.017 8.144-.816 15.46 6.485 15.46 6.485s-.24.168-.494.38C23.42 2.49 18.54 5.274 17.005 6.02c-7.033 3.925-4.91 13.616-4.91 13.616H.987zM24.137 2.32c-.45-.182-.9-.35-1.364-.505l.056-.93c.885.254 1.237.423 1.363.493l-.056.943zM22.8 5.304c.45.028.915.084 1.393.183l-.056.872c-.464-.1-.928-.155-1.392-.17l.056-.885zM17.597.913c-.407 0-.815.015-1.223.058l-.268-.83c.465-.056.915-.084 1.35-.084l.282.858h-.14zm.676 5.178c.35-.154.76-.31 1.237-.45l.31.93c-.41.125-.817.294-1.225.49l-.323-.97zm-6.386-3.7c-.366.184-.718.395-1.083.62l-.647-.985c.38-.225.745-.42 1.097-.604l.633.97zm2.883 6.33c.252-.323.548-.646.87-.942l.634.957c-.31.323-.59.647-.83 1L14.77 8.72zm-2.04 4.53c.112-.506.24-1.027.422-1.547l1.012.802c-.14.548-.24 1.097-.295 1.645l-1.14-.9zM6.57 6.57c-.34.35-.662.73-.958 1.11L4.53 6.752c.323-.352.674-.704 1.04-1.055l1 .872zm-4.25 6.286c-.224.52-.52 1.21-.702 1.688L0 13.954c.14-.38.436-1.084.703-1.69l1.618.592zm10.2 3.967l1.518.548c.084.663.21 1.28.337 1.83l-1.688-.605c-.07-.422-.14-1.027-.168-1.772z"/></g></svg>
diff --git a/app/views/shared/icons/_spring.svg b/app/views/shared/icons/_spring.svg
deleted file mode 100644
index ccf18749029..00000000000
--- a/app/views/shared/icons/_spring.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" class="btn-template-icon icon-java-spring"><g fill="none" fill-rule="evenodd"><path d="M0 0h32v32H0z"/><path fill="#70AD51" d="M5.466 27.993c.586.473 1.446.385 1.918-.202.475-.585.386-1.445-.2-1.92-.585-.474-1.444-.383-1.92.202-.45.555-.392 1.356.115 1.844l-.266-.234C1.972 24.762 0 20.597 0 15.978 0 7.168 7.168 0 15.98 0c4.48 0 8.53 1.857 11.435 4.836.66-.898 1.232-1.902 1.7-3.015 2.036 6.118 3.233 11.26 2.795 15.31-.592 8.274-7.508 14.83-15.93 14.83-3.912 0-7.496-1.416-10.276-3.757l-.238-.21zm23.58-4.982c4.01-5.336 1.775-13.965-.085-19.48-1.657 3.453-5.738 6.094-9.262 6.93-3.303.788-6.226.142-9.283 1.318-6.97 2.68-6.86 10.992-3.02 12.86.002 0 .23.124.227.12 0-.002 5.644-1.122 8.764-2.274 4.56-1.684 9.566-5.835 11.213-10.657-.877 5.015-5.182 9.84-9.507 12.056-2.302 1.182-4.092 1.445-7.88 2.756-.464.158-.828.314-.828.314.96-.16 1.917-.212 1.917-.212 5.393-.255 13.807 1.516 17.745-3.73z"/></g></svg>
diff --git a/app/views/shared/issuable/_board_create_list_dropdown.html.haml b/app/views/shared/issuable/_board_create_list_dropdown.html.haml
index 4597d9439fa..fd413bd68c8 100644
--- a/app/views/shared/issuable/_board_create_list_dropdown.html.haml
+++ b/app/views/shared/issuable/_board_create_list_dropdown.html.haml
@@ -1,7 +1,7 @@
.dropdown.prepend-left-10#js-add-list
%button.btn.btn-success.btn-inverted.js-new-board-list{ type: "button", data: board_list_data }
Add list
- .dropdown-menu.dropdown-menu-paging.dropdown-menu-right.dropdown-menu-issues-board-new.dropdown-menu-selectable.js-tab-container-labels
+ .dropdown-menu.dropdown-extended-height.dropdown-menu-paging.dropdown-menu-right.dropdown-menu-issues-board-new.dropdown-menu-selectable.js-tab-container-labels
= render partial: "shared/issuable/label_page_default", locals: { show_footer: true, show_create: true, show_boards_content: true, title: "Add list" }
- if can?(current_user, :admin_label, board.parent)
= render partial: "shared/issuable/label_page_create"
diff --git a/app/views/shared/issuable/_bulk_update_sidebar.html.haml b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
index ca02424215c..909eb738f95 100644
--- a/app/views/shared/issuable/_bulk_update_sidebar.html.haml
+++ b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
@@ -2,7 +2,7 @@
%aside.issues-bulk-update.js-right-sidebar.right-sidebar{ "aria-live" => "polite", data: { 'signed-in': current_user.present? } }
.issuable-sidebar.hidden
- = form_tag [:bulk_update, @project.namespace.becomes(Namespace), @project, type], method: :post, class: "bulk-update" do
+ = form_tag [:bulk_update, @project.namespace.becomes(Namespace), @project, type], method: :post, class: "bulk-update" do
.block.issuable-sidebar-header
.filter-item.inline.update-issues-btn.float-left
= button_tag "Update all", class: "btn update-selected-issues btn-info", disabled: true
@@ -50,4 +50,3 @@
= hidden_field_tag "update[issuable_ids]", []
= hidden_field_tag :state_event, params[:state_event]
-
diff --git a/app/views/shared/issuable/_feed_buttons.html.haml b/app/views/shared/issuable/_feed_buttons.html.haml
index d4834090413..83f60fa6fe2 100644
--- a/app/views/shared/issuable/_feed_buttons.html.haml
+++ b/app/views/shared/issuable/_feed_buttons.html.haml
@@ -1,4 +1,4 @@
-= link_to safe_params.merge(rss_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: 'Subscribe to RSS feed' do
+= link_to safe_params.merge(rss_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: _('Subscribe to RSS feed') do
= icon('rss')
-= link_to safe_params.merge(calendar_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: 'Subscribe to calendar' do
+= link_to safe_params.merge(calendar_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: _('Subscribe to calendar') do
= custom_icon('icon_calendar')
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
deleted file mode 100644
index 2ca4657851c..00000000000
--- a/app/views/shared/issuable/_filter.html.haml
+++ /dev/null
@@ -1,32 +0,0 @@
-.issues-filters
- .issues-details-filters.row-content-block.second-block
- = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name, :search]), method: :get, class: 'filter-form js-filter-form' do
- - if params[:search].present?
- = hidden_field_tag :search, params[:search]
- .issues-other-filters
- .filter-item.inline
- - if params[:author_id].present?
- = hidden_field_tag(:author_id, params[:author_id])
- = dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit",
- placeholder: "Search authors", data: { any_user: "Any Author", first_user: current_user&.username, current_user: true, project_id: @project&.id, group_id: @group&.id, selected: params[:author_id], field_name: "author_id", default_label: "Author" } })
-
- .filter-item.inline
- - if params[:assignee_id].present?
- = hidden_field_tag(:assignee_id, params[:assignee_id])
- = dropdown_tag(user_dropdown_label(params[:assignee_id], "Assignee"), options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
- placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: current_user&.username, null_user: true, current_user: true, project_id: @project&.id, group_id: @group&.id, selected: params[:assignee_id], field_name: "assignee_id", default_label: "Assignee" } })
-
- .filter-item.inline.milestone-filter
- = render "shared/issuable/milestone_dropdown", selected: finder.milestones.try(:first), name: :milestone_title, show_any: true, show_upcoming: true, show_started: true
-
- .filter-item.inline.labels-filter
- = render "shared/issuable/label_dropdown", selected: selected_labels, use_id: false, selected_toggle: params[:label_name], data_options: { field_name: "label_name[]" }
-
- - unless @no_filters_set
- .float-right
- = render 'shared/issuable/sort_dropdown'
-
- - has_labels = @labels && @labels.any?
- .row-content-block.second-block.filtered-labels{ class: ("hidden" unless has_labels) }
- - if has_labels
- = render 'shared/labels_row', labels: @labels
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 46634693067..f43be304e6b 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -11,7 +11,7 @@
- if params[:search].present?
= hidden_field_tag :search, params[:search]
- if @can_bulk_update
- .check-all-holder.hidden
+ .check-all-holder.d-none.d-sm-block.hidden
= check_box_tag "check-all-issues", nil, false, class: "check-all-issues left"
.issues-other-filters.filtered-search-wrapper
.filtered-search-box
@@ -57,10 +57,10 @@
avatar: { lazy: true, url: '{{avatar_url}}' }
#js-dropdown-assignee.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'none' } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
%button.btn.btn-link{ type: 'button' }
= _('None')
- %li.filter-dropdown-item{ data: { value: 'any' } }
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
%button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
@@ -71,18 +71,19 @@
= 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'
#js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'none' } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
%button.btn.btn-link{ type: 'button' }
= _('None')
- %li.filter-dropdown-item{ data: { value: 'any' } }
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
%button.btn.btn-link{ type: 'button' }
= _('Any')
- %li.filter-dropdown-item{ data: { value: 'upcoming' } }
+ %li.filter-dropdown-item{ data: { value: 'Upcoming' } }
%button.btn.btn-link{ type: 'button' }
= _('Upcoming')
- %li.filter-dropdown-item{ data: { value: 'started' } }
+ %li.filter-dropdown-item{ data: { value: 'Started' } }
%button.btn.btn-link{ type: 'button' }
= _('Started')
%li.divider.droplab-item-ignore
@@ -92,10 +93,10 @@
{{title}}
#js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'none' } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
%button.btn.btn-link{ type: 'button' }
= _('None')
- %li.filter-dropdown-item{ data: { value: 'any' } }
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
%button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
@@ -107,10 +108,10 @@
{{title}}
#js-dropdown-my-reaction.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'none' } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
%button.btn.btn-link{ type: 'button' }
= _('None')
- %li.filter-dropdown-item{ data: { value: 'any' } }
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
%button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
@@ -128,6 +129,14 @@
%li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
%button.btn.btn-link{ type: 'button' }
= _('No')
+ #js-dropdown-confidential.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('Yes')
+ %li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('No')
= render_if_exists 'shared/issuable/filter_weight', type: type
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 0520eda37a4..9596c1df20e 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -133,7 +133,7 @@
#js-confidential-entry-point
-# haml-lint:disable InlineJavaScript
- %script#js-lock-issue-data{ type: "application/json" }= { is_locked: issuable_sidebar[:discussion_locked], is_editable: can_edit_issuable }.to_json.html_safe
+ %script#js-lock-issue-data{ type: "application/json" }= { is_locked: !!issuable_sidebar[:discussion_locked], is_editable: can_edit_issuable }.to_json.html_safe
#js-lock-entry-point
.js-sidebar-participants-entry-point
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index c5cce1823f0..1a59055f652 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -25,7 +25,7 @@
.value.hide-collapsed
- if issuable_sidebar[:assignee]
= link_to_member(@project, assignee, size: 32, extra_class: 'bold') do
- - if issuable_sidebar[:assignee][:can_merge]
+ - unless issuable_sidebar[:assignee][:can_merge]
%span.float-right.cannot-be-merged{ data: { toggle: 'tooltip', placement: 'left' }, title: _('Not allowed to merge') }
= icon('exclamation-triangle', 'aria-hidden': 'true')
%span.username
diff --git a/app/views/shared/issuable/_sort_dropdown.html.haml b/app/views/shared/issuable/_sort_dropdown.html.haml
index b6ea9185b10..967f31c8325 100644
--- a/app/views/shared/issuable/_sort_dropdown.html.haml
+++ b/app/views/shared/issuable/_sort_dropdown.html.haml
@@ -5,7 +5,7 @@
.dropdown.inline.prepend-left-10.issue-sort-dropdown
.btn-group{ role: 'group' }
.btn-group{ role: 'group' }
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'btn btn-default' }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'btn btn-default' }
= sort_title
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
diff --git a/app/views/shared/issuable/form/_merge_params.html.haml b/app/views/shared/issuable/form/_merge_params.html.haml
index 1881875b7c0..f0c4acdd07f 100644
--- a/app/views/shared/issuable/form/_merge_params.html.haml
+++ b/app/views/shared/issuable/form/_merge_params.html.haml
@@ -10,7 +10,7 @@
= hidden_field_tag 'merge_request[force_remove_source_branch]', '0', id: nil
= check_box_tag 'merge_request[force_remove_source_branch]', '1', issuable.force_remove_source_branch?, class: 'form-check-input'
= label_tag 'merge_request[force_remove_source_branch]', class: 'form-check-label' do
- Remove source branch when merge request is accepted.
+ Delete source branch when merge request is accepted.
.form-group.row
.col-sm-10.offset-sm-2
@@ -19,4 +19,4 @@
= check_box_tag 'merge_request[squash]', '1', issuable.squash, class: 'form-check-input'
= label_tag 'merge_request[squash]', class: 'form-check-label' do
Squash commits when merge request is accepted.
- = link_to 'About this feature', help_page_path('user/project/merge_requests/squash_and_merge')
+ = link_to icon('question-circle'), help_page_path('user/project/merge_requests/squash_and_merge'), target: '_blank'
diff --git a/app/views/shared/labels/_nav.html.haml b/app/views/shared/labels/_nav.html.haml
index 98572db738b..e69246dd0eb 100644
--- a/app/views/shared/labels/_nav.html.haml
+++ b/app/views/shared/labels/_nav.html.haml
@@ -18,3 +18,7 @@
%button.btn.btn-default{ type: "submit", "aria-label" => _('Submit search') }
= icon("search")
= render 'shared/labels/sort_dropdown'
+ - if labels_or_filters && can_admin_label && @project
+ = link_to _('New label'), new_project_label_path(@project), class: "btn btn-success qa-label-create-new"
+ - if labels_or_filters && can_admin_label && @group
+ = link_to _('New label'), new_group_label_path(@group), class: "btn btn-success qa-label-create-new"
diff --git a/app/views/shared/members/_access_request_buttons.html.haml b/app/views/shared/members/_access_request_buttons.html.haml
deleted file mode 100644
index ebae58f28ba..00000000000
--- a/app/views/shared/members/_access_request_buttons.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-- model_name = source.model_name.to_s.downcase
-
-- if can?(current_user, :"destroy_#{model_name}_member", source.members.find_by(user_id: current_user.id)) # rubocop: disable CodeReuse/ActiveRecord
- .project-action-button.inline
- - link_text = source.is_a?(Group) ? _('Leave group') : _('Leave project')
- = link_to link_text, polymorphic_path([:leave, source, :members]),
- method: :delete,
- data: { confirm: leave_confirmation_message(source) },
- class: 'btn'
-- elsif requester = source.requesters.find_by(user_id: current_user.id) # rubocop: disable CodeReuse/ActiveRecord
- .project-action-button.inline
- = link_to _('Withdraw Access Request'), polymorphic_path([:leave, source, :members]),
- method: :delete,
- data: { confirm: remove_member_message(requester) },
- class: 'btn'
-- elsif source.request_access_enabled && can?(current_user, :request_access, source)
- .project-action-button.inline
- = link_to _('Request Access'), polymorphic_path([:request_access, source, :members]),
- method: :post,
- class: 'btn'
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 6b3841ebbc4..2db1f67a793 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -10,7 +10,7 @@
- if user
= image_tag avatar_icon_for_user(user, 40), class: "avatar s40", alt: ''
.user-info
- = link_to user.name, user_path(user), class: 'member'
+ = link_to user.name, user_path(user), class: 'member js-user-link', data: { user_id: user.id }
= user_status(user)
%span.cgray= user.to_reference
diff --git a/app/views/shared/milestones/_form_dates.html.haml b/app/views/shared/milestones/_form_dates.html.haml
index 922805958a5..4de89d7c7a0 100644
--- a/app/views/shared/milestones/_form_dates.html.haml
+++ b/app/views/shared/milestones/_form_dates.html.haml
@@ -1,11 +1,13 @@
.col-md-6
.form-group.row
- = f.label :start_date, "Start Date", class: "col-form-label col-sm-2"
+ .col-form-label.col-sm-2
+ = f.label :start_date, "Start Date"
.col-sm-10
= f.text_field :start_date, class: "datepicker form-control", placeholder: "Select start date", autocomplete: 'off'
%a.inline.float-right.prepend-top-5.js-clear-start-date{ href: "#" } Clear start date
.form-group.row
- = f.label :due_date, "Due Date", class: "col-form-label col-sm-2"
+ .col-form-label.col-sm-2
+ = f.label :due_date, "Due Date"
.col-sm-10
= f.text_field :due_date, class: "datepicker form-control", placeholder: "Select due date", autocomplete: 'off'
%a.inline.float-right.prepend-top-5.js-clear-due-date{ href: "#" } Clear due date
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index ed7fefba56d..e75f0a184ea 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -1,5 +1,5 @@
- dashboard = local_assigns[:dashboard]
-- custom_dom_id = dom_id(milestone.try(:milestones) ? milestone.milestones.first : milestone)
+- custom_dom_id = dom_id(milestone.try(:milestone) ? milestone.milestone : milestone)
- milestone_type = milestone.group_milestone? ? 'Group Milestone' : 'Project Milestone'
%li{ class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: custom_dom_id }
@@ -21,16 +21,18 @@
= milestone.group.full_name
- if milestone.legacy_group_milestone?
.projects
- - milestone.milestones.each do |milestone|
- = link_to milestone_path(milestone) do
- %span.label-badge.label-badge-blue.d-inline-block.append-bottom-5
- = dashboard ? milestone.project.full_name : milestone.project.name
+ - link_to milestone_path(milestone.milestone) do
+ %span.label-badge.label-badge-blue.d-inline-block.append-bottom-5
+ = dashboard ? milestone.project.full_name : milestone.project.name
+ - if milestone.project
+ .label-badge.label-badge-gray.d-inline-block
+ = milestone.project.full_name
.col-sm-4.milestone-progress
= milestone_progress_bar(milestone)
= link_to pluralize(milestone.total_issues_count(current_user), 'Issue'), issues_path
&middot;
- = link_to pluralize(milestone.merge_requests.size, 'Merge Request'), merge_requests_path
+ = link_to pluralize(milestone.merge_requests_visible_to_user(current_user).size, 'Merge Request'), merge_requests_path
.float-lg-right.light #{milestone.percent_complete(current_user)}% complete
.col-sm-2
.milestone-actions.d-flex.justify-content-sm-start.justify-content-md-end
@@ -58,5 +60,5 @@
- else
= link_to 'Close Milestone', group_milestone_route(milestone, {state_event: :close }), method: :put, class: "btn btn-sm btn-grouped btn-close"
- if dashboard
- .status-box.status-box-milestone
+ .label-badge.label-badge-gray
= milestone_type
diff --git a/app/views/shared/milestones/_search_form.html.haml b/app/views/shared/milestones/_search_form.html.haml
new file mode 100644
index 00000000000..403a0224a85
--- /dev/null
+++ b/app/views/shared/milestones/_search_form.html.haml
@@ -0,0 +1,8 @@
+= form_tag request.path, method: :get do |f|
+ = search_field_tag :search_title, params[:search_title],
+ placeholder: _('Filter by milestone name'),
+ class: 'form-control input-short',
+ spellcheck: false
+ = hidden_field_tag :state, params[:state]
+ = hidden_field_tag :sort, params[:sort]
+
diff --git a/app/views/shared/milestones/_tabs.html.haml b/app/views/shared/milestones/_tabs.html.haml
index 55460acab8f..b877f66c71e 100644
--- a/app/views/shared/milestones/_tabs.html.haml
+++ b/app/views/shared/milestones/_tabs.html.haml
@@ -12,7 +12,7 @@
%li.nav-item
= link_to '#tab-merge-requests', class: 'nav-link', 'data-toggle' => 'tab', 'data-endpoint': milestone_merge_request_tab_path(milestone) do
Merge Requests
- %span.badge.badge-pill= milestone.merge_requests.size
+ %span.badge.badge-pill= milestone.merge_requests_visible_to_user(current_user).size
- else
%li.nav-item
= link_to '#tab-merge-requests', class: 'nav-link active', 'data-toggle' => 'tab', 'data-endpoint': milestone_merge_request_tab_path(milestone) do
@@ -21,11 +21,11 @@
%li.nav-item
= link_to '#tab-participants', class: 'nav-link', 'data-toggle' => 'tab', 'data-endpoint': milestone_participants_tab_path(milestone) do
Participants
- %span.badge.badge-pill= milestone.participants.count
+ %span.badge.badge-pill= milestone.issue_participants_visible_by_user(current_user).count
%li.nav-item
= link_to '#tab-labels', class: 'nav-link', 'data-toggle' => 'tab', 'data-endpoint': milestone_labels_tab_path(milestone) do
Labels
- %span.badge.badge-pill= milestone.labels.count
+ %span.badge.badge-pill= milestone.issue_labels_visible_by_user(current_user).count
- issues = milestone.sorted_issues(current_user)
- show_project_name = local_assigns.fetch(:show_project_name, false)
diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml
index 0499b04a482..55b1c14022f 100644
--- a/app/views/shared/milestones/_top.html.haml
+++ b/app/views/shared/milestones/_top.html.haml
@@ -62,20 +62,19 @@
%th Open issues
%th State
%th Due date
- - milestone.milestones.each do |ms|
%tr
%td
- - project_name = group ? ms.project.name : ms.project.full_name
- = link_to project_name, project_milestone_path(ms.project, ms)
+ - project_name = group ? milestone.project.name : milestone.project.full_name
+ = link_to project_name, milestone_path(milestone.milestone)
%td
- = ms.issues_visible_to_user(current_user).opened.count
+ = milestone.milestone.issues_visible_to_user(current_user).opened.count
%td
- - if ms.closed?
+ - if milestone.closed?
Closed
- else
Open
%td
- = ms.expires_at
+ = milestone.expires_at
- elsif milestone.group_milestone?
%br
View
diff --git a/app/views/shared/notes/_comment_button.html.haml b/app/views/shared/notes/_comment_button.html.haml
index 0674c822d63..c3f5eeb0da6 100644
--- a/app/views/shared/notes/_comment_button.html.haml
+++ b/app/views/shared/notes/_comment_button.html.haml
@@ -1,30 +1,31 @@
- noteable_name = @note.noteable.human_class_name
.float-left.btn-group.append-right-10.droplab-dropdown.comment-type-dropdown.js-comment-type-dropdown
- %input.btn.btn-nr.btn-success.comment-btn.js-comment-button.js-comment-submit-button{ type: 'submit', value: 'Comment' }
+ %input.btn.btn-nr.btn-success.js-comment-button.js-comment-submit-button{ type: 'submit', value: _('Comment') }
- if @note.can_be_discussion_note?
- = button_tag type: 'button', class: 'btn btn-nr dropdown-toggle comment-btn js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => 'Open comment type dropdown' do
+ = button_tag type: 'button', class: 'btn btn-nr dropdown-toggle btn-success js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => _('Open comment type dropdown') do
= icon('caret-down', class: 'toggle-icon')
%ul#resolvable-comment-menu.dropdown-menu.dropdown-open-top{ data: { dropdown: true } }
- %li#comment.droplab-item-selected{ data: { value: '', 'submit-text' => 'Comment', 'close-text' => "Comment & close #{noteable_name}", 'reopen-text' => "Comment & reopen #{noteable_name}" } }
+ %li#comment.droplab-item-selected{ data: { value: '', 'submit-text' => _('Comment'), 'close-text' => _("Comment & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Comment & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
%button.btn.btn-transparent
= icon('check', class: 'icon')
.description
- %strong Comment
+ %strong= _("Comment")
%p
- Add a general comment to this #{noteable_name}.
+ = _("Add a general comment to this %{noteable_name}.") % { noteable_name: noteable_name }
%li.divider.droplab-item-ignore
- %li#discussion{ data: { value: 'DiscussionNote', 'submit-text' => 'Start discussion', 'close-text' => "Start discussion & close #{noteable_name}", 'reopen-text' => "Start discussion & reopen #{noteable_name}" } }
+ %li#discussion{ data: { value: 'DiscussionNote', 'submit-text' => _('Start discussion'), 'close-text' => _("Start discussion & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Start discussion & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
%button.btn.btn-transparent
= icon('check', class: 'icon')
.description
- %strong Start discussion
+ %strong= _("Start discussion")
%p
= succeed '.' do
- Discuss a specific suggestion or question
- if @note.noteable.supports_resolvable_notes?
- that needs to be resolved
+ = _('Discuss a specific suggestion or question that needs to be resolved')
+ - else
+ = _('Discuss a specific suggestion or question')
diff --git a/app/views/shared/notes/_edit.html.haml b/app/views/shared/notes/_edit.html.haml
index f4b3aac29b4..84a3ef9d8fe 100644
--- a/app/views/shared/notes/_edit.html.haml
+++ b/app/views/shared/notes/_edit.html.haml
@@ -1 +1 @@
-%textarea.hidden.js-task-list-field.original-task-list{ data: {update_url: note_url(note) } }= note.note
+%textarea.hidden.js-task-list-field.original-task-list{ data: { update_url: note_url(note) } }= note.note
diff --git a/app/views/shared/notes/_edit_form.html.haml b/app/views/shared/notes/_edit_form.html.haml
index fec966069b9..6fe511c2999 100644
--- a/app/views/shared/notes/_edit_form.html.haml
+++ b/app/views/shared/notes/_edit_form.html.haml
@@ -3,12 +3,12 @@
= hidden_field_tag :target_id, '', class: 'js-form-target-id'
= hidden_field_tag :target_type, '', class: 'js-form-target-type'
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(project), referenced_users: true } do
- = render 'projects/zen', attr: 'note[note]', classes: 'note-textarea js-note-text js-task-list-field', placeholder: "Write a comment or drag your files here…"
+ = render 'projects/zen', attr: 'note[note]', classes: 'note-textarea js-note-text js-task-list-field', placeholder: _("Write a comment or drag your files here…")
= render 'shared/notes/hints'
.note-form-actions.clearfix
.settings-message.note-edit-warning.js-finish-edit-warning
- Finish editing this message first!
- = submit_tag 'Save comment', class: 'btn btn-nr btn-success js-comment-save-button'
+ = _("Finish editing this message first!")
+ = submit_tag _('Save comment'), class: 'btn btn-nr btn-success js-comment-save-button'
%button.btn.btn-nr.btn-cancel.note-edit-cancel{ type: 'button' }
- Cancel
+ = _("Cancel")
diff --git a/app/views/shared/notes/_form.html.haml b/app/views/shared/notes/_form.html.haml
index c360f1ffe2a..6a1eea85fde 100644
--- a/app/views/shared/notes/_form.html.haml
+++ b/app/views/shared/notes/_form.html.haml
@@ -29,7 +29,7 @@
= render 'projects/zen', f: f,
attr: :note,
classes: 'note-textarea js-note-text',
- placeholder: "Write a comment or drag your files here…",
+ placeholder: _("Write a comment or drag your files here…"),
supports_quick_actions: supports_quick_actions,
supports_autocomplete: supports_autocomplete
= render 'shared/notes/hints', supports_quick_actions: supports_quick_actions
@@ -40,5 +40,5 @@
= yield(:note_actions)
- %a.btn.btn-cancel.js-note-discard{ role: "button", data: {cancel_text: "Cancel" } }
- Discard draft
+ %a.btn.btn-cancel.js-close-discussion-note-form.hide{ role: "button", data: { cancel_text: _("Cancel") } }
+ = _('Cancel')
diff --git a/app/views/shared/notes/_hints.html.haml b/app/views/shared/notes/_hints.html.haml
index 00eae553279..46f3f8428f1 100644
--- a/app/views/shared/notes/_hints.html.haml
+++ b/app/views/shared/notes/_hints.html.haml
@@ -1,10 +1,10 @@
- supports_quick_actions = local_assigns.fetch(:supports_quick_actions, false)
.comment-toolbar.clearfix
.toolbar-text
- = link_to 'Markdown', help_page_path('user/markdown'), target: '_blank', tabindex: -1
+ = link_to _('Markdown'), help_page_path('user/markdown'), target: '_blank', tabindex: -1
- if supports_quick_actions
and
- = link_to 'quick actions', help_page_path('user/project/quick_actions'), target: '_blank', tabindex: -1
+ = link_to _('quick actions'), help_page_path('user/project/quick_actions'), target: '_blank', tabindex: -1
are
- else
is
@@ -24,12 +24,12 @@
= icon('file-image-o', class: 'toolbar-button-icon')
%span.uploading-error-message
-# Populated by app/assets/javascripts/dropzone_input.js
- %button.retry-uploading-link{ type: 'button' } Try again
+ %button.retry-uploading-link{ type: 'button' }= _("Try again")
or
- %button.attach-new-file.markdown-selector{ type: 'button' } attach a new file
+ %button.attach-new-file.markdown-selector{ type: 'button' }= _("attach a new file")
%button.markdown-selector.button-attach-file{ type: 'button', tabindex: '-1' }
= icon('file-image-o', class: 'toolbar-button-icon')
- Attach a file
+ = _("Attach a file")
- %button.btn.btn-default.btn-sm.hide.button-cancel-uploading-files{ type: 'button' } Cancel
+ %button.btn.btn-default.btn-sm.hide.button-cancel-uploading-files{ type: 'button' }= _("Cancel")
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index e125d7f108a..41d6ae79c81 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -54,7 +54,7 @@
.note-text.md
= markdown_field(note, :note)
= edited_time_ago_with_tooltip(note, placement: 'bottom', html_class: 'note_edited_ago')
- .original-note-content.hidden{ data: { post_url: note_url(note), target_id: note.noteable.id, target_type: note.noteable.class.name.underscore, markdown_version: note.cached_markdown_version } }
+ .original-note-content.hidden{ data: { post_url: note_url(note), target_id: note.noteable.id, target_type: note.noteable.class.name.underscore } }
#{note.note}
- if note_editable
= render 'shared/notes/edit', note: note
@@ -62,7 +62,7 @@
= render 'award_emoji/awards_block', awardable: note, inline: false
- if note.system
.system-note-commit-list-toggler.hide
- Toggle commit list
+ = _("Toggle commit list")
%i.fa.fa-angle-down
- if note.attachment.url
.note-attachment
@@ -74,5 +74,5 @@
= icon('paperclip')
= note.attachment_identifier
= link_to delete_attachment_project_note_path(note.project, note),
- title: 'Delete this attachment', method: :delete, remote: true, data: { confirm: 'Are you sure you want to remove the attachment?' }, class: 'danger js-note-attachment-delete' do
+ title: _('Delete this attachment'), method: :delete, remote: true, data: { confirm: _('Are you sure you want to remove the attachment?') }, class: 'danger js-note-attachment-delete' do
= icon('trash-o', class: 'cred')
diff --git a/app/views/shared/notes/_notes_with_form.html.haml b/app/views/shared/notes/_notes_with_form.html.haml
index 4c4050c6054..002189e6ecd 100644
--- a/app/views/shared/notes/_notes_with_form.html.haml
+++ b/app/views/shared/notes/_notes_with_form.html.haml
@@ -19,20 +19,14 @@
= render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete
- elsif !current_user
.disabled-comment.text-center.prepend-top-default
- Please
- = link_to "register", new_session_path(:user, redirect_to_referer: 'yes', anchor: 'register-pane'), class: 'js-register-link'
- or
- = link_to "sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'js-sign-in-link'
- to comment
+ - link_to_register = link_to(_("register"), new_session_path(:user, redirect_to_referer: 'yes', anchor: 'register-pane'), class: 'js-register-link')
+ - link_to_sign_in = link_to(_("sign in"), new_session_path(:user, redirect_to_referer: 'yes'), class: 'js-sign-in-link')
+ = _("Please %{link_to_register} or %{link_to_sign_in} to comment").html_safe % { link_to_register: link_to_register, link_to_sign_in: link_to_sign_in }
- elsif discussion_locked
.disabled-comment.text-center.prepend-top-default
%span.issuable-note-warning
= sprite_icon('lock', size: 16, css_class: 'icon')
%span
- This
- = issuable.class.to_s.titleize.downcase
- is locked. Only
- %b project members
- can comment.
+ = _("This %{issuable} is locked. Only <strong>project members</strong> can comment.").html_safe % { issuable: issuable.class.to_s.titleize.downcase }
-# haml-lint:disable InlineJavaScript
%script.js-notes-data{ type: "application/json" }= initial_notes_data(autocomplete).to_json.html_safe
diff --git a/app/views/shared/notifications/_button.html.haml b/app/views/shared/notifications/_button.html.haml
index 30860988bbb..2ece7b7f701 100644
--- a/app/views/shared/notifications/_button.html.haml
+++ b/app/views/shared/notifications/_button.html.haml
@@ -1,7 +1,7 @@
- btn_class = local_assigns.fetch(:btn_class, nil)
- if notification_setting
- .js-notification-dropdown.notification-dropdown.project-action-button.dropdown.inline
+ .js-notification-dropdown.notification-dropdown.home-panel-action-button.dropdown.inline
= form_for notification_setting, remote: true, html: { class: "inline notification-form" } do |f|
= hidden_setting_source_input(notification_setting)
= f.hidden_field :level, class: "notification_setting_level"
diff --git a/app/views/shared/notifications/_new_button.html.haml b/app/views/shared/notifications/_new_button.html.haml
new file mode 100644
index 00000000000..6d26dbebbc8
--- /dev/null
+++ b/app/views/shared/notifications/_new_button.html.haml
@@ -0,0 +1,27 @@
+- btn_class = local_assigns.fetch(:btn_class, nil)
+
+- if notification_setting
+ .js-notification-dropdown.notification-dropdown.home-panel-action-button.prepend-top-default.append-right-8.dropdown.inline
+ = form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f|
+ = hidden_setting_source_input(notification_setting)
+ = hidden_field_tag "hide_label", true
+ = f.hidden_field :level, class: "notification_setting_level"
+ .js-notification-toggle-btns
+ %div{ class: ("btn-group" if notification_setting.custom?) }
+ - if notification_setting.custom?
+ %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", placement: 'top', toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
+ = sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
+ %span.js-notification-loading.fa.hidden
+ %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" }, class: "#{btn_class}" }
+ = sprite_icon("arrow-down", css_class: "icon mr-0")
+ .sr-only Toggle dropdown
+ - else
+ %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting - #{notification_title(notification_setting.level)}", class: "#{btn_class}", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", placement: 'top', toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
+ = sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
+ %span.js-notification-loading.fa.hidden
+ = sprite_icon("arrow-down", css_class: "icon")
+
+ = render "shared/notifications/notification_dropdown", notification_setting: notification_setting
+
+ = content_for :scripts_body do
+ = render "shared/notifications/custom_notifications", notification_setting: notification_setting
diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml
index 15c29e14cc0..13847cd9be1 100644
--- a/app/views/shared/projects/_list.html.haml
+++ b/app/views/shared/projects/_list.html.haml
@@ -14,6 +14,17 @@
- skip_pagination = false unless local_assigns[:skip_pagination] == true
- compact_mode = false unless local_assigns[:compact_mode] == true
- css_classes = "#{'compact' if compact_mode} #{'explore' if explore_projects_tab?}"
+- contributed_projects_illustration_path = 'illustrations/profile-page/contributed-projects.svg'
+- contributed_projects_current_user_empty_message_header = s_('UserProfile|Explore public groups to find projects to contribute to.')
+- contributed_projects_visitor_empty_message = s_('UserProfile|This user hasn\'t contributed to any projects')
+- own_projects_illustration_path = 'illustrations/profile-page/personal-project.svg'
+- own_projects_current_user_empty_message_header = s_('UserProfile|You haven\'t created any personal projects.')
+- own_projects_current_user_empty_message_description = s_('UserProfile|Your projects can be available publicly, internally, or privately, at your choice.')
+- own_projects_visitor_empty_message = s_('UserProfile|This user doesn\'t have any personal projects')
+- primary_button_label = _('New project')
+- primary_button_link = new_project_path
+- secondary_button_label = _('Explore groups')
+- secondary_button_link = explore_groups_path
.js-projects-list-holder
- if any_projects?(projects)
@@ -33,4 +44,18 @@
%span &nbsp;you have no access to.
= paginate_collection(projects, remote: remote) unless skip_pagination
- else
- .nothing-here-block No projects found
+ - if @contributed_projects
+ = render partial: 'shared/empty_states/profile_tabs', locals: { illustration_path: contributed_projects_illustration_path,
+ current_user_empty_message_header: contributed_projects_current_user_empty_message_header,
+ primary_button_label: primary_button_label,
+ primary_button_link: primary_button_link,
+ secondary_button_label: secondary_button_label,
+ secondary_button_link: secondary_button_link,
+ visitor_empty_message: contributed_projects_visitor_empty_message }
+ - else
+ = render partial: 'shared/empty_states/profile_tabs', locals: { illustration_path: own_projects_illustration_path,
+ current_user_empty_message_header: own_projects_current_user_empty_message_header,
+ current_user_empty_message_description: own_projects_current_user_empty_message_description,
+ primary_button_label: primary_button_label,
+ primary_button_link: primary_button_link,
+ visitor_empty_message: own_projects_visitor_empty_message }
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index fea7e17be3d..d2b1be29eb9 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -12,21 +12,21 @@
- css_class += " no-description" if project.description.blank? && !show_last_commit_as_description
- cache_key = project_list_cache_key(project)
- updated_tooltip = time_ago_with_tooltip(project.last_activity_date)
-- css_details_class = compact_mode ? "d-flex flex-column flex-sm-row flex-md-row align-items-sm-center" : "align-items-center flex-md-fill flex-lg-column d-sm-flex d-lg-block"
-- css_controls_class = compact_mode ? "" : "align-items-md-end align-items-lg-center flex-lg-row"
+- css_controls_class = compact_mode ? "" : "flex-lg-row justify-content-lg-between"
+- avatar_container_class = project.creator && use_creator_avatar ? '' : 'rect-avatar'
%li.project-row.d-flex{ class: css_class }
= cache(cache_key) do
- if avatar
- .avatar-container.s64.flex-grow-0.flex-shrink-0
+ .avatar-container.s48.flex-grow-0.flex-shrink-0{ class: avatar_container_class }
= link_to project_path(project), class: dom_class(project) do
- if project.creator && use_creator_avatar
- = image_tag avatar_icon_for_user(project.creator, 64), class: "avatar s65", alt:''
+ = image_tag avatar_icon_for_user(project.creator, 48), class: "avatar s48", alt:''
- else
- = project_icon(project, alt: '', class: 'avatar project-avatar s64', width: 64, height: 64)
- .project-details.flex-sm-fill{ class: css_details_class }
- .flex-wrapper.flex-fill
- .d-flex.align-items-center.flex-wrap
+ = project_icon(project, alt: '', class: 'avatar project-avatar s48', width: 48, height: 48)
+ .project-details.d-sm-flex.flex-sm-fill.align-items-center
+ .flex-wrapper
+ .d-flex.align-items-center.flex-wrap.project-title
%h2.d-flex.prepend-top-8
= link_to project_path(project), class: 'text-plain' do
%span.project-full-name.append-right-8><
@@ -52,13 +52,13 @@
%span.user-access-role.d-block= Gitlab::Access.human_access(access)
- if show_last_commit_as_description
- .description.d-none.d-sm-block.prepend-top-8.append-right-default
+ .description.d-none.d-sm-block.append-right-default
= link_to_markdown(project.commit.title, project_commit_path(project, project.commit), class: "commit-row-message")
- elsif project.description.present?
- .description.d-none.d-sm-block.prepend-top-8.append-right-default
+ .description.d-none.d-sm-block.append-right-default
= markdown_field(project, :description)
- .controls.d-flex.flex-row.flex-sm-column.flex-md-column.align-items-center.align-items-sm-end.flex-wrap.flex-shrink-0{ class: css_controls_class }
+ .controls.d-flex.flex-sm-column.align-items-center.align-items-sm-end.flex-wrap.flex-shrink-0{ class: css_controls_class }
.icon-container.d-flex.align-items-center
- if project.archived
%span.d-flex.icon-wrapper.badge.badge-warning archived
@@ -74,34 +74,19 @@
= number_with_delimiter(project.forks_count)
- if show_merge_request_count?(disabled: !merge_requests, compact_mode: compact_mode)
= link_to project_merge_requests_path(project),
- class: "d-none d-lg-flex align-items-center icon-wrapper merge-requests has-tooltip",
+ class: "d-none d-xl-flex align-items-center icon-wrapper merge-requests has-tooltip",
title: _('Merge Requests'), data: { container: 'body', placement: 'top' } do
= sprite_icon('git-merge', size: 14, css_class: 'append-right-4')
= number_with_delimiter(project.open_merge_requests_count)
- if show_issue_count?(disabled: !issues, compact_mode: compact_mode)
= link_to project_issues_path(project),
- class: "d-none d-lg-flex align-items-center icon-wrapper issues has-tooltip",
+ class: "d-none d-xl-flex align-items-center icon-wrapper issues has-tooltip",
title: _('Issues'), data: { container: 'body', placement: 'top' } do
= sprite_icon('issues', size: 14, css_class: 'append-right-4')
= number_with_delimiter(project.open_issues_count)
- - if pipeline_status && can?(current_user, :read_cross_project) && project.pipeline_status.has_status?
+ - if pipeline_status && can?(current_user, :read_cross_project) && project.pipeline_status.has_status? && can?(current_user, :read_build, project)
+ - pipeline_path = pipelines_project_commit_path(project.pipeline_status.project, project.pipeline_status.sha, ref: project.pipeline_status.ref)
%span.icon-wrapper.pipeline-status
- = render_project_pipeline_status(project.pipeline_status, tooltip_placement: 'top')
+ = render 'ci/status/icon', status: project.commit.last_pipeline.detailed_status(current_user), type: 'commit', tooltip_placement: 'top', path: pipeline_path
.updated-note
%span Updated #{updated_tooltip}
-
- .d-none.d-lg-flex.align-item-stretch
- - unless compact_mode
- - if current_user
- %button.star-button.btn.btn-default.d-flex.align-items-center.star-btn.toggle-star{ type: "button", data: { endpoint: toggle_star_project_path(project, :json) } }
- - if current_user.starred?(project)
- = sprite_icon('star', { css_class: 'icon' })
- %span.starred= s_('ProjectOverview|Unstar')
- - else
- = sprite_icon('star-o', { css_class: 'icon' })
- %span= s_('ProjectOverview|Star')
-
- - else
- = link_to new_user_session_path, class: 'btn btn-default has-tooltip count-badge-button d-flex align-items-center 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')
diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml
index cf9c3055499..3007da0c189 100644
--- a/app/views/shared/snippets/_form.html.haml
+++ b/app/views/shared/snippets/_form.html.haml
@@ -3,8 +3,7 @@
.snippet-form-holder
= form_for @snippet, url: url,
- html: { class: "snippet-form js-requires-input js-quick-submit common-note-form" },
- data: { markdown_version: @snippet.cached_markdown_version } do |f|
+ html: { class: "snippet-form js-requires-input js-quick-submit common-note-form" } do |f|
= form_errors(@snippet)
.form-group.row
diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml
index 10bfc30492a..a43296aa806 100644
--- a/app/views/shared/snippets/_header.html.haml
+++ b/app/views/shared/snippets/_header.html.haml
@@ -30,7 +30,7 @@
- if @snippet.updated_at != @snippet.created_at
= edited_time_ago_with_tooltip(@snippet, placement: 'bottom', html_class: 'snippet-edited-ago', exclude_author: true)
- - if public_snippet?
+ - if @snippet.embeddable?
.embed-snippet
.input-group
.input-group-prepend
diff --git a/app/views/shared/snippets/_list.html.haml b/app/views/shared/snippets/_list.html.haml
new file mode 100644
index 00000000000..5d2152eb411
--- /dev/null
+++ b/app/views/shared/snippets/_list.html.haml
@@ -0,0 +1,12 @@
+- remote = local_assigns.fetch(:remote, false)
+- link_project = local_assigns.fetch(:link_project, false)
+
+- if @snippets.exists?
+ .snippets-list-holder
+ %ul.content-list
+ = render partial: 'shared/snippets/snippet', collection: @snippets, locals: { link_project: link_project }
+
+ = paginate @snippets, theme: 'gitlab', remote: remote
+
+- else
+ .nothing-here-block= s_("SnippetsEmptyState|No snippets found")
diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml
index 5069e2e4ca6..42af97bc6af 100644
--- a/app/views/shared/snippets/_snippet.html.haml
+++ b/app/views/shared/snippets/_snippet.html.haml
@@ -25,7 +25,7 @@
#{snippet.to_reference} &middot;
authored #{time_ago_with_tooltip(snippet.created_at, placement: 'bottom', html_class: 'snippet-created-ago')}
by
- = link_to user_snippets_path(snippet.author) do
+ = link_to user_snippets_path(snippet.author), class: "js-user-link", data: { user_id: snippet.author.id } do
= snippet.author_name
- if link_project && snippet.project_id?
%span.d-none.d-sm-inline-block
diff --git a/app/views/shared/tokens/_scopes_form.html.haml b/app/views/shared/tokens/_scopes_form.html.haml
index af9db5f59a8..a5d3e1c8de0 100644
--- a/app/views/shared/tokens/_scopes_form.html.haml
+++ b/app/views/shared/tokens/_scopes_form.html.haml
@@ -4,6 +4,6 @@
- scopes.each do |scope|
%fieldset.form-group.form-check
- = check_box_tag "#{prefix}[scopes][]", scope, token.scopes.include?(scope), id: "#{prefix}_scopes_#{scope}", class: 'form-check-input'
+ = check_box_tag "#{prefix}[scopes][]", scope, token.scopes.include?(scope), id: "#{prefix}_scopes_#{scope}", class: "form-check-input qa-#{scope}-radio"
= label_tag ("#{prefix}_scopes_#{scope}"), scope, class: 'label-bold form-check-label'
.text-secondary= t scope, scope: [:doorkeeper, :scope_desc]
diff --git a/app/views/snippets/_snippets.html.haml b/app/views/snippets/_snippets.html.haml
index 69d41f8fe5e..dab247da251 100644
--- a/app/views/snippets/_snippets.html.haml
+++ b/app/views/snippets/_snippets.html.haml
@@ -1,10 +1,21 @@
- link_project = local_assigns.fetch(:link_project, false)
+- illustration_path = 'illustrations/profile-page/activity.svg'
+- current_user_empty_message_header = s_('UserProfile|You haven\'t created any snippets.')
+- current_user_empty_message_description = s_('UserProfile|Snippets in GitLab can either be private, internal, or public.')
+- primary_button_label = _('New snippet')
+- primary_button_link = new_snippet_path
+- visitor_empty_message = s_('UserProfile|No snippets found.')
.snippets-list-holder
%ul.content-list
= render partial: 'shared/snippets/snippet', collection: @snippets, locals: { link_project: link_project }
- if @snippets.empty?
%li
- .nothing-here-block= _("Nothing here.")
+ = render partial: 'shared/empty_states/profile_tabs', locals: { illustration_path: illustration_path,
+ current_user_empty_message_header: current_user_empty_message_header,
+ current_user_empty_message_description: current_user_empty_message_description,
+ primary_button_label: primary_button_label,
+ primary_button_link: primary_button_link,
+ visitor_empty_message: visitor_empty_message }
= paginate @snippets, theme: 'gitlab'
diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml
index 4f418e2381f..f5fe75bed5a 100644
--- a/app/views/snippets/index.html.haml
+++ b/app/views/snippets/index.html.haml
@@ -10,4 +10,4 @@
= link_to user_path(@user) do
= _("%{user_name} profile page") % { user_name: @user.name }
-= render 'snippets'
+= render 'shared/snippets/list'
diff --git a/app/views/users/_groups.html.haml b/app/views/users/_groups.html.haml
index 55799e10a46..6d7a52c7688 100644
--- a/app/views/users/_groups.html.haml
+++ b/app/views/users/_groups.html.haml
@@ -1,5 +1,5 @@
.clearfix
- groups.each do |group|
= link_to group, class: 'profile-groups-avatars inline', title: group.name do
- .avatar-container.s40
+ .avatar-container.rect-avatar.s40
= group_icon(group, class: 'avatar group-avatar s40')
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index d22905ecc93..b5bc1180290 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -9,24 +9,22 @@
.col-md-12.col-lg-6
- if can?(current_user, :read_cross_project)
.activities-block
- .append-right-5
- .prepend-top-16
- .d-flex.align-items-center.border-bottom
- %h4.flex-grow
- = s_('UserProfile|Activity')
- = link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all"
- .overview-content-list{ data: { href: user_path } }
- .center.light.loading
- = spinner nil, true
-
- .col-md-12.col-lg-6
- .projects-block
- .prepend-left-5
.prepend-top-16
.d-flex.align-items-center.border-bottom
%h4.flex-grow
- = s_('UserProfile|Personal projects')
- = link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all"
- .overview-content-list{ data: { href: user_projects_path } }
+ = s_('UserProfile|Activity')
+ = link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all"
+ .overview-content-list{ data: { href: user_path } }
.center.light.loading
= spinner nil, true
+
+ .col-md-12.col-lg-6
+ .projects-block
+ .prepend-top-16
+ .d-flex.align-items-center.border-bottom
+ %h4.flex-grow
+ = s_('UserProfile|Personal projects')
+ = link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all"
+ .overview-content-list{ data: { href: user_projects_path } }
+ .center.light.loading
+ = spinner nil, true
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index dd2cd36eac2..211e3eafac6 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -71,14 +71,14 @@
= icon('twitter-square')
- unless @user.website_url.blank?
.profile-link-holder.middle-dot-divider
- = link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'noopener noreferrer nofollow'
+ = link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'me noopener noreferrer nofollow'
- unless @user.location.blank?
.profile-link-holder.middle-dot-divider
- = icon('map-marker')
+ = sprite_icon('location', size: 16, css_class: 'vertical-align-sub')
= @user.location
- unless @user.organization.blank?
.profile-link-holder.middle-dot-divider
- = icon('briefcase')
+ = sprite_icon('work', size: 16, css_class: 'vertical-align-sub')
= @user.organization
- if @user.bio.present?
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index d3cf21db335..d86f654dd44 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -23,6 +23,7 @@
- cronjob:prune_web_hook_logs
- gcp_cluster:cluster_install_app
+- gcp_cluster:cluster_upgrade_app
- gcp_cluster:cluster_provision
- gcp_cluster:cluster_wait_for_app_installation
- gcp_cluster:wait_for_cluster_creation
@@ -45,6 +46,11 @@
- github_importer:github_import_stage_import_pull_requests
- github_importer:github_import_stage_import_repository
+- hashed_storage:hashed_storage_migrator
+- hashed_storage:hashed_storage_rollbacker
+- hashed_storage:hashed_storage_project_migrate
+- hashed_storage:hashed_storage_project_rollback
+
- mail_scheduler:mail_scheduler_issue_due
- mail_scheduler:mail_scheduler_notification_service
@@ -90,13 +96,16 @@
- object_pool:object_pool_join
- object_pool:object_pool_destroy
+- container_repository:delete_container_repository
+- container_repository:cleanup_container_repository
+
- default
- mailers # ActionMailer::DeliveryJob.queue_name
- authorized_projects
- background_migration
+- chat_notification
- create_gpg_signature
-- delete_container_repository
- delete_merged_branches
- delete_user
- email_receiver
@@ -120,7 +129,6 @@
- project_cache
- project_destroy
- project_export
-- project_migrate_hashed_storage
- project_service
- propagate_service_template
- reactive_caching
@@ -129,7 +137,6 @@
- repository_fork
- repository_import
- repository_remove_remote
-- storage_migrator
- system_hook_push
- update_merge_requests
- upload_checksum
@@ -140,3 +147,5 @@
- detect_repository_languages
- repository_cleanup
- delete_stored_files
+- import_issues_csv
+- project_daily_statistics
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
index 61d866b1f02..adc38226405 100644
--- a/app/workers/build_finished_worker.rb
+++ b/app/workers/build_finished_worker.rb
@@ -9,14 +9,27 @@ class BuildFinishedWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
- # We execute that in sync as this access the files in order to access local file, and reduce IO
- BuildTraceSectionsWorker.new.perform(build.id)
- BuildCoverageWorker.new.perform(build.id)
-
- # We execute that async as this are two independent operations that can be executed after TraceSections and Coverage
- BuildHooksWorker.perform_async(build.id)
- ArchiveTraceWorker.perform_async(build.id)
+ process_build(build)
end
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ # Processes a single CI build that has finished.
+ #
+ # This logic resides in a separate method so that EE can extend it more
+ # easily.
+ #
+ # @param [Ci::Build] build The build to process.
+ def process_build(build)
+ # We execute these in sync to reduce IO.
+ BuildTraceSectionsWorker.new.perform(build.id)
+ BuildCoverageWorker.new.perform(build.id)
+
+ # We execute these async as these are independent operations.
+ BuildHooksWorker.perform_async(build.id)
+ ArchiveTraceWorker.perform_async(build.id)
+ ChatNotificationWorker.perform_async(build.id) if build.pipeline.chat?
+ end
end
diff --git a/app/workers/chat_notification_worker.rb b/app/workers/chat_notification_worker.rb
new file mode 100644
index 00000000000..25a306e94d8
--- /dev/null
+++ b/app/workers/chat_notification_worker.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class ChatNotificationWorker
+ include ApplicationWorker
+
+ RESCHEDULE_INTERVAL = 2.seconds
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def perform(build_id)
+ Ci::Build.find_by(id: build_id).try do |build|
+ send_response(build)
+ end
+ rescue Gitlab::Chat::Output::MissingBuildSectionError
+ # The creation of traces and sections appears to be eventually consistent.
+ # As a result it's possible for us to run the above code before the trace
+ # sections are present. To better handle such cases we'll just reschedule
+ # the job instead of producing an error.
+ self.class.perform_in(RESCHEDULE_INTERVAL, build_id)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def send_response(build)
+ Gitlab::Chat::Responder.responder_for(build).try do |responder|
+ if build.success?
+ output = Gitlab::Chat::Output.new(build)
+
+ responder.success(output.to_s)
+ else
+ responder.failure
+ end
+ end
+ end
+end
diff --git a/app/workers/cleanup_container_repository_worker.rb b/app/workers/cleanup_container_repository_worker.rb
new file mode 100644
index 00000000000..974ee8c8146
--- /dev/null
+++ b/app/workers/cleanup_container_repository_worker.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+class CleanupContainerRepositoryWorker
+ include ApplicationWorker
+ include ExclusiveLeaseGuard
+
+ queue_namespace :container_repository
+
+ LEASE_TIMEOUT = 1.hour
+
+ attr_reader :container_repository, :current_user
+
+ def perform(current_user_id, container_repository_id, params)
+ @current_user = User.find_by_id(current_user_id)
+ @container_repository = ContainerRepository.find_by_id(container_repository_id)
+
+ return unless valid?
+
+ try_obtain_lease do
+ Projects::ContainerRepository::CleanupTagsService
+ .new(project, current_user, params)
+ .execute(container_repository)
+ end
+ end
+
+ private
+
+ def valid?
+ current_user && container_repository && project
+ end
+
+ def project
+ container_repository&.project
+ end
+
+ # For ExclusiveLeaseGuard concern
+ def lease_key
+ @lease_key ||= "container_repository:cleanup_tags:#{container_repository.id}"
+ end
+
+ # For ExclusiveLeaseGuard concern
+ def lease_timeout
+ LEASE_TIMEOUT
+ end
+
+ # For ExclusiveLeaseGuard concern
+ def lease_release?
+ # we don't allow to execute this worker
+ # more often than LEASE_TIMEOUT
+ # for given container repository
+ false
+ end
+end
diff --git a/app/workers/cluster_upgrade_app_worker.rb b/app/workers/cluster_upgrade_app_worker.rb
new file mode 100644
index 00000000000..d1a538859b4
--- /dev/null
+++ b/app/workers/cluster_upgrade_app_worker.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class ClusterUpgradeAppWorker
+ include ApplicationWorker
+ include ClusterQueue
+ include ClusterApplications
+
+ def perform(app_name, app_id)
+ find_application(app_name, app_id) do |app|
+ Clusters::Applications::UpgradeService.new(app).execute
+ end
+ end
+end
diff --git a/app/workers/delete_container_repository_worker.rb b/app/workers/delete_container_repository_worker.rb
index e8fe9d82797..42e66513ff1 100644
--- a/app/workers/delete_container_repository_worker.rb
+++ b/app/workers/delete_container_repository_worker.rb
@@ -4,6 +4,8 @@ class DeleteContainerRepositoryWorker
include ApplicationWorker
include ExclusiveLeaseGuard
+ queue_namespace :container_repository
+
LEASE_TIMEOUT = 1.hour
attr_reader :container_repository
diff --git a/app/workers/expire_build_artifacts_worker.rb b/app/workers/expire_build_artifacts_worker.rb
index dce812d1ae2..251e95c68d5 100644
--- a/app/workers/expire_build_artifacts_worker.rb
+++ b/app/workers/expire_build_artifacts_worker.rb
@@ -4,8 +4,20 @@ class ExpireBuildArtifactsWorker
include ApplicationWorker
include CronjobQueue
- # rubocop: disable CodeReuse/ActiveRecord
def perform
+ if Feature.enabled?(:ci_new_expire_job_artifacts_service, default_enabled: true)
+ perform_efficient_artifacts_removal
+ else
+ perform_legacy_artifacts_removal
+ end
+ end
+
+ def perform_efficient_artifacts_removal
+ Ci::DestroyExpiredJobArtifactsService.new.execute
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def perform_legacy_artifacts_removal
Rails.logger.info 'Scheduling removal of build artifacts'
build_ids = Ci::Build.with_expired_artifacts.pluck(:id)
diff --git a/app/workers/expire_pipeline_cache_worker.rb b/app/workers/expire_pipeline_cache_worker.rb
index c96e8a0379b..2c070d482a1 100644
--- a/app/workers/expire_pipeline_cache_worker.rb
+++ b/app/workers/expire_pipeline_cache_worker.rb
@@ -11,16 +11,9 @@ class ExpirePipelineCacheWorker
pipeline = Ci::Pipeline.find_by(id: pipeline_id)
return unless pipeline
- project = pipeline.project
store = Gitlab::EtagCaching::Store.new
- store.touch(project_pipelines_path(project))
- store.touch(project_pipeline_path(project, pipeline))
- store.touch(commit_pipelines_path(project, pipeline.commit)) unless pipeline.commit.nil?
- store.touch(new_merge_request_pipelines_path(project))
- each_pipelines_merge_request_path(project, pipeline) do |path|
- store.touch(path)
- end
+ update_etag_cache(pipeline, store)
Gitlab::Cache::Ci::ProjectPipelineStatus.update_for_pipeline(pipeline)
end
@@ -44,11 +37,30 @@ class ExpirePipelineCacheWorker
Gitlab::Routing.url_helpers.project_new_merge_request_path(project, format: :json)
end
- def each_pipelines_merge_request_path(project, pipeline)
+ def each_pipelines_merge_request_path(pipeline)
pipeline.all_merge_requests.each do |merge_request|
- path = Gitlab::Routing.url_helpers.pipelines_project_merge_request_path(project, merge_request, format: :json)
+ path = Gitlab::Routing.url_helpers.pipelines_project_merge_request_path(merge_request.target_project, merge_request, format: :json)
yield(path)
end
end
+
+ # Updates ETag caches of a pipeline.
+ #
+ # This logic resides in a separate method so that EE can more easily extend
+ # it.
+ #
+ # @param [Ci::Pipeline] pipeline
+ # @param [Gitlab::EtagCaching::Store] store
+ def update_etag_cache(pipeline, store)
+ project = pipeline.project
+
+ store.touch(project_pipelines_path(project))
+ store.touch(project_pipeline_path(project, pipeline))
+ store.touch(commit_pipelines_path(project, pipeline.commit)) unless pipeline.commit.nil?
+ store.touch(new_merge_request_pipelines_path(project))
+ each_pipelines_merge_request_path(pipeline) do |path|
+ store.touch(path)
+ end
+ end
end
diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb
index d3628b23189..b33e9b1f718 100644
--- a/app/workers/git_garbage_collect_worker.rb
+++ b/app/workers/git_garbage_collect_worker.rb
@@ -23,6 +23,7 @@ class GitGarbageCollectWorker
end
task = task.to_sym
+ project.link_pool_repository
gitaly_call(task, project.repository.raw_repository)
# Refresh the branch cache in case garbage collection caused a ref lookup to fail
diff --git a/app/workers/hashed_storage/base_worker.rb b/app/workers/hashed_storage/base_worker.rb
new file mode 100644
index 00000000000..816e0504db6
--- /dev/null
+++ b/app/workers/hashed_storage/base_worker.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module HashedStorage
+ class BaseWorker
+ include ExclusiveLeaseGuard
+
+ LEASE_TIMEOUT = 30.seconds.to_i
+ LEASE_KEY_SEGMENT = 'project_migrate_hashed_storage_worker'.freeze
+
+ protected
+
+ def lease_key
+ # we share the same lease key for both migration and rollback so they don't run simultaneously
+ "#{LEASE_KEY_SEGMENT}:#{project_id}"
+ end
+
+ def lease_timeout
+ LEASE_TIMEOUT
+ end
+ end
+end
diff --git a/app/workers/hashed_storage/migrator_worker.rb b/app/workers/hashed_storage/migrator_worker.rb
new file mode 100644
index 00000000000..49e347d4060
--- /dev/null
+++ b/app/workers/hashed_storage/migrator_worker.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module HashedStorage
+ class MigratorWorker
+ include ApplicationWorker
+
+ queue_namespace :hashed_storage
+
+ # @param [Integer] start initial ID of the batch
+ # @param [Integer] finish last ID of the batch
+ def perform(start, finish)
+ migrator = Gitlab::HashedStorage::Migrator.new
+ migrator.bulk_migrate(start: start, finish: finish)
+ end
+ end
+end
diff --git a/app/workers/hashed_storage/project_migrate_worker.rb b/app/workers/hashed_storage/project_migrate_worker.rb
new file mode 100644
index 00000000000..f00a459a097
--- /dev/null
+++ b/app/workers/hashed_storage/project_migrate_worker.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module HashedStorage
+ class ProjectMigrateWorker < BaseWorker
+ include ApplicationWorker
+
+ queue_namespace :hashed_storage
+
+ attr_reader :project_id
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def perform(project_id, old_disk_path = nil)
+ @project_id = project_id # we need to set this in order to create the lease_key
+
+ try_obtain_lease do
+ project = Project.without_deleted.find_by(id: project_id)
+ break unless project
+
+ old_disk_path ||= project.disk_path
+
+ ::Projects::HashedStorage::MigrationService.new(project, old_disk_path, logger: logger).execute
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/workers/hashed_storage/project_rollback_worker.rb b/app/workers/hashed_storage/project_rollback_worker.rb
new file mode 100644
index 00000000000..55e1d7ab23e
--- /dev/null
+++ b/app/workers/hashed_storage/project_rollback_worker.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module HashedStorage
+ class ProjectRollbackWorker < BaseWorker
+ include ApplicationWorker
+
+ queue_namespace :hashed_storage
+
+ attr_reader :project_id
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def perform(project_id, old_disk_path = nil)
+ @project_id = project_id # we need to set this in order to create the lease_key
+
+ try_obtain_lease do
+ project = Project.without_deleted.find_by(id: project_id)
+ break unless project
+
+ old_disk_path ||= project.disk_path
+
+ ::Projects::HashedStorage::RollbackService.new(project, old_disk_path, logger: logger).execute
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/workers/hashed_storage/rollbacker_worker.rb b/app/workers/hashed_storage/rollbacker_worker.rb
new file mode 100644
index 00000000000..a4da8443787
--- /dev/null
+++ b/app/workers/hashed_storage/rollbacker_worker.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module HashedStorage
+ class RollbackerWorker
+ include ApplicationWorker
+
+ queue_namespace :hashed_storage
+
+ # @param [Integer] start initial ID of the batch
+ # @param [Integer] finish last ID of the batch
+ def perform(start, finish)
+ migrator = Gitlab::HashedStorage::Migrator.new
+ migrator.bulk_rollback(start: start, finish: finish)
+ end
+ end
+end
diff --git a/app/workers/import_issues_csv_worker.rb b/app/workers/import_issues_csv_worker.rb
new file mode 100644
index 00000000000..d44fdfec8ae
--- /dev/null
+++ b/app/workers/import_issues_csv_worker.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class ImportIssuesCsvWorker
+ include ApplicationWorker
+
+ sidekiq_retries_exhausted do |job|
+ Upload.find(job['args'][2]).destroy
+ end
+
+ def perform(current_user_id, project_id, upload_id)
+ @user = User.find(current_user_id)
+ @project = Project.find(project_id)
+ @upload = Upload.find(upload_id)
+
+ importer = Issues::ImportCsvService.new(@user, @project, @upload.build_uploader)
+ importer.execute
+
+ @upload.destroy
+ end
+end
diff --git a/app/workers/mail_scheduler/notification_service_worker.rb b/app/workers/mail_scheduler/notification_service_worker.rb
index 4726e416182..421fbf04e28 100644
--- a/app/workers/mail_scheduler/notification_service_worker.rb
+++ b/app/workers/mail_scheduler/notification_service_worker.rb
@@ -8,14 +8,64 @@ module MailScheduler
include MailSchedulerQueue
def perform(meth, *args)
- deserialized_args = ActiveJob::Arguments.deserialize(args)
+ check_arguments!(args)
+ deserialized_args = ActiveJob::Arguments.deserialize(args)
notification_service.public_send(meth, *deserialized_args) # rubocop:disable GitlabSecurity/PublicSend
rescue ActiveJob::DeserializationError
+ # No-op.
+ # This exception gets raised when an argument
+ # is correct (deserializeable), but it still cannot be deserialized.
+ # This can happen when an object has been deleted after
+ # rails passes this job to sidekiq, but before
+ # sidekiq gets it for execution.
+ # In this case just do nothing.
end
def self.perform_async(*args)
- super(*ActiveJob::Arguments.serialize(args))
+ super(*Arguments.serialize(args))
+ end
+
+ private
+
+ # If an argument is in the ActiveJob::Arguments::TYPE_WHITELIST list,
+ # it means the argument cannot be deserialized.
+ # Which means there's something wrong with our code.
+ def check_arguments!(args)
+ args.each do |arg|
+ if arg.class.in?(ActiveJob::Arguments::TYPE_WHITELIST)
+ raise(ArgumentError, "Argument `#{arg}` cannot be deserialized because of its type")
+ end
+ end
+ end
+
+ # Permit ActionController::Parameters for serializable Hash
+ #
+ # Port of
+ # https://github.com/rails/rails/commit/945fdd76925c9f615bf016717c4c8db2b2955357#diff-fc90ec41ef75be8b2259526fe1a8b663
+ module Arguments
+ include ActiveJob::Arguments
+ extend self
+
+ private
+
+ def serialize_argument(argument)
+ case argument
+ when -> (arg) { arg.respond_to?(:permitted?) }
+ serialize_hash(argument.to_h).tap do |result|
+ result[WITH_INDIFFERENT_ACCESS_KEY] = serialize_argument(true)
+ end
+ else
+ super
+ end
+ end
+ end
+
+ # Make sure we remove this patch starting with Rails 6.0.
+ if Rails.version.start_with?('6.0')
+ raise <<~MSG
+ Please remove the patch `Arguments` module and use `ActiveJob::Arguments` again.
+ MSG
end
end
end
diff --git a/app/workers/namespaceless_project_destroy_worker.rb b/app/workers/namespaceless_project_destroy_worker.rb
index 2965f3b1150..f6e98746055 100644
--- a/app/workers/namespaceless_project_destroy_worker.rb
+++ b/app/workers/namespaceless_project_destroy_worker.rb
@@ -17,7 +17,7 @@ class NamespacelessProjectDestroyWorker
return
end
- return if project.namespace # Reject doing anything for projects that *do* have a namespace
+ return if project.namespace # Reject doing anything for projects that *do* have a namespace
project.team.truncate
diff --git a/app/workers/object_pool/join_worker.rb b/app/workers/object_pool/join_worker.rb
index 07676011b2a..9c5161fd55a 100644
--- a/app/workers/object_pool/join_worker.rb
+++ b/app/workers/object_pool/join_worker.rb
@@ -5,14 +5,13 @@ module ObjectPool
include ApplicationWorker
include ObjectPoolQueue
- def perform(pool_id, project_id)
- pool = PoolRepository.find_by_id(pool_id)
- return unless pool&.joinable?
-
+ # The use of pool id is deprecated. Keeping the argument allows old jobs to
+ # still be performed.
+ def perform(_pool_id, project_id)
project = Project.find_by_id(project_id)
- return unless project
+ return unless project&.pool_repository&.joinable?
- pool.link_repository(project.repository)
+ project.link_pool_repository
Projects::HousekeepingService.new(project).execute
end
diff --git a/app/workers/pipeline_metrics_worker.rb b/app/workers/pipeline_metrics_worker.rb
index c2fbfd2b3a5..0ddad43b8d5 100644
--- a/app/workers/pipeline_metrics_worker.rb
+++ b/app/workers/pipeline_metrics_worker.rb
@@ -30,6 +30,6 @@ class PipelineMetricsWorker
# rubocop: enable CodeReuse/ActiveRecord
def merge_requests(pipeline)
- pipeline.merge_requests.map(&:id)
+ pipeline.merge_requests_as_head_pipeline.map(&:id)
end
end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 72a1733a2a8..bbd4ab159e4 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -3,7 +3,7 @@
class PostReceive
include ApplicationWorker
- def perform(gl_repository, identifier, changes)
+ def perform(gl_repository, identifier, changes, push_options = [])
project, is_wiki = Gitlab::GlRepository.parse(gl_repository)
if project.nil?
@@ -15,7 +15,7 @@ class PostReceive
# Use Sidekiq.logger so arguments can be correlated with execution
# time and thread ID's.
Sidekiq.logger.info "changes: #{changes.inspect}" if ENV['SIDEKIQ_LOG_ARGUMENTS']
- post_received = Gitlab::GitPostReceive.new(project, identifier, changes)
+ post_received = Gitlab::GitPostReceive.new(project, identifier, changes, push_options)
if is_wiki
process_wiki_changes(post_received)
@@ -38,9 +38,21 @@ class PostReceive
post_received.changes_refs do |oldrev, newrev, ref|
if Gitlab::Git.tag_ref?(ref)
- GitTagPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
+ GitTagPushService.new(
+ post_received.project,
+ @user,
+ oldrev: oldrev,
+ newrev: newrev,
+ ref: ref,
+ push_options: post_received.push_options).execute
elsif Gitlab::Git.branch_ref?(ref)
- GitPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
+ GitPushService.new(
+ post_received.project,
+ @user,
+ oldrev: oldrev,
+ newrev: newrev,
+ ref: ref,
+ push_options: post_received.push_options).execute
end
changes << Gitlab::DataBuilder::Repository.single_change(oldrev, newrev, ref)
diff --git a/app/workers/project_daily_statistics_worker.rb b/app/workers/project_daily_statistics_worker.rb
new file mode 100644
index 00000000000..101f5c28459
--- /dev/null
+++ b/app/workers/project_daily_statistics_worker.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class ProjectDailyStatisticsWorker
+ include ApplicationWorker
+
+ def perform(project_id)
+ project = Project.find_by_id(project_id)
+
+ return unless project&.repository&.exists?
+
+ Projects::FetchStatisticsIncrementService.new(project).execute
+ end
+end
diff --git a/app/workers/project_migrate_hashed_storage_worker.rb b/app/workers/project_migrate_hashed_storage_worker.rb
deleted file mode 100644
index 4c6339f7701..00000000000
--- a/app/workers/project_migrate_hashed_storage_worker.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-class ProjectMigrateHashedStorageWorker
- include ApplicationWorker
-
- LEASE_TIMEOUT = 30.seconds.to_i
-
- # rubocop: disable CodeReuse/ActiveRecord
- def perform(project_id, old_disk_path = nil)
- project = Project.find_by(id: project_id)
- return if project.nil? || project.pending_delete?
-
- uuid = lease_for(project_id).try_obtain
- if uuid
- ::Projects::HashedStorageMigrationService.new(project, old_disk_path || project.full_path, logger: logger).execute
- else
- false
- end
- rescue => ex
- cancel_lease_for(project_id, uuid) if uuid
- raise ex
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def lease_for(project_id)
- Gitlab::ExclusiveLease.new(lease_key(project_id), timeout: LEASE_TIMEOUT)
- end
-
- private
-
- def lease_key(project_id)
- "project_migrate_hashed_storage_worker:#{project_id}"
- end
-
- def cancel_lease_for(project_id, uuid)
- Gitlab::ExclusiveLease.cancel(lease_key(project_id), uuid)
- end
-end
diff --git a/app/workers/reactive_caching_worker.rb b/app/workers/reactive_caching_worker.rb
index 96ff8cd6222..9ec8bcca4f3 100644
--- a/app/workers/reactive_caching_worker.rb
+++ b/app/workers/reactive_caching_worker.rb
@@ -6,13 +6,13 @@ class ReactiveCachingWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(class_name, id, *args)
klass = begin
- Kernel.const_get(class_name)
+ class_name.constantize
rescue NameError
nil
end
return unless klass
- klass.find_by(id: id).try(:exclusively_update_reactive_cache!, *args)
+ klass.find_by(klass.primary_key => id).try(:exclusively_update_reactive_cache!, *args)
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/remote_mirror_notification_worker.rb b/app/workers/remote_mirror_notification_worker.rb
index 70c2e857d09..5bafe8e2046 100644
--- a/app/workers/remote_mirror_notification_worker.rb
+++ b/app/workers/remote_mirror_notification_worker.rb
@@ -9,7 +9,10 @@ class RemoteMirrorNotificationWorker
# We check again if there's an error because a newer run since this job was
# fired could've completed successfully.
return unless remote_mirror && remote_mirror.last_error.present?
+ return if remote_mirror.error_notification_sent?
NotificationService.new.remote_mirror_update_failed(remote_mirror)
+
+ remote_mirror.after_sent_notification
end
end
diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb
index 7eae07d3f6b..a9b88a133be 100644
--- a/app/workers/repository_fork_worker.rb
+++ b/app/workers/repository_fork_worker.rb
@@ -15,19 +15,19 @@ class RepositoryForkWorker
return target_project.import_state.mark_as_failed(_('Source project cannot be found.'))
end
- fork_repository(target_project, source_project.repository_storage, source_project.disk_path)
+ fork_repository(target_project, source_project)
end
private
- def fork_repository(target_project, source_repository_storage_name, source_disk_path)
+ def fork_repository(target_project, source_project)
return unless start_fork(target_project)
Gitlab::Metrics.add_event(:fork_repository)
- result = gitlab_shell.fork_repository(source_repository_storage_name, source_disk_path,
- target_project.repository_storage, target_project.disk_path)
- raise "Unable to fork project #{target_project.id} for repository #{source_disk_path} -> #{target_project.disk_path}" unless result
+ result = gitlab_shell.fork_repository(source_project, target_project)
+
+ raise "Unable to fork project #{target_project.id} for repository #{source_project.disk_path} -> #{target_project.disk_path}" unless result
target_project.after_import
end
diff --git a/app/workers/storage_migrator_worker.rb b/app/workers/storage_migrator_worker.rb
deleted file mode 100644
index fa76fbac55c..00000000000
--- a/app/workers/storage_migrator_worker.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class StorageMigratorWorker
- include ApplicationWorker
-
- def perform(start, finish)
- migrator = Gitlab::HashedStorage::Migrator.new
- migrator.bulk_migrate(start, finish)
- end
-end
diff --git a/app/workers/update_head_pipeline_for_merge_request_worker.rb b/app/workers/update_head_pipeline_for_merge_request_worker.rb
index e8494ffa002..4ec2b9d8fbe 100644
--- a/app/workers/update_head_pipeline_for_merge_request_worker.rb
+++ b/app/workers/update_head_pipeline_for_merge_request_worker.rb
@@ -7,25 +7,8 @@ class UpdateHeadPipelineForMergeRequestWorker
queue_namespace :pipeline_processing
def perform(merge_request_id)
- merge_request = MergeRequest.find(merge_request_id)
-
- sha = merge_request.diff_head_sha
- pipeline = merge_request.all_pipelines(shas: sha).first
-
- return unless pipeline && pipeline.latest?
-
- if merge_request.diff_head_sha != pipeline.sha
- log_error_message_for(merge_request)
-
- return
+ MergeRequest.find_by_id(merge_request_id).try do |merge_request|
+ merge_request.update_head_pipeline
end
-
- merge_request.update_attribute(:head_pipeline_id, pipeline.id)
- end
-
- def log_error_message_for(merge_request)
- Rails.logger.error(
- "Outdated head pipeline for active merge request: id=#{merge_request.id}, source_branch=#{merge_request.source_branch}, diff_head_sha=#{merge_request.diff_head_sha}"
- )
end
end
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 00000000000..78d14095b0b
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,51 @@
+/* eslint-disable import/no-commonjs, filenames/match-regex */
+
+const BABEL_ENV = process.env.BABEL_ENV || process.env.NODE_ENV || null;
+
+const presets = [
+ [
+ '@babel/preset-env',
+ {
+ modules: false,
+ targets: {
+ ie: '11',
+ },
+ },
+ ],
+];
+
+// include stage 3 proposals
+const plugins = [
+ '@babel/plugin-syntax-dynamic-import',
+ '@babel/plugin-syntax-import-meta',
+ '@babel/plugin-proposal-class-properties',
+ '@babel/plugin-proposal-json-strings',
+ '@babel/plugin-proposal-private-methods',
+];
+
+// add code coverage tooling if necessary
+if (BABEL_ENV === 'coverage') {
+ plugins.push([
+ 'babel-plugin-istanbul',
+ {
+ exclude: ['spec/javascripts/**/*', 'app/assets/javascripts/locale/**/app.js'],
+ },
+ ]);
+}
+
+// add rewire support when running tests
+if (BABEL_ENV === 'karma' || BABEL_ENV === 'coverage') {
+ plugins.push('babel-plugin-rewire');
+}
+
+// Jest is running in node environment
+if (BABEL_ENV === 'jest') {
+ plugins.push('@babel/plugin-transform-modules-commonjs');
+ /*
+ without the following, babel-plugin-istanbul throws an error:
+ https://gitlab.com/gitlab-org/gitlab-ce/issues/58390
+ */
+ plugins.push('babel-plugin-dynamic-import-node');
+}
+
+module.exports = { presets, plugins };
diff --git a/bin/background_jobs b/bin/background_jobs
index f28e2f722dc..9d12422b81a 100755
--- a/bin/background_jobs
+++ b/bin/background_jobs
@@ -38,7 +38,14 @@ start_no_deamonize()
start_sidekiq()
{
- exec bundle exec sidekiq -C "${sidekiq_config}" -e $RAILS_ENV -P $sidekiq_pidfile "$@"
+ cmd="exec"
+ chpst=$(which chpst)
+
+ if [ -n "$chpst" ]; then
+ cmd="${cmd} ${chpst} -P"
+ fi
+
+ ${cmd} bundle exec sidekiq -C "${sidekiq_config}" -e $RAILS_ENV -P $sidekiq_pidfile "$@"
}
load_ok()
diff --git a/bin/changelog b/bin/changelog
index 758c036161e..328d9495b96 100755
--- a/bin/changelog
+++ b/bin/changelog
@@ -148,7 +148,7 @@ class ChangelogEntry
def execute
assert_feature_branch!
- assert_title!
+ assert_title! unless editor
assert_new_file!
# Read type from $stdin unless is already set
@@ -162,6 +162,10 @@ class ChangelogEntry
write
amend_commit if options.amend
end
+
+ if editor
+ system("#{editor} '#{file_path}'")
+ end
end
private
@@ -180,6 +184,10 @@ class ChangelogEntry
File.write(file_path, contents)
end
+ def editor
+ ENV['EDITOR']
+ end
+
def amend_commit
fail_with "git add failed" unless system(*%W[git add #{file_path}])
diff --git a/bin/secpick b/bin/secpick
index 11acdd82226..d01304285b6 100755
--- a/bin/secpick
+++ b/bin/secpick
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+
# frozen_string_literal: false
require 'active_support/core_ext/object/to_query'
@@ -7,69 +8,130 @@ require 'open3'
require 'rainbow/refinement'
using Rainbow
-BRANCH_PREFIX = 'security'.freeze
-REMOTE = 'dev'.freeze
-NEW_MR_URL = 'https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/new'.freeze
-
-options = { version: nil, branch: nil, sha: nil }
-
-parser = OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} [options]"
- opts.on('-v', '--version 10.0', 'Version') do |version|
- options[:version] = version&.tr('.', '-')
- end
-
- opts.on('-b', '--branch security-fix-branch', 'Original branch name (optional, defaults to current)') do |branch|
- options[:branch] = branch
- end
-
- opts.on('-s', '--sha abcd', 'SHA to cherry pick') do |sha|
- options[:sha] = sha
- end
-
- opts.on('-h', '--help', 'Displays Help') do
- puts opts
-
- exit
+module Secpick
+ BRANCH_PREFIX = 'security'.freeze
+ STABLE_SUFFIX = 'stable'.freeze
+ DEFAULT_REMOTE = 'dev'.freeze
+ NEW_MR_URL = 'https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/new'.freeze
+
+ class SecurityFix
+ def initialize
+ @options = self.class.options
+ end
+
+ def ee?
+ File.exist?('./CHANGELOG-EE.md')
+ end
+
+ def dry_run?
+ @options[:try] == true
+ end
+
+ def original_branch
+ @options[:branch].strip
+ end
+
+ def source_branch
+ branch = "#{original_branch}-#{@options[:version]}"
+ branch.prepend("#{BRANCH_PREFIX}-") unless branch.start_with?("#{BRANCH_PREFIX}-")
+ branch.freeze
+ end
+
+ def stable_branch
+ "#{@options[:version]}-#{STABLE_SUFFIX}".tap do |name|
+ name << "-ee" if ee?
+ end.freeze
+ end
+
+ def git_commands
+ ["git fetch #{@options[:remote]} #{stable_branch}",
+ "git checkout -B #{source_branch} #{@options[:remote]}/#{stable_branch}",
+ "git cherry-pick #{@options[:sha]}",
+ "git push #{@options[:remote]} #{source_branch}",
+ "git checkout #{original_branch}"]
+ end
+
+ def gitlab_params
+ {
+ issuable_template: 'Security Release',
+ merge_request: {
+ source_branch: source_branch,
+ target_branch: stable_branch
+ }
+ }
+ end
+
+ def new_mr_url
+ if ee?
+ NEW_MR_URL.sub('gitlabhq', 'gitlab-ee')
+ else
+ NEW_MR_URL
+ end
+ end
+
+ def create!
+ if dry_run?
+ puts git_commands.join("\n").green
+ puts "\nMerge request params: ".blue
+ pp gitlab_params
+ else
+ cmd = git_commands.join(' && ')
+ stdin, stdout, stderr, wait_thr = Open3.popen3(cmd)
+
+ puts stdout.read&.green
+ puts stderr.read&.red
+
+ if wait_thr.value.success?
+ puts "#{new_mr_url}?#{gitlab_params.to_query}".blue
+ end
+
+ stdin.close
+ stdout.close
+ stderr.close
+ end
+ end
+
+ def self.options
+ { version: nil, branch: nil, sha: nil }.tap do |options|
+ parser = OptionParser.new do |opts|
+ opts.banner = "Usage: #{$0} [options]"
+ opts.on('-v', '--version 10.0', 'Version') do |version|
+ options[:version] = version&.tr('.', '-')
+ end
+
+ opts.on('-b', '--branch security-fix-branch', 'Original branch name (optional, defaults to current)') do |branch|
+ options[:branch] = branch
+ end
+
+ opts.on('-s', '--sha abcd', 'SHA to cherry pick') do |sha|
+ options[:sha] = sha
+ end
+
+ opts.on('-r', '--remote abcd', 'Git remote name of dev.gitlab.org (optional, defaults to `dev`)') do |remote|
+ options[:remote] = remote
+ end
+
+ opts.on('-d', '--dry-run', 'Only show Git commands, without calling them') do |remote|
+ options[:try] = true
+ end
+
+ opts.on('-h', '--help', 'Displays Help') do
+ puts opts
+
+ exit
+ end
+ end
+
+ parser.parse!
+
+ options[:branch] ||= `git rev-parse --abbrev-ref HEAD`
+ options[:remote] ||= DEFAULT_REMOTE
+
+ abort("Missing options. Use #{$0} --help to see the list of options available".red) if options.values.include?(nil)
+ abort("Wrong version format #{options[:version].bold}".red) unless options[:version] =~ /\A\d*\-\d*\Z/
+ end
+ end
end
end
-parser.parse!
-
-options[:branch] ||= `git rev-parse --abbrev-ref HEAD`
-
-abort("Missing options. Use #{$0} --help to see the list of options available".red) if options.values.include?(nil)
-abort("Wrong version format #{options[:version].bold}".red) unless options[:version] =~ /\A\d*\-\d*\Z/
-
-ee = File.exist?('./CHANGELOG-EE.md')
-original_branch = options[:branch].strip
-branch = "#{original_branch}-#{options[:version]}"
-branch.prepend("#{BRANCH_PREFIX}-") unless branch.start_with?("#{BRANCH_PREFIX}-")
-branch = branch.freeze
-stable_branch = "#{BRANCH_PREFIX}-#{options[:version]}".tap do |name|
- name << "-ee" if ee
-end.freeze
-
-command = "git fetch #{REMOTE} #{stable_branch} && git checkout #{stable_branch} && git pull #{REMOTE} #{stable_branch} && git checkout -B #{branch} && git cherry-pick #{options[:sha]} && git push #{REMOTE} #{branch} && git checkout #{original_branch}"
-
-stdin, stdout, stderr, wait_thr = Open3.popen3(command)
-
-puts stdout.read&.green
-puts stderr.read&.red
-
-if wait_thr.value.success?
- params = {
- merge_request: {
- source_branch: branch,
- target_branch: stable_branch,
- title: "WIP: [#{options[:version].tr('-', '.')}] ",
- description: '/label ~security'
- }
- }
-
- puts "#{NEW_MR_URL}?#{params.to_query}".blue
-end
-
-stdin.close
-stdout.close
-stderr.close
+Secpick::SecurityFix.new.create!
diff --git a/changelogs/README.md b/changelogs/README.md
new file mode 100644
index 00000000000..c4113ccb863
--- /dev/null
+++ b/changelogs/README.md
@@ -0,0 +1,10 @@
+# Generating changelog entries
+
+To generate and validate your changelog entries:
+
+1. Run `bin/changelog` to generate.
+1. Run `scripts/lint-changelog-yaml` to validate.
+
+See [development/changelog] documentation for detailed usage.
+
+[development/changelog]: https://docs.gitlab.com/ee/development/changelog.html
diff --git a/changelogs/unreleased/10095-job-getters.yml b/changelogs/unreleased/10095-job-getters.yml
new file mode 100644
index 00000000000..f12fc8b26ec
--- /dev/null
+++ b/changelogs/unreleased/10095-job-getters.yml
@@ -0,0 +1,5 @@
+---
+title: Removes EE differences for jobs/getters.js
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/10097-number-utils.yml b/changelogs/unreleased/10097-number-utils.yml
new file mode 100644
index 00000000000..417008f6539
--- /dev/null
+++ b/changelogs/unreleased/10097-number-utils.yml
@@ -0,0 +1,5 @@
+---
+title: Moves EE util into the CE file
+merge_request: 25680
+author:
+type: other
diff --git a/changelogs/unreleased/13784-simple-masking-of-protected-variables-in-logs.yml b/changelogs/unreleased/13784-simple-masking-of-protected-variables-in-logs.yml
new file mode 100644
index 00000000000..5c3b6833235
--- /dev/null
+++ b/changelogs/unreleased/13784-simple-masking-of-protected-variables-in-logs.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for masking CI variables.
+merge_request: 25293
+author:
+type: added
diff --git a/changelogs/unreleased/20084-update-the-spinner-component.yml b/changelogs/unreleased/20084-update-the-spinner-component.yml
new file mode 100644
index 00000000000..c93648e4f54
--- /dev/null
+++ b/changelogs/unreleased/20084-update-the-spinner-component.yml
@@ -0,0 +1,5 @@
+---
+title: Add a spinner icon which is rendered using pure css
+merge_request: 25186
+author:
+type: changed
diff --git a/changelogs/unreleased/23367-clarify-docs-allow-failure.yml b/changelogs/unreleased/23367-clarify-docs-allow-failure.yml
deleted file mode 100644
index 221d9e83ffb..00000000000
--- a/changelogs/unreleased/23367-clarify-docs-allow-failure.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Clarifies docs about CI `allow_failure`
-merge_request: 23367
-author: C.J. Jameson
-type: other
diff --git a/changelogs/unreleased/24642-activity_service_optimization.yml b/changelogs/unreleased/24642-activity_service_optimization.yml
new file mode 100644
index 00000000000..bdfa769959e
--- /dev/null
+++ b/changelogs/unreleased/24642-activity_service_optimization.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize Redis usage in User::ActivityService
+merge_request: 25005
+author:
+type: performance
diff --git a/changelogs/unreleased/27333-re-deploy-rollback-button-should-ask-for-confirmation-before-executing.yml b/changelogs/unreleased/27333-re-deploy-rollback-button-should-ask-for-confirmation-before-executing.yml
new file mode 100644
index 00000000000..8c5f05c3575
--- /dev/null
+++ b/changelogs/unreleased/27333-re-deploy-rollback-button-should-ask-for-confirmation-before-executing.yml
@@ -0,0 +1,5 @@
+---
+title: Add Confirmation Modal to Rollback on Environment
+merge_request: 25110
+author:
+type: added
diff --git a/changelogs/unreleased/2802-security-add-public-internal-groups-as-members-to-your-project-idor.yml b/changelogs/unreleased/2802-security-add-public-internal-groups-as-members-to-your-project-idor.yml
new file mode 100644
index 00000000000..27ad151cd06
--- /dev/null
+++ b/changelogs/unreleased/2802-security-add-public-internal-groups-as-members-to-your-project-idor.yml
@@ -0,0 +1,6 @@
+---
+title: Remove the possibility to share a project with a group that a user is not a member
+ of
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/32714-copying-comment-with-ordered-list-includes-extraneous-newlines.yml b/changelogs/unreleased/32714-copying-comment-with-ordered-list-includes-extraneous-newlines.yml
new file mode 100644
index 00000000000..d0bb4225ce4
--- /dev/null
+++ b/changelogs/unreleased/32714-copying-comment-with-ordered-list-includes-extraneous-newlines.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed "Copying comment with ordered list includes extraneous newlines"
+merge_request: 25695
+author:
+type: fixed
diff --git a/changelogs/unreleased/34555-empty-state-for-starred-projects.yml b/changelogs/unreleased/34555-empty-state-for-starred-projects.yml
new file mode 100644
index 00000000000..926d3a2eecf
--- /dev/null
+++ b/changelogs/unreleased/34555-empty-state-for-starred-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Improve empty state for starred projects
+merge_request: 25138
+author:
+type: changed
diff --git a/changelogs/unreleased/34758-list-ancestor-clusters.yml b/changelogs/unreleased/34758-list-ancestor-clusters.yml
deleted file mode 100644
index 8fdba7ba90a..00000000000
--- a/changelogs/unreleased/34758-list-ancestor-clusters.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show clusters of ancestors in cluster list page
-merge_request: 22996
-author:
-type: changed
diff --git a/changelogs/unreleased/35638-move-language-setting-to-preferences.yml b/changelogs/unreleased/35638-move-language-setting-to-preferences.yml
new file mode 100644
index 00000000000..d8658218676
--- /dev/null
+++ b/changelogs/unreleased/35638-move-language-setting-to-preferences.yml
@@ -0,0 +1,5 @@
+---
+title: Move language setting to preferences
+merge_request: 25427
+author: Fabian Schneider @fabsrc
+type: changed
diff --git a/changelogs/unreleased/37673-minor-issue-with-apostrophe-single-quote-when-clicking-assign-to-me.yml b/changelogs/unreleased/37673-minor-issue-with-apostrophe-single-quote-when-clicking-assign-to-me.yml
new file mode 100644
index 00000000000..a470f917d53
--- /dev/null
+++ b/changelogs/unreleased/37673-minor-issue-with-apostrophe-single-quote-when-clicking-assign-to-me.yml
@@ -0,0 +1,5 @@
+---
+title: Fix username escaping when using assign to me for issues
+merge_request: 24673
+author:
+type: fixed
diff --git a/changelogs/unreleased/39010-add-left-margin-to-1st-time-contributor-badge.yml b/changelogs/unreleased/39010-add-left-margin-to-1st-time-contributor-badge.yml
new file mode 100644
index 00000000000..758b97deb3b
--- /dev/null
+++ b/changelogs/unreleased/39010-add-left-margin-to-1st-time-contributor-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Add left margin to 1st time contributor badge
+merge_request: 25216
+author: Gokhan Apaydin
+type: fixed
diff --git a/changelogs/unreleased/39676-wiki-api-problems-on-update-parameters-and-500-error.yml b/changelogs/unreleased/39676-wiki-api-problems-on-update-parameters-and-500-error.yml
new file mode 100644
index 00000000000..1af49fb6a2c
--- /dev/null
+++ b/changelogs/unreleased/39676-wiki-api-problems-on-update-parameters-and-500-error.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Require only one parameter when updating a wiki'
+merge_request: 25191
+author: Robert Schilling
+type: fixed
diff --git a/changelogs/unreleased/40270-remove-gitlab-upgrader-completely.yml b/changelogs/unreleased/40270-remove-gitlab-upgrader-completely.yml
deleted file mode 100644
index 9ea2157bfb7..00000000000
--- a/changelogs/unreleased/40270-remove-gitlab-upgrader-completely.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes all instances of deprecated Gitlab Upgrader calls
-merge_request: 23603
-author: '@jwolen'
-type: removed
diff --git a/changelogs/unreleased/40396-sidekiq-in-process-group.yml b/changelogs/unreleased/40396-sidekiq-in-process-group.yml
new file mode 100644
index 00000000000..e41557e20d0
--- /dev/null
+++ b/changelogs/unreleased/40396-sidekiq-in-process-group.yml
@@ -0,0 +1,5 @@
+---
+title: 'sidekiq: terminate child processes at shutdown'
+merge_request: 25669
+author:
+type: added
diff --git a/changelogs/unreleased/40396-use-pgroups-for-background-jobs.yml b/changelogs/unreleased/40396-use-pgroups-for-background-jobs.yml
new file mode 100644
index 00000000000..578c780e1a1
--- /dev/null
+++ b/changelogs/unreleased/40396-use-pgroups-for-background-jobs.yml
@@ -0,0 +1,5 @@
+---
+title: 'If chpst is available, make fron-source installations run sidekiq as a process group leader'
+merge_request: 25654
+author:
+type: other
diff --git a/changelogs/unreleased/40795-set-project-name-on-fork-api.yml b/changelogs/unreleased/40795-set-project-name-on-fork-api.yml
new file mode 100644
index 00000000000..742184bbe1e
--- /dev/null
+++ b/changelogs/unreleased/40795-set-project-name-on-fork-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to set path and name for project on fork using API
+merge_request: 25363
+author:
+type: added
diff --git a/changelogs/unreleased/41766-vue-component.yml b/changelogs/unreleased/41766-vue-component.yml
deleted file mode 100644
index 12343c8ce84..00000000000
--- a/changelogs/unreleased/41766-vue-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Creates component for release block
-merge_request: 23697
-author:
-type: added
diff --git a/changelogs/unreleased/41766-vuex-store.yml b/changelogs/unreleased/41766-vuex-store.yml
deleted file mode 100644
index f20fc736a6f..00000000000
--- a/changelogs/unreleased/41766-vuex-store.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Creates frontend app for releases
-merge_request: 23796
-author:
-type: added
diff --git a/changelogs/unreleased/41888-access-personal-snippets-by-api.yml b/changelogs/unreleased/41888-access-personal-snippets-by-api.yml
new file mode 100644
index 00000000000..3561a01ec5f
--- /dev/null
+++ b/changelogs/unreleased/41888-access-personal-snippets-by-api.yml
@@ -0,0 +1,5 @@
+---
+title: Allow all snippets to be accessed by API
+merge_request: 25772
+author:
+type: added
diff --git a/changelogs/unreleased/42086-project-fetch-statistics-api-http-only.yml b/changelogs/unreleased/42086-project-fetch-statistics-api-http-only.yml
new file mode 100644
index 00000000000..f2c4f88b746
--- /dev/null
+++ b/changelogs/unreleased/42086-project-fetch-statistics-api-http-only.yml
@@ -0,0 +1,5 @@
+---
+title: Add project fetch statistics
+merge_request: 23596
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/42125-extend-override-check-to-also-check-arity.yml b/changelogs/unreleased/42125-extend-override-check-to-also-check-arity.yml
deleted file mode 100644
index 9892466ca50..00000000000
--- a/changelogs/unreleased/42125-extend-override-check-to-also-check-arity.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Extend override check to also check arity
-merge_request: 23498
-author: Jacopo Beschi @jacopo-beschi
-type: added
diff --git a/changelogs/unreleased/44740-api-to-verify-a-given-user-has-right-to-merge-a-given-mergerequest.yml b/changelogs/unreleased/44740-api-to-verify-a-given-user-has-right-to-merge-a-given-mergerequest.yml
new file mode 100644
index 00000000000..1c739130fcc
--- /dev/null
+++ b/changelogs/unreleased/44740-api-to-verify-a-given-user-has-right-to-merge-a-given-mergerequest.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Expose if the current user can merge a MR'
+merge_request: 25207
+author: Robert Schilling
+type: added
diff --git a/changelogs/unreleased/44984-use-serializer-for-issuable-sidebar.yml b/changelogs/unreleased/44984-use-serializer-for-issuable-sidebar.yml
deleted file mode 100644
index ba9edc8740d..00000000000
--- a/changelogs/unreleased/44984-use-serializer-for-issuable-sidebar.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Refactor issuable sidebar to use serializer
-merge_request: 23379
-author:
-type: other
diff --git a/changelogs/unreleased/45035-force-push-api.yml b/changelogs/unreleased/45035-force-push-api.yml
new file mode 100644
index 00000000000..05f5a36ac38
--- /dev/null
+++ b/changelogs/unreleased/45035-force-push-api.yml
@@ -0,0 +1,5 @@
+---
+title: Accept force option to overwrite branch on commit via API
+merge_request: 25286
+author:
+type: added
diff --git a/changelogs/unreleased/45305-ci-status-icon-mismatch-on-merge-requests-page-and-the-mr-itself.yml b/changelogs/unreleased/45305-ci-status-icon-mismatch-on-merge-requests-page-and-the-mr-itself.yml
new file mode 100644
index 00000000000..64ab76a2b05
--- /dev/null
+++ b/changelogs/unreleased/45305-ci-status-icon-mismatch-on-merge-requests-page-and-the-mr-itself.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pipeline status icon mismatch
+merge_request: 25407
+author:
+type: fixed
diff --git a/changelogs/unreleased/46750-ci-empty-environment-is-created-even-when-a-job-isn-t-run-when-manual.yml b/changelogs/unreleased/46750-ci-empty-environment-is-created-even-when-a-job-isn-t-run-when-manual.yml
new file mode 100644
index 00000000000..d052a28ab51
--- /dev/null
+++ b/changelogs/unreleased/46750-ci-empty-environment-is-created-even-when-a-job-isn-t-run-when-manual.yml
@@ -0,0 +1,5 @@
+---
+title: Sort Environments by Last Updated
+merge_request: 25260
+author:
+type: added
diff --git a/changelogs/unreleased/47052-merge-button-does-not-appear-after-rebase-ing.yml b/changelogs/unreleased/47052-merge-button-does-not-appear-after-rebase-ing.yml
deleted file mode 100644
index fd1e4605f2d..00000000000
--- a/changelogs/unreleased/47052-merge-button-does-not-appear-after-rebase-ing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow merge after rebase without page refresh on FF repositories
-merge_request: 23572
-author:
-type: fixed
diff --git a/changelogs/unreleased/47150-update-sshkey.yml b/changelogs/unreleased/47150-update-sshkey.yml
new file mode 100644
index 00000000000..342bdb1e2bc
--- /dev/null
+++ b/changelogs/unreleased/47150-update-sshkey.yml
@@ -0,0 +1,5 @@
+---
+title: Fix validation of certain ed25519 keys
+merge_request: 25115
+author: Merlijn B. W. Wajer
+type: fixed
diff --git a/changelogs/unreleased/48798-keybinding-mr-diff.yml b/changelogs/unreleased/48798-keybinding-mr-diff.yml
new file mode 100644
index 00000000000..3ef3f07f27c
--- /dev/null
+++ b/changelogs/unreleased/48798-keybinding-mr-diff.yml
@@ -0,0 +1,5 @@
+---
+title: Next/previous navigation between files in MR review
+merge_request: 25355
+author:
+type: added \ No newline at end of file
diff --git a/changelogs/unreleased/49397-move-files-in-ide.yml b/changelogs/unreleased/49397-move-files-in-ide.yml
new file mode 100644
index 00000000000..488091d383c
--- /dev/null
+++ b/changelogs/unreleased/49397-move-files-in-ide.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Move files in the Web IDE
+merge_request: 25431
+author:
+type: added
diff --git a/changelogs/unreleased/49502-gpg-signature-api-endpoint.yml b/changelogs/unreleased/49502-gpg-signature-api-endpoint.yml
new file mode 100644
index 00000000000..8393cb9d282
--- /dev/null
+++ b/changelogs/unreleased/49502-gpg-signature-api-endpoint.yml
@@ -0,0 +1,5 @@
+---
+title: Add API endpoint to get a commit's GPG signature
+merge_request: 25032
+author:
+type: added
diff --git a/changelogs/unreleased/49663-branch-to-mr-connection.yml b/changelogs/unreleased/49663-branch-to-mr-connection.yml
new file mode 100644
index 00000000000..d92ed6fd3bf
--- /dev/null
+++ b/changelogs/unreleased/49663-branch-to-mr-connection.yml
@@ -0,0 +1,5 @@
+---
+title: Link to most recent MR from a branch
+merge_request: 25689
+author:
+type: added
diff --git a/changelogs/unreleased/50006-expose-textcolor-from-public-labels-api.yml b/changelogs/unreleased/50006-expose-textcolor-from-public-labels-api.yml
new file mode 100644
index 00000000000..3c8b58f3001
--- /dev/null
+++ b/changelogs/unreleased/50006-expose-textcolor-from-public-labels-api.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Expose text_color for project and group labels'
+merge_request: 25172
+author: Robert Schilling
+type: added
diff --git a/changelogs/unreleased/50313-use-kaniko-to-build-containers-in-autodevops.yml b/changelogs/unreleased/50313-use-kaniko-to-build-containers-in-autodevops.yml
new file mode 100644
index 00000000000..0188df7fce7
--- /dev/null
+++ b/changelogs/unreleased/50313-use-kaniko-to-build-containers-in-autodevops.yml
@@ -0,0 +1,5 @@
+---
+title: Use auto-build-image for build job in Auto-DevOps.gitlab-ci.yml
+merge_request: 24279
+author:
+type: changed
diff --git a/changelogs/unreleased/50433-make-emoji-picker-bigger.yml b/changelogs/unreleased/50433-make-emoji-picker-bigger.yml
new file mode 100644
index 00000000000..8fcf41df09d
--- /dev/null
+++ b/changelogs/unreleased/50433-make-emoji-picker-bigger.yml
@@ -0,0 +1,5 @@
+---
+title: Make emoji picker bigger
+merge_request: 25187
+author: Jacopo Beschi @jacopo-beschi
+type: changed
diff --git a/changelogs/unreleased/51485-new-issue-labels-note.yml b/changelogs/unreleased/51485-new-issue-labels-note.yml
deleted file mode 100644
index a312d379ce2..00000000000
--- a/changelogs/unreleased/51485-new-issue-labels-note.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Create system notes on issue / MR creation when labels, milestone, or due date is set
-merge_request: 23859
-author:
-type: added
diff --git a/changelogs/unreleased/51606-expanding-a-diff-while-having-an-open-comment-form-will-always-scroll-down-to-the-comment.yml b/changelogs/unreleased/51606-expanding-a-diff-while-having-an-open-comment-form-will-always-scroll-down-to-the-comment.yml
deleted file mode 100644
index a845234b42f..00000000000
--- a/changelogs/unreleased/51606-expanding-a-diff-while-having-an-open-comment-form-will-always-scroll-down-to-the-comment.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Stop autofocusing on diff comment after initial mount
-merge_request: 23849
-author:
-type: fixed
diff --git a/changelogs/unreleased/51668-fix-line-numbers.yml b/changelogs/unreleased/51668-fix-line-numbers.yml
deleted file mode 100644
index ac6e45e3cc7..00000000000
--- a/changelogs/unreleased/51668-fix-line-numbers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adjust line-height of blame view line numbers
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/51819-show-feed-toggle-under-system-notes.yml b/changelogs/unreleased/51819-show-feed-toggle-under-system-notes.yml
new file mode 100644
index 00000000000..76ea4149c56
--- /dev/null
+++ b/changelogs/unreleased/51819-show-feed-toggle-under-system-notes.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for toggling discussion filter from notes section
+merge_request: 25426
+author:
+type: added
diff --git a/changelogs/unreleased/51944-redesign-project-lists-ui.yml b/changelogs/unreleased/51944-redesign-project-lists-ui.yml
deleted file mode 100644
index 56f9a86a686..00000000000
--- a/changelogs/unreleased/51944-redesign-project-lists-ui.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Redesign project lists UI
-merge_request: 22682
-author:
-type: other
diff --git a/changelogs/unreleased/51971-milestones-visibility.yml b/changelogs/unreleased/51971-milestones-visibility.yml
new file mode 100644
index 00000000000..818f0071e6c
--- /dev/null
+++ b/changelogs/unreleased/51971-milestones-visibility.yml
@@ -0,0 +1,5 @@
+---
+title: Check if desired milestone for an issue is available
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/51994-disable-merging-labels-in-dropdowns.yml b/changelogs/unreleased/51994-disable-merging-labels-in-dropdowns.yml
deleted file mode 100644
index 2d54cf814b7..00000000000
--- a/changelogs/unreleased/51994-disable-merging-labels-in-dropdowns.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disable merging of labels with same names
-merge_request: 23265
-author:
-type: changed
diff --git a/changelogs/unreleased/52198-timer-is-vertically-misaligned-for-delayed-jobs-in-pipeline-actions.yml b/changelogs/unreleased/52198-timer-is-vertically-misaligned-for-delayed-jobs-in-pipeline-actions.yml
new file mode 100644
index 00000000000..84062c6db91
--- /dev/null
+++ b/changelogs/unreleased/52198-timer-is-vertically-misaligned-for-delayed-jobs-in-pipeline-actions.yml
@@ -0,0 +1,5 @@
+---
+title: 'Timer and action name aligned vertically for delayed jobs in pipeline actions'
+merge_request: 25117
+author: Gokhan Apaydin
+type: fixed
diff --git a/changelogs/unreleased/52424-goodbye-hipchat.yml b/changelogs/unreleased/52424-goodbye-hipchat.yml
new file mode 100644
index 00000000000..26dc904af5f
--- /dev/null
+++ b/changelogs/unreleased/52424-goodbye-hipchat.yml
@@ -0,0 +1,5 @@
+---
+title: Remove HipChat integration from GitLab
+merge_request: 22223
+author:
+type: removed
diff --git a/changelogs/unreleased/52459-display-job-names-consistently-on-pipelines-and-environments-list.yml b/changelogs/unreleased/52459-display-job-names-consistently-on-pipelines-and-environments-list.yml
new file mode 100644
index 00000000000..816fee1ccfc
--- /dev/null
+++ b/changelogs/unreleased/52459-display-job-names-consistently-on-pipelines-and-environments-list.yml
@@ -0,0 +1,5 @@
+---
+title: Display job names consistently on pipelines and environments list
+merge_request: 24984
+author:
+type: fixed
diff --git a/changelogs/unreleased/52620-fix-loader-animation-alignment.yml b/changelogs/unreleased/52620-fix-loader-animation-alignment.yml
deleted file mode 100644
index 5cfb7fc019f..00000000000
--- a/changelogs/unreleased/52620-fix-loader-animation-alignment.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Aligns build loader animation with the job log
-merge_request: 23959
-author:
-type: fixed
diff --git a/changelogs/unreleased/52734-styling-of-user-project-and-group-avatars.yml b/changelogs/unreleased/52734-styling-of-user-project-and-group-avatars.yml
new file mode 100644
index 00000000000..9329e81eb83
--- /dev/null
+++ b/changelogs/unreleased/52734-styling-of-user-project-and-group-avatars.yml
@@ -0,0 +1,5 @@
+---
+title: Add rectangular project and group avatars
+merge_request: 25098
+author:
+type: other
diff --git a/changelogs/unreleased/52778-don-t-display-pipeline-status-if-pipelines-are-disabled.yml b/changelogs/unreleased/52778-don-t-display-pipeline-status-if-pipelines-are-disabled.yml
new file mode 100644
index 00000000000..7fa01e2835a
--- /dev/null
+++ b/changelogs/unreleased/52778-don-t-display-pipeline-status-if-pipelines-are-disabled.yml
@@ -0,0 +1,5 @@
+---
+title: Hide pipeline status when pipelines are disabled on project.
+merge_request: 25204
+author:
+type: fixed
diff --git a/changelogs/unreleased/52792-align-mirror-repository-button.yml b/changelogs/unreleased/52792-align-mirror-repository-button.yml
new file mode 100644
index 00000000000..e8ce9ee0a4e
--- /dev/null
+++ b/changelogs/unreleased/52792-align-mirror-repository-button.yml
@@ -0,0 +1,5 @@
+---
+title: Add right padding to the repository mirror action buttons
+merge_request: 25606
+author:
+type: fixed
diff --git a/changelogs/unreleased/52877-ios-publishing-blog-post-and-gitlab-ci-yml-template.yml b/changelogs/unreleased/52877-ios-publishing-blog-post-and-gitlab-ci-yml-template.yml
new file mode 100644
index 00000000000..13529348c60
--- /dev/null
+++ b/changelogs/unreleased/52877-ios-publishing-blog-post-and-gitlab-ci-yml-template.yml
@@ -0,0 +1,5 @@
+---
+title: Add iOS-fastlane template for .gitlab-ci.yml
+merge_request: 25395
+author:
+type: changed
diff --git a/changelogs/unreleased/53020-user-specific-profile-page-settings-fields-don-t-have-help-text-placeholders.yml b/changelogs/unreleased/53020-user-specific-profile-page-settings-fields-don-t-have-help-text-placeholders.yml
deleted file mode 100644
index 99da02dd31a..00000000000
--- a/changelogs/unreleased/53020-user-specific-profile-page-settings-fields-don-t-have-help-text-placeholders.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds explanatory text to input fields on user profile settings page
-merge_request: 23673
-author:
-type: other
diff --git a/changelogs/unreleased/53325-admin-runners-page-fails-with-an-sql-statement-timeout.yml b/changelogs/unreleased/53325-admin-runners-page-fails-with-an-sql-statement-timeout.yml
new file mode 100644
index 00000000000..e0ed38fc2fa
--- /dev/null
+++ b/changelogs/unreleased/53325-admin-runners-page-fails-with-an-sql-statement-timeout.yml
@@ -0,0 +1,5 @@
+---
+title: Use limited counter for runner build count in admin page.
+merge_request: 25220
+author:
+type: fixed
diff --git a/changelogs/unreleased/53336-improve-web-ide-launch-performance.yml b/changelogs/unreleased/53336-improve-web-ide-launch-performance.yml
new file mode 100644
index 00000000000..65439f5a6c2
--- /dev/null
+++ b/changelogs/unreleased/53336-improve-web-ide-launch-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Improve Web IDE launch performance
+merge_request: 25700
+author:
+type: performance
diff --git a/changelogs/unreleased/53361-fresh-protected-branches.yml b/changelogs/unreleased/53361-fresh-protected-branches.yml
new file mode 100644
index 00000000000..55080e719b7
--- /dev/null
+++ b/changelogs/unreleased/53361-fresh-protected-branches.yml
@@ -0,0 +1,5 @@
+---
+title: Allow creation of branches that match a wildcard protection, except directly through git
+merge_request: 24969
+author:
+type: added
diff --git a/changelogs/unreleased/53411-remove_personal_access_tokens_token.yml b/changelogs/unreleased/53411-remove_personal_access_tokens_token.yml
new file mode 100644
index 00000000000..32cca07f58d
--- /dev/null
+++ b/changelogs/unreleased/53411-remove_personal_access_tokens_token.yml
@@ -0,0 +1,5 @@
+---
+title: Remove undigested token column from personal_access_tokens table from the database
+merge_request: 22743
+author:
+type: changed
diff --git a/changelogs/unreleased/53413-externalize-markdown-toolbar-tooltips.yml b/changelogs/unreleased/53413-externalize-markdown-toolbar-tooltips.yml
new file mode 100644
index 00000000000..c460760c10b
--- /dev/null
+++ b/changelogs/unreleased/53413-externalize-markdown-toolbar-tooltips.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize markdown toolbar buttons tooltips
+merge_request: 25529
+author:
+type: fixed
diff --git a/changelogs/unreleased/53493-list-id-email-header.yml b/changelogs/unreleased/53493-list-id-email-header.yml
deleted file mode 100644
index 09a0639f6f5..00000000000
--- a/changelogs/unreleased/53493-list-id-email-header.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add project identifier as List-Id email Header to ease filtering
-merge_request: 22817
-author: Olivier Crête
-type: added
diff --git a/changelogs/unreleased/53861-api-promote-project-milestone-to-a-group-milestone.yml b/changelogs/unreleased/53861-api-promote-project-milestone-to-a-group-milestone.yml
new file mode 100644
index 00000000000..6c621763e2e
--- /dev/null
+++ b/changelogs/unreleased/53861-api-promote-project-milestone-to-a-group-milestone.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Promote project milestone to a group milestone'
+merge_request: 25203
+author: Nermin Vehabovic
+type: added
diff --git a/changelogs/unreleased/53933-include-dates-in-milestone-change-email.yml b/changelogs/unreleased/53933-include-dates-in-milestone-change-email.yml
deleted file mode 100644
index 5c40a1e900c..00000000000
--- a/changelogs/unreleased/53933-include-dates-in-milestone-change-email.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add date range in milestone change email notifications
-merge_request: 23762
-author:
-type: changed
diff --git a/changelogs/unreleased/53954-resolved-non-diff-discussions-on-merge-requests-no-longer-show-who-resolved-them-and-when-at-a-glance.yml b/changelogs/unreleased/53954-resolved-non-diff-discussions-on-merge-requests-no-longer-show-who-resolved-them-and-when-at-a-glance.yml
deleted file mode 100644
index 0632c1992c7..00000000000
--- a/changelogs/unreleased/53954-resolved-non-diff-discussions-on-merge-requests-no-longer-show-who-resolved-them-and-when-at-a-glance.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show message on non-diff discussions
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/53966-make-hashed-storage-migration-safer-and-more-inviting.yml b/changelogs/unreleased/53966-make-hashed-storage-migration-safer-and-more-inviting.yml
new file mode 100644
index 00000000000..556a238ff7d
--- /dev/null
+++ b/changelogs/unreleased/53966-make-hashed-storage-migration-safer-and-more-inviting.yml
@@ -0,0 +1,5 @@
+---
+title: Hashed Storage rollback mechanism
+merge_request: 23955
+author:
+type: added
diff --git a/changelogs/unreleased/54146-fix-calendar-query.yml b/changelogs/unreleased/54146-fix-calendar-query.yml
deleted file mode 100644
index dcac343108a..00000000000
--- a/changelogs/unreleased/54146-fix-calendar-query.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix project calendar feed when sorted by priority
-merge_request: 23870
-author:
-type: fixed
diff --git a/changelogs/unreleased/54643-lower_issuable_finder_complexity.yml b/changelogs/unreleased/54643-lower_issuable_finder_complexity.yml
new file mode 100644
index 00000000000..f7f8e4d0e1f
--- /dev/null
+++ b/changelogs/unreleased/54643-lower_issuable_finder_complexity.yml
@@ -0,0 +1,5 @@
+---
+title: Speed up group issue search counts
+merge_request: 25411
+author:
+type: performance
diff --git a/changelogs/unreleased/54725-fix-emoji-button-active-state.yml b/changelogs/unreleased/54725-fix-emoji-button-active-state.yml
new file mode 100644
index 00000000000..4f0a436cc87
--- /dev/null
+++ b/changelogs/unreleased/54725-fix-emoji-button-active-state.yml
@@ -0,0 +1,5 @@
+---
+title: Fix hover and active state colors of award emoji button
+merge_request: 25295
+author:
+type: fixed
diff --git a/changelogs/unreleased/54736-sign-in-bottom-margin.yml b/changelogs/unreleased/54736-sign-in-bottom-margin.yml
deleted file mode 100644
index 32b5b44fe35..00000000000
--- a/changelogs/unreleased/54736-sign-in-bottom-margin.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix login box bottom margins on signin page
-merge_request: 23739
-author: '@gear54'
-type: fixed
diff --git a/changelogs/unreleased/54786-mr-empty-file-display.yml b/changelogs/unreleased/54786-mr-empty-file-display.yml
deleted file mode 100644
index 5adf5744755..00000000000
--- a/changelogs/unreleased/54786-mr-empty-file-display.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display empty files properly on MR diffs
-merge_request: 23671
-author: Sean Nichols
-type: fixed
diff --git a/changelogs/unreleased/54796-api-sort-tie-breaker-for-pagination.yml b/changelogs/unreleased/54796-api-sort-tie-breaker-for-pagination.yml
new file mode 100644
index 00000000000..92b27f63f82
--- /dev/null
+++ b/changelogs/unreleased/54796-api-sort-tie-breaker-for-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Sort tie breaker with id DESC'
+merge_request: 25311
+author: Nermin Vehabovic
+type: changed
diff --git a/changelogs/unreleased/54814-sidebar-styling-updates.yml b/changelogs/unreleased/54814-sidebar-styling-updates.yml
deleted file mode 100644
index 98e3836ee14..00000000000
--- a/changelogs/unreleased/54814-sidebar-styling-updates.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix label and header styles in the job details sidebar.
-merge_request: 23816
-author: Nathan Friend
-type: changed
diff --git a/changelogs/unreleased/54850-pages-domain-show-view-is-not-protected-by-access-control.yml b/changelogs/unreleased/54850-pages-domain-show-view-is-not-protected-by-access-control.yml
new file mode 100644
index 00000000000..41761213d7b
--- /dev/null
+++ b/changelogs/unreleased/54850-pages-domain-show-view-is-not-protected-by-access-control.yml
@@ -0,0 +1,5 @@
+---
+title: Require maintainer access to show pages domain settings
+merge_request: 24926
+author:
+type: fixed
diff --git a/changelogs/unreleased/54924-refactor-notes-actions-params.yml b/changelogs/unreleased/54924-refactor-notes-actions-params.yml
new file mode 100644
index 00000000000..b6083820401
--- /dev/null
+++ b/changelogs/unreleased/54924-refactor-notes-actions-params.yml
@@ -0,0 +1,5 @@
+---
+title: Fix commenting on commits having SHA1 starting with a large number
+merge_request: 25278
+author:
+type: fixed
diff --git a/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml b/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml
deleted file mode 100644
index 623b3a7319c..00000000000
--- a/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix a 500 error that could occur until all migrations are done
-merge_request: 23939
-author:
-type: fixed
diff --git a/changelogs/unreleased/55057-system-message-to-core.yml b/changelogs/unreleased/55057-system-message-to-core.yml
new file mode 100644
index 00000000000..3381879eb4a
--- /dev/null
+++ b/changelogs/unreleased/55057-system-message-to-core.yml
@@ -0,0 +1,5 @@
+---
+title: Port System Header and Footer feature to Core
+merge_request: 25241
+author:
+type: added
diff --git a/changelogs/unreleased/55103-hide-group-cluster-features.yml b/changelogs/unreleased/55103-hide-group-cluster-features.yml
deleted file mode 100644
index fbe780d6f01..00000000000
--- a/changelogs/unreleased/55103-hide-group-cluster-features.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hide cluster features that don't work yet with Group Clusters
-merge_request: 23935
-author:
-type: fixed
diff --git a/changelogs/unreleased/55109-jira-integration-api-doesn-t-respect-available-format.yml b/changelogs/unreleased/55109-jira-integration-api-doesn-t-respect-available-format.yml
new file mode 100644
index 00000000000..c58cdc19555
--- /dev/null
+++ b/changelogs/unreleased/55109-jira-integration-api-doesn-t-respect-available-format.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Support Jira transition ID as string'
+merge_request: 24400
+author: Robert Schilling
+type: fixed
diff --git a/changelogs/unreleased/55191-update-workhorse.yml b/changelogs/unreleased/55191-update-workhorse.yml
deleted file mode 100644
index d16518e673a..00000000000
--- a/changelogs/unreleased/55191-update-workhorse.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Workhorse to v8.0.0
-merge_request: 23740
-author:
-type: other
diff --git a/changelogs/unreleased/55209-tool-tip-hides-menu-item.yml b/changelogs/unreleased/55209-tool-tip-hides-menu-item.yml
new file mode 100644
index 00000000000..44ea4141632
--- /dev/null
+++ b/changelogs/unreleased/55209-tool-tip-hides-menu-item.yml
@@ -0,0 +1,5 @@
+---
+title: Close More Actions tooltip when menu opens
+merge_request: 24285
+author:
+type: fixed
diff --git a/changelogs/unreleased/55293-split-bio-into-individual-line-in-extended-user-tooltips.yml b/changelogs/unreleased/55293-split-bio-into-individual-line-in-extended-user-tooltips.yml
deleted file mode 100644
index c6ff52b0fa1..00000000000
--- a/changelogs/unreleased/55293-split-bio-into-individual-line-in-extended-user-tooltips.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Split bio into individual line in extended user tooltips
-merge_request: 23940
-author:
-type: other
diff --git a/changelogs/unreleased/55312-svg.yml b/changelogs/unreleased/55312-svg.yml
new file mode 100644
index 00000000000..a6260aeaf2a
--- /dev/null
+++ b/changelogs/unreleased/55312-svg.yml
@@ -0,0 +1,5 @@
+---
+title: Use export-import svgs from gitlab-svgs
+merge_request: 24954
+author:
+type: other
diff --git a/changelogs/unreleased/55344-only-prompt-user-once-when-navigating-away-from-file-editor.yml b/changelogs/unreleased/55344-only-prompt-user-once-when-navigating-away-from-file-editor.yml
deleted file mode 100644
index 9c4d73c5323..00000000000
--- a/changelogs/unreleased/55344-only-prompt-user-once-when-navigating-away-from-file-editor.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Only prompt user once when navigating away from file editor
-merge_request: 23820
-author: Sam Bigelow
-type: fixed
diff --git a/changelogs/unreleased/55376-related_merge_requests-api-call-returns-merge-requests-that-are-not-related-to-the-issue.yml b/changelogs/unreleased/55376-related_merge_requests-api-call-returns-merge-requests-that-are-not-related-to-the-issue.yml
new file mode 100644
index 00000000000..d2f24d6f499
--- /dev/null
+++ b/changelogs/unreleased/55376-related_merge_requests-api-call-returns-merge-requests-that-are-not-related-to-the-issue.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Ensure that related merge requests are referenced cross-project'
+merge_request: 25222
+author: Robert Schilling
+type: fixed
diff --git a/changelogs/unreleased/55447-validate-k8s-ca-cert.yml b/changelogs/unreleased/55447-validate-k8s-ca-cert.yml
new file mode 100644
index 00000000000..e0448d403da
--- /dev/null
+++ b/changelogs/unreleased/55447-validate-k8s-ca-cert.yml
@@ -0,0 +1,5 @@
+---
+title: Validate kubernetes cluster CA certificate
+merge_request: 24990
+author:
+type: changed
diff --git a/changelogs/unreleased/55703-md-image-borders.yml b/changelogs/unreleased/55703-md-image-borders.yml
new file mode 100644
index 00000000000..94297a42f6d
--- /dev/null
+++ b/changelogs/unreleased/55703-md-image-borders.yml
@@ -0,0 +1,5 @@
+---
+title: Only show borders for markdown images in notes
+merge_request: 25448
+author:
+type: fixed
diff --git a/changelogs/unreleased/55893-artifacts-download.yml b/changelogs/unreleased/55893-artifacts-download.yml
new file mode 100644
index 00000000000..30c118b7094
--- /dev/null
+++ b/changelogs/unreleased/55893-artifacts-download.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes not working dropdowns in pipelines page
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/55925-if-there-is-only-one-changed-page-in-review-app-go-directly-there.yml b/changelogs/unreleased/55925-if-there-is-only-one-changed-page-in-review-app-go-directly-there.yml
new file mode 100644
index 00000000000..ef3d9844acb
--- /dev/null
+++ b/changelogs/unreleased/55925-if-there-is-only-one-changed-page-in-review-app-go-directly-there.yml
@@ -0,0 +1,5 @@
+---
+title: Review App Link to Changed Page if Only One Change Present
+merge_request: 25048
+author:
+type: changed
diff --git a/changelogs/unreleased/56237-api-truncated-commit-title.yml b/changelogs/unreleased/56237-api-truncated-commit-title.yml
new file mode 100644
index 00000000000..1a48d0fda1b
--- /dev/null
+++ b/changelogs/unreleased/56237-api-truncated-commit-title.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Expose full commit title'
+merge_request: 25189
+author: Robert Schilling
+type: fixed
diff --git a/changelogs/unreleased/56251-fix-issue-board-weekday-shift.yml b/changelogs/unreleased/56251-fix-issue-board-weekday-shift.yml
new file mode 100644
index 00000000000..bedc488ebd4
--- /dev/null
+++ b/changelogs/unreleased/56251-fix-issue-board-weekday-shift.yml
@@ -0,0 +1,5 @@
+---
+title: "Fix weekday shift in issue board cards for UTC+X timezones by removing local timezone to UTC conversion"
+merge_request: 25512
+author: Elias Werberich
+type: fixed
diff --git a/changelogs/unreleased/56477-units-are-appended-to-y-axis-label-on-metrics-dashboard.yml b/changelogs/unreleased/56477-units-are-appended-to-y-axis-label-on-metrics-dashboard.yml
new file mode 100644
index 00000000000..7febe175faf
--- /dev/null
+++ b/changelogs/unreleased/56477-units-are-appended-to-y-axis-label-on-metrics-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicate units from metrics graph
+merge_request: 25485
+author:
+type: fixed
diff --git a/changelogs/unreleased/56485-implement-graphql-mergerequestsresolver.yml b/changelogs/unreleased/56485-implement-graphql-mergerequestsresolver.yml
new file mode 100644
index 00000000000..5362ac65038
--- /dev/null
+++ b/changelogs/unreleased/56485-implement-graphql-mergerequestsresolver.yml
@@ -0,0 +1,5 @@
+---
+title: Add field mergeRequests for project in GraphQL
+merge_request: 24805
+author:
+type: added
diff --git a/changelogs/unreleased/56492-implement-new-arguments-state-closed_before-and-closed_after-for-issuesresolver-in-graphql.yml b/changelogs/unreleased/56492-implement-new-arguments-state-closed_before-and-closed_after-for-issuesresolver-in-graphql.yml
new file mode 100644
index 00000000000..9b7aed82d49
--- /dev/null
+++ b/changelogs/unreleased/56492-implement-new-arguments-state-closed_before-and-closed_after-for-issuesresolver-in-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: "Implement new arguments `state`, `closed_before` and `closed_after` for `IssuesResolver` in GraphQL"
+merge_request: 24910
+author:
+type: changed
diff --git a/changelogs/unreleased/56694-mark-group-level-labels-in-label-api-as-such.yml b/changelogs/unreleased/56694-mark-group-level-labels-in-label-api-as-such.yml
new file mode 100644
index 00000000000..ae2d9e18e0b
--- /dev/null
+++ b/changelogs/unreleased/56694-mark-group-level-labels-in-label-api-as-such.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Indicate if label is a project label'
+merge_request: 25219
+author: Robert Schilling
+type: added
diff --git a/changelogs/unreleased/56726-fix-n-1-in-issues-and-merge-requests-api.yml b/changelogs/unreleased/56726-fix-n-1-in-issues-and-merge-requests-api.yml
new file mode 100644
index 00000000000..3eb9e484647
--- /dev/null
+++ b/changelogs/unreleased/56726-fix-n-1-in-issues-and-merge-requests-api.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 query in Issues and MergeRequest API when issuable_metadata is present
+merge_request: 25042
+author: Alex Koval
+type: other
diff --git a/changelogs/unreleased/56787-realtime-validation-for-user-fullname-and-username.yml b/changelogs/unreleased/56787-realtime-validation-for-user-fullname-and-username.yml
new file mode 100644
index 00000000000..cc3a60479d3
--- /dev/null
+++ b/changelogs/unreleased/56787-realtime-validation-for-user-fullname-and-username.yml
@@ -0,0 +1,5 @@
+---
+title: Add realtime validation for user fullname and username on validation
+merge_request: 25017
+author: Ehsan Abdulqader @EhsanZ
+type: added
diff --git a/changelogs/unreleased/56809-graphql-version-api.yml b/changelogs/unreleased/56809-graphql-version-api.yml
new file mode 100644
index 00000000000..72a4b4e5819
--- /dev/null
+++ b/changelogs/unreleased/56809-graphql-version-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add metadata about the GitLab server to GraphQL
+merge_request: 24636
+author:
+type: added
diff --git a/changelogs/unreleased/56851-blank-values-in-reactive-cache.yml b/changelogs/unreleased/56851-blank-values-in-reactive-cache.yml
new file mode 100644
index 00000000000..5b9253793be
--- /dev/null
+++ b/changelogs/unreleased/56851-blank-values-in-reactive-cache.yml
@@ -0,0 +1,5 @@
+---
+title: Allow empty values such as [] to be stored in reactive cache
+merge_request: 25283
+author:
+type: fixed
diff --git a/changelogs/unreleased/56851-error-tracking-page-seems-broken.yml b/changelogs/unreleased/56851-error-tracking-page-seems-broken.yml
new file mode 100644
index 00000000000..ff4aebb9381
--- /dev/null
+++ b/changelogs/unreleased/56851-error-tracking-page-seems-broken.yml
@@ -0,0 +1,5 @@
+---
+title: Fix error tracking list page
+merge_request: 24806
+author:
+type: fixed
diff --git a/changelogs/unreleased/56863-system-messages-in-email.yml b/changelogs/unreleased/56863-system-messages-in-email.yml
new file mode 100644
index 00000000000..21a90aa95ee
--- /dev/null
+++ b/changelogs/unreleased/56863-system-messages-in-email.yml
@@ -0,0 +1,5 @@
+---
+title: Show header and footer system messages in email
+merge_request: 25474
+author:
+type: added
diff --git a/changelogs/unreleased/56871-list-issues-error.yml b/changelogs/unreleased/56871-list-issues-error.yml
new file mode 100644
index 00000000000..af5585c6b5d
--- /dev/null
+++ b/changelogs/unreleased/56871-list-issues-error.yml
@@ -0,0 +1,5 @@
+---
+title: Display error message when API call to list Sentry issues fails
+merge_request: 24936
+author:
+type: fixed
diff --git a/changelogs/unreleased/56873-only-load-syntax-highlighting-css-when-selected.yml b/changelogs/unreleased/56873-only-load-syntax-highlighting-css-when-selected.yml
new file mode 100644
index 00000000000..a7af8994852
--- /dev/null
+++ b/changelogs/unreleased/56873-only-load-syntax-highlighting-css-when-selected.yml
@@ -0,0 +1,5 @@
+---
+title: Only load syntax highlight CSS of selected theme
+merge_request: 25232
+author:
+type: performance
diff --git a/changelogs/unreleased/56937-edit-knative-domain-after-it-has-been-deployed.yml b/changelogs/unreleased/56937-edit-knative-domain-after-it-has-been-deployed.yml
new file mode 100644
index 00000000000..11d93b34700
--- /dev/null
+++ b/changelogs/unreleased/56937-edit-knative-domain-after-it-has-been-deployed.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes functions finder for upgraded Knative app
+merge_request: 25067
+author:
+type: fixed
diff --git a/changelogs/unreleased/57085-introduce-zoom-and-scroll-functionality-on-metrics-charts.yml b/changelogs/unreleased/57085-introduce-zoom-and-scroll-functionality-on-metrics-charts.yml
new file mode 100644
index 00000000000..1d07666dfb1
--- /dev/null
+++ b/changelogs/unreleased/57085-introduce-zoom-and-scroll-functionality-on-metrics-charts.yml
@@ -0,0 +1,5 @@
+---
+title: Add zoom and scroll to metrics dashboard
+merge_request: 25388
+author:
+type: added
diff --git a/changelogs/unreleased/57101-api-docs-for-hangouts-chat-service-incorrect.yml b/changelogs/unreleased/57101-api-docs-for-hangouts-chat-service-incorrect.yml
new file mode 100644
index 00000000000..2e0ae9c3732
--- /dev/null
+++ b/changelogs/unreleased/57101-api-docs-for-hangouts-chat-service-incorrect.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Fix docs and parameters for hangouts-chat service'
+merge_request: 25180
+author: Robert Schilling
+type: fixed
diff --git a/changelogs/unreleased/57223-wiki-finder.yml b/changelogs/unreleased/57223-wiki-finder.yml
new file mode 100644
index 00000000000..5ddf197568d
--- /dev/null
+++ b/changelogs/unreleased/57223-wiki-finder.yml
@@ -0,0 +1,5 @@
+---
+title: Remove BATCH_SIZE from WikiFileFinder
+merge_request: 24933
+author:
+type: other
diff --git a/changelogs/unreleased/57353-git-push-fails-on-large-lfs-files-where-the-push-take-a-long-time.yml b/changelogs/unreleased/57353-git-push-fails-on-large-lfs-files-where-the-push-take-a-long-time.yml
new file mode 100644
index 00000000000..46f82afda62
--- /dev/null
+++ b/changelogs/unreleased/57353-git-push-fails-on-large-lfs-files-where-the-push-take-a-long-time.yml
@@ -0,0 +1,5 @@
+---
+title: Provide expires_in in LFS authentication payload
+merge_request: 25082
+author:
+type: fixed
diff --git a/changelogs/unreleased/57410-api-create-release-link-with-ftp-address-return-400-bad-request.yml b/changelogs/unreleased/57410-api-create-release-link-with-ftp-address-return-400-bad-request.yml
new file mode 100644
index 00000000000..6be6a2115b9
--- /dev/null
+++ b/changelogs/unreleased/57410-api-create-release-link-with-ftp-address-return-400-bad-request.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for FTP assets for releases
+merge_request: 25071
+author: Robert Schilling
+type: added
diff --git a/changelogs/unreleased/57534_filter_impersonated_sessions.yml b/changelogs/unreleased/57534_filter_impersonated_sessions.yml
new file mode 100644
index 00000000000..80aea0ab1bc
--- /dev/null
+++ b/changelogs/unreleased/57534_filter_impersonated_sessions.yml
@@ -0,0 +1,6 @@
+---
+title: Do not display impersonated sessions under active sessions and remove ability
+ to revoke session
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/57544-web-ide-new-directory-dialog-shows-file-templates.yml b/changelogs/unreleased/57544-web-ide-new-directory-dialog-shows-file-templates.yml
new file mode 100644
index 00000000000..9d9158ca4af
--- /dev/null
+++ b/changelogs/unreleased/57544-web-ide-new-directory-dialog-shows-file-templates.yml
@@ -0,0 +1,5 @@
+---
+title: Do not show file templates when creating a new directory in WebIDE
+merge_request: !25119
+author:
+type: fixed
diff --git a/changelogs/unreleased/57564-contributing-button-border.yml b/changelogs/unreleased/57564-contributing-button-border.yml
new file mode 100644
index 00000000000..e5875ef1c0f
--- /dev/null
+++ b/changelogs/unreleased/57564-contributing-button-border.yml
@@ -0,0 +1,5 @@
+---
+title: Fix the border style of CONTRIBUTING button when it exists
+merge_request: 25124
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/57579-gitlab-project-import-fails-sidekiq-undefined-method-import_jid.yml b/changelogs/unreleased/57579-gitlab-project-import-fails-sidekiq-undefined-method-import_jid.yml
new file mode 100644
index 00000000000..f7d6a6c4863
--- /dev/null
+++ b/changelogs/unreleased/57579-gitlab-project-import-fails-sidekiq-undefined-method-import_jid.yml
@@ -0,0 +1,5 @@
+---
+title: Fix import_jid error on project import
+merge_request: 25239
+author:
+type: fixed
diff --git a/changelogs/unreleased/57582-dropdown-icon-misalignment-on-issues-list-on-mobile-screen.yml b/changelogs/unreleased/57582-dropdown-icon-misalignment-on-issues-list-on-mobile-screen.yml
new file mode 100644
index 00000000000..5681309cb9e
--- /dev/null
+++ b/changelogs/unreleased/57582-dropdown-icon-misalignment-on-issues-list-on-mobile-screen.yml
@@ -0,0 +1,5 @@
+---
+title: Fix alignment of dropdown icon on issuable on mobile
+merge_request: 25205
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/57612-github-importer-ignores-milestone-due_date.yml b/changelogs/unreleased/57612-github-importer-ignores-milestone-due_date.yml
new file mode 100644
index 00000000000..0d5cd057ade
--- /dev/null
+++ b/changelogs/unreleased/57612-github-importer-ignores-milestone-due_date.yml
@@ -0,0 +1,5 @@
+---
+title: Capture due date when importing milestones from Github
+merge_request: 25182
+author: dstanley
+type: changed
diff --git a/changelogs/unreleased/57671-fix_merge_request_base_pipeline.yml b/changelogs/unreleased/57671-fix_merge_request_base_pipeline.yml
new file mode 100644
index 00000000000..d89819eee60
--- /dev/null
+++ b/changelogs/unreleased/57671-fix_merge_request_base_pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure the base pipeline of a Merge Request belongs to its target branch
+merge_request: 25226
+author:
+type: fixed
diff --git a/changelogs/unreleased/57712-project-import-error-user-expected-got-hash.yml b/changelogs/unreleased/57712-project-import-error-user-expected-got-hash.yml
new file mode 100644
index 00000000000..6fb198e1552
--- /dev/null
+++ b/changelogs/unreleased/57712-project-import-error-user-expected-got-hash.yml
@@ -0,0 +1,5 @@
+---
+title: Fix project import error importing releases
+merge_request: 25495
+author:
+type: fixed
diff --git a/changelogs/unreleased/57734-improve-label-dropdown-selection-performance.yml b/changelogs/unreleased/57734-improve-label-dropdown-selection-performance.yml
new file mode 100644
index 00000000000..781446b86d7
--- /dev/null
+++ b/changelogs/unreleased/57734-improve-label-dropdown-selection-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Improve label select rendering
+merge_request: 25281
+author:
+type: performance
diff --git a/changelogs/unreleased/57768-remove-vertical-line.yml b/changelogs/unreleased/57768-remove-vertical-line.yml
new file mode 100644
index 00000000000..b73b0fa229e
--- /dev/null
+++ b/changelogs/unreleased/57768-remove-vertical-line.yml
@@ -0,0 +1,5 @@
+---
+title: Remove vertical connecting line placeholder from diff discussion notes
+merge_request: 25292
+author:
+type: fixed
diff --git a/changelogs/unreleased/57784-make-closed-duplicate-and-closed-moved-button-a-link-to-target.yml b/changelogs/unreleased/57784-make-closed-duplicate-and-closed-moved-button-a-link-to-target.yml
new file mode 100644
index 00000000000..2775d9f4e36
--- /dev/null
+++ b/changelogs/unreleased/57784-make-closed-duplicate-and-closed-moved-button-a-link-to-target.yml
@@ -0,0 +1,5 @@
+---
+title: Add Link from Closed (moved) Issues to Moved Issue
+merge_request: 25300
+author:
+type: added
diff --git a/changelogs/unreleased/57785-create-project-template-for-netlify.yml b/changelogs/unreleased/57785-create-project-template-for-netlify.yml
new file mode 100644
index 00000000000..78e9e3dece5
--- /dev/null
+++ b/changelogs/unreleased/57785-create-project-template-for-netlify.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Create Project Template for Netlify
+merge_request: 25453
+author:
+type: changed
diff --git a/changelogs/unreleased/57788-project-labels-tooltip-missing.yml b/changelogs/unreleased/57788-project-labels-tooltip-missing.yml
new file mode 100644
index 00000000000..9146af0e0f3
--- /dev/null
+++ b/changelogs/unreleased/57788-project-labels-tooltip-missing.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug where project topics truncate
+merge_request: 25398
+author:
+type: fixed
diff --git a/changelogs/unreleased/57794-project-template-for-net.yml b/changelogs/unreleased/57794-project-template-for-net.yml
new file mode 100644
index 00000000000..bc05ac10aff
--- /dev/null
+++ b/changelogs/unreleased/57794-project-template-for-net.yml
@@ -0,0 +1,5 @@
+---
+title: Add Project template for .NET Core
+merge_request: 25486
+author:
+type: changed
diff --git a/changelogs/unreleased/57829-issuable-meta-line-ui-broken-on-mobile.yml b/changelogs/unreleased/57829-issuable-meta-line-ui-broken-on-mobile.yml
new file mode 100644
index 00000000000..b4b305e76d0
--- /dev/null
+++ b/changelogs/unreleased/57829-issuable-meta-line-ui-broken-on-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Fix author layouts in issuable meta line UIs on mobile
+merge_request: 25332
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/57905-etag-caching-probably-broken-since-11-5-0.yml b/changelogs/unreleased/57905-etag-caching-probably-broken-since-11-5-0.yml
new file mode 100644
index 00000000000..046ef8ee99e
--- /dev/null
+++ b/changelogs/unreleased/57905-etag-caching-probably-broken-since-11-5-0.yml
@@ -0,0 +1,5 @@
+---
+title: Fix ETag caching not being used for AJAX requests
+merge_request: 25400
+author:
+type: fixed
diff --git a/changelogs/unreleased/57991-frontend-pagination-needs-to-handle-cases-where-the-x-total-pages-header-isn-t-present.yml b/changelogs/unreleased/57991-frontend-pagination-needs-to-handle-cases-where-the-x-total-pages-header-isn-t-present.yml
new file mode 100644
index 00000000000..2e18377a4cf
--- /dev/null
+++ b/changelogs/unreleased/57991-frontend-pagination-needs-to-handle-cases-where-the-x-total-pages-header-isn-t-present.yml
@@ -0,0 +1,5 @@
+---
+title: "Improve the JS pagination to handle the case when the `X-Total` and `X-Total-Pages` headers aren't present"
+merge_request: 25601
+author:
+type: fixed
diff --git a/changelogs/unreleased/58020-fix-merge-api-endpoint-param.yml b/changelogs/unreleased/58020-fix-merge-api-endpoint-param.yml
new file mode 100644
index 00000000000..7cfeb4a0cd7
--- /dev/null
+++ b/changelogs/unreleased/58020-fix-merge-api-endpoint-param.yml
@@ -0,0 +1,5 @@
+---
+title: Respect the should_remove_source_branch parameter to the merge API
+merge_request: 25525
+author:
+type: fixed
diff --git a/changelogs/unreleased/58023-add-Saturday-to-localization-first-day-of-the-week.yml b/changelogs/unreleased/58023-add-Saturday-to-localization-first-day-of-the-week.yml
new file mode 100644
index 00000000000..69d927dc5e4
--- /dev/null
+++ b/changelogs/unreleased/58023-add-Saturday-to-localization-first-day-of-the-week.yml
@@ -0,0 +1,5 @@
+---
+title: Add Saturday to Localization first day of the week
+merge_request: 25509
+author: Ahmad Haghighi
+type: added
diff --git a/changelogs/unreleased/58082-project-template-for-go-micro.yml b/changelogs/unreleased/58082-project-template-for-go-micro.yml
new file mode 100644
index 00000000000..63a70cda0b8
--- /dev/null
+++ b/changelogs/unreleased/58082-project-template-for-go-micro.yml
@@ -0,0 +1,5 @@
+---
+title: Add Project template for go-micro
+merge_request: 25553
+author:
+type: changed
diff --git a/changelogs/unreleased/58098-auto-devops-postgres-version-variable.yml b/changelogs/unreleased/58098-auto-devops-postgres-version-variable.yml
new file mode 100644
index 00000000000..a7a87f60c28
--- /dev/null
+++ b/changelogs/unreleased/58098-auto-devops-postgres-version-variable.yml
@@ -0,0 +1,5 @@
+---
+title: Allow configuring POSTGRES_VERSION in Auto DevOps
+merge_request: 25500
+author:
+type: added
diff --git a/changelogs/unreleased/58149-fix-read-list-board-policy.yml b/changelogs/unreleased/58149-fix-read-list-board-policy.yml
new file mode 100644
index 00000000000..964813f4c9a
--- /dev/null
+++ b/changelogs/unreleased/58149-fix-read-list-board-policy.yml
@@ -0,0 +1,6 @@
+---
+title: Fix error when viewing group issue boards when user doesn't have explicit group
+ permissions
+merge_request: 25524
+author:
+type: fixed
diff --git a/changelogs/unreleased/58274-folder-icon-in-tags-page.yml b/changelogs/unreleased/58274-folder-icon-in-tags-page.yml
new file mode 100644
index 00000000000..db8128b8dfd
--- /dev/null
+++ b/changelogs/unreleased/58274-folder-icon-in-tags-page.yml
@@ -0,0 +1,5 @@
+---
+title: Use 'folder-open' from sprite icons for Browse Files button in Tag page
+merge_request: 25635
+author:
+type: fixed
diff --git a/changelogs/unreleased/58369-hide-squash-commit.yml b/changelogs/unreleased/58369-hide-squash-commit.yml
new file mode 100644
index 00000000000..e44b483b3a1
--- /dev/null
+++ b/changelogs/unreleased/58369-hide-squash-commit.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve showing squash commit edit issue when only single commit is present
+merge_request: 25807
+author:
+type: fixed
diff --git a/changelogs/unreleased/58570-fix-running-pipline-that-is-imported-via-dotnetcore-template.yml b/changelogs/unreleased/58570-fix-running-pipline-that-is-imported-via-dotnetcore-template.yml
new file mode 100644
index 00000000000..b81dc151b44
--- /dev/null
+++ b/changelogs/unreleased/58570-fix-running-pipline-that-is-imported-via-dotnetcore-template.yml
@@ -0,0 +1,5 @@
+---
+title: Clean up vendored templates
+merge_request: 25794
+author:
+type: changed
diff --git a/changelogs/unreleased/8711-prep-frontend-single-repo.yml b/changelogs/unreleased/8711-prep-frontend-single-repo.yml
new file mode 100644
index 00000000000..9c16e16a84b
--- /dev/null
+++ b/changelogs/unreleased/8711-prep-frontend-single-repo.yml
@@ -0,0 +1,5 @@
+---
+title: Creates a helper function to check if repo is EE
+merge_request: 25647
+author:
+type: other
diff --git a/changelogs/unreleased/9841-geo-unable-to-compare-branches-on-secondary.yml b/changelogs/unreleased/9841-geo-unable-to-compare-branches-on-secondary.yml
new file mode 100644
index 00000000000..c014edf9c09
--- /dev/null
+++ b/changelogs/unreleased/9841-geo-unable-to-compare-branches-on-secondary.yml
@@ -0,0 +1,5 @@
+---
+title: Allow users to compare branches on a read-only instance
+merge_request: 25414
+author:
+type: fixed
diff --git a/changelogs/unreleased/ac-releases-name-sha-author.yml b/changelogs/unreleased/ac-releases-name-sha-author.yml
deleted file mode 100644
index e84b82847eb..00000000000
--- a/changelogs/unreleased/ac-releases-name-sha-author.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add name, author_id, and sha to releases table
-merge_request: 23763
-author:
-type: added
diff --git a/changelogs/unreleased/add-new-nginx-metrics.yml b/changelogs/unreleased/add-new-nginx-metrics.yml
deleted file mode 100644
index 57221056d6e..00000000000
--- a/changelogs/unreleased/add-new-nginx-metrics.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add NGINX 0.16.0 and above metrics
-merge_request: 22133
-author:
-type: added
diff --git a/changelogs/unreleased/add-project-level-config-for-prospective-merge-pipelines-ce.yml b/changelogs/unreleased/add-project-level-config-for-prospective-merge-pipelines-ce.yml
new file mode 100644
index 00000000000..39d7ead9af4
--- /dev/null
+++ b/changelogs/unreleased/add-project-level-config-for-prospective-merge-pipelines-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Add project level config for merge pipelines
+merge_request: 25385
+author:
+type: added
diff --git a/changelogs/unreleased/add-related-merge-request-count-to-api-response.yml b/changelogs/unreleased/add-related-merge-request-count-to-api-response.yml
new file mode 100644
index 00000000000..7438053a84f
--- /dev/null
+++ b/changelogs/unreleased/add-related-merge-request-count-to-api-response.yml
@@ -0,0 +1,5 @@
+---
+title: Add related merge request count to api response
+merge_request: 24974
+author:
+type: added
diff --git a/changelogs/unreleased/add-title-attribute-to-file-row.yml b/changelogs/unreleased/add-title-attribute-to-file-row.yml
new file mode 100644
index 00000000000..c68d3d544e7
--- /dev/null
+++ b/changelogs/unreleased/add-title-attribute-to-file-row.yml
@@ -0,0 +1,5 @@
+---
+title: add title attribute to display file name
+merge_request: 25154
+author: Satoshi Nakamatsu @satoshicano
+type: added
diff --git a/changelogs/unreleased/add-youtrack-integration.yml b/changelogs/unreleased/add-youtrack-integration.yml
new file mode 100644
index 00000000000..f500e625145
--- /dev/null
+++ b/changelogs/unreleased/add-youtrack-integration.yml
@@ -0,0 +1,5 @@
+---
+title: Add YouTrack integration service
+merge_request: 25361
+author: Yauhen Kotau @bessorion
+type: added
diff --git a/changelogs/unreleased/add_ldap_tls_options.yml b/changelogs/unreleased/add_ldap_tls_options.yml
new file mode 100644
index 00000000000..c3678cb8fb6
--- /dev/null
+++ b/changelogs/unreleased/add_ldap_tls_options.yml
@@ -0,0 +1,5 @@
+---
+title: Allow raw `tls_options` to be passed in LDAP configuration
+merge_request: 20678
+author:
+type: changed
diff --git a/changelogs/unreleased/allow-maintainers-to-remove-pages.yml b/changelogs/unreleased/allow-maintainers-to-remove-pages.yml
new file mode 100644
index 00000000000..6e344dbe0e9
--- /dev/null
+++ b/changelogs/unreleased/allow-maintainers-to-remove-pages.yml
@@ -0,0 +1,5 @@
+---
+title: Allow maintainers to remove pages
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/allow-to-recursively-include.yml b/changelogs/unreleased/allow-to-recursively-include.yml
new file mode 100644
index 00000000000..edfbfcb0146
--- /dev/null
+++ b/changelogs/unreleased/allow-to-recursively-include.yml
@@ -0,0 +1,5 @@
+---
+title: Allow to recursively expand includes
+merge_request: 24356
+author:
+type: added
diff --git a/changelogs/unreleased/an-peek-jaeger.yml b/changelogs/unreleased/an-peek-jaeger.yml
new file mode 100644
index 00000000000..8659ee4f9e0
--- /dev/null
+++ b/changelogs/unreleased/an-peek-jaeger.yml
@@ -0,0 +1,5 @@
+---
+title: Provide a performance bar link to the Jaeger UI
+merge_request: 24902
+author:
+type: other
diff --git a/changelogs/unreleased/auto-devops-tags.yml b/changelogs/unreleased/auto-devops-tags.yml
new file mode 100644
index 00000000000..1b96d457776
--- /dev/null
+++ b/changelogs/unreleased/auto-devops-tags.yml
@@ -0,0 +1,5 @@
+---
+title: Adds Auto DevOps build job for tags
+merge_request: 25718
+author: walkafwalka
+type: added
diff --git a/changelogs/unreleased/blackst0ne-convert-specs-rails5-style.yml b/changelogs/unreleased/blackst0ne-convert-specs-rails5-style.yml
deleted file mode 100644
index c29cfec075c..00000000000
--- a/changelogs/unreleased/blackst0ne-convert-specs-rails5-style.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5.1] Update functional specs to use new keyword format"
-merge_request: 23095
-author: "@blackst0ne"
-type: other
diff --git a/changelogs/unreleased/blackst0ne-improve-encoding-helper-spec.yml b/changelogs/unreleased/blackst0ne-improve-encoding-helper-spec.yml
deleted file mode 100644
index 09480499b87..00000000000
--- a/changelogs/unreleased/blackst0ne-improve-encoding-helper-spec.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update specs to exclude possible false positive pass
-merge_request: 23893
-author: "@blackst0ne"
-type: other
diff --git a/changelogs/unreleased/bvl-graphql-csrf.yml b/changelogs/unreleased/bvl-graphql-csrf.yml
new file mode 100644
index 00000000000..d1e5b56c751
--- /dev/null
+++ b/changelogs/unreleased/bvl-graphql-csrf.yml
@@ -0,0 +1,5 @@
+---
+title: Allow GraphQL requests without CSRF token
+merge_request: 25719
+author:
+type: fixed
diff --git a/changelogs/unreleased/bvl-hide-confidential-events-take2.yml b/changelogs/unreleased/bvl-hide-confidential-events-take2.yml
deleted file mode 100644
index a5abd496a9d..00000000000
--- a/changelogs/unreleased/bvl-hide-confidential-events-take2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hide confidential events in the API
-merge_request: 23746
-author:
-type: other
diff --git a/changelogs/unreleased/change-badges-example-to-pipeline.yml b/changelogs/unreleased/change-badges-example-to-pipeline.yml
new file mode 100644
index 00000000000..8ed4d77fd6c
--- /dev/null
+++ b/changelogs/unreleased/change-badges-example-to-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Change badges.svg example to pipeline.svg
+merge_request: 25157
+author: Aviad Levy
+type: fixed
diff --git a/changelogs/unreleased/changelogs-readme.yml b/changelogs/unreleased/changelogs-readme.yml
new file mode 100644
index 00000000000..9f391699575
--- /dev/null
+++ b/changelogs/unreleased/changelogs-readme.yml
@@ -0,0 +1,5 @@
+---
+title: add readme to changelogs directory
+merge_request: 25209
+author: "@glensc"
+type: added
diff --git a/changelogs/unreleased/consistent-pagination.yml b/changelogs/unreleased/consistent-pagination.yml
new file mode 100644
index 00000000000..95eefaeb31d
--- /dev/null
+++ b/changelogs/unreleased/consistent-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: Fix inconsistent pagination styles
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/depracated-migration-inheritance.yml b/changelogs/unreleased/depracated-migration-inheritance.yml
deleted file mode 100644
index 1ea9b2df59c..00000000000
--- a/changelogs/unreleased/depracated-migration-inheritance.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: ActiveRecord::Migration -> ActiveRecord::Migration[5.0]
-merge_request: 23910
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/deprecated-actiondispatch-paramsparser.yml b/changelogs/unreleased/deprecated-actiondispatch-paramsparser.yml
deleted file mode 100644
index 9cfb00a9544..00000000000
--- a/changelogs/unreleased/deprecated-actiondispatch-paramsparser.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove deprecated ActionDispatch::ParamsParser
-merge_request: 23848
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/deprecated-alias-method-chain.yml b/changelogs/unreleased/deprecated-alias-method-chain.yml
deleted file mode 100644
index 76dd016e4cc..00000000000
--- a/changelogs/unreleased/deprecated-alias-method-chain.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: 'Fix deprecation: alias_method_chain is deprecated. Please, use Module#prepend
- instead'
-merge_request: 23887
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/deprecated-comparing-actioncontroller-params-hash.yml b/changelogs/unreleased/deprecated-comparing-actioncontroller-params-hash.yml
deleted file mode 100644
index a7b9d054a4c..00000000000
--- a/changelogs/unreleased/deprecated-comparing-actioncontroller-params-hash.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: 'Fix deprecation: Comparing equality between ActionController::Parameters and
- a Hash is deprecated'
-merge_request: 23855
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/deprecated-delete-all-params.yml b/changelogs/unreleased/deprecated-delete-all-params.yml
deleted file mode 100644
index e23fe92a738..00000000000
--- a/changelogs/unreleased/deprecated-delete-all-params.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Fix deprecation: Passing conditions to delete_all is deprecated'
-merge_request: 23817
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/deprecated-directly-inheriting-migration.yml b/changelogs/unreleased/deprecated-directly-inheriting-migration.yml
deleted file mode 100644
index 2793cc0d44f..00000000000
--- a/changelogs/unreleased/deprecated-directly-inheriting-migration.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Fix deprecation: Directly inheriting from ActiveRecord::Migration is deprecated.'
-merge_request: 23884
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/deprecated-migration-inheritance.yml b/changelogs/unreleased/deprecated-migration-inheritance.yml
new file mode 100644
index 00000000000..814c511195b
--- /dev/null
+++ b/changelogs/unreleased/deprecated-migration-inheritance.yml
@@ -0,0 +1,5 @@
+---
+title: Directly inheriting from ActiveRecord::Migration is deprecated
+merge_request: 25066
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/deprecated-passing-activerecord-objects.yml b/changelogs/unreleased/deprecated-passing-activerecord-objects.yml
deleted file mode 100644
index e58647186b8..00000000000
--- a/changelogs/unreleased/deprecated-passing-activerecord-objects.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Fix deprecation: Passing ActiveRecord::Base objects to sanitize_sql_hash_for_assignment'
-merge_request: 23818
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/deprecated-positional-seperator-parameter.yml b/changelogs/unreleased/deprecated-positional-seperator-parameter.yml
deleted file mode 100644
index 0d952e0d5eb..00000000000
--- a/changelogs/unreleased/deprecated-positional-seperator-parameter.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Passing the separator argument as a positional parameter is deprecated
-merge_request: 23334
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/diff-empty-state-fixes.yml b/changelogs/unreleased/diff-empty-state-fixes.yml
deleted file mode 100644
index 0d347dd17e4..00000000000
--- a/changelogs/unreleased/diff-empty-state-fixes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed merge request diffs empty states
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/diff-tree-resizable.yml b/changelogs/unreleased/diff-tree-resizable.yml
new file mode 100644
index 00000000000..7411640aea5
--- /dev/null
+++ b/changelogs/unreleased/diff-tree-resizable.yml
@@ -0,0 +1,5 @@
+---
+title: Make file tree in merge requests resizable
+merge_request:
+author:
+type: added
diff --git a/changelogs/unreleased/dm-note-email-image-diff-discussion.yml b/changelogs/unreleased/dm-note-email-image-diff-discussion.yml
deleted file mode 100644
index 6532052e132..00000000000
--- a/changelogs/unreleased/dm-note-email-image-diff-discussion.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix notification email for image diff notes
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/dz-sort-labels-alphabetically.yml b/changelogs/unreleased/dz-sort-labels-alphabetically.yml
new file mode 100644
index 00000000000..acfde3de999
--- /dev/null
+++ b/changelogs/unreleased/dz-sort-labels-alphabetically.yml
@@ -0,0 +1,5 @@
+---
+title: Sort labels alphabetically on issues and merge requests list
+merge_request: 25470
+author:
+type: changed
diff --git a/changelogs/unreleased/enable-markup-highlighting.yml b/changelogs/unreleased/enable-markup-highlighting.yml
new file mode 100644
index 00000000000..33fcf784f7d
--- /dev/null
+++ b/changelogs/unreleased/enable-markup-highlighting.yml
@@ -0,0 +1,5 @@
+---
+title: Enable syntax highlighting to other supported markups
+merge_request: 25761
+author:
+type: other
diff --git a/changelogs/unreleased/expose-additional-merge-request-pipeline-variables.yml b/changelogs/unreleased/expose-additional-merge-request-pipeline-variables.yml
new file mode 100644
index 00000000000..399f60ef219
--- /dev/null
+++ b/changelogs/unreleased/expose-additional-merge-request-pipeline-variables.yml
@@ -0,0 +1,5 @@
+---
+title: Expose additional merge request pipeline variables
+merge_request: 24595
+author: Hiroyuki Sato
+type: added
diff --git a/changelogs/unreleased/expose-merge-ref-to-runner.yml b/changelogs/unreleased/expose-merge-ref-to-runner.yml
new file mode 100644
index 00000000000..945f4f6e05a
--- /dev/null
+++ b/changelogs/unreleased/expose-merge-ref-to-runner.yml
@@ -0,0 +1,5 @@
+---
+title: Expose refspecs and depth to runner
+merge_request: 25233
+author:
+type: added
diff --git a/changelogs/unreleased/expose-merge-request-entity-for-pipelines.yml b/changelogs/unreleased/expose-merge-request-entity-for-pipelines.yml
new file mode 100644
index 00000000000..e5cbc87ba24
--- /dev/null
+++ b/changelogs/unreleased/expose-merge-request-entity-for-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Expose merge request entity for pipelines
+merge_request: 25679
+author:
+type: added
diff --git a/changelogs/unreleased/fast-destroy-uploads.yml b/changelogs/unreleased/fast-destroy-uploads.yml
new file mode 100644
index 00000000000..ee3363a6ae9
--- /dev/null
+++ b/changelogs/unreleased/fast-destroy-uploads.yml
@@ -0,0 +1,5 @@
+---
+title: File uploads are deleted asynchronously when deleting a project or group.
+merge_request:
+author:
+type: added
diff --git a/changelogs/unreleased/feature-api-delete-job-artifacts.yml b/changelogs/unreleased/feature-api-delete-job-artifacts.yml
new file mode 100644
index 00000000000..ddbbe3c2650
--- /dev/null
+++ b/changelogs/unreleased/feature-api-delete-job-artifacts.yml
@@ -0,0 +1,5 @@
+---
+title: Extend the Gitlab API for deletion of job_artifacts of a single job.
+merge_request: 25522
+author: rroger
+type: added
diff --git a/changelogs/unreleased/feature-gb-add-serverless-cicd-template.yml b/changelogs/unreleased/feature-gb-add-serverless-cicd-template.yml
new file mode 100644
index 00000000000..ebb71f00c4b
--- /dev/null
+++ b/changelogs/unreleased/feature-gb-add-serverless-cicd-template.yml
@@ -0,0 +1,5 @@
+---
+title: Simplify CI/CD configuration on serverless projects
+merge_request: 25523
+author:
+type: added
diff --git a/changelogs/unreleased/feature-gb-enable-ci-persisted-stages-by-default.yml b/changelogs/unreleased/feature-gb-enable-ci-persisted-stages-by-default.yml
new file mode 100644
index 00000000000..ad92135d401
--- /dev/null
+++ b/changelogs/unreleased/feature-gb-enable-ci-persisted-stages-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Enable persisted pipeline stages by default
+merge_request: 25347
+author:
+type: performance
diff --git a/changelogs/unreleased/feature-option-to-make-variables-protected.yml b/changelogs/unreleased/feature-option-to-make-variables-protected.yml
deleted file mode 100644
index c99c0481c35..00000000000
--- a/changelogs/unreleased/feature-option-to-make-variables-protected.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add option to make ci variables protected by default
-merge_request: 22744
-author: Alexis Reigel
-type: added
diff --git a/changelogs/unreleased/feature-runner-tag-filter-for-admin-view.yml b/changelogs/unreleased/feature-runner-tag-filter-for-admin-view.yml
new file mode 100644
index 00000000000..86df4595e7b
--- /dev/null
+++ b/changelogs/unreleased/feature-runner-tag-filter-for-admin-view.yml
@@ -0,0 +1,5 @@
+---
+title: Add a tag filter to the admin runners view
+merge_request: 19740
+author: Alexis Reigel
+type: added
diff --git a/changelogs/unreleased/filter-confidential-issues.yml b/changelogs/unreleased/filter-confidential-issues.yml
new file mode 100644
index 00000000000..83f19a57aab
--- /dev/null
+++ b/changelogs/unreleased/filter-confidential-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Ability to filter confidential issues
+merge_request: 24960
+author: Robert Schilling
+type: added
diff --git a/changelogs/unreleased/filter-note-parameters.yml b/changelogs/unreleased/filter-note-parameters.yml
new file mode 100644
index 00000000000..fca2a394820
--- /dev/null
+++ b/changelogs/unreleased/filter-note-parameters.yml
@@ -0,0 +1,5 @@
+---
+title: Include note in the Rails filter_parameters configuration
+merge_request: 25238
+author:
+type: other
diff --git a/changelogs/unreleased/fix-38010-sidebar-loads-and-collapses.yml b/changelogs/unreleased/fix-38010-sidebar-loads-and-collapses.yml
new file mode 100644
index 00000000000..af80a069fde
--- /dev/null
+++ b/changelogs/unreleased/fix-38010-sidebar-loads-and-collapses.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed navigation sidebar flashing open on page load
+merge_request: 24555
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-55448.yml b/changelogs/unreleased/fix-55448.yml
deleted file mode 100644
index e0bdbb6eda4..00000000000
--- a/changelogs/unreleased/fix-55448.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove deprecated xhr from specs
-merge_request: 23949
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/fix-badges-logs.yml b/changelogs/unreleased/fix-badges-logs.yml
new file mode 100644
index 00000000000..6236e7b046d
--- /dev/null
+++ b/changelogs/unreleased/fix-badges-logs.yml
@@ -0,0 +1,5 @@
+---
+title: Doc - fix the url of pipeline status badge
+merge_request: 25404
+author: Aviad Levy
+type: fixed
diff --git a/changelogs/unreleased/fix-calendar-events-fetching-error.yml b/changelogs/unreleased/fix-calendar-events-fetching-error.yml
deleted file mode 100644
index ad4a40cd9a0..00000000000
--- a/changelogs/unreleased/fix-calendar-events-fetching-error.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix calendar events fetching error on private profile page
-merge_request: 23718
-author: Harry Kiselev
-type: other
diff --git a/changelogs/unreleased/fix-gb-fix-bridge-jobs-variables-policy.yml b/changelogs/unreleased/fix-gb-fix-bridge-jobs-variables-policy.yml
new file mode 100644
index 00000000000..8a98a39fdc2
--- /dev/null
+++ b/changelogs/unreleased/fix-gb-fix-bridge-jobs-variables-policy.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bridge jobs only/except variables policy
+merge_request: 25710
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-group-without-owner.yml b/changelogs/unreleased/fix-group-without-owner.yml
new file mode 100644
index 00000000000..884f1b3a08a
--- /dev/null
+++ b/changelogs/unreleased/fix-group-without-owner.yml
@@ -0,0 +1,5 @@
+---
+title: fix group without owner after transfer
+merge_request: 25573
+author: Peter Marko
+type: fixed
diff --git a/changelogs/unreleased/fix-n-plus-1-queries-projects.yml b/changelogs/unreleased/fix-n-plus-1-queries-projects.yml
deleted file mode 100644
index cb625784267..00000000000
--- a/changelogs/unreleased/fix-n-plus-1-queries-projects.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fix some N+1 queries related to Admin Dashboard, User Dashboards and Activity
- Stream
-merge_request: 23034
-author:
-type: performance
diff --git a/changelogs/unreleased/fix_-56347.yml b/changelogs/unreleased/fix_-56347.yml
new file mode 100644
index 00000000000..1d03ed8864c
--- /dev/null
+++ b/changelogs/unreleased/fix_-56347.yml
@@ -0,0 +1,5 @@
+---
+title: Fix overlapping empty-header logo
+merge_request: 24868
+author: Jonas L.
+type: fixed
diff --git a/changelogs/unreleased/force-reload-arguments-2.yml b/changelogs/unreleased/force-reload-arguments-2.yml
deleted file mode 100644
index 23ab9433b3d..00000000000
--- a/changelogs/unreleased/force-reload-arguments-2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Passing an argument to force an association to reload is now deprecated
-merge_request: 23894
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/gitlab_kubernetes_helm_bump.yml b/changelogs/unreleased/gitlab_kubernetes_helm_bump.yml
new file mode 100644
index 00000000000..b8668d338de
--- /dev/null
+++ b/changelogs/unreleased/gitlab_kubernetes_helm_bump.yml
@@ -0,0 +1,5 @@
+---
+title: Bump Helm and kubectl used in Kubernetes integration to 2.12.3 and 1.11.7 respectively
+merge_request: 25268
+author:
+type: other
diff --git a/changelogs/unreleased/gokhanap-master-patch-03762.yml b/changelogs/unreleased/gokhanap-master-patch-03762.yml
new file mode 100644
index 00000000000..22ab453e359
--- /dev/null
+++ b/changelogs/unreleased/gokhanap-master-patch-03762.yml
@@ -0,0 +1,5 @@
+---
+title: 'commit page info-well overflow fix #56436'
+merge_request: 24799
+author: Gokhan Apaydin
+type: fixed
diff --git a/changelogs/unreleased/gt-externalize-app-views-projects-commit.yml b/changelogs/unreleased/gt-externalize-app-views-projects-commit.yml
new file mode 100644
index 00000000000..29dbf2367b7
--- /dev/null
+++ b/changelogs/unreleased/gt-externalize-app-views-projects-commit.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings from `/app/views/projects/commit`
+merge_request: 24668
+author: George Tsiolis
+type: other
diff --git a/changelogs/unreleased/gt-remove-unnecessary-line-before-reply-holder.yml b/changelogs/unreleased/gt-remove-unnecessary-line-before-reply-holder.yml
deleted file mode 100644
index 142a9c1f2cc..00000000000
--- a/changelogs/unreleased/gt-remove-unnecessary-line-before-reply-holder.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove unnecessary line before reply holder
-merge_request: 23092
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/gt-update-environment-breadcrumb.yml b/changelogs/unreleased/gt-update-environment-breadcrumb.yml
deleted file mode 100644
index 53b9673a96c..00000000000
--- a/changelogs/unreleased/gt-update-environment-breadcrumb.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update environments breadcrumb
-merge_request: 23751
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/gt-update-navigation-theme-colors.yml b/changelogs/unreleased/gt-update-navigation-theme-colors.yml
deleted file mode 100644
index 749587a6343..00000000000
--- a/changelogs/unreleased/gt-update-navigation-theme-colors.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update header navigation theme colors
-merge_request: 23734
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/gt-update-new-password-breadcrumb.yml b/changelogs/unreleased/gt-update-new-password-breadcrumb.yml
new file mode 100644
index 00000000000..43ea2f0d44b
--- /dev/null
+++ b/changelogs/unreleased/gt-update-new-password-breadcrumb.yml
@@ -0,0 +1,5 @@
+---
+title: Update new password breadcrumb
+merge_request: 25037
+author: George Tsiolis
+type: fixed
diff --git a/changelogs/unreleased/gt-update-operations-settings-breadcrumb-trail.yml b/changelogs/unreleased/gt-update-operations-settings-breadcrumb-trail.yml
new file mode 100644
index 00000000000..f7b10ea5c17
--- /dev/null
+++ b/changelogs/unreleased/gt-update-operations-settings-breadcrumb-trail.yml
@@ -0,0 +1,5 @@
+---
+title: Update operations settings breadcrumb trail
+merge_request: 25539
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/helm-2-12-3.yml b/changelogs/unreleased/helm-2-12-3.yml
new file mode 100644
index 00000000000..0d0d904a9cb
--- /dev/null
+++ b/changelogs/unreleased/helm-2-12-3.yml
@@ -0,0 +1,5 @@
+---
+title: Bump Helm and kubectl in Auto DevOps to 2.12.3 and 1.11.7 respectively
+merge_request: 25072
+author:
+type: other
diff --git a/changelogs/unreleased/import-go-to-project-cta.yml b/changelogs/unreleased/import-go-to-project-cta.yml
new file mode 100644
index 00000000000..ae719f08790
--- /dev/null
+++ b/changelogs/unreleased/import-go-to-project-cta.yml
@@ -0,0 +1,5 @@
+---
+title: Improve GitHub and Gitea project import table UI
+merge_request: 24606
+author:
+type: other
diff --git a/changelogs/unreleased/improve-performance-for-diverging-commit-counts.yml b/changelogs/unreleased/improve-performance-for-diverging-commit-counts.yml
new file mode 100644
index 00000000000..76ff15cba5b
--- /dev/null
+++ b/changelogs/unreleased/improve-performance-for-diverging-commit-counts.yml
@@ -0,0 +1,5 @@
+---
+title: Improve performance for diverging commit counts
+merge_request: 24287
+author:
+type: performance
diff --git a/changelogs/unreleased/improve-snippets-empty-state.yml b/changelogs/unreleased/improve-snippets-empty-state.yml
new file mode 100644
index 00000000000..9859243a81f
--- /dev/null
+++ b/changelogs/unreleased/improve-snippets-empty-state.yml
@@ -0,0 +1,5 @@
+---
+title: Improve snippets empty state
+merge_request: 18348
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/include-ci-yaml.yml b/changelogs/unreleased/include-ci-yaml.yml
new file mode 100644
index 00000000000..5909950ef0b
--- /dev/null
+++ b/changelogs/unreleased/include-ci-yaml.yml
@@ -0,0 +1,5 @@
+---
+title: Validate 'include' keywords in gitlab-ci.yml configuration files.
+merge_request: 24098
+author: Paul Bonaud
+type: fixed
diff --git a/changelogs/unreleased/jc-fix-set-project-writable.yml b/changelogs/unreleased/jc-fix-set-project-writable.yml
new file mode 100644
index 00000000000..0bfd90c3967
--- /dev/null
+++ b/changelogs/unreleased/jc-fix-set-project-writable.yml
@@ -0,0 +1,5 @@
+---
+title: Fix method to mark a project repository as writable
+merge_request: 25546
+author:
+type: fixed
diff --git a/changelogs/unreleased/jej-feature-gates-can-be-set-by-group-path.yml b/changelogs/unreleased/jej-feature-gates-can-be-set-by-group-path.yml
new file mode 100644
index 00000000000..ba882112f70
--- /dev/null
+++ b/changelogs/unreleased/jej-feature-gates-can-be-set-by-group-path.yml
@@ -0,0 +1,5 @@
+---
+title: Allow setting feature flags per GitLab group through the API
+merge_request: 25022
+author:
+type: added
diff --git a/changelogs/unreleased/jira-link-mention-compact.yml b/changelogs/unreleased/jira-link-mention-compact.yml
new file mode 100644
index 00000000000..f75f3ce183c
--- /dev/null
+++ b/changelogs/unreleased/jira-link-mention-compact.yml
@@ -0,0 +1,5 @@
+---
+title: "Jira: make issue links title compact"
+merge_request: 25609
+author: Elan Ruusamäe @glensc
+type: changed
diff --git a/changelogs/unreleased/jlenny-CI_COMMIT_SHORT_SHA.yml b/changelogs/unreleased/jlenny-CI_COMMIT_SHORT_SHA.yml
deleted file mode 100644
index abece81a20d..00000000000
--- a/changelogs/unreleased/jlenny-CI_COMMIT_SHORT_SHA.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add new pipeline variable CI_COMMIT_SHORT_SHA
-merge_request: 23822
-author:
-type: added
diff --git a/changelogs/unreleased/kinolaev-master-patch-87865.yml b/changelogs/unreleased/kinolaev-master-patch-87865.yml
new file mode 100644
index 00000000000..b4dbc2c0e1f
--- /dev/null
+++ b/changelogs/unreleased/kinolaev-master-patch-87865.yml
@@ -0,0 +1,5 @@
+---
+title: Fix rollout status for statefulsets and daemonsets
+merge_request: 24972
+author: Sergej Nikolaev <kinolaev@gmail.com>
+type: fixed
diff --git a/changelogs/unreleased/markdown-toolbar-btn-fix.yml b/changelogs/unreleased/markdown-toolbar-btn-fix.yml
deleted file mode 100644
index eefb4d19f86..00000000000
--- a/changelogs/unreleased/markdown-toolbar-btn-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed markdown toolbar buttons
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/mk-avoid-read-only-error.yml b/changelogs/unreleased/mk-avoid-read-only-error.yml
deleted file mode 100644
index 8641f5db9f0..00000000000
--- a/changelogs/unreleased/mk-avoid-read-only-error.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent admins from attempting hashed storage migration on read only DB
-merge_request: 23597
-author:
-type: fixed
diff --git a/changelogs/unreleased/move_chatops_to_core.yml b/changelogs/unreleased/move_chatops_to_core.yml
new file mode 100644
index 00000000000..7a75efedfa8
--- /dev/null
+++ b/changelogs/unreleased/move_chatops_to_core.yml
@@ -0,0 +1,5 @@
+---
+title: Move ChatOps to Core
+merge_request: 24780
+author:
+type: changed
diff --git a/changelogs/unreleased/none-syntax-highlighting.yml b/changelogs/unreleased/none-syntax-highlighting.yml
deleted file mode 100644
index b373aac7c02..00000000000
--- a/changelogs/unreleased/none-syntax-highlighting.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add no-color theme for syntax highlighting.
-merge_request: !20170
-author: khm
-type: added
diff --git a/changelogs/unreleased/osw-create-and-store-merge-ref-for-mrs.yml b/changelogs/unreleased/osw-create-and-store-merge-ref-for-mrs.yml
new file mode 100644
index 00000000000..012b547a630
--- /dev/null
+++ b/changelogs/unreleased/osw-create-and-store-merge-ref-for-mrs.yml
@@ -0,0 +1,5 @@
+---
+title: Support merge ref writing (without merging to target branch)
+merge_request: 24692
+author:
+type: added
diff --git a/changelogs/unreleased/osw-fetch-latest-version-when-creating-suggestions.yml b/changelogs/unreleased/osw-fetch-latest-version-when-creating-suggestions.yml
new file mode 100644
index 00000000000..4e01a13d781
--- /dev/null
+++ b/changelogs/unreleased/osw-fetch-latest-version-when-creating-suggestions.yml
@@ -0,0 +1,5 @@
+---
+title: Always fetch MR latest version when creating suggestions
+merge_request: 25441
+author:
+type: fixed
diff --git a/changelogs/unreleased/osw-merge-refs-refreshing-api.yml b/changelogs/unreleased/osw-merge-refs-refreshing-api.yml
new file mode 100644
index 00000000000..095600cd088
--- /dev/null
+++ b/changelogs/unreleased/osw-merge-refs-refreshing-api.yml
@@ -0,0 +1,5 @@
+---
+title: API support for MR merge to temporary merge ref path
+merge_request: 24918
+author:
+type: added
diff --git a/changelogs/unreleased/patch-45.yml b/changelogs/unreleased/patch-45.yml
new file mode 100644
index 00000000000..94fa1d29b32
--- /dev/null
+++ b/changelogs/unreleased/patch-45.yml
@@ -0,0 +1,5 @@
+---
+title: Fix incorrect Pages Domains checkbox description.
+merge_request: 25392
+author: Anton Melser
+type: other
diff --git a/changelogs/unreleased/persist-source-sha-and-target-sha-for-pipelines.yml b/changelogs/unreleased/persist-source-sha-and-target-sha-for-pipelines.yml
new file mode 100644
index 00000000000..6957d156161
--- /dev/null
+++ b/changelogs/unreleased/persist-source-sha-and-target-sha-for-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Persist source sha and target sha for merge pipelines
+merge_request: 25417
+author:
+type: added
diff --git a/changelogs/unreleased/ravlen-fix-spaces-unicode.yml b/changelogs/unreleased/ravlen-fix-spaces-unicode.yml
new file mode 100644
index 00000000000..fbcbdc53cfe
--- /dev/null
+++ b/changelogs/unreleased/ravlen-fix-spaces-unicode.yml
@@ -0,0 +1,5 @@
+---
+title: Correct non-standard unicode spaces to regular unicode
+merge_request: 24795
+author: Marcel Amirault
+type: other
diff --git a/changelogs/unreleased/refactor-56367-extract-resolve-with-issue-button-component.yml b/changelogs/unreleased/refactor-56367-extract-resolve-with-issue-button-component.yml
new file mode 100644
index 00000000000..082075506c0
--- /dev/null
+++ b/changelogs/unreleased/refactor-56367-extract-resolve-with-issue-button-component.yml
@@ -0,0 +1,5 @@
+---
+title: Extracted ResolveWithIssueButton to its own component
+merge_request: 25093
+author: Martin Hobert
+type: other
diff --git a/changelogs/unreleased/refactor-merge-request-between-pipeline-and-build.yml b/changelogs/unreleased/refactor-merge-request-between-pipeline-and-build.yml
new file mode 100644
index 00000000000..bf78f8d84a6
--- /dev/null
+++ b/changelogs/unreleased/refactor-merge-request-between-pipeline-and-build.yml
@@ -0,0 +1,5 @@
+---
+title: Add suffix (`_event`) to merge request source
+merge_request: 25508
+author:
+type: other
diff --git a/changelogs/unreleased/remote-mirror-update-failed-notification.yml b/changelogs/unreleased/remote-mirror-update-failed-notification.yml
deleted file mode 100644
index 50ec8624ae5..00000000000
--- a/changelogs/unreleased/remote-mirror-update-failed-notification.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Send a notification email to project maintainers when a mirror update fails
-merge_request: 23595
-author:
-type: added
diff --git a/changelogs/unreleased/remove-rails4-specific-code.yml b/changelogs/unreleased/remove-rails4-specific-code.yml
deleted file mode 100644
index c6c4c0a5d5b..00000000000
--- a/changelogs/unreleased/remove-rails4-specific-code.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove rails4 specific code
-merge_request: 23847
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/remove-rails4-support.yml b/changelogs/unreleased/remove-rails4-support.yml
deleted file mode 100644
index a05c913a70c..00000000000
--- a/changelogs/unreleased/remove-rails4-support.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove rails 4 support in CI, Gemfiles, bin/ and config/
-merge_request: 23717
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/remove-second-primary-button-on-wiki-edit.yml b/changelogs/unreleased/remove-second-primary-button-on-wiki-edit.yml
new file mode 100644
index 00000000000..045fbbb48b7
--- /dev/null
+++ b/changelogs/unreleased/remove-second-primary-button-on-wiki-edit.yml
@@ -0,0 +1,5 @@
+---
+title: Remove second primary button on wiki edit
+merge_request: 19959
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/rs-admin-user-case-insensitive.yml b/changelogs/unreleased/rs-admin-user-case-insensitive.yml
new file mode 100644
index 00000000000..40398c46a1e
--- /dev/null
+++ b/changelogs/unreleased/rs-admin-user-case-insensitive.yml
@@ -0,0 +1,5 @@
+---
+title: Admin section finds users case-insensitively
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/security-2774-milestones-detail.yml b/changelogs/unreleased/security-2774-milestones-detail.yml
new file mode 100644
index 00000000000..faf56fee01e
--- /dev/null
+++ b/changelogs/unreleased/security-2774-milestones-detail.yml
@@ -0,0 +1,5 @@
+---
+title: Display only information visible to current user on the Milestone page
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-2797-milestone-mrs.yml b/changelogs/unreleased/security-2797-milestone-mrs.yml
new file mode 100644
index 00000000000..5bb104ec403
--- /dev/null
+++ b/changelogs/unreleased/security-2797-milestone-mrs.yml
@@ -0,0 +1,5 @@
+---
+title: Show only merge requests visible to user on milestone detail page
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-2798-fix-boards-policy.yml b/changelogs/unreleased/security-2798-fix-boards-policy.yml
new file mode 100644
index 00000000000..10e8ac3a787
--- /dev/null
+++ b/changelogs/unreleased/security-2798-fix-boards-policy.yml
@@ -0,0 +1,5 @@
+---
+title: Disable issue boards API when issues are disabled
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-2799-emails.yml b/changelogs/unreleased/security-2799-emails.yml
new file mode 100644
index 00000000000..dbf1207810e
--- /dev/null
+++ b/changelogs/unreleased/security-2799-emails.yml
@@ -0,0 +1,5 @@
+---
+title: Don't show new issue link after move when a user does not have permissions
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-50334.yml b/changelogs/unreleased/security-50334.yml
new file mode 100644
index 00000000000..828ef82b517
--- /dev/null
+++ b/changelogs/unreleased/security-50334.yml
@@ -0,0 +1,5 @@
+---
+title: Fix git clone revealing private repo's presence
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-55468-check-validity-before-querying.yml b/changelogs/unreleased/security-55468-check-validity-before-querying.yml
new file mode 100644
index 00000000000..8bb11a97f52
--- /dev/null
+++ b/changelogs/unreleased/security-55468-check-validity-before-querying.yml
@@ -0,0 +1,5 @@
+---
+title: Fix blind SSRF in Prometheus integration by checking URL before querying
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-56348.yml b/changelogs/unreleased/security-56348.yml
new file mode 100644
index 00000000000..a289e4e9077
--- /dev/null
+++ b/changelogs/unreleased/security-56348.yml
@@ -0,0 +1,5 @@
+---
+title: Check snippet attached file to be moved is within designated directory
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-commit-private-related-mr.yml b/changelogs/unreleased/security-commit-private-related-mr.yml
new file mode 100644
index 00000000000..c4de200b0d8
--- /dev/null
+++ b/changelogs/unreleased/security-commit-private-related-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Don't allow non-members to see private related MRs.
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-fj-diff-import-file-read-fix.yml b/changelogs/unreleased/security-fj-diff-import-file-read-fix.yml
new file mode 100644
index 00000000000..e98d4e89712
--- /dev/null
+++ b/changelogs/unreleased/security-fj-diff-import-file-read-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fix arbitrary file read via diffs during import
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-id-fix-mr-visibility.yml b/changelogs/unreleased/security-id-fix-mr-visibility.yml
new file mode 100644
index 00000000000..8f41d191acc
--- /dev/null
+++ b/changelogs/unreleased/security-id-fix-mr-visibility.yml
@@ -0,0 +1,5 @@
+---
+title: Display the correct number of MRs a user has access to
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-id-restricted-access-to-private-repo.yml b/changelogs/unreleased/security-id-restricted-access-to-private-repo.yml
new file mode 100644
index 00000000000..7d7478d297b
--- /dev/null
+++ b/changelogs/unreleased/security-id-restricted-access-to-private-repo.yml
@@ -0,0 +1,5 @@
+---
+title: Forbid creating discussions for users with restricted access
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-issue_54789_2.yml b/changelogs/unreleased/security-issue_54789_2.yml
new file mode 100644
index 00000000000..8ecb72a2ae3
--- /dev/null
+++ b/changelogs/unreleased/security-issue_54789_2.yml
@@ -0,0 +1,5 @@
+---
+title: Do not disclose milestone titles for unauthorized users
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-kubernetes-google-login-csrf.yml b/changelogs/unreleased/security-kubernetes-google-login-csrf.yml
new file mode 100644
index 00000000000..2f87100a8dd
--- /dev/null
+++ b/changelogs/unreleased/security-kubernetes-google-login-csrf.yml
@@ -0,0 +1,5 @@
+---
+title: Validate session key when authorizing with GCP to create a cluster
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-kubernetes-local-ssrf.yml b/changelogs/unreleased/security-kubernetes-local-ssrf.yml
new file mode 100644
index 00000000000..7a2ad092339
--- /dev/null
+++ b/changelogs/unreleased/security-kubernetes-local-ssrf.yml
@@ -0,0 +1,5 @@
+---
+title: Block local URLs for Kubernetes integration
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-mermaid.yml b/changelogs/unreleased/security-mermaid.yml
new file mode 100644
index 00000000000..ec42b5a1615
--- /dev/null
+++ b/changelogs/unreleased/security-mermaid.yml
@@ -0,0 +1,5 @@
+---
+title: Limit mermaid rendering to 5K characters
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-osw-stop-linking-to-packages.yml b/changelogs/unreleased/security-osw-stop-linking-to-packages.yml
new file mode 100644
index 00000000000..078f06140fe
--- /dev/null
+++ b/changelogs/unreleased/security-osw-stop-linking-to-packages.yml
@@ -0,0 +1,5 @@
+---
+title: Stop linking to unrecognized package sources
+merge_request: 55518
+author:
+type: security
diff --git a/changelogs/unreleased/security-protect-private-repo-information.yml b/changelogs/unreleased/security-protect-private-repo-information.yml
new file mode 100644
index 00000000000..8b1a528206d
--- /dev/null
+++ b/changelogs/unreleased/security-protect-private-repo-information.yml
@@ -0,0 +1,5 @@
+---
+title: Fix leaking private repository information in API
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-shared-project-private-group.yml b/changelogs/unreleased/security-shared-project-private-group.yml
new file mode 100644
index 00000000000..3b21daa5491
--- /dev/null
+++ b/changelogs/unreleased/security-shared-project-private-group.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed ability to see private groups by users not belonging to given group
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-tags-oracle.yml b/changelogs/unreleased/security-tags-oracle.yml
new file mode 100644
index 00000000000..eb8ad6f646c
--- /dev/null
+++ b/changelogs/unreleased/security-tags-oracle.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent releases links API to leak tag existance
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/sh-bump-fog-gem.yml b/changelogs/unreleased/sh-bump-fog-gem.yml
new file mode 100644
index 00000000000..6a26d5c6488
--- /dev/null
+++ b/changelogs/unreleased/sh-bump-fog-gem.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes issue with AWS V4 signatures not working with some S3 providers
+merge_request: 21788
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-cache-avatar-paths.yml b/changelogs/unreleased/sh-cache-avatar-paths.yml
deleted file mode 100644
index b59a4db413d..00000000000
--- a/changelogs/unreleased/sh-cache-avatar-paths.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cache avatar URLs and paths within a request
-merge_request: 23950
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-carrierwave-patch-google-acl.yml b/changelogs/unreleased/sh-carrierwave-patch-google-acl.yml
deleted file mode 100644
index 206253a100c..00000000000
--- a/changelogs/unreleased/sh-carrierwave-patch-google-acl.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix object storage not working properly with Google S3 compatibility
-merge_request: 23858
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-cpp-templates-404.yml b/changelogs/unreleased/sh-fix-cpp-templates-404.yml
new file mode 100644
index 00000000000..ac958d84099
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-cpp-templates-404.yml
@@ -0,0 +1,5 @@
+---
+title: Fix 404s when C++ .gitignore template selected
+merge_request: 25416
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-double-xhr-pipelines.yml b/changelogs/unreleased/sh-fix-double-xhr-pipelines.yml
new file mode 100644
index 00000000000..e6c762f1d47
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-double-xhr-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicate XHR request when requesting new pipeline page
+merge_request: 25506
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-github-import-without-oauth2-config.yml b/changelogs/unreleased/sh-fix-github-import-without-oauth2-config.yml
deleted file mode 100644
index ad548a6ff35..00000000000
--- a/changelogs/unreleased/sh-fix-github-import-without-oauth2-config.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow GitHub imports via token even if OAuth2 provider not configured
-merge_request: 23703
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-http-clone-panel.yml b/changelogs/unreleased/sh-fix-http-clone-panel.yml
deleted file mode 100644
index ab220bd5076..00000000000
--- a/changelogs/unreleased/sh-fix-http-clone-panel.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix missing Git clone button when protocol restriction setting enabled
-merge_request: 24015
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-58103.yml b/changelogs/unreleased/sh-fix-issue-58103.yml
new file mode 100644
index 00000000000..1599af23fed
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-58103.yml
@@ -0,0 +1,5 @@
+---
+title: Properly handle multiple X-Forwarded-For addresses in runner IP
+merge_request: 25511
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-include-project-path-for-internal-api.yml b/changelogs/unreleased/sh-include-project-path-for-internal-api.yml
new file mode 100644
index 00000000000..1973049e9e3
--- /dev/null
+++ b/changelogs/unreleased/sh-include-project-path-for-internal-api.yml
@@ -0,0 +1,5 @@
+---
+title: Include gl_project_path in API /internal/allowed response
+merge_request: 25314
+author:
+type: other
diff --git a/changelogs/unreleased/sh-log-rails-queue-duration.yml b/changelogs/unreleased/sh-log-rails-queue-duration.yml
new file mode 100644
index 00000000000..89390aef108
--- /dev/null
+++ b/changelogs/unreleased/sh-log-rails-queue-duration.yml
@@ -0,0 +1,5 @@
+---
+title: Log queue duration in production_json.log
+merge_request: 25075
+author:
+type: other
diff --git a/changelogs/unreleased/sh-optimize-calendar-activities.yml b/changelogs/unreleased/sh-optimize-calendar-activities.yml
new file mode 100644
index 00000000000..b8500357e17
--- /dev/null
+++ b/changelogs/unreleased/sh-optimize-calendar-activities.yml
@@ -0,0 +1,5 @@
+---
+title: Eliminate most N+1 queries loading UserController#calendar_activities
+merge_request: 25697
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-remove-nplusone-admin-runners-tags.yml b/changelogs/unreleased/sh-remove-nplusone-admin-runners-tags.yml
new file mode 100644
index 00000000000..f8ac345bc95
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-nplusone-admin-runners-tags.yml
@@ -0,0 +1,5 @@
+---
+title: Remove N+1 query for tags in /admin/runners page
+merge_request: 25572
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-rugged-find-commit.yml b/changelogs/unreleased/sh-rugged-find-commit.yml
new file mode 100644
index 00000000000..85b5936c9ba
--- /dev/null
+++ b/changelogs/unreleased/sh-rugged-find-commit.yml
@@ -0,0 +1,5 @@
+---
+title: Bring back Rugged implementation of find_commit
+merge_request: 25477
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-show-pre-receive-error-merge.yml b/changelogs/unreleased/sh-show-pre-receive-error-merge.yml
new file mode 100644
index 00000000000..5e662b34773
--- /dev/null
+++ b/changelogs/unreleased/sh-show-pre-receive-error-merge.yml
@@ -0,0 +1,5 @@
+---
+title: Show pre-receive error message when merge fails
+merge_request: 25708
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-wip-fix-duplicate-env-xhr.yml b/changelogs/unreleased/sh-wip-fix-duplicate-env-xhr.yml
new file mode 100644
index 00000000000..e7900e2230d
--- /dev/null
+++ b/changelogs/unreleased/sh-wip-fix-duplicate-env-xhr.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pagination and duplicate requests in environments page
+merge_request: 25582
+author:
+type: fixed
diff --git a/changelogs/unreleased/shell-8-7.yml b/changelogs/unreleased/shell-8-7.yml
new file mode 100644
index 00000000000..c2dd0c1f1bb
--- /dev/null
+++ b/changelogs/unreleased/shell-8-7.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Shell to v8.7.1
+merge_request: 25801
+author:
+type: other
diff --git a/changelogs/unreleased/spec-positional-arguments.yml b/changelogs/unreleased/spec-positional-arguments.yml
deleted file mode 100644
index 9dc114e5595..00000000000
--- a/changelogs/unreleased/spec-positional-arguments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Fix deprecation: Using positional arguments in integration tests'
-merge_request: 24009
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/specs-positional-arguments.yml b/changelogs/unreleased/specs-positional-arguments.yml
deleted file mode 100644
index 38b831bd72c..00000000000
--- a/changelogs/unreleased/specs-positional-arguments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: convert specs in javascripts/ and support/ to new syntax
-merge_request: 23947
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/support-gitaly-tls.yml b/changelogs/unreleased/support-gitaly-tls.yml
deleted file mode 100644
index 2a15500d6da..00000000000
--- a/changelogs/unreleased/support-gitaly-tls.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Support tls communication in gitaly
-merge_request: 22602
-author:
-type: added
diff --git a/changelogs/unreleased/support-only-changes-on-mr-pipelines.yml b/changelogs/unreleased/support-only-changes-on-mr-pipelines.yml
new file mode 100644
index 00000000000..fbab898b799
--- /dev/null
+++ b/changelogs/unreleased/support-only-changes-on-mr-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: 'Support `only: changes:` on MR pipelines'
+merge_request: 24490
+author: Hiroyuki Sato
+type: added
diff --git a/changelogs/unreleased/table-fix-scroll-and-block.yml b/changelogs/unreleased/table-fix-scroll-and-block.yml
new file mode 100644
index 00000000000..e6def0468b8
--- /dev/null
+++ b/changelogs/unreleased/table-fix-scroll-and-block.yml
@@ -0,0 +1,5 @@
+---
+title: Fix large table horizontal scroll and prevent side-by-side tables
+merge_request: 25520
+author: Dany Jupille
+type: fixed
diff --git a/changelogs/unreleased/tr-error-tracking-project-selection.yml b/changelogs/unreleased/tr-error-tracking-project-selection.yml
new file mode 100644
index 00000000000..36cfe4556bb
--- /dev/null
+++ b/changelogs/unreleased/tr-error-tracking-project-selection.yml
@@ -0,0 +1,5 @@
+---
+title: Error tracking configuration - add a Sentry project selection dropdown
+merge_request: 24701
+author:
+type: changed
diff --git a/changelogs/unreleased/triggermesh-knative-version.yml b/changelogs/unreleased/triggermesh-knative-version.yml
deleted file mode 100644
index 27f400962da..00000000000
--- a/changelogs/unreleased/triggermesh-knative-version.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Knative version bump 0.1.3 -> 0.2.2
-merge_request:
-author: Chris Baumbauer
-type: changed
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-2-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-2-0.yml
new file mode 100644
index 00000000000..3bf55630c4d
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-2-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.2.0
+merge_request: 25493
+author:
+type: other
diff --git a/changelogs/unreleased/use-encrypted-runner-tokens.yml b/changelogs/unreleased/use-encrypted-runner-tokens.yml
new file mode 100644
index 00000000000..e01978557bf
--- /dev/null
+++ b/changelogs/unreleased/use-encrypted-runner-tokens.yml
@@ -0,0 +1,5 @@
+---
+title: Use encrypted runner tokens
+merge_request: 25532
+author:
+type: security
diff --git a/changelogs/unreleased/web-ide-commit-header-icon-alignment-fix.yml b/changelogs/unreleased/web-ide-commit-header-icon-alignment-fix.yml
new file mode 100644
index 00000000000..7a6bda1580d
--- /dev/null
+++ b/changelogs/unreleased/web-ide-commit-header-icon-alignment-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed alignment of changed icon in Web IDE
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/web-ide-default-editor.yml b/changelogs/unreleased/web-ide-default-editor.yml
new file mode 100644
index 00000000000..b98be5c16c2
--- /dev/null
+++ b/changelogs/unreleased/web-ide-default-editor.yml
@@ -0,0 +1,5 @@
+---
+title: Make the Web IDE the default editor
+merge_request:
+author:
+type: added
diff --git a/changelogs/unreleased/winh-dropdown-title-padding.yml b/changelogs/unreleased/winh-dropdown-title-padding.yml
deleted file mode 100644
index 9d65175b536..00000000000
--- a/changelogs/unreleased/winh-dropdown-title-padding.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adjust padding of .dropdown-title to comply with design specs
-merge_request: 23546
-author:
-type: changed
diff --git a/changelogs/unreleased/winh-merge-request-commit-context.yml b/changelogs/unreleased/winh-merge-request-commit-context.yml
deleted file mode 100644
index 9e12a926af4..00000000000
--- a/changelogs/unreleased/winh-merge-request-commit-context.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display commit ID for discussions made on merge request commits
-merge_request: 23837
-author:
-type: fixed
diff --git a/changelogs/unreleased/winh-princess-mononospace.yml b/changelogs/unreleased/winh-princess-mononospace.yml
deleted file mode 100644
index e2d33de375e..00000000000
--- a/changelogs/unreleased/winh-princess-mononospace.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make commit IDs in merge request discussion header monospace
-merge_request: 23562
-author:
-type: changed
diff --git a/changelogs/unreleased/winh-upgrade-gitlab-ui.yml b/changelogs/unreleased/winh-upgrade-gitlab-ui.yml
deleted file mode 100644
index b312a329f5d..00000000000
--- a/changelogs/unreleased/winh-upgrade-gitlab-ui.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade @gitlab/ui to 1.16.2
-merge_request: 23946
-author:
-type: other
diff --git a/changelogs/unreleased/zj-backup-restore-object-pools.yml b/changelogs/unreleased/zj-backup-restore-object-pools.yml
deleted file mode 100644
index 26e1d49aa04..00000000000
--- a/changelogs/unreleased/zj-backup-restore-object-pools.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Restore Object Pools when restoring an object pool
-merge_request: 23682
-author:
-type: added
diff --git a/changelogs/unreleased/zj-load-languages-from-database.yml b/changelogs/unreleased/zj-load-languages-from-database.yml
new file mode 100644
index 00000000000..1688829b42c
--- /dev/null
+++ b/changelogs/unreleased/zj-load-languages-from-database.yml
@@ -0,0 +1,5 @@
+---
+title: Load repository language from the database if detected before
+merge_request: 25518
+author:
+type: performance
diff --git a/config.ru b/config.ru
index a5d055334dd..5cd79870d54 100644
--- a/config.ru
+++ b/config.ru
@@ -19,7 +19,7 @@ if defined?(Unicorn)
Unicorn::StreamInput.send(:public, :eof?) # rubocop:disable GitlabSecurity/PublicSend
end
-require ::File.expand_path('../config/environment', __FILE__)
+require ::File.expand_path('../config/environment', __FILE__)
warmup do |app|
client = Rack::MockRequest.new(app)
diff --git a/config/application.rb b/config/application.rb
index 349c7258852..1c11e347281 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -97,7 +97,7 @@ module Gitlab
#
# NOTE: It is **IMPORTANT** to also update gitlab-workhorse's filter when adding parameters here to not
# introduce another security vulnerability: https://gitlab.com/gitlab-org/gitlab-workhorse/issues/182
- config.filter_parameters += [/token$/, /password/, /secret/, /key$/]
+ config.filter_parameters += [/token$/, /password/, /secret/, /key$/, /^note$/, /^text$/]
config.filter_parameters += %i(
certificate
encrypted_key
@@ -147,6 +147,8 @@ module Gitlab
config.assets.precompile << "errors.css"
config.assets.precompile << "csslab.css"
+ config.assets.precompile << "highlight/themes/*.css"
+
# Import gitlab-svgs directly from vendored directory
config.assets.paths << "#{config.root}/node_modules/@gitlab/svgs/dist"
config.assets.precompile << "icons.svg"
@@ -162,6 +164,9 @@ module Gitlab
config.action_view.sanitized_allowed_protocols = %w(smb)
+ # Can be removed once upgraded to Rails 5.1 or higher
+ config.action_controller.raise_on_unfiltered_parameters = true
+
# Nokogiri is significantly faster and uses less memory than REXML
ActiveSupport::XmlMini.backend = 'Nokogiri'
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 7fe85f0e0d7..2ad992a059c 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -166,6 +166,23 @@ production: &base
# aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
# endpoint: 'https://s3.amazonaws.com' # default: nil - Useful for S3 compliant services such as DigitalOcean Spaces
+ ## Merge request external diff storage
+ external_diffs:
+ # If disabled (the default), the diffs are in-database. Otherwise, they can
+ # be stored on disk, or in object storage
+ enabled: false
+ # The location where external diffs are stored (default: shared/lfs-external-diffs).
+ # storage_path: shared/external-diffs
+ # object_store:
+ # enabled: false
+ # remote_directory: external-diffs
+ # background_upload: false
+ # proxy_download: false
+ # connection:
+ # provider: AWS
+ # aws_access_key_id: AWS_ACCESS_KEY_ID
+ # aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ # region: us-east-1
## Git LFS
lfs:
@@ -362,19 +379,54 @@ production: &base
# "start_tls" or "simple_tls". Defaults to true.
verify_certificates: true
- # Specifies the path to a file containing a PEM-format CA certificate,
- # e.g. if you need to use an internal CA.
- #
- # Example: '/etc/ca.pem'
- #
- ca_file: ''
-
- # Specifies the SSL version for OpenSSL to use, if the OpenSSL default
- # is not appropriate.
- #
- # Example: 'TLSv1_1'
- #
- ssl_version: ''
+ # OpenSSL::SSL::SSLContext options.
+ tls_options:
+ # Specifies the path to a file containing a PEM-format CA certificate,
+ # e.g. if you need to use an internal CA.
+ #
+ # Example: '/etc/ca.pem'
+ #
+ ca_file: ''
+
+ # Specifies the SSL version for OpenSSL to use, if the OpenSSL default
+ # is not appropriate.
+ #
+ # Example: 'TLSv1_1'
+ #
+ ssl_version: ''
+
+ # Specific SSL ciphers to use in communication with LDAP servers.
+ #
+ # Example: 'ALL:!EXPORT:!LOW:!aNULL:!eNULL:!SSLv2'
+ ciphers: ''
+
+ # Client certificate
+ #
+ # Example:
+ # cert: |
+ # -----BEGIN CERTIFICATE-----
+ # MIIDbDCCAlSgAwIBAgIGAWkJxLmKMA0GCSqGSIb3DQEBCwUAMHcxFDASBgNVBAoTC0dvb2dsZSBJ
+ # bmMuMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQDEwtMREFQIENsaWVudDEPMA0GA1UE
+ # CxMGR1N1aXRlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTAeFw0xOTAyMjAwNzE4
+ # rntnF4d+0dd7zP3jrWkbdtoqjLDT/5D7NYRmVCD5vizV98FJ5//PIHbD1gL3a9b2MPAc6k7NV8tl
+ # ...
+ # 4SbuJPAiJxC1LQ0t39dR6oMCAMab3hXQqhL56LrR6cRBp6Mtlphv7alu9xb/x51y2x+g2zWtsf80
+ # Jrv/vKMsIh/sAyuogb7hqMtp55ecnKxceg==
+ # -----END CERTIFICATE -----
+ cert: ''
+
+ # Client private key
+ # key: |
+ # -----BEGIN PRIVATE KEY-----
+ # MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3DmJtLRmJGY4xU1QtI3yjvxO6
+ # bNuyE4z1NF6Xn7VSbcAaQtavWQ6GZi5uukMo+W5DHVtEkgDwh92ySZMuJdJogFbNvJvHAayheCdN
+ # 7mCQ2UUT9jGXIbmksUn9QMeJVXTZjgJWJzPXToeUdinx9G7+lpVa62UATEd1gaI3oyL72WmpDy/C
+ # rntnF4d+0dd7zP3jrWkbdtoqjLDT/5D7NYRmVCD5vizV98FJ5//PIHbD1gL3a9b2MPAc6k7NV8tl
+ # ...
+ # +9IhSYX+XIg7BZOVDeYqlPfxRvQh8vy3qjt/KUihmEPioAjLaGiihs1Fk5ctLk9A2hIUyP+sEQv9
+ # l6RG+a/mW+0rCWn8JAd464Ps9hE=
+ # -----END PRIVATE KEY-----
+ key: ''
# Set a timeout, in seconds, for LDAP queries. This helps avoid blocking
# a request if the LDAP server becomes unresponsive.
@@ -635,13 +687,16 @@ production: &base
# multipart_chunk_size: 104857600
# # Turns on AWS Server-Side Encryption with Amazon S3-Managed Keys for backups, this is optional
# # encryption: 'AES256'
+ # # Turns on AWS Server-Side Encryption with Amazon Customer-Provided Encryption Keys for backups, this is optional
+ # # This should be set to the 256-bit, base64-encoded encryption key for Amazon S3 to use to encrypt or decrypt your data.
+ # # 'encryption' must also be set in order for this to have any effect.
+ # # encryption_key: '<base64 key>'
# # Specifies Amazon S3 storage class to use for backups, this is optional
# # storage_class: 'STANDARD'
## GitLab Shell settings
gitlab_shell:
path: /home/git/gitlab-shell/
- hooks_path: /home/git/gitlab-shell/hooks/
# File that contains the secret key for verifying access for gitlab-shell.
# Default is '.gitlab_shell_secret' relative to Rails.root (i.e. root of the GitLab app).
@@ -729,6 +784,18 @@ test:
<<: *base
gravatar:
enabled: true
+ external_diffs:
+ enabled: false
+ # The location where external diffs are stored (default: shared/external-diffs).
+ # storage_path: shared/external-diffs
+ object_store:
+ enabled: false
+ remote_directory: external-diffs # The bucket name
+ connection:
+ provider: AWS # Only AWS supported at the moment
+ aws_access_key_id: AWS_ACCESS_KEY_ID
+ aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ region: us-east-1
lfs:
enabled: false
# The location where LFS objects are stored (default: shared/lfs-objects).
@@ -787,7 +854,6 @@ test:
path: tmp/tests/backups
gitlab_shell:
path: tmp/tests/gitlab-shell/
- hooks_path: tmp/tests/gitlab-shell/hooks/
issues_tracker:
redmine:
title: "Redmine"
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index db35fa96ea2..03800f3d9d2 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -40,6 +40,24 @@ if Settings.ldap['enabled'] || Rails.env.test?
# Since GitLab 10.0, verify_certificates defaults to true for security.
server['verify_certificates'] = true if server['verify_certificates'].nil?
+ # Expose ability to set `tls_options` directly. Deprecate `ca_file` and
+ # `ssl_version` in favor of `tls_options` hash option.
+ server['tls_options'] ||= {}
+
+ if server['ssl_version'] || server['ca_file']
+ Rails.logger.warn 'DEPRECATED: LDAP options `ssl_version` and `ca_file` should be nested within `tls_options`'
+ end
+
+ if server['ssl_version']
+ server['tls_options']['ssl_version'] ||= server['ssl_version']
+ server.delete('ssl_version')
+ end
+
+ if server['ca_file']
+ server['tls_options']['ca_file'] ||= server['ca_file']
+ server.delete('ca_file')
+ end
+
Settings.ldap['servers'][key] = server
end
end
@@ -216,6 +234,14 @@ Settings.pages['admin'] ||= Settingslogic.new({})
Settings.pages.admin['certificate'] ||= ''
#
+# External merge request diffs
+#
+Settings['external_diffs'] ||= Settingslogic.new({})
+Settings.external_diffs['enabled'] = false if Settings.external_diffs['enabled'].nil?
+Settings.external_diffs['storage_path'] = Settings.absolute(Settings.external_diffs['storage_path'] || File.join(Settings.shared['path'], 'external-diffs'))
+Settings.external_diffs['object_store'] = ObjectStoreSettings.parse(Settings.external_diffs['object_store'])
+
+#
# Git LFS
#
Settings['lfs'] ||= Settingslogic.new({})
@@ -329,7 +355,7 @@ Settings['sidekiq']['log_format'] ||= 'default'
#
Settings['gitlab_shell'] ||= Settingslogic.new({})
Settings.gitlab_shell['path'] = Settings.absolute(Settings.gitlab_shell['path'] || Settings.gitlab['user_home'] + '/gitlab-shell/')
-Settings.gitlab_shell['hooks_path'] = Settings.absolute(Settings.gitlab_shell['hooks_path'] || Settings.gitlab['user_home'] + '/gitlab-shell/hooks/')
+Settings.gitlab_shell['hooks_path'] = :deprecated_use_gitlab_shell_path_instead
Settings.gitlab_shell['secret_file'] ||= Rails.root.join('.gitlab_shell_secret')
Settings.gitlab_shell['receive_pack'] = true if Settings.gitlab_shell['receive_pack'].nil?
Settings.gitlab_shell['upload_pack'] = true if Settings.gitlab_shell['upload_pack'].nil?
@@ -392,6 +418,7 @@ Settings.backup['archive_permissions'] ||= 0600
Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil })
Settings.backup['upload']['multipart_chunk_size'] ||= 104857600
Settings.backup['upload']['encryption'] ||= nil
+Settings.backup['upload']['encryption_key'] ||= ENV['GITLAB_BACKUP_ENCRYPTION_KEY']
Settings.backup['upload']['storage_class'] ||= nil
#
diff --git a/config/initializers/8_devise.rb b/config/initializers/8_devise.rb
index 67eabb0b4fc..4683b02f300 100644
--- a/config/initializers/8_devise.rb
+++ b/config/initializers/8_devise.rb
@@ -178,7 +178,7 @@ Devise.setup do |config|
# Configure the default scope given to Warden. By default it's the first
# devise role declared in your routes (usually :user).
- config.default_scope = :user # now have an :email scope as well, so set the default
+ config.default_scope = :user # now have an :email scope as well, so set the default
# Configure sign_out behavior.
# Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope).
diff --git a/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb b/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb
index 3e765469995..228ced32188 100644
--- a/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb
+++ b/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb
@@ -20,7 +20,7 @@
#
# This bug was fixed in Rails 5.1 by https://github.com/rails/rails/pull/24745/commits/aa062318c451512035c10898a1af95943b1a3803
-if Rails.version.start_with?("5.1")
+if Rails.gem_version >= Gem::Version.new("5.1")
raise "Remove this monkey patch: #{__FILE__}"
end
diff --git a/config/initializers/active_record_locking.rb b/config/initializers/active_record_locking.rb
index bfe41e6029a..1bd1a12e4b7 100644
--- a/config/initializers/active_record_locking.rb
+++ b/config/initializers/active_record_locking.rb
@@ -1,7 +1,10 @@
# rubocop:disable Lint/RescueException
-# Remove this monkey-patch when all lock_version values are converted from NULLs to zeros.
-# See https://gitlab.com/gitlab-org/gitlab-ce/issues/25228
+# Remove this monkey patch when we move to Rails 5.1, because the bug has been fixed in https://github.com/rails/rails/pull/26050.
+if Rails.gem_version >= Gem::Version.new("5.1")
+ raise "Remove this monkey patch: #{__FILE__}"
+end
+
module ActiveRecord
module Locking
module Optimistic
@@ -16,12 +19,7 @@ module ActiveRecord
return 0 if attribute_names.empty?
lock_col = self.class.locking_column
-
previous_lock_value = send(lock_col).to_i
-
- # This line is added as a patch
- previous_lock_value = nil if previous_lock_value == '0' || previous_lock_value == 0
-
increment_lock
attribute_names += [lock_col]
@@ -32,7 +30,8 @@ module ActiveRecord
affected_rows = relation.where(
self.class.primary_key => id,
- lock_col => previous_lock_value
+ # Patched because when `lock_version` is read as `0`, it may actually be `NULL` in the DB.
+ lock_col => previous_lock_value == 0 ? [nil, 0] : previous_lock_value
).update_all(
attributes_for_update(attribute_names).map do |name|
[name, _read_attribute(name)]
diff --git a/config/initializers/ar_mysql_jsonb_support.rb b/config/initializers/ar_mysql_jsonb_support.rb
new file mode 100644
index 00000000000..63a0b05119a
--- /dev/null
+++ b/config/initializers/ar_mysql_jsonb_support.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'active_record/connection_adapters/abstract_mysql_adapter'
+require 'active_record/connection_adapters/mysql/schema_definitions'
+
+# MySQL (5.6) and MariaDB (10.1) are currently supported versions within GitLab,
+# Since they do not support native `json` datatype we force to emulate it as `text`
+
+if Gitlab::Database.mysql?
+ module ActiveRecord
+ module ConnectionAdapters
+ class AbstractMysqlAdapter
+ JSON_DATASIZE = 1.megabyte
+
+ NATIVE_DATABASE_TYPES.merge!(
+ json: { name: "text", limit: JSON_DATASIZE },
+ jsonb: { name: "text", limit: JSON_DATASIZE }
+ )
+ end
+
+ module MySQL
+ module ColumnMethods
+ # We add `jsonb` helper, as `json` is already defined for `MySQL` since Rails 5
+ def jsonb(*args, **options)
+ args.each { |name| column(name, :json, options) }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/config/initializers/carrierwave_patch.rb b/config/initializers/carrierwave_patch.rb
deleted file mode 100644
index c361784491d..00000000000
--- a/config/initializers/carrierwave_patch.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# This monkey patches CarrierWave 1.2.3 to make Google Cloud Storage work with
-# extra query parameters:
-# https://github.com/carrierwaveuploader/carrierwave/pull/2332/files
-module CarrierWave
- module Storage
- class Fog < Abstract
- class File
- def authenticated_url(options = {})
- if %w(AWS Google Rackspace OpenStack).include?(@uploader.fog_credentials[:provider])
- # avoid a get by using local references
- local_directory = connection.directories.new(key: @uploader.fog_directory)
- local_file = local_directory.files.new(key: path)
- expire_at = ::Fog::Time.now + @uploader.fog_authenticated_url_expiration
- case @uploader.fog_credentials[:provider]
- when 'AWS', 'Google'
- local_file.url(expire_at, options)
- when 'Rackspace'
- connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
- when 'OpenStack'
- connection.get_object_https_url(@uploader.fog_directory, path, expire_at)
- else
- local_file.url(expire_at)
- end
- end
- end
-
- # Fix for https://github.com/carrierwaveuploader/carrierwave/pull/2356
- def acl_header
- if fog_provider == 'AWS'
- { 'x-amz-acl' => @uploader.fog_public ? 'public-read' : 'private' }
- else
- {}
- end
- end
-
- def fog_provider
- @uploader.fog_credentials[:provider].to_s
- end
- end
- end
- end
-end
diff --git a/config/initializers/doorkeeper_openid_connect.rb b/config/initializers/doorkeeper_openid_connect.rb
index ae5d834a02c..fd5a62c39c6 100644
--- a/config/initializers/doorkeeper_openid_connect.rb
+++ b/config/initializers/doorkeeper_openid_connect.rb
@@ -31,8 +31,27 @@ Doorkeeper::OpenidConnect.configure do
o.claim(:name) { |user| user.name }
o.claim(:nickname) { |user| user.username }
- o.claim(:email) { |user| user.public_email }
- o.claim(:email_verified) { |user| true if user.public_email? }
+
+ # Check whether the application has access to the email scope, and grant
+ # access to the user's primary email address if so, otherwise their
+ # public email address (if present)
+ # This allows existing solutions built for GitLab's old behavior to keep
+ # working without modification.
+ o.claim(:email) do |user, scopes|
+ scopes.exists?(:email) ? user.email : user.public_email
+ end
+ o.claim(:email_verified) do |user, scopes|
+ if scopes.exists?(:email)
+ user.primary_email_verified?
+ elsif user.public_email?
+ user.verified_email?(user.public_email)
+ else
+ # If there is no public email set, tell doorkicker-openid-connect to
+ # exclude the email_verified claim by returning nil.
+ nil
+ end
+ end
+
o.claim(:website) { |user| user.full_website_url if user.website_url? }
o.claim(:profile) { |user| Gitlab::Routing.url_helpers.user_url user }
o.claim(:picture) { |user| user.avatar_url(only_path: false) }
diff --git a/config/initializers/fog_core_patch.rb b/config/initializers/fog_core_patch.rb
new file mode 100644
index 00000000000..d3d02216d45
--- /dev/null
+++ b/config/initializers/fog_core_patch.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+#
+# fog-core v2 changed the namespace format:
+#
+# Old: Fog::<service>::<provider> (e.g. Fog::Storage::AWS).
+# New: Fog::<provider>::<service> (e.g. Fog::AWS::Storage)
+#
+# To preserve backwards compatibility, fog-core v2.1.0 tries to load the
+# old schema first, but falls back to the older version if that
+# fails. This creates misleading warnings with fog-aws. See
+# https://github.com/fog/fog-aws/issues/504#issuecomment-468067991 for
+# more details.
+#
+# fog-core v2.1.2 reverses the load order
+# (https://github.com/fog/fog-core/pull/229), which works for fog-aws
+# but causes a stream of deprecation warnings for fog-google.
+# fog-google locked the dependency on fog-core v2.1.0 as a result
+# (https://github.com/fog/fog-google/issues/421) until the new namespace
+# is supported.
+#
+# Since we currently have some Fog gems that have not been updated, this
+# monkey patch makes a smarter decision about which namespace to try
+# first. This squelches a significant number of warning messages.
+#
+# Since this patch is mostly cosmetic, it can be removed safely at any
+# time, but it's probably best to wait until the following issues are
+# closed:
+#
+# fog-google: https://github.com/fog/fog-google/issues/421
+# fog-rackspace: https://github.com/fog/fog-rackspace/issues/29
+# fog-aliyun: https://github.com/fog/fog-aliyun/issues/23
+module Fog
+ module ServicesMixin
+ # Gems that have not yet updated with the new fog-core namespace
+ LEGACY_FOG_PROVIDERS = %w(google rackspace aliyun).freeze
+
+ def service_provider_constant(service_name, provider_name)
+ args = service_provider_search_args(service_name, provider_name)
+ Fog.const_get(args.first).const_get(*const_get_args(args.second))
+ rescue NameError # Try to find the constant from in an alternate location
+ Fog.const_get(args.second).const_get(*const_get_args(args.first))
+ end
+
+ def service_provider_search_args(service_name, provider_name)
+ if LEGACY_FOG_PROVIDERS.include?(provider_name.downcase)
+ [service_name, provider_name]
+ else
+ [provider_name, service_name]
+ end
+ end
+ end
+end
diff --git a/config/initializers/graphql.rb b/config/initializers/graphql.rb
new file mode 100644
index 00000000000..e653556231d
--- /dev/null
+++ b/config/initializers/graphql.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+GraphQL::Field.accepts_definitions(authorize: GraphQL::Define.assign_metadata_key(:authorize))
+GraphQL::Schema::Field.accepts_definition(:authorize)
diff --git a/config/initializers/hipchat_client_patch.rb b/config/initializers/hipchat_client_patch.rb
deleted file mode 100644
index aec265312bb..00000000000
--- a/config/initializers/hipchat_client_patch.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# This monkey patches the HTTParty used in https://github.com/hipchat/hipchat-rb.
-module HipChat
- class Client
- connection_adapter ::Gitlab::ProxyHTTPConnectionAdapter
- end
-
- class Room
- connection_adapter ::Gitlab::ProxyHTTPConnectionAdapter
- end
-
- class User
- connection_adapter ::Gitlab::ProxyHTTPConnectionAdapter
- end
-end
diff --git a/config/initializers/kaminari_active_record_relation_methods_with_limit.rb b/config/initializers/kaminari_active_record_relation_methods_with_limit.rb
new file mode 100644
index 00000000000..cc20b83b234
--- /dev/null
+++ b/config/initializers/kaminari_active_record_relation_methods_with_limit.rb
@@ -0,0 +1,41 @@
+module Kaminari
+ # Active Record specific page scope methods implementations
+ module ActiveRecordRelationMethodsWithLimit
+ MAX_COUNT_LIMIT = 10_000
+
+ # This is a modified version of
+ # https://github.com/kaminari/kaminari/blob/c5186f5d9b7f23299d115408e62047447fd3189d/kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#L17-L41
+ # that limit the COUNT query to 10,000 to avoid query timeouts.
+ # rubocop: disable Gitlab/ModuleWithInstanceVariables
+ def total_count_with_limit(column_name = :all, _options = nil) #:nodoc:
+ return @total_count if defined?(@total_count) && @total_count
+
+ # There are some cases that total count can be deduced from loaded records
+ if loaded?
+ # Total count has to be 0 if loaded records are 0
+ return @total_count = 0 if (current_page == 1) && @records.empty?
+ # Total count is calculable at the last page
+ return @total_count = (current_page - 1) * limit_value + @records.length if @records.any? && (@records.length < limit_value)
+ end
+
+ # #count overrides the #select which could include generated columns referenced in #order, so skip #order here, where it's irrelevant to the result anyway
+ c = except(:offset, :limit, :order)
+ # Remove includes only if they are irrelevant
+ c = c.except(:includes) unless references_eager_loaded_tables?
+ # .group returns an OrderedHash that responds to #count
+ # The following line was modified from `c = c.count(:all)`
+ c = c.limit(MAX_COUNT_LIMIT + 1).count(column_name)
+ @total_count =
+ if c.is_a?(Hash) || c.is_a?(ActiveSupport::OrderedHash)
+ c.count
+ elsif c.respond_to? :count
+ c.count(column_name)
+ else
+ c
+ end
+ end
+ # rubocop: enable Gitlab/ModuleWithInstanceVariables
+
+ Kaminari::ActiveRecordRelationMethods.prepend(self)
+ end
+end
diff --git a/config/initializers/kubeclient.rb b/config/initializers/kubeclient.rb
deleted file mode 100644
index f8fe1156aaa..00000000000
--- a/config/initializers/kubeclient.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-class Kubeclient::Client
- # Monkey patch to set `max_redirects: 0`, so that kubeclient
- # does not follow redirects and expose internal services.
- # See https://gitlab.com/gitlab-org/gitlab-ce/issues/53158
- def create_rest_client(path = nil)
- path ||= @api_endpoint.path
- options = {
- ssl_ca_file: @ssl_options[:ca_file],
- ssl_cert_store: @ssl_options[:cert_store],
- verify_ssl: @ssl_options[:verify_ssl],
- ssl_client_cert: @ssl_options[:client_cert],
- ssl_client_key: @ssl_options[:client_key],
- proxy: @http_proxy_uri,
- user: @auth_options[:username],
- password: @auth_options[:password],
- open_timeout: @timeouts[:open],
- read_timeout: @timeouts[:read],
- max_redirects: 0
- }
- RestClient::Resource.new(@api_endpoint.merge(path).to_s, options)
- end
-end
diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb
index c897bc30e76..164954d1293 100644
--- a/config/initializers/lograge.rb
+++ b/config/initializers/lograge.rb
@@ -23,7 +23,8 @@ unless Sidekiq.server?
remote_ip: event.payload[:remote_ip],
user_id: event.payload[:user_id],
username: event.payload[:username],
- ua: event.payload[:ua]
+ ua: event.payload[:ua],
+ queue_duration: event.payload[:queue_duration]
}
gitaly_calls = Gitlab::GitalyClient.get_request_count
diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb
index 5adb9f7a4b4..115ee08dbb6 100644
--- a/config/initializers/new_framework_defaults.rb
+++ b/config/initializers/new_framework_defaults.rb
@@ -8,8 +8,6 @@
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
-Rails.application.config.action_controller.raise_on_unfiltered_parameters = true
-
# Enable per-form CSRF tokens. Previous versions had false.
Rails.application.config.action_controller.per_form_csrf_tokens = false
@@ -22,6 +20,3 @@ ActiveSupport.to_time_preserves_timezone = false
# Require `belongs_to` associations by default. Previous versions had false.
Rails.application.config.active_record.belongs_to_required_by_default = false
-
-# Do not halt callback chains when a callback returns false. Previous versions had true.
-ActiveSupport.halt_callback_chains_on_return_false = true
diff --git a/config/initializers/peek.rb b/config/initializers/peek.rb
index a6f43415ec5..e051e5c68c4 100644
--- a/config/initializers/peek.rb
+++ b/config/initializers/peek.rb
@@ -19,6 +19,7 @@ Peek.into Peek::Views::Gitaly
Peek.into Peek::Views::Rblineprof
Peek.into Peek::Views::Redis
Peek.into Peek::Views::GC
+Peek.into Peek::Views::Tracing if Gitlab::Tracing.tracing_url_enabled?
# rubocop:disable Naming/ClassAndModuleCamelCase
class PEEK_DB_CLIENT
diff --git a/config/initializers/postgresql_cte.rb b/config/initializers/postgresql_cte.rb
index 38a9cd68d57..56689bc8e74 100644
--- a/config/initializers/postgresql_cte.rb
+++ b/config/initializers/postgresql_cte.rb
@@ -108,7 +108,7 @@ module ActiveRecord
when String
with_value
when Hash
- with_value.map do |name, expression|
+ with_value.map do |name, expression|
case expression
when String
select = Arel::Nodes::SqlLiteral.new "(#{expression})"
diff --git a/config/initializers/postgresql_opclasses_support.rb b/config/initializers/postgresql_opclasses_support.rb
index 70b530415f5..b066f3788ec 100644
--- a/config/initializers/postgresql_opclasses_support.rb
+++ b/config/initializers/postgresql_opclasses_support.rb
@@ -130,9 +130,12 @@ module ActiveRecord
where = inddef.scan(/WHERE (.+)$/).flatten[0]
using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
opclasses = Hash[inddef.scan(/\((.+?)\)(?:$| WHERE )/).flatten[0].split(',').map do |column_and_opclass|
- column, opclass = column_and_opclass.split(' ').map(&:strip)
- [column, opclass] if opclass
- end.compact]
+ column, opclass = column_and_opclass.split(' ').map(&:strip)
+ end.reject do |column, opclass|
+ ['desc', 'asc'].include?(opclass&.downcase)
+ end.map do |column, opclass|
+ [column, opclass] if opclass
+ end.compact]
index_attrs = [table_name, index_name, unique, column_names, [], orders, where, nil, using, nil, opclasses]
@@ -151,6 +154,9 @@ module ActiveRecord
def quoted_columns_for_index(column_names, options = {})
column_opclasses = options[:opclasses] || {}
column_names.map {|name| "#{quote_column_name(name)} #{column_opclasses[name]}"}
+
+ quoted_columns = Hash[column_names.map { |name| [name.to_sym, "#{quote_column_name(name)} #{column_opclasses[name]}"] }]
+ add_options_for_index_columns(quoted_columns, options).values
end
end
end
diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb
index 2a6c5148f71..abc91c3ae51 100644
--- a/config/initializers/sentry.rb
+++ b/config/initializers/sentry.rb
@@ -19,7 +19,7 @@ def configure_sentry
config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s)
# Sanitize authentication headers
config.sanitize_http_headers = %w[Authorization Private-Token]
- config.tags = { program: Gitlab::Sentry.program_context }
+ config.tags = { program: Gitlab.process_name }
end
end
end
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index be4183f39be..2e4aa9c1053 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -11,6 +11,10 @@ queues_config_hash[:namespace] = Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE
# Default is to retry 25 times with exponential backoff. That's too much.
Sidekiq.default_worker_options = { retry: 3 }
+if Rails.env.development?
+ Sidekiq.default_worker_options[:backtrace] = true
+end
+
enable_json_logs = Gitlab.config.sidekiq.log_format == 'json'
Sidekiq.configure_server do |config|
@@ -18,7 +22,7 @@ Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger if ENV['SIDEKIQ_LOG_ARGUMENTS'] && !enable_json_logs
- chain.add Gitlab::SidekiqMiddleware::Shutdown
+ chain.add Gitlab::SidekiqMiddleware::MemoryKiller if ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS']
chain.add Gitlab::SidekiqMiddleware::RequestStoreMiddleware unless ENV['SIDEKIQ_REQUEST_STORE'] == '0'
chain.add Gitlab::SidekiqMiddleware::BatchLoader
chain.add Gitlab::SidekiqMiddleware::CorrelationLogger
@@ -73,6 +77,9 @@ Sidekiq.configure_server do |config|
# Avoid autoload issue such as 'Mail::Parsers::AddressStruct'
# https://github.com/mikel/mail/issues/912#issuecomment-214850355
Mail.eager_autoload!
+
+ # Ensure the whole process group is terminated if possible
+ Gitlab::SidekiqSignals.install!(Sidekiq::CLI::SIGNAL_HANDLERS)
end
Sidekiq.configure_client do |config|
diff --git a/config/initializers/sprockets_base_file_digest_key.rb b/config/initializers/sprockets_base_file_digest_key.rb
new file mode 100644
index 00000000000..81ff3812091
--- /dev/null
+++ b/config/initializers/sprockets_base_file_digest_key.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+Sprockets::Base.prepend(Gitlab::Patch::SprocketsBaseFileDigestKey)
diff --git a/config/initializers/tracing.rb b/config/initializers/tracing.rb
new file mode 100644
index 00000000000..ddd91150c90
--- /dev/null
+++ b/config/initializers/tracing.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+if Gitlab::Tracing.enabled?
+ require 'opentracing'
+
+ Rails.application.configure do |config|
+ config.middleware.insert_after Gitlab::Middleware::CorrelationId, ::Gitlab::Tracing::RackMiddleware
+ end
+
+ # Instrument the Sidekiq client
+ Sidekiq.configure_client do |config|
+ config.client_middleware do |chain|
+ chain.add Gitlab::Tracing::Sidekiq::ClientMiddleware
+ end
+ end
+
+ # Instrument Sidekiq server calls when running Sidekiq server
+ if Sidekiq.server?
+ Sidekiq.configure_server do |config|
+ config.server_middleware do |chain|
+ chain.add Gitlab::Tracing::Sidekiq::ServerMiddleware
+ end
+ end
+ end
+
+ # Instrument Rails
+ Gitlab::Tracing::Rails::ActiveRecordSubscriber.instrument
+ Gitlab::Tracing::Rails::ActionViewSubscriber.instrument
+
+ # In multi-processed clustered architectures (puma, unicorn) don't
+ # start tracing until the worker processes are spawned. This works
+ # around issues when the opentracing implementation spawns threads
+ Gitlab::Cluster::LifecycleEvents.on_worker_start do
+ tracer = Gitlab::Tracing::Factory.create_tracer(Gitlab.process_name, Gitlab::Tracing.connection_string)
+ OpenTracing.global_tracer = tracer if tracer
+ end
+end
diff --git a/config/initializers/zz_metrics.rb b/config/initializers/zz_metrics.rb
index 462e8c811a6..151cad3ef9a 100644
--- a/config/initializers/zz_metrics.rb
+++ b/config/initializers/zz_metrics.rb
@@ -173,7 +173,7 @@ if Gitlab::Metrics.enabled? && !Rails.env.test? && !(Rails.env.development? && d
def connect(*args)
val = super
- if current_transaction = Gitlab::Metrics::Transaction.current
+ if current_transaction = ::Gitlab::Metrics::Transaction.current
current_transaction.increment(:new_redis_connections, 1)
end
diff --git a/config/jsdocs.config.js b/config/jsdocs.config.js
new file mode 100644
index 00000000000..52635b1ce13
--- /dev/null
+++ b/config/jsdocs.config.js
@@ -0,0 +1,14 @@
+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/de.yml b/config/locales/de.yml
index 38c3711c6c7..554e9913faa 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -43,6 +43,7 @@ de:
default: "%d.%m.%Y"
long: "%e. %B %Y"
short: "%e. %b"
+ admin: "%e %b, %Y"
month_names:
-
- Januar
diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml
index 9f451046462..a2dff92908e 100644
--- a/config/locales/doorkeeper.en.yml
+++ b/config/locales/doorkeeper.en.yml
@@ -64,6 +64,8 @@ en:
read_registry: Grants permission to read container registry images
openid: Authenticate using OpenID Connect
sudo: Perform API actions as any user in the system
+ profile: Allows read-only access to the user's personal information using OpenID Connect
+ email: Allows read-only access to the user's primary email address using OpenID Connect
scope_desc:
api:
Grants complete read/write access to the API, including all groups and projects.
@@ -77,6 +79,10 @@ en:
Grants permission to authenticate with GitLab using OpenID Connect. Also gives read-only access to the user's profile and group memberships.
sudo:
Grants permission to perform API actions as any user in the system, when authenticated as an admin user.
+ profile:
+ Grants read-only access to the user's profile data using OpenID Connect.
+ email:
+ Grants read-only access to the user's primary email address using OpenID Connect.
flash:
applications:
create:
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 0a43a1d9a6b..eb3b7771968 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -10,6 +10,10 @@ en:
target: Target issue
group:
path: Group URL
+ project/error_tracking_setting:
+ token: "Auth Token"
+ project: "Project"
+ api_url: "Sentry API URL"
errors:
messages:
label_already_exists_at_group_level: "already exists at group level for %{group}. Please choose another one."
@@ -55,6 +59,7 @@ en:
default: "%Y-%m-%d"
long: "%B %d, %Y"
short: "%b %d"
+ admin: "%e %b, %Y"
month_names:
-
- January
diff --git a/config/locales/es.yml b/config/locales/es.yml
index fdc52b4ae11..78c07583933 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -42,6 +42,7 @@ es:
default: "%d/%m/%Y"
long: "%d de %B de %Y"
short: "%d de %b"
+ admin: "%e %b, %Y"
month_names:
-
- enero
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index af333bdc748..a01003b6039 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -120,6 +120,10 @@ namespace :admin do
get :resume
get :pause
end
+
+ collection do
+ get :tag_list, format: :json
+ end
end
resources :jobs, only: :index do
diff --git a/config/routes/git_http.rb b/config/routes/git_http.rb
index ec5c68f81df..a959d40881b 100644
--- a/config/routes/git_http.rb
+++ b/config/routes/git_http.rb
@@ -40,7 +40,7 @@ scope(path: '*namespace_id/:project_id',
# /info/refs?service=git-receive-pack, but nothing else.
#
git_http_handshake = lambda do |request|
- ::Constraints::ProjectUrlConstrainer.new.matches?(request) &&
+ ::Constraints::ProjectUrlConstrainer.new.matches?(request, existence_check: false) &&
(request.query_string.blank? ||
request.query_string.match(/\Aservice=git-(upload|receive)-pack\z/))
end
diff --git a/config/routes/group.rb b/config/routes/group.rb
index a0aeebe4b91..b3015529c6e 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -67,7 +67,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
end
end
- resources :boards, only: [:index, :show]
+ resources :boards, only: [:index, :show], constraints: { id: /\d+/ }
resources :runners, only: [:index, :edit, :update, :destroy, :show] do
member do
diff --git a/config/routes/import.rb b/config/routes/import.rb
index 3998d977c81..24013eb2c88 100644
--- a/config/routes/import.rb
+++ b/config/routes/import.rb
@@ -1,15 +1,24 @@
+# Alias import callbacks under the /users/auth endpoint so that
+# the OAuth2 callback URL can be restricted under http://example.com/users/auth
+# instead of http://example.com.
+Devise.omniauth_providers.map(&:downcase).each do |provider|
+ next if provider == 'ldapmain'
+
+ get "/users/auth/-/import/#{provider}/callback", to: "import/#{provider}#callback", as: "users_import_#{provider}_callback"
+end
+
namespace :import do
resource :github, only: [:create, :new], controller: :github do
post :personal_access_token
get :status
get :callback
- get :jobs
+ get :realtime_changes
end
resource :gitea, only: [:create, :new], controller: :gitea do
post :personal_access_token
get :status
- get :jobs
+ get :realtime_changes
end
resource :gitlab, only: [:create], controller: :gitlab do
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 03c95b61e51..d60a5cc9ae8 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -2,6 +2,8 @@ resources :projects, only: [:index, :new, :create]
draw :git_http
+get '/projects/:id' => 'projects#resolve'
+
constraints(::Constraints::ProjectUrlConstrainer.new) do
# If the route has a wildcard segment, the segment has a regex constraint,
# the segment is potentially followed by _another_ wildcard segment, and
@@ -222,6 +224,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
collection do
get :metrics, action: :metrics_redirect
get :folder, path: 'folders/*id', constraints: { format: /(html|json)/ }
+ get :search
end
resources :deployments, only: [:index] do
@@ -247,6 +250,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
namespace :serverless do
+ get '/functions/:environment_id/:id', to: 'functions#show'
resources :functions, only: [:index]
end
@@ -255,8 +259,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do
collection do
- post :cancel_all
-
resources :artifacts, only: [] do
collection do
get :latest_succeeded,
@@ -361,6 +363,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
collection do
post :bulk_update
+ post :import_csv
end
end
@@ -391,8 +394,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get 'noteable/:target_type/:target_id/notes' => 'notes#index', as: 'noteable_notes'
- # On CE only index and show are needed
- resources :boards, only: [:index, :show]
+ resources :boards, only: [:index, :show], constraints: { id: /\d+/ }
resources :todos, only: [:create]
@@ -441,10 +443,20 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
+ resources :error_tracking, only: [:index], controller: :error_tracking do
+ collection do
+ post :list_projects
+ end
+ end
+
# Since both wiki and repository routing contains wildcard characters
# its preferable to keep it below all other project routes
draw :wiki
draw :repository
+
+ namespace :settings do
+ resource :operations, only: [:show, :update]
+ end
end
resources(:projects,
diff --git a/config/routes/repository.rb b/config/routes/repository.rb
index 96975759709..f5201b9ddbb 100644
--- a/config/routes/repository.rb
+++ b/config/routes/repository.rb
@@ -62,7 +62,7 @@ scope format: false do
resources :protected_tags, only: [:index, :show, :create, :update, :destroy]
end
- scope constraints: { id: /.+/ } do
+ scope constraints: { id: /.+/ } do
scope controller: :blob do
get '/new/*id', action: :new, as: :new_blob
post '/create/*id', action: :create, as: :create_blob
diff --git a/config/routes/uploads.rb b/config/routes/uploads.rb
index 6becadd57ae..b594f55f8a0 100644
--- a/config/routes/uploads.rb
+++ b/config/routes/uploads.rb
@@ -17,7 +17,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: /.+/ }
+ constraints: { model: /appearance/, mounted_as: /logo|header_logo|favicon/, filename: /.+/ },
+ as: 'appearance_upload'
# Project markdown uploads
get ":namespace_id/:project_id/:secret/:filename",
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 3ee32678f34..cef123b86ae 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -47,7 +47,6 @@
- [project_service, 1]
- [delete_user, 1]
- [todos_destroyer, 1]
- - [delete_container_repository, 1]
- [delete_merged_branches, 1]
- [authorized_projects, 1]
- [expire_build_instance_artifacts, 1]
@@ -69,7 +68,8 @@
- [background_migration, 1]
- [gcp_cluster, 1]
- [project_migrate_hashed_storage, 1]
- - [storage_migrator, 1]
+ - [project_rollback_hashed_storage, 1]
+ - [hashed_storage, 1]
- [pages_domain_verification, 1]
- [object_storage_upload, 1]
- [object_storage, 1]
@@ -81,7 +81,11 @@
- [delete_diff_files, 1]
- [detect_repository_languages, 1]
- [auto_devops, 2]
+ - [container_repository, 1]
- [object_pool, 1]
- [repository_cleanup, 1]
- [delete_stored_files, 1]
- [remote_mirror_notification, 2]
+ - [project_daily_statistics, 1]
+ - [import_issues_csv, 2]
+ - [chat_notification, 2]
diff --git a/config/webpack.config.js b/config/webpack.config.js
index b9044e13f50..64e6ec49219 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -94,6 +94,9 @@ module.exports = {
vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
vue$: 'vue/dist/vue.esm.js',
spec: path.join(ROOT_PATH, 'spec/javascripts'),
+
+ // the following resolves files which are different between CE and EE
+ ee_else_ce: path.join(ROOT_PATH, 'app/assets/javascripts'),
},
},
@@ -147,6 +150,7 @@ module.exports = {
loader: 'worker-loader',
options: {
name: '[name].[hash:8].worker.js',
+ inline: IS_DEV_SERVER,
},
},
'babel-loader',
@@ -241,6 +245,17 @@ module.exports = {
jQuery: 'jquery',
}),
+ new webpack.NormalModuleReplacementPlugin(/^ee_component\/(.*)\.vue/, function(resource) {
+ if (Object.keys(module.exports.resolve.alias).indexOf('ee') >= 0) {
+ resource.request = resource.request.replace(/^ee_component/, 'ee');
+ } else {
+ resource.request = path.join(
+ ROOT_PATH,
+ 'app/assets/javascripts/vue_shared/components/empty_component.js'
+ );
+ }
+ }),
+
// compression can require a lot of compute time and is disabled in CI
IS_PRODUCTION && !NO_COMPRESSION && new CompressionPlugin(),
diff --git a/danger/changelog/Dangerfile b/danger/changelog/Dangerfile
index 530c6638653..63b2f6f5c5c 100644
--- a/danger/changelog/Dangerfile
+++ b/danger/changelog/Dangerfile
@@ -16,16 +16,12 @@ consider adding any of the %<labels>s labels.
#{SEE_DOC}
MSG
-def ee?
- ENV['CI_PROJECT_NAME'] == 'gitlab-ee' || File.exist?('../../CHANGELOG-EE.md')
-end
-
def ee_changelog?(changelog_path)
changelog_path =~ /unreleased-ee/
end
def ce_port_changelog?(changelog_path)
- ee? && !ee_changelog?(changelog_path)
+ helper.ee? && !ee_changelog?(changelog_path)
end
def check_changelog(path)
diff --git a/danger/commit_messages/Dangerfile b/danger/commit_messages/Dangerfile
index abb36098629..9be1ce2ff86 100644
--- a/danger/commit_messages/Dangerfile
+++ b/danger/commit_messages/Dangerfile
@@ -2,6 +2,9 @@
require 'json'
+URL_LIMIT_SUBJECT = "https://chris.beams.io/posts/git-commit/#limit-50"
+URL_GIT_COMMIT = "https://chris.beams.io/posts/git-commit/"
+
# rubocop: disable Style/SignalException
# rubocop: disable Metrics/CyclomaticComplexity
# rubocop: disable Metrics/PerceivedComplexity
@@ -61,11 +64,12 @@ def too_many_changed_lines?(commit)
lines_changed_in_commit(commit) >= 30
end
-def lint_commits(commits)
- failures = false
- emoji_checker = EmojiChecker.new
+def emoji_checker
+ @emoji_checker ||= EmojiChecker.new
+end
- unicode_emoji_regex = %r((
+def unicode_emoji_regex
+ @unicode_emoji_regex ||= %r((
[\u{1F300}-\u{1F5FF}] |
[\u{1F1E6}-\u{1F1FF}] |
[\u{2700}-\u{27BF}] |
@@ -74,129 +78,138 @@ def lint_commits(commits)
[\u{1F680}-\u{1F6FF}] |
[\u{2600}-\u{26FF}]
))x
+end
+
+def lint_commit(commit)
+ # For now we'll ignore merge commits, as getting rid of those is a problem
+ # separate from enforcing good commit messages.
+ return false if commit.message.start_with?('Merge branch')
+
+ # We ignore revert commits as they are well structured by Git already
+ return false if commit.message.start_with?('Revert "')
+
+ failures = false
+ subject, separator, details = commit.message.split("\n", 3)
+
+ if subject.split.length < 3
+ fail_commit(
+ commit,
+ 'The commit subject must contain at least three words'
+ )
+
+ failures = true
+ end
+
+ if subject.length > 72
+ fail_commit(
+ commit,
+ 'The commit subject may not be longer than 72 characters'
+ )
+
+ failures = true
+ elsif subject.length > 50
+ warn_commit(
+ commit,
+ "This commit's subject line is acceptable, but please try to [reduce it to 50 characters](#{URL_LIMIT_SUBJECT})."
+ )
+ end
+
+ unless subject_starts_with_capital?(subject)
+ fail_commit(commit, 'The commit subject must start with a capital letter')
+ failures = true
+ end
+
+ if subject.end_with?('.')
+ fail_commit(commit, 'The commit subject must not end with a period')
+ failures = true
+ end
+
+ if separator && !separator.empty?
+ fail_commit(
+ commit,
+ 'The commit subject and body must be separated by a blank line'
+ )
+
+ failures = true
+ end
+
+ details&.each_line do |line|
+ line = line.strip
- commits.each do |commit|
- # For now we'll ignore merge commits, as getting rid of those is a problem
- # separate from enforcing good commit messages.
- next if commit.message.start_with?('Merge branch')
-
- subject, separator, details = commit.message.split("\n", 3)
-
- if subject.split.length < 3
- fail_commit(
- commit,
- 'The commit subject must contain at least three words'
- )
-
- failures = true
- end
-
- if subject.length > 72
- fail_commit(
- commit,
- 'The commit subject may not be longer than 72 characters'
- )
-
- failures = true
- elsif subject.length > 50
- warn_commit(
- commit,
- "This commit's subject line could be improved. " \
- 'Commit subjects are ideally no longer than roughly 50 characters, ' \
- 'though we allow up to 72 characters in the subject. ' \
- 'If possible, try to reduce the length of the subject to roughly 50 characters.'
- )
- end
-
- unless subject_starts_with_capital?(subject)
- fail_commit(commit, 'The commit subject must start with a capital letter')
- failures = true
- end
-
- if subject.end_with?('.')
- fail_commit(commit, 'The commit subject must not end with a period')
- failures = true
- end
-
- if separator && !separator.empty?
- fail_commit(
- commit,
- 'The commit subject and body must be separated by a blank line'
- )
-
- failures = true
- end
-
- details&.each_line do |line|
- line = line.strip
-
- next if line.length <= 72
-
- url_size = line.scan(%r((https?://\S+))).sum { |(url)| url.length }
-
- # If the line includes a URL, we'll allow it to exceed 72 characters, but
- # only if the line _without_ the URL does not exceed this limit.
- next if line.length - url_size <= 72
-
- fail_commit(
- commit,
- 'The commit body should not contain more than 72 characters per line'
- )
-
- failures = true
- end
-
- if !details && too_many_changed_lines?(commit)
- fail_commit(
- commit,
- 'Commits that change 30 or more lines across at least three files ' \
- 'must describe these changes in the commit body'
- )
-
- failures = true
- end
-
- if emoji_checker.includes_emoji?(commit.message)
- fail_commit(
- commit,
- 'Avoid the use of Markdown Emoji such as `:+1:`. ' \
- 'These add no value to the commit message, ' \
- 'and are displayed as plain text outside of GitLab'
- )
-
- failures = true
- end
-
- if commit.message.match?(unicode_emoji_regex)
- fail_commit(
- commit,
- 'Avoid the use of Unicode Emoji. ' \
- 'These add no value to the commit message, ' \
- 'and may not be displayed properly everywhere'
- )
-
- failures = true
- end
-
- if commit.message.match?(%r(([\w\-\/]+)?(#|!|&|%)\d+))
- fail_commit(
- commit,
- 'Use full URLs instead of short references ' \
- '(`gitlab-org/gitlab-ce#123` or `!123`), as short references are ' \
- 'displayed as plain text outside of GitLab'
- )
-
- failures = true
- end
+ next if line.length <= 72
+
+ url_size = line.scan(%r((https?://\S+))).sum { |(url)| url.length }
+
+ # If the line includes a URL, we'll allow it to exceed 72 characters, but
+ # only if the line _without_ the URL does not exceed this limit.
+ next if line.length - url_size <= 72
+
+ fail_commit(
+ commit,
+ 'The commit body should not contain more than 72 characters per line'
+ )
+
+ failures = true
+ end
+
+ if !details && too_many_changed_lines?(commit)
+ fail_commit(
+ commit,
+ 'Commits that change 30 or more lines across at least three files ' \
+ 'must describe these changes in the commit body'
+ )
+
+ failures = true
+ end
+
+ if emoji_checker.includes_emoji?(commit.message)
+ fail_commit(
+ commit,
+ 'Avoid the use of Markdown Emoji such as `:+1:`. ' \
+ 'These add no value to the commit message, ' \
+ 'and are displayed as plain text outside of GitLab'
+ )
+
+ failures = true
+ end
+
+ if commit.message.match?(unicode_emoji_regex)
+ fail_commit(
+ commit,
+ 'Avoid the use of Unicode Emoji. ' \
+ 'These add no value to the commit message, ' \
+ 'and may not be displayed properly everywhere'
+ )
+
+ failures = true
+ end
+
+ if commit.message.match?(%r(([\w\-\/]+)?(#|!|&|%)\d+\b))
+ fail_commit(
+ commit,
+ 'Use full URLs instead of short references ' \
+ '(`gitlab-org/gitlab-ce#123` or `!123`), as short references are ' \
+ 'displayed as plain text outside of GitLab'
+ )
+
+ failures = true
+ end
+
+ failures
+end
+
+def lint_commits(commits)
+ failed = commits.select do |commit|
+ lint_commit(commit)
end
- if failures
+ if failed.any?
markdown(<<~MARKDOWN)
## Commit message standards
One or more commit messages do not meet our Git commit message standards.
For more information on how to write a good commit message, take a look at
- [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/).
+ [How to Write a Git Commit Message](#{URL_GIT_COMMIT}).
Here is an example of a good commit message:
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index 52af837c261..0cf478b4f89 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -1,47 +1,36 @@
# frozen_string_literal: true
-# All the files/directories that should be reviewed by the Docs team.
-DOCS_FILES = [
- 'doc/'
-].freeze
-
-def docs_paths_requiring_review(files)
- files.select do |file|
- DOCS_FILES.any? { |pattern| file.start_with?(pattern) }
- end
-end
-
-docs_paths_to_review = docs_paths_requiring_review(helper.all_changed_files)
+docs_paths_to_review = helper.changes_by_category[:docs]
unless docs_paths_to_review.empty?
- message 'This merge request adds or changes files that require a ' \
- 'review from the Docs team.'
+ message 'This merge request adds or changes files that require a review ' \
+ 'from the Technical Writing team whether before or after merging.'
markdown(<<~MARKDOWN)
-## Docs review
+## Documentation review
-The following files require a review from the Documentation team:
+The following files will require a review from the [Technical Writing](https://about.gitlab.com/handbook/product/technical-writing/) team:
* #{docs_paths_to_review.map { |path| "`#{path}`" }.join("\n* ")}
-When your content is ready for review, assign the MR to a technical writer
-according to the [DevOps stages](https://about.gitlab.com/handbook/product/categories/#devops-stages)
-in the table below. If necessary, mention them in a comment explaining what needs
-to be reviewed.
+Per the [documentation workflows](https://docs.gitlab.com/ee/development/documentation/workflow.html), the review may occur prior to merging this MR **or** after a maintainer has agreed to review and merge this MR without a tech writer review. (Meanwhile, you are welcome to involve a technical writer at any time if you have questions about writing or updating the documentation. GitLabbers are also welcome to use the [#docs](https://gitlab.slack.com/archives/C16HYA2P5) channel on Slack.)
+
+The technical writer who, by default, will review this content or collaborate as needed is dependent on the [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages) to which the content applies:
| Tech writer | Stage(s) |
| ------------ | ------------------------------------------------------------ |
| `@marcia` | ~Create ~Release + ~"development guidelines" |
-| `@axil` | ~Distribution ~Gitaly ~Gitter ~Monitoring ~Package ~Secure |
+| `@axil` | ~Distribution ~Gitaly ~Gitter ~Monitor ~Package ~Secure |
| `@eread` | ~Manage ~Configure ~Geo ~Verify |
| `@mikelewis` | ~Plan |
-You are welcome to mention them sooner if you have questions about writing or
-updating the documentation. GitLabbers are also welcome to use the
-[#docs](https://gitlab.slack.com/archives/C16HYA2P5) channel on Slack.
+**To request a review prior to merging**
+
+- Assign the MR to the applicable technical writer, above. If you are not sure which category the change falls within, or the change is not part of one of these categories, mention one of the usernames above.
+
+**To request a review to commence after merging**
-If you are not sure which category the change falls within, or the change is not
-part of one of these categories, mention one of the usernames above.
+- Create an issue for a doc review [using the Doc Review template](https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issuable_template=Doc%20Review) and assign it to the applicable technicial writer from the table.
MARKDOWN
unless gitlab.mr_labels.include?('Documentation')
diff --git a/danger/plugins/helper.rb b/danger/plugins/helper.rb
index f4eb9119266..581c0720083 100644
--- a/danger/plugins/helper.rb
+++ b/danger/plugins/helper.rb
@@ -1,34 +1,15 @@
# frozen_string_literal: true
+require 'net/http'
+require 'yaml'
+
+require_relative '../../lib/gitlab/danger/helper'
+
module Danger
- # Common helper functions for our danger scripts
- # If we find ourselves repeating code in our danger files, we might as well put them in here.
+ # Common helper functions for our danger scripts. See Gitlab::Danger::Helper
+ # for more details
class Helper < Plugin
- # Returns a list of all files that have been added, modified or renamed.
- # `git.modified_files` might contain paths that already have been renamed,
- # so we need to remove them from the list.
- #
- # Considering these changes:
- #
- # - A new_file.rb
- # - D deleted_file.rb
- # - M modified_file.rb
- # - R renamed_file_before.rb -> renamed_file_after.rb
- #
- # it will return
- # ```
- # [ 'new_file.rb', 'modified_file.rb', 'renamed_file_after.rb' ]
- # ```
- #
- # @return [Array<String>]
- def all_changed_files
- Set.new
- .merge(git.added_files.to_a)
- .merge(git.modified_files.to_a)
- .merge(git.renamed_files.map { |x| x[:after] })
- .subtract(git.renamed_files.map { |x| x[:before] })
- .to_a
- .sort
- end
+ # Put the helper code somewhere it can be tested
+ include Gitlab::Danger::Helper
end
end
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
new file mode 100644
index 00000000000..6cf54d0f854
--- /dev/null
+++ b/danger/roulette/Dangerfile
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+MESSAGE = <<MARKDOWN
+## Reviewer roulette
+
+Changes that require review have been detected! A merge request is normally
+reviewed by both a reviewer and a maintainer in its primary category (e.g.
+~frontend or ~backend), and by a maintainer in all other categories.
+MARKDOWN
+
+CATEGORY_TABLE_HEADER = <<MARKDOWN
+
+To spread load more evenly across eligible reviewers, Danger has randomly picked
+a candidate for each review slot. Feel free to override this selection if you
+think someone else would be better-suited, or the chosen person is unavailable.
+
+Once you've decided who will review this merge request, mention them as you
+normally would! Danger does not (yet?) automatically notify them for you.
+
+| Category | Reviewer | Maintainer |
+| -------- | -------- | ---------- |
+MARKDOWN
+
+UNKNOWN_FILES_MESSAGE = <<MARKDOWN
+
+These files couldn't be categorised, so Danger was unable to suggest a reviewer.
+Please consider creating a merge request to
+[add support](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/danger/helper.rb)
+for them.
+MARKDOWN
+
+def spin(team, project, category)
+ reviewers = team.select { |member| member.reviewer?(project, category) }
+ maintainers = team.select { |member| member.maintainer?(project, category) }
+
+ # TODO: filter out people who are currently not in the office
+ # TODO: take CODEOWNERS into account?
+
+ reviewer = reviewers[rand(reviewers.size)]
+ maintainer = maintainers[rand(maintainers.size)]
+
+ "| #{helper.label_for_category(category)} | #{reviewer&.markdown_name} | #{maintainer&.markdown_name} |"
+end
+
+def build_list(items)
+ list = items.map { |filename| "* `#{filename}`" }.join("\n")
+
+ if items.size > 10
+ "\n<details>\n\n#{list}\n\n</details>"
+ else
+ list
+ end
+end
+
+changes = helper.changes_by_category
+
+# Ignore any files that are known but uncategoried. Prompt for any unknown files
+changes.delete(:none)
+categories = changes.keys - [:unknown]
+
+unless changes.empty?
+ team =
+ begin
+ helper.project_team
+ rescue => err
+ warn("Reviewer roulette failed to load team data: #{err.message}")
+ []
+ end
+
+ # Exclude the MR author from the team for selection purposes
+ team.delete_if { |teammate| teammate.username == gitlab.mr_author }
+
+ project = helper.project_name
+ unknown = changes.fetch(:unknown, [])
+
+ rows = categories.map { |category| spin(team, project, category) }
+
+ markdown(MESSAGE)
+ markdown(CATEGORY_TABLE_HEADER + rows.join("\n")) unless rows.empty?
+ markdown(UNKNOWN_FILES_MESSAGE + build_list(unknown)) unless unknown.empty?
+end
diff --git a/db/fixtures/development/04_project.rb b/db/fixtures/development/04_project.rb
index aa8686ac7d8..9a5f7cf8175 100644
--- a/db/fixtures/development/04_project.rb
+++ b/db/fixtures/development/04_project.rb
@@ -1,94 +1,136 @@
require './spec/support/sidekiq'
+# rubocop:disable Rails/Output
+
Sidekiq::Testing.inline! do
Gitlab::Seeder.quiet do
- project_urls = [
- 'https://gitlab.com/gitlab-org/gitlab-test.git',
- 'https://gitlab.com/gitlab-org/gitlab-shell.git',
- 'https://gitlab.com/gnuwget/wget2.git',
- 'https://gitlab.com/Commit451/LabCoat.git',
- 'https://github.com/jashkenas/underscore.git',
- 'https://github.com/flightjs/flight.git',
- 'https://github.com/twitter/typeahead.js.git',
- 'https://github.com/h5bp/html5-boilerplate.git',
- 'https://github.com/google/material-design-lite.git',
- 'https://github.com/jlevy/the-art-of-command-line.git',
- 'https://github.com/FreeCodeCamp/freecodecamp.git',
- 'https://github.com/google/deepdream.git',
- 'https://github.com/jtleek/datasharing.git',
- 'https://github.com/WebAssembly/design.git',
- 'https://github.com/airbnb/javascript.git',
- 'https://github.com/tessalt/echo-chamber-js.git',
- 'https://github.com/atom/atom.git',
- 'https://github.com/mattermost/mattermost-server.git',
- 'https://github.com/purifycss/purifycss.git',
- 'https://github.com/facebook/nuclide.git',
- 'https://github.com/wbkd/awesome-d3.git',
- 'https://github.com/kilimchoi/engineering-blogs.git',
- 'https://github.com/gilbarbara/logos.git',
- 'https://github.com/reduxjs/redux.git',
- 'https://github.com/awslabs/s2n.git',
- 'https://github.com/arkency/reactjs_koans.git',
- 'https://github.com/twbs/bootstrap.git',
- 'https://github.com/chjj/ttystudio.git',
- 'https://github.com/MostlyAdequate/mostly-adequate-guide.git',
- 'https://github.com/octocat/Spoon-Knife.git',
- 'https://github.com/opencontainers/runc.git',
- 'https://github.com/googlesamples/android-topeka.git'
- ]
-
- # You can specify how many projects you need during seed execution
- size = ENV['SIZE'].present? ? ENV['SIZE'].to_i : 8
-
- project_urls.first(size).each_with_index do |url, i|
- group_path, project_path = url.split('/')[-2..-1]
-
- group = Group.find_by(path: group_path)
-
- unless group
- group = Group.new(
- name: group_path.titleize,
- path: group_path
- )
- group.description = FFaker::Lorem.sentence
- group.save
-
- group.add_owner(User.first)
- end
+ Gitlab::Seeder.without_gitaly_timeout do
+ project_urls = %w[
+ https://gitlab.com/gitlab-org/gitlab-test.git
+ https://gitlab.com/gitlab-org/gitlab-shell.git
+ https://gitlab.com/gnuwget/wget2.git
+ https://gitlab.com/Commit451/LabCoat.git
+ https://github.com/jashkenas/underscore.git
+ https://github.com/flightjs/flight.git
+ https://github.com/twitter/typeahead.js.git
+ https://github.com/h5bp/html5-boilerplate.git
+ https://github.com/google/material-design-lite.git
+ https://github.com/jlevy/the-art-of-command-line.git
+ https://github.com/FreeCodeCamp/freecodecamp.git
+ https://github.com/google/deepdream.git
+ https://github.com/jtleek/datasharing.git
+ https://github.com/WebAssembly/design.git
+ https://github.com/airbnb/javascript.git
+ https://github.com/tessalt/echo-chamber-js.git
+ https://github.com/atom/atom.git
+ https://github.com/mattermost/mattermost-server.git
+ https://github.com/purifycss/purifycss.git
+ https://github.com/facebook/nuclide.git
+ https://github.com/wbkd/awesome-d3.git
+ https://github.com/kilimchoi/engineering-blogs.git
+ https://github.com/gilbarbara/logos.git
+ https://github.com/reduxjs/redux.git
+ https://github.com/awslabs/s2n.git
+ https://github.com/arkency/reactjs_koans.git
+ https://github.com/twbs/bootstrap.git
+ https://github.com/chjj/ttystudio.git
+ https://github.com/MostlyAdequate/mostly-adequate-guide.git
+ https://github.com/octocat/Spoon-Knife.git
+ https://github.com/opencontainers/runc.git
+ https://github.com/googlesamples/android-topeka.git
+ ]
- project_path.gsub!(".git", "")
+ large_project_urls = %w[
+ https://github.com/torvalds/linux.git
+ https://gitlab.gnome.org/GNOME/gimp.git
+ https://gitlab.gnome.org/GNOME/gnome-mud.git
+ https://gitlab.com/fdroid/fdroidclient.git
+ https://gitlab.com/inkscape/inkscape.git
+ https://github.com/gnachman/iTerm2.git
+ ]
- params = {
- import_url: url,
- namespace_id: group.id,
- name: project_path.titleize,
- description: FFaker::Lorem.sentence,
- visibility_level: Gitlab::VisibilityLevel.values.sample,
- skip_disk_validation: true
- }
+ def create_project(url, force_latest_storage: false)
+ group_path, project_path = url.split('/')[-2..-1]
- if i % 2 == 0
- params[:storage_version] = Project::LATEST_STORAGE_VERSION
- end
+ group = Group.find_by(path: group_path)
+
+ unless group
+ group = Group.new(
+ name: group_path.titleize,
+ path: group_path
+ )
+ group.description = FFaker::Lorem.sentence
+ group.save
+
+ group.add_owner(User.first)
+ end
+
+ project_path.gsub!(".git", "")
+
+ params = {
+ import_url: url,
+ namespace_id: group.id,
+ name: project_path.titleize,
+ description: FFaker::Lorem.sentence,
+ visibility_level: Gitlab::VisibilityLevel.values.sample,
+ skip_disk_validation: true
+ }
+
+ if force_latest_storage
+ params[:storage_version] = Project::LATEST_STORAGE_VERSION
+ end
+
+ project = nil
- project = nil
+ Sidekiq::Worker.skipping_transaction_check do
+ project = Projects::CreateService.new(User.first, params).execute
- Sidekiq::Worker.skipping_transaction_check do
- project = Projects::CreateService.new(User.first, params).execute
+ # Seed-Fu runs this entire fixture in a transaction, so the `after_commit`
+ # hook won't run until after the fixture is loaded. That is too late
+ # since the Sidekiq::Testing block has already exited. Force clearing
+ # the `after_commit` queue to ensure the job is run now.
+ project.send(:_run_after_commit_queue)
+ project.import_state.send(:_run_after_commit_queue)
+ end
- # Seed-Fu runs this entire fixture in a transaction, so the `after_commit`
- # hook won't run until after the fixture is loaded. That is too late
- # since the Sidekiq::Testing block has already exited. Force clearing
- # the `after_commit` queue to ensure the job is run now.
- project.send(:_run_after_commit_queue)
- project.import_state.send(:_run_after_commit_queue)
+ if project.valid? && project.valid_repo?
+ print '.'
+ else
+ puts project.errors.full_messages
+ print 'F'
+ end
end
- if project.valid? && project.valid_repo?
- print '.'
- else
- puts project.errors.full_messages
- print 'F'
+ # You can specify how many projects you need during seed execution
+ size = ENV['SIZE'].present? ? ENV['SIZE'].to_i : 8
+
+ project_urls.first(size).each_with_index do |url, i|
+ create_project(url, force_latest_storage: i.even?)
+ end
+
+ if ENV['LARGE_PROJECTS'].present?
+ large_project_urls.each(&method(:create_project))
+
+ if ENV['FORK'].present?
+ puts "\nGenerating forks"
+
+ project_name = ENV['FORK'] == 'true' ? 'torvalds/linux' : ENV['FORK']
+
+ project = Project.find_by_full_path(project_name)
+
+ User.offset(1).first(5).each do |user|
+ new_project = Projects::ForkService.new(project, user).execute
+
+ if new_project.valid? && (new_project.valid_repo? || new_project.import_state.scheduled?)
+ print '.'
+ else
+ new_project.errors.full_messages.each do |error|
+ puts "#{new_project.full_path}: #{error}"
+ end
+ print 'F'
+ end
+ end
+ end
end
end
end
diff --git a/db/fixtures/development/10_merge_requests.rb b/db/fixtures/development/10_merge_requests.rb
index 8bdc7c6556c..2051bcff8f0 100644
--- a/db/fixtures/development/10_merge_requests.rb
+++ b/db/fixtures/development/10_merge_requests.rb
@@ -27,6 +27,9 @@ Gitlab::Seeder.quiet do
Sidekiq::Worker.skipping_transaction_check do
MergeRequests::CreateService.new(project, developer, params).execute
+ rescue Repository::AmbiguousRefError
+ # Ignore pipelines creation errors for now, we can doing that after
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/55966. will be resolved.
end
print '.'
end
diff --git a/db/fixtures/development/14_pipelines.rb b/db/fixtures/development/14_pipelines.rb
index bdc0a2db7db..db043e39d2c 100644
--- a/db/fixtures/development/14_pipelines.rb
+++ b/db/fixtures/development/14_pipelines.rb
@@ -102,14 +102,15 @@ class Gitlab::Seeder::Pipelines
[]
end
-
def create_pipeline!(project, ref, commit)
project.ci_pipelines.create!(sha: commit.id, ref: ref, source: :push)
end
def build_create!(pipeline, opts = {})
attributes = job_attributes(pipeline, opts)
- .merge(commands: '$ build command')
+
+ attributes[:options] ||= {}
+ attributes[:options][:script] = 'build command'
Ci::Build.create!(attributes).tap do |build|
# We need to set build trace and artifacts after saving a build
diff --git a/db/migrate/20140502125220_migrate_repo_size.rb b/db/migrate/20140502125220_migrate_repo_size.rb
index a69b02cddc4..bff1f01c654 100644
--- a/db/migrate/20140502125220_migrate_repo_size.rb
+++ b/db/migrate/20140502125220_migrate_repo_size.rb
@@ -11,7 +11,7 @@ class MigrateRepoSize < ActiveRecord::Migration[4.2]
path = File.join(namespace_path, project['project_path'] + '.git')
begin
- repo = Gitlab::Git::Repository.new('default', path, '')
+ repo = Gitlab::Git::Repository.new('default', path, '', '')
if repo.empty?
print '-'
else
diff --git a/db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb b/db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb
index 85aa78006db..3ee9c959fca 100644
--- a/db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb
+++ b/db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb
@@ -28,7 +28,7 @@ class AddCiBuildsIndexForJobscontroller < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
def up
- add_concurrent_index :ci_builds, [:project_id, :id] unless index_exists? :ci_builds, [:project_id, :id]
+ add_concurrent_index :ci_builds, [:project_id, :id] unless index_exists? :ci_builds, [:project_id, :id]
remove_concurrent_index :ci_builds, :project_id if index_exists? :ci_builds, :project_id
end
diff --git a/db/migrate/20180209115333_create_chatops_tables.rb b/db/migrate/20180209115333_create_chatops_tables.rb
new file mode 100644
index 00000000000..2cfb71e1007
--- /dev/null
+++ b/db/migrate/20180209115333_create_chatops_tables.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class CreateChatopsTables < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :ci_pipeline_chat_data, id: :bigserial do |t|
+ t.integer :pipeline_id, null: false
+ t.references :chat_name, foreign_key: { on_delete: :cascade }, null: false
+ t.text :response_url, null: false
+
+ # A pipeline can only contain one row in this table, hence this index is
+ # unique.
+ t.index :pipeline_id, unique: true
+
+ t.index :chat_name_id
+ end
+
+ # rubocop:disable Migration/AddConcurrentForeignKey
+ add_foreign_key :ci_pipeline_chat_data, :ci_pipelines,
+ column: :pipeline_id,
+ on_delete: :cascade
+ end
+end
diff --git a/db/migrate/20180314145917_add_header_and_footer_banners_to_appearances_table.rb b/db/migrate/20180314145917_add_header_and_footer_banners_to_appearances_table.rb
new file mode 100644
index 00000000000..8aba3448035
--- /dev/null
+++ b/db/migrate/20180314145917_add_header_and_footer_banners_to_appearances_table.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddHeaderAndFooterBannersToAppearancesTable < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :appearances, :header_message, :text
+ add_column :appearances, :header_message_html, :text
+
+ add_column :appearances, :footer_message, :text
+ add_column :appearances, :footer_message_html, :text
+
+ add_column :appearances, :message_background_color, :text
+ add_column :appearances, :message_font_color, :text
+ end
+end
diff --git a/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
index 90d869a8c10..8de8b3bcc2e 100644
--- a/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
+++ b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
@@ -46,7 +46,7 @@ class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration[4.2]
end
insert_query = "INSERT INTO namespaces(owner_id, path, name, created_at, updated_at) VALUES(#{user_id}, '#{path}', '#{path}', NOW(), NOW())"
- namespace_id = connection.insert_sql(insert_query)
+ namespace_id = connection.insert(insert_query)
create_route(namespace_id)
end
diff --git a/db/migrate/20181027114222_add_first_day_of_week_to_user_preferences.rb b/db/migrate/20181027114222_add_first_day_of_week_to_user_preferences.rb
new file mode 100644
index 00000000000..96ba5fbd816
--- /dev/null
+++ b/db/migrate/20181027114222_add_first_day_of_week_to_user_preferences.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddFirstDayOfWeekToUserPreferences < ActiveRecord::Migration[5.0]
+ DOWNTIME = false
+
+ def change
+ add_column :user_preferences, :first_day_of_week, :integer
+ end
+end
diff --git a/db/migrate/20181028120717_add_first_day_of_week_to_application_settings.rb b/db/migrate/20181028120717_add_first_day_of_week_to_application_settings.rb
new file mode 100644
index 00000000000..e9a8c1011ad
--- /dev/null
+++ b/db/migrate/20181028120717_add_first_day_of_week_to_application_settings.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddFirstDayOfWeekToApplicationSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+
+ def up
+ add_column_with_default(:application_settings, :first_day_of_week, :integer, default: 0)
+ end
+
+ def down
+ remove_column(:application_settings, :first_day_of_week)
+ end
+end
diff --git a/db/migrate/20181119132520_add_indexes_to_ci_builds_and_pipelines.rb b/db/migrate/20181119132520_add_indexes_to_ci_builds_and_pipelines.rb
new file mode 100644
index 00000000000..cb01fa113eb
--- /dev/null
+++ b/db/migrate/20181119132520_add_indexes_to_ci_builds_and_pipelines.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class AddIndexesToCiBuildsAndPipelines < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ indexes.each do |index|
+ add_concurrent_index(*index)
+ end
+ end
+
+ def down
+ indexes.each do |index|
+ remove_concurrent_index(*index)
+ end
+ end
+
+ private
+
+ def indexes
+ [
+ [
+ :ci_pipelines,
+ [:project_id, :ref, :id],
+ {
+ order: { id: :desc },
+ name: 'index_ci_pipelines_on_project_idandrefandiddesc'
+ }
+ ],
+ [
+ :ci_builds,
+ [:commit_id, :artifacts_expire_at, :id],
+ {
+ where: "type::text = 'Ci::Build'::text AND (retried = false OR retried IS NULL) AND (name::text = ANY (ARRAY['sast'::character varying, 'dependency_scanning'::character varying, 'sast:container'::character varying, 'container_scanning'::character varying, 'dast'::character varying]::text[]))",
+ name: 'index_ci_builds_on_commit_id_and_artifacts_expireatandidpartial'
+ }
+ ]
+ ]
+ end
+end
diff --git a/db/migrate/20181205171941_create_project_daily_statistics.rb b/db/migrate/20181205171941_create_project_daily_statistics.rb
new file mode 100644
index 00000000000..c9e2a1e1aa7
--- /dev/null
+++ b/db/migrate/20181205171941_create_project_daily_statistics.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CreateProjectDailyStatistics < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :project_daily_statistics, id: :bigserial do |t|
+ t.integer :project_id, null: false
+ t.integer :fetch_count, null: false
+ t.date :date
+
+ t.index [:project_id, :date], unique: true, order: { date: :desc }
+ t.foreign_key :projects, on_delete: :cascade
+ end
+ end
+end
diff --git a/db/migrate/20181212171634_create_error_tracking_settings.rb b/db/migrate/20181212171634_create_error_tracking_settings.rb
new file mode 100644
index 00000000000..18c38bd2c47
--- /dev/null
+++ b/db/migrate/20181212171634_create_error_tracking_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class CreateErrorTrackingSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :project_error_tracking_settings, id: :int, primary_key: :project_id, default: nil do |t|
+ t.boolean :enabled, null: false, default: true
+ t.string :api_url, null: false
+ t.string :encrypted_token
+ t.string :encrypted_token_iv
+ t.foreign_key :projects, column: :project_id, on_delete: :cascade
+ end
+ end
+end
diff --git a/db/migrate/20181219145521_add_options_to_build_metadata.rb b/db/migrate/20181219145521_add_options_to_build_metadata.rb
new file mode 100644
index 00000000000..dc9569babc2
--- /dev/null
+++ b/db/migrate/20181219145521_add_options_to_build_metadata.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddOptionsToBuildMetadata < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :ci_builds_metadata, :config_options, :jsonb
+ add_column :ci_builds_metadata, :config_variables, :jsonb
+ end
+end
diff --git a/db/migrate/20181228175414_create_releases_link_table.rb b/db/migrate/20181228175414_create_releases_link_table.rb
new file mode 100644
index 00000000000..03558202137
--- /dev/null
+++ b/db/migrate/20181228175414_create_releases_link_table.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class CreateReleasesLinkTable < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :release_links, id: :bigserial do |t|
+ t.references :release, null: false, index: false, foreign_key: { on_delete: :cascade }
+ t.string :url, null: false
+ t.string :name, null: false
+ t.timestamps_with_timezone null: false
+
+ t.index [:release_id, :url], unique: true
+ t.index [:release_id, :name], unique: true
+ end
+ end
+end
diff --git a/db/migrate/20190103140724_make_legacy_false_default.rb b/db/migrate/20190103140724_make_legacy_false_default.rb
new file mode 100644
index 00000000000..154035f76cd
--- /dev/null
+++ b/db/migrate/20190103140724_make_legacy_false_default.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class MakeLegacyFalseDefault < ActiveRecord::Migration[5.0]
+ DOWNTIME = false
+
+ def change
+ change_column_default :cluster_providers_gcp, :legacy_abac, from: true, to: false
+ end
+end
diff --git a/db/migrate/20190104182041_cleanup_legacy_artifact_migration.rb b/db/migrate/20190104182041_cleanup_legacy_artifact_migration.rb
new file mode 100644
index 00000000000..11659846a06
--- /dev/null
+++ b/db/migrate/20190104182041_cleanup_legacy_artifact_migration.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+class CleanupLegacyArtifactMigration < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class Build < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'ci_builds'
+ self.inheritance_column = :_type_disabled
+
+ scope :with_legacy_artifacts, -> { where("artifacts_file <> ''") }
+ end
+
+ def up
+ Gitlab::BackgroundMigration.steal('MigrateLegacyArtifacts')
+
+ CleanupLegacyArtifactMigration::Build
+ .with_legacy_artifacts
+ .each_batch(of: 100) do |batch|
+ range = batch.pluck('MIN(id)', 'MAX(id)').first
+
+ Gitlab::BackgroundMigration::MigrateLegacyArtifacts.new.perform(*range)
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20190107151020_add_services_type_index.rb b/db/migrate/20190107151020_add_services_type_index.rb
new file mode 100644
index 00000000000..26b5bd58750
--- /dev/null
+++ b/db/migrate/20190107151020_add_services_type_index.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddServicesTypeIndex < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :services, :type unless index_exists?(:services, :type)
+ end
+
+ def down
+ remove_concurrent_index :services, :type if index_exists?(:services, :type)
+ end
+end
diff --git a/db/migrate/20190107151029_remove_hipchat_services.rb b/db/migrate/20190107151029_remove_hipchat_services.rb
new file mode 100644
index 00000000000..4741ec88907
--- /dev/null
+++ b/db/migrate/20190107151029_remove_hipchat_services.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class RemoveHipchatServices < ActiveRecord::Migration[5.0]
+ DOWNTIME = false
+
+ def up
+ execute "DELETE FROM services WHERE type = 'HipchatService'"
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb b/db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb
new file mode 100644
index 00000000000..073faf721ae
--- /dev/null
+++ b/db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class RemovePartialIndexFromCiBuildsArtifactsFile < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'partial_index_ci_builds_on_id_with_legacy_artifacts'.freeze
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name(:ci_builds, INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(:ci_builds, :id, where: "artifacts_file <> ''", name: INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20190109153125_add_merge_request_external_diffs.rb b/db/migrate/20190109153125_add_merge_request_external_diffs.rb
new file mode 100644
index 00000000000..c67903c7f67
--- /dev/null
+++ b/db/migrate/20190109153125_add_merge_request_external_diffs.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddMergeRequestExternalDiffs < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def change
+ # Allow the merge request diff to store details about an external file
+ add_column :merge_request_diffs, :external_diff, :string
+ add_column :merge_request_diffs, :external_diff_store, :integer
+ add_column :merge_request_diffs, :stored_externally, :boolean
+
+ # The diff for each file is mapped to a range in the external file
+ add_column :merge_request_diff_files, :external_diff_offset, :integer
+ add_column :merge_request_diff_files, :external_diff_size, :integer
+
+ # If the diff is in object storage, it will be null in the database
+ change_column_null :merge_request_diff_files, :diff, true
+ end
+end
diff --git a/db/migrate/20190114172110_add_domain_to_cluster.rb b/db/migrate/20190114172110_add_domain_to_cluster.rb
new file mode 100644
index 00000000000..58d7664b8c0
--- /dev/null
+++ b/db/migrate/20190114172110_add_domain_to_cluster.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddDomainToCluster < ActiveRecord::Migration[5.0]
+ DOWNTIME = false
+
+ def change
+ add_column :clusters, :domain, :string
+ end
+end
diff --git a/db/migrate/20190115054216_add_error_notification_sent_to_remote_mirrors.rb b/db/migrate/20190115054216_add_error_notification_sent_to_remote_mirrors.rb
new file mode 100644
index 00000000000..d8f979a1848
--- /dev/null
+++ b/db/migrate/20190115054216_add_error_notification_sent_to_remote_mirrors.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddErrorNotificationSentToRemoteMirrors < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :remote_mirrors, :error_notification_sent, :boolean
+ end
+end
diff --git a/db/migrate/20190115092821_add_columns_project_error_tracking_settings.rb b/db/migrate/20190115092821_add_columns_project_error_tracking_settings.rb
new file mode 100644
index 00000000000..190b6f958fd
--- /dev/null
+++ b/db/migrate/20190115092821_add_columns_project_error_tracking_settings.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddColumnsProjectErrorTrackingSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :project_error_tracking_settings, :project_name, :string
+ add_column :project_error_tracking_settings, :organization_name, :string
+
+ change_column_default :project_error_tracking_settings, :enabled, from: true, to: false
+
+ change_column_null :project_error_tracking_settings, :api_url, true
+ end
+end
diff --git a/db/migrate/20190116234221_add_sorting_fields_to_user_preference.rb b/db/migrate/20190116234221_add_sorting_fields_to_user_preference.rb
new file mode 100644
index 00000000000..7bf581fe9b0
--- /dev/null
+++ b/db/migrate/20190116234221_add_sorting_fields_to_user_preference.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddSortingFieldsToUserPreference < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def up
+ add_column :user_preferences, :issues_sort, :string
+ add_column :user_preferences, :merge_requests_sort, :string
+ end
+
+ def down
+ remove_column :user_preferences, :issues_sort
+ remove_column :user_preferences, :merge_requests_sort
+ end
+end
diff --git a/db/migrate/20190130091630_add_local_cached_markdown_version.rb b/db/migrate/20190130091630_add_local_cached_markdown_version.rb
new file mode 100644
index 00000000000..00570e6458c
--- /dev/null
+++ b/db/migrate/20190130091630_add_local_cached_markdown_version.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddLocalCachedMarkdownVersion < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :local_markdown_version, :integer, default: 0, null: false
+ end
+end
diff --git a/db/migrate/20190206193120_add_index_to_tags.rb b/db/migrate/20190206193120_add_index_to_tags.rb
new file mode 100644
index 00000000000..5257ebba003
--- /dev/null
+++ b/db/migrate/20190206193120_add_index_to_tags.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexToTags < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_tags_on_name_trigram'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :tags, :name, name: INDEX_NAME, using: :gin, opclasses: { name: :gin_trgm_ops }
+ end
+
+ def down
+ remove_concurrent_index_by_name(:tags, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20190215154930_add_merge_pipelines_enabled_to_ci_cd_settings.rb b/db/migrate/20190215154930_add_merge_pipelines_enabled_to_ci_cd_settings.rb
new file mode 100644
index 00000000000..2a2a216da7d
--- /dev/null
+++ b/db/migrate/20190215154930_add_merge_pipelines_enabled_to_ci_cd_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddMergePipelinesEnabledToCiCdSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :project_ci_cd_settings, :merge_pipelines_enabled, :boolean
+ end
+end
diff --git a/db/migrate/20190218134158_add_masked_to_ci_variables.rb b/db/migrate/20190218134158_add_masked_to_ci_variables.rb
new file mode 100644
index 00000000000..b4999d5b4a9
--- /dev/null
+++ b/db/migrate/20190218134158_add_masked_to_ci_variables.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddMaskedToCiVariables < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :ci_variables, :masked, :boolean, default: false, allow_null: false
+ end
+
+ def down
+ remove_column :ci_variables, :masked
+ end
+end
diff --git a/db/migrate/20190218134209_add_masked_to_ci_group_variables.rb b/db/migrate/20190218134209_add_masked_to_ci_group_variables.rb
new file mode 100644
index 00000000000..8633875b341
--- /dev/null
+++ b/db/migrate/20190218134209_add_masked_to_ci_group_variables.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddMaskedToCiGroupVariables < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :ci_group_variables, :masked, :boolean, default: false, allow_null: false
+ end
+
+ def down
+ remove_column :ci_group_variables, :masked
+ end
+end
diff --git a/db/migrate/20190220142344_add_email_header_and_footer_enabled_flag_to_appearances_table.rb b/db/migrate/20190220142344_add_email_header_and_footer_enabled_flag_to_appearances_table.rb
new file mode 100644
index 00000000000..85b9e0580f4
--- /dev/null
+++ b/db/migrate/20190220142344_add_email_header_and_footer_enabled_flag_to_appearances_table.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddEmailHeaderAndFooterEnabledFlagToAppearancesTable < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+
+ def up
+ add_column_with_default(:appearances, :email_header_and_footer_enabled, :boolean, default: false)
+ end
+
+ def down
+ remove_column(:appearances, :email_header_and_footer_enabled)
+ end
+end
diff --git a/db/migrate/20190220150130_add_extra_shas_to_ci_pipelines.rb b/db/migrate/20190220150130_add_extra_shas_to_ci_pipelines.rb
new file mode 100644
index 00000000000..45c7c0949c6
--- /dev/null
+++ b/db/migrate/20190220150130_add_extra_shas_to_ci_pipelines.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class AddExtraShasToCiPipelines < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :ci_pipelines, :source_sha, :binary
+ add_column :ci_pipelines, :target_sha, :binary
+ end
+end
diff --git a/db/migrate/20190225160300_steal_encrypt_runners_tokens.rb b/db/migrate/20190225160300_steal_encrypt_runners_tokens.rb
new file mode 100644
index 00000000000..18c0d2a2e1b
--- /dev/null
+++ b/db/migrate/20190225160300_steal_encrypt_runners_tokens.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class StealEncryptRunnersTokens < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # This cleans after `EncryptRunnersTokens`
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration.steal('EncryptRunnersTokens')
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20190225160301_add_runner_tokens_indexes.rb b/db/migrate/20190225160301_add_runner_tokens_indexes.rb
new file mode 100644
index 00000000000..3230c2809de
--- /dev/null
+++ b/db/migrate/20190225160301_add_runner_tokens_indexes.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class AddRunnerTokensIndexes < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ # It seems that `ci_runners.token_encrypted` and `projects.runners_token_encrypted`
+ # are non-unique
+
+ def up
+ add_concurrent_index :ci_runners, :token_encrypted
+ add_concurrent_index :projects, :runners_token_encrypted
+ add_concurrent_index :namespaces, :runners_token_encrypted, unique: true
+ end
+
+ def down
+ remove_concurrent_index :ci_runners, :token_encrypted
+ remove_concurrent_index :projects, :runners_token_encrypted
+ remove_concurrent_index :namespaces, :runners_token_encrypted, unique: true
+ end
+end
diff --git a/db/migrate/limits_to_mysql.rb b/db/migrate/limits_to_mysql.rb
index 87992b541b1..33cb19aff9e 100644
--- a/db/migrate/limits_to_mysql.rb
+++ b/db/migrate/limits_to_mysql.rb
@@ -2,19 +2,6 @@ class LimitsToMysql < ActiveRecord::Migration[4.2]
def up
return unless ActiveRecord::Base.configurations[Rails.env]['adapter'] =~ /^mysql/
- # These columns were removed in 10.3, but this is called from two places:
- # 1. A migration run after they were added, but before they were removed.
- # 2. A rake task which can be run at any time.
- #
- # Because of item 2, we need these checks.
- if column_exists?(:merge_request_diffs, :st_commits)
- change_column :merge_request_diffs, :st_commits, :text, limit: 2147483647
- end
-
- if column_exists?(:merge_request_diffs, :st_diffs)
- change_column :merge_request_diffs, :st_diffs, :text, limit: 2147483647
- end
-
change_column :snippets, :content, :text, limit: 2147483647
change_column :notes, :st_diff, :text, limit: 2147483647
end
diff --git a/db/post_migrate/20161221153951_rename_reserved_project_names.rb b/db/post_migrate/20161221153951_rename_reserved_project_names.rb
index 50e1c8449ba..32579256299 100644
--- a/db/post_migrate/20161221153951_rename_reserved_project_names.rb
+++ b/db/post_migrate/20161221153951_rename_reserved_project_names.rb
@@ -113,7 +113,7 @@ class RenameReservedProjectNames < ActiveRecord::Migration[4.2]
# Because project path update is quite complex operation we can't safely
# copy-paste all code from GitLab. As exception we use Rails code here
if rename_project_row(project, path)
- Projects::AfterRenameService.new(project).execute
+ after_rename_service(project, path_was, namespace_path).execute
end
rescue Exception => e # rubocop: disable Lint/RescueException
Rails.logger.error "Exception when renaming project #{id}: #{e.message}"
@@ -126,4 +126,12 @@ class RenameReservedProjectNames < ActiveRecord::Migration[4.2]
project.update(path: path) &&
defined?(Projects::AfterRenameService)
end
+
+ def after_rename_service(project, path_was, namespace_path)
+ AfterRenameService.new(
+ project,
+ path_before: path_was,
+ full_path_before: "#{namespace_path}/#{path_was}"
+ ).execute
+ end
end
diff --git a/db/post_migrate/20170313133418_rename_more_reserved_project_names.rb b/db/post_migrate/20170313133418_rename_more_reserved_project_names.rb
index bef669b459d..85c97e3687e 100644
--- a/db/post_migrate/20170313133418_rename_more_reserved_project_names.rb
+++ b/db/post_migrate/20170313133418_rename_more_reserved_project_names.rb
@@ -55,7 +55,7 @@ class RenameMoreReservedProjectNames < ActiveRecord::Migration[4.2]
# Because project path update is quite complex operation we can't safely
# copy-paste all code from GitLab. As exception we use Rails code here
if rename_project_row(project, path)
- Projects::AfterRenameService.new(project).execute
+ after_rename_service(project, path_was, namespace_path).execute
end
rescue Exception => e # rubocop: disable Lint/RescueException
Rails.logger.error "Exception when renaming project #{id}: #{e.message}"
@@ -68,4 +68,12 @@ class RenameMoreReservedProjectNames < ActiveRecord::Migration[4.2]
project.update(path: path) &&
defined?(Projects::AfterRenameService)
end
+
+ def after_rename_service(project, path_was, namespace_path)
+ AfterRenameService.new(
+ project,
+ path_before: path_was,
+ full_path_before: "#{namespace_path}/#{path_was}"
+ ).execute
+ end
end
diff --git a/db/post_migrate/20170317162059_update_upload_paths_to_system.rb b/db/post_migrate/20170317162059_update_upload_paths_to_system.rb
index a5a6f043e10..99cdca465e2 100644
--- a/db/post_migrate/20170317162059_update_upload_paths_to_system.rb
+++ b/db/post_migrate/20170317162059_update_upload_paths_to_system.rb
@@ -48,7 +48,7 @@ class UpdateUploadPathsToSystem < ActiveRecord::Migration[4.2]
end
def new_upload_dir
- File.join(base_directory, "-", "system")
+ File.join(base_directory, "-", "system")
end
def arel_table
diff --git a/db/post_migrate/20181101091005_steal_digest_column.rb b/db/post_migrate/20181101091005_steal_digest_column.rb
new file mode 100644
index 00000000000..58ea710c18a
--- /dev/null
+++ b/db/post_migrate/20181101091005_steal_digest_column.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class StealDigestColumn < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration.steal('DigestColumn')
+ end
+
+ def down
+ # raise ActiveRecord::IrreversibleMigration
+ end
+end
diff --git a/db/post_migrate/20181101091124_remove_token_from_personal_access_tokens.rb b/db/post_migrate/20181101091124_remove_token_from_personal_access_tokens.rb
new file mode 100644
index 00000000000..415373068d5
--- /dev/null
+++ b/db/post_migrate/20181101091124_remove_token_from_personal_access_tokens.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class RemoveTokenFromPersonalAccessTokens < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ remove_column :personal_access_tokens, :token, :string
+ end
+end
diff --git a/db/post_migrate/20181218192239_backfill_project_repositories_for_legacy_storage_projects.rb b/db/post_migrate/20181218192239_backfill_project_repositories_for_legacy_storage_projects.rb
deleted file mode 100644
index 42f96750789..00000000000
--- a/db/post_migrate/20181218192239_backfill_project_repositories_for_legacy_storage_projects.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillProjectRepositoriesForLegacyStorageProjects < ActiveRecord::Migration[5.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 1_000
- DELAY_INTERVAL = 5.minutes
- MIGRATION = 'BackfillLegacyProjectRepositories'
-
- disable_ddl_transaction!
-
- class Project < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'projects'
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(Project, MIGRATION, DELAY_INTERVAL)
- end
-
- def down
- # no-op: since there could have been existing rows before the migration do not remove anything
- end
-end
diff --git a/db/post_migrate/20181219130552_update_project_import_visibility_level.rb b/db/post_migrate/20181219130552_update_project_import_visibility_level.rb
new file mode 100644
index 00000000000..6209de88b31
--- /dev/null
+++ b/db/post_migrate/20181219130552_update_project_import_visibility_level.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+class UpdateProjectImportVisibilityLevel < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ BATCH_SIZE = 100
+
+ PRIVATE = 0
+ INTERNAL = 10
+
+ disable_ddl_transaction!
+
+ class Namespace < ActiveRecord::Base
+ self.table_name = 'namespaces'
+ end
+
+ class Project < ActiveRecord::Base
+ include EachBatch
+
+ belongs_to :namespace
+
+ IMPORT_TYPE = 'gitlab_project'
+
+ scope :with_group_visibility, ->(visibility) do
+ joins(:namespace)
+ .where(namespaces: { type: 'Group', visibility_level: visibility })
+ .where(import_type: IMPORT_TYPE)
+ .where('projects.visibility_level > namespaces.visibility_level')
+ end
+
+ self.table_name = 'projects'
+ end
+
+ def up
+ # Update project's visibility to be the same as the group
+ # if it is more restrictive than `PUBLIC`.
+ update_projects_visibility(PRIVATE)
+ update_projects_visibility(INTERNAL)
+ end
+
+ def down
+ # no-op: unrecoverable data migration
+ end
+
+ private
+
+ def update_projects_visibility(visibility)
+ say_with_time("Updating project visibility to #{visibility} on #{Project::IMPORT_TYPE} imports.") do
+ Project.with_group_visibility(visibility).select(:id).each_batch(of: BATCH_SIZE) do |batch, _index|
+ batch_sql = Gitlab::Database.mysql? ? batch.pluck(:id).join(', ') : batch.select(:id).to_sql
+
+ say("Updating #{batch.size} items.", true)
+
+ execute("UPDATE projects SET visibility_level = '#{visibility}' WHERE id IN (#{batch_sql})")
+ end
+ end
+ end
+end
diff --git a/db/post_migrate/20190102152410_delete_inconsistent_internal_id_records2.rb b/db/post_migrate/20190102152410_delete_inconsistent_internal_id_records2.rb
new file mode 100644
index 00000000000..ddcddcf72a3
--- /dev/null
+++ b/db/post_migrate/20190102152410_delete_inconsistent_internal_id_records2.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+class DeleteInconsistentInternalIdRecords2 < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ # This migration cleans up any inconsistent records in internal_ids.
+ #
+ # That is, it deletes records that track a `last_value` that is
+ # smaller than the maximum internal id (usually `iid`) found in
+ # the corresponding model records.
+
+ def up
+ disable_statement_timeout do
+ delete_internal_id_records('milestones', 'project_id')
+ delete_internal_id_records('milestones', 'namespace_id', 'group_id')
+ end
+ end
+
+ class InternalId < ActiveRecord::Base
+ self.table_name = 'internal_ids'
+ enum usage: { issues: 0, merge_requests: 1, deployments: 2, milestones: 3, epics: 4, ci_pipelines: 5 }
+ end
+
+ private
+
+ def delete_internal_id_records(base_table, scope_column_name, base_scope_column_name = scope_column_name)
+ sql = <<~SQL
+ SELECT id FROM ( -- workaround for MySQL
+ SELECT internal_ids.id FROM (
+ SELECT #{base_scope_column_name} AS #{scope_column_name}, max(iid) as maximum_iid from #{base_table} GROUP BY #{scope_column_name}
+ ) maxima JOIN internal_ids USING (#{scope_column_name})
+ WHERE internal_ids.usage=#{InternalId.usages.fetch(base_table)} AND maxima.maximum_iid > internal_ids.last_value
+ ) internal_ids
+ SQL
+
+ InternalId.where("id IN (#{sql})").tap do |ids| # rubocop:disable GitlabSecurity/SqlInjection
+ say "Deleting internal_id records for #{base_table}: #{ids.map { |i| [i.project_id, i.last_value] }}" unless ids.empty?
+ end.delete_all
+ end
+end
diff --git a/db/post_migrate/20190115054215_migrate_delete_container_repository_worker.rb b/db/post_migrate/20190115054215_migrate_delete_container_repository_worker.rb
new file mode 100644
index 00000000000..4fcee326b7e
--- /dev/null
+++ b/db/post_migrate/20190115054215_migrate_delete_container_repository_worker.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class MigrateDeleteContainerRepositoryWorker < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ sidekiq_queue_migrate('delete_container_repository', to: 'container_repository:delete_container_repository')
+ end
+
+ def down
+ sidekiq_queue_migrate('container_repository:delete_container_repository', to: 'delete_container_repository')
+ end
+end
diff --git a/db/post_migrate/20190124200344_migrate_storage_migrator_sidekiq_queue.rb b/db/post_migrate/20190124200344_migrate_storage_migrator_sidekiq_queue.rb
new file mode 100644
index 00000000000..193bd571831
--- /dev/null
+++ b/db/post_migrate/20190124200344_migrate_storage_migrator_sidekiq_queue.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class MigrateStorageMigratorSidekiqQueue < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ sidekiq_queue_migrate 'storage_migrator', to: 'hashed_storage:hashed_storage_migrator'
+ end
+
+ def down
+ sidekiq_queue_migrate 'hashed_storage:hashed_storage_migrator', to: 'storage_migrator'
+ end
+end
diff --git a/db/post_migrate/20190131122559_fix_null_type_labels.rb b/db/post_migrate/20190131122559_fix_null_type_labels.rb
new file mode 100644
index 00000000000..83bb613990c
--- /dev/null
+++ b/db/post_migrate/20190131122559_fix_null_type_labels.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class FixNullTypeLabels < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ update_column_in_batches(:labels, :type, 'ProjectLabel') do |table, query|
+ query.where(
+ table[:project_id].not_eq(nil)
+ .and(table[:template].eq(false))
+ .and(table[:type].eq(nil))
+ )
+ end
+ end
+
+ def down
+ # no action
+ end
+end
diff --git a/db/post_migrate/20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb b/db/post_migrate/20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb
new file mode 100644
index 00000000000..392e64eeade
--- /dev/null
+++ b/db/post_migrate/20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+class MigrateAutoDevOpsDomainToClusterDomain < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ execute(update_clusters_domain_query)
+ end
+
+ def down
+ # no-op
+ end
+
+ private
+
+ def update_clusters_domain_query
+ if Gitlab::Database.mysql?
+ mysql_query
+ else
+ postgresql_query
+ end
+ end
+
+ def mysql_query
+ <<~HEREDOC
+ UPDATE clusters, project_auto_devops, cluster_projects
+ SET
+ clusters.domain = project_auto_devops.domain
+ WHERE
+ cluster_projects.cluster_id = clusters.id
+ AND project_auto_devops.project_id = cluster_projects.project_id
+ AND project_auto_devops.domain != ''
+ HEREDOC
+ end
+
+ def postgresql_query
+ <<~HEREDOC
+ UPDATE clusters
+ SET domain = project_auto_devops.domain
+ FROM cluster_projects, project_auto_devops
+ WHERE
+ cluster_projects.cluster_id = clusters.id
+ AND project_auto_devops.project_id = cluster_projects.project_id
+ AND project_auto_devops.domain != ''
+ HEREDOC
+ end
+end
diff --git a/db/post_migrate/20190301081611_migrate_project_migrate_sidekiq_queue.rb b/db/post_migrate/20190301081611_migrate_project_migrate_sidekiq_queue.rb
new file mode 100644
index 00000000000..6af7902e0c4
--- /dev/null
+++ b/db/post_migrate/20190301081611_migrate_project_migrate_sidekiq_queue.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class MigrateProjectMigrateSidekiqQueue < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ DOWNTIME = false
+
+ def up
+ sidekiq_queue_migrate 'project_migrate_hashed_storage', to: 'hashed_storage:hashed_storage_project_migrate'
+ end
+
+ def down
+ sidekiq_queue_migrate 'hashed_storage:hashed_storage_project_migrate', to: 'project_migrate_hashed_storage'
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 0af185409a9..c782524c391 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20181219145520) do
+ActiveRecord::Schema.define(version: 20190301081611) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -37,7 +37,14 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.integer "cached_markdown_version"
t.text "new_project_guidelines"
t.text "new_project_guidelines_html"
+ t.text "header_message"
+ t.text "header_message_html"
+ t.text "footer_message"
+ t.text "footer_message_html"
+ t.text "message_background_color"
+ t.text "message_font_color"
t.string "favicon"
+ t.boolean "email_header_and_footer_enabled", default: false, null: false
end
create_table "application_setting_terms", force: :cascade do |t|
@@ -168,6 +175,8 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.string "commit_email_hostname"
t.boolean "protected_ci_variables", default: false, null: false
t.string "runners_registration_token_encrypted"
+ t.integer "local_markdown_version", default: 0, null: false
+ t.integer "first_day_of_week", default: 0, null: false
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
end
@@ -349,11 +358,11 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.string "token_encrypted"
t.index ["artifacts_expire_at"], name: "index_ci_builds_on_artifacts_expire_at", where: "(artifacts_file <> ''::text)", using: :btree
t.index ["auto_canceled_by_id"], name: "index_ci_builds_on_auto_canceled_by_id", using: :btree
+ t.index ["commit_id", "artifacts_expire_at", "id"], name: "index_ci_builds_on_commit_id_and_artifacts_expireatandidpartial", where: "(((type)::text = 'Ci::Build'::text) AND ((retried = false) OR (retried IS NULL)) AND ((name)::text = ANY (ARRAY[('sast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('sast:container'::character varying)::text, ('container_scanning'::character varying)::text, ('dast'::character varying)::text])))", using: :btree
t.index ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree
t.index ["commit_id", "status", "type"], name: "index_ci_builds_on_commit_id_and_status_and_type", using: :btree
t.index ["commit_id", "type", "name", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_name_and_ref", using: :btree
t.index ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref", using: :btree
- t.index ["id"], name: "partial_index_ci_builds_on_id_with_legacy_artifacts", where: "(artifacts_file <> ''::text)", using: :btree
t.index ["project_id", "id"], name: "index_ci_builds_on_project_id_and_id", using: :btree
t.index ["project_id", "status"], name: "index_ci_builds_project_id_and_status_for_live_jobs_partial2", where: "(((type)::text = 'Ci::Build'::text) AND ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text])))", using: :btree
t.index ["protected"], name: "index_ci_builds_on_protected", using: :btree
@@ -373,6 +382,8 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.integer "project_id", null: false
t.integer "timeout"
t.integer "timeout_source", default: 1, null: false
+ t.jsonb "config_options"
+ t.jsonb "config_variables"
t.index ["build_id"], name: "index_ci_builds_metadata_on_build_id", unique: true, using: :btree
t.index ["project_id"], name: "index_ci_builds_metadata_on_project_id", using: :btree
end
@@ -395,6 +406,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.boolean "protected", default: false, null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
+ t.boolean "masked", default: false, null: false
t.index ["group_id", "key"], name: "index_ci_group_variables_on_group_id_and_key", unique: true, using: :btree
end
@@ -417,6 +429,14 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.index ["project_id"], name: "index_ci_job_artifacts_on_project_id", using: :btree
end
+ create_table "ci_pipeline_chat_data", id: :bigserial, force: :cascade do |t|
+ t.integer "pipeline_id", null: false
+ t.integer "chat_name_id", null: false
+ t.text "response_url", null: false
+ t.index ["chat_name_id"], name: "index_ci_pipeline_chat_data_on_chat_name_id", using: :btree
+ t.index ["pipeline_id"], name: "index_ci_pipeline_chat_data_on_pipeline_id", unique: true, using: :btree
+ end
+
create_table "ci_pipeline_schedule_variables", force: :cascade do |t|
t.string "key", null: false
t.text "value"
@@ -479,10 +499,13 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.integer "failure_reason"
t.integer "iid"
t.integer "merge_request_id"
+ t.binary "source_sha"
+ t.binary "target_sha"
t.index ["auto_canceled_by_id"], name: "index_ci_pipelines_on_auto_canceled_by_id", using: :btree
t.index ["merge_request_id"], name: "index_ci_pipelines_on_merge_request_id", where: "(merge_request_id IS NOT NULL)", using: :btree
t.index ["pipeline_schedule_id"], name: "index_ci_pipelines_on_pipeline_schedule_id", using: :btree
t.index ["project_id", "iid"], name: "index_ci_pipelines_on_project_id_and_iid", unique: true, where: "(iid IS NOT NULL)", using: :btree
+ t.index ["project_id", "ref", "id"], name: "index_ci_pipelines_on_project_idandrefandiddesc", order: { id: :desc }, using: :btree
t.index ["project_id", "ref", "status", "id"], name: "index_ci_pipelines_on_project_id_and_ref_and_status_and_id", using: :btree
t.index ["project_id", "sha"], name: "index_ci_pipelines_on_project_id_and_sha", using: :btree
t.index ["project_id", "source"], name: "index_ci_pipelines_on_project_id_and_source", using: :btree
@@ -533,6 +556,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.index ["locked"], name: "index_ci_runners_on_locked", using: :btree
t.index ["runner_type"], name: "index_ci_runners_on_runner_type", using: :btree
t.index ["token"], name: "index_ci_runners_on_token", using: :btree
+ t.index ["token_encrypted"], name: "index_ci_runners_on_token_encrypted", using: :btree
end
create_table "ci_stages", force: :cascade do |t|
@@ -581,6 +605,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.integer "project_id", null: false
t.boolean "protected", default: false, null: false
t.string "environment_scope", default: "*", null: false
+ t.boolean "masked", default: false, null: false
t.index ["project_id", "key", "environment_scope"], name: "index_ci_variables_on_project_id_and_key_and_environment_scope", unique: true, using: :btree
end
@@ -630,7 +655,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.string "endpoint"
t.text "encrypted_access_token"
t.string "encrypted_access_token_iv"
- t.boolean "legacy_abac", default: true, null: false
+ t.boolean "legacy_abac", default: false, null: false
t.index ["cluster_id"], name: "index_cluster_providers_gcp_on_cluster_id", unique: true, using: :btree
end
@@ -644,6 +669,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.string "name", null: false
t.string "environment_scope", default: "*", null: false
t.integer "cluster_type", limit: 2, default: 3, null: false
+ t.string "domain"
t.index ["enabled"], name: "index_clusters_on_enabled", using: :btree
t.index ["user_id"], name: "index_clusters_on_user_id", using: :btree
end
@@ -1199,8 +1225,10 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.string "b_mode", null: false
t.text "new_path", null: false
t.text "old_path", null: false
- t.text "diff", null: false
+ t.text "diff"
t.boolean "binary"
+ t.integer "external_diff_offset"
+ t.integer "external_diff_size"
t.index ["merge_request_diff_id", "relative_order"], name: "index_merge_request_diff_files_on_mr_diff_id_and_order", unique: true, using: :btree
end
@@ -1214,6 +1242,9 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.string "head_commit_sha"
t.string "start_commit_sha"
t.integer "commits_count"
+ t.string "external_diff"
+ t.integer "external_diff_store"
+ t.boolean "stored_externally"
t.index ["merge_request_id", "id"], name: "index_merge_request_diffs_on_merge_request_id_and_id", using: :btree
end
@@ -1353,6 +1384,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.index ["path"], name: "index_namespaces_on_path_trigram", using: :gin, opclasses: {"path"=>"gin_trgm_ops"}
t.index ["require_two_factor_authentication"], name: "index_namespaces_on_require_two_factor_authentication", using: :btree
t.index ["runners_token"], name: "index_namespaces_on_runners_token", unique: true, using: :btree
+ t.index ["runners_token_encrypted"], name: "index_namespaces_on_runners_token_encrypted", unique: true, using: :btree
t.index ["type"], name: "index_namespaces_on_type", using: :btree
end
@@ -1496,7 +1528,6 @@ ActiveRecord::Schema.define(version: 20181219145520) do
create_table "personal_access_tokens", force: :cascade do |t|
t.integer "user_id", null: false
- t.string "token"
t.string "name", null: false
t.boolean "revoked", default: false
t.date "expires_at"
@@ -1505,7 +1536,6 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.string "scopes", default: "--- []\n", null: false
t.boolean "impersonation", default: false, null: false
t.string "token_digest"
- t.index ["token"], name: "index_personal_access_tokens_on_token", unique: true, using: :btree
t.index ["token_digest"], name: "index_personal_access_tokens_on_token_digest", unique: true, using: :btree
t.index ["user_id"], name: "index_personal_access_tokens_on_user_id", using: :btree
end
@@ -1548,6 +1578,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
create_table "project_ci_cd_settings", force: :cascade do |t|
t.integer "project_id", null: false
t.boolean "group_runners_enabled", default: true, null: false
+ t.boolean "merge_pipelines_enabled"
t.index ["project_id"], name: "index_project_ci_cd_settings_on_project_id", unique: true, using: :btree
end
@@ -1561,6 +1592,13 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.index ["project_id", "key"], name: "index_project_custom_attributes_on_project_id_and_key", unique: true, using: :btree
end
+ create_table "project_daily_statistics", id: :bigserial, force: :cascade do |t|
+ t.integer "project_id", null: false
+ t.integer "fetch_count", null: false
+ t.date "date"
+ t.index ["project_id", "date"], name: "index_project_daily_statistics_on_project_id_and_date", unique: true, order: { date: :desc }, using: :btree
+ end
+
create_table "project_deploy_tokens", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "deploy_token_id", null: false
@@ -1569,6 +1607,15 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.index ["project_id", "deploy_token_id"], name: "index_project_deploy_tokens_on_project_id_and_deploy_token_id", unique: true, using: :btree
end
+ create_table "project_error_tracking_settings", primary_key: "project_id", id: :integer, force: :cascade do |t|
+ t.boolean "enabled", default: false, null: false
+ t.string "api_url"
+ t.string "encrypted_token"
+ t.string "encrypted_token_iv"
+ t.string "project_name"
+ t.string "organization_name"
+ end
+
create_table "project_features", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "merge_requests_access_level"
@@ -1707,6 +1754,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.index ["repository_storage", "created_at"], name: "idx_project_repository_check_partial", where: "(last_repository_check_at IS NULL)", using: :btree
t.index ["repository_storage"], name: "index_projects_on_repository_storage", using: :btree
t.index ["runners_token"], name: "index_projects_on_runners_token", using: :btree
+ t.index ["runners_token_encrypted"], name: "index_projects_on_runners_token_encrypted", using: :btree
t.index ["star_count"], name: "index_projects_on_star_count", using: :btree
t.index ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree
end
@@ -1796,6 +1844,16 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.index ["source_type", "source_id"], name: "index_redirect_routes_on_source_type_and_source_id", using: :btree
end
+ create_table "release_links", id: :bigserial, force: :cascade do |t|
+ t.integer "release_id", null: false
+ t.string "url", null: false
+ t.string "name", null: false
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.index ["release_id", "name"], name: "index_release_links_on_release_id_and_name", unique: true, using: :btree
+ t.index ["release_id", "url"], name: "index_release_links_on_release_id_and_url", unique: true, using: :btree
+ end
+
create_table "releases", force: :cascade do |t|
t.string "tag"
t.text "description"
@@ -1828,6 +1886,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.string "encrypted_credentials_salt"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.boolean "error_notification_sent"
t.index ["last_successful_update_at"], name: "index_remote_mirrors_on_last_successful_update_at", using: :btree
t.index ["project_id"], name: "index_remote_mirrors_on_project_id", using: :btree
end
@@ -1905,6 +1964,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.boolean "confidential_note_events", default: true
t.index ["project_id"], name: "index_services_on_project_id", using: :btree
t.index ["template"], name: "index_services_on_template", using: :btree
+ t.index ["type"], name: "index_services_on_type", using: :btree
end
create_table "shards", force: :cascade do |t|
@@ -1998,6 +2058,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.string "name"
t.integer "taggings_count", default: 0
t.index ["name"], name: "index_tags_on_name", unique: true, using: :btree
+ t.index ["name"], name: "index_tags_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
end
create_table "term_agreements", force: :cascade do |t|
@@ -2124,6 +2185,9 @@ ActiveRecord::Schema.define(version: 20181219145520) do
t.integer "merge_request_notes_filter", limit: 2, default: 0, null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
+ t.integer "first_day_of_week"
+ t.string "issues_sort"
+ t.string "merge_requests_sort"
t.index ["user_id"], name: "index_user_preferences_on_user_id", unique: true, using: :btree
end
@@ -2310,6 +2374,8 @@ ActiveRecord::Schema.define(version: 20181219145520) do
add_foreign_key "ci_group_variables", "namespaces", column: "group_id", name: "fk_33ae4d58d8", on_delete: :cascade
add_foreign_key "ci_job_artifacts", "ci_builds", column: "job_id", on_delete: :cascade
add_foreign_key "ci_job_artifacts", "projects", on_delete: :cascade
+ add_foreign_key "ci_pipeline_chat_data", "chat_names", on_delete: :cascade
+ add_foreign_key "ci_pipeline_chat_data", "ci_pipelines", column: "pipeline_id", on_delete: :cascade
add_foreign_key "ci_pipeline_schedule_variables", "ci_pipeline_schedules", column: "pipeline_schedule_id", name: "fk_41c35fda51", on_delete: :cascade
add_foreign_key "ci_pipeline_schedules", "projects", name: "fk_8ead60fcc4", on_delete: :cascade
add_foreign_key "ci_pipeline_schedules", "users", column: "owner_id", name: "fk_9ea99f58d2", on_delete: :nullify
@@ -2418,8 +2484,10 @@ ActiveRecord::Schema.define(version: 20181219145520) do
add_foreign_key "project_auto_devops", "projects", on_delete: :cascade
add_foreign_key "project_ci_cd_settings", "projects", name: "fk_24c15d2f2e", on_delete: :cascade
add_foreign_key "project_custom_attributes", "projects", on_delete: :cascade
+ add_foreign_key "project_daily_statistics", "projects", on_delete: :cascade
add_foreign_key "project_deploy_tokens", "deploy_tokens", on_delete: :cascade
add_foreign_key "project_deploy_tokens", "projects", on_delete: :cascade
+ add_foreign_key "project_error_tracking_settings", "projects", on_delete: :cascade
add_foreign_key "project_features", "projects", name: "fk_18513d9b92", on_delete: :cascade
add_foreign_key "project_group_links", "projects", name: "fk_daa8cee94c", on_delete: :cascade
add_foreign_key "project_import_data", "projects", name: "fk_ffb9ee3a10", on_delete: :cascade
@@ -2437,6 +2505,7 @@ ActiveRecord::Schema.define(version: 20181219145520) do
add_foreign_key "protected_tag_create_access_levels", "users"
add_foreign_key "protected_tags", "projects", name: "fk_8e4af87648", on_delete: :cascade
add_foreign_key "push_event_payloads", "events", name: "fk_36c74129da", on_delete: :cascade
+ add_foreign_key "release_links", "releases", on_delete: :cascade
add_foreign_key "releases", "projects", name: "fk_47fe2a0596", on_delete: :cascade
add_foreign_key "releases", "users", column: "author_id", name: "fk_8e4456f90f", on_delete: :nullify
add_foreign_key "remote_mirrors", "projects", on_delete: :cascade
diff --git a/doc/README.md b/doc/README.md
index b15c3a63d92..ecc214d97c8 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -38,6 +38,7 @@ Have a look at some of our most popular documentation resources:
| [GitLab CI/CD examples](ci/examples/README.md) | Get up to speed quickly with common CI/CD scenarios. |
| [GitLab Container Registry](user/project/container_registry.md) | Host containers within GitLab. |
| [GitLab Pages](user/project/pages/index.md) | Host static websites for your projects with GitLab. |
+| [GitLab.com settings](user/gitlab_com/index.md) | Settings for [GitLab.com](#gitlabcom). |
| [Kubernetes integration](user/project/clusters/index.md) | Use GitLab with Kubernetes. |
| [SSH authentication](ssh/README.md) | Secure your network communications. |
| [Using Docker images](ci/docker/using_docker_images.md) | Build and test your applications with Docker. |
@@ -52,6 +53,11 @@ GitLab provides solutions for [all the stages of the DevOps lifecycle](https://a
![DevOps Stages](img/devops-stages.png)
+GitLab is like a top-of-the-line kitchen for making software. As the executive
+chef, you decide what software you want serve. Using your recipe, GitLab handles
+all the prep work, cooking, and delivery, so you can turn around orders faster
+than ever.
+
The following sections provide links to documentation for each DevOps stage:
| DevOps Stage | Documentation for |
@@ -279,9 +285,11 @@ The following documentation relates to the DevOps **Configure** stage:
| [Auto DevOps](topics/autodevops/index.md) | Automatically employ a complete DevOps lifecycle. |
| [Easy creation of Kubernetes<br/>clusters on GKE](user/project/clusters/index.md#adding-and-creating-a-new-gke-cluster-via-gitlab) | Use Google Kubernetes Engine and GitLab. |
| [Executable Runbooks](user/project/clusters/runbooks/index.md) | Documented procedures that explain how to carry out particular processes. |
+| [GitLab ChatOps](ci/chatops/README.md) | Interact with CI/CD jobs through chat services. |
| [Installing Applications](user/project/clusters/index.md#installing-applications) | Deploy Helm, Ingress, and Prometheus on Kubernetes. |
| [Mattermost slash commands](user/project/integrations/mattermost_slash_commands.md) | Enable and use slash commands from within Mattermost. |
| [Protected variables](ci/variables/README.md#protected-variables) | Restrict variables to protected branches and tags. |
+| [Serverless](user/project/clusters/serverless/index.md) | Run serverless workloads on Kubernetes. |
| [Slack slash commands](user/project/integrations/slack_slash_commands.md) | Enable and use slash commands from within Slack. |
<div align="right">
@@ -331,7 +339,7 @@ Viewing [Container Scanning reports](https://docs.gitlab.com/ee/user/project/mer
There are two ways to use GitLab:
- [GitLab self-managed](#gitlab-self-managed): Install, administer, and maintain your own GitLab instance.
-- [GitLab.com](#gitlab-com): GitLab's SaaS offering. You don't need to install anything to use GitLab.com,
+- [GitLab.com](#gitlabcom): GitLab's SaaS offering. You don't need to install anything to use GitLab.com,
you only need to [sign up](https://gitlab.com/users/sign_in) and start using GitLab straight away.
The following sections outline tiers and features within GitLab self-managed and GitLab.com.
diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
index 772e55cef07..726622d8599 100644
--- a/doc/administration/auth/authentiq.md
+++ b/doc/administration/auth/authentiq.md
@@ -50,9 +50,8 @@ Authentiq will generate a Client ID and the accompanying Client Secret for you t
}
```
-
1. The `scope` is set to request the user's name, email (required and signed), and permission to send push notifications to sign in on subsequent visits.
-See [OmniAuth Authentiq strategy](https://github.com/AuthentiqID/omniauth-authentiq/wiki/Scopes,-callback-url-configuration-and-responses) for more information on scopes and modifiers.
+ See [OmniAuth Authentiq strategy](https://github.com/AuthentiqID/omniauth-authentiq/wiki/Scopes,-callback-url-configuration-and-responses) for more information on scopes and modifiers.
1. Change `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` to the Client credentials you received in step 1.
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md b/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
index 621d4f77d5e..15276d364a0 100644
--- a/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
+++ b/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
@@ -14,7 +14,7 @@ Managing a large number of users in GitLab can become a burden for system admini
In this guide we will focus on configuring GitLab with Active Directory. [Active Directory](https://en.wikipedia.org/wiki/Active_Directory) is a popular LDAP compatible directory service provided by Microsoft, included in all modern Windows Server operating systems.
-GitLab has supported LDAP integration since [version 2.2](https://about.gitlab.com/2012/02/22/gitlab-version-2-2/). With GitLab LDAP [group syncing](#group-syncing-ee) being added to GitLab Enterprise Edition in [version 6.0](https://about.gitlab.com/2013/08/20/gitlab-6-dot-0-released/). LDAP integration has become one of the most popular features in GitLab.
+GitLab has supported LDAP integration since [version 2.2](https://about.gitlab.com/2012/02/22/gitlab-version-2-2/). With GitLab LDAP [group syncing](https://docs.gitlab.com/ee/administration/auth/how_to_configure_ldap_gitlab_ee/index.html#group-sync) being added to GitLab Enterprise Edition in [version 6.0](https://about.gitlab.com/2013/08/20/gitlab-6-dot-0-released/). LDAP integration has become one of the most popular features in GitLab.
## Getting started
@@ -111,7 +111,7 @@ The initial configuration of LDAP in GitLab requires changes to the `gitlab.rb`
The two Active Directory specific values are `active_directory: true` and `uid: 'sAMAccountName'`. `sAMAccountName` is an attribute returned by Active Directory used for GitLab usernames. See the example output from `ldapsearch` for a full list of attributes a "person" object (user) has in **AD** - [`ldapsearch` example](#using-ldapsearch-unix)
-> Both group_base and admin_group configuration options are only available in GitLab Enterprise Edition. See [GitLab EE - LDAP Features](#gitlab-enterprise-edition---ldap-features)
+> Both group_base and admin_group configuration options are only available in GitLab Enterprise Edition. See [GitLab EE - LDAP Features](https://docs.gitlab.com/ee/administration/auth/how_to_configure_ldap_gitlab_ee/index.html#gitlab-enterprise-edition---ldap-features)
### Example `gitlab.rb` LDAP
@@ -255,7 +255,7 @@ After configuring LDAP, basic authentication will be available. Users can then l
Users that are removed from the LDAP base group (e.g `OU=GitLab INT,DC=GitLab,DC=org`) will be **blocked** in GitLab. [More information](../ldap.md#security) on LDAP security.
-If `allow_username_or_email_login` is enabled in the LDAP configuration, GitLab will ignore everything after the first '@' in the LDAP username used on login. Example: The username `jon.doe@example.com` is converted to `jon.doe` when authenticating with the LDAP server. Disable this setting if you use `userPrincipalName` as the `uid`.
+If `allow_username_or_email_login` is enabled in the LDAP configuration, GitLab will ignore everything after the first '@' in the LDAP username used on login. Example: The username `` jon.doe@example.com `` is converted to `jon.doe` when authenticating with the LDAP server. Disable this setting if you use `userPrincipalName` as the `uid`.
## LDAP extended features on GitLab EE
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index 54ded25291a..440c2b1285a 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -81,6 +81,9 @@ library. `tls` corresponds to StartTLS, not to be confused with regular TLS.
Normally, if you specify `ssl` it will be on port 636, while `tls` (StartTLS)
would be on port 389. `plain` also operates on port 389.
+NOTE: **Note:**
+LDAP users must have an email address set, regardless of whether it is used to log in.
+
**Omnibus configuration**
```ruby
@@ -136,14 +139,54 @@ main:
##
verify_certificates: true
- ##
- ## Specifies the SSL version for OpenSSL to use, if the OpenSSL default
- ## is not appropriate.
- ##
- ## Example: 'TLSv1_1'
- ##
- ##
- ssl_version: ''
+ # OpenSSL::SSL::SSLContext options.
+ tls_options:
+ # Specifies the path to a file containing a PEM-format CA certificate,
+ # e.g. if you need to use an internal CA.
+ #
+ # Example: '/etc/ca.pem'
+ #
+ ca_file: ''
+
+ # Specifies the SSL version for OpenSSL to use, if the OpenSSL default
+ # is not appropriate.
+ #
+ # Example: 'TLSv1_1'
+ #
+ ssl_version: ''
+
+ # Specific SSL ciphers to use in communication with LDAP servers.
+ #
+ # Example: 'ALL:!EXPORT:!LOW:!aNULL:!eNULL:!SSLv2'
+ ciphers: ''
+
+ # Client certificate
+ #
+ # Example:
+ # cert: |
+ # -----BEGIN CERTIFICATE-----
+ # MIIDbDCCAlSgAwIBAgIGAWkJxLmKMA0GCSqGSIb3DQEBCwUAMHcxFDASBgNVBAoTC0dvb2dsZSBJ
+ # bmMuMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQDEwtMREFQIENsaWVudDEPMA0GA1UE
+ # CxMGR1N1aXRlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTAeFw0xOTAyMjAwNzE4
+ # rntnF4d+0dd7zP3jrWkbdtoqjLDT/5D7NYRmVCD5vizV98FJ5//PIHbD1gL3a9b2MPAc6k7NV8tl
+ # ...
+ # 4SbuJPAiJxC1LQ0t39dR6oMCAMab3hXQqhL56LrR6cRBp6Mtlphv7alu9xb/x51y2x+g2zWtsf80
+ # Jrv/vKMsIh/sAyuogb7hqMtp55ecnKxceg==
+ # -----END CERTIFICATE -----
+ cert: ''
+
+ # Client private key
+ # key: |
+ # -----BEGIN PRIVATE KEY-----
+ # MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3DmJtLRmJGY4xU1QtI3yjvxO6
+ # bNuyE4z1NF6Xn7VSbcAaQtavWQ6GZi5uukMo+W5DHVtEkgDwh92ySZMuJdJogFbNvJvHAayheCdN
+ # 7mCQ2UUT9jGXIbmksUn9QMeJVXTZjgJWJzPXToeUdinx9G7+lpVa62UATEd1gaI3oyL72WmpDy/C
+ # rntnF4d+0dd7zP3jrWkbdtoqjLDT/5D7NYRmVCD5vizV98FJ5//PIHbD1gL3a9b2MPAc6k7NV8tl
+ # ...
+ # +9IhSYX+XIg7BZOVDeYqlPfxRvQh8vy3qjt/KUihmEPioAjLaGiihs1Fk5ctLk9A2hIUyP+sEQv9
+ # l6RG+a/mW+0rCWn8JAd464Ps9hE=
+ # -----END PRIVATE KEY-----
+ key: ''
##
## Set a timeout, in seconds, for LDAP queries. This helps avoid blocking
@@ -335,7 +378,7 @@ group, you can use the following syntax:
```
Find more information about this "LDAP_MATCHING_RULE_IN_CHAIN" filter at
-https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx. Support for
+<https://docs.microsoft.com/en-us/windows/desktop/ADSI/search-filter-syntax>. Support for
nested members in the user filter should not be confused with
[group sync nested groups support (EE only)](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html#supported-ldap-group-types-attributes).
@@ -448,11 +491,10 @@ ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$ba
port.
- We are assuming the password for the bind_dn user is in bind_dn_password.txt.
-
### Invalid credentials when logging in
- Make sure the user you are binding with has enough permissions to read the user's
-tree and traverse it.
+ tree and traverse it.
- Check that the `user_filter` is not blocking otherwise valid users.
- Run the following check command to make sure that the LDAP settings are
correct and GitLab can see your users:
diff --git a/doc/administration/auth/okta.md b/doc/administration/auth/okta.md
index ae38094391b..638405126a5 100644
--- a/doc/administration/auth/okta.md
+++ b/doc/administration/auth/okta.md
@@ -1,6 +1,6 @@
# Okta SSO provider
-Okta is a [Single Sign-on provider][okta-sso] that can be used to authenticate
+Okta is a [Single Sign-on provider](https://www.okta.com/products/single-sign-on/) that can be used to authenticate
with GitLab.
The following documentation enables Okta as a SAML provider.
@@ -140,8 +140,7 @@ Now that the Okta app is configured, it's time to enable it in GitLab.
}
```
-
-1. [Reconfigure][reconf] or [restart] GitLab for Omnibus and installations
+1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart](../restart_gitlab.md#installations-from-source) GitLab for Omnibus and installations
from source respectively for the changes to take effect.
You might want to try this out on an incognito browser window.
@@ -151,10 +150,5 @@ You might want to try this out on an incognito browser window.
>**Note:**
Make sure the groups exist and are assigned to the Okta app.
-You can take a look of the [SAML documentation][saml] on external groups since
+You can take a look of the [SAML documentation](../../integration/saml.md#marking-users-as-external-based-on-saml-groups) on external groups since
it works the same.
-
-[okta-sso]: https://www.okta.com/products/single-sign-on/
-[saml]: ../../integration/saml.md#external-groups
-[reconf]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
-[restart]: ../restart_gitlab.md#installations-from-source
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 0414b3ec12e..72cb57fb36c 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -6,12 +6,12 @@ GitLab’s [security features](../security/README.md) may also help you meet rel
|Feature |GitLab tier |GitLab.com |
| ---------| :--------: | :-------: |
-|**[Restrict SSH Keys](../README.html#administrator-documentation)**<br>Control the technology and key length of SSH keys used to access GitLab|Core+||
-|**[Granular user roles and flexible permissions](../user/permissions.html)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker.|Core+|✓|
-|**[Enforce TOS acceptance](../user/admin_area/settings/terms.html)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Core+||
-|**[Email all users of a project, group, or entire server](../user/admin_area/settings/terms.html)**<br>An admin can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Starter+||
+|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab|Core+||
+|**[Granular user roles and flexible permissions](../user/permissions.md)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker.|Core+|✓|
+|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Core+||
+|**[Email all users of a project, group, or entire server](../user/admin_area/settings/terms.md)**<br>An admin can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Starter+||
|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system.|Starter+||
-|**[Lock project membership to group](../workflow/groups.html#lock-project-membership-to-members-of-this-group)**<br>Group owners can prevent new members from being added to projects within a group.|Starter+|✓|
+|**[Lock project membership to group](https://docs.gitlab.com/ee/user/group/index.html#member-lock-starter)**<br>Group owners can prevent new members from being added to projects within a group.|Starter+|✓|
|**[LDAP group sync](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html#group-sync)**<br>GitLab Enterprise Edition gives admins the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools.|Starter+||
|**[LDAP group sync filters](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html#group-sync)**<br>GitLab Enterprise Edition Premium gives more flexibility to synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions.|Premium+||
|**[Audit logs](https://docs.gitlab.com/ee/administration/audit_events.html)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives admins the ability to view any modifications made within the GitLab server in an advanced audit log system, so you can control, analyze and track every change.|Premium+||
diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md
index 5b7a61ef8ff..a1ac4a2a57c 100644
--- a/doc/administration/container_registry.md
+++ b/doc/administration/container_registry.md
@@ -11,7 +11,7 @@ With the Container Registry integrated into GitLab, every project can have its
own space to store its Docker images.
You can read more about the Container Registry at
-https://docs.docker.com/registry/introduction/.
+<https://docs.docker.com/registry/introduction/>.
## Enable the Container Registry
@@ -378,7 +378,7 @@ Read more about the individual driver's config options in the
> **Warning** GitLab will not backup Docker images that are not stored on the
filesystem. Remember to enable backups with your object storage provider if
desired.
->
+>
> **Important** Enabling storage driver other than `filesystem` would mean
that your Docker client needs to be able to access the storage backend directly.
So you must use an address that resolves and is accessible outside GitLab server.
@@ -542,7 +542,6 @@ Read more about the Container Registry notifications config options in the
>**Note:**
Multiple endpoints can be configured for the Container Registry.
-
**Omnibus GitLab installations**
To configure a notification endpoint in Omnibus:
@@ -587,7 +586,9 @@ notifications:
backoff: 1000
```
-## Using self-signed certificates with Container Registry
+## Troubleshooting
+
+### Using self-signed certificates with Container Registry
If you're using a self-signed certificate with your Container Registry, you
might encounter issues during the CI jobs like the following:
@@ -599,22 +600,28 @@ Error response from daemon: Get registry.example.com/v1/users/: x509: certificat
The Docker daemon running the command expects a cert signed by a recognized CA,
thus the error above.
-While GitLab doesn't support using self-signed certificates with Container
-Registry out of the box, it is possible to make it work if you follow
-[Docker's documentation][docker-insecure-self-signed]. You may find some additional
-information in [issue 18239][ce-18239].
+While GitLab doesn't support using self-signed certificates with Container Registry out of the box, it is possible to make it work by [instructing the docker-daemon to trust the self-signed certificates][docker-insecure-self-signed], mounting the docker-daemon and setting `privileged = false` in the runner's `config.toml`. Setting `privileged = true` takes precedence over the docker-daemon.
-## Troubleshooting
+```
+ [runners.docker]
+ image = "ruby:2.1"
+ privileged = false
+ volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
+```
+
+Additional information about this: [issue 18239][ce-18239].
+
+### AWS S3 with the GitLab registry error when pushing large images
-When using AWS S3 with the GitLab registry, an error may occur when pushing
+When using AWS S3 with the GitLab registry, an error may occur when pushing
large images. Look in the Registry log for the following error:
```
-level=error msg="response completed with error" err.code=unknown err.detail="unexpected EOF" err.message="unknown error"
+level=error msg="response completed with error" err.code=unknown err.detail="unexpected EOF" err.message="unknown error"
```
-To resolve the error specify a `chunksize` value in the Registry configuration.
-Start with a value between `25000000` (25MB) and `50000000` (50MB).
+To resolve the error specify a `chunksize` value in the Registry configuration.
+Start with a value between `25000000` (25MB) and `50000000` (50MB).
**For Omnibus installations**
diff --git a/doc/administration/git_protocol.md b/doc/administration/git_protocol.md
index 341a00009e5..11b2adeeeb8 100644
--- a/doc/administration/git_protocol.md
+++ b/doc/administration/git_protocol.md
@@ -5,6 +5,13 @@ description: "Set and configure Git protocol v2"
# Configuring Git Protocol v2
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/46555) in GitLab 11.4.
+> [Temporarily disabled](https://gitlab.com/gitlab-org/gitlab-ce/issues/55769) in GitLab 11.5.8, 11.6.6, 11.7.1, and 11.8+
+
+NOTE: **Note:**
+Git protocol v2 support has been [temporarily disabled](https://gitlab.com/gitlab-org/gitlab-ce/issues/55769),
+as a feature used to hide certain internal references does not function when it
+is enabled, and this has a security impact. Once this problem has been resolved,
+protocol v2 support will be re-enabled.
Git protocol v2 improves the v1 wire protocol in several ways and is
enabled by default in GitLab for HTTP requests. In order to enable SSH,
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index cf37eaa0b61..2d4b5c65c46 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -45,12 +45,37 @@ installations that are larger than a single machine. Most
installations will be better served with the default configuration
used by Omnibus and the GitLab source installation guide.
-Starting with GitLab 11.4, Gitaly is a replacement for NFS except
-when the [Elastic Search indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer)
-is used.
-
-Gitaly network traffic is unencrypted so you should use a firewall to
-restrict access to your Gitaly server.
+Starting with GitLab 11.4, Gitaly is able to serve all Git requests without
+needed a shared NFS mount for Git repository data.
+Between 11.4 and 11.8 the exception was the
+[Elastic Search indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer).
+But since 11.8 the indexer uses Gitaly for data access as well. NFS can still
+be leveraged for redudancy on block level of the Git data. But only has to
+be mounted on the Gitaly server.
+
+### Network architecture
+
+- gitlab-rails shards repositories into "repository storages"
+- `gitlab-rails/config/gitlab.yml` contains a map from storage names to
+ (Gitaly address, Gitaly token) pairs
+- the `storage name` -\> `(Gitaly address, Gitaly token)` map in
+ `gitlab.yml` is the single source of truth for the Gitaly network
+ topology
+- a (Gitaly address, Gitaly token) corresponds to a Gitaly server
+- a Gitaly server hosts one or more storages
+- Gitaly addresses must be specified in such a way that they resolve
+ correctly for ALL Gitaly clients
+- Gitaly clients are: unicorn, sidekiq, gitlab-workhorse,
+ gitlab-shell, Elasticsearch Indexer, and Gitaly itself
+- special case: a Gitaly server must be able to make RPC calls **to
+ itself** via its own (Gitaly address, Gitaly token) pair as
+ specified in `gitlab-rails/config/gitlab.yml`
+- Gitaly servers must not be exposed to the public internet
+
+Gitaly network traffic is unencrypted by default, but supports
+[TLS](#tls-support). Authentication is done through a static token. For
+security in depth, its recommended to use a firewall to restrict access
+to your Gitaly server.
Below we describe how to configure a Gitaly server at address
`gitaly.internal:8075` with secret token `abc123secret`. We assume
@@ -106,7 +131,7 @@ Omnibus installations:
```ruby
# /etc/gitlab/gitlab.rb
-# Avoid running unnecessary services on the gitaly server
+# Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false
redis['enable'] = false
nginx['enable'] = false
@@ -134,7 +159,7 @@ gitaly['storage'] = [
{ 'name' => 'storage1', 'path' => '/mnt/gitlab/storage1/repositories' },
]
-# To use tls for gitaly you need to add
+# To use TLS for Gitaly you need to add
gitaly['tls_listen_addr'] = "0.0.0.0:9999"
gitaly['certificate_path'] = "path/to/cert.pem"
gitaly['key_path'] = "path/to/key.pem"
@@ -175,17 +200,16 @@ server from reaching the Gitaly server then all Gitaly requests will
fail.
We assume that your Gitaly server can be reached at
-`gitaly.internal:8075` from your GitLab server, and that your GitLab
-NFS shares are mounted at `/mnt/gitlab/default` and
-`/mnt/gitlab/storage1` respectively.
+`gitaly.internal:8075` from your GitLab server, and that Gitaly can read and
+write to `/mnt/gitlab/default` and `/mnt/gitlab/storage1` respectively.
Omnibus installations:
```ruby
# /etc/gitlab/gitlab.rb
git_data_dirs({
- 'default' => { 'path' => '/mnt/gitlab/default', 'gitaly_address' => 'tcp://gitaly.internal:8075' },
- 'storage1' => { 'path' => '/mnt/gitlab/storage1', 'gitaly_address' => 'tcp://gitaly.internal:8075' },
+ 'default' => { 'gitaly_address' => 'tcp://gitaly.internal:8075' },
+ 'storage1' => { 'gitaly_address' => 'tcp://gitaly.internal:8075' },
})
gitlab_rails['gitaly_token'] = 'abc123secret'
@@ -199,10 +223,8 @@ gitlab:
repositories:
storages:
default:
- path: /mnt/gitlab/default/repositories
gitaly_address: tcp://gitaly.internal:8075
storage1:
- path: /mnt/gitlab/storage1/repositories
gitaly_address: tcp://gitaly.internal:8075
gitaly:
@@ -217,12 +239,14 @@ repository from your GitLab server over HTTP.
## TLS support
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22602) in GitLab 11.8.
+
Gitaly supports TLS credentials for GRPC authentication. To be able to communicate
-with a gitaly instance that listens for secure connections you will need to use `tls://` url
+with a Gitaly instance that listens for secure connections you will need to use `tls://` url
scheme in the `gitaly_address` of the corresponding storage entry in the gitlab configuration.
The admin needs to bring their own certificate as we do not provide that automatically.
-The certificate to be used needs to be installed on all gitaly nodes and on all client nodes that communicate with it following procedures described in [GitLab custom certificate configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates)
+The certificate to be used needs to be installed on all Gitaly nodes and on all client nodes that communicate with it following procedures described in [GitLab custom certificate configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates)
### Example TLS configuration
@@ -240,7 +264,7 @@ git_data_dirs({
gitlab_rails['gitaly_token'] = 'abc123secret'
```
-#### On gitaly server nodes:
+#### On Gitaly server nodes:
```ruby
gitaly['tls_listen_addr'] = "0.0.0.0:9999"
@@ -268,7 +292,7 @@ gitlab:
token: 'abc123secret'
```
-#### On gitaly server nodes:
+#### On Gitaly server nodes:
```toml
# /home/git/gitaly/config.toml
diff --git a/doc/administration/high_availability/gitlab.md b/doc/administration/high_availability/gitlab.md
index 2ca860bd763..d95c3acec54 100644
--- a/doc/administration/high_availability/gitlab.md
+++ b/doc/administration/high_availability/gitlab.md
@@ -58,6 +58,7 @@ for each GitLab application server in your environment.
# Disable components that will not be on the GitLab application server
roles ['application_role']
+ nginx['enable'] = true
# PostgreSQL connection details
gitlab_rails['db_adapter'] = 'postgresql'
@@ -90,6 +91,8 @@ for each GitLab application server in your environment.
certificates are not present, Nginx will fail to start. See
[Nginx documentation](http://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for more information.
+ >
+ > **Note:** It is best to set the `uid` and `gid`s prior to the initial reconfigure of GitLab. Omnibus will not recursively `chown` directories if set after the initial reconfigure.
## First GitLab application server
@@ -108,8 +111,9 @@ Additional GitLab servers (servers configured **after** the first GitLab server)
need some extra configuration.
1. Configure shared secrets. These values can be obtained from the primary
- GitLab server in `/etc/gitlab/gitlab-secrets.json`. Add these to
- `/etc/gitlab/gitlab.rb` **prior to** running the first `reconfigure`.
+ GitLab server in `/etc/gitlab/gitlab-secrets.json`. Copy this file to the
+ secondary servers **prior to** running the first `reconfigure` in the steps
+ above.
```ruby
gitlab_shell['secret_token'] = 'fbfb19c355066a9afb030992231c4a363357f77345edd0f2e772359e5be59b02538e1fa6cae8f93f7d23355341cea2b93600dab6d6c3edcdced558fc6d739860'
@@ -142,6 +146,14 @@ the share is exported and exists on the NFS server and try to remount.
---
+## Upgrading GitLab HA
+
+GitLab HA installations can be upgraded with no downtime, but the
+upgrade process must be carefully coordinated to avoid failures. See the
+[Omnibus GitLab multi-node upgrade
+document](https://docs.gitlab.com/omnibus/update/#multi-node--ha-deployment)
+for more details.
+
Read more on high-availability configuration:
1. [Configure the database](database.md)
diff --git a/doc/administration/high_availability/load_balancer.md b/doc/administration/high_availability/load_balancer.md
index 359de0efadb..28b226cacd5 100644
--- a/doc/administration/high_availability/load_balancer.md
+++ b/doc/administration/high_availability/load_balancer.md
@@ -8,7 +8,53 @@ choice already. Some examples including HAProxy (open-source), F5 Big-IP LTM,
and Citrix Net Scaler. This documentation will outline what ports and protocols
you need to use with GitLab.
-## Basic ports
+## SSL
+
+How will you handle SSL in your HA environment? There are several different
+options:
+
+- Each application node terminates SSL
+- The load balancer(s) terminate SSL and communication is not secure between
+ the load balancer(s) and the application nodes
+- The load balancer(s) terminate SSL and communication is *secure* between the
+ load balancer(s) and the application nodes
+
+### Application nodes terminate SSL
+
+Configure your load balancer(s) to pass connections on port 443 as 'TCP' rather
+than 'HTTP(S)' protocol. This will pass the connection to the application nodes
+Nginx service untouched. Nginx will have the SSL certificate and listen on port 443.
+
+See [Nginx HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
+for details on managing SSL certificates and configuring Nginx.
+
+### Load Balancer(s) terminate SSL without backend SSL
+
+Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancer(s) will then be responsible for managing SSL certificates and
+terminating SSL.
+
+Since communication between the load balancer(s) and GitLab will not be secure,
+there is some additional configuration needed. See
+[Nginx Proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl)
+for details.
+
+### Load Balancer(s) terminate SSL with backend SSL
+
+Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancer(s) will be responsible for managing SSL certificates that
+end users will see.
+
+Traffic will also be secure between the load balancer(s) and Nginx in this
+scenario. There is no need to add configuration for proxied SSL since the
+connection will be secure all the way. However, configuration will need to be
+added to GitLab to configure SSL certificates. See
+[Nginx HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
+for details on managing SSL certificates and configuring Nginx.
+
+## Ports
+
+### Basic ports
| LB Port | Backend Port | Protocol |
| ------- | ------------ | --------------- |
@@ -16,9 +62,9 @@ you need to use with GitLab.
| 443 | 443 | TCP or HTTPS [^1] [^2] |
| 22 | 22 | TCP |
-## GitLab Pages Ports
+### GitLab Pages Ports
-If you're using GitLab Pages with custom domain support you will need some
+If you're using GitLab Pages with custom domain support you will need some
additional port configurations.
GitLab Pages requires a separate virtual IP address. Configure DNS to point the
`pages_external_url` from `/etc/gitlab/gitlab.rb` at the new virtual IP address. See the
@@ -29,7 +75,7 @@ GitLab Pages requires a separate virtual IP address. Configure DNS to point the
| 80 | Varies [^3] | HTTP |
| 443 | Varies [^3] | TCP [^4] |
-## Alternate SSH Port
+### Alternate SSH Port
Some organizations have policies against opening SSH port 22. In this case,
it may be helpful to configure an alternate SSH hostname that allows users
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md
index 74b0e2c8184..78ebf8a083b 100644
--- a/doc/administration/high_availability/nfs.md
+++ b/doc/administration/high_availability/nfs.md
@@ -37,6 +37,28 @@ options:
circumstances it could lead to data loss if a failure occurs before data has
synced.
+### Improving NFS performance with GitLab
+
+If you are using NFS to share Git data, we recommend that you enable a
+number of feature flags that will allow GitLab application processes to
+access Git data directly instead of going through the [Gitaly
+service](../gitaly/index.md). Depending on your workload and disk
+performance, these flags may help improve performance. See [the
+issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/57317) for more
+details.
+
+To do this, run the Rake task:
+
+```sh
+gitlab-rake gitlab:features:enable_rugged
+```
+
+If you need to undo this setting for some reason, run:
+
+```sh
+gitlab-rake gitlab:features:disable_rugged
+```
+
### Known issues
On some customer systems, we have seen NFS clients slow precipitously due to
diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md
index 833c1f367dd..a52bc5c3b02 100644
--- a/doc/administration/high_availability/redis.md
+++ b/doc/administration/high_availability/redis.md
@@ -359,11 +359,17 @@ following section assumes you are using Omnibus GitLab Enterprise Edition.
For the Omnibus Community Edition and installations from source, follow the
[Redis HA source install](redis_source.md) guide.
+NOTE: **Note:** If you are using an external Redis Sentinel instance, be sure
+to exclude the `requirepass` parameter from the Sentinel
+configuration. This parameter will cause clients to report `NOAUTH
+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.
If you are not sure if your Redis servers are working and replicating
-correctly, please read the [Troubleshooting Replication](#troubleshooting-replication)
+correctly, please read the [Troubleshooting Replication](#troubleshooting-redis-replication)
and fix it before proceeding with Sentinel setup.
You must have at least `3` Redis Sentinel servers, and they need to
@@ -545,10 +551,10 @@ discussed in [Redis setup overview](#redis-setup-overview) and
Here is a list and description of each **machine** and the assigned **IP**:
-* `10.0.0.1`: Redis Master + Sentinel 1
-* `10.0.0.2`: Redis Slave 1 + Sentinel 2
-* `10.0.0.3`: Redis Slave 2 + Sentinel 3
-* `10.0.0.4`: GitLab application
+- `10.0.0.1`: Redis Master + Sentinel 1
+- `10.0.0.2`: Redis Slave 1 + Sentinel 2
+- `10.0.0.3`: Redis Slave 2 + Sentinel 3
+- `10.0.0.4`: GitLab application
Please note that after the initial configuration, if a failover is initiated
by the Sentinel nodes, the Redis nodes will be reconfigured and the **Master**
@@ -855,7 +861,6 @@ To make sure your configuration is correct:
You should see a different port after a few seconds delay
(the failover/reconnect time).
-
## Changelog
Changes to Redis HA over time.
diff --git a/doc/administration/high_availability/redis_source.md b/doc/administration/high_availability/redis_source.md
index 2101d36d2b6..be6b547372a 100644
--- a/doc/administration/high_availability/redis_source.md
+++ b/doc/administration/high_availability/redis_source.md
@@ -46,7 +46,7 @@ valuable information for the general setup.
Assuming that the Redis master instance IP is `10.0.0.1`:
-1. [Install Redis](../../install/installation.md#6-redis)
+1. [Install Redis](../../install/installation.md#7-redis).
1. Edit `/etc/redis/redis.conf`:
```conf
@@ -72,7 +72,7 @@ Assuming that the Redis master instance IP is `10.0.0.1`:
Assuming that the Redis slave instance IP is `10.0.0.2`:
-1. [Install Redis](../../install/installation.md#6-redis)
+1. [Install Redis](../../install/installation.md#7-redis).
1. Edit `/etc/redis/redis.conf`:
```conf
@@ -214,10 +214,10 @@ For this example, **Sentinel 1** will be configured in the same machine as the
Here is a list and description of each **machine** and the assigned **IP**:
-* `10.0.0.1`: Redis Master + Sentinel 1
-* `10.0.0.2`: Redis Slave 1 + Sentinel 2
-* `10.0.0.3`: Redis Slave 2 + Sentinel 3
-* `10.0.0.4`: GitLab application
+- `10.0.0.1`: Redis Master + Sentinel 1
+- `10.0.0.2`: Redis Slave 1 + Sentinel 2
+- `10.0.0.3`: Redis Slave 2 + Sentinel 3
+- `10.0.0.4`: GitLab application
Please note that after the initial configuration, if a failover is initiated
by the Sentinel nodes, the Redis nodes will be reconfigured and the **Master**
diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md
index bb621b788f1..058346df56d 100644
--- a/doc/administration/housekeeping.md
+++ b/doc/administration/housekeeping.md
@@ -17,19 +17,18 @@ The housekeeping function will run a `repack` or `gc` depending on the
For example in the following scenario a `git repack -d` will be executed:
-+ Project: pushes since gc counter (`pushes_since_gc`) = `10`
-+ Git GC period = `200`
-+ Full repack period = `50`
+- Project: pushes since gc counter (`pushes_since_gc`) = `10`
+- Git GC period = `200`
+- Full repack period = `50`
When the `pushes_since_gc` value is 50 a `repack -A -d --pack-kept-objects` will run, similarly when
the `pushes_since_gc` value is 200 a `git gc` will be run.
-+ `git gc` ([man page][man-gc]) runs a number of housekeeping tasks,
-such as compressing filerevisions (to reduce disk space and increase performance)
-and removing unreachable objects which may have been created from prior invocations of
-`git add`.
-
-+ `git repack` ([man page][man-repack]) re-organize existing packs into a single, more efficient pack.
+- `git gc` ([man page][man-gc]) runs a number of housekeeping tasks,
+ such as compressing filerevisions (to reduce disk space and increase performance)
+ and removing unreachable objects which may have been created from prior invocations of
+ `git add`.
+- `git repack` ([man page][man-repack]) re-organize existing packs into a single, more efficient pack.
You can find this option under your **[Project] > Edit Project**.
@@ -39,4 +38,4 @@ You can find this option under your **[Project] > Edit Project**.
[ce-2371]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2371 "Housekeeping merge request"
[man-gc]: https://www.kernel.org/pub/software/scm/git/docs/git-gc.html "git gc man page"
-[man-repack]: https://www.kernel.org/pub/software/scm/git/docs/git-repack.html \ No newline at end of file
+[man-repack]: https://www.kernel.org/pub/software/scm/git/docs/git-repack.html
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 27a3710632d..658b2f55d30 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -13,43 +13,45 @@ GitLab has several features based on receiving incoming emails:
## Requirements
-Handling incoming emails requires an [IMAP]-enabled email account. GitLab
-requires one of the following three strategies:
+Handling incoming emails requires an [IMAP](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol)-enabled
+email account. GitLab requires one of the following three strategies:
-- Email sub-addressing
-- Dedicated email address
+- Email sub-addressing (recommended)
- Catch-all mailbox
+- Dedicated email address (supports Reply by Email only)
Let's walk through each of these options.
-**If your provider or server supports email sub-addressing, we recommend using it.
-Most features (other than reply by email) only work with sub-addressing.**
-
-[IMAP]: https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol
-
### Email sub-addressing
[Sub-addressing](https://en.wikipedia.org/wiki/Email_address#Sub-addressing) is
-a feature where any email to `user+some_arbitrary_tag@example.com` will end up
-in the mailbox for `user@example.com`, and is supported by providers such as
-Gmail, Google Apps, Yahoo! Mail, Outlook.com and iCloud, as well as the
-[Postfix mail server] which you can run on-premises.
+a mail server feature where any email to `user+arbitrary_tag@example.com` will end up
+in the mailbox for `user@example.com` . It is supported by providers such as
+Gmail, Google Apps, Yahoo! Mail, Outlook.com, and iCloud, as well as the
+[Postfix mail server](reply_by_email_postfix_setup.md), which you can run on-premises.
+
+TIP: **Tip:**
+If your provider or server supports email sub-addressing, we recommend using it.
+A dedicated email address only supports Reply by Email functionality.
+A catch-all mailbox supports the same features as sub-addressing as of GitLab 11.7,
+but sub-addressing is still preferred because only one email address is used,
+leaving a catch-all available for other purposes beyond GitLab.
-[Postfix mail server]: reply_by_email_postfix_setup.md
+### Catch-all mailbox
-### Dedicated email address
+A [catch-all mailbox](https://en.wikipedia.org/wiki/Catch-all) for a domain
+receives all emails addressed to the domain that do not match any addresses that
+exist on the mail server.
-This solution is really simple to set up: you just have to create an email
-address dedicated to receive your users' replies to GitLab notifications.
+As of GitLab 11.7, catch-all mailboxes support the same features as
+email sub-addressing, but email sub-addressing remains our recommendation so that you
+can reserve your catch-all mailbox for other purposes.
-### Catch-all mailbox
-
-A [catch-all mailbox](https://en.wikipedia.org/wiki/Catch-all) for a domain will
-"catch all" the emails addressed to the domain that do not exist in the mail
-server.
+### Dedicated email address
-GitLab can be set up to allow users to comment on issues and merge requests by
-replying to notification emails.
+This solution is relatively simple to set up: you just need to create an email
+address dedicated to receive your users' replies to GitLab notifications. However,
+this method only supports replies, and not the other features of [incoming email](#incoming-email).
## Set it up
@@ -93,240 +95,249 @@ for a real-world example of this exploit.
### Omnibus package installations
-1. Find the `incoming_email` section in `/etc/gitlab/gitlab.rb`, enable the
- feature and fill in the details for your specific IMAP server and email account:
+1. Find the `incoming_email` section in `/etc/gitlab/gitlab.rb`, enable the feature
+ and fill in the details for your specific IMAP server and email account (see [examples](#config-examples) below).
- Configuration for Postfix mail server, assumes mailbox
- incoming@gitlab.example.com
+1. Reconfigure GitLab for the changes to take effect:
- ```ruby
- gitlab_rails['incoming_email_enabled'] = true
+ ```sh
+ sudo gitlab-ctl reconfigure
+ sudo gitlab-ctl restart
+ ```
- # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
- # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
- gitlab_rails['incoming_email_address'] = "incoming+%{key}@gitlab.example.com"
+1. Verify that everything is configured correctly:
- # Email account username
- # With third party providers, this is usually the full email address.
- # With self-hosted email servers, this is usually the user part of the email address.
- gitlab_rails['incoming_email_email'] = "incoming"
- # Email account password
- gitlab_rails['incoming_email_password'] = "[REDACTED]"
+ ```sh
+ sudo gitlab-rake gitlab:incoming_email:check
+ ```
- # IMAP server host
- gitlab_rails['incoming_email_host'] = "gitlab.example.com"
- # IMAP server port
- gitlab_rails['incoming_email_port'] = 143
- # Whether the IMAP server uses SSL
- gitlab_rails['incoming_email_ssl'] = false
- # Whether the IMAP server uses StartTLS
- gitlab_rails['incoming_email_start_tls'] = false
+Reply by email should now be working.
- # The mailbox where incoming mail will end up. Usually "inbox".
- gitlab_rails['incoming_email_mailbox_name'] = "inbox"
- # The IDLE command timeout.
- gitlab_rails['incoming_email_idle_timeout'] = 60
+### Installations from source
+
+1. Go to the GitLab installation directory:
+
+ ```sh
+ cd /home/git/gitlab
```
- Configuration for Gmail / Google Apps, assumes mailbox
- gitlab-incoming@gmail.com
+1. Find the `incoming_email` section in `config/gitlab.yml`, enable the feature
+ and fill in the details for your specific IMAP server and email account (see [examples](#config-examples) below).
- ```ruby
- gitlab_rails['incoming_email_enabled'] = true
+1. Enable `mail_room` in the init script at `/etc/default/gitlab`:
+
+ ```sh
+ sudo mkdir -p /etc/default
+ echo 'mail_room_enabled=true' | sudo tee -a /etc/default/gitlab
+ ```
+
+1. Restart GitLab:
+
+ ```sh
+ sudo service gitlab restart
+ ```
+
+1. Verify that everything is configured correctly:
+
+ ```sh
+ sudo -u git -H bundle exec rake gitlab:incoming_email:check RAILS_ENV=production
+ ```
+
+Reply by email should now be working.
+
+### Config examples
+
+#### Postfix
+
+Example configuration for Postfix mail server. Assumes mailbox incoming@gitlab.example.com.
+
+Example for Omnibus installs:
+
+```ruby
+gitlab_rails['incoming_email_enabled'] = true
+
+# The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+# The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+gitlab_rails['incoming_email_address'] = "incoming+%{key}@gitlab.example.com"
+
+# Email account username
+# With third party providers, this is usually the full email address.
+# With self-hosted email servers, this is usually the user part of the email address.
+gitlab_rails['incoming_email_email'] = "incoming"
+# Email account password
+gitlab_rails['incoming_email_password'] = "[REDACTED]"
+
+# IMAP server host
+gitlab_rails['incoming_email_host'] = "gitlab.example.com"
+# IMAP server port
+gitlab_rails['incoming_email_port'] = 143
+# Whether the IMAP server uses SSL
+gitlab_rails['incoming_email_ssl'] = false
+# Whether the IMAP server uses StartTLS
+gitlab_rails['incoming_email_start_tls'] = false
+
+# The mailbox where incoming mail will end up. Usually "inbox".
+gitlab_rails['incoming_email_mailbox_name'] = "inbox"
+# The IDLE command timeout.
+gitlab_rails['incoming_email_idle_timeout'] = 60
+```
+
+Example for source installs:
+
+```yaml
+incoming_email:
+ enabled: true
# The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
# The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
- gitlab_rails['incoming_email_address'] = "gitlab-incoming+%{key}@gmail.com"
+ address: "incoming+%{key}@gitlab.example.com"
# Email account username
# With third party providers, this is usually the full email address.
# With self-hosted email servers, this is usually the user part of the email address.
- gitlab_rails['incoming_email_email'] = "gitlab-incoming@gmail.com"
+ user: "incoming"
# Email account password
- gitlab_rails['incoming_email_password'] = "[REDACTED]"
+ password: "[REDACTED]"
# IMAP server host
- gitlab_rails['incoming_email_host'] = "imap.gmail.com"
+ host: "gitlab.example.com"
# IMAP server port
- gitlab_rails['incoming_email_port'] = 993
+ port: 143
# Whether the IMAP server uses SSL
- gitlab_rails['incoming_email_ssl'] = true
+ ssl: false
# Whether the IMAP server uses StartTLS
- gitlab_rails['incoming_email_start_tls'] = false
+ start_tls: false
# The mailbox where incoming mail will end up. Usually "inbox".
- gitlab_rails['incoming_email_mailbox_name'] = "inbox"
+ mailbox: "inbox"
# The IDLE command timeout.
- gitlab_rails['incoming_email_idle_timeout'] = 60
- ```
+ idle_timeout: 60
+```
- Configuration for Microsoft Exchange mail server w/ IMAP enabled, assumes
- mailbox incoming@exchange.example.com
+#### Gmail
- ```ruby
- gitlab_rails['incoming_email_enabled'] = true
+Example configuration for Gmail/G Suite. Assumes mailbox gitlab-incoming@gmail.com.
- # The email address replies are sent to - Exchange does not support sub-addressing so %{key} is not used here
- gitlab_rails['incoming_email_address'] = "incoming@exchange.example.com"
+Example for Omnibus installs:
- # Email account username
- # Typically this is the userPrincipalName (UPN)
- gitlab_rails['incoming_email_email'] = "incoming@ad-domain.example.com"
- # Email account password
- gitlab_rails['incoming_email_password'] = "[REDACTED]"
+```ruby
+gitlab_rails['incoming_email_enabled'] = true
- # IMAP server host
- gitlab_rails['incoming_email_host'] = "exchange.example.com"
- # IMAP server port
- gitlab_rails['incoming_email_port'] = 993
- # Whether the IMAP server uses SSL
- gitlab_rails['incoming_email_ssl'] = true
- ```
+# The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+# The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+gitlab_rails['incoming_email_address'] = "gitlab-incoming+%{key}@gmail.com"
-1. Reconfigure GitLab for the changes to take effect:
+# Email account username
+# With third party providers, this is usually the full email address.
+# With self-hosted email servers, this is usually the user part of the email address.
+gitlab_rails['incoming_email_email'] = "gitlab-incoming@gmail.com"
+# Email account password
+gitlab_rails['incoming_email_password'] = "[REDACTED]"
- ```sh
- sudo gitlab-ctl reconfigure
- sudo gitlab-ctl restart
- ```
+# IMAP server host
+gitlab_rails['incoming_email_host'] = "imap.gmail.com"
+# IMAP server port
+gitlab_rails['incoming_email_port'] = 993
+# Whether the IMAP server uses SSL
+gitlab_rails['incoming_email_ssl'] = true
+# Whether the IMAP server uses StartTLS
+gitlab_rails['incoming_email_start_tls'] = false
-1. Verify that everything is configured correctly:
+# The mailbox where incoming mail will end up. Usually "inbox".
+gitlab_rails['incoming_email_mailbox_name'] = "inbox"
+# The IDLE command timeout.
+gitlab_rails['incoming_email_idle_timeout'] = 60
+```
- ```sh
- sudo gitlab-rake gitlab:incoming_email:check
- ```
+Example for source installs:
-1. Reply by email should now be working.
+```yaml
+incoming_email:
+ enabled: true
-### Installations from source
+ # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+ # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+ address: "gitlab-incoming+%{key}@gmail.com"
-1. Go to the GitLab installation directory:
+ # Email account username
+ # With third party providers, this is usually the full email address.
+ # With self-hosted email servers, this is usually the user part of the email address.
+ user: "gitlab-incoming@gmail.com"
+ # Email account password
+ password: "[REDACTED]"
- ```sh
- cd /home/git/gitlab
- ```
+ # IMAP server host
+ host: "imap.gmail.com"
+ # IMAP server port
+ port: 993
+ # Whether the IMAP server uses SSL
+ ssl: true
+ # Whether the IMAP server uses StartTLS
+ start_tls: false
-1. Find the `incoming_email` section in `config/gitlab.yml`, enable the feature
- and fill in the details for your specific IMAP server and email account:
+ # The mailbox where incoming mail will end up. Usually "inbox".
+ mailbox: "inbox"
+ # The IDLE command timeout.
+ idle_timeout: 60
+```
- ```sh
- sudo editor config/gitlab.yml
- ```
+#### MS Exchange
- Configuration for Postfix mail server, assumes mailbox
- incoming@gitlab.example.com
-
- ```yaml
- incoming_email:
- enabled: true
-
- # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
- # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
- address: "incoming+%{key}@gitlab.example.com"
-
- # Email account username
- # With third party providers, this is usually the full email address.
- # With self-hosted email servers, this is usually the user part of the email address.
- user: "incoming"
- # Email account password
- password: "[REDACTED]"
-
- # IMAP server host
- host: "gitlab.example.com"
- # IMAP server port
- port: 143
- # Whether the IMAP server uses SSL
- ssl: false
- # Whether the IMAP server uses StartTLS
- start_tls: false
-
- # The mailbox where incoming mail will end up. Usually "inbox".
- mailbox: "inbox"
- # The IDLE command timeout.
- idle_timeout: 60
- ```
+Example configuration for Microsoft Exchange mail server with IMAP enabled. Assumes the
+catch-all mailbox incoming@exchange.example.com.
- Configuration for Gmail / Google Apps, assumes mailbox
- gitlab-incoming@gmail.com
-
- ```yaml
- incoming_email:
- enabled: true
-
- # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
- # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
- address: "gitlab-incoming+%{key}@gmail.com"
-
- # Email account username
- # With third party providers, this is usually the full email address.
- # With self-hosted email servers, this is usually the user part of the email address.
- user: "gitlab-incoming@gmail.com"
- # Email account password
- password: "[REDACTED]"
-
- # IMAP server host
- host: "imap.gmail.com"
- # IMAP server port
- port: 993
- # Whether the IMAP server uses SSL
- ssl: true
- # Whether the IMAP server uses StartTLS
- start_tls: false
-
- # The mailbox where incoming mail will end up. Usually "inbox".
- mailbox: "inbox"
- # The IDLE command timeout.
- idle_timeout: 60
- ```
+Example for Omnibus installs:
- Configuration for Microsoft Exchange mail server w/ IMAP enabled, assumes
- mailbox incoming@exchange.example.com
-
- ```yaml
- incoming_email:
- enabled: true
-
- # The email address replies are sent to - Exchange does not support sub-addressing so %{key} is not used here
- address: "incoming@exchange.example.com"
-
- # Email account username
- # Typically this is the userPrincipalName (UPN)
- user: "incoming@ad-domain.example.com"
- # Email account password
- password: "[REDACTED]"
-
- # IMAP server host
- host: "exchange.example.com"
- # IMAP server port
- port: 993
- # Whether the IMAP server uses SSL
- ssl: true
- # Whether the IMAP server uses StartTLS
- start_tls: false
-
- # The mailbox where incoming mail will end up. Usually "inbox".
- mailbox: "inbox"
- # The IDLE command timeout.
- idle_timeout: 60
- ```
+```ruby
+gitlab_rails['incoming_email_enabled'] = true
-1. Enable `mail_room` in the init script at `/etc/default/gitlab`:
+# The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+# The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+# Exchange does not support sub-addressing, so a catch-all mailbox must be used.
+gitlab_rails['incoming_email_address'] = "incoming-%{key}@exchange.example.com"
- ```sh
- sudo mkdir -p /etc/default
- echo 'mail_room_enabled=true' | sudo tee -a /etc/default/gitlab
- ```
+# Email account username
+# Typically this is the userPrincipalName (UPN)
+gitlab_rails['incoming_email_email'] = "incoming@ad-domain.example.com"
+# Email account password
+gitlab_rails['incoming_email_password'] = "[REDACTED]"
-1. Restart GitLab:
+# IMAP server host
+gitlab_rails['incoming_email_host'] = "exchange.example.com"
+# IMAP server port
+gitlab_rails['incoming_email_port'] = 993
+# Whether the IMAP server uses SSL
+gitlab_rails['incoming_email_ssl'] = true
+```
- ```sh
- sudo service gitlab restart
- ```
+Example for source installs:
-1. Verify that everything is configured correctly:
+```yaml
+incoming_email:
+ enabled: true
- ```sh
- sudo -u git -H bundle exec rake gitlab:incoming_email:check RAILS_ENV=production
- ```
+ # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+ # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+ # Exchange does not support sub-addressing, so a catch-all mailbox must be used.
+ address: "incoming-%{key}@exchange.example.com"
+
+ # Email account username
+ # Typically this is the userPrincipalName (UPN)
+ user: "incoming@ad-domain.example.com"
+ # Email account password
+ password: "[REDACTED]"
+
+ # IMAP server host
+ host: "exchange.example.com"
+ # IMAP server port
+ port: 993
+ # Whether the IMAP server uses SSL
+ ssl: true
+ # Whether the IMAP server uses StartTLS
+ start_tls: false
-1. Reply by email should now be working.
+ # The mailbox where incoming mail will end up. Usually "inbox".
+ mailbox: "inbox"
+ # The IDLE command timeout.
+ idle_timeout: 60
+```
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 89132cd95f0..b723edfc78f 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -4,24 +4,27 @@ description: 'Learn how to install, configure, update, and maintain your GitLab
# Administrator documentation **[CORE ONLY]**
-Learn how to administer your GitLab instance (Community Edition and
-Enterprise Edition).
-Regular users don't have access to GitLab administration tools and settings.
+Learn how to administer your self-managed GitLab instance.
-GitLab has two product distributions: the open source
-[GitLab Community Edition (CE)](https://gitlab.com/gitlab-org/gitlab-ce),
-and the open core [GitLab Enterprise Edition (EE)](https://gitlab.com/gitlab-org/gitlab-ee),
-available through [different subscriptions](https://about.gitlab.com/pricing/).
+GitLab has two product distributions available through [different subscriptions](https://about.gitlab.com/pricing/):
-You can [install GitLab CE or GitLab EE](https://about.gitlab.com/installation/ce-or-ee/),
-but the features you'll have access to depend on the subscription you choose
-(Core, Starter, Premium, or Ultimate). GitLab Community Edition installations
-only have access to Core features.
+- The open source [GitLab Community Edition (CE)](https://gitlab.com/gitlab-org/gitlab-ce).
+- The open core [GitLab Enterprise Edition (EE)](https://gitlab.com/gitlab-org/gitlab-ee).
+
+You can [install either GitLab CE or GitLab EE](https://about.gitlab.com/installation/ce-or-ee/).
+However, the features you'll have access to depend on the subscription you choose
+(Core, Starter, Premium, or Ultimate).
+
+NOTE: **Note:**
+GitLab Community Edition installations only have access to Core features.
GitLab.com is administered by GitLab, Inc., therefore, only GitLab team members have
access to its admin configurations. If you're a GitLab.com user, please check the
[user documentation](../user/index.html).
+NOTE: **Note:**
+Non-administrator users don’t have access to GitLab administration tools and settings.
+
## Installing and maintaining GitLab
Learn how to install, configure, update, and maintain your GitLab instance.
@@ -41,13 +44,16 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Polling](polling.md): Configure how often the GitLab UI polls for updates.
- [GitLab Pages configuration](pages/index.md): Enable and configure GitLab Pages.
- [GitLab Pages configuration for GitLab source installations](pages/source.md): Enable and configure GitLab Pages on
-[source installations](../install/installation.md#installation-from-source).
+ [source installations](../install/installation.md#installation-from-source).
- [Environment variables](environment_variables.md): Supported environment variables that can be used to override their defaults values in order to configure GitLab.
- [Plugins](plugins.md): With custom plugins, GitLab administrators can introduce custom integrations without modifying GitLab's source code.
- [Enforcing Terms of Service](../user/admin_area/settings/terms.md)
- [Third party offers](../user/admin_area/settings/third_party_offers.md)
- [Compliance](compliance.md): A collection of features from across the application that you may configure to help ensure that your GitLab instance and DevOps workflow meet compliance standards.
- [Diff limits](../user/admin_area/diff_limits.md): Configure the diff rendering size limits of branch comparison pages.
+- [Merge request diffs storage](merge_request_diffs.md): Configure merge requests diffs external storage.
+- [Broadcast Messages](../user/admin_area/broadcast_messages.md): Send messages to GitLab users through the UI.
+- [Admin Area](../user/admin_area/index.md): for self-managed instance-wide configuration and maintenance.
#### Customizing GitLab's appearance
@@ -63,6 +69,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Backup and restore](../raketasks/backup_restore.md): Backup and restore your GitLab instance.
- [Operations](operations/index.md): Keeping GitLab up and running (clean up Redis sessions, moving repositories, Sidekiq MemoryKiller, Unicorn).
- [Restart GitLab](restart_gitlab.md): Learn how to restart GitLab and its components.
+- [Invalidate markdown cache](invalidate_markdown_cache.md): Invalidate any cached markdown.
#### Updating GitLab
@@ -80,7 +87,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/): Integrate with [Mattermost](https://about.mattermost.com/), an open source, private cloud workplace for web messaging.
- [PlantUML](integration/plantuml.md): Create simple diagrams in AsciiDoc and Markdown documents
-created in snippets, wikis, and repos.
+ created in snippets, wikis, and repos.
- [Web terminals](integration/terminal.md): Provide terminal access to your applications deployed to Kubernetes from within GitLab's CI/CD [environments](../ci/environments.md#web-terminals).
## User settings and permissions
@@ -88,7 +95,7 @@ created in snippets, wikis, and repos.
- [Libravatar](../customization/libravatar.md): Use Libravatar instead of Gravatar for user avatars.
- [Sign-up restrictions](../user/admin_area/settings/sign_up_restrictions.md): block email addresses of specific domains, or whitelist only specific domains.
- [Access restrictions](../user/admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols): Define which Git access protocols can be used to talk to GitLab (SSH, HTTP, HTTPS).
-- [Authentication/Authorization](../topics/authentication/index.md#gitlab-administrators): Enforce 2FA, configure external authentication with LDAP, SAML, CAS and additional Omniauth providers.
+- [Authentication and Authorization](auth/README.md): Configure external authentication with LDAP, SAML, CAS and additional providers. See also other [authentication](../topics/authentication/index.md#gitlab-administrators) topics (for example, enforcing 2FA).
- [Incoming email](incoming_email.md): Configure incoming emails to allow
users to [reply by email], create [issues by email] and
[merge requests by email], and to enable [Service Desk].
@@ -123,8 +130,8 @@ created in snippets, wikis, and repos.
- [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully).
- [Job traces](job_traces.md): Information about the job traces (logs).
- [Register Shared and specific Runners](../ci/runners/README.md#registering-a-shared-runner): Learn how to register and configure Shared and specific Runners to your own instance.
-- [Shared Runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota): Limit the usage of pipeline minutes for Shared Runners.
-- [Enable/disable Auto DevOps](../topics/autodevops/index.md#enabling-auto-devops): Enable or disable Auto DevOps for your instance.
+- [Shared Runners pipelines quota](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only): Limit the usage of pipeline minutes for Shared Runners. **[STARTER ONLY]**
+- [Enable/disable Auto DevOps](../topics/autodevops/index.md#enablingdisabling-auto-devops): Enable or disable Auto DevOps for your instance.
## Git configuration options
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
index b61c5409a56..d383d1efe70 100644
--- a/doc/administration/integration/plantuml.md
+++ b/doc/administration/integration/plantuml.md
@@ -52,7 +52,6 @@ http://localhost:8080/plantuml
you can change these defaults by editing the `/etc/tomcat7/server.xml` file.
-
## GitLab
You need to enable PlantUML integration from Settings under Admin Area. To do
diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md
index fa58d0ef15f..25d85d1687b 100644
--- a/doc/administration/integration/terminal.md
+++ b/doc/administration/integration/terminal.md
@@ -14,20 +14,33 @@ A detailed overview of the architecture of web terminals and how they work
can be found in [this document](https://gitlab.com/gitlab-org/gitlab-workhorse/blob/master/doc/terminal.md).
In brief:
-* GitLab relies on the user to provide their own Kubernetes credentials, and to
+- GitLab relies on the user to provide their own Kubernetes credentials, and to
appropriately label the pods they create when deploying.
-* When a user navigates to the terminal page for an environment, they are served
+- When a user navigates to the terminal page for an environment, they are served
a JavaScript application that opens a WebSocket connection back to GitLab.
-* The WebSocket is handled in [Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse),
+- The WebSocket is handled in [Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse),
rather than the Rails application server.
-* Workhorse queries Rails for connection details and user permissions; Rails
- queries Kubernetes for them in the background, using [Sidekiq](../troubleshooting/sidekiq.md)
-* Workhorse acts as a proxy server between the user's browser and the Kubernetes
+- Workhorse queries Rails for connection details and user permissions. Rails
+ queries Kubernetes for them in the background using [Sidekiq](../troubleshooting/sidekiq.md).
+- Workhorse acts as a proxy server between the user's browser and the Kubernetes
API, passing WebSocket frames between the two.
-* Workhorse regularly polls Rails, terminating the WebSocket connection if the
+- Workhorse regularly polls Rails, terminating the WebSocket connection if the
user no longer has permission to access the terminal, or if the connection
details have changed.
+## Security
+
+GitLab and [GitLab Runner](https://docs.gitlab.com/runner/) take some
+precautions to keep interactive web terminal data encrypted between them, and
+everything protected with authorization guards. This is described in more
+detail below.
+
+- Interactive web terminals are completely disabled unless [`[session_server]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section) is configured.
+- Every time the runner starts, it will generate an `x509` certificate that will be used for a `wss` (Web Socket Secure) connection.
+- For every created job, a random URL is generated which is discarded at the end of the job. This URL is used to establish a web socket connection. The URL for the session is in the format `(IP|HOST):PORT/session/$SOME_HASH`, where the `IP/HOST` and `PORT` are the configured [`listen_address`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section).
+- Every session URL that is created has an authorization header that needs to be sent, to establish a `wss` connection.
+- The session URL is not exposed to the users in any way. GitLab holds all the state internally and proxies accordingly.
+
## Enabling and disabling terminal support
As web terminals use WebSockets, every HTTP/HTTPS reverse proxy in front of
@@ -40,10 +53,10 @@ However, if you run a [load balancer](../high_availability/load_balancer.md) in
front of GitLab, you may need to make some changes to your configuration. These
guides document the necessary steps for a selection of popular reverse proxies:
-* [Apache](https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html)
-* [NGINX](https://www.nginx.com/blog/websocket-nginx/)
-* [HAProxy](http://blog.haproxy.com/2012/11/07/websockets-load-balancing-with-haproxy/)
-* [Varnish](https://www.varnish-cache.org/docs/4.1/users-guide/vcl-example-websockets.html)
+- [Apache](https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html)
+- [NGINX](https://www.nginx.com/blog/websocket-nginx/)
+- [HAProxy](http://blog.haproxy.com/2012/11/07/websockets-load-balancing-with-haproxy/)
+- [Varnish](https://www.varnish-cache.org/docs/4.1/users-guide/vcl-example-websockets.html)
Workhorse won't let WebSocket requests through to non-WebSocket endpoints, so
it's safe to enable support for these headers globally. If you'd rather had a
@@ -51,8 +64,9 @@ narrower set of rules, you can restrict it to URLs ending with `/terminal.ws`
(although this may still have a few false positives).
If you installed from source, or have made any configuration changes to your
-Omnibus installation before upgrading to 8.15, you may need to make some
-changes to your configuration. See the [8.14 to 8.15 upgrade](../../update/8.14-to-8.15.md#nginx-configuration)
+Omnibus installation before upgrading to 8.15, you may need to make some changes
+to your configuration. See the [Upgrading Community Edition and Enterprise
+Edition from source](../../update/upgrading_from_source.md#nginx-configuration)
document for more details.
If you'd like to disable web terminal support in GitLab, just stop passing
@@ -60,8 +74,8 @@ the `Connection` and `Upgrade` hop-by-hop headers in the *first* HTTP reverse
proxy in the chain. For most users, this will be the NGINX server bundled with
Omnibus GitLab, in which case, you need to:
-* Find the `nginx['proxy_set_headers']` section of your `gitlab.rb` file
-* Ensure the whole block is uncommented, and then comment out or remove the
+- Find the `nginx['proxy_set_headers']` section of your `gitlab.rb` file
+- Ensure the whole block is uncommented, and then comment out or remove the
`Connection` and `Upgrade` lines.
For your own load balancer, just reverse the configuration changes recommended
diff --git a/doc/administration/invalidate_markdown_cache.md b/doc/administration/invalidate_markdown_cache.md
new file mode 100644
index 00000000000..ad64cb077c1
--- /dev/null
+++ b/doc/administration/invalidate_markdown_cache.md
@@ -0,0 +1,16 @@
+# Invalidate Markdown Cache
+
+For performance reasons, GitLab caches the HTML version of markdown text
+(e.g. issue and merge request descriptions, comments). It's possible
+that these cached versions become outdated, for example
+when the `external_url` configuration option is changed - causing links
+in the cached text to refer to the old URL.
+
+To avoid this problem, the administrator can invalidate the existing cache by
+increasing the `local_markdown_version` setting in application settings. This can
+be done by [changing the application settings through
+the API](../api/settings.md#change-application-settings):
+
+```bash
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/application/settings?local_markdown_version=<increased_number>
+```
diff --git a/doc/administration/issue_closing_pattern.md b/doc/administration/issue_closing_pattern.md
index 35f25e55414..160da47c780 100644
--- a/doc/administration/issue_closing_pattern.md
+++ b/doc/administration/issue_closing_pattern.md
@@ -17,7 +17,7 @@ The default pattern can be located in [gitlab.yml.example] under the
"Automatic issue closing" section.
> **Tip:**
-You are advised to use http://rubular.com to test the issue closing pattern.
+You are advised to use <http://rubular.com> to test the issue closing pattern.
Because Rubular doesn't understand `%{issue_ref}`, you can replace this by
`#\d+` when testing your patterns, which matches only local issue references like `#123`.
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index a1ea78b64bd..8522d046a92 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -165,12 +165,6 @@ _The artifacts are stored by default in
gitlab-rake gitlab:artifacts:migrate
```
- Currently this has to be executed manually and it will allow you to
- migrate the existing artifacts to the object storage, but all new
- artifacts will still be stored on the local disk. In the future
- you will be given an option to define a default storage artifacts for all
- new files.
-
---
**In installations from source:**
@@ -201,12 +195,6 @@ _The artifacts are stored by default in
sudo -u git -H bundle exec rake gitlab:artifacts:migrate RAILS_ENV=production
```
- Currently this has to be executed manually and it will allow you to
- migrate the existing artifacts to the object storage, but all new
- artifacts will still be stored on the local disk. In the future
- you will be given an option to define a default storage artifacts for all
- new files.
-
## Expiring artifacts
If an expiry date is used for the artifacts, they are marked for deletion
@@ -286,7 +274,7 @@ you can flip the feature flag from a Rails console.
## Set the maximum file size of the artifacts
Provided the artifacts are enabled, you can change the maximum file size of the
-artifacts through the [Admin area settings](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size).
+artifacts through the [Admin area settings](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size-core-only).
## Storage statistics
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 698f4caab3a..36dee75bd44 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -23,12 +23,13 @@ requests from the API are logged to a separate file in `api_json.log`.
Each line contains a JSON line that can be ingested by Elasticsearch, Splunk, etc. For example:
```json
-{"method":"GET","path":"/gitlab/gitlab-ce/issues/1234","format":"html","controller":"Projects::IssuesController","action":"show","status":200,"duration":229.03,"view":174.07,"db":13.24,"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","gitaly_calls":76}
+{"method":"GET","path":"/gitlab/gitlab-ce/issues/1234","format":"html","controller":"Projects::IssuesController","action":"show","status":200,"duration":229.03,"view":174.07,"db":13.24,"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","gitaly_calls":76,"queue_duration": 112.47}
```
In this example, you can see this was a GET request for a specific issue. Notice each line also contains performance data:
-1. `duration`: the total time taken to retrieve the request
+1. `duration`: total time in milliseconds taken to retrieve the request
+1. `queue_duration`: total time in milliseconds that the request was queued inside GitLab Workhorse
1. `view`: total time taken inside the Rails views
1. `db`: total time to retrieve data from the database
1. `gitaly_calls`: total number of calls made to Gitaly
@@ -91,6 +92,8 @@ This entry above shows an access to an internal endpoint to check whether an
associated SSH key can download the project in question via a `git fetch` or
`git clone`. In this example, we see:
+1. `duration`: total time in milliseconds taken to retrieve the request
+1. `queue_duration`: total time in milliseconds that the request was queued inside GitLab Workhorse
1. `method`: The HTTP method used to make the request
1. `path`: The relative path of the query
1. `params`: Key-value pairs passed in a query string or HTTP body. Sensitive parameters (e.g. passwords, tokens, etc.) are filtered out.
diff --git a/doc/administration/merge_request_diffs.md b/doc/administration/merge_request_diffs.md
new file mode 100644
index 00000000000..c34a9519ace
--- /dev/null
+++ b/doc/administration/merge_request_diffs.md
@@ -0,0 +1,147 @@
+# Merge request diffs storage **[CORE ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/52568) in GitLab 11.8.
+
+Merge request diffs are size-limited copies of diffs associated with merge
+requests. When viewing a merge request, diffs are sourced from these copies
+wherever possible as a performance optimization.
+
+By default, merge request diffs are stored in the database, in a table named
+`merge_request_diff_files`. Larger installations may find this table grows too
+large, in which case, switching to external storage is recommended.
+
+### Using external storage
+
+Merge request diffs can be stored on disk, or in object storage. In general, it
+is better to store the diffs in the database than on disk.
+
+To enable external storage of merge request diffs, follow the instructions below.
+
+**In Omnibus installations:**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['external_diffs_enabled'] = true
+ ```
+
+1. _The external diffs will be stored in in
+ `/var/opt/gitlab/gitlab-rails/shared/external-diffs`._ To change the path,
+ for example, to `/mnt/storage/external-diffs`, edit `/etc/gitlab/gitlab.rb`
+ and add the following line:
+
+ ```ruby
+ gitlab_rails['external_diffs_storage_path'] = "/mnt/storage/external-diffs"
+ ```
+
+1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+**In installations from source:**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following
+ lines:
+
+ ```yaml
+ external_diffs:
+ enabled: true
+ ```
+
+1. _The external diffs will be stored in
+ `/home/git/gitlab/shared/external-diffs`._ To change the path, for example,
+ to `/mnt/storage/external-diffs`, edit `/home/git/gitlab/config/gitlab.yml`
+ and add or amend the following lines:
+
+ ```yaml
+ external_diffs:
+ enabled: true
+ storage_path: /mnt/storage/external-diffs
+ ```
+
+1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
+
+### Using object storage
+
+Instead of storing the external diffs on disk, we recommended the use of an object
+store like AWS S3 instead. This configuration relies on valid AWS credentials to
+be configured already.
+
+### Object Storage Settings
+
+For source installations, these settings are nested under `external_diffs:` and
+then `object_store:`. On Omnibus installations, they are prefixed by
+`external_diffs_object_store_`.
+
+| Setting | Description | Default |
+|---------|-------------|---------|
+| `enabled` | Enable/disable object storage | `false` |
+| `remote_directory` | The bucket name where external diffs will be stored| |
+| `direct_upload` | Set to true to enable direct upload of external diffs without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. | `false` |
+| `background_upload` | Set to false to disable automatic upload. Option may be removed once upload is direct to S3 | `true` |
+| `proxy_download` | Set to true to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
+| `connection` | Various connection options described below | |
+
+#### S3 compatible connection settings
+
+The connection settings match those provided by [Fog](https://github.com/fog), and are as follows:
+
+| Setting | Description | Default |
+|---------|-------------|---------|
+| `provider` | Always `AWS` for compatible hosts | AWS |
+| `aws_access_key_id` | AWS credentials, or compatible | |
+| `aws_secret_access_key` | AWS credentials, or compatible | |
+| `aws_signature_version` | AWS signature version to use. 2 or 4 are valid options. Digital Ocean Spaces and other providers may need 2. | 4 |
+| `region` | AWS region | us-east-1 |
+| `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com |
+| `endpoint` | Can be used when configuring an S3 compatible service such as [Minio](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) |
+| `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false |
+| `use_iam_profile` | Set to true to use IAM profile instead of access keys | false
+
+**In Omnibus installations:**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with
+ the values you want:
+
+ ```ruby
+ gitlab_rails['external_diffs_enabled'] = true
+ gitlab_rails['external_diffs_object_store_enabled'] = true
+ gitlab_rails['external_diffs_object_store_remote_directory'] = "external-diffs"
+ gitlab_rails['external_diffs_object_store_connection'] = {
+ 'provider' => 'AWS',
+ 'region' => 'eu-central-1',
+ 'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
+ 'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY'
+ }
+ ```
+
+ Note that, if you are using AWS IAM profiles, be sure to omit the
+ AWS access key and secret access key/value pairs. For example:
+
+ ```ruby
+ gitlab_rails['external_diffs_object_store_connection'] = {
+ 'provider' => 'AWS',
+ 'region' => 'eu-central-1',
+ 'use_iam_profile' => true
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+**In installations from source:**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following
+ lines:
+
+ ```yaml
+ external_diffs:
+ enabled: true
+ object_store:
+ enabled: true
+ remote_directory: "external-diffs" # The bucket name
+ connection:
+ provider: AWS # Only AWS supported at the moment
+ aws_access_key_id: AWS_ACCESS_KEY_ID
+ aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ region: eu-central-1
+ ```
+
+1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
index 7947b0fedc4..ab43ec2cc4f 100644
--- a/doc/administration/monitoring/performance/grafana_configuration.md
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -33,8 +33,8 @@ Test Connection to ensure the configuration is correct.
- **Name**: InfluxDB
- **Default**: Checked
- **Type**: InfluxDB 0.9.x (Even if you're using InfluxDB 0.10.x)
-- **Url**: https://localhost:8086 (Or the remote URL if you've installed InfluxDB
-on a separate server)
+- **Url**: `https://localhost:8086` (Or the remote URL if you've installed InfluxDB
+ on a separate server)
- **Access**: proxy
- **Database**: gitlab
- **User**: admin (Or the username configured when setting up InfluxDB)
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index 6a55dbe1eb4..95f497a1470 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -10,11 +10,11 @@ It allows you to see (from left to right):
- the current host serving the page
- the timing of the page (backend, frontend)
- time taken and number of DB queries, click through for details of these queries
-![SQL profiling using the Performance Bar](img/performance_bar_sql_queries.png)
+ ![SQL profiling using the Performance Bar](img/performance_bar_sql_queries.png)
- time taken and number of [Gitaly] calls, click through for details of these calls
-![Gitaly profiling using the Performance Bar](img/performance_bar_gitaly_calls.png)
+ ![Gitaly profiling using the Performance Bar](img/performance_bar_gitaly_calls.png)
- profile of the code used to generate the page, line by line. In the profile view, the numbers in the left panel represent wall time, cpu time, and number of calls (based on [rblineprof](https://github.com/tmm1/rblineprof)).
-![Line profiling using the Performance Bar](img/performance_bar_line_profiling.png)
+ ![Line profiling using the Performance Bar](img/performance_bar_line_profiling.png)
- time taken and number of calls to Redis
- time taken and number of background jobs created by Sidekiq
- time taken and number of Ruby GC calls
diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md
index dfd9be3d04c..726882fbb87 100644
--- a/doc/administration/monitoring/performance/request_profiling.md
+++ b/doc/administration/monitoring/performance/request_profiling.md
@@ -2,14 +2,14 @@
## Procedure
-1. Grab the profiling token from `Monitoring > Requests Profiles` admin page
+1. Grab the profiling token from **Monitoring > Requests Profiles** admin page
(highlighted in a blue in the image below).
![Profile token](img/request_profiling_token.png)
1. Pass the header `X-Profile-Token: <token>` to the request you want to profile. You can use:
- Browser extensions. For example, [ModHeader](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj) Chrome extension.
- `curl`. For example, `curl --header 'X-Profile-Token: <token>' https://gitlab.example.com/group/project`.
1. Once request is finished (which will take a little longer than usual), you can
- view the profiling output from `Monitoring > Requests Profiles` admin page.
+ view the profiling output from **Monitoring > Requests Profiles** admin page.
![Profiling output](img/request_profile_result.png)
## Cleaning up
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index c9a2778b3a4..3bfcc9a289e 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -17,10 +17,7 @@ GitLab monitors its own internal service metrics, and makes them available at th
`/-/metrics` endpoint. Unlike other [Prometheus] exporters, in order to access
it, the client IP needs to be [included in a whitelist][whitelist].
-Currently the embedded Prometheus server is not automatically configured to
-collect metrics from this endpoint. We recommend setting up another Prometheus
-server, because the embedded server configuration is overwritten once every
-[reconfigure of GitLab][reconfigure]. In the future this will not be required.
+For Omnibus and Chart installations, these metrics are automatically enabled and collected as of [GitLab 9.4](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1702). For source installations or earlier versions, these metrics will need to be enabled manually and collected by a Prometheus server.
## Unicorn Metrics available
@@ -48,6 +45,8 @@ The following metrics are available:
| upload_file_does_not_exist | Counter | 10.7 in EE, 11.5 in CE | Number of times an upload record could not find its file |
| 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 |
+| unicorn_active_connections | Gauge | 11.0 | The number of active Unicorn connections (workers) |
+| unicorn_queued_connections | Gauge | 11.0 | The number of queued Unicorn connections |
### Ruby metrics
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index 8f65cd6418c..20d7ef9bb74 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -17,7 +17,7 @@ access to high quality time-series monitoring of GitLab services.
## Overview
Prometheus works by periodically connecting to data sources and collecting their
-performance metrics via the [various exporters](#prometheus-exporters). To view
+performance metrics via the [various exporters](#bundled-software-metrics). To view
and work with the monitoring data, you can either
[connect directly to Prometheus](#viewing-performance-metrics) or utilize a
dashboard tool like [Grafana].
diff --git a/doc/administration/operations/cleaning_up_redis_sessions.md b/doc/administration/operations/cleaning_up_redis_sessions.md
index 3a35aff8366..b45ca99fd80 100644
--- a/doc/administration/operations/cleaning_up_redis_sessions.md
+++ b/doc/administration/operations/cleaning_up_redis_sessions.md
@@ -20,7 +20,6 @@ configuration settings if you have used the advanced Redis
settings outlined in
[Configuration Files Documentation](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/README.md).
-
First we define a shell function with the proper Redis connection details.
```
diff --git a/doc/administration/operations/filesystem_benchmarking.md b/doc/administration/operations/filesystem_benchmarking.md
index 0397452e650..c0c242733a2 100644
--- a/doc/administration/operations/filesystem_benchmarking.md
+++ b/doc/administration/operations/filesystem_benchmarking.md
@@ -7,13 +7,72 @@ systems.
Normally when talking about filesystem performance the biggest concern is
with Network Filesystems (NFS). However, even some local disks can have slow
-IO. The information on this page can be used for either scenario.
+I/O. The information on this page can be used for either scenario.
-## Write Performance
+## Executing benchmarks
-The following one-line command is a quick benchmark for filesystem write
+### Benchmarking with `fio`
+
+We recommend using
+[fio](https://fio.readthedocs.io/en/latest/fio_doc.html) to test I/O
+performance. This test should be run both on the NFS server and on the
+application nodes that talk to the NFS server.
+
+To install:
+
+- On Ubuntu: `apt install fio`.
+- On `yum`-managed environments: `yum install fio`.
+
+Then run the following:
+
+```sh
+fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=/path/to/git-data/testfile --bs=4k --iodepth=64 --size=4G --readwrite=randrw --rwmixread=75
+```
+
+This will create a 4GB file in `/path/to/git-data/testfile`. It performs
+4KB reads and writes using a 75%/25% split within the file, with 64
+operations running at a time. Be sure to delete the file after the test
+completes.
+
+The output will vary depending on what version of `fio` installed. The following
+is an example output from `fio` v2.2.10 on a networked solid-state drive (SSD):
+
+```
+test: (g=0): rw=randrw, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=64
+ fio-2.2.10
+ Starting 1 process
+ test: Laying out IO file(s) (1 file(s) / 1024MB)
+ Jobs: 1 (f=1): [m(1)] [100.0% done] [131.4MB/44868KB/0KB /s] [33.7K/11.3K/0 iops] [eta 00m:00s]
+ test: (groupid=0, jobs=1): err= 0: pid=10287: Sat Feb 2 17:40:10 2019
+ read : io=784996KB, bw=133662KB/s, iops=33415, runt= 5873msec
+ write: io=263580KB, bw=44880KB/s, iops=11219, runt= 5873msec
+ cpu : usr=6.56%, sys=23.11%, ctx=266267, majf=0, minf=8
+ IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
+ submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
+ complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
+ issued : total=r=196249/w=65895/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
+ latency : target=0, window=0, percentile=100.00%, depth=64
+
+ Run status group 0 (all jobs):
+ READ: io=784996KB, aggrb=133661KB/s, minb=133661KB/s, maxb=133661KB/s, mint=5873msec, maxt=5873msec
+ WRITE: io=263580KB, aggrb=44879KB/s, minb=44879KB/s, maxb=44879KB/s, mint=5873msec, maxt=5873msec
+```
+
+Notice the `iops` values in this output. In this example, the SSD
+performed 33,415 read operations per second and 11,219 write operations
+per second. A spinning disk might yield 2,000 and 700 read and write
+operations per second.
+
+### Simple benchmarking
+
+NOTE: **Note:** This test is naive but may be useful if `fio` is not
+available on the system. It's possible to receive good results on this
+test but still have poor performance due to read speed and various other
+factors.
+
+The following one-line commands provide a quick benchmark for filesystem write and read
performance. This will write 1,000 small files to the directory in which it is
-executed.
+executed, and then read the same 1,000 files.
1. Change into the root of the appropriate
[repository storage path](../repository_storage_paths.md).
@@ -27,13 +86,18 @@ executed.
```sh
time for i in {0..1000}; do echo 'test' > "test${i}.txt"; done
```
+1. To benchmark read performance, run the command:
+
+ ```sh
+ time for i in {0..1000}; do cat "test${i}.txt" > /dev/null; done
+ ```
1. Remove the test files:
```sh
cd ../; rm -rf test
```
-The output of the `time for ...` command will look similar to the following. The
+The output of the `time for ...` commands will look similar to the following. The
important metric is the `real` time.
```sh
@@ -42,12 +106,13 @@ $ time for i in {0..1000}; do echo 'test' > "test${i}.txt"; done
real 0m0.116s
user 0m0.025s
sys 0m0.091s
+
+$ time for i in {0..1000}; do cat "test${i}.txt" > /dev/null; done
+
+real 0m3.118s
+user 0m1.267s
+sys 0m1.663s
```
From experience with multiple customers, this task should take under 10
-seconds to indicate good filesystem performance.
-
-NOTE: **Note:**
-This test is naive and only evaluates write performance. It's possible to
-receive good results on this test but still have poor performance due to read
-speed and various other factors. \ No newline at end of file
+seconds to indicate good filesystem performance.
diff --git a/doc/administration/operations/index.md b/doc/administration/operations/index.md
index a16fc7ae74f..32f36d68c50 100644
--- a/doc/administration/operations/index.md
+++ b/doc/administration/operations/index.md
@@ -3,20 +3,20 @@
Keep your GitLab instance up and running smoothly.
- [Clean up Redis sessions](cleaning_up_redis_sessions.md): Prior to GitLab 7.3,
-user sessions did not automatically expire from Redis. If
-you have been running a large GitLab server (thousands of users) since before
-GitLab 7.3 we recommend cleaning up stale sessions to compact the Redis
-database after you upgrade to GitLab 7.3.
+ user sessions did not automatically expire from Redis. If
+ you have been running a large GitLab server (thousands of users) since before
+ GitLab 7.3 we recommend cleaning up stale sessions to compact the Redis
+ database after you upgrade to GitLab 7.3.
- [Moving repositories](moving_repositories.md): Moving all repositories managed
-by GitLab to another file system or another server.
+ by GitLab to another file system or another server.
- [Sidekiq MemoryKiller](sidekiq_memory_killer.md): Configure Sidekiq MemoryKiller
-to restart Sidekiq.
+ to restart Sidekiq.
- [Unicorn](unicorn.md): Understand Unicorn and unicorn-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).
+ 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).
- [Filesystem Performance Benchmarking](filesystem_benchmarking.md): Filesystem
-performance can have a big impact on GitLab performance, especially for actions
-that read or write Git repositories. This information will help benchmark
-filesystem performance against known good and bad real-world systems.
+ performance can have a big impact on GitLab performance, especially for actions
+ that read or write Git repositories. This information will help benchmark
+ filesystem performance against known good and bad real-world systems.
diff --git a/doc/administration/operations/sidekiq_memory_killer.md b/doc/administration/operations/sidekiq_memory_killer.md
index cbffd883774..8eac42f2fe2 100644
--- a/doc/administration/operations/sidekiq_memory_killer.md
+++ b/doc/administration/operations/sidekiq_memory_killer.md
@@ -17,6 +17,11 @@ With the default settings, the MemoryKiller will cause 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 (e.g., 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.
diff --git a/doc/administration/operations/unicorn.md b/doc/administration/operations/unicorn.md
index bad61151bda..0e2079cb093 100644
--- a/doc/administration/operations/unicorn.md
+++ b/doc/administration/operations/unicorn.md
@@ -60,7 +60,17 @@ Unicorn master then automatically replaces the worker process.
This is a robust way to handle memory leaks: Unicorn is designed to handle
workers that 'crash' so no user requests will be dropped. The
unicorn-worker-killer gem is designed to only terminate a worker process _in
-between requests_, so no user requests are affected.
+between requests_, so no user requests are affected. You can set the minimum and
+maximum memory threshold (in bytes) for the Unicorn worker killer by
+setting the following values `/etc/gitlab/gitlab.rb`:
+
+```ruby
+unicorn['worker_memory_limit_min'] = "400 * 1 << 20"
+unicorn['worker_memory_limit_max'] = "650 * 1 << 20"
+```
+
+Otherwise, you can set the `GITLAB_UNICORN_MEMORY_MIN` and `GITLAB_UNICORN_MEMORY_MIN`
+[environment variables](../environment_variables.md).
This is what a Unicorn worker memory restart looks like in unicorn_stderr.log.
You see that worker 4 (PID 125918) is inspecting itself and decides to exit.
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index cbd3032bd4e..279ad018aed 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -11,7 +11,7 @@ description: 'Learn how to administer GitLab Pages.'
> - This guide is for Omnibus GitLab installations. If you have installed
> GitLab from source, follow the [Pages source installation document](source.md).
> - To learn how to use GitLab Pages, read the [user documentation][pages-userguide].
-> - Does NOT support subgroups. See [this issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/30548) for more information and status.
+> - Support for subgroup project's websites was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/30548) in GitLab 11.8.
This document describes how to set up the _latest_ GitLab Pages feature. Make
sure to read the [changelog](#changelog) if you are upgrading to a new GitLab
@@ -332,6 +332,42 @@ The maximum size of the unpacked archive per project can be configured in the
Admin area under the Application settings in the **Maximum size of pages (MB)**.
The default is 100MB.
+## Running GitLab Pages in a separate server
+
+You may want to run GitLab Pages daemon on a separate server in order to decrease the load on your main application server.
+Follow the steps below to configure GitLab Pages in a separate server.
+
+1. Suppose you have the main GitLab application server named `app1`. Prepare
+ new Linux server (let's call it `app2`), create NFS share there and configure access to
+ this share from `app1`. Let's use the default GitLab Pages folder `/var/opt/gitlab/gitlab-rails/shared/pages`
+ as the shared folder on `app2` and mount it to `/mnt/pages` on `app1`.
+
+1. On `app2` install GitLab omnibus and modify `/etc/gitlab/gitlab.rb` this way:
+
+ ```shell
+ external_url 'http://<ip-address-of-the-server>'
+ pages_external_url "http://<your-pages-domain>"
+ postgresql['enable'] = false
+ redis['enable'] = false
+ prometheus['enable'] = false
+ unicorn['enable'] = false
+ sidekiq['enable'] = false
+ gitlab_workhorse['enable'] = false
+ gitaly['enable'] = false
+ alertmanager['enable'] = false
+ node_exporter['enable'] = false
+ ```
+1. Run `sudo gitlab-ctl reconfigure`.
+1. On `app1` apply the following changes to `/etc/gitlab/gitlab.rb`:
+
+ ```shell
+ gitlab_pages['enable'] = false
+ pages_external_url "http://<your-pages-domain>"
+ gitlab_rails['pages_path'] = "/mnt/pages"
+ ```
+
+1. Run `sudo gitlab-ctl reconfigure`.
+
## Backup
Pages are part of the [regular backup][backup] so there is nothing to configure.
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 9f2b4d9075a..60800d445b8 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -88,12 +88,13 @@ since that is needed in all configurations.
### Wildcard domains
->**Requirements:**
-> - [Wildcard DNS setup](#dns-configuration)
->
-> ---
->
-> URL scheme: `http://page.example.io`
+**Requirements:**
+
+- [Wildcard DNS setup](#dns-configuration)
+
+---
+
+URL scheme: `http://page.example.io`
This is the minimum setup that you can use Pages with. It is the base for all
other setups as described below. Nginx will proxy all requests to the daemon.
diff --git a/doc/administration/polling.md b/doc/administration/polling.md
index 35aaa20df2c..a1077614677 100644
--- a/doc/administration/polling.md
+++ b/doc/administration/polling.md
@@ -10,15 +10,15 @@ say that issue notes poll every 2 seconds, and issue titles poll every 5
seconds; these are _not_ the actual values.
- 1 is the default, and recommended for most installations. (Issue notes poll
-every 2 seconds, and issue titles poll every 5 seconds.)
+ every 2 seconds, and issue titles poll every 5 seconds.)
- 0 will disable UI polling completely. (On the next poll, clients will stop
-polling for updates.)
+ polling for updates.)
- A value greater than 1 will slow polling down. If you see issues with
-database load from lots of clients polling for updates, increasing the
-multiplier from 1 can be a good compromise, rather than disabling polling
-completely. (For example: If this is set to 2, then issue notes poll every 4
-seconds, and issue titles poll every 10 seconds.)
+ database load from lots of clients polling for updates, increasing the
+ multiplier from 1 can be a good compromise, rather than disabling polling
+ completely. (For example: If this is set to 2, then issue notes poll every 4
+ seconds, and issue titles poll every 10 seconds.)
- A value between 0 and 1 will make the UI poll more frequently (so updates
-will show in other sessions faster), but is **not recommended**. 1 should be
-fast enough. (For example, if this is set to 0.5, then issue notes poll every
-1 second, and issue titles poll every 2.5 seconds.)
+ will show in other sessions faster), but is **not recommended**. 1 should be
+ fast enough. (For example, if this is set to 0.5, then issue notes poll every
+ 1 second, and issue titles poll every 2.5 seconds.)
diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md
index 0ca1d77f1d0..d8f80965c21 100644
--- a/doc/administration/raketasks/check.md
+++ b/doc/administration/raketasks/check.md
@@ -52,9 +52,9 @@ and these checks will verify them against current files.
Currently, integrity checks are supported for the following types of file:
-* CI artifacts (Available from version 10.7.0)
-* LFS objects (Available from version 10.6.0)
-* User uploads (Available from version 10.6.0)
+- CI artifacts (Available from version 10.7.0)
+- LFS objects (Available from version 10.6.0)
+- User uploads (Available from version 10.6.0)
**Omnibus Installation**
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index 0d863594fc7..b295b7d5dc4 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -60,6 +60,7 @@ Runs the following rake tasks:
It will check that each component was set up according to the installation guide and suggest fixes for issues found.
You may also have a look at our Troubleshooting Guides:
+
- [Troubleshooting Guide (GitLab)](http://docs.gitlab.com/ee/README.html#troubleshooting)
- [Troubleshooting Guide (Omnibus Gitlab)](http://docs.gitlab.com/omnibus/README.html#troubleshooting)
diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md
index b5c40478ea5..fd8ea8d3162 100644
--- a/doc/administration/raketasks/uploads/migrate.md
+++ b/doc/administration/raketasks/uploads/migrate.md
@@ -2,7 +2,7 @@
## Migrate to Object Storage
-After [configuring the object storage](../../uploads.md#using-object-storage) for GitLab's uploads, you may use this task to migrate existing uploads from the local storage to the remote storage.
+After [configuring the object storage](../../uploads.md#using-object-storage-core-only) for GitLab's uploads, you may use this task to migrate existing uploads from the local storage to the remote storage.
>**Note:**
All of the processing will be done in a background worker and requires **no downtime**.
diff --git a/doc/administration/reply_by_email_postfix_setup.md b/doc/administration/reply_by_email_postfix_setup.md
index 4c42cb7756a..d57fc67c83e 100644
--- a/doc/administration/reply_by_email_postfix_setup.md
+++ b/doc/administration/reply_by_email_postfix_setup.md
@@ -333,6 +333,6 @@ If all the tests were successful, Postfix is all set up and ready to receive ema
---
-_This document was adapted from https://help.ubuntu.com/community/PostfixBasicSetupHowto, by contributors to the Ubuntu documentation wiki._
+_This document was adapted from <https://help.ubuntu.com/community/PostfixBasicSetupHowto>, by contributors to the Ubuntu documentation wiki._
[incoming email]: incoming_email.md
diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md
index 8b725e50f58..7cf8f20a9dc 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -31,7 +31,7 @@ panel.
If the repository check fails for some repository you should look up the error
in `repocheck.log`:
-- in the [admin panel](logs.md#repocheck-log)
+- in the [admin panel](logs.md#repochecklog)
- or on disk, see:
- `/var/log/gitlab/gitlab-rails` for Omnibus installations
- `/home/git/gitlab/log` for installations from source
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index 12238ba7b32..4934aaf39f7 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -7,8 +7,8 @@
Legacy Storage is the storage behavior prior to version 10.0. For historical
reasons, GitLab replicated the same mapping structure from the projects URLs:
-* Project's repository: `#{namespace}/#{project_name}.git`
-* Project's wiki: `#{namespace}/#{project_name}.wiki.git`
+- Project's repository: `#{namespace}/#{project_name}.git`
+- Project's wiki: `#{namespace}/#{project_name}.wiki.git`
This structure made it simple to migrate from existing solutions to GitLab and
easy for Administrators to find where the repository is stored.
@@ -41,7 +41,6 @@ Registry, etc.
## Hashed Storage
-
Hashed Storage is the new storage behavior we rolled out with 10.0. Instead
of coupling project URL and the folder structure where the repository will be
stored on disk, we are coupling a hash, based on the project's ID. This makes
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index b561c2f82aa..cbc3fbd9473 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -62,7 +62,8 @@ sudo gitlab-ctl status
Notice that all services say `ok: run`.
-Sometimes, components time out during the restart and sometimes they get stuck.
+Sometimes, components time out (look for `timeout` in the logs) during the
+restart and sometimes they get stuck.
In that case, you can use `gitlab-ctl kill <service>` to send the `SIGKILL`
signal to the service, for example `sidekiq`. After that, a restart should
perform fine.
@@ -136,7 +137,6 @@ If you are using other init systems, like systemd, you can check the
[GitLab Recipes][gl-recipes] repository for some unofficial services. These are
**not** officially supported so use them at your own risk.
-
[omnibus-dl]: https://about.gitlab.com/downloads/ "Download the Omnibus packages"
[install]: ../install/installation.md "Documentation to install GitLab from source"
[mailroom]: reply_by_email.md "Used for replying by email in GitLab issues and merge requests"
diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md
index 643c5b9fe80..8f7280d5128 100644
--- a/doc/administration/troubleshooting/debug.md
+++ b/doc/administration/troubleshooting/debug.md
@@ -158,7 +158,7 @@ are concerned about affecting others during a production system, you can run a
separate Rails process to debug the issue:
1. Log in to your GitLab account.
-1. Copy the URL that is causing problems (e.g. https://gitlab.com/ABC).
+1. Copy the URL that is causing problems (e.g. `https://gitlab.com/ABC`).
1. Create a Personal Access Token for your user (Profile Settings -> Access Tokens).
1. Bring up the GitLab Rails console. For omnibus users, run:
@@ -211,5 +211,5 @@ The output in `/tmp/unicorn.txt` may help diagnose the root cause.
# More information
-* [Debugging Stuck Ruby Processes](https://blog.newrelic.com/2013/04/29/debugging-stuck-ruby-processes-what-to-do-before-you-kill-9/)
-* [Cheatsheet of using gdb and ruby processes](gdb-stuck-ruby.txt)
+- [Debugging Stuck Ruby Processes](https://blog.newrelic.com/2013/04/29/debugging-stuck-ruby-processes-what-to-do-before-you-kill-9/)
+- [Cheatsheet of using gdb and ruby processes](gdb-stuck-ruby.txt)
diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md
index 476ae8e8a76..8c0c7a36736 100644
--- a/doc/administration/uploads.md
+++ b/doc/administration/uploads.md
@@ -53,7 +53,7 @@ _The uploads are stored by default in
> **Notes:**
>
> - [Introduced][ee-3867] in [GitLab Premium][eep] 10.5.
-> - [Introduced][ce17358] in [GitLab Core][ce] 10.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17358) in [GitLab Core][ce] 10.7.
> - Since version 11.1, we support direct_upload to S3.
If you don't want to use the local disk where GitLab is installed to store the
@@ -149,7 +149,6 @@ _The uploads are stored by default in
[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
[restart gitlab]: restart_gitlab.md#installations-from-source "How to restart GitLab"
-[eep]: https://about.gitlab.com/gitlab-ee/ "GitLab Enterprise Edition Premium"
+[eep]: https://about.gitlab.com/gitlab-ee/ "GitLab Premium"
[ce]: https://about.gitlab.com/gitlab-ce/ "GitLab Community Edition"
[ee-3867]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3867
-[ce-17358]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17358
diff --git a/doc/api/README.md b/doc/api/README.md
index fd5e88cb9d5..7ec7955c596 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -1,94 +1,140 @@
# GitLab API
-Automate GitLab via a simple and powerful API. All definitions can be found
-under [`/lib/api`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/api).
+Automate GitLab via a simple and powerful API.
The main GitLab API is a [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) API. Therefore, documentation in this section assumes knowledge of REST concepts.
-## API Resources
-
-The following API resources are available:
-
-- [Applications](applications.md)
-- [Avatar](avatar.md)
-- [Award emoji](award_emoji.md)
-- [Branches](branches.md)
-- [Broadcast messages](broadcast_messages.md)
-- [Code snippets](snippets.md)
-- [Commits](commits.md)
-- [Custom attributes](custom_attributes.md)
-- [Deploy keys](deploy_keys.md), and [deploy keys for multiple projects](deploy_key_multiple_projects.md)
-- [Deployments](deployments.md)
-- [Discussions](discussions.md) (threaded comments)
-- [Environments](environments.md)
-- [Events](events.md)
-- [Feature flags](features.md)
-- Group-related resources, including:
- - [Groups](groups.md)
- - [Group access requests](access_requests.md)
- - [Group badges](group_badges.md)
- - [Group issue boards](group_boards.md)
- - [Group-level variables](group_level_variables.md)
- - [Group members](members.md)
- - [Group milestones](group_milestones.md)
-- [Issues](issues.md)
-- [Issue boards](boards.md)
-- [Jobs](jobs.md)
-- [Keys](keys.md)
-- [Labels](labels.md)
-- [Markdown](markdown.md)
-- [Merge requests](merge_requests.md)
-- [Namespaces](namespaces.md)
-- [Notes](notes.md) (comments)
-- [Notification settings](notification_settings.md)
-- [Pages domains](pages_domains.md)
-- [Pipelines](pipelines.md)
-- [Pipeline schedules](pipeline_schedules.md)
-- [Pipeline triggers](pipeline_triggers.md) and [triggering pipelines](../ci/triggers/README.md)
-- Project-related resources, including:
- - [Projects](projects.md) including setting Webhooks
- - [Project access requests](access_requests.md)
- - [Project badges](project_badges.md)
- - [Project-level variables](project_level_variables.md)
- - [Project import/export](project_import_export.md)
- - [Project members](members.md)
- - [Project milestones](milestones.md)
- - [Project snippets](project_snippets.md)
- - [Project templates](project_templates.md) (see also [Templates API Resources](#templates-api-resources))
-- [Protected branches](protected_branches.md)
-- [Protected tags](protected_tags.md)
-- [Repositories](repositories.md)
-- [Repository files](repository_files.md)
-- [Repository submodules](repository_submodules.md)
-- [Resource label events](resource_label_events.md)
-- [Runners](runners.md)
-- [Search](search.md)
-- [Services](services.md)
-- [Settings](settings.md)
-- [Sidekiq metrics](sidekiq_metrics.md)
-- [System hooks](system_hooks.md)
-- [Tags](tags.md)
-- [Todos](todos.md)
-- [Users](users.md)
-- [Validate CI configuration](lint.md) (linting)
-- [Version](version.md)
-- [Wikis](wikis.md)
-
-See also [V3 to V4](v3_to_v4.md).
-
-### Templates API Resources
+## API resources
+
+Available API resources can be grouped in the following contexts:
+
+- [Projects](#project-resources).
+- [Groups](#group-resources).
+- [Standalone](#standalone-resources).
+
+See also:
+
+- [V3 to V4](v3_to_v4.md).
+- Adding [deploy keys for multiple projects](deploy_key_multiple_projects.md).
+
+### Project resources
+
+The following API resources are available in the project context:
+
+| Resource | Available endpoints |
+|:------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Access requests](access_requests.md) | `/projects/:id/access_requests` (also available for groups) |
+| [Award emoji](award_emoji.md) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` |
+| [Branches](branches.md) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` |
+| [Commits](commits.md) | `/projects/:id/repository/commits`, `/projects/:id/statuses` |
+| [Container Registry](container_registry.md) | `/projects/:id/registry/repositories` |
+| [Custom attributes](custom_attributes.md) | `/projects/:id/custom_attributes` (also available for groups and users) |
+| [Deploy keys](deploy_keys.md) | `/projects/:id/deploy_keys` (also available standalone) |
+| [Deployments](deployments.md) | `/projects/:id/deployments` |
+| [Discussions](discussions.md) (threaded comments) | `/projects/:id/issues/.../discussions`, `/projects/:id/snippets/.../discussions`, `/projects/:id/merge_requests/.../discussions`, `/projects/:id/commits/.../discussions` |
+| [Environments](environments.md) | `/projects/:id/environments` |
+| [Events](events.md) | `/projects/:id/events` (also available for users and standalone) |
+| [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) |
+| [Issue boards](boards.md) | `/projects/:id/boards` |
+| [Jobs](jobs.md) | `/projects/:id/jobs`, `/projects/:id/pipelines/.../jobs` |
+| [Labels](labels.md) | `/projects/:id/labels` |
+| [Members](members.md) | `/projects/:id/members` (also available for groups) |
+| [Merge requests](merge_requests.md) | `/projects/:id/merge_requests` (also available for groups and standalone) |
+| [Notes](notes.md) (comments) | `/projects/:id/issues/.../notes`, `/projects/:id/snippets/.../notes`, `/projects/:id/merge_requests/.../notes` |
+| [Notification settings](notification_settings.md) | `/projects/:id/notification_settings` (also available for groups and standalone) |
+| [Pages domains](pages_domains.md) | `/projects/:id/pages` (also available standalone) |
+| [Pipelines](pipelines.md) | `/projects/:id/pipelines` |
+| [Pipeline schedules](pipeline_schedules.md) | `/projects/:id/pipeline_schedules` |
+| [Pipeline triggers](pipeline_triggers.md) | `/projects/:id/triggers` |
+| [Projects](projects.md) including setting Webhooks | `/projects`, `/projects/:id/hooks` (also available for users) |
+| [Project badges](project_badges.md) | `/projects/:id/badges` |
+| [Project clusters](project_clusters.md) | `/projects/:id/clusters` |
+| [Project-level variables](project_level_variables.md) | `/projects/:id/variables` |
+| [Project import/export](project_import_export.md) | `/projects/:id/export`, `/projects/import`, `/projects/:id/import` |
+| [Project milestones](milestones.md) | `/projects/:id/milestones` |
+| [Project snippets](project_snippets.md) | `/projects/:id/snippets` |
+| [Project templates](project_templates.md) | `/projects/:id/templates` |
+| [Protected branches](protected_branches.md) | `/projects/:id/protected_branches` |
+| [Protected tags](protected_tags.md) | `/projects/:id/protected_tags` |
+| [Releases](releases/index.md) | `/projects/:id/releases` |
+| [Release links](releases/links.md) | `/projects/:id/releases/.../assets/links` |
+| [Repositories](repositories.md) | `/projects/:id/repository` |
+| [Repository files](repository_files.md) | `/projects/:id/repository/files` |
+| [Repository submodules](repository_submodules.md) | `/projects/:id/repository/submodules` |
+| [Resource label events](resource_label_events.md) | `/projects/:id/issues/.../resource_label_events`, `/projects/:id/merge_requests/.../resource_label_events` |
+| [Runners](runners.md) | `/projects/:id/runners` (also available standalone) |
+| [Search](search.md) | `/projects/:id/search` (also available for groups and standalone) |
+| [Services](services.md) | `/projects/:id/services` |
+| [Tags](tags.md) | `/projects/:id/repository/tags` |
+| [Wikis](wikis.md) | `/projects/:id/wikis` |
+
+### Group resources
+
+The following API resources are available in the group context:
+
+| Resource | Available endpoints |
+|:--------------------------------------------------|:---------------------------------------------------------------------------------|
+| [Access requests](access_requests.md) | `/groups/:id/access_requests/` (also available for projects) |
+| [Custom attributes](custom_attributes.md) | `/groups/:id/custom_attributes` (also available for projects and users) |
+| [Groups](groups.md) | `/groups`, `/groups/.../subgroups` |
+| [Group badges](group_badges.md) | `/groups/:id/badges` |
+| [Group issue boards](group_boards.md) | `/groups/:id/boards` |
+| [Group labels](group_labels.md) | `/groups/:id/labels` |
+| [Group-level variables](group_level_variables.md) | `/groups/:id/variables` |
+| [Group milestones](group_milestones.md) | `/groups/:id/milestones` |
+| [Issues](issues.md) | `/groups/:id/issues` (also available for projects and standalone) |
+| [Members](members.md) | `/groups/:id/members` (also available for projects) |
+| [Merge requests](merge_requests.md) | `/groups/:id/merge_requests` (also available for projects and standalone) |
+| [Notification settings](notification_settings.md) | `/groups/:id/notification_settings` (also available for projects and standalone) |
+| [Search](search.md) | `/groups/:id/search` (also available for projects and standalone) |
+
+### Standalone resources
+
+The following API resources are available outside of project and group contexts (including `/users`):
+
+| Resource | Available endpoints |
+|:--------------------------------------------------|:------------------------------------------------------------------------|
+| [Applications](applications.md) | `/applications` |
+| [Avatar](avatar.md) | `/avatar` |
+| [Broadcast messages](broadcast_messages.md) | `/broadcast_messages` |
+| [Code snippets](snippets.md) | `/snippets` |
+| [Custom attributes](custom_attributes.md) | `/users/:id/custom_attributes` (also available for groups and projects) |
+| [Deploy keys](deploy_keys.md) | `/deploy_keys` (also available for projects) |
+| [Events](events.md) | `/events`, `/users/:id/events` (also available for projects) |
+| [Feature flags](features.md) | `/features` |
+| [Import repository from GitHub](import.md) | `/import/github` |
+| [Issues](issues.md) | `/issues` (also available for groups and projects) |
+| [Keys](keys.md) | `/keys` |
+| [Markdown](markdown.md) | `/markdown` |
+| [Merge requests](merge_requests.md) | `/merge_requests` (also available for groups and projects) |
+| [Namespaces](namespaces.md) | `/namespaces` |
+| [Notification settings](notification_settings.md) | `/notification_settings` (also available for groups and projects) |
+| [Pages domains](pages_domains.md) | `/pages/domains` (also available for projects) |
+| [Projects](projects.md) | `/users/:id/projects` (also available for projects) |
+| [Runners](runners.md) | `/runners` (also available for projects) |
+| [Search](search.md) | `/search` (also available for groups and projects) |
+| [Settings](settings.md) | `/application/settings` |
+| [Sidekiq metrics](sidekiq_metrics.md) | `/sidekiq` |
+| [Suggestions](suggestions.md) | `/suggestions` |
+| [System hooks](system_hooks.md) | `/hooks` |
+| [Todos](todos.md) | `/todos` |
+| [Users](users.md) | `/users` |
+| [Validate `.gitlab-ci.yml` file](lint.md) | `/lint` |
+| [Version](version.md) | `/version` |
+
+### Templates API resources
Endpoints are available for:
- [Dockerfile templates](templates/dockerfiles.md).
-- [gitignore templates](templates/gitignores.md).
+- [`.gitignore` templates](templates/gitignores.md).
- [GitLab CI YAML templates](templates/gitlab_ci_ymls.md).
- [Open source license templates](templates/licenses.md).
## Road to GraphQL
Going forward, we will start on moving to
-[GraphQL](http://graphql.org/learn/best-practices/) and deprecate the use of
+[GraphQL](graphql/index.md) and deprecate the use of
controller-specific endpoints. GraphQL has a number of benefits:
1. We avoid having to maintain two different APIs.
@@ -103,7 +149,7 @@ have been resolved to our satisfaction by the relicensing of the reference
implementations under MIT, and the use of the OWF license for the GraphQL
specification.
-## Compatibility Guidelines
+## Compatibility guidelines
The HTTP API is versioned using a single number, the current one being 4. This
number symbolizes the same as the major version number as described by
@@ -194,13 +240,13 @@ You can use a [personal access token][pat] to authenticate with the API by passi
Example of using the personal access token in a parameter:
```shell
-curl https://gitlab.example.com/api/v4/projects?private_token=9koXpg98eAheJpvBs5tK
+curl https://gitlab.example.com/api/v4/projects?private_token=<your_access_token>
```
Example of using the personal access token in a header:
```shell
-curl --header "Private-Token: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects
+curl --header "Private-Token: <your_access_token>" https://gitlab.example.com/api/v4/projects
```
Read more about [personal access tokens][pat].
@@ -228,7 +274,7 @@ personal access tokens, and to using the [Sudo](#sudo) feature, since the user's
password/token may not be known or may change over time.
For more information, refer to the
-[users API](users.md#retrieve-user-impersonation-tokens) docs.
+[users API](users.md#create-an-impersonation-token) docs.
Impersonation tokens are used exactly like regular personal access tokens, and can be passed in either the
`private_token` parameter or the `Private-Token` header.
@@ -319,22 +365,22 @@ Example of a valid API call and a request using cURL with sudo request,
providing a username:
```
-GET /projects?private_token=9koXpg98eAheJpvBs5tK&sudo=username
+GET /projects?private_token=<your_access_token>&sudo=username
```
```shell
-curl --header "Private-Token: 9koXpg98eAheJpvBs5tK" --header "Sudo: username" "https://gitlab.example.com/api/v4/projects"
+curl --header "Private-Token: <your_access_token>" --header "Sudo: username" "https://gitlab.example.com/api/v4/projects"
```
Example of a valid API call and a request using cURL with sudo request,
providing an ID:
```
-GET /projects?private_token=9koXpg98eAheJpvBs5tK&sudo=23
+GET /projects?private_token=<your_access_token>&sudo=23
```
```shell
-curl --header "Private-Token: 9koXpg98eAheJpvBs5tK" --header "Sudo: 23" "https://gitlab.example.com/api/v4/projects"
+curl --header "Private-Token: <your_access_token>" --header "Sudo: 23" "https://gitlab.example.com/api/v4/projects"
```
## Status codes
@@ -383,7 +429,7 @@ resources you can pass the following parameters:
In the example below, we list 50 [namespaces](namespaces.md) per page.
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/namespaces?per_page=50
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/namespaces?per_page=50
```
### Pagination Link header
@@ -397,7 +443,7 @@ and we request the second page (`page=2`) of [comments](notes.md) of the issue
with ID `8` which belongs to the project with ID `8`:
```bash
-curl --head --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/8/issues/8/notes?per_page=3&page=2
+curl --head --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/8/issues/8/notes?per_page=3&page=2
```
The response will then be:
@@ -434,6 +480,14 @@ Additional pagination headers are also sent back.
| `X-Next-Page` | The index of the next page |
| `X-Prev-Page` | The index of the previous page |
+CAUTION: **Caution:**
+For performance reasons since
+[GitLab 11.8](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23931)
+and **behind the `api_kaminari_count_with_limit`
+[feature flag](../development/feature_flags.md)**, if the number of resources is
+more than 10,000, the `X-Total` and `X-Total-Pages` headers as well as the
+`rel="last"` `Link` are not present in the response headers.
+
## Namespaced path encoding
If using namespaced API calls, make sure that the `NAMESPACE/PROJECT_NAME` is
@@ -465,7 +519,7 @@ We can call the API with `array` and `hash` types parameters as shown below:
`import_sources` is a parameter of type `array`:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
-d "import_sources[]=github" \
-d "import_sources[]=bitbucket" \
"https://gitlab.example.com/api/v4/some_endpoint
@@ -476,7 +530,7 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \
`override_params` is a parameter of type `hash`:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
--form "namespace=email" \
--form "path=impapi" \
--form "file=@/path/to/somefile.txt"
@@ -592,7 +646,7 @@ Content-Type: application/json
## Encoding `+` in ISO 8601 dates
If you need to include a `+` in a query parameter, you may need to use `%2B` instead due
-a [W3 recommendation](http://www.w3.org/Addressing/URL/4_URI_Recommentations.html) that
+to a [W3 recommendation](http://www.w3.org/Addressing/URL/4_URI_Recommentations.html) that
causes a `+` to be interpreted as a space. For example, in an ISO 8601 date, you may want to pass
a time in Mountain Standard Time, such as:
diff --git a/doc/api/access_requests.md b/doc/api/access_requests.md
index 4b2014ca843..973c3968d90 100644
--- a/doc/api/access_requests.md
+++ b/doc/api/access_requests.md
@@ -28,8 +28,8 @@ GET /projects/:id/access_requests
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/access_requests
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/access_requests
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/access_requests
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/access_requests
```
Example response:
@@ -69,8 +69,8 @@ POST /projects/:id/access_requests
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/access_requests
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/access_requests
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/access_requests
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/access_requests
```
Example response:
@@ -102,8 +102,8 @@ PUT /projects/:id/access_requests/:user_id/approve
| `access_level` | integer | no | A valid access level (defaults: `30`, developer access level) |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id/approve?access_level=20
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id/approve?access_level=20
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id/approve?access_level=20
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id/approve?access_level=20
```
Example response:
@@ -134,6 +134,6 @@ DELETE /projects/:id/access_requests/:user_id
| `user_id` | integer | yes | The user ID of the access requester |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id
```
diff --git a/doc/api/applications.md b/doc/api/applications.md
index d74a3cdf5c1..82955f0c1db 100644
--- a/doc/api/applications.md
+++ b/doc/api/applications.md
@@ -1,29 +1,37 @@
# Applications API
-> [Introduced][ce-8160] in GitLab 10.5
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8160) in GitLab 10.5.
-[ce-8160]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8160
+Applications API operates on OAuth applications for:
-Only admin user can use the Applications API.
+- [Using GitLab as an authentication provider](../integration/oauth_provider.md).
+- [Allowing access to GitLab resources on a user's behalf](oauth2.md).
-## Create a application
+NOTE: **Note:**
+Only admin users can use the Applications API.
-Create a application by posting a JSON payload.
+## Create an application
+
+Create an application by posting a JSON payload.
Returns `200` if the request succeeds.
-```
+```text
POST /applications
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `name` | string | yes | The name of the application |
-| `redirect_uri` | string | yes | The redirect URI of the application |
-| `scopes` | string | yes | The scopes of the application |
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:---------------|:-------|:---------|:---------------------------------|
+| `name` | string | yes | Name of the application. |
+| `redirect_uri` | string | yes | Redirect URI of the application. |
+| `scopes` | string | yes | Scopes of the application. |
+
+Example request:
-```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "name=MyApplication&redirect_uri=http://redirect.uri&scopes=" https://gitlab.example.com/api/v4/applications
+```sh
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "name=MyApplication&redirect_uri=http://redirect.uri&scopes=" https://gitlab.example.com/api/v4/applications
```
Example response:
@@ -42,12 +50,14 @@ Example response:
List all registered applications.
-```
+```text
GET /applications
```
-```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/applications
+Example request:
+
+```sh
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/applications
```
Example response:
@@ -63,7 +73,8 @@ Example response:
]
```
-> Note: the `secret` value will not be exposed by this API.
+NOTE: **Note:**
+The `secret` value will not be exposed by this API.
## Delete an application
@@ -71,7 +82,7 @@ Delete a specific application.
Returns `204` if the request succeeds.
-```
+```text
DELETE /applications/:id
```
@@ -79,6 +90,8 @@ Parameters:
- `id` (required) - The id of the application (not the application_id)
-```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/applications/:id
+Example request:
+
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/applications/:id
```
diff --git a/doc/api/avatar.md b/doc/api/avatar.md
index aa6f7c185ae..e55fffba4b2 100644
--- a/doc/api/avatar.md
+++ b/doc/api/avatar.md
@@ -1,33 +1,41 @@
# Avatar API
-> [Introduced][ce-19121] in GitLab 11.0
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19121) in GitLab 11.0.
## Get a single avatar URL
-Get a single avatar URL for a given email address. If user with matching public
-email address is not found, results from external avatar services are returned.
-This endpoint can be accessed without authentication. In case public visibility
-is restricted, response will be `403 Forbidden` when unauthenticated.
+Get a single [avatar](../user/profile/index.md#profile-settings) URL for a user with the given email address.
-```
+If:
+
+- No user with the given public email address is found, results from external avatar services are
+ returned.
+- Public visibility is restricted, response will be `403 Forbidden` when unauthenticated.
+
+NOTE: **Note:**
+This endpoint can be accessed without authentication.
+
+```text
GET /avatar?email=admin@example.com
```
-| Attribute | Type | Required | Description |
-| --------- | ------- | -------- | --------------------- |
-| `email` | string | yes | Public email address of the user |
-| `size` | integer | no | Single pixel dimension (since images are squares). Only used for avatar lookups at `Gravatar` or at the configured `Libravatar` server |
+Parameters:
-```bash
-curl https://gitlab.example.com/api/v4/avatar?email=admin@example.com
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
+| `email` | string | yes | Public email address of the user. |
+| `size` | integer | no | Single pixel dimension (since images are squares). Only used for avatar lookups at `Gravatar` or at the configured `Libravatar` server. |
+
+Example request:
+
+```sh
+curl https://gitlab.example.com/api/v4/avatar?email=admin@example.com&size=32
```
Example response:
```json
{
- "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon"
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=64&d=identicon"
}
```
-
-[ce-19121]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19121
diff --git a/doc/api/award_emoji.md b/doc/api/award_emoji.md
index 3f9542d6653..1d0e39e6bbf 100644
--- a/doc/api/award_emoji.md
+++ b/doc/api/award_emoji.md
@@ -1,19 +1,26 @@
# Award Emoji API
-> [Introduced][ce-4575] in GitLab 8.9, Snippet support in 8.12
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4575) in GitLab 8.9. Snippet support added in 8.12.
+An [awarded emoji](../user/award_emojis.md) tells a thousand words.
-An awarded emoji tells a thousand words, and can be awarded on issues, merge
-requests, snippets, and notes/comments. Issues, merge requests, snippets, and notes are further called
-`awardables`.
+Emoji can be awarded on the following (known as "awardables"):
+
+- [Issues](../user/project/issues/index.md) ([API](issues.md)).
+- [Merge requests](../user/project/merge_requests/index.md) ([API](merge_requests.md)).
+- [Snippets](../user/snippets.md) ([API](snippets.md)).
+
+Emoji can also [be awarded](../user/award_emojis.html#award-emoji-for-comments) on comments (also known as notes). See also [Notes API](notes.md).
## Issues, merge requests, and snippets
+See [Award Emoji on Comments](#award-emoji-on-comments) for information on using these endpoints with comments.
+
### List an awardable's award emoji
-Gets a list of all award emoji
+Get a list of all award emoji for a specified awardable.
-```
+```text
GET /projects/:id/issues/:issue_iid/award_emoji
GET /projects/:id/merge_requests/:merge_request_iid/award_emoji
GET /projects/:id/snippets/:snippet_id/award_emoji
@@ -21,16 +28,18 @@ GET /projects/:id/snippets/:snippet_id/award_emoji
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `awardable_id` | integer | yes | The ID (`iid` for merge requests/issues, `id` for snippets) of an awardable |
+| Attribute | Type | Required | Description |
+|:---------------|:---------------|:---------|:-----------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | ID (`iid` for merge requests/issues, `id` for snippets) of an awardable. |
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji
```
-Example Response:
+Example response:
```json
[
@@ -71,9 +80,9 @@ Example Response:
### Get single award emoji
-Gets a single award emoji from an issue, snippet, or merge request.
+Get a single award emoji from an issue, snippet, or merge request.
-```
+```text
GET /projects/:id/issues/:issue_iid/award_emoji/:award_id
GET /projects/:id/merge_requests/:merge_request_iid/award_emoji/:award_id
GET /projects/:id/snippets/:snippet_id/award_emoji/:award_id
@@ -81,17 +90,19 @@ GET /projects/:id/snippets/:snippet_id/award_emoji/:award_id
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `awardable_id` | integer | yes | The ID (`iid` for merge requests/issues, `id` for snippets) of an awardable |
-| `award_id` | integer | yes | The ID of the award emoji |
+| Attribute | Type | Required | Description |
+|:---------------|:---------------|:---------|:-----------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | ID (`iid` for merge requests/issues, `id` for snippets) of an awardable. |
+| `award_id` | integer | yes | ID of the award emoji. |
+
+Example request:
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/1
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/1
```
-Example Response:
+Example response:
```json
{
@@ -114,9 +125,9 @@ Example Response:
### Award a new emoji
-This end point creates an award emoji on the specified resource
+Create an award emoji on the specified awardable.
-```
+```text
POST /projects/:id/issues/:issue_iid/award_emoji
POST /projects/:id/merge_requests/:merge_request_iid/award_emoji
POST /projects/:id/snippets/:snippet_id/award_emoji
@@ -124,14 +135,14 @@ POST /projects/:id/snippets/:snippet_id/award_emoji
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `awardable_id` | integer | yes | The ID (`iid` for merge requests/issues, `id` for snippets) of an awardable |
-| `name` | string | yes | The name of the emoji, without colons |
+| Attribute | Type | Required | Description |
+|:---------------|:---------------|:---------|:-----------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | ID (`iid` for merge requests/issues, `id` for snippets) of an awardable. |
+| `name` | string | yes | Name of the emoji without colons. |
-```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji?name=blowfish
+```sh
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji?name=blowfish
```
Example Response:
@@ -157,10 +168,12 @@ Example Response:
### Delete an award emoji
-Sometimes its just not meant to be, and you'll have to remove your award. Only available to
-admins or the author of the award.
+Sometimes it's just not meant to be and you'll have to remove the award.
-```
+NOTE: **Note:**
+Only available to administrators or the author of the award.
+
+```text
DELETE /projects/:id/issues/:issue_iid/award_emoji/:award_id
DELETE /projects/:id/merge_requests/:merge_request_iid/award_emoji/:award_id
DELETE /projects/:id/snippets/:snippet_id/award_emoji/:award_id
@@ -168,43 +181,48 @@ DELETE /projects/:id/snippets/:snippet_id/award_emoji/:award_id
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `issue_iid` | integer | yes | The internal ID of an issue |
-| `award_id` | integer | yes | The ID of an award_emoji |
+| Attribute | Type | Required | Description |
+|:---------------|:---------------|:---------|:-----------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issue_iid`/`merge_request_iid`/`snippet_id` | integer | yes | ID (`iid` for merge requests/issues, `id` for snippets) of an awardable. |
+| `award_id` | integer | yes | ID of an award emoji. |
-```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/344
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/344
```
-## Award Emoji on Notes
+## Award Emoji on Comments
-The endpoints documented above are available for Notes as well. Notes
-are a sub-resource of Issues, Merge Requests, or Snippets. The examples below
-describe working with Award Emoji on notes for an Issue, but can be
-easily adapted for notes on a Merge Request.
+Comments (also known as notes) are a sub-resource of issues, merge requests, and snippets.
-### List a note's award emoji
+NOTE: **Note:**
+The examples below describe working with award emoji on comments for an issue, but can be
+easily adapted for comments on a merge request or on a snippet. Therefore, you have to replace
+`issue_iid` either with `merge_request_iid` or with the `snippet_id`.
-```
+### List a comment's award emoji
+
+Get all award emoji for a comment (note).
+
+```text
GET /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `issue_iid` | integer | yes | The internal ID of an issue |
-| `note_id` | integer | yes | The ID of a note |
+| Attribute | Type | Required | Description |
+|:------------|:---------------|:---------|:-----------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issue_iid` | integer | yes | Internal ID of an issue. |
+| `note_id` | integer | yes | ID of a comment (note). |
+Example request:
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji
```
-Example Response:
+Example response:
```json
[
@@ -227,26 +245,30 @@ Example Response:
]
```
-### Get single note's award emoji
+### Get an award emoji for a comment
-```
+Get a single award emoji for a comment (note).
+
+```text
GET /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji/:award_id
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `issue_iid` | integer | yes | The internal ID of an issue |
-| `note_id` | integer | yes | The ID of a note |
-| `award_id` | integer | yes | The ID of the award emoji |
+| Attribute | Type | Required | Description |
+|:------------|:---------------|:---------|:-----------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issue_iid` | integer | yes | Internal ID of an issue. |
+| `note_id` | integer | yes | ID of a comment (note). |
+| `award_id` | integer | yes | ID of the award emoji. |
+
+Example request:
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji/2
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji/2
```
-Example Response:
+Example response:
```json
{
@@ -267,26 +289,30 @@ Example Response:
}
```
-### Award a new emoji on a note
+### Award a new emoji on a comment
-```
+Create an award emoji on the specified comment (note).
+
+```text
POST /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `issue_iid` | integer | yes | The internal ID of an issue |
-| `note_id` | integer | yes | The ID of a note |
-| `name` | string | yes | The name of the emoji, without colons |
+| Attribute | Type | Required | Description |
+|:------------|:---------------|:---------|:-----------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issue_iid` | integer | yes | Internal ID of an issue. |
+| `note_id` | integer | yes | ID of a comment (note). |
+| `name` | string | yes | Name of the emoji without colons. |
-```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji?name=rocket
+Example request:
+
+```sh
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji?name=rocket
```
-Example Response:
+Example response:
```json
{
@@ -307,26 +333,28 @@ Example Response:
}
```
-### Delete an award emoji
+### Delete an award emoji from a comment
-Sometimes its just not meant to be, and you'll have to remove your award. Only available to
-admins or the author of the award.
+Sometimes it's just not meant to be and you'll have to remove the award.
-```
+NOTE: **Note:**
+Only available to administrators or the author of the award.
+
+```text
DELETE /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji/:award_id
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `issue_iid` | integer | yes | The internal ID of an issue |
-| `note_id` | integer | yes | The ID of a note |
-| `award_id` | integer | yes | The ID of an award_emoji |
+| Attribute | Type | Required | Description |
+|:------------|:---------------|:---------|:-----------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `issue_iid` | integer | yes | Internal ID of an issue. |
+| `note_id` | integer | yes | ID of a comment (note). |
+| `award_id` | integer | yes | ID of an award_emoji. |
-```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/345
-```
+Example request:
-[ce-4575]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4575
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/345
+```
diff --git a/doc/api/boards.md b/doc/api/boards.md
index 5f006f4f012..28c73db6b98 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -18,7 +18,7 @@ GET /projects/:id/boards
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards
```
Example response:
@@ -37,7 +37,7 @@ Example response:
"web_url": "http://example.com/diaspora/diaspora-project-site"
},
"milestone": {
- "id": 12
+ "id": 12,
"title": "10.0"
},
"lists" : [
@@ -87,7 +87,7 @@ GET /projects/:id/boards/:board_id
| `board_id` | integer | yes | The ID of a board |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1
```
Example response:
@@ -95,7 +95,7 @@ Example response:
```json
{
"id": 1,
- "name:": "project issue board",
+ "name": "project issue board",
"project": {
"id": 5,
"name": "Diaspora Project Site",
@@ -106,7 +106,7 @@ Example response:
"web_url": "http://example.com/diaspora/diaspora-project-site"
},
"milestone": {
- "id": 12
+ "id": 12,
"title": "10.0"
},
"lists" : [
@@ -156,7 +156,7 @@ GET /projects/:id/boards/:board_id/lists
| `board_id` | integer | yes | The ID of a board |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1/lists
```
Example response:
@@ -208,7 +208,7 @@ GET /projects/:id/boards/:board_id/lists/:list_id
| `list_id`| integer | yes | The ID of a board's list |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1
```
Example response:
@@ -240,7 +240,7 @@ POST /projects/:id/boards/:board_id/lists
| `label_id` | integer | yes | The ID of a label |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists?label_id=5
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1/lists?label_id=5
```
Example response:
@@ -273,7 +273,7 @@ PUT /projects/:id/boards/:board_id/lists/:list_id
| `position` | integer | yes | The position of the list |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1?position=2
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1?position=2
```
Example response:
@@ -305,5 +305,5 @@ DELETE /projects/:id/boards/:board_id/lists/:list_id
| `list_id` | integer | yes | The ID of a board's list |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1
```
diff --git a/doc/api/branches.md b/doc/api/branches.md
index 4abf0639eb0..31c8add300d 100644
--- a/doc/api/branches.md
+++ b/doc/api/branches.md
@@ -1,22 +1,32 @@
# Branches API
+This API operates on [repository branches](../user/project/repository/branches/index.md).
+
+TIP: **Tip:**
+See also [Protected branches API](protected_branches.md).
+
## List repository branches
Get a list of repository branches from a project, sorted by name alphabetically.
-This endpoint can be accessed without authentication if the repository is
-publicly accessible.
-```
+NOTE: **Note:**
+This endpoint can be accessed without authentication if the repository is publicly accessible.
+
+```text
GET /projects/:id/repository/branches
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `search` | string | no | Return list of branches matching the search criteria. |
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:---------------|:---------|:------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user.|
+| `search` | string | no | Return list of branches containing the search string. You can use `^term` and `term$` to find branches that begin and end with `term` respectively.|
+
+Example request:
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/branches
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/repository/branches
```
Example response:
@@ -53,20 +63,26 @@ Example response:
## Get single repository branch
-Get a single project repository branch. This endpoint can be accessed without
-authentication if the repository is publicly accessible.
+Get a single project repository branch.
-```
+NOTE: **Note:**
+This endpoint can be accessed without authentication if the repository is publicly accessible.
+
+```text
GET /projects/:id/repository/branches/:branch
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `branch` | string | yes | The name of the branch |
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:---------------|:---------|:-------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `branch` | string | yes | Name of the branch. |
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/branches/master
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/repository/branches/master
```
Example response:
@@ -100,120 +116,34 @@ Example response:
## Protect repository branch
->**Note:** This API endpoint is deprecated in favor of `POST /projects/:id/protected_branches`.
-
-Protects a single project repository branch. This is an idempotent function,
-protecting an already protected repository branch still returns a `200 OK`
-status code.
-
-```
-PUT /projects/:id/repository/branches/:branch/protect
-```
-
-```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/branches/master/protect?developers_can_push=true&developers_can_merge=true
-```
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `branch` | string | yes | The name of the branch |
-| `developers_can_push` | boolean | no | Flag if developers can push to the branch |
-| `developers_can_merge` | boolean | no | Flag if developers can merge to the branch |
-
-Example response:
-
-```json
-{
- "commit": {
- "author_email": "john@example.com",
- "author_name": "John Smith",
- "authored_date": "2012-06-27T05:51:39-07:00",
- "committed_date": "2012-06-28T03:44:20-07:00",
- "committer_email": "john@example.com",
- "committer_name": "John Smith",
- "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
- "short_id": "7b5c3cc",
- "title": "add projects API",
- "message": "add projects API",
- "parent_ids": [
- "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
- ]
- },
- "name": "master",
- "merged": false,
- "protected": true,
- "default": true,
- "developers_can_push": true,
- "developers_can_merge": true,
- "can_push": true
-}
-```
+See [`POST /projects/:id/protected_branches`](protected_branches.md#protect-repository-branches) for
+information on protecting repository branches.
## Unprotect repository branch
->**Note:** This API endpoint is deprecated in favor of `DELETE /projects/:id/protected_branches/:name`
+See [`DELETE /projects/:id/protected_branches/:name`](protected_branches.md#unprotect-repository-branches)
+for information on unprotecting repository branches.
-Unprotects a single project repository branch. This is an idempotent function,
-unprotecting an already unprotected repository branch still returns a `200 OK`
-status code.
-
-```
-PUT /projects/:id/repository/branches/:branch/unprotect
-```
-
-```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/branches/master/unprotect
-```
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `branch` | string | yes | The name of the branch |
+## Create repository branch
-Example response:
+Create a new branch in the repository.
-```json
-{
- "commit": {
- "author_email": "john@example.com",
- "author_name": "John Smith",
- "authored_date": "2012-06-27T05:51:39-07:00",
- "committed_date": "2012-06-28T03:44:20-07:00",
- "committer_email": "john@example.com",
- "committer_name": "John Smith",
- "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
- "short_id": "7b5c3cc",
- "title": "add projects API",
- "message": "add projects API",
- "parent_ids": [
- "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
- ]
- },
- "name": "master",
- "merged": false,
- "protected": false,
- "default": true,
- "developers_can_push": false,
- "developers_can_merge": false,
- "can_push": true
-}
+```text
+POST /projects/:id/repository/branches
```
-## Create repository branch
+Parameters:
-```
-POST /projects/:id/repository/branches
-```
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:-------------------------------------------------------------------------------------------------------------|
+| `id` | integer | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `branch` | string | yes | Name of the branch. |
+| `ref` | string | yes | Branch name or commit SHA to create branch from. |
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `branch` | string | yes | The name of the branch |
-| `ref` | string | yes | The branch name or commit SHA to create branch from |
+Example request:
-```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/branches?branch=newbranch&ref=master"
+```sh
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/repository/branches?branch=newbranch&ref=master
```
Example response:
@@ -247,36 +177,47 @@ Example response:
## Delete repository branch
-```
+Delete a branch from the repository.
+
+NOTE: **Note:**
+In the case of an error, an explanation message is provided.
+
+```text
DELETE /projects/:id/repository/branches/:branch
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `branch` | string | yes | The name of the branch |
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:---------------|:---------|:-------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `branch` | string | yes | Name of the branch. |
-In case of an error, an explaining message is provided.
+Example request:
-```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/branches/newbranch"
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/repository/branches/newbranch
```
## Delete merged branches
Will delete all branches that are merged into the project's default branch.
-Protected branches will not be deleted as part of this operation.
+NOTE: **Note:**
+[Protected branches](../user/project/protected_branches.md) will not be deleted as part of this operation.
-```
+```text
DELETE /projects/:id/repository/merged_branches
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:---------------|:---------|:-------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+Example request:
-```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/merged_branches"
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/repository/merged_branches
```
diff --git a/doc/api/broadcast_messages.md b/doc/api/broadcast_messages.md
index a8a248a17f4..357d9916ade 100644
--- a/doc/api/broadcast_messages.md
+++ b/doc/api/broadcast_messages.md
@@ -1,19 +1,26 @@
# Broadcast Messages API
-> **Note:** This feature was introduced in GitLab 8.12.
+> Introduced in GitLab 8.12.
-The broadcast message API is only accessible to administrators. All requests by
-guests will respond with `401 Unauthorized`, and all requests by normal users
-will respond with `403 Forbidden`.
+Broadcast messages API operates on [broadcast messages](../user/admin_area/broadcast_messages.md).
+
+The broadcast message API is only accessible to administrators. All requests by:
+
+- Guests will result in `401 Unauthorized`.
+- Regular users will result in `403 Forbidden`.
## Get all broadcast messages
-```
+List all broadcast messages.
+
+```text
GET /broadcast_messages
```
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/broadcast_messages
```
Example response:
@@ -34,16 +41,22 @@ Example response:
## Get a specific broadcast message
-```
+Get a specific broadcast message.
+
+```text
GET /broadcast_messages/:id
```
-| Attribute | Type | Required | Description |
-| ----------- | -------- | -------- | ------------------------- |
-| `id` | integer | yes | Broadcast message ID |
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:-------------------------------------|
+| `id` | integer | yes | ID of broadcast message to retrieve. |
+
+Example request:
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages/1
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/broadcast_messages/1
```
Example response:
@@ -62,20 +75,26 @@ Example response:
## Create a broadcast message
-```
+Create a new broadcast message.
+
+```text
POST /broadcast_messages
```
-| Attribute | Type | Required | Description |
-| ----------- | -------- | -------- | ---------------------------------------------------- |
-| `message` | string | yes | Message to display |
-| `starts_at` | datetime | no | Starting time (defaults to current time) |
-| `ends_at` | datetime | no | Ending time (defaults to one hour from current time) |
-| `color` | string | no | Background color hex code |
-| `font` | string | no | Foreground color hex code |
+Parameters:
-```bash
-curl --data "message=Deploy in progress&color=#cecece" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages
+| Attribute | Type | Required | Description |
+|:------------|:---------|:---------|:------------------------------------------------------|
+| `message` | string | yes | Message to display. |
+| `starts_at` | datetime | no | Starting time (defaults to current time). |
+| `ends_at` | datetime | no | Ending time (defaults to one hour from current time). |
+| `color` | string | no | Background color hex code. |
+| `font` | string | no | Foreground color hex code. |
+
+Example request:
+
+```sh
+curl --data "message=Deploy in progress&color=#cecece" --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/broadcast_messages
```
Example response:
@@ -94,21 +113,27 @@ Example response:
## Update a broadcast message
-```
+Update an existing broadcast message.
+
+```text
PUT /broadcast_messages/:id
```
-| Attribute | Type | Required | Description |
-| ----------- | -------- | -------- | ------------------------- |
-| `id` | integer | yes | Broadcast message ID |
-| `message` | string | no | Message to display |
-| `starts_at` | datetime | no | Starting time |
-| `ends_at` | datetime | no | Ending time |
-| `color` | string | no | Background color hex code |
-| `font` | string | no | Foreground color hex code |
-
-```bash
-curl --request PUT --data "message=Update message&color=#000" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages/1
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:------------|:---------|:---------|:-----------------------------------|
+| `id` | integer | yes | ID of broadcast message to update. |
+| `message` | string | no | Message to display. |
+| `starts_at` | datetime | no | Starting time. |
+| `ends_at` | datetime | no | Ending time. |
+| `color` | string | no | Background color hex code. |
+| `font` | string | no | Foreground color hex code. |
+
+Example request:
+
+```sh
+curl --request PUT --data "message=Update message&color=#000" --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/broadcast_messages/1
```
Example response:
@@ -127,14 +152,20 @@ Example response:
## Delete a broadcast message
-```
+Delete a broadcast message.
+
+```sh
DELETE /broadcast_messages/:id
```
-| Attribute | Type | Required | Description |
-| ----------- | -------- | -------- | ------------------------- |
-| `id` | integer | yes | Broadcast message ID |
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:-----------------------------------|
+| `id` | integer | yes | ID of broadcast message to delete. |
+
+Example request:
-```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages/1
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/broadcast_messages/1
```
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 6c16216429d..442178aedff 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -18,9 +18,8 @@ GET /projects/:id/repository/commits
| `all` | boolean | no | Retrieve every commit from the repository |
| `with_stats` | boolean | no | Stats about each commit will be added to the response |
-
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/commits"
```
Example response:
@@ -80,7 +79,7 @@ POST /projects/:id/repository/commits
| `author_email` | string | no | Specify the commit author's email address |
| `author_name` | string | no | Specify the commit author's name |
| `stats` | boolean | no | Include commit stats. Default is true |
-
+| `force` | boolean | no | When `true` overwrites the target branch with a new commit based on the `start_branch` |
| `actions[]` Attribute | Type | Required | Description |
| --------------------- | ---- | -------- | ----------- |
@@ -127,7 +126,7 @@ PAYLOAD=$(cat << 'JSON'
}
JSON
)
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data "$PAYLOAD" https://gitlab.example.com/api/v4/projects/1/repository/commits
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data "$PAYLOAD" https://gitlab.example.com/api/v4/projects/1/repository/commits
```
Example response:
@@ -173,7 +172,7 @@ Parameters:
| `stats` | boolean | no | Include commit stats. Default is true |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master
```
Example response:
@@ -229,7 +228,7 @@ Parameters:
| `type` | string | no | The scope of commits. Possible values `branch`, `tag`, `all`. Default is `all`. |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/5937ac0a7beb003549fc5fd26fc247adbce4a52e/refs?type=all"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/commits/5937ac0a7beb003549fc5fd26fc247adbce4a52e/refs?type=all"
```
Example response:
@@ -263,7 +262,7 @@ Parameters:
| `branch` | string | yes | The name of the branch |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/cherry_pick"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/cherry_pick"
```
Example response:
@@ -307,7 +306,7 @@ Parameters:
| `branch` | string | yes | Target branch name |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/a738f717824ff53aebad8b090c1b79a14f2bd9e8/revert"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/a738f717824ff53aebad8b090c1b79a14f2bd9e8/revert"
```
Example response:
@@ -345,7 +344,7 @@ Parameters:
| `sha` | string | yes | The commit hash or name of a repository branch or tag |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/diff"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/diff"
```
Example response:
@@ -381,7 +380,7 @@ Parameters:
| `sha` | string | yes | The commit hash or name of a repository branch or tag |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/comments"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/comments"
```
Example response:
@@ -434,7 +433,7 @@ POST /projects/:id/repository/commits/:sha/comments
| `line_type` | string | no | The line type. Takes `new` or `old` as arguments |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "note=Nice picture man\!" --form "path=dudeism.md" --form "line=11" --form "line_type=new" https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/comments
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "note=Nice picture man\!" --form "path=dudeism.md" --form "line=11" --form "line_type=new" https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/comments
```
Example response:
@@ -480,7 +479,7 @@ GET /projects/:id/repository/commits/:sha/statuses
| `all` | boolean | no | Return all statuses, not only the latest ones
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/statuses
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/statuses
```
Example response:
@@ -556,7 +555,7 @@ POST /projects/:id/statuses/:sha
| `coverage` | float | no | The total code coverage
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/17/statuses/18f3e63d05582537db6d183d9d557be09e1f90c8?state=success"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/17/statuses/18f3e63d05582537db6d183d9d557be09e1f90c8?state=success"
```
Example response:
@@ -601,9 +600,8 @@ GET /projects/:id/repository/commits/:sha/merge_requests
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
| `sha` | string | yes | The commit SHA
-
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/af5b13261899fb2c0db30abdd0af8b07cb44fdc5/merge_requests"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/commits/af5b13261899fb2c0db30abdd0af8b07cb44fdc5/merge_requests"
```
Example response:
@@ -656,6 +654,46 @@ Example response:
]
```
+## Get GPG signature of a commit
+
+Get the [GPG signature from a commit](../user/project/repository/gpg_signed_commits/index.md),
+if it is signed. For unsigned commits, it results in a 404 response.
+
+```
+GET /projects/:id/repository/commits/:sha/signature
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+| `sha` | string | yes | The commit hash or name of a repository branch or tag |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/repository/commits/da738facbc19eb2fc2cef57c49be0e6038570352/signature"
+```
+
+Example response if commit is signed:
+
+```json
+{
+ "gpg_key_id": 1,
+ "gpg_key_primary_keyid": "8254AAB3FBD54AC9",
+ "gpg_key_user_name": "John Doe",
+ "gpg_key_user_email": "johndoe@example.com",
+ "verification_status": "verified",
+ "gpg_key_subkey_id": null
+}
+```
+
+Example response if commit is unsigned:
+```json
+{
+ "message": "404 GPG Signature Not Found"
+}
+```
+
[ce-6096]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6096 "Multi-file commit"
[ce-8047]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8047
[ce-15026]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15026
diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md
new file mode 100644
index 00000000000..1f17af1f1e9
--- /dev/null
+++ b/doc/api/container_registry.md
@@ -0,0 +1,201 @@
+# Container Registry API
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/55978) in GitLab 11.8.
+
+This is the API docs of the [GitLab Container Registry](../user/project/container_registry.md).
+
+## List registry repositories
+
+Get a list of registry repositories in a project.
+
+```
+GET /projects/:id/registry/repositories
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "",
+ "path": "group/project",
+ "location": "gitlab.example.com:5000/group/project",
+ "created_at": "2019-01-10T13:38:57.391Z"
+ },
+ {
+ "id": 2,
+ "name": "releases",
+ "path": "group/project/releases",
+ "location": "gitlab.example.com:5000/group/project/releases",
+ "created_at": "2019-01-10T13:39:08.229Z"
+ }
+]
+```
+
+## Delete registry repository
+
+Delete a repository in registry.
+
+This operation is executed asynchronously and might take some time to get executed.
+
+```
+DELETE /projects/:id/registry/repositories/:repository_id
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `repository_id` | integer | yes | The ID of registry repository. |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2"
+```
+
+## List repository tags
+
+Get a list of tags for given registry repository.
+
+```
+GET /projects/:id/registry/repositories/:repository_id/tags
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `repository_id` | integer | yes | The ID of registry repository. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
+```
+
+Example response:
+
+```json
+[
+ {
+ "name": "A",
+ "path": "group/project:A",
+ "location": "gitlab.example.com:5000/group/project:A"
+ },
+ {
+ "name": "latest",
+ "path": "group/project:latest",
+ "location": "gitlab.example.com:5000/group/project:latest"
+ }
+]
+```
+
+## Get details of a repository tag
+
+Get details of a registry repository tag.
+
+```
+GET /projects/:id/registry/repositories/:repository_id/tags/:tag_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `repository_id` | integer | yes | The ID of registry repository. |
+| `tag_name` | string | yes | The name of tag. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0"
+```
+
+Example response:
+
+```json
+{
+ "name": "v10.0.0",
+ "path": "group/project:latest",
+ "location": "gitlab.example.com:5000/group/project:latest",
+ "revision": "e9ed9d87c881d8c2fd3a31b41904d01ba0b836e7fd15240d774d811a1c248181",
+ "short_revision": "e9ed9d87c",
+ "digest": "sha256:c3490dcf10ffb6530c1303522a1405dfaf7daecd8f38d3e6a1ba19ea1f8a1751",
+ "created_at": "2019-01-06T16:49:51.272+00:00",
+ "total_size": 350224384
+}
+```
+
+## Delete a repository tag
+
+Delete a registry repository tag.
+
+```
+DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `repository_id` | integer | yes | The ID of registry repository. |
+| `tag_name` | string | yes | The name of tag. |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0"
+```
+
+## Delete repository tags in bulk
+
+Delete repository tags in bulk based on given criteria.
+
+```
+DELETE /projects/:id/registry/repositories/:repository_id/tags
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `repository_id` | integer | yes | The ID of registry repository. |
+| `name_regex` | string | yes | The regex of the name to delete. To delete all tags specify `.*`. |
+| `keep_n` | integer | no | The amount of latest tags of given name to keep. |
+| `older_than` | string | no | Tags to delete that are older than the given time, written in human readable form `1h`, `1d`, `1month`. |
+
+This API call performs the following operations:
+
+1. It orders all tags by creation date. The creation date is the time of the
+ manifest creation, not the time of tag push.
+1. It removes only the tags matching the given `name_regex`.
+1. It never removes the tag named `latest`.
+1. It keeps N latest matching tags (if `keep_n` is specified).
+1. It only removes tags that are older than X amount of time (if `older_than` is specified).
+1. It schedules the asynchronous job to be executed in the background.
+
+These operations are executed asynchronously and it might
+take time to get executed. You can run this at most
+once an hour for a given container repository.
+
+NOTE: **Note:**
+Due to a [Docker Distribution deficiency](https://gitlab.com/gitlab-org/gitlab-ce/issues/21405),
+it doesn't remove tags whose manifest is shared by multiple tags.
+
+Examples:
+
+1. Remove tag names that are matching the regex (Git SHA), keep always at least 5,
+ and remove ones that are older than 2 days:
+
+ ```bash
+ curl --request DELETE --data 'name_regex=[0-9a-z]{40}' --data 'keep_n=5' --data 'older_than=2d' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
+ ```
+
+2. Remove all tags, but keep always the latest 5:
+
+ ```bash
+ curl --request DELETE --data 'name_regex=.*' --data 'keep_n=5' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
+ ```
+
+3. Remove all tags that are older than 1 month:
+
+ ```bash
+ curl --request DELETE --data 'name_regex=.*' --data 'older_than=1month' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
+ ```
diff --git a/doc/api/custom_attributes.md b/doc/api/custom_attributes.md
index 91d1b0e1520..d270b804ad5 100644
--- a/doc/api/custom_attributes.md
+++ b/doc/api/custom_attributes.md
@@ -20,7 +20,7 @@ GET /projects/:id/custom_attributes
| `id` | integer | yes | The ID of a resource |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/42/custom_attributes
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/42/custom_attributes
```
Example response:
@@ -54,7 +54,7 @@ GET /projects/:id/custom_attributes/:key
| `key` | string | yes | The key of the custom attribute |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/42/custom_attributes/location
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/42/custom_attributes/location
```
Example response:
@@ -84,7 +84,7 @@ PUT /projects/:id/custom_attributes/:key
| `value` | string | yes | The value of the custom attribute |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "value=Greenland" https://gitlab.example.com/api/v4/users/42/custom_attributes/location
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "value=Greenland" https://gitlab.example.com/api/v4/users/42/custom_attributes/location
```
Example response:
@@ -112,5 +112,5 @@ DELETE /projects/:id/custom_attributes/:key
| `key` | string | yes | The key of the custom attribute |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/42/custom_attributes/location
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/42/custom_attributes/location
```
diff --git a/doc/api/deploy_key_multiple_projects.md b/doc/api/deploy_key_multiple_projects.md
index 127f9a196de..0c9e3e66cae 100644
--- a/doc/api/deploy_key_multiple_projects.md
+++ b/doc/api/deploy_key_multiple_projects.md
@@ -7,23 +7,23 @@ First, find the ID of the projects you're interested in, by either listing all
projects:
```
-curl --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v4/projects
+curl --header 'PRIVATE-TOKEN: <your_access_token>' https://gitlab.example.com/api/v4/projects
```
Or finding the ID of a group and then listing all projects in that group:
```
-curl --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v4/groups
+curl --header 'PRIVATE-TOKEN: <your_access_token>' https://gitlab.example.com/api/v4/groups
# For group 1234:
-curl --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v4/groups/1234
+curl --header 'PRIVATE-TOKEN: <your_access_token>' https://gitlab.example.com/api/v4/groups/1234
```
With those IDs, add the same deploy key to all:
```
for project_id in 321 456 987; do
- curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" \
+ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
--data '{"title": "my key", "key": "ssh-rsa AAAA..."}' https://gitlab.example.com/api/v4/projects/${project_id}/deploy_keys
done
```
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index 698fa22a438..1d7523fcc3d 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -9,7 +9,7 @@ GET /deploy_keys
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/deploy_keys"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/deploy_keys"
```
Example response:
@@ -44,7 +44,7 @@ GET /projects/:id/deploy_keys
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/deploy_keys"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/deploy_keys"
```
Example response:
@@ -84,7 +84,7 @@ Parameters:
| `key_id` | integer | yes | The ID of the deploy key |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11"
```
Example response:
@@ -118,7 +118,7 @@ POST /projects/:id/deploy_keys
| `can_push` | boolean | no | Can deploy key push to the project's repository |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data '{"title": "My deploy key", "key": "ssh-rsa AAAA...", "can_push": "true"}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"title": "My deploy key", "key": "ssh-rsa AAAA...", "can_push": "true"}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/"
```
Example response:
@@ -148,7 +148,7 @@ PUT /projects/:id/deploy_keys/:key_id
| `can_push` | boolean | no | Can deploy key push to the project's repository |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data '{"title": "New deploy key", "can_push": true}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"title": "New deploy key", "can_push": true}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11"
```
Example response:
@@ -177,7 +177,7 @@ DELETE /projects/:id/deploy_keys/:key_id
| `key_id` | integer | yes | The ID of the deploy key |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/deploy_keys/13"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/deploy_keys/13"
```
## Enable a deploy key
@@ -185,7 +185,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gi
Enables a deploy key for a project so this can be used. Returns the enabled key, with a status code 201 when successful.
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/deploy_keys/13/enable
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/deploy_keys/13/enable
```
| Attribute | Type | Required | Description |
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index 1963b0a21de..0a67f134d54 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -15,7 +15,7 @@ GET /projects/:id/deployments
| `sort` | string | no | Return deployments sorted in `asc` or `desc` order. Default is `asc` |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/deployments"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments"
```
Example of response
@@ -155,7 +155,7 @@ GET /projects/:id/deployments/:deployment_id
| `deployment_id` | integer | yes | The ID of the deployment |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/deployments/1"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/1"
```
Example of response
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index 3538a577c8e..7d68d0ae744 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -97,7 +97,7 @@ GET /projects/:id/issues/:issue_iid/discussions
```
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions
```
### Get single issue discussion
@@ -117,7 +117,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a discussion |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7
```
### Create new issue discussion
@@ -139,7 +139,7 @@ Parameters:
| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions?body=comment
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions?body=comment
```
### Add note to existing issue discussion
@@ -162,7 +162,7 @@ Parameters:
| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
```
### Modify existing issue discussion note
@@ -184,7 +184,7 @@ Parameters:
| `body` | string | yes | The content of a discussion |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment
```
### Delete an issue discussion note
@@ -205,7 +205,7 @@ Parameters:
| `note_id` | integer | yes | The ID of a discussion note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/636
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/636
```
## Snippets
@@ -303,7 +303,7 @@ GET /projects/:id/snippets/:snippet_id/discussions
```
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions
```
### Get single snippet discussion
@@ -323,7 +323,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a discussion |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7
```
### Create new snippet discussion
@@ -345,7 +345,7 @@ Parameters:
| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions?body=comment
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions?body=comment
```
### Add note to existing snippet discussion
@@ -368,7 +368,7 @@ Parameters:
| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
```
### Modify existing snippet discussion note
@@ -390,7 +390,7 @@ Parameters:
| `body` | string | yes | The content of a discussion |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment
```
### Delete an snippet discussion note
@@ -411,7 +411,7 @@ Parameters:
| `note_id` | integer | yes | The ID of a discussion note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/636
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/636
```
## Merge requests
@@ -562,7 +562,7 @@ Diff comments contain also position:
```
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions
```
### Get single merge request discussion
@@ -582,7 +582,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a discussion |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7
```
### Create new merge request discussion
@@ -617,7 +617,7 @@ Parameters:
| `position[y]` | integer | no | Y coordinate (for 'image' diff notes) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions?body=comment
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions?body=comment
```
### Resolve a merge request discussion
@@ -638,10 +638,9 @@ Parameters:
| `resolved` | boolean | yes | Resolve/unresolve the discussion |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7?resolved=true
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7?resolved=true
```
-
### Add note to existing merge request discussion
Adds a new note to the discussion.
@@ -662,7 +661,7 @@ Parameters:
| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
```
### Modify an existing merge request discussion note
@@ -685,13 +684,13 @@ Parameters:
| `resolved` | boolean | no | Resolve/unresolve the note (exactly one of `body` or `resolved` must be set |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment
```
Resolving a note:
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?resolved=true
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?resolved=true
```
### Delete a merge request discussion note
@@ -712,7 +711,7 @@ Parameters:
| `note_id` | integer | yes | The ID of a discussion note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/636
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/636
```
## Commits
@@ -855,7 +854,7 @@ Diff comments contain also position:
```
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions
```
### Get single commit discussion
@@ -875,7 +874,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a discussion |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7
```
### Create new commit discussion
@@ -910,7 +909,7 @@ Parameters:
| `position[y]` | integer | no | Y coordinate (for 'image' diff notes) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions?body=comment
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions?body=comment
```
### Add note to existing commit discussion
@@ -933,7 +932,7 @@ Parameters:
| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
```
### Modify an existing commit discussion note
@@ -955,13 +954,13 @@ Parameters:
| `body` | string | no | The content of a note |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment
```
Resolving a note:
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?resolved=true
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?resolved=true
```
### Delete a commit discussion note
@@ -982,5 +981,5 @@ Parameters:
| `note_id` | integer | yes | The ID of a discussion note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/636
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/636
```
diff --git a/doc/api/environments.md b/doc/api/environments.md
index 29da4590a59..4a38dd73747 100644
--- a/doc/api/environments.md
+++ b/doc/api/environments.md
@@ -13,7 +13,7 @@ GET /projects/:id/environments
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/environments
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/environments
```
Example response:
@@ -46,7 +46,7 @@ POST /projects/:id/environments
| `external_url` | string | no | Place to link to for this environment |
```bash
-curl --data "name=deploy&external_url=https://deploy.example.gitlab.com" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/environments"
+curl --data "name=deploy&external_url=https://deploy.example.gitlab.com" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments"
```
Example response:
@@ -78,7 +78,7 @@ PUT /projects/:id/environments/:environments_id
| `external_url` | string | no | The new external_url |
```bash
-curl --request PUT --data "name=staging&external_url=https://staging.example.gitlab.com" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/environments/1"
+curl --request PUT --data "name=staging&external_url=https://staging.example.gitlab.com" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments/1"
```
Example response:
@@ -106,7 +106,7 @@ DELETE /projects/:id/environments/:environment_id
| `environment_id` | integer | yes | The ID of the environment |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/environments/1"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments/1"
```
## Stop an environment
@@ -123,7 +123,7 @@ POST /projects/:id/environments/:environment_id/stop
| `environment_id` | integer | yes | The ID of the environment |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/environments/1/stop"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments/1/stop"
```
Example response:
diff --git a/doc/api/events.md b/doc/api/events.md
index e1c6b801a77..6dca8e52f69 100644
--- a/doc/api/events.md
+++ b/doc/api/events.md
@@ -71,7 +71,7 @@ Parameters:
Example request:
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01
```
Example response:
@@ -143,7 +143,7 @@ Parameters:
| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc` |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/:id/events
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/:id/events
```
Example response:
@@ -276,7 +276,7 @@ Parameters:
Example request:
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:project_id/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:project_id/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01
```
Example response:
diff --git a/doc/api/features.md b/doc/api/features.md
index 6ee1c36ef5b..6ecd4ec14b9 100644
--- a/doc/api/features.md
+++ b/doc/api/features.md
@@ -14,7 +14,7 @@ GET /features
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/features
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/features
```
Example response:
@@ -60,12 +60,14 @@ POST /features/:name
| `value` | integer/string | yes | `true` or `false` to enable/disable, or an integer for percentage of time |
| `feature_group` | string | no | A Feature group name |
| `user` | string | no | A GitLab username |
+| `group` | string | no | A GitLab group's path, for example 'gitlab-org' |
+| `project` | string | no | A projects path, for example 'gitlab-org/gitlab-ce' |
-Note that you can enable or disable a feature for both a `feature_group` and a
-`user` with a single API call.
+Note that you can enable or disable a feature for a `feature_group`, a `user`,
+a `group`, and a `project` in a single API call.
```bash
-curl --data "value=30" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/features/new_library
+curl --data "value=30" --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/features/new_library
```
Example response:
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index 71922318227..ec48bf4940b 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -24,7 +24,7 @@ feature flag. You can enable the feature using the [features api][features-api]
For example:
```shell
-curl --data "value=100" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/features/graphql
+curl --data "value=100" --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/features/graphql
```
## Available queries
diff --git a/doc/api/group_badges.md b/doc/api/group_badges.md
index f2353542a5c..f88689d80c6 100644
--- a/doc/api/group_badges.md
+++ b/doc/api/group_badges.md
@@ -28,7 +28,7 @@ GET /groups/:id/badges
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/badges
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/badges
```
Example response:
@@ -68,7 +68,7 @@ GET /groups/:id/badges/:badge_id
| `badge_id` | integer | yes | The badge ID |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id
```
Example response:
@@ -99,7 +99,7 @@ POST /groups/:id/badges
| `image_url` | string | yes | URL of the badge image |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "link_url=https://gitlab.com/gitlab-org/gitlab-ce/commits/master&image_url=https://shields.io/my/badge1&position=0" https://gitlab.example.com/api/v4/groups/:id/badges
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "link_url=https://gitlab.com/gitlab-org/gitlab-ce/commits/master&image_url=https://shields.io/my/badge1&position=0" https://gitlab.example.com/api/v4/groups/:id/badges
```
Example response:
@@ -131,7 +131,7 @@ PUT /groups/:id/badges/:badge_id
| `image_url` | string | no | URL of the badge image |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id
```
Example response:
@@ -161,7 +161,7 @@ DELETE /groups/:id/badges/:badge_id
| `badge_id` | integer | yes | The badge ID |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id
```
## Preview a badge from a group
@@ -179,7 +179,7 @@ GET /groups/:id/badges/render
| `image_url` | string | yes | URL of the badge image |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/badges/render?link_url=http%3A%2F%2Fexample.com%2Fci_status.svg%3Fproject%3D%25%7Bproject_path%7D%26ref%3D%25%7Bdefault_branch%7D&image_url=https%3A%2F%2Fshields.io%2Fmy%2Fbadge
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/badges/render?link_url=http%3A%2F%2Fexample.com%2Fci_status.svg%3Fproject%3D%25%7Bproject_path%7D%26ref%3D%25%7Bdefault_branch%7D&image_url=https%3A%2F%2Fshields.io%2Fmy%2Fbadge
```
Example response:
diff --git a/doc/api/group_boards.md b/doc/api/group_boards.md
index 373904e50c4..9b0ac23b41c 100644
--- a/doc/api/group_boards.md
+++ b/doc/api/group_boards.md
@@ -18,7 +18,7 @@ GET /groups/:id/boards
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/boards
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/boards
```
Example response:
@@ -75,7 +75,7 @@ GET /groups/:id/boards/:board_id
| `board_id` | integer | yes | The ID of a board |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/boards/1
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/boards/1
```
Example response:
@@ -131,7 +131,7 @@ GET /groups/:id/boards/:board_id/lists
| `board_id` | integer | yes | The ID of a board |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/boards/1/lists
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/boards/1/lists
```
Example response:
@@ -183,7 +183,7 @@ GET /groups/:id/boards/:board_id/lists/:list_id
| `list_id` | integer | yes | The ID of a board's list |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/boards/1/lists/1
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/boards/1/lists/1
```
Example response:
@@ -215,7 +215,7 @@ POST /groups/:id/boards/:board_id/lists
| `label_id` | integer | yes | The ID of a label |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/boards/1/lists?label_id=5
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/boards/1/lists?label_id=5
```
Example response:
@@ -248,7 +248,7 @@ PUT /groups/:id/boards/:board_id/lists/:list_id
| `position` | integer | yes | The position of the list |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/group/5/boards/1/lists/1?position=2
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/group/5/boards/1/lists/1?position=2
```
Example response:
@@ -280,5 +280,5 @@ DELETE /groups/:id/boards/:board_id/lists/:list_id
| `list_id` | integer | yes | The ID of a board's list |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/boards/1/lists/1
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/boards/1/lists/1
```
diff --git a/doc/api/group_labels.md b/doc/api/group_labels.md
new file mode 100644
index 00000000000..3d4b099b49e
--- /dev/null
+++ b/doc/api/group_labels.md
@@ -0,0 +1,207 @@
+# Group Labels API
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21368) in GitLab 11.8.
+
+This API supports managing of [group labels](../user/project/labels.md#project-labels-and-group-labels). It allows to list, create, update, and delete group labels. Furthermore, users can subscribe and unsubscribe to and from group labels.
+
+## List group labels
+
+Get all labels for a given group.
+
+```
+GET /groups/:id/labels
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/labels
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 7,
+ "name": "bug",
+ "color": "#FF0000",
+ "text_color" : "#FFFFFF",
+ "description": null,
+ "open_issues_count": 0,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 0,
+ "subscribed": false
+ },
+ {
+ "id": 4,
+ "name": "feature",
+ "color": "#228B22",
+ "text_color" : "#FFFFFF",
+ "description": null,
+ "open_issues_count": 0,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 0,
+ "subscribed": false
+ }
+]
+```
+
+## Create a new group label
+
+Create a new group label for a given group.
+
+```
+POST /groups/:id/labels
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | ------- | -------- | ---------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `name` | string | yes | The name of the label |
+| `color` | string | yes | The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
+| `description` | string | no | The description of the label, |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"name": "Feature Proposal", "color": "#FFA500", "description": "Describes new ideas" }' https://gitlab.example.com/api/v4/groups/5/labels
+```
+
+Example response:
+
+```json
+{
+ "id": 9,
+ "name": "Feature Proposal",
+ "color": "#FFA500",
+ "text_color" : "#FFFFFF",
+ "description": "Describes new ideas",
+ "open_issues_count": 0,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 0,
+ "subscribed": false
+}
+```
+
+## Update a group label
+
+Updates an existing group label. At least one parameter is required, to update the group label.
+
+```
+PUT /groups/:id/labels
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | ------- | -------- | ---------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `name` | string | yes | The name of the label |
+| `new_name` | string | no | The new name of the label |
+| `color` | string | no | The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
+| `description` | string | no | The description of the label. |
+
+```bash
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"name": "Feature Proposal", "new_name": "Feature Idea" }' https://gitlab.example.com/api/v4/groups/5/labels
+```
+
+Example response:
+
+```json
+{
+ "id": 9,
+ "name": "Feature Idea",
+ "color": "#FFA500",
+ "text_color" : "#FFFFFF",
+ "description": "Describes new ideas",
+ "open_issues_count": 0,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 0,
+ "subscribed": false
+}
+```
+
+## Delete a group label
+
+Deletes a group label with a given name.
+
+```
+DELETE /groups/:id/labels
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | --------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `name` | string | yes | The name of the label. |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/labels?name=bug
+```
+
+## Subscribe to a group label
+
+Subscribes the authenticated user to a group label to receive notifications. If
+the user is already subscribed to the label, the status code `304` is returned.
+
+```
+POST /groups/:id/labels/:label_id/subscribe
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | ----------------- | -------- | ------------------------------------ |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `label_id` | integer or string | yes | The ID or title of a group's label. |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/labels/9/subscribe
+```
+
+Example response:
+
+```json
+{
+ "id": 9,
+ "name": "Feature Idea",
+ "color": "#FFA500",
+ "text_color" : "#FFFFFF",
+ "description": "Describes new ideas",
+ "open_issues_count": 0,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 0,
+ "subscribed": true
+}
+```
+
+## Unsubscribe from a group label
+
+Unsubscribes the authenticated user from a group label to not receive
+notifications from it. If the user is not subscribed to the label, the status
+code `304` is returned.
+
+```
+POST /groups/:id/labels/:label_id/unsubscribe
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | ----------------- | -------- | ------------------------------------ |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `label_id` | integer or string | yes | The ID or title of a group's label. |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/labels/9/unsubscribe
+```
+
+Example response:
+
+```json
+{
+ "id": 9,
+ "name": "Feature Idea",
+ "color": "#FFA500",
+ "text_color" : "#FFFFFF",
+ "description": "Describes new ideas",
+ "open_issues_count": 0,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 0,
+ "subscribed": false
+}
+```
diff --git a/doc/api/group_level_variables.md b/doc/api/group_level_variables.md
index 33c6da08018..3551bfa3f8b 100644
--- a/doc/api/group_level_variables.md
+++ b/doc/api/group_level_variables.md
@@ -15,7 +15,7 @@ GET /groups/:id/variables
| `id` | integer/string | yes | The ID of a group or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/1/variables"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables"
```
```json
@@ -45,7 +45,7 @@ GET /groups/:id/variables/:key
| `key` | string | yes | The `key` of a variable |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/1/variables/TEST_VARIABLE_1"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables/TEST_VARIABLE_1"
```
```json
@@ -71,7 +71,7 @@ POST /groups/:id/variables
| `protected` | boolean | no | Whether the variable is protected |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
```
```json
@@ -98,7 +98,7 @@ PUT /groups/:id/variables/:key
| `protected` | boolean | no | Whether the variable is protected |
```
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/1/variables/NEW_VARIABLE" --form "value=updated value"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables/NEW_VARIABLE" --form "value=updated value"
```
```json
@@ -123,7 +123,7 @@ DELETE /groups/:id/variables/:key
| `key` | string | yes | The `key` of a variable |
```
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/1/variables/VARIABLE_1"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables/VARIABLE_1"
```
[ce-34519]: https://gitlab.com/gitlab-org/gitlab-ce/issues/34519
diff --git a/doc/api/group_milestones.md b/doc/api/group_milestones.md
index e396f4411e6..eb974267084 100644
--- a/doc/api/group_milestones.md
+++ b/doc/api/group_milestones.md
@@ -26,7 +26,7 @@ Parameters:
| `search` | string | optional | Return only milestones with a title or description matching the provided string |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/milestones
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/milestones
```
Example Response:
@@ -48,7 +48,6 @@ Example Response:
]
```
-
## Get single milestone
Gets a single group milestone.
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 59444a98086..907b443d355 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -220,7 +220,7 @@ Parameters:
| `with_projects` | boolean | no | Include details from projects that belong to the specified group (defaults to `true`). |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/4
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/4
```
Example response:
@@ -357,12 +357,14 @@ Example response:
{
"group_id": 4,
"group_name": "Twitter",
+ "group_full_path": "twitter",
"group_access_level": 30,
"expires_at": null
},
{
"group_id": 3,
"group_name": "Gitlab Org",
+ "group_full_path": "gitlab-org",
"group_access_level": 10,
"expires_at": "2018-08-14"
}
@@ -375,7 +377,7 @@ Example response:
When adding the parameter `with_projects=false`, projects will not be returned.
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/4?with_projects=false
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/4?with_projects=false
```
Example response:
@@ -452,7 +454,7 @@ PUT /groups/:id
| `file_template_project_id` | integer | no | **(Premium)** The ID of a project to load custom file templates from |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/5?name=Experimental"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5?name=Experimental"
```
diff --git a/doc/api/import.md b/doc/api/import.md
new file mode 100644
index 00000000000..1deb26e8388
--- /dev/null
+++ b/doc/api/import.md
@@ -0,0 +1,31 @@
+# Import API
+
+## Import repository from GitHub
+
+Import your projects from GitHub to GitLab via the API.
+
+```
+POST /import/github
+```
+
+| Attribute | Type | Required | Description |
+|------------|---------|----------|---------------------|
+| `personal_access_token` | string | yes | GitHub personal access token |
+| `repo_id` | integer | yes | GitHub repository ID |
+| `new_name` | string | no | New repo name |
+| `target_namespace` | string | yes | Namespace to import repo into |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "personal_access_token=abc123&repo_id=12345&target_namespace=root" https://gitlab.example.com/api/v4/import/github
+```
+
+Example response:
+
+```json
+{
+ "id": 27,
+ "name": "my-repo",
+ "full_path": "/root/my-repo",
+ "full_name": "Administrator / my-repo"
+}
+```
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 6a99c52234d..cb5789e76b7 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -31,6 +31,8 @@ GET /issues?iids[]=42&iids[]=43
GET /issues?author_id=5
GET /issues?assignee_id=5
GET /issues?my_reaction_emoji=star
+GET /issues?search=foo&in=title
+GET /issues?confidential=true
```
| Attribute | Type | Required | Description |
@@ -46,13 +48,15 @@ GET /issues?my_reaction_emoji=star
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Search issues against their `title` and `description` |
+| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
| `created_after` | datetime | no | Return issues created on or after the given time |
| `created_before` | datetime | no | Return issues created on or before the given time |
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
+| `confidential ` | Boolean | no | Filter confidential or public issues. |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/issues
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/issues
```
Example response:
@@ -106,6 +110,9 @@ Example response:
"created_at" : "2016-01-04T15:31:51.081Z",
"iid" : 6,
"labels" : [],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
"user_notes_count": 1,
"due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/6",
@@ -143,6 +150,7 @@ GET /groups/:id/issues?search=issue+title+or+description
GET /groups/:id/issues?author_id=5
GET /groups/:id/issues?assignee_id=5
GET /groups/:id/issues?my_reaction_emoji=star
+GET /groups/:id/issues?confidential=true
```
| Attribute | Type | Required | Description |
@@ -163,10 +171,10 @@ GET /groups/:id/issues?my_reaction_emoji=star
| `created_before` | datetime | no | Return issues created on or before the given time |
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
-
+| `confidential ` | Boolean | no | Filter confidential or public issues. |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/4/issues
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/4/issues
```
Example response:
@@ -214,6 +222,9 @@ Example response:
"name" : "Dr. Luella Kovacek"
},
"labels" : [],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
"id" : 41,
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z",
@@ -257,6 +268,7 @@ GET /projects/:id/issues?search=issue+title+or+description
GET /projects/:id/issues?author_id=5
GET /projects/:id/issues?assignee_id=5
GET /projects/:id/issues?my_reaction_emoji=star
+GET /projects/:id/issues?confidential=true
```
| Attribute | Type | Required | Description |
@@ -277,9 +289,11 @@ GET /projects/:id/issues?my_reaction_emoji=star
| `created_before` | datetime | no | Return issues created on or before the given time |
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
+| `confidential ` | Boolean | no | Filter confidential or public issues. |
+
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues
```
Example response:
@@ -327,6 +341,9 @@ Example response:
"name" : "Dr. Luella Kovacek"
},
"labels" : [],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
"id" : 41,
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z",
@@ -373,7 +390,7 @@ GET /projects/:id/issues/:issue_iid
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues/41
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues/41
```
Example response:
@@ -421,6 +438,9 @@ Example response:
"name" : "Dr. Luella Kovacek"
},
"labels" : [],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
"id" : 41,
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z",
@@ -476,7 +496,7 @@ POST /projects/:id/issues
| `discussion_to_resolve` | string | no | The ID of a discussion to resolve. This will fill in the issue with a default description and mark the discussion as resolved. Use in combination with `merge_request_to_resolve_discussions_of`. |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues?title=Issues%20with%20auth&labels=bug
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues?title=Issues%20with%20auth&labels=bug
```
Example response:
@@ -494,6 +514,9 @@ Example response:
"labels" : [
"bug"
],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
"author" : {
"name" : "Alexandra Bashirian",
"avatar_url" : null,
@@ -556,9 +579,8 @@ PUT /projects/:id/issues/:issue_iid
| `due_date` | string | no | Date time string in the format YEAR-MONTH-DAY, e.g. `2016-03-11` |
| `discussion_locked` | boolean | no | Flag indicating if the issue's discussion is locked. If the discussion is locked only project members can add or edit comments. |
-
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues/85?state_event=close
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues/85?state_event=close
```
Example response:
@@ -592,6 +614,9 @@ Example response:
"labels" : [
"bug"
],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
"id" : 85,
"assignees" : [],
"assignee" : null,
@@ -635,7 +660,7 @@ DELETE /projects/:id/issues/:issue_iid
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues/85
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues/85
```
## Move an issue
@@ -658,7 +683,7 @@ POST /projects/:id/issues/:issue_iid/move
| `to_project_id` | integer | yes | The ID of the new project |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form to_project_id=5 https://gitlab.example.com/api/v4/projects/4/issues/85/move
+curl --header "PRIVATE-TOKEN: <your_access_token>" --form to_project_id=5 https://gitlab.example.com/api/v4/projects/4/issues/85/move
```
Example response:
@@ -676,6 +701,9 @@ Example response:
"closed_at": null,
"closed_by": null,
"labels": [],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
"milestone": null,
"assignees": [{
"name": "Miss Monserrate Beier",
@@ -740,7 +768,7 @@ POST /projects/:id/issues/:issue_iid/subscribe
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/subscribe
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/subscribe
```
Example response:
@@ -758,6 +786,9 @@ Example response:
"closed_at": null,
"closed_by": null,
"labels": [],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
"milestone": null,
"assignees": [{
"name": "Miss Monserrate Beier",
@@ -804,7 +835,6 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
-
**Note**: The `closed_by` attribute was [introduced in GitLab 10.6][ce-17042]. This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
## Unsubscribe from an issue
@@ -823,7 +853,7 @@ POST /projects/:id/issues/:issue_iid/unsubscribe
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/unsubscribe
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/unsubscribe
```
Example response:
@@ -839,6 +869,9 @@ Example response:
"created_at": "2016-04-05T21:41:45.217Z",
"updated_at": "2016-04-07T13:02:37.905Z",
"labels": [],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
"milestone": null,
"assignee": {
"name": "Edwardo Grady",
@@ -882,7 +915,7 @@ POST /projects/:id/issues/:issue_iid/todo
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/todo
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/todo
```
Example response:
@@ -956,6 +989,7 @@ Example response:
"user_notes_count": 7,
"upvotes": 0,
"downvotes": 0,
+ "merge_requests_count": 0,
"due_date": null,
"web_url": "http://example.com/example/example/issues/110",
"confidential": false,
@@ -970,7 +1004,6 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
-
**Note**: The `closed_by` attribute was [introduced in GitLab 10.6][ce-17042]. This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
## Set a time estimate for an issue
@@ -988,7 +1021,7 @@ POST /projects/:id/issues/:issue_iid/time_estimate
| `duration` | string | yes | The duration in human format. e.g: 3h30m |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/time_estimate?duration=3h30m
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/time_estimate?duration=3h30m
```
Example response:
@@ -1016,7 +1049,7 @@ POST /projects/:id/issues/:issue_iid/reset_time_estimate
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/reset_time_estimate
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/reset_time_estimate
```
Example response:
@@ -1045,7 +1078,7 @@ POST /projects/:id/issues/:issue_iid/add_spent_time
| `duration` | string | yes | The duration in human format. e.g: 3h30m |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/add_spent_time?duration=1h
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/add_spent_time?duration=1h
```
Example response:
@@ -1073,7 +1106,7 @@ POST /projects/:id/issues/:issue_iid/reset_spent_time
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/reset_spent_time
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/reset_spent_time
```
Example response:
@@ -1099,7 +1132,7 @@ GET /projects/:id/issues/:issue_iid/time_stats
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/time_stats
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/time_stats
```
Example response:
@@ -1127,7 +1160,7 @@ GET /projects/:id/issues/:issue_id/related_merge_requests
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```sh
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/11/related_merge_requests
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/11/related_merge_requests
```
Example response:
@@ -1214,7 +1247,7 @@ GET /projects/:id/issues/:issue_iid/closed_by
| `issue_iid` | integer | yes | The internal ID of a project issue |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/11/closed_by
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/issues/11/closed_by
```
Example response:
@@ -1268,7 +1301,6 @@ Example response:
]
```
-
## Participants on issues
```
@@ -1281,7 +1313,7 @@ GET /projects/:id/issues/:issue_iid/participants
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/participants
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/participants
```
Example response:
@@ -1307,7 +1339,6 @@ Example response:
]
```
-
## Comments on issues
Comments are done via the [notes](notes.md) resource.
@@ -1326,7 +1357,7 @@ GET /projects/:id/issues/:issue_iid/user_agent_detail
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/user_agent_detail
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/93/user_agent_detail
```
Example response:
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index d2dd9c676e3..877cd99723a 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -10,11 +10,11 @@ GET /projects/:id/jobs
| Attribute | Type | Required | Description |
|-----------|--------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
| `scope` | string **or** array of strings | 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. |
```sh
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/1/jobs?scope[]=pending&scope[]=running'
+curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/1/jobs?scope[]=pending&scope[]=running'
```
Example of response
@@ -142,12 +142,12 @@ GET /projects/:id/pipelines/:pipeline_id/jobs
| Attribute | Type | Required | Description |
|---------------|--------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `pipeline_id` | integer | yes | The ID of a pipeline. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `pipeline_id` | integer | yes | ID of a pipeline. |
| `scope` | string **or** array of strings | 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. |
```sh
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/1/pipelines/6/jobs?scope[]=pending&scope[]=running'
+curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/1/pipelines/6/jobs?scope[]=pending&scope[]=running'
```
Example of response
@@ -275,11 +275,11 @@ GET /projects/:id/jobs/:job_id
| Attribute | Type | Required | Description |
|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | The ID of a job. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | ID of a job. |
```sh
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/8"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8"
```
Example of response
@@ -350,13 +350,13 @@ GET /projects/:id/jobs/:job_id/artifacts
| Attribute | Type | Required | Description |
|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | The ID of a job. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | ID of a job. |
Example requests:
```sh
-curl --location --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/8/artifacts"
+curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8/artifacts"
```
Possible response status codes:
@@ -385,14 +385,14 @@ Parameters
| Attribute | Type | Required | Description |
|------------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.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. |
Example requests:
```sh
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test"
```
Possible response status codes:
@@ -420,14 +420,14 @@ Parameters
| Attribute | Type | Required | Description |
|-----------------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.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. |
Example request:
```sh
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/5/artifacts/some/release/file.pdf"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/5/artifacts/some/release/file.pdf"
```
Possible response status codes:
@@ -454,7 +454,7 @@ Parameters:
| Attribute | Type | Required | Description |
|-----------------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.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. |
@@ -462,7 +462,7 @@ Parameters:
Example request:
```sh
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/raw/some/release/file.pdf?job=pdf"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/raw/some/release/file.pdf?job=pdf"
```
Possible response status codes:
@@ -483,11 +483,11 @@ GET /projects/:id/jobs/:job_id/trace
| Attribute | Type | Required | Description |
|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| id | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| job_id | integer | yes | The ID of a job. |
+| id | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| job_id | integer | yes | ID of a job. |
```sh
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace"
```
Possible response status codes:
@@ -507,11 +507,11 @@ POST /projects/:id/jobs/:job_id/cancel
| Attribute | Type | Required | Description |
|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | The ID of a job. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | ID of a job. |
```sh
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/cancel"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/cancel"
```
Example of response
@@ -555,11 +555,11 @@ POST /projects/:id/jobs/:job_id/retry
| Attribute | Type | Required | Description |
|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | The ID of a job. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | ID of a job. |
```sh
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/retry"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/retry"
```
Example of response
@@ -605,13 +605,13 @@ Parameters
| Attribute | Type | Required | Description |
|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | The ID of a job. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | ID of a job. |
Example of request
```sh
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/erase"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/erase"
```
Example of response
@@ -658,13 +658,13 @@ Parameters
| Attribute | Type | Required | Description |
|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | The ID of a job. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | ID of a job. |
Example request:
```sh
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts/keep"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts/keep"
```
Example response:
@@ -699,6 +699,33 @@ Example response:
}
```
+## Delete artifacts
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/25522) in GitLab 11.9.
+
+Delete artifacts of a job.
+
+```
+DELETE /projects/:id/jobs/:job_id/artifacts
+```
+
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `job_id` | integer | yes | ID of a job. |
+
+
+Example request:
+
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts"
+```
+
+NOTE: **Note:**
+At least Maintainer role is required to delete artifacts.
+
+If the artifacts were deleted successfully, a response with status `204 No Content` is returned.
+
## Play a job
Triggers a manual action to start a job.
@@ -709,11 +736,11 @@ POST /projects/:id/jobs/:job_id/play
| Attribute | Type | Required | Description |
|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | The ID of a job. |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | ID of a job. |
```sh
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/play"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/play"
```
Example of response
diff --git a/doc/api/labels.md b/doc/api/labels.md
index ec93cf50e7a..9d10d383bf9 100644
--- a/doc/api/labels.md
+++ b/doc/api/labels.md
@@ -13,7 +13,7 @@ GET /projects/:id/labels
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/labels
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/labels
```
Example response:
@@ -24,56 +24,66 @@ Example response:
"id" : 1,
"name" : "bug",
"color" : "#d9534f",
+ "text_color" : "#FFFFFF",
"description": "Bug reported by user",
"open_issues_count": 1,
"closed_issues_count": 0,
"open_merge_requests_count": 1,
"subscribed": false,
- "priority": 10
+ "priority": 10,
+ "is_project_label": true
},
{
"id" : 4,
"color" : "#d9534f",
+ "text_color" : "#FFFFFF",
"name" : "confirmed",
"description": "Confirmed issue",
"open_issues_count": 2,
"closed_issues_count": 5,
"open_merge_requests_count": 0,
"subscribed": false,
- "priority": null
+ "priority": null,
+ "is_project_label": true
},
{
"id" : 7,
"name" : "critical",
"color" : "#d9534f",
+ "text_color" : "#FFFFFF",
"description": "Critical issue. Need fix ASAP",
"open_issues_count": 1,
"closed_issues_count": 3,
"open_merge_requests_count": 1,
"subscribed": false,
- "priority": null
+ "priority": null,
+ "is_project_label": true
},
{
"id" : 8,
"name" : "documentation",
"color" : "#f0ad4e",
+ "text_color" : "#FFFFFF",
"description": "Issue about documentation",
"open_issues_count": 1,
"closed_issues_count": 0,
"open_merge_requests_count": 2,
"subscribed": false,
- "priority": null
+ "priority": null,
+ "is_project_label": false
},
{
"id" : 9,
"color" : "#5cb85c",
+ "text_color" : "#FFFFFF",
"name" : "enhancement",
"description": "Enhancement proposal",
"open_issues_count": 1,
"closed_issues_count": 0,
"open_merge_requests_count": 1,
"subscribed": true,
- "priority": null
+ "priority": null,
+ "is_project_label": true
}
]
```
@@ -95,7 +105,7 @@ POST /projects/:id/labels
| `priority` | integer | no | The priority of the label. Must be greater or equal than zero or `null` to remove the priority. |
```bash
-curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/labels"
+curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels"
```
Example response:
@@ -105,12 +115,14 @@ Example response:
"id" : 10,
"name" : "feature",
"color" : "#5843AD",
+ "text_color" : "#FFFFFF",
"description":null,
"open_issues_count": 0,
"closed_issues_count": 0,
"open_merge_requests_count": 0,
"subscribed": false,
- "priority": null
+ "priority": null,
+ "is_project_label": true
}
```
@@ -128,7 +140,7 @@ DELETE /projects/:id/labels
| `name` | string | yes | The name of the label |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/labels?name=bug"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels?name=bug"
```
## Edit an existing label
@@ -149,9 +161,8 @@ PUT /projects/:id/labels
| `description` | string | no | The new description of the label |
| `priority` | integer | no | The new priority of the label. Must be greater or equal than zero or `null` to remove the priority. |
-
```bash
-curl --request PUT --data "name=documentation&new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/labels"
+curl --request PUT --data "name=documentation&new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels"
```
Example response:
@@ -161,12 +172,14 @@ Example response:
"id" : 8,
"name" : "docs",
"color" : "#8E44AD",
+ "text_color" : "#FFFFFF",
"description": "Documentation",
"open_issues_count": 1,
"closed_issues_count": 0,
"open_merge_requests_count": 2,
"subscribed": false,
- "priority": null
+ "priority": null,
+ "is_project_label": true
}
```
@@ -186,7 +199,7 @@ POST /projects/:id/labels/:label_id/subscribe
| `label_id` | integer or string | yes | The ID or title of a project's label |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/labels/1/subscribe
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/labels/1/subscribe
```
Example response:
@@ -196,12 +209,14 @@ Example response:
"id" : 1,
"name" : "bug",
"color" : "#d9534f",
+ "text_color" : "#FFFFFF",
"description": "Bug reported by user",
"open_issues_count": 1,
"closed_issues_count": 0,
"open_merge_requests_count": 1,
"subscribed": true,
- "priority": null
+ "priority": null,
+ "is_project_label": true
}
```
@@ -221,5 +236,5 @@ POST /projects/:id/labels/:label_id/unsubscribe
| `label_id` | integer or string | yes | The ID or title of a project's label |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/labels/1/unsubscribe
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/labels/1/unsubscribe
```
diff --git a/doc/api/lint.md b/doc/api/lint.md
index bd5a216a99d..71c09d35b8c 100644
--- a/doc/api/lint.md
+++ b/doc/api/lint.md
@@ -2,7 +2,7 @@
> [Introduced][ce-5953] in GitLab 8.12.
-Checks if your .gitlab-ci.yml file is valid.
+Checks if your `.gitlab-ci.yml` file is valid.
```
POST /lint
@@ -13,14 +13,14 @@ POST /lint
| `content` | string | yes | the .gitlab-ci.yaml content|
```bash
-curl --header "Content-Type: application/json" https://gitlab.example.com/api/v4/ci/lint --data '{"content": "{ \"image\": \"ruby:2.1\", \"services\": [\"postgres\"], \"before_script\": [\"gem install bundler\", \"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
+curl --header "Content-Type: application/json" https://gitlab.example.com/api/v4/ci/lint --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
```
Be sure to copy paste the exact contents of `.gitlab-ci.yml` as YAML is very picky about indentation and spaces.
Example responses:
-* Valid content:
+- Valid content:
```json
{
@@ -29,7 +29,7 @@ Example responses:
}
```
-* Invalid content:
+- Invalid content:
```json
{
@@ -40,7 +40,7 @@ Example responses:
}
```
-* Without the content attribute:
+- Without the content attribute:
```json
{
@@ -49,4 +49,3 @@ Example responses:
```
[ce-5953]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5953
-
diff --git a/doc/api/members.md b/doc/api/members.md
index bb4fae35f52..0593d2c20ea 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -28,8 +28,8 @@ GET /projects/:id/members
| `query` | string | no | A query string to search for members |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/members
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/members
```
Example response:
@@ -75,8 +75,8 @@ GET /projects/:id/members/all
| `query` | string | no | A query string to search for members |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members/all
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members/all
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/members/all
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/members/all
```
Example response:
@@ -131,8 +131,8 @@ GET /projects/:id/members/:user_id
| `user_id` | integer | yes | The user ID of the member |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members/:user_id
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members/:user_id
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/members/:user_id
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/members/:user_id
```
Example response:
@@ -167,8 +167,8 @@ POST /projects/:id/members
| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "user_id=1&access_level=30" https://gitlab.example.com/api/v4/groups/:id/members
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "user_id=1&access_level=30" https://gitlab.example.com/api/v4/projects/:id/members
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "user_id=1&access_level=30" https://gitlab.example.com/api/v4/groups/:id/members
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "user_id=1&access_level=30" https://gitlab.example.com/api/v4/projects/:id/members
```
Example response:
@@ -203,8 +203,8 @@ PUT /projects/:id/members/:user_id
| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members/:user_id?access_level=40
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members/:user_id?access_level=40
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/members/:user_id?access_level=40
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/members/:user_id?access_level=40
```
Example response:
@@ -237,8 +237,8 @@ DELETE /projects/:id/members/:user_id
| `user_id` | integer | yes | The user ID of the member |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members/:user_id
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members/:user_id
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/members/:user_id
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/members/:user_id
```
## Give a group access to a project
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 9ff6c73b1b6..ed4b6281acc 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -24,6 +24,7 @@ GET /merge_requests?labels=bug,reproduced
GET /merge_requests?author_id=5
GET /merge_requests?my_reaction_emoji=star
GET /merge_requests?scope=assigned_to_me
+GET /merge_requests?search=foo&in=title
```
Parameters:
@@ -47,6 +48,7 @@ Parameters:
| `source_branch` | string | no | Return merge requests with the given source branch |
| `target_branch` | string | no | Return merge requests with the given target branch |
| `search` | string | no | Search merge requests against their `title` and `description` |
+| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests |
```json
@@ -158,7 +160,6 @@ will be the same. In the case of a merge request from a fork,
`target_project_id` and `project_id` will be the same and
`source_project_id` will be the fork project's ID.
-
Parameters:
| Attribute | Type | Required | Description |
@@ -182,6 +183,7 @@ Parameters:
| `source_branch` | string | no | Return merge requests with the given source branch |
| `target_branch` | string | no | Return merge requests with the given target branch |
| `search` | string | no | Search merge requests against their `title` and `description` |
+| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests |
```json
[
@@ -432,6 +434,9 @@ Parameters:
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "user" : {
+ "can_merge" : false
+ }
"assignee": {
"id": 1,
"name": "Administrator",
@@ -525,7 +530,6 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `merge_request_iid` (required) - The internal ID of the merge request
-
```json
[
{
@@ -560,7 +564,6 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `merge_request_iid` (required) - The internal ID of the merge request
-
```json
[
{
@@ -967,7 +970,7 @@ DELETE /projects/:id/merge_requests/:merge_request_iid
| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/merge_requests/85
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/merge_requests/85
```
## Accept MR
@@ -991,6 +994,8 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `merge_request_iid` (required) - Internal ID of MR
- `merge_commit_message` (optional) - Custom merge commit message
+- `squash_commit_message` (optional) - Custom squash commit message
+- `squash` (optional) - if `true` the commits will be squashed into a single commit on merge
- `should_remove_source_branch` (optional) - if `true` removes the source branch
- `merge_when_pipeline_succeeds` (optional) - if `true` the MR is merged when the pipeline succeeds
- `sha` (optional) - if present, then this SHA must match the HEAD of the source branch, otherwise the merge will fail
@@ -1096,6 +1101,40 @@ Parameters:
}
```
+## Merge to default merge ref path
+
+Merge the changes between the merge request source and target branches into `refs/merge-requests/:iid/merge`
+ref, of the target project repository. This ref will have the state the target branch would have if
+a regular merge action was taken.
+
+This is not a regular merge action given it doesn't change the merge request state in any manner.
+
+This ref (`refs/merge-requests/:iid/merge`) is **always** overwritten when submitting
+requests to this API, so none of its state is kept or used in the process.
+
+If the merge request has conflicts, is empty or already merged,
+you'll get a `400` and a descriptive error message. If you don't have permissions to do so,
+you'll get a `403`.
+
+It returns the HEAD commit of `refs/merge-requests/:iid/merge` in the response body in
+case of `200`.
+
+```
+PUT /projects/:id/merge_requests/:merge_request_iid/merge_to_ref
+```
+
+Parameters:
+
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - Internal ID of MR
+- `merge_commit_message` (optional) - Custom merge commit message
+
+```json
+{
+ "commit_id": "854a3a7a17acbcc0bbbea170986df1eb60435f34"
+}
+```
+
## Cancel Merge When Pipeline Succeeds
If you don't have permissions to accept this merge request - you'll get a `401`
@@ -1230,7 +1269,7 @@ PUT /projects/:id/merge_requests/:merge_request_iid/rebase
| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase
```
This is an asynchronous request. The API will return an empty `202 Accepted`
@@ -1286,7 +1325,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/closes_issues
| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/76/merge_requests/1/closes_issues
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/76/merge_requests/1/closes_issues
```
Example response when the GitLab issue tracker is used:
@@ -1362,7 +1401,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/subscribe
| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/17/subscribe
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/17/subscribe
```
Example response:
@@ -1483,7 +1522,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/unsubscribe
| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/17/unsubscribe
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/17/unsubscribe
```
Example response:
@@ -1604,7 +1643,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/todo
| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/27/todo
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/27/todo
```
Example response:
@@ -1707,7 +1746,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/versions
| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions
```
Example response:
@@ -1749,7 +1788,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/versions/:version_id
| `version_id` | integer | yes | The ID of the merge request diff version |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions/1
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions/1
```
Example response:
@@ -1816,7 +1855,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/time_estimate
| `duration` | string | yes | The duration in human format. e.g: 3h30m |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_estimate?duration=3h30m
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_estimate?duration=3h30m
```
Example response:
@@ -1844,7 +1883,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/reset_time_estimate
| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_time_estimate
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_time_estimate
```
Example response:
@@ -1873,7 +1912,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time
| `duration` | string | yes | The duration in human format. e.g: 3h30m |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h
```
Example response:
@@ -1901,7 +1940,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/reset_spent_time
| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_spent_time
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_spent_time
```
Example response:
@@ -1927,7 +1966,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/time_stats
| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_stats
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_stats
```
Example response:
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 7ac97edc7ae..897184d51af 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -23,7 +23,7 @@ Parameters:
| `search` | string | optional | Return only milestones with a title or description matching the provided string |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/milestones
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/milestones
```
Example Response:
@@ -130,3 +130,18 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `milestone_id` (required) - The ID of a project milestone
+
+## Promote project milestone to a group milestone
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/53861) in GitLab 11.9
+
+Only for users with developer access to the group.
+
+```
+POST /projects/:id/milestones/:milestone_id/promote
+```
+
+Parameters:
+
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `milestone_id` (required) - The ID of a project milestone
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index 656bf07bb55..b8bc4c40124 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -19,7 +19,7 @@ GET /namespaces
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/namespaces
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/namespaces
```
Example response:
@@ -71,7 +71,7 @@ GET /namespaces?search=foobar
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/namespaces?search=twitter
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/namespaces?search=twitter
```
Example response:
@@ -105,7 +105,7 @@ GET /namespaces/:id
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/namespaces/2
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/namespaces/2
```
Example response:
@@ -125,7 +125,7 @@ Example response:
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/namespaces/group1
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/namespaces/group1
```
Example response:
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 9f6740ad86a..dd4e18b14e6 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -66,7 +66,7 @@ GET /projects/:id/issues/:issue_iid/notes?sort=asc&order_by=updated_at
```
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/notes
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/notes
```
### Get single issue note
@@ -84,7 +84,7 @@ Parameters:
- `note_id` (required) - The ID of an issue note
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/notes/1
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/notes/1
```
### Create new issue note
@@ -103,7 +103,7 @@ Parameters:
- `created_at` (optional) - Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights)
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note
```
### Modify existing issue note
@@ -122,7 +122,7 @@ Parameters:
- `body` (required) - The content of a note
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note
```
### Delete an issue note
@@ -142,7 +142,7 @@ Parameters:
| `note_id` | integer | yes | The ID of a note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/notes/636
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/notes/636
```
## Snippets
@@ -164,7 +164,7 @@ GET /projects/:id/snippets/:snippet_id/notes?sort=asc&order_by=updated_at
| `order_by` | string | no | Return snippet notes ordered by `created_at` or `updated_at` fields. Default is `created_at`
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/11/notes
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/notes
```
### Get single snippet note
@@ -201,7 +201,7 @@ Parameters:
```
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/11/notes/11
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/notes/11
```
### Create new snippet note
@@ -221,7 +221,7 @@ Parameters:
- `created_at` (optional) - Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note
```
### Modify existing snippet note
@@ -240,7 +240,7 @@ Parameters:
- `body` (required) - The content of a note
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/11/notes?body=note
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/notes?body=note
```
### Delete a snippet note
@@ -260,7 +260,7 @@ Parameters:
| `note_id` | integer | yes | The ID of a note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/52/notes/1659
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/52/notes/1659
```
## Merge Requests
@@ -282,7 +282,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/notes?sort=asc&order_by=upda
| `order_by` | string | no | Return merge request notes ordered by `created_at` or `updated_at` fields. Default is `created_at`
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes
```
### Get single merge request note
@@ -323,7 +323,7 @@ Parameters:
```
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes/1
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes/1
```
### Create new merge request note
@@ -359,7 +359,7 @@ Parameters:
- `body` (required) - The content of a note
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes?body=note
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes?body=note
```
### Delete a merge request note
@@ -379,5 +379,5 @@ Parameters:
| `note_id` | integer | yes | The ID of a note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/7/notes/1602
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/7/notes/1602
```
diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md
index 165b9a11c7a..e21e73c7dac 100644
--- a/doc/api/notification_settings.md
+++ b/doc/api/notification_settings.md
@@ -43,7 +43,7 @@ GET /notification_settings
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/notification_settings
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/notification_settings
```
Example response:
@@ -64,7 +64,7 @@ PUT /notification_settings
```
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/notification_settings?level=watch
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/notification_settings?level=watch
```
| Attribute | Type | Required | Description |
@@ -105,8 +105,8 @@ GET /projects/:id/notification_settings
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/notification_settings
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/8/notification_settings
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/notification_settings
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/8/notification_settings
```
| Attribute | Type | Required | Description |
@@ -131,8 +131,8 @@ PUT /projects/:id/notification_settings
```
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/notification_settings?level=watch
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/8/notification_settings?level=custom&new_note=true
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/notification_settings?level=watch
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/8/notification_settings?level=custom&new_note=true
```
| Attribute | Type | Required | Description |
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 8a1e6b52092..dfe62554852 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -1,126 +1,165 @@
# GitLab as an OAuth2 provider
-This document covers using the [OAuth2](https://oauth.net/2/) protocol to allow other services access GitLab resources on user's behalf.
+This document covers using the [OAuth2](https://oauth.net/2/) protocol to allow
+other services to access GitLab resources on user's behalf.
-If you want GitLab to be an OAuth authentication service provider to sign into other services please see the [OAuth2 provider](../integration/oauth_provider.md)
-documentation.
+If you want GitLab to be an OAuth authentication service provider to sign into
+other services, see the [OAuth2 provider](../integration/oauth_provider.md)
+documentation. This functionality is based on the
+[doorkeeper Ruby gem](https://github.com/doorkeeper-gem/doorkeeper).
-This functionality is based on [doorkeeper gem](https://github.com/doorkeeper-gem/doorkeeper).
+## Supported OAuth2 flows
-## Supported OAuth2 Flows
+GitLab currently supports the following authorization flows:
-GitLab currently supports following authorization flows:
+- **Web application flow:** Most secure and common type of flow, designed for
+ applications with secure server-side.
+- **Implicit grant flow:** This flow is designed for user-agent only apps (e.g., single
+ page web application running on GitLab Pages).
+- **Resource owner password credentials flow:** To be used **only** for securely
+ hosted, first-party services.
-* *Web Application Flow* - Most secure and common type of flow, designed for the applications with secure server-side.
-* *Implicit Flow* - This flow is designed for user-agent only apps (e.g. single page web application running on GitLab Pages).
-* *Resource Owner Password Credentials Flow* - To be used **only** for securely hosted, first-party services.
+Refer to the [OAuth RFC](https://tools.ietf.org/html/rfc6749) to find out
+how all those flows work and pick the right one for your use case.
-Please refer to [OAuth RFC](https://tools.ietf.org/html/rfc6749) to find out in details how all those flows work and pick the right one for your use case.
+Both **web application** and **implicit grant** flows require `application` to be
+registered first via the `/profile/applications` page in your user's account.
+During registration, by enabling proper scopes, you can limit the range of
+resources which the `application` can access. Upon creation, you'll obtain the
+`application` credentials: _Application ID_ and _Client Secret_ - **keep them secure**.
-Both *web application* and *implicit* flows require `application` to be registered first via `/profile/applications` page
-in your user's account. During registration, by enabling proper scopes you can limit the range of resources which the `application` can access. Upon creation
-you'll obtain `application` credentials: _Application ID_ and _Client Secret_ - **keep them secure**.
+CAUTION: **Important:**
+OAuth specification advises sending the `state` parameter with each request to
+`/oauth/authorize`. We highly recommended sending a unique value with each request
+and validate it against the one in the redirect request. This is important in
+order to prevent [CSRF attacks](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)).
+The `state` parameter really should have been a requirement in the standard!
->**Important:** OAuth specification advises sending `state` parameter with each request to `/oauth/authorize`. We highly recommended to send a unique
-value with each request and validate it against the one in redirect request. This is important to prevent [CSRF attacks]. The `state` param really should
-have been a requirement in the standard!
+In the following sections you will find detailed instructions on how to obtain
+authorization with each flow.
-In the following sections you will find detailed instructions on how to obtain authorization with each flow.
+### Web application flow
-### Web Application Flow
+NOTE: **Note:**
+Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.1) for a
+detailed flow description.
-Check [RFC spec](http://tools.ietf.org/html/rfc6749#section-4.1) for a detailed flow description
+The web application flow is:
-#### 1. Requesting authorization code
+1. Request authorization code. To do that, you should redirect the user to the
+ `/oauth/authorize` endpoint with the following GET parameters:
-To request the authorization code, you should redirect the user to the `/oauth/authorize` endpoint with following GET parameters:
+ ```
+ https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=YOUR_UNIQUE_STATE_HASH
+ ```
-```
-https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=YOUR_UNIQUE_STATE_HASH
-```
+ This will ask the user to approve the applications access to their account and
+ then redirect back to the `REDIRECT_URI` you provided. The redirect will
+ include the GET `code` parameter, for example:
-This will ask the user to approve the applications access to their account and then redirect back to the `REDIRECT_URI` you provided. The redirect will
-include the GET `code` parameter, for example:
+ ```
+ http://myapp.com/oauth/redirect?code=1234567890&state=YOUR_UNIQUE_STATE_HASH
+ ```
-`http://myapp.com/oauth/redirect?code=1234567890&state=YOUR_UNIQUE_STATE_HASH`
+ You should then use `code` to request an access token.
-You should then use the `code` to request an access token.
+1. Once you have the authorization code you can request an `access_token` using the
+ code. You can do that by using any HTTP client. In the following example,
+ we are using Ruby's `rest-client`:
-#### 2. Requesting access token
+ ```ruby
+ parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI'
+ RestClient.post 'http://gitlab.example.com/oauth/token', parameters
+ ```
-Once you have the authorization code you can request an `access_token` using the code, to do that you can use any HTTP client. In the following example,
-we are using Ruby's `rest-client`:
+ Example response:
-```
-parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI'
-RestClient.post 'http://gitlab.example.com/oauth/token', parameters
+ ```json
+ {
+ "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
+ "token_type": "bearer",
+ "expires_in": 7200,
+ "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1"
+ }
+ ```
-# The response will be
-{
- "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
- "token_type": "bearer",
- "expires_in": 7200,
- "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1"
-}
-```
->**Note:**
-The `redirect_uri` must match the `redirect_uri` used in the original authorization request.
+NOTE: **Note:**
+The `redirect_uri` must match the `redirect_uri` used in the original
+authorization request.
You can now make requests to the API with the access token returned.
+### Implicit grant flow
-### Implicit Grant
-
-Check [RFC spec](http://tools.ietf.org/html/rfc6749#section-4.2) for a detailed flow description.
-
-Unlike the web flow, the client receives an `access token` immediately as a result of the authorization request. The flow does not use client secret
-or authorization code because all of the application code and storage is easily accessible, therefore __secrets__ can leak easily.
+NOTE: **Note:**
+Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.2) for a
+detailed flow description.
->**Important:** Avoid using this flow for applications that store data outside of the GitLab instance. If you do, make sure to verify `application id`
-associated with access token before granting access to the data
-(see [/oauth/token/info](https://github.com/doorkeeper-gem/doorkeeper/wiki/API-endpoint-descriptions-and-examples#get----oauthtokeninfo)).
-
+CAUTION: **Important:**
+Avoid using this flow for applications that store data outside of the GitLab
+instance. If you do, make sure to verify `application id` associated with the
+access token before granting access to the data
+(see [/oauth/token/info](https://github.com/doorkeeper-gem/doorkeeper/wiki/API-endpoint-descriptions-and-examples#get----oauthtokeninfo)).
-#### 1. Requesting access token
+Unlike the web flow, the client receives an `access token` immediately as a
+result of the authorization request. The flow does not use the client secret
+or the authorization code because all of the application code and storage is
+easily accessible, therefore secrets can leak easily.
-To request the access token, you should redirect the user to the `/oauth/authorize` endpoint using `token` response type:
+To request the access token, you should redirect the user to the
+`/oauth/authorize` endpoint using `token` response type:
```
https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=token&state=YOUR_UNIQUE_STATE_HASH
```
-This will ask the user to approve the applications access to their account and then redirect back to the `REDIRECT_URI` you provided. The redirect
-will include a fragment with `access_token` as well as token details in GET parameters, for example:
+This will ask the user to approve the application's access to their account and
+then redirect them back to the `REDIRECT_URI` you provided. The redirect
+will include a fragment with `access_token` as well as token details in GET
+parameters, for example:
```
http://myapp.com/oauth/redirect#access_token=ABCDExyz123&state=YOUR_UNIQUE_STATE_HASH&token_type=bearer&expires_in=3600
```
-### Resource Owner Password Credentials
+### Resource owner password credentials flow
-Check [RFC spec](http://tools.ietf.org/html/rfc6749#section-4.3) for a detailed flow description.
+NOTE: **Note:**
+Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.3) for a
+detailed flow description.
-> **Deprecation notice:** Starting in GitLab 8.11, the Resource Owner Password Credentials has been *disabled* for users with two-factor authentication
-turned on. These users can access the API using [personal access tokens] instead.
+NOTE: **Note:**
+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.
-In this flow, a token is requested in exchange for the resource owner credentials (username and password).
-The credentials should only be used when there is a high degree of trust between the resource owner and the client (e.g. the
-client is part of the device operating system or a highly privileged application), and when other authorization grant types are not
-available (such as an authorization code).
+In this flow, a token is requested in exchange for the resource owner credentials
+(username and password).
->**Important:**
-Never store the users credentials and only use this grant type when your client is deployed to a trusted environment, in 99% of cases [personal access tokens]
-are a better choice.
+The credentials should only be used when:
-Even though this grant type requires direct client access to the resource owner credentials, the resource owner credentials are used
-for a single request and are exchanged for an access token. This grant type can eliminate the need for the client to store the
-resource owner credentials for future use, by exchanging the credentials with a long-lived access token or refresh token.
+- There is a high degree of trust between the resource owner and the client. For
+ example, the client is part of the device operating system or a highly
+ privileged application.
+- Other authorization grant types are not available (such as an authorization code).
-#### 1. Requesting access token
+CAUTION: **Important:**
+Never store the user's credentials and only use this grant type when your client
+is deployed to a trusted environment, in 99% of cases
+[personal access tokens](../user/profile/personal_access_tokens.md) are a better
+choice.
-POST request to `/oauth/token` with parameters:
+Even though this grant type requires direct client access to the resource owner
+credentials, the resource owner credentials are used for a single request and
+are exchanged for an access token. This grant type can eliminate the need for
+the client to store the resource owner credentials for future use, by exchanging
+the credentials with a long-lived access token or refresh token.
-```
+To request an access token, you must make a POST request to `/oauth/token` with
+the following parameters:
+
+```json
{
"grant_type" : "password",
"username" : "user@example.com",
@@ -128,6 +167,13 @@ POST request to `/oauth/token` with parameters:
}
```
+Example cURL request:
+
+```sh
+echo 'grant_type=password&username=<your_username>&password=<your_password>' > auth.txt
+curl --data "@auth.txt" --request POST https://gitlab.example.com/oauth/token
+```
+
Then, you'll receive the access token back in the response:
```
@@ -138,7 +184,7 @@ Then, you'll receive the access token back in the response:
}
```
-For testing you can use the oauth2 ruby gem:
+For testing, you can use the `oauth2` Ruby gem:
```
client = OAuth2::Client.new('the_client_id', 'the_client_secret', :site => "http://example.com")
@@ -148,7 +194,9 @@ puts access_token.token
## Access GitLab API with `access token`
-The `access token` allows you to make requests to the API on a behalf of a user. You can pass the token either as GET parameter
+The `access token` allows you to make requests to the API on behalf of a user.
+You can pass the token either as GET parameter:
+
```
GET https://gitlab.example.com/api/v4/user?access_token=OAUTH-TOKEN
```
@@ -158,6 +206,3 @@ or you can put the token to the Authorization header:
```
curl --header "Authorization: Bearer OAUTH-TOKEN" https://gitlab.example.com/api/v4/user
```
-
-[personal access tokens]: ../user/profile/personal_access_tokens.md
-[CSRF attacks]: http://www.oauthsecurity.com/#user-content-authorization-code-flow \ No newline at end of file
diff --git a/doc/api/pages_domains.md b/doc/api/pages_domains.md
index da2ffcfe40a..70fbe24099f 100644
--- a/doc/api/pages_domains.md
+++ b/doc/api/pages_domains.md
@@ -8,12 +8,12 @@ The GitLab Pages feature must be enabled to use these endpoints. Find out more a
Get a list of all pages domains. The user must have admin permissions.
-```http
+```text
GET /pages/domains
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/pages/domains
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/pages/domains
```
```json
@@ -34,7 +34,7 @@ curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/a
Get a list of project pages domains. The user must have permissions to view pages domains.
-```http
+```text
GET /projects/:id/pages/domains
```
@@ -43,7 +43,7 @@ GET /projects/:id/pages/domains
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/pages/domains
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/pages/domains
```
```json
@@ -69,7 +69,7 @@ curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/a
Get a single project pages domain. The user must have permissions to view pages domains.
-```http
+```text
GET /projects/:id/pages/domains/:domain
```
@@ -79,7 +79,7 @@ GET /projects/:id/pages/domains/:domain
| `domain` | string | yes | The domain |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/pages/domains/www.domain.example
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/pages/domains/www.domain.example
```
```json
@@ -90,7 +90,7 @@ curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/a
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
```
```json
@@ -110,7 +110,7 @@ curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/a
Creates a new pages domain. The user must have permissions to create new pages domains.
-```http
+```text
POST /projects/:id/pages/domains
```
@@ -122,11 +122,11 @@ POST /projects/:id/pages/domains
| `key` | file/string | no | The certificate key in PEM format. |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "domain=ssl.domain.example" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains
```
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "domain=ssl.domain.example" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" https://gitlab.example.com/api/v4/projects/5/pages/domains
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" https://gitlab.example.com/api/v4/projects/5/pages/domains
```
```json
@@ -146,7 +146,7 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "domai
Updates an existing project pages domain. The user must have permissions to change an existing pages domains.
-```http
+```text
PUT /projects/:id/pages/domains/:domain
```
@@ -158,11 +158,11 @@ PUT /projects/:id/pages/domains/:domain
| `key` | file/string | no | The certificate key in PEM format. |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
```
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
```
```json
@@ -182,7 +182,7 @@ curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "certif
Deletes an existing project pages domain.
-```http
+```text
DELETE /projects/:id/pages/domains/:domain
```
@@ -192,5 +192,5 @@ DELETE /projects/:id/pages/domains/:domain
| `domain` | string | yes | The domain |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
```
diff --git a/doc/api/pipeline_triggers.md b/doc/api/pipeline_triggers.md
index e881e61d4ef..736312df116 100644
--- a/doc/api/pipeline_triggers.md
+++ b/doc/api/pipeline_triggers.md
@@ -15,7 +15,7 @@ GET /projects/:id/triggers
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/triggers"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/triggers"
```
```json
@@ -46,7 +46,7 @@ GET /projects/:id/triggers/:trigger_id
| `trigger_id` | integer | yes | The trigger id |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/triggers/5"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/triggers/5"
```
```json
@@ -75,7 +75,7 @@ POST /projects/:id/triggers
| `description` | string | yes | The trigger name |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers"
```
```json
@@ -105,7 +105,7 @@ PUT /projects/:id/triggers/:trigger_id
| `description` | string | no | The trigger name |
```
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers/10"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers/10"
```
```json
@@ -134,7 +134,7 @@ POST /projects/:id/triggers/:trigger_id/take_ownership
| `trigger_id` | integer | yes | The trigger id |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/triggers/10/take_ownership"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/triggers/10/take_ownership"
```
```json
@@ -163,5 +163,5 @@ DELETE /projects/:id/triggers/:trigger_id
| `trigger_id` | integer | yes | The trigger id |
```
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/triggers/5"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/triggers/5"
```
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 7b4c9a8fbb3..43bbf463c8d 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -22,7 +22,7 @@ GET /projects/:id/pipelines
| `sort` | string | no | Sort pipelines in `asc` or `desc` order (default: `desc`) |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipelines"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipelines"
```
Example of response
@@ -60,7 +60,7 @@ GET /projects/:id/pipelines/:pipeline_id
| `pipeline_id` | integer | yes | The ID of a pipeline |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipelines/46"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipelines/46"
```
Example of response
@@ -108,7 +108,7 @@ POST /projects/:id/pipeline
| `variables` | array | no | An array containing the variables available in the pipeline, matching the structure [{ 'key' => 'UPLOAD_TO_S3', 'value' => 'true' }] |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=master"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=master"
```
Example of response
@@ -155,7 +155,7 @@ POST /projects/:id/pipelines/:pipeline_id/retry
| `pipeline_id` | integer | yes | The ID of a pipeline |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipelines/46/retry"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipelines/46/retry"
```
Response:
@@ -202,7 +202,7 @@ POST /projects/:id/pipelines/:pipeline_id/cancel
| `pipeline_id` | integer | yes | The ID of a pipeline |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipelines/46/cancel"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipelines/46/cancel"
```
Response:
@@ -249,7 +249,7 @@ DELETE /projects/:id/pipelines/:pipeline_id
| `pipeline_id` | integer | yes | The ID of a pipeline |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --request "DELETE" "https://gitlab.example.com/api/v4/projects/1/pipelines/46"
+curl --header "PRIVATE-TOKEN: <your_access_token>" --request "DELETE" "https://gitlab.example.com/api/v4/projects/1/pipelines/46"
```
[ce-5837]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5837
diff --git a/doc/api/project_badges.md b/doc/api/project_badges.md
index 94389273e9c..3a7b3d8975e 100644
--- a/doc/api/project_badges.md
+++ b/doc/api/project_badges.md
@@ -25,7 +25,7 @@ GET /projects/:id/badges
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/badges
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/badges
```
Example response:
@@ -65,7 +65,7 @@ GET /projects/:id/badges/:badge_id
| `badge_id` | integer | yes | The badge ID |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id
```
Example response:
@@ -96,7 +96,7 @@ POST /projects/:id/badges
| `image_url` | string | yes | URL of the badge image |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "link_url=https://gitlab.com/gitlab-org/gitlab-ce/commits/master&image_url=https://shields.io/my/badge1&position=0" https://gitlab.example.com/api/v4/projects/:id/badges
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "link_url=https://gitlab.com/gitlab-org/gitlab-ce/commits/master&image_url=https://shields.io/my/badge1&position=0" https://gitlab.example.com/api/v4/projects/:id/badges
```
Example response:
@@ -128,7 +128,7 @@ PUT /projects/:id/badges/:badge_id
| `image_url` | string | no | URL of the badge image |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id
```
Example response:
@@ -158,7 +158,7 @@ DELETE /projects/:id/badges/:badge_id
| `badge_id` | integer | yes | The badge ID |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id
```
## Preview a badge from a project
@@ -176,7 +176,7 @@ GET /projects/:id/badges/render
| `image_url` | string | yes | URL of the badge image |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/badges/render?link_url=http%3A%2F%2Fexample.com%2Fci_status.svg%3Fproject%3D%25%7Bproject_path%7D%26ref%3D%25%7Bdefault_branch%7D&image_url=https%3A%2F%2Fshields.io%2Fmy%2Fbadge
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/badges/render?link_url=http%3A%2F%2Fexample.com%2Fci_status.svg%3Fproject%3D%25%7Bproject_path%7D%26ref%3D%25%7Bdefault_branch%7D&image_url=https%3A%2F%2Fshields.io%2Fmy%2Fbadge
```
Example response:
diff --git a/doc/api/project_clusters.md b/doc/api/project_clusters.md
new file mode 100644
index 00000000000..8efb98fe1fc
--- /dev/null
+++ b/doc/api/project_clusters.md
@@ -0,0 +1,347 @@
+# Project clusters API
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23922)
+in GitLab 11.7.
+
+NOTE: **Note:**
+User will need at least maintainer access to use these endpoints.
+
+## List project clusters
+
+Returns a list of project clusters.
+
+```
+GET /projects/:id/clusters
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | The ID of the project owned by the authenticated user |
+
+Example request:
+
+```bash
+curl --header 'Private-Token: <your_access_token>' https://gitlab.example.com/api/v4/projects/26/clusters
+```
+
+Example response:
+
+```json
+[
+ {
+ "id":18,
+ "name":"cluster-1",
+ "created_at":"2019-01-02T20:18:12.563Z",
+ "provider_type":"user",
+ "platform_type":"kubernetes",
+ "environment_scope":"*",
+ "cluster_type":"project_type",
+ "user":
+ {
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
+ "web_url":"https://gitlab.example.com/root"
+ },
+ "platform_kubernetes":
+ {
+ "api_url":"https://104.197.68.152",
+ "namespace":"cluster-1-namespace",
+ "authorization_type":"rbac",
+ "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"
+ }
+ },
+ {
+ "id":19,
+ "name":"cluster-2",
+ ...
+ }
+]
+```
+
+## Get a single project cluster
+
+Gets a single project cluster.
+
+```bash
+GET /projects/:id/clusters/:cluster_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `cluster_id` | integer | yes | The ID of the cluster |
+
+Example request:
+
+```bash
+curl --header 'Private-Token: <your_access_token>' https://gitlab.example.com/api/v4/projects/26/clusters/18
+```
+
+Example response:
+
+```json
+{
+ "id":18,
+ "name":"cluster-1",
+ "created_at":"2019-01-02T20:18:12.563Z",
+ "provider_type":"user",
+ "platform_type":"kubernetes",
+ "environment_scope":"*",
+ "cluster_type":"project_type",
+ "user":
+ {
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
+ "web_url":"https://gitlab.example.com/root"
+ },
+ "platform_kubernetes":
+ {
+ "api_url":"https://104.197.68.152",
+ "namespace":"cluster-1-namespace",
+ "authorization_type":"rbac",
+ "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"
+ },
+ "project":
+ {
+ "id":26,
+ "description":"",
+ "name":"project-with-clusters-api",
+ "name_with_namespace":"Administrator / project-with-clusters-api",
+ "path":"project-with-clusters-api",
+ "path_with_namespace":"root/project-with-clusters-api",
+ "created_at":"2019-01-02T20:13:32.600Z",
+ "default_branch":null,
+ "tag_list":[],
+ "ssh_url_to_repo":"ssh://gitlab.example.com/root/project-with-clusters-api.git",
+ "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git",
+ "web_url":"https://gitlab.example.com/root/project-with-clusters-api",
+ "readme_url":null,
+ "avatar_url":null,
+ "star_count":0,
+ "forks_count":0,
+ "last_activity_at":"2019-01-02T20:13:32.600Z",
+ "namespace":
+ {
+ "id":1,
+ "name":"root",
+ "path":"root",
+ "kind":"user",
+ "full_path":"root",
+ "parent_id":null
+ }
+ }
+}
+```
+
+## Add existing cluster to project
+
+Adds an existing Kubernetes cluster to the project.
+
+```bash
+POST /projects/:id/clusters/user
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `name` | String | yes | The name of the cluster |
+| `enabled` | Boolean | no | Determines if cluster is active or not, defaults to true |
+| `platform_kubernetes_attributes[api_url]` | String | yes | The URL to access the Kubernetes API |
+| `platform_kubernetes_attributes[token]` | String | yes | The token to authenticate against Kubernetes |
+| `platform_kubernetes_attributes[ca_cert]` | String | no | TLS certificate (needed if API is using a self-signed TLS certificate |
+| `platform_kubernetes_attributes[namespace]` | String | no | The unique namespace related to the project |
+| `platform_kubernetes_attributes[authorization_type]` | String | no | The cluster authorization type: `rbac`, `abac` or `unknown_authorization`. Defaults to `rbac`. |
+
+Example request:
+
+```bash
+curl --header 'Private-Token: <your_access_token>' https://gitlab.example.com/api/v4/projects/26/clusters/user \
+-H "Accept: application/json" \
+-H "Content-Type:application/json" \
+-X POST --data '{"name":"cluster-5", "platform_kubernetes_attributes":{"api_url":"https://35.111.51.20","token":"12345","namespace":"cluster-5-namespace","ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"}}'
+```
+
+Example response:
+
+```json
+{
+ "id":24,
+ "name":"cluster-5",
+ "created_at":"2019-01-03T21:53:40.610Z",
+ "provider_type":"user",
+ "platform_type":"kubernetes",
+ "environment_scope":"*",
+ "cluster_type":"project_type",
+ "user":
+ {
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
+ "web_url":"https://gitlab.example.com/root"
+ },
+ "platform_kubernetes":
+ {
+ "api_url":"https://35.111.51.20",
+ "namespace":"cluster-5-namespace",
+ "authorization_type":"rbac",
+ "ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"
+ },
+ "project":
+ {
+ "id":26,
+ "description":"",
+ "name":"project-with-clusters-api",
+ "name_with_namespace":"Administrator / project-with-clusters-api",
+ "path":"project-with-clusters-api",
+ "path_with_namespace":"root/project-with-clusters-api",
+ "created_at":"2019-01-02T20:13:32.600Z",
+ "default_branch":null,
+ "tag_list":[],
+ "ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git",
+ "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git",
+ "web_url":"https://gitlab.example.com/root/project-with-clusters-api",
+ "readme_url":null,
+ "avatar_url":null,
+ "star_count":0,
+ "forks_count":0,
+ "last_activity_at":"2019-01-02T20:13:32.600Z",
+ "namespace":
+ {
+ "id":1,
+ "name":"root",
+ "path":"root",
+ "kind":"user",
+ "full_path":"root",
+ "parent_id":null
+ }
+ }
+}
+```
+
+## Edit project cluster
+
+Updates an existing project cluster.
+
+```bash
+PUT /projects/:id/clusters/:cluster_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `cluster_id` | integer | yes | The ID of the cluster |
+| `name` | String | no | The name of the cluster |
+| `platform_kubernetes_attributes[api_url]` | String | no | The URL to access the Kubernetes API |
+| `platform_kubernetes_attributes[token]` | String | no | The token to authenticate against Kubernetes |
+| `platform_kubernetes_attributes[ca_cert]` | String | no | TLS certificate (needed if API is using a self-signed TLS certificate |
+| `platform_kubernetes_attributes[namespace]` | String | no | The unique namespace related to the project |
+
+NOTE: **Note:**
+`name`, `api_url`, `ca_cert` and `token` can only be updated if the cluster was added
+through the ["Add an existing Kubernetes Cluster"](../user/project/clusters/index.md#adding-an-existing-kubernetes-cluster) option or
+through the ["Add existing cluster to project"](#add-existing-cluster-to-project) endpoint.
+
+Example request:
+
+```bash
+curl --header 'Private-Token: <your_access_token>' https://gitlab.example.com/api/v4/projects/26/clusters/24 \
+-H "Content-Type:application/json" \
+-X PUT --data '{"name":"new-cluster-name","api_url":"https://new-api-url.com"}'
+```
+
+Example response:
+
+```json
+{
+ "id":24,
+ "name":"new-cluster-name",
+ "created_at":"2019-01-03T21:53:40.610Z",
+ "provider_type":"user",
+ "platform_type":"kubernetes",
+ "environment_scope":"*",
+ "cluster_type":"project_type",
+ "user":
+ {
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
+ "web_url":"https://gitlab.example.com/root"
+ },
+ "platform_kubernetes":
+ {
+ "api_url":"https://new-api-url.com",
+ "namespace":"cluster-5-namespace",
+ "authorization_type":"rbac",
+ "ca_cert":null
+ },
+ "project":
+ {
+ "id":26,
+ "description":"",
+ "name":"project-with-clusters-api",
+ "name_with_namespace":"Administrator / project-with-clusters-api",
+ "path":"project-with-clusters-api",
+ "path_with_namespace":"root/project-with-clusters-api",
+ "created_at":"2019-01-02T20:13:32.600Z",
+ "default_branch":null,
+ "tag_list":[],
+ "ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git",
+ "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git",
+ "web_url":"https://gitlab.example.com/root/project-with-clusters-api",
+ "readme_url":null,
+ "avatar_url":null,
+ "star_count":0,
+ "forks_count":0,
+ "last_activity_at":"2019-01-02T20:13:32.600Z",
+ "namespace":
+ {
+ "id":1,
+ "name":"root",
+ "path":"root",
+ "kind":"user",
+ "full_path":"root",
+ "parent_id":null
+ }
+ }
+}
+
+```
+
+## Delete project cluster
+
+Deletes an existing project cluster.
+
+```
+DELETE /projects/:id/clusters/:cluster_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `cluster_id` | integer | yes | The ID of the cluster |
+
+Example request:
+
+```bash
+curl --header 'Private-Token: <your_access_token>' https://gitlab.example.com/api/v4/projects/26/clusters/23'
+```
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index 83e405141f1..5155e996158 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -1,8 +1,8 @@
# Project import/export API
-[Introduced][ce-41899] in GitLab 10.6
+> [Introduced][ce-41899] in GitLab 10.6.
-[See also the project import/export documentation](../user/project/settings/import_export.md)
+See also the [project import/export documentation](../user/project/settings/import_export.md).
## Schedule an export
@@ -16,7 +16,7 @@ data file uploads to the final server.
If the `upload` params is present, `upload[url]` param is required.
(**Note:** This feature was introduced in GitLab 10.7)
-```http
+```text
POST /projects/:id/export
```
@@ -28,9 +28,8 @@ POST /projects/:id/export
| `upload[url]` | string | yes | The URL to upload the project |
| `upload[http_method]` | string | no | The HTTP method to upload the exported project. Only `PUT` and `POST` methods allowed. Default is `PUT` |
-
-```console
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/export \
+```sh
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/export \
--data "upload[http_method]=PUT" \
--data-urlencode "upload[url]=https://example-bucket.s3.eu-west-3.amazonaws.com/backup?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIMBJHN2O62W8IELQ%2F20180312%2Feu-west-3%2Fs3%2Faws4_request&X-Amz-Date=20180312T110328Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=8413facb20ff33a49a147a0b4abcff4c8487cc33ee1f7e450c46e8f695569dbd"
```
@@ -45,7 +44,7 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitla
Get the status of export.
-```http
+```text
GET /projects/:id/export
```
@@ -53,8 +52,8 @@ GET /projects/:id/export
| --------- | -------------- | -------- | ---------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-```console
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/export
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/export
```
Status can be one of `none`, `started`, `after_export_action` or `finished`. The
@@ -86,7 +85,7 @@ to a web server, etc.
Download the finished export.
-```http
+```text
GET /projects/:id/export/download
```
@@ -94,18 +93,18 @@ GET /projects/:id/export/download
| --------- | -------------- | -------- | ---------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-```console
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --remote-header-name --remote-name https://gitlab.example.com/api/v4/projects/5/export/download
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" --remote-header-name --remote-name https://gitlab.example.com/api/v4/projects/5/export/download
```
-```console
+```sh
ls *export.tar.gz
2017-12-05_22-11-148_namespace_project_export.tar.gz
```
## Import a file
-```http
+```text
POST /projects/import
```
@@ -124,8 +123,8 @@ cURL to post data using the header `Content-Type: multipart/form-data`.
The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
-```console
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "path=api-project" --form "file=@/path/to/file" https://gitlab.example.com/api/v4/projects/import
+```sh
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "path=api-project" --form "file=@/path/to/file" https://gitlab.example.com/api/v4/projects/import
```
cURL doesn't support posting a file from a remote server. Importing a project from a remote server can be accomplished through something like the following:
@@ -145,7 +144,7 @@ data = {
"namespace": "example-group"
}
headers = {
- 'Private-Token': "9koXpg98eAheJpvBs5tK"
+ 'Private-Token': "<your_access_token>"
}
requests.post(url, headers=headers, data=data, files=files)
@@ -168,7 +167,7 @@ requests.post(url, headers=headers, data=data, files=files)
Get the status of an import.
-```http
+```text
GET /projects/:id/import
```
@@ -176,8 +175,8 @@ GET /projects/:id/import
| --------- | -------------- | -------- | ---------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-```console
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/import
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/import
```
Status can be one of `none`, `scheduled`, `failed`, `started`, or `finished`.
diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md
index 82ac0b09027..438bebe62f5 100644
--- a/doc/api/project_level_variables.md
+++ b/doc/api/project_level_variables.md
@@ -13,7 +13,7 @@ GET /projects/:id/variables
| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables"
```
```json
@@ -43,7 +43,7 @@ GET /projects/:id/variables/:key
| `key` | string | yes | The `key` of a variable |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables/TEST_VARIABLE_1"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables/TEST_VARIABLE_1"
```
```json
@@ -69,7 +69,7 @@ POST /projects/:id/variables
| `protected` | boolean | no | Whether the variable is protected |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
```
```json
@@ -96,7 +96,7 @@ PUT /projects/:id/variables/:key
| `protected` | boolean | no | Whether the variable is protected |
```
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables/NEW_VARIABLE" --form "value=updated value"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables/NEW_VARIABLE" --form "value=updated value"
```
```json
@@ -121,5 +121,5 @@ DELETE /projects/:id/variables/:key
| `key` | string | yes | The `key` of a variable |
```
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables/VARIABLE_1"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables/VARIABLE_1"
```
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index cc495c5d091..f02674adfe2 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -124,7 +124,6 @@ Parameters:
> **Notes:**
> [Introduced][ce-29508] in GitLab 9.4.
-
Available only for admins.
```
@@ -137,7 +136,7 @@ GET /projects/:id/snippets/:snippet_id/user_agent_detail
| `snippet_id` | Integer | yes | The ID of a snippet |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/snippets/2/user_agent_detail
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/snippets/2/user_agent_detail
```
Example response:
diff --git a/doc/api/project_statistics.md b/doc/api/project_statistics.md
new file mode 100644
index 00000000000..34d73abfcbf
--- /dev/null
+++ b/doc/api/project_statistics.md
@@ -0,0 +1,49 @@
+# Project statistics API
+
+Every API call to [project](../user/project/index.md) statistics must be authenticated.
+
+## Get the statistics of the last 30 days
+
+Retrieving the statistics requires write access to the repository.
+Currently only HTTP fetches statistics are returned.
+Fetches statistics includes both clones and pulls count and are HTTP only, SSH fetches are not included.
+
+```
+GET /projects/:id/statistics
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `id ` | integer / string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+
+Example response:
+
+```json
+{
+ "fetches": {
+ "total": 50,
+ "days": [
+ {
+ "count": 10,
+ "date": "2018-01-10"
+ },
+ {
+ "count": 10,
+ "date": "2018-01-09"
+ },
+ {
+ "count": 10,
+ "date": "2018-01-08"
+ },
+ {
+ "count": 10,
+ "date": "2018-01-07"
+ },
+ {
+ "count": 10,
+ "date": "2018-01-06"
+ }
+ ]
+ }
+}
+```
diff --git a/doc/api/project_templates.md b/doc/api/project_templates.md
index ef98205cd68..3b5b12c8da3 100644
--- a/doc/api/project_templates.md
+++ b/doc/api/project_templates.md
@@ -101,7 +101,6 @@ GET /projects/:id/templates/:type/:key
Example response (Dockerfile):
-
```json
{
"name": "Binary",
diff --git a/doc/api/projects.md b/doc/api/projects.md
index ef51ea20e7f..0a950352ecf 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -7,30 +7,29 @@ This is determined by the `visibility` field in the project.
Values for the project visibility level are:
-* `private`:
+- `private`:
Project access must be granted explicitly for each user.
-* `internal`:
+- `internal`:
The project can be cloned by any logged in user.
-* `public`:
+- `public`:
The project can be cloned without any authentication.
## Project merge method
There are currently three options for `merge_method` to choose from:
-* `merge`:
+- `merge`:
A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.
-* `rebase_merge`:
+- `rebase_merge`:
A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible.
This way you could make sure that if this merge request would build, after merging to target branch it would also build.
-* `ff`:
+- `ff`:
No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.
-
## List all projects
Get a list of all visible projects across GitLab for the authenticated user.
@@ -55,6 +54,7 @@ GET /projects
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
+| `with_programming_language` | string | no | Limit by projects which use the given programming language |
| `wiki_checksum_failed` | boolean | no | Limit projects where the wiki checksum calculation has failed _([Introduced][ee-6137] in [GitLab Premium][eep] 11.2)_ |
| `repository_checksum_failed` | boolean | no | Limit projects where the repository checksum calculation has failed _([Introduced][ee-6137] in [GitLab Premium][eep] 11.2)_ |
| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md) |
@@ -280,6 +280,7 @@ GET /users/:user_id/projects
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
+| `with_programming_language` | string | no | Limit by projects which use the given programming language |
| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md) |
```json
@@ -526,11 +527,13 @@ GET /projects/:id
{
"group_id": 4,
"group_name": "Twitter",
+ "group_full_path": "twitter",
"group_access_level": 30
},
{
"group_id": 3,
"group_name": "Gitlab Org",
+ "group_full_path": "gitlab-org",
"group_access_level": 10
}
],
@@ -768,6 +771,8 @@ POST /projects/:id/fork
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `namespace` | integer/string | yes | The ID or path of the namespace that the project will be forked to |
+| `path` | string | no | The path that will be assigned to the resultant project after forking |
+| `name` | string | no | The name that will be assigned to the resultant project after forking |
## List Forks of a project
@@ -798,7 +803,7 @@ GET /projects/:id/forks
| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md) |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/forks"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/forks"
```
Example responses:
@@ -878,7 +883,7 @@ POST /projects/:id/star
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/star"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/star"
```
Example response:
@@ -964,7 +969,7 @@ POST /projects/:id/unstar
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/unstar"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/unstar"
```
Example response:
@@ -1046,7 +1051,7 @@ GET /projects/:id/languages
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/languages"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/languages"
```
Example response:
@@ -1074,7 +1079,7 @@ POST /projects/:id/archive
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/archive"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/archive"
```
Example response:
@@ -1178,7 +1183,7 @@ POST /projects/:id/unarchive
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/unarchive"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/unarchive"
```
Example response:
@@ -1299,7 +1304,7 @@ The `file=` parameter must point to a file on your filesystem and be preceded
by `@`. For example:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "file=@dk.png" https://gitlab.example.com/api/v4/projects/5/uploads
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "file=@dk.png" https://gitlab.example.com/api/v4/projects/5/uploads
```
Returned object:
@@ -1345,7 +1350,7 @@ DELETE /projects/:id/share/:group_id
| `group_id` | integer | yes | The ID of the group |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/share/17
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/share/17
```
## Hooks
@@ -1513,7 +1518,7 @@ GET /projects
| `sort` | string | no | Return requests sorted in `asc` or `desc` order |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects?search=test
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects?search=test
```
## Start the Housekeeping task for a Project
diff --git a/doc/api/protected_branches.md b/doc/api/protected_branches.md
index ed8837574a0..a261bb75be5 100644
--- a/doc/api/protected_branches.md
+++ b/doc/api/protected_branches.md
@@ -5,6 +5,7 @@
**Valid access levels**
The access levels are defined in the `ProtectedRefAccess.allowed_access_levels` method. Currently, these levels are recognized:
+
```
0 => No access
30 => Developer access
@@ -24,7 +25,7 @@ GET /projects/:id/protected_branches
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_branches'
+curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/5/protected_branches'
```
Example response:
@@ -64,7 +65,7 @@ GET /projects/:id/protected_branches/:name
| `name` | string | yes | The name of the branch or wildcard |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_branches/master'
+curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/5/protected_branches/master'
```
Example response:
@@ -97,7 +98,7 @@ POST /projects/:id/protected_branches
```
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&push_access_level=30&merge_access_level=30'
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&push_access_level=30&merge_access_level=30'
```
| Attribute | Type | Required | Description |
@@ -136,7 +137,7 @@ DELETE /projects/:id/protected_branches/:name
```
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_branches/*-stable'
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/5/protected_branches/*-stable'
```
| Attribute | Type | Required | Description |
diff --git a/doc/api/protected_tags.md b/doc/api/protected_tags.md
index aa750e467f8..3adca61a108 100644
--- a/doc/api/protected_tags.md
+++ b/doc/api/protected_tags.md
@@ -25,7 +25,7 @@ GET /projects/:id/protected_tags
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_tags'
+curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/5/protected_tags'
```
Example response:
@@ -60,7 +60,7 @@ GET /projects/:id/protected_tags/:name
| `name` | string | yes | The name of the tag or wildcard |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_tags/release-1-0'
+curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/5/protected_tags/release-1-0'
```
Example response:
@@ -87,7 +87,7 @@ POST /projects/:id/protected_tags
```
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_tags?name=*-stable&create_access_level=30'
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/5/protected_tags?name=*-stable&create_access_level=30'
```
| Attribute | Type | Required | Description |
@@ -119,7 +119,7 @@ DELETE /projects/:id/protected_tags/:name
```
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/5/protected_tags/*-stable'
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/5/protected_tags/*-stable'
```
| Attribute | Type | Required | Description |
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
new file mode 100644
index 00000000000..e7f79a0d359
--- /dev/null
+++ b/doc/api/releases/index.md
@@ -0,0 +1,482 @@
+# Releases API
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41766) in GitLab 11.7.
+> - Using this API you can manipulate GitLab's [Release](../../user/project/releases/index.md) entries.
+> - For manipulating links as a release asset, see [Release Links API](links.md).
+
+## List Releases
+
+Paginated list of Releases, sorted by `created_at`.
+
+```
+GET /projects/:id/releases
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
+
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "http://localhost:3000/api/v4/projects/24/releases"
+```
+
+Example response:
+
+```json
+[
+ {
+ "tag_name":"v0.2",
+ "description":"## CHANGELOG\r\n\r\n- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740\r\n- Prevent private snippets from being embeddable.\r\n- Add subresources removal to member destroy service.",
+ "name":"Awesome app v0.2 beta",
+ "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eEscape label and milestone titles to prevent XSS in GFM autocomplete. !2740\u003c/li\u003e\n\u003cli\u003ePrevent private snippets from being embeddable.\u003c/li\u003e\n\u003cli\u003eAdd subresources removal to member destroy service.\u003c/li\u003e\n\u003c/ul\u003e",
+ "created_at":"2019-01-03T01:56:19.539Z",
+ "author":{
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url":"http://localhost:3000/root"
+ },
+ "commit":{
+ "id":"079e90101242458910cccd35eab0e211dfc359c0",
+ "short_id":"079e9010",
+ "title":"Update README.md",
+ "created_at":"2019-01-03T01:55:38.000Z",
+ "parent_ids":[
+ "f8d3d94cbd347e924aa7b715845e439d00e80ca4"
+ ],
+ "message":"Update README.md",
+ "author_name":"Administrator",
+ "author_email":"admin@example.com",
+ "authored_date":"2019-01-03T01:55:38.000Z",
+ "committer_name":"Administrator",
+ "committer_email":"admin@example.com",
+ "committed_date":"2019-01-03T01:55:38.000Z"
+ },
+ "assets":{
+ "count":6,
+ "sources":[
+ {
+ "format":"zip",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.zip"
+ },
+ {
+ "format":"tar.gz",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.gz"
+ },
+ {
+ "format":"tar.bz2",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.bz2"
+ },
+ {
+ "format":"tar",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar"
+ }
+ ],
+ "links":[
+ {
+ "id":2,
+ "name":"awesome-v0.2.msi",
+ "url":"http://192.168.10.15:3000/msi",
+ "external":true
+ },
+ {
+ "id":1,
+ "name":"awesome-v0.2.dmg",
+ "url":"http://192.168.10.15:3000",
+ "external":true
+ }
+ ]
+ }
+ },
+ {
+ "tag_name":"v0.1",
+ "description":"## CHANGELOG\r\n\r\n-Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516",
+ "name":"Awesome app v0.1 alpha",
+ "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e",
+ "created_at":"2019-01-03T01:55:18.203Z",
+ "author":{
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url":"http://localhost:3000/root"
+ },
+ "commit":{
+ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4",
+ "short_id":"f8d3d94c",
+ "title":"Initial commit",
+ "created_at":"2019-01-03T01:53:28.000Z",
+ "parent_ids":[
+
+ ],
+ "message":"Initial commit",
+ "author_name":"Administrator",
+ "author_email":"admin@example.com",
+ "authored_date":"2019-01-03T01:53:28.000Z",
+ "committer_name":"Administrator",
+ "committer_email":"admin@example.com",
+ "committed_date":"2019-01-03T01:53:28.000Z"
+ },
+ "assets":{
+ "count":4,
+ "sources":[
+ {
+ "format":"zip",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip"
+ },
+ {
+ "format":"tar.gz",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz"
+ },
+ {
+ "format":"tar.bz2",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2"
+ },
+ {
+ "format":"tar",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar"
+ }
+ ],
+ "links":[
+
+ ]
+ }
+ }
+]
+```
+
+## Get a Release by a tag name
+
+Get a Release for the given tag.
+
+```
+GET /projects/:id/releases/:tag_name
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag where the release will be created from. |
+
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "http://localhost:3000/api/v4/projects/24/releases/v0.1"
+```
+
+Example response:
+
+```json
+{
+ "tag_name":"v0.1",
+ "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516",
+ "name":"Awesome app v0.1 alpha",
+ "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e",
+ "created_at":"2019-01-03T01:55:18.203Z",
+ "author":{
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url":"http://localhost:3000/root"
+ },
+ "commit":{
+ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4",
+ "short_id":"f8d3d94c",
+ "title":"Initial commit",
+ "created_at":"2019-01-03T01:53:28.000Z",
+ "parent_ids":[
+
+ ],
+ "message":"Initial commit",
+ "author_name":"Administrator",
+ "author_email":"admin@example.com",
+ "authored_date":"2019-01-03T01:53:28.000Z",
+ "committer_name":"Administrator",
+ "committer_email":"admin@example.com",
+ "committed_date":"2019-01-03T01:53:28.000Z"
+ },
+ "assets":{
+ "count":4,
+ "sources":[
+ {
+ "format":"zip",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip"
+ },
+ {
+ "format":"tar.gz",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz"
+ },
+ {
+ "format":"tar.bz2",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2"
+ },
+ {
+ "format":"tar",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar"
+ }
+ ],
+ "links":[
+
+ ]
+ }
+}
+```
+
+## Create a release
+
+Create a Release. You need push access to the repository to create a Release.
+
+```
+POST /projects/:id/releases
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
+| `name` | string | yes | The release name. |
+| `tag_name` | string | yes | The tag where the release will be created from. |
+| `description` | string | yes | The description of the release. You can use [markdown](../../user/markdown.md). |
+| `ref` | string | no | If `tag_name` doesn't exist, the release will be created from `ref`. It can be a commit SHA, another tag name, or a branch name. |
+| `assets:links`| array of hash | no | An array of assets links. |
+| `assets:links:name`| string | no (if `assets:links` specified, it's required) | The name of the link. |
+| `assets:links:url`| string | no (if `assets:links` specified, it's required) | The url of the link. |
+
+Example request:
+
+```sh
+curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" \
+ --data '{ "name": "New release", "tag_name": "v0.3", "description": "Super nice release", "assets": { "links": [{ "name": "hoge", "url": "https://google.com" }] } }' \
+ --request POST http://localhost:3000/api/v4/projects/24/releases
+```
+
+Example response:
+
+```json
+{
+ "tag_name":"v0.3",
+ "description":"Super nice release",
+ "name":"New release",
+ "description_html":"\u003cp dir=\"auto\"\u003eSuper nice release\u003c/p\u003e",
+ "created_at":"2019-01-03T02:22:45.118Z",
+ "author":{
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url":"http://localhost:3000/root"
+ },
+ "commit":{
+ "id":"079e90101242458910cccd35eab0e211dfc359c0",
+ "short_id":"079e9010",
+ "title":"Update README.md",
+ "created_at":"2019-01-03T01:55:38.000Z",
+ "parent_ids":[
+ "f8d3d94cbd347e924aa7b715845e439d00e80ca4"
+ ],
+ "message":"Update README.md",
+ "author_name":"Administrator",
+ "author_email":"admin@example.com",
+ "authored_date":"2019-01-03T01:55:38.000Z",
+ "committer_name":"Administrator",
+ "committer_email":"admin@example.com",
+ "committed_date":"2019-01-03T01:55:38.000Z"
+ },
+ "assets":{
+ "count":5,
+ "sources":[
+ {
+ "format":"zip",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.zip"
+ },
+ {
+ "format":"tar.gz",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.tar.gz"
+ },
+ {
+ "format":"tar.bz2",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.tar.bz2"
+ },
+ {
+ "format":"tar",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.3/awesome-app-v0.3.tar"
+ }
+ ],
+ "links":[
+ {
+ "id":3,
+ "name":"hoge",
+ "url":"https://google.com",
+ "external":true
+ }
+ ]
+ }
+}
+```
+
+## Update a release
+
+Update a Release.
+
+```
+PUT /projects/:id/releases/:tag_name
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag where the release will be created from. |
+| `name` | string | no | The release name. |
+| `description` | string | no | The description of the release. You can use [markdown](../../user/markdown.md). |
+
+Example request:
+
+```sh
+curl --request PUT --data name="new name" --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "http://localhost:3000/api/v4/projects/24/releases/v0.1"
+```
+
+Example response:
+
+```json
+{
+ "tag_name":"v0.1",
+ "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516",
+ "name":"new name",
+ "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e",
+ "created_at":"2019-01-03T01:55:18.203Z",
+ "author":{
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url":"http://localhost:3000/root"
+ },
+ "commit":{
+ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4",
+ "short_id":"f8d3d94c",
+ "title":"Initial commit",
+ "created_at":"2019-01-03T01:53:28.000Z",
+ "parent_ids":[
+
+ ],
+ "message":"Initial commit",
+ "author_name":"Administrator",
+ "author_email":"admin@example.com",
+ "authored_date":"2019-01-03T01:53:28.000Z",
+ "committer_name":"Administrator",
+ "committer_email":"admin@example.com",
+ "committed_date":"2019-01-03T01:53:28.000Z"
+ },
+ "assets":{
+ "count":4,
+ "sources":[
+ {
+ "format":"zip",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip"
+ },
+ {
+ "format":"tar.gz",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz"
+ },
+ {
+ "format":"tar.bz2",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2"
+ },
+ {
+ "format":"tar",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar"
+ }
+ ],
+ "links":[
+
+ ]
+ }
+}
+```
+
+## Delete a Release
+
+Delete a Release. Deleting a Release will not delete the associated tag.
+
+```
+DELETE /projects/:id/releases/:tag_name
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag where the release will be created from. |
+
+Example request:
+
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "http://localhost:3000/api/v4/projects/24/releases/v0.1"
+```
+
+Example response:
+
+```json
+{
+ "tag_name":"v0.1",
+ "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516",
+ "name":"new name",
+ "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e",
+ "created_at":"2019-01-03T01:55:18.203Z",
+ "author":{
+ "id":1,
+ "name":"Administrator",
+ "username":"root",
+ "state":"active",
+ "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url":"http://localhost:3000/root"
+ },
+ "commit":{
+ "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4",
+ "short_id":"f8d3d94c",
+ "title":"Initial commit",
+ "created_at":"2019-01-03T01:53:28.000Z",
+ "parent_ids":[
+
+ ],
+ "message":"Initial commit",
+ "author_name":"Administrator",
+ "author_email":"admin@example.com",
+ "authored_date":"2019-01-03T01:53:28.000Z",
+ "committer_name":"Administrator",
+ "committer_email":"admin@example.com",
+ "committed_date":"2019-01-03T01:53:28.000Z"
+ },
+ "assets":{
+ "count":4,
+ "sources":[
+ {
+ "format":"zip",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip"
+ },
+ {
+ "format":"tar.gz",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz"
+ },
+ {
+ "format":"tar.bz2",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2"
+ },
+ {
+ "format":"tar",
+ "url":"http://localhost:3000/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar"
+ }
+ ],
+ "links":[
+
+ ]
+ }
+}
+```
diff --git a/doc/api/releases/links.md b/doc/api/releases/links.md
new file mode 100644
index 00000000000..fd7b9d6e6e2
--- /dev/null
+++ b/doc/api/releases/links.md
@@ -0,0 +1,178 @@
+# Release links API
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41766) in GitLab 11.7.
+
+Using this API you can manipulate GitLab's [Release](../../user/project/releases/index.md) links. For manipulating other Release assets, see [Release API](index.md).
+GitLab supports links links to `http`, `https`, and `ftp` assets.
+
+## Get links
+
+Get assets as links from a Release.
+
+```
+GET /projects/:id/releases/:tag_name/assets/links
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag associated with the Release. |
+
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "http://localhost:3000/api/v4/projects/24/releases/v0.1/assets/links"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id":2,
+ "name":"awesome-v0.2.msi",
+ "url":"http://192.168.10.15:3000/msi",
+ "external":true
+ },
+ {
+ "id":1,
+ "name":"awesome-v0.2.dmg",
+ "url":"http://192.168.10.15:3000",
+ "external":true
+ }
+]
+```
+
+## Get a link
+
+Get an asset as a link from a Release.
+
+```
+GET /projects/:id/releases/:tag_name/assets/links/:link_id
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag associated with the Release. |
+| `link_id` | integer | yes | The id of the link. |
+
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "http://localhost:3000/api/v4/projects/24/releases/v0.1/assets/links/1"
+```
+
+Example response:
+
+```json
+{
+ "id":1,
+ "name":"awesome-v0.2.dmg",
+ "url":"http://192.168.10.15:3000",
+ "external":true
+}
+```
+
+## Create a link
+
+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](README.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag associated with the Release. |
+| `name` | string | yes | The name of the link. |
+| `url` | string | yes | The URL of the link. |
+
+Example request:
+
+```sh
+curl --request POST \
+ --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" \
+ --data name="awesome-v0.2.dmg" \
+ --data url="http://192.168.10.15:3000" \
+ "http://localhost:3000/api/v4/projects/24/releases/v0.1/assets/links"
+```
+
+Example response:
+
+```json
+{
+ "id":1,
+ "name":"awesome-v0.2.dmg",
+ "url":"http://192.168.10.15:3000",
+ "external":true
+}
+```
+
+## Update a link
+
+Update an asset as a link from a Release.
+
+```
+PUT /projects/:id/releases/:tag_name/assets/links/:link_id
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag associated with the Release. |
+| `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. |
+
+NOTE: **NOTE**
+You have to specify at least one of `name` or `url`
+
+Example request:
+
+```sh
+curl --request PUT --data name="new name" --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "http://localhost:3000/api/v4/projects/24/releases/v0.1/assets/links/1"
+```
+
+Example response:
+
+```json
+{
+ "id":1,
+ "name":"new name",
+ "url":"http://192.168.10.15:3000",
+ "external":true
+}
+```
+
+## Delete a link
+
+Delete an asset as a link from a Release.
+
+```
+DELETE /projects/:id/releases/:tag_name/assets/links/:link_id
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag associated with the Release. |
+| `link_id` | integer | yes | The id of the link. |
+
+Example request:
+
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "http://localhost:3000/api/v4/projects/24/releases/v0.1/assets/links/1"
+```
+
+Example response:
+
+```json
+{
+ "id":1,
+ "name":"new name",
+ "url":"http://192.168.10.15:3000",
+ "external":true
+}
+```
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 55f5a4cc3b2..681dc72c934 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -112,14 +112,18 @@ GET /projects/:id/repository/archive[.format]
```
`format` is an optional suffix for the archive format. Default is
-`tar.gz`. Options are `tar.gz`, `tar.bz2`, `tbz`, 'tbz2`, `tb2`,
+`tar.gz`. Options are `tar.gz`, `tar.bz2`, `tbz`, `tbz2`, `tb2`,
`bz2`, `tar`, and `zip`. For example, specifying `archive.zip`
would send an archive in ZIP format.
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `sha` (optional) - The commit SHA to download. A tag, branch reference or sha can be used. This defaults to the tip of the default branch if not specified
+- `sha` (optional) - The commit SHA to download. A tag, branch reference, or SHA can be used. This defaults to the tip of the default branch if not specified. For example:
+
+ ```sh
+ curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.com/api/v4/projects/<project_id>/repository/archive?sha=<commit_sha>
+ ```
## Compare branches, tags or commits
@@ -212,7 +216,7 @@ Response:
## Merge Base
-Get the common ancestor for 2 refs (commit SHAs, branch names or tags).
+Get the common ancestor for 2 or more refs (commit SHAs, branch names or tags).
```
GET /projects/:id/repository/merge_base
@@ -224,7 +228,7 @@ GET /projects/:id/repository/merge_base
| `refs` | array | yes | The refs to find the common ancestor of, multiple refs can be passed |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/merge_base?refs[]=304d257dcb821665ab5110318fc58a007bd104ed&refs[]=0031876facac3f2b2702a0e53a26e89939a42209"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/merge_base?refs[]=304d257dcb821665ab5110318fc58a007bd104ed&refs[]=0031876facac3f2b2702a0e53a26e89939a42209"
```
Example response:
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index 5f587f480b6..6fcc06ea8cd 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -25,7 +25,7 @@ GET /projects/:id/repository/files/:file_path
```
```bash
-curl --request GET --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master'
+curl --request GET --header 'PRIVATE-TOKEN: <your_access_token>' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master'
```
Example response:
@@ -60,7 +60,7 @@ HEAD /projects/:id/repository/files/:file_path
```
```bash
-curl --head --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master'
+curl --head --header 'PRIVATE-TOKEN: <your_access_token>' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master'
```
Example response:
@@ -87,7 +87,7 @@ GET /projects/:id/repository/files/:file_path/raw
```
```bash
-curl --request GET --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw?ref=master'
+curl --request GET --header 'PRIVATE-TOKEN: <your_access_token>' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw?ref=master'
```
Parameters:
@@ -107,7 +107,7 @@ POST /projects/:id/repository/files/:file_path
```
```bash
-curl --request POST --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' --header "Content-Type: application/json" \
+curl --request POST --header 'PRIVATE-TOKEN: <your_access_token>' --header "Content-Type: application/json" \
--data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
"content": "some content", "commit_message": "create a new file"}' \
'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb'
@@ -142,7 +142,7 @@ PUT /projects/:id/repository/files/:file_path
```
```bash
-curl --request PUT --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' --header "Content-Type: application/json" \
+curl --request PUT --header 'PRIVATE-TOKEN: <your_access_token>' --header "Content-Type: application/json" \
--data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
"content": "some content", "commit_message": "update file"}' \
'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb'
@@ -171,6 +171,7 @@ Parameters:
If the commit fails for any reason we return a 400 error with a non-specific
error message. Possible causes for a failed commit include:
+
- the `file_path` contained `/../` (attempted directory traversal);
- the new file contents were identical to the current file contents, i.e. the
user tried to make an empty commit;
@@ -187,7 +188,7 @@ DELETE /projects/:id/repository/files/:file_path
```
```bash
-curl --request DELETE --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' --header "Content-Type: application/json" \
+curl --request DELETE --header 'PRIVATE-TOKEN: <your_access_token>' --header "Content-Type: application/json" \
--data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
"commit_message": "delete file"}' \
'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb'
diff --git a/doc/api/repository_submodules.md b/doc/api/repository_submodules.md
index 11b04c81172..2c44c4abc93 100644
--- a/doc/api/repository_submodules.md
+++ b/doc/api/repository_submodules.md
@@ -22,7 +22,7 @@ PUT /projects/:id/repository/submodules/:submodule
| `commit_message` | string | no | Commit message. If no message is provided, a default one will be set |
```sh
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/submodules/lib%2Fmodules%2Fexample"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/submodules/lib%2Fmodules%2Fexample"
--data "branch=master&commit_sha=3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88&commit_message=Update submodule reference"
```
diff --git a/doc/api/resource_label_events.md b/doc/api/resource_label_events.md
index 33e4821ccf4..e1f9ffa9472 100644
--- a/doc/api/resource_label_events.md
+++ b/doc/api/resource_label_events.md
@@ -65,7 +65,7 @@ GET /projects/:id/issues/:issue_iid/resource_label_events
```
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/resource_label_events
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/resource_label_events
```
### Get single issue label event
@@ -85,7 +85,7 @@ Parameters:
| `resource_label_event_id` | integer | yes | The ID of a label event |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/resource_label_events/1
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/resource_label_events/1
```
## Merge requests
@@ -151,7 +151,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/resource_label_events
```
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_label_events
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_label_events
```
### Get single merge request label event
@@ -171,5 +171,5 @@ Parameters:
| `resource_label_event_id` | integer | yes | The ID of a label event |
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_label_events/120
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/resource_label_events/120
```
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 071c13f41cb..7d7215e6b80 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -13,16 +13,18 @@ GET /runners
GET /runners?scope=active
GET /runners?type=project_type
GET /runners?status=active
+GET /runners?tag_list=tag1,tag2
```
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
-| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
-| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
-| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|---------------------|
+| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
+| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
+| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
+| `tag_list` | Array[String] | no | List of of the runner's tags |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners"
```
Example response:
@@ -62,16 +64,18 @@ GET /runners/all
GET /runners/all?scope=online
GET /runners/all?type=project_type
GET /runners/all?status=active
+GET /runners/all?tag_list=tag1,tag2
```
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
-| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online`, `offline`; showing all runners if none provided |
-| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
-| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|---------------------|
+| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online`, `offline`; showing all runners if none provided |
+| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
+| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
+| `tag_list` | Array[String] | no | List of of the runner's tags |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/all"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/all"
```
Example response:
@@ -134,7 +138,7 @@ GET /runners/:id
| `id` | integer | yes | The ID of a runner |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/6"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/6"
```
Example response:
@@ -193,7 +197,7 @@ PUT /runners/:id
| `maximum_timeout` | integer | no | Maximum timeout set when this Runner will handle the job |
```
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/6" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/6" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2"
```
Example response:
@@ -247,7 +251,7 @@ DELETE /runners/:id
| `id` | integer | yes | The ID of a runner |
```
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/6"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/6"
```
## List runner's jobs
@@ -264,7 +268,7 @@ GET /runners/:id/jobs
| `status` | string | no | Status of the job; one of: `running`, `success`, `failed`, `canceled` |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/1/jobs?status=running"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/1/jobs?status=running"
```
Example response:
@@ -347,17 +351,19 @@ GET /projects/:id/runners
GET /projects/:id/runners?scope=active
GET /projects/:id/runners?type=project_type
GET /projects/:id/runners?status=active
+GET /projects/:id/runners?tag_list=tag1,tag2
```
-| Attribute | Type | Required | Description |
-|-----------|----------------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
-| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
-| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
+| Attribute | Type | Required | Description |
+|------------|----------------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
+| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
+| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
+| `tag_list` | Array[String] | no | List of of the runner's tags |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/9/runners"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/9/runners"
```
Example response:
@@ -401,7 +407,7 @@ POST /projects/:id/runners
| `runner_id` | integer | yes | The ID of a runner |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/9/runners" --form "runner_id=9"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/9/runners" --form "runner_id=9"
```
Example response:
@@ -435,7 +441,7 @@ DELETE /projects/:id/runners/:runner_id
| `runner_id` | integer | yes | The ID of a runner |
```
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/9/runners/9"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/9/runners/9"
```
## Register a new Runner
@@ -478,7 +484,7 @@ Example response:
## Delete a registered Runner
-Deletes a registed Runner.
+Deletes a registered Runner.
```
DELETE /runners
diff --git a/doc/api/search.md b/doc/api/search.md
index 7e3ae7404a3..aa601648b2c 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -24,7 +24,7 @@ The response depends on the requested scope.
### Scope: projects
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/search?scope=projects&search=flight
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=projects&search=flight
```
Example response:
@@ -55,7 +55,7 @@ Example response:
### Scope: issues
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/search?scope=issues&search=file
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=issues&search=file
```
Example response:
@@ -120,7 +120,7 @@ Example response:
### Scope: merge_requests
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/search?scope=merge_requests&search=file
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=merge_requests&search=file
```
Example response:
@@ -197,7 +197,7 @@ Example response:
### Scope: milestones
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/search?scope=milestones&search=release
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=milestones&search=release
```
Example response:
@@ -222,7 +222,7 @@ Example response:
### Scope: snippet_titles
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/search?scope=snippet_titles&search=sample
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=snippet_titles&search=sample
```
Example response:
@@ -253,7 +253,7 @@ Example response:
### Scope: snippet_blobs
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/search?scope=snippet_blos&search=test
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=snippet_blos&search=test
```
Example response:
@@ -281,7 +281,6 @@ Example response:
]
```
-
## Group Search API
Search within the specified group.
@@ -305,7 +304,7 @@ The response depends on the requested scope.
### Scope: projects
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/3/search?scope=projects&search=flight
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/3/search?scope=projects&search=flight
```
Example response:
@@ -336,7 +335,7 @@ Example response:
### Scope: issues
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/3/search?scope=issues&search=file
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/3/search?scope=issues&search=file
```
Example response:
@@ -401,7 +400,7 @@ Example response:
### Scope: merge_requests
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/3/search?scope=merge_requests&search=file
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/3/search?scope=merge_requests&search=file
```
Example response:
@@ -478,7 +477,7 @@ Example response:
### Scope: milestones
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/3/search?scope=milestones&search=release
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/3/search?scope=milestones&search=release
```
Example response:
@@ -520,11 +519,10 @@ Search the expression within the specified scope. Currently these scopes are sup
The response depends on the requested scope.
-
### Scope: issues
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/12/search?scope=issues&search=file
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/12/search?scope=issues&search=file
```
Example response:
@@ -589,7 +587,7 @@ Example response:
### Scope: merge_requests
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/6/search?scope=merge_requests&search=file
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/6/search?scope=merge_requests&search=file
```
Example response:
@@ -666,7 +664,7 @@ Example response:
### Scope: milestones
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/12/search?scope=milestones&search=release
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/12/search?scope=milestones&search=release
```
Example response:
@@ -691,7 +689,7 @@ Example response:
### Scope: notes
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/6/search?scope=notes&search=maxime
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/6/search?scope=notes&search=maxime
```
Example response:
@@ -740,7 +738,7 @@ results:
times in the content.
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/6/search?scope=wiki_blobs&search=bye
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/6/search?scope=wiki_blobs&search=bye
```
Example response:
@@ -763,7 +761,7 @@ Example response:
### Scope: commits
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/6/search?scope=commits&search=bye
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/6/search?scope=commits&search=bye
```
Example response:
@@ -810,7 +808,7 @@ Blobs searches are performed on both filenames and contents. Search results:
times in the content.
```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/6/search?scope=blobs&search=installation
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/6/search?scope=blobs&search=installation
```
Example response:
diff --git a/doc/api/services.md b/doc/api/services.md
index f122bac6f1f..c44f5cc5781 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -412,7 +412,7 @@ Google GSuite team collaboration tool.
Set Hangouts Chat service for a project.
```
-PUT /projects/:id/services/hangouts_chat
+PUT /projects/:id/services/hangouts-chat
```
>**Note:** Specific event parameters (e.g. `push_events` flag) were [introduced in v10.4][11435]
@@ -438,7 +438,7 @@ Parameters:
Delete Hangouts Chat service for a project.
```
-DELETE /projects/:id/services/hangouts_chat
+DELETE /projects/:id/services/hangouts-chat
```
### Get Hangouts Chat service settings
@@ -446,46 +446,7 @@ DELETE /projects/:id/services/hangouts_chat
Get Hangouts Chat service settings for a project.
```
-GET /projects/:id/services/hangouts_chat
-```
-
-## HipChat
-
-Private group chat and IM
-
-### Create/Edit HipChat service
-
-Set HipChat service for a project.
-
-```
-PUT /projects/:id/services/hipchat
-```
-
-Parameters:
-
-| Parameter | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `token` | string | true | Room token |
-| `color` | string | false | The room color |
-| `notify` | boolean | false | Enable notifications |
-| `room` | string | false |Room name or ID |
-| `api_version` | string | false | Leave blank for default (v2) |
-| `server` | string | false | Leave blank for default. For example, `https://hipchat.example.com`. |
-
-### Delete HipChat service
-
-Delete HipChat service for a project.
-
-```
-DELETE /projects/:id/services/hipchat
-```
-
-### Get HipChat service settings
-
-Get HipChat service settings for a project.
-
-```
-GET /projects/:id/services/hipchat
+GET /projects/:id/services/hangouts-chat
```
## Irker (IRC gateway)
@@ -561,6 +522,7 @@ Parameters:
| `project_key` | string | yes | The short identifier for your JIRA project, all uppercase, e.g., `PROJ`. |
| `username` | string | yes | The username of the user created to be used with GitLab/JIRA. |
| `password` | string | yes | The password of the user created to be used with GitLab/JIRA. |
+| `active` | boolean | no | Activates or deactivates the service. Defaults to false (deactivated). |
| `jira_issue_transition_id` | integer | no | The ID of a transition that moves issues to a closed state. You can find this number under the JIRA workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`. |
### Delete JIRA service
@@ -573,7 +535,7 @@ DELETE /projects/:id/services/jira
## Kubernetes
-Kubernetes / Openshift integration
+Kubernetes / OpenShift integration
CAUTION: **Warning:**
Kubernetes service integration has been deprecated in GitLab 10.3. API service endpoints will continue to work as long as the Kubernetes service is active, however if the service is inactive API endpoints will automatically return a `400 Bad Request`. Read [GitLab 10.3 release post](https://about.gitlab.com/2017/12/22/gitlab-10-3-released/#kubernetes-integration-service) for more information.
@@ -639,7 +601,7 @@ Example response:
"job_events": true,
"pipeline_events": true,
"properties": {
- "token": "9koXpg98eAheJpvBs5tK"
+ "token": "<your_access_token>"
}
}
```
@@ -1140,3 +1102,39 @@ GET /projects/:id/services/mock-ci
```
[11435]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11435
+
+## YouTrack
+
+YouTrack issue tracker
+
+### Create/Edit YouTrack service
+
+Set YouTrack service for a project.
+
+```
+PUT /projects/:id/services/youtrack
+```
+
+Parameters:
+
+| Parameter | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `issues_url` | string | true | Issue url |
+| `project_url` | string | true | Project url |
+| `description` | string | false | Description |
+
+### Delete YouTrack Service
+
+Delete YouTrack service for a project.
+
+```
+DELETE /projects/:id/services/youtrack
+```
+
+### Get YouTrack Service Settings
+
+Get YouTrack service settings for a project.
+
+```
+GET /projects/:id/services/youtrack
+```
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 9b38e3a4eb7..c2a1f7feefd 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -19,7 +19,7 @@ GET /application/settings
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/application/settings
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/application/settings
```
Example response:
@@ -57,11 +57,13 @@ Example response:
"dsa_key_restriction": 0,
"ecdsa_key_restriction": 0,
"ed25519_key_restriction": 0,
+ "first_day_of_week": 0,
"enforce_terms": true,
"terms": "Hello world!",
"performance_bar_allowed_group_id": 42,
"instance_statistics_visibility_private": false,
- "user_show_add_ssh_key_message": true
+ "user_show_add_ssh_key_message": true,
+ "local_markdown_version": 0
}
```
@@ -75,7 +77,7 @@ PUT /application/settings
```
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/application/settings?signup_enabled=false&default_project_visibility=internal
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/application/settings?signup_enabled=false&default_project_visibility=internal
```
Example response:
@@ -113,11 +115,13 @@ Example response:
"dsa_key_restriction": 0,
"ecdsa_key_restriction": 0,
"ed25519_key_restriction": 0,
+ "first_day_of_week": 0,
"enforce_terms": true,
"terms": "Hello world!",
"performance_bar_allowed_group_id": 42,
"instance_statistics_visibility_private": false,
- "user_show_add_ssh_key_message": true
+ "user_show_add_ssh_key_message": true,
+ "local_markdown_version": 0
}
```
@@ -157,6 +161,7 @@ are listed in the descriptions of the relevant settings.
| `email_author_in_body` | boolean | no | Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead. |
| `enabled_git_access_protocol` | string | no | Enabled protocols for Git access. Allowed values are: `ssh`, `http`, and `nil` to allow both protocols. |
| `enforce_terms` | boolean | no | (**If enabled, requires:** `terms`) Enforce application ToS to all users. |
+| `first_day_of_week` | integer | no | Start day of the week for calendar views and date pickers. Valid values are `0` (default) for Sunday, `1` for Monday, and `6` for Saturday. |
| `gitaly_timeout_default` | integer | no | Default Gitaly timeout, in seconds. This timeout is not enforced for git fetch/push operations or Sidekiq jobs. Set to `0` to disable timeouts. |
| `gitaly_timeout_fast` | integer | no | Gitaly fast operation timeout, in seconds. Some Gitaly operations are expected to be fast. If they exceed this threshold, there may be a problem with a storage shard and 'failing fast' can help maintain the stability of the GitLab instance. Set to `0` to disable timeouts. |
| `gitaly_timeout_medium` | integer | no | Medium Gitaly timeout, in seconds. This should be a value between the Fast and the Default timeout. Set to `0` to disable timeouts. |
@@ -208,7 +213,7 @@ are listed in the descriptions of the relevant settings.
| `rsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded RSA key. Default is `0` (no restriction). `-1` disables RSA keys. |
| `send_user_confirmation_email` | boolean | no | Send confirmation email on sign-up. |
| `sentry_dsn` | string | required by: `sentry_enabled` | Sentry Data Source Name. |
-| `sentry_enabled` | boolean | no | (**If enabled, requires:** `sentry_dsn`) Sentry is an error reporting and logging tool which is currently not shipped with GitLab, available at https://getsentry.com. |
+| `sentry_enabled` | boolean | no | (**If enabled, requires:** `sentry_dsn`) Sentry is an error reporting and logging tool which is currently not shipped with GitLab, available at <https://sentry.io>. |
| `session_expire_delay` | integer | no | Session duration in minutes. GitLab restart is required to apply changes |
| `shared_runners_enabled` | boolean | no | (**If enabled, requires:** `shared_runners_text`) Enable shared runners for new projects. |
| `shared_runners_text` | string | required by: `shared_runners_enabled` | Shared runners text. |
@@ -235,3 +240,4 @@ are listed in the descriptions of the relevant settings.
| `user_oauth_applications` | boolean | no | Allow users to register any application to use GitLab as an OAuth provider. |
| `user_show_add_ssh_key_message` | boolean | no | When set to `false` disable the "You won't be able to pull or push project code via SSH" warning shown to users with no uploaded SSH key. |
| `version_check_enabled` | boolean | no | Let GitLab inform you when an update is available. |
+| `local_markdown_version` | integer | no | Increase this value when any cached markdown should be invalidated. |
diff --git a/doc/api/sidekiq_metrics.md b/doc/api/sidekiq_metrics.md
index b9500916cf2..5f2202fa51d 100644
--- a/doc/api/sidekiq_metrics.md
+++ b/doc/api/sidekiq_metrics.md
@@ -15,7 +15,7 @@ GET /sidekiq/queue_metrics
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/sidekiq/queue_metrics
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/sidekiq/queue_metrics
```
Example response:
@@ -40,7 +40,7 @@ GET /sidekiq/process_metrics
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/sidekiq/process_metrics
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/sidekiq/process_metrics
```
Example response:
@@ -82,7 +82,7 @@ GET /sidekiq/job_stats
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/sidekiq/job_stats
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/sidekiq/job_stats
```
Example response:
@@ -106,7 +106,7 @@ GET /sidekiq/compound_metrics
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/sidekiq/compound_metrics
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/sidekiq/compound_metrics
```
Example response:
@@ -149,4 +149,3 @@ Example response:
}
}
```
-
diff --git a/doc/api/snippets.md b/doc/api/snippets.md
index e840e640377..f90447e124e 100644
--- a/doc/api/snippets.md
+++ b/doc/api/snippets.md
@@ -1,44 +1,101 @@
# Snippets API
-> [Introduced][ce-6373] in GitLab 8.15.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6373) in GitLab 8.15.
+
+Snippets API operates on [snippets](../user/snippets.md).
## Snippet visibility level
Snippets in GitLab can be either private, internal, or public.
You can set it with the `visibility` field in the snippet.
-Constants for snippet visibility levels are:
+Valid values for snippet visibility levels are:
-| Visibility | Description |
-| ---------- | ----------- |
-| `private` | The snippet is visible only to the snippet creator |
-| `internal` | The snippet is visible for any logged in user |
-| `public` | The snippet can be accessed without any authentication |
+| Visibility | Description |
+|:-----------|:----------------------------------------------------|
+| `private` | Snippet is visible only to the snippet creator. |
+| `internal` | Snippet is visible for any logged in user. |
+| `public` | Snippet can be accessed without any authentication. |
-## List snippets
+## List all snippets for a user
-Get a list of current user's snippets.
+Get a list of the current user's snippets.
-```
+```text
GET /snippets
```
-## Single snippet
+Example request:
-Get a single snippet.
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/snippets
+```
+
+Example response:
+```json
+[
+ {
+ "id": 42,
+ "title": "Voluptatem iure ut qui aut et consequatur quaerat.",
+ "file_name": "mclaughlin.rb",
+ "description": null,
+ "visibility": "internal",
+ "author": {
+ "id": 22,
+ "name": "User 0",
+ "username": "user0",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80&d=identicon",
+ "web_url": "http://localhost:3000/user0"
+ },
+ "updated_at": "2018-09-18T01:12:26.383Z",
+ "created_at": "2018-09-18T01:12:26.383Z",
+ "project_id": null,
+ "web_url": "http://localhost:3000/snippets/42",
+ "raw_url": "http://localhost:3000/snippets/42/raw"
+ },
+ {
+ "id": 41,
+ "title": "Ut praesentium non et atque.",
+ "file_name": "ondrickaemard.rb",
+ "description": null,
+ "visibility": "internal",
+ "author": {
+ "id": 22,
+ "name": "User 0",
+ "username": "user0",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80&d=identicon",
+ "web_url": "http://localhost:3000/user0"
+ },
+ "updated_at": "2018-09-18T01:12:26.360Z",
+ "created_at": "2018-09-18T01:12:26.360Z",
+ "project_id": null,
+ "web_url": "http://localhost:3000/snippets/41",
+ "raw_url": "http://localhost:3000/snippets/41/raw"
+ }
+]
```
+
+## Get a single snippet
+
+Get a single snippet.
+
+```text
GET /snippets/:id
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | Integer | yes | The ID of a snippet |
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:---------------------------|
+| `id` | integer | yes | ID of snippet to retrieve. |
+
+Example request:
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/1
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/snippets/1
```
Example response:
@@ -69,46 +126,52 @@ Example response:
Get a single snippet's raw contents.
-```
+```text
GET /snippets/:id/raw
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | Integer | yes | The ID of a snippet |
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:---------------------------|
+| `id` | integer | yes | ID of snippet to retrieve. |
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/1/raw
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/snippets/1/raw
```
Example response:
-```
+```text
Hello World snippet
```
## Create new snippet
-Creates a new snippet. The user must have permission to create new snippets.
+Create a new snippet.
-```
+NOTE: **Note:**
+The user must have permission to create new snippets.
+
+```text
POST /snippets
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `title` | String | yes | The title of a snippet |
-| `file_name` | String | yes | The name of a snippet file |
-| `content` | String | yes | The content of a snippet |
-| `description` | String | no | The description of a snippet |
-| `visibility` | String | no | The snippet's visibility |
+| Attribute | Type | Required | Description |
+|:--------------|:-------|:---------|:---------------------------------------------------|
+| `title` | string | yes | Title of a snippet. |
+| `file_name` | string | yes | Name of a snippet file. |
+| `content` | string | yes | Content of a snippet. |
+| `description` | string | no | Description of a snippet. |
+| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level). |
+Example request:
-```bash
+```sh
curl --request POST \
--data '{"title": "This is a snippet", "content": "Hello world", "description": "Hello World snippet", "file_name": "test.txt", "visibility": "internal" }' \
--header 'Content-Type: application/json' \
@@ -142,25 +205,29 @@ Example response:
## Update snippet
-Updates an existing snippet. The user must have permission to change an existing snippet.
+Update an existing snippet.
-```
+NOTE: **Note:**
+The user must have permission to change an existing snippet.
+
+```text
PUT /snippets/:id
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | Integer | yes | The ID of a snippet |
-| `title` | String | no | The title of a snippet |
-| `file_name` | String | no | The name of a snippet file |
-| `description` | String | no | The description of a snippet |
-| `content` | String | no | The content of a snippet |
-| `visibility` | String | no | The snippet's visibility |
+| Attribute | Type | Required | Description |
+|:--------------|:--------|:---------|:---------------------------------------------------|
+| `id` | integer | yes | ID of snippet to update. |
+| `title` | string | no | Title of a snippet. |
+| `file_name` | string | no | Name of a snippet file. |
+| `description` | string | no | Description of a snippet. |
+| `content` | string | no | Content of a snippet. |
+| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level). |
+Example request:
-```bash
+```sh
curl --request PUT \
--data '{"title": "foo", "content": "bar"}' \
--header 'Content-Type: application/json' \
@@ -194,39 +261,50 @@ Example response:
## Delete snippet
-Deletes an existing snippet.
+Delete an existing snippet.
-```
+```text
DELETE /snippets/:id
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | Integer | yes | The ID of a snippet |
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:-------------------------|
+| `id` | integer | yes | ID of snippet to delete. |
+Example request:
-```
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/snippets/1"
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/snippets/1"
```
-upon successful delete a `204 No content` HTTP code shall be expected, with no data,
-but if the snippet is non-existent, a `404 Not Found` will be returned.
+The following are possible return codes:
-## Explore all public snippets
+| Code | Description |
+|:------|:--------------------------------------------|
+| `204` | Delete was successful. No data is returned. |
+| `404` | The snippet wasn't found. |
-```
+## List all public snippets
+
+List all public snippets.
+
+```text
GET /snippets/public
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `per_page` | Integer | no | number of snippets to return per page |
-| `page` | Integer | no | the page to retrieve |
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:-----------|:--------|:---------|:---------------------------------------|
+| `per_page` | integer | no | Number of snippets to return per page. |
+| `page` | integer | no | Page to retrieve. |
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/public?per_page=2&page=1
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/snippets/public?per_page=2&page=1
```
Example response:
@@ -273,22 +351,23 @@ Example response:
## Get user agent details
-> **Notes:**
-> [Introduced][ce-29508] in GitLab 9.4.
-
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12655) in GitLab 9.4.
-Available only for admins.
+NOTE: **Note:**
+Available only for administrators.
-```
+```text
GET /snippets/:id/user_agent_detail
```
-| Attribute | Type | Required | Description |
-|-------------|---------|----------|--------------------------------------|
-| `id` | Integer | yes | The ID of a snippet |
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:---------------|
+| `id` | integer | yes | ID of snippet. |
-```bash
-curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/1/user_agent_detail
+Example request:
+
+```sh
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/snippets/1/user_agent_detail
```
Example response:
@@ -300,6 +379,3 @@ Example response:
"akismet_submitted": false
}
```
-
-[ce-6373]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6373
-[ce-29508]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12655
diff --git a/doc/api/suggestions.md b/doc/api/suggestions.md
index 9d76ef0c4bf..e88d536282a 100644
--- a/doc/api/suggestions.md
+++ b/doc/api/suggestions.md
@@ -16,7 +16,7 @@ PUT /suggestions/:id/apply
| `id` | integer/string | yes | The ID of a suggestion |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/suggestions/5/apply
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/suggestions/5/apply
```
Example response:
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index 7b8db6cfa8f..f8563e819db 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -20,7 +20,7 @@ GET /hooks
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/hooks
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/hooks
```
Example response:
@@ -63,7 +63,7 @@ POST /hooks
Example request:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/hooks?url=https://gitlab.example.com/hook"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/hooks?url=https://gitlab.example.com/hook"
```
Example response:
@@ -96,7 +96,7 @@ GET /hooks/:id
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/hooks/2
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/hooks/2
```
Example response:
@@ -129,5 +129,5 @@ DELETE /hooks/:id
Example request:
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/hooks/2
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/hooks/2
``` \ No newline at end of file
diff --git a/doc/api/tags.md b/doc/api/tags.md
index 826900ca518..3177fec618f 100644
--- a/doc/api/tags.md
+++ b/doc/api/tags.md
@@ -17,6 +17,9 @@ Parameters:
| `id` | integer/string| yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user|
| `order_by` | string | no | Return tags ordered by `name` or `updated` fields. Default is `updated` |
| `sort` | string | no | Return tags sorted in `asc` or `desc` order. Default is `desc` |
+| `search` | string | no | Return list of tags matching the search criteria |
+
+> Support for `search` was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/54401) in GitLab 11.8.
```json
[
@@ -65,7 +68,7 @@ Parameters:
| `tag_name` | string | yes | The name of the tag |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/tags/v1.0.0
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/repository/tags/v1.0.0
```
Example Response:
@@ -160,7 +163,6 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `tag_name` (required) - The name of a tag
-
## Create a new release
Add release notes to the existing git tag. If there
diff --git a/doc/api/templates/gitignores.md b/doc/api/templates/gitignores.md
index 3804855129c..bf6a914e120 100644
--- a/doc/api/templates/gitignores.md
+++ b/doc/api/templates/gitignores.md
@@ -1,8 +1,8 @@
-# Gitignores API
+# `.gitignore` API
-## List gitignore templates
+## List `.gitignore` templates
-Get all gitignore templates.
+Get all `.gitignore` templates.
```
GET /templates/gitignores
@@ -99,9 +99,9 @@ Example response:
]
```
-## Single gitignore template
+## Single `.gitignore` template
-Get a single gitignore template.
+Get a single `.gitignore` template.
```
GET /templates/gitignores/:key
@@ -109,7 +109,7 @@ GET /templates/gitignores/:key
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
-| `key` | string | yes | The key of the gitignore template |
+| `key` | string | yes | The key of the `.gitignore` template |
```bash
curl https://gitlab.example.com/api/v4/templates/gitignores/Ruby
diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md
index cecfc8cd9b9..11ec7360e06 100644
--- a/doc/api/templates/gitlab_ci_ymls.md
+++ b/doc/api/templates/gitlab_ci_ymls.md
@@ -120,6 +120,6 @@ Example response:
```json
{
"name": "Ruby",
- "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.3\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service\nservices:\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - bundle exec rake db:migrate\n - bundle exec rake db:seed\n - bundle exec rake test\n"
+ "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.5\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service\nservices:\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - rails db:migrate\n - rails db:seed\n - rails test\n\n# This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk\n# are supported too: https://github.com/travis-ci/dpl\ndeploy:\n type: deploy\n environment: production\n script:\n - gem install dpl\n - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_PRODUCTION_KEY\n"
}
```
diff --git a/doc/api/templates/licenses.md b/doc/api/templates/licenses.md
index 8d1006e08c5..5feb1e498bd 100644
--- a/doc/api/templates/licenses.md
+++ b/doc/api/templates/licenses.md
@@ -116,7 +116,7 @@ If you omit the `fullname` parameter but authenticate your request, the name of
the authenticated user will be used to replace the copyright holder placeholder.
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/templates/licenses/mit?project=My+Cool+Project
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/templates/licenses/mit?project=My+Cool+Project
```
Example response:
diff --git a/doc/api/todos.md b/doc/api/todos.md
index 0843e4eedc6..c54c90d9f06 100644
--- a/doc/api/todos.md
+++ b/doc/api/todos.md
@@ -23,7 +23,7 @@ Parameters:
| `type` | string | no | The type of a todo. Can be either `Issue` or `MergeRequest` |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/todos
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/todos
```
Example Response:
@@ -195,7 +195,7 @@ Parameters:
| `id` | integer | yes | The ID of a todo |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/todos/130/mark_as_done
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/todos/130/mark_as_done
```
Example Response:
@@ -285,8 +285,7 @@ POST /todos/mark_as_done
```
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/todos/donmark_as_donee
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/todos/mark_as_done
```
-
[ce-3188]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3188
diff --git a/doc/api/users.md b/doc/api/users.md
index 1cf4444319c..b0977810120 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -458,7 +458,7 @@ GET /user/status
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/user/status"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/user/status"
```
Example response:
@@ -513,7 +513,7 @@ PUT /user/status
When both parameters `emoji` and `message` are empty, the status will be cleared.
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "emoji=coffee" --data "message=I crave coffee" https://gitlab.example.com/api/v4/user/status
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "emoji=coffee" --data "message=I crave coffee" https://gitlab.example.com/api/v4/user/status
```
Example responses
@@ -679,7 +679,7 @@ GET /user/gpg_keys
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/user/gpg_keys
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/user/gpg_keys
```
Example response:
@@ -709,7 +709,7 @@ Parameters:
| `key_id` | integer | yes | The ID of the GPG key |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/user/gpg_keys/1
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/user/gpg_keys/1
```
Example response:
@@ -737,7 +737,7 @@ Parameters:
| key | string | yes | The new GPG key |
```bash
-curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/user/gpg_keys
+curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/user/gpg_keys
```
Example response:
@@ -767,7 +767,7 @@ Parameters:
| `key_id` | integer | yes | The ID of the GPG key |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/user/gpg_keys/1
+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.
@@ -787,7 +787,7 @@ Parameters:
| `id` | integer | yes | The ID of the user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/2/gpg_keys
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/2/gpg_keys
```
Example response:
@@ -818,7 +818,7 @@ Parameters:
| `key_id` | integer | yes | The ID of the GPG key |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/2/gpg_keys/1
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/2/gpg_keys/1
```
Example response:
@@ -847,7 +847,7 @@ Parameters:
| `key_id` | integer | yes | The ID of the GPG key |
```bash
-curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/2/gpg_keys
+curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/2/gpg_keys
```
Example response:
@@ -878,7 +878,7 @@ Parameters:
| `key_id` | integer | yes | The ID of the GPG key |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/2/gpg_keys/1
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/2/gpg_keys/1
```
## List emails
@@ -1043,7 +1043,6 @@ Will return `201 OK` on success, `404 User Not Found` is user cannot be found or
Please refer to the [Events API documentation](events.md#get-user-contribution-events)
-
## Get all impersonation tokens of a user
> Requires admin permissions.
@@ -1063,7 +1062,7 @@ Parameters:
| `state` | string | no | filter tokens based on state (`all`, `active`, `inactive`) |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/42/impersonation_tokens
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/42/impersonation_tokens
```
Example response:
@@ -1115,7 +1114,7 @@ Parameters:
| `impersonation_token_id` | integer | yes | The ID of the impersonation token |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/42/impersonation_tokens/2
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/42/impersonation_tokens/2
```
Example response:
@@ -1160,7 +1159,7 @@ Parameters:
| `scopes` | array | yes | The array of scopes of the impersonation token (`api`, `read_user`) |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "name=mytoken" --data "expires_at=2017-04-04" --data "scopes[]=api" https://gitlab.example.com/api/v4/users/42/impersonation_tokens
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "name=mytoken" --data "expires_at=2017-04-04" --data "scopes[]=api" https://gitlab.example.com/api/v4/users/42/impersonation_tokens
```
Example response:
@@ -1192,7 +1191,7 @@ DELETE /users/:user_id/impersonation_tokens/:impersonation_token_id
```
```
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/42/impersonation_tokens/1
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/users/42/impersonation_tokens/1
```
Parameters:
@@ -1212,6 +1211,7 @@ The activities that update the timestamp are:
- Git HTTP/SSH activities (such as clone, push)
- User logging in into GitLab
+ - User visiting pages related to Dashboards, Projects, Issues and Merge Requests ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/54947) in GitLab 11.8)
By default, it shows the activity for all users in the last 6 months, but this can be
amended by using the `from` parameter.
@@ -1227,7 +1227,7 @@ Parameters:
| `from` | string | no | Date string in the format YEAR-MONTH-DAY, e.g. `2016-03-11`. Defaults to 6 months ago. |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/user/activities
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/user/activities
```
Example response:
diff --git a/doc/api/version.md b/doc/api/version.md
index 8b2a5b51bc5..ac19178b7ad 100644
--- a/doc/api/version.md
+++ b/doc/api/version.md
@@ -10,7 +10,7 @@ GET /version
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/version
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/version
```
Example response:
diff --git a/doc/api/wikis.md b/doc/api/wikis.md
index df3b54e8f89..12f048ac09b 100644
--- a/doc/api/wikis.md
+++ b/doc/api/wikis.md
@@ -18,7 +18,7 @@ GET /projects/:id/wikis
| `with_content` | boolean | no | Include pages' content |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/wikis?with_content=1
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/wikis?with_content=1
```
Example response:
@@ -59,7 +59,7 @@ GET /projects/:id/wikis/:slug
| `slug` | string | yes | The slug (a unique string) of the wiki page |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/wikis/home
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/wikis/home
```
Example response:
@@ -89,7 +89,7 @@ POST /projects/:id/wikis
| `format` | string | no | The format of the wiki page. Available formats are: `markdown` (default), `rdoc`, and `asciidoc` |
```bash
-curl --data "format=rdoc&title=Hello&content=Hello world" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/wikis"
+curl --data "format=rdoc&title=Hello&content=Hello world" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis"
```
Example response:
@@ -119,9 +119,8 @@ PUT /projects/:id/wikis/:slug
| `format` | string | no | The format of the wiki page. Available formats are: `markdown` (default), `rdoc`, and `asciidoc` |
| `slug` | string | yes | The slug (a unique string) of the wiki page |
-
```bash
-curl --request PUT --data "format=rdoc&content=documentation&title=Docs" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/wikis/foo"
+curl --request PUT --data "format=rdoc&content=documentation&title=Docs" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis/foo"
```
Example response:
@@ -149,7 +148,7 @@ DELETE /projects/:id/wikis/:slug
| `slug` | string | yes | The slug (a unique string) of the wiki page |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/wikis/foo"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis/foo"
```
On success the HTTP status code is `204` and no JSON response is expected.
@@ -177,7 +176,7 @@ The `file=` parameter must point to a file on your filesystem and be preceded
by `@`. For example:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "file=@dk.png" https://gitlab.example.com/api/v4/projects/1/wikis/attachments
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "file=@dk.png" https://gitlab.example.com/api/v4/projects/1/wikis/attachments
```
Example response:
diff --git a/doc/articles/index.md b/doc/articles/index.md
index 87ee17bb6de..162db11d6ac 100644
--- a/doc/articles/index.md
+++ b/doc/articles/index.md
@@ -4,8 +4,8 @@ comments: false
# Technical articles list (deprecated)
-[Technical articles](../development/documentation/index.md#technical-articles) are
-topic-related documentation, written with an user-friendly approach and language, aiming
+Technical articles are
+topic-related documentation, written with a user-friendly approach and language, aiming
to provide the community with guidance on specific processes to achieve certain objectives.
The list of technical articles was [deprecated](https://gitlab.com/gitlab-org/gitlab-ce/issues/41138) in favor of having them linked from their topic-related documentation:
diff --git a/doc/articles/openshift_and_gitlab/index.md b/doc/articles/openshift_and_gitlab/index.md
index 76fdb2eb00a..822d012aa3d 100644
--- a/doc/articles/openshift_and_gitlab/index.md
+++ b/doc/articles/openshift_and_gitlab/index.md
@@ -1,4 +1,3 @@
---
redirect_to: '../../install/openshift_and_gitlab/index.html'
---
-
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 4e066a0df97..4c3c9920b93 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -5,131 +5,194 @@ description: "Learn how to use GitLab CI/CD, the GitLab built-in Continuous Inte
# GitLab Continuous Integration (GitLab CI/CD)
-![Pipeline graph](img/cicd_pipeline_infograph.png)
+GitLab provides tools for continuously integrating and delivering code.
+
+Within the [entire DevOps lifecycle](../README.md#the-entire-devops-lifecycle), GitLab CI/CD spans
+the [Verify (CI)](../README.md#verify) and [Release (CD)](../README.md#release) stages.
-The benefits of Continuous Integration are huge when automation plays an
-integral part of your workflow. GitLab comes with built-in Continuous
-Integration, Continuous Deployment, and Continuous Delivery support
-to build, test, and deploy your application.
+## Overview
-Here's some info we've gathered to get you started.
+CI/CD is a vast area, so GitLab provides documentation for all levels of expertise. Consult the following table to find the right documentation for you:
-## Getting started
+| Level of expertise | Resource |
+|:------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------|
+| New to the concepts of CI and CD | For a high-level overview, see the [GitLab Continuous Integration & Delivery](https://about.gitlab.com/product/continuous-integration/) product page. |
+| Familiar with the purpose of CI/CD | Delve into GitLab CI/CD by continuing down the page, starting with our [introduction](#introduction). |
+| Familiar with GitLab CI/CD concepts | After getting familiar with GitLab CI/CD, let us walk you through a simple example in our [quick start guide](quick_start/README.md). |
+| A GitLab CI/CD expert | Jump straight to our [`.gitlab.yml`](yaml/README.md) reference. |
-The first steps towards your GitLab CI/CD journey.
+## Introduction
-- [Getting started with GitLab CI/CD](quick_start/README.md): understand how GitLab CI/CD works.
-- [GitLab CI/CD configuration file: `.gitlab-ci.yml`](yaml/README.md) - Learn all about the ins and outs of `.gitlab-ci.yml`.
-- [Pipelines and jobs](pipelines.md): configure your GitLab CI/CD pipelines to build, test, and deploy your application.
-- Runners: The [GitLab Runner](https://docs.gitlab.com/runner/) is responsible by running the jobs in your CI/CD pipeline. On GitLab.com, Shared Runners are enabled by default, so
-you don't need to set up anything to start to use them with GitLab CI/CD.
+The following introduces the process of continuous integration (CI) and continuous delivery (CD):
-### Introduction to GitLab CI/CD
+![Pipeline graph](img/cicd_pipeline_infograph.png)
-- Article (2016-08-05): [Continuous Integration, Delivery, and Deployment with GitLab - Intro to CI/CD](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)
-- Article (2015-12-14): [Getting started with GitLab and GitLab CI - Intro to CI](https://about.gitlab.com/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/)
-- Article (2017-07-13): [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/)
-- Article (2017-05-22): [Fast and Natural Continuous Integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/)
-- **Videos:**
- - Demo (Streamed live on Jul 17, 2017): [GitLab CI/CD Deep Dive](https://youtu.be/pBe4t1CD8Fc?t=195)
- - Demo (March, 2017): [How to get started using CI/CD with GitLab](https://about.gitlab.com/2017/03/13/ci-cd-demo/)
- - Webcast (April, 2016): [Getting started with CI in GitLab](https://about.gitlab.com/2016/04/20/webcast-recording-and-slides-introduction-to-ci-in-gitlab/)
-- **Third-party videos:**
- - [Intégration continue avec GitLab (September, 2016)](https://www.youtube.com/watch?v=URcMBXjIr24&t=13s)
- - [GitLab CI for Minecraft Plugins (July, 2016)](https://www.youtube.com/watch?v=Z4pcI9F8yf8)
+In this illustration:
-### Why GitLab CI/CD?
+- New code is combined with existing code through a commit to a project's [repository](../user/project/repository/index.md).
+- The newly combined code is sent to a CI [pipeline](pipelines.md) where:
+ - The code is [built](../user/project/pipelines/job_artifacts.md).
+ - Unit and integration tests are run over the built code.
+- Assuming the build and tests are successful, a CD pipeline is triggered to allow for:
+ - Review using [Review Apps](review_apps/index.md).
+ - Deploying to configured [environments](environments.md).
- - Article (2016-10-17): [Why We Chose GitLab CI for our CI/CD Solution](https://about.gitlab.com/2016/10/17/gitlab-ci-oohlala/)
- - Article (2016-07-22): [Building our web-app on GitLab CI: 5 reasons why Captain Train migrated from Jenkins to GitLab CI](https://about.gitlab.com/2016/07/22/building-our-web-app-on-gitlab-ci/)
+The benefits of CI/CD are vast, allowing automation to be an integral part of your workflow for testing, building, deploying, and monitoring your code.
-## Exploring GitLab CI/CD
+Because CI and CD with GitLab is broad topic with many possibilities, the rest of this section provides
+links to topics and resources needed to make use of GitLab CI/CD.
-- [CI/CD Variables](variables/README.md) - Learn how to use variables defined in
- your `.gitlab-ci.yml` or the ones defined in your project's settings
- - [Where variables can be used](variables/where_variables_can_be_used.md) - A
- deeper look on where and how the CI/CD variables can be used
-- **The permissions model** - Learn about the access levels a user can have for
- performing certain CI actions
- - [User permissions](../user/permissions.md#gitlab-ci)
- - [Job permissions](../user/permissions.md#job-permissions)
-- [Configure a Runner, the application that runs your jobs](runners/README.md)
-- Article (2016-03-01): [Setting up GitLab Runner For Continuous Integration](https://about.gitlab.com/2016/03/01/gitlab-runner-with-docker/)
-- Article (2016-07-29): [GitLab CI: Run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/)
-- Article (2016-08-26): [GitLab CI: Deployment & environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/)
-- Article (2016-05-23): [Introduction to GitLab Container Registry](https://about.gitlab.com/2016/05/23/gitlab-container-registry/)
+## Essentials
-## Advanced use
+The following documentation provides the minimum required knowledge for making use of GitLab CI/CD:
-Once you get familiar with the basics of GitLab CI/CD, it's time to dive in and
-learn how to leverage its potential even more.
+| Topic | Description |
+|:------------------------------------------------------------------------|:---------------------------------------------------------|
+| [Getting started with GitLab CI/CD](quick_start/README.md) | Outlines the first steps for configuring GitLab CI/CD. |
+| [Introduction to pipelines and jobs](pipelines.md) | Provides an overview of GitLab CI/CD and jobs. |
+| [Configuration of your pipelines with `.gitlab-ci.yml`](yaml/README.md) | A comprehensive reference for the `.gitlab-ci.yml` file. |
-- [Environments and deployments](environments.md): Separate your jobs into
- environments and use them for different purposes like testing, building and
- deploying
-- [Job artifacts](../user/project/pipelines/job_artifacts.md)
-- [Caching dependencies](caching/index.md)
-- [Git submodules](git_submodules.md) - How to run your CI jobs when Git
- submodules are involved
-- [Pipelines for merge requests](merge_request_pipelines/index.md)
-- [Use SSH keys in your build environment](ssh_keys/README.md)
-- [Trigger pipelines through the GitLab API](triggers/README.md)
-- [Trigger pipelines on a schedule](../user/project/pipelines/schedules.md)
-- [Kubernetes clusters](../user/project/clusters/index.md) - Integrate one or
- more Kubernetes clusters to your project
-- [Interactive web terminal](interactive_web_terminal/index.md) - Open an interactive
- web terminal to debug the running jobs
+NOTE: **Note:**
+Familiarity with [GitLab Runner](https://docs.gitlab.com/runner/) is useful because it is
+responsible for running the jobs in your CI/CD pipeline. On GitLab.com, shared Runners are enabled
+by default so you don't need to set up anything to get started.
-## GitLab CI/CD for Docker
+### Auto DevOps
-Leverage the power of Docker to run your CI pipelines.
+An alternative to manually configuring CI/CD, GitLab supports [Auto DevOps](../topics/autodevops/index.md),
+which:
-- [Use Docker images with GitLab Runner](docker/using_docker_images.md)
-- [Use CI to build Docker images](docker/using_docker_build.md)
-- [CI services (linked Docker containers)](services/README.md)
-- Article (2016-03-01): [Setting up GitLab Runner For Continuous Integration](https://about.gitlab.com/2016/03/01/gitlab-runner-with-docker/)
+- Provides simplified setup and execution of CI/CD.
+- Allows GitLab to automatically detect, build, test, deploy, and monitor your applications.
-## Review Apps
+## Basic usage
-- [Review Apps documentation](review_apps/index.md)
-- Article (2016-11-22): [Introducing Review Apps](https://about.gitlab.com/2016/11/22/introducing-review-apps/)
-- [Example project that shows how to use Review Apps](https://gitlab.com/gitlab-examples/review-apps-nginx/)
+With basic knowledge of how GitLab CI/CD works, the following documentation extends your knowledge
+into more features:
-## Auto DevOps
+| Topic | Description |
+|:-------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|
+| [CI/CD Variables](variables/README.md) | How environment variables can be configured and made available in pipelines. |
+| [Where variables can be used](variables/where_variables_can_be_used.md) | A deeper look into where and how CI/CD variables can be used. |
+| [User](../user/permissions.md#gitlab-ci) and [job](../user/permissions.md#job-permissions) permissions | Learn about the access levels a user can have for performing certain CI actions. |
+| [Configuring GitLab Runners](runners/README.md) | Documentation for configuring [GitLab Runner](https://docs.gitlab.com/runner/). |
-- [Auto DevOps](../topics/autodevops/index.md): Auto DevOps automatically detects, builds, tests, deploys, and monitors your applications.
+## Advanced usage
-## GitLab CI for GitLab Pages
+Once you get familiar with the basics of GitLab CI/CD, consult the following documentation to make
+use of advanced features:
-See the documentation on [GitLab Pages](../user/project/pages/index.md).
+| Topic | Description |
+|:---------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------|
+| [Introduction to environments and deployments](environments.md) | Learn how to separate your jobs into environments and use them for different purposes like testing, building and, deploying. |
+| [Job artifacts](../user/project/pipelines/job_artifacts.md) | Learn about the output of jobs. |
+| [Cache dependencies in GitLab CI/CD](caching/index.md) | Discover how to speed up pipelines using caching. |
+| [Using Git submodules with GitLab CI](git_submodules.md) | How to run your CI jobs when using Git submodules. |
+| [Pipelines for merge requests](merge_request_pipelines/index.md) | Create pipelines specifically for merge requests. |
+| [Using SSH keys with GitLab CI/CD](ssh_keys/README.md) | Use SSH keys in your build environment. |
+| [Triggering pipelines through the API](triggers/README.md) | Use the GitLab API to trigger a pipeline. |
+| [Pipeline schedules](../user/project/pipelines/schedules.md) | Trigger pipelines on a schedule. |
+| [Connecting GitLab with a Kubernetes cluster](../user/project/clusters/index.md) | Integrate one or more Kubernetes clusters to your project. |
+| [ChatOps](chatops/README.md) | Trigger CI jobs from chat, with results sent back to the channel. |
+| [Interactive web terminals](interactive_web_terminal/index.md) | Open an interactive web terminal to debug the running jobs. |
+
+### GitLab Pages
+
+GitLab CI/CD can be used to build and host static websites. For more information, see the
+documentation on [GitLab Pages](../user/project/pages/index.md).
## Examples
-Check the [GitLab CI/CD examples](examples/README.md) for a collection of tutorials and guides on setting up your CI/CD pipeline for various programming languages, frameworks,
-and operating systems.
+Check out the [GitLab CI/CD examples](examples/README.md) for a collection of tutorials and guides on
+setting up your CI/CD pipeline for various programming languages, frameworks, and operating systems.
+
+## Administration
+
+As a GitLab administrator, you can change the default behavior of GitLab CI/CD for:
+
+- An [entire GitLab instance](../user/admin_area/settings/continuous_integration.md).
+- Specific projects, using [pipelines settings](../user/project/pipelines/settings.md).
+
+See also:
+
+- [How to enable or disable GitLab CI/CD](enable_or_disable_ci.md).
+- Other [CI administration settings](../administration/index.md#continuous-integration-settings).
+
+## Using Docker
+
+Docker is commonly used with GitLab CI/CD. Learn more about how to to accomplish this with the following
+documentation:
+
+| Topic | Description |
+|:-------------------------------------------------------------------------|:-------------------------------------------------------------------------|
+| [Using Docker images](docker/using_docker_images.md) | Use GitLab and GitLab Runner with Docker to build and test applications. |
+| [Building Docker images with GitLab CI/CD](docker/using_docker_build.md) | Maintain Docker-based projects using GitLab CI/CD. |
+
+Related topics include:
-## Integrations
+- [Docker integration](docker/README.md).
+- [CI services (linked Docker containers)](services/README.md).
+- [Setting up GitLab Runner For Continuous Integration](https://about.gitlab.com/2016/03/01/gitlab-runner-with-docker/) (article).
-- Article (2016-06-09): [Continuous Delivery with GitLab and Convox](https://about.gitlab.com/2016/06/09/continuous-delivery-with-gitlab-and-convox/)
-- Article (2016-05-05): [Getting Started with GitLab and Shippable Continuous Integration](https://about.gitlab.com/2016/05/05/getting-started-gitlab-and-shippable/)
-- Article (2016-04-19): [GitLab Partners with DigitalOcean to make Continuous Integration faster, safer, and more affordable](https://about.gitlab.com/2016/04/19/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable/)
+## Further resources
-## Special configuration (GitLab admin)
+This section provides further resources to help you get familiar with GitLab CI/CD.
-As a GitLab administrator, you can change the default behavior of GitLab CI/CD in
-your whole GitLab instance as well as in each project.
+### Articles
-- [Continuous Integration admin settings](../administration/index.md#continuous-integration-settings)
-- **Project specific:**
- - [Pipelines settings](../user/project/pipelines/settings.md)
- - [Learn how to enable or disable GitLab CI](enable_or_disable_ci.md)
-- **Affecting the whole GitLab instance:**
- - [Continuous Integration admin settings](../user/admin_area/settings/continuous_integration.md)
+The following table provides a list of articles about CI/CD, sorted in reverse chronological order of publish date:
+
+| Publish Date | Article |
+|:-------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 2017-07-13 | [Making CI easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/). |
+| 2017-05-22 | [Fast and natural continuous integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/). |
+| 2016-11-22 | [Introducing Review Apps](https://about.gitlab.com/2016/11/22/introducing-review-apps/). |
+| 2016-08-26 | [GitLab CI: Deployment & Environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/). |
+| 2016-08-05 | [Continuous Integration, Delivery, and Deployment with GitLab](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/). |
+| 2016-07-29 | [GitLab CI: Run jobs sequentially, in parallel or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/). |
+| 2016-06-09 | [Continuous Delivery with GitLab and Convox](https://about.gitlab.com/2016/06/09/continuous-delivery-with-gitlab-and-convox/) |
+| 2016-05-23 | [GitLab Container Registry](https://about.gitlab.com/2016/05/23/gitlab-container-registry/). |
+| 2016-05-05 | [Getting Started with GitLab and Shippable Continuous Integration](https://about.gitlab.com/2016/05/05/getting-started-gitlab-and-shippable/) |
+| 2016-04-19 | [GitLab Partners with DigitalOcean to make Continuous Integration faster, safer, and more affordable](https://about.gitlab.com/2016/04/19/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable/) |
+| 2015-03-01 | [Setting up GitLab Runner For Continuous Integration](https://about.gitlab.com/2016/03/01/gitlab-runner-with-docker/). |
+| 2015-12-14 | [Getting started with GitLab and GitLab CI](https://about.gitlab.com/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/). |
+
+### Videos
+
+The following table provides a list of videos about CI/CD, sorted in reverse chronological order of publish date:
+
+| Publish Date | Video |
+|:-------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 2017-07-17 | [GitLab CI/CD Deep Dive](https://youtu.be/pBe4t1CD8Fc?t=195). |
+| 2017-03-13 | [Demo: CI/CD with GitLab in action](https://about.gitlab.com/2017/03/13/ci-cd-demo/). |
+| 2016-04-20 | [Webcast Recording and Slides: Getting started with CI in GitLab](https://about.gitlab.com/2016/04/20/webcast-recording-and-slides-introduction-to-ci-in-gitlab/). |
+
+In addition, the following third-party videos are available:
+
+- [Intégration continue avec GitLab (September 2016)](https://www.youtube.com/watch?v=URcMBXjIr24&t=13s).
+- [GitLab CI for Minecraft Plugins (July 2016)](https://www.youtube.com/watch?v=Z4pcI9F8yf8).
+
+### Example Projects
+
+[`review-apps-nginx`](https://gitlab.com/gitlab-examples/review-apps-nginx/) provides an example of using Review Apps.
+
+Other example projects are available at the [`gitlab-examples`](https://gitlab.com/gitlab-examples) group.
+
+### Why GitLab CI/CD?
+
+The following articles explain reasons why you might use GitLab CI/CD for your CI/CD infrastructure:
+
+- [Why we chose GitLab CI for our CI/CD solution](https://about.gitlab.com/2016/10/17/gitlab-ci-oohlala/).
+- [Building our web-app on GitLab CI](https://about.gitlab.com/2016/07/22/building-our-web-app-on-gitlab-ci/).
+
+See also the [Why CI/CD?](https://docs.google.com/presentation/d/1OGgk2Tcxbpl7DJaIOzCX4Vqg3dlwfELC3u2jEeCBbDk) presentation.
## Breaking changes
-- [CI variables renaming for GitLab 9.0](variables/README.md#9-0-renaming) Read about the
+As GitLab CI/CD has evolved, certain breaking changes have been necessary. These are:
+
+- [CI variables renaming for GitLab 9.0](variables/README.md#gitlab-90-renaming). Read about the
deprecated CI variables and what you should use for GitLab 9.0+.
-- [New CI job permissions model](../user/project/new_ci_build_permissions_model.md)
- Read about what changed in GitLab 8.12 and how that affects your jobs.
+- [New CI job permissions model](../user/project/new_ci_build_permissions_model.md).
+ See what changed in GitLab 8.12 and how that affects your jobs.
There's a new way to access your Git submodules and LFS objects in jobs.
diff --git a/doc/ci/autodeploy/img/auto_deploy_btn.png b/doc/ci/autodeploy/img/auto_deploy_btn.png
deleted file mode 100644
index ee88e5ce8c0..00000000000
--- a/doc/ci/autodeploy/img/auto_deploy_btn.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/autodeploy/img/auto_deploy_button.png b/doc/ci/autodeploy/img/auto_deploy_button.png
deleted file mode 100644
index 0e84d9c57a1..00000000000
--- a/doc/ci/autodeploy/img/auto_deploy_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/autodeploy/img/auto_deploy_dropdown.png b/doc/ci/autodeploy/img/auto_deploy_dropdown.png
deleted file mode 100644
index 4094f8ebb4e..00000000000
--- a/doc/ci/autodeploy/img/auto_deploy_dropdown.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/autodeploy/img/auto_monitoring.png b/doc/ci/autodeploy/img/auto_monitoring.png
deleted file mode 100644
index 5a11923d199..00000000000
--- a/doc/ci/autodeploy/img/auto_monitoring.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/autodeploy/img/guide_connect_cluster.png b/doc/ci/autodeploy/img/guide_connect_cluster.png
deleted file mode 100644
index 703d536f37a..00000000000
--- a/doc/ci/autodeploy/img/guide_connect_cluster.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/autodeploy/img/guide_integration.png b/doc/ci/autodeploy/img/guide_integration.png
deleted file mode 100644
index ab72de2bba3..00000000000
--- a/doc/ci/autodeploy/img/guide_integration.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/autodeploy/img/guide_secret.png b/doc/ci/autodeploy/img/guide_secret.png
deleted file mode 100644
index 8469bee48b7..00000000000
--- a/doc/ci/autodeploy/img/guide_secret.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/autodeploy/quick_start_guide.md b/doc/ci/autodeploy/quick_start_guide.md
index 1473703542d..985ec4b972c 100644
--- a/doc/ci/autodeploy/quick_start_guide.md
+++ b/doc/ci/autodeploy/quick_start_guide.md
@@ -1,95 +1 @@
-# Auto Deploy: quick start guide
-
-This is a step-by-step guide to deploying a project hosted on GitLab.com to Google Cloud, using Auto Deploy.
-
-We made a minimal [Ruby application](https://gitlab.com/gitlab-examples/minimal-ruby-app) to use as an example for this guide. It contains two files:
-
-* `server.rb` - our application. It will start an HTTP server on port 5000 and render “Hello, world!â€
-* `Dockerfile` - to build our app into a container image. It will use a ruby base image and run `server.rb`
-
-## Fork sample project on GitLab.com
-
-Let’s start by forking our sample application. Go to [the project page](https://gitlab.com/gitlab-examples/minimal-ruby-app) and press the `Fork` button. Soon you should have a project under your namespace with the necessary files.
-
-## Set up your own cluster on Google Kubernetes Engine
-
-If you do not already have a Google Cloud account, create one at https://console.cloud.google.com.
-
-Visit the [`Kubernetes Engine`](https://console.cloud.google.com/kubernetes/list) tab and create a new cluster. You can change the name and leave the rest of the default settings. Once you have your cluster running, you need to connect to the cluster by following the Google interface.
-
-## Connect to Kubernetes cluster
-
-You need to have the Google Cloud SDK installed. e.g.
-On OSX, install [homebrew](https://brew.sh):
-
-1. Install Brew Caskroom: `brew install caskroom/cask/brew-cask`
-1. Install Google Cloud SDK: `brew cask install google-cloud-sdk`
-1. Add `kubectl`: `gcloud components install kubectl`
-1. Log in: `gcloud auth login`
-
-Now go back to the Google interface, find your cluster, and follow the instructions under `Connect to the cluster` and open the Kubernetes Dashboard. It will look something like `gcloud container clusters get-credentials ruby-autodeploy \ --zone europe-west2-c --project api-project-XXXXXXX` and then `kubectl proxy`.
-
-![connect to cluster](img/guide_connect_cluster.png)
-
-## Copy credentials to GitLab.com project
-
-Once you have the Kubernetes Dashboard interface running, you should visit `Secrets` under the `Config` section. There you should find the settings we need for GitLab integration: ca.crt and token.
-
-![connect to cluster](img/guide_secret.png)
-
-You need to copy-paste the ca.crt and token into your project on GitLab.com in the Kubernetes integration page under project `Settings` > `Integrations` > `Project services` > `Kubernetes`. Don't actually copy the namespace though. Each project should have a unique namespace, and by leaving it blank, GitLab will create one for you.
-
-![connect to cluster](img/guide_integration.png)
-
-For API URL, you should use the `Endpoint` IP from your cluster page on Google Cloud Platform.
-
-## Expose the application to the internet
-
-In order to be able to visit your application, you need to install an NGINX ingress controller and point your domain name to its external IP address.
-
-### Set up Ingress controller
-
-You’ll need to make sure you have an ingress controller. If you don’t have one, do:
-
-```sh
-brew install kubernetes-helm
-helm init
-helm install --name ruby-app stable/nginx-ingress
-```
-
-This should create several services including `ruby-app-nginx-ingress-controller`. You can list your services by running `kubectl get svc` to confirm that.
-
-### Point DNS at Cluster IP
-
-Find out the external IP address of the `ruby-app-nginx-ingress-controller` by running:
-
-```sh
-kubectl get svc ruby-app-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
-```
-
-Use this IP address to configure your DNS. This part heavily depends on your preferences and domain provider. But in case you are not sure, just create an A record with a wildcard host like `*.<your-domain>` pointing to the external IP address you found above.
-
-Use `nslookup minimal-ruby-app-staging.<yourdomain>` to confirm that domain is assigned to the cluster IP.
-
-## Set up Auto Deploy
-
-Visit the home page of your GitLab.com project and press "Set up Auto Deploy" button.
-
-![auto deploy button](img/auto_deploy_btn.png)
-
-You will be redirected to the "New file" page where you can apply one of the Auto Deploy templates. Select "Kubernetes" to apply the template, then in the file, replace `domain.example.com` with your domain name and make any other adjustments you need.
-
-![auto deploy template](img/auto_deploy_dropdown.png)
-
-Change the target branch to `master`, and submit your changes. This should create
-a new pipeline with several jobs. If you made only the domain name change, the
-pipeline will have three jobs: `build`, `staging`, and `production`.
-
-The `build` job will create a Docker image with your new change and push it to
-the GitLab Container Registry. The `staging` job will deploy this image on your
-cluster. Once the deploy job succeeds you should be able to see your application by
-visiting the Kubernetes dashboard. Select the namespace of your project, which
-will look like `ruby-autodeploy-23`, but with a unique ID for your project, and
-your app will be listed as "staging" under the "Deployment" tab.
-
-Once its ready - just visit http://minimal-ruby-app-staging.yourdomain.com to see “Hello, world!â€
+This document was moved to [another location](../../topics/autodevops/index.md#auto-deploy).
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index f93ccc4e3c1..e079483e2b5 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -29,7 +29,7 @@ needed to compile the project:
Cache was designed to be used to speed up invocations of subsequent runs of a
given job, by keeping things like dependencies (e.g., npm packages, Go vendor
packages, etc.) so they don't have to be re-fetched from the public internet.
- While the cache can be abused to pass intermediate build results between
+ While the cache can be abused to pass intermediate build results between
stages, there may be cases where artifacts are a better fit.
- `artifacts`: **Use for stage results that will be passed between stages.**
Artifacts were designed to upload some compiled/generated bits of the build,
@@ -40,20 +40,19 @@ needed to compile the project:
comply to this rule trigger an unintuitive and illogical error message (an
enhancement is discussed at
[https://gitlab.com/gitlab-org/gitlab-ce/issues/15530](https://gitlab.com/gitlab-org/gitlab-ce/issues/15530)
- ). Artifacts need to be uploaded to the GitLab instance (not only the GitLab
- runner) before the next stage job(s) can start, so you need to evaluate
- carefully whether your bandwidth allows you to profit from parallelization
- with stages and shared artifacts before investing time in changes to the
+ ). Artifacts need to be uploaded to the GitLab instance (not only the GitLab
+ runner) before the next stage job(s) can start, so you need to evaluate
+ carefully whether your bandwidth allows you to profit from parallelization
+ with stages and shared artifacts before investing time in changes to the
setup.
-
It's sometimes confusing because the name artifact sounds like something that
is only useful outside of the job, like for downloading a final image. But
artifacts are also available in between stages within a pipeline. So if you
build your application by downloading all the required modules, you might want
to declare them as artifacts so that each subsequent stage can depend on them
being there. There are some optimizations like declaring an
-[expiry time](../yaml/README.md#artifacts-expire_in) so you don't keep artifacts
+[expiry time](../yaml/README.md#artifactsexpire_in) so you don't keep artifacts
around too long, and using [dependencies](../yaml/README.md#dependencies) to
control exactly where artifacts are passed around.
@@ -88,9 +87,9 @@ cache, when declaring `cache` in your jobs, use one or a mix of the following:
that share their cache.
- [Use sticky Runners](../runners/README.md#locking-a-specific-runner-from-being-enabled-for-other-projects)
that will be only available to a particular project.
-- [Use a `key`](../yaml/README.md#cache-key) that fits your workflow (e.g.,
+- [Use a `key`](../yaml/README.md#cachekey) that fits your workflow (e.g.,
different caches on each branch). For that, you can take advantage of the
- [CI/CD predefined variables](../variables/README.md#predefined-variables-environment-variables).
+ [CI/CD predefined variables](../variables/README.md#predefined-environment-variables).
TIP: **Tip:**
Using the same Runner for your pipeline, is the most simple and efficient way to
@@ -170,7 +169,7 @@ job:
```
For more fine tuning, read also about the
-[`cache: policy`](../yaml/README.md#cache-policy).
+[`cache: policy`](../yaml/README.md#cachepolicy).
## Common use cases
@@ -300,7 +299,6 @@ cache:
before_script:
- ruby -v # Print out ruby version for debugging
- - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image
- bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
rspec:
diff --git a/doc/ci/chatops/README.md b/doc/ci/chatops/README.md
new file mode 100644
index 00000000000..6ad1df7bb2a
--- /dev/null
+++ b/doc/ci/chatops/README.md
@@ -0,0 +1,61 @@
+# GitLab ChatOps
+
+> **Notes:**
+>
+> * [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6. [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24780) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.9.
+>
+> * ChatOps is currently in alpha, with some important features missing like access control.
+
+GitLab ChatOps provides a method to interact with CI/CD jobs through chat services like Slack. Many organizations' discussion, collaboration, and troubleshooting is taking place in chat services these days, and having a method to run CI/CD jobs with output posted back to the channel can significantly augment a team's workflow.
+
+## How it works
+
+GitLab ChatOps is built upon two existing features, [GitLab CI/CD](../README.md) and [Slack Slash Commmands](../../user/project/integrations/slack_slash_commands.md).
+
+A new `run` action has been added to the [slash commands](../../integration/slash_commands.md), which takes two arguments: a `<job name>` to execute and the `<job arguments>`. When executed, ChatOps will look up the specified job name and attempt to match it to a corresponding job in [.gitlab-ci.yml](../yaml/README.md). If a matching job is found on `master`, a pipeline containing just that job is scheduled. Two additional [CI/CD variables](../variables/README.html#predefined-variables-environment-variables) are passed to the job: `CHAT_INPUT` contains any additional arguments, and `CHAT_CHANNEL` is set to the name of channel the action was triggered in.
+
+After the job has finished, its output is sent back to Slack provided it has completed within 30 minutes. If a job takes more than 30 minutes to run it must use the Slack API to manually send data back to a channel.
+
+[Developer access and above](../../user/permissions.html#project-members-permissions) is required to use the `run` command. If a job should not be able to be triggered from chat, it can be set to `except: [chat]`.
+
+## Creating a ChatOps CI job
+
+Since ChatOps is built upon GitLab CI/CD, the job has all the same features and functions available. There a few best practices to consider however when creating ChatOps jobs:
+
+* It is strongly recommended to set `only: [chat]` so the job does not run as part of the standard CI pipeline.
+* If the job is set to `when: manual`, the pipeline will be created however the job will wait to be started.
+* It is important to keep in mind that there is very limited support for access control. If the user who triggered the slash command is a developer in the project, the job will run. The job itself can utilize existing [CI/CD variables](../variables/README.html#predefined-environment-variables) like `GITLAB_USER_ID` to perform additional rights validation, however these variables can be [overridden](https://docs.gitlab.com/ce/ci/variables/README.html#priority-of-variables).
+
+### Controlling the ChatOps reply
+
+For jobs with a single command, its output is automatically sent back to the channel as a reply. For example the chat reply of the following job is simply `Hello World.`
+
+```yaml
+hello-world:
+ stage: chatops
+ only: [chat]
+ script:
+ - echo "Hello World."
+```
+
+Jobs that contain multiple commands, or have a `before_script`, include additional content in the chat reply. In these cases both the commands and their output are included, with the commands wrapped in ANSI colors codes.
+
+To selectively reply with the output of one command, its output must be bounded by the `chat_reply` section. For example, the following job will list the files in the current directory.
+
+```yaml
+ls:
+ stage: chatops
+ only: [chat]
+ script:
+ - echo "This command will not be shown."
+ - echo -e "section_start:$( date +%s ):chat_reply\r\033[0K\n$( ls -la )\nsection_end:$( date +%s ):chat_reply\r\033[0K"
+```
+
+## GitLab ChatOps icon
+
+Say Hi to our ChatOps bot.
+You can find and download the official GitLab ChatOps icon here.
+
+![GitLab ChatOps bot icon](img/gitlab-chatops-icon-small.png)
+
+[Download bigger image](img/gitlab-chatops-icon.png)
diff --git a/doc/ci/chatops/img/gitlab-chatops-icon-small.png b/doc/ci/chatops/img/gitlab-chatops-icon-small.png
new file mode 100644
index 00000000000..71cc5dba5cf
--- /dev/null
+++ b/doc/ci/chatops/img/gitlab-chatops-icon-small.png
Binary files differ
diff --git a/doc/ci/chatops/img/gitlab-chatops-icon.png b/doc/ci/chatops/img/gitlab-chatops-icon.png
new file mode 100644
index 00000000000..3ba8bd308e3
--- /dev/null
+++ b/doc/ci/chatops/img/gitlab-chatops-icon.png
Binary files differ
diff --git a/doc/ci/docker/README.md b/doc/ci/docker/README.md
index 8ae80b2bc02..446f5b54f0c 100644
--- a/doc/ci/docker/README.md
+++ b/doc/ci/docker/README.md
@@ -4,6 +4,8 @@ comments: false
# Docker integration
-- [Using Docker Images](using_docker_images.md)
-- [Using Docker Build](using_docker_build.md)
-- [Using kaniko](using_kaniko.md)
+The following documentation is available for using GitLab CI/CD with Docker:
+
+- [Using Docker images](using_docker_images.md).
+- [Building Docker images with GitLab CI/CD](using_docker_build.md).
+- [Building images with kaniko and GitLab CI/CD](using_kaniko.md).
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index fef367051bf..4f9efb57b8d 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -17,7 +17,7 @@ used to create and test an image:
```bash
docker build -t my-image dockerfiles/
-docker run my-docker-image /script/to/run/tests
+docker run my-image /script/to/run/tests
docker tag my-image my-registry:5000/my-image
docker push my-registry:5000/my-image
```
@@ -194,7 +194,7 @@ not without its own challenges:
- docker run -v "$MOUNT_POINT:/mnt" my-docker-image
```
-An example project using this approach can be found here: https://gitlab.com/gitlab-examples/docker.
+An example project using this approach can be found here: <https://gitlab.com/gitlab-examples/docker>.
### Use Docker socket binding
@@ -521,11 +521,11 @@ stages:
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
- CONTAINER_TEST_IMAGE: registry.example.com/my-group/my-project/my-image:$CI_COMMIT_REF_SLUG
- CONTAINER_RELEASE_IMAGE: registry.example.com/my-group/my-project/my-image:latest
+ CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest
before_script:
- - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.example.com
+ - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
build:
stage: build
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 959271d8abc..3314c76d234 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -391,9 +391,9 @@ CI jobs:
from `Dockerfile` that may be overridden in `.gitlab-ci.yml`)
1. The Runner attaches itself to a running container.
1. The Runner prepares a script (the combination of
- [`before_script`](../yaml/README.md#before_script),
+ [`before_script`](../yaml/README.md#before_script-and-after_script),
[`script`](../yaml/README.md#script),
- and [`after_script`](../yaml/README.md#after_script)).
+ and [`after_script`](../yaml/README.md#before_script-and-after_script)).
1. The Runner sends the script to the container's shell STDIN and receives the
output.
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index 66f0d429165..f354cdb398e 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -40,7 +40,7 @@ In the following example, kaniko is used to build a Docker image and then push
it to [GitLab Container Registry](../../user/project/container_registry.md).
The job will run only when a tag is pushed. A `config.json` file is created under
`/kaniko/.docker` with the needed GitLab Container Registry credentials taken from the
-[environment variables](../variables/README.md#predefined-variables-environment-variables)
+[environment variables](../variables/README.md#predefined-environment-variables)
GitLab CI/CD provides. In the last step, kaniko uses the `Dockerfile` under the
root directory of the project, builds the Docker image and pushes it to the
project's Container Registry while tagging it with the Git tag:
@@ -57,3 +57,26 @@ build:
only:
- tags
```
+
+## Using a registry with a custom certificate
+
+When trying to push to a Docker registry that uses a certificate that is signed
+by a custom CA, you might get the following error:
+
+```sh
+$ /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --no-push
+INFO[0000] Downloading base image registry.gitlab.example.com/group/docker-image
+error building image: getting stage builder for stage 0: Get https://registry.gitlab.example.com/v2/: x509: certificate signed by unknown authority
+```
+
+This can be solved by adding your CA's certificate to the kaniko certificate
+store:
+
+```yaml
+ before_script:
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
+ - |
+ echo "-----BEGIN CERTIFICATE-----
+ ...
+ -----END CERTIFICATE-----" >> /kaniko/ssl/certs/ca-certificates.crt
+```
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
index 315d0c5e7ef..fe66f7e3c28 100644
--- a/doc/ci/environments.md
+++ b/doc/ci/environments.md
@@ -103,7 +103,7 @@ the Git SHA and environment name.
To sum up, with the above `.gitlab-ci.yml` we have achieved that:
- All branches will run the `test` and `build` jobs.
-- The `deploy_staging` job will run [only](yaml/README.md#only) on the `master`
+- The `deploy_staging` job will run [only](yaml/README.md#only-and-except-simplified) on the `master`
branch which means all merge requests that are created from branches don't
get to deploy to the staging server
- When a merge request is merged, all jobs will run and the `deploy_staging`
@@ -249,7 +249,7 @@ the basis of [Review apps](review_apps/index.md).
NOTE: **Note:**
The `name` and `url` parameters can use most of the CI/CD variables,
-including [predefined](variables/README.md#predefined-variables-environment-variables),
+including [predefined](variables/README.md#predefined-environment-variables),
[project/group ones](variables/README.md#variables) and
[`.gitlab-ci.yml` variables](yaml/README.md#variables). You however cannot use variables
defined under `script` or on the Runner's side. There are also other variables that
@@ -401,7 +401,7 @@ Let's briefly see where URL that's defined in the environments is exposed.
## Making use of the environment URL
-The [environment URL](yaml/README.md#environments-url) is exposed in a few
+The [environment URL](yaml/README.md#environmenturl) is exposed in a few
places within GitLab.
| In a merge request widget as a link | In the Environments view as a button | In the Deployments view as a button |
@@ -416,81 +416,15 @@ and/or `production`) you can see this information in the merge request itself.
### Go directly from source files to public pages on the environment
-> Introduced in GitLab 8.17. In GitLab 11.5 the file links
-are surfaced to the merge request widget.
+With GitLab's [Route Maps](review_apps/index.md#route-maps) you can go directly
+from source files to public pages on the environment set for Review Apps.
-You can specify a Route Map to get GitLab to show "View on <environment URL>"
-buttons to go directly from a file to that file's representation on the
-[deployed website via Review Apps](review_apps/index.md).
-
-To get this to work, you need to tell GitLab how the paths of files in your repository map to paths of pages on your website, using a Route Map.
-
-A Route Map is a file inside the repository at `.gitlab/route-map.yml`, which contains a YAML array that maps `source` paths (in the repository) to `public` paths (on the website).
-Below is an example of a route map for [Middleman](https://middlemanapp.com) static websites
-like <https://gitlab.com/gitlab-com/www-gitlab-com>:
-
-```yaml
-# Team data
-- source: 'data/team.yml' # data/team.yml
- public: 'team/' # team/
-
-# Blogposts
-- source: /source\/posts\/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.+?)\..*/ # source/posts/2017-01-30-around-the-world-in-6-releases.html.md.erb
- public: '\1/\2/\3/\4/' # 2017/01/30/around-the-world-in-6-releases/
-
-# HTML files
-- source: /source\/(.+?\.html).*/ # source/index.html.haml
- public: '\1' # index.html
-
-# Other files
-- source: /source\/(.*)/ # source/images/blogimages/around-the-world-in-6-releases-cover.png
- public: '\1' # images/blogimages/around-the-world-in-6-releases-cover.png
-```
-
-Mappings are defined as entries in the root YAML array, and are identified by a `-` prefix. Within an entry, we have a hash map with two keys:
-
-- `source`
- - a string, starting and ending with `'`, for an exact match
- - a regular expression, starting and ending with `/`, for a pattern match
- - The regular expression needs to match the entire source path - `^` and `$` anchors are implied.
- - Can include capture groups denoted by `()` that can be referred to in the `public` path.
- - Slashes (`/`) can, but don't have to, be escaped as `\/`.
- - Literal periods (`.`) should be escaped as `\.`.
-- `public`
- - a string, starting and ending with `'`.
- - Can include `\N` expressions to refer to capture groups in the `source` regular expression in order of their occurrence, starting with `\1`.
-
-The public path for a source path is determined by finding the first `source` expression that matches it, and returning the corresponding `public` path, replacing the `\N` expressions with the values of the `()` capture groups if appropriate.
-
-In the example above, the fact that mappings are evaluated in order of their definition is used to ensure that `source/index.html.haml` will match `/source\/(.+?\.html).*/` instead of `/source\/(.*)/`, and will result in a public path of `index.html`, instead of `index.html.haml`.
-
----
-
-Once you have the route mapping set up, it will be exposed in a few places:
-
-- In the merge request widget. The **View app** button will take you to the
- environment URL you have set up in `.gitlab-ci.yml`. The dropdown will render
- the first 5 matched items from the route map, but you can filter them if more
- than 5 are available.
-
- ![View app file list in merge request widget](img/view_on_mr_widget.png)
-
-- In the diff for a merge request, comparison, or commit.
-
- !["View on env" button in merge request diff](img/view_on_env_mr.png)
-
-- In the blob file view.
-
- !["View on env" button in file view](img/view_on_env_blob.png) |
-
----
-
-We now have a full development cycle, where our app is tested, built, deployed
-as a Review app, deployed to a staging server once the merge request is merged,
-and finally manually deployed to the production server. What we just described
-is a single workflow, but imagine tens of developers working on a project
-at the same time. They each push to their branches, and dynamic environments are
-created all the time. In that case, we probably need to do some clean up. Read
+From then on, you have a full development cycle, where your app is tested, built, deployed
+as a Review App, deployed to a staging server once the merge request is merged,
+and finally manually deployed to the production server. This is a simple workflow,
+but when you have multiple developers working on a project
+at the same time, each of them pushing to their own branches, dynamic environments are
+created all the time. In which case, you probably want to do some clean up. Read
next how environments can be stopped.
## Stopping an environment
@@ -685,9 +619,9 @@ Below are some links you may find interesting:
[deployments]: #deployments
[permissions]: ../user/permissions.md
[variables]: variables/README.md
-[env-name]: yaml/README.md#environment-name
-[only]: yaml/README.md#only-and-except
-[onstop]: yaml/README.md#environment-on_stop
+[env-name]: yaml/README.md#environmentname
+[only]: yaml/README.md#only-and-except-simplified
+[onstop]: yaml/README.md#environmenton_stop
[ce-7015]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7015
[gitlab-flow]: ../workflow/gitlab_flow.md
[gitlab runner]: https://docs.gitlab.com/runner/
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index a8c119edaa0..87e86bef44b 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -40,6 +40,7 @@ There's also a collection of repositories with [example projects](https://gitlab
### Miscellaneous
+- [End-to-end testing with GitLab CI/CD and WebdriverIO](end_to_end_testing_webdriverio/index.md)
- [Using `dpl` as deployment tool](deployment/README.md)
- [The `.gitlab-ci.yml` file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml)
diff --git a/doc/ci/examples/artifactory_and_gitlab/index.md b/doc/ci/examples/artifactory_and_gitlab/index.md
index 6aa0edd87b4..9e657275d50 100644
--- a/doc/ci/examples/artifactory_and_gitlab/index.md
+++ b/doc/ci/examples/artifactory_and_gitlab/index.md
@@ -16,8 +16,8 @@ to build a [Maven](https://maven.apache.org/) project, deploy it to [Artifactory
You'll create two different projects:
-- `simple-maven-dep`: the app built and deployed to Artifactory (available at https://gitlab.com/gitlab-examples/maven/simple-maven-dep )
-- `simple-maven-app`: the app using the previous one as a dependency (available at https://gitlab.com/gitlab-examples/maven/simple-maven-app )
+- `simple-maven-dep`: the app built and deployed to Artifactory (available at <https://gitlab.com/gitlab-examples/maven/simple-maven-dep>)
+- `simple-maven-app`: the app using the previous one as a dependency (available at <https://gitlab.com/gitlab-examples/maven/simple-maven-app>)
We assume that you already have a GitLab account on [GitLab.com](https://gitlab.com/), and that you know the basic usage of Git and [GitLab CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/).
We also assume that an Artifactory instance is available and reachable from the internet, and that you have valid credentials to deploy on it.
@@ -107,7 +107,7 @@ Now it's time we set up [GitLab CI/CD](https://about.gitlab.com/features/gitlab-
GitLab CI/CD uses a file in the root of the repo, named `.gitlab-ci.yml`, to read the definitions for jobs
that will be executed by the configured GitLab Runners. You can read more about this file in the [GitLab Documentation](https://docs.gitlab.com/ee/ci/yaml/).
-First of all, remember to set up variables for your deployment. Navigate to your project's **Settings > CI/CD > Variables** page
+First of all, remember to set up variables for your deployment. Navigate to your project's **Settings > CI/CD > Environment variables** page
and add the following ones (replace them with your current values, of course):
- **MAVEN_REPO_URL**: `http://artifactory.example.com:8081/artifactory` (your Artifactory URL)
diff --git a/doc/ci/examples/browser_performance.md b/doc/ci/examples/browser_performance.md
index 7c3b3a65675..b47038011de 100644
--- a/doc/ci/examples/browser_performance.md
+++ b/doc/ci/examples/browser_performance.md
@@ -41,7 +41,7 @@ The above example will create a `performance` job in your CI/CD pipeline and wil
Sitespeed.io against the webpage you defined in `URL` to gather key metrics.
The [GitLab plugin](https://gitlab.com/gitlab-org/gl-performance) for
Sitespeed.io is downloaded in order to save the report as a
-[Performance report artifact](https://docs.gitlab.com/ee//ci/yaml/README.html#artifactsreportsperformance)
+[Performance report artifact](../yaml/README.md#artifactsreportsperformance-premium)
that you can later download and analyze.
Due to implementation limitations we always take the latest Performance artifact available.
diff --git a/doc/ci/examples/code_quality.md b/doc/ci/examples/code_quality.md
index ae000b9d30d..3e7d6e7e3f7 100644
--- a/doc/ci/examples/code_quality.md
+++ b/doc/ci/examples/code_quality.md
@@ -36,7 +36,7 @@ code_quality:
The above example will create a `code_quality` job in your CI/CD pipeline which
will scan your source code for code quality issues. The report will be saved as a
-[Code Quality report artifact](../../ci/yaml/README.md#artifactsreportscodequality)
+[Code Quality report artifact](../yaml/README.md#artifactsreportscodequality-starter)
that you can later download and analyze.
Due to implementation limitations we always take the latest Code Quality artifact available.
diff --git a/doc/ci/examples/container_scanning.md b/doc/ci/examples/container_scanning.md
index 68330261910..e8e9c73d1b2 100644
--- a/doc/ci/examples/container_scanning.md
+++ b/doc/ci/examples/container_scanning.md
@@ -22,7 +22,7 @@ container_scanning:
variables:
DOCKER_DRIVER: overlay2
## Define two new variables based on GitLab's CI/CD predefined variables
- ## https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables
+ ## https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables
CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
CI_APPLICATION_TAG: $CI_COMMIT_SHA
allow_failure: true
@@ -51,7 +51,7 @@ The above example will create a `container_scanning` job in your CI/CD pipeline,
the image from the [Container Registry](../../user/project/container_registry.md)
(whose name is defined from the two `CI_APPLICATION_` variables) and scan it
for possible vulnerabilities. The report will be saved as a
-[Container Scanning report artifact](https://docs.gitlab.com/ee//ci/yaml/README.html#artifactsreportscontainer_scanning)
+[Container Scanning report artifact](../yaml/README.md#artifactsreportscontainer_scanning-ultimate)
that you can later download and analyze.
Due to implementation limitations we always take the latest Container Scanning artifact available.
@@ -87,7 +87,7 @@ container_scanning:
variables:
DOCKER_DRIVER: overlay2
## Define two new variables based on GitLab's CI/CD predefined variables
- ## https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables
+ ## https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables
CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
CI_APPLICATION_TAG: $CI_COMMIT_SHA
allow_failure: true
diff --git a/doc/ci/examples/dast.md b/doc/ci/examples/dast.md
index 0ca89eb6700..ab0ca13d2cf 100644
--- a/doc/ci/examples/dast.md
+++ b/doc/ci/examples/dast.md
@@ -40,7 +40,7 @@ dast:
The above example will create a `dast` job in your CI/CD pipeline which will run
the tests on the URL defined in the `website` variable (change it to use your
own) and scan it for possible vulnerabilities. The report will be saved as a
-[DAST report artifact](https://docs.gitlab.com/ee//ci/yaml/README.html#artifactsreportsdast)
+[DAST report artifact](../yaml/README.md#artifactsreportsdast-ultimate)
that you can later download and analyze.
Due to implementation limitations we always take the latest DAST artifact available.
diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
index 40ceef3d554..474a481836a 100644
--- a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
+++ b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
@@ -104,7 +104,7 @@ to ensure our deployments only happen when we push to the master branch.
Now, since the steps defined in `.gitlab-ci.yml` require credentials to login
to CF, you'll need to add your CF credentials as [environment
-variables](../../variables/README.md#predefined-variables-environment-variables)
+variables](../../variables/README.md#predefined-environment-variables)
on GitLab CI/CD. To set the environment variables, navigate to your project's
**Settings > CI/CD** and expand **Variables**. Name the variables
`CF_USERNAME` and `CF_PASSWORD` and set them to the correct values.
@@ -112,7 +112,7 @@ on GitLab CI/CD. To set the environment variables, navigate to your project's
![Variable Settings in GitLab](img/cloud_foundry_variables.png)
Once set up, GitLab CI/CD will deploy your app to CF at every push to your
-repository's deafult branch. To see the build logs or watch your builds running
+repository's default branch. To see the build logs or watch your builds running
live, navigate to **CI/CD > Pipelines**.
CAUTION: **Caution:**
@@ -138,5 +138,5 @@ buildpack: client-certificate-mapper=1.2.0_RELEASE container-security-provider=1
```
You can then visit your deployed application (for this example,
-https://gitlab-hello-world-undissembling-hotchpot.cfapps.io/) and you should
+`https://gitlab-hello-world-undissembling-hotchpot.cfapps.io/`) and you should
see the "Spring is here!" message.
diff --git a/doc/ci/examples/deployment/README.md b/doc/ci/examples/deployment/README.md
index 46effb76d71..010ba6b66a2 100644
--- a/doc/ci/examples/deployment/README.md
+++ b/doc/ci/examples/deployment/README.md
@@ -6,7 +6,7 @@ used with GitLab CI.
>**Note:**
We recommend to use Dpl if you're deploying to any of these services:
-https://github.com/travis-ci/dpl#supported-providers.
+<https://github.com/travis-ci/dpl#supported-providers>.
## Requirements
@@ -34,7 +34,7 @@ The Dpl provides support for vast number of services, including: Heroku, Cloud F
To use it simply define provider and any additional parameters required by the provider.
For example if you want to use it to deploy your application to heroku, you need to specify `heroku` as provider, specify `api-key` and `app`.
-There's more and all possible parameters can be found here: https://github.com/travis-ci/dpl#heroku
+There's more and all possible parameters can be found here: <https://github.com/travis-ci/dpl#heroku>.
```yaml
staging:
diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md
index 36358515b84..4758ccad5aa 100644
--- a/doc/ci/examples/deployment/composer-npm-deploy.md
+++ b/doc/ci/examples/deployment/composer-npm-deploy.md
@@ -4,7 +4,6 @@ This guide covers the building dependencies of a PHP project while compiling ass
While is possible to create your own image with custom PHP and Node JS versions, for brevity, we will use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and NodeJS installed.
-
```yaml
image: tetraweb/php
```
diff --git a/doc/ci/examples/end_to_end_testing_webdriverio/img/deployed_dependency_update.png b/doc/ci/examples/end_to_end_testing_webdriverio/img/deployed_dependency_update.png
new file mode 100644
index 00000000000..c45d70d7f7a
--- /dev/null
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/img/deployed_dependency_update.png
Binary files differ
diff --git a/doc/ci/examples/end_to_end_testing_webdriverio/index.md b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
new file mode 100644
index 00000000000..d7afe11f41f
--- /dev/null
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
@@ -0,0 +1,251 @@
+---
+author: Vincent Tunru
+author_gitlab: Vinnl
+level: advanced
+article_type: user guide
+date: 2019-02-18
+description: 'Confidence checking your entire app every time a new feature is added can quickly become repetitive. Learn how to automate it with GitLab CI/CD.'
+---
+
+# End-to-end testing with GitLab CI/CD and WebdriverIO
+
+[Review Apps](../../review_apps/index.md) are great: for every merge request
+(or branch, for that matter), the new code can be copied and deployed to a fresh production-like live
+environment, making it incredibly low-effort to assess the impact of the changes. Thus, when we use a dependency manager like
+[Dependencies.io](https://www.dependencies.io/), it can submit a merge request with an updated dependency,
+and it will immediately be clear that the application can still be properly built and deployed. After all, you can _see_ it
+running!
+
+<img src="img/deployed_dependency_update.png" alt="dependencies.io" class="image-noshadow">
+
+However, looking at the freshly deployed code to check whether it still looks and behaves as
+expected is repetitive manual work, which means it is a prime candidate for automation. This is
+where automated [end-to-end testing](https://martinfowler.com/bliki/BroadStackTest.html) comes in:
+having the computer run through a few simple scenarios that requires the proper functioning of all
+layers of your application, from the frontend to the database. In this article, we will discuss how
+to write such end-to-end tests, and how to set up GitLab CI/CD to automatically run these tests
+against your new code, on a branch-by-branch basis. For the scope of this article, we will walk you
+through the process of setting up GitLab CI/CD for end-to-end testing Javascript-based applications
+with WebdriverIO, but the general strategy should carry over to other languages.
+We assume you are familiar with GitLab, [GitLab CI/CD](../../README.md), [Review Apps](../../review_apps/index.md), and running your app locally, e.g., on `localhost:8000`.
+
+### What to test
+
+In the widely-used [testing pyramid strategy](https://martinfowler.com/bliki/TestPyramid.html), end-to-end tests act more like a
+safeguard: [most of your code should be covered by
+unit tests](https://vincenttunru.com/100-percent-coverage/) that allow you to easily identify the source of a problem, should one occur. Rather, you
+will likely want to
+[limit the number of end-to-end tests](https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html)
+to just enough to give you the confidence that the deployment went as intended, that your
+infrastructure is up and running, and that your units of code work well together.
+
+### Selenium and WebdriverIO
+
+[Selenium](http://www.seleniumhq.org/) is a piece of software that can control web browsers, e.g., to make them
+visit a specific URL or interact with elements on the page. It can be programmatically controlled
+from a variety of programming languages. In this article we're going to be using the
+[WebdriverIO](http://webdriver.io/) Javascript bindings, but the general concept should carry over
+pretty well to
+[other programming languages supported by Selenium](http://docs.seleniumhq.org/about/platforms.jsp#programming-languages).
+
+## Writing tests
+
+You can write tests using
+[several testing frameworks supported by WebdriverIO](http://webdriver.io/guide/testrunner/frameworks.html).
+We will be using [Jasmine](https://jasmine.github.io/) here:
+
+```javascript
+describe('A visitor without account', function(){
+ it('should be able to navigate to the homepage from the 404 page', function(){
+ browser.url('/page-that-does-not-exist');
+
+ expect(browser.getUrl()).toMatch('page-that-does-not-exist');
+
+ browser.element('.content a[href="/"]').click();
+
+ expect(browser.getUrl()).not.toMatch('page-that-does-not-exist');
+ });
+});
+```
+
+The functions `describe`, `it`, and `browser` are provided by WebdriverIO. Let's break them down one by one.
+
+The function `describe` allows you to group related tests. This can be useful if, for example, you want to
+run the same initialization commands (using [`beforeEach`](https://jasmine.github.io/api/2.9/global.html#beforeEach)) for
+multiple tests, such as making sure you are logged in.
+
+The function `it` defines an individual test.
+
+[The `browser` object](http://webdriver.io/guide/testrunner/browserobject.html) is WebdriverIO's
+special sauce. It provides most of [the WebdriverIO API methods](http://webdriver.io/api.html) that are the key to
+steering the browser. In this case, we can use
+[`browser.url`](http://webdriver.io/api/protocol/url.html) to visit `/page-that-does-not-exist` to
+hit our 404 page. We can then use [`browser.getUrl`](http://webdriver.io/api/property/getUrl.html)
+to verify that the current page is indeed at the location we specified. To interact with the page,
+we can simply pass CSS selectors to
+[`browser.element`](http://webdriver.io/api/protocol/element.html) to get access to elements on the
+page and to interact with them - for example, to click on the link back to the home page.
+
+The simple test shown above
+can already give us a lot of confidence if it passes: we know our deployment has succeeded, that the
+elements are visible on the page and that actual browsers can interact with it, and that routing
+works as expected. And all that in just 10 lines with gratuitous whitespace! Add to that succeeding
+unit tests and a successfully completed pipeline, and you can be fairly confident that the
+dependency upgrade did not break anything without even having to look at your website.
+
+## Running locally
+
+We'll get to running the above test in CI/CD in a moment. When writing tests, however, it helps if
+you do not have to wait for your pipelines to succeed in order to check whether they do what you
+expect them to do. In other words, let's get it to run locally.
+
+Make sure that your app is running locally. If you use Webpack,
+you can use [the Webpack Dev Server WebdriverIO plugin](https://www.npmjs.com/package/wdio-webpack-dev-server-service)
+that automatically starts a development server before executing the tests.
+
+The WebdriverIO documentation has
+[an overview of all configuration options](http://webdriver.io/guide/getstarted/configuration.html), but the
+easiest way to get started is to start with
+[WebdriverIO's default configuration](http://webdriver.io/guide/testrunner/configurationfile.html), which
+provides an overview of all available options. The two options that are going to be most relevant now are the
+`specs` option, which is an array of paths to your tests, and the `baseUrl` option, which points to where your app is
+running. And finally, we will need to tell WebdriverIO in which browsers we would like to run our
+tests. This can be configured through the `capabilities` option, which is an array of browser names (e.g.
+`firefox` or `chrome`). It is recommended to install
+[selenium-assistant](https://googlechromelabs.github.io/selenium-assistant/) to detect all installed
+browsers:
+
+```javascript
+ const seleniumAssistant = require('selenium-assistant');
+ const browsers = seleniumAssistant.getLocalBrowsers();
+ config.capabilities = browsers.map(browser => ({ browserName: browser.getId() }));
+```
+
+But of course, a simple configuration of `config.capabilities = ['firefox']` would work as well.
+
+If you've installed WebdriverIO as a dependency
+(`npm install --save-dev webdriverio`), you can add a line to the `scripts` property in your
+`package.json` that runs `wdio` with the path to your configuration file as value, e.g.:
+
+```javascript
+ "confidence-check": "wdio wdio.conf.js",
+```
+
+You can then execute the tests using `npm run confidence-check`, after which you will actually see a
+new browser window interacting with your app as you specified.
+
+## Configuring GitLab CI/CD
+
+Which brings us to the exciting part: how do we run this in GitLab CI/CD? There are two things we
+need to do for this:
+
+1. Set up [CI/CD jobs](../../yaml/README.md#jobs) that actually have a browser available.
+2. Update our WebdriverIO configuration to use those browsers to visit the review apps.
+
+For the scope of this article, we've defined an additional [CI/CD stage](../../yaml/README.md#stages)
+`confidence-check` that is executed _after_ the stage that deploys the review app. It uses the `node:latest` [Docker
+image](../../docker/using_docker_images.html). However, WebdriverIO fires up actual browsers
+to interact with your application, so we need to install and run them.
+Furthermore, WebdriverIO uses Selenium as a common interface to control different browsers,
+so we need to install and run Selenium as well. Luckily, the Selenium project provides the Docker images
+[standalone-firefox](https://hub.docker.com/r/selenium/standalone-firefox/) and
+[standalone-chrome](https://hub.docker.com/r/selenium/standalone-chrome/) that provide just that for
+Firefox and Chrome, respectively. (Since Safari and Internet Explorer/Edge are not open source and
+not available for Linux, we are unfortunately unable to use those in GitLab CI/CD).
+
+GitLab CI/CD makes it a breeze to link these images to our `confidence-check` jobs using the
+`service` property, which makes the Selenium server available under a hostname based on the image
+name. Our job configuration then looks something like this:
+
+```yaml
+e2e:firefox:
+ stage: confidence-check
+ services:
+ - selenium/standalone-firefox
+ script:
+ - npm run confidence-check --host=selenium__standalone-firefox
+```
+
+And likewise for Chrome:
+
+```yaml
+e2e:chrome:
+ stage: confidence-check
+ services:
+ - selenium/standalone-chrome
+ script:
+ - npm run confidence-check --host=selenium__standalone-chrome
+```
+
+Now that we have a job to run the end-to-end tests in, we need to tell WebdriverIO how to connect to
+the Selenium servers running alongside it. We've already cheated a bit above by
+passing the value of the [`host`](http://webdriver.io/guide/getstarted/configuration.html#host)
+option as an argument to `npm run confidence-check` on the command line.
+However, we still need to tell WebdriverIO which browser is available for it to use.
+
+[GitLab CI/CD makes
+a number of variables available](../../variables/README.html#predefined-variables-environment-variables)
+with information about the current CI job. We can use this information to dynamically set
+up our WebdriverIO configuration according to the job that is running. More specifically, we can
+tell WebdriverIO what browser to execute the test on depending on the name of the currently running
+job. We can do so in WebdriverIO's configuration file, which we named `wdio.conf.js` above:
+
+```javascript
+if(process.env.CI_JOB_NAME) {
+ dynamicConfig.capabilities = [
+ { browserName: process.env.CI_JOB_NAME === 'e2e:chrome' ? 'chrome' : 'firefox' },
+ ];
+}
+```
+
+Likewise, we can tell WebdriverIO where the review app is running - in this example's case, it's on
+`<branch name>.flockademic.com`:
+
+```javascript
+if(process.env.CI_COMMIT_REF_SLUG) {
+ dynamicConfig.baseUrl = `https://${process.env.CI_COMMIT_REF_SLUG}.flockademic.com`;
+}
+```
+
+And we can make sure our local-specific configuration is only used when _not_ running in CI using
+`if (!process.env.CI)`. That's basically all the ingredients you need to run your end-to-end tests
+on GitLab CI/CD!
+
+To recap, our `.gitlab-ci.yml` configuration file looks something like this:
+
+```yaml
+image: node:8.10
+stages:
+ - deploy
+ - confidence-check
+deploy_terraform:
+ stage: deploy
+ script:
+ # Your Review App deployment scripts - for a working example please check https://gitlab.com/Flockademic/Flockademic/blob/5a45f1c2412e93810fab50e2dab8949e2d0633c7/.gitlab-ci.yml#L315
+e2e:firefox:
+ stage: confidence-check
+ services:
+ - selenium/standalone-firefox
+ script:
+ - npm run confidence-check --host=selenium__standalone-firefox
+e2e:chrome:
+ stage: confidence-check
+ services:
+ - selenium/standalone-chrome
+ script:
+ - npm run confidence-check --host=selenium__standalone-chrome
+```
+
+## What's next
+
+If you are setting this up for yourself and want to peek at the working configuration of a
+production project, see:
+
+- [Flockademic's `wdio.conf.js`](https://gitlab.com/Flockademic/Flockademic/blob/dev/wdio.conf.js)
+- [Flockademic's `.gitlab-ci.yml`](https://gitlab.com/Flockademic/Flockademic/blob/dev/.gitlab-ci.yml)
+- [Flockademic's tests](https://gitlab.com/Flockademic/Flockademic/tree/dev/__e2e__)
+
+There's plenty more that WebdriverIO can do. For example, you can configure a [`screenshotPath`](http://webdriver.io/guide/getstarted/configuration.html#screenshotPath) to tell WebdriverIO to take
+a screenshot when tests are failing. Then tell GitLab CI/CD to store those
+[artifacts](../../yaml/README.md#artifacts), and you'll be able to see what went
+wrong within GitLab.
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
index b1ccce744d8..d3b6650b0f4 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -68,7 +68,6 @@ Since we have our app up and running locally, it's time to push the codebase to
Let's create [a new project](../../../gitlab-basics/create-project.md) in GitLab named `laravel-sample`.
After that, follow the command line instructions displayed on the project's homepage to initiate the repository on our machine and push the first commit.
-
```bash
cd laravel-sample
git init
@@ -127,7 +126,6 @@ We'll use this variable in the `.gitlab-ci.yml` later, to easily connect to our
We also need to add the public key to **Project** > **Settings** > **Repository** as a [Deploy Key](../../../ssh/README.md#deploy-keys), which gives us the ability to access our repository from the server through [SSH protocol](../../../gitlab-basics/command-line-commands.md#start-working-on-your-project).
-
```bash
# As the deployer user on the server
#
@@ -186,7 +184,6 @@ To use Envoy, we should first install it on our local machine [using the given i
The pros of Envoy is that it doesn't require Blade engine, it just uses Blade syntax to define tasks.
To start, we create an `Envoy.blade.php` in the root of our app with a simple task to test Envoy.
-
```php
@servers(['web' => 'remote_username@remote_host'])
@@ -220,7 +217,6 @@ Our deployment plan is to clone the latest release from GitLab repository, insta
The first step of our deployment process is to define a set of variables within [@setup](https://laravel.com/docs/envoy/#setup) directive.
You may change the `app` to your application's name:
-
```php
...
@@ -246,7 +242,6 @@ You may change the `app` to your application's name:
The [@story](https://laravel.com/docs/envoy/#stories) directive allows us define a list of tasks that can be run as a single task.
Here we have three tasks called `clone_repository`, `run_composer`, `update_symlinks`. These variables are usable to making our task's codes more cleaner:
-
```php
...
@@ -618,7 +613,7 @@ Lastly, `when: manual` is used to turn the job from running automatically to a m
deploy_production:
script:
- # Add the private SSH key to the build environment
+ # Add the private SSH key to the build environment
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- ssh-add <(echo "$SSH_PRIVATE_KEY")
diff --git a/doc/ci/examples/sast_docker.md b/doc/ci/examples/sast_docker.md
index 9f4a63e296d..3a657b3a3d5 100644
--- a/doc/ci/examples/sast_docker.md
+++ b/doc/ci/examples/sast_docker.md
@@ -1 +1 @@
-This document was moved to [another location](./container_scanning.md). \ No newline at end of file
+This document was moved to [another location](./container_scanning.md).
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index ec0b5aaed09..61bf68fa0e8 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -47,7 +47,7 @@ This project has three jobs:
## Store API keys
-You'll need to create two variables in `Settings > CI/CD > Variables` on your GitLab project settings:
+You'll need to create two variables in **Settings > CI/CD > Environment variables** in your GitLab project:
- `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app.
- `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
index 33a353f17f5..46e6efccaf8 100644
--- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
@@ -43,7 +43,7 @@ This project has three jobs:
## Store API keys
-You'll need to create two variables in your project's **Settings > CI/CD > Variables**:
+You'll need to create two variables in your project's **Settings > CI/CD > Environment variables**:
- `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app.
- `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
index c0346d78141..f24e79355aa 100644
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
@@ -75,7 +75,7 @@ When we call `mix` command, we'll pass two arguments:
- The task we want it to run: `phoenix.new`
- And the parameter `phoenix.new` requires, which is the name of the new project. In this case,
-we're calling it `hello_gitlab_ci`, but you're free to set your own name:
+ we're calling it `hello_gitlab_ci`, but you're free to set your own name:
```bash
mix phoenix.new hello_gitlab_ci
@@ -249,7 +249,7 @@ project.
![Set up CI](img/setup-ci.png)
- On next screen, we can select a template ready to go. Click on **Apply a GitLab CI/CD Yaml
-template** and select **Elixir**:
+ template** and select **Elixir**:
![Select template](img/select-template.png)
diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md
index d299e28d2e6..2a4160f62b0 100644
--- a/doc/ci/interactive_web_terminal/index.md
+++ b/doc/ci/interactive_web_terminal/index.md
@@ -1,15 +1,19 @@
-# Interactive Web Terminals **[CORE ONLY]**
+# Interactive Web Terminals
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/50144) in GitLab 11.3.
Interactive web terminals give the user access to a terminal in GitLab for
-running one-off commands for their CI pipeline.
+running one-off commands for their CI pipeline. Since this is giving the user
+shell access to the environment where [GitLab Runner](https://docs.gitlab.com/runner/)
+is deployed, some [security precautions](../../administration/integration/terminal.md#security) were
+taken to protect the users.
NOTE: **Note:**
-GitLab.com does not support interactive web terminal at the moment – neither
-using shared GitLab.com runners nor your own runners. Please follow
-[this issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/52611) for
-progress.
+[Shared runners on GitLab.com](../quick_start/README.md#shared-runners) do not
+provide an interactive web terminal. Follow [this
+issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/52611) 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.
## Configuration
diff --git a/doc/ci/junit_test_reports.md b/doc/ci/junit_test_reports.md
index 91a0ae327bf..cf18c6d9660 100644
--- a/doc/ci/junit_test_reports.md
+++ b/doc/ci/junit_test_reports.md
@@ -69,7 +69,7 @@ collects the JUnit test report from each job. After each job is executed, the
XML reports are stored in GitLab as artifacts and their results are shown in the
merge request widget.
-NOTE: **Note:**
+NOTE: **Note:**
If you also want the ability to browse JUnit output files, include the
[`artifacts:paths`](yaml/README.md#artifactspaths) keyword.
@@ -151,7 +151,7 @@ There are a few tools that can produce JUnit reports in C/C++.
#### GoogleTest
In the following example, `gtest` is used to generate the test reports.
-If there are multiple gtest executables created for different architectures (`x86`, `x64` or `arm`),
+If there are multiple gtest executables created for different architectures (`x86`, `x64` or `arm`),
you will be required to run each test providing a unique filename. The results
will then be aggregated together.
@@ -171,4 +171,4 @@ Currently, the following tools might not work because their XML formats are unsu
|Case|Tool|Issue|
|---|---|---|
-|`<testcase>` does not have `classname` attribute|ESlint, sass-lint|https://gitlab.com/gitlab-org/gitlab-ce/issues/50964|
+|`<testcase>` does not have `classname` attribute|ESlint, sass-lint|<https://gitlab.com/gitlab-org/gitlab-ce/issues/50964>|
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index bf1e61442d4..2af0a03cbe4 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -56,6 +56,49 @@ The same tag is shown on the pipeline's details:
![Pipeline's details](img/pipeline_detail.png)
+## Excluding certain jobs
+
+The behavior of the `only: merge_requests` rule is such that _only_ jobs with
+that rule are run in the context of a merge request; no other jobs will be run.
+
+However, you may want to reverse this behaviour, having all of your jobs to run _except_
+for one or two. Consider the following pipeline, with jobs `A`, `B`, and `C`. If you want
+all pipelines to always run `A` and `B`, but only want `C` to run for a merge request,
+you can configure your `.gitlab-ci.yml` file as follows:
+
+``` yaml
+.only-default: &only-default
+ only:
+ - master
+ - merge_requests
+ - tags
+
+A:
+ <<: *only-default
+ script:
+ - ...
+
+B:
+ <<: *only-default
+ script:
+ - ...
+
+C:
+ script:
+ - ...
+ only:
+ - merge_requests
+```
+
+Since `A` and `B` are getting the `only:` rule to execute in all cases, they will
+always run. `C` specifies that it should only run for merge requests, so for any
+pipeline except a merge request pipeline, it will not run.
+
+As you can see, this will help you avoid a lot of boilerplate where you'd need
+to add that `only:` rule to all of your jobs in order to make them always run. You
+can use this for scenarios like having only pipelines with merge requests get a
+Review App set up, helping to save resources.
+
## Important notes about merge requests from forked projects
Note that the current behavior is subject to change. In the usual contribution
@@ -63,10 +106,10 @@ flow, external contributors follow the following steps:
1. Fork a parent project.
1. Create a merge request from the forked project that targets the `master` branch
-in the parent project.
+ in the parent project.
1. A pipeline runs on the merge request.
1. A maintainer from the parent project checks the pipeline result, and merge
-into a target branch if the latest pipeline has passed.
+ into a target branch if the latest pipeline has passed.
Currently, those pipelines are created in a **forked** project, not in the
parent project. This means you cannot completely trust the pipeline result,
diff --git a/doc/ci/pipelines.md b/doc/ci/pipelines.md
index f8cf9de9aff..4f3106c6dc6 100644
--- a/doc/ci/pipelines.md
+++ b/doc/ci/pipelines.md
@@ -3,7 +3,7 @@
> Introduced in GitLab 8.8.
NOTE: **Note:**
-If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository),
+If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository-starter),
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
@@ -197,7 +197,7 @@ stage has a job with a manual action.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21767) in GitLab 11.4.
-When you do not want to run a job immediately, you can [delay the job to run after a certain period](yaml/README.md#when-delayed).
+When you do not want to run a job immediately, you can [delay the job to run after a certain period](yaml/README.md#whendelayed).
This is especially useful for timed incremental rollout that new code is rolled out gradually.
For example, if you start rolling out new code and users do not experience trouble, GitLab automatically completes the deployment from 0% to 100%.
Alternatively, if you start rolling out and you noticed that a few users experience trouble with the version,
@@ -241,9 +241,9 @@ So each job would be represented as a `Period`, which consists of
`Period#first` as when the job started and `Period#last` as when the
job was finished. A simple example here would be:
-* A (1, 3)
-* B (2, 4)
-* C (6, 7)
+- A (1, 3)
+- B (2, 4)
+- C (6, 7)
Here A begins from 1, and ends to 3. B begins from 2, and ends to 4.
C begins from 6, and ends to 7. Visually it could be viewed as:
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index bdc593493ea..9684cb6ed98 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -77,7 +77,7 @@ before_script:
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
+ - gem install bundler --no-document
- bundle install --jobs $(nproc) "${FLAGS[@]}"
rspec:
@@ -127,7 +127,7 @@ Now if you go to the **Pipelines** page you will see that the pipeline is
pending.
NOTE: **Note:**
-If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository),
+If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository-starter),
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
diff --git a/doc/ci/img/view_on_env_blob.png b/doc/ci/review_apps/img/view_on_env_blob.png
index acc457fbb38..acc457fbb38 100644
--- a/doc/ci/img/view_on_env_blob.png
+++ b/doc/ci/review_apps/img/view_on_env_blob.png
Binary files differ
diff --git a/doc/ci/img/view_on_env_mr.png b/doc/ci/review_apps/img/view_on_env_mr.png
index 2c0bd25a4f2..2c0bd25a4f2 100644
--- a/doc/ci/img/view_on_env_mr.png
+++ b/doc/ci/review_apps/img/view_on_env_mr.png
Binary files differ
diff --git a/doc/ci/img/view_on_mr_widget.png b/doc/ci/review_apps/img/view_on_mr_widget.png
index efe023b07b5..efe023b07b5 100644
--- a/doc/ci/img/view_on_mr_widget.png
+++ b/doc/ci/review_apps/img/view_on_mr_widget.png
Binary files differ
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 64be011008e..f4d7b9ad194 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -60,7 +60,7 @@ To get a better understanding of Review Apps, review documentation on how enviro
1. Learn about [environments](../environments.md) and their role in the development workflow.
1. Learn about [CI variables](../variables/README.md) and how they can be used in your CI jobs.
1. Explore the [`environment` syntax](../yaml/README.md#environment) as defined in `.gitlab-ci.yml`. This will become a primary reference.
-1. Additionally, find out about [manual actions](../environments.md#manual-actions) and how you can use them to deploy to critical environments like production with the push of a button.
+1. Additionally, find out about [manual actions](../environments.md#manually-deploying-to-environments) and how you can use them to deploy to critical environments like production with the push of a button.
1. Follow the [example tutorials](#examples). These will guide you through setting up infrastructure and using Review Apps.
### Configuring dynamic environments
@@ -102,3 +102,88 @@ The following are example projects that use Review Apps with:
- [OpenShift](https://gitlab.com/gitlab-examples/review-apps-openshift).
See also the video [Demo: Cloud Native Development with GitLab](https://www.youtube.com/watch?v=jfIyQEwrocw), which includes a Review Apps example.
+
+## Route Maps
+
+> Introduced in GitLab 8.17. In GitLab 11.5 the file links
+are surfaced to the merge request widget.
+
+Route Maps allows you to go directly from source files
+to public pages on the [environment](../environments.md) defined for
+Review Apps. Once set up, the review app link in the merge request
+widget can take you directly to the pages changed, making it easier
+and faster to preview proposed modifications.
+
+All you need to do is to tell GitLab how the paths of files
+in your repository map to paths of pages on your website using a Route Map.
+Once set, GitLab will display **View on ...** buttons, which will take you
+to the pages changed directly from merge requests.
+
+To set up a route map, add a a file inside the repository at `.gitlab/route-map.yml`,
+which contains a YAML array that maps `source` paths (in the repository) to `public`
+paths (on the website).
+
+### Route Maps example
+
+Below there's an example of a route map for [Middleman](https://middlemanapp.com),
+a static site generator (SSG) used to build [GitLab's website](https://about.gitlab.com),
+deployed from its [project on GitLab.com](https://gitlab.com/gitlab-com/www-gitlab-com):
+
+```yaml
+# Team data
+- source: 'data/team.yml' # data/team.yml
+ public: 'team/' # team/
+
+# Blogposts
+- source: /source\/posts\/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.+?)\..*/ # source/posts/2017-01-30-around-the-world-in-6-releases.html.md.erb
+ public: '\1/\2/\3/\4/' # 2017/01/30/around-the-world-in-6-releases/
+
+# HTML files
+- source: /source\/(.+?\.html).*/ # source/index.html.haml
+ public: '\1' # index.html
+
+# Other files
+- source: /source\/(.*)/ # source/images/blogimages/around-the-world-in-6-releases-cover.png
+ public: '\1' # images/blogimages/around-the-world-in-6-releases-cover.png
+```
+
+Mappings are defined as entries in the root YAML array, and are identified by a `-` prefix. Within an entry, we have a hash map with two keys:
+
+- `source`
+ - a string, starting and ending with `'`, for an exact match
+ - a regular expression, starting and ending with `/`, for a pattern match
+ - The regular expression needs to match the entire source path - `^` and `$` anchors are implied.
+ - Can include capture groups denoted by `()` that can be referred to in the `public` path.
+ - Slashes (`/`) can, but don't have to, be escaped as `\/`.
+ - Literal periods (`.`) should be escaped as `\.`.
+- `public`
+ - a string, starting and ending with `'`.
+ - Can include `\N` expressions to refer to capture groups in the `source` regular expression in order of their occurrence, starting with `\1`.
+
+The public path for a source path is determined by finding the first
+`source` expression that matches it, and returning the corresponding
+`public` path, replacing the `\N` expressions with the values of the
+`()` capture groups if appropriate.
+
+In the example above, the fact that mappings are evaluated in order
+of their definition is used to ensure that `source/index.html.haml`
+will match `/source\/(.+?\.html).*/` instead of `/source\/(.*)/`,
+and will result in a public path of `index.html`, instead of
+`index.html.haml`.
+
+Once you have the route mapping set up, it will be exposed in a few places:
+
+- In the merge request widget. The **View app** button will take you to the
+ environment URL you have set up in `.gitlab-ci.yml`. The dropdown will render
+ the first 5 matched items from the route map, but you can filter them if more
+ than 5 are available.
+
+ ![View app file list in merge request widget](img/view_on_mr_widget.png)
+
+- In the diff for a merge request, comparison, or commit.
+
+ !["View on env" button in merge request diff](img/view_on_env_mr.png)
+
+- In the blob file view.
+
+ !["View on env" button in file view](img/view_on_env_blob.png)
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index 9c9ea651678..ce55b231666 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -135,6 +135,14 @@ Consider that if you don't lock your specific Runner to a specific project, any
user with Maintainer role in you project can assign your Runner to another arbitrary
project without requiring your authorization, so use it with caution.
+CAUTION: **Caution:**
+Never add a private Runner that you're using in your private projects to a
+project that you share with other people.
+
+CAUTION: **Caution:**
+Never use a Runner from a project which has multiple maintainers in your
+private project.
+
An admin can enable/disable a specific Runner for projects:
1. Navigate to **Admin > Runners**
@@ -232,21 +240,64 @@ shared Runners will [only run the jobs they are equipped to run](../yaml/README.
For instance, at GitLab we have Runners tagged with "rails" if they contain
the appropriate dependencies to run Rails test suites.
-### Preventing Runners with tags from picking jobs without tags
+### Allowing Runners with tags to pick jobs without tags
-You can configure a Runner to prevent it from picking
-[jobs with tags](../yaml/README.md#tags) when the Runner does not have tags
-assigned. This setting can be enabled the first
-time you [register a Runner][register] and can be changed afterwards under
-each Runner's settings.
+When you [register a Runner][register], its default behavior is to **only pick**
+[tagged jobs](../yaml/README.md#tags).
-To make a Runner pick tagged/untagged jobs:
+NOTE: **Note:**
+Maintainer [permissions](../../user/permissions.md) are required to change the
+Runner settings.
-1. Visit your project's **Settings âž” CI/CD**
-1. Find the Runner you wish and make sure it's enabled
-1. Click the pencil button
-1. Check the **Run untagged jobs** option
-1. Click **Save changes** for the changes to take effect
+To make a Runner pick untagged jobs:
+
+1. Visit your project's **Settings > CI/CD > Runners**.
+1. Find the Runner you want to pick untagged jobs and make sure it's enabled.
+1. Click the pencil button.
+1. Check the **Run untagged jobs** option.
+1. Click the **Save changes** button for the changes to take effect.
+
+NOTE: **Note:**
+The Runner tags list can not be empty when it's not allowed to pick untagged jobs.
+
+Below are some example scenarios of different variations.
+
+#### Runner runs only tagged jobs
+
+The following examples illustrate the potential impact of the Runner being set
+to run only tagged jobs.
+
+Example 1:
+
+1. The Runner is configured to run only tagged jobs and has the `docker` tag.
+1. A job that has a `hello` tag is executed and stuck.
+
+Example 2:
+
+1. The Runner is configured to run only tagged jobs and has the `docker` tag.
+1. A job that has a `docker` tag is executed and run.
+
+Example 3:
+
+1. The Runner is configured to run only tagged jobs and has the `docker` tag.
+1. A job that has no tags defined is executed and stuck.
+
+#### Runner is allowed to run untagged jobs
+
+The following examples illustrate the potential impact of the Runner being set
+to run tagged and untagged jobs.
+
+Example 1:
+
+1. The Runner is configured to run untagged jobs and has the `docker` tag.
+1. A job that has no tags defined is executed and run.
+1. A second job that has a `docker` tag defined is executed and run.
+
+Example 2:
+
+1. The Runner is configured to run untagged jobs and has no tags defined.
+1. A job that has no tags defined is executed and run.
+1. A second job that has a `docker` tag defined is stuck.
### Setting maximum job timeout for a Runner
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index b76f9618fc9..2902c30c7c0 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -16,7 +16,7 @@ services:
- mysql:latest
variables:
- # Configure mysql environment variables (https://hub.docker.com/r/_/mysql/)
+ # Configure mysql environment variables (https://hub.docker.com/_/mysql/)
MYSQL_DATABASE: el_duderino
MYSQL_ROOT_PASSWORD: mysql_strong_password
```
@@ -114,5 +114,5 @@ available [shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
moments the changes will be picked by a public runner and the job will begin.
-[hub-mysql]: https://hub.docker.com/r/_/mysql/
+[hub-mysql]: https://hub.docker.com/_/mysql/
[mysql-example-repo]: https://gitlab.com/gitlab-examples/mysql
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index 0c3b0bf6990..ff63d0bd69f 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -92,7 +92,7 @@ to access it. This is where an SSH key pair comes in handy.
```
NOTE: **Note:**
- The [`before_script`](../yaml/README.md#before-script) can be set globally
+ The [`before_script`](../yaml/README.md#before_script-and-after_script) can be set globally
or per-job.
1. Make sure the private server's [SSH host keys are verified](#verifying-the-ssh-host-keys).
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index c9a60feb73f..61037360326 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -224,5 +224,5 @@ removed with one of the future versions of GitLab. You are advised to
[ee-2017]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2017
[ee]: https://about.gitlab.com/pricing/
[variables]: ../variables/README.md
-[predef]: ../variables/README.md#predefined-variables-environment-variables
+[predef]: ../variables/README.md#predefined-environment-variables
[registry]: ../../user/project/container_registry.md
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 209a2c15d90..6c9831dacfd 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -1,26 +1,36 @@
+---
+table_display_block: true
+---
+
# GitLab CI/CD Variables
-When receiving a job from GitLab CI, the [Runner] prepares the build environment.
-It starts by setting a list of **predefined variables** (environment variables)
-and a list of **user-defined variables**.
+When receiving a job from GitLab CI, the [Runner](https://docs.gitlab.com/runner/) prepares the build environment.
+It starts by setting a list of:
+
+- [Predefined environment variables](#predefined-environment-variables).
+- Other variables.
## Priority of variables
-The variables can be overwritten and they take precedence over each other in
-this order:
+Variables of different types can take precedence over other variables, depending on where they are defined.
+
+The order of precedence for variables is (from highest to lowest):
-1. [Trigger variables][triggers] or [scheduled pipeline variables](../../user/project/pipelines/schedules.md#making-use-of-scheduled-pipeline-variables) (take precedence over all)
-1. Project-level [variables](#variables) or [protected variables](#protected-variables)
-1. Group-level [variables](#variables) or [protected variables](#protected-variables)
-1. YAML-defined [job-level variables](../yaml/README.md#variables)
-1. YAML-defined [global variables](../yaml/README.md#variables)
-1. [Deployment variables](#deployment-variables)
-1. [Predefined variables](#predefined-variables-environment-variables) (are the
- lowest in the chain)
+1. [Trigger variables](../triggers/README.md#pass-job-variables-to-a-trigger) or [scheduled pipeline variables](../../user/project/pipelines/schedules.md#making-use-of-scheduled-pipeline-variables).
+1. Project-level [variables](#variables) or [protected variables](#protected-variables).
+1. Group-level [variables](#variables) or [protected variables](#protected-variables).
+1. YAML-defined [job-level variables](../yaml/README.md#variables).
+1. YAML-defined [global variables](../yaml/README.md#variables).
+1. [Deployment variables](#deployment-variables).
+1. [Predefined environment variables](#predefined-environment-variables).
-For example, if you define `API_TOKEN=secure` as a project variable and
-`API_TOKEN=yaml` in your `.gitlab-ci.yml`, the `API_TOKEN` will take the value
-`secure` as the project variables are higher in the chain.
+For example, you define:
+
+- `API_TOKEN=secure` as a project variable.
+- `API_TOKEN=yaml` in your `.gitlab-ci.yml`.
+
+`API_TOKEN` will take the value `secure` as the project variables take precedence over those defined
+in `.gitlab-ci.yml`.
## Unsupported variables
@@ -28,10 +38,10 @@ There are cases where some variables cannot be used in the context of a
`.gitlab-ci.yml` definition (for example under `script`). Read more
about which variables are [not supported](where_variables_can_be_used.md).
-## Predefined variables (Environment variables)
+## Predefined environment variables
Some of the predefined environment variables are available only if a minimum
-version of [GitLab Runner][runner] is used. Consult the table below to find the
+version of [GitLab Runner](https://docs.gitlab.com/runner/) is used. Consult the table below to find the
version of Runner required.
NOTE: **Note:**
@@ -43,6 +53,8 @@ future GitLab releases.**
| Variable | GitLab | Runner | Description |
|-------------------------------------------|--------|--------|-------------|
| **ARTIFACT_DOWNLOAD_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to download artifacts running a job |
+| **CHAT_INPUT** | 10.6 | all | Additional arguments passed in the [ChatOps](../chatops/README.md) command |
+| **CHAT_CHANNEL** | 10.6 | all | Source chat channel which triggered the [ChatOps](../chatops/README.md) command |
| **CI** | all | 0.4 | Mark that job is executed in CI environment |
| **CI_COMMIT_BEFORE_SHA** | 11.2 | all | The previous latest commit present on a branch before a push request. |
| **CI_COMMIT_DESCRIPTION** | 10.8 | all | The description of the commit: the message without first line, if the title is shorter than 100 characters; full message in other case. |
@@ -55,43 +67,52 @@ future GitLab releases.**
| **CI_COMMIT_TITLE** | 10.8 | all | The title of the commit - the full first line of the message |
| **CI_CONFIG_PATH** | 9.4 | 0.5 | The path to CI config file. Defaults to `.gitlab-ci.yml` |
| **CI_DEBUG_TRACE** | all | 1.7 | Whether [debug tracing](#debug-tracing) is enabled |
-| **CI_DEPLOY_PASSWORD** | 10.8 | all | Authentication password of the [GitLab Deploy Token][gitlab-deploy-token], only present if the Project has one related.|
+| **CI_DEPLOY_PASSWORD** | 10.8 | all | Authentication password of the [GitLab Deploy Token][gitlab-deploy-token], only present if the Project has one related.|
| **CI_DEPLOY_USER** | 10.8 | all | Authentication username of the [GitLab Deploy Token][gitlab-deploy-token], only present if the Project has one related.|
| **CI_DISPOSABLE_ENVIRONMENT** | all | 10.1 | Marks that the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. |
-| **CI_ENVIRONMENT_NAME** | 8.15 | all | The name of the environment for this job |
-| **CI_ENVIRONMENT_SLUG** | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, etc. |
-| **CI_ENVIRONMENT_URL** | 9.3 | all | The URL of the environment for this job |
+| **CI_ENVIRONMENT_NAME** | 8.15 | all | The name of the environment for this job. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. |
+| **CI_ENVIRONMENT_SLUG** | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, etc. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. |
+| **CI_ENVIRONMENT_URL** | 9.3 | all | The URL of the environment for this job. Only present if [`environment:url`](../yaml/README.md#environmenturl) is set. |
| **CI_JOB_ID** | 9.0 | all | The unique id of the current job that GitLab CI uses internally |
| **CI_JOB_MANUAL** | 8.12 | all | The flag to indicate that job was manually started |
| **CI_JOB_NAME** | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml` |
| **CI_JOB_STAGE** | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
| **CI_JOB_TOKEN** | 9.0 | 1.2 | Token used for authenticating with the [GitLab Container Registry][registry] and downloading [dependent repositories][dependent-repositories] |
| **CI_JOB_URL** | 11.1 | 0.5 | Job details URL |
-| **CI_MERGE_REQUEST_ID** | 11.6 | all | The ID of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) |
-| **CI_MERGE_REQUEST_IID** | 11.6 | all | The IID of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) |
-| **CI_MERGE_REQUEST_PROJECT_ID** | 11.6 | all | The ID of the project of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) |
-| **CI_MERGE_REQUEST_PROJECT_PATH** | 11.6 | all | The path of the project of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) (e.g. `namespace/awesome-project`) |
-| **CI_MERGE_REQUEST_PROJECT_URL** | 11.6 | all | The URL of the project of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) (e.g. `http://192.168.10.15:3000/namespace/awesome-project`) |
-| **CI_MERGE_REQUEST_REF_PATH** | 11.6 | all | The ref path of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md). (e.g. `refs/merge-requests/1/head`) |
-| **CI_MERGE_REQUEST_SOURCE_BRANCH_NAME** | 11.6 | all | The source branch name of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) |
-| **CI_MERGE_REQUEST_SOURCE_PROJECT_ID** | 11.6 | all | The ID of the source project of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) |
-| **CI_MERGE_REQUEST_SOURCE_PROJECT_PATH** | 11.6 | all | The path of the source project of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) |
-| **CI_MERGE_REQUEST_SOURCE_PROJECT_URL** | 11.6 | all | The URL of the source project of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) |
-| **CI_MERGE_REQUEST_TARGET_BRANCH_NAME** | 11.6 | all | The target branch name of the merge request if it's [pipelines for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_ID** | 11.6 | all | The ID of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_IID** | 11.6 | all | The IID of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_PROJECT_ID** | 11.6 | all | The ID of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_PROJECT_PATH** | 11.6 | all | The path of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `namespace/awesome-project`) |
+| **CI_MERGE_REQUEST_PROJECT_URL** | 11.6 | all | The URL of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `http://192.168.10.15:3000/namespace/awesome-project`) |
+| **CI_MERGE_REQUEST_REF_PATH** | 11.6 | all | The ref path of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). (e.g. `refs/merge-requests/1/head`) |
+| **CI_MERGE_REQUEST_SOURCE_BRANCH_NAME** | 11.6 | all | The source branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_SOURCE_BRANCH_SHA** | 11.9 | all | The HEAD sha of the source branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_SOURCE_PROJECT_ID** | 11.6 | all | The ID of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_SOURCE_PROJECT_PATH** | 11.6 | all | The path of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_SOURCE_PROJECT_URL** | 11.6 | all | The URL of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_TARGET_BRANCH_NAME** | 11.6 | all | The target branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_TARGET_BRANCH_SHA** | 11.9 | all | The HEAD sha of the target branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_TITLE** | 11.9 | all | The title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_ASSIGNEES** | 11.9 | all | Comma-separated list of usernames of assignees for the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). [Multiple assignees for merge requests](https://gitlab.com/gitlab-org/gitlab-ee/issues/2004) is scheduled for a future release |
+| **CI_MERGE_REQUEST_MILESTONE** | 11.9 | all | The milestone title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| **CI_MERGE_REQUEST_LABELS** | 11.9 | all | Comma-separated label names of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
| **CI_NODE_INDEX** | 11.5 | all | Index of the job in the job set. If the job is not parallelized, this variable is not set. |
| **CI_NODE_TOTAL** | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. |
-| **CI_PIPELINE_ID** | 8.10 | 0.5 | The unique id of the current pipeline that GitLab CI uses internally |
+| **CI_API_V4_URL** | 11.7 | all | The GitLab API v4 root URL |
+| **CI_PAGES_DOMAIN** | 11.8 | all | The configured domain that hosts GitLab Pages. |
+| **CI_PAGES_URL** | 11.8 | all | URL to GitLab Pages-built pages. Always belongs to a subdomain of `CI_PAGES_DOMAIN`. |
+| **CI_PIPELINE_ID** | 8.10 | all | The unique id of the current pipeline that GitLab CI uses internally |
| **CI_PIPELINE_IID** | 11.0 | all | The unique id of the current pipeline scoped to project |
| **CI_PIPELINE_SOURCE** | 10.0 | all | Indicates how the pipeline was triggered. Possible options are: `push`, `web`, `trigger`, `schedule`, `api`, and `pipeline`. For pipelines created before GitLab 9.5, this will show as `unknown` |
| **CI_PIPELINE_TRIGGERED** | all | all | The flag to indicate that job was [triggered] |
| **CI_PIPELINE_URL** | 11.1 | 0.5 | Pipeline details URL |
-| **CI_PROJECT_DIR** | all | all | The full path where the repository is cloned and where the job is run |
+| **CI_PROJECT_DIR** | all | all | The full path where the repository is cloned and where the job is run. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see [Advanced configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) for GitLab Runner. |
| **CI_PROJECT_ID** | all | all | The unique id of the current project that GitLab CI uses internally |
| **CI_PROJECT_NAME** | 8.10 | 0.5 | The project name that is currently being built (actually it is project folder name) |
| **CI_PROJECT_NAMESPACE** | 8.10 | 0.5 | The project namespace (username or groupname) that is currently being built |
| **CI_PROJECT_PATH** | 8.10 | 0.5 | The namespace with project name |
| **CI_PROJECT_PATH_SLUG** | 9.3 | all | `$CI_PROJECT_PATH` lowercased and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. |
-| **CI_PROJECT_URL** | 8.10 | 0.5 | The HTTP address to access project |
+| **CI_PROJECT_URL** | 8.10 | 0.5 | The HTTP(S) address to access project |
| **CI_PROJECT_VISIBILITY** | 10.3 | all | The project visibility (internal, private, public) |
| **CI_REGISTRY** | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of GitLab's Container Registry |
| **CI_REGISTRY_IMAGE** | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project |
@@ -153,7 +174,7 @@ This feature requires GitLab Runner 0.5.0 or higher and GitLab 7.14 or higher.
GitLab CI allows you to add to `.gitlab-ci.yml` variables that are set in the
build environment. The variables are hence saved in the repository, and they
-are meant to store non-sensitive project configuration, e.g., `RAILS_ENV` or
+are meant to store non-sensitive project configuration. For example, `RAILS_ENV` or
`DATABASE_URL`.
For example, if you set the variable below globally (not inside a job), it will
@@ -201,16 +222,18 @@ GitLab CI allows you to define per-project or per-group variables
that are set in the pipeline environment. The variables are stored out of
the repository (not in `.gitlab-ci.yml`) and are securely passed to GitLab Runner
making them available during a pipeline run. It's the recommended method to
-use for storing things like passwords, SSH keys and credentials.
+use for storing things like passwords, SSH keys, and credentials.
+
+Project-level variables can be added by:
-Project-level variables can be added by going to your project's
-**Settings > CI/CD**, then finding the section called **Variables**.
+1. Navigating to your project's **Settings > CI/CD** page.
+1. Inputing variable keys and values in the **Environment variables** section.
-Likewise, group-level variables can be added by going to your group's
-**Settings > CI/CD**, then finding the section called **Variables**.
-Any variables of [subgroups] will be inherited recursively.
+Group-level variables can be added by:
-![Variables](img/variables.png)
+1. Navigating to your group's **Settings > CI/CD** page.
+1. Inputing variable keys and values in the **Environment variables** section. Any variables of
+ [subgroups](../../user/group/subgroups/index.md) will be inherited recursively.
Once you set them, they will be available for all subsequent pipelines. You can also
[protect your variables](#protected-variables).
@@ -249,6 +272,23 @@ the project services that you are using to learn which variables they define.
An example project service that defines deployment variables is the
[Kubernetes integration](../../user/project/clusters/index.md#deployment-variables).
+## Auto DevOps application variables
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/49056) in GitLab 11.7.
+
+You can configure [Auto DevOps](../../topics/autodevops/index.md) to
+pass CI variables to the running application by prefixing the key of the
+variable with `K8S_SECRET_`.
+
+These [prefixed
+variables](../../topics/autodevops/index.md#application-secret-variables) will
+then be available as environment variables on the running application
+container.
+
+CAUTION: **Caution:**
+Variables with multiline values are not currently supported due to
+limitations with the current Auto DevOps scripting environment.
+
## Debug tracing
> Introduced in GitLab Runner 1.7.
@@ -373,6 +413,10 @@ Running on runner-8a2f473d-project-1796893-concurrent-0 via runner-8a2f473d-mach
++ CI_SERVER_VERSION=8.14.3-ee
++ export CI_SERVER_REVISION=82823
++ CI_SERVER_REVISION=82823
+++ export CI_PAGES_DOMAIN=gitlab.io
+++ CI_PAGES_DOMAIN=gitlab.io
+++ export CI_PAGES_URL=https://gitlab-examples.gitlab.io/ci-debug-trace
+++ CI_PAGES_URL=https://gitlab-examples.gitlab.io/ci-debug-trace
++ export CI_PROJECT_ID=17893
++ CI_PROJECT_ID=17893
++ export CI_PROJECT_NAME=ci-debug-trace
@@ -476,6 +520,8 @@ export CI_JOB_TRIGGERED="true"
export CI_JOB_TOKEN="abcde-1234ABCD5678ef"
export CI_PIPELINE_ID="1000"
export CI_PIPELINE_IID="10"
+export CI_PAGES_DOMAIN="gitlab.io"
+export CI_PAGES_URL="https://gitlab-org.gitlab.io/gitlab-ce"
export CI_PROJECT_ID="34"
export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-ce"
export CI_PROJECT_NAME="gitlab-ce"
@@ -591,11 +637,8 @@ Below you can find supported syntax reference:
[envs]: ../environments.md
[protected branches]: ../../user/project/protected_branches.md
[protected tags]: ../../user/project/protected_tags.md
-[runner]: https://docs.gitlab.com/runner/
[shellexecutors]: https://docs.gitlab.com/runner/executors/
[triggered]: ../triggers/README.md
-[triggers]: ../triggers/README.md#pass-job-variables-to-a-trigger
-[subgroups]: ../../user/group/subgroups/index.md
[builds-policies]: ../yaml/README.md#only-and-except-complex
[gitlab-deploy-token]: ../../user/project/deploy_tokens/index.md#gitlab-deploy-token
[registry]: ../../user/project/container_registry.md
diff --git a/doc/ci/variables/img/variables.png b/doc/ci/variables/img/variables.png
deleted file mode 100644
index 0795f7c888f..00000000000
--- a/doc/ci/variables/img/variables.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 440254e58bd..12b2df65fdd 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1,7 +1,7 @@
-# Configuration of your jobs with .gitlab-ci.yml
+# Configuration of your pipelines with .gitlab-ci.yml
This document describes the usage of `.gitlab-ci.yml`, the file that is used by
-GitLab Runner to manage your project's jobs.
+GitLab Runner to manage your project's pipelines.
From version 7.12, GitLab CI uses a [YAML](https://en.wikipedia.org/wiki/YAML)
file (`.gitlab-ci.yml`) for the project configuration. It is placed in the root
@@ -11,7 +11,7 @@ If you want a quick introduction to GitLab CI, follow our
[quick start guide](../quick_start/README.md).
NOTE: **Note:**
-If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository),
+If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository-starter),
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
@@ -57,6 +57,7 @@ A job is defined by a list of parameters that define the job behavior.
|---------------|----------|-------------|
| [script](#script) | yes | Defines a shell script which is executed by Runner |
| [extends](#extends) | no | Defines a configuration entry that this job is going to inherit from |
+| [include](#include) | no | Defines a configuration entry that allows this job to include external YAML files |
| [image](#image-and-services) | no | Use docker image, covered in [Using Docker Images](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml) |
| [services](#image-and-services) | no | Use docker services, covered in [Using Docker Images](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml) |
| [stage](#stage) | no | Defines a job stage (default: `test`) |
@@ -77,118 +78,6 @@ A job is defined by a list of parameters that define the job behavior.
| [retry](#retry) | no | Define when and how many times a job can be auto-retried in case of a failure |
| [parallel](#parallel) | no | Defines how many instances of a job should be run in parallel |
-### `extends`
-
-> Introduced in GitLab 11.3.
-
-`extends` defines an entry name that a job that uses `extends` is going to
-inherit from.
-
-It is an alternative to using [YAML anchors](#anchors) and is a little
-more flexible and readable:
-
-```yaml
-.tests:
- script: rake test
- stage: test
- only:
- refs:
- - branches
-
-rspec:
- extends: .tests
- script: rake rspec
- only:
- variables:
- - $RSPEC
-```
-
-In the example above, the `rspec` job inherits from the `.tests` template job.
-GitLab will perform a reverse deep merge based on the keys. GitLab will:
-
-- Merge the `rspec` contents into `.tests` recursively.
-- Not merge the values of the keys.
-
-This results in the following `rspec` job:
-
-```yaml
-rspec:
- script: rake rspec
- stage: test
- only:
- refs:
- - branches
- variables:
- - $RSPEC
-```
-
-NOTE: **Note:**
-Note that `script: rake test` has been overwritten by `script: rake rspec`.
-
-If you do want to include the `rake test`, have a look at [before_script-and-after_script](#before_script-and-after_script).
-
-`.tests` in this example is a [hidden key](#hidden-keys-jobs), but it's
-possible to inherit from regular jobs as well.
-
-`extends` supports multi-level inheritance, however it is not recommended to
-use more than three levels. The maximum nesting level that is supported is 10.
-The following example has two levels of inheritance:
-
-```yaml
-.tests:
- only:
- - pushes
-
-.rspec:
- extends: .tests
- script: rake rspec
-
-rspec 1:
- variables:
- RSPEC_SUITE: '1'
- extends: .rspec
-
-rspec 2:
- variables:
- RSPEC_SUITE: '2'
- extends: .rspec
-
-spinach:
- extends: .tests
- script: rake spinach
-```
-
-`extends` works across configuration files combined with [`include`](#include).
-
-### `pages`
-
-`pages` is a special job that is used to upload static content to GitLab that
-can be used to serve your website. It has a special syntax, so the two
-requirements below must be met:
-
-1. Any static content must be placed under a `public/` directory
-1. `artifacts` with a path to the `public/` directory must be defined
-
-The example below simply moves all files from the root of the project to the
-`public/` directory. The `.public` workaround is so `cp` doesn't also copy
-`public/` to itself in an infinite loop:
-
-```yaml
-pages:
- stage: deploy
- script:
- - mkdir .public
- - cp -r * .public
- - mv .public public
- artifacts:
- paths:
- - public
- only:
- - master
-```
-
-Read more on [GitLab Pages user documentation](../../user/project/pages/index.md).
-
## `image` and `services`
This allows to specify a custom Docker image and a list of services that can be
@@ -207,9 +96,9 @@ This can be an array or a multi-line string.
jobs, including failed ones. This has to be an array or a multi-line string.
The `before_script` and the main `script` are concatenated and run in a single context/container.
-The `after_script` is run separately, so depending on the executor, changes done
-outside of the working tree might not be visible, e.g. software installed in the
-`before_script`.
+The `after_script` is run separately. The current working directory is set back to
+default. Depending on the executor, changes done outside of the working tree might
+not be visible, e.g. software installed in the `before_script`.
It's possible to overwrite the globally defined `before_script` and `after_script`
if you set it per-job:
@@ -259,7 +148,7 @@ There are also two edge cases worth mentioning:
1. If no `stages` are defined in `.gitlab-ci.yml`, then the `build`,
`test` and `deploy` are allowed to be used as job's stage by default.
-2. If a job doesn't specify a `stage`, the job is assigned the `test` stage.
+1. If a job doesn't specify a `stage`, the job is assigned the `test` stage.
## `stage`
@@ -327,15 +216,15 @@ a "key: value" pair. Be careful when using special characters:
jobs are created:
1. `only` defines the names of branches and tags for which the job will run.
-2. `except` defines the names of branches and tags for which the job will
+1. `except` defines the names of branches and tags for which the job will
**not** run.
There are a few rules that apply to the usage of job policy:
-* `only` and `except` are inclusive. If both `only` and `except` are defined
+- `only` and `except` are inclusive. If both `only` and `except` are defined
in a job specification, the ref is filtered by `only` and `except`.
-* `only` and `except` allow the use of regular expressions (using [Ruby regexp syntax](https://ruby-doc.org/core/Regexp.html)).
-* `only` and `except` allow to specify a repository path to filter jobs for
+- `only` and `except` allow the use of regular expressions (using [Ruby regexp syntax](https://ruby-doc.org/core/Regexp.html)).
+- `only` and `except` allow to specify a repository path to filter jobs for
forks.
In addition, `only` and `except` allow the use of special keywords:
@@ -392,8 +281,8 @@ job:
The above example will run `job` for all branches on `gitlab-org/gitlab-ce`,
except master.
-If a job does not have neither `only` nor `except` rule,
-`only: ['branches', 'tags']` is set by default.
+If a job does not have an `only` rule, `only: ['branches', 'tags']` is set by
+default. If it doesn't have an `except` rule, it is empty.
For example,
@@ -534,10 +423,28 @@ connected with merge requests yet, and because GitLab is creating pipelines
before an user can create a merge request we don't know a target branch at
this point.
-Without a target branch, it is not possible to know what the common ancestor is,
-thus we always create a job in that case. This feature works best for stable
-branches like `master` because in that case GitLab uses the previous commit
-that is present in a branch to compare against the latest SHA that was pushed.
+#### Using `changes` with `merge_requests`
+
+With [pipelines for merge requests](../merge_request_pipelines/index.md),
+make it possible to define if a job should be created base on files modified
+in a merge request.
+
+For example:
+
+```
+docker build service one:
+ script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
+ only:
+ refs:
+ - merge_requests
+ changes:
+ - Dockerfile
+ - service-one/**/*
+```
+
+In the scenario above, if you create or update a merge request that changes
+either files in `service-one` folder or `Dockerfile`, GitLab creates and triggers
+the `docker build service one` job.
## `tags`
@@ -676,9 +583,9 @@ cleanup_job:
The above script will:
1. Execute `cleanup_build_job` only when `build_job` fails.
-2. Always execute `cleanup_job` as the last step in pipeline regardless of
+1. Always execute `cleanup_job` as the last step in pipeline regardless of
success or failure.
-3. Allow you to manually execute `deploy_job` from GitLab's UI.
+1. Allow you to manually execute `deploy_job` from GitLab's UI.
### `when:manual`
@@ -711,9 +618,9 @@ action fails, the pipeline will eventually succeed.
Manual actions are considered to be write actions, so permissions for
[protected branches](../../user/project/protected_branches.md) are used when
-user wants to trigger an action. In other words, in order to trigger a manual
-action assigned to a branch that the pipeline is running for, user needs to
-have ability to merge to this branch.
+a user wants to trigger an action. In other words, in order to trigger a manual
+action assigned to a branch that the pipeline is running for, the user needs to
+have the ability to merge to this branch.
### `when:delayed`
@@ -887,7 +794,7 @@ In the above example we set up the `review_app` job to deploy to the `review`
environment, and we also defined a new `stop_review_app` job under `on_stop`.
Once the `review_app` job is successfully finished, it will trigger the
`stop_review_app` job based on what is defined under `when`. In this case we
-set it up to `manual` so it will need a [manual action](#manual-actions) via
+set it up to `manual` so it will need a [manual action](#whenmanual) via
GitLab's web interface in order to run.
The `stop_review_app` job is **required** to have the following keywords defined:
@@ -1299,7 +1206,7 @@ job:
`expire_in` allows you to specify how long artifacts should live before they
expire and therefore deleted, counting from the time they are uploaded and
stored on GitLab. If the expiry time is not defined, it defaults to the
-[instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration)
+[instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration-core-only)
(30 days by default, forever on GitLab.com).
You can use the **Keep** button on the job page to override expiration and
@@ -1338,7 +1245,7 @@ this with [JUnit reports](#artifactsreportsjunit).
NOTE: **Note:**
The test reports are collected regardless of the job results (success or failure).
-You can use [`artifacts:expire_in`](#artifacts-expire_in) to set up an expiration
+You can use [`artifacts:expire_in`](#artifactsexpire_in) to set up an expiration
date for their artifacts.
NOTE: **Note:**
@@ -1518,7 +1425,7 @@ deploy:
> Introduced in GitLab 10.3.
If the artifacts of the job that is set as a dependency have been
-[expired](#artifacts-expire_in) or
+[expired](#artifactsexpire_in) or
[erased](../../user/project/pipelines/job_artifacts.md#erasing-artifacts), then
the dependent job will fail.
@@ -1621,7 +1528,6 @@ Possible values for `when` are:
- `missing_dependency_failure`: Retry if a dependency was missing.
- `runner_unsupported`: Retry if the runner was unsupported.
-
## `parallel`
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22631) in GitLab 11.5.
@@ -1632,7 +1538,7 @@ parallel. This value has to be greater than or equal to two (2) and less than or
This creates N instances of the same job that run in parallel. They're named
sequentially from `job_name 1/N` to `job_name N/N`.
-For every job, `CI_NODE_INDEX` and `CI_NODE_TOTAL` [environment variables](../variables/README.html#predefined-variables-environment-variables) are set.
+For every job, `CI_NODE_INDEX` and `CI_NODE_TOTAL` [environment variables](../variables/README.html#predefined-environment-variables) are set.
A simple example:
@@ -1644,113 +1550,229 @@ test:
## `include`
-> Introduced in [GitLab Premium](https://about.gitlab.com/pricing/) 10.5.
-> Available for Starter, Premium and Ultimate since 10.6.
-> Behaviour expanded in GitLab 10.8 to allow more flexible overriding.
-> [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21603)
-to GitLab Core in 11.4
+> - Introduced in [GitLab Premium](https://about.gitlab.com/pricing/) 10.5.
+> - Available for Starter, Premium and Ultimate since 10.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21603) to GitLab Core in 11.4.
Using the `include` keyword, you can allow the inclusion of external YAML files.
+`include` requires the external YAML file to have the extensions `.yml` or `.yaml`,
+otherwise the external file will not be included.
-In the following example, the content of `.before-script-template.yml` will be
-automatically fetched and evaluated along with the content of `.gitlab-ci.yml`:
+The files defined in `include` are:
+
+- Deep merged with those in `.gitlab-ci.yml`.
+- Always evaluated first and merged with the content of `.gitlab-ci.yml`,
+ regardless of the position of the `include` keyword.
+
+TIP: **Tip:**
+Use merging to customize and override included CI/CD configurations with local
+definitions.
+
+Recursive includes are not supported. Your external files should not use the
+`include` keyword as it will be ignored.
+
+NOTE: **Note:**
+Using YAML aliases across different YAML files sourced by `include` is not
+supported. You must only refer to aliases in the same file. Instead
+of using YAML anchors, you can use the [`extends` keyword](#extends).
+
+`include` supports four include methods:
+
+- [`local`](#includelocal)
+- [`file`](#includefile)
+- [`template`](#includetemplate)
+- [`remote`](#includeremote)
+
+See [usage examples](#include-examples).
+
+### `include:local`
+
+`include:local` includes a file from the same repository as `.gitlab-ci.yml`.
+It's referenced using full paths relative to the root directory (`/`).
+
+You can only use files that are currently tracked by Git on the same branch
+your configuration file is on. In other words, when using a `include:local`, make
+sure that both `.gitlab-ci.yml` and the local file are on the same branch.
+
+All [nested includes](#nested-includes) will be executed in the scope of the same project,
+so it is possible to use local, project, remote or template includes.
+
+NOTE: **Note:**
+Including local files through Git submodules paths is not supported.
+
+Example:
```yaml
-# Content of https://gitlab.com/awesome-project/raw/master/.before-script-template.yml
+include:
+ - local: '/templates/.gitlab-ci-template.yml'
+```
-before_script:
- - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- - gem install bundler --no-ri --no-rdoc
- - bundle install --jobs $(nproc) "${FLAGS[@]}"
+### `include:file`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/53903) in GitLab 11.7.
+
+To include files from another private project under the same GitLab instance,
+use `include:file`. This file is referenced using full paths relative to the
+root directory (`/`). For example:
+
+```yaml
+include:
+ - project: 'my-group/my-project'
+ file: '/templates/.gitlab-ci-template.yml'
```
+You can also specify `ref`, with the default being the `HEAD` of the project:
+
```yaml
-# Content of .gitlab-ci.yml
+include:
+ - project: 'my-group/my-project'
+ ref: master
+ file: '/templates/.gitlab-ci-template.yml'
-include: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+ - project: 'my-group/my-project'
+ ref: v1.0.0
+ file: '/templates/.gitlab-ci-template.yml'
-rspec:
- script:
- - bundle exec rspec
+ - project: 'my-group/my-project'
+ ref: 787123b47f14b552955ca2786bc9542ae66fee5b # Git SHA
+ file: '/templates/.gitlab-ci-template.yml'
```
-NOTE: **Note:**
-`include` requires the external YAML files to have the extensions `.yml` or `.yaml`.
-The external file will not be included if the extension is missing.
+All nested includes will be executed in the scope of the target project,
+so it is possible to used local (relative to target project), project, remote
+or template includes.
-You can define it either as a single string, or, in case you want to include
-more than one files, an array of different values . The following examples
-are both valid cases:
+### `include:template`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/53445) in GitLab 11.7.
+
+`include:template` can be used to include `.gitlab-ci.yml` templates that are
+[shipped with GitLab](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates).
+
+For example:
```yaml
-# Single string
+# File sourced from GitLab's template collection
+include:
+ - template: Auto-DevOps.gitlab-ci.yml
+```
-include: '/templates/.after-script-template.yml'
+All nested includes will be executed only with the permission of the user,
+so it is possible to use project, remote or template includes.
+
+### `include:remote`
+
+`include:remote` can be used to include a file from a different location,
+using HTTP/HTTPS, referenced by using the full URL. The remote file must be
+publicly accessible through a simple GET request as authentication schemas
+in the remote URL is not supported. For example:
+
+```yaml
+include:
+ - remote: 'https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml'
```
+All nested includes will be executed without context as public user, so only another remote,
+or public project, or template is allowed.
+
+### Nested includes
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/53903) in GitLab 11.7.
+
+Nested includes allow you to compose a set of includes.
+A total of 50 includes is allowed.
+Duplicate includes are considered a configuration error.
+
+### `include` examples
+
+Here are a few more `include` examples.
+
+#### Single string or array of multiple values
+
+You can include your extra YAML file(s) either as a single string or
+an array of multiple values. The following examples are all valid.
+
+Single string with the `include:local` method implied:
+
```yaml
-# Array
+include: '/templates/.after-script-template.yml'
+```
+
+Array with `include` method implied:
+```yaml
include:
- 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
- '/templates/.after-script-template.yml'
```
----
+Single string with `include` method specified explicitly:
-`include` supports two types of files:
+```yaml
+include:
+ remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+```
-- **local** to the same repository, referenced by using full paths in the same
- repository, with `/` being the root directory. For example:
+Array with `include:remote` being the single item:
- ```yaml
- # Within the repository
- include: '/templates/.gitlab-ci-template.yml'
- ```
+```yaml
+include:
+ - remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+```
- NOTE: **Note:**
- You can only use files that are currently tracked by Git on the same branch
- your configuration file is. In other words, when using a **local file**, make
- sure that both `.gitlab-ci.yml` and the local file are on the same branch.
+Array with multiple `include` methods specified explicitly:
- NOTE: **Note:**
- We don't support the inclusion of local files through Git submodules paths.
+```yaml
+include:
+ - remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+ - local: '/templates/.after-script-template.yml'
+ - template: Auto-DevOps.gitlab-ci.yml
+```
-- **remote** in a different location, accessed using HTTP/HTTPS, referenced
- using the full URL. For example:
+Array mixed syntax:
- ```yaml
- include: 'https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml'
- ```
+```yaml
+include:
+ - 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+ - '/templates/.after-script-template.yml'
+ - template: Auto-DevOps.gitlab-ci.yml
+ - project: 'my-group/my-project'
+ ref: master
+ file: '/templates/.gitlab-ci-template.yml'
+```
- NOTE: **Note:**
- The remote file must be publicly accessible through a simple GET request, as we don't support authentication schemas in the remote URL.
+#### Re-using a `before_script` template
- NOTE: **Note:**
- In order to include files from another repository inside your local network,
- you may need to enable the **Allow requests to the local network from hooks and services** checkbox
- located in the **Settings > Network > Outbound requests** section within the **Admin area**.
+In the following example, the content of `.before-script-template.yml` will be
+automatically fetched and evaluated along with the content of `.gitlab-ci.yml`.
----
+Content of `https://gitlab.com/awesome-project/raw/master/.before-script-template.yml`:
+```yaml
+before_script:
+ - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
+ - gem install bundler --no-document
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
+```
-Since GitLab 10.8 we are now deep merging the files defined in `include`
-with those in `.gitlab-ci.yml`. Files defined by `include` are always
-evaluated first and merged with the content of `.gitlab-ci.yml`, no
-matter the position of the `include` keyword. You can take advantage of
-merging to customize and override details in included CI
-configurations with local definitions.
+Content of `.gitlab-ci.yml`:
-NOTE: **Note:**
-The recursive includes are not supported, meaning your external files
-should not use the `include` keyword, as it will be ignored.
+```yaml
+include: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+
+rspec:
+ script:
+ - bundle exec rspec
+```
+
+#### Overriding external template values
The following example shows specific YAML-defined variables and details of the
`production` job from an include file being customized in `.gitlab-ci.yml`.
-```yaml
-# Content of https://company.com/autodevops-template.yml
+Content of `https://company.com/autodevops-template.yml`:
+```yaml
variables:
POSTGRES_USER: user
POSTGRES_PASSWORD: testing_password
@@ -1768,9 +1790,9 @@ production:
- master
```
-```yaml
-# Content of .gitlab-ci.yml
+Content of `.gitlab-ci.yml`:
+```yaml
include: 'https://company.com/autodevops-template.yml'
image: alpine:latest
@@ -1797,11 +1819,11 @@ with the environment url of the `production` job defined in
The merging lets you extend and override dictionary mappings, but
you cannot add or modify items to an included array. For example, to add
an additional item to the production job script, you must repeat the
-existing script items.
+existing script items:
-```yaml
-# Content of https://company.com/autodevops-template.yml
+Content of `https://company.com/autodevops-template.yml`:
+```yaml
production:
stage: production
script:
@@ -1809,9 +1831,9 @@ production:
- deploy
```
-```yaml
-# Content of .gitlab-ci.yml
+Content of `.gitlab-ci.yml`:
+```yaml
include: 'https://company.com/autodevops-template.yml'
stages:
@@ -1828,10 +1850,185 @@ In this case, if `install_dependencies` and `deploy` were not repeated in
`.gitlab-ci.yml`, they would not be part of the script for the `production`
job in the combined CI configuration.
+#### Using nested includes
+
+The examples below show how includes can be nested from different sources
+using a combination of different methods.
+
+In this example, `.gitlab-ci.yml` includes local the file `/.gitlab-ci/another-config.yml`:
+
+```yaml
+include:
+ - local: /.gitlab-ci/another-config.yml
+```
+
+The `/.gitlab-ci/another-config.yml` includes a template and the `/templates/docker-workflow.yml` file
+from another project:
+
+```yaml
+include:
+ - template: Bash.gitlab-ci.yml
+ - project: /group/my-project
+ file: /templates/docker-workflow.yml
+```
+
+The `/templates/docker-workflow.yml` present in `/group/my-project` includes two local files
+of the `/group/my-project`:
+
+```yaml
+include:
+ - local: : /templates/docker-build.yml
+ - local: : /templates/docker-testing.yml
+```
+
+Our `/templates/docker-build.yml` present in `/group/my-project` adds a `docker-build` job:
+
+```yaml
+docker-build:
+ script: docker build -t my-image .
+```
+
+Our second `/templates/docker-test.yml` present in `/group/my-project` adds a `docker-test` job:
+
+```yaml
+docker-test:
+ script: docker run my-image /run/tests.sh
+```
+
+## `extends`
+
+> Introduced in GitLab 11.3.
+
+`extends` defines an entry name that a job that uses `extends` is going to
+inherit from.
+
+It is an alternative to using [YAML anchors](#anchors) and is a little
+more flexible and readable:
+
+```yaml
+.tests:
+ script: rake test
+ stage: test
+ only:
+ refs:
+ - branches
+
+rspec:
+ extends: .tests
+ script: rake rspec
+ only:
+ variables:
+ - $RSPEC
+```
+
+In the example above, the `rspec` job inherits from the `.tests` template job.
+GitLab will perform a reverse deep merge based on the keys. GitLab will:
+
+- Merge the `rspec` contents into `.tests` recursively.
+- Not merge the values of the keys.
+
+This results in the following `rspec` job:
+
+```yaml
+rspec:
+ script: rake rspec
+ stage: test
+ only:
+ refs:
+ - branches
+ variables:
+ - $RSPEC
+```
+
NOTE: **Note:**
-We currently do not support using YAML aliases across different YAML files
-sourced by `include`. You must only refer to aliases in the same file. Instead
-of using YAML anchors you can use [`extends` keyword](#extends).
+Note that `script: rake test` has been overwritten by `script: rake rspec`.
+
+If you do want to include the `rake test`, see [`before_script` and `after_script`](#before_script-and-after_script).
+
+`.tests` in this example is a [hidden key](#hidden-keys-jobs), but it's
+possible to inherit from regular jobs as well.
+
+`extends` supports multi-level inheritance, however it is not recommended to
+use more than three levels. The maximum nesting level that is supported is 10.
+The following example has two levels of inheritance:
+
+```yaml
+.tests:
+ only:
+ - pushes
+
+.rspec:
+ extends: .tests
+ script: rake rspec
+
+rspec 1:
+ variables:
+ RSPEC_SUITE: '1'
+ extends: .rspec
+
+rspec 2:
+ variables:
+ RSPEC_SUITE: '2'
+ extends: .rspec
+
+spinach:
+ extends: .tests
+ script: rake spinach
+```
+
+## Using `extends` and `include` together
+
+`extends` works across configuration files combined with `include`.
+
+For example, if you have a local `included.yml` file:
+
+```yaml
+.template:
+ script:
+ - echo Hello!
+```
+
+Then, in `.gitlab-ci.yml` you can use it like this:
+
+```yaml
+include: included.yml
+
+useTemplate:
+ image: alpine
+ extends: .template
+```
+
+This will run a job called `useTemplate` that runs `echo Hello!` as defined in
+the `.template` job, and uses the `alpine` Docker image as defined in the local job.
+
+## `pages`
+
+`pages` is a special job that is used to upload static content to GitLab that
+can be used to serve your website. It has a special syntax, so the two
+requirements below must be met:
+
+- Any static content must be placed under a `public/` directory.
+- `artifacts` with a path to the `public/` directory must be defined.
+
+The example below simply moves all files from the root of the project to the
+`public/` directory. The `.public` workaround is so `cp` doesn't also copy
+`public/` to itself in an infinite loop:
+
+```yaml
+pages:
+ stage: deploy
+ script:
+ - mkdir .public
+ - cp -r * .public
+ - mv .public public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+```
+
+Read more on [GitLab Pages user documentation](../../user/project/pages/index.md).
## `variables`
@@ -1859,7 +2056,7 @@ The YAML-defined variables are also set to all created service containers,
thus allowing to fine tune them.
Except for the user defined variables, there are also the ones [set up by the
-Runner itself](../variables/README.md#predefined-variables-environment-variables).
+Runner itself](../variables/README.md#predefined-environment-variables).
One example would be `CI_COMMIT_REF_NAME` which has the value of
the branch or tag name for which project is built. Apart from the variables
you can set in `.gitlab-ci.yml`, there are also the so called
@@ -1870,9 +2067,9 @@ which can be set in GitLab's UI.
### Git strategy
-> Introduced in GitLab 8.9 as an experimental feature. May change or be removed
- completely in future releases. `GIT_STRATEGY=none` requires GitLab Runner
- v1.7+.
+> Introduced in GitLab 8.9 as an experimental feature. May change or be removed
+> completely in future releases. `GIT_STRATEGY=none` requires GitLab Runner
+> v1.7+.
You can set the `GIT_STRATEGY` used for getting recent application code, either
globally or per-job in the [`variables`](#variables) section. If left
@@ -1908,6 +2105,11 @@ variables:
GIT_STRATEGY: none
```
+NOTE: **Note:** `GIT_STRATEGY` is not supported for
+[Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html),
+but may be in the future. See the [support Git strategy with Kubernetes executor feature proposal](https://gitlab.com/gitlab-org/gitlab-runner/issues/3847)
+for updates.
+
### Git submodule strategy
> Requires GitLab Runner v1.10+.
@@ -2200,6 +2402,13 @@ with an API call.
If your commit message contains `[ci skip]` or `[skip ci]`, using any
capitalization, the commit will be created but the pipeline will be skipped.
+Alternatively, one can pass the `ci.skip` [Git push option][push-option] if
+using Git 2.10 or newer:
+
+```sh
+git push -o ci.skip
+```
+
## Validate the .gitlab-ci.yml
Each instance of GitLab CI has an embedded debug tool called Lint, which validates the
@@ -2224,3 +2433,4 @@ GitLab CI/CD with various languages.
[environment]: ../environments.md "CI/CD environments"
[schedules]: ../../user/project/pipelines/schedules.md "Pipelines schedules"
[variables]: ../variables/README.md "CI/CD variables"
+[push-option]: https://git-scm.com/docs/git-push#git-push--oltoptiongt
diff --git a/doc/customization/help_message.md b/doc/customization/help_message.md
new file mode 100644
index 00000000000..c2e592d03bf
--- /dev/null
+++ b/doc/customization/help_message.md
@@ -0,0 +1,13 @@
+# GitLab Help custom text
+
+In larger organizations it is useful to have information about who has the responsibility of maintaining the company GitLab server.
+
+1. Navigate to the admin area, click on **Preferences** and expand **Help page**.
+
+1. Under **Help text** fill in the required information about the person(s) administering GitLab or any other information relevant to your needs.
+
+ ![help message](help_message/help_text.png)
+
+1. After saving the page this information will be shown on the GitLab login page and on the GitLab `/help` page (e.g., <https://gitlab.com/help>).
+
+ ![help text on help page](help_message/help_text_on_help_page.png)
diff --git a/doc/customization/help_message/help_text.png b/doc/customization/help_message/help_text.png
new file mode 100644
index 00000000000..99697a106bf
--- /dev/null
+++ b/doc/customization/help_message/help_text.png
Binary files differ
diff --git a/doc/customization/help_message/help_text_on_help_page.png b/doc/customization/help_message/help_text_on_help_page.png
new file mode 100644
index 00000000000..288b4b8c1eb
--- /dev/null
+++ b/doc/customization/help_message/help_text_on_help_page.png
Binary files differ
diff --git a/doc/customization/index.md b/doc/customization/index.md
new file mode 100644
index 00000000000..71e87b3f111
--- /dev/null
+++ b/doc/customization/index.md
@@ -0,0 +1,18 @@
+---
+description: Learn how to customize GitLab's appearance for self-managed installations.
+---
+
+# Customizing GitLab's appearance **[CORE ONLY]**
+
+For GitLab self-managed instances, it's possible to customize
+a few pages.
+
+Read through the following documents to adjust GitLab's
+look and feel to meet your needs:
+
+- [Custom login page](branded_login_page.md)
+- [Custom header and email logo](branded_page_and_email_header.md)
+- [Custom favicon](favicon.md)
+- [Libravatar](libravatar.md)
+- [New project page](new_project_page.md)
+- [Custom `/help` message](help_message.md) \ No newline at end of file
diff --git a/doc/customization/libravatar.md b/doc/customization/libravatar.md
index 9bd22d3966d..18aaeb5a712 100644
--- a/doc/customization/libravatar.md
+++ b/doc/customization/libravatar.md
@@ -38,7 +38,6 @@ For example, you host a service on `http://libravatar.example.com` the `plain_ur
`http://libravatar.example.com/avatar/%{hash}?s=%{size}&d=identicon`
-
## Omnibus-gitlab example
In `/etc/gitlab/gitlab.rb`:
@@ -57,10 +56,8 @@ gitlab_rails['gravatar_enabled'] = true
gitlab_rails['gravatar_ssl_url'] = "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
```
-
Run `sudo gitlab-ctl reconfigure` for changes to take effect.
-
## Default URL for missing images
[Libravatar supports different sets](https://wiki.libravatar.org/api/) of `missing images` for emails not found on the Libravatar service.
@@ -68,7 +65,6 @@ Run `sudo gitlab-ctl reconfigure` for changes to take effect.
In order to use a different set other than `identicon`, replace `&d=identicon` portion of the URL with another supported set.
For example, you can use `retro` set in which case the URL would look like: `plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"`
-
## Usage examples
#### For Microsoft Office 365
diff --git a/doc/customization/system_header_and_footer_messages.md b/doc/customization/system_header_and_footer_messages.md
new file mode 100644
index 00000000000..9d6931c730d
--- /dev/null
+++ b/doc/customization/system_header_and_footer_messages.md
@@ -0,0 +1,22 @@
+# Adding a system message to every page
+
+> [Introduced][ee-1283] in [GitLab Premium][eep] 10.7.
+
+Navigate to the **Admin** area and go to the **Appearance** page.
+
+Under **System header and footer** insert your header message and/or footer message.
+Both background and font color of the header and footer are customizable.
+
+You can also apply the header and footer messages to gitlab emails,
+by checking the **Enable header and footer in emails** checkbox.
+Note that color settings will only be applied within the app interface and not to emails
+
+![appearance](system_header_and_footer_messages/appearance.png)
+
+After saving, all GitLab pages will contain the custom system header and/or footer messages:
+
+![custom_header_footer](system_header_and_footer_messages/custom_header_footer.png)
+
+The GitLab sign in page will also show the header and the footer messages:
+
+![sign_up_custom_header_and_footer](system_header_and_footer_messages/sign_up_custom_header_and_footer.png)
diff --git a/doc/customization/system_header_and_footer_messages/appearance.png b/doc/customization/system_header_and_footer_messages/appearance.png
new file mode 100644
index 00000000000..fd315bb6c07
--- /dev/null
+++ b/doc/customization/system_header_and_footer_messages/appearance.png
Binary files differ
diff --git a/doc/customization/system_header_and_footer_messages/custom_header_footer.png b/doc/customization/system_header_and_footer_messages/custom_header_footer.png
new file mode 100644
index 00000000000..691ca8a3484
--- /dev/null
+++ b/doc/customization/system_header_and_footer_messages/custom_header_footer.png
Binary files differ
diff --git a/doc/customization/system_header_and_footer_messages/sign_up_custom_header_and_footer.png b/doc/customization/system_header_and_footer_messages/sign_up_custom_header_and_footer.png
new file mode 100644
index 00000000000..a9c59bc9f62
--- /dev/null
+++ b/doc/customization/system_header_and_footer_messages/sign_up_custom_header_and_footer.png
Binary files differ
diff --git a/doc/customization/welcome_message.md b/doc/customization/welcome_message.md
index 0aef0bf5abb..9194f847cdf 100644
--- a/doc/customization/welcome_message.md
+++ b/doc/customization/welcome_message.md
@@ -1,12 +1 @@
-# Customize the complete sign-in page
-
-Please see [Branded login page](branded_login_page.md)
-
-# Add a welcome message to the sign-in page (GitLab Community Edition)
-
-It is possible to add a markdown-formatted welcome message to your GitLab
-sign-in page. Users of GitLab Enterprise Edition should use the [branded login
-page feature](branded_login_page.md) instead.
-
-The welcome message (extra_sign_in_text) can now be set/changed in the Admin UI.
-Admin area > Settings
+This document was moved to [another location](branded_login_page.md).
diff --git a/doc/development/README.md b/doc/development/README.md
index f22dde32de9..13646cbfe48 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -47,7 +47,9 @@ description: 'Learn how to contribute to GitLab.'
- [Avoid modules with instance variables](module_with_instance_variables.md) if possible
- [How to dump production data to staging](db_dump.md)
- [Working with the GitHub importer](github_importer.md)
+- [Import/Export development documentation](import_export.md)
- [Working with Merge Request diffs](diffs.md)
+- [Kubernetes integration guidelines](kubernetes.md)
- [Permissions](permissions.md)
- [Prometheus metrics](prometheus_metrics.md)
- [Guidelines for reusing abstractions](reusing_abstractions.md)
@@ -122,3 +124,7 @@ description: 'Learn how to contribute to GitLab.'
## Compliance
- [Licensing](licensing.md) for ensuring license compliance
+
+## Go guides
+
+- [Go Guidelines](go_guide/index.md)
diff --git a/doc/development/adding_database_indexes.md b/doc/development/adding_database_indexes.md
index d1d2b8c4907..c47ce0f1182 100644
--- a/doc/development/adding_database_indexes.md
+++ b/doc/development/adding_database_indexes.md
@@ -113,9 +113,9 @@ the meaning of the various columns can be found at
Because the output of this query relies on the actual usage of your database it
may be affected by factors such as (but not limited to):
-* Certain queries never being executed, thus not being able to use certain
+- Certain queries never being executed, thus not being able to use certain
indexes.
-* Certain tables having little data, resulting in PostgreSQL using sequence
+- Certain tables having little data, resulting in PostgreSQL using sequence
scans instead of index scans.
In other words, this data is only reliable for a frequently used database with
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 95722c027ba..501092ff2aa 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -12,24 +12,34 @@ add a `HTTP_PRIVATE_TOKEN` header.
### Authorization
Fields can be authorized using the same abilities used in the Rails
-app. This can be done using the `authorize` helper:
+app. This can be done by supplying the `authorize` option:
```ruby
module Types
class QueryType < BaseObject
graphql_name 'Query'
- field :project, Types::ProjectType, null: true, resolver: Resolvers::ProjectResolver do
- authorize :read_project
- end
+ field :project, Types::ProjectType, null: true, resolver: Resolvers::ProjectResolver, authorize: :read_project
end
+end
+```
+
+Fields can be authorized against multiple abilities, in which case all
+ability checks must pass. This requires explicitly passing a block to `field`:
+
+```ruby
+field :project, Types::ProjectType, null: true, resolver: Resolvers::ProjectResolver do
+ authorize [:read_project, :another_ability]
+end
```
The object found by the resolve call is used for authorization.
-This works for authorizing a single record, for authorizing
-collections, we should only load what the currently authenticated user
-is allowed to view. Preferably we use our existing finders for that.
+TIP: **Tip:**
+When authorizing collections, try to load only what the currently
+authenticated user is allowed to view with our existing finders first.
+This minimizes database queries and unnecessary authorization checks of
+the loaded records.
## Types
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index ce444ebdde4..4fc38a460f8 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -14,7 +14,7 @@ Always use an [Entity] to present the endpoint's payload.
## Methods and parameters description
Every method must be described using the [Grape DSL](https://github.com/ruby-grape/grape#describing-methods)
-(see https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/api/environments.rb
+(see <https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/api/environments.rb>
for a good example):
- `desc` for the method summary. You should pass it a block for additional
@@ -49,14 +49,14 @@ end
`params` block. It filters out the params that have been passed, but are not
allowed.
-– https://github.com/ruby-grape/grape#declared
+– <https://github.com/ruby-grape/grape#declared>
### Exclude params from parent namespaces!
> By default `declared(params) `includes parameters that were defined in all
parent namespaces.
-– https://github.com/ruby-grape/grape#include-parent-namespaces
+– <https://github.com/ruby-grape/grape#include-parent-namespaces>
In most cases you will want to exclude params from the parent namespaces:
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index e65c5f05505..ae880e3deb6 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -35,7 +35,7 @@ run: redis: (pid 30560) 14274s; run: log: (pid 13807) 2432047s
run: redis-exporter: (pid 30946) 14205s; run: log: (pid 13869) 2432045s
run: sidekiq: (pid 30953) 14205s; run: log: (pid 13810) 2432047s
run: unicorn: (pid 30960) 14204s; run: log: (pid 13809) 2432047s
-```
+```
### Layers
@@ -51,28 +51,28 @@ GitLab can be considered to have two layers from a process perspective:
- Omnibus configuration options
- Layer: Monitoring
-[Alert manager](https://prometheus.io/docs/alerting/alertmanager/) is a tool provided by prometheus that _"handles alerts sent by client applications such as the Prometheus server. It takes care of deduplicating, grouping, and routing them to the correct receiver integration such as email, PagerDuty, or OpsGenie. It also takes care of silencing and inhibition of alerts."_ You can read more in [issue gitlab-ce#45740](https://gitlab.com/gitlab-org/gitlab-ce/issues/45740) about what we will be alerting on.
+[Alert manager](https://prometheus.io/docs/alerting/alertmanager/) is a tool provided by prometheus that _"handles alerts sent by client applications such as the Prometheus server. It takes care of deduplicating, grouping, and routing them to the correct receiver integration such as email, PagerDuty, or OpsGenie. It also takes care of silencing and inhibition of alerts."_ You can read more in [issue gitlab-ce#45740](https://gitlab.com/gitlab-org/gitlab-ce/issues/45740) about what we will be alerting on.
### gitaly
-- [Omnibus configuration options](https://gitlab.com/gitlab-org/gitaly/tree/master/doc/configuration)
+- [Omnibus configuration options](https://gitlab.com/gitlab-org/gitaly/tree/master/doc/configuration)
- Layer: Core Service (Data)
-Gitaly is a service designed by GitLab to remove our need for NFS for Git storage in distributed deployments of GitLab. (Think GitLab.com or High Availablity Deployments) As of 11.3.0, This service handles all Git level access in GitLab. You can read more about the project [in the project's readme](https://gitlab.com/gitlab-org/gitaly).
+Gitaly is a service designed by GitLab to remove our need for NFS for Git storage in distributed deployments of GitLab (Think GitLab.com or High Availability Deployments). As of 11.3.0, this service handles all Git level access in GitLab. You can read more about the project [in the project's readme](https://gitlab.com/gitlab-org/gitaly).
### gitlab-monitor
- Omnibus configuration options
-- Layer: Monitoring
+- Layer: Monitoring
-GitLab Monitor is a process disigned in house that allows us to export metrics about GitLab application internals to prometheus. You can read more [in the project's readme](https://gitlab.com/gitlab-org/gitlab-monitor)
+GitLab Monitor is a process designed in house that allows us to export metrics about GitLab application internals to prometheus. You can read more [in the project's readme](https://gitlab.com/gitlab-org/gitlab-monitor)
### gitlab-workhorse
- Omnibus configuration options
- Layer: Core Service (Processor)
-[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) is a program designed at GitLab to help alieviate pressure from unicorn. You can read more about the [historical reasons for developing](https://about.gitlab.com/2016/04/12/a-brief-history-of-gitlab-workhorse/). It's designed to act as a smart reverse proxy to help speed up GitLab as a whole.
+[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) is a program designed at GitLab to help alleviate pressure from unicorn. You can read more about the [historical reasons for developing](https://about.gitlab.com/2016/04/12/a-brief-history-of-gitlab-workhorse/). It's designed to act as a smart reverse proxy to help speed up GitLab as a whole.
### logrotate
@@ -100,14 +100,14 @@ Nginx as an ingress port for all HTTP requests and routes them to the approriate
- [Omnibus configuration options](https://docs.gitlab.com/ee/administration/monitoring/prometheus/postgres_exporter.html)
- Layer: Monitoring
-[Postgres-exporter](https://github.com/wrouesnel/postgres_exporter) is the community provided Prometheus exporter that will deliver data about Postgres to prometheus for use in Grafana Dashboards.
+[Postgres-exporter](https://github.com/wrouesnel/postgres_exporter) is the community provided Prometheus exporter that will deliver data about Postgres to prometheus for use in Grafana Dashboards.
### postgresql
- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/database.html)
- Layer: Core Service (Data)
-GitLab packages the popular Database to provide storage for Application meta data and user information.
+GitLab packages the popular Database to provide storage for Application meta data and user information.
### prometheus
@@ -121,11 +121,11 @@ Prometheus is a time-series tool that helps GitLab administrators expose metrics
- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/redis.html)
- Layer: Core Service (Data)
-Redis is packaged to provide a place to store:
+Redis is packaged to provide a place to store:
- session data
- temporary cache information
-- background job queues.
+- background job queues.
### redis-exporter
@@ -146,7 +146,7 @@ Sidekiq is a Ruby background job processor that pulls jobs from the redis queue
- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/unicorn.html)
- Layer: Core Service (Processor)
-[Unicorn](https://bogomips.org/unicorn/) is a Ruby application server that is used to run the core Rails Application that provides the user facing features in GitLab. Often process output you will see this as `bundle` or `config.ru` depending on the GitLab version.
+[Unicorn](https://bogomips.org/unicorn/) is a Ruby application server that is used to run the core Rails Application that provides the user facing features in GitLab. Often process output you will see this as `bundle` or `config.ru` depending on the GitLab version.
### Additional Processes
@@ -174,8 +174,7 @@ When making a request to an HTTP Endpoint (Think `/users/sign_in`) the request w
- nginx - Acts as our first line reverse proxy
- gitlab-workhorse - This determines if it needs to go to the Rails application or somewhere else to reduce load on unicorn.
- unicorn - Since this is a web request, and it needs to access the application it will go to Unicorn.
-- Postgres/Gitaly/Redis - Depending on the type of request, it may hit these services to store or retreive data.
-
+- Postgres/Gitaly/Redis - Depending on the type of request, it may hit these services to store or retrieve data.
### GitLab Git Request Cycle
diff --git a/doc/development/automatic_ce_ee_merge.md b/doc/development/automatic_ce_ee_merge.md
index 0cc083cefc0..3ca841353e6 100644
--- a/doc/development/automatic_ce_ee_merge.md
+++ b/doc/development/automatic_ce_ee_merge.md
@@ -115,16 +115,16 @@ Now, every time you create an MR for CE and EE:
1. Continue cherry-picking: `git cherry-pick --continue`
1. Push to EE: `git push origin branch-example-ee`
1. Create the EE-equivalent MR and link to the CE MR from the
-description "Ports [CE-MR-LINK] to EE"
+ description "Ports [CE-MR-LINK] to EE"
1. Once all the jobs are passing in both CE and EE, you've addressed the
-feedback from your own team, and got them approved, the merge requests can be merged.
+ feedback from your own team, and got them approved, the merge requests can be merged.
1. When both MRs are ready, the EE merge request will be merged first, and the
-CE-equivalent will be merged next.
+ CE-equivalent will be merged next.
**Important notes:**
- The commit SHA can be easily found from the GitLab UI. From a merge request,
-open the tab **Commits** and click the copy icon to copy the commit SHA.
+ open the tab **Commits** and click the copy icon to copy the commit SHA.
- To cherry-pick a **commit range**, such as [A > B > C > D] use:
```shell
@@ -140,7 +140,7 @@ open the tab **Commits** and click the copy icon to copy the commit SHA.
```
- To cherry-pick a **merge commit**, use the flag `-m 1`. For example, suppose that the
-merge commit SHA is `138f5e2f20289bb376caffa0303adb0cac859ce1`:
+ merge commit SHA is `138f5e2f20289bb376caffa0303adb0cac859ce1`:
```shell
git cherry-pick -m 1 138f5e2f20289bb376caffa0303adb0cac859ce1
@@ -148,7 +148,7 @@ merge commit SHA is `138f5e2f20289bb376caffa0303adb0cac859ce1`:
- To cherry-pick multiple commits, such as B and D in a range [A > B > C > D], use:
```shell
- git cherry-pick commmit-B-SHA commit-D-SHA
+ git cherry-pick commit-B-SHA commit-D-SHA
```
For example, suppose commit B SHA = `4f5e4018c09ed797fdf446b3752f82e46f5af502`,
@@ -163,12 +163,12 @@ merge commit SHA is `138f5e2f20289bb376caffa0303adb0cac859ce1`:
commits and you want to cherry-pick all but the merge commit.
- If you push more commits to the CE branch, you can safely repeat the procedure
-to cherry-pick them to the EE-equivalent branch. You can do that as many times as
-necessary, using the same CE and EE branches.
+ to cherry-pick them to the EE-equivalent branch. You can do that as many times as
+ necessary, using the same CE and EE branches.
- If you submitted the merge request to the CE repo and the `ee-compat-check` job passed,
-you are not required to submit the EE-equivalent MR, but it's still recommended. If the
-job failed, you are required to submit the EE MR so that you can fix the conflicts in EE
-before merging your changes into CE.
+ you are not required to submit the EE-equivalent MR, but it's still recommended. If the
+ job failed, you are required to submit the EE MR so that you can fix the conflicts in EE
+ before merging your changes into CE.
## FAQ
@@ -213,7 +213,7 @@ being able to deploy.
No, not if there is an EE merge request for every CE merge request that causes
conflicts _and_ that EE merge request is merged first. In the past we may have
been a bit more relaxed when it comes to enforcing EE merge requests, but to
-enable automatic merging have to start requiring such merge requests even for
+enable automatic merging we have to start requiring such merge requests even for
the smallest conflicts.
### Some files I work with often conflict, how can I best deal with this?
diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md
index dd4a9e058d7..642dac614c7 100644
--- a/doc/development/background_migrations.md
+++ b/doc/development/background_migrations.md
@@ -25,9 +25,9 @@ should only be used for data migrations.
Some examples where background migrations can be useful:
-* Migrating events from one table to multiple separate tables.
-* Populating one column based on JSON stored in another column.
-* Migrating data that depends on the output of external services (e.g. an API).
+- Migrating events from one table to multiple separate tables.
+- Populating one column based on JSON stored in another column.
+- Migrating data that depends on the output of external services (e.g. an API).
## Isolation
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index cd0a1f46d27..6efed36edf0 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -135,21 +135,13 @@ If you're working on the GitLab EE repository, the entry will be added to
| Argument | Shorthand | Purpose |
| ----------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
-| [`--amend`] | | Amend the previous commit |
-| [`--force`] | `-f` | Overwrite an existing entry |
-| [`--merge-request`] | `-m` | Set merge request ID |
-| [`--dry-run`] | `-n` | Don't actually write anything, just print |
-| [`--git-username`] | `-u` | Use Git user.name configuration as the author |
-| [`--type`] | `-t` | The category of the change, valid options are: `added`, `fixed`, `changed`, `deprecated`, `removed`, `security`, `performance`, `other` |
-| [`--help`] | `-h` | Print help message |
-
-[`--amend`]: #-amend
-[`--force`]: #-force-or-f
-[`--merge-request`]: #-merge-request-or-m
-[`--dry-run`]: #-dry-run-or-n
-[`--git-username`]: #-git-username-or-u
-[`--type`]: #-type-or-t
-[`--help`]: #-help
+| [`--amend`](#--amend) | | Amend the previous commit |
+| [`--force`](#--force-or--f) | `-f` | Overwrite an existing entry |
+| [`--merge-request`](#--merge-request-or--m) | `-m` | Set merge request ID |
+| [`--dry-run`](#--dry-run-or--n) | `-n` | Don't actually write anything, just print |
+| [`--git-username`](#--git-username-or--u) | `-u` | Use Git user.name configuration as the author |
+| [`--type`](#--type-or--t) | `-t` | The category of the change, valid options are: `added`, `fixed`, `changed`, `deprecated`, `removed`, `security`, `performance`, `other` |
+| `--help` | `-h` | Print help message |
##### `--amend`
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 25ea2211b64..f115045dbb7 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -23,6 +23,11 @@ one of the [Merge request coaches][team].
If you need assistance with security scans or comments, feel free to include the
Security Team (`@gitlab-com/gl-security`) in the review.
+The `danger-review` CI job will randomly pick a reviewer and a maintainer for
+each area of the codebase that your merge request seems to touch. It only makes
+recommendations - feel free to override it if you think someone else is a better
+fit!
+
Depending on the areas your merge request touches, it must be **approved** by one
or more [maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#maintainer):
@@ -132,6 +137,14 @@ If a developer who happens to also be a maintainer was involved in a merge reque
as a domain expert and/or reviewer, it is recommended that they are not also picked
as the maintainer to ultimately approve and merge it.
+Try to review in a timely manner; doing so allows everyone involved in the merge
+request to iterate faster as the context is fresh in memory. Further, this
+improves contributors' experiences significantly. Reviewers should aim to review
+within two working days from the date they were assigned the merge request. If
+you don't think you'll be able to review a merge request within that time, let
+the author know as soon as possible. When the author of the merge request has not
+heard anything after two days, a new reviewer should be assigned.
+
Maintainers should check before merging if the merge request is approved by the
required approvers.
@@ -190,7 +203,10 @@ first time.
- Extract unrelated changes and refactorings into future merge requests/issues.
- Seek to understand the reviewer's perspective.
- Try to respond to every comment.
-- Let the reviewer select the "Resolve discussion" buttons.
+- The merge request author resolves only the discussions they have fully
+ addressed. If there's an open reply, an open discussion, a suggestion,
+ a question, or anything else, the discussion should be left to be resolved
+ by the reviewer.
- Push commits based on earlier rounds of feedback as isolated commits to the
branch. Do not squash until the branch is ready to merge. Reviewers should be
able to read individual updates based on their earlier feedback.
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index 9dffca5b99c..f7a0fdbeb40 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -4,7 +4,7 @@ Thank you for your interest in contributing to GitLab. This guide details how
to contribute to GitLab in a way that is easy for everyone.
We want to create a welcoming environment for everyone who is interested in contributing.
-Please visit our [Code of Conduct page](https://about.gitlab.com/contributing/code-of-conduct) to learn more about our committment to an open and welcoming environment.
+Please visit our [Code of Conduct page](https://about.gitlab.com/contributing/code-of-conduct) to learn more about our commitment to an open and welcoming environment.
For a first-time step-by-step guide to the contribution process, please see
["Contributing to GitLab"](https://about.gitlab.com/contributing/).
@@ -97,28 +97,28 @@ When your code contains more than 500 changes, any major breaking changes, or an
This [documentation](issue_workflow.md) outlines the current issue process.
-* [Type labels](issue_workflow.md#type-labels)
-* [Subject labels](issue_workflow.md#subject-labels)
-* [Team labels](issue_workflow.md#team-labels)
-* [Release Scoping labels](issue_workflow.md#release-scoping-labels)
-* [Priority labels](issue_workflow.md#priority-labels)
-* [Severity labels](issue_workflow.md#severity-labels)
-* [Label for community contributors](issue_workflow.md#label-for-community-contributors)
-* [Issue triaging](issue_workflow.md#issue-triaging)
-* [Feature proposals](issue_workflow.md#feature-proposals)
-* [Issue tracker guidelines](issue_workflow.md#issue-tracker-guidelines)
-* [Issue weight](issue_workflow.md#issue-weight)
-* [Regression issues](issue_workflow.md#regression-issues)
-* [Technical and UX debt](issue_workflow.md#technical-and-ux-debt)
-* [Stewardship](issue_workflow.md#stewardship)
+- [Type labels](issue_workflow.md#type-labels)
+- [Subject labels](issue_workflow.md#subject-labels)
+- [Team labels](issue_workflow.md#team-labels)
+- [Release Scoping labels](issue_workflow.md#release-scoping-labels)
+- [Priority labels](issue_workflow.md#priority-labels)
+- [Severity labels](issue_workflow.md#severity-labels)
+- [Label for community contributors](issue_workflow.md#label-for-community-contributors)
+- [Issue triaging](issue_workflow.md#issue-triaging)
+- [Feature proposals](issue_workflow.md#feature-proposals)
+- [Issue tracker guidelines](issue_workflow.md#issue-tracker-guidelines)
+- [Issue weight](issue_workflow.md#issue-weight)
+- [Regression issues](issue_workflow.md#regression-issues)
+- [Technical and UX debt](issue_workflow.md#technical-and-ux-debt)
+- [Stewardship](issue_workflow.md#stewardship)
## Merge requests
This [documentation](merge_request_workflow.md) outlines the current merge request process.
-* [Merge request guidelines](merge_request_workflow.md#merge-request-guidelines)
-* [Contribution acceptance criteria](merge_request_workflow.md#contribution-acceptance-criteria)
-* [Definition of done](merge_request_workflow.md#definition-of-done)
+- [Merge request guidelines](merge_request_workflow.md#merge-request-guidelines)
+- [Contribution acceptance criteria](merge_request_workflow.md#contribution-acceptance-criteria)
+- [Definition of done](merge_request_workflow.md#definition-of-done)
## Style guides
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index 7c7da50a149..4c53643ed9c 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -6,7 +6,7 @@ scheduling into milestones. Labelling is a task for everyone.
Most issues will have labels for at least one of the following:
-- Type: ~"feature proposal", ~bug, ~customer, etc.
+- Type: ~feature, ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~Plan, ~Manage, ~Quality, etc.
- Stage: ~"devops:plan", ~"devops:create", etc.
@@ -20,15 +20,15 @@ All labels, their meaning and priority are defined on the
If you come across an issue that has none of these, and you're allowed to set
labels, you can _always_ add the team and type, and often also the subject.
-[milestones-page]: https://gitlab.com/gitlab-org/gitlab-ce/milestones
+[milestones-page]: https://gitlab.com/groups/gitlab-org/-/milestones
## Type labels
Type labels are very important. They define what kind of issue this is. Every
issue should have one or more.
-Examples of type labels are ~"feature proposal", ~bug, ~customer, ~security,
-and ~"direction".
+Examples of type labels are ~feature, ~bug, ~customer, ~security,
+and ~direction.
A number of type labels have a priority assigned to them, which automatically
makes them float to the top, depending on their importance.
@@ -67,7 +67,7 @@ The current team labels are:
- ~Geo
- ~Gitaly
- ~Manage
-- ~Monitoring
+- ~Monitor
- ~Plan
- ~Quality
- ~Release
@@ -199,8 +199,8 @@ different way.
We add the ~"Accepting merge requests" label to:
- Low priority ~bug issues (i.e. we do not add it to the bugs that we want to
-solve in the ~"Next Patch Release")
-- Small ~"feature proposal"
+ solve in the ~"Next Patch Release")
+- Small ~feature
- Small ~"technical debt" issues
After adding the ~"Accepting merge requests" label, we try to estimate the
@@ -259,10 +259,10 @@ For feature proposals for EE, open an issue on the
[issue tracker of EE][ee-tracker].
In order to help track the feature proposals, we have created a
-[`feature proposal`][fpl] label. For the time being, users that are not members
+[`feature`][fl] label. For the time being, users that are not members
of the project cannot add labels. You can instead ask one of the [core team]
-members to add the label ~"feature proposal" to the issue or add the following
-code snippet right after your description in a new line: `~"feature proposal"`.
+members to add the label ~feature to the issue or add the following
+code snippet right after your description in a new line: `~feature`.
Please keep feature proposals as small and simple as possible, complex ones
might be edited to make them small and simple.
@@ -276,7 +276,7 @@ need to ask one of the [core team] members to add the label, if you do not have
If you want to create something yourself, consider opening an issue first to
discuss whether it is interesting to include this in GitLab.
-[fpl]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=feature+proposal
+[fl]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=feature
## Issue tracker guidelines
@@ -300,17 +300,17 @@ below will make it easy to manage this, without unnecessary overhead.
1. Set weight for any issue at the earliest possible convenience
1. If you don't agree with a set weight, discuss with other developers until
-consensus is reached about the weight
+ consensus is reached about the weight
1. Issue weights are an abstract measurement of complexity of the issue. Do not
-relate issue weight directly to time. This is called [anchoring](https://en.wikipedia.org/wiki/Anchoring)
-and something you want to avoid.
+ relate issue weight directly to time. This is called [anchoring](https://en.wikipedia.org/wiki/Anchoring)
+ and something you want to avoid.
1. Something that has a weight of 1 (or no weight) is really small and simple.
-Something that is 9 is rewriting a large fundamental part of GitLab,
-which might lead to many hard problems to solve. Changing some text in GitLab
-is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
+ Something that is 9 is rewriting a large fundamental part of GitLab,
+ which might lead to many hard problems to solve. Changing some text in GitLab
+ is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
1. If something is very large, it should probably be split up in multiple
-issues or chunks. You can simply not set the weight of a parent issue and set
-weights to children issues.
+ issues or chunks. You can simply not set the weight of a parent issue and set
+ weights to children issues.
## Regression issues
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 6bcee74a3dd..8b14c3b20ea 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -86,6 +86,14 @@ request is as follows:
guidelines](../merge_request_performance_guidelines.md).
1. For tests that use Capybara or PhantomJS, see this [article on how
to write reliable asynchronous tests](https://robots.thoughtbot.com/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.
Please keep the change in a single MR **as small as possible**. If you want to
contribute a large feature think very hard what the minimum viable change is.
@@ -171,21 +179,21 @@ the feature you contribute through all of these steps.
1. Added to [the website](https://gitlab.com/gitlab-com/www-gitlab-com/), if relevant
1. Community questions answered
1. Answers to questions radiated (in docs/wiki/support etc.)
-1. [Black-box tests/end-to-end tests](../testing_guide/testing_levels.md#black-box-tests-or-end-to-end-tests) added if required. Please contact [the quality team](https://about.gitlab.com/handbook/engineering/quality/#teams) with any questions
+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
If you add a dependency in GitLab (such as an operating system package) please
consider updating the following and note the applicability of each in your
merge request:
-1. Note the addition in the release blog post (create one if it doesn't exist yet) https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/
-1. Upgrade guide, for example https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.5-to-7.6.md
-1. Installation guide https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies
-1. GitLab Development Kit https://gitlab.com/gitlab-org/gitlab-development-kit
-1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh
-1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
+1. Note the addition in the release blog post (create one if it doesn't exist yet) <https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/>
+1. Upgrade guide, for example <https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.5-to-7.6.md>
+1. Installation guide <https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies>
+1. GitLab Development Kit <https://gitlab.com/gitlab-org/gitlab-development-kit>
+1. Test suite <https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh>
+1. Omnibus package creator <https://gitlab.com/gitlab-org/omnibus-gitlab>
[definition-of-done]: http://guide.agilealliance.org/guide/definition-of-done.html
-[testing]: ../testing_guide/index.md
+[testing]: ../testing_guide/index.md
---
diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md
index 6f1ba5d62a5..0eedef5e14f 100644
--- a/doc/development/contributing/style_guides.md
+++ b/doc/development/contributing/style_guides.md
@@ -21,6 +21,7 @@
of _prohibited this user from being saved due to the following errors:_ the
text should be _sorry, we could not create your account because:_
1. Code should be written in [US English][us-english]
+1. [Go](../go_guide/index.md)
This is also the style used by linting tools such as
[RuboCop](https://github.com/bbatsov/rubocop) and [Hound CI](https://houndci.com).
diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md
index b2c804b2ff0..f00c5ccb9e9 100644
--- a/doc/development/database_debugging.md
+++ b/doc/development/database_debugging.md
@@ -13,7 +13,6 @@ Available `RAILS_ENV`
- `development` (this is your main GDK db)
- `test` (used for tests like rspec)
-
## Nuke everything and start over
If you just want to delete everything and start over with an empty DB (~1 minute):
@@ -36,7 +35,6 @@ If your test DB is giving you problems, it is safe to nuke it because it doesn't
- `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)
@@ -54,7 +52,6 @@ bundle exec rails db RAILS_ENV=development
- `SELECT * FROM schema_migrations WHERE version = '20170926203418';`: Check if a migration was run
- `DELETE FROM schema_migrations WHERE version = '20170926203418';`: Manually remove a migration
-
## FAQ
### `ActiveRecord::PendingMigrationError` with Spring
diff --git a/doc/development/diffs.md b/doc/development/diffs.md
index 43fc125c21d..56e869c21f8 100644
--- a/doc/development/diffs.md
+++ b/doc/development/diffs.md
@@ -59,28 +59,24 @@ Gitlab::Git::DiffCollection.collection_limits[:safe_max_files] = Gitlab::Git::Di
File diffs will be collapsed (but be expandable) if 100 files have already been rendered.
-
```ruby
Gitlab::Git::DiffCollection.collection_limits[:safe_max_lines] = Gitlab::Git::DiffCollection::DEFAULT_LIMITS[:max_lines] = 5000
```
File diffs will be collapsed (but be expandable) if 5000 lines have already been rendered.
-
```ruby
Gitlab::Git::DiffCollection.collection_limits[:safe_max_bytes] = Gitlab::Git::DiffCollection.collection_limits[:safe_max_files] * 5.kilobytes = 500.kilobytes
```
File diffs will be collapsed (but be expandable) if 500 kilobytes have already been rendered.
-
```ruby
Gitlab::Git::DiffCollection.collection_limits[:max_files] = Commit::DIFF_HARD_LIMIT_FILES = 1000
```
No more files will be rendered at all if 1000 files have already been rendered.
-
```ruby
Gitlab::Git::DiffCollection.collection_limits[:max_lines] = Commit::DIFF_HARD_LIMIT_LINES = 50000
```
@@ -129,4 +125,3 @@ Diff Viewers, which can be found on `models/diff_viewer/*` are classes used to m
whether it's a binary, which partial should be used to render it or which File extensions this class accounts for.
`DiffViewer::Base` validates _blobs_ (old and new versions) content, extension and file type in order to check if it can be rendered.
-
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
new file mode 100644
index 00000000000..038e3de10d7
--- /dev/null
+++ b/doc/development/distributed_tracing.md
@@ -0,0 +1,182 @@
+# Distributed Tracing - development guidelines
+
+GitLab is instrumented for distributed tracing.
+
+According to [Open Tracing](https://opentracing.io/docs/overview/what-is-tracing/):
+
+> Distributed tracing, also called distributed request tracing, is a method used to profile and
+> monitor applications, especially those built using a microservices architecture. Distributed
+> tracing helps to pinpoint where failures occur and what causes poor performance.
+
+Distributed tracing is especially helpful in understanding the lifecycle of a request as it passes
+through the different components of the GitLab application. At present, Workhorse, Rails, Sidekiq,
+and Gitaly support tracing instrumentation.
+
+Distributed tracing adds minimal overhead when disabled, but imposes only small overhead when
+enabled and is therefore capable in any environment, including production. For this reason, it can
+be useful in diagnosing production issues, particularly performance problems.
+
+## Enabling distributed tracing
+
+GitLab uses the `GITLAB_TRACING` environment variable to configure distributed tracing. The same
+configuration is used for all components (e.g., Workhorse, Rails, etc).
+
+When `GITLAB_TRACING` is not set, the application will not be instrumented, meaning that there is
+no overhead at all.
+
+To enable `GITLAB_TRACING`, a valid _"configuration-string"_ value should be set, with a URL-like
+form:
+
+```console
+GITLAB_TRACING=opentracing://<driver>?<param_name>=<param_value>&<param_name_2>=<param_value_2>
+```
+
+In this example, we have the following hypothetical values:
+
+- `driver`: the driver. [GitLab supports
+ `jaeger`](https://docs.gitlab.com/ee/user/project/operations/tracing.html). In future, other
+ tracing implementations may also be supported.
+- `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.
+ 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
+Jaeger out-of-the-box.
+
+The easiest way to access tracing from a GDK environment is through the
+[performance-bar](../administration/monitoring/performance/performance_bar.md). This can be shown
+by typing `p` `b` in the browser window.
+
+![Jaeger Search UI](img/distributed_tracing_performance_bar.png)
+
+Once the performance bar is enabled, click on the **Trace** link in the performance bar to go to
+the Jaeger UI.
+
+The Jaeger search UI will return a query for the `Correlation-ID` of the current request. Normally,
+this search should return a single trace result. Clicking this result will show the detail of the
+trace in a hierarchical time-line.
+
+![Jaeger Search UI](img/distributed_tracing_jaeger_ui.png)
+
+## Using Jaeger without the GitLab Developer Kit
+
+Distributed Tracing can be enabled in non-GDK development environments as well as production or
+staging environments, for troubleshooting. Please note that at this time, this functionality is
+experimental, and not supported in production environments at present. In this first release, it is intended to be
+used for debugging in development environments only.
+
+Jaeger tracing can be enabled through a three-step process:
+
+1. [Start Jaeger](#1-start-jaeger).
+1. [Configure the `GITLAB_TRACING` environment variable](#2-configure-the-gitlab_tracing-environment-variable).
+1. [Start the GitLab application](#3-start-the-gitlab-application).
+1. [Go to the Jaeger Search UI in your browser](#4-open-the-jaeger-search-ui).
+
+### 1. Start Jaeger
+
+Jaeger has many configuration options, but is very easy to start in an "all-in-one" mode which uses
+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/).
+
+#### Using Docker
+
+If you have Docker available, the easier approach to running the Jaeger all-in-one is through
+Docker, using the following command:
+
+```console
+$ docker run \
+ --rm \
+ -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
+ -p 5775:5775/udp \
+ -p 6831:6831/udp \
+ -p 6832:6832/udp \
+ -p 5778:5778 \
+ -p 16686:16686 \
+ -p 14268:14268 \
+ -p 9411:9411 \
+ jaegertracing/all-in-one:latest
+```
+
+#### Using the Jaeger process
+
+Without Docker, the all-in-one process is still easy to setup.
+
+1. Download the [latest Jaeger release](https://github.com/jaegertracing/jaeger/releases) for your
+ platform.
+1. Extract the archive and run the `bin/all-in-one` process.
+
+This should start the process with the default listening ports.
+
+### 2. Configure the `GITLAB_TRACING` environment variable
+
+Once you have Jaeger running, you'll need to configure the `GITLAB_TRACING` variable with the
+appropriate configuration string.
+
+**TL;DR:** If you are running everything on the same host, use the following value:
+
+```console
+$ export GITLAB_TRACING="opentracing://jaeger?http_endpoint=http%3A%2F%2Flocalhost%3A14268%2Fapi%2Ftraces&sampler=const&sampler_param=1"
+```
+
+This configuration string uses the Jaeger driver `opentracing://jaeger` with the following options:
+
+| Name | Value | Description |
+|------|-------|-------------|
+| `http_endpoint` | `http://localhost:14268/api/traces` | Configures Jaeger to send trace information to the HTTP endpoint running on `http://localhost:14268/`. Alternatively, the `upd_endpoint` can be used. |
+| `sampler` | `const` | Configures Jaeger to use the constant sampler (either on or off). |
+| `sampler_param` | `1` | Configures the `const` sampler to sample _all_ traces. Using `0` would sample _no_ traces. |
+
+**Other parameter values are also possible:**
+
+| Name | Example | Description |
+|------|-------|-------------|
+| `udp_endpoint` | `localhost:6831` | This is the default. Configures Jaeger to send trace information to the UDP listener on port `6831` using compact thrift protocol. Note that we've experienced some issues with the [Jaeger Client for Ruby](https://github.com/salemove/jaeger-client-ruby) when using this protocol. |
+| `sampler` | `probabalistic` | Configures Jaeger to use a probabilistic random sampler. The rate of samples is configured by the `sampler_param` value. |
+| `sampler_param` | `0.01` | Use a ratio of `0.01` to configure the `probabalistic` sampler to randomly sample _1%_ of traces. |
+
+NOTE: **Note:**
+The same `GITLAB_TRACING` value should to be configured in the environment
+variables for all GitLab processes, including Workhorse, Gitaly, Rails, and Sidekiq.
+
+### 3. Start the GitLab application
+
+Once the `GITLAB_TRACING` environment variable is exported to all GitLab services, start the
+application.
+
+When `GITLAB_TRACING` is configured properly, the application will log this on startup:
+
+```console
+13:41:53 gitlab-workhorse.1 | 2019/02/12 13:41:53 Tracing enabled
+...
+13:41:54 gitaly.1 | 2019/02/12 13:41:54 Tracing enabled
+...
+```
+
+If `GITLAB_TRACING` is not configured correctly, this will also be logged:
+
+```console
+13:43:45 gitaly.1 | 2019/02/12 13:43:45 skipping tracing configuration step: tracer: unable to load driver mytracer
+```
+
+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://godoc.org/gitlab.com/gitlab-org/labkit/tracing).
+
+If no log messages about tracing are emitted, the `GITLAB_TRACING` environment variable is likely
+not set.
+
+### 4. Open the Jaeger Search UI
+
+By default, the Jaeger search UI is available at <http://localhost:16686/search>.
+
+TIP: **Tip:**
+Don't forget that you will need to generate traces by using the application before
+they appear in the Jaeger UI.
+
diff --git a/doc/development/documentation/feature-change-workflow.md b/doc/development/documentation/feature-change-workflow.md
new file mode 100644
index 00000000000..3f31fe5ca19
--- /dev/null
+++ b/doc/development/documentation/feature-change-workflow.md
@@ -0,0 +1,179 @@
+---
+description: How to add docs for new or enhanced GitLab features.
+---
+
+# Documentation process for feature changes
+
+At GitLab, developers contribute new or updated documentation along with their code, but product managers and technical writers also have essential roles in the process.
+
+- **Developers**: Author/update documentation in the same MR as their code, and
+ merge it by the feature freeze for the assigned milestone. Request technical writer
+ assistance if needed. Other developers typically act as reviewers.
+- **Product Managers** (PMs): In the issue for all new and enhanced features,
+ confirm the documentation requirements, plus the mentioned feature description
+ and use cases, which can be reused in docs. They can bring in a technical
+ writer for discussion or collaboration, and can be called upon themselves as a doc reviewer.
+- **Technical Writers**: Review doc requirements in issues, track issues and MRs
+ that contain docs changes, help with any questions throughout the authoring/editing process,
+ work on special projects related to the documentation, and review all new and updated
+ docs content, whether before or after it is merged.
+
+Beyond this process, any member of the GitLab community can also author or request documentation
+improvements that are not associated with a new or changed feature. See the [Documentation improvement workflow](improvement-workflow.md).
+
+## When documentation is required
+
+Documentation must be delivered whenever:
+
+- A new or enhanced feature is shipped that impacts the user/admin experience.
+- There are changes to the UI or API.
+- A process, workflow, or previously documented feature is changed.
+- A feature is deprecated or removed.
+
+For example, a UI restyling that offers no difference in functionality may require
+documentation updates if screenshots are now needed, or need to be updated.
+
+Documentation is not required when a feature is changed on the backend
+only and does not directly affect the way that any user or administrator would
+interact with GitLab.
+
+NOTE: **Note:**
+When revamping documentation, if unrelated to the feature change, this should be submitted
+in its own MR (using the [documentation improvement workflow](improvement-workflow.md))
+so that we can ensure the more time-sensitive doc updates are merged with code by the freeze.
+
+## Documentation requirements in feature issues
+
+Requirements for the documentation of a feature should be included as part of the
+issue for planning that feature, in a Documentation section within the issue description.
+
+This section is provided as part of the Feature Proposal template and should be added
+to the issue if it is not already present.
+
+Anyone can add these details, but the product manager who assigns the issue to a specific release
+milestone will ensure these details are present and finalized by the time of that milestone's kickoff.
+Developers, technical writers, and others may help further refine this plan at any time.
+
+### Details to include
+
+- What concepts and procedures should the docs guide and enable the user to understand or accomplish?
+- To this end, what new page(s) are needed, if any? What pages/subsections need updates? Consider user, admin, and API doc changes and additions.
+- For any guide or instruction set, should it help address a single use case, or be flexible to address a certain range of use cases?
+- Do we need to update a previously recommended workflow? Should we link the new feature from various relevant locations? Consider all ways documentation should be affected.
+- Are there any key terms or task descriptions that should be included so that the docs are found in relevant searches?
+- Include suggested titles of any pages or subsections, if applicable.
+
+## Documenting a new or changed feature
+
+To follow a consistent workflow every month, documentation changes
+involve the Product Managers, the developer who shipped the feature,
+and the technical writer for the DevOps stage. Each role is described below.
+
+The Documentation items in the GitLab CE/EE [Feature Proposal issue template](https://gitlab.com/gitlab-org/gitlab-ce/raw/template-improvements-for-documentation/.gitlab/issue_templates/Feature%20proposal.md)
+and default merge request template will assist you with following this process.
+
+### Product Manager role
+
+For issues requiring any new or updated documentation, the Product Manager (PM)
+must:
+
+- Add the `Documentation` label.
+- Confirm or add the [documentation requirements](#documentation-requirements).
+- Ensure the issue contains any new or updated feature name, overview/description,
+ and use cases, as required per the [documentation structure and template](structure.md), when applicable.
+
+Everyone is encouraged to draft the requirements in the issue, but a product manager will
+do the following:
+
+- When the issue is assigned a release milestone, review and update the Documentation details.
+- By the kickoff, finalizie the Documentation details.
+
+### Developer and maintainer roles
+
+#### Authoring
+
+As a developer, you must ship the documentation with the code of the feature that
+you are creating or updating. The documentation is an essential part of the product.
+Technical writers are happy to help, as requested and planned on an issue-by-issue basis.
+
+Follow the process below unless otherwise agreed with the product manager and technical writer for a given issue:
+
+- Include any new and edited docs in the MR introducing the code.
+- Use the Documentation requirements confirmed by the Product Manager in the
+ issue and discuss any further doc plans or ideas as needed.
+ - If the new or changed doc requires extensive collaboration or conversation, a separate,
+ linked issue can be used for the planning process.
+ - We are trying to avoid using a separate MR, so that the docs stay with the code, but the
+ Technical Writing team is interested in discussing any potential exceptions that may be suggested.
+- Use the [Documentation guidelines](index.md), as well as other resources linked from there,
+ including the Documentation [Structure and template](structure.md) page, [Style Guide](styleguide.md), and [Markdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/).
+- If you need any help to choose the correct place for a doc, discuss a documentation
+ idea or outline, or request any other help, ping the Technical Writer for the relevant
+ [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages)
+ in your issue or MR, or write within `#docs` on the GitLab Slack.
+- The docs must be merged with the code **by the feature freeze date**, otherwise
+ the feature cannot be included with the release. A policy for documenting feature-flagged
+ issues is forthcoming and you are welcome to join the [discussion](https://gitlab.com/gitlab-org/gitlab-ce/issues/56813).
+
+#### Reviews and merging
+
+All reviewers can help ensure accuracy, clarity, completeness, and adherence to the plans in the issue, as well as the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide.html).
+
+- **Prior to merging**, documentation changes committed by the developer must be reviewed by:
+
+ 1. **The code reviewer** for the MR, to confirm accuracy, clarity, and completeness.
+ 1. Optionally: Others involved in the work, such as other devs or the PM.
+ 1. Optionally: The technical writer for the DevOps stage. If not prior to merging, the technical writer will review after the merge.
+ This helps us ensure that the developer has time to merge good content by the freeze, and that it can be further refined by the release, if needed.
+ - To decide whether to request this review before the merge, consider the amount of time left before the code freeze, the size of the change,
+ and your degree of confidence in having users of an RC use your docs as written.
+ - Pre-merge tech writer reviews should be most common when the code is complete well in advance of the freeze and/or for larger documentation changes.
+ - You can request a review and if there is not sufficient time to complete it prior to the freeze,
+ the maintainer can merge the current doc changes (if complete) and create a follow-up doc review issue.
+ - The technical writer can also help decide what docs to merge before the freeze and whether to work on further changes in a follow up MR.
+ - **To request a pre-merge technical writer review**, assign the writer listed for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages).
+ - **To request a post-merge technical writer review**, [create an issue for one using the Doc Review template](https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issuable_template=Doc%20Review) and link it from the MR that makes the doc change.
+ 1. **The maintainer** who is assigned to merge the MR, to verify clarity, completeness, and quality, to the best of their ability.
+
+- Upon merging, if a technical writer review has not been performed and there is not yet a linked issue for a follow-up review, the maintainer should [create an issue using the Doc Review template](https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issuable_template=Doc%20Review), link it from the MR, and
+ mention the original MR author in the new issue. Alternatively, the mainitainer can ask the MR author to create and link this issue before the MR is merged.
+
+- After merging, documentation changes are reviewed by:
+
+ 1. The technical writer--**if** their review was not performed prior to the merge.
+ 2. Optionally: by the PM (for accuracy and to ensure it's consistent with the vision for how the product will be used).
+ Any party can raise the item to the PM for review at any point: the dev, the technical writer, or the PM, who can request/plan a review at the outset.
+
+### Technical Writer role
+
+#### Planning
+
+- The technical writer monitors the documentation needs of issues assigned to the current and next milestone
+ for their DevOps stage(s), and participates in any needed discussion on docs planning and requirements refinement
+ with the dev, PM, and others.
+- The technical writer will review these requirements again upon the kickoff and provide feedback, as needed.
+ This is not a blocking review and developers should not wait to work on docs.
+
+#### Collaboration
+
+By default, the developer will work on documentation changes independently, but
+the developer, PM, or technicial writer can propose a broader collaboration for
+any given issue.
+
+Additionally, technical writers are available for questions at any time.
+
+#### Review
+
+- Techncial writers provide non-blocking reviews of all documentation changes,
+ before or after the change is merged. However, if the docs are ready in the MR while
+ there's time before the freeze, the technical writer's review can commence early, on request.
+- The technical writer will confirm that the doc is clear, grammatically correct,
+ and discoverable, while avoiding redundancy, bad file locations, typos, broken links,
+ etc. The technical writer will review the documentation for the following, which
+ the developer and code reviewer should have already made a good-faith effort to ensure:
+ - Clarity.
+ - Adherence to the plans and goals in the issue.
+ - Location (make sure the docs are in the correct directorkes and has the correct name).
+ - Syntax, typos, and broken links.
+ - Improvements to the content.
+ - Accordance with the [Documentation Style Guide](styleguide.md), and [Structure and Template](structure.md) doc.
diff --git a/doc/development/documentation/improvement-workflow.md b/doc/development/documentation/improvement-workflow.md
new file mode 100644
index 00000000000..a12c3d5ea7b
--- /dev/null
+++ b/doc/development/documentation/improvement-workflow.md
@@ -0,0 +1,63 @@
+---
+description: How to improve GitLab's documentation.
+---
+
+# Documentation improvement workflow
+
+Anyone can contribute a merge request or create an issue for GitLab's documentation.
+
+This page covers the process for any contributions to GitLab's docs that are
+not part of feature development. If you are looking for information on updating
+GitLab's docs as is required with the development and release of a new feature
+or feature enhancement, see the [documentation process for feature changes](feature-change-workflow.md).
+
+## Who updates the docs
+
+Anyone can contribute! You can create a merge request with documentation
+when you find errors or other room for improvement in an existing doc, or when you
+have an idea for all-new documentation that would help a GitLab user or administrator
+to accomplish their work with GitLab.
+
+## How to update the docs
+
+1. Click "Edit this Page" at the bottom of any page on docs.gitlab.com, or navigate to
+ one of the repositories and doc paths listed on the [GitLab Documentation guidelines](index.md) page.
+ Work in a fork if you do not have developer access to the GitLab project.
+1. Follow the described standards and processes listed on that Guidelines page,
+ including the linked resources: the [Structure and template](structure.md) page, [Style Guide](styleguide.md), and [Markdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/).
+1. Follow GitLab's [Merge Request Guidelines](../contributing/merge_request_workflow.md#merge-request-guidelines).
+
+If you need any help to choose the correct place for a doc, discuss a documentation
+idea or outline, or request any other help, ping the Technical Writer for the relevant
+[DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages)
+in your issue or MR, or write within `#docs` if you are a member of GitLab's Slack workspace.
+
+## Review and merging
+
+Anyone with master access to the affected GitLab project can merge documentation changes.
+This person must make a good-faith effort to ensure that the content is clear
+(sufficiently easy for the intended audience to navigate and understand) and
+that it meets the [Documentation Guidelines](index.md) and [Style Guide](styleguide.md).
+
+If the author or reviewer has any questions, or would like a techncial writer's review
+before merging, mention the writer who is assigned to the relevant [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages).
+
+The process can involve the following parties/phases, and is replicated in the `Documentation` MR template for GitLab CE and EE, to help with following the process.
+
+**1. Primary Reviewer** - Review by a [code reviewer](https://about.gitlab.com/handbook/engineering/projects/) or other appropriate colleague to confirm accuracy, clarity, and completeness. This can be skipped for minor fixes without substantive content changes.
+
+**2. Technical Writer** - Optional - If not requested for this MR, must be scheduled post-merge. To request a pre-merge review, assign the writer listed for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages).
+To request a post-merge review, [create an issue for one using the Doc Review template](https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issuable_template=Doc%20Review) and link it from the MR that makes the doc change.
+
+**3. Maintainer**
+
+1. Review by assigned maintainer, who can always request/require the above reviews. Maintainer review can occur before or after a technical writer review.
+2. Ensure a release milestone of the format XX.Y is set. If the freeze for that release has begun, add the label `pick into <XX.Y>` unless this change is not required for the release. In that case, simply change the milestone.
+3. If EE and CE MRs exist, merge the EE MR first, then the CE MR.
+4. After merging, if there has not been a technical writer review and an issue for a follow-up review was not already created and linked from the MR, [create the issue using the Doc Review template](https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issuable_template=Doc%20Review) and link it from the MR.
+
+## Other ways to help
+
+If you have ideas for further documentation resources that would be best
+considered/handled by technical writers, devs, and other SMEs, please [create an issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issuable_template=Documentation)
+using the Documentation template.
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 4e5b4a85a97..a4da34a50ce 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -4,48 +4,49 @@ description: Learn how to contribute to GitLab Documentation.
# GitLab Documentation guidelines
-- **General Documentation**: written by the [developers responsible by creating features](#contributing-to-docs). Should be submitted in the same merge request containing code. Feature proposals (by GitLab contributors) should also be accompanied by its respective documentation. They can be later improved by PMs and Technical Writers.
-- **[Technical Articles](#technical-articles)**: written by any [GitLab Team](https://about.gitlab.com/team/) member, GitLab contributors, or [Community Writers](https://about.gitlab.com/handbook/product/technical-writing/community-writers/).
-- **Indexes per topic**: initially prepared by the Technical Writing Team, and kept up-to-date by developers and PMs in the same merge request containing code. They gather all resources for that topic in a single page (user and admin documentation, articles, and third-party docs).
+GitLab's documentation is [intended as the single source of truth (SSOT)](https://about.gitlab.com/handbook/documentation/) for information about how to configure, use, and troubleshoot GitLab. The documentation contains use cases and usage instructions covering every GitLab feature, organized by product area and subject. This includes topics and workflows that span multiple GitLab features, as well as the use of GitLab with other applications.
-## Contributing to docs
+In addition to this page, the following resources to help craft and contribute documentation are available:
+
+- [Style Guide](styleguide.md) - What belongs in the docs, language guidelines, and more.
+- [Structure and template](structure.md) - Learn the typical parts of a doc page and how to write each one.
+- [Workflows](workflow.md) - A landing page for our key workflows:
+ - [Documentation process for feature changes](feature-change-workflow.md) - Adding required documentation when developing a GitLab feature.
+ - [Documentation improvement workflow](improvement-workflow.md) - New content not associated with a new feature.
+- [Markdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/) - A reference for the markdown implementation used by GitLab's documentation site and about.gitlab.com.
+- [Site architecture](site_architecture/index.md) - How docs.gitlab.com is built.
+
+## Source and rendered locations
-Whenever a feature is changed, updated, introduced, or deprecated, the merge
-request introducing these changes must be accompanied by the documentation
-(either updating existing ones or creating new ones). This is also valid when
-changes are introduced to the UI.
+Documentation for GitLab Community Edition (CE) and Enterprise Edition (EE), along with GitLab Runner and Omnibus, is published to [docs.gitlab.com](https://docs.gitlab.com). The documentation for CE and EE is also published within the application at `/help` on the domain of the GitLab instance.
-The one responsible for writing the first piece of documentation is the developer who
-wrote the code. It's the job of the Product Manager to ensure all features are
-shipped with its docs, whether is a small or big change. At the pace GitLab evolves,
-this is the only way to keep the docs up-to-date. If you have any questions about it,
-ask a Technical Writer. Otherwise, when your content is ready, assign one of
-them to review it for you.
+At `/help`, only content for your current edition and version is included, whereas multiple versions' content is available at docs.gitlab.com.
-We use the [monthly release blog post](https://about.gitlab.com/handbook/marketing/blog/release-posts/#monthly-releases) as a changelog checklist to ensure everything
-is documented.
+The source of the documentation is maintained in the following repository locations:
-Whenever you submit a merge request for the documentation, use the
-"Documentation" MR description template. If you're changing documentation
-location, use the MR description template called "Change documentation
-location" instead.
+| Project | Path |
+| --- | --- |
+| [GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-ce/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc) |
+| [GitLab Enterprise Edition](https://gitlab.com/gitlab-org/gitlab-ee/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc) |
+| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/) | [`/docs`](https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs) |
+| [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc) |
-## Documentation workflow
+Documentation issues and merge requests are part of their respective repositories and all have the label `Documentation`.
-Please read through the [documentation workflow](workflow.md) before getting started.
+## Contributing to docs
+
+[Contributions to GitLab docs](workflow.md) are welcome from the entire GitLab community.
-## Documentation structure
+To ensure that GitLab docs keep up with changes to the product, special processes and responsibilities are in place concerning all [feature changes](feature-change-workflow.md)—i.e. development work that impacts the appearance, usage, or administration of a feature.
-Follow through the [documentation structure guide](structure.md) for learning
-how to structure GitLab docs.
+Meanwhile, anyone can contribute [documentation improvements](improvement-workflow.md) large or small that are not associated with a feature change. For example, adding a new doc on how to accomplish a use case that's already possible with GitLab or with third-party tools and GitLab.
## Markdown and styles
[GitLab docs](https://gitlab.com/gitlab-com/gitlab-docs) uses [GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown)
-as markdown engine. Check the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/)
-for a complete Kramdown reference.
+as its markdown rendering engine. See the [GitLab Markdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/) for a complete Kramdown reference.
-Follow the [documentation style guidelines](styleguide.md) strictly.
+Adhere to the [Documentation Style Guide](styleguide.md). If a style standard is missing, you are welcome to suggest one via a merge request.
## Documentation directory structure
@@ -58,7 +59,7 @@ all docs should be linked. Every new document should be cross-linked to its rela
The directories `/workflow/`, `/gitlab-basics/`, `/university/`, and `/articles/` have
been **deprecated** and the majority their docs have been moved to their correct location
-in small iterations. Please don't create new docs in these folders.
+in small iterations. Please do not create new docs in these folders. Organize docs by product area and subject, not type.
### Documentation files
@@ -71,18 +72,23 @@ in small iterations. Please don't create new docs in these folders.
### Location and naming documents
-The documentation hierarchy can be vastly improved by providing a better layout
-and organization of directories.
-
-Having a structured document layout, we will be able to have meaningful URLs
-like `docs.gitlab.com/user/project/merge_requests/index.html`. With this pattern,
-you can immediately tell that you are navigating a user related documentation
-and is about the project and its merge requests.
-
-Do not create summaries of similar types of content (e.g. an index of all articles, videos, etc.),
-rather organize content by its subject (e.g. everything related to CI goes together)
+Our goal is to have a clear hierarchical structure with meaningful URLs
+like `docs.gitlab.com/user/project/merge_requests/`. With this pattern,
+you can immediately tell that you are navigating to user-related documentation
+about project features; specifically about merge requests. Our site's paths match
+those of our repository, so the clear structure also makes documentation easier to update.
+
+While the documentation is home to a variety of content types, we do not organize by content type.
+For example, do not create groupings of similar media types (e.g. indexes of all articles, videos, etc.).
+Similarly, we do not use glossaries or FAQs. Such grouping of content by type makes
+it difficult to browse for the information you need and difficult to maintain up-to-date content.
+Instead, organize content by its subject (e.g. everything related to CI goes together)
and cross-link between any related content.
+Do not simply link out to GitLab technical blog posts. There should be an up-to-date
+single source of truth on the topic within the documentation, and the top of the
+blog post should be updated to link to that doc.
+
The table below shows what kind of documentation goes where.
| Directory | What belongs here |
@@ -90,14 +96,12 @@ The table below shows what kind of documentation goes where.
| `doc/user/` | User related documentation. Anything that can be done within the GitLab UI goes here including `/admin`. |
| `doc/administration/` | Documentation that requires the user to have access to the server where GitLab is installed. The admin settings that can be accessed via GitLab's interface go under `doc/user/admin_area/`. |
| `doc/api/` | API related documentation. |
-| `doc/development/` | Documentation related to the development of GitLab. Any styleguides should go here. |
+| `doc/development/` | Documentation related to the development of GitLab. Related process and style guides should go here. |
| `doc/legal/` | Legal documents about contributing to GitLab. |
| `doc/install/` | Probably the most visited directory, since `installation.md` is there. Ideally this should go under `doc/administration/`, but it's best to leave it as-is in order to avoid confusion (still debated though). |
| `doc/update/` | Same with `doc/install/`. Should be under `administration/`, but this is a well known location, better leave as-is, at least for now. |
| `doc/topics/` | Indexes per Topic (`doc/topics/topic-name/index.md`): all resources for that topic (user and admin documentation, articles, and third-party docs) |
----
-
**General rules & best practices:**
1. When creating a new document and it has more than one word in its name,
@@ -126,18 +130,23 @@ The table below shows what kind of documentation goes where.
`doc/topics/topic-name/subtopic-name/index.md` when subtopics become necessary.
General user- and admin- related documentation, should be placed accordingly.
-If you are unsure where a document should live, you can ping `@axil` or `@marcia` in your
-merge request.
+If you are unsure where a document or a content addition should live, this should
+not stop you from authoring and contributing. You can use your best judgment and
+then ask the reviewer of your MR to confirm your decision, and/or ask a technical writer
+at any stage in the process. The techncial writing team will review all documentation
+changes, regardless, and can move content if there is a better place for it.
### Changing document location
-Changing a document's location is not to be taken lightly. Remember that the
-documentation is available to all installations under `help/` and not only to
-GitLab.com or <http://docs.gitlab.com>. Make sure this is discussed with the
-Documentation team beforehand.
+Changing a document's location requires specific steps to be followed to ensure that
+users can seamlessly access the new doc page, whether they are accesing content
+on a GitLab instance domain at `/help` or at docs.gitlab.com. Be sure to ping a
+GitLab technical writer if you have any questions during the process (such as
+whether the move is necessary), and ensure that a technical writer reviews this
+change prior to merging.
-If you indeed need to change a document's location, do NOT remove the old
-document, but rather replace all of its contents with a new line:
+If you indeed need to change a document's location, do not remove the old
+document, but rather replace all of its content with a new line:
```md
This document was moved to [another location](path/to/new_doc.md).
@@ -175,6 +184,7 @@ Things to note:
- Since we also use inline documentation, except for the documentation itself,
the document might also be referenced in the views of GitLab (`app/`) which will
render when visiting `/help`, and sometimes in the testing suite (`spec/`).
+ You must search these paths for references to the doc and update them as well.
- The above `git grep` command will search recursively in the directory you run
it in for `workflow/lfs/lfs_administration` and `lfs/lfs_administration`
and will print the file and the line where this file is mentioned.
@@ -202,7 +212,7 @@ This redirection method will not provide a redirect fallback on GitLab `/help`.
it, make sure to add a link to the new page on the doc, otherwise it's a dead end for users that
land on the doc via `/help`.
-### Redirections for pages with Disqus comments
+#### Redirections for pages with Disqus comments
If the documentation page being relocated already has any Disqus comments,
we need to preserve the Disqus thread.
@@ -240,20 +250,26 @@ choices:
| Ending in `-docs` | `123-update-api-issues-docs` |
If your branch name matches any of the above, it will run only the docs
-tests. If it doesn't, the whole test suite will run (including docs).
+tests. If it does not, the whole application test suite will run (including docs tests).
## Merge requests for GitLab documentation
Before getting started, make sure you read the introductory section
"[contributing to docs](#contributing-to-docs)" above and the
-[tech writing workflow](https://about.gitlab.com/handbook/product/technical-writing/workflow/)
-for GitLab Team members.
+[documentation workflow](workflow.md).
- Use the current [merge request description template](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/merge_request_templates/Documentation.md)
- Use the correct [branch name](#branch-naming)
- Label the MR `Documentation`
- Assign the correct milestone (see note below)
+Documentation will be merged if it is an improvement on existing content,
+represents a good-faith effort to follow the template and style standards,
+and is believed to be accurate.
+
+Further needs for what would make the doc even better should be immediately addressed
+in a follow-up MR or issue.
+
NOTE: **Note:**
If the release version you want to add the documentation to has already been
frozen or released, use the label `Pick into X.Y` to get it merged into
@@ -380,80 +396,14 @@ to merge changes that will break `master` from a merge request with a successful
## Docs site architecture
-Read through [docs architecture](site_architecture/index.md) to learn
-how we architecture, build, and deploy the docs site, <https://docs.gitlab.com>, and
-to check all the assets and libraries available.
+See the [Docs site architecture](site_architecture/index.md) page to learn
+how we build and deploy the site at [docs.gitlab.com](https://docs.gitlab.com), and
+to review all the assets and libraries in use.
### Global navigation
-Read through the [global navigation](site_architecture/global_nav.md) doc.
-
-## General Documentation vs Technical Articles
-
-### General documentation
-
-General documentation is categorized by _User_, _Admin_, and _Contributor_, and describe what that feature is, what it does, and its available settings.
-
-### Technical Articles
-
-Technical articles replace technical content that once lived in the [GitLab Blog](https://about.gitlab.com/blog/), where they got out-of-date and weren't easily found.
-
-They are topic-related documentation, written with an user-friendly approach and language, aiming to provide the community with guidance on specific processes to achieve certain objectives.
-
-A technical article guides users and/or admins to achieve certain objectives (within guides and tutorials), or provide an overview of that particular topic or feature (within technical overviews). It can also describe the use, implementation, or integration of third-party tools with GitLab.
-
-They should be placed in a new directory named `/article-title/index.md` under a topic-related folder, and their images should be placed in `/article-title/img/`. For example, a new article on GitLab Pages should be placed in `doc/user/project/pages/article-title/` and a new article on GitLab CI/CD should be placed in `doc/ci/examples/article-title/`.
-
-#### Types of Technical Articles
-
-- **User guides**: technical content to guide regular users from point A to point B
-- **Admin guides**: technical content to guide administrators of GitLab instances from point A to point B
-- **Technical Overviews**: technical content describing features, solutions, and third-party integrations
-- **Tutorials**: technical content provided step-by-step on how to do things, or how to reach specific objectives
-
-#### Understanding guides, tutorials, and technical overviews
-
-Suppose there's a process to go from point A to point B in 5 steps: `(A) 1 > 2 > 3 > 4 > 5 (B)`.
-
-A **guide** can be understood as a description of certain processes to achieve a particular objective. A guide brings you from A to B describing the characteristics of that process, but not necessarily going over each step. It can mention, for example, steps 2 and 3, but does not necessarily explain how to accomplish them.
-
-- Live example: "[Static sites and GitLab Pages domains (Part 1)](../../user/project/pages/getting_started_part_one.md) to [Creating and Tweaking GitLab CI/CD for GitLab Pages (Part 4)](../../user/project/pages/getting_started_part_four.md)"
-
-A **tutorial** requires a clear **step-by-step** guidance to achieve a singular objective. It brings you from A to B, describing precisely all the necessary steps involved in that process, showing each of the 5 steps to go from A to B.
-It does not only describes steps 2 and 3, but also shows you how to accomplish them.
-
-- Live example (on the blog): [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/)
-
-A **technical overview** is a description of what a certain feature is, and what it does, but does not walk
-through the process of how to use it systematically.
-
-- Live example (on the blog): [GitLab Workflow, an overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/)
-
-#### Special format
-
-Every **Technical Article** contains a frontmatter at the beginning of the doc
-with the following information:
-
-- **Type of article** (user guide, admin guide, technical overview, tutorial)
-- **Knowledge level** expected from the reader to be able to follow through (beginner, intermediate, advanced)
-- **Author's name** and **GitLab.com handle**
-- **Publication date** (ISO format YYYY-MM-DD)
-
-For example:
-
-```yaml
----
-author: John Doe
-author_gitlab: johnDoe
-level: beginner
-article_type: user guide
-date: 2017-02-01
----
-```
-
-#### Technical Articles - Writing Method
-
-Use the [writing method](https://about.gitlab.com/handbook/product/technical-writing/#writing-method) defined by the Technical Writing team.
+See the [Global navigation](site_architecture/global_nav.md) doc for information
+on how the left-side navigation menu is built and updated.
## Previewing the changes live
@@ -468,13 +418,13 @@ The live preview is currently enabled for the following projects:
- <https://gitlab.com/gitlab-org/gitlab-runner>
If your branch contains only documentation changes, you can use
-[special branch names](#branch-naming) to avoid long running pipelines.
+[special branch names](#branch-naming) to avoid long-running pipelines.
For [docs-only changes](#branch-naming), the review app is run automatically.
For all other branches, you can use the manual `review-docs-deploy-manual` job
in your merge request. You will need at least Maintainer permissions to be able
-to run it. In the mini pipeline graph, you should see an `>>` icon. Clicking on it will
-reveal the `review-docs-deploy-manual` job. Hit the play button for the job to start.
+to run it. In the mini pipeline graph, you should see a `>>` icon. Clicking it will
+reveal the `review-docs-deploy-manual` job. Click the play button to start the job.
![Manual trigger a docs build](img/manual_build_docs.png)
@@ -548,7 +498,7 @@ If you want to know the in-depth details, here's what's really happening:
The following GitLab features are used among others:
-- [Manual actions](../../ci/yaml/README.md#manual-actions)
+- [Manual actions](../../ci/yaml/README.md#whenmanual)
- [Multi project pipelines](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html)
- [Review Apps](../../ci/review_apps/index.md)
- [Artifacts](../../ci/yaml/README.md#artifacts)
@@ -561,10 +511,10 @@ Currently, the following tests are in place:
1. `docs lint`: Check that all internal (relative) links work correctly and
that all cURL examples in API docs use the full switches. It's recommended
- to [check locally](#previewing-locally) before pushing to GitLab by executing the command
+ to [check locally](#previewing-the-changes-live) before pushing to GitLab by executing the command
`bundle exec nanoc check internal_links` on your local
[`gitlab-docs`](https://gitlab.com/gitlab-com/gitlab-docs) directory.
-1. [`ee_compat_check`](../automatic_ce_ee_merge.md#avoiding-ce-gt-ee-merge-conflicts-beforehand) (runs on CE only):
+1. [`ee_compat_check`](../automatic_ce_ee_merge.md#avoiding-ce-ee-merge-conflicts-beforehand) (runs on CE only):
When you submit a merge request to GitLab Community Edition (CE),
there is this additional job that runs against Enterprise Edition (EE)
and checks if your changes can apply cleanly to the EE codebase.
@@ -630,9 +580,10 @@ A file with `proselint` configuration must be placed in a
#### `markdownlint`
`markdownlint` checks that certain rules ([example](https://github.com/DavidAnson/markdownlint/blob/master/README.md#rules--aliases))
- are followed for Markdown syntax. Our [style guidelines](styleguide.md) elaborate on which choices
- must be made when selecting Markdown syntax for GitLab documentation and this tool helps
- catch deviations from those guidelines.
+ are followed for Markdown syntax.
+ Our [Documentation Style Guide](styleguide.md) and [Markdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/)
+ elaborate on which choices must be made when selecting Markdown syntax for
+ GitLab documentation. This tool helps catch deviations from those guidelines.
`markdownlint` can be used [on the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--),
either on a single Markdown file or on all Markdown files in a project. For example, to run
@@ -655,7 +606,7 @@ markdownlint **/*.md
The following sample `markdownlint` configuration modifies the available default rules to:
-- Adhere to the [style guidelines](styleguide.md).
+- Adhere to the [Documentation Style Guide](styleguide.md).
- Apply conventions found in the GitLab documentation.
- Allow the flexibility of using some inline HTML.
@@ -694,9 +645,10 @@ For [`markdownlint`](https://github.com/DavidAnson/markdownlint/), this configur
placed in a [valid location](https://github.com/igorshubovych/markdownlint-cli#configuration). For
example, `~/.markdownlintrc`.
-## Danger bot
+## Danger Bot
-GitLab uses [danger bot](https://github.com/danger/danger) for some elements in
-code review. For docs changes in merge requests, whenever a change under `/doc`
-is made, the bot leaves a comment for the author to mention `@gl-docsteam`, so
-that the docs can be properly reviewed.
+GitLab uses [Danger](https://github.com/danger/danger) for some elements in
+code review. For docs changes in merge requests, whenever a change to files under `/doc`
+is made, Danger Bot leaves a comment with further instructions about the documentation
+process. This is configured in the Dangerfile in the GitLab CE and EE repo under
+[/danger/documentation/](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/danger/documentation).
diff --git a/doc/development/documentation/site_architecture/global_nav.md b/doc/development/documentation/site_architecture/global_nav.md
index 62ca7d6c805..f2f4f5f0e1c 100644
--- a/doc/development/documentation/site_architecture/global_nav.md
+++ b/doc/development/documentation/site_architecture/global_nav.md
@@ -62,7 +62,7 @@ the consent of one of the technical writers.
The global nav is built from two files:
- [Data](#data-file)
-- [Layout](#layout-file)
+- [Layout](#layout-file-logic)
The data file feeds the layout with the links to the docs. The layout organizes
the data among the nav in containers properly [styled](#css-classes).
@@ -234,7 +234,7 @@ Examples:
```yaml
- category_title: Issues
category_url: 'user/project/issues/'
- # note that the above URL does not start with a slash and
+ # note that the above URL does not start with a slash and
# does not include index.html at the end
docs:
@@ -295,7 +295,6 @@ On the other hand, if the user is looking at `/ce/` docs,
all the links in the CE nav should link internally to `/ce/`
files, except for [`ee-only` docs](#ee-only-docs).
-
```html
<% if dir != 'ce' %>
<a href="/ee/<%= sec[:section_url] %>">...</a>
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index 956bf90a5d9..ee3a9caf9a0 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -2,11 +2,18 @@
description: "Learn how GitLab's documentation website is architectured."
---
-# Docs site architecture
+# Documentation site architecture
Learn how we build and architecture [`gitlab-docs`](https://gitlab.com/gitlab-com/gitlab-docs)
and deploy it to <https://docs.gitlab.com>.
+## Repository
+
+While the source of the documentation content is stored in GitLab's respective product
+repositories, the source that is used to build the documentation site _from that content_
+is located at <https://gitlab.com/gitlab-com/gitlab-docs>. See the README there for
+detailed information.
+
## Assets
To provide an optimized site structure, design, and a search-engine friendly
@@ -37,7 +44,7 @@ read through the [global navigation](global_nav.md) doc.
The docs site is deployed to production with GitLab Pages, and previewed in
merge requests with Review Apps.
-The deployment aspects will be soon transfered from the [original document](https://gitlab.com/gitlab-com/gitlab-docs/blob/master/README.md)
+The deployment aspects will be soon transferred from the [original document](https://gitlab.com/gitlab-com/gitlab-docs/blob/master/README.md)
to this page.
<!--
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index 607ad21d459..95b5fcd99a1 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -1,147 +1,121 @@
---
-description: Learn the how to correctly structure GitLab documentation.
+description: What to include in GitLab documentation pages.
---
-# Documentation structure
+# Documentation structure and template
-For consistency throughout the documentation, it's important to maintain the same
-structure among the docs.
+This document will help you determine how to structure a page within GitLab's
+documentation and what content to include. These standards help ensure consistency
+and completeness throughout the documentation, and they make it easier to contribute.
-Before getting started, read through the following docs:
+Before getting started, familiarize yourself with [GitLab's Documentation guidelines](index.md)
+and the section on Content in the [Style Guide](styleguide.md).
-- [Contributing to GitLab documentation](index.md#contributing-to-docs)
-- [Merge requests for GitLab documentation](index.md#merge-requests-for-gitlab-documentation)
-- [Branch naming for docs-only changes](index.md#branch-naming)
-- [Documentation directory structure](index.md#documentation-directory-structure)
-- [Documentation style guidelines](styleguide.md)
-- [Documentation workflow](workflow.md)
+## Components of a documentation page
-## Documentation blurb
+Most pages will be dedicated to a specifig GitLab feature or to a use case that involves
+one or more features, potentially in conjunction with third-party tools.
-Every document should include the following content in the following sequence:
+Every feature or use case document should include the following content in the following sequence,
+with exceptions and details noted below and in the template included on this page.
-- **Feature name**: defines an intuitive name for the feature that clearly
- states what it is and is consistent with any relevant UI text.
-- **Feature overview** and description: describe what it is, what it does, and in what context it should be used.
-- **Use cases**: describes real use case scenarios for that feature.
-- **Requirements**: describes what software and/or configuration is required to be able to
- use the feature and, if applicable, prerequisite knowledge for being able to follow/implement the tutorial.
- For example, familiarity with GitLab CI/CD, an account on a third-party service, dependencies installed, etc.
- Link each one to its most relevant resource; i.e., where the reader can go to begin to fullfil that requirement.
- (Another doc page, a third party application's site, etc.)
-- **Instructions**: clearly describes the steps to use the feature, leaving no gaps.
-- **Troubleshooting** guide (recommended but not required): if you know beforehand what issues
- one might have when setting it up, or when something is changed, or on upgrading, it's
- important to describe those too. Think of things that may go wrong and include them in the
- docs. This is important to minimize requests for support, and to avoid doc comments with
- questions that you know someone might ask. Answering them beforehand only makes your
- document better and more approachable.
+- **Title**: Top-level heading with the feature name, or a use case name, which would start with
+ a verb, like Configuring, Enabling, etc.
+- **Introduction**: A couple sentences about the subject matter and what's to be found on this page.
+- **Overview** Describe what it is, what it does, and in what context it should be used.
+- **Use cases**: describes real use case scenarios for that feature/configuration.
+- **Requirements**: describes what software, configuration, account, or knowledge is required.
+- **Instructions**: One or more sets of detailed instructions to follow.
+- **Troubleshooting** guide (recommended but not required).
-For additional details, see the subsections below, as well as the [Documentation template for new docs](#Documentation-template-for-new-docs).
+For additional details on each, see the [template for new docs](#template-for-new-docs),
+below.
-### Feature overview and use cases
+Note that you can include additional subsections, as appropriate, such as 'How it Works', 'Architecture',
+and other logicial divisions such as pre- and post-deployment steps.
-Every major feature (regardless if present in GitLab Community or Enterprise editions)
-should present, at the beginning of the document, two main sections: **overview** and
-**use cases**. Every GitLab EE-only feature should also contain these sections.
-
-**Overview**: as the name suggests, the goal here is to provide an overview of the feature.
-Describe what is it, what it does, why it is important/cool/nice-to-have,
-what problem it solves, and what you can do with this feature that you couldn't
-do before.
-
-**Use cases**: provide at least two, ideally three, use cases for every major feature.
-You should answer this question: what can you do with this feature/change? Use cases
-are examples of how this feature or change can be used in real life.
-
-Examples:
-
-- CE and EE: [Issues](../../user/project/issues/index.md#use-cases)
-- CE and EE: [Merge Requests](../../user/project/merge_requests/index.md)
-- EE-only: [Geo](https://docs.gitlab.com/ee/administration/geo/replication/index.html)
-- EE-only: [Jenkins integration](https://docs.gitlab.com/ee/integration/jenkins.html)
-
-Note that if you don't have anything to add between the doc title (`<h1>`) and
-the header `## Overview`, you can omit the header, but keep the content of the
-overview there.
-
-> **Overview** and **use cases** are required to **every** Enterprise Edition feature,
-and for every **major** feature present in Community Edition.
-
-### Discoverability
-
-Your new document will be discoverable by the user only if:
-
-- Crosslinked from the higher-level index (e.g., Issue Boards docs
- should be linked from Issues; Prometheus docs should be linked from
- Monitoring; CI/CD tutorials should be linked from CI/CD examples).
- - When referencing other GitLab products and features, link to their
- respective docs; when referencing third-party products or technologies,
- link out to their external sites, documentation, and resources.
-- The headings are clear. E.g., "App testing" is a bad heading, "Testing
- an application with GitLab CI/CD" is much better. Think of something
- someone will search for and use these keywords in the headings.
-
-## Documentation template for new docs
+## Template for new docs
To start a new document, respect the file tree and file name guidelines,
as well as the style guidelines. Use the following template:
```md
+<!--Follow the Style Guide when working on this document. https://docs.gitlab.com/ee/development/documentation/styleguide.html
+When done, remove all of this commented-out text, except a commented-out Troubleshooting section,
+which, if empty, can be left in place to encourage future use.-->
---
-description: "short document description." # Up to ~200 chars long. They will be displayed in Google Search Snippets.
+description: "Short document description." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
---
-# Feature Name **[TIER]** (1)
+# Feature Name or Use Case Name **[TIER]** (1)
+<!--If writing about a use case, drop the tier, and start with a verb, e.g. 'Configuring', 'Implementing', + the goal/scenario-->
-> [Introduced](link_to_issue_or_mr) in GitLab Tier X.Y (2).
+<!--For pages on newly introduced features, add the following line. If only some aspects of the feature have been introduced, specify what parts of the feature.-->
+> [Introduced](link_to_issue_or_mr) in GitLab (Tier) X.Y (2).
-A short description for the feature (can be the same used in the frontmatter's
-`description`).
+An introduction -- without its own additional header -- goes here.
+Offer a very short description of the feature or use case, and what to expect on this page.
+(You can reuse this content, or part of it, for the front matter's `description` at the top of this file).
## Overview
-To write the feature overview, you should consider answering the following questions:
+The feature overview should answer the following questions:
-- What is it?
+- What is this feature or use case?
- Who is it for?
- What is the context in which it is used and are there any prerequisites/requirements?
-- What can the user do with it? (Be sure to consider multiple audiences, like GitLab admin and developer-user.)
-- What are the benefits to using it over any alternatives?
+- What can the audience do with this? (Be sure to consider all applicable audiences, like GitLab admin and developer-user.)
+- What are the benefits to using this over any alternatives?
## Use cases
-Describe one to three use cases for that feature. Give real-life examples.
+Describe some use cases, typically in bulleted form. Include real-life examples for each.
+
+If the page itself is dedicated to a use case, this section can usually include more specific scenarios
+for use (e.g. variations on the main use case), but if that's not applicable, the section can be omitted.
+
+Examples of use cases on feature pages:
+- CE and EE: [Issues](../../user/project/issues/index.md#use-cases)
+- CE and EE: [Merge Requests](../../user/project/merge_requests/index.md)
+- EE-only: [Geo](https://docs.gitlab.com/ee/administration/geo/replication/index.html)
+- EE-only: [Jenkins integration](https://docs.gitlab.com/ee/integration/jenkins.html)
## Requirements
-State any requirements, if any, for using the feature and/or following along with the tutorial.
+State any requirements for using the feature and/or following along with the instructions.
-The only assumption that is redundant and doesn't need to be mentioned is having an account
-on GitLab.
+These can include both:
+- technical requirements (e.g. an account on a third party service, an amount of storage space, prior configuration of another feature)
+- prerequisite knowledge (e.g. familiarity with certain GitLab features, cloud technologies)
+
+Link each one to an appropriate place for more information.
## Instructions
-("Instructions" is not necessarily the name of the heading)
+"Instructions" is usually not the name of the heading.
+This is the part of the document where you can include one or more sets of instructions, each to accomplish a specific task.
+Headers should describe the task the reader will achieve by following the instructions within, typically starting with a verb.
+Larger instruction sets may have subsections covering specific phases of the process.
- Write a step-by-step guide, with no gaps between the steps.
- Start with an h2 (`##`), break complex steps into small steps using
-subheadings h3 > h4 > h5 > h6. _Never skip the hierarchy level, such
+subheadings h3 > h4 > h5 > h6. _Never skip a hierarchy level, such
as h2 > h4_, as it will break the TOC and may affect the breadcrumbs.
- Use short and descriptive headings (up to ~50 chars). You can use one
-single heading `## How it works` for the instructions when the feature
+single heading like `## Configuring X` for instructions when the feature
is simple and the document is short.
-- Be clear, concise, and stick to the goal of the doc: explain how to
-use that feature.
-- Use inclusive language and avoid jargons, as well as uncommon and
-fancy words. The docs should be clear and easy to understand.
-- Write in the 3rd person (use "we", "you", "us", "one", instead of "I" or "me").
-- Always provide internal and external reference links.
-- Always link the doc from its higher-level index.
<!-- ## Troubleshooting
-Add a troubleshooting guide when possible/applicable. -->
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
---
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index 8309ba9a72c..0c51d3832aa 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -1,21 +1,21 @@
---
-description: 'Writing styles, markup, formatting, and reusing regular expressions throughout the GitLab Documentation.'
+description: 'Writing styles, markup, formatting, and other standards for GitLab Documentation.'
---
-# Documentation style guidelines
+# Documentation Style Guide
The documentation style guide defines the markup structure used in
GitLab documentation. Check the
[documentation guidelines](index.md) for general development instructions.
-Check the GitLab handbook for the [writing styles guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines).
+See the GitLab handbook for the [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines).
-For help adhering to the guidelines, see [linting](index.md#linting).
+For programmatic help adhering to the guidelines, see [linting](index.md#linting).
## Files
- [Directory structure](index.md#location-and-naming-documents): place the docs
-in the correct location.
+ in the correct location.
- [Documentation files](index.md#documentation-files): name the files accordingly.
DANGER: **Attention:**
@@ -29,31 +29,54 @@ a test that will fail if it spots a new `README.md` file.
### Markdown
The [documentation website](https://docs.gitlab.com) had its markdown engine migrated from [Redcarpet to GitLab Kramdown](https://gitlab.com/gitlab-com/gitlab-docs/merge_requests/108)
-in October, 2018.
+in October 2018.
The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown)
gem will support all [GFM markup](../../user/markdown.md) in the future. For now,
use regular markdown markup, following the rules on this style guide. For a complete
-Kramdown reference, check the [GiLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/).
+Kramdown reference, check the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/).
Use Kramdown markup wisely: do not overuse its specific markup (e.g., `{:.class}`) as it will not render properly in
-[`/help`](#gitlab-help).
+[`/help`](index.md#gitlab-help).
## Content
-- Make sure that the documentation is added in the correct
- [directory](index.md#documentation-directory-structure), linked from its
- higher-level index, and linked from other related pages.
+These guidelines help toward the goal of having every user's search of documentation
+yield a useful result, and ensuring content is helpful and easy to consume.
+
+- What to include:
+ - Any and all helpful information, processes, and tips for implementing,
+ using, and troubleshooting GitLab features. [The documentation is the single source of truth](https://about.gitlab.com/handbook/documentation/#documentation-as-single-source-of-truth-ssot)
+ for this information.
+ - 'Risky' or niche problem-solving steps. There is no reason to withhold these or
+ store them elsewhere; simply include them along with the rest of the docs including all necessary
+ detail, such as specific warnings and caveats about potential ramifications.
+ - Any content types/sources, if relevant to users or admins. You can freely
+ include presentations, videos, etc.; no matter who it was originally written for,
+ if it is helpful to any of our audiences, we can include it. If an outside source
+ that's under copyright, rephrase, or summarize and link out; do not copy and paste.
+ - All applicable subsections as described on the [structure and template](structure.md) page,
+ with files organized in the [correct directory](index.md#documentation-directory-structure).
+- To ensure discoverability, link to each doc from its higher-level index page and other related pages.
+- When referencing other GitLab products and features, link to their
+ respective docs; when referencing third-party products or technologies,
+ link out to their external sites, documentation, and resources.
- Do not duplicate information.
-- Be brief and clear.
-- Unless there's a logical reason not to, structure the document in alphabetical order
-(headings, tables, and lists).
+- Structure content in alphabetical order in tables, lists, etc., unless there is
+ a logical reason not to (for example, when mirroring the UI or an ordered sequence).
+
+## Language
+
+- Use inclusive language and avoid jargon, as well as uncommon
+ words. The docs should be clear and easy to understand.
+- Write in the 3rd person (use "we", "you", "us", "one", instead of "I" or "me").
+- Be clear, concise, and stick to the goal of the doc.
- Write in US English.
- Capitalize "G" and "L" in GitLab.
- Use title case when referring to [features](https://about.gitlab.com/features/) or
-[products](https://about.gitlab.com/pricing/) (e.g., GitLab Runner, Geo,
-Issue Boards, GitLab Core, Git, Prometheus, Kubernetes, etc), and methods or methodologies
-(e.g., Continuous Integration, Continuous Deployment, Scrum, Agile, etc). Note that
-some features are also objects (e.g. "GitLab's Merge Requests support X." and "Create a new merge request for Z.").
+ [products](https://about.gitlab.com/pricing/) (e.g., GitLab Runner, Geo,
+ Issue Boards, GitLab Core, Git, Prometheus, Kubernetes, etc), and methods or methodologies
+ (e.g., Continuous Integration, Continuous Deployment, Scrum, Agile, etc). Note that
+ some features are also objects (e.g. "GitLab's Merge Requests support X." and "Create a new merge request for Z.").
## Text
@@ -72,10 +95,24 @@ some features are also objects (e.g. "GitLab's Merge Requests support X." and "C
- List item 2
```
+### Tables overlapping the ToC
+
+By default, all tables have a width of 100% on docs.gitlab.com.
+In a few cases, the table will overlap the table of contents (ToC).
+For these cases, add an entry to the document's frontmatter to
+render them displaying block. This will make sure the table
+is displayed behind the ToC, scrolling horizontally:
+
+```md
+---
+table_display_block: true
+---
+```
+
## Emphasis
- Use double asterisks (`**`) to mark a word or text in bold (`**bold**`).
-- Use undescore (`_`) for text in italics (`_italic_`).
+- Use underscore (`_`) for text in italics (`_italic_`).
- Use greater than (`>`) for blockquotes.
## Punctuation
@@ -104,9 +141,9 @@ Check specific punctuation rules for [list items](#list-items) below.
**Markup:**
-- Use dashes (`- `) for unordered lists instead of asterisks (`* `).
+- Use dashes (`-`) for unordered lists instead of asterisks (`*`).
- Use the number one (`1`) for each item in an ordered list.
-When rendered, the list items will appear with sequential numbering.
+ When rendered, the list items will appear with sequential numbering.
**Punctuation:**
@@ -187,7 +224,7 @@ For other punctuation rules, please refer to the
- Use inline link markdown markup `[Text](https://example.com)`.
It's easier to read, review, and maintain. **Do not** use `[Text][identifier]`.
- To link to internal documentation, use relative links, not full URLs. Use `../` to
- navigate tp high-level directories, and always add the file name `file.md` at the
+ navigate to high-level directories, and always add the file name `file.md` at the
end of the link with the `.md` extension, not `.html`.
Example: instead of `[text](../../merge_requests/)`, use
`[text](../../merge_requests/index.md)` or, `[text](../../ci/README.md)`, or,
@@ -199,16 +236,42 @@ For other punctuation rules, please refer to the
E.g., instead of writing something like `Read more about GitLab Issue Boards [here](LINK)`,
write `Read more about [GitLab Issue Boards](LINK)`.
+### Links to confidential issues
+
+Don't link directly to [confidential issues](../../user/project/issues/confidential_issues.md). These will fail for:
+
+- Those without sufficient permissions.
+- Automated link checkers.
+
+Instead:
+
+- Mention in the text that the information is contained in a confidential issue. This will reduce confusion.
+- Provide a link in back ticks (`` ` ``) so that those with access to the issue can easily navigate to it.
+
+Example:
+
+```md
+For more information, see the [confidential issue](https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html) `https://gitlab.com/gitlab-org/gitlab-ce/issues/<issue_number>`.
+```
+
+### Unlinking emails
+
+By default, all email addresses will render in an email tag on docs.gitlab.com.
+To escape the code block and unlink email addresses, use two backticks:
+
+```md
+`` example@email.com ``
+```
+
## Navigation
To indicate the steps of navigation through the UI:
-
- Use the exact word as shown in the UI, including any capital letters as-is.
- Use bold text for navigation items and the char "greater than" (`>`) as separator
-(e.g., `Navigate to your project's **Settings > CI/CD**` ).
+ (e.g., `Navigate to your project's **Settings > CI/CD**` ).
- If there are any expandable menus, make sure to mention that the user
-needs to expand the tab to find the settings you're referring to (e.g., `Navigate to your project's **Settings > CI/CD** and expand **General pipelines**`).
+ needs to expand the tab to find the settings you're referring to (e.g., `Navigate to your project's **Settings > CI/CD** and expand **General pipelines**`).
## Images
@@ -223,7 +286,7 @@ needs to expand the tab to find the settings you're referring to (e.g., `Navigat
- Compress all images with <https://tinypng.com/> or similar tool.
- Compress gifs with <https://ezgif.com/optimize> or similar tool.
- Images should be used (only when necessary) to _illustrate_ the description
-of a process, not to _replace_ it.
+ of a process, not to _replace_ it.
- Max image size: 100KB (gifs included).
- The GitLab docs do not support videos yet.
@@ -240,30 +303,46 @@ Inside the document:
- If a heading is placed right after an image, always add three dashes (`---`)
between the image and the heading.
+### Remove image shadow
+
+All images displayed on docs.gitlab.com have a box shadow by default.
+To remove the box shadow, use the image class `.image-noshadow` applied
+directly to an HTML `img` tag:
+
+```html
+<img src="path/to/image.jpg" alt="Alt text (required)" class="image-noshadow">
+```
+
## Code blocks
- Always wrap code added to a sentence in inline code blocks (``` ` ```).
-E.g., `.gitlab-ci.yml`, `git add .`, `CODEOWNERS`, `only: master`.
-File names, commands, entries, and anything that refers to code should be added to code blocks.
-To make things easier for the user, always add a full code block for things that can be
-useful to copy and paste, as they can easily do it with the button on code blocks.
+ E.g., `.gitlab-ci.yml`, `git add .`, `CODEOWNERS`, `only: master`.
+ File names, commands, entries, and anything that refers to code should be added to code blocks.
+ To make things easier for the user, always add a full code block for things that can be
+ useful to copy and paste, as they can easily do it with the button on code blocks.
- For regular code blocks, always use a highlighting class corresponding to the
-language for better readability. Examples:
+ language for better readability. Examples:
- ```md
- ```ruby
- Ruby code
- ```
+ ````md
+ ```ruby
+ Ruby code
+ ```
- ```js
- JavaScript code
- ```
+ ```js
+ JavaScript code
+ ```
- ```md
- Markdown code
- ```
- ```
+ ```md
+ Markdown code
+ ```
+ ```text
+ Code for which no specific highlighting class is available.
+ ```
+ ````
+
+- To display raw markdown instead of rendered markdown, use four backticks on their own lines around the
+ markdown to display. See [example](https://gitlab.com/gitlab-org/gitlab-ce/blob/8c1991b9bb7e3b8d606481fdea316d633cfa5eb7/doc/development/documentation/styleguide.md#L275-287).
- For a complete reference on code blocks, check the [Kramdown guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/#code-blocks).
## Alert boxes
@@ -361,12 +440,36 @@ Which renders to:
> ### This is an `h3`
>{:.no_toc}
-## Specific sections and terms
+## Terms
+
+To maintain consistency through GitLab documentation, the following guides documentation authors
+on agreed styles and usage of terms.
+
+### Describing UI elements
+
+The following are styles to follow when describing UI elements on a screen:
+
+- For elements with a visible label, use that label in bold with matching case. For example, `the **Cancel** button`.
+- For elements with a tooltip or hover label, use that label in bold with matching case. For example, `the **Add status emoji** button`.
-To mention and/or reference specific terms in GitLab, please follow the styles
-below.
+### Verbs for UI elements
-### GitLab versions and tiers
+The following are recommended verbs for specific uses.
+
+| Recommended | Used for | Alternatives |
+|:------------|:---------------------------|:---------------------------|
+| "click" | buttons, links, menu items | "hit", "press", "select" |
+| "check" | checkboxes | "enable", "click", "press" |
+| "select" | dropdowns | "pick" |
+| "expand" | expandable sections | "open" |
+
+### Other Verbs
+
+| Recommended | Used for | Alternatives |
+|:------------|:--------------------------------|:-------------------|
+| "go" | making a browser go to location | "navigate", "open" |
+
+## GitLab versions and tiers
- Every piece of documentation that comes with a new feature should declare the
GitLab version that feature got introduced. Right below the heading add a
@@ -391,7 +494,7 @@ below.
> [Introduced](<link-to-issue>) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
```
-#### Early versions of EE
+### Early versions of EE
If the feature was created before GitLab 9.2 (before [different EE tiers were introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1851)):
@@ -404,7 +507,7 @@ For example:
> [Introduced](<link-to-issue>) in GitLab Enterprise Edition 9.0. Available in [GitLab Premium](https://about.gitlab.com/pricing/).
```
-### Product badges
+## Product badges
When a feature is available in EE-only tiers, add the corresponding tier according to the
feature availability:
@@ -425,18 +528,26 @@ keyword "only":
The tier should be ideally added to headers, so that the full badge will be displayed.
However, it can be also mentioned from paragraphs, list items, and table cells. For these cases,
the tier mention will be represented by an orange question mark that will show the tiers on hover.
-E.g., `**[STARTER]**` renders **[STARTER]**, `**[STARTER ONLY]**` renders **[STARTER ONLY]**.
+
+For example:
+
+- `**[STARTER]**` renders as **[STARTER]**
+- `**[STARTER ONLY]**` renders as **[STARTER ONLY]**
The absence of tiers' mentions mean that the feature is available in GitLab Core,
GitLab.com Free, and all higher tiers.
-#### How it works
+### How it works
Introduced by [!244](https://gitlab.com/gitlab-com/gitlab-docs/merge_requests/244),
the special markup `**[STARTER]**` will generate a `span` element to trigger the
badges and tooltips (`<span class="badge-trigger starter">`). When the keyword
"only" is added, the corresponding GitLab.com badge will not be displayed.
+## Specific sections
+
+Certain styles should be applied to specific sections. Styles for specific sections are outlined below.
+
### GitLab Restart
There are many cases that a restart/reconfigure of GitLab is required. To
@@ -513,13 +624,63 @@ the style below as a guide:
In this case:
-- Before each step list the installation method is declared in bold
+- Before each step list the installation method is declared in bold.
- Three dashes (`---`) are used to create a horizontal line and separate the
- two methods
+ two methods.
- The code blocks are indented one or more spaces under the list item to render
- correctly
-- Different highlighting languages are used for each config in the code block
-- The [references](#references) guide is used for reconfigure/restart
+ correctly.
+- Different highlighting languages are used for each config in the code block.
+- The [GitLab Restart](#gitlab-restart) section is used to explain a required restart/reconfigure of GitLab.
+
+## API
+
+Here is a list of must-have items. Use them in the exact order that appears
+on this document. Further explanation is given below.
+
+- Every method must have the REST API request. For example:
+
+ ```
+ GET /projects/:id/repository/branches
+ ```
+
+- Every method must have a detailed
+ [description of the parameters](#method-description).
+- Every method must have a cURL example.
+- Every method must have a response body (in JSON format).
+
+### API topic template
+
+The following can be used as a template to get started:
+
+````md
+## Descriptive title
+
+One or two sentence description of what endpoint does.
+
+```text
+METHOD /endpoint
+```
+
+| Attribute | Type | Required | Description |
+|:------------|:---------|:---------|:----------------------|
+| `attribute` | datatype | yes/no | Detailed description. |
+| `attribute` | datatype | yes/no | Detailed description. |
+
+Example request:
+
+```sh
+curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/endpoint?parameters'
+```
+
+Example response:
+
+```json
+[
+ {
+ }
+]
+```
+````
### Fake tokens
@@ -530,9 +691,9 @@ low.
You can use the following fake tokens as examples.
-| **Token type** | **Token value** |
+| Token type | Token value |
|:----------------------|:-------------------------------------------------------------------|
-| Private user token | `9koXpg98eAheJpvBs5tK` |
+| Private user token | `<your_access_token>` |
| Personal access token | `n671WNGecHugsdEDPsyo` |
| Application ID | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` |
| Application secret | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` |
@@ -544,23 +705,7 @@ You can use the following fake tokens as examples.
| Health check token | `Tu7BgjR9qeZTEyRzGG2P` |
| Request profile token | `7VgpS4Ax5utVD2esNstz` |
-### API
-
-Here is a list of must-have items. Use them in the exact order that appears
-on this document. Further explanation is given below.
-
-- Every method must have the REST API request. For example:
-
- ```
- GET /projects/:id/repository/branches
- ```
-
-- Every method must have a detailed
- [description of the parameters](#method-description).
-- Every method must have a cURL example.
-- Every method must have a response body (in JSON format).
-
-#### Method description
+### Method description
Use the following table headers to describe the methods. Attributes should
always be in code blocks using backticks (``` ` ```).
@@ -576,10 +721,10 @@ Rendered example:
|:----------|:-------|:---------|:--------------------|
| `user` | string | yes | The GitLab username |
-#### cURL commands
+### cURL commands
- Use `https://gitlab.example.com/api/v4/` as an endpoint.
-- Wherever needed use this personal access token: `9koXpg98eAheJpvBs5tK`.
+- Wherever needed use this personal access token: `<your_access_token>`.
- Always put the request first. `GET` is the default so you don't have to
include it.
- Use double quotes to the URL when it includes additional parameters.
@@ -588,63 +733,63 @@ Rendered example:
| Methods | Description |
|:-------------------------------------------|:------------------------------------------------------|
-| `-H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK"` | Use this method as is, whenever authentication needed |
+| `-H "PRIVATE-TOKEN: <your_access_token>"` | Use this method as is, whenever authentication needed |
| `-X POST` | Use this method when creating new objects |
| `-X PUT` | Use this method when updating existing objects |
| `-X DELETE` | Use this method when removing existing objects |
-#### cURL Examples
+### cURL Examples
Below is a set of [cURL][] examples that you can use in the API documentation.
-##### Simple cURL command
+#### Simple cURL command
Get the details of a group:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/gitlab-org
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/gitlab-org
```
-##### cURL example with parameters passed in the URL
+#### cURL example with parameters passed in the URL
Create a new project under the authenticated user's namespace:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects?name=foo"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects?name=foo"
```
-##### Post data using cURL's --data
+#### Post data using cURL's --data
Instead of using `-X POST` and appending the parameters to the URI, you can use
cURL's `--data` option. The example below will create a new project `foo` under
the authenticated user's namespace.
```bash
-curl --data "name=foo" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects"
+curl --data "name=foo" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects"
```
-##### Post data using JSON content
+#### Post data using JSON content
> **Note:** In this example we create a new group. Watch carefully the single
and double quotes.
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' https://gitlab.example.com/api/v4/groups
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' https://gitlab.example.com/api/v4/groups
```
-##### Post data using form-data
+#### Post data using form-data
Instead of using JSON or urlencode you can use multipart/form-data which
properly handles data encoding:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "title=ssh-key" --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." https://gitlab.example.com/api/v4/users/25/keys
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "title=ssh-key" --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." https://gitlab.example.com/api/v4/users/25/keys
```
The above example is run by and administrator and will add an SSH public key
titled ssh-key to user's account which has an id of 25.
-##### Escape special characters
+#### Escape special characters
Spaces or slashes (`/`) may sometimes result to errors, thus it is recommended
to escape them when possible. In the example below we create a new issue which
@@ -652,19 +797,19 @@ contains spaces in its title. Observe how spaces are escaped using the `%20`
ASCII code.
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/42/issues?title=Hello%20Dude"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/42/issues?title=Hello%20Dude"
```
Use `%2F` for slashes (`/`).
-##### Pass arrays to API calls
+#### Pass arrays to API calls
The GitLab API sometimes accepts arrays of strings or integers. For example, to
restrict the sign-up e-mail domains of a GitLab instance to `*.example.com` and
`example.net`, you would do something like this:
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "domain_whitelist[]=*.example.com" --data "domain_whitelist[]=example.net" https://gitlab.example.com/api/v4/application/settings
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "domain_whitelist[]=*.example.com" --data "domain_whitelist[]=example.net" https://gitlab.example.com/api/v4/application/settings
```
[cURL]: http://curl.haxx.se/ "cURL website"
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index 75ce8640e87..0abfe4b82a4 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -1,185 +1,10 @@
---
-description: Learn the process of shipping documentation for GitLab.
+description: Learn the processes for contributing to GitLab's documentation.
---
-# Documentation process at GitLab
+# Documentation workflows
-At GitLab, developers contribute new or updated documentation along with their code, but product managers and technical writers also have essential roles in the process.
+Documentation workflows at GitLab differ depending on the reason for the change:
-- Product Managers (PMs): in the issue for all new and updated features,
- PMs include specific documentation requirements that the developer who is
- writing or updating the docs must meet, along with feature descriptions
- and use cases. They call out any specific areas where collaborating with
- a technical writer is recommended, and usually act as the first reviewer
- of the docs.
-- Developers: author documentation and merge it on time (up to a week after
- the feature freeze).
-- Technical Writers: review each issue to ensure PM's requirements are complete,
- help developers with any questions throughout the process, and act as the final
- reviewer of all new and updated docs content before it's merged.
-
-## Requirements
-
-Documentation must be delivered whenever:
-
-- A new feature is shipped
-- There are changes to the UI
-- A process, workflow, or previously documented feature is changed
-
-Documentation is not required when a feature is changed on the backend
-only and does not directly affect the way that any regular user or
-administrator would interact with GitLab.
-
-NOTE: **Note:**
-When refactoring documentation, it should be submitted in its own MR.
-**Do not** join new features' MRs with refactoring existing docs, as they might have
-different priorities.
-
-NOTE: **Note:**
-[Smaller MRs are better](https://gitlab.com/gitlab-com/blog-posts/issues/185#note_4401010)! Do not mix subjects, and ship the smallest MR possible.
-
-### Documentation review process
-
-The docs shipped by the developer should be reviewed by the PM (for accuracy) and a Technical Writer (for clarity and structure).
-
-#### Documentation updates that require Technical Writer review
-
-Every documentation change that meets the criteria below must be reviewed by a Technical Writer
-to ensure clarity and discoverability, and avoid redundancy, bad file locations, typos, broken links, etc.
-Within the GitLab issue or MR, ping the relevant technical writer for the subject area. If you're not sure who that is,
-ping any of them or all of them (`@gl\-docsteam`).
-
-A Technical Writer must review documentation updates that involve:
-
-- Docs introducing new features
-- Changing documentation location
-- Refactoring existing documentation
-- Creating new documentation files
-
-If you need any help to choose the correct place for a doc, discuss a documentation
-idea or outline, or request any other help, ping a Technical Writer on your issue, MR,
-or on Slack in `#docs`.
-
-#### Skip the PM's review
-
-When there's a non-significant change to the docs, you can skip the review
-of the PM. Add the same labels as you would for a regular doc change and
-assign the correct milestone. In these cases, assign a Technical Writer
-for approval/merge, or mention `@gl\-docsteam` in case you don't know
-which Tech Writer to assign for.
-
-#### Skip the entire review
-
-When the MR only contains corrections to the content (typos, grammar,
-broken links, etc), it can be merged without the PM's and Tech Writer's review.
-
-## Documentation structure
-
-Read through the [documentation structure](structure.md) docs for an overview.
-
-## Documentation workflow
-
-To follow a consistent workflow every month, documentation changes
-involve the Product Managers, the developer who shipped the feature,
-and the Technical Writing team. Each role is described below.
-
-### 1. Product Manager's role in the documentation process
-
-The Product Manager (PM) should add to the feature issue:
-
-- Feature name, overview/description, and use cases, for the [documentation blurb](structure.md#documentation-blurb)
-- The documentation requirements for the developer working on the docs
- - What new page, new subsection of an existing page, or other update to an existing page/subsection is needed.
- - Just one page/section/update or multiple (perhaps there's an end user and admin change needing docs, or we need to update a previously recommended workflow, or we want to link the new feature from various places; consider and mention all ways documentation should be affected
- - Suggested title of any page or subsection, if applicable
-- Label the issue with `Documentation`, `Deliverable`, `docs:P1`, and assign
- the correct milestone
-
-### 2. Developer's role in the documentation process
-
-As a developer, or as a community contributor, you should ship the documentation
-with the feature, as in GitLab the documentation is part of the product.
-
-The docs can either be shipped along with the MR introducing the code, or,
-alternatively, created from a follow-up issue and MR.
-
-The docs should be shipped **by the feature freeze date**. Justified
-exceptions are accepted, as long as the [following process](#documentation-shipped-late)
-and the missed-deliverable due date (the 14th of each month) are both respected.
-
-#### Documentation shipped in the feature MR
-
-The developer should add to the feature MR the documentation containing:
-
-- The [documentation blurb](structure.md#documentation-blurb): copy the
- feature name, overview/description, and use cases from the feature issue
-- Instructions: write how to use the feature, step by step, with no gaps.
-- [Crosslink for discoverability](structure.md#discoverability): link with
- internal docs and external resources (if applicable)
-- Index: link the new doc or the new heading from the higher-level index
- for [discoverability](#discoverability)
-- [Screenshots](styleguide.md#images): when necessary, add screenshots for:
- - Illustrating a step of the process
- - Indicating the location of a navigation menu
-- Label the MR with `Documentation`, `Deliverable`, `docs-P1`, and assign
- the correct milestone
-- Assign the PM for review
-- When done, mention the `@gl\-docsteam` in the MR asking for review
-- **Due date**: feature freeze date and time
-
-#### Documentation shipped in a follow-up MR
-
-If the docs aren't being shipped within the feature MR:
-
-- Create a new issue mentioning "docs" or "documentation" in the title (use the Documentation issue description template)
-- Label the issue with: `Documentation`, `Deliverable`, `docs-P1`, `<product-label>`
- (product label == CI/CD, Pages, Prometheus, etc)
-- Add the correct milestone
-- Create a new MR for shipping the docs changes and follow the same
- process [described above](#documentation-shipped-in-the-feature-mr)
-- Use the MR description template called "Documentation"
-- Add the same labels and milestone as you did for the issue
-- Assign the PM for review
-- When done, mention the `@gl\-docsteam` in the MR asking for review
-- **Due date**: feature freeze date and time
-
-#### Documentation shipped late
-
-Shipping late means that you are affecting the whole feature workflow
-as well as other teams' priorities (PMs, tech writers, release managers,
-release post reviewers), so every effort should be made to avoid this.
-
-If you did not ship the docs within the feature freeze, proceed as
-[described above](#documentation-shipped-in-a-follow-up-mr) and,
-besides the regular labels, include the labels `Pick into X.Y` and
-`missed-deliverable` in the issue and the MR, and assign them the correct
-milestone.
-
-The **due date** for **merging** `missed-deliverable` MRs is on the
-**14th** of each month.
-
-### 3. Technical Writer's role in the documentation process
-
-- **Planning**
- - Once an issue contains a Documentation label and the current milestone, a
- technical writer reviews the Product Manager's documentation requirements.
- - Once the documentation requirements are approved, the technical writer can
- work with the developer to discuss any documentation questions and plans/outlines, as needed.
-
-- **Review** - A technical writer must review the documentation for:
- - Clarity
- - Relevance (make sure the content is appropriate given the impact of the feature)
- - Location (make sure the doc is in the correct dir and has the correct name)
- - Syntax, typos, and broken links
- - Improvements to the content
- - Accordance to the [docs style guide](styleguide.md)
-
-<!-- TBA: issue and MR description templates as part of the process -->
-
-<!--
-## New features vs feature updates
-
-- TBA:
- - Describe the difference between new features and feature updates
- - Creating a new doc vs updating an existing doc
--->
+- [Documentation process for feature changes](feature-change-workflow.md) - The documentation is being created or updated as part of the development and release of a new or enhanced feature. This process involves the developer of the feature (who includes new/updated documentation files as part of the same merge request containing the feature's code) and also involves the product manager and technical writer who are listed for the feature's [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages).
+- [Documentation improvement workflow](improvement-workflow.md) - All documentation additions not associated with a feature release. Documentation is being created or updated to improve accuracy, completeness, ease of use, or any reason other than a feature change. Anyone (and everyone) can contribute a merge request for this type of change at any time.
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 790b1bf951b..41a64044c68 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -161,7 +161,7 @@ still having access the class's implementation with `super`.
There are a few gotchas with it:
-- you should always [`extend ::Gitlab::Utils::Override`] and use `override` to
+- you should always [`extend ::Gitlab::Utils::Override`](utilities.md#overridehttpsgitlabcomgitlab-orggitlab-ceblobmasterlibgitlabutilsoverriderb) and use `override` to
guard the "overrider" method to ensure that if the method gets renamed in
CE, the EE override won't be silently forgotten.
- when the "overrider" would add a line in the middle of the CE
@@ -273,8 +273,6 @@ module EE
end
```
-[`extend ::Gitlab::Utils::Override`]: utilities.md#override
-
##### Overriding CE class methods
The same applies to class methods, except we want to use
@@ -831,6 +829,29 @@ should remain working as-is when EE is running without a license.
Instead place EE specs in the `ee/spec` folder.
+### Code in `spec/factories`
+
+Use `FactoryBot.modify` to extend factories already defined in CE.
+
+Note that you cannot define new factories (even nested ones) inside the `FactoryBot.modify` block. You can do so in a
+separate `FactoryBot.define` block as shown in the example below:
+
+```ruby
+# ee/spec/factories/notes.rb
+FactoryBot.modify do
+ factory :note do
+ trait :on_epic do
+ noteable { create(:epic) }
+ project nil
+ end
+ end
+end
+
+FactoryBot.define do
+ factory :note_on_epic, parent: :note, traits: [:on_epic]
+end
+```
+
## JavaScript code in `assets/javascripts/`
To separate EE-specific JS-files we should also move the files into an `ee` folder.
@@ -839,16 +860,122 @@ For example there can be an
`app/assets/javascripts/protected_branches/protected_branches_bundle.js` and an
EE counterpart
`ee/app/assets/javascripts/protected_branches/protected_branches_bundle.js`.
+The corresponding import statement would then look like this:
+
+```javascript
+// app/assets/javascripts/protected_branches/protected_branches_bundle.js
+import bundle from '~/protected_branches/protected_branches_bundle.js';
+
+// ee/app/assets/javascripts/protected_branches/protected_branches_bundle.js
+// (only works in EE)
+import bundle from 'ee/protected_branches/protected_branches_bundle.js';
+
+// in CE: app/assets/javascripts/protected_branches/protected_branches_bundle.js
+// in EE: ee/app/assets/javascripts/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.
+
+## Vue code in `assets/javascript`
+### script tag
+
+#### Child Component only used in EE
+To seperate Vue template differences we should [async import the components](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components).
+
+Doing this allows for us to load the correct component in EE whilst 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.
+
+```html
+<script>
+export default {
+ components: {
+ EEComponent: () => import('ee_component/components/test.vue'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <ee-component />
+ </div>
+</template>
+```
+
+#### For JS code that is EE only, like props, computed properties, methods, etc, we will keep the current approach
+ - Since we [can't async load a mixin](https://github.com/vuejs/vue-loader/issues/418#issuecomment-254032223) we will use the [`ee_else_ce`](https://docs.gitlab.com/ee/development/ee_features.html#javascript-code-in-assetsjavascripts) alias we already have for webpack.
+ - This means all the EE specific props, computed properties, methods, etc that are EE only should be in a mixin in the `ee/` folder and we need to create a CE counterpart of the mixin
+
+ ##### Example:
+ ```javascript
+ import mixin from 'ee_else_ce/path/mixin';
+
+ {
+ mixins: [mixin]
+ }
+ ```
+- Computed Properties/methods and getters only used in the child import still need a counterpart in CE
+
+- For store modules, we will need a CE counterpart too.
+- You can see an MR with an example [here](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9762)
+
+#### `template` tag
+* **EE Child components**
+ - Since we are using the async loading to check which component to load, we'd still use the component's name, check [this example](#child-component-only-used-in-ee).
+
+* **EE extra HTML**
+ - For the templates that have extra HTML in EE we will use the `ifEE` mixin with the `v-if` directive.
+ - You can either use the `template` tag as a wrapper or directly in the element, if there is only one element to be rendered in EE:
+
+```html
+ <template v-if="ifEE">
+ <p>Several</p>
+ <p>non wrapper</p>
+ <p>elements</p>
+ <p>that are rendered</p>
+ <p>in EE only</p>
+ </template>
+```
+
+
+```html
+ <ul v-if="renderIfEE">
+ <li>One wrapped</li>
+ <li>element</li>
+ <li>that is rendered</li>
+ <li>in EE only</li>
+ </template>
+```
+
+### Non Vue Files
+For regular JS files, the approach is similar.
+
+1. We will keep using the [`ee_else_ce`](https://docs.gitlab.com/ee/development/ee_features.html#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, we will use an `if` statement with the `ifEE` helper
+
+##### Example:
+
+```javascript
+import { ifEE } from '~/lib/utils/common_utils'
+if (renderIfEE) {
+ $('.js-import-git-toggle-button').on('click', () => {
+ const $projectMirror = $('#project_mirror');
+
+ $projectMirror.attr('disabled', !$projectMirror.attr('disabled'));
+ });
+}
+```
+
## SCSS code in `assets/stylesheets`
To separate EE-specific styles in SCSS files, if a component you're adding styles for
is limited to only EE, it is better to have a separate SCSS file in appropriate directory
within `app/assets/stylesheets`.
-See [backporting changes](#backporting-changes) for instructions on how to merge changes safely.
+See [backporting changes](#backporting-changes-from-EE-to-CE) for instructions on how to merge changes safely.
In some cases, this is not entirely possible or creating dedicated SCSS file is an overkill,
e.g. a text style of some component is different for EE. In such cases,
diff --git a/doc/development/emails.md b/doc/development/emails.md
index 35ada35babe..8baf343b133 100644
--- a/doc/development/emails.md
+++ b/doc/development/emails.md
@@ -76,14 +76,32 @@ See the [Rails guides] for more info.
## Email namespace
-If you need to implement a new feature which requires a new email handler, follow these rules:
+As of GitLab 11.7, we support a new format for email handler addresses. This was done to
+support catch-all mailboxes.
- - You must choose a namespace. The namespace cannot contain `/` or `+`, and cannot match `\h{16}`.
- - If your feature is related to a project, you will append the namespace **after** the project path, separated by a `+`
- - If you have different actions in the namespace, you add the actions **after** the namespace separated by a `+`. The action name cannot contain `/` or `+`, , and cannot match `\h{16}`.
- - You will register your handlers in `lib/gitlab/email/handler.rb`
+If you need to implement a feature which requires a new email handler, follow these rules
+for the format of the email key:
-Therefore, these are the only valid formats for an email handler:
+- Actions are always at the end, separated by `-`. For example `-issue` or `-merge-request`
+- If your feature is related to a project, the key begins with the project identifiers (project path slug
+ and project id), separated by `-`. For example, `gitlab-org-gitlab-ce-20`
+- Additional information, such as an author's token, can be added between the project identifiers and
+ the action, separated by `-`. For example, `gitlab-org-gitlab-ce-20-Author_Token12345678-issue`
+- You register your handlers in `lib/gitlab/email/handler.rb`
+
+Examples of valid email keys:
+
+ - `gitlab-org-gitlab-ce-20-Author_Token12345678-issue` (create a new issue)
+ - `gitlab-org-gitlab-ce-20-Author_Token12345678-merge-request` (create a new merge request)
+ - `1234567890abcdef1234567890abcdef-unsubscribe` (unsubscribe from a conversation)
+ - `1234567890abcdef1234567890abcdef` (reply to a conversation)
+
+Please note that the action `-issue-` is used in GitLab Premium as the handler for the Service Desk feature.
+
+### Legacy format
+
+Although we continue to support the older legacy format, no new features should use a legacy format.
+These are the only valid legacy formats for an email handler:
- `path/to/project+namespace`
- `path/to/project+namespace+action`
diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md
index 366b220cbb2..df32242a522 100644
--- a/doc/development/fe_guide/accessibility.md
+++ b/doc/development/fe_guide/accessibility.md
@@ -8,6 +8,5 @@ are useful for testing for potential accessibility problems in GitLab.
Accessibility best-practices and more in-depth information is available on
[the Audit Rules page][audit-rules] for the Chrome Accessibility Developer Tools.
-
[chrome-accessibility-developer-tools]: https://github.com/GoogleChrome/accessibility-developer-tools
[audit-rules]: https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules
diff --git a/doc/development/fe_guide/architecture.md b/doc/development/fe_guide/architecture.md
index aebb22caa15..c67389b169e 100644
--- a/doc/development/fe_guide/architecture.md
+++ b/doc/development/fe_guide/architecture.md
@@ -11,12 +11,9 @@ Architectural decisions should be accessible to everyone, so please document
them in the relevant Merge Request discussion or by updating our documentation
when appropriate.
-You can find the Frontend Architecture experts on the [team page][team-page].
+You can find the Frontend Architecture experts on the [team page](https://about.gitlab.com/team).
## Examples
You can find documentation about the desired architecture for a new feature
-built with Vue.js [here][vue-section].
-
-[team-page]: https://about.gitlab.com/team
-[vue-section]: vue.md#frontend.html#how-to-build-a-new-feature-with-vue-js
+built with Vue.js [here](vue.md).
diff --git a/doc/development/fe_guide/components.md b/doc/development/fe_guide/components.md
index 0e9126ee667..52462a4bec9 100644
--- a/doc/development/fe_guide/components.md
+++ b/doc/development/fe_guide/components.md
@@ -1,18 +1,19 @@
# Components
## Contents
-* [Dropdowns](#dropdowns)
-* [Modals](#modals)
+
+- [Dropdowns](#dropdowns)
+- [Modals](#modals)
## Dropdowns
See also the [corresponding UX guide](https://design.gitlab.com/#/components/dropdowns).
### How to style a bootstrap dropdown
+
1. Use the HTML structure provided by the [docs][bootstrap-dropdowns]
1. Add a specific class to the top level `.dropdown` element
-
```Haml
.dropdown.my-dropdown
%button{ type: 'button', data: { toggle: 'dropdown' }, 'aria-haspopup': true, 'aria-expanded': false }
diff --git a/doc/development/fe_guide/design_patterns.md b/doc/development/fe_guide/design_patterns.md
index e05887a19af..0342d16a87c 100644
--- a/doc/development/fe_guide/design_patterns.md
+++ b/doc/development/fe_guide/design_patterns.md
@@ -74,5 +74,4 @@ new Foo({ container: '.my-element' });
```
You can find an example of the above in this [class][container-class-example];
-
[container-class-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/mini_pipeline_graph_dropdown.js
diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md
index 905668eef58..f3fdaa3b883 100644
--- a/doc/development/fe_guide/development_process.md
+++ b/doc/development/fe_guide/development_process.md
@@ -61,17 +61,19 @@ Please use your best judgement when to use it and please contribute new points t
---
### Share your work early
+
1. Before writing code, ensure your vision of the architecture is aligned with
-GitLab's architecture.
+ GitLab's architecture.
1. Add a diagram to the issue and ask a frontend architect in the slack channel `#fe_architectural` about it.
![Diagram of Issue Boards Architecture](img/boards_diagram.png)
1. Don't take more than one week between starting work on a feature and
-sharing a Merge Request with a reviewer or a maintainer.
+ sharing a Merge Request with a reviewer or a maintainer.
### Vue features
+
1. Follow the steps in [Vue.js Best Practices](vue.md)
1. Follow the style guide.
1. Only a handful of people are allowed to merge Vue related features.
-Reach out to one of Vue experts early in this process.
+ Reach out to one of Vue experts early in this process.
diff --git a/doc/development/fe_guide/droplab/droplab.md b/doc/development/fe_guide/droplab/droplab.md
index ce96a9fc8ae..2f8c79abde1 100644
--- a/doc/development/fe_guide/droplab/droplab.md
+++ b/doc/development/fe_guide/droplab/droplab.md
@@ -90,7 +90,6 @@ const list = document.getElementById('list');
droplab.addHook(trigger, list);
```
-
### Dynamic data
Adding `data-dynamic` to your dropdown element will enable dynamic list rendering.
@@ -177,28 +176,28 @@ droplab.init().addData('trigger', [{
DropLab adds some CSS classes to help lower the barrier to integration.
-For example,
+For example:
-* The `droplab-item-selected` css class is added to items that have been selected
-either by a mouse click or by enter key selection.
-* The `droplab-item-active` css class is added to items that have been selected
-using arrow key navigation.
-* You can add the `droplab-item-ignore` css class to any item that you do not want to be selectable. For example,
-an `<li class="divider"></li>` list divider element that should not be interactive.
+- The `droplab-item-selected` css class is added to items that have been selected
+ either by a mouse click or by enter key selection.
+- The `droplab-item-active` css class is added to items that have been selected
+ using arrow key navigation.
+- You can add the `droplab-item-ignore` css class to any item that you do not want to be selectable. For example,
+ an `<li class="divider"></li>` list divider element that should not be interactive.
## Internal events
DropLab uses some custom events to help lower the barrier to integration.
-For example,
+For example:
-* The `click.dl` event is fired when an `li` list item has been clicked. It is also
-fired when a list item has been selected with the keyboard. It is also fired when a
-`HookButton` button is clicked (a registered `button` tag or `a` tag trigger).
-* The `input.dl` event is fired when a `HookInput` (a registered `input` tag trigger) triggers an `input` event.
-* The `mousedown.dl` event is fired when a `HookInput` triggers a `mousedown` event.
-* The `keyup.dl` event is fired when a `HookInput` triggers a `keyup` event.
-* The `keydown.dl` event is fired when a `HookInput` triggers a `keydown` event.
+- The `click.dl` event is fired when an `li` list item has been clicked. It is also
+ fired when a list item has been selected with the keyboard. It is also fired when a
+ `HookButton` button is clicked (a registered `button` tag or `a` tag trigger).
+- The `input.dl` event is fired when a `HookInput` (a registered `input` tag trigger) triggers an `input` event.
+- The `mousedown.dl` event is fired when a `HookInput` triggers a `mousedown` event.
+- The `keyup.dl` event is fired when a `HookInput` triggers a `keyup` event.
+- The `keydown.dl` event is fired when a `HookInput` triggers a `keydown` event.
These custom events add a `detail` object to the vanilla `Event` object that provides some potentially useful data.
@@ -233,9 +232,9 @@ droplab.init(trigger, list, [droplabAjax], {
### Documentation
-* [Ajax plugin](plugins/ajax.md)
-* [Filter plugin](plugins/filter.md)
-* [InputSetter plugin](plugins/input_setter.md)
+- [Ajax plugin](plugins/ajax.md)
+- [Filter plugin](plugins/filter.md)
+- [InputSetter plugin](plugins/input_setter.md)
### Development
diff --git a/doc/development/fe_guide/droplab/plugins/ajax.md b/doc/development/fe_guide/droplab/plugins/ajax.md
index 9c7e56fa448..b6a883ce6c4 100644
--- a/doc/development/fe_guide/droplab/plugins/ajax.md
+++ b/doc/development/fe_guide/droplab/plugins/ajax.md
@@ -8,10 +8,10 @@ Add the `Ajax` object to the plugins array of a `DropLab.prototype.init` or `Dro
`Ajax` requires 2 config values, the `endpoint` and `method`.
-* `endpoint` should be a URL to the request endpoint.
-* `method` should be `setData` or `addData`.
-* `setData` completely replaces the dropdown with the response data.
-* `addData` appends the response data to the current dropdown list.
+- `endpoint` should be a URL to the request endpoint.
+- `method` should be `setData` or `addData`.
+- `setData` completely replaces the dropdown with the response data.
+- `addData` appends the response data to the current dropdown list.
```html
<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
diff --git a/doc/development/fe_guide/droplab/plugins/filter.md b/doc/development/fe_guide/droplab/plugins/filter.md
index 0853ea4d320..1f188c64fe4 100644
--- a/doc/development/fe_guide/droplab/plugins/filter.md
+++ b/doc/development/fe_guide/droplab/plugins/filter.md
@@ -7,9 +7,9 @@ to the dropdown using a simple fuzzy string search of an input value.
Add the `Filter` object to the plugins array of a `DropLab.prototype.init` or `DropLab.prototype.addHook` call.
-* `Filter` requires a config value for `template`.
-* `template` should be the key of the objects within your data array that you want to compare
-to the user input string, for filtering.
+- `Filter` requires a config value for `template`.
+- `template` should be the key of the objects within your data array that you want to compare
+ to the user input string, for filtering.
```html
<input href="#" id="trigger" data-dropdown-trigger="#list">
diff --git a/doc/development/fe_guide/droplab/plugins/input_setter.md b/doc/development/fe_guide/droplab/plugins/input_setter.md
index 94f3c8254a8..e4050213869 100644
--- a/doc/development/fe_guide/droplab/plugins/input_setter.md
+++ b/doc/development/fe_guide/droplab/plugins/input_setter.md
@@ -6,14 +6,13 @@
Add the `InputSetter` object to the plugins array of a `DropLab.prototype.init` or `DropLab.prototype.addHook` call.
-* `InputSetter` requires a config value for `input` and `valueAttribute`.
-* `input` should be the DOM element that you want to manipulate.
-* `valueAttribute` should be a string that is the name of an attribute on your list items that is used to get the value
-to update the `input` element with.
+- `InputSetter` requires a config value for `input` and `valueAttribute`.
+- `input` should be the DOM element that you want to manipulate.
+- `valueAttribute` should be a string that is the name of an attribute on your list items that is used to get the value
+ to update the `input` element with.
You can also set the `InputSetter` config to an array of objects, which will allow you to update multiple elements.
-
```html
<input id="input" value="">
<div id="div" data-selected-id=""></div>
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index f55f01720fd..3290f29530a 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -9,7 +9,7 @@ read more about [Feature Flags][feature-flags].
## Apollo Client
To save duplicated clients getting created in different apps, we have a
-[default client][defualt-client] that should be used. This setups the
+[default client][default-client] that should be used. This setups the
Apollo client with the correct URL and also sets the CSRF headers.
## GraphQL Queries
@@ -27,11 +27,11 @@ the Vue application is mounted.
```javascript
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import defaultClient from '~/lib/graphql';
+import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient,
+ defaultClient: createDefaultClient(),
});
new Vue({
@@ -43,6 +43,29 @@ new Vue({
Read more about [Vue Apollo][vue-apollo] in the [Vue Apollo documentation][vue-apollo-docs].
+### Local state with `apollo-link-state`
+
+It is possible to use our Apollo setup with [apollo-link-state][apollo-link-state] by passing
+in the client state object when creating the default client.
+
+```javascript
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient({
+ defaults: {
+ testing: true,
+ },
+ resolvers: {
+ ...
+ },
+ }),
+});
+```
+
### Testing
With [Vue test utils][vue-test-utils] it is easy to quickly test components that
@@ -81,3 +104,4 @@ Read more about the [Apollo] client in the [Apollo documentation][apollo-client-
[default-client]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/lib/graphql.js
[apollo-client-docs]: https://www.apollographql.com/docs/tutorial/client.html
[vue-test-utils]: https://vue-test-utils.vuejs.org/
+[apollo-link-state]: https://www.apollographql.com/docs/link/links/state.html
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index cca3ad6fae6..86b8972a69e 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -1,7 +1,7 @@
# Frontend Development Guidelines
> **Notice:**
-We are currently in the process of re-writing our development guide to make it easier to find information. The new guide is still WIP but viewable in [development/new_fe_guide](../new_fe_guide/index.md)
+> We are currently in the process of re-writing our development guide to make it easier to find information. The new guide is still WIP but viewable in [development/new_fe_guide](../new_fe_guide/index.md)
This document describes various guidelines to ensure consistency and quality
across GitLab's frontend team.
@@ -21,8 +21,8 @@ We also use [Axios][axios] to handle all of our network requests.
We also utilize [webpack][webpack] to handle the bundling, minification, and
compression of our assets.
-Working with our frontend assets requires Node (v6.0 or greater) and Yarn
-(v1.2 or greater). You can find information on how to install these on our
+Working with our frontend assets requires Node (v8.10.0 or greater) and Yarn
+(v1.10.0 or greater). You can find information on how to install these on our
[installation guide][install].
### Browser Support
@@ -32,32 +32,41 @@ For our currently-supported browsers, see our [requirements][requirements].
---
## [Development Process](development_process.md)
+
How we plan and execute the work on the frontend.
## [Architecture](architecture.md)
+
How we go about making fundamental design decisions in GitLab's frontend team
or make changes to our frontend development guidelines.
## [Testing](../testing_guide/frontend_testing.md)
+
How we write frontend tests, run the GitLab test suite, and debug test related
issues.
## [Design Patterns](design_patterns.md)
+
Common JavaScript design patterns in GitLab's codebase.
## [Vue.js Best Practices](vue.md)
+
Vue specific design patterns and practices.
## [Vuex](vuex.md)
+
Vuex specific design patterns and practices.
## [Axios](axios.md)
+
Axios specific practices and gotchas.
## [GraphQL](graphql.md)
+
How to use GraphQL
## [Icons and Illustrations](icons.md)
+
How we use SVG for our Icons and Illustrations.
## [Components](components.md)
@@ -70,7 +79,7 @@ How we use UI components.
### [JavaScript Style Guide](style_guide_js.md)
-We use eslint to enforce our JavaScript style guides. Our guide is based on
+We use eslint to enforce our JavaScript style guides. Our guide is based on
the excellent [Airbnb][airbnb-js-style-guide] style guide with a few small
changes.
@@ -81,23 +90,26 @@ Our SCSS conventions which are enforced through [scss-lint][scss-lint].
---
## [Performance](performance.md)
+
Best practices for monitoring and maximizing frontend performance.
---
## [Security](security.md)
+
Frontend security practices.
---
## [Accessibility](accessibility.md)
+
Our accessibility standards and resources.
## [Internationalization (i18n) and Translations](../i18n/externalization.md)
+
Frontend internationalization support is described in [this document](../i18n/).
The [externalization part of the guide](../i18n/externalization.md) explains the helpers/methods available.
-
[rails]: http://rubyonrails.org/
[haml]: http://haml.info/
[hamlit]: https://github.com/k0kubun/hamlit
@@ -116,9 +128,10 @@ The [externalization part of the guide](../i18n/externalization.md) explains the
---
## [DropLab](droplab/droplab.md)
+
Our internal `DropLab` dropdown library.
-* [DropLab](droplab/droplab.md)
-* [Ajax plugin](droplab/plugins/ajax.md)
-* [Filter plugin](droplab/plugins/filter.md)
-* [InputSetter plugin](droplab/plugins/input_setter.md)
+- [DropLab](droplab/droplab.md)
+- [Ajax plugin](droplab/plugins/ajax.md)
+- [Filter plugin](droplab/plugins/filter.md)
+- [InputSetter plugin](droplab/plugins/input_setter.md)
diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md
index ef0eed786d2..2628e95dbc1 100644
--- a/doc/development/fe_guide/performance.md
+++ b/doc/development/fe_guide/performance.md
@@ -5,6 +5,7 @@
### Realtime Components
When writing code for realtime features we have to keep a couple of things in mind:
+
1. Do not overload the server with requests.
1. It should feel realtime.
@@ -12,16 +13,16 @@ Thus, we must strike a balance between sending requests and the feeling of realt
Use the following rules when creating realtime solutions.
1. The server will tell you how much to poll by sending `Poll-Interval` in the header.
-Use that as your polling interval. This way it is [easy for system administrators to change the
-polling rate](../../administration/polling.md).
-A `Poll-Interval: -1` means you should disable polling, and this must be implemented.
+ Use that as your polling interval. This way it is [easy for system administrators to change the
+ polling rate](../../administration/polling.md).
+ 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. Use regular polling intervals, do not use backoff polling, or jitter, as the interval will be
-controlled by the server.
+ controlled by the server.
1. The backend code will most likely be using etags. You do not and should not check for status
-`304 Not Modified`. The browser will transform it for you.
+ `304 Not Modified`. The browser will transform it for you.
### Lazy Loading Images
@@ -29,8 +30,8 @@ To improve the time to first render we are using lazy loading for images. This w
the actual image source on the `data-src` attribute. After the HTML is rendered and JavaScript is loaded,
the value of `data-src` will be moved to `src` automatically if the image is in the current viewport.
-* Prepare images in HTML for lazy loading by renaming the `src` attribute to `data-src` AND adding the class `lazy`
-* If you are using the Rails `image_tag` helper, all images will be lazy-loaded by default unless `lazy: false` is provided.
+- Prepare images in HTML for lazy loading by renaming the `src` attribute to `data-src` AND adding the class `lazy`.
+- If you are using the Rails `image_tag` helper, all images will be lazy-loaded by default unless `lazy: false` is provided.
If you are asynchronously adding content which contains lazy images then you need to call the function
`gl.lazyLoader.searchLazyImages()` which will search for lazy images and load them if needed.
@@ -169,7 +170,6 @@ General tips:
- [Profiling with Chrome DevTools][google-devtools-profiling]
- [Browser Diet][browser-diet] is a community-built guide that catalogues practical tips for improving web page performance.
-
[web-page-test]: http://www.webpagetest.org/
[pagespeed-insights]: https://developers.google.com/speed/pagespeed/insights/
[google-devtools-profiling]: https://developers.google.com/web/tools/chrome-devtools/profile/?hl=en
diff --git a/doc/development/fe_guide/security.md b/doc/development/fe_guide/security.md
index 19e72c1d368..83bb449e54d 100644
--- a/doc/development/fe_guide/security.md
+++ b/doc/development/fe_guide/security.md
@@ -77,7 +77,6 @@ Inline styles should be avoided in almost all cases, they should only be used
when no alternatives can be found. This allows reusability of styles as well as
readability.
-
[observatory-cli]: https://github.com/mozilla/http-observatory-cli
[qualys-ssl]: https://www.ssllabs.com/ssltest/analyze.html
[secure_headers]: https://github.com/twitter/secureheaders
diff --git a/doc/development/fe_guide/style_guide_js.md b/doc/development/fe_guide/style_guide_js.md
index 1e0529262ad..060cd8baf7f 100644
--- a/doc/development/fe_guide/style_guide_js.md
+++ b/doc/development/fe_guide/style_guide_js.md
@@ -14,9 +14,9 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
#### ESlint
1. **Never** disable eslint rules unless you have a good reason.
-You may see a lot of legacy files with `/* eslint-disable some-rule, some-other-rule */`
-at the top, but legacy files are a special case. Any time you develop a new feature or
-refactor an existing one, you should abide by the eslint rules.
+ You may see a lot of legacy files with `/* eslint-disable some-rule, some-other-rule */`
+ at the top, but legacy files are a special case. Any time you develop a new feature or
+ refactor an existing one, you should abide by the eslint rules.
1. **Never Ever EVER** disable eslint globally for a file
@@ -53,7 +53,7 @@ refactor an existing one, you should abide by the eslint rules.
1. [class-methods-use-this][eslint-this]
1. When they are needed _always_ place ESlint directive comment blocks on the first line of a script,
-followed by any global declarations, then a blank newline prior to any imports or code.
+ followed by any global declarations, then a blank newline prior to any imports or code.
```javascript
// bad
@@ -125,8 +125,8 @@ followed by any global declarations, then a blank newline prior to any imports o
```
1. Relative paths: when importing a module in the same directory, a child
-directory, or an immediate parent directory prefer relative paths. When
-importing a module which is two or more levels up, prefer either `~/` or `ee/`.
+ directory, or an immediate parent directory prefer relative paths. When
+ importing a module which is two or more levels up, prefer either `~/` or `ee/`.
In **app/assets/javascripts/my-feature/subdir**:
@@ -163,9 +163,9 @@ importing a module which is two or more levels up, prefer either `~/` or `ee/`.
```
1. Avoid using IIFE. Although we have a lot of examples of files which wrap their
-contents in IIFEs (immediately-invoked function expressions),
-this is no longer necessary after the transition from Sprockets to webpack.
-Do not use them anymore and feel free to remove them when refactoring legacy code.
+ contents in IIFEs (immediately-invoked function expressions),
+ this is no longer necessary after the transition from Sprockets to webpack.
+ Do not use them anymore and feel free to remove them when refactoring legacy code.
1. Avoid adding to the global namespace.
```javascript
@@ -484,8 +484,8 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
```
1. Default key should be provided if the prop is not required.
-_Note:_ There are some scenarios where we need to check for the existence of the property.
-On those a default key should not be provided.
+ _Note:_ There are some scenarios where we need to check for the existence of the property.
+ On those a default key should not be provided.
```javascript
// good
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index ccfd465531a..435fdf39fb4 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -6,9 +6,9 @@ To get started with Vue, read through [their documentation][vue-docs].
What is described in the following sections can be found in these examples:
-- web ide: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/ide/stores
-- security products: https://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/app/assets/javascripts/vue_shared/security_reports
-- registry: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/registry/stores
+- web ide: <https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/ide/stores>
+- security products: <https://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/app/assets/javascripts/vue_shared/security_reports>
+- registry: <https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/registry/stores>
## Vue architecture
@@ -122,7 +122,7 @@ Check this [page](vuex.md) for more details.
## Style guide
-Please refer to the Vue section of our [style guide](style_guide_js.md#vue-js)
+Please refer to the Vue section of our [style guide](style_guide_js.md#vuejs)
for best practices while writing your Vue components and templates.
## Testing Vue Components
@@ -132,7 +132,7 @@ Each Vue component has a unique output. This output is always present in the ren
Although we can test each method of a Vue component individually, our goal must be to test the output
of the render/template function, which represents the state at all times.
-Make use of the [axios mock adapter](axios.md#mock-axios-response-on-tests) to mock data returned.
+Make use of the [axios mock adapter](axios.md#mock-axios-response-in-tests) to mock data returned.
Here's how we would test the Todo App above:
@@ -223,13 +223,13 @@ need to test the rendered output. [Vue][vue-test] guide's to unit test show us e
## Vue.js Expert Role
One should apply to be a Vue.js expert by opening an MR when the Merge Request's they create and review show:
+
- Deep understanding of Vue and Vuex reactivy
- Vue and Vuex code are structured according to both official and our guidelines
- Full understanding of testing a Vue and Vuex application
- Vuex code follows the [documented pattern](./vuex.md#actions-pattern-request-and-receive-namespaces)
- Knowledge about the existing Vue and Vuex applications and existing reusable components
-
[vue-docs]: http://vuejs.org/guide/index.html
[issue-boards]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/boards
[environments-table]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/environments
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md
index 65963b959f7..4b60ec80cb8 100644
--- a/doc/development/fe_guide/vuex.md
+++ b/doc/development/fe_guide/vuex.md
@@ -120,8 +120,8 @@ create:
1. An action `receiveSomethingError`, to handle the error callback
1. An action `fetchSomething` to make the request.
1. In case your application does more than a `GET` request you can use these as examples:
- - `PUT`: `createSomething`
- - `POST`: `updateSomething`
+ - `POST`: `createSomething`
+ - `PUT`: `updateSomething`
- `DELETE`: `deleteSomething`
The component MUST only dispatch the `fetchNamespace` action. Actions namespaced with `request` or `receive` should not be called from the component
diff --git a/doc/development/feature_flags.md b/doc/development/feature_flags.md
index b6161cd6163..3271f9a7fb3 100644
--- a/doc/development/feature_flags.md
+++ b/doc/development/feature_flags.md
@@ -26,8 +26,9 @@ the time, you should execute `/chatops run feature set my_feature_flag 50`.
## Feature flags for user applications
-GitLab does not yet support the use of feature flags in deployed user applications.
-You can follow the progress on that [in the issue on our issue tracker](https://gitlab.com/gitlab-org/gitlab-ee/issues/779).
+This document only covers feature flags used in the development of GitLab
+itself. Feature flags in deployed user applications can be found at
+[Feature Flags](https://docs.gitlab.com/ee/user/project/operations/feature_flags.html)
## Developing with feature flags
@@ -124,4 +125,3 @@ Feature.enable(:feature_flag_name)
## Enabling a feature flag (in production)
Check how to [roll out changes using feature flags](rolling_out_changes_using_feature_flags.md).
-
diff --git a/doc/development/file_storage.md b/doc/development/file_storage.md
index 6e014e8c751..18e4dc2ca0c 100644
--- a/doc/development/file_storage.md
+++ b/doc/development/file_storage.md
@@ -4,21 +4,21 @@ We use the [CarrierWave] gem to handle file upload, store and retrieval.
There are many places where file uploading is used, according to contexts:
-* System
+- System
- Instance Logo (logo visible in sign in/sign up pages)
- Header Logo (one displayed in the navigation bar)
-* Group
+- Group
- Group avatars
-* User
+- User
- User avatars
- User snippet attachments
-* Project
+- Project
- Project avatars
- Issues/MR/Notes Markdown attachments
- Issues/MR/Notes Legacy Markdown attachments
- CI Artifacts (archive, metadata, trace)
- LFS Objects
-
+ - Merge request diffs
## Disk storage
@@ -37,6 +37,7 @@ they are still not 100% standardized. You can see them below:
| Issues/MR/Notes Legacy Markdown attachments | no | uploads/-/system/note/attachment/:id/:filename | `AttachmentUploader` | Note |
| CI Artifacts (CE) | yes | shared/artifacts/:disk_hash[0..1]/:disk_hash[2..3]/:disk_hash/:year_:month_:date/:job_id/:job_artifact_id (:disk_hash is SHA256 digest of project_id) | `JobArtifactUploader` | Ci::JobArtifact |
| LFS Objects (CE) | yes | shared/lfs-objects/:hex/:hex/:object_hash | `LfsObjectUploader` | LfsObject |
+| External merge request diffs | yes | shared/external-diffs/merge_request_diffs/mr-:parent_id/diff-:id | `ExternalDiffUploader` | MergeRequestDiff |
CI Artifacts and LFS Objects behave differently in CE and EE. In CE they inherit the `GitlabUploader`
while in EE they inherit the `ObjectStorage` and store files in and S3 API compatible object store.
@@ -52,7 +53,7 @@ hash of the project ID instead, if project migrates to the new approach (introdu
### Path segments
-Files are stored at multiple locations and use different path schemes.
+Files are stored at multiple locations and use different path schemes.
All the `GitlabUploader` derived classes should comply with this path segment schema:
```
@@ -61,7 +62,7 @@ All the `GitlabUploader` derived classes should comply with this path segment sc
| `<gitlab_root>/public/` | `uploads/-/system/` | `user/avatar/:id/` | `:filename` |
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `CarrierWave.root` | `GitlabUploader.base_dir` | `GitlabUploader#dynamic_segment` | `CarrierWave::Uploader#filename` |
-| | `CarrierWave::Uploader#store_dir` | |
+| | `CarrierWave::Uploader#store_dir` | |
| FileUploader
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
@@ -69,7 +70,7 @@ All the `GitlabUploader` derived classes should comply with this path segment sc
| `<gitlab_root>/shared/` | `snippets/` | `:secret/` | `:filename` |
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `CarrierWave.root` | `GitlabUploader.base_dir` | `GitlabUploader#dynamic_segment` | `CarrierWave::Uploader#filename` |
-| | `CarrierWave::Uploader#store_dir` | |
+| | `CarrierWave::Uploader#store_dir` | |
| | | `FileUploader#upload_path |
| ObjectStore::Concern (store = remote)
@@ -77,7 +78,7 @@ All the `GitlabUploader` derived classes should comply with this path segment sc
| `<bucket_name>` | <ignored> | `user/avatar/:id/` | `:filename` |
| ----------------------- + ------------------------- + ----------------------------------- + -------------------------------- |
| `#fog_dir` | `GitlabUploader.base_dir` | `GitlabUploader#dynamic_segment` | `CarrierWave::Uploader#filename` |
-| | | `ObjectStorage::Concern#store_dir` | |
+| | | `ObjectStorage::Concern#store_dir` | |
| | | `ObjectStorage::Concern#upload_path |
```
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index 32beafad307..b1785e6f803 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -5,8 +5,9 @@ Workhorse and GitLab-Shell.
## Developing new Git features
-Starting with GitLab 10.8, all new Git features should be developed in
-Gitaly.
+To read or write Git data, a request has to be made to Gitaly. This means that
+if you're developing a new feature where you need data that's not yet available
+in `lib/gitlab/git` changes have to be made to Gitaly.
> This is a new process that is not clearly defined yet. If you want
to contribute a Git feature and you're getting stuck, reach out to the
@@ -56,6 +57,44 @@ If your test-suite is failing with Gitaly issues, as a first step, try running:
rm -rf tmp/tests/gitaly
```
+## Legacy Rugged code
+
+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-ce/issues/57317) for more
+details.
+
+Until GitLab has eliminated most of these inefficiencies or the use of
+NFS is discontinued for Git data, Rugged implementations of some of the
+most commonly-used RPCs can be enabled via feature flags:
+
+* `rugged_find_commit`
+* `rugged_get_tree_entries`
+* `rugged_tree_entry`
+* `rugged_commit_is_ancestor`
+
+A convenience Rake task can be used to enable or disable these flags
+all together. To enable:
+
+```sh
+bundle exec rake gitlab:features:enable_rugged
+```
+
+To disable:
+
+```sh
+bundle exec rake gitlab:features:disable_rugged
+```
+
+Most of this code exists in the `lib/gitlab/git/rugged_impl` directory.
+
+NOTE: **Note:** You should NOT need to add or modify code related to
+Rugged unless explicitly discussed with the [Gitaly
+Team](https://gitlab.com/groups/gl-gitaly/group_members). This code will
+NOT work on GitLab.com or other GitLab instances that do not use NFS.
+
## `TooManyInvocationsError` errors
During development and testing, you may experience `Gitlab::GitalyClient::TooManyInvocationsError` failures.
@@ -128,7 +167,26 @@ to manually run `make` again.
Note that CI tests will not use your locally modified version of
Gitaly. To use a custom Gitaly version in CI you need to update
GITALY_SERVER_VERSION. You can use the format `=revision` to use a
-non-tagged commit from https://gitlab.com/gitlab-org/gitaly in CI.
+non-tagged commit from <https://gitlab.com/gitlab-org/gitaly> in CI.
+
+To use a different Gitaly repository, e.g., if your changes are present
+on a fork, you can specify a `GITALY_REPO_URL` environment variable when
+running tests:
+
+```shell
+GITALY_REPO_URL=https://gitlab.com/nick.thomas/gitaly bundle exec rspec spec/lib/gitlab/git/repository_spec.rb
+```
+
+If your fork of Gitaly is private, you can generate a [Deploy Token](../user/project/deploy_tokens/index.md)
+and specify it in the URL:
+
+```shell
+GITALY_REPO_URL=https://gitlab+deploy-token-1000:token-here@gitlab.com/nick.thomas/gitaly bundle exec rspec spec/lib/gitlab/git/repository_spec.rb
+```
+
+To use a custom Gitaly repository in CI, for instance if you want your
+GitLab fork to always use your own Gitaly fork, set `GITALY_REPO_URL`
+as a [CI environment variable](../ci/variables/README.md#variables).
---
diff --git a/doc/development/github_importer.md b/doc/development/github_importer.md
index 863ac049db6..5445f36b9fa 100644
--- a/doc/development/github_importer.md
+++ b/doc/development/github_importer.md
@@ -13,20 +13,20 @@ or Rake tasks. The parallel importer on the other hand uses Sidekiq.
## Requirements
-* GitLab CE 10.2.0 or newer.
-* Sidekiq workers that process the `github_importer` and
+- GitLab CE 10.2.0 or newer.
+- Sidekiq workers that process the `github_importer` and
`github_importer_advance_stage` queues (this is enabled by default).
-* Octokit (used for interacting with the GitHub API)
+- Octokit (used for interacting with the GitHub API).
## Code structure
The importer's codebase is broken up into the following directories:
-* `lib/gitlab/github_import`: this directory contains most of the code such as
+- `lib/gitlab/github_import`: this directory contains most of the code such as
the classes used for importing resources.
-* `app/workers/gitlab/github_import`: this directory contains the Sidekiq
+- `app/workers/gitlab/github_import`: this directory contains the Sidekiq
workers.
-* `app/workers/concerns/gitlab/github_import`: this directory contains a few
+- `app/workers/concerns/gitlab/github_import`: this directory contains a few
modules reused by the various Sidekiq workers.
## Architecture overview
@@ -188,8 +188,8 @@ projects get imported the fewer GitHub API calls will be needed.
The code for this resides in:
-* `lib/gitlab/github_import/user_finder.rb`
-* `lib/gitlab/github_import/caching.rb`
+- `lib/gitlab/github_import/user_finder.rb`
+- `lib/gitlab/github_import/caching.rb`
## Mapping labels and milestones
@@ -204,6 +204,6 @@ project that is being imported.
The code for this resides in:
-* `lib/gitlab/github_import/label_finder.rb`
-* `lib/gitlab/github_import/milestone_finder.rb`
-* `lib/gitlab/github_import/caching.rb`
+- `lib/gitlab/github_import/label_finder.rb`
+- `lib/gitlab/github_import/milestone_finder.rb`
+- `lib/gitlab/github_import/caching.rb`
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
new file mode 100644
index 00000000000..cdc806a2d31
--- /dev/null
+++ b/doc/development/go_guide/index.md
@@ -0,0 +1,216 @@
+# Go standards and style guidelines
+
+This document describes various guidelines and best practices for GitLab
+projects using the [Go language](https://golang.org).
+
+## Overview
+
+GitLab is built on top of [Ruby on Rails](https://rubyonrails.org/), but we're
+also using Go for projects where it makes sense. Go is a very powerful
+language, with many advantages, and is best suited for projects with a lot of
+IO (disk/network access), HTTP requests, parallel processing, etc. Since we
+have both Ruby on Rails and Go at GitLab, we should evaluate carefully which of
+the two is best for the job.
+
+This page aims to define and organize our Go guidelines, based on our various
+experiences. Several projects were started with different standards and they
+can still have specifics. They will be described in their respective
+`README.md` or `PROCESS.md` files.
+
+## Code Review
+
+We follow the common principles of
+[Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments).
+
+Reviewers and maintainers should pay attention to:
+
+- `defer` functions: ensure the presence when needed, and after `err` check.
+- Inject dependencies as parameters.
+- Void structs when marshalling to JSON (generates `null` instead of `[]`).
+
+### Security
+
+Security is our top priority at GitLab. During code reviews, we must take care
+of possible security breaches in our code:
+
+- XSS when using text/template
+- CSRF Protection using Gorilla
+- Use a Go version without known vulnerabilities
+- Don't leak secret tokens
+- SQL injections
+
+Remember to run
+[SAST](https://docs.gitlab.com/ee/user/project/merge_requests/sast.html)
+**[ULTIMATE]** on your project (or at least the [gosec
+analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/gosec)),
+and to follow our [Security
+requirements](../code_review.md#security-requirements).
+
+Web servers can take advantages of middlewares like [Secure](https://github.com/unrolled/secure).
+
+### Finding a reviewer
+
+Many of our projects are too small to have full-time maintainers. That's why we
+have a shared pool of Go reviewers at GitLab. To find a reviewer, use the
+[Engineering Projects](https://about.gitlab.com/handbook/engineering/projects/)
+page in the handbook. "GitLab Community Edition (CE)" and "GitLab Community
+Edition (EE)" both have a "Go" section with its list of reviewers.
+
+To add yourself to this list, add the following to your profile in the
+[team.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/team.yml)
+file and ask your manager to review and merge.
+
+```yaml
+projects:
+ gitlab-ee: reviewer go
+ gitlab-ce: reviewer go
+```
+
+## Code style and format
+
+- Avoid global variables, even in packages. By doing so you will introduce side
+ effects if the package is included multiple times.
+- Use `go fmt` before committing ([Gofmt](https://golang.org/cmd/gofmt/) is a
+ tool that automatically formats Go source code).
+
+### Automatic linting
+
+All Go projects should include these GitLab CI/CD jobs:
+
+```yaml
+go lint:
+ image: golang:1.11
+ script:
+ - go get -u golang.org/x/lint/golint
+ - golint -set_exit_status
+```
+
+Once [recursive includes](https://gitlab.com/gitlab-org/gitlab-ce/issues/56836)
+become available, you will be able to share job templates like this
+[analyzer](https://gitlab.com/gitlab-org/security-products/ci-templates/raw/master/includes-dev/analyzer.yml).
+
+## 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.html#approval-guidelines). Both [License
+Management](https://docs.gitlab.com/ee/user/project/merge_requests/license_management.html)
+**[ULTIMATE]** and [Dependency
+Scanning](https://docs.gitlab.com/ee/user/project/merge_requests/dependency_scanning.html)
+**[ULTIMATE]** should be activated on all projects to ensure new dependencies
+security status and license compatibility.
+
+### Modules
+
+Since Go 1.11, 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.
+
+There was a [bug on modules
+checksums](https://github.com/golang/go/issues/29278) in Go < v1.11.4, so make
+sure to use at least this version to avoid `checksum mismatch` errors.
+
+### ORM
+
+We don't use object-relational mapping libraries (ORMs) at GitLab (except
+[ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html) in
+Ruby on Rails). Projects can be structured with services to avoid them.
+[PQ](https://github.com/lib/pq) should be enough to interact with PostgreSQL
+databases.
+
+### Migrations
+
+In the rare event of managing a hosted database, it's necessary to use a
+migration system like ActiveRecord is providing. A simple library like
+[Journey](https://github.com/db-journey/journey), designed to be used in
+`postgres` containers, can be deployed as long-running pods. New versions will
+deploy a new pod, migrating the data automatically.
+
+## Testing
+
+We should not use any specific library or framework for testing, as the
+[standard library](https://golang.org/pkg/) provides already everything to get
+started. For example, some external dependencies might be worth considering in
+case we decide to use a specific library or framework:
+
+- [Testify](https://github.com/stretchr/testify)
+- [httpexpect](https://github.com/gavv/httpexpect)
+
+Use [subtests](https://blog.golang.org/subtests) whenever possible to improve
+code readability and test output.
+
+### Benchmarks
+
+Programs handling a lot of IO or complex operations should always include
+[benchmarks](https://golang.org/pkg/testing/#hdr-Benchmarks), to ensure
+performance consistency over time.
+
+## 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,
+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.
+
+## Daemons
+
+### Logging
+
+The usage of a logging library is strongly recommended for daemons. Even though
+there is a `log` package in the standard library, we generally use
+[logrus](https://github.com/sirupsen/logrus). Its plugin ("hooks") system
+makes it a powerful logging library, with the ability to add notifiers and
+formatters at the logger level directly.
+
+### Tracing and Correlation
+
+[LabKit](https://gitlab.com/gitlab-org/labkit) is a place to keep common
+libraries for Go services. Currently it's vendored into two projects:
+Workhorse and Gitaly, and it exports two main (but related) pieces of
+functionality:
+
+- [`gitlab.com/gitlab-org/labkit/correlation`](https://gitlab.com/gitlab-org/labkit/tree/master/correlation):
+ for propagating and extracting correlation ids between services.
+- [`gitlab.com/gitlab-org/labkit/tracing`](https://gitlab.com/gitlab-org/labkit/tree/master/tracing):
+ for instrumenting Go libraries for distributed tracing.
+
+This gives us a thin abstraction over underlying implementations that is
+consistent across Workhorse, Gitaly, and, in future, other Go servers. For
+example, in the case of `gitlab.com/gitlab-org/labkit/tracing` we can switch
+from using Opentracing directly to using Zipkin or Gokit's own tracing wrapper
+without changes to the application code, while still keeping the same
+consistent configuration mechanism (i.e. the `GITLAB_TRACING` environment
+variable).
+
+### Context
+
+Since daemons are long-running applications, they should have mechanisms to
+manage cancellations, and avoid unnecessary resources consumption (which could
+lead to DDOS vulnerabilities). [Go
+Context](https://github.com/golang/go/wiki/CodeReviewComments#contexts) should
+be used in functions that can block and passed as the first parameter.
+
+## Dockerfiles
+
+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/):
+
+- They let the user build the project with the right Go version and
+ dependencies.
+- They generate a small, self-contained image, derived from `Scratch`.
+
+Generated docker images should have the program at their `Entrypoint` to create
+portable commands. That way, anyone can run the image, and without parameters
+it will display its help message (if `cli` has been used).
+
+---
+
+[Return to Development documentation](../README.md).
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index a5a34d82bec..1b9ebb50c29 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -96,8 +96,8 @@ end
### Why
-* Because it is not isolated therefore it might be broken at times.
-* Because it doesn't work whenever the method we want to stub was defined
+- Because it is not isolated therefore it might be broken at times.
+- Because it doesn't work whenever the method we want to stub was defined
in a prepended module, which is very likely the case in EE. We could see
error like this:
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index 6323275426f..223585ebb55 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -228,6 +228,16 @@ This makes use of [`Intl.DateTimeFormat`].
[`Intl.DateTimeFormat`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
+- In Ruby/HAML, we have two ways of adding format to dates and times:
+
+ 1. **Through the `l` helper**, i.e. `l(active_session.created_at, format: :short)`. We have some predefined formats for
+ [dates](https://gitlab.com/gitlab-org/gitlab-ce/blob/v11.7.0/config/locales/en.yml#L54) and [times](https://gitlab.com/gitlab-org/gitlab-ce/blob/v11.7.0/config/locales/en.yml#L261).
+ If you need to add a new format, because other parts of the code could benefit from it,
+ you'll need to add it to [en.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/locales/en.yml) file.
+ 1. **Through `strftime`**, i.e. `milestone.start_date.strftime('%b %-d')`. We use `strftime` in case none of the formats
+ defined on [en.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/locales/en.yml) matches the date/time
+ specifications we need, and if there is no need to add it as a new format because is very particular (i.e. it's only used in a single view).
+
## Best practices
### Splitting sentences
diff --git a/doc/development/i18n/index.md b/doc/development/i18n/index.md
index c44690a4c5d..5e4923341af 100644
--- a/doc/development/i18n/index.md
+++ b/doc/development/i18n/index.md
@@ -51,4 +51,4 @@ able to proofread and instructions on becoming a proofreader yourself.
Translations are typically included in the next major or minor release.
-See [Merging translations from Crowdin](merging_translations.md)
+See [Merging translations from Crowdin](merging_translations.md).
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index d172aa6da21..85284d8c714 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -4,7 +4,7 @@ Crowdin automatically syncs the `gitlab.pot` file presenting newly
added translations to the community of translators.
At the same time, it creates a merge request to merge all newly added
-& approved translations. Find the [merge reqeust created by
+& approved translations. Find the [merge request created by
`gitlab-crowdin-bot`](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&author_username=gitlab-crowdin-bot)
to see new and merged merge requests. They are created in EE and need
to be ported to CE manually.
@@ -32,8 +32,7 @@ clicking `Pause sync` on the [Crowdin integration settings
page](https://translate.gitlab.com/project/gitlab-ee/settings#integration).
When all failures are resolved, the translations need to be double
-checked once more [as discussed in this
-issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/37850).
+checked once more as discussed in [confidential issue](https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html) `https://gitlab.com/gitlab-org/gitlab-ce/issues/37850`.
## Merging translations
diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md
index ac910e80a89..dd338f6f67d 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -47,6 +47,7 @@ are very appreciative of the work done by translators and proofreaders!
- Hungarian
- Proofreaders needed.
- Indonesian
+ - Adi Ferdian - [GitLab](https://gitlab.com/adiferd), [Crowdin](https://crowdin.com/profile/adiferd)
- Ahmad Naufal Mukhtar - [GitLab](https://gitlab.com/anaufalm), [Crowdin](https://crowdin.com/profile/anaufalm)
- Italian
- Paolo Falomo - [GitLab](https://gitlab.com/paolofalomo), [Crowdin](https://crowdin.com/profile/paolo.falomo)
@@ -85,7 +86,7 @@ are very appreciative of the work done by translators and proofreaders!
- Spanish
- Pedro Garcia - [GitLab](https://gitlab.com/pedgarrod), [Crowdin](https://crowdin.com/profile/breaking_pitt)
- Turkish
- - Proofreaders needed.
+ - Ali DemirtaÅŸ - [GitLab](https://gitlab.com/alidemirtas), [Crowdin](https://crowdin.com/profile/alidemirtas)
- Ukrainian
- Volodymyr Sobotovych - [GitLab](https://gitlab.com/wheleph), [Crowdin](https://crowdin.com/profile/wheleph)
- Andrew Vityuk - [GitLab](https://gitlab.com/3_1_3_u), [Crowdin](https://crowdin.com/profile/andruwa13)
diff --git a/doc/development/img/distributed_tracing_jaeger_ui.png b/doc/development/img/distributed_tracing_jaeger_ui.png
new file mode 100644
index 00000000000..57517dacced
--- /dev/null
+++ b/doc/development/img/distributed_tracing_jaeger_ui.png
Binary files differ
diff --git a/doc/development/img/distributed_tracing_performance_bar.png b/doc/development/img/distributed_tracing_performance_bar.png
new file mode 100644
index 00000000000..c9998cedd2d
--- /dev/null
+++ b/doc/development/img/distributed_tracing_performance_bar.png
Binary files differ
diff --git a/doc/development/import_export.md b/doc/development/import_export.md
new file mode 100644
index 00000000000..f7f48b03651
--- /dev/null
+++ b/doc/development/import_export.md
@@ -0,0 +1,351 @@
+# Import/Export development documentation
+
+Troubleshooing and general development guidelines and tips for the [Import/Export feature](../user/project/settings/import_export.md).
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> This document is originally based on the [Import/Export 201 presentation available on YouTube](https://www.youtube.com/watch?v=V3i1OfExotE).
+
+## Troubleshooting commands
+
+Finds information about the status of the import and further logs using the JID:
+
+```ruby
+# Rails console
+Project.find_by_full_path('group/project').import_state.slice(:jid, :status, :last_error)
+> {"jid"=>"414dec93f941a593ea1a6894", "status"=>"finished", "last_error"=>nil}
+```
+
+```bash
+# Logs
+grep JID /var/log/gitlab/sidekiq/current
+grep "Import/Export error" /var/log/gitlab/sidekiq/current
+grep "Import/Export backtrace" /var/log/gitlab/sidekiq/current
+```
+
+## Troubleshooting performance issues
+
+Read through the current performance problems using the Import/Export below.
+
+### OOM errors
+
+Out of memory (OOM) errors are normally caused by the [Sidekiq Memory Killer](https://docs.gitlab.com/ee/administration/operations/sidekiq_memory_killer.html):
+
+```bash
+SIDEKIQ_MEMORY_KILLER_MAX_RSS = 2GB in GitLab.com
+```
+
+An import status `started`, and the following sidekiq logs will signal a memory issue:
+
+```bash
+WARN: Work still in progress <struct with JID>
+```
+
+### Timeouts
+
+Timeout errors occur due to the `StuckImportJobsWorker` marking the process as failed:
+
+```ruby
+class StuckImportJobsWorker
+ include ApplicationWorker
+ include CronjobQueue
+
+ IMPORT_JOBS_EXPIRATION = 15.hours.to_i
+
+ def perform
+ import_state_without_jid_count = mark_import_states_without_jid_as_failed!
+ import_state_with_jid_count = mark_import_states_with_jid_as_failed!
+ ...
+```
+
+```bash
+Marked stuck import jobs as failed. JIDs: xyz
+```
+
+```
+ +-----------+ +-----------------------------------+
+ |Export Job |--->| Calls ActiveRecord `as_json` and |
+ +-----------+ | `to_json` on all project models |
+ +-----------------------------------+
+
+ +-----------+ +-----------------------------------+
+ |Import Job |--->| Loads all JSON in memory, then |
+ +-----------+ | inserts into the DB in batches |
+ +-----------------------------------+
+```
+
+### Problems and solutions
+
+| Problem | Possible solutions |
+| -------- | -------- |
+| [Slow JSON](https://gitlab.com/gitlab-org/gitlab-ce/issues/54084) loading/dumping models from the database | [split the worker](https://gitlab.com/gitlab-org/gitlab-ce/issues/54085) |
+| | Batch export
+| | Optimize SQL
+| | Move away from `ActiveRecord` callbacks (difficult)
+| High memory usage (see also some [analysis](https://gitlab.com/gitlab-org/gitlab-ce/issues/35389) | DB Commit sweet spot that uses less memory |
+| | [Netflix Fast JSON API](https://github.com/Netflix/fast_jsonapi) may help |
+| | Batch reading/writing to disk and any SQL
+
+### Temporary solutions
+
+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/))
+
+## Security
+
+The Import/Export feature is constantly updated (adding new things to export), however
+the code hasn't been refactored in a long time. We should perform a [code audit](https://gitlab.com/gitlab-org/gitlab-ce/issues/42135)
+to make sure its dynamic nature does not increase the number of security concerns.
+
+### Security in the code
+
+Some of these classes provide a layer of security to the Import/Export.
+
+The `AttributeCleaner` removes any prohibited keys:
+
+```ruby
+# AttributeCleaner
+# Removes all `_ids` and other prohibited keys
+ class AttributeCleaner
+ ALLOWED_REFERENCES = RelationFactory::PROJECT_REFERENCES + RelationFactory::USER_REFERENCES + ['group_id']
+
+ def clean
+ @relation_hash.reject do |key, _value|
+ prohibited_key?(key) || !@relation_class.attribute_method?(key) || excluded_key?(key)
+ end.except('id')
+ end
+
+ ...
+
+```
+
+The `AttributeConfigurationSpec` checks and confirms the addition of new columns:
+
+```ruby
+# AttributeConfigurationSpec
+<<-MSG
+ It looks like #{relation_class}, which is exported using the project Import/Export, has new attributes:
+
+ Please add the attribute(s) to SAFE_MODEL_ATTRIBUTES if you consider this can be exported.
+ Otherwise, please blacklist the attribute(s) in IMPORT_EXPORT_CONFIG by adding it to its correspondent
+ model in the +excluded_attributes+ section.
+
+ SAFE_MODEL_ATTRIBUTES: #{File.expand_path(safe_attributes_file)}
+ IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file}
+MSG
+```
+
+The `ModelConfigurationSpec` checks and confirms the addition of new models:
+
+```ruby
+# ModelConfigurationSpec
+<<-MSG
+ New model(s) <#{new_models.join(',')}> have been added, related to #{parent_model_name}, which is exported by
+ the Import/Export feature.
+
+ If you think this model should be included in the export, please add it to `#{Gitlab::ImportExport.config_file}`.
+
+ Definitely add it to `#{File.expand_path(ce_models_yml)}`
+ #{"or `#{File.expand_path(ee_models_yml)}` if the model/associations are EE-specific\n" if ee_models_hash.any?}
+ to signal that you've handled this error and to prevent it from showing up in the future.
+MSG
+```
+
+The `ExportFileSpec` detects encrypted or sensitive columns:
+
+```ruby
+# ExportFileSpec
+<<-MSG
+ Found a new sensitive word <#{key_found}>, which is part of the hash #{parent.inspect}
+ If you think this information shouldn't get exported, please exclude the model or attribute in
+ IMPORT_EXPORT_CONFIG.
+
+ Otherwise, please add the exception to +safe_list+ in CURRENT_SPEC using #{sensitive_word} as the
+ key and the correspondent hash or model as the value.
+
+ Also, if the attribute is a generated unique token, please add it to RelationFactory::TOKEN_RESET_MODELS
+ if it needs to be reset (to prevent duplicate column problems while importing to the same instance).
+
+ IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file}
+ CURRENT_SPEC: #{__FILE__}
+MSG
+```
+
+## Versioning
+
+Import/Export does not use strict SemVer, since it has frequent constant changes
+during a single GitLab release. It does require an update when there is a breaking change.
+
+```ruby
+# ImportExport
+module Gitlab
+ module ImportExport
+ extend self
+
+ # For every version update, the version history in import_export.md has to be kept up to date.
+ VERSION = '0.2.4'
+```
+
+## Version history
+
+The [current version history](../user/project/settings/import_export.md) also displays the equivalent GitLab version
+and it is useful for knowing which versions won't be compatible between them.
+
+| GitLab version | Import/Export version |
+| ---------------- | --------------------- |
+| 11.1 to current | 0.2.4 |
+| 10.8 | 0.2.3 |
+| 10.4 | 0.2.2 |
+| ... | ... |
+| 8.10.3 | 0.1.3 |
+| 8.10.0 | 0.1.2 |
+| 8.9.5 | 0.1.1 |
+| 8.9.0 | 0.1.0 |
+
+### When to bump the version up
+
+We will have to bump the verision if we rename model/columns or perform any format
+modifications in the JSON structure or the file structure of the archive file.
+
+We do not need to bump the version up in any of the following cases:
+
+- Add a new column or a model
+- Remove a column or model (unless there is a DB constraint)
+- Export new things (such as a new type of upload)
+
+Every time we bump the version, the integration specs will fail and can be fixed with:
+
+```bash
+bundle exec rake gitlab:import_export:bump_version
+```
+
+### Renaming columns or models
+
+This is a relatively common occurrence that will require a version bump.
+
+There is also the _RC problem_ - GitLab.com runs an RC, prior to any customers,
+meaning that we want to bump the version up in the next version (or patch release).
+
+For example:
+
+1. Add rename to `RelationRenameService` in X.Y
+2. Remove it from `RelationRenameService` in X.Y + 1
+3. Bump Import/Export version in X.Y + 1
+
+```ruby
+module Gitlab
+ module ImportExport
+ class RelationRenameService
+ RENAMES = {
+ 'pipelines' => 'ci_pipelines' # Added in 11.6, remove in 11.7
+ }.freeze
+```
+
+## A quick dive into the code
+
+### Import/Export configuration (`import_export.yml`)
+
+The main configuration `import_export.yml` defines what models can be exported/imported.
+
+Model relationships to be included in the project import/export:
+
+```yaml
+project_tree:
+ - labels:
+ :priorities
+ - milestones:
+ - events:
+ - :push_event_payload
+ - issues:
+ - events:
+ - ...
+```
+
+Only include the following attributes for the models specified:
+
+```yaml
+included_attributes:
+ user:
+ - :id
+ - :email
+ ...
+
+```
+
+Do not include the following attributes for the models specified:
+
+```yaml
+excluded_attributes:
+ project:
+ - :name
+ - :path
+ - ...
+```
+
+Extra methods to be called by the export:
+
+```yaml
+# Methods
+methods:
+ labels:
+ - :type
+ label:
+ - :type
+```
+
+### Import
+
+The import job status moves from `none` to `finished` or `failed` into different states:
+
+_import\_status_: none -> scheduled -> started -> finished/failed
+
+While the status is `started` the `Importer` code processes each step required for the import.
+
+```ruby
+# ImportExport::Importer
+module Gitlab
+ module ImportExport
+ class Importer
+ def execute
+ if import_file && check_version! && restorers.all?(&:restore) && overwrite_project
+ project_tree.restored_project
+ else
+ raise Projects::ImportService::Error.new(@shared.errors.join(', '))
+ end
+ rescue => e
+ raise Projects::ImportService::Error.new(e.message)
+ ensure
+ remove_import_file
+ end
+
+ def restorers
+ [repo_restorer, wiki_restorer, project_tree, avatar_restorer,
+ uploads_restorer, lfs_restorer, statistics_restorer]
+ end
+```
+
+The export service, is similar to the `Importer`, restoring data instead of saving it.
+
+### Export
+
+```ruby
+# ImportExport::ExportService
+module Projects
+ module ImportExport
+ class ExportService < BaseService
+
+ def save_all!
+ if save_services
+ Gitlab::ImportExport::Saver.save(project: project, shared: @shared)
+ notify_success
+ else
+ cleanup_and_notify_error!
+ end
+ end
+
+ def save_services
+ [version_saver, avatar_saver, project_tree_saver, uploads_saver, repo_saver,
+ wiki_repo_saver, lfs_saver].all?(&:save)
+ end
+```
diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md
index a36dc6424a7..5f95cf3707c 100644
--- a/doc/development/instrumentation.md
+++ b/doc/development/instrumentation.md
@@ -11,12 +11,12 @@ Instrumenting methods is done by using the `Gitlab::Metrics::Instrumentation`
module. This module offers a few different methods that can be used to
instrument code:
-* `instrument_method`: instruments a single class method.
-* `instrument_instance_method`: instruments a single instance method.
-* `instrument_class_hierarchy`: given a Class this method will recursively
+- `instrument_method`: instruments a single class method.
+- `instrument_instance_method`: instruments a single instance method.
+- `instrument_class_hierarchy`: given a Class this method will recursively
instrument all sub-classes (both class and instance methods).
-* `instrument_methods`: instruments all public and private class methods of a Module.
-* `instrument_instance_methods`: instruments all public and private instance methods of a
+- `instrument_methods`: instruments all public and private class methods of a Module.
+- `instrument_instance_methods`: instruments all public and private instance methods of a
Module.
To remove the need for typing the full `Gitlab::Metrics::Instrumentation`
diff --git a/doc/development/kubernetes.md b/doc/development/kubernetes.md
new file mode 100644
index 00000000000..4b2d48903ac
--- /dev/null
+++ b/doc/development/kubernetes.md
@@ -0,0 +1,126 @@
+# Kubernetes integration - development guidelines
+
+This document provides various guidelines when developing for GitLab's
+[Kubernetes integration](../user/project/clusters/index.md).
+
+## Development
+
+### Architecture
+
+Some Kubernetes operations, such as creating restricted project
+namespaces are performed on the GitLab Rails application. These
+operations are performed using a [client library](#client-library).
+These operations will carry an element of risk as the operations will be
+run as the same user running the GitLab Rails application, see the
+[security](#security) section below.
+
+Some Kubernetes operations, such as installing cluster applications are
+performed on one-off pods on the Kubernetes cluster itself. These
+installation pods are currently named `install-<application_name>` and
+are created within the `gitlab-managed-apps` namespace.
+
+In terms of code organization, we generally add objects that represent
+Kubernetes resources in
+[`lib/gitlab/kubernetes`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/kubernetes).
+
+### Client library
+
+We use the [`kubeclient`](https://rubygems.org/gems/kubeclient) gem to
+perform Kubernetes API calls. As the `kubeclient` gem does not support
+different API Groups (e.g. `apis/rbac.authorization.k8s.io`) from a
+single client, we have created a wrapper class,
+[`Gitlab::Kubernetes::KubeClient`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/kubernetes/kube_client.rb)
+that will enable you to achieve this.
+
+Selected Kubernetes API groups are currently supported. Do add support
+for new API groups or methods to
+[`Gitlab::Kubernetes::KubeClient`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/kubernetes/kube_client.rb)
+if you need to use them. New API groups or API group versions can be
+added to `SUPPORTED_API_GROUPS` - internally, this will create an
+internal client for that group. New methods can be added as a delegation
+to the relevant internal client.
+
+### Performance considerations
+
+All calls to the Kubernetes API must be in a background process. Do not
+perform Kubernetes API calls within a web request as this will block
+unicorn and can easily lead to a Denial Of Service (DoS) attack in GitLab as
+the Kubernetes cluster response times are outside of our control.
+
+The easiest way to ensure your calls happen a background process is to
+delegate any such work to happen in a [sidekiq
+worker](sidekiq_style_guide.md).
+
+There are instances where you would like to make calls to Kubernetes and
+return the response and as such a background worker does not seem to be
+a good fit. For such cases you should make use of [reactive
+caching](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/models/concerns/reactive_caching.rb).
+For example:
+
+```ruby
+ def calculate_reactive_cache!
+ { pods: cluster.platform_kubernetes.kubeclient.get_pods }
+ end
+
+ def pods
+ with_reactive_cache do |data|
+ data[:pods]
+ end
+ end
+```
+
+### Testing
+
+We have some Webmock stubs in
+[`KubernetesHelpers`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/support/helpers/kubernetes_helpers.rb)
+which can help with mocking out calls to Kubernetes API in your tests.
+
+## Security
+
+### SSRF
+
+As URLs for Kubernetes clusters are user controlled it is easily
+susceptible to Server Side Request Forgery (SSRF) attacks. You should
+understand the mitigation strategies if you are adding more API calls to
+a cluster.
+
+Mitigation strategies include:
+
+1. Not allowing redirects to attacker controller resources:
+ [`Kubeclient::KubeClient`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/kubernetes/kube_client.rb#)
+ can be configured to disallow any redirects by passing in
+ `http_max_redirects: 0` as an option.
+1. Not exposing error messages: by doing so, we
+ prevent attackers from triggering errors to expose results from
+ attacker controlled requests. For example, we do not expose (or store)
+ raw error messages:
+
+ ```ruby
+ rescue Kubernetes::HttpError => e
+ # bad
+ # app.make_errored!("Kubernetes error: #{e.message}")
+
+ # good
+ app.make_errored!("Kubernetes error: #{e.error_code}")
+ ```
+
+## Debugging
+
+Logs related to the Kubernetes integration can be found in
+[kubernetes.log](../administration/logs.md#kuberneteslog). On a local
+GDK install, this will be present in `log/kubernetes.log`.
+
+Some services such as
+[`Clusters::Applications::InstallService`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/services/clusters/applications/install_service.rb#L18)
+rescues `StandardError` which can make it harder to debug issues in an
+development environment. The current workaround is to temporarily
+comment out the `rescue` in your local development source.
+
+You can also follow the installation pod logs to debug issues related to
+installation. Once the installation/upgrade is underway, wait for the
+pod to be created. Then run the following to obtain the pods logs as
+they are written:
+
+```bash
+kubectl logs <pod_name> --follow -n gitlab-managed-apps
+```
diff --git a/doc/development/logging.md b/doc/development/logging.md
index 5c1d96b9e0c..d61441813b2 100644
--- a/doc/development/logging.md
+++ b/doc/development/logging.md
@@ -32,8 +32,8 @@ These logs suffer from a number of problems:
1. They often lack timestamps or other contextual information (e.g. project ID, user)
2. They may span multiple lines, which make them hard to find via Elasticsearch.
3. They lack a common structure, which make them hard to parse by log
-forwarders, such as Logstash or Fluentd. This also makes them hard to
-search.
+ forwarders, such as Logstash or Fluentd. This also makes them hard to
+ search.
Note that currently on GitLab.com, any messages in `production.log` will
NOT get indexed by Elasticsearch due to the sheer volume and noise. They
@@ -61,12 +61,12 @@ importer. You want to log issues created, merge requests, etc. as the
importer progresses. Here's what to do:
1. Look at [the list of GitLab Logs](../administration/logs.md) to see
-if your log message might belong with one of the existing log files.
+ 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
-make it easy for people to search pertinent logs in one place. For
-example, `geo.log` contains all logs pertaining to GitLab Geo.
-To create a new file:
+ check with a maintainer if it makes sense to do so. A log file should
+ make it easy for people to search pertinent logs in one place. For
+ example, `geo.log` contains all logs pertaining to GitLab Geo.
+ To create a new file:
1. Choose a filename (e.g. `importer_json.log`).
1. Create a new subclass of `Gitlab::JsonLogger`:
@@ -130,15 +130,15 @@ To create a new file:
## Additional steps with new log files
1. Consider log retention settings. By default, Omnibus will rotate 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).
-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).
+ 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
-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).
+ 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/howto/logging.md).
+ runbooks](https://gitlab.com/gitlab-com/runbooks/blob/master/howto/logging.md).
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index ee01c89e0ed..6f1baad3a2d 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -9,8 +9,8 @@ To measure the impact of a merge request you can use
[Sherlock](profiling.md#sherlock). It's also highly recommended that you read
the following guides:
-* [Performance Guidelines](performance.md)
-* [What requires downtime?](what_requires_downtime.md)
+- [Performance Guidelines](performance.md)
+- [What requires downtime?](what_requires_downtime.md)
## Impact Analysis
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index d0a054c3290..bb40c0d32b4 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -40,7 +40,7 @@ migrations _unless_ schema changes are absolutely required to solve a problem.
## What Requires Downtime?
The document ["What Requires Downtime?"](what_requires_downtime.md) specifies
-various database operations, such as
+various database operations, such as
- [adding, dropping, and renaming columns](what_requires_downtime.md#adding-columns)
- [changing column constraints and types](what_requires_downtime.md#changing-column-constraints)
@@ -48,7 +48,6 @@ various database operations, such as
and whether they require downtime and how to work around that whenever possible.
-
## Downtime Tagging
Every migration must specify if it requires downtime or not, and if it should
@@ -59,9 +58,9 @@ the migrations that _do_ require downtime.
To tag a migration, add the following two constants to the migration class'
body:
-* `DOWNTIME`: a boolean that when set to `true` indicates the migration requires
+- `DOWNTIME`: a boolean that when set to `true` indicates the migration requires
downtime.
-* `DOWNTIME_REASON`: a String containing the reason for the migration requiring
+- `DOWNTIME_REASON`: a String containing the reason for the migration requiring
downtime. This constant **must** be set when `DOWNTIME` is set to `true`.
For example:
@@ -318,13 +317,38 @@ end
Instead of using these methods one should use the following methods to store timestamps with timezones:
-* `add_timestamps_with_timezone`
-* `timestamps_with_timezone`
+- `add_timestamps_with_timezone`
+- `timestamps_with_timezone`
This ensures all timestamps have a time zone specified. This in turn means existing timestamps won't
suddenly use a different timezone when the system's timezone changes. It also makes it very clear which
timezone was used in the first place.
+## Storing JSON in database
+
+The Rails 5 natively supports `JSONB` (binary JSON) column type.
+Example migration adding this column:
+
+```ruby
+class AddOptionsToBuildMetadata < ActiveRecord::Migration[5.0]
+ DOWNTIME = false
+
+ def change
+ add_column :ci_builds_metadata, :config_options, :jsonb
+ end
+end
+```
+
+On MySQL the `JSON` and `JSONB` is translated to `TEXT 1MB`, as `JSONB` is PostgreSQL only feature.
+
+For above reason you have to use a serializer to provide a translation layer
+in order to support PostgreSQL and MySQL seamlessly:
+
+```ruby
+class BuildMetadata
+ serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
+end
+```
## Testing
diff --git a/doc/development/new_fe_guide/development/accessibility.md b/doc/development/new_fe_guide/development/accessibility.md
index 2a3a126ca5c..8420a504ec4 100644
--- a/doc/development/new_fe_guide/development/accessibility.md
+++ b/doc/development/new_fe_guide/development/accessibility.md
@@ -2,7 +2,7 @@
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.
+WAI-ARIA, the Accessible Rich Internet Applications specification, defines a way to make Web content and Web applications more accessible to people with disabilities.
> Note: It is [recommended][using-aria] to use semantic elements as the primary method to achieve accessibility rather than adding aria attributes. Adding aria attributes should be seen as a secondary method for creating accessible elements.
@@ -15,6 +15,7 @@ Check the list of WAI-ARIA roles [here][roles]
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
diff --git a/doc/development/new_fe_guide/development/components.md b/doc/development/new_fe_guide/development/components.md
index 899efb398cd..8ae58d30c35 100644
--- a/doc/development/new_fe_guide/development/components.md
+++ b/doc/development/new_fe_guide/development/components.md
@@ -6,16 +6,16 @@ We have a lot of graphing libraries in our codebase to render graphs. In an effo
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)
+- [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://plot.ly/)
-* [Droptask](https://www.droptask.com/)
+- [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://plot.ly/)
+- [Droptask](https://www.droptask.com/)
Within GitLab, D3 has been used for the following notable features
-* [Prometheus graphs](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html)
-* Contribution calendars
+- [Prometheus graphs](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html)
+- Contribution calendars
diff --git a/doc/development/new_fe_guide/development/performance.md b/doc/development/new_fe_guide/development/performance.md
index 5ccd5357314..640a8d64176 100644
--- a/doc/development/new_fe_guide/development/performance.md
+++ b/doc/development/new_fe_guide/development/performance.md
@@ -7,10 +7,10 @@ We have a performance dashboard available in one of our [grafana instances](http
These pages can be found inside a text file in the gitlab-build-images [repository](https://gitlab.com/gitlab-org/gitlab-build-images) called [gitlab.txt](https://gitlab.com/gitlab-org/gitlab-build-images/blob/master/scripts/gitlab.txt)
Any frontend engineer can contribute to this dashboard. They can contribute by adding or removing urls of pages from this text file. Please have a [frontend monitoring expert](https://about.gitlab.com/team) review your changes before assigning to a maintainer of the `gitlab-build-images` project. The changes will go live on the next scheduled run after the changes are merged into `master`.
-There are 3 recommended high impact metrics to review on each page
+There are 3 recommended high impact metrics to review on each page:
-* [First visual change](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint)
-* [Speed Index](https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index)
-* [Visual Complete 95%](https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index)
+- [First visual change](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint)
+- [Speed Index](https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index)
+- [Visual Complete 95%](https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index)
For these metrics, lower numbers are better as it means that the website is more performant.
diff --git a/doc/development/new_fe_guide/development/testing.md b/doc/development/new_fe_guide/development/testing.md
index 0d98180add0..8441089418e 100644
--- a/doc/development/new_fe_guide/development/testing.md
+++ b/doc/development/new_fe_guide/development/testing.md
@@ -1,29 +1,27 @@
# Overview of Frontend Testing
-Tests relevant for frontend development can be found at two places:
+Tests relevant for frontend development can be found at the following places:
-- `spec/javascripts/` which are run by Karma and contain
+- `spec/javascripts/` which are run by Karma (command: `yarn karma`) and contain
- [frontend unit tests](#frontend-unit-tests)
- [frontend component tests](#frontend-component-tests)
- [frontend integration tests](#frontend-integration-tests)
-- `spec/frontend/` which are run by Jest and contain
+- `spec/frontend/` which are run by Jest (command: `yarn jest`) and contain
- [frontend unit tests](#frontend-unit-tests)
- [frontend component tests](#frontend-component-tests)
- [frontend integration tests](#frontend-integration-tests)
- `spec/features/` which are run by RSpec and contain
- [feature tests](#feature-tests)
-All tests in `spec/javascripts/` will eventually be migrated to `spec/frontend/` (see also [#53757]).
+All tests in `spec/javascripts/` will eventually be migrated to `spec/frontend/` (see also [#52483](https://gitlab.com/gitlab-org/gitlab-ce/issues/52483)).
In addition there were feature tests in `features/` run by Spinach in the past.
These have been removed from our codebase in May 2018 ([#23036](https://gitlab.com/gitlab-org/gitlab-ce/issues/23036)).
See also:
-- [old testing guide](../../testing_guide/frontend_testing.html)
-- [notes on testing Vue components](../../fe_guide/vue.html#testing-vue-components)
-
-[#53757]: https://gitlab.com/gitlab-org/gitlab-ce/issues/53757
+- [Old testing guide](../../testing_guide/frontend_testing.html).
+- [Notes on testing Vue components](../../fe_guide/vue.html#testing-vue-components).
## Frontend unit tests
@@ -246,6 +244,8 @@ Their abstraction level is comparable to how a user would interact with the UI.
In contrast to [frontend integration tests](#frontend-integration-tests), feature tests make requests against the real backend instead of using fixtures.
This also implies that database queries are executed which makes this category significantly slower.
+See also the [RSpec testing guidelines](../../testing_guide/best_practices.md#rspec).
+
### When to use feature tests
- use cases that require a backend and cannot be tested using fixtures
@@ -302,8 +302,8 @@ Check an example in [spec/javascripts/ide/stores/actions_spec.jsspec/javascripts
To make mounting a Vue component easier and more readable, we have a few helpers available in `spec/helpers/vue_mount_component_helper`.
-* `createComponentWithStore`
-* `mountComponentWithStore`
+- `createComponentWithStore`
+- `mountComponentWithStore`
Examples of usage:
@@ -339,7 +339,6 @@ afterEach(() => {
Some regressions only affect a specific browser version. We can install and test in particular browsers with either Firefox or Browserstack using the following steps:
-
### Browserstack
[Browserstack](https://www.browserstack.com/) allows you to test more than 1200 mobile devices and browsers.
@@ -350,7 +349,7 @@ You can find the credentials on 1Password, under `frontendteam@gitlab.com`.
#### macOS
-You can download any older version of Firefox from the releases FTP server, https://ftp.mozilla.org/pub/firefox/releases/
+You can download any older version of Firefox from the releases FTP server, <https://ftp.mozilla.org/pub/firefox/releases/>
1. From the website, select a version, in this case `50.0.1`.
1. Go to the mac folder.
diff --git a/doc/development/new_fe_guide/event_tracking.md b/doc/development/new_fe_guide/event_tracking.md
new file mode 100644
index 00000000000..1958f1ce528
--- /dev/null
+++ b/doc/development/new_fe_guide/event_tracking.md
@@ -0,0 +1,74 @@
+# Event Tracking
+
+We use [Snowplow](https://github.com/snowplow/snowplow) for tracking custom events.
+
+## Generic tracking function
+
+In addition to Snowplow's built-in method for tracking page views, we use a generic tracking function which enables us to selectively apply listeners to events.
+
+The generic tracking function can be imported in EE-specific JS files as follows:
+
+```javascript
+import { trackEvent } from `ee/stats`;
+```
+
+This gives the user access to the `trackEvent` method, which takes the following parameters:
+
+| parameter | type | description | required |
+| ---------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
+| `category` | string | Describes the page that you're capturing click events on. Unless infeasible, please use the Rails page attribute `document.body.dataset.page` by default. | true |
+| `eventName` | string | Describes the action the user is taking. The first word should always describe the action. For example, clicks should be `click` and activations should be `activate`. Use underscores to describe what was acted on. For example, activating a form field would be `activate_form_input`. Clicking on a dropdown is `click_dropdown`. | true |
+| `additionalData` | object | Additional data such as `label`, `property`, and `value` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/feature-instrumentation/#taxonomy). | false |
+
+Read more about instrumentation and the taxonomy in the [Product Handbook](https://about.gitlab.com/handbook/product/feature-instrumentation).
+
+### Tracking in `.js` and `.vue` files
+
+The most simple use case is to add tracking programmatically to an event of interest in Javascript.
+
+The following example demonstrates how to track a click on a button in Javascript by calling the `trackEvent` method explicitly:
+
+```javascript
+import { trackEvent } from `ee/stats`;
+
+trackEvent('dashboard:projects:index', 'click_button', {
+ label: 'create_from_template',
+ property: 'template_preview',
+ value: 'rails',
+});
+```
+
+### Tracking in HAML templates
+
+Sometimes we want to track clicks for multiple elements on a page. Creating event handlers for all elements could soon turn into a tedious task.
+
+There's a more convenient solution to this problem. When working with HAML templates, we can add `data-track-*` attributes to elements of interest. This way, all elements that have both `data-track-label` and `data-track-event` attributes assigned get marked for event tracking. All we have to do is call the `bindTrackableContainer` method on a container which allows for better scoping.
+
+Below is an example of `data-track-*` attributes assigned to a button in HAML:
+
+```ruby
+%button.btn{ data: { track_label: "create_from_template", track_property: "template_preview", track_event: "click_button", track_value: "my-template" } }
+```
+
+By calling `bindTrackableContainer('.my-container')`, click handlers get bound to all elements located in `.my-container` provided that they have the necessary `data-track-*` attributes assigned to them.
+
+```javascript
+import Stats from 'ee/stats';
+
+document.addEventListener('DOMContentLoaded', () => {
+ Stats.bindTrackableContainer('.my-container', 'category');
+});
+```
+
+The second parameter in `bindTrackableContainer` is optional. If omitted, the value of `document.body.dataset.page` will be used as category instead.
+
+Below is a list of supported `data-track-*` attributes:
+
+| attribute | description | required |
+| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
+| `data-track-label` | The `label` in `trackEvent` | true |
+| `data-track-event` | The `eventName` in `trackEvent` | true |
+| `data-track-property` | The `property` in `trackEvent`. If omitted, an empty string will be used as a default value. | false |
+| `data-track-value` | The `value` in `trackEvent`. If omitted, this will be `target.value` or empty string. For checkboxes, the default value being tracked will be the element's checked attribute if `data-track-value` is omitted. | false |
+
+Since Snowplow is an Enterprise Edition feature, it's necessary to create a CE backport when adding `data-track-*` attributes to HAML templates in most cases.
diff --git a/doc/development/new_fe_guide/index.md b/doc/development/new_fe_guide/index.md
index bfcca9cec7b..5fd5af252ef 100644
--- a/doc/development/new_fe_guide/index.md
+++ b/doc/development/new_fe_guide/index.md
@@ -27,6 +27,10 @@ Learn about all the internal JavaScript modules that make up our frontend.
Style guides to keep our code consistent.
+## [Event Tracking with Snowplow](event_tracking.md)
+
+How we use Snowplow to track custom events.
+
## [Tips](tips.md)
Tips from our frontend team to develop more efficiently and effectively.
diff --git a/doc/development/new_fe_guide/modules/index.md b/doc/development/new_fe_guide/modules/index.md
index 0a7f2dbd819..a7820442df0 100644
--- a/doc/development/new_fe_guide/modules/index.md
+++ b/doc/development/new_fe_guide/modules/index.md
@@ -1,5 +1,5 @@
# Modules
-* [DirtySubmit](dirty_submit.md)
+- [DirtySubmit](dirty_submit.md)
- Disable form submits until there are unsaved changes. \ No newline at end of file
+ Disable form submits until there are unsaved changes.
diff --git a/doc/development/new_fe_guide/style/html.md b/doc/development/new_fe_guide/style/html.md
index 2d5b7d048ab..035fcbb28df 100644
--- a/doc/development/new_fe_guide/style/html.md
+++ b/doc/development/new_fe_guide/style/html.md
@@ -3,6 +3,7 @@
## Buttons
<a name="button-type"></a><a name="1.1"></a>
+
- [1.1](#button-type) **Use button type** Button tags requires a `type` attribute according to the [W3C HTML specification][button-type-spec].
```
@@ -14,6 +15,7 @@
```
<a name="button-role"></a><a name="1.2"></a>
+
- [1.2](#button-role) **Use button role for non buttons** If an HTML element has an onClick handler but is not a button, it should have `role="button"`. This is more [accessible][button-role-accessible].
```
@@ -27,6 +29,7 @@
## Links
<a name="blank-links"></a><a name="2.1"></a>
+
- [2.1](#blank-links) **Use rel for target blank** Use `rel="noopener noreferrer"` whenever your links open in a new window i.e. `target="_blank"`. This prevents [the following][jitbit-target-blank] security vulnerability documented by JitBit
```
@@ -38,6 +41,7 @@
```
<a name="fake-links"></a><a name="2.2"></a>
+
- [2.2](#fake-links) **Do not use fake links** Use a button tag if a link only invokes JavaScript click event handlers. This is more semantic.
```
diff --git a/doc/development/new_fe_guide/style/javascript.md b/doc/development/new_fe_guide/style/javascript.md
index 922fd1e4ea4..7985b893c9e 100644
--- a/doc/development/new_fe_guide/style/javascript.md
+++ b/doc/development/new_fe_guide/style/javascript.md
@@ -10,6 +10,7 @@ You can run eslint locally by running `yarn eslint`
## Arrays
<a name="avoid-foreach"></a><a name="1.1"></a>
+
- [1.1](#avoid-foreach) **Avoid ForEach when mutating data** Use `map`, `reduce` or `filter` instead of `forEach` when mutating data. This will minimize mutations in functions ([which is aligned with Airbnb's style guide][airbnb-minimize-mutations])
```
@@ -17,7 +18,7 @@ You can run eslint locally by running `yarn eslint`
users.forEach((user, index) => {
user.id = index;
});
-
+
// good
const usersWithId = users.map((user, index) => {
return Object.assign({}, user, { id: index });
@@ -27,6 +28,7 @@ You can run eslint locally by running `yarn eslint`
## Functions
<a name="limit-params"></a><a name="2.1"></a>
+
- [2.1](#limit-params) **Limit number of parameters** If your function or method has more than 3 parameters, use an object as a parameter instead.
```
@@ -34,7 +36,7 @@ You can run eslint locally by running `yarn eslint`
function a(p1, p2, p3) {
// ...
};
-
+
// good
function a(p) {
// ...
@@ -44,6 +46,7 @@ You can run eslint locally by running `yarn eslint`
## Classes & constructors
<a name="avoid-constructor-side-effects"></a><a name="3.1"></a>
+
- [3.1](#avoid-constructor-side-effects) **Avoid side effects in constructors** Avoid making some operations in the `constructor`, such as asynchronous calls, API requests and DOM manipulations. Prefer moving them into separate functions. This will make tests easier to write and code easier to maintain.
```javascript
@@ -54,23 +57,24 @@ You can run eslint locally by running `yarn eslint`
axios.get(this.config.endpoint)
}
}
-
+
// good
class myClass {
constructor(config) {
this.config = config;
}
-
+
makeRequest() {
axios.get(this.config.endpoint)
}
}
const instance = new myClass();
instance.makeRequest();
-
+
```
<a name="avoid-classes-to-handle-dom-events"></a><a name="3.2"></a>
+
- [3.2](#avoid-classes-to-handle-dom-events) **Avoid classes to handle DOM events** If the only purpose of the class is to bind a DOM event and handle the callback, prefer using a function.
```
@@ -79,14 +83,14 @@ You can run eslint locally by running `yarn eslint`
constructor(config) {
this.config = config;
}
-
+
init() {
document.addEventListener('click', () => {});
}
}
-
+
// good
-
+
const myFunction = () => {
document.addEventListener('click', () => {
// handle callback here
@@ -95,8 +99,9 @@ You can run eslint locally by running `yarn eslint`
```
<a name="element-container"></a><a name="3.3"></a>
+
- [3.3](#element-container) **Pass element container to constructor** When your class manipulates the DOM, receive the element container as a parameter.
-This is more maintainable and performant.
+ This is more maintainable and performant.
```
// bad
@@ -105,7 +110,7 @@ This is more maintainable and performant.
document.querySelector('.b');
}
}
-
+
// good
class a {
constructor(options) {
@@ -117,12 +122,13 @@ This is more maintainable and performant.
## Type Casting & Coercion
<a name="use-parseint"></a><a name="4.1"></a>
+
- [4.1](#use-parseint) **Use ParseInt** Use `ParseInt` when converting a numeric string into a number.
```
// bad
Number('10')
-
+
// good
parseInt('10', 10);
```
@@ -130,12 +136,13 @@ This is more maintainable and performant.
## CSS Selectors
<a name="use-js-prefix"></a><a name="5.1"></a>
+
- [5.1](#use-js-prefix) **Use js prefix** If a CSS class is only being used in JavaScript as a reference to the element, prefix the class name with `js-`
```
// bad
<button class="add-user"></button>
-
+
// good
<button class="js-add-user"></button>
```
@@ -143,44 +150,51 @@ This is more maintainable and performant.
## Modules
<a name="use-absolute-paths"></a><a name="6.1"></a>
+
- [6.1](#use-absolute-paths) **Use absolute paths for nearby modules** Use absolute paths if the module you are importing is less than two levels up.
```
// bad
import GitLabStyleGuide from '~/guides/GitLabStyleGuide';
-
+
// good
import GitLabStyleGuide from '../GitLabStyleGuide';
```
<a name="use-relative-paths"></a><a name="6.2"></a>
+
- [6.2](#use-relative-paths) **Use relative paths for distant modules** If the module you are importing is two or more levels up, use a relative path instead of an absolute path.
```
// bad
import GitLabStyleGuide from '../../../guides/GitLabStyleGuide';
-
+
// good
import GitLabStyleGuide from '~/GitLabStyleGuide';
```
<a name="global-namespace"></a><a name="6.3"></a>
+
- [6.3](#global-namespace) **Do not add to global namespace**
<a name="domcontentloaded"></a><a name="6.4"></a>
+
- [6.4](#domcontentloaded) **Do not use DOMContentLoaded in non-page modules** Imported modules should act the same each time they are loaded. `DOMContentLoaded` events are only allowed on modules loaded in the `/pages/*` directory because those are loaded dynamically with webpack.
## Security
<a name="avoid-xss"></a><a name="7.1"></a>
+
- [7.1](#avoid-xss) **Avoid XSS** Do not use `innerHTML`, `append()` or `html()` to set content. It opens up too many vulnerabilities.
## ESLint
<a name="disable-eslint-file"></a><a name="8.1"></a>
+
- [8.1](#disable-eslint-file) **Disabling ESLint in new files** Do not disable ESLint when creating new files. Existing files may have existing rules disabled due to legacy compatibility reasons but they are in the process of being refactored.
<a name="disable-eslint-rule"></a><a name="8.2"></a>
+
- [8.2](#disable-eslint-rule) **Disabling ESLint rule** Do not disable specific ESLint rules. Due to technical debt, you may disable the following rules only if you are invoking/instantiating existing code modules
- [no-new][no-new]
diff --git a/doc/development/ordering_table_columns.md b/doc/development/ordering_table_columns.md
index e9c6481635b..cbfd05e731d 100644
--- a/doc/development/ordering_table_columns.md
+++ b/doc/development/ordering_table_columns.md
@@ -19,7 +19,7 @@ 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 will be 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 (ommiting variable length
+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 will require 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
@@ -30,7 +30,7 @@ ideal column order would be the following:
- `user_id` (integer, 4 bytes)
- `name` (text, variable)
-or
+or
- `name` (text, variable)
- `id` (integer, 4 bytes)
@@ -47,8 +47,7 @@ type size in descending order with variable sizes (`text`, `varchar`, arrays,
## Type Sizes
-While the PostgreSQL documentation
-(https://www.postgresql.org/docs/current/static/datatype.html) contains plenty
+While the [PostgreSQL documentation](https://www.postgresql.org/docs/current/datatype.html) contains plenty
of information we will 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.
@@ -138,7 +137,7 @@ This would produce the following chunks:
| 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
+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/performance.md b/doc/development/performance.md
index 4cc2fdc9a58..0e21d45f57c 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -23,9 +23,9 @@ The process of solving performance problems is roughly as follows:
When providing timings make sure to provide:
-* The 95th percentile
-* The 99th percentile
-* The mean
+- The 95th percentile
+- The 99th percentile
+- The mean
When providing screenshots of graphs, make sure that both the X and Y axes and
the legend are clearly visible. If you happen to have access to GitLab.com's own
@@ -36,12 +36,13 @@ graphs/dashboards.
GitLab provides built-in tools to help improve performance and availability:
-* [Profiling](profiling.md)
- * [Sherlock](profiling.md#sherlock)
-* [GitLab Performance Monitoring](../administration/monitoring/performance/index.md)
-* [Request Profiling](../administration/monitoring/performance/request_profiling.md)
-* [QueryRecoder](query_recorder.md) for preventing `N+1` regressions
-* [Chaos endpoints](chaos_endpoints.md) for testing failure scenarios. Intended mainly for testing availability.
+- [Profiling](profiling.md).
+ - [Sherlock](profiling.md#sherlock).
+- [Distributed Tracing](distributed_tracing.md)
+- [GitLab Performance Monitoring](../administration/monitoring/performance/index.md).
+- [Request Profiling](../administration/monitoring/performance/request_profiling.md).
+- [QueryRecoder](query_recorder.md) for preventing `N+1` regressions.
+- [Chaos endpoints](chaos_endpoints.md) for testing failure scenarios. Intended mainly for testing availability.
GitLab employees can use GitLab.com's performance monitoring systems located at
<https://dashboards.gitlab.net>, this requires you to log in using your
@@ -269,11 +270,11 @@ piece of code is worth optimizing. The only two things you can do are:
Some examples of changes that aren't really important/worth the effort:
-* Replacing double quotes with single quotes.
-* Replacing usage of Array with Set when the list of values is very small.
-* Replacing library A with library B when both only take up 0.1% of the total
+- Replacing double quotes with single quotes.
+- Replacing usage of Array with Set when the list of values is very small.
+- Replacing library A with library B when both only take up 0.1% of the total
execution time.
-* Calling `freeze` on every string (see [String Freezing](#string-freezing)).
+- Calling `freeze` on every string (see [String Freezing](#string-freezing)).
## Slow Operations & Sidekiq
@@ -336,7 +337,6 @@ the same method won't end up retrieving data from Redis upon every call. When
memoizing cached data in an instance variable, make sure to also reset the
instance variable when flushing the cache. An example:
-
```ruby
def first_branch
@first_branch ||= cache.fetch(:first_branch) { branches.first }
@@ -411,6 +411,21 @@ there's nothing stopping somebody from doing this elsewhere in the code:
SOME_CONSTANT = 'bar'
```
+## How to seed a database with millions of rows
+
+You might want millions of project rows in your local database, for example,
+in order to compare relative query performance, or to reproduce a bug. You could
+do this by hand with SQL commands, but since you have ActiveRecord models, you
+might find using these gems more convenient:
+
+- [BulkInsert gem](https://github.com/jamis/bulk_insert)
+- [ActiveRecord::PgGenerateSeries gem](https://github.com/ryu39/active_record-pg_generate_series)
+
+### Examples
+
+You may find some useful examples in this snippet:
+https://gitlab.com/gitlab-org/gitlab-ce/snippets/33946
+
[#15607]: https://gitlab.com/gitlab-org/gitlab-ce/issues/15607
[yorickpeterse]: https://gitlab.com/yorickpeterse
[anti-pattern]: https://en.wikipedia.org/wiki/Anti-pattern
diff --git a/doc/development/policies.md b/doc/development/policies.md
index 62141356f59..c4ac42bb40a 100644
--- a/doc/development/policies.md
+++ b/doc/development/policies.md
@@ -8,12 +8,11 @@ The policy used is based on the subject's class name - so `Ability.allowed?(user
Permissions are broken into two parts: `conditions` and `rules`. Conditions are boolean expressions that can access the database and the environment, while rules are statically configured combinations of expressions and other rules that enable or prevent certain abilities. For an ability to be allowed, it must be enabled by at least one rule, and not prevented by any.
-
### Conditions
Conditions are defined by the `condition` method, and are given a name and a block. The block will be executed in the context of the policy object - so it can access `@user` and `@subject`, as well as call any methods defined on the policy. Note that `@user` may be nil (in the anonymous case), but `@subject` is guaranteed to be a real instance of the subject class.
-``` ruby
+```ruby
class FooPolicy < BasePolicy
condition(:is_public) do
# @subject guaranteed to be an instance of Foo
@@ -37,7 +36,7 @@ Conditions are cached according to their scope. Scope and ordering will be cover
A `rule` is a logical combination of conditions and other rules, that are configured to enable or prevent certain abilities. It is important to note that the rule configuration is static - a rule's logic cannot touch the database or know about `@user` or `@subject`. This allows us to cache only at the condition level. Rules are specified through the `rule` method, which takes a block of DSL configuration, and returns an object that responds to `#enable` or `#prevent`:
-``` ruby
+```ruby
class FooPolicy < BasePolicy
# ...
@@ -57,22 +56,66 @@ end
Within the rule DSL, you can use:
-* A regular word mentions a condition by name - a rule that is in effect when that condition is truthy.
-* `~` indicates negation
-* `&` and `|` are logical combinations, also available as `all?(...)` and `any?(...)`
-* `can?(:other_ability)` delegates to the rules that apply to `:other_ability`. Note that this is distinct from the instance method `can?`, which can check dynamically - this only configures a delegation to another ability.
+- A regular word mentions a condition by name - a rule that is in effect when that condition is truthy.
+- `~` indicates negation.
+- `&` and `|` are logical combinations, also available as `all?(...)` and `any?(...)`.
+- `can?(:other_ability)` delegates to the rules that apply to `:other_ability`. Note that this is distinct from the instance method `can?`, which can check dynamically - this only configures a delegation to another ability.
## Scores, Order, Performance
To see how the rules get evaluated into a judgment, it is useful in a console to use `policy.debug(:some_ability)`. This will print the rules in the order they are evaluated.
-When a policy is asked whether a particular ability is allowed (`policy.allowed?(:some_ability)`), it does not necessarily have to compute all the conditions on the policy. First, only the rules relevant to that particular ability are selected. Then, the execution model takes advantage of short-circuiting, and attempts to sort rules based on a heuristic of how expensive they will be to calculate. The sorting is dynamic and cache-aware, so that previously calculated conditions will be considered first, before computing other conditions.
+For example, let's say you wanted to debug `IssuePolicy`. You might run
+the debugger in this way:
+
+```ruby
+user = User.find_by(username: 'john')
+issue = Issue.first
+policy = IssuePolicy.new(user, issue)
+policy.debug(:read_issue)
+```
+
+An example debug output would look as follows:
+
+```ruby
+- [0] prevent when all?(confidential, ~can_read_confidential) ((@john : Issue/1))
+- [0] prevent when archived ((@john : Project/4))
+- [0] prevent when issues_disabled ((@john : Project/4))
+- [0] prevent when all?(anonymous, ~public_project) ((@john : Project/4))
++ [32] enable when can?(:reporter_access) ((@john : Project/4))
+```
+
+Each line represents a rule that was evaluated. There are a few things to note:
+
+1. The `-` or `+` symbol indicates whether the rule block was evaluated to be
+ `false` or `true`, respectively.
+2. The number inside the brackets indicates the score.
+3. The last part of the line (e.g. `@john : Issue/1`) shows the username
+ and subject for that rule.
+
+Here you can see that the first four rules were evaluated `false` for
+which user and subject. For example, you can see in the last line that
+the rule was activated because the user `root` had at reporter access to
+the `Project/4`.
+
+When a policy is asked whether a particular ability is allowed
+(`policy.allowed?(:some_ability)`), it does not necessarily have to
+compute all the conditions on the policy. First, only the rules relevant
+to that particular ability are selected. Then, the execution model takes
+advantage of short-circuiting, and attempts to sort rules based on a
+heuristic of how expensive they will be to calculate. The sorting is
+dynamic and cache-aware, so that previously calculated conditions will
+be considered first, before computing other conditions.
+
+Note that the score is chosen by a developer via the `score:` parameter
+in a `condition` to denote how expensive evaluating this rule would be
+relative to other rules.
## Scope
Sometimes, a condition will only use data from `@user` or only from `@subject`. In this case, we want to change the scope of the caching, so that we don't recalculate conditions unnecessarily. For example, given:
-``` ruby
+```ruby
class FooPolicy < BasePolicy
condition(:expensive_condition) { @subject.expensive_query? }
@@ -82,7 +125,7 @@ end
Naively, if we call `Ability.can?(user1, :some_ability, foo)` and `Ability.can?(user2, :some_ability, foo)`, we would have to calculate the condition twice - since they are for different users. But if we use the `scope: :subject` option:
-``` ruby
+```ruby
condition(:expensive_condition, scope: :subject) { @subject.expensive_query? }
```
@@ -93,7 +136,7 @@ both user and subject (including a simple anonymous check!) your result will be
Sometimes we are checking permissions for a lot of users for one subject, or a lot of subjects for one user. In this case, we want to set a *preferred scope* - i.e. tell the system that we prefer rules that can be cached on the repeated parameter. For example, in `Ability.users_that_can_read_project`:
-``` ruby
+```ruby
def users_that_can_read_project(users, project)
DeclarativePolicy.subject_scope do
users.select { |u| allowed?(u, :read_project, project) }
@@ -105,9 +148,9 @@ This will, for example, prefer checking `project.public?` to checking `user.admi
## Delegation
-Delegation is the inclusion of rules from another policy, on a different subject. For example,
+Delegation is the inclusion of rules from another policy, on a different subject. For example:
-``` ruby
+```ruby
class FooPolicy < BasePolicy
delegate { @subject.project }
end
diff --git a/doc/development/polling.md b/doc/development/polling.md
index 3b34f985cd4..76bb5ae7819 100644
--- a/doc/development/polling.md
+++ b/doc/development/polling.md
@@ -51,6 +51,7 @@ request path. By doing this we avoid query parameter ordering problems and make
route matching easier.
For more information see:
+
- [`Poll-Interval` header](fe_guide/performance.md#realtime-components)
- [RFC 7232](https://tools.ietf.org/html/rfc7232)
- [ETag proposal](https://gitlab.com/gitlab-org/gitlab-ce/issues/26926)
diff --git a/doc/development/polymorphic_associations.md b/doc/development/polymorphic_associations.md
index d63b9fb115f..5d69c8add38 100644
--- a/doc/development/polymorphic_associations.md
+++ b/doc/development/polymorphic_associations.md
@@ -7,9 +7,9 @@ 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
+- `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
+- `source_id`: the ID of the row to retrieve based on `source_type`. For
example, when `source_type` is `Project` then `source_id` will contain a
project ID.
@@ -92,10 +92,10 @@ 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
+- 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:
diff --git a/doc/development/post_deployment_migrations.md b/doc/development/post_deployment_migrations.md
index 5986efa9974..a41096aa3eb 100644
--- a/doc/development/post_deployment_migrations.md
+++ b/doc/development/post_deployment_migrations.md
@@ -70,6 +70,6 @@ version (which doesn't depend on the column anymore) has been deployed.
Some other examples where these migrations are useful:
-* Cleaning up data generated due to a bug in GitLab
-* Removing tables
-* Migrating jobs from one Sidekiq queue to another
+- Cleaning up data generated due to a bug in GitLab
+- Removing tables
+- Migrating jobs from one Sidekiq queue to another
diff --git a/doc/development/profiling.md b/doc/development/profiling.md
index 0b0c6dfc8cf..be13485ff78 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -72,16 +72,22 @@ Gitlab::Profiler.print_by_total_time(result, max_percent: 60, min_percent: 2)
# 0.02 0.865 0.000 0.000 0.864 638 *Enumerable#inject
```
+To print the profile in HTML format, use the following example:
+
+```ruby
+result = Gitlab::Profiler.profile('/my-user')
+
+printer = RubyProf::CallStackPrinter.new(result)
+printer.print(File.open('/tmp/profile.html', 'w'))
+```
+
[GitLab-Profiler](https://gitlab.com/gitlab-com/gitlab-profiler) is a project
that builds on this to add some additional niceties, such as allowing
configuration with a single Yaml file for multiple URLs, and uploading of the
profile and log output to S3.
-For GitLab.com, currently the latest profiling data has been [moved from
-Redash to Looker](https://gitlab.com/gitlab-com/Product/issues/5#note_121194467).
-We are [currently investigating how to make this data
-public](https://gitlab.com/meltano/looker/issues/294).
-
+For GitLab.com, you can find the latest results here:
+<http://redash.gitlab.com/dashboard/gitlab-profiler-statistics>
## Sherlock
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index 2ad748d4802..dcb32c89f65 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -38,6 +38,14 @@ Note that since you can't see the questions from stdout, you might just want
to `echo 'yes'` to keep it running. It would still print the errors on stderr
so no worries about missing errors.
+### Extra Project seed options
+
+There are a few environment flags you can pass to change how projects are seeded
+
+- `SIZE`: defaults to `8`, max: `32`. Amount of projects to create.
+- `LARGE_PROJECTS`: defaults to false. If set will clone 6 large projects to help with testing.
+- `FORK`: defaults to false. If set to `true` will fork `torvalds/linux` five times. Can also be set to an existing project full_path and it will fork that instead.
+
### Notes for MySQL
Since the seeds would contain various UTF-8 characters, such as emojis or so,
@@ -65,6 +73,7 @@ To make sure that indices still fit. You could find great details in:
## Run tests
In order to run the test you can use the following commands:
+
- `rake spec` to run the rspec suite
- `rake karma` to run the karma test suite
- `rake gitlab:test` to run all the tests
@@ -143,7 +152,6 @@ following:
bundle exec rake gemojione:digests
```
-
This will update the file `fixtures/emojis/digests.json` based on the currently
available Emoji.
diff --git a/doc/development/reusing_abstractions.md b/doc/development/reusing_abstractions.md
index 83d7d42bd1f..01cedf734fb 100644
--- a/doc/development/reusing_abstractions.md
+++ b/doc/development/reusing_abstractions.md
@@ -149,11 +149,11 @@ typically in JSON.
These are class methods defined by _GitLab itself_, including the following
methods provided by Active Record:
-* `find`
-* `find_by_id`
-* `delete_all`
-* `destroy`
-* `destroy_all`
+- `find`
+- `find_by_id`
+- `delete_all`
+- `destroy`
+- `destroy_all`
Any other methods such as `find_by(some_column: X)` are not included, and
instead fall under the "Active Record" abstraction.
@@ -163,10 +163,10 @@ instead fall under the "Active Record" abstraction.
Instance methods defined on Active Record models by _GitLab itself_. Methods
provided by Active Record are not included, except for the following methods:
-* `save`
-* `update`
-* `destroy`
-* `delete`
+- `save`
+- `update`
+- `destroy`
+- `delete`
### Active Record
diff --git a/doc/development/rolling_out_changes_using_feature_flags.md b/doc/development/rolling_out_changes_using_feature_flags.md
index b65fbc9d958..4e0d1b74bc9 100644
--- a/doc/development/rolling_out_changes_using_feature_flags.md
+++ b/doc/development/rolling_out_changes_using_feature_flags.md
@@ -10,12 +10,12 @@ disable those changes, without having to revert an entire release.
Starting with GitLab 11.4, developers are required to use feature flags for
non-trivial changes. Such changes include:
-* New features (e.g. a new merge request widget, epics, etc).
-* Complex performance improvements that may require additional testing in
+- New features (e.g. a new merge request widget, epics, etc).
+- Complex performance improvements that may require additional testing in
production, such as rewriting complex queries.
-* Invasive changes to the user interface, such as a new navigation bar or the
+- Invasive changes to the user interface, such as a new navigation bar or the
removal of a sidebar.
-* Adding support for importing projects from a third-party service.
+- Adding support for importing projects from a third-party service.
In all cases, those working on the changes can best decide if a feature flag is
necessary. For example, changing the color of a button doesn't need a feature
@@ -135,6 +135,20 @@ want to wait several hours or even days. This is entirely up to you, just make
sure it is clearly communicated to your team, and the Production team if you
anticipate any potential problems.
+Feature gates can also be actor based, for example a feature could first be
+enabled for only the `gitlab-ce` project. The project is passed by supplying a
+`--project` flag:
+
+```
+/chatops run feature set --project=gitlab-org/gitlab-ce some_feature true
+```
+
+For groups the `--group` flag is available:
+
+```
+/chatops run feature set --group=gitlab-org some_feature true
+```
+
Once a change is deemed stable, submit a new merge request to remove the
feature flag. This ensures the change is available to all users and self-hosted
instances. Make sure to add the ~"feature flag" label to this merge request so
@@ -188,3 +202,12 @@ to be shipped. You can do this via ChatOps:
Note that you can do this at any time, even before the merge request using the
flag has been merged!
+
+### Cleaning up
+
+When a feature gate has been removed from the code base, the value still exists
+in the database. This can be removed through ChatOps:
+
+```
+/chatops run feature delete some_feature
+```
diff --git a/doc/development/shell_commands.md b/doc/development/shell_commands.md
index 73893f9dd46..7bdf676be58 100644
--- a/doc/development/shell_commands.md
+++ b/doc/development/shell_commands.md
@@ -190,7 +190,7 @@ A check like this could have avoided CVE-2013-4583.
## Properly anchor regular expressions to the start and end of strings
-When using regular expressions to validate user input that is passed as an argument to a shell command, make sure to use the `\A` and `\z` anchors that designate the start and end of the string, rather than `^` and `$`, or no anchors at all.
+When using regular expressions to validate user input that is passed as an argument to a shell command, make sure to use the `\A` and `\z` anchors that designate the start and end of the string, rather than `^` and `$`, or no anchors at all.
If you don't, an attacker could use this to execute commands with potentially harmful effect.
@@ -198,7 +198,7 @@ For example, when a project's `import_url` is validated like below, the user cou
```ruby
validates :import_url, format: { with: URI.regexp(%w(ssh git http https)) }
-# URI.regexp(%w(ssh git http https)) roughly evaluates to /(ssh|git|http|https):(something_that_looks_like_a_url)/
+# URI.regexp(%w(ssh git http https)) roughly evaluates to /(ssh|git|http|https):(something_that_looks_like_a_url)/
```
Suppose the user submits the following as their import URL:
@@ -211,7 +211,6 @@ Since there are no anchors in the used regular expression, the `git:/tmp/lol` in
When importing, GitLab would execute the following command, passing the `import_url` as an argument:
-
```sh
git clone file://git:/tmp/lol
```
diff --git a/doc/development/sidekiq_debugging.md b/doc/development/sidekiq_debugging.md
index 84b61bd7e61..2b3a9481b93 100644
--- a/doc/development/sidekiq_debugging.md
+++ b/doc/development/sidekiq_debugging.md
@@ -11,6 +11,11 @@ Example:
gitlab_rails['env'] = {"SIDEKIQ_LOG_ARGUMENTS" => "1"}
```
-Please note: It is not recommend to enable this setting in production because some
+Please note: It is not recommend to enable this setting in production because some
Sidekiq jobs (such as sending a password reset email) take secret arguments (for
-example the password reset token). \ No newline at end of file
+example the password reset token).
+
+When using [Sidekiq JSON logging](../administration/logs.md#sidekiqlog),
+arguments logs are limited to a maximum size of 10 kilobytes of text;
+any arguments after this limit will be discarded and replaced with a
+single argument containing the string `"..."`.
diff --git a/doc/development/sql.md b/doc/development/sql.md
index 06005a0a6f8..47519d39e74 100644
--- a/doc/development/sql.md
+++ b/doc/development/sql.md
@@ -256,32 +256,12 @@ violation, for example.
Using transactions does not solve this problem.
-The following pattern should be used to avoid the problem:
+To solve this we've added the `ApplicationRecord.safe_find_or_create_by`.
-```ruby
-Project.transaction do
- begin
- User.find_or_create_by(username: "foo")
- rescue ActiveRecord::RecordNotUnique
- retry
- end
-end
-```
-
-If the above block is run inside a transaction and hits the race
-condition, the transaction is aborted and we cannot simply retry (any
-further queries inside the aborted transaction are going to fail). We
-can employ [nested transactions](http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html#module-ActiveRecord::Transactions::ClassMethods-label-Nested+transactions)
-here to only rollback the "inner transaction". Note that `requires_new: true` is required here.
+This method can be used just as you would the normal
+`find_or_create_by` but it wraps the call in a *new* transaction and
+retries if it were to fail because of an
+`ActiveRecord::RecordNotUnique` error.
-```ruby
-Project.transaction do
- begin
- User.transaction(requires_new: true) do
- User.find_or_create_by(username: "foo")
- end
- rescue ActiveRecord::RecordNotUnique
- retry
- end
-end
-```
+To be able to use this method, make sure the model you want to use
+this on inherits from `ApplicationRecord`.
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 24f4d457d45..cfe0e6f70fc 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -40,7 +40,7 @@ bundle exec rspec spec/[path]/[to]/[spec].rb
to separate phases.
- Use `Gitlab.config.gitlab.host` rather than hard coding `'localhost'`
- Don't assert against the absolute value of a sequence-generated attribute (see
- [Gotchas](../gotchas.md#dont-assert-against-the-absolute-value-of-a-sequence-generated-attribute)).
+ [Gotchas](../gotchas.md#do-not-assert-against-the-absolute-value-of-a-sequence-generated-attribute)).
- Don't supply the `:each` argument to hooks since it's the default.
- On `before` and `after` hooks, prefer it scoped to `:context` over `:all`
- When using `evaluate_script("$('.js-foo').testSomething()")` (or `execute_script`) which acts on a given element,
@@ -121,7 +121,7 @@ failure. In CI you can download these files as job artifacts.
Also, you can manually take screenshots at any point in a test by adding the
methods below. Be sure to remove them when they are no longer needed! See
-https://github.com/mattheworiordan/capybara-screenshot#manual-screenshots for
+<https://github.com/mattheworiordan/capybara-screenshot#manual-screenshots> for
more.
Add `screenshot_and_save_page` in a `:js` spec to screenshot what Capybara
@@ -168,12 +168,13 @@ instead of 30+ seconds in case of a regular `spec_helper`.
### `let` variables
-GitLab's RSpec suite has made extensive use of `let` variables to reduce
-duplication. However, this sometimes [comes at the cost of clarity][lets-not],
+GitLab's RSpec suite has made extensive use of `let`(along with it strict, non-lazy
+version `let!`) variables to reduce duplication. However, this sometimes [comes at the cost of clarity][lets-not],
so we need to set some guidelines for their use going forward:
-- `let` variables are preferable to instance variables. Local variables are
- preferable to `let` variables.
+- `let!` variables are preferable to instance variables. `let` variables
+ are preferable to `let!` variables. Local variables are preferable to
+ `let` variables.
- Use `let` to reduce duplication throughout an entire spec file.
- Don't use `let` to define variables used by a single test; define them as
local variables inside the test's `it` block.
@@ -183,6 +184,9 @@ so we need to set some guidelines for their use going forward:
- Try to avoid overriding the definition of one `let` variable with another.
- Don't define a `let` variable that's only used by the definition of another.
Use a helper method instead.
+- `let!` variables should be used only in case if strict evaluation with defined
+ order is required, otherwise `let` will suffice. Remember that `let` is lazy and won't
+ be evaluated until it is referenced.
[lets-not]: https://robots.thoughtbot.com/lets-not
@@ -302,7 +306,7 @@ path, they will use the same repository on disk and lead to test environment
pollution.
Other files must be managed manually by the spec. If you run code that creates a
-`tmp/test-file.csv` file, for instance, the spec must ensure that the file is
+`tmp/test-file.csv` file, for instance, the spec must ensure that the file is
removed as part of cleanup.
#### Persistent in-memory application state
@@ -358,16 +362,11 @@ range of inputs, might look like this:
describe "#==" do
using RSpec::Parameterized::TableSyntax
- let(:project1) { create(:project) }
- let(:project2) { create(:project) }
where(:a, :b, :result) do
1 | 1 | true
1 | 2 | false
true | true | true
true | false | false
- project1 | project1 | true
- project2 | project2 | true
- project 1 | project2 | false
end
with_them do
@@ -380,6 +379,11 @@ describe "#==" do
end
```
+CAUTION: **Caution:**
+Only use simple values as input in the `where` block. Using procs, stateful
+objects, FactoryBot-created objects etc. can lead to
+[unexpected results](https://github.com/tomykaira/rspec-parameterized/issues/8).
+
### Prometheus tests
Prometheus metrics may be preserved from one test run to another. To ensure that metrics are
diff --git a/doc/development/testing_guide/ci.md b/doc/development/testing_guide/ci.md
index d685cacf9ea..7a7fca46534 100644
--- a/doc/development/testing_guide/ci.md
+++ b/doc/development/testing_guide/ci.md
@@ -24,14 +24,18 @@ Our current CI parallelization setup is as follows:
uploaded to S3.
After that, the next pipeline will use the up-to-date
-`knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file.
+`knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file.
### Monitoring
The GitLab test suite is [monitored] for the `master` branch, and any branch
that includes `rspec-profile` in their name.
+A [public dashboard] is available for everyone to see. Feel free to look at the
+slowest test files and try to improve them.
+
[monitored]: ../performance.md#rspec-profiling
+[public dashboard]: https://redash.gitlab.com/public/dashboards/l1WhHXaxrCWM5Ai9D7YDqHKehq6OU3bx5gssaiWe?org_slug=default
## CI setup
diff --git a/doc/development/testing_guide/end_to_end_tests.md b/doc/development/testing_guide/end_to_end_tests.md
index e9f236c6b3a..a239dc84a1c 100644
--- a/doc/development/testing_guide/end_to_end_tests.md
+++ b/doc/development/testing_guide/end_to_end_tests.md
@@ -41,24 +41,24 @@ Currently, we are using _multi-project pipeline_-like approach to run QA
pipelines.
1. Developer triggers a manual action, that can be found in CE / EE merge
-requests. This starts a chain of pipelines in multiple projects.
+ requests. This starts a chain of pipelines in multiple projects.
1. The script being executed triggers a pipeline in [Omnibus GitLab][omnibus-gitlab]
-and waits for the resulting status. We call this a _status attribution_.
+ and waits for the resulting status. We call this a _status attribution_.
1. GitLab packages are being built in the [Omnibus GitLab][omnibus-gitlab]
-pipeline. Packages are then pushed to its Container Registry.
+ pipeline. Packages are then pushed to its Container Registry.
1. When packages are ready, and available in the registry, a final step in the
-[Omnibus GitLab][omnibus-gitlab] pipeline, triggers a new
-[GitLab QA pipeline][gitlab-qa-pipelines]. It also waits for a resulting status.
+ [Omnibus GitLab][omnibus-gitlab] pipeline, triggers a new
+ [GitLab QA pipeline][gitlab-qa-pipelines]. It also waits for a resulting status.
1. GitLab QA pulls images from the registry, spins-up containers and runs tests
-against a test environment that has been just orchestrated by the `gitlab-qa`
-tool.
+ against a test environment that has been just orchestrated by the `gitlab-qa`
+ tool.
1. The result of the [GitLab QA pipeline][gitlab-qa-pipelines] is being
-propagated upstream, through Omnibus, back to the CE / EE merge request.
+ propagated upstream, through Omnibus, back to the CE / EE merge request.
#### How do I write tests?
diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md
index bbb2313ea7b..3d568c37fba 100644
--- a/doc/development/testing_guide/flaky_tests.md
+++ b/doc/development/testing_guide/flaky_tests.md
@@ -5,6 +5,39 @@
It's a test that sometimes fails, but if you retry it enough times, it passes,
eventually.
+## Quarantined tests
+
+When a test frequently fails in `master`,
+[a ~"broken master" issue](https://about.gitlab.com/handbook/engineering/workflow/#broken-master)
+should be created.
+If the test cannot be fixed in a timely fashion, there is an impact on the
+productivity of all the developers, so it should be placed in quarantine by
+assigning the `:quarantine` metadata.
+
+This means it will be skipped unless run with `--tag quarantine`:
+
+```shell
+bin/rspec --tag quarantine
+```
+
+**Before putting a test in quarantine, you should make sure that a
+~"broken master" issue exists for it so it won't stay in quarantine forever.**
+
+Once a test is in quarantine, there are 3 choices:
+
+- Should the test be fixed (i.e. get rid of its flakiness)?
+- Should the test be moved to a lower level of testing?
+- Should the test be removed entirely (e.g. because there's already a
+ lower-level test, or it's duplicating another same-level test, or it's testing
+ too much etc.)?
+
+### Quarantine tests on the CI
+
+Quarantined tests are run on the CI in dedicated jobs that are allowed to fail:
+
+- `rspec-pg-quarantine` and `rspec-mysql-quarantine` (CE & EE)
+- `rspec-pg-quarantine-ee` and `rspec-mysql-quarantine-ee` (EE only)
+
## Automatic retries and flaky tests detection
On our CI, we use [rspec-retry] to automatically retry a failing example a few
@@ -15,51 +48,51 @@ examples in a JSON report file on `master` (`retrieve-tests-metadata` and `updat
is detected in any other branch (`flaky-examples-check` job). In the future, the
`flaky-examples-check` job will not be allowed to fail.
-This was originally implemented in: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13021.
+This was originally implemented in: <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13021>.
[rspec-retry]: https://github.com/NoRedInk/rspec-retry
[`spec/spec_helper.rb`]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/spec_helper.rb
## Problems we had in the past at GitLab
-- [`rspec-retry` is bitting us when some API specs fail](https://gitlab.com/gitlab-org/gitlab-ce/issues/29242): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9825
-- [Sporadic RSpec failures due to `PG::UniqueViolation`](https://gitlab.com/gitlab-org/gitlab-ce/issues/28307#note_24958837): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9846
- - Follow-up: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10688
- - [Capybara.reset_session! should be called before requests are blocked](https://gitlab.com/gitlab-org/gitlab-ce/issues/33779): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12224
+- [`rspec-retry` is bitting us when some API specs fail](https://gitlab.com/gitlab-org/gitlab-ce/issues/29242): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9825>
+- [Sporadic RSpec failures due to `PG::UniqueViolation`](https://gitlab.com/gitlab-org/gitlab-ce/issues/28307#note_24958837): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9846>
+ - Follow-up: <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10688>
+ - [Capybara.reset_session! should be called before requests are blocked](https://gitlab.com/gitlab-org/gitlab-ce/issues/33779): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12224>
- FFaker generates funky data that tests are not ready to handle (and tests should be predictable so that's bad!):
- - [Make `spec/mailers/notify_spec.rb` more robust](https://gitlab.com/gitlab-org/gitlab-ce/issues/20121): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10015
- - [Transient failure in spec/requests/api/commits_spec.rb](https://gitlab.com/gitlab-org/gitlab-ce/issues/27988#note_25342521): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9944
- - [Replace FFaker factory data with sequences](https://gitlab.com/gitlab-org/gitlab-ce/issues/29643): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10184
- - [Transient failure in spec/finders/issues_finder_spec.rb](https://gitlab.com/gitlab-org/gitlab-ce/issues/30211#note_26707685): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10404
+ - [Make `spec/mailers/notify_spec.rb` more robust](https://gitlab.com/gitlab-org/gitlab-ce/issues/20121): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10015>
+ - [Transient failure in spec/requests/api/commits_spec.rb](https://gitlab.com/gitlab-org/gitlab-ce/issues/27988#note_25342521): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9944>
+ - [Replace FFaker factory data with sequences](https://gitlab.com/gitlab-org/gitlab-ce/issues/29643): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10184>
+ - [Transient failure in spec/finders/issues_finder_spec.rb](https://gitlab.com/gitlab-org/gitlab-ce/issues/30211#note_26707685): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10404>
### Time-sensitive flaky tests
-- https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10046
-- https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10306
+- <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10046>
+- <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10306>
### Array order expectation
-- https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10148
+- <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10148>
### Feature tests
-- [Be sure to create all the data the test need before starting exercize](https://gitlab.com/gitlab-org/gitlab-ce/issues/32622#note_31128195): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12059
-- [Bis](https://gitlab.com/gitlab-org/gitlab-ce/issues/34609#note_34048715): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12604
-- [Bis](https://gitlab.com/gitlab-org/gitlab-ce/issues/34698#note_34276286): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12664
-- [Assert against the underlying database state instead of against a page's content](https://gitlab.com/gitlab-org/gitlab-ce/issues/31437): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10934
+- [Be sure to create all the data the test need before starting exercize](https://gitlab.com/gitlab-org/gitlab-ce/issues/32622#note_31128195): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12059>
+- [Bis](https://gitlab.com/gitlab-org/gitlab-ce/issues/34609#note_34048715): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12604>
+- [Bis](https://gitlab.com/gitlab-org/gitlab-ce/issues/34698#note_34276286): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12664>
+- [Assert against the underlying database state instead of against a page's content](https://gitlab.com/gitlab-org/gitlab-ce/issues/31437): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10934>
#### Capybara viewport size related issues
-- [Transient failure of spec/features/issues/filtered_search/filter_issues_spec.rb](https://gitlab.com/gitlab-org/gitlab-ce/issues/29241#note_26743936): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10411
+- [Transient failure of spec/features/issues/filtered_search/filter_issues_spec.rb](https://gitlab.com/gitlab-org/gitlab-ce/issues/29241#note_26743936): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10411>
#### Capybara JS driver related issues
-- [Don't wait for AJAX when no AJAX request is fired](https://gitlab.com/gitlab-org/gitlab-ce/issues/30461): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10454
-- [Bis](https://gitlab.com/gitlab-org/gitlab-ce/issues/34647): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12626
+- [Don't wait for AJAX when no AJAX request is fired](https://gitlab.com/gitlab-org/gitlab-ce/issues/30461): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10454>
+- [Bis](https://gitlab.com/gitlab-org/gitlab-ce/issues/34647): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12626>
#### PhantomJS / WebKit related issues
-- Memory is through the roof! (TL;DR: Load images but block images requests!): https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12003
+- Memory is through the roof! (TL;DR: Load images but block images requests!): <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12003>
## Resources
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index f8993653aec..0470a071d39 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -141,14 +141,15 @@ module. GitLab has a custom `spyOnDependency` method which utilizes
[babel-plugin-rewire](https://github.com/speedskater/babel-plugin-rewire) to
achieve this. It can be used like so:
-```javascript
+```js
// my_module.js
import { visitUrl } from '~/lib/utils/url_utility';
export default function doSomething() {
visitUrl('/foo/bar');
}
-
+```
+```js
// my_module_spec.js
import doSomething from '~/my_module';
@@ -185,8 +186,8 @@ See this [section][vue-test].
`rake karma` runs the frontend-only (JavaScript) tests.
It consists of two subtasks:
-* `rake karma:fixtures` (re-)generates fixtures
-* `rake karma:tests` actually executes the tests
+- `rake karma:fixtures` (re-)generates fixtures
+- `rake karma:tests` actually executes the tests
As long as the fixtures don't change, `rake karma:tests` (or `yarn karma`)
is sufficient (and saves you some time).
@@ -243,14 +244,14 @@ supported by the PhantomJS test runner which is used for both Karma and RSpec
tests. We polyfill some JavaScript objects for older browsers, but some
features are still unavailable:
-* Array.from
-* Array.first
-* Async functions
-* Generators
-* Array destructuring
-* For..Of
-* Symbol/Symbol.iterator
-* Spread
+- Array.from
+- Array.first
+- Async functions
+- Generators
+- Array destructuring
+- For..Of
+- Symbol/Symbol.iterator
+- Spread
Until these are polyfilled appropriately, they should not be used. Please
update this list with additional unsupported features.
diff --git a/doc/development/testing_guide/img/review_apps_cicd_architecture.png b/doc/development/testing_guide/img/review_apps_cicd_architecture.png
new file mode 100644
index 00000000000..87e472076f3
--- /dev/null
+++ b/doc/development/testing_guide/img/review_apps_cicd_architecture.png
Binary files differ
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 309babb5f94..fda3ff57316 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -6,39 +6,72 @@ Review Apps are automatically deployed by each pipeline, both in
## How does it work?
+### CD/CD architecture diagram
+
+![Review Apps CI/CD architecture](img/review_apps_cicd_architecture.png)
+
+<details>
+<summary>Show mermaid source</summary>
+<pre>
+graph TD
+ B1 -.->|2. once gitlab:assets:compile is done,<br />triggers a CNG-mirror pipeline and wait for it to be done| A2
+ C1 -.->|2. once review-build-cng is done,<br />Helm deploys the Review App using the Cloud<br/>Native images built by the CNG-mirror pipeline| A3
+
+subgraph gitlab-ce/ee `test` stage
+ A1[gitlab:assets:compile]
+ B1[review-build-cng] -->|1. wait for| A1
+ C1[review-deploy] -->|1. wait for| B1
+ D1[review-qa-smoke] -->|1. wait for| C1
+ D1[review-qa-smoke] -.->|2. once review-deploy is done| E1>gitlab-qa runs the smoke<br/>suite against the Review App]
+ end
+
+subgraph CNG-mirror pipeline
+ A2>Cloud Native images are built];
+ end
+
+subgraph GCP `gitlab-review-apps` project
+ A3>"Cloud Native images are deployed to the<br />`review-apps-ce` or `review-apps-ee` Kubernetes (GKE) cluster"];
+ end
+</pre>
+</details>
+
+### Detailed explanation
+
1. On every [pipeline][gitlab-pipeline] during the `test` stage, the
- [`review-deploy`][review-deploy-job] job is automatically started.
-1. The `review-deploy` job:
- 1. Waits for the `gitlab:assets:compile` job to finish since the
- [`CNG-mirror`][cng-mirror] pipeline triggerred in the following step
- depends on it.
- 1. [Triggers a pipeline][cng-pipeline] in the [`CNG-mirror`][cng-mirror]
- project.
- - We use the `CNG-mirror` project so that the `CNG`, (**C**loud
- **N**ative **G**itLab), project's registry is not overloaded with a
- lot of transient Docker images.
- - The `CNG-mirror` pipeline creates the Docker images of each component
- (e.g. `gitlab-rails-ee`, `gitlab-shell`, `gitaly` etc.) based on the
- commit from the [GitLab pipeline][gitlab-pipeline] and store them in
- its [registry][cng-mirror-registry].
- 1. Once all images are built by [`CNG-mirror`][cng-mirror], the Review App
- is deployed using [the official GitLab Helm chart][helm-chart] to the
- [`review-apps-ce`][review-apps-ce] / [`review-apps-ee`][review-apps-ee]
- Kubernetes cluster on GCP.
- - The actual scripts used to deploy the Review App can be found at
- [`scripts/review_apps/review-apps.sh`][review-apps.sh].
- - These scripts are basically
- [our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the
- default CNG images are overridden with the images built and stored in the
- [`CNG-mirror` project's registry][cng-mirror-registry].
- - Since we're using [the official GitLab Helm chart][helm-chart], this means
- you get a dedicated environment for your branch that's very close to what
- it would look in production.
-1. Once the `review-deploy` job succeeds, you should be able to use your Review
- App thanks to the direct link to it from the MR widget. The default username
- is `root` and its password can be found in the 1Password secure note named
- **gitlab-{ce,ee} Review App's root password** (note that there's currently
- [a bug where the default password seems to be overridden][password-bug]).
+ [`review-build-cng`][review-build-cng] and
+ [`review-deploy`][review-deploy] jobs are automatically started.
+ - The [`review-deploy`][review-deploy] job waits for the
+ [`review-build-cng`][review-build-cng] job to finish.
+ - The [`review-build-cng`][review-build-cng] job waits for the
+ [`gitlab:assets:compile`][gitlab:assets:compile] job to finish since the
+ [`CNG-mirror`][cng-mirror] pipeline triggered in the following step depends on it.
+1. Once the [`gitlab:assets:compile`][gitlab:assets:compile] job is done,
+ [`review-build-cng`][review-build-cng] [triggers a pipeline][cng-pipeline]
+ in the [`CNG-mirror`][cng-mirror] project.
+ - The [`CNG-mirror`][cng-pipeline] pipeline creates the Docker images of
+ each component (e.g. `gitlab-rails-ee`, `gitlab-shell`, `gitaly` etc.)
+ based on the commit from the [GitLab pipeline][gitlab-pipeline] and store
+ them in its [registry][cng-mirror-registry].
+ - We use the [`CNG-mirror`][cng-mirror] project so that the `CNG`, (**C**loud
+ **N**ative **G**itLab), project's registry is not overloaded with a
+ lot of transient Docker images.
+1. Once the [`review-build-cng`][review-build-cng] job is done, the
+ [`review-deploy`][review-deploy] job deploys the Review App using
+ [the official GitLab Helm chart][helm-chart] to the
+ [`review-apps-ce`][review-apps-ce] / [`review-apps-ee`][review-apps-ee]
+ Kubernetes cluster on GCP.
+ - The actual scripts used to deploy the Review App can be found at
+ [`scripts/review_apps/review-apps.sh`][review-apps.sh].
+ - These scripts are basically
+ [our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the
+ default CNG images are overridden with the images built and stored in the
+ [`CNG-mirror` project's registry][cng-mirror-registry].
+ - Since we're using [the official GitLab Helm chart][helm-chart], this means
+ you get a dedicated environment for your branch that's very close to what
+ it would look in production.
+1. Once the [`review-deploy`][review-deploy] job succeeds, you should be able to
+ use your Review App thanks to the direct link to it from the MR widget. To log
+ into the Review App, see "Log into my Review App?" below.
**Additional notes:**
@@ -62,8 +95,27 @@ You can also manually start the `review-qa-all`: it runs the full QA suite.
Note that both jobs first wait for the `review-deploy` job to be finished.
+## Performance Metrics
+
+On every [pipeline][gitlab-pipeline] during the `test` stage, the
+`review-performance` job is automatically started: this job does basic
+browser performance testing using [Sitespeed.io Container](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html) .
+
+This job waits for the `review-deploy` job to be finished.
+
## How to?
+### Log into my Review App?
+
+The default username is `root` and its password can be found in the 1Password
+secure note named **gitlab-{ce,ee} Review App's root password**.
+
+### Enable a feature flag for my Review App?
+
+1. Open your Review App and log in as documented above.
+1. Create a personal access token.
+1. Enable the feature flag using the [Feature flag API](../../api/features.md).
+
### Find my Review App slug?
1. Open the `review-deploy` job.
@@ -109,21 +161,28 @@ thousands of unused Docker images.**
**How big are the Kubernetes clusters (`review-apps-ce` and `review-apps-ee`)?**
> The clusters are currently set up with a single pool of preemptible nodes,
- with a minimum of 1 node and a maximum of 100 nodes.
+ with a minimum of 1 node and a maximum of 50 nodes.
**What are the machine running on the cluster?**
- > We're currently using `n1-standard-4` (4 vCPUs, 15 GB memory) machines.
+ > We're currently using `n1-standard-16` (16 vCPUs, 60 GB memory) machines.
**How do we secure this from abuse? Apps are open to the world so we need to
find a way to limit it to only us.**
> This isn't enabled for forks.
-[gitlab-pipeline]: https://gitlab.com/gitlab-org/gitlab-ce/pipelines/35850709
-[review-deploy-job]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/118076368
+## Other resources
+
+* [Review Apps integration for CE/EE (presentation)](https://docs.google.com/presentation/d/1QPLr6FO4LduROU8pQIPkX1yfGvD13GEJIBOenqoKxR8/edit?usp=sharing)
+
+[charts-1068]: https://gitlab.com/charts/gitlab/issues/1068
+[gitlab-pipeline]: https://gitlab.com/gitlab-org/gitlab-ce/pipelines/44362587
+[gitlab:assets:compile]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511610
+[review-build-cng]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511623
+[review-deploy]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511624
[cng-mirror]: https://gitlab.com/gitlab-org/build/CNG-mirror
-[cng-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/35883435
+[cng-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657
[cng-mirror-registry]: https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry
[helm-chart]: https://gitlab.com/charts/gitlab/
[review-apps-ce]: https://console.cloud.google.com/kubernetes/clusters/details/us-central1-a/review-apps-ce?project=gitlab-review-apps
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index a8671fc3aa3..5d46833a1e2 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -6,7 +6,7 @@ _This diagram demonstrates the relative priority of each test type we use. `e2e`
## Unit tests
-Formal definition: https://en.wikipedia.org/wiki/Unit_testing
+Formal definition: <https://en.wikipedia.org/wiki/Unit_testing>
These kind of tests ensure that a single unit of code (a method) works as
expected (given an input, it has a predictable output). These tests should be
@@ -32,7 +32,7 @@ records should use stubs/doubles as much as possible.
## Integration tests
-Formal definition: https://en.wikipedia.org/wiki/Integration_testing
+Formal definition: <https://en.wikipedia.org/wiki/Integration_testing>
These kind of tests ensure that individual parts of the application work well
together, without the overhead of the actual app environment (i.e. the browser).
@@ -46,7 +46,7 @@ They're useful to test permissions, redirections, what view is rendered etc.
| `app/mailers/` | `spec/mailers/` | RSpec | |
| `lib/api/` | `spec/requests/api/` | RSpec | |
| `lib/ci/api/` | `spec/requests/ci/api/` | RSpec | |
-| `app/assets/javascripts/` | `spec/javascripts/` | Karma | More details in the [JavaScript](#javascript) section. |
+| `app/assets/javascripts/` | `spec/javascripts/` | Karma | More details in the [Karma JavaScript test suite](frontend_testing.md#karma-test-suite) section. |
### About controller tests
@@ -75,8 +75,8 @@ of multiple components).
Formal definitions:
-- https://en.wikipedia.org/wiki/System_testing
-- https://en.wikipedia.org/wiki/White-box_testing
+- <https://en.wikipedia.org/wiki/System_testing>
+- <https://en.wikipedia.org/wiki/White-box_testing>
These kind of tests ensure the GitLab *Rails* application (i.e.
`gitlab-ce`/`gitlab-ee`) works as expected from a *browser* point of view.
@@ -135,8 +135,8 @@ The reasons why we should follow these best practices are as follows:
Formal definitions:
-- https://en.wikipedia.org/wiki/System_testing
-- https://en.wikipedia.org/wiki/Black-box_testing
+- <https://en.wikipedia.org/wiki/System_testing>
+- <https://en.wikipedia.org/wiki/Black-box_testing>
GitLab consists of [multiple pieces] such as [GitLab Shell], [GitLab Workhorse],
[Gitaly], [GitLab Pages], [GitLab Runner], and GitLab Rails. All theses pieces
@@ -159,6 +159,10 @@ Every new feature should come with a [test plan].
> See [end-to-end tests](end_to_end_tests.md) for more information.
+Note that `qa/spec` contains unit tests of the QA framework itself, not to be
+confused with the application's [unit tests](#unit-tests) or
+[end-to-end tests](#black-box-tests-at-the-system-level-aka-end-to-end-tests).
+
[multiple pieces]: ../architecture.md#components
[GitLab Shell]: https://gitlab.com/gitlab-org/gitlab-shell
[GitLab Workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse
@@ -206,7 +210,7 @@ trade-off:
- Integration tests are a bit more expensive, but don't abuse them. A system test
is often better than an integration test that is stubbing a lot of internals.
- System tests are expensive (compared to unit tests), even more if they require
- a JavaScript driver. Make sure to follow the guidelines in the [Speed](#test-speed)
+ a JavaScript driver. Make sure to follow the guidelines in the [Speed](best_practices.md#test-speed)
section.
Another way to see it is to think about the "cost of tests", this is well
diff --git a/doc/development/understanding_explain_plans.md b/doc/development/understanding_explain_plans.md
index adf8795a5e3..01a0044f096 100644
--- a/doc/development/understanding_explain_plans.md
+++ b/doc/development/understanding_explain_plans.md
@@ -625,9 +625,9 @@ 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 (e.g. an index scan) that requires _a lot_ of
+- Sequential scans on large tables
+- Filters that remove a lot of rows
+- Performing a certain step (e.g. an index scan) that requires _a lot_ of
buffers (e.g. more than 512 MB for GitLab.com).
As a general guideline, aim for a query that:
@@ -650,8 +650,8 @@ 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:
-* <https://explain.depesz.com/>
-* <http://tatiyants.com/postgres-query-plan-visualization/>
+- <https://explain.depesz.com/>
+- <http://tatiyants.com/postgres-query-plan-visualization/>
GitLab employees can also use our chatops solution, available in Slack using the
`/chatops` slash command. You can use chatops to get a query plan by running the
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
index e5466ae8914..0e396baccff 100644
--- a/doc/development/utilities.md
+++ b/doc/development/utilities.md
@@ -4,7 +4,7 @@ We developed a number of utilities to ease development.
## [`MergeHash`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/utils/merge_hash.rb)
-* Deep merges an array of hashes:
+- Deep merges an array of hashes:
``` ruby
Gitlab::Utils::MergeHash.merge(
@@ -31,7 +31,7 @@ We developed a number of utilities to ease development.
]
```
-* Extracts all keys and values from a hash into an array:
+- Extracts all keys and values from a hash into an array:
``` ruby
Gitlab::Utils::MergeHash.crush(
@@ -47,14 +47,14 @@ We developed a number of utilities to ease development.
## [`Override`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/utils/override.rb)
-* This utility could help us check if a particular method would override
+- This utility could help us check if a particular method would override
another method or not. It has the same idea of Java's `@Override` annotation
or Scala's `override` keyword. However we only do this check when
`ENV['STATIC_VERIFICATION']` is set to avoid production runtime overhead.
This is useful to check:
- * If we have typos in overriding methods.
- * If we renamed the overridden methods, making original overriding methods
+ - If we have typos in overriding methods.
+ - If we renamed the overridden methods, making original overriding methods
overrides nothing.
Here's a simple example:
@@ -92,7 +92,7 @@ We developed a number of utilities to ease development.
## [`StrongMemoize`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/utils/strong_memoize.rb)
-* Memoize the value even if it is `nil` or `false`.
+- Memoize the value even if it is `nil` or `false`.
We often do `@value ||= compute`, however this doesn't work well if
`compute` might eventually give `nil` and we don't want to compute again.
@@ -126,7 +126,7 @@ We developed a number of utilities to ease development.
end
```
-* Clear memoization
+- Clear memoization
``` ruby
class Find
diff --git a/doc/development/verifying_database_capabilities.md b/doc/development/verifying_database_capabilities.md
index ffdeff47d4a..661ab9cef1a 100644
--- a/doc/development/verifying_database_capabilities.md
+++ b/doc/development/verifying_database_capabilities.md
@@ -6,9 +6,9 @@ necessary to add database (version) specific behaviour.
To facilitate this we have the following methods that you can use:
-* `Gitlab::Database.postgresql?`: returns `true` if PostgreSQL is being used
-* `Gitlab::Database.mysql?`: returns `true` if MySQL is being used
-* `Gitlab::Database.version`: returns the PostgreSQL version number as a string
+- `Gitlab::Database.postgresql?`: returns `true` if PostgreSQL is being used
+- `Gitlab::Database.mysql?`: returns `true` if MySQL is being used
+- `Gitlab::Database.version`: returns the PostgreSQL version number as a string
in the format `X.Y.Z`. This method does not work for MySQL
This allows you to write code such as:
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index 33f46e8d4f3..3d4259ab7d3 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -1,27 +1,28 @@
-# How to create a project in GitLab
+# Create a project
-> **Notes:**
-> - For a list of words that are not allowed to be used as project names see the
-> [reserved names][reserved].
+[Projects](../user/project/index.md) combine many features of GitLab together.
-1. In your dashboard, click the green **New project** button or use the plus
- icon in the upper right corner of the navigation bar.
+NOTE: **Note:**
+For a list of words that cannot be used as project names see
+[Reserved project and group names](../user/reserved_names.md).
- ![Create a project](img/create_new_project_button.png)
+To create a project in GitLab:
-1. This opens the **New project** page.
+1. In your dashboard, click the green **New project** button or use the plus
+ icon in the navigation bar. This opens the **New project** page.
+1. On the **New project** page, choose if you want to:
+ - Create a [blank project](#blank-projects).
+ - Create a project using with one of the available [project templates](#project-templates).
+ - [Import a project](../user/project/import/index.md) from a different repository,
+ if enabled on your GitLab instance. Contact your GitLab admin if this
+ is unavailable.
- ![Project information](img/create_new_project_info.png)
+## Blank projects
-1. Choose if you want start a blank project, or with one of the predefined
- [Project Templates](https://gitlab.com/gitlab-org/project-templates):
- this will kickstart your repository code and CI automatically.
- Otherwise, if you have a project in a different repository, you can [import it] by
- clicking on the **Import project** tab, provided this is enabled in
- your GitLab instance. Ask your administrator if not.
+To create a new blank project on the **New project** page:
-1. Provide the following information:
- - Enter the name of your project in the **Project name** field. You can't use
+1. On the **Blank project** tab, provide the following information:
+ - The name of your project in the **Project name** field. You can't use
special characters, but you can use spaces, hyphens, underscores or even
emoji.
- The **Project description (optional)** field enables you to enter a
@@ -31,11 +32,64 @@
- Changing the **Visibility Level** modifies the project's
[viewing and access rights](../public_access/public_access.md) for users.
- Selecting the **Initialize repository with a README** option creates a
- README so that the Git repository is initialized, has a default branch and
+ README file so that the Git repository is initialized, has a default branch, and
can be cloned.
-
1. Click **Create project**.
+## Project templates
+
+Project templates can pre-populate your project with necessary files to get you started quickly.
+
+There are two types of project templates:
+
+- [Built-in templates](#built-in-templates), sourced from the [`project-templates`](https://gitlab.com/gitlab-org/project-templates) group.
+- [Custom project templates](#custom-project-templates-premium-only), for custom templates configured by GitLab administrators and users.
+
+### Built-in templates
+
+Built-in templates are project templates that are:
+
+- Developed and maintained in the
+ [`project-templates`](https://gitlab.com/gitlab-org/project-templates) group.
+- Released with GitLab.
+
+To use a built-in template on the **New project** page:
+
+1. On the **Create from template** tab.
+1. From the list of available built-in templates, click the:
+ - **Preview** button to look at the template source itself.
+ - **Use template** button to start creating the project.
+1. Finish creating the project by filling out the project's details. The process is the same as for
+ using a [blank project](#blank-projects).
+
+TIP: **Tip:**
+You can improve the existing built-in templates or contribute new ones on the
+[`project-templates`](https://gitlab.com/gitlab-org/project-templates) group.
+
+### Custom project templates **[PREMIUM ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6860) in
+[GitLab Premium](https://about.gitlab.com/pricing) 11.2.
+
+Creating new projects based on custom project templates is a convenient option to bootstrap a project.
+
+Custom projects are available from the **Instance** or **Group** tabs under the **Create from template** tab,
+depending on the type of template.
+
+To use a custom project template on the **New project** page:
+
+1. On the **Create from template** tab, select the **Instance** tab or the **Group** tab.
+1. From the list of available custom templates, click the:
+ - **Preview** button to look at the template source itself.
+ - **Use template** button to start creating the project.
+1. Finish creating the project by filling out the project's details. The process is the same as for
+ using a [blank project](#blank-projects).
+
+For information on configuring custom project templates, see:
+
+- [Custom instance-level project templates](../user/admin_area/custom_project_templates.md), for instance-level templates.
+- [Custom group-level project templates](../user/group/custom_project_templates.md), for group-level templates.
+
## Push to create a new project
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/26388) in GitLab 10.5.
@@ -46,20 +100,20 @@ GitLab to create the new project, all without leaving your terminal. If you have
namespace, we will automatically create a new project under that GitLab namespace with its
visibility set to Private by default (you can later change it in the [project's settings](../public_access/public_access.md#how-to-change-project-visibility)).
-This can be done by using either SSH or HTTP:
+This can be done by using either SSH or HTTPS:
-```
+```sh
## Git push using SSH
git push --set-upstream git@gitlab.example.com:namespace/nonexistent-project.git master
-## Git push using HTTP
+## Git push using HTTPS
git push --set-upstream https://gitlab.example.com/namespace/nonexistent-project.git master
```
Once the push finishes successfully, a remote message will indicate
the command to set the remote and the URL to the new project:
-```
+```text
remote:
remote: The private project namespace/nonexistent-project was created.
remote:
@@ -70,6 +124,3 @@ remote: To view the project, visit:
remote: https://gitlab.example.com/namespace/nonexistent-project
remote:
```
-
-[import it]: ../workflow/importing/README.md
-[reserved]: ../user/reserved_names.md
diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md
index 881629c3bfd..da7853d7d34 100644
--- a/doc/gitlab-basics/create-your-ssh-keys.md
+++ b/doc/gitlab-basics/create-your-ssh-keys.md
@@ -1,10 +1,9 @@
# How to create your SSH Keys
-1. The first thing you need to do is go to your [command line](start-using-git.md)
- and follow the [instructions](../ssh/README.md) to generate your SSH key pair.
+1. Go to your [command line](start-using-git.md) and follow the [instructions](../ssh/README.md) to generate your SSH key pair.
-1. Once you do that, login to GitLab with your credentials.
-1. On the upper right corner, click on your avatar and go to your **Profile settings**.
+1. Log in to GitLab with your credentials.
+1. In the upper-right corner, click your avatar and then click **Settings**.
![Profile settings dropdown](img/profile_settings.png)
@@ -22,12 +21,11 @@
![SSH key title](img/profile_settings_ssh_keys_title.png)
-1. Finally, click on **Add key** to add it to GitLab. You will be able to see
- its fingerprint, its title and creation date.
+1. Finally, click **Add key** to add it to GitLab. You will be able to see
+ its fingerprint, title, and creation date.
![SSH key single page](img/profile_settings_ssh_keys_single_key.png)
-
>**Note:**
Once you add a key, you cannot edit it, only remove it. In case the paste
didn't work, you will have to remove the offending key and re-add it.
diff --git a/doc/gitlab-basics/img/create_new_project_button.png b/doc/gitlab-basics/img/create_new_project_button.png
deleted file mode 100644
index 567f104880f..00000000000
--- a/doc/gitlab-basics/img/create_new_project_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/img/create_new_project_info.png b/doc/gitlab-basics/img/create_new_project_info.png
deleted file mode 100644
index 2693a7f9a6d..00000000000
--- a/doc/gitlab-basics/img/create_new_project_info.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index 0d9994c9925..e30afdf8a40 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -68,6 +68,54 @@ git config --global --list
## Basic Git commands
+Start using Git via the command line with the most basic
+commands as described below.
+
+### Clone a repository
+
+To start working locally on an existing remote repository,
+clone it with the command `git clone <repository path>`.
+By cloning a repository, you'll download a copy of its
+files into your local computer, preserving the Git
+connection with the remote repository.
+
+You can either clone it via HTTPS or [SSH](../ssh/README.md).
+If you chose to clone it via HTTPS, you'll have to enter your
+credentials every time you pull and push. With SSH, you enter
+your credentials once and can pull and push straightaway.
+
+You can find both paths (HTTPS and SSH) by navigating to
+your project's landing page and clicking **Clone**. GitLab
+will prompt you with both paths, from which you can copy
+and paste in your command line.
+
+As an example, consider a repository path:
+
+- HTTPS: `https://gitlab.com/gitlab-org/gitlab-ce.git`
+- SSH: `` git@gitlab.com:gitlab-org/gitlab-ce.git ``
+
+To get started, open a terminal window in the directory
+you wish to clone the repository files into, and run one
+of the following commands.
+
+Clone via HTTPS:
+
+```bash
+git clone https://gitlab.com/gitlab-org/gitlab-ce.git
+```
+
+Clone via SSH:
+
+```bash
+git clone git@gitlab.com:gitlab-org/gitlab-ce.git
+```
+
+Both commands will download a copy of the files in a
+folder named after the project's name.
+
+You can then navigate to the directory and start working
+on it locally.
+
### Go to the master branch to pull the latest changes from there
```bash
diff --git a/doc/install/README.md b/doc/install/README.md
index ae48306e65e..52011526768 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -3,7 +3,7 @@ comments: false
description: Read through the GitLab installation methods.
---
-# Installation
+# Installation **[CORE ONLY]**
GitLab can be installed in most GNU/Linux distributions and in a number
of cloud providers. To get the best experience from GitLab you need to balance
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index ce61ace60a0..2fcc9b90157 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -60,7 +60,7 @@ Here's a list of the AWS services we will use, with links to pricing information
To minimize the permissions of the user, we'll create a new [IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html)
role with limited access:
-1. Navigate to the IAM dashboard https://console.aws.amazon.com/iam/home and
+1. Navigate to the IAM dashboard <https://console.aws.amazon.com/iam/home> and
click **Create role**.
1. Create a new role by selecting **AWS service > EC2**, then click
**Next: Permissions**.
@@ -78,7 +78,7 @@ Internet Gateway.
We'll now create a VPC, a virtual networking environment that you'll control:
-1. Navigate to https://console.aws.amazon.com/vpc/home.
+1. Navigate to <https://console.aws.amazon.com/vpc/home>.
1. Select **Your VPCs** from the left menu and then click **Create VPC**.
At the "Name tag" enter `gitlab-vpc` and at the "IPv4 CIDR block" enter
`10.0.0.0/16`. If you don't require dedicated hardware, you can leave
@@ -379,6 +379,10 @@ size depends on your needs and you can always migrate to a bigger volume later.
You will be able to [set up that volume](#setting-up-the-ebs-volume)
after the instance is created.
+CAUTION: **Caution:**
+We **do not** recommend using the AWS Elastic File System (EFS), as it can result
+in [significantly degraded performance](../../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs).
+
### Configure security group
As a last step, configure the security group:
@@ -471,7 +475,6 @@ gitlab_rails['redis_port'] = 6379
Finally, reconfigure GitLab for the change to take effect:
-
```sh
sudo gitlab-ctl reconfigure
```
@@ -607,7 +610,7 @@ To back up GitLab:
To restore GitLab, first review the [restore documentation](../../raketasks/backup_restore.md#restore),
and primarily the restore prerequisites. Then, follow the steps under the
-[Omnibus installations section](../../raketasks/backup_restore.md#restore-for-omnibus-installations).
+[Omnibus installations section](../../raketasks/backup_restore.md#restore-for-omnibus-gitlab-installations).
## Updating GitLab
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index 19a6e46f969..fa5be1d30f9 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -1,5 +1,5 @@
---
-description: 'Learn how to spin up a
+description: 'Learn how to spin up a
pre-configured GitLab VM on Microsoft Azure and have your very own private GitLab instance up and running in around 30 minutes.'
---
@@ -9,10 +9,10 @@ pre-configured GitLab VM on Microsoft Azure and have your very own private GitLa
>
> _Ported to the GitLab documentation and updated on 2017-08-24 by [Ian Scorer](https://gitlab.com/iscorer)._
-Azure is Microsoft's business cloud and GitLab is a pre-configured offering on the Azure Marketplace.
-Hopefully, you aren't surprised to hear that Microsoft and Azure have embraced open source software
-like Ubuntu, Red Hat Enterprise Linux, and of course - GitLab! This means that you can spin up a
-pre-configured GitLab VM and have your very own private GitLab up and running in around 30 minutes.
+Azure is Microsoft's business cloud and GitLab is a pre-configured offering on the Azure Marketplace.
+Hopefully, you aren't surprised to hear that Microsoft and Azure have embraced open source software
+like Ubuntu, Red Hat Enterprise Linux, and of course - GitLab! This means that you can spin up a
+pre-configured GitLab VM and have your very own private GitLab up and running in around 30 minutes.
Let's get started.
## Getting started
@@ -20,40 +20,40 @@ Let's get started.
First, you'll need an account on Azure. There are three ways to do this:
- If your company (or you) already has an account, then you are ready to go!
-- You can also open your own Azure account for free. _At time of writing_, you get $200
-of credit to spend on Azure services for 30 days. You can use this credit to try out paid Azure
-services, exploring Microsoft's cloud for free. Even after the first 30 days, you never have to pay
-anything unless you decide to transition to paid services with a Pay-As-You-Go Azure subscription.
-This is a great way to try out Azure and cloud computing, and you can
-[read more in their comprehensive FAQ][Azure-Free-Account-FAQ].
-- If you have an MSDN subscription, you can activate your Azure subscriber benefits. Your MSDN
-subscription gives you recurring Azure credits every month, so why not put those credits to use and
-try out GitLab right now?
+- You can also open your own Azure account for free. _At time of writing_, you get $200
+ of credit to spend on Azure services for 30 days. You can use this credit to try out paid Azure
+ services, exploring Microsoft's cloud for free. Even after the first 30 days, you never have to pay
+ anything unless you decide to transition to paid services with a Pay-As-You-Go Azure subscription.
+ This is a great way to try out Azure and cloud computing, and you can
+ [read more in their comprehensive FAQ][Azure-Free-Account-FAQ].
+- If you have an MSDN subscription, you can activate your Azure subscriber benefits. Your MSDN
+ subscription gives you recurring Azure credits every month, so why not put those credits to use and
+ try out GitLab right now?
## Working with Azure
-Once you have an Azure account, you can get started. Login to Azure using
+Once you have an Azure account, you can get started. Login to Azure using
[portal.azure.com](https://portal.azure.com) and the first thing you will see is the Dashboard:
![Azure Dashboard](img/azure-dashboard.png)
-The Dashboard gives you a quick overview of Azure resources, and from here you can build VMs,
+The Dashboard gives you a quick overview of Azure resources, and from here you can build VMs,
create SQL Databases, author websites, and perform lots of other cloud tasks.
## Create New VM
-The [Azure Marketplace][Azure-Marketplace] is an online store for pre-configured applications and
+The [Azure Marketplace][Azure-Marketplace] is an online store for pre-configured applications and
services which have been optimized for the cloud by software vendors like GitLab,
available on the Azure Marketplace as pre-configured solutions. In this tutorial
we will install GitLab Community Edition, but for GitLab Enterprise Edition you
can follow the same process.
-To begin creating a new GitLab VM, click on the **+ New** icon, type "GitLab" into the search
+To begin creating a new GitLab VM, click on the **+ New** icon, type "GitLab" into the search
box, and then click the **"GitLab Community Edition"** search result:
![Azure - New - Search for 'GitLab'](img/azure-new-search-gitlab.png)
-A new "blade" window will pop-out, where you can read more about the **"GitLab Community Edition"**
+A new "blade" window will pop-out, where you can read more about the **"GitLab Community Edition"**
offering which is freely available under the MIT Expat License:
![Azure - New - Select 'GitLab Community Edition'](img/azure-new-gitlab-ce.png)
@@ -70,18 +70,18 @@ The first items we need to configure are the basic settings of the underlying vi
1. Select a `VM disk type` - either **HDD** _(slower, lower cost)_ or **SSD** _(faster, higher cost)_
1. Enter a `User name` - e.g. **"gitlab-admin"**
1. Select an `Authentication type`, either **SSH public key** or **Password**:
-
+
> **Note:** if you're unsure which authentication type to use, select **Password**
- 1. If you chose **SSH public key** - enter your `SSH public key` into the field provided
- _(read the [SSH documentation][GitLab-Docs-SSH] to learn more about how to set up SSH
+ 1. If you chose **SSH public key** - enter your `SSH public key` into the field provided
+ _(read the [SSH documentation][GitLab-Docs-SSH] to learn more about how to set up SSH
public keys)_
- 1. If you chose **Password** - enter the password you wish to use _(this is the password that you
+ 1. If you chose **Password** - enter the password you wish to use _(this is the password that you
will use later in this tutorial to [SSH] into the VM, so make sure it's a strong password/passphrase)_
1. Choose the appropriate `Subscription` tier for your Azure account
1. Choose an existing `Resource Group` or create a new one - e.g. **"GitLab-CE-Azure"**
- > **Note:** a "Resource group" is a way to group related resources together for easier administration.
+ > **Note:** a "Resource group" is a way to group related resources together for easier administration.
> We chose "GitLab-CE-Azure", but your resource group can have the same name as your VM.
1. Choose a `Location` - if you're unsure, select the default location
@@ -94,23 +94,23 @@ Check the settings you have entered, and then click **"OK"** when you're ready t
## Size
-Next, you need to choose the size of your VM - selecting features such as the number of CPU cores,
+Next, you need to choose the size of your VM - selecting features such as the number of CPU cores,
the amount of RAM, the size of storage (and its speed), etc.
-> **Note:** in common with other cloud vendors, Azure operates a resource/usage pricing model, i.e.
-the more resources your VM consumes the more it will cost you to run, so make your selection
+> **Note:** in common with other cloud vendors, Azure operates a resource/usage pricing model, i.e.
+the more resources your VM consumes the more it will cost you to run, so make your selection
carefully. You'll see that Azure provides an _estimated_ monthly cost beneath each VM Size to help
guide your selection.
-The default size - the lowest cost **"DS1_V2 Standard"** VM - meets the minimum system requirements
-to run a small GitLab environment for testing and evaluation purposes, and so we're going to go
+The default size - the lowest cost **"DS1_V2 Standard"** VM - meets the minimum system requirements
+to run a small GitLab environment for testing and evaluation purposes, and so we're going to go
ahead and select this one, but please choose the size which best meets your own requirements:
![Azure - Create Virtual Machine - Size](img/azure-create-virtual-machine-size.png)
-> **Note:** be aware that whilst your VM is active (known as "allocated"), it will incur
-"compute charges" which, ultimately, you will be billed for. So, even if you're using the
-free trial credits, you'll likely want to learn
+> **Note:** be aware that whilst your VM is active (known as "allocated"), it will incur
+"compute charges" which, ultimately, you will be billed for. So, even if you're using the
+free trial credits, you'll likely want to learn
[how to properly shutdown an Azure VM to save money][Azure-Properly-Shutdown-VM].
Go ahead and click your chosen size, then click **"Select"** when you're ready to proceed to the
@@ -118,8 +118,8 @@ next step.
## Settings
-On the next blade, you're asked to configure the Storage, Network and Extension settings.
-We've gone with the default settings as they're sufficient for test-driving GitLab, but please
+On the next blade, you're asked to configure the Storage, Network and Extension settings.
+We've gone with the default settings as they're sufficient for test-driving GitLab, but please
choose the settings which best meet your own requirements:
![Azure - Create Virtual Machine - Settings](img/azure-create-virtual-machine-settings.png)
@@ -128,80 +128,80 @@ Review the settings and then click **"OK"** when you're ready to proceed to the
## Purchase
-The Purchase page is the last step and here you will be presented with the price per hour for your
-new VM. You'll be billed only for the VM itself (e.g. "Standard DS1 v2") because the
+The Purchase page is the last step and here you will be presented with the price per hour for your
+new VM. You'll be billed only for the VM itself (e.g. "Standard DS1 v2") because the
**"GitLab Community Edition"** marketplace solution is free to use at 0 USD/hr:
![Azure - Create Virtual Machine - Purchase](img/azure-create-virtual-machine-purchase.png)
-> **Note:** at this stage, you can review and modify the any of the settings you have made during all
+> **Note:** at this stage, you can review and modify the any of the settings you have made during all
previous steps, just click on any of the four steps to re-open them.
When you have read and agreed to the terms of use and are ready to proceed, click **"Purchase"**.
## Deployment
-At this point, Azure will begin deploying your new VM. The deployment process will take a few
+At this point, Azure will begin deploying your new VM. The deployment process will take a few
minutes to complete, with progress displayed on the **"Deployment"** blade:
![Azure - Create Virtual Machine - Deployment](img/azure-create-virtual-machine-deployment.png)
-Once the deployment process is complete, the new VM and its associated resources will be displayed
+Once the deployment process is complete, the new VM and its associated resources will be displayed
on the Azure Dashboard (you may need to refresh the page):
![Azure - Dashboard - All resources](img/azure-dashboard-running-resources.png)
-The new VM can also be accessed by clicking the `All resources` or `Virtual machines` icons in the
+The new VM can also be accessed by clicking the `All resources` or `Virtual machines` icons in the
Azure Portal sidebar navigation menu.
## Set up a domain name
-The VM will have a public IP address (static by default), but Azure allows us to assign a friendly
+The VM will have a public IP address (static by default), but Azure allows us to assign a friendly
DNS name to the VM, so let's go ahead and do that.
-From the Dashboard, click on the **"GitLab-CE"** tile to open the management blade for the new VM.
+From the Dashboard, click on the **"GitLab-CE"** tile to open the management blade for the new VM.
The public IP address that the VM uses is shown in the 'Essentials' section:
![Azure - VM - Management - Public IP Address](img/azure-vm-management-public-ip.png)
-Click on the public IP address - which should open the **"Public IP address - Configuration"** blade,
-then click on **"Configuration"** (under "Settings"). Now enter a friendly DNS name for your instance
+Click on the public IP address - which should open the **"Public IP address - Configuration"** blade,
+then click on **"Configuration"** (under "Settings"). Now enter a friendly DNS name for your instance
in the `DNS name label` field:
![Azure - VM - Domain Name](img/azure-vm-domain-name.png)
-In the screenshot above, you'll see that we've set the `DNS name label` to **"gitlab-ce-test"**.
-This will make our VM accessible at `gitlab-ce-test.centralus.cloudapp.azure.com`
-_(the full domain name of your own VM will be different, of course)_.
+In the screenshot above, you'll see that we've set the `DNS name label` to **"gitlab-ce-test"**.
+This will make our VM accessible at `gitlab-ce-test.centralus.cloudapp.azure.com`
+_(the full domain name of your own VM will be different, of course)_.
Click **"Save"** for the changes to take effect.
-> **Note:** if you want to use your own domain name, you will need to add a DNS `A` record at your
-domain registrar which points to the public IP address of your Azure VM. If you do this, you'll need
-to make sure your VM is configured to use a _static_ public IP address (i.e. not a _dynamic_ one)
-or you will have to reconfigure the DNS `A` record each time Azure reassigns your VM a new public IP
+> **Note:** if you want to use your own domain name, you will need to add a DNS `A` record at your
+domain registrar which points to the public IP address of your Azure VM. If you do this, you'll need
+to make sure your VM is configured to use a _static_ public IP address (i.e. not a _dynamic_ one)
+or you will have to reconfigure the DNS `A` record each time Azure reassigns your VM a new public IP
address. Read [IP address types and allocation methods in Azure][Azure-IP-Address-Types] to learn more.
## Let's open some ports!
-At this stage you should have a running and fully operational VM. However, none of the services on
-your VM (e.g. GitLab) will be publicly accessible via the internet until you have opened up the
+At this stage you should have a running and fully operational VM. However, none of the services on
+your VM (e.g. GitLab) will be publicly accessible via the internet until you have opened up the
necessary ports to enable access to those services.
-Ports are opened by adding _security rules_ to the **"Network security group"** (NSG) which our VM
-has been assigned to. If you followed the process above, then Azure will have automatically created
-an NSG named `GitLab-CE-nsg` and assigned the `GitLab-CE` VM to it.
+Ports are opened by adding _security rules_ to the **"Network security group"** (NSG) which our VM
+has been assigned to. If you followed the process above, then Azure will have automatically created
+an NSG named `GitLab-CE-nsg` and assigned the `GitLab-CE` VM to it.
-> **Note:** if you gave your VM a different name then the NSG automatically created by Azure will
+> **Note:** if you gave your VM a different name then the NSG automatically created by Azure will
also have a different name - the name you have your VM, with `-nsg` appended to it.
-You can navigate to the NSG settings via many different routes in the Azure Portal, but one of the
-simplest ways is to go to the Azure Dashboard, and then click on the Network Security Group listed
+You can navigate to the NSG settings via many different routes in the Azure Portal, but one of the
+simplest ways is to go to the Azure Dashboard, and then click on the Network Security Group listed
in the **"All resources"** tile:
![Azure - Dashboard - All resources - Network security group](img/azure-dashboard-highlight-nsg.png)
-With the **"Network security group"** blade open, click on **"Inbound security rules"** under
+With the **"Network security group"** blade open, click on **"Inbound security rules"** under
**"Settings"**:
![Azure - Network security group - Inbound security rules](img/azure-nsg-inbound-sec-rules-highlight.png)
@@ -212,18 +212,18 @@ Next, click **"Add"**:
### Which ports to open?
-Like all servers, our VM will be running many services. However, we want to open up the correct
+Like all servers, our VM will be running many services. However, we want to open up the correct
ports to enable public internet access to two services in particular:
-1. **HTTP** (port 80) - opening port 80 will enable our VM to respond to HTTP requests, allowing
-public access to the instance of GitLab running on our VM.
-1. **SSH** (port 22) - opening port 22 will enable our VM to respond to SSH connection requests,
-allowing public access (with authentication) to remote terminal sessions
-_(you'll see why we need [SSH] access to our VM [later on in this tutorial](#maintaining-your-gitlab-instance))_
+1. **HTTP** (port 80) - opening port 80 will enable our VM to respond to HTTP requests, allowing
+ public access to the instance of GitLab running on our VM.
+1. **SSH** (port 22) - opening port 22 will enable our VM to respond to SSH connection requests,
+ allowing public access (with authentication) to remote terminal sessions
+ _(you'll see why we need [SSH] access to our VM [later on in this tutorial](#maintaining-your-gitlab-instance))_
### Open HTTP on Port 80
-In the **"Add inbound security rule"** blade, let's open port 80 so that our VM will accept HTTP
+In the **"Add inbound security rule"** blade, let's open port 80 so that our VM will accept HTTP
connections:
![Azure - Add inbound security rules - HTTP](img/azure-add-inbound-sec-rule-http.png)
@@ -235,7 +235,7 @@ connections:
### Open SSH on Port 22
-Repeat the above process, adding a second Inbound security rule to open port 22, enabling our VM to
+Repeat the above process, adding a second Inbound security rule to open port 22, enabling our VM to
accept [SSH] connections:
![Azure - Add inbound security rules - SSH](img/azure-add-inbound-sec-rule-ssh.png)
@@ -245,16 +245,15 @@ accept [SSH] connections:
1. Make sure the `Action` is set to **Allow**
1. Click **"OK"**
-
-It will take a moment for Azure to add each new Inbound Security Rule (and you may need to click on
-**"Inbound security rules"** to refresh the list), but once completed, you should see the two new
+It will take a moment for Azure to add each new Inbound Security Rule (and you may need to click on
+**"Inbound security rules"** to refresh the list), but once completed, you should see the two new
rules in the list:
![Azure - Inbound security rules - List](img/azure-inbound-sec-rules-list.png)
## Connecting to GitLab
-Use the domain name you set up earlier (or the public IP address) to visit your new GitLab instance
-in your browser. If everything has gone according to plan you should be presented with the
+Use the domain name you set up earlier (or the public IP address) to visit your new GitLab instance
+in your browser. If everything has gone according to plan you should be presented with the
following page, asking you to set a _new_ password for the administrator account automatically
created by GitLab:
@@ -262,26 +261,26 @@ created by GitLab:
Enter your _new_ password into both form fields, and then click **"Change your password"**.
-Once you have changed the password you will be redirected to the GitLab login page. Use `root` as
+Once you have changed the password you will be redirected to the GitLab login page. Use `root` as
the username, enter the new password you set in the previous step, and then click **"Sign in"**:
![GitLab - Login](img/gitlab-login.png)
### Success?
-After signing in successfully, you should see the GitLab Projects page displaying a
+After signing in successfully, you should see the GitLab Projects page displaying a
**"Welcome to GitLab!"** message:
![GitLab - Projects Page](img/gitlab-home.png)
-If so, you now have a working GitLab instance on your own private Azure VM. **Congratulations!**
+If so, you now have a working GitLab instance on your own private Azure VM. **Congratulations!**
## Creating your first GitLab project
-You can skip this section if you are familiar with Git and GitLab. Otherwise, let's create our first
+You can skip this section if you are familiar with Git and GitLab. Otherwise, let's create our first
project. From the Welcome page, click **"New Project"**.
-Let's give our project a name and a description, and then accept the default values for everything
+Let's give our project a name and a description, and then accept the default values for everything
else:
1. Enter **"demo"** into the `Project path` project name field
@@ -290,12 +289,12 @@ else:
![GitLab - New Project](img/gitlab-new-project.png)
-Once the new project has been created (which should only take a moment), you'll be redirected to
+Once the new project has been created (which should only take a moment), you'll be redirected to
homepage for the project:
![GitLab - Empty Project](img/gitlab-project-home-empty.png)
-If you scroll further down the project's home page, you'll see some basic instructions on how to
+If you scroll further down the project's home page, you'll see some basic instructions on how to
set up a local clone of your new repository and push and pull from it:
![GitLab - Empty Project - Basic Instructions](img/gitlab-project-home-instructions.png)
@@ -304,50 +303,50 @@ set up a local clone of your new repository and push and pull from it:
## Maintaining your GitLab instance
-It's important to keep your GitLab environment up-to-date. The GitLab team is constantly making
-enhancements and occasionally you may need to update for security reasons. So let's review how to
-update GitLab.
+It's important to keep your GitLab environment up-to-date. The GitLab team is constantly making
+enhancements and occasionally you may need to update for security reasons. So let's review how to
+update GitLab.
### Checking our current version
To check which version of GitLab we're currently running, click on the "Admin Area" link - it's the
-the wrench icon displayed in the top-right, next to the search box.
+the wrench icon displayed in the top-right, next to the search box.
-In the following screenshot you can see an **"update asap"** notification message in the top-right.
-This particular message indicates that there is a newer version of GitLab available which contains
+In the following screenshot you can see an **"update asap"** notification message in the top-right.
+This particular message indicates that there is a newer version of GitLab available which contains
one or more security fixes:
![GitLab - update asap](img/gitlab-admin-area.png)
-Under the **"Components"** section, we can see that our VM is currently running version `8.6.5` of
-GitLab. This is the version of GitLab which was contained in the Azure Marketplace
-**"GitLab Community Edition"** offering we used to build the VM when we wrote this tutorial.
+Under the **"Components"** section, we can see that our VM is currently running version `8.6.5` of
+GitLab. This is the version of GitLab which was contained in the Azure Marketplace
+**"GitLab Community Edition"** offering we used to build the VM when we wrote this tutorial.
-> **Note:** The version of GitLab in your own VM instance may well be different, but the update
+> **Note:** The version of GitLab in your own VM instance may well be different, but the update
process will still be the same.
### Connect via SSH
-To perform an update, we need to connect directly to our Azure VM instance and run some commands
-from the terminal. Our Azure VM is actually a server running Linux (Ubuntu), so we'll need to
-connect to it using SSH ([Secure Shell][SSH]).
+To perform an update, we need to connect directly to our Azure VM instance and run some commands
+from the terminal. Our Azure VM is actually a server running Linux (Ubuntu), so we'll need to
+connect to it using SSH ([Secure Shell][SSH]).
-If you're running Windows, you'll need to connect using [PuTTY] or an equivalent Windows SSH client.
-If you're running Linux or macOS, then you already have an SSH client installed.
+If you're running Windows, you'll need to connect using [PuTTY] or an equivalent Windows SSH client.
+If you're running Linux or macOS, then you already have an SSH client installed.
-> **Note:**
-> - Remember that you will need to login with the username and password you specified
+> **Note:**
+> - Remember that you will need to login with the username and password you specified
> [when you created](#basics) your Azure VM
-> - If you need to reset your VM password, read
+> - If you need to reset your VM password, read
> [how to reset SSH credentials for a user on an Azure VM][Azure-Troubleshoot-SSH-Connection].
#### SSH from the command-line
-If you're running [SSH] from the command-line (terminal), then type in the following command to
-connect to your VM, substituting `username` and `your-azure-domain-name.com` for the correct values.
+If you're running [SSH] from the command-line (terminal), then type in the following command to
+connect to your VM, substituting `username` and `your-azure-domain-name.com` for the correct values.
-Again, remember that your Azure VM domain name will be the one you
-[set up previously in the tutorial](#set-up-a-domain-name). If you didn't set up a domain name for
+Again, remember that your Azure VM domain name will be the one you
+[set up previously in the tutorial](#set-up-a-domain-name). If you didn't set up a domain name for
your VM, you can use the IP address in its place in the following command:
```bash
@@ -357,7 +356,7 @@ Provide your password at the prompt to authenticate.
#### SSH from Windows (PuTTY)
-If you're using [PuTTY] in Windows as your [SSH] client, then you might want to take a quick
+If you're using [PuTTY] in Windows as your [SSH] client, then you might want to take a quick
read on [using PuTTY in Windows][Using-SSH-In-Putty].
### Updating GitLab
@@ -369,8 +368,8 @@ version:
sudo apt-get update && sudo apt-get install gitlab-ce
```
-This command will update GitLab and its associated components to the latest versions, so it will
-take a little time to complete. You'll see various update tasks being completed in your SSH
+This command will update GitLab and its associated components to the latest versions, so it will
+take a little time to complete. You'll see various update tasks being completed in your SSH
terminal window:
![GitLab updating](img/gitlab-ssh-update-in-progress.png)
@@ -387,23 +386,23 @@ before anything else.
#### Check out your updated GitLab
-Refresh your GitLab instance in the browser and navigate to the Admin Area. You should now have an
-up-to-date GitLab instance.
+Refresh your GitLab instance in the browser and navigate to the Admin Area. You should now have an
+up-to-date GitLab instance.
-When we wrote this tutorial our Azure VM GitLab instance was updated to the latest version at time
-of writing (`9.4.0`). You can see that the message which was previously displaying **"update asap"**
+When we wrote this tutorial our Azure VM GitLab instance was updated to the latest version at time
+of writing (`9.4.0`). You can see that the message which was previously displaying **"update asap"**
is now showing **"up-to-date"**:
![GitLab up to date](img/gitlab-admin-area-9.4.0.png)
## Conclusion
-Naturally, we believe that GitLab is a great git repository tool. However, GitLab is a whole lot
-more than that too. GitLab unifies issues, code review, CI and CD into a single UI, helping you to
-move faster from idea to production, and in this tutorial we showed you how quick and easy it is to
-set up and run your own instance of GitLab on Azure, Microsoft's cloud service.
+Naturally, we believe that GitLab is a great git repository tool. However, GitLab is a whole lot
+more than that too. GitLab unifies issues, code review, CI and CD into a single UI, helping you to
+move faster from idea to production, and in this tutorial we showed you how quick and easy it is to
+set up and run your own instance of GitLab on Azure, Microsoft's cloud service.
-Azure is a great way to experiment with GitLab, and if you decide (as we hope) that GitLab is for
+Azure is a great way to experiment with GitLab, and if you decide (as we hope) that GitLab is for
you, you can continue to use Azure as your secure, scalable cloud provider or of course run GitLab
on any cloud service you choose.
diff --git a/doc/install/docker.md b/doc/install/docker.md
index d0129f0f5c4..4568a949b0a 100644
--- a/doc/install/docker.md
+++ b/doc/install/docker.md
@@ -2,7 +2,7 @@
[Docker](https://www.docker.com) and container technology have been revolutionizing the software world for the past few years. They combine the performance and efficiency of native execution with the abstraction, security, and immutability of virtualization.
-GitLab provides official Docker images to allowing you to easily take advantage of the benefits of containerization while operating your GitLab instance.
+GitLab provides official Docker images allowing you to easily take advantage of the benefits of containerization while operating your GitLab instance.
## Omnibus GitLab based images
diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md
index ab5f7507f24..aa4b3dccf7d 100644
--- a/doc/install/google_cloud_platform/index.md
+++ b/doc/install/google_cloud_platform/index.md
@@ -22,14 +22,14 @@ Once you have performed those two steps, you can [create a VM](#creating-the-vm)
To deploy GitLab on GCP you need to follow five simple steps:
-1. Go to https://console.cloud.google.com/compute/instances and login with your Google credentials.
+1. Go to <https://console.cloud.google.com/compute/instances> and login with your Google credentials.
1. Click on **Create**
![Search for GitLab](img/launch_vm.png)
1. On the next page, you can select the type of VM as well as the
- estimated costs. Provide the name of the instance, desired datacenter, and machine type. Note that GitLab recommends at least 2 vCPU's and 4GB of RAM.
+ estimated costs. Provide the name of the instance, desired datacenter, and machine type. Note that GitLab recommends at least 2 vCPU's and 4GB of RAM.
![Launch on Compute Engine](img/vm_details.png)
@@ -51,7 +51,7 @@ After a few seconds, the instance will be created and available to log in. The n
![GitLab first sign in](img/ssh_terminal.png)
-1. Next, follow the instructions for installing GitLab for the operating system you choose, at https://about.gitlab.com/installation/. You can use the IP address from the step above, as the hostname.
+1. Next, follow the instructions for installing GitLab for the operating system you choose, at <https://about.gitlab.com/installation/>. You can use the IP address from the step above, as the hostname.
1. Congratulations! GitLab is now installed and you can access it via your browser. To finish installation, open the URL in your browser and provide the initial administrator password. The username for this account is `root`.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index d041bfa863a..61f544deabe 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -6,28 +6,30 @@ Since an installation from source is a lot of work and error prone we strongly r
One reason the Omnibus package is more reliable is its use of Runit to restart any of the GitLab processes in case one crashes.
On heavily used GitLab instances the memory usage of the Sidekiq background worker will grow over time.
-Omnibus packages solve this by [letting the Sidekiq terminate gracefully](http://docs.gitlab.com/ce/operations/sidekiq_memory_killer.html) if it uses too much memory.
+
+Omnibus packages solve this by [letting the Sidekiq terminate gracefully](../administration/operations/sidekiq_memory_killer.md) if it uses too much memory.
After this termination Runit will detect Sidekiq is not running and will start it.
-Since installations from source don't have Runit, Sidekiq can't be terminated and its memory usage will grow over time.
+Since installations from source don't use Runit for process supervision, Sidekiq
+can't be terminated and its memory usage will grow over time.
## Select Version to Install
-Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-6-stable`).
+Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-7-stable`).
You can select the branch in the version dropdown in the top left corner of GitLab (below the menu bar).
-If the highest number stable branch is unclear please check the [GitLab Blog](https://about.gitlab.com/blog/) for installation guide links by version.
+If the highest number stable branch is unclear, check the [GitLab blog](https://about.gitlab.com/blog/) for installation guide links by version.
## Important Notes
This guide is long because it covers many cases and includes all commands you need, this is [one of the few installation scripts that actually works out of the box](https://twitter.com/robinvdvleuten/status/424163226532986880).
-This installation guide was created for and tested on **Debian/Ubuntu** operating systems. Please read [requirements.md](requirements.md) for hardware and operating system requirements. If you want to install on RHEL/CentOS we recommend using the [Omnibus packages](https://about.gitlab.com/downloads/).
+This installation guide was created for and tested on **Debian/Ubuntu** operating systems. Read [requirements.md](requirements.md) for hardware and operating system requirements. If you want to install on RHEL/CentOS, we recommend using the [Omnibus packages](https://about.gitlab.com/downloads/).
-This is the official installation guide to set up a production server. To set up a **development installation** or for many other installation options please see [the installation section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#installation).
+This is the official installation guide to set up a production server. To set up a **development installation** or for many other installation options, see [the installation section of the README](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#installation).
-The following steps have been known to work. Please **use caution when you deviate** from this guide. Make sure you don't violate any assumptions GitLab makes about its environment. For example many people run into permission problems because they changed the location of directories or run services as the wrong user.
+The following steps have been known to work. **Use caution when you deviate** from this guide. Make sure you don't violate any assumptions GitLab makes about its environment. For example, many people run into permission problems because they changed the location of directories or run services as the wrong user.
-If you find a bug/error in this guide please **submit a merge request**
+If you find a bug/error in this guide, **submit a merge request**
following the
[contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md).
@@ -35,77 +37,103 @@ following the
The GitLab installation consists of setting up the following components:
-1. Packages / Dependencies
-1. Ruby
-1. Go
-1. Node
-1. System Users
-1. Database
-1. Redis
-1. GitLab
-1. Nginx
+1. [Packages and dependencies](#1-packages-and-dependencies).
+1. [Ruby](#2-ruby).
+1. [Go](#3-go).
+1. [Node](#4-node).
+1. [System users](#5-system-users).
+1. [Database](#6-database).
+1. [Redis](#7-redis).
+1. [GitLab](#8-gitlab).
+1. [Nginx](#9-nginx).
-## 1. Packages / Dependencies
+## 1. Packages and dependencies
`sudo` is not installed on Debian by default. Make sure your system is
up-to-date and install it.
- # run as root!
- apt-get update -y
- apt-get upgrade -y
- apt-get install sudo -y
+```sh
+# run as root!
+apt-get update -y
+apt-get upgrade -y
+apt-get install sudo -y
+```
-**Note:** During this installation some files will need to be edited manually. If you are familiar with vim set it as default editor with the commands below. If you are not familiar with vim please skip this and keep using the default editor.
+NOTE: **Note:**
+During this installation, some files will need to be edited manually. If you are familiar with vim, set it as default editor with the commands below. If you are not familiar with vim, skip this and keep using the default editor.
- # Install vim and set as default editor
- sudo apt-get install -y vim
- sudo update-alternatives --set editor /usr/bin/vim.basic
+```sh
+# Install vim and set as default editor
+sudo apt-get install -y vim
+sudo update-alternatives --set editor /usr/bin/vim.basic
+```
Install the required packages (needed to compile Ruby and native extensions to Ruby gems):
- sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libre2-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate rsync python-docutils pkg-config cmake
+```sh
+sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libre2-dev \
+ libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev \
+ libxslt-dev libcurl4-openssl-dev libicu-dev logrotate rsync python-docutils pkg-config cmake \
+ runit
+```
Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
you can [install re2 manually](https://github.com/google/re2/wiki/Install).
-If you want to use Kerberos for user authentication, then install libkrb5-dev:
+If you want to use Kerberos for user authentication, install `libkrb5-dev`:
- sudo apt-get install libkrb5-dev
+```sh
+sudo apt-get install libkrb5-dev
+```
-**Note:** If you don't know what Kerberos is, you can assume you don't need it.
+NOTE: **Note:**
+If you don't know what Kerberos is, you can assume you don't need it.
-Make sure you have the right version of Git installed
+Make sure you have the right version of Git installed:
- # Install Git
- sudo apt-get install -y git-core
+```sh
+# Install Git
+sudo apt-get install -y git-core
- # Make sure Git is version 2.18.0 or higher
- git --version
+# Make sure Git is version 2.18.0 or higher
+git --version
+```
Is the system packaged Git too old? Remove it and compile from source.
- # Remove packaged Git
- sudo apt-get remove git-core
+```sh
+# Remove packaged Git
+sudo apt-get remove git-core
+
+# Install dependencies
+sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev build-essential
+
+# Download and compile from source
+cd /tmp
+curl --remote-name --location --progress https://www.kernel.org/pub/software/scm/git/git-2.18.0.tar.gz
+echo '94faf2c0b02a7920b0b46f4961d8e9cad08e81418614102898a55f980fa3e7e4 git-2.18.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.18.0.tar.gz
+cd git-2.18.0/
+./configure
+make prefix=/usr/local all
- # Install dependencies
- sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev build-essential
+# Install into /usr/local/bin
+sudo make prefix=/usr/local install
- # Download and compile from source
- cd /tmp
- curl --remote-name --progress https://www.kernel.org/pub/software/scm/git/git-2.18.0.tar.gz
- echo '94faf2c0b02a7920b0b46f4961d8e9cad08e81418614102898a55f980fa3e7e4 git-2.18.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.18.0.tar.gz
- cd git-2.18.0/
- ./configure
- make prefix=/usr/local all
+# When editing config/gitlab.yml (Step 5), change the git -> bin_path to /usr/local/bin/git
+```
- # Install into /usr/local/bin
- sudo make prefix=/usr/local install
+For the [Custom Favicon](../customization/favicon.md) to work, GraphicsMagick
+needs to be installed.
- # When editing config/gitlab.yml (Step 5), change the git -> bin_path to /usr/local/bin/git
+```sh
+sudo apt-get install -y graphicsmagick
+```
**Note:** In order to receive mail notifications, make sure to install a mail server. By default, Debian is shipped with exim4 but this [has problems](https://gitlab.com/gitlab-org/gitlab-ce/issues/12754) while Ubuntu does not ship with one. The recommended mail server is postfix and you can install it with:
- sudo apt-get install -y postfix
+```sh
+sudo apt-get install -y postfix
+```
Then select 'Internet Site' and press enter to confirm the hostname.
@@ -113,8 +141,8 @@ Then select 'Internet Site' and press enter to confirm the hostname.
The Ruby interpreter is required to run GitLab.
-**Note:** The current supported Ruby (MRI) version is 2.3.x. GitLab 9.0 dropped
-support for Ruby 2.1.x.
+**Note:** The current supported Ruby (MRI) version is 2.5.x. GitLab 11.6
+ dropped support for Ruby 2.4.x.
The use of Ruby version managers such as [RVM], [rbenv] or [chruby] with GitLab
in production, frequently leads to hard to diagnose problems. For example,
@@ -127,22 +155,28 @@ instructions are designed to install Ruby from the official source code.
Remove the old Ruby 1.8 if present:
- sudo apt-get remove ruby1.8
+```sh
+sudo apt-get remove ruby1.8
+```
Download Ruby and compile it:
- mkdir /tmp/ruby && cd /tmp/ruby
- curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
- echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
- cd ruby-2.5.3
-
- ./configure --disable-install-rdoc
- make
- sudo make install
+```sh
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
+echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
+cd ruby-2.5.3
+
+./configure --disable-install-rdoc
+make
+sudo make install
+```
-Then install the Bundler Gem:
+Then install the Bundler gem (a version below 2.x):
- sudo gem install bundler --no-ri --no-rdoc
+```sh
+sudo gem install bundler --no-document --version '< 2'
+```
## 3. Go
@@ -151,81 +185,91 @@ GitLab we need a Go compiler. The instructions below assume you use 64-bit
Linux. You can find downloads for other platforms at the [Go download
page](https://golang.org/dl).
- # Remove former Go installation folder
- sudo rm -rf /usr/local/go
-
- curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
- echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
- sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
- rm go1.10.3.linux-amd64.tar.gz
+```sh
+# Remove former Go installation folder
+sudo rm -rf /usr/local/go
+
+curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
+echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
+sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
+rm go1.10.3.linux-amd64.tar.gz
+```
## 4. Node
-Since GitLab 8.17, GitLab requires the use of Node to compile javascript
-assets, and Yarn to manage javascript dependencies. The current minimum
-requirements for these are node >= v6.0.0 and yarn >= v1.2.0. In many distros
+Since GitLab 8.17, GitLab requires the use of Node to compile JavaScript
+assets, and Yarn to manage JavaScript dependencies. The current minimum
+requirements for these are:
+
+- `node` >= v8.10.0.
+- `yarn` >= v1.10.0.
+
+In many distros,
the versions provided by the official package repositories are out of date, so
we'll need to install through the following commands:
- # install node v8.x
- curl --location https://deb.nodesource.com/setup_8.x | sudo bash -
- sudo apt-get install -y nodejs
-
- curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
- echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
- sudo apt-get update
- sudo apt-get install yarn
+```sh
+# install node v8.x
+curl --location https://deb.nodesource.com/setup_8.x | sudo bash -
+sudo apt-get install -y nodejs
+
+curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+sudo apt-get update
+sudo apt-get install yarn
+```
Visit the official websites for [node](https://nodejs.org/en/download/package-manager/) and [yarn](https://yarnpkg.com/en/docs/install/) if you have any trouble with these steps.
-## 5. System Users
+## 5. System users
Create a `git` user for GitLab:
- sudo adduser --disabled-login --gecos 'GitLab' git
+```sh
+sudo adduser --disabled-login --gecos 'GitLab' git
+```
## 6. Database
-We recommend using a PostgreSQL database. For MySQL check the
-[MySQL setup guide](database_mysql.md).
+We recommend using a PostgreSQL database. For MySQL, see the [MySQL setup guide](database_mysql.md).
-> **Note**: because we need to make use of extensions and concurrent index removal,
-you need at least PostgreSQL 9.2.
+NOTE: **Note:**
+Because we need to make use of extensions and concurrent index removal, you need at least PostgreSQL 9.2.
1. Install the database packages:
- ```bash
+ ```sh
sudo apt-get install -y postgresql postgresql-client libpq-dev postgresql-contrib
```
1. Create a database user for GitLab:
- ```bash
+ ```sh
sudo -u postgres psql -d template1 -c "CREATE USER git CREATEDB;"
```
1. Create the `pg_trgm` extension (required for GitLab 8.6+):
- ```bash
+ ```sh
sudo -u postgres psql -d template1 -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
```
1. Create the GitLab production database and grant all privileges on database:
- ```bash
+ ```sh
sudo -u postgres psql -d template1 -c "CREATE DATABASE gitlabhq_production OWNER git;"
```
1. Try connecting to the new database with the new user:
- ```bash
+ ```sh
sudo -u git -H psql -d gitlabhq_production
```
1. Check if the `pg_trgm` extension is enabled:
- ```bash
+ ```sh
SELECT true AS enabled
FROM pg_available_extensions
WHERE name = 'pg_trgm'
@@ -243,7 +287,7 @@ you need at least PostgreSQL 9.2.
1. Quit the database session:
- ```bash
+ ```sh
gitlabhq_production> \q
```
@@ -251,7 +295,7 @@ you need at least PostgreSQL 9.2.
GitLab requires at least Redis 2.8.
-If you are using Debian 8 or Ubuntu 14.04 and up, then you can simply install
+If you are using Debian 8 or Ubuntu 14.04 and up, you can simply install
Redis 2.8 with:
```sh
@@ -262,7 +306,7 @@ If you are using Debian 7 or Ubuntu 12.04, follow the special documentation
on [an alternate Redis installation](redis.md). Once done, follow the rest of
the guide here.
-```
+```sh
# Configure redis to use sockets
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig
@@ -294,146 +338,175 @@ sudo usermod -aG redis git
## 8. GitLab
- # We'll install GitLab into home directory of the user "git"
- cd /home/git
+```sh
+# We'll install GitLab into home directory of the user "git"
+cd /home/git
+```
### Clone the Source
- # Clone GitLab repository
- sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-6-stable gitlab
+```sh
+# Clone GitLab repository
+sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b X-Y-stable gitlab
+```
-**Note:** You can change `11-6-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+Make sure to replace `X-Y-stable` with the stable branch that matches the
+version you want to install. For example, if you want to install 11.8 you would
+use the branch name `11-8-stable`.
+
+CAUTION: **Caution:**
+You can change `X-Y-stable` to `master` if you want the *bleeding edge* version, but never install `master` on a production server!
### Configure It
- # Go to GitLab installation folder
- cd /home/git/gitlab
+```sh
+# Go to GitLab installation folder
+cd /home/git/gitlab
- # Copy the example GitLab config
- sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml
+# Copy the example GitLab config
+sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml
- # Update GitLab config file, follow the directions at top of file
- sudo -u git -H editor config/gitlab.yml
+# Update GitLab config file, follow the directions at top of file
+sudo -u git -H editor config/gitlab.yml
- # Copy the example secrets file
- sudo -u git -H cp config/secrets.yml.example config/secrets.yml
- sudo -u git -H chmod 0600 config/secrets.yml
+# Copy the example secrets file
+sudo -u git -H cp config/secrets.yml.example config/secrets.yml
+sudo -u git -H chmod 0600 config/secrets.yml
- # Make sure GitLab can write to the log/ and tmp/ directories
- sudo chown -R git log/
- sudo chown -R git tmp/
- sudo chmod -R u+rwX,go-w log/
- sudo chmod -R u+rwX tmp/
+# Make sure GitLab can write to the log/ and tmp/ directories
+sudo chown -R git log/
+sudo chown -R git tmp/
+sudo chmod -R u+rwX,go-w log/
+sudo chmod -R u+rwX tmp/
- # Make sure GitLab can write to the tmp/pids/ and tmp/sockets/ directories
- sudo chmod -R u+rwX tmp/pids/
- sudo chmod -R u+rwX tmp/sockets/
+# Make sure GitLab can write to the tmp/pids/ and tmp/sockets/ directories
+sudo chmod -R u+rwX tmp/pids/
+sudo chmod -R u+rwX tmp/sockets/
- # Create the public/uploads/ directory
- sudo -u git -H mkdir public/uploads/
+# Create the public/uploads/ directory
+sudo -u git -H mkdir public/uploads/
- # Make sure only the GitLab user has access to the public/uploads/ directory
- # now that files in public/uploads are served by gitlab-workhorse
- sudo chmod 0700 public/uploads
+# Make sure only the GitLab user has access to the public/uploads/ directory
+# now that files in public/uploads are served by gitlab-workhorse
+sudo chmod 0700 public/uploads
- # Change the permissions of the directory where CI job traces are stored
- sudo chmod -R u+rwX builds/
+# Change the permissions of the directory where CI job traces are stored
+sudo chmod -R u+rwX builds/
- # Change the permissions of the directory where CI artifacts are stored
- sudo chmod -R u+rwX shared/artifacts/
+# Change the permissions of the directory where CI artifacts are stored
+sudo chmod -R u+rwX shared/artifacts/
- # Change the permissions of the directory where GitLab Pages are stored
- sudo chmod -R ug+rwX shared/pages/
+# Change the permissions of the directory where GitLab Pages are stored
+sudo chmod -R ug+rwX shared/pages/
- # Copy the example Unicorn config
- sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
+# Copy the example Unicorn config
+sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
- # Find number of cores
- nproc
+# Find number of cores
+nproc
- # Enable cluster mode if you expect to have a high load instance
- # Set the number of workers to at least the number of cores
- # Ex. change amount of workers to 3 for 2GB RAM server
- sudo -u git -H editor config/unicorn.rb
+# Enable cluster mode if you expect to have a high load instance
+# Set the number of workers to at least the number of cores
+# Ex. change amount of workers to 3 for 2GB RAM server
+sudo -u git -H editor config/unicorn.rb
- # Copy the example Rack attack config
- sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
+# Copy the example Rack attack config
+sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
- # Configure Git global settings for git user
- # 'autocrlf' is needed for the web editor
- sudo -u git -H git config --global core.autocrlf input
+# Configure Git global settings for git user
+# 'autocrlf' is needed for the web editor
+sudo -u git -H git config --global core.autocrlf input
- # Disable 'git gc --auto' because GitLab already runs 'git gc' when needed
- sudo -u git -H git config --global gc.auto 0
+# 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 packfile bitmaps
+sudo -u git -H git config --global repack.writeBitmaps true
- # Enable push options
- sudo -u git -H git config --global receive.advertisePushOptions true
+# Enable push options
+sudo -u git -H git config --global receive.advertisePushOptions true
- # Configure Redis connection settings
- sudo -u git -H cp config/resque.yml.example config/resque.yml
+# Configure Redis connection settings
+sudo -u git -H cp config/resque.yml.example config/resque.yml
- # Change the Redis socket path if you are not using the default Debian / Ubuntu configuration
- sudo -u git -H editor config/resque.yml
+# Change the Redis socket path if you are not using the default Debian / Ubuntu configuration
+sudo -u git -H editor config/resque.yml
+```
-**Important Note:** Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
+CAUTION: **Caution:**
+Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
-**Note:** If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
+NOTE: **Note:**
+If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
### Configure GitLab DB Settings
- # PostgreSQL only:
- sudo -u git cp config/database.yml.postgresql config/database.yml
+```sh
+# PostgreSQL only:
+sudo -u git cp config/database.yml.postgresql config/database.yml
+
+# MySQL only:
+sudo -u git cp config/database.yml.mysql config/database.yml
+
+# MySQL and remote PostgreSQL only:
+# Update username/password in config/database.yml.
+# You only need to adapt the production settings (first part).
+# If you followed the database guide then please do as follows:
+# Change 'secure password' with the value you have given to $password
+# You can keep the double quotes around the password
+sudo -u git -H editor config/database.yml
+
+# PostgreSQL and MySQL:
+# Make config/database.yml readable to git only
+sudo -u git -H chmod o-rwx config/database.yml
+```
- # MySQL only:
- sudo -u git cp config/database.yml.mysql config/database.yml
+### Install Gems
- # MySQL and remote PostgreSQL only:
- # Update username/password in config/database.yml.
- # You only need to adapt the production settings (first part).
- # If you followed the database guide then please do as follows:
- # Change 'secure password' with the value you have given to $password
- # You can keep the double quotes around the password
- sudo -u git -H editor config/database.yml
+NOTE: **Note:**
+As of Bundler 1.5.2, you can invoke `bundle install -jN` (where `N` is the number of your processor cores) and enjoy parallel gems installation with measurable difference in completion time (~60% faster). Check the number of your cores with `nproc`. For more information, see this [post](https://robots.thoughtbot.com/parallel-gem-installing-using-bundler).
- # PostgreSQL and MySQL:
- # Make config/database.yml readable to git only
- sudo -u git -H chmod o-rwx config/database.yml
+Make sure you have `bundle` (run `bundle -v`):
-### Install Gems
+- `>= 1.5.2`, because some [issues](https://devcenter.heroku.com/changelog-items/411) were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2.
+- `< 2.x`.
-**Note:** As of bundler 1.5.2, you can invoke `bundle install -jN` (where `N` the number of your processor cores) and enjoy the parallel gems installation with measurable difference in completion time (~60% faster). Check the number of your cores with `nproc`. For more information check this [post](https://robots.thoughtbot.com/parallel-gem-installing-using-bundler). First make sure you have bundler >= 1.5.2 (run `bundle -v`) as it addresses some [issues](https://devcenter.heroku.com/changelog-items/411) that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2.
-
- # For PostgreSQL (note, the option says "without ... mysql")
- sudo -u git -H bundle install --deployment --without development test mysql aws kerberos
+```sh
+# For PostgreSQL (note, the option says "without ... mysql")
+sudo -u git -H bundle install --deployment --without development test mysql aws kerberos
- # Or if you use MySQL (note, the option says "without ... postgres")
- sudo -u git -H bundle install --deployment --without development test postgres aws kerberos
+# Or if you use MySQL (note, the option says "without ... postgres")
+sudo -u git -H bundle install --deployment --without development test postgres aws kerberos
+```
-**Note:** If you want to use Kerberos for user authentication, then omit `kerberos` in the `--without` option above.
+NOTE: **Note:**
+If you want to use Kerberos for user authentication, omit `kerberos` in the `--without` option above.
### Install GitLab Shell
GitLab Shell is an SSH access and repository management software developed specially for GitLab.
- # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed):
- sudo -u git -H bundle exec rake gitlab:shell:install REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production SKIP_STORAGE_VALIDATION=true
+```sh
+# Run the installation task for gitlab-shell (replace `REDIS_URL` if needed):
+sudo -u git -H bundle exec rake gitlab:shell:install REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production SKIP_STORAGE_VALIDATION=true
- # By default, the gitlab-shell config is generated from your main GitLab config.
- # You can review (and modify) the gitlab-shell config as follows:
- sudo -u git -H editor /home/git/gitlab-shell/config.yml
+# By default, the gitlab-shell config is generated from your main GitLab config.
+# You can review (and modify) the gitlab-shell config as follows:
+sudo -u git -H editor /home/git/gitlab-shell/config.yml
+```
-**Note:** If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
+NOTE: **Note:**
+If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
-**Note:** Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in /etc/hosts ("127.0.0.1 hostname"). This might be necessary for example if you set up GitLab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)".
+NOTE: **Note:**
+Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in `/etc/hosts` ("127.0.0.1 hostname"). This might be necessary, for example, if you set up GitLab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)".
-**Note:** GitLab Shell application startup time can be greatly reduced by disabling RubyGems. This can be done in several manners:
+NOTE: **Note:**
+GitLab Shell application startup time can be greatly reduced by disabling RubyGems. This can be done in several ways:
-* Export `RUBYOPT=--disable-gems` environment variable for the processes
-* Compile Ruby with `configure --disable-rubygems` to disable RubyGems by default. Not recommended for system-wide Ruby.
-* Omnibus GitLab [replaces the *shebang* line of the `gitlab-shell/bin/*` scripts](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1707)
+- Export `RUBYOPT=--disable-gems` environment variable for the processes.
+- Compile Ruby with `configure --disable-rubygems` to disable RubyGems by default. Not recommended for system-wide Ruby.
+- Omnibus GitLab [replaces the *shebang* line of the `gitlab-shell/bin/*` scripts](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1707).
### Install gitlab-workhorse
@@ -441,57 +514,74 @@ GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/). The
following command-line will install GitLab-Workhorse in `/home/git/gitlab-workhorse`
which is the recommended location.
- sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
+```sh
+sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
+```
You can specify a different Git repository by providing it as an extra parameter:
- sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse,https://example.com/gitlab-workhorse.git]" RAILS_ENV=production
+```sh
+sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse,https://example.com/gitlab-workhorse.git]" RAILS_ENV=production
+```
-### Install gitlab-pages
+### Install GitLab Pages
-GitLab-Pages uses [GNU Make](https://www.gnu.org/software/make/). This step is optional and only needed if you wish to host static sites from within GitLab. The following commands will install GitLab-Pages in `/home/git/gitlab-pages`. For additional setup steps, please consult the [administration guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/administration/pages/source.md) for your version of GitLab as the GitLab Pages daemon can be ran several different ways.
+GitLab Pages uses [GNU Make](https://www.gnu.org/software/make/). This step is optional and only needed if you wish to host static sites from within GitLab. The following commands will install GitLab Pages in `/home/git/gitlab-pages`. For additional setup steps, consult the [administration guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/administration/pages/source.md) for your version of GitLab as the GitLab Pages daemon can be run several different ways.
- cd /home/git
- sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-pages.git
- cd gitlab-pages
- sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
- sudo -u git -H make
+```sh
+cd /home/git
+sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-pages.git
+cd gitlab-pages
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
+sudo -u git -H make
+```
### Install Gitaly
- # Fetch Gitaly source with Git and compile with Go
- sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories]" RAILS_ENV=production
+```sh
+# Fetch Gitaly source with Git and compile with Go
+sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories]" RAILS_ENV=production
+```
You can specify a different Git repository by providing it as an extra parameter:
- sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories,https://example.com/gitaly.git]" RAILS_ENV=production
+```sh
+sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories,https://example.com/gitaly.git]" RAILS_ENV=production
+```
Next, make sure gitaly configured:
- # Restrict Gitaly socket access
- sudo chmod 0700 /home/git/gitlab/tmp/sockets/private
- sudo chown git /home/git/gitlab/tmp/sockets/private
+```sh
+# Restrict Gitaly socket access
+sudo chmod 0700 /home/git/gitlab/tmp/sockets/private
+sudo chown git /home/git/gitlab/tmp/sockets/private
- # If you are using non-default settings you need to update config.toml
- cd /home/git/gitaly
- sudo -u git -H editor config.toml
+# If you are using non-default settings you need to update config.toml
+cd /home/git/gitaly
+sudo -u git -H editor config.toml
+```
For more information about configuring Gitaly see
[doc/administration/gitaly](../administration/gitaly).
### Initialize Database and Activate Advanced Features
- sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
- # Type 'yes' to create the database tables.
+```sh
+sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
+# Type 'yes' to create the database tables.
- # or you can skip the question by adding force=yes
- sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production force=yes
+# or you can skip the question by adding force=yes
+sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production force=yes
- # When done you see 'Administrator account created:'
+# When done you see 'Administrator account created:'
+```
-**Note:** You can set the Administrator/root password and e-mail by supplying them in environmental variables, `GITLAB_ROOT_PASSWORD` and `GITLAB_ROOT_EMAIL` respectively, as seen below. If you don't set the password (and it is set to the default one) please wait with exposing GitLab to the public internet until the installation is done and you've logged into the server the first time. During the first login you'll be forced to change the default password.
+NOTE: **Note:**
+You can set the Administrator/root password and e-mail by supplying them in environmental variables, `GITLAB_ROOT_PASSWORD` and `GITLAB_ROOT_EMAIL` respectively, as seen below. If you don't set the password (and it is set to the default one), wait to expose GitLab to the public internet until the installation is done and you've logged into the server the first time. During the first login, you'll be forced to change the default password.
- sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=youremail
+```sh
+sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=youremail
+```
### Secure secrets.yml
@@ -503,71 +593,93 @@ Otherwise your secrets are exposed if one of your backups is compromised.
Download the init script (will be `/etc/init.d/gitlab`):
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```sh
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
And if you are installing with a non-default folder or user copy and edit the defaults file:
- sudo cp lib/support/init.d/gitlab.default.example /etc/default/gitlab
+```sh
+sudo cp lib/support/init.d/gitlab.default.example /etc/default/gitlab
+```
-If you installed GitLab in another directory or as a user other than the default you should change these settings in `/etc/default/gitlab`. Do not edit `/etc/init.d/gitlab` as it will be changed on upgrade.
+If you installed GitLab in another directory or as a user other than the default, you should change these settings in `/etc/default/gitlab`. Do not edit `/etc/init.d/gitlab` as it will be changed on upgrade.
Make GitLab start on boot:
- sudo update-rc.d gitlab defaults 21
+```sh
+sudo update-rc.d gitlab defaults 21
+```
### Set up Logrotate
- sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
+```sh
+sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
+```
### Check Application Status
Check if GitLab and its environment are configured correctly:
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
+```sh
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
### Compile GetText PO files
- sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
+```sh
+sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
+```
### Compile Assets
- sudo -u git -H yarn install --production --pure-lockfile
- sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+```sh
+sudo -u git -H yarn install --production --pure-lockfile
+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+```
### Start Your GitLab Instance
- sudo service gitlab start
- # or
- sudo /etc/init.d/gitlab restart
+```sh
+sudo service gitlab start
+# or
+sudo /etc/init.d/gitlab restart
+```
## 9. Nginx
-**Note:** Nginx is the officially supported web server for GitLab. If you cannot or do not want to use Nginx as your web server, have a look at the [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/).
+NOTE: **Note:**
+Nginx is the officially supported web server for GitLab. If you cannot or do not want to use Nginx as your web server, see [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/).
### Installation
- sudo apt-get install -y nginx
+```sh
+sudo apt-get install -y nginx
+```
### Site Configuration
Copy the example site config:
- sudo cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab
- sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
+```sh
+sudo cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab
+sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
+```
-Make sure to edit the config file to match your setup. Also, ensure that you match your paths to GitLab, especially if installing for a user other than the 'git' user:
+Make sure to edit the config file to match your setup. Also, ensure that you match your paths to GitLab, especially if installing for a user other than the `git` user:
- # Change YOUR_SERVER_FQDN to the fully-qualified
- # domain name of your host serving GitLab.
- #
- # Remember to match your paths to GitLab, especially
- # if installing for a user other than 'git'.
- #
- # If using Ubuntu default nginx install:
- # either remove the default_server from the listen line
- # or else sudo rm -f /etc/nginx/sites-enabled/default
- sudo editor /etc/nginx/sites-available/gitlab
+```sh
+# Change YOUR_SERVER_FQDN to the fully-qualified
+# domain name of your host serving GitLab.
+#
+# Remember to match your paths to GitLab, especially
+# if installing for a user other than 'git'.
+#
+# If using Ubuntu default nginx install:
+# either remove the default_server from the listen line
+# or else sudo rm -f /etc/nginx/sites-enabled/default
+sudo editor /etc/nginx/sites-available/gitlab
+```
If you intend to enable GitLab pages, there is a separate Nginx config you need
to use. Read all about the needed configuration at the
@@ -579,13 +691,22 @@ to use. Read all about the needed configuration at the
Validate your `gitlab` or `gitlab-ssl` Nginx config file with the following command:
- sudo nginx -t
+```sh
+sudo nginx -t
+```
You should receive `syntax is okay` and `test is successful` messages. If you receive errors check your `gitlab` or `gitlab-ssl` Nginx config file for typos, etc. as indicated in the error message given.
+NOTE: **Note:**
+Verify that the installed version is greater than 1.12.1 by running `nginx -v`. If it's lower, you may receive the error below:
+`nginx: [emerg] unknown "start$temp=[filtered]$rest" variable
+nginx: configuration file /etc/nginx/nginx.conf test failed`
+
### Restart
- sudo service nginx restart
+```sh
+sudo service nginx restart
+```
## Done!
@@ -593,9 +714,11 @@ You should receive `syntax is okay` and `test is successful` messages. If you re
To make sure you didn't miss anything run a more thorough check with:
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```sh
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
-If all items are green, then congratulations on successfully installing GitLab!
+If all items are green, congratulations on successfully installing GitLab!
NOTE: Supply `SANITIZE=true` environment variable to `gitlab:check` to omit project names from the output of the check command.
@@ -637,11 +760,11 @@ To use GitLab with HTTPS:
1. Update `ssl_certificate` and `ssl_certificate_key`.
1. Review the configuration file and consider applying other security and performance enhancing features.
-Using a self-signed certificate is discouraged but if you must use it follow the normal directions then:
+Using a self-signed certificate is discouraged but if you must use it, follow the normal directions. Then:
1. Generate a self-signed SSL certificate:
- ```
+ ```sh
mkdir -p /etc/nginx/ssl/
cd /etc/nginx/ssl/
sudo openssl req -newkey rsa:2048 -x509 -nodes -days 3560 -out gitlab.crt -keyout gitlab.key
@@ -655,16 +778,16 @@ See the ["Reply by email" documentation](../administration/reply_by_email.md) fo
### LDAP Authentication
-You can configure LDAP authentication in `config/gitlab.yml`. Please restart GitLab after editing this file.
+You can configure LDAP authentication in `config/gitlab.yml`. Restart GitLab after editing this file.
### Using Custom Omniauth Providers
-See the [omniauth integration document](../integration/omniauth.md)
+See the [omniauth integration document](../integration/omniauth.md).
### Build your projects
-GitLab can build your projects. To enable that feature you need GitLab Runners to do that for you.
-Checkout the [GitLab Runner section](https://about.gitlab.com/gitlab-ci/#gitlab-runner) to install it
+GitLab can build your projects. To enable that feature, you need GitLab Runners to do that for you.
+See the [GitLab Runner section](https://about.gitlab.com/product/continuous-integration/#gitlab-runner) to install it.
### Adding your Trusted Proxies
@@ -680,37 +803,45 @@ for the changes to take effect.
If you'd like to connect to a Redis server on a non-standard port or on a different host, you can configure its connection string via the `config/resque.yml` file.
- # example
- production:
- url: redis://redis.example.tld:6379
+```
+# example
+production:
+ url: redis://redis.example.tld:6379
+```
-If you want to connect the Redis server via socket, then use the "unix:" URL scheme and the path to the Redis socket file in the `config/resque.yml` file.
+If you want to connect the Redis server via socket, use the "unix:" URL scheme and the path to the Redis socket file in the `config/resque.yml` file.
- # example
- production:
- url: unix:/path/to/redis/socket
+```
+# example
+production:
+ url: unix:/path/to/redis/socket
+```
Also you can use environment variables in the `config/resque.yml` file:
- # example
- production:
- url: <%= ENV.fetch('GITLAB_REDIS_URL') %>
+```
+# example
+production:
+ url: <%= ENV.fetch('GITLAB_REDIS_URL') %>
+```
### Custom SSH Connection
If you are running SSH on a non-standard port, you must change the GitLab user's SSH config.
- # Add to /home/git/.ssh/config
- host localhost # Give your setup a name (here: override localhost)
- user git # Your remote git user
- port 2222 # Your port number
- hostname 127.0.0.1; # Your server name or IP
+```
+# Add to /home/git/.ssh/config
+host localhost # Give your setup a name (here: override localhost)
+ user git # Your remote git user
+ port 2222 # Your port number
+ hostname 127.0.0.1; # Your server name or IP
+```
You also need to change the corresponding options (e.g. `ssh_user`, `ssh_host`, `admin_uri`) in the `config\gitlab.yml` file.
### Additional Markup Styles
-Apart from the always supported markdown style there are other rich text files that GitLab can display. But you might have to install a dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information.
+Apart from the always supported markdown style, there are other rich text files that GitLab can display. But you might have to install a dependency to do so. See the [github-markup gem README](https://github.com/gitlabhq/markup#markups) for more information.
## Troubleshooting
diff --git a/doc/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
index 26ced45de7b..9db246b3eb3 100644
--- a/doc/install/kubernetes/gitlab_chart.md
+++ b/doc/install/kubernetes/gitlab_chart.md
@@ -5,7 +5,7 @@ This is the official way to install GitLab on a cloud native environment.
NOTE: **Kubernetes experience required:**
Our Helm charts are recommended for those who are familiar with Kubernetes.
If you're not sure if Kubernetes is for you, our
-[Omnibus GitLab packages](../README.md#install-gitlab-using-the-omnibus-gitlab-package-recommended)
+[Omnibus GitLab packages](../README.md#installing-gitlab-using-the-omnibus-gitlab-package-recommended)
are mature, scalable, support [high availability](../../administration/high_availability/README.md)
and are used today on GitLab.com.
It is not necessary to have GitLab installed on Kubernetes in order to use [GitLab Kubernetes integration](https://docs.gitlab.com/ee/user/project/clusters/index.html).
diff --git a/doc/install/kubernetes/gitlab_omnibus.md b/doc/install/kubernetes/gitlab_omnibus.md
index 498b702cab1..c0cb7694e91 100644
--- a/doc/install/kubernetes/gitlab_omnibus.md
+++ b/doc/install/kubernetes/gitlab_omnibus.md
@@ -4,10 +4,10 @@ CAUTION: **Caution:**
This chart is **deprecated**. We recommend using the [`gitlab` chart](gitlab_chart.md)
instead. A comparison of the two charts is available in [this video](https://youtu.be/Z6jWR8Z8dv8).
-For more information on available GitLab Helm Charts, see the [charts overview](index.md#chart-overview).
+For more information on available GitLab Helm Charts, see [Installing GitLab on Kubernetes](index.md).
- This GitLab-Omnibus chart has been tested on Google Kubernetes Engine and Azure Container Service.
-- This work is based partially on: https://github.com/lwolf/kubernetes-gitlab/. GitLab would like to thank Sergey Nuzhdin for his work.
+- This work is based partially on: <https://github.com/lwolf/kubernetes-gitlab/>. GitLab would like to thank Sergey Nuzhdin for his work.
## Introduction
@@ -32,14 +32,14 @@ The deployment includes:
## Limitations
[High Availability](../../administration/high_availability/README.md) and
-[Geo](https://docs.gitlab.com/ee/gitlab-geo/README.html) are not supported.
+[Geo](https://docs.gitlab.com/ee/administration/geo/replication/index.html) are not supported.
## Requirements
- _At least_ 4 GB of RAM available on your cluster. 41GB of storage and 2 CPU are also required.
- Kubernetes 1.4+ with Beta APIs enabled
- [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) provisioner support in the underlying infrastructure
-- A [wildcard DNS entry](#networking-prerequisites), which resolves to the external IP address
+- A [wildcard DNS entry](#networking-requirements), which resolves to the external IP address
- The `kubectl` CLI installed locally and authenticated for the cluster
- The [Helm client](https://github.com/kubernetes/helm/blob/master/docs/quickstart.md) installed locally on your machine
@@ -52,7 +52,7 @@ and [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/).
To support the GitLab services and dynamic environments, a wildcard DNS entry
is required which resolves to the [load balancer](#load-balancer-ip) or
-[external IP](#external-ip). Configuration of the DNS entry will depend upon
+[external IP](#external-ip-recommended). Configuration of the DNS entry will depend upon
the DNS service being used.
#### External IP (recommended)
@@ -84,13 +84,13 @@ to configure the Wildcard DNS entry. For more information on creating a wildcard
DNS entry, consult the documentation for the DNS server you are using.
For production deployments of GitLab, we strongly recommend using a
-[external IP](#external-ip).
+[external IP](#external-ip-recommended).
## Configuring and Installing GitLab
For most installations, two parameters are required:
-- `baseDomain`: the [base domain](#networking-prerequisites) of the wildcard host entry. For example, `mycompany.io` if the wild card entry is `*.mycompany.io`.
+- `baseDomain`: the [base domain](#networking-requirements) of the wildcard host entry. For example, `mycompany.io` if the wild card entry is `*.mycompany.io`.
- `legoEmail`: Email address to use when requesting new SSL certificates from Let's Encrypt.
Other common configuration options:
@@ -105,7 +105,7 @@ For additional configuration options, consult the
### Choosing a different GitLab release version
-The version of GitLab installed is based on the `gitlab` setting (see [section](#choosing-gitlab-edition) above), and
+The version of GitLab installed is based on the `gitlab` setting (see [section](#configuring-and-installing-gitLab) above), and
the value of the corresponding helm setting: `gitlabCEImage` or `gitabEEImage`.
```yaml
diff --git a/doc/install/kubernetes/gitlab_runner_chart.md b/doc/install/kubernetes/gitlab_runner_chart.md
index 3c2f883f29d..68b2a146115 100644
--- a/doc/install/kubernetes/gitlab_runner_chart.md
+++ b/doc/install/kubernetes/gitlab_runner_chart.md
@@ -11,7 +11,7 @@ This chart configures the Runner to:
- For each new job it receives from [GitLab CI](https://about.gitlab.com/features/gitlab-ci-cd/), it will provision a
new pod within the specified namespace to run it.
-For more information on available GitLab Helm Charts, please see our [overview](index.md#chart-overview).
+For more information on available GitLab Helm Charts, please see our [overview](index.md).
## Prerequisites
@@ -33,7 +33,7 @@ In order for GitLab Runner to function, your config file **must** specify the fo
- `gitlabUrl` - the GitLab Server URL (with protocol) to register the runner against
- `runnerRegistrationToken` - The Registration Token for adding new Runners to the GitLab Server. This must be
- retrieved from your GitLab Instance. See the [GitLab Runner Documentation](../../ci/runners/README.md#creating-and-registering-a-runner) for more information.
+ retrieved from your GitLab Instance. See the [GitLab Runner Documentation](../../ci/runners/README.md) for more information.
Unless you need to specify additional configuration, you are [ready to install](#installing-gitlab-runner-using-the-helm-chart).
@@ -51,7 +51,7 @@ gitlabUrl: http://gitlab.your-domain.com/
## The Registration Token for adding new Runners to the GitLab Server. This must
## be retrieved from your GitLab Instance.
-## ref: https://docs.gitlab.com/ce/ci/runners/README.html#creating-and-registering-a-runner
+## ref: https://docs.gitlab.com/ee/ci/runners/README.html
##
runnerRegistrationToken: ""
@@ -227,7 +227,7 @@ helm repo add gitlab https://charts.gitlab.io
helm init
```
-Once you [have configured](#configuration) GitLab Runner in your `values.yml` file,
+Once you [have configured](#configuring-gitlab-runner-using-the-helm-chart) GitLab Runner in your `values.yml` file,
run the following:
```bash
@@ -236,7 +236,7 @@ helm install --namespace <NAMESPACE> --name gitlab-runner -f <CONFIG_VALUES_FILE
- `<NAMESPACE>` is the Kubernetes namespace where you want to install the GitLab Runner.
- `<CONFIG_VALUES_FILE>` is the path to values file containing your custom configuration. See the
- [Configuration](#configuration) section to create it.
+ [Configuring GitLab Runner using the Helm Chart](#configuring-gitlab-runner-using-the-helm-chart) section to create it.
## Updating GitLab Runner using the Helm Chart
@@ -247,11 +247,12 @@ helm upgrade --namespace <NAMESPACE> -f <CONFIG_VALUES_FILE> <RELEASE-NAME> gitl
```
Where:
+
- `<NAMESPACE>` is the Kubernetes namespace where GitLab Runner is installed
- `<CONFIG_VALUES_FILE>` is the path to values file containing your custom configuration. See the
- [Configuration](#configuration) section to create it.
+ [Configuring GitLab Runner using the Helm Chart](#configuring-gitlab-runner-using-the-helm-chart) section to create it.
- `<RELEASE-NAME>` is the name you gave the chart when installing it.
- In the [Install section](#installing) we called it `gitlab-runner`.
+ In the [Installing GitLab Runner using the Helm Chart](#installing-gitlab-runner-using-the-helm-chart) section, we called it `gitlab-runner`.
## Uninstalling GitLab Runner using the Helm Chart
@@ -265,4 +266,4 @@ where:
- `<NAMESPACE>` is the Kubernetes namespace where GitLab Runner is installed
- `<RELEASE-NAME>` is the name you gave the chart when installing it.
- In the [Install section](#installing) we called it `gitlab-runner`.
+ In the [Installing GitLab Runner using the Helm Chart](#installing-gitlab-runner-using-the-helm-chart) section, we called it `gitlab-runner`.
diff --git a/doc/install/kubernetes/index.md b/doc/install/kubernetes/index.md
index 281630174e7..ecc956d04e9 100644
--- a/doc/install/kubernetes/index.md
+++ b/doc/install/kubernetes/index.md
@@ -7,7 +7,7 @@ description: 'Read through the different methods to deploy GitLab on Kubernetes.
NOTE: **Kubernetes experience required:**
Our Helm charts are recommended for those who are familiar with Kubernetes.
If you're not sure if Kubernetes is for you, our
-[Omnibus GitLab packages](../README.md#install-gitlab-using-the-omnibus-gitlab-package-recommended)
+[Omnibus GitLab packages](../README.md#installing-gitlab-using-the-omnibus-gitlab-package-recommended)
are mature, scalable, support [high availability](../../administration/high_availability/README.md)
and are used today on GitLab.com.
It is not necessary to have GitLab installed on Kubernetes in order to use [GitLab Kubernetes integration](https://docs.gitlab.com/ee/user/project/clusters/index.html).
diff --git a/doc/install/kubernetes/preparation/eks.md b/doc/install/kubernetes/preparation/eks.md
index c40177c4302..ea3b075dd82 100644
--- a/doc/install/kubernetes/preparation/eks.md
+++ b/doc/install/kubernetes/preparation/eks.md
@@ -5,6 +5,7 @@ There are a few nuances to Amazon EKS which are important to be aware of, when d
## Persistent volume management
There are two methods to manage volume claims on Kubernetes:
+
1. Manually creating each persistent volume (recommended on EKS)
1. Utilizing dynamic provisioning to automatically create the persistent volumes
@@ -26,7 +27,7 @@ With EKS, there are a few important details to keep in mind:
The easiest way to solve this and still utilize dynamic provisioning is to utilize, or create, a Storage Class that is locked to a specific zone.
-> **Note**: Restricting volumes to specific zone will cause GitLab and any other application using this Storage Class to only reside in that zone. For multiple zone support, utilize [manually provisioned volumes](#manual-provisioning-of-volumes).
+> **Note**: Restricting volumes to specific zone will cause GitLab and any other application using this Storage Class to only reside in that zone. For multiple zone support, utilize [manually provisioned volumes](#manual-provisioning-of-volumes-recommended).
To create the storage class, download and edit Amazon EKS's [sample Storage Class](https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html) and add the following parameter:
diff --git a/doc/install/kubernetes/preparation/networking.md b/doc/install/kubernetes/preparation/networking.md
index 34a6130de27..b9fb9a7399f 100644
--- a/doc/install/kubernetes/preparation/networking.md
+++ b/doc/install/kubernetes/preparation/networking.md
@@ -12,7 +12,7 @@ To support the GitLab services and dynamic environments, a wildcard DNS entry is
To provision an external IP on GCP and Azure, simply request a new address from the Networking section. Ensure that the region matches the region your container cluster is created in. Note, it is important that the IP is not assigned at this point in time. It will be automatically assigned once the Helm chart is installed, to the Load Balancer.
-Set `global.hosts.externalIP` to this IP address when [deploying GitLab](../gitlab_chart.md#configuring-and-installing-gitlab).
+Set `global.hosts.externalIP` to this IP address when [deploying GitLab](../gitlab_chart.md#installing-gitlab-using-the-helm-chart).
Then, create a [wildcard DNS record](#wildcard-dns-entry) which resolves to this IP address.
@@ -35,4 +35,4 @@ Please consult the documentation for your DNS service for more information on cr
- [Google Domains](https://support.google.com/domains/answer/3290350?hl=en)
- [GoDaddy](https://www.godaddy.com/help/add-an-a-record-19238)
-Set `global.hosts.domain` to this DNS name when [deploying GitLab](../gitlab_chart.md#configuring-and-installing-gitlab).
+Set `global.hosts.domain` to this DNS name when [deploying GitLab](../gitlab_chart.md#installing-gitlab-using-the-helm-chart).
diff --git a/doc/install/kubernetes/preparation/tiller.md b/doc/install/kubernetes/preparation/tiller.md
index 107df074b3b..684df14ac2c 100644
--- a/doc/install/kubernetes/preparation/tiller.md
+++ b/doc/install/kubernetes/preparation/tiller.md
@@ -7,7 +7,7 @@ Helm consists of two parts, the `helm` client and a `tiller` server inside Kuber
NOTE: **Note:**
If you are not able to run Tiller in your cluster, for example on OpenShift, it
-is possible to use [Tiller locally](https://gitlab.com/charts/gitlab/tree/master/doc/helm#local-tiller)
+is possible to use [Tiller locally](https://docs.gitlab.com/charts/installation/tools.html#local-tiller)
and avoid deploying it into the cluster. This should only be used when Tiller
cannot be normally deployed.
@@ -15,7 +15,7 @@ cannot be normally deployed.
Tiller is deployed into the cluster and interacts with the Kubernetes API to deploy your applications. If role based access control (RBAC) is enabled, Tiller will need to be [granted permissions](#preparing-for-helm-with-rbac) to allow it to talk to the Kubernetes API.
-If RBAC is not enabled, skip to [initalizing Helm](#initialize-helm).
+If RBAC is not enabled, skip to [initializing Helm](#initialize-helm).
If you are not sure whether RBAC is enabled in your cluster, or to learn more, read through our [RBAC documentation](rbac.md).
@@ -54,19 +54,25 @@ Some clusters require authentication to use `kubectl` to create the Tiller roles
#### Upload the RBAC config as an admin user (GKE)
-For GKE, you need to grab the admin credentials:
+For GKE, you need to obtain the admin credentials. This command will output the admin password:
```
gcloud container clusters describe <cluster-name> --zone <zone> --project <project-id> --format='value(masterAuth.password)'
```
-This command will output the admin password. We need the password to authenticate with `kubectl` and create the role.
+Use the admin password to set the admin credentials. Replace the password value below with the output value from the above step:
```
-kubectl --username=admin --password=xxxxxxxxxxxxxx create -f rbac-config.yaml
+kubectl config set-credentials admin --username=admin --password=xxxxxxxxxxxxxx
```
-#### Upload the RBAC config (Other clusters)
+Once credentials have been set, create the role:
+
+```
+kubectl --user=admin create -f rbac-config.yaml
+```
+
+#### Upload the RBAC config (Non-GKE clusters)
For other clusters like Amazon EKS, you can directly upload the RBAC configuration.
diff --git a/doc/install/kubernetes/preparation/tools_installation.md b/doc/install/kubernetes/preparation/tools_installation.md
index 210bc2f9e58..d2f7a69a0af 100644
--- a/doc/install/kubernetes/preparation/tools_installation.md
+++ b/doc/install/kubernetes/preparation/tools_installation.md
@@ -16,4 +16,4 @@ You can get Helm from the project's [releases page](https://github.com/kubernete
# Next steps
-Once installed, proceed to the next [installation step](../gitlab_chart.md#prerequisites).
+Once installed, proceed to the next [installation step](../gitlab_chart.md#installing-gitlab-using-the-helm-chart).
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index 4c88b6f97fc..77bd9e9f7a9 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -8,6 +8,12 @@ date: 2016-06-28
# How to install GitLab on OpenShift Origin 3
+CAUTION: **Deprecated:**
+This article is deprecated. Use the official Kubernetes Helm charts for
+installing GitLab to OpenShift. Check out the
+[official installation docs](https://docs.gitlab.com/charts/installation/cloud/openshift.html)
+for details.
+
## Introduction
[OpenShift Origin][openshift] is an open source container application
@@ -18,7 +24,7 @@ In this tutorial, we will see how to deploy GitLab in OpenShift using GitLab's
official Docker image while getting familiar with the web interface and CLI
tools that will help us achieve our goal.
-For a video demonstration on installing GitLab on Openshift, check the article [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/).
+For a video demonstration on installing GitLab on OpenShift, check the article [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/).
---
@@ -518,7 +524,7 @@ PaaS and managing your applications with the ease of containers.
[templates]: https://docs.openshift.org/latest/architecture/core_concepts/templates.html "Documentation - OpenShift templates"
[old-post]: https://blog.openshift.com/deploy-gitlab-openshift/ "Old post - Deploy GitLab on OpenShift"
[line]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/658c065c8d022ce858dd63eaeeadb0b2ddc8deea/docker/openshift-template.json#L239 "GitLab - OpenShift template"
-[oc-gh]: https://github.com/openshift/origin/releases/tag/v1.3.0 "Openshift 1.3.0 release on GitHub"
+[oc-gh]: https://github.com/openshift/origin/releases/tag/v1.3.0 "OpenShift Origin 1.3.0 release on GitHub"
[ha]: ../../administration/high_availability/gitlab.html "Documentation - GitLab High Availability"
[replicas]: https://docs.openshift.org/latest/architecture/core_concepts/deployments.html#replication-controllers "Documentation - Replication controller"
[autoscaling]: https://docs.openshift.org/latest/dev_guide/pod_autoscaling.html "Documentation - Autoscale"
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 1b7e0d1d0ab..8ab7189c2a6 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -33,7 +33,7 @@ Please consider using a virtual machine to run GitLab.
## Ruby versions
-GitLab requires Ruby (MRI) 2.3. Support for Ruby versions below 2.3 (2.1, 2.2) will stop with GitLab 8.13.
+GitLab requires Ruby (MRI) 2.5. Support for Ruby versions below 2.5 (2.3, 2.4) will stop with GitLab 11.6.
You will have to use the standard MRI implementation of Ruby.
We love [JRuby](https://www.jruby.org/) and [Rubinius](https://rubinius.com) but GitLab
@@ -51,6 +51,8 @@ Apart from a local hard drive you can also mount a volume that supports the netw
If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab.
+NOTE: **Note:** Since file system performance may affect GitLab's overall performance, we do not recommend using EFS for storage. See the [relevant documentation](../administration/high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs) for more details.
+
### CPU
- 1 core supports up to 100 users but the application can be a bit slower due to having all workers and background jobs running on the same core
diff --git a/doc/install/structure.md b/doc/install/structure.md
index d58b0040eef..8fc6ab4ab2f 100644
--- a/doc/install/structure.md
+++ b/doc/install/structure.md
@@ -9,10 +9,10 @@ This is the directory structure you will end up with following the instructions
| |-- gitlab-shell
| |-- repositories
-* `/home/git/.ssh` - contains openssh settings. Specifically the `authorized_keys` file managed by gitlab-shell.
-* `/home/git/gitlab` - GitLab core software.
-* `/home/git/gitlab-shell` - Core add-on component of GitLab. Maintains SSH cloning and other functionality.
-* `/home/git/repositories` - bare repositories for all projects organized by namespace. This is where the git repositories which are pushed/pulled are maintained for all projects. **This area is critical data for projects. [Keep a backup](../raketasks/backup_restore.md)**
+- `/home/git/.ssh` - contains openssh settings. Specifically the `authorized_keys` file managed by gitlab-shell.
+- `/home/git/gitlab` - GitLab core software.
+- `/home/git/gitlab-shell` - Core add-on component of GitLab. Maintains SSH cloning and other functionality.
+- `/home/git/repositories` - bare repositories for all projects organized by namespace. This is where the git repositories which are pushed/pulled are maintained for all projects. **This area is critical data for projects. [Keep a backup](../raketasks/backup_restore.md).**
*Note: the default locations for repositories can be configured in `config/gitlab.yml` of GitLab and `config.yml` of gitlab-shell.*
diff --git a/doc/integration/README.md b/doc/integration/README.md
index 8a93d4cb84b..f5bc0693b84 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -11,8 +11,7 @@ See the documentation below for details on how to configure these services.
- [Akismet](akismet.md) Configure Akismet to stop spam
- [Auth0 OmniAuth](auth0.md) Enable the Auth0 OmniAuth provider
-- [Bitbucket](bitbucket.md) Import projects from Bitbucket.org and login to your GitLab instance with your
-Bitbucket.org account
+- [Bitbucket](bitbucket.md) Import projects from Bitbucket.org and login to your GitLab instance with your Bitbucket.org account
- [CAS](cas.md) Configure GitLab to sign in using CAS
- [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc.
- [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages
@@ -30,8 +29,8 @@ Bitbucket.org account
## Project services
-Integration with services such as Campfire, Flowdock, HipChat,
-Pivotal Tracker, and Slack are available in the form of a [Project Service][].
+Integration with services such as Campfire, Flowdock, Pivotal Tracker, and Slack
+are available in the form of a [Project Service][].
[Project Service]: ../user/project/integrations/project_services.md
diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md
index 200fe6f5206..4f7be70baf2 100644
--- a/doc/integration/akismet.md
+++ b/doc/integration/akismet.md
@@ -18,7 +18,7 @@ from happening.
To use Akismet:
-1. Go to the URL: https://akismet.com/account/
+1. Go to the URL: <https://akismet.com/account/>
1. Sign-in or create a new account.
@@ -34,7 +34,6 @@ To use Akismet:
![Screenshot of Akismet settings](img/akismet_settings.png)
-
## Training
> *Note:* Training the Akismet filter is only available in 8.11 and above.
diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md
index bccaeec3706..c67375ede50 100644
--- a/doc/integration/auth0.md
+++ b/doc/integration/auth0.md
@@ -4,29 +4,29 @@ To enable the Auth0 OmniAuth provider, you must create an Auth0 account, and an
application.
1. Sign in to the [Auth0 Console](https://auth0.com/auth/login). If you need to
-create an account, you can do so at the same link.
+ create an account, you can do so at the same link.
1. Select "New App/API".
1. Provide the Application Name ('GitLab' works fine).
1. Once created, you should see the Quick Start options. Disregard them and
-select 'Settings' above the Quick Start options.
+ select 'Settings' above the Quick Start options.
1. At the top of the Settings screen, you should see your Domain, Client ID and
-Client Secret. Take note of these as you'll need to put them in the
-configuration file. For example:
+ Client Secret. Take note of these as you'll need to put them in the
+ configuration file. For example:
- Domain: `test1234.auth0.com`
- Client ID: `t6X8L2465bNePWLOvt9yi41i`
- Client Secret: `KbveM3nqfjwCbrhaUy_gDu2dss8TIlHIdzlyf33pB7dEK5u_NyQdp65O_o02hXs2`
1. Fill in the Allowed Callback URLs:
- - http://`YOUR_GITLAB_URL`/users/auth/auth0/callback (or)
- - https://`YOUR_GITLAB_URL`/users/auth/auth0/callback
+ - `http://YOUR_GITLAB_URL/users/auth/auth0/callback` (or)
+ - `https://YOUR_GITLAB_URL/users/auth/auth0/callback`
1. Fill in the Allowed Origins (CORS):
- - http://`YOUR_GITLAB_URL` (or)
- - https://`YOUR_GITLAB_URL`
+ - `http://YOUR_GITLAB_URL` (or)
+ - `https://YOUR_GITLAB_URL`
1. On your GitLab server, open the configuration file.
@@ -44,7 +44,7 @@ configuration file. For example:
```
1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
-for initial settings.
+ for initial settings.
1. Add the provider configuration:
@@ -76,10 +76,10 @@ for initial settings.
```
1. Change `YOUR_AUTH0_CLIENT_ID` to the client ID from the Auth0 Console page
-from step 5.
+ from step 5.
1. Change `YOUR_AUTH0_CLIENT_SECRET` to the client secret from the Auth0 Console
-page from step 5.
+ page from step 5.
1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
installed GitLab via Omnibus or from source respectively.
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index 634dd952448..7a6d4bb143f 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -15,12 +15,12 @@ To enable the Microsoft Azure OAuth2 OmniAuth provider you must register your ap
- Type: 'WEB APPLICATION AND/OR WEB API'
1. On the "App properties" page enter the needed URI's and click the "Complete" button.
- - SIGN-IN URL: Enter the URL of your GitLab installation (e.g 'https://gitlab.mycompany.com/')
- - APP ID URI: Enter the endpoint URL for Microsoft to use, just has to be unique (e.g 'https://mycompany.onmicrosoft.com/gitlab')
+ - SIGN-IN URL: Enter the URL of your GitLab installation (e.g `https://gitlab.mycompany.com/`)
+ - APP ID URI: Enter the endpoint URL for Microsoft to use, just has to be unique (e.g `https://mycompany.onmicrosoft.com/gitlab`)
1. Select "Configure" in the top menu.
-1. Add a "Reply URL" pointing to the Azure OAuth callback of your GitLab installation (e.g. https://gitlab.mycompany.com/users/auth/azure_oauth2/callback).
+1. Add a "Reply URL" pointing to the Azure OAuth callback of your GitLab installation (e.g. `https://gitlab.mycompany.com/users/auth/azure_oauth2/callback`).
1. Create a "Client secret" by selecting a duration, the secret will be generated as soon as you click the "Save" button in the bottom menu..
@@ -28,7 +28,7 @@ To enable the Microsoft Azure OAuth2 OmniAuth provider you must register your ap
1. Select "View endpoints" from the bottom menu.
-1. You will see lots of endpoint URLs in the form 'https://login.microsoftonline.com/TENANT ID/...', note down the TENANT ID part of one of those endpoints.
+1. You will see lots of endpoint URLs in the form `https://login.microsoftonline.com/TENANT ID/...`, note down the TENANT ID part of one of those endpoints.
1. On your GitLab server, open the configuration file.
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
index a69db1d1a6e..68ec8c4b5c2 100644
--- a/doc/integration/bitbucket.md
+++ b/doc/integration/bitbucket.md
@@ -43,9 +43,13 @@ you to use.
| :--- | :---------- |
| **Name** | This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or something else descriptive. |
| **Application description** | Fill this in if you wish. |
- | **Callback URL** | The URL to your GitLab installation, e.g., `https://gitlab.example.com`. |
+ | **Callback URL** | The URL to your GitLab installation, e.g., `https://gitlab.example.com/users/auth`. |
| **URL** | The URL to your GitLab installation, e.g., `https://gitlab.example.com`. |
+ NOTE: Be sure to append `/users/auth` to the end of the callback URL
+ to prevent a [OAuth2 convert
+ redirect](http://tetraph.com/covert_redirect/) vulnerability.
+
NOTE: Starting in GitLab 8.15, you MUST specify a callback URL, or you will
see an "Invalid redirect_uri" message. For more details, see [the
Bitbucket documentation](https://confluence.atlassian.com/bitbucket/oauth-faq-338365710.html).
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index f757edf0bc2..c6178fa44f0 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -38,7 +38,6 @@ To enable the CAS OmniAuth provider you must register your application with your
}
]
```
-
For installations from source:
@@ -65,4 +64,3 @@ On the sign in page there should now be a CAS tab in the sign in form.
[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
-
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index 075feaeead9..edd1af423ca 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -1,8 +1,8 @@
# External issue tracker
GitLab has a great issue tracker but you can also use an external one such as
-Jira, Redmine, or Bugzilla. Issue trackers are configurable per GitLab project and allow
-you to do the following:
+Jira, Redmine, YouTrack, or Bugzilla. Issue trackers are configurable per GitLab project
+and allow you to do the following:
- you can reference these external issues inside GitLab interface
(merge requests, commits, comments) and they will be automatically converted
@@ -20,6 +20,7 @@ To enable an external issue tracker you must configure the appropriate **Service
Visit the links below for details:
- [Redmine](../user/project/integrations/redmine.md)
+- [YouTrack](../user/project/integrations/youtrack.md)
- [Jira](../user/project/integrations/jira.md)
- [Bugzilla](../user/project/integrations/bugzilla.md)
- [Custom Issue Tracker](../user/project/integrations/custom_issue_tracker.md)
diff --git a/doc/integration/facebook.md b/doc/integration/facebook.md
index a67de23b17b..fe789a80eed 100644
--- a/doc/integration/facebook.md
+++ b/doc/integration/facebook.md
@@ -9,7 +9,7 @@ To enable the Facebook OmniAuth provider you must register your application with
1. Select the type "Website"
1. Enter a name for your app. This can be anything. Consider something like "&lt;Organization&gt;'s GitLab" or "&lt;Your Name&gt;'s GitLab" or
-something else descriptive.
+ something else descriptive.
1. Choose "Create New Facebook App ID"
diff --git a/doc/integration/github.md b/doc/integration/github.md
index b8156b2b593..bee68688ace 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -21,9 +21,13 @@ To get the credentials (a pair of Client ID and Client Secret), you must registe
- Application name: This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or something else descriptive.
- Homepage URL: the URL to your GitLab installation. e.g., `https://gitlab.company.com`
- Application description: Fill this in if you wish.
- - Authorization callback URL: `http(s)://${YOUR_DOMAIN}`. Please make sure the port is included if your GitLab instance is not configured on default port.
+ - Authorization callback URL: `http(s)://${YOUR_DOMAIN}/users/auth/github/callback`. Please make sure the port is included if your GitLab instance is not configured on default port.
![Register OAuth App](img/github_register_app.png)
+ NOTE: Be sure to append `/users/auth/github/callback` to the end of the callback URL
+ to prevent a [OAuth2 convert
+ redirect](http://tetraph.com/covert_redirect/) vulnerability.
+
1. Select **Register application**.
1. You should now see a pair of **Client ID** and **Client Secret** near the top right of the page (see screenshot).
@@ -89,7 +93,6 @@ To get the credentials (a pair of Client ID and Client Secret), you must registe
args: { scope: 'user:email' } }
```
-
For GitHub Enterprise:
```
diff --git a/doc/integration/gmail_action_buttons_for_gitlab.md b/doc/integration/gmail_action_buttons_for_gitlab.md
index c19320471e3..cc5d444c069 100644
--- a/doc/integration/gmail_action_buttons_for_gitlab.md
+++ b/doc/integration/gmail_action_buttons_for_gitlab.md
@@ -14,9 +14,9 @@ To get this functioning, you need to be registered with Google.
Pay close attention to:
-* Email account used by GitLab to send notification emails needs to have "Consistent history of sending a high volume of mail from your domain (order of hundred emails a day minimum to Gmail) for a few weeks at least".
-* "A very very low rate of spam complaints from users."
-* Emails must be authenticated via DKIM or SPF
-* Before sending the final form("Gmail Schema Whitelist Request"), you must send a real email from your production server. This means that you will have to find a way to send this email from the email address you are registering. You can do this by, for example, forwarding the real email from the email address you are registering or going into the rails console on the GitLab server and triggering the email sending from there.
+- Email account used by GitLab to send notification emails needs to have "Consistent history of sending a high volume of mail from your domain (order of hundred emails a day minimum to Gmail) for a few weeks at least".
+- "A very very low rate of spam complaints from users."
+- Emails must be authenticated via DKIM or SPF.
+- Before sending the final form ("Gmail Schema Whitelist Request"), you must send a real email from your production server. This means that you will have to find a way to send this email from the email address you are registering. You can do this by, for example, forwarding the real email from the email address you are registering or going into the rails console on the GitLab server and triggering the email sending from there.
You can check how it looks going through all the steps laid out in the "Registering with Google" doc in [this GitLab.com issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/1517).
diff --git a/doc/integration/google.md b/doc/integration/google.md
index b91d40d4bd4..d2b4e119978 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -35,7 +35,6 @@ In Google's side:
1. You should now be able to see a Client ID and Client secret. Note them down
or keep this page open as you will need them later.
-1. From the **Dashboard** select **ENABLE APIS AND SERVICES > Social > Google+ API > Enable**
1. To enable projects to access [Google Kubernetes Engine](../user/project/clusters/index.md), you must also
enable these APIs:
- Google Kubernetes Engine API
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index acc9db15826..c02a29dffb4 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -3,8 +3,11 @@
This document is about using GitLab as an OAuth authentication service provider
to sign in to other services.
-If you want to use other OAuth authentication service providers to sign in to
-GitLab, please see the [OAuth2 client documentation](../api/oauth2.md).
+If you want to use:
+
+- Other OAuth authentication service providers to sign in to
+ GitLab, see the [OAuth2 client documentation](omniauth.md).
+- The related API, see [Applications API](../api/applications.md).
## Introduction to OAuth
@@ -28,7 +31,7 @@ GitLab supports two ways of adding a new OAuth2 application to an instance. You
can either add an application as a regular user or add it in the admin area.
What this means is that GitLab can actually have instance-wide and a user-wide
applications. There is no difference between them except for the different
-permission levels they are set (user/admin). The default callback URL is
+permission levels they are set (user/admin). The default callback URL is
`http://your-gitlab.example.com/users/auth/gitlab/callback`
## Adding an application through the profile
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 4e1d5ba9b35..69bbd05c367 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -66,7 +66,7 @@ that are in common for all providers that we need to consider.
To change these settings:
-* **For omnibus package**
+- **For omnibus package**
Open the configuration file:
@@ -89,7 +89,7 @@ To change these settings:
gitlab_rails['omniauth_block_auto_created_users'] = true
```
-* **For installations from source**
+- **For installations from source**
Open the configuration file:
@@ -199,7 +199,7 @@ from the Omniauth provider's documentation.
sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment
- > These are the same commands you used in the [Install Gems section](#install-gems) with `--path vendor/bundle --no-deployment` instead of `--deployment`.
+ > These are the same commands you used during initial installation in the [Install Gems section](../install/installation.md#install-gems) with `--path vendor/bundle --no-deployment` instead of `--deployment`.
- Start GitLab:
@@ -231,7 +231,6 @@ In order to enable/disable an OmniAuth provider, go to Admin Area -> Settings ->
![Enabled OAuth Sign-In sources](img/enabled-oauth-sign-in-sources.png)
-
## Disabling Omniauth
Starting from version 11.4 of GitLab, Omniauth is enabled by default. This only
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index a7470d27b4b..8ee07a7fcdc 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -249,7 +249,6 @@ If you want some SAML authentication methods to count as 2FA on a per session ba
1. Save the file and [restart GitLab][] for the changes ot take effect
-
In addition to the changes in GitLab, make sure that your Idp is returning the
`AuthnContext`. For example:
@@ -287,7 +286,7 @@ so you will not be able to sign in using local credentials. Make sure that at le
of the SAML users has admin permissions.
You may also bypass the auto signin feature by browsing to
-https://gitlab.example.com/users/sign_in?auto_sign_in=false.
+`https://gitlab.example.com/users/sign_in?auto_sign_in=false`.
### `attribute_statements`
diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md
index 7d73026a6c6..cd755089be8 100644
--- a/doc/integration/slash_commands.md
+++ b/doc/integration/slash_commands.md
@@ -1,5 +1,7 @@
# Slash Commands
+> The `run` command was [introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6. [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24780) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.9.
+
Slash commands in Mattermost and Slack allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires a [project service configuration](../user/project/integrations/slack_slash_commands.md). Simply type the command as a message in your chat client to activate it.
Commands are scoped to a project, with a trigger term that is specified during configuration.
@@ -8,7 +10,6 @@ We suggest you use the project name as the trigger term for simplicity and clari
Taking the trigger term as `project-name`, the commands are:
-
| Command | Effect |
| ------- | ------ |
| `/project-name help` | Shows all available slash commands |
@@ -17,6 +18,7 @@ Taking the trigger term as `project-name`, the commands are:
| `/project-name issue search <query>` | Shows up to 5 issues matching `<query>` |
| `/project-name issue move <id> to <project>` | Moves issue ID `<id>` to `<project>` |
| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
+| `/project-name run <job name> <arguments>` | Execute [ChatOps](../ci/chatops/README.md) job `<job name>` on `master` |
Note that if you are using the [GitLab Slack application](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html) for
your GitLab.com projects, you need to [add the `gitlab` keyword at the beginning of the command](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#usage).
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index d0976b6201e..1cbfd81dfa9 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -10,8 +10,8 @@ To enable the Twitter OmniAuth provider you must register your application with
- Name: This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or
something else descriptive.
- Description: Create a description.
- - Website: The URL to your GitLab installation. 'https://gitlab.example.com'
- - Callback URL: 'https://gitlab.example.com/users/auth/twitter/callback'
+ - Website: The URL to your GitLab installation. `https://gitlab.example.com`
+ - Callback URL: `https://gitlab.example.com/users/auth/twitter/callback`
- Agree to the "Developer Agreement".
![Twitter App Details](img/twitter_app_details.png)
diff --git a/doc/intro/README.md b/doc/intro/README.md
index d9acc5bdeac..9bc7c3d9ea4 100644
--- a/doc/intro/README.md
+++ b/doc/intro/README.md
@@ -9,13 +9,13 @@ comments: false
Create projects and groups.
- [Create a new project](../gitlab-basics/create-project.md)
-- [Create a new group](../gitlab-basics/create-group.md)
+- [Create a new group](../user/group/index.md#create-a-new-group)
## Prioritize
Create issues, labels, milestones, cast your vote, and review issues.
-- [Create a new issue](../user/project/issues/index.md#new-issue)
+- [Create an issue](../user/project/issues/create_new_issue.md)
- [Assign labels to issues](../user/project/labels.md)
- [Use milestones as an overview of your project's tracker](../user/project/milestones/index.md)
- [Use voting to express your like/dislike to issues and merge requests](../workflow/award_emoji.md)
diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md
index 9347a834510..4c4b423f40f 100644
--- a/doc/migrate_ci_to_ce/README.md
+++ b/doc/migrate_ci_to_ce/README.md
@@ -71,7 +71,7 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production SKIP=r
```
If this fails you need to fix it before upgrading to 8.0. Also see
-https://about.gitlab.com/getting-help/
+<https://about.gitlab.com/get-help/>
### 2. Check source and target database types
@@ -118,7 +118,7 @@ From this point on, GitLab CI will be unavailable for your end users.
### 1. Upgrade GitLab to 8.0
First upgrade your GitLab server to version 8.0:
-https://about.gitlab.com/update/
+<https://about.gitlab.com/update/>
### 2. Disable CI on the GitLab server during the migration
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index 03ba2ae8817..1d656574acd 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -3,21 +3,23 @@
## Versioning
GitLab follows the [Semantic Versioning](http://semver.org/) for its releases:
-`(Major).(Minor).(Patch)` in a [pragmatic way].
-
-- **Major version**: Whenever there is something significant or any backwards
- incompatible changes are introduced to the public API.
-- **Minor version**: When new, backwards compatible functionality is introduced
- to the public API or a minor feature is introduced, or when a set of smaller
- features is rolled out.
-- **Patch number**: When backwards compatible bug fixes are introduced that fix
- incorrect behavior.
+`(Major).(Minor).(Patch)` in a [pragmatic way](https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e).
For example, for GitLab version 10.5.7:
-* `10` represents major version
-* `5` represents minor version
-* `7` represents patch number
+- `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 increment into multiple digits, for example, 13.10.11.
+
+The following table describes the version types and their release cadence:
+
+| Version type | Description | Cadence |
+|:-------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 12.0 on June 22, 2019. Subsequent major releases will be scheduled for May 22 each year, by default. | |
+| Minor | For when new backward-compatible functionality is introduced to the public API, a minor feature is introduced, or when a set of smaller features is rolled out. | Monthly on the 22nd. |
+| Patch | For backward-compatible bug fixes that fix incorrect behavior. See [Patch releases](#patch-releases). | As needed. |
## Patch releases
@@ -55,20 +57,20 @@ cases you need to consider.
It is considered safe to jump between patch versions and minor versions within
one major version. For example, it is safe to:
-* Upgrade the patch version:
- * `8.9.0` -> `8.9.7`
- * `8.9.0` -> `8.9.1`
- * `8.9.2` -> `8.9.6`
-* Upgrade the minor version:
- * `8.9.4` -> `8.12.3`
- * `9.2.3` -> `9.5.5`
+- Upgrade the patch version:
+ - `8.9.0` -> `8.9.7`
+ - `8.9.0` -> `8.9.1`
+ - `8.9.2` -> `8.9.6`
+- Upgrade the minor version:
+ - `8.9.4` -> `8.12.3`
+ - `9.2.3` -> `9.5.5`
Upgrading the major version requires more attention.
We cannot guarantee that upgrading between major versions will be seamless. As previously mentioned, major versions are reserved for backwards incompatible changes.
We recommend that you first upgrade to the latest available minor version within
your major version. By doing this, you can address any deprecation messages
-that could possibly change behaviour in the next major release.
+that could change behavior in the next major release.
Please see the table below for some examples:
@@ -79,9 +81,5 @@ Please see the table below for some examples:
| 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` |
More information about the release procedures can be found in our
-[release-tools documentation][rel]. You may also want to read our
-[Responsible Disclosure Policy][disclosure].
-
-[rel]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/
-[disclosure]: https://about.gitlab.com/disclosure/
-[pragmatic way]: https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e
+[release documentation](https://gitlab.com/gitlab-org/release/docs). You may also want to read our
+[Responsible Disclosure Policy](https://about.gitlab.com/security/disclosure/).
diff --git a/doc/project_services/bamboo.md b/doc/project_services/bamboo.md
index 5b171080c72..a1ff8909f87 100644
--- a/doc/project_services/bamboo.md
+++ b/doc/project_services/bamboo.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/bamboo.md'
+---
+
This document was moved to [user/project/integrations/bamboo.md](../user/project/integrations/bamboo.md).
diff --git a/doc/project_services/bugzilla.md b/doc/project_services/bugzilla.md
index e67055d5616..1abf1b28939 100644
--- a/doc/project_services/bugzilla.md
+++ b/doc/project_services/bugzilla.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/bugzilla.md'
+---
+
This document was moved to [user/project/integrations/bugzilla.md](../user/project/integrations/bugzilla.md).
diff --git a/doc/project_services/emails_on_push.md b/doc/project_services/emails_on_push.md
index a2e831ada34..c5ab8aa5c70 100644
--- a/doc/project_services/emails_on_push.md
+++ b/doc/project_services/emails_on_push.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/emails_on_push.md'
+---
+
This document was moved to [user/project/integrations/emails_on_push.md](../user/project/integrations/emails_on_push.md).
diff --git a/doc/project_services/hipchat.md b/doc/project_services/hipchat.md
deleted file mode 100644
index 4ae9f6c6b2e..00000000000
--- a/doc/project_services/hipchat.md
+++ /dev/null
@@ -1 +0,0 @@
-This document was moved to [user/project/integrations/hipchat.md](../user/project/integrations/hipchat.md).
diff --git a/doc/project_services/irker.md b/doc/project_services/irker.md
index 7f0850dcc24..af47abab117 100644
--- a/doc/project_services/irker.md
+++ b/doc/project_services/irker.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/irker.md'
+---
+
This document was moved to [user/project/integrations/irker.md](../user/project/integrations/irker.md).
diff --git a/doc/project_services/jira.md b/doc/project_services/jira.md
index 63614feba82..6a0108f400f 100644
--- a/doc/project_services/jira.md
+++ b/doc/project_services/jira.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/jira.md'
+---
+
This document was moved to [user/project/integrations/jira.md](../user/project/integrations/jira.md).
diff --git a/doc/project_services/kubernetes.md b/doc/project_services/kubernetes.md
index 0497a13c2b7..cfe36fcd1b2 100644
--- a/doc/project_services/kubernetes.md
+++ b/doc/project_services/kubernetes.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/kubernetes.md'
+---
+
This document was moved to [user/project/integrations/kubernetes.md](../user/project/integrations/kubernetes.md).
diff --git a/doc/project_services/mattermost.md b/doc/project_services/mattermost.md
index 554a028853e..de9f4d14cf7 100644
--- a/doc/project_services/mattermost.md
+++ b/doc/project_services/mattermost.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/mattermost.md'
+---
+
This document was moved to [user/project/integrations/mattermost.md](../user/project/integrations/mattermost.md).
diff --git a/doc/project_services/mattermost_slash_commands.md b/doc/project_services/mattermost_slash_commands.md
index 7c238b5dc37..82ec34739c1 100644
--- a/doc/project_services/mattermost_slash_commands.md
+++ b/doc/project_services/mattermost_slash_commands.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/mattermost_slash_commands.md'
+---
+
This document was moved to [user/project/integrations/mattermost_slash_commands.md](../user/project/integrations/mattermost_slash_commands.md).
diff --git a/doc/project_services/project_services.md b/doc/project_services/project_services.md
index 2c555c4edae..a355851a273 100644
--- a/doc/project_services/project_services.md
+++ b/doc/project_services/project_services.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/project_services.md'
+---
+
This document was moved to [user/project/integrations/project_services.md](../user/project/integrations/project_services.md).
diff --git a/doc/project_services/redmine.md b/doc/project_services/redmine.md
index 6010aa4dc75..05f28f00adc 100644
--- a/doc/project_services/redmine.md
+++ b/doc/project_services/redmine.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/redmine.md'
+---
+
This document was moved to [user/project/integrations/redmine.md](../user/project/integrations/redmine.md).
diff --git a/doc/project_services/services_templates.md b/doc/project_services/services_templates.md
index 8905d667c5a..ac6b85cc801 100644
--- a/doc/project_services/services_templates.md
+++ b/doc/project_services/services_templates.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/services_templates.md'
+---
+
This document was moved to [user/project/integrations/services_templates.md](../user/project/integrations/services_templates.md).
diff --git a/doc/project_services/slack.md b/doc/project_services/slack.md
index 1d3f98705e3..4c89ce92002 100644
--- a/doc/project_services/slack.md
+++ b/doc/project_services/slack.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/slack.md'
+---
+
This document was moved to [user/project/integrations/slack.md](../user/project/integrations/slack.md).
diff --git a/doc/project_services/slack_slash_commands.md b/doc/project_services/slack_slash_commands.md
index 9554c8decc8..ca0034256f1 100644
--- a/doc/project_services/slack_slash_commands.md
+++ b/doc/project_services/slack_slash_commands.md
@@ -1 +1,5 @@
+---
+redirect_to: '../user/project/integrations/slack_slash_commands.md'
+---
+
This document was moved to [user/project/integrations/slack_slash_commands.md](../user/project/integrations/slack_slash_commands.md).
diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md
index 81ee7338e4e..8601551e3bd 100644
--- a/doc/public_access/public_access.md
+++ b/doc/public_access/public_access.md
@@ -1,6 +1,6 @@
# Public access
-GitLab allows you to change your projects' visibility in order be accessed
+GitLab allows [Owners](../user/permissions.md) to change a projects' visibility in order to be accessed
**publicly** or **internally**.
Projects with either of these visibility levels will be listed in the
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 22a67e3ed01..e28b4fc683a 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -329,6 +329,11 @@ For installations from source:
remote_directory: 'my.s3.bucket'
# Turns on AWS Server-Side Encryption with Amazon S3-Managed Keys for backups, this is optional
# encryption: 'AES256'
+ # Turns on AWS Server-Side Encryption with Amazon Customer-Provided Encryption Keys for backups, this is optional
+ # This should be set to the base64-encoded encryption key for Amazon S3 to use to encrypt or decrypt your data.
+ # 'encryption' must also be set in order for this to have any effect.
+ # To avoid storing the key on disk, the key can also be specified via the `GITLAB_BACKUP_ENCRYPTION_KEY` environment variable.
+ # encryption_key: '<base64 key>'
# Specifies Amazon S3 storage class to use for backups, this is optional
# storage_class: 'STANDARD'
```
@@ -391,7 +396,7 @@ with the name of your bucket:
If you want to use Google Cloud Storage to save backups, you'll have to create
an access key from the Google console first:
-1. Go to the storage settings page https://console.cloud.google.com/storage/settings
+1. Go to the storage settings page <https://console.cloud.google.com/storage/settings>
1. Select "Interoperability" and create an access key
1. Make note of the "Access Key" and "Secret" and replace them in the
configurations below
@@ -455,6 +460,7 @@ backups will be copied to, and will be created if it does not exist. If the
directory that you want to copy the tarballs to is the root of your mounted
directory, just use `.` instead.
+NOTE: **Note:** Since file system performance may affect GitLab's overall performance, we do not recommend using EFS for storage. See the [relevant documentation](../administration/high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs) for more details.
For Omnibus GitLab packages:
@@ -577,7 +583,6 @@ For installations from source:
1. [Restart GitLab] for the changes to take effect.
-
```sh
sudo -u git crontab -e # Edit the crontab for the git user
```
@@ -819,9 +824,22 @@ If you have failed to [back up the secrets file](#storing-configuration-files),
then users with 2FA enabled will not be able to log into GitLab. In that case,
you need to [disable 2FA for everyone](../security/two_factor_authentication.md#disabling-2fa-for-everyone).
-In the case of CI/CD, if your project has secure variables set, you might experience
-some weird behavior, like stuck jobs or 500 errors. In that case, you can try
-deleting the `ci_variables` table from the database.
+The secrets file is also responsible for storing the encryption key for several
+columns containing sensitive information. If the key is lost, GitLab will be
+unable to decrypt those columns. This will break a wide range of functionality,
+including (but not restricted to):
+
+* [CI/CD variables](../ci/variables/README.md)
+* [Kubernetes / GCP integration](../user/project/clusters/index.md)
+* [Custom Pages domains](../user/project/pages/getting_started_part_three.md)
+* [Project error tracking](../user/project/operations/error_tracking.md)
+* [Runner authentication](../ci/runners/README.md)
+* [Project mirroring](../workflow/repository_mirroring.md)
+* [Web hooks](../user/project/integrations/webhooks.md)
+
+In the case of CI/CD, variables, you might experience some weird behavior, like
+stuck jobs or 500 errors. In that case, you can try removing contents of the
+`ci_group_variables` and `ci_project_variables` tables from the database.
CAUTION: **Warning:**
Use the following commands at your own risk, and make sure you've taken a
@@ -841,9 +859,10 @@ backup beforehand.
sudo -u git -H bundle exec rails dbconsole RAILS_ENV=production
```
-1. Check the `ci_variables` table:
+1. Check the `ci_group_variables` and `ci_variables` tables:
```sql
+ SELECT * FROM public."ci_group_variables";
SELECT * FROM public."ci_variables";
```
@@ -852,6 +871,7 @@ backup beforehand.
1. Drop the table:
```sql
+ DELETE FROM ci_group_variables;
DELETE FROM ci_variables;
```
@@ -861,5 +881,9 @@ backup beforehand.
You should now be able to visit your project, and the jobs will start
running again.
+A similar strategy can be employed for the remaining features - by removing the
+data that cannot be decrypted, GitLab can be brought back into working order,
+and the lost data can be manually replaced.
+
[reconfigure GitLab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index e1b1912ed47..571e784e530 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -52,7 +52,6 @@ bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production
- Enable this setting to keep new users blocked until they have been cleared by the admin (default: false).
-
```
block_auto_created_users: false
```
@@ -77,7 +76,6 @@ GitLab stores the secret data enabling 2FA to work in an encrypted database
column. The encryption key for this data is known as `otp_key_base`, and is
stored in `config/secrets.yml`.
-
If that file is leaked, but the individual 2FA secrets have not, it's possible
to re-encrypt those secrets with a new encryption key. This allows you to change
the leaked key without forcing all users to change their 2FA details.
diff --git a/doc/security/README.md b/doc/security/README.md
index e22dc00759d..a90127e0356 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -15,3 +15,4 @@ comments: false
- [How we manage the CRIME vulnerability](crime_vulnerability.md)
- [Enforce Two-factor authentication](two_factor_authentication.md)
- [Send email confirmation on sign-up](user_email_confirmation.md)
+- [Security of running jobs](https://docs.gitlab.com/runner/security/)
diff --git a/doc/security/crime_vulnerability.md b/doc/security/crime_vulnerability.md
index 94ba5d1375d..d61a205d954 100644
--- a/doc/security/crime_vulnerability.md
+++ b/doc/security/crime_vulnerability.md
@@ -17,8 +17,8 @@ GitLab supports both gzip and [SPDY][ngx-spdy] and mitigates the CRIME
vulnerability by deactivating gzip when HTTPS is enabled. You can see the
sources of the files in question:
-* [Source installation NGINX file][source-nginx]
-* [Omnibus installation NGINX file][omnibus-nginx]
+- [Source installation NGINX file][source-nginx]
+- [Omnibus installation NGINX file][omnibus-nginx]
Although SPDY is enabled in Omnibus installations, CRIME relies on compression
(the 'C') and the default compression level in NGINX's SPDY module is 0
@@ -52,9 +52,9 @@ vulnerability.
### References
-* Nginx ["Module ngx_http_spdy_module"][ngx-spdy]
-* Tenable Network Security, Inc. ["Transport Layer Security (TLS) Protocol CRIME Vulnerability"][nessus]
-* Wikipedia contributors, ["CRIME"][wiki-crime] Wikipedia, The Free Encyclopedia
+- Nginx ["Module ngx_http_spdy_module"][ngx-spdy]
+- Tenable Network Security, Inc. ["Transport Layer Security (TLS) Protocol CRIME Vulnerability"][nessus]
+- Wikipedia contributors, ["CRIME"][wiki-crime] Wikipedia, The Free Encyclopedia
[source-nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/gitlab-ssl
[omnibus-nginx]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/templates/default/nginx-gitlab-http.conf.erb
diff --git a/doc/security/img/ssh_keys_restricted_key_icon.png b/doc/security/img/ssh_keys_restricted_key_icon.png
new file mode 100644
index 00000000000..ad3749e8233
--- /dev/null
+++ b/doc/security/img/ssh_keys_restricted_key_icon.png
Binary files differ
diff --git a/doc/security/ssh_keys_restrictions.md b/doc/security/ssh_keys_restrictions.md
index 213fa5bfef5..6b6a8a06cc9 100644
--- a/doc/security/ssh_keys_restrictions.md
+++ b/doc/security/ssh_keys_restrictions.md
@@ -17,3 +17,11 @@ In the Admin area under **Settings** (`/admin/application_settings`), look for
the "Visibility and Access Controls" area:
![SSH keys restriction admin settings](img/ssh_keys_restrictions_settings.png)
+
+If a restriction is imposed on any key type, users will be unable to upload new SSH keys that don't meet the requirement. Any existing keys that don't meet it will be disabled but not removed and users will be unable to pull or push code using them.
+
+An icon will be visible to the user of a restricted key in the SSH keys section of their profile:
+
+![Restricted SSH key icon](img/ssh_keys_restricted_key_icon.png)
+
+Hovering over this icon will tell you why the key is restricted.
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index b17b0a4bc4a..8c26bbac6a7 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -6,13 +6,13 @@ With [Webhooks](../user/project/integrations/webhooks.md), you and your project
Things get hairy, however, when a Webhook is set up with a URL that doesn't point to an external, but to an internal service, that may do something completely unintended when the webhook is triggered and the POST request is sent.
-Because Webhook requests are made by the GitLab server itself, these have complete access to everything running on the server (http://localhost:123) or within the server's local network (http://192.168.1.12:345), even if these services are otherwise protected and inaccessible from the outside world.
+Because Webhook requests are made by the GitLab server itself, these have complete access to everything running on the server (`http://localhost:123`) or within the server's local network (`http://192.168.1.12:345`), even if these services are otherwise protected and inaccessible from the outside world.
-If a web service does not require authentication, Webhooks can be used to trigger destructive commands by getting the GitLab server to make POST requests to endpoints like "http://localhost:123/some-resource/delete".
+If a web service does not require authentication, Webhooks can be used to trigger destructive commands by getting the GitLab server to make POST requests to endpoints like `http://localhost:123/some-resource/delete`.
To prevent this type of exploitation from happening, starting with GitLab 10.6, all Webhook requests to the current GitLab instance server address and/or in a private network will be forbidden by default. That means that all requests made to 127.0.0.1, ::1 and 0.0.0.0, as well as IPv4 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 and IPv6 site-local (ffc0::/10) addresses won't be allowed.
-This behavior can be overridden by enabling the option *"Allow requests to the local network from hooks and services"* in the *"Outbound requests"* section inside the Admin area under **Settings** (`/admin/application_settings`):
+This behavior can be overridden by enabling the option *"Allow requests to the local network from hooks and services"* in the *"Outbound requests"* section inside the Admin area under **Settings** (`/admin/application_settings/network`):
![Outbound requests admin settings](img/outbound_requests_section.png)
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index e570627bfc1..9c4a391e8da 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -19,7 +19,7 @@ comes pre-installed on GNU/Linux and macOS, but not on Windows.
Depending on your Windows version, there are different methods to work with
SSH keys.
-### Installing the SSH client for Windows 10
+### Windows 10: Windows Subsystem for Linux
Starting with Windows 10, you can
[install the Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10)
@@ -27,10 +27,10 @@ where you can run Linux distributions directly on Windows, without the overhead
of a virtual machine. Once installed and set up, you'll have the Git and SSH
clients at your disposal.
-### Installing the SSH client for Windows 8.1 and Windows 7
+### Windows 10, 8.1, and 7: Git for Windows
The easiest way to install Git and the SSH client on Windows 8.1 and Windows 7
-is [Git for Windows](https://gitforwindows.org). It provides a BASH
+is [Git for Windows](https://gitforwindows.org). It provides a Bash
emulation (Git Bash) used for running Git from the command line and the
`ssh-keygen` command that is useful to create SSH keys as you'll learn below.
@@ -114,7 +114,8 @@ To create a new SSH key pair:
and want to tell which is which. It is optional.
1. Next, you will be prompted to input a file path to save your SSH key pair to.
- If you don't already have an SSH key pair, use the suggested path by pressing
+ If you don't already have an SSH key pair and aren't generating a [deploy key](#deploy-keys),
+ use the suggested path by pressing
<kbd>Enter</kbd>. Using the suggested path will normally allow your SSH client
to automatically use the SSH key pair with no additional configuration.
@@ -128,7 +129,7 @@ To create a new SSH key pair:
<kbd>Enter</kbd> twice.
If, in any case, you want to add or change the password of your SSH key pair,
- you can use the `-p`flag:
+ you can use the `-p` flag:
```
ssh-keygen -p -o -f <keyname>
@@ -246,6 +247,17 @@ Public SSH keys need to be unique to GitLab, as they will bind to your account.
Your SSH key is the only identifier you'll have when pushing code via SSH,
that's why it needs to uniquely map to a single user.
+## Per-repository SSH keys
+
+If you want to use different keys depending on the repository you are working
+on, you can issue the following command while inside your repository:
+
+```sh
+git config core.sshCommand "ssh -o IdentitiesOnly=yes -i ~/.ssh/private-key-filename-for-this-repository -F /dev/null"
+```
+
+This will not use the SSH Agent and requires at least Git 2.10.
+
## Deploy keys
### Per-repository deploy keys
@@ -258,7 +270,8 @@ Integration (CI) server. By using deploy keys, you don't have to set up a
dummy user account.
If you are a project maintainer or owner, you can add a deploy key in the
-project settings under the section 'Repository'. Specify a title for the new
+project's **Settings > Repository** page by expanding the
+**Deploy Keys** section. Specify a title for the new
deploy key and paste a public SSH key. After this, the machine that uses
the corresponding private SSH key has read-only or read-write (if enabled)
access to the project.
@@ -300,8 +313,8 @@ of broader usage for something like "Anywhere you need to give read access to
your repository".
Once a GitLab administrator adds the Global Deployment key, project maintainers
-and owners can add it in project's **Settings > Repository** section by expanding the
-**Deploy Key** section and clicking **Enable** next to the appropriate key listed
+and owners can add it in project's **Settings > Repository** page by expanding the
+**Deploy Keys** section and clicking **Enable** next to the appropriate key listed
under **Public deploy keys available to any project**.
NOTE: **Note:**
@@ -318,7 +331,7 @@ not implicitly give any access just by setting them up.
### Eclipse
-How to add your SSH key to Eclipse: https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration
+How to add your SSH key to Eclipse: <https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration>
## SSH on the GitLab server
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index cce02d218c2..a3698d60f6d 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -138,7 +138,7 @@ Please refer to `group_rename` and `user_rename` for that case.
"created_at": "2012-07-21T07:30:56Z",
"updated_at": "2012-07-21T07:38:22Z",
"event_name": "user_add_to_team",
- "project_access": "Maintainer",
+ "access_level": "Maintainer",
"project_id": 74,
"project_name": "StoreCloud",
"project_path": "storecloud",
@@ -147,7 +147,7 @@ Please refer to `group_rename` and `user_rename` for that case.
"user_name": "John Smith",
"user_username": "johnsmith",
"user_id": 41,
- "project_visibility": "private"
+ "project_visibility": "visibilitylevel|private"
}
```
@@ -158,7 +158,7 @@ Please refer to `group_rename` and `user_rename` for that case.
"created_at": "2012-07-21T07:30:56Z",
"updated_at": "2012-07-21T07:38:22Z",
"event_name": "user_remove_from_team",
- "project_access": "Maintainer",
+ "access_level": "Maintainer",
"project_id": 74,
"project_name": "StoreCloud",
"project_path": "storecloud",
@@ -167,7 +167,7 @@ Please refer to `group_rename` and `user_rename` for that case.
"user_name": "John Smith",
"user_username": "johnsmith",
"user_id": 41,
- "project_visibility": "private"
+ "project_visibility": "visibilitylevel|private"
}
```
@@ -272,7 +272,7 @@ If the user is blocked via LDAP, `state` will be `ldap_blocked`.
}
```
-`owner_name` and `owner_email` are always `null`. Please see https://gitlab.com/gitlab-org/gitlab-ce/issues/39675.
+`owner_name` and `owner_email` are always `null`. Please see <https://gitlab.com/gitlab-org/gitlab-ce/issues/39675>.
**Group removed:**
@@ -289,7 +289,7 @@ If the user is blocked via LDAP, `state` will be `ldap_blocked`.
}
```
-`owner_name` and `owner_email` are always `null`. Please see https://gitlab.com/gitlab-org/gitlab-ce/issues/39675.
+`owner_name` and `owner_email` are always `null`. Please see <https://gitlab.com/gitlab-org/gitlab-ce/issues/39675>.
**Group renamed:**
@@ -309,7 +309,7 @@ If the user is blocked via LDAP, `state` will be `ldap_blocked`.
}
```
-`owner_name` and `owner_email` are always `null`. Please see https://gitlab.com/gitlab-org/gitlab-ce/issues/39675.
+`owner_name` and `owner_email` are always `null`. Please see <https://gitlab.com/gitlab-org/gitlab-ce/issues/39675>.
**New Group Member:**
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 766a23c419d..eef26612d5b 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -21,7 +21,7 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Enforce Two-factor Authentication (2FA)](../../security/two_factor_authentication.md#enforce-two-factor-authentication-2fa)
- **Articles:**
- [How to Configure LDAP with GitLab CE](../../administration/auth/how_to_configure_ldap_gitlab_ce/index.md)
- - [How to Configure LDAP with GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/)
+ - [How to Configure LDAP with GitLab EE](https://docs.gitlab.com/ee/administration/auth/how_to_configure_ldap_gitlab_ee/index.md)
- [Feature Highlight: LDAP Integration](https://about.gitlab.com/2014/07/10/feature-highlight-ldap-sync/)
- [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/support-engineering/ldap/debugging_ldap.html)
- **Integrations:**
@@ -35,7 +35,7 @@ This page gathers all the resources for the topic **Authentication** within GitL
## API
-- [OAuth 2 Tokens](../../api/README.md#oauth-2-tokens)
+- [OAuth 2 Tokens](../../api/README.md#oauth2-tokens)
- [Personal access tokens](../../api/README.md#personal-access-tokens)
- [Impersonation tokens](../../api/README.md#impersonation-tokens)
- [GitLab as an OAuth2 provider](../../api/oauth2.md#gitlab-as-an-oauth2-provider)
@@ -45,4 +45,4 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Kanboard Plugin GitLab Authentication](https://github.com/kanboard/plugin-gitlab-auth)
- [Jenkins GitLab OAuth Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+OAuth+Plugin)
- [How to customize GitLab to support OpenID authentication](http://eric.van-der-vlist.com/blog/2013/11/23/how-to-customize-gitlab-to-support-openid-authentication/)
-- [Openshift - Configuring Authentication and User Agent](https://docs.openshift.org/latest/install_config/configuring_authentication.html#GitLab)
+- [OKD - Configuring Authentication and User Agent](https://docs.okd.io/latest/install_config/configuring_authentication.html#GitLab)
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index b41f401e14c..195dd3e8846 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -13,7 +13,7 @@ Starting with GitLab 11.3, the Auto DevOps pipeline is enabled by default for al
projects. If it has not been explicitly enabled for the project, Auto DevOps will be automatically
disabled on the first pipeline failure. Your project will continue to use an alternative
[CI/CD configuration file](../../ci/yaml/README.md) if one is found. A GitLab
-administrator can [change this setting](../../user/admin_area/settings/continuous_integration.html#auto-devops)
+administrator can [change this setting](../../user/admin_area/settings/continuous_integration.html#auto-devops-core-only)
in the admin area.
With Auto DevOps, the software development process becomes easier to set up
@@ -58,15 +58,15 @@ project in a simple and automatic way:
1. [Auto Build](#auto-build)
1. [Auto Test](#auto-test)
-1. [Auto Code Quality](#auto-code-quality) **[STARTER]**
-1. [Auto SAST (Static Application Security Testing)](#auto-sast) **[ULTIMATE]**
-1. [Auto Dependency Scanning](#auto-dependency-scanning) **[ULTIMATE]**
-1. [Auto License Management](#auto-license-management) **[ULTIMATE]**
+1. [Auto Code Quality](#auto-code-quality-starter) **[STARTER]**
+1. [Auto SAST (Static Application Security Testing)](#auto-sast-ultimate) **[ULTIMATE]**
+1. [Auto Dependency Scanning](#auto-dependency-scanning-ultimate) **[ULTIMATE]**
+1. [Auto License Management](#auto-license-management-ultimate) **[ULTIMATE]**
1. [Auto Container Scanning](#auto-container-scanning)
1. [Auto Review Apps](#auto-review-apps)
-1. [Auto DAST (Dynamic Application Security Testing)](#auto-dast) **[ULTIMATE]**
+1. [Auto DAST (Dynamic Application Security Testing)](#auto-dast-ultimate) **[ULTIMATE]**
1. [Auto Deploy](#auto-deploy)
-1. [Auto Browser Performance Testing](#auto-browser-performance-testing) **[PREMIUM]**
+1. [Auto Browser Performance Testing](#auto-browser-performance-testing-premium) **[PREMIUM]**
1. [Auto Monitoring](#auto-monitoring)
As Auto DevOps relies on many different components, it's good to have a basic
@@ -114,7 +114,7 @@ To make full use of Auto DevOps, you will need:
will need Prometheus installed somewhere (inside or outside your cluster) and
configured to scrape your Kubernetes cluster. To get response metrics
(in addition to system metrics), you need to
- [configure Prometheus to monitor NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.md#configuring-prometheus-to-monitor-for-nginx-ingress-metrics).
+ [configure Prometheus to monitor NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.md#configuring-nginx-ingress-monitoring).
The [Prometheus service](../../user/project/integrations/prometheus.md)
integration needs to be enabled for the project, or enabled as a
[default service template](../../user/project/integrations/services_templates.md)
@@ -126,14 +126,22 @@ Auto Deploy, and Auto Monitoring will be silently skipped.
## Auto DevOps base domain
+NOTE: **Note**
+`AUTO_DEVOPS_DOMAIN` environment variable is deprecated and
+[is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959).
+
The Auto DevOps base domain is required if you want to make use of [Auto
Review Apps](#auto-review-apps) and [Auto Deploy](#auto-deploy). It can be defined
-in three places:
+in any of the following places:
-- either under the project's CI/CD settings while [enabling Auto DevOps](#enabling-auto-devops)
+- either under the cluster's settings, whether for [projects](../../user/project/clusters/index.md#base-domain) or [groups](../../user/group/clusters/index.md#base-domain)
- or in instance-wide settings in the **admin area > Settings** under the "Continuous Integration and Delivery" section
-- or at the project as a variable: `AUTO_DEVOPS_DOMAIN` (required if you want to use [multiple clusters](#using-multiple-kubernetes-clusters))
-- or at the group level as a variable: `AUTO_DEVOPS_DOMAIN`
+- or at the project level as a variable: `KUBE_INGRESS_BASE_DOMAIN`
+- or at the group level as a variable: `KUBE_INGRESS_BASE_DOMAIN`.
+
+NOTE: **Note**
+The Auto DevOps base domain variable (`KUBE_INGRESS_BASE_DOMAIN`) follows the same order of precedence
+as other environment [variables](../../ci/variables/README.md#priority-of-variables).
A wildcard DNS A record matching the base domain(s) is required, for example,
given a base domain of `example.com`, you'd need a DNS entry like:
@@ -158,7 +166,7 @@ them to the Kubernetes pods that run your application(s).
When using Auto DevOps, you may want to deploy different environments to
different Kubernetes clusters. This is possible due to the 1:1 connection that
-[exists between them](../../user/project/clusters/index.md#multiple-kubernetes-clusters).
+[exists between them](../../user/project/clusters/index.md#multiple-kubernetes-clusters-premium).
In the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
(used behind the scenes by Auto DevOps), there are currently 3 defined environment names that you need to know:
@@ -170,17 +178,17 @@ In the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab-ce/blob/maste
Those environments are tied to jobs that use [Auto Deploy](#auto-deploy), so
except for the environment scope, they would also need to have a different
domain they would be deployed to. This is why you need to define a separate
-`AUTO_DEVOPS_DOMAIN` variable for all the above
-[based on the environment](../../ci/variables/README.md#limiting-environment-scopes-of-variables).
+`KUBE_INGRESS_BASE_DOMAIN` variable for all the above
+[based on the environment](https://docs.gitlab.com/ee/ci/variables/index.html#limiting-environment-scopes-of-variables-premium).
The following table is an example of how the three different clusters would
be configured.
-| Cluster name | Cluster environment scope | `AUTO_DEVOPS_DOMAIN` variable value | Variable environment scope | Notes |
+| Cluster name | Cluster environment scope | `KUBE_INGRESS_BASE_DOMAIN` variable value | Variable environment scope | Notes |
| ------------ | -------------- | ----------------------------- | ------------- | ------ |
| review | `review/*` | `review.example.com` | `review/*` | The review cluster which will run all [Review Apps](../../ci/review_apps/index.md). `*` is a wildcard, which means it will be used by every environment name starting with `review/`. |
| staging | `staging` | `staging.example.com` | `staging` | (Optional) The staging cluster which will run the deployments of the staging environments. You need to [enable it first](#deploy-policy-for-staging-and-production-environments). |
-| production | `production` | `example.com` | `production` | The production cluster which will run the deployments of the production environment. You can use [incremental rollouts](#incremental-rollout-to-production). |
+| production | `production` | `example.com` | `production` | The production cluster which will run the deployments of the production environment. You can use [incremental rollouts](#incremental-rollout-to-production-premium). |
To add a different cluster for each environment:
@@ -190,14 +198,11 @@ To add a different cluster for each environment:
![Auto DevOps multiple clusters](img/autodevops_multiple_clusters.png)
1. After the clusters are created, navigate to each one and install Helm Tiller
- and Ingress.
+ and Ingress. Wait for the Ingress IP address to be assigned.
1. Make sure you have [configured your DNS](#auto-devops-base-domain) with the
specified Auto DevOps domains.
-1. Navigate to your project's **Settings > CI/CD > Variables** and add
- the `AUTO_DEVOPS_DOMAIN` variables with their respective environment
- scope.
-
- ![Auto DevOps domain variables](img/autodevops_domain_variables.png)
+1. Navigate to each cluster's page, through **Operations > Kubernetes**,
+ and add the domain based on its Ingress IP address.
Now that all is configured, you can test your setup by creating a merge request
and verifying that your app is deployed as a review app in the Kubernetes
@@ -205,10 +210,8 @@ cluster with the `review/*` environment scope. Similarly, you can check the
other environments.
NOTE: **Note:**
-Auto DevOps is not supported for a group with multiple clusters, as it
-is not possible to set `AUTO_DEVOPS_DOMAIN` per environment on the group
-level. This will be resolved in the future with the [following issue](
-https://gitlab.com/gitlab-org/gitlab-ce/issues/52363).
+From GitLab 11.8, `KUBE_INGRESS_BASE_DOMAIN` replaces `AUTO_DEVOPS_DOMAIN`.
+`AUTO_DEVOPS_DOMAIN` [is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959).
## Enabling/Disabling Auto DevOps
@@ -266,12 +269,12 @@ The available options are:
- **Continuous deployment to production**: Enables [Auto Deploy](#auto-deploy)
with `master` branch directly deployed to production.
- **Continuous deployment to production using timed incremental rollout**: Sets the
- [`INCREMENTAL_ROLLOUT_MODE`](#timed-incremental-rollout-to-production) variable
+ [`INCREMENTAL_ROLLOUT_MODE`](#timed-incremental-rollout-to-production-premium) variable
to `timed`, and production deployment will be executed with a 5 minute delay between
each increment in rollout.
- **Automatic deployment to staging, manual deployment to production**: Sets the
[`STAGING_ENABLED`](#deploy-policy-for-staging-and-production-environments) and
- [`INCREMENTAL_ROLLOUT_MODE`](#incremental-rollout-to-production) variables
+ [`INCREMENTAL_ROLLOUT_MODE`](#incremental-rollout-to-production-premium) variables
to `1` and `manual`. This means:
- `master` branch is directly deployed to staging.
@@ -284,21 +287,44 @@ to understand how each one works.
### Auto Build
-Auto Build creates a build of the application in one of two ways:
-
-- If there is a `Dockerfile`, it will use `docker build` to create a Docker image.
-- Otherwise, it will use [Herokuish](https://github.com/gliderlabs/herokuish)
- and [Heroku buildpacks](https://devcenter.heroku.com/articles/buildpacks)
- to automatically detect and build the application into a Docker image.
+Auto Build creates a build of the application using an existing `Dockerfile` or
+Heroku buildpacks.
Either way, the resulting Docker image is automatically pushed to the
-[Container Registry][container-registry] and tagged with the commit SHA.
+[Container Registry][container-registry] and tagged with the commit SHA or tag.
+
+#### Auto Build using a Dockerfile
+
+If a project's repository contains a `Dockerfile`, Auto Build will use
+`docker build` to create a Docker image.
-CAUTION: **Important:**
If you are also using Auto Review Apps and Auto Deploy and choose to provide
your own `Dockerfile`, make sure you expose your application to port
`5000` as this is the port assumed by the default Helm chart.
+#### Auto Build using Heroku buildpacks
+
+Auto Build builds an application using a project's `Dockerfile` if present, or
+otherwise it will use [Herokuish](https://github.com/gliderlabs/herokuish)
+and [Heroku buildpacks](https://devcenter.heroku.com/articles/buildpacks)
+to automatically detect and build the application into a Docker image.
+
+Each buildpack requires certain files to be in your project's repository for
+Auto Build to successfully build your application. For example, the following
+files are required at the root of your application's repository, depending on
+the language:
+
+- A `Pipfile` or `requirements.txt` file for Python projects.
+- A `Gemfile` or `Gemfile.lock` file for Ruby projects.
+
+For the requirements of other languages and frameworks, read the
+[buildpacks docs](https://devcenter.heroku.com/articles/buildpacks#officially-supported-buildpacks).
+
+TIP: **Tip:**
+If Auto Build fails despite the project meeting the buildpack requirements, set
+a project variable `TRACE=true` to enable verbose logging, which may help to
+troubleshoot.
+
### Auto Test
Auto Test automatically runs the appropriate tests for your application using
@@ -340,6 +366,9 @@ Any security warnings are also
NOTE: **Note:**
The Auto SAST stage will be skipped on licenses other than Ultimate.
+NOTE: **Note:**
+The Auto SAST job requires GitLab Runner 11.5 or above.
+
### Auto Dependency Scanning **[ULTIMATE]**
> Introduced in [GitLab Ultimate][ee] 10.7.
@@ -356,6 +385,9 @@ Any security warnings are also
NOTE: **Note:**
The Auto Dependency Scanning stage will be skipped on licenses other than Ultimate.
+NOTE: **Note:**
+The Auto Dependency Scanning job requires GitLab Runner 11.5 or above.
+
### Auto License Management **[ULTIMATE]**
> Introduced in [GitLab Ultimate][ee] 11.0.
@@ -471,7 +503,7 @@ Auto Deploy doesn't include deployments to staging or canary by default, but the
[Auto DevOps template] contains job definitions for these tasks if you want to
enable them.
-You can make use of [environment variables](#helm-chart-variables) to automatically
+You can make use of [environment variables](#environment-variables) to automatically
scale your pod replicas.
It's important to note that when a project is deployed to a Kubernetes cluster,
@@ -510,9 +542,9 @@ a helm pre-upgrade hook.
For example, in a Rails application:
-* `DB_INITIALIZE` can be set to `cd /app && RAILS_ENV=production
+- `DB_INITIALIZE` can be set to `cd /app && RAILS_ENV=production
bin/setup`
-* `DB_MIGRATE` can be set to `cd /app && RAILS_ENV=production bin/update`
+- `DB_MIGRATE` can be set to `cd /app && RAILS_ENV=production bin/update`
NOTE: **Note:**
The `/app` path is the directory of your project inside the docker image
@@ -521,7 +553,7 @@ Herokuish](https://github.com/gliderlabs/herokuish#paths)
> [Introduced][ce-19507] in GitLab 11.0.
-For internal and private projects a [GitLab Deploy Token](../../user/project/deploy_tokens/index.md###gitlab-deploy-token)
+For internal and private projects a [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token)
will be automatically created, when Auto DevOps is enabled and the Auto DevOps settings are saved. This Deploy Token
can be used for permanent access to the registry.
@@ -549,7 +581,7 @@ The metrics include:
In order to make use of monitoring you need to:
-1. [Deploy Prometheus](../../user/project/integrations/prometheus.md#configuring-your-own-prometheus-server-within-kubernetes) into your Kubernetes cluster
+1. [Deploy Prometheus](../../user/project/integrations/prometheus.md) into your Kubernetes cluster
1. If you would like response metrics, ensure you are running at least version
0.9.0 of NGINX Ingress and
[enable Prometheus metrics](https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/customization/custom-vts-metrics-prometheus/nginx-vts-metrics-conf.yaml).
@@ -603,7 +635,12 @@ repo or by specifying a project variable:
one](https://gitlab.com/charts/auto-deploy-app).
This can be a great way to control exactly how your application is deployed.
- **Project variable** - Create a [project variable](../../ci/variables/README.md#variables)
- `AUTO_DEVOPS_CHART` with the URL of a custom chart to use.
+ `AUTO_DEVOPS_CHART` with the URL of a custom chart to use or create two project variables `AUTO_DEVOPS_CHART_REPOSITORY` with the URL of a custom chart repository and `AUTO_DEVOPS_CHART` with the path to the chart.
+
+### Custom Helm chart per environment **[PREMIUM]**
+
+You can specify the use of a custom Helm chart per environment by scoping the environment variable
+to the desired environment. See [Limiting environment scopes of variables](https://docs.gitlab.com/ee/ci/variables/#limiting-environment-scopes-of-variables-premium).
### Customizing `.gitlab-ci.yml`
@@ -647,24 +684,28 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac
| **Variable** | **Description** |
| ------------ | --------------- |
-| `AUTO_DEVOPS_DOMAIN` | The [Auto DevOps domain](#auto-devops-domain); by default set automatically by the [Auto DevOps setting](#enabling-auto-devops). |
+| `AUTO_DEVOPS_DOMAIN` | The [Auto DevOps domain](#auto-devops-base-domain). By default, set automatically by the [Auto DevOps setting](#enablingdisabling-auto-devops). This variable is deprecated and [is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959). Use `KUBE_INGRESS_BASE_DOMAIN` instead. |
| `AUTO_DEVOPS_CHART` | The Helm Chart used to deploy your apps; defaults to the one [provided by GitLab](https://gitlab.com/charts/auto-deploy-app). |
+| `AUTO_DEVOPS_CHART_REPOSITORY` | The Helm Chart repository used to search for charts; defaults to `https://charts.gitlab.io`. |
| `REPLICAS` | The number of replicas to deploy; defaults to 1. |
| `PRODUCTION_REPLICAS` | The number of replicas to deploy in the production environment. This takes precedence over `REPLICAS`; defaults to 1. |
| `CANARY_REPLICAS` | The number of canary replicas to deploy for [Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html); defaults to 1 |
| `CANARY_PRODUCTION_REPLICAS` | The number of canary replicas to deploy for [Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html) in the production environment. This takes precedence over `CANARY_REPLICAS`; defaults to 1 |
+| `ADDITIONAL_HOSTS` | Fully qualified domain names specified as a comma-separated list that are added to the ingress hosts. |
+| `<ENVIRONMENT>_ADDITIONAL_HOSTS` | For a specific environment, the fully qualified domain names specified as a comma-separated list that are added to the ingress hosts. This takes precedence over `ADDITIONAL_HOSTS`. |
| `POSTGRES_ENABLED` | Whether PostgreSQL is enabled; defaults to `"true"`. Set to `false` to disable the automatic deployment of PostgreSQL. |
| `POSTGRES_USER` | The PostgreSQL user; defaults to `user`. Set it to use a custom username. |
| `POSTGRES_PASSWORD` | The PostgreSQL password; defaults to `testing-password`. Set it to use a custom password. |
-| `POSTGRES_DB` | The PostgreSQL database name; defaults to the value of [`$CI_ENVIRONMENT_SLUG`](../../ci/variables/README.md#predefined-variables-environment-variables). Set it to use a custom database name. |
+| `POSTGRES_DB` | The PostgreSQL database name; defaults to the value of [`$CI_ENVIRONMENT_SLUG`](../../ci/variables/README.md#predefined-environment-variables). Set it to use a custom database name. |
+| `POSTGRES_VERSION` | Tag for the [`postgres` Docker image](https://hub.docker.com/_/postgres) to use. Defaults to `9.6.2`. |
| `BUILDPACK_URL` | The buildpack's full URL. It can point to either Git repositories or a tarball URL. For Git repositories, it is possible to point to a specific `ref`, for example `https://github.com/heroku/heroku-buildpack-ruby.git#v142` |
| `SAST_CONFIDENCE_LEVEL` | The minimum confidence level of security issues you want to be reported; `1` for Low, `2` for Medium, `3` for High; defaults to `3`.|
| `DEP_SCAN_DISABLE_REMOTE_CHECKS` | Whether remote Dependency Scanning checks are disabled; defaults to `"false"`. Set to `"true"` to disable checks that send data to GitLab central servers. [Read more about remote checks](https://gitlab.com/gitlab-org/security-products/dependency-scanning#remote-checks).|
| `DB_INITIALIZE` | From GitLab 11.4, this variable can be used to specify the command to run to initialize the application's PostgreSQL database. It runs inside the application pod. |
| `DB_MIGRATE` | From GitLab 11.4, this variable can be used to specify the command to run to migrate the application's PostgreSQL database. It runs inside the application pod. |
| `STAGING_ENABLED` | From GitLab 10.8, this variable can be used to define a [deploy policy for staging and production environments](#deploy-policy-for-staging-and-production-environments). |
-| `CANARY_ENABLED` | From GitLab 11.0, this variable can be used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments). |
-| `INCREMENTAL_ROLLOUT_MODE`| From GitLab 11.4, this variable, if present, can be used to enable an [incremental rollout](#incremental-rollout-to-production) of your application for the production environment.<br/>Set to: <ul><li>`manual`, for manual deployment jobs.</li><li>`timed`, for automatic rollout deployments with a 5 minute delay each one.</li></ul> |
+| `CANARY_ENABLED` | From GitLab 11.0, this variable can be used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments-premium). |
+| `INCREMENTAL_ROLLOUT_MODE`| From GitLab 11.4, this variable, if present, can be used to enable an [incremental rollout](#incremental-rollout-to-production-premium) of your application for the production environment.<br/>Set to: <ul><li>`manual`, for manual deployment jobs.</li><li>`timed`, for automatic rollout deployments with a 5 minute delay each one.</li></ul> |
| `TEST_DISABLED` | From GitLab 11.0, this variable can be used to disable the `test` job. If the variable is present, the job will not be created. |
| `CODE_QUALITY_DISABLED` | From GitLab 11.0, this variable can be used to disable the `codequality` job. If the variable is present, the job will not be created. |
| `SAST_DISABLED` | From GitLab 11.0, this variable can be used to disable the `sast` job. If the variable is present, the job will not be created. |
@@ -673,6 +714,8 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac
| `REVIEW_DISABLED` | From GitLab 11.0, this variable can be used to disable the `review` and the manual `review:stop` job. If the variable is present, these jobs will not be created. |
| `DAST_DISABLED` | From GitLab 11.0, this variable can be used to disable the `dast` job. If the variable is present, the job will not be created. |
| `PERFORMANCE_DISABLED` | From GitLab 11.0, this variable can be used to disable the `performance` job. If the variable is present, the job will not be created. |
+| `K8S_SECRET_*` | From GitLab 11.7, any variable prefixed with [`K8S_SECRET_`](#application-secret-variables) will be made available by Auto DevOps as environment variables to the deployed application. |
+| `KUBE_INGRESS_BASE_DOMAIN` | From GitLab 11.8, this variable can be used to set a domain per cluster. See [cluster domains](../../user/project/clusters/index.md#base-domain) for more information. |
TIP: **Tip:**
Set up the replica variables using a
@@ -684,6 +727,63 @@ You should *not* scale your application using Kubernetes directly. This can
cause confusion with Helm not detecting the change, and subsequent deploys with
Auto DevOps can undo your changes.
+#### Application secret variables
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/49056) in GitLab 11.7.
+
+Some applications need to define secret variables that are
+accessible by the deployed application. Auto DevOps detects variables where the key starts with
+`K8S_SECRET_` and make these prefixed variables available to the
+deployed application, as environment variables.
+
+To configure your application variables:
+
+1. Go to your project's **Settings > CI/CD**, then expand the section
+ called **Variables**.
+
+2. Create a CI Variable, ensuring the key is prefixed with
+ `K8S_SECRET_`. For example, you can create a variable with key
+`K8S_SECRET_RAILS_MASTER_KEY`.
+
+3. Run an Auto Devops pipeline either by manually creating a new
+ pipeline or by pushing a code change to GitLab.
+
+Auto DevOps pipelines will take your application secret variables to
+populate a Kubernetes secret. This secret is unique per environment.
+When deploying your application, the secret is loaded as environment
+variables in the container running the application. Following the
+example above, you can see the secret below containing the
+`RAILS_MASTER_KEY` variable.
+
+```sh
+$ kubectl get secret production-secret -n minimal-ruby-app-54 -o yaml
+apiVersion: v1
+data:
+ RAILS_MASTER_KEY: MTIzNC10ZXN0
+kind: Secret
+metadata:
+ creationTimestamp: 2018-12-20T01:48:26Z
+ name: production-secret
+ namespace: minimal-ruby-app-54
+ resourceVersion: "429422"
+ selfLink: /api/v1/namespaces/minimal-ruby-app-54/secrets/production-secret
+ uid: 57ac2bfd-03f9-11e9-b812-42010a9400e4
+type: Opaque
+```
+
+CAUTION: **Caution:**
+Variables with multiline values are not currently supported due to
+limitations with the current Auto DevOps scripting environment.
+
+NOTE: **Note:**
+Environment variables are generally considered immutable in a Kubernetes
+pod. Therefore, if you update an application secret without changing any
+code then manually create a new pipeline, you will find that any running
+application pods will not have the updated secrets. In this case, you
+can either push a code update to GitLab to force the Kubernetes
+Deployment to recreate pods or manually delete running pods to
+cause Kubernetes to create new pods with updated secrets.
+
#### Advanced replica variables setup
Apart from the two replica-related variables for production mentioned above,
@@ -839,7 +939,7 @@ TIP: **Tip:**
You can also set this inside your [project's settings](#deployment-strategy).
This configuration based on
-[incremental rollout to production](#incremental-rollout-to-production).
+[incremental rollout to production](#incremental-rollout-to-production-premium).
Everything behaves the same way, except:
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 6326aadcdf2..367e192b85a 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -83,7 +83,7 @@ under which this application will be deployed.
![GitLab GKE cluster details](img/guide_gitlab_gke_details.png)
1. Once ready, click **Create Kubernetes cluster**.
-
+
NOTE: **Note:**
Do not select `f1-micro` from the **Machine type** dropdown. `f1-micro` machines cannot support a full GitLab installation.
@@ -159,15 +159,15 @@ In the **test** stage, GitLab runs various checks on the application:
- The `test` job runs unit and integration tests by detecting the language and
framework ([Auto Test](index.md#auto-test))
- The `code_quality` job checks the code quality and is allowed to fail
- ([Auto Code Quality](index.md#auto-code-quality)) **[STARTER]**
+ ([Auto Code Quality](index.md#auto-code-quality-starter)) **[STARTER]**
- The `container_scanning` job checks the Docker container if it has any
vulnerabilities and is allowed to fail ([Auto Container Scanning](index.md#auto-container-scanning))
- The `dependency_scanning` job checks if the application has any dependencies
- susceptible to vulnerabilities and is allowed to fail ([Auto Dependency Scanning](index.md#auto-dependency-scanning)) **[ULTIMATE]**
+ susceptible to vulnerabilities and is allowed to fail ([Auto Dependency Scanning](index.md#auto-dependency-scanning-ultimate)) **[ULTIMATE]**
- The `sast` job runs static analysis on the current code to check for potential
- security issues and is allowed to fail([Auto SAST](index.md#auto-sast)) **[ULTIMATE]**
+ security issues and is allowed to fail([Auto SAST](index.md#auto-sast-ultimate)) **[ULTIMATE]**
- The `license_management` job searches the application's dependencies to determine each of their
- licenses and is allowed to fail ([Auto License Management](index.md#auto-license-management)) **[ULTIMATE]**
+ licenses and is allowed to fail ([Auto License Management](index.md#auto-license-management-ultimate)) **[ULTIMATE]**
NOTE: **Note:**
As you might have noticed, all jobs except `test` are allowed to fail in the
@@ -178,7 +178,7 @@ deploys the application in Kubernetes ([Auto Deploy](index.md#auto-deploy)).
Lastly, in the **performance** stage, some performance tests will run
on the deployed application
-([Auto Browser Performance Testing](index.md#auto-browser-performance-testing)). **[PREMIUM]**
+([Auto Browser Performance Testing](index.md#auto-browser-performance-testing-premium)). **[PREMIUM]**
---
@@ -216,7 +216,7 @@ deployment and clicking a square will take you to the pod's logs page.
TIP: **Tip:**
There is only one pod hosting the application at the moment, but you can add
more pods by defining the [`REPLICAS` variable](index.md#environment-variables)
-under **Settings > CI/CD > Variables**.
+under **Settings > CI/CD > Environment variables**.
### Working with branches
@@ -285,8 +285,8 @@ all within GitLab. Despite its automatic nature, Auto DevOps can also be configu
and customized to fit your workflow. Here are some helpful resources for further reading:
1. [Auto DevOps](index.md)
-1. [Multiple Kubernetes clusters](index.md#using-multiple-kubernetes-clusters) **[PREMIUM]**
-1. [Incremental rollout to production](index.md#incremental-rollout-to-production) **[PREMIUM]**
+1. [Multiple Kubernetes clusters](index.md#using-multiple-kubernetes-clusters-premium) **[PREMIUM]**
+1. [Incremental rollout to production](index.md#incremental-rollout-to-production-premium) **[PREMIUM]**
1. [Disable jobs you don't need with environment variables](index.md#environment-variables)
1. [Use a static IP for your cluster](../../user/project/clusters/index.md#using-a-static-ip)
1. [Use your own buildpacks to build your application](index.md#custom-buildpacks)
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
index 7195b0f0f04..8a8021dc36d 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -45,7 +45,6 @@ Here's what we'll cover in this tutorial:
- [How to modify history](#how-modifying-history-is-done)
- [How to remove sensitive information from repository](#deleting-sensitive-information-from-commits)
-
### Branching strategy
[Git][git-official] is a de-centralized version control system, which means that beside regular
@@ -64,14 +63,12 @@ prevent that anything is lost or out of sync when feature is complete. You can a
read through this blog post on [Git Tips & Tricks][gitlab-git-tips-n-tricks]
to learn how to easily **do** things in Git.
-
## Undo local changes
Until you push your changes to any remote repository, they will only affect you.
That broadens your options on how to handle undoing them. Still, local changes
can be on various stages and each stage has a different approach on how to tackle them.
-
### Unstaged local changes (before you commit)
When a change is made, but it is not added to the staged tree, Git itself
@@ -315,7 +312,6 @@ In case you want to modify something introduced in commit `B`.
You can find some more examples in [below section where we explain how to modify
history](#how-modifying-history-is-done)
-
### Redoing the Undo
Sometimes you realize that the changes you undid were useful and you want them
@@ -396,8 +392,8 @@ a nicer history of your contribution.
Keep in mind that this also removes the comments attached to certain commits
in merge requests, so if you need to retain traceability in GitLab, then
modifying history is not acceptable.
-A feature-branch of a merge request is a public branch and might be used by
-other developers, but project process and rules might allow or require
+A feature-branch of a merge request is a public branch and might be used by
+other developers, but project process and rules might allow or require
you to use `git rebase` (command that changes history) to reduce number of
displayed commits on target branch after reviews are done (for example
GitLab). There is a `git merge --squash` command which does exactly that
diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md
index 7c7e44d29e7..254e234a22c 100644
--- a/doc/university/glossary/README.md
+++ b/doc/university/glossary/README.md
@@ -41,7 +41,7 @@ Objects (usually binary and large) created by a build process. These can include
### Atlassian
-A [company](https://www.atlassian.com) that develops software products for developers and project managers including Bitbucket, Jira, Hipchat, Confluence, Bamboo.
+A [company](https://www.atlassian.com) that develops software products for developers and project managers including Bitbucket, Jira, Confluence, Bamboo.
### Audit Log
@@ -241,7 +241,7 @@ Our free SaaS for public and private repositories.
### GitLab Geo
-Allows you to replicate your GitLab instance to other geographical locations as a read-only fully operational version. It [can be used](https://docs.gitlab.com/ee/gitlab-geo/README.html) for cloning and fetching projects, in addition to reading any data. This will make working with large repositories over large distances much faster.
+Allows you to replicate your GitLab instance to other geographical locations as a read-only fully operational version. It [can be used](https://docs.gitlab.com/ee/administration/geo/replication/index.html) for cloning and fetching projects, in addition to reading any data. This will make working with large repositories over large distances much faster.
### GitLab High Availability
@@ -303,7 +303,7 @@ A [tool](https://docs.gitlab.com/ee/integration/external-issue-tracker.html) use
### Jenkins
-An Open Source CI tool written using the Java programming language. [Jenkins](https://jenkins.io/) does the same job as GitLab CI, Bamboo, and Travis CI. It is extremely popular. Related [documentation](https://docs.gitlab.com/ee/integration/jenkins.html).
+An Open Source CI tool written using the Java programming language. [Jenkins](https://jenkins.io/) does the same job as GitLab CI, Bamboo, and Travis CI. It is extremely popular. Related [documentation](https://docs.gitlab.com/ee/integration/jenkins.html).
### Jira
@@ -407,7 +407,7 @@ A free disaster recovery [software](https://help.ubuntu.com/community/MondoMindi
#### Mount
-External reference:
+External reference:
As stated on the [wikipedia page](https://en.wikipedia.org/wiki/Mount_(Unix)), "Mounting makes file systems, files, directories, devices and special files available for use and available to the user."
@@ -423,7 +423,7 @@ A set of symbols that are used to organize objects of various kinds so that thes
### Nginx
-A web [server](https://www.nginx.com/resources/wiki/) (pronounced "engine x"). [It can act]((https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md) as a reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer and an HTTP cache.
+A web [server](https://www.nginx.com/resources/wiki/) (pronounced "engine x"). [It can act](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md) as a reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer and an HTTP cache.
### OAuth
@@ -447,7 +447,7 @@ Software for which the original source code is freely [available](https://openso
#### Open Source Stewardship
-[Related blog post](https://about.gitlab.com/2016/01/11/being-a-good-open-source-steward/).
+[Related blog post](https://about.gitlab.com/2016/01/11/being-a-good-open-source-steward/).
### Owner
@@ -557,7 +557,7 @@ Software that is hosted centrally and accessed on-demand (i.e. whenever you want
This term is often used by people when they mean "Version Control."
-### Scrum
+### Scrum
An Agile [framework](https://www.scrum.org/Resources/What-is-Scrum) designed to typically help complete complex software projects. It's made up of several parts: product requirements backlog, sprint planning, sprint (development), sprint review, and retrospec (analyzing the sprint). The goal is to end up with potentially shippable products.
@@ -697,7 +697,7 @@ A [website/system](http://www.wiki.com/) that allows for collaborative editing o
### Working area
-Files that have been modified but are not committed. Check them by using the command "git status".
+Files that have been modified but are not committed. Check them by using the command "git status".
### Working Tree
@@ -706,4 +706,3 @@ Files that have been modified but are not committed. Check them by using the com
### YAML
A human-readable data serialization [language](http://www.yaml.org/about.html) that takes concepts from programming languages such as C, Perl, and Python, and ideas from XML and the data format of electronic mail.
-
diff --git a/doc/university/high-availability/aws/README.md b/doc/university/high-availability/aws/README.md
index b21cf27c1d3..1906655dfa5 100644
--- a/doc/university/high-availability/aws/README.md
+++ b/doc/university/high-availability/aws/README.md
@@ -3,7 +3,7 @@ comments: false
---
> **Note**: We **do not** recommend using the AWS Elastic File System (EFS), as it can result
-in [significantly degraded performance](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/administration/high_availability/nfs.md#aws-elastic-file-system).
+in [significantly degraded performance](../../../administration/high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs).
# High Availability on AWS
@@ -66,10 +66,10 @@ RDS instances as well.
The subnets are listed with their name, AZ and CIDR block:
-* gitlab-public-10.0.0.0 - us-west-2a - 10.0.0.0
-* gitlab-private-10.0.1.0 - us-west-2a - 10.0.1.0
-* gitlab-public-10.0.2.0 - us-west-2b - 10.0.2.0
-* gitlab-private-10.0.3.0 - us-west-2b - 10.0.3.0
+- gitlab-public-10.0.0.0 - us-west-2a - 10.0.0.0
+- gitlab-private-10.0.1.0 - us-west-2a - 10.0.1.0
+- gitlab-public-10.0.2.0 - us-west-2b - 10.0.2.0
+- gitlab-private-10.0.3.0 - us-west-2b - 10.0.3.0
### Route Table
@@ -80,7 +80,6 @@ our newly created VPC.
![Route Table](img/route_table.png)
-
### Internet Gateway
Now still on the same dashboard head over to Internet Gateways and
@@ -126,10 +125,10 @@ image below we have the settings for this article but note the
following two options which are of particular interest for HA:
1. Multi-AZ-Deployment is recommended as redundancy. Read more at
-[High Availability (Multi-AZ)](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html)
+ [High Availability (Multi-AZ)](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html)
1. While we chose a General Purpose (SSD) for this article a Provisioned
-IOPS (SSD) is best suited for HA. Read more about it at
-[Storage for Amazon RDS](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html)
+ IOPS (SSD) is best suited for HA. Read more about it at
+ [Storage for Amazon RDS](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html)
![RDS Instance Specs](img/instance_specs.png)
@@ -161,7 +160,7 @@ private subnets.
Now press the Launch a Cache Cluster and choose Redis for our
DB engine. You'll be able to configure details such as replication,
Multi-AZ and node types. The second section will allow us to choose our
-subnet and security group and
+subnet and security group and
![Redis Cluster details](img/redis-cluster-det.png)
@@ -183,7 +182,7 @@ Another option is to build a simple NFS server using a vanilla Linux server back
by AWS Elastic Block Storage (EBS).
> **Note:** GitLab does not recommend using AWS Elastic File System (EFS). See
- details in [High Availability NFS documentation](../../../administration/high_availability/nfs.md#aws-elastic-file-system)
+ details in [High Availability NFS documentation](../../../administration/high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs)
***
@@ -206,7 +205,7 @@ http traffic from anywhere and name it something such as
`gitlab-ec2-security-group`.
While we wait for it to launch we can allocate an Elastic IP and
-associate it with our new EC2 instance.
+associate it with our new EC2 instance.
### RDS and Redis Security Group
@@ -238,7 +237,6 @@ running reconfigure we need to make sure all our services are tied down
so just leave the reconfigure command until after we edit our gitlab.rb
file.
-
### Extension for PostgreSQL
Connect to your new RDS instance to verify access and to install
@@ -268,8 +266,8 @@ our current case we'll specify the adapter, encoding, host, db name,
username, and password.
gitlab_rails['db_adapter'] = "postgresql"
- gitlab_rails['db_encoding'] = "unicode"
- gitlab_rails['db_database'] = "gitlabhq_production"
+ gitlab_rails['db_encoding'] = "unicode"
+ gitlab_rails['db_database'] = "gitlabhq_production"
gitlab_rails['db_username'] = "gitlab"
gitlab_rails['db_password'] = "mypassword"
gitlab_rails['db_host'] = "<rds-endpoint>"
@@ -277,8 +275,6 @@ username, and password.
Next, we only need to configure the Redis section by adding the host and
uncommenting the port.
-
-
The last configuration step is to [change the default file locations ](http://docs.gitlab.com/ee/administration/high_availability/nfs.html)
to make the EFS integration easier to manage.
@@ -288,9 +284,9 @@ to make the EFS integration easier to manage.
Finally, run reconfigure. You might find it useful to run a check and
a service status to make sure everything has been set up correctly.
- sudo gitlab-ctl reconfigure
- sudo gitlab-rake gitlab:check
- sudo gitlab-ctl status
+ sudo gitlab-ctl reconfigure
+ sudo gitlab-rake gitlab:check
+ sudo gitlab-ctl status
If everything looks good copy the Elastic IP over to your browser and
test the instance manually.
@@ -344,7 +340,6 @@ text area that allows us to add a lot of custom configurations which
allows you to add a custom script for when launching an instance. Let's
add the following script to the User Data section:
-
#cloud-config
package_upgrade: true
packages:
@@ -395,5 +390,5 @@ some redundancy options but it might also imply Geographic replication.
There is a lot of ground yet to cover so have a read through these other
resources and feel free to open an issue to request additional material.
-* [GitLab High Availability](http://docs.gitlab.com/ce/administration/high_availability/README.html#sts=High%20Availability)
-* [GitLab Geo](http://docs.gitlab.com/ee/gitlab-geo/README.html)
+- [GitLab High Availability](http://docs.gitlab.com/ce/administration/high_availability/README.html#sts=High%20Availability)
+- [GitLab Geo](https://docs.gitlab.com/ee/administration/geo/replication/index.html)
diff --git a/doc/university/support/README.md b/doc/university/support/README.md
index 805af253367..feb90ae9bad 100644
--- a/doc/university/support/README.md
+++ b/doc/university/support/README.md
@@ -2,7 +2,6 @@
comments: false
---
-
# Support Boot Camp
**Goal:** Prepare new Service Engineers at GitLab
diff --git a/doc/university/training/end-user/README.md b/doc/university/training/end-user/README.md
index 701533358c8..99fb5e83387 100644
--- a/doc/university/training/end-user/README.md
+++ b/doc/university/training/end-user/README.md
@@ -2,7 +2,6 @@
comments: false
---
-
# Training
This training material is the markdown used to generate training slides
@@ -50,7 +49,7 @@ project.
- Use the tools at your disposal when you get stuck.
- Use `git help <command>` command
- Use Google (i.e. StackOverflow, Google groups)
- - Read documentation at https://git-scm.com
+ - Read documentation at <https://git-scm.com>
---
@@ -62,7 +61,7 @@ Workshop Time!
### Setup
- Windows: Install 'Git for Windows'
- - https://git-for-windows.github.io
+ - <https://git-for-windows.github.io>
- Mac: Type `git` in the Terminal application.
- If it's not installed, it will prompt you to install it.
- Linux
@@ -87,6 +86,7 @@ git config --global user.email you@example.com
```bash
git config --global --list
```
+
- You might want or be required to use an SSH key.
- Instructions: [SSH](http://doc.gitlab.com/ce/ssh/README.html)
@@ -142,7 +142,7 @@ cd ~/workspace
- Sign in into your gitlab.com account
- Create a project
-- Choose to import from 'Any Repo by URL' and use https://gitlab.com/gitlab-org/training-examples.git
+- Choose to import from 'Any Repo by URL' and use <https://gitlab.com/gitlab-org/training-examples.git>
- On your machine clone the `training-examples` project
---
@@ -205,7 +205,6 @@ git push origin squash_some_bugs
- Anyone can comment, not just the assignee
- Push corrections to the same branch
-
---
### Merge request example
@@ -242,10 +241,11 @@ git push origin squash_some_bugs
---
### Merge Conflicts
-* Happen often
-* Learning to fix conflicts is hard
-* Practice makes perfect
-* Force push after fixing conflicts. Be careful!
+
+- Happen often
+- Learning to fix conflicts is hard
+- Practice makes perfect
+- Force push after fixing conflicts. Be careful!
---
@@ -306,10 +306,10 @@ Create a merge request on the GitLab web UI. You'll see a conflict warning.
### Notes
-* When to use `git merge` and when to use `git rebase`
-* Rebase when updating your branch with master
-* Merge when bringing changes from feature to master
-* Reference: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/
+- When to use `git merge` and when to use `git rebase`
+- Rebase when updating your branch with master
+- Merge when bringing changes from feature to master
+- Reference: <https://www.atlassian.com/git/tutorials/merging-vs-rebasing/>
---
@@ -394,7 +394,6 @@ git revert vs git reset
Reset removes the commit while revert removes the changes but leaves the commit
Revert is safer considering we can revert a revert
-
# Changed file
git commit -am "bug introduced"
git revert HEAD
@@ -415,6 +414,7 @@ Revert is safer considering we can revert a revert
---
### Version Control
+
- Local VCS was used with a filesystem or a simple db.
- Centralized VCS such as Subversion includes collaboration but
still is prone to data loss as the main server is the single point of
diff --git a/doc/university/training/topics/env_setup.md b/doc/university/training/topics/env_setup.md
index bdf805711e0..78ca30e0f55 100644
--- a/doc/university/training/topics/env_setup.md
+++ b/doc/university/training/topics/env_setup.md
@@ -8,7 +8,7 @@ comments: false
## Install
- **Windows**
- - Install 'Git for Windows' from https://git-for-windows.github.io
+ - Install 'Git for Windows' from <https://git-for-windows.github.io>
- **Mac**
- Type '`git`' in the Terminal application.
diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md
index 66cb08feacb..d76ff57bfa3 100644
--- a/doc/university/training/topics/getting_started.md
+++ b/doc/university/training/topics/getting_started.md
@@ -8,12 +8,12 @@ comments: false
## Instantiating Repositories
-* Create a new repository by instantiating it through
+- Create a new repository by instantiating it through:
```bash
git init
```
-* Copy an existing project by cloning the repository through
+- Copy an existing project by cloning the repository through:
```bash
git clone <url>
@@ -23,9 +23,9 @@ comments: false
## Central Repos
-* To instantiate a central repository a `--bare` flag is required.
-* Bare repositories don't allow file editing or committing changes.
-* Create a bare repo with
+- To instantiate a central repository a `--bare` flag is required.
+- Bare repositories don't allow file editing or committing changes.
+- Create a bare repo with:
```bash
git init --bare project-name.git
@@ -97,5 +97,5 @@ git log
## Note
-* git fetch vs pull
-* Pull is git fetch + git merge
+- git fetch vs pull
+- Pull is git fetch + git merge
diff --git a/doc/university/training/topics/git_add.md b/doc/university/training/topics/git_add.md
index b1483e725fe..e02a7deab91 100644
--- a/doc/university/training/topics/git_add.md
+++ b/doc/university/training/topics/git_add.md
@@ -10,13 +10,13 @@ comments: false
Adds content to the index or staging area.
-* Adds a list of file
+- Adds a list of file:
```bash
git add <files>
```
-* Adds all files including deleted ones
+- Adds all files including deleted ones:
```bash
git add -A
@@ -26,19 +26,19 @@ Adds content to the index or staging area.
## Git add continued
-* Add all text files in current dir
+- Add all text files in current dir:
```bash
git add *.txt
```
-* Add all text file in the project
+- Add all text file in the project:
```bash
git add "*.txt*"
```
-* Adds all files in directory
+- Adds all files in directory:
```bash
git add views/layouts/
diff --git a/doc/university/training/topics/git_intro.md b/doc/university/training/topics/git_intro.md
index 7e502d6dad4..127323c292c 100644
--- a/doc/university/training/topics/git_intro.md
+++ b/doc/university/training/topics/git_intro.md
@@ -8,7 +8,7 @@ comments: false
## Intro
-https://git-scm.com/about
+<https://git-scm.com/about>
- Distributed version control
- Does not rely on connection to a central server
@@ -25,4 +25,4 @@ Use the tools at your disposal when you get stuck.
- Use '`git help <command>`' command
- Use Google
-- Read documentation at https://git-scm.com
+- Read documentation at <https://git-scm.com>
diff --git a/doc/university/training/topics/git_log.md b/doc/university/training/topics/git_log.md
index 6ba6f9eb69d..763ef802a04 100644
--- a/doc/university/training/topics/git_log.md
+++ b/doc/university/training/topics/git_log.md
@@ -8,19 +8,19 @@ comments: false
Git log lists commit history. It allows searching and filtering.
-* Initiate log
+- Initiate log:
```
git log
```
-* Retrieve set number of records:
+- Retrieve set number of records:
```
git log -n 2
```
-* Search commits by author. Allows user name or a regular expression.
+- Search commits by author. Allows user name or a regular expression.
```
git log --author="user_name"
@@ -28,19 +28,18 @@ Git log lists commit history. It allows searching and filtering.
----------
-* Search by comment message.
+- Search by comment message:
```
git log --grep="<pattern>"
```
-* Search by date
+- Search by date:
```
git log --since=1.month.ago --until=3.weeks.ago
```
-
----------
## Git Log Workflow
diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md
index 071baddf508..a7d42904229 100644
--- a/doc/university/training/topics/merge_conflicts.md
+++ b/doc/university/training/topics/merge_conflicts.md
@@ -68,7 +68,8 @@ git push origin conflicts_branch -f
----------
## Note
-* When to use 'git merge' and when to use 'git rebase'
-* Rebase when updating your branch with master
-* Merge when bringing changes from feature to master
-* Reference: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/
+
+- When to use 'git merge' and when to use 'git rebase'
+- Rebase when updating your branch with master
+- Merge when bringing changes from feature to master
+- Reference: <https://www.atlassian.com/git/tutorials/merging-vs-rebasing/>
diff --git a/doc/university/training/topics/rollback_commits.md b/doc/university/training/topics/rollback_commits.md
index 44304634f36..96b89e3319a 100644
--- a/doc/university/training/topics/rollback_commits.md
+++ b/doc/university/training/topics/rollback_commits.md
@@ -8,13 +8,13 @@ comments: false
## Undo Commits
-* Undo last commit putting everything back into the staging area.
+- Undo last commit putting everything back into the staging area:
```
git reset --soft HEAD^
```
-* Add files and change message with:
+- Add files and change message with:
```
git commit --amend -m "New Message"
@@ -22,13 +22,13 @@ comments: false
----------
-* Undo last and remove changes
+- Undo last and remove changes:
```
git reset --hard HEAD^
```
-* Same as last one but for two commits back
+- Same as last one but for two commits back:
```
git reset --hard HEAD^^
@@ -51,7 +51,6 @@ comments: false
1. Pull for updates
1. Push changes
-
----------
## Commands
@@ -73,9 +72,9 @@ git push origin master
## Note
-* git revert vs git reset
-* Reset removes the commit while revert removes the changes but leaves the commit
-* Revert is safer considering we can revert a revert
+- git revert vs git reset
+- Reset removes the commit while revert removes the changes but leaves the commit
+- Revert is safer considering we can revert a revert
```
# Changed file
diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md
index 42eedea14e5..dfd28fbcbc9 100644
--- a/doc/university/training/topics/stash.md
+++ b/doc/university/training/topics/stash.md
@@ -9,7 +9,7 @@ comments: false
We use git stash to store our changes when they are not ready to be committed
and we need to change to a different branch.
-* Stash
+- Stash:
```
git stash save
@@ -19,7 +19,7 @@ and we need to change to a different branch.
git stash save "this is a message to display on the list"
```
-* Apply stash to keep working on it
+- Apply stash to keep working on it:
```
git stash apply
@@ -29,8 +29,8 @@ and we need to change to a different branch.
----------
-* Every time we save a stash it gets stacked so by using list we can see all our
-stashes.
+- Every time we save a stash it gets stacked so by using list we can see all our
+ stashes.
```
git stash list
@@ -38,7 +38,7 @@ stashes.
git stash list --stat
```
-* To clean our stack we need to manually remove them.
+- To clean our stack we need to manually remove them:
```
# drop top stash
@@ -51,15 +51,14 @@ stashes.
----------
-* Apply and drop on one command
+- Apply and drop on one command:
```
git stash pop
```
-* If we meet conflicts we need to either reset or commit our changes.
-
-* Conflicts through `pop` will not drop a stash afterwards.
+- If we meet conflicts we need to either reset or commit our changes.
+- Conflicts through `pop` will not drop a stash afterwards.
----------
diff --git a/doc/university/training/topics/subtree.md b/doc/university/training/topics/subtree.md
index b5a892dc17b..ba7c3394938 100644
--- a/doc/university/training/topics/subtree.md
+++ b/doc/university/training/topics/subtree.md
@@ -4,20 +4,20 @@ comments: false
# Subtree
-* Used when there are nested repositories.
-* Not recommended when the amount of dependencies is too large
-* For these cases we need a dependency control system
-* Command are painfully long so aliases are necessary
+- Used when there are nested repositories.
+- Not recommended when the amount of dependencies is too large.
+- For these cases we need a dependency control system.
+- Command are painfully long so aliases are necessary.
----------
## Subtree Aliases
-* Add: git subtree add --prefix <target-folder> <url> <branch> --squash
-* Pull: git subtree add --prefix <target-folder> <url> <branch> --squash
-* Push: git subtree add --prefix <target-folder> <url> <branch>
-* Ex: git config alias.sbp 'subtree pull --prefix st /
- git@gitlab.com:balameb/subtree-nested-example.git master --squash'
+- Add: git subtree add --prefix <target-folder> <url> <branch> --squash.
+- Pull: git subtree add --prefix <target-folder> <url> <branch> --squash.
+- Push: git subtree add --prefix <target-folder> <url> <branch>.
+- Ex: git config alias.sbp 'subtree pull --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master --squash'.
----------
diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md
index ee7913637b9..da36a3218e5 100644
--- a/doc/university/training/topics/unstage.md
+++ b/doc/university/training/topics/unstage.md
@@ -8,13 +8,13 @@ comments: false
## Unstage
-* To remove files from stage use reset HEAD. Where HEAD is the last commit of the current branch.
+- To remove files from stage use reset HEAD. Where HEAD is the last commit of the current branch.
```bash
git reset HEAD <file>
```
-* This will unstage the file but maintain the modifications. To revert the file back to the state it was in before the changes we can use:
+- This will unstage the file but maintain the modifications. To revert the file back to the state it was in before the changes we can use:
```bash
git checkout -- <file>
@@ -22,14 +22,14 @@ comments: false
----------
-* To remove a file from disk and repo use 'git rm' and to rm a dir use the '-r' flag.
+- To remove a file from disk and repo use 'git rm' and to rm a dir use the '-r' flag:
```
git rm '*.txt'
git rm -r <dirname>
```
-* If we want to remove a file from the repository but keep it on disk, say we forgot to add it to our `.gitignore` file then use `--cache`.
+- If we want to remove a file from the repository but keep it on disk, say we forgot to add it to our `.gitignore` file then use `--cache`:
```
git rm <filename> --cache
diff --git a/doc/update/10.0-to-10.1.md b/doc/update/10.0-to-10.1.md
index af815d26a74..8514aa13f48 100644
--- a/doc/update/10.0-to-10.1.md
+++ b/doc/update/10.0-to-10.1.md
@@ -1,360 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 10.0 to 10.1
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.5.tar.gz
-echo '3247e217d6745c27ef23bdc77b6abdb4b57a118f ruby-2.3.5.tar.gz' | shasum -c - && tar xzf ruby-2.3.5.tar.gz
-cd ruby-2.3.5
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-1-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-1-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-0-stable:config/gitlab.yml.example origin/10-1-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/10-0-stable:lib/support/nginx/gitlab-ssl origin/10-1-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/10-0-stable:lib/support/nginx/gitlab origin/10-1-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-1-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-1-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-0-stable:lib/support/init.d/gitlab.default.example origin/10-1-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (10.0)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 9.5 to 10.0](9.5-to-10.0.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-1-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-1-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/10.1-to-10.2.md b/doc/update/10.1-to-10.2.md
index 632e8befa74..8514aa13f48 100644
--- a/doc/update/10.1-to-10.2.md
+++ b/doc/update/10.1-to-10.2.md
@@ -1,360 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 10.1 to 10.2
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.5.tar.gz
-echo '3247e217d6745c27ef23bdc77b6abdb4b57a118f ruby-2.3.5.tar.gz' | shasum -c - && tar xzf ruby-2.3.5.tar.gz
-cd ruby-2.3.5
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-2-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-2-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-1-stable:config/gitlab.yml.example origin/10-2-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/10-1-stable:lib/support/nginx/gitlab-ssl origin/10-2-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/10-1-stable:lib/support/nginx/gitlab origin/10-2-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-2-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-2-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-1-stable:lib/support/init.d/gitlab.default.example origin/10-2-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (10.1)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 10.0 to 10.1](10.0-to-10.1.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-2-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-2-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/10.2-to-10.3.md b/doc/update/10.2-to-10.3.md
index f8fe4a4b6bf..8514aa13f48 100644
--- a/doc/update/10.2-to-10.3.md
+++ b/doc/update/10.2-to-10.3.md
@@ -1,359 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 10.2 to 10.3
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.5.tar.gz
-echo '3247e217d6745c27ef23bdc77b6abdb4b57a118f ruby-2.3.5.tar.gz' | shasum -c - && tar xzf ruby-2.3.5.tar.gz
-cd ruby-2.3.5
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets.
-We require a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-3-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-3-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-2-stable:config/gitlab.yml.example origin/10-3-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/10-2-stable:lib/support/nginx/gitlab-ssl origin/10-3-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/10-2-stable:lib/support/nginx/gitlab origin/10-3-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-3-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-3-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-2-stable:lib/support/init.d/gitlab.default.example origin/10-3-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (10.2)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 10.1 to 10.2](10.1-to-10.2.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-3-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-3-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/10.3-to-10.4.md b/doc/update/10.3-to-10.4.md
index 083f6090a8a..8514aa13f48 100644
--- a/doc/update/10.3-to-10.4.md
+++ b/doc/update/10.3-to-10.4.md
@@ -1,361 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 10.3 to 10.4
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.6.tar.gz
-echo '4e6a0f828819e15d274ae58485585fc8b7caace0 ruby-2.3.6.tar.gz' | shasum -c - && tar xzf ruby-2.3.6.tar.gz
-cd ruby-2.3.6
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets.
-We require a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-4-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-4-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-3-stable:config/gitlab.yml.example origin/10-4-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/10-3-stable:lib/support/nginx/gitlab-ssl origin/10-4-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/10-3-stable:lib/support/nginx/gitlab origin/10-4-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-4-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-4-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-3-stable:lib/support/init.d/gitlab.default.example origin/10-4-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (10.3)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 10.2 to 10.3](10.2-to-10.3.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-4-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-4-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/10.4-to-10.5.md b/doc/update/10.4-to-10.5.md
index 313419ed13d..8514aa13f48 100644
--- a/doc/update/10.4-to-10.5.md
+++ b/doc/update/10.4-to-10.5.md
@@ -1,361 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 10.4 to 10.5
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.6.tar.gz
-echo '4e6a0f828819e15d274ae58485585fc8b7caace0 ruby-2.3.6.tar.gz' | shasum -c - && tar xzf ruby-2.3.6.tar.gz
-cd ruby-2.3.6
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets.
-We require a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-5-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-5-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-4-stable:config/gitlab.yml.example origin/10-5-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/10-4-stable:lib/support/nginx/gitlab-ssl origin/10-5-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/10-4-stable:lib/support/nginx/gitlab origin/10-5-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-5-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-5-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-4-stable:lib/support/init.d/gitlab.default.example origin/10-5-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (10.4)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 10.3 to 10.4](10.3-to-10.4.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-5-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-5-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/10.5-to-10.6.md b/doc/update/10.5-to-10.6.md
index 2f90fb62c4a..8514aa13f48 100644
--- a/doc/update/10.5-to-10.6.md
+++ b/doc/update/10.5-to-10.6.md
@@ -1,361 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 10.5 to 10.6
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.6.tar.gz
-echo '4e6a0f828819e15d274ae58485585fc8b7caace0 ruby-2.3.6.tar.gz' | shasum -c - && tar xzf ruby-2.3.6.tar.gz
-cd ruby-2.3.6
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-6-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-6-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-5-stable:config/gitlab.yml.example origin/10-6-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/10-5-stable:lib/support/nginx/gitlab-ssl origin/10-6-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/10-5-stable:lib/support/nginx/gitlab origin/10-6-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-6-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-6-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-5-stable:lib/support/init.d/gitlab.default.example origin/10-6-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (10.5)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 10.4 to 10.5](10.4-to-10.5.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-6-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-6-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/10.6-to-10.7.md b/doc/update/10.6-to-10.7.md
index b9c14395a3a..8514aa13f48 100644
--- a/doc/update/10.6-to-10.7.md
+++ b/doc/update/10.6-to-10.7.md
@@ -1,361 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 10.6 to 10.7
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.6.tar.gz
-echo '4e6a0f828819e15d274ae58485585fc8b7caace0 ruby-2.3.6.tar.gz' | shasum -c - && tar xzf ruby-2.3.6.tar.gz
-cd ruby-2.3.6
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.9 and dropped support for Go
-1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz
-echo 'd70eadefce8e160638a9a6db97f7192d8463069ab33138893ad3bf31b0650a79 go1.9.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.9.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.9.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-7-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-7-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-6-stable:config/gitlab.yml.example origin/10-7-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/10-6-stable:lib/support/nginx/gitlab-ssl origin/10-7-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/10-6-stable:lib/support/nginx/gitlab origin/10-7-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-7-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-7-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-6-stable:lib/support/init.d/gitlab.default.example origin/10-7-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (10.6)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 10.5 to 10.6](10.5-to-10.6.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-7-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-7-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/10.7-to-10.8.md b/doc/update/10.7-to-10.8.md
index 7bb628f9740..8514aa13f48 100644
--- a/doc/update/10.7-to-10.8.md
+++ b/doc/update/10.7-to-10.8.md
@@ -1,362 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 10.7 to 10.8
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download Ruby and compile it:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.7.tar.gz
-echo '540996fec64984ab6099e34d2f5820b14904f15a ruby-2.3.7.tar.gz' | shasum -c - && tar xzf ruby-2.3.7.tar.gz
-cd ruby-2.3.7
-
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-8-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-8-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-7-stable:config/gitlab.yml.example origin/10-8-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/10-7-stable:lib/support/nginx/gitlab-ssl origin/10-8-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/10-7-stable:lib/support/nginx/gitlab origin/10-8-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-8-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-8-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-7-stable:lib/support/init.d/gitlab.default.example origin/10-8-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (10.7)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 10.6 to 10.7](10.6-to-10.7.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-8-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-8-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/10.8-to-11.0.md b/doc/update/10.8-to-11.0.md
index 22a0c9f950c..8514aa13f48 100644
--- a/doc/update/10.8-to-11.0.md
+++ b/doc/update/10.8-to-11.0.md
@@ -1,361 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 10.8 to 11.0
-
-Make sure you view this update guide from the branch (version) of GitLab you would
-like to install (e.g., `11-0-stable`. You can select the branch in the version
-dropdown at the top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download Ruby and compile it:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz
-echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz
-cd ruby-2.4.4
-
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
-1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
-echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-0-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-0-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-8-stable:config/gitlab.yml.example origin/11-0-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/10-8-stable:lib/support/nginx/gitlab-ssl origin/11-0-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/10-8-stable:lib/support/nginx/gitlab origin/11-0-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-0-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-0-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/10-8-stable:lib/support/init.d/gitlab.default.example origin/11-0-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (10.8)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 10.7 to 10.8](10.7-to-10.8.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-0-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-0-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/11.0-to-11.1.md b/doc/update/11.0-to-11.1.md
index 3f10a7edb8a..8514aa13f48 100644
--- a/doc/update/11.0-to-11.1.md
+++ b/doc/update/11.0-to-11.1.md
@@ -1,378 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 11.0 to 11.1
-
-Make sure you view this update guide from the branch (version) of GitLab you would
-like to install (e.g., `11-1-stable`. You can select the branch in the version
-dropdown at the top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download Ruby and compile it:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz
-echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz
-cd ruby-2.4.4
-
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
-1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
-echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-1-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-1-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update gitlab-pages
-
-#### Only needed if you use GitLab Pages.
-
-Install and compile gitlab-pages. GitLab-Pages uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-pages
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
-sudo -u git -H make
-```
-
-### 11. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 12. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-0-stable:config/gitlab.yml.example origin/11-1-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/11-0-stable:lib/support/nginx/gitlab-ssl origin/11-1-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/11-0-stable:lib/support/nginx/gitlab origin/11-1-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-1-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-1-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-0-stable:lib/support/init.d/gitlab.default.example origin/11-1-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 13. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 14. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 15. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (11.0)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 10.8 to 11.0](10.8-to-11.0.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-1-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-1-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/11.1-to-11.2.md b/doc/update/11.1-to-11.2.md
index 3edc7e6923e..8514aa13f48 100644
--- a/doc/update/11.1-to-11.2.md
+++ b/doc/update/11.1-to-11.2.md
@@ -1,378 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 11.1 to 11.2
-
-Make sure you view this update guide from the branch (version) of GitLab you would
-like to install (e.g., `11-2-stable`. You can select the branch in the version
-dropdown at the top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download Ruby and compile it:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz
-echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz
-cd ruby-2.4.4
-
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
-1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
-echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-2-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-2-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update gitlab-pages
-
-#### Only needed if you use GitLab Pages.
-
-Install and compile gitlab-pages. GitLab-Pages uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-pages
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
-sudo -u git -H make
-```
-
-### 11. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 12. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-1-stable:config/gitlab.yml.example origin/11-2-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/11-1-stable:lib/support/nginx/gitlab-ssl origin/11-2-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/11-1-stable:lib/support/nginx/gitlab origin/11-2-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-2-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-2-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-1-stable:lib/support/init.d/gitlab.default.example origin/11-2-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 13. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 14. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 15. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (11.1)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 11.0 to 11.1](11.0-to-11.1.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-2-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-2-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/11.2-to-11.3.md b/doc/update/11.2-to-11.3.md
index f2b8efc3e6e..8514aa13f48 100644
--- a/doc/update/11.2-to-11.3.md
+++ b/doc/update/11.2-to-11.3.md
@@ -1,378 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 11.2 to 11.3
-
-Make sure you view this update guide from the branch (version) of GitLab you would
-like to install (e.g., `11-3-stable`. You can select the branch in the version
-dropdown at the top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download Ruby and compile it:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz
-echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz
-cd ruby-2.4.4
-
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
-1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
-echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-3-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-3-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update gitlab-pages
-
-#### Only needed if you use GitLab Pages.
-
-Install and compile gitlab-pages. GitLab-Pages uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-pages
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
-sudo -u git -H make
-```
-
-### 11. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 12. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-2-stable:config/gitlab.yml.example origin/11-3-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/11-2-stable:lib/support/nginx/gitlab-ssl origin/11-3-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/11-2-stable:lib/support/nginx/gitlab origin/11-3-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-2-stable:lib/support/init.d/gitlab.default.example origin/11-3-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 13. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 14. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 15. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (11.2)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 11.1 to 11.2](11.1-to-11.2.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/11.3-to-11.4.md b/doc/update/11.3-to-11.4.md
index fddec45e57a..8514aa13f48 100644
--- a/doc/update/11.3-to-11.4.md
+++ b/doc/update/11.3-to-11.4.md
@@ -1,378 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 11.3 to 11.4
-
-Make sure you view this update guide from the branch (version) of GitLab you would
-like to install (e.g., `11-4-stable`. You can select the branch in the version
-dropdown at the top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download Ruby and compile it:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.5.tar.gz
-echo '4d650f302f1ec00256450b112bb023644b6ab6dd ruby-2.4.5.tar.gz' | shasum -c - && tar xzf ruby-2.4.5.tar.gz
-cd ruby-2.4.5
-
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 11.4 and higher only supports Go 1.10.x and newer, and dropped support for Go
-1.9.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
-echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-4-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-4-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update gitlab-pages
-
-#### Only needed if you use GitLab Pages.
-
-Install and compile gitlab-pages. GitLab-Pages uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-pages
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
-sudo -u git -H make
-```
-
-### 11. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 12. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-3-stable:config/gitlab.yml.example origin/11-4-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/11-3-stable:lib/support/nginx/gitlab-ssl origin/11-4-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/11-3-stable:lib/support/nginx/gitlab origin/11-4-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-3-stable:lib/support/init.d/gitlab.default.example origin/11-4-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 13. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 14. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 15. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (11.3)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 11.2 to 11.3](11.2-to-11.3.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/11.4-to-11.5.md b/doc/update/11.4-to-11.5.md
index 44105348d14..8514aa13f48 100644
--- a/doc/update/11.4-to-11.5.md
+++ b/doc/update/11.4-to-11.5.md
@@ -1,390 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 11.4 to 11.5
-
-Make sure you view this update guide from the branch (version) of GitLab you would
-like to install (e.g., `11-5-stable`. You can select the branch in the version
-dropdown at the top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download Ruby and compile it:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.5.tar.gz
-echo '4d650f302f1ec00256450b112bb023644b6ab6dd ruby-2.4.5.tar.gz' | shasum -c - && tar xzf ruby-2.4.5.tar.gz
-cd ruby-2.4.5
-
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 11.4 and higher only supports Go 1.10.x and newer, and dropped support for Go
-1.9.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://dl.google.com/go/go1.10.5.linux-amd64.tar.gz
-echo 'a035d9beda8341b645d3f45a1b620cf2d8fb0c5eb409be36b389c0fd384ecc3a go1.10.5.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.5.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.5.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-5-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-5-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update gitlab-pages
-
-#### Only needed if you use GitLab Pages.
-
-Install and compile gitlab-pages. GitLab-Pages uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-pages
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
-sudo -u git -H make
-```
-
-### 11. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 12. Update configuration files
-
-#### New `unicorn.rb` configuration
-
-Note: we have made [changes](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22372) to `unicorn.rb` to allow GitLab run with both Unicorn and Puma in future.
-
-- Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/config/unicorn.rb.example but with your settings.
- - In particular, make sure that `require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"` line exists and the `before_exec`, `before_fork`, and `after_fork` handlers are configured as shown below:
-
-```ruby
-require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
-
-before_exec do |server|
- # Signal application hooks that we're about to restart
- Gitlab::Cluster::LifecycleEvents.do_master_restart
-end
-
-before_fork do |server, worker|
- # Signal application hooks that we're about to fork
- Gitlab::Cluster::LifecycleEvents.do_before_fork
-end
-
-after_fork do |server, worker|
- # Signal application hooks of worker start
- Gitlab::Cluster::LifecycleEvents.do_worker_start
-end
-```
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-4-stable:config/gitlab.yml.example origin/11-5-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/11-4-stable:lib/support/nginx/gitlab-ssl origin/11-5-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/11-4-stable:lib/support/nginx/gitlab origin/11-5-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-4-stable:lib/support/init.d/gitlab.default.example origin/11-5-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 13. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 14. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 15. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (11.4)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 11.3 to 11.4](11.3-to-11.4.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/11.5-to-11.6.md b/doc/update/11.5-to-11.6.md
index 031abc434ca..8514aa13f48 100644
--- a/doc/update/11.5-to-11.6.md
+++ b/doc/update/11.5-to-11.6.md
@@ -1,390 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 11.5 to 11.6
-
-Make sure you view this update guide from the branch (version) of GitLab you would
-like to install (e.g., `11-6-stable`. You can select the branch in the version
-dropdown at the top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download Ruby and compile it:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
-echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
-cd ruby-2.5.3
-
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 11.4 and higher only supports Go 1.10.x and newer, and dropped support for Go
-1.9.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://dl.google.com/go/go1.10.5.linux-amd64.tar.gz
-echo 'a035d9beda8341b645d3f45a1b620cf2d8fb0c5eb409be36b389c0fd384ecc3a go1.10.5.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.5.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.5.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-6-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-6-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update gitlab-pages
-
-#### Only needed if you use GitLab Pages
-
-Install and compile gitlab-pages. GitLab-Pages uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-pages
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
-sudo -u git -H make
-```
-
-### 11. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 12. Update configuration files
-
-#### New `unicorn.rb` configuration
-
-We have made [changes](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22372) to `unicorn.rb` to allow GitLab run with both Unicorn and Puma in future.
-
-Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/11-6-stable/config/unicorn.rb.example but with your settings.
-In particular, make sure that `require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"` line exists and the `before_exec`, `before_fork`, and `after_fork` handlers are configured as shown below:
-
-```ruby
-require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
-
-before_exec do |server|
- # Signal application hooks that we're about to restart
- Gitlab::Cluster::LifecycleEvents.do_master_restart
-end
-
-before_fork do |server, worker|
- # Signal application hooks that we're about to fork
- Gitlab::Cluster::LifecycleEvents.do_before_fork
-end
-
-after_fork do |server, worker|
- # Signal application hooks of worker start
- Gitlab::Cluster::LifecycleEvents.do_worker_start
-end
-```
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-5-stable:config/gitlab.yml.example origin/11-6-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/11-5-stable:lib/support/nginx/gitlab-ssl origin/11-6-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/11-5-stable:lib/support/nginx/gitlab origin/11-6-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-6-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-6-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-5-stable:lib/support/init.d/gitlab.default.example origin/11-6-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 13. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 14. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 15. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (11.5)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 11.4 to 11.5](11.4-to-11.5.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-6-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-6-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/11.6-to-11.7.md b/doc/update/11.6-to-11.7.md
new file mode 100644
index 00000000000..8514aa13f48
--- /dev/null
+++ b/doc/update/11.6-to-11.7.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_source.md
+---
+
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/11.7-to-11.8.md b/doc/update/11.7-to-11.8.md
new file mode 100644
index 00000000000..8514aa13f48
--- /dev/null
+++ b/doc/update/11.7-to-11.8.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_source.md
+---
+
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/2.6-to-3.0.md b/doc/update/2.6-to-3.0.md
index 8f18bd93cea..8514aa13f48 100644
--- a/doc/update/2.6-to-3.0.md
+++ b/doc/update/2.6-to-3.0.md
@@ -1,70 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 2.6 to 3.0
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/2.6-to-3.0.md) for the most up to date instructions.*
-
-## 1. Stop server & resque
-
- sudo service gitlab stop
-
-## 2. Update code & db
-
-
-```bash
-# Get latest code
-git fetch origin
-git checkout v3.0.3
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u gitlab -H vim Gemfile
-
-# Install libs
-sudo -u gitlab bundle install --without development test postgres
-
-# update db
-sudo -u gitlab bundle exec rake db:migrate RAILS_ENV=production
-
-# !!! Config should be replaced with a new one. Check it after replace
-cp config/gitlab.yml.example config/gitlab.yml
-
-# update Gitolite hooks
-
-# Gitolite v2:
-sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive
-sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive
-
-# Gitolite v3:
-sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
-sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
-
-# set valid path to hooks in gitlab.yml in git_host section
-# like this
-git_host:
- # Gitolite 2
- hooks_path: /home/git/share/gitolite/hooks
- # Gitolite 3
- hooks_path: /home/git/.gitolite/hooks/
-
-
-# Make some changes to Gitolite config
-# For more information visit https://github.com/gitlabhq/gitlabhq/pull/1719
-
-# Gitolite v2
-sudo -u git -H sed -i 's/\(GL_GITCONFIG_KEYS\s*=>*\s*\).\{2\}/\\1"\.\*"/g' /home/git/.gitolite.rc
-
-# gitlite v3
-sudo -u git -H sed -i "s/\(GIT_CONFIG_KEYS\s*=>*\s*\).\{2\}/\\1'\.\*'/g" /home/git/.gitolite.rc
-
-
-# Check app status
-sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production
-
-```
-
-## 3. Start all
-
- sudo service gitlab start
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/2.9-to-3.0.md b/doc/update/2.9-to-3.0.md
index 6a3c2387683..8514aa13f48 100644
--- a/doc/update/2.9-to-3.0.md
+++ b/doc/update/2.9-to-3.0.md
@@ -1,46 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 2.9 to 3.0
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/2.9-to-3.0.md) for the most up to date instructions.*
-
-## 1. Stop server & resque
-
- sudo service gitlab stop
-
-## 2. Follow instructions
-
-```bash
-
-# Get latest code
-sudo -u gitlab -H git fetch origin
-sudo -u gitlab -H git checkout v3.0.3
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u gitlab -H vim Gemfile
-
-# Install gems
-sudo -u gitlab -H bundle install --without development test postgres
-
-# Migrate db
-sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Make some changes to gitolite v3 config
-# For more information visit https://github.com/gitlabhq/gitlabhq/pull/1719
-
-# Gitolite version 3
-sudo -u git -H sed -i "s/\(GIT_CONFIG_KEYS\s*=>*\s*\).\{2\}/\\1'\.\*'/g" /home/git/.gitolite.rc
-
-# If you still use gitolite v2
-sudo -u git -H sed -i 's/\(GL_GITCONFIG_KEYS\s*=>*\s*\).\{2\}/\\1"\.\*"/g' /home/git/.gitolite.rc
-
-# Check APP Status
-sudo -u gitlab -H bundle exec rake gitlab:app:status RAILS_ENV=production
-```
-
-## 3. Start all
-
- sudo service gitlab start
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/3.0-to-3.1.md b/doc/update/3.0-to-3.1.md
index 1f25b8265c9..8514aa13f48 100644
--- a/doc/update/3.0-to-3.1.md
+++ b/doc/update/3.0-to-3.1.md
@@ -1,106 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 3.0 to 3.1
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/3.0-to-3.1.md) for the most up to date instructions.*
-
-**IMPORTANT!**
-
-In this release **we moved Resque jobs under own gitlab namespace**
-
-Despite a lot of advantages it requires from our users to **replace gitolite post-receive hook with new one**.
-
-Most of projects has post-receive file as symlink to gitolite `/home/git/.gitolite/hooks/post-receive`. But some of them may have a real file. In this case you should rewrite it with symlink to gitolite hook.
-
-I wrote a bash script which will do it automatically for you. Just make sure all path inside is valid for you
-
-## 1. Stop server & resque
-
- sudo service gitlab stop
-
-## 2. Update GitLab
-
-```bash
-# Get latest code
-sudo -u gitlab -H git fetch
-sudo -u gitlab -H git checkout v3.1.0
-
-# Install new charlock_holmes
-sudo gem install charlock_holmes --version '0.6.9'
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u gitlab -H vim Gemfile
-
-# Install gems for MySQL
-sudo -u gitlab -H bundle install --without development test postgres sqlite
-
-
-# Migrate db
-sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production
-
-```
-
-## 3. Update post-receive hooks
-
-### Gitolite 3
-
-Step 1: Rewrite post-receive hook
-
-```bash
-# Rewrite hook for gitolite 3
-sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
-sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
-```
-
-Step 2: Rewrite hooks in all projects to symlink gitolite hook
-
-```bash
-# 1. Check for valid path
-sudo -u gitlab -H vim lib/support/rewrite-hooks.sh
-
-# 2. Run script
-sudo -u git -H lib/support/rewrite-hooks.sh
-```
-
-### Gitolite v2
-
-Step 1: rewrite post-receive hook for gitolite 2
-
-```
-sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive
-sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive
-```
-
-Step 2: Replace symlinks in project to valid place
-
- #!/bin/bash
- src="/home/git/repositories"
- for dir in `ls "$src/"`
- do
- if [ -d "$src/$dir" ]; then
-
- if [ "$dir" = "gitolite-admin.git" ]
- then
- continue
- fi
-
- project_hook="$src/$dir/hooks/post-receive"
- gitolite_hook="/home/git/share/gitolite/hooks/common/post-receive"
-
- ln -s -f $gitolite_hook $project_hook
- fi
- done
-
-## 4. Check app status
-
-```bash
-# Check APP Status
-sudo -u gitlab -H bundle exec rake gitlab:app:status RAILS_ENV=production
-```
-
-## 5. Start all
-
- sudo service gitlab start
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/3.1-to-4.0.md b/doc/update/3.1-to-4.0.md
index 1a53ddeb4bd..8514aa13f48 100644
--- a/doc/update/3.1-to-4.0.md
+++ b/doc/update/3.1-to-4.0.md
@@ -1,99 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 3.1 to 4.0
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/3.1-to-4.0.md) for the most up to date instructions.*
-
-## Important changes
-
-- Support for SQLite was dropped
-- Support for Gitolite 2 was dropped
-- Projects are organized in namespaces
-- The GitLab post-receive hook needs to be updated
-- The configuration file needs to be updated
-- Availability of `python2` executable
-
-Most of projects has post-receive file as symlink to Gitolite `/home/git/.gitolite/hooks/post-receive`. But some of them may have a real file. In this case you should rewrite it with symlink to Gitolite hook.
-
-I wrote a bash script which will do it automatically for you. Just make sure all path inside is valid for you
-
-## 1. Stop GitLab & Resque
-
- sudo service gitlab stop
-
-## 2. Update GitLab
-
-```bash
-
-# Get latest code
-sudo -u gitlab -H git fetch
-sudo -u gitlab -H git checkout 4-0-stable
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u gitlab -H vim Gemfile
-
-# Install gems for MySQL
-sudo -u gitlab -H bundle install --without development test postgres
-
-# Update repos permissions
-sudo chmod -R ug+rwXs /home/git/repositories/
-sudo chown -R git:git /home/git/repositories/
-
-# Migrate db
-sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Enable namespaces (**Warning!** All projects in groups will be moved to subdirectories)
-sudo -u gitlab -H bundle exec rake gitlab:enable_namespaces RAILS_ENV=production
-
-```
-
-## 3. Update post-receive hooks (Requires Gitolite v3 )
-
-Step 1: Rewrite post-receive hook
-
-```bash
-sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
-sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
-```
-
-Step 2: Update project hooks to be symlinks to the Gitolite hook
-
-```bash
-# 1. Check paths in script
-sudo -u gitlab -H vim lib/support/rewrite-hooks.sh
-
-# 2. Run script
-sudo -u git -H lib/support/rewrite-hooks.sh
-```
-
-## 4. Replace config with new one
-
- # backup old one
- sudo -u gitlab -H cp config/gitlab.yml config/gitlab.yml.old
-
- # copy new one
- sudo -u gitlab -H cp config/gitlab.yml.example config/gitlab.yml
-
- # edit it
- sudo -u gitlab -H vim config/gitlab.yml
-
-## 5. Disable ssh known_host check for own domain
-
- echo "Host localhost
- StrictHostKeyChecking no
- UserKnownHostsFile=/dev/null" | sudo tee -a /etc/ssh/ssh_config
-
- echo "Host YOUR_DOMAIN_NAME
- StrictHostKeyChecking no
- UserKnownHostsFile=/dev/null" | sudo tee -a /etc/ssh/ssh_config
-
-## 6. Check GitLab's status
-
- sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production
-
-## 7. Start GitLab & Resque
-
- sudo service gitlab start
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/4.0-to-4.1.md b/doc/update/4.0-to-4.1.md
index 40a133e796e..8514aa13f48 100644
--- a/doc/update/4.0-to-4.1.md
+++ b/doc/update/4.0-to-4.1.md
@@ -1,65 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 4.0 to 4.1
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/4.0-to-4.1.md) for the most up to date instructions.*
-
-## Important changes
-
-- Resque replaced with Sidekiq
-- New options for configuration file added
-- Init.d script should be updated
-- **requires ruby1.9.3-p327**
-
-## 1. Stop GitLab & Resque
-
- sudo service gitlab stop
-
-## 2. Update GitLab
-
-```bash
-# Set the working directory
-cd /home/gitlab/gitlab/
-
-# Get latest code
-sudo -u gitlab -H git fetch
-sudo -u gitlab -H git checkout 4-1-stable
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u gitlab -H vim Gemfile
-
-# Install gems for MySQL
-sudo -u gitlab -H bundle install --without development test postgres
-
-# Migrate db
-sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production
-
-```
-
-## 3. Replace init.d script with a new one
-
-```
-# backup old one
-sudo mv /etc/init.d/gitlab /etc/init.d/gitlab.old
-
-# get new one using sidekiq
-sudo curl --location --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/4-1-stable/init.d/gitlab
-sudo chmod +x /etc/init.d/gitlab
-
-```
-
-## 4. Check GitLab's status
-
- sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production
-
-
-## 5. Start GitLab & Sidekiq
-
- sudo service gitlab start
-
-## 6. Remove old init.d script
-
- sudo rm /etc/init.d/gitlab.old
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/4.1-to-4.2.md b/doc/update/4.1-to-4.2.md
index 1fd6c58bda7..8514aa13f48 100644
--- a/doc/update/4.1-to-4.2.md
+++ b/doc/update/4.1-to-4.2.md
@@ -1,48 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 4.1 to 4.2
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/4.1-to-4.2.md) for the most up to date instructions.*
-
-## 1. Stop server & Resque
-
- sudo service gitlab stop
-
-## 2. Update code & DB
-
-```bash
-
-#Set the working directory
-cd /home/gitlab/gitlab/
-
-# Get latest code
-sudo -u gitlab -H git fetch
-
-sudo -u gitlab -H git checkout 4-2-stable
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u gitlab -H vim Gemfile
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u gitlab -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u gitlab -H bundle install --without development test postgres --deployment
-
-# update db
-sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production
-
-```
-
-## 3. Check GitLab's status
-
-```bash
-sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-## 4. Start all
-
- sudo service gitlab start
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md
index d292327efbd..8514aa13f48 100644
--- a/doc/update/4.2-to-5.0.md
+++ b/doc/update/4.2-to-5.0.md
@@ -1,224 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 4.2 to 5.0
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/4.2-to-5.0.md) for the most up to date instructions.*
-
-## Warning
-
-GitLab 5.0 is affected by critical security vulnerability CVE-2013-4490.
-
-## Important changes
-
-- We don't use `gitlab` user any more. Everything will be moved to `git` user
-- Self signed SSL certificates are not supported until GitLab 5.1
-- **requires ruby1.9.3**
-
-## 0. Stop GitLab
-
- sudo service gitlab stop
-
-## 1. add bash to git user
-
-```
-sudo chsh -s /bin/bash git
-```
-
-## 2. git clone gitlab-shell
-
-```
-cd /home/git/
-sudo -u git -H git clone https://github.com/gitlabhq/gitlab-shell.git /home/git/gitlab-shell
-```
-
-## 3. set up gitlab-shell
-
-```bash
-# chmod all repos and files under git
-sudo chown git:git -R /home/git/repositories/
-
-# login as git
-sudo su git
-cd /home/git/gitlab-shell
-git checkout v1.1.0
-
-# copy config
-cp config.yml.example config.yml
-
-# change URL to GitLab instance
-# ! make sure the URL ends with '/' like 'https://gitlab.example/'
-vim config.yml
-
-# rewrite hooks
-./support/rewrite-hooks.sh
-
-# check ruby version for git user ( 1.9 required!! )
-# GitLab shell requires system ruby 1.9
-ruby -v
-
-# exit from git user
-exit
-```
-
-## 4. Copy GitLab instance to git user
-
-```bash
-sudo cp -R /home/gitlab/gitlab /home/git/gitlab
-sudo chown git:git -R /home/git/gitlab
-sudo rm -rf /home/gitlab/gitlab-satellites
-
-# if exists
-sudo rm /tmp/gitlab.socket
-```
-
-## 5. Update GitLab to recent version
-
-```bash
-cd /home/git/gitlab
-
-# backup current config
-sudo -u git -H cp config/gitlab.yml config/gitlab.yml.old
-
-sudo -u git -H git fetch
-sudo -u git -H git checkout 5-0-stable
-
-# replace config with recent one
-sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml
-
-# edit it
-sudo -u git -H vim config/gitlab.yml
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production
-sudo -u git -H bundle exec rake gitlab:shell:build_missing_projects RAILS_ENV=production
-
-sudo -u git -H mkdir -p /home/git/gitlab-satellites
-sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production
-
-# migrate wiki to git
-sudo -u git -H bundle exec rake gitlab:wiki:migrate RAILS_ENV=production
-
-
-# check permissions for /home/git/.ssh/
-sudo -u git -H chmod 700 /home/git/.ssh
-sudo -u git -H chmod 600 /home/git/.ssh/authorized_keys
-
-# check permissions for /home/git/gitlab/
-sudo chown -R git /home/git/gitlab/log/
-sudo chown -R git /home/git/gitlab/tmp/
-sudo chmod -R u+rwX /home/git/gitlab/log/
-sudo chmod -R u+rwX /home/git/gitlab/tmp/
-sudo -u git -H mkdir -p /home/git/gitlab/tmp/pids/
-sudo chmod -R u+rwX /home/git/gitlab/tmp/pids
-
-```
-
-## 6. Update init.d script and Nginx config
-
-```bash
-# init.d
-sudo rm /etc/init.d/gitlab
-sudo curl --location --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/5-0-stable/init.d/gitlab
-sudo chmod +x /etc/init.d/gitlab
-
-# unicorn
-sudo -u git -H cp /home/git/gitlab/config/unicorn.rb /home/git/gitlab/config/unicorn.rb.old
-sudo -u git -H cp /home/git/gitlab/config/unicorn.rb.example /home/git/gitlab/config/unicorn.rb
-
-# Nginx
-# Replace path from '/home/gitlab/' to '/home/git/'
-sudo vim /etc/nginx/sites-enabled/gitlab
-sudo service nginx restart
-
-```
-
-## 7. Start GitLab instance
-
-```
-sudo service gitlab start
-
-# check if unicorn and sidekiq started
-# If not try to logout, also check replaced path from '/home/gitlab/' to '/home/git/'
-# in Nginx, unicorn, init.d etc
-ps aux | grep unicorn
-ps aux | grep sidekiq
-
-```
-
-## 8. Check installation
-
-
-```bash
-# In 5-10 seconds lets check gitlab-shell
-sudo -u git -H /home/git/gitlab-shell/bin/check
-
-# Example of success output
-# Check GitLab API access: OK
-# Check directories and files:
-# /home/git/repositories: OK
-# /home/git/.ssh/authorized_keys: OK
-
-
-# Now check GitLab instance
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-```
-
-## 9. Cleanup
-
-**If everything works as expected you can cleanup some old things**
-Recommend you wait a bit and do a backup before completing the following.
-
-```bash
-# remove GitLab user from system
-sudo userdel -r gitlab
-
-cd /home/git
-
-# cleanup .profile
-## remove text from .profile added during gitolite installation:
-## PATH=\$PATH:/home/git/bin
-## export PATH
-## to see what a clean .profile for new users on your system would look like see /etc/skel/.profile
-sudo -u git -H vim .profile
-
-# remove gitolite
-sudo rm -R bin
-sudo rm -Rf gitolite
-sudo rm -R .gitolite
-sudo rm .gitolite.rc
-sudo rm -f gitlab.pub
-sudo rm projects.list
-
-# reset tmp folders
-sudo service gitlab stop
-cd /home/git/gitlab
-sudo rm -R tmp
-sudo -u git -H mkdir tmp
-sudo chmod -R u+rwX tmp/
-
-# create directory for pids, make sure GitLab can write to it
-sudo -u git -H mkdir tmp/pids/
-sudo chmod -R u+rwX tmp/pids/
-
-# if you are already running a newer version of GitLab check that installation guide for other tmp folders you need to create
-
-# reboot system
-sudo reboot
-
-# login, check that GitLab is running fine
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/5.0-to-5.1.md b/doc/update/5.0-to-5.1.md
index 7067ea4c40c..8514aa13f48 100644
--- a/doc/update/5.0-to-5.1.md
+++ b/doc/update/5.0-to-5.1.md
@@ -1,105 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 5.0 to 5.1
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.0-to-5.1.md) for the most up to date instructions.*
-
-## Warning
-
-GitLab 5.1 is affected by critical security vulnerability CVE-2013-4490.
-
-## Release notes
-
-- `unicorn` replaced with `puma`
-- merge request cached diff will be truncated
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch
-sudo -u git -H git checkout 5-1-stable
-```
-
-## 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.3.0
-# replace your old config with the new one
-sudo -u git -H mv config.yml config.yml.old
-sudo -u git -H cp config.yml.example config.yml
-# edit options to match old config
-sudo -u git -H vi config.yml
-```
-
-## 4. Install libs, migrations etc
-
-```bash
-cd /home/git/gitlab
-sudo rm tmp/sockets/gitlab.socket
-sudo -u git -H cp config/puma.rb.example config/puma.rb
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_merge_requests RAILS_ENV=production
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-```
-
-## 5. Update init.d script with a new one
-
-```bash
-# init.d
-sudo rm /etc/init.d/gitlab
-sudo curl --location --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/5-1-stable/init.d/gitlab
-sudo chmod +x /etc/init.d/gitlab
-```
-
-## 6. MySQL grant privileges
-
-Only if you are using MySQL:
-
-```bash
-mysql -u root -p
-mysql> GRANT LOCK TABLES ON `gitlabhq_production`.* TO 'gitlab'@'localhost';
-mysql> \q
-```
-
-## 7. Start application
-
- sudo service gitlab start
-
-## 8. Check installation
-
-
-```bash
-# In 5-10 seconds lets check gitlab-shell
-sudo -u git -H /home/git/gitlab-shell/bin/check
-
-# Example of success output
-# Check GitLab API access: OK
-# Check directories and files:
-# /home/git/repositories: OK
-# /home/git/.ssh/authorized_keys: OK
-
-
-# Now check gitlab instance
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/5.1-to-5.2.md b/doc/update/5.1-to-5.2.md
index 4faf5fa549e..8514aa13f48 100644
--- a/doc/update/5.1-to-5.2.md
+++ b/doc/update/5.1-to-5.2.md
@@ -1,124 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 5.1 to 5.2
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.1-to-5.2.md) for the most up to date instructions.*
-
-## Warning
-
-GitLab 5.2 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489.
-
-## 0. Backup
-
-It's useful to make a backup just in case things go south:
-(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch
-sudo -u git -H git checkout 5-2-stable
-```
-
-## 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.4.0
-```
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-```
-
-## 5. Update config files
-
-- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-2-stable/config/gitlab.yml.example but with your settings.
-- Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-2-stable/config/puma.rb.example but with your settings.
-
-## 6. Update Init script
-
-```bash
-cd /home/git/gitlab
-sudo rm /etc/init.d/gitlab
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-sudo chmod +x /etc/init.d/gitlab
-```
-
-## 7. Create uploads directory
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H mkdir public/uploads
-sudo chmod -R u+rwX public/uploads
-```
-
-## 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## Things went south? Revert to previous version (5.1)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 5.0 to 5.1](5.0-to-5.1.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/5.1-to-5.4.md b/doc/update/5.1-to-5.4.md
index 212343bac3f..8514aa13f48 100644
--- a/doc/update/5.1-to-5.4.md
+++ b/doc/update/5.1-to-5.4.md
@@ -1,120 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 5.1 to 5.4
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.1-to-5.4.md) for the most up to date instructions.*
-
-Also works starting from 5.2.
-
-## 0. Backup
-
-It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version):
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch
-sudo -u git -H git checkout 5-4-stable # Latest version of 5-4-stable addresses CVE-2013-4489
-```
-
-## 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
-```
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-```
-
-## 5. Update config files
-
-- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/gitlab.yml.example but with your settings.
-- Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/puma.rb.example but with your settings.
-
-## 6. Update Init script
-
-```bash
-sudo rm /etc/init.d/gitlab
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-sudo chmod +x /etc/init.d/gitlab
-```
-
-## 7. Create uploads directory
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H mkdir public/uploads
-sudo chmod -R u+rwX public/uploads
-```
-
-## 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## Things went south? Revert to previous version (5.3)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 5.2 to 5.3](5.2-to-5.3.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/5.1-to-6.0.md b/doc/update/5.1-to-6.0.md
index 865d38e0ca4..8514aa13f48 100644
--- a/doc/update/5.1-to-6.0.md
+++ b/doc/update/5.1-to-6.0.md
@@ -1,236 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 5.1 to 6.0
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.1-to-6.0.md) for the most up to date instructions.*
-
-## Warning
-
-GitLab 6.0 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489.
-
-## Deprecations
-
-### Global projects
-
-The root (global) namespace for projects is deprecated.
-
-So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote URL. Please make sure you disable sending email when you do a test of the upgrade.
-
-### Teams
-
-We introduce group membership in 6.0 as a replacement for teams.
-
-The old combination of groups and teams was confusing for a lot of people.
-
-And when the members of a team where changed this wasn't reflected in the project permissions.
-
-In GitLab 6.0 you will be able to add members to a group with a permission level for each member.
-
-These group members will have access to the projects in that group.
-
-Any changes to group members will immediately be reflected in the project permissions.
-
-You can even have multiple owners for a group, greatly simplifying administration.
-
-## 0. Backup & prepare for update
-
-It's useful to make a backup just in case things go south:
-(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-The migrations in this update are very sensitive to incomplete or inconsistent data. If you have a long-running GitLab installation and some of the previous upgrades did not work out 100% correct this may bite you now. The following can help you have a more smooth upgrade.
-
-### Find projects with invalid project names
-
-#### MySQL
-Login to MySQL:
-
- mysql -u root -p
-
-Find projects with invalid names:
-
-```bash
-mysql> use gitlabhq_production;
-
-# find projects with invalid first char, projects must start with letter
-mysql> select name from projects where name REGEXP '^[^A-Za-z]';
-
-# find projects with other invalid chars
-## names must only contain alphanumeric chars, underscores, spaces, periods, and dashes
-mysql> select name from projects where name REGEXP '[^a-zA-Z0-9_ .-]+';
-```
-
-If any projects have invalid names try correcting them from the web interface before starting the upgrade.
-If correcting them from the web interface fails you can correct them using MySQL:
-
-```bash
-# e.g. replace invalid / with allowed _
-mysql> update projects set name = REPLACE(name,'/','_');
-# repeat for all invalid chars found in project names
-```
-
-#### PostgreSQL
-Make sure all project names start with a letter and only contain alphanumeric chars, underscores, spaces, periods, and dashes (a-zA-Z0-9_ .-).
-
-### Find other common errors
-
-```
-cd /home/git/gitlab
-# Start rails console
-sudo -u git -H bin/rails console production
-
-# Make sure none of the following rails commands return results
-
-# All project owners should have an owner:
-Project.all.select { |project| project.owner.blank? }
-
-# Every user should have a namespace:
-User.all.select { |u| u.namespace.blank? }
-
-# Projects in the global namespace should not conflict with projects in the owner namespace:
-Project.where(namespace_id: nil).select { |p| Project.where(path: p.path, namespace_id: p.owner.try(:namespace).try(:id)).present? }
-```
-
-If any of the above rails commands returned results other than `=> []` try correcting the issue from the web interface.
-
-If you find projects without an owner (first rails command above), correct it. For MySQL setups:
-
-```bash
-# get your user id
-mysql> select id, name from users order by name;
-
-# set yourself as owner of project
-# replace your_user_id with your user id and bad_project_id with the project id from the rails command
-mysql> update projects set creator_id=your_user_id where id=bad_project_id;
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch
-sudo -u git -H git checkout 6-0-stable
-```
-
-## 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.9
-```
-
-## 4. Install additional packages
-
-```bash
-# For reStructuredText markup language support install required package:
-sudo apt-get install python-docutils
-```
-
-## 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_groups RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production
-sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production
-
-# Clear redis cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-
-# Clear and precompile assets
-sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-
-#Add dealing with newlines for editor
-sudo -u git -H git config --global core.autocrlf input
-```
-
-## 6. Update config files
-
-Note: We switched from Puma in GitLab 5.x to unicorn in GitLab 6.0.
-
-- Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-0-stable/config/gitlab.yml.example but with your settings.
-- Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-0-stable/config/unicorn.rb.example but with your settings.
-
-## 7. Update Init script
-
-```bash
-cd /home/git/gitlab
-sudo rm /etc/init.d/gitlab
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-sudo chmod +x /etc/init.d/gitlab
-```
-
-## 8. Create uploads directory
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H mkdir -p public/uploads
-sudo chmod -R u+rwX public/uploads
-```
-
-## 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## Things went south? Revert to previous version (5.1)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 5.0 to 5.1](5.0-to-5.1.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/5.2-to-5.3.md b/doc/update/5.2-to-5.3.md
index ed4f3ebdd53..8514aa13f48 100644
--- a/doc/update/5.2-to-5.3.md
+++ b/doc/update/5.2-to-5.3.md
@@ -1,106 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 5.2 to 5.3
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.2-to-5.3.md) for the most up to date instructions.*
-
-## Warning
-
-GitLab 5.3 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489.
-
-## 0. Backup
-
-It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version):
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch
-sudo -u git -H git checkout 5-3-stable
-```
-
-## 3. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-```
-
-## 4. Update config files
-
-- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-3-stable/config/gitlab.yml.example but with your settings.
-- Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-3-stable/config/puma.rb.example but with your settings.
-
-## 5. Update Init script
-
-```bash
-sudo rm /etc/init.d/gitlab
-sudo curl --location --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-3-stable/lib/support/init.d/gitlab
-sudo chmod +x /etc/init.d/gitlab
-```
-
-## 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## Things went south? Revert to previous version (5.2)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 5.1 to 5.2](5.1-to-5.2.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/5.3-to-5.4.md b/doc/update/5.3-to-5.4.md
index 7277250eb32..8514aa13f48 100644
--- a/doc/update/5.3-to-5.4.md
+++ b/doc/update/5.3-to-5.4.md
@@ -1,110 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 5.3 to 5.4
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.3-to-5.4.md) for the most up to date instructions.*
-
-## 0. Backup
-
-It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version):
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch
-sudo -u git -H git checkout 5-4-stable # Latest version of 5-4-stable addresses CVE-2013-4489
-```
-
-## 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
-```
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-```
-
-## 5. Update config files
-
-- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/gitlab.yml.example but with your settings.
-- Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/puma.rb.example but with your settings.
-
-## 6. Update Init script
-
-```bash
-sudo rm /etc/init.d/gitlab
-sudo curl --location --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-4-stable/lib/support/init.d/gitlab
-sudo chmod +x /etc/init.d/gitlab
-```
-
-## 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## Things went south? Revert to previous version (5.3)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 5.2 to 5.3](5.2-to-5.3.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md
index dacdf05cc9c..8514aa13f48 100644
--- a/doc/update/5.4-to-6.0.md
+++ b/doc/update/5.4-to-6.0.md
@@ -1,169 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 5.4 to 6.0
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.4-to-6.0.md) for the most up to date instructions.*
-
-## Warning
-
-GitLab 6.0 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489.
-
-**You need to follow this guide first, before updating past 6.0, as it contains critical migration steps that are only present
-in the `6-0-stable` branch**
-
-## Deprecations
-
-### Global projects
-
-The root (global) namespace for projects is deprecated.
-
-So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote URL. Please make sure you disable sending email when you do a test of the upgrade.
-
-### Teams
-
-We introduce group membership in 6.0 as a replacement for teams.
-
-The old combination of groups and teams was confusing for a lot of people.
-
-And when the members of a team where changed this wasn't reflected in the project permissions.
-
-In GitLab 6.0 you will be able to add members to a group with a permission level for each member.
-
-These group members will have access to the projects in that group.
-
-Any changes to group members will immediately be reflected in the project permissions.
-
-You can even have multiple owners for a group, greatly simplifying administration.
-
-## 0. Backup
-
-It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version):
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch
-sudo -u git -H git checkout 6-0-stable
-```
-
-## 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.9
-```
-
-## 4. Install additional packages
-
-```bash
-# For reStructuredText markup language support install required package:
-sudo apt-get install python-docutils
-```
-
-## 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_groups RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production
-sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production
-
-# Clear redis cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-
-# Clear and precompile assets
-sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-```
-
-## 6. Update config files
-
-Note: We switched from Puma in GitLab 5.4 to unicorn in GitLab 6.0.
-
-- Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example but with your settings.
-- Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/unicorn.rb.example but with your settings.
-
-## 7. Update Init script
-
-```bash
-sudo rm /etc/init.d/gitlab
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-sudo chmod +x /etc/init.d/gitlab
-```
-
-## 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## Troubleshooting
-
-The migrations in this update are very sensitive to incomplete or inconsistent data. If you have a long-running GitLab installation and some of the previous upgrades did not work out 100% correct this may bite you now. The following commands can be run in the rails console to look for 'bad' data.
-
-All project owners should have an owner:
-
-```
-Project.all.select { |project| project.owner.blank? }
-```
-
-Every user should have a namespace:
-
-```
-User.all.select { |u| u.namespace.blank? }
-```
-
-Projects in the global namespace should not conflict with projects in the owner namespace:
-
-```
-Project.where(namespace_id: nil).select { |p| Project.where(path: p.path, namespace_id: p.owner.try(:namespace).try(:id)).present? }
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md
index a3c52a1cfb4..8514aa13f48 100644
--- a/doc/update/6.0-to-6.1.md
+++ b/doc/update/6.0-to-6.1.md
@@ -1,127 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.0 to 6.1
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.0-to-6.1.md) for the most up to date instructions.*
-
-## Warning
-
-GitLab 6.1 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489.
-
-**In 6.1 we remove a lot of deprecated code.**
-
-**You should update to 6.0 before installing 6.1 so all the necessary conversions are run.**
-
-## Deprecations
-
-### Global issue numbers
-
-In 6.1 issue numbers are project specific. This means all issues are renumbered and get a new number in their URL. If you use an old issue number URL and the issue number does not exist yet you are redirected to the new one. This conversion does not trigger if the old number already exists for this project, this is unlikely but will happen with old issues and large projects.
-
-## 0. Backup
-
-It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version):
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout 6-1-stable
-# For GitLab Enterprise Edition: sudo -u git -H git checkout 6-1-stable-ee
-```
-
-## 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.9
-```
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production
-sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-## 5. Update config files
-
-- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-1-stable/config/gitlab.yml.example but with your settings.
-- Make `/home/git/gitlab/config/unicorn.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-1-stable/config/unicorn.rb.example but with your settings.
-
-## 6. Update Init script
-
-```bash
-sudo rm /etc/init.d/gitlab
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-## 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- cd /home/git/gitlab
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## Things went south? Revert to previous version (6.0)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 5.4 to 6.0](5.4-to-6.0.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.1-to-6.2.md b/doc/update/6.1-to-6.2.md
index 36a395bf01e..8514aa13f48 100644
--- a/doc/update/6.1-to-6.2.md
+++ b/doc/update/6.1-to-6.2.md
@@ -1,141 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.1 to 6.2
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.1-to-6.2.md) for the most up to date instructions.*
-
-**You should update to 6.1 before installing 6.2 so all the necessary conversions are run.**
-
-## 0. Backup
-
-It's useful to make a backup just in case things go south: (With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version).
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout 6-2-stable # Latest version of 6-2-stable addresses CVE-2013-4489
-# For GitLab Enterprise Edition: sudo -u git -H git checkout 6-2-stable-ee
-```
-
-## 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
-```
-
-## 4. Install additional packages
-
-```bash
-# Add support for logrotate for better log file handling
-sudo apt-get install logrotate
-```
-
-## 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-## 6. Update config files
-
-TIP: to see what changed in `gitlab.yml.example` in this release use next command:
-
-```
-git diff 6-1-stable:config/gitlab.yml.example 6-2-stable:config/gitlab.yml.example
-```
-
-- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-2-stable/config/gitlab.yml.example but with your settings.
-
-- Make `/home/git/gitlab/config/unicorn.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-2-stable/config/unicorn.rb.example but with your settings.
-
-- Copy rack attack middleware config:
-
- ```bash
- sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
- ```
-
-- Uncomment `config.middleware.use Rack::Attack` in `/home/git/gitlab/config/application.rb`
-
-- Set up logrotate.
-
-```bash
-sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
-```
-
-## 7. Update Init script
-
-```bash
-sudo rm /etc/init.d/gitlab
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-## 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## Things went south? Revert to previous version (6.1)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 6.0 to 6.1](6.0-to-6.1.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.2-to-6.3.md b/doc/update/6.2-to-6.3.md
index 02e87a08b8f..8514aa13f48 100644
--- a/doc/update/6.2-to-6.3.md
+++ b/doc/update/6.2-to-6.3.md
@@ -1,127 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.2 to 6.3
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.2-to-6.3.md) for the most up to date instructions.*
-
-**Requires version: 6.1 or 6.2.**
-
-## 0. Backup
-
-It's useful to make a backup just in case things go south: (With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout 6-3-stable
-# For GitLab Enterprise Edition: sudo -u git -H git checkout 6-3-stable-ee
-```
-
-## 3. Update gitlab-shell (and its config)
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities
-```
-
-The gitlab-shell config changed recently, so check for config file changes and make `/home/git/gitlab-shell/config.yml` the same as <https://github.com/gitlabhq/gitlab-shell/blob/master/config.yml.example>
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-```
-
-## 5. Update config files
-
-TIP: to see what changed in gitlab.yml.example in this release use next command:
-
-```
-git diff 6-2-stable:config/gitlab.yml.example 6-3-stable:config/gitlab.yml.example
-```
-
-- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-3-stable/config/gitlab.yml.example but with your settings.
-- Make `/home/git/gitlab/config/unicorn.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-3-stable/config/unicorn.rb.example but with your settings.
-
-```bash
-# Copy rack attack middleware config
-cd /home/git/gitlab
-sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
-```
-
-## 6. Update Init script
-
-```bash
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-## 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## Things went south? Revert to previous version (6.2)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 6.1 to 6.2](6.1-to-6.2.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.3-to-6.4.md b/doc/update/6.3-to-6.4.md
index 285ed06bdad..8514aa13f48 100644
--- a/doc/update/6.3-to-6.4.md
+++ b/doc/update/6.3-to-6.4.md
@@ -1,109 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.3 to 6.4
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.3-to-6.4.md) for the most up to date instructions.*
-
-## 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
-```bash
-sudo service gitlab stop
-````
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout 6-4-stable
-# For GitLab Enterprise Edition: sudo -u git -H git checkout 6-4-stable-ee
-```
-
-## 3. Update gitlab-shell (and its config)
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.8.0
-```
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-## 5. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-## 6. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check with:
-
-```bash
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations upgrade complete!
-
-## Things went south? Revert to previous version (6.3)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 6.2 to 6.3](6.2-to-6.3.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.4-to-6.5.md b/doc/update/6.4-to-6.5.md
index e07c98a5ad4..8514aa13f48 100644
--- a/doc/update/6.4-to-6.5.md
+++ b/doc/update/6.4-to-6.5.md
@@ -1,115 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.4 to 6.5
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.4-to-6.5.md) for the most up to date instructions.*
-
-## 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 6-5-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 6-5-stable-ee
-```
-
-## 3. Update gitlab-shell (and its config)
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.8.0
-```
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-## 5. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 6. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## Things went south? Revert to previous version (6.4)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 6.3 to 6.4](6.3-to-6.4.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.5-to-6.6.md b/doc/update/6.5-to-6.6.md
index 3f79b19644e..8514aa13f48 100644
--- a/doc/update/6.5-to-6.6.md
+++ b/doc/update/6.5-to-6.6.md
@@ -1,117 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.5 to 6.6
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.5-to-6.6.md) for the most up to date instructions.*
-
-## 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 6-6-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 6-6-stable-ee
-```
-
-## 3. Update gitlab-shell (and its config)
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.8.0
-```
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# The Modernizr gem was yanked from RubyGems. It is required for GitLab >= 2.8.0
-# Edit `Gemfile` and change `gem "modernizr", "2.5.3"` to
-# `gem "modernizr-rails", "2.7.1"``
-sudo -u git -H vim Gemfile
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-## 5. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 6. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## Things went south? Revert to previous version (6.5)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 6.4 to 6.5](6.4-to-6.5.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.6-to-6.7.md b/doc/update/6.6-to-6.7.md
index a0542d20d49..8514aa13f48 100644
--- a/doc/update/6.6-to-6.7.md
+++ b/doc/update/6.6-to-6.7.md
@@ -1,123 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.6 to 6.7
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.6-to-6.7.md) for the most up to date instructions.*
-
-## 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 6-7-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 6-7-stable-ee
-```
-
-## 3. Update gitlab-shell (and its config)
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.9.1
-```
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test postgres --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL
-
-# Run a bundle install without deployment to generate the new Gemfile
-sudo -u git -H bundle install --without development test mysql --no-deployment
-
-# Install libs (with deployment this time)
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Both MySQL and PostgreSQL
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-# Update the logrotate configuration (keep logs for 90 days instead of 52 weeks)
-sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
-
-# Compress existing .log.1 files because we turned off delaycompress in logrotate
-sudo -u git -H gzip /home/git/gitlab/log/*.log.1
-sudo -u git -H gzip /home/git/gitlab-shell/gitlab-shell.log.1
-
-# Close access to gitlab-satellites for others
-sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites
-
-# Add directory for uploads
-sudo -u git -H mkdir -p /home/git/gitlab/public/uploads
-```
-
-## 5. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 6. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## Things went south? Revert to previous version (6.6)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 6.5 to 6.6](6.5-to-6.6.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.7-to-6.8.md b/doc/update/6.7-to-6.8.md
index acf004577f1..8514aa13f48 100644
--- a/doc/update/6.7-to-6.8.md
+++ b/doc/update/6.7-to-6.8.md
@@ -1,126 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.7 to 6.8
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.7-to-6.8.md) for the most up to date instructions.*
-
-## 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-## 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 6-8-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 6-8-stable-ee
-```
-
-## 3. Update gitlab-shell (and its config)
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.9.3
-```
-
-## 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-# Close access to gitlab-satellites for others
-sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites
-```
-
-## 5. Update config files
-
-### New configuration options for gitlab.yml
-
-There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml if desired.
-
-```
-git diff 6-7-stable:config/gitlab.yml.example 6-8-stable:config/gitlab.yml.example
-```
-
-### MySQL? Remove reaping frequency
-
-If you are using MySQL as a database, remove `reaping_frequency` from you database.yml to prevent crashes. [Relevant commit](https://gitlab.com/gitlab-org/gitlab-ce/commit/5163a8fcb9cfd63435560fda00173b76df2ccc93).
-
-### HTTPS? Disable gzip
-
-If you are using HTTPS, disable gzip as in [this commit](https://gitlab.com/gitlab-org/gitlab-ce/commit/563fec734912d81cd7caea6fa8ec2b397fb72a9b) to prevent BREACH attacks.
-
-### Turn on asset compression
-
-To improve performance, enable gzip asset compression as seen [in this commit](https://gitlab.com/gitlab-org/gitlab-ce/commit/8af94ed75505f0253823b9b2d44320fecea5b5fb).
-
-## 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## Things went south? Revert to previous version (6.7)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 6.6 to 6.7](6.6-to-6.7.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.8-to-6.9.md b/doc/update/6.8-to-6.9.md
index 3d7b1e5346b..8514aa13f48 100644
--- a/doc/update/6.8-to-6.9.md
+++ b/doc/update/6.8-to-6.9.md
@@ -1,107 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.8 to 6.9
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.8-to-6.9.md) for the most up to date instructions.*
-
-### 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 6-9-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 6-9-stable-ee
-```
-
-### 3. Update gitlab-shell (and its config)
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.9.4
-```
-
-### 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-```
-
-### 5. Update config files
-
-#### New configuration options for gitlab.yml
-
-There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml if desired.
-
-```
-git diff 6-8-stable:config/gitlab.yml.example 6-9-stable:config/gitlab.yml.example
-```
-
-### 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## Things went south? Revert to previous version (6.8)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 6.7 to 6.8](6.7-to-6.8.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.9-to-7.0.md b/doc/update/6.9-to-7.0.md
index 27063948028..8514aa13f48 100644
--- a/doc/update/6.9-to-7.0.md
+++ b/doc/update/6.9-to-7.0.md
@@ -1,145 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.9 to 7.0
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.9-to-7.0.md) for the most up to date instructions.*
-
-### 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Update Ruby
-
-If you are still using Ruby 1.9.3 or below, you will need to update Ruby.
-You can check which version you are running with `ruby -v`.
-
-If you are you running Ruby 2.0.x, you do not need to upgrade ruby, but can consider doing so for performance reasons.
-
-If you are running Ruby 2.1.1 consider upgrading to 2.1.2, because of the high memory usage of Ruby 2.1.1.
-
-Install, update dependencies:
-
-```bash
-sudo apt-get install build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl
-```
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --location --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
-cd ruby-2.1.2
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 3. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-0-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-0-stable-ee
-```
-
-### 4. Update gitlab-shell (and its config)
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.9.6
-```
-
-### 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 6. Update config files
-
-#### New configuration options for gitlab.yml
-
-There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml if desired.
-
-```
-git diff origin/6-9-stable:config/gitlab.yml.example origin/7-0-stable:config/gitlab.yml.example
-```
-
-* HTTP setups: Make `/etc/nginx/sites-available/nginx` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-0-stable/lib/support/nginx/gitlab but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/nginx-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-0-stable/lib/support/nginx/gitlab-ssl but with your setting
-
-### 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## Things went south? Revert to previous version (6.9)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 6.8 to 6.9](6.8-to-6.9.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/6.x-or-7.x-to-7.14.md b/doc/update/6.x-or-7.x-to-7.14.md
index 61854b91aa2..8514aa13f48 100644
--- a/doc/update/6.x-or-7.x-to-7.14.md
+++ b/doc/update/6.x-or-7.x-to-7.14.md
@@ -1,317 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 6.x or 7.x to 7.14
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.x-or-7.x-to-7.14.md) for the most up to date instructions.*
-
-This allows you to upgrade any version of GitLab from 6.0 and up (including 7.0 and up) to 7.14.
-
-## Global issue numbers
-
-As of 6.1 issue numbers are project specific. This means all issues are renumbered and get a new number in their URL. If you use an old issue number URL and the issue number does not exist yet you are redirected to the new one. This conversion does not trigger if the old number already exists for this project, this is unlikely but will happen with old issues and large projects.
-
-## Editable labels
-
-In GitLab 7.2 we replace Issue and Merge Request tags with labels, making it
-possible to edit the label text and color. The characters `?`, `&` and `,` are
-no longer allowed however so those will be removed from your tags during the
-database migrations for GitLab 7.2.
-
-## Stash changes
-
-If you deleted the vendors folder during your original installation, [you will get an error](https://gitlab.com/gitlab-org/gitlab-ce/issues/1494) when you attempt to rebuild the assets in step 7. To avoid this, stash the changes in your GitLab working copy before starting:
-
- git stash
-
-## 0. Stop server
-
- sudo service gitlab stop
-
-## 1. Backup
-
-It's useful to make a backup just in case things go south:
-(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-## 2. Update Ruby
-
-If you are still using Ruby 1.9.3 or below, you will need to update Ruby.
-You can check which version you are running with `ruby -v`.
-
-If you are you running Ruby 2.0.x, you do not need to upgrade ruby, but can consider doing so for performance reasons.
-
-If you are running Ruby 2.1.1 consider upgrading to 2.1.6, because of the high memory usage of Ruby 2.1.1.
-
-Install, update dependencies:
-
-```bash
-sudo apt-get install build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl
-```
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --progress https://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.6.tar.gz | tar xz
-cd ruby-2.1.6
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-## 3. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-14-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-14-stable-ee
-```
-
-## 4. Install additional packages
-
-```bash
-# Add support for logrotate for better log file handling
-sudo apt-get install logrotate
-
-# Install pkg-config and cmake, which is needed for the latest versions of rugged
-sudo apt-get install pkg-config cmake
-
-# If you want to use Kerberos with GitLab EE for user authentication, install Kerberos header files
-# If you don't know what Kerberos is, you can assume you don't need it.
-sudo apt-get install libkrb5-dev
-
-# Install nodejs, javascript runtime required for assets
-sudo apt-get install nodejs
-```
-
-## 5. Configure Redis to use sockets
-
- # Configure redis to use sockets
- sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig
- # Disable Redis listening on TCP by setting 'port' to 0
- sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf
- # Enable Redis socket for default Debian / Ubuntu path
- echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf
- # Be sure redis group can write to the socket, enable only if supported (>= redis 2.4.0).
- sudo sed -i '/# unixsocketperm/ s/^# unixsocketperm.*/unixsocketperm 0775/' /etc/redis/redis.conf
- # Activate the changes to redis.conf
- sudo service redis-server restart
- # Add git to the redis group
- sudo usermod -aG redis git
-
- # Configure Redis connection settings
- sudo -u git -H cp config/resque.yml.example config/resque.yml
- # Change the Redis socket path if you are not using the default Debian / Ubuntu configuration
- sudo -u git -H editor config/resque.yml
-
- # Configure gitlab-shell to use Redis sockets
- sudo -u git -H sed -i 's|^ # socket.*| socket: /var/run/redis/redis.sock|' /home/git/gitlab-shell/config.yml
-
-## 6. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.5
-```
-
-## 7. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations from 6.0 to 6.1
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production VERSION=20130909132950
-
-# Enable internal issue IDs (introduced in GitLab 6.1)
-sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production
-
-# Run left database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Close access to gitlab-satellites for others
-sudo chmod u+rwx,g+rx,o-rwx /home/git/gitlab-satellites
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-## 8. Update config files
-
-TIP: to see what changed in `gitlab.yml.example` in this release use next command:
-
-```
-git diff 6-0-stable:config/gitlab.yml.example 7-14-stable:config/gitlab.yml.example
-```
-
-* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-14-stable/config/gitlab.yml.example but with your settings.
-* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-14-stable/config/unicorn.rb.example but with your settings.
-* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.6.5/config.yml.example but with your settings.
-* Copy rack attack middleware config
-
-```bash
-sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
-```
-
-* Set up logrotate
-
-```bash
-sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
-```
-
-### Change Nginx settings
-
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-14-stable/lib/support/nginx/gitlab but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-14-stable/lib/support/nginx/gitlab-ssl but with your settings.
-* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
-
-### Check the version of /usr/local/bin/git
-
-If you installed Git from source into /usr/local/bin/git then please [check
-your version](7.13-to-7.14.md).
-
-## 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- cd /home/git/gitlab
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade complete!
-
-## 11. Update OmniAuth configuration
-
-When using Google omniauth login, changes of the Google account required.
-Ensure that `Contacts API` and the `Google+ API` are enabled in the [Google Developers Console](https://console.developers.google.com/).
-More details can be found at the [integration documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/integration/google.md).
-
-## 12. Optional optimizations for GitLab setups with MySQL databases
-
-Only applies if running MySQL database created with GitLab 6.7 or earlier. If you are not experiencing any issues you may not need the following instructions however following them will bring your database in line with the latest recommended installation configuration and help avoid future issues. Be sure to follow these directions exactly. These directions should be safe for any MySQL instance but to be sure make a current MySQL database backup beforehand.
-
-```
-# Stop GitLab
-sudo service gitlab stop
-
-# Secure your MySQL installation (added in GitLab 6.2)
-sudo mysql_secure_installation
-
-# Login to MySQL
-mysql -u root -p
-
-# do not type the 'mysql>', this is part of the prompt
-
-# Convert all tables to use the InnoDB storage engine (added in GitLab 6.8)
-SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' ENGINE=InnoDB;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `ENGINE` <> 'InnoDB' AND `TABLE_TYPE` = 'BASE TABLE';
-
-# If previous query returned results, copy & run all shown SQL statements
-
-# Convert all tables to correct character set
-SET foreign_key_checks = 0;
-SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `TABLE_COLLATION` <> 'utf8_unicode_ci' AND `TABLE_TYPE` = 'BASE TABLE';
-
-# If previous query returned results, copy & run all shown SQL statements
-
-# turn foreign key checks back on
-SET foreign_key_checks = 1;
-
-# Find MySQL users
-mysql> SELECT user FROM mysql.user WHERE user LIKE '%git%';
-
-# If git user exists and gitlab user does not exist
-# you are done with the database cleanup tasks
-mysql> \q
-
-# If both users exist skip to Delete gitlab user
-
-# Create new user for GitLab (changed in GitLab 6.4)
-# change $password in the command below to a real password you pick
-mysql> CREATE USER 'git'@'localhost' IDENTIFIED BY '$password';
-
-# Grant the git user necessary permissions on the database
-mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, LOCK TABLES ON `gitlabhq_production`.* TO 'git'@'localhost';
-
-# Delete the old gitlab user
-mysql> DELETE FROM mysql.user WHERE user='gitlab';
-
-# Quit the database session
-mysql> \q
-
-# Try connecting to the new database with the new user
-sudo -u git -H mysql -u git -p -D gitlabhq_production
-
-# Type the password you replaced $password with earlier
-
-# You should now see a 'mysql>' prompt
-
-# Quit the database session
-mysql> \q
-
-# Update database configuration details
-# See config/database.yml.mysql for latest recommended configuration details
-# Remove the reaping_frequency setting line if it exists (removed in GitLab 6.8)
-# Set production -> pool: 10 (updated in GitLab 5.3)
-# Set production -> username: git
-# Set production -> password: the password your replaced $password with earlier
-sudo -u git -H editor /home/git/gitlab/config/database.yml
-```
-
-## Things went south? Revert to previous version (7.0)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 6.9 to 7.0](6.9-to-7.0.md), except for the database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-## Login issues after upgrade?
-
-If running in HTTPS mode, be sure to read [Can't Verify CSRF token authenticity](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide#cant-verify-csrf-token-authenticitycant-get-past-login-pageredirected-to-login-page)
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.0-to-7.1.md b/doc/update/7.0-to-7.1.md
index 308e8aeb985..8514aa13f48 100644
--- a/doc/update/7.0-to-7.1.md
+++ b/doc/update/7.0-to-7.1.md
@@ -1,144 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.0 to 7.1
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.0-to-7.1.md) for the most up to date instructions.*
-
-### 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Update Ruby
-
-If you are still using Ruby 1.9.3 or below, you will need to update Ruby.
-You can check which version you are running with `ruby -v`.
-
-If you are you running Ruby 2.0.x, you do not need to upgrade ruby, but can consider doing so for performance reasons.
-
-If you are running Ruby 2.1.1 consider upgrading to 2.1.2, because of the high memory usage of Ruby 2.1.1.
-
-Install, update dependencies:
-
-```bash
-sudo apt-get install build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl
-```
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --location --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
-cd ruby-2.1.2
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 3. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-1-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-1-stable-ee
-```
-
-### 4. Update gitlab-shell (and its config)
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.9.6
-```
-
-### 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 6. Update config files
-
-#### New configuration options for gitlab.yml
-
-There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml if desired.
-
-```
-git diff 7-0-stable:config/gitlab.yml.example 7-1-stable:config/gitlab.yml.example
-```
-
-### 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## Things went south? Revert to previous version (7.0)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 6.9 to 7.0](6.9-to-7.0.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-1-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.1-to-7.2.md b/doc/update/7.1-to-7.2.md
index 07f92ac3af6..8514aa13f48 100644
--- a/doc/update/7.1-to-7.2.md
+++ b/doc/update/7.1-to-7.2.md
@@ -1,143 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.1 to 7.2
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.1-to-7.2.md) for the most up to date instructions.*
-
-## Editable labels
-
-In GitLab 7.2 we replace Issue and Merge Request tags with labels, making it
-possible to edit the label text and color. The characters `?`, `&` and `,` are
-no longer allowed however so those will be removed from your tags during the
-database migrations for GitLab 7.2.
-
-### 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-2-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-2-stable-ee
-```
-
-### 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v1.9.8
-```
-
-### 4. Install new system dependencies
-
-The latest version of the 'rugged' gem requires `pkg-config` and `cmake` to
-build its native extensions.
-
-```bash
-sudo apt-get install pkg-config cmake
-```
-
-### 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 6. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for `gitlab.yml`. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff 7-1-stable:config/gitlab.yml.example 7-2-stable:config/gitlab.yml.example
-```
-
-* HTTP setups: Make `/etc/nginx/sites-available/nginx` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-0-stable/lib/support/nginx/gitlab but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/nginx-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-0-stable/lib/support/nginx/gitlab-ssl but with your setting
-
-Update rack attack middleware config
-
-```
-sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
-```
-
-### 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-### 9. Update OmniAuth configuration
-
-When using Google omniauth login, changes of the Google account required.
-Ensure that `Contacts API` and the `Google+ API` are enabled in the [Google Developers Console](https://console.developers.google.com/).
-More details can be found at the [integration documentation](../integration/google.md).
-
-## Things went south? Revert to previous version (7.1)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.0 to 7.1](7.0-to-7.1.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-2-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.10-to-7.11.md b/doc/update/7.10-to-7.11.md
index 39eeefc0e32..8514aa13f48 100644
--- a/doc/update/7.10-to-7.11.md
+++ b/doc/update/7.10-to-7.11.md
@@ -1,109 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.10 to 7.11
-
-### 0. Stop server
-
- sudo service gitlab stop
-
-### 1. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 2. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-11-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-11-stable-ee
-```
-
-### 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.3
-```
-
-### 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 5. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff origin/7-10-stable:config/gitlab.yml.example origin/7-11-stable:config/gitlab.yml.example
-``````
-
-### 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (7.10)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.9 to 7.10](7.9-to-7.10.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-11-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.11-to-7.12.md b/doc/update/7.11-to-7.12.md
index 530066e5fdb..8514aa13f48 100644
--- a/doc/update/7.11-to-7.12.md
+++ b/doc/update/7.11-to-7.12.md
@@ -1,135 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.11 to 7.12
-
-### 0. Double-check your Git version
-
-**This notice applies only to /usr/local/bin/git**
-
-If you compiled Git from source on your GitLab server then please double-check
-that you are using a version that protects against CVE-2014-9390. For six
-months after this vulnerability became known the GitLab installation guide
-still contained instructions that would install the outdated, 'vulnerable' Git
-version 2.1.2.
-
-Run the following command to get your current Git version.
-
-```
-/usr/local/bin/git --version
-```
-
-If you see 'No such file or directory' then you did not install Git according
-to the outdated instructions from the GitLab installation guide and you can go
-to the next step 'Stop server' below.
-
-If you see a version string then it should be v1.8.5.6, v1.9.5, v2.0.5, v2.1.4,
-v2.2.1 or newer. You can use the [instructions in the GitLab source
-installation
-guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
-to install a newer version of Git.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-12-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-12-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.3
-```
-
-### 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 6. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff origin/7-11-stable:config/gitlab.yml.example origin/7-12-stable:config/gitlab.yml.example
-``````
-
-### 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (7.11)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.10 to 7.11](7.10-to-7.11.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-12-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.12-to-7.13.md b/doc/update/7.12-to-7.13.md
index 8f413a2079a..8514aa13f48 100644
--- a/doc/update/7.12-to-7.13.md
+++ b/doc/update/7.12-to-7.13.md
@@ -1,135 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.12 to 7.13
-
-### 0. Double-check your Git version
-
-**This notice applies only to /usr/local/bin/git**
-
-If you compiled Git from source on your GitLab server then please double-check
-that you are using a version that protects against CVE-2014-9390. For six
-months after this vulnerability became known the GitLab installation guide
-still contained instructions that would install the outdated, 'vulnerable' Git
-version 2.1.2.
-
-Run the following command to get your current Git version.
-
-```
-/usr/local/bin/git --version
-```
-
-If you see 'No such file or directory' then you did not install Git according
-to the outdated instructions from the GitLab installation guide and you can go
-to the next step 'Stop server' below.
-
-If you see a version string then it should be v1.8.5.6, v1.9.5, v2.0.5, v2.1.4,
-v2.2.1 or newer. You can use the [instructions in the GitLab source
-installation
-guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
-to install a newer version of Git.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-13-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-13-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.3
-```
-
-### 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 6. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff origin/7-12-stable:config/gitlab.yml.example origin/7-13-stable:config/gitlab.yml.example
-``````
-
-### 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (7.12)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.11 to 7.12](7.11-to-7.12.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-13-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.13-to-7.14.md b/doc/update/7.13-to-7.14.md
index a8980662855..8514aa13f48 100644
--- a/doc/update/7.13-to-7.14.md
+++ b/doc/update/7.13-to-7.14.md
@@ -1,135 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.13 to 7.14
-
-### 0. Double-check your Git version
-
-**This notice applies only to /usr/local/bin/git**
-
-If you compiled Git from source on your GitLab server then please double-check
-that you are using a version that protects against CVE-2014-9390. For six
-months after this vulnerability became known the GitLab installation guide
-still contained instructions that would install the outdated, 'vulnerable' Git
-version 2.1.2.
-
-Run the following command to get your current Git version.
-
-```
-/usr/local/bin/git --version
-```
-
-If you see 'No such file or directory' then you did not install Git according
-to the outdated instructions from the GitLab installation guide and you can go
-to the next step 'Stop server' below.
-
-If you see a version string then it should be v1.8.5.6, v1.9.5, v2.0.5, v2.1.4,
-v2.2.1 or newer. You can use the [instructions in the GitLab source
-installation
-guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
-to install a newer version of Git.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-14-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-14-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.5
-```
-
-### 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 6. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff origin/7-13-stable:config/gitlab.yml.example origin/7-14-stable:config/gitlab.yml.example
-``````
-
-### 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (7.13)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.12 to 7.13](7.12-to-7.13.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-14-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.14-to-8.0.md b/doc/update/7.14-to-8.0.md
index 513afccff50..8514aa13f48 100644
--- a/doc/update/7.14-to-8.0.md
+++ b/doc/update/7.14-to-8.0.md
@@ -1,235 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.14 to 8.0
-
-### 0. Double-check your Git version
-
-**This notice applies only to /usr/local/bin/git**
-
-If you compiled Git from source on your GitLab server then please double-check
-that you are using a version that protects against CVE-2014-9390. For six
-months after this vulnerability became known the GitLab installation guide
-still contained instructions that would install the outdated, 'vulnerable' Git
-version 2.1.2.
-
-Run the following command to get your current Git version:
-
-```sh
-/usr/local/bin/git --version
-```
-
-If you see 'No such file or directory' then you did not install Git according
-to the outdated instructions from the GitLab installation guide and you can go
-to the next step 'Stop server' below.
-
-If you see a version string then it should be v1.8.5.6, v1.9.5, v2.0.5, v2.1.4,
-v2.2.1 or newer. You can use the [instructions in the GitLab source
-installation
-guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
-to install a newer version of Git.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-0-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-0-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.5
-```
-
-### 5. Install gitlab-git-http-server
-
-First we download Go 1.5 and install it into `/usr/local/go`:
-
-```bash
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.5.linux-amd64.tar.gz
-echo '5817fa4b2252afdb02e11e8b9dc1d9173ef3bd5a go1.5.linux-amd64.tar.gz' | shasum -c - && \
- sudo tar -C /usr/local -xzf go1.5.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.5.linux-amd64.tar.gz
-```
-
-Now we download `gitlab-git-http-server` and install it in `/home/git/gitlab-git-http-server`:
-
-```bash
-cd /home/git
-sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-git-http-server.git
-cd gitlab-git-http-server
-sudo -u git -H git checkout 0.2.14
-sudo -u git -H make
-```
-
-Make sure your unicorn.rb file contains a 'listen' line for
-'127.0.0.1:8080' and that this line is not commented out.
-
-```
-cd /home/git/gitlab
-grep ^listen config/unicorn.rb
-
-# If there is no 'listen' line for 127.0.0.1:8080, add it:
-sudo -u git tee -a config/unicorn.rb <<EOF
-listen "127.0.0.1:8080", :tcp_nopush => true
-EOF
-```
-
-If your Git repositories are in a directory other than `/home/git/repositories`,
-you need to tell `gitlab-git-http-server` about it via `/etc/default/gitlab`.
-See `lib/support/init.d/gitlab.default.example` for the options.
-
-### 6. Copy secrets
-
-The `secrets.yml` file is used to store keys to encrypt sessions and encrypt secure variables.
-When you run migrations make sure to store it someplace safe.
-Don't store it in the same place as your database backups,
-otherwise your secrets are exposed if one of your backups is compromised.
-
-```
-cd /home/git/gitlab
-sudo -u git -H cp config/secrets.yml.example config/secrets.yml
-sudo -u git -H chmod 0600 config/secrets.yml
-```
-
-### 7. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 8. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/7-14-stable:config/gitlab.yml.example origin/8-0-stable:config/gitlab.yml.example
-```
-
-The new options include configuration of GitLab CI that are now being part of GitLab CE and EE.
-
-#### New Nginx configuration
-
-Because of the new `gitlab-git-http-server` you need to update your Nginx
-configuration. If you skip this step 'git clone' and 'git push' over HTTP(S)
-will stop working.
-
-View changes between the previous recommended Nginx configuration and the
-current one:
-
-```sh
-# For HTTPS configurations
-git diff origin/7-14-stable:lib/support/nginx/gitlab-ssl origin/8-0-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/7-14-stable:lib/support/nginx/gitlab origin/8-0-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates](https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache).
-Also note that because Apache does not support upstreams behind Unix sockets you will need to let gitlab-git-http-server listen on a TCP port. You can do this via [/etc/default/gitlab](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-0-stable/lib/support/init.d/gitlab.default.example#L34).
-
-### 9. Migrate GitLab CI to GitLab CE/EE
-
-Now, GitLab CE and EE has CI integrated. However, migrations don't happen automatically and you need to do it manually.
-Please follow the following guide [to migrate](../migrate_ci_to_ce/README.md) your GitLab CI instance to GitLab CE/EE.
-
-### 10. Use Redis v2.4.0+
-
-Previous versions of GitLab allowed Redis versions >= 2.0 to be used, but
-Sidekiq jobs could fail due to lack of support for the SREM command. GitLab
-8.0 now checks that Redis >= 2.4.0 is used. You can check your Redis version
-with the following command:
-
- redis-cli info | grep redis_version
-
-### 11. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 12. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (7.14)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 7.13 to 7.14](7.13-to-7.14.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-## Troubleshooting
-
-### "You appear to have cloned an empty repository."
-
-If you see this message when attempting to clone a repository hosted by GitLab,
-this is likely due to an outdated Nginx or Apache configuration, or a missing or
-misconfigured `gitlab-git-http-server` instance. Double-check that you correctly
-completed [Step 5](#5-install-gitlab-git-http-server) to install the daemon and
-[Step 8](#new-nginx-configuration) to reconfigure Nginx.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-0-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.2-to-7.3.md b/doc/update/7.2-to-7.3.md
index a16f9de54e4..8514aa13f48 100644
--- a/doc/update/7.2-to-7.3.md
+++ b/doc/update/7.2-to-7.3.md
@@ -1,151 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.2 to 7.3
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.2-to-7.3.md) for the most up to date instructions.*
-
-### 0. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Get latest code
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-3-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-3-stable-ee
-```
-
-### 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.0.1
-```
-
-### 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-
-### 5. Configure Redis to use sockets
-
- # Configure redis to use sockets
- sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig
- # Disable Redis listening on TCP by setting 'port' to 0
- sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf
- # Enable Redis socket for default Debian / Ubuntu path
- echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf
- # Be sure redis group can write to the socket, enable only if supported (>= redis 2.4.0).
- sudo sed -i '/# unixsocketperm/ s/^# unixsocketperm.*/unixsocketperm 0775/' /etc/redis/redis.conf
- # Activate the changes to redis.conf
- sudo service redis-server restart
- # Add git to the redis group
- sudo usermod -aG redis git
-
- # Configure Redis connection settings
- sudo -u git -H cp config/resque.yml.example config/resque.yml
- # Change the Redis socket path if you are not using the default Debian / Ubuntu configuration
- sudo -u git -H editor config/resque.yml
-
- # Configure gitlab-shell to use Redis sockets
- sudo -u git -H sed -i 's|^ # socket.*| socket: /var/run/redis/redis.sock|' /home/git/gitlab-shell/config.yml
-
-### 6. Update config files
-
-#### New configuration options for gitlab.yml
-
-There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml.
-
-```
-git diff origin/7-2-stable:config/gitlab.yml.example origin/7-3-stable:config/gitlab.yml.example
-```
-
-```
-# Use the default Unicorn socket backlog value of 1024
-sudo -u git -H sed -i 's/:backlog => 64/:backlog => 1024/' config/unicorn.rb
-```
-
-* HTTP setups: Make `/etc/nginx/sites-available/nginx` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-3-stable/lib/support/nginx/gitlab but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/nginx-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-3-stable/lib/support/nginx/gitlab-ssl but with your setting
-
-### 7. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 8. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-### 9. Update OmniAuth configuration
-
-When using Google omniauth login, changes of the Google account required.
-Ensure that `Contacts API` and the `Google+ API` are enabled in the [Google Developers Console](https://console.developers.google.com/).
-More details can be found at the [integration documentation](../integration/google.md).
-
-## Things went south? Revert to previous version (7.2)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.1 to 7.2](7.1-to-7.2.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-3-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.3-to-7.4.md b/doc/update/7.3-to-7.4.md
index 734c655f1d1..8514aa13f48 100644
--- a/doc/update/7.3-to-7.4.md
+++ b/doc/update/7.3-to-7.4.md
@@ -1,200 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.3 to 7.4
-*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.3-to-7.4.md) for the most up to date instructions.*
-
-### 0. Stop server
-
- sudo service gitlab stop
-
-### 1. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 2. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-4-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-4-stable-ee
-```
-
-### 3. Install libs, migrations, etc.
-
-```bash
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 4. Update config files
-
-#### New configuration options for gitlab.yml
-
-There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml.
-
-```
-git diff origin/7-3-stable:config/gitlab.yml.example origin/7-4-stable:config/gitlab.yml.example
-```
-
-#### Change timeout for unicorn
-
-```
-# set timeout to 60
-sudo -u git -H editor config/unicorn.rb
-```
-
-#### Change Nginx HTTPS settings
-
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/lib/support/nginx/gitlab-ssl but with your setting
-
-#### MySQL Databases: Update database.yml config file
-
-* Add `collation: utf8_general_ci` to `config/database.yml` as seen in [config/database.yml.mysql][mysql]:
-
-```
-sudo -u git -H editor config/database.yml
-```
-
-### 5. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 6. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-
-### 7. Optional optimizations for GitLab setups with MySQL databases
-
-Only applies if running MySQL database created with GitLab 6.7 or earlier. If you are not experiencing any issues you may not need the following instructions however following them will bring your database in line with the latest recommended installation configuration and help avoid future issues. Be sure to follow these directions exactly. These directions should be safe for any MySQL instance but to be sure make a current MySQL database backup beforehand.
-
-```
-# Stop GitLab
-sudo service gitlab stop
-
-# Secure your MySQL installation (added in GitLab 6.2)
-sudo mysql_secure_installation
-
-# Login to MySQL
-mysql -u root -p
-
-# do not type the 'mysql>', this is part of the prompt
-
-# Convert all tables to use the InnoDB storage engine (added in GitLab 6.8)
-SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' ENGINE=InnoDB;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `ENGINE` <> 'InnoDB' AND `TABLE_TYPE` = 'BASE TABLE';
-
-# If previous query returned results, copy & run all shown SQL statements
-
-# Convert all tables to correct character set
-SET foreign_key_checks = 0;
-SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `TABLE_COLLATION` <> 'utf8_unicode_ci' AND `TABLE_TYPE` = 'BASE TABLE';
-
-# If previous query returned results, copy & run all shown SQL statements
-
-# turn foreign key checks back on
-SET foreign_key_checks = 1;
-
-# Find MySQL users
-mysql> SELECT user FROM mysql.user WHERE user LIKE '%git%';
-
-# If git user exists and gitlab user does not exist
-# you are done with the database cleanup tasks
-mysql> \q
-
-# If both users exist skip to Delete gitlab user
-
-# Create new user for GitLab (changed in GitLab 6.4)
-# change $password in the command below to a real password you pick
-mysql> CREATE USER 'git'@'localhost' IDENTIFIED BY '$password';
-
-# Grant the git user necessary permissions on the database
-mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, LOCK TABLES ON `gitlabhq_production`.* TO 'git'@'localhost';
-
-# Delete the old gitlab user
-mysql> DELETE FROM mysql.user WHERE user='gitlab';
-
-# Quit the database session
-mysql> \q
-
-# Try connecting to the new database with the new user
-sudo -u git -H mysql -u git -p -D gitlabhq_production
-
-# Type the password you replaced $password with earlier
-
-# You should now see a 'mysql>' prompt
-
-# Quit the database session
-mysql> \q
-
-# Update database configuration details
-# See config/database.yml.mysql for latest recommended configuration details
-# Remove the reaping_frequency setting line if it exists (removed in GitLab 6.8)
-# Set production -> pool: 10 (updated in GitLab 5.3)
-# Set production -> username: git
-# Set production -> password: the password your replaced $password with earlier
-sudo -u git -H editor /home/git/gitlab/config/database.yml
-
-# Start GitLab
-sudo service gitlab start
-sudo service nginx restart
-
-# Run thorough check
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-
-## Things went south? Revert to previous version (7.3)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.2 to 7.3](7.2-to-7.3.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/config/gitlab.yml.example
-[mysql]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/config/database.yml.mysql
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.4-to-7.5.md b/doc/update/7.4-to-7.5.md
index 7a3a49ff948..8514aa13f48 100644
--- a/doc/update/7.4-to-7.5.md
+++ b/doc/update/7.4-to-7.5.md
@@ -1,116 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.4 to 7.5
-
-### 0. Stop server
-
- sudo service gitlab stop
-
-### 1. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 2. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-5-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-5-stable-ee
-```
-
-### 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.2.0
-```
-
-### 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 5. Update config files
-
-#### New configuration options for gitlab.yml
-
-There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml.
-
-```
-git diff origin/7-4-stable:config/gitlab.yml.example origin/7-5-stable:config/gitlab.yml.example
-```
-
-#### Change Nginx settings
-
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your setting
-
-### 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## Things went south? Revert to previous version (7.4)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.3 to 7.4](7.3-to-7.4.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-5-stable/config/gitlab.yml.example
-[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-5-stable/lib/support/nginx/gitlab
-[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-5-stable/lib/support/nginx/gitlab-ssl
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.5-to-7.6.md b/doc/update/7.5-to-7.6.md
index 0d45a9528b9..8514aa13f48 100644
--- a/doc/update/7.5-to-7.6.md
+++ b/doc/update/7.5-to-7.6.md
@@ -1,123 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.5 to 7.6
-
-### 0. Stop server
-
- sudo service gitlab stop
-
-### 1. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 2. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-6-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-6-stable-ee
-```
-
-### 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.4.0
-```
-
-### 4. Install libs, migrations, etc.
-
-```bash
-sudo apt-get install libkrb5-dev
-
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 5. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff origin/7-5-stable:config/gitlab.yml.example origin/7-6-stable:config/gitlab.yml.example
-```
-
-#### Change Nginx settings
-
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your setting
-
-#### Set up time zone (optional)
-
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
-
-### 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## Things went south? Revert to previous version (7.5)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.4 to 7.5](7.4-to-7.5.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/config/gitlab.yml.example
-[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/config/application.rb
-[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/lib/support/nginx/gitlab
-[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/lib/support/nginx/gitlab-ssl
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.6-to-7.7.md b/doc/update/7.6-to-7.7.md
index 5e0b2ca7bcd..8514aa13f48 100644
--- a/doc/update/7.6-to-7.7.md
+++ b/doc/update/7.6-to-7.7.md
@@ -1,128 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.6 to 7.7
-
-### 0. Stop server
-
- sudo service gitlab stop
-
-### 1. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 2. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-7-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-7-stable-ee
-```
-
-### 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.4.2
-```
-
-### 4. Install libs, migrations, etc.
-
-```bash
-sudo apt-get install libkrb5-dev
-
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 5. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff origin/7-6-stable:config/gitlab.yml.example origin/7-7-stable:config/gitlab.yml.example
-```
-
-#### Change Nginx settings
-
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your setting
-
-#### Set up time zone (optional)
-
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
-
-### 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-### 8. GitHub settings (if applicable)
-
-If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it
-only contains a root URL (ex. `https://gitlab.example.com/`)
-
-## Things went south? Revert to previous version (7.6)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.5 to 7.6](7.5-to-7.6.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/config/gitlab.yml.example
-[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/config/application.rb
-[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/lib/support/nginx/gitlab
-[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/lib/support/nginx/gitlab-ssl
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.7-to-7.8.md b/doc/update/7.7-to-7.8.md
index f5b1ebf0a9c..8514aa13f48 100644
--- a/doc/update/7.7-to-7.8.md
+++ b/doc/update/7.7-to-7.8.md
@@ -1,129 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.7 to 7.8
-
-### 0. Stop server
-
- sudo service gitlab stop
-
-### 1. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 2. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-8-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-8-stable-ee
-```
-
-### 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.5.4
-```
-
-### 4. Install libs, migrations, etc.
-
-```bash
-sudo apt-get install libkrb5-dev
-
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 5. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff origin/7-7-stable:config/gitlab.yml.example origin/7-8-stable:config/gitlab.yml.example
-```
-
-#### Change Nginx settings
-
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your settings.
-* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
-
-#### Set up time zone (optional)
-
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
-
-### 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-### 8. GitHub settings (if applicable)
-
-If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it
-only contains a root URL (ex. `https://gitlab.example.com/`)
-
-## Things went south? Revert to previous version (7.7)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.6 to 7.7](7.6-to-7.7.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/config/gitlab.yml.example
-[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/config/application.rb
-[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/lib/support/nginx/gitlab
-[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/lib/support/nginx/gitlab-ssl
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.8-to-7.9.md b/doc/update/7.8-to-7.9.md
index 0db7698936b..8514aa13f48 100644
--- a/doc/update/7.8-to-7.9.md
+++ b/doc/update/7.8-to-7.9.md
@@ -1,131 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.8 to 7.9
-
-### 0. Stop server
-
- sudo service gitlab stop
-
-### 1. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 2. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-9-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-9-stable-ee
-```
-
-### 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.0
-```
-
-### 4. Install libs, migrations, etc.
-
-Please refer to the [Node.js setup documentation](https://github.com/joyent/node/wiki/installing-node.js-via-package-manager#debian-and-ubuntu-based-linux-distributions) if you aren't running default GitLab server setup.
-
-```bash
-sudo apt-get install nodejs
-
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 5. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff origin/7-8-stable:config/gitlab.yml.example origin/7-9-stable:config/gitlab.yml.example
-```
-
-#### Change Nginx settings
-
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your settings.
-* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
-
-#### Set up time zone (optional)
-
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
-
-### 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-### 8. GitHub settings (if applicable)
-
-If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it
-only contains a root URL (ex. `https://gitlab.example.com/`)
-
-## Things went south? Revert to previous version (7.8)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.7 to 7.8](7.7-to-7.8.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/config/gitlab.yml.example
-[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/config/application.rb
-[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/lib/support/nginx/gitlab
-[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/lib/support/nginx/gitlab-ssl
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/7.9-to-7.10.md b/doc/update/7.9-to-7.10.md
index 782fb0736e6..8514aa13f48 100644
--- a/doc/update/7.9-to-7.10.md
+++ b/doc/update/7.9-to-7.10.md
@@ -1,127 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 7.9 to 7.10
-
-### 0. Stop server
-
- sudo service gitlab stop
-
-### 1. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 2. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 7-10-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 7-10-stable-ee
-```
-
-### 3. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.2
-```
-
-### 4. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without ... postgres')
-sudo -u git -H bundle install --without development test postgres --deployment
-
-# PostgreSQL installations (note: the line below states '--without ... mysql')
-sudo -u git -H bundle install --without development test mysql --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-### 5. Update config files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
-
-```
-git diff origin/7-9-stable:config/gitlab.yml.example origin/7-10-stable:config/gitlab.yml.example
-```
-
-#### Change Nginx settings
-
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your settings.
-* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
-
-#### Set up time zone (optional)
-
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
-
-### 6. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 7. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check with:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-### 8. GitHub settings (if applicable)
-
-If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it
-only contains a root URL (ex. `https://gitlab.example.com/`)
-
-## Things went south? Revert to previous version (7.9)
-
-### 1. Revert the code to the previous version
-Follow the [upgrade guide from 7.8 to 7.9](7.8-to-7.9.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup:
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-10-stable/config/gitlab.yml.example
-[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-10-stable/config/application.rb
-[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-10-stable/lib/support/nginx/gitlab
-[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-10-stable/lib/support/nginx/gitlab-ssl
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.0-to-8.1.md b/doc/update/8.0-to-8.1.md
index f612606af68..8514aa13f48 100644
--- a/doc/update/8.0-to-8.1.md
+++ b/doc/update/8.0-to-8.1.md
@@ -1,181 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.0 to 8.1
-
-**NOTE:** GitLab 8.0 introduced several significant changes related to
-installation and configuration which *are not duplicated here*. Be sure you're
-already running a working version of 8.0 before proceeding with this guide.
-
-### 0. Double-check your Git version
-
-**This notice applies only to /usr/local/bin/git**
-
-If you compiled Git from source on your GitLab server then please double-check
-that you are using a version that protects against CVE-2014-9390. For six
-months after this vulnerability became known the GitLab installation guide
-still contained instructions that would install the outdated, 'vulnerable' Git
-version 2.1.2.
-
-Run the following command to get your current Git version:
-
-```sh
-/usr/local/bin/git --version
-```
-
-If you see 'No such file or directory' then you did not install Git according
-to the outdated instructions from the GitLab installation guide and you can go
-to the next step 'Stop server' below.
-
-If you see a version string then it should be v1.8.5.6, v1.9.5, v2.0.5, v2.1.4,
-v2.2.1 or newer. You can use the [instructions in the GitLab source
-installation
-guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
-to install a newer version of Git.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-1-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-1-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.5
-```
-
-### 5. Update gitlab-git-http-server
-
-```bash
-cd /home/git/gitlab-git-http-server
-sudo -u git -H git fetch origin
-sudo -u git -H git checkout 0.3.0
-sudo -u git -H make
-```
-
-### 6. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 7. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-0-stable:config/gitlab.yml.example origin/8-1-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-View changes between the previous recommended Nginx configuration and the
-current one:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-0-stable:lib/support/nginx/gitlab-ssl origin/8-1-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-0-stable:lib/support/nginx/gitlab origin/8-1-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-git-http-server listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-1-stable/lib/support/init.d/gitlab.default.example#L34
-
-### 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.0)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 7.14 to 8.0](7.14-to-8.0.md), except for the database migration
-(The backup is already migrated to the previous version)
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-## Troubleshooting
-
-### "You appear to have cloned an empty repository."
-
-See the [7.14 to 8.0 update guide](7.14-to-8.0.md#troubleshooting).
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-1-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.1-to-8.2.md b/doc/update/8.1-to-8.2.md
index 2d0b19abd74..8514aa13f48 100644
--- a/doc/update/8.1-to-8.2.md
+++ b/doc/update/8.1-to-8.2.md
@@ -1,198 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.1 to 8.2
-
-**NOTE:** GitLab 8.0 introduced several significant changes related to
-installation and configuration which *are not duplicated here*. Be sure you're
-already running a working version of at least 8.0 before proceeding with this
-guide.
-
-### 0. Double-check your Git version
-
-**This notice applies only to /usr/local/bin/git**
-
-If you compiled Git from source on your GitLab server then please double-check
-that you are using a version that protects against CVE-2014-9390. For six
-months after this vulnerability became known the GitLab installation guide
-still contained instructions that would install the outdated, 'vulnerable' Git
-version 2.1.2.
-
-Run the following command to get your current Git version:
-
-```sh
-/usr/local/bin/git --version
-```
-
-If you see 'No such file or directory' then you did not install Git according
-to the outdated instructions from the GitLab installation guide and you can go
-to the next step 'Stop server' below.
-
-If you see a version string then it should be v1.8.5.6, v1.9.5, v2.0.5, v2.1.4,
-v2.2.1 or newer. You can use the [instructions in the GitLab source
-installation
-guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
-to install a newer version of Git.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-2-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-2-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v2.6.8
-```
-
-### 5. Replace gitlab-git-http-server with gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires [Go
-1.5](https://golang.org/dl) which should already be on your system
-from GitLab 8.1.
-
-```bash
-cd /home/git
-sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
-cd gitlab-workhorse
-sudo -u git -H git checkout 0.4.2
-sudo -u git -H make
-```
-
-Update the GitLab 'default' file.
-
-```
-cd /home/git/gitlab
-test -e /etc/default/gitlab && \
- sudo sed -i.pre-8.2 's/^\([^=]*\)gitlab_git_http_server/\1gitlab_workhorse/' /etc/default/gitlab
-```
-
-Make sure that you also update your **NGINX configuration** to use
-the new gitlab-workhorse.socket file.
-
-### 6. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 7. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-1-stable:config/gitlab.yml.example origin/8-2-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-View changes between the previous recommended Nginx configuration and the
-current one:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-1-stable:lib/support/nginx/gitlab-ssl origin/8-2-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-1-stable:lib/support/nginx/gitlab origin/8-2-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-2-stable/lib/support/init.d/gitlab.default.example#L34
-
-### 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.1)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.0 to 8.1](8.0-to-8.1.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-## Troubleshooting
-
-### "You appear to have cloned an empty repository."
-
-See the [7.14 to 8.0 update guide](7.14-to-8.0.md#troubleshooting).
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-2-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.10-to-8.11.md b/doc/update/8.10-to-8.11.md
index df3e34f5cc6..8514aa13f48 100644
--- a/doc/update/8.10-to-8.11.md
+++ b/doc/update/8.10-to-8.11.md
@@ -1,205 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.10 to 8.11
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-We will continue supporting Ruby < 2.3 for the time being but we recommend you
-upgrade to Ruby 2.3 if you're running a source installation, as this is the same
-version that ships with our Omnibus package.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
-echo 'c39b4001f7acb4e334cb60a0f4df72d434bef711 ruby-2.3.1.tar.gz' | shasum --check - && tar xzf ruby-2.3.1.tar.gz
-cd ruby-2.3.1
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-11-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-11-stable-ee
-```
-
-### 5. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v3.4.0
-```
-
-### 6. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.7.11
-sudo -u git -H make
-```
-
-### 7. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-10-stable:config/gitlab.yml.example origin/8-11-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-10-stable:lib/support/nginx/gitlab-ssl origin/8-11-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-10-stable:lib/support/nginx/gitlab origin/8-11-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-11-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-11-stable/config/initializers/smtp_settings.rb.sample#L13?
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.10)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.9 to 8.10](8.9-to-8.10.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-11-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.11-to-8.12.md b/doc/update/8.11-to-8.12.md
index 9d6a1f42375..8514aa13f48 100644
--- a/doc/update/8.11-to-8.12.md
+++ b/doc/update/8.11-to-8.12.md
@@ -1,213 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.11 to 8.12
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-We will continue supporting Ruby < 2.3 for the time being but we recommend you
-upgrade to Ruby 2.3 if you're running a source installation, as this is the same
-version that ships with our Omnibus package.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
-echo 'c39b4001f7acb4e334cb60a0f4df72d434bef711 ruby-2.3.1.tar.gz' | shasum --check - && tar xzf ruby-2.3.1.tar.gz
-cd ruby-2.3.1
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-12-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-12-stable-ee
-```
-
-### 5. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v3.6.1
-```
-
-### 6. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.8.2
-sudo -u git -H make
-```
-
-### 7. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-11-stable:config/gitlab.yml.example origin/8-12-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
-the GitLab server during `git gc`.
-
-```sh
-sudo -u git -H git config --global repack.writeBitmaps true
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-11-stable:lib/support/nginx/gitlab-ssl origin/8-12-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-11-stable:lib/support/nginx/gitlab origin/8-12-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-12-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-12-stable/config/initializers/smtp_settings.rb.sample#L13?
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.11)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.10 to 8.11](8.10-to-8.11.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-12-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.12-to-8.13.md b/doc/update/8.12-to-8.13.md
index 6225dee9802..8514aa13f48 100644
--- a/doc/update/8.12-to-8.13.md
+++ b/doc/update/8.12-to-8.13.md
@@ -1,213 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.12 to 8.13
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-We will continue supporting Ruby < 2.3 for the time being but we recommend you
-upgrade to Ruby 2.3 if you're running a source installation, as this is the same
-version that ships with our Omnibus package.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
-echo 'c39b4001f7acb4e334cb60a0f4df72d434bef711 ruby-2.3.1.tar.gz' | shasum --check - && tar xzf ruby-2.3.1.tar.gz
-cd ruby-2.3.1
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-13-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-13-stable-ee
-```
-
-### 5. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v3.6.7
-```
-
-### 6. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.8.5
-sudo -u git -H make
-```
-
-### 7. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-12-stable:config/gitlab.yml.example origin/8-13-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
-the GitLab server during `git gc`.
-
-```sh
-sudo -u git -H git config --global repack.writeBitmaps true
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-12-stable:lib/support/nginx/gitlab-ssl origin/8-13-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-12-stable:lib/support/nginx/gitlab origin/8-13-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.12)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.11 to 8.12](8.11-to-8.12.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.13-to-8.14.md b/doc/update/8.13-to-8.14.md
index d2508e3f980..8514aa13f48 100644
--- a/doc/update/8.13-to-8.14.md
+++ b/doc/update/8.13-to-8.14.md
@@ -1,213 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.13 to 8.14
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-We will continue supporting Ruby < 2.3 for the time being but we recommend you
-upgrade to Ruby 2.3 if you're running a source installation, as this is the same
-version that ships with our Omnibus package.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
-echo 'c39b4001f7acb4e334cb60a0f4df72d434bef711 ruby-2.3.1.tar.gz' | shasum --check - && tar xzf ruby-2.3.1.tar.gz
-cd ruby-2.3.1
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-14-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-14-stable-ee
-```
-
-### 5. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v4.1.1
-```
-
-### 6. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v1.0.1
-sudo -u git -H make
-```
-
-### 7. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-13-stable:config/gitlab.yml.example origin/8-14-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
-the GitLab server during `git gc`.
-
-```sh
-sudo -u git -H git config --global repack.writeBitmaps true
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-13-stable:lib/support/nginx/gitlab-ssl origin/8-14-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-13-stable:lib/support/nginx/gitlab origin/8-14-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-14-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-14-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.13)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.12 to 8.13](8.12-to-8.13.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-14-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.14-to-8.15.md b/doc/update/8.14-to-8.15.md
index daf8d0f2ca6..8514aa13f48 100644
--- a/doc/update/8.14-to-8.15.md
+++ b/doc/update/8.14-to-8.15.md
@@ -1,243 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.14 to 8.15
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-We will continue supporting Ruby < 2.3 for the time being but we recommend you
-upgrade to Ruby 2.3 if you're running a source installation, as this is the same
-version that ships with our Omnibus package.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
-echo 'c39b4001f7acb4e334cb60a0f4df72d434bef711 ruby-2.3.1.tar.gz' | shasum --check - && tar xzf ruby-2.3.1.tar.gz
-cd ruby-2.3.1
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 8-15-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 8-15-stable-ee
-```
-
-### 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-```
-
-### 6. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v4.1.1
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/8-14-stable:config/gitlab.yml.example origin/8-15-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
-the GitLab server during `git gc`.
-
-```sh
-cd /home/git/gitlab
-
-sudo -u git -H git config --global repack.writeBitmaps true
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/8-14-stable:lib/support/nginx/gitlab-ssl origin/8-15-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-14-stable:lib/support/nginx/gitlab origin/8-15-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-15-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-15-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 9. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.14)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.13 to 8.14](8.13-to-8.14.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-15-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.15-to-8.16.md b/doc/update/8.15-to-8.16.md
index 3668142edd2..8514aa13f48 100644
--- a/doc/update/8.15-to-8.16.md
+++ b/doc/update/8.15-to-8.16.md
@@ -1,245 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.15 to 8.16
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-We will continue supporting Ruby < 2.3 for the time being but we recommend you
-upgrade to Ruby 2.3 if you're running a source installation, as this is the same
-version that ships with our Omnibus package.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
-echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
-cd ruby-2.3.3
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 8-16-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 8-16-stable-ee
-```
-
-### 5. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 6. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v4.1.1
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/8-15-stable:config/gitlab.yml.example origin/8-16-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
-the GitLab server during `git gc`.
-
-```sh
-cd /home/git/gitlab
-
-sudo -u git -H git config --global repack.writeBitmaps true
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/8-15-stable:lib/support/nginx/gitlab-ssl origin/8-16-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-15-stable:lib/support/nginx/gitlab origin/8-16-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 9. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.15)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.14 to 8.15](8.14-to-8.15.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.16-to-8.17.md b/doc/update/8.16-to-8.17.md
index ee2e31c2aec..8514aa13f48 100644
--- a/doc/update/8.16-to-8.17.md
+++ b/doc/update/8.16-to-8.17.md
@@ -1,272 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.16 to 8.17
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-We will continue supporting Ruby < 2.3 for the time being but we recommend you
-upgrade to Ruby 2.3 if you're running a source installation, as this is the same
-version that ships with our Omnibus package.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
-echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
-cd ruby-2.3.3
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-### 5. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 8-17-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 8-17-stable-ee
-```
-
-### 6. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Install/update frontend asset dependencies
-sudo -u git -H npm install --production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake gitlab:assets:clean gitlab:assets:compile cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 7. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
-```
-
-### 8. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v4.1.1
-```
-
-### 9. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/8-16-stable:config/gitlab.yml.example origin/8-17-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
-the GitLab server during `git gc`.
-
-```sh
-cd /home/git/gitlab
-
-sudo -u git -H git config --global repack.writeBitmaps true
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/8-16-stable:lib/support/nginx/gitlab-ssl origin/8-17-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-16-stable:lib/support/nginx/gitlab origin/8-17-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example].
-You need to update this file if you want to [enable GitLab Pages][pages-admin].
-View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/8-16-stable:lib/support/init.d/gitlab.default.example origin/8-17-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 10. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 11. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.16)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.15 to 8.16](8.15-to-8.16.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/lib/support/init.d/gitlab.default.example
-[pages-admin]: ../administration/pages/source.md
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.17-to-9.0.md b/doc/update/8.17-to-9.0.md
index 3c73bc573a6..8514aa13f48 100644
--- a/doc/update/8.17-to-9.0.md
+++ b/doc/update/8.17-to-9.0.md
@@ -1,358 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.17 to 9.0
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 only supports Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
-echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
-cd ruby-2.3.3
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-0-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-0-stable-ee
-```
-
-### 6. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-```
-
-### 7. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/8-17-stable:config/gitlab.yml.example origin/9-0-stable:config/gitlab.yml.example
-```
-
-#### Configuration changes for repository storages
-
-This version introduces a new configuration structure for repository storages.
-Update your current configuration as follows, replacing with your storages names and paths:
-
-**For installations from source**
-
-1. Update your `gitlab.yml`, from
-
- ```yaml
- repositories:
- storages: # You must have at least a 'default' storage path.
- default: /home/git/repositories
- nfs: /mnt/nfs/repositories
- cephfs: /mnt/cephfs/repositories
- ```
-
- to
-
- ```yaml
- repositories:
- storages: # You must have at least a 'default' storage path.
- default:
- path: /home/git/repositories
- nfs:
- path: /mnt/nfs/repositories
- cephfs:
- path: /mnt/cephfs/repositories
- ```
-
-**For Omnibus installations**
-
-1. Update your `/etc/gitlab/gitlab.rb`, from
-
- ```ruby
- git_data_dirs({
- "default" => "/var/opt/gitlab/git-data",
- "nfs" => "/mnt/nfs/git-data",
- "cephfs" => "/mnt/cephfs/git-data"
- })
- ```
-
- to
-
- ```ruby
- git_data_dirs({
- "default" => { "path" => "/var/opt/gitlab/git-data" },
- "nfs" => { "path" => "/mnt/nfs/git-data" },
- "cephfs" => { "path" => "/mnt/cephfs/git-data" }
- })
- ```
-
-#### Git configuration
-
-Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
-the GitLab server during `git gc`.
-
-```sh
-cd /home/git/gitlab
-
-sudo -u git -H git config --global repack.writeBitmaps true
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/8-17-stable:lib/support/nginx/gitlab-ssl origin/9-0-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-17-stable:lib/support/nginx/gitlab origin/9-0-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-0-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-0-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/8-17-stable:lib/support/init.d/gitlab.default.example origin/9-0-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 9. Install libs, migrations, etc.
-
-GitLab 9.0.11 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on the `re2` regular expression library. To install this dependency:
-
-```bash
-sudo apt-get install libre2-dev
-```
-
-Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
-you can [install re2 manually](https://github.com/google/re2/wiki/Install).
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 10. Optional: install Gitaly
-
-Gitaly is still an optional component of GitLab. If you want to save time
-during your 9.0 upgrade **you can skip this step**.
-
-If you do want to set up Gitaly in GitLab 9.0 then follow [Gitaly section of the installation
-guide](../install/installation.md#install-gitaly).
-
-### 11. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 12. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.17)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.16 to 8.17](8.16-to-8.17.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-0-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-0-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.2-to-8.3.md b/doc/update/8.2-to-8.3.md
index 3a0d647cbfe..8514aa13f48 100644
--- a/doc/update/8.2-to-8.3.md
+++ b/doc/update/8.2-to-8.3.md
@@ -1,227 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.2 to 8.3
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-**NOTE:** GitLab 8.0 introduced several significant changes related to
-installation and configuration which *are not duplicated here*. Be sure you're
-already running a working version of at least 8.0 before proceeding with this
-guide.
-
-### 0. Double-check your Git version
-
-**This notice applies only to /usr/local/bin/git**
-
-If you compiled Git from source on your GitLab server then please double-check
-that you are using a version that protects against CVE-2014-9390. For six
-months after this vulnerability became known the GitLab installation guide
-still contained instructions that would install the outdated, 'vulnerable' Git
-version 2.1.2.
-
-Run the following command to get your current Git version:
-
-```sh
-/usr/local/bin/git --version
-```
-
-If you see 'No such file or directory' then you did not install Git according
-to the outdated instructions from the GitLab installation guide and you can go
-to the next step 'Stop server' below.
-
-If you see a version string then it should be v1.8.5.6, v1.9.5, v2.0.5, v2.1.4,
-v2.2.1 or newer. You can use the [instructions in the GitLab source installation
-guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
-to install a newer version of Git.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-3-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-3-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v2.6.9
-```
-
-### 5. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires [Go 1.5](https://golang.org/dl)
-which should already be on your system from GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout 0.5.4
-sudo -u git -H make
-```
-
-### 6. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 7. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-2-stable:config/gitlab.yml.example origin/8-3-stable:config/gitlab.yml.example
-```
-
-#### GitLab default file
-
-The value of the `gitlab_workhorse_options` variable should be updated within the default gitlab file (`/etc/default/gitlab`) according to the following diff:
-
-```sh
-git diff origin/8-2-stable:lib/support/init.d/gitlab.default.example origin/8-3-stable:lib/support/init.d/gitlab.default.example
-```
-
-#### Nginx configuration
-
-GitLab 8.3 introduces major changes in the NGINX configuration.
-Because all HTTP requests pass through gitlab-workhorse now a lot of
-directives need to be removed from NGINX. During future upgrades there
-should be much less changes in the NGINX configuration because of
-this.
-
-View changes between the previous recommended Nginx configuration and the
-current one:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-2-stable:lib/support/nginx/gitlab-ssl origin/8-3-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-2-stable:lib/support/nginx/gitlab origin/8-3-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-3-stable/lib/support/init.d/gitlab.default.example#L34
-
-#### Init script
-
-We updated the init script for GitLab in order to pass new
-configuration options to gitlab-workhorse. We let gitlab-workhorse
-connect to the Rails application via a Unix domain socket and we tell
-it where the 'public' directory of GitLab is.
-
-```
-cd /home/git/gitlab
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 8. Use Redis v2.8.0+
-
-Previous versions of GitLab allowed Redis versions >= 2.0 to be used, but
-GitLab 8.3 uses Sidekiq 4.0, which requires Redis 2.8. You can check your Redis version
-with the following command:
-
- redis-cli info | grep redis_version
-
-If you need to upgrade, see the [installation guide for Redis](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-3-stable/doc/install/installation.md#6-redis).
-
-### 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.2)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.1 to 8.2](8.1-to-8.2.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-## Troubleshooting
-
-### "You appear to have cloned an empty repository."
-
-See the [7.14 to 8.0 update guide](7.14-to-8.0.md#troubleshooting).
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-3-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.3-to-8.4.md b/doc/update/8.3-to-8.4.md
index f5162dd5ff5..8514aa13f48 100644
--- a/doc/update/8.3-to-8.4.md
+++ b/doc/update/8.3-to-8.4.md
@@ -1,143 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.3 to 8.4
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-4-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-4-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v2.6.10
-```
-
-### 5. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires [Go 1.5](https://golang.org/dl)
-which should already be on your system from GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout 0.6.2
-sudo -u git -H make
-```
-
-### 6. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 7. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-3-stable:config/gitlab.yml.example origin/8-4-stable:config/gitlab.yml.example
-```
-
-#### Init script
-
-We updated the init script for GitLab in order to set a specific PATH for gitlab-workhorse.
-
-```
-cd /home/git/gitlab
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.3)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.2 to 8.3](8.2-to-8.3.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-4-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.4-to-8.5.md b/doc/update/8.4-to-8.5.md
index 9e2f98add8d..8514aa13f48 100644
--- a/doc/update/8.4-to-8.5.md
+++ b/doc/update/8.4-to-8.5.md
@@ -1,164 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.4 to 8.5
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-5-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-5-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v2.6.10
-```
-
-### 5. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout 0.6.4
-sudo -u git -H make
-```
-
-### 6. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 7. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-4-stable:config/gitlab.yml.example origin/8-5-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-4-stable:lib/support/nginx/gitlab-ssl origin/8-5-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-4-stable:lib/support/nginx/gitlab origin/8-5-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-5-stable/lib/support/init.d/gitlab.default.example#L37
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.4)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.3 to 8.4](8.3-to-8.4.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-5-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.5-to-8.6.md b/doc/update/8.5-to-8.6.md
index 55d8178c407..8514aa13f48 100644
--- a/doc/update/8.5-to-8.6.md
+++ b/doc/update/8.5-to-8.6.md
@@ -1,183 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.5 to 8.6
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-6-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-6-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v2.6.12
-```
-
-### 5. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.7.1
-sudo -u git -H make
-```
-
-### 6. Updates for PostgreSQL Users
-
-Starting with 8.6 users using GitLab in combination with PostgreSQL are required
-to have the `pg_trgm` extension enabled for all GitLab databases. If you're
-using GitLab's Omnibus packages there's nothing you'll need to do manually as
-this extension is enabled automatically. Users who install GitLab without using
-Omnibus (e.g. by building from source) have to enable this extension manually.
-To enable this extension run the following SQL command as a PostgreSQL super
-user for _every_ GitLab database:
-
-```sql
-CREATE EXTENSION IF NOT EXISTS pg_trgm;
-```
-
-Certain operating systems might require the installation of extra packages for
-this extension to be available. For example, users using Ubuntu will have to
-install the `postgresql-contrib` package in order for this extension to be
-available.
-
-### 7. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-5-stable:config/gitlab.yml.example origin/8-6-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-5-stable:lib/support/nginx/gitlab-ssl origin/8-6-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-5-stable:lib/support/nginx/gitlab origin/8-6-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-6-stable/lib/support/init.d/gitlab.default.example#L37
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.5)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.4 to 8.5](8.4-to-8.5.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-6-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.6-to-8.7.md b/doc/update/8.6-to-8.7.md
index 49db6f2967c..8514aa13f48 100644
--- a/doc/update/8.6-to-8.7.md
+++ b/doc/update/8.6-to-8.7.md
@@ -1,172 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.6 to 8.7
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-7-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-7-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --tags
-sudo -u git -H git checkout v2.7.2
-```
-
-### 5. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.7.1
-sudo -u git -H make
-```
-
-### 6. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 7. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-6-stable:config/gitlab.yml.example origin/8-7-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Disable `git gc --auto` because GitLab runs `git gc` for us already.
-
-```sh
-sudo -u git -H git config --global gc.auto 0
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-6-stable:lib/support/nginx/gitlab-ssl origin/8-7-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-6-stable:lib/support/nginx/gitlab origin/8-7-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-7-stable/lib/support/init.d/gitlab.default.example#L37
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.6)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.5 to 8.6](8.5-to-8.6.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-7-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.7-to-8.8.md b/doc/update/8.7-to-8.8.md
index ee7ec6f7614..8514aa13f48 100644
--- a/doc/update/8.7-to-8.8.md
+++ b/doc/update/8.7-to-8.8.md
@@ -1,172 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.7 to 8.8
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-8-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-8-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v2.7.2
-```
-
-### 5. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.7.1
-sudo -u git -H make
-```
-
-### 6. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 7. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-7-stable:config/gitlab.yml.example origin/8-8-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Disable `git gc --auto` because GitLab runs `git gc` for us already.
-
-```sh
-sudo -u git -H git config --global gc.auto 0
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-7-stable:lib/support/nginx/gitlab-ssl origin/8-8-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-7-stable:lib/support/nginx/gitlab origin/8-8-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/lib/support/init.d/gitlab.default.example#L37
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.7)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.6 to 8.7](8.6-to-8.7.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.8-to-8.9.md b/doc/update/8.8-to-8.9.md
index 7508443c30a..8514aa13f48 100644
--- a/doc/update/8.8-to-8.9.md
+++ b/doc/update/8.8-to-8.9.md
@@ -1,201 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.8 to 8.9
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-9-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-9-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v3.0.0
-```
-
-### 5. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.7.5
-sudo -u git -H make
-```
-
-### 6. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-# Login to MySQL
-mysql -u root -p
-
-# Grant the GitLab user the REFERENCES permission on the database
-GRANT REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
-
-# Quit the database session
-mysql> \q
-```
-
-### 7. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-8-stable:config/gitlab.yml.example origin/8-9-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Disable `git gc --auto` because GitLab runs `git gc` for us already.
-
-```sh
-sudo -u git -H git config --global gc.auto 0
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-8-stable:lib/support/nginx/gitlab-ssl origin/8-9-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-8-stable:lib/support/nginx/gitlab origin/8-9-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-9-stable/lib/support/init.d/gitlab.default.example#L37
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/v8.9.0/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.8)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.7 to 8.8](8.7-to-8.8.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-9-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/8.9-to-8.10.md b/doc/update/8.9-to-8.10.md
index 915e7db819a..8514aa13f48 100644
--- a/doc/update/8.9-to-8.10.md
+++ b/doc/update/8.9-to-8.10.md
@@ -1,201 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 8.9 to 8.10
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-10-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-10-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v3.2.1
-```
-
-### 5. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.7.8
-sudo -u git -H make
-```
-
-### 6. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-# Login to MySQL
-mysql -u root -p
-
-# Grant the GitLab user the REFERENCES permission on the database
-GRANT REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
-
-# Quit the database session
-mysql> \q
-```
-
-### 7. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-9-stable:config/gitlab.yml.example origin/8-10-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Disable `git gc --auto` because GitLab runs `git gc` for us already.
-
-```sh
-sudo -u git -H git config --global gc.auto 0
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-9-stable:lib/support/nginx/gitlab-ssl origin/8-10-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-9-stable:lib/support/nginx/gitlab origin/8-10-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-10-stable/lib/support/init.d/gitlab.default.example#L37
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/v8.9.0/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-For Ubuntu 16.04.1 LTS:
-
- sudo systemctl daemon-reload
-
-### 9. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 10. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.9)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.8 to 8.9](8.8-to-8.9.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-10-stable/config/gitlab.yml.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/9.0-to-9.1.md b/doc/update/9.0-to-9.1.md
index 7c9dacc9b90..8514aa13f48 100644
--- a/doc/update/9.0-to-9.1.md
+++ b/doc/update/9.0-to-9.1.md
@@ -1,407 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 9.0 to 9.1
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
-echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
-cd ruby-2.3.3
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-1-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-1-stable-ee
-```
-
-### 6. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-```
-
-### 7. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 8. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-0-stable:config/gitlab.yml.example origin/9-1-stable:config/gitlab.yml.example
-```
-
-#### Configuration changes for repository storages
-
-This version introduces a new configuration structure for repository storages.
-Update your current configuration as follows, replacing with your storages names and paths:
-
-**For installations from source**
-
-1. Update your `gitlab.yml`, from
-
- ```yaml
- repositories:
- storages: # You must have at least a 'default' storage path.
- default: /home/git/repositories
- nfs: /mnt/nfs/repositories
- cephfs: /mnt/cephfs/repositories
- ```
-
- to
-
- ```yaml
- repositories:
- storages: # You must have at least a 'default' storage path.
- default:
- path: /home/git/repositories
- nfs:
- path: /mnt/nfs/repositories
- cephfs:
- path: /mnt/cephfs/repositories
- ```
-
-**For Omnibus installations**
-
-1. Update your `/etc/gitlab/gitlab.rb`, from
-
- ```ruby
- git_data_dirs({
- "default" => "/var/opt/gitlab/git-data",
- "nfs" => "/mnt/nfs/git-data",
- "cephfs" => "/mnt/cephfs/git-data"
- })
- ```
-
- to
-
- ```ruby
- git_data_dirs({
- "default" => { "path" => "/var/opt/gitlab/git-data" },
- "nfs" => { "path" => "/mnt/nfs/git-data" },
- "cephfs" => { "path" => "/mnt/cephfs/git-data" }
- })
- ```
-
-#### Git configuration
-
-Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
-the GitLab server during `git gc`.
-
-```sh
-cd /home/git/gitlab
-
-sudo -u git -H git config --global repack.writeBitmaps true
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/9-0-stable:lib/support/nginx/gitlab-ssl origin/9-1-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/9-0-stable:lib/support/nginx/gitlab origin/9-1-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-1-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-1-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-0-stable:lib/support/init.d/gitlab.default.example origin/9-1-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 9. Install libs, migrations, etc.
-
-GitLab 9.1.8 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on the `re2` regular expression library. To install this dependency:
-
-```bash
-sudo apt-get install libre2-dev
-```
-
-Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
-you can [install re2 manually](https://github.com/google/re2/wiki/Install).
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 10. Optional: install Gitaly
-
-Gitaly is still an optional component of GitLab. If you want to save time
-during your 9.1 upgrade **you can skip this step**.
-
-If you have not yet set up Gitaly then follow [Gitaly section of the installation
-guide](../install/installation.md#install-gitaly).
-
-If you installed Gitaly in GitLab 9.0 you need to make some changes in
-gitlab.yml, and create a new config.toml file.
-
-#### Gitaly gitlab.yml changes
-
-Look for `socket_path:` the `gitaly:` section. Its value is usually
-`/home/git/gitlab/tmp/sockets/private/gitaly.socket`. Note what socket
-path your gitlab.yml is using. Now go to the `repositories:` section,
-and for each entry under `storages:`, add a `gitaly_address:` based on
-the socket path, but with `unix:` in front.
-
-```yaml
- repositories:
- storages:
- default:
- path: /home/git/repositories
- gitaly_address: unix:/home/git/gitlab/tmp/sockets/private/gitaly.socket
- other_storage:
- path: /home/git/other-repositories
- gitaly_address: unix:/home/git/gitlab/tmp/sockets/private/gitaly.socket
-```
-
-Each entry under `storages:` should use the same `gitaly_address`.
-
-#### Compile Gitaly
-
-This step will also create `config.toml.example` which you need below.
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-#### Gitaly config.toml
-
-In GitLab 9.1 we are replacing environment variables in Gitaly with a
-TOML configuration file.
-
-```shell
-cd /home/git/gitaly
-
-sudo mv env env.old
-sudo -u git cp config.toml.example config.toml
-# If you are using custom repository storage paths they need to be in config.toml
-sudo -u git -H editor config.toml
-```
-
-### 11. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 12. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (9.0)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.17 to 9.0](8.17-to-9.0.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-1-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-1-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/9.1-to-9.2.md b/doc/update/9.1-to-9.2.md
index b815242ab4e..8514aa13f48 100644
--- a/doc/update/9.1-to-9.2.md
+++ b/doc/update/9.1-to-9.2.md
@@ -1,330 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 9.1 to 9.2
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
-echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
-cd ruby-2.3.3
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-2-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-2-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-1-stable:config/gitlab.yml.example origin/9-2-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/9-1-stable:lib/support/nginx/gitlab-ssl origin/9-2-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/9-1-stable:lib/support/nginx/gitlab origin/9-2-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-2-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-2-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-1-stable:lib/support/init.d/gitlab.default.example origin/9-2-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 10. Install libs, migrations, etc.
-
-GitLab 9.2.8 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on the `re2` regular expression library. To install this dependency:
-
-```bash
-sudo apt-get install libre2-dev
-```
-
-Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
-you can [install re2 manually](https://github.com/google/re2/wiki/Install).
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:pack RAILS_ENV=production
-sudo -u git -H bundle exec rake gettext:po_to_json RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 11. Optional: install Gitaly
-
-Gitaly is still an optional component of GitLab. If you want to save time
-during your 9.2 upgrade **you can skip this step**.
-
-If you have not yet set up Gitaly then follow [Gitaly section of the installation
-guide](../install/installation.md#install-gitaly).
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 12. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 13. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (9.1)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 9.0 to 9.1](9.0-to-9.1.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-2-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-2-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/9.2-to-9.3.md b/doc/update/9.2-to-9.3.md
index a58b12cb81c..8514aa13f48 100644
--- a/doc/update/9.2-to-9.3.md
+++ b/doc/update/9.2-to-9.3.md
@@ -1,348 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 9.2 to 9.3
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
-echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
-cd ruby-2.3.3
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-3-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-3-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-If you have not yet set up Gitaly then follow [Gitaly section of the installation
-guide](../install/installation.md#install-gitaly).
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-2-stable:config/gitlab.yml.example origin/9-3-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/9-2-stable:lib/support/nginx/gitlab-ssl origin/9-3-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/9-2-stable:lib/support/nginx/gitlab origin/9-3-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-3-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-3-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-2-stable:lib/support/init.d/gitlab.default.example origin/9-3-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-GitLab 9.3.8 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on the `re2` regular expression library. To install this dependency:
-
-```bash
-sudo apt-get install libre2-dev
-```
-
-Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
-you can [install re2 manually](https://github.com/google/re2/wiki/Install).
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (9.2)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 9.1 to 9.2](9.1-to-9.2.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-3-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-3-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/9.3-to-9.4.md b/doc/update/9.3-to-9.4.md
index 0c87468334b..8514aa13f48 100644
--- a/doc/update/9.3-to-9.4.md
+++ b/doc/update/9.3-to-9.4.md
@@ -1,361 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 9.3 to 9.4
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
-echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
-cd ruby-2.3.3
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-4-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-4-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-If you have not yet set up Gitaly then follow [Gitaly section of the installation
-guide](../install/installation.md#install-gitaly).
-
-As of GitLab 9.4, Gitaly is a mandatory component of GitLab.
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-9.4 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-3-stable:config/gitlab.yml.example origin/9-4-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/9-3-stable:lib/support/nginx/gitlab-ssl origin/9-4-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/9-3-stable:lib/support/nginx/gitlab origin/9-4-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-4-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-4-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-3-stable:lib/support/init.d/gitlab.default.example origin/9-4-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-GitLab 9.4 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on the `re2` regular expression library. To install this dependency:
-
-```bash
-sudo apt-get install libre2-dev
-```
-
-Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
-you can [install re2 manually](https://github.com/google/re2/wiki/Install).
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (9.3)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 9.2 to 9.3](9.2-to-9.3.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-4-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-4-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/9.4-to-9.5.md b/doc/update/9.4-to-9.5.md
index 6a655f77a55..8514aa13f48 100644
--- a/doc/update/9.4-to-9.5.md
+++ b/doc/update/9.4-to-9.5.md
@@ -1,360 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 9.4 to 9.5
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
-echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
-cd ruby-2.3.3
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-5-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 9-5-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-9.5 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-4-stable:config/gitlab.yml.example origin/9-5-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/9-4-stable:lib/support/nginx/gitlab-ssl origin/9-5-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/9-4-stable:lib/support/nginx/gitlab origin/9-5-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-5-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-5-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-4-stable:lib/support/init.d/gitlab.default.example origin/9-5-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (9.4)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 9.3 to 9.4](9.3-to-9.4.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-5-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-5-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/9.5-to-10.0.md b/doc/update/9.5-to-10.0.md
index 7790d192a82..8514aa13f48 100644
--- a/doc/update/9.5-to-10.0.md
+++ b/doc/update/9.5-to-10.0.md
@@ -1,360 +1,5 @@
---
-comments: false
+redirect_to: upgrading_from_source.md
---
-# From 9.5 to 10.0
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download and compile Ruby:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
-echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
-cd ruby-2.3.3
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
-it has a minimum requirement of node v4.3.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v4.3.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-
-Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
-JavaScript dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-0-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 10-0-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.0 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 11. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-5-stable:config/gitlab.yml.example origin/10-0-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/9-5-stable:lib/support/nginx/gitlab-ssl origin/10-0-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/9-5-stable:lib/support/nginx/gitlab origin/10-0-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-0-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-0-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/9-5-stable:lib/support/init.d/gitlab.default.example origin/10-0-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 12. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 13. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 14. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (9.5)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 9.4 to 9.5](9.4-to-9.5.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-0-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-0-stable/lib/support/init.d/gitlab.default.example
+This document was moved to [another location](upgrading_from_source.md).
diff --git a/doc/update/README.md b/doc/update/README.md
index d4fc0cc91bf..e2fffadb1ea 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -5,32 +5,38 @@ update guides.
There are currently 3 official ways to install GitLab:
-- Omnibus packages
-- Source installation
-- Docker installation
+- [Omnibus packages](#omnibus-packages)
+- [Source installation](#installation-from-source)
+- [Docker installation](#installation-using-docker)
Based on your installation, choose a section below that fits your needs.
## Omnibus Packages
-- The [Omnibus update guide](http://docs.gitlab.com/omnibus/update/README.html)
+- The [Omnibus update guide][omni-update]
contains the steps needed to update an Omnibus GitLab package.
## Installation from source
-- [Upgrading Community Edition from source][source-ce] - The individual
- upgrade guides are for those who have installed GitLab CE from source.
-- [Upgrading Enterprise Edition from source][source-ee] - The individual
- upgrade guides are for those who have installed GitLab EE 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, eg. 6.2.0 to 6.2.1, and apply to both Community and Enterprise
Editions.
+In the past we used separate documents for the upgrading instructions, but we
+have since switched to using a single document. The old upgrading guidelines
+can still be found in the Git repository:
+
+- [Old upgrading guidelines for Community Edition][old-ce-upgrade-docs]
+- [Old upgrading guidelines for Enterprise Edition][old-ee-upgrade-docs]
+
## Installation using Docker
GitLab provides official Docker images for both Community and Enterprise
editions. They are based on the Omnibus package and instructions on how to
-update them are in [a separate document][omnidocker].
+update them are in [a separate document][omni-docker].
## Upgrading without downtime
@@ -97,6 +103,10 @@ migrations this could potentially lead to hours of downtime, depending on the
size of your database. To work around this you will have to use PostgreSQL and
meet the other online upgrade requirements mentioned above.
+### Steps
+
+Steps to [upgrade without downtime][omni-zero-downtime].
+
## Upgrading between editions
GitLab comes in two flavors: [Community Edition][ce] which is MIT licensed,
@@ -113,11 +123,10 @@ The following guides are for subscribers of the Enterprise Edition only.
If you wish to upgrade your GitLab installation from Community to Enterprise
Edition, follow the guides below based on the installation method:
-- [Source CE to EE update guides][source-ee] - Find your version, and follow the
- `-ce-to-ee.md` guide. The steps are very similar to a version upgrade: stop
- the server, get the code, update config files for the new functionality,
- install libraries and do migrations, update the init script, start the
- application and check its status.
+- [Source CE to EE update guides][source-ce-to-ee] - The steps are very similar
+ to a version upgrade: stop the server, get the code, update config files for
+ the new functionality, install libraries and do migrations, update the init
+ script, start the application and check its status.
- [Omnibus CE to EE][omni-ce-ee] - Follow this guide to update your Omnibus
GitLab Community Edition to the Enterprise Edition.
@@ -138,9 +147,13 @@ possible.
upgrading a PostgreSQL database with minimal downtime.
[omnidocker]: http://docs.gitlab.com/omnibus/docker/README.html
-[source-ee]: https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc/update
-[source-ce]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update
+[old-ee-upgrade-docs]: https://gitlab.com/gitlab-org/gitlab-ee/tree/11-8-stable-ee/doc/update
+[old-ce-upgrade-docs]: https://gitlab.com/gitlab-org/gitlab-ce/tree/11-8-stable/doc/update
+[source-ce-to-ee]: upgrading_from_ce_to_ee.md
[ee-ce]: ../downgrade_ee_to_ce/README.md
[ce]: https://about.gitlab.com/features/#community
[ee]: https://about.gitlab.com/features/#enterprise
[omni-ce-ee]: https://docs.gitlab.com/omnibus/update/README.html#updating-community-edition-to-enterprise-edition
+[omni-docker]: https://docs.gitlab.com/omnibus/docker/README.html
+[omni-update]: https://docs.gitlab.com/omnibus/update/README.html
+[omni-zero-downtime]: https://docs.gitlab.com/omnibus/update/README.html#zero-downtime-updates
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index 7c6a14cb104..350072186ee 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -95,8 +95,7 @@ Now, you can use pgloader to migrate the data from MySQL to PostgreSQL:
```
1. Once the migration finishes, you should see a summary table that looks like
-the following:
-
+ the following:
```
table name read imported errors total time
@@ -243,8 +242,7 @@ Now, you can use pgloader to migrate the data from MySQL to PostgreSQL:
```
1. Once the migration finishes, you should see a summary table that looks like
-the following:
-
+ the following:
```
table name read imported errors total time
@@ -286,4 +284,3 @@ If you experience 500 errors after the migration, try to clear the cache:
``` bash
sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
```
-
diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md
index 01c52aae7f5..964a3c76c04 100644
--- a/doc/update/restore_after_failure.md
+++ b/doc/update/restore_after_failure.md
@@ -12,7 +12,7 @@ First, roll back the code or package. For source installations this involves
checking out the older version (branch or tag). For Omnibus installations this
means installing the older .deb or .rpm package. Then, restore from a backup.
Follow the instructions in the
-[Backup and Restore](../raketasks/backup_restore.md#restore-a-previously-created-backup)
+[Backup and Restore](../raketasks/backup_restore.md#restore)
documentation.
## Potential problems on the next upgrade
@@ -80,4 +80,3 @@ exit
Once the migration is successfully marked, run the rake `db:migrate` task again.
You will likely have to repeat this process several times until all failed
migrations are marked complete.
-
diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
new file mode 100644
index 00000000000..0d1ecab5f8e
--- /dev/null
+++ b/doc/update/upgrading_from_ce_to_ee.md
@@ -0,0 +1,132 @@
+---
+comments: false
+---
+
+# Upgrading from Community Edition to Enterprise Edition from source
+
+NOTE: **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][old-ee-upgrade-docs].
+
+## General upgrading steps
+
+This guide assumes you have a correctly configured and tested installation of
+GitLab Community Edition. If you run into any trouble or if you have any
+questions please contact us at [support@gitlab.com].
+
+In all examples, replace `EE_BRANCH` with the Enterprise Edition branch for the
+version you are using, and `CE_BRANCH` with the Community Edition branch.
+Branch names use the format `major-minor-stable-ee` for Enterprise Edition, and
+`major-minor-stable` for Community Edition. For example, for 11.8.0 you would
+use the following branches:
+
+* Enterprise Edition: `11-8-stable-ee`
+* Community Edition: `11-8-stable`
+
+### 0. Backup
+
+Make a backup just in case something goes wrong:
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+For installations using MySQL, this may require granting "LOCK TABLES"
+privileges to the GitLab user on the database version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Get the EE code
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H git remote add -f ee https://gitlab.com/gitlab-org/gitlab-ee.git
+sudo -u git -H git checkout EE_BRANCH
+```
+
+### 3. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+```
+
+### 4. Install `gitlab-elasticsearch-indexer` (optional) **[STARTER ONLY]**
+
+If you're interested in using GitLab's new [elasticsearch repository
+indexer][indexer-beta] (currently in beta) please follow the instructions on the
+document linked above and enable the indexer usage in the GitLab admin settings.
+
+### 5. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 6. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check with:
+
+```bash
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations upgrade complete!
+
+## Things went south? Revert to previous version (Community Edition)
+
+### 1. Revert the code to the previous version
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H git checkout CE_BRANCH
+```
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+## Version specific steps
+
+Certain versions of GitLab may require you to perform additional steps when
+upgrading from Community Edition to Enterprise Edition. Should such steps be
+necessary, they will listed per version below.
+
+<!--
+Example:
+
+### 11.8.0
+
+Additional instructions here.
+-->
+
+[support@gitlab.com]: mailto:support@gitlab.com
+[old-ee-upgrade-docs]: https://gitlab.com/gitlab-org/gitlab-ee/tree/11-8-stable-ee/doc/update
+[indexer-beta]: https://docs.gitlab.com/ee/integration/elasticsearch.html
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
new file mode 100644
index 00000000000..b0c9aaa1eed
--- /dev/null
+++ b/doc/update/upgrading_from_source.md
@@ -0,0 +1,390 @@
+---
+comments: false
+---
+
+# Upgrading Community Edition and Enterprise Edition from source
+
+Make sure you view this update guide from the branch (version) of GitLab you
+would like to install (e.g., `11.8`. You can select the version in the version
+dropdown at the top left corner of GitLab (below the menu bar).
+
+In all examples, replace `BRANCH` with the branch for the version you uprading
+to (e.g. `11-8-stable` for `11.8`), and replace `PREVIOUS_BRANCH` with the
+branch for the version you are upgrading from (e.g. `11-7-stable` for `11.7`).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+## Guidelines for all versions
+
+This section contains all the steps necessary to upgrade Community Edition or
+Enterprise Edition, regardless of the version you are upgrading to. Version
+specific guidelines (should there be any) are covered separately.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+NOTE: If you installed GitLab from source, make sure `rsync` is installed.
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+NOTE: Beginning in GitLab 11.6, we only support Ruby 2.5 or higher, and dropped
+support for Ruby 2.4. Be sure to upgrade if necessary.
+
+You can check which version you are running with `ruby -v`.
+
+Download Ruby and compile it:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
+echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
+cd ruby-2.5.3
+
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-document --version '< 2'
+```
+
+### 4. Update Node
+
+NOTE: Beginning in GitLab 11.8, we only support node 8 or higher, and dropped
+support for node 6. Be sure to upgrade if necessary.
+
+GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
+This requires a minimum version of node v8.10.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v8.10.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+GitLab also requires the use of yarn `>= v1.10.0` to manage JavaScript
+dependencies.
+
+```bash
+curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+sudo apt-get update
+sudo apt-get install yarn
+```
+
+More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
+
+### 5. Update Go
+
+NOTE: GitLab 11.4 and higher only supports Go 1.10.x and newer, and dropped support for Go
+1.9.x. Be sure to upgrade your installation if necessary.
+
+You can check which version you are running with `go version`.
+
+Download and install Go:
+
+```bash
+# Remove former Go installation folder
+sudo rm -rf /usr/local/go
+
+curl --remote-name --progress https://dl.google.com/go/go1.10.5.linux-amd64.tar.gz
+echo 'a035d9beda8341b645d3f45a1b620cf2d8fb0c5eb409be36b389c0fd384ecc3a go1.10.5.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.10.5.linux-amd64.tar.gz
+sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
+rm go1.10.5.linux-amd64.tar.gz
+```
+
+### 6. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all --prune
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+sudo -u git -H git checkout -- locale
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout BRANCH
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout BRANCH-ee
+```
+
+### 7. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
+sudo -u git -H bin/compile
+```
+
+### 8. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. GitLab-Workhorse uses
+[GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-workhorse
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
+sudo -u git -H make
+```
+
+### 9. Update Gitaly
+
+#### Compile Gitaly
+
+```shell
+cd /home/git/gitaly
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
+sudo -u git -H make
+```
+
+### 10. Update gitlab-pages
+
+#### Only needed if you use GitLab Pages
+
+Install and compile gitlab-pages. GitLab-Pages uses
+[GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-pages
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
+sudo -u git -H make
+```
+
+### 11. Update MySQL permissions
+
+If you are using MySQL you need to grant the GitLab user the necessary
+permissions on the database:
+
+```bash
+mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
+```
+
+If you use MySQL with replication, or just have MySQL configured with binary logging,
+you will need to also run the following on all of your MySQL servers:
+
+```bash
+mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
+```
+
+You can make this setting permanent by adding it to your `my.cnf`:
+
+```
+log_bin_trust_function_creators=1
+```
+
+### 12. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There might be configuration options available for [`gitlab.yml`][yaml]. View
+them with the command below and apply them manually to your current
+`gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/PREVIOUS_BRANCH:config/gitlab.yml.example origin/BRANCH:config/gitlab.yml.example
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/PREVIOUS_BRANCH:lib/support/nginx/gitlab-ssl origin/BRANCH:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/PREVIOUS_BRANCH:lib/support/nginx/gitlab origin/BRANCH:lib/support/nginx/gitlab
+```
+
+If you are using Strict-Transport-Security in your installation to continue
+using it you must enable it in your Nginx configuration as GitLab application no
+longer handles setting it.
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to
+add the following line to `config/initializers/smtp_settings.rb`:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+#### Init script
+
+There might be new configuration options available for
+[`gitlab.default.example`][gl-example]. View them with the command below and
+apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/PREVIOUS_BRANCH:lib/support/init.d/gitlab.default.example origin/BRANCH:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 13. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --deployment --without development test mysql aws kerberos
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --deployment --without development test postgres aws kerberos
+
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Compile GetText PO files
+
+sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
+
+# Update node dependencies and recompile assets
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+# Clean up cache
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and
+data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 14. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 15. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Version specific upgrading instructions
+
+This section contains upgrading instructions for specific versions. When
+present, first follow the upgrading guidelines for all versions. If the version
+you are upgrading to is not listed here, then no additional steps are required.
+
+<!--
+Example:
+
+### 11.8.0
+
+Additional instructions here.
+-->
+
+## Things went south? Revert to previous version
+
+### 1. Revert the code to the previous version
+
+To revert to a previous version, you'll need to following the upgrading guides
+for the previous version. If you upgraded to 11.8 and want to revert back to
+11.7, you'll need to follow the guides for upgrading from 11.6 to 11.7. You can
+use the version dropdown at the top of the page to select the right version.
+
+When reverting, you should _not_ follow the database migration guides, as the
+backup is already migrated to the previous version.
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/init.d/gitlab.default.example
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/initializers/smtp_settings.rb.sample#L13
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/init.d/gitlab.default.example#L38
diff --git a/doc/update/upgrading_postgresql_using_slony.md b/doc/update/upgrading_postgresql_using_slony.md
index f009906256e..835166837a8 100644
--- a/doc/update/upgrading_postgresql_using_slony.md
+++ b/doc/update/upgrading_postgresql_using_slony.md
@@ -57,7 +57,7 @@ server.
## Installing Slony
Slony will be used to upgrade the database without requiring long downtimes.
-Slony can be downloaded from http://www.slony.info/. If you have installed
+Slony can be downloaded from <http://www.slony.info/>. If you have installed
PostgreSQL using your operating system's package manager you may also be able to
install Slony using said package manager.
@@ -176,10 +176,10 @@ if ($ENV{"SLONYSET"}) {
In this configuration file you should replace a few placeholders before you can
use it. The following placeholders should be replaced:
-* `OLD_HOST`: the address of the old database server.
-* `NEW_HOST`: the address of the new database server.
-* `SLONY_PASSWORD`: the password of the Slony user created earlier.
-* `TABLES`: the tables to replicate.
+- `OLD_HOST`: the address of the old database server.
+- `NEW_HOST`: the address of the new database server.
+- `SLONY_PASSWORD`: the password of the Slony user created earlier.
+- `TABLES`: the tables to replicate.
The list of tables to replicate can be generated by running the following
command on your old PostgreSQL database:
@@ -270,7 +270,6 @@ sudo -u gitlab-psql /opt/gitlab/embedded/bin/slon_start 1 --conf /var/opt/gitlab
If all went well this will produce output such as:
-
```
Invoke slon for node 1 - /opt/gitlab/embedded/bin/slon -p /var/run/slony1/slony_replication_node1.pid -s 1000 -d2 slony_replication 'host=192.168.0.7 dbname=gitlabhq_production user=slony port=5432 password=hieng8ezohHuCeiqu0leeghai4aeyahp' > /var/log/gitlab/slony/node1/gitlabhq_production-2016-10-06.log 2>&1 &
Slon successfully started for cluster slony_replication, node node1
diff --git a/doc/user/abuse_reports.md b/doc/user/abuse_reports.md
index 1f4f598b121..41ee7e62b2c 100644
--- a/doc/user/abuse_reports.md
+++ b/doc/user/abuse_reports.md
@@ -25,7 +25,6 @@ To report abuse from a user's comment:
1. Complete an abuse report.
1. Click the **Send report** button.
-
NOTE: **Note:**
A URL to the reported user's comment will be
pre-filled in the abuse report's **Message** field.
diff --git a/doc/user/account/security.md b/doc/user/account/security.md
index f4078876fab..8a8edc23529 100644
--- a/doc/user/account/security.md
+++ b/doc/user/account/security.md
@@ -1 +1,5 @@
+---
+redirect_to: '../profile/account/index.md'
+---
+
This document was moved to [profile](../profile/account/index.md).
diff --git a/doc/user/account/two_factor_authentication.md b/doc/user/account/two_factor_authentication.md
index ea2c8307860..42a66becc50 100644
--- a/doc/user/account/two_factor_authentication.md
+++ b/doc/user/account/two_factor_authentication.md
@@ -1 +1,5 @@
+---
+redirect_to: '../profile/account/two_factor_authentication.md'
+---
+
This document was moved to [profile/account/two_factor_authentication](../profile/account/two_factor_authentication.md).
diff --git a/doc/user/admin_area/broadcast_messages.md b/doc/user/admin_area/broadcast_messages.md
new file mode 100644
index 00000000000..02445abdb37
--- /dev/null
+++ b/doc/user/admin_area/broadcast_messages.md
@@ -0,0 +1,53 @@
+# Broadcast Messages
+
+GitLab can display messages to all users of a GitLab instance in a banner that appears in the UI.
+
+![Broadcast Message](img/broadcast_messages.png)
+
+Broadcast messages can be managed using the [broadcast messages API](../../api/broadcast_messages.md).
+
+NOTE: **Note:**
+If more than one banner message is active at one time, they are displayed in a stack in order of creation.
+
+## Adding a broadcast message
+
+To display messages to users on your GitLab instance, add broadcast message.
+
+To add a broadcast message:
+
+1. Navigate to the **Admin Area > Messages** page.
+1. Add the text for the message to the **Message** field. Markdown and emoji are supported.
+1. If required, click the **Customize colors** link to edit the background color and font color of the message.
+1. Select a date for the message to start and end.
+1. Click the **Add broadcast message** button.
+
+NOTE: **Note:**
+Once a broadcast message has expired, it is no longer displayed in the UI but is still listed in the
+list of broadcast messages.
+
+## Editing a broadcast message
+
+If changes are required to a broadcast message, they can be edited.
+
+To edit a broadcast message:
+
+1. Navigate to the **Admin Area > Messages** page.
+1. From the list of broadcast messages, click the appropriate button to edit the message.
+1. After making the required changes, click the **Update broadcast message** button.
+
+TIP: **Tip:**
+Expired messages can be made active again by changing their end date.
+
+## Deleting a broadcast message
+
+Broadcast messages that are no longer required can be deleted.
+
+To delete a broadcast message:
+
+1. Navigate to the **Admin Area > Messages** page.
+1. From the list of broadcast messages, click the appropriate button to delete the message.
+
+Once deleted, the broadcast message is removed from the list of broadcast messages.
+
+NOTE: **Note:**
+Broadcast messages can be deleted while active.
diff --git a/doc/user/admin_area/custom_project_templates.md b/doc/user/admin_area/custom_project_templates.md
index 5afbf9f2934..e34ba045c54 100644
--- a/doc/user/admin_area/custom_project_templates.md
+++ b/doc/user/admin_area/custom_project_templates.md
@@ -2,24 +2,25 @@
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing) 11.2.
-When you create a new project, creating it based on custom project templates is
-a convenient option to bootstrap from an existing project boilerplate.
-The administration setting to configure a GitLab group that serves as template
-source can be found under **Admin > Settings > Custom project templates**.
+When you create a new [project](../project/index.md), creating it based on custom project templates is
+a convenient bootstrap option.
+
+GitLab administrators can configure a GitLab group that serves as template
+source for an entire GitLab instance under **Admin area > Settings > Custom project templates**.
+
+NOTE: **Note:**
+To set project templates at a group level,
+see [Custom group-level project templates](../group/custom_project_templates.md).
Within this section, you can configure the group where all the custom project
templates are sourced. Every project directly under the group namespace will be
available to the user if they have access to them. For example, every public
-project in the group will be available to every logged user. However,
-private projects will be available only if the user has view [permissions](../permissions.md)
-in the project:
+project in the group will be available to every logged in user.
-- Project Owner, Maintainer, Developer, Reporter or Guest
-- Is a member of the Group: Owner, Maintainer, Developer, Reporter or Guest
+However, private projects will be available only if the user is a member of the project.
+NOTE: **Note:**
Projects below subgroups of the template group are **not** supported.
Repository and database information that are copied over to each new project are
identical to the data exported with [GitLab's Project Import/Export](../project/settings/import_export.md).
-
-If you would like to set project templates at a group level, please see [Custom group-level project templates](../group/custom_project_templates.md). \ No newline at end of file
diff --git a/doc/user/admin_area/img/broadcast_messages.png b/doc/user/admin_area/img/broadcast_messages.png
new file mode 100644
index 00000000000..926d38ae049
--- /dev/null
+++ b/doc/user/admin_area/img/broadcast_messages.png
Binary files differ
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
new file mode 100644
index 00000000000..00cea22e4e1
--- /dev/null
+++ b/doc/user/admin_area/index.md
@@ -0,0 +1,29 @@
+# GitLab Admin Area **[CORE ONLY]**
+
+The Admin Area provides a web UI for administering some features of GitLab self-managed instances.
+
+To access the Admin Area, either:
+
+- Click the Admin Area icon (the spanner or wrench icon).
+- Visit `/admin` on your self-managed instance.
+
+NOTE: **Note:**
+Only admin users can access the Admin Area.
+
+## Admin Area sections
+
+The Admin Area is made up of the following sections:
+
+| Section | Description |
+|:------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Overview | View your GitLab Dashboard, and maintain projects, users, groups, jobs, runners, and Gitaly servers. |
+| Monitoring | View GitLab system information, and information on background jobs, logs, [health checks](monitoring/health_check.md), request profiles, and audit logs. |
+| Messages | Send and manage [broadcast messages](broadcast_messages.md) for your users. |
+| System Hooks | Configure [system hooks](../../system_hooks/system_hooks.md) for many events. |
+| Applications | Create system [OAuth applications](../../integration/oauth_provider.md) for integrations with other services. |
+| Abuse Reports | Manage [abuse reports](abuse_reports.md) submitted by your users. |
+| Deploy Keys | Create instance-wide [SSH deploy keys](../../ssh/README.md#deploy-keys). |
+| Service Templates | Create [service templates](../project/integrations/services_templates.md) for projects. |
+| Labels | Create and maintain [labels](labels.md) for your GitLab instance. |
+| Appearance | Customize [GitLab's appearance](../../customization/index.md). |
+| Settings | Modify the [settings](settings/index.md) for your GitLab instance. |
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index 43b1190fb48..e183898dfb1 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -1,11 +1,11 @@
# Health Check
> **Notes:**
+
> - Liveness and readiness probes were [introduced][ce-10416] in GitLab 9.1.
-> - The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and will
-> be deprecated in GitLab 9.1. Read more in the [old behavior](#old-behavior)
-> section.
-> - [Access token](#access-token) has been deprecated in GitLab 9.4
+> - The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and was
+> be deprecated in GitLab 9.1.
+> - [Access token](#access-token-deprecated) has been deprecated in GitLab 9.4
> in favor of [IP whitelist](#ip-whitelist)
GitLab provides liveness and readiness probes to indicate service health and
@@ -16,22 +16,19 @@ traffic until the system is ready or restart the container as needed.
## IP whitelist
-To access monitoring resources, the client IP needs to be included in a whitelist.
+To access monitoring resources, the requesting client IP needs to be included in a whitelist.
[Read how to add IPs to a whitelist for the monitoring endpoints][admin].
## Using the endpoints
-With default whitelist settings, the probes can be accessed from localhost:
+With default whitelist settings, the probes can be accessed from localhost using the following URLs:
- `http://localhost/-/health`
- `http://localhost/-/readiness`
- `http://localhost/-/liveness`
-
-The first endpoint, `/-/health/`, only checks whether the application server is running. It does
--not verify the database or other services are running. A successful response will return
-a 200 status code with the following message:
+The first endpoint, `health`, only checks whether the application server is running. It does not verify the database or other services are running. A successful response will return a 200 status code with the following message:
```
GitLab OK
@@ -39,9 +36,9 @@ GitLab OK
The readiness and liveness probes will provide a report of system health in JSON format.
-Readiness example output:
+`readiness` probe example output:
-```
+```json
{
"queues_check" : {
"status" : "ok"
@@ -61,9 +58,9 @@ Readiness example output:
}
```
-Liveness example output:
+`liveness` probe example output:
-```
+```json
{
"cache_check" : {
"status" : "ok"
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index d4853a5842e..01979f12a01 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -20,7 +20,7 @@ From now on, every existing project and newly created ones that don't have a
`.gitlab-ci.yml`, will use the Auto DevOps pipelines.
If you want to disable it for a specific project, you can do so in
-[its settings](../../../topics/autodevops/index.md#enabling-auto-devops).
+[its settings](../../../topics/autodevops/index.md##enablingdisabling-auto-devops).
## Maximum artifacts size **[CORE ONLY]**
@@ -38,7 +38,7 @@ To change it:
The default expiration time of the [job artifacts](../../../administration/job_artifacts.md)
can be set in the Admin area of your GitLab instance. The syntax of duration is
-described in [`artifacts:expire_in`](../../../ci/yaml/README.md#artifacts-expire_in)
+described in [`artifacts:expire_in`](../../../ci/yaml/README.md#artifactsexpire_in)
and the default value is `30 days`. On GitLab.com they
[never expire](../../gitlab_com/index.md#gitlab-ci-cd).
@@ -47,7 +47,7 @@ and the default value is `30 days`. On GitLab.com they
1. Hit **Save changes** for the changes to take effect.
This setting is set per job and can be overridden in
-[`.gitlab-ci.yml`](../../../ci/yaml/README.md#artifacts-expire_in).
+[`.gitlab-ci.yml`](../../../ci/yaml/README.md#artifactsexpire_in).
To disable the expiration, set it to `0`. The default unit is in seconds.
## Archive jobs **[CORE ONLY]**
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index 93767aefb51..8358fe64f18 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -14,6 +14,10 @@ include:
- [Usage statistics](usage_statistics.md)
- [Visibility and access controls](visibility_and_access_controls.md)
+NOTE: **Note:**
+You can change the [first day of the week](../../profile/preferences.md) for the entire GitLab instance
+in the **Localization** section of **Admin area > Settings > Preferences**.
+
## GitLab.com admin area settings
Most of the settings under the admin area change the behavior of the whole
diff --git a/doc/user/admin_area/settings/third_party_offers.md b/doc/user/admin_area/settings/third_party_offers.md
index 177251b52b9..23311801790 100644
--- a/doc/user/admin_area/settings/third_party_offers.md
+++ b/doc/user/admin_area/settings/third_party_offers.md
@@ -3,4 +3,7 @@
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20379)
> in [GitLab Core](https://about.gitlab.com/pricing/) 11.1
-The display of third party offers can be controlled in the Admin Area -> Settings page.
+Within GitLab, we inform users of available third-party offers they might find valuable in order to enhance the development of their projects.
+An example is the Google Cloud Platform free credit for using [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/).
+
+The display of third-party offers can be toggled in the Admin area on the Settings page.
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index bd0155dc712..e165a120162 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -12,9 +12,9 @@ If enabled, version check will inform you if a new version is available and the
importance of it through a status. This is shown on the help page (i.e. `/help`)
for all signed in users, and on the admin pages. The statuses are:
-* Green: You are running the latest version of GitLab.
-* Orange: An updated version of GitLab is available.
-* Red: The version of GitLab you are running is vulnerable. You should install
+- Green: You are running the latest version of GitLab.
+- Orange: An updated version of GitLab is available.
+- Red: The version of GitLab you are running is vulnerable. You should install
the latest version with security fixes as soon as possible.
![Orange version check example](img/update-available.png)
diff --git a/doc/user/award_emojis.md b/doc/user/award_emojis.md
index 93be3da44d4..e4fd08a582c 100644
--- a/doc/user/award_emojis.md
+++ b/doc/user/award_emojis.md
@@ -1,24 +1,24 @@
# Award emoji
-> **Notes:**
-> - First [introduced][1825] in GitLab 8.2.
-> - GitLab 9.0 [introduced][ce-9570] the usage of native emojis if the platform
+> - First [introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1825) in GitLab 8.2.
+> - GitLab 9.0 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9570) the usage of native emoji if the platform
> supports them and falls back to images or CSS sprites. This change greatly
-> improved the award emoji performance overall.
+> improved award emoji performance overall.
When you're collaborating online, you get fewer opportunities for high-fives
-and thumbs-ups. Emoji can be awarded to issues, merge requests, snippets, and
-virtually everywhere where you can have a discussion.
+and thumbs-ups. Emoji can be awarded to [issues](project/issues/index.md), [merge requests](project/merge_requests/index.md),
+[snippets](snippets.md), and anywhere you can have a discussion.
![Award emoji](img/award_emoji_select.png)
Award emoji make it much easier to give and receive feedback without a long
-comment thread. Comments that are only emoji will automatically become
-award emoji.
+comment thread.
+
+For information on the relevant API, see [Award Emoji API](../api/award_emoji.md).
## Sort issues and merge requests on vote count
-> [Introduced][2871] in GitLab 8.5.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2781) in GitLab 8.5.
You can quickly sort issues and merge requests by the number of votes they
have received. The sort options can be found in the dropdown menu as "Most
@@ -32,20 +32,16 @@ downvotes.
## Award emoji for comments
-> [Introduced][4291] in GitLab 8.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4291) in GitLab 8.9.
Award emoji can also be applied to individual comments when you want to
celebrate an accomplishment or agree with an opinion.
-To add an award emoji, click the smile in the top right of the comment and pick
-an emoji from the dropdown. If you want to remove an award emoji, just click
-the emoji again and the vote will be removed.
+To:
+
+- Add an award emoji, click the smile in the top right of the comment and pick an emoji from the dropdown.
+- Remove an award emoji, click the emoji again and the vote will be removed.
![Picking an emoji for a comment](img/award_emoji_comment_picker.png)
![An award emoji has been applied to a comment](img/award_emoji_comment_awarded.png)
-
-[2871]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2781
-[1825]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1825
-[4291]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4291
-[ce-9570]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9570
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 9379d047fca..1e2fad1efe9 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -248,13 +248,14 @@ For large projects with many contributors, it may be useful to stop discussions
in issues or merge requests in these scenarios:
- The project maintainer has already resolved the discussion and it is not helpful
-for continued feedback. The project maintainer has already directed new conversation
-to newer issues or merge requests.
+ for continued feedback. The project maintainer has already directed new conversation
+ to newer issues or merge requests.
- The people participating in the discussion are trolling, abusive, or otherwise
-being unproductive.
+ being unproductive.
-In these cases, a user with Maintainer permissions or higher in the project can lock (and unlock)
-an issue or a merge request, using the "Lock" section in the sidebar:
+In these cases, a user with Developer permissions or higher in the project can lock (and unlock)
+an issue or a merge request, using the "Lock" section in the sidebar. For issues,
+a user with Reporter permissions can lock (and unlock).
| Unlock | Lock |
| :-----------: | :----------: |
@@ -275,17 +276,17 @@ Additionally locked issues can not be reopened.
## Filtering notes
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/26723) in GitLab 11.5.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/26723) in GitLab 11.5.
-For issues with many comments like activity notes and user comments, sometimes
-finding useful information can be hard. There is a way to filter comments from single notes and discussions for merge requests and issues.
+For issues with many comments like activity notes and user comments, sometimes
+finding useful information can be hard. There is a way to filter comments from single notes and discussions for merge requests and issues.
-From a merge request's **Discussion** tab, or from an issue overview, find the filter's dropdown menu on the right side of the page, from which you can choose one of the following options:
+From a merge request's **Discussion** tab, or from an epic/issue overview, find the filter's dropdown menu on the right side of the page, from which you can choose one of the following options:
- **Show all activity**: displays all user comments and system notes
-(issue updates, mentions from other issues, changes to the description, etc).
+ (issue updates, mentions from other issues, changes to the description, etc).
- **Show comments only**: only displays user comments in the list.
-- **Show history only**: only displays activity notes.
+- **Show history only**: only displays activity notes.
![Notes filters dropdown options](img/index_notes_filters.png)
@@ -297,21 +298,21 @@ from any device you're logged into.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/18008) in GitLab 11.6.
-As a reviewer, you're able to suggest code changes with a simple
+As a reviewer, you're able to suggest code changes with a simple
markdown syntax in Merge Request Diff discussions. Then, the
-Merge Request author (or other users with appropriate
+Merge Request author (or other users with appropriate
[permission](../permissions.md)) is able to apply these
-suggestions with a click, which will generate a commit in
+suggestions with a click, which will generate a commit in
the Merge Request authored by the user that applied them.
1. Choose a line of code to be changed, add a new comment, then click
-on the **Insert suggestion** icon in the toolbar:
+ on the **Insert suggestion** icon in the toolbar:
![Add a new comment](img/insert_suggestion.png)
-
+
> **Note:**
The suggestion will only affect the commented line. Multi-line
- suggestions are currently not supported. Will be introduced by
+ suggestions are currently not supported. Will be introduced by
[#53310](https://gitlab.com/gitlab-org/gitlab-ce/issues/53310).
1. In the comment, add your suggestion to the pre-populated code block:
@@ -326,9 +327,9 @@ on the **Insert suggestion** icon in the toolbar:
![Apply suggestions](img/suggestion.png)
> **Note:**
- Discussions are _not_ automatically resolved. Will be introduced by
+ Discussions are _not_ automatically resolved. Will be introduced by
[#54405](https://gitlab.com/gitlab-org/gitlab-ce/issues/54405).
-
+
Once the author applies a suggestion, it will be marked with the **Applied** label,
and GitLab will create a new commit with the message `Apply suggestion to <file-name>`
and push the suggested change directly into the codebase in the merge request's branch.
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index e14e716a5eb..762cf911fcf 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -46,7 +46,7 @@ Below are the settings for [GitLab Pages].
| Setting | GitLab.com | Default |
| ----------------------- | ---------------- | ------------- |
| Domain name | `gitlab.io` | - |
-| IP address | `52.167.214.135` | - |
+| IP address | `35.185.44.232` | - |
| Custom domains support | yes | no |
| TLS certificates support| yes | no |
@@ -60,7 +60,7 @@ Below are the current settings regarding [GitLab CI/CD](../../ci/README.md).
| Setting | GitLab.com | Default |
| ----------- | ----------------- | ------------- |
| Artifacts maximum size | 1G | 100M |
-| Artifacts [expiry time](../../ci/yaml/README.md#artifacts-expire_in) | kept forever | deleted after 30 days unless otherwise specified |
+| Artifacts [expiry time](../../ci/yaml/README.md#artifactsexpire_in) | kept forever | deleted after 30 days unless otherwise specified |
## Repository size limit
@@ -281,12 +281,14 @@ of proposed changes can be found at
GitLab.com adjusts the memory limits for the [unicorn-worker-killer][unicorn-worker-killer] gem.
Base default:
-* `memory_limit_min` = 750MiB
-* `memory_limit_max` = 1024MiB
+
+- `memory_limit_min` = 750MiB
+- `memory_limit_max` = 1024MiB
Web front-ends:
-* `memory_limit_min` = 1024MiB
-* `memory_limit_max` = 1280MiB
+
+- `memory_limit_min` = 1024MiB
+- `memory_limit_max` = 1280MiB
## GitLab.com at scale
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index 9f9b2da23e1..8cdfb13a97b 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -56,14 +56,19 @@ group. That way you can have different clusters for different environments,
like dev, staging, production, etc.
Add another cluster similar to the first one and make sure to
-[set an environment scope](#environment-scopes) that will
+[set an environment scope](#environment-scopes-premium) that will
differentiate the new cluster from the rest.
-NOTE: **Note:**
-Auto DevOps is not supported for a group with multiple clusters, as it
-is not possible to set `AUTO_DEVOPS_DOMAIN` per environment on the group
-level. This will be resolved in the future with the [following issue](
-https://gitlab.com/gitlab-org/gitlab-ce/issues/52363).
+## Base domain
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24580) in GitLab 11.8.
+
+Domains at the cluster level permit support for multiple domains
+per [multiple Kubernetes clusters](#multiple-kubernetes-clusters-premium). When specifying a domain,
+this will be automatically set as an environment variable (`KUBE_INGRESS_BASE_DOMAIN`) during
+the [Auto DevOps](../../../topics/autodevops/index.md) stages.
+
+The domain should have a wildcard DNS configured to the Ingress IP address.
## Environment scopes **[PREMIUM]**
@@ -90,7 +95,6 @@ For example, let's say we have the following Kubernetes clusters:
| Test | `test` | Group |
| Development| `*` | Group |
-
And the following environments are set in [`.gitlab-ci.yml`](../../../ci/yaml/README.md):
```yaml
@@ -129,4 +133,4 @@ The following features are not currently available for group-level clusters:
1. Terminals (see [related issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/55487)).
1. Pod logs (see [related issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/55488)).
-1. Deployment boards (see [related issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/55488)).
+1. Deployment boards (see [related issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/55489)).
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index eaf0273050b..8e101407ac0 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -2,22 +2,25 @@
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing) 11.6.
-When you create a new project, creating it based on custom project templates is
-a convenient option to bootstrap from an existing project boilerplate.
-The group-level setting to configure a GitLab group that serves as template
-source can be found under **Group > Settings > General > Custom project templates**.
+When you create a new [project](../project/index.md), creating it based on custom project templates is
+a convenient bootstrap option.
+
+Users can configure a GitLab group that serves as template
+source under a group's **Settings > General > Custom project templates**.
+
+NOTE: **Note:**
+GitLab administrators can
+[set project templates for an entire GitLab instance](../admin_area/custom_project_templates.md).
Within this section, you can configure the group where all the custom project
templates are sourced. Every project directly under the group namespace will be
available to the user if they have access to them. For example, every public
-project in the group will be available to every logged in user. However,
-private projects will be available only if the user has view [permissions](../permissions.md)
-in the project. That is, users with Owner, Maintainer, Developer, Reporter or Guest roles for projects,
-or for groups to which the project belongs.
+project in the group will be available to every logged in user.
+However, private projects will be available only if the user is a member of the project.
+
+NOTE: **Note:**
Projects of nested subgroups of a selected template source cannot be used.
Repository and database information that are copied over to each new project are
identical to the data exported with [GitLab's Project Import/Export](../project/settings/import_export.md).
-
-If you would like to set project templates at an instance level, please see [Custom instance-level project templates](../admin_area/custom_project_templates.md). \ No newline at end of file
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 5fea683a7fd..c1f50bcc593 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -18,9 +18,9 @@ a link to the group settings. By clicking the last button you can leave that gro
You can create groups for numerous reasons. To name a few:
- Organize related projects under the same [namespace](#namespaces), add members to that
-group and grant access to all their projects at once
+ group and grant access to all their projects at once
- Create a group, include members of your team, and make it easier to
-`@mention` all the team at once in issues and merge requests
+ `@mention` all the team at once in issues and merge requests
- Create a group for your company members, and create [subgroups](subgroups/index.md)
for each individual team. Let's say you create a group called `company-team`, and among others,
you created subgroups in this group for each individual team `backend-team`,
@@ -43,11 +43,11 @@ In GitLab, a namespace is a unique name to be used as a user name, a group name,
For example, consider a user named Alex:
1. Alex creates an account on GitLab.com with the username `alex`;
-their profile will be accessed under `https://gitlab.example.com/alex`
+ their profile will be accessed under `https://gitlab.example.com/alex`
1. Alex creates a group for their team with the groupname `alex-team`;
-the group and its projects will be accessed under `https://gitlab.example.com/alex-team`
+ the group and its projects will be accessed under `https://gitlab.example.com/alex-team`
1. Alex creates a subgroup of `alex-team` with the subgroup name `marketing`;
-this subgroup and its projects will be accessed under `https://gitlab.example.com/alex-team/marketing`
+ this subgroup and its projects will be accessed under `https://gitlab.example.com/alex-team/marketing`
By doing so:
@@ -107,7 +107,7 @@ Consider we have a group with two projects:
- On the **Group Members** page we can now add a new user to the group.
- Now because this user is a **Developer** member of the group, he automatically
-gets **Developer** access to **all projects** within that group.
+ gets **Developer** access to **all projects** within that group.
If necessary, you can increase the access level of an individual user for a specific project,
by adding them again as a new member to the project with the new permission levels.
@@ -154,7 +154,7 @@ There are two different ways to add a new project to a group:
## Transfer projects into groups
-Learn how to [transfer a project into a group](../project/index.md#transfer-an-existing-project-into-a-group).
+Learn how to [transfer a project into a group](../project/settings/index.md#transferring-an-existing-project-into-another-namespace).
## Sharing a project with a group
@@ -181,6 +181,7 @@ Please make sure to understand that:
- You can only transfer the group to a group you manage.
- You will need to update your local repositories to point to the new location.
- If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.
+- Only explicit group membership is transferred, not the inherited membership. If this would leave the group without an owner, the transferring user is added as owner instead.
## Group settings
@@ -267,9 +268,9 @@ Define project templates at a group-level by setting a group as a template sourc
### Advanced settings
- **Projects**: view all projects within that group, add members to each project,
-access each project's settings, and remove any project from the same screen.
+ access each project's settings, and remove any project from the same screen.
- **Webhooks**: configure [webhooks](../project/integrations/webhooks.md) to your group.
- **Kubernetes cluster integration**: connect your GitLab group with [Kubernetes clusters](clusters/index.md).
- **Audit Events**: view [Audit Events](https://docs.gitlab.com/ee/administration/audit_events.html#audit-events)
-for the group. **[STARTER ONLY]**
+ for the group. **[STARTER ONLY]**
- **Pipelines quota**: keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group.
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 943b0c693c0..3cecefe11f5 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -1,8 +1,8 @@
# Subgroups
NOTE: **Note:**
-[Introduced][ce-2772] in GitLab 9.0. Not available when using MySQL as external
-database (support removed in GitLab 9.3 [due to performance reasons][issue]).
+[Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2772) in GitLab 9.0. Not available when using MySQL as external
+database (support removed in GitLab 9.3 [due to performance reasons](https://gitlab.com/gitlab-org/gitlab-ce/issues/30472#note_27747600)).
With subgroups (aka nested groups or hierarchical groups) you can have
up to 20 levels of nested groups, which among other things can help you to:
@@ -13,7 +13,7 @@ up to 20 levels of nested groups, which among other things can help you to:
- **Organize large projects.** For large projects, subgroups makes it
potentially easier to separate permissions on parts of the source code.
- **Make it easier to manage people and control visibility.** Give people
- different [permissions][] depending on their group [membership](#membership).
+ different [permissions](../../permissions.md#group-members-permissions) depending on their group [membership](#membership).
## Database Requirements
@@ -21,8 +21,8 @@ Nested groups are only supported when you use PostgreSQL. Supporting nested
groups on MySQL in an efficient way is not possible due to MySQL's limitations.
See the following links for more information:
-* <https://gitlab.com/gitlab-org/gitlab-ce/issues/30472>
-* <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10885>
+- <https://gitlab.com/gitlab-org/gitlab-ce/issues/30472>
+- <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10885>
## Overview
@@ -80,9 +80,9 @@ structure.
NOTE: **Note:**
You need to be an Owner of a group in order to be able to create a subgroup. For
-more information check the [permissions table][permissions].
+more information check the [permissions table](../../permissions.md#group-members-permissions).
For a list of words that are not allowed to be used as group names see the
-[reserved names][reserved].
+[reserved names](../../reserved_names.md).
Users can always create subgroups if they are explicitly added as an Owner to
a parent group even if group creation is disabled by an administrator in their
settings.
@@ -164,9 +164,11 @@ and you can choose the group of people to be notified.
Here's a list of what you can't do with subgroups:
-- [GitLab Pages](../../project/pages/index.md) are not currently working for
- projects hosted under a subgroup. That means that only projects hosted under
- the first parent group will work.
+- [GitLab Pages](../../project/pages/index.md) supports projects hosted under
+ a subgroup, but not subgroup websites.
+ That means that only the highest-level group supports
+ [group websites](../../project/pages/introduction.html#user-or-group-pages),
+ although you can have project websites under a subgroup.
- It is not possible to share a project with a group that's an ancestor of
the group the project is in. That means you can only share as you walk down
the hierarchy. For example, `group/subgroup01/project` **cannot** be shared
@@ -174,6 +176,6 @@ Here's a list of what you can't do with subgroups:
`group/subgroup01/subgroup03`.
[ce-2772]: https://gitlab.com/gitlab-org/gitlab-ce/issues/2772
-[permissions]: ../../permissions.md#group
+[permissions]: ../../permissions.md#group-members-permissions
[reserved]: ../../reserved_names.md
[issue]: https://gitlab.com/gitlab-org/gitlab-ce/issues/30472#note_27747600
diff --git a/doc/user/index.md b/doc/user/index.md
index fc68404d0c2..b84879601ff 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -8,32 +8,26 @@ Welcome to GitLab! We're glad to have you here!
As a GitLab user you'll have access to all the features
your [subscription](https://about.gitlab.com/pricing/)
-includes, except [GitLab administrator](../README.md#administrator-documentation)
+includes, except [GitLab administrator](../administration/index.md)
settings, unless you have admin privileges to install, configure,
and upgrade your GitLab instance.
-For GitLab.com, admin privileges are restricted to the GitLab team.
+Admin privileges for [GitLab.com](https://gitlab.com/) are restricted to the GitLab team.
-If you run your own GitLab instance and are looking for the administration settings,
-please refer to the [administration](../README.md#administrator-documentation)
-documentation.
+For more information on configuring GitLab self-managed instances, see [Administrator documentation](../administration/index.md).
## Overview
-GitLab is a fully integrated software development platform that enables you
-and your team to work cohesively, faster, transparently, and effectively,
-since the discussion of a new idea until taking that idea to production all
-the way through, from within the same platform.
+GitLab is a fully integrated software development platform that enables your team to be transparent, fast, effective, and cohesive from discussion on a new idea to production, all on the same platform.
-Please check this page for an overview on [GitLab's features](https://about.gitlab.com/features/).
+For more information, see [All GitLab Features](https://about.gitlab.com/features/).
### Concepts
-For an overview on concepts involved when developing code on GitLab,
-read the articles on:
+To get familiar with the concepts needed to develop code on GitLab, read the following articles:
-- [Mastering Code Review With GitLab](https://about.gitlab.com/2017/03/17/demo-mastering-code-review-with-gitlab/).
-- [GitLab Workflow, an Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario).
+- [Demo: Mastering Code Review With GitLab](https://about.gitlab.com/2017/03/17/demo-mastering-code-review-with-gitlab/).
+- [GitLab Workflow: An Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario).
- [Tutorial: It's all connected in GitLab](https://about.gitlab.com/2016/03/08/gitlab-tutorial-its-all-connected/): an overview on code collaboration with GitLab.
- [Trends in Version Control Land: Microservices](https://about.gitlab.com/2016/08/16/trends-in-version-control-land-microservices/).
- [Trends in Version Control Land: Innersourcing](https://about.gitlab.com/2016/07/07/trends-version-control-innersourcing/).
@@ -42,24 +36,24 @@ read the articles on:
GitLab is a Git-based platform that integrates a great number of essential tools for software development and deployment, and project management:
-- Code hosting in repositories with version control
-- Track proposals for new implementations, bug reports, and feedback with a
-fully featured [Issue Tracker](project/issues/index.md#issue-tracker)
-- Organize and prioritize with [Issue Boards](project/issues/index.md#issue-boards)
-- Code review in [Merge Requests](project/merge_requests/index.md) with live-preview changes per
-branch with [Review Apps](../ci/review_apps/index.md)
-- Build, test and deploy with built-in [Continuous Integration](../ci/README.md)
-- Deploy your personal and professional static websites with [GitLab Pages](project/pages/index.md)
-- Integrate with Docker with [GitLab Container Registry](project/container_registry.md)
-- Track the development lifecycle with [GitLab Cycle Analytics](project/cycle_analytics.md)
+- Hosting code in repositories with version control
+- Tracking proposals for new implementations, bug reports, and feedback with a
+ fully featured [Issue Tracker](project/issues/index.md#issue-tracker)
+- Organizing and prioritizing with [Issue Boards](project/issues/index.md#issue-boards)
+- Reviewing code in [Merge Requests](project/merge_requests/index.md) with live-preview changes per
+ branch with [Review Apps](../ci/review_apps/index.md)
+- Building, testing and deploying with built-in [Continuous Integration](../ci/README.md)
+- Deploying personal and professional static websites with [GitLab Pages](project/pages/index.md)
+- Integrating with Docker by using [GitLab Container Registry](project/container_registry.md)
+- Tracking the development lifecycle by usingn [GitLab Cycle Analytics](project/cycle_analytics.md)
With GitLab Enterprise Edition, you can also:
- Provide support with [Service Desk](https://docs.gitlab.com/ee/user/project/service_desk.html)
- Improve collaboration with
-[Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/index.html#merge-request-approvals),
-[Multiple Assignees for Issues](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html),
-and [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards)
+ [Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/index.html#merge-request-approvals),
+ [Multiple Assignees for Issues](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html),
+ and [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards)
- Create formal relationships between issues with [Related Issues](https://docs.gitlab.com/ee/user/project/issues/related_issues.html)
- Use [Burndown Charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_charts.html) to track progress during a sprint or while working on a new version of their software.
- Leverage [Elasticsearch](https://docs.gitlab.com/ee/integration/elasticsearch.html) with [Advanced Global Search](https://docs.gitlab.com/ee/user/search/advanced_global_search.html) and [Advanced Syntax Search](https://docs.gitlab.com/ee/user/search/advanced_search_syntax.html) for faster, more advanced code search across your entire GitLab instance
@@ -68,25 +62,27 @@ and [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.
- [Export issues as CSV](https://docs.gitlab.com/ee/user/project/issues/csv_export.html)
- View your entire CI/CD pipeline involving more than one project with [Multiple-Project Pipeline Graphs](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html)
- [Lock files](https://docs.gitlab.com/ee/user/project/file_lock.html) to prevent conflicts
-- View of the current health and status of each CI environment running on Kubernetes with [Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html)
-- Leverage your continuous delivery method with [Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html)
+- View the current health and status of each CI environment running on Kubernetes with [Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html)
+- Leverage continuous delivery method with [Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html)
-You can also [integrate](project/integrations/project_services.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, HipChat, Trello, Slack, Bamboo CI, JIRA, and a lot more.
+You can also [integrate](project/integrations/project_services.md) GitLab with
+numerous third-party applications, such as Mattermost, Microsoft Teams, Trello,
+Slack, Bamboo CI, JIRA, and a lot more.
## Projects
-In GitLab, you can create [projects](project/index.md) for numerous reasons, such as, host
-your code, use it as an issue tracker, collaborate on code, and continuously
+In GitLab, you can create [projects](project/index.md) to host
+your code, track issues, collaborate on code, and continuously
build, test, and deploy your app with built-in GitLab CI/CD. Or, you can do
it all at once, from one single project.
- [Repositories](project/repository/index.md): Host your codebase in
-repositories with version control and as part of a fully integrated platform.
+ repositories with version control and as part of a fully integrated platform.
- [Issues](project/issues/index.md): Explore the best of GitLab Issues' features.
- [Merge Requests](project/merge_requests/index.md): Collaborate on code,
-reviews, live preview changes per branch, and request approvals with Merge Requests.
+ reviews, live preview changes per branch, and request approvals with Merge Requests.
- [Milestones](project/milestones/index.md): Work on multiple issues and merge
-requests towards the same target date with Milestones.
+ requests towards the same target date with Milestones.
## GitLab CI/CD
@@ -96,9 +92,9 @@ directly from GitLab. No third-party integrations needed.
- [GitLab Auto Deploy](../ci/autodeploy/index.md): Deploy your application out-of-the-box with GitLab Auto Deploy.
- [Review Apps](../ci/review_apps/index.md): Live-preview the changes introduced by a merge request with Review Apps.
- [GitLab Pages](project/pages/index.md): Publish your static site directly from
-GitLab with GitLab Pages. You can build, test, and deploy any Static Site Generator with Pages.
+ GitLab with GitLab Pages. You can build, test, and deploy any Static Site Generator with Pages.
- [GitLab Container Registry](project/container_registry.md): Build and deploy Docker
-images with Container Registry.
+ images with Container Registry.
## Account
@@ -106,13 +102,13 @@ There is a lot you can customize and configure
to enjoy the best of GitLab.
- [Settings](profile/index.md): Manage your user settings to change your personal info,
-personal access tokens, authorized applications, etc.
+ personal access tokens, authorized applications, etc.
- [Authentication](../topics/authentication/index.md): Read through the authentication
-methods available in GitLab.
+ methods available in GitLab.
- [Permissions](permissions.md): Learn the different set of permissions levels for each
-user type (guest, reporter, developer, maintainer, owner).
+ user type (guest, reporter, developer, maintainer, owner).
- [Feature highlight](feature_highlight.md): Learn more about the little blue dots
-around the app that explain certain features
+ around the app that explain certain features
- [Abuse reports](abuse_reports.md): Report abuse from users to GitLab administrators
## Groups
diff --git a/doc/user/instance_statistics/convdev.md b/doc/user/instance_statistics/convdev.md
index 52b99b69a02..247be1fb392 100644
--- a/doc/user/instance_statistics/convdev.md
+++ b/doc/user/instance_statistics/convdev.md
@@ -1,27 +1,26 @@
# Conversational Development Index
-> [Introduced][ce-30469] in GitLab 9.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/30469) in GitLab 9.3.
+
+NOTE: **NOTE**
+Your GitLab instance's [usage ping](../admin_area/settings/usage_statistics.md#usage-ping-core-only) must be activated in order to use this feature.
The Conversational Development Index (ConvDev Index) gives you an overview of your entire
instance's adoption of [Concurrent DevOps](https://about.gitlab.com/concurrent-devops/)
-from planning to monitoring. It displays the usage of these GitLab features over
+from planning to monitoring.
+
+This displays the usage of these GitLab features over
the last 30 days, averaged over the number of active users in that time period. It also
provides a Lead score per feature, which is calculated based on GitLab's analysis
-of top-performing instances based on [usage ping data][ping] that GitLab has
-collected. Your score is compared to the lead score, expressed as a percentage.
-Your overall index score is an average of all your feature score percentages.
+of top-performing instances based on [usage ping data](../admin_area/settings/usage_statistics.md#usage-ping-core-only) that GitLab has
+collected. Your score is compared to the lead score of each feature and then expressed as a percentage at the bottom of said feature.
+Your overall index score is an average of all your feature score percentages - this percentage value is presented above all the of features on the page.
![ConvDev index](img/convdev_index.png)
The page also provides helpful links to articles and GitLab docs, to help you
improve your scores.
-Your GitLab instance's [usage ping][ping] must be activated in order to use this feature.
Usage ping data is aggregated on GitLab's servers for analysis. Your usage
-information is **not sent** to any other GitLab instances.
-
-If you have just started using GitLab, it may take a few weeks for data to be
+information is **not sent** to any other GitLab instances. If you have just started using GitLab, it may take a few weeks for data to be
collected before this feature is available.
-
-[ce-30469]: https://gitlab.com/gitlab-org/gitlab-ce/issues/30469
-[ping]: ../admin_area/settings/usage_statistics.md#usage-ping
diff --git a/doc/user/instance_statistics/user_cohorts.md b/doc/user/instance_statistics/user_cohorts.md
index 70d5912dc4e..e76363a6d9f 100644
--- a/doc/user/instance_statistics/user_cohorts.md
+++ b/doc/user/instance_statistics/user_cohorts.md
@@ -23,5 +23,6 @@ the month, but who have never actually had any activity in the instance.
How do we measure the activity of users? GitLab considers a user active if:
-* the user signs in
-* the user has Git activity (whether push or pull).
+- The user signs in.
+- The user has Git activity (whether push or pull).
+- The user visits pages related to Dashboards, Projects, Issues and Merge Requests ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/54947) in GitLab 11.8).
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 893658290e5..a7a87773eec 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -31,8 +31,10 @@ dependency to do so. Please see the [`github-markup` gem readme](https://github.
> As of 11.1, GitLab uses the [CommonMark Ruby Library][commonmarker] for Markdown
processing of all new issues, merge requests, comments, and other Markdown content
in the GitLab system. As of 11.3, wiki pages and Markdown files (`.md`) in the
-repositories are also processed with CommonMark. Older content in issues/comments
-are still processed using the [Redcarpet Ruby library][redcarpet].
+repositories are also processed with CommonMark. As of 11.8, the [Redcarpet
+Ruby library][redcarpet] has been removed and all issues/comments, including
+those from pre-11.1, are now processed using [CommonMark Ruby
+Library][commonmarker].
>
> The documentation website had its [markdown engine migrated from Redcarpet to Kramdown](https://gitlab.com/gitlab-com/gitlab-docs/merge_requests/108)
in October 2018.
@@ -41,11 +43,11 @@ in October 2018.
### Transitioning to CommonMark
-You may have Markdown documents in your repository that were written using some
-of the nuances of RedCarpet's version of Markdown. Since CommonMark uses a
-slightly stricter syntax, these documents may now display a little strangely
-since we've transitioned to CommonMark. Numbered lists with nested lists in
-particular can be displayed incorrectly.
+You may have older issues/merge requests or Markdown documents in your
+repository that were written using some of the nuances of RedCarpet's version
+of Markdown. Since CommonMark uses a slightly stricter syntax, these documents
+may now display a little strangely since we've transitioned to CommonMark.
+Numbered lists with nested lists in particular can be displayed incorrectly.
It is usually quite easy to fix. In the case of a nested list such as this:
@@ -65,11 +67,6 @@ simply add a space to each nested item:
In the documentation below, we try to highlight some of the differences.
-If you have a need to view a document using RedCarpet, you can add the token
-`legacy_render=1` to the end of the url, like this:
-
-https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md?legacy_render=1
-
If you have a large volume of Markdown files, it can be tedious to determine
if they will be displayed correctly or not. You can use the
[diff_redcarpet_cmark](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark)
@@ -291,7 +288,6 @@ On Linux, you can download [Noto Color Emoji](https://www.google.com/get/noto/he
Ubuntu 18.04 (like many modern Linux distros) has this font installed by default.
```
-
Sometimes you want to <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/monkey.png" width="20px" height="20px"> around a bit and add some <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/star2.png" width="20px" height="20px"> to your <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/speech_balloon.png" width="20px" height="20px">. Well we have a gift for you:
<img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/zap.png" width="20px" height="20px">You can use emoji anywhere GFM is supported. <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/v.png" width="20px" height="20px">
@@ -300,7 +296,7 @@ You can use it to point out a <img src="https://gitlab.com/gitlab-org/gitlab-ce/
If you are new to this, don't be <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/fearful.png" width="20px" height="20px">. You can easily join the emoji <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/family.png" width="20px" height="20px">. All you need to do is to look up one of the supported codes.
-Consult the [Emoji Cheat Sheet](https://www.emojicopy.com) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/thumbsup.png" width="20px" height="20px">
+Consult the [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/thumbsup.png" width="20px" height="20px">
Most emoji are natively supported on macOS, Windows, iOS, Android and will fallback to image-based emoji where there is lack of support.
@@ -456,14 +452,14 @@ Color written inside backticks will be followed by a color "chip".
Examples:
- `#F00`
- `#F00A`
- `#FF0000`
- `#FF0000AA`
- `RGB(0,255,0)`
- `RGB(0%,100%,0%)`
- `RGBA(0,255,0,0.7)`
- `HSL(540,70%,50%)`
+ `#F00`
+ `#F00A`
+ `#FF0000`
+ `#FF0000AA`
+ `RGB(0,255,0)`
+ `RGB(0%,100%,0%)`
+ `RGBA(0,255,0,0.7)`
+ `HSL(540,70%,50%)`
`HSLA(540,70%,50%,0.7)`
Becomes:
@@ -677,7 +673,7 @@ Becomes:
+ Or pluses
If a list item contains multiple paragraphs,
-each subsequent paragraph should be indented to the same level as the start of the list item text (_Redcarpet: paragraph should be indented with four spaces._)
+each subsequent paragraph should be indented to the same level as the start of the list item text
Example:
@@ -841,7 +837,7 @@ These details <em>will</em> remain <strong>hidden</strong> until expanded.
</details>
</p>
-**Note:** Markdown inside these tags is supported, as long as you have a blank line after the `</summary>` tag and before the `</details>` tag, as shown in the example. _Redcarpet does not support Markdown inside these tags. You can work around this by using HTML, for example you can use `<pre><code>` tags instead of [code fences](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#code-and-syntax-highlighting)._
+**Note:** Markdown inside these tags is supported, as long as you have a blank line after the `</summary>` tag and before the `</details>` tag, as shown in the example.
```html
<details>
@@ -990,7 +986,6 @@ while the equation for the theory of relativity is E = mc<sup>2</sup>.
The formula for water is H<sub>2</sub>O while the equation for the theory of relativity is E = mc<sup>2</sup>.
-
## Wiki-specific Markdown
The following examples show how links inside wikis behave.
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index ed00f86f9de..833b9b66102 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -14,7 +14,7 @@ be able to create issues, leave comments, and clone or download the project code
When a member leaves the team all the assigned [Issues](project/issues/index.md) and [Merge Requests](project/merge_requests/index.md)
will be unassigned automatically.
-GitLab [administrators](../README.md#administrator-documentation) receive all permissions.
+GitLab [administrators](../administration/index.md) receive all permissions.
To add or import a user, you can follow the
[project members documentation](../user/project/members/index.md).
@@ -44,6 +44,7 @@ The following table depicts the various user permission levels in a project.
| View wiki pages | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| View license management reports **[ULTIMATE]** | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| View Security reports **[ULTIMATE]** | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
+| View project code | [^1] | ✓ | ✓ | ✓ | ✓ |
| Pull project code | [^1] | ✓ | ✓ | ✓ | ✓ |
| Download project | [^1] | ✓ | ✓ | ✓ | ✓ |
| Assign issues | | ✓ | ✓ | ✓ | ✓ |
@@ -60,6 +61,9 @@ The following table depicts the various user permission levels in a project.
| Manage related issues **[STARTER]** | | ✓ | ✓ | ✓ | ✓ |
| Lock issue discussions | | ✓ | ✓ | ✓ | ✓ |
| Create issue from vulnerability **[ULTIMATE]** | | ✓ | ✓ | ✓ | ✓ |
+| View Error Tracking list | | ✓ | ✓ | ✓ | ✓ |
+| Pull from [Maven repository](https://docs.gitlab.com/ee/user/project/packages/maven_repository.html) or [NPM registry](https://docs.gitlab.com/ee/user/project/packages/npm_registry.html) **[PREMIUM]** | | ✓ | ✓ | ✓ | ✓ |
+| Publish to [Maven repository](https://docs.gitlab.com/ee/user/project/packages/maven_repository.html) or [NPM registry](https://docs.gitlab.com/ee/user/project/packages/npm_registry.html) **[PREMIUM]** | | | ✓ | ✓ | ✓ |
| Lock merge request discussions | | | ✓ | ✓ | ✓ |
| Create new environments | | | ✓ | ✓ | ✓ |
| Stop environments | | | ✓ | ✓ | ✓ |
@@ -95,19 +99,20 @@ The following table depicts the various user permission levels in a project.
| Manage variables | | | | ✓ | ✓ |
| Manage GitLab Pages | | | | ✓ | ✓ |
| Manage GitLab Pages domains and certificates | | | | ✓ | ✓ |
-| Remove GitLab Pages | | | | | ✓ |
+| Remove GitLab Pages | | | | ✓ | ✓ |
| View GitLab Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control-core-only) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Manage clusters | | | | ✓ | ✓ |
| Manage license policy **[ULTIMATE]** | | | | ✓ | ✓ |
| Edit comments (posted by any user) | | | | ✓ | ✓ |
+| Manage Error Tracking | | | | ✓ | ✓ |
| Switch visibility level | | | | | ✓ |
| Transfer project to another namespace | | | | | ✓ |
| Remove project | | | | | ✓ |
| Delete issues | | | | | ✓ |
-| Remove pages | | | | | ✓ |
| Force push to protected branches [^4] | | | | | |
| Remove protected branches [^4] | | | | | |
| View project Audit Events | | | | ✓ | ✓ |
+| View project statistics | | | | ✓ | ✓ |
## Project features permissions
@@ -158,6 +163,13 @@ Confidential issues can be accessed by reporters and higher permission levels,
as well as by guest users that create a confidential issue. To learn more,
read through the documentation on [permissions and access to confidential issues](project/issues/confidential_issues.md#permissions-and-access-to-confidential-issues).
+### Releases permissions
+
+[Project Releases](project/releases/index.md) can be read by all project
+members (Reporters, Developers, Maintainers, Owners) **except Guests**.
+Releases can be created, updated, or deleted via [Releases APIs](../api/releases/index.md)
+by project Developers, Maintainers, and Owners.
+
## Group members permissions
NOTE: **Note:**
@@ -172,14 +184,12 @@ group.
| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ |
| Edit group | | | | | ✓ |
| Create subgroup | | | | | ✓ |
-| Create project in group | | | | ✓ | ✓ |
+| Create project in group | | | ✓ | ✓ | ✓ |
| Manage group members | | | | | ✓ |
| Remove group | | | | | ✓ |
| Manage group labels | | ✓ | ✓ | ✓ | ✓ |
| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ |
-| View private group epic **[ULTIMATE]** | | ✓ | ✓ | ✓ | ✓ |
-| View internal group epic **[ULTIMATE]** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View public group epic **[ULTIMATE]** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View group epic **[ULTIMATE]** | ✓ | ✓ | ✓ | ✓ | ✓ |
| Create/edit group epic **[ULTIMATE]** | | ✓ | ✓ | ✓ | ✓ |
| Delete group epic **[ULTIMATE]** | | | | | ✓ |
| View group Audit Events | | | | | ✓ |
diff --git a/doc/user/profile/account/index.md b/doc/user/profile/account/index.md
index 06667bfc5f1..56b6498e16c 100644
--- a/doc/user/profile/account/index.md
+++ b/doc/user/profile/account/index.md
@@ -1,2 +1,5 @@
+---
+redirect_to: '../index.md#profile-settings'
+---
This document was moved to [../index.md#profile-settings](../index.md#profile-settings).
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 76f7e869ff7..8e5fe4b0fb9 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -18,7 +18,7 @@ the second factor of authentication. Once enabled, in addition to supplying your
password to login, you'll be prompted to activate your U2F device (usually by pressing
a button on it), and it will perform secure authentication on your behalf.
-The U2F workflow is only supported by Google Chrome at this point, so we _strongly_ recommend
+The U2F workflow is only [supported by](https://caniuse.com/#search=U2F) Google Chrome, Opera and Firefox at this point, so we _strongly_ recommend
that you set up both methods of two-factor authentication, so you can still access your account
from other browsers.
@@ -41,10 +41,10 @@ or a U2F device.
**On your phone:**
1. Install a compatible application. We recommend [Google Authenticator]
-\(proprietary\) or [FreeOTP] \(open source\).
+ \(proprietary\) or [FreeOTP] \(open source\).
1. In the application, add a new entry in one of two ways:
- * Scan the code with your phone's camera to add the entry automatically.
- * Enter the details provided to add the entry manually.
+ - Scan the code with your phone's camera to add the entry automatically.
+ - Enter the details provided to add the entry manually.
**In GitLab:**
@@ -106,7 +106,7 @@ Enter the pin from your one time password authenticator's application or a recov
### Log in via U2F device
-1. Click **Login via U2F Device**
+1. Click **Login via U2F Device**.
1. A light will start blinking on your device. Activate it by pressing its button.
You will see a message indicating that your device responded to the authentication request.
@@ -135,9 +135,9 @@ authenticate with Git over HTTPS on the command line or when using
To disable two-factor authentication on your account (for example, if you
have lost your code generation device) you can:
-* [Use a saved recovery code](#use-a-saved-recovery-code)
-* [Generate new recovery codes using SSH](#generate-new-recovery-codes-using-ssh)
-* [Ask a GitLab administrator to disable two-factor authentication on your account](#ask-a-gitlab-administrator-to-disable-two-factor-authentication-on-your-account)
+- [Use a saved recovery code](#use-a-saved-recovery-code).
+- [Generate new recovery codes using SSH](#generate-new-recovery-codes-using-ssh).
+- [Ask a GitLab administrator to disable two-factor authentication on your account](#ask-a-gitlab-administrator-to-disable-two-factor-authentication-on-your-account).
### Use a saved recovery code
diff --git a/doc/user/profile/active_sessions.md b/doc/user/profile/active_sessions.md
index 5119c0e30d0..28e3f4904a9 100644
--- a/doc/user/profile/active_sessions.md
+++ b/doc/user/profile/active_sessions.md
@@ -4,7 +4,7 @@
> in GitLab 10.8.
GitLab lists all devices that have logged into your account. This allows you to
-review the sessions and revoke any of it that you don't recognize.
+review the sessions.
## Listing all active sessions
@@ -12,9 +12,3 @@ review the sessions and revoke any of it that you don't recognize.
1. Navigate to the **Active Sessions** tab.
![Active sessions list](img/active_sessions_list.png)
-
-## Revoking a session
-
-1. Navigate to your [profile's](#profile-settings) **Settings > Active Sessions**.
-1. Click on **Revoke** besides a session. The current session cannot be
- revoked, as this would sign you out of GitLab.
diff --git a/doc/user/profile/img/active_sessions_list.png b/doc/user/profile/img/active_sessions_list.png
index 5d94dca69cc..1e242ac4710 100644
--- a/doc/user/profile/img/active_sessions_list.png
+++ b/doc/user/profile/img/active_sessions_list.png
Binary files differ
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index 2f989a26725..b216b9f255c 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -35,13 +35,13 @@ From there, you can:
- Manage [2FA](account/two_factor_authentication.md)
- Change your username and [delete your account](account/delete_account.md)
- Manage applications that can
-[use GitLab as an OAuth provider](../../integration/oauth_provider.md#introduction-to-oauth)
+ [use GitLab as an OAuth provider](../../integration/oauth_provider.md#introduction-to-oauth)
- Manage [personal access tokens](personal_access_tokens.md) to access your account via API and authorized applications
- Add and delete emails linked to your account
- Choose which email to use for notifications, web-based commits, and display on your public profile
-- Manage [SSH keys](../../ssh/README.md#ssh) to access your account via SSH
+- Manage [SSH keys](../../ssh/README.md) to access your account via SSH
- Manage your [preferences](preferences.md#syntax-highlighting-theme)
-to customize your own GitLab experience
+ to customize your own GitLab experience
- [View your active sessions](active_sessions.md) and revoke any of them if necessary
- Access your audit log, a security log of important events involving your account
@@ -73,7 +73,7 @@ which also covers the case where you have projects hosted with
## Private profile
-The following information will be hidden from the user profile page (https://gitlab.example.com/username) if this feature is enabled:
+The following information will be hidden from the user profile page (`https://gitlab.example.com/username`) if this feature is enabled:
- Atom feed
- Date when account is created
@@ -89,7 +89,6 @@ To enable private profile:
1. Check the "Private profile" option.
1. Hit **Update profile settings**.
-
NOTE: **Note:**
You and GitLab admins can see your the abovementioned information on your profile even if it is private.
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index eb2d731343e..f399dc40164 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -57,7 +57,10 @@ and default views of your dashboard and the projects' landing pages.
### Layout width
GitLab can be set up to use different widths depending on your liking. Choose
-between the fixed (max. 1200px) and the fluid (100%) application layout.
+between the fixed (max. `1280px`) and the fluid (`100%`) application layout.
+
+NOTE: **Note:**
+While `1280px` is the standard max width when using fixed layout, some pages still use 100% width, depending on the content.
### Default dashboard
@@ -87,3 +90,23 @@ You can choose between 3 options:
- Files and Readme (default)
- Readme
- Activity
+
+## Localization
+
+### Language
+
+Select your preferred language from a list of supported languages.
+
+*This feature is experimental and translations are not complete yet.*
+
+### First day of the week
+
+The first day of the week can be customised for calendar views and date pickers.
+
+You can choose one of the following options as the first day of the week:
+
+- Saturday
+- Sunday
+- Monday
+
+If you select **System Default**, the system-wide default setting will be used.
diff --git a/doc/user/project/builds/artifacts.md b/doc/user/project/builds/artifacts.md
index 514c729b37d..1b0f3f61394 100644
--- a/doc/user/project/builds/artifacts.md
+++ b/doc/user/project/builds/artifacts.md
@@ -1 +1,5 @@
+---
+redirect_to: '../pipelines/job_artifacts.md'
+---
+
This document was moved to [pipelines/job_artifacts](../pipelines/job_artifacts.md).
diff --git a/doc/user/project/clusters/eks_and_gitlab/index.md b/doc/user/project/clusters/eks_and_gitlab/index.md
index 0e6d4bce153..ea09f9f1547 100644
--- a/doc/user/project/clusters/eks_and_gitlab/index.md
+++ b/doc/user/project/clusters/eks_and_gitlab/index.md
@@ -253,7 +253,7 @@ With RBAC disabled and services deployed,
[Auto DevOps](../../../../topics/autodevops/index.md) can now be leveraged
to build, test, and deploy the app.
-[Enable Auto DevOps](../../../../topics/autodevops/index.md##enablingdisabling-auto-devops-at-the-project-level)
+[Enable Auto DevOps](../../../../topics/autodevops/index.md#enablingdisabling-auto-devops-at-the-project-level)
if not already enabled. If a wildcard DNS entry was created resolving to the
Load Balancer, enter it in the `domain` field under the Auto DevOps settings.
Otherwise, the deployed app will not be externally available outside of the cluster.
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 6bdafc60949..6e64053a6ca 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -41,7 +41,7 @@ integration, make sure the following requirements are met:
- A [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account)
is set up and you have permissions to access it.
-- The Kubernetes Engine API is enabled. Follow the steps as outlined in the
+- The Kubernetes Engine API and related service are 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).
### Creating the cluster
@@ -60,7 +60,7 @@ new Kubernetes cluster to your project:
**Sign in with Google** button.
1. From there on, choose your cluster's settings:
- **Kubernetes cluster name** - The name you wish to give the cluster.
- - **Environment scope** - The [associated environment](#setting-the-environment-scope) to this cluster.
+ - **Environment scope** - The [associated environment](#setting-the-environment-scope-premium) to this cluster.
- **Google Cloud Platform project** - Choose the project you created in your GCP
console that will host the Kubernetes cluster. Learn more about
[Google Cloud Platform projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
@@ -69,6 +69,7 @@ new Kubernetes cluster to your project:
- **Number of nodes** - Enter the number of nodes you wish the cluster to have.
- **Machine type** - The [machine type](https://cloud.google.com/compute/docs/machine-types)
of the Virtual Machine instance that the cluster will be based on.
+ - **RBAC-enabled cluster** - Leave this checked if using default GKE creation options, see the [RBAC section](#role-based-access-control-rbac-core-only) for more information.
1. Finally, click the **Create Kubernetes cluster** button.
After a couple of minutes, your cluster will be ready to go. You can now proceed
@@ -86,15 +87,20 @@ To add an existing Kubernetes cluster to your project:
1. Click **Add Kubernetes cluster**.
1. Click **Add an existing Kubernetes cluster** and fill in the details:
- **Kubernetes cluster name** (required) - The name you wish to give the cluster.
- - **Environment scope** (required)- The
- [associated environment](#setting-the-environment-scope) to this cluster.
+ - **Environment scope** (required) - The
+ [associated environment](#setting-the-environment-scope-premium) to this cluster.
- **API URL** (required) -
It's the URL that GitLab uses to access the Kubernetes API. Kubernetes
exposes several APIs, we want the "base" URL that is common to all of them,
e.g., `https://kubernetes.example.com` rather than `https://kubernetes.example.com/api/v1`.
- - **CA certificate** (optional) -
- If the API is using a self-signed TLS certificate, you'll also need to include
- the `ca.crt` contents here.
+ - **CA certificate** (required) - A valid Kubernetes certificate is needed to authenticate to the EKS cluster. We will use the certificate created by default.
+ - List the secrets with `kubectl get secrets`, and one should named similar to
+ `default-token-xxxxx`. Copy that token name for use below.
+ - Get the certificate by running this command:
+
+ ```sh
+ kubectl get secret <secret name> -o jsonpath="{['data']['ca\.crt']}" | base64 --decode
+ ```
- **Token** -
GitLab authenticates against Kubernetes using service tokens, which are
scoped to a particular `namespace`.
@@ -102,36 +108,81 @@ To add an existing Kubernetes cluster to your project:
[`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
privileges.** To create this service account:
- 1. Create a `gitlab` service account in the `default` namespace:
+ 1. Create a file called `gitlab-admin-service-account.yaml` with contents:
- ```bash
- kubectl create -f - <<EOF
- apiVersion: v1
- kind: ServiceAccount
- metadata:
- name: gitlab
- namespace: default
- EOF
+ ```yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: gitlab-admin
+ namespace: kube-system
```
- 1. Create a cluster role binding to give the `gitlab` service account
- `cluster-admin` privileges:
+
+ 2. Apply the service account to your cluster:
```bash
- kubectl create -f - <<EOF
+ kubectl apply -f gitlab-admin-service-account.yaml
+ ```
+
+ Output:
+
+ ```bash
+ serviceaccount "gitlab-admin" created
+ ```
+
+ 3. Create a file called `gitlab-admin-cluster-role-binding.yaml` with contents:
+
+ ```yaml
+ apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
- apiVersion: rbac.authorization.k8s.io/v1
metadata:
- name: gitlab-cluster-admin
- subjects:
- - kind: ServiceAccount
- name: gitlab
- namespace: default
+ name: gitlab-admin
roleRef:
+ apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
- apiGroup: rbac.authorization.k8s.io
- EOF
+ subjects:
+ - kind: ServiceAccount
+ name: gitlab-admin
+ namespace: kube-system
+ ```
+
+ 4. Apply the cluster role binding to your cluster:
+
+ ```bash
+ kubectl apply -f gitlab-admin-cluster-role-binding.yaml
+ ```
+
+ Output:
+
+ ```bash
+ clusterrolebinding "gitlab-admin" created
+ ```
+
+ 5. Retrieve the token for the `gitlab-admin` service account:
+
+ ```bash
+ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep gitlab-admin | awk '{print $1}')
```
+
+ Copy the `<authentication_token>` value from the output:
+
+ ```yaml
+ Name: gitlab-admin-token-b5zv4
+ Namespace: kube-system
+ Labels: <none>
+ Annotations: kubernetes.io/service-account.name=gitlab-admin
+ kubernetes.io/service-account.uid=bcfe66ac-39be-11e8-97e8-026dce96b6e8
+
+ Type: kubernetes.io/service-account-token
+
+ Data
+ ====
+ ca.crt: 1025 bytes
+ namespace: 11 bytes
+ token: <authentication_token>
+ ```
+
NOTE: **Note:**
For GKE clusters, you will need the
`container.clusterRoleBindings.create` permission to create a cluster
@@ -172,14 +223,35 @@ functionalities needed to successfully build and deploy a containerized
application. Bear in mind that the same credentials are used for all the
applications running on the cluster.
+## Base domain
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24580) in GitLab 11.8.
+
+NOTE: **Note:**
+You do not need to specify a base domain on cluster settings when using GitLab Serverless. The domain in that case
+will be specified as part of the Knative installation. See [Installing Applications](#installing-applications).
+
+Specifying a base domain will automatically set `KUBE_INGRESS_BASE_DOMAIN` as an environment variable.
+If you are using [Auto DevOps](../../../topics/autodevops/index.md), this domain will be used for the different
+stages. For example, Auto Review Apps and Auto Deploy.
+
+The domain should have a wildcard DNS configured to the Ingress IP address. After ingress has been installed (see [Installing Applications](#installing-applications)),
+you can either:
+
+- Create an `A` record that points to the Ingress IP address with your domain provider.
+- Enter a wildcard DNS address using a service such as nip.io or xip.io. For example, `192.168.1.1.xip.io`.
+
## Access controls
When creating a cluster in GitLab, you will be asked if you would like to create an
[Attribute-based access control (ABAC)](https://kubernetes.io/docs/admin/authorization/abac/) cluster, or
a [Role-based access control (RBAC)](https://kubernetes.io/docs/admin/authorization/rbac/) one.
-Whether ABAC or RBAC is enabled, GitLab will create the necessary
-service accounts and privileges in order to install and run
+NOTE: **Note:**
+[RBAC](#role-based-access-control-rbac) is recommended and the GitLab default.
+
+Whether [ABAC](#attribute-based-access-control-abac) or [RBAC](#role-based-access-control-rbac) is enabled,
+GitLab will create the necessary service accounts and privileges in order to install and run
[GitLab managed applications](#installing-applications):
- If GitLab is creating the cluster, a `gitlab` service account with
@@ -251,6 +323,12 @@ install it manually.
## Installing applications
+NOTE: **Note:**
+Before starting the installation of applications, make sure that time is synchronized
+between your GitLab server and your Kubernetes cluster. Otherwise, installation could fail
+and you may get errors like `Error: remote error: tls: bad certificate`
+in the `stdout` of pods created by GitLab in your Kubernetes cluster.
+
GitLab provides a one-click install for various applications which can
be added directly to your configured cluster. Those applications are
needed for [Review Apps](../../../ci/review_apps/index.md) and
@@ -287,6 +365,28 @@ you should be careful as GitLab cannot detect it. In this case, installing
Tiller via the applications will result in the cluster having it twice, which
can lead to confusion during deployments.
+### Upgrading applications
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24789)
+in GitLab 11.8.
+
+Users can perform a one-click upgrade for the GitLab Runner application,
+when there is an upgrade available.
+
+To upgrade the GitLab Runner application:
+
+1. Navigate to your project's **Operations > Kubernetes**.
+1. Select your cluster.
+1. Click the **Upgrade** button for the Runnner application.
+
+The **Upgrade** button will not be shown if there is no upgrade
+available.
+
+NOTE: **Note:**
+Upgrades will reset values back to the values built into the `runner`
+chart plus the values set by
+[`values.yaml`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/vendor/runner/values.yaml)
+
## Getting the external IP address
NOTE: **Note:**
@@ -373,7 +473,7 @@ project. That way you can have different clusters for different environments,
like dev, staging, production, etc.
Simply add another cluster, like you did the first time, and make sure to
-[set an environment scope](#setting-the-environment-scope) that will
+[set an environment scope](#setting-the-environment-scope-premium) that will
differentiate the new cluster with the rest.
## Setting the environment scope **[PREMIUM]**
@@ -446,6 +546,7 @@ GitLab CI/CD build environment.
| `KUBE_CA_PEM_FILE` | Path to a file containing PEM data. Only present if a custom CA bundle was specified. |
| `KUBE_CA_PEM` | (**deprecated**) Raw PEM data. Only if a custom CA bundle was specified. |
| `KUBECONFIG` | Path to a file containing `kubeconfig` for this deployment. CA bundle would be embedded if specified. This config also embeds the same token defined in `KUBE_TOKEN` so you likely will only need this variable. This variable name is also automatically picked up by `kubectl` so you won't actually need to reference it explicitly if using `kubectl`. |
+| `KUBE_INGRESS_BASE_DOMAIN` | From GitLab 11.8, this variable can be used to set a domain per cluster. See [cluster domains](#base-domain) for more information. | 
NOTE: **NOTE:**
Prior to GitLab 11.5, `KUBE_TOKEN` was the Kubernetes token of the main
diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md
index e1b8dc07b50..54c475a1762 100644
--- a/doc/user/project/clusters/runbooks/index.md
+++ b/doc/user/project/clusters/runbooks/index.md
@@ -4,6 +4,10 @@ Runbooks are a collection of documented procedures that explain how to
carry out a particular process, be it starting, stopping, debugging,
or troubleshooting a particular system.
+Using [Jupyter Notebooks](https://jupyter.org/) and the [Rubix library](https://github.com/Nurtch/rubix),
+users can get started writing their own executable runbooks.
+
+
## Overview
Historically, runbooks took the form of a decision tree or a detailed
@@ -23,7 +27,7 @@ runbooks. A sample runbook is provided, showcasing common operations.
**<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
Watch this [video](https://www.youtube.com/watch?v=Q_OqHIIUPjE)
-for an overview of how this is acomplished in GitLab!**
+for an overview of how this is accomplished in GitLab!**
## Requirements
@@ -36,7 +40,7 @@ To create an executable runbook, you will need:
can run the helm CLI in a safe environment.
1. **Ingress** - Ingress can provide load balancing, SSL termination, and name-based
virtual hosting. It acts as a web proxy for your applications.
-1. **JupyterHub** - JupyterHub is a multi-user service for managing notebooks across
+1. **JupyterHub** - [JupyterHub](https://jupyterhub.readthedocs.io/) is a multi-user service for managing notebooks across
a team. Jupyter Notebooks provide a web-based interactive programming environment
used for data analysis, visualization, and machine learning.
diff --git a/doc/user/project/clusters/serverless/img/dns-entry.png b/doc/user/project/clusters/serverless/img/dns-entry.png
index 678743f256e..351e40b77d5 100644
--- a/doc/user/project/clusters/serverless/img/dns-entry.png
+++ b/doc/user/project/clusters/serverless/img/dns-entry.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/install-knative.png b/doc/user/project/clusters/serverless/img/install-knative.png
index 93b1cbe602f..ecc2f8fb481 100644
--- a/doc/user/project/clusters/serverless/img/install-knative.png
+++ b/doc/user/project/clusters/serverless/img/install-knative.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/serverless-page.png b/doc/user/project/clusters/serverless/img/serverless-page.png
index 960d6e736d6..a872fda7740 100644
--- a/doc/user/project/clusters/serverless/img/serverless-page.png
+++ b/doc/user/project/clusters/serverless/img/serverless-page.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index a423212a879..856ae03f4bc 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -1,7 +1,9 @@
# Serverless
> Introduced in GitLab 11.5.
-> Serverless is currently in [alpha](https://about.gitlab.com/handbook/product/#alpha).
+
+CAUTION: **Caution:**
+Serverless is currently in [alpha](https://about.gitlab.com/handbook/product/#alpha).
Run serverless workloads on Kubernetes using [Knative](https://cloud.google.com/knative/).
@@ -17,14 +19,23 @@ For more information on Knative, visit the [Knative docs repo](https://github.co
With GitLab serverless, you can deploy both functions-as-a-service (FaaS) and serverless applications.
-## Requirements
+## Prerequisites
To run Knative on Gitlab, you will need:
+1. **Existing GitLab project:** You will need a GitLab project to associate all resources. The simplest way to get started:
+
+ - If you are planning on deploying functions, clone the [functions example project](https://gitlab.com/knative-examples/functions) to get started.
+ - If you are planning on deploying a serverless application, clone the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) to get started.
+
1. **Kubernetes Cluster:** An RBAC-enabled Kubernetes cluster is required to deploy Knative.
The simplest way to get started is to add a cluster using [GitLab's GKE integration](../index.md#adding-and-creating-a-new-gke-cluster-via-gitlab).
+ The set of minimum recommended cluster specifications to run Knative is 3 nodes, 6 vCPUs, and 22.50 GB memory.
1. **Helm Tiller:** Helm is a package manager for Kubernetes and is required to install
Knative.
+1. **GitLab Runner:** A runner is required to run the CI jobs that will deploy serverless
+ applications or functions onto your cluster. You can install the GitLab Runner
+ onto the existing Kubernetes cluster. See [Installing Applications](../index.md#installing-applications) for more information.
1. **Domain Name:** Knative will provide its own load balancer using Istio. It will provide an
external IP address for all the applications served by Knative. You will be prompted to enter a
wildcard domain where your applications will be served. Configure your DNS server to use the
@@ -32,25 +43,27 @@ To run Knative on Gitlab, you will need:
1. **`.gitlab-ci.yml`:** GitLab uses [Kaniko](https://github.com/GoogleContainerTools/kaniko)
to build the application and the [TriggerMesh CLI](https://github.com/triggermesh/tm) to simplify the
deployment of knative services and functions.
-1. **`serverless.yaml`** (for [functions only](#deploying-functions)): When using serverless to deploy functions, the `serverless.yaml` file
+1. **`serverless.yml`** (for [functions only](#deploying-functions)): When using serverless to deploy functions, the `serverless.yml` file
will contain the information for all the functions being hosted in the repository as well as a reference to the
runtime being used.
1. **`Dockerfile`** (for [applications only](#deploying-serverless-applications): Knative requires a `Dockerfile` in order to build your application. It should be included
at the root of your project's repo and expose port `8080`.
+1. **Prometheus** (optional): Installing Prometheus allows you to monitor the scale and traffic of your serverless function/application.
+ See [Installing Applications](../index.md#installing-applications) for more information.
## Installing Knative via GitLab's Kubernetes integration
NOTE: **Note:**
The minimum recommended cluster size to run Knative is 3-nodes, 6 vCPUs, and 22.50 GB memory. **RBAC must be enabled.**
-1. [Add a Kubernetes cluster](../index.md) and install Helm.
-1. Once Helm has been successfully installed, on the Knative app section, enter the domain to be used with
- your application and click "Install".
+1. [Add a Kubernetes cluster](../index.md) and [install Helm](../index.md#installing-applications).
+1. Once Helm has been successfully installed, scroll down to the Knative app section. Enter the domain to be used with
+ your application/functions (e.g. `example.com`) and click **Install**.
![install-knative](img/install-knative.png)
1. After the Knative installation has finished, you can wait for the IP address to be displayed in the
- **Knative IP Address** field or retrieve the Istio Ingress IP address by running the following command:
+ **Knative IP Address** field (takes up to 5 minutes) or retrieve the Istio Ingress IP address by running the following command:
```bash
kubectl get svc --namespace=istio-system knative-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
@@ -62,14 +75,23 @@ The minimum recommended cluster size to run Knative is 3-nodes, 6 vCPUs, and 22.
35.161.143.124 my-machine-name:~ my-user$
```
+ NOTE: **Note:**
+ Running `kubectl` commands on your cluster requires setting up access to the cluster first.
+ For clusters created on GKE, see [GKE Cluster Access](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl),
+ for other platforms [Install kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
+
1. The ingress is now available at this address and will route incoming requests to the proper service based on the DNS
name in the request. To support this, a wildcard DNS A record should be created for the desired domain name. For example,
- if your Knative base domain is `knative.info` then you need to create an A record with domain `*.knative.info`
+ if your Knative base domain is `example.com` then you need to create an A record with domain `*.example.com`
pointing the ip address of the ingress.
![dns entry](img/dns-entry.png)
-## Deploying Functions
+NOTE: **Note:**
+You can deploy either [functions](#deploying-functions) or [serverless applications](#deploying-serverless-applications)
+on a given project but not both. The current implementation makes use of a `serverless.yml` file to signal a FaaS project.
+
+## Deploying functions
> Introduced in GitLab 11.6.
@@ -82,31 +104,45 @@ Currently the following [runtimes](https://gitlab.com/triggermesh/runtimes) are
- node.js
- kaniko
-In order to deploy functions to your Knative instance, the following files must be present:
+You can find and import all the files referenced in this doc in the **[functions example project](https://gitlab.com/knative-examples/functions)**.
+
+Follow these steps to deploy a function using the Node.js runtime to your Knative instance (you can skip these steps if you've cloned the example project):
+
+1. Create a directory that will house the function. In this example we will create a directory called `echo` at the root of the project.
+
+1. Create the file that will contain the function code. In this example, our file is called `echo.js` and is located inside the `echo` directory. If your project is:
+ - Public, continue to the next step.
+ - Private, you will need to [create a GitLab deploy token](../../deploy_tokens/index.md#creating-a-deploy-token) with `gitlab-deploy-token` as the name and the `read_registry` scope.
-1. `.gitlab-ci.yml`: This template allows to define the stage, environment, and
- image to be used for your functions. It must be included at the root of your repository:
+1. `.gitlab-ci.yml`: this defines a pipeline used to deploy your functions.
+ It must be included at the root of your repository:
```yaml
- stages:
- - deploy
+ include:
+ template: Serverless.gitlab-ci.yml
functions:
- stage: deploy
- environment: test
- image: gcr.io/triggermesh/tm:v0.0.7
- script:
- - tm -n "$KUBE_NAMESPACE" set registry-auth gitlab-registry --registry "$CI_REGISTRY" --username "$CI_REGISTRY_USER" --password "$CI_JOB_TOKEN"
- - tm -n "$KUBE_NAMESPACE" --registry-host "$CI_REGISTRY_IMAGE" deploy --wait
+ extends: .serverless:deploy:functions
+ environment: production
```
- The `gitlab-ci.yml` template creates a `Deploy` stage with a `functions` job that invokes the `tm` CLI with the required parameters.
+ This `.gitlab-ci.yml` creates a `functions` job that invokes some
+ predefined commands to deploy your functions to your cluster.
-2. `serverless.yaml`: This file contains the metadata for your functions,
- such as name, runtime, and environment. It must be included at the root of your repository. The following is a sample `echo` function which shows the required structure for the file.
+ `Serverless.gitlab-ci.yml` is a template that allows customization.
+ You can either import it with `include` parameter and use `extends` to
+ customize your jobs, or you can inline the entire template by choosing it
+ from **Apply a template** dropdown when editing the `.gitlab-ci.yml` file through
+ the user interface.
- NOTE: **Note:**
- The file extension for the `serverless.yaml` file must be specified as `.yaml` in order to the file to be parsed properly. Specifying the extension as `.yml` will not work.
+2. `serverless.yml`: this file contains the metadata for your functions,
+ such as name, runtime, and environment.
+
+ It must be included at the root of your repository.
+ The following is a sample `echo` function which shows the required structure
+ for the file.
+
+ You can find the relevant files for this project in the [functions example project](https://gitlab.com/knative-examples/functions).
```yaml
service: my-functions
@@ -124,13 +160,14 @@ In order to deploy functions to your Knative instance, the following files must
runtime: https://gitlab.com/triggermesh/runtimes/raw/master/nodejs.yaml
description: "echo function using node.js runtime"
buildargs:
- - DIRECTORY=echo
- environment:
- FUNCTION: echo
+ - DIRECTORY=echo
+ environment:
+ FUNCTION: echo
```
-
-The `serverless.yaml` file contains three sections with distinct parameters:
+The `serverless.yml` file references both an `echo` directory (under `buildargs`) and an `echo` file (under `handler`),
+which is a reference to `echo.js` in the [repository](https://gitlab.com/knative-examples/functions). Additionally, it
+contains three sections with distinct parameters:
### `service`
@@ -139,19 +176,17 @@ The `serverless.yaml` file contains three sections with distinct parameters:
| `service` | Name for the Knative service which will serve the function. |
| `description` | A short description of the `service`. |
-
### `provider`
| Parameter | Description |
|-----------|-------------|
-| `name` | Indicates which provider is used to execute the `serverless.yaml` file. In this case, the TriggerMesh `tm` CLI. |
+| `name` | Indicates which provider is used to execute the `serverless.yml` file. In this case, the TriggerMesh `tm` CLI. |
| `registry-secret` | Indicates which registry will be used to store docker images. The sample function is using the GitLab Registry (`gitlab-registry`). A different registry host may be specified using `registry` key in the `provider` object. If changing the default, update the permission and the secret value on the `gitlab-ci.yml` file |
| `environment` | Includes the environment variables to be passed as part of function execution for **all** functions in the file, where `FOO` is the variable name and `BAR` are he variable contents. You may replace this with you own variables. |
### `functions`
-In the `serverless.yaml` example above, the function name is `echo` and the subsequent lines contain the function attributes.
-
+In the `serverless.yml` example above, the function name is `echo` and the subsequent lines contain the function attributes.
| Parameter | Description |
|-----------|-------------|
@@ -161,19 +196,18 @@ In the `serverless.yaml` example above, the function name is `echo` and the subs
| `buildargs` | Pointer to the function file in the repo. In the sample the function is located in the `echo` directory. |
| `environment` | Sets an environment variable for the specific function only. |
-After the `gitlab-ci.yml` template has been added and the `serverless.yaml` file has been
-created, each function must be defined as a single file in your repository. Committing a
-function to your project will result in a
+After the `gitlab-ci.yml` template has been added and the `serverless.yml` file has been
+created, pushing a commit to your project will result in a
CI pipeline being executed which will deploy each function as a Knative service.
Once the deploy stage has finished, additional details for the function will
appear under **Operations > Serverless**.
![serverless page](img/serverless-page.png)
-This page contains all functions available for the project, the URL for
-accessing the function, and if available, the function's runtime information.
+This page contains all functions available for the project, the description for
+accessing the function, and, if available, the function's runtime information.
The details are derived from the Knative installation inside each of the project's
-Kubernetes cluster.
+Kubernetes cluster. Click on each function to obtain detailed scale and invocation data.
The function details can be retrieved directly from Knative on the cluster:
@@ -181,57 +215,56 @@ The function details can be retrieved directly from Knative on the cluster:
kubectl -n "$KUBE_NAMESPACE" get services.serving.knative.dev
```
-The sample function can now be triggered from any HTTP client using a simple `POST` call.
+The sample function can now be triggered from any HTTP client using a simple `POST` call:
-![function exection](img/function-execution.png)
+ 1. Using curl (replace the URL on the last line with the URL of your application):
-Currently, the Serverless page presents all functions available in all clusters registered for the project with Knative installed.
+ ```bash
+ curl \
+ --header "Content-Type: application/json" \
+ --request POST \
+ --data '{"GitLab":"FaaS"}' \
+ <http://functions-echo.functions-1.functions.example.com/>
+ ```
+ 2. Using a web-based tool (ie. postman, restlet, etc)
+
+ ![function execution](img/function-execution.png)
## Deploying Serverless applications
> Introduced in GitLab 11.5.
NOTE: **Note:**
-You can reference the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) to get started.
+You can reference and import the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) to get started.
Add the following `.gitlab-ci.yml` to the root of your repository
-(you may skip this step if using the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) mentioned above):
+(you may skip this step if you've previously cloned the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) mentioned above):
```yaml
-stages:
- - build
- - deploy
+include:
+ template: Serverless.gitlab-ci.yml
build:
- stage: build
- image:
- name: gcr.io/kaniko-project/executor:debug
- entrypoint: [""]
- only:
- - master
- script:
- - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE
+ extends: .serverless:build:image
deploy:
- stage: deploy
- image: gcr.io/triggermesh/tm@sha256:e3ee74db94d215bd297738d93577481f3e4db38013326c90d57f873df7ab41d5
- only:
- - master
- environment: production
- script:
- - echo "$CI_REGISTRY_IMAGE"
- - tm -n "$KUBE_NAMESPACE" --config "$KUBECONFIG" deploy service "$CI_PROJECT_NAME" --from-image "$CI_REGISTRY_IMAGE" --wait
+ extends: .serverless:deploy:image
```
-## Deploy the application with Knative
+`Serverless.gitlab-ci.yml` is a template that allows customization.
+You can either import it with `include` parameter and use `extends` to
+customize your jobs, or you can inline the entire template by choosing it
+from **Apply a template** dropdown when editing the `.gitlab-ci.yml` file through
+the user interface.
+
+### Deploy the application with Knative
With all the pieces in place, the next time a CI pipeline runs, the Knative application will be deployed. Navigate to
**CI/CD > Pipelines** and click the most recent pipeline.
-## Obtain the URL for the Knative deployment
+### Obtain the URL for the Knative deployment
-Use the CI/CD deployment job output to obtain the deployment URL. Once all the stages of the pipeline finish, click the **deploy** stage.
+Go to the **CI/CD > Pipelines** and click on the pipeline that deployed your app. Once all the stages of the pipeline finish, click the **deploy** stage.
![deploy stage](img/deploy-stage.png)
@@ -253,7 +286,7 @@ registry.staging.gitlab.com/danielgruesso/knative
$ tm -n "$KUBE_NAMESPACE" --config "$KUBECONFIG" deploy service "$CI_PROJECT_NAME" --from-image "$CI_REGISTRY_IMAGE" --wait
Deployment started. Run "tm -n knative-4342902 describe service knative" to see the details
Waiting for ready state.......
-Service domain: knative.knative-4342902.knative.info
+Service domain: knative.knative-4342902.example.com
Job succeeded
```
diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md
index cac64fc0cb6..dec6eac2508 100644
--- a/doc/user/project/container_registry.md
+++ b/doc/user/project/container_registry.md
@@ -15,7 +15,7 @@
With the Docker Container Registry integrated into GitLab, every project can
have its own space to store its Docker images.
-You can read more about Docker Registry at https://docs.docker.com/registry/introduction/.
+You can read more about Docker Registry at <https://docs.docker.com/registry/introduction/>.
## Enable the Container Registry for your project
@@ -47,7 +47,6 @@ to enable it.
> - To move or rename a repository with a container registry you will have to
> delete all existing images.
-
If you visit the **Registry** link under your project's menu, you can see the
explicit instructions to login to the Container Registry using your GitLab
credentials.
@@ -283,9 +282,9 @@ In the example above, we see the following trace on the mitmproxy window:
The above image shows:
-* The initial PUT requests went through fine with a 201 status code.
-* The 201 redirected the client to the S3 bucket.
-* The HEAD request to the AWS bucket reported a 403 Unauthorized.
+- The initial PUT requests went through fine with a 201 status code.
+- The 201 redirected the client to the S3 bucket.
+- The HEAD request to the AWS bucket reported a 403 Unauthorized.
What does this mean? This strongly suggests that the S3 user does not have the right
[permissions to perform a HEAD request](http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html).
diff --git a/doc/user/project/cycle_analytics.md b/doc/user/project/cycle_analytics.md
index b98221bea61..05127b274e0 100644
--- a/doc/user/project/cycle_analytics.md
+++ b/doc/user/project/cycle_analytics.md
@@ -46,7 +46,7 @@ You can see that there are seven stages in total:
## How the data is measured
Cycle Analytics records cycle time and data based on the project issues with the
-exception of the staging and production stages, where only data deployed to
+exception of the staging and production stages, where only data deployed to
production are measured.
Specifically, if your CI is not set up and you have not defined a `production`
@@ -80,13 +80,13 @@ Here's a little explanation of how this works behind the scenes:
To sum up, anything that doesn't follow the [GitLab flow] won't be tracked at all.
So, the Cycle Analytics dashboard won't present any data:
+
- For merge requests that do not close an issue.
- For issues not labeled with a label present in the Issue Board.
- For issues not assigned a milestone.
- For staging and production stages, if the project has no `production` or `production/*`
environment.
-
## Example workflow
Below is a simple fictional workflow of a single cycle that happens in a
@@ -159,7 +159,6 @@ Learn more about Cycle Analytics in the following resources:
- [Cycle Analytics feature preview](https://about.gitlab.com/2016/09/16/feature-preview-introducing-cycle-analytics/)
- [Cycle Analytics feature highlight](https://about.gitlab.com/2016/09/21/cycle-analytics-feature-highlight/)
-
[board]: issue_board.md#creating-a-new-list
[ce-5986]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5986
[ce-20975]: https://gitlab.com/gitlab-org/gitlab-ce/issues/20975
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 7c94f4ef4d8..08647caaf07 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -93,4 +93,3 @@ Possible fixes
[ce-4981]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4981
[gitlab-ce-templates]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/.gitlab
-
diff --git a/doc/user/project/gpg_signed_commits/index.md b/doc/user/project/gpg_signed_commits/index.md
index 261eedeb412..bd9a5313489 100644
--- a/doc/user/project/gpg_signed_commits/index.md
+++ b/doc/user/project/gpg_signed_commits/index.md
@@ -1 +1,5 @@
+---
+redirect_to: '../repository/gpg_signed_commits/index.md'
+---
+
This document was moved to [another location](../repository/gpg_signed_commits/index.md).
diff --git a/doc/user/project/img/issue_boards_multiple.png b/doc/user/project/img/issue_boards_multiple.png
index 7bb088aad0b..4b1a8356dc9 100644
--- a/doc/user/project/img/issue_boards_multiple.png
+++ b/doc/user/project/img/issue_boards_multiple.png
Binary files differ
diff --git a/doc/user/project/img/releases.png b/doc/user/project/img/releases.png
deleted file mode 100644
index aec1db89a75..00000000000
--- a/doc/user/project/img/releases.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index ebf87890cfd..d51a0c0ccca 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -22,14 +22,14 @@ Import your projects from Bitbucket Server to GitLab with minimal effort.
## Limitations
1. Currently GitLab doesn't allow comments on arbitrary lines of code, so any
-Bitbucket comments out of bounds will be inserted as comments in the merge
-request.
+ Bitbucket comments out of bounds will be inserted as comments in the merge
+ request.
1. Bitbucket Server allows multiple levels of threading. GitLab
-import will collapse this into one discussion and quote part of the original
-comment.
+ import will collapse this into one discussion and quote part of the original
+ comment.
1. Declined pull requests have unreachable commits, which prevents the GitLab
-importer from generating a proper diff. These pull requests will show up as
-empty changes.
+ importer from generating a proper diff. These pull requests will show up as
+ empty changes.
1. Attachments in Markdown are currently not imported.
1. Task lists are not imported.
1. Emoji reactions are not imported
diff --git a/doc/user/project/import/fogbugz.md b/doc/user/project/import/fogbugz.md
index 17222c53675..13409c93929 100644
--- a/doc/user/project/import/fogbugz.md
+++ b/doc/user/project/import/fogbugz.md
@@ -23,6 +23,6 @@ users to GitLab users.
![Import Project](img/fogbugz_import_select_project.png)
1. Once the import has finished click the link to take you to the project
-dashboard. Follow the directions to push your existing repository.
+ dashboard. Follow the directions to push your existing repository.
![Finished](img/fogbugz_import_finished.png)
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index 42da2210fab..63b90dd76fd 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -18,16 +18,16 @@ GitHub without the constraints of a Sidekiq worker.
The following aspects of a project are imported:
- * Repository description (GitLab.com & 7.7+)
- * Git repository data (GitLab.com & 7.7+)
- * Issues (GitLab.com & 7.7+)
- * Pull requests (GitLab.com & 8.4+)
- * Wiki pages (GitLab.com & 8.4+)
- * Milestones (GitLab.com & 8.7+)
- * Labels (GitLab.com & 8.7+)
- * Release note descriptions (GitLab.com & 8.12+)
- * Pull request review comments (GitLab.com & 10.2+)
- * Regular issue and pull request comments
+- Repository description (GitLab.com & 7.7+)
+- Git repository data (GitLab.com & 7.7+)
+- Issues (GitLab.com & 7.7+)
+- Pull requests (GitLab.com & 8.4+)
+- Wiki pages (GitLab.com & 8.4+)
+- Milestones (GitLab.com & 8.7+)
+- Labels (GitLab.com & 8.7+)
+- Release note descriptions (GitLab.com & 8.12+)
+- Pull request review comments (GitLab.com & 10.2+)
+- Regular issue and pull request comments
References to pull requests and issues are preserved (GitLab.com & 8.7+), and
each imported repository maintains visibility level unless that [visibility
@@ -67,7 +67,7 @@ developer documentation.
Before you begin, ensure that any GitHub users who you want to map to GitLab users have either:
- A GitLab account that has logged in using the GitHub icon
-\- or -
+ \- or -
- A GitLab account with an email address that matches the [public email address](https://help.github.com/articles/setting-your-commit-email-address-on-github/) of the GitHub user
User-matching attempts occur in that order, and if a user is not identified either way, the activity is associated with
@@ -92,7 +92,7 @@ integration enabled, that should be the preferred method to import your reposito
If you are not using the GitHub integration, you can still perform an authorization with GitHub to grant GitLab access your repositories:
-1. Go to https://github.com/settings/tokens/new
+1. Go to <https://github.com/settings/tokens/new>
1. Enter a token description.
1. Select the repo scope.
1. Click **Generate token**.
@@ -132,8 +132,8 @@ Admin access to the GitLab server is required.
For large projects it may take a while to import all data. To reduce the time necessary, you can increase the number of
Sidekiq workers that process the following queues:
-* `github_importer`
-* `github_importer_advance_stage`
+- `github_importer`
+- `github_importer_advance_stage`
For an optimal experience, it's recommended having at least 4 Sidekiq processes (each running a number of threads equal
to the number of CPU cores) that *only* process these queues. It's also recommended that these processes run on separate
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 2f5efbe84d9..ca02e4e9e96 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -25,3 +25,10 @@ but issues and merge requests can't be imported.
If you want to retain all metadata like issues and merge requests, you can use
the [import/export feature](../settings/import_export.md).
+
+## Migrating between two self-hosted GitLab instances
+
+The best method for migrating a project from one GitLab instance to another,
+perhaps from an old server to a new server for example, is to
+[back up the project](../../../raketasks/backup_restore.md),
+then restore it on the new server.
diff --git a/doc/user/project/import/repo_by_url.md b/doc/user/project/import/repo_by_url.md
index f43e384de88..c20b1cb7f5e 100644
--- a/doc/user/project/import/repo_by_url.md
+++ b/doc/user/project/import/repo_by_url.md
@@ -6,7 +6,7 @@ You can import your existing repositories by providing the Git URL:
1. Switch to the **Import project** tab
1. Click on the **Repo by URL** button
1. Fill in the "Git repository URL" and the remaining project fields
-1. Click **Create project** to being the import process
+1. Click **Create project** to begin the import process
1. Once complete, you will be redirected to your newly created project
![Import project by repo URL](img/import_projects_from_repo_url.png)
diff --git a/doc/user/project/import/svn.md b/doc/user/project/import/svn.md
index a5923986292..4825b005a85 100644
--- a/doc/user/project/import/svn.md
+++ b/doc/user/project/import/svn.md
@@ -8,7 +8,7 @@ between the two, for more information consult your favorite search engine.
There are two approaches to SVN to Git migration:
-1. [Git/SVN Mirror](#smooth-migration-with-a-git-svn-mirror-using-subgit) which:
+1. [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which:
- Makes the GitLab repository to mirror the SVN project.
- Git and SVN repositories are kept in sync; you can use either one.
- Smoothens the migration process and allows to manage migration risks.
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index e63ed88249d..4148310dc98 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -8,7 +8,7 @@ Your projects can be [available](../../public_access/public_access.md)
publicly, internally, or privately, at your choice. GitLab does not limit
the number of private projects you create.
-## Project's features
+## Project features
When you create a project in GitLab, you'll have access to a large number of
[features](https://about.gitlab.com/features/):
@@ -19,7 +19,7 @@ When you create a project in GitLab, you'll have access to a large number of
- [Issue Boards](issue_board.md): Organize and prioritize your workflow
- [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards): Allow your teams to create their own workflows (Issue Boards) for the same project **[STARTER]**
- [Repositories](repository/index.md): Host your code in a fully
-integrated platform
+ integrated platform
- [Branches](repository/branches/index.md): use Git branching strategies to
collaborate on code
- [Protected branches](protected_branches.md): Prevent collaborators
@@ -29,7 +29,7 @@ integrated platform
- [Signing commits](gpg_signed_commits/index.md): use GPG to sign your commits
- [Deploy tokens](deploy_tokens/index.md): Manage project-based deploy tokens that allow permanent access to the repository and Container Registry.
- [Merge Requests](merge_requests/index.md): Apply your branching
-strategy and get reviewed by your team
+ strategy and get reviewed by your team
- [Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html): Ask for approval before
implementing a change **[STARTER]**
- [Fix merge conflicts from the UI](merge_requests/resolve_conflicts.md):
@@ -38,13 +38,13 @@ strategy and get reviewed by your team
of the changes proposed in a merge request in a per-branch basis
- [Labels](labels.md): Organize issues and merge requests by labels
- [Time Tracking](../../workflow/time_tracking.md): Track estimate time
-and time spent on
+ and time spent on
the conclusion of an issue or merge request
- [Milestones](milestones/index.md): Work towards a target date
- [Description templates](description_templates.md): Define context-specific
-templates for issue and merge request description fields for your project
+ templates for issue and merge request description fields for your project
- [Slash commands (quick actions)](quick_actions.md): Textual shortcuts for
-common actions on issues or merge requests
+ common actions on issues or merge requests
- [Web IDE](web_ide/index.md)
**GitLab CI/CD:**
@@ -65,21 +65,24 @@ common actions on issues or merge requests
browse, and download job artifacts
- [Pipeline settings](pipelines/settings.md): Set up Git strategy (choose the default way your repository is fetched from GitLab in a job),
timeout (defines the maximum amount of time in minutes that a job is able run), custom path for `.gitlab-ci.yml`, test coverage parsing, pipeline's visibility, and much more
- - [GKE cluster integration](clusters/index.md): Connecting your GitLab project
- with Google Kubernetes Engine
+ - [Kubernetes cluster integration](clusters/index.md): Connecting your GitLab project
+ with a Kubernetes cluster
- [GitLab Pages](pages/index.md): Build, test, and deploy your static
-website with GitLab Pages
+ website with GitLab Pages
**Other features:**
-- [Wiki](wiki/index.md): Document your GitLab project in an integrated Wiki
-- [Snippets](../snippets.md): Store, share and collaborate on code snippets
-- [Cycle Analytics](cycle_analytics.md): Review your development lifecycle
-- [Syntax highlighting](highlighting.md): An alternative to customize
-your code blocks, overriding GitLab's default choice of language
-- [Badges](badges.md): Badges for the project overview
+- [Wiki](wiki/index.md): document your GitLab project in an integrated Wiki.
+- [Snippets](../snippets.md): store, share and collaborate on code snippets.
+- [Cycle Analytics](cycle_analytics.md): review your development lifecycle.
+- [Syntax highlighting](highlighting.md): an alternative to customize
+ your code blocks, overriding GitLab's default choice of language.
+- [Badges](badges.md): badges for the project overview.
+- [Releases](releases/index.md): a way to track deliverables in your project as snapshot in time of
+ the source, build output, and other metadata or artifacts
+ associated with a released version of your code.
-### Project's integrations
+### Project integrations
[Integrate your project](integrations/index.md) with Jira, Mattermost,
Kubernetes, Slack, and a lot more.
@@ -93,7 +96,7 @@ Learn how to [create a new project](../../gitlab-basics/create-project.md) in Gi
You can [fork a project](../../gitlab-basics/fork-project.md) in order to:
- Collaborate on code by forking a project and creating a merge request
-from your fork to the upstream project
+ from your fork to the upstream project
- Fork a sample project to work on the top of that
## Project settings
@@ -113,7 +116,7 @@ Read through the documentation on [project settings](settings/index.md).
- [Export a project from GitLab](settings/import_export.md#exporting-a-project-and-its-data)
- [Importing and exporting projects between GitLab instances](settings/import_export.md)
-## Project's members
+## Project members
Learn how to [add members to your projects](members/index.md).
@@ -134,7 +137,7 @@ and Git push/pull redirects.
Depending on the situation, different things apply.
When [renaming a user](../profile/index.md#changing-your-username),
-[changing a group path](../group/index.md#changing-a-group-s-path) or [renaming a repository](settings/index.md#renaming-a-repository):
+[changing a group path](../group/index.md#changing-a-groups-path) or [renaming a repository](settings/index.md#renaming-a-repository):
- Existing web URLs for the namespace and anything under it (e.g., projects) will
redirect to the new URLs.
@@ -146,3 +149,44 @@ When [renaming a user](../profile/index.md#changing-your-username),
work after a rename, making any transition a lot smoother.
- The redirects will be available as long as the original path is not claimed by
another group, user or project.
+
+## Use your project as a Go package
+
+Any project can be used as a Go package including private projects in subgroups. To use packages
+hosted in private projects with the `go get` command, use a [`.netrc` file](https://ec.haxx.se/usingcurl-netrc.html)
+and a [personal access token](../profile/personal_access_tokens.md) in the password field.
+
+For example:
+
+```text
+machine example.gitlab.com
+login <gitlab_user_name>
+password <personal_access_token>
+```
+
+## Access project page with project ID
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/53671) in GitLab 11.8.
+
+To quickly access a project from the GitLab UI using the project ID,
+visit the `/projects/:id` URL in your browser or other tool accessing the project.
+
+## Project APIs
+
+There are numerous [APIs](../../api/README.md) to use with your projects:
+
+- [Badges](../../api/project_badges.md)
+- [Clusters](../../api/project_clusters.md)
+- [Discussions](../../api/discussions.md)
+- [General](../../api/projects.md)
+- [Import/export](../../api/project_import_export.md)
+- [Issue Board](../../api/boards.md)
+- [Labels](../../api/labels.md)
+- [Markdown](../../api/markdown.md)
+- [Merge Requests](../../api/merge_requests.md)
+- [Milestones](../../api/milestones.md)
+- [Services](../../api/services.md)
+- [Snippets](../../api/project_snippets.md)
+- [Templates](../../api/project_templates.md)
+- [Traffic](../../api/project_statistics.md)
+- [Variables](../../api/project_level_variables.md)
diff --git a/doc/user/project/integrations/bamboo.md b/doc/user/project/integrations/bamboo.md
index 70c0d434f1f..3206a39dc08 100644
--- a/doc/user/project/integrations/bamboo.md
+++ b/doc/user/project/integrations/bamboo.md
@@ -40,7 +40,7 @@ service in GitLab.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
1. Click 'Atlassian Bamboo CI'
1. Select the 'Active' checkbox.
-1. Enter the base URL of your Bamboo server. 'https://bamboo.example.com'
+1. Enter the base URL of your Bamboo server. `https://bamboo.example.com`
1. Enter the build key from your Bamboo build plan. Build keys are typically made
up from the Project Key and Plan Key that are set on project/plan creation and
separated with a dash (`-`), for example **PROJ-PLAN**. This is a short, all
@@ -59,4 +59,3 @@ Bamboo under 'Trigger IP addresses'.
> **Note:**
> - Starting with GitLab 8.14.0, builds are triggered on push events.
-
diff --git a/doc/user/project/integrations/emails_on_push.md b/doc/user/project/integrations/emails_on_push.md
index df320de7e16..61359dcaa90 100644
--- a/doc/user/project/integrations/emails_on_push.md
+++ b/doc/user/project/integrations/emails_on_push.md
@@ -10,10 +10,10 @@ In the _Recipients_ area, provide a list of emails separated by spaces or newlin
The following options are available:
-+ **Push events** - Email will be triggered when a push event is received
-+ **Tag push events** - Email will be triggered when a tag is created and pushed
-+ **Send from committer** - Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. `user@gitlab.com`).
-+ **Disable code diffs** - Don't include possibly sensitive code diffs in notification body.
+- **Push events** - Email will be triggered when a push event is received.
+- **Tag push events** - Email will be triggered when a tag is created and pushed.
+- **Send from committer** - Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. `user@gitlab.com`).
+- **Disable code diffs** - Don't include possibly sensitive code diffs in notification body.
| Settings | Notification |
| --- | --- |
diff --git a/doc/user/project/integrations/hipchat.md b/doc/user/project/integrations/hipchat.md
deleted file mode 100644
index eee779c50d4..00000000000
--- a/doc/user/project/integrations/hipchat.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Atlassian HipChat
-
-GitLab provides a way to send HipChat notifications upon a number of events,
-such as when a user pushes code, creates a branch or tag, adds a comment, and
-creates a merge request.
-
-## Setup
-
-GitLab requires the use of a HipChat v2 API token to work. v1 tokens are
-not supported at this time. Note the differences between v1 and v2 tokens:
-
-HipChat v1 API (legacy) supports "API Auth Tokens" in the Group API menu. A v1
-token is allowed to send messages to *any* room.
-
-HipChat v2 API has tokens that are can be created using the Integrations tab
-in the Group or Room admin page. By design, these are lightweight tokens that
-allow GitLab to send messages only to *one* room.
-
-### Complete these steps in HipChat
-
-1. Go to: https://admin.hipchat.com/admin
-1. Click on "Group Admin" -> "Integrations".
-1. Find "Build Your Own!" and click "Create".
-1. Select the desired room, name the integration "GitLab", and click "Create".
-1. In the "Send messages to this room by posting this URL" column, you should
-see a URL in the format:
-
-```
-https://api.hipchat.com/v2/room/<room>/notification?auth_token=<token>
-```
-
-HipChat is now ready to accept messages from GitLab. Next, set up the HipChat
-service in GitLab.
-
-### Complete these steps in GitLab
-
-1. Navigate to the project you want to configure for notifications.
-1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
-1. Click "HipChat".
-1. Select the "Active" checkbox.
-1. Insert the `token` field from the URL into the `Token` field on the Web page.
-1. Insert the `room` field from the URL into the `Room` field on the Web page.
-1. Save or optionally click "Test Settings".
-
-## Troubleshooting
-
-If you do not see notifications, make sure you are using a HipChat v2 API
-token, not a v1 token.
-
-Note that the v2 token is tied to a specific room. If you want to be able to
-specify arbitrary rooms, you can create an API token for a specific user in
-HipChat under "Account settings" and "API access". Use the `XXX` value under
-`auth_token=XXX`.
diff --git a/doc/user/project/integrations/irker.md b/doc/user/project/integrations/irker.md
index ecdd83ce8f0..4fb753d1707 100644
--- a/doc/user/project/integrations/irker.md
+++ b/doc/user/project/integrations/irker.md
@@ -4,12 +4,12 @@ GitLab provides a way to push update messages to an Irker server. When
configured, pushes to a project will trigger the service to send data directly
to the Irker server.
-See the project homepage for further info: https://gitlab.com/esr/irker
+See the project homepage for further info: <https://gitlab.com/esr/irker>
## Needed setup
You will first need an Irker daemon. You can download the Irker code from its
-repository on https://gitlab.com/esr/irker:
+repository on <https://gitlab.com/esr/irker>:
```
git clone https://gitlab.com/esr/irker.git
@@ -30,12 +30,12 @@ need to follow the firsts steps of the next section.
1. Click "Irker".
1. Select the "Active" checkbox.
1. Enter the server host address where `irkerd` runs (defaults to `localhost`)
-in the `Server host` field on the Web page
+ in the `Server host` field on the Web page
1. Enter the server port of `irkerd` (e.g. defaults to 6659) in the
-`Server port` field on the Web page.
+ `Server port` field on the Web page.
1. Optional: if `Default IRC URI` is set, it has to be in the format
-`irc[s]://domain.name` and will be prepend to each and every channel provided
-by the user which is not a full URI.
+ `irc[s]://domain.name` and will be prepend to each and every channel provided
+ by the user which is not a full URI.
1. Specify the recipients (e.g. #channel1, user1, etc.)
1. Save or optionally click "Test Settings".
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
index bc4bba40e59..754711f5919 100644
--- a/doc/user/project/integrations/jira.md
+++ b/doc/user/project/integrations/jira.md
@@ -31,7 +31,7 @@ directly from GitLab, as covered in the article
Each GitLab project can be configured to connect to an entire Jira instance. That
means one GitLab project can interact with _all_ Jira projects in that instance, once
-configured. Therefore, you will not have to explicitly associate
+configured. Therefore, you will not have to explicitly associate
a GitLab project with any single Jira project.
If you have one Jira instance, you can pre-fill the settings page with a default
@@ -46,10 +46,12 @@ project in Jira and then enter the correct values in GitLab.
### Configuring Jira
When connecting to **JIRA Server**, which supports basic authentication, a **username and password** are required. Check the link below and proceed to the next step:
-* [Setting up an user in JIRA server](jira_server_configuration.md)
+
+- [Setting up an user in JIRA server](jira_server_configuration.md)
When connecting to **JIRA Cloud**, which supports authentication via API token, an **email and API token**, are required. Check the link below and proceed to the next step:
-* [Setting up an user in JIRA cloud](jira_cloud_configuration.md)
+
+- [Setting up an user in JIRA cloud](jira_cloud_configuration.md)
### Configuring GitLab
@@ -114,11 +116,11 @@ USER mentioned this issue in RESOURCE_NAME of [PROJECT_NAME|LINK_TO_COMMENT]:
ENTITY_TITLE
```
-* `USER` A user that mentioned the issue. This is the link to the user profile in GitLab.
-* `LINK_TO_THE_COMMENT` Link to the origin of mention with a name of the entity where Jira issue was mentioned.
-* `RESOURCE_NAME` Kind of resource which referenced the issue. Can be a commit or merge request.
-* `PROJECT_NAME` GitLab project name.
-* `ENTITY_TITLE` Merge request title or commit message first line.
+- `USER` A user that mentioned the issue. This is the link to the user profile in GitLab.
+- `LINK_TO_THE_COMMENT` Link to the origin of mention with a name of the entity where Jira issue was mentioned.
+- `RESOURCE_NAME` Kind of resource which referenced the issue. Can be a commit or merge request.
+- `PROJECT_NAME` GitLab project name.
+- `ENTITY_TITLE` Merge request title or commit message first line.
![example of mentioning or closing the Jira issue](img/jira_issue_reference.png)
@@ -190,11 +192,11 @@ Make sure that the Jira issue is not already marked as resolved; that is,
the Jira issue resolution field is not set. (It should not be struck through in
Jira lists.)
-### CAPTCHA
+### CAPTCHA
-CAPTCHA may be triggered after several consecutive failed login attempts
+CAPTCHA may be triggered after several consecutive failed login attempts
which may lead to a `401 unauthorized` error when testing your Jira integration.
-If CAPTCHA has been triggered, you will not be able to use Jira's REST API to
+If CAPTCHA has been triggered, you will not be able to use Jira's REST API to
authenticate with the Jira site. You will need to log in to your Jira instance
and complete the CAPTCHA.
diff --git a/doc/user/project/integrations/jira_cloud_configuration.md b/doc/user/project/integrations/jira_cloud_configuration.md
index cae66526175..849df707521 100644
--- a/doc/user/project/integrations/jira_cloud_configuration.md
+++ b/doc/user/project/integrations/jira_cloud_configuration.md
@@ -3,7 +3,7 @@
An API token is needed when integrating with JIRA Cloud, follow the steps
below to create one:
-1. Log in to https://id.atlassian.com with your email.
+1. Log in to <https://id.atlassian.com> with your email.
1. **Click API tokens**, then **Create API token**.
![JIRA API token](img/jira_api_token_menu.png)
diff --git a/doc/user/project/integrations/kubernetes.md b/doc/user/project/integrations/kubernetes.md
index 9342a2cbb00..ab43eb2da7e 100644
--- a/doc/user/project/integrations/kubernetes.md
+++ b/doc/user/project/integrations/kubernetes.md
@@ -1 +1,5 @@
+---
+redirect_to: '../clusters/index.md'
+---
+
This document was moved to [another location](../clusters/index.md).
diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md
index ed4367c1135..8c5461de42f 100644
--- a/doc/user/project/integrations/mattermost.md
+++ b/doc/user/project/integrations/mattermost.md
@@ -10,7 +10,7 @@ To enable Mattermost integration you must create an incoming webhook integration
1. Save it, copy the **Webhook URL**, we'll need this later for GitLab.
There might be some cases that Incoming Webhooks are blocked by admin, ask your mattermost admin to enable
-it on https://mattermost.example/admin_console/integrations/custom.
+it on `https://mattermost.example/admin_console/integrations/custom`.
Display name override is not enabled by default, you need to ask your admin to enable it on that same section.
@@ -38,7 +38,7 @@ At the end, fill in your Mattermost details:
| Field | Description |
| ----- | ----------- |
-| **Webhook** | The incoming webhook URL which you have to set up on Mattermost, it will be something like: http://mattermost.example/hooks/5xo… |
+| **Webhook** | The incoming webhook URL which you have to set up on Mattermost, it will be something like: `http://mattermost.example/hooks/5xo…` |
| **Username** | Optional username which can be on messages sent to Mattermost. Fill this in if you want to change the username of the bot. |
| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. |
diff --git a/doc/user/project/integrations/mattermost_slash_commands.md b/doc/user/project/integrations/mattermost_slash_commands.md
index e031dcad2c3..9c69437537a 100644
--- a/doc/user/project/integrations/mattermost_slash_commands.md
+++ b/doc/user/project/integrations/mattermost_slash_commands.md
@@ -152,7 +152,7 @@ trigger word followed by <kbd>help</kbd>. Example: <samp>/gitlab help</samp>
## Permissions
The permissions to run the [available commands](#available-slash-commands) derive from
-the [permissions you have on the project](../../permissions.md#project).
+the [permissions you have on the project](../../permissions.md#project-members-permissions).
## Further reading
diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md
index be45ce46dfd..e2f23827360 100644
--- a/doc/user/project/integrations/project_services.md
+++ b/doc/user/project/integrations/project_services.md
@@ -36,7 +36,6 @@ Click on the service links to see further configuration instructions and details
| External Wiki | Replaces the link to the internal wiki with a link to an external wiki |
| Flowdock | Flowdock is a collaboration web app for technical teams |
| [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat |
-| [HipChat](hipchat.md) | Private group chat and IM |
| [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway |
| [JIRA](jira.md) | JIRA issue tracker |
| JetBrains TeamCity CI | A continuous integration and build server |
@@ -51,6 +50,7 @@ Click on the service links to see further configuration instructions and details
| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop |
| [Redmine](redmine.md) | Redmine issue tracker |
+| [YouTrack](youtrack.md) | YouTrack issue tracker |
## Services templates
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index d9a2eeb32ae..26989e2a8a4 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -9,8 +9,9 @@ within the GitLab interface.
![Environment Dashboard](img/prometheus_dashboard.png)
There are two ways to set up Prometheus integration, depending on where your apps are running:
-* For deployments on Kubernetes, GitLab can automatically [deploy and manage Prometheus](#managed-prometheus-on-kubernetes)
-* For other deployment targets, simply [specify the Prometheus server](#manual-configuration-of-prometheus).
+
+- For deployments on Kubernetes, GitLab can automatically [deploy and manage Prometheus](#managed-prometheus-on-kubernetes).
+- For other deployment targets, simply [specify the Prometheus server](#manual-configuration-of-prometheus).
Once enabled, GitLab will automatically detect metrics from known services in the [metric library](#monitoring-ci-cd-environments).
@@ -23,14 +24,14 @@ GitLab can seamlessly deploy and manage Prometheus on a [connected Kubernetes cl
#### Requirements
-* A [connected Kubernetes cluster](../clusters/index.md)
-* Helm Tiller [installed by GitLab](../clusters/index.md#installing-applications)
+- A [connected Kubernetes cluster](../clusters/index.md)
+- Helm Tiller [installed by GitLab](../clusters/index.md#installing-applications)
#### Getting started
Once you have a connected Kubernetes cluster with Helm installed, deploying a managed Prometheus is as easy as a single click.
-1. Go to the `Operations > Kubernetes` page, to view your connected clusters
+1. Go to the **Operations > Kubernetes** page to view your connected clusters
1. Select the cluster you would like to deploy Prometheus to
1. Click the **Install** button to deploy Prometheus to the cluster
@@ -42,9 +43,9 @@ Prometheus is deployed into the `gitlab-managed-apps` namespace, using the [offi
The Prometheus server will [automatically detect and monitor](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Ckubernetes_sd_config%3E) nodes, pods, and endpoints. To configure a resource to be monitored by Prometheus, simply set the following [Kubernetes annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/):
-* `prometheus.io/scrape` to `true` to enable monitoring of the resource.
-* `prometheus.io/port` to define the port of the metrics endpoint.
-* `prometheus.io/path` to define the path of the metrics endpoint. Defaults to `/metrics`.
+- `prometheus.io/scrape` to `true` to enable monitoring of the resource.
+- `prometheus.io/port` to define the port of the metrics endpoint.
+- `prometheus.io/path` to define the path of the metrics endpoint. Defaults to `/metrics`.
CPU and Memory consumption is monitored, but requires [naming conventions](prometheus_library/kubernetes.html#specifying-the-environment) in order to determine the environment. If you are using [Auto DevOps](../../../topics/autodevops/), this is handled automatically.
@@ -88,7 +89,7 @@ to integrate with.
Once configured, GitLab will attempt to retrieve performance metrics for any
environment which has had a successful deployment.
-GitLab will automatically scan the Prometheus server for metrics from known serves like Kubernetes and NGINX, and attempt to identify individual environment. The supported metrics and scan process is detailed in our [Prometheus Metric Library documentation](prometheus_library/metrics.html).
+GitLab will automatically scan the Prometheus server for metrics from known servers like Kubernetes and NGINX, and attempt to identify individual environment. The supported metrics and scan process is detailed in our [Prometheus Metrics Library documentation](prometheus_library/index.md).
You can view the performance dashboard for an environment by [clicking on the monitoring button](../../../ci/environments.md#monitoring-environments).
@@ -119,7 +120,7 @@ If the "No data found" screen continues to appear, it could be due to:
- No successful deployments have occurred to this environment.
- Prometheus does not have performance data for this environment, or the metrics
are not labeled correctly. To test this, connect to the Prometheus server and
- [run a query](#gitlab-prometheus-queries), replacing `$CI_ENVIRONMENT_SLUG`
+ [run a query](prometheus_library/kubernetes.html#metrics-supported), replacing `$CI_ENVIRONMENT_SLUG`
with the name of your environment.
[autodeploy]: ../../../ci/autodeploy/index.md
@@ -131,7 +132,7 @@ If the "No data found" screen continues to appear, it could be due to:
[prometheus-docker-image]: https://hub.docker.com/r/prom/prometheus/
[prometheus-yml]:samples/prometheus.yml
[gitlab.com-ip-range]: https://gitlab.com/gitlab-com/infrastructure/issues/434
-[ci-environment-slug]: ../../../ci/variables/#predefined-variables-environment-variables
+[ci-environment-slug]: ../../../ci/variables/#predefined-environment-variables
[ce-8935]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8935
[ce-10408]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10408
[promgldocs]: ../../../administration/monitoring/prometheus/index.md
diff --git a/doc/user/project/integrations/prometheus_library/index.md b/doc/user/project/integrations/prometheus_library/index.md
index 9b9b4f6c8ca..f47884996d8 100644
--- a/doc/user/project/integrations/prometheus_library/index.md
+++ b/doc/user/project/integrations/prometheus_library/index.md
@@ -10,7 +10,8 @@ Currently supported exporters are:
- [Kubernetes](kubernetes.md)
- [NGINX](nginx.md)
-- [NGINX Ingress Controller](nginx_ingress.md)
+- [NGINX Ingress Controller 0.9.0-0.15.x](nginx_ingress_vts.md)
+- [NGINX Ingress Controller 0.16.0+](nginx_ingress.md)
- [HAProxy](haproxy.md)
- [Amazon Cloud Watch](cloudwatch.md)
@@ -28,6 +29,6 @@ In order to isolate and only display relevant metrics for a given environment,
GitLab needs a method to detect which labels are associated. To do that,
GitLab uses the defined queries and fills in the environment specific variables.
Typically this involves looking for the
-[`$CI_ENVIRONMENT_SLUG`](../../../../ci/variables/README.md#predefined-variables-environment-variables),
+[`$CI_ENVIRONMENT_SLUG`](../../../../ci/variables/README.md#predefined-environment-variables),
but may also include other information such as the project's Kubernetes namespace.
Each search query is defined in the [exporter specific documentation](#exporters).
diff --git a/doc/user/project/integrations/prometheus_library/kubernetes.md b/doc/user/project/integrations/prometheus_library/kubernetes.md
index 6b190deaa6c..7a45c87ada0 100644
--- a/doc/user/project/integrations/prometheus_library/kubernetes.md
+++ b/doc/user/project/integrations/prometheus_library/kubernetes.md
@@ -34,4 +34,4 @@ Prometheus needs to be deployed into the cluster and configured properly in orde
In order to isolate and only display relevant CPU and Memory metrics for a given environment, GitLab needs a method to detect which containers it is running. Because these metrics are tracked at the container level, traditional Kubernetes labels are not available.
-Instead, the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) name should begin with [CI_ENVIRONMENT_SLUG](../../../../ci/variables/README.md#predefined-variables-environment-variables). It can be followed by a `-` and additional content if desired. For example, a deployment name of `review-homepage-5620p5` would match the `review/homepage` environment.
+Instead, the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) name should begin with [CI_ENVIRONMENT_SLUG](../../../../ci/variables/README.md#predefined-environment-variables). It can be followed by a `-` and additional content if desired. For example, a deployment name of `review-homepage-5620p5` would match the `review/homepage` environment.
diff --git a/doc/user/project/integrations/prometheus_library/metrics.md b/doc/user/project/integrations/prometheus_library/metrics.md
index 37a5388d2fc..7ace0ec5a93 100644
--- a/doc/user/project/integrations/prometheus_library/metrics.md
+++ b/doc/user/project/integrations/prometheus_library/metrics.md
@@ -1 +1,5 @@
+---
+redirect_to: 'index.md'
+---
+
This document was moved to [another location](index.md).
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index 40ac855c74f..b7601f26802 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -1,8 +1,10 @@
# Monitoring NGINX Ingress Controller
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13438) in GitLab 9.5.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22133) in GitLab 11.7.
-GitLab has support for automatically detecting and monitoring the Kubernetes NGINX ingress controller. This is provided by leveraging the built in Prometheus metrics included in [version 0.9.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#09-beta1) and above of the ingress.
+NOTE: **Note:** NGINX Ingress versions prior to 0.16.0 offer an included [VTS Prometheus metrics exporter](nginx_ingress_vts.md), which exports metrics different than the built-in metrics.
+
+GitLab has support for automatically detecting and monitoring the Kubernetes NGINX ingress controller. This is provided by leveraging the built-in Prometheus metrics included starting with [version 0.16.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0160).
## Requirements
@@ -12,27 +14,29 @@ GitLab has support for automatically detecting and monitoring the Kubernetes NGI
| Name | Query |
| ---- | ----- |
-| Throughput (req/sec) | sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code) |
-| Latency (ms) | avg(nginx_upstream_response_msecs_avg{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}) |
-| HTTP Error Rate (%) | sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) * 100 |
+| Throughput (req/sec) | sum(label_replace(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m]), "status_code", "${1}xx", "status", "(.)..")) by (status_code) |
+| Latency (ms) | sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_sum{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_count{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 1000 |
+| HTTP Error Rate (%) | sum(rate(nginx_ingress_controller_requests{status=~"5.*",namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 100 |
## Configuring NGINX ingress monitoring
If you have deployed NGINX Ingress using GitLab's [Kubernetes cluster integration](../../clusters/index.md#installing-applications), it will [automatically be monitored](#about-managed-nginx-ingress-deployments) by Prometheus.
For other deployments, there is [some configuration](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) required depending on your installation:
-* NGINX Ingress should be version 0.9.0 or above, with metrics enabled
-* NGINX Ingress should be annotated for Prometheus monitoring
-* Prometheus should be configured to monitor annotated pods
+
+- NGINX Ingress should be version 0.16.0 or above, with metrics enabled.
+- NGINX Ingress should be annotated for Prometheus monitoring.
+- Prometheus should be configured to monitor annotated pods.
### About managed NGINX Ingress deployments
NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer's IP](../../clusters/index.md#getting-the-external-ip-address).
NGINX is configured for Prometheus monitoring, by setting:
-* `enable-vts-status: "true"`, to export Prometheus metrics
-* `prometheus.io/scrape: "true"`, to enable automatic discovery
-* `prometheus.io/port: "10254"`, to specify the metrics port
+
+- `enable-vts-status: "true"`, to export Prometheus metrics.
+- `prometheus.io/scrape: "true"`, to enable automatic discovery.
+- `prometheus.io/port: "10254"`, to specify the metrics port.
When used in conjunction with the GitLab deployed Prometheus service, response metrics will be automatically collected.
@@ -42,13 +46,13 @@ Version 0.9.0 and above of [NGINX ingress](https://github.com/kubernetes/ingress
Next, the ingress needs to be annotated for Prometheus monitoring. Two new annotations need to be added:
-* `prometheus.io/scrape: "true"`
-* `prometheus.io/port: "10254"`
+- `prometheus.io/scrape: "true"`
+- `prometheus.io/port: "10254"`
Managing these settings depends on how NGINX ingress has been deployed. If you have deployed via the [official Helm chart](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress), metrics can be enabled with `controller.stats.enabled` along with the required annotations. Alternatively it is possible edit the NGINX ingress YML directly in the [Kubernetes dashboard](https://github.com/kubernetes/dashboard).
## Specifying the Environment label
-In order to isolate and only display relevant metrics for a given environment, GitLab needs a method to detect which labels are associated. To do this, GitLab will search for metrics with appropriate labels. In this case, the `upstream` label must be of the form `<KUBE_NAMESPACE>-<CI_ENVIRONMENT_SLUG>-*`.
+In order to isolate and only display relevant metrics for a given environment, GitLab needs a method to detect which labels are associated. To do this, GitLab will search for metrics with appropriate labels. In this case, the `ingress` label must `<CI_ENVIRONMENT_SLUG>`.
If you have used [Auto Deploy](../../../../topics/autodevops/index.md#auto-deploy) to deploy your app, this format will be used automatically and metrics will be detected with no action on your part.
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
new file mode 100644
index 00000000000..081eb8732ad
--- /dev/null
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
@@ -0,0 +1,58 @@
+# Monitoring NGINX Ingress Controller with VTS metrics
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13438) in GitLab 9.5.
+
+NOTE: **Note:** [NGINX Ingress version 0.16](nginx_ingress.md) and above have built-in Prometheus metrics, which are different than the VTS based metrics.
+
+GitLab has support for automatically detecting and monitoring the Kubernetes NGINX ingress controller. This is provided by leveraging the included VTS Prometheus metrics exporter in [version 0.9.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#09-beta1) through [0.15.x](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0150).
+
+## Requirements
+
+[Prometheus integration](../prometheus.md) must be active.
+
+## Metrics supported
+
+| Name | Query |
+| ---- | ----- |
+| Throughput (req/sec) | sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code) |
+| Latency (ms) | avg(nginx_upstream_response_msecs_avg{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}) |
+| HTTP Error Rate (%) | sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) * 100 |
+
+## Configuring NGINX ingress monitoring
+
+If you have deployed NGINX Ingress using GitLab's [Kubernetes cluster integration](../../clusters/index.md#installing-applications), it will [automatically be monitored](#about-managed-nginx-ingress-deployments) by Prometheus.
+
+For other deployments, there is [some configuration](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) required depending on your installation:
+
+- NGINX Ingress should be version 0.9.0 or above, with metrics enabled.
+- NGINX Ingress should be annotated for Prometheus monitoring.
+- Prometheus should be configured to monitor annotated pods.
+
+### About managed NGINX Ingress deployments
+
+NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer's IP](../../clusters/index.md#getting-the-external-ip-address).
+
+NGINX is configured for Prometheus monitoring, by setting:
+
+- `enable-vts-status: "true"`, to export Prometheus metrics.
+- `prometheus.io/scrape: "true"`, to enable automatic discovery.
+- `prometheus.io/port: "10254"`, to specify the metrics port.
+
+When used in conjunction with the GitLab deployed Prometheus service, response metrics will be automatically collected.
+
+### Manually setting up NGINX Ingress for Prometheus monitoring
+
+Version 0.9.0 and above of [NGINX ingress](https://github.com/kubernetes/ingress-nginx) have built-in support for exporting Prometheus metrics. To enable, a ConfigMap setting must be passed: `enable-vts-status: "true"`. Once enabled, a Prometheus metrics endpoint will start running on port 10254.
+
+Next, the ingress needs to be annotated for Prometheus monitoring. Two new annotations need to be added:
+
+- `prometheus.io/scrape: "true"`
+- `prometheus.io/port: "10254"`
+
+Managing these settings depends on how NGINX ingress has been deployed. If you have deployed via the [official Helm chart](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress), metrics can be enabled with `controller.stats.enabled` along with the required annotations. Alternatively it is possible edit the NGINX ingress YML directly in the [Kubernetes dashboard](https://github.com/kubernetes/dashboard).
+
+## Specifying the Environment label
+
+In order to isolate and only display relevant metrics for a given environment, GitLab needs a method to detect which labels are associated. To do this, GitLab will search for metrics with appropriate labels. In this case, the `upstream` label must be of the form `<KUBE_NAMESPACE>-<CI_ENVIRONMENT_SLUG>-*`.
+
+If you have used [Auto Deploy](../../../../topics/autodevops/index.md#auto-deploy) to deploy your app, this format will be used automatically and metrics will be detected with no action on your part.
diff --git a/doc/user/project/integrations/redmine.md b/doc/user/project/integrations/redmine.md
index 76a2617125e..8112aa21859 100644
--- a/doc/user/project/integrations/redmine.md
+++ b/doc/user/project/integrations/redmine.md
@@ -1,9 +1,9 @@
# Redmine Service
1. To enable the Redmine integration in a project, navigate to the
-[Integrations page](project_services.md#accessing-the-project-services), click
-the **Redmine** service, and fill in the required details on the page as described
-in the table below.
+ [Integrations page](project_services.md#accessing-the-project-services), click
+ the **Redmine** service, and fill in the required details on the page as described
+ in the table below.
| Field | Description |
| ----- | ----------- |
diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md
index af4ca35a215..bb8d276c2fc 100644
--- a/doc/user/project/integrations/slack.md
+++ b/doc/user/project/integrations/slack.md
@@ -23,4 +23,54 @@ The Slack Notifications Service allows your GitLab project to send events (e.g.
Your Slack team will now start receiving GitLab event notifications as configured.
-![Slack configuration](img/slack_configuration.png) \ No newline at end of file
+![Slack configuration](img/slack_configuration.png)
+
+## Troubleshooting
+
+If you're having trouble with the Slack integration not working, then start by
+searching through the [Sidekiq logs](../../../administration/logs.md#sidekiqlog)
+for errors relating to your Slack service.
+
+### Something went wrong on our end
+
+This is a generic error shown in the GitLab UI and doesn't mean much by itself.
+You'll need to look in [the logs](../../../administration/logs.md#productionlog) to find
+an error message and keep troubleshooting from there.
+
+### `certificate verify failed`
+
+You may see an entry similar to the following in your Sidekiq log:
+
+```text
+2019-01-10_13:22:08.42572 2019-01-10T13:22:08.425Z 6877 TID-abcdefg ProjectServiceWorker JID-3bade5fb3dd47a85db6d78c5 ERROR: {:class=>"ProjectServiceWorker", :service_class=>"SlackService", :message=>"SSL_connect returned=1 errno=0 state=error: certificate verify failed"}
+```
+
+This is probably a problem either with GitLab communicating with Slack, or GitLab
+communicating with itself. The former is less likely since Slack's security certificates
+should _hopefully_ always be trusted. We can establish which we're dealing with by using
+the below rails console script.
+
+```sh
+# start a rails console:
+sudo gitlab-rails console production
+
+# or for source installs:
+bundle exec rails console production
+```
+
+```ruby
+# run this in the Rails console
+# replace <SLACK URL> with your actual Slack URL
+result = Net::HTTP.get(URI('https://<SLACK URL>'));0
+
+# replace <GITLAB URL> with your actual GitLab URL
+result = Net::HTTP.get(URI('https://<GITLAB URL>'));0
+```
+
+If it's an issue with GitLab not trusting HTTPS connections to itself, then you may simply
+need to [add your certificate to GitLab's trusted certificates](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates).
+
+If it's an issue with GitLab not trusting connections to Slack, then the GitLab
+OpenSSL trust store probably got messed up somehow. Typically this is from overriding
+the trust store with `gitlab_rails['env'] = {"SSL_CERT_FILE" => "/path/to/file.pem"}`
+or by accidentally modifying the default CA bundle `/opt/gitlab/embedded/ssl/certs/cacert.pem`.
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index 4d1d95da6f0..c3fc6d4b859 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -22,12 +22,37 @@ a new issue is created. You can configure webhooks to listen for specific events
like pushes, issues or merge requests. GitLab will send a POST request with data
to the webhook URL.
+In most cases, you'll need to set up your own [webhook receiver](#example-webhook-receiver)
+to receive information from GitLab, and send it to another app, according to your needs.
+We already have a [built-in receiver](http://docs.gitlab.com/ce/project_services/slack.html)
+for sending [Slack](https://api.slack.com/incoming-webhooks) notifications _per project_.
+
+## Overview
+
+[Webhooks](https://en.wikipedia.org/wiki/Webhook) are "_user-defined HTTP
+callbacks_". They are usually triggered by some
+event, such as pushing code to a repository or a comment being posted to a blog.
+When that event occurs, the source app makes an HTTP request to the URI
+configured for the webhook. The action taken may be anything.
+Common uses are to trigger builds with continuous integration systems or to
+notify bug tracking systems.
+
Webhooks can be used to update an external issue tracker, trigger CI jobs,
update a backup mirror, or even deploy to your production server.
+They are available **per project** for GitLab Community Edition,
+and **per project and per group** for **GitLab Enterprise Edition**.
Navigate to the webhooks page by going to your project's
**Settings âž” Integrations**.
+## Use-cases
+
+- You can set up a webhook in GitLab to send a notification to
+ [Slack](https://api.slack.com/incoming-webhooks) every time a build fails, for example
+- You can [integrate with Twilio to be notified via SMS](https://www.datadoghq.com/blog/send-alerts-sms-customizable-webhooks-twilio/)
+ every time an issue is created for a specific project or group within GitLab
+- You can use them to [automatically assign labels to merge requests](https://about.gitlab.com/2016/08/19/applying-gitlab-labels-automatically/).
+
## Webhook endpoint tips
If you are writing your own endpoint (web server) that will receive
@@ -1203,6 +1228,15 @@ by uncommenting or adding the following setting to your `/etc/gitlab/gitlab.rb`:
gitlab_rails['webhook_timeout'] = 10
```
+### Troubleshooting: "Unable to get local issuer certificate"
+
+When SSL verification is enabled, this error indicates that GitLab isn't able to verify the SSL certificate of the webhook endpoint.
+Typically, this is because the root certificate isn't issued by a trusted certification authority as
+determined by [CAcert.org](http://www.cacert.org/).
+
+Should that not be the case, consider using [SSL Checker](https://www.sslshopper.com/ssl-checker.html) to identify faults.
+Missing intermediate certificates are a common point of verification failure.
+
## Example webhook receiver
If you want to see GitLab's webhooks in action for testing purposes you can use
diff --git a/doc/user/project/integrations/youtrack.md b/doc/user/project/integrations/youtrack.md
new file mode 100644
index 00000000000..2ab14a8db2c
--- /dev/null
+++ b/doc/user/project/integrations/youtrack.md
@@ -0,0 +1,31 @@
+# YouTrack Service
+
+JetBrains YouTrack is a web-based issue tracking and project management platform.
+Please refer official [documentation](https://www.jetbrains.com/help/youtrack/standalone/YouTrack-Documentation.html) for details about YouTrack itself.
+
+
+1. To enable the YouTrack integration in a project, navigate to the
+[Integrations page](project_services.md#accessing-the-project-services), click
+the **YouTrack** service, and fill in the required details on the page as described
+in the table below.
+
+ | Field | Description |
+ | ----- | ----------- |
+ | `description` | A name for the issue tracker (to differentiate between instances, for example) |
+ | `project_url` | The URL to the project in YouTrack which is being linked to this GitLab project |
+ | `issues_url` | The URL to the issue in YouTrack project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. |
+
+ Once you have configured and enabled YouTrack you'll see the YouTrack link on the GitLab project pages that takes you to the appropriate YouTrack project.
+
+1. To disable the internal issue tracking system in a project, navigate to the General page, expand [Permissions](../settings/index.md#sharing-and-permissions), and slide the Issues switch invalid.
+
+ ![Issue configuration](img/issue_configuration.png)
+
+## Referencing issues in YouTrack
+
+Issues in YouTrack can be referenced as `<PROJECT>-<ID>` where `<PROJECT>`
+starts with a capital letter which is then followed by capital or lower case
+letters, numbers or underscores, and `<ID>` is a number (example `Api_32-143`).
+
+`<PROJECT>` part is included into issue_id and links can point any YouTrack
+project (`issues_url` + issue_id)
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 9e2434c02ec..66168080087 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -78,9 +78,9 @@ with labels, and from there organize and prioritize them with Issue Boards.
For example, let's consider this simplified development workflow:
1. You have a repository hosting your app's codebase
-and your team actively contributing to code
+ and your team actively contributing to code
1. Your **backend** team starts working a new
-implementation, gathers feedback and approval, and pass it over to **frontend**
+ implementation, gathers feedback and approval, and pass it over to **frontend**
1. When frontend is complete, the new feature is deployed to **staging** to be tested
1. When successful, it is deployed to **production**
@@ -88,7 +88,7 @@ If we have the labels "**backend**", "**frontend**", "**staging**", and
"**production**", and an Issue Board with a list for each, we can:
- Visualize the entire flow of implementations since the
-beginning of the development lifecycle until deployed to production
+ beginning of the development lifecycle until deployed to production
- Prioritize the issues in a list by moving them vertically
- Move issues between lists to organize them according to the labels you've set
- Add multiple issues to lists in the board by selecting one or more existing issues
@@ -173,18 +173,21 @@ or in situations where a repository is used to host the code of multiple
products.
Clicking on the current board name in the upper left corner will reveal a
-menu from where you can create another Issue Board and rename or delete the
-existing one.
+menu from where you can create another Issue Board or delete the existing one.
+Using the search box at the top of the menu, you can filter the listed boards.
-When you're revisiting an issue board in a project or group with multiple boards,
+When you have 10 or more boards available, a "Recent" section is also shown in the menu.
+These are shortcuts to your last 4 visited boards.
+
+![Multiple Issue Boards](img/issue_boards_multiple.png)
+
+When you're revisiting an issue board in a project or group with multiple boards,
GitLab will automatically load the last board you visited.
NOTE: **Note:**
The Multiple Issue Boards feature is available for
**projects in GitLab Starter Edition** and for **groups in GitLab Premium Edition**.
-![Multiple Issue Boards](img/issue_boards_multiple.png)
-
### Configurable Issue Boards **[STARTER]**
> Introduced in [GitLab Starter Edition 10.2](https://about.gitlab.com/2017/11/22/gitlab-10-2-released/#issue-boards-configuration).
@@ -233,7 +236,7 @@ group-level objects are available.
NOTE: **Note:**
Multiple group issue boards were originally introduced in [GitLab 10.0 Premium](https://about.gitlab.com/2017/09/22/gitlab-10-0-released/#group-issue-boards) and
-one group issue board per group was made available in GitLab 10.6 Core.
+one group issue board per group was made available in GitLab 10.6 Core.
![Group issue board](img/group_issue_board.png)
diff --git a/doc/user/project/issues/automatic_issue_closing.md b/doc/user/project/issues/automatic_issue_closing.md
index afb7d9ada5f..c3e06b219ff 100644
--- a/doc/user/project/issues/automatic_issue_closing.md
+++ b/doc/user/project/issues/automatic_issue_closing.md
@@ -1,6 +1,7 @@
# Automatic issue closing
>**Notes:**
+>
> - This is the user docs. In order to change the default issue closing pattern,
> follow the steps in the [administration docs].
> - For performance reasons, automatic issue closing is disabled for the very
diff --git a/doc/user/project/issues/create_new_issue.md b/doc/user/project/issues/create_new_issue.md
index c33d1365001..40040e44d64 100644
--- a/doc/user/project/issues/create_new_issue.md
+++ b/doc/user/project/issues/create_new_issue.md
@@ -39,40 +39,46 @@ It opens a new issue for that project labeled after its respective list.
## New issue via email
-*This feature needs [incoming email](../../../administration/incoming_email.md)
-to be configured by a GitLab administrator to be available for CE/EE users, and
-it's available on GitLab.com.*
+At the bottom of a project's Issues List page, a link to **Email a new issue to this project**
+is displayed if your GitLab instance has [incoming email](../../../administration/incoming_email.md) configured.
-At the bottom of a project's issue page, click
-**Email a new issue to this project**, and you will find an email address
-which belongs to you. You could add this address to your contact.
+![Bottom of a project issues page](img/new_issue_from_email.png)
+
+When you click this link, an email address is displayed which belongs to you for creating issues in this project.
+You can save this address as a contact in your email client for easy acceess.
-This is a private email address, generated just for you.
-**Keep it to yourself** as anyone who gets ahold of it can create issues or
-merge requests as if they were you. You can add this address to your contact
-list for easy access.
+CAUTION: **Caution:**
+This is a private email address, generated just for you. **Keep it to yourself**,
+as anyone who gets ahold of it can create issues or merge requests as if they
+were you. If the address is compromised, or you'd like it to be regenerated for
+any reason, click **Email a new issue to this project** again and click the reset link.
Sending an email to this address will create a new issue on your behalf for
-this project, where the email subject becomes the issue title, and the email
-body becomes the issue description. [Markdown] and [quick actions] are
-supported.
+this project, where:
-![Bottom of a project issues page](img/new_issue_from_email.png)
+- The email subject becomes the issue title.
+- The email body becomes the issue description.
+- [Markdown](../../markdown.md) and [quick actions](../quick_actions.md) are supported.
+
+NOTE: **Note:**
+In GitLab 11.7, we updated the format of the generated email address.
+However the older format is still supported, allowing existing aliases
+or contacts to continue working._
## New issue via URL with prefilled fields
You can link directly to the new issue page for a given project, with prefilled
-field values using query string parameters in a URL. This is useful for embedding
-a URL in an external HTML page, and also certain scenarios where you want the user to
+field values using query string parameters in a URL. This is useful for embedding
+a URL in an external HTML page, and also certain scenarios where you want the user to
create an issue with certain fields prefilled.
-The title, description, and description template fields can be prefilled using
+The title, description, and description template fields can be prefilled using
this method. The description and description template fields cannot be pre-entered
in the same URL (since a description template just populates the description field).
Follow these examples to form your new issue URL with prefilled fields.
- For a new issue in the GitLab Community Edition project with a pre-entered title
-and a pre-entered description, the URL would be `https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issue[title]=Validate%20new%20concept&issue[description]=Research%20idea`
+ and a pre-entered description, the URL would be `https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issue[title]=Validate%20new%20concept&issue[description]=Research%20idea`
- For a new issue in the GitLab Community Edition project with a pre-entered title
-and a pre-entered description template, the URL would be `https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issue[title]=Validate%20new%20concept&issuable_template=Research%20proposal`
+ and a pre-entered description template, the URL would be `https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issue[title]=Validate%20new%20concept&issuable_template=Research%20proposal`
diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md
new file mode 100644
index 00000000000..032e3a73ad0
--- /dev/null
+++ b/doc/user/project/issues/csv_import.md
@@ -0,0 +1,63 @@
+# Importing Issues from CSV
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23532) in GitLab 11.7.
+
+Issues can be imported to a project by uploading a CSV file. Supported fields are
+`title` and `description`.
+
+The user uploading the CSV file will be set as the author of the imported issues.
+
+> **Note:** A permission level of `Developer` or higher is required to import issues.
+
+To import issues:
+
+1. Ensure your CSV file meets the [file format](#csv-file-format) requirements.
+1. Navigate to a project's Issues list page.
+1. If existing issues are present, click the import icon at the top right, next to the **Edit issues** button.
+1. For a project without any issues, click the button labeled **Import CSV** in the middle of the page.
+1. Select the file and click the **Import issues** button.
+
+The file is processed in the background and a notification email is sent
+to you once the import is completed.
+
+## CSV File Format
+
+### Header row
+
+CSV files must contain a header row beginning with at least two columns, `title` and `description`, in that order.
+If additional columns are present, they will be ignored.
+
+### Column separator
+
+The column separator is automatically detected from the header row.
+
+Supported separator characters are: commas (`,`), semicolons (`;`), and tabs (`\t`).
+
+### Row separator
+
+Lines ending in either `CRLF` or `LF` are supported.
+
+### Quote character
+
+The double-quote (`"`) character is used to quote fields so you can use the column separator within a field. To insert
+a double-quote (`"`) within a quoted field, use two double-quote characters in succession, i.e. `""`.
+
+### Data rows
+
+After the header row, succeeding rows must follow the same column order. The issue title is required while the
+description is optional.
+
+### File size
+
+The limit depends on the configuration value of Max Attachment Size for the GitLab instance.
+
+For GitLab.com, it is set to 10 MB.
+
+## Sample Data
+
+```csv
+title,description
+My Issue Title,My Issue Description
+Another Title,"A description, with a comma"
+"One More Title","One More Description"
+```
diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md
index 93306437c6c..7972c14c1c4 100644
--- a/doc/user/project/issues/due_dates.md
+++ b/doc/user/project/issues/due_dates.md
@@ -42,6 +42,7 @@ server's timezone.
Issues with due dates can also be exported as an iCalendar feed. The URL of the
feed can be added to calendar applications. The feed is accessible by clicking
on the _Subscribe to calendar_ button on the following pages:
+
- on the **Assigned Issues** page that is linked on the right-hand side of the
GitLab header
- on the **Project Issues** page
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 200b3a642a1..907a305fe23 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -142,20 +142,29 @@ to find out more about this feature.
With [GitLab Starter](https://about.gitlab.com/pricing/), you can also
create various boards per project with [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards).
+### Import Issues from CSV
+
+You can import a CSV file containing issue titles and descriptions to create
+a batch of issues simultaneously.
+
+When you navigate to the Issues list page, an import button is displayed.
+
+For further details, see [Importing issues from CSV](csv_import.md)
+
### External Issue Tracker
Alternatively to GitLab's built-in Issue Tracker, you can also use an [external
tracker](../../../integration/external-issue-tracker.md) such as Jira, Redmine,
-or Bugzilla.
+YouTrack, or Bugzilla.
-### Issue's API
+### Issue API
-Read through the [API documentation](../../../api/issues.md).
+See the [API documentation](../../../api/issues.md).
### Bulk editing issues
-Find out about [bulk editing issues](../../project/bulk_editing.md).
+See the [bulk editing issues](../../project/bulk_editing.md) page.
### Similar issues
-Find out about [similar issues](similar_issues.md).
+See the [similar issues](similar_issues.md) page.
diff --git a/doc/user/project/issues/issues_functionalities.md b/doc/user/project/issues/issues_functionalities.md
index d78721f8658..27b9dc51760 100644
--- a/doc/user/project/issues/issues_functionalities.md
+++ b/doc/user/project/issues/issues_functionalities.md
@@ -4,7 +4,7 @@ Please read through the [GitLab Issue Documentation](index.md) for an overview o
## Issues Functionalities
-The image bellow illustrates how an issue looks like:
+The image below illustrates what an issue looks like:
![Issue view](img/issues_main_view_numbered.jpg)
@@ -13,7 +13,7 @@ You can find all the information on that issue on one screen.
### Issue screen
An issue starts with its status (open or closed), followed by its author,
-and includes many other functionalities, numbered on the image above to
+and includes many other functionalities, numbered in the image above to
explain what they mean, one by one.
Many of the elements of the issue screen refresh automatically, such as the title and description, when they are changed by another user.
@@ -27,7 +27,7 @@ Comments and system notes also appear automatically in response to various actio
#### 2. Todos
-- Add todo: add that issue to your [GitLab Todo](../../../workflow/todos.html) list
+- Add todo: add that issue to your [GitLab Todo](../../../workflow/todos.md) list
- Mark todo as done: mark that issue as done (reflects on the Todo list)
#### 3. Assignee
@@ -43,14 +43,14 @@ assigned to them if they created the issue themselves.
##### 3.1. Multiple Assignees **[STARTER]**
-Often multiple people likely work on the same issue together,
-which can especially be difficult to track in large teams
+Often multiple people work on the same issue together,
+which can be especially difficult to track in large teams
where there is shared ownership of an issue.
-In [GitLab Starter](https://about.gitlab.com/pricing/), you can also
-select multiple assignees to an issue.
+In [GitLab Starter](https://about.gitlab.com/pricing/), you can
+assign multiple people to an issue.
-Learn more on the [Multiple Assignees documentation](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html).
+Learn more in the [Multiple Assignees documentation](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html).
#### 4. Milestone
@@ -58,40 +58,39 @@ Learn more on the [Multiple Assignees documentation](https://docs.gitlab.com/ee/
#### 5. Time Tracking
-- Estimate time: add an estimate time in which the issue will be implemented
-- Spend: add the time spent on the implementation of that issue
+- Estimate time: add an estimate of the time it will take to resolve the issue.
+- Spend: add the time spent on the resolution of the issue
> **Note:**
Both estimate and spend times are set via [GitLab Quick Actions](../quick_actions.md).
-Learn more on the [Time Tracking documentation](../../../workflow/time_tracking.md).
+Learn more in the [Time Tracking documentation](../../../workflow/time_tracking.md).
#### 6. Due date
-When you work on a tight schedule, and it's important to
-have a way to set up a deadline for implementations and for solving
-problems. This can be facilitated by the [due date](due_dates.md)). Due dates
+When you work on a tight schedule, it's important to
+have a way to set a deadline for implementations and for solving
+problems. This can be done in the [due date](due_dates.md) element. Due dates
can be changed as many times as needed.
#### 7. Labels
Categorize issues by giving them [labels](../labels.md). They help to
-organize team's workflows, once they enable you to work with the
-[GitLab Issue Board](index.md#gitlab-issue-board).
+organize workflows, and they enable you to work with the
+[GitLab Issue Board](index.md#issue-board).
-Group Labels, which allow you to use the same labels per
+Group Labels, which allow you to use the same labels for a
group of projects, can be also given to issues. They work exactly the same,
but they are immediately available to all projects in the group.
> **Tip:**
-if the label doesn't exist yet, when you click **Edit**, it opens a dropdown menu from which you can select **Create new label**.
+If a label doesn't exist yet, you can click **Edit**, and it opens a dropdown menu from which you can select **Create new label**.
#### 8. Weight **[STARTER]**
-- Attribute a weight (in a 0 to 9 range) to that issue. Easy to complete
-should weight 1 and very hard to complete should weight 9.
+- Assign a weight. Larger values are used to indicate more effort is required to complete the issue. Only positive values or zero are allowed.
-Learn more on the [Issue Weight documentation](https://docs.gitlab.com/ee/workflow/issue_weight.html).
+Learn more in the [Issue Weight documentation](https://docs.gitlab.com/ee/workflow/issue_weight.html).
#### 9. Participants
@@ -100,34 +99,35 @@ Learn more on the [Issue Weight documentation](https://docs.gitlab.com/ee/workfl
#### 10. Notifications
- Subscribe: if you are not a participant of the discussion on that issue, but
-want to receive notifications on each new input, subscribe to it.
+ want to receive notifications on each new input, subscribe to it.
- Unsubscribe: if you are receiving notifications on that issue but no
-longer want to receive them, unsubscribe to it.
+ longer want to receive them, unsubscribe from it.
-Read more on the [notifications documentation](../../../workflow/notifications.md#issue-merge-request-events).
+Read more in the [notifications documentation](../../../workflow/notifications.md#issue--merge-request-events).
#### 11. Reference
-- A quick "copy to clipboard" button to that issue's reference, `foo/bar#xxx`, where `foo` is the `username` or `groupname`, `bar`
-is the `project-name`, and `xxx` is the issue number.
+- A quick "copy to clipboard" button for that issue's reference, `foo/bar#xxx`, where `foo` is the `username` or `groupname`, `bar`
+ is the `project-name`, and `xxx` is the issue number.
#### 12. Title and description
-- Title: a plain text title describing the issue's subject.
-- Description: a text field which fully supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
+- Title: a plain text title for describing the subject of the issue.
+- Description: a large text field which fully supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm),
+ to describe all the details of the issue.
-#### 13. @mentions
+#### 13. Mentions
-- You can either `@mention` a user or a group present in your
- GitLab instance and they will be notified via todos and email, unless that
- person has disabled all notifications in their profile settings.
-- Mentions for yourself (the current logged in user),will be distinctly highlighted
+- You can mention a user or a group present in your GitLab instance with
+ `@username` or `@groupname` and they will be notified via todos and email, unless
+ they have disabled all notifications in their profile settings.
+- Mentions for yourself (the current logged in user), will be highlighted
in a different color, allowing you to easily see which comments involve you,
helping you focus on them quickly.
-To change your [notification settings](../../../workflow/notifications.md) navigate to
+To change your [notification settings](../../../workflow/notifications.md), navigate to
**Profile Settings** > **Notifications** > **Global notification level**
-and choose your preferences from the dropdown menu.
+and choose your preference from the dropdown menu.
> **Tip:**
Avoid mentioning `@all` in issues and merge requests,
@@ -138,26 +138,26 @@ interpreted as spam.
#### 14. Related Merge Requests
- Any merge requests mentioned in that issue's description
-or in the issue thread.
+ or in the issue discussion thread.
#### 15. Award emoji
- Award an emoji to that issue.
> **Tip:**
-Posting "+1" as comments in threads spam all
+Posting "+1" as a comment in a thread spams all subscribed
participants of that issue. Awarding an emoji is a way to let them
know you like it without spamming them.
#### 16. Thread
- Comments: collaborate to that issue by posting comments in its thread.
-These text fields also fully support
-[GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
+ These text fields also fully support
+ [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
#### 17. Comment, start a discussion, or comment and close
-Once you wrote your comment, you can either:
+Once you write a comment, you can either:
- Click "Comment" and your comment will be published.
- Click "Start discussion": start a thread within that issue's thread to discuss specific points.
@@ -166,7 +166,7 @@ Once you wrote your comment, you can either:
#### 18. New Merge Request
- Create a new merge request (with a new source branch named after the issue) in one action.
-The merge request will automatically inherit the milestone and labels of the issue. The merge
-request will automatically close that issue as soon as merged.
+ The merge request will automatically inherit the milestone and labels of the issue. The merge
+ request will automatically close that issue when it is merged.
- Optionally, you can just create a [new branch](../repository/web_editor.md#create-a-new-branch-from-an-issue)
-named after that issue.
+ named after that issue.
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index 2c2e8e2d556..2a490e3fd7f 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -77,7 +77,7 @@ GitLab users to the project.
Once done, hit **Add users to project** and watch that there is a new member
with the e-mail address we used above. From there on, you can resend the
-invitation, change their access level or even delete them.
+invitation, change their access level, or even delete them.
![Invite user members list](img/add_user_email_accept.png)
diff --git a/doc/user/project/merge_requests.md b/doc/user/project/merge_requests.md
index 84a79f04094..1d7ebc856c3 100644
--- a/doc/user/project/merge_requests.md
+++ b/doc/user/project/merge_requests.md
@@ -1 +1,5 @@
+---
+redirect_to: 'merge_requests/index.md'
+---
+
This document was moved to [merge_requests/index.md](merge_requests/index.md).
diff --git a/doc/user/project/merge_requests/allow_collaboration.md b/doc/user/project/merge_requests/allow_collaboration.md
index 859ac92ef89..da6e6b5fd3a 100644
--- a/doc/user/project/merge_requests/allow_collaboration.md
+++ b/doc/user/project/merge_requests/allow_collaboration.md
@@ -1,20 +1,72 @@
# Allow collaboration on merge requests across forks
-> [Introduced][ce-17395] in GitLab 10.6.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17395)
+ in GitLab 10.6.
+
+When a user opens a merge request from a fork, they are given the option to allow
+upstream members to collaborate with them on the source branch. This allows
+the members of the upstream project to make small fixes or rebase branches
+before merging, reducing the back and forth of accepting external contributions.
This feature is available for merge requests across forked projects that are
-publicly accessible. It makes it easier for members of projects to
-collaborate on merge requests across forks.
+publicly accessible.
When enabled for a merge request, members with merge access to the target
branch of the project will be granted write permissions to the source branch
of the merge request.
+## Enabling commit edits from upstream members
+
The feature can only be enabled by users who already have push access to the
-source project, and only lasts while the merge request is open.
+source project and only lasts while the merge request is open. Once enabled,
+upstream members will also be able to retry the pipelines and jobs of the
+merge request:
+
+1. Enable the contribution while creating or editing a merge request.
+
+ ![Enable contribution](img/allow_collaboration.png)
+
+1. Once the merge request is created, you'll see that commits from members who
+ can merge to the target branch are allowed.
+
+ ![Check that contribution is enabled](img/allow_collaboration_after_save.png)
+
+## Pushing to the fork as the upstream member
+
+If the creator of the merge request has enabled contributions from upstream
+members, you can push directly to the branch of the forked repository.
+
+Assuming that:
+
+- The forked project URL is `git@gitlab.com:thedude/awesome-project.git`.
+- The branch of the merge request is `update-docs`.
+
+Here's how the process would look like:
+
+1. First, you need to get the changes that the merge request has introduced.
+ Click the **Check out branch** button that has some pre-populated
+ commands that you can run.
+
+ ![Check out branch button](img/checkout_button.png)
+
+1. Use the copy to clipboard button to copy the first command and paste them
+ in your terminal:
+
+ ```sh
+ git fetch git@gitlab.com:thedude/awesome-project.git update-docs
+ git checkout -b thedude-awesome-project-update-docs FETCH_HEAD
+ ```
+
+ This will fetch the branch of the forked project and then create a local branch
+ based off the fetched branch.
-Enable this functionality while creating or editing a merge request:
+1. Make any changes you want and commit.
+1. Push to the forked project:
-![Enable collaboration](./img/allow_collaboration.png)
+ ```sh
+ git push git@gitlab.com:thedude/awesome-project.git thedude-awesome-project-update-docs:update-docs
+ ```
-[ce-17395]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17395
+ Note the colon (`:`) between the two branches. The above command will push the
+ local branch `thedude-awesome-project-update-docs` to the
+ `update-docs` branch of the `git@gitlab.com:thedude/awesome-project.git` repository.
diff --git a/doc/user/project/merge_requests/img/allow_collaboration.png b/doc/user/project/merge_requests/img/allow_collaboration.png
index 3c81e4c27b8..e40e8a6b11c 100644
--- a/doc/user/project/merge_requests/img/allow_collaboration.png
+++ b/doc/user/project/merge_requests/img/allow_collaboration.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/allow_collaboration_after_save.png b/doc/user/project/merge_requests/img/allow_collaboration_after_save.png
new file mode 100644
index 00000000000..4ba4c84c8c5
--- /dev/null
+++ b/doc/user/project/merge_requests/img/allow_collaboration_after_save.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/checkout_button.png b/doc/user/project/merge_requests/img/checkout_button.png
new file mode 100644
index 00000000000..9850795c9b4
--- /dev/null
+++ b/doc/user/project/merge_requests/img/checkout_button.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/create_from_email.png b/doc/user/project/merge_requests/img/create_from_email.png
index 610f0b3d0c1..5cb2afaf976 100644
--- a/doc/user/project/merge_requests/img/create_from_email.png
+++ b/doc/user/project/merge_requests/img/create_from_email.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/squash_mr_message.png b/doc/user/project/merge_requests/img/squash_mr_message.png
new file mode 100644
index 00000000000..8734cab29aa
--- /dev/null
+++ b/doc/user/project/merge_requests/img/squash_mr_message.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index d4f8cf929f6..593eb80e044 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -46,7 +46,7 @@ A. Consider you are a software developer working in a team:
1. You verify your changes with [JUnit test reports](../../../ci/junit_test_reports.md) in GitLab CI/CD
1. You request the approval from your manager
1. Your manager pushes a commit with his final review, [approves the merge request](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html), and set it to [merge when pipeline succeeds](#merge-when-pipeline-succeeds) (Merge Request Approvals are available in GitLab Starter)
-1. Your changes get deployed to production with [manual actions](../../../ci/yaml/README.md#manual-actions) for GitLab CI/CD
+1. Your changes get deployed to production with [manual actions](../../../ci/yaml/README.md#whenmanual) for GitLab CI/CD
1. Your implementations were successfully shipped to your customer
B. Consider you're a web developer writing a webpage for your company's:
@@ -76,10 +76,10 @@ You can [search and filter the results](../../search/index.md#issues-and-merge-r
![Group Issues list view](img/group_merge_requests_list_view.png)
-## Removing the source branch
+## Deleting the source branch
-When creating a merge request, select the "Remove source branch when merge
-request accepted" option and the source branch will be removed when the merge
+When creating a merge request, select the "Delete source branch when merge
+request accepted" option and the source branch will be deleted when the merge
request is merged.
This option is also visible in an existing merge request next to the merge
@@ -87,10 +87,19 @@ request button and can be selected/deselected before merging. It's only visible
to users with [Maintainer permissions](../../permissions.md) in the source project.
If the user viewing the merge request does not have the correct permissions to
-remove the source branch and the source branch is set for removal, the merge
-request widget will show the "Removes source branch" text.
+delete the source branch and the source branch is set for deletion, the merge
+request widget will show the "Deletes source branch" text.
-![Remove source branch status](img/remove_source_branch_status.png)
+![Delete source branch status](img/remove_source_branch_status.png)
+
+## Allow collaboration on merge requests across forks
+
+When a user opens a merge request from a fork, they are given the option to allow
+upstream maintainers to collaborate with them on the source branch. This allows
+the maintainers of the upstream project to make small fixes or rebase branches
+before merging, reducing the back and forth of accepting community contributions.
+
+[Learn more about allowing upstream members to push to forks.](allow_collaboration.md)
## Authorization for merge requests
@@ -169,9 +178,9 @@ those conflicts in the GitLab UI.
## Create new merge requests by email
-*This feature needs [incoming email](../../../administration/incoming_email.md)
+_This feature needs [incoming email](../../../administration/incoming_email.md)
to be configured by a GitLab administrator to be available for CE/EE users, and
-it's available on GitLab.com.*
+it's available on GitLab.com._
You can create a new merge request by sending an email to a user-specific email
address. The address can be obtained on the merge requests page by clicking on
@@ -183,8 +192,16 @@ will be used as the merge request description. You need
this feature. If it's not enabled to your instance, you may ask your GitLab
administrator to do so.
+This is a private email address, generated just for you. **Keep it to yourself**
+as anyone who gets ahold of it can create issues or merge requests as if they were you.
+You can add this address to your contact list for easy access.
+
![Create new merge requests by email](img/create_from_email.png)
+_In GitLab 11.7, we updated the format of the generated email address.
+However the older format is still supported, allowing existing aliases
+or contacts to continue working._
+
### Adding patches when creating a merge request via e-mail
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22723) in GitLab 11.5.
@@ -267,7 +284,11 @@ you can preview the changes submitted to a feature-branch through a merge reques
in a per-branch basis. No need to checkout the branch, install and preview locally;
all your changes will be available to preview by anyone with the Review Apps link.
-[Read more about Review Apps.](../../../ci/review_apps/index.md)
+With GitLab's [Route Maps](../../../ci/review_apps/index.md#route-maps) set, the
+merge request widget takes you directly to the pages changed, making it easier and
+faster to preview proposed modifications.
+
+[Read more about Review Apps](../../../ci/review_apps/index.md).
## Pipelines for merge requests
@@ -320,8 +341,8 @@ troubleshooting steps.
This can occur for one of two reasons:
-* Sidekiq doesn't pick up the changes fast enough
-* Because of the bug described in [#41545](https://gitlab.com/gitlab-org/gitlab-ce/issues/41545)
+- Sidekiq doesn't pick up the changes fast enough
+- Because of the bug described in [#41545](https://gitlab.com/gitlab-org/gitlab-ce/issues/41545)
#### Sidekiq
diff --git a/doc/user/project/merge_requests/maintainer_access.md b/doc/user/project/merge_requests/maintainer_access.md
index d59afecd375..fe7e1f558c7 100644
--- a/doc/user/project/merge_requests/maintainer_access.md
+++ b/doc/user/project/merge_requests/maintainer_access.md
@@ -1 +1,5 @@
+---
+redirect_to: 'allow_collaboration.md'
+---
+
This document was moved to [another location](allow_collaboration.md).
diff --git a/doc/user/project/merge_requests/merge_request_discussion_resolution.md b/doc/user/project/merge_requests/merge_request_discussion_resolution.md
index 200965875a1..a554d727ca4 100644
--- a/doc/user/project/merge_requests/merge_request_discussion_resolution.md
+++ b/doc/user/project/merge_requests/merge_request_discussion_resolution.md
@@ -1 +1,5 @@
+---
+redirect_to: '../../discussions/index.md'
+---
+
This document was moved to [another location](../../discussions/index.md).
diff --git a/doc/user/project/merge_requests/merge_when_build_succeeds.md b/doc/user/project/merge_requests/merge_when_build_succeeds.md
index 2167fdfbf7e..cf5e3af16c9 100644
--- a/doc/user/project/merge_requests/merge_when_build_succeeds.md
+++ b/doc/user/project/merge_requests/merge_when_build_succeeds.md
@@ -1,5 +1,7 @@
-This document was moved to [merge_when_pipeline_succeeds](merge_when_pipeline_succeeds.md).
+---
+redirect_to: 'merge_when_pipeline_succeeds.md'
+---
->[Introduced][ce-7135] by the "Rename MWBS service to Merge When Pipeline Succeeds" change.
+This document was moved to [merge_when_pipeline_succeeds](merge_when_pipeline_succeeds.md).
-[ce-7135]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7135
+>[Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7135) by the "Rename MWBS service to Merge When Pipeline Succeeds" change.
diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md
index 2ec423dcf70..4ff8ec3a7e6 100644
--- a/doc/user/project/merge_requests/squash_and_merge.md
+++ b/doc/user/project/merge_requests/squash_and_merge.md
@@ -18,23 +18,30 @@ Into a single commit on merge:
![A squashed commit followed by a merge commit][squashed-commit]
-The squashed commit's commit message is the merge request title. And note that
-the squashed commit is still followed by a merge commit, as the merge
-method for this example repository uses a merge commit. Squashing also works
-with the fast-forward merge strategy, see
-[squashing and fast-forward merge](#squash-and-fast-forward-merge) for more
-details.
+The squashed commit's commit message will be either:
+
+- Taken from the first multi-line commit message in the merge.
+- The merge request's title if no multi-line commit message is found.
+
+It can be customized before merging a merge request.
+
+![A squash commit message editor](img/squash_mr_message.png)
+
+NOTE: **Note:**
+The squashed commit in this example is followed by a merge commit, as the merge method for this example repository uses a merge commit.
+
+Squashing also works with the fast-forward merge strategy, see [squashing and fast-forward merge](#squash-and-fast-forward-merge) for more details.
## Use cases
When working on a feature branch, you sometimes want to commit your current
progress, but don't really care about the commit messages. Those 'work in
progress commits' don't necessarily contain important information and as such
-you'd rather not include them in your target branch.
+you'd rather not include them in your target branch.
With squash and merge, when the merge request is ready to be merged,
all you have to do is enable squashing before you press merge to join
-the commits include in the merge request into a single commit.
+the commits in the merge request into a single commit.
This way, the history of your base branch remains clean with
meaningful commit messages and is simpler to [revert] if necessary.
@@ -56,9 +63,9 @@ This can then be overridden at the time of accepting the merge request:
The squashed commit has the following metadata:
-* Message: the title of the merge request.
-* Author: the author of the merge request.
-* Committer: the user who initiated the squash.
+- Message: the message of the squash commit, or a customized message.
+- Author: the author of the merge request.
+- Committer: the user who initiated the squash.
## Squash and fast-forward merge
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index ac58a0b5c18..e6033ca8655 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -28,8 +28,9 @@ the milestone to the issue.
## Project milestones and group milestones
-- **Project milestones** can be assigned to issues or merge requests in that project only.
-- **Group milestones** can be assigned to any issue or merge request of any project in that group.
+- **Project milestones** can be assigned to issues or merge requests in that project only. Navigate to **Issues > Milestones** in a project to view the project milestone list.
+- **Group milestones** can be assigned to any issue or merge request of any project in that group. Navigate to **Issues > Milestones** in a group to view the group milestone list.
+- All milestones you have access to can also be viewed in the dashboard milestones list. Click on **Milestones** on the top navigation bar to view both project milestones and group milestones you have access to.
## Creating milestones
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index 9a53036b4d1..d7a1a69f29d 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -238,6 +238,6 @@ test:
[triggers]: ../../ci/triggers/README.md
[update-docs]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update
[workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse
-[jobenv]: ../../ci/variables/README.md#predefined-variables-environment-variables
+[jobenv]: ../../ci/variables/README.md#predefined-environment-variables
[2fa]: ../profile/account/two_factor_authentication.md
[pat]: ../profile/personal_access_tokens.md
diff --git a/doc/user/project/operations/error_tracking.md b/doc/user/project/operations/error_tracking.md
new file mode 100644
index 00000000000..1b319c5641c
--- /dev/null
+++ b/doc/user/project/operations/error_tracking.md
@@ -0,0 +1,41 @@
+# Error Tracking
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/169) in GitLab 11.8.
+
+Error tracking allows developers to easily discover and view the errors that their application may be generating. By surfacing error information where the code is being developed, efficiency and awareness can be increased.
+
+## Sentry error tracking
+
+[Sentry](https://sentry.io/) is an open source error tracking system. GitLab allows administrators to connect Sentry to GitLab, to allow users to view a list of Sentry errors in GitLab itself.
+
+### Deploying Sentry
+
+You may sign up to the cloud hosted <https://sentry.io> or deploy your own [on-premise instance](https://docs.sentry.io/server/installation/).
+
+### Enabling Sentry
+
+NOTE: **Note:**
+You will need at least Maintainer [permissions](../../permissions.md) to enable the Sentry integration.
+
+GitLab provides an easy way to connect Sentry to your project:
+
+1. Sign up to Sentry.io or [deploy your own](#deploying-sentry) Sentry instance.
+1. [Find or generate](https://docs.sentry.io/api/auth/) a Sentry auth token for your Sentry project.
+ Make sure to give the token at least the following scopes: `event:read` and `project:read`.
+1. Navigate to your project’s **Settings > Operations**.
+1. Ensure that the **Active** checkbox is set.
+1. In the **Sentry API URL** field, enter your Sentry hostname. For example, `https://sentry.example.com`.
+1. In the **Auth Token** field, enter the token you previously generated.
+1. Click the **Connect** button to test the connection to Sentry and populate the **Project** dropdown.
+1. From the **Project** dropdown, choose a Sentry project to link to your GitLab project.
+1. Click **Save changes** for the changes to take effect.
+1. You can now visit **Operations > Error Tracking** in your project's sidebar to [view a list](#error-tracking-list) of Sentry errors.
+
+## Error Tracking List
+
+NOTE: **Note:**
+You will need at least Reporter [permissions](../../permissions.md) to view the Error Tracking list.
+
+The Error Tracking list may be found at **Operations > Error Tracking** in your project's sidebar.
+
+![Error Tracking list](img/error_tracking_list.png)
diff --git a/doc/user/project/operations/img/error_tracking_list.png b/doc/user/project/operations/img/error_tracking_list.png
new file mode 100644
index 00000000000..aa0f9867fdb
--- /dev/null
+++ b/doc/user/project/operations/img/error_tracking_list.png
Binary files differ
diff --git a/doc/user/project/operations/index.md b/doc/user/project/operations/index.md
new file mode 100644
index 00000000000..b0f9936be5c
--- /dev/null
+++ b/doc/user/project/operations/index.md
@@ -0,0 +1,11 @@
+# Project operations
+
+GitLab provides a variety of tools to help operate and maintain
+your applications:
+
+- Collect [Prometheus metrics](../integrations/prometheus_library/index.md).
+- Deploy to different [environments](../../../ci/environments.md).
+- Connect your project to a [Kubernetes cluster](../clusters/index.md).
+- Discover and view errors generated by your applications with [Error Tracking](error_tracking.md).
+- Create, toggle, and remove [Feature Flags](https://docs.gitlab.com/ee/user/project/operations/feature_flags.html). **[PREMIUM]**
+- [Trace](https://docs.gitlab.com/ee/user/project/operations/tracing.html) the performance and health of a deployed application. **[ULTIMATE]**
diff --git a/doc/user/project/pages/getting_started_part_four.md b/doc/user/project/pages/getting_started_part_four.md
index e4ee2f7cdfa..05d5a2fd99a 100644
--- a/doc/user/project/pages/getting_started_part_four.md
+++ b/doc/user/project/pages/getting_started_part_four.md
@@ -376,11 +376,11 @@ manually in the past. Read through the
to understand how to go even further on your scripts.
- On this blog post, understand the concept of
-[using GitLab CI `environments` to deploy your
-web app to staging and production](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/).
+ [using GitLab CI `environments` to deploy your
+ web app to staging and production](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/).
- On this post, learn [how to run jobs sequentially,
-in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/)
+ in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/)
- On this blog post, we go through the process of
-[pulling specific directories from different projects](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)
-to deploy this website you're looking at, docs.gitlab.com.
+ [pulling specific directories from different projects](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)
+ to deploy this website you're looking at, docs.gitlab.com.
- On this blog post, we teach you [how to use GitLab Pages to produce a code coverage report](https://about.gitlab.com/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 290dfa5af84..f1e2771dcb9 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -59,7 +59,7 @@ which is highly recommendable and much faster than hardcoding.
If you set up a GitLab Pages project on GitLab.com,
it will automatically be accessible under a
-[subdomain of `namespace.gitlab.io`](introduction.md#gitlab-pages-on-gitlab-com).
+[subdomain of `namespace.gitlab.io`](introduction.md#gitlab-pages-on-gitlabcom).
The `namespace` is defined by your username on GitLab.com,
or the group name you created this project under.
@@ -77,37 +77,41 @@ Learn more about [namespaces](../../group/index.md#namespaces).
#### Project Websites
- You created a project called `blog` under your username `john`,
-therefore your project URL is `https://gitlab.com/john/blog/`.
-Once you enable GitLab Pages for this project, and build your site,
-it will be available under `https://john.gitlab.io/blog/`.
+ therefore your project URL is `https://gitlab.com/john/blog/`.
+ Once you enable GitLab Pages for this project, and build your site,
+ it will be available under `https://john.gitlab.io/blog/`.
- You created a group for all your websites called `websites`,
-and a project within this group is called `blog`. Your project
-URL is `https://gitlab.com/websites/blog/`. Once you enable
-GitLab Pages for this project, the site will live under
-`https://websites.gitlab.io/blog/`.
+ and a project within this group is called `blog`. Your project
+ URL is `https://gitlab.com/websites/blog/`. Once you enable
+ GitLab Pages for this project, the site will live under
+ `https://websites.gitlab.io/blog/`.
+- You created a group for your engineering department called `engineering`,
+ a subgroup for all your documentation websites called `docs`,
+ and a project within this subgroup is called `workflows`. Your project
+ URL is `https://gitlab.com/engineering/docs/workflows/`. Once you enable
+ GitLab Pages for this project, the site will live under
+ `https://engineering.gitlab.io/docs/workflows`.
#### User and Group Websites
- Under your username, `john`, you created a project called
-`john.gitlab.io`. Your project URL will be `https://gitlab.com/john/john.gitlab.io`.
-Once you enable GitLab Pages for your project, your website
-will be published under `https://john.gitlab.io`.
+ `john.gitlab.io`. Your project URL will be `https://gitlab.com/john/john.gitlab.io`.
+ Once you enable GitLab Pages for your project, your website
+ will be published under `https://john.gitlab.io`.
- Under your group `websites`, you created a project called
-`websites.gitlab.io`. your project's URL will be `https://gitlab.com/websites/websites.gitlab.io`.
-Once you enable GitLab Pages for your project,
-your website will be published under `https://websites.gitlab.io`.
+ `websites.gitlab.io`. your project's URL will be `https://gitlab.com/websites/websites.gitlab.io`.
+ Once you enable GitLab Pages for your project,
+ your website will be published under `https://websites.gitlab.io`.
->**Note:**
-GitLab Pages [does **not** support subgroups](../../group/subgroups/index.md#limitations).
-You can only create the highest level group website.
+> Support for subgroup project's websites was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/30548) in GitLab 11.8.
**General example:**
- On GitLab.com, a project site will always be available under
-`https://namespace.gitlab.io/project-name`
+ `https://namespace.gitlab.io/project-name`
- On GitLab.com, a user or group website will be available under
-`https://namespace.gitlab.io/`
+ `https://namespace.gitlab.io/`
- On your GitLab instance, replace `gitlab.io` above with your
-Pages server domain. Ask your sysadmin for this information.
+ Pages server domain. Ask your sysadmin for this information.
_Read on about [Projects for GitLab Pages and URL structure](getting_started_part_two.md)._
diff --git a/doc/user/project/pages/getting_started_part_three.md b/doc/user/project/pages/getting_started_part_three.md
index cea9628966d..756b8b698c7 100644
--- a/doc/user/project/pages/getting_started_part_three.md
+++ b/doc/user/project/pages/getting_started_part_three.md
@@ -19,14 +19,14 @@ To use one or more custom domain with your Pages site, there are two things
you should consider first, which we'll cover in this guide:
1. Either if you're adding a **root domain** or a **subdomain**, for which
-you'll need to set up [DNS records](#dns-records)
-1. Whether you want to add an [SSL/TLS certificate](#ssl-tls-certificates) or not
+ you'll need to set up [DNS records](#dns-records)
+1. Whether you want to add an [SSL/TLS certificate](#ssltls-certificates) or not
To finish the association, you need to [add your domain to your project's Pages settings](#add-your-custom-domain-to-gitlab-pages-settings).
Let's start from the beginning with [DNS records](#dns-records).
If you already know how they work and want to skip the introduction to DNS,
-you may be interested in skipping it until the [TL;DR](#tl-dr) section below.
+you may be interested in skipping it until the [TL;DR](#tldr) section below.
### DNS Records
@@ -79,11 +79,14 @@ running on your instance).
![DNS A record pointing to GitLab.com Pages server](img/dns_add_new_a_record_example_updated_2018.png)
-NOTE: **Note:**
-Note that if you use your root domain for your GitLab Pages website **only**, and if
-your domain registrar supports this feature, you can add a DNS apex `CNAME`
-record instead of an `A` record. The main advantage of doing so is that when GitLab Pages
-IP on GitLab.com changes for whatever reason, you don't need to update your `A` record.
+CAUTION: **Caution:**
+Note that if you use your root domain for your GitLab Pages website
+**only**, and if your domain registrar supports this feature, you can
+add a DNS apex `CNAME` record instead of an `A` record. The main
+advantage of doing so is that when GitLab Pages IP on GitLab.com
+changes for whatever reason, you don't need to update your `A` record.
+There may be a few exceptions, but **this method is not recommended**
+as it most likely won't work if you set an `MX` record for your root domain.
#### DNS CNAME record
@@ -114,14 +117,16 @@ co-exist, so you need to place the TXT record in a special subdomain of its own.
#### TL;DR
-If the domain has multiple uses (e.g., you host email on it as well):
+For root domains (`domain.com`), set a DNS `A` record and verify your
+domain's ownership with a TXT record:
| From | DNS Record | To |
| ---- | ---------- | -- |
| domain.com | A | 35.185.44.232 |
| domain.com | TXT | gitlab-pages-verification-code=00112233445566778899aabbccddeeff |
-If the domain is dedicated to GitLab Pages use and no other services run on it:
+For subdomains (`subdomain.domain.com`), set a DNS `CNAME` record and
+verify your domain's ownership with a TXT record:
| From | DNS Record | To |
| ---- | ---------- | -- |
@@ -131,19 +136,19 @@ If the domain is dedicated to GitLab Pages use and no other services run on it:
> **Notes**:
>
> - **Do not** use a CNAME record if you want to point your
-`domain.com` to your GitLab Pages site. Use an `A` record instead.
+ `domain.com` to your GitLab Pages site. Use an `A` record instead.
> - **Do not** add any special chars after the default Pages
-domain. E.g., **do not** point your `subdomain.domain.com` to
-`namespace.gitlab.io.` or `namespace.gitlab.io/`.
+ domain. E.g., **do not** point your `subdomain.domain.com` to
+ `namespace.gitlab.io.` or `namespace.gitlab.io/`.
> - GitLab Pages IP on GitLab.com [was changed](https://about.gitlab.com/2017/03/06/we-are-changing-the-ip-of-gitlab-pages-on-gitlab-com/) in 2017
> - GitLab Pages IP on GitLab.com [has been changed](https://about.gitlab.com/2018/07/19/gcp-move-update/#gitlab-pages-and-custom-domains)
-from `52.167.214.135` to `35.185.44.232` in 2018
+ from `52.167.214.135` to `35.185.44.232` in 2018
### Add your custom domain to GitLab Pages settings
Once you've set the DNS record, you'll need navigate to your project's
**Setting > Pages** and click **+ New domain** to add your custom domain to
-GitLab Pages. You can choose whether to add an [SSL/TLS certificate](#ssl-tls-certificates)
+GitLab Pages. You can choose whether to add an [SSL/TLS certificate](#ssltls-certificates)
to make your website accessible under HTTPS or leave it blank. If don't add a certificate,
your site will be accessible only via HTTP:
@@ -264,7 +269,7 @@ your Pages project are the same.
1. A PEM certificate
1. An intermediate certificate
-1. A public key
+1. A private key
![Pages project - adding certificates](img/add_certificate_to_pages.png)
@@ -273,15 +278,15 @@ These fields are found under your **Project**'s **Settings** > **Pages** > **New
### What's what?
- A PEM certificate is the certificate generated by the CA,
-which needs to be added to the field **Certificate (PEM)**.
+ which needs to be added to the field **Certificate (PEM)**.
- An [intermediate certificate](https://en.wikipedia.org/wiki/Intermediate_certificate_authority) (aka "root certificate") is
-the part of the encryption keychain that identifies the CA.
-Usually it's combined with the PEM certificate, but there are
-some cases in which you need to add them manually.
-[CloudFlare certs](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/)
-are one of these cases.
-- A public key is an encrypted key which validates
-your PEM against your domain.
+ the part of the encryption keychain that identifies the CA.
+ Usually it's combined with the PEM certificate, but there are
+ some cases in which you need to add them manually.
+ [CloudFlare certs](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/)
+ are one of these cases.
+- A private key is an encrypted key which validates
+ your PEM against your domain.
### Now what?
@@ -290,10 +295,10 @@ of this, it's simple:
- Your PEM certificate needs to be added to the first field
- If your certificate is missing its intermediate, copy
-and paste the root certificate (usually available from your CA website)
-and paste it in the [same field as your PEM certificate](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/),
-just jumping a line between them.
-- Copy your public key and paste it in the last field
+ and paste the root certificate (usually available from your CA website)
+ and paste it in the [same field as your PEM certificate](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/),
+ just jumping a line between them.
+- Copy your private key and paste it in the last field
>**Note:**
**Do not** open certificates or encryption keys in
diff --git a/doc/user/project/pages/getting_started_part_two.md b/doc/user/project/pages/getting_started_part_two.md
index b0560c2f44c..644a1c951d3 100644
--- a/doc/user/project/pages/getting_started_part_two.md
+++ b/doc/user/project/pages/getting_started_part_two.md
@@ -16,7 +16,7 @@ To get started with GitLab Pages, you need:
1. A project
1. A configuration file (`.gitlab-ci.yml`) to deploy your site
1. A specific `job` called `pages` in the configuration file
-that will make GitLab aware that you are deploying a GitLab Pages website
+ that will make GitLab aware that you are deploying a GitLab Pages website
1. A `public` directory with the content of the website
Optional Features:
@@ -31,12 +31,26 @@ The optional settings, custom domain, DNS records, and SSL/TLS certificates, are
## Project
Your GitLab Pages project is a regular project created the
-same way you do for the other ones. To get started with GitLab Pages, you have two ways:
+same way you do for the other ones. To get started with GitLab Pages, you have three ways:
+- Use one of the popular templates already in the app,
- Fork one of the templates from Page Examples, or
- Create a new project from scratch
-Let's go over both options.
+Let's go over each option.
+
+### Use one of the popular Pages templates bundled with GitLab
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/47857)
+in GitLab 11.8.
+
+The simplest way to create a GitLab Pages site is to use one of the most
+popular templates, which come already bundled and ready to go. To use one
+of these templates:
+
+1. From the top navigation, click the **+** button and select **New project**
+1. Select **Create from Template**
+1. Choose one of the templates starting with **Pages**
### Fork a project to get started from
@@ -57,7 +71,7 @@ created for the steps below.
To turn a **project website** forked from the Pages group into a **user/group** website, you'll need to:
- Rename it to `namespace.gitlab.io`: navigate to project's **Settings** > expand **Advanced settings** > and scroll down to **Rename repository**
-- Adjust your SSG's [base URL](#urls-and-baseurls) to from `"project-name"` to `""`. This setting will be at a different place for each SSG, as each of them have their own structure and file tree. Most likely, it will be in the SSG's config file.
+- Adjust your SSG's [base URL](#urls-and-baseurls) from `"project-name"` to `""`. This setting will be at a different place for each SSG, as each of them have their own structure and file tree. Most likely, it will be in the SSG's config file.
> **Notes:**
>
@@ -71,16 +85,16 @@ is useful for submitting merge requests to the upstream.
### Create a project from scratch
1. From your **Project**'s **[Dashboard](https://gitlab.com/dashboard/projects)**,
-click **New project**, and name it considering the
-[practical examples](getting_started_part_one.md#practical-examples).
+ click **New project**, and name it considering the
+ [practical examples](getting_started_part_one.md#practical-examples).
1. Clone it to your local computer, add your website
-files to your project, add, commit and push to GitLab.
+ files to your project, add, commit and push to GitLab.
1. From the your **Project**'s page, click **Set up CI/CD**:
![setup GitLab CI/CD](img/setup_ci.png)
1. Choose one of the templates from the dropbox menu.
-Pick up the template corresponding to the SSG you're using (or plain HTML).
+ Pick up the template corresponding to the SSG you're using (or plain HTML).
![gitlab-ci templates](img/choose_ci_template.png)
@@ -93,20 +107,20 @@ where you'll find its default URL.
> **Notes:**
>
> - GitLab Pages [supports any SSG](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/), but,
-if you don't find yours among the templates, you'll need
-to configure your own `.gitlab-ci.yml`. To do that, please
-read through the article [Creating and Tweaking GitLab CI/CD for GitLab Pages](getting_started_part_four.md). New SSGs are very welcome among
-the [example projects](https://gitlab.com/pages). If you set
-up a new one, please
-[contribute](https://gitlab.com/pages/pages.gitlab.io/blob/master/CONTRIBUTING.md)
-to our examples.
+ if you don't find yours among the templates, you'll need
+ to configure your own `.gitlab-ci.yml`. To do that, please
+ read through the article [Creating and Tweaking GitLab CI/CD for GitLab Pages](getting_started_part_four.md). New SSGs are very welcome among
+ the [example projects](https://gitlab.com/pages). If you set
+ up a new one, please
+ [contribute](https://gitlab.com/pages/pages.gitlab.io/blob/master/CONTRIBUTING.md)
+ to our examples.
>
> - The second step _"Clone it to your local computer"_, can be done
-differently, achieving the same results: instead of cloning the bare
-repository to you local computer and moving your site files into it,
-you can run `git init` in your local website directory, add the
-remote URL: `git remote add origin git@gitlab.com:namespace/project-name.git`,
-then add, commit, and push.
+ differently, achieving the same results: instead of cloning the bare
+ repository to you local computer and moving your site files into it,
+ you can run `git init` in your local website directory, add the
+ remote URL: `git remote add origin git@gitlab.com:namespace/project-name.git`,
+ then add, commit, and push.
## URLs and Baseurls
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index ce4fccdaff3..ee471fa6534 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -66,7 +66,7 @@ publish any website written directly in plain HTML, CSS, and JavaScript.</p>
If you're using GitLab.com, your website will be publicly available to the internet.
If you're using self-managed instances (Core, Starter, Premium, or Ultimate),
your websites will be published on your own server, according to the
-[Pages admin settings](../../../administration/pages/index.md) chosen by your sysdamin,
+[Pages admin settings](../../../administration/pages/index.md) chosen by your sysadmin,
who can opt for making them public or internal to your server.
### How it works
@@ -91,13 +91,13 @@ site under the HTTPS protocol.
## Getting started
-To get started with GitLab Pages, you can either [create a project from scratch](getting_started_part_two.md#create-a-project-from-scratch)
-or quickly start from copying an existing example project, as follows:
+To get started with GitLab Pages, you can either [create a project from scratch](getting_started_part_two.md#create-a-project-from-scratch),
+use a [bundled template](getting_started_part_two.md#use-one-of-the-popular-pages-templates-bundled-with-gitlab), or copy any of our existing example projects:
1. Choose an [example project](https://gitlab.com/pages) to [fork](../../../gitlab-basics/fork-project.md#how-to-fork-a-project):
by forking a project, you create a copy of the codebase you're forking from to start from a template instead of starting from scratch.
1. From the left sidebar, navigate to your project's **CI/CD > Pipelines** and click
-**Run pipeline** so that GitLab CI/CD will build and deploy your site to the server.
+ **Run pipeline** so that GitLab CI/CD will build and deploy your site to the server.
1. Once the pipeline has finished successfully, find the link to visit your website from your
project's **Settings > Pages**.
@@ -141,7 +141,7 @@ You can also take some optional further steps:
_Advanced options:_
- [Use a custom domain](getting_started_part_three.md#adding-your-custom-domain-to-gitlab-pages)
-- Apply [SSL/TLS certification](getting_started_part_three.md#ssl-tls-certificates) to your custom domain
+- Apply [SSL/TLS certification](getting_started_part_three.md#ssltls-certificates) to your custom domain
## Explore GitLab Pages
@@ -164,7 +164,7 @@ with Pages, read through this series:
### GitLab Pages with SSL/TLS certificates
-If you're using GitLab Pages default domain (`.gitlab.io`), your website will be
+If you're using GitLab Pages default domain (`.gitlab.io`), your website will be
automatically secure and available under HTTPS. If you're using your own domain, you can
optionally secure it with SSL/TLS certificates. You can read the following
tutorials to learn how to use these third-party certificates with GitLab Pages:
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index ed049e2e648..6bb58689f38 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -11,7 +11,7 @@ With GitLab Pages you can host for free your static websites on GitLab.
Combined with the power of [GitLab CI] and the help of [GitLab Runner] you can
deploy static pages for your individual projects, your user or your group.
-Read [GitLab Pages on GitLab.com](#gitlab-pages-on-gitlab-com) for specific
+Read [GitLab Pages on GitLab.com](#gitlab-pages-on-gitlabcom) for specific
information, if you are using GitLab.com to host your website.
## Getting started with GitLab Pages domains
@@ -38,6 +38,7 @@ be served on.
| Group pages | `groupname.example.io` | `http(s)://groupname.example.io` |
| Project pages owned by a user | `projectname` | `http(s)://username.example.io/projectname` |
| Project pages owned by a group | `projectname` | `http(s)://groupname.example.io/projectname`|
+| Project pages owned by a subgroup | `subgroup/projectname` | `http(s)://groupname.example.io/subgroup/projectname`|
> **Warning:**
> There are some known [limitations](#limitations) regarding namespaces served
@@ -150,7 +151,7 @@ Depending on how you plan to publish your website, the steps defined in the
Be aware that Pages are by default branch/tag agnostic and their deployment
relies solely on what you specify in `.gitlab-ci.yml`. If you don't limit the
-`pages` job with the [`only` parameter](../../../ci/yaml/README.md#only-and-except),
+`pages` job with the [`only` parameter](../../../ci/yaml/README.md#only-and-except-simplified),
whenever a new commit is pushed to whatever branch or tag, the Pages will be
overwritten. In the example below, we limit the Pages to be deployed whenever
a commit is pushed only on the `master` branch:
@@ -177,7 +178,7 @@ Supposed your repository contained the following files:
```
├── index.html
├── css
-│   └── main.css
+│ └── main.css
└── js
└── main.js
```
@@ -251,7 +252,7 @@ get you started.
Remember that GitLab Pages are by default branch/tag agnostic and their
deployment relies solely on what you specify in `.gitlab-ci.yml`. You can limit
-the `pages` job with the [`only` parameter](../../../ci/yaml/README.md#only-and-except),
+the `pages` job with the [`only` parameter](../../../ci/yaml/README.md#only-and-except-simplified),
whenever a new commit is pushed to a branch that will be used specifically for
your pages.
@@ -332,7 +333,7 @@ public/
│ └ index.html.gz
│
├── css/
-│   └─┬ main.css
+│ └─┬ main.css
│ └ main.css.gz
│
└── js/
@@ -347,18 +348,69 @@ This can be achieved by including a `script:` command like this in your
pages:
# Other directives
script:
- - # build the public/ directory first
- - find public -type f -iregex '.*\.\(htm\|html\|txt\|text\|js\|css\)$' -execdir gzip -f --keep {} \;
+ # Build the public/ directory first
+ - find public -type f -regex '.*\.\(htm\|html\|txt\|text\|js\|css\)$' -exec gzip -f -k {} \;
```
By pre-compressing the files and including both versions in the artifact, Pages
can serve requests for both compressed and uncompressed content without
needing to compress files on-demand.
+### Resolving ambiguous URLs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/issues/95) in GitLab 11.8
+
+GitLab Pages makes assumptions about which files to serve when receiving a
+request for a URL that does not include an extension.
+
+Consider a Pages site deployed with the following files:
+
+```
+public/
+├─┬ index.html
+│ ├ data.html
+│ └ info.html
+│
+├── data/
+│ └── index.html
+├── info/
+│ └── details.html
+└── other/
+ └── index.html
+```
+
+Pages supports reaching each of these files through several different URLs. In
+particular, it will always look for an `index.html` file if the URL only
+specifies the directory. If the URL references a file that doesn't exist, but
+adding `.html` to the URL leads to a file that *does* exist, it will be served
+instead. Here are some examples of what will happen given the above Pages site:
+
+| URL path | HTTP response | File served |
+| -------------------- | ------------- | ----------- |
+| `/` | `200 OK` | `public/index.html` |
+| `/index.html` | `200 OK` | `public/index.html` |
+| `/index` | `200 OK` | `public/index.html` |
+| `/data` | `200 OK` | `public/data/index.html` |
+| `/data/` | `200 OK` | `public/data/index.html` |
+| `/data.html` | `200 OK` | `public/data.html` |
+| `/info` | `200 OK` | `public/info.html` |
+| `/info/` | `200 OK` | `public/info.html` |
+| `/info.html` | `200 OK` | `public/info.html` |
+| `/info/details` | `200 OK` | `public/info/details.html` |
+| `/info/details.html` | `200 OK` | `public/info/details.html` |
+| `/other` | `302 Found` | `public/other/index.html` |
+| `/other/` | `200 OK` | `public/other/index.html` |
+| `/other/index` | `200 OK` | `public/other/index.html` |
+| `/other/index.html` | `200 OK` | `public/other/index.html` |
+
+NOTE: **Note:**
+When `public/data/index.html` exists, it takes priority over the `public/data.html`
+file for both the `/data` and `/data/` URL paths.
+
### Add a custom domain to your Pages website
For a complete guide on Pages domains, read through the article
-[GitLab Pages from A to Z: Part 3 - Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md#setting-up-custom-domains-dns-records-and-ssl-tls-certificates)
+[GitLab Pages from A to Z: Part 3 - GitLab Pages custom domains and SSL/TLS Certificates](getting_started_part_three.md)
If this setting is enabled by your GitLab administrator, you should be able to
see the **New Domain** button when visiting your project's settings through the
@@ -399,7 +451,7 @@ private key when adding a new domain.
![Pages upload cert](img/pages_upload_cert.png)
For a complete guide on Pages domains, read through the article
-[GitLab Pages from A to Z: Part 3 - Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md#setting-up-custom-domains-dns-records-and-ssl-tls-certificates)
+[GitLab Pages from A to Z: Part 3 - GitLab Pages custom domains and SSL/TLS Certificates](getting_started_part_three.md)
### Custom error codes pages
@@ -494,8 +546,8 @@ don't redirect HTTP to HTTPS.
[rfc]: https://tools.ietf.org/html/rfc2818#section-3.1 "HTTP Over TLS RFC"
-GitLab Pages [does **not** support subgroups](../../group/subgroups/index.md#limitations).
-You can only create the highest level group website.
+GitLab Pages [does **not** support group websites for subgroups](../../group/subgroups/index.md#limitations).
+You can only create the highest-level group website.
## Redirects in GitLab Pages
diff --git a/doc/user/project/pipelines/job_artifacts.md b/doc/user/project/pipelines/job_artifacts.md
index a8b47558c99..8b57129c9e1 100644
--- a/doc/user/project/pipelines/job_artifacts.md
+++ b/doc/user/project/pipelines/job_artifacts.md
@@ -38,8 +38,9 @@ turn are defined with the `paths` keyword. All paths to files and directories
are relative to the repository that was cloned during the build. These uploaded
artifacts will be kept in GitLab for 1 week as defined by the `expire_in`
definition. You have the option to keep the artifacts from expiring via the
-[web interface](#browsing-job-artifacts). If you don't define an expiry date,
-the artifacts will be kept forever.
+[web interface](#browsing-artifacts). If the expiry time is not defined,
+it defaults to the [instance wide
+setting](../../admin_area/settings/continuous_integration.md#default-artifacts-expiration-core-only).
For more examples on artifacts, follow the [artifacts reference in
`.gitlab-ci.yml`](../../../ci/yaml/README.md#artifacts).
@@ -190,5 +191,9 @@ artifacts and the job's trace.
1. Click the trash icon at the top right of the job's trace.
1. Confirm the deletion.
-[expiry date]: ../../../ci/yaml/README.md#artifacts-expire_in
-[ce-14399]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14399
+## Retrieve artifacts of private projects when using GitLab CI
+
+In order to retrieve a job artifact of a different project, you might need to use a private token in order to [authenticate and download](../../../api/jobs.md#get-job-artifacts) the artifacts.
+
+[expiry date]: ../../../ci/yaml/README.md#artifactsexpire_in
+[ce-14399]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14399 \ No newline at end of file
diff --git a/doc/user/project/pipelines/schedules.md b/doc/user/project/pipelines/schedules.md
index 051277dfe02..58a0fbc97cd 100644
--- a/doc/user/project/pipelines/schedules.md
+++ b/doc/user/project/pipelines/schedules.md
@@ -1,9 +1,9 @@
-# Pipeline Schedules
+# Pipeline schedules
> **Notes**:
> - This feature was introduced in 9.1 as [Trigger Schedule][ce-10533].
> - In 9.2, the feature was [renamed to Pipeline Schedule][ce-10853].
-> - Cron notation is parsed by [Rufus-Scheduler](https://github.com/jmettraux/rufus-scheduler).
+> - Cron notation is parsed by [Fugit](https://github.com/floraison/fugit).
Pipeline schedules can be used to run a pipeline at specific intervals, for example every
month on the 22nd for a certain branch.
diff --git a/doc/user/project/pipelines/settings.md b/doc/user/project/pipelines/settings.md
index 15eacc48dfe..4a989afad4d 100644
--- a/doc/user/project/pipelines/settings.md
+++ b/doc/user/project/pipelines/settings.md
@@ -1,7 +1,7 @@
# Pipelines settings
To reach the pipelines settings navigate to your project's
-**Settings âž” CI/CD**.
+**Settings > CI/CD**.
The following settings can be configured per project.
@@ -10,33 +10,34 @@ The following settings can be configured per project.
With Git strategy, you can choose the default way your repository is fetched
from GitLab in a job.
-There are two options:
+There are two options. Using:
-- Using `git clone` which is slower since it clones the repository from scratch
+- `git clone`, which is slower since it clones the repository from scratch
for every job, ensuring that the project workspace is always pristine.
-- Using `git fetch` which is faster as it re-uses the project workspace (falling
+- `git fetch`, which is faster as it re-uses the project workspace (falling
back to clone if it doesn't exist).
-The default Git strategy can be overridden by the [GIT_STRATEGY variable][var]
+The default Git strategy can be overridden by the [GIT_STRATEGY variable](../../../ci/yaml/README.md#git-strategy)
in `.gitlab-ci.yml`.
## Timeout
Timeout defines the maximum amount of time in minutes that a job is able run.
+This is configurable under your project's **Settings > CI/CD > General pipelines settings**.
The default value is 60 minutes. Decrease the time limit if you want to impose
a hard limit on your jobs' running time or increase it otherwise. In any case,
if the job surpasses the threshold, it is marked as failed.
### Timeout overriding on Runner level
-> - [Introduced][ce-17221] in GitLab 10.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17221) in GitLab 10.7.
Project defined timeout (either specific timeout set by user or the default
-60 minutes timeout) may be [overridden on Runner level][timeout overriding].
+60 minutes timeout) may be [overridden on Runner level](../../../ci/runners/README.html#setting-maximum-job-timeout-for-a-runner).
## Custom CI config path
-> - [Introduced][ce-12509] in GitLab 9.4.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12509) in GitLab 9.4.
By default we look for the `.gitlab-ci.yml` file in the project's root
directory. If you require a different location **within** the repository,
@@ -45,10 +46,10 @@ this filepath should be **relative** to the root.
Here are some valid examples:
-> * .gitlab-ci.yml
-> * .my-custom-file.yml
-> * my/path/.gitlab-ci.yml
-> * my/path/.my-custom-file.yml
+- `.gitlab-ci.yml`
+- `.my-custom-file.yml`
+- `my/path/.gitlab-ci.yml`
+- `my/path/.my-custom-file.yml`
## Test coverage parsing
@@ -59,7 +60,7 @@ job log using a regular expression. In the pipelines settings, search for the
![Pipelines settings test coverage](img/pipelines_settings_test_coverage.png)
Leave blank if you want to disable it or enter a ruby regular expression. You
-can use http://rubular.com to test your regex.
+can use <http://rubular.com> to test your regex.
If the pipeline succeeds, the coverage is shown in the merge request widget and
in the jobs table.
@@ -79,28 +80,28 @@ project setting under your project's **Settings > CI/CD > General pipelines sett
If **Public pipelines** is enabled (default):
-- for **public** projects, anyone can view the pipelines and access the job details
- (output logs and artifacts)
-- for **internal** projects, any logged in user can view the pipelines
+- For **public** projects, anyone can view the pipelines and access the job details
+ (output logs and artifacts).
+- For **internal** projects, any logged in user can view the pipelines
and access the job details
- (output logs and artifacts)
-- for **private** projects, any member (guest or higher) can view the pipelines
+ (output logs and artifacts).
+- For **private** projects, any member (guest or higher) can view the pipelines
and access the job details
- (output logs and artifacts)
+ (output logs and artifacts).
If **Public pipelines** is disabled:
-- for **public** projects, anyone can view the pipelines, but only members
- (reporter or higher) can access the job details (output logs and artifacts)
-- for **internal** projects, any logged in user can view the pipelines,
- but only members (reporter or higher) can access the job details (output logs
- and artifacts)
-- for **private** projects, only members (reporter or higher)
- can view the pipelines and access the job details (output logs and artifacts)
+- For **public** projects, anyone can view the pipelines, but only members
+ (reporter or higher) can access the job details (output logs and artifacts).
+- For **internal** projects, any logged in user can view the pipelines.
+ However, only members (reporter or higher) can access the job details (output logs
+ and artifacts).
+- For **private** projects, only members (reporter or higher)
+ can view the pipelines and access the job details (output logs and artifacts).
## Auto-cancel pending pipelines
-> [Introduced][ce-9362] in GitLab 9.1.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9362) in GitLab 9.1.
If you want to auto-cancel all pending non-HEAD pipelines on branch, when
new pipeline will be created (after your git push or manually from UI),
@@ -132,19 +133,19 @@ Depending on the status of your job, a badge can have the following values:
You can access a pipeline status badge image using the following link:
-```
-https://example.gitlab.com/<namespace>/<project>/badges/<branch>/build.svg
+```text
+https://example.gitlab.com/<namespace>/<project>/badges/<branch>/pipeline.svg
```
### Test coverage report badge
-GitLab makes it possible to define the regular expression for [coverage report],
+GitLab makes it possible to define the regular expression for [coverage report](#test-coverage-parsing),
that each job log will be matched against. This means that each job in the
pipeline can have the test coverage percentage value defined.
The test coverage badge can be accessed using following link:
-```
+```text
https://example.gitlab.com/<namespace>/<project>/badges/<branch>/coverage.svg
```
@@ -157,13 +158,28 @@ into your `README.md`:
![coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage)
```
-### Environment Variables
+### Badge styles
-[Environment variables](../../../ci/variables/README.html#variables) can be set in an environment to be available to a runner.
+Pipeline badges can be rendered in different styles by adding the `style=style_name` parameter to the URL. Currently two styles are available:
+
+#### Flat (default)
+
+```text
+https://example.gitlab.com/<namespace>/<project>/badges/<branch>/coverage.svg?style=flat
+```
+
+![Badge flat style](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage&style=flat)
-[var]: ../../../ci/yaml/README.md#git-strategy
-[coverage report]: #test-coverage-parsing
-[timeout overriding]: ../../../ci/runners/README.html#setting-maximum-job-timeout-for-a-runner
-[ce-9362]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9362
-[ce-12509]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12509
-[ce-17221]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17221
+#### Flat square
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/30120) in GitLab 11.8.
+
+```text
+https://example.gitlab.com/<namespace>/<project>/badges/<branch>/coverage.svg?style=flat-square
+```
+
+![Badge flat square style](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage&style=flat-square)
+
+## Environment Variables
+
+[Environment variables](../../../ci/variables/README.html#variables) can be set in an environment to be available to a runner.
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index db706e5020e..3eb8123144f 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -10,7 +10,7 @@ created protected branches.
By default, a protected branch does four simple things:
- it prevents its creation, if not already created, from everybody except users
- with Maintainer permission
+ who are allowed to merge
- it prevents pushes from everybody except users with Maintainer permission
- it prevents **anyone** from force pushing to the branch
- it prevents **anyone** from deleting the branch
@@ -94,6 +94,25 @@ all matching branches:
![Protected branch matches](img/protected_branches_matches.png)
+## Creating a protected branch
+
+> [Introduced][https://gitlab.com/gitlab-org/gitlab-ce/issues/53361] in GitLab 11.9.
+
+When a protected branch or wildcard protected branches are set to
+[**No one** is **Allowed to push**](#using-the-allowed-to-merge-and-allowed-to-push-settings),
+Developers (and users with higher [permission levels](../permissions.md)) are allowed
+to create a new protected branch, but only via the UI or through the API (to avoid
+creating protected branches accidentally from the command line or from a Git
+client application).
+
+To create a new branch through the user interface:
+
+1. Visit **Repository > Branches**.
+1. Click on **New branch**.
+1. Fill in the branch name and select an existing branch, tag, or commit that
+ the new branch will be based off. Only existing protected branches and commits
+ that are already in protected branches will be accepted.
+
## Deleting a protected branch
> [Introduced][ce-21393] in GitLab 9.3.
@@ -125,6 +144,10 @@ for details about the pipelines security model.
## Changelog
+**11.9**
+
+- [Allow protected branches to be created](https://gitlab.com/gitlab-org/gitlab-ce/issues/53361) by Developers (and users with higher permission levels) through the API and the user interface.
+
**9.2**
- Allow deletion of protected branches via the web interface [gitlab-org/gitlab-ce#21393][ce-21393]
diff --git a/doc/user/project/protected_tags.md b/doc/user/project/protected_tags.md
index 3d8fff9f733..26bec323f02 100644
--- a/doc/user/project/protected_tags.md
+++ b/doc/user/project/protected_tags.md
@@ -10,7 +10,6 @@ This feature evolved out of [Protected Branches](protected_branches.md)
Protected tags will prevent anyone from updating or deleting the tag, as and will prevent creation of matching tags based on the permissions you have selected. By default, anyone without Maintainer permission will be prevented from creating tags.
-
## Configuring protected tags
To protect a tag, you need to have at least Maintainer permission level.
@@ -43,7 +42,6 @@ matching the wildcard. For example:
| `*gitlab*` | `gitlab`, `gitlab/v1` |
| `*` | `v1.0.1rc2`, `accidental-tag` |
-
Two different wildcards can potentially match the same tag. For example,
`*-stable` and `production-*` would both match a `production-stable` tag.
In that case, if _any_ of these protected tags have a setting like
@@ -54,7 +52,6 @@ all matching tags:
![Protected tag matches](img/protected_tag_matches.png)
-
---
[ce-10356]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10356 "Protected Tags"
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 85a03d125dd..392e72dcc5c 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -55,7 +55,6 @@ discussions, and descriptions:
| `/merge` | Merge (when pipeline succeeds) | | ✓ |
| `/create_merge_request <branch name>` | Create a new merge request starting from the current issue | ✓ | |
-
## Quick actions for commit messages
The following quick actions are applicable for commit messages:
diff --git a/doc/user/project/releases.md b/doc/user/project/releases.md
index 8dad4240c91..baa7a295273 100644
--- a/doc/user/project/releases.md
+++ b/doc/user/project/releases.md
@@ -1,12 +1,5 @@
-# Releases
+---
+redirect_to: 'releases/index.md'
+---
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41766) in GitLab 11.7.
-
-Releases mark specific points in a project's development history, communicate
-information about the type of change, and deliver on prepared, often compiled,
-versions of the software to be reused elsewhere. Currently, releases can only be
-created through the API.
-
-Navigate to **Project > Releases** in order to see the list of releases of a project.
-
-![Releases list](img/releases.png)
+This document was moved to [another location](releases/index.md).
diff --git a/doc/user/project/releases/img/releases.png b/doc/user/project/releases/img/releases.png
new file mode 100644
index 00000000000..f8b1b7305ad
--- /dev/null
+++ b/doc/user/project/releases/img/releases.png
Binary files differ
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
new file mode 100644
index 00000000000..00a4f6c6a6b
--- /dev/null
+++ b/doc/user/project/releases/index.md
@@ -0,0 +1,62 @@
+# Releases
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41766) in GitLab 11.7.
+
+It's typical to create a [Git tag](../../../university/training/topics/tags.md) at
+the moment of release to introduce a checkpoint in your source code
+history, but in most cases your users will need compiled objects or other
+assets output by your CI system to use them, not just the raw source
+code.
+
+GitLab's **Releases** are a way to track deliverables in your project. Consider them
+a snapshot in time of the source, build output, and other metadata or artifacts
+associated with a released version of your code.
+
+At the moment, you can create Release entries via the [Releases API](../../../api/releases/index.md);
+we recommend doing this as one of the last steps in your CI/CD release pipeline.
+
+## Getting started with Releases
+
+Start by giving a [description](#release-description) to the Release and
+including its [assets](#release-assets), as follows.
+
+### Release 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 will allow
+your users to quickly scan the differences between each one you publish.
+
+NOTE: **Note:**
+[Git's tagging messages](https://git-scm.com/book/en/v2/Git-Basics-Tagging) and
+Release descriptions are unrelated. Description supports [markdown](../../markdown.md).
+
+### Release assets
+
+You can currently add the following types of assets to each Release:
+
+- [Source code](#source-code): state of the repo at the time of the Release
+- [Links](#links): to content such as built binaries or documentation
+
+GitLab will support more asset types in the future, including objects such
+as pre-built packages, compliance/security evidence, or container images.
+
+#### Source code
+
+GitLab automatically generate `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.
+
+NOTE: **NOTE**
+You can manipulate links of each release entry with [Release Links API](../../../api/releases/links.md)
+
+## Releases list
+
+Navigate to **Project > Releases** in order to see the list of releases for a given
+project.
+
+![Releases list](img/releases.png)
diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md
index 783081cec26..13e4f2ce163 100644
--- a/doc/user/project/repository/branches/index.md
+++ b/doc/user/project/repository/branches/index.md
@@ -2,16 +2,17 @@
Read through GiLab's branching documentation:
-- [Create a branch](../web_editor.md#create-a-new-branch)
-- [Default branch](#default-branch)
-- [Protected branches](../../protected_branches.md#protected-branches)
-- [Delete merged branches](#delete-merged-branches)
-- [Branch filter search box](#branch-filter-search-box)
+- [Create a branch](../web_editor.md#create-a-new-branch).
+- [Default branch](#default-branch).
+- [Protected branches](../../protected_branches.md#protected-branches).
+- [Delete merged branches](#delete-merged-branches).
+- [Branch filter search box](#branch-filter-search-box).
See also:
-- [GitLab Flow](../../../../university/training/gitlab_flow.md#gitlab-flow): use the best of GitLab for your branching strategies
-- [Getting started with Git](../../../../topics/git/index.md) and GitLab
+- [Branches API](../../../../api/branches.md), for information on operating on repository branches using the GitLab API.
+- [GitLab Flow](../../../../university/training/gitlab_flow.md). Use the best of GitLab for your branching strategies.
+- [Getting started with Git](../../../../topics/git/index.md) and GitLab.
## Default branch
@@ -41,7 +42,6 @@ this operation.
It's particularly useful to clean up old branches that were not deleted
automatically when a merge request was merged.
-
## Branch filter search box
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22166) in GitLab 11.5.
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
index c6239c8e41c..6495ede42e0 100644
--- a/doc/user/project/repository/gpg_signed_commits/index.md
+++ b/doc/user/project/repository/gpg_signed_commits/index.md
@@ -4,7 +4,7 @@ NOTE: **Note:**
The term GPG is used for all OpenPGP/PGP/GPG related material and
implementations.
-> - [Introduced][ce-9546] in GitLab 9.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9546) in GitLab 9.5.
> - Subkeys support was added in GitLab 10.1.
GitLab can show whether a commit is verified or not when signed with a GPG key.
@@ -36,30 +36,22 @@ to be met:
## Generating a GPG key
-> **Notes:**
-> - If your Operating System has `gpg2` installed, replace `gpg` with `gpg2` in
-> the following commands.
-> - If Git is using `gpg` and you get errors like `secret key not available` or
-> `gpg: signing failed: secret key not available`, run the following command to
-> change to `gpg2`:
->
-> ```
-> git config --global gpg.program gpg2
-> ```
-
If you don't already have a GPG key, the following steps will help you get
started:
-1. [Install GPG](https://www.gnupg.org/download/index.html) for your operating system
-1. Generate the private/public key pair with the following command:
+1. [Install GPG](https://www.gnupg.org/download/index.html) for your operating system.
+ If your Operating System has `gpg2` installed, replace `gpg` with `gpg2` in
+ the following commands.
+1. Generate the private/public key pair with the following command, which will
+ spawn a series of questions:
```sh
gpg --full-gen-key
```
-
- _NOTE: In some cases like Gpg4win on Windows and other Mac OS versions the command here may be ` gpg --gen-key`_
- This will spawn a series of questions.
+ NOTE: **Note:**
+ In some cases like Gpg4win on Windows and other macOS versions, the command
+ here may be `gpg --gen-key`.
1. The first question is which algorithm can be used. Select the kind you want
or press <kbd>Enter</kbd> to choose the default (RSA and RSA):
@@ -109,10 +101,10 @@ started:
GnuPG needs to construct a user ID to identify your key.
Real name: Mr. Robot
- Email address: mr@robot.sh
+ Email address: <your_email>
Comment:
You selected this USER-ID:
- "Mr. Robot <mr@robot.sh>"
+ "Mr. Robot <your_email>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
```
@@ -121,10 +113,10 @@ started:
1. Use the following command to list the private GPG key you just created:
```
- gpg --list-secret-keys --keyid-format LONG mr@robot.sh
+ gpg --list-secret-keys --keyid-format LONG <your_email>
```
- Replace `mr@robot.sh` with the email address you entered above.
+ Replace `<your_email>` with the email address you entered above.
1. Copy the GPG key ID that starts with `sec`. In the following example, that's
`30F2B65B9246B6CA`:
@@ -132,7 +124,7 @@ started:
```
sec rsa4096/30F2B65B9246B6CA 2017-08-18 [SC]
D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA
- uid [ultimate] Mr. Robot <mr@robot.sh>
+ uid [ultimate] Mr. Robot <your_email>
ssb rsa4096/B7ABC0813E4028C0 2017-08-18 [E]
```
@@ -146,7 +138,7 @@ started:
## Adding a GPG key to your account
->**Note:**
+NOTE: **Note:**
Once you add a key, you cannot edit it, only remove it. In case the paste
didn't work, you'll have to remove the offending key and re-add it.
@@ -174,11 +166,11 @@ key to use.
1. Use the following command to list the private GPG key you just created:
- ```
- gpg --list-secret-keys --keyid-format LONG mr@robot.sh
+ ```sh
+ gpg --list-secret-keys --keyid-format LONG <your_email>
```
- Replace `mr@robot.sh` with the email address you entered above.
+ Replace `<your_email>` with the email address you entered above.
1. Copy the GPG key ID that starts with `sec`. In the following example, that's
`30F2B65B9246B6CA`:
@@ -186,18 +178,26 @@ key to use.
```
sec rsa4096/30F2B65B9246B6CA 2017-08-18 [SC]
D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA
- uid [ultimate] Mr. Robot <mr@robot.sh>
+ uid [ultimate] Mr. Robot <your_email>
ssb rsa4096/B7ABC0813E4028C0 2017-08-18 [E]
```
1. Tell Git to use that key to sign the commits:
- ```
+ ```sh
git config --global user.signingkey 30F2B65B9246B6CA
```
Replace `30F2B65B9246B6CA` with your GPG key ID.
+1. (Optional) If Git is using `gpg` and you get errors like `secret key not available`
+ or `gpg: signing failed: secret key not available`, run the following command to
+ change to `gpg2`:
+
+ ```sh
+ git config --global gpg.program gpg2
+ ```
+
## Signing commits
After you have [created your GPG key](#generating-a-gpg-key) and [added it to
@@ -261,4 +261,11 @@ To remove a GPG key from your account:
1. Navigate to the **GPG keys** tab.
1. Click on the trash icon besides the GPG key you want to delete.
-[ce-9546]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9546
+## Rejecting commits that are not signed **[PREMIUM]**
+
+You can configure your project to reject commits that aren't GPG-signed
+via [push rules](https://docs.gitlab.com/ee/push_rules/push_rules.html).
+
+## GPG signing API
+
+Learn how to [get the GPG signature from a commit via API](../../../../api/commits.md#get-gpg-signature-of-a-commit).
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index fac5975a0dc..22d912cd9d1 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -146,9 +146,9 @@ you are introducing those changes to your branch.
Via command line, you can commit multiple times before pushing.
- **Commit message:**
-A commit message is important to identity what is being changed and,
-more importantly, why. In GitLab, you can add keywords to the commit
-message that will perform one of the actions below:
+ A commit message is important to identity what is being changed and,
+ more importantly, why. In GitLab, you can add keywords to the commit
+ message that will perform one of the actions below:
- **Trigger a GitLab CI/CD pipeline:**
If you have your project configured with [GitLab CI/CD](../../../ci/README.md),
you will trigger a pipeline per push, not per commit.
@@ -162,14 +162,14 @@ message that will perform one of the actions below:
If you mention an issue or a merge request in a commit message, they will be shown
on their respective thread.
- **Cherry-pick a commit:**
-In GitLab, you can
-[cherry-pick a commit](../merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
-right from the UI.
+ In GitLab, you can
+ [cherry-pick a commit](../merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
+ right from the UI.
- **Revert a commit:**
-Easily [revert a commit](../merge_requests/revert_changes.md#reverting-a-commit)
-from the UI to a selected branch.
+ Easily [revert a commit](../merge_requests/revert_changes.md#reverting-a-commit)
+ from the UI to a selected branch.
- **Sign a commit:**
-Use GPG to [sign your commits](gpg_signed_commits/index.md).
+ Use GPG to [sign your commits](gpg_signed_commits/index.md).
## Repository size
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index 035028c9266..ce9d23bf911 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -33,13 +33,13 @@ easy for you.
![First file for your project](img/web_editor_template_dropdown_first_file.png)
-When clicking on either `LICENSE` or `.gitignore`, a dropdown will be displayed
+When clicking on either `LICENSE` or `.gitignore`, etc., a dropdown will be displayed
to provide you with a template which might be suitable for your project.
![MIT license selected](img/web_editor_template_dropdown_mit_license.png)
The license, changelog, contribution guide, or `.gitlab-ci.yml` file could also
-be added through a button on the project page. In the example below the license
+be added through a button on the project page. In the example below, the license
has already been created, which creates a link to the license itself.
![New file button](img/web_editor_template_dropdown_buttons.png)
@@ -112,7 +112,6 @@ screenshot above will yield a branch named
Since GitLab 9.0, when you click the `New branch` in an empty repository project, GitLab automatically creates the master branch, commits a blank `README.md` file to it and creates and redirects you to a new branch based on the issue title.
If your [project is already configured with a deployment service][project-services-doc] (e.g. Kubernetes), GitLab takes one step further and prompts you to set up [auto deploy][auto-deploy-doc] by helping you create a `.gitlab-ci.yml` file.
-
After the branch is created, you can edit files in the repository to fix
the issue. When a merge request is created based on the newly created branch,
the description field will automatically display the [issue closing pattern]
diff --git a/doc/user/project/settings/img/general_settings.png b/doc/user/project/settings/img/general_settings.png
index 96f5b84871f..4ff6fff5ca3 100644
--- a/doc/user/project/settings/img/general_settings.png
+++ b/doc/user/project/settings/img/general_settings.png
Binary files differ
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index cb68c9318bc..89008fd15b9 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -61,7 +61,7 @@ The following items will be exported:
- Project and wiki repositories
- Project uploads
-- Project configuration including web hooks and services
+- Project configuration, including services
- Issues with comments, merge requests with diffs and comments, labels, milestones, snippets,
and other project entities
- LFS objects
@@ -71,6 +71,7 @@ The following items will NOT be exported:
- Build traces and artifacts
- Container registry images
- CI variables
+- Webhooks
- Any encrypted tokens
## Exporting a project and its data
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index d6754372816..d5f4a7fd4ac 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -14,7 +14,7 @@ functionality of a project.
### General project settings
-Adjust your project's name, description, avatar, [default branch](../repository/branches/index.md#default-branch), and tags:
+Adjust your project's name, description, avatar, [default branch](../repository/branches/index.md#default-branch), and topics:
![general project settings](img/general_settings.png)
@@ -121,4 +121,10 @@ NOTE: **Note:**
GitLab administrators can use the admin interface to move any project to any
namespace if needed.
-[permissions]: ../../permissions.md##project-members-permissions
+[permissions]: ../../permissions.md#project-members-permissions
+
+## Operations settings
+
+### Error Tracking
+
+Configure Error Tracking to discover and view [Sentry errors within GitLab](../operations/error_tracking.md).
diff --git a/doc/user/project/slash_commands.md b/doc/user/project/slash_commands.md
index e9103a3f49c..1280524bc9b 100644
--- a/doc/user/project/slash_commands.md
+++ b/doc/user/project/slash_commands.md
@@ -1 +1,5 @@
+---
+redirect_to: 'quick_actions.md'
+---
+
This document was moved to [user/project/quick_actions.md](quick_actions.md).
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 55e53b865af..46a1b2bc3aa 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -3,8 +3,8 @@
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/4539) in [GitLab Ultimate][ee] 10.4.
> [Brought to GitLab Core](https://gitlab.com/gitlab-org/gitlab-ce/issues/44157) in 10.7.
-The Web IDE makes it faster and easier to contribute changes to your projects
-by providing an advanced editor with commit staging.
+The Web IDE editor makes it faster and easier to contribute changes to your
+projects by providing an advanced editor with commit staging.
## Open the Web IDE
@@ -22,23 +22,23 @@ searching. The file finder is launched using the keyboard shortcut `Command-p`,
`Control-p`, or `t` (when editor is not in focus). Type the filename or
file path fragments to start seeing results.
-## Syntax highligting
+## Syntax highlighting
-As expected from an IDE, syntax highlighting for many languages within
+As expected from an IDE, syntax highlighting for many languages within
the Web IDE will make your direct editing even easier.
The Web IDE currently provides:
-- Basic syntax colorization for a variety of programming, scripting and markup
-languages such as XML, PHP, C#, C++, Markdown, Java, VB, Batch, Python, Ruby
-and Objective-C.
-- IntelliSense and validation support (displaying errors and warnings, providing
-smart completions, formatting, and outlining) for some languages. For example:
-TypeScript, JavaScript, CSS, LESS, SCSS, JSON and HTML.
+- Basic syntax colorization for a variety of programming, scripting and markup
+ languages such as XML, PHP, C#, C++, Markdown, Java, VB, Batch, Python, Ruby
+ and Objective-C.
+- IntelliSense and validation support (displaying errors and warnings, providing
+ smart completions, formatting, and outlining) for some languages. For example:
+TypeScript, JavaScript, CSS, LESS, SCSS, JSON and HTML.
-Because the Web IDE is based on the [Monaco Editor](https://microsoft.github.io/monaco-editor/),
-you can find a more complete list of supported languages in the
-[Monaco languages](https://github.com/Microsoft/monaco-languages) repository.
+Because the Web IDE is based on the [Monaco Editor](https://microsoft.github.io/monaco-editor/),
+you can find a more complete list of supported languages in the
+[Monaco languages](https://github.com/Microsoft/monaco-languages) repository.
NOTE: **Note:**
Single file editing is based on the [Ace Editor](https://ace.c9.io).
@@ -47,10 +47,10 @@ Single file editing is based on the [Ace Editor](https://ace.c9.io).
After making your changes, click the Commit button in the bottom left to
review the list of changed files. Click on each file to review the changes and
-click the tick icon to stage the file.
+click the tick icon to stage the file.
Once you have staged some changes, you can add a commit message and commit the
-staged changes. Unstaged changes will not be commited.
+staged changes. Unstaged changes will not be committed.
![Commit changes](img/commit_changes.png)
@@ -80,7 +80,7 @@ left.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19318) in [GitLab Core][ce] 11.0.
Switching between your authored and assigned merge requests can be done without
-leaving the Web IDE. Click the dropdown in the top of the sidebar to open a list
+leaving the Web IDE. Click the dropdown in the top of the sidebar to open a list
of merge requests. You will need to commit or discard all your changes before
switching to a different merge request.
@@ -89,7 +89,7 @@ switching to a different merge request.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20850) in [GitLab Core][ce] 11.2.
Switching between branches of the current project repository can be done without
-leaving the Web IDE. Click the dropdown in the top of the sidebar to open a list
+leaving the Web IDE. Click the dropdown in the top of the sidebar to open a list
of branches. You will need to commit or discard all your changes before
switching to a different branch.
diff --git a/doc/user/reserved_names.md b/doc/user/reserved_names.md
index 45c306f5988..9aa81e33fc0 100644
--- a/doc/user/reserved_names.md
+++ b/doc/user/reserved_names.md
@@ -5,6 +5,7 @@ existing routes used by GitLab.
For a list of words that are not allowed to be used as group or project names, see the
[`path_regex.rb` file][reserved] under the `TOP_LEVEL_ROUTES`, `PROJECT_WILDCARD_ROUTES` and `GROUP_ROUTES` lists:
+
- `TOP_LEVEL_ROUTES`: are names that are reserved as usernames or top level groups
- `PROJECT_WILDCARD_ROUTES`: are names that are reserved for child groups or projects.
- `GROUP_ROUTES`: are names that are reserved for all groups or projects.
@@ -61,8 +62,6 @@ Currently the following names are reserved as top level groups:
- favicon.ico
- favicon.png
- groups
-- header_logo_dark.png
-- header_logo_light.png
- health_check
- help
- import
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 78c1294346b..705983cce2a 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -31,7 +31,7 @@ on the search field on the top-right of your screen:
If you want to search for issues present in a specific project, navigate to
a project's **Issues** tab, and click on the field **Search or filter results...**. It will
-display a dropdown menu, from which you can add filters per author, assignee, milestone,
+display a dropdown menu, from which you can add filters per author, assignee, milestone,
label, weight, and 'my-reaction' (based on your emoji votes). When done, press **Enter** on your keyboard to filter the issues.
![filter issues in a project](img/issue_search_filter.png)
@@ -54,12 +54,12 @@ Selecting **Any** does the opposite. It returns results that have a non-empty va
You can filter issues and merge requests by specific terms included in titles or descriptions.
-* Syntax
- * Searches look for all the words in a query, in any order. E.g.: searching
+- Syntax
+ - Searches look for all the words in a query, in any order. E.g.: searching
issues for `display bug` will return all issues matching both those words, in any order.
- * To find the exact term, use double quotes: `"display bug"`
-* Limitation
- * For performance reasons, terms shorter than 3 chars are ignored. E.g.: searching
+ - To find the exact term, use double quotes: `"display bug"`
+- Limitation
+ - For performance reasons, terms shorter than 3 chars are ignored. E.g.: searching
issues for `included in titles` is same as `included titles`
![filter issues by specific terms](img/issue_search_by_term.png)
@@ -96,7 +96,7 @@ quickly access issues and merge requests created or assigned to you within that
Your [todos](../../workflow/todos.md#gitlab-todos) can be searched by "to do" and "done".
You can [filter](../../workflow/todos.md#filtering-your-todos) them per project,
author, type, and action. Also, you can sort them by
-[**Label priority**](../../user/project/labels.md#prioritize-labels),
+[**Label priority**](../../user/project/labels.md#label-priority),
**Last created** and **Oldest created**.
## Projects
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
index 7efb6bafee7..569bdc9e2d5 100644
--- a/doc/user/snippets.md
+++ b/doc/user/snippets.md
@@ -4,7 +4,12 @@ With GitLab Snippets you can store and share bits of code and text with other us
![GitLab Snippet](img/gitlab_snippet.png)
-There are 2 types of snippets, personal snippets and project snippets.
+Snippets can be maintained using [snippets API](../api/snippets.md).
+
+There are two types of snippets:
+
+- Personal snippets.
+- Project snippets.
## Personal snippets
@@ -15,7 +20,7 @@ and private. See [Public access](../public_access/public_access.md) for more inf
## Project snippets
Project snippets are always related to a specific project.
-See [Project's features](project/index.md#project-39-s-features) for more information.
+See [Project's features](project/index.md#projects-features) for more information.
## Discover snippets
diff --git a/doc/workflow/forking_workflow.md b/doc/workflow/forking_workflow.md
index 733d079bd4a..02be0ad191d 100644
--- a/doc/workflow/forking_workflow.md
+++ b/doc/workflow/forking_workflow.md
@@ -10,7 +10,6 @@ document more information about using branches to work together.
Forking a project is in most cases a two-step process.
-
1. Click on the fork button located in the middle of the page or a project's
home page right next to the stars button.
diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md
index a7313082fac..1b9fb504b15 100644
--- a/doc/workflow/gitlab_flow.md
+++ b/doc/workflow/gitlab_flow.md
@@ -2,314 +2,324 @@
# Introduction to GitLab Flow
-Version management with git makes branching and merging much easier than older versioning systems such as SVN.
-This allows a wide variety of branching strategies and workflows.
-Almost all of these are an improvement over the methods used before git.
-But many organizations end up with a workflow that is not clearly defined, overly complex or not integrated with issue tracking systems.
-Therefore we propose the GitLab flow as clearly defined set of best practices.
-It combines [feature driven development](https://en.wikipedia.org/wiki/Feature-driven_development) and [feature branches](http://martinfowler.com/bliki/FeatureBranch.html) with issue tracking.
+Git allows a wide variety of branching strategies and workflows.
+Because of this, many organizations end up with workflows that are too complicated, not clearly defined, or not integrated with issue tracking systems.
+Therefore, we propose GitLab flow as a clearly defined set of best practices.
+It combines [feature-driven development](https://en.wikipedia.org/wiki/Feature-driven_development) and [feature branches](https://martinfowler.com/bliki/FeatureBranch.html) with issue tracking.
-Organizations coming to git from other version control systems frequently find it hard to develop an effective workflow.
-This article describes the GitLab flow that integrates the git workflow with an issue tracking system.
-It offers a simple, transparent and effective way to work with git.
+Organizations coming to Git from other version control systems frequently find it hard to develop a productive workflow.
+This article describes GitLab flow, which integrates the Git workflow with an issue tracking system.
+It offers a simple, transparent, and effective way to work with Git.
![Four stages (working copy, index, local repo, remote repo) and three steps between them](four_stages.png)
-When converting to git you have to get used to the fact that there are three steps before a commit is shared with colleagues.
-Most version control systems have only one step, committing from the working copy to a shared server.
-In git you add files from the working copy to the staging area. After that you commit them to the local repo.
+When converting to Git, you have to get used to the fact that it takes three steps to share a commit with colleagues.
+Most version control systems have only one step: committing from the working copy to a shared server.
+In Git, you add files from the working copy to the staging area. After that, you commit them to your local repo.
The third step is pushing to a shared remote repository.
-After getting used to these three steps the branching model becomes the challenge.
+After getting used to these three steps, the next challenge is the branching model.
-![Multiple long running branches and merging in all directions](messy_flow.png)
+![Multiple long-running branches and merging in all directions](messy_flow.png)
-Since many organizations new to git have no conventions how to work with it, it can quickly become a mess.
-The biggest problem they run into is that many long running branches that each contain part of the changes are around.
-People have a hard time figuring out which branch they should develop on or deploy to production.
-Frequently the reaction to this problem is to adopt a standardized pattern such as [git flow](http://nvie.com/posts/a-successful-git-branching-model/) and [GitHub flow](http://scottchacon.com/2011/08/31/github-flow.html).
-We think there is still room for improvement and will detail a set of practices we call GitLab flow.
+Since many organizations new to Git have no conventions for how to work with it, their repositories can quickly become messy.
+The biggest problem is that many long-running branches emerge that all contain part of the changes.
+People have a hard time figuring out which branch has the latest code, or which branch to deploy to production.
+Frequently, the reaction to this problem is to adopt a standardized pattern such as [Git flow](https://nvie.com/posts/a-successful-git-branching-model/) and [GitHub flow](http://scottchacon.com/2011/08/31/github-flow.html).
+We think there is still room for improvement. In this document, we describe a set of practices we call GitLab flow.
## Git flow and its problems
![Git Flow timeline by Vincent Driessen, used with permission](gitdashflow.png)
-Git flow was one of the first proposals to use git branches and it has gotten a lot of attention.
-It advocates a master branch and a separate develop branch as well as supporting branches for features, releases and hotfixes.
-The development happens on the develop branch, moves to a release branch and is finally merged into the master branch.
-Git flow is a well defined standard but its complexity introduces two problems.
-The first problem is that developers must use the develop branch and not master, master is reserved for code that is released to production.
-It is a convention to call your default branch master and to mostly branch from and merge to this.
-Since most tools automatically make the master branch the default one and display that one by default it is annoying to have to switch to another one.
-The second problem of git flow is the complexity introduced by the hotfix and release branches.
+Git flow was one of the first proposals to use Git branches, and it has received a lot of attention.
+It suggests a `master` branch and a separate `develop` branch, as well as supporting branches for features, releases, and hotfixes.
+The development happens on the `develop` branch, moves to a release branch, and is finally merged into the `master` branch.
+
+Git flow is a well-defined standard, but its complexity introduces two problems.
+The first problem is that developers must use the `develop` branch and not `master`. `master` is reserved for code that is released to production.
+It is a convention to call your default branch `master` and to mostly branch from and merge to this.
+Since most tools automatically use the `master` branch as the default, it is annoying to have to switch to another branch.
+
+The second problem of Git flow is the complexity introduced by the hotfix and release branches.
These branches can be a good idea for some organizations but are overkill for the vast majority of them.
-Nowadays most organizations practice continuous delivery which means that your default branch can be deployed.
-This means that hotfix and release branches can be prevented including all the ceremony they introduce.
+Nowadays, most organizations practice continuous delivery, which means that your default branch can be deployed.
+Continuous delivery removes the need for hotfix and release branches, including all the ceremony they introduce.
An example of this ceremony is the merging back of release branches.
Though specialized tools do exist to solve this, they require documentation and add complexity.
-Frequently developers make a mistake and for example changes are only merged into master and not into the develop branch.
-The root cause of these errors is that git flow is too complex for most of the use cases.
-And doing releases doesn't automatically mean also doing hotfixes.
+Frequently, developers make mistakes such as merging changes only into `master` and not into the `develop` branch.
+The reason for these errors is that Git flow is too complicated for most use cases.
+For example, many projects do releases but don't need to do hotfixes.
## GitHub flow as a simpler alternative
![Master branch with feature branches merged in](github_flow.png)
-In reaction to git flow a simpler alternative was detailed, [GitHub flow](https://guides.github.com/introduction/flow/index.html).
-This flow has only feature branches and a master branch.
-This is very simple and clean, many organizations have adopted it with great success.
-Atlassian recommends [a similar strategy](http://blogs.atlassian.com/2014/01/simple-git-workflow-simple/) although they rebase feature branches.
-Merging everything into the master branch and deploying often means you minimize the amount of code in 'inventory' which is in line with the lean and continuous delivery best practices.
-But this flow still leaves a lot of questions unanswered regarding deployments, environments, releases and integrations with issues.
-With GitLab flow we offer additional guidance for these questions.
+In reaction to Git flow, GitHub created a simpler alternative.
+[GitHub flow](https://guides.github.com/introduction/flow/index.html) has only feature branches and a `master` branch.
+This flow is clean and straightforward, and many organizations have adopted it with great success.
+Atlassian recommends [a similar strategy](https://www.atlassian.com/blog/archives/simple-git-workflow-simple), although they rebase feature branches.
+Merging everything into the `master` branch and frequently deploying means you minimize the amount of unreleased code, which is in line with lean and continuous delivery best practices.
+However, this flow still leaves a lot of questions unanswered regarding deployments, environments, releases, and integrations with issues.
+With GitLab flow, we offer additional guidance for these questions.
## Production branch with GitLab flow
-![Master branch and production branch with arrow that indicate deployments](production_branch.png)
+![Master branch and production branch with an arrow that indicates a deployment](production_branch.png)
-GitHub flow does assume you are able to deploy to production every time you merge a feature branch.
-This is possible for e.g. SaaS applications, but there are many cases where this is not possible.
-One would be a situation where you are not in control of the exact release moment, for example an iOS application that needs to pass App Store validation.
-Another example is when you have deployment windows (workdays from 10am to 4pm when the operations team is at full capacity) but you also merge code at other times.
-In these cases you can make a production branch that reflects the deployed code.
-You can deploy a new version by merging in master to the production branch.
-If you need to know what code is in production you can just checkout the production branch to see.
+GitHub flow assumes you can deploy to production every time you merge a feature branch.
+While this is possible in some cases, such as SaaS applications, there are many cases where this is not possible.
+One case is where you don't control the timing of a release, for example, an iOS application that is released when it passes App Store validation.
+Another case is when you have deployment windows &mdash; for example, workdays from 10&nbsp;AM to 4&nbsp;PM when the operations team is at full capacity &mdash; but you also merge code at other times.
+In these cases, you can make a production branch that reflects the deployed code.
+You can deploy a new version by merging `master` into the production branch.
+If you need to know what code is in production, you can just checkout the production branch to see.
The approximate time of deployment is easily visible as the merge commit in the version control system.
This time is pretty accurate if you automatically deploy your production branch.
-If you need a more exact time you can have your deployment script create a tag on each deployment.
-This flow prevents the overhead of releasing, tagging and merging that is common to git flow.
+If you need a more exact time, you can have your deployment script create a tag on each deployment.
+This flow prevents the overhead of releasing, tagging, and merging that happens with Git flow.
## Environment branches with GitLab flow
![Multiple branches with the code cascading from one to another](environment_branches.png)
-It might be a good idea to have an environment that is automatically updated to the master branch.
-Only in this case, the name of this environment might differ from the branch name.
-Suppose you have a staging environment, a pre-production environment and a production environment.
-In this case the master branch is deployed on staging. When someone wants to deploy to pre-production they create a merge request from the master branch to the pre-production branch.
-And going live with code happens by merging the pre-production branch into the production branch.
-This workflow where commits only flow downstream ensures that everything has been tested on all environments.
-If you need to cherry-pick a commit with a hotfix it is common to develop it on a feature branch and merge it into master with a merge request, do not delete the feature branch.
-If master is good to go (it should be if you are practicing [continuous delivery](http://martinfowler.com/bliki/ContinuousDelivery.html)) you then merge it to the other branches.
-If this is not possible because more manual testing is required you can send merge requests from the feature branch to the downstream branches.
+It might be a good idea to have an environment that is automatically updated to the `master` branch.
+Only, in this case, the name of this environment might differ from the branch name.
+Suppose you have a staging environment, a pre-production environment, and a production environment.
+In this case, deploy the `master` branch to staging.
+To deploy to pre-production, create a merge request from the `master` branch to the pre-production branch.
+Go live by merging the pre-production branch into the production branch.
+This workflow, where commits only flow downstream, ensures that everything is tested in all environments.
+If you need to cherry-pick a commit with a hotfix, it is common to develop it on a feature branch and merge it into `master` with a merge request.
+In this case, do not delete the feature branch yet.
+If `master` passes automatic testing, you then merge the feature branch into the other branches.
+If this is not possible because more manual testing is required, you can send merge requests from the feature branch to the downstream branches.
## Release branches with GitLab flow
![Master and multiple release branches that vary in length with cherry-picks from master](release_branches.png)
-Only in case you need to release software to the outside world you need to work with release branches.
-In this case, each branch contains a minor version (2-3-stable, 2-4-stable, etc.).
-The stable branch uses master as a starting point and is created as late as possible.
-By branching as late as possible you minimize the time you have to apply bug fixes to multiple branches.
-After a release branch is announced, only serious bug fixes are included in the release branch.
-If possible these bug fixes are first merged into master and then cherry-picked into the release branch.
-This way you can't forget to cherry-pick them into master and encounter the same bug on subsequent releases.
-This is called an 'upstream first' policy that is also practiced by [Google](https://www.chromium.org/chromium-os/chromiumos-design-docs/upstream-first) and [Red Hat](https://www.redhat.com/about/news/archive/2013/5/a-community-for-using-openstack-with-red-hat-rdo).
-Every time a bug-fix is included in a release branch the patch version is raised (to comply with [Semantic Versioning](http://semver.org/)) by setting a new tag.
+You only need to work with release branches if you need to release software to the outside world.
+In this case, each branch contains a minor version, for example, 2-3-stable, 2-4-stable, etc.
+Create stable branches using `master` as a starting point, and branch as late as possible.
+By doing this, you minimize the length of time during which you have to apply bug fixes to multiple branches.
+After announcing a release branch, only add serious bug fixes to the branch.
+If possible, first merge these bug fixes into `master`, and then cherry-pick them into the release branch.
+If you start by merging into the release branch, you might forget to cherry-pick them into `master`, and then you'd encounter the same bug in subsequent releases.
+Merging into `master` and then cherry-picking into release is called an "upstream first" policy, which is also practiced by [Google](https://www.chromium.org/chromium-os/chromiumos-design-docs/upstream-first) and [Red Hat](https://www.redhat.com/en/blog/a-community-for-using-openstack-with-red-hat-rdo).
+Every time you include a bug fix in a release branch, increase the patch version (to comply with [Semantic Versioning](https://semver.org/)) by setting a new tag.
Some projects also have a stable branch that points to the same commit as the latest released branch.
-In this flow it is not common to have a production branch (or git flow master branch).
+In this flow, it is not common to have a production branch (or Git flow `master` branch).
## Merge/pull requests with GitLab flow
-![Merge request with line comments](mr_inline_comments.png)
+![Merge request with inline comments](mr_inline_comments.png)
-Merge or pull requests are created in a git management application and ask an assigned person to merge two branches.
-Tools such as GitHub and Bitbucket choose the name pull request since the first manual action would be to pull the feature branch.
-Tools such as GitLab and others choose the name merge request since that is the final action that is requested of the assignee.
-In this article we'll refer to them as merge requests.
+Merge or pull requests are created in a Git management application. They ask an assigned person to merge two branches.
+Tools such as GitHub and Bitbucket choose the name "pull request" since the first manual action is to pull the feature branch.
+Tools such as GitLab and others choose the name "merge request" since the final action is to merge the feature branch.
+In this article, we'll refer to them as merge requests.
-If you work on a feature branch for more than a few hours it is good to share the intermediate result with the rest of the team.
-This can be done by creating a merge request without assigning it to anyone, instead you mention people in the description or a comment (/cc @mark @susan).
-This means it is not ready to be merged but feedback is welcome.
+If you work on a feature branch for more than a few hours, it is good to share the intermediate result with the rest of the team.
+To do this, create a merge request without assigning it to anyone.
+Instead, mention people in the description or a comment, for example, "/cc @mark @susan."
+This indicates that the merge request is not ready to be merged yet, but feedback is welcome.
Your team members can comment on the merge request in general or on specific lines with line comments.
-The merge requests serves as a code review tool and no separate tools such as Gerrit and reviewboard should be needed.
-If the review reveals shortcomings anyone can commit and push a fix.
-Commonly the person to do this is the creator of the merge/pull request.
-The diff in the merge/pull requests automatically updates when new commits are pushed on the branch.
+The merge request serves as a code review tool, and no separate code review tools should be needed.
+If the review reveals shortcomings, anyone can commit and push a fix.
+Usually, the person to do this is the creator of the merge request.
+The diff in the merge request automatically updates when new commits are pushed to the branch.
+
+When you are ready for your feature branch to be merged, assign the merge request to the person who knows most about the codebase you are changing.
+Also, mention any other people from whom you would like feedback.
+After the assigned person feels comfortable with the result, they can merge the branch.
+If the assigned person does not feel comfortable, they can request more changes or close the merge request without merging.
+
+In GitLab, it is common to protect the long-lived branches, e.g., the `master` branch, so that [most developers can't modify them](../permissions/permissions.md).
+So, if you want to merge into a protected branch, assign your merge request to someone with maintainer permissions.
-When you feel comfortable with it to be merged you assign it to the person that knows most about the codebase you are changing and mention any other people you would like feedback from.
-There is room for more feedback and after the assigned person feels comfortable with the result the branch is merged.
-If the assigned person does not feel comfortable they can close the merge request without merging.
+After you merge a feature branch, you should remove it from the source control software.
+In GitLab, you can do this when merging.
+Removing finished branches ensures that the list of branches shows only work in progress.
+It also ensures that if someone reopens the issue, they can use the same branch name without causing problems.
-In GitLab it is common to protect the long-lived branches (e.g. the master branch) so that normal developers [can't modify these protected branches](http://docs.gitlab.com/ce/permissions/permissions.html).
-So if you want to merge it into a protected branch you assign it to someone with maintainer authorizations.
+NOTE: **Note:**
+When you reopen an issue you need to create a new merge request.
+
+![Remove checkbox for branch in merge requests](remove_checkbox.png)
## Issue tracking with GitLab flow
-![Merge request with the branch name 15-require-a-password-to-change-it and assignee field shown](merge_request.png)
+![Merge request with the branch name "15-require-a-password-to-change-it" and assignee field shown](merge_request.png)
GitLab flow is a way to make the relation between the code and the issue tracker more transparent.
-Any significant change to the code should start with an issue where the goal is described.
-Having a reason for every code change is important to inform everyone on the team and to help people keep the scope of a feature branch small.
-In GitLab each change to the codebase starts with an issue in the issue tracking system.
-If there is no issue yet it should be created first provided there is significant work involved (more than 1 hour).
-For many organizations this will be natural since the issue will have to be estimated for the sprint.
-Issue titles should describe the desired state of the system, e.g. "As an administrator I want to remove users without receiving an error" instead of "Admin can't remove users.".
-
-When you are ready to code you start a branch for the issue from the master branch.
-The name of this branch should start with the issue number, for example '15-require-a-password-to-change-it'.
-
-When you are done or want to discuss the code you open a merge request.
-This is an online place to discuss the change and review the code.
-Opening a merge request is a manual action since you do not always want to merge a new branch you push, it could be a long-running environment or release branch.
-If you open the merge request but do not assign it to anyone it is a 'Work In Progress' merge request.
-These are used to discuss the proposed implementation but are not ready for inclusion in the master branch yet.
-_Pro tip:_ Start the title of the merge request with `[WIP]` or `WIP:` to prevent it from being merged before it's ready.
-
-When the author thinks the code is ready the merge request is assigned to reviewer.
-The reviewer presses the merge button when they think the code is ready for inclusion in the master branch.
-In this case the code is merged and a merge commit is generated that makes this event easily visible later on.
-Merge requests always create a merge commit even when the commit could be added without one.
-This merge strategy is called 'no fast-forward' in git.
-After the merge the feature branch is deleted since it is no longer needed, in GitLab this deletion is an option when merging.
+Any significant change to the code should start with an issue that describes the goal.
+Having a reason for every code change helps to inform the rest of the team and to keep the scope of a feature branch small.
+In GitLab, each change to the codebase starts with an issue in the issue tracking system.
+If there is no issue yet, create the issue, as long as the change will take a significant amount of work, i.e., more than 1 hour.
+In many organizations, raising an issue is part of the development process because they are used in sprint planning.
+The issue title should describe the desired state of the system.
+For example, the issue title "As an administrator, I want to remove users without receiving an error" is better than "Admin can't remove users."
+
+When you are ready to code, create a branch for the issue from the `master` branch.
+This branch is the place for any work related to this change.
+
+NOTE: **Note:**
+The name of a branch might be dictated by organizational standards.
+For example, in GitLab, any branches in GitLab EE that are equivalent to branches in GitLab CE [must end in `-ee`](https://docs.gitlab.com/ee/development/automatic_ce_ee_merge.html#cherry-picking-from-ce-to-ee).
+
+When you are done or want to discuss the code, open a merge request.
+A merge request is an online place to discuss the change and review the code.
+
+If you open the merge request but do not assign it to anyone, it is a "Work In Progress" merge request.
+These are used to discuss the proposed implementation but are not ready for inclusion in the `master` branch yet.
+Start the title of the merge request with "[WIP]" or "WIP:" to prevent it from being merged before it's ready.
+
+When you think the code is ready, assign the merge request to a reviewer.
+The reviewer can merge the changes when they think the code is ready for inclusion in the `master` branch.
+When they press the merge button, GitLab merges the code and creates a merge commit that makes this event easily visible later on.
+Merge requests always create a merge commit, even when the branch could be merged without one.
+This merge strategy is called "no fast-forward" in Git.
+After the merge, delete the feature branch since it is no longer needed.
+In GitLab, this deletion is an option when merging.
Suppose that a branch is merged but a problem occurs and the issue is reopened.
-In this case it is no problem to reuse the same branch name since it was deleted when the branch was merged.
-At any time there is at most one branch for every issue.
+In this case, it is no problem to reuse the same branch name since the first branch was deleted when it was merged.
+At any time, there is at most one branch for every issue.
It is possible that one feature branch solves more than one issue.
## Linking and closing issues from merge requests
![Merge request showing the linked issues that will be closed](close_issue_mr.png)
-Linking to issues can happen by mentioning them in commit messages (fixes #14, closes #67, etc.) or in the merge request description.
-GitLab then creates links to the mentioned issues and creates comments in the corresponding issues linking back to the merge request.
+Link to issues by mentioning them in commit messages or the description of a merge request, for example, "Fixes #16" or "Duck typing is preferred. See #12."
+GitLab then creates links to the mentioned issues and creates comments in the issues linking back to the merge request.
-These issues are closed once code is merged into the default branch.
+To automatically close linked issues, mention them with the words "fixes" or "closes," for example, "fixes #14" or "closes #67." GitLab closes these issues when the code is merged into the default branch.
-If you only want to make the reference without closing the issue you can also just mention it: "Duck typing is preferred. #12".
-
-If you have an issue that spans across multiple repositories, the best thing is to create an issue for each repository and link all issues to a parent issue.
+If you have an issue that spans across multiple repositories, create an issue for each repository and link all issues to a parent issue.
## Squashing commits with rebase
![Vim screen showing the rebase view](rebase.png)
-With git you can use an interactive rebase (`rebase -i`) to squash multiple commits into one and reorder them.
-In GitLab EE and .com you can also [rebase before merge](http://docs.gitlab.com/ee/workflow/rebase_before_merge.html) from the web interface.
-This functionality is useful if you made a couple of commits for small changes during development and want to replace them with a single commit or if you want to make the order more logical.
-However you should never rebase commits you have pushed to a remote server.
-Somebody can have referred to the commits or cherry-picked them.
-When you rebase you change the identifier (SHA-1) of the commit and this is confusing.
-If you do that the same change will be known under multiple identifiers and this can cause much confusion.
-If people already reviewed your code it will be hard for them to review only the improvements you made since then if you have rebased everything into one commit.
-Another reasons not to rebase is that you lose authorship information, maybe someone created a merge request, another person pushed a commit on there to improve it and a third one merged it.
-In this case rebasing all the commits into one prevent the other authors from being properly attributed and sharing part of the [git blame](https://git-scm.com/docs/git-blame).
-
-People are encouraged to commit often and to frequently push to the remote repository so other people are aware what everyone is working on.
-This will lead to many commits per change which makes the history harder to understand.
-But the advantages of having stable identifiers outweigh this drawback.
-And to understand a change in context one can always look at the merge commit that groups all the commits together when the code is merged into the master branch.
-
-After you merge multiple commits from a feature branch into the master branch this is harder to undo.
-If you had squashed all the commits into one you could have just reverted this commit but as we indicated you should not rebase commits after they are pushed.
-Fortunately [reverting a merge made some time ago](https://git-scm.com/blog/2010/03/02/undoing-merges.html) can be done with git.
-This however, requires having specific merge commits for the commits your want to revert.
-If you revert a merge and you change your mind, revert the revert instead of merging again since git will not allow you to merge the code again otherwise.
-
-Being able to revert a merge is a good reason always to create a merge commit when you merge manually with the `--no-ff` option.
-Git management software will always create a merge commit when you accept a merge request.
-
-## Do not order commits with rebase
+With Git, you can use an interactive rebase (`rebase -i`) to squash multiple commits into one or reorder them.
+This functionality is useful if you want to replace a couple of small commits with a single commit, or if you want to make the order more logical.
+
+However, you should never rebase commits you have pushed to a remote server.
+Rebasing creates new commits for all your changes, which can cause confusion because the same change would have multiple identifiers.
+It also causes merge errors for anyone working on the same branch because their history would not match with yours.
+Also, if someone has already reviewed your code, rebasing makes it hard to tell what changed since the last review.
+
+You should also never rebase commits authored by other people.
+Not only does this rewrite history, but it also loses authorship information.
+Rebasing prevents the other authors from being attributed and sharing part of the [`git blame`](https://git-scm.com/docs/git-blame).
+
+If a merge involves many commits, it may seem more difficult to undo.
+You might think to solve this by squashing all the changes into one commit before merging, but as discussed earlier, it is a bad idea to rebase commits that you have already pushed.
+Fortunately, there is an easy way to undo a merge with all its commits.
+The way to do this is by reverting the merge commit.
+Preserving this ability to revert a merge is a good reason to always use the "no fast-forward" (`--no-ff`) strategy when you merge manually.
+
+NOTE: **Note:**
+If you revert a merge commit and then change your mind, revert the revert commit to redo the merge.
+Git does not allow you to merge the code again otherwise.
+
+## Reducing merge commits in feature branches
![List of sequential merge commits](merge_commits.png)
-With git you can also rebase your feature branch commits to order them after the commits on the master branch.
-This prevents creating a merge commit when merging master into your feature branch and creates a nice linear history.
-However, just like with squashing you should never rebase commits you have pushed to a remote server.
-This makes it impossible to rebase work in progress that you already shared with your team which is something we recommend.
-When using rebase to keep your feature branch updated you [need to resolve similar conflicts again and again](https://blogs.atlassian.com/2013/10/git-team-workflows-merge-or-rebase/).
-You can reuse recorded resolutions (rerere) sometimes, but without rebasing you only have to solve the conflicts one time and you’re set.
-There has to be a better way to avoid many merge commits.
-
-The way to prevent creating many merge commits is to not frequently merge master into the feature branch.
-We'll discuss the three reasons to merge in master: leveraging code, merge conflicts, and long running branches.
-If you need to leverage some code that was introduced in master after you created the feature branch you can sometimes solve this by just cherry-picking a commit.
-If your feature branch has a merge conflict, creating a merge commit is a normal way of solving this.
-You can prevent some merge conflicts by using [gitattributes](http://git-scm.com/docs/gitattributes) for files that can be in a random order.
-For example in GitLab our changelog file is specified in .gitattributes as `CHANGELOG.md merge=union` so that there are fewer merge conflicts in it.
-The last reason for creating merge commits is having long lived branches that you want to keep up to date with the latest state of the project.
-Martin Fowler, in [his article about feature branches](http://martinfowler.com/bliki/FeatureBranch.html) talks about this Continuous Integration (CI).
-At GitLab we are guilty of confusing CI with branch testing. Quoting Martin Fowler: "I've heard people say they are doing CI because they are running builds, perhaps using a CI server, on every branch with every commit.
-That's continuous building, and a Good Thing, but there's no integration, so it's not CI.".
-The solution to prevent many merge commits is to keep your feature branches short-lived, the vast majority should take less than one day of work.
-If your feature branches commonly take more than a day of work, look into ways to create smaller units of work and/or use [feature toggles](http://martinfowler.com/bliki/FeatureToggle.html).
-As for the long running branches that take more than one day there are two strategies.
-In a CI strategy you can merge in master at the start of the day to prevent painful merges at a later time.
-In a synchronization point strategy you only merge in from well defined points in time, for example a tagged release.
-This strategy is [advocated by Linus Torvalds](https://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html) because the state of the code at these points is better known.
-
-In conclusion, we can say that you should try to prevent merge commits, but not eliminate them.
-Your codebase should be clean but your history should represent what actually happened.
-Developing software happen in small messy steps and it is OK to have your history reflect this.
-You can use tools to view the network graphs of commits and understand the messy history that created your code.
-If you rebase code the history is incorrect, and there is no way for tools to remedy this because they can't deal with changing commit identifiers.
+Having lots of merge commits can make your repository history messy.
+Therefore, you should try to avoid merge commits in feature branches.
+Often, people avoid merge commits by just using rebase to reorder their commits after the commits on the `master` branch.
+Using rebase prevents a merge commit when merging `master` into your feature branch, and it creates a neat linear history.
+However, as discussed in [the section about rebasing](#squashing-commits-with-rebase), you should never rebase commits you have pushed to a remote server.
+This restriction makes it impossible to rebase work in progress that you already shared with your team, which is something we recommend.
-## Award emojis on issues and merge requests
+Rebasing also creates more work, since every time you rebase, you have to resolve similar conflicts.
+Sometimes you can reuse recorded resolutions (`rerere`), but merging is better since you only have to resolve conflicts once.
+Atlassian has a more thorough explanation of the tradeoffs between merging and rebasing [on their blog](https://www.atlassian.com/blog/git/git-team-workflows-merge-or-rebase).
-![Emoji bar in GitLab](award_emoji.png)
+A good way to prevent creating many merge commits is to not frequently merge `master` into the feature branch.
+There are three reasons to merge in `master`: utilizing new code, resolving merge conflicts, and updating long-running branches.
-It is common to voice approval or disapproval by using +1 or -1. In GitLab you
-can use emojis to give a virtual high five on issues and merge requests.
+If you need to utilize some code that was introduced in `master` after you created the feature branch, you can often solve this by just cherry-picking a commit.
-## Pushing and removing branches
+If your feature branch has a merge conflict, creating a merge commit is a standard way of solving this.
-![Remove checkbox for branch in merge requests](remove_checkbox.png)
+NOTE: **Note:**
+Sometimes you can use .gitattributes to reduce merge conflicts.
+For example, you can set your changelog file to use the [union merge driver](https://git-scm.com/docs/gitattributes#gitattributes-union) so that multiple new entries don't conflict with each other.
-We recommend that people push their feature branches frequently, even when they are not ready for review yet.
-By doing this you prevent team members from accidentally starting to work on the same issue.
-Of course this situation should already be prevented by assigning someone to the issue in the issue tracking software.
-However sometimes one of the two parties forgets to assign someone in the issue tracking software.
-After a branch is merged it should be removed from the source control software.
-In GitLab and similar systems this is an option when merging.
-This ensures that the branch overview in the repository management software shows only work in progress.
-This also ensures that when someone reopens the issue a new branch with the same name can be used without problem.
-When you reopen an issue you need to create a new merge request.
+The last reason for creating merge commits is to keep long-running feature branches up-to-date with the latest state of the project.
+The solution here is to keep your feature branches short-lived.
+Most feature branches should take less than one day of work.
+If your feature branches often take more than a day of work, try to split your features into smaller units of work.
+
+If you need to keep a feature branch open for more than a day, there are a few strategies to keep it up-to-date.
+One option is to use continuous integration (CI) to merge in `master` at the start of the day.
+Another option is to only merge in from well-defined points in time, for example, a tagged release.
+You could also use [feature toggles](https://martinfowler.com/bliki/FeatureToggle.html) to hide incomplete features so you can still merge back into `master` every day.
+
+> **Note:** Don't confuse automatic branch testing with continuous integration.
+> Martin Fowler makes this distinction in [his article about feature branches](https://martinfowler.com/bliki/FeatureBranch.html):
+>
+> "I've heard people say they are doing CI because they are running builds, perhaps using a CI server, on every branch with every commit.
+> That's continuous building, and a Good Thing, but there's no *integration*, so it's not CI."
+
+In conclusion, you should try to prevent merge commits, but not eliminate them.
+Your codebase should be clean, but your history should represent what actually happened.
+Developing software happens in small, messy steps, and it is OK to have your history reflect this.
+You can use tools to view the network graphs of commits and understand the messy history that created your code.
+If you rebase code, the history is incorrect, and there is no way for tools to remedy this because they can't deal with changing commit identifiers.
+
+## Commit often and push frequently
+
+Another way to make your development work easier is to commit often.
+Every time you have a working set of tests and code, you should make a commit.
+Splitting up work into individual commits provides context for developers looking at your code later.
+Smaller commits make it clear how a feature was developed, and they make it easy to roll back to a specific good point in time or to revert one code change without reverting several unrelated changes.
+
+Committing often also makes it easy to share your work, which is important so that everyone is aware of what you are working on.
+You should push your feature branch frequently, even when it is not yet ready for review.
+By sharing your work in a feature branch or [a merge request](#mergepull-requests-with-gitlab-flow), you prevent your team members from duplicating work.
+Sharing your work before it's complete also allows for discussion and feedback about the changes, which can help improve the code before it gets to review.
-## Committing often and with the right message
+## How to write a good commit message
![Good and bad commit message](good_commit.png)
-We recommend to commit early and often.
-Each time you have a functioning set of tests and code a commit can be made.
-The advantage is that when an extension or refactor goes wrong it is easy to revert to a working version.
-This is quite a change for programmers that used SVN before, they used to commit when their work was ready to share.
-The trick is to use the merge/pull request with multiple commits when your work is ready to share.
-The commit message should reflect your intention, not the contents of the commit.
-The contents of the commit can be easily seen anyway, the question is why you did it.
-An example of a good commit message is: "Combine templates to dry up the user views.".
-Some words that are bad commit messages because they don't contain much information are: change, improve and refactor.
-The word fix or fixes is also a red flag, unless it comes after the commit sentence and references an issue number.
-To see more information about the formatting of commit messages please see this great [blog post by Tim Pope](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
+A commit message should reflect your intention, not just the contents of the commit.
+It is easy to see the changes in a commit, so the commit message should explain why you made those changes.
+An example of a good commit message is: "Combine templates to reduce duplicate code in the user views."
+The words "change," "improve," "fix," and "refactor" don't add much information to a commit message.
+For example, "Improve XML generation" could be better written as "Properly escape special characters in XML generation."
+For more information about formatting commit messages, please see this excellent [blog post by Tim Pope](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
## Testing before merging
-![Merge requests showing the test states, red, yellow and green](ci_mr.png)
-
-In old workflows the Continuous Integration (CI) server commonly ran tests on the master branch only.
-Developers had to ensure their code did not break the master branch.
-When using GitLab flow developers create their branches from this master branch so it is essential it is green.
-Therefore each merge request must be tested before it is accepted.
-CI software like Travis and GitLab CI show the build results right in the merge request itself to make this easy.
-One drawback is that they are testing the feature branch itself and not the merged result.
-What one can do to improve this is to test the merged result itself.
-The problem is that the merge result changes every time something is merged into master.
-Retesting on every commit to master is computationally expensive and means you are more frequently waiting for test results.
-If there are no merge conflicts and the feature branches are short lived the risk is acceptable.
-If there are merge conflicts you merge the master branch into the feature branch and the CI server will rerun the tests.
-If you have long lived feature branches that last for more than a few days you should make your issues smaller.
+![Merge requests showing the test states: red, yellow, and green](ci_mr.png)
-## Working with feature branches
+In old workflows, the continuous integration (CI) server commonly ran tests on the `master` branch only.
+Developers had to ensure their code did not break the `master` branch.
+When using GitLab flow, developers create their branches from this `master` branch, so it is essential that it never breaks.
+Therefore, each merge request must be tested before it is accepted.
+CI software like Travis CI and GitLab CI show the build results right in the merge request itself to make this easy.
-![Shell output showing git pull output](git_pull.png)
+There is one drawback to testing merge requests: the CI server only tests the feature branch itself, not the merged result.
+Ideally, the server could also test the `master` branch after each change.
+However, retesting on every commit to `master` is computationally expensive and means you are more frequently waiting for test results.
+Since feature branches should be short-lived, testing just the branch is an acceptable risk.
+If new commits in `master` cause merge conflicts with the feature branch, merge `master` back into the branch to make the CI server re-run the tests.
+As said before, if you often have feature branches that last for more than a few days, you should make your issues smaller.
-When initiating a feature branch, always start with an up to date master to branch off from.
-If you know beforehand that your work absolutely depends on another branch you can also branch from there.
-If you need to merge in another branch after starting explain the reason in the merge commit.
-If you have not pushed your commits to a shared location yet you can also rebase on master or another feature branch.
-Do not merge in upstream if your code will work and merge cleanly without doing so, Linus even says that [you should never merge in upstream at random points, only at major releases](https://lwn.net/Articles/328438/).
-Merging only when needed prevents creating merge commits in your feature branch that later end up littering the master history.
+## Working with feature branches
-### References
+![Shell output showing git pull output](git_pull.png)
-- [Git Flow by Vincent Driessen](http://nvie.com/posts/a-successful-git-branching-model/)
+When creating a feature branch, always branch from an up-to-date `master`.
+If you know before you start that your work depends on another branch, you can also branch from there.
+If you need to merge in another branch after starting, explain the reason in the merge commit.
+If you have not pushed your commits to a shared location yet, you can also incorporate changes by rebasing on `master` or another feature branch.
+Do not merge from upstream again if your code can work and merge cleanly without doing so.
+Merging only when needed prevents creating merge commits in your feature branch that later end up littering the `master` history.
diff --git a/doc/workflow/groups.md b/doc/workflow/groups.md
index 06eec1ed928..c7f4647baa9 100644
--- a/doc/workflow/groups.md
+++ b/doc/workflow/groups.md
@@ -1,2 +1,5 @@
+---
+redirect_to: '../user/group/index.md'
+---
This document was moved to [another location](../user/group/index.md).
diff --git a/doc/workflow/lfs/lfs_administration.md b/doc/workflow/lfs/lfs_administration.md
index ec5943fd51b..3fb553280d0 100644
--- a/doc/workflow/lfs/lfs_administration.md
+++ b/doc/workflow/lfs/lfs_administration.md
@@ -4,9 +4,9 @@ Documentation on how to use Git LFS are under [Managing large binary files with
## Requirements
-* Git LFS is supported in GitLab starting with version 8.2.
-* Support for object storage, such as AWS S3, was introduced in 10.0.
-* Users need to install [Git LFS client](https://git-lfs.github.com) version 1.0.1 and up.
+- Git LFS is supported in GitLab starting with version 8.2.
+- Support for object storage, such as AWS S3, was introduced in 10.0.
+- Users need to install [Git LFS client](https://git-lfs.github.com) version 1.0.1 and up.
## Configuration
@@ -15,9 +15,9 @@ GitLab is installed on.
There are various configuration options to help GitLab server administrators:
-* Enabling/disabling Git LFS support
-* Changing the location of LFS object storage
-* Setting up object storage supported by [Fog](http://fog.io/about/provider_documentation.html)
+- Enabling/disabling Git LFS support
+- Changing the location of LFS object storage
+- Setting up object storage supported by [Fog](http://fog.io/about/provider_documentation.html)
### Configuration for Omnibus installations
@@ -229,11 +229,11 @@ See more information in [!19581](https://gitlab.com/gitlab-org/gitlab-ce/merge_r
## Known limitations
-* Support for removing unreferenced LFS objects was added in 8.14 onwards.
-* LFS authentications via SSH was added with GitLab 8.12
-* Only compatible with the GitLFS client versions 1.1.0 and up, or 1.0.2.
-* The storage statistics currently count each LFS object multiple times for
- every project linking to it
+- Support for removing unreferenced LFS objects was added in 8.14 onwards.
+- LFS authentications via SSH was added with GitLab 8.12.
+- Only compatible with the GitLFS client versions 1.1.0 and up, or 1.0.2.
+- The storage statistics currently count each LFS object multiple times for
+ every project linking to it.
[reconfigure gitlab]: ../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
[restart gitlab]: ../../administration/restart_gitlab.md#installations-from-source "How to restart GitLab"
diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
index d02e921fa84..da0243705aa 100644
--- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
+++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
@@ -21,18 +21,18 @@ Documentation for GitLab instance administrators is under [LFS administration do
## Requirements
-* Git LFS is supported in GitLab starting with version 8.2
-* Git LFS must be enabled under project settings
-* [Git LFS client](https://git-lfs.github.com) version 1.0.1 and up
+- Git LFS is supported in GitLab starting with version 8.2
+- Git LFS must be enabled under project settings
+- [Git LFS client](https://git-lfs.github.com) version 1.0.1 and up
## Known limitations
-* Git LFS v1 original API is not supported since it was deprecated early in LFS
+- Git LFS v1 original API is not supported since it was deprecated early in LFS
development
-* When SSH is set as a remote, Git LFS objects still go through HTTPS
-* Any Git LFS request will ask for HTTPS credentials to be provided so a good Git
+- When SSH is set as a remote, Git LFS objects still go through HTTPS
+- Any Git LFS request will ask for HTTPS credentials to be provided so a good Git
credentials store is recommended
-* Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have
+- Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have
to add the URL to Git config manually (see [troubleshooting](#troubleshooting))
>**Note**: With 8.12 GitLab added LFS support to SSH. The Git LFS communication
@@ -158,16 +158,16 @@ git lfs unlock --id=123 --force
There are a couple of reasons why this error can occur:
-* You don't have permissions to access certain LFS object
+- You don't have permissions to access certain LFS object
Check if you have permissions to push to the project or fetch from the project.
-* Project is not allowed to access the LFS object
+- Project is not allowed to access the LFS object
LFS object you are trying to push to the project or fetch from the project is not
available to the project anymore. Probably the object was removed from the server.
-* Local git repository is using deprecated LFS API
+- Local git repository is using deprecated LFS API
### Invalid status for `<url>` : 501
@@ -180,15 +180,15 @@ git lfs logs last
If the status `error 501` is shown, it is because:
-* Git LFS is not enabled in project settings. Check your project settings and
+- Git LFS is not enabled in project settings. Check your project settings and
enable Git LFS.
-* Git LFS support is not enabled on the GitLab server. Check with your GitLab
+- Git LFS support is not enabled on the GitLab server. Check with your GitLab
administrator why Git LFS is not enabled on the server. See
[LFS administration documentation](lfs_administration.md) for instructions
on how to enable LFS support.
-* Git LFS client version is not supported by GitLab server. Check your Git LFS
+- Git LFS client version is not supported by GitLab server. Check your Git LFS
version with `git lfs version`. Check the Git config of the project for traces
of deprecated API with `git lfs -l`. If `batch = false` is set in the config,
remove the line and try to update your Git LFS client. Only version 1.0.1 and
diff --git a/doc/workflow/releases.md b/doc/workflow/releases.md
index 6176784fc57..00cddda24a4 100644
--- a/doc/workflow/releases.md
+++ b/doc/workflow/releases.md
@@ -1,14 +1,17 @@
# Releases
-You can turn any git tag into a release, by adding a note to it.
-Release notes behave like any other markdown form in GitLab so you can write text and drag-n-drop files to it.
-Release notes are stored in the database of GitLab.
+NOTE: In GitLab 11.7, we introduced the full fledged [Releases](../user/project/releases/index.md)
+feature. You can still create release notes on this page, but the new method is preferred.
-There are several ways to add release notes:
+You can add release notes to any git tag using the notes feature. Release notes
+behave like any other markdown form in GitLab so you can write text and
+drag-n-drop files to it. Release notes are stored in GitLab's database.
-* In the interface, when you create a new git tag with GitLab
-* In the interface, by adding a note to an existing git tag
-* with the GitLab API
+There are several ways to add release notes:
+
+- In the interface, when you create a new git tag
+- In the interface, by adding a note to an existing git tag
+- Using the GitLab API
## New tag page with release notes text area
@@ -17,4 +20,3 @@ There are several ways to add release notes:
## Tags page with button to add or edit release notes for existing git tag
![tags](releases/tags.png)
-
diff --git a/doc/workflow/repository_mirroring.md b/doc/workflow/repository_mirroring.md
index e259e6fe50c..8a2f4e1b40e 100644
--- a/doc/workflow/repository_mirroring.md
+++ b/doc/workflow/repository_mirroring.md
@@ -55,7 +55,7 @@ When push mirroring is enabled, only push commits directly to the mirrored repos
mirror diverging. All changes will end up in the mirrored repository whenever:
- Commits are pushed to GitLab.
-- A [forced update](#forcing-an-update) is initiated.
+- A [forced update](#forcing-an-update-core) is initiated.
Changes pushed to files in the repository are automatically pushed to the remote mirror at least:
@@ -80,10 +80,21 @@ mirror.
To set up a mirror from GitLab to GitHub, you need to follow these steps:
1. Create a [GitHub personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) with the `public_repo` box checked.
-1. Fill in the **Git repository URL** field, with the personal access token instead of a password.
- For example: `https://<GitHubUsername>:<GitHubPersonalAccessToken>@github.com/group/project.git`.
+1. Fill in the **Git repository URL** field using this format: `https://<your_github_username>@github.com/<your_github_group>/<your_github_project>.git`.
+1. Fill in **Password** field with your GitHub personal access token.
1. Click the **Mirror repository** button.
-1. Wait, or click the update button.
+
+The mirrored repository will be listed. For example, `https://*****:*****@github.com/<your_github_group>/<your_github_project>.git`.
+
+The repository will push soon. To force a push, click the appropriate button.
+
+## Setting up a push mirror to another GitLab instance with 2FA activated
+
+1. On the destination GitLab instance, create a [personal access token](../user/profile/personal_access_tokens.md) with `API` scope.
+1. On the source GitLab instance:
+ 1. Fill in the **Git repository URL** field using this format: `https://oauth2@<destination host>/<your_gitlab_group_or_name>/<your_gitlab_project>.git`.
+ 1. Fill in **Password** field with the GitLab personal access token created on the destination GitLab instance.
+ 1. Click the **Mirror repository** button.
## Pulling from a remote repository **[STARTER]**
@@ -119,7 +130,7 @@ directly to the repository on GitLab. Instead, any commits should be pushed to t
Changes pushed to the upstream repository will be pulled into the GitLab repository, either:
- Automatically within a certain period of time.
-- When a [forced update](#forcing-an-update) is initiated.
+- When a [forced update](#forcing-an-update-core) is initiated.
CAUTION: **Caution:**
If you do manually update a branch in the GitLab repository, the branch will become diverged from
@@ -137,8 +148,8 @@ increased each time it fails, up to a maximum amount of time.
### SSH authentication
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2551) for Push mirroring in [GitLab Starter](https://about.gitlab.com/pricing/) 9.5.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22982) for Pull mirroring in [GitLab Core](https://about.gitlab.com/pricing/) 11.6
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2551) for Pull mirroring in [GitLab Starter](https://about.gitlab.com/pricing/) 9.5.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22982) for Push mirroring in [GitLab Core](https://about.gitlab.com/pricing/) 11.6
SSH authentication is mutual:
@@ -256,7 +267,7 @@ failed. This will become visible in either the:
- Pull mirror settings page.
When a project is hard failed, it will no longer get picked up for mirroring. A user can resume the
-project mirroring again by [Forcing an update](#forcing-an-update).
+project mirroring again by [Forcing an update](#forcing-an-update-core).
### Trigger update using API **[STARTER]**
@@ -289,8 +300,8 @@ them and how they will be resolved.
Rewriting any mirrored commit on either remote will cause conflicts and mirroring to fail. This can
be prevented by:
-- [Pulling only protected branches](#pull-only-protected-branches).
-- [Pushing only protected branches](#push-only-protected-branches).
+- [Pulling only protected branches](#only-mirror-protected-branches-starter).
+- [Pushing only protected branches](#push-only-protected-branches-core).
You should [protect the branches](../user/project/protected_branches.md) you wish to mirror on both
remotes to prevent conflicts caused by rewriting history.
diff --git a/doc/workflow/shortcuts.md b/doc/workflow/shortcuts.md
index 7359e1c6119..6ed6b0bda66 100644
--- a/doc/workflow/shortcuts.md
+++ b/doc/workflow/shortcuts.md
@@ -82,6 +82,8 @@ You can see GitLab's keyboard shortcuts by using 'shift + ?'
| <kbd>r</kbd> | Reply (quoting selected text) |
| <kbd>e</kbd> | Edit issue/merge request |
| <kbd>l</kbd> | Change label |
+| <kbd>]</kbd> or <kbd>j</kbd> | Move to next file |
+| <kbd>[</kbd> or <kbd>k</kbd> | Move to previous file |
## Wiki pages
diff --git a/doc/workflow/time_tracking.md b/doc/workflow/time_tracking.md
index 8a75687e4f5..e60b6819bf1 100644
--- a/doc/workflow/time_tracking.md
+++ b/doc/workflow/time_tracking.md
@@ -8,9 +8,10 @@ requests within GitLab.
## Overview
Time Tracking lets you:
-* record the time spent working on an issue or a merge request,
-* add an estimate of the amount of time needed to complete an issue or a merge
-request.
+
+- Record the time spent working on an issue or a merge request.
+- Add an estimate of the amount of time needed to complete an issue or a merge
+ request.
You don't have to indicate an estimate to enter the time spent, and vice versa.
@@ -37,13 +38,14 @@ Adding time entries (time spent or estimates) is limited to project members.
To enter an estimate, write `/estimate`, followed by the time. For example, if
you need to enter an estimate of 3 days, 5 hours and 10 minutes, you would write
-`/estimate 3d 5h 10m`.
+`/estimate 3d 5h 10m`. Time units that we support are listed at the bottom of
+this help page.
Every time you enter a new time estimate, any previous time estimates will be
overridden by this new value. There should only be one valid estimate in an
issue or a merge request.
-To remove an estimation entirely, use `/remove_estimation`.
+To remove an estimation entirely, use `/remove_estimate`.
### Time spent
@@ -62,13 +64,17 @@ To remove all the time spent at once, use `/remove_time_spent`.
## Configuration
The following time units are available:
-* months (mo)
-* weeks (w)
-* days (d)
-* hours (h)
-* minutes (m)
+
+- months (mo)
+- weeks (w)
+- days (d)
+- hours (h)
+- minutes (m)
Default conversion rates are 1mo = 4w, 1w = 5d and 1d = 8h.
-[landing]: https://about.gitlab.com/features/time-tracking
+Other interesting links:
+
+- [Time Tracking landing page on about.gitlab.com](https://about.gitlab.com/features/time-tracking)
+
[quick actions]: ../user/project/quick_actions.md
diff --git a/doc/workflow/todos.md b/doc/workflow/todos.md
index f94d592d0db..830f17aa7f2 100644
--- a/doc/workflow/todos.md
+++ b/doc/workflow/todos.md
@@ -35,6 +35,9 @@ A Todo appears in your Todos dashboard when:
- the author, or
- have set it to automatically merge once pipeline succeeds.
+NOTE: **Note:**
+When an user no longer has access to a resource related to a Todo like an issue, merge request, project or group the related Todos, for security reasons, gets deleted within the next hour. The delete is delayed to prevent data loss in case user got their access revoked by mistake.
+
### Directly addressed Todos
> [Introduced][ce-7926] in GitLab 9.0.
diff --git a/jest.config.js b/jest.config.js
index 4dab7c2891a..efbf2e602c1 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -13,11 +13,14 @@ if (process.env.CI) {
// eslint-disable-next-line import/no-commonjs
module.exports = {
- testMatch: ['<rootDir>/spec/frontend/**/*_spec.js'],
+ testMatch: ['<rootDir>/spec/frontend/**/*_spec.js', '<rootDir>/ee/spec/frontend/**/*_spec.js'],
moduleFileExtensions: ['js', 'json', 'vue'],
moduleNameMapper: {
'^~(.*)$': '<rootDir>/app/assets/javascripts$1',
+ '^ee(.*)$': '<rootDir>/ee/app/assets/javascripts$1',
'^helpers(.*)$': '<rootDir>/spec/frontend/helpers$1',
+ '^vendor(.*)$': '<rootDir>/vendor/assets/javascripts$1',
+ '\\.(jpg|jpeg|png|svg)$': '<rootDir>/spec/frontend/__mocks__/file_mock.js',
},
collectCoverageFrom: ['<rootDir>/app/assets/javascripts/**/*.{js,vue}'],
coverageDirectory: '<rootDir>/coverage-frontend/',
@@ -25,10 +28,12 @@ module.exports = {
cacheDirectory: '<rootDir>/tmp/cache/jest',
modulePathIgnorePatterns: ['<rootDir>/.yarn-cache/'],
reporters,
- setupTestFrameworkScriptFile: '<rootDir>/spec/frontend/test_setup.js',
+ setupFilesAfterEnv: ['<rootDir>/spec/frontend/test_setup.js'],
restoreMocks: true,
transform: {
+ '^.+\\.(gql|graphql)$': 'jest-transform-graphql',
'^.+\\.js$': 'babel-jest',
'^.+\\.vue$': 'vue-jest',
},
+ transformIgnorePatterns: ['node_modules/(?!(@gitlab/ui)/)'],
};
diff --git a/lib/api/api.rb b/lib/api/api.rb
index f1448da7403..bf8ddba6f0d 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -9,6 +9,7 @@ module API
NO_SLASH_URL_PART_REGEX = %r{[^/]+}
NAMESPACE_OR_PROJECT_REQUIREMENTS = { id: NO_SLASH_URL_PART_REGEX }.freeze
COMMIT_ENDPOINT_REQUIREMENTS = NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(sha: NO_SLASH_URL_PART_REGEX).freeze
+ USER_REQUIREMENTS = { user_id: NO_SLASH_URL_PART_REGEX }.freeze
insert_before Grape::Middleware::Error,
GrapeLogging::Middleware::RequestLogger,
@@ -100,6 +101,7 @@ module API
mount ::API::CircuitBreakers
mount ::API::Commits
mount ::API::CommitStatuses
+ mount ::API::ContainerRegistry
mount ::API::DeployKeys
mount ::API::Deployments
mount ::API::Environments
@@ -107,9 +109,11 @@ module API
mount ::API::Features
mount ::API::Files
mount ::API::GroupBoards
+ mount ::API::GroupLabels
mount ::API::GroupMilestones
mount ::API::Groups
mount ::API::GroupVariables
+ mount ::API::ImportGithub
mount ::API::Internal
mount ::API::Issues
mount ::API::JobArtifacts
@@ -129,6 +133,7 @@ module API
mount ::API::PagesDomains
mount ::API::Pipelines
mount ::API::PipelineSchedules
+ mount ::API::ProjectClusters
mount ::API::ProjectExport
mount ::API::ProjectImport
mount ::API::ProjectHooks
@@ -136,9 +141,12 @@ module API
mount ::API::Projects
mount ::API::ProjectSnapshots
mount ::API::ProjectSnippets
+ mount ::API::ProjectStatistics
mount ::API::ProjectTemplates
mount ::API::ProtectedBranches
mount ::API::ProtectedTags
+ mount ::API::Releases
+ mount ::API::Release::Links
mount ::API::Repositories
mount ::API::Runner
mount ::API::Runners
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index e7e58ad0e66..07f529b01bb 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -34,11 +34,11 @@ module API
repository = user_project.repository
branches = BranchesFinder.new(repository, declared_params(include_missing: false)).execute
-
+ branches = ::Kaminari.paginate_array(branches)
merged_branch_names = repository.merged_branch_names(branches.map(&:name))
present(
- paginate(::Kaminari.paginate_array(branches)),
+ paginate(branches),
with: Entities::Branch,
current_user: current_user,
project: user_project,
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 9d23daafe95..65eb9bfb87e 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -99,6 +99,7 @@ module API
optional :author_email, type: String, desc: 'Author email for commit'
optional :author_name, type: String, desc: 'Author name for commit'
optional :stats, type: Boolean, default: true, desc: 'Include commit stats'
+ optional :force, type: Boolean, default: false, desc: 'When `true` overwrites the target branch with a new commit based on the `start_branch`'
end
post ':id/repository/commits' do
authorize_push_to_branch!(params[:branch])
@@ -318,10 +319,34 @@ module API
use :pagination
end
get ':id/repository/commits/:sha/merge_requests', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
+ authorize! :read_merge_request, user_project
+
+ commit = user_project.commit(params[:sha])
+ not_found! 'Commit' unless commit
+
+ commit_merge_requests = MergeRequestsFinder.new(
+ current_user,
+ project_id: user_project.id,
+ commit_sha: commit.sha
+ ).execute
+
+ present paginate(commit_merge_requests), with: Entities::MergeRequestBasic
+ end
+
+ desc "Get a commit's GPG signature" do
+ success Entities::CommitSignature
+ end
+ params do
+ requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag'
+ end
+ get ':id/repository/commits/:sha/signature', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
commit = user_project.commit(params[:sha])
not_found! 'Commit' unless commit
- present paginate(commit.merge_requests), with: Entities::MergeRequestBasic
+ signature = commit.signature
+ not_found! 'GPG Signature' unless signature
+
+ present signature, with: Entities::CommitSignature
end
end
end
diff --git a/lib/api/container_registry.rb b/lib/api/container_registry.rb
new file mode 100644
index 00000000000..e4493910196
--- /dev/null
+++ b/lib/api/container_registry.rb
@@ -0,0 +1,143 @@
+# frozen_string_literal: true
+
+module API
+ class ContainerRegistry < Grape::API
+ include PaginationParams
+
+ REGISTRY_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(
+ tag_name: API::NO_SLASH_URL_PART_REGEX)
+
+ before { error!('404 Not Found', 404) unless Feature.enabled?(:container_registry_api, user_project, default_enabled: true) }
+ before { authorize_read_container_images! }
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Get a project container repositories' do
+ detail 'This feature was introduced in GitLab 11.8.'
+ success Entities::ContainerRegistry::Repository
+ end
+ params do
+ use :pagination
+ end
+ get ':id/registry/repositories' do
+ repositories = user_project.container_repositories.ordered
+
+ present paginate(repositories), with: Entities::ContainerRegistry::Repository
+ end
+
+ desc 'Delete repository' do
+ detail 'This feature was introduced in GitLab 11.8.'
+ end
+ params do
+ requires :repository_id, type: Integer, desc: 'The ID of the repository'
+ end
+ delete ':id/registry/repositories/:repository_id', requirements: REGISTRY_ENDPOINT_REQUIREMENTS do
+ authorize_admin_container_image!
+
+ DeleteContainerRepositoryWorker.perform_async(current_user.id, repository.id)
+
+ status :accepted
+ end
+
+ desc 'Get a list of repositories tags' do
+ detail 'This feature was introduced in GitLab 11.8.'
+ success Entities::ContainerRegistry::Tag
+ end
+ params do
+ requires :repository_id, type: Integer, desc: 'The ID of the repository'
+ use :pagination
+ end
+ get ':id/registry/repositories/:repository_id/tags', requirements: REGISTRY_ENDPOINT_REQUIREMENTS do
+ authorize_read_container_image!
+
+ tags = Kaminari.paginate_array(repository.tags)
+ present paginate(tags), with: Entities::ContainerRegistry::Tag
+ end
+
+ desc 'Delete repository tags (in bulk)' do
+ detail 'This feature was introduced in GitLab 11.8.'
+ end
+ params do
+ requires :repository_id, type: Integer, desc: 'The ID of the repository'
+ requires :name_regex, type: String, desc: 'The tag name regexp to delete, specify .* to delete all'
+ optional :keep_n, type: Integer, desc: 'Keep n of latest tags with matching name'
+ optional :older_than, type: String, desc: 'Delete older than: 1h, 1d, 1month'
+ end
+ delete ':id/registry/repositories/:repository_id/tags', requirements: REGISTRY_ENDPOINT_REQUIREMENTS do
+ authorize_admin_container_image!
+
+ CleanupContainerRepositoryWorker.perform_async(current_user.id, repository.id,
+ declared_params.except(:repository_id)) # rubocop: disable CodeReuse/ActiveRecord
+
+ status :accepted
+ end
+
+ desc 'Get a details about repository tag' do
+ detail 'This feature was introduced in GitLab 11.8.'
+ success Entities::ContainerRegistry::TagDetails
+ end
+ params do
+ requires :repository_id, type: Integer, desc: 'The ID of the repository'
+ requires :tag_name, type: String, desc: 'The name of the tag'
+ end
+ get ':id/registry/repositories/:repository_id/tags/:tag_name', requirements: REGISTRY_ENDPOINT_REQUIREMENTS do
+ authorize_read_container_image!
+ validate_tag!
+
+ present tag, with: Entities::ContainerRegistry::TagDetails
+ end
+
+ desc 'Delete repository tag' do
+ detail 'This feature was introduced in GitLab 11.8.'
+ end
+ params do
+ requires :repository_id, type: Integer, desc: 'The ID of the repository'
+ requires :tag_name, type: String, desc: 'The name of the tag'
+ end
+ delete ':id/registry/repositories/:repository_id/tags/:tag_name', requirements: REGISTRY_ENDPOINT_REQUIREMENTS do
+ authorize_destroy_container_image!
+ validate_tag!
+
+ tag.delete
+
+ status :ok
+ end
+ end
+
+ helpers do
+ def authorize_read_container_images!
+ authorize! :read_container_image, user_project
+ end
+
+ def authorize_read_container_image!
+ authorize! :read_container_image, repository
+ end
+
+ def authorize_update_container_image!
+ authorize! :update_container_image, repository
+ end
+
+ def authorize_destroy_container_image!
+ authorize! :admin_container_image, repository
+ end
+
+ def authorize_admin_container_image!
+ authorize! :admin_container_image, repository
+ end
+
+ def repository
+ @repository ||= user_project.container_repositories.find(params[:repository_id])
+ end
+
+ def tag
+ @tag ||= repository.tag(params[:tag_name])
+ end
+
+ def validate_tag!
+ not_found!('Tag') unless tag.valid?
+ end
+ end
+ end
+end
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index 8706a971a1a..eb45df31ff9 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -33,7 +33,7 @@ module API
success Entities::Deployment
end
params do
- requires :deployment_id, type: Integer, desc: 'The deployment ID'
+ requires :deployment_id, type: Integer, desc: 'The deployment ID'
end
get ':id/deployments/:deployment_id' do
authorize! :read_deployment, user_project
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 22403664c21..5176e9713c1 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -115,6 +115,9 @@ module API
expose :group_name do |group_link, options|
group_link.group.name
end
+ expose :group_full_path do |group_link, options|
+ group_link.group.full_path
+ end
expose :group_access, as: :group_access_level
expose :expires_at
end
@@ -153,7 +156,7 @@ module API
class BasicProjectDetails < ProjectIdentity
include ::API::ProjectsRelationBuilder
- expose :default_branch
+ expose :default_branch, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) }
# Avoids an N+1 query: https://github.com/mbleigh/acts-as-taggable-on/issues/91#issuecomment-168273770
expose :tag_list do |project|
# project.tags.order(:name).pluck(:name) is the most suitable option
@@ -187,7 +190,7 @@ module API
expose :custom_attributes, using: 'API::Entities::CustomAttribute', if: :with_custom_attributes
# rubocop: disable CodeReuse/ActiveRecord
- def self.preload_relation(projects_relation, options = {})
+ def self.preload_relation(projects_relation, options = {})
# Preloading tags, should be done with using only `:tags`,
# as `:tags` are defined as: `has_many :tags, through: :taggings`
# N+1 is solved then by using `subject.tags.map(&:name)`
@@ -258,7 +261,7 @@ module API
expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) }
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :public_builds, as: :public_jobs
- expose :ci_config_path
+ expose :ci_config_path, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) }
expose :shared_with_groups do |project, options|
SharedGroup.represent(project.project_group_links, options)
end
@@ -267,17 +270,18 @@ module API
expose :only_allow_merge_if_all_discussions_are_resolved
expose :printing_merge_request_link_enabled
expose :merge_method
-
- expose :statistics, using: 'API::Entities::ProjectStatistics', if: :statistics
+ expose :statistics, using: 'API::Entities::ProjectStatistics', if: -> (project, options) {
+ options[:statistics] && Ability.allowed?(options[:current_user], :download_code, project)
+ }
# rubocop: disable CodeReuse/ActiveRecord
- def self.preload_relation(projects_relation, options = {})
+ def self.preload_relation(projects_relation, options = {})
# Preloading tags, should be done with using only `:tags`,
# as `:tags` are defined as: `has_many :tags, through: :taggings`
# N+1 is solved then by using `subject.tags.map(&:name)`
# MR describing the solution: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20555
super(projects_relation).preload(:group)
- .preload(project_group_links: :group,
+ .preload(project_group_links: { group: :route },
fork_network: :root_project,
fork_network_member: :forked_from_project,
forked_from_project: [:route, :forks, :tags, namespace: :route])
@@ -297,6 +301,18 @@ module API
expose :build_artifacts_size, as: :job_artifacts_size
end
+ class ProjectDailyFetches < Grape::Entity
+ expose :fetch_count, as: :count
+ expose :date
+ end
+
+ class ProjectDailyStatistics < Grape::Entity
+ expose :fetches do
+ expose :total_fetch_count, as: :total
+ expose :fetches, as: :days, using: ProjectDailyFetches
+ end
+ end
+
class Member < Grape::Entity
expose :user, merge: true, using: UserBasic
expose :access_level
@@ -341,19 +357,23 @@ module API
class GroupDetail < Group
expose :projects, using: Entities::Project do |group, options|
- GroupProjectsFinder.new(
+ projects = GroupProjectsFinder.new(
group: group,
current_user: options[:current_user],
options: { only_owned: true }
).execute
+
+ Entities::Project.prepare_relation(projects)
end
expose :shared_projects, using: Entities::Project do |group, options|
- GroupProjectsFinder.new(
+ projects = GroupProjectsFinder.new(
group: group,
current_user: options[:current_user],
options: { only_shared: true }
).execute
+
+ Entities::Project.prepare_relation(projects)
end
end
@@ -362,8 +382,9 @@ module API
end
class Commit < Grape::Entity
- expose :id, :short_id, :title, :created_at
+ expose :id, :short_id, :created_at
expose :parent_ids
+ expose :full_title, as: :title
expose :safe_message, as: :message
expose :author_name, :author_email, :authored_date
expose :committer_name, :committer_email, :committed_date
@@ -384,6 +405,13 @@ module API
expose :project_id
end
+ class CommitSignature < Grape::Entity
+ expose :gpg_key_id
+ expose :gpg_key_primary_keyid, :gpg_key_user_name, :gpg_key_user_email
+ expose :verification_status
+ expose :gpg_key_subkey_id
+ end
+
class BasicRef < Grape::Entity
expose :type, :name
end
@@ -458,6 +486,12 @@ module API
expose(:project_id) { |entity| entity&.project.try(:id) }
expose :title, :description
expose :state, :created_at, :updated_at
+
+ # Avoids an N+1 query when metadata is included
+ def issuable_metadata(subject, options, method)
+ cached_subject = options.dig(:issuable_metadata, subject.id)
+ (cached_subject || subject).public_send(method) # rubocop: disable GitlabSecurity/PublicSend
+ end
end
class Diff < Grape::Entity
@@ -503,39 +537,26 @@ module API
class IssueBasic < ProjectEntity
expose :closed_at
expose :closed_by, using: Entities::UserBasic
- expose :labels do |issue, options|
+ expose :labels do |issue|
# Avoids an N+1 query since labels are preloaded
issue.labels.map(&:title).sort
end
expose :milestone, using: Entities::Milestone
expose :assignees, :author, using: Entities::UserBasic
- expose :assignee, using: ::API::Entities::UserBasic do |issue, options|
+ expose :assignee, using: ::API::Entities::UserBasic do |issue|
issue.assignees.first
end
- expose :user_notes_count
- expose :upvotes do |issue, options|
- if options[:issuable_metadata]
- # Avoids an N+1 query when metadata is included
- options[:issuable_metadata][issue.id].upvotes
- else
- issue.upvotes
- end
- end
- expose :downvotes do |issue, options|
- if options[:issuable_metadata]
- # Avoids an N+1 query when metadata is included
- options[:issuable_metadata][issue.id].downvotes
- else
- issue.downvotes
- end
- end
+ expose(:user_notes_count) { |issue, options| issuable_metadata(issue, options, :user_notes_count) }
+ expose(:merge_requests_count) { |issue, options| issuable_metadata(issue, options, :merge_requests_count) }
+ expose(:upvotes) { |issue, options| issuable_metadata(issue, options, :upvotes) }
+ expose(:downvotes) { |issue, options| issuable_metadata(issue, options, :downvotes) }
expose :due_date
expose :confidential
expose :discussion_locked
- expose :web_url do |issue, options|
+ expose :web_url do |issue|
Gitlab::UrlBuilder.build(issue)
end
@@ -635,23 +656,12 @@ module API
MarkupHelper.markdown_field(entity, :description)
end
expose :target_branch, :source_branch
- expose :upvotes do |merge_request, options|
- if options[:issuable_metadata]
- options[:issuable_metadata][merge_request.id].upvotes
- else
- merge_request.upvotes
- end
- end
- expose :downvotes do |merge_request, options|
- if options[:issuable_metadata]
- options[:issuable_metadata][merge_request.id].downvotes
- else
- merge_request.downvotes
- end
- end
+ expose(:user_notes_count) { |merge_request, options| issuable_metadata(merge_request, options, :user_notes_count) }
+ expose(:upvotes) { |merge_request, options| issuable_metadata(merge_request, options, :upvotes) }
+ expose(:downvotes) { |merge_request, options| issuable_metadata(merge_request, options, :downvotes) }
expose :author, :assignee, using: Entities::UserBasic
expose :source_project_id, :target_project_id
- expose :labels do |merge_request, options|
+ expose :labels do |merge_request|
# Avoids an N+1 query since labels are preloaded
merge_request.labels.map(&:title).sort
end
@@ -669,7 +679,6 @@ module API
end
expose :diff_head_sha, as: :sha
expose :merge_commit_sha
- expose :user_notes_count
expose :discussion_locked
expose :should_remove_source_branch?, as: :should_remove_source_branch
expose :force_remove_source_branch?, as: :force_remove_source_branch
@@ -677,7 +686,7 @@ module API
# Deprecated
expose :allow_collaboration, as: :allow_maintainer_to_push, if: -> (merge_request, _) { merge_request.for_fork? }
- expose :web_url do |merge_request, options|
+ expose :web_url do |merge_request|
Gitlab::UrlBuilder.build(merge_request)
end
@@ -724,6 +733,12 @@ module API
def build_available?(options)
options[:project]&.feature_available?(:builds, options[:current_user])
end
+
+ expose :user do
+ expose :can_merge do |merge_request, options|
+ merge_request.can_be_merged_by?(options[:current_user])
+ end
+ end
end
class MergeRequestChanges < MergeRequest
@@ -961,7 +976,7 @@ module API
if options[:group_members]
options[:group_members].find { |member| member.source_id == project.namespace_id }
else
- project.group.group_member(options[:current_user])
+ project.group.highest_group_member(options[:current_user])
end
end
end
@@ -996,7 +1011,7 @@ module API
end
class LabelBasic < Grape::Entity
- expose :id, :name, :color, :description
+ expose :id, :name, :color, :description, :text_color
end
class Label < LabelBasic
@@ -1012,12 +1027,20 @@ module API
label.open_merge_requests_count(options[:current_user])
end
- expose :priority do |label, options|
- label.priority(options[:project])
+ expose :subscribed do |label, options|
+ label.subscribed?(options[:current_user], options[:parent])
end
+ end
- expose :subscribed do |label, options|
- label.subscribed?(options[:current_user], options[:project])
+ class GroupLabel < Label
+ end
+
+ class ProjectLabel < Label
+ expose :priority do |label, options|
+ label.priority(options[:parent])
+ end
+ expose :is_project_label do |label, options|
+ label.is_a?(::ProjectLabel)
end
end
@@ -1087,11 +1110,44 @@ module API
expose :password_authentication_enabled_for_web, as: :signin_enabled
end
- class Release < Grape::Entity
+ # deprecated old Release representation
+ class TagRelease < Grape::Entity
expose :tag, as: :tag_name
expose :description
end
+ module Releases
+ class Link < Grape::Entity
+ expose :id
+ expose :name
+ expose :url
+ expose :external?, as: :external
+ end
+
+ class Source < Grape::Entity
+ expose :format
+ expose :url
+ end
+ end
+
+ class Release < TagRelease
+ expose :name
+ expose :description_html do |entity|
+ MarkupHelper.markdown_field(entity, :description)
+ end
+ expose :created_at
+ expose :author, using: Entities::UserBasic, if: -> (release, _) { release.author.present? }
+ expose :commit, using: Entities::Commit
+
+ expose :assets do
+ expose :assets_count, as: :count
+ expose :sources, using: Entities::Releases::Source
+ expose :links, using: Entities::Releases::Link do |release, options|
+ release.links.sorted
+ end
+ end
+ end
+
class Tag < Grape::Entity
expose :name, :message, :target
@@ -1100,7 +1156,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
- expose :release, using: Entities::Release do |repo_tag, options|
+ expose :release, using: Entities::TagRelease do |repo_tag, options|
options[:project].releases.find_by(tag: repo_tag.name)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -1185,8 +1241,11 @@ module API
end
class Trigger < Grape::Entity
+ include ::API::Helpers::Presentable
+
expose :id
- expose :token, :description
+ expose :token
+ expose :description
expose :created_at, :updated_at, :last_used
expose :owner, using: Entities::UserBasic
end
@@ -1311,13 +1370,9 @@ module API
class GitInfo < Grape::Entity
expose :repo_url, :ref, :sha, :before_sha
- expose :ref_type do |model|
- if model.tag
- 'tag'
- else
- 'branch'
- end
- end
+ expose :ref_type
+ expose :refspecs
+ expose :git_depth, as: :depth
end
class RunnerInfo < Grape::Entity
@@ -1507,5 +1562,38 @@ module API
expose :from_content
expose :to_content
end
+
+ module Platform
+ class Kubernetes < Grape::Entity
+ expose :api_url
+ expose :namespace
+ expose :authorization_type
+ expose :ca_cert
+ end
+ end
+
+ module Provider
+ class Gcp < Grape::Entity
+ expose :cluster_id
+ expose :status_name
+ expose :gcp_project_id
+ expose :zone
+ expose :machine_type
+ expose :num_nodes
+ expose :endpoint
+ end
+ end
+
+ class Cluster < Grape::Entity
+ expose :id, :name, :created_at
+ expose :provider_type, :platform_type, :environment_scope, :cluster_type
+ expose :user, using: Entities::UserBasic
+ expose :platform_kubernetes, using: Entities::Platform::Kubernetes
+ expose :provider_gcp, using: Entities::Provider::Gcp
+ end
+
+ class ClusterProject < Cluster
+ expose :project, using: Entities::BasicProjectDetails
+ end
end
end
diff --git a/lib/api/entities/container_registry.rb b/lib/api/entities/container_registry.rb
new file mode 100644
index 00000000000..00833ca7480
--- /dev/null
+++ b/lib/api/entities/container_registry.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module ContainerRegistry
+ class Repository < Grape::Entity
+ expose :id
+ expose :name
+ expose :path
+ expose :location
+ expose :created_at
+ end
+
+ class Tag < Grape::Entity
+ expose :name
+ expose :path
+ expose :location
+ end
+
+ class TagDetails < Tag
+ expose :revision
+ expose :short_revision
+ expose :digest
+ expose :created_at
+ expose :total_size
+ end
+ end
+ end
+end
diff --git a/lib/api/environments.rb b/lib/api/environments.rb
index 633f24d3c9a..5b0f3b914cb 100644
--- a/lib/api/environments.rb
+++ b/lib/api/environments.rb
@@ -22,7 +22,7 @@ module API
get ':id/environments' do
authorize! :read_environment, user_project
- present paginate(user_project.environments), with: Entities::Environment
+ present paginate(user_project.environments), with: Entities::Environment, current_user: current_user
end
desc 'Creates a new environment' do
@@ -40,7 +40,7 @@ module API
environment = user_project.environments.create(declared_params)
if environment.persisted?
- present environment, with: Entities::Environment
+ present environment, with: Entities::Environment, current_user: current_user
else
render_validation_error!(environment)
end
@@ -63,7 +63,7 @@ module API
update_params = declared_params(include_missing: false).extract!(:name, :external_url)
if environment.update(update_params)
- present environment, with: Entities::Environment
+ present environment, with: Entities::Environment, current_user: current_user
else
render_validation_error!(environment)
end
@@ -74,7 +74,7 @@ module API
success Entities::Environment
end
params do
- requires :environment_id, type: Integer, desc: 'The environment ID'
+ requires :environment_id, type: Integer, desc: 'The environment ID'
end
delete ':id/environments/:environment_id' do
authorize! :update_environment, user_project
@@ -88,7 +88,7 @@ module API
success Entities::Environment
end
params do
- requires :environment_id, type: Integer, desc: 'The environment ID'
+ requires :environment_id, type: Integer, desc: 'The environment ID'
end
post ':id/environments/:environment_id/stop' do
authorize! :read_environment, user_project
@@ -99,7 +99,7 @@ module API
environment.stop_with_action!(current_user)
status 200
- present environment, with: Entities::Environment
+ present environment, with: Entities::Environment, current_user: current_user
end
end
end
diff --git a/lib/api/features.rb b/lib/api/features.rb
index 1331248699f..4dc1834c644 100644
--- a/lib/api/features.rb
+++ b/lib/api/features.rb
@@ -16,15 +16,13 @@ module API
end
end
- # rubocop: disable CodeReuse/ActiveRecord
def gate_targets(params)
- targets = []
- targets << Feature.group(params[:feature_group]) if params[:feature_group]
- targets << UserFinder.new(params[:user]).find_by_username if params[:user]
+ Feature::Target.new(params).targets
+ end
- targets
+ def gate_specified?(params)
+ Feature::Target.new(params).gate_specified?
end
- # rubocop: enable CodeReuse/ActiveRecord
end
resource :features do
@@ -44,6 +42,8 @@ module API
requires :value, type: String, desc: '`true` or `false` to enable/disable, an integer for percentage of time'
optional :feature_group, type: String, desc: 'A Feature group name'
optional :user, type: String, desc: 'A GitLab username'
+ optional :group, type: String, desc: "A GitLab group's path, such as 'gitlab-org'"
+ optional :project, type: String, desc: 'A projects path, like gitlab-org/gitlab-ce'
end
post ':name' do
feature = Feature.get(params[:name])
@@ -52,13 +52,13 @@ module API
case value
when true
- if targets.present?
+ if gate_specified?(params)
targets.each { |target| feature.enable(target) }
else
feature.enable
end
when false
- if targets.present?
+ if gate_specified?(params)
targets.each { |target| feature.disable(target) }
else
feature.disable
diff --git a/lib/api/group_labels.rb b/lib/api/group_labels.rb
new file mode 100644
index 00000000000..0dbc5f45a68
--- /dev/null
+++ b/lib/api/group_labels.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module API
+ class GroupLabels < Grape::API
+ include PaginationParams
+ helpers ::API::Helpers::LabelHelpers
+
+ before { authenticate! }
+
+ params do
+ requires :id, type: String, desc: 'The ID of a group'
+ end
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Get all labels of the group' do
+ detail 'This feature was added in GitLab 11.8'
+ success Entities::GroupLabel
+ end
+ params do
+ use :pagination
+ end
+ get ':id/labels' do
+ get_labels(user_group, Entities::GroupLabel)
+ end
+
+ desc 'Create a new label' do
+ detail 'This feature was added in GitLab 11.8'
+ success Entities::GroupLabel
+ end
+ params do
+ use :label_create_params
+ end
+ post ':id/labels' do
+ create_label(user_group, Entities::GroupLabel)
+ end
+
+ desc 'Update an existing label. At least one optional parameter is required.' do
+ detail 'This feature was added in GitLab 11.8'
+ success Entities::GroupLabel
+ end
+ params do
+ requires :name, type: String, desc: 'The name of the label to be updated'
+ optional :new_name, type: String, desc: 'The new name of the label'
+ optional :color, type: String, desc: "The new color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
+ optional :description, type: String, desc: 'The new description of label'
+ at_least_one_of :new_name, :color, :description
+ end
+ put ':id/labels' do
+ update_label(user_group, Entities::GroupLabel)
+ end
+
+ desc 'Delete an existing label' do
+ detail 'This feature was added in GitLab 11.8'
+ success Entities::GroupLabel
+ end
+ params do
+ requires :name, type: String, desc: 'The name of the label to be deleted'
+ end
+ delete ':id/labels' do
+ delete_label(user_group)
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index c3eca713712..825fab62034 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -84,8 +84,8 @@ module API
page || not_found!('Wiki Page')
end
- def available_labels_for(label_parent)
- search_params = { include_ancestor_groups: true }
+ def available_labels_for(label_parent, include_ancestor_groups: true)
+ search_params = { include_ancestor_groups: include_ancestor_groups }
if label_parent.is_a?(Project)
search_params[:project_id] = label_parent.id
@@ -170,13 +170,6 @@ module API
end
end
- def find_project_label(id)
- labels = available_labels_for(user_project)
- label = labels.find_by_id(id) || labels.find_by_title(id)
-
- label || not_found!('Label')
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def find_project_issue(iid)
IssuesFinder.new(current_user, project_id: user_project.id).find_by!(iid: iid)
@@ -235,8 +228,8 @@ module API
forbidden! unless current_user.admin?
end
- def authorize!(action, subject = :global)
- forbidden! unless can?(current_user, action, subject)
+ def authorize!(action, subject = :global, reason = nil)
+ forbidden!(reason) unless can?(current_user, action, subject)
end
def authorize_push_project
@@ -251,6 +244,10 @@ module API
authorize! :read_build, user_project
end
+ def authorize_destroy_artifacts!
+ authorize! :destroy_artifacts, user_project
+ end
+
def authorize_update_builds!
authorize! :update_build, user_project
end
@@ -306,6 +303,12 @@ module API
items.search(text)
end
+ def order_options_with_tie_breaker
+ order_options = { params[:order_by] => params[:sort] }
+ order_options['id'] ||= 'desc'
+ order_options
+ end
+
# error helpers
def forbidden!(reason = nil)
@@ -400,7 +403,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def reorder_projects(projects)
- projects.reorder(params[:order_by] => params[:sort])
+ projects.reorder(order_options_with_tie_breaker)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -422,7 +425,7 @@ module API
def present_disk_file!(path, filename, content_type = 'application/octet-stream')
filename ||= File.basename(path)
- header['Content-Disposition'] = "attachment; filename=#{filename}"
+ header['Content-Disposition'] = ::Gitlab::ContentDisposition.format(disposition: 'attachment', filename: filename)
header['Content-Transfer-Encoding'] = 'binary'
content_type content_type
@@ -496,7 +499,11 @@ module API
def send_git_blob(repository, blob)
env['api.format'] = :txt
content_type 'text/plain'
- header['Content-Disposition'] = "attachment; filename=#{blob.name.inspect}"
+ header['Content-Disposition'] = ::Gitlab::ContentDisposition.format(disposition: 'inline', filename: blob.name)
+
+ # Let Workhorse examine the content and determine the better content disposition
+ header[Gitlab::Workhorse::DETECT_HEADER] = "true"
+
header(*Gitlab::Workhorse.send_git_blob(repository, blob))
end
@@ -512,7 +519,7 @@ module API
# `request`. We workaround this by defining methods that returns the right
# values.
def define_params_for_grape_middleware
- self.define_singleton_method(:request) { Rack::Request.new(env) }
+ self.define_singleton_method(:request) { ActionDispatch::Request.new(env) }
self.define_singleton_method(:params) { request.params.symbolize_keys }
end
diff --git a/lib/api/helpers/custom_validators.rb b/lib/api/helpers/custom_validators.rb
index 1058f4e8a5e..c86eae6f2da 100644
--- a/lib/api/helpers/custom_validators.rb
+++ b/lib/api/helpers/custom_validators.rb
@@ -22,9 +22,22 @@ module API
message: "should be an integer, 'None' or 'Any'"
end
end
+
+ class ArrayNoneAny < Grape::Validations::Base
+ def validate_param!(attr_name, params)
+ value = params[attr_name]
+
+ return if value.is_a?(Array) ||
+ [IssuableFinder::FILTER_NONE, IssuableFinder::FILTER_ANY].include?(value.to_s.downcase)
+
+ raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)],
+ message: "should be an array, 'None' or 'Any'"
+ end
+ end
end
end
end
Grape::Validations.register_validator(:absence, ::API::Helpers::CustomValidators::Absence)
Grape::Validations.register_validator(:integer_none_any, ::API::Helpers::CustomValidators::IntegerNoneAny)
+Grape::Validations.register_validator(:array_none_any, ::API::Helpers::CustomValidators::ArrayNoneAny)
diff --git a/lib/api/helpers/graphql_helpers.rb b/lib/api/helpers/graphql_helpers.rb
new file mode 100644
index 00000000000..94010ab1bc2
--- /dev/null
+++ b/lib/api/helpers/graphql_helpers.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ # GraphqlHelpers is used by the REST API when it is acting like a client
+ # against the graphql API. Helper code for the graphql server implementation
+ # should be in app/graphql/ or lib/gitlab/graphql/
+ module GraphqlHelpers
+ def conditionally_graphql!(fallback:, query:, context: {}, transform: nil)
+ return fallback.call unless Feature.enabled?(:graphql)
+
+ result = GitlabSchema.execute(query, context: context)
+
+ if transform
+ transform.call(result)
+ else
+ result
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index 4eaaca96b49..fe78049af87 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -81,6 +81,14 @@ module API
Gitlab::GlRepository.gl_repository(project, wiki?)
end
+ def gl_project_path
+ if wiki?
+ project.wiki.full_path
+ else
+ project.full_path
+ end
+ end
+
# Return the repository depending on whether we want the wiki or the
# regular repository
def repository
diff --git a/lib/api/helpers/label_helpers.rb b/lib/api/helpers/label_helpers.rb
new file mode 100644
index 00000000000..c11e7d614ab
--- /dev/null
+++ b/lib/api/helpers/label_helpers.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module LabelHelpers
+ extend Grape::API::Helpers
+
+ params :label_create_params do
+ requires :name, type: String, desc: 'The name of the label to be created'
+ requires :color, type: String, desc: "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
+ optional :description, type: String, desc: 'The description of label to be created'
+ end
+
+ def find_label(parent, id, include_ancestor_groups: true)
+ labels = available_labels_for(parent, include_ancestor_groups: include_ancestor_groups)
+ label = labels.find_by_id(id) || labels.find_by_title(id)
+
+ label || not_found!('Label')
+ end
+
+ def get_labels(parent, entity)
+ present paginate(available_labels_for(parent)), with: entity, current_user: current_user, parent: parent
+ end
+
+ def create_label(parent, entity)
+ authorize! :admin_label, parent
+
+ label = available_labels_for(parent).find_by_title(params[:name])
+ conflict!('Label already exists') if label
+
+ priority = params.delete(:priority)
+ label_params = declared_params(include_missing: false)
+
+ label =
+ if parent.is_a?(Project)
+ ::Labels::CreateService.new(label_params).execute(project: parent)
+ else
+ ::Labels::CreateService.new(label_params).execute(group: parent)
+ end
+
+ if label.persisted?
+ if parent.is_a?(Project)
+ label.prioritize!(parent, priority) if priority
+ end
+
+ present label, with: entity, current_user: current_user, parent: parent
+ else
+ render_validation_error!(label)
+ end
+ end
+
+ def update_label(parent, entity)
+ authorize! :admin_label, parent
+
+ label = find_label(parent, params[:name], include_ancestor_groups: false)
+ update_priority = params.key?(:priority)
+ priority = params.delete(:priority)
+
+ label = ::Labels::UpdateService.new(declared_params(include_missing: false)).execute(label)
+ render_validation_error!(label) unless label.valid?
+
+ if parent.is_a?(Project) && update_priority
+ if priority.nil?
+ label.unprioritize!(parent)
+ else
+ label.prioritize!(parent, priority)
+ end
+ end
+
+ present label, with: entity, current_user: current_user, parent: parent
+ end
+
+ def delete_label(parent)
+ authorize! :admin_label, parent
+
+ label = find_label(parent, params[:name], include_ancestor_groups: false)
+
+ destroy_conditionally!(label)
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index 216b2c45741..795dca5cf03 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -70,14 +70,7 @@ module API
def find_noteable(parent, noteables_str, noteable_id)
noteable = public_send("find_#{parent}_#{noteables_str.singularize}", noteable_id) # rubocop:disable GitlabSecurity/PublicSend
- readable =
- if noteable.is_a?(Commit)
- # for commits there is not :read_commit policy, check if user
- # has :read_note permission on the commit's project
- can?(current_user, :read_note, user_project)
- else
- can?(current_user, noteable_read_ability_name(noteable), noteable)
- end
+ readable = can?(current_user, noteable_read_ability_name(noteable), noteable)
return not_found!(noteables_str) unless readable
@@ -89,12 +82,11 @@ module API
end
def create_note(noteable, opts)
- policy_object = noteable.is_a?(Commit) ? user_project : noteable
- authorize!(:create_note, policy_object)
+ authorize!(:create_note, noteable)
parent = noteable_parent(noteable)
- opts.delete(:created_at) unless current_user.can?(:set_note_created_at, policy_object)
+ opts.delete(:created_at) unless current_user.can?(:set_note_created_at, noteable)
opts[:updated_at] = opts[:created_at] if opts[:created_at]
diff --git a/lib/api/helpers/pagination.rb b/lib/api/helpers/pagination.rb
index d311cbb5f7e..94b58a64d26 100644
--- a/lib/api/helpers/pagination.rb
+++ b/lib/api/helpers/pagination.rb
@@ -13,6 +13,33 @@ module API
strategy.new(self).paginate(relation)
end
+ class Base
+ private
+
+ def per_page
+ @per_page ||= params[:per_page]
+ end
+
+ def base_request_uri
+ @base_request_uri ||= URI.parse(request.url).tap do |uri|
+ uri.host = Gitlab.config.gitlab.host
+ uri.port = nil
+ end
+ end
+
+ def build_page_url(query_params:)
+ base_request_uri.tap do |uri|
+ uri.query = query_params
+ end.to_s
+ end
+
+ def page_href(next_page_params = {})
+ query_params = params.merge(**next_page_params, per_page: per_page).to_query
+
+ build_page_url(query_params: query_params)
+ end
+ end
+
class KeysetPaginationInfo
attr_reader :relation, :request_context
@@ -85,7 +112,7 @@ module API
end
end
- class KeysetPaginationStrategy
+ class KeysetPaginationStrategy < Base
attr_reader :request_context
delegate :params, :header, :request, to: :request_context
@@ -122,7 +149,7 @@ module API
def conditions(pagination)
fields = pagination.fields
- return nil if fields.empty?
+ return if fields.empty?
placeholder = fields.map { '?' }
@@ -141,12 +168,8 @@ module API
]
end
- def per_page
- params[:per_page]
- end
-
def add_default_pagination_headers
- header 'X-Per-Page', per_page.to_s
+ header 'X-Per-Page', per_page.to_s
end
def add_navigation_links(next_page_params)
@@ -154,22 +177,12 @@ module API
header 'Link', link_for('next', next_page_params)
end
- def page_href(next_page_params)
- request_url = request.url.split('?').first
- request_params = params.dup
- request_params[:per_page] = per_page
-
- request_params.merge!(next_page_params) if next_page_params
-
- "#{request_url}?#{request_params.to_query}"
- end
-
def link_for(rel, next_page_params)
%(<#{page_href(next_page_params)}>; rel="#{rel}")
end
end
- class DefaultPaginationStrategy
+ class DefaultPaginationStrategy < Base
attr_reader :request_context
delegate :params, :header, :request, to: :request_context
@@ -178,24 +191,33 @@ module API
end
def paginate(relation)
- relation = add_default_order(relation)
-
- relation.page(params[:page]).per(params[:per_page]).tap do |data|
+ paginate_with_limit_optimization(add_default_order(relation)).tap do |data|
add_pagination_headers(data)
end
end
private
- # rubocop: disable CodeReuse/ActiveRecord
+ def paginate_with_limit_optimization(relation)
+ pagination_data = relation.page(params[:page]).per(params[:per_page])
+ return pagination_data unless pagination_data.is_a?(ActiveRecord::Relation)
+ return pagination_data unless Feature.enabled?(:api_kaminari_count_with_limit)
+
+ limited_total_count = pagination_data.total_count_with_limit
+ if limited_total_count > Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT
+ pagination_data.without_count
+ else
+ pagination_data
+ end
+ end
+
def add_default_order(relation)
if relation.is_a?(ActiveRecord::Relation) && relation.order_values.empty?
- relation = relation.order(:id)
+ relation = relation.order(:id) # rubocop: disable CodeReuse/ActiveRecord
end
relation
end
- # rubocop: enable CodeReuse/ActiveRecord
def add_pagination_headers(paginated_data)
header 'X-Per-Page', paginated_data.limit_value.to_s
@@ -211,27 +233,13 @@ module API
end
def pagination_links(paginated_data)
- request_url = request.url.split('?').first
- request_params = params.clone
- request_params[:per_page] = paginated_data.limit_value
-
- links = []
-
- request_params[:page] = paginated_data.prev_page
- links << %(<#{request_url}?#{request_params.to_query}>; rel="prev") if request_params[:page]
-
- request_params[:page] = paginated_data.next_page
- links << %(<#{request_url}?#{request_params.to_query}>; rel="next") if request_params[:page]
-
- request_params[:page] = 1
- links << %(<#{request_url}?#{request_params.to_query}>; rel="first")
-
- unless data_without_counts?(paginated_data)
- request_params[:page] = total_pages(paginated_data)
- links << %(<#{request_url}?#{request_params.to_query}>; rel="last")
- end
+ [].tap do |links|
+ links << %(<#{page_href(page: paginated_data.prev_page)}>; rel="prev") if paginated_data.prev_page
+ links << %(<#{page_href(page: paginated_data.next_page)}>; rel="next") if paginated_data.next_page
+ links << %(<#{page_href(page: 1)}>; rel="first")
- links.join(', ')
+ links << %(<#{page_href(page: total_pages(paginated_data))}>; rel="last") unless data_without_counts?(paginated_data)
+ end.join(', ')
end
def total_pages(paginated_data)
diff --git a/lib/api/helpers/presentable.rb b/lib/api/helpers/presentable.rb
new file mode 100644
index 00000000000..973c2132efe
--- /dev/null
+++ b/lib/api/helpers/presentable.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ ##
+ # This module makes it possible to use `app/presenters` with
+ # Grape Entities. It instantiates model presenter and passes
+ # options defined in the API endpoint to the presenter itself.
+ #
+ # present object, with: Entities::Something,
+ # current_user: current_user,
+ # another_option: 'my options'
+ #
+ # Example above will make `current_user` and `another_option`
+ # values available in the subclass of `Gitlab::View::Presenter`
+ # thorough a separate method in the presenter.
+ #
+ # The model class needs to have `::Presentable` module mixed in
+ # if you want to use `API::Helpers::Presentable`.
+ #
+ module Presentable
+ extend ActiveSupport::Concern
+
+ def initialize(object, options = {})
+ super(object.present(options), options)
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/runner.rb b/lib/api/helpers/runner.rb
index 45d0343bc89..ff73a49d5e8 100644
--- a/lib/api/helpers/runner.rb
+++ b/lib/api/helpers/runner.rb
@@ -26,7 +26,7 @@ module API
end
def get_runner_ip
- { ip_address: request.ip }
+ { ip_address: env["action_dispatch.remote_ip"].to_s || request.ip }
end
def current_runner
diff --git a/lib/api/helpers/version.rb b/lib/api/helpers/version.rb
new file mode 100644
index 00000000000..7f53094e90c
--- /dev/null
+++ b/lib/api/helpers/version.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ class Version
+ include Helpers::RelatedResourcesHelpers
+
+ def initialize(version)
+ @version = version.to_s
+
+ unless API.versions.include?(version)
+ raise ArgumentError, 'Unknown API version!'
+ end
+ end
+
+ def root_path
+ File.join('/', API.prefix.to_s, @version)
+ end
+
+ def root_url
+ @root_url ||= expose_url(root_path)
+ end
+
+ def to_s
+ @version
+ end
+ end
+ end
+end
diff --git a/lib/api/import_github.rb b/lib/api/import_github.rb
new file mode 100644
index 00000000000..bb4e536cf57
--- /dev/null
+++ b/lib/api/import_github.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module API
+ class ImportGithub < Grape::API
+ rescue_from Octokit::Unauthorized, with: :provider_unauthorized
+
+ helpers do
+ def client
+ @client ||= Gitlab::LegacyGithubImport::Client.new(params[:personal_access_token], client_options)
+ end
+
+ def access_params
+ { github_access_token: params[:personal_access_token] }
+ end
+
+ def client_options
+ {}
+ end
+
+ def provider
+ :github
+ end
+ end
+
+ desc 'Import a GitHub project' do
+ detail 'This feature was introduced in GitLab 11.3.4.'
+ success Entities::ProjectEntity
+ end
+ params do
+ requires :personal_access_token, type: String, desc: 'GitHub personal access token'
+ requires :repo_id, type: Integer, desc: 'GitHub repository ID'
+ optional :new_name, type: String, desc: 'New repo name'
+ requires :target_namespace, type: String, desc: 'Namespace to import repo into'
+ end
+ post 'import/github' do
+ result = Import::GithubService.new(client, current_user, params).execute(access_params, provider)
+
+ if result[:status] == :success
+ present ProjectSerializer.new.represent(result[:project])
+ else
+ status result[:http_status]
+ { errors: result[:message] }
+ end
+ end
+ end
+end
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index ae40b5f7557..70b32f7d758 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -77,6 +77,7 @@ module API
when ::Gitlab::GitAccessResult::Success
payload = {
gl_repository: gl_repository,
+ gl_project_path: gl_project_path,
gl_id: Gitlab::GlId.gl_id(user),
gl_username: user&.username,
git_config_options: [],
@@ -117,13 +118,7 @@ module API
raise ActiveRecord::RecordNotFound.new("No key_id or user_id passed!")
end
- token_handler = Gitlab::LfsToken.new(actor)
-
- {
- username: token_handler.actor_name,
- lfs_token: token_handler.token,
- repository_http_path: project.http_url_to_repo
- }
+ Gitlab::LfsToken.new(actor).authentication_payload(project.http_url_to_repo)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -256,8 +251,9 @@ module API
post '/post_receive' do
status 200
+
PostReceive.perform_async(params[:gl_repository], params[:identifier],
- params[:changes])
+ params[:changes], params[:push_options].to_a)
broadcast_message = BroadcastMessage.current&.last&.message
reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index dac700482b4..d59d2f5a098 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -29,13 +29,12 @@ module API
issues = IssuesFinder.new(current_user, args).execute
.preload(:assignees, :labels, :notes, :timelogs, :project, :author, :closed_by)
-
- issues.reorder(args[:order_by] => args[:sort])
+ issues.reorder(order_options_with_tie_breaker)
end
# rubocop: enable CodeReuse/ActiveRecord
params :issues_params do
- optional :labels, type: String, desc: 'Comma-separated list of label names'
+ optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names'
optional :milestone, type: String, desc: 'Milestone title'
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
desc: 'Return issues ordered by `created_at` or `updated_at` fields.'
@@ -43,7 +42,8 @@ module API
desc: 'Return issues sorted in `asc` or `desc` order.'
optional :milestone, type: String, desc: 'Return issues for a specific milestone'
optional :iids, type: Array[Integer], desc: 'The IID array of issues'
- optional :search, type: String, desc: 'Search issues for text present in the title or description'
+ 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'
optional :created_after, type: DateTime, desc: 'Return issues created after the specified time'
optional :created_before, type: DateTime, desc: 'Return issues created before the specified time'
optional :updated_after, type: DateTime, desc: 'Return issues updated after the specified time'
@@ -54,6 +54,7 @@ module API
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
+ optional :confidential, type: Boolean, desc: 'Filter confidential or public issues'
use :pagination
use :issues_params_ee
@@ -64,7 +65,7 @@ module API
optional :assignee_ids, type: Array[Integer], desc: 'The array of user IDs to assign issue'
optional :assignee_id, type: Integer, desc: '[Deprecated] The ID of a user to assign issue'
optional :milestone_id, type: Integer, desc: 'The ID of a milestone to assign issue'
- optional :labels, type: String, desc: 'Comma-separated list of label names'
+ optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names'
optional :due_date, type: String, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :confidential, type: Boolean, desc: 'Boolean parameter if the issue should be confidential'
optional :discussion_locked, type: Boolean, desc: " Boolean parameter indicating if the issue's discussion is locked"
@@ -294,7 +295,7 @@ module API
end
# rubocop: enable CodeReuse/ActiveRecord
- desc 'List merge requests that are related to the issue' do
+ desc 'List merge requests that are related to the issue' do
success Entities::MergeRequestBasic
end
params do
@@ -303,22 +304,17 @@ module API
get ':id/issues/:issue_iid/related_merge_requests' do
issue = find_project_issue(params[:issue_iid])
- merge_request_iids = ::Issues::ReferencedMergeRequestsService.new(user_project, current_user)
+ merge_requests = ::Issues::ReferencedMergeRequestsService.new(user_project, current_user)
.execute(issue)
.flatten
- .map(&:iid)
-
- merge_requests =
- if merge_request_iids.present?
- MergeRequestsFinder.new(current_user, project_id: user_project.id, iids: merge_request_iids).execute
- else
- MergeRequest.none
- end
- present paginate(merge_requests), with: Entities::MergeRequestBasic, current_user: current_user, project: user_project
+ present paginate(::Kaminari.paginate_array(merge_requests)),
+ with: Entities::MergeRequestBasic,
+ current_user: current_user,
+ project: user_project
end
- desc 'List merge requests closing issue' do
+ desc 'List merge requests closing issue' do
success Entities::MergeRequestBasic
end
params do
@@ -335,7 +331,7 @@ module API
end
# rubocop: enable CodeReuse/ActiveRecord
- desc 'List participants for an issue' do
+ desc 'List participants for an issue' do
success Entities::UserBasic
end
params do
diff --git a/lib/api/job_artifacts.rb b/lib/api/job_artifacts.rb
index a4068a200b3..e7fed55170e 100644
--- a/lib/api/job_artifacts.rb
+++ b/lib/api/job_artifacts.rb
@@ -23,17 +23,14 @@ module API
requires :job, type: String, desc: 'The name for the job'
end
route_setting :authentication, job_token_allowed: true
- # rubocop: disable CodeReuse/ActiveRecord
get ':id/jobs/artifacts/:ref_name/download',
requirements: { ref_name: /.+/ } do
authorize_download_artifacts!
- builds = user_project.latest_successful_builds_for(params[:ref_name])
- latest_build = builds.find_by!(name: params[:job])
+ latest_build = user_project.latest_successful_build_for!(params[:job], params[:ref_name])
present_carrierwave_file!(latest_build.artifacts_file)
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Download a specific file from artifacts archive from a ref' do
detail 'This feature was introduced in GitLab 11.5'
@@ -48,7 +45,7 @@ module API
requirements: { ref_name: /.+/ } do
authorize_download_artifacts!
- build = user_project.latest_successful_build_for(params[:job], params[:ref_name])
+ build = user_project.latest_successful_build_for!(params[:job], params[:ref_name])
path = Gitlab::Ci::Build::Artifacts::Path
.new(params[:artifact_path])
@@ -112,6 +109,22 @@ module API
status 200
present build, with: Entities::Job
end
+
+ desc 'Delete the artifacts files from a job' do
+ detail 'This feature was introduced in GitLab 11.9'
+ end
+ params do
+ requires :job_id, type: Integer, desc: 'The ID of a job'
+ end
+ delete ':id/jobs/:job_id/artifacts' do
+ authorize_destroy_artifacts!
+ build = find_build!(params[:job_id])
+ authorize!(:destroy_artifacts, build)
+
+ build.erase_erasable_artifacts!
+
+ status :no_content
+ end
end
end
end
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index 80a5cbd6b19..59f0dbe8a9b 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -38,6 +38,8 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/jobs' do
+ authorize_read_builds!
+
builds = user_project.builds.order('id DESC')
builds = filter_builds(builds, params[:scope])
@@ -50,13 +52,16 @@ module API
success Entities::Job
end
params do
- requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
+ requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
use :optional_scope
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/pipelines/:pipeline_id/jobs' do
+ authorize!(:read_pipeline, user_project)
pipeline = user_project.ci_pipelines.find(params[:pipeline_id])
+ authorize!(:read_build, pipeline)
+
builds = pipeline.builds
builds = filter_builds(builds, params[:scope])
builds = builds.preload(:job_artifacts_archive, :job_artifacts, project: [:namespace])
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index 2e676b0aa6b..d729d3ee625 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -3,6 +3,7 @@
module API
class Labels < Grape::API
include PaginationParams
+ helpers ::API::Helpers::LabelHelpers
before { authenticate! }
@@ -11,98 +12,50 @@ module API
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get all labels of the project' do
- success Entities::Label
+ success Entities::ProjectLabel
end
params do
use :pagination
end
get ':id/labels' do
- present paginate(available_labels_for(user_project)), with: Entities::Label, current_user: current_user, project: user_project
+ get_labels(user_project, Entities::ProjectLabel)
end
desc 'Create a new label' do
- success Entities::Label
+ success Entities::ProjectLabel
end
params do
- requires :name, type: String, desc: 'The name of the label to be created'
- requires :color, type: String, desc: "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
- optional :description, type: String, desc: 'The description of label to be created'
+ use :label_create_params
optional :priority, type: Integer, desc: 'The priority of the label', allow_blank: true
end
- # rubocop: disable CodeReuse/ActiveRecord
post ':id/labels' do
- authorize! :admin_label, user_project
-
- label = available_labels_for(user_project).find_by(title: params[:name])
- conflict!('Label already exists') if label
-
- priority = params.delete(:priority)
- label = ::Labels::CreateService.new(declared_params(include_missing: false)).execute(project: user_project)
-
- if label.valid?
- label.prioritize!(user_project, priority) if priority
- present label, with: Entities::Label, current_user: current_user, project: user_project
- else
- render_validation_error!(label)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- desc 'Delete an existing label' do
- success Entities::Label
- end
- params do
- requires :name, type: String, desc: 'The name of the label to be deleted'
- end
- # rubocop: disable CodeReuse/ActiveRecord
- delete ':id/labels' do
- authorize! :admin_label, user_project
-
- label = user_project.labels.find_by(title: params[:name])
- not_found!('Label') unless label
-
- destroy_conditionally!(label)
+ create_label(user_project, Entities::ProjectLabel)
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Update an existing label. At least one optional parameter is required.' do
- success Entities::Label
+ success Entities::ProjectLabel
end
params do
- requires :name, type: String, desc: 'The name of the label to be updated'
+ requires :name, type: String, desc: 'The name of the label to be updated'
optional :new_name, type: String, desc: 'The new name of the label'
optional :color, type: String, desc: "The new color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
optional :description, type: String, desc: 'The new description of label'
optional :priority, type: Integer, desc: 'The priority of the label', allow_blank: true
at_least_one_of :new_name, :color, :description, :priority
end
- # rubocop: disable CodeReuse/ActiveRecord
put ':id/labels' do
- authorize! :admin_label, user_project
-
- label = user_project.labels.find_by(title: params[:name])
- not_found!('Label not found') unless label
-
- update_priority = params.key?(:priority)
- priority = params.delete(:priority)
- label_params = declared_params(include_missing: false)
- # Rename new name to the actual label attribute name
- label_params[:name] = label_params.delete(:new_name) if label_params.key?(:new_name)
-
- label = ::Labels::UpdateService.new(label_params).execute(label)
- render_validation_error!(label) unless label.valid?
-
- if update_priority
- if priority.nil?
- label.unprioritize!(user_project)
- else
- label.prioritize!(user_project, priority)
- end
- end
+ update_label(user_project, Entities::ProjectLabel)
+ end
- present label, with: Entities::Label, current_user: current_user, project: user_project
+ desc 'Delete an existing label' do
+ success Entities::ProjectLabel
+ end
+ params do
+ requires :name, type: String, desc: 'The name of the label to be deleted'
+ end
+ delete ':id/labels' do
+ delete_label(user_project)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index 0342a4b6654..a7672021db0 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -8,7 +8,8 @@ module API
requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
end
post '/lint' do
- error = Gitlab::Ci::YamlProcessor.validation_message(params[:content])
+ error = Gitlab::Ci::YamlProcessor.validation_message(params[:content],
+ user: current_user)
status 200
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 8c1951cc535..6518ebbcff5 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -12,6 +12,9 @@ module API
helpers do
params :optional_params_ee do
end
+
+ params :optional_merge_requests_search_params do
+ end
end
def self.update_params_at_least_one_of
@@ -38,7 +41,7 @@ module API
args[:scope] = args[:scope].underscore if args[:scope]
merge_requests = MergeRequestsFinder.new(current_user, args).execute
- .reorder(args[:order_by] => args[:sort])
+ .reorder(order_options_with_tie_breaker)
merge_requests = paginate(merge_requests)
.preload(:source_project, :target_project)
@@ -95,7 +98,7 @@ module API
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return merge requests sorted in `asc` or `desc` order.'
optional :milestone, type: String, desc: 'Return merge requests for a specific milestone'
- optional :labels, type: String, desc: 'Comma-separated list of label names'
+ optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names'
optional :created_after, type: DateTime, desc: 'Return merge requests created after the specified time'
optional :created_before, type: DateTime, desc: 'Return merge requests created before the specified time'
optional :updated_after, type: DateTime, desc: 'Return merge requests updated after the specified time'
@@ -109,8 +112,11 @@ module API
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
optional :source_branch, type: String, desc: 'Return merge requests with the given source branch'
optional :target_branch, type: String, desc: 'Return merge requests with the given target branch'
- optional :search, type: String, desc: 'Search merge requests for text present in the title or description'
+ optional :search, type: String, desc: 'Search merge requests 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'
optional :wip, type: String, values: %w[yes no], desc: 'Search merge requests for WIP in the title'
+
+ use :optional_merge_requests_search_params
use :pagination
end
end
@@ -178,7 +184,7 @@ module API
optional :description, type: String, desc: 'The description of the merge request'
optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request'
optional :milestone_id, type: Integer, desc: 'The ID of a milestone to assign the merge request'
- optional :labels, type: String, desc: 'Comma-separated list of label names'
+ optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names'
optional :remove_source_branch, type: Boolean, desc: 'Remove source branch when merging'
optional :allow_collaboration, type: Boolean, desc: 'Allow commits from members who can merge to the target branch'
optional :allow_maintainer_to_push, type: Boolean, as: :allow_collaboration, desc: '[deprecated] See allow_collaboration'
@@ -342,6 +348,7 @@ module API
end
params do
optional :merge_commit_message, type: String, desc: 'Custom merge commit message'
+ optional :squash_commit_message, type: String, desc: 'Custom squash commit message'
optional :should_remove_source_branch, type: Boolean,
desc: 'When true, the source branch will be deleted if possible'
optional :merge_when_pipeline_succeeds, type: Boolean,
@@ -367,10 +374,11 @@ module API
merge_request.update(squash: params[:squash]) if params[:squash]
- merge_params = {
+ merge_params = HashWithIndifferentAccess.new(
commit_message: params[:merge_commit_message],
+ squash_commit_message: params[:squash_commit_message],
should_remove_source_branch: params[:should_remove_source_branch]
- }
+ )
if merge_when_pipeline_succeeds && merge_request.head_pipeline && merge_request.head_pipeline.active?
::MergeRequests::MergeWhenPipelineSucceedsService
@@ -385,6 +393,31 @@ module API
present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
end
+ desc 'Merge a merge request to its default temporary merge ref path'
+ params do
+ optional :merge_commit_message, type: String, desc: 'Custom merge commit message'
+ end
+ put ':id/merge_requests/:merge_request_iid/merge_to_ref' do
+ merge_request = find_project_merge_request(params[:merge_request_iid])
+
+ authorize! :admin_merge_request, user_project
+
+ merge_params = {
+ commit_message: params[:merge_commit_message]
+ }
+
+ result = ::MergeRequests::MergeToRefService
+ .new(merge_request.target_project, current_user, merge_params)
+ .execute(merge_request)
+
+ if result[:status] == :success
+ present result.slice(:commit_id), 200
+ else
+ http_status = result[:http_status] || 400
+ render_api_error!(result[:message], http_status)
+ end
+ end
+
desc 'Cancel merge if "Merge When Pipeline Succeeds" is enabled' do
success Entities::MergeRequest
end
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 1bdf7aeb119..f7bd092ce50 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -39,7 +39,7 @@ module API
# at the DB query level (which we cannot in that case), the current
# page can have less elements than :per_page even if
# there's more than one page.
- raw_notes = noteable.notes.with_metadata.reorder(params[:order_by] => params[:sort])
+ raw_notes = noteable.notes.with_metadata.reorder(order_options_with_tie_breaker)
notes =
# paginate() only works with a relation. This could lead to a
# mismatch between the pagination headers info and the actual notes
diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb
index 47b711917e2..c86b50d3736 100644
--- a/lib/api/pipeline_schedules.rb
+++ b/lib/api/pipeline_schedules.rb
@@ -32,7 +32,7 @@ module API
success Entities::PipelineScheduleDetails
end
params do
- requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
+ requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
end
get ':id/pipeline_schedules/:pipeline_schedule_id' do
present pipeline_schedule, with: Entities::PipelineScheduleDetails
@@ -87,7 +87,7 @@ module API
success Entities::PipelineScheduleDetails
end
params do
- requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
+ requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
end
post ':id/pipeline_schedules/:pipeline_schedule_id/take_ownership' do
authorize! :update_pipeline_schedule, pipeline_schedule
@@ -103,7 +103,7 @@ module API
success Entities::PipelineScheduleDetails
end
params do
- requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
+ requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
end
delete ':id/pipeline_schedules/:pipeline_schedule_id' do
authorize! :admin_pipeline_schedule, pipeline_schedule
diff --git a/lib/api/pipelines.rb b/lib/api/pipelines.rb
index 7a7b23d2bbb..ac8fe98e55e 100644
--- a/lib/api/pipelines.rb
+++ b/lib/api/pipelines.rb
@@ -42,7 +42,7 @@ module API
success Entities::Pipeline
end
params do
- requires :ref, type: String, desc: 'Reference'
+ requires :ref, type: String, desc: 'Reference'
optional :variables, Array, desc: 'Array of variables available in the pipeline'
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -76,7 +76,7 @@ module API
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
end
get ':id/pipelines/:pipeline_id' do
- authorize! :read_pipeline, user_project
+ authorize! :read_pipeline, pipeline
present pipeline, with: Entities::Pipeline
end
@@ -101,10 +101,10 @@ module API
success Entities::Pipeline
end
params do
- requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
+ requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
end
post ':id/pipelines/:pipeline_id/retry' do
- authorize! :update_pipeline, user_project
+ authorize! :update_pipeline, pipeline
pipeline.retry_failed(current_user)
@@ -116,10 +116,10 @@ module API
success Entities::Pipeline
end
params do
- requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
+ requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
end
post ':id/pipelines/:pipeline_id/cancel' do
- authorize! :update_pipeline, user_project
+ authorize! :update_pipeline, pipeline
pipeline.cancel_running
diff --git a/lib/api/project_clusters.rb b/lib/api/project_clusters.rb
new file mode 100644
index 00000000000..c96261a7b57
--- /dev/null
+++ b/lib/api/project_clusters.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+module API
+ class ProjectClusters < Grape::API
+ include PaginationParams
+
+ before { authenticate! }
+
+ # EE::API::ProjectClusters will
+ # override these methods
+ helpers do
+ params :create_params_ee do
+ end
+
+ params :update_params_ee do
+ end
+ end
+
+ params do
+ requires :id, type: String, desc: 'The ID of the project'
+ end
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Get all clusters from the project' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Cluster
+ end
+ params do
+ use :pagination
+ end
+ get ':id/clusters' do
+ authorize! :read_cluster, user_project
+
+ present paginate(clusters_for_current_user), with: Entities::Cluster
+ end
+
+ desc 'Get specific cluster for the project' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::ClusterProject
+ end
+ params do
+ requires :cluster_id, type: Integer, desc: 'The cluster ID'
+ end
+ get ':id/clusters/:cluster_id' do
+ authorize! :read_cluster, cluster
+
+ present cluster, with: Entities::ClusterProject
+ end
+
+ desc 'Adds an existing cluster' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::ClusterProject
+ end
+ params do
+ requires :name, type: String, desc: 'Cluster name'
+ optional :enabled, type: Boolean, default: true, desc: 'Determines if cluster is active or not, defaults to true'
+ requires :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do
+ requires :api_url, type: String, allow_blank: false, desc: 'URL to access the Kubernetes API'
+ requires :token, type: String, desc: 'Token to authenticate against Kubernetes'
+ optional :ca_cert, type: String, desc: 'TLS certificate (needed if API is using a self-signed TLS certificate)'
+ optional :namespace, type: String, desc: 'Unique namespace related to Project'
+ optional :authorization_type, type: String, values: Clusters::Platforms::Kubernetes.authorization_types.keys, default: 'rbac', desc: 'Cluster authorization type, defaults to RBAC'
+ end
+ use :create_params_ee
+ end
+ post ':id/clusters/user' do
+ authorize! :add_cluster, user_project, 'Instance does not support multiple Kubernetes clusters'
+
+ user_cluster = ::Clusters::CreateService
+ .new(current_user, create_cluster_user_params)
+ .execute
+
+ if user_cluster.persisted?
+ present user_cluster, with: Entities::ClusterProject
+ else
+ render_validation_error!(user_cluster)
+ end
+ end
+
+ desc 'Update an existing cluster' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::ClusterProject
+ end
+ params do
+ requires :cluster_id, type: Integer, desc: 'The cluster ID'
+ optional :name, type: String, desc: 'Cluster name'
+ optional :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do
+ optional :api_url, type: String, desc: 'URL to access the Kubernetes API'
+ optional :token, type: String, desc: 'Token to authenticate against Kubernetes'
+ optional :ca_cert, type: String, desc: 'TLS certificate (needed if API is using a self-signed TLS certificate)'
+ optional :namespace, type: String, desc: 'Unique namespace related to Project'
+ end
+ use :update_params_ee
+ end
+ put ':id/clusters/:cluster_id' do
+ authorize! :update_cluster, cluster
+
+ update_service = Clusters::UpdateService.new(current_user, update_cluster_params)
+
+ if update_service.execute(cluster)
+ present cluster, with: Entities::ClusterProject
+ else
+ render_validation_error!(cluster)
+ end
+ end
+
+ desc 'Remove a cluster' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::ClusterProject
+ end
+ params do
+ requires :cluster_id, type: Integer, desc: 'The Cluster ID'
+ end
+ delete ':id/clusters/:cluster_id' do
+ authorize! :admin_cluster, cluster
+
+ destroy_conditionally!(cluster)
+ end
+ end
+
+ helpers do
+ def clusters_for_current_user
+ @clusters_for_current_user ||= ClustersFinder.new(user_project, current_user, :all).execute
+ end
+
+ def cluster
+ @cluster ||= clusters_for_current_user.find(params[:cluster_id])
+ end
+
+ def create_cluster_user_params
+ declared_params.merge({
+ provider_type: :user,
+ platform_type: :kubernetes,
+ clusterable: user_project
+ })
+ end
+
+ def update_cluster_params
+ declared_params(include_missing: false).without(:cluster_id)
+ end
+ end
+ end
+end
diff --git a/lib/api/project_milestones.rb b/lib/api/project_milestones.rb
index da31bcb8dac..ca24742b7a3 100644
--- a/lib/api/project_milestones.rb
+++ b/lib/api/project_milestones.rb
@@ -98,6 +98,23 @@ module API
milestone_issuables_for(user_project, :merge_request)
end
+
+ desc 'Promote a milestone to group milestone' do
+ detail 'This feature was introduced in GitLab 11.9'
+ end
+ post ':id/milestones/:milestone_id/promote' do
+ begin
+ authorize! :admin_milestone, user_project
+ authorize! :admin_milestone, user_project.group
+
+ milestone = user_project.milestones.find(params[:milestone_id])
+ Milestones::PromoteService.new(user_project, current_user).execute(milestone)
+
+ status(200)
+ rescue Milestones::PromoteService::PromoteMilestoneError => error
+ render_api_error!(error.message, 400)
+ end
+ end
end
end
end
diff --git a/lib/api/project_statistics.rb b/lib/api/project_statistics.rb
new file mode 100644
index 00000000000..2f73785f72d
--- /dev/null
+++ b/lib/api/project_statistics.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module API
+ class ProjectStatistics < Grape::API
+ before do
+ authenticate!
+ not_found! unless user_project.daily_statistics_enabled?
+ authorize! :daily_statistics, user_project
+ end
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Get the list of project fetch statistics for the last 30 days'
+ get ":id/statistics" do
+ statistic_finder = ::Projects::DailyStatisticsFinder.new(user_project)
+
+ present statistic_finder, with: Entities::ProjectDailyStatistics
+ end
+ end
+ end
+end
diff --git a/lib/api/project_templates.rb b/lib/api/project_templates.rb
index d05ddad7466..119902a189c 100644
--- a/lib/api/project_templates.rb
+++ b/lib/api/project_templates.rb
@@ -36,7 +36,10 @@ module API
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
- get ':id/templates/:type/:name', requirements: { name: /[\w\.-]+/ } do
+ # The regex is needed to ensure a period (e.g. agpl-3.0)
+ # isn't confused with a format type. We also need to allow encoded
+ # values (e.g. C%2B%2B for C++), so allow % and + as well.
+ get ':id/templates/:type/:name', requirements: { name: /[\w%.+-]+/ } do
template = TemplateFinder
.build(params[:type], user_project, name: params[:name])
.execute
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index f5d21d8923f..91501ba4d36 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -25,6 +25,9 @@ module API
projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled]
projects = projects.with_statistics if params[:statistics]
+ lang = params[:with_programming_language]
+ projects = projects.with_programming_language(lang) if lang
+
projects
end
@@ -91,6 +94,7 @@ module API
optional :membership, type: Boolean, default: false, desc: 'Limit by projects that the current user is a member of'
optional :with_issues_enabled, type: Boolean, default: false, desc: 'Limit by enabled issues feature'
optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature'
+ optional :with_programming_language, type: String, desc: 'Limit to repositories which use the given programming language'
optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user'
use :optional_filter_params_ee
@@ -128,7 +132,7 @@ module API
end
end
- resource :users, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :users, requirements: API::USER_REQUIREMENTS do
desc 'Get a user projects' do
success Entities::BasicProjectDetails
end
@@ -180,7 +184,8 @@ module API
if project.saved?
present project, with: Entities::Project,
- user_can_admin_project: can?(current_user, :admin_project, project)
+ user_can_admin_project: can?(current_user, :admin_project, project),
+ current_user: current_user
else
if project.errors[:limit_reached].present?
error!(project.errors[:limit_reached], 403)
@@ -213,7 +218,8 @@ module API
if project.saved?
present project, with: Entities::Project,
- user_can_admin_project: can?(current_user, :admin_project, project)
+ user_can_admin_project: can?(current_user, :admin_project, project),
+ current_user: current_user
else
render_validation_error!(project)
end
@@ -254,6 +260,8 @@ module API
end
params do
optional :namespace, type: String, desc: 'The ID or name of the namespace that the project will be forked into'
+ optional :path, type: String, desc: 'The path that will be assigned to the fork'
+ optional :name, type: String, desc: 'The name that will be assigned to the fork'
end
post ':id/fork' do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42284')
@@ -275,7 +283,8 @@ module API
conflict!(forked_project.errors.messages)
else
present forked_project, with: Entities::Project,
- user_can_admin_project: can?(current_user, :admin_project, forked_project)
+ user_can_admin_project: can?(current_user, :admin_project, forked_project),
+ current_user: current_user
end
end
@@ -324,7 +333,8 @@ module API
if result[:status] == :success
present user_project, with: Entities::Project,
- user_can_admin_project: can?(current_user, :admin_project, user_project)
+ user_can_admin_project: can?(current_user, :admin_project, user_project),
+ current_user: current_user
else
render_validation_error!(user_project)
end
@@ -338,7 +348,7 @@ module API
::Projects::UpdateService.new(user_project, current_user, archived: true).execute
- present user_project, with: Entities::Project
+ present user_project, with: Entities::Project, current_user: current_user
end
desc 'Unarchive a project' do
@@ -349,7 +359,7 @@ module API
::Projects::UpdateService.new(@project, current_user, archived: false).execute
- present user_project, with: Entities::Project
+ present user_project, with: Entities::Project, current_user: current_user
end
desc 'Star a project' do
@@ -362,7 +372,7 @@ module API
current_user.toggle_star(user_project)
user_project.reload
- present user_project, with: Entities::Project
+ present user_project, with: Entities::Project, current_user: current_user
end
end
@@ -374,7 +384,7 @@ module API
current_user.toggle_star(user_project)
user_project.reload
- present user_project, with: Entities::Project
+ present user_project, with: Entities::Project, current_user: current_user
else
not_modified!
end
@@ -382,7 +392,11 @@ module API
desc 'Get languages in project repository'
get ':id/languages' do
- user_project.repository.languages.map { |language| language.values_at(:label, :value) }.to_h
+ if user_project.repository_languages.present?
+ user_project.repository_languages.map { |l| [l.name, l.share] }.to_h
+ else
+ user_project.repository.languages.map { |language| language.values_at(:label, :value) }.to_h
+ end
end
desc 'Remove a project'
@@ -410,7 +424,7 @@ module API
result = ::Projects::ForkService.new(fork_from_project, current_user).execute(user_project)
if result
- present user_project.reload, with: Entities::Project
+ present user_project.reload, with: Entities::Project, current_user: current_user
else
render_api_error!("Project already forked", 409) if user_project.forked?
end
@@ -432,27 +446,24 @@ module API
end
params do
requires :group_id, type: Integer, desc: 'The ID of a group'
- requires :group_access, type: Integer, values: Gitlab::Access.values, desc: 'The group access level'
+ requires :group_access, type: Integer, values: Gitlab::Access.values, as: :link_group_access, desc: 'The group access level'
optional :expires_at, type: Date, desc: 'Share expiration date'
end
post ":id/share" do
authorize! :admin_project, user_project
group = Group.find_by_id(params[:group_id])
- unless group && can?(current_user, :read_group, group)
- not_found!('Group')
- end
-
unless user_project.allowed_to_share_with_group?
break render_api_error!("The project sharing with group is disabled", 400)
end
- link = user_project.project_group_links.new(declared_params(include_missing: false))
+ result = ::Projects::GroupLinks::CreateService.new(user_project, current_user, declared_params(include_missing: false))
+ .execute(group)
- if link.save
- present link, with: Entities::ProjectGroupLink
+ if result[:status] == :success
+ present result[:link], with: Entities::ProjectGroupLink
else
- render_api_error!(link.errors.full_messages.first, 409)
+ render_api_error!(result[:message], result[:http_status])
end
end
@@ -475,7 +486,7 @@ module API
requires :file, type: File, desc: 'The file to be uploaded'
end
post ":id/uploads" do
- UploadService.new(user_project, params[:file]).execute
+ UploadService.new(user_project, params[:file]).execute.to_h
end
desc 'Get the users list of a project' do
@@ -516,7 +527,7 @@ module API
result = ::Projects::TransferService.new(user_project, current_user).execute(namespace)
if result
- present user_project, with: Entities::Project
+ present user_project, with: Entities::Project, current_user: current_user
else
render_api_error!("Failed to transfer project #{user_project.errors.messages}", 400)
end
diff --git a/lib/api/projects_relation_builder.rb b/lib/api/projects_relation_builder.rb
index 8edcfea7c93..263468c9aa6 100644
--- a/lib/api/projects_relation_builder.rb
+++ b/lib/api/projects_relation_builder.rb
@@ -11,7 +11,7 @@ module API
projects_relation
end
- def preload_relation(projects_relation, options = {})
+ def preload_relation(projects_relation, options = {})
projects_relation
end
diff --git a/lib/api/release/links.rb b/lib/api/release/links.rb
new file mode 100644
index 00000000000..5d1b40e3bff
--- /dev/null
+++ b/lib/api/release/links.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+module API
+ module Release
+ class Links < Grape::API
+ include PaginationParams
+
+ RELEASE_ENDPOINT_REQUIREMETS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS
+ .merge(tag_name: API::NO_SLASH_URL_PART_REGEX)
+
+ before { authorize! :read_release, user_project }
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+ resource 'projects/:id', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ params do
+ requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
+ end
+ resource 'releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do
+ resource :assets do
+ desc 'Get a list of links of a release' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Releases::Link
+ end
+ params do
+ use :pagination
+ end
+ get 'links' do
+ authorize! :read_release, release
+
+ present paginate(release.links.sorted), with: Entities::Releases::Link
+ end
+
+ desc 'Create a link of a release' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Releases::Link
+ end
+ params do
+ requires :name, type: String, desc: 'The name of the link'
+ requires :url, type: String, desc: 'The URL of the link'
+ end
+ post 'links' do
+ authorize! :create_release, release
+
+ new_link = release.links.create(declared_params(include_missing: false))
+
+ if new_link.persisted?
+ present new_link, with: Entities::Releases::Link
+ else
+ render_api_error!(new_link.errors.messages, 400)
+ end
+ end
+
+ params do
+ requires :link_id, type: String, desc: 'The id of the link'
+ end
+ resource 'links/:link_id' do
+ desc 'Get a link detail of a release' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Releases::Link
+ end
+ get do
+ authorize! :read_release, release
+
+ present link, with: Entities::Releases::Link
+ end
+
+ desc 'Update a link of a release' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Releases::Link
+ end
+ params do
+ optional :name, type: String, desc: 'The name of the link'
+ optional :url, type: String, desc: 'The URL of the link'
+ at_least_one_of :name, :url
+ end
+ put do
+ authorize! :update_release, release
+
+ if link.update(declared_params(include_missing: false))
+ present link, with: Entities::Releases::Link
+ else
+ render_api_error!(link.errors.messages, 400)
+ end
+ end
+
+ desc 'Delete a link of a release' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Releases::Link
+ end
+ delete do
+ authorize! :destroy_release, release
+
+ if link.destroy
+ present link, with: Entities::Releases::Link
+ else
+ render_api_error!(link.errors.messages, 400)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ helpers do
+ def release
+ @release ||= user_project.releases.find_by_tag!(params[:tag])
+ end
+
+ def link
+ @link ||= release.links.find(params[:link_id])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
new file mode 100644
index 00000000000..cb85028f22c
--- /dev/null
+++ b/lib/api/releases.rb
@@ -0,0 +1,143 @@
+# frozen_string_literal: true
+
+module API
+ class Releases < Grape::API
+ include PaginationParams
+
+ RELEASE_ENDPOINT_REQUIREMETS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS
+ .merge(tag_name: API::NO_SLASH_URL_PART_REGEX)
+
+ before { authorize_read_releases! }
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Get a project releases' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Release
+ end
+ params do
+ use :pagination
+ end
+ get ':id/releases' do
+ releases = ::ReleasesFinder.new(user_project, current_user).execute
+
+ present paginate(releases), with: Entities::Release
+ end
+
+ desc 'Get a single project release' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Release
+ end
+ params do
+ requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
+ end
+ get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do
+ authorize_read_release!
+
+ present release, with: Entities::Release
+ end
+
+ desc 'Create a new release' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Release
+ end
+ params do
+ requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
+ requires :name, type: String, desc: 'The name of the release'
+ requires :description, type: String, desc: 'The release notes'
+ optional :ref, type: String, desc: 'The commit sha or branch name'
+ optional :assets, type: Hash do
+ optional :links, type: Array do
+ requires :name, type: String
+ requires :url, type: String
+ end
+ end
+ end
+ post ':id/releases' do
+ authorize_create_release!
+
+ result = ::Releases::CreateService
+ .new(user_project, current_user, declared_params(include_missing: false))
+ .execute
+
+ if result[:status] == :success
+ present result[:release], with: Entities::Release
+ else
+ render_api_error!(result[:message], result[:http_status])
+ end
+ end
+
+ desc 'Update a release' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Release
+ end
+ params do
+ requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
+ optional :name, type: String, desc: 'The name of the release'
+ optional :description, type: String, desc: 'Release notes with markdown support'
+ end
+ put ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do
+ authorize_update_release!
+
+ result = ::Releases::UpdateService
+ .new(user_project, current_user, declared_params(include_missing: false))
+ .execute
+
+ if result[:status] == :success
+ present result[:release], with: Entities::Release
+ else
+ render_api_error!(result[:message], result[:http_status])
+ end
+ end
+
+ desc 'Delete a release' do
+ detail 'This feature was introduced in GitLab 11.7.'
+ success Entities::Release
+ end
+ params do
+ requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
+ end
+ delete ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do
+ authorize_destroy_release!
+
+ result = ::Releases::DestroyService
+ .new(user_project, current_user, declared_params(include_missing: false))
+ .execute
+
+ if result[:status] == :success
+ present result[:release], with: Entities::Release
+ else
+ render_api_error!(result[:message], result[:http_status])
+ end
+ end
+ end
+
+ helpers do
+ def authorize_create_release!
+ authorize! :create_release, user_project
+ end
+
+ def authorize_read_releases!
+ authorize! :read_release, user_project
+ end
+
+ def authorize_read_release!
+ authorize! :read_release, release
+ end
+
+ def authorize_update_release!
+ authorize! :update_release, release
+ end
+
+ def authorize_destroy_release!
+ authorize! :destroy_release, release
+ end
+
+ def release
+ @release ||= user_project.releases.find_by_tag(params[:tag])
+ end
+ end
+ end
+end
diff --git a/lib/api/runners.rb b/lib/api/runners.rb
index f72b33605a7..f3fea463e7f 100644
--- a/lib/api/runners.rb
+++ b/lib/api/runners.rb
@@ -17,6 +17,7 @@ module API
desc: 'The type of the runners to show'
optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
+ optional :tag_list, type: Array[String], desc: 'The tags of the runners to show'
use :pagination
end
get do
@@ -24,6 +25,7 @@ module API
runners = filter_runners(runners, params[:scope], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
runners = filter_runners(runners, params[:type], allowed_scopes: Ci::Runner::AVAILABLE_TYPES)
runners = filter_runners(runners, params[:status], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
+ runners = runners.tagged_with(params[:tag_list]) if params[:tag_list]
present paginate(runners), with: Entities::Runner
end
@@ -38,6 +40,7 @@ module API
desc: 'The type of the runners to show'
optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
+ optional :tag_list, type: Array[String], desc: 'The tags of the runners to show'
use :pagination
end
get 'all' do
@@ -47,6 +50,7 @@ module API
runners = filter_runners(runners, params[:scope])
runners = filter_runners(runners, params[:type], allowed_scopes: Ci::Runner::AVAILABLE_TYPES)
runners = filter_runners(runners, params[:status], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
+ runners = runners.tagged_with(params[:tag_list]) if params[:tag_list]
present paginate(runners), with: Entities::Runner
end
@@ -139,6 +143,7 @@ module API
desc: 'The type of the runners to show'
optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
+ optional :tag_list, type: Array[String], desc: 'The tags of the runners to show'
use :pagination
end
get ':id/runners' do
@@ -146,6 +151,7 @@ module API
runners = filter_runners(runners, params[:scope])
runners = filter_runners(runners, params[:type], allowed_scopes: Ci::Runner::AVAILABLE_TYPES)
runners = filter_runners(runners, params[:status], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
+ runners = runners.tagged_with(params[:tag_list]) if params[:tag_list]
present paginate(runners), with: Entities::Runner
end
diff --git a/lib/api/services.rb b/lib/api/services.rb
index d60f0f5f08d..bda6be51553 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -368,46 +368,9 @@ module API
name: :webhook,
type: String,
desc: 'The Hangouts Chat webhook. e.g. https://chat.googleapis.com/v1/spaces…'
- }
- ],
- 'hipchat' => [
- {
- required: true,
- name: :token,
- type: String,
- desc: 'The room token'
- },
- {
- required: false,
- name: :room,
- type: String,
- desc: 'The room name or ID'
- },
- {
- required: false,
- name: :color,
- type: String,
- desc: 'The room color'
},
- {
- required: false,
- name: :notify,
- type: Boolean,
- desc: 'Enable notifications'
- },
- {
- required: false,
- name: :api_version,
- type: String,
- desc: 'Leave blank for default (v2)'
- },
- {
- required: false,
- name: :server,
- type: String,
- desc: 'Leave blank for default. https://hipchat.example.com'
- }
- ],
+ CHAT_NOTIFICATION_EVENTS
+ ].flatten,
'irker' => [
{
required: true,
@@ -468,7 +431,7 @@ module API
{
required: false,
name: :jira_issue_transition_id,
- type: Integer,
+ type: String,
desc: 'The ID of a transition that moves issues to a closed state. You can find this number under the JIRA workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`'
}
],
@@ -629,6 +592,26 @@ module API
desc: 'The description of the tracker'
}
],
+ 'youtrack' => [
+ {
+ required: true,
+ name: :project_url,
+ type: String,
+ desc: 'The project URL'
+ },
+ {
+ required: true,
+ name: :issues_url,
+ type: String,
+ desc: 'The issues URL'
+ },
+ {
+ required: false,
+ name: :description,
+ type: String,
+ desc: 'The description of the tracker'
+ }
+ ],
'slack' => [
CHAT_NOTIFICATION_SETTINGS,
CHAT_NOTIFICATION_FLAGS,
@@ -691,7 +674,6 @@ module API
ExternalWikiService,
FlowdockService,
HangoutsChatService,
- HipchatService,
IrkerService,
JiraService,
KubernetesService,
@@ -703,6 +685,7 @@ module API
PrometheusService,
PushoverService,
RedmineService,
+ YoutrackService,
SlackService,
MattermostService,
MicrosoftTeamsService,
@@ -763,7 +746,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before { authenticate! }
before { authorize_admin_project }
@@ -842,7 +825,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Trigger a slash command for #{service_slug}" do
detail 'Added in GitLab 8.13'
end
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index f53ba0ab761..b16faffe335 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -35,7 +35,7 @@ module API
end
optional :container_registry_token_expire_delay, type: Integer, desc: 'Authorization token duration (minutes)'
optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts"
- optional :default_branch_protection, type: Integer, values: [0, 1, 2], desc: 'Determine if developers can push to master'
+ optional :default_branch_protection, type: Integer, values: Gitlab::Access.protection_values, desc: 'Determine if developers can push to master'
optional :default_group_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default group visibility'
optional :default_project_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default project visibility'
optional :default_projects_limit, type: Integer, desc: 'The maximum number of personal projects'
@@ -121,6 +121,7 @@ module API
optional :terminal_max_session_time, type: Integer, desc: 'Maximum time for web terminal websocket connection (in seconds). Set to 0 for unlimited time.'
optional :usage_ping_enabled, type: Boolean, desc: 'Every week GitLab will report license usage back to GitLab, Inc.'
optional :instance_statistics_visibility_private, type: Boolean, desc: 'When set to `true` Instance statistics will only be available to admins'
+ optional :local_markdown_version, type: Integer, desc: "Local markdown version, increase this value when any cached markdown should be invalidated"
ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type|
optional :"#{type}_key_restriction",
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index 326d55afd0e..f8b37b33348 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -16,6 +16,10 @@ module API
def public_snippets
SnippetsFinder.new(current_user, scope: :are_public).execute
end
+
+ def snippets
+ SnippetsFinder.new(current_user).execute
+ end
end
desc 'Get a snippets list for authenticated user' do
@@ -48,7 +52,10 @@ module API
requires :id, type: Integer, desc: 'The ID of a snippet'
end
get ':id' do
- snippet = snippets_for_current_user.find(params[:id])
+ snippet = snippets.find_by_id(params[:id])
+
+ break not_found!('Snippet') unless snippet
+
present snippet, with: Entities::PersonalSnippet
end
@@ -94,9 +101,8 @@ module API
desc: 'The visibility of the snippet'
at_least_one_of :title, :file_name, :content, :visibility
end
- # rubocop: disable CodeReuse/ActiveRecord
put ':id' do
- snippet = snippets_for_current_user.find_by(id: params.delete(:id))
+ snippet = snippets_for_current_user.find_by_id(params.delete(:id))
break not_found!('Snippet') unless snippet
authorize! :update_personal_snippet, snippet
@@ -113,7 +119,6 @@ module API
render_validation_error!(snippet)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Remove snippet' do
detail 'This feature was introduced in GitLab 8.15.'
@@ -122,16 +127,14 @@ module API
params do
requires :id, type: Integer, desc: 'The ID of a snippet'
end
- # rubocop: disable CodeReuse/ActiveRecord
delete ':id' do
- snippet = snippets_for_current_user.find_by(id: params.delete(:id))
+ snippet = snippets_for_current_user.find_by_id(params.delete(:id))
break not_found!('Snippet') unless snippet
authorize! :destroy_personal_snippet, snippet
destroy_conditionally!(snippet)
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Get a raw snippet' do
detail 'This feature was introduced in GitLab 8.15.'
@@ -139,9 +142,8 @@ module API
params do
requires :id, type: Integer, desc: 'The ID of a snippet'
end
- # rubocop: disable CodeReuse/ActiveRecord
get ":id/raw" do
- snippet = snippets_for_current_user.find_by(id: params.delete(:id))
+ snippet = snippets.find_by_id(params.delete(:id))
break not_found!('Snippet') unless snippet
env['api.format'] = :txt
@@ -149,7 +151,6 @@ module API
header['Content-Disposition'] = 'attachment'
present snippet.content
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Get the user agent details for a snippet' do
success Entities::UserAgentDetail
@@ -157,17 +158,15 @@ module API
params do
requires :id, type: Integer, desc: 'The ID of a snippet'
end
- # rubocop: disable CodeReuse/ActiveRecord
get ":id/user_agent_detail" do
authenticated_as_admin!
- snippet = Snippet.find_by!(id: params[:id])
+ snippet = Snippet.find_by_id!(params[:id])
break not_found!('UserAgentDetail') unless snippet.user_agent_detail
present snippet.user_agent_detail, with: Entities::UserAgentDetail
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb
index 74ad3c35a61..dfb54446ddf 100644
--- a/lib/api/subscriptions.rb
+++ b/lib/api/subscriptions.rb
@@ -2,51 +2,88 @@
module API
class Subscriptions < Grape::API
+ helpers ::API::Helpers::LabelHelpers
+
before { authenticate! }
- subscribable_types = {
- 'merge_requests' => proc { |id| find_merge_request_with_access(id, :update_merge_request) },
- 'issues' => proc { |id| find_project_issue(id) },
- 'labels' => proc { |id| find_project_label(id) }
- }
+ subscribables = [
+ {
+ type: 'merge_requests',
+ entity: Entities::MergeRequest,
+ source: Project,
+ finder: ->(id) { find_merge_request_with_access(id, :update_merge_request) }
+ },
+ {
+ type: 'issues',
+ entity: Entities::Issue,
+ source: Project,
+ finder: ->(id) { find_project_issue(id) }
+ },
+ {
+ type: 'labels',
+ entity: Entities::ProjectLabel,
+ source: Project,
+ finder: ->(id) { find_label(user_project, id) }
+ },
+ {
+ type: 'labels',
+ entity: Entities::GroupLabel,
+ source: Group,
+ finder: ->(id) { find_label(user_group, id) }
+ }
+ ]
- params do
- requires :id, type: String, desc: 'The ID of a project'
- requires :subscribable_id, type: String, desc: 'The ID of a resource'
- end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- subscribable_types.each do |type, finder|
- type_singularized = type.singularize
- entity_class = Entities.const_get(type_singularized.camelcase)
+ subscribables.each do |subscribable|
+ source_type = subscribable[:source].name.underscore
+ params do
+ requires :id, type: String, desc: "The #{source_type} ID"
+ requires :subscribable_id, type: String, desc: 'The ID of a resource'
+ end
+ resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Subscribe to a resource' do
- success entity_class
+ success subscribable[:entity]
end
- post ":id/#{type}/:subscribable_id/subscribe" do
- resource = instance_exec(params[:subscribable_id], &finder)
+ post ":id/#{subscribable[:type]}/:subscribable_id/subscribe" do
+ parent = parent_resource(source_type)
+ resource = instance_exec(params[:subscribable_id], &subscribable[:finder])
- if resource.subscribed?(current_user, user_project)
+ if resource.subscribed?(current_user, parent)
not_modified!
else
- resource.subscribe(current_user, user_project)
- present resource, with: entity_class, current_user: current_user, project: user_project
+ resource.subscribe(current_user, parent)
+ present resource, with: subscribable[:entity], current_user: current_user, project: parent, parent: parent
end
end
desc 'Unsubscribe from a resource' do
- success entity_class
+ success subscribable[:entity]
end
- post ":id/#{type}/:subscribable_id/unsubscribe" do
- resource = instance_exec(params[:subscribable_id], &finder)
+ post ":id/#{subscribable[:type]}/:subscribable_id/unsubscribe" do
+ parent = parent_resource(source_type)
+ resource = instance_exec(params[:subscribable_id], &subscribable[:finder])
- if !resource.subscribed?(current_user, user_project)
+ if !resource.subscribed?(current_user, parent)
not_modified!
else
- resource.unsubscribe(current_user, user_project)
- present resource, with: entity_class, current_user: current_user, project: user_project
+ resource.unsubscribe(current_user, parent)
+ present resource, with: subscribable[:entity], current_user: current_user, project: parent, parent: parent
end
end
end
end
+
+ private
+
+ helpers do
+ def parent_resource(source_type)
+ case source_type
+ when 'project'
+ user_project
+ else
+ nil
+ end
+ end
+ end
end
end
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index b18eec7d796..f5359fd316c 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -20,12 +20,15 @@ module API
desc: 'Return tags sorted in updated by `asc` or `desc` order.'
optional :order_by, type: String, values: %w[name updated], default: 'updated',
desc: 'Return tags ordered by `name` or `updated` fields.'
+ optional :search, type: String, desc: 'Return list of tags matching the search criteria'
use :pagination
end
get ':id/repository/tags' do
- tags = ::Kaminari.paginate_array(::TagsFinder.new(user_project.repository, sort: "#{params[:order_by]}_#{params[:sort]}").execute)
+ tags = ::TagsFinder.new(user_project.repository,
+ sort: "#{params[:order_by]}_#{params[:sort]}",
+ search: params[:search]).execute
- present paginate(tags), with: Entities::Tag, project: user_project
+ present paginate(::Kaminari.paginate_array(tags)), with: Entities::Tag, project: user_project
end
desc 'Get a single repository tag' do
@@ -42,21 +45,35 @@ module API
end
desc 'Create a new repository tag' do
+ detail 'This optional release_description parameter was deprecated in GitLab 11.7.'
success Entities::Tag
end
params do
requires :tag_name, type: String, desc: 'The name of the tag'
requires :ref, type: String, desc: 'The commit sha or branch name'
optional :message, type: String, desc: 'Specifying a message creates an annotated tag'
- optional :release_description, type: String, desc: 'Specifying release notes stored in the GitLab database'
+ optional :release_description, type: String, desc: 'Specifying release notes stored in the GitLab database (deprecated in GitLab 11.7)'
end
post ':id/repository/tags' do
authorize_push_project
result = ::Tags::CreateService.new(user_project, current_user)
- .execute(params[:tag_name], params[:ref], params[:message], params[:release_description])
+ .execute(params[:tag_name], params[:ref], params[:message])
if result[:status] == :success
+ # Release creation with Tags API was deprecated in GitLab 11.7
+ if params[:release_description].present?
+ release_create_params = {
+ tag: params[:tag_name],
+ name: params[:tag_name], # Name can be specified in new API
+ description: params[:release_description]
+ }
+
+ ::Releases::CreateService
+ .new(user_project, current_user, release_create_params)
+ .execute
+ end
+
present result[:tag],
with: Entities::Tag,
project: user_project
@@ -88,44 +105,72 @@ module API
end
desc 'Add a release note to a tag' do
- success Entities::Release
+ detail 'This feature was deprecated in GitLab 11.7.'
+ success Entities::TagRelease
end
params do
- requires :tag_name, type: String, desc: 'The name of the tag'
+ requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
requires :description, type: String, desc: 'Release notes with markdown support'
end
post ':id/repository/tags/:tag_name/release', requirements: TAG_ENDPOINT_REQUIREMENTS do
- authorize_push_project
+ authorize_create_release!
+
+ ##
+ # Legacy API does not support tag auto creation.
+ not_found!('Tag') unless user_project.repository.find_tag(params[:tag])
- result = CreateReleaseService.new(user_project, current_user)
- .execute(params[:tag_name], params[:description])
+ release_create_params = {
+ tag: params[:tag],
+ name: params[:tag], # Name can be specified in new API
+ description: params[:description]
+ }
+
+ result = ::Releases::CreateService
+ .new(user_project, current_user, release_create_params)
+ .execute
if result[:status] == :success
- present result[:release], with: Entities::Release
+ present result[:release], with: Entities::TagRelease
else
render_api_error!(result[:message], result[:http_status])
end
end
desc "Update a tag's release note" do
- success Entities::Release
+ detail 'This feature was deprecated in GitLab 11.7.'
+ success Entities::TagRelease
end
params do
- requires :tag_name, type: String, desc: 'The name of the tag'
+ requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
requires :description, type: String, desc: 'Release notes with markdown support'
end
put ':id/repository/tags/:tag_name/release', requirements: TAG_ENDPOINT_REQUIREMENTS do
- authorize_push_project
+ authorize_update_release!
- result = UpdateReleaseService.new(user_project, current_user)
- .execute(params[:tag_name], params[:description])
+ result = ::Releases::UpdateService
+ .new(user_project, current_user, declared_params(include_missing: false))
+ .execute
if result[:status] == :success
- present result[:release], with: Entities::Release
+ present result[:release], with: Entities::TagRelease
else
render_api_error!(result[:message], result[:http_status])
end
end
end
+
+ helpers do
+ def authorize_create_release!
+ authorize! :create_release, user_project
+ end
+
+ def authorize_update_release!
+ authorize! :update_release, release
+ end
+
+ def release
+ @release ||= user_project.releases.find_by_tag(params[:tag])
+ end
+ end
end
end
diff --git a/lib/api/todos.rb b/lib/api/todos.rb
index d2c8cf7c1aa..64ac8ece56c 100644
--- a/lib/api/todos.rb
+++ b/lib/api/todos.rb
@@ -14,7 +14,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
ISSUABLE_TYPES.each do |type, finder|
type_id_str = "#{type.singularize}_iid".to_sym
diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb
index 3ce1529f259..8fc7c7361e1 100644
--- a/lib/api/triggers.rb
+++ b/lib/api/triggers.rb
@@ -7,7 +7,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Trigger a GitLab project pipeline' do
success Entities::Pipeline
end
@@ -51,7 +51,7 @@ module API
triggers = user_project.triggers.includes(:trigger_requests)
- present paginate(triggers), with: Entities::Trigger
+ present paginate(triggers), with: Entities::Trigger, current_user: current_user
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -59,7 +59,7 @@ module API
success Entities::Trigger
end
params do
- requires :trigger_id, type: Integer, desc: 'The trigger ID'
+ requires :trigger_id, type: Integer, desc: 'The trigger ID'
end
get ':id/triggers/:trigger_id' do
authenticate!
@@ -68,14 +68,14 @@ module API
trigger = user_project.triggers.find(params.delete(:trigger_id))
break not_found!('Trigger') unless trigger
- present trigger, with: Entities::Trigger
+ present trigger, with: Entities::Trigger, current_user: current_user
end
desc 'Create a trigger' do
success Entities::Trigger
end
params do
- requires :description, type: String, desc: 'The trigger description'
+ requires :description, type: String, desc: 'The trigger description'
end
post ':id/triggers' do
authenticate!
@@ -85,7 +85,7 @@ module API
declared_params(include_missing: false).merge(owner: current_user))
if trigger.valid?
- present trigger, with: Entities::Trigger
+ present trigger, with: Entities::Trigger, current_user: current_user
else
render_validation_error!(trigger)
end
@@ -106,7 +106,7 @@ module API
break not_found!('Trigger') unless trigger
if trigger.update(declared_params(include_missing: false))
- present trigger, with: Entities::Trigger
+ present trigger, with: Entities::Trigger, current_user: current_user
else
render_validation_error!(trigger)
end
@@ -116,7 +116,7 @@ module API
success Entities::Trigger
end
params do
- requires :trigger_id, type: Integer, desc: 'The trigger ID'
+ requires :trigger_id, type: Integer, desc: 'The trigger ID'
end
post ':id/triggers/:trigger_id/take_ownership' do
authenticate!
@@ -127,7 +127,7 @@ module API
if trigger.update(owner: current_user)
status :ok
- present trigger, with: Entities::Trigger
+ present trigger, with: Entities::Trigger, current_user: current_user
else
render_validation_error!(trigger)
end
@@ -137,7 +137,7 @@ module API
success Entities::Trigger
end
params do
- requires :trigger_id, type: Integer, desc: 'The trigger ID'
+ requires :trigger_id, type: Integer, desc: 'The trigger ID'
end
delete ':id/triggers/:trigger_id' do
authenticate!
diff --git a/lib/api/users.rb b/lib/api/users.rb
index b41fce76df0..7d88880d412 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -26,7 +26,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def reorder_users(users)
if params[:order_by] && params[:sort]
- users.reorder(params[:order_by] => params[:sort])
+ users.reorder(order_options_with_tie_breaker)
else
users
end
@@ -133,10 +133,10 @@ module API
desc "Get the status of a user"
params do
- requires :id_or_username, type: String, desc: 'The ID or username of the user'
+ requires :user_id, type: String, desc: 'The ID or username of the user'
end
- get ":id_or_username/status" do
- user = find_user(params[:id_or_username])
+ get ":user_id/status", requirements: API::USER_REQUIREMENTS do
+ user = find_user(params[:user_id])
not_found!('User') unless user && can?(current_user, :read_user, user)
present user.status || {}, with: Entities::UserStatus
diff --git a/lib/api/validations/types/labels_list.rb b/lib/api/validations/types/labels_list.rb
new file mode 100644
index 00000000000..47cd83c29cf
--- /dev/null
+++ b/lib/api/validations/types/labels_list.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module API
+ module Validations
+ module Types
+ class LabelsList
+ def self.coerce
+ lambda do |value|
+ case value
+ when String
+ value.split(',').map(&:strip)
+ when Array
+ value.map { |v| v.to_s.split(',').map(&:strip) }.flatten
+ when LabelsList
+ value
+ else
+ []
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index f7cae2251c2..148deb86c4c 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -11,7 +11,7 @@ module API
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get project variables' do
success Entities::Variable
end
diff --git a/lib/api/version.rb b/lib/api/version.rb
index 74cd857f447..eca1b529094 100644
--- a/lib/api/version.rb
+++ b/lib/api/version.rb
@@ -2,13 +2,29 @@
module API
class Version < Grape::API
+ helpers ::API::Helpers::GraphqlHelpers
+
before { authenticate! }
+ METADATA_QUERY = <<~EOF
+ {
+ metadata {
+ version
+ revision
+ }
+ }
+ EOF
+
desc 'Get the version information of the GitLab instance.' do
detail 'This feature was introduced in GitLab 8.13.'
end
get '/version' do
- { version: Gitlab::VERSION, revision: Gitlab.revision }
+ conditionally_graphql!(
+ query: METADATA_QUERY,
+ context: { current_user: current_user },
+ transform: ->(result) { result.dig('data', 'metadata') },
+ fallback: -> { { version: Gitlab::VERSION, revision: Gitlab.revision } }
+ )
end
end
end
diff --git a/lib/api/wikis.rb b/lib/api/wikis.rb
index 302b2797a34..994074ddc67 100644
--- a/lib/api/wikis.rb
+++ b/lib/api/wikis.rb
@@ -11,9 +11,7 @@ module API
}
end
- params :wiki_page_params do
- requires :content, type: String, desc: 'Content of a wiki page'
- requires :title, type: String, desc: 'Title of a wiki page'
+ params :common_wiki_page_params do
optional :format,
type: String,
values: ProjectWiki::MARKUPS.values.map(&:to_s),
@@ -22,7 +20,9 @@ module API
end
end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ WIKI_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(slug: API::NO_SLASH_URL_PART_REGEX)
+
+ resource :projects, requirements: WIKI_ENDPOINT_REQUIREMENTS do
desc 'Get a list of wiki pages' do
success Entities::WikiPageBasic
end
@@ -52,7 +52,9 @@ module API
success Entities::WikiPage
end
params do
- use :wiki_page_params
+ requires :title, type: String, desc: 'Title of a wiki page'
+ requires :content, type: String, desc: 'Content of a wiki page'
+ use :common_wiki_page_params
end
post ':id/wikis' do
authorize! :create_wiki, user_project
@@ -70,7 +72,10 @@ module API
success Entities::WikiPage
end
params do
- use :wiki_page_params
+ optional :title, type: String, desc: 'Title of a wiki page'
+ optional :content, type: String, desc: 'Content of a wiki page'
+ use :common_wiki_page_params
+ at_least_one_of :content, :title, :format
end
put ':id/wikis/:slug' do
authorize! :create_wiki, user_project
@@ -103,7 +108,7 @@ module API
requires :file, type: ::API::Validations::Types::SafeFile, desc: 'The attachment file to be uploaded'
optional :branch, type: String, desc: 'The name of the branch'
end
- post ":id/wikis/attachments", requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ post ":id/wikis/attachments" do
authorize! :create_wiki, user_project
result = ::Wikis::CreateAttachmentService.new(user_project,
diff --git a/lib/backup/files.rb b/lib/backup/files.rb
index 427c65e2d91..098f2da6d88 100644
--- a/lib/backup/files.rb
+++ b/lib/backup/files.rb
@@ -71,8 +71,14 @@ module Backup
end
def run_pipeline!(cmd_list, options = {})
- status_list = Open3.pipeline(*cmd_list, options)
- raise Backup::Error, 'Backup failed' unless status_list.compact.all?(&:success?)
+ err_r, err_w = IO.pipe
+ options[:err] = err_w
+ status = Open3.pipeline(*cmd_list, options)
+ err_w.close
+ return if status.compact.all?(&:success?)
+
+ regex = /^g?tar: \.: Cannot mkdir: No such file or directory$/
+ raise Backup::Error, 'Backup failed' unless err_r.read =~ regex
end
end
end
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 12121920c67..aeaf61cda39 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -50,6 +50,7 @@ module Backup
if directory.files.create(key: remote_target, body: File.open(tar_file), public: false,
multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size,
encryption: Gitlab.config.backup.upload.encryption,
+ encryption_key: Gitlab.config.backup.upload.encryption_key,
storage_class: Gitlab.config.backup.upload.storage_class)
progress.puts "done".color(:green)
else
@@ -195,7 +196,7 @@ module Backup
if connection.service == ::Fog::Storage::Local
connection.directories.create(key: remote_directory)
else
- connection.directories.get(remote_directory)
+ connection.directories.new(key: remote_directory)
end
end
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 184c7418e75..22ed1d8e7b4 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -93,7 +93,7 @@ module Backup
progress.puts "Error: #{e}".color(:red)
end
else
- restore_repo_success = gitlab_shell.create_repository(project.repository_storage, project.disk_path)
+ restore_repo_success = gitlab_shell.create_project_repository(project)
end
if restore_repo_success
diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb
index deda4b1872e..086adf59d2b 100644
--- a/lib/banzai/filter/autolink_filter.rb
+++ b/lib/banzai/filter/autolink_filter.rb
@@ -8,6 +8,10 @@ module Banzai
#
# Based on HTML::Pipeline::AutolinkFilter
#
+ # Note that our CommonMark parser, `commonmarker` (using the autolink extension)
+ # handles standard autolinking, like http/https. We detect additional
+ # schemes (smb, rdar, etc).
+ #
# Context options:
# :autolink - Boolean, skips all processing done by this filter when false
# :link_attr - Hash of attributes for the generated links
@@ -107,10 +111,17 @@ module Banzai
end
end
- # match has come from node.to_html above, so we know it's encoded
- # correctly.
+ # Since this came from a Text node, make sure the new href is encoded.
+ # `commonmarker` percent encodes the domains of links it handles, so
+ # do the same (instead of using `normalized_encode`).
+ begin
+ href_safe = Addressable::URI.encode(match).html_safe
+ rescue Addressable::URI::InvalidURIError
+ return uri.to_s
+ end
+
html_safe_match = match.html_safe
- options = link_options.merge(href: html_safe_match)
+ options = link_options.merge(href: href_safe)
content_tag(:a, html_safe_match, options) + dropped
end
diff --git a/lib/banzai/filter/emoji_filter.rb b/lib/banzai/filter/emoji_filter.rb
index c87948a30bf..fa1690f73ad 100644
--- a/lib/banzai/filter/emoji_filter.rb
+++ b/lib/banzai/filter/emoji_filter.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/emoji.js
module Banzai
module Filter
# HTML filter that replaces :emoji: and unicode with images.
diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb
index 2e6d742de27..61ee3eac216 100644
--- a/lib/banzai/filter/external_link_filter.rb
+++ b/lib/banzai/filter/external_link_filter.rb
@@ -4,18 +4,29 @@ module Banzai
module Filter
# HTML Filter to modify the attributes of external links
class ExternalLinkFilter < HTML::Pipeline::Filter
- SCHEMES = ['http', 'https', nil].freeze
+ SCHEMES = ['http', 'https', nil].freeze
+ RTLO = "\u202E".freeze
+ ENCODED_RTLO = '%E2%80%AE'.freeze
def call
links.each do |node|
- uri = uri(node['href'].to_s)
- next unless uri
-
- node.set_attribute('href', uri.to_s)
+ # URI.parse does stricter checking on the url than Addressable,
+ # such as on `mailto:` links. Since we've been using it, do an
+ # initial parse for validity and then use Addressable
+ # for IDN support, etc
+ uri = uri_strict(node['href'].to_s)
+ if uri
+ node.set_attribute('href', uri.to_s)
+ addressable_uri = addressable_uri(node['href'])
+ else
+ addressable_uri = nil
+ end
- if SCHEMES.include?(uri.scheme) && external_url?(uri)
- node.set_attribute('rel', 'nofollow noreferrer noopener')
- node.set_attribute('target', '_blank')
+ unless internal_url?(addressable_uri)
+ punycode_autolink_node!(addressable_uri, node)
+ sanitize_link_text!(node)
+ add_malicious_tooltip!(addressable_uri, node)
+ add_nofollow!(addressable_uri, node)
end
end
@@ -24,27 +35,85 @@ module Banzai
private
- def uri(href)
+ def uri_strict(href)
URI.parse(href)
rescue URI::Error
nil
end
+ def addressable_uri(href)
+ Addressable::URI.parse(href)
+ rescue Addressable::URI::InvalidURIError
+ nil
+ end
+
def links
query = 'descendant-or-self::a[@href and not(@href = "")]'
doc.xpath(query)
end
- def external_url?(uri)
+ def internal_url?(uri)
+ return false if uri.nil?
# Relative URLs miss a hostname
- return false unless uri.hostname
+ return true unless uri.hostname
- uri.hostname != internal_url.hostname
+ uri.hostname == internal_url.hostname
end
def internal_url
@internal_url ||= URI.parse(Gitlab.config.gitlab.url)
end
+
+ # Only replace an autolink with an IDN with it's punycode
+ # version if we need emailable links. Otherwise let it
+ # be shown normally and the tooltips will show the
+ # punycode version.
+ def punycode_autolink_node!(uri, node)
+ return unless uri
+ return unless context[:emailable_links]
+
+ unencoded_uri_str = Addressable::URI.unencode(node['href'])
+
+ if unencoded_uri_str == node.content && idn?(uri)
+ node.content = uri.normalize
+ end
+ end
+
+ # escape any right-to-left (RTLO) characters in link text
+ def sanitize_link_text!(node)
+ node.inner_html = node.inner_html.gsub(RTLO, ENCODED_RTLO)
+ end
+
+ # If the domain is an international domain name (IDN),
+ # let's expose with a tooltip in case it's intended
+ # to be malicious. This is particularly useful for links
+ # where the link text is not the same as the actual link.
+ # We will continue to show the unicode version of the domain
+ # in autolinked link text, which could contain emojis, etc.
+ #
+ # Also show the tooltip if the url contains the RTLO character,
+ # as this is an indicator of a malicious link
+ def add_malicious_tooltip!(uri, node)
+ if idn?(uri) || has_encoded_rtlo?(uri)
+ node.add_class('has-tooltip')
+ node.set_attribute('title', uri.normalize)
+ end
+ end
+
+ def add_nofollow!(uri, node)
+ if SCHEMES.include?(uri&.scheme)
+ node.set_attribute('rel', 'nofollow noreferrer noopener')
+ node.set_attribute('target', '_blank')
+ end
+ end
+
+ def idn?(uri)
+ uri&.normalized_host&.start_with?('xn--')
+ end
+
+ def has_encoded_rtlo?(uri)
+ uri&.to_s&.include?(ENCODED_RTLO)
+ end
end
end
end
diff --git a/lib/banzai/filter/footnote_filter.rb b/lib/banzai/filter/footnote_filter.rb
new file mode 100644
index 00000000000..de133774dfa
--- /dev/null
+++ b/lib/banzai/filter/footnote_filter.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ # HTML Filter for footnotes
+ #
+ # Footnotes are supported in CommonMark. However we were stripping
+ # the ids during sanitization. Those are now allowed.
+ #
+ # Footnotes are numbered the same - the first one has `id=fn1`, the
+ # second is `id=fn2`, etc. In order to allow footnotes when rendering
+ # multiple markdown blocks on a page, we need to make each footnote
+ # reference unique.
+ #
+ # This filter adds a random number to each footnote (the same number
+ # can be used for a single render). So you get `id=fn1-4335` and `id=fn2-4335`.
+ #
+ class FootnoteFilter < HTML::Pipeline::Filter
+ INTEGER_PATTERN = /\A\d+\z/.freeze
+ FOOTNOTE_ID_PREFIX = 'fn'.freeze
+ FOOTNOTE_LINK_ID_PREFIX = 'fnref'.freeze
+ FOOTNOTE_LI_REFERENCE_PATTERN = /\A#{FOOTNOTE_ID_PREFIX}\d+\z/.freeze
+ FOOTNOTE_LINK_REFERENCE_PATTERN = /\A#{FOOTNOTE_LINK_ID_PREFIX}\d+\z/.freeze
+ FOOTNOTE_START_NUMBER = 1
+
+ def call
+ return doc unless first_footnote = doc.at_css("ol > li[id=#{fn_id(FOOTNOTE_START_NUMBER)}]")
+
+ # Sanitization stripped off the section wrapper - add it back in
+ first_footnote.parent.wrap('<section class="footnotes">')
+ rand_suffix = "-#{random_number}"
+ modified_footnotes = {}
+
+ doc.css('sup > a[id]').each do |link_node|
+ ref_num = link_node[:id].delete_prefix(FOOTNOTE_LINK_ID_PREFIX)
+ footnote_node = doc.at_css("li[id=#{fn_id(ref_num)}]")
+
+ if INTEGER_PATTERN.match?(ref_num) && (footnote_node || modified_footnotes[ref_num])
+ link_node[:href] += rand_suffix
+ link_node[:id] += rand_suffix
+
+ # Sanitization stripped off class - add it back in
+ link_node.parent.append_class('footnote-ref')
+
+ unless modified_footnotes[ref_num]
+ footnote_node[:id] += rand_suffix
+ backref_node = footnote_node.at_css("a[href=\"##{fnref_id(ref_num)}\"]")
+
+ if backref_node
+ backref_node[:href] += rand_suffix
+ backref_node.append_class('footnote-backref')
+ end
+
+ modified_footnotes[ref_num] = true
+ end
+ end
+ end
+
+ doc
+ end
+
+ private
+
+ def random_number
+ @random_number ||= rand(10000)
+ end
+
+ def fn_id(num)
+ "#{FOOTNOTE_ID_PREFIX}#{num}"
+ end
+
+ def fnref_id(num)
+ "#{FOOTNOTE_LINK_ID_PREFIX}#{num}"
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/image_lazy_load_filter.rb b/lib/banzai/filter/image_lazy_load_filter.rb
index afaee70f351..d8b9eb29cf5 100644
--- a/lib/banzai/filter/image_lazy_load_filter.rb
+++ b/lib/banzai/filter/image_lazy_load_filter.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/image.js
module Banzai
module Filter
# HTML filter that moves the value of image `src` attributes to `data-src`
diff --git a/lib/banzai/filter/image_link_filter.rb b/lib/banzai/filter/image_link_filter.rb
index 884a94fb761..01237303c27 100644
--- a/lib/banzai/filter/image_link_filter.rb
+++ b/lib/banzai/filter/image_link_filter.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/image.js
module Banzai
module Filter
# HTML filter that wraps links around inline images.
diff --git a/lib/banzai/filter/inline_diff_filter.rb b/lib/banzai/filter/inline_diff_filter.rb
index e9ddc6e0e3d..5a1c0bee32d 100644
--- a/lib/banzai/filter/inline_diff_filter.rb
+++ b/lib/banzai/filter/inline_diff_filter.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/marks/inline_diff.js
module Banzai
module Filter
class InlineDiffFilter < HTML::Pipeline::Filter
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
index 04ec38209c7..f90a35952e5 100644
--- a/lib/banzai/filter/label_reference_filter.rb
+++ b/lib/banzai/filter/label_reference_filter.rb
@@ -29,7 +29,7 @@ module Banzai
if label
yield match, label.id, project, namespace, $~
else
- match
+ escape_html_entities(match)
end
end
end
@@ -102,6 +102,10 @@ module Banzai
CGI.unescapeHTML(text.to_s)
end
+ def escape_html_entities(text)
+ CGI.escapeHTML(text.to_s)
+ end
+
def object_link_title(object, matches)
# use title of wrapped element instead
nil
diff --git a/lib/banzai/filter/markdown_engines/common_mark.rb b/lib/banzai/filter/markdown_engines/common_mark.rb
index e52c0d15b31..d3af776db05 100644
--- a/lib/banzai/filter/markdown_engines/common_mark.rb
+++ b/lib/banzai/filter/markdown_engines/common_mark.rb
@@ -32,8 +32,13 @@ module Banzai
:DEFAULT # default rendering system. Nothing special.
].freeze
- def initialize
- @renderer = Banzai::Renderer::CommonMark::HTML.new(options: RENDER_OPTIONS)
+ RENDER_OPTIONS_SOURCEPOS = RENDER_OPTIONS + [
+ :SOURCEPOS # enable embedding of source position information
+ ].freeze
+
+ def initialize(context)
+ @context = context
+ @renderer = Banzai::Renderer::CommonMark::HTML.new(options: render_options)
end
def render(text)
@@ -41,6 +46,12 @@ module Banzai
@renderer.render(doc)
end
+
+ private
+
+ def render_options
+ @context[:no_sourcepos] ? RENDER_OPTIONS : RENDER_OPTIONS_SOURCEPOS
+ end
end
end
end
diff --git a/lib/banzai/filter/markdown_engines/redcarpet.rb b/lib/banzai/filter/markdown_engines/redcarpet.rb
deleted file mode 100644
index ec150d041ff..00000000000
--- a/lib/banzai/filter/markdown_engines/redcarpet.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-# `Redcarpet` markdown engine for GitLab's Banzai markdown filter.
-# This module is used in Banzai::Filter::MarkdownFilter.
-# Used gem is `redcarpet` which is a ruby library for markdown processing.
-# Homepage: https://github.com/vmg/redcarpet
-
-module Banzai
- module Filter
- module MarkdownEngines
- class Redcarpet
- OPTIONS = {
- fenced_code_blocks: true,
- footnotes: true,
- lax_spacing: true,
- no_intra_emphasis: true,
- space_after_headers: true,
- strikethrough: true,
- superscript: true,
- tables: true
- }.freeze
-
- def initialize
- html_renderer = Banzai::Renderer::Redcarpet::HTML.new
- @renderer = ::Redcarpet::Markdown.new(html_renderer, OPTIONS)
- end
-
- def render(text)
- @renderer.render(text)
- end
- end
- end
- end
-end
diff --git a/lib/banzai/filter/markdown_filter.rb b/lib/banzai/filter/markdown_filter.rb
index cdf758472c1..242e39f5495 100644
--- a/lib/banzai/filter/markdown_filter.rb
+++ b/lib/banzai/filter/markdown_filter.rb
@@ -6,7 +6,7 @@ module Banzai
def initialize(text, context = nil, result = nil)
super(text, context, result)
- @renderer = renderer(context[:markdown_engine]).new
+ @renderer = renderer(context[:markdown_engine]).new(context)
@text = @text.delete("\r")
end
diff --git a/lib/banzai/filter/math_filter.rb b/lib/banzai/filter/math_filter.rb
index 9d1bc3cf60c..8dd5a8979c8 100644
--- a/lib/banzai/filter/math_filter.rb
+++ b/lib/banzai/filter/math_filter.rb
@@ -2,6 +2,9 @@
require 'uri'
+# Generated HTML is transformed back to GFM by:
+# - app/assets/javascripts/behaviors/markdown/marks/math.js
+# - app/assets/javascripts/behaviors/markdown/nodes/code_block.js
module Banzai
module Filter
# HTML filter that adds class="code math" and removes the dollar sign in $`2+2`$.
diff --git a/lib/banzai/filter/mermaid_filter.rb b/lib/banzai/filter/mermaid_filter.rb
index 7c8b165a330..f0adb83af8a 100644
--- a/lib/banzai/filter/mermaid_filter.rb
+++ b/lib/banzai/filter/mermaid_filter.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/code_block.js
module Banzai
module Filter
class MermaidFilter < HTML::Pipeline::Filter
diff --git a/lib/banzai/filter/milestone_reference_filter.rb b/lib/banzai/filter/milestone_reference_filter.rb
index c70c3f0c04e..fce042e8946 100644
--- a/lib/banzai/filter/milestone_reference_filter.rb
+++ b/lib/banzai/filter/milestone_reference_filter.rb
@@ -101,9 +101,9 @@ module Banzai
def self_and_ancestors_ids(parent)
if group_context?(parent)
- parent.self_and_ancestors_ids
+ parent.self_and_ancestors.select(:id)
elsif project_context?(parent)
- parent.group&.self_and_ancestors_ids
+ parent.group&.self_and_ancestors&.select(:id)
end
end
diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb
index e5164e7f72a..42f9b3a689c 100644
--- a/lib/banzai/filter/reference_filter.rb
+++ b/lib/banzai/filter/reference_filter.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/reference.js
module Banzai
module Filter
# Base class for GitLab Flavored Markdown reference filters.
diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb
index 7acbc933adc..2745905c5ff 100644
--- a/lib/banzai/filter/relative_link_filter.rb
+++ b/lib/banzai/filter/relative_link_filter.rb
@@ -58,6 +58,8 @@ module Banzai
path_parts.unshift(relative_url_root, 'groups', group.full_path, '-')
elsif project
path_parts.unshift(relative_url_root, project.full_path)
+ else
+ path_parts.unshift(relative_url_root)
end
begin
@@ -148,7 +150,10 @@ module Banzai
end
def uri_type(path)
- @uri_types[path] ||= current_commit.uri_type(path)
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/58011
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ @uri_types[path] ||= current_commit.uri_type(path)
+ end
end
def current_commit
diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb
index 8ba09290e6d..a4a06eae7b7 100644
--- a/lib/banzai/filter/sanitization_filter.rb
+++ b/lib/banzai/filter/sanitization_filter.rb
@@ -8,8 +8,8 @@ module Banzai
class SanitizationFilter < HTML::Pipeline::SanitizationFilter
include Gitlab::Utils::StrongMemoize
- UNSAFE_PROTOCOLS = %w(data javascript vbscript).freeze
- TABLE_ALIGNMENT_PATTERN = /text-align: (?<alignment>center|left|right)/
+ UNSAFE_PROTOCOLS = %w(data javascript vbscript).freeze
+ TABLE_ALIGNMENT_PATTERN = /text-align: (?<alignment>center|left|right)/.freeze
def whitelist
strong_memoize(:whitelist) do
@@ -41,14 +41,16 @@ module Banzai
whitelist[:elements].push('abbr')
whitelist[:attributes]['abbr'] = %w(title)
+ # Allow the 'data-sourcepos' from CommonMark on all elements
+ whitelist[:attributes][:all].push('data-sourcepos')
+
# Disallow `name` attribute globally, allow on `a`
whitelist[:attributes][:all].delete('name')
whitelist[:attributes]['a'].push('name')
- # Allow any protocol in `a` elements...
+ # Allow any protocol in `a` elements
+ # and then remove links with unsafe protocols
whitelist[:protocols].delete('a')
-
- # ...but then remove links with unsafe protocols
whitelist[:transformers].push(self.class.remove_unsafe_links)
# Remove `rel` attribute from `a` elements
@@ -57,6 +59,12 @@ module Banzai
# Remove any `style` properties not required for table alignment
whitelist[:transformers].push(self.class.remove_unsafe_table_style)
+ # Allow `id` in a and li elements for footnotes
+ # and remove any `id` properties not matching for footnotes
+ whitelist[:attributes]['a'].push('id')
+ whitelist[:attributes]['li'] = %w(id)
+ whitelist[:transformers].push(self.class.remove_non_footnote_ids)
+
whitelist
end
@@ -112,6 +120,20 @@ module Banzai
end
end
end
+
+ def remove_non_footnote_ids
+ lambda do |env|
+ node = env[:node]
+
+ return unless node.name == 'a' || node.name == 'li'
+ return unless node.has_attribute?('id')
+
+ return if node.name == 'a' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LINK_REFERENCE_PATTERN
+ return if node.name == 'li' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LI_REFERENCE_PATTERN
+
+ node.remove_attribute('id')
+ end
+ end
end
end
end
diff --git a/lib/banzai/filter/spaced_link_filter.rb b/lib/banzai/filter/spaced_link_filter.rb
index c6a3a763c23..50bf823929c 100644
--- a/lib/banzai/filter/spaced_link_filter.rb
+++ b/lib/banzai/filter/spaced_link_filter.rb
@@ -45,8 +45,6 @@ module Banzai
]).freeze
def call
- return doc if context[:markdown_engine] == :redcarpet
-
doc.xpath(TEXT_QUERY).each do |node|
content = node.to_html
@@ -73,7 +71,8 @@ module Banzai
html = Banzai::Filter::MarkdownFilter.call(transform_markdown(match), context)
# link is wrapped in a <p>, so strip that off
- html.sub('<p>', '').chomp('</p>')
+ p_node = Nokogiri::HTML.fragment(html).at_css('p')
+ p_node ? p_node.children.to_html : html
end
def spaced_link_filter(text)
diff --git a/lib/banzai/filter/suggestion_filter.rb b/lib/banzai/filter/suggestion_filter.rb
index 307ea449140..9950db373d8 100644
--- a/lib/banzai/filter/suggestion_filter.rb
+++ b/lib/banzai/filter/suggestion_filter.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/code_block.js
module Banzai
module Filter
class SuggestionFilter < HTML::Pipeline::Filter
diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
index 18e5e9185de..9ffde52b5f2 100644
--- a/lib/banzai/filter/syntax_highlight_filter.rb
+++ b/lib/banzai/filter/syntax_highlight_filter.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
require 'rouge/plugins/common_mark'
-require 'rouge/plugins/redcarpet'
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/code_block.js
module Banzai
module Filter
# HTML Filter to highlight fenced code blocks
diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb
index c6d1e028eaa..f2ae17b44fa 100644
--- a/lib/banzai/filter/table_of_contents_filter.rb
+++ b/lib/banzai/filter/table_of_contents_filter.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js
module Banzai
module Filter
# HTML filter that adds an anchor child element to all Headers in a
diff --git a/lib/banzai/filter/task_list_filter.rb b/lib/banzai/filter/task_list_filter.rb
index ef35a49edcb..c6b402575cb 100644
--- a/lib/banzai/filter/task_list_filter.rb
+++ b/lib/banzai/filter/task_list_filter.rb
@@ -2,6 +2,10 @@
require 'task_list/filter'
+# Generated HTML is transformed back to GFM by:
+# - app/assets/javascripts/behaviors/markdown/nodes/ordered_task_list.js
+# - app/assets/javascripts/behaviors/markdown/nodes/task_list.js
+# - app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
module Banzai
module Filter
class TaskListFilter < TaskList::Filter
diff --git a/lib/banzai/filter/video_link_filter.rb b/lib/banzai/filter/video_link_filter.rb
index 0fb59c914c3..0fff104cf91 100644
--- a/lib/banzai/filter/video_link_filter.rb
+++ b/lib/banzai/filter/video_link_filter.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/video.js
module Banzai
module Filter
# Find every image that isn't already wrapped in an `a` tag, and that has
diff --git a/lib/banzai/pipeline/atom_pipeline.rb b/lib/banzai/pipeline/atom_pipeline.rb
index 13a342351b6..c632910585d 100644
--- a/lib/banzai/pipeline/atom_pipeline.rb
+++ b/lib/banzai/pipeline/atom_pipeline.rb
@@ -6,7 +6,8 @@ module Banzai
def self.transform_context(context)
super(context).merge(
only_path: false,
- xhtml: true
+ xhtml: true,
+ no_sourcepos: true
)
end
end
diff --git a/lib/banzai/pipeline/broadcast_message_pipeline.rb b/lib/banzai/pipeline/broadcast_message_pipeline.rb
index a3d63e0aaf5..580b5b72474 100644
--- a/lib/banzai/pipeline/broadcast_message_pipeline.rb
+++ b/lib/banzai/pipeline/broadcast_message_pipeline.rb
@@ -14,6 +14,12 @@ module Banzai
Filter::ExternalLinkFilter
]
end
+
+ def self.transform_context(context)
+ super(context).merge(
+ no_sourcepos: true
+ )
+ end
end
end
end
diff --git a/lib/banzai/pipeline/email_pipeline.rb b/lib/banzai/pipeline/email_pipeline.rb
index 2c08581ce0d..13e6a990407 100644
--- a/lib/banzai/pipeline/email_pipeline.rb
+++ b/lib/banzai/pipeline/email_pipeline.rb
@@ -11,7 +11,9 @@ module Banzai
def self.transform_context(context)
super(context).merge(
- only_path: false
+ only_path: false,
+ emailable_links: true,
+ no_sourcepos: true
)
end
end
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index 5f13a6d6cde..30cafd11834 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -3,11 +3,11 @@
module Banzai
module Pipeline
class GfmPipeline < BasePipeline
- # These filters convert GitLab Flavored Markdown (GFM) to HTML.
- # The handlers defined in app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
- # consequently convert that same HTML to GFM to be copied to the clipboard.
- # Every filter that generates HTML from GFM should have a handler in
- # app/assets/javascripts/behaviors/markdown/copy_as_gfm.js, in reverse order.
+ # These filters transform GitLab Flavored Markdown (GFM) to HTML.
+ # The nodes and marks referenced in app/assets/javascripts/behaviors/markdown/editor_extensions.js
+ # consequently transform that same HTML to GFM to be copied to the clipboard.
+ # Every filter that generates HTML from GFM should have a node or mark in
+ # app/assets/javascripts/behaviors/markdown/editor_extensions.js.
# The GFM-to-HTML-to-GFM cycle is tested in spec/features/copy_as_gfm_spec.rb.
def self.filters
@filters ||= FilterArray[
@@ -30,6 +30,7 @@ module Banzai
Filter::AutolinkFilter,
Filter::ExternalLinkFilter,
Filter::SuggestionFilter,
+ Filter::FootnoteFilter,
*reference_filters,
diff --git a/lib/banzai/pipeline/markup_pipeline.rb b/lib/banzai/pipeline/markup_pipeline.rb
index db79a22549c..ceba082cd4f 100644
--- a/lib/banzai/pipeline/markup_pipeline.rb
+++ b/lib/banzai/pipeline/markup_pipeline.rb
@@ -7,7 +7,8 @@ module Banzai
@filters ||= FilterArray[
Filter::SanitizationFilter,
Filter::ExternalLinkFilter,
- Filter::PlantumlFilter
+ Filter::PlantumlFilter,
+ Filter::SyntaxHighlightFilter
]
end
end
diff --git a/lib/banzai/pipeline/single_line_pipeline.rb b/lib/banzai/pipeline/single_line_pipeline.rb
index 61ff7b0bcce..72374207a8f 100644
--- a/lib/banzai/pipeline/single_line_pipeline.rb
+++ b/lib/banzai/pipeline/single_line_pipeline.rb
@@ -27,6 +27,12 @@ module Banzai
Filter::CommitReferenceFilter
]
end
+
+ def self.transform_context(context)
+ super(context).merge(
+ no_sourcepos: true
+ )
+ end
end
end
end
diff --git a/lib/banzai/renderer/redcarpet/html.rb b/lib/banzai/renderer/redcarpet/html.rb
deleted file mode 100644
index 84931fdc784..00000000000
--- a/lib/banzai/renderer/redcarpet/html.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Renderer
- module Redcarpet
- class HTML < ::Redcarpet::Render::HTML
- def block_code(code, lang)
- lang_attr = lang ? %Q{ lang="#{lang}"} : ''
-
- "\n<pre>" \
- "<code#{lang_attr}>#{ERB::Util.html_escape(code)}</code>" \
- "</pre>"
- end
- end
- end
- end
-end
diff --git a/lib/bitbucket_server/client.rb b/lib/bitbucket_server/client.rb
index 83e8808db07..6a608058813 100644
--- a/lib/bitbucket_server/client.rb
+++ b/lib/bitbucket_server/client.rb
@@ -4,18 +4,6 @@ module BitbucketServer
class Client
attr_reader :connection
- ServerError = Class.new(StandardError)
-
- SERVER_ERRORS = [SocketError,
- OpenSSL::SSL::SSLError,
- Errno::ECONNRESET,
- Errno::ECONNREFUSED,
- Errno::EHOSTUNREACH,
- Net::OpenTimeout,
- Net::ReadTimeout,
- Gitlab::HTTP::BlockedUrlError,
- BitbucketServer::Connection::ConnectionError].freeze
-
def initialize(options = {})
@connection = Connection.new(options)
end
@@ -64,8 +52,6 @@ module BitbucketServer
def get_collection(path, type, page_offset: 0, limit: nil)
paginator = BitbucketServer::Paginator.new(connection, Addressable::URI.escape(path), type, page_offset: page_offset, limit: limit)
BitbucketServer::Collection.new(paginator)
- rescue *SERVER_ERRORS => e
- raise ServerError, e
end
end
end
diff --git a/lib/bitbucket_server/collection.rb b/lib/bitbucket_server/collection.rb
index 7e4b2277bbe..f549acbd87f 100644
--- a/lib/bitbucket_server/collection.rb
+++ b/lib/bitbucket_server/collection.rb
@@ -25,13 +25,13 @@ module BitbucketServer
end
def prev_page
- return nil unless current_page > 1
+ return unless current_page > 1
current_page - 1
end
def next_page
- return nil unless has_next_page?
+ return unless has_next_page?
current_page + 1
end
diff --git a/lib/bitbucket_server/connection.rb b/lib/bitbucket_server/connection.rb
index 7efcdcf8619..fbd451efb23 100644
--- a/lib/bitbucket_server/connection.rb
+++ b/lib/bitbucket_server/connection.rb
@@ -7,6 +7,17 @@ module BitbucketServer
DEFAULT_API_VERSION = '1.0'
SEPARATOR = '/'
+ NETWORK_ERRORS = [
+ SocketError,
+ OpenSSL::SSL::SSLError,
+ Errno::ECONNRESET,
+ Errno::ECONNREFUSED,
+ Errno::EHOSTUNREACH,
+ Net::OpenTimeout,
+ Net::ReadTimeout,
+ Gitlab::HTTP::BlockedUrlError
+ ].freeze
+
attr_reader :api_version, :base_uri, :username, :token
ConnectionError = Class.new(StandardError)
@@ -27,6 +38,8 @@ module BitbucketServer
check_errors!(response)
response.parsed_response
+ rescue *NETWORK_ERRORS => e
+ raise ConnectionError, e
end
def post(path, body)
@@ -38,6 +51,8 @@ module BitbucketServer
check_errors!(response)
response.parsed_response
+ rescue *NETWORK_ERRORS => e
+ raise ConnectionError, e
end
# We need to support two different APIs for deletion:
@@ -55,11 +70,14 @@ module BitbucketServer
check_errors!(response)
response.parsed_response
+ rescue *NETWORK_ERRORS => e
+ raise ConnectionError, e
end
private
def check_errors!(response)
+ return if ActionDispatch::Response::NO_CONTENT_CODES.include?(response.code)
raise ConnectionError, "Response is not valid JSON" unless response.parsed_response.is_a?(Hash)
return if response.code >= 200 && response.code < 300
diff --git a/lib/bitbucket_server/paginator.rb b/lib/bitbucket_server/paginator.rb
index aa5f84f44b3..9eda1c921b2 100644
--- a/lib/bitbucket_server/paginator.rb
+++ b/lib/bitbucket_server/paginator.rb
@@ -12,7 +12,7 @@ module BitbucketServer
@url = url
@page = nil
@page_offset = page_offset
- @limit = limit || PAGE_LENGTH
+ @limit = limit
@total = 0
end
@@ -34,6 +34,8 @@ module BitbucketServer
attr_reader :connection, :page, :url, :type, :limit
def over_limit?
+ return false unless @limit
+
@limit.positive? && @total >= @limit
end
@@ -42,11 +44,15 @@ module BitbucketServer
end
def starting_offset
- [0, page_offset - 1].max * limit
+ [0, page_offset - 1].max * max_per_page
+ end
+
+ def max_per_page
+ limit || PAGE_LENGTH
end
def fetch_next_page
- parsed_response = connection.get(@url, start: next_offset, limit: @limit)
+ parsed_response = connection.get(@url, start: next_offset, limit: max_per_page)
Page.new(parsed_response, type)
end
end
diff --git a/lib/constraints/project_url_constrainer.rb b/lib/constraints/project_url_constrainer.rb
index eadfbf7bc01..d41490d2ebd 100644
--- a/lib/constraints/project_url_constrainer.rb
+++ b/lib/constraints/project_url_constrainer.rb
@@ -2,12 +2,13 @@
module Constraints
class ProjectUrlConstrainer
- def matches?(request)
+ def matches?(request, existence_check: true)
namespace_path = request.params[:namespace_id]
project_path = request.params[:project_id] || request.params[:id]
full_path = [namespace_path, project_path].join('/')
return false unless ProjectPathValidator.valid_path?(full_path)
+ return true unless existence_check
# We intentionally allow SELECT(*) here so result of this query can be used
# as cache for further Project.find_by_full_path calls within request
diff --git a/lib/container_registry/tag.rb b/lib/container_registry/tag.rb
index 8633e764f90..ef41dc560c9 100644
--- a/lib/container_registry/tag.rb
+++ b/lib/container_registry/tag.rb
@@ -2,6 +2,8 @@
module ContainerRegistry
class Tag
+ include Gitlab::Utils::StrongMemoize
+
attr_reader :repository, :name
delegate :registry, :client, to: :repository
@@ -15,6 +17,10 @@ module ContainerRegistry
manifest.present?
end
+ def latest?
+ name == "latest"
+ end
+
def v1?
manifest && manifest['schemaVersion'] == 1
end
@@ -24,7 +30,9 @@ module ContainerRegistry
end
def manifest
- @manifest ||= client.repository_manifest(repository.path, name)
+ strong_memoize(:manifest) do
+ client.repository_manifest(repository.path, name)
+ end
end
def path
@@ -42,36 +50,44 @@ module ContainerRegistry
end
def digest
- @digest ||= client.repository_tag_digest(repository.path, name)
+ strong_memoize(:digest) do
+ client.repository_tag_digest(repository.path, name)
+ end
end
def config_blob
- return @config_blob if defined?(@config_blob)
return unless manifest && manifest['config']
- @config_blob = repository.blob(manifest['config'])
+ strong_memoize(:config_blob) do
+ repository.blob(manifest['config'])
+ end
end
def config
- return unless config_blob
+ return unless config_blob&.data
- @config ||= ContainerRegistry::Config.new(self, config_blob) if config_blob.data
+ strong_memoize(:config) do
+ ContainerRegistry::Config.new(self, config_blob)
+ end
end
def created_at
return unless config
- @created_at ||= DateTime.rfc3339(config['created'])
+ strong_memoize(:created_at) do
+ DateTime.rfc3339(config['created'])
+ end
end
def layers
- return @layers if defined?(@layers)
return unless manifest
- layers = manifest['layers'] || manifest['fsLayers']
+ strong_memoize(:layers) do
+ layers = manifest['layers'] || manifest['fsLayers']
- @layers = layers.map do |layer|
- repository.blob(layer)
+ layers.map do |layer|
+ repository.blob(layer)
+ end
end
end
diff --git a/lib/declarative_policy/rule.rb b/lib/declarative_policy/rule.rb
index f38f4f0a50f..964d35cde9e 100644
--- a/lib/declarative_policy/rule.rb
+++ b/lib/declarative_policy/rule.rb
@@ -84,7 +84,7 @@ module DeclarativePolicy
# returns nil unless it's already cached
def cached_pass?(context)
condition = context.condition(@name)
- return nil unless condition.cached?
+ return unless condition.cached?
condition.pass?
end
@@ -124,7 +124,7 @@ module DeclarativePolicy
def cached_pass?(context)
condition = delegated_context(context).condition(@name)
- return nil unless condition.cached?
+ return unless condition.cached?
condition.pass?
rescue MissingDelegate
@@ -161,7 +161,7 @@ module DeclarativePolicy
def cached_pass?(context)
runner = context.runner(@ability)
- return nil unless runner.cached?
+ return unless runner.cached?
runner.pass?
end
diff --git a/lib/feature.rb b/lib/feature.rb
index e048a443abc..749c861d740 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -102,4 +102,48 @@ class Feature
expires_in: 1.hour)
end
end
+
+ class Target
+ attr_reader :params
+
+ def initialize(params)
+ @params = params
+ end
+
+ def gate_specified?
+ %i(user project group feature_group).any? { |key| params.key?(key) }
+ end
+
+ def targets
+ [feature_group, user, project, group].compact
+ end
+
+ private
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def feature_group
+ return unless params.key?(:feature_group)
+
+ Feature.group(params[:feature_group])
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def user
+ return unless params.key?(:user)
+
+ UserFinder.new(params[:user]).find_by_username!
+ end
+
+ def project
+ return unless params.key?(:project)
+
+ Project.find_by_full_path(params[:project])
+ end
+
+ def group
+ return unless params.key?(:group)
+
+ Group.find_by_full_path(params[:group])
+ end
+ end
end
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index 2ef54658a11..f42ca5a9cd6 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -7,6 +7,14 @@ module Gitlab
Pathname.new(File.expand_path('..', __dir__))
end
+ def self.version_info
+ Gitlab::VersionInfo.parse(Gitlab::VERSION)
+ end
+
+ def self.pre_release?
+ VERSION.include?('pre')
+ end
+
def self.config
Settings
end
@@ -50,11 +58,15 @@ module Gitlab
Rails.env.development? || org? || com?
end
- def self.pre_release?
- VERSION.include?('pre')
+ def self.ee?
+ Object.const_defined?(:License)
end
- def self.version_info
- Gitlab::VersionInfo.parse(Gitlab::VERSION)
+ def self.process_name
+ return 'sidekiq' if Sidekiq.server?
+ return 'console' if defined?(Rails::Console)
+ return 'test' if Rails.env.test?
+
+ 'web'
end
end
diff --git a/lib/gitlab/access/branch_protection.rb b/lib/gitlab/access/branch_protection.rb
new file mode 100644
index 00000000000..f039e5c011f
--- /dev/null
+++ b/lib/gitlab/access/branch_protection.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Access
+ # A wrapper around Integer based branch protection levels.
+ #
+ # This wrapper can be used to work with branch protection levels without
+ # having to directly refer to the constants. For example, instead of this:
+ #
+ # if access_level == Gitlab::Access::PROTECTION_DEV_CAN_PUSH
+ # ...
+ # end
+ #
+ # You can write this instead:
+ #
+ # protection = BranchProtection.new(access_level)
+ #
+ # if protection.developer_can_push?
+ # ...
+ # end
+ class BranchProtection
+ attr_reader :level
+
+ # @param [Integer] level The branch protection level as an Integer.
+ def initialize(level)
+ @level = level
+ end
+
+ def any?
+ level != PROTECTION_NONE
+ end
+
+ def developer_can_push?
+ level == PROTECTION_DEV_CAN_PUSH
+ end
+
+ def developer_can_merge?
+ level == PROTECTION_DEV_CAN_MERGE
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 7aa02009aa0..b2ef04d23d7 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -12,6 +12,9 @@ module Gitlab
# Scopes used for OpenID Connect
OPENID_SCOPES = [:openid].freeze
+ # OpenID Connect profile scopes
+ PROFILE_SCOPES = [:profile, :email].freeze
+
# Default scopes for OAuth applications that don't define their own
DEFAULT_SCOPES = [:api].freeze
@@ -284,7 +287,7 @@ module Gitlab
# Other available scopes
def optional_scopes
- available_scopes + OPENID_SCOPES - DEFAULT_SCOPES
+ available_scopes + OPENID_SCOPES + PROFILE_SCOPES - DEFAULT_SCOPES
end
def registry_scopes
diff --git a/lib/gitlab/auth/ldap/adapter.rb b/lib/gitlab/auth/ldap/adapter.rb
index 42c657afe6a..15b9d5ad6e9 100644
--- a/lib/gitlab/auth/ldap/adapter.rb
+++ b/lib/gitlab/auth/ldap/adapter.rb
@@ -30,14 +30,7 @@ module Gitlab
def users(fields, value, limit = nil)
options = user_options(Array(fields), value, limit)
-
- entries = ldap_search(options).select do |entry|
- entry.respond_to? config.uid
- end
-
- entries.map do |entry|
- Gitlab::Auth::LDAP::Person.new(entry, provider)
- end
+ users_search(options)
end
def user(*args)
@@ -90,6 +83,16 @@ module Gitlab
SEARCH_RETRY_FACTOR[retry_number] * config.timeout
end
+ def users_search(options)
+ entries = ldap_search(options).select do |entry|
+ entry.respond_to? config.uid
+ end
+
+ entries.map do |entry|
+ Gitlab::Auth::LDAP::Person.new(entry, provider)
+ end
+ end
+
def user_options(fields, value, limit)
options = {
attributes: Gitlab::Auth::LDAP::Person.ldap_attributes(config),
diff --git a/lib/gitlab/auth/ldap/config.rb b/lib/gitlab/auth/ldap/config.rb
index 7ceb96f502b..47d63eb53cf 100644
--- a/lib/gitlab/auth/ldap/config.rb
+++ b/lib/gitlab/auth/ldap/config.rb
@@ -75,7 +75,8 @@ module Gitlab
encryption: options['encryption'],
filter: omniauth_user_filter,
name_proc: name_proc,
- disable_verify_certificates: !options['verify_certificates']
+ disable_verify_certificates: !options['verify_certificates'],
+ tls_options: tls_options
)
if has_auth?
@@ -85,9 +86,6 @@ module Gitlab
)
end
- opts[:ca_file] = options['ca_file'] if options['ca_file'].present?
- opts[:ssl_version] = options['ssl_version'] if options['ssl_version'].present?
-
opts
end
@@ -196,24 +194,28 @@ module Gitlab
end
def encryption_options
- method = translate_method(options['encryption'])
- return nil unless method
+ method = translate_method
+ return unless method
{
method: method,
- tls_options: tls_options(method)
+ tls_options: tls_options
}
end
- def translate_method(method_from_config)
- NET_LDAP_ENCRYPTION_METHOD[method_from_config.to_sym]
+ def translate_method
+ NET_LDAP_ENCRYPTION_METHOD[options['encryption']&.to_sym]
end
- def tls_options(method)
- return { verify_mode: OpenSSL::SSL::VERIFY_NONE } unless method
+ def tls_options
+ return @tls_options if defined?(@tls_options)
+
+ method = translate_method
+ return unless method
- opts = if options['verify_certificates']
- OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
+ opts = if options['verify_certificates'] && method != 'plain'
+ # Dup so we don't accidentally overwrite the constant
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.dup
else
# It is important to explicitly set verify_mode for two reasons:
# 1. The behavior of OpenSSL is undefined when verify_mode is not set.
@@ -222,10 +224,35 @@ module Gitlab
{ verify_mode: OpenSSL::SSL::VERIFY_NONE }
end
- opts[:ca_file] = options['ca_file'] if options['ca_file'].present?
- opts[:ssl_version] = options['ssl_version'] if options['ssl_version'].present?
+ opts.merge!(custom_tls_options)
- opts
+ @tls_options = opts
+ end
+
+ def custom_tls_options
+ return {} unless options['tls_options']
+
+ # Dup so we don't overwrite the original value
+ custom_options = options['tls_options'].dup.delete_if { |_, value| value.nil? || value.blank? }
+ custom_options.symbolize_keys!
+
+ if custom_options[:cert]
+ begin
+ custom_options[:cert] = OpenSSL::X509::Certificate.new(custom_options[:cert])
+ rescue OpenSSL::X509::CertificateError => e
+ Rails.logger.error "LDAP TLS Options 'cert' is invalid for provider #{provider}: #{e.message}"
+ end
+ end
+
+ if custom_options[:key]
+ begin
+ custom_options[:key] = OpenSSL::PKey.read(custom_options[:key])
+ rescue OpenSSL::PKey::PKeyError => e
+ Rails.logger.error "LDAP TLS Options 'key' is invalid for provider #{provider}: #{e.message}"
+ end
+ end
+
+ custom_options
end
def auth_options
diff --git a/lib/gitlab/auth/ldap/person.rb b/lib/gitlab/auth/ldap/person.rb
index a0244a3cea1..13d67e0f871 100644
--- a/lib/gitlab/auth/ldap/person.rb
+++ b/lib/gitlab/auth/ldap/person.rb
@@ -98,9 +98,7 @@ module Gitlab
private
- def entry
- @entry
- end
+ attr_reader :entry
def config
@config ||= Gitlab::Auth::LDAP::Config.new(provider)
@@ -114,7 +112,7 @@ module Gitlab
attributes = Array(config.attributes[attribute.to_s])
selected_attr = attributes.find { |attr| entry.respond_to?(attr) }
- return nil unless selected_attr
+ return unless selected_attr
entry.public_send(selected_attr) # rubocop:disable GitlabSecurity/PublicSend
end
diff --git a/lib/gitlab/auth/o_auth/user.rb b/lib/gitlab/auth/o_auth/user.rb
index a4e8a41b246..f38c5d57c44 100644
--- a/lib/gitlab/auth/o_auth/user.rb
+++ b/lib/gitlab/auth/o_auth/user.rb
@@ -46,7 +46,7 @@ module Gitlab
gl_user.block if block_after_save
- log.info "(#{provider}) saving user #{auth_hash.email} from login with extern_uid => #{auth_hash.uid}"
+ log.info "(#{provider}) saving user #{auth_hash.email} from login with admin => #{gl_user.admin}, extern_uid => #{auth_hash.uid}"
gl_user
rescue ActiveRecord::RecordInvalid => e
log.info "(#{provider}) Error saving user #{auth_hash.uid} (#{auth_hash.email}): #{gl_user.errors.full_messages}"
diff --git a/lib/gitlab/auth/omniauth_identity_linker_base.rb b/lib/gitlab/auth/omniauth_identity_linker_base.rb
index 253445570f2..c620fc5d6bd 100644
--- a/lib/gitlab/auth/omniauth_identity_linker_base.rb
+++ b/lib/gitlab/auth/omniauth_identity_linker_base.rb
@@ -12,7 +12,7 @@ module Gitlab
end
def link
- save if identity.new_record?
+ save if unlinked?
end
def changed?
@@ -35,6 +35,10 @@ module Gitlab
@changed = identity.save
end
+ def unlinked?
+ identity.new_record?
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def identity
@identity ||= current_user.identities
diff --git a/lib/gitlab/auth/saml/auth_hash.rb b/lib/gitlab/auth/saml/auth_hash.rb
index 1af9fa40c3a..b0df9757bbd 100644
--- a/lib/gitlab/auth/saml/auth_hash.rb
+++ b/lib/gitlab/auth/saml/auth_hash.rb
@@ -10,11 +10,11 @@ module Gitlab
def authn_context
response_object = auth_hash.extra[:response_object]
- return nil if response_object.blank?
+ return if response_object.blank?
document = response_object.decrypted_document
document ||= response_object.document
- return nil if document.blank?
+ return if document.blank?
extract_authn_context(document)
end
diff --git a/lib/gitlab/background_migration.rb b/lib/gitlab/background_migration.rb
index d72befce571..5251e0fadf9 100644
--- a/lib/gitlab/background_migration.rb
+++ b/lib/gitlab/background_migration.rb
@@ -16,11 +16,18 @@ module Gitlab
# re-raises the exception.
#
# steal_class - The name of the class for which to steal jobs.
- def self.steal(steal_class)
- enqueued = Sidekiq::Queue.new(self.queue)
- scheduled = Sidekiq::ScheduledSet.new
+ def self.steal(steal_class, retry_dead_jobs: false)
+ queues = [
+ Sidekiq::ScheduledSet.new,
+ Sidekiq::Queue.new(self.queue)
+ ]
+
+ if retry_dead_jobs
+ queues << Sidekiq::RetrySet.new
+ queues << Sidekiq::DeadSet.new
+ end
- [scheduled, enqueued].each do |queue|
+ queues.each do |queue|
queue.each do |job|
migration_class, migration_args = job.args
@@ -51,6 +58,19 @@ module Gitlab
migration_class_for(class_name).new.perform(*arguments)
end
+ def self.exists?(migration_class)
+ enqueued = Sidekiq::Queue.new(self.queue)
+ scheduled = Sidekiq::ScheduledSet.new
+
+ [enqueued, scheduled].each do |queue|
+ queue.each do |job|
+ return true if job.queue == self.queue && job.args.first == migration_class
+ end
+ end
+
+ false
+ end
+
def self.migration_class_for(class_name)
const_get(class_name)
end
diff --git a/lib/gitlab/background_migration/backfill_project_repositories.rb b/lib/gitlab/background_migration/backfill_project_repositories.rb
index aaf520d70f6..c8d83cc1803 100644
--- a/lib/gitlab/background_migration/backfill_project_repositories.rb
+++ b/lib/gitlab/background_migration/backfill_project_repositories.rb
@@ -83,7 +83,7 @@ module Gitlab
extend ActiveSupport::Concern
def full_path
- @full_path ||= build_full_path
+ route&.path || build_full_path
end
def build_full_path
@@ -99,7 +99,12 @@ module Gitlab
end
end
- # Namespace model.
+ # Route model
+ class Route < ActiveRecord::Base
+ belongs_to :source, inverse_of: :route, polymorphic: true
+ end
+
+ # Namespace model
class Namespace < ActiveRecord::Base
self.table_name = 'namespaces'
self.inheritance_column = nil
@@ -108,6 +113,8 @@ module Gitlab
belongs_to :parent, class_name: 'Namespace', inverse_of: 'namespaces'
+ has_one :route, -> { where(source_type: 'Namespace') }, inverse_of: :source, foreign_key: :source_id
+
has_many :projects, inverse_of: :parent
has_many :namespaces, inverse_of: :parent
end
@@ -134,6 +141,7 @@ module Gitlab
belongs_to :parent, class_name: 'Namespace', foreign_key: :namespace_id, inverse_of: 'projects'
+ has_one :route, -> { where(source_type: 'Project') }, inverse_of: :source, foreign_key: :source_id
has_one :project_repository, inverse_of: :project
delegate :disk_path, to: :storage
@@ -194,6 +202,8 @@ module Gitlab
def project_repositories(start_id, stop_id)
projects
.without_project_repository
+ .includes(:route, parent: [:route]).references(:routes)
+ .includes(:parent).references(:namespaces)
.where(id: start_id..stop_id)
.map { |project| build_attributes_for_project(project) }
.compact
diff --git a/lib/gitlab/background_migration/encrypt_columns.rb b/lib/gitlab/background_migration/encrypt_columns.rb
index b9ad8267e37..173543b7c25 100644
--- a/lib/gitlab/background_migration/encrypt_columns.rb
+++ b/lib/gitlab/background_migration/encrypt_columns.rb
@@ -91,7 +91,8 @@ module Gitlab
# No need to do anything if the plaintext is nil, or an encrypted
# value already exists
- return nil unless plaintext.present? && !ciphertext.present?
+ return unless plaintext.present?
+ return if ciphertext.present?
# attr_encrypted will calculate and set the expected value for us
instance.public_send("#{plain_column}=", plaintext) # rubocop:disable GitlabSecurity/PublicSend
diff --git a/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb b/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb
index 38fecac1bfe..42fcaa87e66 100644
--- a/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb
+++ b/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb
@@ -24,7 +24,7 @@ module Gitlab
def commit_title
commit = commits.last
- return nil unless commit && commit[:message]
+ return unless commit && commit[:message]
index = commit[:message].index("\n")
message = index ? commit[:message][0..index] : commit[:message]
diff --git a/lib/gitlab/background_migration/migrate_stage_status.rb b/lib/gitlab/background_migration/migrate_stage_status.rb
index 0e5c7f092f2..6a29a632577 100644
--- a/lib/gitlab/background_migration/migrate_stage_status.rb
+++ b/lib/gitlab/background_migration/migrate_stage_status.rb
@@ -16,10 +16,10 @@ module Gitlab
scope :running, -> { where(status: 'running') }
scope :pending, -> { where(status: 'pending') }
scope :success, -> { where(status: 'success') }
- scope :failed, -> { where(status: 'failed') }
- scope :canceled, -> { where(status: 'canceled') }
- scope :skipped, -> { where(status: 'skipped') }
- scope :manual, -> { where(status: 'manual') }
+ scope :failed, -> { where(status: 'failed') }
+ scope :canceled, -> { where(status: 'canceled') }
+ scope :skipped, -> { where(status: 'skipped') }
+ scope :manual, -> { where(status: 'manual') }
scope :failed_but_allowed, -> do
where(allow_failure: true, status: [:failed, :canceled])
diff --git a/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb b/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb
index 4a9a62aaeb5..a84f794bfae 100644
--- a/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb
+++ b/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb
@@ -127,7 +127,7 @@ module Gitlab
full_path = matchd[1]
project = Gitlab::BackgroundMigration::PopulateUntrackedUploadsDependencies::Project.find_by_full_path(full_path)
- return nil unless project
+ return unless project
project.id
end
diff --git a/lib/gitlab/bare_repository_import/importer.rb b/lib/gitlab/bare_repository_import/importer.rb
index 3cd327f5109..144ba2ec031 100644
--- a/lib/gitlab/bare_repository_import/importer.rb
+++ b/lib/gitlab/bare_repository_import/importer.rb
@@ -108,7 +108,7 @@ module Gitlab
end
def find_or_create_groups
- return nil unless group_path.present?
+ return unless group_path.present?
log " * Using namespace: #{group_path}"
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
index eaead41a720..441fdec8a1e 100644
--- a/lib/gitlab/bitbucket_import/importer.rb
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -47,7 +47,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def find_user_id(username)
- return nil unless username
+ return unless username
return users[username] if users.key?(username)
@@ -65,9 +65,9 @@ module Gitlab
def import_wiki
return if project.wiki.repository_exists?
- disk_path = project.wiki.disk_path
- import_url = project.import_url.sub(/\.git\z/, ".git/wiki")
- gitlab_shell.import_repository(project.repository_storage, disk_path, import_url)
+ wiki = WikiFormatter.new(project)
+
+ gitlab_shell.import_wiki_repository(project, wiki)
rescue StandardError => e
errors << { type: :wiki, errors: e.message }
end
diff --git a/lib/gitlab/bitbucket_import/wiki_formatter.rb b/lib/gitlab/bitbucket_import/wiki_formatter.rb
new file mode 100644
index 00000000000..b8ff43b777b
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/wiki_formatter.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BitbucketImport
+ class WikiFormatter
+ attr_reader :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ def disk_path
+ project.wiki.disk_path
+ end
+
+ def full_path
+ project.wiki.full_path
+ end
+
+ def import_url
+ project.import_url.sub(/\.git\z/, ".git/wiki")
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb
index 28cfb46e2d4..4a789ae457f 100644
--- a/lib/gitlab/bitbucket_server_import/importer.rb
+++ b/lib/gitlab/bitbucket_server_import/importer.rb
@@ -65,7 +65,7 @@ module Gitlab
end
def find_user_id(email)
- return nil unless email
+ return unless email
return users[email] if users.key?(email)
@@ -132,7 +132,7 @@ module Gitlab
project.repository.fetch_as_mirror(project.import_url, refmap: self.class.refmap, remote_name: REMOTE_NAME)
log_info(stage: 'import_repository', message: 'finished import')
- rescue Gitlab::Shell::Error, Gitlab::Git::RepositoryMirroring::RemoteError => e
+ rescue Gitlab::Shell::Error => e
log_error(stage: 'import_repository', message: 'failed import', error: e.message)
# Expire cache to prevent scenarios such as:
@@ -140,7 +140,7 @@ module Gitlab
# 2. Retried import, repo is broken or not imported but +exists?+ still returns true
project.repository.expire_content_cache if project.repository_exists?
- raise e.message
+ raise
end
# Bitbucket Server keeps tracks of references for open pull requests in
diff --git a/lib/gitlab/blob_helper.rb b/lib/gitlab/blob_helper.rb
index 488c1d85387..d3e15a79a8b 100644
--- a/lib/gitlab/blob_helper.rb
+++ b/lib/gitlab/blob_helper.rb
@@ -12,7 +12,7 @@ module Gitlab
end
def viewable?
- !large? && text?
+ !large? && text_in_repo?
end
MEGABYTE = 1024 * 1024
@@ -21,7 +21,7 @@ module Gitlab
size.to_i > MEGABYTE
end
- def binary?
+ def binary_in_repo?
# Large blobs aren't even loaded into memory
if data.nil?
true
@@ -40,8 +40,8 @@ module Gitlab
end
end
- def text?
- !binary?
+ def text_in_repo?
+ !binary_in_repo?
end
def image?
@@ -113,7 +113,7 @@ module Gitlab
def content_type
# rubocop:disable Style/MultilineTernaryOperator
# rubocop:disable Style/NestedTernaryOperator
- @content_type ||= binary_mime_type? || binary? ? mime_type :
+ @content_type ||= binary_mime_type? || binary_in_repo? ? mime_type :
(encoding ? "text/plain; charset=#{encoding.downcase}" : "text/plain")
# rubocop:enable Style/NestedTernaryOperator
# rubocop:enable Style/MultilineTernaryOperator
diff --git a/lib/gitlab/chat.rb b/lib/gitlab/chat.rb
new file mode 100644
index 00000000000..23d4fb36b66
--- /dev/null
+++ b/lib/gitlab/chat.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Chat
+ # Returns `true` if Chatops is available for the current instance.
+ def self.available?
+ ::Feature.enabled?(:chatops, default_enabled: true)
+ end
+ end
+end
diff --git a/lib/gitlab/chat/command.rb b/lib/gitlab/chat/command.rb
new file mode 100644
index 00000000000..49b7dcf4bbe
--- /dev/null
+++ b/lib/gitlab/chat/command.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Chat
+ # Class for scheduling chat pipelines.
+ #
+ # A Command takes care of creating a `Ci::Pipeline` with all the data
+ # necessary to execute a chat command. This includes data such as the chat
+ # data (e.g. the response URL) and any environment variables that should be
+ # exposed to the chat command.
+ class Command
+ include Utils::StrongMemoize
+
+ attr_reader :project, :chat_name, :name, :arguments, :response_url,
+ :channel
+
+ # project - The Project to schedule the command for.
+ # chat_name - The ChatName belonging to the user that scheduled the
+ # command.
+ # name - The name of the chat command to run.
+ # arguments - The arguments (as a String) to pass to the command.
+ # channel - The channel the message was sent from.
+ # response_url - The URL to send the response back to.
+ def initialize(project:, chat_name:, name:, arguments:, channel:, response_url:)
+ @project = project
+ @chat_name = chat_name
+ @name = name
+ @arguments = arguments
+ @channel = channel
+ @response_url = response_url
+ end
+
+ # Tries to create a new pipeline.
+ #
+ # This method will return a pipeline that _may_ be persisted, or `nil` if
+ # the pipeline could not be created.
+ def try_create_pipeline
+ return unless valid?
+
+ create_pipeline
+ end
+
+ def create_pipeline
+ service = ::Ci::CreatePipelineService.new(
+ project,
+ chat_name.user,
+ ref: branch,
+ sha: commit,
+ chat_data: {
+ chat_name_id: chat_name.id,
+ command: name,
+ arguments: arguments,
+ response_url: response_url
+ }
+ )
+
+ service.execute(:chat) do |pipeline|
+ build_environment_variables(pipeline)
+ build_chat_data(pipeline)
+ end
+ end
+
+ # pipeline - The `Ci::Pipeline` to create the environment variables for.
+ def build_environment_variables(pipeline)
+ pipeline.variables.build(
+ [{ key: 'CHAT_INPUT', value: arguments },
+ { key: 'CHAT_CHANNEL', value: channel }]
+ )
+ end
+
+ # pipeline - The `Ci::Pipeline` to create the chat data for.
+ def build_chat_data(pipeline)
+ pipeline.build_chat_data(
+ chat_name_id: chat_name.id,
+ response_url: response_url
+ )
+ end
+
+ def valid?
+ branch && commit
+ end
+
+ def branch
+ strong_memoize(:branch) { project.default_branch }
+ end
+
+ def commit
+ strong_memoize(:commit) do
+ project.commit(branch)&.id if branch
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/chat/output.rb b/lib/gitlab/chat/output.rb
new file mode 100644
index 00000000000..411b1555a7d
--- /dev/null
+++ b/lib/gitlab/chat/output.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Chat
+ # Class for gathering and formatting the output of a `Ci::Build`.
+ class Output
+ attr_reader :build
+
+ MissingBuildSectionError = Class.new(StandardError)
+
+ # The primary trace section to look for.
+ PRIMARY_SECTION = 'chat_reply'
+
+ # The backup trace section in case the primary one could not be found.
+ FALLBACK_SECTION = 'build_script'
+
+ # build - The `Ci::Build` to obtain the output from.
+ def initialize(build)
+ @build = build
+ end
+
+ # Returns a `String` containing the output of the build.
+ #
+ # The output _does not_ include the command that was executed.
+ def to_s
+ offset, length = read_offset_and_length
+
+ trace.read do |stream|
+ stream.seek(offset)
+
+ output = stream
+ .stream
+ .read(length)
+ .force_encoding(Encoding.default_external)
+
+ without_executed_command_line(output)
+ end
+ end
+
+ # Returns the offset to seek to and the number of bytes to read relative
+ # to the offset.
+ def read_offset_and_length
+ section = find_build_trace_section(PRIMARY_SECTION) ||
+ find_build_trace_section(FALLBACK_SECTION)
+
+ unless section
+ raise(
+ MissingBuildSectionError,
+ "The build_script trace section could not be found for build #{build.id}"
+ )
+ end
+
+ length = section[:byte_end] - section[:byte_start]
+
+ [section[:byte_start], length]
+ end
+
+ # Removes the line containing the executed command from the build output.
+ #
+ # output - A `String` containing the output of a trace section.
+ def without_executed_command_line(output)
+ # If `output.split("\n")` produces an empty Array then the slicing that
+ # follows it will produce a nil. For example:
+ #
+ # "\n".split("\n") # => []
+ # "\n".split("\n")[1..-1] # => nil
+ #
+ # To work around this we only "join" if we're given an Array.
+ if (converted = output.split("\n")[1..-1])
+ converted.join("\n")
+ else
+ ''
+ end
+ end
+
+ # Returns the trace section for the given name, or `nil` if the section
+ # could not be found.
+ #
+ # name - The name of the trace section to find.
+ def find_build_trace_section(name)
+ trace_sections.find { |s| s[:name] == name }
+ end
+
+ def trace_sections
+ @trace_sections ||= trace.extract_sections
+ end
+
+ def trace
+ @trace ||= build.trace
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/chat/responder.rb b/lib/gitlab/chat/responder.rb
new file mode 100644
index 00000000000..6267fbc20e2
--- /dev/null
+++ b/lib/gitlab/chat/responder.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Chat
+ module Responder
+ # Returns an instance of the responder to use for generating chat
+ # responses.
+ #
+ # This method will return `nil` if no formatter is available for the given
+ # build.
+ #
+ # build - A `Ci::Build` that executed a chat command.
+ def self.responder_for(build)
+ service = build.pipeline.chat_data&.chat_name&.service
+
+ if (responder = service.try(:chat_responder))
+ responder.new(build)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/chat/responder/base.rb b/lib/gitlab/chat/responder/base.rb
new file mode 100644
index 00000000000..f1ad0e36793
--- /dev/null
+++ b/lib/gitlab/chat/responder/base.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Chat
+ module Responder
+ class Base
+ attr_reader :build
+
+ # build - The `Ci::Build` that was executed.
+ def initialize(build)
+ @build = build
+ end
+
+ def pipeline
+ build.pipeline
+ end
+
+ def project
+ pipeline.project
+ end
+
+ def success(*)
+ raise NotImplementedError, 'You must implement #success(output)'
+ end
+
+ def failure
+ raise NotImplementedError, 'You must implement #failure'
+ end
+
+ def send_response(output)
+ raise NotImplementedError, 'You must implement #send_response(output)'
+ end
+
+ def scheduled_output
+ raise NotImplementedError, 'You must implement #scheduled_output'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/chat/responder/slack.rb b/lib/gitlab/chat/responder/slack.rb
new file mode 100644
index 00000000000..0cf02c92a67
--- /dev/null
+++ b/lib/gitlab/chat/responder/slack.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Chat
+ module Responder
+ class Slack < Responder::Base
+ SUCCESS_COLOR = '#B3ED8E'
+ FAILURE_COLOR = '#FF5640'
+ RESPONSE_TYPE = :in_channel
+
+ # Slack breaks messages apart if they're around 4 KB in size. We use a
+ # slightly smaller limit here to account for user mentions.
+ MESSAGE_SIZE_LIMIT = 3.5.kilobytes
+
+ # Sends a response back to Slack
+ #
+ # output - The output to send back to Slack, as a Hash.
+ def send_response(output)
+ Gitlab::HTTP.post(
+ pipeline.chat_data.response_url,
+ {
+ headers: { Accept: 'application/json' },
+ body: output.to_json
+ }
+ )
+ end
+
+ # Sends the output for a build that completed successfully.
+ #
+ # output - The output produced by the chat command.
+ def success(output)
+ return if output.empty?
+
+ send_response(
+ text: message_text(limit_output(output)),
+ response_type: RESPONSE_TYPE
+ )
+ end
+
+ # Sends the output for a build that failed.
+ def failure
+ send_response(
+ text: message_text("<#{build_url}|Sorry, the build failed!>"),
+ response_type: RESPONSE_TYPE
+ )
+ end
+
+ # Returns the output to send back after a command has been scheduled.
+ def scheduled_output
+ # We return an empty message so that Slack still shows the input
+ # command, without polluting the channel with standard "The job has
+ # been scheduled" (or similar) responses.
+ { text: '' }
+ end
+
+ private
+
+ def limit_output(output)
+ if output.bytesize <= MESSAGE_SIZE_LIMIT
+ output
+ else
+ "<#{build_url}|The output is too large to be sent back directly!>"
+ end
+ end
+
+ def mention_user
+ "<@#{pipeline.chat_data.chat_name.chat_id}>"
+ end
+
+ def message_text(output)
+ "#{mention_user}: #{output}"
+ end
+
+ def build_url
+ ::Gitlab::Routing.url_helpers.project_build_url(project, build)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/base_checker.rb b/lib/gitlab/checks/base_checker.rb
index f8cda0382fe..09b17b5b76b 100644
--- a/lib/gitlab/checks/base_checker.rb
+++ b/lib/gitlab/checks/base_checker.rb
@@ -18,12 +18,16 @@ module Gitlab
private
+ def creation?
+ Gitlab::Git.blank_ref?(oldrev)
+ end
+
def deletion?
Gitlab::Git.blank_ref?(newrev)
end
def update?
- !Gitlab::Git.blank_ref?(oldrev) && !deletion?
+ !creation? && !deletion?
end
def updated_from_web?
@@ -33,6 +37,22 @@ module Gitlab
def tag_exists?
project.repository.tag_exists?(tag_name)
end
+
+ def validate_once(resource)
+ Gitlab::SafeRequestStore.fetch(cache_key_for_resource(resource)) do
+ yield(resource)
+
+ true
+ end
+ end
+
+ def cache_key_for_resource(resource)
+ "git_access:#{checker_cache_key}:#{resource.cache_key}"
+ end
+
+ def checker_cache_key
+ self.class.name.demodulize.underscore
+ end
end
end
end
diff --git a/lib/gitlab/checks/branch_check.rb b/lib/gitlab/checks/branch_check.rb
index d06b2df36f2..ad926739752 100644
--- a/lib/gitlab/checks/branch_check.rb
+++ b/lib/gitlab/checks/branch_check.rb
@@ -9,13 +9,17 @@ module Gitlab
non_master_delete_protected_branch: 'You are not allowed to delete protected branches from this project. Only a project maintainer or owner can delete a protected branch.',
non_web_delete_protected_branch: 'You can only delete protected branches using the web interface.',
merge_protected_branch: 'You are not allowed to merge code into protected branches on this project.',
- push_protected_branch: 'You are not allowed to push code to protected branches on this project.'
+ push_protected_branch: 'You are not allowed to push code to protected branches on this project.',
+ create_protected_branch: 'You are not allowed to create protected branches on this project.',
+ invalid_commit_create_protected_branch: 'You can only use an existing protected branch ref as the basis of a new protected branch.',
+ non_web_create_protected_branch: 'You can only create protected branches using the web interface and API.'
}.freeze
LOG_MESSAGES = {
delete_default_branch_check: "Checking if default branch is being deleted...",
protected_branch_checks: "Checking if you are force pushing to a protected branch...",
protected_branch_push_checks: "Checking if you are allowed to push to the protected branch...",
+ protected_branch_creation_checks: "Checking if you are allowed to create a protected branch...",
protected_branch_deletion_checks: "Checking if you are allowed to delete the protected branch..."
}.freeze
@@ -42,13 +46,33 @@ module Gitlab
end
end
- if deletion?
+ if project.empty_repo?
+ protected_branch_push_checks
+ elsif creation? && protected_branch_creation_enabled?
+ protected_branch_creation_checks
+ elsif deletion?
protected_branch_deletion_checks
else
protected_branch_push_checks
end
end
+ def protected_branch_creation_checks
+ logger.log_timed(LOG_MESSAGES[:protected_branch_creation_checks]) do
+ unless user_access.can_merge_to_branch?(branch_name)
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:create_protected_branch]
+ end
+
+ unless safe_commit_for_new_protected_branch?
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:invalid_commit_create_protected_branch]
+ end
+
+ unless updated_from_web?
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:non_web_create_protected_branch]
+ end
+ end
+ end
+
def protected_branch_deletion_checks
logger.log_timed(LOG_MESSAGES[:protected_branch_deletion_checks]) do
unless user_access.can_delete_branch?(branch_name)
@@ -98,6 +122,10 @@ module Gitlab
Gitlab::Routing.url_helpers.project_project_members_url(project)
end
+ def protected_branch_creation_enabled?
+ Feature.enabled?(:protected_branch_creation, project, default_enabled: true)
+ end
+
def matching_merge_request?
Checks::MatchingMergeRequest.new(newrev, branch_name, project).match?
end
@@ -105,6 +133,10 @@ module Gitlab
def forced_push?
Gitlab::Checks::ForcePush.force_push?(project, oldrev, newrev)
end
+
+ def safe_commit_for_new_protected_branch?
+ ProtectedBranch.any_protected?(project, project.repository.branch_names_contains_sha(newrev))
+ end
end
end
end
diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb
index 7778d3068cc..8a57a3a6d9a 100644
--- a/lib/gitlab/checks/change_access.rb
+++ b/lib/gitlab/checks/change_access.rb
@@ -10,7 +10,7 @@ module Gitlab
attr_reader(*ATTRIBUTES)
def initialize(
- change, user_access:, project:, skip_authorization: false,
+ change, user_access:, project:,
skip_lfs_integrity_check: false, protocol:, logger:
)
@oldrev, @newrev, @ref = change.values_at(:oldrev, :newrev, :ref)
@@ -18,7 +18,6 @@ module Gitlab
@tag_name = Gitlab::Git.tag_name(@ref)
@user_access = user_access
@project = project
- @skip_authorization = skip_authorization
@skip_lfs_integrity_check = skip_lfs_integrity_check
@protocol = protocol
@@ -27,8 +26,6 @@ module Gitlab
end
def exec
- return true if skip_authorization
-
ref_level_checks
# Check of commits should happen as the last step
# given they're expensive in terms of performance
diff --git a/lib/gitlab/checks/diff_check.rb b/lib/gitlab/checks/diff_check.rb
index 8ee345ab45a..ea0d8c85a66 100644
--- a/lib/gitlab/checks/diff_check.rb
+++ b/lib/gitlab/checks/diff_check.rb
@@ -11,16 +11,20 @@ module Gitlab
}.freeze
def validate!
- return if deletion? || newrev.nil?
+ return if deletion?
return unless should_run_diff_validations?
return if commits.empty?
- return unless uses_raw_delta_validations?
file_paths = []
- process_raw_deltas do |diff|
- file_paths << (diff.new_path || diff.old_path)
- validate_diff(diff)
+ process_commits do |commit|
+ validate_once(commit) do
+ commit.raw_deltas.each do |diff|
+ file_paths << (diff.new_path || diff.old_path)
+
+ validate_diff(diff)
+ end
+ end
end
validate_file_paths(file_paths)
@@ -28,17 +32,13 @@ module Gitlab
private
- def should_run_diff_validations?
- validate_lfs_file_locks?
- end
-
def validate_lfs_file_locks?
strong_memoize(:validate_lfs_file_locks) do
project.lfs_enabled? && project.any_lfs_file_locks?
end
end
- def uses_raw_delta_validations?
+ def should_run_diff_validations?
validations_for_diff.present? || path_validations.present?
end
@@ -59,16 +59,14 @@ module Gitlab
validate_lfs_file_locks? ? [lfs_file_locks_validation] : []
end
- def process_raw_deltas
+ def process_commits
logger.log_timed(LOG_MESSAGES[:diff_content_check]) do
# n+1: https://gitlab.com/gitlab-org/gitlab-ee/issues/3593
::Gitlab::GitalyClient.allow_n_plus_1_calls do
commits.each do |commit|
logger.check_timeout_reached
- commit.raw_deltas.each do |diff|
- yield(diff)
- end
+ yield(commit)
end
end
end
diff --git a/lib/gitlab/checks/lfs_check.rb b/lib/gitlab/checks/lfs_check.rb
index e42684e679a..cc6a14d2d9a 100644
--- a/lib/gitlab/checks/lfs_check.rb
+++ b/lib/gitlab/checks/lfs_check.rb
@@ -7,6 +7,7 @@ module Gitlab
ERROR_MESSAGE = 'LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".'.freeze
def validate!
+ return unless project.lfs_enabled?
return if skip_lfs_integrity_check
logger.log_timed(LOG_MESSAGE) do
diff --git a/lib/gitlab/checks/push_check.rb b/lib/gitlab/checks/push_check.rb
index f3a52f09868..91f8d0bdbc8 100644
--- a/lib/gitlab/checks/push_check.rb
+++ b/lib/gitlab/checks/push_check.rb
@@ -6,7 +6,7 @@ module Gitlab
def validate!
logger.log_timed("Checking if you are allowed to push...") do
unless can_push?
- raise GitAccess::UnauthorizedError, 'You are not allowed to push code to this project.'
+ raise GitAccess::UnauthorizedError, GitAccess::ERROR_MESSAGES[:push_code]
end
end
end
@@ -15,7 +15,7 @@ module Gitlab
def can_push?
user_access.can_do_action?(:push_code) ||
- user_access.can_push_to_branch?(branch_name)
+ project.branch_allows_collaboration?(user_access.user, branch_name)
end
end
end
diff --git a/lib/gitlab/ci/ansi2html.rb b/lib/gitlab/ci/ansi2html.rb
index 974b5ad6877..fba0de20ced 100644
--- a/lib/gitlab/ci/ansi2html.rb
+++ b/lib/gitlab/ci/ansi2html.rb
@@ -31,7 +31,7 @@ module Gitlab
end
class Converter
- def on_0(_) reset() end
+ def on_0(_) reset end
def on_1(_) enable(STYLE_SWITCHES[:bold]) end
@@ -177,7 +177,7 @@ module Gitlab
end
end
- close_open_tags()
+ close_open_tags
OpenStruct.new(
html: @out.force_encoding(Encoding.default_external),
@@ -194,7 +194,7 @@ module Gitlab
action = scanner[1]
timestamp = scanner[2]
section = scanner[3]
- line = scanner.matched()[0...-5] # strips \r\033[0K
+ line = scanner.matched[0...-5] # strips \r\033[0K
@out << %{<div class="hidden" data-action="#{action}" data-timestamp="#{timestamp}" data-section="#{section}">#{line}</div>}
end
@@ -209,10 +209,10 @@ module Gitlab
# sequence gets stripped (including stuff like "delete last line")
return unless indicator == '[' && terminator == 'm'
- close_open_tags()
+ close_open_tags
- if commands.empty?()
- reset()
+ if commands.empty?
+ reset
return
end
@@ -222,7 +222,7 @@ module Gitlab
end
def evaluate_command_stack(stack)
- return unless command = stack.shift()
+ return unless command = stack.shift
if self.respond_to?("on_#{command}", true)
self.__send__("on_#{command}", stack) # rubocop:disable GitlabSecurity/PublicSend
@@ -313,7 +313,7 @@ module Gitlab
def get_term_color_class(color_index, prefix)
color_name = COLOR[color_index]
- return nil if color_name.nil?
+ return if color_name.nil?
get_color_class(["term", prefix, color_name])
end
@@ -333,8 +333,8 @@ module Gitlab
return unless command_stack.length >= 2
return unless command_stack[0] == "5"
- command_stack.shift() # ignore the "5" command
- color_index = command_stack.shift().to_i
+ command_stack.shift # ignore the "5" command
+ color_index = command_stack.shift.to_i
return unless color_index >= 0
return unless color_index <= 255
diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb
index 08dac756cc1..d45a044686e 100644
--- a/lib/gitlab/ci/build/artifacts/metadata.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata.rb
@@ -103,7 +103,7 @@ module Gitlab
def read_string(gz)
string_size = read_uint32(gz)
- return nil unless string_size
+ return unless string_size
gz.read(string_size)
end
diff --git a/lib/gitlab/ci/build/artifacts/metadata/entry.rb b/lib/gitlab/ci/build/artifacts/metadata/entry.rb
index d0a80518ae8..80e69cdcc95 100644
--- a/lib/gitlab/ci/build/artifacts/metadata/entry.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata/entry.rb
@@ -44,7 +44,7 @@ module Gitlab
end
def parent
- return nil unless has_parent?
+ return unless has_parent?
self.class.new(@path.to_s.chomp(basename), @entries)
end
diff --git a/lib/gitlab/ci/build/policy/changes.rb b/lib/gitlab/ci/build/policy/changes.rb
index 1663c875426..9c705a1cd3e 100644
--- a/lib/gitlab/ci/build/policy/changes.rb
+++ b/lib/gitlab/ci/build/policy/changes.rb
@@ -10,7 +10,7 @@ module Gitlab
end
def satisfied_by?(pipeline, seed)
- return true unless pipeline.branch_updated?
+ return true if pipeline.modified_paths.nil?
pipeline.modified_paths.any? do |path|
@globs.any? do |glob|
diff --git a/lib/gitlab/ci/build/policy/refs.rb b/lib/gitlab/ci/build/policy/refs.rb
index 0e9bb5c94bb..df5f5ffc253 100644
--- a/lib/gitlab/ci/build/policy/refs.rb
+++ b/lib/gitlab/ci/build/policy/refs.rb
@@ -29,8 +29,8 @@ module Gitlab
def matches_pattern?(pattern, pipeline)
return true if pipeline.tag? && pattern == 'tags'
return true if pipeline.branch? && pattern == 'branches'
- return true if pipeline.source == pattern
- return true if pipeline.source&.pluralize == pattern
+ return true if sanitized_source_name(pipeline) == pattern
+ return true if sanitized_source_name(pipeline)&.pluralize == pattern
# patterns can be matched only when branch or tag is used
# the pattern matching does not work for merge requests pipelines
@@ -42,6 +42,10 @@ module Gitlab
end
end
end
+
+ def sanitized_source_name(pipeline)
+ @sanitized_source_name ||= pipeline&.source&.delete_suffix('_event')
+ end
end
end
end
diff --git a/lib/gitlab/ci/build/step.rb b/lib/gitlab/ci/build/step.rb
index d587c896712..7fcabc035ac 100644
--- a/lib/gitlab/ci/build/step.rb
+++ b/lib/gitlab/ci/build/step.rb
@@ -15,7 +15,6 @@ module Gitlab
def from_commands(job)
self.new(:script).tap do |step|
step.script = job.options[:before_script].to_a + job.options[:script].to_a
- step.script = job.commands.split("\n") if step.script.empty?
step.timeout = job.metadata_timeout
step.when = WHEN_ON_SUCCESS
end
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index 6333799a491..15643fa03ac 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -8,9 +8,9 @@ module Gitlab
class Config
ConfigError = Class.new(StandardError)
- def initialize(config, opts = {})
+ def initialize(config, project: nil, sha: nil, user: nil)
@config = Config::Extendable
- .new(build_config(config, opts))
+ .new(build_config(config, project: project, sha: sha, user: user))
.to_hash
@global = Entry::Global.new(@config)
@@ -70,20 +70,22 @@ module Gitlab
private
- def build_config(config, opts = {})
+ def build_config(config, project:, sha:, user:)
initial_config = Gitlab::Config::Loader::Yaml.new(config).load!
- project = opts.fetch(:project, nil)
if project
- process_external_files(initial_config, project, opts)
+ process_external_files(initial_config, project: project, sha: sha, user: user)
else
initial_config
end
end
- def process_external_files(config, project, opts)
- sha = opts.fetch(:sha) { project.repository.root_ref_sha }
- Config::External::Processor.new(config, project, sha).perform
+ def process_external_files(config, project:, sha:, user:)
+ Config::External::Processor.new(config,
+ project: project,
+ sha: sha || project.repository.root_ref_sha,
+ user: user,
+ expandset: Set.new).perform
end
end
end
diff --git a/lib/gitlab/ci/config/entry/global.rb b/lib/gitlab/ci/config/entry/global.rb
index 09ecb5fdb99..2b5a59c078e 100644
--- a/lib/gitlab/ci/config/entry/global.rb
+++ b/lib/gitlab/ci/config/entry/global.rb
@@ -17,6 +17,9 @@ module Gitlab
entry :image, Entry::Image,
description: 'Docker image that will be used to execute jobs.'
+ entry :include, Entry::Includes,
+ description: 'List of external YAML files to include.'
+
entry :services, Entry::Services,
description: 'Docker images that will be linked to the container.'
diff --git a/lib/gitlab/ci/config/entry/include.rb b/lib/gitlab/ci/config/entry/include.rb
new file mode 100644
index 00000000000..f2f3dd84eda
--- /dev/null
+++ b/lib/gitlab/ci/config/entry/include.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Entry
+ ##
+ # Entry that represents a single include.
+ #
+ class Include < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
+
+ ALLOWED_KEYS = %i[local file remote template].freeze
+
+ validations do
+ validates :config, hash_or_string: true
+ validates :config, allowed_keys: ALLOWED_KEYS
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/entry/includes.rb b/lib/gitlab/ci/config/entry/includes.rb
new file mode 100644
index 00000000000..82b2b1ccf4b
--- /dev/null
+++ b/lib/gitlab/ci/config/entry/includes.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Entry
+ ##
+ # Entry that represents a list of include.
+ #
+ class Includes < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
+
+ validations do
+ validates :config, type: Array
+ end
+
+ def self.aspects
+ super.append -> do
+ @config = Array.wrap(@config)
+
+ @config.each_with_index do |config, i|
+ @entries[i] = ::Gitlab::Config::Entry::Factory.new(Entry::Include)
+ .value(config || {})
+ .create!
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index 50942fbdb40..290c9591b98 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -16,13 +16,6 @@ module Gitlab
dependencies before_script after_script variables
environment coverage retry parallel extends].freeze
- DEFAULT_ONLY_POLICY = {
- refs: %w(branches tags)
- }.freeze
-
- DEFAULT_EXCEPT_POLICY = {
- }.freeze
-
validations do
validates :config, allowed_keys: ALLOWED_KEYS
validates :config, presence: true
@@ -73,7 +66,8 @@ module Gitlab
description: 'Services that will be used to execute this job.'
entry :only, Entry::Policy,
- description: 'Refs policy this job will be executed for.'
+ description: 'Refs policy this job will be executed for.',
+ default: Entry::Policy::DEFAULT_ONLY
entry :except, Entry::Policy,
description: 'Refs policy this job will be executed for.'
@@ -95,7 +89,7 @@ module Gitlab
helpers :before_script, :script, :stage, :type, :after_script,
:cache, :image, :services, :only, :except, :variables,
- :artifacts, :commands, :environment, :coverage, :retry,
+ :artifacts, :environment, :coverage, :retry,
:parallel
attributes :script, :tags, :allow_failure, :when, :dependencies,
@@ -121,10 +115,6 @@ module Gitlab
@config.merge(to_hash.compact)
end
- def commands
- (before_script_value.to_a + script_value.to_a).join("\n")
- end
-
def manual_action?
self.when == 'manual'
end
@@ -156,13 +146,12 @@ module Gitlab
{ name: name,
before_script: before_script_value,
script: script_value,
- commands: commands,
image: image_value,
services: services_value,
stage: stage_value,
cache: cache_value,
- only: DEFAULT_ONLY_POLICY.deep_merge(only_value.to_h),
- except: DEFAULT_EXCEPT_POLICY.deep_merge(except_value.to_h),
+ only: only_value,
+ except: except_value,
variables: variables_defined? ? variables_value : nil,
environment: environment_defined? ? environment_value : nil,
environment_name: environment_defined? ? environment_value[:name] : nil,
diff --git a/lib/gitlab/ci/config/entry/jobs.rb b/lib/gitlab/ci/config/entry/jobs.rb
index 82b72e40404..9845c4af655 100644
--- a/lib/gitlab/ci/config/entry/jobs.rb
+++ b/lib/gitlab/ci/config/entry/jobs.rb
@@ -28,11 +28,15 @@ module Gitlab
name.to_s.start_with?('.')
end
+ def node_type(name)
+ hidden?(name) ? Entry::Hidden : Entry::Job
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def compose!(deps = nil)
super do
@config.each do |name, config|
- node = hidden?(name) ? Entry::Hidden : Entry::Job
+ node = node_type(name)
factory = ::Gitlab::Config::Entry::Factory.new(node)
.value(config || {})
diff --git a/lib/gitlab/ci/config/entry/policy.rb b/lib/gitlab/ci/config/entry/policy.rb
index 998da1f6837..adc3660d950 100644
--- a/lib/gitlab/ci/config/entry/policy.rb
+++ b/lib/gitlab/ci/config/entry/policy.rb
@@ -11,6 +11,8 @@ module Gitlab
strategy :RefsPolicy, if: -> (config) { config.is_a?(Array) }
strategy :ComplexPolicy, if: -> (config) { config.is_a?(Hash) }
+ DEFAULT_ONLY = { refs: %w[branches tags] }.freeze
+
class RefsPolicy < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable
@@ -64,7 +66,8 @@ module Gitlab
end
end
- def self.default
+ def value
+ default.to_h.deep_merge(subject.value.to_h)
end
end
end
diff --git a/lib/gitlab/ci/config/entry/retry.rb b/lib/gitlab/ci/config/entry/retry.rb
index eaf8b38aa3c..e9cbcb31e21 100644
--- a/lib/gitlab/ci/config/entry/retry.rb
+++ b/lib/gitlab/ci/config/entry/retry.rb
@@ -82,9 +82,6 @@ module Gitlab
'retry config'
end
end
-
- def self.default
- end
end
end
end
diff --git a/lib/gitlab/ci/config/entry/variables.rb b/lib/gitlab/ci/config/entry/variables.rb
index 89d790ebfa6..c9d0c7cb568 100644
--- a/lib/gitlab/ci/config/entry/variables.rb
+++ b/lib/gitlab/ci/config/entry/variables.rb
@@ -14,7 +14,7 @@ module Gitlab
validates :config, variables: true
end
- def self.default
+ def self.default(**)
{}
end
diff --git a/lib/gitlab/ci/config/external/file/base.rb b/lib/gitlab/ci/config/external/file/base.rb
index ee4ea9bbb1d..2ffbb214a92 100644
--- a/lib/gitlab/ci/config/external/file/base.rb
+++ b/lib/gitlab/ci/config/external/file/base.rb
@@ -8,20 +8,26 @@ module Gitlab
class Base
include Gitlab::Utils::StrongMemoize
- attr_reader :location, :opts, :errors
+ attr_reader :location, :params, :context, :errors
YAML_WHITELIST_EXTENSION = /.+\.(yml|yaml)$/i.freeze
- def initialize(location, opts = {})
- @location = location
- @opts = opts
+ Context = Struct.new(:project, :sha, :user, :expandset)
+
+ def initialize(params, context)
+ @params = params
+ @context = context
@errors = []
validate!
end
+ def matching?
+ location.present?
+ end
+
def invalid_extension?
- !::File.basename(location).match(YAML_WHITELIST_EXTENSION)
+ location.nil? || !::File.basename(location).match?(YAML_WHITELIST_EXTENSION)
end
def valid?
@@ -37,13 +43,27 @@ module Gitlab
end
def to_hash
- @hash ||= Gitlab::Config::Loader::Yaml.new(content).load!
- rescue Gitlab::Config::Loader::FormatError
- nil
+ expanded_content_hash
end
protected
+ def expanded_content_hash
+ return unless content_hash
+
+ strong_memoize(:expanded_content_yaml) do
+ expand_includes(content_hash)
+ end
+ end
+
+ def content_hash
+ strong_memoize(:content_yaml) do
+ Gitlab::Config::Loader::Yaml.new(content).load!
+ end
+ rescue Gitlab::Config::Loader::FormatError
+ nil
+ end
+
def validate!
validate_location!
validate_content! if errors.none?
@@ -67,6 +87,14 @@ module Gitlab
errors.push("Included file `#{location}` does not have valid YAML syntax!")
end
end
+
+ def expand_includes(hash)
+ External::Processor.new(hash, **expand_context).perform
+ end
+
+ def expand_context
+ { project: nil, sha: nil, user: nil, expandset: context.expandset }
+ end
end
end
end
diff --git a/lib/gitlab/ci/config/external/file/local.rb b/lib/gitlab/ci/config/external/file/local.rb
index 2a256aff65c..229a06451e8 100644
--- a/lib/gitlab/ci/config/external/file/local.rb
+++ b/lib/gitlab/ci/config/external/file/local.rb
@@ -8,11 +8,8 @@ module Gitlab
class Local < Base
include Gitlab::Utils::StrongMemoize
- attr_reader :project, :sha
-
- def initialize(location, opts = {})
- @project = opts.fetch(:project)
- @sha = opts.fetch(:sha)
+ def initialize(params, context)
+ @location = params[:local]
super
end
@@ -32,7 +29,14 @@ module Gitlab
end
def fetch_local_content
- project.repository.blob_data_at(sha, location)
+ context.project.repository.blob_data_at(context.sha, location)
+ end
+
+ def expand_context
+ super.merge(
+ project: context.project,
+ sha: context.sha,
+ user: context.user)
end
end
end
diff --git a/lib/gitlab/ci/config/external/file/project.rb b/lib/gitlab/ci/config/external/file/project.rb
new file mode 100644
index 00000000000..b828f77835c
--- /dev/null
+++ b/lib/gitlab/ci/config/external/file/project.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module External
+ module File
+ class Project < Base
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :project_name, :ref_name
+
+ def initialize(params, context = {})
+ @location = params[:file]
+ @project_name = params[:project]
+ @ref_name = params[:ref] || 'HEAD'
+
+ super
+ end
+
+ def matching?
+ super && project_name.present?
+ end
+
+ def content
+ strong_memoize(:content) { fetch_local_content }
+ end
+
+ private
+
+ def validate_content!
+ if !can_access_local_content?
+ errors.push("Project `#{project_name}` not found or access denied!")
+ elsif sha.nil?
+ errors.push("Project `#{project_name}` reference `#{ref_name}` does not exist!")
+ elsif content.nil?
+ errors.push("Project `#{project_name}` file `#{location}` does not exist!")
+ elsif content.blank?
+ errors.push("Project `#{project_name}` file `#{location}` is empty!")
+ end
+ end
+
+ def project
+ strong_memoize(:project) do
+ ::Project.find_by_full_path(project_name)
+ end
+ end
+
+ def can_access_local_content?
+ Ability.allowed?(context.user, :download_code, project)
+ end
+
+ def fetch_local_content
+ return unless can_access_local_content?
+ return unless sha
+
+ project.repository.blob_data_at(sha, location)
+ rescue GRPC::NotFound, GRPC::Internal
+ nil
+ end
+
+ def sha
+ strong_memoize(:sha) do
+ project.commit(ref_name).try(:sha)
+ end
+ end
+
+ def expand_context
+ super.merge(
+ project: project,
+ sha: sha,
+ user: context.user)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/external/file/remote.rb b/lib/gitlab/ci/config/external/file/remote.rb
index 86fa5ad8800..567a86c47e5 100644
--- a/lib/gitlab/ci/config/external/file/remote.rb
+++ b/lib/gitlab/ci/config/external/file/remote.rb
@@ -8,6 +8,12 @@ module Gitlab
class Remote < Base
include Gitlab::Utils::StrongMemoize
+ def initialize(params, context)
+ @location = params[:remote]
+
+ super
+ end
+
def content
strong_memoize(:content) { fetch_remote_content }
end
diff --git a/lib/gitlab/ci/config/external/file/template.rb b/lib/gitlab/ci/config/external/file/template.rb
new file mode 100644
index 00000000000..54f4cf74c4d
--- /dev/null
+++ b/lib/gitlab/ci/config/external/file/template.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module External
+ module File
+ class Template < Base
+ attr_reader :location, :project
+
+ SUFFIX = '.gitlab-ci.yml'.freeze
+
+ def initialize(params, context)
+ @location = params[:template]
+
+ super
+ end
+
+ def content
+ strong_memoize(:content) { fetch_template_content }
+ end
+
+ private
+
+ def validate_location!
+ super
+
+ unless template_name_valid?
+ errors.push("Template file `#{location}` is not a valid location!")
+ end
+ end
+
+ def template_name
+ return unless template_name_valid?
+
+ location.first(-SUFFIX.length)
+ end
+
+ def template_name_valid?
+ location.to_s.end_with?(SUFFIX)
+ end
+
+ def fetch_template_content
+ Gitlab::Template::GitlabCiYmlTemplate.find(template_name, project)&.content
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/external/mapper.rb b/lib/gitlab/ci/config/external/mapper.rb
index def3563e505..aff5c5b9651 100644
--- a/lib/gitlab/ci/config/external/mapper.rb
+++ b/lib/gitlab/ci/config/external/mapper.rb
@@ -5,25 +5,93 @@ module Gitlab
class Config
module External
class Mapper
- def initialize(values, project, sha)
- @locations = Array(values.fetch(:include, []))
+ include Gitlab::Utils::StrongMemoize
+
+ MAX_INCLUDES = 50
+
+ FILE_CLASSES = [
+ External::File::Remote,
+ External::File::Template,
+ External::File::Local,
+ External::File::Project
+ ].freeze
+
+ Error = Class.new(StandardError)
+ AmbigiousSpecificationError = Class.new(Error)
+ DuplicateIncludesError = Class.new(Error)
+ TooManyIncludesError = Class.new(Error)
+
+ def initialize(values, project:, sha:, user:, expandset:)
+ raise Error, 'Expanded needs to be `Set`' unless expandset.is_a?(Set)
+
+ @locations = Array.wrap(values.fetch(:include, []))
@project = project
@sha = sha
+ @user = user
+ @expandset = expandset
end
def process
- locations.map { |location| build_external_file(location) }
+ return [] if locations.empty?
+
+ locations
+ .compact
+ .map(&method(:normalize_location))
+ .each(&method(:verify_duplicates!))
+ .map(&method(:select_first_matching))
end
private
- attr_reader :locations, :project, :sha
+ attr_reader :locations, :project, :sha, :user, :expandset
- def build_external_file(location)
+ # convert location if String to canonical form
+ def normalize_location(location)
+ if location.is_a?(String)
+ normalize_location_string(location)
+ else
+ location.deep_symbolize_keys
+ end
+ end
+
+ def normalize_location_string(location)
if ::Gitlab::UrlSanitizer.valid?(location)
- External::File::Remote.new(location)
+ { remote: location }
else
- External::File::Local.new(location, project: project, sha: sha)
+ { local: location }
+ end
+ end
+
+ def verify_duplicates!(location)
+ if expandset.count >= MAX_INCLUDES
+ raise TooManyIncludesError, "Maximum of #{MAX_INCLUDES} nested includes are allowed!"
+ end
+
+ # We scope location to context, as this allows us to properly support
+ # relative incldues, and similarly looking relative in another project
+ # does not trigger duplicate error
+ scoped_location = location.merge(
+ context_project: project,
+ context_sha: sha)
+
+ unless expandset.add?(scoped_location)
+ raise DuplicateIncludesError, "Include `#{location.to_json}` was already included!"
+ end
+ end
+
+ def select_first_matching(location)
+ matching = FILE_CLASSES.map do |file_class|
+ file_class.new(location, context)
+ end.select(&:matching?)
+
+ raise AmbigiousSpecificationError, "Include `#{location.to_json}` needs to match exactly one accessor!" unless matching.one?
+
+ matching.first
+ end
+
+ def context
+ strong_memoize(:context) do
+ External::File::Base::Context.new(project, sha, user, expandset)
end
end
end
diff --git a/lib/gitlab/ci/config/external/processor.rb b/lib/gitlab/ci/config/external/processor.rb
index eae0bdeb644..1dd2d42016a 100644
--- a/lib/gitlab/ci/config/external/processor.rb
+++ b/lib/gitlab/ci/config/external/processor.rb
@@ -7,10 +7,12 @@ module Gitlab
class Processor
IncludeError = Class.new(StandardError)
- def initialize(values, project, sha)
+ def initialize(values, project:, sha:, user:, expandset:)
@values = values
- @external_files = External::Mapper.new(values, project, sha).process
+ @external_files = External::Mapper.new(values, project: project, sha: sha, user: user, expandset: expandset).process
@content = {}
+ rescue External::Mapper::Error => e
+ raise IncludeError, e.message
end
def perform
diff --git a/lib/gitlab/ci/config/normalizer.rb b/lib/gitlab/ci/config/normalizer.rb
index b7743bd2090..191f5d09645 100644
--- a/lib/gitlab/ci/config/normalizer.rb
+++ b/lib/gitlab/ci/config/normalizer.rb
@@ -46,7 +46,8 @@ module Gitlab
parallelized_job_names = @parallelized_jobs.keys.map(&:to_s)
parallelized_config.each_with_object({}) do |(job_name, config), hash|
if config[:dependencies] && (intersection = config[:dependencies] & parallelized_job_names).any?
- deps = intersection.map { |dep| @parallelized_jobs[dep.to_sym].map(&:first) }.flatten
+ parallelized_deps = intersection.map { |dep| @parallelized_jobs[dep.to_sym].map(&:first) }.flatten
+ deps = config[:dependencies] - intersection + parallelized_deps
hash[job_name] = config.merge(dependencies: deps)
else
hash[job_name] = config
diff --git a/lib/gitlab/ci/cron_parser.rb b/lib/gitlab/ci/cron_parser.rb
index b1db9084662..94f4a4e36c9 100644
--- a/lib/gitlab/ci/cron_parser.rb
+++ b/lib/gitlab/ci/cron_parser.rb
@@ -35,7 +35,7 @@ module Gitlab
# NOTE:
# cron_timezone can only accept timezones listed in TZInfo::Timezone.
# Aliases of Timezones from ActiveSupport::TimeZone are NOT accepted,
- # because Rufus::Scheduler only supports TZInfo::Timezone.
+ # because Fugit::Cron only supports TZInfo::Timezone.
#
# For example, those codes have the same effect.
# Time.zone = 'Pacific Time (US & Canada)' (ActiveSupport::TimeZone)
@@ -47,10 +47,7 @@ module Gitlab
# If you want to know more, please take a look
# https://github.com/rails/rails/blob/master/activesupport/lib/active_support/values/time_zone.rb
def try_parse_cron(cron, cron_timezone)
- cron_line = Rufus::Scheduler.parse("#{cron} #{cron_timezone}")
- cron_line if cron_line.is_a?(Rufus::Scheduler::CronLine)
- rescue
- # noop
+ Fugit::Cron.parse("#{cron} #{cron_timezone}")
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/build.rb b/lib/gitlab/ci/pipeline/chain/build.rb
index d33d1edfe35..164a4634d84 100644
--- a/lib/gitlab/ci/pipeline/chain/build.rb
+++ b/lib/gitlab/ci/pipeline/chain/build.rb
@@ -12,12 +12,13 @@ module Gitlab
ref: @command.ref,
sha: @command.sha,
before_sha: @command.before_sha,
+ source_sha: @command.source_sha,
+ target_sha: @command.target_sha,
tag: @command.tag_exists?,
trigger_requests: Array(@command.trigger_request),
user: @command.current_user,
pipeline_schedule: @command.schedule,
merge_request: @command.merge_request,
- protected: @command.protected_ref?,
variables_attributes: Array(@command.variables_attributes)
)
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index 100b9521412..7b77e86feae 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -7,10 +7,11 @@ module Gitlab
module Chain
Command = Struct.new(
:source, :project, :current_user,
- :origin_ref, :checkout_sha, :after_sha, :before_sha,
+ :origin_ref, :checkout_sha, :after_sha, :before_sha, :source_sha, :target_sha,
:trigger_request, :schedule, :merge_request,
:ignore_skip_ci, :save_incompleted,
- :seeds_block, :variables_attributes
+ :seeds_block, :variables_attributes, :push_options,
+ :chat_data
) do
include Gitlab::Utils::StrongMemoize
@@ -54,7 +55,13 @@ module Gitlab
def protected_ref?
strong_memoize(:protected_ref) do
- project.protected_for?(ref)
+ project.protected_for?(origin_ref)
+ end
+ end
+
+ def ambiguous_ref?
+ strong_memoize(:ambiguous_ref) do
+ project.repository.ambiguous_ref?(origin_ref)
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/limit/activity.rb b/lib/gitlab/ci/pipeline/chain/limit/activity.rb
new file mode 100644
index 00000000000..fe7c8738cc0
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/limit/activity.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ module Limit
+ class Activity < Chain::Base
+ def perform!
+ # to be overriden in EE
+ end
+
+ def break?
+ false # to be overriden in EE
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/limit/size.rb b/lib/gitlab/ci/pipeline/chain/limit/size.rb
new file mode 100644
index 00000000000..b4d51437cd6
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/limit/size.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ module Limit
+ class Size < Chain::Base
+ def perform!
+ # to be overriden in EE
+ end
+
+ def break?
+ false # to be overriden in EE
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/populate.rb b/lib/gitlab/ci/pipeline/chain/populate.rb
index 633d3cd4f6b..0405292a25b 100644
--- a/lib/gitlab/ci/pipeline/chain/populate.rb
+++ b/lib/gitlab/ci/pipeline/chain/populate.rb
@@ -13,6 +13,10 @@ module Gitlab
# Allocate next IID. This operation must be outside of transactions of pipeline creations.
pipeline.ensure_project_iid!
+ # Protect the pipeline. This is assigned in Populate instead of
+ # Build to prevent erroring out on ambiguous refs.
+ pipeline.protected = @command.protected_ref?
+
##
# Populate pipeline with block argument of CreatePipelineService#execute.
#
diff --git a/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb b/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb
new file mode 100644
index 00000000000..1e09b417311
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class RemoveUnwantedChatJobs < Chain::Base
+ def perform!
+ return unless pipeline.config_processor && pipeline.chat?
+
+ # When scheduling a chat pipeline we only want to run the build
+ # that matches the chat command.
+ pipeline.config_processor.jobs.select! do |name, _|
+ name.to_s == command.chat_data[:command].to_s
+ end
+ end
+
+ def break?
+ false
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/skip.rb b/lib/gitlab/ci/pipeline/chain/skip.rb
index b9707d2f8f5..79bbcc1ed1e 100644
--- a/lib/gitlab/ci/pipeline/chain/skip.rb
+++ b/lib/gitlab/ci/pipeline/chain/skip.rb
@@ -8,6 +8,7 @@ module Gitlab
include ::Gitlab::Utils::StrongMemoize
SKIP_PATTERN = /\[(ci[ _-]skip|skip[ _-]ci)\]/i
+ SKIP_PUSH_OPTION = 'ci.skip'
def perform!
if skipped?
@@ -16,7 +17,7 @@ module Gitlab
end
def skipped?
- !@command.ignore_skip_ci && commit_message_skips_ci?
+ !@command.ignore_skip_ci && (commit_message_skips_ci? || push_option_skips_ci?)
end
def break?
@@ -32,6 +33,10 @@ module Gitlab
!!(@pipeline.git_commit_message =~ SKIP_PATTERN)
end
end
+
+ def push_option_skips_ci?
+ !!(@command.push_options&.include?(SKIP_PUSH_OPTION))
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/validate/repository.rb b/lib/gitlab/ci/pipeline/chain/validate/repository.rb
index d88851d8245..9c6c2bc8e25 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/repository.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/repository.rb
@@ -16,6 +16,10 @@ module Gitlab
unless @command.sha
return error('Commit not found')
end
+
+ if @command.ambiguous_ref?
+ return error('Ref is ambiguous')
+ end
end
def break?
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index ef738a93bfe..d8296940a04 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -38,9 +38,17 @@ module Gitlab
)
end
+ def bridge?
+ @attributes.to_h.dig(:options, :trigger).present?
+ end
+
def to_resource
strong_memoize(:resource) do
- ::Ci::Build.new(attributes)
+ if bridge?
+ ::Ci::Bridge.new(attributes)
+ else
+ ::Ci::Build.new(attributes)
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/seed/stage.rb b/lib/gitlab/ci/pipeline/seed/stage.rb
index 4775ff15581..9c15064756a 100644
--- a/lib/gitlab/ci/pipeline/seed/stage.rb
+++ b/lib/gitlab/ci/pipeline/seed/stage.rb
@@ -39,7 +39,13 @@ module Gitlab
def to_resource
strong_memoize(:stage) do
::Ci::Stage.new(attributes).tap do |stage|
- seeds.each { |seed| stage.builds << seed.to_resource }
+ seeds.each do |seed|
+ if seed.bridge?
+ stage.bridges << seed.to_resource
+ else
+ stage.builds << seed.to_resource
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/status/bridge/common.rb b/lib/gitlab/ci/status/bridge/common.rb
index c6cb620f7a0..4746195c618 100644
--- a/lib/gitlab/ci/status/bridge/common.rb
+++ b/lib/gitlab/ci/status/bridge/common.rb
@@ -18,7 +18,6 @@ module Gitlab
end
def details_path
- raise NotImplementedError
end
end
end
diff --git a/lib/gitlab/ci/status/external/common.rb b/lib/gitlab/ci/status/external/common.rb
index 4169f5b3210..cd772819293 100644
--- a/lib/gitlab/ci/status/external/common.rb
+++ b/lib/gitlab/ci/status/external/common.rb
@@ -6,7 +6,7 @@ module Gitlab
module External
module Common
def label
- subject.description
+ subject.description.presence || super
end
def has_details?
diff --git a/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml b/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml
new file mode 100644
index 00000000000..9c534b2b8e7
--- /dev/null
+++ b/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml
@@ -0,0 +1,121 @@
+# Read more about how to use this script on this blog post https://about.gitlab.com/2019/01/28/android-publishing-with-gitlab-and-fastlane/
+# You will also need to configure your build.gradle, Dockerfile, and fastlane configuration to make this work.
+# If you are looking for a simpler template that does not publish, see the Android template.
+
+stages:
+ - environment
+ - build
+ - test
+ - internal
+ - alpha
+ - beta
+ - production
+
+
+.updateContainerJob:
+ image: docker:stable
+ stage: environment
+ services:
+ - docker:dind
+ script:
+ - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
+ - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG || true
+ - docker build --cache-from $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG -t $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG .
+ - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+
+updateContainer:
+ extends: .updateContainerJob
+ only:
+ changes:
+ - Dockerfile
+
+ensureContainer:
+ extends: .updateContainerJob
+ allow_failure: true
+ before_script:
+ - "mkdir -p ~/.docker && echo '{\"experimental\": \"enabled\"}' > ~/.docker/config.json"
+ - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
+ # Skip update container `script` if the container already exists
+ # via https://gitlab.com/gitlab-org/gitlab-ce/issues/26866#note_97609397 -> https://stackoverflow.com/a/52077071/796832
+ - docker manifest inspect $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG > /dev/null && exit || true
+
+
+.build_job:
+ image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ stage: build
+ before_script:
+ # We store this binary file in a variable as hex with this command: `xxd -p android-app.jks`
+ # Then we convert the hex back to a binary file
+ - echo "$signing_jks_file_hex" | xxd -r -p - > android-signing-keystore.jks
+ - "export VERSION_CODE=$CI_PIPELINE_IID && echo $VERSION_CODE"
+ - "export VERSION_SHA=`echo ${CI_COMMIT_SHA:0:8}` && echo $VERSION_SHA"
+ after_script:
+ - rm -f android-signing-keystore.jks || true
+ artifacts:
+ paths:
+ - app/build/outputs
+
+buildDebug:
+ extends: .build_job
+ script:
+ - bundle exec fastlane buildDebug
+
+buildRelease:
+ extends: .build_job
+ script:
+ - bundle exec fastlane buildRelease
+ environment:
+ name: production
+
+testDebug:
+ image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ stage: test
+ dependencies:
+ - buildDebug
+ script:
+ - bundle exec fastlane test
+
+publishInternal:
+ image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ stage: internal
+ dependencies:
+ - buildRelease
+ when: manual
+ before_script:
+ - echo $google_play_service_account_api_key_json > ~/google_play_api_key.json
+ after_script:
+ - rm ~/google_play_api_key.json
+ script:
+ - bundle exec fastlane internal
+
+.promote_job:
+ image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ when: manual
+ dependencies: []
+ before_script:
+ - echo $google_play_service_account_api_key_json > ~/google_play_api_key.json
+ after_script:
+ - rm ~/google_play_api_key.json
+
+promoteAlpha:
+ extends: .promote_job
+ stage: alpha
+ script:
+ - bundle exec fastlane promote_internal_to_alpha
+
+promoteBeta:
+ extends: .promote_job
+ stage: beta
+ script:
+ - bundle exec fastlane promote_alpha_to_beta
+
+promoteProduction:
+ extends: .promote_job
+ stage: production
+ # We only allow production promotion on `master` because
+ # it has its own production scoped secret variables
+ only:
+ - master
+ script:
+ - bundle exec fastlane promote_beta_to_production
+ \ No newline at end of file
diff --git a/lib/gitlab/ci/templates/Android.gitlab-ci.yml b/lib/gitlab/ci/templates/Android.gitlab-ci.yml
index 6e138639b71..c169e3f7686 100644
--- a/lib/gitlab/ci/templates/Android.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Android.gitlab-ci.yml
@@ -1,4 +1,6 @@
# Read more about this script on this blog post https://about.gitlab.com/2018/10/24/setting-up-gitlab-ci-for-android-projects/, by Jason Lenny
+# If you are interested in using Android with FastLane for publishing take a look at the Android-Fastlane template.
+
image: openjdk:8-jdk
variables:
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index a9e361b0b32..6c99e20e7af 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -21,8 +21,8 @@
#
# In order to deploy, you must have a Kubernetes cluster configured either
# via a project integration, or via group/project variables.
-# AUTO_DEVOPS_DOMAIN must also be set as a variable at the group or project
-# level, or manually added below.
+# KUBE_INGRESS_BASE_DOMAIN must also be set on the cluster settings,
+# as a variable at the group or project level, or manually added below.
#
# Continuous deployment to production is enabled by default.
# If you want to deploy to staging first, set STAGING_ENABLED environment variable.
@@ -41,19 +41,22 @@
image: alpine:latest
variables:
- # AUTO_DEVOPS_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.
- # AUTO_DEVOPS_DOMAIN: domain.example.com
+ # KUBE_INGRESS_BASE_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.
+ # KUBE_INGRESS_BASE_DOMAIN: domain.example.com
POSTGRES_USER: user
POSTGRES_PASSWORD: testing-password
POSTGRES_ENABLED: "true"
POSTGRES_DB: $CI_ENVIRONMENT_SLUG
+ POSTGRES_VERSION: 9.6.2
- KUBERNETES_VERSION: 1.10.9
- HELM_VERSION: 2.11.0
+ KUBERNETES_VERSION: 1.11.7
+ HELM_VERSION: 2.12.3
DOCKER_DRIVER: overlay2
+ ROLLOUT_RESOURCE_TYPE: deployment
+
stages:
- build
- test
@@ -71,14 +74,14 @@ stages:
build:
stage: build
- image: docker:stable-git
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-build-image/master:stable"
services:
- - docker:stable-dind
+ - docker:stable-dind
script:
- - setup_docker
- - build
+ - /build/build.sh
only:
- branches
+ - tags
test:
services:
@@ -93,6 +96,7 @@ test:
- /bin/herokuish buildpack test
only:
- branches
+ - tags
except:
variables:
- $TEST_DISABLED
@@ -110,13 +114,14 @@ code_quality:
paths: [gl-code-quality-report.json]
only:
- branches
+ - tags
except:
variables:
- $CODE_QUALITY_DISABLED
license_management:
stage: test
- image:
+ image:
name: "registry.gitlab.com/gitlab-org/security-products/license-management:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable"
entrypoint: [""]
allow_failure: true
@@ -127,6 +132,7 @@ license_management:
only:
refs:
- branches
+ - tags
variables:
- $GITLAB_FEATURES =~ /\blicense_management\b/
except:
@@ -149,6 +155,7 @@ performance:
only:
refs:
- branches
+ - tags
kubernetes: active
except:
variables:
@@ -169,6 +176,7 @@ sast:
only:
refs:
- branches
+ - tags
variables:
- $GITLAB_FEATURES =~ /\bsast\b/
except:
@@ -185,10 +193,12 @@ dependency_scanning:
- setup_docker
- dependency_scanning
artifacts:
- paths: [gl-dependency-scanning-report.json]
+ reports:
+ dependency_scanning: gl-dependency-scanning-report.json
only:
refs:
- branches
+ - tags
variables:
- $GITLAB_FEATURES =~ /\bdependency_scanning\b/
except:
@@ -209,6 +219,7 @@ container_scanning:
only:
refs:
- branches
+ - tags
variables:
- $GITLAB_FEATURES =~ /\bcontainer_scanning\b/
except:
@@ -228,6 +239,7 @@ dast:
only:
refs:
- branches
+ - tags
kubernetes: active
variables:
- $GITLAB_FEATURES =~ /\bdast\b/
@@ -250,13 +262,14 @@ review:
- persist_environment_url
environment:
name: review/$CI_COMMIT_REF_NAME
- url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$AUTO_DEVOPS_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$KUBE_INGRESS_BASE_DOMAIN
on_stop: stop_review
artifacts:
paths: [environment_url.txt]
only:
refs:
- branches
+ - tags
kubernetes: active
except:
refs:
@@ -280,6 +293,7 @@ stop_review:
only:
refs:
- branches
+ - tags
kubernetes: active
except:
refs:
@@ -305,7 +319,7 @@ staging:
- deploy
environment:
name: staging
- url: http://$CI_PROJECT_PATH_SLUG-staging.$AUTO_DEVOPS_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_INGRESS_BASE_DOMAIN
only:
refs:
- master
@@ -329,7 +343,7 @@ canary:
- deploy canary
environment:
name: production
- url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
when: manual
only:
refs:
@@ -353,7 +367,7 @@ canary:
- persist_environment_url
environment:
name: production
- url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
artifacts:
paths: [environment_url.txt]
@@ -402,7 +416,7 @@ production_manual:
- persist_environment_url
environment:
name: production
- url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
artifacts:
paths: [environment_url.txt]
@@ -485,9 +499,13 @@ rollout 100%:
[[ "$TRACE" ]] && set -x
auto_database_url=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${CI_ENVIRONMENT_SLUG}-postgres:5432/${POSTGRES_DB}
export DATABASE_URL=${DATABASE_URL-$auto_database_url}
- export CI_APPLICATION_REPOSITORY=$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
- export CI_APPLICATION_TAG=$CI_COMMIT_SHA
- export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID}
+ if [[ -z "$CI_COMMIT_TAG" ]]; then
+ export CI_APPLICATION_REPOSITORY=$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
+ export CI_APPLICATION_TAG=$CI_COMMIT_SHA
+ else
+ export CI_APPLICATION_REPOSITORY=$CI_REGISTRY_IMAGE
+ export CI_APPLICATION_TAG=$CI_COMMIT_TAG
+ fi
export TILLER_NAMESPACE=$KUBE_NAMESPACE
# Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable" for Security Products
export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
@@ -595,10 +613,55 @@ rollout 100%:
fi
}
+ # Extracts variables prefixed with K8S_SECRET_
+ # and creates a Kubernetes secret.
+ #
+ # e.g. If we have the following environment variables:
+ # K8S_SECRET_A=value1
+ # K8S_SECRET_B=multi\ word\ value
+ #
+ # Then we will create a secret with the following key-value pairs:
+ # data:
+ # A: dmFsdWUxCg==
+ # B: bXVsdGkgd29yZCB2YWx1ZQo=
+ function create_application_secret() {
+ track="${1-stable}"
+ export APPLICATION_SECRET_NAME=$(application_secret_name "$track")
+
+ env | sed -n "s/^K8S_SECRET_\(.*\)$/\1/p" > k8s_prefixed_variables
+
+ kubectl create secret \
+ -n "$KUBE_NAMESPACE" generic "$APPLICATION_SECRET_NAME" \
+ --from-env-file k8s_prefixed_variables -o yaml --dry-run |
+ kubectl replace -n "$KUBE_NAMESPACE" --force -f -
+
+ export APPLICATION_SECRET_CHECKSUM=$(cat k8s_prefixed_variables | sha256sum | cut -d ' ' -f 1)
+
+ rm k8s_prefixed_variables
+ }
+
+ function deploy_name() {
+ name="$CI_ENVIRONMENT_SLUG"
+ track="${1-stable}"
+
+ if [[ "$track" != "stable" ]]; then
+ name="$name-$track"
+ fi
+
+ echo $name
+ }
+
+ function application_secret_name() {
+ track="${1-stable}"
+ name=$(deploy_name "$track")
+
+ echo "${name}-secret"
+ }
+
function deploy() {
track="${1-stable}"
percentage="${2:-100}"
- name="$CI_ENVIRONMENT_SLUG"
+ name=$(deploy_name "$track")
replicas="1"
service_enabled="true"
@@ -607,7 +670,6 @@ rollout 100%:
# if track is different than stable,
# re-use all attached resources
if [[ "$track" != "stable" ]]; then
- name="$name-$track"
service_enabled="false"
postgres_enabled="false"
fi
@@ -620,6 +682,16 @@ rollout 100%:
secret_name=''
fi
+ create_application_secret "$track"
+
+ env_slug=$(echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]')
+ eval env_ADDITIONAL_HOSTS=\$${env_slug}_ADDITIONAL_HOSTS
+ if [ -n "$env_ADDITIONAL_HOSTS" ]; then
+ additional_hosts="{$env_ADDITIONAL_HOSTS}"
+ elif [ -n "$ADDITIONAL_HOSTS" ]; then
+ additional_hosts="{$ADDITIONAL_HOSTS}"
+ fi
+
if [[ -n "$DB_INITIALIZE" && -z "$(helm ls -q "^$name$")" ]]; then
echo "Deploying first release with database initialization..."
helm upgrade --install \
@@ -632,13 +704,18 @@ rollout 100%:
--set image.secrets[0].name="$secret_name" \
--set application.track="$track" \
--set application.database_url="$DATABASE_URL" \
+ --set application.secretName="$APPLICATION_SECRET_NAME" \
+ --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
+ --set service.commonName="le.$KUBE_INGRESS_BASE_DOMAIN" \
--set service.url="$CI_ENVIRONMENT_URL" \
+ --set service.additionalHosts="$additional_hosts" \
--set replicaCount="$replicas" \
--set postgresql.enabled="$postgres_enabled" \
--set postgresql.nameOverride="postgres" \
--set postgresql.postgresUser="$POSTGRES_USER" \
--set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
--set postgresql.postgresDatabase="$POSTGRES_DB" \
+ --set postgresql.imageTag="$POSTGRES_VERSION" \
--set application.initializeCommand="$DB_INITIALIZE" \
--namespace="$KUBE_NAMESPACE" \
"$name" \
@@ -664,7 +741,11 @@ rollout 100%:
--set image.secrets[0].name="$secret_name" \
--set application.track="$track" \
--set application.database_url="$DATABASE_URL" \
+ --set application.secretName="$APPLICATION_SECRET_NAME" \
+ --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
+ --set service.commonName="le.$KUBE_INGRESS_BASE_DOMAIN" \
--set service.url="$CI_ENVIRONMENT_URL" \
+ --set service.additionalHosts="$additional_hosts" \
--set replicaCount="$replicas" \
--set postgresql.enabled="$postgres_enabled" \
--set postgresql.nameOverride="postgres" \
@@ -677,17 +758,13 @@ rollout 100%:
chart/
fi
- kubectl rollout status -n "$KUBE_NAMESPACE" -w "deployment/$name"
+ kubectl rollout status -n "$KUBE_NAMESPACE" -w "$ROLLOUT_RESOURCE_TYPE/$name"
}
function scale() {
track="${1-stable}"
percentage="${2-100}"
- name="$CI_ENVIRONMENT_SLUG"
-
- if [[ "$track" != "stable" ]]; then
- name="$name-$track"
- fi
+ name=$(deploy_name "$track")
replicas=$(get_replicas "$track" "$percentage")
@@ -748,7 +825,7 @@ rollout 100%:
fi
helm init --client-only
- helm repo add gitlab https://charts.gitlab.io
+ helm repo add gitlab ${AUTO_DEVOPS_CHART_REPOSITORY:-https://charts.gitlab.io}
if [[ ! -d "$auto_chart" ]]; then
helm fetch ${auto_chart} --untar
fi
@@ -764,59 +841,28 @@ rollout 100%:
kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
}
- function check_kube_domain() {
- if [ -z ${AUTO_DEVOPS_DOMAIN+x} ]; then
- echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
- echo "You can do it in Auto DevOps project settings or defining a variable at group or project level"
- echo "You can also manually add it in .gitlab-ci.yml"
- false
- else
- true
+
+ # Function to ensure backwards compatibility with AUTO_DEVOPS_DOMAIN
+ function ensure_kube_ingress_base_domain() {
+ if [ -z ${KUBE_INGRESS_BASE_DOMAIN+x} ] && [ -n "$AUTO_DEVOPS_DOMAIN" ] ; then
+ export KUBE_INGRESS_BASE_DOMAIN=$AUTO_DEVOPS_DOMAIN
fi
}
- function build() {
- registry_login
+ function check_kube_domain() {
+ ensure_kube_ingress_base_domain
- if [[ -f Dockerfile ]]; then
- echo "Building Dockerfile-based application..."
- docker build \
- --build-arg HTTP_PROXY="$HTTP_PROXY" \
- --build-arg http_proxy="$http_proxy" \
- --build-arg HTTPS_PROXY="$HTTPS_PROXY" \
- --build-arg https_proxy="$https_proxy" \
- --build-arg FTP_PROXY="$FTP_PROXY" \
- --build-arg ftp_proxy="$ftp_proxy" \
- --build-arg NO_PROXY="$NO_PROXY" \
- --build-arg no_proxy="$no_proxy" \
- -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" .
+ if [ -z ${KUBE_INGRESS_BASE_DOMAIN+x} ]; then
+ echo "In order to deploy or use Review Apps,"
+ echo "AUTO_DEVOPS_DOMAIN or KUBE_INGRESS_BASE_DOMAIN variables must be set"
+ echo "From 11.8, you can set KUBE_INGRESS_BASE_DOMAIN in cluster settings"
+ echo "or by defining a variable at group or project level."
+ echo "You can also manually add it in .gitlab-ci.yml"
+ echo "AUTO_DEVOPS_DOMAIN support will be dropped on 12.0"
+ false
else
- echo "Building Heroku-based application using gliderlabs/herokuish docker image..."
- docker run -i \
- -e BUILDPACK_URL \
- -e HTTP_PROXY \
- -e http_proxy \
- -e HTTPS_PROXY \
- -e https_proxy \
- -e FTP_PROXY \
- -e ftp_proxy \
- -e NO_PROXY \
- -e no_proxy \
- --name="$CI_CONTAINER_NAME" -v "$(pwd):/tmp/app:ro" gliderlabs/herokuish /bin/herokuish buildpack build
- docker commit "$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
- docker rm "$CI_CONTAINER_NAME" >/dev/null
- echo ""
-
- echo "Configuring $CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG docker image..."
- docker create --expose 5000 --env PORT=5000 --name="$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" /bin/herokuish procfile start web
- docker commit "$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
- docker rm "$CI_CONTAINER_NAME" >/dev/null
- echo ""
+ true
fi
-
- echo "Pushing to GitLab Container Registry..."
- docker push "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
- echo ""
}
function initialize_tiller() {
@@ -881,15 +927,14 @@ rollout 100%:
function delete() {
track="${1-stable}"
- name="$CI_ENVIRONMENT_SLUG"
-
- if [[ "$track" != "stable" ]]; then
- name="$name-$track"
- fi
+ name=$(deploy_name "$track")
if [[ -n "$(helm ls -q "^$name$")" ]]; then
helm delete --purge "$name"
fi
+
+ secret_name=$(application_secret_name "$track")
+ kubectl delete secret --ignore-not-found -n "$KUBE_NAMESPACE" "$secret_name"
}
before_script:
diff --git a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
index 93cb31f48c0..0d12cbc6460 100644
--- a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
@@ -24,7 +24,6 @@ before_script:
- ruby -v # Print out ruby version for debugging
# Uncomment next line if your rails app needs a JS runtime:
# - apt-get update -q && apt-get install nodejs -yqq
- - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image
- bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
# Optional - Delete if not using `rubocop`
diff --git a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
new file mode 100644
index 00000000000..805df26b957
--- /dev/null
+++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
@@ -0,0 +1,44 @@
+# Read more about this feature here: https://docs.gitlab.com/ee/user/project/merge_requests/dependency_scanning.html
+#
+# Configure the scanning tool through the environment variables.
+# List of the variables: https://gitlab.com/gitlab-org/security-products/dependency-scanning#settings
+# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+
+stages:
+ - test
+
+dependency_scanning:
+ stage: test
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - export DS_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')}
+ - |
+ docker run \
+ --env DS_ANALYZER_IMAGES \
+ --env DS_ANALYZER_IMAGE_PREFIX \
+ --env DS_ANALYZER_IMAGE_TAG \
+ --env DS_DEFAULT_ANALYZERS \
+ --env DEP_SCAN_DISABLE_REMOTE_CHECKS \
+ --env DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
+ --env DS_PULL_ANALYZER_IMAGE_TIMEOUT \
+ --env DS_RUN_ANALYZER_TIMEOUT \
+ --volume "$PWD:/code" \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
+ "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$DS_VERSION" /code
+ artifacts:
+ reports:
+ dependency_scanning: gl-dependency-scanning-report.json
+ dependencies: []
+ only:
+ refs:
+ - branches
+ variables:
+ - $GITLAB_FEATURES =~ /\bdependency_scanning\b/
+ except:
+ variables:
+ - $DEPENDENCY_SCANNING_DISABLED
diff --git a/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml b/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml
new file mode 100644
index 00000000000..4f3d08d98fe
--- /dev/null
+++ b/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml
@@ -0,0 +1,41 @@
+# GitLab Serverless template
+
+image: alpine:latest
+
+stages:
+ - build
+ - deploy
+
+.serverless:build:image:
+ variables:
+ DOCKERFILE: "Dockerfile"
+ stage: build
+ image:
+ name: gcr.io/kaniko-project/executor:debug
+ entrypoint: [""]
+ only:
+ refs:
+ - master
+ script:
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
+ - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/$DOCKERFILE --destination $CI_REGISTRY_IMAGE
+
+.serverless:deploy:image:
+ stage: deploy
+ image: gcr.io/triggermesh/tm@sha256:e3ee74db94d215bd297738d93577481f3e4db38013326c90d57f873df7ab41d5
+ only:
+ refs:
+ - master
+ environment: development
+ script:
+ - echo "$CI_REGISTRY_IMAGE"
+ - tm -n "$KUBE_NAMESPACE" --config "$KUBECONFIG" deploy service "$CI_PROJECT_NAME" --from-image "$CI_REGISTRY_IMAGE" --wait
+
+.serverless:deploy:functions:
+ stage: deploy
+ environment: development
+ image: gcr.io/triggermesh/tm:v0.0.9
+ script:
+ - tm -n "$KUBE_NAMESPACE" set registry-auth gitlab-registry --registry "$CI_REGISTRY" --username "$CI_REGISTRY_USER" --password "$CI_JOB_TOKEN" --push
+ - tm -n "$KUBE_NAMESPACE" set registry-auth gitlab-registry --registry "$CI_REGISTRY" --username "$CI_DEPLOY_USER" --password "$CI_DEPLOY_PASSWORD" --pull
+ - tm -n "$KUBE_NAMESPACE" deploy --wait
diff --git a/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml b/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml
index fc3d4ecdbba..25a32ba0f74 100644
--- a/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml
@@ -57,6 +57,7 @@ test_job:
script:
- '& "$env:NUNIT_PATH" ".\$env:TEST_FOLDER\Tests.dll"' # running NUnit tests
artifacts:
+ when: always # save test results even when the task fails
expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
paths:
- '.\TestResult.xml' # saving NUnit results to copy to deploy folder
diff --git a/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml b/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
new file mode 100644
index 00000000000..245e6bec60a
--- /dev/null
+++ b/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
@@ -0,0 +1,28 @@
+# This is a very simple template that mainly relies on FastLane to build and distribute your app.
+# Read more about how to use this template on the blog post https://about.gitlab.com/2019/03/06/ios-publishing-with-gitlab-and-fastlane/
+# You will also need fastlane and signing configuration for this to work, along with a MacOS runner.
+# These details are provided in the blog post.
+
+# Note that when you're using the shell executor for MacOS builds, the
+# build and tests run as the identity of the runner logged in user, directly on
+# the build host. This is less secure than using container executors, so please
+# take a look at our security implications documentation at
+# https://docs.gitlab.com/runner/security/#usage-of-shell-executor for additional
+# detail on what to keep in mind in this scenario.
+
+stages:
+ - build
+
+variables:
+ LC_ALL: "en_US.UTF-8"
+ LANG: "en_US.UTF-8"
+ GIT_STRATEGY: clone
+
+build:
+ stage: build
+ script:
+ - bundle install
+ - bundle exec fastlane build
+ artifacts:
+ paths:
+ - ./*.ipa
diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb
index 0f23b95ba15..e61fb50a303 100644
--- a/lib/gitlab/ci/trace/stream.rb
+++ b/lib/gitlab/ci/trace/stream.rb
@@ -46,7 +46,7 @@ module Gitlab
stream.seek(offset, IO::SEEK_SET)
stream.write(data)
stream.truncate(offset + data.bytesize)
- stream.flush()
+ stream.flush
end
def set(data)
diff --git a/lib/gitlab/ci/variables/collection.rb b/lib/gitlab/ci/variables/collection.rb
index a7b4e0348c2..f7bbb58df7e 100644
--- a/lib/gitlab/ci/variables/collection.rb
+++ b/lib/gitlab/ci/variables/collection.rb
@@ -17,6 +17,8 @@ module Gitlab
end
def concat(resources)
+ return self if resources.nil?
+
tap { resources.each { |variable| self.append(variable) } }
end
diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb
index e3e4e62cc02..833aa75adb5 100644
--- a/lib/gitlab/ci/variables/collection/item.rb
+++ b/lib/gitlab/ci/variables/collection/item.rb
@@ -5,12 +5,12 @@ module Gitlab
module Variables
class Collection
class Item
- def initialize(key:, value:, public: true, file: false)
+ def initialize(key:, value:, public: true, file: false, masked: false)
raise ArgumentError, "`#{key}` must be of type String or nil value, while it was: #{value.class}" unless
value.is_a?(String) || value.nil?
@variable = {
- key: key, value: value, public: public, file: file
+ key: key, value: value, public: public, file: file, masked: masked
}
end
@@ -27,9 +27,13 @@ module Gitlab
# don't expose `file` attribute at all (stems from what the runner
# expects).
#
+ # If the `variable_masking` feature is enabled we expose the `masked`
+ # attribute, otherwise it's not exposed.
+ #
def to_runner_variable
@variable.reject do |hash_key, hash_value|
- hash_key == :file && hash_value == false
+ (hash_key == :file && hash_value == false) ||
+ (hash_key == :masked && !Feature.enabled?(:variable_masking))
end
end
diff --git a/lib/gitlab/ci/yaml_processor.rb b/lib/gitlab/ci/yaml_processor.rb
index 172926b8ab0..07ba6f83d47 100644
--- a/lib/gitlab/ci/yaml_processor.rb
+++ b/lib/gitlab/ci/yaml_processor.rb
@@ -10,7 +10,7 @@ module Gitlab
attr_reader :cache, :stages, :jobs
def initialize(config, opts = {})
- @ci_config = Gitlab::Ci::Config.new(config, opts)
+ @ci_config = Gitlab::Ci::Config.new(config, **opts)
@config = @ci_config.to_hash
unless @ci_config.valid?
@@ -33,8 +33,7 @@ module Gitlab
{ stage_idx: @stages.index(job[:stage]),
stage: job[:stage],
- commands: job[:commands],
- tag_list: job[:tags] || [],
+ tag_list: job[:tags],
name: job[:name].to_s,
allow_failure: job[:ignore],
when: job[:when] || 'on_success',
@@ -54,8 +53,9 @@ module Gitlab
retry: job[:retry],
parallel: job[:parallel],
instance: job[:instance],
- start_in: job[:start_in]
- }.compact }
+ start_in: job[:start_in],
+ trigger: job[:trigger]
+ }.compact }.compact
end
def stage_builds_attributes(stage)
diff --git a/lib/gitlab/cleanup/remote_uploads.rb b/lib/gitlab/cleanup/remote_uploads.rb
index eba1faacc3a..03298d960a4 100644
--- a/lib/gitlab/cleanup/remote_uploads.rb
+++ b/lib/gitlab/cleanup/remote_uploads.rb
@@ -67,7 +67,7 @@ module Gitlab
end
def remote_directory
- connection.directories.get(configuration['remote_directory'])
+ connection.directories.new(key: configuration['remote_directory'])
end
def connection
diff --git a/lib/gitlab/config/entry/configurable.rb b/lib/gitlab/config/entry/configurable.rb
index afdb60b2cd5..37ba16dba25 100644
--- a/lib/gitlab/config/entry/configurable.rb
+++ b/lib/gitlab/config/entry/configurable.rb
@@ -56,6 +56,7 @@ module Gitlab
def entry(key, entry, metadata)
factory = ::Gitlab::Config::Entry::Factory.new(entry)
.with(description: metadata[:description])
+ .with(default: metadata[:default])
(@nodes ||= {}).merge!(key.to_sym => factory)
end
diff --git a/lib/gitlab/config/entry/factory.rb b/lib/gitlab/config/entry/factory.rb
index 30d43c9f9a1..79f9ff32514 100644
--- a/lib/gitlab/config/entry/factory.rb
+++ b/lib/gitlab/config/entry/factory.rb
@@ -12,7 +12,7 @@ module Gitlab
def initialize(entry)
@entry = entry
@metadata = {}
- @attributes = {}
+ @attributes = { default: entry.default }
end
def value(value)
@@ -21,12 +21,12 @@ module Gitlab
end
def metadata(metadata)
- @metadata.merge!(metadata)
+ @metadata.merge!(metadata.compact)
self
end
def with(attributes)
- @attributes.merge!(attributes)
+ @attributes.merge!(attributes.compact)
self
end
@@ -38,9 +38,7 @@ module Gitlab
# See issue #18775.
#
if @value.nil?
- Entry::Unspecified.new(
- fabricate_unspecified
- )
+ Entry::Unspecified.new(fabricate_unspecified)
else
fabricate(@entry, @value)
end
@@ -53,10 +51,12 @@ module Gitlab
# If entry has a default value we fabricate concrete node
# with default value.
#
- if @entry.default.nil?
+ default = @attributes.fetch(:default)
+
+ if default.nil?
fabricate(Entry::Undefined)
else
- fabricate(@entry, @entry.default)
+ fabricate(@entry, default)
end
end
@@ -64,6 +64,7 @@ module Gitlab
entry.new(value, @metadata).tap do |node|
node.key = @attributes[:key]
node.parent = @attributes[:parent]
+ node.default = @attributes[:default]
node.description = @attributes[:description]
end
end
diff --git a/lib/gitlab/config/entry/node.rb b/lib/gitlab/config/entry/node.rb
index 30357b2c95b..9999ab4ff95 100644
--- a/lib/gitlab/config/entry/node.rb
+++ b/lib/gitlab/config/entry/node.rb
@@ -10,7 +10,7 @@ module Gitlab
InvalidError = Class.new(StandardError)
attr_reader :config, :metadata
- attr_accessor :key, :parent, :description
+ attr_accessor :key, :parent, :default, :description
def initialize(config, **metadata)
@config = config
@@ -85,7 +85,7 @@ module Gitlab
"#<#{self.class.name} #{unspecified}{#{key}: #{val.inspect}}>"
end
- def self.default
+ def self.default(**)
end
def self.aspects
diff --git a/lib/gitlab/config/entry/simplifiable.rb b/lib/gitlab/config/entry/simplifiable.rb
index 3e148fe2e91..5fbf7565e2a 100644
--- a/lib/gitlab/config/entry/simplifiable.rb
+++ b/lib/gitlab/config/entry/simplifiable.rb
@@ -6,6 +6,8 @@ module Gitlab
class Simplifiable < SimpleDelegator
EntryStrategy = Struct.new(:name, :condition)
+ attr_reader :subject
+
def initialize(config, **metadata)
unless self.class.const_defined?(:UnknownStrategy)
raise ArgumentError, 'UndefinedStrategy not available!'
@@ -17,7 +19,7 @@ module Gitlab
entry = self.class.entry_class(strategy)
- super(entry.new(config, metadata))
+ super(@subject = entry.new(config, metadata))
end
def self.strategy(name, **opts)
@@ -37,6 +39,9 @@ module Gitlab
self::UnknownStrategy
end
end
+
+ def self.default
+ end
end
end
end
diff --git a/lib/gitlab/content_disposition.rb b/lib/gitlab/content_disposition.rb
new file mode 100644
index 00000000000..32207514ce5
--- /dev/null
+++ b/lib/gitlab/content_disposition.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+# This ports ActionDispatch::Http::ContentDisposition (https://github.com/rails/rails/pull/33829,
+# which will be available in Rails 6.
+module Gitlab
+ class ContentDisposition # :nodoc:
+ # Make sure we remove this patch starting with Rails 6.0.
+ if Rails.version.start_with?('6.0')
+ raise <<~MSG
+ Please remove this file and use `ActionDispatch::Http::ContentDisposition` instead.
+ MSG
+ end
+
+ def self.format(disposition:, filename:)
+ new(disposition: disposition, filename: filename).to_s
+ end
+
+ attr_reader :disposition, :filename
+
+ def initialize(disposition:, filename:)
+ @disposition = disposition
+ @filename = filename
+ end
+
+ # rubocop:disable Style/VariableInterpolation
+ TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/
+
+ def ascii_filename
+ 'filename="' + percent_escape(::I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"'
+ end
+
+ RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/
+ # rubocop:enable Style/VariableInterpolation
+
+ def utf8_filename
+ "filename*=UTF-8''" + percent_escape(filename, RFC_5987_ESCAPED_CHAR)
+ end
+
+ def to_s
+ if filename
+ "#{disposition}; #{ascii_filename}; #{utf8_filename}"
+ else
+ "#{disposition}"
+ end
+ end
+
+ private
+
+ def percent_escape(string, pattern)
+ string.gsub(pattern) do |char|
+ char.bytes.map { |byte| "%%%02X" % byte }.join
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb
index 5ed6427072a..f7d046600e8 100644
--- a/lib/gitlab/contributions_calendar.rb
+++ b/lib/gitlab/contributions_calendar.rb
@@ -49,6 +49,7 @@ module Gitlab
Event.contributions.where(author_id: contributor.id)
.where(created_at: date.beginning_of_day..date.end_of_day)
.where(project_id: projects)
+ .with_associations
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 477f9101e98..552aad83dd4 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -7,10 +7,6 @@ module Gitlab
Gitlab::SafeRequestStore.fetch(:current_application_settings) { ensure_application_settings! }
end
- def fake_application_settings(attributes = {})
- Gitlab::FakeApplicationSettings.new(::ApplicationSetting.defaults.merge(attributes || {}))
- end
-
def clear_in_memory_application_settings!
@in_memory_application_settings = nil
end
@@ -50,28 +46,21 @@ module Gitlab
# and other callers from failing, use any loaded settings and return
# defaults for missing columns.
if ActiveRecord::Migrator.needs_migration?
- return fake_application_settings(current_settings&.attributes)
- end
-
- return current_settings if current_settings.present?
-
- with_fallback_to_fake_application_settings do
- ::ApplicationSetting.create_from_defaults || in_memory_application_settings
+ db_attributes = current_settings&.attributes || {}
+ ::ApplicationSetting.build_from_defaults(db_attributes)
+ elsif current_settings.present?
+ current_settings
+ else
+ ::ApplicationSetting.create_from_defaults
end
end
- def in_memory_application_settings
- with_fallback_to_fake_application_settings do
- @in_memory_application_settings ||= ::ApplicationSetting.build_from_defaults
- end
+ def fake_application_settings(attributes = {})
+ Gitlab::FakeApplicationSettings.new(::ApplicationSetting.defaults.merge(attributes || {}))
end
- def with_fallback_to_fake_application_settings(&block)
- yield
- rescue
- # In case the application_settings table is not created yet, or if a new
- # ApplicationSetting column is not yet migrated we fallback to a simple OpenStruct
- fake_application_settings
+ def in_memory_application_settings
+ @in_memory_application_settings ||= ::ApplicationSetting.build_from_defaults
end
def connect_to_db?
diff --git a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
index db8ac3becea..aeca9d00156 100644
--- a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
@@ -40,11 +40,11 @@ module Gitlab
end
def first_time_reference_commit(event)
- return nil unless event && merge_request_diff_commits
+ return unless event && merge_request_diff_commits
commits = merge_request_diff_commits[event['id'].to_i]
- return nil if commits.blank?
+ return if commits.blank?
commits.find do |commit|
next unless commit[:committed_date] && event['first_mentioned_in_commit_at']
diff --git a/lib/gitlab/danger/helper.rb b/lib/gitlab/danger/helper.rb
new file mode 100644
index 00000000000..d2b7ca015d4
--- /dev/null
+++ b/lib/gitlab/danger/helper.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+require 'net/http'
+require 'json'
+
+require_relative 'teammate'
+
+module Gitlab
+ module Danger
+ module Helper
+ ROULETTE_DATA_URL = URI.parse('https://about.gitlab.com/roulette.json').freeze
+
+ # Returns a list of all files that have been added, modified or renamed.
+ # `git.modified_files` might contain paths that already have been renamed,
+ # so we need to remove them from the list.
+ #
+ # Considering these changes:
+ #
+ # - A new_file.rb
+ # - D deleted_file.rb
+ # - M modified_file.rb
+ # - R renamed_file_before.rb -> renamed_file_after.rb
+ #
+ # it will return
+ # ```
+ # [ 'new_file.rb', 'modified_file.rb', 'renamed_file_after.rb' ]
+ # ```
+ #
+ # @return [Array<String>]
+ def all_changed_files
+ Set.new
+ .merge(git.added_files.to_a)
+ .merge(git.modified_files.to_a)
+ .merge(git.renamed_files.map { |x| x[:after] })
+ .subtract(git.renamed_files.map { |x| x[:before] })
+ .to_a
+ .sort
+ end
+
+ def ee?
+ ENV['CI_PROJECT_NAME'] == 'gitlab-ee' || File.exist?('../../CHANGELOG-EE.md')
+ end
+
+ def project_name
+ ee? ? 'gitlab-ee' : 'gitlab-ce'
+ end
+
+ # Looks up the current list of GitLab team members and parses it into a
+ # useful form
+ #
+ # @return [Array<Teammate>]
+ def team
+ @team ||=
+ begin
+ rsp = Net::HTTP.get_response(ROULETTE_DATA_URL)
+ raise "Failed to read #{ROULETTE_DATA_URL}: #{rsp.code} #{rsp.message}" unless
+ rsp.is_a?(Net::HTTPSuccess)
+
+ data = JSON.parse(rsp.body)
+ data.map { |hash| ::Gitlab::Danger::Teammate.new(hash) }
+ rescue JSON::ParserError
+ raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}"
+ end
+ end
+
+ # Like +team+, but only returns teammates in the current project, based on
+ # project_name.
+ #
+ # @return [Array<Teammate>]
+ def project_team
+ team.select { |member| member.in_project?(project_name) }
+ end
+
+ # @return [Hash<String,Array<String>>]
+ def changes_by_category
+ all_changed_files.each_with_object(Hash.new { |h, k| h[k] = [] }) do |file, hash|
+ hash[category_for_file(file)] << file
+ end
+ end
+
+ # Determines the category a file is in, e.g., `:frontend` or `:backend`
+ # @return[Symbol]
+ def category_for_file(file)
+ _, category = CATEGORIES.find { |regexp, _| regexp.match?(file) }
+
+ category || :unknown
+ end
+
+ # Returns the GFM for a category label, making its best guess if it's not
+ # a category we know about.
+ #
+ # @return[String]
+ def label_for_category(category)
+ CATEGORY_LABELS.fetch(category, "~#{category}")
+ end
+
+ CATEGORY_LABELS = {
+ docs: "~Documentation",
+ none: "",
+ qa: "~QA"
+ }.freeze
+
+ # rubocop:disable Style/RegexpLiteral
+ CATEGORIES = {
+ %r{\Adoc/} => :docs,
+ %r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
+
+ %r{\A(ee/)?app/(assets|views)/} => :frontend,
+ %r{\A(ee/)?public/} => :frontend,
+ %r{\A(ee/)?spec/(javascripts|frontend)/} => :frontend,
+ %r{\A(ee/)?vendor/assets/} => :frontend,
+ %r{\A(jest\.config\.js|package\.json|yarn\.lock)\z} => :frontend,
+
+ %r{\A(ee/)?app/(?!assets|views)[^/]+} => :backend,
+ %r{\A(ee/)?(bin|config|danger|generator_templates|lib|rubocop|scripts)/} => :backend,
+ %r{\A(ee/)?spec/(?!javascripts|frontend)[^/]+} => :backend,
+ %r{\A(ee/)?vendor/(?!assets)[^/]+} => :backend,
+ %r{\A(ee/)?vendor/(languages\.yml|licenses\.csv)\z} => :backend,
+ %r{\A(Dangerfile|Gemfile|Gemfile.lock|Procfile|Rakefile|\.gitlab-ci\.yml)\z} => :backend,
+ %r{\A[A-Z_]+_VERSION\z} => :backend,
+
+ %r{\A(ee/)?db/} => :database,
+ %r{\A(ee/)?qa/} => :qa,
+
+ # Files that don't fit into any category are marked with :none
+ %r{\A(ee/)?changelogs/} => :none,
+ %r{\Alocale/gitlab\.pot\z} => :none,
+
+ # Fallbacks in case the above patterns miss anything
+ %r{\.rb\z} => :backend,
+ %r{\.(md|txt)\z} => :docs,
+ %r{\.js\z} => :frontend
+ }.freeze
+ # rubocop:enable Style/RegexpLiteral
+ end
+ end
+end
diff --git a/lib/gitlab/danger/teammate.rb b/lib/gitlab/danger/teammate.rb
new file mode 100644
index 00000000000..4b822aa86c5
--- /dev/null
+++ b/lib/gitlab/danger/teammate.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Danger
+ class Teammate
+ attr_reader :name, :username, :projects
+
+ def initialize(options = {})
+ @name = options['name']
+ @username = options['username']
+ @projects = options['projects']
+ end
+
+ def markdown_name
+ "[#{name}](https://gitlab.com/#{username}) (`@#{username}`)"
+ end
+
+ def in_project?(name)
+ projects&.has_key?(name)
+ end
+
+ # Traintainers also count as reviewers
+ def reviewer?(project, category)
+ capabilities(project) == "reviewer #{category}" || traintainer?(project, category)
+ end
+
+ def traintainer?(project, category)
+ capabilities(project) == "trainee_maintainer #{category}"
+ end
+
+ def maintainer?(project, category)
+ capabilities(project) == "maintainer #{category}"
+ end
+
+ private
+
+ def capabilities(project)
+ projects.fetch(project, '')
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb
index 9bf2f9291a8..ea08b5f7eae 100644
--- a/lib/gitlab/data_builder/push.rb
+++ b/lib/gitlab/data_builder/push.rb
@@ -31,7 +31,11 @@ module Gitlab
}
}
],
- total_commits_count: 1
+ total_commits_count: 1,
+ push_options: [
+ "ci.skip",
+ "custom option"
+ ]
}.freeze
# Produce a hash of post-receive data
@@ -52,10 +56,12 @@ module Gitlab
# homepage: String,
# },
# commits: Array,
- # total_commits_count: Fixnum
+ # total_commits_count: Fixnum,
+ # push_options: Array
# }
#
- def build(project, user, oldrev, newrev, ref, commits = [], message = nil, commits_count: nil)
+ # rubocop:disable Metrics/ParameterLists
+ def build(project, user, oldrev, newrev, ref, commits = [], message = nil, commits_count: nil, push_options: [])
commits = Array(commits)
# Total commits count
@@ -87,12 +93,13 @@ module Gitlab
user_id: user.id,
user_name: user.name,
user_username: user.username,
- user_email: user.email,
+ user_email: user.public_email,
user_avatar: user.avatar_url(only_path: false),
project_id: project.id,
project: project.hook_attrs,
commits: commit_attrs,
total_commits_count: commits_count,
+ push_options: push_options,
# DEPRECATED
repository: project.hook_attrs.slice(:name, :url, :description, :homepage,
:git_http_url, :git_ssh_url, :visibility_level)
diff --git a/lib/gitlab/database/count/tablesample_count_strategy.rb b/lib/gitlab/database/count/tablesample_count_strategy.rb
index cf1cf054dbf..fedf6ca4fe1 100644
--- a/lib/gitlab/database/count/tablesample_count_strategy.rb
+++ b/lib/gitlab/database/count/tablesample_count_strategy.rb
@@ -36,7 +36,7 @@ module Gitlab
def perform_count(model, estimate)
# If we estimate 0, we may not have statistics at all. Don't use them.
- return nil unless estimate && estimate > 0
+ return unless estimate && estimate > 0
if estimate < EXACT_COUNT_THRESHOLD
# The table is considered small, the assumption here is that
diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb
index ac2efe598b4..ffad00fa7d7 100644
--- a/lib/gitlab/dependency_linker/base_linker.rb
+++ b/lib/gitlab/dependency_linker/base_linker.rb
@@ -4,6 +4,7 @@ module Gitlab
module DependencyLinker
class BaseLinker
URL_REGEX = %r{https?://[^'" ]+}.freeze
+ GIT_INVALID_URL_REGEX = /^git\+#{URL_REGEX}/.freeze
REPO_REGEX = %r{[^/'" ]+/[^/'" ]+}.freeze
class_attribute :file_type
@@ -29,8 +30,25 @@ module Gitlab
highlighted_lines.join.html_safe
end
+ def external_url(name, external_ref)
+ return if external_ref =~ GIT_INVALID_URL_REGEX
+
+ case external_ref
+ when /\A#{URL_REGEX}\z/
+ external_ref
+ when /\A#{REPO_REGEX}\z/
+ github_url(external_ref)
+ else
+ package_url(name)
+ end
+ end
+
private
+ def package_url(_name)
+ raise NotImplementedError
+ end
+
def link_dependencies
raise NotImplementedError
end
diff --git a/lib/gitlab/dependency_linker/composer_json_linker.rb b/lib/gitlab/dependency_linker/composer_json_linker.rb
index 22d2bead891..4b8862b31ee 100644
--- a/lib/gitlab/dependency_linker/composer_json_linker.rb
+++ b/lib/gitlab/dependency_linker/composer_json_linker.rb
@@ -8,8 +8,8 @@ module Gitlab
private
def link_packages
- link_packages_at_key("require", &method(:package_url))
- link_packages_at_key("require-dev", &method(:package_url))
+ link_packages_at_key("require")
+ link_packages_at_key("require-dev")
end
def package_url(name)
diff --git a/lib/gitlab/dependency_linker/gemfile_linker.rb b/lib/gitlab/dependency_linker/gemfile_linker.rb
index 8ab219c4962..c6e02248b0a 100644
--- a/lib/gitlab/dependency_linker/gemfile_linker.rb
+++ b/lib/gitlab/dependency_linker/gemfile_linker.rb
@@ -3,8 +3,14 @@
module Gitlab
module DependencyLinker
class GemfileLinker < MethodLinker
+ class_attribute :package_keyword
+
+ self.package_keyword = :gem
self.file_type = :gemfile
+ GITHUB_REGEX = /(github:|:github\s*=>)\s*['"](?<name>[^'"]+)['"]/.freeze
+ GIT_REGEX = /(git:|:git\s*=>)\s*['"](?<name>#{URL_REGEX})['"]/.freeze
+
private
def link_dependencies
@@ -14,21 +20,35 @@ module Gitlab
def link_urls
# Link `github: "user/repo"` to https://github.com/user/repo
- link_regex(/(github:|:github\s*=>)\s*['"](?<name>[^'"]+)['"]/, &method(:github_url))
+ link_regex(GITHUB_REGEX, &method(:github_url))
# Link `git: "https://gitlab.example.com/user/repo"` to https://gitlab.example.com/user/repo
- link_regex(/(git:|:git\s*=>)\s*['"](?<name>#{URL_REGEX})['"]/, &:itself)
+ link_regex(GIT_REGEX, &:itself)
# Link `source "https://rubygems.org"` to https://rubygems.org
link_method_call('source', URL_REGEX, &:itself)
end
def link_packages
- # Link `gem "package_name"` to https://rubygems.org/gems/package_name
- link_method_call('gem') do |name|
- "https://rubygems.org/gems/#{name}"
+ packages = parse_packages
+
+ return if packages.blank?
+
+ packages.each do |package|
+ link_method_call('gem', package.name) do
+ external_url(package.name, package.external_ref)
+ end
end
end
+
+ def package_url(name)
+ "https://rubygems.org/gems/#{name}"
+ end
+
+ def parse_packages
+ parser = Gitlab::DependencyLinker::Parser::Gemfile.new(plain_text)
+ parser.parse(keyword: self.class.package_keyword)
+ end
end
end
end
diff --git a/lib/gitlab/dependency_linker/gemspec_linker.rb b/lib/gitlab/dependency_linker/gemspec_linker.rb
index b924ea86d89..94c2b375cf9 100644
--- a/lib/gitlab/dependency_linker/gemspec_linker.rb
+++ b/lib/gitlab/dependency_linker/gemspec_linker.rb
@@ -11,7 +11,7 @@ module Gitlab
link_method_call('homepage', URL_REGEX, &:itself)
link_method_call('license', &method(:license_url))
- link_method_call(%w[name add_dependency add_runtime_dependency add_development_dependency]) do |name|
+ link_method_call(%w[add_dependency add_runtime_dependency add_development_dependency]) do |name|
"https://rubygems.org/gems/#{name}"
end
end
diff --git a/lib/gitlab/dependency_linker/method_linker.rb b/lib/gitlab/dependency_linker/method_linker.rb
index d4d85bb3390..33899a931c6 100644
--- a/lib/gitlab/dependency_linker/method_linker.rb
+++ b/lib/gitlab/dependency_linker/method_linker.rb
@@ -23,18 +23,22 @@ module Gitlab
# link_method_call('name')
# # Will link `package` in `self.name = "package"`
def link_method_call(method_name, value = nil, &url_proc)
+ regex = method_call_regex(method_name, value)
+
+ link_regex(regex, &url_proc)
+ end
+
+ def method_call_regex(method_name, value = nil)
method_name = regexp_for_value(method_name)
value = regexp_for_value(value)
- regex = %r{
+ %r{
#{method_name} # Method name
\s* # Whitespace
[(=]? # Opening brace or equals sign
\s* # Whitespace
['"](?<name>#{value})['"] # Package name in quotes
}x
-
- link_regex(regex, &url_proc)
end
end
end
diff --git a/lib/gitlab/dependency_linker/package.rb b/lib/gitlab/dependency_linker/package.rb
new file mode 100644
index 00000000000..8a509bbd562
--- /dev/null
+++ b/lib/gitlab/dependency_linker/package.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module DependencyLinker
+ class Package
+ attr_reader :name, :git_ref, :github_ref
+
+ def initialize(name, git_ref, github_ref)
+ @name = name
+ @git_ref = git_ref
+ @github_ref = github_ref
+ end
+
+ def external_ref
+ @git_ref || @github_ref
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/dependency_linker/package_json_linker.rb b/lib/gitlab/dependency_linker/package_json_linker.rb
index 578e25f806a..6857f2a4fa2 100644
--- a/lib/gitlab/dependency_linker/package_json_linker.rb
+++ b/lib/gitlab/dependency_linker/package_json_linker.rb
@@ -8,7 +8,6 @@ module Gitlab
private
def link_dependencies
- link_json('name', json["name"], &method(:package_url))
link_json('license', &method(:license_url))
link_json(%w[homepage url], URL_REGEX, &:itself)
@@ -16,25 +15,19 @@ module Gitlab
end
def link_packages
- link_packages_at_key("dependencies", &method(:package_url))
- link_packages_at_key("devDependencies", &method(:package_url))
+ link_packages_at_key("dependencies")
+ link_packages_at_key("devDependencies")
end
- def link_packages_at_key(key, &url_proc)
+ def link_packages_at_key(key)
dependencies = json[key]
return unless dependencies
dependencies.each do |name, version|
- link_json(name, version, link: :key, &url_proc)
-
- link_json(name) do |value|
- case value
- when /\A#{URL_REGEX}\z/
- value
- when /\A#{REPO_REGEX}\z/
- github_url(value)
- end
- end
+ external_url = external_url(name, version)
+
+ link_json(name, version, link: :key) { external_url }
+ link_json(name) { external_url }
end
end
diff --git a/lib/gitlab/dependency_linker/parser/gemfile.rb b/lib/gitlab/dependency_linker/parser/gemfile.rb
new file mode 100644
index 00000000000..7f755375cea
--- /dev/null
+++ b/lib/gitlab/dependency_linker/parser/gemfile.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module DependencyLinker
+ module Parser
+ class Gemfile < MethodLinker
+ GIT_REGEX = Gitlab::DependencyLinker::GemfileLinker::GIT_REGEX
+ GITHUB_REGEX = Gitlab::DependencyLinker::GemfileLinker::GITHUB_REGEX
+
+ def initialize(plain_text)
+ @plain_text = plain_text
+ end
+
+ # Returns a list of Gitlab::DependencyLinker::Package
+ #
+ # keyword - The package definition keyword, e.g. `:gem` for
+ # Gemfile parsing, `:pod` for Podfile.
+ def parse(keyword:)
+ plain_lines.each_with_object([]) do |line, packages|
+ name = fetch(line, method_call_regex(keyword))
+
+ next unless name
+
+ git_ref = fetch(line, GIT_REGEX)
+ github_ref = fetch(line, GITHUB_REGEX)
+
+ packages << Gitlab::DependencyLinker::Package.new(name, git_ref, github_ref)
+ end
+ end
+
+ private
+
+ def fetch(line, regex, group: :name)
+ match = line.match(regex)
+ match[group] if match
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/dependency_linker/podfile_linker.rb b/lib/gitlab/dependency_linker/podfile_linker.rb
index def9b04cca9..a20d285da79 100644
--- a/lib/gitlab/dependency_linker/podfile_linker.rb
+++ b/lib/gitlab/dependency_linker/podfile_linker.rb
@@ -5,12 +5,21 @@ module Gitlab
class PodfileLinker < GemfileLinker
include Cocoapods
+ self.package_keyword = :pod
self.file_type = :podfile
private
def link_packages
- link_method_call('pod', &method(:package_url))
+ packages = parse_packages
+
+ return unless packages
+
+ packages.each do |package|
+ link_method_call('pod', package.name) do
+ external_url(package.name, package.external_ref)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/dependency_linker/podspec_linker.rb b/lib/gitlab/dependency_linker/podspec_linker.rb
index 6b1758c5a43..14abd3999c4 100644
--- a/lib/gitlab/dependency_linker/podspec_linker.rb
+++ b/lib/gitlab/dependency_linker/podspec_linker.rb
@@ -19,7 +19,7 @@ module Gitlab
link_method_call('license', &method(:license_url))
link_regex(/license\s*=\s*\{\s*(type:|:type\s*=>)\s*#{STRING_REGEX}/, &method(:license_url))
- link_method_call(%w[name dependency], &method(:package_url))
+ link_method_call('dependency', &method(:package_url))
end
end
end
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index b5fc8d364c8..eac9bb88eb6 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -3,7 +3,9 @@
module Gitlab
module Diff
class File
- attr_reader :diff, :repository, :diff_refs, :fallback_diff_refs
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :diff, :repository, :diff_refs, :fallback_diff_refs, :unique_identifier
delegate :new_file?, :deleted_file?, :renamed_file?,
:old_path, :new_path, :a_mode, :b_mode, :mode_changed?,
@@ -22,12 +24,20 @@ module Gitlab
DiffViewer::Image
].sort_by { |v| v.binary? ? 0 : 1 }.freeze
- def initialize(diff, repository:, diff_refs: nil, fallback_diff_refs: nil, stats: nil)
+ def initialize(
+ diff,
+ repository:,
+ diff_refs: nil,
+ fallback_diff_refs: nil,
+ stats: nil,
+ unique_identifier: nil)
+
@diff = diff
@stats = stats
@repository = repository
@diff_refs = diff_refs
@fallback_diff_refs = fallback_diff_refs
+ @unique_identifier = unique_identifier
@unfolded = false
# Ensure items are collected in the the batch
@@ -65,9 +75,17 @@ module Gitlab
end
def line_for_position(pos)
- return nil unless pos.position_type == 'text'
+ return unless pos.position_type == 'text'
- diff_lines.find { |line| line.old_line == pos.old_line && line.new_line == pos.new_line }
+ # This method is normally used to find which line the diff was
+ # commented on, and in this context, it's normally the raw diff persisted
+ # at `note_diff_files`, which is a fraction of the entire diff
+ # (it goes from the first line, to the commented line, or
+ # one line below). Therefore it's more performant to fetch
+ # from bottom to top instead of the other way around.
+ diff_lines
+ .reverse_each
+ .find { |line| line.old_line == pos.old_line && line.new_line == pos.new_line }
end
def position_for_line_code(code)
@@ -166,6 +184,10 @@ module Gitlab
@unfolded
end
+ def highlight_loaded?
+ @highlighted_diff_lines.present?
+ end
+
def highlighted_diff_lines
@highlighted_diff_lines ||=
Gitlab::Diff::Highlight.new(self, repository: self.repository).highlight
@@ -212,12 +234,12 @@ module Gitlab
repository.attributes(file_path).fetch('diff') { true }
end
- def binary?
- has_binary_notice? || try_blobs(:binary?)
+ def binary_in_repo?
+ has_binary_notice? || try_blobs(:binary_in_repo?)
end
- def text?
- !binary?
+ def text_in_repo?
+ !binary_in_repo?
end
def external_storage_error?
@@ -259,12 +281,20 @@ module Gitlab
valid_blobs.map(&:empty?).all?
end
- def raw_binary?
- try_blobs(:raw_binary?)
+ def binary?
+ strong_memoize(:is_binary) do
+ try_blobs(:binary?)
+ end
+ end
+
+ def text?
+ strong_memoize(:is_text) do
+ !binary? && !different_type?
+ end
end
- def raw_text?
- !raw_binary? && !different_type?
+ def viewer
+ rich_viewer || simple_viewer
end
def simple_viewer
@@ -347,19 +377,19 @@ module Gitlab
return DiffViewer::NotDiffable unless diffable?
if content_changed?
- if raw_text?
+ if text?
DiffViewer::Text
else
DiffViewer::NoPreview
end
elsif new_file?
- if raw_text?
+ if text?
DiffViewer::Text
else
DiffViewer::Added
end
elsif deleted_file?
- if raw_text?
+ if text?
DiffViewer::Text
else
DiffViewer::Deleted
diff --git a/lib/gitlab/diff/lines_unfolder.rb b/lib/gitlab/diff/lines_unfolder.rb
index 9306b7e16a2..6cf904b2b2a 100644
--- a/lib/gitlab/diff/lines_unfolder.rb
+++ b/lib/gitlab/diff/lines_unfolder.rb
@@ -158,9 +158,14 @@ module Gitlab
from = comment_position - UNFOLD_CONTEXT_SIZE
- # There's no line before the match if it's in the top-most
- # position.
- prev_line_number = line_before_unfold_position&.old_pos || 0
+ prev_line_number =
+ if bottom?
+ last_line.old_pos
+ else
+ # There's no line before the match if it's in the top-most
+ # position.
+ line_before_unfold_position&.old_pos || 0
+ end
if from <= prev_line_number + 1
@generate_top_match_line = false
diff --git a/lib/gitlab/discussions_diff/file_collection.rb b/lib/gitlab/discussions_diff/file_collection.rb
new file mode 100644
index 00000000000..4ab7314f509
--- /dev/null
+++ b/lib/gitlab/discussions_diff/file_collection.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module DiscussionsDiff
+ class FileCollection
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(collection)
+ @collection = collection
+ end
+
+ # Returns a Gitlab::Diff::File with the given ID (`unique_identifier` in
+ # Gitlab::Diff::File).
+ def find_by_id(id)
+ diff_files_indexed_by_id[id]
+ end
+
+ # Writes cache and preloads highlighted diff lines for
+ # object IDs, in @collection.
+ #
+ # highlightable_ids - Diff file `Array` responding to ID. The ID will be used
+ # to generate the cache key.
+ #
+ # - Highlight cache is written just for uncached diff files
+ # - The cache content is not updated (there's no need to do so)
+ def load_highlight(highlightable_ids)
+ preload_highlighted_lines(highlightable_ids)
+ end
+
+ private
+
+ def preload_highlighted_lines(ids)
+ cached_content = read_cache(ids)
+
+ uncached_ids = ids.select.each_with_index { |_, i| cached_content[i].nil? }
+ mapping = highlighted_lines_by_ids(uncached_ids)
+
+ HighlightCache.write_multiple(mapping)
+
+ diffs = diff_files_indexed_by_id.values_at(*ids)
+
+ diffs.zip(cached_content).each do |diff, cached_lines|
+ next unless diff && cached_lines
+
+ diff.highlighted_diff_lines = cached_lines
+ end
+ end
+
+ def read_cache(ids)
+ HighlightCache.read_multiple(ids)
+ end
+
+ def diff_files_indexed_by_id
+ strong_memoize(:diff_files_indexed_by_id) do
+ diff_files.index_by(&:unique_identifier)
+ end
+ end
+
+ def diff_files
+ strong_memoize(:diff_files) do
+ @collection.map(&:raw_diff_file)
+ end
+ end
+
+ # Processes the diff lines highlighting for diff files matching the given
+ # IDs.
+ #
+ # Returns a Hash with { id => [Array of Gitlab::Diff::line], ...]
+ def highlighted_lines_by_ids(ids)
+ diff_files_indexed_by_id.slice(*ids).each_with_object({}) do |(id, file), hash|
+ hash[id] = file.highlighted_diff_lines.map(&:to_hash)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/discussions_diff/highlight_cache.rb b/lib/gitlab/discussions_diff/highlight_cache.rb
new file mode 100644
index 00000000000..270cfb89488
--- /dev/null
+++ b/lib/gitlab/discussions_diff/highlight_cache.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+#
+module Gitlab
+ module DiscussionsDiff
+ class HighlightCache
+ class << self
+ VERSION = 1
+ EXPIRATION = 1.week
+
+ # Sets multiple keys to a given value. The value
+ # is serialized as JSON.
+ #
+ # mapping - Write multiple cache values at once
+ def write_multiple(mapping)
+ Redis::Cache.with do |redis|
+ redis.multi do |multi|
+ mapping.each do |raw_key, value|
+ key = cache_key_for(raw_key)
+
+ multi.set(key, value.to_json, ex: EXPIRATION)
+ end
+ end
+ end
+ end
+
+ # Reads multiple cache keys at once.
+ #
+ # raw_keys - An Array of unique cache keys, without namespaces.
+ #
+ # It returns a list of deserialized diff lines. Ex.:
+ # [[Gitlab::Diff::Line, ...], [Gitlab::Diff::Line]]
+ def read_multiple(raw_keys)
+ return [] if raw_keys.empty?
+
+ keys = raw_keys.map { |id| cache_key_for(id) }
+
+ content =
+ Redis::Cache.with do |redis|
+ redis.mget(keys)
+ end
+
+ content.map! do |lines|
+ next unless lines
+
+ JSON.parse(lines).map! do |line|
+ line = line.with_indifferent_access
+ rich_text = line[:rich_text]
+ line[:rich_text] = rich_text&.html_safe
+
+ Gitlab::Diff::Line.init_from_hash(line)
+ end
+ end
+ end
+
+ def cache_key_for(raw_key)
+ "#{cache_key_prefix}:#{raw_key}"
+ end
+
+ private
+
+ def cache_key_prefix
+ "#{Redis::Cache::CACHE_NAMESPACE}:#{VERSION}:discussion-highlight"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb
index 5d9ecd651a0..01fd261404b 100644
--- a/lib/gitlab/ee_compat_check.rb
+++ b/lib/gitlab/ee_compat_check.rb
@@ -7,7 +7,7 @@ module Gitlab
CANONICAL_CE_PROJECT_URL = 'https://gitlab.com/gitlab-org/gitlab-ce'.freeze
CANONICAL_EE_REPO_URL = 'https://gitlab.com/gitlab-org/gitlab-ee.git'.freeze
CHECK_DIR = Rails.root.join('ee_compat_check')
- IGNORED_FILES_REGEX = %r{VERSION|CHANGELOG\.md|db/schema\.rb|locale/gitlab\.pot}i.freeze
+ IGNORED_FILES_REGEX = /VERSION|CHANGELOG\.md/i.freeze
PLEASE_READ_THIS_BANNER = %Q{
============================================================
===================== PLEASE READ THIS =====================
diff --git a/lib/gitlab/email/attachment_uploader.rb b/lib/gitlab/email/attachment_uploader.rb
index a826519b2dd..3323ce60158 100644
--- a/lib/gitlab/email/attachment_uploader.rb
+++ b/lib/gitlab/email/attachment_uploader.rb
@@ -23,8 +23,8 @@ module Gitlab
content_type: attachment.content_type
}
- link = UploadService.new(project, file).execute
- attachments << link if link
+ uploader = UploadService.new(project, file).execute
+ attachments << uploader.to_h if uploader
ensure
tmp.close!
end
diff --git a/lib/gitlab/email/handler/base_handler.rb b/lib/gitlab/email/handler/base_handler.rb
index 35bb49ad19a..f89d1d15010 100644
--- a/lib/gitlab/email/handler/base_handler.rb
+++ b/lib/gitlab/email/handler/base_handler.rb
@@ -6,12 +6,14 @@ module Gitlab
class BaseHandler
attr_reader :mail, :mail_key
+ HANDLER_ACTION_BASE_REGEX ||= /(?<project_slug>.+)-(?<project_id>\d+)/.freeze
+
def initialize(mail, mail_key)
@mail = mail
@mail_key = mail_key
end
- def can_execute?
+ def can_handle?
raise NotImplementedError
end
diff --git a/lib/gitlab/email/handler/create_issue_handler.rb b/lib/gitlab/email/handler/create_issue_handler.rb
index 69982efbbe6..78a3a9489ac 100644
--- a/lib/gitlab/email/handler/create_issue_handler.rb
+++ b/lib/gitlab/email/handler/create_issue_handler.rb
@@ -2,21 +2,33 @@
require 'gitlab/email/handler/base_handler'
+# handles issue creation emails with these formats:
+# incoming+gitlab-org-gitlab-ce-20-Author_Token12345678-issue@incoming.gitlab.com
+# incoming+gitlab-org/gitlab-ce+Author_Token12345678@incoming.gitlab.com (legacy)
module Gitlab
module Email
module Handler
class CreateIssueHandler < BaseHandler
include ReplyProcessing
- attr_reader :project_path, :incoming_email_token
+
+ HANDLER_REGEX = /\A#{HANDLER_ACTION_BASE_REGEX}-(?<incoming_email_token>.+)-issue\z/.freeze
+ HANDLER_REGEX_LEGACY = /\A(?<project_path>[^\+]*)\+(?<incoming_email_token>.*)\z/.freeze
def initialize(mail, mail_key)
super(mail, mail_key)
- @project_path, @incoming_email_token =
- mail_key && mail_key.split('+', 2)
+
+ if !mail_key&.include?('/') && (matched = HANDLER_REGEX.match(mail_key.to_s))
+ @project_slug = matched[:project_slug]
+ @project_id = matched[:project_id]&.to_i
+ @incoming_email_token = matched[:incoming_email_token]
+ elsif matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s)
+ @project_path = matched[:project_path]
+ @incoming_email_token = matched[:incoming_email_token]
+ end
end
def can_handle?
- !incoming_email_token.nil? && !incoming_email_token.include?("+") && !mail_key.include?(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX)
+ incoming_email_token && (project_id || can_handle_legacy_format?)
end
def execute
@@ -36,10 +48,6 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
- def project
- @project ||= Project.find_by_full_path(project_path)
- end
-
private
def create_issue
@@ -50,6 +58,10 @@ module Gitlab
description: message_including_reply
).execute
end
+
+ def can_handle_legacy_format?
+ project_path && !incoming_email_token.include?('+') && !mail_key.include?(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY)
+ end
end
end
end
diff --git a/lib/gitlab/email/handler/create_merge_request_handler.rb b/lib/gitlab/email/handler/create_merge_request_handler.rb
index 5772727e855..b3b5063f2ca 100644
--- a/lib/gitlab/email/handler/create_merge_request_handler.rb
+++ b/lib/gitlab/email/handler/create_merge_request_handler.rb
@@ -3,23 +3,33 @@
require 'gitlab/email/handler/base_handler'
require 'gitlab/email/handler/reply_processing'
+# handles merge request creation emails with these formats:
+# incoming+gitlab-org-gitlab-ce-20-Author_Token12345678-merge-request@incoming.gitlab.com
+# incoming+gitlab-org/gitlab-ce+merge-request+Author_Token12345678@incoming.gitlab.com (legacy)
module Gitlab
module Email
module Handler
class CreateMergeRequestHandler < BaseHandler
include ReplyProcessing
- attr_reader :project_path, :incoming_email_token
+
+ HANDLER_REGEX = /\A#{HANDLER_ACTION_BASE_REGEX}-(?<incoming_email_token>.+)-merge-request\z/.freeze
+ HANDLER_REGEX_LEGACY = /\A(?<project_path>[^\+]*)\+merge-request\+(?<incoming_email_token>.*)/.freeze
def initialize(mail, mail_key)
super(mail, mail_key)
- if m = /\A([^\+]*)\+merge-request\+(.*)/.match(mail_key.to_s)
- @project_path, @incoming_email_token = m.captures
+ if !mail_key&.include?('/') && (matched = HANDLER_REGEX.match(mail_key.to_s))
+ @project_slug = matched[:project_slug]
+ @project_id = matched[:project_id]&.to_i
+ @incoming_email_token = matched[:incoming_email_token]
+ elsif matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s)
+ @project_path = matched[:project_path]
+ @incoming_email_token = matched[:incoming_email_token]
end
end
def can_handle?
- @project_path && @incoming_email_token
+ incoming_email_token && (project_id || project_path)
end
def execute
@@ -40,10 +50,6 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
- def project
- @project ||= Project.find_by_full_path(project_path)
- end
-
def metrics_params
super.merge(includes_patches: patch_attachments.any?)
end
@@ -97,7 +103,7 @@ module Gitlab
def remove_patch_attachments
patch_attachments.each { |patch| mail.parts.delete(patch) }
- # reset the message, so it needs to be reporocessed when the attachments
+ # reset the message, so it needs to be reprocessed when the attachments
# have been modified
@message = nil
end
diff --git a/lib/gitlab/email/handler/create_note_handler.rb b/lib/gitlab/email/handler/create_note_handler.rb
index c7c573595fa..b00af15364d 100644
--- a/lib/gitlab/email/handler/create_note_handler.rb
+++ b/lib/gitlab/email/handler/create_note_handler.rb
@@ -3,6 +3,8 @@
require 'gitlab/email/handler/base_handler'
require 'gitlab/email/handler/reply_processing'
+# handles note/reply creation emails with these formats:
+# incoming+1234567890abcdef1234567890abcdef@incoming.gitlab.com
module Gitlab
module Email
module Handler
diff --git a/lib/gitlab/email/handler/reply_processing.rb b/lib/gitlab/email/handler/reply_processing.rb
index ff6b2c729b2..d8f4be8ada1 100644
--- a/lib/gitlab/email/handler/reply_processing.rb
+++ b/lib/gitlab/email/handler/reply_processing.rb
@@ -6,13 +6,26 @@ module Gitlab
module ReplyProcessing
private
+ attr_reader :project_id, :project_slug, :project_path, :incoming_email_token
+
def author
raise NotImplementedError
end
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
def project
- raise NotImplementedError
+ return @project if instance_variable_defined?(:@project)
+
+ if project_id
+ @project = Project.find_by_id(project_id)
+ @project = nil unless valid_project_slug?(@project)
+ else
+ @project = Project.find_by_full_path(project_path)
+ end
+
+ @project
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
def message
@message ||= process_message
@@ -43,7 +56,7 @@ module Gitlab
raise ProjectNotFound unless author.can?(:read_project, project)
end
- raise UserNotAuthorizedError unless author.can?(permission, project || noteable)
+ raise UserNotAuthorizedError unless author.can?(permission, try(:noteable) || project)
end
def verify_record!(record:, invalid_exception:, record_name:)
@@ -58,6 +71,10 @@ module Gitlab
raise invalid_exception, msg
end
+
+ def valid_project_slug?(found_project)
+ project_slug == found_project.full_path_slug
+ end
end
end
end
diff --git a/lib/gitlab/email/handler/unsubscribe_handler.rb b/lib/gitlab/email/handler/unsubscribe_handler.rb
index d2f617b868a..20e4c125626 100644
--- a/lib/gitlab/email/handler/unsubscribe_handler.rb
+++ b/lib/gitlab/email/handler/unsubscribe_handler.rb
@@ -2,14 +2,28 @@
require 'gitlab/email/handler/base_handler'
+# handles unsubscribe emails with these formats:
+# incoming+1234567890abcdef1234567890abcdef-unsubscribe@incoming.gitlab.com
+# incoming+1234567890abcdef1234567890abcdef+unsubscribe@incoming.gitlab.com (legacy)
module Gitlab
module Email
module Handler
class UnsubscribeHandler < BaseHandler
delegate :project, to: :sent_notification, allow_nil: true
+ HANDLER_REGEX_FOR = -> (suffix) { /\A(?<reply_token>\w+)#{Regexp.escape(suffix)}\z/ }.freeze
+ HANDLER_REGEX = HANDLER_REGEX_FOR.call(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX).freeze
+ HANDLER_REGEX_LEGACY = HANDLER_REGEX_FOR.call(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY).freeze
+
+ def initialize(mail, mail_key)
+ super(mail, mail_key)
+
+ matched = HANDLER_REGEX.match(mail_key.to_s) || HANDLER_REGEX_LEGACY.match(mail_key.to_s)
+ @reply_token = matched[:reply_token] if matched
+ end
+
def can_handle?
- mail_key =~ /\A\w+#{Regexp.escape(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX)}\z/
+ reply_token.present?
end
def execute
@@ -24,12 +38,10 @@ module Gitlab
private
- def sent_notification
- @sent_notification ||= SentNotification.for(reply_key)
- end
+ attr_reader :reply_token
- def reply_key
- mail_key.sub(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX, '')
+ def sent_notification
+ @sent_notification ||= SentNotification.for(reply_token)
end
end
end
diff --git a/lib/gitlab/email/reply_parser.rb b/lib/gitlab/email/reply_parser.rb
index 2743f011ca6..dc44e9d7481 100644
--- a/lib/gitlab/email/reply_parser.rb
+++ b/lib/gitlab/email/reply_parser.rb
@@ -61,7 +61,7 @@ module Gitlab
# Force encoding to UTF-8 on a Mail::Message or Mail::Part
def fix_charset(object)
- return nil if object.nil?
+ return if object.nil?
if object.charset
object.body.decoded.force_encoding(object.charset.gsub(/utf8/i, "UTF-8")).encode("UTF-8").to_s
diff --git a/lib/gitlab/error_tracking/error.rb b/lib/gitlab/error_tracking/error.rb
new file mode 100644
index 00000000000..4af5192aa6a
--- /dev/null
+++ b/lib/gitlab/error_tracking/error.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ErrorTracking
+ class Error
+ include ActiveModel::Model
+
+ attr_accessor :id, :title, :type, :user_count, :count,
+ :first_seen, :last_seen, :message, :culprit,
+ :external_url, :project_id, :project_name, :project_slug,
+ :short_id, :status, :frequency
+ end
+ end
+end
diff --git a/lib/gitlab/error_tracking/project.rb b/lib/gitlab/error_tracking/project.rb
new file mode 100644
index 00000000000..93e81da5034
--- /dev/null
+++ b/lib/gitlab/error_tracking/project.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ErrorTracking
+ class Project
+ include ActiveModel::Model
+
+ ACCESSORS = [
+ :id, :name, :status, :slug, :organization_name,
+ :organization_id, :organization_slug
+ ].freeze
+
+ attr_accessor(*ACCESSORS)
+ end
+ end
+end
diff --git a/lib/gitlab/etag_caching/middleware.rb b/lib/gitlab/etag_caching/middleware.rb
index 0341f930b9c..a11d6b66409 100644
--- a/lib/gitlab/etag_caching/middleware.rb
+++ b/lib/gitlab/etag_caching/middleware.rb
@@ -8,7 +8,7 @@ module Gitlab
end
def call(env)
- request = Rack::Request.new(env)
+ request = ActionDispatch::Request.new(env)
route = Gitlab::EtagCaching::Router.match(request.path_info)
return @app.call(env) unless route
diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb
index 08e30214b46..0891f79198d 100644
--- a/lib/gitlab/etag_caching/router.rb
+++ b/lib/gitlab/etag_caching/router.rb
@@ -52,6 +52,14 @@ module Gitlab
Gitlab::EtagCaching::Router::Route.new(
%r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/environments\.json\z),
'environments'
+ ),
+ Gitlab::EtagCaching::Router::Route.new(
+ %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/import/github/realtime_changes\.json\z),
+ 'realtime_changes_import_github'
+ ),
+ Gitlab::EtagCaching::Router::Route.new(
+ %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/import/gitea/realtime_changes\.json\z),
+ 'realtime_changes_import_gitea'
)
].freeze
diff --git a/lib/gitlab/fogbugz_import/importer.rb b/lib/gitlab/fogbugz_import/importer.rb
index 431911d1eee..2c53f9b026d 100644
--- a/lib/gitlab/fogbugz_import/importer.rb
+++ b/lib/gitlab/fogbugz_import/importer.rb
@@ -239,7 +239,7 @@ module Gitlab
res = ::Projects::DownloadService.new(project, link).execute
- return nil if res.nil?
+ return if res.nil?
res[:markdown]
end
diff --git a/lib/gitlab/gfm/reference_rewriter.rb b/lib/gitlab/gfm/reference_rewriter.rb
index 08d7db49ad7..4d82acd9d87 100644
--- a/lib/gitlab/gfm/reference_rewriter.rb
+++ b/lib/gitlab/gfm/reference_rewriter.rb
@@ -93,7 +93,7 @@ module Gitlab
end
def markdown(text)
- Banzai.render(text, project: @source_parent, no_original_data: true)
+ Banzai.render(text, project: @source_parent, no_original_data: true, no_sourcepos: true)
end
end
end
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index c4aac228b2f..44a62586a23 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -54,11 +54,11 @@ module Gitlab
end
def tag_ref?(ref)
- ref.start_with?(TAG_REF_PREFIX)
+ ref =~ /^#{TAG_REF_PREFIX}.+/
end
def branch_ref?(ref)
- ref.start_with?(BRANCH_REF_PREFIX)
+ ref =~ /^#{BRANCH_REF_PREFIX}.+/
end
def blank_ref?(ref)
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index 2d25389594e..259a2b7911a 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -100,7 +100,7 @@ module Gitlab
@loaded_all_data = @loaded_size == size
end
- def binary?
+ def binary_in_repo?
@binary.nil? ? super : @binary == true
end
@@ -174,7 +174,7 @@ module Gitlab
private
def has_lfs_version_key?
- !empty? && text? && data.start_with?("version https://git-lfs.github.com/spec")
+ !empty? && text_in_repo? && data.start_with?("version https://git-lfs.github.com/spec")
end
end
end
diff --git a/lib/gitlab/git/bundle_file.rb b/lib/gitlab/git/bundle_file.rb
new file mode 100644
index 00000000000..8384a436fcc
--- /dev/null
+++ b/lib/gitlab/git/bundle_file.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ class BundleFile
+ # All git bundle files start with this string
+ #
+ # https://github.com/git/git/blob/v2.20.1/bundle.c#L15
+ MAGIC = "# v2 git bundle\n"
+
+ InvalidBundleError = Class.new(StandardError)
+
+ attr_reader :filename
+
+ def self.check!(filename)
+ new(filename).check!
+ end
+
+ def initialize(filename)
+ @filename = filename
+ end
+
+ def check!
+ data = File.open(filename, 'r') { |f| f.read(MAGIC.size) }
+
+ raise InvalidBundleError, 'Invalid bundle file' unless data == MAGIC
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index 5863815ca85..491e4b47196 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -5,6 +5,7 @@ module Gitlab
module Git
class Commit
include Gitlab::EncodingHelper
+ prepend Gitlab::Git::RuggedImpl::Commit
extend Gitlab::Git::WrapsGitalyErrors
attr_accessor :raw_commit, :head
@@ -57,20 +58,24 @@ module Gitlab
return commit_id if commit_id.is_a?(Gitlab::Git::Commit)
# Some weird thing?
- return nil unless commit_id.is_a?(String)
+ return unless commit_id.is_a?(String)
# This saves us an RPC round trip.
- return nil if commit_id.include?(':')
+ return if commit_id.include?(':')
- commit = wrapped_gitaly_errors do
- repo.gitaly_commit_client.find_commit(commit_id)
- end
+ commit = find_commit(repo, commit_id)
decorate(repo, commit) if commit
rescue Gitlab::Git::CommandError, Gitlab::Git::Repository::NoRepository, ArgumentError
nil
end
+ def find_commit(repo, commit_id)
+ wrapped_gitaly_errors do
+ repo.gitaly_commit_client.find_commit(commit_id)
+ end
+ end
+
# Get last commit for HEAD
#
# Ex.
@@ -185,6 +190,10 @@ module Gitlab
@repository = repository
@head = head
+ init_commit(raw_commit)
+ end
+
+ def init_commit(raw_commit)
case raw_commit
when Hash
init_from_hash(raw_commit)
@@ -400,3 +409,5 @@ module Gitlab
end
end
end
+
+Gitlab::Git::Commit.singleton_class.prepend Gitlab::Git::RuggedImpl::Commit::ClassMethods
diff --git a/lib/gitlab/git/object_pool.rb b/lib/gitlab/git/object_pool.rb
index 1c6242b444a..e93ca3e11f8 100644
--- a/lib/gitlab/git/object_pool.rb
+++ b/lib/gitlab/git/object_pool.rb
@@ -10,12 +10,13 @@ module Gitlab
delegate :exists?, :size, to: :repository
delegate :unlink_repository, :delete, to: :object_pool_service
- attr_reader :storage, :relative_path, :source_repository
+ attr_reader :storage, :relative_path, :source_repository, :gl_project_path
- def initialize(storage, relative_path, source_repository)
+ def initialize(storage, relative_path, source_repository, gl_project_path)
@storage = storage
@relative_path = relative_path
@source_repository = source_repository
+ @gl_project_path = gl_project_path
end
def create
@@ -31,12 +32,12 @@ module Gitlab
end
def to_gitaly_repository
- Gitlab::GitalyClient::Util.repository(storage, relative_path, GL_REPOSITORY)
+ Gitlab::GitalyClient::Util.repository(storage, relative_path, GL_REPOSITORY, gl_project_path)
end
# Allows for reusing other RPCs by 'tricking' Gitaly to think its a repository
def repository
- @repository ||= Gitlab::Git::Repository.new(storage, relative_path, GL_REPOSITORY)
+ @repository ||= Gitlab::Git::Repository.new(storage, relative_path, GL_REPOSITORY, gl_project_path)
end
private
diff --git a/lib/gitlab/git/ref.rb b/lib/gitlab/git/ref.rb
index eec91194949..47cfb483509 100644
--- a/lib/gitlab/git/ref.rb
+++ b/lib/gitlab/git/ref.rb
@@ -4,6 +4,7 @@ module Gitlab
module Git
class Ref
include Gitlab::EncodingHelper
+ include Gitlab::Git::RuggedImpl::Ref
# Branch or tag name
# without "refs/tags|heads" prefix
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 5bbedc9d5e3..7750978fb95 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -11,6 +11,7 @@ module Gitlab
include Gitlab::Git::WrapsGitalyErrors
include Gitlab::EncodingHelper
include Gitlab::Utils::StrongMemoize
+ include Gitlab::Git::RuggedImpl::Repository
SEARCH_CONTEXT_LINES = 3
REV_LIST_COMMIT_LIMIT = 2_000
@@ -67,7 +68,7 @@ module Gitlab
# Relative path of repo
attr_reader :relative_path
- attr_reader :storage, :gl_repository, :relative_path
+ attr_reader :storage, :gl_repository, :relative_path, :gl_project_path
# This remote name has to be stable for all types of repositories that
# can join an object pool. If it's structure ever changes, a migration
@@ -78,10 +79,11 @@ module Gitlab
# This initializer method is only used on the client side (gitlab-ce).
# Gitaly-ruby uses a different initializer.
- def initialize(storage, relative_path, gl_repository)
+ def initialize(storage, relative_path, gl_repository, gl_project_path)
@storage = storage
@relative_path = relative_path
@gl_repository = gl_repository
+ @gl_project_path = gl_project_path
@name = @relative_path.split("/").last
end
@@ -274,7 +276,7 @@ module Gitlab
# senddata response.
def archive_file_path(storage_path, sha, name, format = "tar.gz")
# Build file path
- return nil unless name
+ return unless name
extension =
case format
@@ -490,6 +492,13 @@ module Gitlab
end
end
+ # Return total diverging commits count
+ def diverging_commit_count(from, to, max_count:)
+ wrapped_gitaly_errors do
+ gitaly_commit_client.diverging_commit_count(from, to, max_count: max_count)
+ end
+ end
+
# Mimic the `git clean` command and recursively delete untracked files.
# Valid keys that can be passed in the +options+ hash are:
#
@@ -548,6 +557,12 @@ module Gitlab
tags.find { |tag| tag.name == name }
end
+ def merge_to_ref(user, source_sha, branch, target_ref, message)
+ wrapped_gitaly_errors do
+ gitaly_operation_client.user_merge_to_ref(user, source_sha, branch, target_ref, message)
+ end
+ end
+
def merge(user, source_sha, target_branch, message, &block)
wrapped_gitaly_errors do
gitaly_operation_client.user_merge_branch(user, source_sha, target_branch, message, &block)
@@ -789,6 +804,11 @@ module Gitlab
end
def create_from_bundle(bundle_path)
+ # It's important to check that the linked-to file is actually a valid
+ # .bundle file as it is passed to `git clone`, which may otherwise
+ # interpret it as a pointer to another repository
+ ::Gitlab::Git::BundleFile.check!(bundle_path)
+
gitaly_repository_client.create_from_bundle(bundle_path)
end
@@ -833,17 +853,20 @@ module Gitlab
true
end
+ # rubocop:disable Metrics/ParameterLists
def multi_action(
user, branch_name:, message:, actions:,
author_email: nil, author_name: nil,
- start_branch_name: nil, start_repository: self)
+ start_branch_name: nil, start_repository: self,
+ force: false)
wrapped_gitaly_errors do
gitaly_operation_client.user_commit_files(user, branch_name,
message, actions, author_email, author_name,
- start_branch_name, start_repository)
+ start_branch_name, start_repository, force)
end
end
+ # rubocop:enable Metrics/ParameterLists
def write_config(full_path:)
return unless full_path.present?
@@ -867,7 +890,7 @@ module Gitlab
end
def gitaly_repository
- Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository)
+ Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository, @gl_project_path)
end
def gitaly_ref_client
diff --git a/lib/gitlab/git/rugged_impl/commit.rb b/lib/gitlab/git/rugged_impl/commit.rb
new file mode 100644
index 00000000000..251802878c3
--- /dev/null
+++ b/lib/gitlab/git/rugged_impl/commit.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+# NOTE: This code is legacy. Do not add/modify code here unless you have
+# discussed with the Gitaly team. See
+# https://docs.gitlab.com/ee/development/gitaly.html#legacy-rugged-code
+# for more details.
+
+# rubocop:disable Gitlab/ModuleWithInstanceVariables
+module Gitlab
+ module Git
+ module RuggedImpl
+ module Commit
+ module ClassMethods
+ extend ::Gitlab::Utils::Override
+
+ def rugged_find(repo, commit_id)
+ obj = repo.rev_parse_target(commit_id)
+
+ obj.is_a?(::Rugged::Commit) ? obj : nil
+ rescue ::Rugged::Error
+ nil
+ end
+
+ override :find_commit
+ def find_commit(repo, commit_id)
+ if Feature.enabled?(:rugged_find_commit)
+ rugged_find(repo, commit_id)
+ else
+ super
+ end
+ end
+ end
+
+ extend ::Gitlab::Utils::Override
+
+ override :init_commit
+ def init_commit(raw_commit)
+ case raw_commit
+ when ::Rugged::Commit
+ init_from_rugged(raw_commit)
+ else
+ super
+ end
+ end
+
+ def init_from_rugged(commit)
+ author = commit.author
+ committer = commit.committer
+
+ @raw_commit = commit
+ @id = commit.oid
+ @message = commit.message
+ @authored_date = author[:time]
+ @committed_date = committer[:time]
+ @author_name = author[:name]
+ @author_email = author[:email]
+ @committer_name = committer[:name]
+ @committer_email = committer[:email]
+ @parent_ids = commit.parents.map(&:oid)
+ end
+ end
+ end
+ end
+end
+# rubocop:enable Gitlab/ModuleWithInstanceVariables
diff --git a/lib/gitlab/git/rugged_impl/ref.rb b/lib/gitlab/git/rugged_impl/ref.rb
new file mode 100644
index 00000000000..b553e82dc47
--- /dev/null
+++ b/lib/gitlab/git/rugged_impl/ref.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# NOTE: This code is legacy. Do not add/modify code here unless you have
+# discussed with the Gitaly team. See
+# https://docs.gitlab.com/ee/development/gitaly.html#legacy-rugged-code
+# for more details.
+
+module Gitlab
+ module Git
+ module RuggedImpl
+ module Ref
+ def self.dereference_object(object)
+ object = object.target while object.is_a?(::Rugged::Tag::Annotation)
+
+ object
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/rugged_impl/repository.rb b/lib/gitlab/git/rugged_impl/repository.rb
new file mode 100644
index 00000000000..135c47017b3
--- /dev/null
+++ b/lib/gitlab/git/rugged_impl/repository.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+# NOTE: This code is legacy. Do not add/modify code here unless you have
+# discussed with the Gitaly team. See
+# https://docs.gitlab.com/ee/development/gitaly.html#legacy-rugged-code
+# for more details.
+
+# rubocop:disable Gitlab/ModuleWithInstanceVariables
+module Gitlab
+ module Git
+ module RuggedImpl
+ module Repository
+ FEATURE_FLAGS = %i(rugged_find_commit).freeze
+
+ def alternate_object_directories
+ relative_object_directories.map { |d| File.join(path, d) }
+ end
+
+ ALLOWED_OBJECT_RELATIVE_DIRECTORIES_VARIABLES = %w[
+ GIT_OBJECT_DIRECTORY_RELATIVE
+ GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE
+ ].freeze
+
+ def relative_object_directories
+ Gitlab::Git::HookEnv.all(gl_repository).values_at(*ALLOWED_OBJECT_RELATIVE_DIRECTORIES_VARIABLES).flatten.compact
+ end
+
+ def rugged
+ @rugged ||= ::Rugged::Repository.new(path, alternates: alternate_object_directories)
+ rescue ::Rugged::RepositoryError, ::Rugged::OSError
+ raise ::Gitlab::Git::Repository::NoRepository.new('no repository for such path')
+ end
+
+ def cleanup
+ @rugged&.close
+ end
+
+ # Return the object that +revspec+ points to. If +revspec+ is an
+ # annotated tag, then return the tag's target instead.
+ def rev_parse_target(revspec)
+ obj = rugged.rev_parse(revspec)
+ Ref.dereference_object(obj)
+ end
+ end
+ end
+ end
+end
+# rubocop:enable Gitlab/ModuleWithInstanceVariables
diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb
index 51542bcaaa2..6fcea4e12b4 100644
--- a/lib/gitlab/git/tree.rb
+++ b/lib/gitlab/git/tree.rb
@@ -44,7 +44,7 @@ module Gitlab
entry[:name] == path_arr[0] && entry[:type] == :tree
end
- return nil unless entry
+ return unless entry
if path_arr.size > 1
path_arr.shift
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 802fa65dd63..010bd0e520c 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -12,6 +12,10 @@ module Gitlab
TimeoutError = Class.new(StandardError)
ProjectMovedError = Class.new(NotFoundError)
+ # Use the magic string '_any' to indicate we do not know what the
+ # changes are. This is also what gitlab-shell does.
+ ANY = '_any'
+
ERROR_MESSAGES = {
upload: 'You are not allowed to upload code for this project.',
download: 'You are not allowed to download code from this project.',
@@ -24,7 +28,8 @@ module Gitlab
upload_pack_disabled_over_http: 'Pulling over HTTP is not allowed.',
receive_pack_disabled_over_http: 'Pushing over HTTP is not allowed.',
read_only: 'The repository is temporarily read-only. Please try again later.',
- cannot_push_to_read_only: "You can't push code to a read-only GitLab instance."
+ cannot_push_to_read_only: "You can't push code to a read-only GitLab instance.",
+ push_code: 'You are not allowed to push code to this project.'
}.freeze
INTERNAL_TIMEOUT = 50.seconds.freeze
@@ -199,7 +204,7 @@ module Gitlab
def ensure_project_on_push!(cmd, changes)
return if project || deploy_key?
- return unless receive_pack?(cmd) && changes == '_any' && authentication_abilities.include?(:push_code)
+ return unless receive_pack?(cmd) && changes == ANY && authentication_abilities.include?(:push_code)
namespace = Namespace.find_by_full_path(namespace_path)
@@ -256,24 +261,34 @@ module Gitlab
raise UnauthorizedError, ERROR_MESSAGES[:upload]
end
- return if changes.blank? # Allow access this is needed for EE.
-
check_change_access!
end
def check_change_access!
- # If there are worktrees with a HEAD pointing to a non-existent object,
- # calls to `git rev-list --all` will fail in git 2.15+. This should also
- # clear stale lock files.
- project.repository.clean_stale_repository_files
-
- # Iterate over all changes to find if user allowed all of them to be applied
- changes_list.each.with_index do |change, index|
- first_change = index == 0
-
- # If user does not have access to make at least one change, cancel all
- # push by allowing the exception to bubble up
- check_single_change_access(change, skip_lfs_integrity_check: !first_change)
+ # Deploy keys with write access can push anything
+ return if deploy_key?
+
+ if changes == ANY
+ can_push = user_access.can_do_action?(:push_code) ||
+ project.any_branch_allows_collaboration?(user_access.user)
+
+ unless can_push
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:push_code]
+ end
+ else
+ # If there are worktrees with a HEAD pointing to a non-existent object,
+ # calls to `git rev-list --all` will fail in git 2.15+. This should also
+ # clear stale lock files.
+ project.repository.clean_stale_repository_files
+
+ # Iterate over all changes to find if user allowed all of them to be applied
+ changes_list.each.with_index do |change, index|
+ first_change = index == 0
+
+ # If user does not have access to make at least one change, cancel all
+ # push by allowing the exception to bubble up
+ check_single_change_access(change, skip_lfs_integrity_check: !first_change)
+ end
end
end
@@ -282,7 +297,6 @@ module Gitlab
change,
user_access: user_access,
project: project,
- skip_authorization: deploy_key?,
skip_lfs_integrity_check: skip_lfs_integrity_check,
protocol: protocol,
logger: logger
@@ -348,7 +362,7 @@ module Gitlab
protected
def changes_list
- @changes_list ||= Gitlab::ChangesList.new(changes)
+ @changes_list ||= Gitlab::ChangesList.new(changes == ANY ? [] : changes)
end
def user
diff --git a/lib/gitlab/git_access_wiki.rb b/lib/gitlab/git_access_wiki.rb
index 3f24001e4ee..0af91957fa8 100644
--- a/lib/gitlab/git_access_wiki.rb
+++ b/lib/gitlab/git_access_wiki.rb
@@ -15,7 +15,7 @@ module Gitlab
authentication_abilities.include?(:download_code) && user_access.can_do_action?(:download_wiki_code)
end
- def check_single_change_access(change, _options = {})
+ def check_change_access!
unless user_access.can_do_action?(:create_wiki)
raise UnauthorizedError, ERROR_MESSAGES[:write_to_wiki]
end
diff --git a/lib/gitlab/git_post_receive.rb b/lib/gitlab/git_post_receive.rb
index cf2329e489d..426436c2164 100644
--- a/lib/gitlab/git_post_receive.rb
+++ b/lib/gitlab/git_post_receive.rb
@@ -3,12 +3,13 @@
module Gitlab
class GitPostReceive
include Gitlab::Identifier
- attr_reader :project, :identifier, :changes
+ attr_reader :project, :identifier, :changes, :push_options
- def initialize(project, identifier, changes)
+ def initialize(project, identifier, changes, push_options)
@project = project
@identifier = identifier
@changes = deserialize_changes(changes)
+ @push_options = push_options
end
def identify
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 8bf8a3b53cd..48c113a8b14 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -28,7 +28,7 @@ module Gitlab
PEM_REGEX = /\-+BEGIN CERTIFICATE\-+.+?\-+END CERTIFICATE\-+/m
SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'
- MAXIMUM_GITALY_CALLS = 35
+ MAXIMUM_GITALY_CALLS = 30
CLIENT_NAME = (Sidekiq.server? ? 'gitlab-sidekiq' : 'gitlab-web').freeze
MUTEX = Mutex.new
@@ -52,11 +52,18 @@ module Gitlab
klass = stub_class(name)
addr = stub_address(storage)
creds = stub_creds(storage)
- klass.new(addr, creds)
+ klass.new(addr, creds, interceptors: interceptors)
end
end
end
+ def self.interceptors
+ return [] unless Gitlab::Tracing.enabled?
+
+ [Gitlab::Tracing::GRPCInterceptor.instance]
+ end
+ private_class_method :interceptors
+
def self.stub_cert_paths
cert_paths = Dir["#{OpenSSL::X509::DEFAULT_CERT_DIR}/*"]
cert_paths << OpenSSL::X509::DEFAULT_CERT_FILE if File.exist? OpenSSL::X509::DEFAULT_CERT_FILE
@@ -126,7 +133,11 @@ module Gitlab
end
def self.address_metadata(storage)
- Base64.strict_encode64(JSON.dump({ storage => { 'address' => address(storage), 'token' => token(storage) } }))
+ Base64.strict_encode64(JSON.dump(storage => connection_data(storage)))
+ end
+
+ def self.connection_data(storage)
+ { 'address' => address(storage), 'token' => token(storage) }
end
# All Gitaly RPC call sites should use GitalyClient.call. This method
@@ -153,8 +164,6 @@ module Gitlab
kwargs = yield(kwargs) if block_given?
stub(service, storage).__send__(rpc, request, kwargs) # rubocop:disable GitlabSecurity/PublicSend
- rescue GRPC::Unavailable => ex
- handle_grpc_unavailable!(ex)
ensure
duration = Gitlab::Metrics::System.monotonic_time - start
@@ -167,27 +176,6 @@ module Gitlab
add_call_details(feature: "#{service}##{rpc}", duration: duration, request: request_hash, rpc: rpc)
end
- def self.handle_grpc_unavailable!(ex)
- status = ex.to_status
- raise ex unless status.details == 'Endpoint read failed'
-
- # There is a bug in grpc 1.8.x that causes a client process to get stuck
- # always raising '14:Endpoint read failed'. The only thing that we can
- # do to recover is to restart the process.
- #
- # See https://gitlab.com/gitlab-org/gitaly/issues/1029
-
- if Sidekiq.server?
- raise Gitlab::SidekiqMiddleware::Shutdown::WantShutdown.new(ex.to_s)
- else
- # SIGQUIT requests a Unicorn worker to shut down gracefully after the current request.
- Process.kill('QUIT', Process.pid)
- end
-
- raise ex
- end
- private_class_method :handle_grpc_unavailable!
-
def self.current_transaction_labels
Gitlab::Metrics::Transaction.current&.labels || {}
end
@@ -240,7 +228,7 @@ module Gitlab
result
end
- SERVER_FEATURE_FLAGS = %w[].freeze
+ SERVER_FEATURE_FLAGS = %w[go-find-all-tags].freeze
def self.server_feature_flags
SERVER_FEATURE_FLAGS.map do |f|
@@ -256,7 +244,9 @@ module Gitlab
end
def self.feature_enabled?(feature_name)
- Feature.enabled?("gitaly_#{feature_name}")
+ Feature::FlipperFeature.table_exists? && Feature.enabled?("gitaly_#{feature_name}")
+ rescue ActiveRecord::NoDatabaseError
+ false
end
# Ensures that Gitaly is not being abuse through n+1 misuse etc
@@ -396,13 +386,13 @@ module Gitlab
# Returns the stacks that calls Gitaly the most times. Used for n+1 detection
def self.max_stacks
- return nil unless Gitlab::SafeRequestStore.active?
+ return unless Gitlab::SafeRequestStore.active?
stack_counter = Gitlab::SafeRequestStore[:stack_counter]
- return nil unless stack_counter
+ return unless stack_counter
max = max_call_count
- return nil if max.zero?
+ return if max.zero?
stack_counter.select { |_, v| v == max }.keys
end
diff --git a/lib/gitlab/gitaly_client/blob_service.rb b/lib/gitlab/gitaly_client/blob_service.rb
index 39547328210..6b8e58e6199 100644
--- a/lib/gitlab/gitaly_client/blob_service.rb
+++ b/lib/gitlab/gitaly_client/blob_service.rb
@@ -27,7 +27,7 @@ module Gitlab
data << msg.data
end
- return nil if blob.oid.blank?
+ return if blob.oid.blank?
data = data.join
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 4e46cb9f05c..ea12424eb4a 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -150,6 +150,17 @@ module Gitlab
GitalyClient.call(@repository.storage, :commit_service, :count_commits, request, timeout: GitalyClient.medium_timeout).count
end
+ def diverging_commit_count(from, to, max_count:)
+ request = Gitaly::CountDivergingCommitsRequest.new(
+ repository: @gitaly_repo,
+ from: encode_binary(from),
+ to: encode_binary(to),
+ max_count: max_count
+ )
+ response = GitalyClient.call(@repository.storage, :commit_service, :count_diverging_commits, request, timeout: GitalyClient.medium_timeout)
+ [response.left_count, response.right_count]
+ end
+
def list_last_commits_for_tree(revision, path, offset: 0, limit: 25)
request = Gitaly::ListLastCommitsForTreeRequest.new(
repository: @gitaly_repo,
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 22d2d149e65..2528208440e 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -62,7 +62,7 @@ module Gitlab
end
branch = response.branch
- return nil unless branch
+ return unless branch
target_commit = Gitlab::Git::Commit.decorate(@repository, branch.target_commit)
Gitlab::Git::Branch.new(@repository, branch.name, target_commit.id, target_commit)
@@ -100,6 +100,25 @@ module Gitlab
end
end
+ def user_merge_to_ref(user, source_sha, branch, target_ref, message)
+ request = Gitaly::UserMergeToRefRequest.new(
+ repository: @gitaly_repo,
+ source_sha: source_sha,
+ branch: encode_binary(branch),
+ target_ref: encode_binary(target_ref),
+ user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
+ message: message
+ )
+
+ response = GitalyClient.call(@repository.storage, :operation_service, :user_merge_to_ref, request)
+
+ if pre_receive_error = response.pre_receive_error.presence
+ raise Gitlab::Git::PreReceiveError, pre_receive_error
+ end
+
+ response.commit_id
+ end
+
def user_merge_branch(user, source_sha, target_branch, message)
request_enum = QueueEnumerator.new
response_enum = GitalyClient.call(
@@ -258,14 +277,14 @@ module Gitlab
end
end
+ # rubocop:disable Metrics/ParameterLists
def user_commit_files(
user, branch_name, commit_message, actions, author_email, author_name,
- start_branch_name, start_repository)
-
+ start_branch_name, start_repository, force = false)
req_enum = Enumerator.new do |y|
header = user_commit_files_request_header(user, branch_name,
commit_message, actions, author_email, author_name,
- start_branch_name, start_repository)
+ start_branch_name, start_repository, force)
y.yield Gitaly::UserCommitFilesRequest.new(header: header)
@@ -300,6 +319,7 @@ module Gitlab
Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
end
+ # rubocop:enable Metrics/ParameterLists
def user_commit_patches(user, branch_name, patches)
header = Gitaly::UserApplyPatchRequest::Header.new(
@@ -363,9 +383,10 @@ module Gitlab
Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
end
+ # rubocop:disable Metrics/ParameterLists
def user_commit_files_request_header(
user, branch_name, commit_message, actions, author_email, author_name,
- start_branch_name, start_repository)
+ start_branch_name, start_repository, force)
Gitaly::UserCommitFilesRequestHeader.new(
repository: @gitaly_repo,
@@ -375,9 +396,11 @@ 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
)
end
+ # rubocop:enable Metrics/ParameterLists
def user_commit_files_action_header(action)
Gitaly::UserCommitFilesActionHeader.new(
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 8a1abfbf874..a08bfd0e25b 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -326,11 +326,31 @@ module Gitlab
def search_files_by_content(ref, query)
request = Gitaly::SearchFilesByContentRequest.new(repository: @gitaly_repo, ref: ref, query: query)
- GitalyClient.call(@storage, :repository_service, :search_files_by_content, request).flat_map(&:matches)
+ response = GitalyClient.call(@storage, :repository_service, :search_files_by_content, request)
+
+ search_results_from_response(response)
end
private
+ def search_results_from_response(gitaly_response)
+ matches = []
+ current_match = +""
+
+ gitaly_response.each do |message|
+ next if message.nil?
+
+ current_match << message.match_data
+
+ if message.end_of_match
+ matches << current_match
+ current_match = +""
+ end
+ end
+
+ matches
+ end
+
def gitaly_fetch_stream_to_file(save_path, rpc_name, request_class, timeout)
request = request_class.new(repository: @gitaly_repo)
response = GitalyClient.call(
diff --git a/lib/gitlab/gitaly_client/storage_settings.rb b/lib/gitlab/gitaly_client/storage_settings.rb
index 754cccb6b3f..78ef6bfc0ec 100644
--- a/lib/gitlab/gitaly_client/storage_settings.rb
+++ b/lib/gitlab/gitaly_client/storage_settings.rb
@@ -32,11 +32,19 @@ module Gitlab
end
def self.disk_access_denied?
+ return false if rugged_enabled?
+
!temporarily_allowed?(ALLOW_KEY) && GitalyClient.feature_enabled?(DISK_ACCESS_DENIED_FLAG)
rescue
false # Err on the side of caution, don't break gitlab for people
end
+ def self.rugged_enabled?
+ Gitlab::Git::RuggedImpl::Repository::FEATURE_FLAGS.any? do |flag|
+ Feature.enabled?(flag)
+ end
+ end
+
def initialize(storage)
raise InvalidConfigurationError, "expected a Hash, got a #{storage.class.name}" unless storage.is_a?(Hash)
raise InvalidConfigurationError, INVALID_STORAGE_MESSAGE unless storage.has_key?('path')
diff --git a/lib/gitlab/gitaly_client/util.rb b/lib/gitlab/gitaly_client/util.rb
index dce5d6a8ad0..899921f76e4 100644
--- a/lib/gitlab/gitaly_client/util.rb
+++ b/lib/gitlab/gitaly_client/util.rb
@@ -4,7 +4,7 @@ module Gitlab
module GitalyClient
module Util
class << self
- def repository(repository_storage, relative_path, gl_repository)
+ def repository(repository_storage, relative_path, gl_repository, gl_project_path)
git_env = Gitlab::Git::HookEnv.all(gl_repository)
git_object_directory = git_env['GIT_OBJECT_DIRECTORY_RELATIVE'].presence
git_alternate_object_directories = Array.wrap(git_env['GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE'])
@@ -14,14 +14,16 @@ module Gitlab
relative_path: relative_path,
gl_repository: gl_repository.to_s,
git_object_directory: git_object_directory.to_s,
- git_alternate_object_directories: git_alternate_object_directories
+ git_alternate_object_directories: git_alternate_object_directories,
+ gl_project_path: gl_project_path
)
end
def git_repository(gitaly_repository)
Gitlab::Git::Repository.new(gitaly_repository.storage_name,
gitaly_repository.relative_path,
- gitaly_repository.gl_repository)
+ gitaly_repository.gl_repository,
+ gitaly_repository.gl_project_path)
end
end
end
diff --git a/lib/gitlab/github_import/bulk_importing.rb b/lib/gitlab/github_import/bulk_importing.rb
index da2f96b5c4b..147597289cf 100644
--- a/lib/gitlab/github_import/bulk_importing.rb
+++ b/lib/gitlab/github_import/bulk_importing.rb
@@ -15,12 +15,10 @@ module Gitlab
end
# Bulk inserts the given rows into the database.
- def bulk_insert(model, rows, batch_size: 100, pre_hook: nil)
+ def bulk_insert(model, rows, batch_size: 100)
rows.each_slice(batch_size) do |slice|
- pre_hook.call(slice) if pre_hook
Gitlab::Database.bulk_insert(model.table_name, slice)
end
- rows
end
end
end
diff --git a/lib/gitlab/github_import/importer/issue_importer.rb b/lib/gitlab/github_import/importer/issue_importer.rb
index 4226eee85cc..656d46b6a7d 100644
--- a/lib/gitlab/github_import/importer/issue_importer.rb
+++ b/lib/gitlab/github_import/importer/issue_importer.rb
@@ -57,11 +57,7 @@ module Gitlab
updated_at: issue.updated_at
}
- insert_and_return_id(attributes, project.issues).tap do |id|
- # We use .insert_and_return_id which effectively disables all callbacks.
- # Trigger iid logic here to make sure we track internal id values consistently.
- project.issues.find(id).ensure_project_iid!
- end
+ insert_and_return_id(attributes, project.issues)
rescue ActiveRecord::InvalidForeignKey
# It's possible the project has been deleted since scheduling this
# job. In this case we'll just skip creating the issue.
diff --git a/lib/gitlab/github_import/importer/lfs_object_importer.rb b/lib/gitlab/github_import/importer/lfs_object_importer.rb
index a88c17aaf82..195383fd3e9 100644
--- a/lib/gitlab/github_import/importer/lfs_object_importer.rb
+++ b/lib/gitlab/github_import/importer/lfs_object_importer.rb
@@ -13,10 +13,12 @@ module Gitlab
@project = project
end
+ def lfs_download_object
+ LfsDownloadObject.new(oid: lfs_object.oid, size: lfs_object.size, link: lfs_object.link)
+ end
+
def execute
- Projects::LfsPointers::LfsDownloadService
- .new(project)
- .execute(lfs_object.oid, lfs_object.download_link)
+ Projects::LfsPointers::LfsDownloadService.new(project, lfs_download_object).execute
end
end
end
diff --git a/lib/gitlab/github_import/importer/milestones_importer.rb b/lib/gitlab/github_import/importer/milestones_importer.rb
index 8d54b27374c..71ff7465d9b 100644
--- a/lib/gitlab/github_import/importer/milestones_importer.rb
+++ b/lib/gitlab/github_import/importer/milestones_importer.rb
@@ -19,20 +19,10 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
def execute
- # We insert records in bulk, by-passing any standard model callbacks.
- # The pre_hook here makes sure we track internal ids consistently.
- # Note this has to be called before performing an insert of a batch
- # because we're outside a transaction scope here.
- bulk_insert(Milestone, build_milestones, pre_hook: method(:track_greatest_iid))
+ bulk_insert(Milestone, build_milestones)
build_milestones_cache
end
- def track_greatest_iid(slice)
- greatest_iid = slice.max { |e| e[:iid] }[:iid]
-
- InternalId.track_greatest(nil, { project: project }, :milestones, greatest_iid, ->(_) { project.milestones.maximum(:iid) })
- end
-
def build_milestones
build_database_rows(each_milestone)
end
@@ -52,6 +42,7 @@ module Gitlab
description: milestone.description,
project_id: project.id,
state: state_for(milestone),
+ due_date: milestone.due_on&.to_date,
created_at: milestone.created_at,
updated_at: milestone.updated_at
}
diff --git a/lib/gitlab/github_import/importer/pull_request_importer.rb b/lib/gitlab/github_import/importer/pull_request_importer.rb
index ae7c4cf1b38..e294173f992 100644
--- a/lib/gitlab/github_import/importer/pull_request_importer.rb
+++ b/lib/gitlab/github_import/importer/pull_request_importer.rb
@@ -67,6 +67,36 @@ module Gitlab
def insert_git_data(merge_request, already_exists)
insert_or_replace_git_data(merge_request, pull_request.source_branch_sha, pull_request.target_branch_sha, already_exists)
+ # We need to create the branch after the merge request is
+ # populated to ensure the merge request is in the right state
+ # when the branch is created.
+ create_source_branch_if_not_exists(merge_request)
+ end
+
+ # An imported merge request will not be mergeable unless the
+ # source branch exists. For pull requests from forks, the source
+ # branch will be in the form of
+ # "github/fork/{project-name}/{source_branch}". This branch will never
+ # exist, so we create it here.
+ #
+ # Note that we only create the branch if the merge request is still open.
+ # For projects that have many pull requests, we assume that if it's closed
+ # the branch has already been deleted.
+ def create_source_branch_if_not_exists(merge_request)
+ return unless merge_request.open?
+
+ source_branch = pull_request.formatted_source_branch
+
+ return if project.repository.branch_exists?(source_branch)
+
+ project.repository.add_branch(merge_request.author, source_branch, pull_request.source_branch_sha)
+ rescue Gitlab::Git::CommandError => e
+ Gitlab::Sentry.track_acceptable_exception(e,
+ extra: {
+ source_branch: source_branch,
+ project_id: merge_request.project.id,
+ merge_request_id: merge_request.id
+ })
end
end
end
diff --git a/lib/gitlab/github_import/importer/repository_importer.rb b/lib/gitlab/github_import/importer/repository_importer.rb
index bc3ea9e9226..e2dfb00dcc5 100644
--- a/lib/gitlab/github_import/importer/repository_importer.rb
+++ b/lib/gitlab/github_import/importer/repository_importer.rb
@@ -6,11 +6,12 @@ module Gitlab
class RepositoryImporter
include Gitlab::ShellAdapter
- attr_reader :project, :client
+ attr_reader :project, :client, :wiki_formatter
def initialize(project, client)
@project = project
@client = client
+ @wiki_formatter = ::Gitlab::LegacyGithubImport::WikiFormatter.new(project)
end
# Returns true if we should import the wiki for the project.
@@ -57,9 +58,7 @@ module Gitlab
end
def import_wiki_repository
- wiki_path = "#{project.disk_path}.wiki"
-
- gitlab_shell.import_repository(project.repository_storage, wiki_path, wiki_url)
+ gitlab_shell.import_wiki_repository(project, wiki_formatter)
true
rescue Gitlab::Shell::Error => e
@@ -72,7 +71,7 @@ module Gitlab
end
def wiki_url
- project.import_url.sub(/\.git\z/, '.wiki.git')
+ wiki_formatter.import_url
end
def update_clone_time
diff --git a/lib/gitlab/github_import/representation/lfs_object.rb b/lib/gitlab/github_import/representation/lfs_object.rb
index debe0fa0baf..a4606173f49 100644
--- a/lib/gitlab/github_import/representation/lfs_object.rb
+++ b/lib/gitlab/github_import/representation/lfs_object.rb
@@ -9,11 +9,11 @@ module Gitlab
attr_reader :attributes
- expose_attribute :oid, :download_link
+ expose_attribute :oid, :link, :size
# Builds a lfs_object
def self.from_api_response(lfs_object)
- new({ oid: lfs_object[0], download_link: lfs_object[1] })
+ new({ oid: lfs_object.oid, link: lfs_object.link, size: lfs_object.size })
end
# Builds a new lfs_object using a Hash that was built from a JSON payload.
diff --git a/lib/gitlab/github_import/representation/pull_request.rb b/lib/gitlab/github_import/representation/pull_request.rb
index 593b491a837..0ccc4bfaed3 100644
--- a/lib/gitlab/github_import/representation/pull_request.rb
+++ b/lib/gitlab/github_import/representation/pull_request.rb
@@ -76,10 +76,10 @@ module Gitlab
# Returns a formatted source branch.
#
# For cross-project pull requests the branch name will be in the format
- # `owner-name:branch-name`.
+ # `github/fork/owner-name/branch-name`.
def formatted_source_branch
if cross_project? && source_repository_owner
- "#{source_repository_owner}:#{source_branch}"
+ "github/fork/#{source_repository_owner}/#{source_branch}"
elsif source_branch == target_branch
# Sometimes the source and target branch are the same, but GitLab
# doesn't support this. This can happen when both the user and
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 15137140639..e00309e7946 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -8,10 +8,7 @@ module Gitlab
def add_gon_variables
gon.api_version = 'v4'
- gon.default_avatar_url =
- Gitlab::Utils.append_path(
- Gitlab.config.gitlab.url,
- ActionController::Base.helpers.image_path('no_avatar.png'))
+ gon.default_avatar_url = default_avatar_url
gon.max_file_size = Gitlab::CurrentSettings.max_attachment_size
gon.asset_host = ActionController::Base.asset_host
gon.webpack_public_path = webpack_public_path
@@ -27,6 +24,8 @@ module Gitlab
gon.emoji_sprites_css_path = ActionController::Base.helpers.stylesheet_path('emoji_sprites')
gon.test_env = Rails.env.test?
gon.suggested_label_colors = LabelsHelper.suggested_colors
+ gon.first_day_of_week = current_user&.first_day_of_week || Gitlab::CurrentSettings.first_day_of_week
+ gon.ee = Gitlab.ee?
if current_user
gon.current_user_id = current_user.id
@@ -50,5 +49,15 @@ module Gitlab
# use this method to push multiple feature flags.
gon.push({ features: { var_name => enabled } }, true)
end
+
+ def default_avatar_url
+ # We can't use ActionController::Base.helpers.image_url because it
+ # doesn't return an actual URL because request is nil for some reason.
+ #
+ # We also can't use Gitlab::Utils.append_path because the image path
+ # may be an absolute URL.
+ URI.join(Gitlab.config.gitlab.url,
+ ActionController::Base.helpers.image_path('no_avatar.png')).to_s
+ end
end
end
diff --git a/lib/gitlab/gpg/commit.rb b/lib/gitlab/gpg/commit.rb
index 4fbb87385c3..5ff415b6126 100644
--- a/lib/gitlab/gpg/commit.rb
+++ b/lib/gitlab/gpg/commit.rb
@@ -88,9 +88,10 @@ module Gitlab
def create_cached_signature!
using_keychain do |gpg_key|
- signature = GpgSignature.new(attributes(gpg_key))
- signature.save! unless Gitlab::Database.read_only?
- signature
+ attributes = attributes(gpg_key)
+ break GpgSignature.new(attributes) if Gitlab::Database.read_only?
+
+ GpgSignature.safe_create!(attributes)
end
end
diff --git a/lib/gitlab/graphql/authorize.rb b/lib/gitlab/graphql/authorize.rb
index 5e48bf9043d..f62813db82c 100644
--- a/lib/gitlab/graphql/authorize.rb
+++ b/lib/gitlab/graphql/authorize.rb
@@ -10,21 +10,6 @@ module Gitlab
def self.use(schema_definition)
schema_definition.instrument(:field, Instrumentation.new)
end
-
- def required_permissions
- # If the `#authorize` call is used on multiple classes, we add the
- # permissions specified on a subclass, to the ones that were specified
- # on it's superclass.
- @required_permissions ||= if self.respond_to?(:superclass) && superclass.respond_to?(:required_permissions)
- superclass.required_permissions.dup
- else
- []
- end
- end
-
- def authorize(*permissions)
- required_permissions.concat(permissions)
- end
end
end
end
diff --git a/lib/gitlab/graphql/authorize/authorize_resource.rb b/lib/gitlab/graphql/authorize/authorize_resource.rb
index a56c4f6368d..b367a97105c 100644
--- a/lib/gitlab/graphql/authorize/authorize_resource.rb
+++ b/lib/gitlab/graphql/authorize/authorize_resource.rb
@@ -6,8 +6,21 @@ module Gitlab
module AuthorizeResource
extend ActiveSupport::Concern
- included do
- extend Gitlab::Graphql::Authorize
+ class_methods do
+ def required_permissions
+ # If the `#authorize` call is used on multiple classes, we add the
+ # permissions specified on a subclass, to the ones that were specified
+ # on it's superclass.
+ @required_permissions ||= if self.respond_to?(:superclass) && superclass.respond_to?(:required_permissions)
+ superclass.required_permissions.dup
+ else
+ []
+ end
+ end
+
+ def authorize(*permissions)
+ required_permissions.concat(permissions)
+ end
end
def find_object(*args)
diff --git a/lib/gitlab/graphql/authorize/instrumentation.rb b/lib/gitlab/graphql/authorize/instrumentation.rb
index d638d2b43ee..593da8471dd 100644
--- a/lib/gitlab/graphql/authorize/instrumentation.rb
+++ b/lib/gitlab/graphql/authorize/instrumentation.rb
@@ -6,19 +6,15 @@ module Gitlab
class Instrumentation
# Replace the resolver for the field with one that will only return the
# resolved object if the permissions check is successful.
- #
- # Collections are not supported. Apply permissions checks for those at the
- # database level instead, to avoid loading superfluous data from the DB
def instrument(_type, field)
- field_definition = field.metadata[:type_class]
- return field unless field_definition.respond_to?(:required_permissions)
- return field if field_definition.required_permissions.empty?
+ required_permissions = Array.wrap(field.metadata[:authorize])
+ return field if required_permissions.empty?
old_resolver = field.resolve_proc
new_resolver = -> (obj, args, ctx) do
resolved_obj = old_resolver.call(obj, args, ctx)
- checker = build_checker(ctx[:current_user], field_definition.required_permissions)
+ checker = build_checker(ctx[:current_user], required_permissions)
if resolved_obj.respond_to?(:then)
resolved_obj.then(&checker)
@@ -35,10 +31,22 @@ module Gitlab
private
def build_checker(current_user, abilities)
- proc do |obj|
+ lambda do |value|
# Load the elements if they weren't loaded by BatchLoader yet
- obj = obj.sync if obj.respond_to?(:sync)
- obj if abilities.all? { |ability| Ability.allowed?(current_user, ability, obj) }
+ value = value.sync if value.respond_to?(:sync)
+
+ check = lambda do |object|
+ abilities.all? do |ability|
+ Ability.allowed?(current_user, ability, object)
+ end
+ end
+
+ case value
+ when Array
+ value.select(&check)
+ else
+ value if check.call(value)
+ end
end
end
end
diff --git a/lib/gitlab/hashed_storage/migrator.rb b/lib/gitlab/hashed_storage/migrator.rb
index 1f29cf10cad..7046b4e2a43 100644
--- a/lib/gitlab/hashed_storage/migrator.rb
+++ b/lib/gitlab/hashed_storage/migrator.rb
@@ -11,21 +11,29 @@ module Gitlab
# Schedule a range of projects to be bulk migrated with #bulk_migrate asynchronously
#
- # @param [Object] start first project id for the range
- # @param [Object] finish last project id for the range
- def bulk_schedule(start, finish)
- StorageMigratorWorker.perform_async(start, finish)
+ # @param [Integer] start first project id for the range
+ # @param [Integer] finish last project id for the range
+ def bulk_schedule_migration(start:, finish:)
+ ::HashedStorage::MigratorWorker.perform_async(start, finish)
+ end
+
+ # Schedule a range of projects to be bulk rolledback with #bulk_rollback asynchronously
+ #
+ # @param [Integer] start first project id for the range
+ # @param [Integer] finish last project id for the range
+ def bulk_schedule_rollback(start:, finish:)
+ ::HashedStorage::RollbackerWorker.perform_async(start, finish)
end
# Start migration of projects from specified range
#
- # Flagging a project to be migrated is a synchronous action,
+ # Flagging a project to be migrated is a synchronous action
# but the migration runs through async jobs
#
- # @param [Object] start first project id for the range
- # @param [Object] finish last project id for the range
+ # @param [Integer] start first project id for the range
+ # @param [Integer] finish last project id for the range
# rubocop: disable CodeReuse/ActiveRecord
- def bulk_migrate(start, finish)
+ def bulk_migrate(start:, finish:)
projects = build_relation(start, finish)
projects.with_route.find_each(batch_size: BATCH_SIZE) do |project|
@@ -34,9 +42,26 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
- # Flag a project to be migrated
+ # Start rollback of projects from specified range
+ #
+ # Flagging a project to be rolled back is a synchronous action
+ # but the rollback runs through async jobs
+ #
+ # @param [Integer] start first project id for the range
+ # @param [Integer] finish last project id for the range
+ # rubocop: disable CodeReuse/ActiveRecord
+ def bulk_rollback(start:, finish:)
+ projects = build_relation(start, finish)
+
+ projects.with_route.find_each(batch_size: BATCH_SIZE) do |project|
+ rollback(project)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # Flag a project to be migrated to Hashed Storage
#
- # @param [Object] project that will be migrated
+ # @param [Project] project that will be migrated
def migrate(project)
Rails.logger.info "Starting storage migration of #{project.full_path} (ID=#{project.id})..."
@@ -45,6 +70,17 @@ module Gitlab
Rails.logger.error("#{err.message} migrating storage of #{project.full_path} (ID=#{project.id}), trace - #{err.backtrace}")
end
+ # Flag a project to be rolled-back to Legacy Storage
+ #
+ # @param [Project] project that will be rolled-back
+ def rollback(project)
+ Rails.logger.info "Starting storage rollback of #{project.full_path} (ID=#{project.id})..."
+
+ project.rollback_to_legacy_storage!
+ rescue => err
+ Rails.logger.error("#{err.message} rolling-back storage of #{project.full_path} (ID=#{project.id}), trace - #{err.backtrace}")
+ end
+
private
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/hashed_storage/rake_helper.rb b/lib/gitlab/hashed_storage/rake_helper.rb
index 38f552fab03..87a31a37e3f 100644
--- a/lib/gitlab/hashed_storage/rake_helper.rb
+++ b/lib/gitlab/hashed_storage/rake_helper.rb
@@ -24,7 +24,7 @@ module Gitlab
end
# rubocop: disable CodeReuse/ActiveRecord
- def self.project_id_batches(&block)
+ def self.project_id_batches_migration(&block)
Project.with_unmigrated_storage.in_batches(of: batch_size, start: range_from, finish: range_to) do |relation| # rubocop: disable Cop/InBatches
ids = relation.pluck(:id)
@@ -34,6 +34,16 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
+ def self.project_id_batches_rollback(&block)
+ Project.with_storage_feature(:repository).in_batches(of: batch_size, start: range_from, finish: range_to) do |relation| # rubocop: disable Cop/InBatches
+ ids = relation.pluck(:id)
+
+ yield ids.min, ids.max
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
def self.legacy_attachments_relation
Upload.joins(<<~SQL).where('projects.storage_version < :version OR projects.storage_version IS NULL', version: Project::HASHED_STORAGE_FEATURES[:attachments])
JOIN projects
diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb
index a4e60bbd828..381f1dd4e55 100644
--- a/lib/gitlab/highlight.rb
+++ b/lib/gitlab/highlight.rb
@@ -39,7 +39,7 @@ module Gitlab
private
def custom_language
- return nil unless @language
+ return unless @language
Rouge::Lexer.find_fancy(@language)
end
diff --git a/lib/gitlab/i18n/metadata_entry.rb b/lib/gitlab/i18n/metadata_entry.rb
index 3764e379681..4facd10bfc8 100644
--- a/lib/gitlab/i18n/metadata_entry.rb
+++ b/lib/gitlab/i18n/metadata_entry.rb
@@ -15,7 +15,7 @@ module Gitlab
end
def expected_forms
- return nil unless plural_information
+ return unless plural_information
plural_information['nplurals'].to_i
end
diff --git a/lib/gitlab/import/merge_request_helpers.rb b/lib/gitlab/import/merge_request_helpers.rb
index 9215067d973..fa3ff6c3f12 100644
--- a/lib/gitlab/import/merge_request_helpers.rb
+++ b/lib/gitlab/import/merge_request_helpers.rb
@@ -24,10 +24,6 @@ module Gitlab
merge_request = project.merge_requests.reload.find(merge_request_id)
- # We use .insert_and_return_id which effectively disables all callbacks.
- # Trigger iid logic here to make sure we track internal id values consistently.
- merge_request.ensure_target_project_iid!
-
[merge_request, false]
end
rescue ActiveRecord::InvalidForeignKey
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index 3cd8ede830c..fa54fc17d95 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -28,7 +28,7 @@ project_tree:
- notes:
:author
- releases:
- :author
+ - :links
- project_members:
- :user
- merge_requests:
@@ -63,7 +63,6 @@ project_tree:
- :triggers
- :pipeline_schedules
- :services
- - :hooks
- protected_branches:
- :merge_access_levels
- :push_access_levels
@@ -74,6 +73,7 @@ project_tree:
- :prometheus_metrics
- :project_badges
- :ci_cd_settings
+ - :error_tracking_setting
# Only include the following attributes for the models specified.
included_attributes:
@@ -129,9 +129,13 @@ excluded_attributes:
snippets:
- :expired_at
merge_request_diff:
- - :st_diffs
+ - :external_diff
+ - :stored_externally
+ - :external_diff_store
merge_request_diff_files:
- :diff
+ - :external_diff_offset
+ - :external_diff_size
issues:
- :milestone_id
merge_requests:
@@ -148,6 +152,7 @@ excluded_attributes:
- :when
- :artifacts_file
- :artifacts_metadata
+ - :commands
push_event_payload:
- :event_id
project_badges:
@@ -156,17 +161,15 @@ excluded_attributes:
- :reference
- :reference_html
- :epic_id
- hooks:
- - :token
- - :encrypted_token
- - :encrypted_token_iv
- - :encrypted_url
- - :encrypted_url_iv
runners:
- :token
- :token_encrypted
services:
- :template
+ error_tracking_setting:
+ - :encrypted_token
+ - :encrypted_token_iv
+ - :enabled
methods:
labels:
diff --git a/lib/gitlab/import_export/json_hash_builder.rb b/lib/gitlab/import_export/json_hash_builder.rb
index 477499e1688..b145f37c052 100644
--- a/lib/gitlab/import_export/json_hash_builder.rb
+++ b/lib/gitlab/import_export/json_hash_builder.rb
@@ -67,7 +67,7 @@ module Gitlab
# +value+ existing model to be included in the hash
# +parsed_hash+ the original hash
def parse_hash(value)
- return nil if already_contains_methods?(value)
+ return if already_contains_methods?(value)
@attributes_finder.parse(value) do |hash|
{ include: hash_or_merge(value, hash) }
diff --git a/lib/gitlab/import_export/merge_request_parser.rb b/lib/gitlab/import_export/merge_request_parser.rb
index 040a70d6775..deb2f59f05f 100644
--- a/lib/gitlab/import_export/merge_request_parser.rb
+++ b/lib/gitlab/import_export/merge_request_parser.rb
@@ -20,6 +20,17 @@ module Gitlab
create_target_branch unless branch_exists?(@merge_request.target_branch)
end
+ # The merge_request_diff associated with the current @merge_request might
+ # be invalid. Than means, when the @merge_request object is saved, the
+ # @merge_request.merge_request_diff won't. This can leave the merge request
+ # in an invalid state, because a merge request must have an associated
+ # merge request diff.
+ # In this change, if the associated merge request diff is invalid, we set
+ # it to nil. This change, in association with the after callback
+ # :ensure_merge_request_diff in the MergeRequest class, makes that
+ # when the merge request is going to be created and it doesn't have
+ # one, a default one will be generated.
+ @merge_request.merge_request_diff = nil unless @merge_request.merge_request_diff&.valid?
@merge_request
end
diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb
index a56ec65b9f1..51001750a6c 100644
--- a/lib/gitlab/import_export/project_tree_restorer.rb
+++ b/lib/gitlab/import_export/project_tree_restorer.rb
@@ -107,7 +107,7 @@ module Gitlab
def project_params
@project_params ||= begin
- attrs = json_params.merge(override_params)
+ attrs = json_params.merge(override_params).merge(visibility_level)
# Cleaning all imported and overridden params
Gitlab::ImportExport::AttributeCleaner.clean(relation_hash: attrs,
@@ -127,6 +127,13 @@ module Gitlab
end
end
+ def visibility_level
+ level = override_params['visibility_level'] || json_params['visibility_level'] || @project.visibility_level
+ level = @project.group.visibility_level if @project.group && level > @project.group.visibility_level
+
+ { 'visibility_level' => level }
+ end
+
# Given a relation hash containing one or more models and its relationships,
# loops through each model and each object from a model type and
# and assigns its correspondent attributes hash from +tree_hash+
diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb
index a4902e2104f..61a1aa6da5a 100644
--- a/lib/gitlab/import_export/relation_factory.rb
+++ b/lib/gitlab/import_export/relation_factory.rb
@@ -23,7 +23,9 @@ module Gitlab
custom_attributes: 'ProjectCustomAttribute',
project_badges: 'Badge',
metrics: 'MergeRequest::Metrics',
- ci_cd_settings: 'ProjectCiCdSetting' }.freeze
+ ci_cd_settings: 'ProjectCiCdSetting',
+ error_tracking_setting: 'ErrorTracking::ProjectErrorTrackingSetting',
+ links: 'Releases::Link' }.freeze
USER_REFERENCES = %w[author_id assignee_id updated_by_id merged_by_id latest_closed_by_id user_id created_by_id last_edited_by_id merge_user_id resolved_by_id closed_by_id].freeze
@@ -73,7 +75,7 @@ module Gitlab
# the relation_hash, updating references with new object IDs, mapping users using
# the "members_mapper" object, also updating notes if required.
def create
- return nil if unknown_service?
+ return if unknown_service?
setup_models
@@ -149,6 +151,7 @@ module Gitlab
if BUILD_MODELS.include?(@relation_name)
@relation_hash.delete('trace') # old export files have trace
@relation_hash.delete('token')
+ @relation_hash.delete('commands')
imported_object
elsif @relation_name == :merge_requests
diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb
index c13e6c1d83b..725c1101d70 100644
--- a/lib/gitlab/import_export/shared.rb
+++ b/lib/gitlab/import_export/shared.rb
@@ -8,6 +8,7 @@ module Gitlab
def initialize(project)
@project = project
@errors = []
+ @logger = Gitlab::Import::Logger.build
end
def active_export_count
@@ -23,19 +24,16 @@ module Gitlab
end
def error(error)
- error_out(error.message, caller[0].dup)
- add_error_message(error.message)
+ log_error(message: error.message, caller: caller[0].dup)
+ log_debug(backtrace: error.backtrace&.join("\n"))
+
+ Gitlab::Sentry.track_acceptable_exception(error, extra: log_base_data)
- # Debug:
- if error.backtrace
- Rails.logger.error("Import/Export backtrace: #{error.backtrace.join("\n")}")
- else
- Rails.logger.error("No backtrace found")
- end
+ add_error_message(error.message)
end
- def add_error_message(error_message)
- @errors << error_message
+ def add_error_message(message)
+ @errors << filtered_error_message(message)
end
def after_export_in_progress?
@@ -52,8 +50,25 @@ module Gitlab
@project.disk_path
end
- def error_out(message, caller)
- Rails.logger.error("Import/Export error raised on #{caller}: #{message}")
+ def log_error(details)
+ @logger.error(log_base_data.merge(details))
+ end
+
+ def log_debug(details)
+ @logger.debug(log_base_data.merge(details))
+ end
+
+ def log_base_data
+ {
+ importer: 'Import/Export',
+ import_jid: @project&.import_state&.jid,
+ project_id: @project&.id,
+ project_path: @project&.full_path
+ }
+ end
+
+ def filtered_error_message(message)
+ Projects::ImportErrorFilter.filter_message(message)
end
def after_export_lock_file
diff --git a/lib/gitlab/import_export/uploads_manager.rb b/lib/gitlab/import_export/uploads_manager.rb
index 474e9d45566..e232198150a 100644
--- a/lib/gitlab/import_export/uploads_manager.rb
+++ b/lib/gitlab/import_export/uploads_manager.rb
@@ -40,7 +40,7 @@ module Gitlab
def add_upload(upload)
uploader_context = FileUploader.extract_dynamic_path(upload).named_captures.symbolize_keys
- UploadService.new(@project, File.open(upload, 'r'), FileUploader, uploader_context).execute
+ UploadService.new(@project, File.open(upload, 'r'), FileUploader, uploader_context).execute.to_h
end
def copy_project_uploads
diff --git a/lib/gitlab/incoming_email.rb b/lib/gitlab/incoming_email.rb
index 20fc8226611..8b346f6d7d2 100644
--- a/lib/gitlab/incoming_email.rb
+++ b/lib/gitlab/incoming_email.rb
@@ -2,8 +2,9 @@
module Gitlab
module IncomingEmail
- UNSUBSCRIBE_SUFFIX = '+unsubscribe'.freeze
- WILDCARD_PLACEHOLDER = '%{key}'.freeze
+ UNSUBSCRIBE_SUFFIX = '-unsubscribe'.freeze
+ UNSUBSCRIBE_SUFFIX_LEGACY = '+unsubscribe'.freeze
+ WILDCARD_PLACEHOLDER = '%{key}'.freeze
class << self
def enabled?
@@ -22,6 +23,7 @@ module Gitlab
config.address.sub(WILDCARD_PLACEHOLDER, key)
end
+ # example: incoming+1234567890abcdef1234567890abcdef-unsubscribe@incoming.gitlab.com
def unsubscribe_address(key)
config.address.sub(WILDCARD_PLACEHOLDER, "#{key}#{UNSUBSCRIBE_SUFFIX}")
end
@@ -55,7 +57,7 @@ module Gitlab
def address_regex
wildcard_address = config.address
- return nil unless wildcard_address
+ return unless wildcard_address
regex = Regexp.escape(wildcard_address)
regex = regex.sub(Regexp.escape(WILDCARD_PLACEHOLDER), '(.+)')
diff --git a/lib/gitlab/json_cache.rb b/lib/gitlab/json_cache.rb
index 1adf83739ad..24daad638f4 100644
--- a/lib/gitlab/json_cache.rb
+++ b/lib/gitlab/json_cache.rb
@@ -71,7 +71,21 @@ module Gitlab
end
def parse_entry(raw, klass)
- klass.new(raw) if valid_entry?(raw, klass)
+ return unless valid_entry?(raw, klass)
+ return klass.new(raw) unless klass.ancestors.include?(ActiveRecord::Base)
+
+ # When the cached value is a persisted instance of ActiveRecord::Base in
+ # some cases a relation can return an empty collection becauses scope.none!
+ # is being applied on ActiveRecord::Associations::CollectionAssociation#scope
+ # when the new_record? method incorrectly returns false.
+ #
+ # See https://gitlab.com/gitlab-org/gitlab-ee/issues/9903#note_145329964
+ attributes = klass.attributes_builder.build_from_database(raw, {})
+ klass.allocate.init_with("attributes" => attributes, "new_record" => new_record?(raw, klass))
+ end
+
+ def new_record?(raw, klass)
+ raw.fetch(klass.primary_key, nil).blank?
end
def valid_entry?(raw, klass)
diff --git a/lib/gitlab/kubernetes/helm.rb b/lib/gitlab/kubernetes/helm.rb
index 03d38ec78fd..42c4745ff98 100644
--- a/lib/gitlab/kubernetes/helm.rb
+++ b/lib/gitlab/kubernetes/helm.rb
@@ -3,8 +3,8 @@
module Gitlab
module Kubernetes
module Helm
- HELM_VERSION = '2.11.0'.freeze
- KUBECTL_VERSION = '1.11.0'.freeze
+ HELM_VERSION = '2.12.3'.freeze
+ KUBECTL_VERSION = '1.11.7'.freeze
NAMESPACE = 'gitlab-managed-apps'.freeze
SERVICE_ACCOUNT = 'tiller'.freeze
CLUSTER_ROLE_BINDING = 'tiller-admin'.freeze
diff --git a/lib/gitlab/kubernetes/helm/api.rb b/lib/gitlab/kubernetes/helm/api.rb
index b9903e37f40..7dfd9ed4f35 100644
--- a/lib/gitlab/kubernetes/helm/api.rb
+++ b/lib/gitlab/kubernetes/helm/api.rb
@@ -20,14 +20,7 @@ module Gitlab
kubeclient.create_pod(command.pod_resource)
end
- def update(command)
- namespace.ensure_exists!
-
- update_config_map(command)
-
- delete_pod!(command.pod_name)
- kubeclient.create_pod(command.pod_resource)
- end
+ alias_method :update, :install
##
# Returns Pod phase
@@ -62,6 +55,8 @@ module Gitlab
def create_config_map(command)
command.config_map_resource.tap do |config_map_resource|
+ break unless config_map_resource
+
if config_map_exists?(config_map_resource)
kubeclient.update_config_map(config_map_resource)
else
diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb
index a1ab5e048ac..f931248b747 100644
--- a/lib/gitlab/kubernetes/helm/install_command.rb
+++ b/lib/gitlab/kubernetes/helm/install_command.rb
@@ -42,8 +42,17 @@ module Gitlab
'helm repo update' if repository
end
+ # Uses `helm upgrade --install` which means we can use this for both
+ # installation and uprade of applications
def install_command
- command = ['helm', 'install', chart] + install_command_flags
+ command = ['helm', 'upgrade', name, chart] +
+ install_flag +
+ reset_values_flag +
+ optional_tls_flags +
+ optional_version_flag +
+ rbac_create_flag +
+ namespace_flag +
+ value_flag
command.shelljoin
end
@@ -56,17 +65,20 @@ module Gitlab
postinstall.join("\n") if postinstall
end
- def install_command_flags
- name_flag = ['--name', name]
- namespace_flag = ['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
- value_flag = ['-f', "/data/helm/#{name}/config/values.yaml"]
+ def install_flag
+ ['--install']
+ end
- name_flag +
- optional_tls_flags +
- optional_version_flag +
- rbac_create_flag +
- namespace_flag +
- value_flag
+ def reset_values_flag
+ ['--reset-values']
+ end
+
+ def value_flag
+ ['-f', "/data/helm/#{name}/config/values.yaml"]
+ end
+
+ def namespace_flag
+ ['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
end
def rbac_create_flag
diff --git a/lib/gitlab/kubernetes/helm/upgrade_command.rb b/lib/gitlab/kubernetes/helm/upgrade_command.rb
deleted file mode 100644
index 9daffc138b5..00000000000
--- a/lib/gitlab/kubernetes/helm/upgrade_command.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Kubernetes
- module Helm
- class UpgradeCommand
- include BaseCommand
- include ClientCommand
-
- attr_reader :name, :chart, :version, :repository, :files
-
- def initialize(name, chart:, files:, rbac:, version: nil, repository: nil)
- @name = name
- @chart = chart
- @rbac = rbac
- @version = version
- @files = files
- @repository = repository
- end
-
- def generate_script
- super + [
- init_command,
- wait_for_tiller_command,
- repository_command,
- script_command
- ].compact.join("\n")
- end
-
- def rbac?
- @rbac
- end
-
- def pod_name
- "upgrade-#{name}"
- end
-
- private
-
- def script_command
- upgrade_flags = "#{optional_version_flag}#{optional_tls_flags}" \
- " --reset-values" \
- " --install" \
- " --namespace #{::Gitlab::Kubernetes::Helm::NAMESPACE}" \
- " -f /data/helm/#{name}/config/values.yaml"
-
- "helm upgrade #{name} #{chart}#{upgrade_flags}"
- end
-
- def optional_version_flag
- " --version #{version}" if version
- end
-
- def optional_tls_flags
- return unless files.key?(:'ca.pem')
-
- " --tls" \
- " --tls-ca-cert #{files_dir}/ca.pem" \
- " --tls-cert #{files_dir}/cert.pem" \
- " --tls-key #{files_dir}/key.pem"
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/kubernetes/kube_client.rb b/lib/gitlab/kubernetes/kube_client.rb
index fe839940f74..de14df56555 100644
--- a/lib/gitlab/kubernetes/kube_client.rb
+++ b/lib/gitlab/kubernetes/kube_client.rb
@@ -76,9 +76,14 @@ module Gitlab
attr_reader :api_prefix, :kubeclient_options
+ # We disable redirects through 'http_max_redirects: 0',
+ # so that KubeClient does not follow redirects and
+ # expose internal services.
def initialize(api_prefix, **kubeclient_options)
@api_prefix = api_prefix
- @kubeclient_options = kubeclient_options
+ @kubeclient_options = kubeclient_options.merge(http_max_redirects: 0)
+
+ validate_url!
end
def create_or_update_cluster_role_binding(resource)
@@ -115,6 +120,12 @@ module Gitlab
private
+ def validate_url!
+ return if Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services?
+
+ Gitlab::UrlBlocker.validate!(api_prefix, allow_local_network: false)
+ end
+
def cluster_role_binding_exists?(resource)
get_cluster_role_binding(resource.metadata.name)
rescue ::Kubeclient::ResourceNotFoundError
diff --git a/lib/gitlab/legacy_github_import/client.rb b/lib/gitlab/legacy_github_import/client.rb
index bc952147667..bbdd094e33b 100644
--- a/lib/gitlab/legacy_github_import/client.rb
+++ b/lib/gitlab/legacy_github_import/client.rb
@@ -68,7 +68,7 @@ module Gitlab
end
def user(login)
- return nil unless login.present?
+ return unless login.present?
return @users[login] if @users.key?(login)
@users[login] = api.user(login)
diff --git a/lib/gitlab/legacy_github_import/importer.rb b/lib/gitlab/legacy_github_import/importer.rb
index c526d31a591..f3323c98af2 100644
--- a/lib/gitlab/legacy_github_import/importer.rb
+++ b/lib/gitlab/legacy_github_import/importer.rb
@@ -267,7 +267,7 @@ module Gitlab
def import_wiki
unless project.wiki.repository_exists?
wiki = WikiFormatter.new(project)
- gitlab_shell.import_repository(project.repository_storage, wiki.disk_path, wiki.import_url)
+ gitlab_shell.import_wiki_repository(project, wiki)
end
rescue Gitlab::Shell::Error => e
# GitHub error message when the wiki repo has not been created,
diff --git a/lib/gitlab/legacy_github_import/user_formatter.rb b/lib/gitlab/legacy_github_import/user_formatter.rb
index ec0e221b1ff..889e6aaa968 100644
--- a/lib/gitlab/legacy_github_import/user_formatter.rb
+++ b/lib/gitlab/legacy_github_import/user_formatter.rb
@@ -25,7 +25,7 @@ module Gitlab
end
def find_by_email
- return nil unless email
+ return unless email
User.find_by_any_email(email)
.try(:id)
@@ -33,7 +33,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def find_by_external_uid
- return nil unless id
+ return unless id
identities = ::Identity.arel_table
diff --git a/lib/gitlab/legacy_github_import/wiki_formatter.rb b/lib/gitlab/legacy_github_import/wiki_formatter.rb
index ea52be5ee0f..cf1e21ad1e1 100644
--- a/lib/gitlab/legacy_github_import/wiki_formatter.rb
+++ b/lib/gitlab/legacy_github_import/wiki_formatter.rb
@@ -13,6 +13,10 @@ module Gitlab
project.wiki.disk_path
end
+ def full_path
+ project.wiki.full_path
+ end
+
def import_url
project.import_url.sub(/\.git\z/, ".wiki.git")
end
diff --git a/lib/gitlab/lfs_token.rb b/lib/gitlab/lfs_token.rb
index c09d3ebc7be..31e6fc9d8c7 100644
--- a/lib/gitlab/lfs_token.rb
+++ b/lib/gitlab/lfs_token.rb
@@ -30,8 +30,8 @@ module Gitlab
end
end
- def token(expire_time: DEFAULT_EXPIRE_TIME)
- HMACToken.new(actor).token(expire_time)
+ def token
+ HMACToken.new(actor).token(DEFAULT_EXPIRE_TIME)
end
def token_valid?(token_to_check)
@@ -47,7 +47,16 @@ module Gitlab
user? ? :lfs_token : :lfs_deploy_token
end
- private # rubocop:disable Lint/UselessAccessModifier
+ def authentication_payload(repository_http_path)
+ {
+ username: actor_name,
+ lfs_token: token,
+ repository_http_path: repository_http_path,
+ expires_in: DEFAULT_EXPIRE_TIME
+ }
+ end
+
+ private # rubocop:disable Lint/UselessAccessModifier
class HMACToken
include LfsTokenHelper
@@ -100,7 +109,7 @@ module Gitlab
#
class LegacyRedisDeviseToken
TOKEN_LENGTH = 50
- DEFAULT_EXPIRY_TIME = 1800 * 1000 # 30 mins
+ DEFAULT_EXPIRY_TIME = 1800 * 1000 # 30 mins
def initialize(actor)
@actor = actor
diff --git a/lib/gitlab/loop_helpers.rb b/lib/gitlab/loop_helpers.rb
new file mode 100644
index 00000000000..3873156a3b0
--- /dev/null
+++ b/lib/gitlab/loop_helpers.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module LoopHelpers
+ ##
+ # This helper method repeats the same task until it's expired.
+ #
+ # Note: ExpiredLoopError does not happen until the given block finished.
+ # Please do not use this method for heavy or asynchronous operations.
+ def loop_until(timeout: nil, limit: 1_000_000)
+ raise ArgumentError unless limit
+
+ start = Time.now
+
+ limit.times do
+ return true unless yield
+
+ return false if timeout && (Time.now - start) > timeout
+ end
+
+ false
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb
index 1359e973590..0b04340fbb5 100644
--- a/lib/gitlab/metrics/influx_db.rb
+++ b/lib/gitlab/metrics/influx_db.rb
@@ -147,9 +147,7 @@ module Gitlab
#
# See `Gitlab::Metrics::Transaction#add_event` for more details.
def add_event(*args)
- trans = current_transaction
-
- trans&.add_event(*args)
+ current_transaction&.add_event(*args)
end
# Returns the prefix to use for the name of a series.
diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb
index 651e241362c..ff3fffe7b95 100644
--- a/lib/gitlab/metrics/instrumentation.rb
+++ b/lib/gitlab/metrics/instrumentation.rb
@@ -19,7 +19,7 @@ module Gitlab
# Returns the name of the series to use for storing method calls.
def self.series
- @series ||= "#{Metrics.series_prefix}method_calls"
+ @series ||= "#{::Gitlab::Metrics.series_prefix}method_calls"
end
# Instruments a class method.
@@ -118,7 +118,7 @@ module Gitlab
# mod - The module containing the method.
# name - The name of the method to instrument.
def self.instrument(type, mod, name)
- return unless Metrics.enabled?
+ return unless ::Gitlab::Metrics.enabled?
name = name.to_sym
target = type == :instance ? mod : mod.singleton_class
diff --git a/lib/gitlab/metrics/method_call.rb b/lib/gitlab/metrics/method_call.rb
index 85438011cb9..d0c63a862c2 100644
--- a/lib/gitlab/metrics/method_call.rb
+++ b/lib/gitlab/metrics/method_call.rb
@@ -65,7 +65,7 @@ module Gitlab
# Returns true if the total runtime of this method exceeds the method call
# threshold.
def above_threshold?
- real_time.in_milliseconds >= Metrics.method_call_threshold
+ real_time.in_milliseconds >= ::Gitlab::Metrics.method_call_threshold
end
end
end
diff --git a/lib/gitlab/metrics/methods.rb b/lib/gitlab/metrics/methods.rb
index 447d03bfca4..cee601ff14c 100644
--- a/lib/gitlab/metrics/methods.rb
+++ b/lib/gitlab/metrics/methods.rb
@@ -58,11 +58,11 @@ module Gitlab
def build_metric!(type, name, options)
case type
when :gauge
- Gitlab::Metrics.gauge(name, options.docstring, options.base_labels, options.multiprocess_mode)
+ ::Gitlab::Metrics.gauge(name, options.docstring, options.base_labels, options.multiprocess_mode)
when :counter
- Gitlab::Metrics.counter(name, options.docstring, options.base_labels)
+ ::Gitlab::Metrics.counter(name, options.docstring, options.base_labels)
when :histogram
- Gitlab::Metrics.histogram(name, options.docstring, options.base_labels, options.buckets)
+ ::Gitlab::Metrics.histogram(name, options.docstring, options.base_labels, options.buckets)
when :summary
raise NotImplementedError, "summary metrics are not currently supported"
else
diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb
index 74c956ab5af..26aa0910047 100644
--- a/lib/gitlab/metrics/requests_rack_middleware.rb
+++ b/lib/gitlab/metrics/requests_rack_middleware.rb
@@ -8,15 +8,15 @@ module Gitlab
end
def self.http_request_total
- @http_request_total ||= Gitlab::Metrics.counter(:http_requests_total, 'Request count')
+ @http_request_total ||= ::Gitlab::Metrics.counter(:http_requests_total, 'Request count')
end
def self.rack_uncaught_errors_count
- @rack_uncaught_errors_count ||= Gitlab::Metrics.counter(:rack_uncaught_errors_total, 'Request handling uncaught errors count')
+ @rack_uncaught_errors_count ||= ::Gitlab::Metrics.counter(:rack_uncaught_errors_total, 'Request handling uncaught errors count')
end
def self.http_request_duration_seconds
- @http_request_duration_seconds ||= Gitlab::Metrics.histogram(:http_request_duration_seconds, 'Request handling execution time',
+ @http_request_duration_seconds ||= ::Gitlab::Metrics.histogram(:http_request_duration_seconds, 'Request handling execution time',
{}, [0.05, 0.1, 0.25, 0.5, 0.7, 1, 2.5, 5, 10, 25])
end
diff --git a/lib/gitlab/metrics/samplers/influx_sampler.rb b/lib/gitlab/metrics/samplers/influx_sampler.rb
index c4c38b23a55..5138b37f83e 100644
--- a/lib/gitlab/metrics/samplers/influx_sampler.rb
+++ b/lib/gitlab/metrics/samplers/influx_sampler.rb
@@ -10,7 +10,7 @@ module Gitlab
# statistics, etc.
class InfluxSampler < BaseSampler
# interval - The sampling interval in seconds.
- def initialize(interval = Metrics.settings[:sample_interval])
+ def initialize(interval = ::Gitlab::Metrics.settings[:sample_interval])
super(interval)
@last_step = nil
@@ -32,7 +32,7 @@ module Gitlab
end
def flush
- Metrics.submit_metrics(@metrics.map(&:to_hash))
+ ::Gitlab::Metrics.submit_metrics(@metrics.map(&:to_hash))
end
def sample_memory_usage
diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb
index 232a58a7d69..18a69321905 100644
--- a/lib/gitlab/metrics/samplers/ruby_sampler.rb
+++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb
@@ -24,14 +24,14 @@ module Gitlab
def init_metrics
metrics = {}
- metrics[:sampler_duration] = Metrics.counter(with_prefix(:sampler, :duration_seconds_total), 'Sampler time', labels)
- metrics[:total_time] = Metrics.counter(with_prefix(:gc, :duration_seconds_total), 'Total GC time', labels)
+ metrics[:sampler_duration] = ::Gitlab::Metrics.counter(with_prefix(:sampler, :duration_seconds_total), 'Sampler time', labels)
+ metrics[:total_time] = ::Gitlab::Metrics.counter(with_prefix(:gc, :duration_seconds_total), 'Total GC time', labels)
GC.stat.keys.each do |key|
- metrics[key] = Metrics.gauge(with_prefix(:gc_stat, key), to_doc_string(key), labels, :livesum)
+ metrics[key] = ::Gitlab::Metrics.gauge(with_prefix(:gc_stat, key), to_doc_string(key), labels, :livesum)
end
- metrics[:memory_usage] = Metrics.gauge(with_prefix(:memory, :bytes), 'Memory used', labels, :livesum)
- metrics[:file_descriptors] = Metrics.gauge(with_prefix(:file, :descriptors), 'File descriptors used', labels, :livesum)
+ metrics[:memory_usage] = ::Gitlab::Metrics.gauge(with_prefix(:memory, :bytes), 'Memory used', labels, :livesum)
+ metrics[:file_descriptors] = ::Gitlab::Metrics.gauge(with_prefix(:file, :descriptors), 'File descriptors used', labels, :livesum)
metrics
end
diff --git a/lib/gitlab/metrics/samplers/unicorn_sampler.rb b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
index 4c4ec026823..bec64e864b3 100644
--- a/lib/gitlab/metrics/samplers/unicorn_sampler.rb
+++ b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
@@ -9,11 +9,11 @@ module Gitlab
end
def unicorn_active_connections
- @unicorn_active_connections ||= Gitlab::Metrics.gauge(:unicorn_active_connections, 'Unicorn active connections', {}, :max)
+ @unicorn_active_connections ||= ::Gitlab::Metrics.gauge(:unicorn_active_connections, 'Unicorn active connections', {}, :max)
end
def unicorn_queued_connections
- @unicorn_queued_connections ||= Gitlab::Metrics.gauge(:unicorn_queued_connections, 'Unicorn queued connections', {}, :max)
+ @unicorn_queued_connections ||= ::Gitlab::Metrics.gauge(:unicorn_queued_connections, 'Unicorn queued connections', {}, :max)
end
def enabled?
@@ -23,13 +23,13 @@ module Gitlab
def sample
Raindrops::Linux.tcp_listener_stats(tcp_listeners).each do |addr, stats|
- unicorn_active_connections.set({ type: 'tcp', address: addr }, stats.active)
- unicorn_queued_connections.set({ type: 'tcp', address: addr }, stats.queued)
+ unicorn_active_connections.set({ socket_type: 'tcp', socket_address: addr }, stats.active)
+ unicorn_queued_connections.set({ socket_type: 'tcp', socket_address: addr }, stats.queued)
end
Raindrops::Linux.unix_listener_stats(unix_listeners).each do |addr, stats|
- unicorn_active_connections.set({ type: 'unix', address: addr }, stats.active)
- unicorn_queued_connections.set({ type: 'unix', address: addr }, stats.queued)
+ unicorn_active_connections.set({ socket_type: 'unix', socket_address: addr }, stats.active)
+ unicorn_queued_connections.set({ socket_type: 'unix', socket_address: addr }, stats.queued)
end
end
diff --git a/lib/gitlab/metrics/sidekiq_metrics_exporter.rb b/lib/gitlab/metrics/sidekiq_metrics_exporter.rb
index 56e106b9612..71a5406815f 100644
--- a/lib/gitlab/metrics/sidekiq_metrics_exporter.rb
+++ b/lib/gitlab/metrics/sidekiq_metrics_exporter.rb
@@ -9,7 +9,7 @@ module Gitlab
LOG_FILENAME = File.join(Rails.root, 'log', 'sidekiq_exporter.log')
def enabled?
- Gitlab::Metrics.metrics_folder_present? && settings.enabled
+ ::Gitlab::Metrics.metrics_folder_present? && settings.enabled
end
def settings
diff --git a/lib/gitlab/metrics/subscribers/rails_cache.rb b/lib/gitlab/metrics/subscribers/rails_cache.rb
index f633e1a9d7c..01db507761b 100644
--- a/lib/gitlab/metrics/subscribers/rails_cache.rb
+++ b/lib/gitlab/metrics/subscribers/rails_cache.rb
@@ -64,7 +64,7 @@ module Gitlab
end
def metric_cache_operation_duration_seconds
- @metric_cache_operation_duration_seconds ||= Gitlab::Metrics.histogram(
+ @metric_cache_operation_duration_seconds ||= ::Gitlab::Metrics.histogram(
:gitlab_cache_operation_duration_seconds,
'Cache access time',
Transaction::BASE_LABELS.merge({ action: nil }),
@@ -73,7 +73,7 @@ module Gitlab
end
def metric_cache_misses_total
- @metric_cache_misses_total ||= Gitlab::Metrics.counter(
+ @metric_cache_misses_total ||= ::Gitlab::Metrics.counter(
:gitlab_cache_misses_total,
'Cache read miss',
Transaction::BASE_LABELS
diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb
index 468d7cb56fc..e91803ecd62 100644
--- a/lib/gitlab/metrics/transaction.rb
+++ b/lib/gitlab/metrics/transaction.rb
@@ -64,7 +64,7 @@ module Gitlab
end
def add_metric(series, values, tags = {})
- @metrics << Metric.new("#{Metrics.series_prefix}#{series}", values, tags)
+ @metrics << Metric.new("#{::Gitlab::Metrics.series_prefix}#{series}", values, tags)
end
# Tracks a business level event
@@ -127,7 +127,7 @@ module Gitlab
hash
end
- Metrics.submit_metrics(submit_hashes)
+ ::Gitlab::Metrics.submit_metrics(submit_hashes)
end
def labels
diff --git a/lib/gitlab/middleware/basic_health_check.rb b/lib/gitlab/middleware/basic_health_check.rb
index f2a03217098..acf8c301b8f 100644
--- a/lib/gitlab/middleware/basic_health_check.rb
+++ b/lib/gitlab/middleware/basic_health_check.rb
@@ -24,7 +24,7 @@ module Gitlab
def call(env)
return @app.call(env) unless env['PATH_INFO'] == HEALTH_PATH
- request = Rack::Request.new(env)
+ request = ActionDispatch::Request.new(env)
return OK_RESPONSE if client_ip_whitelisted?(request)
diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb
index d1a87c3b3bb..f9efef38825 100644
--- a/lib/gitlab/middleware/go.rb
+++ b/lib/gitlab/middleware/go.rb
@@ -6,6 +6,7 @@ module Gitlab
module Middleware
class Go
include ActionView::Helpers::TagHelper
+ include ActionController::HttpAuthentication::Basic
PROJECT_PATH_REGEX = %r{\A(#{Gitlab::PathRegex.full_namespace_route_regex}/#{Gitlab::PathRegex.project_route_regex})/}.freeze
@@ -14,7 +15,7 @@ module Gitlab
end
def call(env)
- request = Rack::Request.new(env)
+ request = ActionDispatch::Request.new(env)
render_go_doc(request) || @app.call(env)
end
@@ -110,21 +111,23 @@ module Gitlab
def project_for_paths(paths, request)
project = Project.where_full_path_in(paths).first
- return unless Ability.allowed?(current_user(request), :read_project, project)
+ return unless Ability.allowed?(current_user(request, project), :read_project, project)
project
end
- def current_user(request)
- authenticator = Gitlab::Auth::RequestAuthenticator.new(request)
- user = authenticator.find_user_from_access_token || authenticator.find_user_from_warden
+ def current_user(request, project)
+ return unless has_basic_credentials?(request)
- return unless user&.can?(:access_api)
+ login, password = user_name_and_password(request)
+ auth_result = Gitlab::Auth.find_for_git_client(login, password, project: project, ip: request.ip)
+ return unless auth_result.success?
- # Right now, the `api` scope is the only one that should be able to determine private project existence.
- return unless authenticator.valid_access_token?(scopes: [:api])
+ return unless auth_result.actor&.can?(:access_git)
- user
+ return unless auth_result.authentication_abilities.include?(:read_project)
+
+ auth_result.actor
end
end
end
diff --git a/lib/gitlab/middleware/multipart.rb b/lib/gitlab/middleware/multipart.rb
index 84c2f0d5720..433151b80e7 100644
--- a/lib/gitlab/middleware/multipart.rb
+++ b/lib/gitlab/middleware/multipart.rb
@@ -32,7 +32,7 @@ module Gitlab
class Handler
def initialize(env, message)
- @request = Rack::Request.new(env)
+ @request = ActionDispatch::Request.new(env)
@rewritten_fields = message['rewritten_fields']
@open_files = []
end
diff --git a/lib/gitlab/middleware/rails_queue_duration.rb b/lib/gitlab/middleware/rails_queue_duration.rb
index 96c6a0a7d28..a147e165262 100644
--- a/lib/gitlab/middleware/rails_queue_duration.rb
+++ b/lib/gitlab/middleware/rails_queue_duration.rb
@@ -7,6 +7,8 @@
module Gitlab
module Middleware
class RailsQueueDuration
+ GITLAB_RAILS_QUEUE_DURATION_KEY = 'GITLAB_RAILS_QUEUE_DURATION'
+
def initialize(app)
@app = app
end
@@ -19,6 +21,7 @@ module Gitlab
duration = Time.now.to_f * 1_000 - proxy_start.to_f / 1_000_000
trans.set(:rails_queue_duration, duration)
metric_rails_queue_duration_seconds.observe(trans.labels, duration / 1_000)
+ env[GITLAB_RAILS_QUEUE_DURATION_KEY] = duration.round(2)
end
@app.call(env)
diff --git a/lib/gitlab/middleware/read_only/controller.rb b/lib/gitlab/middleware/read_only/controller.rb
index 89941a9efa0..817db12ac55 100644
--- a/lib/gitlab/middleware/read_only/controller.rb
+++ b/lib/gitlab/middleware/read_only/controller.rb
@@ -60,7 +60,7 @@ module Gitlab
end
def request
- @env['rack.request'] ||= Rack::Request.new(@env)
+ @env['actionpack.request'] ||= ActionDispatch::Request.new(@env)
end
def last_visited_url
@@ -71,12 +71,16 @@ module Gitlab
@route_hash ||= Rails.application.routes.recognize_path(request.url, { method: request.request_method }) rescue {}
end
+ def relative_url
+ File.join('', Gitlab.config.gitlab.relative_url_root).chomp('/')
+ end
+
# Overridden in EE module
def whitelisted_routes
- grack_route || ReadOnly.internal_routes.any? { |path| request.path.include?(path) } || lfs_route || sidekiq_route
+ grack_route? || internal_route? || lfs_route? || sidekiq_route?
end
- def grack_route
+ def grack_route?
# Calling route_hash may be expensive. Only do it if we think there's a possible match
return false unless
request.path.end_with?('.git/git-upload-pack', '.git/git-receive-pack')
@@ -84,7 +88,11 @@ module Gitlab
WHITELISTED_GIT_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
end
- def lfs_route
+ def internal_route?
+ ReadOnly.internal_routes.any? { |path| request.path.include?(path) }
+ end
+
+ def lfs_route?
# Calling route_hash may be expensive. Only do it if we think there's a possible match
unless request.path.end_with?('/info/lfs/objects/batch',
'/info/lfs/locks', '/info/lfs/locks/verify') ||
@@ -95,8 +103,8 @@ module Gitlab
WHITELISTED_GIT_LFS_ROUTES[route_hash[:controller]]&.include?(route_hash[:action])
end
- def sidekiq_route
- request.path.start_with?('/admin/sidekiq')
+ def sidekiq_route?
+ request.path.start_with?("#{relative_url}/admin/sidekiq")
end
end
end
diff --git a/lib/gitlab/pages_client.rb b/lib/gitlab/pages_client.rb
index 3626e53f84c..d74fdba2241 100644
--- a/lib/gitlab/pages_client.rb
+++ b/lib/gitlab/pages_client.rb
@@ -103,7 +103,7 @@ module Gitlab
end
def write_token(new_token)
- Tempfile.open(File.basename(token_path), File.dirname(token_path), encoding: 'ascii-8bit') do |f|
+ Tempfile.open(File.basename(token_path), File.dirname(token_path), encoding: 'ascii-8bit') do |f|
f.write(new_token)
f.close
File.link(f.path, token_path)
diff --git a/lib/gitlab/patch/sprockets_base_file_digest_key.rb b/lib/gitlab/patch/sprockets_base_file_digest_key.rb
new file mode 100644
index 00000000000..1c472638145
--- /dev/null
+++ b/lib/gitlab/patch/sprockets_base_file_digest_key.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+# This monkey patch prevent cache ballooning when caching tmp/cache/assets/sprockets
+# on the CI. See https://github.com/rails/sprockets/issues/563 and
+# https://github.com/rails/sprockets/compare/3.x...jmreid:no-mtime-for-digest-key.
+module Gitlab
+ module Patch
+ module SprocketsBaseFileDigestKey
+ def file_digest(path)
+ if stat = self.stat(path)
+ digest = self.stat_digest(path, stat)
+ integrity_uri = self.integrity_uri(digest)
+
+ key = Sprockets::UnloadedAsset.new(path, self).file_digest_key(integrity_uri)
+ cache.fetch(key) do
+ digest
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb
index fa68dead80b..3c888be0710 100644
--- a/lib/gitlab/path_regex.rb
+++ b/lib/gitlab/path_regex.rb
@@ -125,7 +125,8 @@ module Gitlab
# allow non-regex validations, etc), `NAMESPACE_FORMAT_REGEX_JS` serves as a Javascript-compatible version of
# `NAMESPACE_FORMAT_REGEX`, with the negative lookbehind assertion removed. This means that the client-side validation
# will pass for usernames ending in `.atom` and `.git`, but will be caught by the server-side validation.
- PATH_REGEX_STR = '[a-zA-Z0-9_\.][a-zA-Z0-9_\-\.]*'.freeze
+ PATH_START_CHAR = '[a-zA-Z0-9_\.]'.freeze
+ PATH_REGEX_STR = PATH_START_CHAR + '[a-zA-Z0-9_\-\.]*'.freeze
NAMESPACE_FORMAT_REGEX_JS = PATH_REGEX_STR + '[a-zA-Z0-9_\-]|[a-zA-Z0-9_]'.freeze
NO_SUFFIX_REGEX = /(?<!\.git|\.atom)/.freeze
diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb
index 3bfd6ee892c..9b6ff602fcd 100644
--- a/lib/gitlab/project_template.rb
+++ b/lib/gitlab/project_template.rb
@@ -2,14 +2,12 @@
module Gitlab
class ProjectTemplate
- attr_reader :title, :name, :description, :preview
+ attr_reader :title, :name, :description, :preview, :logo
- def initialize(name, title, description, preview)
- @name, @title, @description, @preview = name, title, description, preview
+ def initialize(name, title, description, preview, logo = 'illustrations/gitlab_logo.svg')
+ @name, @title, @description, @preview, @logo = name, title, description, preview, logo
end
- alias_method :logo, :name
-
def file
archive_path.open
end
@@ -27,9 +25,21 @@ module Gitlab
end
TEMPLATES_TABLE = [
- ProjectTemplate.new('rails', 'Ruby on Rails', 'Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/rails'),
- 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'),
- ProjectTemplate.new('express', 'NodeJS Express', 'Includes an MVC structure to help you get started.', 'https://gitlab.com/gitlab-org/project-templates/express')
+ ProjectTemplate.new('rails', 'Ruby on Rails', _('Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started.'), 'https://gitlab.com/gitlab-org/project-templates/rails', 'illustrations/logos/rails.svg'),
+ 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('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('gomicro', 'Go Micro', _('Go Micro is a framework for micro service development.'), 'https://gitlab.com/gitlab-org/project-templates/go-micro'),
+ ProjectTemplate.new('hugo', 'Pages/Hugo', _('Everything you need to create a GitLab Pages site using Hugo.'), 'https://gitlab.com/pages/hugo'),
+ ProjectTemplate.new('jekyll', 'Pages/Jekyll', _('Everything you need to create a GitLab Pages site using Jekyll.'), 'https://gitlab.com/pages/jekyll'),
+ ProjectTemplate.new('plainhtml', 'Pages/Plain HTML', _('Everything you need to create a GitLab Pages site using plain HTML.'), 'https://gitlab.com/pages/plain-html'),
+ ProjectTemplate.new('gitbook', 'Pages/GitBook', _('Everything you need to create a GitLab Pages site using GitBook.'), 'https://gitlab.com/pages/gitbook'),
+ ProjectTemplate.new('hexo', 'Pages/Hexo', _('Everything you need to create a GitLab Pages site using Hexo.'), 'https://gitlab.com/pages/hexo'),
+ ProjectTemplate.new('nfhugo', 'Netlify/Hugo', _('A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfhugo', 'illustrations/logos/netlify.svg'),
+ ProjectTemplate.new('nfjekyll', 'Netlify/Jekyll', _('A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfjekyll', 'illustrations/logos/netlify.svg'),
+ ProjectTemplate.new('nfplainhtml', 'Netlify/Plain HTML', _('A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfplain-html', 'illustrations/logos/netlify.svg'),
+ ProjectTemplate.new('nfgitbook', 'Netlify/GitBook', _('A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfgitbook', 'illustrations/logos/netlify.svg'),
+ ProjectTemplate.new('nfhexo', 'Netlify/Hexo', _('A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfhexo', 'illustrations/logos/netlify.svg')
].freeze
class << self
diff --git a/lib/gitlab/prometheus/metric_group.rb b/lib/gitlab/prometheus/metric_group.rb
index 8f30cdee232..394556e8708 100644
--- a/lib/gitlab/prometheus/metric_group.rb
+++ b/lib/gitlab/prometheus/metric_group.rb
@@ -10,9 +10,15 @@ module Gitlab
validates :name, :priority, :metrics, presence: true
def self.common_metrics
- ::PrometheusMetric.common.group_by(&:group_title).map do |name, metrics|
- MetricGroup.new(name: name, priority: 0, metrics: metrics.map(&:to_query_metric))
+ all_groups = ::PrometheusMetric.common.group_by(&:group_title).map do |name, metrics|
+ MetricGroup.new(
+ name: name,
+ priority: metrics.map(&:priority).max,
+ metrics: metrics.map(&:to_query_metric)
+ )
end
+
+ all_groups.sort_by(&:priority).reverse
end
# EE only
diff --git a/lib/gitlab/quick_actions/command_definition.rb b/lib/gitlab/quick_actions/command_definition.rb
index 259345b8a9a..e7bfcb16582 100644
--- a/lib/gitlab/quick_actions/command_definition.rb
+++ b/lib/gitlab/quick_actions/command_definition.rb
@@ -48,6 +48,8 @@ module Gitlab
def execute(context, arg)
return if noop? || !available?(context)
+ count_commands_executed_in(context)
+
execute_block(action_block, context, arg)
end
@@ -73,6 +75,13 @@ module Gitlab
private
+ def count_commands_executed_in(context)
+ return unless context.respond_to?(:commands_executed_count=)
+
+ context.commands_executed_count ||= 0
+ context.commands_executed_count += 1
+ end
+
def execute_block(block, context, arg)
if arg.present?
parsed = parse_params(arg, context)
diff --git a/lib/gitlab/repository_cache.rb b/lib/gitlab/repository_cache.rb
index 6b0808f5304..56007574b1b 100644
--- a/lib/gitlab/repository_cache.rb
+++ b/lib/gitlab/repository_cache.rb
@@ -7,13 +7,13 @@ module Gitlab
def initialize(repository, extra_namespace: nil, backend: Rails.cache)
@repository = repository
- @namespace = "project:#{repository.project.id}"
+ @namespace = "#{repository.full_path}:#{repository.project.id}"
@namespace = "#{@namespace}:#{extra_namespace}" if extra_namespace
@backend = backend
end
def cache_key(type)
- "#{namespace}:#{type}"
+ "#{type}:#{namespace}"
end
def expire(key)
diff --git a/lib/gitlab/request_context.rb b/lib/gitlab/request_context.rb
index f8f8ec789ce..d9811e036d3 100644
--- a/lib/gitlab/request_context.rb
+++ b/lib/gitlab/request_context.rb
@@ -13,7 +13,7 @@ module Gitlab
end
def call(env)
- req = Rack::Request.new(env)
+ req = ActionDispatch::Request.new(env)
Gitlab::SafeRequestStore[:client_ip] = req.ip
diff --git a/lib/gitlab/seeder.rb b/lib/gitlab/seeder.rb
index 84a51773276..8e2f16271eb 100644
--- a/lib/gitlab/seeder.rb
+++ b/lib/gitlab/seeder.rb
@@ -26,6 +26,19 @@ module Gitlab
puts "\nOK".color(:green)
end
+ def self.without_gitaly_timeout
+ # Remove Gitaly timeout
+ old_timeout = Gitlab::CurrentSettings.current_application_settings.gitaly_timeout_default
+ Gitlab::CurrentSettings.current_application_settings.update_columns(gitaly_timeout_default: 0)
+ # Otherwise we still see the default value when running seed_fu
+ ApplicationSetting.expire
+
+ yield
+ ensure
+ Gitlab::CurrentSettings.current_application_settings.update_columns(gitaly_timeout_default: old_timeout)
+ ApplicationSetting.expire
+ end
+
def self.mute_notifications
NotificationService.prepend(MuteNotifications)
end
diff --git a/lib/gitlab/sentry.rb b/lib/gitlab/sentry.rb
index 46d01964eac..956c16117f5 100644
--- a/lib/gitlab/sentry.rb
+++ b/lib/gitlab/sentry.rb
@@ -52,14 +52,6 @@ module Gitlab
end
end
- def self.program_context
- if Sidekiq.server?
- 'sidekiq'
- else
- 'rails'
- end
- end
-
def self.should_raise_for_dev?
Rails.env.development? || Rails.env.test?
end
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index c6a6fb9b5ce..40b641b8317 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -64,27 +64,48 @@ module Gitlab
end
end
+ # Convenience methods for initializing a new repository with a Project model.
+ def create_project_repository(project)
+ create_repository(project.repository_storage, project.disk_path, project.full_path)
+ end
+
+ def create_wiki_repository(project)
+ create_repository(project.repository_storage, project.wiki.disk_path, project.wiki.full_path)
+ end
+
# Init new repository
#
# storage - the shard key
- # name - project disk path
+ # disk_path - project disk path
+ # gl_project_path - project name
#
# Ex.
- # create_repository("default", "gitlab/gitlab-ci")
+ # create_repository("default", "path/to/gitlab-ci", "gitlab/gitlab-ci")
#
- def create_repository(storage, name)
- relative_path = name.dup
+ def create_repository(storage, disk_path, gl_project_path)
+ relative_path = disk_path.dup
relative_path << '.git' unless relative_path.end_with?('.git')
- repository = Gitlab::Git::Repository.new(storage, relative_path, '')
+ # During creation of a repository, gl_repository may not be known
+ # because that depends on a yet-to-be assigned project ID in the
+ # database (e.g. project-1234), so for now it is blank.
+ repository = Gitlab::Git::Repository.new(storage, relative_path, '', gl_project_path)
wrapped_gitaly_errors { repository.gitaly_repository_client.create_repository }
true
rescue => err # Once the Rugged codes gets removes this can be improved
- Rails.logger.error("Failed to add repository #{storage}/#{name}: #{err}")
+ Rails.logger.error("Failed to add repository #{storage}/#{disk_path}: #{err}")
false
end
+ def import_wiki_repository(project, wiki_formatter)
+ import_repository(project.repository_storage, wiki_formatter.disk_path, wiki_formatter.import_url, project.wiki.full_path)
+ end
+
+ def import_project_repository(project)
+ import_repository(project.repository_storage, project.disk_path, project.import_url, project.full_path)
+ end
+
# Import repository
#
# storage - project's storage name
@@ -94,13 +115,13 @@ module Gitlab
# Ex.
# import_repository("nfs-file06", "gitlab/gitlab-ci", "https://gitlab.com/gitlab-org/gitlab-test.git")
#
- def import_repository(storage, name, url)
+ def import_repository(storage, name, url, gl_project_path)
if url.start_with?('.', '/')
raise Error.new("don't use disk paths with import_repository: #{url.inspect}")
end
relative_path = "#{name}.git"
- cmd = GitalyGitlabProjects.new(storage, relative_path)
+ cmd = GitalyGitlabProjects.new(storage, relative_path, gl_project_path)
success = cmd.import_project(url, git_timeout)
raise Error, cmd.output unless success
@@ -125,18 +146,13 @@ module Gitlab
end
# Fork repository to new path
- # forked_from_storage - forked-from project's storage name
- # forked_from_disk_path - project disk relative path
- # forked_to_storage - forked-to project's storage name
- # forked_to_disk_path - forked project disk relative path
- #
- # Ex.
- # fork_repository("nfs-file06", "gitlab/gitlab-ci", "nfs-file07", "new-namespace/gitlab-ci")
- def fork_repository(forked_from_storage, forked_from_disk_path, forked_to_storage, forked_to_disk_path)
- forked_from_relative_path = "#{forked_from_disk_path}.git"
- fork_args = [forked_to_storage, "#{forked_to_disk_path}.git"]
+ # source_project - forked-from Project
+ # target_project - forked-to Project
+ def fork_repository(source_project, target_project)
+ forked_from_relative_path = "#{source_project.disk_path}.git"
+ fork_args = [target_project.repository_storage, "#{target_project.disk_path}.git", target_project.full_path]
- GitalyGitlabProjects.new(forked_from_storage, forked_from_relative_path).fork_repository(*fork_args)
+ GitalyGitlabProjects.new(source_project.repository_storage, forked_from_relative_path, source_project.full_path).fork_repository(*fork_args)
end
# Removes a repository from file system, using rm_diretory which is an alias
@@ -264,7 +280,10 @@ module Gitlab
# add_namespace("default", "gitlab")
#
def add_namespace(storage, name)
- Gitlab::GitalyClient::NamespaceService.new(storage).add(name)
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/58012
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ Gitlab::GitalyClient::NamespaceService.new(storage).add(name)
+ end
rescue GRPC::InvalidArgument => e
raise ArgumentError, e.message
end
@@ -289,10 +308,12 @@ module Gitlab
#
def mv_namespace(storage, old_name, new_name)
Gitlab::GitalyClient::NamespaceService.new(storage).rename(old_name, new_name)
- rescue GRPC::InvalidArgument
+ rescue GRPC::InvalidArgument => e
+ Gitlab::Sentry.track_acceptable_exception(e, extra: { old_name: old_name, new_name: new_name, storage: storage })
+
false
end
- alias_method :mv_directory, :mv_namespace
+ alias_method :mv_directory, :mv_namespace # Note: ShellWorker uses this alias
def url_to_repo(path)
Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git"
@@ -319,16 +340,16 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
+ def hooks_path
+ File.join(gitlab_shell_path, 'hooks')
+ end
+
protected
def gitlab_shell_path
File.expand_path(Gitlab.config.gitlab_shell.path)
end
- def gitlab_shell_hooks_path
- File.expand_path(Gitlab.config.gitlab_shell.hooks_path)
- end
-
def gitlab_shell_user_home
File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}")
end
@@ -395,16 +416,17 @@ module Gitlab
end
class GitalyGitlabProjects
- attr_reader :shard_name, :repository_relative_path, :output
+ attr_reader :shard_name, :repository_relative_path, :output, :gl_project_path
- def initialize(shard_name, repository_relative_path)
+ def initialize(shard_name, repository_relative_path, gl_project_path)
@shard_name = shard_name
@repository_relative_path = repository_relative_path
@output = ''
+ @gl_project_path = gl_project_path
end
def import_project(source, _timeout)
- raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil)
+ raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil, gl_project_path)
Gitlab::GitalyClient::RepositoryService.new(raw_repository).import_repository(source)
true
@@ -413,9 +435,9 @@ module Gitlab
false
end
- def fork_repository(new_shard_name, new_repository_relative_path)
- target_repository = Gitlab::Git::Repository.new(new_shard_name, new_repository_relative_path, nil)
- raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil)
+ def fork_repository(new_shard_name, new_repository_relative_path, new_project_name)
+ target_repository = Gitlab::Git::Repository.new(new_shard_name, new_repository_relative_path, nil, new_project_name)
+ raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil, gl_project_path)
Gitlab::GitalyClient::RepositoryService.new(target_repository).fork_repository(raw_repository)
rescue GRPC::BadStatus => e
diff --git a/lib/gitlab/sidekiq_logging/structured_logger.rb b/lib/gitlab/sidekiq_logging/structured_logger.rb
index e86db8db3a1..fdc0d518c59 100644
--- a/lib/gitlab/sidekiq_logging/structured_logger.rb
+++ b/lib/gitlab/sidekiq_logging/structured_logger.rb
@@ -5,6 +5,7 @@ module Gitlab
class StructuredLogger
START_TIMESTAMP_FIELDS = %w[created_at enqueued_at].freeze
DONE_TIMESTAMP_FIELDS = %w[started_at retried_at failed_at completed_at].freeze
+ MAXIMUM_JOB_ARGUMENTS_LENGTH = 10.kilobytes
def call(job, queue)
started_at = current_time
@@ -64,6 +65,7 @@ module Gitlab
job['pid'] = ::Process.pid
job.delete('args') unless ENV['SIDEKIQ_LOG_ARGUMENTS']
+ job['args'] = limited_job_args(job['args']) if job['args']
convert_to_iso8601(job, START_TIMESTAMP_FIELDS)
@@ -93,6 +95,21 @@ module Gitlab
Time.at(timestamp).utc.iso8601(3)
end
+
+ def limited_job_args(args)
+ return unless args.is_a?(Array)
+
+ total_length = 0
+ limited_args = args.take_while do |arg|
+ total_length += arg.to_json.length
+
+ total_length <= MAXIMUM_JOB_ARGUMENTS_LENGTH
+ end
+
+ limited_args.push('...') if total_length > MAXIMUM_JOB_ARGUMENTS_LENGTH
+
+ limited_args
+ end
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/memory_killer.rb b/lib/gitlab/sidekiq_middleware/memory_killer.rb
new file mode 100644
index 00000000000..ed2c7ee9a2d
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/memory_killer.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqMiddleware
+ class MemoryKiller
+ # Default the RSS limit to 0, meaning the MemoryKiller is disabled
+ MAX_RSS = (ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS'] || 0).to_s.to_i
+ # Give Sidekiq 15 minutes of grace time after exceeding the RSS limit
+ GRACE_TIME = (ENV['SIDEKIQ_MEMORY_KILLER_GRACE_TIME'] || 15 * 60).to_s.to_i
+ # Wait 30 seconds for running jobs to finish during graceful shutdown
+ SHUTDOWN_WAIT = (ENV['SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT'] || 30).to_s.to_i
+
+ # Create a mutex used to ensure there will be only one thread waiting to
+ # shut Sidekiq down
+ MUTEX = Mutex.new
+
+ def call(worker, job, queue)
+ yield
+
+ current_rss = get_rss
+
+ return unless MAX_RSS > 0 && current_rss > MAX_RSS
+
+ Thread.new do
+ # Return if another thread is already waiting to shut Sidekiq down
+ next unless MUTEX.try_lock
+
+ Sidekiq.logger.warn "Sidekiq worker PID-#{pid} current RSS #{current_rss}"\
+ " exceeds maximum RSS #{MAX_RSS} after finishing job #{worker.class} JID-#{job['jid']}"
+ Sidekiq.logger.warn "Sidekiq worker PID-#{pid} will stop fetching new jobs in #{GRACE_TIME} seconds, and will be shut down #{SHUTDOWN_WAIT} seconds later"
+
+ # Wait `GRACE_TIME` to give the memory intensive job time to finish.
+ # Then, tell Sidekiq to stop fetching new jobs.
+ wait_and_signal(GRACE_TIME, 'SIGTSTP', 'stop fetching new jobs')
+
+ # Wait `SHUTDOWN_WAIT` to give already fetched jobs time to finish.
+ # Then, tell Sidekiq to gracefully shut down by giving jobs a few more
+ # moments to finish, killing and requeuing them if they didn't, and
+ # then terminating itself. Sidekiq will replicate the TERM to all its
+ # children if it can.
+ wait_and_signal(SHUTDOWN_WAIT, 'SIGTERM', 'gracefully shut down')
+
+ # Wait for Sidekiq to shutdown gracefully, and kill it if it didn't.
+ # Kill the whole pgroup, so we can be sure no children are left behind
+ wait_and_signal_pgroup(Sidekiq.options[:timeout] + 2, 'SIGKILL', 'die')
+ end
+ end
+
+ private
+
+ def get_rss
+ output, status = Gitlab::Popen.popen(%W(ps -o rss= -p #{pid}), Rails.root.to_s)
+ return 0 unless status.zero?
+
+ output.to_i
+ end
+
+ # If this sidekiq process is pgroup leader, signal to the whole pgroup
+ def wait_and_signal_pgroup(time, signal, explanation)
+ return wait_and_signal(time, signal, explanation) unless Process.getpgrp == pid
+
+ Sidekiq.logger.warn "waiting #{time} seconds before sending Sidekiq worker PGRP-#{pid} #{signal} (#{explanation})"
+ sleep(time)
+
+ Sidekiq.logger.warn "sending Sidekiq worker PGRP-#{pid} #{signal} (#{explanation})"
+ Process.kill(signal, "-#{pid}")
+ end
+
+ def wait_and_signal(time, signal, explanation)
+ Sidekiq.logger.warn "waiting #{time} seconds before sending Sidekiq worker PID-#{pid} #{signal} (#{explanation})"
+ sleep(time)
+
+ Sidekiq.logger.warn "sending Sidekiq worker PID-#{pid} #{signal} (#{explanation})"
+ Process.kill(signal, pid)
+ end
+
+ def pid
+ Process.pid
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/shutdown.rb b/lib/gitlab/sidekiq_middleware/shutdown.rb
deleted file mode 100644
index 19f3be83bce..00000000000
--- a/lib/gitlab/sidekiq_middleware/shutdown.rb
+++ /dev/null
@@ -1,135 +0,0 @@
-# frozen_string_literal: true
-
-require 'mutex_m'
-
-module Gitlab
- module SidekiqMiddleware
- class Shutdown
- extend Mutex_m
-
- # Default the RSS limit to 0, meaning the MemoryKiller is disabled
- MAX_RSS = (ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS'] || 0).to_s.to_i
- # Give Sidekiq 15 minutes of grace time after exceeding the RSS limit
- GRACE_TIME = (ENV['SIDEKIQ_MEMORY_KILLER_GRACE_TIME'] || 15 * 60).to_s.to_i
- # Wait 30 seconds for running jobs to finish during graceful shutdown
- SHUTDOWN_WAIT = (ENV['SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT'] || 30).to_s.to_i
-
- # This exception can be used to request that the middleware start shutting down Sidekiq
- WantShutdown = Class.new(StandardError)
-
- ShutdownWithoutRaise = Class.new(WantShutdown)
- private_constant :ShutdownWithoutRaise
-
- # For testing only, to avoid race conditions (?) in Rspec mocks.
- attr_reader :trace
-
- # We store the shutdown thread in a class variable to ensure that there
- # can be only one shutdown thread in the process.
- def self.create_shutdown_thread
- mu_synchronize do
- break unless @shutdown_thread.nil?
-
- @shutdown_thread = Thread.new { yield }
- end
- end
-
- # For testing only: so we can wait for the shutdown thread to finish.
- def self.shutdown_thread
- mu_synchronize { @shutdown_thread }
- end
-
- # For testing only: so that we can reset the global state before each test.
- def self.clear_shutdown_thread
- mu_synchronize { @shutdown_thread = nil }
- end
-
- def initialize
- @trace = Queue.new if Rails.env.test?
- end
-
- def call(worker, job, queue)
- shutdown_exception = nil
-
- begin
- yield
- check_rss!
- rescue WantShutdown => ex
- shutdown_exception = ex
- end
-
- return unless shutdown_exception
-
- self.class.create_shutdown_thread do
- do_shutdown(worker, job, shutdown_exception)
- end
-
- raise shutdown_exception unless shutdown_exception.is_a?(ShutdownWithoutRaise)
- end
-
- private
-
- def do_shutdown(worker, job, shutdown_exception)
- Sidekiq.logger.warn "Sidekiq worker PID-#{pid} shutting down because of #{shutdown_exception} after job "\
- "#{worker.class} JID-#{job['jid']}"
- Sidekiq.logger.warn "Sidekiq worker PID-#{pid} will stop fetching new jobs in #{GRACE_TIME} seconds, and will be shut down #{SHUTDOWN_WAIT} seconds later"
-
- # Wait `GRACE_TIME` to give the memory intensive job time to finish.
- # Then, tell Sidekiq to stop fetching new jobs.
- wait_and_signal(GRACE_TIME, 'SIGTSTP', 'stop fetching new jobs')
-
- # Wait `SHUTDOWN_WAIT` to give already fetched jobs time to finish.
- # Then, tell Sidekiq to gracefully shut down by giving jobs a few more
- # moments to finish, killing and requeuing them if they didn't, and
- # then terminating itself.
- wait_and_signal(SHUTDOWN_WAIT, 'SIGTERM', 'gracefully shut down')
-
- # Wait for Sidekiq to shutdown gracefully, and kill it if it didn't.
- wait_and_signal(Sidekiq.options[:timeout] + 2, 'SIGKILL', 'die')
- end
-
- def check_rss!
- return unless MAX_RSS > 0
-
- current_rss = get_rss
- return unless current_rss > MAX_RSS
-
- raise ShutdownWithoutRaise.new("current RSS #{current_rss} exceeds maximum RSS #{MAX_RSS}")
- end
-
- def get_rss
- output, status = Gitlab::Popen.popen(%W(ps -o rss= -p #{pid}), Rails.root.to_s)
- return 0 unless status.zero?
-
- output.to_i
- end
-
- def wait_and_signal(time, signal, explanation)
- Sidekiq.logger.warn "waiting #{time} seconds before sending Sidekiq worker PID-#{pid} #{signal} (#{explanation})"
- sleep(time)
-
- Sidekiq.logger.warn "sending Sidekiq worker PID-#{pid} #{signal} (#{explanation})"
- kill(signal, pid)
- end
-
- def pid
- Process.pid
- end
-
- def sleep(time)
- if Rails.env.test?
- @trace << [:sleep, time]
- else
- Kernel.sleep(time)
- end
- end
-
- def kill(signal, pid)
- if Rails.env.test?
- @trace << [:kill, signal, pid]
- else
- Process.kill(signal, pid)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/sidekiq_signals.rb b/lib/gitlab/sidekiq_signals.rb
new file mode 100644
index 00000000000..b704ee9a0a9
--- /dev/null
+++ b/lib/gitlab/sidekiq_signals.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab
+ # As a process group leader, we can ensure that children of sidekiq are killed
+ # at the same time as sidekiq itself, to stop long-lived children from being
+ # reparented to init and "escaping". To do this, we override the default
+ # handlers used by sidekiq for INT and TERM signals
+ module SidekiqSignals
+ REPLACE_SIGNALS = %w[INT TERM].freeze
+
+ SIDEKIQ_CHANGED_MESSAGE =
+ "Intercepting signal handlers: #{REPLACE_SIGNALS.join(", ")} failed. " \
+ "Sidekiq should have registered them, but appears not to have done so."
+
+ def self.install!(sidekiq_handlers)
+ # This only works if we're process group leader
+ return unless Process.getpgrp == Process.pid
+
+ raise SIDEKIQ_CHANGED_MESSAGE unless
+ REPLACE_SIGNALS == sidekiq_handlers.keys & REPLACE_SIGNALS
+
+ REPLACE_SIGNALS.each do |signal|
+ old_handler = sidekiq_handlers[signal]
+ sidekiq_handlers[signal] = ->(cli) do
+ blindly_signal_pgroup!(signal)
+ old_handler.call(cli)
+ end
+ end
+ end
+
+ # The process group leader can forward INT and TERM signals to the whole
+ # group. However, the forwarded signal is *also* received by the leader,
+ # which could lead to an infinite loop. We can avoid this by temporarily
+ # ignoring the forwarded signal. This may cause us to miss some repeated
+ # signals from outside the process group, but that isn't fatal.
+ def self.blindly_signal_pgroup!(signal)
+ old_trap = trap(signal, 'IGNORE')
+ Process.kill(signal, "-#{Process.getpgrp}")
+ trap(signal, old_trap)
+ end
+ end
+end
diff --git a/lib/gitlab/slash_commands/application_help.rb b/lib/gitlab/slash_commands/application_help.rb
new file mode 100644
index 00000000000..0ea7554ba64
--- /dev/null
+++ b/lib/gitlab/slash_commands/application_help.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SlashCommands
+ class ApplicationHelp < BaseCommand
+ def initialize(params)
+ @params = params
+ end
+
+ def execute
+ Gitlab::SlashCommands::Presenters::Help.new(commands).present(trigger, params[:text])
+ end
+
+ private
+
+ def trigger
+ "#{params[:command]} [project name or alias]"
+ end
+
+ def commands
+ Gitlab::SlashCommands::Command.commands
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/slash_commands/command.rb b/lib/gitlab/slash_commands/command.rb
index 474c09b9c4d..7c963fcf38a 100644
--- a/lib/gitlab/slash_commands/command.rb
+++ b/lib/gitlab/slash_commands/command.rb
@@ -9,7 +9,8 @@ module Gitlab
Gitlab::SlashCommands::IssueNew,
Gitlab::SlashCommands::IssueSearch,
Gitlab::SlashCommands::IssueMove,
- Gitlab::SlashCommands::Deploy
+ Gitlab::SlashCommands::Deploy,
+ Gitlab::SlashCommands::Run
]
end
diff --git a/lib/gitlab/slash_commands/presenters/error.rb b/lib/gitlab/slash_commands/presenters/error.rb
new file mode 100644
index 00000000000..442f8796338
--- /dev/null
+++ b/lib/gitlab/slash_commands/presenters/error.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SlashCommands
+ module Presenters
+ class Error < Presenters::Base
+ def initialize(message)
+ @message = message
+ end
+
+ def message
+ ephemeral_response(text: @message)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/slash_commands/presenters/run.rb b/lib/gitlab/slash_commands/presenters/run.rb
new file mode 100644
index 00000000000..c4bbc231464
--- /dev/null
+++ b/lib/gitlab/slash_commands/presenters/run.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SlashCommands
+ module Presenters
+ class Run < Presenters::Base
+ # rubocop: disable CodeReuse/ActiveRecord
+ def present(pipeline)
+ build = pipeline.builds.take
+
+ if build && (responder = Chat::Responder.responder_for(build))
+ in_channel_response(responder.scheduled_output)
+ else
+ unsupported_chat_service
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def unsupported_chat_service
+ ephemeral_response(text: 'Sorry, this chat service is currently not supported by GitLab ChatOps.')
+ end
+
+ def failed_to_schedule(command)
+ ephemeral_response(
+ text: 'The command could not be scheduled. Make sure that your ' \
+ 'project has a .gitlab-ci.yml that defines a job with the ' \
+ "name #{command.inspect}"
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/slash_commands/run.rb b/lib/gitlab/slash_commands/run.rb
new file mode 100644
index 00000000000..10a545e28ac
--- /dev/null
+++ b/lib/gitlab/slash_commands/run.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SlashCommands
+ # Slash command for triggering chatops jobs.
+ class Run < BaseCommand
+ def self.match(text)
+ /\Arun\s+(?<command>\S+)(\s+(?<arguments>.+))?\z/.match(text)
+ end
+
+ def self.help_message
+ 'run <command> <arguments>'
+ end
+
+ def self.available?(project)
+ Chat.available? && project.builds_enabled?
+ end
+
+ def self.allowed?(project, user)
+ can?(user, :create_pipeline, project)
+ end
+
+ def execute(match)
+ command = Chat::Command.new(
+ project: project,
+ chat_name: chat_name,
+ name: match[:command],
+ arguments: match[:arguments],
+ channel: params[:channel_id],
+ response_url: params[:response_url]
+ )
+
+ presenter = Gitlab::SlashCommands::Presenters::Run.new
+ pipeline = command.try_create_pipeline
+
+ if pipeline&.persisted?
+ presenter.present(pipeline)
+ else
+ presenter.failed_to_schedule(command.name)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sql/pattern.rb b/lib/gitlab/sql/pattern.rb
index 92388262035..07d0acdbae9 100644
--- a/lib/gitlab/sql/pattern.rb
+++ b/lib/gitlab/sql/pattern.rb
@@ -33,7 +33,7 @@ module Gitlab
# `LOWER(column) = query` instead of using `ILIKE`.
def fuzzy_arel_match(column, query, lower_exact_match: false)
query = query.squish
- return nil unless query.present?
+ return unless query.present?
words = select_fuzzy_words(query)
diff --git a/lib/gitlab/sql/recursive_cte.rb b/lib/gitlab/sql/recursive_cte.rb
index ec1f00a3a91..e45ac5d4765 100644
--- a/lib/gitlab/sql/recursive_cte.rb
+++ b/lib/gitlab/sql/recursive_cte.rb
@@ -48,7 +48,7 @@ module Gitlab
#
# alias_table - The Arel table to use as the alias.
def alias_to(alias_table)
- Arel::Nodes::As.new(table, alias_table)
+ Arel::Nodes::As.new(table, Arel::Table.new(alias_table.name.tr('.', '_')))
end
# Applies the CTE to the given relation, returning a new one that will
diff --git a/lib/gitlab/sql/union.rb b/lib/gitlab/sql/union.rb
index d24d5116167..f05592fc3a3 100644
--- a/lib/gitlab/sql/union.rb
+++ b/lib/gitlab/sql/union.rb
@@ -9,7 +9,7 @@ module Gitlab
#
# Example usage:
#
- # union = Gitlab::SQL::Union.new(user.personal_projects, user.projects)
+ # union = Gitlab::SQL::Union.new([user.personal_projects, user.projects])
# sql = union.to_sql
#
# Project.where("id IN (#{sql})")
diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb
index 224bb648d8f..8532845f3cb 100644
--- a/lib/gitlab/task_helpers.rb
+++ b/lib/gitlab/task_helpers.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'rainbow/ext/string'
-require 'gitlab/utils/strong_memoize'
+require_dependency 'gitlab/utils/strong_memoize'
# rubocop:disable Rails/Output
module Gitlab
@@ -13,6 +13,12 @@ module Gitlab
extend self
+ def invoke_and_time_task(task)
+ start = Time.now
+ Rake::Task[task].invoke
+ puts "`#{task}` finished in #{Time.now - start} seconds"
+ end
+
# Ask if the user wants to continue
#
# Returns "yes" the user chose to continue
diff --git a/lib/gitlab/template/gitlab_ci_yml_template.rb b/lib/gitlab/template/gitlab_ci_yml_template.rb
index fbefb5f7f0e..3e2bb11c35f 100644
--- a/lib/gitlab/template/gitlab_ci_yml_template.rb
+++ b/lib/gitlab/template/gitlab_ci_yml_template.rb
@@ -28,11 +28,6 @@ module Gitlab
def finder(project = nil)
Gitlab::Template::Finders::GlobalTemplateFinder.new(self.base_dir, self.extension, self.categories)
end
-
- def dropdown_names(context)
- categories = context == 'autodeploy' ? ['Auto deploy'] : %w(General Pages)
- super().slice(*categories)
- end
end
end
end
diff --git a/lib/gitlab/tracing.rb b/lib/gitlab/tracing.rb
new file mode 100644
index 00000000000..29517591c51
--- /dev/null
+++ b/lib/gitlab/tracing.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracing
+ # Only enable tracing when the `GITLAB_TRACING` env var is configured. Note that we avoid using ApplicationSettings since
+ # the same environment variable needs to be configured for Workhorse, Gitaly and any other components which
+ # emit tracing. Since other components may start before Rails, and may not have access to ApplicationSettings,
+ # an env var makes more sense.
+ def self.enabled?
+ connection_string.present?
+ end
+
+ def self.connection_string
+ ENV['GITLAB_TRACING']
+ end
+
+ def self.tracing_url_template
+ ENV['GITLAB_TRACING_URL']
+ end
+
+ def self.tracing_url_enabled?
+ enabled? && tracing_url_template.present?
+ end
+
+ # This will provide a link into the distributed tracing for the current trace,
+ # if it has been captured.
+ def self.tracing_url
+ return unless tracing_url_enabled?
+
+ # Avoid using `format` since it can throw TypeErrors
+ # which we want to avoid on unsanitised env var input
+ tracing_url_template.to_s
+ .gsub(/\{\{\s*correlation_id\s*\}\}/, Gitlab::CorrelationId.current_id.to_s)
+ .gsub(/\{\{\s*service\s*\}\}/, Gitlab.process_name)
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/common.rb b/lib/gitlab/tracing/common.rb
new file mode 100644
index 00000000000..3a08ede8138
--- /dev/null
+++ b/lib/gitlab/tracing/common.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'opentracing'
+
+module Gitlab
+ module Tracing
+ module Common
+ def tracer
+ OpenTracing.global_tracer
+ end
+
+ # Convience method for running a block with a span
+ def in_tracing_span(operation_name:, tags:, child_of: nil)
+ scope = tracer.start_active_span(
+ operation_name,
+ child_of: child_of,
+ tags: tags
+ )
+ span = scope.span
+
+ # Add correlation details to the span if we have them
+ correlation_id = Gitlab::CorrelationId.current_id
+ if correlation_id
+ span.set_tag('correlation_id', correlation_id)
+ end
+
+ begin
+ yield span
+ rescue => e
+ log_exception_on_span(span, e)
+ raise e
+ ensure
+ scope.close
+ end
+ end
+
+ def postnotify_span(operation_name, start_time, end_time, tags: nil, child_of: nil, exception: nil)
+ span = OpenTracing.start_span(operation_name, start_time: start_time, tags: tags, child_of: child_of)
+
+ log_exception_on_span(span, exception) if exception
+
+ span.finish(end_time: end_time)
+ end
+
+ def log_exception_on_span(span, exception)
+ span.set_tag('error', true)
+ span.log_kv(kv_tags_for_exception(exception))
+ end
+
+ def kv_tags_for_exception(exception)
+ case exception
+ when Exception
+ {
+ 'event': 'error',
+ 'error.kind': exception.class.to_s,
+ 'message': Gitlab::UrlSanitizer.sanitize(exception.message),
+ 'stack': exception.backtrace&.join("\n")
+ }
+ else
+ {
+ 'event': 'error',
+ 'error.kind': exception.class.to_s,
+ 'error.object': Gitlab::UrlSanitizer.sanitize(exception.to_s)
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/factory.rb b/lib/gitlab/tracing/factory.rb
new file mode 100644
index 00000000000..fc714164353
--- /dev/null
+++ b/lib/gitlab/tracing/factory.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require "cgi"
+
+module Gitlab
+ module Tracing
+ class Factory
+ OPENTRACING_SCHEME = "opentracing"
+
+ def self.create_tracer(service_name, connection_string)
+ return unless connection_string.present?
+
+ begin
+ opentracing_details = parse_connection_string(connection_string)
+ driver_name = opentracing_details[:driver_name]
+
+ case driver_name
+ when "jaeger"
+ JaegerFactory.create_tracer(service_name, opentracing_details[:options])
+ else
+ raise "Unknown driver: #{driver_name}"
+ end
+ rescue => e
+ # Can't create the tracer? Warn and continue sans tracer
+ warn "Unable to instantiate tracer: #{e}"
+ nil
+ end
+ end
+
+ def self.parse_connection_string(connection_string)
+ parsed = URI.parse(connection_string)
+
+ unless valid_uri?(parsed)
+ raise "Invalid tracing connection string"
+ end
+
+ {
+ driver_name: parsed.host,
+ options: parse_query(parsed.query)
+ }
+ end
+ private_class_method :parse_connection_string
+
+ def self.parse_query(query)
+ return {} unless query
+
+ CGI.parse(query).symbolize_keys.transform_values(&:first)
+ end
+ private_class_method :parse_query
+
+ def self.valid_uri?(uri)
+ return false unless uri
+
+ uri.scheme == OPENTRACING_SCHEME &&
+ uri.host.to_s =~ /^[a-z0-9_]+$/ &&
+ uri.path.empty?
+ end
+ private_class_method :valid_uri?
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/grpc_interceptor.rb b/lib/gitlab/tracing/grpc_interceptor.rb
new file mode 100644
index 00000000000..6c2aab73125
--- /dev/null
+++ b/lib/gitlab/tracing/grpc_interceptor.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'opentracing'
+require 'grpc'
+
+module Gitlab
+ module Tracing
+ class GRPCInterceptor < GRPC::ClientInterceptor
+ include Common
+ include Singleton
+
+ def request_response(request:, call:, method:, metadata:)
+ wrap_with_tracing(method, 'unary', metadata) do
+ yield
+ end
+ end
+
+ def client_streamer(requests:, call:, method:, metadata:)
+ wrap_with_tracing(method, 'client_stream', metadata) do
+ yield
+ end
+ end
+
+ def server_streamer(request:, call:, method:, metadata:)
+ wrap_with_tracing(method, 'server_stream', metadata) do
+ yield
+ end
+ end
+
+ def bidi_streamer(requests:, call:, method:, metadata:)
+ wrap_with_tracing(method, 'bidi_stream', metadata) do
+ yield
+ end
+ end
+
+ private
+
+ def wrap_with_tracing(method, grpc_type, metadata)
+ tags = {
+ 'component' => 'grpc',
+ 'span.kind' => 'client',
+ 'grpc.method' => method,
+ 'grpc.type' => grpc_type
+ }
+
+ in_tracing_span(operation_name: "grpc:#{method}", tags: tags) do |span|
+ OpenTracing.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, metadata)
+
+ yield
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/jaeger_factory.rb b/lib/gitlab/tracing/jaeger_factory.rb
new file mode 100644
index 00000000000..93520d5667b
--- /dev/null
+++ b/lib/gitlab/tracing/jaeger_factory.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'jaeger/client'
+
+module Gitlab
+ module Tracing
+ class JaegerFactory
+ # When the probabilistic sampler is used, by default 0.1% of requests will be traced
+ DEFAULT_PROBABILISTIC_RATE = 0.001
+
+ # The default port for the Jaeger agent UDP listener
+ DEFAULT_UDP_PORT = 6831
+
+ # Reduce this from default of 10 seconds as the Ruby jaeger
+ # client doesn't have overflow control, leading to very large
+ # messages which fail to send over UDP (max packet = 64k)
+ # Flush more often, with smaller packets
+ FLUSH_INTERVAL = 5
+
+ def self.create_tracer(service_name, options)
+ kwargs = {
+ service_name: service_name,
+ sampler: get_sampler(options[:sampler], options[:sampler_param]),
+ reporter: get_reporter(service_name, options[:http_endpoint], options[:udp_endpoint])
+ }.compact
+
+ extra_params = options.except(:sampler, :sampler_param, :http_endpoint, :udp_endpoint, :strict_parsing, :debug) # rubocop: disable CodeReuse/ActiveRecord
+ if extra_params.present?
+ message = "jaeger tracer: invalid option: #{extra_params.keys.join(", ")}"
+
+ if options[:strict_parsing]
+ raise message
+ else
+ warn message
+ end
+ end
+
+ Jaeger::Client.build(kwargs)
+ end
+
+ def self.get_sampler(sampler_type, sampler_param)
+ case sampler_type
+ when "probabilistic"
+ sampler_rate = sampler_param ? sampler_param.to_f : DEFAULT_PROBABILISTIC_RATE
+ Jaeger::Samplers::Probabilistic.new(rate: sampler_rate)
+ when "const"
+ const_value = sampler_param == "1"
+ Jaeger::Samplers::Const.new(const_value)
+ else
+ nil
+ end
+ end
+ private_class_method :get_sampler
+
+ def self.get_reporter(service_name, http_endpoint, udp_endpoint)
+ encoder = Jaeger::Encoders::ThriftEncoder.new(service_name: service_name)
+
+ if http_endpoint.present?
+ sender = get_http_sender(encoder, http_endpoint)
+ elsif udp_endpoint.present?
+ sender = get_udp_sender(encoder, udp_endpoint)
+ else
+ return
+ end
+
+ Jaeger::Reporters::RemoteReporter.new(
+ sender: sender,
+ flush_interval: FLUSH_INTERVAL
+ )
+ end
+ private_class_method :get_reporter
+
+ def self.get_http_sender(encoder, address)
+ Jaeger::HttpSender.new(
+ url: address,
+ encoder: encoder,
+ logger: Logger.new(STDOUT)
+ )
+ end
+ private_class_method :get_http_sender
+
+ def self.get_udp_sender(encoder, address)
+ pair = address.split(":", 2)
+ host = pair[0]
+ port = pair[1] ? pair[1].to_i : DEFAULT_UDP_PORT
+
+ Jaeger::UdpSender.new(
+ host: host,
+ port: port,
+ encoder: encoder,
+ logger: Logger.new(STDOUT)
+ )
+ end
+ private_class_method :get_udp_sender
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/rack_middleware.rb b/lib/gitlab/tracing/rack_middleware.rb
new file mode 100644
index 00000000000..e6a31293f7b
--- /dev/null
+++ b/lib/gitlab/tracing/rack_middleware.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'opentracing'
+
+module Gitlab
+ module Tracing
+ class RackMiddleware
+ include Common
+
+ REQUEST_METHOD = 'REQUEST_METHOD'
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ method = env[REQUEST_METHOD]
+
+ context = tracer.extract(OpenTracing::FORMAT_RACK, env)
+ tags = {
+ 'component' => 'rack',
+ 'span.kind' => 'server',
+ 'http.method' => method,
+ 'http.url' => self.class.build_sanitized_url_from_env(env)
+ }
+
+ in_tracing_span(operation_name: "http:#{method}", child_of: context, tags: tags) do |span|
+ @app.call(env).tap do |status_code, _headers, _body|
+ span.set_tag('http.status_code', status_code)
+ end
+ end
+ end
+
+ # Generate a sanitized (safe) request URL from the rack environment
+ def self.build_sanitized_url_from_env(env)
+ request = ActionDispatch::Request.new(env)
+
+ original_url = request.original_url
+ uri = URI.parse(original_url)
+ uri.query = request.filtered_parameters.to_query if uri.query.present?
+
+ uri.to_s
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/rails/action_view_subscriber.rb b/lib/gitlab/tracing/rails/action_view_subscriber.rb
new file mode 100644
index 00000000000..88816e1fb32
--- /dev/null
+++ b/lib/gitlab/tracing/rails/action_view_subscriber.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracing
+ module Rails
+ class ActionViewSubscriber
+ include RailsCommon
+
+ COMPONENT_TAG = 'ActionView'
+ RENDER_TEMPLATE_NOTIFICATION_TOPIC = 'render_template.action_view'
+ RENDER_COLLECTION_NOTIFICATION_TOPIC = 'render_collection.action_view'
+ RENDER_PARTIAL_NOTIFICATION_TOPIC = 'render_partial.action_view'
+
+ # Instruments Rails ActionView events for opentracing.
+ # Returns a lambda, which, when called will unsubscribe from the notifications
+ def self.instrument
+ subscriber = new
+
+ subscriptions = [
+ ActiveSupport::Notifications.subscribe(RENDER_TEMPLATE_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
+ subscriber.notify_render_template(start, finish, payload)
+ end,
+ ActiveSupport::Notifications.subscribe(RENDER_COLLECTION_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
+ subscriber.notify_render_collection(start, finish, payload)
+ end,
+ ActiveSupport::Notifications.subscribe(RENDER_PARTIAL_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
+ subscriber.notify_render_partial(start, finish, payload)
+ end
+ ]
+
+ create_unsubscriber subscriptions
+ end
+
+ # For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
+ def notify_render_template(start, finish, payload)
+ generate_span_for_notification("render_template", start, finish, payload, tags_for_render_template(payload))
+ end
+
+ def notify_render_collection(start, finish, payload)
+ generate_span_for_notification("render_collection", start, finish, payload, tags_for_render_collection(payload))
+ end
+
+ def notify_render_partial(start, finish, payload)
+ generate_span_for_notification("render_partial", start, finish, payload, tags_for_render_partial(payload))
+ end
+
+ private
+
+ def tags_for_render_template(payload)
+ {
+ 'component' => COMPONENT_TAG,
+ 'template.id' => payload[:identifier],
+ 'template.layout' => payload[:layout]
+ }
+ end
+
+ def tags_for_render_collection(payload)
+ {
+ 'component' => COMPONENT_TAG,
+ 'template.id' => payload[:identifier],
+ 'template.count' => payload[:count] || 0,
+ 'template.cache.hits' => payload[:cache_hits] || 0
+ }
+ end
+
+ def tags_for_render_partial(payload)
+ {
+ 'component' => COMPONENT_TAG,
+ 'template.id' => payload[:identifier]
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/rails/active_record_subscriber.rb b/lib/gitlab/tracing/rails/active_record_subscriber.rb
new file mode 100644
index 00000000000..32f5658e57e
--- /dev/null
+++ b/lib/gitlab/tracing/rails/active_record_subscriber.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracing
+ module Rails
+ class ActiveRecordSubscriber
+ include RailsCommon
+
+ ACTIVE_RECORD_NOTIFICATION_TOPIC = 'sql.active_record'
+ OPERATION_NAME_PREFIX = 'active_record:'
+ DEFAULT_OPERATION_NAME = 'sqlquery'
+
+ # Instruments Rails ActiveRecord events for opentracing.
+ # Returns a lambda, which, when called will unsubscribe from the notifications
+ def self.instrument
+ subscriber = new
+
+ subscription = ActiveSupport::Notifications.subscribe(ACTIVE_RECORD_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
+ subscriber.notify(start, finish, payload)
+ end
+
+ create_unsubscriber [subscription]
+ end
+
+ # For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
+ def notify(start, finish, payload)
+ generate_span_for_notification(notification_name(payload), start, finish, payload, tags_for_notification(payload))
+ end
+
+ private
+
+ def notification_name(payload)
+ OPERATION_NAME_PREFIX + (payload[:name].presence || DEFAULT_OPERATION_NAME)
+ end
+
+ def tags_for_notification(payload)
+ {
+ 'component' => 'ActiveRecord',
+ 'span.kind' => 'client',
+ 'db.type' => 'sql',
+ 'db.connection_id' => payload[:connection_id],
+ 'db.cached' => payload[:cached] || false,
+ 'db.statement' => payload[:sql]
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/rails/rails_common.rb b/lib/gitlab/tracing/rails/rails_common.rb
new file mode 100644
index 00000000000..88e914f62f8
--- /dev/null
+++ b/lib/gitlab/tracing/rails/rails_common.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracing
+ module Rails
+ module RailsCommon
+ extend ActiveSupport::Concern
+ include Gitlab::Tracing::Common
+
+ class_methods do
+ def create_unsubscriber(subscriptions)
+ -> { subscriptions.each { |subscriber| ActiveSupport::Notifications.unsubscribe(subscriber) } }
+ end
+ end
+
+ def generate_span_for_notification(operation_name, start, finish, payload, tags)
+ exception = payload[:exception]
+
+ postnotify_span(operation_name, start, finish, tags: tags, exception: exception)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/sidekiq/client_middleware.rb b/lib/gitlab/tracing/sidekiq/client_middleware.rb
new file mode 100644
index 00000000000..2b71c1ea21e
--- /dev/null
+++ b/lib/gitlab/tracing/sidekiq/client_middleware.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'opentracing'
+
+module Gitlab
+ module Tracing
+ module Sidekiq
+ class ClientMiddleware
+ include SidekiqCommon
+
+ SPAN_KIND = 'client'
+
+ def call(worker_class, job, queue, redis_pool)
+ in_tracing_span(
+ operation_name: "sidekiq:#{job['class']}",
+ tags: tags_from_job(job, SPAN_KIND)) do |span|
+ # Inject the details directly into the job
+ tracer.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, job)
+
+ yield
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/sidekiq/server_middleware.rb b/lib/gitlab/tracing/sidekiq/server_middleware.rb
new file mode 100644
index 00000000000..5b43c4310e6
--- /dev/null
+++ b/lib/gitlab/tracing/sidekiq/server_middleware.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'opentracing'
+
+module Gitlab
+ module Tracing
+ module Sidekiq
+ class ServerMiddleware
+ include SidekiqCommon
+
+ SPAN_KIND = 'server'
+
+ def call(worker, job, queue)
+ context = tracer.extract(OpenTracing::FORMAT_TEXT_MAP, job)
+
+ in_tracing_span(
+ operation_name: "sidekiq:#{job['class']}",
+ child_of: context,
+ tags: tags_from_job(job, SPAN_KIND)) do |span|
+ yield
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/sidekiq/sidekiq_common.rb b/lib/gitlab/tracing/sidekiq/sidekiq_common.rb
new file mode 100644
index 00000000000..a911a29d773
--- /dev/null
+++ b/lib/gitlab/tracing/sidekiq/sidekiq_common.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracing
+ module Sidekiq
+ module SidekiqCommon
+ include Gitlab::Tracing::Common
+
+ def tags_from_job(job, kind)
+ {
+ 'component' => 'sidekiq',
+ 'span.kind' => kind,
+ 'sidekiq.queue' => job['queue'],
+ 'sidekiq.jid' => job['jid'],
+ 'sidekiq.retry' => job['retry'].to_s,
+ 'sidekiq.args' => job['args']&.join(", ")
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tree_summary.rb b/lib/gitlab/tree_summary.rb
index 453d78e2f7b..8518a13cd1c 100644
--- a/lib/gitlab/tree_summary.rb
+++ b/lib/gitlab/tree_summary.rb
@@ -95,7 +95,7 @@ module Gitlab
end
def cache_commit(commit)
- return nil unless commit.present?
+ return unless commit.present?
resolved_commits[commit.id] ||= commit
end
diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb
index 44c71f8431d..9b7b0db9525 100644
--- a/lib/gitlab/url_blocker.rb
+++ b/lib/gitlab/url_blocker.rb
@@ -8,16 +8,18 @@ module Gitlab
BlockedUrlError = Class.new(StandardError)
class << self
- def validate!(url, ports: [], protocols: [], allow_localhost: false, allow_local_network: true, ascii_only: false, enforce_user: false)
+ def validate!(url, ports: [], protocols: [], allow_localhost: false, allow_local_network: true, ascii_only: false, enforce_user: false, enforce_sanitization: false)
return true if url.nil?
# Param url can be a string, URI or Addressable::URI
uri = parse_url(url)
+ validate_html_tags!(uri) if enforce_sanitization
+
# Allow imports from the GitLab instance itself but only from the configured ports
return true if internal?(uri)
- port = uri.port || uri.default_port
+ port = get_port(uri)
validate_protocol!(uri.scheme, protocols)
validate_port!(port, ports) if ports.any?
validate_user!(uri.user) if enforce_user
@@ -50,6 +52,18 @@ module Gitlab
private
+ def get_port(uri)
+ uri.port || uri.default_port
+ end
+
+ def validate_html_tags!(uri)
+ uri_str = uri.to_s
+ sanitized_uri = ActionController::Base.helpers.sanitize(uri_str, tags: [])
+ if sanitized_uri != uri_str
+ raise BlockedUrlError, 'HTML/CSS/JS tags are not allowed'
+ end
+ end
+
def parse_url(url)
raise Addressable::URI::InvalidURIError if multiline?(url)
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 083c620267a..0101ccc046a 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -64,12 +64,12 @@ module Gitlab
group_clusters_disabled: count(::Clusters::Cluster.disabled.group_type),
clusters_platforms_gke: count(::Clusters::Cluster.gcp_installed.enabled),
clusters_platforms_user: count(::Clusters::Cluster.user_provided.enabled),
- clusters_applications_helm: count(::Clusters::Applications::Helm.installed),
- clusters_applications_ingress: count(::Clusters::Applications::Ingress.installed),
- clusters_applications_cert_managers: count(::Clusters::Applications::CertManager.installed),
- clusters_applications_prometheus: count(::Clusters::Applications::Prometheus.installed),
- clusters_applications_runner: count(::Clusters::Applications::Runner.installed),
- clusters_applications_knative: count(::Clusters::Applications::Knative.installed),
+ clusters_applications_helm: count(::Clusters::Applications::Helm.available),
+ clusters_applications_ingress: count(::Clusters::Applications::Ingress.available),
+ clusters_applications_cert_managers: count(::Clusters::Applications::CertManager.available),
+ clusters_applications_prometheus: count(::Clusters::Applications::Prometheus.available),
+ clusters_applications_runner: count(::Clusters::Applications::Runner.available),
+ clusters_applications_knative: count(::Clusters::Applications::Knative.available),
in_review_folder: count(::Environment.in_review_folder),
groups: count(Group),
issues: count(Issue),
@@ -81,6 +81,7 @@ module Gitlab
pages_domains: count(PagesDomain),
projects: count(Project),
projects_imported_from_github: count(Project.where(import_type: 'github')),
+ projects_with_repositories_enabled: count(ProjectFeature.where('repository_access_level > ?', ProjectFeature::DISABLED)),
protected_branches: count(ProtectedBranch),
releases: count(Release),
remote_mirrors: count(RemoteMirror),
@@ -89,8 +90,14 @@ module Gitlab
todos: count(Todo),
uploads: count(Upload),
web_hooks: count(WebHook)
- }.merge(services_usage).merge(approximate_counts)
- }
+ }
+ .merge(services_usage)
+ .merge(approximate_counts)
+ }.tap do |data|
+ if Feature.enabled?(:group_overview_security_dashboard)
+ data[:counts][:user_preferences] = user_preferences_usage
+ end
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -158,6 +165,10 @@ module Gitlab
}
end
+ def user_preferences_usage
+ {} # augmented in EE
+ end
+
def count(relation, fallback: -1)
relation.count
rescue ActiveRecord::StatementInvalid
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index 980a8014409..9ef23cf849f 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -118,8 +118,8 @@ module Gitlab
protected_refs: project.protected_tags)
end
- request_cache def protected?(kind, project, ref)
- kind.protected?(project, ref)
+ request_cache def protected?(kind, project, refs)
+ kind.protected?(project, refs)
end
end
end
diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb
index a81cee0d6d2..99fa65e0e90 100644
--- a/lib/gitlab/utils.rb
+++ b/lib/gitlab/utils.rb
@@ -115,5 +115,15 @@ module Gitlab
string_or_array.split(',').map(&:strip)
end
+
+ def deep_indifferent_access(data)
+ if data.is_a?(Array)
+ data.map(&method(:deep_indifferent_access))
+ elsif data.is_a?(Hash)
+ data.with_indifferent_access
+ else
+ data
+ end
+ end
end
end
diff --git a/lib/gitlab/utils/merge_hash.rb b/lib/gitlab/utils/merge_hash.rb
index fc237861e2f..48ba13b8561 100644
--- a/lib/gitlab/utils/merge_hash.rb
+++ b/lib/gitlab/utils/merge_hash.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_dependency 'gitlab/utils'
+
module Gitlab
module Utils
module MergeHash
diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb
index c87e97d0213..f5299439fce 100644
--- a/lib/gitlab/utils/override.rb
+++ b/lib/gitlab/utils/override.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_dependency 'gitlab/utils'
+
module Gitlab
module Utils
module Override
diff --git a/lib/gitlab/utils/strong_memoize.rb b/lib/gitlab/utils/strong_memoize.rb
index aa1f8e2fdda..3021a91dd83 100644
--- a/lib/gitlab/utils/strong_memoize.rb
+++ b/lib/gitlab/utils/strong_memoize.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_dependency 'gitlab/utils'
+
module Gitlab
module Utils
module StrongMemoize
diff --git a/lib/gitlab/wiki_file_finder.rb b/lib/gitlab/wiki_file_finder.rb
index 5303b3582ab..e9be6db50da 100644
--- a/lib/gitlab/wiki_file_finder.rb
+++ b/lib/gitlab/wiki_file_finder.rb
@@ -2,8 +2,6 @@
module Gitlab
class WikiFileFinder < FileFinder
- BATCH_SIZE = 100
-
attr_reader :repository
def initialize(project, ref)
@@ -19,7 +17,7 @@ module Gitlab
safe_query = Regexp.new(safe_query, Regexp::IGNORECASE)
filenames = repository.ls_files(ref)
- filenames.grep(safe_query).first(BATCH_SIZE)
+ filenames.grep(safe_query)
end
end
end
diff --git a/lib/json_web_token/hmac_token.rb b/lib/json_web_token/hmac_token.rb
index ceb1b9c913f..ec0917ab49d 100644
--- a/lib/json_web_token/hmac_token.rb
+++ b/lib/json_web_token/hmac_token.rb
@@ -18,7 +18,7 @@ module JSONWebToken
end
def encoded
- JWT.encode(payload, secret, JWT_ALGORITHM)
+ JWT.encode(payload, secret, JWT_ALGORITHM, { typ: 'JWT' })
end
private
diff --git a/lib/json_web_token/rsa_token.rb b/lib/json_web_token/rsa_token.rb
index 160e1e506f1..bcce811cd28 100644
--- a/lib/json_web_token/rsa_token.rb
+++ b/lib/json_web_token/rsa_token.rb
@@ -11,7 +11,8 @@ module JSONWebToken
def encoded
headers = {
- kid: kid
+ kid: kid,
+ typ: 'JWT'
}
JWT.encode(payload, key, 'RS256', headers)
end
diff --git a/lib/peek/views/tracing.rb b/lib/peek/views/tracing.rb
new file mode 100644
index 00000000000..0de32a8fdda
--- /dev/null
+++ b/lib/peek/views/tracing.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Peek
+ module Views
+ class Tracing < View
+ def results
+ {
+ tracing_url: Gitlab::Tracing.tracing_url
+ }
+ end
+ end
+ end
+end
diff --git a/lib/safe_zip/entry.rb b/lib/safe_zip/entry.rb
new file mode 100644
index 00000000000..664e2f52f91
--- /dev/null
+++ b/lib/safe_zip/entry.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+module SafeZip
+ class Entry
+ attr_reader :zip_archive, :zip_entry
+ attr_reader :path, :params
+
+ def initialize(zip_archive, zip_entry, params)
+ @zip_archive = zip_archive
+ @zip_entry = zip_entry
+ @params = params
+ @path = ::File.expand_path(zip_entry.name, params.extract_path)
+ end
+
+ def path_dir
+ ::File.dirname(path)
+ end
+
+ def real_path_dir
+ ::File.realpath(path_dir)
+ end
+
+ def exist?
+ ::File.exist?(path)
+ end
+
+ def extract
+ # do not extract if file is not part of target directory
+ return false unless matching_target_directory
+
+ # do not overwrite existing file
+ raise SafeZip::Extract::AlreadyExistsError, "File already exists #{zip_entry.name}" if exist?
+
+ create_path_dir
+
+ if zip_entry.file?
+ extract_file
+ elsif zip_entry.directory?
+ extract_dir
+ elsif zip_entry.symlink?
+ extract_symlink
+ else
+ raise SafeZip::Extract::UnsupportedEntryError, "File #{zip_entry.name} cannot be extracted"
+ end
+ rescue SafeZip::Extract::Error
+ raise
+ rescue => e
+ raise SafeZip::Extract::ExtractError, e.message
+ end
+
+ private
+
+ def extract_file
+ zip_archive.extract(zip_entry, path)
+ end
+
+ def extract_dir
+ FileUtils.mkdir(path)
+ end
+
+ def extract_symlink
+ source_path = read_symlink
+ real_source_path = expand_symlink(source_path)
+
+ # ensure that source path of symlink is within target directories
+ unless real_source_path.start_with?(matching_target_directory)
+ raise SafeZip::Extract::PermissionDeniedError, "Symlink cannot be created targeting: #{source_path}"
+ end
+
+ ::File.symlink(source_path, path)
+ end
+
+ def create_path_dir
+ # Create all directories, but ignore permissions
+ FileUtils.mkdir_p(path_dir)
+
+ # disallow to make path dirs to point to another directories
+ unless path_dir == real_path_dir
+ raise SafeZip::Extract::PermissionDeniedError, "Directory of #{zip_entry.name} points to another directory"
+ end
+ end
+
+ def matching_target_directory
+ params.matching_target_directory(path)
+ end
+
+ def read_symlink
+ zip_archive.read(zip_entry)
+ end
+
+ def expand_symlink(source_path)
+ ::File.realpath(source_path, path_dir)
+ rescue
+ raise SafeZip::Extract::SymlinkSourceDoesNotExistError, "Symlink source #{source_path} does not exist"
+ end
+ end
+end
diff --git a/lib/safe_zip/extract.rb b/lib/safe_zip/extract.rb
new file mode 100644
index 00000000000..679c021c730
--- /dev/null
+++ b/lib/safe_zip/extract.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module SafeZip
+ class Extract
+ Error = Class.new(StandardError)
+ PermissionDeniedError = Class.new(Error)
+ SymlinkSourceDoesNotExistError = Class.new(Error)
+ UnsupportedEntryError = Class.new(Error)
+ AlreadyExistsError = Class.new(Error)
+ NoMatchingError = Class.new(Error)
+ ExtractError = Class.new(Error)
+
+ attr_reader :archive_path
+
+ def initialize(archive_file)
+ @archive_path = archive_file
+ end
+
+ def extract(opts = {})
+ params = SafeZip::ExtractParams.new(**opts)
+
+ if Feature.enabled?(:safezip_use_rubyzip, default_enabled: true)
+ extract_with_ruby_zip(params)
+ else
+ legacy_unsafe_extract_with_system_zip(params)
+ end
+ end
+
+ private
+
+ def extract_with_ruby_zip(params)
+ ::Zip::File.open(archive_path) do |zip_archive|
+ # Extract all files in the following order:
+ # 1. Directories first,
+ # 2. Files next,
+ # 3. Symlinks last (or anything else)
+ extracted = extract_all_entries(zip_archive, params,
+ zip_archive.lazy.select(&:directory?))
+
+ extracted += extract_all_entries(zip_archive, params,
+ zip_archive.lazy.select(&:file?))
+
+ extracted += extract_all_entries(zip_archive, params,
+ zip_archive.lazy.reject(&:directory?).reject(&:file?))
+
+ raise NoMatchingError, 'No entries extracted' unless extracted > 0
+ end
+ end
+
+ def extract_all_entries(zip_archive, params, entries)
+ entries.count do |zip_entry|
+ SafeZip::Entry.new(zip_archive, zip_entry, params)
+ .extract
+ end
+ end
+
+ def legacy_unsafe_extract_with_system_zip(params)
+ # Requires UnZip at least 6.00 Info-ZIP.
+ # -n never overwrite existing files
+ args = %W(unzip -n -qq #{archive_path})
+
+ # We add * to end of directory, because we want to extract directory and all subdirectories
+ args += params.directories_wildcard
+
+ # Target directory where we extract
+ args += %W(-d #{params.extract_path})
+
+ unless system(*args)
+ raise Error, 'archive failed to extract'
+ end
+ end
+ end
+end
diff --git a/lib/safe_zip/extract_params.rb b/lib/safe_zip/extract_params.rb
new file mode 100644
index 00000000000..bd3b788bac9
--- /dev/null
+++ b/lib/safe_zip/extract_params.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module SafeZip
+ class ExtractParams
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :directories, :extract_path
+
+ def initialize(directories:, to:)
+ @directories = directories
+ @extract_path = ::File.realpath(to)
+ end
+
+ def matching_target_directory(path)
+ target_directories.find do |directory|
+ path.start_with?(directory)
+ end
+ end
+
+ def target_directories
+ strong_memoize(:target_directories) do
+ directories.map do |directory|
+ ::File.join(::File.expand_path(directory, extract_path), '')
+ end
+ end
+ end
+
+ def directories_wildcard
+ strong_memoize(:directories_wildcard) do
+ directories.map do |directory|
+ ::File.join(directory, '*')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/sentry/client.rb b/lib/sentry/client.rb
new file mode 100644
index 00000000000..49ec196b103
--- /dev/null
+++ b/lib/sentry/client.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+module Sentry
+ class Client
+ Error = Class.new(StandardError)
+ SentryError = Class.new(StandardError)
+
+ attr_accessor :url, :token
+
+ def initialize(api_url, token)
+ @url = api_url
+ @token = token
+ end
+
+ def list_issues(issue_status:, limit:)
+ issues = get_issues(issue_status: issue_status, limit: limit)
+ map_to_errors(issues)
+ end
+
+ def list_projects
+ projects = get_projects
+ map_to_projects(projects)
+ rescue KeyError => e
+ raise Client::SentryError, "Sentry API response is missing keys. #{e.message}"
+ end
+
+ private
+
+ def request_params
+ {
+ headers: {
+ 'Authorization' => "Bearer #{@token}"
+ },
+ follow_redirects: false
+ }
+ end
+
+ def http_get(url, params = {})
+ resp = Gitlab::HTTP.get(url, **request_params.merge(params))
+
+ handle_response(resp)
+ end
+
+ def get_issues(issue_status:, limit:)
+ http_get(issues_api_url, query: {
+ query: "is:#{issue_status}",
+ limit: limit
+ })
+ end
+
+ def get_projects
+ http_get(projects_api_url)
+ end
+
+ def handle_response(response)
+ unless response.code == 200
+ raise Client::Error, "Sentry response status code: #{response.code}"
+ end
+
+ response.as_json
+ end
+
+ def projects_api_url
+ projects_url = URI(@url)
+ projects_url.path = '/api/0/projects/'
+
+ projects_url
+ end
+
+ def issues_api_url
+ issues_url = URI(@url + '/issues/')
+ issues_url.path.squeeze!('/')
+
+ issues_url
+ end
+
+ def map_to_errors(issues)
+ issues.map(&method(:map_to_error))
+ end
+
+ def map_to_projects(projects)
+ projects.map(&method(:map_to_project))
+ end
+
+ def issue_url(id)
+ issues_url = @url + "/issues/#{id}"
+ issues_url = ErrorTracking::ProjectErrorTrackingSetting.extract_sentry_external_url(issues_url)
+
+ uri = URI(issues_url)
+ uri.path.squeeze!('/')
+
+ uri.to_s
+ end
+
+ def map_to_error(issue)
+ id = issue.fetch('id')
+ project = issue.fetch('project')
+
+ count = issue.fetch('count', nil)
+
+ frequency = issue.dig('stats', '24h')
+ message = issue.dig('metadata', 'value')
+
+ external_url = issue_url(id)
+
+ Gitlab::ErrorTracking::Error.new(
+ id: id,
+ first_seen: issue.fetch('firstSeen', nil),
+ last_seen: issue.fetch('lastSeen', nil),
+ title: issue.fetch('title', nil),
+ type: issue.fetch('type', nil),
+ user_count: issue.fetch('userCount', nil),
+ count: count,
+ message: message,
+ culprit: issue.fetch('culprit', nil),
+ external_url: external_url,
+ short_id: issue.fetch('shortId', nil),
+ status: issue.fetch('status', nil),
+ frequency: frequency,
+ project_id: project.fetch('id'),
+ project_name: project.fetch('name', nil),
+ project_slug: project.fetch('slug', nil)
+ )
+ end
+
+ def map_to_project(project)
+ organization = project.fetch('organization')
+
+ Gitlab::ErrorTracking::Project.new(
+ id: project.fetch('id'),
+ name: project.fetch('name'),
+ slug: project.fetch('slug'),
+ status: project.dig('status'),
+ organization_name: organization.fetch('name'),
+ organization_id: organization.fetch('id'),
+ organization_slug: organization.fetch('slug')
+ )
+ end
+ end
+end
diff --git a/lib/serializers/json.rb b/lib/serializers/json.rb
new file mode 100644
index 00000000000..93cb192087a
--- /dev/null
+++ b/lib/serializers/json.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Serializers
+ # This serializer exports data as JSON,
+ # it is designed to be used with interwork compatibility between MySQL and PostgreSQL
+ # implementations, as used version of MySQL does not support native json type
+ #
+ # Secondly, the loader makes the resulting hash to have deep indifferent access
+ class JSON
+ class << self
+ def dump(obj)
+ # MySQL stores data as text
+ # look at ./config/initializers/ar_mysql_jsonb_support.rb
+ if Gitlab::Database.mysql?
+ obj = ActiveSupport::JSON.encode(obj)
+ end
+
+ obj
+ end
+
+ def load(data)
+ return if data.nil?
+
+ # On MySQL we store data as text
+ # look at ./config/initializers/ar_mysql_jsonb_support.rb
+ if Gitlab::Database.mysql?
+ data = ActiveSupport::JSON.decode(data)
+ end
+
+ Gitlab::Utils.deep_indifferent_access(data)
+ end
+ end
+ end
+end
diff --git a/lib/system_check/app/git_user_default_ssh_config_check.rb b/lib/system_check/app/git_user_default_ssh_config_check.rb
index 6cd53779bfd..a331f88873b 100644
--- a/lib/system_check/app/git_user_default_ssh_config_check.rb
+++ b/lib/system_check/app/git_user_default_ssh_config_check.rb
@@ -53,7 +53,7 @@ module SystemCheck
end
def ssh_dir
- return nil unless home_dir
+ return unless home_dir
File.join(home_dir, '.ssh')
end
diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb
index e06245294c4..46aad8aa885 100644
--- a/lib/system_check/base_check.rb
+++ b/lib/system_check/base_check.rb
@@ -70,18 +70,14 @@ module SystemCheck
# multiple reasons why a check can fail
#
# @param [String] reason to be displayed
- def skip_reason=(reason)
- @skip_reason = reason
- end
+ attr_writer :skip_reason
# Skip reason defined during runtime
#
# This value have precedence over the one defined in the subclass
#
# @return [String] the reason
- def skip_reason
- @skip_reason
- end
+ attr_reader :skip_reason
# Does the check support automatically repair routine?
#
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index 4beb94eeb8e..b1db4dc94a6 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -10,6 +10,7 @@ namespace :dev do
desc "GitLab | Eager load application"
task load: :environment do
+ Rails.configuration.eager_load = true
Rails.application.eager_load!
end
end
diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake
index 560a52053d8..c24207b134a 100644
--- a/lib/tasks/gemojione.rake
+++ b/lib/tasks/gemojione.rake
@@ -30,33 +30,28 @@ namespace :gemojione do
# We don't have `node_modules` available in built versions of GitLab
FileUtils.cp_r(Rails.root.join('node_modules', 'emoji-unicode-version', 'emoji-unicode-version-map.json'), File.join(Rails.root, 'fixtures', 'emojis'))
- dir = Gemojione.images_path
resultant_emoji_map = {}
Gitlab::Emoji.emojis.each do |name, emoji_hash|
# Ignore aliases
unless Gitlab::Emoji.emojis_aliases.key?(name)
- fpath = File.join(dir, "#{emoji_hash['unicode']}.png")
- hash_digest = Digest::SHA256.file(fpath).hexdigest
-
category = emoji_hash['category']
if name == 'gay_pride_flag'
category = 'flags'
end
entry = {
- category: category,
- moji: emoji_hash['moji'],
- description: emoji_hash['description'],
- unicodeVersion: Gitlab::Emoji.emoji_unicode_version(name),
- digest: hash_digest
+ c: category,
+ e: emoji_hash['moji'],
+ d: emoji_hash['description'],
+ u: Gitlab::Emoji.emoji_unicode_version(name)
}
resultant_emoji_map[name] = entry
end
end
- out = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json')
+ out = File.join(Rails.root, 'public', '-', 'emojis', '1', 'emojis.json')
File.open(out, 'w') do |handle|
handle.write(JSON.pretty_generate(resultant_emoji_map))
end
diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake
index a42f02a84fd..7a42e4e92a0 100644
--- a/lib/tasks/gitlab/assets.rake
+++ b/lib/tasks/gitlab/assets.rake
@@ -1,13 +1,17 @@
namespace :gitlab do
namespace :assets do
desc 'GitLab | Assets | Compile all frontend assets'
- task compile: [
- 'yarn:check',
- 'gettext:po_to_json',
- 'rake:assets:precompile',
- 'webpack:compile',
- 'fix_urls'
- ]
+ task :compile do
+ require_dependency 'gitlab/task_helpers'
+
+ %w[
+ yarn:check
+ gettext:po_to_json
+ rake:assets:precompile
+ webpack:compile
+ gitlab:assets:fix_urls
+ ].each(&Gitlab::TaskHelpers.method(:invoke_and_time_task))
+ end
desc 'GitLab | Assets | Clean up old compiled frontend assets'
task clean: ['rake:assets:clean']
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index e96fbb64372..3977fc7ad8c 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -47,9 +47,9 @@ namespace :gitlab do
# Drop all tables Load the schema to ensure we don't have any newer tables
# hanging out from a failed upgrade
- progress.puts 'Cleaning the database ... '.color(:blue)
+ puts_time 'Cleaning the database ... '.color(:blue)
Rake::Task['gitlab:db:drop_tables'].invoke
- progress.puts 'done'.color(:green)
+ puts_time 'done'.color(:green)
Rake::Task['gitlab:backup:db:restore'].invoke
rescue Gitlab::TaskAbortedByUserError
puts "Quitting...".color(:red)
@@ -61,7 +61,7 @@ namespace :gitlab do
Rake::Task['gitlab:backup:uploads:restore'].invoke unless backup.skipped?('uploads')
Rake::Task['gitlab:backup:builds:restore'].invoke unless backup.skipped?('builds')
Rake::Task['gitlab:backup:artifacts:restore'].invoke unless backup.skipped?('artifacts')
- Rake::Task["gitlab:backup:pages:restore"].invoke unless backup.skipped?('pages')
+ Rake::Task['gitlab:backup:pages:restore'].invoke unless backup.skipped?('pages')
Rake::Task['gitlab:backup:lfs:restore'].invoke unless backup.skipped?('lfs')
Rake::Task['gitlab:backup:registry:restore'].invoke unless backup.skipped?('registry')
Rake::Task['gitlab:shell:setup'].invoke
@@ -72,165 +72,169 @@ namespace :gitlab do
namespace :repo do
task create: :gitlab_environment do
- progress.puts "Dumping repositories ...".color(:blue)
+ puts_time "Dumping repositories ...".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("repositories")
- progress.puts "[SKIPPED]".color(:cyan)
+ puts_time "[SKIPPED]".color(:cyan)
else
Backup::Repository.new(progress).dump
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
task restore: :gitlab_environment do
- progress.puts "Restoring repositories ...".color(:blue)
+ puts_time "Restoring repositories ...".color(:blue)
Backup::Repository.new(progress).restore
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
namespace :db do
task create: :gitlab_environment do
- progress.puts "Dumping database ... ".color(:blue)
+ puts_time "Dumping database ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("db")
- progress.puts "[SKIPPED]".color(:cyan)
+ puts_time "[SKIPPED]".color(:cyan)
else
Backup::Database.new(progress).dump
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
task restore: :gitlab_environment do
- progress.puts "Restoring database ... ".color(:blue)
+ puts_time "Restoring database ... ".color(:blue)
Backup::Database.new(progress).restore
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
namespace :builds do
task create: :gitlab_environment do
- progress.puts "Dumping builds ... ".color(:blue)
+ puts_time "Dumping builds ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("builds")
- progress.puts "[SKIPPED]".color(:cyan)
+ puts_time "[SKIPPED]".color(:cyan)
else
Backup::Builds.new(progress).dump
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
task restore: :gitlab_environment do
- progress.puts "Restoring builds ... ".color(:blue)
+ puts_time "Restoring builds ... ".color(:blue)
Backup::Builds.new(progress).restore
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
namespace :uploads do
task create: :gitlab_environment do
- progress.puts "Dumping uploads ... ".color(:blue)
+ puts_time "Dumping uploads ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("uploads")
- progress.puts "[SKIPPED]".color(:cyan)
+ puts_time "[SKIPPED]".color(:cyan)
else
Backup::Uploads.new(progress).dump
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
task restore: :gitlab_environment do
- progress.puts "Restoring uploads ... ".color(:blue)
+ puts_time "Restoring uploads ... ".color(:blue)
Backup::Uploads.new(progress).restore
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
namespace :artifacts do
task create: :gitlab_environment do
- progress.puts "Dumping artifacts ... ".color(:blue)
+ puts_time "Dumping artifacts ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("artifacts")
- progress.puts "[SKIPPED]".color(:cyan)
+ puts_time "[SKIPPED]".color(:cyan)
else
Backup::Artifacts.new(progress).dump
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
task restore: :gitlab_environment do
- progress.puts "Restoring artifacts ... ".color(:blue)
+ puts_time "Restoring artifacts ... ".color(:blue)
Backup::Artifacts.new(progress).restore
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
namespace :pages do
task create: :gitlab_environment do
- progress.puts "Dumping pages ... ".color(:blue)
+ puts_time "Dumping pages ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("pages")
- progress.puts "[SKIPPED]".color(:cyan)
+ puts_time "[SKIPPED]".color(:cyan)
else
Backup::Pages.new(progress).dump
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
task restore: :gitlab_environment do
- progress.puts "Restoring pages ... ".color(:blue)
+ puts_time "Restoring pages ... ".color(:blue)
Backup::Pages.new(progress).restore
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
namespace :lfs do
task create: :gitlab_environment do
- progress.puts "Dumping lfs objects ... ".color(:blue)
+ puts_time "Dumping lfs objects ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("lfs")
- progress.puts "[SKIPPED]".color(:cyan)
+ puts_time "[SKIPPED]".color(:cyan)
else
Backup::Lfs.new(progress).dump
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
task restore: :gitlab_environment do
- progress.puts "Restoring lfs objects ... ".color(:blue)
+ puts_time "Restoring lfs objects ... ".color(:blue)
Backup::Lfs.new(progress).restore
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
end
namespace :registry do
task create: :gitlab_environment do
- progress.puts "Dumping container registry images ... ".color(:blue)
+ puts_time "Dumping container registry images ... ".color(:blue)
if Gitlab.config.registry.enabled
if ENV["SKIP"] && ENV["SKIP"].include?("registry")
- progress.puts "[SKIPPED]".color(:cyan)
+ puts_time "[SKIPPED]".color(:cyan)
else
Backup::Registry.new(progress).dump
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
end
else
- progress.puts "[DISABLED]".color(:cyan)
+ puts_time "[DISABLED]".color(:cyan)
end
end
task restore: :gitlab_environment do
- progress.puts "Restoring container registry images ... ".color(:blue)
+ puts_time "Restoring container registry images ... ".color(:blue)
if Gitlab.config.registry.enabled
Backup::Registry.new(progress).restore
- progress.puts "done".color(:green)
+ puts_time "done".color(:green)
else
- progress.puts "[DISABLED]".color(:cyan)
+ puts_time "[DISABLED]".color(:cyan)
end
end
end
+ def puts_time(msg)
+ progress.puts "#{Time.now} -- #{msg}"
+ end
+
def progress
if ENV['CRON']
# We need an object we can say 'puts' and 'print' to; let's use a
diff --git a/lib/tasks/gitlab/bulk_add_permission.rake b/lib/tasks/gitlab/bulk_add_permission.rake
index 26cbf0740b6..c0d6cc8ca8e 100644
--- a/lib/tasks/gitlab/bulk_add_permission.rake
+++ b/lib/tasks/gitlab/bulk_add_permission.rake
@@ -14,7 +14,7 @@ namespace :gitlab do
end
desc "GitLab | Add a specific user to all projects (as a developer)"
- task :user_to_projects, [:email] => :environment do |t, args|
+ task :user_to_projects, [:email] => :environment do |t, args|
user = User.find_by(email: args.email)
project_ids = Project.pluck(:id)
puts "Importing #{user.email} users into #{project_ids.size} projects"
@@ -22,7 +22,7 @@ namespace :gitlab do
end
desc "GitLab | Add all users to all groups (admin users are added as owners)"
- task all_users_to_all_groups: :environment do |t, args|
+ task all_users_to_all_groups: :environment do |t, args|
user_ids = User.where(admin: false).pluck(:id)
admin_ids = User.where(admin: true).pluck(:id)
groups = Group.all
@@ -36,7 +36,7 @@ namespace :gitlab do
end
desc "GitLab | Add a specific user to all groups (as a developer)"
- task :user_to_groups, [:email] => :environment do |t, args|
+ task :user_to_groups, [:email] => :environment do |t, args|
user = User.find_by_email args.email
groups = Group.all
puts "Importing #{user.email} users into #{groups.size} groups"
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 74cd70c6e9f..b94b21775ee 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -29,10 +29,11 @@ namespace :gitlab do
# If MySQL, turn off foreign key checks
connection.execute('SET FOREIGN_KEY_CHECKS=0') if Gitlab::Database.mysql?
- tables = connection.tables
+ tables = connection.data_sources
+ # Removes the entry from the array
tables.delete 'schema_migrations'
# Truncate schema_migrations to ensure migrations re-run
- connection.execute('TRUNCATE schema_migrations')
+ connection.execute('TRUNCATE schema_migrations') if connection.data_source_exists? 'schema_migrations'
# Drop tables with cascade to avoid dependent table errors
# PG: http://www.postgresql.org/docs/current/static/ddl-depend.html
diff --git a/lib/tasks/gitlab/features.rake b/lib/tasks/gitlab/features.rake
new file mode 100644
index 00000000000..d115961108e
--- /dev/null
+++ b/lib/tasks/gitlab/features.rake
@@ -0,0 +1,24 @@
+namespace :gitlab do
+ namespace :features do
+ desc 'GitLab | Features | Enable direct Git access via Rugged for NFS'
+ task enable_rugged: :environment do
+ set_rugged_feature_flags(true)
+ puts 'All Rugged feature flags were enabled.'
+ end
+
+ task disable_rugged: :environment do
+ set_rugged_feature_flags(false)
+ puts 'All Rugged feature flags were disabled.'
+ end
+ end
+
+ def set_rugged_feature_flags(status)
+ Gitlab::Git::RuggedImpl::Repository::FEATURE_FLAGS.each do |flag|
+ if status
+ Feature.enable(flag)
+ else
+ Feature.disable(flag)
+ end
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake
index e97d77d20e0..b8798fb3cfd 100644
--- a/lib/tasks/gitlab/info.rake
+++ b/lib/tasks/gitlab/info.rake
@@ -58,7 +58,7 @@ namespace :gitlab do
puts "Omniauth Providers: #{omniauth_providers.join(', ')}" if Gitlab::Auth.omniauth_enabled?
# check Gitolite version
- gitlab_shell_version_file = "#{Gitlab.config.gitlab_shell.hooks_path}/../VERSION"
+ gitlab_shell_version_file = "#{Gitlab.config.gitlab_shell.path}/VERSION"
if File.readable?(gitlab_shell_version_file)
gitlab_shell_version = File.read(gitlab_shell_version_file)
end
@@ -72,7 +72,7 @@ namespace :gitlab do
puts "- #{name}: \t#{repository_storage.legacy_disk_path}"
end
end
- puts "Hooks:\t\t#{Gitlab.config.gitlab_shell.hooks_path}"
+ puts "GitLab Shell path:\t\t#{Gitlab.config.gitlab_shell.path}"
puts "Git:\t\t#{Gitlab.config.git.bin_path}"
end
end
diff --git a/lib/tasks/gitlab/setup.rake b/lib/tasks/gitlab/setup.rake
index f71e69987cb..e876b23d43f 100644
--- a/lib/tasks/gitlab/setup.rake
+++ b/lib/tasks/gitlab/setup.rake
@@ -25,6 +25,11 @@ namespace :gitlab do
puts ""
end
+ # In production, we might want to prevent ourselves from shooting
+ # ourselves in the foot, so let's only do this in a test or
+ # development environment.
+ terminate_all_connections unless Rails.env.production?
+
Rake::Task["db:reset"].invoke
Rake::Task["add_limits_mysql"].invoke
Rake::Task["setup_postgresql"].invoke
@@ -33,4 +38,24 @@ namespace :gitlab do
puts "Quitting...".color(:red)
exit 1
end
+
+ # If there are any clients connected to the DB, PostgreSQL won't let
+ # you drop the database. It's possible that Sidekiq, Unicorn, or
+ # some other client will be hanging onto a connection, preventing
+ # the DROP DATABASE from working. To workaround this problem, this
+ # method terminates all the connections so that a subsequent DROP
+ # will work.
+ def self.terminate_all_connections
+ return false unless Gitlab::Database.postgresql?
+
+ cmd = <<~SQL
+ SELECT pg_terminate_backend(pg_stat_activity.pid)
+ FROM pg_stat_activity
+ WHERE datname = current_database()
+ AND pid <> pg_backend_pid();
+ SQL
+
+ ActiveRecord::Base.connection.execute(cmd)&.result_status == PG::PGRES_TUPLES_OK
+ rescue ActiveRecord::NoDatabaseError
+ end
end
diff --git a/lib/tasks/gitlab/storage.rake b/lib/tasks/gitlab/storage.rake
index 09dc3aa9882..a2136ce1b92 100644
--- a/lib/tasks/gitlab/storage.rake
+++ b/lib/tasks/gitlab/storage.rake
@@ -36,8 +36,54 @@ namespace :gitlab do
print "Enqueuing migration of #{legacy_projects_count} projects in batches of #{helper.batch_size}"
- helper.project_id_batches do |start, finish|
- storage_migrator.bulk_schedule(start, finish)
+ helper.project_id_batches_migration do |start, finish|
+ storage_migrator.bulk_schedule_migration(start: start, finish: finish)
+
+ print '.'
+ end
+
+ puts ' Done!'
+ end
+
+ desc 'GitLab | Storage | Rollback existing projects to Legacy Storage'
+ task rollback_to_legacy: :environment do
+ if Gitlab::Database.read_only?
+ warn 'This task requires database write access. Exiting.'
+
+ next
+ end
+
+ storage_migrator = Gitlab::HashedStorage::Migrator.new
+ helper = Gitlab::HashedStorage::RakeHelper
+
+ if helper.range_single_item?
+ project = Project.with_storage_feature(:repository).find_by(id: helper.range_from)
+
+ unless project
+ warn "There are no projects that can be rolledback with ID=#{helper.range_from}"
+
+ next
+ end
+
+ puts "Enqueueing storage rollback of #{project.full_path} (ID=#{project.id})..."
+ storage_migrator.rollback(project)
+
+ next
+ end
+
+ hashed_projects_count = Project.with_storage_feature(:repository).count
+
+ if hashed_projects_count == 0
+ warn 'There are no projects that can have storage rolledback. Nothing to do!'
+
+ next
+ end
+
+ print "Enqueuing rollback of #{hashed_projects_count} projects in batches of #{helper.batch_size}"
+
+ helper.project_id_batches_rollback do |start, finish|
+ puts "Start: #{start} FINISH: #{finish}"
+ storage_migrator.bulk_schedule_rollback(start: start, finish: finish)
print '.'
end
diff --git a/lib/tasks/karma.rake b/lib/tasks/karma.rake
index 62a12174efa..53325d492d1 100644
--- a/lib/tasks/karma.rake
+++ b/lib/tasks/karma.rake
@@ -2,7 +2,7 @@ unless Rails.env.production?
namespace :karma do
desc 'GitLab | Karma | Generate fixtures for JavaScript tests'
RSpec::Core::RakeTask.new(:fixtures, [:pattern]) do |t, args|
- args.with_defaults(pattern: 'spec/javascripts/fixtures/*.rb')
+ args.with_defaults(pattern: '{spec,ee/spec}/javascripts/fixtures/*.rb')
ENV['NO_KNAPSACK'] = 'true'
t.pattern = args[:pattern]
t.rspec_opts = '--format documentation'
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 4047b9bfd81..71f89268a38 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:20\n"
+"PO-Revision-Date: 2019-02-11 08:11\n"
msgid " Status"
msgstr ""
@@ -39,26 +39,17 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -78,14 +69,8 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -123,6 +108,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -192,6 +186,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -219,12 +216,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -234,9 +237,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -246,6 +246,39 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -267,12 +300,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -384,10 +426,13 @@ msgstr[5] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -429,7 +474,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -477,6 +522,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -513,10 +561,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -528,7 +576,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -561,6 +612,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -570,6 +624,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -585,9 +642,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -621,12 +675,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -639,12 +723,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -660,6 +774,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -669,9 +786,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -693,6 +816,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -720,40 +846,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -762,6 +858,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -834,12 +933,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -870,9 +978,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -903,6 +1056,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -915,6 +1083,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -924,12 +1095,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -945,6 +1128,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -963,6 +1149,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -972,6 +1161,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -999,6 +1191,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -1011,6 +1206,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -1026,6 +1224,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -1053,15 +1254,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -1095,13 +1287,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1287,6 +1491,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1296,15 +1506,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1458,21 +1659,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1509,12 +1725,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1524,18 +1734,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1548,12 +1767,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1575,10 +1803,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1590,9 +1818,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1614,6 +1848,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1632,6 +1872,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1725,7 +1968,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1746,6 +1989,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1785,28 +2034,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1830,27 +2103,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1860,6 +2148,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1872,6 +2163,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1899,6 +2193,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1971,6 +2274,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1986,6 +2295,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -2022,6 +2337,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -2100,6 +2418,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2142,12 +2463,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2163,6 +2490,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2175,6 +2514,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2202,6 +2544,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2214,9 +2559,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2238,18 +2592,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2313,6 +2664,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2340,12 +2694,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2379,6 +2739,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2427,6 +2790,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2442,7 +2808,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2478,13 +2844,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2493,6 +2862,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2517,9 +2889,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2541,6 +2910,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2550,6 +2922,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2589,6 +2964,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2655,9 +3033,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2673,6 +3048,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2682,6 +3060,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2712,6 +3096,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2721,6 +3108,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2733,6 +3123,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2742,6 +3135,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2751,6 +3150,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2781,6 +3183,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2919,6 +3327,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2946,6 +3357,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2976,6 +3390,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2997,15 +3417,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -3033,6 +3462,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -3057,6 +3492,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -3072,9 +3510,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3084,6 +3528,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -3093,6 +3543,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -3111,6 +3564,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -3135,6 +3591,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3150,9 +3609,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3165,6 +3633,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3180,9 +3654,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3258,6 +3750,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3270,9 +3765,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3282,7 +3774,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3309,9 +3801,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3354,9 +3852,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3366,6 +3870,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3387,6 +3897,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3396,9 +3912,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3411,6 +3957,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3432,9 +3984,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3474,6 +4038,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3483,28 +4050,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3516,7 +4095,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3528,30 +4110,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3570,6 +4170,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3579,13 +4194,37 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3603,12 +4242,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3621,12 +4278,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3672,6 +4335,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3696,6 +4362,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3747,6 +4416,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3837,7 +4509,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3912,6 +4587,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3957,6 +4635,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3993,6 +4674,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -4071,9 +4755,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -4101,9 +4794,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4134,6 +4833,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4158,6 +4860,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4203,13 +4908,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4221,37 +4929,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4278,6 +4983,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4377,6 +5085,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4392,7 +5103,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4401,6 +5112,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4458,6 +5172,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4488,9 +5205,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4509,12 +5232,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4539,6 +5274,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4554,15 +5292,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4578,6 +5331,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4611,6 +5367,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4626,9 +5385,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4647,6 +5424,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4680,6 +5472,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4698,6 +5496,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4737,10 +5541,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4755,12 +5559,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4842,6 +5652,9 @@ msgstr[5] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4857,6 +5670,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4872,15 +5688,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -5022,6 +5862,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -5088,6 +5934,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -5118,6 +5967,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -5154,9 +6006,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5178,13 +6027,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5193,9 +6045,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5208,19 +6069,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5238,6 +6111,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5247,6 +6138,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5265,7 +6159,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5274,6 +6168,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5283,7 +6183,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5295,22 +6195,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Query"
-msgstr ""
-
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5325,10 +6219,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5349,21 +6243,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5436,6 +6321,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5496,6 +6393,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5508,6 +6408,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5526,6 +6429,12 @@ msgstr[5] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5544,6 +6453,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5565,6 +6477,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5592,6 +6507,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5601,6 +6519,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5613,15 +6534,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5634,6 +6564,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5643,10 +6576,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5667,6 +6603,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5676,12 +6615,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5706,6 +6639,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5736,6 +6672,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5838,21 +6780,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5886,16 +6843,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5943,6 +6897,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5955,12 +6915,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5982,9 +6957,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -6000,6 +6972,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6186,6 +7164,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6198,9 +7179,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6213,6 +7200,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6255,6 +7245,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6276,9 +7269,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6294,15 +7296,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6321,6 +7338,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6330,6 +7350,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6366,10 +7392,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6378,7 +7407,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6387,10 +7416,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6417,12 +7449,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6441,16 +7476,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6459,6 +7497,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6516,12 +7560,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6666,9 +7716,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6693,6 +7740,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6822,6 +7872,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6861,21 +7914,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6906,6 +7968,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6936,6 +8001,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6945,6 +8016,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6975,9 +8052,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -7038,6 +8121,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -7056,6 +8145,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -7065,12 +8157,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -7080,6 +8187,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -7089,12 +8202,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -7107,9 +8226,6 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
@@ -7119,6 +8235,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -7146,6 +8265,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -7173,6 +8295,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7206,7 +8331,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7227,6 +8352,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7236,6 +8364,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7272,6 +8403,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7284,6 +8418,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7353,7 +8490,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7362,10 +8499,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7383,6 +8523,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7392,6 +8544,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7419,6 +8577,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7452,9 +8613,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7464,6 +8631,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7494,6 +8703,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7509,6 +8721,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7572,10 +8787,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7617,12 +8832,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7632,6 +8856,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7653,9 +8880,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7665,6 +8901,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7674,9 +8913,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7695,6 +8940,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7719,9 +8967,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7767,7 +9021,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7800,6 +9054,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7812,6 +9069,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7839,6 +9099,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7854,6 +9117,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7890,6 +9156,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7899,9 +9171,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7911,6 +9195,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7920,6 +9213,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7935,6 +9234,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7950,6 +9252,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7965,10 +9270,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7983,7 +9372,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7992,14 +9384,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -8094,6 +9483,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -8109,9 +9504,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -8148,6 +9549,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8226,16 +9630,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8271,12 +9693,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8304,13 +9735,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8373,10 +9807,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8385,7 +9819,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8406,6 +9840,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8433,7 +9876,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8445,7 +9888,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8646,9 +10089,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8691,13 +10143,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8706,6 +10173,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8715,6 +10185,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8730,13 +10203,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8790,9 +10266,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8802,6 +10275,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8811,9 +10290,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8826,10 +10311,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8838,9 +10323,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8889,6 +10380,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8901,6 +10395,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8910,6 +10407,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8928,15 +10428,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8967,9 +10482,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8994,19 +10515,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -9015,25 +10545,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -9042,12 +10599,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -9060,6 +10623,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -9099,6 +10668,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -9123,6 +10695,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9147,27 +10725,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9192,6 +10791,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9333,12 +10935,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9351,6 +10962,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9369,6 +10983,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9393,6 +11010,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9411,6 +11031,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9420,12 +11043,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9435,16 +11064,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9486,6 +11121,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9501,12 +11139,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9519,12 +11163,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9534,12 +11190,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9648,6 +11310,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9663,6 +11328,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9795,6 +11466,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9819,12 +11493,24 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "done"
msgstr ""
@@ -9840,6 +11526,15 @@ msgstr[5] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9849,21 +11544,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9882,9 +11595,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9897,6 +11628,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
@@ -9906,9 +11640,21 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9924,10 +11670,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9966,6 +11712,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -10038,12 +11787,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -10098,19 +11841,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -10119,6 +11862,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -10131,10 +11877,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -10155,9 +11901,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -10185,6 +11943,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -10197,6 +11958,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -10209,6 +11976,9 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
@@ -10218,22 +11988,49 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -10242,9 +12039,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10257,3 +12060,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 7175ea66422..ed642e63cdf 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:21\n"
+"PO-Revision-Date: 2019-02-11 08:12\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,11 +433,11 @@ msgstr "ДейноÑÑ‚"
msgid "Add"
msgstr ""
-msgid "Add Changelog"
-msgstr "ДобавÑне на ÑпиÑък Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ð¸"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "ДобавÑне на ръководÑтво за ÑътрудничеÑтво"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ÐаиÑтина ли иÑкате да изтриете този план за Ñхема?"
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Прикачете файл чрез влачене и пуÑкане или %{upload_link}"
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "Клонът <strong>%{branch_name}</strong> беше Ñъздаден. За да наÑтроите автоматичното внедрÑване, изберете Yaml шаблон за GitLab CI и подайте промените Ñи. %{link_to_autodeploy_doc}"
@@ -1326,21 +1527,36 @@ msgstr "Преглед на файловете"
msgid "Browse files"
msgstr "Разглеждане на файловете"
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "от"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "Отказ"
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,12 +1671,12 @@ msgstr "ОтмÑна"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
-msgstr "СпиÑък Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ð¸"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "Графики"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] "Подаване"
msgstr[1] "ПодаваниÑ"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "Времетраене на подаваниÑта в минути за поÑледните 30 подаваниÑ"
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,8 +2672,8 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
-msgstr "РъководÑтво за ÑътрудничеÑтво"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr ""
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr "Създаване на нова папка"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Създайте Ñи личен жетон за доÑтъп в акаунта Ñи, за да можете да изтеглÑте и изпращате промени чрез %{protocol}."
@@ -2449,6 +2828,9 @@ msgstr "Създаване на заÑвка за Ñливане"
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr "ПерÑонализираните нива на извеÑÑ‚Ñване
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr "Подготовка за издаване"
msgid "CycleAnalyticsStage|Test"
msgstr "ТеÑтване"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Задайте потребителÑки шаблон, използвайки ÑинтакÑиÑа на „Cron“"
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr "СвалÑне"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "СвалÑне във формат „tar“"
@@ -2913,6 +3352,9 @@ msgstr "Обикновен файл Ñ Ñ€Ð°Ð·Ð»Ð¸ÐºÐ¸"
msgid "DownloadSource|Download"
msgstr "СвалÑне"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr "Редактиране"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Редактиране на плана %{id} за Ñхема"
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Ð’Ñеки ден (в 4 ч. Ñутринта)"
@@ -3252,9 +3772,39 @@ msgstr "Ð’Ñеки меÑец (на 1-во чиÑло, в 4 ч. Ñутринта
msgid "Every week (Sundays at 4:00am)"
msgstr "Ð’ÑÑка Ñедмица (в неделÑ, в 4 ч. Ñутринта)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Планът за Ñхема не може да бъде премахнат"
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,15 +4054,35 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "Файлове"
-msgid "Files (%{human_size})"
-msgstr ""
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr "Филтриране по Ñъобщение"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "ТърÑене по път"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "ТърÑене на файл"
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "Първо"
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr "ОÑвежаването започна уÑпешно"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr "ВнаÑÑне на хранилище"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr "Шаблон за интервала"
msgid "Introducing Cycle Analytics"
msgstr "ПредÑтавÑме Ви анализа на циклите"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] "ПоÑледните %d дни"
msgid "Last Pipeline"
msgstr "ПоÑледна Ñхема"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "ПоÑледно подаване"
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] "Ðови проблема"
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "Ðов план за Ñхема"
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr "Ðова папка"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr "Ðова заÑвка за Ñливане"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr "ÐÑма планове"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr "Ð¡ÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð·Ð° извеÑÑ‚Ñване"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "ЗатварÑне на проблем"
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only policy:"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "Схема"
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr "Връзката към изнеÑените данни на проекÑ
msgid "Project export started. A download link will be sent by email."
msgstr "ИзнаÑÑнето на проекта започна. Ще получите връзка към данните по е-поща."
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "Прочетете повече"
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
-msgstr "ПрочетиМе"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr "Свързани приложени заÑвки за Ñливане"
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "ÐапомнÑне по-къÑно"
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr "ЗаÑвка за доÑтъп"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "ОтмÑна на това подаване"
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Запазване на плана за Ñхема"
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr "Изходен код"
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "Създайте %{new_merge_request} Ñ Ñ‚ÐµÐ·Ð¸ промени"
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "Етикети"
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Етапът на проблемите показва колко е времето от Ñъздаването на проблем до определÑнето на целеви етап на проекта за него, или до добавÑнето му в ÑпиÑък на дъÑката за проблеми. Започнете да добавÑте проблеми, за да видите данните за този етап."
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "СтойноÑтта, коÑто Ñе намира в Ñредата на поÑледователноÑтта от наблюдавани данни. Ðапример: медианата на 3, 5 и 9 е 5, а медианата на 3, 5, 7 и 8 е (5+7)/2 = 6."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "Качване на нов файл"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "Качване на файл"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "щракнете за качване"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr "Използване на глобалната Ви наÑтройка за извеÑтиÑта"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr "Публичен"
msgid "VisibilityLevel|Unknown"
msgstr "ÐеизвеÑтно"
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ИÑкате ли да видите данните? Помолете админиÑтратор за доÑтъп."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "ÐÑма доÑтатъчно данни за този етап."
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr "ОттеглÑне на заÑвката за доÑтъп"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr "Можете да добавÑте файлове Ñамо когато
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr "Ðе можете да Ñъздавате повече проекти"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr "Ðуждаете Ñе от разрешение."
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "Вашето име"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] "ден"
msgstr[1] "дни"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr "нова заÑвка за Ñливане"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "извеÑÑ‚Ð¸Ñ Ð¿Ð¾ е-поща"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 904717e7d03..a6bc33b3974 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -13,10 +13,10 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ca\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:21\n"
+"PO-Revision-Date: 2019-02-11 08:12\n"
msgid " Status"
-msgstr ""
+msgstr " Estat"
msgid " and"
msgstr ""
@@ -31,33 +31,30 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d comissió"
+msgstr[1] "%d comissions"
msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d capa"
@@ -91,8 +93,8 @@ msgstr[1] "%d peticions de fusió"
msgid "%d metric"
msgid_plural "%d metrics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d mètrica"
+msgstr[1] "%d mètriques"
msgid "%d staged change"
msgid_plural "%d staged changes"
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text} %{files}"
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] "%d usuaris"
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "2FA activat"
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr "Informes d'abús"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr "Activitat"
msgid "Add"
msgstr "Afegeix"
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,39 +448,45 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
msgid "Add a table"
-msgstr ""
+msgstr "Afegeix una taula"
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
msgid "Add comment now"
-msgstr ""
+msgstr "Afegeix el comentari"
msgid "Add image comment"
-msgstr ""
+msgstr "Afegeix un comentari a la imatge"
msgid "Add license"
-msgstr ""
+msgstr "Afegeix una llicència"
msgid "Add new application"
-msgstr ""
+msgstr "Afegeix una aplicació nova"
msgid "Add new directory"
msgstr "Afegeix un directori nou"
msgid "Add projects"
-msgstr ""
+msgstr "Afegeix projectes"
msgid "Add reaction"
msgstr "Afegeix una reacció"
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr "Afegeix usuaris al grup:"
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr "Afegeix usuaris al grup"
@@ -461,9 +514,6 @@ msgstr "Àrea d'administració"
msgid "Admin Overview"
msgstr "Informació general d'administració"
-msgid "Admin area"
-msgstr "Àrea d'administració"
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -471,13 +521,13 @@ msgid "AdminArea| You are about to permanently delete the user %{username}. This
msgstr ""
msgid "AdminArea|Stop all jobs"
-msgstr ""
+msgstr "Atura totes les tasques"
msgid "AdminArea|Stop all jobs?"
-msgstr ""
+msgstr "Voleu aturar totes les tasques?"
msgid "AdminArea|Stop jobs"
-msgstr ""
+msgstr "Atura les tasques"
msgid "AdminArea|Stopping jobs failed"
msgstr ""
@@ -497,10 +547,40 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
+msgstr "Bloca l'usuari"
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
msgid "AdminUsers|Delete User %{username} and contributions?"
@@ -510,17 +590,47 @@ msgid "AdminUsers|Delete User %{username}?"
msgstr ""
msgid "AdminUsers|Delete user"
-msgstr ""
+msgstr "Suprimeix l'usuari"
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,18 +642,27 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "All"
+msgid "Alerts"
msgstr ""
+msgid "All"
+msgstr "Tots"
+
msgid "All changes are committed"
msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr "Tots els usuaris"
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,17 +846,62 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
-msgid "Analytics"
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
msgstr ""
+msgid "Analytics"
+msgstr "Analítiques"
+
msgid "Anonymous"
msgstr "Anònim"
msgid "Anti-spam verification"
-msgstr ""
+msgstr "Verificació contra el correu brossa"
msgid "Any"
msgstr "Qualsevol"
@@ -767,7 +916,7 @@ msgid "Application"
msgstr "Aplicació"
msgid "Application ID"
-msgstr ""
+msgstr "ID de l'aplicació"
msgid "Application: %{name}"
msgstr "Aplicació: %{name}"
@@ -775,6 +924,21 @@ msgstr "Aplicació: %{name}"
msgid "Applications"
msgstr "Aplicacions"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "abr"
@@ -785,6 +949,9 @@ msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
+msgstr "Projectes arxivats"
+
+msgid "Are you sure"
msgstr ""
msgid "Are you sure you want to delete this pipeline schedule?"
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "N'esteu segur?"
@@ -824,7 +1006,7 @@ msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
-msgstr ""
+msgstr "Artefactes"
msgid "Ascending"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -878,11 +1069,14 @@ msgid "Audit Events"
msgstr ""
msgid "Aug"
-msgstr ""
+msgstr "ag."
msgid "August"
msgstr "agost"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr "Autor"
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -986,19 +1186,19 @@ msgid "Background Color"
msgstr "Color de fons"
msgid "Background Jobs"
-msgstr ""
+msgstr "Tasques de fons"
msgid "Background color"
-msgstr ""
+msgstr "Color de fons"
msgid "Badges"
-msgstr ""
+msgstr "Insígnies"
msgid "Badges|A new badge was added."
-msgstr ""
+msgstr "S'ha afegit una insígnia nova."
msgid "Badges|Add badge"
-msgstr ""
+msgstr "Afegeix una insígnia"
msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
msgstr ""
@@ -1022,7 +1222,7 @@ msgid "Badges|Group Badge"
msgstr ""
msgid "Badges|Link"
-msgstr ""
+msgstr "Enllaç"
msgid "Badges|No badge image"
msgstr ""
@@ -1040,7 +1240,7 @@ msgid "Badges|Reload badge image"
msgstr ""
msgid "Badges|Save changes"
-msgstr ""
+msgstr "Desa els canvis"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
@@ -1088,7 +1288,7 @@ msgid "Below you will find all the groups that are public."
msgstr ""
msgid "Billing"
-msgstr ""
+msgstr "Facturació"
msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
msgstr ""
@@ -1151,7 +1351,7 @@ msgid "BillingPlans|paid annually at %{price_per_year}"
msgstr ""
msgid "BillingPlans|per user"
-msgstr ""
+msgstr "per usuari"
msgid "Bitbucket Server Import"
msgstr ""
@@ -1159,20 +1359,21 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
msgid "Boards"
-msgstr ""
+msgstr "Taulers"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1183,7 +1384,7 @@ msgid "Branch is already taken"
msgstr ""
msgid "Branch name"
-msgstr ""
+msgstr "Nom de la branca"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1192,16 +1393,16 @@ msgid "BranchSwitcherTitle|Switch branch"
msgstr ""
msgid "Branches"
-msgstr ""
+msgstr "Branques"
msgid "Branches|Active"
-msgstr ""
+msgstr "Actives"
msgid "Branches|Active branches"
-msgstr ""
+msgstr "Branques actives"
msgid "Branches|All"
-msgstr ""
+msgstr "Totes"
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -1237,10 +1438,10 @@ msgid "Branches|Merged into %{default_branch}"
msgstr ""
msgid "Branches|New branch"
-msgstr ""
+msgstr "Branca nova"
msgid "Branches|No branches to show"
-msgstr ""
+msgstr "No hi ha cap branca per mostrar"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
@@ -1255,10 +1456,10 @@ msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
msgid "Branches|Show active branches"
-msgstr ""
+msgstr "Mostra les branques actives"
msgid "Branches|Show all branches"
-msgstr ""
+msgstr "Mostra totes les branques"
msgid "Branches|Show more active branches"
msgstr ""
@@ -1306,7 +1507,7 @@ msgid "Branches|diverged from upstream"
msgstr ""
msgid "Branches|merged"
-msgstr ""
+msgstr "fusionada"
msgid "Branches|project settings"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,14 +1593,8 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
-msgstr ""
+msgstr "Tasques"
msgid "CICD|Learn more about Auto DevOps"
msgstr ""
@@ -1392,23 +1602,32 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
-msgid "Cancel"
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
+msgid "Cancel"
+msgstr "Cancel·la"
+
msgid "Cancel this job"
-msgstr ""
+msgstr "Cancel·la aquesta tasca"
msgid "Cannot be merged automatically"
msgstr ""
@@ -1416,15 +1635,24 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
-msgid "Change template"
+msgid "Change permissions"
msgstr ""
+msgid "Change template"
+msgstr "Canvia la plantilla"
+
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
@@ -1443,24 +1671,30 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
-msgstr ""
+msgstr "Diagrames"
msgid "Chat"
-msgstr ""
+msgstr "Xat"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1477,29 +1711,38 @@ msgid "Choose <strong>Next</strong> at the bottom of the page."
msgstr ""
msgid "Choose File ..."
-msgstr ""
+msgstr "Trieu el fitxer..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
-msgid "Choose a template..."
+msgid "Choose a file"
msgstr ""
-msgid "Choose a type..."
+msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template..."
+msgstr "Trieu una plantilla..."
+
+msgid "Choose a type..."
+msgstr "Trieu un tipus..."
+
msgid "Choose any color."
-msgstr ""
+msgstr "Trieu un color."
msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
msgstr ""
msgid "Choose file..."
-msgstr ""
+msgstr "Trieu el fitxer..."
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1513,19 +1756,19 @@ msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
msgid "CiStatusLabel|canceled"
-msgstr ""
+msgstr "cancel·lat"
msgid "CiStatusLabel|created"
-msgstr ""
+msgstr "creat"
msgid "CiStatusLabel|delayed"
msgstr ""
msgid "CiStatusLabel|failed"
-msgstr ""
+msgstr "fallit"
msgid "CiStatusLabel|manual action"
-msgstr ""
+msgstr "acció manual"
msgid "CiStatusLabel|passed"
msgstr ""
@@ -1588,12 +1831,12 @@ msgid "CiVariable|* (All environments)"
msgstr ""
msgid "CiVariable|All environments"
-msgstr ""
+msgstr "Tots els entorns"
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1651,21 +1900,45 @@ msgid "Client authentication key password"
msgstr ""
msgid "Clients"
+msgstr "Clients"
+
+msgid "Clone"
msgstr ""
msgid "Clone repository"
msgstr ""
-msgid "Close"
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
msgstr ""
+msgid "Close"
+msgstr "Tanca"
+
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
+msgstr "Tancades"
+
+msgid "Closed (moved)"
msgstr ""
msgid "Closed issues"
+msgstr "Incidències tancades"
+
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
@@ -1674,7 +1947,7 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2095,21 +2449,22 @@ msgid "Comment form position"
msgstr ""
msgid "Comments"
-msgstr ""
+msgstr "Comentaris"
msgid "Commit"
msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2153,7 +2508,7 @@ msgid "Commits|Commit: %{commitText}"
msgstr ""
msgid "Commits|History"
-msgstr ""
+msgstr "Historial"
msgid "Commits|No related merge requests found"
msgstr ""
@@ -2165,7 +2520,7 @@ msgid "Commit…"
msgstr ""
msgid "Compare"
-msgstr ""
+msgstr "Compara"
msgid "Compare Git revisions"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2183,7 +2541,7 @@ msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
msgstr ""
msgid "CompareBranches|Compare"
-msgstr ""
+msgstr "Compara"
msgid "CompareBranches|Source"
msgstr ""
@@ -2195,9 +2553,12 @@ msgid "CompareBranches|There isn't anything to compare."
msgstr ""
msgid "Confidential"
-msgstr ""
+msgstr "Confidencial"
msgid "Confidentiality"
+msgstr "Confidencialitat"
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure Gitaly timeouts."
@@ -2206,6 +2567,9 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2225,7 +2589,7 @@ msgid "Configure the way a user creates a new account."
msgstr ""
msgid "Connect"
-msgstr ""
+msgstr "Connecta"
msgid "Connect all repositories"
msgstr ""
@@ -2237,10 +2601,13 @@ msgid "Connect your external repositories, and CI/CD pipelines will run for new
msgstr ""
msgid "Connecting..."
+msgstr "S'està connectant..."
+
+msgid "Contact sales to upgrade"
msgstr ""
msgid "Container Registry"
-msgstr ""
+msgstr "Registre de contenidors"
msgid "ContainerRegistry|Created"
msgstr ""
@@ -2270,13 +2637,13 @@ msgid "ContainerRegistry|Remove tag"
msgstr ""
msgid "ContainerRegistry|Size"
-msgstr ""
+msgstr "Mida"
msgid "ContainerRegistry|Tag"
-msgstr ""
+msgstr "Etiqueta"
msgid "ContainerRegistry|Tag ID"
-msgstr ""
+msgstr "ID de l'etiqueta"
msgid "ContainerRegistry|Use different image names"
msgstr ""
@@ -2287,9 +2654,12 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
-msgid "Continue"
+msgid "Contents of .gitlab-ci.yml"
msgstr ""
+msgid "Continue"
+msgstr "Continua"
+
msgid "Continue to the next step"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,11 +2726,14 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
msgid "Copy URL to clipboard"
-msgstr ""
+msgstr "Copia l'URL al porta-retalls"
msgid "Copy branch name to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2447,46 +2826,49 @@ msgid "Create merge request"
msgstr ""
msgid "Create merge request and branch"
+msgstr "Crea una petició de fusió i una branca"
+
+msgid "Create milestone"
msgstr ""
msgid "Create new branch"
-msgstr ""
+msgstr "Crea una branca nova"
msgid "Create new directory"
-msgstr ""
+msgstr "Crea un directori nou"
msgid "Create new file"
-msgstr ""
+msgstr "Crea un fitxer nou"
msgid "Create new file or directory"
-msgstr ""
+msgstr "Crea un fitxer o directori nou"
msgid "Create new label"
-msgstr ""
+msgstr "Crea una etiqueta nova"
msgid "Create new..."
-msgstr ""
+msgstr "Crea..."
msgid "Create project label"
-msgstr ""
+msgstr "Crea una etiqueta de projecte"
msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
-msgstr ""
+msgstr "Etiqueta"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
msgid "Created"
-msgstr ""
+msgstr "Creat"
msgid "Created At"
msgstr ""
msgid "Created by me"
-msgstr ""
+msgstr "Creat per mi"
msgid "Created on"
msgstr ""
@@ -2504,19 +2886,16 @@ msgid "Cron syntax"
msgstr ""
msgid "Current Branch"
-msgstr ""
+msgstr "Branca actual"
msgid "Current node"
-msgstr ""
+msgstr "Node actual"
msgid "CurrentUser|Profile"
-msgstr ""
+msgstr "Perfil"
msgid "CurrentUser|Settings"
-msgstr ""
-
-msgid "Custom"
-msgstr ""
+msgstr "Configuració"
msgid "Custom CI config path"
msgstr ""
@@ -2533,15 +2912,24 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
-msgid "Customize colors"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
msgstr ""
+msgid "Customize colors"
+msgstr "Personalitza els colors"
+
msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2552,7 +2940,7 @@ msgid "Cycle Analytics gives an overview of how much time it takes to go from id
msgstr ""
msgid "CycleAnalyticsStage|Code"
-msgstr ""
+msgstr "Codi"
msgid "CycleAnalyticsStage|Issue"
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,16 +2972,22 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
-msgid "Date picker"
+msgid "Data is still calculating..."
msgstr ""
+msgid "Date picker"
+msgstr "Selector de data"
+
msgid "Debug"
-msgstr ""
+msgstr "Depura"
msgid "Dec"
-msgstr ""
+msgstr "des."
msgid "December"
+msgstr "desembre"
+
+msgid "Decline"
msgstr ""
msgid "Decline and sign out"
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2627,7 +3033,7 @@ msgid "DelayedJobs|delayed"
msgstr ""
msgid "Delete"
-msgstr ""
+msgstr "Suprimeix"
msgid "Delete Package"
msgstr ""
@@ -2639,6 +3045,12 @@ msgid "Delete comment"
msgstr ""
msgid "Delete list"
+msgstr "Suprimeix la llista"
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
msgstr ""
msgid "Deleted"
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2785,21 +3200,24 @@ msgid "Deprioritize label"
msgstr ""
msgid "Descending"
-msgstr ""
+msgstr "Descendent"
msgid "Description"
-msgstr ""
+msgstr "Descripció"
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr ""
msgid "Description:"
-msgstr ""
+msgstr "Descripció:"
msgid "Destroy"
msgstr ""
msgid "Details"
+msgstr "Detalls"
+
+msgid "Details (default)"
msgstr ""
msgid "Detect host keys"
@@ -2818,20 +3236,26 @@ msgid "Diffs|Something went wrong while fetching diff lines."
msgstr ""
msgid "Direction"
-msgstr ""
+msgstr "Direcció"
msgid "Directory name"
-msgstr ""
+msgstr "Nom del directori"
msgid "Disable"
-msgstr ""
+msgstr "Desactiva"
msgid "Disable for this project"
-msgstr ""
+msgstr "Desactiva per a aquest projecte"
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2878,28 +3311,34 @@ msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
-msgstr ""
+msgstr "Domini"
msgid "Don't show again"
-msgstr ""
+msgstr "No ho mostris més"
msgid "Done"
-msgstr ""
+msgstr "Fet"
msgid "Download"
+msgstr "Baixa"
+
+msgid "Download artifacts"
msgstr ""
-msgid "Download tar"
+msgid "Download asset"
msgstr ""
+msgid "Download tar"
+msgstr "Baixa un arxiu tar"
+
msgid "Download tar.bz2"
-msgstr ""
+msgstr "Baixa un arxiu tar.bz2"
msgid "Download tar.gz"
-msgstr ""
+msgstr "Baixa un arxiu tar.gz"
msgid "Download zip"
-msgstr ""
+msgstr "Baixa un arxiu zip"
msgid "DownloadArtifacts|Download"
msgstr ""
@@ -2913,9 +3352,12 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
-msgid "Downvotes"
+msgid "Downstream"
msgstr ""
+msgid "Downvotes"
+msgstr "Vots negatius"
+
msgid "Due date"
msgstr ""
@@ -2926,11 +3368,17 @@ msgid "Each Runner can be in one of the following states:"
msgstr ""
msgid "Edit"
+msgstr "Edita"
+
+msgid "Edit %{name}"
msgstr ""
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2938,25 +3386,34 @@ msgid "Edit Snippet"
msgstr ""
msgid "Edit application"
+msgstr "Edita l'aplicació"
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
msgstr ""
msgid "Edit files in the editor and commit changes here"
msgstr ""
msgid "Edit group: %{group_name}"
-msgstr ""
+msgstr "Edita el grup: %{group_name}"
msgid "Edit identity for %{user_name}"
msgstr ""
-msgid "Elasticsearch"
+msgid "Edit issues"
msgstr ""
+msgid "Elasticsearch"
+msgstr "Elasticsearch"
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
-msgstr ""
+msgstr "Adreça electrònica"
msgid "Email patch"
msgstr ""
@@ -2967,9 +3424,12 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
+msgid "Enable"
+msgstr "Activa"
+
msgid "Enable Auto DevOps"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3016,11 +3488,17 @@ msgid "Enable usage ping to get an overview of how you are using GitLab from a f
msgstr ""
msgid "Enabled"
-msgstr ""
+msgstr "Activat"
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3034,9 +3512,27 @@ msgid "Enter the merge request description"
msgstr ""
msgid "Enter the merge request title"
+msgstr "Introduïu el títol de la petició de fusió"
+
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
msgstr ""
msgid "Environments"
+msgstr "Entorns"
+
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
msgid "Environments|An error occurred while fetching the environments."
@@ -3070,7 +3566,7 @@ msgid "Environments|Environments are places where code gets deployed, such as st
msgstr ""
msgid "Environments|Job"
-msgstr ""
+msgstr "Tasca"
msgid "Environments|Learn more about stopping environments"
msgstr ""
@@ -3106,14 +3602,17 @@ msgid "Environments|Rollback environment"
msgstr ""
msgid "Environments|Show all"
-msgstr ""
+msgstr "Mostra-ho tot"
msgid "Environments|Stop"
-msgstr ""
+msgstr "Atura"
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,14 +3634,14 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
-msgstr ""
+msgstr "Com ho puc resoldre-ho?"
msgid "Epics|More information"
-msgstr ""
+msgstr "Més informació"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
@@ -3160,14 +3656,20 @@ msgid "Epics|start"
msgstr ""
msgid "Error"
-msgstr ""
+msgstr "Error"
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3196,7 +3698,7 @@ msgid "Error loading markdown preview"
msgstr ""
msgid "Error loading merge requests."
-msgstr ""
+msgstr "S'ha produït un error en carregar les peticions de fusió."
msgid "Error loading project data. Please try again."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,11 +3817,17 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
msgid "Explore"
-msgstr ""
+msgstr "Explora"
msgid "Explore GitLab"
msgstr ""
@@ -3280,17 +3836,29 @@ msgid "Explore Groups"
msgstr ""
msgid "Explore groups"
-msgstr ""
+msgstr "Explora els grups"
msgid "Explore projects"
-msgstr ""
+msgstr "Explora els projectes"
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3310,7 +3878,7 @@ msgid "ExternalAuthorizationService|When no classification label is set the defa
msgstr ""
msgid "Facebook"
-msgstr ""
+msgstr "Facebook"
msgid "Failed"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,71 +3970,124 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
msgid "FeatureFlags|Name"
-msgstr ""
+msgstr "Nom"
msgid "FeatureFlags|New"
-msgstr ""
+msgstr "Nova"
msgid "FeatureFlags|New Feature Flag"
msgstr ""
msgid "FeatureFlags|Save changes"
-msgstr ""
+msgstr "Desa els canvis"
msgid "FeatureFlags|Status"
+msgstr "Estat"
+
+msgid "FeatureFlags|Target environments"
msgstr ""
-msgid "Feb"
+msgid "FeatureFlags|There are no active Feature Flags"
msgstr ""
-msgid "February"
+msgid "FeatureFlags|There are no inactive Feature Flags"
msgstr ""
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Feb"
+msgstr "feb."
+
+msgid "February"
+msgstr "febrer"
+
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
-msgid "File templates"
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
msgstr ""
-msgid "Files"
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
msgstr ""
-msgid "Files (%{human_size})"
+msgid "File templates"
+msgstr "Plantilles de fitxers"
+
+msgid "File upload error."
msgstr ""
+msgid "Files"
+msgstr "Fitxers"
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
msgid "Filter"
-msgstr ""
+msgstr "Filtra"
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
+msgstr "Filtra..."
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
msgstr ""
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3520,14 +4183,17 @@ msgid "Follow the steps below to export your Google Code project data."
msgstr ""
msgid "Font Color"
-msgstr ""
+msgstr "Color del tipus de lletra"
msgid "Footer message"
-msgstr ""
+msgstr "Missatge a peu de pàgina"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,9 +4218,12 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
-msgid "Format"
+msgid "Forks"
msgstr ""
+msgid "Format"
+msgstr "Format"
+
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
@@ -3592,10 +4261,10 @@ msgid "From the Kubernetes cluster details view, install Runner from the applica
msgstr ""
msgid "GPG Keys"
-msgstr ""
+msgstr "Claus GPG"
msgid "General"
-msgstr ""
+msgstr "General"
msgid "General pipelines"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3679,7 +4351,7 @@ msgid "GeoNodes|Local job artifacts"
msgstr ""
msgid "GeoNodes|New node"
-msgstr ""
+msgstr "Node nou"
msgid "GeoNodes|Node Authentication was successfully repaired."
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3784,7 +4462,7 @@ msgid "Geo|All"
msgstr ""
msgid "Geo|All projects"
-msgstr ""
+msgstr "Tots els projectes"
msgid "Geo|All projects are being scheduled for re-check"
msgstr ""
@@ -3799,7 +4477,7 @@ msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
-msgstr ""
+msgstr "Fallit"
msgid "Geo|File sync capacity"
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3823,7 +4504,7 @@ msgid "Geo|Last time verified"
msgstr ""
msgid "Geo|Never"
-msgstr ""
+msgstr "Mai"
msgid "Geo|Next sync scheduled at"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3880,10 +4564,10 @@ msgid "Geo|Shards to synchronize"
msgstr ""
msgid "Geo|Status"
-msgstr ""
+msgstr "Estat"
msgid "Geo|Synced"
-msgstr ""
+msgstr "Sincronitzat"
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
@@ -3895,7 +4579,7 @@ msgid "Geo|Tracking entry will be removed. Are you sure?"
msgstr ""
msgid "Geo|Unknown state"
-msgstr ""
+msgstr "Estat desconegut"
msgid "Geo|Verification capacity"
msgstr ""
@@ -3927,7 +4611,16 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
+msgstr "Git"
+
+msgid "Git global setup"
msgstr ""
msgid "Git repository URL"
@@ -3940,7 +4633,7 @@ msgid "Git strategy for pipelines"
msgstr ""
msgid "Git version"
-msgstr ""
+msgstr "Versió del Git"
msgid "GitHub import"
msgstr ""
@@ -3949,7 +4642,7 @@ msgid "GitLab CI Linter has been moved"
msgstr ""
msgid "GitLab Geo"
-msgstr ""
+msgstr "GitLab Geo"
msgid "GitLab Group Runners can execute code for all the projects in this group."
msgstr ""
@@ -3957,7 +4650,13 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
+msgstr "Usuari del GitLab"
+
+msgid "GitLab metadata URL"
msgstr ""
msgid "GitLab project export"
@@ -3976,7 +4675,7 @@ msgid "GitLab’s issue tracker"
msgstr ""
msgid "Gitaly"
-msgstr ""
+msgstr "Gitaly"
msgid "Gitaly Servers"
msgstr ""
@@ -3990,14 +4689,17 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
-msgid "Go Back"
+msgid "Given access %{time_ago}"
msgstr ""
+msgid "Go Back"
+msgstr "Enrere"
+
msgid "Go back"
-msgstr ""
+msgstr "Enrere"
msgid "Go to"
-msgstr ""
+msgstr "Vés a"
msgid "Go to %{link_to_google_takeout}."
msgstr ""
@@ -4014,11 +4716,14 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
msgid "Group"
-msgstr ""
+msgstr "Grup"
msgid "Group CI/CD settings"
msgstr ""
@@ -4048,10 +4753,10 @@ msgid "Group description (optional)"
msgstr ""
msgid "Group details"
-msgstr ""
+msgstr "Detalls del grup"
msgid "Group info:"
-msgstr ""
+msgstr "Informació del grup:"
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4129,11 +4834,14 @@ msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name
msgstr ""
msgid "Groups"
-msgstr ""
+msgstr "Grups"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4177,7 +4885,7 @@ msgid "GroupsTree|Create a subgroup in this group."
msgstr ""
msgid "GroupsTree|Edit group"
-msgstr ""
+msgstr "Edita el grup"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
@@ -4222,10 +4930,10 @@ msgid "HealthCheck|Unhealthy"
msgstr ""
msgid "Help"
-msgstr ""
+msgstr "Ajuda"
msgid "Help page"
-msgstr ""
+msgstr "Pàgina d'ajuda"
msgid "Help page text and support page url."
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4241,18 +4952,21 @@ msgstr ""
msgid "Hide value"
msgid_plural "Hide values"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Amaga el valor"
+msgstr[1] "Amaga els valors"
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
-msgstr ""
+msgstr "Historial"
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4260,13 +4974,13 @@ msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
msgid "ID"
-msgstr ""
+msgstr "ID"
msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
msgstr ""
msgid "IDE|Back"
-msgstr ""
+msgstr "Enrere"
msgid "IDE|Client side evaluation"
msgstr ""
@@ -4275,7 +4989,7 @@ msgid "IDE|Commit"
msgstr ""
msgid "IDE|Edit"
-msgstr ""
+msgstr "Edita"
msgid "IDE|Get started with Live Preview"
msgstr ""
@@ -4299,17 +5013,20 @@ msgid "IDE|Review"
msgstr ""
msgid "IP Address"
-msgstr ""
+msgstr "Adreça IP"
msgid "Identifier"
-msgstr ""
+msgstr "Identificador"
msgid "Identities"
-msgstr ""
+msgstr "Identitats"
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,7 +5057,13 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
+msgstr "Importa"
+
+msgid "Import CSV"
msgstr ""
msgid "Import Projects from Gitea"
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4438,8 +5194,8 @@ msgstr ""
msgid "Instance"
msgid_plural "Instances"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Instància"
+msgstr[1] "Instàncies"
msgid "Instance Statistics"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,49 +5867,73 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
+msgid "Merge Request"
+msgstr "Petició de fusió"
+
msgid "Merge Requests"
-msgstr ""
+msgstr "Peticions de fusió"
msgid "Merge Requests created"
+msgstr "S'han creat les peticions de fusió"
+
+msgid "Merge commit message"
msgstr ""
msgid "Merge events"
+msgstr "Esdeveniments de fusió"
+
+msgid "Merge immediately"
msgstr ""
-msgid "Merge request"
+msgid "Merge in progress"
msgstr ""
+msgid "Merge request"
+msgstr "Petició de fusió"
+
msgid "Merge request approvals"
msgstr ""
msgid "Merge requests"
-msgstr ""
+msgstr "Peticions de fusió"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,14 +5978,17 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
msgid "Messages"
-msgstr ""
+msgstr "Missatges"
msgid "Metrics"
-msgstr ""
+msgstr "Mètriques"
msgid "Metrics - Influx"
msgstr ""
@@ -5105,25 +5999,31 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
msgid "Metrics|Create metric"
+msgstr "Crea una mètrica"
+
+msgid "Metrics|Delete metric"
msgstr ""
-msgid "Metrics|Edit metric"
+msgid "Metrics|Delete metric?"
msgstr ""
+msgid "Metrics|Edit metric"
+msgstr "Edita la mètrica"
+
msgid "Metrics|Environment"
-msgstr ""
+msgstr "Entorn"
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,26 +6035,20 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
-msgstr ""
+msgstr "Mètrica nova"
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
-msgstr ""
+msgstr "Sistema"
msgid "Metrics|There was an error fetching the environments data, please try again"
msgstr ""
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5271,28 +6156,40 @@ msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
msgid "Modal|Cancel"
-msgstr ""
+msgstr "Cancel·la"
msgid "Modal|Close"
+msgstr "Tanca"
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
msgstr ""
msgid "Monitoring"
msgstr ""
msgid "Months"
-msgstr ""
+msgstr "Mesos"
msgid "More"
-msgstr ""
+msgstr "Més"
msgid "More actions"
msgstr ""
msgid "More info"
-msgstr ""
+msgstr "Més informació"
msgid "More information"
-msgstr ""
+msgstr "Més informació"
msgid "More information is available|here"
msgstr ""
@@ -5301,7 +6198,7 @@ msgid "Most stars"
msgstr ""
msgid "Move"
-msgstr ""
+msgstr "Mou"
msgid "Move issue"
msgstr ""
@@ -5310,7 +6207,7 @@ msgid "Multiple issue boards"
msgstr ""
msgid "Name"
-msgstr ""
+msgstr "Nom"
msgid "Name new label"
msgstr ""
@@ -5319,16 +6216,16 @@ msgid "Name your individual key via a title"
msgstr ""
msgid "Name:"
-msgstr ""
+msgstr "Nom:"
msgid "Naming, visibility"
msgstr ""
msgid "Nav|Help"
-msgstr ""
+msgstr "Ajuda"
msgid "Nav|Home"
-msgstr ""
+msgstr "Inici"
msgid "Nav|Sign In / Register"
msgstr ""
@@ -5336,23 +6233,29 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
-msgid "Network"
+msgid "Need help?"
msgstr ""
+msgid "Network"
+msgstr "Xarxa"
+
msgid "Never"
-msgstr ""
+msgstr "Mai"
msgid "New"
-msgstr ""
+msgstr "Nou"
msgid "New Application"
+msgstr "Aplicació nova"
+
+msgid "New Environment"
msgstr ""
msgid "New Group"
-msgstr ""
+msgstr "Grup nou"
msgid "New Identity"
-msgstr ""
+msgstr "Identitat nova"
msgid "New Issue"
msgid_plural "New Issues"
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 9e25b8de9f4..c71b768ece2 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:22\n"
+"PO-Revision-Date: 2019-02-11 08:13\n"
msgid " Status"
msgstr ""
@@ -35,22 +35,17 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -66,12 +61,8 @@ msgstr[1] "%d commity pozadu"
msgstr[2] "%d commitů pozadu"
msgstr[3] "%d commitů pozadu"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -101,6 +92,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -158,6 +156,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -181,12 +182,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -196,9 +203,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr "Profilový obrázek %{name}"
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} lze použít jako alternativu vlastní domény."
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -208,6 +212,33 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr "%{percent}%% dokonÄeno"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -227,12 +258,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -322,10 +362,13 @@ msgstr[3] ""
msgid "1st contribution!"
msgstr "1. příspěvek!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "Dvoufaktorové ověření povoleno"
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -367,7 +410,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -415,6 +458,9 @@ msgstr "Hlášení o zneužití"
msgid "Abuse reports"
msgstr "Hlášení o zneužití"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -451,10 +497,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -466,7 +512,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -499,6 +548,9 @@ msgstr ""
msgid "Add reaction"
msgstr "Přidat reakci"
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -508,6 +560,9 @@ msgstr "Přidat úkol"
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -523,9 +578,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -559,12 +611,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Blokovat uživatele"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -577,12 +659,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -596,6 +708,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -605,9 +720,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -629,6 +750,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -656,40 +780,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -698,6 +792,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -770,12 +867,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -806,9 +912,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -839,6 +990,21 @@ msgstr ""
msgid "Applications"
msgstr "Aplikace"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "Dub"
@@ -851,6 +1017,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -860,12 +1029,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -881,6 +1062,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "Jste si jisti?"
@@ -899,6 +1083,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "PÅ™iÅ™aÄte vlastní barvu jako například #FF0000"
@@ -908,6 +1095,9 @@ msgstr "Přiřadit štítky"
msgid "Assign milestone"
msgstr "Přiřadit milník"
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr "Přiřadit k"
@@ -935,6 +1125,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -947,6 +1140,9 @@ msgstr "Srp"
msgid "August"
msgstr "Srpen"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -962,6 +1158,9 @@ msgstr "Autor"
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -989,15 +1188,6 @@ msgstr "Auto DevOps aktivní"
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -1031,13 +1221,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "K dispozici"
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1223,6 +1425,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1232,13 +1440,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1392,21 +1593,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1443,12 +1659,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1458,18 +1668,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1482,12 +1701,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1509,10 +1737,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1524,9 +1752,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1548,6 +1782,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1566,6 +1806,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1659,7 +1902,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1680,6 +1923,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1719,28 +1968,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1764,27 +2037,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1794,6 +2082,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1806,6 +2097,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1833,6 +2127,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1905,6 +2208,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1920,6 +2229,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1956,6 +2271,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -2034,6 +2352,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2076,12 +2397,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2097,6 +2424,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2109,6 +2448,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2136,6 +2478,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2148,9 +2493,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2170,16 +2524,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2243,6 +2596,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2270,12 +2626,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2309,6 +2671,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2357,6 +2722,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2372,7 +2740,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2408,13 +2776,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2423,6 +2794,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2447,9 +2821,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2471,6 +2842,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2480,6 +2854,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2519,6 +2896,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2585,9 +2965,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2603,6 +2980,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2612,6 +2992,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2642,6 +3028,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2651,6 +3040,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2663,6 +3055,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2672,6 +3067,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2681,6 +3082,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2711,6 +3115,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2847,6 +3257,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2874,6 +3287,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2904,6 +3320,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2925,15 +3347,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2961,6 +3392,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2985,6 +3422,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -3000,9 +3440,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3012,6 +3458,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -3021,6 +3473,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -3039,6 +3494,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -3063,6 +3521,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3078,9 +3539,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3093,6 +3563,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3108,9 +3584,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3186,6 +3680,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3198,9 +3695,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3210,7 +3704,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3237,9 +3731,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3282,9 +3782,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3294,6 +3800,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3315,6 +3827,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3324,9 +3842,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3339,6 +3887,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3360,9 +3914,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3402,6 +3968,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3411,28 +3980,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3444,7 +4025,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3456,30 +4040,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3498,6 +4100,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3507,13 +4124,35 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3531,12 +4170,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3549,12 +4206,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3600,6 +4263,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3624,6 +4290,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3675,6 +4344,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3765,7 +4437,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3840,6 +4515,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3885,6 +4563,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3921,6 +4602,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3999,9 +4683,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -4029,9 +4722,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4062,6 +4761,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4086,6 +4788,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4131,13 +4836,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4149,37 +4857,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4206,6 +4911,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4305,6 +5013,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4318,7 +5029,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4327,6 +5038,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4384,6 +5098,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4414,9 +5131,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4435,12 +5158,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4465,6 +5200,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4480,15 +5218,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4504,6 +5257,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4535,6 +5291,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4550,9 +5309,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4571,6 +5348,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4604,6 +5396,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4622,6 +5420,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4661,10 +5465,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4679,12 +5483,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4764,6 +5574,9 @@ msgstr[3] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4779,6 +5592,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4794,15 +5610,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4942,6 +5782,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -5008,6 +5854,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -5038,6 +5887,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -5074,9 +5926,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5098,13 +5947,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5113,9 +5965,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5128,19 +5989,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5158,6 +6031,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5167,6 +6058,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5185,7 +6079,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5194,6 +6088,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5203,7 +6103,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5215,22 +6115,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5245,10 +6139,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5269,21 +6163,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5356,6 +6241,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5416,6 +6313,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5428,6 +6328,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5444,6 +6347,12 @@ msgstr[3] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5462,6 +6371,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5483,6 +6395,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5510,6 +6425,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5519,6 +6437,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5531,15 +6452,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5552,6 +6482,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5561,10 +6494,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5585,6 +6521,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5594,12 +6533,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5624,6 +6557,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5654,6 +6590,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5754,21 +6696,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5802,16 +6759,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5859,6 +6813,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5871,12 +6831,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5898,9 +6873,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5916,6 +6888,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6102,6 +7080,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6114,9 +7095,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6129,6 +7116,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6171,6 +7161,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6192,9 +7185,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6210,15 +7212,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6237,6 +7254,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6246,6 +7266,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6282,10 +7308,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6294,7 +7323,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6303,10 +7332,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6333,12 +7365,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6357,16 +7392,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6375,6 +7413,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6432,12 +7476,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6582,9 +7632,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6609,6 +7656,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6738,6 +7788,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6777,21 +7830,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6820,6 +7882,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6850,6 +7915,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6859,6 +7930,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6889,9 +7966,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6952,6 +8035,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6970,6 +8059,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6979,12 +8071,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6994,6 +8101,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -7003,12 +8116,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -7021,9 +8140,6 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
@@ -7031,6 +8147,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -7058,6 +8177,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -7085,6 +8207,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7118,7 +8243,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7139,6 +8264,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7148,6 +8276,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7184,6 +8315,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7196,6 +8330,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7265,7 +8402,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7274,10 +8411,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7295,6 +8435,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7304,6 +8456,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7331,6 +8489,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7364,9 +8525,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7376,6 +8543,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7406,6 +8615,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7421,6 +8633,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7484,10 +8699,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7527,12 +8742,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7542,6 +8766,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7563,9 +8790,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7575,6 +8811,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7584,9 +8823,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7605,6 +8850,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7629,9 +8877,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7677,7 +8931,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7710,6 +8964,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7722,6 +8979,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7749,6 +9009,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7764,6 +9027,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7800,6 +9066,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7809,9 +9081,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7821,6 +9105,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7830,6 +9123,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7845,6 +9144,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7860,6 +9162,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7875,10 +9180,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7893,7 +9282,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7902,12 +9294,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -8002,6 +9393,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -8017,9 +9414,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -8056,6 +9459,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8134,16 +9540,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8179,12 +9603,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8212,13 +9645,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8281,10 +9717,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8293,7 +9729,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8314,6 +9750,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8341,7 +9786,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8353,7 +9798,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8550,9 +9995,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8595,13 +10049,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8610,6 +10079,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8619,6 +10091,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8634,13 +10109,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8694,9 +10172,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8706,6 +10181,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8715,9 +10196,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8730,10 +10217,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8742,9 +10229,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8793,6 +10286,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8805,6 +10301,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8814,6 +10313,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8832,15 +10334,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8871,9 +10388,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8898,19 +10421,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8919,25 +10451,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8946,12 +10505,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8964,6 +10529,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -9003,6 +10574,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -9027,6 +10601,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9051,27 +10631,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9096,6 +10697,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9237,12 +10841,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9255,6 +10868,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9273,6 +10889,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9297,6 +10916,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9315,6 +10937,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9324,12 +10949,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9339,16 +10970,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9390,6 +11027,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9405,12 +11045,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9423,12 +11069,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9438,12 +11096,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9544,6 +11208,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9559,6 +11226,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9685,6 +11358,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9707,12 +11383,22 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "done"
msgstr ""
@@ -9726,6 +11412,15 @@ msgstr[3] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9735,21 +11430,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9766,9 +11479,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9781,6 +11512,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
@@ -9788,9 +11522,21 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9806,10 +11552,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9848,6 +11594,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9920,12 +11669,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9976,19 +11719,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9997,6 +11740,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -10009,10 +11755,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -10033,9 +11779,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -10059,6 +11817,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -10069,6 +11830,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -10081,6 +11848,9 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
@@ -10088,22 +11858,49 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -10112,9 +11909,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10125,3 +11928,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 8d06e64d3e0..174737050e6 100644
--- a/locale/cy_GB/gitlab.po
+++ b/locale/cy_GB/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: cy\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:23\n"
+"PO-Revision-Date: 2019-02-11 08:16\n"
msgid " Status"
msgstr ""
@@ -39,26 +39,17 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -78,14 +69,8 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -123,6 +108,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -192,6 +186,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -219,12 +216,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -234,9 +237,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -246,6 +246,39 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -267,12 +300,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -384,10 +426,13 @@ msgstr[5] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -429,7 +474,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -477,6 +522,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -513,10 +561,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -528,7 +576,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -561,6 +612,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -570,6 +624,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -585,9 +642,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -621,12 +675,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -639,12 +723,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -660,6 +774,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -669,9 +786,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -693,6 +816,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -720,40 +846,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -762,6 +858,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -834,12 +933,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -870,9 +978,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -903,6 +1056,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -915,6 +1083,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -924,12 +1095,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -945,6 +1128,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -963,6 +1149,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -972,6 +1161,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -999,6 +1191,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -1011,6 +1206,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -1026,6 +1224,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -1053,15 +1254,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -1095,13 +1287,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1287,6 +1491,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1296,15 +1506,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1458,21 +1659,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1509,12 +1725,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1524,18 +1734,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1548,12 +1767,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1575,10 +1803,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1590,9 +1818,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1614,6 +1848,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1632,6 +1872,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1725,7 +1968,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1746,6 +1989,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1785,28 +2034,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1830,27 +2103,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1860,6 +2148,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1872,6 +2163,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1899,6 +2193,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1971,6 +2274,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1986,6 +2295,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -2022,6 +2337,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -2100,6 +2418,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2142,12 +2463,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2163,6 +2490,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2175,6 +2514,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2202,6 +2544,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2214,9 +2559,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2238,18 +2592,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2313,6 +2664,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2340,12 +2694,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2379,6 +2739,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2427,6 +2790,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2442,7 +2808,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2478,13 +2844,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2493,6 +2862,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2517,9 +2889,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2541,6 +2910,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2550,6 +2922,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2589,6 +2964,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2655,9 +3033,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2673,6 +3048,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2682,6 +3060,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2712,6 +3096,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2721,6 +3108,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2733,6 +3123,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2742,6 +3135,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2751,6 +3150,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2781,6 +3183,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2919,6 +3327,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2946,6 +3357,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2976,6 +3390,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2997,15 +3417,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -3033,6 +3462,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -3057,6 +3492,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -3072,9 +3510,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3084,6 +3528,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -3093,6 +3543,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -3111,6 +3564,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -3135,6 +3591,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3150,9 +3609,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3165,6 +3633,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3180,9 +3654,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3258,6 +3750,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3270,9 +3765,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3282,7 +3774,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3309,9 +3801,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3354,9 +3852,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3366,6 +3870,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3387,6 +3897,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3396,9 +3912,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3411,6 +3957,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3432,9 +3984,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3474,6 +4038,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3483,28 +4050,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3516,7 +4095,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3528,30 +4110,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3570,6 +4170,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3579,13 +4194,37 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3603,12 +4242,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3621,12 +4278,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3672,6 +4335,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3696,6 +4362,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3747,6 +4416,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3837,7 +4509,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3912,6 +4587,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3957,6 +4635,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3993,6 +4674,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -4071,9 +4755,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -4101,9 +4794,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4134,6 +4833,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4158,6 +4860,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4203,13 +4908,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4221,37 +4929,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4278,6 +4983,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4377,6 +5085,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4392,7 +5103,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4401,6 +5112,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4458,6 +5172,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4488,9 +5205,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4509,12 +5232,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4539,6 +5274,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4554,15 +5292,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4578,6 +5331,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4611,6 +5367,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4626,9 +5385,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4647,6 +5424,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4680,6 +5472,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4698,6 +5496,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4737,10 +5541,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4755,12 +5559,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4842,6 +5652,9 @@ msgstr[5] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4857,6 +5670,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4872,15 +5688,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -5022,6 +5862,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -5088,6 +5934,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -5118,6 +5967,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -5154,9 +6006,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5178,13 +6027,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5193,9 +6045,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5208,19 +6069,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5238,6 +6111,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5247,6 +6138,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5265,7 +6159,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5274,6 +6168,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5283,7 +6183,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5295,22 +6195,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Query"
-msgstr ""
-
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5325,10 +6219,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5349,21 +6243,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5436,6 +6321,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5496,6 +6393,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5508,6 +6408,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5526,6 +6429,12 @@ msgstr[5] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5544,6 +6453,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5565,6 +6477,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5592,6 +6507,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5601,6 +6519,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5613,15 +6534,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5634,6 +6564,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5643,10 +6576,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5667,6 +6603,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5676,12 +6615,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5706,6 +6639,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5736,6 +6672,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5838,21 +6780,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5886,16 +6843,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5943,6 +6897,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5955,12 +6915,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5982,9 +6957,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -6000,6 +6972,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6186,6 +7164,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6198,9 +7179,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6213,6 +7200,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6255,6 +7245,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6276,9 +7269,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6294,15 +7296,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6321,6 +7338,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6330,6 +7350,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6366,10 +7392,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6378,7 +7407,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6387,10 +7416,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6417,12 +7449,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6441,16 +7476,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6459,6 +7497,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6516,12 +7560,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6666,9 +7716,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6693,6 +7740,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6822,6 +7872,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6861,21 +7914,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6906,6 +7968,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6936,6 +8001,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6945,6 +8016,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6975,9 +8052,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -7038,6 +8121,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -7056,6 +8145,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -7065,12 +8157,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -7080,6 +8187,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -7089,12 +8202,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -7107,9 +8226,6 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
@@ -7119,6 +8235,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -7146,6 +8265,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -7173,6 +8295,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7206,7 +8331,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7227,6 +8352,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7236,6 +8364,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7272,6 +8403,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7284,6 +8418,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7353,7 +8490,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7362,10 +8499,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7383,6 +8523,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7392,6 +8544,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7419,6 +8577,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7452,9 +8613,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7464,6 +8631,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7494,6 +8703,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7509,6 +8721,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7572,10 +8787,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7617,12 +8832,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7632,6 +8856,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7653,9 +8880,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7665,6 +8901,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7674,9 +8913,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7695,6 +8940,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7719,9 +8967,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7767,7 +9021,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7800,6 +9054,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7812,6 +9069,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7839,6 +9099,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7854,6 +9117,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7890,6 +9156,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7899,9 +9171,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7911,6 +9195,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7920,6 +9213,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7935,6 +9234,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7950,6 +9252,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7965,10 +9270,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7983,7 +9372,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7992,14 +9384,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -8094,6 +9483,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -8109,9 +9504,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -8148,6 +9549,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8226,16 +9630,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8271,12 +9693,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8304,13 +9735,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8373,10 +9807,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8385,7 +9819,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8406,6 +9840,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8433,7 +9876,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8445,7 +9888,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8646,9 +10089,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8691,13 +10143,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8706,6 +10173,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8715,6 +10185,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8730,13 +10203,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8790,9 +10266,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8802,6 +10275,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8811,9 +10290,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8826,10 +10311,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8838,9 +10323,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8889,6 +10380,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8901,6 +10395,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8910,6 +10407,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8928,15 +10428,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8967,9 +10482,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8994,19 +10515,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -9015,25 +10545,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -9042,12 +10599,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -9060,6 +10623,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -9099,6 +10668,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -9123,6 +10695,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9147,27 +10725,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9192,6 +10791,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9333,12 +10935,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9351,6 +10962,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9369,6 +10983,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9393,6 +11010,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9411,6 +11031,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9420,12 +11043,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9435,16 +11064,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9486,6 +11121,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9501,12 +11139,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9519,12 +11163,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9534,12 +11190,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9648,6 +11310,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9663,6 +11328,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9795,6 +11466,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9819,12 +11493,24 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "done"
msgstr ""
@@ -9840,6 +11526,15 @@ msgstr[5] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9849,21 +11544,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9882,9 +11595,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9897,6 +11628,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
@@ -9906,9 +11640,21 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9924,10 +11670,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9966,6 +11712,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -10038,12 +11787,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -10098,19 +11841,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -10119,6 +11862,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -10131,10 +11877,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -10155,9 +11901,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -10185,6 +11943,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -10197,6 +11958,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -10209,6 +11976,9 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
@@ -10218,22 +11988,49 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -10242,9 +12039,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10257,3 +12060,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index a81ab6f60b3..ee02b31f2b0 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:20\n"
+"PO-Revision-Date: 2019-02-11 08:13\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 440622b08af..f77e2599726 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:23\n"
+"PO-Revision-Date: 2019-02-11 08:15\n"
msgid " Status"
msgstr " Status"
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] " um %d Punkt verbessert"
msgstr[1] " um %d Punkte verbessert"
-msgid "\"%{query}\" in projects"
-msgstr "\"%{query}\" in Projekten"
+msgid " or "
+msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] "%d geänderte Datei"
-msgstr[1] "%d geänderte Dateien"
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" in Projekten"
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] "%d Commit hinterher"
msgstr[1] "%d Commits hinterher"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] "%d gelöscht"
-msgstr[1] "%d Löschungen"
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] "%d Ticket"
msgstr[1] "%d Tickets"
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d Ebene"
@@ -122,6 +124,9 @@ msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build
msgstr "%{counter_storage} (%{counter_repositories} Repositories, %{counter_build_artifacts} Buildartefakte, %{counter_lfs_objects} LFS)"
msgid "%{count} %{alerts}"
+msgstr "%{count} %{alerts}"
+
+msgid "%{count} more"
msgstr ""
msgid "%{count} more assignees"
@@ -143,12 +148,18 @@ msgstr "%{filePath} gelöscht"
msgid "%{firstLabel} +%{labelCount} more"
msgstr "%{firstLabel} +%{labelCount} mehr"
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Gruppen%{group_docs_link_end} ermöglichen dir die Verwaltung und die Zusammenarbeit über mehrere Projekte hinweg. Mitglieder einer Gruppe haben Zugriff auf alle Projekte darin."
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} wird entfernt! Bist du sicher?"
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Gestartet"
@@ -158,9 +169,6 @@ msgstr "%{lock_path} ist durch Gitlab-Benutzer(in) %{lock_user_id} gesperrt"
msgid "%{name}'s avatar"
msgstr "Avatar von %{name}"
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} kann als Alternative zu einer benutzerdefinierten Domain verwendet werden."
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} Commits hinter %{default_branch}, %{number_commits_ahead} Commits voraus"
@@ -170,6 +178,27 @@ msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% abgeschlossen"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text} %{files}"
@@ -187,12 +216,21 @@ msgstr "%{unstaged} nicht vorgemerkte und %{staged} vorgemerkte Änderungen"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}Erfahre mehr%{usage_ping_link_end} darüber, welche Informationen mit GitLab Inc. geteilt werden."
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr "+ %{count} weitere"
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} weitere"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr "- Prozessor ist aktiv und kann neue Jobs verarbeiten"
@@ -260,11 +298,14 @@ msgstr[1] "%d Benutzer(innen)"
msgid "1st contribution!"
msgstr "Erster Beitrag!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "Zwei-Faktor-Authentifizierung aktiviert"
-msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "Bitte kontaktiere deine(n) GitLab-Administrator(in), um die Erlaubnis zu erhalten."
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
msgid "403|You don't have the permission to access this page."
msgstr "Du hast nicht die Berechtigung auf diese Seite zuzugreifen."
@@ -305,8 +346,8 @@ msgstr "<strong>%{group_name}</strong> Gruppenmitglieder"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr "<strong>%{pushes}</strong> Pushes, mehr als <strong>%{commits}</strong> Commits von <strong>%{people}</strong> Mitwirkenden."
-msgid "<strong>Removes</strong> source branch"
-msgstr "<strong>Entfernt</strong> Quell-Branch"
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "Ein 'Runner' ist ein Prozess, welcher ein Job ausführt. Du kannst so viele Runner erstellen wie du benötigst."
@@ -321,7 +362,7 @@ msgid "A deleted user"
msgstr "Ein(e) gelöschte(r) Benutzer(in)"
msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr ""
+msgstr "Ein Mitglied des GitLab-Missbrauchsteams wird deinen Bericht so schnell wie möglich überprüfen."
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "Ein neuer Branch wird in deinem Fork erzeugt und ein neuer Merge-Request wird gestartet."
@@ -353,6 +394,9 @@ msgstr "Missbrauchsmeldungen"
msgid "Abuse reports"
msgstr "Missbrauchsmeldungen"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr "Bedingungen akzeptieren"
@@ -389,27 +433,30 @@ msgstr "Aktivität"
msgid "Add"
msgstr "Hinzufügen"
-msgid "Add Changelog"
-msgstr "Änderungsprotokoll hinzufügen"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "Mitarbeitsanleitung hinzufügen"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Gruppen-Webhooks und GitLab Enterprise Edition hinzufügen."
msgid "Add Jaeger URL"
-msgstr ""
+msgstr "Jaeger URL hinzufügen"
msgid "Add Kubernetes cluster"
msgstr "Kubernetes-Cluster hinzufügen"
-msgid "Add Readme"
-msgstr "Readme anlegen"
+msgid "Add README"
+msgstr ""
-msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr "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 table"
msgstr "Tabelle hinzufügen"
@@ -437,6 +484,9 @@ msgstr "Projekte hinzufügen"
msgid "Add reaction"
msgstr "Reaktion hinzufügen"
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr "Zum Review hinzufügen"
@@ -446,6 +496,9 @@ msgstr "To-do hinzufügen"
msgid "Add user(s) to the group:"
msgstr "Benutzer(innen) zur Gruppe hinzufügen:"
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr "Füge Benutzer(innen) zur Gruppe hinzu"
@@ -461,9 +514,6 @@ msgstr "Adminbereich"
msgid "Admin Overview"
msgstr "Admin-Ãœbersicht"
-msgid "Admin area"
-msgstr "Adminbereich"
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "Du bist gerade dabei den/die Benutzer(in) %{username} dauerhaft zu löschen. Tickets, Merge-Requests und Gruppen, die mit ihm/ihr verknüpft sind, werden einem systemweiten \"Ghost-user\" zugewiesen. Um Datenverlust zu vermeiden, ziehe in Erwägung stattdessen die Funktion %{strong_start}Benutzer(in) blockieren%{strong_end} zu verwenden. Nachdem du %{strong_start}Benutzer(in) entfernen%{strong_end} ausgeführt hast, kann es nicht rückgängig gemacht oder der/die Benutzer(in) wiederhergestellt werden."
@@ -497,12 +547,42 @@ msgstr "Projekt %{projectName} löschen?"
msgid "AdminProjects|Delete project"
msgstr "Projekt löschen"
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Gib eine Domäne an, die standardmäßig für die Auto-Review-Anwendungen- und Auto-Bereitstsellungs-Phasen jedes Projekts verwendet werden soll."
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Benutzer(in) blockieren"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "Benutzer(in) %{username} und seine/ihre Beiträge löschen?"
@@ -515,15 +595,45 @@ msgstr "Benutzer(in) löschen"
msgid "AdminUsers|Delete user and contributions"
msgstr "Benutzer(in) und Beiträge löschen"
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Zur Bestätigung %{projectName} eingeben"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Zur Bestätigung %{username} eingeben"
-msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
msgstr ""
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr "Erweiterte Berechtigungen, Large File Storage und Einstellungen zur Zwei-Faktor-Authentifizierung."
+
msgid "Advanced settings"
msgstr "Erweiterte Einstellungen"
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] "Alarm"
msgstr[1] "Alarme"
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr "Alle"
@@ -541,9 +654,15 @@ msgstr "Alle Änderungen sind committed"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Alle Features sind für leere Projekte, Vorlagen, oder beim Import aktiviert. Du kannst sie aber danach in den Projekteinstellungen deaktivieren."
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr "Alle Benutzer(innen)"
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr "Erlaube Commits von Mitgliedern die zum Zielbranch mergen können."
@@ -565,6 +684,9 @@ msgstr "Erlaube es Benutzer(innen) Zugriff zu beantragen"
msgid "Allow users to request access if visibility is public or internal."
msgstr "Erlaube es Benutzer(innen) Zugriff zu beantragen, wenn die Sichtbarkeit Öffentlich oder Intern ist."
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Ermöglicht dir das Hinzufügen und Verwalten von Kubernetes-Clustern."
@@ -581,7 +703,7 @@ msgid "Alternatively, you can use a %{personal_access_token_link}. When you crea
msgstr "Alternativ kannst du einen %{personal_access_token_link} verwenden. Wenn du deinen persönlichen Access-Token erzeugst, musst du den Gültigkeitsbereich <code>repo</code> auswählen, damit wir eine Liste deiner öffentlichen und privaten Repositories anzeigen können, die für den Import verfügbar sind."
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
-msgstr ""
+msgstr "Dauer (in Stunden), für die der/die Benutzer(in) die erzwungene Konfiguration der Zwei-Faktor-Authentifizierung überspringen darf"
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr "Beim Absenden des Formulars wird automatisch ein SSH-Schlüssel generiert. Weitere Informationen findest du in der Dokumentation."
@@ -592,48 +714,21 @@ msgstr "Eine Anwendung namens %{link_to_client} fordert Zugriff auf dein GitLab-
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Bei einem leeren GitLab-Benutzerfeld wird der vollständigen Namen des FogBugz-Benutzers/-Benutzerin (z. B. \"Von John Smith\") in die Beschreibung aller Tickets und Kommentare eingefügt. Außerdem werden diese Tickets und Kommentare auch mit dem/der Projektersteller(in) assoziiert und/oder ihm/ihr zugewiesen."
-msgid "An error accured whilst committing your changes."
-msgstr "Beim Committen der Änderungen ist ein Fehler aufgetreten."
-
msgid "An error has occurred"
msgstr "Es ist ein Fehler aufgetreten"
-msgid "An error occured creating the new branch."
-msgstr "Beim Anlegen des neuen Branchs ist ein Fehler aufgetreten."
-
-msgid "An error occured whilst fetching the job trace."
-msgstr "Beim Abrufen der Fehlerprotokollierung des Jobs ist ein Fehler aufgetreten."
-
-msgid "An error occured whilst fetching the latest pipeline."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
-msgid "An error occured whilst loading all the files."
-msgstr "Beim Laden aller Dateien ist ein Fehler aufgetreten."
-
-msgid "An error occured whilst loading the file content."
-msgstr "Beim Laden des Dateiinhalts ist ein Fehler aufgetreten."
-
-msgid "An error occured whilst loading the file."
-msgstr "Beim Laden der Datei ist ein Fehler aufgetreten."
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr "Beim Laden der Merge-Request-Änderungen ist ein Fehler aufgetreten."
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr "Beim Laden der Versionsdaten des Merge-Requests ist ein Fehler aufgetreten."
-
-msgid "An error occured whilst loading the merge request."
-msgstr "Beim Laden des Merge-Requests ist ein Fehler aufgetreten."
-
-msgid "An error occured whilst loading the pipelines jobs."
-msgstr "Beim Laden der Pipeline-Jobs ist ein Fehler aufgetreten."
-
msgid "An error occurred adding a draft to the discussion."
msgstr "Beim Hinzufügen eines Entwurfs zur Diskussion ist ein Fehler aufgetreten."
msgid "An error occurred adding a new draft."
msgstr "Beim Hinzufügen eines neuen Entwurfs ist ein Fehler aufgetreten."
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Bei der Vorschau des Blobs ist ein Fehler aufgetreten"
@@ -706,12 +801,21 @@ msgstr "Beim Laden der Dateinamen ist ein Fehler aufgetreten"
msgid "An error occurred while loading the file"
msgstr "Beim Laden der Datei ist ein Fehler aufgetreten"
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr "Beim Bearbeiten der Anfrage ist ein Fehler aufgetreten."
msgid "An error occurred while removing approver"
msgstr "Beim Löschen eines Genehmigungsberechtigten ist ein Fehler aufgetreten"
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr "Beim Erstellen der Vorschau für KaTeX trat ein Fehler auf"
@@ -742,9 +846,54 @@ msgstr "Beim Aktualisieren des Kommentars ist ein Fehler aufgetreten"
msgid "An error occurred while validating username"
msgstr "Beim Validieren des Benutzernamens ist ein Fehler aufgetreten"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Ein Fehler ist aufgetreten. Bitte versuche es erneut."
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr "Analysen"
@@ -775,6 +924,21 @@ msgstr "Anwendung: %{name}"
msgid "Applications"
msgstr "Anwendungen"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "Apr"
@@ -787,6 +951,9 @@ msgstr "Archiviertes Projekt! Repository und andere Projektressourcen sind schre
msgid "Archived projects"
msgstr "Archivierte Projekte"
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Bist Du sicher, dass Du diesen Pipeline-Zeitplan löschen möchtest?"
@@ -796,12 +963,24 @@ msgstr "Bist du sicher, dass du diesen Build löschen möchtest?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Bist du sicher, dass du alle nicht gespeicherten Änderungen verwerfen möchtest?"
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "Möchtest du den öffentlichen Schlüssel wirklich neu generieren? Du musst dann den öffentlichen Schlüssel auf dem Remote-Server aktualisieren, bevor die Spiegelung wieder funktioniert."
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Bist du sicher, dass du %{group_name} wirklich entfernen willst?"
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr "Bist du sicher, dass du diese Identität entfernen willst?"
@@ -817,6 +996,9 @@ msgstr "Bist du sicher, dass du diese Umgebung stoppen möchtest?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Bist du sicher, dass du %{path_lock_path} entsperren willst?"
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "Bist Du sicher?"
@@ -835,6 +1017,9 @@ msgstr "Bitte deine(n) Gruppenbetreuer(in) einen Gruppenrunner einzurichten."
msgid "Assertion consumer service URL"
msgstr "Assertion-Consumer-Service-URL"
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "Benutzerdefinierte Farbe wie #FF0000 zuweisen"
@@ -844,6 +1029,9 @@ msgstr "Label zuweisen"
msgid "Assign milestone"
msgstr "Meilenstein zuweisen"
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr "Zuweisen an"
@@ -871,6 +1059,9 @@ msgstr "Zuweisungslisten zeigen alle dem ausgewählten Benutzer zugewiesenen Tic
msgid "Assignee(s)"
msgstr "Zugewiesene Personen"
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Datei mittels Drag &amp; Drop oder %{upload_link} hinzufügen"
@@ -883,6 +1074,9 @@ msgstr "Aug"
msgid "August"
msgstr "August"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "Authentifizierungsprotokoll"
@@ -898,6 +1092,9 @@ msgstr "Autor(in)"
msgid "Authorization code:"
msgstr "Autorisierungscode:"
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr "Die Autorisierung wurde erteilt, indem du deinen Benutzernamen und Passwort in die Anwendung eingeben hast."
@@ -925,15 +1122,6 @@ msgstr "Auto-DevOps aktiviert"
msgid "Auto DevOps, runners and job artifacts"
msgstr "Auto-DevOps, Runners und Jobartefakte"
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr "Auto-Review-Anwendungen und automatische Bereitstellung benötigen ein %{kubernetes} um korrekt zu funktionieren."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr "Auto-Review-Anwendungen und automatische Bereitstellung benötigen einen Domänennamen und ein %{kubernetes} um korrekt zu funktionieren."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "Auto-Review-Anwendungen und automatische Bereitstellung benötigen einen Domänennamen um korrekt zu funktionieren."
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr "Lösche redundante, ausstehende Pipelines automatisch"
@@ -967,14 +1155,26 @@ msgstr "aktiviere Auto-DevOps"
msgid "Automatically marked as default internal user"
msgstr "Automatisch als interne(r) Standardbenutzer(in) gekennzeichnet"
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "Verfügbar"
-msgid "Available group Runners : %{runners}"
-msgstr "Verfügbare Gruppen-Runner: %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
-msgid "Available group Runners : %{runners}."
-msgstr "Verfügbare Gruppen-Runner: %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr "Avatar wird entfernt. Bist du sicher?"
@@ -1159,6 +1359,12 @@ msgstr "Bitbucket-Server-Import"
msgid "Bitbucket import"
msgstr "Bitbucket-Import"
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr "Blog"
@@ -1168,11 +1374,6 @@ msgstr "Boards"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Branch %{branchName} wurde im Repository dieses Projekts nicht gefunden."
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] "Branch (%{branch_count})"
-msgstr[1] "Branches (%{branch_count})"
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "Branch <strong>%{branch_name}</strong> wurde erstellt. Um die automatische Bereitstellung einzurichten, wähle eine GitLab CI Yaml Vorlage und committe deine Änderungen. %{link_to_autodeploy_doc}"
@@ -1326,21 +1527,36 @@ msgstr "Dateien durchsuchen"
msgid "Browse files"
msgstr "Dateien durchsuchen"
-msgid "Built-In"
-msgstr "Integriert"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
msgid "Business metrics (Custom)"
msgstr "Business-Metriken (benutzerdefiniert)"
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "von"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr "CI/CD-Einstellungen"
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr "CI wird mit den oben angegebenen Anmeldeinformationen ausgeführt."
@@ -1377,12 +1593,6 @@ msgstr "Standard für Auto-DevOps-Pipeline"
msgid "CICD|Deployment strategy"
msgstr "Bereitstellungsstrategie"
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr "Die Bereitstellungsstrategie benötigt einen Domänennamen, um korrekt zu funktionieren."
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr "Richte hier keine Domäne ein, wenn du mehrere Kubernetes-Cluster mit Auto-DevOps einrichtest."
-
msgid "CICD|Jobs"
msgstr "Jobs"
@@ -1392,18 +1602,27 @@ msgstr "Erfahre mehr über Auto-DevOps"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr "Die Auto-DevOps-Pipeline wird ausgeführt, wenn keine alternative CI-Konfigurationsdatei gefunden wird."
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
-msgstr "Du musst eine Domäne angeben, wenn du Auto Review-Anwendungen und automatische Bereitstellungsphasen verwenden möchtest."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
msgid "CICD|instance enabled"
msgstr "Instanz aktiviert"
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr "Callback-URL"
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr "HEAD-Commit kann für diesen Branch nicht gefunden werden"
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "Abbrechen"
@@ -1416,12 +1635,21 @@ msgstr "Kann nicht automatisch zusammengeführt werden"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Kann verwalteten Kubernetes-Cluster nicht ändern"
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr "Zertifikat-Fingerabdruck"
msgid "Change Weight"
msgstr "Gewichtung ändern"
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr "Vorlage ändern"
@@ -1443,12 +1671,12 @@ msgstr "Wiederherstellen "
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Dies wird einen neuen Commit erzeugen, um die vorhandenen Änderungen rückgängig zu machen."
-msgid "Changelog"
-msgstr "Änderungsprotokoll"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "Änderungen werden angezeigt, als ob die <b>Quell</b>-Revision in die <b>Ziel</b>-Revision gemerged wurde."
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "Diagramme"
@@ -1458,9 +1686,15 @@ msgstr "Chat"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Lies die %{docs_link_start}Dokumentation%{docs_link_end}."
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr "Prüfe %{text} Verfügbarkeit…"
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "Überprüfe Verfügbarkeit des Branches..."
@@ -1482,6 +1716,12 @@ msgstr "Datei auswählen ..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Wähle einen Branch/Tag (z. B. %{master}) oder gib einen Commit ein (z. B. %{sha}), um zu sehen, was geändert wurde oder um einen Merge-Request zu erstellen."
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr "Wählen Sie eine Vorlage..."
@@ -1500,6 +1740,9 @@ msgstr "Datei auswählen..."
msgid "Choose the top-level group for your repository imports."
msgstr "Wähle die übergeordnetste Gruppe für deine Repository-Importe."
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr "Wähle die Gruppen aus, die du mit diesem sekundären Knoten synchronisieren möchtest."
@@ -1519,7 +1762,7 @@ msgid "CiStatusLabel|created"
msgstr "erstellt"
msgid "CiStatusLabel|delayed"
-msgstr ""
+msgstr "verzögert"
msgid "CiStatusLabel|failed"
msgstr "fehlgeschlagen"
@@ -1555,7 +1798,7 @@ msgid "CiStatusText|created"
msgstr "erstellt"
msgid "CiStatusText|delayed"
-msgstr ""
+msgstr "verzögert"
msgid "CiStatusText|failed"
msgstr "fehlgeschlagen"
@@ -1593,8 +1836,8 @@ msgstr "Alle Umgebungen"
msgid "CiVariable|Create wildcard"
msgstr "Wildcard erstellen"
-msgid "CiVariable|Error occured while saving variables"
-msgstr "Beim Speichern der Variablen ist ein Fehler aufgetreten"
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
msgid "CiVariable|New environment"
msgstr "Neue Umgebung"
@@ -1614,6 +1857,12 @@ msgstr "Validierung fehlgeschlagen"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "ist nicht verfügbar: %{reason}"
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr "Suche löschen"
@@ -1653,28 +1902,52 @@ msgstr "Kennwort für den Client-Authentifizierungsschlüssel"
msgid "Clients"
msgstr "Kunden"
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr "Repository klonen"
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr "Schließen"
msgid "Close epic"
msgstr "Epic schließen"
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr "Geschlossen"
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr "Geschlossene Tickets"
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} wurde erfolgreich auf deinem Kubernetes-Cluster installiert"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr "%{boldNotice} Hierdurch werden einige zusätzliche Ressourcen wie ein Load-Balancer hinzugefügt, was je nach Hosting-Provider, auf dem dein Kubernetes-Cluster installiert ist, zusätzliche Kosten verursachen kann. Wenn du Google Kubernetes-Engine verwendest, kannst du %{pricingLink}."
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1684,13 +1957,13 @@ msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Kubernetes-Cluster hinzufügen"
msgid "ClusterIntegration|Add a Kubernetes cluster integration"
-msgstr ""
+msgstr "ClusterIntegration|Eine Kubernetes-Cluster-Integration hinzufügen"
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 "Wenn du deiner Gruppe ein Kubernetes-Cluster hinzufügst, wird das Cluster automatisch von allen deinen Projekten geteilt. Benutze Review-Anwendungen, stelle deine Anwendungen bereit und führe einfach alle deine Pipelines für alle Projekte auf dem selben Cluster aus."
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "Wenn du deiner Gruppe eine Integration hinzufügst, wird das Cluster von allen deinen Projekten geteilt."
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Erweiterte Optionen für die Integration dieses Kubernetes-Clusters"
@@ -1698,27 +1971,42 @@ msgstr "Erweiterte Optionen für die Integration dieses Kubernetes-Clusters"
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr "Nachdem Ingress installiert wurde, solltest du deine Wildcard-DNS an die generierte externe IP-Adresse anpassen, um deine App nach der Bereitstellung sichtbar zu machen. %{ingressHelpLink}"
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "Beim Abrufen der Projektzonen ist ein Fehler aufgetreten: %{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr "Beim Abrufen deiner Projekte ist ein Fehler aufgetreten: %{error}"
-
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
-msgstr "Ein Fehler ist bei dem Versuch aufgetreten die Maschinentypen der Zone aufzurufen: %{error}"
-
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr "Ein Fehler ist bei dem Verbindungsversuch mit der Google Cloud API aufgetreten. Bitte versuche es später erneut."
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "Anwendungen"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr "Bist du sicher, dass du die Integration dieses Kubernetes-Clusters entfernen möchtest? Dadurch wird dein tatsächlicher Kubernetes-Cluster nicht gelöscht."
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr "CA-Zertifikat"
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Zertifizierungsstellen-Bundle (PEM-Format)"
@@ -1728,6 +2016,9 @@ msgstr "Wähle, welche Anwendungen auf deinem Kubernetes Cluster installiert wer
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Wähle, welche deiner Umgebungen du für dieses Cluster verwenden willst."
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "API-URL kopieren"
@@ -1740,6 +2031,9 @@ msgstr "Ingress-IP-Adresse in die Zwischenablage kopieren"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr "Jupyter-Hostnamen in die Zwischenablage kopieren"
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Kubernetes-Clusternamen kopieren"
@@ -1767,6 +2061,15 @@ msgstr "Umgebungsumfang"
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 "Jedes neue Google Cloud Platform-Konto (GCP-Konto) erhält 300 $ Guthaben bei %{sign_up_link}. In Zusammenarbeit mit Google kann GitLab zusätzlich 200 $ für neue und bestehende GCP-Konten anbieten, um mit GitLabs Integration der Google Kubernetes-Engine zu beginnen."
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr "Abrufen von Maschinentypen"
@@ -1795,7 +2098,7 @@ msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Google Kubernetes-Engine-Projekt"
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "Cluster gruppieren"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1839,6 +2142,12 @@ msgstr "Kubernetes-Cluster-Automatisierung integrieren"
msgid "ClusterIntegration|Integration status"
msgstr "Integrationsstatus"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Jupyter-Hostname"
@@ -1849,9 +2158,15 @@ msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and pro
msgstr "JupyterHub, ein Mehrbenutzer-Hub, erstellt, verwaltet und leitet mehrere Instanzen des Jupyter-Notebook-Servers für Einzelbenutzer. JupyterHub kann verwendet werden, um Notebooks an eine Klasse von Studenten, eine Unternehmens-Data-Science-Gruppe oder eine wissenschaftliche Forschungsgruppe zu liefern."
msgid "ClusterIntegration|Knative"
-msgstr ""
+msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
+msgstr "Knative Domainname:"
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster"
@@ -1873,7 +2188,7 @@ msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google
msgstr "Kubernetes-Cluster wurde erfolgreich mit der Google Kubernetes Engine erstellt. Aktualisiere die Seite um Clusterdetails anzuzeigen"
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
+msgstr "Kubernetes-Cluster ermöglichen dir auf einfache Weise die Benutzung der Review-Anwendungen, die Bereitstellung deiner Anwendungen, deine Pipelines auszuführen, und vieles mehr."
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Kubernetes-Cluster können zum Bereitstellen von Anwendungen und zur Zur­ver­fü­gung­stel­lung von Review-Anwendungen für dieses Projekt verwendet werden"
@@ -1885,9 +2200,12 @@ msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_en
msgstr "Erfahre mehr über %{help_link_start}Zonen%{help_link_end}."
msgid "ClusterIntegration|Learn more about Kubernetes"
-msgstr ""
+msgstr "Lerne mehr über Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr "Lerne mehr über die Kubernetes Gruppen-Cluster"
+
+msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1933,7 +2251,7 @@ msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in o
msgstr "Verweise mit einem Wildcard-DNS auf diese generierte IP-Adresse um auf deine Anwendung zugreifen zu können, nachdem sie bereitgestellt wurde."
msgid "ClusterIntegration|Project cluster"
-msgstr ""
+msgstr "Projektcluster"
msgid "ClusterIntegration|Project namespace"
msgstr "Projekt-Namensraum"
@@ -1948,7 +2266,7 @@ msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{
msgstr "Prometheus ist ein Open-Source-Ãœberwachungssystem mit %{gitlabIntegrationLink} zur Ãœberwachung von bereitgestellten Anwendungen."
msgid "ClusterIntegration|RBAC-enabled cluster"
-msgstr ""
+msgstr "RBAC-kompatibles Cluster"
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr "Lies unsere %{link_to_help_page} zur Kubernetes-Cluster-Integration."
@@ -1968,6 +2286,9 @@ msgstr "Ersetze dies mit deinem eigenen Hostnamen wenn du möchtest. Wenn du die
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Anfrage zur Installation fehlgeschlagen"
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr "Änderungen speichern"
@@ -2010,12 +2331,18 @@ msgstr "Zeige"
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Auf unserer Seite ist etwas schief gelaufen."
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr "Beim Erstellen deines Kubernetes-Clusters auf der Google Kubernetes Engine ist etwas schief gelaufen"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Beim Installieren von %{title} ist ein Fehler aufgetreten"
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr "Die IP-Adresse wird gerade zugewiesen. Wenn es lange dauert, überprüfe bitte dein Kubernetes-Cluster oder dein Kontingent für die Google Kubernetes-Engine."
@@ -2031,6 +2358,18 @@ msgstr "Kubernetes-Cluster umschalten"
msgid "ClusterIntegration|Token"
msgstr "Token"
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr "Validierung des Projektabrechnungsstatus"
@@ -2043,6 +2382,9 @@ msgstr "Mit einem Kubernetes-Cluster innerhalb dieses Projekts kannst du auf ein
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "Du musst zuerst Helm Tiller installieren, bevor du die Anwendung unten installierst"
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Dein Account benötigt eine %{link_to_kubernetes_engine}"
@@ -2070,6 +2412,9 @@ msgstr "ordnungsgemäß konfiguriert"
msgid "ClusterIntegration|sign up"
msgstr "Registrierung"
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr "Code-Besitzer(innen)"
@@ -2082,8 +2427,17 @@ msgstr "Reduzieren"
msgid "Collapse sidebar"
msgstr "Seitenleiste einklappen"
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
-msgstr "Kommentar"
+msgstr "Kommentieren"
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
msgid "Comment & resolve discussion"
msgstr "Kommentieren & Diskussion beenden"
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] "Commit"
msgstr[1] "Commits"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] "Commit (%{commit_count})"
-msgstr[1] "Commits (%{commit_count})"
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "Commit-Nachricht"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "Dauer der Commits in Minuten für die letzten 30 Commits"
@@ -2173,6 +2528,9 @@ msgstr "Vergleiche Git-Revisionen"
msgid "Compare Revisions"
msgstr "Vergleiche Revisionen"
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr "Vergleiche Änderungen mit dem letzten Commit"
@@ -2200,10 +2558,16 @@ msgstr "Vertraulich"
msgid "Confidentiality"
msgstr "Vertraulichkeit"
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr "Zeitüberschreitung für Gitaly konfigurieren."
msgid "Configure Tracing"
+msgstr "Tracing konfigurieren"
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2239,6 +2603,9 @@ msgstr "Verbinde deine externen Repositories, und CI/CD-Pipelines werden für ne
msgid "Connecting..."
msgstr "Verbinden..."
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr "Container-Registry"
@@ -2287,6 +2654,9 @@ msgstr "Mit der in GitLab integrierten Docker-Container-Registry kann jedes Proj
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Du kannst auch %{deploy_token} für den schreibgeschützten Zugriff auf die Registry-Images verwenden."
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr "Fortsetzen"
@@ -2302,8 +2672,8 @@ msgstr "Trage etwas zu GitLab bei"
msgid "Contribution"
msgstr "Beitrag"
-msgid "Contribution guide"
-msgstr "Anleitung zur Mitarbeit"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr "Beiträge am <strong>%{calendar_date}</strong>"
@@ -2338,21 +2708,27 @@ msgstr "Steuere die maximale Parallelität des Repository-Backfills für diesen
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr "Steuere die maximale Parallelität von Verifizierungsoperationen für diesen Geo-Knoten"
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr "ConvDev-Index"
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Kopiere %{protocol} clone-URL"
-msgid "Copy HTTPS clone URL"
-msgstr "Kopiere HTTPS clone-URL"
-
msgid "Copy ID to clipboard"
msgstr "ID in Zwischenablage kopieren"
msgid "Copy SSH clone URL"
msgstr "Kopiere SSH clone-URL"
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr "Kopiere öffentlichen SSH-Schlüssel in die Zwischenablage"
@@ -2375,16 +2751,13 @@ msgid "Copy incoming email address to clipboard"
msgstr "Eingehende E-Mail-Adresse in Zwischenablage kopieren"
msgid "Copy link"
-msgstr ""
-
-msgid "Copy name to clipboard"
-msgstr "Name in Zwischenablage kopieren"
+msgstr "Link kopieren"
msgid "Copy reference to clipboard"
msgstr "Referenz in Zwischenablage kopieren"
msgid "Copy secret to clipboard"
-msgstr ""
+msgstr "Secret in Zwischenablage kopieren"
msgid "Copy to clipboard"
msgstr "In Zwischenablage kopieren"
@@ -2393,7 +2766,7 @@ msgid "Copy token to clipboard"
msgstr "Token in Zwischenablage kopieren"
msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
-msgstr ""
+msgstr "Der Status der Pipeline konnte nicht abgerufen werden. Zur Fehlerbehebung lies die %{linkStart}Dokumentation.%{linkEnd}"
msgid "Create"
msgstr "Erstellen"
@@ -2401,6 +2774,9 @@ msgstr "Erstellen"
msgid "Create New Directory"
msgstr "Erstelle neues Verzeichnis"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr "Erstelle einen neuen Branch"
@@ -2410,6 +2786,9 @@ msgstr "Erstelle einen neuen Branch und Merge-Request"
msgid "Create a new issue"
msgstr "Neues Ticket erstellen"
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Erstelle einen persönlichen Zugriffstoken in deinem Konto um mittels %{protocol} zu übertragen (push) oder abzurufen (pull)."
@@ -2449,6 +2828,9 @@ msgstr "Erstelle Merge-Request"
msgid "Create merge request and branch"
msgstr "Merge-Request und Branch erstellen"
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "Neuen Branch erstellen"
@@ -2515,9 +2897,6 @@ msgstr "Profil"
msgid "CurrentUser|Settings"
msgstr "Einstellungen"
-msgid "Custom"
-msgstr "Benutzerdefiniert"
-
msgid "Custom CI config path"
msgstr "Benutzerdefinierter CI-Konfigurationspfad"
@@ -2533,6 +2912,9 @@ msgstr "Benutzerdefinierte Benachrichtigungsstufen sind identisch mit den Beteil
msgid "Custom project templates"
msgstr "Benutzerspezifische Projektvorlage"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr "Farben anpassen"
@@ -2542,9 +2924,15 @@ msgstr "Passe an, wie E-Mail-Adressen und Benutzernamen von FogBugz in GitLab im
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "Passe an, wie E-Mail-Adressen und Benutzernamen von Google Code in GitLab importiert werden. Im nächsten Schritt kannst du die Projekte auswählen, die du importieren möchtest."
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr "Passe deine Pipeline-Konfiguration an und zeige deinen Pipeline-Status und den Abdeckungsbericht an."
+
msgid "Cycle Analytics"
msgstr "Zyklusanalysen"
@@ -2572,6 +2960,9 @@ msgstr "Staging"
msgid "CycleAnalyticsStage|Test"
msgstr "Test"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr "Dashboard"
@@ -2581,6 +2972,9 @@ msgstr "Alle"
msgid "DashboardProjects|Personal"
msgstr "Persönliche"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr "Datumsauswahl"
@@ -2593,6 +2987,9 @@ msgstr "Dez"
msgid "December"
msgstr "Dezember"
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr "Ablehnen und abmelden"
@@ -2602,6 +2999,12 @@ msgstr "Default-Branch"
msgid "Default classification label"
msgstr "Standardklassifikationslabel"
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr "Standard: Importiere direkt die Google Code-E-Mail-Adresse oder den Nutzernamen"
@@ -2611,20 +3014,23 @@ msgstr "Standard: Ordne eine FogBugz-Konto-ID einem vollständigen Namen zu"
msgid "Define a custom pattern with cron syntax"
msgstr "Erstelle ein benutzerdefiniertes Muster mittels Cron-Syntax"
-msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr "Bist du sicher, dass du %{jobName} sofort ausführen möchtest? Andernfalls wird dieser Job nach Ablauf des Timers automatisch ausgeführt."
+
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
-msgstr ""
+msgstr "Bist du sicher, dass du %{job_name} sofort ausführen möchtest? Dieser Job wird automatisch nach Ablauf des Timers ausgeführt."
msgid "DelayedJobs|Start now"
msgstr "Jetzt starten"
msgid "DelayedJobs|Unschedule"
-msgstr ""
+msgstr "Zeitplan aufheben"
msgid "DelayedJobs|delayed"
-msgstr ""
+msgstr "verzögert"
msgid "Delete"
msgstr "Löschen"
@@ -2636,11 +3042,17 @@ msgid "Delete Snippet"
msgstr "Codeausschnitt löschen"
msgid "Delete comment"
-msgstr ""
+msgstr "Kommentar entfernen"
msgid "Delete list"
msgstr "Liste löschen"
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr "Gelöscht"
@@ -2775,6 +3187,9 @@ msgstr "Dein neuer Bereitstellungstoken"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Dein neuer Projektbereitstellungstoken wurde erstellt."
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr "Bereitgestellt für"
@@ -2802,11 +3217,14 @@ msgstr "Löschen"
msgid "Details"
msgstr "Details"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr "Hostschlüssel erkennen"
msgid "Diff content limits"
-msgstr ""
+msgstr "Diff Inhaltsbeschränkungen"
msgid "Diff limits"
msgstr "Diff-Grenzen"
@@ -2832,6 +3250,12 @@ msgstr "Für dieses Projekt deaktivieren"
msgid "Disable group Runners"
msgstr "Gruppen-Runner deaktivieren"
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr "Verwerfen"
@@ -2853,15 +3277,24 @@ msgstr "Entwurf verwerfen"
msgid "Discard review"
msgstr "Review verwerfen"
-msgid "Discover GitLab Geo."
-msgstr "Entdecke GitLab Geo."
+msgid "Discover GitLab Geo"
+msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "Entdecke Projekte, Gruppen und Codeausschnitte. Teile deine Projekte mit anderen"
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr "Verwerfen"
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "Einführungsbox zur Zyklusanalyse ausblenden"
@@ -2869,7 +3302,7 @@ msgid "Dismiss Merge Request promotion"
msgstr "Hervorheben des Merge-Requests beenden"
msgid "Dismiss trial promotion"
-msgstr ""
+msgstr "Testversions-Hinweis ausblenden"
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Möchtest du festlegen, wie die E-Mail-Adressen und Nutzernamen von Google Code in GitLab importiert werden?"
@@ -2889,6 +3322,12 @@ msgstr "Erledigt"
msgid "Download"
msgstr "Herunterladen"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "TAR-Datei herunterladen"
@@ -2913,6 +3352,9 @@ msgstr "Einfaches Diff"
msgid "DownloadSource|Download"
msgstr "Herunterladen"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr "Negativ bewertet"
@@ -2928,9 +3370,15 @@ msgstr "Jeder Runner kann in einem der folgenden Zustände sein:"
msgid "Edit"
msgstr "Bearbeiten"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr "Label bearbeiten"
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Pipeline-Zeitplan bearbeiten %{id}"
@@ -2940,6 +3388,12 @@ msgstr "Codeausschnitt bearbeiten"
msgid "Edit application"
msgstr "Anwendung bearbeiten"
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr "Bearbeite Dateien im Editor und committe die Änderungen hier"
@@ -2949,11 +3403,14 @@ msgstr "Gruppe bearbeiten: %{group_name}"
msgid "Edit identity for %{user_name}"
msgstr "Identität für %{user_name} bearbeiten"
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr "Elasticsearch"
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
+msgstr "Elasticsearch-Integration. Elasticsearch AWS IAM."
msgid "Email"
msgstr "E-Mail"
@@ -2967,6 +3424,9 @@ msgstr "E-Mails"
msgid "Embed"
msgstr "Einbetten"
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr "Aktivieren"
@@ -2991,6 +3451,9 @@ msgstr "Aktiviere und konfiguriere Prometheus-Messwerte."
msgid "Enable classification control using an external service"
msgstr "Aktiviere die Klassifizierungskontrolle mithilfe eines externen Service"
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr "Für dieses Projekt aktivieren"
@@ -3006,9 +3469,18 @@ msgstr "Aktiviere oder deaktiviere die Versionsprüfung und den Nutzungsbericht.
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "Aktiviere reCAPTCHA oder Akismet und lege die IP-Grenzwerte fest."
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr "Aktiviere die Performance-Leiste für eine bestimmte Gruppe."
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr "Nutzungsbericht einschalten"
@@ -3021,6 +3493,12 @@ msgstr "Aktiviert"
msgid "Ends at (UTC)"
msgstr "Endet am (UTC)"
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "Gib unten deine Bitbucket-Server-URL und deinen persönlichen Zugriffstoken ein"
@@ -3036,9 +3514,27 @@ msgstr "Gib die Beschreibung des Merge-Requests ein"
msgid "Enter the merge request title"
msgstr "Gib den Titel des Merge-Requests ein"
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr "Umgebungen"
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Beim Abrufen der Umgebungen ist ein Fehler aufgetreten."
@@ -3114,6 +3610,9 @@ msgstr "Stopp"
msgid "Environments|Stop environment"
msgstr "Umgebung stoppen"
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Aktualisiert"
@@ -3126,9 +3625,6 @@ msgstr "geschützt"
msgid "Epic"
msgstr "Epic"
-msgid "Epic will be removed! Are you sure?"
-msgstr "Epic wird entfernt! Bist du dir sicher?"
-
msgid "Epics"
msgstr "Epics"
@@ -3138,8 +3634,8 @@ msgstr "Epics Roadmap"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Mit Epics können Sie Ihre Projekte effizienter und mit weniger Aufwand verwalten"
-msgid "Epics|An error occurred while saving %{epicDateType} date"
-msgstr "Fehler beim Speichern des %{epicDateType}-Datums"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
msgid "Epics|How can I solve this?"
msgstr "Wie kann ich dieses Problem lösen?"
@@ -3165,9 +3661,15 @@ msgstr "Fehler"
msgid "Error Reporting and Logging"
msgstr "Fehlerberichterstattung und Protokollierung"
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr "Fehler beim Erstellen des Epics"
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr "Fehler beim Abrufen der Daten der Mitwirkenden."
@@ -3210,9 +3712,15 @@ msgstr "Fehler beim Laden der Vorlage."
msgid "Error occurred when toggling the notification subscription"
msgstr "Beim Umschalten des Benachrichtigungs-Abonnements trat ein Fehler auf"
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr "Fehler beim Speichern der Label-Aktualisierung."
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr "Fehler beim Aktualisieren des Status für alle To-dos."
@@ -3222,6 +3730,12 @@ msgstr "Fehler beim Aktualisieren des To-do-Status."
msgid "Error while loading the merge request. Please try again."
msgstr "Fehler beim Laden des Merge-Requests. Bitte versuche es erneut."
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr "Geschätzt"
@@ -3243,6 +3757,12 @@ msgstr "Filtere nach Push-Ereignissen"
msgid "EventFilterBy|Filter by team"
msgstr "Filtere nach Teams"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Täglich (um 4:00 Uhr)"
@@ -3252,9 +3772,39 @@ msgstr "Monatlich (am Ersten um 4:00 Uhr)"
msgid "Every week (Sundays at 4:00am)"
msgstr "Wöchentlich (Sonntags um 4:00 Uhr)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr "Jeder kann beitragen"
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr "Aufklappen"
@@ -3267,9 +3817,15 @@ msgstr "Menüleiste ausklappen"
msgid "Expiration date"
msgstr "Ablaufdatum"
-msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr "Erläutere das Problem. Falls erforderlich, gib einen Link zu dem fraglichen Ticket oder Kommentar an."
+
msgid "Explore"
msgstr "Erkunden"
@@ -3288,9 +3844,21 @@ msgstr "Projekte erkunden"
msgid "Explore public groups"
msgstr "Erkunde öffentliche Gruppen"
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr "Externe Autorisierung der Klassifikationsrichtlinie"
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr "Externe Authentifizierung"
@@ -3330,6 +3898,9 @@ msgstr "Bereitstellung fehlgeschlagen für"
msgid "Failed to load emoji list."
msgstr "Fehler beim Laden der Emoji-Liste."
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "Fehler beim Entfernen des Tickets vom Bord, bitte versuche es erneut."
@@ -3339,19 +3910,34 @@ msgstr "Fehler beim Entfernen des Mirrors."
msgid "Failed to remove the pipeline schedule"
msgstr "Entfernung der Pipelineplanung fehlgeschlagen"
-msgid "Failed to signing using smartcard authentication"
+msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr "Signieren mit Smartcard-Authentifizierung fehlgeschlagen"
+
msgid "Failed to update issues, please try again."
msgstr "Tickets konnten nicht aktualisiert werden, bitte versuche es erneut."
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr "Fehlschlag"
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "Schneller als wenn es den Projektarbeitsplatz wieder benützt (fällt zurück auf den Clone wenn es nicht existiert)"
msgid "Feature Flags"
+msgstr "Feature Flags"
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
msgstr ""
msgid "FeatureFlags|API URL"
@@ -3360,52 +3946,70 @@ msgstr "API-URL"
msgid "FeatureFlags|Active"
msgstr "Aktiv"
-msgid "FeatureFlags|Application name"
-msgstr "Anwendungsname"
-
msgid "FeatureFlags|Configure"
msgstr "Konfiguriere"
msgid "FeatureFlags|Configure feature flags"
-msgstr ""
+msgstr "Feature-Flags konfigurieren"
msgid "FeatureFlags|Create feature flag"
+msgstr "Feature-Flag erstellen"
+
+msgid "FeatureFlags|Delete %{name}?"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
-msgstr "%{feature_flag_name} löschen?"
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
msgid "FeatureFlags|Description"
-msgstr ""
+msgstr "Beschreibung"
msgid "FeatureFlags|Edit %{feature_flag_name}"
-msgstr ""
+msgstr "%{feature_flag_name} bearbeiten"
msgid "FeatureFlags|Edit Feature Flag"
+msgstr "Feature-Flag bearbeiten"
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
msgstr ""
msgid "FeatureFlags|Feature Flag"
+msgstr "Feature-Flag"
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
+msgstr "Inaktiv"
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr ""
+msgstr "Installiere eine %{docs_link_start}kompatible Client-Bibliothek%{docs_link_end} und gib während der Konfiguration die API-URL, den Namen der Anwendung und die Instanz-ID an."
msgid "FeatureFlags|Instance ID"
+msgstr "Instanz-ID"
+
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
msgstr ""
msgid "FeatureFlags|More information"
@@ -3418,7 +4022,7 @@ msgid "FeatureFlags|New"
msgstr "Neu"
msgid "FeatureFlags|New Feature Flag"
-msgstr ""
+msgstr "Neues Feature-Flag"
msgid "FeatureFlags|Save changes"
msgstr "Änderungen speichern"
@@ -3426,6 +4030,21 @@ msgstr "Änderungen speichern"
msgid "FeatureFlags|Status"
msgstr "Status"
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr "Feb"
@@ -3435,15 +4054,35 @@ msgstr "Februar"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "Felder auf dieser Seite sind jetzt nicht mehr editierbar, du kannst nun konfigurieren"
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr "Dateivorlagen"
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "Dateien"
-msgid "Files (%{human_size})"
-msgstr "Dateien (%{human_size})"
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "Fülle die Felder unten aus, schalte <strong>%{enable_label}</strong> an, und drücke <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr "Filtern nach %{issuable_type}, die derzeit offen sind."
msgid "Filter by commit message"
msgstr "Filter nach Commit-Nachricht"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr "Filter..."
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "Finde über den Pfad"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "Finde Datei"
@@ -3477,12 +4134,18 @@ msgstr "Suche die neu extrahierte Datei <code>Takeout/Google Code Project Hostin
msgid "Fingerprints"
msgstr "Fingerabdrücke"
-msgid "Finish review"
+msgid "Finish editing this message first!"
msgstr ""
+msgid "Finish review"
+msgstr "Review beenden"
+
msgid "Finished"
msgstr "Fertiggestellt"
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "Erster"
@@ -3528,11 +4191,14 @@ msgstr "Fußzeilennachricht"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "Bei interne Projekte kann jede(r) angemeldete Benutzer(in) die Pipelines anzeigen lassen und auf Job-Details (Ausgabeprotokolle und Artefakte) zugreifen"
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr "Für mehr Informationen, gehe zu "
msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr ""
+msgstr "Lies für weitere Informationen bitte die %{link_start_tag}Jaeger Konfigurationsdokumentation%{link_end_tag}"
msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
msgstr "Weitere Informationen zum %{deactivating_usage_ping_link_start}Deaktivieren des Nutzungsberichts%{deactivating_usage_ping_link_end} findest du in der Dokumentation."
@@ -3552,6 +4218,9 @@ msgstr "Geforkt von %{project_name} (gelöscht)"
msgid "Forking in progress"
msgstr "Fork wird erstellt"
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "Format"
@@ -3559,7 +4228,7 @@ msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Fehler in deiner .gitlab-ci.yml gefunden:"
msgid "Free Trial of GitLab.com Gold"
-msgstr ""
+msgstr "Kostenlose Testversion von GitLab.com Gold"
msgid "From %{provider_title}"
msgstr "Von %{provider_title}"
@@ -3603,6 +4272,9 @@ msgstr "Allgemeine Pipelines"
msgid "Generate a default set of labels"
msgstr "Generiere einen Standardsatz von Labels"
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr "Geo"
@@ -3693,8 +4365,11 @@ msgstr "Keine Prüfsumme"
msgid "GeoNodes|Out of sync"
msgstr "Nicht synchron"
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
-msgstr "Durch das Entfernen eines Knotens wird der Synchronisierungsprozess gestoppt. Bist du sicher?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
msgid "GeoNodes|Replication slot WAL"
msgstr "Replikations-Slot WAL"
@@ -3768,6 +4443,9 @@ msgstr "Wiki-Prüfsummen wurden mit ihren Gegenstücken auf dem sekundären Knot
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr "Wikis wurden mit ihren Gegenstücken auf dem primären Knoten verifiziert"
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr "Du hast Geo-Knoten mit einer unsicheren HTTP-Verbindung konfiguriert. Wir empfehlen die Verwendung von HTTPS."
@@ -3787,10 +4465,10 @@ msgid "Geo|All projects"
msgstr "Alle Projekte"
msgid "Geo|All projects are being scheduled for re-check"
-msgstr ""
+msgstr "Alle Projekte sind für eine erneute Überprüfung eingeplant"
msgid "Geo|All projects are being scheduled for re-sync"
-msgstr ""
+msgstr "Alle Projekte sind für eine erneute Synchronisierung eingeplant"
msgid "Geo|Batch operations"
msgstr "Stapelverarbeitung"
@@ -3813,6 +4491,9 @@ msgstr "Gruppen für die Synchronisierung"
msgid "Geo|In sync"
msgstr "Wird synchronisiert"
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr "Letzte erfolgreiche Synchronisierung"
@@ -3829,7 +4510,7 @@ msgid "Geo|Next sync scheduled at"
msgstr "Nächste Synchronisierung geplant um"
msgid "Geo|Not synced yet"
-msgstr ""
+msgstr "Noch nicht synchronisiert"
msgid "Geo|Pending"
msgstr "Ausstehend"
@@ -3849,11 +4530,14 @@ msgstr "Projekte in bestimmten Gruppen"
msgid "Geo|Projects in certain storage shards"
msgstr "Projekte in bestimmten Speicherfragmenten"
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr "Neuprüfung"
msgid "Geo|Recheck all projects"
-msgstr ""
+msgstr "Alle Projekte überprüfen"
msgid "Geo|Redownload"
msgstr "Erneuter Download"
@@ -3868,7 +4552,7 @@ msgid "Geo|Resync"
msgstr "Resynchronisation"
msgid "Geo|Resync all projects"
-msgstr ""
+msgstr "Alle Projekte erneut synchronisieren"
msgid "Geo|Retry count"
msgstr "Wiederholversuch"
@@ -3907,10 +4591,10 @@ msgid "Geo|Waiting for scheduler"
msgstr "Warte auf den Scheduler"
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
+msgstr "Du befindest dich auf einem sekundären, <b>read-only</b> Geo-Knoten. Um Änderungen vorzunehmen, musst du diese Seite auf dem %{primary_node} aufrufen."
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
-msgstr ""
+msgstr "Du befindest dich auf einem sekundären, <b>read-only</b> Geo-Knoten. Möglicherweise kannst du nur eine begrenzte Anzahl an Änderungen oder Aktionen auf dieser Seite durchführen."
msgid "Geo|You need a different license to use Geo replication"
msgstr "Du benötigst eine andere Lizenz, um die Geo-Replikation zu verwenden"
@@ -3927,9 +4611,18 @@ msgstr "sekundär"
msgid "Get a free instance review"
msgstr "Erhalte eine kostenlose Instanzprüfung"
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr "Git"
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr "Git-Repository-URL"
@@ -3957,9 +4650,15 @@ msgstr "GitLab Gruppenrunner können Code für alle Projekte in dieser Gruppe au
msgid "GitLab Import"
msgstr "GitLab-Import"
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr "GitLab-Nutzer(in)"
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr "GitLab-Projekt exportieren"
@@ -3990,6 +4689,9 @@ msgstr "Gitea-Host-URL"
msgid "Gitea Import"
msgstr "Gitea-Import"
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr "Zurück"
@@ -4014,6 +4716,9 @@ msgstr "Google-Authentifizierung ist nicht %{link_to_documentation}. Frage deine
msgid "Got it!"
msgstr "Verstanden!"
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr "Diagramm"
@@ -4033,7 +4738,7 @@ msgid "Group Runners"
msgstr "Gruppen Runner"
msgid "Group SAML must be enabled to test"
-msgstr ""
+msgstr "Gruppen-SAML muss zum Testen aktiviert sein"
msgid "Group URL"
msgstr "Gruppen-URL"
@@ -4059,15 +4764,18 @@ msgstr "Gruppenbetreuer können Gruppen-Runner unter %{link} registrieren"
msgid "Group name"
msgstr "Gruppenname"
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr "Gruppe: %{group_name}"
msgid "GroupRoadmap|From %{dateWord}"
msgstr "Vom %{dateWord}"
-msgid "GroupRoadmap|Loading roadmap"
-msgstr "Roadmap wird geladen"
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Beim Abfragen der Epics ist etwas schief gelaufen"
@@ -4077,23 +4785,11 @@ msgstr "Entschuldigung, keine Epics stimmen mit deiner Suche überein"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "Die Roadmap zeigt den Fortschritt deiner Epics anhand einer Zeitleiste an"
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. Nur Epics der letzten oder nächsten Monate werden angezeigt &ndash; von %{startDate} bis %{endDate}."
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. In der Quartalsansicht werden nur Epics im letzten Quartal, im aktuellen Quartal und in den nächsten 4 Quartalen angezeigt &ndash; von %{startDate} bis %{endDate}."
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. In der Wochenansicht werden nur Epics der letzten Woche, der aktuellen Woche und der nächsten 4 Wochen angezeigt &ndash; von %{startDate} bis %{endDate}."
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Um deine Suche auszuweiten, ändere oder entferne Filter. In der Monatsansicht werden nur Epics des letzten Monats, des aktuellen Monats und der nächsten 5 Monate angezeigt &ndash; von %{startDate} bis %{endDate}."
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Um deine Suche auszuweiten, ändere oder entferne Filter. In der Quartalsansicht werden nur Epics des letzten Quartals, des aktuellen Quartals und der nächsten 4 Quartale angezeigt &ndash; von %{startDate} bis %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Um deine Suche auszuweiten, ändere oder entferne Filter. In der Wochenansicht werden nur Epics der letzten Woche, de aktuellen Woche und der nächsten 4 Wochen angezeigt &ndash; von %{startDate} bis %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
msgid "GroupRoadmap|Until %{dateWord}"
msgstr "Bis %{dateWord}"
@@ -4101,15 +4797,24 @@ msgstr "Bis %{dateWord}"
msgid "GroupSettings|Badges"
msgstr "Badges"
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
msgid "GroupSettings|Customize your group badges."
msgstr "Deine Gruppen-Badges anpassen."
msgid "GroupSettings|Learn more about badges."
msgstr "Erfahre mehr über Badges."
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Freigabe eines Projekts innerhalb %{group} mit anderen Gruppen verhindern"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Diese Einstellung wird auf %{ancestor_group} angewendet und wurde für diese Untergruppe überschrieben."
@@ -4134,6 +4839,9 @@ msgstr "Gruppen"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "Gruppen können durch %{subgroup_docs_link_start}Untergruppen%{subgroup_docs_link_end} verschachtelt werden."
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr "Häufig besucht"
@@ -4233,6 +4941,9 @@ msgstr "Text der Hilfeseite und die Supportseiten-URL."
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr "Hier ist der öffentliche SSH-Schlüssel, der auf dem Remote-Server hinzugefügt werden muss. Weitere Informationen findest du in der Dokumentation."
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr "Manuelle Eingabe der Host-Tasten ausblenden"
@@ -4244,8 +4955,8 @@ msgid_plural "Hide values"
msgstr[0] "Wert ausblenden"
msgstr[1] "Werte ausblenden"
-msgid "Hide whitespace changes"
-msgstr "Leerzeichenänderungen ausblenden"
+msgid "Hide values"
+msgstr ""
msgid "History"
msgstr "Verlauf"
@@ -4253,6 +4964,9 @@ msgstr "Verlauf"
msgid "Housekeeping successfully started"
msgstr "Bereinigung erfolgreich gestartet"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr "Ich akzeptiere die %{terms_link}"
@@ -4310,6 +5024,9 @@ msgstr "Identitäten"
msgid "Identity provider single sign on URL"
msgstr "Single Sign On-URL des Identitätsanbieters"
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr "Wenn diese Option deaktiviert ist, wird ein abweichender lokaler Branch nicht automatisch mit Commits von seinem remote Gegenstück aktualisiert, um lokalen Datenverlust zu verhindern. Wenn der Standardbranch (%{default_branch}) abweicht und nicht aktualisiert werden kann, schlägt die Spiegelung fehl. Andere abweichende Branches werden ohne Meldung ignoriert."
@@ -4340,9 +5057,15 @@ msgstr "Onion-Skin"
msgid "ImageDiffViewer|Swipe"
msgstr "Wischen"
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr "Importieren"
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr "Importiere Projekte von Gitea"
@@ -4361,12 +5084,24 @@ msgstr "Importiere ein exportiertes GitLab-Projekt"
msgid "Import in progress"
msgstr "Import wird durchgeführt"
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr "Importiere mehrere Repositorys, indem du eine Manifestdatei hochlädst."
msgid "Import project"
msgstr "Projekt importieren"
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr "Importiere Projekte von Bitbucket"
@@ -4391,6 +5126,9 @@ msgstr "Importiere Repositories von GitHub"
msgid "Import repository"
msgstr "Repository importieren"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr "Verbinde Repositories von"
@@ -4406,15 +5144,30 @@ msgstr "Verbessere die Suche mit der „Erweiterten globalen Suche“ und GitLab
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr "Um die Analyse auf Instanzebene zu aktivieren, bitte eine(n) Administrator(in), den %{usage_ping_link_start}Nutzungsbericht%{usage_ping_link_end} zu aktivieren."
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "Im nächsten Schritt kannst du die Projekte auswählen, die du importieren möchtest."
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "Füge Nutzungsbedingungen und eine Datenschutzrichtlinie hinzu, die alle Benutzer(innen) akzeptieren müssen."
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr "Füge bei Bedarf den Benutzernamen in die URL ein: <code>https://benutzername@gitlab.company.com/group/project.git</code>."
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr "Inkompatibles Projekt"
@@ -4430,6 +5183,9 @@ msgstr "Gib die Host-Schlüssel manuell ein"
msgid "Input your repository URL"
msgstr "Gib deine Repository-URL ein"
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "Installiere einen GitLab Runner"
@@ -4459,6 +5215,9 @@ msgstr "Integrationseinstellungen"
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "Interessierte können auch etwas beitragen wenn sie möchten, indem sie Commits pushen."
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr "Intern - Die Gruppe und alle internen Projekte können von jedem/jeder angemeldeten Benutzer(in) angesehen werden."
@@ -4474,9 +5233,27 @@ msgstr "Intervallmuster"
msgid "Introducing Cycle Analytics"
msgstr "Arbeitsablaufsanalysen vorgestellt"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr "Einladen"
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr "Ticket"
@@ -4495,6 +5272,21 @@ msgstr "Board"
msgid "IssueBoards|Boards"
msgstr "Boards"
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr "Tickets"
@@ -4505,32 +5297,38 @@ msgid "Issues closed"
msgstr "Geschlossene Tickets"
msgid "Issues, merge requests, pushes and comments."
-msgstr ""
+msgstr "Tickets, Merge-Requests, Pushes und Kommentare."
msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
msgstr ""
msgid "IssuesAnalytics|Issues Created"
-msgstr ""
+msgstr "Erstellte Tickets"
msgid "IssuesAnalytics|Issues created per month"
-msgstr ""
+msgstr "Erstellte Tickets pro Monat"
msgid "IssuesAnalytics|Last 12 months"
-msgstr ""
+msgstr "Letzten 12 Monate"
msgid "IssuesAnalytics|Sorry, your filter produced no results"
-msgstr ""
+msgstr "Entschuldigung, leider gibt es für deinen Filter keine Ergebnisse"
msgid "IssuesAnalytics|There are no issues for the projects in your group"
-msgstr ""
+msgstr "Es gibt keine Tickets für die Projekte in deiner Gruppe"
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr "Um deine Suche auszuweiten, ändere oder entferne Filter in der Filterleiste oben"
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
-msgid "Jaeger URL"
+msgid "It's you"
msgstr ""
+msgid "Jaeger URL"
+msgstr "Jaeger-URL"
+
msgid "Jaeger tracing"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr "Job"
msgid "Job has been erased"
msgstr "Job wurde gelöscht"
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr "Jobs"
@@ -4585,11 +5389,11 @@ msgstr "Zeige komplette Rohdaten"
msgid "Job|The artifacts were removed"
msgstr "Die Artefakte wurden entfernt"
-msgid "Job|The artifacts will be removed in"
-msgstr "Die Artefakte werden entfernt in"
+msgid "Job|The artifacts will be removed"
+msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
-msgstr "Der Job hängt, da das Projekt keine zugewiesenen Runner besitzt, die online sind."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
msgid "Jul"
msgstr "Juli"
@@ -4603,12 +5407,18 @@ msgstr "Juni"
msgid "June"
msgstr "Juni"
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
msgid "Kubernetes Cluster"
msgstr "Kubernetes-Cluster"
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "Zeitüberschreitung beim Erstellen des Kubernetes-Clusters; %{timeout}"
@@ -4676,7 +5486,7 @@ msgid "Labels|Promoting %{labelTitle} will make it available for all projects in
msgstr "%{labelTitle} hochzustufen macht es für alle Projekte in %{groupName} verfügbar. Existierende Projektlabels mit dem selben Titel werden zusammengeführt. Diese Aktion kann nicht rückgängig gemacht werden."
msgid "Large File Storage"
-msgstr ""
+msgstr "Large File Storage"
msgid "Last %d day"
msgid_plural "Last %d days"
@@ -4686,6 +5496,9 @@ msgstr[1] "Letzten %d Tage"
msgid "Last Pipeline"
msgstr "Letzte Pipeline"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "Letzter Commit"
@@ -4699,6 +5512,9 @@ msgid "Last edited by %{name}"
msgstr "Zuletzt bearbeitet von %{name}"
msgid "Last reply by"
+msgstr "Letzte Antwort von"
+
+msgid "Last seen"
msgstr ""
msgid "Last update"
@@ -4716,15 +5532,39 @@ msgstr "am"
msgid "Latest changes"
msgstr "Letzte Änderungen"
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr "Mehr Informationen"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr "Erfahre mehr über %{issue_boards_url}, um Tickets in mehreren Listen zu verfolgen, indem du Labels, Verantwortliche und Meilensteine verwendest. Falls du etwas im Ticketboard vermisst, erstelle bitte ein Ticket auf %{gitlab_issues_url}."
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr "Erfahre mehr über Kubernetes"
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr "Erfahre mehr über geschützte Branches"
@@ -4862,6 +5702,12 @@ msgstr "Laden der GitLab IDE..."
msgid "Loading..."
msgstr "Lade..."
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr "Sperren"
@@ -4890,7 +5736,7 @@ msgid "Locks give the ability to lock specific file or folder."
msgstr "Sperrungen bieten die Möglichkeit, bestimmte Dateien oder Ordner zu sperren."
msgid "Login with smartcard"
-msgstr ""
+msgstr "Mit Smartcard einloggen"
msgid "Logs"
msgstr "Protokolle"
@@ -4928,6 +5774,9 @@ msgstr "Label verwalten"
msgid "Manage project labels"
msgstr "Projektlabel verwalten"
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr "Verwalte die Mitgliedschaft deiner Gruppe, während du mit SAML eine weitere Sicherheitsstufe hinzufügst."
@@ -4958,6 +5807,9 @@ msgstr "März"
msgid "Mark todo as done"
msgstr "To-do als erledigt markieren"
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr "Markdown aktiviert"
@@ -4994,9 +5846,6 @@ msgstr "Füge Code ein"
msgid "Maven Metadata"
msgstr "Maven-Metadaten"
-msgid "Maven package"
-msgstr "Maven-Paket"
-
msgid "Max access level"
msgstr "Maximale Zugriffsstufe"
@@ -5010,7 +5859,7 @@ msgid "Median"
msgstr "Median"
msgid "Member lock"
-msgstr ""
+msgstr "Mitgliedersperre"
msgid "Member since %{date}"
msgstr "Mitglied seit %{date}"
@@ -5018,23 +5867,35 @@ msgstr "Mitglied seit %{date}"
msgid "Members"
msgstr "Mitglieder"
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "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 "Mitglieder werden hierher weitergeleitet, wenn diese sich bei deiner Gruppe anmelden. Diese URL bekommst du von deinem Identitätsanbieter, wo es auch als \"SSO Service Location\", \"SAML Token Issuance Endpoint\" oder \"SAML 2.0/W-Federation URL\" bezeichnet sein könnte."
msgid "Merge Request"
msgstr "Merge-Request"
-msgid "Merge Request:"
-msgstr "Merge-Request:"
-
msgid "Merge Requests"
msgstr "Merge-Requests"
msgid "Merge Requests created"
msgstr "Merge_Request erstellt"
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
-msgstr "Ereignisse zusammenführen"
+msgstr "Merge-Ereignisse"
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
msgid "Merge request"
msgstr "Merge-Request"
@@ -5048,20 +5909,32 @@ msgstr "Merge-Requests"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Merge-Requests dienen dazu, deine Änderungsvorschläge für ein Projekt einzureichen und sie mit anderen zu diskutieren"
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr "Beim Hinzufügen des Kommentarentwurfs ist ein Fehler aufgetreten."
-msgid "MergeRequests|Discussion stays resolved."
-msgstr "Die Diskussion bleibt gelöst."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
-msgstr "Die Diskussion bleibt ungelöst."
+msgid "MergeRequests|Discussion will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
-msgstr "Diskussion wird gelöst."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
-msgstr "Diskussion wird nicht mehr gelöst sein."
+msgid "MergeRequests|Reply..."
+msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "Löse diese Diskussion in einem neuen Ticket"
@@ -5078,6 +5951,24 @@ msgstr "Datei anzeigen @ %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "Ersetzte Datei anzeigen @ %{commitId}"
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr "%{paragraphStart}hat die Beschreibung %{descriptionChangedTimes} Mal %{timeDifferenceMinutes} geändert%{paragraphEnd}"
@@ -5087,6 +5978,9 @@ msgstr "Dateien filtern"
msgid "MergeRequest|No files found"
msgstr "Keine Dateien gefunden"
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr "Merged"
@@ -5105,8 +5999,8 @@ msgstr "Metriken - Prometheus"
msgid "Metrics and profiling"
msgstr "Metriken und Profiling"
-msgid "Metrics|Business"
-msgstr "Business"
+msgid "Metrics for environment"
+msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Sieh dir die CI/CD-Dokumentation zur Bereitstellung in einer Umgebung an"
@@ -5114,6 +6008,12 @@ msgstr "Sieh dir die CI/CD-Dokumentation zur Bereitstellung in einer Umgebung an
msgid "Metrics|Create metric"
msgstr "Metrik erstellen"
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr "Metrik bearbeiten"
@@ -5123,8 +6023,8 @@ msgstr "Umgebung"
msgid "Metrics|For grouping similar metrics"
msgstr "Zum Gruppieren ähnlicher Metriken"
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
-msgstr "Beizeichnung der vertikalen Achse des Diagramms. Normalerweise der Typ der dargestellten Einheit. Die horizontale Achse (X-Achse) entspricht immer der Zeit."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
msgid "Metrics|Learn about environments"
msgstr "Erfahre mehr über Umgebungen"
@@ -5135,24 +6035,18 @@ msgstr "Legendenbeschriftung (optional)"
msgid "Metrics|Must be a valid PromQL query."
msgstr "Muss eine gültige PromQL-Abfrage sein."
-msgid "Metrics|Name"
-msgstr "Name"
-
msgid "Metrics|New metric"
msgstr "Neue Metrik"
msgid "Metrics|No deployed environments"
msgstr "Keine bereitgestellten Umgebungen"
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
msgid "Metrics|Prometheus Query Documentation"
msgstr "Prometheus Query-Dokumentation"
-msgid "Metrics|Query"
-msgstr "Abfrage"
-
-msgid "Metrics|Response"
-msgstr "Antwort"
-
msgid "Metrics|System"
msgstr "System"
@@ -5165,12 +6059,12 @@ msgstr "Es ist ein Fehler beim Abrufen der Bereitstellungsinformationen aufgetre
msgid "Metrics|There was an error getting environments information."
msgstr "Es gab ein Fehler beim Abrufen der Umgebungsinformationen."
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
msgid "Metrics|There was an error while retrieving metrics"
msgstr "Beim Abrufen der Metriken ist ein Fehler aufgetreten"
-msgid "Metrics|Type"
-msgstr "Typ"
-
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr "Unerwartete Bereitstellungs-Datenantwort vom Prometheus-Endpunkt"
@@ -5189,21 +6083,12 @@ msgstr "Wird verwendet, wenn die Abfrage eine einzelne Serie zurückgibt. Wenn m
msgid "Metrics|Y-axis label"
msgstr "Y-Achsen-Bezeichnung"
-msgid "Metrics|e.g. HTTP requests"
-msgstr "z. B. HTTP-Anfragen"
-
-msgid "Metrics|e.g. Requests/second"
-msgstr "z. B. Anfragen/Sekunde"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr "z. B. Durchsatz"
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr "z. B. Rate(http_requests_total[5m])"
-
-msgid "Metrics|e.g. req/sec"
-msgstr "z. B. Anfr./Sek."
-
msgid "Milestone"
msgstr "Meilenstein"
@@ -5276,6 +6161,18 @@ msgstr "Abbrechen"
msgid "Modal|Close"
msgstr "Schließen"
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "Ãœberwachung"
@@ -5322,7 +6219,7 @@ msgid "Name:"
msgstr "Name:"
msgid "Naming, visibility"
-msgstr ""
+msgstr "Benennung, Sichtbarkeit"
msgid "Nav|Help"
msgstr "Hilfe"
@@ -5336,6 +6233,9 @@ msgstr "Anmelden / Registrieren"
msgid "Nav|Sign out and sign in with a different account"
msgstr "Abmelden und mit einem anderen Konto anmelden"
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr "Netzwerk"
@@ -5348,6 +6248,9 @@ msgstr "Neu"
msgid "New Application"
msgstr "Neue Anwendung"
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr "Neue Gruppe"
@@ -5362,6 +6265,12 @@ msgstr[1] "Neue Tickets"
msgid "New Label"
msgstr "Neues Label"
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "Neuer Pipeline Zeitplan"
@@ -5380,6 +6289,9 @@ msgstr "Neuer Branch ist nicht verfügbar"
msgid "New directory"
msgstr "Neues Verzeichnis"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr "Neuer Epic"
@@ -5401,6 +6313,9 @@ msgstr "Neues Label"
msgid "New merge request"
msgstr "Neuer Merge-Request"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "Neue Pipelines brechen ältere, ausstehende Pipelines in dem selben Branch ab"
@@ -5428,6 +6343,9 @@ msgstr "Nein"
msgid "No Label"
msgstr "Kein Label"
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr "Niemandem zugewiesen"
@@ -5437,6 +6355,9 @@ msgstr "Keine Branches gefunden"
msgid "No changes"
msgstr "Keine Änderungen"
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Es konnte keine Verbindung zu einem Gitaly-Server hergestellt werden. Bitte überprüfe deine Protokolle!"
@@ -5447,17 +6368,26 @@ msgid "No contributions were found"
msgstr "Keine Beiträge gefunden"
msgid "No credit card required."
+msgstr "Keine Kreditkarte erforderlich."
+
+msgid "No details available"
msgstr ""
msgid "No due date"
msgstr "Kein Fälligkeitsdatum"
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
-msgstr "Keine geschätzte oder verbrauchte Zeit"
+msgstr "Weder Schätzung noch Zeitaufwand eingetragen"
msgid "No file chosen"
msgstr "Keine Datei ausgewählt"
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr "Keine Dateien gefunden."
@@ -5470,6 +6400,9 @@ msgstr "Keine Tags mit einem solchen Namen oder einer solchen Beschreibung"
msgid "No license. All rights reserved"
msgstr "Keine Lizenz. Alle Rechte vorbehalten"
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr "Keine Merge-Requests für den gewählten Zeitraum."
@@ -5479,11 +6412,14 @@ msgstr "Keine Merge-Requests gefunden"
msgid "No messages were logged"
msgstr "Es wurden Nachrichten protokolliert"
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Keine anderen Tags mit einem solchen Namen oder einer solchen Beschreibung"
-msgid "No packages stored for this project."
-msgstr "Keine Pakete für dieses Projekt gespeichert."
+msgid "No preview for this file type"
+msgstr ""
msgid "No prioritised labels with such name or description"
msgstr "Keine priorisierten Labels mit einem solchen Namen oder einer solchen Beschreibung"
@@ -5503,6 +6439,9 @@ msgstr "Keine Runner gefunden"
msgid "No schedules"
msgstr "Keine Zeitpläne"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr "Nein, importiere die vorhandenen E-Mail-Adressen und Benutzernamen direkt."
@@ -5512,12 +6451,6 @@ msgstr "Knoten"
msgid "None"
msgstr "Keine"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr "Nicht alle Kommentare werden angezeigt, da du zwei Versionen des Diffs vergleichst."
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr "Nicht alle Kommentare werden angezeigt, da du eine alte Versionen des Diffs betrachtest."
-
msgid "Not allowed to merge"
msgstr "Keine Berechtigung um zu mergen"
@@ -5542,6 +6475,9 @@ msgstr "Nicht jetzt"
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "Beachte, dass der master-Branch automatisch geschützt ist. %{link_to_protected_branches}"
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "Hinweis: Als Administrator(in) möchtest du möglicherweise %{github_integration_link} konfigurieren, mit dem du dich über GitHub anmelden und das Verbinden von Repositories ohne Erstellung eines persönlichen Zugriffstokens erlauben kannst."
@@ -5558,20 +6494,26 @@ msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Bist du sicher, dass du die Erstellung dieses Kommentars abbrechen möchtest?"
msgid "Notes|Collapse replies"
-msgstr ""
+msgstr "Antworten reduzieren"
msgid "Notes|Show all activity"
-msgstr ""
+msgstr "Alle Aktivitäten anzeigen"
msgid "Notes|Show comments only"
-msgstr ""
+msgstr "Nur Kommentare anzeigen"
msgid "Notes|Show history only"
-msgstr ""
+msgstr "Nur Verlauf anzeigen"
msgid "Notification events"
msgstr "Benachrichtigungsereignisse"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Ticket schließen"
@@ -5670,20 +6612,35 @@ msgstr "Ein oder mehrere Ihrer Google Code-Projekte kann/können nicht direkt in
msgid "Only admins"
msgstr "Nur Administrator(inn)en"
-msgid "Only comments from the following commit are shown below"
-msgstr "Nur Kommentare des folgende Commits werden unten angezeigt"
-
msgid "Only mirror protected branches"
msgstr "Nur geschützte Branches spiegeln"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
msgid "Only project members can comment."
msgstr "Nur Projektmitglieder können kommentieren."
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "Ups, bist du sicher?"
msgid "Open"
-msgstr "Öffnen"
+msgstr "Offen"
+
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
msgid "Open in Xcode"
msgstr "In Xcode öffnen"
@@ -5718,16 +6675,13 @@ msgstr "Vorgänge"
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "Ein Projekt zum Dashboard hinzufügen"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr "Pakete"
msgid "Pages"
msgstr "Seiten"
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Letzte »"
@@ -5787,17 +6747,32 @@ msgstr "Vorherige"
msgid "Pagination|« First"
msgstr "« Erste"
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr "Teil der Merge-Request-Änderungen"
msgid "Password"
msgstr "Passwort"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "Füge deinen öffentlichen SSH-Schlüssel ein, der normalerweise in der Datei '~/.ssh/id_rsa.pub' enthalten ist und mit 'ssh-rsa' beginnt. Verwende nicht deinen privaten SSH-Schlüssel."
msgid "Path, transfer, remove"
-msgstr ""
+msgstr "Pfad, übertragen, entfernen"
msgid "Path:"
msgstr "Pfad:"
@@ -5814,9 +6789,6 @@ msgstr "In Arbeit"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Personen ohne Berechtigung werden nie eine Benachrichtigung bekommen und können auch nicht kommentieren."
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr "Pro Job. Wenn ein Job diesen Schwellenwert überschreitet, wird er als fehlgeschlagen markiert"
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "Führe erweiterte Optionen aus, wie z. B. das Ändern des Pfades, Übertragen oder Entfernen einer Gruppe."
@@ -5832,6 +6804,12 @@ msgstr "Berechtigungen, LFS, 2FA"
msgid "Personal Access Token"
msgstr "Persönlicher Zugangs-Token"
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "Pipeline"
@@ -5842,7 +6820,7 @@ msgid "Pipeline Schedule"
msgstr "Zeitplan der Pipeline"
msgid "Pipeline Schedules"
-msgstr "Zietpläne der Pipeline"
+msgstr "Zeitpläne der Pipeline"
msgid "Pipeline quota"
msgstr "Pipeline-Kontingent"
@@ -6018,6 +6996,9 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Ausführen"
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr "Bitte akzeptiere die Nutzungsbedingungen, um fortzufahren."
@@ -6030,9 +7011,15 @@ msgstr "Bitte wandle sie in %{link_to_git} um und durchlaufe erneut die %{link_t
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "Bitte wandle sie in Git auf Google Code um und durchlaufe erneut die %{link_to_import_flow}."
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Bitte gib einen beschreibenden Namen für deine Gruppe ein."
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Bitte beachte, dass diese Anwendung nicht von GitLab bereitgestellt wird. Du solltest daher die Authentizität überprüfen, bevor du den Zugriff erlaubst."
@@ -6045,9 +7032,12 @@ msgstr "Bitte löse das reCAPTCHA"
msgid "Please try again"
msgstr "Bitte erneut versuchen"
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr "Bitte verwende dieses Formular um Benutzer(innen) zu melden, die Spam-Tickets, -Kommentare erstellen oder sich unangemessen verhalten."
+
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."
@@ -6087,6 +7077,9 @@ msgstr "Priorisierte Labels"
msgid "Prioritized label"
msgstr "Priorisiertes Label"
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr "Privat - Projektzugriff muss explizit jedem/jeder Benutzer(in) gewährt werden."
@@ -6108,9 +7101,18 @@ msgstr "Du bist dabei, %{yourAccount} permanent zu löschen, inklusive aller Tic
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 "Du bist dabei, deinen Benutzernamen von %{currentUsernameBold} in %{newUsernameBold} zu ändern. Profile und Projekte werden auf den neuen %{newUsername}-Namensraum umgeleitet, aber diese Umleitung wird auslaufen, sobald der %{currentUsername}-Namensraum von einem anderen Benutzer oder einer anderen Gruppe registriert wird. Bitte aktualisiere deine Git-Repository-Remotes so bald wie möglich."
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "Konto zur Löschung vorgemerkt."
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr "Schlüssel hinzufügen"
@@ -6126,15 +7128,30 @@ msgstr "Avatar wird entfernt. Bist du sicher?"
msgid "Profiles|Change username"
msgstr "Benutzernamen ändern"
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr "Datei auswählen..."
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
-msgstr "Wähle dies aus, um Beiträge privater Projekte in deinem öffentlichen Profil ohne Projekt-, Repository- oder Organisationsinformationen anzuzeigen."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
msgid "Profiles|Clear status"
msgstr "Status löschen"
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Aktueller Pfad: %{path}"
@@ -6153,6 +7170,9 @@ msgstr "Dein Konto löschen?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Löschen eines Kontos hat folgende Auswirkungen:"
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr "Nicht im Profil zeigen"
@@ -6162,6 +7182,12 @@ msgstr "Zeige keine aktivitätsbezogenen persönlichen Informationen in deinem P
msgid "Profiles|Edit Profile"
msgstr "Profil bearbeiten"
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Ungültiges Kennwort"
@@ -6172,7 +7198,7 @@ msgid "Profiles|Learn more"
msgstr "Erfahre mehr"
msgid "Profiles|Made a private contribution"
-msgstr ""
+msgstr "Hat einen privaten Beitrag geleistet"
msgid "Profiles|Main settings"
msgstr "Haupteinstellungen"
@@ -6198,11 +7224,14 @@ msgstr "Avatar entfernen"
msgid "Profiles|Set new profile picture"
msgstr "Neues Profilbild festlegen"
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr "Einige Optionen sind für LDAP-Accounts nicht verfügbar"
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
-msgstr "Erzähle uns von dir in weniger als 250 Zeichen."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "Die maximal zulässige Dateigröße beträgt 200KB."
@@ -6210,8 +7239,8 @@ msgstr "Die maximal zulässige Dateigröße beträgt 200KB."
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Das sieht nicht aus wie ein öffentlicher SSH-Schlüssel aus. Bist du sicher, dass du ihn hinzufügen willst?"
-msgid "Profiles|This email will be displayed on your public profile."
-msgstr "Diese E-Mail wird in deinem öffentlichen Profil angezeigt."
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
msgstr "Diese E-Mail-Adresse wird für webbasierte Vorgänge wie Bearbeitungen und Merges verwendet. %{learn_more}"
@@ -6219,11 +7248,14 @@ msgstr "Diese E-Mail-Adresse wird für webbasierte Vorgänge wie Bearbeitungen u
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr "Dieses Emoji und diese Nachricht werden in deinem Profil und auf der gesamten Benutzeroberfläche angezeigt."
-msgid "Profiles|This feature is experimental and translations are not complete yet."
-msgstr "Dieses Feature ist experimentell und die Ãœbersetzungen sind noch nicht abgeschlossen."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
-msgid "Profiles|This information will appear on your profile."
-msgstr "Diese Informationen werden in deinem Profil angezeigt."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Gib deinen %{confirmationValue} zur Bestätigung ein:"
@@ -6249,12 +7281,15 @@ msgstr "Änderung des Benutzernamens fehlgeschlagen - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "Benutzername erfolgreich geändert"
-msgid "Profiles|Website"
-msgstr "Webseite"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
msgid "Profiles|What's your status?"
msgstr "Was ist dein Status?"
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr "Du kannst deinen Avatar hier ändern"
@@ -6273,17 +7308,20 @@ msgstr "Du hast keine Berechtigung, um diese(n) Benutzer(in) zu löschen."
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
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 ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Dein Konto ist derzeit ein Besitzer in diesen Gruppen:"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
-msgstr "Deine E-Mail-Adresse wurde automatisch basierend auf deinem %{provider_label} Konto festgelegt."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
-msgstr "Dein Standort wurde automatisch basierend auf deinem %{provider_label} Konto festgelegt."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
-msgstr "Dein Name wurde automatisch basierend auf deinem %{provider_label} Konto festgelegt, sodass du von dir bekannten Personen erkannt werden kannst."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
msgid "Profiles|Your status"
msgstr "Dein Status"
@@ -6291,6 +7329,12 @@ msgstr "Dein Status"
msgid "Profiles|e.g. My MacBook key"
msgstr "z. B. Mein MacBook-Schlüssel"
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "Dein Konto"
@@ -6348,12 +7392,18 @@ msgstr "Der Link für den Export des Projektes ist abgelaufen. Bitte generiere e
msgid "Project export started. A download link will be sent by email."
msgstr "Export des Projektes gestartet. Ein Link zum Herunterladen wir dir per E-Mail zugesandt."
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr "Projektname"
msgid "Project slug"
msgstr "Projekt-Slug"
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Abonnieren"
@@ -6498,9 +7548,6 @@ msgstr "Operator"
msgid "PrometheusAlerts|Threshold"
msgstr "Grenzwert"
-msgid "PrometheusDashboard|Time"
-msgstr "Zeit"
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "Es wurden %{exporters} mit %{metrics} gefunden"
@@ -6525,6 +7572,9 @@ msgstr "Gemeinsame Metriken werden anhand einer Bibliothek von Metriken bekannte
msgid "PrometheusService|Custom metrics"
msgstr "Benutzerdefinierte Metriken"
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "Metriken finden und konfigurieren..."
@@ -6654,6 +7704,9 @@ msgstr "Provider"
msgid "Pseudonymizer data collection"
msgstr "Pseudonymizer-Datensammlung"
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "Öffentlich - Die Gruppe und alle öffentlichen Projekte können ohne Authentifizierung eingesehen werden."
@@ -6693,26 +7746,35 @@ msgstr "Pushes"
msgid "Quarters"
msgstr "Quartale"
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Kurzbefehle können in Ticket-Beschreibungen und Kommentarfeldern verwendet werden."
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "Mehr lesen"
+msgid "Read more about environments"
+msgstr ""
+
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr "Lies mehr über Projektberechtigungen <strong>%{link_to_help}</strong>"
-msgid "Readme"
-msgstr "Readme"
-
msgid "Real-time features"
msgstr "Echtzeit-Features"
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr "Zuletzt gesucht"
msgid "Redirect to SAML provider to test configuration"
-msgstr ""
+msgstr "Zu SAML-Provider umleiten um Konfiguration zu testen"
msgid "Reference:"
msgstr "Referenz:"
@@ -6734,6 +7796,9 @@ msgstr "Regex-Muster"
msgid "Register / Sign In"
msgstr "Anmelden"
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "Registriere dich und sieh deine Runner für diese Gruppe."
@@ -6764,6 +7829,12 @@ msgstr "Zugehörige umgesetzte Merge-Requests"
msgid "Related merge requests"
msgstr "Zugehörige Merge-Requests"
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "Später erinnern"
@@ -6773,6 +7844,12 @@ msgstr "Entfernen"
msgid "Remove Runner"
msgstr "Runner entfernen"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Avatar entfernen"
@@ -6803,9 +7880,15 @@ msgstr "Ordner umbenennen"
msgid "Reopen epic"
msgstr "Epic erneut öffnen"
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr "Authentifizierung reparieren"
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr "Antworte direkt auf diese E-Mail oder %{view_it_on_gitlab}."
@@ -6813,7 +7896,7 @@ msgid "Repo by URL"
msgstr "Repo via URL"
msgid "Report abuse to GitLab"
-msgstr ""
+msgstr "Missbrauch an GitLab melden"
msgid "Reporting"
msgstr "Statusbericht"
@@ -6866,6 +7949,12 @@ msgstr "Repository-Einstellungen"
msgid "Repository URL"
msgstr "Repository-URL"
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr "Das Repository hat keine Sperren."
@@ -6884,21 +7973,39 @@ msgstr "Auswählen"
msgid "Request Access"
msgstr "Anfrage auf Zugriff"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr "Fordert Profile an"
msgid "Require all users in this group to setup Two-factor authentication"
-msgstr ""
+msgstr "Alle Benutzer(innen) dieser Gruppe müssen die Zwei-Faktor-Authentifizierung einrichten"
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Fordere alle Benutzer(innen) auf, die Nutzungsbedingungen und Datenschutzrichtlinien zu akzeptieren, wenn sie auf GitLab zugreifen."
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr "Zugriffstoken für den Health-Check zurücksetzen"
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "Registrierungstoken für Runner zurücksetzen"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr "Löse alle Diskussionen in einem neuen Ticket"
@@ -6908,6 +8015,12 @@ msgstr "Konflikte im Quell-Branch lösen"
msgid "Resolve discussion"
msgstr "Diskussion beenden"
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr "Antwortmesswerte (AWS ELB)"
@@ -6917,12 +8030,18 @@ msgstr "Antwortmesswerte (benutzerdefiniert)"
msgid "Response metrics (HA Proxy)"
msgstr "Antwortmesswerte (HA Proxy)"
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr "Antwortmesswerte (NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Antwortmesswerte (NGINX)"
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr "Fortsetzen"
@@ -6935,14 +8054,14 @@ msgstr "Wiederhole diese Aufgabe"
msgid "Retry verification"
msgstr "Wiederhole die Überprüfung"
-msgid "Reveal Variables"
-msgstr "Variablen anzeigen"
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] "Wert anzeigen"
msgstr[1] "Werte anzeigen"
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Diesen Commit zurücksetzen"
@@ -6970,6 +8089,9 @@ msgstr "Roadmap"
msgid "Run CI/CD pipelines for external repositories"
msgstr "Führe CI/CD-Pipelines für externe Repositories aus"
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr "Unmarkierte Jobs ausführen"
@@ -6997,6 +8119,9 @@ msgstr "Runners"
msgid "Runners API"
msgstr "Runners-API"
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Runner können durch separate Benutzer, auf Servern und sogar auf deinem lokalen Rechner ausgeführt werden."
@@ -7030,8 +8155,8 @@ msgstr "SAML Single Sign On"
msgid "SAML Single Sign On Settings"
msgstr "SAML Single Sign On-Einstellungen"
-msgid "SAST"
-msgstr "SAST"
+msgid "SAML for %{group_name}"
+msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "SHA-1-Fingerabdruck des SAML-Tokensignaturzertifikats. Hole diesen von deinem Identitätsanbieter, wo es auch \"Daumenabdruck (Thumbprint)\" heißen könnte."
@@ -7051,6 +8176,9 @@ msgstr "SSL-Verifizierung"
msgid "Save"
msgstr "Speichern"
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr "Anwendung speichern"
@@ -7060,6 +8188,9 @@ msgstr "Änderungen speichern"
msgid "Save changes before testing"
msgstr "Änderungen vor dem Testen speichern"
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Zeitplan der Pipeline speichern"
@@ -7096,6 +8227,9 @@ msgstr "Nach oben scrollen"
msgid "Search"
msgstr "Suche"
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr "Branches durchsuchen"
@@ -7108,6 +8242,9 @@ msgstr "Dateien durchsuchen"
msgid "Search for projects, issues, etc."
msgstr "Suche nach Projekten, Tickets usw."
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr "Merge-Requests durchsuchen"
@@ -7157,7 +8294,7 @@ msgid "SearchAutocomplete|in this project"
msgstr "in diesem Projekt"
msgid "Secret"
-msgstr ""
+msgstr "Secret"
msgid "Security"
msgstr "Sicherheit"
@@ -7175,21 +8312,24 @@ msgid "Security Dashboard|Error fetching the vulnerability list. Please check yo
msgstr ""
msgid "Security Dashboard|Issue Created"
-msgstr ""
+msgstr "Ticket erstellt"
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
-msgstr ""
+msgstr "Ticket erstellen"
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
-msgid "Security Reports|More info"
+msgid "Security Reports|Learn more about setting up your dashboard"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|More info"
+msgstr "Mehr Informationen"
+
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr "Das Sicherheits-Dashboard zeigt den neuesten Sicherheitsbericht an. Verwende es, um Schwachstellen zu finden und zu beheben."
@@ -7216,6 +8368,12 @@ msgstr "Überwache Sicherheitslücken in deinem Code"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "Pipeline %{pipelineLink} ausgelöst"
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr "Auswählen"
@@ -7243,6 +8401,9 @@ msgstr "Bearbeiter auswählen"
msgid "Select branch/tag"
msgstr "Branch/Tag auswählen"
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr "Projekt wählen"
@@ -7276,9 +8437,15 @@ msgstr "Selektive Synchronisation"
msgid "Send email"
msgstr "E-Mail senden"
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr "Nutzungsdaten senden"
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr "Sept"
@@ -7288,6 +8455,48 @@ msgstr "September"
msgid "Server version"
msgstr "Serverversion"
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr "Service-Desk"
@@ -7318,6 +8527,9 @@ msgstr "Lege die maximale Sitzungszeit für das Web-Terminal fest."
msgid "Set notification email for abuse reports."
msgstr "Benachrichtigungs-E-Mail für Missbrauchsberichte festlegen."
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "Lege Anforderungen für eine(n) Benutzer(in) fest, um sich anzumelden. Aktiviere die erforderliche Zwei-Faktor-Authentifizierung."
@@ -7333,6 +8545,9 @@ msgstr "Richte einen bestimmten Runner automatisch ein"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "Richte notwendige Angaben (E-Mail, Vorname, Nachname) und NameID gemäß %{docsLinkStart}der Dokumentation %{icon}%{docsLinkEnd} ein"
+msgid "Set up new U2F device"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Richte dein Projekt so ein, dass Änderungen automatisch an ein anderes Repository gesendet bzw. von diesem abgerufen werden. Branches, Tags und Commits werden automatisch synchronisiert."
@@ -7396,12 +8611,12 @@ msgstr "Befehl anzeigen"
msgid "Show complete raw log"
msgstr "Zeige komplettes Rohprotokoll"
+msgid "Show file browser"
+msgstr ""
+
msgid "Show latest version"
msgstr "Neuste Version zeigen"
-msgid "Show latest version of the diff"
-msgstr "Zeige die letzte Version des Diffs"
-
msgid "Show parent pages"
msgstr "Ãœbergeordnete Seiten anzeigen"
@@ -7437,12 +8652,21 @@ msgstr "Anmelden"
msgid "Sign in / Register"
msgstr "Anmelden / Registrieren"
-msgid "Sign in to %{group_name}"
-msgstr "Melde dich bei %{group_name} an"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
msgid "Sign in with Single Sign-On"
msgstr "Melde dich mit Single Sign-On an"
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr "Abmelden"
@@ -7452,6 +8676,9 @@ msgstr "Anmeldebeschränkungen"
msgid "Sign-up restrictions"
msgstr "Registrierungsbeschränkungen"
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr "Größe"
@@ -7468,14 +8695,23 @@ msgid "Slower but makes sure the project workspace is pristine as it clones the
msgstr "Langsamer, aber stellt sicher, dass der Projektarbeitsbereich unberührt ist, da das Repository für jeden Job neu geklont wird"
msgid "Smartcard"
-msgstr ""
+msgstr "Smartcard"
msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr "Smartcard-Authentifizierung fehlgeschlagen: Client-Zertifikat-Header fehlt."
+
+msgid "Snippet Contents"
msgstr ""
msgid "Snippets"
msgstr "Codeausschnitte"
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr "Bei uns ist etwas schief gelaufen"
@@ -7485,6 +8721,9 @@ msgstr "Bei uns ist etwas schief gelaufen."
msgid "Something went wrong on our end. Please try again!"
msgstr "Etwas ist an unserem Ende schief gelaufen. Bitte versuche es erneut!"
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr "Etwas ist beim Ändern der Vertraulichkeit dieses Tickets fehlgeschlagen"
@@ -7494,9 +8733,15 @@ msgstr "Etwas ist beim Ändern des Sperrzustandes von %{issuableDisplayName} sch
msgid "Something went wrong when toggling the button"
msgstr "Beim Umschalten des Buttons ist etwas schief gelaufen"
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "Beim Schließen des %{issuable} ist etwas schief gelaufen. Bitte versuche es später erneut"
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr "Etwas ist beim Laden der Liste %{listType} fehlgeschlagen"
@@ -7515,6 +8760,9 @@ msgstr "Beim Abrufen der Projekte ist etwas schief gegangen."
msgid "Something went wrong while fetching the registry list."
msgstr "Beim Abrufen der Registryliste ist etwas schief gegangen."
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr "Etwas ist beim Wiedereröffnen von %{issuable} fehlgeschlagen. Versuche es später nochmal"
@@ -7539,9 +8787,15 @@ msgstr "Entschuldigung, keine Epics stimmten mit deiner Suche überein"
msgid "Sorry, no projects matched your search"
msgstr "Entschuldigung, keine Projekte stimmten mit deiner Suche überein"
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr "Sortieren nach"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr "Zugriffsebene, aufsteigend"
@@ -7587,8 +8841,8 @@ msgstr "Am unbeliebtesten"
msgid "SortOptions|Less weight"
msgstr "Niedrigere Gewichtung"
-msgid "SortOptions|Milestone"
-msgstr "Meilenstein"
+msgid "SortOptions|Milestone due date"
+msgstr ""
msgid "SortOptions|Milestone due later"
msgstr "Meilenstein später fällig"
@@ -7620,6 +8874,9 @@ msgstr "Zuerst erstellt"
msgid "SortOptions|Oldest joined"
msgstr "Zuerst beigetreten"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr "Älteste Anmeldung"
@@ -7632,6 +8889,9 @@ msgstr "Beliebtheit"
msgid "SortOptions|Priority"
msgstr "Priorität"
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr "Zuletzt angemeldet"
@@ -7659,6 +8919,9 @@ msgstr "Quellcode"
msgid "Source is not available"
msgstr "Quelle ist nicht verfügbar"
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr "Spam-Protokolle"
@@ -7674,6 +8937,9 @@ msgstr "Gib ein Regex-Muster für E-Mail-Adressen an, um interne Standardbenutze
msgid "Specify the following URL during the Runner setup:"
msgstr "Gib die folgende URL während des Runner-Setups an:"
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr "Squash Commits"
@@ -7710,6 +8976,12 @@ msgstr "Aktivität markierter Projekte"
msgid "Starred projects"
msgstr "Markierte Projekte"
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "Beginne einen %{new_merge_request} mit diesen Änderungen"
@@ -7719,18 +8991,39 @@ msgstr "Einen Review starten"
msgid "Start and due date"
msgstr "Start- und Fälligkeitsdatum"
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr "Startdatum"
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Starte den Runner!"
msgid "Start your trial"
-msgstr ""
+msgstr "Testzeitraum beginnen"
msgid "Started"
msgstr "Begonnen"
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "Beginnt am (UTC)"
@@ -7740,9 +9033,15 @@ msgstr "Gib deine Nachricht an, um sie zu aktivieren"
msgid "Status"
msgstr "Status"
-msgid "Stop environment"
+msgid "Status:"
msgstr ""
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop environment"
+msgstr "Umgebung stoppen"
+
msgid "Stop impersonation"
msgstr "Stoppe die Personifikation"
@@ -7753,6 +9052,9 @@ msgid "Stopped"
msgstr "Gestoppt"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr "Diese Umgebung kann derzeit nicht gestoppt werden, da ein Bereitstellung stattfindet"
+
+msgid "Stopping..."
msgstr ""
msgid "Storage"
@@ -7770,6 +9072,9 @@ msgstr "Untergruppen und Projekte"
msgid "Submit as spam"
msgstr "Als Spam einreichen"
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr "Review senden"
@@ -7785,10 +9090,94 @@ msgstr "Abonniere auf Gruppenebene"
msgid "Subscribe at project level"
msgstr "Abonniere auf Projektebene"
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr "Abonniert"
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,8 +9192,11 @@ msgstr "System-Hooks"
msgid "System Info"
msgstr "Systeminformationen"
-msgid "System header and footer:"
-msgstr "Kopfzeile und Fußzeile des Systems:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
msgid "System metrics (Custom)"
msgstr "Systemmetriken (benutzerdefiniert)"
@@ -7812,10 +9204,11 @@ msgstr "Systemmetriken (benutzerdefiniert)"
msgid "System metrics (Kubernetes)"
msgstr "Systemmetriken (Kubernetes)"
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] "Tag (%{tag_count})"
-msgstr[1] "Tags (%{tag_count})"
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "Tags"
@@ -7910,6 +9303,12 @@ msgstr "Vorlage"
msgid "Templates"
msgstr "Vorlagen"
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Nutzungsbedingungen und Datenschutzerklärung"
@@ -7925,9 +9324,15 @@ msgstr "Testabdeckung analysieren"
msgid "Thanks! Don't show me this again"
msgstr "Vielen Dank! Zeig es mir nicht nochmal"
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global 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 "Die „Erweiterte Globale Suche“ in GitLab ist ein leistungsfähiger Suchdienst, der dir Zeit spart. Anstatt doppelten Code zu erstellen und Zeit zu verschwenden, kannst du nun bei anderen Teams nach Code suchen, der für dein eigenes Projekt hilfreich sein kann."
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr "Die Git LFS-Objekte werden <strong>nicht</strong> synchronisiert werden."
@@ -7964,6 +9369,9 @@ msgstr "Der Import wird nach %{timeout} beendet. Verwende eine Clone/Push-Kombin
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Die Ticketphase stellt die Zeit vom Anlegen eines Tickets bis zum Zuweisen zu einem Meilenstein oder dem Hinzufügen zu deinem Ticket-Board dar. Erstelle einen Ticket, damit dessen Daten hier erscheinen."
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr "Die maximal zulässige Dateigröße beträgt 200 KB."
@@ -8042,17 +9450,35 @@ msgstr "Die Benutzerzuordnung legt fest, wie die E-Mail-Adressen und Benutzernam
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Der mittlere aller erfassten Werte. Zum Beispiel ist für 3, 5, 9 der Median 5. Bei 3, 5, 7, 8 ist der Median (5+7)/2 = 6."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Es gibt noch keine archivierten Projekte"
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr "Es gibt keine Tickets die angezeigt werden können"
msgid "There are no labels yet"
msgstr "Es gibt noch keine Labels"
-msgid "There are no merge requests to show"
-msgstr "Es sind keine Merge-Requests zum Anzeigen vorhanden"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
msgid "There are no projects shared with this group yet"
msgstr "Es gibt noch keine geteilten Projekte mit dieser Gruppe"
@@ -8087,12 +9513,21 @@ msgstr "Beim Abonnieren dieses Labels ist ein Fehler aufgetreten."
msgid "There was an error when unsubscribing from this label."
msgstr "Beim Abmelden von der Abonnierung dieses Labels ist ein Fehler aufgetreten."
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr "Können unter %{link} verwaltet werden."
msgid "Third party offers"
msgstr "Angebote von Drittanbietern"
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "Diese GitLab-Instanz stellt noch keine geteilten Runner bereit. Instanz-Administrator(inn)en können geteilte Runner im Admin-Bereich registrieren."
@@ -8120,15 +9555,18 @@ msgstr "Dieses Datum ist vor dem Startdatum, daher erscheint dieses Epic nicht i
msgid "This diff is collapsed."
msgstr "Dieser Diff ist reduziert."
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr "Dieses Verzeichnis"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
msgid "This group"
msgstr "Diese Gruppe"
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr "In dieser Gruppe kannst du dich mit deinem %{group_name}-Single Sign-On-Konto anmelden. Dabei wirst du auf eine externe Anmeldeseite weitergeleitet."
-
msgid "This group does not provide any group Runners yet."
msgstr "Diese Gruppe stellt noch keine Gruppenrunner zur Verfügung."
@@ -8136,7 +9574,7 @@ msgid "This is a confidential issue."
msgstr "Dies ist ein vertrauliches Ticket."
msgid "This is a delayed job to run in %{remainingTime}"
-msgstr ""
+msgstr "Dies ist ein in %{remainingTime} auszuführender verzögerter Job"
msgid "This is the author's first Merge Request to this project."
msgstr "Dies ist der erste Merge-Request des Autors für dieses Projekt."
@@ -8178,10 +9616,10 @@ msgid "This job is an out-of-date deployment to %{environmentLink}. View the mos
msgstr "Dieser Job ist eine veraltete Bereitstellung für %{environmentLink}. Zeige die neueste Bereitstellung an %{deploymentLink}."
msgid "This job is archived. Only the complete pipeline can be retried."
-msgstr ""
+msgstr "Dieser Job ist archiviert. Nur die gesamte Pipeline kann erneut versucht werden."
msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "Dieser Job erstellt ein Deployment für %{environmentLink} und überschreibt %{deploymentLink}."
msgid "This job is creating a deployment to %{environmentLink}."
msgstr "Dieser Job erstellt eine Bereitstellung für %{environmentLink}."
@@ -8189,11 +9627,11 @@ msgstr "Dieser Job erstellt eine Bereitstellung für %{environmentLink}."
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "Dieser Job befindet sich im Status \"ausstehend\" und wartet darauf, durch einen Runner ausgewählt zu werden"
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
-msgstr "Dieser Job ist blockiert, da du keine aktiven Runner online hast, die einem dieser Tags zugeordnet sind:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
-msgstr "Dieser Job hängt, da du keine aktiven Runner hast, die diesen Job ausführen können."
+msgid "This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
msgid "This job is the most recent deployment to %{link}."
msgstr "Dieser Job ist die neueste Bereitstellung für %{link}."
@@ -8201,7 +9639,7 @@ msgstr "Dieser Job ist die neueste Bereitstellung für %{link}."
msgid "This job requires a manual action"
msgstr "Dieser Job erfordert eine manuelle Aktion"
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr "Diese Seite ist nicht verfügbar, da du nicht Informationen über mehrer
msgid "This page will be removed in a future release."
msgstr "Diese Seite wird in einer zukünftigen Version entfernt."
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr "Dieses Projekt"
@@ -8229,7 +9676,7 @@ msgid "This project does not belong to a group and can therefore not make use of
msgstr "Dieses Projekt gehört keiner Gruppe an und kann daher keine Gruppenrunner verwenden."
msgid "This project does not have a wiki homepage yet"
-msgstr ""
+msgstr "Dieses Projekt hat derzeit noch keine Wiki-Startseite"
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr "Für dieses Projekt ist keine Abrechnung aktiviert. Um ein Cluster zu erstellen, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">aktiviere die Abrechnung<i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> und versuche es erneut."
@@ -8241,16 +9688,16 @@ msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "Dieser Runner wird nur Pipelines von geschützen Branches ausführen"
msgid "This setting can be overridden in each project."
-msgstr ""
+msgstr "Diese Einstellung kann in jedem Projekt überschrieben werden."
msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
-msgstr ""
+msgstr "Diese Einstellung aktualisiert den Hostnamen der für die Generierung von privaten Commit-E-Mails verwendet wird. %{learn_more}"
msgid "This source diff could not be displayed because it is too large."
msgstr "Dieser Quelltext-Diff konnte nicht angezeigt werden, da er zu groß ist."
-msgid "This timeout will take precedence when lower than Project-defined timeout"
-msgstr "Dieser Timeout wird den projektspezifischen Timeout überschreiben, wenn er niedriger ist"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
+msgstr ""
msgid "This user has no identities"
msgstr "Diese(r) Benutzer(in) hat keine Identitäten"
@@ -8261,8 +9708,8 @@ msgstr "Diese(r) Benutzer(in) wird der/die Autor(in) aller Ereignisse im Aktivit
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr "Diese(r) Benutzer(in) wird der/die Autor(in) aller Ereignisse im Aktivitätsfeed sein, die die Folge eines Updates, wie die Erstellung neuer Branches oder das Pushen neuer Commits zu existierenden Branches, sind. Bei der Erstellung oder der Neuzuweisung kannst du nur dich selbst als Mirror-Benutzer(in) zuweisen."
-msgid "This will delete the custom metric, Are you sure?"
-msgstr "Dadurch wird die benutzerdefinierte Metrik gelöscht. Bist du sicher?"
+msgid "This will redirect you to an external sign in page."
+msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "Diese E-Mails werden automatisch zu hier gelisteten Tickets (wobei die Kommentare zur E-Mail-Konversation werden)."
@@ -8280,7 +9727,7 @@ msgid "Time between merge request creation and merge/close"
msgstr "Zeit zwischen Anlegen und Mergen/Schließen eines Merge-Requests"
msgid "Time estimate"
-msgstr ""
+msgstr "Geschätzte Zeit"
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "Zeit in Sekunden die GitLab auf die Antwort des externen Dienstes warten wird. Wenn der Dienst nicht rechtzeitig antwortet, wird der Zugriff verweigert."
@@ -8454,9 +9901,18 @@ msgstr "Tipp:"
msgid "Title"
msgstr "Titel"
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr "Zu GitLab"
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "Um einen SSH-Schlüssel hinzuzufügen, musst du %{generate_link_start}einen generieren%{link_end} oder einen %{existing_link_start}vorhandenen Schlüssel%{link_end} verwenden."
@@ -8499,13 +9955,28 @@ msgstr "Um GitHub-Repositories zu importieren, musst du GitLab zunächst erlaube
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "Um ein SVN-Repository zu importieren, schaue dir %{svn_link} an."
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr "Um ein komplettes GitLab-Projekt von einer GitLab-Installation zu einer anderen umzuziehen oder zu kopieren, navigiere zur Einstellungsseite des Originalprojektes, erzeuge eine Export-Datei und lade sie hier hoch."
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "Um die CI/CD-Funktionen nur für ein externes Repository zu verwenden, wähle <strong>CI/CD für externes Repo</strong> aus."
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr "So richtest du die SAML-Authentifizierung für deine Gruppe über einen
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Um deine Jobs zur Verfügung zu stellen, kannst du Runner zu deiner Gruppe hinzufügen"
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr "Zu dieser GitLab-Instanz"
@@ -8523,6 +9997,9 @@ msgstr "Um deine GitLab CI-Konfigurationen zu validieren, gehe in deinem Projekt
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. In der Monatsansicht werden nur Epics des letzten Monats, des aktuellen Monats und der nächsten 5 Monate angezeigt."
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr "Um deine Suche zu erweitern, verändere oder entferne Filter."
@@ -8538,15 +10015,18 @@ msgstr "To-dos"
msgid "Toggle Sidebar"
msgstr "Seitenleiste ein-/ausblenden"
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr "Beschreibung des Commits ein-/ausklappen"
+msgid "Toggle commit list"
+msgstr ""
+
msgid "Toggle discussion"
msgstr "Diskussion ein-/ausblenden"
-msgid "Toggle file browser"
-msgstr "Dateibrowser umschalten"
-
msgid "Toggle navigation"
msgstr "Navigation umschalten"
@@ -8598,9 +10078,6 @@ msgstr "Baumstrukturansicht"
msgid "Trending"
msgstr "Beliebt"
-msgid "Trigger"
-msgstr "Trigger"
-
msgid "Trigger pipelines for mirror updates"
msgstr "Pipelines für Mirror-Updates auslösen"
@@ -8610,6 +10087,12 @@ msgstr "Triggere Pipelines, wenn Branches oder Tags aus dem Upstream-Repository
msgid "Trigger this manual action"
msgstr "Löse diese manuelle Aktion aus"
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "Trigger können erzwingen, dass einen bestimmten Branch oder Tag mit einem API-Aufruf neu erstellt wird. Diese Token nehmen die Identität ihres/ihrer verbundenen Benutzers/Benutzerin an, einschließlich ihres Zugriffs auf Projekte und ihrer Projektberechtigungen."
@@ -8619,7 +10102,13 @@ msgstr ""
msgid "Try again"
msgstr "Wiederholen"
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
+msgstr "Teste für 30 Tage alles was GitLab zu bieten hat."
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
msgid "Turn on Service Desk"
@@ -8629,26 +10118,32 @@ msgid "Twitter"
msgstr "Twitter"
msgid "Two-factor authentication"
-msgstr ""
+msgstr "Zwei-Faktor-Authentifizierung"
msgid "Type"
msgstr "Typ"
+msgid "URL"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Der Diff konnten nicht geladen werden. %{button_try_again}"
-msgid "Unable to save your changes"
-msgstr ""
-
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Aufgrund von \"%{reason}\" konntest du dich nicht mit SAML anmelden"
msgid "Unable to update this epic at this time."
msgstr "Dieses Epic kann gerade nicht aktualisiert werden."
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr "Rückgängig machen"
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr "Unbekannt"
@@ -8697,6 +10192,9 @@ msgstr "Abmeldung auf Gruppenebene"
msgid "Unsubscribe at project level"
msgstr "Abmeldung auf Projektebene"
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr "Nicht bestätigt"
@@ -8704,20 +10202,26 @@ msgid "Up to date"
msgstr "Aktuell"
msgid "Upcoming"
-msgstr ""
+msgstr "Demnächst"
msgid "Update"
msgstr "Aktualisieren"
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr "Jetzt updaten"
msgid "Update your group name, description, avatar, and visibility."
-msgstr ""
+msgstr "Deine Gruppenbezeichnung, Beschreibung, Avatar und Sichtbarkeit anpassen."
msgid "Updating"
msgstr "Aktualisiere"
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "Aktualisiere deinen Tarif, um die erweiterte globale Suche zu aktivieren."
@@ -8736,15 +10240,30 @@ msgstr "Upgrade deinen Tarif um die Ticketboards zu verbessern."
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr "Lade <code>GoogleCodeProjectHosting.json</code> hier hoch:"
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "Neue Datei hochladen"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "Datei hochladen"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "Zum Upload klicken"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr "Upvotes"
@@ -8775,9 +10294,15 @@ msgstr "Benutze den folgenden Registrierungstoken während des Setups:"
msgid "Use your global notification setting"
msgstr "Benutze deine globalen Benachrichtigungseinstellungen"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Wird von Mitgliedern verwendet, um sich in GitLab in deiner Gruppe anzumelden"
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr "Benutzer-Kohorten sind nur sichtbar, wenn der %{usage_ping_link_start}Nutzungsbericht%{usage_ping_link_end} aktiviert ist."
@@ -8791,58 +10316,94 @@ msgid "User map"
msgstr "Benutzerzuordnung"
msgid "UserProfile|Activity"
-msgstr ""
+msgstr "Aktivität"
msgid "UserProfile|Already reported for abuse"
-msgstr ""
+msgstr "Bereits wegen Missbrauchs gemeldet"
msgid "UserProfile|Contributed projects"
msgstr ""
msgid "UserProfile|Edit profile"
+msgstr "Profil bearbeiten"
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr ""
msgid "UserProfile|Groups"
+msgstr "Gruppen"
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
msgstr ""
msgid "UserProfile|Most Recent Activity"
+msgstr "Neueste Aktivität"
+
+msgid "UserProfile|No snippets found."
msgstr ""
msgid "UserProfile|Overview"
-msgstr ""
+msgstr "Ãœbersicht"
msgid "UserProfile|Personal projects"
-msgstr ""
-
-msgid "UserProfile|Recent contributions"
-msgstr ""
+msgstr "Persönliche Projekte"
msgid "UserProfile|Report abuse"
-msgstr ""
+msgstr "Missbrauch melden"
msgid "UserProfile|Snippets"
+msgstr "Codeausschnitte"
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
msgstr ""
msgid "UserProfile|Subscribe"
+msgstr "Abonnieren"
+
+msgid "UserProfile|This user doesn't have any personal projects"
msgstr ""
msgid "UserProfile|This user has a private profile"
+msgstr "Diese(r) Benutzer(in) hat ein privates Profil"
+
+msgid "UserProfile|This user hasn't contributed to any projects"
msgstr ""
msgid "UserProfile|View all"
-msgstr ""
+msgstr "Alles anzeigen"
msgid "UserProfile|View user in admin area"
+msgstr "Benutzer(in) im Adminbereich anzeigen"
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
msgid "Users"
msgstr "Benutzer(innen)"
-msgid "Variables"
-msgstr "Variablen"
+msgid "Users requesting access to"
+msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr "Variablen werden über den Runner auf Umgebungen angewendet. Sie können geschützt werden, indem sie nur für geschützten Branches oder Tags sichtbar gemacht werden. Du kannst Variablen für Passwörter, geheime Schlüssel oder was immer du möchtest verwenden."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
msgid "Various container registry settings."
msgstr "Verschiedene Einstellungen für die Container-Registry."
@@ -8850,12 +10411,18 @@ msgstr "Verschiedene Einstellungen für die Container-Registry."
msgid "Various email settings."
msgstr "Verschiedene E-Mail-Einstellungen."
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr "Verschiedene Einstellungen, die sich auf die GitLab-Leistung auswirken."
msgid "Verification information"
msgstr "Bestätigungsinformationen"
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr "Bestätigt"
@@ -8863,14 +10430,20 @@ msgid "Version"
msgstr "Version"
msgid "View %{alerts}"
-msgstr ""
+msgstr "%{alerts} anzeigen"
msgid "View app"
+msgstr "App anzeigen"
+
+msgid "View deployment"
msgstr ""
-msgid "View documentation"
+msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr "Dokumentation anzeigen"
+
msgid "View epics list"
msgstr "Epic-Liste anzeigen"
@@ -8905,6 +10478,9 @@ msgid "View replaced file @ "
msgstr "Zeige ersetzte Datei @ "
msgid "View the documentation"
+msgstr "Die Dokumentation anzeigen"
+
+msgid "Viewing commit"
msgstr ""
msgid "Visibility and access controls"
@@ -8931,51 +10507,78 @@ msgstr "Öffentlich"
msgid "VisibilityLevel|Unknown"
msgstr "Unbekannt"
-msgid "Vulnerability|Class"
+msgid "Vulnerability Chart"
msgstr ""
-msgid "Vulnerability|Confidence"
+msgid "Vulnerability List"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr "Klasse"
+
+msgid "Vulnerability|Confidence"
+msgstr "Vertrauen"
+
msgid "Vulnerability|Description"
-msgstr ""
+msgstr "Beschreibung"
msgid "Vulnerability|File"
-msgstr ""
+msgstr "Datei"
msgid "Vulnerability|Identifiers"
-msgstr ""
+msgstr "Bezeichner"
msgid "Vulnerability|Instances"
-msgstr ""
+msgstr "Instanzen"
msgid "Vulnerability|Links"
-msgstr ""
+msgstr "Links"
msgid "Vulnerability|Project"
+msgstr "Projekt"
+
+msgid "Vulnerability|Report Type"
msgstr ""
msgid "Vulnerability|Severity"
msgstr "Schweregrad"
-msgid "Vulnerability|Solution"
-msgstr "Lösung"
-
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Du möchtest die Daten sehen? Bitte frage eine(n) Administrator(in) nach dem Zugang."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Wir haben potenziellen Spam in %{humanized_resource_name} gefunden. Bitte löse den reCAPTCHA um fortzufahren."
msgid "We don't have enough data to show this stage."
msgstr "Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Wir wollen sicher gehen, dass du es bist. Bitte bestätige, dass du kein Roboter bist."
msgid "Web IDE"
msgstr "Web IDE"
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr "Web-Terminal"
@@ -9000,6 +10603,9 @@ msgstr "Wenn diese Option aktiviert ist, können Benutzer(innen) GitLab nicht ve
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Wenn die URL leer gelassen wird, können Klassifizierungslabels weiterhin angegeben werden ohne projektübergreifende Eigenschaften auszuschalten oder einen externen Autorisierungscheck durchzuführen."
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr "Wer kann diese Gruppe sehen?"
@@ -9141,12 +10747,21 @@ msgstr "Seiten"
msgid "Wiki|Wiki Pages"
msgstr "Wiki-Seiten"
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr "Mit der Beitragsanalyse hast du einen Überblick über die Aktivitäten von Tickets, Merge-Requests und Push-Events deiner Organisation und seiner Mitglieder."
msgid "Withdraw Access Request"
msgstr "Zugriffsanfrage widerrufen"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr "Ja"
@@ -9159,6 +10774,9 @@ msgstr "Ja, lass mich Google Code-Benutzer(innen) vollständigen Namen oder GitL
msgid "Yesterday"
msgstr "Gestern"
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Du bist Administrator(in). Wenn du <strong>%{client_name}</strong> Zugriff gewährst, wird es auch als Administrator mit GitLab interagieren können. Mit Vorsicht fortfahren."
@@ -9177,6 +10795,9 @@ msgstr "Du bist dabei %{project_full_name} einem/einer andere(n) Besitzer(in) zu
msgid "You are on a read-only GitLab instance."
msgstr "Du bist auf einer GitLab-Instanz, die nur Lesezugriff erlaubt."
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "Du kannst stattdessen %{linkStart}den Blob anzeigen%{linkEnd}."
@@ -9201,6 +10822,9 @@ msgstr "Du kannst Dateien nur hinzufügen, wenn du dich auf einem Branch befinde
msgid "You can only edit files when you are on a branch"
msgstr "Du kannst Dateien nur bearbeiten, wenn du dich auf einem Branch befindest"
+msgid "You can only merge once the items above are resolved"
+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 "Du kannst den Merge-Konflikt lösen, indem du entweder den interaktiven Modus verwendest, indem du die Schaltflächen %{use_ours} oder %{use_theirs} wählst, oder indem du die Dateien direkt bearbeitest. Übernimm diese Änderungen mittels Commit in %{branch_name}"
@@ -9219,6 +10843,9 @@ msgstr "Du kannst nicht auf dieser schreibgeschützte GitLab-Instanz schreiben."
msgid "You do not have any subscriptions yet"
msgstr "Du hast noch keine Abonnements"
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "Du verfügst nicht über die erforderlichen Berechtigungen um die Einstellungen der LDAP-Gruppensynchronisierung zu überschreiben."
@@ -9228,12 +10855,18 @@ msgstr "Du hast keine Anwendungen"
msgid "You don't have any authorized applications"
msgstr "Du hast keine autorisierten Anwendungen"
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr "Du hast keine Berechtigungen"
msgid "You have reached your project limit"
msgstr "Du hast die Projektbegrenzung erreicht"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr "Du musst unsere Nutzungsbedingungen und Datenschutzerklärung akzeptieren, um ein Konto registrieren zu können"
@@ -9243,17 +10876,23 @@ msgstr "Du musst Betreuerzugriff besitzen, um das Entfernen einer Sperre zu erzw
msgid "You need a different license to enable FileLocks feature"
msgstr "Du benötigst eine andere Lizenz, um die FileLocks-Funktion zu aktivieren"
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr "Du benötigst git-lfs in Version %{min_git_lfs_version} (oder höher) um fortzufahren. Bitte besuche https://git-lfs.github.com"
msgid "You need permission."
msgstr "Du brauchst eine Genehmigung."
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
-msgstr "Du wirst alle Änderungen an dieser Datei verlieren. Dies kann nicht rückgängig gemacht werden."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
-msgstr "Du wirst alle nicht vorgemerkten Änderungen an diesem Projekt verlieren. Dies kann nicht rückgängig gemacht werden."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
msgid "You will not get any notifications via email"
msgstr "Du wirst keine Benachrichtigungen per E-Mail erhalten"
@@ -9294,6 +10933,9 @@ msgstr "Du erhältst diese E-Mail aufgrund deines Kontos auf %{host}. %{manage_n
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr "Deine Gruppen"
@@ -9309,12 +10951,18 @@ msgstr "Aktivitäten deiner Projekte"
msgid "Your Todos"
msgstr "Deine To-dos"
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr "Deine Anwendungen (%{size})"
msgid "Your authorized applications"
msgstr "Deine autorisierten Anwendungen"
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "Deine Änderungen können an %{branch_name} committet werden, da eine Merge-Request geöffnet ist."
@@ -9322,17 +10970,29 @@ msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr "Deine Änderungen wurden committet. Commit %{commitId}%{commitStats}"
msgid "Your changes have been saved"
-msgstr ""
+msgstr "Deine Änderungen wurden gespeichert"
msgid "Your comment will not be visible to the public."
msgstr "Dein Kommentar wird nicht öffentlich sichtbar sein."
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "Deine Gruppen"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "Dein Name"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr "Deine Projekte"
@@ -9342,12 +11002,18 @@ msgstr "ein(e) gelöschte(r) Benutzer(in)"
msgid "ago"
msgstr "vor"
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr "unter anderem"
msgid "assign yourself"
msgstr "selber zuweisen"
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr "Branch-Name"
@@ -9440,6 +11106,9 @@ msgstr "Containerüberprüfung entdeckt bekannte Sicherheitslücken in deinen Do
msgid "ciReport|DAST"
msgstr "DAST"
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr "Die Abhängigkeitsüberprüfung entdeckt bekannte Sicherheitslücken in den Abhängigkeiten deines Quellcodes."
@@ -9455,6 +11124,12 @@ msgstr "Sicherheitslücke ausblenden"
msgid "ciReport|Dismissed by"
msgstr "Abgelehnt von"
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr "Dynamic Application Security Testing (DAST) entdeckt Schwachstellen in deiner Webanwendung."
@@ -9575,6 +11250,9 @@ msgstr "in der Pipeline"
msgid "command line instructions"
msgstr "Befehlszeilenanweisungen"
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr "Du willst die Vertraulichkeit deaktivieren. Das bedeutet, dass <strong>jeder</strong> das Ticket betrachten und kommentieren kann."
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] "Tag"
msgstr[1] "Tage"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr "Bereitstellungstoken"
msgid "disabled"
msgstr "dektiviert"
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr "erledigt"
@@ -9612,6 +11298,15 @@ msgstr[1] "Entwürfe"
msgid "enabled"
msgstr "aktiviert"
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} aktualisiert die geschätzte Zeit mit dem aktuellsten Befehl."
@@ -9621,21 +11316,39 @@ msgstr "für dieses Projekt"
msgid "from"
msgstr "von"
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr "Hilfe"
msgid "here"
msgstr "hier"
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://dein-bitbucket-server"
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr "Vorgehen beim Import"
msgid "importing"
msgstr "Importiere"
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "Instanz abgeschlossen"
@@ -9650,9 +11363,27 @@ msgstr "ist aufgrund einer Upstream-Sperre ungültig"
msgid "is not a valid X509 certificate."
msgstr "ist kein gültiges X509-Zertifikat."
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr "Ticketboards"
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr "neuste Bereitstellung"
@@ -9665,14 +11396,29 @@ msgstr "Lizenzverwaltung"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "gesperrt durch %{path_lock_user_name} %{created_at}"
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "Merge-Request"
msgstr[1] "Merge-Requests"
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Bitte stelle es wieder her, oder verwende einen anderen Branch %{missingBranchName}"
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} %{emphasisStart} gesunken %{emphasisEnd} von %{memoryFrom} MB auf %{memoryTo} MB"
@@ -9688,11 +11434,11 @@ msgstr "Genehmigung hinzufügen"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Erlaube Commits von Mitgliedern die zum Zielbranch mergen können"
-msgid "mrWidget|An error occured while removing your approval."
-msgstr "Beim Entfernen deiner Genehmigung ist ein Fehler aufgetreten."
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
-msgstr "Beim Abrufen der Genehmigungsdaten für diesen Merge-Request ist ein Fehler aufgetreten."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Während des Sendens deiner Genehmigung trat ein Fehler auf."
@@ -9730,6 +11476,9 @@ msgstr "Schließt"
msgid "mrWidget|Create an issue to resolve them later"
msgstr "Erstelle ein Ticket, um es später zu lösen"
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Bereitstellungsstatistiken derzeit nicht verfügbar"
@@ -9782,7 +11531,7 @@ msgid "mrWidget|No Approval required; you can still approve"
msgstr "Keine Genehmigung erforderlich; du kannst noch genehmigen"
msgid "mrWidget|Open in Web IDE"
-msgstr "Öffnen im Web-IDE"
+msgstr "In Web-IDE öffnen"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
msgstr "Pipeline blockiert. Die Pipeline für diesen Merge-Request erfordert eine manuelle Aktion um fortzufahren"
@@ -9802,12 +11551,6 @@ msgstr "Jetzt aktualisieren"
msgid "mrWidget|Refreshing now"
msgstr "Aktualisiere gerade"
-msgid "mrWidget|Remove Source Branch"
-msgstr "Quellbranch entfernen"
-
-msgid "mrWidget|Remove source branch"
-msgstr "Quellbranch entfernen"
-
msgid "mrWidget|Remove your approval"
msgstr "Entferne deine Genehmigung"
@@ -9854,20 +11597,20 @@ msgstr "Die Pipeline für diesen Merge-Request ist fehlgeschlagen. Bitte wiederh
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "Der HEAD des Quellbranches wurde kürzlich geändert. Bitte lade die Seite neu und überprüfe die Änderungen vor dem Mergen"
-msgid "mrWidget|The source branch has been removed"
-msgstr "Der Quellbranch wurde entfernt"
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr "Der Quellbranch ist %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} dem Zielbranch"
-msgid "mrWidget|The source branch is being removed"
-msgstr "Der Quellbranch wird gerade entfernt"
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
-msgid "mrWidget|The source branch will be removed"
-msgstr "Der Quellbranch wird entfernt"
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
-msgid "mrWidget|The source branch will not be removed"
-msgstr "Der Quellbranch wird nicht entfernt"
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "Es gibt Merge-Konflikte"
@@ -9875,6 +11618,9 @@ msgstr "Es gibt Merge-Konflikte"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "Es gibt ungelöste Diskussionen. Bitte löse diese Diskussionen"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Dieser Merge-Request konnte nicht automatisch gemerged werden"
@@ -9887,12 +11633,12 @@ msgstr "Dieses Projekt wurde archiviert, der Schreibzugriff wurde deaktiviert"
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr "Du darfst dieses Projekt nicht direkt bearbeiten. Bitte erstelle einen Fork, um Änderungen vorzunehmen."
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "Du kannst diesen Merge-Request manuell mergen mit dem"
-msgid "mrWidget|You can remove source branch now"
-msgstr "Du kannst den Quellbranch jetzt entfernen"
-
msgid "mrWidget|branch does not exist."
msgstr "Branch existiert nicht."
@@ -9911,9 +11657,21 @@ msgstr "nicht verfügbar"
msgid "new merge request"
msgstr "Neuer Merge-Request"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "Benachrichtungs-E-mails"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr "oder"
@@ -9933,6 +11691,9 @@ msgstr "Passwort"
msgid "personal access token"
msgstr "Persönlicher Zugangs-Token"
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr "Der private Schlüssel stimmt nicht mit dem Zertifikat überein."
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] "Projekt"
msgstr[1] "Projekte"
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr "verbleibend"
@@ -9953,28 +11720,58 @@ msgstr "Fälligkeitsdatum entfernen"
msgid "remove weight"
msgstr "Gewichtung entfernen"
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Antwort"
+msgstr[1] "Antworten"
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
msgid "source"
msgstr "Quelle"
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} aktualisiert die Summe der aufgewendeten Zeit."
msgid "started"
msgstr "gestartet"
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr "dieses Dokument"
msgid "to help your contributors communicate effectively!"
msgstr "um deinen Mitwirkenden zu helfen möglichst effizient zu kommunizieren!"
-msgid "toggle collapse"
-msgstr "Ein- und ausklappen"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
+msgstr ""
msgid "username"
msgstr "Benutzername"
@@ -9982,9 +11779,15 @@ msgstr "Benutzername"
msgid "uses Kubernetes clusters to deploy your code!"
msgstr "verwendet Kubernetes-Cluster, um deinen Code bereitzustellen!"
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "sieh es auf GitLab an"
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "mit %{additions} Ergänzungen, %{deletions} Löschungen."
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] "innerhalb %d Minute "
msgstr[1] "innerhalb %d Minuten "
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 1184b396e13..68aebe5b9f2 100644
--- a/locale/el_GR/gitlab.po
+++ b/locale/el_GR/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: el\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:23\n"
+"PO-Revision-Date: 2019-02-11 08:15\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index aed12521a79..fde168f06af 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: eo\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:22\n"
+"PO-Revision-Date: 2019-02-11 08:13\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,11 +433,11 @@ msgstr "Aktiveco"
msgid "Add"
msgstr ""
-msgid "Add Changelog"
-msgstr "Aldoni liston de ÅanÄoj"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "Aldoni gvidliniojn por kontribuado"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ĉu vi certe volas forigi ĉi tiun ĉenstablan planon?"
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Alkroĉu dosieron per Åovmetado aÅ­ %{upload_link}"
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "La branĉo <strong>%{branch_name}</strong> estis kreita. Por agordi aÅ­tomatan disponigadon, bonvolu elekti Yaml-Åablonon por GitLab CI kaj enmeti viajn ÅanÄojn. %{link_to_autodeploy_doc}"
@@ -1326,21 +1527,36 @@ msgstr "Foliumi dosierojn"
msgid "Browse files"
msgstr "Elekti dosierojn"
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "de"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "Nuligi"
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,12 +1671,12 @@ msgstr "Malfari"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
-msgstr "Listo de ÅanÄoj"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "Diagramoj"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] "Enmetado"
msgstr[1] "Enmetadoj"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "DaÅ­ro de la enmetadoj por la lastaj 30 enmetadoj"
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,8 +2672,8 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
-msgstr "Gvidlinioj por kontribuado"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr ""
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr "Krei novan dosierujon"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Kreu propran atingoĵetonon en via konto por ebligi al vi eltiri kaj alpuÅi per %{protocol}."
@@ -2449,6 +2828,9 @@ msgstr "Krei peton pri kunfando"
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr "La propraj sciigaj niveloj estas la samaj kiel la niveloj de partoprenad
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr "Preparo por eldono"
msgid "CycleAnalyticsStage|Test"
msgstr "Testado"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Difini propran Åablonon, uzante la sintakson de Cron"
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr "ElÅuti"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "ElÅuti en formato „tar“"
@@ -2913,6 +3352,9 @@ msgstr "Normala dosiero kun diferencoj"
msgid "DownloadSource|Download"
msgstr "ElÅuti"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr "Redakti"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Redakti ĉenstablan planon %{id}"
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Ĉiutage (je 4:00)"
@@ -3252,9 +3772,39 @@ msgstr "Ĉiumonate (en la 1a de la monato, je 4:00)"
msgid "Every week (Sundays at 4:00am)"
msgstr "Ĉiusemajne (en dimanĉo, je 4:00)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Ne eblas forigi la ĉenstablan planon"
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,15 +4054,35 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "Dosieroj"
-msgid "Files (%{human_size})"
-msgstr ""
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr "Filtri per mesaÄo"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "Trovi per dosierindiko"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "Trovi dosieron"
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "Unue"
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr "La refreÅigo komenciÄis sukcese"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr "Enporti deponejon"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr "Intervala Åablono"
msgid "Introducing Cycle Analytics"
msgstr "Ni prezentas al vi la ciklan analizon"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] "La lastaj %d tagoj"
msgid "Last Pipeline"
msgstr "Lasta ĉenstablo"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "Lasta enmetado"
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] "Novaj problemoj"
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "Nova ĉenstabla plano"
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr "Nova dosierujo"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr "Nova peto pri kunfando"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr "Ne estas planoj"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr "Sciigaj eventoj"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Fermi problemon"
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only policy:"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "Ĉenstablo"
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr "La ligilo por la projekta elporto eksvalidiÄis. Bonvolu krei novan elpo
msgid "Project export started. A download link will be sent by email."
msgstr "La elporto de la projekto komenciÄis. Vi ricevos ligilon per retpoÅto por elÅuti la datenoj."
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "Legu pli"
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
-msgstr "LeguMin"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr "Rilataj aplikitaj petoj pri kunfando"
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "Rememorigu denove"
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr "Peti atingeblon"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Malfari ĉi tiun enmetadon"
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Konservi ĉenstablan planon"
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr "Kodo"
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "Kreu %{new_merge_request} kun ĉi tiuj ÅanÄoj"
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "Etikedoj"
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "La etapo de la problemo montras kiom la tempo pasas de la kreado de problemo Äis la atribuado de la problemo al cela etapo de la projekto, aÅ­ al listo sur la problemtabulo. Komencu krei problemojn por vidi la datenojn por ĉi tiu etapo."
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "La valoro, kiu troviÄas en la mezo de aro da rigardataj valoroj. Ekzemple: inter 3, 5 kaj 9, la mediano estas 5. Inter 3, 5, 7 kaj 8, la mediano estas (5+7)/2 = 6."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "AlÅuti novan dosieron"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "AlÅuti dosieron"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "alklaku por alÅuti"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr "Uzi vian Äeneralan agordon pri la sciigoj"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr "Publika"
msgid "VisibilityLevel|Unknown"
msgstr "Nekonata"
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Ĉu vi volas vidi la datenojn? Bonvolu peti atingeblon de administranto."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "Ne estas sufiĉe da datenoj por montri ĉi tiun etapon."
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr "Nuligi la peton pri atingeblo"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr "Oni povas aldoni dosierojn nur kiam oni estas en branĉo"
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr "Vi ne povas krei pliajn projektojn"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr "VI bezonas permeson."
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "Via nomo"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] "tago"
msgstr[1] "tagoj"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr "novan peton pri kunfando"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "sciigoj per retpoÅto"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index d838e5e2418..ae1db647187 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -13,36 +13,35 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:19\n"
+"PO-Revision-Date: 2019-02-11 10:21\n"
msgid " Status"
-msgstr ""
+msgstr " Estado"
msgid " and"
-msgstr ""
+msgstr " y"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " degradado en %d punto"
+msgstr[1] " degradado en %d puntos"
msgid " improved on %d point"
msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " mejorado en %d punto"
+msgstr[1] " mejorado en %d puntos"
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" en proyectos"
msgid "%d commit"
msgid_plural "%d commits"
@@ -51,13 +50,11 @@ msgstr[1] "%d cambios"
msgid "%d commit behind"
msgid_plural "%d commits behind"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commit detrás"
+msgstr[1] "%d commits detrás"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -76,6 +73,11 @@ msgstr[1] ""
msgid "%d issue"
msgid_plural "%d issues"
+msgstr[0] "%d incidencia"
+msgstr[1] "%d incidencias"
+
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
msgstr[0] ""
msgstr[1] ""
@@ -91,8 +93,8 @@ msgstr[1] ""
msgid "%d metric"
msgid_plural "%d metrics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d métrica"
+msgstr[1] "%d métricas"
msgid "%d staged change"
msgid_plural "%d staged changes"
@@ -113,7 +115,7 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
msgid "%{authorsName}'s discussion"
-msgstr ""
+msgstr "Discusión de %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
@@ -122,6 +124,9 @@ msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build
msgstr ""
msgid "%{count} %{alerts}"
+msgstr "%{count} %{alerts}"
+
+msgid "%{count} more"
msgstr ""
msgid "%{count} more assignees"
@@ -138,48 +143,72 @@ msgstr[0] ""
msgstr[1] ""
msgid "%{filePath} deleted"
-msgstr ""
+msgstr "%{filePath} eliminado"
msgid "%{firstLabel} +%{labelCount} more"
+msgstr "%{firstLabel} +%{labelCount} más"
+
+msgid "%{firstOption} +%{extraOptionCount} more"
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "¡Va a eliminar %{issuableType}! ¿Está seguro de que desea realizar esta acción?"
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
msgid "%{loadingIcon} Started"
-msgstr ""
+msgstr "%{loadingIcon} Iniciado"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
-msgstr ""
+msgstr "%{lock_path} está bloqueado por el usuario de GitLab %{lock_user_id}"
msgid "%{name}'s avatar"
-msgstr ""
-
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
+msgstr "Avatar de %{name}"
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits detrás de %{default_branch}, %{number_commits_ahead} commits por delante"
msgid "%{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
+msgstr "%{percent}%% completado"
+
+msgid "%{state} epics"
msgstr ""
-msgid "%{text} %{files}"
-msgid_plural "%{text} %{files} files"
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] "%{text}%{files}"
+msgstr[1] "%{text}%{files} archivos"
+
msgid "%{text} is available"
msgstr "%{text} esta disponible"
msgid "%{title} changes"
-msgstr ""
+msgstr "%{title} cambios"
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr ""
@@ -187,35 +216,44 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
-msgid "+ %{count} more"
+msgid "%{user_name} profile page"
msgstr ""
+msgid "(external source)"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr "+ %{count} más"
+
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} más"
-msgid "- Runner is active and can process any new jobs"
+msgid ", or "
msgstr ""
+msgid "- Runner is active and can process any new jobs"
+msgstr "- El ejecutor está activo y puede procesar cualquier trabajo nuevo"
+
msgid "- Runner is paused and will not receive any new jobs"
-msgstr ""
+msgstr "- El ejecutor está en pausa y no recibirá ningún trabajo nuevo"
msgid "- show less"
msgstr "- mostrar menos"
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 adición de %{type}"
+msgstr[1] "%{count} %{type} adiciones"
msgid "1 %{type} modification"
msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 %{type} modificación"
+msgstr[1] "%{count} %{type} modificaciones"
msgid "1 closed issue"
msgid_plural "%d closed issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 incidencia cerrada"
+msgstr[1] "%d incidencias cerradas"
msgid "1 closed merge request"
msgid_plural "%d closed merge requests"
@@ -224,8 +262,8 @@ msgstr[1] ""
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 grupo"
+msgstr[1] "%d grupos"
msgid "1 merged merge request"
msgid_plural "%d merged merge requests"
@@ -234,8 +272,8 @@ msgstr[1] ""
msgid "1 open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 incidencia abierta"
+msgstr[1] "%d incidencias abiertas"
msgid "1 open merge request"
msgid_plural "%d open merge requests"
@@ -249,34 +287,37 @@ msgstr[1] "%d pipelines"
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 rol"
+msgstr[1] "%d roles"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 usuario"
+msgstr[1] "%d usuarios"
msgid "1st contribution!"
msgstr "¡1ra contribución!"
-msgid "2FA enabled"
+msgid "2FA"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "2FA enabled"
+msgstr "Verificación en 2 pasos habilitada"
+
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
-msgstr ""
+msgstr "No tiene permisos para acceder a esta página."
msgid "404|Make sure the address is correct and the page hasn't moved."
-msgstr ""
+msgstr "Asegúrese de que la dirección sea correcta y que la página no se haya movido."
msgid "404|Page Not Found"
-msgstr ""
+msgstr "Página no encontrada"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "Por favor, contacte con su administrador de GitLab si cree que se trata de un error."
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
msgstr ""
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -318,10 +359,10 @@ msgid "A default branch cannot be chosen for an empty project."
msgstr ""
msgid "A deleted user"
-msgstr ""
+msgstr "Un usuario eliminado"
msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr ""
+msgstr "Un miembro del equipo de GitLab revisará tus comentarios tan pronto como sea posible."
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -336,16 +377,16 @@ msgid "A user with write access to the source branch selected this option"
msgstr ""
msgid "About GitLab"
-msgstr ""
+msgstr "Acerca de Gitlab"
msgid "About GitLab CE"
-msgstr ""
+msgstr "Acerca de Gitlab CE"
msgid "About auto deploy"
msgstr "Acerca del auto despliegue"
msgid "About this feature"
-msgstr ""
+msgstr "Acerca de esta característica"
msgid "Abuse Reports"
msgstr "Reportes de abuso"
@@ -353,11 +394,14 @@ msgstr "Reportes de abuso"
msgid "Abuse reports"
msgstr ""
-msgid "Accept terms"
+msgid "Accept invitation"
msgstr ""
+msgid "Accept terms"
+msgstr "Aceptar los términos"
+
msgid "Accepted MR"
-msgstr ""
+msgstr "Merge Request aceptado"
msgid "Access Tokens"
msgstr "Tokens de acceso"
@@ -375,94 +419,100 @@ msgid "Account"
msgstr "Cuenta"
msgid "Account and limit"
-msgstr ""
+msgstr "Cuenta y límite"
msgid "Active"
msgstr "Activo"
msgid "Active Sessions"
-msgstr ""
+msgstr "Sesiones activas"
msgid "Activity"
msgstr "Actividad"
msgid "Add"
-msgstr ""
+msgstr "Añadir"
-msgid "Add Changelog"
-msgstr "Agregar Changelog"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "Agregar guía de contribución"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
msgid "Add Jaeger URL"
-msgstr ""
+msgstr "Añadir URL de Jaeger"
msgid "Add Kubernetes cluster"
+msgstr "Añadir clúster de Kubernetes"
+
+msgid "Add README"
msgstr ""
-msgid "Add Readme"
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
msgid "Add a table"
-msgstr ""
+msgstr "Añadir tabla"
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
msgid "Add comment now"
-msgstr ""
+msgstr "Añadir comentario ahora"
msgid "Add image comment"
-msgstr ""
+msgstr "Añadir comentario a la imagen"
msgid "Add license"
-msgstr ""
+msgstr "Añadir licencia"
msgid "Add new application"
-msgstr ""
+msgstr "Añadir una nueva aplicación"
msgid "Add new directory"
msgstr "Agregar nuevo directorio"
msgid "Add projects"
-msgstr ""
+msgstr "Añadir proyectos"
msgid "Add reaction"
+msgstr "Añadir reacción"
+
+msgid "Add to project"
msgstr ""
msgid "Add to review"
-msgstr ""
+msgstr "Añadir a revisión"
msgid "Add todo"
-msgstr ""
+msgstr "Añadir tarea pendiente"
msgid "Add user(s) to the group:"
+msgstr "Añadir usuario(s) al grupo:"
+
+msgid "Add users or groups who are allowed to approve every merge request"
msgstr ""
msgid "Add users to group"
-msgstr ""
+msgstr "Agregar usuarios al grupo"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
msgid "Additional text"
-msgstr ""
+msgstr "Texto adicional"
msgid "Admin Area"
-msgstr ""
+msgstr "Ãrea de administración"
msgid "Admin Overview"
-msgstr ""
-
-msgid "Admin area"
-msgstr ""
+msgstr "Vista de administrador"
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -489,48 +539,111 @@ msgid "AdminProjects| You’re about to permanently delete the project %{project
msgstr ""
msgid "AdminProjects|Delete"
-msgstr ""
+msgstr "Eliminar"
msgid "AdminProjects|Delete Project %{projectName}?"
-msgstr ""
+msgstr "¿Eliminar el proyecto %{projectName}?"
msgid "AdminProjects|Delete project"
+msgstr "Eliminar proyecto"
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
+msgstr "Bloquear usuario"
+
+msgid "AdminUsers|Blocked"
msgstr ""
-msgid "AdminUsers|Delete User %{username} and contributions?"
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr "¿Eliminar el usuario %{username} y sus contribuciones?"
+
msgid "AdminUsers|Delete User %{username}?"
-msgstr ""
+msgstr "¿Eliminar el usuario %{username}?"
msgid "AdminUsers|Delete user"
-msgstr ""
+msgstr "Eliminar usuario"
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
msgstr ""
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr "Permisos avanzados, almacenamiento de grandes archivos y configuraciones de autenticación de dos factores."
+
msgid "Advanced settings"
msgstr "Configuración avanzada"
msgid "Alert"
msgid_plural "Alerts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Alerta"
+msgstr[1] "Alertas"
+
+msgid "Alerts"
+msgstr ""
msgid "All"
msgstr "Todos"
@@ -539,9 +652,15 @@ msgid "All changes are committed"
msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr "Todas las funcionalidades están habilitadas para proyectos en blanco, plantillas, o al importar, pero puedes deshabilitarlas posteriormente en la configuración del proyecto."
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All users"
+msgstr "Todos los usuarios"
+
+msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
msgid "Allow commits from members who can merge to the target branch."
@@ -560,9 +679,12 @@ msgid "Allow requests to the local network from hooks and services."
msgstr ""
msgid "Allow users to request access"
-msgstr ""
+msgstr "Permitir a los usuarios solicitar acceso"
msgid "Allow users to request access if visibility is public or internal."
+msgstr "Permitir a los usuarios solicitar acceso si la visibilidad es pública o interna."
+
+msgid "Allowed to fail"
msgstr ""
msgid "Allows you to add and manage Kubernetes clusters."
@@ -592,46 +714,19 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
-msgstr ""
-
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
+msgstr "Se ha producido un error"
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
-msgstr ""
+msgstr "Se ha producido un error al agregar un borrador a la discusión."
msgid "An error occurred adding a new draft."
+msgstr "Se ha producido un error al añadir un nuevo borrador."
+
+msgid "An error occurred creating the new branch."
msgstr ""
msgid "An error occurred previewing the blob"
@@ -641,170 +736,254 @@ msgid "An error occurred when toggling the notification subscription"
msgstr "Se produjo un error al activar/desactivar la suscripción de notificación"
msgid "An error occurred when updating the issue weight"
-msgstr ""
+msgstr "Se ha producido un error al actualizar el tamaño de la incidencia"
msgid "An error occurred while adding approver"
-msgstr ""
+msgstr "Se ha producido un error al añadir el aprobador."
msgid "An error occurred while deleting the comment"
-msgstr ""
+msgstr "Se ha producido un error al eliminar el comentario"
msgid "An error occurred while detecting host keys"
-msgstr ""
+msgstr "Se ha producido un error al detectar las claves del host."
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
-msgstr ""
+msgstr "Se ha producido un error al desactivar la alerta. Actualice la página y vuelva a intentarlo."
msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
msgstr ""
msgid "An error occurred while fetching markdown preview"
-msgstr ""
+msgstr "Se ha producido un error al obtener la previsualización del markdown."
msgid "An error occurred while fetching pending comments"
-msgstr ""
+msgstr "Se ha producido un error al recuperar los comentarios pendientes"
msgid "An error occurred while fetching sidebar data"
-msgstr "Se produjo un error al obtener datos de la barra lateral"
+msgstr "Se ha producido un error al obtener los datos de la barra lateral."
msgid "An error occurred while fetching stages."
msgstr ""
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "Se ha producido un error al obtener el log del trabajo."
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "Se ha producido un error al obtener el trabajo."
msgid "An error occurred while fetching the jobs."
-msgstr ""
+msgstr "Se ha producido un error al obtener los trabajos."
msgid "An error occurred while fetching the pipeline."
-msgstr ""
+msgstr "Se ha producido un error mientras se obtenía el pipeline."
msgid "An error occurred while getting projects"
-msgstr ""
+msgstr "Se ha producido un error al obtener los proyectos"
msgid "An error occurred while importing project: %{details}"
-msgstr ""
+msgstr "Se ha producido un error al importar el proyecto: %{details}"
msgid "An error occurred while initializing path locks"
-msgstr ""
+msgstr "Se ha producido un error al inicializar los bloqueos de ruta."
msgid "An error occurred while loading chart data"
-msgstr ""
+msgstr "Se ha producido un error al cargar los datos del gráfico."
msgid "An error occurred while loading commit signatures"
-msgstr ""
+msgstr "Se ha producido un error al cargar las firmas de los commits"
msgid "An error occurred while loading diff"
-msgstr ""
+msgstr "Se ha producido un error al cargar el diff"
msgid "An error occurred while loading filenames"
-msgstr ""
+msgstr "Se ha producido un error al cargar los nombres de archivo"
msgid "An error occurred while loading the file"
+msgstr "Se ha producido un error al cargar el archivo"
+
+msgid "An error occurred while loading the subscription details."
msgstr ""
msgid "An error occurred while making the request."
-msgstr ""
+msgstr "Se ha producido un error al crear la petición."
msgid "An error occurred while removing approver"
+msgstr "Se ha producido un error al eliminar el aprobador."
+
+msgid "An error occurred while removing epics."
msgstr ""
-msgid "An error occurred while rendering KaTeX"
+msgid "An error occurred while removing issues."
msgstr ""
+msgid "An error occurred while rendering KaTeX"
+msgstr "Se ha producido un error durante el renderizado con KaTeX"
+
msgid "An error occurred while rendering preview broadcast message"
msgstr ""
msgid "An error occurred while retrieving calendar activity"
-msgstr ""
+msgstr "Se ha producido un error al recuperar la actividad del calendario"
msgid "An error occurred while retrieving diff"
-msgstr ""
+msgstr "Se ha producido un error durante la recuperación de diff"
msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al guardar el estado de LDAP. Por favor, inténtalo de nuevo."
msgid "An error occurred while saving assignees"
-msgstr ""
+msgstr "Se ha producido un error al guardar las asignaciones"
msgid "An error occurred while subscribing to notifications."
-msgstr ""
+msgstr "Se ha producido un error al suscribirse a las notificaciones."
msgid "An error occurred while unsubscribing to notifications."
-msgstr ""
+msgstr "Se ha producido un error al cancelar la suscripción a las notificaciones."
msgid "An error occurred while updating the comment"
-msgstr ""
+msgstr "Se ha producido un error al actualizar el comentario"
msgid "An error occurred while validating username"
+msgstr "Se ha producido un error al validar el nombre de usuario"
+
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
msgstr ""
msgid "An error occurred. Please try again."
-msgstr "Se produjo un error. Por favor inténtelo de nuevo."
+msgstr "Se ha producido un error. Por favor inténtelo de nuevo."
-msgid "Analytics"
+msgid "An unexpected error occurred while checking the project environment."
msgstr ""
-msgid "Anonymous"
+msgid "An unexpected error occurred while checking the project runners."
msgstr ""
-msgid "Anti-spam verification"
+msgid "An unexpected error occurred while communicating with the Web Terminal."
msgstr ""
-msgid "Any"
+msgid "An unexpected error occurred while starting the Web Terminal."
msgstr ""
-msgid "Any Label"
+msgid "An unexpected error occurred while stopping the Web Terminal."
msgstr ""
+msgid "Analytics"
+msgstr "Analíticas"
+
+msgid "Anonymous"
+msgstr "Anónimo"
+
+msgid "Anti-spam verification"
+msgstr "Verificación de correo no deseado"
+
+msgid "Any"
+msgstr "Cualquiera"
+
+msgid "Any Label"
+msgstr "Cualquier etiqueta"
+
msgid "Appearance"
msgstr "Apariencia"
msgid "Application"
-msgstr ""
+msgstr "Aplicación"
msgid "Application ID"
-msgstr ""
+msgstr "ID de la aplicación"
msgid "Application: %{name}"
-msgstr ""
+msgstr "Aplicación: %{name}"
msgid "Applications"
msgstr "Aplicaciones"
-msgid "Apr"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
msgstr ""
+msgid "Apr"
+msgstr "Abril"
+
msgid "April"
msgstr "Abril"
msgid "Archived project! Repository and other project resources are read-only"
-msgstr ""
+msgstr "¡Proyecto archivado!. El repositorio y el resto de recursos del proyecto son de sólo lectura"
msgid "Archived projects"
+msgstr "Proyectos archivados"
+
+msgid "Are you sure"
msgstr ""
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "¿Estás seguro que deseas eliminar esta programación del pipeline?"
msgid "Are you sure you want to erase this build?"
-msgstr ""
+msgstr "¿Estás seguro de que quieres borrar esta versión?"
msgid "Are you sure you want to lose unsaved changes?"
+msgstr "¿Estás seguro de que deseas descartar los cambios no guardados?"
+
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
-msgstr ""
+msgstr "¿Seguro que quiere regenerar la clave pública? Deberá actualizar la clave pública en el servidor remoto antes de que la duplicación funcione nuevamente."
msgid "Are you sure you want to remove %{group_name}?"
+msgstr "¿Está seguro que desea eliminar %{group_name}?"
+
+msgid "Are you sure you want to remove approver %{name}?"
msgstr ""
-msgid "Are you sure you want to remove this identity?"
+msgid "Are you sure you want to remove group %{name}?"
msgstr ""
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr "¿Está seguro de que desea eliminar esta identidad?"
+
msgid "Are you sure you want to reset registration token?"
msgstr "¿Está seguro que desea reinicializar el token de registro?"
@@ -812,31 +991,37 @@ msgid "Are you sure you want to reset the health check token?"
msgstr "¿Está seguro que desea reinicializar el token de Verificación de Estado?"
msgid "Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "¿Está seguro de que desea detener este entorno?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr "¿Está seguro que quieres desbloquear %{path_lock_path}?"
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
msgid "Are you sure?"
msgstr "¿Estás seguro?"
msgid "Artifact ID"
-msgstr ""
+msgstr "ID del artefacto"
msgid "Artifacts"
msgstr "Artefactos"
msgid "Ascending"
-msgstr ""
+msgstr "Ascendente"
msgid "Ask your group maintainer to set up a group Runner."
-msgstr ""
+msgstr "Pídale al administrador de su grupo que configure un grupo de ejecutores."
msgid "Assertion consumer service URL"
+msgstr "URL del servicio de aserción del consumidor"
+
+msgid "Assets"
msgstr ""
msgid "Assign custom color like #FF0000"
-msgstr ""
+msgstr "Asigne colores personalizados como #FF0000"
msgid "Assign labels"
msgstr "Asignar etiquetas"
@@ -844,38 +1029,44 @@ msgstr "Asignar etiquetas"
msgid "Assign milestone"
msgstr "Asignar milestone"
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr "Asignar a"
msgid "Assigned Issues"
-msgstr ""
+msgstr "Incidencias asignadas"
msgid "Assigned Merge Requests"
-msgstr ""
+msgstr "Merge requests asignados"
msgid "Assigned to :name"
-msgstr ""
+msgstr "Asignado a :name"
msgid "Assigned to me"
-msgstr ""
+msgstr "Asignado a mí"
msgid "Assignee"
msgstr "Asignado a"
msgid "Assignee lists not available with your current license"
-msgstr ""
+msgstr "Las listas de asignaciones no se encuentran disponibles con su licencia actual"
msgid "Assignee lists show all issues assigned to the selected user."
msgstr ""
msgid "Assignee(s)"
+msgstr "Asignado(s)"
+
+msgid "Attach a file"
msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Adjunte un archivo arrastrando &amp; soltando o %{upload_link}"
msgid "Audit Events"
-msgstr ""
+msgstr "Eventos de auditoría"
msgid "Aug"
msgstr "Ago"
@@ -883,62 +1074,59 @@ msgstr "Ago"
msgid "August"
msgstr "Agosto"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "Registro de Autenticación"
msgid "Authentication log"
-msgstr ""
+msgstr "Log de autenticación"
msgid "Authentication method"
-msgstr ""
+msgstr "Método de autenticación"
msgid "Author"
-msgstr ""
+msgstr "Autor"
msgid "Authorization code:"
+msgstr "Código de autorización:"
+
+msgid "Authorization key"
msgstr ""
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
msgid "Authorize"
-msgstr ""
+msgstr "Autorizar"
msgid "Authorize %{link_to_client} to use your account?"
-msgstr ""
+msgstr "¿Autorizar %{link_to_client} para utilizar su cuenta?"
msgid "Authorized At"
-msgstr ""
+msgstr "Autorizado en"
msgid "Authorized applications (%{size})"
-msgstr ""
+msgstr "Aplicaciones autorizadas (%{size})"
msgid "Authors: %{authors}"
msgstr "Autores: %{authors}"
msgid "Auto DevOps"
-msgstr ""
+msgstr "Auto DevOps"
msgid "Auto DevOps enabled"
-msgstr ""
+msgstr "Auto DevOps habilitado"
msgid "Auto DevOps, runners and job artifacts"
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "Tanto las Auto Review Apps como Auto Deploy necesitan un dominio para funcionar correctamente."
+msgstr "Auto DevOps, ejecutores y artefactos"
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
msgid "AutoDevOps|Auto DevOps"
-msgstr ""
+msgstr "Auto DevOps"
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Documentación de Auto DevOps"
@@ -959,121 +1147,133 @@ msgid "AutoDevOps|You can automatically build and test your application if you %
msgstr ""
msgid "AutoDevOps|add a Kubernetes cluster"
-msgstr ""
+msgstr "añadir un clúster de Kubernetes"
msgid "AutoDevOps|enable Auto DevOps"
-msgstr ""
+msgstr "habilitar Auto DevOps"
msgid "Automatically marked as default internal user"
+msgstr "Marcado automáticamente como usuario interno por defecto"
+
+msgid "Automatically resolved"
msgstr ""
msgid "Available"
msgstr "Disponible"
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
msgstr ""
-msgid "Avatar will be removed. Are you sure?"
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
msgstr ""
+msgid "Avatar for %{name}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr "El avatar será eliminado. ¿Está seguro?"
+
msgid "Average per day: %{average}"
msgstr "Promedio por día: %{average}"
msgid "Background Color"
-msgstr ""
+msgstr "Color de fondo"
msgid "Background Jobs"
-msgstr ""
+msgstr "Trabajos de fondo"
msgid "Background color"
-msgstr ""
+msgstr "Color de fondo"
msgid "Badges"
-msgstr ""
+msgstr "Insignias"
msgid "Badges|A new badge was added."
-msgstr ""
+msgstr "Se ha añadido una nueva insignia."
msgid "Badges|Add badge"
-msgstr ""
+msgstr "Añadir insignia"
msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "Se ha producido un error al agregar la insignia, por favor, compruebe las URLs introducidas e inténtelo de nuevo."
msgid "Badges|Badge image URL"
-msgstr ""
+msgstr "URL de imagen de la insignia"
msgid "Badges|Badge image preview"
-msgstr ""
+msgstr "Vista previa de la imagen de la insignia"
msgid "Badges|Delete badge"
-msgstr ""
+msgstr "Eliminar la insignia"
msgid "Badges|Delete badge?"
-msgstr ""
+msgstr "¿Desea eliminar la insignia?"
msgid "Badges|Deleting the badge failed, please try again."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la insignia. Inténtelo de nuevo."
msgid "Badges|Group Badge"
-msgstr ""
+msgstr "Insignia del grupo"
msgid "Badges|Link"
-msgstr ""
+msgstr "Enlace"
msgid "Badges|No badge image"
-msgstr ""
+msgstr "No hay imagen de insignia"
msgid "Badges|No image to preview"
-msgstr ""
+msgstr "No hay imagen para la vista previa"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "Por favor, introduzca una URL válida"
msgid "Badges|Project Badge"
-msgstr ""
+msgstr "Insignia del proyecto"
msgid "Badges|Reload badge image"
-msgstr ""
+msgstr "Recargar la imagen de la insignia"
msgid "Badges|Save changes"
-msgstr ""
+msgstr "Guardar los cambios"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "Se ha producido un error al guardar la insignia, por favor, compruebe las URLs introducidas e inténtelo de nuevo."
msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr ""
+msgstr "Las %{docsLinkStart}variables%{docsLinkEnd} que admite GitLab: %{placeholders}"
msgid "Badges|The badge was deleted."
-msgstr ""
+msgstr "Se ha eliminado la insignia."
msgid "Badges|The badge was saved."
-msgstr ""
+msgstr "Se ha guardado la insignia."
msgid "Badges|This group has no badges"
-msgstr ""
+msgstr "Este grupo no tiene insignias"
msgid "Badges|This project has no badges"
-msgstr ""
+msgstr "Este proyecto no tiene insignias"
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
msgstr ""
msgid "Badges|Your badges"
-msgstr ""
+msgstr "Sus insignias"
msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
+msgstr "por ejemplo, %{exampleUrl}"
msgid "BatchComments|Delete all pending comments"
-msgstr ""
+msgstr "Borrar todos los comentarios pendientes"
msgid "BatchComments|Discard review?"
-msgstr ""
+msgstr "¿Descartar revisión?"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
msgstr ""
@@ -1082,28 +1282,28 @@ msgid "Begin with the selected commit"
msgstr "Iniciar con el commit seleccionado"
msgid "Below are examples of regex for existing tools:"
-msgstr ""
+msgstr "A continuación se muestran ejemplos de expresiones regulares para las herramientas existentes:"
msgid "Below you will find all the groups that are public."
-msgstr ""
+msgstr "A continuación encontrará todos los grupos públicos."
msgid "Billing"
-msgstr ""
+msgstr "Facturación"
msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
-msgstr ""
+msgstr "%{group_name} está actualmente en el plan %{plan_link}."
msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
-msgstr ""
+msgstr "Actualizar o volver a un plan anterior de forma automática no está actualmente disponible para algunos de los planes."
msgid "BillingPlans|Current plan"
-msgstr ""
+msgstr "Plan actual"
msgid "BillingPlans|Customer Support"
-msgstr ""
+msgstr "Servicio al Cliente"
msgid "BillingPlans|Downgrade"
-msgstr ""
+msgstr "Planes de Facturación | Volver a un plan anterior"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
msgstr ""
@@ -1112,67 +1312,68 @@ msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
msgstr ""
msgid "BillingPlans|Manage plan"
-msgstr ""
+msgstr "Gestionar plan"
msgid "BillingPlans|Please contact %{customer_support_link} in that case."
msgstr ""
msgid "BillingPlans|See all %{plan_name} features"
-msgstr ""
+msgstr "Ver todas las novedades del %{plan_name}"
msgid "BillingPlans|This group uses the plan associated with its parent group."
-msgstr ""
+msgstr "Este grupo utiliza el mismo plan asociado que su grupo principal."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
-msgstr ""
+msgstr "Para administrar el plan de este grupo, por favor visite la sección de facturación de %{parent_billing_page_link}."
msgid "BillingPlans|Upgrade"
-msgstr ""
+msgstr "Actualizar plan"
msgid "BillingPlans|You are currently on the %{plan_link} plan."
-msgstr ""
+msgstr "Está actualmente en el plan %{plan_link}."
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
-msgstr ""
+msgstr "Su periodo de prueba de Gitlab.com expiró el %{expiration_date}. %{learn_more_text}"
msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
-msgstr ""
+msgstr "Su periodo de prueba de la versión de Gitlab Gold <strong> finalizará después de %{expiration_date} </strong>. Puede obtener más información acerca de Gitlab Gold leyendo nuestro %{features_link}."
msgid "BillingPlans|features"
-msgstr ""
+msgstr "características"
msgid "BillingPlans|frequently asked questions"
-msgstr ""
+msgstr "preguntas frecuentes"
msgid "BillingPlans|monthly"
-msgstr ""
+msgstr "mensual"
msgid "BillingPlans|paid annually at %{price_per_year}"
-msgstr ""
+msgstr "pagado anualmente a %{price_per_year}"
msgid "BillingPlans|per user"
-msgstr ""
+msgstr "por usuario"
msgid "Bitbucket Server Import"
msgstr ""
msgid "Bitbucket import"
+msgstr "Importar desde Bitbucket"
+
+msgid "Block"
msgstr ""
-msgid "Blog"
+msgid "Blocked"
msgstr ""
+msgid "Blog"
+msgstr "Blog"
+
msgid "Boards"
-msgstr ""
+msgstr "Tableros"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "La rama <strong>%{branch_name}</strong> fue creada. Para configurar el auto despliegue, escoge una plantilla Yaml para GitLab CI y envía tus cambios. %{link_to_autodeploy_doc}"
@@ -1195,10 +1396,10 @@ msgid "Branches"
msgstr "Ramas"
msgid "Branches|Active"
-msgstr ""
+msgstr "Activo"
msgid "Branches|Active branches"
-msgstr ""
+msgstr "Branches activos"
msgid "Branches|All"
msgstr ""
@@ -1249,7 +1450,7 @@ msgid "Branches|Only a project maintainer or owner can delete a protected branch
msgstr ""
msgid "Branches|Overview"
-msgstr ""
+msgstr "Resumen"
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -1273,7 +1474,7 @@ msgid "Branches|Show stale branches"
msgstr ""
msgid "Branches|Sort by"
-msgstr ""
+msgstr "Ordenar por"
msgid "Branches|Stale"
msgstr ""
@@ -1309,10 +1510,10 @@ msgid "Branches|merged"
msgstr ""
msgid "Branches|project settings"
-msgstr ""
+msgstr "configuración del proyecto"
msgid "Branches|protected"
-msgstr ""
+msgstr "protegido"
msgid "Browse Directory"
msgstr "Examinar directorio"
@@ -1326,47 +1527,62 @@ msgstr "Examinar archivos"
msgid "Browse files"
msgstr "Examinar archivos"
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
+msgstr "Métricas de negocio (personalizadas)"
+
+msgid "By %{user_name}"
msgstr ""
msgid "ByAuthor|by"
msgstr "por"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
+msgstr "Configuración de CI/CD"
+
+msgid "CI Lint"
msgstr ""
msgid "CI will run using the credentials assigned above."
msgstr ""
msgid "CI/CD"
-msgstr ""
+msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "Configuración de CI/CD"
msgid "CI/CD for external repo"
-msgstr ""
+msgstr "CI/CD para repositorio externo"
msgid "CI/CD settings"
-msgstr ""
+msgstr "Configuración de CI/CD"
msgid "CICD|Auto DevOps"
-msgstr ""
+msgstr "Auto DevOps"
msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
-msgstr ""
+msgstr "Auto DevOps construirá, probará e implementará automáticamente su aplicación en base a una configuración predefinida de integración y entrega continuas."
msgid "CICD|Automatic deployment to staging, manual deployment to production"
-msgstr ""
+msgstr "Despliegue automático en entornos previos, despliegue manual en producción"
msgid "CICD|Continuous deployment to production"
-msgstr ""
+msgstr "Despliegue continuo a producción"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
msgstr ""
@@ -1375,55 +1591,67 @@ msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
msgid "CICD|Deployment strategy"
-msgstr ""
-
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
+msgstr "Estrategia de despliegue"
msgid "CICD|Jobs"
-msgstr ""
+msgstr "Trabajos"
msgid "CICD|Learn more about Auto DevOps"
-msgstr ""
+msgstr "Aprenda más de Auto DevOps"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
+msgstr "Instancia habilitada"
+
+msgid "CONTRIBUTING"
msgstr ""
msgid "Callback URL"
+msgstr "URL de callback"
+
+msgid "Can override approvers and approvals required per merge request"
msgstr ""
msgid "Can't find HEAD commit for this branch"
+msgstr "No se puede encontrar el commit HEAD para este 'branch'"
+
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
msgid "Cancel"
msgstr "Cancelar"
msgid "Cancel this job"
-msgstr ""
+msgstr "Cancelar este trabajo"
msgid "Cannot be merged automatically"
msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
+msgstr "No se puede modificar el clúster de Kubernetes gestionado"
+
+msgid "Certificate"
msgstr ""
-msgid "Certificate fingerprint"
+msgid "Certificate (PEM)"
msgstr ""
+msgid "Certificate fingerprint"
+msgstr "Huella digital del certificado"
+
msgid "Change Weight"
+msgstr "Cambiar peso"
+
+msgid "Change permissions"
msgstr ""
msgid "Change template"
-msgstr ""
+msgstr "Cambiar plantilla"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
@@ -1443,24 +1671,30 @@ msgstr "Revertir"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
msgstr "Gráficos"
msgid "Chat"
-msgstr ""
+msgstr "Chat"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr "Comprobando disponibilidad de %{text}..."
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "Verificando disponibilidad de la rama..."
@@ -1477,19 +1711,25 @@ msgid "Choose <strong>Next</strong> at the bottom of the page."
msgstr ""
msgid "Choose File ..."
-msgstr ""
+msgstr "Elegir archivo ..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr "Elija un branch/tag (por ejemplo, %{master}) o introduzca un commit (por ejemplo, %{sha}) para ver lo qué ha cambiado o para crear un merge request."
+
+msgid "Choose a file"
msgstr ""
-msgid "Choose a template..."
+msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template..."
+msgstr "Elegir una plantilla..."
+
msgid "Choose a type..."
-msgstr ""
+msgstr "Elegir un tipo..."
msgid "Choose any color."
-msgstr ""
+msgstr "Elegir cualquier color."
msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr "Elegir archivo..."
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1507,7 +1750,7 @@ msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr ""
msgid "Choose which repositories you want to import."
-msgstr ""
+msgstr "Seleccione que repositorios desea importar."
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
@@ -1519,7 +1762,7 @@ msgid "CiStatusLabel|created"
msgstr "creado"
msgid "CiStatusLabel|delayed"
-msgstr ""
+msgstr "retrasado"
msgid "CiStatusLabel|failed"
msgstr "fallido"
@@ -1555,7 +1798,7 @@ msgid "CiStatusText|created"
msgstr "creado"
msgid "CiStatusText|delayed"
-msgstr ""
+msgstr "retrasado"
msgid "CiStatusText|failed"
msgstr "fallado"
@@ -1585,40 +1828,46 @@ msgid "CiVariables|Remove variable row"
msgstr ""
msgid "CiVariable|* (All environments)"
-msgstr ""
+msgstr "* (Todos los entornos)"
msgid "CiVariable|All environments"
-msgstr ""
+msgstr "Todos los entornos"
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
msgstr ""
msgid "CiVariable|Protected"
-msgstr ""
+msgstr "Protegido"
msgid "CiVariable|Search environments"
-msgstr ""
+msgstr "Buscar entornos"
msgid "CiVariable|Toggle protected"
msgstr ""
msgid "CiVariable|Validation failed"
-msgstr ""
+msgstr "Error de validación"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr "no está disponible: %{reason}"
+
+msgid "Clear"
msgstr ""
-msgid "Clear search"
+msgid "Clear input"
msgstr ""
+msgid "Clear search"
+msgstr "Limpiar búsqueda"
+
msgid "Clear search input"
-msgstr ""
+msgstr "Limpiar el historial de búsqueda"
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
@@ -1636,36 +1885,60 @@ msgid "Click the button below to begin the install process by navigating to the
msgstr ""
msgid "Click to expand it."
-msgstr ""
+msgstr "Haga clic para expandir."
msgid "Click to expand text"
msgstr "Haga clic para expandir el texto"
msgid "Client authentication certificate"
-msgstr ""
+msgstr "Certificado de autenticación del cliente"
msgid "Client authentication key"
-msgstr ""
+msgstr "Clave de autenticación del cliente"
msgid "Client authentication key password"
-msgstr ""
+msgstr "Contraseña de clave de autenticación del cliente"
msgid "Clients"
+msgstr "Clientes"
+
+msgid "Clone"
msgstr ""
msgid "Clone repository"
+msgstr "Clonar repositorio"
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
msgstr ""
msgid "Close"
msgstr "Cerrar"
msgid "Close epic"
+msgstr "Cerrar épica"
+
+msgid "Close milestone"
msgstr ""
msgid "Closed"
+msgstr "Cerrado"
+
+msgid "Closed (moved)"
msgstr ""
msgid "Closed issues"
+msgstr "Incidencias cerradas"
+
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
@@ -1674,17 +1947,17 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
-msgstr ""
+msgstr "API URL"
msgid "ClusterIntegration|Add Kubernetes cluster"
-msgstr ""
+msgstr "Añadir cluster de Kubernetes"
msgid "ClusterIntegration|Add a Kubernetes cluster integration"
-msgstr ""
+msgstr "Añadir integración con cluster de 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 ""
@@ -1698,25 +1971,40 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
+msgstr "Certificado CA"
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
@@ -1728,45 +2016,60 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Copy API URL"
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
msgstr ""
+msgid "ClusterIntegration|Copy API URL"
+msgstr "Copiar la URL del API"
+
msgid "ClusterIntegration|Copy CA Certificate"
msgstr "Copiar Certificado CA"
msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
-msgstr ""
+msgstr "Copiar la dirección IP de entrada al portapapeles"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr "Copiar el nombre del host de Jupyter en el portapapeles"
+
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
msgstr ""
msgid "ClusterIntegration|Copy Kubernetes cluster name"
-msgstr ""
+msgstr "Copiar el nombre del clúster Kubernetes"
msgid "ClusterIntegration|Copy Token"
-msgstr "Copiar Token"
+msgstr "Copiar token"
msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "Crear cluster de Kubernetes"
msgid "ClusterIntegration|Did you know?"
-msgstr ""
+msgstr "¿Sabía usted?"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
-msgstr ""
+msgstr "Habilita o inhabilita la conexión de GitLab con su clúster Kubernetes."
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
-msgstr ""
+msgstr "Habilite esta configuración si utiliza el control de acceso basado en roles (RBAC)."
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
-msgstr ""
+msgstr "Introduzca los detalles de su clúster de Kubernetes"
msgid "ClusterIntegration|Environment scope"
-msgstr ""
+msgstr "Alcance del entorno"
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1786,7 +2089,7 @@ msgid "ClusterIntegration|GitLab Runner connects to this project's repository an
msgstr ""
msgid "ClusterIntegration|Google Cloud Platform project"
-msgstr ""
+msgstr "Proyecto de Google Cloud Platform"
msgid "ClusterIntegration|Google Kubernetes Engine"
msgstr "Google Kubernetes Engine"
@@ -1795,7 +2098,7 @@ msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Proyecto Google Kubernetes Engine"
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "ClusterIntegration|Grupo de clúster"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1804,7 +2107,7 @@ msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes ap
msgstr ""
msgid "ClusterIntegration|Hide"
-msgstr ""
+msgstr "Ocultar"
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -1813,10 +2116,10 @@ msgid "ClusterIntegration|In order to show the health of the cluster, we'll need
msgstr ""
msgid "ClusterIntegration|Ingress"
-msgstr ""
+msgstr "Entrada"
msgid "ClusterIntegration|Ingress IP Address"
-msgstr ""
+msgstr "Dirección IP de entrada"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
@@ -1839,21 +2142,33 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr "Estado de integración"
-msgid "ClusterIntegration|Jupyter Hostname"
+msgid "ClusterIntegration|Issuer Email"
msgstr ""
-msgid "ClusterIntegration|JupyterHub"
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
msgstr ""
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr "Nombre del host Jupyter"
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr "JupyterHub"
+
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
msgid "ClusterIntegration|Knative"
-msgstr ""
+msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "cluster de Kubernetes"
@@ -1873,28 +2188,31 @@ msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
+msgstr "ClusterIntegration | Los clústeres de Kubernetes le permiten utilizar aplicaciones de revisión, desplegar sus aplicaciones, ejecutar sus pipelines y mucho más de una manera sencilla."
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
-msgstr ""
+msgstr "Aprenda más sobre los tipos de %{help_link_start_machine_type}instancias %{help_link_end} y sus %{help_link_start_pricing}precios%{help_link_end}."
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
-msgstr ""
+msgstr "Conozca más sobre las %{help_link_start}zonas%{help_link_end}."
msgid "ClusterIntegration|Learn more about Kubernetes"
-msgstr ""
+msgstr "Más información sobre Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr "Más información sobre los grupos de clústeres de Kubernetes"
+
+msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
msgid "ClusterIntegration|Machine type"
msgstr "Tipo de máquina"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
-msgstr ""
+msgstr "Asegúrese de que su cuenta %{link_to_requirements} cumple con los requisitos para crear clusters de Kubernetes"
msgid "ClusterIntegration|Manage"
msgstr "Administrar"
@@ -1903,19 +2221,19 @@ msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}
msgstr "Administre su cluster de Kubernetes visitando %{link_gke}"
msgid "ClusterIntegration|More information"
-msgstr ""
+msgstr "Más información"
msgid "ClusterIntegration|No machine types matched your search"
-msgstr ""
+msgstr "No hay tipos de máquinas que coincidan con su búsqueda"
msgid "ClusterIntegration|No projects found"
-msgstr ""
+msgstr "No se encontraron proyectos"
msgid "ClusterIntegration|No projects matched your search"
-msgstr ""
+msgstr "No hay proyectos que coincidan con su búsqueda"
msgid "ClusterIntegration|No zones matched your search"
-msgstr ""
+msgstr "No hay zonas que coincidan con su búsqueda"
msgid "ClusterIntegration|Note:"
msgstr "Nota:"
@@ -1924,7 +2242,7 @@ msgid "ClusterIntegration|Number of nodes"
msgstr "Número de nodos"
msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr ""
+msgstr "Por favor, introduzca la información de acceso a su clúster de Kubernetes. Si necesita ayuda, puede leer nuestra %{link_to_help_page} en Kubernetes"
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Asegúrese de que su cuenta de Google cumpla con los siguientes requisitos:"
@@ -1933,22 +2251,22 @@ msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in o
msgstr ""
msgid "ClusterIntegration|Project cluster"
-msgstr ""
+msgstr "Clúster del proyecto"
msgid "ClusterIntegration|Project namespace"
-msgstr ""
+msgstr "Espacio de nombres del proyecto"
msgid "ClusterIntegration|Project namespace (optional, unique)"
-msgstr ""
+msgstr "Espacio de nombres del proyecto (opcional, único)"
msgid "ClusterIntegration|Prometheus"
-msgstr ""
+msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
-msgstr ""
+msgstr "Prometheus es un sistema de monitorización de código abierto con %{gitlabIntegrationLink} para monitorizar las aplicaciones desplegadas."
msgid "ClusterIntegration|RBAC-enabled cluster"
-msgstr ""
+msgstr "Cluster RBAC habilitado"
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1968,41 +2286,44 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Falló la solicitud para iniciar la instalación"
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr "Guardar cambios"
msgid "ClusterIntegration|Search machine types"
-msgstr ""
+msgstr "Buscar tipos de máquina"
msgid "ClusterIntegration|Search projects"
-msgstr ""
+msgstr "Buscar proyectos"
msgid "ClusterIntegration|Search zones"
-msgstr ""
+msgstr "Buscar zonas"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|Select machine type"
-msgstr ""
+msgstr "Seleccione el tipo de máquina"
msgid "ClusterIntegration|Select project"
-msgstr ""
+msgstr "Seleccione el proyecto"
msgid "ClusterIntegration|Select project and zone to choose machine type"
-msgstr ""
+msgstr "Seleccione el proyecto y la zona para elegir el tipo de máquina"
msgid "ClusterIntegration|Select project to choose zone"
-msgstr ""
+msgstr "Seleccione un proyecto para elegir la zona"
msgid "ClusterIntegration|Select zone"
-msgstr ""
+msgstr "Seleccione la zona"
msgid "ClusterIntegration|Select zone to choose machine type"
-msgstr ""
+msgstr "Seleccione la zona para elegir el tipo de máquina"
msgid "ClusterIntegration|Service token"
-msgstr ""
+msgstr "Token de servicio"
msgid "ClusterIntegration|Show"
msgstr "Mostrar"
@@ -2010,15 +2331,21 @@ msgstr "Mostrar"
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Algo salió mal de nuestro lado."
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Algo salió mal durante la instalación de %{title}"
-msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr "La dirección IP está en proceso de ser asignada. Por favor, verifique su clúster de Kubernetes o las cuotas en Google Kubernetes Engine si este proceso lleva mucho tiempo"
+
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
@@ -2031,9 +2358,21 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr "Token"
-msgid "ClusterIntegration|Validating project billing status"
+msgid "ClusterIntegration|Upgrade"
msgstr ""
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr "Validación del estado de facturación del proyecto"
+
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
@@ -2041,6 +2380,9 @@ msgid "ClusterIntegration|With a Kubernetes cluster associated to this project,
msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr "Primero debe instalar Helm Tiller antes de instalar las aplicaciones que se muestran a continuación"
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
@@ -2053,7 +2395,7 @@ msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "acceso a Google Kubernetes Engine"
msgid "ClusterIntegration|check the pricing here"
-msgstr ""
+msgstr "consulte los precios aqui"
msgid "ClusterIntegration|documentation"
msgstr "documentación"
@@ -2065,13 +2407,16 @@ msgid "ClusterIntegration|meets the requirements"
msgstr "cumple con los requisitos"
msgid "ClusterIntegration|properly configured"
-msgstr ""
+msgstr "configurado correctamente"
msgid "ClusterIntegration|sign up"
+msgstr "regístrese"
+
+msgid "Code"
msgstr ""
msgid "Code owners"
-msgstr ""
+msgstr "Propietarios del código"
msgid "Cohorts"
msgstr ""
@@ -2080,16 +2425,25 @@ msgid "Collapse"
msgstr "Contraer"
msgid "Collapse sidebar"
+msgstr "Contraer la barra lateral"
+
+msgid "Command line instructions"
msgstr ""
msgid "Comment"
+msgstr "Comentar"
+
+msgid "Comment & close %{noteable_name}"
msgstr ""
-msgid "Comment & resolve discussion"
+msgid "Comment & reopen %{noteable_name}"
msgstr ""
+msgid "Comment & resolve discussion"
+msgstr "Comentar y resolver la discusión"
+
msgid "Comment & unresolve discussion"
-msgstr ""
+msgstr "Comentar y dejar la discusión sin resolver"
msgid "Comment form position"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] "Cambio"
msgstr[1] "Cambios"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "Mensaje del commit"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "Duración de los cambios en minutos para los últimos 30"
@@ -2144,13 +2499,13 @@ msgid "Commits per day of month"
msgstr ""
msgid "Commits per weekday"
-msgstr ""
+msgstr "Commits por dia de la semana"
msgid "Commits|An error occurred while fetching merge requests data."
-msgstr ""
+msgstr "Se ha producido un error al obtener los datos de los merge requests."
msgid "Commits|Commit: %{commitText}"
-msgstr ""
+msgstr "Commit: %{commitText}"
msgid "Commits|History"
msgstr "Historial"
@@ -2162,50 +2517,59 @@ msgid "Committed by"
msgstr "Enviado por"
msgid "Commit…"
-msgstr ""
+msgstr "Commit..."
msgid "Compare"
msgstr "Comparar"
msgid "Compare Git revisions"
-msgstr ""
+msgstr "Comparar revisiones de Git"
msgid "Compare Revisions"
+msgstr "Comparar revisiones"
+
+msgid "Compare changes"
msgstr ""
msgid "Compare changes with the last commit"
-msgstr ""
+msgstr "Comparar los cambios con el último commit"
msgid "Compare changes with the merge request target branch"
msgstr ""
msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
-msgstr ""
+msgstr "Los 'branches' %{source_branch} y %{target_branch} son iguales."
msgid "CompareBranches|Compare"
-msgstr ""
+msgstr "Comparar"
msgid "CompareBranches|Source"
-msgstr ""
+msgstr "Origen"
msgid "CompareBranches|Target"
-msgstr ""
+msgstr "Destino"
msgid "CompareBranches|There isn't anything to compare."
-msgstr ""
+msgstr "No hay nada que comparar."
msgid "Confidential"
-msgstr ""
+msgstr "Confidencial"
msgid "Confidentiality"
msgstr "Confidencialidad"
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2222,25 +2586,28 @@ msgid "Configure the %{link} integration."
msgstr ""
msgid "Configure the way a user creates a new account."
-msgstr ""
+msgstr "Configure la forma en la que un usuario crea una cuenta nueva."
msgid "Connect"
-msgstr ""
+msgstr "Conectar"
msgid "Connect all repositories"
-msgstr ""
+msgstr "Conectar todos los repositorios"
msgid "Connect repositories from GitHub"
-msgstr ""
+msgstr "Conectar los repositorios desde 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 "Conecte sus repositorios externos, y los pipelines de CI/CD se ejecutarán para los nuevos commits. Se creará un proyecto de Gitlab sólo con las caracteristicas de CI/CD habilitadas."
msgid "Connecting..."
+msgstr "Conectando..."
+
+msgid "Contact sales to upgrade"
msgstr ""
msgid "Container Registry"
-msgstr ""
+msgstr "Registro de contenedores"
msgid "ContainerRegistry|Created"
msgstr "Creado"
@@ -2287,11 +2654,14 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
-msgid "Continue"
+msgid "Contents of .gitlab-ci.yml"
msgstr ""
+msgid "Continue"
+msgstr "Continuar"
+
msgid "Continue to the next step"
-msgstr ""
+msgstr "Continuar con el siguiente paso"
msgid "Continuous Integration and Deployment"
msgstr ""
@@ -2300,34 +2670,34 @@ msgid "Contribute to GitLab"
msgstr ""
msgid "Contribution"
-msgstr ""
+msgstr "Contribución"
-msgid "Contribution guide"
-msgstr "Guía de contribución"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
-msgstr ""
+msgstr "Contribuciones para <strong>%{calendar_date}</strong>"
msgid "Contributions per group member"
-msgstr ""
+msgstr "Contribuciones por cada miembro de un grupo"
msgid "Contributors"
msgstr "Contribuidores"
msgid "ContributorsPage|%{startDate} – %{endDate}"
-msgstr ""
+msgstr "%{startDate} – %{endDate}"
msgid "ContributorsPage|Building repository graph."
-msgstr ""
+msgstr "Generando los gráficos del repositorio."
msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
-msgstr ""
+msgstr "Commits a %{branch_name}, excluyendo merge commits. Limitado a 6,000 commits."
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
-msgstr ""
+msgstr "Espere un momento; esta página se actualizará automáticamente cuando esté lista."
msgid "Control the display of third party offers."
-msgstr ""
+msgstr "Controlar la visualización de las ofertas de terceros."
msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
msgstr ""
@@ -2338,59 +2708,62 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
-msgid "ConvDev Index"
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "ConvDev Index"
+msgstr "Ãndice ConvDev"
+
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
-msgstr ""
+msgstr "Copiar el ID a portapapeles"
msgid "Copy SSH clone URL"
msgstr ""
-msgid "Copy SSH public key to clipboard"
+msgid "Copy SSH public key"
msgstr ""
+msgid "Copy SSH public key to clipboard"
+msgstr "Copiar la clave pública SSH al portapapeles"
+
msgid "Copy URL to clipboard"
msgstr "Copiar URL al portapapeles"
msgid "Copy branch name to clipboard"
-msgstr ""
+msgstr "Copiar el nombre del branch al portapapeles"
msgid "Copy command to clipboard"
-msgstr ""
+msgstr "Copiar el comando al portapapeles"
msgid "Copy commit SHA to clipboard"
msgstr "Copiar SHA del cambio al portapapeles"
msgid "Copy file path to clipboard"
-msgstr ""
+msgstr "Copie la ruta del archivo al portapapeles"
msgid "Copy incoming email address to clipboard"
-msgstr ""
+msgstr "Copiar la dirección de corro electrónico al portapapeles"
msgid "Copy link"
-msgstr ""
-
-msgid "Copy name to clipboard"
-msgstr ""
+msgstr "Copiar enlace"
msgid "Copy reference to clipboard"
-msgstr ""
+msgstr "Copiar la referencia al portapapeles"
msgid "Copy secret to clipboard"
-msgstr ""
+msgstr "Copia secreto al portapapeles"
msgid "Copy to clipboard"
-msgstr ""
+msgstr "Copiar al portapapeles"
msgid "Copy token to clipboard"
-msgstr ""
+msgstr "Copiar token al portapapeles"
msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
msgstr ""
@@ -2401,13 +2774,19 @@ msgstr "Crear"
msgid "Create New Directory"
msgstr "Crear Nuevo Directorio"
-msgid "Create a new branch"
+msgid "Create New Domain"
msgstr ""
+msgid "Create a new branch"
+msgstr "Crear un nuevo 'branch'"
+
msgid "Create a new branch and merge request"
-msgstr ""
+msgstr "Crear un nuevo 'branch' y 'merge request'"
msgid "Create a new issue"
+msgstr "Crear una nueva incidencia"
+
+msgid "Create a new repository"
msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
@@ -2417,28 +2796,28 @@ msgid "Create branch"
msgstr ""
msgid "Create commit"
-msgstr ""
+msgstr "Crear commit"
msgid "Create directory"
msgstr "Crear directorio"
msgid "Create empty repository"
-msgstr ""
+msgstr "Crear un repositorio vacío"
msgid "Create epic"
-msgstr ""
+msgstr "Crear épica"
msgid "Create file"
msgstr "Crear archivo"
msgid "Create group"
-msgstr ""
+msgstr "Crear grupo"
msgid "Create group label"
-msgstr ""
+msgstr "Crear etiqueta de grupo"
msgid "Create issue"
-msgstr ""
+msgstr "Crear incidencia"
msgid "Create lists from labels. Issues with that label appear in that list."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr "Crear solicitud de fusión"
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "Crear una nueva rama"
@@ -2468,7 +2850,7 @@ msgid "Create new..."
msgstr "Crear nuevo..."
msgid "Create project label"
-msgstr ""
+msgstr "Crear etiqueta de proyecto"
msgid "Create your first page"
msgstr ""
@@ -2480,22 +2862,22 @@ msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "crear un token de acceso personal"
msgid "Created"
-msgstr ""
+msgstr "Creado"
msgid "Created At"
-msgstr ""
+msgstr "Creado en"
msgid "Created by me"
-msgstr ""
+msgstr "Creado por mí"
msgid "Created on"
-msgstr ""
+msgstr "Creado en"
msgid "Created on:"
-msgstr ""
+msgstr "Creado sobre:"
msgid "Creating epic"
-msgstr ""
+msgstr "Creando épica"
msgid "Cron Timezone"
msgstr "Zona horaria del Cron"
@@ -2507,7 +2889,7 @@ msgid "Current Branch"
msgstr ""
msgid "Current node"
-msgstr ""
+msgstr "Nodo actual"
msgid "CurrentUser|Profile"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,15 +2912,24 @@ msgstr "Los niveles de notificación personalizados son los mismos que los nivel
msgid "Custom project templates"
msgstr ""
-msgid "Customize colors"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
msgstr ""
+msgid "Customize colors"
+msgstr "Personalizar colores"
+
msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,20 +2960,26 @@ msgstr "Puesta en escena"
msgid "CycleAnalyticsStage|Test"
msgstr "Pruebas"
-msgid "Dashboard"
+msgid "DNS"
msgstr ""
+msgid "Dashboard"
+msgstr "Panel de control"
+
msgid "DashboardProjects|All"
msgstr "Todos"
msgid "DashboardProjects|Personal"
msgstr "Personales"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
msgid "Debug"
-msgstr ""
+msgstr "Depurar"
msgid "Dec"
msgstr "Dic"
@@ -2593,15 +2987,24 @@ msgstr "Dic"
msgid "December"
msgstr "Diciembre"
-msgid "Decline and sign out"
+msgid "Decline"
msgstr ""
+msgid "Decline and sign out"
+msgstr "Rechazar y cerrar sesión"
+
msgid "Default Branch"
msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Definir un patrón personalizado con la sintaxis de cron"
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2630,22 +3036,28 @@ msgid "Delete"
msgstr "Eliminar"
msgid "Delete Package"
-msgstr ""
+msgstr "Eliminar paquete"
msgid "Delete Snippet"
-msgstr ""
+msgstr "Eliminar fragmento de código"
msgid "Delete comment"
-msgstr ""
+msgstr "Eliminar comentario"
msgid "Delete list"
+msgstr "Eliminar lista"
+
+msgid "Delete source branch"
msgstr ""
-msgid "Deleted"
+msgid "Delete this attachment"
msgstr ""
+msgid "Deleted"
+msgstr "Eliminado"
+
msgid "Deny"
-msgstr ""
+msgstr "Denegar"
msgid "Deploy"
msgid_plural "Deploys"
@@ -2653,52 +3065,52 @@ msgstr[0] "Despliegue"
msgstr[1] "Despliegues"
msgid "Deploy Keys"
-msgstr ""
+msgstr "Claves de despliegue"
msgid "DeployKeys|+%{count} others"
-msgstr ""
+msgstr "+%{count} otros"
msgid "DeployKeys|Current project"
-msgstr ""
+msgstr "Proyecto actual"
msgid "DeployKeys|Deploy key"
-msgstr ""
+msgstr "Clave de despliegue"
msgid "DeployKeys|Enabled deploy keys"
-msgstr ""
+msgstr "Claves de despliegue habilitadas"
msgid "DeployKeys|Error enabling deploy key"
-msgstr ""
+msgstr "Se ha producido un error al habilitar las claves de despliegue"
msgid "DeployKeys|Error getting deploy keys"
-msgstr ""
+msgstr "Se ha producido un error al obtener las claves de despliegue"
msgid "DeployKeys|Error removing deploy key"
-msgstr ""
+msgstr "Se ha producido un error al eliminar las claves de despliegue"
msgid "DeployKeys|Expand %{count} other projects"
-msgstr ""
+msgstr "Ampliar %{count} a otros proyectos"
msgid "DeployKeys|Loading deploy keys"
-msgstr ""
+msgstr "Cargando claves de despliegue"
msgid "DeployKeys|No deploy keys found. Create one with the form above."
-msgstr ""
+msgstr "No se han encontrado claves de despliegue. Puede crear unas utilizando el formulario de arriba."
msgid "DeployKeys|Privately accessible deploy keys"
-msgstr ""
+msgstr "Claves de despliegue accesibles de modo privado"
msgid "DeployKeys|Project usage"
-msgstr ""
+msgstr "Uso del proyecto"
msgid "DeployKeys|Publicly accessible deploy keys"
-msgstr ""
+msgstr "Claves de despliegue accesibles de modo públco"
msgid "DeployKeys|Read access only"
-msgstr ""
+msgstr "Acceso de sólo lectura"
msgid "DeployKeys|Write access allowed"
-msgstr ""
+msgstr "Acceso de escritura permitido"
msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
msgstr ""
@@ -2722,28 +3134,28 @@ msgid "DeployTokens|Copy username to clipboard"
msgstr ""
msgid "DeployTokens|Create deploy token"
-msgstr ""
+msgstr "Crear un token de despliegue"
msgid "DeployTokens|Created"
-msgstr ""
+msgstr "Creado"
msgid "DeployTokens|Deploy Tokens"
-msgstr ""
+msgstr "Tokens de despliegue"
msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
-msgstr ""
+msgstr "Los tokens de despliegue le permiten el acceso en modo de solo lectura a su repositorio y a al registro de imágenes."
msgid "DeployTokens|Expires"
-msgstr ""
+msgstr "Expira"
msgid "DeployTokens|Name"
-msgstr ""
+msgstr "Nombre"
msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
msgstr ""
msgid "DeployTokens|Revoke"
-msgstr ""
+msgstr "Revocar"
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr "Detalles"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2818,7 +3236,7 @@ msgid "Diffs|Something went wrong while fetching diff lines."
msgstr ""
msgid "Direction"
-msgstr ""
+msgstr "Dirección"
msgid "Directory name"
msgstr "Nombre del directorio"
@@ -2827,11 +3245,17 @@ msgid "Disable"
msgstr "Deshabilitar"
msgid "Disable for this project"
-msgstr ""
+msgstr "Deshabilitar para este proyecto"
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,13 +3277,22 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
+msgstr "Descartar"
+
+msgid "Dismiss ConvDev introduction"
msgstr ""
msgid "Dismiss Cycle Analytics introduction box"
@@ -2878,17 +3311,23 @@ msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
-msgstr ""
+msgstr "Dominio"
msgid "Don't show again"
msgstr "No mostrar de nuevo"
msgid "Done"
-msgstr ""
+msgstr "Hecho"
msgid "Download"
msgstr "Descargar"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "Descargar tar"
@@ -2913,11 +3352,14 @@ msgstr "Diferencias en texto plano"
msgid "DownloadSource|Download"
msgstr "Descargar"
-msgid "Downvotes"
+msgid "Downstream"
msgstr ""
+msgid "Downvotes"
+msgstr "Voto negativo"
+
msgid "Due date"
-msgstr ""
+msgstr "Fecha de vencimiento"
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -2928,71 +3370,92 @@ msgstr ""
msgid "Edit"
msgstr "Editar"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
+msgstr "Editar etiqueta"
+
+msgid "Edit Milestone"
msgstr ""
msgid "Edit Pipeline Schedule %{id}"
msgstr "Editar Programación del Pipeline %{id}"
msgid "Edit Snippet"
-msgstr ""
+msgstr "Editar fragmento de código"
msgid "Edit application"
+msgstr "Editar aplicación"
+
+msgid "Edit comment"
msgstr ""
-msgid "Edit files in the editor and commit changes here"
+msgid "Edit environment"
msgstr ""
+msgid "Edit files in the editor and commit changes here"
+msgstr "Editar los archivos en el editor y confirmar los cambios aquí"
+
msgid "Edit group: %{group_name}"
-msgstr ""
+msgstr "Editar grupo: %{group_name}"
msgid "Edit identity for %{user_name}"
+msgstr "Editar la identidad para %{user_name}"
+
+msgid "Edit issues"
msgstr ""
msgid "Elasticsearch"
-msgstr ""
+msgstr "Elasticsearch"
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
+msgstr "Integración de Elastisearch. Elasticsearch AWS IAM."
msgid "Email"
-msgstr ""
+msgstr "Correo electrónico"
msgid "Email patch"
-msgstr ""
+msgstr "Enviar parche por correo electrónico"
msgid "Emails"
-msgstr ""
+msgstr "Correos electrónicos"
msgid "Embed"
+msgstr "Incrustado"
+
+msgid "Empty file"
msgstr ""
msgid "Enable"
msgstr "Habilitar"
msgid "Enable Auto DevOps"
-msgstr ""
+msgstr "Activar Auto DevOps"
msgid "Enable Pseudonymizer data collection"
-msgstr ""
+msgstr "Habilitar la recolección de datos Pseudonymizer"
msgid "Enable SAML authentication for this group"
-msgstr ""
+msgstr "Habilitar autenticación SAML para este grupo"
msgid "Enable Sentry for error reporting and logging."
-msgstr ""
+msgstr "Habilite Sentry para el obtener el informe de errores y el registro."
msgid "Enable and configure InfluxDB metrics."
-msgstr ""
+msgstr "Habilitar y configurar las métricas de InfluxDB."
msgid "Enable and configure Prometheus metrics."
-msgstr ""
+msgstr "Habilitar y configurar las métricas de Prometheus."
msgid "Enable classification control using an external service"
+msgstr "Habilitar control de clasificación utilizando un servicio externo"
+
+msgid "Enable error tracking"
msgstr ""
msgid "Enable for this project"
-msgstr ""
+msgstr "Habilitar para este proyecto"
msgid "Enable group Runners"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3016,9 +3488,15 @@ msgid "Enable usage ping to get an overview of how you are using GitLab from a f
msgstr ""
msgid "Enabled"
-msgstr ""
+msgstr "Habilitado"
msgid "Ends at (UTC)"
+msgstr "Finaliza a las (UTC)"
+
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
@@ -3036,14 +3514,32 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
+msgstr "Entornos"
+
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
msgid "Environments|An error occurred while fetching the environments."
-msgstr ""
+msgstr "Se ha producido un error al recuperar los entornos."
msgid "Environments|An error occurred while making the request."
-msgstr ""
+msgstr "Se ha producido un error al realizar la solicitud."
msgid "Environments|An error occurred while stopping the environment, please try again"
msgstr ""
@@ -3052,7 +3548,7 @@ msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
msgid "Environments|Commit"
-msgstr ""
+msgstr "Commit"
msgid "Environments|Deploy to..."
msgstr ""
@@ -3061,10 +3557,10 @@ msgid "Environments|Deployment"
msgstr ""
msgid "Environments|Environment"
-msgstr ""
+msgstr "Entorno"
msgid "Environments|Environments"
-msgstr ""
+msgstr "Entornos"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
msgstr ""
@@ -3076,7 +3572,7 @@ msgid "Environments|Learn more about stopping environments"
msgstr ""
msgid "Environments|New environment"
-msgstr ""
+msgstr "Nuevo entorno"
msgid "Environments|No deployments yet"
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Actualizado"
@@ -3124,21 +3623,18 @@ msgid "Environments|protected"
msgstr ""
msgid "Epic"
-msgstr ""
-
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
+msgstr "Épica"
msgid "Epics"
-msgstr ""
+msgstr "Épicas"
msgid "Epics Roadmap"
-msgstr ""
+msgstr "Hoja de ruta de tareas épicas"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
-msgstr ""
+msgstr "Las tareas épicas le permiten administrar sus proyectos de manera más eficiente y con menos esfuerzo"
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3160,28 +3656,34 @@ msgid "Epics|start"
msgstr ""
msgid "Error"
-msgstr ""
+msgstr "Error"
msgid "Error Reporting and Logging"
+msgstr "Informe y registro de errores"
+
+msgid "Error Tracking"
msgstr ""
msgid "Error creating epic"
+msgstr "Error al crear la tarea épica"
+
+msgid "Error deleting %{issuableType}"
msgstr ""
msgid "Error fetching contributors data."
-msgstr ""
+msgstr "Se ha producido un error al obtener los datos de los colaboradores."
msgid "Error fetching labels."
-msgstr ""
+msgstr "Se ha producido un error en la recuperación de las etiquetas."
msgid "Error fetching network graph."
-msgstr ""
+msgstr "Se ha producido un error al obtener el gráfico de la red."
msgid "Error fetching refs"
-msgstr ""
+msgstr "Se ha producido un error al obtener los refs"
msgid "Error fetching usage ping data."
-msgstr ""
+msgstr "Se ha producido un error al obtener los datos de uso de ping."
msgid "Error loading branch data. Please try again."
msgstr ""
@@ -3208,11 +3710,17 @@ msgid "Error loading template."
msgstr ""
msgid "Error occurred when toggling the notification subscription"
-msgstr "Se produjo un error al activar/desactivar la suscripción de notificación"
+msgstr "Se ha producido un error al activar/desactivar la suscripción de las notificaciones"
+
+msgid "Error rendering markdown preview"
+msgstr ""
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,12 +3730,18 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
-msgid "Estimated"
+msgid "Error:"
msgstr ""
-msgid "EventFilterBy|Filter by all"
+msgid "Errors"
msgstr ""
+msgid "Estimated"
+msgstr "Estimado"
+
+msgid "EventFilterBy|Filter by all"
+msgstr "Filtrar por todos"
+
msgid "EventFilterBy|Filter by comments"
msgstr "Filtrar por comentarios"
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr "Filtrar por equipo"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Todos los días (a las 4:00 am)"
@@ -3252,26 +3772,62 @@ msgstr "Todos los meses (el día 1 a las 4:00 am)"
msgid "Every week (Sundays at 4:00am)"
msgstr "Todas las semanas (domingos a las 4:00 am)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
+msgstr "Todo el mundo puede colaborar"
+
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
msgstr ""
msgid "Expand"
msgstr "Expandir"
msgid "Expand all"
-msgstr ""
+msgstr "Expandir todo"
msgid "Expand sidebar"
-msgstr ""
+msgstr "Expandir barra lateral"
msgid "Expiration date"
+msgstr "Fecha de vencimiento"
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
msgstr ""
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
msgid "Explore"
-msgstr ""
+msgstr "Explorar"
msgid "Explore GitLab"
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr "Explorar proyectos"
msgid "Explore public groups"
msgstr "Explorar grupos públicos"
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3304,48 +3872,60 @@ msgid "ExternalAuthorizationService|Classification Label"
msgstr ""
msgid "ExternalAuthorizationService|Classification label"
-msgstr ""
+msgstr "Etiqueta de clasificación"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
-msgstr ""
+msgstr "Cuando no existe ninguna etiqueta de clasificación se utilizará la etiqueta predeterminada `%{default_label}'."
msgid "Facebook"
-msgstr ""
+msgstr "Facebook"
msgid "Failed"
-msgstr ""
+msgstr "Fallido"
msgid "Failed Jobs"
-msgstr ""
+msgstr "Trabajos fallidos"
msgid "Failed to change the owner"
msgstr "Error al cambiar el propietario"
msgid "Failed to check related branches."
-msgstr ""
+msgstr "Se ha producido un error al verificar las branchs relacionadas."
msgid "Failed to deploy to"
-msgstr ""
+msgstr "Se ha producido un error al desplegar a"
msgid "Failed to load emoji list."
+msgstr "Se ha producido un error al cargar la lista de emojis."
+
+msgid "Failed to load errors from Sentry"
msgstr ""
msgid "Failed to remove issue from board, please try again."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la incidencia del tablero, por favor, inténtelo de nuevo."
msgid "Failed to remove mirror."
-msgstr ""
+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 signing using smartcard authentication"
+msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr "Se ha producido un error al inciar sesión utilizando la autenticación mediante una tarjeta inteligente"
+
msgid "Failed to update issues, please try again."
+msgstr "Se ha producido un error al actualizar las incidencias. Por favor, inténtalo de nuevo."
+
+msgid "Failed to upload object map file"
msgstr ""
msgid "Failure"
+msgstr "Error"
+
+msgid "Fast-forward merge without a merge commit"
msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
@@ -3354,13 +3934,16 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,28 +3970,46 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
+msgstr "ID de instancia"
+
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
msgstr ""
msgid "FeatureFlags|More information"
@@ -3426,61 +4030,120 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
-msgid "Feb"
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Feb"
+msgstr "Feb"
+
msgid "February"
msgstr "Febrero"
msgid "Fields on this page are now uneditable, you can configure"
+msgstr "Ahora puede editar los campos en esta página, puede configurar"
+
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
msgstr ""
msgid "File templates"
msgstr ""
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "Archivos"
-msgid "Files (%{human_size})"
-msgstr ""
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
msgid "Filter"
-msgstr ""
+msgstr "Filtro"
msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
+msgstr "Filtrar por %{issuable_type} que actualmente estén cerrados."
msgid "Filter by %{issuable_type} that are currently opened."
-msgstr ""
+msgstr "Filtrar por %{issuable_type} que actualmente estén abiertos."
msgid "Filter by commit message"
msgstr "Filtrar por mensaje del cambio"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
+msgstr "Filtrar..."
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
msgstr ""
msgid "Find by path"
msgstr "Buscar por ruta"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "Buscar archivo"
msgid "Find the downloaded ZIP file and decompress it."
-msgstr ""
+msgstr "Busque el archivo ZIP descargado y descomprímalo."
msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
-msgstr ""
+msgstr "Busque el archivo extraído <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code>."
msgid "Fingerprints"
+msgstr "Huellas digitales"
+
+msgid "Finish editing this message first!"
msgstr ""
msgid "Finish review"
-msgstr ""
+msgstr "Finalizar revisión"
msgid "Finished"
+msgstr "Finalizado"
+
+msgid "First day of the week"
msgstr ""
msgid "FirstPushedBy|First"
@@ -3490,7 +4153,7 @@ msgid "FirstPushedBy|pushed by"
msgstr "enviado por"
msgid "Fixed date"
-msgstr ""
+msgstr "Fecha fija"
msgid "Fixed due date"
msgstr ""
@@ -3502,16 +4165,16 @@ msgid "Fixed:"
msgstr ""
msgid "FogBugz Email"
-msgstr ""
+msgstr "Correo electrónico de FogBugz"
msgid "FogBugz Import"
-msgstr ""
+msgstr "Importar desde FogBugz"
msgid "FogBugz Password"
-msgstr ""
+msgstr "Contraseña de Fogbugz"
msgid "FogBugz URL"
-msgstr ""
+msgstr "URL de FogBugz"
msgid "FogBugz import"
msgstr ""
@@ -3520,14 +4183,17 @@ msgid "Follow the steps below to export your Google Code project data."
msgstr ""
msgid "Font Color"
-msgstr ""
+msgstr "Color de la fuente"
msgid "Footer message"
-msgstr ""
+msgstr "Mensaje a pie de página"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,32 +4218,35 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "Formato"
msgid "Found errors in your .gitlab-ci.yml:"
-msgstr ""
+msgstr "Se han encontrado errores en su fichero .gitlab-ci.yml:"
msgid "Free Trial of GitLab.com Gold"
msgstr ""
msgid "From %{provider_title}"
-msgstr ""
+msgstr "De %{provider_title}"
msgid "From Bitbucket"
-msgstr ""
+msgstr "Desde Bitbucket"
msgid "From Bitbucket Server"
-msgstr ""
+msgstr "Desde un servidor Bitbucket"
msgid "From FogBugz"
-msgstr ""
+msgstr "Desde FogBugz"
msgid "From GitLab.com"
-msgstr ""
+msgstr "Desde GitLab.com"
msgid "From Google Code"
-msgstr ""
+msgstr "Desde Google Code"
msgid "From issue creation until deploy to production"
msgstr "Desde la creación de la incidencia hasta el despliegue a producción"
@@ -3586,25 +4255,28 @@ msgid "From merge request merge until deploy to production"
msgstr "Desde la integración de la solicitud de fusión hasta el despliegue a producción"
msgid "From milestones:"
-msgstr ""
+msgstr "De los hitos:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr ""
+msgstr "Desde la vista de detalles del clúster de Kubernetes, seleccione instalar 'runner' desde la lista de aplicaciones"
msgid "GPG Keys"
msgstr "Llaves GPG"
msgid "General"
-msgstr ""
+msgstr "General"
msgid "General pipelines"
msgstr ""
msgid "Generate a default set of labels"
+msgstr "Generar un conjunto predeterminado de etiquetas"
+
+msgid "Generate key"
msgstr ""
msgid "Geo"
-msgstr ""
+msgstr "Geo"
msgid "Geo Nodes"
msgstr ""
@@ -3628,13 +4300,13 @@ msgid "GeoNodes|Data replication lag"
msgstr ""
msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
-msgstr ""
+msgstr "Al deshabilitar un nodo se detiene el proceso de sincronización. ¿Está seguro que desea continuar con la proceso?"
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
msgid "GeoNodes|Failed"
-msgstr ""
+msgstr "Fallido"
msgid "GeoNodes|Full"
msgstr ""
@@ -3688,118 +4360,124 @@ msgid "GeoNodes|Node was successfully removed."
msgstr ""
msgid "GeoNodes|Not checksummed"
-msgstr ""
+msgstr "Sin suma de verificación"
msgid "GeoNodes|Out of sync"
+msgstr "Sin sincronización"
+
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
-msgstr ""
+msgstr "Slots de replicación WAL"
msgid "GeoNodes|Replication slots"
-msgstr ""
+msgstr "Slots de replicación"
msgid "GeoNodes|Repositories"
-msgstr ""
+msgstr "Repositorios"
msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
-msgstr ""
+msgstr "Comprobadas las sumas de verificación de los repositorios con sus contrapartes en los nodos secundarios"
msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
-msgstr ""
+msgstr "Repositorios verificados con sus contrapartes en el nodo principal"
msgid "GeoNodes|Repository checksum progress"
-msgstr ""
+msgstr "Progreso de la suma de verificación del repositorio"
msgid "GeoNodes|Repository verification progress"
-msgstr ""
+msgstr "GeoNodes|Progreso de la verificación del repositorio"
msgid "GeoNodes|Selective"
-msgstr ""
+msgstr "Selectivo"
msgid "GeoNodes|Something went wrong while changing node status"
-msgstr ""
+msgstr "Se ha producido un error mientras se cambiaba el estado del nodo"
msgid "GeoNodes|Something went wrong while fetching nodes"
-msgstr ""
+msgstr "Se ha producido un error obtener los nodos"
msgid "GeoNodes|Something went wrong while removing node"
-msgstr ""
+msgstr "Se ha producido un error al eliminar el nodo"
msgid "GeoNodes|Something went wrong while repairing node"
-msgstr ""
+msgstr "Se ha producido un error mientras al reparar el nodo"
msgid "GeoNodes|Storage config"
-msgstr ""
+msgstr "Configuración del almacenamiento"
msgid "GeoNodes|Sync settings"
-msgstr ""
+msgstr "Opciones de sincronización"
msgid "GeoNodes|Synced"
-msgstr ""
+msgstr "Sincronizado"
msgid "GeoNodes|Unused slots"
-msgstr ""
+msgstr "Slots sin utilizar"
msgid "GeoNodes|Unverified"
-msgstr ""
+msgstr " Sin verificar"
msgid "GeoNodes|Used slots"
-msgstr ""
+msgstr "Slots utilizados"
msgid "GeoNodes|Verified"
-msgstr ""
+msgstr "Verificado"
msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
+msgstr "Progreso de verificación del wiki"
msgid "GeoNodes|Wiki verification progress"
-msgstr ""
+msgstr "Progreso de la verificación del wiki"
msgid "GeoNodes|Wikis"
-msgstr ""
+msgstr "Wikis"
msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
-msgstr ""
+msgstr "Suma de verificación de Wikis para su comprobación con sus contrapartes en los nodos secundarios"
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr "Wikis verificados con sus contrapartes en el nodo principal"
+
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
-msgstr ""
+msgstr "Ha configurado los nodos Geo utilizando una conexión HTTP insegura. Le recomendamos la utilización de una conexión HTTPS."
msgid "Geo|%{name} is scheduled for forced re-download"
-msgstr ""
+msgstr "%{name} está programado para una nueva descarga forzada"
msgid "Geo|%{name} is scheduled for re-check"
-msgstr ""
+msgstr "%{name} está programado para volver a comprobar"
msgid "Geo|%{name} is scheduled for re-sync"
-msgstr ""
+msgstr "%{name} está programado para volver a sincronizar"
msgid "Geo|All"
-msgstr ""
+msgstr "Todos"
msgid "Geo|All projects"
-msgstr ""
+msgstr "Todos los proyectos"
msgid "Geo|All projects are being scheduled for re-check"
-msgstr ""
+msgstr "Se ha programado la comprobación de todos los proyectos"
msgid "Geo|All projects are being scheduled for re-sync"
-msgstr ""
+msgstr "Se ha programado la sincronización de los proyectos"
msgid "Geo|Batch operations"
-msgstr ""
+msgstr "Operaciones por lotes"
msgid "Geo|Could not remove tracking entry for an existing project."
-msgstr ""
+msgstr "No se puede eliminar la entrada de seguimiento para un proyecto existente."
msgid "Geo|Failed"
-msgstr ""
+msgstr "Fallido"
msgid "Geo|File sync capacity"
msgstr ""
@@ -3811,6 +4489,9 @@ msgid "Geo|Groups to synchronize"
msgstr ""
msgid "Geo|In sync"
+msgstr "Sincronizado"
+
+msgid "Geo|Last repository check run"
msgstr ""
msgid "Geo|Last successful sync"
@@ -3823,32 +4504,35 @@ msgid "Geo|Last time verified"
msgstr ""
msgid "Geo|Never"
-msgstr ""
+msgstr "Nunca"
msgid "Geo|Next sync scheduled at"
-msgstr ""
+msgstr "Próxima sincronización programada en"
msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
-msgstr ""
+msgstr "Pendiente"
msgid "Geo|Pending synchronization"
-msgstr ""
+msgstr "Sincronización pendiente"
msgid "Geo|Pending verification"
-msgstr ""
+msgstr "Pendiente de verificación"
msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
msgstr ""
msgid "Geo|Projects in certain groups"
-msgstr ""
+msgstr "Proyectos en determinados grupos"
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3880,10 +4564,10 @@ msgid "Geo|Shards to synchronize"
msgstr ""
msgid "Geo|Status"
-msgstr ""
+msgstr "Estado"
msgid "Geo|Synced"
-msgstr ""
+msgstr "Sincronizado"
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
@@ -3919,186 +4603,201 @@ msgid "Geo|misconfigured"
msgstr ""
msgid "Geo|primary"
-msgstr ""
+msgstr "primario"
msgid "Geo|secondary"
-msgstr ""
+msgstr "secundario"
msgid "Get a free instance review"
+msgstr "Obtenga una revisión de instancia gratuita"
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
msgstr ""
msgid "Git"
+msgstr "Git"
+
+msgid "Git global setup"
msgstr ""
msgid "Git repository URL"
-msgstr ""
+msgstr "URL del repositorio Git"
msgid "Git revision"
-msgstr ""
+msgstr "Revisión de Git"
msgid "Git strategy for pipelines"
-msgstr ""
+msgstr "Estrategia de Git para los 'pipelines'"
msgid "Git version"
-msgstr ""
+msgstr "Versión de Git"
msgid "GitHub import"
-msgstr ""
+msgstr "Importar desde GitHub"
msgid "GitLab CI Linter has been moved"
-msgstr ""
+msgstr "Se ha movido GitLab CI Linter"
msgid "GitLab Geo"
-msgstr ""
+msgstr "GitLab Geo"
msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
+msgstr "El grupo de ejecutores de GitLab puede ejecutar código para todos los proyectos en este grupo."
msgid "GitLab Import"
+msgstr "Importar desde GitLab"
+
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
msgstr ""
msgid "GitLab User"
+msgstr "Usuario de GitLab"
+
+msgid "GitLab metadata URL"
msgstr ""
msgid "GitLab project export"
-msgstr ""
+msgstr "Exportar proyecto desde GitLab"
msgid "GitLab single sign on URL"
-msgstr ""
+msgstr "URL de inicio de sesión único de GitLab"
msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
msgid "GitLab.com import"
-msgstr ""
+msgstr "Importar desde GitLab.com"
msgid "GitLab’s issue tracker"
msgstr ""
msgid "Gitaly"
-msgstr ""
+msgstr "Gitaly"
msgid "Gitaly Servers"
-msgstr ""
+msgstr "Servidores de Gitaly"
msgid "Gitaly|Address"
-msgstr ""
+msgstr "Dirección"
msgid "Gitea Host URL"
-msgstr ""
+msgstr "URL del host de Gitea"
msgid "Gitea Import"
+msgstr "Importar desde Gitea"
+
+msgid "Given access %{time_ago}"
msgstr ""
msgid "Go Back"
-msgstr ""
+msgstr "Volver"
msgid "Go back"
-msgstr ""
+msgstr "Volver"
msgid "Go to"
-msgstr ""
+msgstr "Ir a"
msgid "Go to %{link_to_google_takeout}."
msgstr ""
msgid "Google Code import"
-msgstr ""
+msgstr "Importar desde Google Code"
msgid "Google Takeout"
-msgstr ""
+msgstr "Google Takeout"
msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
msgstr "La autenticación de Google no se encuentra %{link_to_documentation}. Pregúntale a tu administrador de GitLab si quieres usar este servicio."
msgid "Got it!"
+msgstr "¡Lo tengo!"
+
+msgid "Grant access"
msgstr ""
msgid "Graph"
-msgstr ""
+msgstr "Gráfico"
msgid "Group"
-msgstr ""
+msgstr "Grupo"
msgid "Group CI/CD settings"
-msgstr ""
+msgstr "Configuración de grupo CI/CD"
msgid "Group Git LFS status:"
msgstr ""
msgid "Group ID"
-msgstr ""
+msgstr "Id de grupo"
msgid "Group Runners"
-msgstr ""
+msgstr "Grupo de ejecutores"
msgid "Group SAML must be enabled to test"
msgstr ""
msgid "Group URL"
-msgstr ""
+msgstr "URL del grupo"
msgid "Group avatar"
-msgstr ""
+msgstr "Avatar del grupo"
msgid "Group description"
-msgstr ""
+msgstr "Descripción del grupo"
msgid "Group description (optional)"
-msgstr ""
+msgstr "Descripción del grupo (opcional)"
msgid "Group details"
-msgstr ""
+msgstr "Detalles del grupo"
msgid "Group info:"
-msgstr ""
+msgstr "Información del grupo:"
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
msgid "Group name"
-msgstr ""
+msgstr "Nombre del grupo"
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
-msgstr ""
+msgid "Group: %{group_name}"
+msgstr "Grupo: %{group_name}"
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr "Desde %{dateWord}"
msgid "GroupRoadmap|Something went wrong while fetching epics"
-msgstr ""
+msgstr " Se ha producido un error al obtener las tareas épicas"
msgid "GroupRoadmap|Sorry, no epics matched your search"
-msgstr ""
+msgstr "Lo sentimos, no hay tareas épicas que coincidan con su búsqueda"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
msgid "GroupSettings|Badges"
+msgstr "GroupSettings|Insignias"
+
+msgid "GroupSettings|Custom project templates"
msgstr ""
msgid "GroupSettings|Customize your group badges."
@@ -4107,9 +4806,15 @@ msgstr ""
msgid "GroupSettings|Learn more about badges."
msgstr ""
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Prevenir que se comparta un proyecto de %{group} con otros grupos"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -4129,22 +4834,25 @@ msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name
msgstr ""
msgid "Groups"
-msgstr ""
+msgstr "Grupos"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
-msgid "GroupsDropdown|Frequently visited"
+msgid "Groups with access to <strong>%{project_name}</strong>"
msgstr ""
+msgid "GroupsDropdown|Frequently visited"
+msgstr "Más visitado"
+
msgid "GroupsDropdown|Groups you visit often will appear here"
-msgstr ""
+msgstr "Sus proyectos más visitados aparecerán aquí"
msgid "GroupsDropdown|Loading groups"
-msgstr ""
+msgstr "Cargando grupos"
msgid "GroupsDropdown|Search your groups"
-msgstr ""
+msgstr "Buscar en sus grupos"
msgid "GroupsDropdown|Something went wrong on our end."
msgstr ""
@@ -4201,10 +4909,10 @@ msgid "Have your users email"
msgstr ""
msgid "Header message"
-msgstr ""
+msgstr "Encabezado del mensaje"
msgid "Health Check"
-msgstr ""
+msgstr "Verificación del estado"
msgid "Health information can be retrieved from the following endpoints. More information is available"
msgstr ""
@@ -4222,15 +4930,18 @@ msgid "HealthCheck|Unhealthy"
msgstr "Poco Saludable"
msgid "Help"
-msgstr ""
+msgstr "Ayuda"
msgid "Help page"
-msgstr ""
+msgstr "Página de ayuda"
msgid "Help page text and support page url."
-msgstr ""
+msgstr "Texto de la página de ayuda y url de la página de soporte."
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr "Aquí está la clave pública SSH que se debe añadir al servidor remoto. Para obtener más información, consulte la documentación."
+
+msgid "Hide file browser"
msgstr ""
msgid "Hide host keys manual input"
@@ -4241,10 +4952,10 @@ msgstr ""
msgid "Hide value"
msgid_plural "Hide values"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ocultar valor"
+msgstr[1] "Ocultar valores"
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,29 +4964,32 @@ msgstr "Historial"
msgid "Housekeeping successfully started"
msgstr "Servicio de limpieza iniciado con éxito"
-msgid "I accept the %{terms_link}"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
+msgid "I accept the %{terms_link}"
+msgstr "Aceptar los %{terms_link}"
+
msgid "I accept the|Terms of Service and Privacy Policy"
-msgstr ""
+msgstr "Aceptar los términos de servicio y la política de privacidad"
msgid "ID"
-msgstr ""
+msgstr "ID"
msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
msgstr ""
msgid "IDE|Back"
-msgstr ""
+msgstr "Volver"
msgid "IDE|Client side evaluation"
-msgstr ""
+msgstr "Evaluación del lado del cliente"
msgid "IDE|Commit"
-msgstr ""
+msgstr "Commit"
msgid "IDE|Edit"
-msgstr ""
+msgstr "Editar"
msgid "IDE|Get started with Live Preview"
msgstr ""
@@ -4293,21 +5007,24 @@ msgid "IDE|Preview your web application using Web IDE client-side evaluation."
msgstr ""
msgid "IDE|Refresh preview"
-msgstr ""
+msgstr "Actualizar vista previa"
msgid "IDE|Review"
-msgstr ""
+msgstr "Revisión"
msgid "IP Address"
-msgstr ""
+msgstr "Direccion IP"
msgid "Identifier"
-msgstr ""
+msgstr "Identificador"
msgid "Identities"
-msgstr ""
+msgstr "Identidades"
msgid "Identity provider single sign on URL"
+msgstr "URL de inicio de sesión único del proveedor de identidades"
+
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "If 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."
@@ -4317,83 +5034,104 @@ msgid "If disabled, the access level will depend on the user's permissions in th
msgstr ""
msgid "If enabled"
-msgstr ""
+msgstr "Si está habilitado"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
+msgstr "Si está habilitado, el acceso a los proyectos se validará en un servicio externo utilizando su etiqueta de clasificación."
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
-msgstr ""
+msgstr "Si utiliza GitHub, verá los estados del pipeline en GitHub para sus commit y sus pull request. %{more_info_link}"
msgid "If you already have files you can push them using the %{link_to_cli} below."
-msgstr ""
+msgstr "Si ya tiene archivos listos, puede subirlos usando el link que se muestra a continuación %{link_to_cli}."
msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
msgstr ""
msgid "ImageDiffViewer|2-up"
-msgstr ""
+msgstr "2-up"
msgid "ImageDiffViewer|Onion skin"
-msgstr ""
+msgstr "Onion skin"
msgid "ImageDiffViewer|Swipe"
+msgstr "Swipe"
+
+msgid "Impersonation has been disabled"
msgstr ""
msgid "Import"
+msgstr "Importar"
+
+msgid "Import CSV"
msgstr ""
msgid "Import Projects from Gitea"
-msgstr ""
+msgstr "Importar proyectos desde Gitea"
msgid "Import all compatible projects"
-msgstr ""
+msgstr "Importar todos los proyectos compatibles"
msgid "Import all projects"
-msgstr ""
+msgstr "Importar todos los proyectos"
msgid "Import all repositories"
-msgstr ""
+msgstr "Importar todos los repositorios"
msgid "Import an exported GitLab project"
-msgstr ""
+msgstr "Importar un proyecto exportado desde GitLab"
msgid "Import in progress"
+msgstr "Importación en progreso"
+
+msgid "Import issues"
msgstr ""
-msgid "Import multiple repositories by uploading a manifest file."
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
msgstr ""
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr "Importar varios repositorios subiendo un archivo manifiesto."
+
msgid "Import project"
+msgstr "Importar proyecto"
+
+msgid "Import project members"
msgstr ""
msgid "Import projects from Bitbucket"
-msgstr ""
+msgstr "Importar proyectos desde Bitbucket"
msgid "Import projects from Bitbucket Server"
-msgstr ""
+msgstr "Importar proyectos desde un servidor de Bitbucket"
msgid "Import projects from FogBugz"
-msgstr ""
+msgstr "Importar proyectos desde FogBugz"
msgid "Import projects from GitLab.com"
-msgstr ""
+msgstr "Importar proyectos desde GitLab.com"
msgid "Import projects from Google Code"
-msgstr ""
+msgstr "Importar proyectos desde Google Code"
msgid "Import repositories from Bitbucket Server"
-msgstr ""
+msgstr "Importar repositorios desde un servidor de Bitbucket"
msgid "Import repositories from GitHub"
-msgstr ""
+msgstr "Importar repositorios desde GitHub"
msgid "Import repository"
msgstr "Importar repositorio"
-msgid "ImportButtons|Connect repositories from"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
+msgid "ImportButtons|Connect repositories from"
+msgstr "Conectar repositorios desde"
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -4406,23 +5144,38 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
-msgid "Incompatible Project"
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
msgstr ""
+msgid "Incompatible Project"
+msgstr "Proyecto incompatible"
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inline"
-msgstr ""
+msgstr "En línea"
msgid "Input host keys manually"
msgstr ""
@@ -4430,22 +5183,25 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Insert suggestion"
msgstr ""
+msgid "Install GitLab Runner"
+msgstr "Instalar GitLab Runner"
+
msgid "Install Runner on Kubernetes"
-msgstr ""
+msgstr "Instalar Gitlab Runner en Kubernetes"
msgid "Instance"
msgid_plural "Instances"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Instancia"
+msgstr[1] "Instancias"
msgid "Instance Statistics"
-msgstr ""
+msgstr "Estadísticas de la Instancia"
msgid "Instance Statistics visibility"
-msgstr ""
+msgstr "Visibilidad de las estadísticas de instancia"
msgid "Instance does not support multiple Kubernetes clusters"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr "Interno - cualquier usuario que haya iniciado sesión puede ver el grupo y cualquier proyecto interno."
@@ -4466,7 +5225,7 @@ msgid "Internal - The project can be accessed by any logged in user."
msgstr "Interno - cualquier usuario haya iniciado sesión puede acceder a este proyecto."
msgid "Internal users"
-msgstr ""
+msgstr "Usuarios internos"
msgid "Interval Pattern"
msgstr "Patrón de intervalo"
@@ -4474,15 +5233,33 @@ msgstr "Patrón de intervalo"
msgid "Introducing Cycle Analytics"
msgstr "Introducción a Cycle Analytics"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
+msgstr "Invitar"
+
+msgid "Invite group"
msgstr ""
-msgid "Issue"
+msgid "Invite member"
msgstr ""
-msgid "Issue Boards"
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
msgstr ""
+msgid "Issue"
+msgstr "Incidencia"
+
+msgid "Issue Boards"
+msgstr "Tablero de incidencias"
+
msgid "Issue board focus mode"
msgstr ""
@@ -4493,16 +5270,31 @@ msgid "IssueBoards|Board"
msgstr "Tablero"
msgid "IssueBoards|Boards"
+msgstr "Tableros"
+
+msgid "IssueBoards|Create new board"
msgstr ""
-msgid "Issues"
+msgid "IssueBoards|Delete board"
msgstr ""
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "Issues"
+msgstr "Incidencias"
+
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr ""
msgid "Issues closed"
-msgstr ""
+msgstr "Incidencias cerradas"
msgid "Issues, merge requests, pushes and comments."
msgstr ""
@@ -4520,7 +5312,7 @@ msgid "IssuesAnalytics|Last 12 months"
msgstr ""
msgid "IssuesAnalytics|Sorry, your filter produced no results"
-msgstr ""
+msgstr "Lo sentimos, su filtro no ha producido ningún resultado."
msgid "IssuesAnalytics|There are no issues for the projects in your group"
msgstr ""
@@ -4528,27 +5320,39 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
-msgid "Jaeger URL"
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
msgstr ""
+msgid "Jaeger URL"
+msgstr "URL de Jaeger"
+
msgid "Jaeger tracing"
msgstr ""
msgid "Jan"
-msgstr ""
+msgstr "Ene"
msgid "January"
msgstr "Enero"
msgid "Job"
-msgstr ""
+msgstr "Trabajo"
msgid "Job has been erased"
+msgstr "El trabajo ha sido eliminado"
+
+msgid "Job is stuck. Check runners."
msgstr ""
-msgid "Jobs"
+msgid "Job was retried"
msgstr ""
+msgid "Jobs"
+msgstr "Trabajos"
+
msgid "Job|Browse"
msgstr ""
@@ -4585,35 +5389,41 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
-msgstr ""
+msgstr "Jul"
msgid "July"
-msgstr ""
+msgstr "Julio"
msgid "Jun"
-msgstr ""
+msgstr "Jun"
msgid "June"
msgstr "Junio"
-msgid "Kubernetes"
+msgid "Key (PEM)"
msgstr ""
+msgid "Kubernetes"
+msgstr "Kubernetes"
+
msgid "Kubernetes Cluster"
+msgstr "Clúster de Kubernetes"
+
+msgid "Kubernetes Clusters"
msgstr ""
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
-msgstr ""
+msgstr "El tiempo de creación del clúster de Kubernetes excede el tiempo de espera; %{timeout}"
msgid "Kubernetes cluster integration was not removed."
-msgstr ""
+msgstr "No se ha eliminado la integración del clúster de Kubernetes."
msgid "Kubernetes cluster integration was successfully removed."
msgstr ""
@@ -4622,13 +5432,13 @@ msgid "Kubernetes cluster was successfully updated."
msgstr ""
msgid "Kubernetes configured"
-msgstr ""
+msgstr "Kubernetes configurado"
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LFS"
-msgstr ""
+msgstr "LFS"
msgid "LFSStatus|Disabled"
msgstr "Deshabilitado"
@@ -4637,7 +5447,7 @@ msgid "LFSStatus|Enabled"
msgstr "Habilitado"
msgid "Label"
-msgstr ""
+msgstr "Etiqueta"
msgid "Label actions dropdown"
msgstr ""
@@ -4652,10 +5462,10 @@ msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
msgstr ""
msgid "LabelSelect|Labels"
-msgstr ""
+msgstr "Etiquetas"
msgid "Labels"
-msgstr ""
+msgstr "Etiquetas"
msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
msgstr ""
@@ -4686,11 +5496,14 @@ msgstr[1] "Últimos %d días"
msgid "Last Pipeline"
msgstr "Último Pipeline"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "Último cambio"
msgid "Last contact"
-msgstr ""
+msgstr "Último contacto"
msgid "Last edited %{date}"
msgstr ""
@@ -4699,6 +5512,9 @@ msgid "Last edited by %{name}"
msgstr "Última edición por %{name}"
msgid "Last reply by"
+msgstr "Última respuesta por"
+
+msgid "Last seen"
msgstr ""
msgid "Last update"
@@ -4708,12 +5524,21 @@ msgid "Last updated"
msgstr "Última actualización"
msgid "LastPushEvent|You pushed to"
-msgstr ""
+msgstr "Ha hecho push a"
msgid "LastPushEvent|at"
msgstr ""
msgid "Latest changes"
+msgstr "Últimos cambios"
+
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
msgid "Learn more"
@@ -4722,7 +5547,22 @@ msgstr "Conozca más"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
+msgstr "Aprenda más acerca de Kubernetes"
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
msgstr ""
msgid "Learn more about protected branches"
@@ -4735,7 +5575,7 @@ msgid "Learn more in the|pipeline schedules documentation"
msgstr "documentación sobre la programación de pipelines"
msgid "Leave"
-msgstr ""
+msgstr "Abandonar"
msgid "Leave group"
msgstr "Abandonar grupo"
@@ -4747,10 +5587,10 @@ msgid "Leave the \"File type\" and \"Delivery method\" options on their default
msgstr ""
msgid "License"
-msgstr ""
+msgstr "Licencia"
msgid "LicenseManagement|Add a license"
-msgstr ""
+msgstr "Añadir licencia"
msgid "LicenseManagement|Add licenses manually to approve or blacklist"
msgstr ""
@@ -4816,13 +5656,13 @@ msgid "LicenseManagement|This license already exists in this project."
msgstr ""
msgid "LicenseManagement|URL"
-msgstr ""
+msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
msgid "Licenses"
-msgstr ""
+msgstr "Licencias"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
@@ -4830,76 +5670,82 @@ msgstr[0] ""
msgstr[1] ""
msgid "LinkedIn"
-msgstr ""
+msgstr "LinkedIn"
msgid "List"
-msgstr ""
+msgstr "Lista"
msgid "List Your Gitea Repositories"
-msgstr ""
+msgstr "Mostrar sus repositorios de Gitea"
msgid "List available repositories"
-msgstr ""
+msgstr "Lista de repositorios disponibles"
msgid "List view"
-msgstr ""
+msgstr "Vista de lista"
msgid "List your Bitbucket Server repositories"
-msgstr ""
+msgstr "Listar sus repositorios de Bitbucket Server"
msgid "List your GitHub repositories"
-msgstr ""
+msgstr "Listar sus repositorios de GitHub"
msgid "Live preview"
-msgstr ""
+msgstr "Vista previa"
msgid "Loading contribution stats for group members"
-msgstr ""
+msgstr "Cargando las estadísticas de las colaboraciones de los miembros del grupo"
msgid "Loading the GitLab IDE..."
-msgstr ""
+msgstr "Cargando el IDE de GitLab..."
msgid "Loading..."
+msgstr "Cargando..."
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
msgstr ""
msgid "Lock"
msgstr "Bloquear"
msgid "Lock %{issuableDisplayName}"
-msgstr ""
+msgstr "Bloquear %{issuableDisplayName}"
msgid "Lock not found"
-msgstr ""
+msgstr "Bloqueo no encontrado"
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
msgid "Lock to current projects"
-msgstr ""
+msgstr "Bloquear al proyecto actual"
msgid "Locked"
msgstr "Bloqueado"
msgid "Locked Files"
-msgstr ""
+msgstr "Archivos bloqueados"
msgid "Locked to current projects"
-msgstr ""
+msgstr "Bloqueado a los proyectos actuales"
msgid "Locks give the ability to lock specific file or folder."
-msgstr ""
+msgstr "Los bloqueos brindan la capacidad de bloquear archivos o carpetas específicos."
msgid "Login with smartcard"
-msgstr ""
+msgstr "Iniciar sesión con una tarjeta inteligente"
msgid "Logs"
-msgstr ""
+msgstr "Logs"
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 "Haga que todos en su equipo sean más productivos, independientemente de su ubicación. GitLab Geo crea réplicas de solo lectura de su instancia de GitLab para que pueda reducir el tiempo que lleva clonar y obtener grandes repositorios."
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
-msgstr ""
+msgstr "Asegúrese de haber iniciado sesión en la cuenta que posee los proyectos que desea importar."
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
msgstr ""
@@ -4908,10 +5754,10 @@ msgid "Manage Web IDE features"
msgstr ""
msgid "Manage access"
-msgstr ""
+msgstr "Administrar accesos"
msgid "Manage all notifications"
-msgstr ""
+msgstr "Administrar todas las notificaciones"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr ""
@@ -4920,46 +5766,52 @@ msgid "Manage applications that you've authorized to use your account."
msgstr ""
msgid "Manage group labels"
-msgstr ""
+msgstr "Administrar etiquetas de grupo"
msgid "Manage labels"
-msgstr ""
+msgstr "Administrar etiquetas"
msgid "Manage project labels"
+msgstr "Administrar etiquetas de proyectos"
+
+msgid "Manage two-factor authentication"
msgstr ""
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
msgid "Manifest"
-msgstr ""
+msgstr "Manifiesto"
msgid "Manifest file import"
-msgstr ""
+msgstr "Importar fichero de manifiesto"
msgid "Map a FogBugz account ID to a GitLab user"
-msgstr ""
+msgstr "Asigne una ID de cuenta de FogBugz a un usuario de GitLab"
msgid "Map a Google Code user to a GitLab user"
-msgstr ""
+msgstr "Asigne un usuario de Google Code a un usuario de GitLab"
msgid "Map a Google Code user to a full email address"
-msgstr ""
+msgstr "Asigne un usuario de Google Code a una dirección de correo electrónico completa"
msgid "Map a Google Code user to a full name"
-msgstr ""
+msgstr "Asigne un usuario de Google Code a un nombre completo"
msgid "Mar"
-msgstr ""
+msgstr "Marzo"
msgid "March"
msgstr "Marzo"
msgid "Mark todo as done"
+msgstr "Marcar tarea pendiente como completada"
+
+msgid "Markdown"
msgstr ""
msgid "Markdown enabled"
-msgstr ""
+msgstr "Markdown habilitado"
msgid "MarkdownToolbar|Add a bullet list"
msgstr ""
@@ -4992,19 +5844,16 @@ msgid "MarkdownToolbar|Insert code"
msgstr ""
msgid "Maven Metadata"
-msgstr ""
-
-msgid "Maven package"
-msgstr ""
+msgstr "Metadatos de Maven"
msgid "Max access level"
-msgstr ""
+msgstr "Nivel de acceso máximo"
msgid "Maximum job timeout"
msgstr ""
msgid "May"
-msgstr ""
+msgstr "Mayo"
msgid "Median"
msgstr "Mediana"
@@ -5013,54 +5862,78 @@ msgid "Member lock"
msgstr ""
msgid "Member since %{date}"
-msgstr ""
+msgstr "Miembro desde %{date}"
msgid "Members"
msgstr "Miembros"
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
+msgid "Merge Request"
+msgstr "Merge request"
+
msgid "Merge Requests"
-msgstr ""
+msgstr "Merge requests"
msgid "Merge Requests created"
+msgstr "Solicitudes de merge creadas"
+
+msgid "Merge commit message"
msgstr ""
msgid "Merge events"
+msgstr "Eventos de merge"
+
+msgid "Merge immediately"
msgstr ""
-msgid "Merge request"
+msgid "Merge in progress"
msgstr ""
+msgid "Merge request"
+msgstr "Merge request"
+
msgid "Merge request approvals"
msgstr ""
msgid "Merge requests"
-msgstr ""
+msgstr "Merge requests"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr "Los merge request son un lugar para proponer los cambios que ha realizado en un proyecto y discutir esos cambios con otros miembros"
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
msgstr ""
msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr "Se ha producido un error al guardar el borrador del comentario."
+
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,77 +5978,80 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
-msgid "Merged"
+msgid "MergeRequest|Search files"
msgstr ""
+msgid "Merged"
+msgstr "Mergeado"
+
msgid "Messages"
msgstr "Mensajes"
msgid "Metrics"
-msgstr ""
+msgstr "Métricas"
msgid "Metrics - Influx"
-msgstr ""
+msgstr "Métricas - Influx"
msgid "Metrics - Prometheus"
-msgstr ""
+msgstr "Métricas - Prometheus"
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
-msgstr ""
+msgstr "Consulte la documentación de CI/CD sobre la implementación en un entorno"
msgid "Metrics|Create metric"
+msgstr "Crear métrica"
+
+msgid "Metrics|Delete metric"
msgstr ""
-msgid "Metrics|Edit metric"
+msgid "Metrics|Delete metric?"
msgstr ""
+msgid "Metrics|Edit metric"
+msgstr "Editar métrica"
+
msgid "Metrics|Environment"
-msgstr ""
+msgstr "Entorno"
msgid "Metrics|For grouping similar metrics"
-msgstr ""
+msgstr "Para agrupar métricas similares"
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
-msgstr ""
+msgstr "Aprenda sobre los entornos"
msgid "Metrics|Legend label (optional)"
-msgstr ""
+msgstr "Leyenda de la etiqueta (opcional)"
msgid "Metrics|Must be a valid PromQL query."
-msgstr ""
-
-msgid "Metrics|Name"
-msgstr ""
+msgstr "Debe ser una consulta PromQL válida."
msgid "Metrics|New metric"
-msgstr ""
+msgstr "Nueva métrica"
msgid "Metrics|No deployed environments"
-msgstr ""
-
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
+msgstr "No hay entornos desplegados"
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
-msgstr ""
+msgid "Metrics|Prometheus Query Documentation"
+msgstr "Documentción sobre las consultas de Prometheus"
msgid "Metrics|System"
-msgstr ""
+msgstr "Sistema"
msgid "Metrics|There was an error fetching the environments data, please try again"
-msgstr ""
+msgstr "Se ha producido un error al recuperar los datos de los distintos entornos, por favor inténtelo de nuevo"
msgid "Metrics|There was an error getting deployment information."
msgstr ""
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5178,34 +6072,25 @@ msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
msgstr ""
msgid "Metrics|Unit label"
-msgstr ""
+msgstr "Etiqueta de las unidades"
msgid "Metrics|Used as a title for the chart"
-msgstr ""
+msgstr "Utilizado como título para el gráfico"
msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
msgstr ""
msgid "Metrics|Y-axis label"
-msgstr ""
+msgstr "Etiqueta del eje Y"
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
-msgstr ""
-
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
+msgstr "por ejemplo, rendimiento"
msgid "Milestone"
-msgstr ""
+msgstr "Hito"
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -5214,7 +6099,7 @@ msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
msgid "Milestones"
-msgstr ""
+msgstr "Hitos"
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 ""
@@ -5271,64 +6156,76 @@ msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "agregar una clave SSH"
msgid "Modal|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "Modal|Close"
+msgstr "Cerrar"
+
+msgid "Modify commit messages"
msgstr ""
-msgid "Monitoring"
+msgid "Modify merge commit"
msgstr ""
-msgid "Months"
+msgid "Monday"
msgstr ""
-msgid "More"
+msgid "Monitor your errors by integrating with Sentry"
msgstr ""
+msgid "Monitoring"
+msgstr "Monitorizar"
+
+msgid "Months"
+msgstr "Meses"
+
+msgid "More"
+msgstr "Más"
+
msgid "More actions"
-msgstr ""
+msgstr "Más acciones"
msgid "More info"
-msgstr ""
+msgstr "Más información"
msgid "More information"
-msgstr ""
+msgstr "Más información"
msgid "More information is available|here"
-msgstr ""
+msgstr "Hay más información disponible | aquí"
msgid "Most stars"
-msgstr ""
+msgstr "Más estrellas"
msgid "Move"
-msgstr ""
+msgstr "Mover"
msgid "Move issue"
-msgstr ""
+msgstr "Mover incidencia"
msgid "Multiple issue boards"
-msgstr ""
+msgstr "Múltiples tableros de incidencias"
msgid "Name"
-msgstr ""
+msgstr "Nombre"
msgid "Name new label"
-msgstr ""
+msgstr "Nombre de la nueva etiqueta"
msgid "Name your individual key via a title"
-msgstr ""
+msgstr "Nombre su clave individual mediante un título"
msgid "Name:"
-msgstr ""
+msgstr "Nombre:"
msgid "Naming, visibility"
msgstr ""
msgid "Nav|Help"
-msgstr ""
+msgstr "Ayuda"
msgid "Nav|Home"
-msgstr ""
+msgstr "Inicio"
msgid "Nav|Sign In / Register"
msgstr ""
@@ -5336,23 +6233,29 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
-msgid "Network"
+msgid "Need help?"
msgstr ""
+msgid "Network"
+msgstr "Red"
+
msgid "Never"
-msgstr ""
+msgstr "Nunca"
msgid "New"
-msgstr ""
+msgstr "Nuevo"
msgid "New Application"
+msgstr "Nueva aplicación"
+
+msgid "New Environment"
msgstr ""
msgid "New Group"
-msgstr ""
+msgstr "Nuevo grupo"
msgid "New Identity"
-msgstr ""
+msgstr "Nueva Identidad"
msgid "New Issue"
msgid_plural "New Issues"
@@ -5360,16 +6263,22 @@ msgstr[0] "Nueva incidencia"
msgstr[1] "Nuevas incidencias"
msgid "New Label"
+msgstr "Nueva etiqueta"
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
msgstr ""
msgid "New Pipeline Schedule"
msgstr "Nueva Programación del Pipeline"
msgid "New Snippet"
-msgstr ""
+msgstr "Nuevo fragmento de código"
msgid "New Snippets"
-msgstr ""
+msgstr "Nuevo fragmento de código"
msgid "New branch"
msgstr "Nueva rama"
@@ -5380,9 +6289,12 @@ msgstr "Nueva rama no disponible"
msgid "New directory"
msgstr "Nuevo directorio"
-msgid "New epic"
+msgid "New environment"
msgstr ""
+msgid "New epic"
+msgstr "Nueva tarea épica"
+
msgid "New file"
msgstr "Nuevo archivo"
@@ -5390,20 +6302,23 @@ msgid "New group"
msgstr "Nuevo grupo"
msgid "New identity"
-msgstr ""
+msgstr "Nueva identidad"
msgid "New issue"
msgstr "Nueva incidencia"
msgid "New label"
-msgstr ""
+msgstr "Nueva etiqueta"
msgid "New merge request"
msgstr "Nueva solicitud de fusión"
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New milestone"
msgstr ""
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr "Los nuevos 'pipelines' cancelarán los 'pipelines' más antiguos y pendientes en el mismo 'branch'"
+
msgid "New project"
msgstr "Nuevo proyecto"
@@ -5420,21 +6335,27 @@ msgid "New tag"
msgstr "Nueva etiqueta"
msgid "New..."
-msgstr ""
+msgstr "Nuevo..."
msgid "No"
-msgstr ""
+msgstr "No"
msgid "No Label"
+msgstr "Sin etiqueta"
+
+msgid "No activities found"
msgstr ""
msgid "No assignee"
-msgstr ""
+msgstr "Sin asignar"
msgid "No branches found"
msgstr ""
msgid "No changes"
+msgstr "Sin cambios"
+
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -5447,27 +6368,39 @@ msgid "No contributions were found"
msgstr ""
msgid "No credit card required."
+msgstr "No se necesita tarjeta de crédito."
+
+msgid "No details available"
msgstr ""
msgid "No due date"
+msgstr "Sin fecha límite"
+
+msgid "No errors to display"
msgstr ""
msgid "No estimate or time spent"
-msgstr ""
+msgstr "Sin estimación o tiempo gastado"
msgid "No file chosen"
+msgstr "No se ha seleccionado nignun archivo"
+
+msgid "No file selected"
msgstr ""
msgid "No files found."
-msgstr ""
+msgstr "No se han encontrado archivos."
msgid "No issues for the selected time period."
-msgstr ""
+msgstr "No hay incidencias para el período de tiempo seleccionado."
msgid "No labels with such name or description"
msgstr ""
msgid "No license. All rights reserved"
+msgstr "Sin licencia. Todos los derechos reservados"
+
+msgid "No matching results"
msgstr ""
msgid "No merge requests for the selected time period."
@@ -5477,47 +6410,47 @@ msgid "No merge requests found"
msgstr ""
msgid "No messages were logged"
+msgstr "No se registraron mensajes"
+
+msgid "No milestones to show"
msgstr ""
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
msgstr ""
msgid "No public groups"
-msgstr ""
+msgstr "No hay grupos públicos"
msgid "No pushes for the selected time period."
-msgstr ""
+msgstr "No hay pushes para el período de tiempo seleccionado."
msgid "No repository"
msgstr "No hay repositorio"
msgid "No runners found"
-msgstr ""
+msgstr "No se encontraron ejecutores"
msgid "No schedules"
msgstr "No hay programaciones"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
msgid "Nodes"
-msgstr ""
+msgstr "Nodos"
msgid "None"
msgstr "Ninguno"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5531,15 +6464,18 @@ msgid "Not available for protected branches"
msgstr ""
msgid "Not confidential"
-msgstr ""
+msgstr "No es confidencial"
msgid "Not enough data"
msgstr "No hay suficientes datos"
msgid "Not now"
-msgstr ""
+msgstr "Ahora no"
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr "Tenga en cuenta que la rama principal está protegida automáticamente. %{link_to_protected_branches}"
+
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
@@ -5555,23 +6491,29 @@ msgid "Note: Consider asking your GitLab administrator to configure %{github_int
msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
-msgstr ""
+msgstr "¿Está seguro de que desea cancelar la creación de este comentario?"
msgid "Notes|Collapse replies"
-msgstr ""
+msgstr "Contraer respuestas"
msgid "Notes|Show all activity"
-msgstr ""
+msgstr "Mostrar toda la actividad"
msgid "Notes|Show comments only"
-msgstr ""
+msgstr "Mostrar sólo los comentarios"
msgid "Notes|Show history only"
-msgstr ""
+msgstr "Mostrar sólo el historial"
msgid "Notification events"
msgstr "Eventos de notificación"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Cerrar incidencia"
@@ -5585,7 +6527,7 @@ msgid "NotificationEvent|Merge merge request"
msgstr "Integrar solicitud de fusión"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "Nueva tarea épica"
msgid "NotificationEvent|New issue"
msgstr "Nueva incidencia"
@@ -5630,22 +6572,22 @@ msgid "Notifications"
msgstr "Notificaciones"
msgid "Notifications off"
-msgstr ""
+msgstr "Notificaciones desactivadas"
msgid "Notifications on"
-msgstr ""
+msgstr "Notificaciones activadas"
msgid "Nov"
-msgstr ""
+msgstr "Nov"
msgid "November"
msgstr "Noviembre"
msgid "OK"
-msgstr ""
+msgstr "OK"
msgid "Oct"
-msgstr ""
+msgstr "Oct"
msgid "October"
msgstr "Octubre"
@@ -5654,12 +6596,12 @@ msgid "OfSearchInADropdown|Filter"
msgstr "Filtrar"
msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr ""
+msgstr "Una vez importados, los repositorios se pueden duplicar a través de SSH. Lea más en %{ssh_link}"
msgid "One more item"
msgid_plural "%d more items"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Un elemento más"
+msgstr[1] "%d elementos más"
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
@@ -5668,43 +6610,58 @@ msgid "One or more of your Google Code projects cannot be imported into GitLab d
msgstr ""
msgid "Only admins"
+msgstr "Sólo administradores"
+
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only policy:"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr "Sólo los miembros de proyecto pueden comentar."
-msgid "Oops, are you sure?"
+msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Oops, are you sure?"
+msgstr "Oops, ¿está seguro?"
+
msgid "Open"
+msgstr "Abrir"
+
+msgid "Open Documentation"
msgstr ""
-msgid "Open in Xcode"
+msgid "Open comment type dropdown"
msgstr ""
-msgid "Open projects"
+msgid "Open errors"
msgstr ""
+msgid "Open in Xcode"
+msgstr "Abrir en Xcode"
+
+msgid "Open projects"
+msgstr "Proyectos abiertos"
+
msgid "Open sidebar"
-msgstr ""
+msgstr "Abrir barra lateral"
msgid "Open source software to collaborate on code"
-msgstr ""
+msgstr "Software de código abierto para colaborar en el código"
msgid "Opened"
-msgstr ""
+msgstr "Abierto"
msgid "Opened MR"
-msgstr ""
+msgstr "MR abiertos"
msgid "Opened issues"
-msgstr ""
+msgstr "Incidencias abiertas"
msgid "OpenedNDaysAgo|Opened"
msgstr "Abierto"
@@ -5713,21 +6670,18 @@ msgid "Opens in a new window"
msgstr "Abre en una nueva ventana"
msgid "Operations"
-msgstr ""
+msgstr "Operaciones"
msgid "Operations Dashboard"
-msgstr ""
-
-msgid "Operations Settings"
-msgstr ""
+msgstr "Panel de operaciones"
msgid "OperationsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "Agregar un proyecto al panel"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5743,16 +6697,16 @@ msgid "Or you can choose one of the suggested colors below"
msgstr ""
msgid "Other Labels"
-msgstr ""
+msgstr "Otras etiquetas"
msgid "Other information"
-msgstr ""
+msgstr "Otra información"
msgid "Otherwise it is recommended you start with one of the options below."
-msgstr ""
+msgstr "De lo contrario, se recomienda empezar con una de las siguientes opciones."
msgid "Outbound requests"
-msgstr ""
+msgstr "Peticiones salientes"
msgid "Overview"
msgstr "Resumen"
@@ -5764,22 +6718,28 @@ msgid "Owner"
msgstr "Propietario"
msgid "Package information"
-msgstr ""
+msgstr "Información del paquete"
msgid "Package was removed"
-msgstr ""
+msgstr "El paquete ha sido eliminado"
msgid "Packages"
-msgstr ""
+msgstr "Paquetes"
msgid "Pages"
+msgstr "Páginas"
+
+msgid "Pages Domain"
msgstr ""
-msgid "Pagination|Last »"
+msgid "Pages Domains"
msgstr ""
+msgid "Pagination|Last »"
+msgstr "Último »"
+
msgid "Pagination|Next"
-msgstr ""
+msgstr "Siguiente"
msgid "Pagination|Prev"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr "Contraseña"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "Pipeline"
@@ -5947,22 +6925,22 @@ msgid "Pipelines|There are currently no pipelines."
msgstr ""
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
-msgstr ""
+msgstr "Se ha producido un error al obtener los pipelines. Por favor, inténtelo de nuevo en unos momentos o contacte con su equipo de soporte."
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
msgid "Pipeline|Commit"
-msgstr ""
+msgstr "Commit"
msgid "Pipeline|Create for"
-msgstr ""
+msgstr "Crear para"
msgid "Pipeline|Create pipeline"
-msgstr ""
+msgstr "Crear pipeline"
msgid "Pipeline|Duration"
-msgstr ""
+msgstr "Duración"
msgid "Pipeline|Existing branch name or tag"
msgstr ""
@@ -5971,7 +6949,7 @@ msgid "Pipeline|Pipeline"
msgstr ""
msgid "Pipeline|Run Pipeline"
-msgstr ""
+msgstr "Ejecutar Pipeline"
msgid "Pipeline|Search branches"
msgstr ""
@@ -5983,19 +6961,19 @@ msgid "Pipeline|Stages"
msgstr ""
msgid "Pipeline|Status"
-msgstr ""
+msgstr "Estado"
msgid "Pipeline|Stop pipeline"
-msgstr ""
+msgstr "Detener pipeline"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
-msgstr ""
+msgstr "¿Desea detener la ejecución del pipeline #%{pipelineId}?"
msgid "Pipeline|Variables"
-msgstr ""
+msgstr "Variables"
msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
-msgstr ""
+msgstr "Está a punto de detener la ejecución del pipeline %{pipelineId}."
msgid "Pipeline|all"
msgstr "todos"
@@ -6010,19 +6988,22 @@ msgid "Pipeline|with stages"
msgstr "con etapas"
msgid "Plain diff"
-msgstr ""
+msgstr "Dif simple"
msgid "PlantUML"
-msgstr ""
+msgstr "PlantUML"
msgid "Play"
+msgstr "Ejecutar"
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
-msgstr ""
+msgstr "Por favor, acepte los términos del servicio antes de continuar."
msgid "Please choose a group URL with no special characters."
-msgstr ""
+msgstr "Por favor, elija una URL de grupo sin caracteres especiales."
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6061,30 +7051,33 @@ msgid "Preferences|Navigation theme"
msgstr ""
msgid "Press Enter or click to search"
-msgstr ""
+msgstr "Presione Enter o haga clic para buscar"
msgid "Prevent adding new members to project membership within this group"
msgstr ""
msgid "Preview"
-msgstr ""
+msgstr "Vista previa"
msgid "Preview payload"
msgstr ""
msgid "Primary"
-msgstr ""
+msgstr "Principal"
msgid "Prioritize"
-msgstr ""
+msgstr "Priorizar"
msgid "Prioritize label"
-msgstr ""
+msgstr "Priorizar la etiqueta"
msgid "Prioritized Labels"
-msgstr ""
+msgstr "Etiquetas priorizadas"
msgid "Prioritized label"
+msgstr "Etiquetas priorizada"
+
+msgid "Private"
msgstr ""
msgid "Private - Project access must be granted explicitly to each user."
@@ -6094,13 +7087,13 @@ msgid "Private - The group and its projects can only be viewed by members."
msgstr "Privado - El grupo y sus proyectos sólo pueden ser vistos por sus miembros."
msgid "Private projects can be created in your personal namespace with:"
-msgstr ""
+msgstr "Los proyectos privados se pueden crear en su espacio de nombres personal con:"
msgid "Profile"
msgstr "Perfil"
msgid "Profile Settings"
-msgstr ""
+msgstr "Configuración del perfil"
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 ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Contraseña inválida"
@@ -6193,49 +7219,55 @@ msgid "Profiles|Public Avatar"
msgstr ""
msgid "Profiles|Remove avatar"
-msgstr ""
+msgstr "Eliminar avatar"
msgid "Profiles|Set new profile picture"
+msgstr "Establecer una nueva imagen de perfil"
+
+msgid "Profiles|Social sign-in"
msgstr ""
msgid "Profiles|Some options are unavailable for LDAP accounts"
-msgstr ""
+msgstr "Algunas opciones no están disponibles para cuentas LDAP"
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
-msgstr ""
+msgstr "El tamaño máximo de archivo permitido es 200KB."
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
-msgstr ""
+msgstr "No se parece a una clave SSH pública, ¿está seguro de que desea agregarla?"
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
-msgstr ""
+msgstr "Este correo electrónico se utilizará para operaciones basadas en la web, como por ejemplo, realizar ediciones y merges. %{learn_more}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Escribe tu %{confirmationValue} para confirmar:"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr ""
+msgstr "Normalmente comienza con \"ssh-rsa ...\""
msgid "Profiles|Update profile settings"
msgstr ""
msgid "Profiles|Update username"
-msgstr ""
+msgstr "Actualizar el nombre de usuario"
msgid "Profiles|Upload new avatar"
msgstr ""
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,41 +7308,50 @@ msgstr "No tienes acceso para eliminar este usuario."
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "Debes transferir o eliminar estos grupos antes de que puedas eliminar tu cuenta."
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Actualmente su cuenta es propietaria de estos grupos:"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
-msgstr ""
+msgstr "Su estado"
msgid "Profiles|e.g. My MacBook key"
+msgstr "por ejemplo, mi clave MacBook"
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
msgstr ""
msgid "Profiles|your account"
msgstr "tu cuenta"
msgid "Profiling - Performance bar"
-msgstr ""
+msgstr "Profiling - Barra de rendimiento"
msgid "Programming languages used in this repository"
-msgstr ""
+msgstr "Lenguajes de programación utilizados en este repositorio"
msgid "Progress"
-msgstr ""
+msgstr "Progreso"
msgid "Project"
-msgstr ""
+msgstr "Proyecto"
msgid "Project '%{project_name}' is in the process of being deleted."
-msgstr "Proyecto '%{project_name}' está en proceso de ser eliminado."
+msgstr "El proyecto '%{project_name}' está en proceso de ser eliminado."
msgid "Project '%{project_name}' queued for deletion."
msgstr "Proyecto ‘%{project_name}’ en cola para eliminación."
@@ -6319,19 +7363,19 @@ msgid "Project '%{project_name}' was successfully updated."
msgstr "Proyecto ‘%{project_name}’ fue actualizado satisfactoriamente."
msgid "Project Badges"
-msgstr ""
+msgstr "Insignias de proyecto"
msgid "Project URL"
-msgstr ""
+msgstr "URL del proyecto"
msgid "Project access must be granted explicitly to each user."
msgstr "El acceso al proyecto debe concederse explícitamente a cada usuario."
msgid "Project avatar"
-msgstr ""
+msgstr "Avatar del proyecto"
msgid "Project avatar in repository: %{link}"
-msgstr ""
+msgstr "Avatar de proyecto en el repositorio: %{link}"
msgid "Project details"
msgstr "Detalles del Proyecto"
@@ -6348,29 +7392,35 @@ msgstr "El enlace de exportación del proyecto ha caducado. Por favor, genera un
msgid "Project export started. A download link will be sent by email."
msgstr "Se inició la exportación del proyecto. Se enviará un enlace de descarga por correo electrónico."
-msgid "Project name"
+msgid "Project members"
msgstr ""
+msgid "Project name"
+msgstr "Nombre del proyecto"
+
msgid "Project slug"
+msgstr "Slug del proyecto"
+
+msgid "Project:"
msgstr ""
msgid "ProjectActivityRSS|Subscribe"
msgstr "Suscribirse"
msgid "ProjectCreationLevel|Allowed to create projects"
-msgstr ""
+msgstr "Permitido para crear proyectos"
msgid "ProjectCreationLevel|Default project creation protection"
-msgstr ""
+msgstr "Protección de creación de proyectos predeterminada"
msgid "ProjectCreationLevel|Developers + Maintainers"
-msgstr ""
+msgstr "Desarrolladores + Mantenedores"
msgid "ProjectCreationLevel|Maintainers"
-msgstr ""
+msgstr "Mantenedores"
msgid "ProjectCreationLevel|No one"
-msgstr ""
+msgstr "Nadie"
msgid "ProjectFileTree|Name"
msgstr "Nombre"
@@ -6382,28 +7432,28 @@ msgid "ProjectLifecycle|Stage"
msgstr "Etapa"
msgid "ProjectOverview|Fork"
-msgstr ""
+msgstr "Fork"
msgid "ProjectOverview|Forks"
-msgstr ""
+msgstr "Forks"
msgid "ProjectOverview|Go to your fork"
-msgstr ""
+msgstr "Ir a su fork"
msgid "ProjectOverview|Star"
-msgstr ""
+msgstr "Marcar como favorito"
msgid "ProjectOverview|Unstar"
-msgstr ""
+msgstr "Desmarcar como favorito"
msgid "ProjectOverview|You have reached your project limit"
-msgstr ""
+msgstr "Ha alcanzado el límite de tu proyecto"
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
-msgstr ""
+msgstr "ID de proyecto: %{project_id}"
msgid "ProjectSettings|Badges"
msgstr ""
@@ -6469,37 +7519,34 @@ msgid "ProjectsDropdown|This feature requires browser localStorage support"
msgstr ""
msgid "PrometheusAlerts|Add alert"
-msgstr ""
+msgstr "Añadir alerta"
msgid "PrometheusAlerts|Alert set"
-msgstr ""
+msgstr "Establecer alerta"
msgid "PrometheusAlerts|Edit alert"
-msgstr ""
+msgstr "Editar alerta"
msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
+msgstr "Se ha producido un error al crear la alerta"
msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
+msgstr "Se ha producido un error al eliminar la alerta"
msgid "PrometheusAlerts|Error fetching alert"
msgstr ""
msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
+msgstr "Se ha producido un error al guardar la alerta"
msgid "PrometheusAlerts|No alert set"
msgstr ""
msgid "PrometheusAlerts|Operator"
-msgstr ""
+msgstr "Operador"
msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
-msgid "PrometheusDashboard|Time"
-msgstr ""
+msgstr "Umbral"
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6511,7 +7558,7 @@ msgid "PrometheusService|Active"
msgstr ""
msgid "PrometheusService|Auto configuration"
-msgstr ""
+msgstr "Configuración automática"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
@@ -6523,22 +7570,25 @@ msgid "PrometheusService|Common metrics are automatically monitored based on a l
msgstr ""
msgid "PrometheusService|Custom metrics"
+msgstr "Métricas personalizadas"
+
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
msgstr ""
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "Encontrar y configurar métricas..."
msgid "PrometheusService|Finding custom metrics..."
-msgstr ""
+msgstr "Buscar métricas personalizadas..."
msgid "PrometheusService|Install Prometheus on clusters"
-msgstr ""
+msgstr "Instalar Prometheus en los clusters"
msgid "PrometheusService|Manage clusters"
-msgstr ""
+msgstr "Administrar clústeres"
msgid "PrometheusService|Manual configuration"
-msgstr ""
+msgstr "Configuración manual"
msgid "PrometheusService|Metrics"
msgstr "Métricas"
@@ -6550,7 +7600,7 @@ msgid "PrometheusService|More information"
msgstr "Más información"
msgid "PrometheusService|New metric"
-msgstr ""
+msgstr "Nueva métrica"
msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
msgstr "URL Base de Prometheus, como http://prometheus.example.com/"
@@ -6574,34 +7624,34 @@ msgid "PrometheusService|Waiting for your first deployment to an environment to
msgstr ""
msgid "Promote"
-msgstr ""
+msgstr "Promocionar"
msgid "Promote these project milestones into a group milestone."
-msgstr ""
+msgstr "Promocionar estos hitos del proyecto a hitos de grupo."
msgid "Promote to Group Milestone"
-msgstr ""
+msgstr "Promocionar a hito de grupo"
msgid "Promote to group label"
-msgstr ""
+msgstr "Promocionar a etiqueta de grupo"
msgid "Promotions|Don't show me this again"
-msgstr ""
+msgstr "No mostrar este mensaje de nuevo"
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 "La tareas épicas le permiten administrar su cartera de proyectos de manera más eficiente y con menos esfuerzo mediante el seguimiento de grupos de incidencias comunes, a través de proyectos e hitos."
msgid "Promotions|This feature is locked."
-msgstr ""
+msgstr "Esta funcionalidad está bloqueada."
msgid "Promotions|Upgrade plan"
-msgstr ""
+msgstr "Plan de actualización"
msgid "Protected"
-msgstr ""
+msgstr "Protegido"
msgid "Protected Environments"
-msgstr ""
+msgstr "Entornos protegidos"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
@@ -6646,14 +7696,17 @@ msgid "ProtectedEnvironment|Your environment has been unprotected"
msgstr ""
msgid "Protip:"
-msgstr ""
+msgstr "Sugerencia:"
msgid "Provider"
-msgstr ""
+msgstr "Proveedor"
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "Público - El grupo y cualquier proyecto público puede ser visto sin autenticación."
@@ -6664,13 +7717,13 @@ msgid "Public pipelines"
msgstr ""
msgid "Pull"
-msgstr ""
+msgstr "Pull"
msgid "Push"
-msgstr ""
+msgstr "Push"
msgid "Push Rules"
-msgstr ""
+msgstr "Reglas de Push"
msgid "Push events"
msgstr "Eventos Push"
@@ -6679,7 +7732,7 @@ msgid "Push project from command line"
msgstr ""
msgid "Push to create a project"
-msgstr ""
+msgstr "Push para crear un proyecto"
msgid "PushRule|Committer restriction"
msgstr ""
@@ -6688,57 +7741,69 @@ msgid "Pushed"
msgstr ""
msgid "Pushes"
-msgstr ""
+msgstr "Pushes"
msgid "Quarters"
+msgstr "Trimestres"
+
+msgid "Query"
msgstr ""
msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr "Se pueden utilizar acciones rápidas en la descripción de las incidencias y en los cuadros de texto de los comentarios."
+
+msgid "README"
msgstr ""
msgid "Read more"
msgstr "Leer más"
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
-msgstr "Léeme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
msgid "Real-time features"
+msgstr "Características en tiempo real"
+
+msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
msgid "Recent searches"
-msgstr ""
+msgstr "Búsquedas recientes"
msgid "Redirect to SAML provider to test configuration"
msgstr ""
msgid "Reference:"
-msgstr ""
+msgstr "Referencia:"
msgid "Refresh"
-msgstr ""
+msgstr "Actualizar"
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Actualizar en un segundo para mostrar el estado actualizado..."
+msgstr[1] "Actualizar en %d segundos para mostrar el estado actualizado..."
msgid "Regenerate key"
-msgstr ""
+msgstr "Regenerar clave"
msgid "Regex pattern"
-msgstr ""
+msgstr "Patrón regex"
msgid "Register / Sign In"
+msgstr "Registrarse / Iniciar sesión"
+
+msgid "Register U2F device"
msgstr ""
msgid "Register and see your runners for this group."
-msgstr ""
+msgstr "Registrar y ver sus ejecutores en este grupo."
msgid "Register and see your runners for this project."
-msgstr ""
+msgstr "Registrar y ver sus ejecutores en este proyecto."
msgid "Registry"
msgstr "Registro"
@@ -6764,56 +7829,74 @@ msgstr "Solicitudes de fusión Relacionadas"
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "Recordar después"
msgid "Remove"
-msgstr ""
+msgstr "Eliminar"
msgid "Remove Runner"
+msgstr "Eliminar ejecutor"
+
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove avatar"
+msgid "Remove approver"
msgstr ""
+msgid "Remove avatar"
+msgstr "Eliminar avatar"
+
msgid "Remove group"
-msgstr ""
+msgstr "Eliminar grupo"
msgid "Remove priority"
-msgstr ""
+msgstr "Eliminar prioridad"
msgid "Remove project"
msgstr "Eliminar proyecto"
msgid "Removed group can not be restored!"
-msgstr ""
+msgstr "¡No se puede restaurar un grupo eliminado!"
msgid "Removing group will cause all child projects and resources to be removed."
-msgstr ""
+msgstr "Eliminar un grupo hará que todos los proyectos y recursos sean eliminados."
msgid "Rename"
-msgstr ""
+msgstr "Renombrar"
msgid "Rename file"
-msgstr ""
+msgstr "Renombrar archivo"
msgid "Rename folder"
-msgstr ""
+msgstr "Renombrar carpeta"
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
+msgstr "Reparar la autenticación"
+
+msgid "Reply to comment"
msgstr ""
msgid "Reply to this email directly or %{view_it_on_gitlab}."
-msgstr ""
+msgstr "Responda a este correo directamente o %{view_it_on_gitlab}."
msgid "Repo by URL"
-msgstr ""
+msgstr "Repo por URL"
msgid "Report abuse to GitLab"
-msgstr ""
+msgstr "Reportar abuso a GitLab"
msgid "Reporting"
msgstr ""
@@ -6861,16 +7944,22 @@ msgid "Repository"
msgstr "Repositorio"
msgid "Repository Settings"
-msgstr ""
+msgstr "Configuración del repositorio"
msgid "Repository URL"
+msgstr "URL del repositorio"
+
+msgid "Repository cleanup"
msgstr ""
-msgid "Repository has no locks."
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
msgstr ""
+msgid "Repository has no locks."
+msgstr "El repositorio no tiene bloqueos."
+
msgid "Repository maintenance"
-msgstr ""
+msgstr "Mantenimiento del repositorio"
msgid "Repository mirror"
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr "Solicitar acceso"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "Reinicializar el token de registro del runner"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,31 +8030,37 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
-msgid "Resume"
+msgid "Restart Terminal"
msgstr ""
+msgid "Resume"
+msgstr "Reanudar"
+
msgid "Retry"
-msgstr ""
+msgstr "Reintentar"
msgid "Retry this job"
-msgstr ""
+msgstr "Reintentar este trabajo"
msgid "Retry verification"
-msgstr ""
-
-msgid "Reveal Variables"
-msgstr ""
+msgstr "Reintentar la verificación"
msgid "Reveal value"
msgid_plural "Reveal values"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Mostrar valor"
+msgstr[1] "Mostrar valores"
+
+msgid "Reveal values"
+msgstr ""
msgid "Revert this commit"
msgstr "Revertir este cambio"
@@ -6950,7 +8069,7 @@ msgid "Revert this merge request"
msgstr "Revertir esta solicitud de fusión"
msgid "Review"
-msgstr ""
+msgstr "Revisión"
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr ""
@@ -6962,16 +8081,19 @@ msgid "Reviewing (merge request !%{mergeRequestId})"
msgstr ""
msgid "Revoke"
-msgstr ""
+msgstr "Revocar"
msgid "Roadmap"
-msgstr ""
+msgstr "Hoja de ruta"
msgid "Run CI/CD pipelines for external repositories"
+msgstr "Ejecutar los pipelines de CI/CD para los repositorios externos"
+
+msgid "Run tests against your code live using the Web Terminal"
msgstr ""
msgid "Run untagged jobs"
-msgstr ""
+msgstr "Ejecutar trabajos no etiquetados"
msgid "Runner cannot be assigned to other projects"
msgstr ""
@@ -6986,15 +8108,18 @@ msgid "Runner runs jobs from assigned projects"
msgstr ""
msgid "Runner token"
-msgstr ""
+msgstr "Token del ejecutor"
msgid "Runner will not receive any new jobs"
-msgstr ""
+msgstr "El ejecutor no recibirá ningún trabajo nuevo"
msgid "Runners"
-msgstr ""
+msgstr "Runners"
msgid "Runners API"
+msgstr "Runners API"
+
+msgid "Runners activated for this project"
msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
@@ -7004,33 +8129,33 @@ msgid "Runners can be placed on separate users, servers, even on your local mach
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
-msgstr ""
+msgstr "Ejecutores actualmente en línea: %{active_runners_count}"
msgid "Runners page"
-msgstr ""
+msgstr "Página de ejecutores"
msgid "Runners page."
-msgstr ""
+msgstr "Página de ejecutores."
msgid "Runners|You have used all your shared Runners pipeline minutes."
msgstr ""
msgid "Running"
-msgstr ""
+msgstr "En ejecución"
msgid "SAML SSO"
-msgstr ""
+msgstr "SAML SSO"
msgid "SAML SSO for %{group_name}"
-msgstr ""
+msgstr "SAML SSO para %{group_name}"
msgid "SAML Single Sign On"
-msgstr ""
+msgstr "SAML Inicio de sesión único"
msgid "SAML Single Sign On Settings"
-msgstr ""
+msgstr "Configuración de inicio de sesión SAML"
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7040,19 +8165,22 @@ msgid "SSH Keys"
msgstr "Llaves SSH"
msgid "SSH host keys"
-msgstr ""
+msgstr "Claves de host SSH"
msgid "SSH public key"
-msgstr ""
+msgstr "Clave pública SSH"
msgid "SSL Verification"
-msgstr ""
+msgstr "Verificación SSL"
msgid "Save"
+msgstr "Guardar"
+
+msgid "Save Changes"
msgstr ""
msgid "Save application"
-msgstr ""
+msgstr "Guardar aplicación"
msgid "Save changes"
msgstr "Guardar los cambios"
@@ -7060,110 +8188,119 @@ msgstr "Guardar los cambios"
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Guardar programación del pipeline"
msgid "Save variables"
-msgstr ""
+msgstr "Guardar variables"
msgid "Schedule a new pipeline"
msgstr "Programar un nuevo pipeline"
msgid "Scheduled"
-msgstr ""
+msgstr "Programado"
msgid "Schedules"
-msgstr ""
+msgstr "Programaciones"
msgid "Scheduling Pipelines"
msgstr "Programación de Pipelines"
msgid "Scope"
-msgstr ""
+msgstr "Alcance"
msgid "Scoped issue boards"
msgstr ""
msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
-msgstr ""
+msgstr "Desplácese hasta <strong>Google Code Project</strong> y active el selector de la derecha."
msgid "Scroll to bottom"
-msgstr ""
+msgstr "Desplazar hacia abajo"
msgid "Scroll to top"
-msgstr ""
+msgstr "Desplazar hacia arriba"
msgid "Search"
+msgstr "Buscar"
+
+msgid "Search an environment spec"
msgstr ""
msgid "Search branches"
-msgstr ""
+msgstr "Buscar ramas"
msgid "Search branches and tags"
msgstr "Buscar ramas y etiquetas"
msgid "Search files"
-msgstr ""
+msgstr "Buscar archivos"
msgid "Search for projects, issues, etc."
+msgstr "Buscar proyectos, incidencias, etc."
+
+msgid "Search groups"
msgstr ""
msgid "Search merge requests"
-msgstr ""
+msgstr "Buscar merge requests"
msgid "Search milestones"
-msgstr ""
+msgstr "Buscar hitos"
msgid "Search or filter results..."
-msgstr ""
+msgstr "Buscar o filtrar resultados..."
msgid "Search or jump to…"
-msgstr ""
+msgstr "Buscar o ir a…"
msgid "Search project"
-msgstr ""
+msgstr "Buscar proyecto"
msgid "Search projects"
-msgstr ""
+msgstr "Buscar proyectos"
msgid "Search users"
-msgstr ""
+msgstr "Buscar usuarios"
msgid "Search your projects"
-msgstr ""
+msgstr "Buscar tus proyectos"
msgid "SearchAutocomplete|All GitLab"
-msgstr ""
+msgstr "Todo GitLab"
msgid "SearchAutocomplete|Issues I've created"
-msgstr ""
+msgstr "Incidencias creadas por mí"
msgid "SearchAutocomplete|Issues assigned to me"
-msgstr ""
+msgstr "Incidencias asignadas a mí"
msgid "SearchAutocomplete|Merge requests I've created"
-msgstr ""
+msgstr "Merge requests creados por mí"
msgid "SearchAutocomplete|Merge requests assigned to me"
-msgstr ""
+msgstr "Merge requests asignados a mí"
msgid "SearchAutocomplete|in all GitLab"
-msgstr ""
+msgstr "en todo GitLab"
msgid "SearchAutocomplete|in this group"
-msgstr ""
+msgstr "en este grupo"
msgid "SearchAutocomplete|in this project"
-msgstr ""
+msgstr "en este proyecto"
msgid "Secret"
-msgstr ""
+msgstr "Secreto"
msgid "Security"
-msgstr ""
+msgstr "Seguridad"
msgid "Security Dashboard"
-msgstr ""
+msgstr "Tablero de seguridad"
msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
@@ -7175,9 +8312,9 @@ msgid "Security Dashboard|Error fetching the vulnerability list. Please check yo
msgstr ""
msgid "Security Dashboard|Issue Created"
-msgstr ""
+msgstr "Incidencia creada"
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,56 +8347,77 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
-msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
msgstr ""
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr "Panel de control de seguridad muestra el último informe de seguridad. Úselo para encontrar y corregir vulnerabilidades."
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
-msgid "Select"
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
msgstr ""
+msgid "Select"
+msgstr "Seleccionar"
+
msgid "Select Archive Format"
msgstr "Seleccionar formato de archivo"
msgid "Select a group to invite"
-msgstr ""
+msgstr "Seleccione un grupo a invitar"
msgid "Select a namespace to fork the project"
-msgstr ""
+msgstr "Seleccione un espacio de nombres para hacer un fork del proyecto"
msgid "Select a template repository"
-msgstr ""
+msgstr "Seleccione una plantilla de repositorio"
msgid "Select a timezone"
msgstr "Selecciona una zona horaria"
msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr ""
+msgstr "Seleccione un clúster existente de Kubernetes o cree un cluster nuevo"
msgid "Select assignee"
-msgstr ""
+msgstr "Seleccionar persona asignada"
msgid "Select branch/tag"
msgstr ""
-msgid "Select project"
+msgid "Select members to invite"
msgstr ""
+msgid "Select project"
+msgstr "Seleccionar proyecto"
+
msgid "Select project and zone to choose machine type"
-msgstr ""
+msgstr "Seleccione el proyecto y la zona para elegir el tipo de máquina"
msgid "Select project to choose zone"
-msgstr ""
+msgstr "Seleccione el proyecto para elegir la zona"
msgid "Select projects you want to import."
-msgstr ""
+msgstr "Seleccione qué proyectos desea importar."
msgid "Select source branch"
-msgstr ""
+msgstr "Seleccione la rama de origen"
msgid "Select target branch"
msgstr "Selecciona una rama de destino"
@@ -7271,34 +8432,82 @@ msgid "Selecting a GitLab user will add a link to the GitLab user in the descrip
msgstr ""
msgid "Selective synchronization"
-msgstr ""
+msgstr "Sincronización selectiva"
msgid "Send email"
+msgstr "Enviar correo electrónico"
+
+msgid "Send report"
msgstr ""
msgid "Send usage data"
+msgstr "Enviar estadísticas de uso"
+
+msgid "Sentry API URL"
msgstr ""
msgid "Sep"
-msgstr ""
+msgstr "Sep"
msgid "September"
msgstr "Septiembre"
msgid "Server version"
+msgstr "Versión del servidor"
+
+msgid "Serverless"
msgstr ""
-msgid "Service Desk"
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
msgstr ""
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
+msgid "Service Desk"
+msgstr "Service Desk"
+
msgid "Service Templates"
msgstr "Plantillas de Servicio"
msgid "Service URL"
-msgstr ""
+msgstr "URL del servicio"
msgid "Session expiration, projects limit and attachment size."
-msgstr ""
+msgstr "Caducidad de la sesión, límite de proyectos y tamaño de los archivos adjuntos."
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}."
@@ -7318,19 +8527,25 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
msgid "Set up CI/CD"
-msgstr ""
+msgstr "Configurar CI/CD"
msgid "Set up a %{type} Runner manually"
-msgstr ""
+msgstr "Configurar un %{type} ejecutor manualmente"
msgid "Set up a specific Runner automatically"
-msgstr ""
+msgstr "Configurar un ejecutor específico automáticamente"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr "Configure las afirmaciones/atributos/reclamaciones (correo electrónico, first_name, last_name) y el NameID según %{docsLinkStart}la documentación %{icon}%{docsLinkEnd}"
+
+msgid "Set up new U2F device"
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."
@@ -7367,16 +8582,16 @@ msgid "Settings"
msgstr "Configuración"
msgid "Share"
-msgstr ""
+msgstr "Compartir"
msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
msgstr ""
msgid "Shared Runners"
-msgstr ""
+msgstr "Ejecturores compartidos"
msgid "Shared projects"
-msgstr ""
+msgstr "Proyectos compartidos"
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -7388,19 +8603,19 @@ msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
msgid "Sherlock Transactions"
-msgstr ""
+msgstr "Transacciones de Sherlock"
msgid "Show command"
-msgstr ""
+msgstr "Mostrar comando"
msgid "Show complete raw log"
-msgstr ""
+msgstr "Mostrar el registro completo sin procesar"
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
-msgstr ""
+msgid "Show latest version"
+msgstr "Mostrar la última versión"
msgid "Show parent pages"
msgstr "Mostrar páginas padre"
@@ -7409,7 +8624,7 @@ msgid "Show parent subgroups"
msgstr ""
msgid "Show whitespace changes"
-msgstr ""
+msgstr "Mostrar los espacios en blanco de los cambios"
msgid "Showing %d event"
msgid_plural "Showing %d events"
@@ -7417,131 +8632,170 @@ msgstr[0] "Mostrando %d evento"
msgstr[1] "Mostrando %d eventos"
msgid "Side-by-side"
-msgstr ""
+msgstr "En paralelo"
msgid "Sidebar|Change weight"
-msgstr ""
+msgstr "Cambiar peso"
msgid "Sidebar|None"
-msgstr ""
+msgstr "Ninguno"
msgid "Sidebar|Only numeral characters allowed"
msgstr ""
msgid "Sidebar|Weight"
-msgstr ""
+msgstr "Peso"
msgid "Sign in"
-msgstr ""
+msgstr "Iniciar sesión"
msgid "Sign in / Register"
+msgstr "Iniciar sesión / Registro"
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
+msgstr "Inicie sesión mediante inicio de sesión único"
+
+msgid "Sign in with smart card"
msgstr ""
msgid "Sign out"
-msgstr ""
+msgstr "Cerrar sesión"
msgid "Sign-in restrictions"
-msgstr ""
+msgstr "Restricciones de inicio de sesión"
msgid "Sign-up restrictions"
+msgstr "Restricciones de registro"
+
+msgid "Similar issues"
msgstr ""
msgid "Size"
-msgstr ""
+msgstr "Tamaño"
msgid "Size and domain settings for static websites"
-msgstr ""
+msgstr "Configuración del tamaño y del dominio para los sitios web estáticos"
msgid "Slack application"
-msgstr ""
+msgstr "Aplicación Slack"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
-msgstr ""
+msgstr "La integración con Slack le permite interactuar con GitLab mediante comandos slash en una ventana de chat."
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
+msgstr "Más lento, pero se asegura de que el espacio de trabajo del proyecto sea prístino, ya que se clona el repositorio desde cero para cada trabajo"
msgid "Smartcard"
-msgstr ""
+msgstr "Tarjeta inteligente"
msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr "Falló la autenticación de la tarjeta inteligente: falta la cabecera del certificado del cliente."
+
+msgid "Snippet Contents"
msgstr ""
msgid "Snippets"
+msgstr "Fragmentos de código"
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
msgstr ""
-msgid "Something went wrong on our end"
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Something went wrong on our end"
+msgstr "Algo salió mal por nuestra parte"
+
msgid "Something went wrong on our end."
-msgstr ""
+msgstr "Algo salió mal por nuestra parte."
msgid "Something went wrong on our end. Please try again!"
+msgstr "Algo salió mal en nuestro lado. ¡Por favor, inténtelo de nuevo!"
+
+msgid "Something went wrong on our end. Please try again."
msgstr ""
msgid "Something went wrong trying to change the confidentiality of this issue"
-msgstr ""
+msgstr "Algo salió mal al intentar cambiar la confidencialidad de esta incidencia. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
-msgstr ""
+msgstr "Algo salió mal al intentar cambiar el estado de bloqueo de este %{issuableDisplayName}. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong when toggling the button"
+msgstr "Algo salió mal al cambiar el estado del botón. ¡Por favor, inténtelo de nuevo!"
+
+msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr "Algo salió mal al cerrar la incidencia %{issuable}. ¡Por favor, inténtelo de nuevo!"
+
+msgid "Something went wrong while deleting the source branch. Please try again."
msgstr ""
msgid "Something went wrong while fetching %{listType} list"
-msgstr ""
+msgstr "Algo salió mal al obtener la lista de %{listType}. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong while fetching comments. Please try again."
-msgstr ""
+msgstr "Algo salió mal al buscar comentarios. Inténtalo de nuevo. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong while fetching group member contributions"
-msgstr ""
+msgstr "Algo salió mal al obtener las contribuciones de los miembros del grupo. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
-msgstr ""
+msgstr "Algo salió mal al buscar los entornos para este merge request. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong while fetching the projects."
-msgstr ""
+msgstr "Se ha producido un error al obtener los proyectos."
msgid "Something went wrong while fetching the registry list."
+msgstr "Se ha producido un error mientras se obtenía la lista de registros."
+
+msgid "Something went wrong while merging this merge request. Please try again."
msgstr ""
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
-msgstr ""
+msgstr "Algo salió mal al volver a abrir la incidencia %{issuable}. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong while resolving this discussion. Please try again."
-msgstr ""
+msgstr "Algo salió mal al resolver esta discusión. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong, unable to add %{project} to dashboard"
-msgstr ""
+msgstr "Algo salió mal, no se puede agregar %{project} al panel de control"
msgid "Something went wrong, unable to get operations projects"
-msgstr ""
+msgstr "Algo salió mal, no es posible obtener los proyectos operativos"
msgid "Something went wrong, unable to remove project"
msgstr ""
msgid "Something went wrong. Please try again."
-msgstr ""
+msgstr "Algo salió mal. ¡Por favor, inténtelo de nuevo!"
msgid "Sorry, no epics matched your search"
-msgstr ""
+msgstr "Lo sentimos, no hay tareas épicas que coincidan con su búsqueda"
msgid "Sorry, no projects matched your search"
+msgstr "Lo sentimos, no hay proyectos que coincidan con su búsqueda"
+
+msgid "Sorry, your filter produced no results"
msgstr ""
msgid "Sort by"
msgstr "Ordenar por"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7549,45 +8803,45 @@ msgid "SortOptions|Access level, descending"
msgstr ""
msgid "SortOptions|Created date"
-msgstr ""
+msgstr "Fecha de creación"
msgid "SortOptions|Due date"
-msgstr ""
+msgstr "Fecha de vencimiento"
msgid "SortOptions|Due later"
-msgstr ""
+msgstr "Vencen más tarde"
msgid "SortOptions|Due soon"
-msgstr ""
+msgstr "Vencen pronto"
msgid "SortOptions|Label priority"
-msgstr ""
+msgstr "Prioridad de la etiqueta"
msgid "SortOptions|Largest group"
-msgstr ""
+msgstr "Grupo más grande"
msgid "SortOptions|Largest repository"
-msgstr ""
+msgstr "Repositorio más grande"
msgid "SortOptions|Last Contact"
-msgstr ""
+msgstr "Último Contacto"
msgid "SortOptions|Last created"
-msgstr ""
+msgstr "Fecha de creación"
msgid "SortOptions|Last joined"
-msgstr ""
+msgstr "Fecha de incorporación"
msgid "SortOptions|Last updated"
-msgstr ""
+msgstr "Fecha de actualización"
msgid "SortOptions|Least popular"
-msgstr ""
+msgstr "Menos popular"
msgid "SortOptions|Less weight"
-msgstr ""
+msgstr "Menos peso"
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7606,13 +8860,13 @@ msgid "SortOptions|Most stars"
msgstr ""
msgid "SortOptions|Name"
-msgstr ""
+msgstr "Nombre"
msgid "SortOptions|Name, ascending"
-msgstr ""
+msgstr "Nombre, ascendente"
msgid "SortOptions|Name, descending"
-msgstr ""
+msgstr "Nombre, descendente"
msgid "SortOptions|Oldest created"
msgstr ""
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7642,10 +8902,10 @@ msgid "SortOptions|Start later"
msgstr ""
msgid "SortOptions|Start soon"
-msgstr ""
+msgstr "Comienza pronto"
msgid "SortOptions|Weight"
-msgstr ""
+msgstr "Peso"
msgid "Source"
msgstr "Fuente"
@@ -7659,14 +8919,17 @@ msgstr "Código fuente"
msgid "Source is not available"
msgstr ""
-msgid "Spam Logs"
+msgid "Source project cannot be found."
msgstr ""
+msgid "Spam Logs"
+msgstr "Registros de correo no deseado"
+
msgid "Spam and Anti-bot Protection"
-msgstr ""
+msgstr "Protección Anti-Spam y Anti-Bot"
msgid "Specific Runners"
-msgstr ""
+msgstr "Ejecutores específicos"
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr "Proyectos favoritos"
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar una %{new_merge_request} con estos cambios"
@@ -7719,35 +8991,62 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
+msgstr "Fecha de inicio"
+
+msgid "Start discussion"
msgstr ""
-msgid "Start the Runner!"
+msgid "Start discussion & close %{noteable_name}"
msgstr ""
-msgid "Start your trial"
+msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start the Runner!"
+msgstr "¡Inicie el ejecutor!"
+
+msgid "Start your trial"
+msgstr "Comience su prueba gratuita"
+
msgid "Started"
+msgstr "Iniciado"
+
+msgid "Started %{startsIn}"
msgstr ""
-msgid "Starts at (UTC)"
+msgid "Starting..."
msgstr ""
-msgid "State your message to activate"
+msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at (UTC)"
+msgstr "Comienza a las (UTC)"
+
+msgid "State your message to activate"
+msgstr "Indique su mensaje para activar"
+
msgid "Status"
+msgstr "Estado"
+
+msgid "Status:"
msgstr ""
-msgid "Stop environment"
+msgid "Stop Terminal"
msgstr ""
+msgid "Stop environment"
+msgstr "Detener este entorno"
+
msgid "Stop impersonation"
msgstr ""
msgid "Stop this environment"
-msgstr ""
+msgstr "Detener este entorno"
msgid "Stopped"
msgstr "Detenido"
@@ -7755,94 +9054,188 @@ msgstr "Detenido"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
-msgid "Storage"
+msgid "Stopping..."
msgstr ""
+msgid "Storage"
+msgstr "Almacenamiento"
+
msgid "Storage:"
-msgstr ""
+msgstr "Almacenamiento:"
msgid "Subgroups"
msgstr "Sub-grupos"
msgid "Subgroups and projects"
-msgstr ""
+msgstr "Subgrupos y proyectos"
msgid "Submit as spam"
+msgstr "Enviar como correo no deseado"
+
+msgid "Submit feedback"
msgstr ""
msgid "Submit review"
-msgstr ""
+msgstr "Enviar para revisión"
msgid "Submit search"
-msgstr ""
+msgstr "Enviar búsqueda"
msgid "Subscribe"
-msgstr ""
+msgstr "Suscrípción"
msgid "Subscribe at group level"
-msgstr ""
+msgstr "Suscribir a nivel de grupo"
msgid "Subscribe at project level"
+msgstr "Suscribir a nivel de proyecto"
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
msgstr ""
msgid "Subscribed"
+msgstr "Suscrito"
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
msgstr "Cambiar rama/etiqueta"
msgid "Sync information"
-msgstr ""
+msgstr "Sincronizar información"
msgid "System Hooks"
msgstr "Hooks de sistema"
msgid "System Info"
+msgstr "Información del sistema"
+
+msgid "System default (%{default})"
msgstr ""
-msgid "System header and footer:"
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
-msgstr ""
+msgstr "Métricas del sistema (personalizadas)"
msgid "System metrics (Kubernetes)"
+msgstr "Métricas del sistema (Kubernetes)"
+
+msgid "Tag"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "Etiquetas"
msgid "Tags feed"
-msgstr ""
+msgstr "Feed de tags"
msgid "Tags:"
-msgstr ""
+msgstr "Etiquetas:"
msgid "TagsPage|Browse commits"
-msgstr ""
+msgstr "Explorar commits"
msgid "TagsPage|Browse files"
-msgstr ""
+msgstr "Explorar archivos"
msgid "TagsPage|Can't find HEAD commit for this tag"
-msgstr ""
+msgstr "No se puede encontrar el commit HEAD para este tag"
msgid "TagsPage|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "TagsPage|Create tag"
-msgstr ""
+msgstr "Crear etiqueta"
msgid "TagsPage|Delete tag"
-msgstr ""
+msgstr "Eliminar etiqueta"
msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
msgstr ""
@@ -7857,43 +9250,43 @@ msgid "TagsPage|Filter by tag name"
msgstr ""
msgid "TagsPage|New Tag"
-msgstr ""
+msgstr "Nueva etiqueta"
msgid "TagsPage|New tag"
-msgstr ""
+msgstr "Nueva etiqueta"
msgid "TagsPage|Optionally, add a message to the tag."
-msgstr ""
+msgstr "Opcionalmente, añada un mensaje a la etiqueta."
msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
-msgstr ""
+msgstr "Opcionalmente, añada las notas de la versión a la etiqueta. Se almacenarán en la base de datos de GitLab y se mostrarán en la página de etiquetas."
msgid "TagsPage|Release notes"
-msgstr ""
+msgstr "Notas de la versión"
msgid "TagsPage|Repository has no tags yet."
-msgstr ""
+msgstr "El repositorio todavía no tiene etiquetas."
msgid "TagsPage|Sort by"
-msgstr ""
+msgstr "Ordenar por"
msgid "TagsPage|Tags"
-msgstr ""
+msgstr "Etiquetas"
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 "Esta etiqueta no tiene notas de la versión."
msgid "TagsPage|Use git tag command to add a new one:"
-msgstr ""
+msgstr "Utilice el comando git tag para agregar una nueva:"
msgid "TagsPage|Write your release notes or drag files here…"
-msgstr ""
+msgstr "Escriba sus notas de la versión o arrastre los archivos aquí…"
msgid "TagsPage|protected"
-msgstr ""
+msgstr "protegido"
msgid "Target Branch"
msgstr "Rama de destino"
@@ -7905,29 +9298,41 @@ msgid "Team"
msgstr "Equipo"
msgid "Template"
-msgstr ""
+msgstr "Plantilla"
msgid "Templates"
+msgstr "Plantillas"
+
+msgid "Terminal"
msgstr ""
-msgid "Terms of Service Agreement and Privacy Policy"
+msgid "Terminal for environment"
msgstr ""
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr "Términos del acuerdo de servicio y de la política de privacidad"
+
msgid "Terms of Service and Privacy Policy"
-msgstr ""
+msgstr "Términos del servicio y política de privacidad"
msgid "Test SAML SSO"
-msgstr ""
+msgstr "Prueba SAML SSO"
msgid "Test coverage parsing"
msgstr ""
msgid "Thanks! Don't show me this again"
+msgstr "¡Gracias! No mostrar esto de nuevo"
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "La etapa de incidencia muestra el tiempo que toma desde la creación de un tema hasta asignar el tema a un hito, o añadir el tema a una lista en el panel de temas. Empieza a crear temas para ver los datos de esta etapa."
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8001,19 +9409,19 @@ msgid "The repository for this project does not exist."
msgstr "El repositorio para este proyecto no existe."
msgid "The repository for this project is empty"
-msgstr ""
+msgstr "El repositorio de este proyecto está vacío"
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
-msgstr ""
+msgstr "El repositorio debe ser accesible a través de <code>http://</code>, <code>https://</code> o <code>git://</code>."
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
-msgstr ""
+msgstr "El repositorio debe ser accesible a través de <code>http: //</code>, <code>https: //</code>, <code>ssh: //</code> y <code>git: //</code>."
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "La etapa de revisión muestra el tiempo desde la creación de la solicitud de fusión hasta que los cambios se fusionaron. Los datos se añadirán automáticamente después de fusionar su primera solicitud de fusión."
msgid "The roadmap shows the progress of your epics along a timeline"
-msgstr ""
+msgstr "La hoja de ruta muestra el progreso de sus tareas épicas a lo largo de una línea de tiempo"
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "La etapa de puesta en escena muestra el tiempo entre la fusión y el despliegue de código en el entorno de producción. Los datos se añadirán automáticamente una vez que se despliega a producción por primera vez."
@@ -8042,21 +9450,39 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "El valor en el punto medio de una serie de valores observados. Por ejemplo, entre 3, 5, 9, la mediana es 5. Entre 3, 5, 7, 8, la mediana es (5 + 7) / 2 = 6."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
+msgstr "Aún no hay proyectos archivados"
+
+msgid "There are no closed issues"
msgstr ""
-msgid "There are no issues to show"
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
msgstr ""
+msgid "There are no issues to show"
+msgstr "Aún no hay incidencias que mostrar"
+
msgid "There are no labels yet"
+msgstr "Aún no hay etiquetas"
+
+msgid "There are no open issues"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open merge requests"
msgstr ""
-msgid "There are no projects shared with this group yet"
+msgid "There are no packages yet"
msgstr ""
+msgid "There are no projects shared with this group yet"
+msgstr "Aún no hay proyectos compartidos con este grupo"
+
msgid "There are no staged changes"
msgstr ""
@@ -8070,7 +9496,7 @@ msgid "There was an error deleting the todo."
msgstr ""
msgid "There was an error loading users activity calendar."
-msgstr ""
+msgstr "Se ha producido un error al cargar el calendario de actividades de los usuarios."
msgid "There was an error saving your notification settings."
msgstr ""
@@ -8079,7 +9505,7 @@ msgid "There was an error subscribing to this label."
msgstr ""
msgid "There was an error when reseting email token."
-msgstr ""
+msgstr "Se ha producido un error al restablecer el token de correo electrónico."
msgid "There was an error when subscribing to this label."
msgstr ""
@@ -8087,26 +9513,35 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "They can be managed using the %{link}."
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
+msgid "They can be managed using the %{link}."
+msgstr "Se pueden administrar usando el %{link}."
+
msgid "Third party offers"
+msgstr "Ofertas de terceros"
+
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
-msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr "Esta instancia de GitLab aún no proporciona ningún 'runner' compartido. Los administradores de instancias pueden registrar 'runner' compartidos en el área de administración."
+
msgid "This application was created by %{link_to_owner}."
-msgstr ""
+msgstr "Esta aplicación fue creada por %{link_to_owner}."
msgid "This application will be able to:"
-msgstr ""
+msgstr "Está aplicación podrá:"
msgid "This board's scope is reduced"
-msgstr ""
+msgstr "El alcance de este tablero es limitado"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
-msgstr ""
+msgstr "Esta rama ha cambiado desde que se comenzó a editar. ¿Le gustaría crear una nueva rama?"
msgid "This container registry has been scheduled for deletion."
msgstr ""
@@ -8118,22 +9553,25 @@ msgid "This date is before the start date, so this epic won't appear in the road
msgstr ""
msgid "This diff is collapsed."
+msgstr "El diff está contraído."
+
+msgid "This diff was suppressed by a .gitattributes entry."
msgstr ""
msgid "This directory"
-msgstr ""
+msgstr "Este directorio"
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr ""
+msgid "This group"
+msgstr "Este grupo"
msgid "This group does not provide any group Runners yet."
-msgstr ""
+msgstr "Este grupo aún no proporciona ningún grupo de 'runners'."
msgid "This is a confidential issue."
-msgstr ""
+msgstr "Esta incidencia es confidencial."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
@@ -8142,34 +9580,34 @@ msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This issue is confidential"
-msgstr ""
+msgstr "Esta incidencia es confidencial"
msgid "This issue is confidential and locked."
-msgstr ""
+msgstr "Esta incidencia es confidencial y está bloqueada."
msgid "This issue is locked."
-msgstr ""
+msgstr "Esta incidencia está bloqueada."
msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
-msgstr ""
+msgstr "Este trabajo depende de que un usuario active su proceso. A menudo se utilizan para implementar código en entornos de producción"
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
msgstr ""
msgid "This job does not have a trace."
-msgstr ""
+msgstr "Esta tarea no tiene seguimiento."
msgid "This job has been canceled"
-msgstr ""
+msgstr "Se ha cancelado esta tarea"
msgid "This job has been skipped"
-msgstr ""
+msgstr "Se ha omitido esta tarea"
msgid "This job has not been triggered yet"
-msgstr ""
+msgstr "Esta tarea todavía no se ha activado"
msgid "This job has not started yet"
-msgstr ""
+msgstr "Todavia no ha comenzado la tarea"
msgid "This job is an out-of-date deployment to %{environmentLink}."
msgstr ""
@@ -8189,26 +9627,26 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
msgstr ""
msgid "This job requires a manual action"
-msgstr ""
+msgstr "Este trabajo requiere una acción manual"
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Esto significa que no puede enviar código hasta que cree un repositorio vacío o importe uno existente."
msgid "This merge request is locked."
-msgstr ""
+msgstr "Este merge request está bloqueado."
msgid "This option is disabled as you don't have write permissions for the current branch"
msgstr ""
@@ -8222,9 +9660,18 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
-msgid "This project"
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
msgstr ""
+msgid "This project"
+msgstr "Este proyecto"
+
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
@@ -8235,7 +9682,7 @@ msgid "This project does not have billing enabled. To create a cluster, <a href=
msgstr ""
msgid "This repository"
-msgstr ""
+msgstr "Este repositorio"
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
@@ -8249,11 +9696,11 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
-msgstr ""
+msgstr "El usuario no tiene ninguna identidad"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8280,19 +9727,19 @@ msgid "Time between merge request creation and merge/close"
msgstr "Tiempo entre la creación de la solicitud de fusión y la integración o cierre de ésta"
msgid "Time estimate"
-msgstr ""
+msgstr "Tiempo estimado"
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
msgid "Time remaining"
-msgstr ""
+msgstr "Tiempo restante"
msgid "Time spent"
-msgstr ""
+msgstr "Tiempo dedicado"
msgid "Time tracking"
-msgstr ""
+msgstr "Seguimiento de tiempo"
msgid "Time until first merge request"
msgstr "Tiempo hasta la primera solicitud de fusión"
@@ -8301,10 +9748,10 @@ msgid "TimeTrackingEstimated|Est"
msgstr ""
msgid "TimeTracking|Estimated:"
-msgstr ""
+msgstr "Estimado:"
msgid "TimeTracking|Spent"
-msgstr ""
+msgstr "Gastado"
msgid "Timeago|%s days ago"
msgstr "hace %s días"
@@ -8313,7 +9760,7 @@ msgid "Timeago|%s days remaining"
msgstr "%s días restantes"
msgid "Timeago|%s hours ago"
-msgstr ""
+msgstr "hace %s horas"
msgid "Timeago|%s hours remaining"
msgstr "%s horas restantes"
@@ -8331,7 +9778,7 @@ msgid "Timeago|%s months remaining"
msgstr "%s meses restantes"
msgid "Timeago|%s seconds ago"
-msgstr ""
+msgstr "hace %s segundos"
msgid "Timeago|%s seconds remaining"
msgstr "%s segundos restantes"
@@ -8349,37 +9796,37 @@ msgid "Timeago|%s years remaining"
msgstr "%s años restantes"
msgid "Timeago|1 day ago"
-msgstr ""
+msgstr "hace 1 día"
msgid "Timeago|1 day remaining"
msgstr "1 día restante"
msgid "Timeago|1 hour ago"
-msgstr ""
+msgstr "hace 1 hora"
msgid "Timeago|1 hour remaining"
msgstr "1 hora restante"
msgid "Timeago|1 minute ago"
-msgstr ""
+msgstr "hace 1 minuto"
msgid "Timeago|1 minute remaining"
msgstr "1 minuto restante"
msgid "Timeago|1 month ago"
-msgstr ""
+msgstr "hace 1 mes"
msgid "Timeago|1 month remaining"
msgstr "1 mes restante"
msgid "Timeago|1 week ago"
-msgstr ""
+msgstr "hace 1 semana"
msgid "Timeago|1 week remaining"
msgstr "1 semana restante"
msgid "Timeago|1 year ago"
-msgstr ""
+msgstr "hace 1 año"
msgid "Timeago|1 year remaining"
msgstr "1 año restante"
@@ -8427,13 +9874,13 @@ msgid "Timeago|in 1 year"
msgstr "en 1 año"
msgid "Timeago|just now"
-msgstr ""
+msgstr "solo ahora"
msgid "Timeago|right now"
-msgstr ""
+msgstr "justo ahora"
msgid "Timeout"
-msgstr ""
+msgstr "Tiempo de espera"
msgid "Time|hr"
msgid_plural "Time|hrs"
@@ -8449,12 +9896,21 @@ msgid "Time|s"
msgstr "s"
msgid "Tip:"
-msgstr ""
+msgstr "Sugerencia:"
msgid "Title"
+msgstr "Título"
+
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
msgstr ""
msgid "To GitLab"
+msgstr "A GitLab"
+
+msgid "To access this domain create a new DNS record"
msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,37 +9985,46 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
-msgid "To this GitLab instance"
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
msgstr ""
+msgid "To this GitLab instance"
+msgstr "A esta instancia de GitLab"
+
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
-msgid "To widen your search, change or remove filters."
+msgid "To widen your search, change or remove filters above"
msgstr ""
+msgid "To widen your search, change or remove filters."
+msgstr "Para ampliar la búsqueda, cambie o elimine filtros."
+
msgid "Today"
-msgstr ""
+msgstr "Hoy"
msgid "Todo"
-msgstr ""
+msgstr "Tareas pendientes"
msgid "Todos"
-msgstr ""
+msgstr "Tareas pendientes"
msgid "Toggle Sidebar"
+msgstr "Ocultar barra lateral"
+
+msgid "Toggle comments for this file"
msgstr ""
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8560,16 +10040,16 @@ msgid "ToggleButton|Toggle Status: ON"
msgstr ""
msgid "Token"
-msgstr ""
+msgstr "Token"
msgid "Tomorrow"
-msgstr ""
+msgstr "Mañana"
msgid "Too many changes to show."
-msgstr ""
+msgstr "Hay demasiados cambios para mostrar."
msgid "Total Contributions"
-msgstr ""
+msgstr "Contribuciones totales"
msgid "Total Time"
msgstr "Tiempo Total"
@@ -8578,13 +10058,13 @@ msgid "Total test time for all commits/merges"
msgstr "Tiempo total de pruebas para todos los cambios o integraciones"
msgid "Total: %{total}"
-msgstr ""
+msgstr "Total: %{total}"
msgid "Tracing"
-msgstr ""
+msgstr "Seguimiento"
msgid "Track activity with Contribution Analytics."
-msgstr ""
+msgstr "Monitorizar la actividad con Contribution Analytics."
msgid "Track groups of issues that share a theme, across projects and milestones"
msgstr ""
@@ -8593,13 +10073,10 @@ msgid "Track time with quick actions"
msgstr ""
msgid "Tree view"
-msgstr ""
+msgstr "Vista de árbol"
msgid "Trending"
-msgstr ""
-
-msgid "Trigger"
-msgstr ""
+msgstr "Tendencia"
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8608,6 +10085,12 @@ msgid "Trigger pipelines when branches or tags are updated from the upstream rep
msgstr ""
msgid "Trigger this manual action"
+msgstr "Disparar esta acción manual"
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
@@ -8617,27 +10100,33 @@ msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
msgid "Try again"
+msgstr "Inténtelo de nuevo"
+
+msgid "Try again?"
msgstr ""
msgid "Try all GitLab has to offer for 30 days."
+msgstr "Pruebe todo lo que GitLab tiene para ofrecer durante 30 días."
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
-msgstr ""
+msgstr "Twitter"
msgid "Two-factor authentication"
msgstr ""
msgid "Type"
-msgstr ""
+msgstr "Tipo"
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,11 +10135,17 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
+msgstr "Deshacer"
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
msgid "Unknown"
-msgstr ""
+msgstr "Desconocido"
msgid "Unlock"
msgstr "Desbloquear"
@@ -8689,43 +10184,52 @@ msgid "Unstar"
msgstr "No Destacar"
msgid "Unsubscribe"
-msgstr ""
+msgstr "Eliminar suscripción"
msgid "Unsubscribe at group level"
-msgstr ""
+msgstr "Eliminar suscripción a nivel de grupo"
msgid "Unsubscribe at project level"
+msgstr "Eliminar suscripción a nivel de proyecto"
+
+msgid "Unsubscribe from %{type}"
msgstr ""
msgid "Unverified"
-msgstr ""
+msgstr "Sin verificar"
msgid "Up to date"
-msgstr ""
+msgstr "Actualizado"
msgid "Upcoming"
msgstr ""
msgid "Update"
+msgstr "Actualizar"
+
+msgid "Update failed"
msgstr ""
msgid "Update now"
-msgstr ""
+msgstr "Actualizar ahora"
msgid "Update your group name, description, avatar, and visibility."
-msgstr ""
+msgstr "Actualice el nombre de su grupo, su descripción, su avatar y su visibilidad."
msgid "Updating"
+msgstr "Actualizando"
+
+msgid "Upgrade plan to unlock Canary Deployments feature"
msgstr ""
msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr ""
+msgstr "Actualice su plan para activar la búsqueda global avanzada."
msgid "Upgrade your plan to activate Contribution Analytics."
msgstr ""
msgid "Upgrade your plan to activate Group Webhooks."
-msgstr ""
+msgstr "Actualice su plan para activar la herramienta Group Webhooks."
msgid "Upgrade your plan to activate Issue weight."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "Subir nuevo archivo"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "Subir archivo"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "Hacer clic para subir"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr "Utiliza tu configuración de notificación global"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8797,24 +10322,33 @@ msgid "UserProfile|Already reported for abuse"
msgstr ""
msgid "UserProfile|Contributed projects"
-msgstr ""
+msgstr "Proyectos contribuidos"
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
+msgstr "Usuarios"
+
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables"
+msgid "Validate"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,29 +10411,41 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
+msgstr "Información de verificación"
+
+msgid "Verification status"
msgstr ""
msgid "Verified"
-msgstr ""
+msgstr "Verificado"
msgid "Version"
-msgstr ""
+msgstr "Versión"
msgid "View %{alerts}"
-msgstr ""
+msgstr "Ver %{alerts}"
msgid "View app"
+msgstr "Ver aplicación"
+
+msgid "View deployment"
msgstr ""
-msgid "View documentation"
+msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr "Ver documentación"
+
msgid "View epics list"
-msgstr ""
+msgstr "Ver lista de tareas épicas"
msgid "View file @ "
msgstr "Ver archivo @ "
@@ -8881,43 +10454,46 @@ msgid "View group labels"
msgstr ""
msgid "View issue"
-msgstr ""
+msgstr "Ver incidencia"
msgid "View it on GitLab"
-msgstr ""
+msgstr "Ver en GitLab"
msgid "View jobs"
-msgstr ""
+msgstr "Ver trabajos"
msgid "View labels"
-msgstr ""
+msgstr "Ver etiquetas"
msgid "View log"
-msgstr ""
+msgstr "Ver log"
msgid "View open merge request"
msgstr "Ver solicitud de fusión abierta"
msgid "View project labels"
-msgstr ""
+msgstr "Ver etiquetas de proyectos"
msgid "View replaced file @ "
msgstr "Ver archivo reemplazado @ "
msgid "View the documentation"
+msgstr "Ver documentación"
+
+msgid "Viewing commit"
msgstr ""
msgid "Visibility and access controls"
-msgstr ""
+msgstr "Visibilidad y control de acceso"
msgid "Visibility level"
-msgstr ""
+msgstr "Nivel de visibilidad"
msgid "Visibility level:"
-msgstr ""
+msgstr "Nivel de visibilidad:"
msgid "Visibility:"
-msgstr ""
+msgstr "Visibilidad:"
msgid "VisibilityLevel|Internal"
msgstr "Interno"
@@ -8931,38 +10507,59 @@ msgstr "Público"
msgid "VisibilityLevel|Unknown"
msgstr "Desconocido"
-msgid "Vulnerability|Class"
+msgid "Vulnerability Chart"
msgstr ""
-msgid "Vulnerability|Confidence"
+msgid "Vulnerability List"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr "Clase"
+
+msgid "Vulnerability|Confidence"
+msgstr "Confianza"
+
msgid "Vulnerability|Description"
-msgstr ""
+msgstr "Descripción"
msgid "Vulnerability|File"
-msgstr ""
+msgstr "Archivo"
msgid "Vulnerability|Identifiers"
-msgstr ""
+msgstr "Identificadores"
msgid "Vulnerability|Instances"
-msgstr ""
+msgstr "Instancias"
msgid "Vulnerability|Links"
-msgstr ""
+msgstr "Enlaces"
msgid "Vulnerability|Project"
+msgstr "Proyecto"
+
+msgid "Vulnerability|Report Type"
msgstr ""
msgid "Vulnerability|Severity"
+msgstr "Severidad"
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr "¿Quieres ver los datos? Por favor pide acceso al administrador."
+
+msgid "We can't find an epic that matches what you are looking for."
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "We can't find an issue that matches what you are looking for."
msgstr ""
-msgid "Want to see the data? Please ask an administrator for access."
-msgstr "¿Quieres ver los datos? Por favor pide acceso al administrador."
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -8970,56 +10567,65 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "No hay suficientes datos para mostrar en esta etapa."
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
+msgstr "Web IDE"
+
+msgid "Web Terminal"
msgstr ""
msgid "Web terminal"
-msgstr ""
+msgstr "Terminal web"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
msgid "Weeks"
-msgstr ""
+msgstr "Semanas"
msgid "Weight"
-msgstr ""
+msgstr "Peso"
msgid "Weight %{weight}"
-msgstr ""
+msgstr "Peso %{weight}"
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
-msgstr ""
+msgstr "Cuando está habilitado, los usuarios no pueden utilizar GitLab hasta que se hayan aceptado los términos de uso."
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
-msgid "Who can see this group?"
+msgid "When:"
msgstr ""
+msgid "Who can see this group?"
+msgstr "¿Quién puede ver este grupo?"
+
msgid "Who will be able to see this group?"
-msgstr ""
+msgstr "¿Quién podrá ver a este grupo?"
msgid "Wiki"
msgstr "Wiki"
msgid "WikiClone|Clone your wiki"
-msgstr ""
+msgstr "Clonar su wiki"
msgid "WikiClone|Git Access"
-msgstr ""
+msgstr "Acceso Git"
msgid "WikiClone|Install Gollum"
-msgstr ""
+msgstr "Instalar Gollum"
msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
-msgstr ""
+msgstr "Se recomienda instalar %{markdown} para que las características de GFM se procesen localmente:"
msgid "WikiClone|Start Gollum and edit locally"
msgstr ""
@@ -9115,30 +10721,33 @@ msgid "WikiPage|Write your content or drag files here…"
msgstr ""
msgid "Wiki|Create Page"
-msgstr ""
+msgstr "Crear página"
msgid "Wiki|Create page"
-msgstr ""
+msgstr "Crear página"
msgid "Wiki|Edit Page"
-msgstr ""
+msgstr "Editar página"
msgid "Wiki|More Pages"
-msgstr ""
+msgstr "Más páginas"
msgid "Wiki|New page"
-msgstr ""
+msgstr "Nueva página"
msgid "Wiki|Page history"
-msgstr ""
+msgstr "Historial de página"
msgid "Wiki|Page version"
-msgstr ""
+msgstr "Versión de la página"
msgid "Wiki|Pages"
-msgstr ""
+msgstr "Páginas"
msgid "Wiki|Wiki Pages"
+msgstr "Páginas del Wiki"
+
+msgid "Will deploy to"
msgstr ""
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
@@ -9147,16 +10756,25 @@ msgstr ""
msgid "Withdraw Access Request"
msgstr "Retirar Solicitud de Acceso"
-msgid "Yes"
+msgid "Write a comment or drag your files here…"
msgstr ""
-msgid "Yes, add it"
+msgid "Write milestone description..."
msgstr ""
+msgid "Yes"
+msgstr "Si"
+
+msgid "Yes, add it"
+msgstr "Si, hazlo"
+
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
msgid "Yesterday"
+msgstr "Ayer"
+
+msgid "You"
msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr "Solo puedes agregar archivos cuando estás en una rama"
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr "Has alcanzado el límite de tu proyecto"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr "Necesitas permisos."
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9292,27 +10931,36 @@ msgid "You're receiving this email because of your account on %{host}. %{manage_
msgstr ""
msgid "YouTube"
+msgstr "YouTube"
+
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your Groups"
-msgstr ""
+msgstr "Sus grupos"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "La información del cluster de Kubernetes en esta página aún se puede editar, pero se recomienda desactivarla y modificar"
msgid "Your Projects (default)"
-msgstr ""
+msgstr "Sus proyectos (por defecto)"
msgid "Your Projects' Activity"
-msgstr ""
+msgstr "Actividad de sus proyectos"
msgid "Your Todos"
+msgstr "Sus tareas pendientes"
+
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
msgid "Your applications (%{size})"
-msgstr ""
+msgstr "Sus aplicaciones (%{size})"
msgid "Your authorized applications"
+msgstr "Sus aplicaciones autorizadas"
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
@@ -9322,55 +10970,73 @@ msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
msgid "Your changes have been saved"
-msgstr ""
+msgstr "Se han guardado sus cambios"
msgid "Your comment will not be visible to the public."
msgstr "Tus comentarios no serán visibles al público."
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "Tus grupos"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "Tu nombre"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr "Tus proyectos"
msgid "a deleted user"
-msgstr ""
+msgstr "un usuario eliminado"
msgid "ago"
+msgstr "hace"
+
+msgid "allowed to fail"
msgstr ""
msgid "among other things"
-msgstr ""
+msgstr "entre otras cosas"
msgid "assign yourself"
+msgstr "asignar a uno mismo"
+
+msgid "attach a new file"
msgstr ""
msgid "branch name"
msgstr "nombre de la rama"
msgid "by"
-msgstr ""
+msgstr "por"
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}Aprenda más sobre el analísis de contenedores %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}Aprenda más sobre DAST %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}Aprenda más sobre el análisis de dependencias %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}Aprenda más sobre SAST %{linkEndTag}"
msgid "ciReport|%{namespace} is affected by %{vulnerability}."
-msgstr ""
+msgstr "%{namespace} está afectado por %{vulnerability}."
msgid "ciReport|%{remainingPackagesCount} more"
-msgstr ""
+msgstr "%{remainingPackagesCount} más"
msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
@@ -9408,73 +11074,82 @@ msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
msgid "ciReport|%{reportType} is loading"
-msgstr ""
+msgstr "%{reportType} está cargando"
msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
msgid "ciReport|(errors when loading results)"
-msgstr ""
+msgstr "(se han producido errores al cargar resultados)"
msgid "ciReport|(is loading)"
-msgstr ""
+msgstr "(está cargando)"
msgid "ciReport|(is loading, errors when loading results)"
-msgstr ""
+msgstr "(está cargando, se han producido errores al cargar resultados)"
msgid "ciReport|Class"
-msgstr ""
+msgstr "Clase"
msgid "ciReport|Code quality"
-msgstr ""
+msgstr "Calidad del código"
msgid "ciReport|Confidence"
-msgstr ""
+msgstr "Confianza"
msgid "ciReport|Container scanning"
-msgstr ""
+msgstr "Análisis de contenedores"
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
-msgstr ""
+msgstr "El análisis de contenedores detecta vulnerabilidades conocidas en sus imágenes de Docker."
msgid "ciReport|DAST"
+msgstr "DAST"
+
+msgid "ciReport|Dependency Scanning"
msgstr ""
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
-msgstr ""
+msgstr "El análisis de dependencias detecta vulnerabilidades conocidas en las dependencias de su código fuente."
msgid "ciReport|Dependency scanning"
-msgstr ""
+msgstr "Escaneo de seguridad"
msgid "ciReport|Description"
-msgstr ""
+msgstr "Descripción"
msgid "ciReport|Dismiss vulnerability"
-msgstr ""
+msgstr "Descartar vulnerabilidad"
msgid "ciReport|Dismissed by"
+msgstr "Descartado por"
+
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
-msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgid "ciReport|Download patch"
msgstr ""
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr "Dynamic Application Security Testing (DAST) detecta vulnerabilidades conocidas en su código fuente."
+
msgid "ciReport|Failed to load %{reportName} report"
-msgstr ""
+msgstr "Se ha producido un error al cargar el informe %{reportName}"
msgid "ciReport|File"
-msgstr ""
+msgstr "Archivo"
msgid "ciReport|Fixed:"
-msgstr ""
+msgstr "Solucionado:"
msgid "ciReport|Identifiers"
-msgstr ""
+msgstr "Identificadores"
msgid "ciReport|Instances"
-msgstr ""
+msgstr "Instancias"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
-msgstr ""
+msgstr "Obtenga más información sobre cómo interactuar con los informes de seguridad (Alpha)."
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
@@ -9493,49 +11168,49 @@ msgid "ciReport|License management detected no new licenses"
msgstr ""
msgid "ciReport|Links"
-msgstr ""
+msgstr "Enlaces"
msgid "ciReport|Loading %{reportName} report"
-msgstr ""
+msgstr "Cargando el informe %{reportName}"
msgid "ciReport|Manage licenses"
-msgstr ""
+msgstr "Administrar licencias"
msgid "ciReport|Method"
-msgstr ""
+msgstr "Método"
msgid "ciReport|Namespace"
-msgstr ""
+msgstr "Espacio de nombres"
msgid "ciReport|No changes to code quality"
-msgstr ""
+msgstr "No hay cambios en la calidad del código"
msgid "ciReport|No changes to performance metrics"
-msgstr ""
+msgstr "No hay cambios en las métricas de rendimiento"
msgid "ciReport|Performance metrics"
-msgstr ""
+msgstr "Métricas de rendimiento"
msgid "ciReport|Revert dismissal"
msgstr ""
msgid "ciReport|SAST"
-msgstr ""
+msgstr "SAST"
msgid "ciReport|Security scanning"
-msgstr ""
+msgstr "Análisis de seguridad"
msgid "ciReport|Security scanning failed loading any results"
-msgstr ""
+msgstr "El análisis de seguridad falló al cargar los resultados"
msgid "ciReport|Severity"
-msgstr ""
+msgstr "Severidad"
msgid "ciReport|Solution"
-msgstr ""
+msgstr "Solución"
msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
-msgstr ""
+msgstr "Static Application Security Testing (SAST) detecta vulnerabilidades conocidas en su código fuente."
msgid "ciReport|There was an error creating the issue. Please try again."
msgstr ""
@@ -9544,13 +11219,13 @@ msgid "ciReport|There was an error dismissing the vulnerability. Please try agai
msgstr ""
msgid "ciReport|There was an error loading DAST report"
-msgstr ""
+msgstr "Se ha producido un error al cargar el informe SAST."
msgid "ciReport|There was an error loading SAST report"
-msgstr ""
+msgstr "Se ha producido un error al cargar el informe SAST."
msgid "ciReport|There was an error loading container scanning report"
-msgstr ""
+msgstr "Se ha producido un error al cargar el informe de escaneo de contenedores."
msgid "ciReport|There was an error loading dependency scanning report"
msgstr ""
@@ -9567,12 +11242,15 @@ msgstr[0] ""
msgstr[1] ""
msgid "ciReport|View full report"
-msgstr ""
+msgstr "Ver informe completo"
msgid "ciReport|on pipeline"
-msgstr ""
+msgstr "en el pipeline"
msgid "command line instructions"
+msgstr "instrucciones de la línea de comando"
+
+msgid "commented on %{link_to_project}"
msgstr ""
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
@@ -9582,87 +11260,143 @@ msgid "confidentiality|You are going to turn on the confidentiality. This means
msgstr ""
msgid "connecting"
-msgstr ""
+msgstr "conectando"
msgid "could not read private key, is the passphrase correct?"
-msgstr ""
+msgstr "no se ha podido leer la clave privada, ¿La contraseña es correcta?"
msgid "customize"
-msgstr ""
+msgstr "personalizar"
msgid "day"
msgid_plural "days"
msgstr[0] "día"
msgstr[1] "días"
-msgid "deploy token"
+msgid "deleted"
msgstr ""
+msgid "deploy token"
+msgstr "desplegar token"
+
msgid "disabled"
-msgstr ""
+msgstr "deshabilitado"
+
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
msgid "done"
-msgstr ""
+msgstr "hecho"
msgid "draft"
msgid_plural "drafts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "borrador"
+msgstr[1] "borradores"
msgid "enabled"
+msgstr "habilitado"
+
+msgid "epic"
msgstr ""
-msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgid "error"
msgstr ""
-msgid "for this project"
+msgid "error code:"
msgstr ""
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr "%{slash_command} actualizará la hora estimada con el último comando."
+
+msgid "for this project"
+msgstr "para este proyecto"
+
msgid "from"
+msgstr "de"
+
+msgid "group"
msgstr ""
msgid "help"
-msgstr ""
+msgstr "ayuda"
msgid "here"
+msgstr "aquí"
+
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
msgstr ""
msgid "https://your-bitbucket-server"
+msgstr "https://tu-servidor-bitbucket"
+
+msgid "image diff"
msgstr ""
msgid "import flow"
msgstr ""
msgid "importing"
+msgstr "importando"
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
msgstr ""
msgid "instance completed"
msgid_plural "instances completed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "instancia completada"
+msgstr[1] "instancias completadas"
msgid "is invalid because there is downstream lock"
-msgstr ""
+msgstr "no es válido porque hay un bloqueo en sentido descendente"
msgid "is invalid because there is upstream lock"
-msgstr ""
+msgstr "no es válido porque hay un bloqueo en sentido ascendente"
msgid "is not a valid X509 certificate."
+msgstr "no es un certificado X509 válido."
+
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
msgstr ""
msgid "issue boards"
+msgstr "tablero de incidencias"
+
+msgid "it is stored externally"
msgstr ""
-msgid "latest deployment"
+msgid "it is stored in LFS"
msgstr ""
-msgid "latest version"
+msgid "it is too large"
msgstr ""
-msgid "license management"
+msgid "latest"
msgstr ""
+msgid "latest deployment"
+msgstr "último despliegue"
+
+msgid "latest version"
+msgstr "última versión"
+
+msgid "license management"
+msgstr "gestión de licencias"
+
msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr "bloqueado por %{path_lock_user_name} %{created_at}"
+
+msgid "manual"
msgstr ""
msgid "merge request"
@@ -9670,7 +11404,19 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr "Restaure o use una rama diferente %{missingBranchName}"
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
@@ -9683,31 +11429,31 @@ msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasis
msgstr ""
msgid "mrWidget|Add approval"
-msgstr ""
+msgstr "Añadir aprobación"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
msgid "mrWidget|Approve"
-msgstr ""
+msgstr "Aprobar"
msgid "mrWidget|Approved by"
-msgstr ""
+msgstr "Aprobado por"
msgid "mrWidget|Cancel automatic merge"
msgstr ""
msgid "mrWidget|Check out branch"
-msgstr ""
+msgstr "Check-out"
msgid "mrWidget|Checking ability to merge automatically"
msgstr ""
@@ -9719,76 +11465,79 @@ msgid "mrWidget|Cherry-pick this merge request in a new merge request"
msgstr ""
msgid "mrWidget|Closed"
-msgstr ""
+msgstr "Cerrado"
msgid "mrWidget|Closed by"
-msgstr ""
+msgstr "Cerrado por"
msgid "mrWidget|Closes"
-msgstr ""
+msgstr "Cierra"
msgid "mrWidget|Create an issue to resolve them later"
+msgstr "Crear una incidencia para resolverla posteriormente"
+
+msgid "mrWidget|Delete source branch"
msgstr ""
msgid "mrWidget|Deployment statistics are not available currently"
-msgstr ""
+msgstr "Las estadísticas de los despliegues no están disponibles actualmente"
msgid "mrWidget|Did not close"
-msgstr ""
+msgstr "No se cerró"
msgid "mrWidget|Email patches"
-msgstr ""
+msgstr "Enviar parches por correo electrónico"
msgid "mrWidget|Failed to load deployment statistics"
-msgstr ""
+msgstr "Error al cargar las estadísticas de despliegue"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr ""
+msgstr "No es posible realizar un merge fast-forward. Para poder hacer un merge de esta solicitud, es necesario hacer rebase localmente."
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
-msgstr ""
+msgstr "Si el branch %{branch} existe en su repositorio local, puede hacer un merge de la solicitud de merge request manualmente utilizando la línea de comandos"
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
-msgstr ""
+msgstr "Si el branch %{missingBranchName} existe en su repositorio local, puede hacer un merge de la solicitud de merge request manualmente utilizando la línea de comandos"
msgid "mrWidget|Loading deployment statistics"
-msgstr ""
+msgstr "Cargando las estadísticas de los despliegues"
msgid "mrWidget|Mentions"
-msgstr ""
+msgstr "Menciones"
msgid "mrWidget|Merge"
-msgstr ""
+msgstr "Merge"
msgid "mrWidget|Merge failed."
-msgstr ""
+msgstr "Merge fallido."
msgid "mrWidget|Merge locally"
-msgstr ""
+msgstr "Merge local"
msgid "mrWidget|Merge request approved"
-msgstr ""
+msgstr "Solicitud de merge request aprobada"
msgid "mrWidget|Merge request approved; you can approve additionally"
msgstr ""
msgid "mrWidget|Merged by"
-msgstr ""
+msgstr "Merge realizado por"
msgid "mrWidget|No Approval required"
-msgstr ""
+msgstr "No es necesaria la aprobación"
msgid "mrWidget|No Approval required; you can still approve"
-msgstr ""
+msgstr "No es necesaria una aprobación; todavía puede aprobarlo"
msgid "mrWidget|Open in Web IDE"
-msgstr ""
+msgstr "Abrir en Web IDE"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
+msgstr "pipeline bloqueado. El pipeline para este merge request requiere la ejecución una acción manualmente para continuar"
msgid "mrWidget|Plain diff"
-msgstr ""
+msgstr "Diff normal"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9816,16 +11559,16 @@ msgstr ""
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Requiere una aprobación más"
+msgstr[1] "Requiere %d aprobaciones más"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "requiere 1 aprobación más de"
+msgstr[1] "requiere %d aprobaciones más de"
msgid "mrWidget|Resolve conflicts"
-msgstr ""
+msgstr "Resolver conflictos"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
msgstr ""
@@ -9837,7 +11580,7 @@ msgid "mrWidget|Revert this merge request in a new merge request"
msgstr ""
msgid "mrWidget|Set by"
-msgstr ""
+msgstr "Establecido por"
msgid "mrWidget|The changes were merged into"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9882,41 +11628,53 @@ msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
-msgstr ""
+msgstr "Este proyecto está archivado, se ha deshabilitado el acceso de escritura"
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
msgstr ""
msgid "mrWidget|command line"
-msgstr ""
+msgstr "línea de comandos"
msgid "mrWidget|into"
-msgstr ""
+msgstr "en"
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
msgid "n/a"
-msgstr ""
+msgstr "n/a"
msgid "new merge request"
msgstr "nueva solicitud de fusión"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "correos electrónicos de notificación"
-msgid "or"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
msgstr ""
+msgid "or"
+msgstr "o"
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -9933,63 +11691,111 @@ msgstr "contraseña"
msgid "personal access token"
msgstr "token de acceso personal"
-msgid "private key does not match certificate."
+msgid "private"
msgstr ""
+msgid "private key does not match certificate."
+msgstr "la clave privada no coincide con el certificado."
+
msgid "project"
msgid_plural "projects"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "proyecto"
+msgstr[1] "proyectos"
-msgid "remaining"
+msgid "quick actions"
msgstr ""
-msgid "remove"
+msgid "register"
msgstr ""
+msgid "remaining"
+msgstr "restante"
+
+msgid "remove"
+msgstr "eliminar"
+
msgid "remove due date"
-msgstr ""
+msgstr "eliminar la fecha de vencimiento"
msgid "remove weight"
+msgstr "eliminar el peso"
+
+msgid "rendered diff"
msgstr ""
msgid "reply"
msgid_plural "replies"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "respuesta"
+msgstr[1] "respuestas"
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
msgid "source"
+msgstr "origen"
+
+msgid "source diff"
msgstr ""
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
-msgstr ""
+msgstr "%{slash_command} actualizará la suma del tiempo empleado."
msgid "started"
+msgstr "iniciado"
+
+msgid "stuck"
msgstr ""
-msgid "this document"
+msgid "syntax is correct"
msgstr ""
+msgid "syntax is incorrect"
+msgstr ""
+
+msgid "this document"
+msgstr "este documento"
+
msgid "to help your contributors communicate effectively!"
+msgstr "¡Para ayudar a sus colaboradores a comunicarse de manera efectiva!"
+
+msgid "triggered"
msgstr ""
-msgid "toggle collapse"
+msgid "updated"
msgstr ""
msgid "username"
msgstr "usuario"
msgid "uses Kubernetes clusters to deploy your code!"
+msgstr "¡Utilizar los clústeres de Kubernetes para implementar tu código!"
+
+msgid "verify ownership"
msgstr ""
msgid "view it on GitLab"
+msgstr "ver en GitLab"
+
+msgid "view the blob"
msgstr ""
msgid "with %{additions} additions, %{deletions} deletions."
-msgstr ""
+msgstr "con %{additions} adiciones, %{deletions} eliminaciones."
msgid "within %d minute "
msgid_plural "within %d minutes "
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "dentro de un %d minuto"
+msgstr[1] "dentro de %d minutos "
+
+msgid "yaml invalid"
+msgstr ""
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 849926d8ae2..ee015172f6d 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: et\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:22\n"
+"PO-Revision-Date: 2019-02-11 08:14\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 39e45baf002..c943b2814a3 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: fil\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:22\n"
+"PO-Revision-Date: 2019-02-11 08:14\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 177570cc590..83e62a5f9de 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:23\n"
+"PO-Revision-Date: 2019-02-11 08:14\n"
msgid " Status"
msgstr " Statut"
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] " amélioré sur %d point"
msgstr[1] " amélioré sur %d points"
-msgid "\"%{query}\" in projects"
-msgstr "« %{query} » dans les projets"
+msgid " or "
+msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] "%d ajout"
-msgstr[1] "%d ajouts"
+msgid " or <#epic id>"
+msgstr ""
+
+msgid " or <#issue id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] "%d fichier modifié"
-msgstr[1] "%d fichiers modifiés"
+msgid "\"%{query}\" in projects"
+msgstr "« %{query} » dans les projets"
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] "%d commit de retard"
msgstr[1] "%d commits de retard"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] "%d supprimé"
-msgstr[1] "%d supprimés"
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] "%d ticket"
msgstr[1] "%d tickets"
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d couche"
@@ -124,6 +126,9 @@ msgstr "%{counter_storage} (%{counter_repositories} dépôts, %{counter_build_ar
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr "%{filePath} supprimé"
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "Les %{group_docs_link_start}groupes%{group_docs_link_end} vous permettent de gérer plusieurs projets et d’y collaborer. Les membres d’un groupe ont accès à tous ses projets."
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} sera supprimé ! Êtesâ€vous sûr ?"
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Démarré"
@@ -158,9 +169,6 @@ msgstr "%{lock_path} est verrouillé par l’utilisateur GitLab %{lock_user_id}"
msgid "%{name}'s avatar"
msgstr "Avatar de %{name}"
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} peut être utilisé comme alternative à un domaine personnalisé."
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits de retard sur %{default_branch}, %{number_commits_ahead} commits d’avance"
@@ -170,6 +178,27 @@ msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent} %% effectués"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr "%{staged} changements prêts à être validés et %{unstaged} autres cha
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}En savoir plus%{usage_ping_link_end} sur les informations partagées avec GitLab Inc."
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr "+ %{count} de plus"
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} de plus"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr "- l’exécuteur est actif et peut traiter de nouvelles tâches"
@@ -260,11 +298,14 @@ msgstr[1] "%d utilisateurs"
msgid "1st contribution!"
msgstr "1ʳᵉ contribution !"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "2FA activé"
-msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "Veuillez contacter votre administrateur GitLab afin d’obtenir l’autorisation."
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
msgid "403|You don't have the permission to access this page."
msgstr "Vous n’avez pas l’autorisation d’accéder à cette page."
@@ -305,8 +346,8 @@ msgstr "Membres du groupe <strong>%{group_name}</strong>"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr "<strong>%{pushes}</strong> poussées Git, plus de <strong>%{commits}</strong> commits effectués par <strong>%{people}</strong> contributeurs."
-msgid "<strong>Removes</strong> source branch"
-msgstr "<strong>Supprime</strong> la branche source"
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "Un « exécuteur » est un processus qui exécute une tâche. Vous pouvez configurer autant d’exécuteurs que nécessaire."
@@ -353,6 +394,9 @@ msgstr "Rapports d’abus"
msgid "Abuse reports"
msgstr "Rapports d’abus"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr "Accepter les conditions"
@@ -389,11 +433,11 @@ msgstr "Activité"
msgid "Add"
msgstr "Ajouter"
-msgid "Add Changelog"
-msgstr "Ajouter un journal des modifications"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "Ajouter un guide de contribution"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Ajoutez des Webhooks de groupe avec GitLab Enterprise Edition."
@@ -404,8 +448,11 @@ msgstr "Ajouter une URL Jaeger"
msgid "Add Kubernetes cluster"
msgstr "Ajouter une grappe de serveurs Kubernetes"
-msgid "Add Readme"
-msgstr "Ajouter un fichier Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Ajoutez une page d’accueil à votre wiki contenant des informations sur votre projet. GitLab l’affichera ici à la place de ce message."
@@ -437,6 +484,9 @@ msgstr "Ajouter des projets"
msgid "Add reaction"
msgstr "Ajouter une réaction"
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr "Ajouter à la revue de code"
@@ -446,6 +496,9 @@ msgstr "Ajouter à la liste « à faire »"
msgid "Add user(s) to the group:"
msgstr "Ajouter un ou des utilisateurs au groupe :"
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr "Ajouter des utilisateurs au groupe"
@@ -461,9 +514,6 @@ msgstr "Espace d’administration"
msgid "Admin Overview"
msgstr "Vue administrateur"
-msgid "Admin area"
-msgstr "Espace d’administration"
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "Vous êtes sur le point de supprimer définitivement l’utilisateur %{username}. Les tickets, demandes de fusion et les groupes qui leur sont liés seront transférés à un « utilisateur fantôme » du système. Pour éviter toute perte de données, envisagez plutôt d’utiliser la fonctionnalité « %{strong_start}bloquer l’utilisateur%{strong_end} ». L’action « %{strong_start}supprimer l’utilisateur%{strong_end} » ne peut être annulée ni faire l’objet d’une restauration."
@@ -497,12 +547,42 @@ msgstr "Supprimer le projet %{projectName} ?"
msgid "AdminProjects|Delete project"
msgstr "Supprimer le projet"
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Spécifiez un domaine à utiliser par défaut pour les étapes Auto Review Apps et Auto Deploy de chaque projet."
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Bloquer ce compte"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "Supprimer le compte %{username} et ses contributions ?"
@@ -515,12 +595,42 @@ msgstr "Supprimer un compte utilisateur"
msgid "AdminUsers|Delete user and contributions"
msgstr "Supprimer le compte et ses contributions"
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Pour confirmer, veuillez saisir %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Pour confirmer, veuillez saisir %{username}"
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Autorisations avancées, stockage de fichiers volumineux et paramètres d’authentification à double facteur."
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] "Alerte"
msgstr[1] "Alertes"
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr "Tous"
@@ -541,9 +654,15 @@ msgstr "Toutes les modifications sont validées"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Toutes les fonctionnalités sont activées pour les projets vierges, à partir de modèles ou lors de l’importation, mais vous pouvez les désactiver ultérieurement dans les paramètres du projet."
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr "Tous les utilisateurs"
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr "Autoriser les commits des membres qui peuvent fusionner dans la branche cible."
@@ -565,6 +684,9 @@ msgstr "Autoriser les utilisateurs à demander un accès"
msgid "Allow users to request access if visibility is public or internal."
msgstr "Autoriser les utilisateurs à demander l’accès si la visibilité est publique ou interne."
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Vous permet d’ajouter et de gérer des grappes de serveurs Kubernetes."
@@ -592,48 +714,21 @@ msgstr "Une application appelée %{link_to_client} demande l’accès à votre c
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Un champ utilisateur Gitlab vide ajoutera le nom complet de l’utilisateur FogBugz (p. ex., « Par John Smith ») dans la description de tous les tickets et commentaires. Il associera ou assignera ces tickets et commentaires au créateur du projet."
-msgid "An error accured whilst committing your changes."
-msgstr "Une erreur est survenue lors du commit de vos modifications."
-
msgid "An error has occurred"
msgstr "Une erreur est survenue"
-msgid "An error occured creating the new branch."
-msgstr "Une erreur est survenue lors de la création de la nouvelle branche."
-
-msgid "An error occured whilst fetching the job trace."
-msgstr "Une erreur est survenue pendant le rapatriement de la trace de la tâche."
-
-msgid "An error occured whilst fetching the latest pipeline."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
-msgid "An error occured whilst loading all the files."
-msgstr "Une erreur est survenue lors du chargement de l’ensemble des fichiers."
-
-msgid "An error occured whilst loading the file content."
-msgstr "Une erreur est survenue lors du chargement du contenu du fichier."
-
-msgid "An error occured whilst loading the file."
-msgstr "Une erreur est survenue lors du chargement du fichier."
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr "Une erreur est survenue lors du chargement des modifications de la demande de fusion."
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr "Une erreur est survenue lors du chargement des données de version de la demande de fusion."
-
-msgid "An error occured whilst loading the merge request."
-msgstr "Une erreur est survenue lors du chargement de la demande de fusion."
-
-msgid "An error occured whilst loading the pipelines jobs."
-msgstr "Une erreur est survenue lors du chargement des tâches des pipelines."
-
msgid "An error occurred adding a draft to the discussion."
msgstr "Une erreur est survenue lors de l’ajout d’un brouillon à la discussion."
msgid "An error occurred adding a new draft."
msgstr "Une erreur est survenue lors de l’ajout d’un nouveau brouillon."
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Une erreur s’est produite lors de la prévisualisation du blob"
@@ -706,12 +801,21 @@ msgstr "Une erreur s’est produite lors du chargement des noms de fichiers"
msgid "An error occurred while loading the file"
msgstr "Une erreur s’est produite lors du chargement du fichier"
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr "Une erreur s’est produite lors de la requête."
msgid "An error occurred while removing approver"
msgstr "Une erreur est survenue lors de la suppression de l’approba·teur·trice"
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr "Une erreur s’est produite lors du rendu de KaTeX"
@@ -742,9 +846,54 @@ msgstr "Une erreur est survenue lors de la mise à jour du commentaire"
msgid "An error occurred while validating username"
msgstr "Une erreur s’est produite lors de la validation du nom d’utilisateur"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Une erreur est survenue. Merci de réessayer."
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr "Analyse"
@@ -775,6 +924,21 @@ msgstr "Application : %{name}"
msgid "Applications"
msgstr "Applications"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "avr."
@@ -787,6 +951,9 @@ msgstr "Projet archivé ! Le dépôt et les autres ressources du projet sont e
msgid "Archived projects"
msgstr "Projets archivés"
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Êtesâ€vous sûr·e de vouloir supprimer ce pipeline programmé ?"
@@ -796,12 +963,24 @@ msgstr "Êtesâ€vous sûr(e) de vouloir supprimer cette construction ?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Êtesâ€vous vraiment prêt(e) à perdre les modifications non enregistrées ?"
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "Êtesâ€vous sûr de vouloir générer une nouvelle paire de clefs ? Vous devrez copier la nouvelle clef publique sur le serveur distant pour que la mise en miroir refonctionne."
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Voulezâ€vous vraiment supprimer %{group_name} ?"
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr "Êtesâ€vous sûr(e) de vouloir supprimer cette identité ?"
@@ -817,6 +996,9 @@ msgstr "Êtesâ€vous sûr(e) de vouloir arrêter cet environnement ?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Êtesâ€vous sûr·e de vouloir déverrouiller %{path_lock_path} ?"
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "Êtesâ€vous certain(e) ?"
@@ -835,6 +1017,9 @@ msgstr "Demandez au responsable du groupe de configurer un exécuteur de groupe.
msgid "Assertion consumer service URL"
msgstr "URL du service consommateur d’assertion"
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "Attribuer une couleur personnalisée comme #FF0000"
@@ -844,6 +1029,9 @@ msgstr "Attribuer des étiquettes"
msgid "Assign milestone"
msgstr "Attribuer un jalon"
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr "Assigner à"
@@ -871,6 +1059,9 @@ msgstr "Les listes d’assignation montrent tous les bogues assignés à l’uti
msgid "Assignee(s)"
msgstr "Assigné·e(s)"
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Attachez un fichier par glisserâ€déposer ou %{upload_link}"
@@ -883,6 +1074,9 @@ msgstr "août"
msgid "August"
msgstr "août"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "Journal d’authentification"
@@ -898,6 +1092,9 @@ msgstr "Auteur·e"
msgid "Authorization code:"
msgstr "Code d’autorisation :"
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr "L’autorisation a été accordée via la saisie de vos nom d’utilisateur et mot de passe dans l’application."
@@ -925,15 +1122,6 @@ msgstr "Auto DevOps activé"
msgid "Auto DevOps, runners and job artifacts"
msgstr "Auto DevOps, exécuteurs et artéfacts de tâches"
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr "Auto Review Apps et Auto Deploy ont besoin d’un %{kubernetes} qui fonctionne correctement."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr "Auto Review Apps et Auto Deploy ont besoin d’un nom de domaine et d’un %{kubernetes} qui fonctionne correctement."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "Auto Review Apps et Auto Deploy ont besoin d’un nom de domaine qui fonctionne correctement."
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr "Annuler automatiquement les pipelines redondants en attente"
@@ -967,14 +1155,26 @@ msgstr "activez Auto DevOps"
msgid "Automatically marked as default internal user"
msgstr "Marqué automatiquement comme utilisateur interne par défaut"
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "Disponible"
-msgid "Available group Runners : %{runners}"
-msgstr "Exécuteurs de groupe disponibles : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
-msgid "Available group Runners : %{runners}."
-msgstr "Exécuteurs de groupe disponibles : %{runners}."
+msgid "Avatar for %{name}"
+msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr "L’avatar sera supprimé. Êtesâ€vous sûr·e ?"
@@ -1159,6 +1359,12 @@ msgstr "Importation d’un serveur Bitbucket"
msgid "Bitbucket import"
msgstr "Importation de Bitbucket"
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr "Blog"
@@ -1168,11 +1374,6 @@ msgstr "Tableaux"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "La branche %{branchName} n’a pas été trouvée dans le dépôt de ce projet."
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] "Branche (%{branch_count})"
-msgstr[1] "Branches (%{branch_count})"
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "La branche <strong>%{branch_name}</strong> a été créée. Pour mettre en place le déploiement automatisé, sélectionnez un modèle de fichier YAML pour l’intégration continue (CI) de GitLab, et validez les modifications. %{link_to_autodeploy_doc}"
@@ -1326,21 +1527,36 @@ msgstr "Parcourir les fichiers"
msgid "Browse files"
msgstr "Parcourir les fichiers"
-msgid "Built-In"
-msgstr "Intégré"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
msgid "Business metrics (Custom)"
msgstr "Métriques commerciales (personnalisées)"
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "par"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "Intégration et livraison continues"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr "Paramètres CI / CD (intégration et livraison continues)"
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr "L’intégration continue fonctionnera avec les paramètres d’authentification ciâ€dessus."
@@ -1377,12 +1593,6 @@ msgstr "Pipeline Auto DevOps par défaut"
msgid "CICD|Deployment strategy"
msgstr "Stratégie de déploiement"
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr "La stratégie de déploiement nécessite un nom de domaine pour fonctionner correctement."
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr "Ne définissez pas un domaine ici si vous mettez en place plusieurs grappes de serveurs Kubernetes avec Auto DevOps."
-
msgid "CICD|Jobs"
msgstr "Tâches"
@@ -1392,18 +1602,27 @@ msgstr "En savoir plus à propos d’Auto DevOps"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr "Le pipeline Auto DevOps sera exécuté si aucun autre fichier de configuration n’est trouvé."
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
-msgstr "Vous devez spécifier un domaine si vous voulez utiliser la revue automatique d’applications Auto Review Apps et le déploiement automatique d’étapes Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
msgid "CICD|instance enabled"
msgstr "instance activée"
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de retour"
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr "Impossible de trouver le dernier commit (HEAD) pour cette branche"
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "Annuler"
@@ -1416,12 +1635,21 @@ msgstr "Ne peut être fusionnée automatiquement"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Impossible de modifier la grappe de serveurs gérée par Kubernetes"
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr "Empreinte du certificat"
msgid "Change Weight"
msgstr "Modifier le poids"
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr "Changer de modèle"
@@ -1443,12 +1671,12 @@ msgstr "Défaire"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Cela va créer un nouveau commit afin de défaire les modifications existantes."
-msgid "Changelog"
-msgstr "Journal des modifications"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "Les modifications sont affichées comme si la révision <b>source</b> était fusionnée dans la révision<b>cible</b>."
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "Statistiques"
@@ -1458,9 +1686,15 @@ msgstr "Discussion"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Veuillez vérifier la %{docs_link_start}documentation%{docs_link_end}."
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr "Vérification de la disponibilité de %{text}…"
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "Vérification de la disponibilité du nom de branche…"
@@ -1482,6 +1716,12 @@ msgstr "Choisir le fichier…"
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Choisissez une branche ou une étiquette (par exemple %{master}) ou entrez un commit (par exemple %{sha}) pour voir ce qui a changé ou pour créer une demande de fusion."
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr "Choisir un modèle…"
@@ -1500,6 +1740,9 @@ msgstr "Choisir le fichier…"
msgid "Choose the top-level group for your repository imports."
msgstr "Choisissez le groupe de premier niveau pour vos importations dans le dépôt."
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr "Choisissez les groupes que vous souhaitez synchroniser avec ce nœud secondaire."
@@ -1593,8 +1836,8 @@ msgstr "Tous les environnements"
msgid "CiVariable|Create wildcard"
msgstr "Créer un joker"
-msgid "CiVariable|Error occured while saving variables"
-msgstr "Une erreur s’est produite pendant la sauvegarde des variables"
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
msgid "CiVariable|New environment"
msgstr "Nouvel environnement"
@@ -1614,6 +1857,12 @@ msgstr "La validation a échoué"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "est indisponible : %{reason}"
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr "Effacer la recherche"
@@ -1653,29 +1902,53 @@ msgstr "Mot de passe de la clef d’authentification client"
msgid "Clients"
msgstr "Clients"
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr "Cloner le dépôt"
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr "Fermer"
msgid "Close epic"
msgstr "Clore l’épopée"
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr "Fermé(e)"
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr "Tickets clos"
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} a été installé avec succès sur votre grappe de serveurs Kubernetes"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr "%{boldNotice} Ceci ajoutera quelques ressources supplémentaires comme un équilibreur de charge, ce qui peut engager des frais supplémentaires selon l’hébergeur de votre grappe de serveurs Kubernetes. Si vous utilisez Google Kubernetes Engine, vous pouvez %{pricingLink}."
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
-msgstr "Une construction Knative étend Kubernetes en utilisant les primitives Kubernetes existantes pour vous permettre d’exécuter des constructions de conteneurs sur une grappe de serveurs à partir des sources. Par exemple, vous pouvez écrire une construction qui utilise les ressources natives de Kubernetes pour obtenir votre code source à partir d’un dépôt, puis compiler ce code dans une image de conteneur, et enfin exécuter cette image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
+msgstr ""
msgid "ClusterIntegration|API URL"
msgstr "URL de l’API"
@@ -1698,27 +1971,42 @@ msgstr "Options avancées concernant l’intégration de cette grappe de serveur
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr "Après avoir installé Ingress, vous devrez faire pointer votre entrée DNS générique (wildcard) vers l’adresse IP externe générée afin que votre application puisse s’afficher après son déploiement. %{ingressHelpLink}"
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "Une erreur est survenue lors de la tentative de récupération des zones du projet : %{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr "Une erreur est survenue lors de la tentative de récupération de vos projets : %{error}"
-
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
-msgstr "Une erreur est survenue lors de la tentative de récupération des types de machines de la zone : %{error}"
-
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr "Une erreur est survenue lors de la tentative de contact de l’API Google Cloud. Veuillez réessayer plus tard."
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "Applications"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr "Êtesâ€vous sûr·e de vouloir supprimer l’intégration de cette grappe de serveurs Kubernetes ? Cela ne supprimera pas votre grappe de serveurs Kubernetes."
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr "Certificat d’autorité de certification"
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Ensemble de certificats des autorités de certification (format PEM)"
@@ -1728,6 +2016,9 @@ msgstr "Choisissez les applications à installer sur votre grappe de serveurs Ku
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Choisissez lequel de vos environnements utilisera cette grappe de serveurs."
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Copier l’URL de l’API"
@@ -1740,6 +2031,9 @@ msgstr "Copier l’adresse IP Ingress dans le presseâ€papiers"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr "Copier le nom d’hôte Jupyter dans le presseâ€papiers"
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Copier le nom de la grappe de serveurs Kubernetes"
@@ -1767,6 +2061,15 @@ msgstr "Portée de l’environnement"
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr "Chaque nouveau compte Google Cloud Platform (GCP) reçoit un crédit de 300 US$ sur %{sign_up_link}. En partenariat avec Google, GitLab est en mesure de vous offrir 200 US$ supplémentaires, à la fois pour les nouveaux et les anciens comptes GCP, afin de vous permettre de commencer l’intégration de Google Kubernetes Engine sur GitLab."
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr "Récupération des types de machines"
@@ -1839,6 +2142,12 @@ msgstr "Intégrez l’automatisation de la grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Integration status"
msgstr "Statut de l’intégration"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Nom de l’hôte Jupyter"
@@ -1854,6 +2163,12 @@ msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
msgstr "Nom de domaine Knative :"
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Grappe de serveurs Kubernetes"
@@ -1890,6 +2205,9 @@ msgstr "En savoir plus sur Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "En savoir plus sur les grappes de serveurs Kubernetes de groupe"
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr "Type de machine"
@@ -1968,6 +2286,9 @@ msgstr "Vous pouvez remplacer ceci par un nom d’hôte personnalisé. Auquel ca
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "La demande de lancement de l’installation a échoué"
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr "Enregistrer les modifications"
@@ -2010,12 +2331,18 @@ msgstr "Afficher"
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Un problème est survenu de notre côté."
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr "Une erreur s’est produite lors de la création de votre grappe de serveurs Kubernetes sur Google Kubernetes Engine"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Une erreur s’est produite lors de l’installation de %{title}"
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr "L’adresse IP est en cours d’affectation. Si cela dure trop longtemps, veuillez vérifier votre grappe de serveurs Kubernetes ou vos quotas sur Google Kubernetes Engine."
@@ -2031,6 +2358,18 @@ msgstr "Activer/désactiver la grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Token"
msgstr "Jeton"
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr "Validation de l’état de la facturation du projet"
@@ -2043,6 +2382,9 @@ msgstr "Avec une grappe de serveurs Kubernetes associée à ce projet, vous pouv
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "Vous devez d’abord installer Helm Tiller avant d’installer les applications ciâ€dessous"
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Votre compte doit disposer de %{link_to_kubernetes_engine}"
@@ -2070,6 +2412,9 @@ msgstr "correctement configuré"
msgid "ClusterIntegration|sign up"
msgstr "s’inscrire"
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr "Propriétaires du code"
@@ -2082,8 +2427,17 @@ msgstr "Réduire"
msgid "Collapse sidebar"
msgstr "Masquer la barre latérale"
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
-msgstr "Commentaire"
+msgstr "Commenter"
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
msgid "Comment & resolve discussion"
msgstr "Commenter et marquer la discussion comme résolue"
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] "Commit"
msgstr[1] "Commits"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] "Commit (%{commit_count})"
-msgstr[1] "Commits (%{commit_count})"
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "Message du commit"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "Durée des 30 derniers commits en minutes"
@@ -2173,6 +2528,9 @@ msgstr "Comparer les révisions Git"
msgid "Compare Revisions"
msgstr "Comparer les révisions"
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr "Comparer les changements avec le dernier commit"
@@ -2200,12 +2558,18 @@ msgstr "Confidentiel"
msgid "Confidentiality"
msgstr "Confidentialité"
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr "Configurer les délais d’expiration de Gitaly."
msgid "Configure Tracing"
msgstr "Configurer le traçage"
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "Configurer les vérifications Git automatiques et la maintenance des dépôts."
@@ -2239,6 +2603,9 @@ msgstr "Connectez vos dépôts externes afin que les pipelines d’intégration
msgid "Connecting..."
msgstr "Connexion en cours…"
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr "Registre de conteneur"
@@ -2287,6 +2654,9 @@ msgstr "Avec le registre de conteneur Docker intégré à GitLab, chaque projet
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Vous pouvez également utiliser un %{deploy_token} pour un accès en lecture seule aux images du registre."
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr "Continuer"
@@ -2302,8 +2672,8 @@ msgstr "Contribuer à GitLab"
msgid "Contribution"
msgstr "Contribution"
-msgid "Contribution guide"
-msgstr "Guide de contribution"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr "Contributions du <strong>%{calendar_date}</strong>"
@@ -2338,21 +2708,27 @@ msgstr "Contrôle la concurrence maximale des remplacements de dépôt pour ce n
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr "Contrôle la concurrence maximale des opérations de vérification pour ce nœud Geo"
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr "Index ConvDev"
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Copier l’URL %{protocol} de clonage"
-msgid "Copy HTTPS clone URL"
-msgstr "Copier l’URL HTTPS de clonage"
-
msgid "Copy ID to clipboard"
msgstr "Copier l’identifiant dans le presseâ€papiers"
msgid "Copy SSH clone URL"
msgstr "Copier l’URL SSH de clonage"
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr "Copier la clef SSH publique dans le presseâ€papiers"
@@ -2377,9 +2753,6 @@ msgstr "Copier l’adresse de courriel de l’expéditeur dans le presse-papiers
msgid "Copy link"
msgstr "Copier le lien"
-msgid "Copy name to clipboard"
-msgstr "Copier le nom dans le presseâ€papiers"
-
msgid "Copy reference to clipboard"
msgstr "Copier la référence dans le presseâ€papiers"
@@ -2401,6 +2774,9 @@ msgstr "Créer"
msgid "Create New Directory"
msgstr "Créer un nouveau dossier"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr "Créer une nouvelle branche"
@@ -2410,6 +2786,9 @@ msgstr "Créer une nouvelle branche et une nouvelle demande de fusion"
msgid "Create a new issue"
msgstr "Créer un nouveau ticket"
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Créer un jeton d’accès personnel pour votre compte afin de récupérer ou pousser par %{protocol}."
@@ -2449,6 +2828,9 @@ msgstr "Créer une demande de fusion"
msgid "Create merge request and branch"
msgstr "Créer une demande de fusion et une branche"
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "Créer une nouvelle branche"
@@ -2515,9 +2897,6 @@ msgstr "Profil"
msgid "CurrentUser|Settings"
msgstr "Paramètres"
-msgid "Custom"
-msgstr "Personnalisé"
-
msgid "Custom CI config path"
msgstr "Chemin d’accès de la config d’intégration continue personnalisée"
@@ -2533,6 +2912,9 @@ msgstr "Les niveaux de notification personnalisés sont similaires aux niveaux d
msgid "Custom project templates"
msgstr "Modèles de projets personnalisés"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr "Personnaliser les couleurs"
@@ -2542,6 +2924,12 @@ msgstr "Personnalisez la manière dont les adresses de courriel et les noms d’
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "Personnalisez la manière dont les adresses de courriel et les noms d’utilisateur provenant de Google Code sont importés dans GitLab. À la prochaine étape, vous pourrez sélectionner les projets que vous souhaitez importer."
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr "Personnalisez la configuration de votre pipeline et affichez son état et le rapport de couverture."
@@ -2572,6 +2960,9 @@ msgstr "Préproduction"
msgid "CycleAnalyticsStage|Test"
msgstr "Test"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr "Tableau de bord"
@@ -2581,6 +2972,9 @@ msgstr "Tous"
msgid "DashboardProjects|Personal"
msgstr "Personnels"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr "Sélecteur de date"
@@ -2593,6 +2987,9 @@ msgstr "déc."
msgid "December"
msgstr "décembre"
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr "Refuser et se déconnecter"
@@ -2602,6 +2999,12 @@ msgstr "Branche par défaut"
msgid "Default classification label"
msgstr "Étiquette de classement par défaut"
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr "Par défaut : importer directement l’adresse de courriel ou le nom d’utilisateur provenant de Google Code"
@@ -2611,6 +3014,9 @@ msgstr "Par défaut : associer un identifiant de compte FogBugz à un nom compl
msgid "Define a custom pattern with cron syntax"
msgstr "Définir un schéma personnalisé avec une syntaxe Cron"
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr "Êtesâ€vous sûr(e) de vouloir exécuter %{jobName} immédiatement ? Dans le cas contraire, cette tâche sera automatiquement exécutée à l’heure programmée."
@@ -2641,6 +3047,12 @@ msgstr "Supprimer le commentaire"
msgid "Delete list"
msgstr "Supprimer la liste"
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr "Supprimé"
@@ -2775,6 +3187,9 @@ msgstr "Votre nouveau jeton de déploiement"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Votre nouveau jeton de déploiement pour votre projet a été créé."
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr "Déployé sur"
@@ -2802,6 +3217,9 @@ msgstr "Détruire"
msgid "Details"
msgstr "Détails"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr "Détecter les clefs de l’hôte"
@@ -2832,6 +3250,12 @@ msgstr "Désactiver pour ce projet"
msgid "Disable group Runners"
msgstr "Désactiver les exécuteurs de groupe"
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr "Rejeter"
@@ -2853,15 +3277,24 @@ msgstr "Abandonner le brouillon"
msgid "Discard review"
msgstr "Rejeter la revue de code"
-msgid "Discover GitLab Geo."
-msgstr "Découvrez GitLab Geo."
+msgid "Discover GitLab Geo"
+msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "Découvrez des projets, des groupes et des extraits de code. Partagez vos projets avec d’autres personnes"
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr "Rejeter"
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "Passer l’introduction à Cycle Analytics"
@@ -2869,7 +3302,7 @@ msgid "Dismiss Merge Request promotion"
msgstr "Rejeter la promotion de la demande de fusion"
msgid "Dismiss trial promotion"
-msgstr ""
+msgstr "Rejeter l’offre promotionnelle"
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Voulezâ€vous personnaliser la manière dont les adresses de courriel et les noms d’utilisateurs issus de Google Code sont importés dans GitLab ?"
@@ -2889,6 +3322,12 @@ msgstr "Effectué"
msgid "Download"
msgstr "Télécharger"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "Télécharger une archive TAR"
@@ -2913,6 +3352,9 @@ msgstr "Pur diff"
msgid "DownloadSource|Download"
msgstr "Télécharger"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr "Votes négatifs"
@@ -2928,9 +3370,15 @@ msgstr "Chaque exécuteur peut être dans l’un des états suivants :"
msgid "Edit"
msgstr "Éditer"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr "Modifier l’étiquette"
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Éditer le pipeline programmé %{id}"
@@ -2940,6 +3388,12 @@ msgstr "Modifier le fragment de code"
msgid "Edit application"
msgstr "Modifier l’application"
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr "Modifier les fichiers dans l’éditeur et valider les modifications ici"
@@ -2949,11 +3403,14 @@ msgstr "Modifier le groupe : %{group_name}"
msgid "Edit identity for %{user_name}"
msgstr "Modifier l’identité de %{user_name}"
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr "Elasticsearch"
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
+msgstr "Intégration d’Elasticsearch. Elasticsearch AWS IAM."
msgid "Email"
msgstr "Courriel"
@@ -2967,6 +3424,9 @@ msgstr "Courriels"
msgid "Embed"
msgstr "Embarquer"
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr "Activer"
@@ -2991,6 +3451,9 @@ msgstr "Activer et configurer les métriques Prometheus."
msgid "Enable classification control using an external service"
msgstr "Activer le contrôle de classification à l’aide d’un service externe"
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr "Activer pour ce projet"
@@ -3006,9 +3469,18 @@ msgstr "Activer ou désactiver le contrôle de version et l’envoi des données
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "Activer reCAPTCHA ou Akismet et définir des limites d’adresse IP."
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr "Activer la barre de performance pour un groupe donné."
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr "Activer la collecte des données d’utilisation"
@@ -3021,6 +3493,12 @@ msgstr "activé"
msgid "Ends at (UTC)"
msgstr "Se termine à (UTC)"
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "Entrez l’URL de votre serveur Bitbucket et votre jeton d’accès personnel ciâ€dessous"
@@ -3036,9 +3514,27 @@ msgstr "Entrez la description de la demande de fusion"
msgid "Enter the merge request title"
msgstr "Entrez l’intitulé de la demande de fusion"
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr "Environnements"
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Une erreur s’est produite lors de la récupération des environnements."
@@ -3114,6 +3610,9 @@ msgstr "Arrêter"
msgid "Environments|Stop environment"
msgstr "Arrêter l’environnement"
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Mis à jour"
@@ -3126,9 +3625,6 @@ msgstr "protégé"
msgid "Epic"
msgstr "Épopée"
-msgid "Epic will be removed! Are you sure?"
-msgstr "L’épopée sera supprimée ! Êtesâ€vous sûr(e) ?"
-
msgid "Epics"
msgstr "Épopées"
@@ -3138,7 +3634,7 @@ msgstr "Feuille de route des épopées"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Les épopées vous permettent de gérer votre portefeuille de projets plus efficacement et avec moins d’efforts"
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3151,7 +3647,7 @@ msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from
msgstr "Ces dates affectent la manière dont vos épopées apparaissent sur la feuille de route. Les dates des jalons proviennent des jalons attribués aux tickets de l’épopée. Vous pouvez également définir des dates fixes ou les supprimer complètement."
msgid "Epics|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 "Afin de planifier la date de %{epicDateType} de votre épopée en fonction des jalons, attribuez un jalon avec une date de %{epicDateType} à tous les tickets concernant l’épopée."
msgid "Epics|due"
msgstr "Échéance"
@@ -3165,9 +3661,15 @@ msgstr "Erreur"
msgid "Error Reporting and Logging"
msgstr "Rapport d’erreur et journalisation"
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr "Erreur lors de la création de l’épopée"
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr "Erreur lors de l’extraction des données des contributeur·rice·s."
@@ -3210,9 +3712,15 @@ msgstr "Erreur lors du chargement du modèle."
msgid "Error occurred when toggling the notification subscription"
msgstr "Une erreur s’est produite lors de l’activation ou de la désactivation de l’abonnement aux notifications"
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr "Erreur lors de la mise à jour de l’étiquette."
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr "Erreur lors de la mise à jour de l’état de la liste de tâches à faire."
@@ -3222,6 +3730,12 @@ msgstr "Erreur lors de la mise à jour du statut de tâche à faire."
msgid "Error while loading the merge request. Please try again."
msgstr "Erreur lors du chargement de la demande de fusion. Veuillez réessayer."
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr "Estimé"
@@ -3243,6 +3757,12 @@ msgstr "Filtrer par événements Git push"
msgid "EventFilterBy|Filter by team"
msgstr "Filtrer par équipe"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Chaque jour (à 4 h du matin)"
@@ -3252,9 +3772,39 @@ msgstr "Chaque mois (le 1ᵉʳ à 4 h du matin)"
msgid "Every week (Sundays at 4:00am)"
msgstr "Chaque semaine (dimanche à 4 h du matin)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr "Tout le monde peut contribuer"
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr "Étendre"
@@ -3267,6 +3817,12 @@ msgstr "Étendre la barre latérale"
msgid "Expiration date"
msgstr "Date d’expiration"
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr "Décrivez le problème. Le cas échéant, fournissez un lien vers un ticket ou un commentaire idoine."
@@ -3288,9 +3844,21 @@ msgstr "Explorer les projets"
msgid "Explore public groups"
msgstr "Explorer les groupes publics"
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr "Autorisation de politique de classification externe"
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr "Authentification externe"
@@ -3330,6 +3898,9 @@ msgstr "Échec du déploiement sur"
msgid "Failed to load emoji list."
msgstr "Impossible de charger la liste des émojis."
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "Impossible de supprimer le ticket du tableau, veuillez réessayer."
@@ -3339,30 +3910,42 @@ msgstr "Impossible de supprimer le miroir."
msgid "Failed to remove the pipeline schedule"
msgstr "Échec de la suppression du pipeline programmé"
-msgid "Failed to signing using smartcard authentication"
+msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr "Échec de la signature via authentification par carte à puce"
+
msgid "Failed to update issues, please try again."
msgstr "Échec de la mise à jour du ticket. Veuillez réessayer."
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr "Échec"
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "Plus rapide parce qu’il réutilise l’espace de travail du projet (faire un clone en solution de secours s’il n’existe pas)"
msgid "Feature Flags"
msgstr "Indicateurs de fonctionnalités"
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
msgid "FeatureFlags|API URL"
msgstr "URL de l’API"
msgid "FeatureFlags|Active"
msgstr "Actif"
-msgid "FeatureFlags|Application name"
-msgstr "Nom de l’application"
-
msgid "FeatureFlags|Configure"
msgstr "Configurer"
@@ -3372,8 +3955,11 @@ msgstr "Configurer les indicateurs de fonctionnalité"
msgid "FeatureFlags|Create feature flag"
msgstr "Créer un indicateur de fonctionnalité"
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
-msgstr "Supprimer %{feature_flag_name} ?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
msgid "FeatureFlags|Description"
msgstr "Description"
@@ -3384,30 +3970,48 @@ msgstr "Modifier %{feature_flag_name}"
msgid "FeatureFlags|Edit Feature Flag"
msgstr "Modifier l’indicateur de fonctionnalité"
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr "Indicateur de fonctionnalité"
-msgid "FeatureFlags|Feature flag"
-msgstr "Indicateur de fonctionnalité"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
-msgstr "L’indicateur de fonctionnalité %{feature_flag_name} va être supprimé. Êtesâ€vous sûr(e) ?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
-msgstr "Les indicateurs de fonctionnalités vous permettent de configurer votre code de différentes manières en activant dynamiquement ou non certaines fonctionnalités."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
-msgstr "Découvrez les indicateurs de fonctionnalité"
+msgid "FeatureFlags|Get started with Feature Flags"
+msgstr ""
msgid "FeatureFlags|Inactive"
msgstr "Inactif"
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr "Installez une %{docs_link_start}bibliothèque cliente compatible%{docs_link_end} et spécifiez l’URL de l’API, le nom de l’application et l’identifiant d’instance lors de la configuration."
msgid "FeatureFlags|Instance ID"
msgstr "Identifiant d’instance"
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr "Plus d’informations"
@@ -3426,6 +4030,21 @@ msgstr "Enregistrer les modifications"
msgid "FeatureFlags|Status"
msgstr "État"
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr "févr."
@@ -3435,15 +4054,35 @@ msgstr "février"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "Les champs de cette page sont désormais non modifiables, vous pouvez configurer"
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr "Modèles de fichiers"
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "Fichiers"
-msgid "Files (%{human_size})"
-msgstr "Fichiers (%{human_size})"
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "Renseignez les champs ciâ€dessous, activez <strong>%{enable_label}</strong> et appuyez sur <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr "Filtrer sur les tickets de type %{issuable_type} qui sont actuellement o
msgid "Filter by commit message"
msgstr "Filtrer par message de commit"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr "Filtrer…"
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "Rechercher par chemin d’accès"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "Rechercher un fichier"
@@ -3477,12 +4134,18 @@ msgstr "Cherchez le fichier <code>Takeout/Google Code Project Hosting/GoogleC
msgid "Fingerprints"
msgstr "Empreintes"
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr "Terminer la revue de code"
msgid "Finished"
msgstr "Terminé"
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "En premier"
@@ -3528,6 +4191,9 @@ msgstr "Message de pied de page"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "Pour les projets internes, tout utilisateur connecté peut afficher les pipelines et accéder aux détails des tâches (journaux de sortie et artefacts)"
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr "Pour plus d’informations, consultez "
@@ -3552,6 +4218,9 @@ msgstr "Divergence issue de %{project_name} (supprimé)"
msgid "Forking in progress"
msgstr "Divergence en cours"
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "Format"
@@ -3559,7 +4228,7 @@ msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Erreurs trouvées dans votre fichier .gitlab-ci.yml :"
msgid "Free Trial of GitLab.com Gold"
-msgstr ""
+msgstr "Essai gratuit de GitLab.com Gold"
msgid "From %{provider_title}"
msgstr "De %{provider_title}"
@@ -3603,6 +4272,9 @@ msgstr "Pipelines généraux"
msgid "Generate a default set of labels"
msgstr "Générer un jeu d’étiquettes par défaut"
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr "Geo"
@@ -3693,8 +4365,11 @@ msgstr "Non vérifié par somme de contrôle"
msgid "GeoNodes|Out of sync"
msgstr "Désynchronisé"
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
-msgstr "Supprimer un nÅ“ud arrête le processus de synchronisation. Êtesâ€vous sûr(e) ?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
msgid "GeoNodes|Replication slot WAL"
msgstr ""
@@ -3768,6 +4443,9 @@ msgstr "Sommes de contrôle des wikis vérifiées avec leurs homologues sur les
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr "Wikis vérifiés avec leurs homologues sur le nœud principal"
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr "Vous avez configuré des nœuds Geo en utilisant une connexion HTTP non sécurisée. Nous recommandons l’utilisation de HTTPS."
@@ -3813,6 +4491,9 @@ msgstr "Groupes à synchroniser"
msgid "Geo|In sync"
msgstr "Synchronisé"
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr "Dernière synchro réussie"
@@ -3849,6 +4530,9 @@ msgstr "Projets de certains groupes"
msgid "Geo|Projects in certain storage shards"
msgstr "Projets dans certains fragments de stockage"
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr "Revérifier"
@@ -3927,9 +4611,18 @@ msgstr "secondaire"
msgid "Get a free instance review"
msgstr "Obtenez une revue d’instance gratuite"
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr "Git"
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr "URL du dépôt Git"
@@ -3957,9 +4650,15 @@ msgstr "Les exécuteurs de groupe peuvent exécuter du code pour tous les projet
msgid "GitLab Import"
msgstr "Importation depuis GitLab"
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr "Utilisateur GitLab"
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr "Exportation de projet GitLab"
@@ -3990,6 +4689,9 @@ msgstr "URL de l’hôte Gitea"
msgid "Gitea Import"
msgstr "Importation depuis Gitea"
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr "Retour"
@@ -4014,6 +4716,9 @@ msgstr "L’authentification Google n’est pas %{link_to_documentation}. Demand
msgid "Got it!"
msgstr "Compris !"
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr "Graphique"
@@ -4059,15 +4764,18 @@ msgstr "Les responsables de groupe peuvent créer des exécuteurs de groupe via
msgid "Group name"
msgstr "Nom du groupe"
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr "Groupe : %{group_name}"
msgid "GroupRoadmap|From %{dateWord}"
msgstr "Depuis %{dateWord}"
-msgid "GroupRoadmap|Loading roadmap"
-msgstr "Chargement de la feuille de route en cours"
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Une erreur s’est produite lors de la récupération des épopées"
@@ -4077,23 +4785,11 @@ msgstr "Désolé, aucune épopée ne correspond à votre recherche"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "La feuille de route affiche la progression de vos épopées dans le temps"
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Afin d’afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€mensuelle, seules les épopées du mois dernier, du mois courant et des cinq prochains mois sont affichées, du %{startDate} au %{endDate}."
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Pour afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€trimestrielle, seules les épopées du trimestre dernier, du trimestre courant et des quatre prochains trimestres sont affichées, du %{startDate} au %{endDate}."
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Pour afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€hebdomadaire, seules les épopées de la semaine dernière, de la semaine courante et des quatre prochaines semaines sont affichées, du %{startDate} au %{endDate}."
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des filtres. Dans la vue multiâ€mensuelle, seules les épopées du mois dernier, du mois courant et des cinq prochains mois sont affichées, du %{startDate} au %{endDate}."
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des filtres. Dans la vue multiâ€trimestrielle, seules les épopées du trimestre dernier, du trimestre courant et des quatre prochains trimestres sont affichées, du %{startDate} au %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des filtres. Dans la vue multiâ€hebdomadaire, seules les épopées de la semaine dernière, de la semaine courante et des quatre prochaines semaines sont affichées, du %{startDate} au %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
msgid "GroupRoadmap|Until %{dateWord}"
msgstr "Jusqu’au %{dateWord}"
@@ -4101,15 +4797,24 @@ msgstr "Jusqu’au %{dateWord}"
msgid "GroupSettings|Badges"
msgstr "Badges numériques"
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
msgid "GroupSettings|Customize your group badges."
msgstr "Personnalisez vos badges numériques de groupe."
msgid "GroupSettings|Learn more about badges."
msgstr "En savoir plus sur les badges numériques."
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Empêcher le partage d’un projet du groupe %{group} avec d’autres groupes"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Ce paramètre s’applique au groupe %{ancestor_group} et a été forcé pour ce sousâ€groupe."
@@ -4134,6 +4839,9 @@ msgstr "Groupes"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "Les groupes peuvent également être imbriqués en créant des %{subgroup_docs_link_start}sousâ€groupes%{subgroup_docs_link_end}."
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr "Fréquemment consultés"
@@ -4233,6 +4941,9 @@ msgstr "Texte de la page d’aide et URL de la page de support."
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr "Voici la clef SSH publique qui doit être ajoutée sur le serveur distant. Pour plus d’informations, veuillez vous référer à la documentation."
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr "Masquer la saisie manuelle des clefs d’hôtes"
@@ -4244,8 +4955,8 @@ msgid_plural "Hide values"
msgstr[0] "Masquer la valeur"
msgstr[1] "Masquer les valeurs"
-msgid "Hide whitespace changes"
-msgstr "Masquer les modifications des espaces"
+msgid "Hide values"
+msgstr ""
msgid "History"
msgstr "Historique"
@@ -4253,6 +4964,9 @@ msgstr "Historique"
msgid "Housekeeping successfully started"
msgstr "Maintenance démarrée avec succès"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr "J’accepte les %{terms_link}"
@@ -4310,6 +5024,9 @@ msgstr "Identités"
msgid "Identity provider single sign on URL"
msgstr "URL d’authentification unique du fournisseur d’identité"
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr "Si cette option est désactivée, une branche locale divergente ne sera pas automatiquement mise à jour avec les commits de son homologue distant, afin d’éviter toute perte de données locales. Si la branche par défaut (%{default_branch}) a divergé et ne peut pas être mise à jour, la mise en miroir échouera. Les autres branches divergentes sont ignorées silencieusement."
@@ -4340,9 +5057,15 @@ msgstr "en pelure d’oignon"
msgid "ImageDiffViewer|Swipe"
msgstr "par balayage"
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr "Importer"
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr "Importe des projets depuis Gitea"
@@ -4361,12 +5084,24 @@ msgstr "Importer un projet GitLab exporté"
msgid "Import in progress"
msgstr "Importation en cours"
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr "Importez plusieurs dépôts en téléversant un fichier manifeste."
msgid "Import project"
msgstr "Importer un projet"
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr "Importer des projets depuis Bitbucket"
@@ -4391,6 +5126,9 @@ msgstr "Importer des dépôts à partir de GitHub"
msgid "Import repository"
msgstr "Importer un dépôt"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr "Connecter des dépôts provenant de"
@@ -4406,15 +5144,30 @@ msgstr "Améliorez vos recherches avec la recherche globale avancée de GitLab E
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr "Afin d’activer les statistiques au niveau de l’instance, veuillez demander à un administrateur d’activer la %{usage_ping_link_start}collecte des données d’utilisation%{usage_ping_link_end}."
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "À la prochaine étape, vous pourrez sélectionner les projets que vous souhaitez importer."
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "Inclure un accord sur les conditions générales d’utilisation et la politique de confidentialité que tous les utilisateurs doivent accepter."
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr "Si besoin, ajouter le nom d’utilisateur dans l’URL : <code>https: //username@gitlab.company.com/group/project.git</code>."
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr "Projet incompatible"
@@ -4430,6 +5183,9 @@ msgstr "Entrer les clefs d’hôte manuellement"
msgid "Input your repository URL"
msgstr "Entrez l’URL de votre dépôt"
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "Installer GitLab Runner"
@@ -4459,6 +5215,9 @@ msgstr "Paramètres des intégrations"
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "Les personnes intéressées peuvent même contribuer en poussant des commits si elles le souhaitent."
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr "Interne — le groupe ainsi que tous les projets internes sont accessibles à tout utilisateur connecté."
@@ -4474,9 +5233,27 @@ msgstr "Modèle d’intervalle"
msgid "Introducing Cycle Analytics"
msgstr "Introduction à l’analyseur de cycle"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr "Inviter"
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr "Ticket"
@@ -4495,6 +5272,21 @@ msgstr "Tableau"
msgid "IssueBoards|Boards"
msgstr "Tableaux"
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr "Tickets"
@@ -4528,6 +5320,12 @@ msgstr "Il n’y a aucun ticket concernant les projets de votre groupe"
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des critères de recherche dans la barre de filtrage ciâ€dessus"
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr "URL Jaeger"
@@ -4546,6 +5344,12 @@ msgstr "Tâche"
msgid "Job has been erased"
msgstr "La tâche a été supprimée"
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr "Tâches"
@@ -4585,11 +5389,11 @@ msgstr "Afficher la version brute"
msgid "Job|The artifacts were removed"
msgstr "Les artefacts ont été supprimés"
-msgid "Job|The artifacts will be removed in"
-msgstr "Les artefacts seront supprimés dans"
+msgid "Job|The artifacts will be removed"
+msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
-msgstr "Cette tâche est bloquée, car aucun exécuteur en ligne n’est attribué au projet."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
msgid "Jul"
msgstr "juill."
@@ -4603,12 +5407,18 @@ msgstr "juin"
msgid "June"
msgstr "juin"
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
msgid "Kubernetes Cluster"
msgstr "Grappe de serveurs Kubernetes"
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "Le temps de création de la grappe de serveurs Kubernetes dépasse le délai d’expiration : %{timeout}"
@@ -4686,6 +5496,9 @@ msgstr[1] "Les %d derniers jours"
msgid "Last Pipeline"
msgstr "Dernier pipeline"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "Dernier commit"
@@ -4701,6 +5514,9 @@ msgstr "Dernière modification par %{name}"
msgid "Last reply by"
msgstr "Dernière réponse de"
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr "Dernière mise à jour"
@@ -4716,15 +5532,39 @@ msgstr "à"
msgid "Latest changes"
msgstr "Derniers changements"
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr "En savoir plus"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr "En savoir plus sur %{issue_boards_url}, afin de suivre des tickets dans de multiples listes, à l’aide des étiquettes, des personnes assignées et des jalons. Si une fonctionnalité concernant les tableaux des tickets vous manque, veuillez créer un ticket sur %{gitlab_issues_url}."
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr "En savoir plus sur Kubernetes"
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr "En savoir plus sur les branches protégées"
@@ -4862,6 +5702,12 @@ msgstr "Chargement de l’EDI de GitLab…"
msgid "Loading..."
msgstr "Chargement…"
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr "Verrouiller"
@@ -4890,7 +5736,7 @@ msgid "Locks give the ability to lock specific file or folder."
msgstr "Les verrous permettent de verrouiller un fichier ou un dossier spécifique."
msgid "Login with smartcard"
-msgstr ""
+msgstr "Se connecter avec une carte à puce"
msgid "Logs"
msgstr "Journaux"
@@ -4928,6 +5774,9 @@ msgstr "Gérer les étiquettes"
msgid "Manage project labels"
msgstr "Gérer les étiquettes de projet"
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr "Gérez les membres de votre groupe tout en ajoutant un niveau de sécurité supplémentaire avec SAML."
@@ -4958,6 +5807,9 @@ msgstr "mars"
msgid "Mark todo as done"
msgstr "Marquer comme fait"
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr "Markdown activé"
@@ -4994,9 +5846,6 @@ msgstr "Insérer du code"
msgid "Maven Metadata"
msgstr "Métadonnées Maven"
-msgid "Maven package"
-msgstr "Paquet Maven"
-
msgid "Max access level"
msgstr "Niveau d’accès maximum"
@@ -5018,24 +5867,36 @@ msgstr "Membre depuis le %{date}"
msgid "Members"
msgstr "Membres"
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "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 "Les membres seront redirigés à cet emplacement lors de la connexion à votre groupe. Obtenezâ€le auprès de votre fournisseur d’identités, sous la dénomination « emplacement du service SSO », « point de terminaison d’émission de jetons SAML » ou « URL SAML 2.0 / W-Federation »."
msgid "Merge Request"
msgstr "Demande de fusion"
-msgid "Merge Request:"
-msgstr "Demande de fusion :"
-
msgid "Merge Requests"
msgstr "Demandes de fusion"
msgid "Merge Requests created"
msgstr "Demandes de fusion créées"
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr "Événements de fusion"
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr "Demande de fusion"
@@ -5048,20 +5909,32 @@ msgstr "Demandes de fusion"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Les demandes de fusion permettent de proposer les modifications que vous avez apportées à un projet et de discuter de ces modifications avec les autres"
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr "Une erreur est survenue lors de l’enregistrement du brouillon du commentaire."
-msgid "MergeRequests|Discussion stays resolved."
-msgstr "La discussion reste à l’état « résolu »."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
-msgstr "La discussion reste à l’état « non résolu »."
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
-msgstr "La discussion passera à l’état « résolu »."
+msgid "MergeRequests|Discussion will be resolved"
+msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
-msgstr "La discussion passera à l’état « non résolu »."
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
+msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "Résoudre cette discussion avec un nouveau ticket"
@@ -5078,6 +5951,24 @@ msgstr "Afficher le fichier au commit %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "Afficher le fichier remplacé au commit %{commitId}"
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr "%{paragraphStart}a changé la description %{descriptionChangedTimes} fois %{timeDifferenceMinutes}%{paragraphEnd}"
@@ -5087,6 +5978,9 @@ msgstr "Filtrer les fichiers"
msgid "MergeRequest|No files found"
msgstr "Aucun fichier trouvé"
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr "Fusionnée"
@@ -5105,8 +5999,8 @@ msgstr "Métriques — Prometheus"
msgid "Metrics and profiling"
msgstr "Statistiques et rapports"
-msgid "Metrics|Business"
-msgstr "Affaires"
+msgid "Metrics for environment"
+msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Consultez la documentation sur l’intégration et la livraison continues (CI/CD) concernant le déploiement dans un environnement"
@@ -5114,6 +6008,12 @@ msgstr "Consultez la documentation sur l’intégration et la livraison continue
msgid "Metrics|Create metric"
msgstr "Créer une métrique"
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr "Modifier la métrique"
@@ -5123,8 +6023,8 @@ msgstr "Environnement"
msgid "Metrics|For grouping similar metrics"
msgstr "Pour regrouper des métriques similaires"
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
-msgstr "Libellé de l’axe vertical du graphique. En général, l’unité de mesure. L’axe horizontal (axe X) représente toujours le temps."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
msgid "Metrics|Learn about environments"
msgstr "En savoir plus sur les environnements"
@@ -5135,24 +6035,18 @@ msgstr "Libellé de légende (facultatif)"
msgid "Metrics|Must be a valid PromQL query."
msgstr "La requête doit être une requête PromQL valide."
-msgid "Metrics|Name"
-msgstr "Nom"
-
msgid "Metrics|New metric"
msgstr "Nouvelle métrique"
msgid "Metrics|No deployed environments"
msgstr "Aucun environnement déployé"
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
msgid "Metrics|Prometheus Query Documentation"
msgstr "Documentation des requêtes Prometheus"
-msgid "Metrics|Query"
-msgstr "Requête"
-
-msgid "Metrics|Response"
-msgstr "Réponse"
-
msgid "Metrics|System"
msgstr "Système"
@@ -5165,12 +6059,12 @@ msgstr "Une erreur s’est produite lors de l’obtention des informations de dÃ
msgid "Metrics|There was an error getting environments information."
msgstr "Une erreur s’est produite lors de l’obtention des informations d’environnement."
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
msgid "Metrics|There was an error while retrieving metrics"
msgstr "Une erreur est survenue lors de la récupération des métriques"
-msgid "Metrics|Type"
-msgstr "Type"
-
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr "Le point de terminaison Prometheus a renvoyé une réponse contenant des données de déploiement inattendues"
@@ -5189,21 +6083,12 @@ msgstr "Utilisé si la requête ne renvoie qu’une seule série. Si elle renvoi
msgid "Metrics|Y-axis label"
msgstr "Libellé de l’axe Y"
-msgid "Metrics|e.g. HTTP requests"
-msgstr "p. ex., requêtes HTTP"
-
-msgid "Metrics|e.g. Requests/second"
-msgstr "p. ex., requêtes/seconde"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr "p. ex., débit"
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr "p. ex., rate(http_requests_total[5m])"
-
-msgid "Metrics|e.g. req/sec"
-msgstr "p. ex., req/sec"
-
msgid "Milestone"
msgstr "Jalon"
@@ -5276,6 +6161,18 @@ msgstr "Annuler"
msgid "Modal|Close"
msgstr "Fermer"
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "Supervision"
@@ -5336,6 +6233,9 @@ msgstr "Connexion / Inscription"
msgid "Nav|Sign out and sign in with a different account"
msgstr "Se déconnecter et se reconnecter avec un autre compte"
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr "Réseau"
@@ -5348,6 +6248,9 @@ msgstr "Nouveau"
msgid "New Application"
msgstr "Nouvelle application"
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr "Nouveau groupe"
@@ -5362,6 +6265,12 @@ msgstr[1] "Nouveaux tickets"
msgid "New Label"
msgstr "Nouvelle étiquette"
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "Nouvelle planification de pipeline"
@@ -5380,6 +6289,9 @@ msgstr "Nouvelle branche indisponible"
msgid "New directory"
msgstr "Nouveau dossier"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr "Nouvelle épopée"
@@ -5401,6 +6313,9 @@ msgstr "Nouvelle étiquette"
msgid "New merge request"
msgstr "Nouvelle demande de fusion"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "De nouveaux pipelines annuleront les anciens pipelines en attente sur la même branche"
@@ -5428,6 +6343,9 @@ msgstr "Non"
msgid "No Label"
msgstr "Aucune étiquette"
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr "Aucune personne assignée"
@@ -5437,6 +6355,9 @@ msgstr "Aucune branche trouvée"
msgid "No changes"
msgstr "Aucun changement"
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Aucune connexion n’a pu être établie avec un serveur Gitaly, veuillez vérifier votre journal !"
@@ -5447,17 +6368,26 @@ msgid "No contributions were found"
msgstr "Aucune contribution n’a été trouvée"
msgid "No credit card required."
+msgstr "Aucune carte de crédit n’est nécessaire."
+
+msgid "No details available"
msgstr ""
msgid "No due date"
msgstr "Aucune date d’échéance"
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr "Aucune estimation ou temps passé"
msgid "No file chosen"
msgstr "Aucun fichier sélectionné"
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr "Aucun fichier trouvé."
@@ -5470,6 +6400,9 @@ msgstr "Aucune étiquette avec un tel nom ou une telle description"
msgid "No license. All rights reserved"
msgstr "Aucune licence. Tous droits réservés"
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr "Aucune demande de fusion pour la période sélectionnée."
@@ -5479,11 +6412,14 @@ msgstr "Aucune demande de fusion trouvée"
msgid "No messages were logged"
msgstr "Aucun message n’a été enregistré"
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Aucune autre étiquette avec un tel nom ou une telle description"
-msgid "No packages stored for this project."
-msgstr "Aucun paquet stocké pour ce projet."
+msgid "No preview for this file type"
+msgstr ""
msgid "No prioritised labels with such name or description"
msgstr "Aucune étiquette prioritaire avec un tel nom ou une telle description"
@@ -5503,6 +6439,9 @@ msgstr "Aucun exécuteur trouvé"
msgid "No schedules"
msgstr "Aucune planification"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr "Non, importer directement les adresses de courriel et les noms d’utilisateur existants."
@@ -5512,12 +6451,6 @@ msgstr "NÅ“uds"
msgid "None"
msgstr "Aucun·e"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr "Certains commentaires ne sont pas affichés car vous comparez deux versions du diff."
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr "Certains commentaires ne sont pas affichés car vous consultez une ancienne version du diff."
-
msgid "Not allowed to merge"
msgstr "Non autorisé·e à fusionner"
@@ -5542,6 +6475,9 @@ msgstr "Pas maintenant"
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "Notez que la branche principale « master » est automatiquement protégée. %{link_to_protected_branches}"
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "Remarque : En tant qu’administrateur ou administratrice, vous pouvez configurer %{github_integration_link}, ce qui vous permettra de vous authentifier via GitHub et de connecter des dépôts sans générer de jeton d’accès personnel."
@@ -5572,6 +6508,12 @@ msgstr "Afficher uniquement l’historique"
msgid "Notification events"
msgstr "Événement de notifications"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Clore le ticket"
@@ -5670,21 +6612,36 @@ msgstr "Un ou plusieurs de vos projets Google Code ne peuvent être importés d
msgid "Only admins"
msgstr "Seulement les administrateurs"
-msgid "Only comments from the following commit are shown below"
-msgstr "Seuls les commentaires du commit suivant sont affichés ciâ€dessous"
-
msgid "Only mirror protected branches"
msgstr "Ne mettre en miroir que les branches protégées"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
msgid "Only project members can comment."
msgstr "Seuls les membres du projet peuvent commenter."
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "Ouh là, êtesâ€vous sûr(e) ?"
msgid "Open"
msgstr "Ouvrir"
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr "Ouvrir dans Xcode"
@@ -5718,17 +6675,14 @@ msgstr "Opérations"
msgid "Operations Dashboard"
msgstr "Tableau de bord des opérations"
-msgid "Operations Settings"
-msgstr "Paramètres des opérations"
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr "Ajouter un projet au tableau de bord"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "Le tableau de bord des opérations fournit un résumé de l’état de santé opérationnel de chaque projet, comprenant les états des pipelines et des alertes."
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
-msgstr "Impossible d’ajouter %{invalidProjects}. Le tableau de bord des opérations n’est disponible que pour les projets avec un abonnement Gold."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Vous pouvez éventuellement %{link_to_customize} la manière dont les adresses de courriel et les noms d’utilisateur issus de FogBugz sont importés dans GitLab."
@@ -5775,6 +6729,12 @@ msgstr "Paquets"
msgid "Pages"
msgstr "Pages"
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Dernière ⇥"
@@ -5787,12 +6747,27 @@ msgstr "Précédente"
msgid "Pagination|« First"
msgstr "⇤ Première"
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr "Partie des modifications de la demande de fusion"
msgid "Password"
msgstr "Mot de Passe"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "Collez votre clef SSH publique, qui est habituellement située dans le fichier « ~/.ssh/id_rsa.pub » et commence par « ssh-rsa ». N’utilisez pas votre clef SSH privée !"
@@ -5814,9 +6789,6 @@ msgstr "En attente"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Les personnes sans autorisation ne recevront jamais de notifications et ne pourront pas commenter."
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr "Par tâche. Si une tâche dépasse ce seuil, elle sera marquée comme ayant échoué"
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "Effectuer des actions avancées telles que la modification du chemin d’accès, le transfert ou la suppression du groupe."
@@ -5832,6 +6804,12 @@ msgstr "Autorisations, LFS, 2FA"
msgid "Personal Access Token"
msgstr "Jeton d’accès personnel"
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "Pipeline"
@@ -6018,6 +6996,9 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Lancer"
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr "Veuillez accepter les conditions générales d’utilisation avant de continuer."
@@ -6030,9 +7011,15 @@ msgstr "Veuillez les convertir en %{link_to_git} et repasser par %{link_to_impor
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "Veuillez les convertir en dépôts Git sur Google Code et repasser par %{link_to_import_flow}."
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Veuillez saisir un nom descriptif pour votre groupe."
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Veuillez noter que cette application n’est pas fournie par GitLab, vous devriez vérifier son authenticité avant d’autoriser son accès."
@@ -6045,6 +7032,9 @@ msgstr "Veuillez résoudre le reCAPTCHA"
msgid "Please try again"
msgstr "Veuillez réessayer"
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr "Veuillez utiliser ce formulaire pour signaler à GitLab les utilisateurs qui créent des tickets ou des commentaires indésirables, ou qui se comportent de manière inappropriée."
@@ -6087,6 +7077,9 @@ msgstr "Étiquettes prioritaires"
msgid "Prioritized label"
msgstr "Étiquette prioritaire"
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr "Privé — l’accès au projet doit être autorisé explicitement pour chaque utilisateur et utilisatrice."
@@ -6108,9 +7101,18 @@ msgstr "Vous êtes sur le point de supprimer définitivement %{yourAccount}, ain
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 "Vous êtes sur le point de changer le nom d’utilisateur %{currentUsernameBold} en %{newUsernameBold}. Le profil et les projets seront redirigés vers l’espace de noms %{newUsername}, mais cette redirection expire si un nouvel utilisateur ou un nouveau groupe est créé avec l’ancien nom %{currentUsername}. Veuillez mettre à jour vos dépôts Git dès que possible."
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "Compte programmé pour suppression."
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr "Ajouter une clef"
@@ -6126,15 +7128,30 @@ msgstr "L’avatar sera supprimé. Êtesâ€vous sûr·e ?"
msgid "Profiles|Change username"
msgstr "Changer le nom d’utilisateur·rice"
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr "Choisir un fichier…"
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
-msgstr "Afficher les contributions de projets privés sur votre profil public sans aucune information sur les projets, les dépôts ou les organisations."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
msgid "Profiles|Clear status"
msgstr "Effacer le statut"
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Chemin d’accès actuel : %{path}"
@@ -6153,6 +7170,9 @@ msgstr "Supprimer votre compte ?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Supprimer un compte aura les conséquences suivantes :"
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr "Ne pas montrer sur le profil"
@@ -6162,6 +7182,12 @@ msgstr "Ne pas afficher les informations personnelles liées à l’activité su
msgid "Profiles|Edit Profile"
msgstr "Modifier le profil"
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Mot de passe incorrect"
@@ -6198,11 +7224,14 @@ msgstr "Supprimer l’avatar"
msgid "Profiles|Set new profile picture"
msgstr "Définir une nouvelle photo de profil"
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr "Certaines options ne sont pas disponibles pour les comptes LDAP"
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
-msgstr "Parlezâ€nous de vous en moins de 250 caractères."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "La taille de fichier maximale autorisée est de 200 Kio."
@@ -6210,8 +7239,8 @@ msgstr "La taille de fichier maximale autorisée est de 200 Kio."
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Ceci ne ressemble pas à une clef SSH publique, êtesâ€vous sûr(e) de vouloir l’ajouter ?"
-msgid "Profiles|This email will be displayed on your public profile."
-msgstr "Cette adresse de courriel sera affichée sur votre profil public."
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
msgstr "Cette adresse de courriel sera utilisée pour les opérations Web, telles que les modifications et les fusions. %{learn_more}"
@@ -6219,11 +7248,14 @@ msgstr "Cette adresse de courriel sera utilisée pour les opérations Web, telle
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr "Cet émoji et ce message apparaîtront sur votre profil et partout dans l’interface."
-msgid "Profiles|This feature is experimental and translations are not complete yet."
-msgstr "Cette fonctionnalité est expérimentale et les traductions ne sont pas encore complètes."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
-msgid "Profiles|This information will appear on your profile."
-msgstr "Cette information apparaîtra sur votre profil."
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Saisissez votre %{confirmationValue} pour confirmer :"
@@ -6249,12 +7281,15 @@ msgstr "Le changement de nom d’utilisateur a échoué : %{message}"
msgid "Profiles|Username successfully changed"
msgstr "Changement de nom d’utilisateur effectué"
-msgid "Profiles|Website"
-msgstr "Site Web"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
msgid "Profiles|What's your status?"
msgstr "Quel est votre statut ?"
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr "Vous pouvez changer votre avatar ici"
@@ -6273,17 +7308,20 @@ msgstr "Vous n’avez pas les autorisations suffisantes pour supprimer cet utili
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "Vous devez transférer la propriété ou supprimer ces groupes avant de pouvoir supprimer votre compte."
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Votre compte est actuellement propriétaire des groupes suivants :"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
-msgstr "Votre adresse de courriel a été automatiquement définie en fonction de votre compte %{provider_label}."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
-msgstr "Votre localisation a été automatiquement définie en fonction de votre compte %{provider_label}."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
-msgstr "Votre nom a été automatiquement défini en fonction de votre compte %{provider_label}, afin que les personnes que vous connaissez puissent vous identifier."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
msgid "Profiles|Your status"
msgstr "Votre statut"
@@ -6291,6 +7329,12 @@ msgstr "Votre statut"
msgid "Profiles|e.g. My MacBook key"
msgstr "p. ex., Ma clef MacBook"
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "votre compte"
@@ -6348,12 +7392,18 @@ msgstr "Le lien de l’exportation du projet a expiré. Merci de générer une n
msgid "Project export started. A download link will be sent by email."
msgstr "L’exportation du projet a débuté. Un lien de téléchargement sera envoyé par courriel."
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr "Nom du projet"
msgid "Project slug"
msgstr "Identifiant « slug » du projet"
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "S’abonner"
@@ -6498,9 +7548,6 @@ msgstr "Opérateur"
msgid "PrometheusAlerts|Threshold"
msgstr "Seuil"
-msgid "PrometheusDashboard|Time"
-msgstr "Heure"
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "%{exporters} avec %{metrics} ont été trouvés"
@@ -6525,6 +7572,9 @@ msgstr "Les métriques courantes sont automatiquement supervisées grâce à une
msgid "PrometheusService|Custom metrics"
msgstr "Métriques personnalisées"
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "Recherche et configuration des métriques en cours…"
@@ -6654,6 +7704,9 @@ msgstr "Fournisseur"
msgid "Pseudonymizer data collection"
msgstr "Collecte de données Pseudonymizer"
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "Public — le groupe ainsi que n’importe quel projet public est accessible sans authentification."
@@ -6693,21 +7746,30 @@ msgstr "Poussées Git"
msgid "Quarters"
msgstr "Trimestres"
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Les actions rapides peuvent être utilisées dans la description des tickets et dans les zones de commentaire."
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "Lire plus"
+msgid "Read more about environments"
+msgstr ""
+
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr "Pour en savoir plus sur les autorisations de projet : <strong>%{link_to_help}</strong>"
-msgid "Readme"
-msgstr "LisezMoi"
-
msgid "Real-time features"
msgstr "Fonctionnalités en temps réel"
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr "Recherches récentes"
@@ -6734,6 +7796,9 @@ msgstr "Expression rationnelle"
msgid "Register / Sign In"
msgstr "Inscription / Connexion"
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "Identifiezâ€vous et accédez à vos exécuteurs pour ce groupe."
@@ -6764,6 +7829,12 @@ msgstr "Demandes fusionnées liées"
msgid "Related merge requests"
msgstr "Demandes de fusion liées"
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "Me le rappeler ultérieurement"
@@ -6773,6 +7844,12 @@ msgstr "Supprimer"
msgid "Remove Runner"
msgstr "Supprimer l’exécuteur"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Supprimer l’avatar"
@@ -6803,9 +7880,15 @@ msgstr "Renommer le dossier"
msgid "Reopen epic"
msgstr "Rouvrir l’épopée"
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr "Réparer l’authentification"
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr "Répondez directement à ce courriel ou %{view_it_on_gitlab}."
@@ -6866,6 +7949,12 @@ msgstr "Paramètres du dépôt"
msgid "Repository URL"
msgstr "URL du dépôt"
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr "Le dépôt n’a aucun verrou."
@@ -6884,6 +7973,9 @@ msgstr "Sélectionner"
msgid "Request Access"
msgstr "Demander l’accès"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr "Profils de requêtes"
@@ -6893,12 +7985,27 @@ msgstr "Exiger de tous les utilisateurs de ce groupe la configuration de l’aut
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Exiger que tous les utilisateurs acceptent les conditions générales d’utilisation et la politique de confidentialité quand ils accèdent à GitLab."
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr "Réinitialiser le jeton d’accès au bilan de santé"
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "Réinitialiser le jeton d’inscription des exécuteurs"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr "Résoudre toutes les discussions dans un nouveau ticket"
@@ -6908,6 +8015,12 @@ msgstr "Résoudre les conflits sur la branche source"
msgid "Resolve discussion"
msgstr "Résoudre la discussion"
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr "Métriques de réponse (AWS ELB)"
@@ -6917,12 +8030,18 @@ msgstr "Métriques de réponse (personnalisées)"
msgid "Response metrics (HA Proxy)"
msgstr "Métriques de réponse (HA Proxy)"
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr "Métriques de réponse (nginx Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Métriques de réponse (nginx)"
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr "Reprendre"
@@ -6935,14 +8054,14 @@ msgstr "Relancer cette tâche"
msgid "Retry verification"
msgstr "Relancer la vérification"
-msgid "Reveal Variables"
-msgstr "Révéler les variables"
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] "Révéler la valeur"
msgstr[1] "Révéler les valeurs"
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Défaire ce commit"
@@ -6970,6 +8089,9 @@ msgstr "Feuille de route"
msgid "Run CI/CD pipelines for external repositories"
msgstr "Exécuter des pipelines CI / CD pour les dépôts externes"
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr "Exécuter les tâches non étiquetées"
@@ -6997,6 +8119,9 @@ msgstr "Exécuteurs"
msgid "Runners API"
msgstr "API des exécuteurs"
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Les exécuteurs peuvent être placés sur différents utilisateurs et serveurs, voire sur votre machine locale."
@@ -7030,8 +8155,8 @@ msgstr "Authentification unique SAML"
msgid "SAML Single Sign On Settings"
msgstr "Paramètres d’authentification unique SAML"
-msgid "SAST"
-msgstr "SAST"
+msgid "SAML for %{group_name}"
+msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "Empreinte SHA-1 du certificat de signature de jetons SAML. Obtenezâ€la auprès de votre fournisseur d’identité, parfois sous la dénomination « Thumbprint »."
@@ -7051,6 +8176,9 @@ msgstr "Vérification SSL"
msgid "Save"
msgstr "Enregistrer"
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr "Enregistrer l’application"
@@ -7060,6 +8188,9 @@ msgstr "Enregistrer les modifications"
msgid "Save changes before testing"
msgstr "Enregistrer les modifications avant de tester"
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Sauvegarder la planification du pipeline"
@@ -7096,6 +8227,9 @@ msgstr "Faire défiler vers le haut"
msgid "Search"
msgstr "Rechercher"
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr "Rechercher des branches"
@@ -7108,6 +8242,9 @@ msgstr "Rechercher des fichiers"
msgid "Search for projects, issues, etc."
msgstr "Rechercher des projets, des tickets, etc."
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr "Rechercher des demandes de fusion"
@@ -7177,23 +8314,26 @@ msgstr "Erreur lors de la récupération de la liste des vulnérabilités. Veuil
msgid "Security Dashboard|Issue Created"
msgstr "Ticket créé"
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
-msgstr "Pour le moment, le tableau de bord de sécurité ne prend uniquement en charge que SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
+msgstr ""
msgid "Security Reports|Create issue"
-msgstr ""
+msgstr "Créer un ticket"
msgid "Security Reports|Dismiss vulnerability"
+msgstr "Rejeter la vulnérabilité"
+
+msgid "Security Reports|Learn more about setting up your dashboard"
msgstr ""
msgid "Security Reports|More info"
msgstr "Plus d’informations"
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
-msgstr ""
+msgstr "Documentation du tableau de bord de sécurité"
msgid "Security Reports|There was an error creating the issue."
msgstr "Une erreur est survenue lors de la création du ticket."
@@ -7202,9 +8342,21 @@ msgid "Security Reports|There was an error dismissing the vulnerability."
msgstr "Une erreur est survenue lors du rejet de la vulnérabilité."
msgid "Security Reports|There was an error reverting the dismissal."
-msgstr ""
+msgstr "Une erreur est survenue lors de l’annulation du rejet."
msgid "Security Reports|There was an error reverting this dismissal."
+msgstr "Une erreur est survenue lors de l’annulation de ce rejet."
+
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -7216,6 +8368,12 @@ msgstr "Surveiller les vulnérabilités dans votre code"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "Pipeline %{pipelineLink} déclenché"
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr "Sélectionner"
@@ -7243,6 +8401,9 @@ msgstr "Sélectionner une personne assignée"
msgid "Select branch/tag"
msgstr "Sélectionner une branche ou une étiquette"
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr "Sélectionner un projet"
@@ -7276,9 +8437,15 @@ msgstr "Synchronisation sélective"
msgid "Send email"
msgstr "Envoyer un courriel"
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr "Envoyer des données d’utilisation"
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr "sept."
@@ -7288,6 +8455,48 @@ msgstr "septembre"
msgid "Server version"
msgstr "Version du serveur"
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr "Service d’assistance"
@@ -7318,6 +8527,9 @@ msgstr "Définissez le temps maximal de la session pour le terminal Web."
msgid "Set notification email for abuse reports."
msgstr "Définissez un courriel de notification pour les rapports d’abus."
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "Définissez les exigences pour la connexion d’un utilisateur. Activez l’authentification obligatoire à deux facteurs."
@@ -7333,6 +8545,9 @@ msgstr "Configurer automatiquement un exécuteur spécifique"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "Configure les assertions, attributs et revendications (courriel, prénom et nom), ainsi que le NameID, conformément à %{docsLinkStart}la documentation %{icon}%{docsLinkEnd}"
+msgid "Set up new U2F device"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Configurez votre projet afin de pouvoir pousser et/ou récupérer automatiquement les modifications vers ou depuis un autre dépôt. Les branches, les étiquetets et les commits seront automatiquement synchronisés."
@@ -7396,12 +8611,12 @@ msgstr "Afficher la commande"
msgid "Show complete raw log"
msgstr "Afficher le journal brut complet"
+msgid "Show file browser"
+msgstr ""
+
msgid "Show latest version"
msgstr "Afficher la dernière version"
-msgid "Show latest version of the diff"
-msgstr "Afficher la dernière version du diff"
-
msgid "Show parent pages"
msgstr "Afficher les pages parentes"
@@ -7437,12 +8652,21 @@ msgstr "Connexion"
msgid "Sign in / Register"
msgstr "Connexion / Inscription"
-msgid "Sign in to %{group_name}"
-msgstr "Se connecter au groupe %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
msgid "Sign in with Single Sign-On"
msgstr "Se connecter avec une authentification unique"
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr "Se déconnecter"
@@ -7452,6 +8676,9 @@ msgstr "Restrictions de connexion"
msgid "Sign-up restrictions"
msgstr "Restrictions d’inscription"
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr "Taille"
@@ -7468,14 +8695,23 @@ msgid "Slower but makes sure the project workspace is pristine as it clones the
msgstr "Plus lent, mais permet de s’assurer que l’espace de travail du projet est vierge, comme il clone le dépôt à partir de zéro pour chaque tâche"
msgid "Smartcard"
-msgstr ""
+msgstr "Carte à puce"
msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr "L’authentification par carte à puce a échoué : un enâ€tête de certificat client est manquant."
+
+msgid "Snippet Contents"
msgstr ""
msgid "Snippets"
msgstr "Extraits de code"
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr "Une erreur est survenue de notre côté"
@@ -7485,6 +8721,9 @@ msgstr "Une erreur est survenue de notre côté."
msgid "Something went wrong on our end. Please try again!"
msgstr "Quelque chose s’est mal passé de notre côté. Veuillez réessayer."
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr "Une erreur est survenue lors de la tentative de modification de la confidentialité de ce ticket"
@@ -7494,9 +8733,15 @@ msgstr "Une erreur est survenue lors de la tentative de modification de l’éta
msgid "Something went wrong when toggling the button"
msgstr "Une erreur s’est produite lors du basculement du bouton"
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "Une erreur s’est produite lors de la fermeture du / de la %{issuable}. Veuillez réessayer plus tard"
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr "Une erreur est survenue lors de la récupération de la liste de %{listType}"
@@ -7515,6 +8760,9 @@ msgstr "Une erreur s’est produite lors de la récupération des projets."
msgid "Something went wrong while fetching the registry list."
msgstr "Une erreur s’est produite lors de la récupération de la liste du registre."
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr "Désolé, aucune épopée ne correspond à votre recherche"
msgid "Sorry, no projects matched your search"
msgstr "Désolé, aucun projet ne correspond à votre recherche"
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr "Trier par"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr "Niveau d’accès, croissant"
@@ -7549,7 +8803,7 @@ msgid "SortOptions|Access level, descending"
msgstr "Niveau d’accès décroissant"
msgid "SortOptions|Created date"
-msgstr "Date de création"
+msgstr "Date de création décroissante"
msgid "SortOptions|Due date"
msgstr "Date d’échéance"
@@ -7579,7 +8833,7 @@ msgid "SortOptions|Last joined"
msgstr "Date de participation décroissante"
msgid "SortOptions|Last updated"
-msgstr "Mis à jour récemment"
+msgstr "Date de mise à jour décroissante"
msgid "SortOptions|Least popular"
msgstr "Popularité croissante"
@@ -7587,8 +8841,8 @@ msgstr "Popularité croissante"
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
-msgstr "Jalon"
+msgid "SortOptions|Milestone due date"
+msgstr ""
msgid "SortOptions|Milestone due later"
msgstr "Jalon avec une échéance lointaine"
@@ -7620,6 +8874,9 @@ msgstr "Date de création croissante"
msgid "SortOptions|Oldest joined"
msgstr "Ancienneté des participants croissante"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr "Date d’inscription croissante"
@@ -7632,6 +8889,9 @@ msgstr "Popularité"
msgid "SortOptions|Priority"
msgstr "Priorité"
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr "Date d’inscription décroissante"
@@ -7659,6 +8919,9 @@ msgstr "Code source"
msgid "Source is not available"
msgstr "La source n’est pas disponible"
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr "Journaux des messages indésirables"
@@ -7674,6 +8937,9 @@ msgstr "Spécifiez un motif d’expression rationnelle permettant l’identifica
msgid "Specify the following URL during the Runner setup:"
msgstr "Spécifiez l’URL suivante lors de la configuration de l’exécuteur :"
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr "Combiner (squash) les commits"
@@ -7710,6 +8976,12 @@ msgstr "Activité des projets favoris"
msgid "Starred projects"
msgstr "Projets favoris"
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "Créer une %{new_merge_request} avec ces changements"
@@ -7719,18 +8991,39 @@ msgstr "Démarrer une revue de code"
msgid "Start and due date"
msgstr "Dates de début et d’échéance"
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr "Date de début"
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Démarrer l’exécuteur !"
msgid "Start your trial"
-msgstr ""
+msgstr "Commencez votre essai gratuit"
msgid "Started"
msgstr "Démarré"
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "Démarre à (UTC)"
@@ -7740,6 +9033,12 @@ msgstr "Énoncez votre message à activer"
msgid "Status"
msgstr "État "
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr "Arrêter l’environnement"
@@ -7755,6 +9054,9 @@ msgstr "Arrêté"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr "L’arrêt de cet environnement est actuellement impossible car un déploiement est en cours"
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr "Stockage"
@@ -7770,6 +9072,9 @@ msgstr "Sousâ€groupes et projets"
msgid "Submit as spam"
msgstr "Soumettre comme indésirable"
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr "Envoyer la revue de code"
@@ -7785,11 +9090,95 @@ msgstr "S’abonner au niveau du groupe"
msgid "Subscribe at project level"
msgstr "S’abonner au niveau du projet"
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr "Abonné"
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
-msgstr "Résumé des tickets, demandes de fusion, poussages de code et commentaires (fuseau horaire : %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
msgid "Switch branch/tag"
msgstr "Changer de branche ou d’étiquette"
@@ -7803,8 +9192,11 @@ msgstr "« Hooks » système"
msgid "System Info"
msgstr "Informations système"
-msgid "System header and footer:"
-msgstr "Enâ€tête et pied de page du système :"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
msgid "System metrics (Custom)"
msgstr "Métriques du système (personnalisées)"
@@ -7812,10 +9204,11 @@ msgstr "Métriques du système (personnalisées)"
msgid "System metrics (Kubernetes)"
msgstr "Métriques du système (Kubernetes)"
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] "Étiquette (%{tag_count})"
-msgstr[1] "Étiquettes (%{tag_count})"
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "Étiquettes"
@@ -7910,6 +9303,12 @@ msgstr "Modèle"
msgid "Templates"
msgstr "Modèles "
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Conditions générales d’utilisation et politique de confidentialité"
@@ -7925,9 +9324,15 @@ msgstr "Analyse de la couverture des tests"
msgid "Thanks! Don't show me this again"
msgstr "Merci ! Ne plus afficher ce message"
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global 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 "La recherche globale avancée de Gitlab est un outil puissant qui vous fait gagner du temps. Au lieu de perdre du temps à recréer du code existant, vous pouvez maintenant faire des recherches dans le code d’autres équipes afin de vous aider sur votre projet."
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr "Les objets Git LFS <strong>ne sont pas</strong> synchronisés."
@@ -7964,6 +9369,9 @@ msgstr "L’importation expirera après %{timeout}. Pour les dépôts qui prenne
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Le présentoir des tickets affiche le temps nécessaire entre la création d’un ticket et son assignation à un jalon ou son ajout à une liste dans votre tableau de tickets. Commencez par créer des tickets pour voir des données sur ce présentoir."
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr "La taille maximale autorisée pour un fichier est de 200 Kio."
@@ -8042,17 +9450,35 @@ msgstr "La carte des utilisateurs met en correspondance les utilisateurs de FogB
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "La valeur située au point médian d’une série de valeur observée. Par exemple., entre 3, 5 et 9, le médian est 5. Entre 3, 5, 7 et 8, le médian est (5+7)/2 = 6."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Il n’y a pas encore de projets archivés"
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr "Il n’y a aucun ticket à afficher"
msgid "There are no labels yet"
msgstr "Il n’y a pas encore d’étiquette"
-msgid "There are no merge requests to show"
-msgstr "Il n’y a aucune demande de fusion à afficher"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
msgid "There are no projects shared with this group yet"
msgstr "Il n’y a pas encore de projets partagés avec ce groupe"
@@ -8087,12 +9513,21 @@ msgstr "Une erreur s’est produite lors de l’abonnement à cette étiquette."
msgid "There was an error when unsubscribing from this label."
msgstr "Une erreur s’est produite lors de la désinscription à cette étiquette."
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr "Ils peuvent être gérés en utilisant %{link}."
msgid "Third party offers"
msgstr "Offres tierces"
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "Cette instance de GitLab ne fournit aucun exécuteur partagé pour le moment. Les administra·teur·trice·s de l’instance peuvent enregistrer des exécuteurs partagés dans la zone d’administration."
@@ -8120,15 +9555,18 @@ msgstr "Cette date est antérieure à la date de début, cette épopée n’appa
msgid "This diff is collapsed."
msgstr "Ce diff est replié."
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr "Ce répertoire"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
msgid "This group"
msgstr "Ce groupe"
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr "Ce groupe vous autorise à vous connecter avec votre compte d’authentification unique %{group_name}. Vous serez alors redirigé vers une page d’authentification externe."
-
msgid "This group does not provide any group Runners yet."
msgstr "Ce groupe ne fournit pas encore d’exécuteurs de groupe."
@@ -8189,11 +9627,11 @@ msgstr "Cette tâche va effectuer un déploiement sur %{environmentLink}."
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "Cette tâche est en attente d’être choisie par un exécuteur"
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
-msgstr "Cette tâche est bloquée parce que vous n’avez aucun exécuteur actif en ligne auquel l’une des étiquettes suivantes est assignée :"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
-msgstr "Cette tâche est bloquée parce que vous n’avez aucun exécuteur actif pouvant la prendre en charge."
+msgid "This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
msgid "This job is the most recent deployment to %{link}."
msgstr "Cette tâche est le déploiement le plus récent sur %{link}."
@@ -8201,8 +9639,8 @@ msgstr "Cette tâche est le déploiement le plus récent sur %{link}."
msgid "This job requires a manual action"
msgstr "Cette tâche nécessite une action manuelle"
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
-msgstr "Cette tâche s’exécutera automatiquement à l’heure programmée. Les tâches programmées sont souvent utilisées pour les déploiements continus dans des environnements de production. Lorsqu’elles sont déprogrammées, elles deviennent des tâches qui peuvent être démarrées manuellement."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Cela signifie que vous ne pouvez pas pousser du code tant que vous n’avez pas créé un dépôt vide ou que vous n’avez pas importé un dépôt existant."
@@ -8222,6 +9660,15 @@ msgstr "Cette page n’est pas disponible car vous n’êtes pas autorisé à li
msgid "This page will be removed in a future release."
msgstr "Cette page sera supprimée dans une version ultérieure."
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr "Ce projet"
@@ -8249,8 +9696,8 @@ msgstr "Ce paramètre modifie le nom d’hôte qui est utilisé pour générer d
msgid "This source diff could not be displayed because it is too large."
msgstr "Ce diff n’a pas pu être affiché car il est trop grand."
-msgid "This timeout will take precedence when lower than Project-defined timeout"
-msgstr "Ce délai d’attente aura préséance lorsqu’il est inférieur au délai d’attente défini pour le projet"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
+msgstr ""
msgid "This user has no identities"
msgstr "Cet utilisateur ou cette utilisatrice n’a aucune identité"
@@ -8261,8 +9708,8 @@ msgstr "Cet utilisateur sera l’auteur de tous les événements du flux d’act
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr "Cet utilisateur sera l’auteur de tous les événements du flux d’activité résultant d’une mise à jour, comme la création de nouvelles branches ou les nouveaux commits poussés vers des branches existantes. Lors de la création ou lors de la réaffectation, vous ne pouvez assigner que vousâ€même comme utilisateur du miroir."
-msgid "This will delete the custom metric, Are you sure?"
-msgstr "Ceci va supprimer la métrique personnalisée. Êtesâ€vous sûr(e) ?"
+msgid "This will redirect you to an external sign in page."
+msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "Ces courriels deviennent automatiquement des tickets (dont les commentaires résultent de la conversation par courriel) répertoriés ici."
@@ -8454,9 +9901,18 @@ msgstr "Astuce :"
msgid "Title"
msgstr "Titre"
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr "Vers GitLab"
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "Afin d’ajouter une clef SSH, vous devez soit %{generate_link_start}en génèrer une%{link_end}, soit utiliser une %{existing_link_start}clef existante%{link_end}."
@@ -8499,14 +9955,29 @@ msgstr "Pour importer des dépôts GitHub, vous devez d’abord autoriser GitLab
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "Pour importer un dépôt SVN, consultez %{svn_link}."
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr "Pour déplacer ou copier un projet GitLab entier depuis une autre installation de GitLab vers celleâ€ci, accédez à la page des paramètres du projet d’origine, générez un fichier d’exportation et téléversezâ€le ici."
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "Pour n’utiliser uniquement que les fonctionnalités d’intégration et livraison continues (CI / CD) pour un dépôt externe, choisissez <strong>Intégration et livraison continues (CI / CD) pour dépôt externe</strong>."
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
-msgstr "Afin d’ouvrir Jaeger pour visualiser facilement le traçage de GitLab, créez un lien vers la page %{start_tag}Traçage%{end_tag} sur votre serveur"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "Pour configurer l’authentification SAML pour votre groupe via un fournisseur d’identité tel qu’Azure, Okta, Onelogin, Ping Identity ou votre fournisseur SAML 2.0 personnalisé :"
@@ -8514,6 +9985,9 @@ msgstr "Pour configurer l’authentification SAML pour votre groupe via un fourn
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Pour commencer à exécuter vos tâches, vous pouvez ajouter des exécuteurs à votre groupe"
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr "À cette instance de GitLab"
@@ -8523,6 +9997,9 @@ msgstr "Pour valider vos configurations GitLab CI, allez dans « CI / CD Â
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "Afin d’afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€mensuelle, seules les épopées du mois dernier, du mois courant et des cinq prochains mois sont affichées."
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des filtres."
@@ -8538,15 +10015,18 @@ msgstr "À faire"
msgid "Toggle Sidebar"
msgstr "Afficher/masquer la barre latérale"
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr "Afficher ou masquer la description du commit"
+msgid "Toggle commit list"
+msgstr ""
+
msgid "Toggle discussion"
msgstr "Basculer la discussion"
-msgid "Toggle file browser"
-msgstr "Afficher/masquer le navigateur de fichiers"
-
msgid "Toggle navigation"
msgstr "Activer/désactiver la navigation"
@@ -8598,9 +10078,6 @@ msgstr "Vue arborescente"
msgid "Trending"
msgstr "Tendance"
-msgid "Trigger"
-msgstr "Déclencheur"
-
msgid "Trigger pipelines for mirror updates"
msgstr "Déclencher des pipelines pour les mises à jour de miroirs"
@@ -8610,6 +10087,12 @@ msgstr "Déclenche les pipelines lorsque les branches ou les étiquettes sont mi
msgid "Trigger this manual action"
msgstr "Déclencher cette action manuelle"
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "Les déclencheurs peuvent forcer la reconstruction pour une branche ou une étiquette spécifique via l’appel à une API. Ces jetons emprunteront l’identité de l’utilisateur auquel ils sont associés, ainsi que ses accès et permissions sur les projets."
@@ -8619,7 +10102,13 @@ msgstr "Dépanner et surveiller votre application grâce au traçage"
msgid "Try again"
msgstr "Veuillez réessayer"
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
+msgstr "Essayez tout ce que GitLab peut vous offrir pendant 30 jours."
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
msgid "Turn on Service Desk"
@@ -8634,21 +10123,27 @@ msgstr "Authentification à double facteur"
msgid "Type"
msgstr "Type"
+msgid "URL"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Impossible de charger le diff. %{button_try_again}"
-msgid "Unable to save your changes"
-msgstr "Impossible d’enregistrer les modifications"
-
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Impossible de vous connecter au groupe via SAML en raison de « %{reason} »"
msgid "Unable to update this epic at this time."
msgstr "Impossible de mettre à jour cette épopée pour le moment."
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr "Annuler"
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr "Inconnu"
@@ -8697,6 +10192,9 @@ msgstr "Se désabonner au niveau du groupe"
msgid "Unsubscribe at project level"
msgstr "Se désabonner au niveau du projet"
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr "Non vérifié"
@@ -8709,6 +10207,9 @@ msgstr "À venir"
msgid "Update"
msgstr "Mettre à jour"
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr "Mettre à jour maintenant"
@@ -8718,6 +10219,9 @@ msgstr "Modifiez le nom du groupe, sa description, son avatar et sa visibilité.
msgid "Updating"
msgstr "Mise à jour en cours"
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "Mettez à niveau votre forfait pour activer la recherche globale avancée."
@@ -8736,15 +10240,30 @@ msgstr "Mettez à niveau votre forfait pour améliorer les tableaux de tickets."
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr "Téléversez le fichier <code>GoogleCodeProjectHosting.json</code> ici :"
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "Téléverser un nouveau fichier"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "Téléverser un fichier"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "Cliquez pour envoyer"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr "Votes positifs"
@@ -8775,9 +10294,15 @@ msgstr "Utiliser le jeton d’inscription suivant pendant l’installation :"
msgid "Use your global notification setting"
msgstr "Utiliser vos paramètres de notification globaux"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Utilisé par les membres pour se connecter à votre groupe dans GitLab"
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr "Les cohortes d’utilisateurs ne sont affichées que lorsque la %{usage_ping_link_start}collecte des données d’utilisation%{usage_ping_link_end} est activée."
@@ -8802,47 +10327,83 @@ msgstr "À contribué aux projets"
msgid "UserProfile|Edit profile"
msgstr "Modifier le profil"
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr "Groupes"
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr "Activité la plus récente"
+msgid "UserProfile|No snippets found."
+msgstr ""
+
msgid "UserProfile|Overview"
msgstr "Vue d’ensemble"
msgid "UserProfile|Personal projects"
msgstr "Projets personnels"
-msgid "UserProfile|Recent contributions"
-msgstr "Contributions récentes"
-
msgid "UserProfile|Report abuse"
msgstr "Signaler un abus"
msgid "UserProfile|Snippets"
msgstr "Fragments de code"
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr "S’abonner"
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr "Cet utilisateur a un profil privé"
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "Tout afficher"
msgid "UserProfile|View user in admin area"
msgstr "Afficher l’utilisateur dans l’espace d’administration"
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr "Utilisateurs et utilisatrices"
-msgid "Variables"
-msgstr "Variables"
+msgid "Users requesting access to"
+msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr "Les variables sont appliquées aux environnements via l’exécuteur. Elles peuvent être protégées en les exposant uniquement à des branches ou des tags protégées. Vous pouvez utiliser des variables pour les mots de passe, les clés secrètes ou tout ce que vous voulez."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
msgid "Various container registry settings."
msgstr "Divers paramètres de registre de conteneur."
@@ -8850,12 +10411,18 @@ msgstr "Divers paramètres de registre de conteneur."
msgid "Various email settings."
msgstr "Divers paramètres de courriel."
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr "Divers paramètres qui affectent les performances de GitLab."
msgid "Verification information"
msgstr "Informations de vérification"
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr "Vérifié"
@@ -8868,6 +10435,12 @@ msgstr "Afficher les %{alerts}"
msgid "View app"
msgstr "Voir l’application"
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr "Voir la documentation"
@@ -8907,6 +10480,9 @@ msgstr "Voir le fichier remplacé @ "
msgid "View the documentation"
msgstr "Afficher la documentation"
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "Contrôles de visibilité et d’accès"
@@ -8931,6 +10507,12 @@ msgstr "Public"
msgid "VisibilityLevel|Unknown"
msgstr "Inconnu"
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr "Classe"
@@ -8955,27 +10537,48 @@ msgstr "Liens"
msgid "Vulnerability|Project"
msgstr "Projet"
+msgid "Vulnerability|Report Type"
+msgstr ""
+
msgid "Vulnerability|Severity"
msgstr "Gravité"
-msgid "Vulnerability|Solution"
-msgstr "Solution"
-
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Vous voulez voir les données ? Merci de contacter un administrateur pour en obtenir l’accès."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Nous avons détecté un potentiel courriel indésirable dans %{humanized_resource_name}. Veuillez résoudre le reCAPTCHA pour continuer."
msgid "We don't have enough data to show this stage."
msgstr "Nous n’avons pas suffisamment de données pour afficher cette étape."
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Nous voulons nous assurer qu’il s’agit bien de vous, merci de confirmer que vous n’êtes pas un robot."
msgid "Web IDE"
msgstr "EDI Web"
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr "Terminal Web"
@@ -9000,6 +10603,9 @@ msgstr "Lorsque cette option est activée, les utilisateurs et utilisarices ne p
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Lorsque vous laissez l’URL vide, des étiquettes de classification peuvent toujours être spécifiées sans désactiver les fonctionnalités interâ€projets ni effectuer de vérifications d’autorisation externes."
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr "Qui peut voir ce groupe ?"
@@ -9141,12 +10747,21 @@ msgstr "Pages"
msgid "Wiki|Wiki Pages"
msgstr "Pages du Wiki"
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr "Grâce à l’analyse des contributions, vous pouvez avoir une vue d’ensemble de l’activité concernant les tickets, les demandes de fusion et les poussées Git de l’ensemble de votre organisation et de chacun de ses membres."
msgid "Withdraw Access Request"
msgstr "Retirer la demande d’accès"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr "Oui"
@@ -9159,6 +10774,9 @@ msgstr "Oui, permettezâ€moi d’associer les utilisateurs de Google Code aux n
msgid "Yesterday"
msgstr "Hier"
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Vous êtes un administrateur ou une administratrice, ce qui signifie qu’accorder un accès à <strong>%{client_name}</strong> lui permettra d’interagir avec GitLab en tant qu’administrateur également. Faitesâ€le avec prudence."
@@ -9177,6 +10795,9 @@ msgstr "Vous allez transférer %{project_full_name} à un nouveau ou une nouvell
msgid "You are on a read-only GitLab instance."
msgstr "Vous êtes sur une instance GitLab en lecture seule."
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "Vous pouvez %{linkStart}afficher les données brutes%{linkEnd} à la place."
@@ -9201,6 +10822,9 @@ msgstr "Vous ne pouvez ajouter de fichier que dans une branche"
msgid "You can only edit files when you are on a branch"
msgstr "Vous ne pouvez modifier des fichiers que dans une branche"
+msgid "You can only merge once the items above are resolved"
+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 "Vous pouvez résoudre le conflit de fusion Git soit en mode interactif, en cliquant sur les boutons « %{use_ours} » ou « %{use_theirs} », soit en modifiant directement les fichiers. Valider ces modifications dans la branche « %{branch_name} »"
@@ -9219,6 +10843,9 @@ msgstr "Vous ne pouvez pas écrire sur cette instance GitLab en lecture seule."
msgid "You do not have any subscriptions yet"
msgstr "Vous n’avez souscrit à aucun abonnement pour le moment"
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "Vous ne disposez pas des autorisations appropriées pour outrepasser les paramètres de synchronisation du groupe LDAP."
@@ -9228,12 +10855,18 @@ msgstr "Vous ne disposez d’aucune application"
msgid "You don't have any authorized applications"
msgstr "Vous ne disposez d’aucune application autorisée"
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr "Vous n’avez pas les autorisations"
msgid "You have reached your project limit"
msgstr "Vous avez atteint votre limite de projet"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr "Vous devez accepter les conditions générales d’utilisation et la politique de confidentialité afin de pouvoir vous créer un compte"
@@ -9243,17 +10876,23 @@ msgstr "Seul un responsable peut forcer la suppression d’un verrou"
msgid "You need a different license to enable FileLocks feature"
msgstr "Vous avez besoin d’une licence différente pour activer la fonctionnalité de verrouillage de fichiers FileLocks"
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr "Pour aller plus loin, vous devez disposer de git-lfs en version %{min_git_lfs_version} (ou supérieure). Veuillez consulter https://git-lfs.github.com"
msgid "You need permission."
msgstr "Vous avez besoin d’une autorisation."
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
-msgstr "Vous allez perdre toutes les modifications apportées à ce fichier. Cette action ne peut pas être annulée."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
-msgstr "Vous allez perdre toutes les modifications non indexées que vous avez effectuées sur ce projet. Cette action ne peut pas être annulée."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
msgid "You will not get any notifications via email"
msgstr "Vous ne recevrez aucune notification par courriel"
@@ -9271,13 +10910,13 @@ msgid "You will receive notifications only for comments in which you were @menti
msgstr "Vous ne recevrez de notifications que pour les commentaires où vous êtes @mentionné"
msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
-msgstr "Vous ne pourrez pas récupérer ou pousser de code via %{protocol} tant que vous n’aurez pas %{set_password_link} pour votre compte"
+msgstr "Vous devez %{set_password_link} pour votre compte afin de pouvoir récupérer ou pousser du code via %{protocol}"
msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
-msgstr "Vous ne pourrez pas récupérer ou pousser de code par SSH tant que vous n’aurez pas %{add_ssh_key_link} dans votre profil"
+msgstr "Vous devez %{add_ssh_key_link} dans votre profil afin de pouvoir récupérer ou pousser du code via SSH"
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
-msgstr "Vous ne pourrez pas récupérer ou pousser de code par SSH tant que vous n’aurez pas ajouté de clé SSH à votre profil"
+msgstr "Vous ne pourrez pas récupérer ou pousser de code via SSH tant que vous n’aurez pas ajouté de clef SSH à votre profil"
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "Vous devrez utiliser différents noms de branches pour obtenir une comparaison valide."
@@ -9294,6 +10933,9 @@ msgstr "Vous recevez ce courriel en raison de votre compte sur %{host}. %{manage
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr "Vos groupes"
@@ -9309,12 +10951,18 @@ msgstr "Activité de vos projets favoris"
msgid "Your Todos"
msgstr "Vos tâches à faire"
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr "Vos applications (%{size})"
msgid "Your authorized applications"
msgstr "Vos applications autorisées"
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "Vos modifications peuvent être validées sur %{branch_name} car une demande de fusion est ouverte."
@@ -9327,12 +10975,24 @@ msgstr "Vos modifications ont été enregistrées"
msgid "Your comment will not be visible to the public."
msgstr "Votre commentaire ne sera pas visible publiquement."
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "Vos groupes"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "Votre nom"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr "Vos projets"
@@ -9342,12 +11002,18 @@ msgstr "un utilisateur supprimé"
msgid "ago"
msgstr "auparavant "
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr "entre autres choses"
msgid "assign yourself"
msgstr "assignez vous"
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr "nom de la branche"
@@ -9440,6 +11106,9 @@ msgstr "L’analyse des conteneurs permet la détection de vulnérabilités conn
msgid "ciReport|DAST"
msgstr "DAST"
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr "L’analyse des dépendances a détecté une vulnérabilité connue dans les dépendances de votre code source."
@@ -9455,6 +11124,12 @@ msgstr "Rejeter la vulnérabilité"
msgid "ciReport|Dismissed by"
msgstr "Rejeté par"
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr "Le test de sécurité d’applications dynamique (Dynamic Application Security Testing — DAST) a détecté une vulnérabilité connue dans votre application Web."
@@ -9575,6 +11250,9 @@ msgstr "dans le pipeline"
msgid "command line instructions"
msgstr "instructions en ligne de commande"
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr "Vous êtes sur le point de désactiver la confidentialité. Cela signifie que <strong>tout le monde</strong> sera en mesure de voir et de laisser un commentaire sur ce ticket."
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] "jour"
msgstr[1] "jours"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr "jeton de déploiement"
msgid "disabled"
msgstr "désactivé"
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr "terminé"
@@ -9612,6 +11298,15 @@ msgstr[1] "brouillons"
msgid "enabled"
msgstr "activé"
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} mettra à jour la durée estimée avec la dernière commande."
@@ -9621,21 +11316,39 @@ msgstr "pour ce projet"
msgid "from"
msgstr "de"
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr "aide"
msgid "here"
msgstr "ici"
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://votre-serveur-bitbucket"
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr "flux d’importation"
msgid "importing"
msgstr "importation en cours"
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "instance terminée"
@@ -9650,9 +11363,27 @@ msgstr "n’est pas valide, car il y a un verrou en amont"
msgid "is not a valid X509 certificate."
msgstr "n’est pas un certificat X.509 valide."
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr "tableaux des tickets"
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr "dernier déploiement"
@@ -9665,14 +11396,29 @@ msgstr "gestion des licences"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "verrouillé par %{path_lock_user_name} %{created_at}"
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "demande de fusion"
msgstr[1] "demandes de fusion"
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Veuillez la restaurer ou utiliser une autre branche %{missingBranchName}"
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr "%{metricsLinkStart}L’usage mémoire%{metricsLinkEnd} %{emphasisStart}a diminué%{emphasisEnd} de %{memoryFrom}MO à %{memoryTo}MO"
@@ -9688,11 +11434,11 @@ msgstr "Ajouter une approbation"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Autoriser les commits des membres qui peuvent fusionner dans la branche cible"
-msgid "mrWidget|An error occured while removing your approval."
-msgstr "Une erreur est survenue lors de la suppression de votre approbation."
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
-msgstr "Une erreur est survenue lors de la récupération des données d’approbation pour cette demande de fusion."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Une erreur est survenue lors de l’envoi de votre approbation."
@@ -9730,6 +11476,9 @@ msgstr "Résout"
msgid "mrWidget|Create an issue to resolve them later"
msgstr "Créer un ticket pour les résoudre plus tard"
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Les statistiques de déploiement ne sont pas disponibles pour le moment"
@@ -9802,12 +11551,6 @@ msgstr "Actualiser maintenant"
msgid "mrWidget|Refreshing now"
msgstr "Actualisation en cours"
-msgid "mrWidget|Remove Source Branch"
-msgstr "Supprimer la branche source"
-
-msgid "mrWidget|Remove source branch"
-msgstr "Supprimer la branche source"
-
msgid "mrWidget|Remove your approval"
msgstr "Supprimer votre approbation"
@@ -9854,20 +11597,20 @@ msgstr "Le pipeline de cette demande de fusion a échoué. Veuillez réexécutez
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "La branche source HEAD a changé récemment. Veuillez recharger la page et vérifier les modifications avant d’effectuer la fusion"
-msgid "mrWidget|The source branch has been removed"
-msgstr "La branche source a été supprimée"
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr "La branche source est à %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} de la branche cible"
-msgid "mrWidget|The source branch is being removed"
-msgstr "La branche source est en cours de suppression"
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
-msgid "mrWidget|The source branch will be removed"
-msgstr "La branche source sera supprimée"
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
-msgid "mrWidget|The source branch will not be removed"
-msgstr "La branche source ne sera pas supprimée"
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "Il y a des conflits de fusion"
@@ -9875,6 +11618,9 @@ msgstr "Il y a des conflits de fusion"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "Il y a des discussions non résolues. Veuillez résoudre ces discussions"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Cette demande de fusion n’a pas pu être fusionnée automatiquement"
@@ -9887,12 +11633,12 @@ msgstr "Ce projet est archivé, l’accès en écriture a été désactivé"
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr "Vous n’êtes pas autorisé à modifier directement ce projet. Veuillez créer un projet divergent afin d’effectuer des changements."
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "Vous pouvez fusionner cette demande de fusion manuellement à l’aide de la"
-msgid "mrWidget|You can remove source branch now"
-msgstr "Vous pouvez maintenant supprimer la branche source"
-
msgid "mrWidget|branch does not exist."
msgstr "la branche n’existe pas."
@@ -9911,9 +11657,21 @@ msgstr "non disponible"
msgid "new merge request"
msgstr "nouvelle demande de fusion"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "courriels de notification"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr "ou"
@@ -9933,6 +11691,9 @@ msgstr "mot de passe"
msgid "personal access token"
msgstr "jeton d’accès personnel"
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr "la clef privée ne correspond pas au certificat."
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] "projet"
msgstr[1] "projets"
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr "restant"
@@ -9953,28 +11720,58 @@ msgstr "supprimer la date d’échéance"
msgid "remove weight"
msgstr "supprimer le poids"
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] "réponse"
msgstr[1] "réponses"
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr "source"
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} mettra à jour la somme du temps passé."
msgid "started"
msgstr "démarré"
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr "ce document"
msgid "to help your contributors communicate effectively!"
msgstr "pour aider vos contributeurs à communiquer efficacement !"
-msgid "toggle collapse"
-msgstr "déplier ou replier"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
+msgstr ""
msgid "username"
msgstr "nom d’utilisateur"
@@ -9982,9 +11779,15 @@ msgstr "nom d’utilisateur"
msgid "uses Kubernetes clusters to deploy your code!"
msgstr "utilise les grappes de serveurs Kubernetes pour déployer votre code !"
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "voir sur GitLab"
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "avec %{additions} ajouts, %{deletions} suppressions."
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] "dans %d minute "
msgstr[1] "dans les %d minutes"
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index b27efe04966..9552dd03039 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -19,15 +19,8 @@ msgstr ""
msgid " Status"
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or "
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -39,10 +32,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -103,6 +94,9 @@ msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -123,13 +117,16 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
-msgid "%{loadingIcon} Started"
+msgid "%{label_for_message} unavailable"
msgstr ""
-msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
@@ -179,12 +176,18 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -276,12 +279,27 @@ msgstr ""
msgid "<strong>%{group_name}</strong> group members"
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
+msgid "A .NET Core console application template, customizable for any .NET Core project"
+msgstr ""
+
+msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
@@ -297,6 +315,9 @@ msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
+msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
@@ -363,15 +384,39 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a bullet list"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
+
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
+msgid "Add a link"
+msgstr ""
+
+msgid "Add a numbered list"
+msgstr ""
+
msgid "Add a table"
msgstr ""
+msgid "Add a task list"
+msgstr ""
+
+msgid "Add bold text"
+msgstr ""
+
+msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgstr ""
+
msgid "Add image comment"
msgstr ""
+msgid "Add italic text"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -384,6 +429,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -435,6 +483,9 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
@@ -444,9 +495,30 @@ msgstr ""
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -459,18 +531,51 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "After a successful password update you will be redirected to login screen."
+msgstr ""
+
msgid "All"
msgstr ""
@@ -480,6 +585,9 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
@@ -504,6 +612,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -522,16 +633,13 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while fetching the releases. Please try again."
+msgid "An error occurred creating the new branch."
msgstr ""
-msgid "An error occurred creating the new branch."
+msgid "An error occurred fetching the dropdown data."
msgstr ""
msgid "An error occurred previewing the blob"
@@ -570,6 +678,9 @@ msgstr ""
msgid "An error occurred while fetching the pipeline."
msgstr ""
+msgid "An error occurred while fetching the releases. Please try again."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -609,6 +720,9 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
msgid "An error occurred whilst fetching the job trace."
msgstr ""
@@ -681,6 +795,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -690,12 +807,18 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -708,6 +831,9 @@ msgstr ""
msgid "Are you sure you want to stop this environment?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -729,6 +855,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -750,6 +879,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -801,15 +933,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -849,10 +972,7 @@ msgstr ""
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
-msgstr ""
-
-msgid "Available group Runners : %{runners}."
+msgid "Available group Runners: %{runners}"
msgstr ""
msgid "Available shared Runners:"
@@ -864,12 +984,18 @@ msgstr ""
msgid "Avatar for %{assigneeName}"
msgstr ""
+msgid "Avatar for %{name}"
+msgstr ""
+
msgid "Avatar will be removed. Are you sure?"
msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Background Color"
+msgstr ""
+
msgid "Background Jobs"
msgstr ""
@@ -969,6 +1095,9 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
msgid "Blocked"
msgstr ""
@@ -1146,6 +1275,9 @@ msgstr ""
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI/CD"
msgstr ""
@@ -1176,9 +1308,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1188,7 +1317,7 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
@@ -1215,6 +1344,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Change permissions"
msgstr ""
@@ -1239,6 +1377,9 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
+msgid "Changes"
+msgstr ""
+
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
@@ -1251,9 +1392,15 @@ msgstr ""
msgid "Chat"
msgstr ""
+msgid "Check again"
+msgstr ""
+
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
@@ -1281,6 +1428,9 @@ msgstr ""
msgid "Choose a file"
msgstr ""
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1299,7 +1449,10 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
-msgid "Choose which repositories you want to import."
+msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
+msgstr ""
+
+msgid "Choose your merge method, set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -1392,6 +1545,9 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
+msgid "Clear"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1437,15 +1593,30 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|%{title} upgraded successfully."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
@@ -1467,12 +1638,15 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgid "ClusterIntegration|Alternatively"
msgstr ""
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
+msgid "ClusterIntegration|An error occurred while trying to fetch project zones: %{error}"
+msgstr ""
+
msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
@@ -1482,9 +1656,15 @@ msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -1761,6 +1941,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -1803,12 +1986,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -1824,6 +2013,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -1836,6 +2037,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1863,6 +2067,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1878,6 +2085,12 @@ msgstr ""
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -1895,9 +2108,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
+
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -1961,6 +2180,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2060,6 +2282,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2159,6 +2384,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2204,6 +2432,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2243,6 +2474,9 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created on"
+msgstr ""
+
msgid "Created on:"
msgstr ""
@@ -2273,12 +2507,18 @@ msgstr ""
msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
msgstr ""
+msgid "Customize colors"
+msgstr ""
+
msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2309,6 +2549,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2318,6 +2561,12 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -2336,6 +2585,12 @@ msgstr ""
msgid "Default Branch"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2375,6 +2630,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2509,6 +2770,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2587,9 +2851,18 @@ msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2608,6 +2881,9 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
msgid "Download asset"
msgstr ""
@@ -2650,6 +2926,9 @@ msgstr ""
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2674,6 +2953,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Email"
msgstr ""
@@ -2686,6 +2968,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Emojis|Something went wrong while loading emojis."
+msgstr ""
+
msgid "Empty file"
msgstr ""
@@ -2704,12 +2989,18 @@ msgstr ""
msgid "Enable and configure Prometheus metrics."
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
msgid "Enable group Runners"
msgstr ""
+msgid "Enable header and footer in emails"
+msgstr ""
+
msgid "Enable or disable version check and usage ping."
msgstr ""
@@ -2722,6 +3013,9 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -2758,6 +3052,9 @@ msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
msgstr ""
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
@@ -2770,6 +3067,12 @@ msgstr ""
msgid "Environments|An error occurred while making the request."
msgstr ""
+msgid "Environments|An error occurred while re-deploying the environment, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while rolling back the environment, please try again"
+msgstr ""
+
msgid "Environments|An error occurred while stopping the environment, please try again"
msgstr ""
@@ -2815,15 +3118,33 @@ msgstr ""
msgid "Environments|Open live environment"
msgstr ""
+msgid "Environments|Re-deploy"
+msgstr ""
+
+msgid "Environments|Re-deploy environment %{environment_name}?"
+msgstr ""
+
+msgid "Environments|Re-deploy environment %{name}?"
+msgstr ""
+
msgid "Environments|Re-deploy to environment"
msgstr ""
msgid "Environments|Read more about environments"
msgstr ""
+msgid "Environments|Rollback"
+msgstr ""
+
msgid "Environments|Rollback environment"
msgstr ""
+msgid "Environments|Rollback environment %{environment_name}?"
+msgstr ""
+
+msgid "Environments|Rollback environment %{name}?"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -2836,6 +3157,18 @@ msgstr ""
msgid "Environments|Stopping"
msgstr ""
+msgid "Environments|This action will relaunch the job for commit %{commit_id}, putting the environment in a previous version. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will run the job defined by staging for commit %{commit_id}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -2851,6 +3184,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating a new path"
+msgstr ""
+
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -2893,9 +3235,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -2905,6 +3253,39 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "ErrorTracking|Active"
+msgstr ""
+
+msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgstr ""
+
+msgid "ErrorTracking|Auth Token"
+msgstr ""
+
+msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgstr ""
+
+msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgstr ""
+
+msgid "ErrorTracking|Find your hostname in your Sentry account settings page"
+msgstr ""
+
+msgid "ErrorTracking|No projects available"
+msgstr ""
+
+msgid "ErrorTracking|Select project"
+msgstr ""
+
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -2926,6 +3307,9 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
msgstr ""
@@ -2944,12 +3328,33 @@ msgstr ""
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
msgid "Existing Git repository"
msgstr ""
msgid "Existing folder"
msgstr ""
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -2992,6 +3397,9 @@ msgstr ""
msgid "External URL"
msgstr ""
+msgid "External Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -3013,6 +3421,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3031,6 +3442,9 @@ msgstr ""
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
@@ -3043,9 +3457,17 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "File added"
msgstr ""
+msgid "File browser"
+msgstr ""
+
msgid "File deleted"
msgstr ""
@@ -3058,6 +3480,9 @@ msgstr ""
msgid "File templates"
msgstr ""
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3067,15 +3492,27 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
msgid "Filter by two-factor authentication"
msgstr ""
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3088,9 +3525,15 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3115,6 +3558,12 @@ msgstr ""
msgid "Follow the steps below to export your Google Code project data."
msgstr ""
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -3145,7 +3594,7 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
-msgid "From %{provider_title}"
+msgid "From %{providerTitle}"
msgstr ""
msgid "From Bitbucket"
@@ -3172,12 +3621,21 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "GPG Key ID:"
+msgstr ""
+
msgid "GPG Keys"
msgstr ""
+msgid "GPG signature (loading...)"
+msgstr ""
+
msgid "General"
msgstr ""
+msgid "General Settings"
+msgstr ""
+
msgid "General pipelines"
msgstr ""
@@ -3187,6 +3645,9 @@ msgstr ""
msgid "Geo"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
msgid "Getting started with releases"
msgstr ""
@@ -3256,15 +3717,24 @@ msgstr ""
msgid "Go Back"
msgstr ""
+msgid "Go Micro is a framework for micro service development."
+msgstr ""
+
msgid "Go back"
msgstr ""
+msgid "Go full screen"
+msgstr ""
+
msgid "Go to"
msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to project"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -3322,6 +3792,9 @@ msgstr ""
msgid "Group name"
msgstr ""
+msgid "Group:"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3361,6 +3834,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -3424,6 +3900,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "Header message"
+msgstr ""
+
msgid "Health Check"
msgstr ""
@@ -3454,6 +3933,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -3468,15 +3950,15 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
-msgid "Hide whitespace changes"
-msgstr ""
-
msgid "History"
msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "Housekeeping, export, path, transfer, remove, archive."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -3564,6 +4046,9 @@ msgstr ""
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -3582,12 +4067,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -3615,24 +4112,57 @@ msgstr ""
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
+msgid "Import/Export illustration"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed"
+msgstr ""
+
+msgid "ImportProjects|Requesting your %{provider} repositories failed"
+msgstr ""
+
+msgid "ImportProjects|Select the projects you want to import"
+msgstr ""
+
+msgid "ImportProjects|Updating the imported projects failed"
+msgstr ""
+
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -3642,6 +4172,12 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert a quote"
+msgstr ""
+
+msgid "Insert code"
+msgstr ""
+
msgid "Insert suggestion"
msgstr ""
@@ -3687,18 +4223,33 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invalid input, please avoid emojis"
+msgstr ""
+
msgid "Invitation"
msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
msgid "Invoke Count"
msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -3717,7 +4268,10 @@ msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr ""
-msgid "Issues, merge requests, pushes and comments."
+msgid "Issues, merge requests, pushes, and comments."
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
msgid "It's you"
@@ -3735,6 +4289,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -3792,12 +4352,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -3858,6 +4424,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Language"
+msgstr ""
+
msgid "Large File Storage"
msgstr ""
@@ -3869,6 +4438,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -3884,6 +4456,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -3902,6 +4477,9 @@ msgstr ""
msgid "Latest pipeline for this branch"
msgstr ""
+msgid "Lead"
+msgstr ""
+
msgid "Learn more"
msgstr ""
@@ -3917,6 +4495,9 @@ msgstr ""
msgid "Learn more about protected branches"
msgstr ""
+msgid "Learn more about signing commits"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -3973,6 +4554,9 @@ msgstr ""
msgid "Loading…"
msgstr ""
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4027,12 +4611,18 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manifest"
msgstr ""
msgid "Manifest file import"
msgstr ""
+msgid "Manual job"
+msgstr ""
+
msgid "Map a FogBugz account ID to a GitLab user"
msgstr ""
@@ -4054,73 +4644,73 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
-msgid "Markdown enabled"
+msgid "Markdown"
msgstr ""
-msgid "MarkdownToolbar|Add a bullet list"
+msgid "Markdown enabled"
msgstr ""
-msgid "MarkdownToolbar|Add a link"
+msgid "Max access level"
msgstr ""
-msgid "MarkdownToolbar|Add a numbered list"
+msgid "Maximum job timeout"
msgstr ""
-msgid "MarkdownToolbar|Add a table"
+msgid "May"
msgstr ""
-msgid "MarkdownToolbar|Add a task list"
+msgid "Median"
msgstr ""
-msgid "MarkdownToolbar|Add bold text"
+msgid "Member since %{date}"
msgstr ""
-msgid "MarkdownToolbar|Add italic text"
+msgid "Members"
msgstr ""
-msgid "MarkdownToolbar|Go full screen"
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "MarkdownToolbar|Insert a quote"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "MarkdownToolbar|Insert code"
+msgid "Merge Request"
msgstr ""
-msgid "Max access level"
+msgid "Merge Requests"
msgstr ""
-msgid "Maximum job timeout"
+msgid "Merge commit message"
msgstr ""
-msgid "May"
+msgid "Merge events"
msgstr ""
-msgid "Median"
+msgid "Merge immediately"
msgstr ""
-msgid "Member since %{date}"
+msgid "Merge in progress"
msgstr ""
-msgid "Members"
+msgid "Merge request"
msgstr ""
-msgid "Merge Request"
+msgid "Merge requests"
msgstr ""
-msgid "Merge Requests"
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
-msgid "Merge events"
+msgid "Merge when pipeline succeeds"
msgstr ""
-msgid "Merge request"
+msgid "MergeRequests|Add a reply"
msgstr ""
-msgid "Merge requests"
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -4138,6 +4728,9 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
msgid "MergeRequests|started a discussion"
msgstr ""
@@ -4162,6 +4755,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4192,9 +4788,6 @@ msgstr ""
msgid "Metrics|Learn about environments"
msgstr ""
-msgid "Metrics|No data to display"
-msgstr ""
-
msgid "Metrics|No deployed environments"
msgstr ""
@@ -4270,6 +4863,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -4282,6 +4887,9 @@ msgstr ""
msgid "More information is available|here"
msgstr ""
+msgid "More than %{number_commits_distance} commits different with %{default_branch}"
+msgstr ""
+
msgid "Most stars"
msgstr ""
@@ -4303,6 +4911,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, tags, avatar"
+msgstr ""
+
msgid "Naming, visibility"
msgstr ""
@@ -4347,13 +4958,19 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
-msgid "New Pipeline Schedule"
+msgid "New Milestone"
msgstr ""
-msgid "New Snippet"
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Password"
msgstr ""
-msgid "New Snippets"
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
msgstr ""
msgid "New branch"
@@ -4386,6 +5003,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -4410,6 +5030,15 @@ msgstr ""
msgid "No"
msgstr ""
+msgid "No %{providerTitle} repositories available to import"
+msgstr ""
+
+msgid "No Tag"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -4431,9 +5060,15 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display."
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
@@ -4458,6 +5093,9 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -4506,6 +5144,9 @@ msgstr ""
msgid "Not now"
msgstr ""
+msgid "Not started"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -4533,9 +5174,6 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
-msgid "Nothing here."
-msgstr ""
-
msgid "Notification events"
msgstr ""
@@ -4637,9 +5275,15 @@ msgstr ""
msgid "Only mirror protected branches"
msgstr ""
+msgid "Only policy:"
+msgstr ""
+
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -4649,6 +5293,12 @@ msgstr ""
msgid "Open Documentation"
msgstr ""
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -4673,6 +5323,9 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
+msgid "Operations Settings"
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -4703,6 +5356,15 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -4715,12 +5377,18 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -4757,6 +5425,9 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
@@ -4823,6 +5494,12 @@ msgstr ""
msgid "PipelineSheduleIntervalPattern|Custom"
msgstr ""
+msgid "PipelineStatusTooltip|Commit: %{ci_status}"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
+msgstr ""
+
msgid "Pipelines"
msgstr ""
@@ -4943,6 +5620,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -4955,6 +5635,9 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please create a username with only alphanumeric characters."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -4964,6 +5647,9 @@ msgstr ""
msgid "Please select at least one filter to see results"
msgstr ""
+msgid "Please set a new password before proceeding."
+msgstr ""
+
msgid "Please solve the reCAPTCHA"
msgstr ""
@@ -4982,6 +5668,9 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|This feature is experimental and translations are not complete yet"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -5033,6 +5722,12 @@ msgstr ""
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -5048,6 +5743,9 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
@@ -5060,6 +5758,15 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -5078,6 +5785,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -5090,6 +5800,9 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -5126,6 +5839,9 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
@@ -5147,10 +5863,10 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile"
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -5177,6 +5893,9 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
@@ -5243,6 +5962,9 @@ msgstr ""
msgid "Project"
msgstr ""
+msgid "Project \"%{name}\" is no longer available. Select another project to continue."
+msgstr ""
+
msgid "Project '%{project_name}' is in the process of being deleted."
msgstr ""
@@ -5285,12 +6007,21 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project has too many %{label_for_message} to search"
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5339,6 +6070,9 @@ msgstr ""
msgid "Projects"
msgstr ""
+msgid "Projects Successfully Retrieved"
+msgstr ""
+
msgid "Projects shared with %{group_name}"
msgstr ""
@@ -5366,9 +6100,6 @@ msgstr ""
msgid "ProjectsDropdown|This feature requires browser localStorage support"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -5587,6 +6318,12 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -5784,6 +6521,9 @@ msgstr ""
msgid "Running"
msgstr ""
+msgid "Running…"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -5796,15 +6536,24 @@ msgstr ""
msgid "SSL Verification"
msgstr ""
+msgid "Saturday"
+msgstr ""
+
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -5820,6 +6569,9 @@ msgstr ""
msgid "Schedules"
msgstr ""
+msgid "Scheduling"
+msgstr ""
+
msgid "Scheduling Pipelines"
msgstr ""
@@ -5850,6 +6602,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -5865,6 +6620,9 @@ msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -5925,6 +6683,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -5958,6 +6719,9 @@ msgstr ""
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -5970,16 +6734,25 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgid "ServerlessDetails|Kubernetes Pods"
msgstr ""
-msgid "Serverless|An error occurred while retrieving serverless components"
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
msgstr ""
-msgid "Serverless|Domain"
+msgid "ServerlessURL|Copy URL to clipboard"
msgstr ""
-msgid "Serverless|Function"
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
msgstr ""
msgid "Serverless|Getting started with serverless"
@@ -5991,18 +6764,12 @@ msgstr ""
msgid "Serverless|Install Knative"
msgstr ""
-msgid "Serverless|Last Update"
-msgstr ""
-
msgid "Serverless|Learn more about Serverless"
msgstr ""
msgid "Serverless|No functions available"
msgstr ""
-msgid "Serverless|Runtime"
-msgstr ""
-
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
@@ -6021,6 +6788,9 @@ msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
+msgid "Set new password"
+msgstr ""
+
msgid "Set notification email for abuse reports."
msgstr ""
@@ -6039,6 +6809,9 @@ msgstr ""
msgid "Set up new U2F device"
msgstr ""
+msgid "Set up new password"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -6084,12 +6857,21 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Show all activity"
+msgstr ""
+
msgid "Show command"
msgstr ""
+msgid "Show comments only"
+msgstr ""
+
msgid "Show complete raw log"
msgstr ""
+msgid "Show file browser"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -6137,9 +6919,36 @@ msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "SnippetsEmptyState|Explore public snippets"
+msgstr ""
+
+msgid "SnippetsEmptyState|New snippet"
+msgstr ""
+
+msgid "SnippetsEmptyState|No snippets found"
+msgstr ""
+
+msgid "SnippetsEmptyState|Snippets are small pieces of code or notes that you want to keep."
+msgstr ""
+
+msgid "SnippetsEmptyState|There are no snippets to show."
+msgstr ""
+
+msgid "SnippetsEmptyState|They can be either public or private."
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -6164,6 +6973,9 @@ msgstr ""
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr ""
@@ -6176,6 +6988,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -6233,7 +7048,7 @@ msgstr ""
msgid "SortOptions|Least popular"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -6263,6 +7078,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -6275,6 +7093,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -6314,6 +7135,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -6350,6 +7174,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page."
+msgstr ""
+
+msgid "StarredProjectsEmptyState|You don't have starred projects yet."
+msgstr ""
+
msgid "Stars"
msgstr ""
@@ -6365,6 +7195,15 @@ msgstr ""
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -6380,9 +7219,15 @@ msgstr ""
msgid "Starts at (UTC)"
msgstr ""
+msgid "State your message to activate"
+msgstr ""
+
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -6413,6 +7258,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6425,12 +7273,24 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6440,6 +7300,12 @@ msgstr ""
msgid "System Info"
msgstr ""
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -6449,6 +7315,9 @@ msgstr ""
msgid "Tag"
msgstr ""
+msgid "Tag list:"
+msgstr ""
+
msgid "Tags"
msgstr ""
@@ -6584,12 +7453,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
-msgid "The maximum file size allowed is %{max_attachment_size}mb"
+msgid "The maximum file size allowed is %{size}."
msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
+msgid "The name %{entryName} is already taken in this directory."
+msgstr ""
+
msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
msgstr ""
@@ -6656,12 +7528,24 @@ msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
msgid "There are no projects shared with this group yet"
msgstr ""
@@ -6674,6 +7558,9 @@ msgstr ""
msgid "There was an error loading users activity calendar."
msgstr ""
+msgid "There was an error saving your changes."
+msgstr ""
+
msgid "There was an error saving your notification settings."
msgstr ""
@@ -6698,7 +7585,10 @@ msgstr ""
msgid "Third party offers"
msgstr ""
-msgid "This %{viewer} could not be displayed because %{reason}."
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
@@ -6713,6 +7603,21 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
+msgstr ""
+
+msgid "This commit was signed with a <strong>verified</strong> signature and the committer email is verified to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with a different user's verified signature."
+msgstr ""
+
+msgid "This commit was signed with a verified signature, but the committer email is <strong>not verified</strong> to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with an <strong>unverified</strong> signature."
+msgstr ""
+
msgid "This container registry has been scheduled for deletion."
msgstr ""
@@ -6725,6 +7630,12 @@ msgstr ""
msgid "This directory"
msgstr ""
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This field is required."
+msgstr ""
+
msgid "This group"
msgstr ""
@@ -6821,6 +7732,12 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
msgstr ""
@@ -7044,9 +7961,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -7077,10 +8003,19 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
-msgid "To preserve performance only <strong>%{display_size} of ${real_size}</strong> files are displayed."
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
@@ -7116,10 +8051,10 @@ msgstr ""
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -7194,9 +8129,15 @@ msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unlock"
msgstr ""
@@ -7242,6 +8183,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -7254,21 +8198,36 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
+msgid "Update your project name, tags, description and avatar."
+msgstr ""
+
msgid "Updating"
msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -7329,12 +8288,24 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
+msgid "UserProfile|No snippets found."
+msgstr ""
+
msgid "UserProfile|Overview"
msgstr ""
@@ -7347,33 +8318,69 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
msgid "Various container registry settings."
msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -7395,6 +8402,9 @@ msgstr ""
msgid "View group labels"
msgstr ""
+msgid "View in Sentry"
+msgstr ""
+
msgid "View it on GitLab"
msgstr ""
@@ -7431,6 +8441,9 @@ msgstr ""
msgid "Visibility level:"
msgstr ""
+msgid "Visibility, project features, permissions"
+msgstr ""
+
msgid "Visibility:"
msgstr ""
@@ -7449,6 +8462,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -7473,6 +8489,9 @@ msgstr ""
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -7620,6 +8639,15 @@ msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -7632,6 +8660,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -7668,6 +8699,9 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -7677,6 +8711,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -7707,6 +8744,9 @@ msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -7719,10 +8759,10 @@ msgstr ""
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -7752,6 +8792,9 @@ msgstr ""
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
+msgid "You're only seeing %{startTag}other activity%{endTag} in the feed. To add a comment, switch to one of the following options."
+msgstr ""
+
msgid "You're receiving this email because %{reason}."
msgstr ""
@@ -7764,6 +8807,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -7797,6 +8843,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -7806,9 +8855,18 @@ msgstr ""
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -7818,18 +8876,30 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
+msgid "authored"
+msgstr ""
+
msgid "branch name"
msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -7867,6 +8937,9 @@ msgstr ""
msgid "enabled"
msgstr ""
+msgid "error"
+msgstr ""
+
msgid "error code:"
msgstr ""
@@ -7888,32 +8961,68 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
-msgid "in"
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
msgstr ""
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
msgid "latest version"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -7953,6 +9062,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -8013,12 +9125,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Request to merge"
msgstr ""
@@ -8052,19 +9158,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -8073,6 +9179,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -8085,10 +9194,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -8109,9 +9218,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -8131,35 +9252,71 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "project"
msgstr ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
msgid "remove due date"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
msgid "should be higher than %{access} inherited membership from group %{group_name}"
msgstr ""
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
+msgid "triggered"
+msgstr ""
+
msgid "updated"
msgstr ""
@@ -8169,9 +9326,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -8179,3 +9342,6 @@ msgid "within %d minute "
msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+
+msgid "yaml invalid"
+msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index 035123e629f..a931df046da 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: gl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:23\n"
+"PO-Revision-Date: 2019-02-11 08:15\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] "%d incidencia"
msgstr[1] "%d incidencias"
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d capa"
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index a7e4fdd134e..0c3654b1266 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: he\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:22\n"
+"PO-Revision-Date: 2019-02-11 08:15\n"
msgid " Status"
msgstr ""
@@ -35,22 +35,17 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -66,12 +61,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -101,6 +92,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -158,6 +156,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -181,12 +182,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -196,9 +203,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -208,6 +212,33 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -227,12 +258,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -322,10 +362,13 @@ msgstr[3] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -367,7 +410,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -415,6 +458,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -451,10 +497,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -466,7 +512,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -499,6 +548,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -508,6 +560,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -523,9 +578,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -559,12 +611,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -577,12 +659,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -596,6 +708,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -605,9 +720,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -629,6 +750,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -656,40 +780,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -698,6 +792,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -770,12 +867,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -806,9 +912,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -839,6 +990,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -851,6 +1017,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -860,12 +1029,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -881,6 +1062,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -899,6 +1083,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -908,6 +1095,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -935,6 +1125,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -947,6 +1140,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -962,6 +1158,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -989,15 +1188,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -1031,13 +1221,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1223,6 +1425,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1232,13 +1440,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1392,21 +1593,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1443,12 +1659,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1458,18 +1668,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1482,12 +1701,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1509,10 +1737,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1524,9 +1752,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1548,6 +1782,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1566,6 +1806,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1659,7 +1902,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1680,6 +1923,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1719,28 +1968,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1764,27 +2037,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1794,6 +2082,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1806,6 +2097,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1833,6 +2127,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1905,6 +2208,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1920,6 +2229,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1956,6 +2271,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -2034,6 +2352,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2076,12 +2397,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2097,6 +2424,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2109,6 +2448,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2136,6 +2478,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2148,9 +2493,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2170,16 +2524,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2243,6 +2596,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2270,12 +2626,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2309,6 +2671,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2357,6 +2722,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2372,7 +2740,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2408,13 +2776,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2423,6 +2794,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2447,9 +2821,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2471,6 +2842,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2480,6 +2854,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2519,6 +2896,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2585,9 +2965,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2603,6 +2980,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2612,6 +2992,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2642,6 +3028,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2651,6 +3040,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2663,6 +3055,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2672,6 +3067,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2681,6 +3082,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2711,6 +3115,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2847,6 +3257,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2874,6 +3287,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2904,6 +3320,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2925,15 +3347,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2961,6 +3392,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2985,6 +3422,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -3000,9 +3440,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3012,6 +3458,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -3021,6 +3473,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -3039,6 +3494,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -3063,6 +3521,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3078,9 +3539,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3093,6 +3563,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3108,9 +3584,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3186,6 +3680,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3198,9 +3695,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3210,7 +3704,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3237,9 +3731,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3282,9 +3782,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3294,6 +3800,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3315,6 +3827,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3324,9 +3842,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3339,6 +3887,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3360,9 +3914,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3402,6 +3968,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3411,28 +3980,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3444,7 +4025,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3456,30 +4040,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3498,6 +4100,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3507,13 +4124,35 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3531,12 +4170,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3549,12 +4206,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3600,6 +4263,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3624,6 +4290,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3675,6 +4344,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3765,7 +4437,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3840,6 +4515,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3885,6 +4563,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3921,6 +4602,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3999,9 +4683,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -4029,9 +4722,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4062,6 +4761,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4086,6 +4788,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4131,13 +4836,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4149,37 +4857,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4206,6 +4911,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4305,6 +5013,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4318,7 +5029,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4327,6 +5038,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4384,6 +5098,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4414,9 +5131,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4435,12 +5158,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4465,6 +5200,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4480,15 +5218,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4504,6 +5257,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4535,6 +5291,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4550,9 +5309,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4571,6 +5348,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4604,6 +5396,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4622,6 +5420,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4661,10 +5465,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4679,12 +5483,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4764,6 +5574,9 @@ msgstr[3] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4779,6 +5592,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4794,15 +5610,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4942,6 +5782,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -5008,6 +5854,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -5038,6 +5887,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -5074,9 +5926,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5098,13 +5947,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5113,9 +5965,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5128,19 +5989,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5158,6 +6031,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5167,6 +6058,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5185,7 +6079,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5194,6 +6088,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5203,7 +6103,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5215,22 +6115,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5245,10 +6139,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5269,21 +6163,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5356,6 +6241,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5416,6 +6313,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5428,6 +6328,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5444,6 +6347,12 @@ msgstr[3] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5462,6 +6371,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5483,6 +6395,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5510,6 +6425,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5519,6 +6437,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5531,15 +6452,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5552,6 +6482,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5561,10 +6494,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5585,6 +6521,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5594,12 +6533,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5624,6 +6557,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5654,6 +6590,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5754,21 +6696,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5802,16 +6759,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5859,6 +6813,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5871,12 +6831,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5898,9 +6873,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5916,6 +6888,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6102,6 +7080,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6114,9 +7095,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6129,6 +7116,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6171,6 +7161,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6192,9 +7185,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6210,15 +7212,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6237,6 +7254,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6246,6 +7266,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6282,10 +7308,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6294,7 +7323,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6303,10 +7332,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6333,12 +7365,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6357,16 +7392,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6375,6 +7413,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6432,12 +7476,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6582,9 +7632,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6609,6 +7656,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6738,6 +7788,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6777,21 +7830,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6820,6 +7882,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6850,6 +7915,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6859,6 +7930,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6889,9 +7966,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6952,6 +8035,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6970,6 +8059,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6979,12 +8071,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6994,6 +8101,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -7003,12 +8116,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -7021,9 +8140,6 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
@@ -7031,6 +8147,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -7058,6 +8177,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -7085,6 +8207,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7118,7 +8243,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7139,6 +8264,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7148,6 +8276,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7184,6 +8315,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7196,6 +8330,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7265,7 +8402,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7274,10 +8411,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7295,6 +8435,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7304,6 +8456,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7331,6 +8489,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7364,9 +8525,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7376,6 +8543,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7406,6 +8615,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7421,6 +8633,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7484,10 +8699,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7527,12 +8742,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7542,6 +8766,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7563,9 +8790,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7575,6 +8811,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7584,9 +8823,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7605,6 +8850,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7629,9 +8877,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7677,7 +8931,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7710,6 +8964,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7722,6 +8979,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7749,6 +9009,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7764,6 +9027,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7800,6 +9066,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7809,9 +9081,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7821,6 +9105,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7830,6 +9123,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7845,6 +9144,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7860,6 +9162,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7875,10 +9180,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7893,7 +9282,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7902,12 +9294,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -8002,6 +9393,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -8017,9 +9414,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -8056,6 +9459,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8134,16 +9540,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8179,12 +9603,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8212,13 +9645,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8281,10 +9717,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8293,7 +9729,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8314,6 +9750,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8341,7 +9786,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8353,7 +9798,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8550,9 +9995,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8595,13 +10049,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8610,6 +10079,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8619,6 +10091,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8634,13 +10109,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8694,9 +10172,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8706,6 +10181,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8715,9 +10196,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8730,10 +10217,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8742,9 +10229,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8793,6 +10286,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8805,6 +10301,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8814,6 +10313,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8832,15 +10334,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8871,9 +10388,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8898,19 +10421,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8919,25 +10451,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8946,12 +10505,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8964,6 +10529,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -9003,6 +10574,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -9027,6 +10601,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9051,27 +10631,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9096,6 +10697,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9237,12 +10841,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9255,6 +10868,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9273,6 +10889,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9297,6 +10916,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9315,6 +10937,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9324,12 +10949,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9339,16 +10970,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9390,6 +11027,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9405,12 +11045,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9423,12 +11069,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9438,12 +11096,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9544,6 +11208,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9559,6 +11226,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9685,6 +11358,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9707,12 +11383,22 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "done"
msgstr ""
@@ -9726,6 +11412,15 @@ msgstr[3] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9735,21 +11430,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9766,9 +11479,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9781,6 +11512,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
@@ -9788,9 +11522,21 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9806,10 +11552,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9848,6 +11594,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9920,12 +11669,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9976,19 +11719,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9997,6 +11740,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -10009,10 +11755,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -10033,9 +11779,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -10059,6 +11817,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -10069,6 +11830,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -10081,6 +11848,9 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
@@ -10088,22 +11858,49 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -10112,9 +11909,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10125,3 +11928,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
new file mode 100644
index 00000000000..8a3603ef135
--- /dev/null
+++ b/locale/hi_IN/gitlab.po
@@ -0,0 +1,11801 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Hindi\n"
+"Language: hi_IN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: hi\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2019-02-11 08:15\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " or "
+msgstr ""
+
+msgid " or <#epic id>"
+msgstr ""
+
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commits"
+msgstr ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid ", or "
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add CHANGELOG"
+msgstr ""
+
+msgid "Add CONTRIBUTING"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to project"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Auth Token"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization key"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "By %{user_name}"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Charts"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI Lint"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "CONTRIBUTING"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change permissions"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking approval status"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed (moved)"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} upgraded successfully."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Command line instructions"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit %{commit_id}"
+msgstr ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit deleted"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Contact sales to upgrade"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution Charts"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create milestone"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downstream"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable error tracking"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Stopping"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error rendering markdown preview"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating %{issuableType}"
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find existing members by name"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish editing this message first!"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate key"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last repository check run"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Re-verification interval"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Given access %{time_ago}"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import project members"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include merge request description"
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed"
+msgstr ""
+
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes Clusters"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage two-factor authentication"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge commit message"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search files"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics for environment"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No details available"
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No errors to display"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No milestones to show"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No preview for this file type"
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No start date"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|@username"
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Social sign-in"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "Project:"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about environments"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register U2F device"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset key"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Restart Terminal"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reveal values"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners activated for this project"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search groups"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|No Vulnerabilities"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select members to invite"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new U2F device"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippet Contents"
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "Sort direction"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start cleanup"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Stopping..."
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no approvers"
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This 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. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To 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>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle commit list"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try again?"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "URL"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Upload object map"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "Used to help configure your identity provider"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various localization settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Report Type"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web Terminal"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "When:"
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "Will deploy to"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "allowed to fail"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "commented on %{link_to_project}"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "deleted"
+msgstr ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "group"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "image diff"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "none"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
new file mode 100644
index 00000000000..5267aa42b8d
--- /dev/null
+++ b/locale/hr_HR/gitlab.po
@@ -0,0 +1,11867 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Croatian\n"
+"Language: hr_HR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: hr\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2019-02-11 08:13\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid " or "
+msgstr ""
+
+msgid " or <#epic id>"
+msgstr ""
+
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d commits"
+msgstr ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+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[2] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid ", or "
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add CHANGELOG"
+msgstr ""
+
+msgid "Add CONTRIBUTING"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to project"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Auth Token"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization key"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "By %{user_name}"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Charts"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI Lint"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "CONTRIBUTING"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change permissions"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking approval status"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed (moved)"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} upgraded successfully."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Command line instructions"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Commit %{commit_id}"
+msgstr ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit deleted"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Contact sales to upgrade"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution Charts"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create milestone"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downstream"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable error tracking"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Stopping"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error rendering markdown preview"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating %{issuableType}"
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find existing members by name"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish editing this message first!"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate key"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last repository check run"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Re-verification interval"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Given access %{time_ago}"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import project members"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include merge request description"
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed"
+msgstr ""
+
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes Clusters"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage two-factor authentication"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge commit message"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search files"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics for environment"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No details available"
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No errors to display"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No milestones to show"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No preview for this file type"
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No start date"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|@username"
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Social sign-in"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "Project:"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about environments"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register U2F device"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset key"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Restart Terminal"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Reveal values"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners activated for this project"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search groups"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|No Vulnerabilities"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select members to invite"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new U2F device"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippet Contents"
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "Sort direction"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start cleanup"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Stopping..."
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no approvers"
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This 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. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To 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>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle commit list"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try again?"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "URL"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Upload object map"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "Used to help configure your identity provider"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various localization settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Report Type"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web Terminal"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "When:"
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "Will deploy to"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "allowed to fail"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "commented on %{link_to_project}"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "deleted"
+msgstr ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "group"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "image diff"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "none"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index 02eaff28e83..bc8e95021c1 100644
--- a/locale/hu_HU/gitlab.po
+++ b/locale/hu_HU/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: hu\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:20\n"
+"PO-Revision-Date: 2019-02-11 08:14\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index 265d725424e..79a8b5aa073 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: id\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:18\n"
+"PO-Revision-Date: 2019-02-11 08:11\n"
msgid " Status"
msgstr ""
@@ -29,16 +29,17 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -48,9 +49,8 @@ msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -68,6 +68,10 @@ msgid "%d issue"
msgid_plural "%d issues"
msgstr[0] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -107,6 +111,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -124,12 +131,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,9 +152,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -151,6 +161,24 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,12 +195,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -229,10 +266,13 @@ msgstr[0] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -274,7 +314,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -322,6 +362,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -358,10 +401,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -373,7 +416,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -406,6 +452,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -415,6 +464,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -430,9 +482,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -466,12 +515,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -484,12 +563,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -500,6 +609,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -509,9 +621,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -533,6 +651,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -560,40 +681,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -602,6 +693,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -674,12 +768,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -710,9 +813,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -743,6 +891,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -755,6 +918,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -764,12 +930,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -785,6 +963,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -803,6 +984,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -812,6 +996,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -839,6 +1026,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -851,6 +1041,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -866,6 +1059,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -893,15 +1089,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -935,13 +1122,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1127,6 +1326,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1136,10 +1341,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1293,21 +1494,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1344,12 +1560,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1359,18 +1569,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1383,12 +1602,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1410,10 +1638,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1425,9 +1653,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1449,6 +1683,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1467,6 +1707,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1560,7 +1803,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1581,6 +1824,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1620,28 +1869,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1665,27 +1938,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1695,6 +1983,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1707,6 +1998,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1734,6 +2028,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1806,6 +2109,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1821,6 +2130,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1857,6 +2172,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1935,6 +2253,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -1977,12 +2298,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -1998,6 +2325,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2010,6 +2349,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2037,6 +2379,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2049,9 +2394,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2068,13 +2422,15 @@ msgid "Commit"
msgid_plural "Commits"
msgstr[0] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2138,6 +2494,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2165,12 +2524,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2204,6 +2569,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2252,6 +2620,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2267,7 +2638,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2303,13 +2674,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2318,6 +2692,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2342,9 +2719,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2366,6 +2740,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2375,6 +2752,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2414,6 +2794,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2480,9 +2863,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2498,6 +2878,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2507,6 +2890,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2537,6 +2926,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2546,6 +2938,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2558,6 +2953,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2567,6 +2965,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2576,6 +2980,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2606,6 +3013,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2739,6 +3152,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2766,6 +3182,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2796,6 +3215,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2817,15 +3242,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2853,6 +3287,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2877,6 +3317,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2892,9 +3335,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2904,6 +3353,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2913,6 +3368,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2931,6 +3389,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2955,6 +3416,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -2970,9 +3434,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -2985,6 +3458,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3000,9 +3479,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3078,6 +3575,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3090,9 +3590,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3102,7 +3599,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3129,9 +3626,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3174,9 +3677,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3186,6 +3695,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3207,6 +3722,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3216,9 +3737,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3231,6 +3782,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3252,9 +3809,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3294,6 +3863,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3303,28 +3875,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3336,7 +3920,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3348,30 +3935,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3390,6 +3995,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3399,13 +4019,32 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3423,12 +4062,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3441,12 +4098,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3492,6 +4155,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3516,6 +4182,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3567,6 +4236,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3657,7 +4329,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3732,6 +4407,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3777,6 +4455,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3813,6 +4494,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3891,9 +4575,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3921,9 +4614,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3954,6 +4653,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -3978,6 +4680,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4023,13 +4728,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4041,37 +4749,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4098,6 +4803,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4197,6 +4905,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4207,7 +4918,7 @@ msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4216,6 +4927,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4273,6 +4987,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4303,9 +5020,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4324,12 +5047,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4354,6 +5089,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4369,15 +5107,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4393,6 +5146,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4421,6 +5177,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4436,9 +5195,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4457,6 +5234,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4490,6 +5282,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4508,6 +5306,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4547,10 +5351,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4565,12 +5369,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4647,6 +5457,9 @@ msgstr[0] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4662,6 +5475,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4677,15 +5493,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4822,6 +5662,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4888,6 +5734,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4918,6 +5767,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4954,9 +5806,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -4978,13 +5827,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -4993,9 +5845,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5008,19 +5869,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5038,6 +5911,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5047,6 +5938,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5065,7 +5959,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5074,6 +5968,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5083,7 +5983,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5095,22 +5995,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5125,10 +6019,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5149,21 +6043,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5236,6 +6121,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5296,6 +6193,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5308,6 +6208,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5321,6 +6224,12 @@ msgstr[0] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5339,6 +6248,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5360,6 +6272,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5387,6 +6302,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5396,6 +6314,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5408,15 +6329,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5429,6 +6359,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5438,10 +6371,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5462,6 +6398,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5471,12 +6410,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5501,6 +6434,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5531,6 +6467,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5628,21 +6570,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5676,16 +6633,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5733,6 +6687,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5745,12 +6705,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5772,9 +6747,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5790,6 +6762,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -5976,6 +6954,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -5988,9 +6969,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6003,6 +6990,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6045,6 +7035,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6066,9 +7059,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6084,15 +7086,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6111,6 +7128,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6120,6 +7140,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6156,10 +7182,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6168,7 +7197,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6177,10 +7206,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6207,12 +7239,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6231,16 +7266,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6249,6 +7287,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6306,12 +7350,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6456,9 +7506,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6483,6 +7530,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6612,6 +7662,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6651,21 +7704,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6691,6 +7753,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6721,6 +7786,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6730,6 +7801,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6760,9 +7837,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6823,6 +7906,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6841,6 +7930,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6850,12 +7942,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6865,6 +7972,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6874,12 +7987,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6892,13 +8011,13 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6926,6 +8045,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6953,6 +8075,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -6986,7 +8111,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7007,6 +8132,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7016,6 +8144,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7052,6 +8183,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7064,6 +8198,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7133,7 +8270,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7142,10 +8279,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7163,6 +8303,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7172,6 +8324,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7199,6 +8357,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7232,9 +8393,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7244,6 +8411,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7274,6 +8483,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7289,6 +8501,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7352,10 +8567,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7392,12 +8607,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7407,6 +8631,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7428,9 +8655,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7440,6 +8676,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7449,9 +8688,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7470,6 +8715,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7494,9 +8742,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7542,7 +8796,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7575,6 +8829,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7587,6 +8844,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7614,6 +8874,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7629,6 +8892,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7665,6 +8931,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7674,9 +8946,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7686,6 +8970,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7695,6 +8988,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7710,6 +9009,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7725,6 +9027,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7740,10 +9045,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7758,7 +9147,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7767,9 +9159,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7864,6 +9258,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7879,9 +9279,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7918,6 +9324,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -7996,16 +9405,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8041,12 +9468,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8074,13 +9510,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8143,10 +9582,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8155,7 +9594,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8176,6 +9615,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8203,7 +9651,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8215,7 +9663,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8406,9 +9854,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8451,13 +9908,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8466,6 +9938,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8475,6 +9950,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8490,13 +9968,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8550,9 +10031,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8562,6 +10040,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8571,9 +10055,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8586,10 +10076,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8598,9 +10088,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8649,6 +10145,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8661,6 +10160,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8670,6 +10172,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8688,15 +10193,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8727,9 +10247,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8754,19 +10280,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8775,25 +10310,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8802,12 +10364,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8820,6 +10388,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8859,6 +10433,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8883,6 +10460,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8907,27 +10490,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -8952,6 +10556,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9093,12 +10700,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9111,6 +10727,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9129,6 +10748,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9153,6 +10775,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9171,6 +10796,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9180,12 +10808,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9195,16 +10829,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9246,6 +10886,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9261,12 +10904,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9279,12 +10928,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9294,12 +10955,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9388,6 +11055,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9403,6 +11073,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9520,6 +11196,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9539,12 +11218,19 @@ msgid "day"
msgid_plural "days"
msgstr[0] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+
msgid "done"
msgstr ""
@@ -9555,6 +11241,15 @@ msgstr[0] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9564,21 +11259,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9592,9 +11305,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9607,13 +11338,28 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9629,10 +11375,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9671,6 +11417,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9743,12 +11492,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9793,19 +11536,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9814,6 +11557,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9826,10 +11572,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9850,9 +11596,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9870,6 +11628,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9877,6 +11638,12 @@ msgid "project"
msgid_plural "projects"
msgstr[0] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9889,26 +11656,56 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9917,9 +11714,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9927,3 +11730,6 @@ msgid "within %d minute "
msgid_plural "within %d minutes "
msgstr[0] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index ab967c458d2..a7dd46e61dd 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -13,36 +13,35 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:20\n"
+"PO-Revision-Date: 2019-02-11 08:09\n"
msgid " Status"
-msgstr ""
+msgstr " Stato"
msgid " and"
-msgstr ""
+msgstr " e"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " degradato di %d punto"
+msgstr[1] " degradato di %d punti"
msgid " improved on %d point"
msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " migliorato di %d punto"
+msgstr[1] " migliorato di %d punti"
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" nei progetti"
msgid "%d commit"
msgid_plural "%d commits"
@@ -51,31 +50,34 @@ msgstr[1] "%d commits"
msgid "%d commit behind"
msgid_plural "%d commits behind"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commit indietro"
+msgstr[1] "%d commit indietro"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d exporter"
+msgstr[1] "%d exporter"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d risultato test non riuscito"
+msgstr[1] "%d risultati di test falliti"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d risultato del test risolto"
+msgstr[1] "%d risultati dei test risolti"
msgid "%d issue"
msgid_plural "%d issues"
+msgstr[0] "%d issue"
+msgstr[1] "%d issue"
+
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
msgstr[0] ""
msgstr[1] ""
@@ -86,8 +88,8 @@ msgstr[1] "%d livelli"
msgid "%d merge request"
msgid_plural "%d merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d richiesta di merge"
+msgstr[1] "%d richieste di merge"
msgid "%d metric"
msgid_plural "%d metrics"
@@ -96,13 +98,13 @@ msgstr[1] "%d metriche"
msgid "%d staged change"
msgid_plural "%d staged changes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d modifica in stage"
+msgstr[1] "%d modifiche in stage"
msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d modifica non in stage"
+msgstr[1] "%d modifiche non in stage"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
@@ -110,10 +112,10 @@ msgstr[0] "%s commit aggiuntivo è stato omesso per evitare degradi di prestazio
msgstr[1] "%s commit aggiuntivi sono stati omessi per evitare degradi di prestazioni negli issues."
msgid "%{actionText} & %{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{actionText} & %{openOrClose} %{noteable}"
msgid "%{authorsName}'s discussion"
-msgstr ""
+msgstr "Discussione di %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} fatto %{commit_timeago}"
@@ -122,10 +124,13 @@ msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build
msgstr ""
msgid "%{count} %{alerts}"
+msgstr "%{count}%{alerts}"
+
+msgid "%{count} more"
msgstr ""
msgid "%{count} more assignees"
-msgstr ""
+msgstr "%{count} altri assegnatari"
msgid "%{count} participant"
msgid_plural "%{count} participants"
@@ -134,42 +139,66 @@ msgstr[1] "%{count} partecipanti"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} commento in attesa"
+msgstr[1] "%{count} commenti in attesa"
msgid "%{filePath} deleted"
-msgstr ""
+msgstr "%{filePath} eliminato"
msgid "%{firstLabel} +%{labelCount} more"
+msgstr "%{firstLabel} + %{labelCount} più"
+
+msgid "%{firstOption} +%{extraOptionCount} more"
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
+msgstr "I %{group_docs_link_start}Gruppi%{group_docs_link_end} consentono di gestire e collaborare in vari progetti. I membri di un gruppo hanno accesso a tutti i suoi progetti."
msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType} sarà rimosso! Sei sicuro?"
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
msgid "%{loadingIcon} Started"
-msgstr ""
+msgstr "%{loadingIcon} Partito"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
-msgstr ""
+msgstr "%{lock_path} è bloccato dall'utente GitLab %{lock_user_id}"
msgid "%{name}'s avatar"
-msgstr ""
-
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
+msgstr "Avatar di %{name}"
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits precedenti %{default_branch}, %{number_commits_ahead} commits avanti"
msgid "%{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{openOrClose}%{noteable}"
msgid "%{percent}%% complete"
+msgstr "%{percent}%% completato"
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} più"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr "Primo contributo!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "2FA abilitata"
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr "Segnalazioni di abuso"
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,11 +433,11 @@ msgstr "Attività"
msgid "Add"
msgstr ""
-msgid "Add Changelog"
-msgstr "Aggiungi Changelog"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "Aggiungi Guida per contribuire"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr "Tutto"
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Si è verificato un errore. Riprova."
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr "Applicazioni"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "Apr"
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Sei sicuro di voler cancellare questa pipeline programmata?"
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "Sei sicuro?"
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Aggiungi un file tramite trascina &amp; rilascia ( drag &amp; drop) o %{upload_link}"
@@ -883,6 +1074,9 @@ msgstr "Ago"
msgid "August"
msgstr "Agosto"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "Log di autenticazione"
@@ -898,6 +1092,9 @@ msgstr "Autore"
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "Le app d'auto-review e l'Auto Deploy (rilascio automatico) necessita di un nome dominio per funzionare correttamente."
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "Disponibile"
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "La branch <strong>%{branch_name}</strong> è stata creata. Per impostare un rilascio automatico scegli un template CI di Gitlab e committa le tue modifiche %{link_to_autodeploy_doc}"
@@ -1326,21 +1527,36 @@ msgstr "Esplora Files"
msgid "Browse files"
msgstr "Guarda i files"
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "per"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr "Jobs"
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "Cancella"
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,12 +1671,12 @@ msgstr "Ripristina"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
-msgstr "Changelog"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "Grafici"
@@ -1458,9 +1686,15 @@ msgstr "Chat"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr "Controllo disponibilità per %{text}…"
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "Controllo disponibilità branch..."
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr "Clona repository"
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr "Applicazioni"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr "Certificato CA"
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Certificate Authority bundle (formato PEM)"
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Copia URL API"
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr "Tipo di macchina"
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "Messaggio di commit"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "Durata del commit (in minuti) per gli ultimi 30 commit"
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr "Con il Docker Container Registry integrato in Gitlab, ogni progetto può
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,8 +2672,8 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
-msgstr "Guida per contribuire"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr ""
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr "Crea una nuova cartella"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Creare un token di accesso sul tuo account per eseguire pull o push tramite %{protocol}"
@@ -2449,6 +2828,9 @@ msgstr "Crea una richiesta di merge"
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "Crea un nuova branch"
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr "I livelli di notifica personalizzati sono uguali a quelli di partecipazi
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr "Pre-rilascio"
msgid "CycleAnalyticsStage|Test"
msgstr "Test"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr "Tutti"
msgid "DashboardProjects|Personal"
msgstr "Personale"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr "Dic"
msgid "December"
msgstr "Dicembre"
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Definisci un patter personalizzato mediante la sintassi cron"
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr "Dettagli"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "Chiudi l'introduzione alle Analisi Cicliche"
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr "Scarica"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "Scarica tar"
@@ -2913,6 +3352,9 @@ msgstr "Differenze"
msgid "DownloadSource|Download"
msgstr "Scarica"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr "Modifica"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Cambia programmazione della pipeline %{id}"
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr "E-mail"
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Errore durante il fetch degli ambienti."
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Aggiornato"
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr "Errore durante l'attivazione/disattivazione della sottoscrizione per l'iscrizione"
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr "Filtra per eventi di push"
msgid "EventFilterBy|Filter by team"
msgstr "Filtra per team"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Ogni giorno (alle 4 del mattino)"
@@ -3252,9 +3772,39 @@ msgstr "Ogni primo giorno del mese (alle 4 del mattino)"
msgid "Every week (Sundays at 4:00am)"
msgstr "Ogni settimana (Di domenica alle 4 del mattino)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr "Esplora progetti"
msgid "Explore public groups"
msgstr "Esplora gruppi pubblici"
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Impossibile rimuovere la pipeline pianificata"
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr "Feb"
@@ -3435,15 +4054,35 @@ msgstr "Febbraio"
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "Files"
-msgid "Files (%{human_size})"
-msgstr ""
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr "Filtra per messaggio di commit"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "Trova in percorso"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "Trova file"
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "Primo"
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr "Fork da %{project_name} (eliminato)"
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "Formato"
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr "L'autenticazione Google non è %{link_to_documentation}. Richiedi al tuo
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,22 +4785,10 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|Until %{dateWord}"
@@ -4101,15 +4797,24 @@ msgstr ""
msgid "GroupSettings|Badges"
msgstr ""
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
msgid "GroupSettings|Customize your group badges."
msgstr ""
msgid "GroupSettings|Learn more about badges."
msgstr ""
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Blocca la condivisione di un progetto di %{group} con altri gruppi"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Questa modifica è stata applicata su %{ancestor_group} ed è stata ignorata nel sottogruppo."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr "Cronologia"
msgid "Housekeeping successfully started"
msgstr "Housekeeping iniziato con successo"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr "Importa repository"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr "Intervallo di Pattern"
msgid "Introducing Cycle Analytics"
msgstr "Introduzione delle Analisi Cicliche"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr "Giu"
msgid "June"
msgstr "Giugno"
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] "Gli ultimi %d giorni"
msgid "Last Pipeline"
msgstr "Ultima Pipeline"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "Ultimo Commit"
@@ -4701,6 +5514,9 @@ msgstr "Modificato da %{name}"
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr "Ultimo aggiornamento"
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr "Marzo"
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr "Membri"
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr "Richieste di merge"
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr "Richiesta di merge"
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "Monitoraggio"
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] "Nuovi Issues"
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "Nuova pianificazione Pipeline"
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr "Nuova directory"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr "Nuova richiesta di merge"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr "Nessuna pianificazione"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr "Nessuno"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr "Notifica eventi"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Chiudi issue"
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr "Solo i membri del progetto possono commentare."
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Ultima »"
@@ -5787,12 +6747,27 @@ msgstr "Precedente"
msgid "Pagination|« First"
msgstr "« Prima"
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr "Password"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "Pipeline"
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr "Privato - L'accesso al progetto deve essere fornito esplicitamente ad ogni utente."
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "Account pianificato per la rimozione."
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr "Eliminare il tuo account?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Password non valida"
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr "Non hai i permessi per eliminare questo utente."
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "Devi trasferire la proprietà o eliminare questi gruppi prima che tu possa eliminare l'account."
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Il tuo account è attualmente proprietario in questi gruppi:"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "il tuo account"
@@ -6348,12 +7392,18 @@ msgstr "Il link d'esportazione del progetto è scaduto. Genera una nuova esporta
msgid "Project export started. A download link will be sent by email."
msgstr "Esportazione del progetto iniziata. Un link di download sarà inviato via email."
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Iscriviti"
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "Ricerco e configuro le metriche..."
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "Pubblico - il gruppo e tutti i progetti pubblici possono essere visualizzati senza alcuna autenticazione."
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "Vedi altro"
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
-msgstr "Leggimi"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr "Richieste di Merge Completate Correlate"
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "Ricordamelo più tardi"
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr "Richiedi accesso"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Ripristina questo commit"
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr "Salva modifiche"
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Salva pianificazione pipeline"
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr "Set"
@@ -7288,6 +8455,48 @@ msgstr "Settembre"
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr "Snippet"
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr "Qualcosa è andato storto durante il fetch dei progetti."
msgid "Something went wrong while fetching the registry list."
msgstr "Qualcosa è andato storto durante il recupero dell'elenco dei registri."
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr "Ordina per"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr "Dal primo Joinato"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr "Codice Sorgente"
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "inizia una %{new_merge_request} con queste modifiche"
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Lo stadio di Issue mostra il tempo che impiega un issue ad esser correlato ad una Milestone, o ad esser aggiunto ad una tua Lavagna. Inizia la creazione di problemi per visualizzare i dati in questo stadio."
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Il valore falsato nel mezzo di una serie di dati osservati. ES: tra 3,5,9 il mediano è 5. Tra 3,5,7,8 il mediano è (5+7)/2 quindi 6."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "Carica un nuovo file"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "Carica file"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "clicca per caricare"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr "Usa le tue impostazioni globali "
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr "Pubblico"
msgid "VisibilityLevel|Unknown"
msgstr "Sconosciuto"
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Vuoi visualizzare i dati? Richiedi l'accesso ad un amministratore, grazie."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "Non ci sono sufficienti dati da mostrare su questo stadio"
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr "Ritira richiesta d'accesso"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr "Puoi aggiungere files solo quando sei in una branch"
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr "Hai raggiunto il tuo limite di progetto"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr "Necessiti del permesso."
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "Il tuo nome"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr "fa"
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] "giorno"
msgstr[1] "giorni"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr "Nuova richiesta di merge"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "Notifiche via email"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] "in %d minuto "
msgstr[1] "entro %d minuti "
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index 26390fb862a..8998c660e18 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:46\n"
+"PO-Revision-Date: 2019-02-11 12:12\n"
msgid " Status"
msgstr " ステータス"
@@ -29,16 +29,17 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] " %dãƒã‚¤ãƒ³ãƒˆã§æ”¹å–„"
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] "%d 個ã®å¤‰æ›´ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«"
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr "プロジェクト内㮠\"%{query}\""
msgid "%d commit"
msgid_plural "%d commits"
@@ -48,9 +49,8 @@ msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] "%d個ã®ã‚³ãƒŸãƒƒãƒˆå¾…ã¡"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -68,6 +68,10 @@ msgid "%d issue"
msgid_plural "%d issues"
msgstr[0] "%d個ã®èª²é¡Œ"
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d 個ã®ãƒ¬ã‚¤ãƒ¤ãƒ¼"
@@ -96,15 +100,18 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 㨠%{openOrClose} %{noteable}"
msgid "%{authorsName}'s discussion"
-msgstr ""
+msgstr "%{authorsName} ã®ãƒ‡ã‚£ã‚¹ã‚«ãƒƒã‚·ãƒ§ãƒ³"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} ㌠%{commit_timeago} ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã—ãŸ"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
+msgstr "%{counter_storage} (%{counter_repositories} リãƒã‚¸ãƒˆãƒªã€%{counter_build_artifacts} ビルドアーティファクトã€%{counter_lfs_objects} LFS)"
msgid "%{count} %{alerts}"
+msgstr "%{count} %{alerts}"
+
+msgid "%{count} more"
msgstr ""
msgid "%{count} more assignees"
@@ -116,18 +123,24 @@ msgstr[0] "%{count} 人ã®å‚加者"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
-msgstr[0] ""
+msgstr[0] "ä¿ç•™ä¸­ã®ã‚³ãƒ¡ãƒ³ãƒˆ%{count} 件"
msgid "%{filePath} deleted"
msgstr "%{filePath} ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
msgid "%{firstLabel} +%{labelCount} more"
+msgstr "%{firstLabel} +%{labelCount} ã®è©³ç´°"
+
+msgid "%{firstOption} +%{extraOptionCount} more"
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}グループ%{group_docs_link_end}を使用ã™ã‚‹ã¨ã€è¤‡æ•°ã®ãƒ—ロジェクトを管ç†ã—ã¦å…±åŒä½œæ¥­ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚グループã®ãƒ¡ãƒ³ãƒãƒ¼ã¯ã€æ‰€å±žã™ã‚‹ãƒ—ロジェクトã®ã™ã¹ã¦ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType}を削除ã—ã¾ã™ï¼ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
msgid "%{loadingIcon} Started"
@@ -139,9 +152,6 @@ msgstr "%{lock_path} ã¯GitLab ユーザー %{lock_user_id} ã«ã‚ˆã£ã¦ãƒ­ãƒƒã‚
msgid "%{name}'s avatar"
msgstr "%{name}ã®ã‚¢ãƒã‚¿ãƒ¼"
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} ã¯ã€ã‚«ã‚¹ã‚¿ãƒ ãƒ‰ãƒ¡ã‚¤ãƒ³ã®ä»£æ›¿ã¨ã—ã¦ä½¿ç”¨ã§ãã¾ã™ã€‚"
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{default_branch} ã‹ã‚‰ %{number_commits_behind} コミットé…ã‚Œã¦ã„ã¦ã€ %{number_commits_ahead} コミット進んã§ã„ã¾ã™ã€‚"
@@ -151,6 +161,24 @@ msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% 完了"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text} %{files} ファイル"
@@ -165,6 +193,12 @@ msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{unstaged} 件ã®æœªã‚¹ãƒ†ãƒ¼ã‚¸ã®å¤‰æ›´ã¨ã€ %{staged} 件ã®ã‚¹ãƒ†ãƒ¼ã‚¸æ¸ˆã¿å¤‰æ›´"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr "GitLab Inc. ã¨ã©ã®ã‚ˆã†ãªæƒ…報を共有ã™ã‚‹ã‹ã«ã¤ã„ã¦ã¯ %{usage_ping_link_start} ã“ã¡ã‚‰%{usage_ping_link_end} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
msgstr ""
msgid "+ %{count} more"
@@ -173,6 +207,9 @@ msgstr ""
msgid "+ %{moreCount} more"
msgstr "+ 他 %{moreCount} 件"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr "- RunnerãŒã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã§æ–°ã—ã„ジョブを処ç†ã§ãã¾ã™"
@@ -229,11 +266,14 @@ msgstr[0] "%dユーザー"
msgid "1st contribution!"
msgstr "最åˆã®è²¢çŒ®!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "2段階èªè¨¼ãŒæœ‰åŠ¹"
-msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã®é–²è¦§ã«ã¯æ¨©é™ãŒå¿…è¦ã§ã™ã€‚GitLab管ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。"
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
msgid "403|You don't have the permission to access this page."
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。"
@@ -274,11 +314,11 @@ msgstr "<strong>%{group_name}</strong> グループã®ãƒ¡ãƒ³ãƒãƒ¼"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr "<strong>%{pushes}</strong>回ã®ãƒ—ッシュã€<strong>%{commits}</strong>回以上ã®ã‚³ãƒŸãƒƒãƒˆãŒè²¢çŒ®è€…<strong>%{people}</strong>ã«ã‚ˆã£ã¦è¡Œã‚ã‚Œã¾ã—ãŸã€‚"
-msgid "<strong>Removes</strong> source branch"
-msgstr "ソースブランãƒã‚’<strong>削除</strong>"
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr ""
+msgstr "「Runnerã€ã¯ã‚¸ãƒ§ãƒ–を実行ã™ã‚‹ãƒ—ロセスã§ã™ã€‚å¿…è¦ãªæ•°ã® Runner ã‚’ä»»æ„ã«ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã§ãã¾ã™ã€‚"
msgid "A collection of graphs regarding Continuous Integration"
msgstr "CIã«ã¤ã„ã¦ã®ã‚°ãƒ©ãƒ•"
@@ -287,10 +327,10 @@ msgid "A default branch cannot be chosen for an empty project."
msgstr ""
msgid "A deleted user"
-msgstr ""
+msgstr "削除ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr ""
+msgstr "ãŸã ã¡ã«é–‹ç™ºãƒ¡ãƒ³ãƒãƒ¼ã§ã„ãŸã ã„ãŸãƒ¬ãƒãƒ¼ãƒˆã‚’æ‹èª­ã—å‚考ã«ã•ã›ã¦ã„ãŸã ãã¾ã™ã€‚"
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "フォークã«æ–°ã—ã„ブランãƒãŒä½œæˆã•ã‚Œã€æ–°ã—ã„マージリクエストãŒé–‹å§‹ã—ã¾ã™ã€‚"
@@ -322,6 +362,9 @@ msgstr "ä¸æ­£è¡Œç‚ºãƒ¬ãƒãƒ¼ãƒˆ"
msgid "Abuse reports"
msgstr "迷惑行為レãƒãƒ¼ãƒˆ"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr "利用è¦ç´„ã«åŒæ„ã™ã‚‹"
@@ -358,29 +401,32 @@ msgstr "アクティビティー"
msgid "Add"
msgstr "追加"
-msgid "Add Changelog"
-msgstr "変更履歴を追加"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "貢献者å‘ã‘ガイドを追加"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
-msgstr ""
+msgstr "グループ Webhooks 㨠GitLab ã®ã‚¨ãƒ³ã‚¿ãƒ¼ãƒ—ライズ版を追加ã—ã¾ã™ã€‚"
msgid "Add Jaeger URL"
-msgstr ""
+msgstr "Jaeger URL を追加"
msgid "Add Kubernetes cluster"
msgstr "Kubernetes クラスターを追加"
-msgid "Add Readme"
-msgstr "Readmeを追加"
+msgid "Add README"
+msgstr ""
-msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr "ã‚ãªãŸã® Wiki ã«ãƒ—ロジェクトã«é–¢ã™ã‚‹æƒ…報をå«ã‚€ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’追加ã™ã‚‹ã¨ã€GitLab ã¯ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®ä»£ã‚ã‚Šã«ãれをã“ã“ã«è¡¨ç¤ºã—ã¾ã™ã€‚"
+
msgid "Add a table"
-msgstr ""
+msgstr "テーブルを追加ã™ã‚‹"
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã«è¡¨ç¤ºã™ã‚‹ãƒ†ã‚­ã‚¹ãƒˆã‚’追加ã—ã¾ã™ã€‚ ãŸã ã—ã€%{character_limit} 文字ã®åˆ¶é™ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -389,7 +435,7 @@ msgid "Add comment now"
msgstr ""
msgid "Add image comment"
-msgstr ""
+msgstr "ç”»åƒã‚³ãƒ¡ãƒ³ãƒˆã‚’追加"
msgid "Add license"
msgstr "ライセンスを追加"
@@ -401,20 +447,26 @@ msgid "Add new directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’追加"
msgid "Add projects"
-msgstr ""
+msgstr "プロジェクト追加"
msgid "Add reaction"
msgstr "リアクションã®è¿½åŠ "
-msgid "Add to review"
+msgid "Add to project"
msgstr ""
+msgid "Add to review"
+msgstr "レビュー追加"
+
msgid "Add todo"
msgstr "Todoを追加"
msgid "Add user(s) to the group:"
msgstr "グループã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追加:"
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr "ユーザーをグループã¸è¿½åŠ "
@@ -425,14 +477,11 @@ msgid "Additional text"
msgstr "追加テキスト"
msgid "Admin Area"
-msgstr ""
+msgstr "管ç†è€…エリア"
msgid "Admin Overview"
msgstr "管ç†è€…用概è¦"
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -466,12 +515,42 @@ msgstr "プロジェクト %{projectName} を削除ã—ã¾ã™ã‹?"
msgid "AdminProjects|Delete project"
msgstr "プロジェクトã®å‰Šé™¤"
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクトã®Auto Review AppsãŠã‚ˆã³Auto Deployステージã§ä½¿ç”¨ã™ã‚‹ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’指定ã—ã¾ã™ã€‚"
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "ブロックユーザー"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "ユーザー %{username} ã¨è²¢çŒ®åº¦ã‚’削除ã—ã¾ã™ã‹?"
@@ -484,12 +563,42 @@ msgstr "ユーザーã®å‰Šé™¤"
msgid "AdminUsers|Delete user and contributions"
msgstr "ユーザーã¨è²¢çŒ®åº¦ã®å‰Šé™¤"
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "確èªã®ãŸã‚ã€%{projectName} を入力ã—ã¦ãã ã•ã„"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "確èªã®ãŸã‚ã€%{username} を入力ã—ã¦ãã ã•ã„"
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -498,7 +607,10 @@ msgstr "高度ãªè¨­å®š"
msgid "Alert"
msgid_plural "Alerts"
-msgstr[0] ""
+msgstr[0] "アラート"
+
+msgid "Alerts"
+msgstr ""
msgid "All"
msgstr "ã™ã¹ã¦"
@@ -509,14 +621,20 @@ msgstr "ã™ã¹ã¦ã®å¤‰æ›´ãŒã‚³ãƒŸãƒƒãƒˆã•ã‚Œã¦ã„ã¾ã™"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "空ã®ãƒ—ロジェクトã€ãƒ†ãƒ³ãƒ—レートã‹ã‚‰ã€ã¾ãŸã¯ã‚¤ãƒ³ãƒãƒ¼ãƒˆæ™‚ã«ã™ã¹ã¦ã®æ©Ÿèƒ½ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ãŒã€å¾Œã§ãƒ—ロジェクト設定ã§ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr "ターゲットブランãƒã«ãƒžãƒ¼ã‚¸ã§ãるメンãƒãƒ¼ã‹ã‚‰ã®ã‚³ãƒŸãƒƒãƒˆã‚’許å¯ã—ã¾ã™ã€‚"
msgid "Allow projects within this group to use Git LFS"
-msgstr ""
+msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—内ã®ãƒ—ロジェクト㫠Git LFS を使用ã§ãるよã†ã«ã™ã‚‹"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr "パイプラインã«åŠ ãˆã€ãƒ­ã‚°ã‚„æˆæžœç‰©ãªã©ã®ã‚ˆã†ãªã‚¸ãƒ§ãƒ–ã®è©³ç´°ãªæƒ…å ±ã«å¯¾ã—ã¦ã€ãƒ‘ブリックレベルã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã—ã¾ã™ã€‚"
@@ -528,11 +646,14 @@ msgid "Allow requests to the local network from hooks and services."
msgstr "フックãŠã‚ˆã³ã‚µãƒ¼ãƒ“スã‹ã‚‰ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’許å¯ã™ã‚‹ã€‚"
msgid "Allow users to request access"
-msgstr ""
+msgstr "ユーザーãŒã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã§ãるよã†ã«ã™ã‚‹"
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Kubernetes クラスターを追加ãŠã‚ˆã³ç®¡ç†ã§ãã¾ã™ã€‚"
@@ -560,46 +681,19 @@ msgstr "アプリケーション㮠%{link_to_client} ãŒã‚ãªãŸã® GitLab ã‚¢
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "GitLab ユーザフィールドãŒç©ºã®å ´åˆã€ã™ã¹ã¦ã®å•é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã®èª¬æ˜Žã« FogBugz ユーザã®ãƒ•ãƒ«ãƒãƒ¼ãƒ  (例ãˆã°ã€By John Smith)を追加ã—ã¾ã™ã€‚ã¾ãŸã€ã“れらã®å•é¡Œã‚„コメントをプロジェクト作æˆè€…ã«é–¢é€£ä»˜ã‘ã‚‹ã‹ã€ã¾ãŸã¯å‰²ã‚Šå½“ã¦ã¾ã™ã€‚"
-msgid "An error accured whilst committing your changes."
-msgstr "変更ã®ã‚³ãƒŸãƒƒãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
msgid "An error has occurred"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-msgid "An error occured creating the new branch."
-msgstr "æ–°ã—ã„ブランãƒã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "An error occured whilst fetching the job trace."
-msgstr "ジョブトレースã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "An error occured whilst fetching the latest pipeline."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
-msgid "An error occured whilst loading all the files."
-msgstr "ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "An error occured whilst loading the file content."
-msgstr "ファイルã®å†…容を読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "An error occured whilst loading the file."
-msgstr "ファイルを読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr "マージリクエストã®å¤‰æ›´ã‚’読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr "マージリクエストã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報を読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "An error occured whilst loading the merge request."
-msgstr "マージリクエストã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "An error occured whilst loading the pipelines jobs."
-msgstr "パイプラインジョブã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
msgid "An error occurred adding a draft to the discussion."
-msgstr ""
+msgstr "ディスカッションã«ä¸‹æ›¸ãを追加ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred adding a new draft."
+msgstr "æ–°ã—ã„ドラフトã®è¿½åŠ ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
+msgid "An error occurred creating the new branch."
msgstr ""
msgid "An error occurred previewing the blob"
@@ -615,7 +709,7 @@ msgid "An error occurred while adding approver"
msgstr "承èªè€…ã®è¿½åŠ ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while deleting the comment"
-msgstr ""
+msgstr "コメントã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while detecting host keys"
msgstr "ホストキーã®æ¤œå‡ºä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -627,7 +721,7 @@ msgid "An error occurred while dismissing the feature highlight. Refresh the pag
msgstr "ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚’消去ã—ã¦ã„ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ページを更新ã—ã¦ã‚‚ã†ä¸€åº¦æ¶ˆåŽ»ã—ã¦ãã ã•ã„。"
msgid "An error occurred while fetching markdown preview"
-msgstr ""
+msgstr "Markdown プレビューã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while fetching pending comments"
msgstr ""
@@ -674,17 +768,26 @@ msgstr "ファイルåã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while loading the file"
msgstr "ファイルã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr "リクエスト作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while removing approver"
msgstr "承èªè€…ã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr "KaTeXã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while rendering preview broadcast message"
-msgstr ""
+msgstr "プレビュー時ã®ãƒ–ロードキャストメッセージをレンダリングã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while retrieving calendar activity"
msgstr "カレンダーアクティビティーå–å¾—ã®éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -705,17 +808,62 @@ msgid "An error occurred while unsubscribing to notifications."
msgstr "通知ã®è³¼èª­ã‚’解除中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while updating the comment"
-msgstr ""
+msgstr "コメントを更新中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while validating username"
msgstr "ユーザåã®æ¤œè¨¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†åº¦ãŠè©¦ã—ãã ã•ã„。"
-msgid "Analytics"
+msgid "An unexpected error occurred while checking the project environment."
msgstr ""
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "Analytics"
+msgstr "アクセス解æž"
+
msgid "Anonymous"
msgstr "匿å"
@@ -735,7 +883,7 @@ msgid "Application"
msgstr "アプリケーション"
msgid "Application ID"
-msgstr ""
+msgstr "アプリケーション ID"
msgid "Application: %{name}"
msgstr "アプリケーション:%{name}"
@@ -743,6 +891,21 @@ msgstr "アプリケーション:%{name}"
msgid "Applications"
msgstr "アプリケーション"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "4月"
@@ -753,23 +916,38 @@ msgid "Archived project! Repository and other project resources are read-only"
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚リãƒã‚¸ãƒˆãƒªãŠã‚ˆã³ãã®ä»–ã®ãƒ—ロジェクトリソースã¯èª­ã¿å–り専用ã§ã™"
msgid "Archived projects"
+msgstr "アーカイブã•ã‚ŒãŸãƒ—ロジェクト"
+
+msgid "Are you sure"
msgstr ""
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ã“ã®ãƒ‘イプラインスケジュールを削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to erase this build?"
-msgstr ""
+msgstr "ã“ã®ãƒ“ルドを削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "変更ãŒä¿å­˜ã•ã‚Œã¦ã„ã¾ã›ã‚“ãŒç ´æ£„ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr "ã“ã® %{group_name} を削除ã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr "ã“ã® ID を削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -780,16 +958,19 @@ msgid "Are you sure you want to reset the health check token?"
msgstr "本当ã«ãƒ˜ãƒ«ã‚¹ãƒã‚§ãƒƒã‚¯ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセットã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "ã“ã®ç’°å¢ƒã‚’åœæ­¢ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "%{path_lock_path} ã®ãƒ­ãƒƒã‚¯ã‚’解除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Artifact ID"
-msgstr ""
+msgstr "アーティファクト ID"
msgid "Artifacts"
msgstr "アーティファクト"
@@ -803,6 +984,9 @@ msgstr "グループ Runner ã®è¨­å®šã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—ã® Maintainer ã«ä¾é ¼ã
msgid "Assertion consumer service URL"
msgstr "アサーション コンシューマー サービス URL"
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "#FF0000ã®ã‚ˆã†ãªã‚«ã‚¹ã‚¿ãƒ ã‚«ãƒ©ãƒ¼ã‚’割り当ã¦ã‚‹"
@@ -812,6 +996,9 @@ msgstr "ラベルを割り当ã¦ã‚‹"
msgid "Assign milestone"
msgstr "マイルストーンを割り当ã¦ã‚‹"
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr "割り当ã¦å…ˆ"
@@ -839,6 +1026,9 @@ msgstr "担当者一覧ã«ã¯ã€é¸æŠžã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦
msgid "Assignee(s)"
msgstr "担当者"
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "ドラッグ&ドロップã¾ãŸã¯ %{upload_link} ã§ãƒ•ã‚¡ã‚¤ãƒ«ã‚’添付"
@@ -851,6 +1041,9 @@ msgstr "8月"
msgid "August"
msgstr "8月"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "èªè¨¼ãƒ­ã‚°"
@@ -866,6 +1059,9 @@ msgstr "作æˆè€…"
msgid "Authorization code:"
msgstr "èªè¨¼ã‚³ãƒ¼ãƒ‰:"
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr "ã“ã®ã‚¢ãƒ—リケーションã«ã‚ãªãŸã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードãŒå…¥åŠ›ã•ã‚ŒãŸã®ã§ã€æ‰¿èªãŒè¨±å¯ã•ã‚Œã¾ã—ãŸã€‚"
@@ -893,15 +1089,6 @@ msgstr "Auto DevOps ãŒæœ‰åŠ¹ã§ã™"
msgid "Auto DevOps, runners and job artifacts"
msgstr "Auto DevOps, Runner,ãŠã‚ˆã³æˆæžœç‰©"
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr "自動 Review Apps ã¨è‡ªå‹•ãƒ‡ãƒ—ロイã§ã¯ã€ %{kubernetes} ãŒæ­£ã—ã動作ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr "自動 Review Apps ã¨è‡ªå‹•ãƒ‡ãƒ—ロイã§ã¯ã€ãƒ‰ãƒ¡ã‚¤ãƒ³åã¨æ­£å¸¸ã«å‹•ä½œã™ã‚‹ %{kubernetes} ãŒå¿…è¦ã§ã™ã€‚"
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "自動 Review Apps ã¨è‡ªå‹•ãƒ‡ãƒ—ロイを正ã—ãå‹•ã‹ã™ãŸã‚ã«ã¯ãƒ‰ãƒ¡ã‚¤ãƒ³åãŒå¿…è¦ã§ã™ã€‚"
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -935,14 +1122,26 @@ msgstr "Auto DevOps を有効ã«ã™ã‚‹"
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "利用å¯èƒ½"
-msgid "Available group Runners : %{runners}"
-msgstr "利用å¯èƒ½ãªã‚°ãƒ«ãƒ¼ãƒ— Runner : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
-msgid "Available group Runners : %{runners}."
-msgstr "利用å¯èƒ½ãªã‚°ãƒ«ãƒ¼ãƒ— Runner : %{runners}。"
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -999,7 +1198,7 @@ msgid "Badges|No image to preview"
msgstr "プレビューã™ã‚‹ç”»åƒã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "有効㪠URL を入力ã—ã¦ãã ã•ã„。"
msgid "Badges|Project Badge"
msgstr "プロジェクト ãƒãƒƒã‚¸"
@@ -1029,19 +1228,19 @@ msgid "Badges|This project has no badges"
msgstr "ã“ã®ãƒ—ロジェクトã«ãƒãƒƒã‚¸ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr ""
+msgstr "ã“ã®ãƒãƒƒã‚¸ã‚’削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚削除ã•ã‚ŒãŸãƒãƒƒã‚¸ã¯<strong>復元ã§ãã¾ã›ã‚“</strong>。"
msgid "Badges|Your badges"
msgstr "ãƒãƒƒã‚¸"
msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
+msgstr "例 %{exampleUrl}"
msgid "BatchComments|Delete all pending comments"
-msgstr ""
+msgstr "ä¿ç•™ä¸­ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’ã™ã¹ã¦å‰Šé™¤"
msgid "BatchComments|Discard review?"
-msgstr ""
+msgstr "レビューを破棄ã—ã¾ã™ã‹ï¼Ÿ"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
msgstr ""
@@ -1074,7 +1273,7 @@ msgid "BillingPlans|Downgrade"
msgstr "ダウングレード"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
-msgstr ""
+msgstr "%{faq_link} を読んã§å„プランã®è©³ç´°ã‚’確èªã™ã‚‹ã‹ã€GitLab.com Gold ã®30日間無料試用版を開始ã—ã¦ãã ã•ã„。"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
msgstr "å„プランã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ %{faq_link} ã‚’ã”確èªãã ã•ã„。"
@@ -1122,11 +1321,17 @@ msgid "BillingPlans|per user"
msgstr "1ユーザーã«ã¤ã"
msgid "Bitbucket Server Import"
-msgstr ""
+msgstr "Bitbucket サーãƒãƒ¼ インãƒãƒ¼ãƒˆ"
msgid "Bitbucket import"
msgstr "Bitbucket インãƒãƒ¼ãƒˆ"
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr "ブログ"
@@ -1136,10 +1341,6 @@ msgstr "ボード"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "%{branchName} ブランãƒã¯ã“ã®ãƒ—ロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] "ブランム(%{branch_count})"
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "<strong>%{branch_name}</strong> ブランãƒãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚自動デプロイを設定ã™ã‚‹ã«ã¯ã€GitLab CI Yaml テンプレートをé¸æŠžã—ã¦ã€å¤‰æ›´ã‚’コミットã—ã¦ãã ã•ã„。 %{link_to_autodeploy_doc}"
@@ -1293,24 +1494,39 @@ msgstr "ファイルを表示"
msgid "Browse files"
msgstr "ファイルを表示"
-msgid "Built-In"
-msgstr "ビルトイン"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
msgid "Business metrics (Custom)"
msgstr "ビジãƒã‚¹ãƒ¡ãƒˆãƒªã‚¯ã‚¹ï¼ˆã‚«ã‚¹ã‚¿ãƒ ï¼‰"
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr "CI / CD 設定"
-msgid "CI will run using the credentials assigned above."
+msgid "CI Lint"
msgstr ""
+msgid "CI will run using the credentials assigned above."
+msgstr "CI ã¯ä¸Šè¨˜ã§å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸè³‡æ ¼æƒ…報を元ã«å®Ÿè¡Œã—ã¾ã™ã€‚"
+
msgid "CI/CD"
msgstr "CI/CD"
@@ -1339,17 +1555,11 @@ msgid "CICD|Continuous deployment to production using timed incremental rollout"
msgstr ""
msgid "CICD|Default to Auto DevOps pipeline"
-msgstr ""
+msgstr "デフォルト㮠Auto DevOps パイプライン"
msgid "CICD|Deployment strategy"
msgstr "デプロイ戦略"
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr "デプロイ戦略を正ã—ã動作ã•ã›ã‚‹ãŸã‚ã«ã¯ãƒ‰ãƒ¡ã‚¤ãƒ³åãŒå¿…è¦ã§ã™ã€‚"
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr "Auto DevOps 㧠Auto マルムKubernetes クラスターをセットアップã™ã‚‹å ´åˆã¯ã€ã“ã“ã§ãƒ‰ãƒ¡ã‚¤ãƒ³ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã‚’è¡Œã‚ãªã„ã§ãã ã•ã„。"
-
msgid "CICD|Jobs"
msgstr "ジョブ"
@@ -1357,20 +1567,29 @@ msgid "CICD|Learn more about Auto DevOps"
msgstr "Auto DevOps ã®è©³ç´°"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "ãã®ä»–ã« CI 設定ファイルãŒè¦‹ã¤ã‹ã‚‰ãªã„å ´åˆã€Auto DevOps パイプラインãŒå®Ÿè¡Œã•ã‚Œã¾ã™ã€‚"
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
-msgstr "自動 Review Apps ã¨è‡ªå‹•ãƒ‡ãƒ—ロイステージを使用ã—ãŸã„å ´åˆã¯ã€ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
msgid "CICD|instance enabled"
msgstr "インスタンスãŒæœ‰åŠ¹"
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr "コールãƒãƒƒã‚¯ URL"
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr "ã“ã®ãƒ–ランãƒã«ã¯ HEAD コミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "キャンセル"
@@ -1383,12 +1602,21 @@ msgstr "自動的ã«ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "管ç†ä¸‹ã® Kubernetes クラスターを変更ã§ãã¾ã›ã‚“"
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr "証明書ã®ãƒ•ã‚£ãƒ³ã‚¬ãƒ¼ プリント"
msgid "Change Weight"
msgstr "ウェイトを変更ã™ã‚‹"
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr "テンプレートを変更"
@@ -1410,12 +1638,12 @@ msgstr "リãƒãƒ¼ãƒˆ"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "コミット済ã®å¤‰æ›´ã‚’ revert ã™ã‚‹ãŸã‚ã«æ–°ã—ã„コミットを作æˆã—ã¾ã™"
-msgid "Changelog"
-msgstr "変更履歴"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "<b>source</b>リビジョンãŒ<b>target</b>リビジョン内ã«å–ã‚Šè¾¼ã¾ã‚Œã¦ã„るよã†ãªå¤‰æ›´ã¨ã—ã¦è¡¨ç¤ºã•ã‚Œã¾ã™"
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "ãƒãƒ£ãƒ¼ãƒˆ"
@@ -1425,9 +1653,15 @@ msgstr "ãƒãƒ£ãƒƒãƒˆ"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr "%{text} ãŒåˆ©ç”¨å¯èƒ½ã‹ç¢ºèªã—ã¦ã„ã¾ã™â€¦"
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "ブランãƒãŒåˆ©ç”¨å¯èƒ½ã‹ç¢ºèªã—ã¦ã„ã¾ã™â€¦"
@@ -1438,10 +1672,10 @@ msgid "Cherry-pick this merge request"
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ãƒã‚§ãƒªãƒ¼ãƒ”ック"
msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
-msgstr ""
+msgstr "<strong>アーカイブã®ä½œæˆ</strong>ã‚’é¸æŠžã—ã€ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–作æˆã®å®Œäº†ã‚’ãŠå¾…ã¡ãã ã•ã„。"
msgid "Choose <strong>Next</strong> at the bottom of the page."
-msgstr ""
+msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã®ä¸‹éƒ¨ã«ã‚ã‚‹<strong>次ã¸</strong>ã‚’é¸æŠžã—ã¦ãã ã•ã„。"
msgid "Choose File ..."
msgstr "ファイルをé¸æŠž..."
@@ -1449,6 +1683,12 @@ msgstr "ファイルをé¸æŠž..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "変更内容を確èªã—ãŸã‚Šãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã™ã‚‹ãŸã‚ã«ã€Branch/tag (例: %{master}) ã‚’é¸æŠžã™ã‚‹ã‹ã€ã‚³ãƒŸãƒƒãƒˆID(例: %{sha})を入力ã—ã¦ãã ã•ã„。"
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1459,7 +1699,7 @@ msgid "Choose any color."
msgstr "カラーをé¸æŠžã—ã¦ãã ã•ã„。"
msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
-msgstr ""
+msgstr "<code>clone</code> ã¾ãŸã¯ <code>fetch</code> ã‚’é¸æŠžã—ã¦æœ€æ–°ã®ã‚¢ãƒ—リケーションコードをå–å¾—ã—ã¦ãã ã•ã„"
msgid "Choose file..."
msgstr "ファイルをé¸æŠž..."
@@ -1467,6 +1707,9 @@ msgstr "ファイルをé¸æŠž..."
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr "åŒæœŸã•ã›ãŸã„セカンダリノードã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžã—ã¦ãã ã•ã„。"
@@ -1477,7 +1720,7 @@ msgid "Choose which repositories you want to import."
msgstr "インãƒãƒ¼ãƒˆã—ãŸã„リãƒã‚¸ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。"
msgid "Choose which shards you wish to synchronize to this secondary node."
-msgstr ""
+msgstr "セカンダリノードã¨åŒæœŸã•ã›ãŸã„シャードをé¸æŠžã—ã¦ãã ã•ã„。"
msgid "CiStatusLabel|canceled"
msgstr "キャンセル"
@@ -1486,7 +1729,7 @@ msgid "CiStatusLabel|created"
msgstr "作æˆæ¸ˆã¿"
msgid "CiStatusLabel|delayed"
-msgstr ""
+msgstr "é…延"
msgid "CiStatusLabel|failed"
msgstr "失敗"
@@ -1560,8 +1803,8 @@ msgstr "ã™ã¹ã¦ã®ç’°å¢ƒ"
msgid "CiVariable|Create wildcard"
msgstr "ワイルドカードã®ä½œæˆ"
-msgid "CiVariable|Error occured while saving variables"
-msgstr "変数ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
msgid "CiVariable|New environment"
msgstr "æ–°ã—ã„環境"
@@ -1581,9 +1824,15 @@ msgstr "検証ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "使用ã§ãã¾ã›ã‚“:%{reason}"
-msgid "Clear search"
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
msgstr ""
+msgid "Clear search"
+msgstr "検索をクリア"
+
msgid "Clear search input"
msgstr "検索欄ã®æ¶ˆåŽ»"
@@ -1591,7 +1840,7 @@ msgid "Click any <strong>project name</strong> in the project list below to navi
msgstr "プロジェクトリストã§<strong>プロジェクトå</strong>をクリックã™ã‚‹ã¨ã€ãƒ—ロジェクトã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«ç§»å‹•ã—ã¾ã™ã€‚"
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
-msgstr ""
+msgstr "<strong>ダウンロード</strong> ボタンをクリックã—ã€ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã®å®Œäº†ã‚’ãŠå¾…ã¡ãã ã•ã„。"
msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
msgstr "å³ä¸Šã®<strong>昇格</strong>ボタンをクリックã—ã¦ã‚°ãƒ«ãƒ¼ãƒ—マイルストーンã¸æ˜‡æ ¼"
@@ -1620,28 +1869,52 @@ msgstr "クライアントèªè¨¼ã‚­ãƒ¼ã®ãƒ‘スワード"
msgid "Clients"
msgstr "クライアント"
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr "リãƒã‚¸ãƒˆãƒªã‚’クローン"
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr "クローズã™ã‚‹"
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
+msgstr "クローズ"
+
+msgid "Closed (moved)"
msgstr ""
msgid "Closed issues"
msgstr "クローズã—ãŸèª²é¡Œ"
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} ã¯æ­£å¸¸ã« Kubernetes クラスターã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã—ãŸ"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
-msgstr ""
+msgstr "%{boldNotice} ã“ã‚Œã«ã‚ˆã‚Šã€ãƒ­ãƒ¼ãƒ‰ãƒãƒ©ãƒ³ã‚µã®ã‚ˆã†ãªã€è¿½åŠ ã®ãƒªã‚½ãƒ¼ã‚¹ã‚’追加ã—ã¾ã™ã€‚例ãˆã°ã€ã‚ãªãŸãŒ Kubernetes クラスターãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„るホスティングプロãƒã‚¤ãƒ€ を使用ã—ã¦ã„るよã†ãªå ´åˆã€è¿½åŠ ã®è²»ç”¨ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚Google Kubernetes Engine を使用ã—ã¦ã„ã‚‹å ´åˆã¯ã€ %{pricingLink} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1651,13 +1924,13 @@ msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Kubernetes クラスターを追加"
msgid "ClusterIntegration|Add a Kubernetes cluster integration"
-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 ""
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "グループã«çµ±åˆã‚’追加ã™ã‚‹ã¨ã€ã™ã¹ã¦ã®ãƒ—ロジェクトã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ãŒå…±æœ‰ã•ã‚Œã¾ã™ã€‚"
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "ã“ã® Kubernetes クラスター統åˆã«é–¢ã™ã‚‹è©³ç´°ã‚ªãƒ—ション"
@@ -1665,27 +1938,42 @@ msgstr "ã“ã® Kubernetes クラスター統åˆã«é–¢ã™ã‚‹è©³ç´°ã‚ªãƒ—ション
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "プロジェクトゾーンã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr "プロジェクトã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr "Google Cloud API ã¸æŽ¥ç¶šã‚’試ã¿ãŸéš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚後ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr "アプリケーション"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr "ã“ã® Kubernetes クラスター統åˆã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿã“ã®æ“作ã§ã¯å®Ÿéš›ã® Kubernetes クラスターã¯å‰Šé™¤ã•ã‚Œã¾ã›ã‚“。"
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr "CA 証明書"
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "èªè¨¼å±€ãƒãƒ³ãƒ‰ãƒ« (PEMå½¢å¼)"
@@ -1695,6 +1983,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "API URLをコピー"
@@ -1707,6 +1998,9 @@ msgstr "Ingressã®IPアドレスをクリップボードã«ã‚³ãƒ”ーã™ã‚‹"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr "Jupyter ã®ãƒ›ã‚¹ãƒˆåをクリップボードã¸ã‚³ãƒ”ー"
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Kubernetes クラスターåをコピー"
@@ -1717,7 +2011,7 @@ msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "Kubernetes クラスターを作æˆ"
msgid "ClusterIntegration|Did you know?"
-msgstr ""
+msgstr "ã”存知ã§ã™ã‹ï¼Ÿ"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
msgstr ""
@@ -1734,6 +2028,15 @@ 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 "Google Cloud Platform (GCP) ã®ã™ã¹ã¦ã®æ–°è¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã¯ã€300ドル分ã®ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆãŒä»˜ä¸Žã•ã‚Œã¾ã™ %{sign_up_link} 。ã¾ãŸã€Google ã¨ã®ãƒ‘ートナーシップã«ã‚ˆã‚Šã€Google Kubernetes Engine 㨠GitLab ã®ã‚¤ãƒ³ãƒ†ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’開始ã™ã‚‹ãŸã‚ã«ã€æ–°è¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒ»æ—¢å­˜ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’å•ã‚ãšã€GCP アカウントã«è¿½åŠ ã®200ドル分ã®ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆã‚’æä¾›ã—ã¾ã™ã€‚"
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr "マシンタイプをå–得中"
@@ -1762,7 +2065,7 @@ msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Google Kubernetes Engine プロジェクト"
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "グループクラスター"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1806,6 +2109,12 @@ msgstr "Kubernetes クラスターを自動統åˆ"
msgid "ClusterIntegration|Integration status"
msgstr "çµ±åˆã®çŠ¶æ…‹"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Jupyter ã®ãƒ›ã‚¹ãƒˆå"
@@ -1816,9 +2125,15 @@ msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and pro
msgstr ""
msgid "ClusterIntegration|Knative"
-msgstr ""
+msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
+msgstr "Knativeドメインå:"
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster"
@@ -1852,9 +2167,12 @@ msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_en
msgstr "%{help_link_start}ゾーン%{help_link_end}ã®è©³ç´°ã€‚"
msgid "ClusterIntegration|Learn more about Kubernetes"
-msgstr ""
+msgstr "Kubernetes ã®è©³ç´°"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr "グループ Kubernetes クラスターã®è©³ç´°"
+
+msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1900,7 +2218,7 @@ msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in o
msgstr ""
msgid "ClusterIntegration|Project cluster"
-msgstr ""
+msgstr "プロジェクトクラスター"
msgid "ClusterIntegration|Project namespace"
msgstr "プロジェクトã®åå‰ç©ºé–“"
@@ -1935,6 +2253,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "インストール開始ã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr "変更をä¿å­˜"
@@ -1977,12 +2298,18 @@ msgstr "表示"
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr "Google Kubernetes Engine 上㮠Kubernetes クラスターを作æˆä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "%{title} ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -1998,6 +2325,18 @@ msgstr "Kubernetes クラスターを切り替ãˆ"
msgid "ClusterIntegration|Token"
msgstr "トークン"
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr "プロジェクトã®è«‹æ±‚ステータスを検証ã—ã¦ã„ã¾ã™"
@@ -2010,6 +2349,9 @@ msgstr "ã“ã®ãƒ—ロジェクト㫠Kubernetes クラスターを関連付ã‘ã‚‹
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "アカウント㫠%{link_to_kubernetes_engine} ãŒå¿…è¦ã§ã™ã€‚"
@@ -2037,9 +2379,12 @@ msgstr "æ­£ã—ã設定ã•ã‚Œã¦ã„ã‚‹"
msgid "ClusterIntegration|sign up"
msgstr "æ–°è¦ç™»éŒ²"
-msgid "Code owners"
+msgid "Code"
msgstr ""
+msgid "Code owners"
+msgstr "コードオーナー"
+
msgid "Cohorts"
msgstr ""
@@ -2049,7 +2394,16 @@ msgstr "折りãŸãŸã‚€"
msgid "Collapse sidebar"
msgstr "サイドãƒãƒ¼ã‚’éš ã™"
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
+msgstr "コメント"
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
msgstr ""
msgid "Comment & resolve discussion"
@@ -2059,7 +2413,7 @@ msgid "Comment & unresolve discussion"
msgstr "ã“ã®æ¤œè¨Žã«ã‚³ãƒ¡ãƒ³ãƒˆã—未解決ã«ã™ã‚‹"
msgid "Comment form position"
-msgstr ""
+msgstr "コメントフォームã®ä½ç½®"
msgid "Comments"
msgstr "コメント"
@@ -2068,13 +2422,15 @@ msgid "Commit"
msgid_plural "Commits"
msgstr[0] "コミット"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] "コミット (%{commit_count})"
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "コミットメッセージ"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "ç›´è¿‘30コミットã®æ‰€è¦æ™‚é–“(分)"
@@ -2138,6 +2494,9 @@ msgstr "Git リビジョンを比較"
msgid "Compare Revisions"
msgstr "リビジョンを比較"
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr "最後ã®ã‚³ãƒŸãƒƒãƒˆã¨å¤‰æ›´ã‚’比較"
@@ -2165,10 +2524,16 @@ msgstr "éžå…¬é–‹"
msgid "Confidentiality"
msgstr "機密性"
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr "Gitaly ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã‚’設定ã—ã¾ã™ã€‚"
msgid "Configure Tracing"
+msgstr "トレースã®æ§‹æˆ"
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2199,11 +2564,14 @@ msgid "Connect repositories from GitHub"
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 "Connecting..."
msgstr "接続ã—ã¦ã„ã¾ã™..."
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr "コンテナレジストリ"
@@ -2252,6 +2620,9 @@ msgstr "GitLabã¨çµ±åˆã•ã‚ŒãŸã‚³ãƒ³ãƒ†ãƒŠãƒ¬ã‚¸ã‚¹ãƒˆãƒªã§ã€å…¨ã¦ã®ãƒ—ロ
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "レジストリイメージã¸ã®èª­ã¿å–り専用アクセスã®ãŸã‚ã« %{deploy_token} を使用ã§ãã¾ã™ã€‚"
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr "続行"
@@ -2267,8 +2638,8 @@ msgstr "GitLab ã«è²¢çŒ®ã™ã‚‹"
msgid "Contribution"
msgstr "貢献度"
-msgid "Contribution guide"
-msgstr "貢献者å‘ã‘ガイド"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr ""
@@ -2303,19 +2674,25 @@ msgstr "ã“ã®ã‚»ã‚«ãƒ³ãƒ€ãƒªãƒŽãƒ¼ãƒ‰ã®ãƒªãƒã‚¸ãƒˆãƒªãƒãƒƒã‚¯ãƒ•ã‚£ãƒ«ã®æœ€
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr "ã“ã® Geo ノードã®æ¤œè¨¼æ“作ã®æœ€å¤§åŒæ™‚実行数を制御ã™ã‚‹"
-msgid "ConvDev Index"
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
msgstr ""
-msgid "Copy %{protocol} clone URL"
-msgstr ""
+msgid "ConvDev Index"
+msgstr "ConvDev インデックス"
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr "%{protocol} クローン URL をコピー"
+
msgid "Copy ID to clipboard"
-msgstr ""
+msgstr "クリップボード㫠ID をコピー"
msgid "Copy SSH clone URL"
+msgstr "SSH 用クローン URL をコピー"
+
+msgid "Copy SSH public key"
msgstr ""
msgid "Copy SSH public key to clipboard"
@@ -2342,9 +2719,6 @@ msgstr "å—信用メールアドレスをクリップボードã«ã‚³ãƒ”ーã—ã¾
msgid "Copy link"
msgstr "リンクをコピー"
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr "クリップボードã¸ã‚³ãƒ”ー"
@@ -2366,6 +2740,9 @@ msgstr "作æˆ"
msgid "Create New Directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作æˆ"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr "æ–°ã—ã„ブランãƒã‚’作æˆ"
@@ -2373,6 +2750,9 @@ msgid "Create a new branch and merge request"
msgstr "ブランãƒã®æ–°è¦ä½œæˆã¨ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "Create a new issue"
+msgstr "課題ã®æ–°è¦ä½œæˆ"
+
+msgid "Create a new repository"
msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
@@ -2414,6 +2794,9 @@ msgstr "マージリクエストを作æˆ"
msgid "Create merge request and branch"
msgstr "マージリクエストã¨ãƒ–ランãƒã‚’作æˆ"
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "æ–°ã—ã„ブランãƒã‚’作æˆ"
@@ -2436,7 +2819,7 @@ msgid "Create project label"
msgstr "プロジェクトラベルを作æˆ"
msgid "Create your first page"
-msgstr ""
+msgstr "最åˆã®ãƒšãƒ¼ã‚¸ã‚’作æˆã™ã‚‹"
msgid "CreateTag|Tag"
msgstr "ã‚¿ã‚°"
@@ -2454,7 +2837,7 @@ msgid "Created by me"
msgstr "自分ãŒä½œæˆ"
msgid "Created on"
-msgstr ""
+msgstr "作æˆæ—¥æ™‚"
msgid "Created on:"
msgstr "作æˆæ—¥æ™‚:"
@@ -2480,11 +2863,8 @@ msgstr "プロフィール"
msgid "CurrentUser|Settings"
msgstr "設定"
-msgid "Custom"
-msgstr "カスタム"
-
msgid "Custom CI config path"
-msgstr ""
+msgstr "カスタム CI config パス"
msgid "Custom hostname (for private commit emails)"
msgstr ""
@@ -2498,6 +2878,9 @@ msgstr "\"カスタム\" ã®é€šçŸ¥ãƒ¬ãƒ™ãƒ«ã®åŸºæœ¬ã¯ \"å‚加\" ã¨åŒã˜ã§ã
msgid "Custom project templates"
msgstr "カスタムプロジェクトテンプレート"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr "カスタムカラー"
@@ -2507,6 +2890,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr "Runner トークンã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã€ãƒ‘イプラインã®è¨­å®šã‚’カスタマイズã€ãã—ã¦ãƒ‘イプラインã®çŠ¶æ…‹ã¨ã‚«ãƒãƒ¬ãƒƒã‚¸ãƒ¬ãƒãƒ¼ãƒˆã‚’閲覧ã—ã¾ã™ã€‚"
@@ -2514,7 +2903,7 @@ msgid "Cycle Analytics"
msgstr "サイクル分æž"
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
-msgstr ""
+msgstr "サイクル分æžã«ã‚ˆã‚Šã€ã‚ãªãŸã®ãƒ—ロジェクトãŒã‚¢ã‚¤ãƒ‡ã‚£ã‚¢ã®æ®µéšŽã‹ã‚‰ãƒ—ロダクション環境ã«ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã‚‹ã¾ã§ã©ã‚Œãらã„時間ãŒã‹ã‹ã£ãŸã‹ä¿¯çž°ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "CycleAnalyticsStage|Code"
msgstr "コード"
@@ -2537,6 +2926,9 @@ msgstr "ステージング"
msgid "CycleAnalyticsStage|Test"
msgstr "テスト"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr "ダッシュボード"
@@ -2546,6 +2938,9 @@ msgstr "ã™ã¹ã¦"
msgid "DashboardProjects|Personal"
msgstr "個人"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2558,24 +2953,36 @@ msgstr "12月"
msgid "December"
msgstr "12月"
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr "辞退ã—ã¦ã‚µã‚¤ãƒ³ã‚¢ã‚¦ãƒˆ"
msgid "Default Branch"
-msgstr ""
+msgstr "デフォルトブランãƒ"
msgid "Default classification label"
msgstr "デフォルト分類ラベル"
-msgid "Default: Directly import the Google Code email address or username"
+msgid "Default first day of the week"
msgstr ""
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr "デフォルト:Google コードã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¾ãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼åを直接インãƒãƒ¼ãƒˆã™ã‚‹"
+
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Cron 構文ã§ã‚«ã‚¹ã‚¿ãƒ ãªãƒ‘ターンを指定ã™ã‚‹"
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2601,11 +3008,17 @@ msgid "Delete Snippet"
msgstr "スニペットを削除"
msgid "Delete comment"
-msgstr ""
+msgstr "コメントを削除"
msgid "Delete list"
msgstr "リストを削除ã™ã‚‹"
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr "削除完了"
@@ -2739,6 +3152,9 @@ msgstr "æ–°è¦ãƒ‡ãƒ—ロイトークン"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "æ–°ã—ã„プロジェクトデプロイトークンãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2766,6 +3182,9 @@ msgstr "破棄"
msgid "Details"
msgstr "詳細"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2782,7 +3201,7 @@ msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "diff 行をå–得中ã«ä½•ã‹å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Direction"
-msgstr ""
+msgstr "æ–¹å‘"
msgid "Directory name"
msgstr "ディレクトリå"
@@ -2796,9 +3215,15 @@ msgstr "ã“ã®ãƒ—ロジェクトã§ã¯ç„¡åŠ¹ã«ã™ã‚‹"
msgid "Disable group Runners"
msgstr "グループ Runner を無効ã«ã™ã‚‹"
-msgid "Discard"
+msgid "Disable shared Runners"
msgstr ""
+msgid "Disabled"
+msgstr ""
+
+msgid "Discard"
+msgstr "破棄"
+
msgid "Discard all changes"
msgstr ""
@@ -2817,15 +3242,24 @@ msgstr "下書ãを破棄"
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
-msgstr "GitLab Geo ã«ã¤ã„ã¦"
+msgid "Discover GitLab Geo"
+msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr "プロジェクトã€ã‚°ãƒ«ãƒ¼ãƒ—ã€ã‚¹ãƒ‹ãƒšãƒƒãƒˆã‚’発見ã™ã‚‹ã€‚ã‚ãªãŸã®ãƒ—ロジェクトを他ã®äººã¨å…±æœ‰ã™ã‚‹"
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
msgstr ""
msgid "Dismiss"
msgstr "解除"
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "サイクル分æžã®ç´¹ä»‹ã‚’é–‰ã˜ã‚‹"
@@ -2836,7 +3270,7 @@ msgid "Dismiss trial promotion"
msgstr ""
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
-msgstr ""
+msgstr "Google コードã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ GitLab ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹æ–¹æ³•ã‚’カスタマイズã—ã¾ã™ã‹ï¼Ÿ"
msgid "Documentation for popular identity providers"
msgstr "一般的㪠ID プロãƒã‚¤ãƒ€ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
@@ -2853,6 +3287,12 @@ msgstr "完了"
msgid "Download"
msgstr "ダウンロード"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "tarå½¢å¼ã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰"
@@ -2877,6 +3317,9 @@ msgstr "プレーン差分"
msgid "DownloadSource|Download"
msgstr "ダウンロード"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr "イマイãƒ"
@@ -2892,9 +3335,15 @@ msgstr "å„ Runner ã¯æ¬¡ã®ã„ãšã‚Œã‹ã®çŠ¶æ…‹ã‚’ã¨ã‚Šã¾ã™:"
msgid "Edit"
msgstr "編集"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr "ラベルã®ç·¨é›†"
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "パイプラインスケジュール %{id} を編集"
@@ -2904,6 +3353,12 @@ msgstr "スニペットを編集"
msgid "Edit application"
msgstr "アプリケーションã®ç·¨é›†"
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr "エディターã§ãƒ•ã‚¡ã‚¤ãƒ«ã‚’編集ã—ã€ã“ã“ã§å¤‰æ›´ã‚’コミットã—ã¾ã™"
@@ -2913,6 +3368,9 @@ msgstr "グループを編集:%{group_name}"
msgid "Edit identity for %{user_name}"
msgstr "%{user_name} ã® ID を編集ã™ã‚‹"
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr "Elasticsearch"
@@ -2931,6 +3389,9 @@ msgstr "メール"
msgid "Embed"
msgstr "埋ã‚è¾¼ã¿"
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr "有効化ã™ã‚‹"
@@ -2938,7 +3399,7 @@ msgid "Enable Auto DevOps"
msgstr "Auto DevOps を有効ã«ã™ã‚‹"
msgid "Enable Pseudonymizer data collection"
-msgstr ""
+msgstr "匿å化データã®åŽé›†ã‚’有効ã«ã—ã¾ã™"
msgid "Enable SAML authentication for this group"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã® SAML èªè¨¼ã‚’有効ã«ã™ã‚‹"
@@ -2955,6 +3416,9 @@ msgstr "Prometheus ã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’有効ã«ã—ã¦è¨­å®šã™ã‚‹ã€‚"
msgid "Enable classification control using an external service"
msgstr "外部サービスを使用ã—ã¦ã€åˆ†é¡žåˆ¶å¾¡ã‚’有効ã«ã™ã‚‹ã€‚"
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr "ã“ã®ãƒ—ロジェクトã§ã¯æœ‰åŠ¹ã«ã™ã‚‹"
@@ -2970,12 +3434,21 @@ msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒã‚§ãƒƒã‚¯ã¨ä½¿ç”¨çŠ¶æ³ã® ping を有効ã«ã™ã‚‹ã€‚
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "reCAPTCHA ã¾ãŸã¯ Akismet ã®æœ‰åŠ¹ã€ãŠã‚ˆã³ IP 制é™ã‚’設定ã™ã‚‹ã€‚"
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr "指定グループã®ãƒ‘フォーマンスãƒãƒ¼ã‚’有効ã«ã™ã‚‹ã€‚"
-msgid "Enable usage ping"
+msgid "Enable two-factor authentication"
msgstr ""
+msgid "Enable usage ping"
+msgstr "利用状æ³ã®é€ä¿¡ã‚’有効ã«ã™ã‚‹"
+
msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
msgstr ""
@@ -2985,9 +3458,15 @@ msgstr "有効"
msgid "Ends at (UTC)"
msgstr "終了時刻 (UTC)"
-msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgid "Enforce SSO-only authentication for this group"
msgstr ""
+msgid "Enforced SSO"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr "ã‚ãªãŸã® Bitbucket Server ã® URL ã¨ä»¥ä¸‹ã®å€‹äººã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’入力ã—ã¦ãã ã•ã„"
+
msgid "Enter the issue description"
msgstr "課題ã®èª¬æ˜Žã‚’入力ã—ã¦ãã ã•ã„"
@@ -3000,9 +3479,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr "環境"
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "環境をå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3073,26 +3570,26 @@ msgid "Environments|Show all"
msgstr "全件を表示"
msgid "Environments|Stop"
-msgstr ""
+msgstr "åœæ­¢"
msgid "Environments|Stop environment"
+msgstr "環境ã®åœæ­¢"
+
+msgid "Environments|Stopping"
msgstr ""
msgid "Environments|Updated"
msgstr "更新済ã¿"
msgid "Environments|You don't have any environments right now"
-msgstr ""
+msgstr "ã¾ã ç’°å¢ƒãŒã‚ã‚Šã¾ã›ã‚“。"
msgid "Environments|protected"
-msgstr ""
+msgstr "ä¿è­·æ¸ˆã¿"
msgid "Epic"
msgstr "エピック"
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr "エピック"
@@ -3102,14 +3599,14 @@ msgstr "エピック ロードマップ"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "エピックを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトã®ãƒãƒ¼ãƒˆãƒ•ã‚©ãƒªã‚ªã‚’より効率的ã‹ã¤å°‘ãªã„労力ã§ç®¡ç†ã§ãã¾ã™"
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
-msgstr ""
+msgstr "詳ã—ã„情報"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
@@ -3121,20 +3618,26 @@ msgid "Epics|due"
msgstr ""
msgid "Epics|start"
-msgstr ""
+msgstr "開始"
msgid "Error"
-msgstr ""
+msgstr "エラー"
msgid "Error Reporting and Logging"
msgstr "エラー報告ã¨ãƒ­ã‚°"
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr "エピックã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼"
-msgid "Error fetching contributors data."
+msgid "Error deleting %{issuableType}"
msgstr ""
+msgid "Error fetching contributors data."
+msgstr "貢献者データã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
msgid "Error fetching labels."
msgstr "ラベルã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3174,9 +3677,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr "通知購読ã®åˆ‡ã‚Šæ›¿ãˆã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr "ラベルã®æ›´æ–°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr "ã™ã¹ã¦ã® TODO ã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’更新中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3186,6 +3695,12 @@ msgstr "TODO ã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’更新中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr "見ç©"
@@ -3207,6 +3722,12 @@ msgstr "プッシュイベントã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
msgid "EventFilterBy|Filter by team"
msgstr "ãƒãƒ¼ãƒ ã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "毎日 (åˆå‰4:00)"
@@ -3216,9 +3737,39 @@ msgstr "毎月 (1æ—¥ã®åˆå‰4:00)"
msgid "Every week (Sundays at 4:00am)"
msgstr "毎週 (日曜日ã®åˆå‰4:00)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr "展開"
@@ -3229,6 +3780,12 @@ msgid "Expand sidebar"
msgstr "サイドãƒãƒ¼ã‚’é–‹ã"
msgid "Expiration date"
+msgstr "有効期é™"
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
msgstr ""
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
@@ -3252,14 +3809,26 @@ msgstr "プロジェクトを探ã™"
msgid "Explore public groups"
msgstr "公開グループを検索"
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
+msgstr "外部分類èªè¨¼ãƒãƒªã‚·ãƒ¼"
+
+msgid "External URL"
msgstr ""
-msgid "External authentication"
+msgid "External Wiki"
msgstr ""
+msgid "External authentication"
+msgstr "外部èªè¨¼"
+
msgid "External authorization denied access to this project"
-msgstr ""
+msgstr "ã“ã®ãƒ—ロジェクトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’æ‹’å¦ã™ã‚‹å¤–部èªè¨¼"
msgid "External authorization request timeout"
msgstr "外部èªè¨¼å‡¦ç†ãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸ"
@@ -3294,6 +3863,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "ボードã®èª²é¡Œã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -3303,28 +3875,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "パイプラインスケジュールを削除ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr "課題ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr "失敗"
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr "API URL"
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3336,47 +3920,68 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
msgstr ""
-msgid "FeatureFlags|Description"
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
+msgid "FeatureFlags|Description"
+msgstr "説明"
+
msgid "FeatureFlags|Edit %{feature_flag_name}"
-msgstr ""
+msgstr "%{feature_flag_name} を編集"
msgid "FeatureFlags|Edit Feature Flag"
+msgstr "機能フラグを編集"
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
msgstr ""
msgid "FeatureFlags|Feature Flag"
+msgstr "機能フラグ"
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
+msgstr "インスタンス ID"
+
+msgid "FeatureFlags|Loading Feature Flags"
msgstr ""
-msgid "FeatureFlags|More information"
+msgid "FeatureFlags|More Information"
msgstr ""
+msgid "FeatureFlags|More information"
+msgstr "詳細情報"
+
msgid "FeatureFlags|Name"
-msgstr ""
+msgstr "åå‰"
msgid "FeatureFlags|New"
msgstr ""
@@ -3385,9 +3990,24 @@ msgid "FeatureFlags|New Feature Flag"
msgstr ""
msgid "FeatureFlags|Save changes"
-msgstr ""
+msgstr "変更をä¿å­˜"
msgid "FeatureFlags|Status"
+msgstr "ステータス"
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
msgid "Feb"
@@ -3399,15 +4019,34 @@ msgstr "2月"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã®é …ç›®ã¯ç·¨é›†ã§ããªã„設定ã§ã™ã€‚次㮠Kubernetes クラスターを設定ã§ãã¾ã™ã€‚"
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
+msgstr "ファイルテンプレート"
+
+msgid "File upload error."
msgstr ""
msgid "Files"
msgstr "ファイル"
-msgid "Files (%{human_size})"
-msgstr "ファイル (%{human_size})"
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "下記項目ã«å¿…è¦äº‹é …を入力ã—〠<strong>%{enable_label}</strong>をオンã«ã—ã¦ã€ <strong>%{save_changes}</strong>を押ã—ã¦ãã ã•ã„。"
@@ -3423,12 +4062,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr "コミットメッセージã§çµžã‚Šè¾¼ã¿"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "パスã§æ¤œç´¢"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "ファイルを検索"
@@ -3441,12 +4098,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr "完了"
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "åˆå›ž"
@@ -3466,19 +4129,19 @@ msgid "Fixed:"
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 ã® URL"
msgid "FogBugz import"
-msgstr ""
+msgstr "FogBugz ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Follow the steps below to export your Google Code project data."
msgstr ""
@@ -3492,6 +4155,9 @@ msgstr "フッターメッセージ"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3516,6 +4182,9 @@ msgstr "%{project_name} ã‹ã‚‰ãƒ•ã‚©ãƒ¼ã‚¯ (削除済)"
msgid "Forking in progress"
msgstr "フォーク中ã§ã™"
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "フォーマット"
@@ -3529,19 +4198,19 @@ msgid "From %{provider_title}"
msgstr "%{provider_title}ã‹ã‚‰"
msgid "From Bitbucket"
-msgstr ""
+msgstr "Bitbucket ã‹ã‚‰"
msgid "From Bitbucket Server"
-msgstr ""
+msgstr "Bitbucket Server ã‹ã‚‰"
msgid "From FogBugz"
-msgstr ""
+msgstr "FogBugz ã‹ã‚‰"
msgid "From GitLab.com"
-msgstr ""
+msgstr "GitLab.com ã‹ã‚‰"
msgid "From Google Code"
-msgstr ""
+msgstr "Google コードã‹ã‚‰"
msgid "From issue creation until deploy to production"
msgstr "課題ãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§"
@@ -3550,7 +4219,7 @@ msgid "From merge request merge until deploy to production"
msgstr "マージリクエストãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§"
msgid "From milestones:"
-msgstr ""
+msgstr "マイルストーンã‹ã‚‰:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Kubernetes クラスターã®è©³ç´°ç”»é¢ã‚’介ã—ã¦ã€ã‚¢ãƒ—リケーションリストã‹ã‚‰ Runner をインストールã—ã¾ã™ã€‚"
@@ -3562,16 +4231,19 @@ msgid "General"
msgstr "一般"
msgid "General pipelines"
-msgstr ""
+msgstr "一般ã®ãƒ‘イプライン"
msgid "Generate a default set of labels"
msgstr "åˆæœŸè¨­å®šãƒ©ãƒ™ãƒ«ã‚»ãƒƒãƒˆã‚’生æˆã™ã‚‹"
-msgid "Geo"
+msgid "Generate key"
msgstr ""
+msgid "Geo"
+msgstr "Geo"
+
msgid "Geo Nodes"
-msgstr ""
+msgstr "Geo ノード"
msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
msgstr "Geo ã¯ã€GitLab インスタンスを他ã®åœ°ç†çš„ãªå ´æ‰€ã«è¤‡è£½ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -3583,16 +4255,16 @@ msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an
msgstr "ノードãŒé…延ã€éŽè² è·ãŒã‹ã‹ã£ã¦ã„ã‚‹ã€ã¾ãŸã¯åœæ­¢ã‹ã‚‰ã®å›žå¾©ç›´å¾Œã§ã™ã€‚"
msgid "GeoNodes|Checksummed"
-msgstr ""
+msgstr "ãƒã‚§ãƒƒã‚¯ã‚µãƒ "
msgid "GeoNodes|Data is out of date from %{timeago}"
-msgstr ""
+msgstr "データ㯠%{timeago} ã‹ã‚‰å¤ããªã£ã¦ã„ã¾ã™"
msgid "GeoNodes|Data replication lag"
-msgstr ""
+msgstr "データ レプリケーションã®é…延"
msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
-msgstr ""
+msgstr "ノードを無効ã«ã™ã‚‹ã¨åŒæœŸå‡¦ç†ã‚‚åœæ­¢ã—ã¾ã™ã€‚本当ã«ç„¡åŠ¹ã«ã—ã¾ã™ã‹ï¼Ÿ"
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "プライマリストレージ構æˆã¨ä¸€è‡´ã—ã¾ã›ã‚“"
@@ -3613,16 +4285,16 @@ msgid "GeoNodes|Health status"
msgstr ""
msgid "GeoNodes|Last event ID processed by cursor"
-msgstr ""
+msgstr "カーソルã§å‡¦ç†ã•ã‚ŒãŸæœ€çµ‚イベント ID"
msgid "GeoNodes|Last event ID seen from primary"
-msgstr ""
+msgstr "プライマリãŒå–å¾—ã—ãŸæœ€çµ‚イベント ID"
msgid "GeoNodes|Learn more about Repository checksum progress"
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªãƒã‚§ãƒƒã‚¯ã‚µãƒ é€²æ—ã®è©³ç´°"
msgid "GeoNodes|Learn more about Repository verification"
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªæ¤œè¨¼ã®è©³ç´°"
msgid "GeoNodes|Learn more about Wiki checksum progress"
msgstr "Wiki ã®ãƒã‚§ãƒƒã‚¯ã‚µãƒ ã®é€²æ—ã®è©³ç´°"
@@ -3657,7 +4329,10 @@ msgstr "ãƒã‚§ãƒƒã‚¯ã‚µãƒ ãªã—"
msgid "GeoNodes|Out of sync"
msgstr "åŒæœŸå¯¾è±¡å¤–"
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3732,6 +4407,9 @@ msgstr "セカンダリノードã®å¯¾å¿œ Wiki ã¨ã®ãƒã‚§ãƒƒã‚¯ã‚µãƒ ãŒæ¤œè¨¼
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr "安全ã§ãªã„ HTTP 接続を使用ã—㦠Geo ノードを設定ã—ã¾ã—ãŸã€‚HTTPS 通信ã®ä½¿ç”¨ã‚’推奨ã—ã¾ã™ã€‚"
@@ -3745,7 +4423,7 @@ msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
msgid "Geo|All"
-msgstr ""
+msgstr "ã™ã¹ã¦"
msgid "Geo|All projects"
msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクト"
@@ -3757,13 +4435,13 @@ msgid "Geo|All projects are being scheduled for re-sync"
msgstr ""
msgid "Geo|Batch operations"
-msgstr ""
+msgstr "ãƒãƒƒãƒå‡¦ç†"
msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
-msgstr ""
+msgstr "失敗"
msgid "Geo|File sync capacity"
msgstr "ファイルåŒæœŸå®¹é‡"
@@ -3777,6 +4455,9 @@ msgstr "åŒæœŸã‚°ãƒ«ãƒ¼ãƒ—"
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3813,6 +4494,9 @@ msgstr "特定グループã®ãƒ—ロジェクト"
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3835,13 +4519,13 @@ msgid "Geo|Resync all projects"
msgstr ""
msgid "Geo|Retry count"
-msgstr ""
+msgstr "リトライ回数"
msgid "Geo|Select groups to replicate."
msgstr "é¸æŠžã—ãŸã‚°ãƒ«ãƒ¼ãƒ—を複製ã™ã‚‹"
msgid "Geo|Shards to synchronize"
-msgstr ""
+msgstr "シャードã®åŒæœŸ"
msgid "Geo|Status"
msgstr ""
@@ -3891,9 +4575,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr "Git"
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr "Git リãƒã‚¸ãƒˆãƒª URL"
@@ -3921,12 +4614,18 @@ msgstr "GitLab グループ Runner ã¯ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—内ã®å…¨ã¦ã®ãƒ—ロジ
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr "GitLab ユーザー"
-msgid "GitLab project export"
+msgid "GitLab metadata URL"
msgstr ""
+msgid "GitLab project export"
+msgstr "GitLab プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
+
msgid "GitLab single sign on URL"
msgstr "GitLab シングルサインオン㮠URL"
@@ -3934,10 +4633,10 @@ msgid "GitLab will run a background job that will produce pseudonymized CSVs of
msgstr ""
msgid "GitLab.com import"
-msgstr ""
+msgstr "GitLab.com インãƒãƒ¼ãƒˆ"
msgid "GitLab’s issue tracker"
-msgstr ""
+msgstr "GitLab ã®èª²é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼"
msgid "Gitaly"
msgstr "Gitaly"
@@ -3949,9 +4648,12 @@ msgid "Gitaly|Address"
msgstr "アドレス"
msgid "Gitea Host URL"
-msgstr ""
+msgstr "Gitea ホスト㮠URL"
msgid "Gitea Import"
+msgstr "Gitea インãƒãƒ¼ãƒˆ"
+
+msgid "Given access %{time_ago}"
msgstr ""
msgid "Go Back"
@@ -3967,7 +4669,7 @@ msgid "Go to %{link_to_google_takeout}."
msgstr ""
msgid "Google Code import"
-msgstr ""
+msgstr "Google コードã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Google Takeout"
msgstr ""
@@ -3978,6 +4680,9 @@ msgstr "Google èªè¨¼ã¯ %{link_to_documentation} ã§ã¯ã‚ã‚Šã¾ã›ã‚“。ã“ã®
msgid "Got it!"
msgstr "入手ã—ã¾ã—ょã†ï¼"
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr "グラフ"
@@ -3988,7 +4693,7 @@ msgid "Group CI/CD settings"
msgstr "CI/CD グループ設定"
msgid "Group Git LFS status:"
-msgstr ""
+msgstr "グループ Git LFS ã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹:"
msgid "Group ID"
msgstr "グループ ID"
@@ -4000,13 +4705,13 @@ msgid "Group SAML must be enabled to test"
msgstr ""
msgid "Group URL"
-msgstr ""
+msgstr "グループ URL"
msgid "Group avatar"
-msgstr ""
+msgstr "グループアãƒã‚¿ãƒ¼"
msgid "Group description"
-msgstr ""
+msgstr "グループã®èª¬æ˜Ž"
msgid "Group description (optional)"
msgstr ""
@@ -4021,6 +4726,12 @@ msgid "Group maintainers can register group runners in the %{link}"
msgstr "グループ Maintainer 㯠%{link} ã§ã‚°ãƒ«ãƒ¼ãƒ— Runner を登録ã§ãã¾ã™ã€‚"
msgid "Group name"
+msgstr "グループå"
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
msgstr ""
msgid "Group: %{group_name}"
@@ -4029,9 +4740,6 @@ msgstr "グループ:%{group_name}"
msgid "GroupRoadmap|From %{dateWord}"
msgstr "%{dateWord} ã‹ã‚‰"
-msgid "GroupRoadmap|Loading roadmap"
-msgstr "ロードマップã®èª­ã¿è¾¼ã¿ä¸­"
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "エピックã®èª­ã¿è¾¼ã¿ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -4041,39 +4749,36 @@ msgstr "申ã—訳ã‚ã‚Šã¾ã›ã‚“ã€æ¤œç´¢ã«ãƒžãƒƒãƒã™ã‚‹ã‚¨ãƒ”ックã¯ã‚ã‚Š
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "ロードマップã¯æ™‚é–“ã®çµŒéŽã¨ã¨ã‚‚ã«ã‚¨ãƒ”ックã®é€²è¡Œã‚’表示ã—ã¾ã™"
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "検索対象を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã™ã‚‹ã‹å‰Šé™¤ã—ã¦ãã ã•ã„。月表示ã§ã¯ã€å…ˆæœˆã€ä»Šæœˆã‚‚ã—ãã¯5ヶ月先ã¾ã§ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ &ndash; %{startDate} 〜 %{endDate}"
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "検索対象を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã™ã‚‹ã‹å‰Šé™¤ã—ã¦ãã ã•ã„。四åŠæœŸè¡¨ç¤ºã§ã¯ã€å‰å››åŠæœŸã€å½“å››åŠæœŸã‚‚ã—ãã¯4ã¤å…ˆã®å››åŠæœŸã¾ã§ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ &ndash; %{startDate} 〜 %{endDate}"
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "検索対象を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã™ã‚‹ã‹å‰Šé™¤ã—ã¦ãã ã•ã„。週表示ã§ã¯ã€å…ˆé€±ã€ä»Šé€±ã‚‚ã—ãã¯4週先ã¾ã§ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ &ndash; %{startDate} 〜 %{endDate}"
-
msgid "GroupRoadmap|Until %{dateWord}"
msgstr "%{dateWord} ã¾ã§"
msgid "GroupSettings|Badges"
+msgstr "ãƒãƒƒã‚¸"
+
+msgid "GroupSettings|Custom project templates"
msgstr ""
msgid "GroupSettings|Customize your group badges."
-msgstr ""
+msgstr "グループãƒãƒƒã‚¸ã®ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚º"
msgid "GroupSettings|Learn more about badges."
+msgstr "ãƒãƒƒã‚¸ã®è©³ç´°ã€‚"
+
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "%{group} 内ã®ãƒ—ロジェクトを他ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¨å…±æœ‰ã—ãªã„よã†ã«ã™ã‚‹"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "ã“ã®è¨­å®šã¯ %{ancestor_group} ã«é©ç”¨ã•ã‚Œã€ã‚µãƒ–グループã§ä¸Šæ›¸ãã•ã‚Œã¾ã™ã€‚"
@@ -4087,7 +4792,7 @@ msgid "GroupSettings|This setting will be applied to all subgroups unless overri
msgstr "ã“ã®è¨­å®šã¯ã‚°ãƒ«ãƒ¼ãƒ—オーナーã«ã‚ˆã£ã¦ä¸Šæ›¸ãã•ã‚Œãªã„é™ã‚Šã€ã™ã¹ã¦ã®ã‚µãƒ–グループã«é©ç”¨ã•ã‚Œã¾ã™ã€‚プロジェクトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒæ—¢ã«ã‚るグループã¯ã€æ‰‹å‹•ã§å‰Šé™¤ã—ãªã„é™ã‚Šå¼•ã続ãアクセスã§ãã¾ã™ã€‚"
msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
-msgstr ""
+msgstr "親グループã®ã€Œã‚°ãƒ«ãƒ¼ãƒ—ã¨ã®ãƒ­ãƒƒã‚¯ã‚’共有ã€ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å ´åˆã€è¦ªã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ªãƒ¼ãƒŠãƒ¼ä»¥å¤–ã¯ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
msgstr "グループã®ãƒ­ãƒƒã‚¯ã‚’ %{ancestor_group_name} ã®å…±æœ‰ã‹ã‚‰å‰Šé™¤"
@@ -4098,9 +4803,12 @@ msgstr "グループ"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "グループã¯ã€%{subgroup_docs_link_start}サブグループ%{subgroup_docs_link_end}を作æˆã™ã‚‹ã“ã¨ã§ãƒã‚¹ãƒˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
-msgid "GroupsDropdown|Frequently visited"
+msgid "Groups with access to <strong>%{project_name}</strong>"
msgstr ""
+msgid "GroupsDropdown|Frequently visited"
+msgstr "よã使ã†ãƒ—ロジェクト"
+
msgid "GroupsDropdown|Groups you visit often will appear here"
msgstr "よã使ã†ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã“ã“ã«è¡¨ç¤ºã•ã‚Œã¾ã™"
@@ -4197,6 +4905,9 @@ msgstr "ヘルプページテキストã¨ã‚µãƒãƒ¼ãƒˆãƒšãƒ¼ã‚¸URL。"
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4207,8 +4918,8 @@ msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éžè¡¨ç¤º"
-msgid "Hide whitespace changes"
-msgstr "空白ã®å¤‰æ›´ã‚’éš ã™"
+msgid "Hide values"
+msgstr ""
msgid "History"
msgstr "履歴"
@@ -4216,6 +4927,9 @@ msgstr "履歴"
msgid "Housekeeping successfully started"
msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã¯æ­£å¸¸ã«èµ·å‹•ã—ã¾ã—ãŸã€‚"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr "%{terms_link} ã«åŒæ„ã™ã‚‹"
@@ -4271,6 +4985,9 @@ msgid "Identities"
msgstr "ID"
msgid "Identity provider single sign on URL"
+msgstr "アイデンティティプロãƒã‚¤ãƒ€ã®ã‚·ãƒ³ã‚°ãƒ«ã‚µã‚¤ãƒ³ã‚ªãƒ³ URL"
+
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "If 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."
@@ -4292,7 +5009,7 @@ msgid "If you already have files you can push them using the %{link_to_cli} belo
msgstr "ã™ã§ã«ãƒ•ã‚¡ã‚¤ãƒ«ãŒå­˜åœ¨ã™ã‚‹ã¨ãã¯ã€æ¬¡ã® %{link_to_cli} を使用ã—ã¦ãƒ•ã‚¡ã‚¤ãƒ«ã‚’プッシュã§ãã¾ã™ã€‚"
msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr ""
+msgstr "HTTP リãƒã‚¸ãƒˆãƒªãŒå…¬é–‹è¨­å®šã•ã‚Œã¦ã„ãªã„ã¨ãã¯ã€èªè¨¼æƒ…報を URL ã«è¿½åŠ ã—ã¦ãã ã•ã„(URL: <code>https://username:password@gitlab.company.com/group/project.git</code>)。"
msgid "ImageDiffViewer|2-up"
msgstr "2-up"
@@ -4303,81 +5020,117 @@ msgstr "オニオンスキン"
msgid "ImageDiffViewer|Swipe"
msgstr "スワイプ"
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr "インãƒãƒ¼ãƒˆ"
-msgid "Import Projects from Gitea"
+msgid "Import CSV"
msgstr ""
+msgid "Import Projects from Gitea"
+msgstr "Gitea ã‹ã‚‰ãƒ—ロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
msgid "Import all compatible projects"
msgstr ""
msgid "Import all projects"
-msgstr ""
+msgstr "全プロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Import all repositories"
msgstr "ã™ã¹ã¦ã®ãƒªãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆ"
msgid "Import an exported GitLab project"
-msgstr ""
+msgstr "エクスãƒãƒ¼ãƒˆã—㟠GItLab プロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Import in progress"
msgstr "インãƒãƒ¼ãƒˆä¸­ã§ã™"
-msgid "Import multiple repositories by uploading a manifest file."
+msgid "Import issues"
msgstr ""
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr "manifest ファイルã®ã‚¢ãƒƒãƒ—ロードã«ã‚ˆã‚‹è¤‡æ•°ãƒªãƒã‚¸ãƒˆãƒªã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
msgid "Import project"
+msgstr "プロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
+msgid "Import project members"
msgstr ""
msgid "Import projects from Bitbucket"
msgstr ""
msgid "Import projects from Bitbucket Server"
-msgstr ""
+msgstr "Bitbucket Server ã‹ã‚‰ãƒ—ロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Import projects from FogBugz"
-msgstr ""
+msgstr "FogBugz ã‹ã‚‰ãƒ—ロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Import projects from GitLab.com"
-msgstr ""
+msgstr "GitLab.com ã‹ã‚‰ãƒ—ロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Import projects from Google Code"
-msgstr ""
+msgstr "Google コードã‹ã‚‰ãƒ—ロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Import repositories from Bitbucket Server"
-msgstr ""
+msgstr "Bitbucket Server ã‹ã‚‰ãƒªãƒã‚¸ãƒˆãƒªã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Import repositories from GitHub"
msgstr "リãƒã‚¸ãƒˆãƒªã‚’ GitHub ã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹"
msgid "Import repository"
+msgstr "リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆ"
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr "リãƒã‚¸ãƒˆãƒªã¸æŽ¥ç¶š"
msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgstr "GitLab エンタープライズエディションを使用ã™ã‚‹ã¨ã€èª²é¡Œãƒœãƒ¼ãƒ‰ã®æ©Ÿèƒ½ãŒå¼·åŒ–ã•ã‚Œã¾ã™ã€‚"
msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr ""
+msgstr "GitLab エンタープライズエディションを使用ã™ã‚‹ã¨ã€æ¤œç´¢æ©Ÿèƒ½ãŒå¼·åŒ–ã•ã‚Œã€é«˜åº¦ãªã‚°ãƒ­ãƒ¼ãƒãƒ«æ¤œç´¢ãŒå¯èƒ½ã«ãªã‚Šã¾ã™ã€‚"
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåŒæ„ã—ãªã‘ã‚Œã°ãªã‚‰ãªã„利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼ã‚’å«ã‚ã¾ã™ã€‚"
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr "互æ›æ€§ã®ãªã„プロジェクト"
@@ -4393,6 +5146,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4421,6 +5177,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "貢献をã—ãŸã„関係者ã¯ã€ã‚³ãƒŸãƒƒãƒˆã‚’プッシュã™ã‚‹ã“ã¨ã§è²¢çŒ®ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr "内部 - グループãŠã‚ˆã³å†…部プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¦‹ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -4436,9 +5195,27 @@ msgstr "é–“éš”ã®ãƒ‘ターン"
msgid "Introducing Cycle Analytics"
msgstr "サイクル分æžã®ã”紹介"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4457,6 +5234,21 @@ msgstr "ボード"
msgid "IssueBoards|Boards"
msgstr "ボード"
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr "課題"
@@ -4490,6 +5282,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4508,6 +5306,12 @@ msgstr "ジョブ"
msgid "Job has been erased"
msgstr "ジョブãŒæ¶ˆåŽ»ã•ã‚Œã¾ã—ãŸ"
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr "ジョブ"
@@ -4547,10 +5351,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4565,12 +5369,18 @@ msgstr "6月"
msgid "June"
msgstr "6月"
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
msgid "Kubernetes Cluster"
msgstr "Kubernetes クラスター"
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "Kubernetes クラスターã®ä½œæˆä¸­ã«ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸ:%{timeout}"
@@ -4647,6 +5457,9 @@ msgstr[0] "éŽåŽ»%d日間"
msgid "Last Pipeline"
msgstr "最新パイプライン"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "最新コミット"
@@ -4662,6 +5475,9 @@ msgstr "最終編集者 %{name}"
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr "最終更新"
@@ -4677,15 +5493,39 @@ msgstr "ã“ã®æ™‚刻ã«"
msgid "Latest changes"
msgstr "最新ã®å¤‰æ›´"
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr "詳細"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr "Kubernetes ã®è©³ç´°"
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr "ä¿è­·ã•ã‚ŒãŸãƒ–ランãƒã«ã¤ã„ã¦ã®è©³ç´°"
@@ -4822,6 +5662,12 @@ msgstr "GitLab IDE ã®èª­ã¿è¾¼ã¿ä¸­..."
msgid "Loading..."
msgstr "読ã¿è¾¼ã¿ä¸­..."
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr "ロック"
@@ -4888,6 +5734,9 @@ msgstr "ラベルを管ç†"
msgid "Manage project labels"
msgstr "プロジェクトラベルã®ç®¡ç†"
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr "グループã®ãƒ¡ãƒ³ãƒãƒ¼ã‚·ãƒƒãƒ—を管ç†ã—ãªãŒã‚‰ã€SAML ã§åˆ¥ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ¬ãƒ™ãƒ«ã‚’追加ã—ã¾ã™ã€‚"
@@ -4918,9 +5767,12 @@ msgstr "3月"
msgid "Mark todo as done"
msgstr "Todo を完了ã«ã™ã‚‹"
-msgid "Markdown enabled"
+msgid "Markdown"
msgstr ""
+msgid "Markdown enabled"
+msgstr "マークダウンを使用ã§ãã¾ã™"
+
msgid "MarkdownToolbar|Add a bullet list"
msgstr ""
@@ -4954,9 +5806,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -4978,24 +5827,36 @@ msgstr ""
msgid "Members"
msgstr "メンãƒãƒ¼"
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "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 "メンãƒãƒ¼ãŒã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ã¨ã€ã“ã“ã«ãƒ•ã‚©ãƒ¯ãƒ¼ãƒ‰ã•ã‚Œã¾ã™ã€‚ã“ã‚Œã¯IDプロãƒã‚¤ãƒ€ãƒ¼ã‹ã‚‰å–å¾—ã§ãã¾ã™ã€‚IDプロãƒã‚¤ãƒ€ãƒ¼ã¯\"SSO Service Location\"ã€\"SAML Token Issuance Endpoint\"ã€\"SAML 2.0/W-Federation URL\"ãªã©ã¨ã‚‚呼ã°ã‚Œã¾ã™ã€‚"
msgid "Merge Request"
msgstr "マージリクエスト"
-msgid "Merge Request:"
-msgstr "マージリクエスト:"
-
msgid "Merge Requests"
msgstr "マージリクエスト"
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr "マージイベント"
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr "マージリクエスト"
@@ -5008,19 +5869,31 @@ msgstr "マージリクエスト"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "マージリクエストã¨ã¯ã€ãƒ—ロジェクトã«åŠ ãˆãŸå¤‰æ›´ã‚’æ示ã—ã€ãã®å¤‰æ›´ã«ã¤ã„ã¦ä»–ã®ãƒ¡ãƒ³ãƒãƒ¼ã¨è©±ã—åˆã†ãŸã‚ã®å ´æ‰€ã§ã™"
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5038,6 +5911,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5047,6 +5938,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr "マージ済ã¿"
@@ -5065,8 +5959,8 @@ msgstr "メトリクス - Prometheus"
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
-msgstr "ビジãƒã‚¹"
+msgid "Metrics for environment"
+msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -5074,6 +5968,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr "メトリクスを作æˆ"
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr "メトリクスを編集"
@@ -5083,7 +5983,7 @@ msgstr "環境"
msgid "Metrics|For grouping similar metrics"
msgstr "é¡žä¼¼ã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’グループ化"
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5095,24 +5995,18 @@ msgstr "汎用ラベル(オプション)"
msgid "Metrics|Must be a valid PromQL query."
msgstr "有効㪠PromQL クエリã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "Metrics|Name"
-msgstr "åå‰"
-
msgid "Metrics|New metric"
msgstr "æ–°è¦ãƒ¡ãƒˆãƒªã‚¯ã‚¹"
msgid "Metrics|No deployed environments"
msgstr ""
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
msgid "Metrics|Prometheus Query Documentation"
msgstr "Prometheus クエリã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
-msgid "Metrics|Query"
-msgstr "クエリ"
-
-msgid "Metrics|Response"
-msgstr "レスãƒãƒ³ã‚¹"
-
msgid "Metrics|System"
msgstr "システム"
@@ -5125,11 +6019,11 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
-msgstr "タイプ"
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr ""
@@ -5149,21 +6043,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr "Y軸ラベル"
-msgid "Metrics|e.g. HTTP requests"
-msgstr "例:HTTP リクエスト"
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr "例:スループット"
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr "マイルストーン"
@@ -5236,6 +6121,18 @@ msgstr "キャンセル"
msgid "Modal|Close"
msgstr "é–‰ã˜ã‚‹"
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "監視"
@@ -5264,7 +6161,7 @@ msgid "Move"
msgstr "移動"
msgid "Move issue"
-msgstr ""
+msgstr "課題を移動"
msgid "Multiple issue boards"
msgstr "マルãƒèª²é¡Œãƒœãƒ¼ãƒ‰"
@@ -5296,6 +6193,9 @@ msgstr "サインイン / 登録"
msgid "Nav|Sign out and sign in with a different account"
msgstr "別ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹"
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯"
@@ -5308,6 +6208,9 @@ msgstr "æ–°ã—ã„"
msgid "New Application"
msgstr "æ–°ã—ã„アプリケーション"
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr "æ–°ã—ã„グループ"
@@ -5321,6 +6224,12 @@ msgstr[0] "æ–°è¦èª²é¡Œ"
msgid "New Label"
msgstr "æ–°ã—ã„ラベル"
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "æ–°è¦ãƒ‘イプラインスケジュール"
@@ -5339,6 +6248,9 @@ msgstr "æ–°ã—ã„ブランãƒã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
msgid "New directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr "æ–°ã—ã„エピック"
@@ -5360,6 +6272,9 @@ msgstr "æ–°ã—ã„ラベル"
msgid "New merge request"
msgstr "æ–°è¦ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5387,6 +6302,9 @@ msgstr "ã„ã„ãˆ"
msgid "No Label"
msgstr "ラベルãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr "担当者ãªã—"
@@ -5396,6 +6314,9 @@ msgstr ""
msgid "No changes"
msgstr "変更ãªã—"
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Gitaly サーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ログを確èªã—ã¦ãã ã•ã„ï¼"
@@ -5408,15 +6329,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr "期é™ãªã—"
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr "ファイルãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“"
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
@@ -5429,6 +6359,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5438,10 +6371,13 @@ msgstr "マージリクエストã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
msgid "No messages were logged"
msgstr "メッセージã¯è¨˜éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“"
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5462,6 +6398,9 @@ msgstr ""
msgid "No schedules"
msgstr "スケジュールãªã—"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5471,12 +6410,6 @@ msgstr ""
msgid "None"
msgstr "ãªã—"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr "マージã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“"
@@ -5501,6 +6434,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "マスターブランãƒã¯è‡ªå‹•çš„ã«ä¿è­·ã•ã‚Œã‚‹ã“ã¨ã«ç•™æ„ã—ã¦ãã ã•ã„。%{link_to_protected_branches}"
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "注: 管ç†è€…ã¨ã—ã¦%{github_integration_link} を設定ã™ã‚‹ã¨ã€GitHub 経由ã®ãƒ­ã‚°ã‚¤ãƒ³ã‚’許å¯ã—ã€å€‹äººç”¨ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’生æˆã›ãšã«ãƒªãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -5531,6 +6467,12 @@ msgstr ""
msgid "Notification events"
msgstr "イベント通知"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "課題をクローズ"
@@ -5628,21 +6570,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
-msgstr "次ã®ã‚³ãƒŸãƒƒãƒˆã®ã‚³ãƒ¡ãƒ³ãƒˆã®ã¿ãŒä¸‹ã«è¡¨ç¤ºã•ã‚Œã¾ã™"
-
msgid "Only mirror protected branches"
msgstr ""
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
msgid "Only project members can comment."
msgstr "プロジェクトメンãƒãƒ¼ã®ã¿ã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™"
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr "Xcode ã§é–‹ã"
@@ -5676,16 +6633,13 @@ msgstr "é‹ç”¨"
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5733,6 +6687,12 @@ msgstr "パッケージ"
msgid "Pages"
msgstr "Pages"
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "最後 »"
@@ -5745,12 +6705,27 @@ msgstr "å‰ãƒšãƒ¼ã‚¸"
msgid "Pagination|« First"
msgstr "« 最åˆ"
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr "マージリクエストã§ã®å¤‰æ›´ç®‡æ‰€"
msgid "Password"
msgstr "パスワード"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "ã‚ãªãŸã® SSH 公開éµã‚’貼り付ã‘ã¾ã™ã€‚ã“ã®éµã¯é€šå¸¸ã€ãƒ•ã‚¡ã‚¤ãƒ« '~/.ssh/id_rsa.pub' 内ã«ã‚ã‚Šã€'ssh-rsa' ã¨ã„ã†æ–‡å­—列ã‹ã‚‰å§‹ã¾ã‚Šã¾ã™ã€‚SSH ã®ç§˜å¯†éµã‚’使用ã—ãªã„よã†ã«ã—ã¦ãã ã•ã„。"
@@ -5772,9 +6747,6 @@ msgstr "ä¿ç•™ä¸­"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "パスã®å¤‰æ›´ã€è»¢é€ã€ã‚°ãƒ«ãƒ¼ãƒ—ã®å‰Šé™¤ãªã©ã®é«˜åº¦ãªã‚ªãƒ—ションを実行ã—ã¾ã™ã€‚"
@@ -5790,6 +6762,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr "個人ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³"
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "パイプライン"
@@ -5976,6 +6954,9 @@ msgstr "PlantUML"
msgid "Play"
msgstr "実行"
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr "続ã‘ã‚‹å‰ã«ã€åˆ©ç”¨è¦ç´„ã«åŒæ„ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -5988,9 +6969,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6003,6 +6990,9 @@ msgstr "reCAPTCHA を解決ã—ã¦ãã ã•ã„"
msgid "Please try again"
msgstr "ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„"
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6045,6 +7035,9 @@ msgstr "優先ラベル"
msgid "Prioritized label"
msgstr "優先ラベル"
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr "プライベート - å„ユーザーã«ãƒ—ロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©é™ã‚’明示的ã«è¨±å¯ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -6066,9 +7059,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "削除予定ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã™ã€‚"
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr "キーを追加"
@@ -6084,15 +7086,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr "ユーザーåã®å¤‰æ›´"
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "ç¾åœ¨ã®ãƒ‘ス: %{path}"
@@ -6111,6 +7128,9 @@ msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "アカウントを削除ã™ã‚‹ã¨æ¬¡ã®ã‚ˆã†ãªå½±éŸ¿ãŒã‚ã‚Šã¾ã™:"
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6120,6 +7140,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "パスワードãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“"
@@ -6156,10 +7182,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6168,7 +7197,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6177,10 +7206,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6207,12 +7239,15 @@ msgstr "ユーザーåã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—㟠- %{message}"
msgid "Profiles|Username successfully changed"
msgstr "ユーザーåã¯æ­£å¸¸ã«å¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6231,16 +7266,19 @@ msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "アカウントを削除ã™ã‚‹å‰ã«ã“れらã®ã‚°ãƒ«ãƒ¼ãƒ—を削除ã€ã¾ãŸã¯æ‰€æœ‰æ¨©ã‚’譲渡ã—ã¦ãã ã•ã„。"
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ç¾åœ¨ã“れらã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ªãƒ¼ãƒŠãƒ¼ã§ã™:"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6249,6 +7287,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ"
@@ -6306,12 +7350,18 @@ msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãƒªãƒ³ã‚¯ã¯æœŸé™åˆ‡ã‚Œã«ãªã‚Š
msgid "Project export started. A download link will be sent by email."
msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã‚’開始ã—ã¾ã—ãŸã€‚ダウンロードã®ãƒªãƒ³ã‚¯ã¯ãƒ¡ãƒ¼ãƒ«ã§é€ä¿¡ã—ã¾ã™"
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr "プロジェクトå"
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "講読"
@@ -6456,9 +7506,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr "時間"
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "%{metrics} ã® %{exporters} ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ"
@@ -6483,6 +7530,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr "カスタムメトリクス"
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "メトリクスã®æ¤œç´¢ã¨è¨­å®š..."
@@ -6511,7 +7561,7 @@ msgid "PrometheusService|New metric"
msgstr "æ–°è¦ãƒ¡ãƒˆãƒªã‚¯ã‚¹"
msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
-msgstr ""
+msgstr "Prometheus API ã®ãƒ™ãƒ¼ã‚¹ URLã€ä¾‹:http://prometheus.example.com/"
msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
msgstr "Prometheus ã¯ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ä¸Šã§è‡ªå‹•çš„ã«ç®¡ç†ã•ã‚Œã¦ã„ã¾ã™"
@@ -6612,6 +7662,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "公開- グループãŠã‚ˆã³å…¬é–‹ãƒ—ロジェクトã¯èªè¨¼ç„¡ã—ã§é–²è¦§ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™"
@@ -6651,21 +7704,30 @@ msgstr "プッシュ"
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "クイックアクションã¯èª²é¡Œã®èª¬æ˜Žã¨ã‚³ãƒ¡ãƒ³ãƒˆæ¬„ã§ä½¿ç”¨ã§ãã¾ã™ã€‚"
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "続ãを読む"
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
-msgstr "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
msgid "Real-time features"
msgstr "リアルタイム機能"
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6691,6 +7753,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr "登録 / サインイン"
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã® Runner ã®ç™»éŒ²ã¨ç¢ºèª"
@@ -6721,6 +7786,12 @@ msgstr "関連ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "Related merge requests"
msgstr "関連ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "後ã§é€šçŸ¥"
@@ -6730,6 +7801,12 @@ msgstr "削除"
msgid "Remove Runner"
msgstr "Runner を削除"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除"
@@ -6760,9 +7837,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr "èªè¨¼ã®ä¿®å¾©"
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6823,6 +7906,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr "リãƒã‚¸ãƒˆãƒªã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
@@ -6841,6 +7930,9 @@ msgstr "é¸æŠž"
msgid "Request Access"
msgstr "アクセス権é™ã‚’リクエストã™ã‚‹"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6850,12 +7942,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "GitLab ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹éš›ã«ã€ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåˆ©ç”¨è¦ç´„ã«åŒæ„ã™ã‚‹ã“ã¨ã‚’è¦æ±‚ã—ã¾ã™ã€‚"
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr "正常性ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセット"
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "Runner 登録トークンをリセット"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6865,6 +7972,12 @@ msgstr "ソースブランãƒã§ã®ç«¶åˆã‚’解決ã™ã‚‹"
msgid "Resolve discussion"
msgstr "検討を解決"
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6874,12 +7987,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr "å†é–‹"
@@ -6892,13 +8011,13 @@ msgstr "ジョブをå†è©¦è¡Œã—ã¦ãã ã•ã„"
msgid "Retry verification"
msgstr "検証をå†è©¦è¡Œã—ã¦ãã ã•ã„"
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] "値を表示ã™ã‚‹"
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "ã“ã®ã‚³ãƒŸãƒƒãƒˆã‚’リãƒãƒ¼ãƒˆ"
@@ -6915,7 +8034,7 @@ msgid "Reviewing"
msgstr "レビュー中"
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr ""
+msgstr "レビュー中 (マージリクエスト !%{mergeRequestId})"
msgid "Revoke"
msgstr ""
@@ -6926,6 +8045,9 @@ msgstr "ロードマップ"
msgid "Run CI/CD pipelines for external repositories"
msgstr "外部リãƒã‚¸ãƒˆãƒªç”¨ CI/CD パイプラインを実行"
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6953,6 +8075,9 @@ msgstr "Runner"
msgid "Runners API"
msgstr "Runner API"
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Runner ã¯åˆ¥ã€…ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã€ã‚µãƒ¼ãƒãƒ¼ã€ã•ã‚‰ã«ã¯ã‚ãªãŸã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒžã‚·ãƒ¼ãƒ³ã«ã‚‚é…ç½®ã§ãã¾ã™ã€‚"
@@ -6986,8 +8111,8 @@ msgstr "SAML シングル サインオン"
msgid "SAML Single Sign On Settings"
msgstr "SAML シングル サインオンã®è¨­å®š"
-msgid "SAST"
-msgstr "SAST"
+msgid "SAML for %{group_name}"
+msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "SAML トークン㮠SHA1 フィンガープリントã§è¨¼æ˜Žæ›¸ã«ç½²åã—ã¾ã™ã€‚ã“ã‚Œã¯ã‚µãƒ ãƒ—リントã¨å‘¼ã°ã‚Œã‚¢ã‚¤ãƒ‡ãƒ³ãƒ†ã‚£ãƒ†ã‚£ãƒ—ロãƒã‚¤ãƒ€ãƒ¼ã‹ã‚‰å–å¾—ã§ãã¾ã™ã€‚"
@@ -6996,26 +8121,32 @@ msgid "SSH Keys"
msgstr "SSH éµ"
msgid "SSH host keys"
-msgstr ""
+msgstr "SSH ホストキー"
msgid "SSH public key"
-msgstr ""
+msgstr "SSH 公開éµ"
msgid "SSL Verification"
-msgstr ""
+msgstr "SSL ã®æ¤œè¨¼"
msgid "Save"
msgstr "ä¿å­˜"
-msgid "Save application"
+msgid "Save Changes"
msgstr ""
+msgid "Save application"
+msgstr "アプリケーションã®ä¿å­˜"
+
msgid "Save changes"
msgstr "変更をä¿å­˜"
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "パイプラインスケジュールをä¿å­˜"
@@ -7035,23 +8166,26 @@ msgid "Scheduling Pipelines"
msgstr "パイプラインスケジューリング"
msgid "Scope"
-msgstr ""
+msgstr "スコープ"
msgid "Scoped issue boards"
-msgstr ""
+msgstr "スコープ付課題ボード"
msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
msgstr ""
msgid "Scroll to bottom"
-msgstr ""
+msgstr "最下部ã«ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«"
msgid "Scroll to top"
-msgstr ""
+msgstr "最上部ã«ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«"
msgid "Search"
msgstr "検索"
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr "ブランãƒã‚’検索"
@@ -7062,6 +8196,9 @@ msgid "Search files"
msgstr "ファイルã®æ¤œç´¢"
msgid "Search for projects, issues, etc."
+msgstr "プロジェクトや課題ãªã©ã‚’検索ã™ã‚‹ã€‚"
+
+msgid "Search groups"
msgstr ""
msgid "Search merge requests"
@@ -7074,7 +8211,7 @@ msgid "Search or filter results..."
msgstr ""
msgid "Search or jump to…"
-msgstr ""
+msgstr "検索ã¾ãŸã¯ã‚¸ãƒ£ãƒ³ãƒ—å…ˆ..."
msgid "Search project"
msgstr "プロジェクトを検索"
@@ -7133,7 +8270,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7142,10 +8279,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7163,6 +8303,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7172,6 +8324,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr "é¸æŠž"
@@ -7199,11 +8357,14 @@ msgstr "担当者をé¸æŠž"
msgid "Select branch/tag"
msgstr "ブランãƒãƒ»ã‚¿ã‚°é¸æŠž"
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr "プロジェクトã®é¸æŠž"
msgid "Select project and zone to choose machine type"
-msgstr ""
+msgstr "マシンタイプをé¸æŠžã™ã‚‹ãŸã‚ã«ã€ãƒ—ロジェクトã¨ã‚¾ãƒ¼ãƒ³ã‚’é¸æŠž"
msgid "Select project to choose zone"
msgstr ""
@@ -7224,17 +8385,23 @@ msgid "Select the custom project template source group."
msgstr ""
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
-msgstr ""
+msgstr "GitLab ユーザーをé¸æŠžã™ã‚‹ã¨ã€GitLab ユーザーã¸ã®ãƒªãƒ³ã‚¯ãŒèª²é¡Œã‚„コメントã®èª¬æ˜Žã«è¿½åŠ ã•ã‚Œã¾ã™ (例:\"By <a href=\"#\">@johnsmith</a>\")。ã¾ãŸã€ã“れらã®èª²é¡Œã‚„コメントをé¸æŠžã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«é–¢é€£ä»˜ã‘や割り当ã¦ãŒã§ãã¾ã™ã€‚"
msgid "Selective synchronization"
-msgstr ""
+msgstr "é¸æŠžçš„ãªåŒæœŸ"
msgid "Send email"
msgstr "メールをé€ä¿¡"
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr "9月"
@@ -7244,6 +8411,48 @@ msgstr "9月"
msgid "Server version"
msgstr "サーãƒãƒ¼ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr "サービスデスク"
@@ -7266,17 +8475,20 @@ msgid "Set default and restrict visibility levels. Configure import sources and
msgstr "デフォルトを設定ã—ã€å¯è¦–性レベルを制é™ã—ã¾ã™ã€‚インãƒãƒ¼ãƒˆã‚½ãƒ¼ã‚¹ã¨ git アクセスプロトコルを設定ã—ã¾ã™ã€‚"
msgid "Set instance-wide template repository"
-msgstr ""
+msgstr "インスタンス全体レベルã®ãƒ†ãƒ³ãƒ—レートリãƒã‚¸ãƒˆãƒªã‚’設定ã—ã¾ã™ã€‚"
msgid "Set max session time for web terminal."
-msgstr ""
+msgstr "ウェブターミナルã®æœ€å¤§ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚¿ã‚¤ãƒ ã‚’設定ã™ã‚‹ã€‚"
msgid "Set notification email for abuse reports."
msgstr "迷惑行為レãƒãƒ¼ãƒˆã®é€šçŸ¥ãƒ¡ãƒ¼ãƒ«ã‚’設定ã™ã‚‹ã€‚"
-msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgid "Set number of approvers required before open merge requests can be merged"
msgstr ""
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr "ユーザーãŒã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ãŸã‚ã®è¦ä»¶ã‚’設定ã—ã¾ã™ã€‚å¿…é ˆã®äºŒè¦ç´ èªè¨¼ã‚’有効ã«ã—ã¾ã™ã€‚"
+
msgid "Set up CI/CD"
msgstr "CI/CD を設定"
@@ -7289,6 +8501,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7344,7 +8559,7 @@ msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
msgid "Sherlock Transactions"
-msgstr ""
+msgstr "シャーロックトランザクション"
msgid "Show command"
msgstr "コマンドを表示"
@@ -7352,10 +8567,10 @@ msgstr "コマンドを表示"
msgid "Show complete raw log"
msgstr "完全ãªç”Ÿãƒ­ã‚°ã‚’表示ã™ã‚‹"
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7372,7 +8587,7 @@ msgid_plural "Showing %d events"
msgstr[0] "%d ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’表示中"
msgid "Side-by-side"
-msgstr ""
+msgstr "並列"
msgid "Sidebar|Change weight"
msgstr "ウェイトを変更"
@@ -7390,14 +8605,23 @@ msgid "Sign in"
msgstr "サインイン"
msgid "Sign in / Register"
+msgstr "サインイン / 登録"
+
+msgid "Sign in to \"%{group_name}\""
msgstr ""
-msgid "Sign in to %{group_name}"
-msgstr "%{group_name} ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¾ã™"
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
msgid "Sign in with Single Sign-On"
msgstr "シングルサインオンã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹"
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr "サインアウト"
@@ -7407,6 +8631,9 @@ msgstr "サインインã®åˆ¶é™"
msgid "Sign-up restrictions"
msgstr "サインアップã®åˆ¶é™"
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr "サイズ"
@@ -7423,38 +8650,56 @@ msgid "Slower but makes sure the project workspace is pristine as it clones the
msgstr ""
msgid "Smartcard"
-msgstr ""
+msgstr "スマートカード"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr "スニペット"
-msgid "Something went wrong on our end"
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Something went wrong on our end"
+msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+
msgid "Something went wrong on our end."
msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Something went wrong on our end. Please try again!"
msgstr ""
-msgid "Something went wrong trying to change the confidentiality of this issue"
+msgid "Something went wrong on our end. Please try again."
msgstr ""
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr "課題ã®å…¬é–‹ç¯„囲ã®å¤‰æ›´ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
-msgstr ""
+msgstr "%{issuableDisplayName} をロック状態ã«ã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Something went wrong when toggling the button"
msgstr "ボタンã®åˆ‡ã‚Šæ›¿ãˆä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "%{issuable} を解決中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚ã¨ã§ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-msgid "Something went wrong while fetching %{listType} list"
+msgid "Something went wrong while deleting the source branch. Please try again."
msgstr ""
+msgid "Something went wrong while fetching %{listType} list"
+msgstr "%{listType} ã®ãƒªã‚¹ãƒˆå–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr ""
@@ -7465,9 +8710,12 @@ msgid "Something went wrong while fetching the environments for this merge reque
msgstr ""
msgid "Something went wrong while fetching the projects."
-msgstr ""
+msgstr "プロジェクト情報をå–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Something went wrong while fetching the registry list."
+msgstr "レジストリ一覧をå–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
+msgid "Something went wrong while merging this merge request. Please try again."
msgstr ""
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
@@ -7494,9 +8742,15 @@ msgstr "申ã—訳ã‚ã‚Šã¾ã›ã‚“ã€æ¤œç´¢ã«ä¸€è‡´ã™ã‚‹ã‚¨ãƒ”ックã¯ã‚ã‚Šã¾
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr "並ã¹æ›¿ãˆ"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr "アクセスレベル昇順"
@@ -7534,7 +8788,7 @@ msgid "SortOptions|Last joined"
msgstr "æ–°ã—ãå‚加ã—ãŸé †"
msgid "SortOptions|Last updated"
-msgstr ""
+msgstr "最終更新日時"
msgid "SortOptions|Least popular"
msgstr "人気順"
@@ -7542,8 +8796,8 @@ msgstr "人気順"
msgid "SortOptions|Less weight"
msgstr "ウェイトãŒå°ã•ã„é †"
-msgid "SortOptions|Milestone"
-msgstr "マイルストーン順"
+msgid "SortOptions|Milestone due date"
+msgstr ""
msgid "SortOptions|Milestone due later"
msgstr "マイルストーン期é™ã®é…ã„é †"
@@ -7575,6 +8829,9 @@ msgstr "å¤ã„é †"
msgid "SortOptions|Oldest joined"
msgstr "å‚加ã—ãŸé †"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr "サインイン順"
@@ -7587,6 +8844,9 @@ msgstr "人気順"
msgid "SortOptions|Priority"
msgstr "優先度順"
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr "最近ã®ã‚µã‚¤ãƒ³ã‚¤ãƒ³é †"
@@ -7614,6 +8874,9 @@ msgstr "ソースコード"
msgid "Source is not available"
msgstr "ソースã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr "スパム ログ"
@@ -7624,11 +8887,14 @@ msgid "Specific Runners"
msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
-msgstr ""
+msgstr "メールアドレスã®æ­£è¦è¡¨ç¾ãƒ‘ターンを指定ã—ã¦ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®å†…部ユーザーを区別ã—ã¾ã™ã€‚"
msgid "Specify the following URL during the Runner setup:"
msgstr "Runner セットアップã®éš›ã«æ¬¡ã® URL を指定ã—ã¦ãã ã•ã„:"
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr "コミットを1ã¤ã«ã¾ã¨ã‚ã‚‹"
@@ -7636,7 +8902,7 @@ msgid "Stage"
msgstr "ステージ"
msgid "Stage & Commit"
-msgstr ""
+msgstr "ステージ&コミット"
msgid "Stage all changes"
msgstr "ã™ã¹ã¦ã®å¤‰æ›´ã‚’ステージã™ã‚‹"
@@ -7648,7 +8914,7 @@ msgid "Staged"
msgstr "ステージ済"
msgid "Staged %{type}"
-msgstr ""
+msgstr "ステージ済㿠%{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "優先ラベルã«ã™ã‚‹ã«ã¯ã€ãƒ©ãƒ™ãƒ«ã«ã‚¹ã‚¿ãƒ¼ã‚’付ã‘ã¾ã™ã€‚ドラッグã—ã¦ã€å„ªå…ˆé †ä½ã‚’並ã¹æ›¿ãˆã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -7665,6 +8931,12 @@ msgstr "スター付ãプロジェクトã®æ´»å‹•"
msgid "Starred projects"
msgstr "スター付ãプロジェクト"
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "ã“ã®å¤‰æ›´ã§ %{new_merge_request} を作æˆã™ã‚‹"
@@ -7674,9 +8946,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Runner ã‚’èµ·å‹•!"
@@ -7686,15 +8970,30 @@ msgstr ""
msgid "Started"
msgstr "開始済ã¿"
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "開始時刻 (UTC)"
msgid "State your message to activate"
-msgstr ""
+msgstr "メッセージを有効ã«ã™ã‚‹"
msgid "Status"
msgstr "状態"
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7710,11 +9009,14 @@ msgstr "åœæ­¢ä¸­"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr "ストレージ"
msgid "Storage:"
-msgstr ""
+msgstr "ストレージ:"
msgid "Subgroups"
msgstr "サブグループ"
@@ -7723,6 +9025,9 @@ msgid "Subgroups and projects"
msgstr ""
msgid "Submit as spam"
+msgstr "スパムã¨ã—ã¦å ±å‘Š"
+
+msgid "Submit feedback"
msgstr ""
msgid "Submit review"
@@ -7740,10 +9045,94 @@ msgstr "グループレベルã§è³¼èª­ã™ã‚‹"
msgid "Subscribe at project level"
msgstr "プロジェクトレベルã§è³¼èª­ã™ã‚‹"
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7758,24 +9147,29 @@ msgstr "システムフック"
msgid "System Info"
msgstr "システム情報"
-msgid "System header and footer:"
-msgstr "システムヘッダーã¨ãƒ•ãƒƒã‚¿ãƒ¼:"
+msgid "System default (%{default})"
+msgstr ""
-msgid "System metrics (Custom)"
+msgid "System header and footer"
msgstr ""
+msgid "System metrics (Custom)"
+msgstr "システムメトリクス(カスタム)"
+
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] "タグ(%{tag_count})"
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "ã‚¿ã‚°"
msgid "Tags feed"
-msgstr ""
+msgstr "タグフィード"
msgid "Tags:"
msgstr "ã‚¿ã‚°:"
@@ -7817,16 +9211,16 @@ msgid "TagsPage|New tag"
msgstr "æ–°ã—ã„ã‚¿ã‚°"
msgid "TagsPage|Optionally, add a message to the tag."
-msgstr ""
+msgstr "オプションã¨ã—ã¦ã€ã‚¿ã‚°ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’追加ã§ãã¾ã™ã€‚"
msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
-msgstr ""
+msgstr "オプションã¨ã—ã¦ã€ã‚¿ã‚°ã«ãƒªãƒªãƒ¼ã‚¹ãƒŽãƒ¼ãƒˆã‚’追加ã§ãã¾ã™ã€‚リリースノート㯠GitLab ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä¿å­˜ã•ã‚Œã€ã‚¿ã‚°ã®ãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
msgid "TagsPage|Release notes"
-msgstr ""
+msgstr "リリースノート"
msgid "TagsPage|Repository has no tags yet."
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªã«ã¯ã¾ã ã‚¿ã‚°ãŒã‚ã‚Šã¾ã›ã‚“。"
msgid "TagsPage|Sort by"
msgstr "並ã¹æ›¿ãˆ"
@@ -7841,7 +9235,7 @@ msgid "TagsPage|This tag has no release notes."
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 "リリースノートを書ãã‹ã€ã“ã“ã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ドラッグ…"
@@ -7864,6 +9258,12 @@ msgstr "テンプレート"
msgid "Templates"
msgstr "テンプレート"
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼"
@@ -7874,17 +9274,23 @@ msgid "Test SAML SSO"
msgstr ""
msgid "Test coverage parsing"
-msgstr ""
+msgstr "テストカãƒãƒ¬ãƒƒã‚¸è§£æž"
msgid "Thanks! Don't show me this again"
+msgstr "ã‚ã‚ŠãŒã¨ã†ï¼ä»Šå¾Œè¡¨ç¤ºã—ãªã„"
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr "GitLab ã®é«˜åº¦ãªã‚°ãƒ­ãƒ¼ãƒãƒ«æ¤œç´¢ã¯ã€æ™‚間を節約ã§ãる強力ãªæ¤œç´¢ã‚µãƒ¼ãƒ“スã§ã™ã€‚é‡è¤‡ã—ãŸã‚³ãƒ¼ãƒ‰ã®ä½œæˆã‚’ã—ã¦æ™‚間を無駄ã«ã™ã‚‹ã“ã¨ãªãã€è‡ªèº«ã®ãƒ—ロジェクトã®åŠ©ã‘ã¨ãªã‚‹å¤–ã®ãƒãƒ¼ãƒ ã®ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚"
-msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
msgstr ""
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr "Git ã® LFS オブジェクトã¯<strong>åŒæœŸã—ã¾ã›ã‚“</strong>。"
+
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
msgstr "課題トラッカーã¯ã€ãƒ—ロジェクトを改善ã—ãŸã‚Šè§£æ±ºã—ãŸã‚Šã™ã‚‹ãŸã‚ã«å¿…è¦ãªæƒ…報を追加ã™ã‚‹å ´æ‰€ã§ã™"
@@ -7904,7 +9310,7 @@ msgid "The collection of events added to the data gathered for that stage."
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 deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -7913,11 +9319,14 @@ msgid "The fork relationship has been removed."
msgstr "フォークã®ãƒªãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
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 issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "課題ステージã§ã¯ã€èª²é¡ŒãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã‚‹ã‹ã€èª²é¡Œãƒœãƒ¼ãƒ‰ã®ãƒªã‚¹ãƒˆã«è¿½åŠ ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã™ã‚‹ã«ã¯èª²é¡Œã‚’最åˆã«ä½œæˆã—ã¦ãã ã•ã„。"
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr "許å¯ã•ã‚Œã‚‹æœ€å¤§ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã¯ 200KB ã§ã™ã€‚"
@@ -7925,13 +9334,13 @@ msgid "The passphrase required to decrypt the private key. This is optional and
msgstr "秘密éµã®å¾©å·ã«å¿…è¦ã¨ãªã‚‹ãƒ‘スフレーズ。ã“ã‚Œã¯ã‚ªãƒ—ションã§ã€å€¤ã¯æš—å·åŒ–ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚"
msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
-msgstr ""
+msgstr "CI 設定ファイルã¸ã®ãƒ‘ス。デフォルト㯠<code>.gitlab-ci.yml</code>"
msgid "The phase of the development lifecycle."
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 planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "計画ステージã§ã¯ã€èª²é¡Œã‚¹ãƒ†ãƒ¼ã‚¸ã«ç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—ッシュã•ã‚ŒãŸæœ€åˆã®ã‚³ãƒŸãƒƒãƒˆæ™‚刻ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚最åˆã®ã‚³ãƒŸãƒƒãƒˆãŒãƒ—ッシュã•ã‚Œã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
@@ -7949,7 +9358,7 @@ msgid "The project can be accessed without any authentication."
msgstr "プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãªã—ã«èª°ã§ã‚‚アクセスã§ãã¾ã™ã€‚"
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
+msgstr "匿å化データコレクションã¯ç„¡åŠ¹ã§ã™ã€‚有効ã«ã—ãŸã¨ãã€GitLab ã¯ã€ã‚ãªãŸãŒè¨­å®šã—ãŸã‚ªãƒ–ジェクトストレージディレクトリã«ã‚¢ãƒƒãƒ—ロードã™ã‚‹ GitLab データベースã®åŒ¿å化ã—㟠CSV を生æˆã™ã‚‹ã‚¸ãƒ§ãƒ–ã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã—ã¾ã™ã€‚"
msgid "The repository for this project does not exist."
msgstr "ã“ã®ãƒ—ロジェクトã«ãƒªãƒã‚¸ãƒˆãƒªã¯ã‚ã‚Šã¾ã›ã‚“。"
@@ -7961,13 +9370,13 @@ msgid "The repository must be accessible over <code>http://</code>, <code>https:
msgstr "リãƒã‚¸ãƒˆãƒªã«ã¯ã€<code>http://</code>〠<code>https://</code> ã¾ãŸã¯ <code>git://</code>ã§æŽ¥ç¶šã§ããªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªã¯ <code>http://</code> プロトコルã«ã‚‚ã€<code>https://</code> プロトコルã«ã‚‚ã€<code>ssh://</code> プロトコルã«ã‚‚ã€<code>git://</code> プロトコルã«ã‚‚接続ã•ã‚Œã‚‹ã“ã¨ãŒå¿…è¦ã§ã™ã€‚"
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "レビューステージã¨ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã—ã¦ã‹ã‚‰ãƒžãƒ¼ã‚¸ã™ã‚‹ã¾ã§ã®æ™‚é–“ã§ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚ŒãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
msgid "The roadmap shows the progress of your epics along a timeline"
-msgstr ""
+msgstr "ロードマップã«ã¯ã€ã‚¿ã‚¤ãƒ ãƒ©ã‚¤ãƒ³ã«æ²¿ã£ãŸã‚¨ãƒ”ックã®é€²æ—ãŒè¡¨ç¤ºã•ã‚Œã¾ã™"
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "ステージングステージã§ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã‹ã‚‰ã‚³ãƒ¼ãƒ‰ãŒãƒ—ロダクション環境ã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã«ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã—ãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
@@ -7988,25 +9397,43 @@ msgid "The usage ping is disabled, and cannot be configured through this form."
msgstr ""
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
-msgstr ""
+msgstr "ユーザーマップã¯ã€ã‚ãªãŸã®ãƒ—ロジェクトã«å‚加ã—㟠Google コードã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ GitLab ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ã¨ãã«ãƒžãƒƒãƒ”ングã™ã‚‹ JSON ファイルã§ã™ã€‚ã“れを変更ã™ã‚‹ã«ã¯ã€ <code>:</code> ã®å³å´ã®å€¤ã‚’変更ã—ã¾ã™ã€‚å·¦å´ã®äºŒé‡å¼•ç”¨ç¬¦ã€ãã®ä»–ã®å¥èª­ç‚¹ã€ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¾ãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼åãŒä¿å­˜ã•ã‚Œã¾ã™ã€‚"
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
-msgstr ""
+msgstr "ユーザーマップã¯ã€ã‚ãªãŸã®ãƒ—ロジェクトã«å‚加ã—㟠FogBugz ユーザーã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ GitLab ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹æ™‚ã«ãƒžãƒƒãƒ”ングã—ã¾ã™ã€‚ã“れを変更ã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®è¡¨ã«å…¥åŠ›ã—ã¾ã™ã€‚"
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "得られãŸä¸€é€£ã®ãƒ‡ãƒ¼ã‚¿ã‚’å°ã•ã„é †ã«ä¸¦ã¹ãŸã¨ãã«ä¸­å¤®ã«ä½ç½®ã™ã‚‹å€¤ã€‚例ãˆã°ã€3, 5, 9 ã®ä¸­å¤®å€¤ã¯ 5。3, 5, 7, 8 ã®ä¸­å¤®å€¤ã¯ (5+7)/2 = 6。"
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr "表示ã™ã‚‹èª²é¡ŒãŒã‚ã‚Šã¾ã›ã‚“"
msgid "There are no labels yet"
+msgstr "ã¾ã ãƒ©ãƒ™ãƒ«ãŒã‚ã‚Šã¾ã›ã‚“"
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
msgstr ""
-msgid "There are no merge requests to show"
-msgstr "表示ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "There are no packages yet"
+msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
@@ -8041,17 +9468,26 @@ msgstr "ラベルã®è³¼èª­ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "There was an error when unsubscribing from this label."
msgstr "ラベルã®è³¼èª­è§£é™¤ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr "%{link}を使用ã—ã¦ãれらを管ç†ã§ãã¾ã™ã€‚"
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "ã“ã® GitLab インスタンスã¯ã¾ã å…±æœ‰ Runner ã‚’æä¾›ã—ã¦ã„ã¾ã›ã‚“。インスタンス管ç†è€…ã¯ç®¡ç†è€…エリアã§å…±æœ‰ Runner を登録ã§ãã¾ã™ã€‚"
msgid "This application was created by %{link_to_owner}."
-msgstr ""
+msgstr "ã“ã®ã‚¢ãƒ—リケーション㯠%{link_to_owner} ã«ã‚ˆã£ã¦ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
msgid "This application will be able to:"
msgstr ""
@@ -8060,7 +9496,7 @@ msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
-msgstr ""
+msgstr "編集を開始ã—ã¦ã‹ã‚‰ãƒ–ランãƒãŒæ›´æ–°ã•ã‚Œã¦ã„ã¾ã™ã€‚æ–°ã—ã„ブランãƒã‚’作æˆã—ã¾ã™ã‹ï¼Ÿ"
msgid "This container registry has been scheduled for deletion."
msgstr ""
@@ -8072,16 +9508,19 @@ msgid "This date is before the start date, so this epic won't appear in the road
msgstr ""
msgid "This diff is collapsed."
+msgstr "ã“ã®å·®åˆ†ã¯å´©å£Šã—ã¦ã„ã¾ã™ã€‚"
+
+msgid "This diff was suppressed by a .gitattributes entry."
msgstr ""
msgid "This directory"
msgstr "ディレクトリ"
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã§ã¯ã€ã‚ãªãŸã®%{group_name}シングルサインオンアカウントã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã§ãã¾ã™ã€‚シングルサインオン利用時ã¯ã€å¤–部ã®ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãƒšãƒ¼ã‚¸ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã•ã‚Œã¾ã™ã€‚"
+msgid "This group"
+msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—"
msgid "This group does not provide any group Runners yet."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã¾ã ã‚°ãƒ«ãƒ¼ãƒ— Runner ã‚’æä¾›ã—ã¦ã„ã¾ã›ã‚“。"
@@ -8093,7 +9532,7 @@ msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
msgid "This is the author's first Merge Request to this project."
-msgstr ""
+msgstr "ã“ã®ãƒ—ロジェクトã«å¯¾ã™ã‚‹ã€ä½œæˆè€…ã®æœ€åˆã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§ã™ã€‚"
msgid "This issue is confidential"
msgstr "ã“ã®èª²é¡Œã¯éžå…¬é–‹è¨­å®šã§ã™"
@@ -8143,10 +9582,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã¯ä¿ç•™ä¸­ã§ Runner ãŒå‹•ä½œã™ã‚‹ã®ã‚’å¾…ã£ã¦ã„ã¾ã™ã€‚"
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8155,17 +9594,17 @@ msgstr ""
msgid "This job requires a manual action"
msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã¯æ‰‹å‹•ã«ã‚ˆã‚‹å®Ÿè¡Œã‚’求ã‚ã¦ã„ã¾ã™"
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
-msgstr ""
+msgstr "空リãƒã‚¸ãƒˆãƒªã‚’作æˆã¾ãŸã¯æ—¢å­˜ãƒªãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã‚’ã—ãªã‘ã‚Œã°ã€ã‚³ãƒ¼ãƒ‰ã®ãƒ—ッシュã¯ã§ãã¾ã›ã‚“。"
msgid "This merge request is locked."
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "This option is disabled as you don't have write permissions for the current branch"
-msgstr ""
+msgstr "ã‚ãªãŸã¯ç¾åœ¨ã®ãƒ–ランãƒã«å¯¾ã—ã¦æ›¸ãè¾¼ã¿æ¨©é™ãŒãªã„ã®ã§ã€ã“ã®ã‚ªãƒ—ションã¯ç„¡åŠ¹ã§ã™"
msgid "This option is disabled while you still have unstaged changes"
msgstr "ã¾ã ã‚¹ãƒ†ãƒ¼ã‚¸ãƒ³ã‚°ã•ã‚Œã¦ã„ãªã„変更ãŒã‚ã‚‹ã¨ã€ã“ã®ã‚ªãƒ—ションã¯ç„¡åŠ¹ã«ãªã‚Šã¾ã™"
@@ -8176,6 +9615,15 @@ msgstr "複数ã®ãƒ—ロジェクト間ã§èª­ã¿è¾¼ã¿ãŒè¨±å¯ã•ã‚Œã¦ã„ãªã„
msgid "This page will be removed in a future release."
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã¯ã€å°†æ¥ã®ãƒªãƒªãƒ¼ã‚¹ã§å‰Šé™¤ã•ã‚Œã‚‹äºˆå®šã§ã™ã€‚"
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr "プロジェクト"
@@ -8201,13 +9649,13 @@ msgid "This setting will update the hostname that is used to generate private co
msgstr ""
msgid "This source diff could not be displayed because it is too large."
-msgstr ""
+msgstr "差分ãŒå¤§ãã™ãŽã‚‹ãŸã‚ã€ã‚½ãƒ¼ã‚¹å·®åˆ†ã‚’表示ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
-msgstr ""
+msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã¯ ID ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
@@ -8215,7 +9663,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8406,14 +9854,23 @@ msgstr "ヒント:"
msgid "Title"
msgstr "タイトル"
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr "GitLab ã¸"
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgid "To access this domain create a new DNS record"
msgstr ""
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr "SSH キーを追加ã™ã‚‹ã«ã¯ã€%{generate_link_start}キーを生æˆã™ã‚‹%{link_end} ã¾ãŸã¯%{existing_link_start}既存ã®ã‚­ãƒ¼ã‚’使用ã™ã‚‹%{link_end}ã®ã©ã¡ã‚‰ã‹ãŒå¿…è¦ã§ã™ã€‚"
+
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>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr ""
+msgstr "GitHub リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã« %{personal_access_token_link} を使用ã§ãã¾ã™ã€‚個人用アクセストークンを作æˆã™ã‚‹ã«ã¯<code>リãƒã‚¸ãƒˆãƒª</code> スコープをé¸æŠžã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚ŠæŽ¥ç¶šã§ãる公開・éžå…¬é–‹ãƒªãƒã‚¸ãƒˆãƒªã®ä¸€è¦§ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
msgstr "GitHub リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã«ã¯ã€GitLab ãŒã‚ãªãŸã® GitHub リãƒã‚¸ãƒˆãƒªä¸€è¦§ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™:"
@@ -8422,19 +9879,19 @@ msgid "To connect an SVN repository, check out %{svn_link}."
msgstr "SVN リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã¨ãã¯ã€%{svn_link} ã‚’ã”確èªãã ã•ã„。"
msgid "To define internal users, first enable new users set to external"
-msgstr ""
+msgstr "内部ユーザーを定義ã™ã‚‹ãŸã‚ã«ã¯ã€å…ˆã«æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’外部ユーザーã«è¨­å®šã§ãるよã†ã«ã—ã¾ã™ã€‚"
msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
msgstr ""
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
-msgstr ""
+msgstr "ã¯ã˜ã‚ã« FogBugz ã® URL ã¨ãƒ­ã‚°ã‚¤ãƒ³æƒ…報を入力ã—ã¦ãã ã•ã„。次ã®ã‚¹ãƒ†ãƒƒãƒ—ã§ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’マップã—ã¦ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ãƒ—ロジェクトをé¸æŠžã—ã¾ã™ã€‚"
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
-msgstr ""
+msgstr "開始ã™ã‚‹ã«ã¯ã€Gitea Host ã® URL 㨠%{link_to_personal_token} を入力ã—ã¦ãã ã•ã„。"
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
msgstr ""
@@ -8451,23 +9908,41 @@ msgstr "GitHub リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€GitLab ãŒã‚ãªã
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "SVN リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€%{svn_link} ã‚’ã”確èªãã ã•ã„。"
-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."
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
msgstr ""
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr "GitLab プロジェクト全体を別㮠GitLab インストールã‹ã‚‰ã“ã®ãƒ—ロジェクトã«ç§»å‹•ã¾ãŸã¯ã‚³ãƒ”ーã™ã‚‹ã«ã¯ã€å…ƒã®ãƒ—ロジェクトã®è¨­å®šãƒšãƒ¼ã‚¸ã«ç§»å‹•ã—ã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’生æˆã—ã¦ã“ã“ã«ã‚¢ãƒƒãƒ—ロードã—ã¾ã™ã€‚"
+
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr "外部リãƒã‚¸ãƒˆãƒªã«ã®ã¿ CI/CD ã®æ©Ÿèƒ½ã‚’使用ã™ã‚‹ã«ã¯ã€<strong>外部リãƒã‚¸ãƒˆãƒªç”¨ CI/CD</strong>ã‚’é¸æŠžã—ã¦ãã ã•ã„。"
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
msgstr ""
-msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr "Azureã€Oktaã€Oneloginã€Ping Identyã€ã¾ãŸã¯ã‚«ã‚¹ã‚¿ãƒ  SAML 2.0 プロãƒã‚¤ãƒ€ãƒ¼ãªã©ã® ID プロãƒã‚¤ãƒ€ãƒ¼ã‚’利用ã—ã¦ã€ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã® SAML èªè¨¼ã‚’設定ã™ã‚‹ã«ã¯:"
+
msgid "To start serving your jobs you can add Runners to your group"
+msgstr "ジョブを開始ã™ã‚‹ãŸã‚ã€ã‚°ãƒ«ãƒ¼ãƒ—ã« Runner を追加ã§ãã¾ã™"
+
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
msgstr ""
msgid "To this GitLab instance"
-msgstr ""
+msgstr "ã“ã® GitLab インスタンスã«"
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr "GitLab CI ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’検証ã™ã‚‹ã«ã¯ã€ãƒ—ロジェクト内ã®ã€ŒCI / CD→Pipelinesã€ã«è¡Œãã€ã€ŒCI Lintã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。"
@@ -8475,11 +9950,14 @@ msgstr "GitLab CI ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’検証ã™ã‚‹ã«ã¯ã€ãƒ—ロジェクãƒ
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr "検索範囲を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚"
msgid "Today"
-msgstr ""
+msgstr "今日"
msgid "Todo"
msgstr "Todo"
@@ -8490,15 +9968,18 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr "サイドãƒãƒ¼ã‚’切り替ãˆ"
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
+msgid "Toggle commit list"
+msgstr ""
+
msgid "Toggle discussion"
msgstr "検討ã®è¡¨ç¤ºãƒ»éžè¡¨ç¤ºã‚’切り替ãˆã‚‹"
-msgid "Toggle file browser"
-msgstr ""
-
msgid "Toggle navigation"
msgstr ""
@@ -8506,22 +9987,22 @@ msgid "Toggle sidebar"
msgstr "サイドãƒãƒ¼ã‚’切り替ãˆ"
msgid "ToggleButton|Toggle Status: OFF"
-msgstr ""
+msgstr "切り替ãˆçŠ¶æ…‹:オフ"
msgid "ToggleButton|Toggle Status: ON"
-msgstr ""
+msgstr "切り替ãˆçŠ¶æ…‹:オン"
msgid "Token"
msgstr "トークン"
msgid "Tomorrow"
-msgstr ""
+msgstr "明日"
msgid "Too many changes to show."
msgstr ""
msgid "Total Contributions"
-msgstr ""
+msgstr "ç·è²¢çŒ®åº¦"
msgid "Total Time"
msgstr "åˆè¨ˆæ™‚é–“"
@@ -8539,7 +10020,7 @@ msgid "Track activity with Contribution Analytics."
msgstr ""
msgid "Track groups of issues that share a theme, across projects and milestones"
-msgstr ""
+msgstr "プロジェクトãŠã‚ˆã³ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³å…¨ä½“ã§ã€ãƒ†ãƒ¼ãƒžã‚’共有ã™ã‚‹èª²é¡Œã®ã‚°ãƒ«ãƒ¼ãƒ—を追跡"
msgid "Track time with quick actions"
msgstr "クイックアクションã§ä½œæ¥­æ™‚間を記録"
@@ -8548,10 +10029,7 @@ msgid "Tree view"
msgstr ""
msgid "Trending"
-msgstr ""
-
-msgid "Trigger"
-msgstr "トリガー"
+msgstr "トレンド分æž"
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8560,23 +10038,35 @@ msgid "Trigger pipelines when branches or tags are updated from the upstream rep
msgstr ""
msgid "Trigger this manual action"
+msgstr "ã“ã®æ‰‹å‹•ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã‚’トリガーã™ã‚‹"
+
+msgid "Trigger token:"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Trigger variables:"
msgstr ""
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr "トリガーã¯ã€ç‰¹å®šã®ãƒ–ランãƒã¾ãŸã¯ã‚¿ã‚°ã‚’ API 呼ã³å‡ºã—ã§å¼·åˆ¶çš„ã«å†æ§‹ç¯‰ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“れらã®ãƒˆãƒ¼ã‚¯ãƒ³ã¯ã€ãƒ—ロジェクトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚„プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ãªã©ã€é–¢é€£ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’å½è£…ã—ã¾ã™ã€‚"
+
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
msgid "Try again"
msgstr "å†è©¦è¡Œ"
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
-msgid "Turn on Service Desk"
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Turn on Service Desk"
+msgstr "サービスデスクを有効ã«ã™ã‚‹"
+
msgid "Twitter"
msgstr "Twitter"
@@ -8584,31 +10074,37 @@ msgid "Two-factor authentication"
msgstr ""
msgid "Type"
-msgstr ""
+msgstr "タイプ"
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
-msgstr ""
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr "差分を読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“。%{button_try_again}"
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
-msgstr ""
+msgstr "\"%{reason}\"ã®ãŸã‚ SAML ã§ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã§ãã¾ã›ã‚“"
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
-msgid "Unknown"
+msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
+msgid "Unknown"
+msgstr "ä¸æ˜Ž"
+
msgid "Unlock"
msgstr "アンロック"
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr ""
+msgstr "%{issuableDisplayName} ã®ãƒ­ãƒƒã‚¯ã‚’解除ã—ã¾ã™ã‹ï¼Ÿ <strong>全員</strong>ãŒã‚³ãƒ¡ãƒ³ãƒˆã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚"
msgid "Unlocked"
msgstr "アンロック済ã¿"
@@ -8649,6 +10145,9 @@ msgstr "グループレベルã§è³¼èª­ã‚’解除"
msgid "Unsubscribe at project level"
msgstr "プロジェクトレベルã§è³¼èª­ã‚’解除"
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr "未検証"
@@ -8661,13 +10160,19 @@ msgstr ""
msgid "Update"
msgstr "アップデート"
-msgid "Update now"
+msgid "Update failed"
msgstr ""
+msgid "Update now"
+msgstr "今ã™ãæ›´æ–°"
+
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
+msgstr "更新中"
+
+msgid "Upgrade plan to unlock Canary Deployments feature"
msgstr ""
msgid "Upgrade your plan to activate Advanced Global Search."
@@ -8686,17 +10191,32 @@ msgid "Upgrade your plan to improve Issue boards."
msgstr "課題ボードã®æ©Ÿèƒ½ã‚’強化ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランをアップグレード"
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr "<code>GoogleCodeProjectHosting.json</code> をアップロードã—ã¾ã™:"
+
+msgid "Upload CSV file"
msgstr ""
msgid "Upload New File"
msgstr "æ–°è¦ãƒ•ã‚¡ã‚¤ãƒ«ã‚’アップロード"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "ファイルをアップロード"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "クリックã—ã¦ã‚¢ãƒƒãƒ—ロード"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr "ã„ã„ã­"
@@ -8707,7 +10227,7 @@ msgid "Usage statistics"
msgstr "使用状æ³ã®çµ±è¨ˆ"
msgid "Use <code>%{native_redirect_uri}</code> for local tests"
-msgstr ""
+msgstr "ローカルテスト㫠<code>%{native_redirect_uri}</code> を使用"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "サービスデスクを使用ã—ã¦ã€GitLab 内ã®ãƒ¡ãƒ¼ãƒ«ã§ãƒ¦ãƒ¼ã‚¶ã¨æŽ¥ç¶šï¼ˆä¾‹ï¼šé¡§å®¢ã‚µãƒãƒ¼ãƒˆï¼‰"
@@ -8716,10 +10236,10 @@ msgid "Use group milestones to manage issues from multiple projects in the same
msgstr "グループマイルストーンを使用ã—ã¦ã€åŒã˜ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³å†…ã®è¤‡æ•°ã®ãƒ—ロジェクトã®èª²é¡Œã‚’管ç†ã—ã¾ã™ã€‚"
msgid "Use one line per URI"
-msgstr ""
+msgstr "URI ã”ã¨ã«1行使用"
msgid "Use template"
-msgstr ""
+msgstr "テンプレートを使用"
msgid "Use the following registration token during setup:"
msgstr "セットアップã®éš›ã«æ¬¡ã®ç™»éŒ²ãƒˆãƒ¼ã‚¯ãƒ³ã‚’使用ã—ã¦ãã ã•ã„:"
@@ -8727,20 +10247,26 @@ msgstr "セットアップã®éš›ã«æ¬¡ã®ç™»éŒ²ãƒˆãƒ¼ã‚¯ãƒ³ã‚’使用ã—ã¦ãã 
msgid "Use your global notification setting"
msgstr "全体通知設定を利用"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "メンãƒãƒ¼ãŒ GitLab ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™"
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
msgid "User Settings"
-msgstr ""
+msgstr "ユーザー設定"
msgid "User and IP Rate Limits"
msgstr "ユーザーã¨IPレートã®åˆ¶é™"
msgid "User map"
-msgstr ""
+msgstr "ユーザーマップ"
msgid "UserProfile|Activity"
msgstr ""
@@ -8754,47 +10280,83 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
+msgstr "グループ"
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
msgstr ""
-msgid "UserProfile|Most Recent Activity"
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Overview"
+msgstr "概è¦"
+
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
msgstr ""
msgid "UserProfile|Snippets"
+msgstr "スニペット"
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
msgstr ""
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr "ユーザー"
-msgid "Variables"
-msgstr "変数"
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr "変数㯠Runner を介ã—ã¦ç’°å¢ƒã«é©ç”¨ã•ã‚Œã¾ã™ã€‚ã¾ãŸã€ä¿è­·ã•ã‚ŒãŸãƒ–ランãƒã‚„ã‚¿ã‚°ã ã‘ã«å¤‰æ•°ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’制é™ã—ã€å¤‰æ•°ã‚’ä¿è­·ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ãƒ‘スワードã€ç§˜å¯†éµãªã©ã‚’æ ¼ç´ã™ã‚‹ãŸã‚ã«å¤‰æ•°ã‚’使用ã§ãã¾ã™ã€‚"
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
msgid "Various container registry settings."
msgstr "å„種コンテナレジストリã®è¨­å®šã€‚"
@@ -8802,10 +10364,16 @@ msgstr "å„種コンテナレジストリã®è¨­å®šã€‚"
msgid "Various email settings."
msgstr "å„種メール設定。"
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr "GitLab ã®ãƒ‘フォーマンスã«å½±éŸ¿ã™ã‚‹å„種設定。"
msgid "Verification information"
+msgstr "検証情報"
+
+msgid "Verification status"
msgstr ""
msgid "Verified"
@@ -8820,6 +10388,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8833,10 +10407,10 @@ msgid "View group labels"
msgstr "グループラベルを表示"
msgid "View issue"
-msgstr ""
+msgstr "課題を表示"
msgid "View it on GitLab"
-msgstr ""
+msgstr "GitLab ã§è¡¨ç¤º"
msgid "View jobs"
msgstr "ジョブを表示"
@@ -8854,19 +10428,22 @@ msgid "View project labels"
msgstr "プロジェクトラベルを表示"
msgid "View replaced file @ "
-msgstr ""
+msgstr "変更後ファイルを表示 @ "
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "å¯è¦–性ã¨ã‚¢ã‚¯ã‚»ã‚¹åˆ¶å¾¡"
msgid "Visibility level"
-msgstr ""
+msgstr "å¯è¦–性レベル"
msgid "Visibility level:"
-msgstr ""
+msgstr "å¯è¦–性レベル:"
msgid "Visibility:"
msgstr ""
@@ -8883,59 +10460,86 @@ msgstr "パブリック"
msgid "VisibilityLevel|Unknown"
msgstr "ä¸æ˜Ž"
-msgid "Vulnerability|Class"
+msgid "Vulnerability Chart"
msgstr ""
+msgid "Vulnerability List"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr "クラス"
+
msgid "Vulnerability|Confidence"
msgstr ""
msgid "Vulnerability|Description"
-msgstr ""
+msgstr "説明"
msgid "Vulnerability|File"
-msgstr ""
+msgstr "ファイル"
msgid "Vulnerability|Identifiers"
-msgstr ""
+msgstr "識別å­"
msgid "Vulnerability|Instances"
-msgstr ""
+msgstr "インスタンス"
msgid "Vulnerability|Links"
-msgstr ""
+msgstr "リンク"
msgid "Vulnerability|Project"
-msgstr ""
+msgstr "プロジェクト"
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ã“ã®ãƒ‡ãƒ¼ã‚¿ã‚’å‚ç…§ã—ãŸã„ã§ã™ã‹ï¼Ÿã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ç®¡ç†è€…ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
-msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
msgstr ""
+msgid "We couldn't find any results matching"
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr "%{humanized_resource_name} ã«ã‚¹ãƒ‘ムãŒã‚ã‚‹å¯èƒ½æ€§ã‚’検出ã—ã¾ã—ãŸã€‚続行ã™ã‚‹ã«ã¯ reCAPTCHA を実行ã—ã¦ãã ã•ã„。"
+
msgid "We don't have enough data to show this stage."
msgstr "データä¸è¶³ã®ãŸã‚ã€ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã®è¡¨ç¤ºã¯ã§ãã¾ã›ã‚“。"
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "本人確èªã®ãŸã‚ã€ã‚ãªãŸãŒãƒ­ãƒœãƒƒãƒˆã§ãªã„ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
msgid "Web IDE"
msgstr "Web IDE"
-msgid "Web terminal"
+msgid "Web Terminal"
msgstr ""
+msgid "Web terminal"
+msgstr "ウェブターミナル"
+
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
msgid "Weeks"
-msgstr ""
+msgstr "週"
msgid "Weight"
msgstr "ウェイト"
@@ -8950,6 +10554,9 @@ msgid "When enabled, users cannot use GitLab until the terms have been accepted.
msgstr "有効ã«ã—ãŸå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¦ç´„ã«åŒæ„ã•ã‚Œã‚‹ã¾ã§ GitLab を使用ã§ãã¾ã›ã‚“。"
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr "URL を空白ã®ã¾ã¾ã«ã™ã‚‹ã¨ã€ãƒ—ロジェクト間ã®æ©Ÿèƒ½ã‚’無効ã«ã—ãŸã‚Šã€å¤–部èªè¨¼ãƒã‚§ãƒƒã‚¯ã‚’実行ã—ãŸã‚Šã›ãšã«åˆ†é¡žãƒ©ãƒ™ãƒ«ã‚’指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+
+msgid "When:"
msgstr ""
msgid "Who can see this group?"
@@ -8971,16 +10578,16 @@ msgid "WikiClone|Install Gollum"
msgstr "Gollum をインストール"
msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
-msgstr ""
+msgstr "GFM 機能をローカルã§ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã™ã‚‹ã«ã¯ %{markdown} をインストールã—ã¦ãã ã•ã„。"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "Gollum ã‚’èµ·å‹•ã—ã¦ãƒ­ãƒ¼ã‚«ãƒ«ã§ç·¨é›†ã™ã‚‹"
msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
-msgstr ""
+msgstr "ヒント:タイトルã®å…ˆé ­ã«ãƒ‘スを追加ã™ã‚‹ã¨ã€ã“ã®ãƒšãƒ¼ã‚¸ã‚’移動ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "WikiEdit|There is already a page with the same title in that path."
-msgstr ""
+msgstr "åŒã˜ãƒ‘スã«åŒã˜ã‚¿ã‚¤ãƒˆãƒ«ã®ãƒšãƒ¼ã‚¸ãŒæ—¢ã«ã‚ã‚Šã¾ã™ã€‚"
msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
msgstr "Wiki ã®æ”¹å–„ã‚’æ案ã™ã‚‹"
@@ -8989,7 +10596,7 @@ msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki p
msgstr "Wiki ページを追加ã™ã‚‹ã«ã¯ã€ãƒ—ロジェクトメンãƒãƒ¼ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。ã“ã®ãƒ—ロジェクト㮠Wiki を改善ã™ã‚‹æ–¹æ³•ã®æ案ãŒã‚ã‚‹å ´åˆã¯ã€ %{issues_link} ã§å•é¡Œã‚’é–‹ãã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。"
msgid "WikiEmptyIssueMessage|issue tracker"
-msgstr ""
+msgstr "課題トラッカー"
msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
msgstr "Wiki ã¯ãƒ—ロジェクトã«é–¢ã™ã‚‹ã™ã¹ã¦ã®è©³ç´°ã‚’ä¿å­˜ã™ã‚‹å ´æ‰€ã§ã™ã€‚ã“ã‚Œã«ã¯ã€ãƒ—ロジェクトを作æˆã—ãŸç†ç”±ã€ãƒ—ロジェクトã®åŽŸå‰‡ã€ãƒ—ロジェクトã®ä½¿ç”¨æ–¹æ³•ãªã©ãŒå«ã¾ã‚Œã¾ã™ã€‚"
@@ -9034,7 +10641,7 @@ msgid "WikiNewPagePlaceholder|how-to-setup"
msgstr "セットアップ方法"
msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
-msgstr ""
+msgstr "ヒント:æ–°ã—ã„ファイルをフルパスã§æŒ‡å®šã—ã¾ã™ã€‚途中ã®å­˜åœ¨ã—ãªã„ディレクトリã¯è‡ªå‹•çš„ã«ä½œæˆã•ã‚Œã¾ã™ã€‚"
msgid "WikiNewPageTitle|New Wiki Page"
msgstr "æ–°ã—ã„ Wiki ページ"
@@ -9093,22 +10700,34 @@ msgstr "Pages"
msgid "Wiki|Wiki Pages"
msgstr "Wikiページ"
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr "アクセスリクエストをå–り消ã™"
-msgid "Yes"
+msgid "Write a comment or drag your files here…"
msgstr ""
-msgid "Yes, add it"
+msgid "Write milestone description..."
msgstr ""
+msgid "Yes"
+msgstr "ã¯ã„"
+
+msgid "Yes, add it"
+msgstr "ã¯ã„ã€è¿½åŠ ã—ã¾ã™"
+
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
msgid "Yesterday"
+msgstr "昨日"
+
+msgid "You"
msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
@@ -9127,6 +10746,9 @@ msgid "You are going to transfer %{project_full_name} to another owner. Are you
msgstr "%{project_full_name} を別ã®ã‚ªãƒ¼ãƒŠãƒ¼ã«å§”è­²ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "You are on a read-only GitLab instance."
+msgstr "読ã¿å–り専用 GitLab インスタンスをå‚照中ã§ã™ã€‚"
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
@@ -9139,13 +10761,13 @@ msgid "You can also star a label to make it a priority label."
msgstr "ラベルã«ã‚¹ã‚¿ãƒ¼ã‚’付ã‘ã¦å„ªå…ˆãƒ©ãƒ™ãƒ«ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
msgid "You can easily contribute to them by requesting to join these groups."
-msgstr ""
+msgstr "ã“れらã®ã‚°ãƒ«ãƒ¼ãƒ—ã¸ã®å‚加をリクエストã™ã‚‹ã“ã¨ã§ã€ç°¡å˜ã«è²¢çŒ®ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "Kubernetes クラスター㫠Runner ã‚’ç°¡å˜ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã™ã€‚%{link_to_help_page}"
msgid "You can move around the graph by using the arrow keys."
-msgstr ""
+msgstr "矢å°ã‚­ãƒ¼ã‚’使用ã—ã¦ã‚°ãƒ©ãƒ•ã‚’移動ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "You can only add files when you are on a branch"
msgstr "ファイルを追加ã™ã‚‹ã«ã¯ã€ã©ã“ã‹ã®ãƒ–ランãƒã«ã„ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“"
@@ -9153,6 +10775,9 @@ msgstr "ファイルを追加ã™ã‚‹ã«ã¯ã€ã©ã“ã‹ã®ãƒ–ランãƒã«ã„ãªã‘
msgid "You can only edit files when you are on a branch"
msgstr "ファイルを編集ã™ã‚‹ã«ã¯ã€ã©ã“ã‹ã®ãƒ–ランãƒã«ã„ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“"
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9163,21 +10788,27 @@ msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
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 do not have any subscriptions yet"
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr "LDAP グループã®åŒæœŸã®è¨­å®šã‚’上書ãã™ã‚‹ãŸã‚ã®é©åˆ‡ãªæ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。"
+
msgid "You don't have any applications"
-msgstr ""
+msgstr "アプリケーションãŒã‚ã‚Šã¾ã›ã‚“"
msgid "You don't have any authorized applications"
+msgstr "承èªã•ã‚ŒãŸã‚¢ãƒ—リケーションãŒã‚ã‚Šã¾ã›ã‚“"
+
+msgid "You don't have any deployments right now."
msgstr ""
msgid "You have no permissions"
@@ -9186,6 +10817,9 @@ msgstr "権é™ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "You have reached your project limit"
msgstr "プロジェクト数ã®ä¸Šé™ã«é”ã—ã¦ã„ã¾ã™"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr "アカウントを登録ã™ã‚‹ã«ã¯ã€åˆ©ç”¨è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼ã«åŒæ„ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"
@@ -9195,16 +10829,22 @@ msgstr "ロックを強制的ã«å‰Šé™¤ã™ã‚‹ã«ã¯ã€Maintainer ã®ã‚¢ã‚¯ã‚»ã‚¹æ
msgid "You need a different license to enable FileLocks feature"
msgstr "ファイルロック機能を有効ã«ã™ã‚‹ã«ã¯åˆ¥ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãŒå¿…è¦ã§ã™"
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr "権é™ãŒå¿…è¦ã§ã™"
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9238,7 +10878,7 @@ msgid "You're receiving this email because %{reason}."
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_notifications_link} &middot; %{help_link}"
msgstr "ã“ã®ãƒ¡ãƒ¼ãƒ«ã¯ %{host} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆå®›ã«é€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚ %{manage_notifications_link}&middot;%{help_link}"
@@ -9246,6 +10886,9 @@ msgstr "ã“ã®ãƒ¡ãƒ¼ãƒ«ã¯ %{host} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆå®›ã«é€ä¿¡ã•ã‚Œã¾ã—ãŸ
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr "所属グループ"
@@ -9261,17 +10904,23 @@ msgstr "プロジェクトã®æ´»å‹•"
msgid "Your Todos"
msgstr "ã‚ãªãŸã®Todo"
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
+msgstr "承èªã•ã‚ŒãŸã‚¢ãƒ—リケーション"
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "マージリクエストãŒé–‹ã„ã¦ã„ã‚‹ãŸã‚ã€å¤‰æ›´ã¯ %{branch_name} ã«ã‚³ãƒŸãƒƒãƒˆã§ãã¾ã™ã€‚"
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
-msgstr ""
+msgstr "ã™ã§ã«å¤‰æ›´ã‚’コミット済ã¿ã§ã™ã€‚コミット %{commitId} %{commitStats} "
msgid "Your changes have been saved"
msgstr ""
@@ -9279,27 +10928,45 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr "ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ä¸€èˆ¬ã«ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。"
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "所属グループ"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "åå‰"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr "ã‚ãªãŸã®ãƒ—ロジェクト"
msgid "a deleted user"
-msgstr ""
+msgstr "削除ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "ago"
msgstr "å‰"
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr "ãã®ä»–ã®ã‚‚ã®"
msgid "assign yourself"
msgstr "自分ã«å‰²ã‚Šå½“ã¦"
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr "ブランãƒå"
@@ -9310,19 +10977,19 @@ msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}
msgstr "%{linkStartTag}コンテナスキャンã®è©³ç´°%{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|%{namespace} is affected by %{vulnerability}."
msgstr "%{namespace} 㯠%{vulnerability} ã®å½±éŸ¿ã‚’å—ã‘ã¾ã™ã€‚"
msgid "ciReport|%{remainingPackagesCount} more"
-msgstr ""
+msgstr "他 %{remainingPackagesCount} 件"
msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
@@ -9374,7 +11041,7 @@ msgid "ciReport|Class"
msgstr "クラス"
msgid "ciReport|Code quality"
-msgstr ""
+msgstr "コードã®å“質"
msgid "ciReport|Confidence"
msgstr ""
@@ -9386,13 +11053,16 @@ msgid "ciReport|Container scanning detects known vulnerabilities in your docker
msgstr "コンテナスキャンã¯ã€Docker イメージã«å­˜åœ¨ã™ã‚‹æ—¢çŸ¥ã®è„†å¼±æ€§ã‚’検出ã—ã¾ã™ã€‚"
msgid "ciReport|DAST"
+msgstr "DAST"
+
+msgid "ciReport|Dependency Scanning"
msgstr ""
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
-msgstr ""
+msgstr "ä¾å­˜é–¢ä¿‚スキャンã¯ã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã®ä¾å­˜é–¢ä¿‚ã®ä¸­ã®ã€æ—¢çŸ¥ã®è„†å¼±æ€§ã‚’検出ã—ã¾ã™ã€‚"
msgid "ciReport|Dependency scanning"
-msgstr ""
+msgstr "ä¾å­˜é–¢ä¿‚スキャン"
msgid "ciReport|Description"
msgstr "説明"
@@ -9401,13 +11071,19 @@ msgid "ciReport|Dismiss vulnerability"
msgstr "脆弱性を無視ã™ã‚‹"
msgid "ciReport|Dismissed by"
+msgstr "次ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ç„¡è¦–ã•ã‚Œã¾ã—ãŸ"
+
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
-msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgid "ciReport|Download patch"
msgstr ""
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr "動的アプリケーションセキュリティテスト (DAST) ã¯ã€ã‚¦ã‚§ãƒ–アプリケーションã®æ—¢çŸ¥ã®è„†å¼±æ€§ã‚’検出ã—ã¾ã™ã€‚"
+
msgid "ciReport|Failed to load %{reportName} report"
-msgstr ""
+msgstr "%{reportName} レãƒãƒ¼ãƒˆã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "ciReport|File"
msgstr "ファイル"
@@ -9416,63 +11092,63 @@ msgid "ciReport|Fixed:"
msgstr "修正済ã¿:"
msgid "ciReport|Identifiers"
-msgstr ""
+msgstr "識別å­"
msgid "ciReport|Instances"
msgstr "インスタンス"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
-msgstr ""
+msgstr "セキュリティレãƒãƒ¼ãƒˆ (Alpha) ã¨ã®ç›¸äº’作用ã®è©³ç´°ã‚’ã”覧ãã ã•ã„。"
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
-msgstr[0] ""
+msgstr[0] "ライセンス管ç†ã¯ã€ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’ %d 件検出ã—ã¾ã—ãŸã€‚"
msgid "ciReport|License management detected %d new license"
msgid_plural "ciReport|License management detected %d new licenses"
-msgstr[0] ""
+msgstr[0] "ライセンス管ç†ã¯ã€æ–°ãŸãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’ %d 件検出ã—ã¾ã—ãŸã€‚"
msgid "ciReport|License management detected no licenses for the source branch only"
-msgstr ""
+msgstr "ライセンス管ç†ã¯ã€ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’検出ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "ciReport|License management detected no new licenses"
-msgstr ""
+msgstr "ライセンス管ç†ã«ã‚ˆã£ã¦ã€æ–°ãŸãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’検出ã—ã¾ã›ã‚“ã§ã—ãŸ"
msgid "ciReport|Links"
msgstr "リンク"
msgid "ciReport|Loading %{reportName} report"
-msgstr ""
+msgstr "%{reportName} レãƒãƒ¼ãƒˆã‚’読ã¿è¾¼ã‚“ã§ã„ã¾ã™"
msgid "ciReport|Manage licenses"
msgstr ""
msgid "ciReport|Method"
-msgstr ""
+msgstr "メソッド"
msgid "ciReport|Namespace"
msgstr "åå‰ç©ºé–“"
msgid "ciReport|No changes to code quality"
-msgstr ""
+msgstr "コードå“質ã«å¤‰æ›´ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "ciReport|No changes to performance metrics"
-msgstr ""
+msgstr "パーフォーマンスメトリクスã«å¤‰æ›´ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "ciReport|Performance metrics"
-msgstr ""
+msgstr "パフォーマンスメトリクス"
msgid "ciReport|Revert dismissal"
-msgstr ""
+msgstr "無視ã®å–り消ã—"
msgid "ciReport|SAST"
-msgstr ""
+msgstr "SAST"
msgid "ciReport|Security scanning"
-msgstr ""
+msgstr "セキュリティスキャン"
msgid "ciReport|Security scanning failed loading any results"
-msgstr ""
+msgstr "セキュリティスキャンã¯çµæžœã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "ciReport|Severity"
msgstr "é‡è¦åº¦"
@@ -9481,7 +11157,7 @@ msgid "ciReport|Solution"
msgstr ""
msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
-msgstr ""
+msgstr "é™çš„アプリケーションセキュリティテスト(SAST)ã¯ã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ä¸­ã®æ—¢çŸ¥ã®è„†å¼±æ€§ã‚’検出ã—ã¾ã™ã€‚"
msgid "ciReport|There was an error creating the issue. Please try again."
msgstr "課題を作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -9502,7 +11178,7 @@ msgid "ciReport|There was an error loading dependency scanning report"
msgstr "ä¾å­˜é–¢ä¿‚スキャンレãƒãƒ¼ãƒˆã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "ciReport|There was an error reverting the dismissal. Please try again."
-msgstr ""
+msgstr "無視ã®å–り消ã—中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "%{name} ã‚’ %{version} ã‹ã‚‰ %{fixed} ã¸ã‚¢ãƒƒãƒ—グレードã—ã¦ãã ã•ã„。"
@@ -9512,19 +11188,22 @@ msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
msgstr[0] ""
msgid "ciReport|View full report"
-msgstr ""
+msgstr "レãƒãƒ¼ãƒˆå…¨ä½“を見る"
msgid "ciReport|on pipeline"
-msgstr ""
+msgstr "パイプライン"
msgid "command line instructions"
msgstr "コマンドライン"
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgid "commented on %{link_to_project}"
msgstr ""
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr "ã‚ãªãŸã¯å…¬é–‹è¨­å®šã«å¤‰æ›´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯<strong>ã™ã¹ã¦ã®äºº</strong> ãŒé–²è¦§å¯èƒ½ã«ãªã‚Šã€èª²é¡Œã«å¯¾ã—ã¦ã‚³ãƒ¡ãƒ³ãƒˆã‚’残ã™ã“ã¨ãŒã§ãるよã†ã«ãªã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚"
+
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
+msgstr "ã‚ãªãŸã¯å…¬é–‹è¨­å®šã«å¤‰æ›´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯ãƒãƒ¼ãƒ ã«é™å®šã—ã¦ã„ãŸ<strong>最å°é™ã®å ±å‘Šæ¨©é™</strong>ã‚’ãªãã—ã€èª²é¡Œã«å¯¾ã—ã¦ã‚³ãƒ¡ãƒ³ãƒˆã‚’残ã™ã“ã¨ãŒã§ãるよã†ã«ãªã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚"
msgid "connecting"
msgstr "接続中"
@@ -9539,14 +11218,21 @@ msgid "day"
msgid_plural "days"
msgstr[0] "æ—¥"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr "デプロイトークン"
msgid "disabled"
msgstr "無効"
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+
msgid "done"
-msgstr ""
+msgstr "完了"
msgid "draft"
msgid_plural "drafts"
@@ -9555,6 +11241,15 @@ msgstr[0] ""
msgid "enabled"
msgstr "有効"
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} コマンドã§è¦‹ç©æ™‚é–“ã‚’æ›´æ–°ã§ãã¾ã™ã€‚"
@@ -9564,24 +11259,42 @@ msgstr "ã“ã®ãƒ—ロジェクトã§ã¯"
msgid "from"
msgstr ""
-msgid "help"
+msgid "group"
msgstr ""
+msgid "help"
+msgstr "ヘルプ"
+
msgid "here"
+msgstr "ã“ã“"
+
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr "インãƒãƒ¼ãƒˆä¸­"
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
-msgstr[0] ""
+msgstr[0] "インスタンスãŒå®Œäº†ã—ã¾ã—ãŸ"
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -9592,28 +11305,61 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
+msgstr "課題ボード"
+
+msgid "it is stored externally"
msgstr ""
-msgid "latest deployment"
+msgid "it is stored in LFS"
msgstr ""
-msgid "latest version"
+msgid "it is too large"
msgstr ""
-msgid "license management"
+msgid "latest"
msgstr ""
+msgid "latest deployment"
+msgstr "最新ã®ãƒ‡ãƒ—ロイ"
+
+msgid "latest version"
+msgstr "最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
+
+msgid "license management"
+msgstr "ライセンス管ç†"
+
msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr "%{path_lock_user_name} ã«ã‚ˆã£ã¦ %{created_at} ã«ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
+
+msgid "manual"
msgstr ""
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "マージリクエスト"
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "ブランãƒã‚’復元ã™ã‚‹ã‹ã€åˆ¥ã® %{missingBranchName} ブランãƒã‚’使用ã—ã¦ãã ã•ã„"
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr "%{metricsLinkStart} メモリ %{metricsLinkEnd} 使用率㌠%{memoryFrom} MBã‹ã‚‰ %{memoryTo} MB㸠%{emphasisStart} 減少 %{emphasisEnd}"
@@ -9629,14 +11375,14 @@ msgstr "承èªã‚’追加"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "ターゲットブランãƒã«ãƒžãƒ¼ã‚¸ã§ãるメンãƒãƒ¼ã‹ã‚‰ã®ã‚³ãƒŸãƒƒãƒˆã‚’許å¯ã™ã‚‹"
-msgid "mrWidget|An error occured while removing your approval."
-msgstr "承èªã‚’削除中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
-msgstr ""
+msgstr "承èªã‚’é€ä¿¡ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "mrWidget|Approve"
msgstr "承èª"
@@ -9660,7 +11406,7 @@ msgid "mrWidget|Cherry-pick this merge request in a new merge request"
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ãƒã‚§ãƒªãƒ¼ãƒ”ックã—ã¦ã€æ–°ã—ã„マージリクエストを作æˆã™ã‚‹"
msgid "mrWidget|Closed"
-msgstr ""
+msgstr "クローズ済ã¿"
msgid "mrWidget|Closed by"
msgstr "クローズ作業者"
@@ -9671,9 +11417,12 @@ msgstr "クローズ"
msgid "mrWidget|Create an issue to resolve them later"
msgstr "ã‚ã¨ã§è§£æ±ºã™ã‚‹ãŸã‚ã«èª²é¡Œã‚’作æˆã™ã‚‹"
-msgid "mrWidget|Deployment statistics are not available currently"
+msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr "デプロイ統計ã¯ç¾åœ¨åˆ©ç”¨ã§ãã¾ã›ã‚“"
+
msgid "mrWidget|Did not close"
msgstr "クローズã—ãªã‹ã£ãŸ"
@@ -9708,7 +11457,7 @@ msgid "mrWidget|Merge locally"
msgstr "ローカルã§ãƒžãƒ¼ã‚¸"
msgid "mrWidget|Merge request approved"
-msgstr ""
+msgstr "マージリクエストãŒæ‰¿èªã•ã‚Œã¾ã—ãŸ"
msgid "mrWidget|Merge request approved; you can approve additionally"
msgstr ""
@@ -9729,7 +11478,7 @@ msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a
msgstr ""
msgid "mrWidget|Plain diff"
-msgstr ""
+msgstr "プレーン差分"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -9743,12 +11492,6 @@ msgstr "ã™ãã«æ›´æ–°"
msgid "mrWidget|Refreshing now"
msgstr "更新中"
-msgid "mrWidget|Remove Source Branch"
-msgstr "ソースブランãƒã‚’削除"
-
-msgid "mrWidget|Remove source branch"
-msgstr "ソースブランãƒã‚’削除ã™ã‚‹"
-
msgid "mrWidget|Remove your approval"
msgstr "承èªã‚’削除ã™ã‚‹"
@@ -9757,11 +11500,11 @@ msgstr "マージをリクエスト"
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
+msgstr[0] "もㆠ%d 件ã®æ‰¿èªãŒå¿…è¦ã§ã™"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
+msgstr[0] "もㆠ%d 件ã®æ‰¿èªãŒå¿…è¦ã§ã™"
msgid "mrWidget|Resolve conflicts"
msgstr "競åˆã‚’解決ã™ã‚‹"
@@ -9788,25 +11531,25 @@ msgid "mrWidget|The changes will be merged into"
msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã™"
msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr ""
+msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ãƒ‘イプラインãŒå¤±æ•—ã—ã¾ã—ãŸã€‚ジョブをå†è©¦è¡Œã™ã‚‹ã‹ã€æ–°ã—ãコミットã—ã¦å¤±æ•—を修正ã—ã¦ãã ã•ã„"
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
-msgstr ""
+msgstr "ソースブランãƒã® HEAD ãŒæœ€è¿‘変更ã•ã‚Œã¾ã—ãŸã€‚ページをå†èª­ã¿è¾¼ã¿ã—ã¦ãƒžãƒ¼ã‚¸å‰ã«å¤‰æ›´ã‚’確èªã—ã¦ãã ã•ã„"
-msgid "mrWidget|The source branch has been removed"
-msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
-msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã‚ˆã†ã¨ã—ã¦ã„ã¾ã™"
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
-msgid "mrWidget|The source branch will be removed"
-msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã¾ã™"
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
-msgid "mrWidget|The source branch will not be removed"
-msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã¾ã›ã‚“"
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "マージã®ç«¶åˆãŒã‚ã‚Šã¾ã™"
@@ -9814,6 +11557,9 @@ msgstr "マージã®ç«¶åˆãŒã‚ã‚Šã¾ã™"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "未解決ã®æ¤œè¨ŽãŒã‚ã‚Šã¾ã™ã€‚ã“れらã®æ¤œè¨Žã‚’解決ã—ã¦ãã ã•ã„。"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯è‡ªå‹•çš„ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
@@ -9826,12 +11572,12 @@ msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€æ›¸ã
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’手動ã§ãƒžãƒ¼ã‚¸ã§ãã¾ã™"
-msgid "mrWidget|You can remove source branch now"
-msgstr ""
-
msgid "mrWidget|branch does not exist."
msgstr "ブランãƒãŒå­˜åœ¨ã—ã¾ã›ã‚“。"
@@ -9850,9 +11596,21 @@ msgstr ""
msgid "new merge request"
msgstr "æ–°è¦ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "メール通知"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr "ã¾ãŸã¯"
@@ -9870,18 +11628,27 @@ msgstr "パスワード"
msgid "personal access token"
msgstr "個人ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³"
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr "秘密éµãŒè¨¼æ˜Žæ›¸ã¨ä¸€è‡´ã—ã¾ã›ã‚“。"
msgid "project"
msgid_plural "projects"
-msgstr[0] ""
+msgstr[0] "プロジェクト"
+
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
msgid "remaining"
msgstr "残り"
msgid "remove"
-msgstr ""
+msgstr "消去"
msgid "remove due date"
msgstr "期é™ã‚’削除"
@@ -9889,17 +11656,44 @@ msgstr "期é™ã‚’削除"
msgid "remove weight"
msgstr "ウェイトを削除"
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
-msgstr[0] ""
+msgstr[0] "返信"
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
msgid "source"
msgstr "ソース"
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} ã¯ç´¯è¨ˆçµŒéŽæ™‚é–“ã‚’æ›´æ–°ã—ã¾ã™"
msgid "started"
+msgstr "開始"
+
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
msgstr ""
msgid "this document"
@@ -9908,7 +11702,10 @@ msgstr "ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9917,9 +11714,15 @@ msgstr "ユーザーå"
msgid "uses Kubernetes clusters to deploy your code!"
msgstr "コードをデプロイã™ã‚‹ãŸã‚ã« Kubernetes クラスターを使用ã™ã‚‹ã€‚"
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "GitLab ã§è¦‹ã‚‹"
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "%{additions} 件ã®è¿½åŠ ã¨ %{deletions} 件ã®å‰Šé™¤ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -9927,3 +11730,6 @@ msgid "within %d minute "
msgid_plural "within %d minutes "
msgstr[0] "%d 分以内"
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 22a6ce3b7d8..369ca42cb2f 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:17\n"
+"PO-Revision-Date: 2019-02-11 10:21\n"
msgid " Status"
msgstr " ìƒíƒœ"
@@ -29,16 +29,17 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] " %d í¬ì¸íŠ¸ í–¥ìƒ"
-msgid "\"%{query}\" in projects"
-msgstr "프로ì íŠ¸ì—ì„œ \"%{query}\""
+msgid " or "
+msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] "%dê°œì˜ ë³€ê²½ëœ íŒŒì¼"
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr "프로ì íŠ¸ì—ì„œ \"%{query}\""
msgid "%d commit"
msgid_plural "%d commits"
@@ -48,9 +49,8 @@ msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] "%d 커밋 behind"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] "%dê°œ ì‚­ì œë¨"
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -68,6 +68,10 @@ msgid "%d issue"
msgid_plural "%d issues"
msgstr[0] "%d ì´ìŠˆ"
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d ë ˆì´ì–´"
@@ -107,9 +111,12 @@ msgstr "%{counter_storage} (%{counter_repositories} 저장소, %{counter_build_a
msgid "%{count} %{alerts}"
msgstr "%{count} %{alerts}"
-msgid "%{count} more assignees"
+msgid "%{count} more"
msgstr ""
+msgid "%{count} more assignees"
+msgstr "%{count}ëª…ì˜ ë‹´ë‹¹ìž"
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} ëª…ì˜ ì°¸ì—¬ìž"
@@ -124,12 +131,18 @@ msgstr "%{filePath} ì‚­ì œë¨"
msgid "%{firstLabel} +%{labelCount} more"
msgstr "%{firstLabel} +%{labelCount} ë”보기"
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}그룹%{group_docs_link_end}ì„ ì‚¬ìš©í•˜ë©´ 여러 프로ì íŠ¸ë¥¼ 관리하고 ê³µë™ ìž‘ì—…ì„ ìˆ˜í–‰ í•  수 있습니다. 그룹 회ì›ì€ 모든 프로ì íŠ¸ì— 액세스 í•  수 있습니다."
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType}ì´ ì‚­ì œë©ë‹ˆë‹¤! 확실합니까?"
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 시작ë¨"
@@ -139,9 +152,6 @@ msgstr "%{lock_path} 경로는 GitLab User %{lock_user_id} ì— ì˜í•´ 잠겼습ë
msgid "%{name}'s avatar"
msgstr "%{name} ì˜ ì•„ë°”íƒ€"
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} ì€ ì»¤ìŠ¤í…€ ë„ë©”ì¸ ëŒ€ì‹  사용할 수 있습니다."
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{default_branch} 로부터 %{number_commits_behind} commits behind, %{number_commits_ahead} commits ahead"
@@ -151,6 +161,24 @@ msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% 완료"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text} %{files} 파ì¼"
@@ -167,12 +195,21 @@ msgstr "%{unstaged} ê±´ì´ ìŠ¤í…Œì´ì§•ë˜ì§€ 않았고, %{staged} ê±´ì´ ìŠ¤í…Œ
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "GitLab Inc와 공유ë˜ëŠ” ì •ë³´ì— ëŒ€í•´ %{usage_ping_link_start}ë” ì•Œì•„ë³´ê¸°%{usage_ping_link_end}"
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr "+ %{count} ë”보기"
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} ë”"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr "- Runner ê°€ 활성화ë˜ì—ˆê³ , 새로운 ìž‘ì—…ì„ ì²˜ë¦¬í•  수 있습니다."
@@ -229,11 +266,14 @@ msgstr[0] "%dëª…ì˜ ì‚¬ìš©ìž"
msgid "1st contribution!"
msgstr "첫번째 기여!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "2FA 사용"
-msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "ê¶Œí•œì„ ì–»ìœ¼ë ¤ë©´ GitLab 관리ìžì—게 문ì˜í•˜ì‹­ì‹œì˜¤."
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
msgid "403|You don't have the permission to access this page."
msgstr "ì´ íŽ˜ì´ì§€ì— 대한 액세스 ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
@@ -272,10 +312,10 @@ msgid "<strong>%{group_name}</strong> group members"
msgstr "<strong>%{group_name}</strong> 그룹 멤버"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
-msgstr ""
+msgstr "<strong>%{pushes}</strong> íšŒì˜ í‘¸ì‹œ, <strong>%{commits}</strong> 회 ì´ìƒì˜ ì»¤ë°‹ì´ <strong>%{people}</strong> 기여ìžì— ì˜í•´ ì¼ì–´ 났습니다. "
-msgid "<strong>Removes</strong> source branch"
-msgstr "소스 브랜치 <strong>제거</strong>"
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "'러너(Runner)'는 ìž‘ì—…ì„ ì‹¤í–‰í•˜ëŠ” 프로세스입니다. 필요한 ë§Œí¼ ëŸ¬ë„ˆë¥¼ ì…‹ì—…í•  수 있습니다."
@@ -290,7 +330,7 @@ msgid "A deleted user"
msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr ""
+msgstr "GitLabì˜ ì‚¬ì´ë²„ í­ë ¥ ë°©ì§€íŒ€ì´ ìµœëŒ€í•œ 빨리 ê·€í•˜ì˜ ë¦¬í¬íŠ¸ë¥¼ 검토 í•  것 입니다."
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "í¬í¬ì™€ 새 머지 리퀘스트(MR)ê°€ 시작ë˜ë©´ 새로운 브랜치가 만들어질 것입니다."
@@ -322,6 +362,9 @@ msgstr "오남용 리í¬íŠ¸"
msgid "Abuse reports"
msgstr "악용 사례 보고서"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr "약관ë™ì˜"
@@ -358,38 +401,41 @@ msgstr "활ë™"
msgid "Add"
msgstr "추가"
-msgid "Add Changelog"
-msgstr "변경 로그 추가"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "기여 ê°€ì´ë“œ 추가"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "그룹 Webhooks ë° GitLab Enterprise Editionì„ ì¶”ê°€"
msgid "Add Jaeger URL"
-msgstr ""
+msgstr "Jaeger URL 추가"
msgid "Add Kubernetes cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 추가"
-msgid "Add Readme"
-msgstr "Readme 추가"
+msgid "Add README"
+msgstr ""
-msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr "프로ì íŠ¸ì— 관한 ì •ë³´ê°€ 담긴 홈페ì´ì§€ë¥¼ wikiì— ì¶”ê°€í•˜ë©´ GitLabì´ ë©”ì‹œì§€ 대신 ì—¬ê¸°ì— í‘œì‹œ 합니다."
+
msgid "Add a table"
-msgstr ""
+msgstr "í…Œì´ë¸” 추가"
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "모든 ì´ë©”ì¼ì— í‘œì‹œë  í…스트를 추가합니다. %{character_limit} ìž ì œí•œì´ ìžˆìŠµë‹ˆë‹¤."
msgid "Add comment now"
-msgstr ""
+msgstr "댓글 추가"
msgid "Add image comment"
-msgstr ""
+msgstr "ì´ë¯¸ì§€ 댓글 추가"
msgid "Add license"
msgstr "ë¼ì´ì„ ìŠ¤ 추가"
@@ -401,20 +447,26 @@ msgid "Add new directory"
msgstr "새 디렉토리 추가"
msgid "Add projects"
-msgstr ""
+msgstr "프로ì íŠ¸ 추가"
msgid "Add reaction"
msgstr "ë°˜ì‘ ì¶”ê°€"
-msgid "Add to review"
+msgid "Add to project"
msgstr ""
+msgid "Add to review"
+msgstr "리뷰 추가"
+
msgid "Add todo"
msgstr "í•  ì¼ ì¶”ê°€"
msgid "Add user(s) to the group:"
msgstr "ê·¸ë£¹ì— ì‚¬ìš©ìž ì¶”ê°€:"
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr "ê·¸ë£¹ì— ì‚¬ìš©ìž ì¶”ê°€"
@@ -430,9 +482,6 @@ msgstr "ê´€ë¦¬ìž ì˜ì—­"
msgid "Admin Overview"
msgstr "ê´€ë¦¬ìž ê°œìš”"
-msgid "Admin area"
-msgstr "ê´€ë¦¬ìž ì˜ì—­"
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "%{username}ì„ ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ìŠˆ, 머지 리퀘스트(MR) ë° ì—°ê²°ëœ ê·¸ë£¹ì´ \"Ghost-user\"으로 변경ë©ë‹ˆë‹¤. ë°ì´í„° ì†ì‹¤ì„ 방지하기 위해 %{strong_start}차단 사용ìž%{strong_end} ê¸°ëŠ¥ì„ ì‚¬ìš©í•´ë³´ì„¸ìš”. %{strong_start}ì‚¬ìš©ìž ì‚­ì œ%{strong_end}ì‹œ ë˜ëŒë¦¬ê±°ë‚˜, 복구할 수 없습니다."
@@ -455,7 +504,7 @@ msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs
msgstr "모든 ìž‘ì—…ì„ ì¤‘ì§€í•©ë‹ˆë‹¤. 현재 ì‹¤í–‰ì¤‘ì¸ ëª¨ë“  ìž‘ì—…ì´ ì¤‘ì§€ë©ë‹ˆë‹¤."
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr "%{projectName}프로ì íŠ¸, 저장소 ë° ë¬¸ì œ, 병합 요청 ë“±ì„ í¬í•¨í•œ 모든 관련 리소스를 ì˜êµ¬ížˆ 삭제하려고합니다. 확ì¸í•˜ê³  %{strong_start}프로ì íŠ¸ ì‚­ì œ%{strong_end}를 누르면 실행 취소 ë˜ëŠ” 복구를 í•  수 없습니다."
+msgstr "%{projectName}프로ì íŠ¸, 저장소 ë° ë¬¸ì œ, 머지 리퀘스트(MR) ë“±ì„ í¬í•¨í•œ 모든 관련 리소스를 ì˜êµ¬ížˆ 삭제하려고합니다. 확ì¸í•˜ê³  %{strong_start}프로ì íŠ¸ ì‚­ì œ%{strong_end}를 누르면 실행 취소 ë˜ëŠ” 복구를 í•  수 없습니다."
msgid "AdminProjects|Delete"
msgstr "삭제"
@@ -466,12 +515,42 @@ msgstr "%{projectName} 프로ì íŠ¸ë¥¼ 삭제하시겠습니까?"
msgid "AdminProjects|Delete project"
msgstr "프로ì íŠ¸ ì‚­ì œ"
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "모든 프로ì íŠ¸ì˜ ìžë™ 앱 리뷰 ë° ìžë™ ë°°í¬ ë‹¨ê³„ì—ì„œ 기본ì ìœ¼ë¡œ 사용할 ë„ë©”ì¸ì„ 지정하십시오."
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "ì‚¬ìš©ìž ì°¨ë‹¨"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr " ì‚¬ìš©ìž %{username}와 기여를 삭제하시겠습니까?"
@@ -484,21 +563,54 @@ msgstr "ì‚¬ìš©ìž ì‚­ì œ"
msgid "AdminUsers|Delete user and contributions"
msgstr "사용ìžì™€ 기여 ì‚­ì œ"
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "확ì¸ì„ 위해 %{projectName} 를 입력해주세요."
msgid "AdminUsers|To confirm, type %{username}"
msgstr "확ì¸ì„ 위해 %{username} ì„ ìž…ë ¥í•˜ì„¸ìš”"
-msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgid "AdminUsers|User will be blocked"
msgstr ""
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr "고급 사용 권한, 대용량 íŒŒì¼ ì €ìž¥ì†Œì™€ ì´ì¤‘-ì¸ì¦ 설정"
+
msgid "Advanced settings"
msgstr "고급 설정"
msgid "Alert"
msgid_plural "Alerts"
-msgstr[0] ""
+msgstr[0] "알림"
+
+msgid "Alerts"
+msgstr ""
msgid "All"
msgstr "ì „ì²´"
@@ -509,38 +621,47 @@ msgstr "모든 ë³€ê²½ì‚¬í•­ì´ ì»¤ë°‹ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "모든 ê¸°ëŠ¥ì€ ë¹„ì–´ìžˆëŠ” 프로ì íŠ¸, 템플릿, 가져올 ë•Œ 사용할 수 있지만 ë‚˜ì¤‘ì— í”„ë¡œì íŠ¸ 설정ì—ì„œ 비활성화 í•  수 있습니다."
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr "모든 사용ìž"
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜ì— ë¨¸ì§€í•  수 있는 ë©¤ë²„ì˜ ì»¤ë°‹ì„ í—ˆìš©í•©ë‹ˆë‹¤."
msgid "Allow projects within this group to use Git LFS"
-msgstr ""
+msgstr "ì´ ê·¸ë£¹ì˜ í”„ë¡œì íŠ¸ë“¤ì´ Git LFS를 사용하ë„ë¡ í—ˆìš©"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
-msgstr ""
+msgstr "출력 로그 ë° ì•„í‹°íŒ©íŠ¸ë¥¼ í¬í•¨í•˜ì—¬ 파ì´í”„ ë¼ì¸ ë° ìž‘ì—… 세부 ì •ë³´ì— ëŒ€í•œ 공용 액세스 허용"
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
-msgstr ""
+msgstr "Asciidoc 문서ì—ì„œ PlantUML 다ì´ì–´ê·¸ëž¨ ë Œë”ë§ì„ 허용합니다."
msgid "Allow requests to the local network from hooks and services."
msgstr "후í¬ì™€ 서비스ì—ì„œ 로컬 네트워í¬ì— 대한 ìš”ì²­ì„ í—ˆìš©í•©ë‹ˆë‹¤."
msgid "Allow users to request access"
-msgstr ""
+msgstr "사용ìžê°€ 액세스를 요청하ë„ë¡ í—ˆìš©"
msgid "Allow users to request access if visibility is public or internal."
+msgstr "가시성 í¼ë¸”릭 ë˜ëŠ” ì¸í„°ë„ ì¼ ê²½ìš° 사용ìžê°€ 액세스를 요청 í•  수 있습니다."
+
+msgid "Allowed to fail"
msgstr ""
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 추가하고 관리 í•  수 ​​있습니다."
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
-msgstr ""
+msgstr "\"issuer\" ë˜ëŠ” \"Relying party trust identifier\" ë¼ê³ ë„ 합니다."
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
-msgstr ""
+msgstr "\"Relying party service URL\" ë˜ëŠ” \"Reply URL\"ì´ë¼ê³ ë„ 합니다."
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "대신, %{personal_access_token_link} (ì„) 를 사용할 수 있습니다. ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ ìƒì„±í•  ë•Œ, <code>저장소</code> 범위를 ì„ íƒí•˜ë©´ ì—°ê²°ì´ ê°€ëŠ¥í•œ 공개, 비공개 저장소를 표시할 수 있습니다."
@@ -549,7 +670,7 @@ msgid "Alternatively, you can use a %{personal_access_token_link}. When you crea
msgstr "대신, %{personal_access_token_link} (ì„) 를 사용할 수 있습니다. ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ ìƒì„±í•  ë•Œ, <code>저장소</code> 범위를 ì„ íƒí•´ì•¼ 가져오기가 가능한 공개, 비공개 저장소를 표시할 수 있습니다."
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
-msgstr ""
+msgstr "사용ìžê°€ 다중 ì¸ì¦ì„ 강제로 구성해야 í•  ì‹œê°„ì„ ê±´ë„ˆ 뛸 수있는 기간 (시간)"
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr "ì–‘ì‹ì„ 제출하면 SSH 키가 ìžë™ìœ¼ë¡œ ìƒì„±ë©ë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ ë¬¸ì„œë¥¼ 참조하십시오."
@@ -558,48 +679,21 @@ msgid "An application called %{link_to_client} is requesting access to your GitL
msgstr "%{link_to_client} ì´ë¼ëŠ” ì‘ìš© í”„ë¡œê·¸ëž¨ì´ GitLab ê³„ì •ì— ëŒ€í•œ 액세스를 요청하고 있습니다."
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
-msgstr ""
-
-msgid "An error accured whilst committing your changes."
-msgstr "변경 커밋 ì¤‘ì— ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgstr "비어 있는 GitLab User 필드는 FogBugzì˜ ì‚¬ìš©ìž ì „ì²´ ì´ë¦„ (예 : By í™ ê¸¸ë™)ì„ ì´ìŠˆ ë° ì»¤ë§¨íŠ¸ì˜ ì„¤ëª…ìœ¼ë¡œ 추가 합니다. ë˜í•œ ì´ ì´ìŠˆì™€ 커맨트를 프로ì íŠ¸ 작성ìžì— 알리고 할당 í•  것입니다."
msgid "An error has occurred"
msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-msgid "An error occured creating the new branch."
-msgstr "새 브랜치를 만드는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
-msgid "An error occured whilst fetching the job trace."
-msgstr "작업를 가져오는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
-msgid "An error occured whilst fetching the latest pipeline."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
-msgid "An error occured whilst loading all the files."
-msgstr "모든 파ì¼ì„ 로드하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
-msgid "An error occured whilst loading the file content."
-msgstr "íŒŒì¼ ë‚´ìš©ì„ ë¡œë“œí•˜ëŠ” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
-msgid "An error occured whilst loading the file."
-msgstr "파ì¼ì„ 로드하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr "머지 리퀘스트(MR) ë³€ê²½ì‚¬í•­ì„ ê°€ì ¸ì˜¤ëŠ” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr "머지 리퀘스트(MR) 버전 ë°ì´í„°ë¥¼ 로드하는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
-msgid "An error occured whilst loading the merge request."
-msgstr "머지 리퀘스트(MR)를 로드하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
-msgid "An error occured whilst loading the pipelines jobs."
-msgstr "파ì´í”„ë¼ì¸ ìž‘ì—…ì„ ê°€ì ¸ì˜¤ëŠ” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
msgid "An error occurred adding a draft to the discussion."
-msgstr ""
+msgstr "í† ë¡ ì— ì´ˆì•ˆì„ ì¶”ê°€í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred adding a new draft."
+msgstr "새 드래프트를 추가하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
+msgid "An error occurred creating the new branch."
msgstr ""
msgid "An error occurred previewing the blob"
@@ -615,7 +709,7 @@ msgid "An error occurred while adding approver"
msgstr "승ì¸ìžë¥¼ ì¶”ê°€í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "An error occurred while deleting the comment"
-msgstr ""
+msgstr "ëŒ“ê¸€ì„ ì‚­ì œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while detecting host keys"
msgstr "호스트 í‚¤ë“¤ì„ ì‚­ì œí•˜ë˜ ì¤‘ 오류가 ë°œìƒ í–ˆìŠµë‹ˆë‹¤."
@@ -630,7 +724,7 @@ msgid "An error occurred while fetching markdown preview"
msgstr "마í¬ë‹¤ìš´ 미리보기를 가져 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching pending comments"
-msgstr ""
+msgstr "ëŒ“ê¸€ì„ ì—…ë°ì´íŠ¸í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching sidebar data"
msgstr "사ì´ë“œë°” ë°ì´í„°ë¥¼ 가져오는 중 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -657,10 +751,10 @@ msgid "An error occurred while importing project: %{details}"
msgstr "프로ì íŠ¸ë¥¼ ê°€ì ¸ì˜¤ë˜ ì¤‘ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤: %{details}"
msgid "An error occurred while initializing path locks"
-msgstr ""
+msgstr "경로 ìž ê¸ˆì„ ì´ˆê¸°í™”í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "An error occurred while loading chart data"
-msgstr ""
+msgstr "차트 ë°ì´í„°ë¥¼ ë¡œë“œí•˜ë˜ ë„중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while loading commit signatures"
msgstr "커밋 시그너ì³ë¥¼ 불러오는 ë„ì¤‘ì— ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -674,10 +768,19 @@ msgstr "íŒŒì¼ ì´ë¦„ì„ ë¡œë“œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while loading the file"
msgstr "íŒŒì¼ ë¡œë“œ 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr "ìš”ì²­ì„ ìƒì„±í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while removing approver"
+msgstr "승ì¸ìžë¥¼ 삭제하는 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
msgstr ""
msgid "An error occurred while rendering KaTeX"
@@ -693,7 +796,7 @@ msgid "An error occurred while retrieving diff"
msgstr "ì°¨ì´ì ì„ 가져오는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
+msgstr "LDAP 무시 ìƒíƒœë¥¼ 저장하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하십시오."
msgid "An error occurred while saving assignees"
msgstr "담당ìžë¥¼ 저장하는 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -705,17 +808,62 @@ msgid "An error occurred while unsubscribing to notifications."
msgstr "알림 구ë…ì„ í•´ì œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while updating the comment"
-msgstr ""
+msgstr "ëŒ“ê¸€ì„ ì—…ë°ì´íŠ¸í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while validating username"
msgstr "ì‚¬ìš©ìž ì´ë¦„ì„ í™•ì¸í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•´ 주세요."
-msgid "Analytics"
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
msgstr ""
+msgid "Analytics"
+msgstr "분ì„"
+
msgid "Anonymous"
msgstr "ìµëª…"
@@ -735,7 +883,7 @@ msgid "Application"
msgstr "어플리케ì´ì…˜"
msgid "Application ID"
-msgstr ""
+msgstr "애플리케ì´ì…˜ ID"
msgid "Application: %{name}"
msgstr "애플리케ì´ì…˜: %{name}"
@@ -743,6 +891,21 @@ msgstr "애플리케ì´ì…˜: %{name}"
msgid "Applications"
msgstr "어플리케ì´ì…˜"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "4ì›”"
@@ -755,21 +918,36 @@ msgstr "ë³´ê´€ëœ í”„ë¡œì íŠ¸! 저장소 ë° ê¸°íƒ€ 프로ì íŠ¸ 리소스는 ì
msgid "Archived projects"
msgstr "ì•„ì¹´ì´ë¸Œëœ 프로ì íŠ¸"
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ì´ íŒŒì´í”„ë¼ì¸ ìŠ¤ì¼€ì¥´ì„ ì‚­ì œ 하시겠습니까?"
msgid "Are you sure you want to erase this build?"
-msgstr ""
+msgstr "ì •ë§ë¡œ ì´ ë¹Œë“œë¥¼ 지우시겠습니까?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "저장ë˜ì§€ ì•Šì€ ë³€ê²½ì‚¬í•­ì„ ì‚­ì œí•˜ê² ìŠµë‹ˆê¹Œ?"
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr "공개키를 재ìƒì„±í•˜ì‹œê² ìŠµë‹ˆê¹Œ? 미러ë§ì´ 다시 ë™ìž‘하기 위해서 remote ì„œë²„ì˜ ê³µê°œí‚¤ë¥¼ ì—…ë°ì´íŠ¸í•´ì•¼ í•  것입니다."
+
msgid "Are you sure you want to remove %{group_name}?"
msgstr "ì •ë§ë¡œ %{group_name}(ì„)를 ì‚­ì œ 하시겠습니까?"
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr "ì •ë§ë¡œ 해당 í•­ëª©ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
@@ -780,16 +958,19 @@ msgid "Are you sure you want to reset the health check token?"
msgstr "헬스 ì²´í¬ í† í°ì„ 초기화 하시겠습니까?"
msgid "Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "ì´ í™˜ê²½ì„ ì¤‘ë‹¨í•˜ê¸¸ ì›í•˜ë‚˜ìš”?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "ì •ë§ë¡œ %{path_lock_path}ì˜ ìž ê¸ˆì„ í•´ì œ 하시겠습니까?"
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "확실합니까?"
msgid "Artifact ID"
-msgstr ""
+msgstr "결과물 ID"
msgid "Artifacts"
msgstr "결과물"
@@ -801,6 +982,9 @@ msgid "Ask your group maintainer to set up a group Runner."
msgstr "그룹 관리ìžì—게 그룹 Runner 를 설정하ë„ë¡ ìš”ì²­í•˜ì„¸ìš”"
msgid "Assertion consumer service URL"
+msgstr "문제 알림 ì†Œë¹„ìž ì„œë¹„ìŠ¤ URL"
+
+msgid "Assets"
msgstr ""
msgid "Assign custom color like #FF0000"
@@ -812,9 +996,12 @@ msgstr "ë¼ë²¨ 지정"
msgid "Assign milestone"
msgstr "마ì¼ìŠ¤í†¤ 지정"
-msgid "Assign to"
+msgid "Assign some issues to this milestone."
msgstr ""
+msgid "Assign to"
+msgstr "담당ìž"
+
msgid "Assigned Issues"
msgstr "í• ë‹¹ëœ ì´ìŠˆ"
@@ -822,7 +1009,7 @@ msgid "Assigned Merge Requests"
msgstr "í• ë‹¹ëœ ë¨¸ì§€ 리퀘스트(MR)"
msgid "Assigned to :name"
-msgstr ""
+msgstr "할당 ëŒ€ìƒ :ì´ë¦„"
msgid "Assigned to me"
msgstr "나ì—게 할당 ë¨"
@@ -839,11 +1026,14 @@ msgstr "ë‹´ë‹¹ìž ëª©ë¡ì€ ì„ íƒëœ 사용ìžì—게 할당 ëœ ëª¨ë“  ì´ìŠˆê°
msgid "Assignee(s)"
msgstr "담당ìž"
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "드래그 &amp; 드롭 ë˜ëŠ” %{upload_link}"
msgid "Audit Events"
-msgstr ""
+msgstr "ê°ì‚¬ ì´ë²¤íŠ¸"
msgid "Aug"
msgstr "8ì›”"
@@ -851,6 +1041,9 @@ msgstr "8ì›”"
msgid "August"
msgstr "8ì›”"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "ì¸ì¦ 로그"
@@ -866,6 +1059,9 @@ msgstr "작성ìž"
msgid "Authorization code:"
msgstr "ì¸ì¦ 코드:"
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr "ì‘ìš© í”„ë¡œê·¸ëž¨ì— ì‚¬ìš©ìž ì´ë¦„ê³¼ 암호를 입력하여 ê¶Œí•œì´ ë¶€ì—¬ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -893,17 +1089,8 @@ msgstr "ìžë™ DevOps 활성화ë¨"
msgid "Auto DevOps, runners and job artifacts"
msgstr "ìžë™ DevOps, Runner ìž‘ì—… artifacts"
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr "Auto Review Apps 와 Auto Deploy ê°€ ì •ìƒ ë™ìž‘하기 위해서는 %{kubernetes} ê°€ 필요합니다."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr "Auto Review Apps 와 Auto Deploy ê°€ ì •ìƒ ë™ìž‘하기 위해서는 ë„ë©”ì¸ ë„¤ìž„ê³¼ %{kubernetes} ê°€ 필요합니다."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "Auto Review Apps 와 Auto Deploy ê°€ ì •ìƒ ë™ìž‘하기 위해서는 ë„ë©”ì¸ ë„¤ìž„ì´ í•„ìš”í•©ë‹ˆë‹¤."
-
msgid "Auto-cancel redundant, pending pipelines"
-msgstr ""
+msgstr "사용ë˜ì§€ 않거나 ë³´ë¥˜ì¤‘ì¸ íŒŒì´í”„ ë¼ì¸ì˜ ìžë™ 취소"
msgid "AutoDevOps|Auto DevOps"
msgstr "Auto DevOps|Auto DevOps"
@@ -933,16 +1120,28 @@ msgid "AutoDevOps|enable Auto DevOps"
msgstr "Auto DevOps 활성화"
msgid "Automatically marked as default internal user"
+msgstr "기본 내부 사용ìžë¡œ ìžë™ 표시"
+
+msgid "Automatically resolved"
msgstr ""
msgid "Available"
msgstr "ì´ìš© 가능"
-msgid "Available group Runners : %{runners}"
-msgstr "사용 가능한 그룹 Runner: %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
-msgid "Available group Runners : %{runners}."
-msgstr "사용 가능한 그룹 Runner: %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr "아바타가 ì‚­ì œë©ë‹ˆë‹¤. 확실합니까?"
@@ -1038,22 +1237,22 @@ msgid "Badges|e.g. %{exampleUrl}"
msgstr "e.g. %{exampleUrl}"
msgid "BatchComments|Delete all pending comments"
-msgstr ""
+msgstr "모든 보류 ì¤‘ì— ìžˆëŠ” 커맨트 ì‚­ì œ"
msgid "BatchComments|Discard review?"
-msgstr ""
+msgstr "리뷰를 취소 하시겠습니까?"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
-msgstr ""
+msgstr "리뷰를 취소하시려고 합니다. 리뷰를 취소 하시면 보류 ì¤‘ì— ìžˆëŠ” 모든 ëŒ“ê¸€ì´ ì‚­ì œë©ë‹ˆë‹¤. %{strong_start} 여기부터%{strong_end} ì—¬ê¸°ê¹Œì§€ì˜ ì‚­ì œëœ ëŒ“ê¸€ì€ ë³µì› í•˜ì‹¤ 수 없습니다."
msgid "Begin with the selected commit"
-msgstr ""
+msgstr "ì„ íƒí•œ 커밋으로 시작"
msgid "Below are examples of regex for existing tools:"
-msgstr ""
+msgstr "다ìŒì€ 기존 ë„êµ¬ì— ëŒ€í•œ ì •ê·œì‹ì˜ 예입니다."
msgid "Below you will find all the groups that are public."
-msgstr ""
+msgstr "공개 ëœ ëª¨ë“  ê·¸ë£¹ì„ ì•„ëž˜ì—ì„œ ì°¾ì„ ìˆ˜ 있습니다."
msgid "Billing"
msgstr "결제"
@@ -1127,6 +1326,12 @@ msgstr "Bitbucket 서버ì—ì„œ 가져 오기"
msgid "Bitbucket import"
msgstr "Bitbucketì—ì„œ 가져오기"
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr "블로그"
@@ -1134,11 +1339,7 @@ msgid "Boards"
msgstr "보드"
msgid "Branch %{branchName} was not found in this project's repository."
-msgstr ""
-
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] "브랜치 (%{branch_count})"
+msgstr "%{branchName} 브랜치는 ì´ í”„ë¡œì íŠ¸ ì €ìž¥ì†Œì— ì—†ìŠµë‹ˆë‹¤."
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "<strong>%{branch_name}</strong> 브랜치가 ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. ìžë™ ë°°í¬ë¥¼ 설정하려면 GitLab CI Yaml í…œí”Œë¦¿ì„ ì„ íƒí•˜ê³  변경 ì‚¬í•­ì„ ì ìš©í•˜ì‹­ì‹œì˜¤. %{link_to_autodeploy_doc}"
@@ -1177,13 +1378,13 @@ msgid "Branches|Compare"
msgstr "비êµ"
msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
-msgstr "'%{default_branch}'ì— ë³‘í•©ëœ ëª¨ë“  브랜치 지우기"
+msgstr "'%{default_branch}'ì— ë¨¸ì§€ëœ ëª¨ë“  브랜치 지우기"
msgid "Branches|Delete branch"
msgstr "브랜치 지우기"
msgid "Branches|Delete merged branches"
-msgstr "ë³‘í•©ëœ ë¸Œëžœì¹˜ 지우기"
+msgstr "ë¨¸ì§€ëœ ë¸Œëžœì¹˜ 지우기"
msgid "Branches|Delete protected branch"
msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ 지우기"
@@ -1195,7 +1396,7 @@ msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you s
msgstr "'%{branch_name}' 브랜치를 삭제하면 ë˜ëŒë¦´ 수 없습니다. 괜찮습니까?"
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
-msgstr "ë³‘í•©ëœ ë¸Œëžœì¹˜ë¥¼ 삭제하면 ë˜ëŒë¦´ 수 없습니다. 괜찮ì„까요?"
+msgstr "ë¨¸ì§€ëœ ë¸Œëžœì¹˜ë¥¼ 삭제하면 ë˜ëŒë¦´ 수 없습니다. 괜찮ì„까요?"
msgid "Branches|Filter by branch name"
msgstr "브랜치 ì´ë¦„으로 í•„í„°ë§"
@@ -1255,7 +1456,7 @@ msgid "Branches|The default branch cannot be deleted"
msgstr "Default 브랜치는 삭제할 수 없습니다."
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
-msgstr "ì´ ë¸Œëžœì¹˜ëŠ” %{default_branch} ë¡œ 병합ë˜ì§€ 않았습니다."
+msgstr "ì´ ë¸Œëžœì¹˜ëŠ” %{default_branch} ë¡œ 머지ë˜ì§€ 않았습니다."
msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
msgstr "ë°ì´í„° ì†ì‹¤ì„ 방지 하려면 삭제하기 ì „ì— ì´ ë¸Œëžœì¹˜ë¥¼ 머지하는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
@@ -1273,7 +1474,7 @@ msgid "Branches|diverged from upstream"
msgstr "업스트림ì—ì„œ 분기ë¨"
msgid "Branches|merged"
-msgstr "병합ë¨"
+msgstr "머지ë¨"
msgid "Branches|project settings"
msgstr "프로ì íŠ¸ 설정"
@@ -1293,21 +1494,36 @@ msgstr "íŒŒì¼ ì°¾ì•„ë³´ê¸°"
msgid "Browse files"
msgstr "íŒŒì¼ ì°¾ì•„ë³´ê¸°"
-msgid "Built-In"
-msgstr "빌트-ì¸"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
msgid "Business metrics (Custom)"
msgstr "비즈니스 지표 (ì‚¬ìš©ìž ì •ì˜)"
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "작성ìž"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr "CI/CD 설정"
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr "ìœ„ì˜ ìžê²© ì¦ëª…ì„ ì‚¬ìš©í•˜ì—¬ CIê°€ 실행ë©ë‹ˆë‹¤."
@@ -1336,7 +1552,7 @@ msgid "CICD|Continuous deployment to production"
msgstr "프로ë•ì…˜ í™˜ê²½ì— ì§€ì†ì ì¸ ë°°í¬"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "ì ì§„ì  ë¡¤ì•„ì›ƒì„ ì‚¬ìš©í•˜ì—¬ ìš´ì˜ í™˜ê²½ì— ì§€ì†ì  ë°°í¬ (Continuous Deplyment)"
msgid "CICD|Default to Auto DevOps pipeline"
msgstr "Auto DevOps 파ì´í”„ë¼ì¸ì„ 기본으로 사용"
@@ -1344,12 +1560,6 @@ msgstr "Auto DevOps 파ì´í”„ë¼ì¸ì„ 기본으로 사용"
msgid "CICD|Deployment strategy"
msgstr "ë°°í¬ ì „ëžµ"
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr "ë°°í¬ ì „ëžµì´ ì˜¬ë°”ë¥´ê²Œ ìž‘ë™í•˜ë ¤ë©´ ë„ë©”ì¸ ì´ë¦„ì´ í•„ìš”í•©ë‹ˆë‹¤."
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr "Auto DevOpsë¡œ 여러 Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 설정하는 경우 ë„ë©”ì¸ì„ 설정하지 마십시오."
-
msgid "CICD|Jobs"
msgstr "ìž‘ì—…"
@@ -1359,18 +1569,27 @@ msgstr "Auto DevOpsì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr "대체 CI 구성 파ì¼ì´ì—†ëŠ” 경우 Auto DevOps 파ì´í”„ë¼ì¸ì´ 실행ë©ë‹ˆë‹¤."
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr "ì¸ìŠ¤í„´ìŠ¤ 사용"
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr "콜백 URL"
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr "ì´ ë¸Œëžœì¹˜ì—ì„œ HEAD ì»¤ë°‹ì„ ì°¾ì„ ìˆ˜ 없습니다."
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "취소"
@@ -1378,17 +1597,26 @@ msgid "Cancel this job"
msgstr "ì´ ìž‘ì—… 취소"
msgid "Cannot be merged automatically"
-msgstr "ìžë™ìœ¼ë¡œ 병합할 수 없습니다."
+msgstr "ìžë™ìœ¼ë¡œ 머지할 수 없습니다."
msgid "Cannot modify managed Kubernetes cluster"
msgstr "ì´ë¯¸ êµ¬ì„±ëœ Kubernetes í´ëŸ¬ìŠ¤í„°ëŠ” 수정할 수 없습니다"
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr "ì¸ì¦ì„œ 지문"
msgid "Change Weight"
msgstr "ì¤‘ìš”ë„ ë³€ê²½"
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr "템플릿 변경"
@@ -1410,12 +1638,12 @@ msgstr "Revert"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "기존 변경 ì‚¬í•­ì„ ë˜ëŒë¦¬ê¸° 위해 새로운 ì»¤ë°‹ì„ ë§Œë“­ë‹ˆë‹¤."
-msgid "Changelog"
-msgstr "변경사항"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "변경 ì‚¬í•­ì€ <b>source</b> ë¦¬ë¹„ì „ì´ <b>target</b> ë¦¬ë¹„ì „ì— ë¨¸ì§€ëœ ê²ƒì²˜ëŸ¼ 표시ë©ë‹ˆë‹¤."
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "차트"
@@ -1423,11 +1651,17 @@ msgid "Chat"
msgstr "채팅"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr "%{docs_link_start} 여기부터 %{docs_link_end} 여기까지 확ì¸."
+
+msgid "Check your .gitlab-ci.yml"
msgstr ""
msgid "Checking %{text} availability…"
msgstr "%{text}ì´(ê°€) 사용 가능한지 í™•ì¸ ì¤‘â€¦"
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "브랜치가 사용 가능한지 í™•ì¸ ì¤‘..."
@@ -1438,7 +1672,7 @@ msgid "Cherry-pick this merge request"
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 Cherry-pick"
msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
-msgstr ""
+msgstr "<strong>ë³´ê´€ íŒŒì¼ ìƒì„±</strong>ì„ ì„ íƒí•˜ê³  ë³´ê´€ì´ ì™„ë£Œ ë  ë•Œê¹Œì§€ 기다립니다."
msgid "Choose <strong>Next</strong> at the bottom of the page."
msgstr "페ì´ì§€ì˜ ì•„ëž˜ì˜ <strong>다ìŒ</strong> ì„ íƒ"
@@ -1447,6 +1681,12 @@ msgid "Choose File ..."
msgstr "íŒŒì¼ ì„ íƒ ..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr "브랜치/태그 (예. %{master})를 ì„ íƒí•˜ê±°ë‚˜ 커밋 (예. %{sha})ì„ ìž…ë ¥í•˜ì—¬ 변경 ì‚¬í•­ì„ í™•ì¸í•˜ê±°ë‚˜ 머지 리퀘스트(MR)ì„ ë§Œë“­ë‹ˆë‹¤."
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
msgstr ""
msgid "Choose a template..."
@@ -1459,7 +1699,7 @@ msgid "Choose any color."
msgstr "아무 색ìƒì„ ì„ íƒí•´ 주세요."
msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
-msgstr ""
+msgstr "최근 ì‘ìš© 프로그램 코드를 얻으려면 <code>í´ë¡ </code> ë˜ëŠ” <code>fetch</code>를 ì„ íƒí•˜ì‹­ì‹œì˜¤."
msgid "Choose file..."
msgstr "íŒŒì¼ ì„ íƒâ€¦"
@@ -1467,17 +1707,20 @@ msgstr "íŒŒì¼ ì„ íƒâ€¦"
msgid "Choose the top-level group for your repository imports."
msgstr "저장소 ê°€ì ¸ì˜¤ê¸°ì— ëŒ€í•œ 최ìƒìœ„ ê·¸ë£¹ì„ ì„ íƒí•˜ì„¸ìš”."
-msgid "Choose which groups you wish to synchronize to this secondary node."
+msgid "Choose what content you want to see on a group’s overview page"
msgstr ""
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr "ì´ ì„¸ì»¨ë”리 ë…¸ë“œì— ë™ê¸°í™” í•  ê·¸ë£¹ì„ ì„ íƒí•˜ì„¸ìš”."
+
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
-msgstr ""
+msgstr "Ci/CD 파ì´í”„ë¼ì¸ì´ ì—°ê²°ë˜ê³  실행할 저장소를 ì„ íƒí•´ 주세요."
msgid "Choose which repositories you want to import."
msgstr "가져올 저장소를 ì„ íƒí•´ì£¼ì„¸ìš”."
msgid "Choose which shards you wish to synchronize to this secondary node."
-msgstr ""
+msgstr "ì´ ì„¸ì»¨ë”리 ë…¸ë“œì— ì–´ë–¤ 샤드 (shards)를 ë™ê¸°í™” 할지 ì„ íƒí•˜ì„¸ìš”."
msgid "CiStatusLabel|canceled"
msgstr "취소ë¨"
@@ -1486,7 +1729,7 @@ msgid "CiStatusLabel|created"
msgstr "ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "CiStatusLabel|delayed"
-msgstr ""
+msgstr "지연ë¨"
msgid "CiStatusLabel|failed"
msgstr "실패"
@@ -1507,7 +1750,7 @@ msgid "CiStatusLabel|skipped"
msgstr "건너 뜀"
msgid "CiStatusLabel|waiting for delayed job"
-msgstr ""
+msgstr "ì§€ì—°ëœ ìž‘ì—… 대기 중"
msgid "CiStatusLabel|waiting for manual action"
msgstr "ìˆ˜ë™ ì‹¤í–‰ 대기 중"
@@ -1522,7 +1765,7 @@ msgid "CiStatusText|created"
msgstr "ìƒì„±ë¨"
msgid "CiStatusText|delayed"
-msgstr ""
+msgstr "지연ë¨"
msgid "CiStatusText|failed"
msgstr "실패"
@@ -1558,10 +1801,10 @@ msgid "CiVariable|All environments"
msgstr "모든 환경"
msgid "CiVariable|Create wildcard"
-msgstr ""
+msgstr "와ì¼ë“œ ì¹´ë“œ 만들기"
-msgid "CiVariable|Error occured while saving variables"
-msgstr "CiVariable 변수를 저장 하는 중 오류가 ë°œìƒ í–ˆìŠµë‹ˆë‹¤."
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
msgid "CiVariable|New environment"
msgstr "새로운 환경"
@@ -1579,11 +1822,17 @@ msgid "CiVariable|Validation failed"
msgstr "유효성 검사 실패"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr "사용할 수 없습니다: %{reason}"
+
+msgid "Clear"
msgstr ""
-msgid "Clear search"
+msgid "Clear input"
msgstr ""
+msgid "Clear search"
+msgstr "검색 지우기"
+
msgid "Clear search input"
msgstr "검색 입력 지우기"
@@ -1594,10 +1843,10 @@ msgid "Click the <strong>Download</strong> button and wait for downloading to co
msgstr "<strong>다운로드</strong> ë²„íŠ¼ì„ í´ë¦­í•˜ê³  다운로드가 완료 ë  ë•Œê¹Œì§€ 기다려 주세요."
msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
-msgstr ""
+msgstr "오른쪽 ìƒë‹¨ ëª¨ì„œë¦¬ì˜ <strong>승격</strong> 단추를 눌러 그룹 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 보낼 수 있습니다."
msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
-msgstr ""
+msgstr "ì˜¤ë¥¸ìª½ì˜ <strong>ì„ íƒ ì—†ìŒ</strong> ë²„íŠ¼ì„ í´ë¦­ 하십시오. 우리는 \"\"Google Code Project Hosting\" 만 사용하기 ë•Œë¬¸ì— ë‹¤ë¥¸ ê²ƒì€ í•„ìš” 없습니다. "
msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
msgstr "Kubernetes 페ì´ì§€ë¡œ ì´ë™í•˜ì—¬ 설치 프로세스를 시작하려면 아래 ë²„íŠ¼ì„ í´ë¦­í•˜ì‹­ì‹œì˜¤."
@@ -1620,28 +1869,52 @@ msgstr "í´ë¼ì´ì–¸íŠ¸ ì¸ì¦ 키 비밀번호"
msgid "Clients"
msgstr "í´ë¼ì´ì–¸íŠ¸"
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr "저장소 í´ë¡ "
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr "닫기"
msgid "Close epic"
msgstr "ì—픽 닫기"
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr "닫힘"
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr "닫힌 ì´ìŠˆ"
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList}ê°€ Kubernetes í´ëŸ¬ìŠ¤í„°ì— 설치ë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
-msgstr ""
+msgstr "%{boldNotice} ì´ê²ƒì€ 로드 밸러서와 ê°™ì€ ë¦¬ì†ŒìŠ¤ë¥¼ 추가하게 ë  ê²ƒ 입니다. Kubernetes í´ëŸ¬ìŠ¤í„°ê°€ ì„¤ì¹˜ëœ í˜¸ìŠ¤íŒ… 제공 ì—…ì²´ì— ë”°ë¼ ì¶”ê°€ ë¹„ìš©ì´ ë°œìƒ í•  수 있습니다. Google Kubernetes Engineì„ ì‚¬ìš©í•˜ì‹¤ 경우ì—는 ì´ê³³ %{pricingLink} ì„ ì°¸ì¡° 하십시오."
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1651,13 +1924,13 @@ msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 추가"
msgid "ClusterIntegration|Add a Kubernetes cluster integration"
-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 an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "ê·¸ë£¹ì— ì—°ë™ì„ 하시면 모든 프로ì íŠ¸ì—ì„œ í´ëŸ¬ìŠ¤í„°ê°€ 공유ë©ë‹ˆë‹¤."
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° í†µí•©ì— ëŒ€í•œ 고급 옵션"
@@ -1665,27 +1938,42 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° í†µí•©ì— ëŒ€í•œ 고급 옵션"
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "프로ì íŠ¸ ì˜ì—­ì„ 가져 오는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤: %{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr ""
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr "Google Cloud APIì— ì—°ê²°ì„ ì‹œë„하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. ë‚˜ì¤‘ì— ë‹¤ì‹œ ì‹œë„하십시오."
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr "애플리케ì´ì…˜"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr "ì´ Kubernetes í´ëŸ¬ìŠ¤í„°ì˜ í†µí•©ì„ ì œê±° 하시겠습니까? (실제 Kubernetes í´ëŸ¬ìŠ¤í„°ëŠ” ì‚­ì œë˜ì§€ 않습니다)"
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr "CA ì¸ì¦ì„œ"
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "ì¸ì¦ 기관 번들 (PEM í¬ë§·)"
@@ -1695,6 +1983,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "API URL 복사"
@@ -1707,6 +1998,9 @@ msgstr "Ingress IP 주소를 í´ë¦½ë³´ë“œë¡œ 복사"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ì´ë¦„ 복사"
@@ -1734,6 +2028,15 @@ msgstr "환경 범위"
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1750,7 +2053,7 @@ msgid "ClusterIntegration|GitLab Runner"
msgstr "ClusterIntegration|GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
-msgstr ""
+msgstr "GitLab Runner를 ì´ í”„ë¡œì íŠ¸ì˜ ì €ìž¥ì†Œì— ì—°ê²°í•˜ê³ , CI/CD ìž‘ì—…ì„ ì‹¤í–‰í•˜ê³ , 결과를 다시 가져오고, ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ìš´ì˜í™˜ê²½ì— ë°°í¬í•©ë‹ˆë‹¤."
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform 프로ì íŠ¸"
@@ -1762,13 +2065,13 @@ msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Google Kubernetes 엔진 프로ì íŠ¸"
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "그룹 í´ëŸ¬ìŠ¤í„°"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helmì€ Kubernetes ì‘ìš© 프로그램 설치 ë° ê´€ë¦¬ë¥¼ 간소화 합니다. Tiller는 Kubernetes Cluster 내부ì—ì„œ 실행ë˜ë©° ì°¨íŠ¸ì˜ ë¦´ë¦¬ìŠ¤ë¥¼ 관리합니다."
msgid "ClusterIntegration|Hide"
msgstr "숨기기"
@@ -1806,6 +2109,12 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ìžë™í™” 통합"
msgid "ClusterIntegration|Integration status"
msgstr "통합 ìƒíƒœ"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Jupyter 호스트 ì´ë¦„"
@@ -1821,6 +2130,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°"
@@ -1852,9 +2167,12 @@ msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_en
msgstr ""
msgid "ClusterIntegration|Learn more about Kubernetes"
-msgstr ""
+msgstr "Kubernetesì— ëŒ€í•´ ìžì„¸ížˆ 알아보기."
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr "그룹 Kubernetes í´ëŸ¬ìŠ¤í„°ì— 대해 ìžì„¸ížˆ 알아보기."
+
+msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1882,7 +2200,7 @@ msgid "ClusterIntegration|No projects matched your search"
msgstr "검색과 ì¼ì¹˜í•˜ëŠ” 프로ì íŠ¸ê°€ 없습니다."
msgid "ClusterIntegration|No zones matched your search"
-msgstr ""
+msgstr "검색과 ì¼ì¹˜í•˜ëŠ” ì˜ì—­ì´ 없습니다."
msgid "ClusterIntegration|Note:"
msgstr "Note:"
@@ -1900,7 +2218,7 @@ msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in o
msgstr ""
msgid "ClusterIntegration|Project cluster"
-msgstr ""
+msgstr "프로ì íŠ¸ í´ëŸ¬ìŠ¤í„°"
msgid "ClusterIntegration|Project namespace"
msgstr "프로ì íŠ¸ 네임스페ì´ìŠ¤"
@@ -1935,6 +2253,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "설치 시작 요청 실패"
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr "변경 ì‚¬í•­ì„ ì €ìž¥"
@@ -1945,13 +2266,13 @@ msgid "ClusterIntegration|Search projects"
msgstr "ClusterIntegration|프로ì íŠ¸ 검색"
msgid "ClusterIntegration|Search zones"
-msgstr ""
+msgstr "ClusterIntegration|ì˜ì—­ 검색"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ì˜ 세부 ì •ë³´ 보기 ë° ìˆ˜ì •"
msgid "ClusterIntegration|Select machine type"
-msgstr ""
+msgstr "시스템 유형 ì„ íƒ"
msgid "ClusterIntegration|Select project"
msgstr "프로ì íŠ¸ ì„ íƒ"
@@ -1963,7 +2284,7 @@ msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
msgid "ClusterIntegration|Select zone"
-msgstr ""
+msgstr "ClusterIntegration|지역 ì„ íƒ"
msgid "ClusterIntegration|Select zone to choose machine type"
msgstr ""
@@ -1977,12 +2298,18 @@ msgstr "표시"
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr "구글 Kubernetes ì—”ì§„ì— Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 만드는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "설치하는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. %{title}"
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -1996,6 +2323,18 @@ msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 토글"
msgid "ClusterIntegration|Token"
+msgstr "토í°"
+
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2010,9 +2349,12 @@ msgstr "ì´ í”„ë¡œì íŠ¸ì— ì—°ê²°ëœ Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 통해 어플ë¦
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
-msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
msgstr ""
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì€ %{link_to_kubernetes_engine} ì´ ìžˆì–´ì•¼ 합니다."
+
msgid "ClusterIntegration|Zone"
msgstr "Zone"
@@ -2037,11 +2379,14 @@ msgstr "ì •ìƒì ìœ¼ë¡œ 구성ë˜ì—ˆìŒ"
msgid "ClusterIntegration|sign up"
msgstr "ClusterIntegration|가입"
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr "코드 소유ìž"
msgid "Cohorts"
-msgstr ""
+msgstr "Cohorts"
msgid "Collapse"
msgstr "ê°ì¶”기"
@@ -2049,14 +2394,23 @@ msgstr "ê°ì¶”기"
msgid "Collapse sidebar"
msgstr "사ì´ë“œ ë°” 축소"
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
+msgstr "코멘트"
+
+msgid "Comment & close %{noteable_name}"
msgstr ""
-msgid "Comment & resolve discussion"
+msgid "Comment & reopen %{noteable_name}"
msgstr ""
+msgid "Comment & resolve discussion"
+msgstr "댓글 작성 ë° í† ë¡  í•´ê²°"
+
msgid "Comment & unresolve discussion"
-msgstr ""
+msgstr "댓글 작성 ë° í† ë¡ ì„ í•´ê²°í•˜ì§€ ì•ŠìŒ"
msgid "Comment form position"
msgstr ""
@@ -2068,13 +2422,15 @@ msgid "Commit"
msgid_plural "Commits"
msgstr[0] "커밋"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] "커밋 (%{commit_count})"
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "커밋 메시지"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "최근 30 ê±´ì˜ ì»¤ë°‹ 소요시간 (분)"
@@ -2094,7 +2450,7 @@ msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} 추가"
msgid "CommitWidget|authored"
-msgstr ""
+msgstr "작성 ë¨"
msgid "Commits"
msgstr "커밋"
@@ -2112,7 +2468,7 @@ msgid "Commits per weekday"
msgstr "í‰ì¼ 커밋"
msgid "Commits|An error occurred while fetching merge requests data."
-msgstr ""
+msgstr "머지 리퀘스트(MR) ë°ì´í„°ë¥¼ ë°˜ì˜í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Commits|Commit: %{commitText}"
msgstr "커밋: %{commitText}"
@@ -2138,14 +2494,17 @@ msgstr "Git 리비전 비êµ"
msgid "Compare Revisions"
msgstr "리비전 비êµ"
-msgid "Compare changes with the last commit"
+msgid "Compare changes"
msgstr ""
+msgid "Compare changes with the last commit"
+msgstr "마지막 커밋과 ë³€ê²½ì  ë¹„êµ"
+
msgid "Compare changes with the merge request target branch"
-msgstr ""
+msgstr "머지 리퀘스트(MR) ëŒ€ìƒ ë¸Œëžœì¹˜ì™€ 변경 사항 비êµ"
msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
-msgstr ""
+msgstr "%{source_branch} 와 %{target_branch}ê°€ ë™ì¼í•©ë‹ˆë‹¤."
msgid "CompareBranches|Compare"
msgstr "비êµ"
@@ -2157,25 +2516,31 @@ msgid "CompareBranches|Target"
msgstr "대ìƒ"
msgid "CompareBranches|There isn't anything to compare."
-msgstr ""
+msgstr "비êµí•  ê²ƒì´ ì—†ìŠµë‹ˆë‹¤."
msgid "Confidential"
-msgstr ""
+msgstr "비밀"
msgid "Confidentiality"
+msgstr "비밀"
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure Gitaly timeouts."
-msgstr ""
+msgstr "Gitaly 시간 제한 설정."
msgid "Configure Tracing"
+msgstr "ì¶”ì  êµ¬ì„±"
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
-msgstr ""
+msgstr "ìžë™ git 검사 ë° ì €ìž¥ì†Œ 하우스 í‚¤í•‘ì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Configure limits for web and API requests."
-msgstr ""
+msgstr "웹 ë° API ìš”ì²­ì— ëŒ€í•œ ì œí•œì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Configure push mirrors."
msgstr "푸시 미러를 구성하십시오."
@@ -2184,7 +2549,7 @@ msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
-msgstr ""
+msgstr "%{link} ì—°ë™ êµ¬ì„±"
msgid "Configure the way a user creates a new account."
msgstr "사용ìžê°€ 새로운 ê³„ì •ì„ ë§Œë“œëŠ” ë°©ë²•ì„ ì„¤ì •í•©ë‹ˆë‹¤."
@@ -2199,11 +2564,14 @@ msgid "Connect repositories from GitHub"
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 파ì´í”„ë¼ì¸ì´ 새로운 ì»¤ë°‹ì— ëŒ€í•´ 실행ë©ë‹ˆë‹¤. GitLab 프로ì íŠ¸ëŠ” CI/CD기능만 사용하여 ìƒì„±ë©ë‹ˆë‹¤."
msgid "Connecting..."
msgstr "연결중..."
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr "컨테ì´ë„ˆ 레지스트리"
@@ -2214,7 +2582,7 @@ msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using
msgstr "GitLab ì‚¬ìš©ìž ì´ë¦„ ë° ì•”í˜¸ë¥¼ 사용 하여 GitLabì˜ ì»¨í…Œì´ë„ˆ ë ˆì§€ìŠ¤íŠ¸ë¦¬ì— ì²˜ìŒ ë¡œê·¸ì¸ í•©ë‹ˆë‹¤. %{link_2fa} 를 사용한다면 %{link_token} 를 사용해야 합니다."
msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
-msgstr ""
+msgstr "GitLabì€ ì´ë¯¸ì§€ ì´ë¦„ì— ìµœëŒ€ 3 ë ˆë²¨ì„ ì§€ì›í•©ë‹ˆë‹¤. 다ìŒì˜ 예제 ì´ë¯¸ì§€ë“¤ì´ ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ì—ì„œ 유효합니다"
msgid "ContainerRegistry|How to use the Container Registry"
msgstr "컨테ì´ë„ˆ 레지스트리를 사용 하는 방법"
@@ -2252,6 +2620,9 @@ msgstr "GitLabì— í†µí•© Docker 컨테ì´ë„ˆ 레지스트리를 ì´ìš©í•˜ë©´, ëª
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr "계ì†"
@@ -2267,14 +2638,14 @@ msgstr "GitLabì— ê¸°ì—¬í•˜ì„¸ìš”"
msgid "Contribution"
msgstr "기여"
-msgid "Contribution guide"
-msgstr "ê¸°ì—¬ì— ëŒ€í•œ 안내"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr ""
msgid "Contributions per group member"
-msgstr ""
+msgstr "그룹 구성ì›ë³„ 기여"
msgid "Contributors"
msgstr "기여해 주신 분들"
@@ -2286,7 +2657,7 @@ msgid "ContributorsPage|Building repository graph."
msgstr "저장소 그래프 작성"
msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
-msgstr ""
+msgstr "머지 ì»¤ë°‹ì„ ì œì™¸í•œ %{branch_name}ì„ ì»¤ë°‹í•˜ì‹­ì‹œì˜¤. 6,000ê°œì˜ ì»¤ë°‹ìœ¼ë¡œ 제한ë©ë‹ˆë‹¤."
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "잠시만 기다려주십시오, ì´ íŽ˜ì´ì§€ëŠ” 준비가 완료ë˜ë©´ ìžë™ìœ¼ë¡œ 새로고침ë©ë‹ˆë‹¤."
@@ -2303,21 +2674,27 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
+msgstr "ConvDev ì¸ë±ìŠ¤"
+
+msgid "Copy %{http_label} clone URL"
msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr "%{protocol} í´ë¡  URL 복사"
-msgid "Copy HTTPS clone URL"
-msgstr "HTTPS í´ë¡  URL 복사"
-
msgid "Copy ID to clipboard"
-msgstr ""
+msgstr "í´ë¦½ ë³´ë“œì— ID 복사"
msgid "Copy SSH clone URL"
msgstr "SSH í´ë¡  URL 복사"
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr "SSH 공개키를 í´ë¦½ë³´ë“œì— 복사하기"
@@ -2340,16 +2717,13 @@ msgid "Copy incoming email address to clipboard"
msgstr "수신 ì´ë©”ì¼ ì£¼ì†Œë¥¼ í´ë¦½ ë³´ë“œì— ë³µì‚¬"
msgid "Copy link"
-msgstr ""
-
-msgid "Copy name to clipboard"
-msgstr ""
+msgstr "ë§í¬ 복사"
msgid "Copy reference to clipboard"
-msgstr ""
+msgstr "ë ˆí¼ëŸ°ìŠ¤ë¥¼ í´ë¦½ë³´ë“œë¡œ 복사"
msgid "Copy secret to clipboard"
-msgstr ""
+msgstr "í´ë¦½ë³´ë“œì— 비밀값 복사"
msgid "Copy to clipboard"
msgstr "í´ë¦½ë³´ë“œì— 복사"
@@ -2366,6 +2740,9 @@ msgstr "만들기"
msgid "Create New Directory"
msgstr "새 디렉토리 만들기"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr "새 브랜치 ìƒì„±"
@@ -2375,6 +2752,9 @@ msgstr "새 브랜치 ë° ë¨¸ì§€ 리퀘스트(MR) ìƒì„±"
msgid "Create a new issue"
msgstr "새 ì´ìŠˆ 만들기"
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "%{protocol}ì„ (를) 통해 Pull 하거나 Push í•  ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ 만드십시오."
@@ -2391,7 +2771,7 @@ msgid "Create empty repository"
msgstr "빈 저장소 ìƒì„±"
msgid "Create epic"
-msgstr ""
+msgstr "ì—픽 ìƒì„±"
msgid "Create file"
msgstr "íŒŒì¼ ë§Œë“¤ê¸°"
@@ -2406,12 +2786,15 @@ msgid "Create issue"
msgstr "ì´ìŠˆ 만들기"
msgid "Create lists from labels. Issues with that label appear in that list."
-msgstr ""
+msgstr "ë¼ë²¨ë¡œë¶€í„° 목ë¡ì„ ìƒì„±í•©ë‹ˆë‹¤. ì´ìŠˆì™€ 함께 ë¼ë²¨ì´ 목ë¡ì— 표시ë©ë‹ˆë‹¤."
msgid "Create merge request"
msgstr "머지 리퀘스트(MR) 만들기"
msgid "Create merge request and branch"
+msgstr "머지 리퀘스트(MR) ë° ë¸Œëžœì¹˜ ìƒì„±"
+
+msgid "Create milestone"
msgstr ""
msgid "Create new branch"
@@ -2436,7 +2819,7 @@ msgid "Create project label"
msgstr "새로운 프로ì íŠ¸ ë¼ë²¨"
msgid "Create your first page"
-msgstr ""
+msgstr "첫 페ì´ì§€ 만들기"
msgid "CreateTag|Tag"
msgstr "태그"
@@ -2454,10 +2837,10 @@ msgid "Created by me"
msgstr "ë‚˜ì— ì˜í•´ ìƒì„±ë¨"
msgid "Created on"
-msgstr ""
+msgstr "ìƒì„±ì¼"
msgid "Created on:"
-msgstr ""
+msgstr "ìƒì„±ì¼:"
msgid "Creating epic"
msgstr "ì—픽 ìƒì„± 중"
@@ -2480,14 +2863,11 @@ msgstr "프로파ì¼"
msgid "CurrentUser|Settings"
msgstr "설정"
-msgid "Custom"
-msgstr "ì‚¬ìš©ìž ì§€ì •"
-
msgid "Custom CI config path"
msgstr "ì‚¬ìš©ìž ì§€ì • CI config 경로"
msgid "Custom hostname (for private commit emails)"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì§€ì • 호스트네임 (ê°œì¸ ì»¤ë°‹ ì´ë©”ì¼ìš©)"
msgid "Custom notification events"
msgstr "ì‚¬ìš©ìž ì •ì˜ ì•Œë¦¼ ì´ë²¤íŠ¸"
@@ -2498,23 +2878,32 @@ msgstr "ì‚¬ìš©ìž ì •ì˜ ì•Œë¦¼ ìˆ˜ì¤€ì€ ì°¸ì—¬ 수준과 ë™ì¼í•©ë‹ˆë‹¤. 맞ì
msgid "Custom project templates"
msgstr "ì‚¬ìš©ìž ì§€ì • 프로ì íŠ¸ 템플릿"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr "ìƒ‰ìƒ ë§žì¶¤í™”"
msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
-msgstr ""
+msgstr "FogBugz ì´ë©”ì¼ ì£¼ì†Œì™€ 사용ìžëª…ì„ GitLab으로 가져오는 ë°©ë²•ì„ ì‚¬ìš©ìž ì •ì˜í•˜ì„¸ìš”. ë‹¤ìŒ ë‹¨ê³„ì—서는 가져올 프로ì íŠ¸ë¥¼ ì„ íƒí•  수 있습니다."
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr "Google Code ì´ë©”ì¼ê³¼ 사용ìžëª…ì„ GitLab으로 가져오는 ë°©ë²•ì„ ì‚¬ìš©ìž ì •ì˜í•˜ì„¸ìš”. ë‹¤ìŒ ë‹¨ê³„ì—서는 가져올 프로ì íŠ¸ë¥¼ ì„ íƒí•  수 있습니다."
+
+msgid "Customize language and region related settings."
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your merge request approval settings."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr "파ì´í”„ë¼ì¸ ì„¤ì •ì„ ë³€ê²½í•˜ê³ , ë‚˜ì˜ íŒŒì´í”„ë¼ì¸ìƒíƒœì™€ ì ìš© 범위 보고서를 보세요."
+
msgid "Cycle Analytics"
msgstr "사ì´í´ 분ì„"
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
-msgstr ""
+msgstr "Cycle Analytics는 ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ì—ì„œ ì•„ì´ë””ì–´ê°€ 제품화 ë˜ê¸°ê¹Œì§€ 걸리는 ì‹œê°„ì„ ëŒ€ëžµì ìœ¼ë¡œ ë³´ì—¬ì¤ë‹ˆë‹¤."
msgid "CycleAnalyticsStage|Code"
msgstr "코드"
@@ -2537,6 +2926,9 @@ msgstr "스테ì´ì§•"
msgid "CycleAnalyticsStage|Test"
msgstr "테스트"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr "대시보드"
@@ -2546,6 +2938,9 @@ msgstr "모든"
msgid "DashboardProjects|Personal"
msgstr "ê°œì¸"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr "날짜 ì„ íƒ"
@@ -2558,6 +2953,9 @@ msgstr "12ì›”"
msgid "December"
msgstr "12ì›”"
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr "취소 ë° ë¡œê·¸ì•„ì›ƒ"
@@ -2565,31 +2963,40 @@ msgid "Default Branch"
msgstr "기본 브랜치"
msgid "Default classification label"
+msgstr "기본 분류 ë¼ë²¨"
+
+msgid "Default first day of the week"
msgstr ""
-msgid "Default: Directly import the Google Code email address or username"
+msgid "Default first day of the week in calendars and date pickers."
msgstr ""
+msgid "Default: Directly import the Google Code email address or username"
+msgstr "기본값: Google 코드 ì´ë©”ì¼ ì£¼ì†Œ ë˜ëŠ” ì‚¬ìš©ìž ì´ë¦„ì„ ì§ì ‘ 가져옵니다."
+
msgid "Default: Map a FogBugz account ID to a full name"
-msgstr ""
+msgstr "기본: FogBugz 계정 ID를 풀네임으로 매핑"
msgid "Define a custom pattern with cron syntax"
msgstr "cron êµ¬ë¬¸ì„ ì‚¬ìš©í•˜ì—¬ ì‚¬ìš©ìž ì •ì˜ íŒ¨í„´ ì •ì˜"
-msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+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|Start now"
-msgstr ""
+msgstr "지금 시작"
msgid "DelayedJobs|Unschedule"
-msgstr ""
+msgstr "스케쥴 취소"
msgid "DelayedJobs|delayed"
-msgstr ""
+msgstr "지연ë¨"
msgid "Delete"
msgstr "삭제 "
@@ -2601,9 +3008,15 @@ msgid "Delete Snippet"
msgstr "스니펫 삭제"
msgid "Delete comment"
-msgstr ""
+msgstr "댓글 삭제"
msgid "Delete list"
+msgstr "ëª©ë¡ ì‚­ì œ"
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
msgstr ""
msgid "Deleted"
@@ -2674,10 +3087,10 @@ msgid "DeployTokens|Add a deploy token"
msgstr "ë°°í¬ í† í° ì¶”ê°€"
msgid "DeployTokens|Allows read-only access to the registry images"
-msgstr ""
+msgstr "레지스트리 ì´ë¯¸ì§€ì— 대한 ì½ê¸° ì „ìš© 액세스 허용"
msgid "DeployTokens|Allows read-only access to the repository"
-msgstr ""
+msgstr "ì €ìž¥ì†Œì— ëŒ€í•œ ì½ê¸° ì „ìš© 액세스 허용"
msgid "DeployTokens|Copy deploy token to clipboard"
msgstr "ë°°í¬ í† í°ì„ í´ë¦½ë³´ë“œì— 복사"
@@ -2695,7 +3108,7 @@ msgid "DeployTokens|Deploy Tokens"
msgstr "ë°°í¬ í† í°"
msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
-msgstr ""
+msgstr "ë°°í¬ í† í°ì´ 저장소 ë° ë ˆì§€ìŠ¤íŠ¸ë¦¬ ì´ë¯¸ì§€ì— 대한 ì½ê¸° ì „ìš© 액세스를 허용합니다."
msgid "DeployTokens|Expires"
msgstr "만료"
@@ -2704,7 +3117,7 @@ msgid "DeployTokens|Name"
msgstr "ì´ë¦„"
msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
-msgstr ""
+msgstr "ì‘ìš© í”„ë¡œê·¸ëž¨ì˜ ì´ë¦„ì„ ì„ íƒí•˜ë©´ 고유한 ë°°í¬ í† í°ì´ 제공ë©ë‹ˆë‹¤."
msgid "DeployTokens|Revoke"
msgstr "취소"
@@ -2739,14 +3152,17 @@ msgstr "새 ë°°í¬ í† í°"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "프로ì íŠ¸ ë°°í¬ í† í°ì„ 새로 만들었습니다."
-msgid "Deployed to"
+msgid "Deployed"
msgstr ""
+msgid "Deployed to"
+msgstr "ë°°í¬ë¨"
+
msgid "Deploying to"
-msgstr ""
+msgstr "다ìŒì— ë°°í¬ì¤‘: "
msgid "Deprioritize label"
-msgstr ""
+msgstr "ë¼ë²¨ ìš°ì„  순위 낮추기"
msgid "Descending"
msgstr "내림차순"
@@ -2766,11 +3182,14 @@ msgstr "제거"
msgid "Details"
msgstr "ìƒì„¸"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr "호스트 키 발견"
msgid "Diff content limits"
-msgstr ""
+msgstr "diff 컨í…츠 제한"
msgid "Diff limits"
msgstr ""
@@ -2779,7 +3198,7 @@ msgid "Diffs|No file name available"
msgstr "사용가능한 íŒŒì¼ ì´ë¦„ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "Diffs|Something went wrong while fetching diff lines."
-msgstr ""
+msgstr "Diffs | ë³µìˆ˜ì˜ ì—´ì„ íŒ¨ì¹˜í•˜ëŠ” 중 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Direction"
msgstr "ë°©í–¥"
@@ -2796,6 +3215,12 @@ msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해 사용 중지"
msgid "Disable group Runners"
msgstr "그룹 Runner 사용 중지"
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr "취소"
@@ -2809,7 +3234,7 @@ msgid "Discard changes"
msgstr "변경 ì‚¬í•­ì„ ì·¨ì†Œ"
msgid "Discard changes to %{path}?"
-msgstr ""
+msgstr "%{path}ì— ëŒ€í•œ 변경 취소?"
msgid "Discard draft"
msgstr "초안 삭제"
@@ -2817,29 +3242,38 @@ msgstr "초안 삭제"
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr "프로ì íŠ¸, 그룹 그리고 ìŠ¤ë‹ˆíŽ«ì„ ë°œê²¬í•˜ê³  ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ë¥¼ 다른 사람과 공유합니다."
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
msgstr ""
msgid "Dismiss"
msgstr "닫기"
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "사ì´í´ ë¶„ì„ ì†Œê°œ 박스 제거"
msgid "Dismiss Merge Request promotion"
-msgstr ""
+msgstr "머지 리퀘스트 프로모션 제거"
msgid "Dismiss trial promotion"
-msgstr ""
+msgstr "í‰ê°€íŒ 프로모션 제거"
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
-msgstr ""
+msgstr "Google Code ì´ë©”ì¼ ì£¼ì†Œì™€ 사용ìžëª…ì„ GitLab으로 가져오는 ë°©ë²•ì„ ì‚¬ìš©ìž ì •ì˜í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
msgid "Documentation for popular identity providers"
-msgstr ""
+msgstr "ì¸ê¸°ìžˆëŠ” ID 제공 ì—…ì²´ì— ëŒ€í•œ 문서"
msgid "Domain"
msgstr "ë„ë©”ì¸"
@@ -2853,6 +3287,12 @@ msgstr "완료"
msgid "Download"
msgstr "다운로드"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "tar 다운로드"
@@ -2877,6 +3317,9 @@ msgstr "Plain Diff"
msgid "DownloadSource|Download"
msgstr "다운로드"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr "비추천"
@@ -2892,9 +3335,15 @@ msgstr "ê° Runner는 ë‹¤ìŒ ìƒíƒœ 중 í•˜ë‚˜ì¼ ìˆ˜ 있습니다."
msgid "Edit"
msgstr "편집"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr "ë¼ë²¨ 편집"
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "파ì´í”„ë¼ì¸ 스케줄 편집 %{id}"
@@ -2904,6 +3353,12 @@ msgstr "스니펫 편집"
msgid "Edit application"
msgstr "애플리케ì´ì…˜ 수정"
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr "ì—디터ì—ì„œ 파ì¼ì„ 편집하고 여기서 ë³€ê²½ì‚¬í•­ì„ ì»¤ë°‹í•˜ì„¸ìš”."
@@ -2913,17 +3368,20 @@ msgstr "그룹 편집: %{group_name}"
msgid "Edit identity for %{user_name}"
msgstr "%{user_name}ì˜ ì‹ ì› íŽ¸ì§‘"
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr "Elasticsearch"
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
+msgstr "Elasticsearch ì—°ë™, Elasticsearch AWS IAM"
msgid "Email"
msgstr "ì´ë©”ì¼"
msgid "Email patch"
-msgstr ""
+msgstr "패치를 ì´ë©”ì¼ë¡œ 보냄"
msgid "Emails"
msgstr "ì´ë©”ì¼"
@@ -2931,6 +3389,9 @@ msgstr "ì´ë©”ì¼"
msgid "Embed"
msgstr "임베드"
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr "사용"
@@ -2947,12 +3408,15 @@ msgid "Enable Sentry for error reporting and logging."
msgstr "Sentry를 사용해 오류 보고와 ë¡œê¹…ì„ í™œì„±í™”í•©ë‹ˆë””."
msgid "Enable and configure InfluxDB metrics."
-msgstr ""
+msgstr "InfluxDB 매트릭스를 활성화하고 구성합니다."
msgid "Enable and configure Prometheus metrics."
-msgstr ""
+msgstr "Prometheus 매트릭스를 활성화하고 구성합니다."
msgid "Enable classification control using an external service"
+msgstr "외부 서비스로 분류 제어 사용"
+
+msgid "Enable error tracking"
msgstr ""
msgid "Enable for this project"
@@ -2965,16 +3429,25 @@ msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
msgid "Enable or disable version check and usage ping."
-msgstr ""
+msgstr "버전 í™•ì¸ ë° ì‚¬ìš© í•‘ì„ ì‚¬ìš©í•˜ê±°ë‚˜ 사용하지 ì•Šë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "reCAPTCHA ë˜ëŠ” Akismetì„ í™œì„±í™”í•˜ê³  IP ì œí•œì„ ì„¤ì •í•©ë‹ˆë‹¤."
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
+msgstr "주어진 ê·¸ë£¹ì— ëŒ€í•´ 성능 표시 바를 활성화 합니다."
+
+msgid "Enable two-factor authentication"
msgstr ""
msgid "Enable usage ping"
-msgstr ""
+msgstr "ping 사용 활성화"
msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
msgstr ""
@@ -2985,6 +3458,12 @@ msgstr "활성화ë¨"
msgid "Ends at (UTC)"
msgstr "(UTC)ì— ì¢…ë£Œë©ë‹ˆë‹¤"
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "아래 Bitbucket Server URL ë° ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ 입력하십시오."
@@ -3000,12 +3479,30 @@ msgstr "머지 리퀘스트(MR) ì„¤ëª…ì„ ìž…ë ¥ 해주세요"
msgid "Enter the merge request title"
msgstr "머지 리퀘스트(MR) ì œëª©ì„ ìž…ë ¥ 해주세요"
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr "환경"
-msgid "Environments|An error occurred while fetching the environments."
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "Environments|An error occurred while fetching the environments."
+msgstr "í™˜ê²½ê°’ë“¤ì„ ë°˜ì˜í•˜ëŠ” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
msgid "Environments|An error occurred while making the request."
msgstr "ìš”ì²­ì„ ë§Œë“œëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -3043,7 +3540,7 @@ msgid "Environments|New environment"
msgstr "새 환경"
msgid "Environments|No deployments yet"
-msgstr ""
+msgstr "ë°°í¬ê°€ 없습니다."
msgid "Environments|No pod name has been specified"
msgstr ""
@@ -3064,7 +3561,7 @@ msgid "Environments|Re-deploy to environment"
msgstr ""
msgid "Environments|Read more about environments"
-msgstr ""
+msgstr "í™˜ê²½ì— ëŒ€í•œ 추가 ì •ë³´"
msgid "Environments|Rollback environment"
msgstr ""
@@ -3078,9 +3575,12 @@ msgstr "중지"
msgid "Environments|Stop environment"
msgstr "중지 환경"
-msgid "Environments|Updated"
+msgid "Environments|Stopping"
msgstr ""
+msgid "Environments|Updated"
+msgstr "갱신ë¨"
+
msgid "Environments|You don't have any environments right now"
msgstr ""
@@ -3090,9 +3590,6 @@ msgstr "보호ë¨"
msgid "Epic"
msgstr "ì—픽"
-msgid "Epic will be removed! Are you sure?"
-msgstr "ì—í”½ì´ ì‚­ì œë©ë‹ˆë‹¤! 확실합니까?"
-
msgid "Epics"
msgstr "ì—픽"
@@ -3102,7 +3599,7 @@ msgstr "ì—픽 로드맵"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3129,7 +3626,13 @@ msgstr "ì—러"
msgid "Error Reporting and Logging"
msgstr "오류 ë³´ê³  ë° ë¡œê¹…"
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
+msgstr "ì—í”½ì„ ë§Œë“œëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
+msgid "Error deleting %{issuableType}"
msgstr ""
msgid "Error fetching contributors data."
@@ -3139,16 +3642,16 @@ msgid "Error fetching labels."
msgstr "ë¼ë²¨ì„ 가져 오는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error fetching network graph."
-msgstr ""
+msgstr "ë„¤íŠ¸ì›Œí¬ ê·¸ëž˜í”„ ë°˜ì˜ ì¤‘ 오류"
msgid "Error fetching refs"
-msgstr ""
+msgstr "refs ë°˜ì˜ ì¤‘ 오류"
msgid "Error fetching usage ping data."
-msgstr ""
+msgstr "사용 í•‘ ë°ì´í„° ë°˜ì˜ ì¤‘ 오류"
msgid "Error loading branch data. Please try again."
-msgstr ""
+msgstr "브랜치 ë°ì´í„°ë¥¼ 로드하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하십시오."
msgid "Error loading branches."
msgstr "브랜치 로드 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -3157,33 +3660,45 @@ msgid "Error loading last commit."
msgstr "마지막 ì»¤ë°‹ì„ ë¡œë“œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error loading markdown preview"
-msgstr ""
+msgstr "ë§ˆí¬ ë‹¤ìš´ 미리보기 오류"
msgid "Error loading merge requests."
msgstr "머지 리퀘스트(MR)를 로드하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error loading project data. Please try again."
-msgstr ""
+msgstr "프로ì íŠ¸ ë°ì´í„°ë¥¼ 로드하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하십시오."
msgid "Error loading template types."
-msgstr ""
+msgstr "템플릿 유형 로드 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error loading template."
-msgstr ""
+msgstr "템플릿 로딩 오류."
msgid "Error occurred when toggling the notification subscription"
+msgstr "êµ¬ë… ì•Œë¦¼ì„ ì „í™˜í•  ë•Œ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
+
+msgid "Error rendering markdown preview"
msgstr ""
msgid "Error saving label update."
+msgstr "ë ˆì´ë¸” 갱신 중 오류 ë°œìƒ"
+
+msgid "Error updating %{issuableType}"
msgstr ""
msgid "Error updating status for all todos."
-msgstr ""
+msgstr "모든 해야할 ì¼ì˜ ìƒíƒœë¥¼ ë³€ê²½í•˜ë˜ ì¤‘ 오류"
msgid "Error updating todo status."
-msgstr ""
+msgstr "해야할 ì¼ ìƒíƒœ 갱신 중 오류 ë°œìƒ"
msgid "Error while loading the merge request. Please try again."
+msgstr "머지 리퀘스트(MR) 요청 중 오류 ë°œìƒ. 다시 ì‹œë„하십시오."
+
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
msgstr ""
msgid "Estimated"
@@ -3207,6 +3722,12 @@ msgstr "푸쉬 ì´ë²¤íŠ¸ 기준으로 í•„í„°"
msgid "EventFilterBy|Filter by team"
msgstr "팀 기준으로 필터"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "ë§¤ì¼ (오전 4ì‹œì—)"
@@ -3216,9 +3737,39 @@ msgstr "매월 (1ì¼ ì˜¤ì „ 4ì‹œ)"
msgid "Every week (Sundays at 4:00am)"
msgstr "매주 (ì¼ìš”ì¼ ì˜¤ì „ 4ì‹œì—)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr "모ë‘ê°€ 기여할 수 있ìŒ."
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr "펼치기"
@@ -3231,6 +3782,12 @@ msgstr "사ì´ë“œë°” 확장"
msgid "Expiration date"
msgstr "만료ì¼"
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3252,7 +3809,19 @@ msgstr "프로ì íŠ¸ 둘러보기"
msgid "Explore public groups"
msgstr "공개 그룹 íƒìƒ‰"
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
+msgstr "외부 분류 ì •ì±… ì¸ì¦"
+
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
msgstr ""
msgid "External authentication"
@@ -3262,7 +3831,7 @@ msgid "External authorization denied access to this project"
msgstr "외부 ì¸ì¦ì´ ì´ í”„ë¡œì íŠ¸ì— 대한 액세스를 거부했습니다."
msgid "External authorization request timeout"
-msgstr ""
+msgstr "외부 ì¸ì¦ 요청 시간 초과"
msgid "ExternalAuthorizationService|Classification Label"
msgstr ""
@@ -3286,128 +3855,198 @@ msgid "Failed to change the owner"
msgstr "소유ìžë¥¼ 변경하지 못했습니다"
msgid "Failed to check related branches."
-msgstr ""
+msgstr "관련 브랜치를 확ì¸í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
msgid "Failed to deploy to"
msgstr ""
msgid "Failed to load emoji list."
+msgstr "ì´ëª¨ì§€ 목ë¡ì„ 불러올 수 없습니다"
+
+msgid "Failed to load errors from Sentry"
msgstr ""
msgid "Failed to remove issue from board, please try again."
-msgstr ""
+msgstr "게시íŒì—ì„œ ì´ìŠˆë¥¼ ì œê±°í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤, 다시 ì‹œë„í•´ 주십시오."
msgid "Failed to remove mirror."
-msgstr ""
+msgstr "미러를 제거하지 못했습니다."
msgid "Failed to remove the pipeline schedule"
msgstr "파ì´í”„ë¼ì¸ ìŠ¤ì¼€ì¤„ì„ ì œê±°í•˜ì§€ 못했습니다."
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
+msgstr "ì´ìŠˆë¥¼ ê°±ì‹ í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤, 다시 ì‹œë„í•´ 주십시오."
+
+msgid "Failed to upload object map file"
msgstr ""
msgid "Failure"
msgstr "실패"
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
-msgstr ""
+msgid "FeatureFlags|API URL"
+msgstr "API URL"
+
+msgid "FeatureFlags|Active"
+msgstr "활성화"
msgid "FeatureFlags|Configure"
-msgstr ""
+msgstr "구성"
msgid "FeatureFlags|Configure feature flags"
-msgstr ""
+msgstr "Feature 플래그 구성"
msgid "FeatureFlags|Create feature flag"
+msgstr "Feature 플래그 ìƒì„±"
+
+msgid "FeatureFlags|Delete %{name}?"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
-msgstr ""
+msgstr "설명"
msgid "FeatureFlags|Edit %{feature_flag_name}"
-msgstr ""
+msgstr "%{feature_flag_name} 수정"
msgid "FeatureFlags|Edit Feature Flag"
+msgstr "Feature 플래그 수정"
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
msgstr ""
msgid "FeatureFlags|Feature Flag"
+msgstr "Feature 플래그"
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
+msgstr "비활성화"
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr ""
+msgstr "%{docs_link_start}호환 í´ë¼ì´ì–¸íŠ¸ ë¼ì´ë¸ŒëŸ¬ë¦¬%{docs_link_end}를 설치하고 API URL, 어플리케ì´ì…˜ ì´ë¦„, ì¸ìŠ¤í„´ìŠ¤ ID를 설정 과정ì—ì„œ 지정하세요."
msgid "FeatureFlags|Instance ID"
+msgstr "ì¸ìŠ¤í„´ìŠ¤ ID"
+
+msgid "FeatureFlags|Loading Feature Flags"
msgstr ""
-msgid "FeatureFlags|More information"
+msgid "FeatureFlags|More Information"
msgstr ""
+msgid "FeatureFlags|More information"
+msgstr "ë” ë§Žì€ ì •ë³´"
+
msgid "FeatureFlags|Name"
-msgstr ""
+msgstr "ì´ë¦„"
msgid "FeatureFlags|New"
-msgstr ""
+msgstr "새로운"
msgid "FeatureFlags|New Feature Flag"
-msgstr ""
+msgstr "새로운 Feature 플래그"
msgid "FeatureFlags|Save changes"
-msgstr ""
+msgstr "변경사항 저장"
msgid "FeatureFlags|Status"
+msgstr "ìƒíƒœ"
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
msgid "Feb"
msgstr "2ì›”"
msgid "February"
-msgstr ""
+msgstr "2ì›”"
msgid "Fields on this page are now uneditable, you can configure"
+msgstr "ì´ íŽ˜ì´ì§€ì˜ ìž…ë ¥ëž€ì€ ì´ì œ 변경할 수 없습니다, 설정할 수 있습니다."
+
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
msgstr ""
msgid "File templates"
msgstr "íŒŒì¼ í…œí”Œë¦¿"
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "파ì¼"
-msgid "Files (%{human_size})"
-msgstr "íŒŒì¼ (%{human_size})"
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -3423,12 +4062,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr "커밋 메시지로 필터"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr "í•„í„°..."
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "경로로 찾기"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "íŒŒì¼ ì°¾ê¸°"
@@ -3441,12 +4098,18 @@ msgstr ""
msgid "Fingerprints"
msgstr "지문"
-msgid "Finish review"
+msgid "Finish editing this message first!"
msgstr ""
+msgid "Finish review"
+msgstr "리뷰 완료"
+
msgid "Finished"
msgstr "완료"
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "처ìŒ"
@@ -3454,7 +4117,7 @@ msgid "FirstPushedBy|pushed by"
msgstr "푸시한 사용ìž"
msgid "Fixed date"
-msgstr ""
+msgstr "수정 날짜"
msgid "Fixed due date"
msgstr ""
@@ -3487,11 +4150,14 @@ msgid "Font Color"
msgstr "글꼴 색"
msgid "Footer message"
-msgstr ""
+msgstr "바닥글 메시지"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3516,6 +4182,9 @@ msgstr "%{project_name} (ì‚­ì œ) ì—ì„œ í¬í¬ë¨"
msgid "Forking in progress"
msgstr "í¬í¬ 진행중"
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "í¬ë§·"
@@ -3523,7 +4192,7 @@ msgid "Found errors in your .gitlab-ci.yml:"
msgstr ".gitlab-ci.ymlì—ì„œ 오류를 발견했습니다:"
msgid "Free Trial of GitLab.com Gold"
-msgstr ""
+msgstr "GitLab.com Gold 무료 ì²´í—˜íŒ"
msgid "From %{provider_title}"
msgstr "%{provider_title}ì—ì„œ"
@@ -3550,7 +4219,7 @@ msgid "From merge request merge until deploy to production"
msgstr "머지 리퀘스트(MR) 머지ì—ì„œ 프로ë•ì…˜ í™˜ê²½ì— ë°°í¬ê¹Œì§€"
msgid "From milestones:"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ì—ì„œ:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 세부사항 ë³´ê¸°ì˜ ì• í”Œë¦¬ì¼€ì´ì…˜ 목ë¡ì—ì„œ Runner를 설치하십시오."
@@ -3562,16 +4231,19 @@ msgid "General"
msgstr "ì¼ë°˜"
msgid "General pipelines"
-msgstr ""
+msgstr "ì¼ë°˜ 파ì´í”„ë¼ì¸"
msgid "Generate a default set of labels"
+msgstr " 초기설정 ë ˆì´ë¸” 세트 ìƒì„±"
+
+msgid "Generate key"
msgstr ""
msgid "Geo"
-msgstr ""
+msgstr "Geo"
msgid "Geo Nodes"
-msgstr ""
+msgstr "Geo 노드"
msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
msgstr ""
@@ -3583,55 +4255,55 @@ msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an
msgstr ""
msgid "GeoNodes|Checksummed"
-msgstr ""
+msgstr "ì²´í¬ì„¬ë¨"
msgid "GeoNodes|Data is out of date from %{timeago}"
msgstr ""
msgid "GeoNodes|Data replication lag"
-msgstr ""
+msgstr "ë°ì´í„° 복제 지연"
msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
-msgstr ""
+msgstr "노드를 비활성화하면 ë™ê¸°í™” 프로세스가 중지ë©ë‹ˆë‹¤. ì •ë§ë¡œ 진행하시겠습니까?"
msgid "GeoNodes|Does not match the primary storage configuration"
-msgstr ""
+msgstr "ë§ˆìŠ¤í„°ì˜ ìŠ¤í† ë¦¬ì§€ 구성과 ì¼ì¹˜í•˜ì§€ 않습니다."
msgid "GeoNodes|Failed"
-msgstr ""
+msgstr "실패"
msgid "GeoNodes|Full"
-msgstr ""
+msgstr "ì „ì²´"
msgid "GeoNodes|GitLab version"
-msgstr ""
+msgstr "GitLab 버전"
msgid "GeoNodes|GitLab version does not match the primary node version"
-msgstr ""
+msgstr "GitLab ë²„ì „ì´ ì£¼ìš” 노드 버전과 ì¼ì¹˜í•˜ì§€ 않습니다."
msgid "GeoNodes|Health status"
-msgstr ""
+msgstr "ìš´ì˜ ìƒíƒœ"
msgid "GeoNodes|Last event ID processed by cursor"
-msgstr ""
+msgstr "커서로 ì²˜ë¦¬ëœ ë§ˆì§€ë§‰ ì´ë²¤íŠ¸ ID"
msgid "GeoNodes|Last event ID seen from primary"
msgstr ""
msgid "GeoNodes|Learn more about Repository checksum progress"
-msgstr ""
+msgstr "저장소 ì²´í¬ì„¬ ì§„í–‰ì— ëŒ€í•´ì„œ ë” ì•Œì•„ë³´ê¸°"
msgid "GeoNodes|Learn more about Repository verification"
-msgstr ""
+msgstr "저장소 ê²€ì¦ì— 대해 ë” ì•Œì•„ë³´ê¸°"
msgid "GeoNodes|Learn more about Wiki checksum progress"
msgstr ""
msgid "GeoNodes|Learn more about Wiki verification"
-msgstr ""
+msgstr "위키 ê²€ì¦ì— 대해 ë” ì•Œì•„ë³´ê¸°"
msgid "GeoNodes|Loading nodes"
-msgstr ""
+msgstr "노드 불러오는 중"
msgid "GeoNodes|Local LFS objects"
msgstr ""
@@ -3643,21 +4315,24 @@ msgid "GeoNodes|Local job artifacts"
msgstr ""
msgid "GeoNodes|New node"
-msgstr ""
+msgstr "새 노드"
msgid "GeoNodes|Node Authentication was successfully repaired."
-msgstr ""
+msgstr "노드 ì¸ì¦ì´ 성공ì ìœ¼ë¡œ ë³µì›ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "GeoNodes|Node was successfully removed."
-msgstr ""
+msgstr "노드가 성공ì ìœ¼ë¡œ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "GeoNodes|Not checksummed"
-msgstr ""
+msgstr "ì²´í¬ì„¬ ë˜ì§€ ì•ŠìŒ"
msgid "GeoNodes|Out of sync"
+msgstr "ë™ê¸°í™”ë˜ì§€ ì•ŠìŒ"
+
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3667,7 +4342,7 @@ msgid "GeoNodes|Replication slots"
msgstr ""
msgid "GeoNodes|Repositories"
-msgstr ""
+msgstr "저장소"
msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
msgstr ""
@@ -3685,46 +4360,46 @@ msgid "GeoNodes|Selective"
msgstr ""
msgid "GeoNodes|Something went wrong while changing node status"
-msgstr ""
+msgstr "노드 ìƒíƒœë¥¼ ë³€ê²½í•˜ëŠ”ë° ë¬¸ì œê°€ 있습니다."
msgid "GeoNodes|Something went wrong while fetching nodes"
-msgstr ""
+msgstr "노드를 ê°€ì ¸ì˜¤ëŠ”ë° ë¬¸ì œê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "GeoNodes|Something went wrong while removing node"
-msgstr ""
+msgstr "노드를 ì‚­ì œí•˜ëŠ”ë° ë¬¸ì œê°€ 있습니다."
msgid "GeoNodes|Something went wrong while repairing node"
-msgstr ""
+msgstr "노드를 ë³µì›í•˜ëŠ”ë° ë¬¸ì œê°€ 있습니다."
msgid "GeoNodes|Storage config"
-msgstr ""
+msgstr "스토리지 구성"
msgid "GeoNodes|Sync settings"
-msgstr ""
+msgstr "ë™ê¸°í™” 설정"
msgid "GeoNodes|Synced"
-msgstr ""
+msgstr "ë™ê¸°í™”ë¨"
msgid "GeoNodes|Unused slots"
msgstr ""
msgid "GeoNodes|Unverified"
-msgstr ""
+msgstr "미확ì¸"
msgid "GeoNodes|Used slots"
msgstr ""
msgid "GeoNodes|Verified"
-msgstr ""
+msgstr "확ì¸ë¨"
msgid "GeoNodes|Wiki checksum progress"
msgstr ""
msgid "GeoNodes|Wiki verification progress"
-msgstr ""
+msgstr "위키 í™•ì¸ ì§„í–‰"
msgid "GeoNodes|Wikis"
-msgstr ""
+msgstr "위키"
msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
msgstr ""
@@ -3732,6 +4407,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3748,7 +4426,7 @@ msgid "Geo|All"
msgstr ""
msgid "Geo|All projects"
-msgstr ""
+msgstr "모든 프로ì íŠ¸"
msgid "Geo|All projects are being scheduled for re-check"
msgstr ""
@@ -3763,7 +4441,7 @@ msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
-msgstr ""
+msgstr "실패"
msgid "Geo|File sync capacity"
msgstr ""
@@ -3777,6 +4455,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3813,14 +4494,17 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
-msgid "Geo|Recheck"
+msgid "Geo|Re-verification interval"
msgstr ""
+msgid "Geo|Recheck"
+msgstr "재확ì¸"
+
msgid "Geo|Recheck all projects"
msgstr ""
msgid "Geo|Redownload"
-msgstr ""
+msgstr "다시 다운로드"
msgid "Geo|Remove"
msgstr ""
@@ -3835,7 +4519,7 @@ msgid "Geo|Resync all projects"
msgstr ""
msgid "Geo|Retry count"
-msgstr ""
+msgstr "ìž¬ì‹œë„ íšŸìˆ˜"
msgid "Geo|Select groups to replicate."
msgstr ""
@@ -3847,10 +4531,10 @@ msgid "Geo|Status"
msgstr "ìƒíƒœ"
msgid "Geo|Synced"
-msgstr ""
+msgstr "Geo|ë™ê¸°í™” ë¨"
msgid "Geo|Synchronization failed - %{error}"
-msgstr ""
+msgstr "Geo|ë™ê¸°í™” 실패 - %{error}"
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr ""
@@ -3859,13 +4543,13 @@ msgid "Geo|Tracking entry will be removed. Are you sure?"
msgstr ""
msgid "Geo|Unknown state"
-msgstr ""
+msgstr "ì•Œ 수 없는 ìƒíƒœ"
msgid "Geo|Verification capacity"
-msgstr ""
+msgstr "ê²€ì¦ ë²”ìœ„"
msgid "Geo|Verification failed - %{error}"
-msgstr ""
+msgstr "í™•ì¸ ì‹¤íŒ¨- %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "스케줄러 대기 중"
@@ -3891,9 +4575,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr "Git"
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr "Git 저장소 URL"
@@ -3901,7 +4594,7 @@ msgid "Git revision"
msgstr "Git 리비전"
msgid "Git strategy for pipelines"
-msgstr ""
+msgstr "파ì´í”„ ë¼ì¸ì— 대한 Git ì „ëžµ"
msgid "Git version"
msgstr "Git 버전"
@@ -3916,19 +4609,25 @@ msgid "GitLab Geo"
msgstr "GitLab Geo"
msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
+msgstr "GitLab Group RunnersëŠ”ì´ ê·¸ë£¹ì˜ ëª¨ë“  프로ì íŠ¸ì— 대한 코드를 실행할 수 있습니다."
msgid "GitLab Import"
msgstr "GitLab 가져오기"
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr "GitLab 사용ìž"
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr "GitLab 프로ì íŠ¸ 내보내기"
msgid "GitLab single sign on URL"
-msgstr ""
+msgstr "GitLab 싱글 사ì¸ì˜¨ URL"
msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
@@ -3954,6 +4653,9 @@ msgstr "Gitea 호스트 URL"
msgid "Gitea Import"
msgstr "Gitea 가져오기"
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr "ì´ì „으로"
@@ -3961,7 +4663,7 @@ msgid "Go back"
msgstr "뒤로 가기"
msgid "Go to"
-msgstr ""
+msgstr "ì´ë™"
msgid "Go to %{link_to_google_takeout}."
msgstr "%{link_to_google_takeout}ë¡œ ì´ë™í•˜ì‹­ì‹œì˜¤."
@@ -3978,6 +4680,9 @@ msgstr "Google ì¸ì¦ì„ 사용할 수 없습니다. %{link_to_documentation} Gi
msgid "Got it!"
msgstr "확ì¸!"
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr "그래프"
@@ -3988,7 +4693,7 @@ msgid "Group CI/CD settings"
msgstr "그룹 CI/CD 설정"
msgid "Group Git LFS status:"
-msgstr ""
+msgstr "그룹 Git LFS ìƒíƒœ:"
msgid "Group ID"
msgstr "그룹 ID"
@@ -4000,16 +4705,16 @@ msgid "Group SAML must be enabled to test"
msgstr ""
msgid "Group URL"
-msgstr ""
+msgstr "그룹 URL"
msgid "Group avatar"
msgstr "그룹 아바타"
msgid "Group description"
-msgstr ""
+msgstr "그룹 설명"
msgid "Group description (optional)"
-msgstr ""
+msgstr "그룹 설명 (ì„ íƒ ì‚¬í•­)"
msgid "Group details"
msgstr "그룹 세부 정보"
@@ -4018,18 +4723,21 @@ msgid "Group info:"
msgstr "그룹 정보:"
msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
+msgstr "그룹 관리ìžëŠ” grouo runners를 여기서 ë“±ë¡ í•  수 있습니다: %{link}"
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr "그룹: %{group_name}"
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4041,22 +4749,10 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|Until %{dateWord}"
@@ -4065,15 +4761,24 @@ msgstr ""
msgid "GroupSettings|Badges"
msgstr "배지"
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
msgid "GroupSettings|Customize your group badges."
msgstr "그룹 배지를 ì‚¬ìš©ìž ì •ì˜í•©ë‹ˆë‹¤."
msgid "GroupSettings|Learn more about badges."
msgstr "ë°°ì§€ì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "%{group} ë‚´ì˜ í”„ë¡œì íŠ¸ë¥¼ 다른 ê·¸ë£¹ì— ê³µìœ í•  수 없게 합니다."
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "ì´ ì„¤ì •ì€ %{ancestor_group} ì— ì ìš©ë˜ê³  ì´ í•˜ìœ„ 그룹ì—ì„œ ìž¬ì •ì˜ ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -4098,6 +4803,9 @@ msgstr "그룹들"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4129,7 +4837,7 @@ msgid "GroupsEmptyState|No groups found"
msgstr "ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
-msgstr ""
+msgstr "그룹 구성ì›ì˜ 사용 ê¶Œí•œì„ ê´€ë¦¬í•˜ê³  ê·¸ë£¹ì˜ ê° í”„ë¡œì íŠ¸ì— ì ‘ê·¼ í•  수 있습니다."
msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
msgstr ""
@@ -4162,10 +4870,10 @@ msgid "GroupsTree|Search by name"
msgstr "ì´ë¦„으로 검색"
msgid "Have your users email"
-msgstr ""
+msgstr "사용ìžì—게 ì´ë©”ì¼ ë°œì‹ "
msgid "Header message"
-msgstr ""
+msgstr "머릿글 메시지"
msgid "Health Check"
msgstr "헬스 ì²´í¬"
@@ -4189,25 +4897,28 @@ msgid "Help"
msgstr "ë„움ë§"
msgid "Help page"
-msgstr ""
+msgstr "ë„ì›€ë§ íŽ˜ì´ì§€"
msgid "Help page text and support page url."
-msgstr ""
+msgstr "ë„ì›€ë§ íŽ˜ì´ì§€ í…스트 ë° ì§€ì› íŽ˜ì´ì§€ url."
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
-msgid "Hide host keys manual input"
+msgid "Hide file browser"
msgstr ""
+msgid "Hide host keys manual input"
+msgstr "호스트 키 ìˆ˜ë™ ìž…ë ¥ 숨기기"
+
msgid "Hide payload"
-msgstr ""
+msgstr "페ì´ë¡œë“œ 숨기기"
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "값 숨기기"
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4216,6 +4927,9 @@ msgstr "ì´ë ¥"
msgid "Housekeeping successfully started"
msgstr "Housekeepingì´ ì„±ê³µì ìœ¼ë¡œ 시작ë˜ì—ˆìŠµë‹ˆë‹¤"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr "%{terms_link}ì— ë™ì˜í•©ë‹ˆë‹¤."
@@ -4226,7 +4940,7 @@ msgid "ID"
msgstr "ID"
msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
-msgstr ""
+msgstr "CodeSandbox client side evaluation를 사용하여 Web IDEì—ì„œ JavaScript 프로ì íŠ¸ì˜ 실시간 미리보기를 허용합니다."
msgid "IDE|Back"
msgstr "뒤로"
@@ -4253,10 +4967,10 @@ msgid "IDE|Open in file view"
msgstr "íŒŒì¼ ë·°ì–´ë¡œ 열기"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
-msgstr ""
+msgstr "Web IDE client-side evaluationì„ í†µí•´ì„œ 웹 어플리케ì´ì…˜ì„ 미리 봅니다."
msgid "IDE|Refresh preview"
-msgstr ""
+msgstr "미리보기 새로 고침"
msgid "IDE|Review"
msgstr "리뷰"
@@ -4265,12 +4979,15 @@ msgid "IP Address"
msgstr "IP 주소"
msgid "Identifier"
-msgstr ""
+msgstr "ì‹ë³„ìž"
msgid "Identities"
-msgstr ""
+msgstr "ID"
msgid "Identity provider single sign on URL"
+msgstr "ID ì œê³µìž ì‹±ê¸€ì‚¬ì¸ì˜¨ URL"
+
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "If 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."
@@ -4289,7 +5006,7 @@ msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commit
msgstr ""
msgid "If you already have files you can push them using the %{link_to_cli} below."
-msgstr ""
+msgstr "ì´ë¯¸ 파ì¼ì´ 있는 경우 아래 %{link_to_cli} 를 사용하여 파ì¼ì„ 푸시 í•  수 있습니다."
msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
msgstr "HTTP 저장소를 공개ì ìœ¼ë¡œ 액세스할 수 없는 경우, URLì— ì¸ì¦ 정보를 추가하십시오:<code>https://username:password@gitlab.company.com/group/project.git</code>."
@@ -4303,12 +5020,18 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr "가져오기"
-msgid "Import Projects from Gitea"
+msgid "Import CSV"
msgstr ""
+msgid "Import Projects from Gitea"
+msgstr "Giteaì—ì„œ 프로ì íŠ¸ 가져오기"
+
msgid "Import all compatible projects"
msgstr "호환ë˜ëŠ” 모든 프로ì íŠ¸ 가져오기"
@@ -4319,9 +5042,18 @@ msgid "Import all repositories"
msgstr "모든 저장소 가져오기"
msgid "Import an exported GitLab project"
-msgstr ""
+msgstr "내보낸 GitLab 프로ì íŠ¸ 가져오기"
msgid "Import in progress"
+msgstr "가져오기 진행중"
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
msgstr ""
msgid "Import multiple repositories by uploading a manifest file."
@@ -4330,54 +5062,75 @@ msgstr ""
msgid "Import project"
msgstr "프로ì íŠ¸ 가져오기"
-msgid "Import projects from Bitbucket"
+msgid "Import project members"
msgstr ""
+msgid "Import projects from Bitbucket"
+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 projects from Google Code"
-msgstr ""
+msgstr "Google Codeì—ì„œ 프로ì íŠ¸ 가져오기"
msgid "Import repositories from Bitbucket Server"
msgstr ""
msgid "Import repositories from GitHub"
-msgstr ""
+msgstr "GitHub으로 부터 저장소 가져오기"
msgid "Import repository"
msgstr "저장소 가져 오기"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgstr "GitLab Enterprise Editionì„ í†µí•´ ì´ìŠˆ 보드를 í–¥ìƒ ì‹œí‚µë‹ˆë‹¤."
msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
-msgstr ""
+msgstr "ì´ìŠˆ 가중치와 GitLab Enterprise Editionì„ í†µí•´ ì´ìŠˆ 관리를 í–¥ìƒ ì‹œí‚¤ì„¸ìš”."
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr ""
+msgstr "고급 Global 검색과 GitLab Enterprise Edition ì„ í†µí•´ ê²€ìƒ‰ê¸°ëŠ¥ì„ í–¥ìƒì‹œí‚¤ì„¸ìš”."
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr "모든 사용ìžê°€ 수ë½í•´ì•¼ 하는 서비스 약관 ë° ê°œì¸ ì •ë³´ 보호 ì •ì±…ì„ í¬í•¨í•©ë‹ˆë‹¤."
+
+msgid "Include merge request description"
msgstr ""
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr "호환ë˜ì§€ 않는 프로ì íŠ¸"
@@ -4385,42 +5138,48 @@ msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inline"
-msgstr ""
+msgstr "ì¸ë¼ì¸"
msgid "Input host keys manually"
-msgstr ""
+msgstr "호스트 키를 수ë™ìœ¼ë¡œ ìž…ë ¥"
msgid "Input your repository URL"
+msgstr "저장소 URLì„ ìž…ë ¥ 하세요"
+
+msgid "Insert suggestion"
msgstr ""
msgid "Install GitLab Runner"
-msgstr ""
+msgstr "GitLab Runner 설치"
msgid "Install Runner on Kubernetes"
msgstr "Kubernetesì— Runner 설치"
msgid "Instance"
msgid_plural "Instances"
-msgstr[0] ""
+msgstr[0] "ì¸ìŠ¤í„´ìŠ¤"
msgid "Instance Statistics"
-msgstr ""
+msgstr "ì¸ìŠ¤í„´ìŠ¤ 통계"
msgid "Instance Statistics visibility"
-msgstr ""
+msgstr "ì¸ìŠ¤í„´ìŠ¤ 통계 가시성"
msgid "Instance does not support multiple Kubernetes clusters"
-msgstr ""
+msgstr "ì¸ìŠ¤í„´ìŠ¤ê°€ 여러 Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 지ì›í•˜ì§€ 않습니다."
msgid "Integrations"
-msgstr ""
+msgstr "ì—°ë™"
msgid "Integrations Settings"
-msgstr ""
+msgstr "ì—°ë™ ì„¤ì •"
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "관심있는 íŒŒí‹°ë“¤ì€ ì›í•˜ëŠ” ê³³ì— ì»¤ë°‹ì„ í‘¸ì‹œí•¨ìœ¼ë¡œì¨ ê¸°ì—¬í•  ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤."
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr "내부 - 그룹 ë° ëª¨ë“  내부 프로ì íŠ¸ëŠ” 로그ì¸í•œ 사용ìžê°€ ë³¼ 수 있습니다."
@@ -4436,17 +5195,35 @@ msgstr "주기 패턴"
msgid "Introducing Cycle Analytics"
msgstr "Cycle Analytics 소개"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr "초대"
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr "ì´ìŠˆ"
msgid "Issue Boards"
-msgstr ""
+msgstr "ì´ìŠˆ ë³´ë“œ"
msgid "Issue board focus mode"
-msgstr ""
+msgstr "ì´ìŠˆ ë³´ë“œ í¬ì»¤ìŠ¤ 모드"
msgid "Issue events"
msgstr "ì´ìŠˆ ì´ë²¤íŠ¸"
@@ -4457,6 +5234,21 @@ msgstr "보드"
msgid "IssueBoards|Boards"
msgstr "보드"
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr "ì´ìŠˆ"
@@ -4490,6 +5282,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4506,6 +5304,12 @@ msgid "Job"
msgstr "Job"
msgid "Job has been erased"
+msgstr "ìž‘ì—…ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤"
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
msgstr ""
msgid "Jobs"
@@ -4530,13 +5334,13 @@ msgid "Job|Job has been erased"
msgstr "ìž‘ì—…ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "Job|Job has been erased by"
-msgstr ""
+msgstr "ìž‘ì—…|ìž‘ì—…ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤. by"
msgid "Job|Keep"
-msgstr ""
+msgstr "유지"
msgid "Job|Scroll to bottom"
-msgstr ""
+msgstr "맨 아래로 스í¬ë¡¤"
msgid "Job|Scroll to top"
msgstr "맨 위로 스í¬ë¡¤"
@@ -4547,10 +5351,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4565,12 +5369,18 @@ msgstr "6ì›”"
msgid "June"
msgstr "6ì›”"
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
msgid "Kubernetes Cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°"
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ìƒì„± ì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆìŠµë‹ˆë‹¤. %{timeout}"
@@ -4620,7 +5430,7 @@ msgid "Labels"
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 "ë¼ë²¨ì€ ì´ìŠˆì™€ 머지 리퀘스트(MR)ì— ì¹´í…Œê³ ë¼ì´ì¦ˆë¥¼ 위해 ì ìš©ê°€ëŠ¥í•©ë‹ˆë‹¤."
@@ -4632,7 +5442,7 @@ msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</sp
msgstr "<span>ë¼ë²¨</span> %{labelTitle} <span>(ì„)를 그룹 ë¼ë²¨ë¡œ 승격하시겠습니까?</span>"
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. This action cannot be reversed."
msgstr ""
@@ -4647,11 +5457,14 @@ msgstr[0] "최근 %d ì¼"
msgid "Last Pipeline"
msgstr "최근 파ì´í”„ë¼ì¸"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "최근 커밋"
msgid "Last contact"
-msgstr ""
+msgstr "마지막 연결"
msgid "Last edited %{date}"
msgstr "%{date}ì— ë§ˆì§€ë§‰ 편집ë¨"
@@ -4662,6 +5475,9 @@ msgstr "%{name}가 마지막으로 편집함"
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr "최근 ì—…ë°ì´íŠ¸"
@@ -4677,15 +5493,39 @@ msgstr "at"
msgid "Latest changes"
msgstr "최근 변경사항"
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr "ë” ì•Œì•„ë³´ê¸°"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr "Kubernetesì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ë“¤ì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
@@ -4787,7 +5627,7 @@ msgstr "ë¼ì´ì„¼ìŠ¤"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
-msgstr[0] ""
+msgstr[0] "최대 %d ì´ë²¤íŠ¸ 만 표시하는 것으로 제한ë©ë‹ˆë‹¤."
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -4814,7 +5654,7 @@ msgid "Live preview"
msgstr "실시간 미리보기"
msgid "Loading contribution stats for group members"
-msgstr ""
+msgstr "그룹 구성ì›ë“¤ì˜ ê¸°ì—¬ë„ í†µê³„ì¹˜ 로드 중"
msgid "Loading the GitLab IDE..."
msgstr "GitLab IDE 로드 중..."
@@ -4822,6 +5662,12 @@ msgstr "GitLab IDE 로드 중..."
msgid "Loading..."
msgstr "불러오는 중…"
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr "잠금"
@@ -4835,22 +5681,22 @@ msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> w
msgstr ""
msgid "Lock to current projects"
-msgstr ""
+msgstr "현재 프로ì íŠ¸ 잠금"
msgid "Locked"
msgstr "ìž ê¹€"
msgid "Locked Files"
-msgstr ""
+msgstr "잠긴 파ì¼"
msgid "Locked to current projects"
-msgstr ""
+msgstr "현재 프로ì íŠ¸ì— ìž ê¹€"
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
msgid "Login with smartcard"
-msgstr ""
+msgstr "스마트 카드로 로그ì¸"
msgid "Logs"
msgstr "로그"
@@ -4868,7 +5714,7 @@ msgid "Manage Web IDE features"
msgstr "웹 IDE 기능 관리"
msgid "Manage access"
-msgstr ""
+msgstr "액세스 관리"
msgid "Manage all notifications"
msgstr "모든 알림 관리"
@@ -4880,14 +5726,17 @@ msgid "Manage applications that you've authorized to use your account."
msgstr ""
msgid "Manage group labels"
-msgstr ""
+msgstr "그룹 ë ˆì´ë¸” 관리"
msgid "Manage labels"
-msgstr ""
+msgstr "ë ˆì´ë¸” 관리"
msgid "Manage project labels"
msgstr "프로ì íŠ¸ ë¼ë²¨ 관리"
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4918,6 +5767,9 @@ msgstr "3ì›”"
msgid "Mark todo as done"
msgstr "í•  ì¼ì„ 완료로 표시"
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr "마í¬ë‹¤ìš´ 활성화ë¨"
@@ -4954,9 +5806,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr "Maven 메타 ë°ì´í„°"
-msgid "Maven package"
-msgstr "Maven 패키지"
-
msgid "Max access level"
msgstr "최대 액세스 수준"
@@ -4978,29 +5827,41 @@ msgstr ""
msgid "Members"
msgstr "회ì›"
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
msgid "Merge Request"
-msgstr "병합 요청"
-
-msgid "Merge Request:"
-msgstr "머지 리퀘스트(MR):"
+msgstr "머지 리퀘스트(MR)"
msgid "Merge Requests"
-msgstr "병합 요청"
+msgstr "머지 리퀘스트(MR)"
msgid "Merge Requests created"
-msgstr "병합 요청 ìƒì„±ë¨"
+msgstr "머지 리퀘스트(MR) ìƒì„±ë¨"
+
+msgid "Merge commit message"
+msgstr ""
msgid "Merge events"
msgstr "머지 ì´ë²¤íŠ¸"
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr "머지 리퀘스트(MR)"
msgid "Merge request approvals"
-msgstr "병합 요청 승ì¸"
+msgstr "머지 리퀘스트(MR) 승ì¸"
msgid "Merge requests"
msgstr "머지 리퀘스트(MR)"
@@ -5008,19 +5869,31 @@ msgstr "머지 리퀘스트(MR)"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "머지 리퀘스트(MR)는 프로ì íŠ¸ì˜ 변경 ì‚¬í•­ì„ ì œì•ˆí•˜ê³  변경 ì‚¬í•­ì„ ë‹¤ë¥¸ 사람들과 ë…¼ì˜ í•˜ëŠ” 곳입니다."
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5038,6 +5911,24 @@ msgstr "íŒŒì¼ ë³´ê¸° @ %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "êµì²´ëœ íŒŒì¼ ë³´ê¸° @ %{commitId}"
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5047,6 +5938,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr "머지ë¨"
@@ -5057,15 +5951,15 @@ msgid "Metrics"
msgstr ""
msgid "Metrics - Influx"
-msgstr ""
+msgstr "측정 - Influx"
msgid "Metrics - Prometheus"
-msgstr ""
+msgstr "측정 - Prometheus"
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5074,6 +5968,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5083,7 +5983,7 @@ msgstr "환경"
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5095,24 +5995,18 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr "ì´ë¦„"
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Query"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
-msgid "Metrics|Response"
-msgstr "ì‘답"
-
msgid "Metrics|System"
msgstr "시스템"
@@ -5125,10 +6019,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5149,21 +6043,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr "마ì¼ìŠ¤í†¤"
@@ -5180,10 +6065,10 @@ msgid "Milestones| You’re about to permanently delete the milestone %{mileston
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}ì„ ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ ë§ˆì¼ìŠ¤í†¤ì€ ì–´ë– í•œ ì´ìŠˆ ë˜ëŠ” 머지 리퀘스트(MR)ì—ì„œë„ ì‚¬ìš©ë˜ì§€ 않습니다."
msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
+msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
msgid "Milestones|Delete milestone"
msgstr "마ì¼ìŠ¤í†¤ ì‚­ì œ"
@@ -5213,7 +6098,7 @@ msgid "Mirror a repository"
msgstr "저장소 미러하기"
msgid "Mirror direction"
-msgstr ""
+msgstr "미러 방향"
msgid "Mirror repository"
msgstr "미러 저장소"
@@ -5236,6 +6121,18 @@ msgstr "취소"
msgid "Modal|Close"
msgstr "닫기"
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "모니터ë§"
@@ -5246,7 +6143,7 @@ msgid "More"
msgstr "ë” ë³´ê¸°"
msgid "More actions"
-msgstr ""
+msgstr "추가 작업"
msgid "More info"
msgstr "ë” ë§Žì€ ì •ë³´"
@@ -5276,7 +6173,7 @@ msgid "Name new label"
msgstr "새 ë¼ë²¨ ì´ë¦„ 지정"
msgid "Name your individual key via a title"
-msgstr ""
+msgstr "ì œëª©ì„ í†µí•´ 개별 키 ì´ë¦„ 지정"
msgid "Name:"
msgstr "ì´ë¦„:"
@@ -5296,11 +6193,14 @@ msgstr "ë¡œê·¸ì¸ / 등ë¡"
msgid "Nav|Sign out and sign in with a different account"
msgstr "로그아웃하고 다른 계정으로 로그ì¸"
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr "네트워í¬"
msgid "Never"
-msgstr ""
+msgstr "절대 아님"
msgid "New"
msgstr "신규"
@@ -5308,11 +6208,14 @@ msgstr "신규"
msgid "New Application"
msgstr "새로운 애플리케ì´ì…˜"
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr "새 그룹"
msgid "New Identity"
-msgstr ""
+msgstr "신규 ID"
msgid "New Issue"
msgid_plural "New Issues"
@@ -5321,6 +6224,12 @@ msgstr[0] "새 ì´ìŠˆ"
msgid "New Label"
msgstr "새 ë¼ë²¨"
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "새로운 파ì´í”„ë¼ì¸ ì¼ì •"
@@ -5339,9 +6248,12 @@ msgstr "새로운 브랜치 사용 불가능"
msgid "New directory"
msgstr "새 디렉토리"
-msgid "New epic"
+msgid "New environment"
msgstr ""
+msgid "New epic"
+msgstr "ì‹ ê·œ ì—픽"
+
msgid "New file"
msgstr "새 파ì¼"
@@ -5349,7 +6261,7 @@ msgid "New group"
msgstr "새 그룹"
msgid "New identity"
-msgstr ""
+msgstr "신규 ID"
msgid "New issue"
msgstr "새 ì´ìŠˆ"
@@ -5360,9 +6272,12 @@ msgstr "새 ë¼ë²¨"
msgid "New merge request"
msgstr "새 머지 리퀘스트(MR)"
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New milestone"
msgstr ""
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr "새로운 파ì´í”„ ë¼ì¸ì€ ë™ì¼í•œ ë¸Œëžœì¹˜ì— ìžˆëŠ” ì´ì „ì˜ ëŒ€ê¸° ì¤‘ì¸ íŒŒì´í”„ ë¼ì¸ì„ 취소 합니다."
+
msgid "New project"
msgstr "새 프로ì íŠ¸"
@@ -5387,6 +6302,9 @@ msgstr "아니오"
msgid "No Label"
msgstr "ë¼ë²¨ ì—†ìŒ"
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr "ë‹´ë‹¹ìž ì—†ìŒ"
@@ -5396,6 +6314,9 @@ msgstr "브랜치가 존재하지 않습니다."
msgid "No changes"
msgstr "변경 사항 ì—†ìŒ"
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Gitaly Serverì— ì—°ê²°í•  수 없습니다. 로그를 확ì¸í•˜ì‹­ì‹œì˜¤!"
@@ -5403,20 +6324,29 @@ msgid "No container images stored for this project. Add one by following the ins
msgstr ""
msgid "No contributions were found"
-msgstr ""
+msgstr "기여를 ì°¾ì„ ìˆ˜ 없습니다."
msgid "No credit card required."
+msgstr "신용 카드가 필요하지 않습니다."
+
+msgid "No details available"
msgstr ""
msgid "No due date"
msgstr "기한 ì—†ìŒ"
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr "ì˜ˆìƒ ì‹œê°„ì´ë‚˜ ì†Œë¹„ëœ ì‹œê°„ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "No file chosen"
msgstr "파ì¼ì„ ì„ íƒí•˜ì§€ 않았습니다."
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr "파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다."
@@ -5424,11 +6354,14 @@ msgid "No issues for the selected time period."
msgstr "ì„ íƒí•œ 기간 ë™ì•ˆ ì´ìŠˆê°€ 없습니다."
msgid "No labels with such name or description"
-msgstr ""
+msgstr "그런 ì´ë¦„ ë˜ëŠ” 설명ì´ìžˆëŠ” ë ˆì´ë¸”ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "No license. All rights reserved"
msgstr "ë¼ì´ì„¼ìŠ¤ê°€ 없습니다. All rights reserved"
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr "ì„ íƒí•œ 기간 ë™ì•ˆ 머지 리퀘스트(MR)ê°€ 없습니다."
@@ -5438,10 +6371,13 @@ msgstr "머지 리퀘스트(MR)를 ì°¾ì„ ìˆ˜ 없습니다."
msgid "No messages were logged"
msgstr "메시지가 기ë¡ë˜ì§€ 않았습니다."
-msgid "No other labels with such name or description"
+msgid "No milestones to show"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No other labels with such name or description"
+msgstr "그런 ì´ë¦„ ë˜ëŠ” 설명ì´ìžˆëŠ” 다른 ë ˆì´ë¸”ì´ ì—†ìŠµë‹ˆë‹¤."
+
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5451,7 +6387,7 @@ msgid "No public groups"
msgstr "공개 ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "No pushes for the selected time period."
-msgstr ""
+msgstr "ì„ íƒí•œ 기간 ë™ì•ˆ 푸시하지 않습니다."
msgid "No repository"
msgstr "저장소 ì—†ìŒ"
@@ -5462,21 +6398,18 @@ msgstr "Runners ì—†ìŒ"
msgid "No schedules"
msgstr "ì¼ì • ì—†ìŒ"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
msgid "Nodes"
-msgstr ""
+msgstr "노드"
msgid "None"
msgstr "ì—†ìŒ"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr "머지가 허용ë˜ì§€ ì•ŠìŒ"
@@ -5484,10 +6417,10 @@ msgid "Not available"
msgstr "사용할 수 ì—†ìŒ"
msgid "Not available for private projects"
-msgstr ""
+msgstr "프ë¼ì´ë¹— 프로ì íŠ¸ì—는 사용할 수 없습니다."
msgid "Not available for protected branches"
-msgstr ""
+msgstr "프로í…íŠ¸ëœ ë¸Œëžœì¹˜ì—는 사용할 수 없습니다."
msgid "Not confidential"
msgstr "비밀 아님"
@@ -5496,11 +6429,14 @@ msgid "Not enough data"
msgstr "ë°ì´í„°ê°€ 충분하지 않습니다."
msgid "Not now"
-msgstr ""
+msgstr "나중ì—"
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "마스터 브랜치는 ìžë™ìœ¼ë¡œ 보호ë©ë‹ˆë‹¤. %{link_to_protected_branches}"
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5531,6 +6467,12 @@ msgstr ""
msgid "Notification events"
msgstr "알림 ì´ë²¤íŠ¸"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "ì´ìŠˆ 닫기"
@@ -5544,7 +6486,7 @@ msgid "NotificationEvent|Merge merge request"
msgstr "머지 리퀘스트(MR) 머지하기"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "새 ì—픽"
msgid "NotificationEvent|New issue"
msgstr "새 ì´ìŠˆ"
@@ -5589,7 +6531,7 @@ msgid "Notifications"
msgstr "알림"
msgid "Notifications off"
-msgstr ""
+msgstr "알림 ë„기"
msgid "Notifications on"
msgstr "알림 켬"
@@ -5628,21 +6570,36 @@ msgstr ""
msgid "Only admins"
msgstr "관리ìžë§Œ 가능"
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr "프로ì íŠ¸ 구성ì›ë§Œ ëŒ“ê¸€ì„ ë‹¬ 수 있습니다."
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "ì´ëŸ°, 확실합니까?"
msgid "Open"
msgstr "열기"
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr "Xcodeì—ì„œ 열기"
@@ -5671,21 +6628,18 @@ msgid "Opens in a new window"
msgstr "새 창으로 열기"
msgid "Operations"
-msgstr ""
+msgstr "ìš´ì˜ìž"
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5733,6 +6687,12 @@ msgstr "패키지"
msgid "Pages"
msgstr "페ì´ì§€"
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "마지막 »"
@@ -5745,12 +6705,27 @@ msgstr "ì´ì „"
msgid "Pagination|« First"
msgstr "« 처ìŒ"
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr "머지 리퀘스트(MR) 변경 사항 중 ì¼ë¶€"
msgid "Password"
msgstr "패스워드"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5772,9 +6747,6 @@ msgstr "대기중"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "경로 변경, 그룹 전송 ë˜ëŠ” 제거와 ê°™ì€ ê³ ê¸‰ ì˜µì…˜ì„ ìˆ˜í–‰í•©ë‹ˆë‹¤."
@@ -5790,6 +6762,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr "ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°"
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "파ì´í”„ë¼ì¸"
@@ -5806,7 +6784,7 @@ msgid "Pipeline quota"
msgstr "파ì´í”„ë¼ì¸ 할당량"
msgid "Pipeline triggers"
-msgstr ""
+msgstr "파ì´í”„ë¼ì¸ 트리거"
msgid "PipelineCharts|Failed:"
msgstr "실패 :"
@@ -5899,16 +6877,16 @@ msgid "Pipelines|Something went wrong while cleaning runners cache."
msgstr "Runnerì˜ ìºì‹œë¥¼ ë¹„ìš°ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "Pipelines|There are currently no %{scope} pipelines."
-msgstr ""
+msgstr "%{scope} 파ì´í”„ë¼ì¸ 중 현재 실행중 ì¸ ê²ƒì€ ì—†ìŠµë‹ˆë‹¤."
msgid "Pipelines|There are currently no pipelines."
-msgstr ""
+msgstr "현재 ì‹¤í–‰ì¤‘ì¸ íŒŒì´í”„ë¼ì¸ì´ 없습니다."
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
-msgstr ""
+msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” 현재 파ì´í”„ë¼ì¸ì„ 실행하ë„ë¡ ì„¤ì •ë˜ì§€ 않았습니다."
msgid "Pipeline|Commit"
msgstr ""
@@ -5971,14 +6949,17 @@ msgid "Plain diff"
msgstr ""
msgid "PlantUML"
-msgstr ""
+msgstr "PlantUML"
msgid "Play"
msgstr "Play"
-msgid "Please accept the Terms of Service before continuing."
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
+msgid "Please accept the Terms of Service before continuing."
+msgstr "계ì†í•˜ê¸° ì „ì— ì„œë¹„ìŠ¤ ì•½ê´€ì— ë™ì˜í•˜ì‹­ì‹œì˜¤."
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -5988,14 +6969,20 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
msgid "Please select at least one filter to see results"
-msgstr ""
+msgstr "결과를 보려면 최소 í•˜ë‚˜ì˜ í•„í„°ë¥¼ ì„ íƒí•˜ì‹­ì‹œì˜¤"
msgid "Please solve the reCAPTCHA"
msgstr "ReCAPTCHA를 풀어 주십시오."
@@ -6003,6 +6990,9 @@ msgstr "ReCAPTCHA를 풀어 주십시오."
msgid "Please try again"
msgstr "다시 ì‹œë„í•´ 주세요."
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6010,13 +7000,13 @@ msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
-msgstr ""
+msgstr "저장소를 가져오는 ë™ì•ˆ 기다려주십시오. 완료ë˜ë©´ ìžë™ìœ¼ë¡œ 페ì´ì§€ë¥¼ 새로고침 합니다."
msgid "Preferences"
msgstr "환경 설정"
msgid "Preferences|Navigation theme"
-msgstr ""
+msgstr "테마 íƒìƒ‰"
msgid "Press Enter or click to search"
msgstr ""
@@ -6034,7 +7024,7 @@ msgid "Primary"
msgstr "주"
msgid "Prioritize"
-msgstr ""
+msgstr "우선 순위"
msgid "Prioritize label"
msgstr "ë¼ë²¨ ìš°ì„  순위"
@@ -6045,6 +7035,9 @@ msgstr "ìš°ì„  순위가 ì§€ì •ëœ ë¼ë²¨"
msgid "Prioritized label"
msgstr "ìš°ì„  순위가 ì§€ì •ëœ ë¼ë²¨"
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr "Private - 프로ì íŠ¸ ì ‘ê·¼ì€ ê° ì‚¬ìš©ìžë³„ë¡œ 명시ì ìœ¼ë¡œ 허용ë˜ì–´ì•¼ 합니다."
@@ -6052,7 +7045,7 @@ msgid "Private - The group and its projects can only be viewed by members."
msgstr "Private - 그룹과 ê·¸ë£¹ì˜ í”„ë¡œì íŠ¸ë“¤ì€ ë©¤ë²„ë“¤ì´ ì—´ëžŒí•  수 있습니다."
msgid "Private projects can be created in your personal namespace with:"
-msgstr ""
+msgstr "비공개 프로ì íŠ¸ëŠ” ê°œì¸ ë„¤ìž„ìŠ¤íŽ˜ì´ìŠ¤ì—ì„œ 만들어집니다:"
msgid "Profile"
msgstr "프로필"
@@ -6066,9 +7059,18 @@ msgstr "%{yourAccount}를 ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ìŠˆ, 머
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 "ì‚¬ìš©ìž ì´ë¦„ì„ %{currentUsernameBold}ì—ì„œ %{newUsernameBold}으로 변경하려고 합니다. 기존 프로필과 프로ì íŠ¸ë“¤ì€ %{newUsername}으로 리디렉션ë˜ì§€ë§Œ, %{currentUsername}ê°€ 다른 유저나 ê·¸ë£¹ì— ì˜í•´ 등ë¡ë˜ë©´ ë” ì´ìƒ 리디렉션ë˜ì§€ 않습니다. ì‚¬ìš©ìž ì´ë¦„ì„ ë³€ê²½í•œ ë’¤ git ì €ìž¥ì†Œì˜ ë¦¬ëª¨íŠ¸ë¥¼ 변경하세요."
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "ê³„ì •ì´ ì‚­ì œë  ì˜ˆì •ìž…ë‹ˆë‹¤."
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr "키 추가"
@@ -6076,7 +7078,7 @@ msgid "Profiles|Add status emoji"
msgstr "ìƒíƒœ ì´ëª¨í‹°ì½˜ 추가"
msgid "Profiles|Avatar cropper"
-msgstr ""
+msgstr "아바타 ìžë¥´ê¸°"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "아바타가 ì‚­ì œë©ë‹ˆë‹¤. 확실합니까?"
@@ -6084,15 +7086,30 @@ msgstr "아바타가 ì‚­ì œë©ë‹ˆë‹¤. 확실합니까?"
msgid "Profiles|Change username"
msgstr "사용ìžëª… 변경"
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr "íŒŒì¼ ì„ íƒ.."
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr "ìƒíƒœ 지우기"
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "현재 경로: %{path}"
@@ -6111,15 +7128,24 @@ msgstr "ê³„ì •ì„ ì‚­ì œí• ê¹Œìš”?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "ê³„ì •ì„ ì‚­ì œí•˜ë©´ 다ìŒê³¼ ê°™ì€ ì˜í–¥ì´ 있습니다:"
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr "í”„ë¡œí•„ì— í‘œì‹œí•˜ì§€ ì•ŠìŒ"
msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr ""
+msgstr "í”„ë¡œí•„ì— í™œë™ ê´€ë ¨ ê°œì¸ ì •ë³´ 표시 안함"
msgid "Profiles|Edit Profile"
msgstr "프로필 편집"
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "ìž˜ëª»ëœ íŒ¨ìŠ¤ì›Œë“œ"
@@ -6127,13 +7153,13 @@ msgid "Profiles|Invalid username"
msgstr "ìž˜ëª»ëœ ì‚¬ìš©ìžì´ë¦„"
msgid "Profiles|Learn more"
-msgstr ""
+msgstr "ë” ì•Œì•„ë³´ê¸°"
msgid "Profiles|Made a private contribution"
msgstr ""
msgid "Profiles|Main settings"
-msgstr ""
+msgstr "주요 설정"
msgid "Profiles|No file chosen"
msgstr "파ì¼ì´ ì„ íƒë˜ì§€ 않았습니다."
@@ -6142,10 +7168,10 @@ msgid "Profiles|Path"
msgstr "경로"
msgid "Profiles|Position and size your new avatar"
-msgstr ""
+msgstr "새 아바타 위치 ë° í¬ê¸° ì¡°ì ˆ"
msgid "Profiles|Private contributions"
-msgstr ""
+msgstr "비밀 기여"
msgid "Profiles|Public Avatar"
msgstr "공개 아바타"
@@ -6156,11 +7182,14 @@ msgstr "아바타 제거"
msgid "Profiles|Set new profile picture"
msgstr "새 프로필 사진 설정"
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr "ì¼ë¶€ ì˜µì…˜ì€ LDAP 계정ì—ì„œ 사용할 수 없습니다."
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
-msgstr "250ìž ë¯¸ë§Œìœ¼ë¡œ ìžì‹ ì— 대해 알려주세요."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "최대 허용ë˜ëŠ” 파ì¼ì˜ í¬ê¸°ëŠ” 200KB입니다."
@@ -6168,20 +7197,23 @@ msgstr "최대 허용ë˜ëŠ” 파ì¼ì˜ í¬ê¸°ëŠ” 200KB입니다."
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "ì´ê²ƒì€ 공개 SSH 키가 아닌것 같습니다. ì •ë§ë¡œ 추가 하시겠어요?"
-msgid "Profiles|This email will be displayed on your public profile."
-msgstr "ì´ ì´ë©”ì¼ì€ 공개 í”„ë¡œí•„ì— í‘œì‹œë©ë‹ˆë‹¤."
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
-msgstr ""
+msgstr "ì´ ì´ë©”ì¼ì€ 웹 기반 ìž‘ì—…, 수정ì´ë‚˜ mergeì— ì‚¬ìš©ë©ë‹ˆë‹¤. %{learn_more}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr "ì´ ê·¸ë¦¼ê³¼ 메시지는 프로필과 ì¸í„°íŽ˜ì´ìŠ¤ ì „ì²´ì— ë‚˜íƒ€ë‚©ë‹ˆë‹¤."
-msgid "Profiles|This feature is experimental and translations are not complete yet."
-msgstr "ì´ ê¸°ëŠ¥ì€ ì‹¤í—˜ì ì´ë©° ë²ˆì—­ì´ ì•„ì§ ì™„ë£Œë˜ì§€ 않았습니다."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
-msgid "Profiles|This information will appear on your profile."
-msgstr "ì´ ì •ë³´ëŠ” í”„ë¡œí•„ì— í‘œì‹œë©ë‹ˆë‹¤."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "확ì¸ì„ 위해 %{confirmationValue} 를 입력하세요."
@@ -6199,7 +7231,7 @@ msgid "Profiles|Upload new avatar"
msgstr "새 아바타 업로드"
msgid "Profiles|Use a private email - %{email}"
-msgstr ""
+msgstr "ê°œì¸ ì´ë©”ì¼ ì‚¬ìš© - %{email}"
msgid "Profiles|Username change failed - %{message}"
msgstr "ì‚¬ìš©ìž ì´ë¦„ 바꾸기 실패 - %{message}"
@@ -6207,12 +7239,15 @@ msgstr "ì‚¬ìš©ìž ì´ë¦„ 바꾸기 실패 - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "ì‚¬ìš©ìž ì´ë¦„ì„ ì„±ê³µì ìœ¼ë¡œ 바꿨습니다"
-msgid "Profiles|Website"
-msgstr "웹 사ì´íŠ¸"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
msgid "Profiles|What's your status?"
msgstr "ìƒíƒœëŠ” 어떤가요?"
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr "여기ì—ì„œ 아바타를 변경할 수 있습니다."
@@ -6223,7 +7258,7 @@ msgid "Profiles|You can upload your avatar here"
msgstr "여기ì—ì„œ 아바타를 업로드 í•  수 있습니다."
msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
-msgstr ""
+msgstr "ì´ê³³ì— 아바타를 업로드하거나 %{gravatar_link}ì—ì„œ 변경할 수 있습니다."
msgid "Profiles|You don't have access to delete this user."
msgstr "ì´ ì‚¬ìš©ìžë¥¼ 삭제할 ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
@@ -6231,16 +7266,19 @@ msgstr "ì´ ì‚¬ìš©ìžë¥¼ 삭제할 ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì„ ì‚­ì œí•˜ê¸° ì „ì— ì´ ê·¸ë£¹ë“¤ì˜ ì†Œìœ ê¶Œì„ ì´ì „하거나 삭제해야합니다."
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì€ í˜„ìž¬ ë‹¤ìŒ ê·¸ë£¹ë“¤ì˜ ì†Œìœ ìžìž…니다:"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6249,6 +7287,12 @@ msgstr "ë‚˜ì˜ ìƒíƒœ"
msgid "Profiles|e.g. My MacBook key"
msgstr "예: 내 MacBook 키"
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "계정"
@@ -6306,12 +7350,18 @@ msgstr "프로ì íŠ¸ 내보내기 ë§í¬ê°€ 만료ë˜ì—ˆìŠµë‹ˆë‹¤. 프로ì íŠ¸
msgid "Project export started. A download link will be sent by email."
msgstr "프로ì íŠ¸ 내보내기가 시작ë˜ì—ˆìŠµë‹ˆë‹¤. 다운로드 ë§í¬ëŠ” ì´ë©”ì¼ë¡œ 전송ë©ë‹ˆë‹¤."
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr "프로ì íŠ¸ ì´ë¦„"
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "구ë…"
@@ -6322,10 +7372,10 @@ msgid "ProjectCreationLevel|Default project creation protection"
msgstr ""
msgid "ProjectCreationLevel|Developers + Maintainers"
-msgstr ""
+msgstr "ê°œë°œìž + 관리ìž"
msgid "ProjectCreationLevel|Maintainers"
-msgstr ""
+msgstr "관리ìž"
msgid "ProjectCreationLevel|No one"
msgstr ""
@@ -6340,19 +7390,19 @@ msgid "ProjectLifecycle|Stage"
msgstr "스테ì´ì§•"
msgid "ProjectOverview|Fork"
-msgstr ""
+msgstr "í¬í¬"
msgid "ProjectOverview|Forks"
-msgstr ""
+msgstr "í¬í¬"
msgid "ProjectOverview|Go to your fork"
-msgstr ""
+msgstr "ë‚´ forkë¡œ ì´ë™"
msgid "ProjectOverview|Star"
-msgstr ""
+msgstr "별표"
msgid "ProjectOverview|Unstar"
-msgstr ""
+msgstr "별표 해제"
msgid "ProjectOverview|You have reached your project limit"
msgstr "프로ì íŠ¸ í•œë„ì— ë„달했습니다."
@@ -6394,7 +7444,7 @@ msgid "ProjectSettings|This setting will be applied to all projects unless overr
msgstr "관리ìžì— 변경ë˜ì§€ 않는 í•œ, ì´ ì„¤ì •ì€ ëª¨ë“  프로ì íŠ¸ì— ì ìš©ë©ë‹ˆë‹¤."
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
-msgstr ""
+msgstr "사용ìžëŠ” ì´ ì €ìž¥ì†Œì— ì¸ì¦ëœ ì´ë©”ì¼ë¡œ ì»¤ë°‹ëœ ì»¤ë°‹ë§Œì„ push í•  수 있습니다."
msgid "Projects"
msgstr "프로ì íŠ¸"
@@ -6456,14 +7506,11 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr "시간"
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
-msgstr ""
+msgstr "%{metrics} ì¸ %{exporters} 를 찾았습니다."
msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr ""
+msgstr "<p class=\"text-tertiary\"><a href=\"%{docsUrl}\">공통 메트릭스</a>ê°€ 발견ë˜ì§€ 않았습니다.</p>"
msgid "PrometheusService|Active"
msgstr "활성"
@@ -6472,10 +7519,10 @@ msgid "PrometheusService|Auto configuration"
msgstr "ìžë™ 설정"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
-msgstr ""
+msgstr "프로ì íŠ¸ í™˜ê²½ì„ ëª¨ë‹ˆí„°ë§í•˜ê¸° 위해 ë‹¹ì‹ ì˜ í´ëŸ¬ìŠ¤í„°ì— Prometheus를 ìžë™ìœ¼ë¡œ ë°°í¬í•˜ê³  설정하십시오."
msgid "PrometheusService|Common metrics"
-msgstr ""
+msgstr "공통 메트릭스"
msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
msgstr ""
@@ -6483,35 +7530,38 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
-msgid "PrometheusService|Finding and configuring metrics..."
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
msgstr ""
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr "메트릭스 항목 찾기 ë° ì„¤ì •..."
+
msgid "PrometheusService|Finding custom metrics..."
msgstr ""
msgid "PrometheusService|Install Prometheus on clusters"
-msgstr ""
+msgstr "í´ëŸ¬ìŠ¤í„°ì— Prometheus 설치"
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|More information"
-msgstr ""
+msgstr "추가 정보"
msgid "PrometheusService|New metric"
msgstr ""
msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
-msgstr ""
+msgstr "Prometheus API 기반 URL, 예를 들면 http://prometheus.example.com/"
msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
msgstr "ë‹¹ì‹ ì˜ í´ëŸ¬ìŠ¤í„°ì—ì„œ Prometheusê°€ ìžë™ìœ¼ë¡œ 관리ë˜ê³  있습니다."
@@ -6520,16 +7570,16 @@ msgid "PrometheusService|These metrics will only be monitored after your first d
msgstr ""
msgid "PrometheusService|Time-series monitoring service"
-msgstr ""
+msgstr "시간 계열 ëª¨ë‹ˆí„°ë§ ì„œë¹„ìŠ¤"
msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
-msgstr ""
+msgstr "ìˆ˜ë™ ì„¤ì •ì„ í™œì„±í™” 하려면, í´ëŸ¬ìŠ¤í„°ì—ì„œ Prometheus를 제거하십시오."
msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
-msgstr ""
+msgstr "í´ëŸ¬ìŠ¤í„°ì— Prometheus를 설치하려면, 아래 ìˆ˜ë™ ì„¤ì •ì„ ë¹„í™œì„±í™” 하십시오."
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
-msgstr ""
+msgstr "공통 매트릭스를 찾기 위하여 첫 환경 ë°°í¬ë¥¼ 기다리는 중입니다"
msgid "Promote"
msgstr "승격"
@@ -6544,16 +7594,16 @@ msgid "Promote to group label"
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 ""
msgid "Promotions|This feature is locked."
-msgstr ""
+msgstr "ì´ ê¸°ëŠ¥ì€ ìž ê²¨ìžˆìŠµë‹ˆë‹¤."
msgid "Promotions|Upgrade plan"
-msgstr ""
+msgstr "업그레ì´ë“œ 플랜"
msgid "Protected"
msgstr "보호ë¨"
@@ -6571,7 +7621,7 @@ msgid "ProtectedEnvironment|Choose who is allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
-msgstr ""
+msgstr "환경"
msgid "ProtectedEnvironment|Protect"
msgstr "보호"
@@ -6612,6 +7662,9 @@ msgstr "공급ìž"
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "공개 - ì´ ê·¸ë£¹ê³¼ 모든 공개 프로ì íŠ¸ë“¤ì€ ì–´ë–¤ ì¸ì¦ ì—†ì´ë„ ë³¼ 수 있습니다."
@@ -6619,7 +7672,7 @@ msgid "Public - The project can be accessed without any authentication."
msgstr "공개 - ì´ í”„ë¡œì íŠ¸ëŠ” ì–´ë–¤ ì¸ì¦ ì—†ì´ë„ 접근할 수 있습니다."
msgid "Public pipelines"
-msgstr ""
+msgstr "공용 파ì´í”„ ë¼ì¸"
msgid "Pull"
msgstr "Pull"
@@ -6640,30 +7693,39 @@ msgid "Push to create a project"
msgstr "푸쉬해서 프로ì íŠ¸ ìƒì„±"
msgid "PushRule|Committer restriction"
-msgstr ""
+msgstr "커미터 제한"
msgid "Pushed"
msgstr "푸시ë¨"
msgid "Pushes"
-msgstr ""
+msgstr "푸시"
msgid "Quarters"
+msgstr "분기별"
+
+msgid "Query"
msgstr ""
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Quick actionì€ ì´ìŠˆ 설명ì´ë‚˜ 댓글 박스ì—ì„œ 사용 가능합니다."
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "ë” ì½ê¸°"
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
-msgstr "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
msgid "Real-time features"
+msgstr "실시간 기능"
+
+msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
msgid "Recent searches"
@@ -6673,7 +7735,7 @@ msgid "Redirect to SAML provider to test configuration"
msgstr ""
msgid "Reference:"
-msgstr ""
+msgstr "참조:"
msgid "Refresh"
msgstr "새로고침"
@@ -6683,7 +7745,7 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgid "Regenerate key"
-msgstr ""
+msgstr "키 재ìƒì„±"
msgid "Regex pattern"
msgstr "ì •ê·œ í‘œí˜„ì‹ íŒ¨í„´"
@@ -6691,6 +7753,9 @@ msgstr "ì •ê·œ í‘œí˜„ì‹ íŒ¨í„´"
msgid "Register / Sign In"
msgstr "ë“±ë¡ / 로그ì¸"
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6721,6 +7786,12 @@ msgstr "관련 머지 리퀘스트(MR)"
msgid "Related merge requests"
msgstr "ê´€ë ¨ëœ ë¨¸ì§€ 리퀘스트(MR)"
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "ë‚˜ì¤‘ì— ë‹¤ì‹œ 알림"
@@ -6730,6 +7801,12 @@ msgstr "삭제"
msgid "Remove Runner"
msgstr "Runner 제거"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr "아바타 제거"
@@ -6760,7 +7837,13 @@ msgstr "í´ë” ì´ë¦„ 바꾸기"
msgid "Reopen epic"
msgstr "ì—픽 다시 열기"
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
+msgstr "ì¸ì¦ 복구"
+
+msgid "Reply to comment"
msgstr ""
msgid "Reply to this email directly or %{view_it_on_gitlab}."
@@ -6770,19 +7853,19 @@ msgid "Repo by URL"
msgstr "저장소 URL"
msgid "Report abuse to GitLab"
-msgstr ""
+msgstr "GitLabì— ì•…ìš© 사례 ì‹ ê³ "
msgid "Reporting"
msgstr "ë³´ê³ "
msgid "Reports|%{failedString} and %{resolvedString}"
-msgstr ""
+msgstr "%{failedString} ë° %{resolvedString}"
msgid "Reports|Actions"
-msgstr ""
+msgstr "ìž‘ì—…"
msgid "Reports|Class"
-msgstr ""
+msgstr "í´ëž˜ìŠ¤"
msgid "Reports|Confidence"
msgstr ""
@@ -6803,16 +7886,16 @@ msgid "Reports|Test summary"
msgstr "테스트 요약"
msgid "Reports|Test summary failed loading results"
-msgstr ""
+msgstr "테스트 요약 로드 실패"
msgid "Reports|Test summary results are being parsed"
-msgstr ""
+msgstr "테스트 요약 ê²°ê³¼ 분ì„중"
msgid "Reports|Vulnerability"
-msgstr ""
+msgstr "취약ì "
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "ë³€ê²½ëœ í…ŒìŠ¤íŠ¸ ê²°ê³¼ ì—†ìŒ"
msgid "Repository"
msgstr "저장소"
@@ -6823,6 +7906,12 @@ msgstr "저장소 설정"
msgid "Repository URL"
msgstr "저장소 URL"
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr "ì €ìž¥ì†Œì— ìž ê¸ˆì´ ì—†ìŠµë‹ˆë‹¤."
@@ -6841,28 +7930,52 @@ msgstr ""
msgid "Request Access"
msgstr "액세스 요청"
-msgid "Requests Profiles"
+msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requests Profiles"
+msgstr "요청 프로필"
+
msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "GitLabì— ì•¡ì„¸ìŠ¤ í•  ë•Œ 모든 사용ìžê°€ 서비스 약관 ë° ê°œì¸ ì •ë³´ 취급 ë°©ì¹¨ì— ë™ì˜í•˜ë„ë¡í•˜ì‹­ì‹œì˜¤."
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr "헬스 ì²´í¬ ì ‘ê·¼ í† í° ì´ˆê¸°í™”"
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "runner ë“±ë¡ í† í° ì´ˆê¸°í™”"
-msgid "Resolve all discussions in new issue"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
msgstr ""
+msgid "Resolve all discussions in new issue"
+msgstr "새로운 ì´ìŠˆì˜ 모든 í† ë¡ ì„ í•´ê²°í•˜ì‹­ì‹œì˜¤."
+
msgid "Resolve conflicts on source branch"
msgstr ""
msgid "Resolve discussion"
+msgstr "토론 해결"
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
msgstr ""
msgid "Response metrics (AWS ELB)"
@@ -6874,12 +7987,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr "재개"
@@ -6892,13 +8011,13 @@ msgstr "ì´ ìž‘ì—… 재시ë„"
msgid "Retry verification"
msgstr "ê²€ì¦ ìž¬ì‹œë„"
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] "값 표시"
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "ì´ ì»¤ë°‹ ë˜ëŒë¦¬ê¸°"
@@ -6926,9 +8045,12 @@ msgstr "로드맵"
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
-msgid "Run untagged jobs"
+msgid "Run tests against your code live using the Web Terminal"
msgstr ""
+msgid "Run untagged jobs"
+msgstr "태그없는 작업 실행"
+
msgid "Runner cannot be assigned to other projects"
msgstr ""
@@ -6953,6 +8075,9 @@ msgstr "Runners"
msgid "Runners API"
msgstr "Runners API"
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -6986,8 +8111,8 @@ msgstr "SAML Single Sign On"
msgid "SAML Single Sign On Settings"
msgstr "SAML Single Sign On 설정"
-msgid "SAST"
-msgstr "SAST"
+msgid "SAML for %{group_name}"
+msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -7007,6 +8132,9 @@ msgstr "SSL ê²€ì¦"
msgid "Save"
msgstr "저장"
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr "애플리케ì´ì…˜ 저장"
@@ -7016,6 +8144,9 @@ msgstr "변경사항 저장"
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "파ì´í”„ë¼ì¸ 스케줄 저장"
@@ -7052,6 +8183,9 @@ msgstr "맨 위로 스í¬ë¡¤"
msgid "Search"
msgstr "검색"
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr "브랜치 검색"
@@ -7064,6 +8198,9 @@ msgstr "íŒŒì¼ ê²€ìƒ‰"
msgid "Search for projects, issues, etc."
msgstr "프로ì íŠ¸, 문제 등 검색"
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr "머지 리퀘스트(MR) 검색"
@@ -7080,16 +8217,16 @@ msgid "Search project"
msgstr "프로ì íŠ¸ 검색"
msgid "Search projects"
-msgstr ""
+msgstr "프로ì íŠ¸ 검색"
msgid "Search users"
msgstr "ì‚¬ìš©ìž ê²€ìƒ‰"
msgid "Search your projects"
-msgstr ""
+msgstr "프로ì íŠ¸ 검색"
msgid "SearchAutocomplete|All GitLab"
-msgstr ""
+msgstr "모든 GitLab"
msgid "SearchAutocomplete|Issues I've created"
msgstr ""
@@ -7113,7 +8250,7 @@ msgid "SearchAutocomplete|in this project"
msgstr ""
msgid "Secret"
-msgstr ""
+msgstr "비밀"
msgid "Security"
msgstr "보안"
@@ -7133,26 +8270,29 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
-msgstr ""
+msgstr "ì´ìŠˆ ìƒì„±"
msgid "Security Reports|Dismiss vulnerability"
+msgstr "ì·¨ì•½ì  ë¬´ì‹œ"
+
+msgid "Security Reports|Learn more about setting up your dashboard"
msgstr ""
msgid "Security Reports|More info"
-msgstr ""
+msgstr "ë” ë§Žì€ ì •ë³´"
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
-msgstr ""
+msgstr "보안 대시보드 문서"
msgid "Security Reports|There was an error creating the issue."
-msgstr ""
+msgstr "ì´ìŠˆë¥¼ ìƒì„± í•˜ë˜ ì¤‘ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Security Reports|There was an error dismissing the vulnerability."
msgstr ""
@@ -7163,13 +8303,31 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
-msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgid "Security Reports|Undo dismiss"
msgstr ""
-msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgid "Security Reports|We've found no vulnerabilities for your group"
msgstr ""
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr "보안 대시보드ì—는 최신 보안 보고서가 표시ë©ë‹ˆë‹¤. 취약ì ì„ 찾고, ìˆ˜ì •í•˜ëŠ”ë° ì‚¬ìš©í•˜ì„¸ìš”."
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr "코드 ì·¨ì•½ì  ëª¨ë‹ˆí„°ë§"
+
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr "파ì´í”„ë¼ì¸ %{pipelineLink} 실행ë¨"
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
msgstr ""
msgid "Select"
@@ -7179,13 +8337,13 @@ msgid "Select Archive Format"
msgstr "ì•„ì¹´ì´ë¸Œ í¬ë§· ì„ íƒ"
msgid "Select a group to invite"
-msgstr ""
+msgstr "초대 í•  그룹 ì„ íƒ"
msgid "Select a namespace to fork the project"
-msgstr ""
+msgstr "프로ì íŠ¸ë¥¼ í¬í¬ë¥¼ 위한 ì´ë¦„ ì„ íƒ"
msgid "Select a template repository"
-msgstr ""
+msgstr "저장소 템플릿 ì„ íƒ"
msgid "Select a timezone"
msgstr "시간대 ì„ íƒ"
@@ -7199,20 +8357,23 @@ msgstr "ë‹´ë‹¹ìž ì„ íƒ"
msgid "Select branch/tag"
msgstr "브랜치/태그 ì„ íƒ"
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr "프로ì íŠ¸ ì„ íƒ"
msgid "Select project and zone to choose machine type"
-msgstr ""
+msgstr "머신 타입 ì„¤ì •ì„ ìœ„í•´ 프로ì íŠ¸ì™€ ì¡´ì„ ì„ íƒí•˜ì„¸ìš”."
msgid "Select project to choose zone"
msgstr ""
msgid "Select projects you want to import."
-msgstr ""
+msgstr "가져오고 ì‹¶ì€ í”„ë¡œì íŠ¸ë¥¼ ì„ íƒí•˜ì„¸ìš”."
msgid "Select source branch"
-msgstr ""
+msgstr "소스 브랜치 ì„ íƒ"
msgid "Select target branch"
msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜ ì„ íƒ"
@@ -7227,14 +8388,20 @@ msgid "Selecting a GitLab user will add a link to the GitLab user in the descrip
msgstr ""
msgid "Selective synchronization"
-msgstr ""
+msgstr "ì„ íƒì  ë™ê¸°í™”"
msgid "Send email"
msgstr "ì´ë©”ì¼ ì „ì†¡"
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr "사용 ë°ì´í„° 보내기"
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr "9ì›”"
@@ -7244,6 +8411,48 @@ msgstr "9ì›”"
msgid "Server version"
msgstr "서버 버전"
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr "서비스 ë°ìŠ¤í¬"
@@ -7254,7 +8463,7 @@ msgid "Service URL"
msgstr "서비스 URL"
msgid "Session expiration, projects limit and attachment size."
-msgstr ""
+msgstr "세션 만료, 프로ì íŠ¸ 제한 ë° ì²¨ë¶€ íŒŒì¼ í¬ê¸°."
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "%{protocol} í”„ë¡œí† ì½œì„ í†µí•´ Pull 하거나 Push하려면 ê³„ì •ì— íŒ¨ìŠ¤ì›Œë“œë¥¼ 설정하십시오."
@@ -7263,7 +8472,7 @@ msgid "Set a template repository for projects in this group"
msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
-msgstr ""
+msgstr "ê¸°ë³¸ê°’ì„ ì„¤ì •í•˜ê³  공개 ìˆ˜ì¤€ì„ ì œí•œí•˜ì‹­ì‹œì˜¤. 소스 가져오기와 git ì ‘ê·¼ í”„ë¡œí† ì½œì„ ì„¤ì •í•˜ì‹­ì‹œì˜¤."
msgid "Set instance-wide template repository"
msgstr ""
@@ -7274,6 +8483,9 @@ msgstr "웹 터미ë„ì˜ ìµœëŒ€ 세션 ì‹œê°„ì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Set notification email for abuse reports."
msgstr "남용 ë³´ê³ ì„œì— ëŒ€í•œ 알림 ì´ë©”ì¼ì„ 설정합니다."
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "사용ìžì˜ ë¡œê·¸ì¸ ìš”êµ¬ ì‚¬í•­ì„ ì„¤ì •í•©ë‹ˆë‹¤. 반드시 ì´ì¤‘ ì¸ì¦ 하ë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤."
@@ -7289,6 +8501,9 @@ msgstr "특정 Runner ìžë™ 설정"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7296,28 +8511,28 @@ msgid "SetPasswordToCloneLink|set a password"
msgstr "패스워드 설정"
msgid "SetStatusModal|Add status emoji"
-msgstr ""
+msgstr "ìƒíƒœ ì´ëª¨ì§€ 추가"
msgid "SetStatusModal|Clear status"
-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|What's your status?"
-msgstr ""
+msgstr "ìƒíƒœê°€ 어떤가요?"
msgid "Settings"
msgstr "설정"
@@ -7326,7 +8541,7 @@ msgid "Share"
msgstr "공유"
msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
-msgstr ""
+msgstr "회ì›ê³¼ <strong>%{sso_label}</strong> í•­ëª©ì„ ê³µìœ í•´ ì‹ ì› ì œê³µ 업체를 통해 ê·¸ë£¹ì— ë¡œê·¸ì¸í•  수 있ë„ë¡ í•©ë‹ˆë‹¤."
msgid "Shared Runners"
msgstr "공용 Runners"
@@ -7344,7 +8559,7 @@ msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr ""
msgid "Sherlock Transactions"
-msgstr ""
+msgstr "ì…œë¡ íŠ¸ëžœì ì…˜"
msgid "Show command"
msgstr "명령 보기"
@@ -7352,12 +8567,12 @@ msgstr "명령 보기"
msgid "Show complete raw log"
msgstr "완료 로그 표시"
+msgid "Show file browser"
+msgstr ""
+
msgid "Show latest version"
msgstr "최신 버전 보기"
-msgid "Show latest version of the diff"
-msgstr ""
-
msgid "Show parent pages"
msgstr "부모 페ì´ì§€ 보기"
@@ -7375,7 +8590,7 @@ msgid "Side-by-side"
msgstr "나란히"
msgid "Sidebar|Change weight"
-msgstr ""
+msgstr "ì¤‘ìš”ë„ ë³€ê²½"
msgid "Sidebar|None"
msgstr "ì—†ìŒ"
@@ -7384,7 +8599,7 @@ msgid "Sidebar|Only numeral characters allowed"
msgstr ""
msgid "Sidebar|Weight"
-msgstr ""
+msgstr "중요ë„"
msgid "Sign in"
msgstr "로그ì¸"
@@ -7392,12 +8607,21 @@ msgstr "로그ì¸"
msgid "Sign in / Register"
msgstr "ë¡œê·¸ì¸ / 등ë¡"
-msgid "Sign in to %{group_name}"
-msgstr "%{group_name}ì— ë¡œê·¸ì¸"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
msgid "Sign in with Single Sign-On"
msgstr "Single Sign-On으로 로그ì¸"
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr "로그아웃"
@@ -7407,11 +8631,14 @@ msgstr "ë¡œê·¸ì¸ ì œí•œ"
msgid "Sign-up restrictions"
msgstr "가입 제한"
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr "í¬ê¸°"
msgid "Size and domain settings for static websites"
-msgstr ""
+msgstr "ì •ì  ì›¹ 사ì´íŠ¸ì˜ í¬ê¸° ë° ë„ë©”ì¸ ì„¤ì •"
msgid "Slack application"
msgstr "Slack 어플리케ì´ì…˜"
@@ -7423,23 +8650,35 @@ msgid "Slower but makes sure the project workspace is pristine as it clones the
msgstr ""
msgid "Smartcard"
-msgstr ""
+msgstr "스마트카드"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr "스니펫"
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr "문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
msgid "Something went wrong on our end."
-msgstr ""
+msgstr "문제가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7449,9 +8688,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr "ë²„íŠ¼ì„ í† ê¸€í•˜ë˜ ì¤‘ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7470,6 +8715,9 @@ msgstr "프로ì íŠ¸ë¥¼ 가져오는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Something went wrong while fetching the registry list."
msgstr "레지스트리 목ë¡ì„ 가져오는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7492,11 +8740,17 @@ msgid "Sorry, no epics matched your search"
msgstr "죄송합니다. 검색과 ì¼ì¹˜í•˜ëŠ” ì—í”½ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "Sorry, no projects matched your search"
+msgstr "죄송합니다. 검색 결과와 ì¼ì¹˜í•˜ëŠ” 프로ì íŠ¸ê°€ 없습니다."
+
+msgid "Sorry, your filter produced no results"
msgstr ""
msgid "Sort by"
msgstr "다ìŒìœ¼ë¡œ ì •ë ¬"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr "권한 레벨, 오름차순"
@@ -7542,8 +8796,8 @@ msgstr "ëœ ì¸ê¸°ìžˆëŠ”"
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
-msgstr "마ì¼ìŠ¤í†¤"
+msgid "SortOptions|Milestone due date"
+msgstr ""
msgid "SortOptions|Milestone due later"
msgstr "마ì¼ìŠ¤í†¤ 마ê°ì¼ì´ 먼"
@@ -7575,6 +8829,9 @@ msgstr "ìƒì„±í•œì§€ 오래ëœ"
msgid "SortOptions|Oldest joined"
msgstr "참여한지 오래ëœ"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr "ë¡œê·¸ì¸ ìˆœ"
@@ -7587,6 +8844,9 @@ msgstr "ì¸ê¸°"
msgid "SortOptions|Priority"
msgstr "우선 순위"
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr "최근 로그ì¸"
@@ -7614,6 +8874,9 @@ msgstr "소스 코드"
msgid "Source is not available"
msgstr "소스를 사용할 수 없습니다."
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr "스팸 로그"
@@ -7629,6 +8892,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr "Runner 설정 중 ë‹¤ìŒ URLì„ ì§€ì •í•˜ì„¸ìš”."
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7636,10 +8902,10 @@ msgid "Stage"
msgstr "스테ì´ì§€"
msgid "Stage & Commit"
-msgstr ""
+msgstr "스테ì´ì§• & 커밋"
msgid "Stage all changes"
-msgstr ""
+msgstr "모든 변경사항 스테ì´ì§•"
msgid "Stage changes"
msgstr "스테ì´ì§€ 변경사항"
@@ -7665,6 +8931,12 @@ msgstr "별표 í‘œì‹œëœ í”„ë¡œì íŠ¸ 활ë™"
msgid "Starred projects"
msgstr "ë³„í‘œëœ í”„ë¡œì íŠ¸"
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "ì´ ë³€ê²½ 사항으로 %{new_merge_request} ì„ ì‹œìž‘í•˜ì‹­ì‹œì˜¤."
@@ -7674,9 +8946,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr "시작 날짜"
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Runner 시작!"
@@ -7686,6 +8970,15 @@ msgstr ""
msgid "Started"
msgstr "시작ë¨"
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "(UTC)ì— ì‹œìž‘"
@@ -7695,6 +8988,12 @@ msgstr ""
msgid "Status"
msgstr "ìƒíƒœ"
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7710,6 +9009,9 @@ msgstr "중지"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr "스토리지"
@@ -7725,6 +9027,9 @@ msgstr "서브 그룹과 프로ì íŠ¸"
msgid "Submit as spam"
msgstr "스팸으로 제출"
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7740,10 +9045,94 @@ msgstr "그룹 수준ì—ì„œ 구ë…"
msgid "Subscribe at project level"
msgstr "프로ì íŠ¸ 수준ì—ì„œ 구ë…"
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
+msgstr "구ë…ë¨"
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7753,12 +9142,15 @@ msgid "Sync information"
msgstr "ì •ë³´ ë™ê¸°í™”"
msgid "System Hooks"
-msgstr ""
+msgstr "시스템 훅"
msgid "System Info"
msgstr "시스템 정보"
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7767,9 +9159,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] "태그 (%{tag_count})"
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "태그 "
@@ -7838,7 +9232,7 @@ msgid "TagsPage|Tags give the ability to mark specific points in history as bein
msgstr "태그는 특정 지ì ì„ 중요하다고 표시하는 기능입니다."
msgid "TagsPage|This tag has no release notes."
-msgstr ""
+msgstr "ì´ íƒœê·¸ëŠ” 릴리즈 노트가 없습니다."
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "git tag ëª…ë ¹ì„ ì‚¬ìš©í•˜ì—¬ 새 태그를 추가하십시오:"
@@ -7864,6 +9258,12 @@ msgstr "템플릿"
msgid "Templates"
msgstr "템플릿"
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "서비스 약관 계약 ë° ê°œì¸ ì •ë³´ 보호 ì •ì±…"
@@ -7879,9 +9279,15 @@ msgstr "테스트 커버리지 파싱"
msgid "Thanks! Don't show me this again"
msgstr "ê°ì‚¬í•©ë‹ˆë‹¤! 다시 보지 않겠습니다."
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7918,6 +9324,9 @@ msgstr "%{timeout} ì´í›„ 가져오기 ì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆìŠµë‹ˆë‹¤. 저장ì†
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "ì´ìŠˆ 단계ì—는 ì´ìŠˆë¥¼ 작성하여 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 지정하는 ë° ê±¸ë¦¬ëŠ” 시간 ë˜ëŠ” ì´ìŠˆ ë³´ë“œì˜ ëª©ë¡ì— ì´ìŠˆë¥¼ 추가하는 ì‹œê°„ì´ í‘œì‹œë©ë‹ˆë‹¤. ì´ ë‹¨ê³„ì˜ ë°ì´í„°ë¥¼ 보기 위해서는 ì´ìŠˆë¥¼ 먼저 작성해야 합니다."
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr "허용ë˜ëŠ” 최대 íŒŒì¼ í¬ê¸°ëŠ” 200KB입니다."
@@ -7996,17 +9405,35 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "ê°’ì€ ì¼ë ¨ì˜ 관측 ê°’ 중ì ì— 있습니다. 예를 들어, 3, 5, 9 사ì´ì˜ 중간 ê°’ì€ 5입니다. 3, 5, 7, 8 사ì´ì˜ 중간 ê°’ì€ (5 + 7) / 2 = 6입니다."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr "표시할 ì´ìŠˆê°€ 없습니다"
msgid "There are no labels yet"
msgstr "ì•„ì§ ë¼ë²¨ì´ 없습니다."
-msgid "There are no merge requests to show"
-msgstr "표시할 머지 리퀘스트(MR)가 없습니다."
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
@@ -8024,7 +9451,7 @@ msgid "There was an error deleting the todo."
msgstr "í•  ì¼ì„ 삭제하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "There was an error loading users activity calendar."
-msgstr ""
+msgstr "ì‚¬ìš©ìž í™œë™ ìº˜ë¦°ë”를 로딩하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "There was an error saving your notification settings."
msgstr "알림 ì„¤ì •ì„ ì €ìž¥í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -8036,15 +9463,24 @@ msgid "There was an error when reseting email token."
msgstr "ì´ë©”ì¼ í† í°ì„ ìž¬ì„¤ì •í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "There was an error when subscribing to this label."
-msgstr ""
+msgstr "ì´ ë¼ë²¨ì„ 구ë…í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "There was an error when unsubscribing from this label."
+msgstr "ì´ ë¼ë²¨ì„ 구ë…ì·¨ì†Œí•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
msgid "They can be managed using the %{link}."
msgstr "%{link}를 사용하여 관리 할 수 ​​있습니다."
msgid "Third party offers"
+msgstr "타사 제공"
+
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
@@ -8057,7 +9493,7 @@ msgid "This application will be able to:"
msgstr "ì´ ì‘ìš© í”„ë¡œê·¸ëž¨ì€ ë‹¤ìŒì„ 수행 í•  수 있습니다."
msgid "This board's scope is reduced"
-msgstr ""
+msgstr "ì´ ë³´ë“œì˜ ë²”ìœ„ê°€ 축소ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
@@ -8072,17 +9508,20 @@ msgid "This date is before the start date, so this epic won't appear in the road
msgstr ""
msgid "This diff is collapsed."
+msgstr "ì´ ë¹„êµëŠ” 접혀있습니다."
+
+msgid "This diff was suppressed by a .gitattributes entry."
msgstr ""
msgid "This directory"
msgstr "ì´ ë””ë ‰í† ë¦¬"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
msgid "This group"
msgstr "ì´ ê·¸ë£¹"
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr ""
-
msgid "This group does not provide any group Runners yet."
msgstr "ì´ ê·¸ë£¹ì€ ì•„ì§ ê·¸ë£¹ Runners를 제공하지 않습니다."
@@ -8105,13 +9544,13 @@ msgid "This issue is locked."
msgstr "ì´ ì´ìŠˆëŠ” lock ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì€ ì‚¬ìš©ìžì˜ 트리거 í”„ë¡œì„¸ìŠ¤ì— ì˜ì¡´í•©ë‹ˆë‹¤. 종종 ìš´ì˜í™˜ê²½ì— 코드를 ë°°í¬í•˜ëŠ”ë° ì“°ì´ê¸°ë„ 합니다."
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
msgstr "ì´ ìž‘ì—…ì„ ì‹œìž‘í•˜ë ¤ë©´ ì—… 스트림 ìž‘ì—…ì˜ ì„±ê³µì„ í•„ìš”ë¡œ 합니다."
msgid "This job does not have a trace."
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì€ ì´ë ¥ì´ 남아 있지 않습니다."
msgid "This job has been canceled"
msgstr "ì´ ìž‘ì—…ì€ ì·¨ì†Œë˜ì—ˆìŠµë‹ˆë‹¤"
@@ -8143,10 +9582,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "ì´ ìž‘ì—…ì€ ëŒ€ê¸° ìƒíƒœì´ë©° Runnerê°€ 실행하기를 기다리고 있습니다."
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8155,7 +9594,7 @@ msgstr "ì´ ìž‘ì—…ì€ %{link}ì— ëŒ€í•œ 가장 ìµœê·¼ì˜ ë°°í¬ìž…니다."
msgid "This job requires a manual action"
msgstr "ì´ ìž‘ì—…ì—는 ìˆ˜ë™ ìž‘ì—…ì´ í•„ìš”í•©ë‹ˆë‹¤."
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8165,17 +9604,26 @@ msgid "This merge request is locked."
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)는 잠겨있습니다."
msgid "This option is disabled as you don't have write permissions for the current branch"
-msgstr ""
+msgstr "현재 ë¸Œëžœì¹˜ì— ëŒ€í•œ 쓰기 ê¶Œí•œì´ ì—†ìœ¼ë¯€ë¡œ ì´ ì˜µì…˜ì´ ë¹„í™œì„±í™”ë©ë‹ˆë‹¤."
msgid "This option is disabled while you still have unstaged changes"
msgstr ""
msgid "This page is unavailable because you are not allowed to read information across multiple projects."
-msgstr ""
+msgstr "여러 프로ì íŠ¸ì—ì„œ 정보를 ì½ì„ 수 없으므로 ì´ íŽ˜ì´ì§€ë¥¼ 사용할 수 없습니다."
msgid "This page will be removed in a future release."
msgstr "ì´ íŽ˜ì´ì§€ëŠ” 앞으로 릴리스ì—ì„œ ì œê±°ë  ì˜ˆì •ìž…ë‹ˆë‹¤."
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr "ì´ í”„ë¡œì íŠ¸"
@@ -8203,7 +9651,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8215,7 +9663,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8406,9 +9854,18 @@ msgstr "íŒ:"
msgid "Title"
msgstr "제목"
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr "GitLab으로"
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8419,7 +9876,7 @@ msgid "To connect GitHub repositories, you first need to authorize GitLab to acc
msgstr "GitHub ì €ìž¥ì†Œì— ì—°ê²°í•˜ë ¤ë©´, 먼저 GitHub 저장소 목ë¡ì„ 액세스 í•  수 있ë„ë¡ GitLabì— ì—‘ì„¸ìŠ¤ ê¶Œí•œì„ ë¶€ì—¬í•´ì•¼í•©ë‹ˆë‹¤:"
msgid "To connect an SVN repository, check out %{svn_link}."
-msgstr ""
+msgstr "SVN ì €ìž¥ì†Œì— ì—°ê²°í•˜ë ¤ë©´ %{svn_link}ì„ í™•ì¸í•˜ì‹­ì‹œì˜¤."
msgid "To define internal users, first enable new users set to external"
msgstr ""
@@ -8451,13 +9908,28 @@ msgstr "GitHub 저장소를 가져오려면, 먼저 GitHub 저장소 목ë¡ì„ ì
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "SVN 저장소ì—ì„œ 가져오려면, %{svn_link}(ì„)를 확ì¸í•˜ì„¸ìš”."
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr "CI/CD 기능만 외부 저장소를 위해 사용할 수 있습니다, <strong>외부 저장소용 CI/CD 저장소</strong>를 ì„ íƒí•˜ì‹­ì‹œì˜¤."
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8466,6 +9938,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr "ì´ GitLab ì¸ìŠ¤í„´ìŠ¤ë¡œ"
@@ -8475,11 +9950,14 @@ msgstr "GitLab CI êµ¬ì„±ì„ ê²€ì¦í•˜ë ¤ë©´ 프로ì íŠ¸ ë‚´ë¶€ì˜ 'CI/CD → íŒ
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
msgid "Today"
-msgstr ""
+msgstr "오늘"
msgid "Todo"
msgstr "Todo"
@@ -8488,19 +9966,22 @@ msgid "Todos"
msgstr "í• ì¼ë“¤"
msgid "Toggle Sidebar"
+msgstr "사ì´ë“œë°” 전환"
+
+msgid "Toggle comments for this file"
msgstr ""
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
-msgstr ""
+msgid "Toggle discussion"
+msgstr "토글 토론"
msgid "Toggle navigation"
-msgstr ""
+msgstr "토글 네비게ì´ì…˜"
msgid "Toggle sidebar"
msgstr "사ì´ë“œë°” 토글"
@@ -8518,10 +9999,10 @@ msgid "Tomorrow"
msgstr ""
msgid "Too many changes to show."
-msgstr ""
+msgstr "표시 í•  변경 ì‚¬í•­ì´ ë„ˆë¬´ 많습니다."
msgid "Total Contributions"
-msgstr ""
+msgstr "ì´ ê¸°ì—¬ë„"
msgid "Total Time"
msgstr "시간 합계:"
@@ -8542,7 +10023,7 @@ msgid "Track groups of issues that share a theme, across projects and milestones
msgstr ""
msgid "Track time with quick actions"
-msgstr ""
+msgstr "퀵 ì•¡ì…˜ 시간 추ì "
msgid "Tree view"
msgstr ""
@@ -8550,9 +10031,6 @@ msgstr ""
msgid "Trending"
msgstr "ì¸ê¸°"
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8562,6 +10040,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr "수ë™ìœ¼ë¡œ 실행해주세요."
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8571,7 +10055,13 @@ msgstr ""
msgid "Try again"
msgstr "다시 ì‹œë„하십시오"
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
+msgstr "GitLabì´ ì œê³µí•˜ëŠ” 모든 ê¸°ëŠ¥ì„ 30ë™ì•ˆ 사용해 보세요."
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
msgid "Turn on Service Desk"
@@ -8581,16 +10071,16 @@ msgid "Twitter"
msgstr "Twitter"
msgid "Two-factor authentication"
-msgstr ""
+msgstr "2단계 ì¸ì¦"
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
-msgstr ""
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr "ì°¨ì´ì ì„ ì½ì–´ë“¤ì¼ 수 없습니다. %{button_try_again}"
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
@@ -8598,17 +10088,23 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr "실행 취소"
-msgid "Unknown"
+msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
+msgid "Unknown"
+msgstr "ì•Œ 수 ì—†ìŒ"
+
msgid "Unlock"
msgstr "잠금 해제"
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr ""
+msgstr "%{issuableDisplayName}(ì„)를 잠금해제 하시겠습니까? <strong>모ë‘ê°€</strong> 코멘트 í•  수 있게 ë©ë‹ˆë‹¤."
msgid "Unlocked"
msgstr "잠금 í•´ì œë¨"
@@ -8620,7 +10116,7 @@ msgid "Unschedule job"
msgstr ""
msgid "Unstage"
-msgstr ""
+msgstr "스테ì´ì§• 취소"
msgid "Unstage all changes"
msgstr ""
@@ -8649,6 +10145,9 @@ msgstr "그룹 수준ì—ì„œ êµ¬ë… í•´ì œ"
msgid "Unsubscribe at project level"
msgstr "프로ì íŠ¸ 수준ì—ì„œ êµ¬ë… í•´ì œ"
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr "ê²€ì¦ë˜ì§€ ì•ŠìŒ"
@@ -8661,6 +10160,9 @@ msgstr ""
msgid "Update"
msgstr "ì—…ë°ì´íŠ¸"
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr "지금 ì—…ë°ì´íŠ¸"
@@ -8670,6 +10172,9 @@ msgstr ""
msgid "Updating"
msgstr "ì—…ë°ì´íŠ¸ì¤‘..."
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "고급 글로벌 ê²€ìƒ‰ì„ í™œì„±í™”í•˜ê¸° 위해 í”Œëžœì„ ì—…ê·¸ë ˆì´ë“œí•˜ì„¸ìš”."
@@ -8688,20 +10193,35 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "새 íŒŒì¼ ì—…ë¡œë“œ"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "íŒŒì¼ ì—…ë¡œë“œ"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "업로드하려면 í´ë¦­í•˜ì‹­ì‹œì˜¤."
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr "추천"
msgid "Usage ping is not enabled"
-msgstr ""
+msgstr "ping ì‚¬ìš©ì´ í™œì„±í™” ë˜ì§€ 않았습니다."
msgid "Usage statistics"
msgstr "사용 통계"
@@ -8713,7 +10233,7 @@ msgid "Use Service Desk to connect with your users (e.g. to offer customer suppo
msgstr ""
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
-msgstr ""
+msgstr "그룹 마ì¼ìŠ¤í†¤ì„ 사용하시면 여러 프로ì íŠ¸ì˜ ì´ìŠˆë“¤ì„ í•˜ë‚˜ì˜ ë§ˆì¼ìŠ¤í†¤ìœ¼ë¡œ 관리할 수 있습니다."
msgid "Use one line per URI"
msgstr ""
@@ -8727,9 +10247,15 @@ msgstr "설정 ì¤‘ì— ë‹¤ìŒ ë“±ë¡ í† í° ì´ìš© : "
msgid "Use your global notification setting"
msgstr "전체 알림 설정 사용"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8743,58 +10269,94 @@ msgid "User map"
msgstr ""
msgid "UserProfile|Activity"
-msgstr ""
+msgstr "활ë™"
msgid "UserProfile|Already reported for abuse"
-msgstr ""
+msgstr "ì´ë¯¸ 악용으로 ì‹ ê³ ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "UserProfile|Contributed projects"
-msgstr ""
+msgstr "기여한 프로ì íŠ¸ë“¤"
msgid "UserProfile|Edit profile"
+msgstr "프로필 수정"
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr ""
msgid "UserProfile|Groups"
+msgstr "그룹"
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
msgstr ""
msgid "UserProfile|Most Recent Activity"
+msgstr "최근 활ë™"
+
+msgid "UserProfile|No snippets found."
msgstr ""
msgid "UserProfile|Overview"
-msgstr ""
+msgstr "개요"
msgid "UserProfile|Personal projects"
-msgstr ""
-
-msgid "UserProfile|Recent contributions"
-msgstr ""
+msgstr "ê°œì¸ í”„ë¡œì íŠ¸"
msgid "UserProfile|Report abuse"
-msgstr ""
+msgstr "악용사례 신고"
msgid "UserProfile|Snippets"
+msgstr "스니펫"
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
msgstr ""
msgid "UserProfile|Subscribe"
+msgstr "구ë…"
+
+msgid "UserProfile|This user doesn't have any personal projects"
msgstr ""
msgid "UserProfile|This user has a private profile"
msgstr ""
-msgid "UserProfile|View all"
+msgid "UserProfile|This user hasn't contributed to any projects"
msgstr ""
+msgid "UserProfile|View all"
+msgstr "ëª¨ë‘ ë³´ê¸°"
+
msgid "UserProfile|View user in admin area"
+msgstr "ê´€ë¦¬ìž ì˜ì—­ì—ì„œ ì‚¬ìš©ìž ë³´ê¸°"
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
msgid "Users"
msgstr "사용ìžë“¤"
-msgid "Variables"
-msgstr "변수"
+msgid "Users requesting access to"
+msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr "변수는 runner를 통해 í™˜ê²½ì— ì ìš©ë©ë‹ˆë‹¤. 변수는 ë³´í˜¸ëœ ë¸Œëžœì¹˜ë‚˜ 태그ì—만 노출하여 보호할 수 있습니다. 비밀번호, 암호키, ë˜ëŠ” ì›í•˜ëŠ”대로 변수를 사용할 수 있습니다."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
msgid "Various container registry settings."
msgstr "여러가지 컨테ì´ë„ˆ 레지스트리 설정."
@@ -8802,12 +10364,18 @@ msgstr "여러가지 컨테ì´ë„ˆ 레지스트리 설정."
msgid "Various email settings."
msgstr "여러가지 ì´ë©”ì¼ ì„¤ì •."
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr "GitLab ì„±ëŠ¥ì— ì˜í–¥ì„ 주는 여러가지 설정."
msgid "Verification information"
msgstr "ì¸ì¦ ì •ë³´"
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr "ê²€ì¦ë¨"
@@ -8815,19 +10383,25 @@ msgid "Version"
msgstr "버전"
msgid "View %{alerts}"
-msgstr ""
+msgstr "%{alerts} 보기"
msgid "View app"
+msgstr "앱 보기"
+
+msgid "View deployment"
msgstr ""
-msgid "View documentation"
+msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr "문서 보기"
+
msgid "View epics list"
msgstr "ì—픽 ëª©ë¡ ë³´ê¸°"
msgid "View file @ "
-msgstr ""
+msgstr "파ì¼ë³´ê¸° @ "
msgid "View group labels"
msgstr "그룹 ë¼ë²¨ 보기"
@@ -8857,10 +10431,13 @@ msgid "View replaced file @ "
msgstr "êµì²´ëœ íŒŒì¼ ë³´ê¸° @ "
msgid "View the documentation"
+msgstr "문서 보기"
+
+msgid "Viewing commit"
msgstr ""
msgid "Visibility and access controls"
-msgstr ""
+msgstr "공개 범위 ë° ì•¡ì„¸ìŠ¤ 설정"
msgid "Visibility level"
msgstr ""
@@ -8883,6 +10460,12 @@ msgstr "Public"
msgid "VisibilityLevel|Unknown"
msgstr "ì•Œ 수 ì—†ìŒ"
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8907,27 +10490,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ì´ ë°ì´í„°ë¥¼ ë³´ê³  싶ì€ê°€ìš”? 관리ìžì—게 액세스 ê¶Œí•œì„ ìš”ì²­í•˜ì„¸ìš”."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "%{humanized_resource_name}ì—ì„œ 잠재ì ì¸ ìŠ¤íŒ¸ì„ íƒì§€í–ˆìŠµë‹ˆë‹¤. 계ì†í•˜ë ¤ë©´ reCAPTCHA를 진행하세요."
msgid "We don't have enough data to show this stage."
msgstr "ì´ ë‹¨ê³„ë¥¼ ë³´ì—¬ì£¼ê¸°ì— ì¶©ë¶„í•œ ë°ì´í„°ê°€ 없습니다."
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "ì •ë§ ë‹¹ì‹ ì´ ë§žëŠ”ì§€ 확ì¸í•˜ê³  싶습니다, ë‹¹ì‹ ì´ ë¡œë´‡ì´ ì•„ë‹ˆë¼ëŠ” ê²ƒì„ í™•ì¸í•´ì£¼ì‹­ì‹œì˜¤."
msgid "Web IDE"
msgstr "웹 IDE"
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr "웹 터미ë„"
@@ -8952,11 +10556,14 @@ msgstr "사용 설정ë˜ë©´ 사용ìžëŠ” GitLab ì•½ê´€ì´ ìˆ˜ë½ ë  ë•Œê¹Œì§€ G
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
-msgid "Who can see this group?"
+msgid "When:"
msgstr ""
+msgid "Who can see this group?"
+msgstr "누가 ì´ ê·¸ë£¹ì„ ë³¼ 수 있나요?"
+
msgid "Who will be able to see this group?"
-msgstr ""
+msgstr "누가 ì´ ê·¸ë£¹ì„ ë³¼ 수 있게 ë˜ë‚˜ìš”?"
msgid "Wiki"
msgstr "위키"
@@ -9093,12 +10700,21 @@ msgstr "페ì´ì§€"
msgid "Wiki|Wiki Pages"
msgstr "위키 페ì´ì§€"
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr "액세스 요청 철회"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr "예"
@@ -9109,6 +10725,9 @@ msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr "네, Google code 사용ìžë¥¼ ì´ë¦„ì´ë‚˜ GitLab 사용ìžì— 연결하겠습니다."
msgid "Yesterday"
+msgstr "어제"
+
+msgid "You"
msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
@@ -9129,6 +10748,9 @@ msgstr "%{project_full_name} (ì„) 를 다른 소유ìžì—게 ì´ì „하려고합
msgid "You are on a read-only GitLab instance."
msgstr "ì½ê¸°ì „ìš© GitLab ì¸ìŠ¤í„´ìŠ¤ë¥¼ 사용중입니다."
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9153,6 +10775,9 @@ msgstr "ë¸Œëžœì¹˜ì— ìžˆì„ ë•Œì—만 파ì¼ì„ 추가 í•  수 있습니다."
msgid "You can only edit files when you are on a branch"
msgstr "ë¸Œëžœì¹˜ì— ìžˆì„ ë•Œë§Œ 파ì¼ì„ 편집할 수 있습니다."
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9171,6 +10796,9 @@ msgstr "ì½ê¸° ì „ìš© GitLab ì¸ìŠ¤í„´ìŠ¤ì—는 쓰기가 불가능합니다."
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9180,12 +10808,18 @@ msgstr "ë‹¹ì‹ ì€ ì• í”Œë¦¬ì¼€ì´ì…˜ì„ 가지고 있지 않습니다."
msgid "You don't have any authorized applications"
msgstr "ìŠ¹ì¸ ëœ ì• í”Œë¦¬ì¼€ì´ì…˜ì´ 없습니다."
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr "ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
msgid "You have reached your project limit"
msgstr "프로ì íŠ¸ ìˆ«ìž í•œë„ì— ë„달했습니다."
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr "ê³„ì •ì„ ë“±ë¡í•˜ë ¤ë©´ 서비스 약관 ë° ê°œì¸ ì •ë³´ 취급 ë°©ì¹¨ì— ë™ì˜í•´ì•¼í•©ë‹ˆë‹¤."
@@ -9195,16 +10829,22 @@ msgstr "강제로 ìž ê¸ˆì„ ì œê±°í•˜ë ¤ë©´ ê´€ë¦¬ìž ê¶Œí•œì´ ìžˆì–´ì•¼í•©ë‹ˆë
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr "ê¶Œí•œì´ í•„ìš”í•©ë‹ˆë‹¤."
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9246,8 +10886,11 @@ msgstr "ì´ ì´ë©”ì¼ì„ 받는 ì´ìœ ëŠ” 사용ìžì˜ ê³„ì •ì´ %{host}ì— ìžˆê
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
-msgstr "ë‹¹ì‹ ì˜ ê·¸ë£¹"
+msgstr "ë‚˜ì˜ ê·¸ë£¹ë“¤"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "ì´ íŽ˜ì´ì§€ì—ì„œ Kubernetes í´ëŸ¬ìŠ¤í„° 정보를 계ì†í•´ì„œ 편집할 수 있지만, 비활성화 하거나 재설정하는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
@@ -9261,12 +10904,18 @@ msgstr "ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ 활ë™"
msgid "Your Todos"
msgstr "ë‹¹ì‹ ì˜ í• ì¼"
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr "승ì¸ëœ 애플리케ì´ì…˜ (%{size})"
msgid "Your authorized applications"
msgstr "승ì¸ëœ 애플리케ì´ì…˜"
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "머지 리퀘스트(MR)ê°€ 열려있기 ë•Œë¬¸ì— ë³€ê²½ì‚¬í•­ì€ %{branch_name}(으)ë¡œ ì»¤ë°‹ë  ìˆ˜ 있습니다."
@@ -9279,12 +10928,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr "ëŒ“ê¸€ì´ ê³µê°œì— í‘œì‹œë˜ì§€ 않습니다."
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "ë‹¹ì‹ ì˜ ê·¸ë£¹"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "ê·€í•˜ì˜ ì´ë¦„"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr "ë‚´ 프로ì íŠ¸"
@@ -9294,12 +10955,18 @@ msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
msgid "ago"
msgstr "ì „"
-msgid "among other things"
+msgid "allowed to fail"
msgstr ""
+msgid "among other things"
+msgstr "다른 것들 중"
+
msgid "assign yourself"
msgstr "ìžì‹ ì„ 담당ìžë¡œ 지정"
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr "브랜치 ì´ë¦„"
@@ -9388,6 +11055,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9403,6 +11073,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9466,7 +11142,7 @@ msgid "ciReport|Revert dismissal"
msgstr ""
msgid "ciReport|SAST"
-msgstr ""
+msgstr "SAST"
msgid "ciReport|Security scanning"
msgstr ""
@@ -9520,6 +11196,9 @@ msgstr ""
msgid "command line instructions"
msgstr "명령줄 지침"
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9539,12 +11218,19 @@ msgid "day"
msgid_plural "days"
msgstr[0] "ì¼"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr "ë°°í¬ í† í°"
msgid "disabled"
msgstr "사용 안 함"
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+
msgid "done"
msgstr "완료"
@@ -9555,30 +11241,57 @@ msgstr[0] ""
msgid "enabled"
msgstr "사용"
-msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgid "epic"
msgstr ""
-msgid "for this project"
+msgid "error"
msgstr ""
+msgid "error code:"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr "%{slash_command} ëª…ë ¹ì€ ì˜ˆìƒì‹œê°„ì„ ê°€ìž¥ 마지막 명령으로 ì—…ë°ì´íŠ¸ 합니다."
+
+msgid "for this project"
+msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해"
+
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr "여기"
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://나ì˜-bitbucket-server"
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr "가져오는중"
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9592,9 +11305,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr "올바른 X509 ì¸ì¦ì„œê°€ 아닙니다."
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr "ì´ìŠˆ ë³´ë“œ"
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9607,13 +11338,28 @@ msgstr "ë¼ì´ì„ ìŠ¤ 관리"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "머지 리퀘스트(MR)"
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "브랜치를 ë³µì›í•˜ê±°ë‚˜ 다른 %{missingBranchName} 브랜치를 사용해주세요."
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFrom}MB ì—ì„œ %{memoryTo}MB ë¡œ %{emphasisStart} ê°ì†Œí•˜ì˜€ìŠµë‹ˆë‹¤. %{emphasisEnd}"
@@ -9629,10 +11375,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9642,7 +11388,7 @@ msgid "mrWidget|Approve"
msgstr ""
msgid "mrWidget|Approved by"
-msgstr ""
+msgstr "ë‹¤ìŒ ì‚¬ìš©ìžì— ì˜í•´ 승ì¸ë¨: "
msgid "mrWidget|Cancel automatic merge"
msgstr "ìžë™ 머지 취소"
@@ -9671,6 +11417,9 @@ msgstr "ë‹«ìŒ"
msgid "mrWidget|Create an issue to resolve them later"
msgstr "ë‚˜ì¤‘ì— í•´ê²°í•  수 있ë„ë¡ ì´ìŠˆë¥¼ 만듭니다"
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "ë°°í¬ í†µê³„ëŠ” ì•„ì§ ì‚¬ìš©í•  수 없습니다."
@@ -9687,7 +11436,7 @@ msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first
msgstr ""
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
-msgstr ""
+msgstr "%{branch} 브랜치가 로컬 ì €ìž¥ì†Œì— ìžˆìœ¼ë©´ ì´ ë¨¸ì§€ 리퀘스트(MR)를 다ìŒê³¼ ê°™ì´ ìˆ˜ë™ìœ¼ë¡œ 머지할 수 있습니다."
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "만약 %{missingBranchName} 브랜치가 ë‹¹ì‹ ì˜ ë¡œì»¬ ì €ìž¥ì†Œì— ì¡´ìž¬í•œë‹¤ë©´, ëª…ë ¹ì¤„ì„ ì‚¬ìš©í•˜ì—¬ 수ë™ìœ¼ë¡œ 머지할 수 있습니다."
@@ -9708,31 +11457,31 @@ msgid "mrWidget|Merge locally"
msgstr "로컬ì—ì„œ 머지"
msgid "mrWidget|Merge request approved"
-msgstr ""
+msgstr "머지 리퀘스트(MR) 승ì¸ë¨"
msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
+msgstr "머지 리퀘스트(MR)승ì¸ë¨; 추가ì ìœ¼ë¡œ 승ì¸í•  수 있습니다."
msgid "mrWidget|Merged by"
msgstr "머지:"
msgid "mrWidget|No Approval required"
-msgstr ""
+msgstr "ìŠ¹ì¸ í•„ìš” ì—†ìŒ"
msgid "mrWidget|No Approval required; you can still approve"
-msgstr ""
+msgstr "ìŠ¹ì¸ í•„ìš” ì—†ìŒ; 여전히 승ì¸í•  수 있습니다."
msgid "mrWidget|Open in Web IDE"
-msgstr ""
+msgstr "Web IDEì—ì„œ 열기"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
+msgstr "파ì´í”„ë¼ì¸ 차단ë¨. ì´ ë¨¸ì§€ 리퀘스트(MR)ì˜ íŒŒì´í”„ë¼ì¸ì€ ìˆ˜ë™ ìž‘ì—…ì´ í•„ìš”í•©ë‹ˆë‹¤."
msgid "mrWidget|Plain diff"
msgstr "Plain diff"
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 "새로고침"
@@ -9743,21 +11492,15 @@ msgstr "지금 새로고침"
msgid "mrWidget|Refreshing now"
msgstr "지금 새로고침 중"
-msgid "mrWidget|Remove Source Branch"
-msgstr "소스 브랜치 삭제"
-
-msgid "mrWidget|Remove source branch"
-msgstr "소스 브랜치 삭제"
-
msgid "mrWidget|Remove your approval"
-msgstr ""
+msgstr "ë‚˜ì˜ ìŠ¹ì¸ ì œê±°"
msgid "mrWidget|Request to merge"
msgstr "머지 리퀘스트(MR)"
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
+msgstr[0] "%dê°œì˜ ì¶”ê°€ ìŠ¹ì¸ í•„ìš”"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
@@ -9793,20 +11536,20 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
-msgstr "소스 브랜치가 제거ë˜ì—ˆìŠµë‹ˆë‹¤."
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
-msgstr "소스 브랜치가 제거ë˜ëŠ” 중입니다"
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
-msgid "mrWidget|The source branch will be removed"
-msgstr "소스 브랜치가 ì œê±°ë  ê²ƒ 입니다."
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
-msgid "mrWidget|The source branch will not be removed"
-msgstr "소스 브랜치가 제거ë˜ì§€ ì•Šì„ ê²ƒ 입니다."
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "머지 충ëŒì´ 있습니다."
@@ -9814,6 +11557,9 @@ msgstr "머지 충ëŒì´ 있습니다."
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "í•´ê²°ë˜ì§€ ì•Šì€ í† ë¡ ì´ ìžˆìŠµë‹ˆë‹¤. ì´ í† ë¡ ì„ í•´ê²°í•˜ì‹­ì‹œì˜¤"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 ìžë™ìœ¼ë¡œ ë¨¸ì§€í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -9826,12 +11572,12 @@ msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” ë³´ê´€ë˜ì—ˆê³ , 쓰기 ì ‘ê·¼ì´ ë¹„í™œì„±í™”ë˜ì—ˆ
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 수ë™ìœ¼ë¡œ 머지할 수 있습니다."
-msgid "mrWidget|You can remove source branch now"
-msgstr "지금 소스 브랜치를 삭제할 수 있습니다."
-
msgid "mrWidget|branch does not exist."
msgstr "브랜치가 존재하지 않습니다."
@@ -9845,20 +11591,32 @@ msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "파ì´í”„ë¼ì¸ì´ 성공하면 ìžë™ìœ¼ë¡œ 머지ë©ë‹ˆë‹¤."
msgid "n/a"
-msgstr ""
+msgstr "해당 ì—†ìŒ"
msgid "new merge request"
msgstr "새 머지 리퀘스트(MR)"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "알림 ì´ë©”ì¼"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr "ë˜ëŠ”"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
-msgstr[0] ""
+msgstr[0] "전체 테스트 중 %d"
msgid "parent"
msgid_plural "parents"
@@ -9870,45 +11628,84 @@ msgstr "패스워드"
msgid "personal access token"
msgstr "ê°œì¸ ì—‘ì„¸ìŠ¤ 토í°"
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr "ê°œì¸ í‚¤ì™€ ì¸ì¦ì„œê°€ ì¼ì¹˜í•˜ì§€ 않습니다."
msgid "project"
msgid_plural "projects"
-msgstr[0] ""
+msgstr[0] "프로ì íŠ¸"
-msgid "remaining"
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
msgstr ""
+msgid "remaining"
+msgstr "남ì€"
+
msgid "remove"
msgstr "제거"
msgid "remove due date"
-msgstr ""
+msgstr "마ê°ê¸°í•œ ì‚­ì œ"
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
-msgstr[0] ""
+msgstr[0] "답변"
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
msgid "source"
msgstr "소스"
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} 소요 ëœ ì‹œê°„ì˜ í•©ê³„ë¥¼ ì—…ë°ì´íŠ¸í•©ë‹ˆë‹¤."
msgid "started"
msgstr "시작ë¨"
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr "ì´ ë¬¸ì„œ"
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9917,13 +11714,22 @@ msgstr "사용ìžëª…"
msgid "uses Kubernetes clusters to deploy your code!"
msgstr "kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 사용하여 코드를 ë°°í¬í•©ë‹ˆë‹¤!"
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "GitLabì—ì„œ 보기"
-msgid "with %{additions} additions, %{deletions} deletions."
+msgid "view the blob"
msgstr ""
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr "%{additions} ê°œì˜ ì¶”ê°€, %{deletions} ê°œì˜ ì‚­ì œê°€ 있습니다."
+
msgid "within %d minute "
msgid_plural "within %d minutes "
-msgstr[0] ""
+msgstr[0] "%d 분 ì´ë‚´ "
+
+msgid "yaml invalid"
+msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index f6b0a71c3d6..01bbcaaa9c6 100644
--- a/locale/mn_MN/gitlab.po
+++ b/locale/mn_MN/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: mn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:17\n"
+"PO-Revision-Date: 2019-02-11 08:07\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index be6ccfe1adc..ef5040725b3 100644
--- a/locale/nb_NO/gitlab.po
+++ b/locale/nb_NO/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: nb\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:17\n"
+"PO-Revision-Date: 2019-02-11 08:07\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 6b7e84d0af6..17bc141ae0c 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:22\n"
+"PO-Revision-Date: 2019-02-11 08:11\n"
msgid " Status"
msgstr " Status"
@@ -23,26 +23,25 @@ msgstr " en"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " gedegradeerd op %d punt"
+msgstr[1] " gedegradeerd op %d punten"
msgid " improved on %d point"
msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " verbeterd op %d punt"
+msgstr[1] " verbeterd op %d punten"
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
+
+msgid " or <#issue id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] "%d gewijzigd bestand"
-msgstr[1] "%d gewijzigde bestanden"
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" in projecten"
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] "%d commit achterlopend"
msgstr[1] "%d commits achterlopend"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -66,19 +63,24 @@ msgstr[1] "%d exporters"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d mislukt testresultaat"
+msgstr[1] "%d mislukte testresultaten"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d opgelost testresultaat"
+msgstr[1] "%d opgeloste testresultaten"
msgid "%d issue"
msgid_plural "%d issues"
msgstr[0] "%d probleem"
msgstr[1] "%d problemen"
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d laag"
@@ -113,19 +115,22 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
msgid "%{authorsName}'s discussion"
-msgstr ""
+msgstr "%{authorsName}'s discussie"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} schreef %{commit_timeago}"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
+msgstr "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artefacten, %{counter_lfs_objects} LFS)"
msgid "%{count} %{alerts}"
+msgstr "%{count} %{alerts}"
+
+msgid "%{count} more"
msgstr ""
msgid "%{count} more assignees"
-msgstr ""
+msgstr "%{count} andere toebedeelden"
msgid "%{count} participant"
msgid_plural "%{count} participants"
@@ -134,19 +139,25 @@ msgstr[1] "%{count} deelnemers"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} openstaande reactie"
+msgstr[1] "%{count} openstaande reacties"
msgid "%{filePath} deleted"
msgstr "%{filePath} verwijderd"
msgid "%{firstLabel} +%{labelCount} more"
+msgstr "%{firstLabel} +%{labelCount} meer"
+
+msgid "%{firstOption} +%{extraOptionCount} more"
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
+msgstr "%{group_docs_link_start}Groepen%{group_docs_link_end} stellen u in staat over meerdere projecten samen te werken en te beheren. Leden van een groep hebben toegang tot alle projecten."
msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType} wordt verwijderd! Weet je het zeker?"
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
msgid "%{loadingIcon} Started"
@@ -158,9 +169,6 @@ msgstr "%{lock_path} is vergrendeld door GitLab Gebruiker %{lock_user_id}"
msgid "%{name}'s avatar"
msgstr "%{name};'s avatar"
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} kan worden gebruikt als een alternatief voor een eigen domein."
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits achter %{default_branch}, %{number_commits_ahead} commits voor"
@@ -170,11 +178,32 @@ msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% compleet"
-msgid "%{text} %{files}"
-msgid_plural "%{text} %{files} files"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] "%{text}%{files}"
+msgstr[1] "%{text}%{files} bestanden"
+
msgid "%{text} is available"
msgstr "%{text} is beschikbaar"
@@ -182,17 +211,26 @@ msgid "%{title} changes"
msgstr "%{title} wijzigingen"
msgid "%{unstaged} unstaged and %{staged} staged changes"
-msgstr ""
+msgstr "%{unstaged} unstaged en %{staged} staged wijzigingen"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr "%{usage_ping_link_start}Lees meer%{usage_ping_link_end} over welke informatie gedeeld wordt met GitLab Inc."
+
+msgid "%{user_name} profile page"
msgstr ""
-msgid "+ %{count} more"
+msgid "(external source)"
msgstr ""
+msgid "+ %{count} more"
+msgstr "+ %{count} meer"
+
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} meer"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr "- Runner is actief en kan nieuwe taken verwerken"
@@ -224,8 +262,8 @@ msgstr[1] "%d gesloten merge requests"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 groep"
+msgstr[1] "%d groepen"
msgid "1 merged merge request"
msgid_plural "%d merged merge requests"
@@ -249,21 +287,24 @@ msgstr[1] "%d pipelines"
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 rol"
+msgstr[1] "%d rollen"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 gebruiker"
+msgstr[1] "%d gebruikers"
msgid "1st contribution!"
msgstr "1e bijdrage!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "2FA ingeschakeld"
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr "Misbruik rapporten"
msgid "Abuse reports"
msgstr "Misbruik rapporten"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr "Voorwaarden accepteren"
@@ -389,10 +433,10 @@ msgstr "Activiteit"
msgid "Add"
msgstr ""
-msgid "Add Changelog"
-msgstr "Changelog toevoegen"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr "Admin omgeving"
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr "Alles"
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr "Er is een fout opgetreden tijdens het laden van de merge request wijzigingen."
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr "Applicaties"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr "Auteur"
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr "Door bestanden bladeren"
msgid "Browse files"
msgstr "Door bestanden bladeren"
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "door"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "Annuleren"
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr "Chat"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] "Nieuwe issues"
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
new file mode 100644
index 00000000000..1f1f71a35e9
--- /dev/null
+++ b/locale/pa_IN/gitlab.po
@@ -0,0 +1,11801 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Punjabi\n"
+"Language: pa_IN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: pa-IN\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2019-02-11 08:08\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " or "
+msgstr ""
+
+msgid " or <#epic id>"
+msgstr ""
+
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commits"
+msgstr ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid ", or "
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add CHANGELOG"
+msgstr ""
+
+msgid "Add CONTRIBUTING"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to project"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Auth Token"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization key"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "By %{user_name}"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Charts"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI Lint"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "CONTRIBUTING"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change permissions"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking approval status"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed (moved)"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} upgraded successfully."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Command line instructions"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit %{commit_id}"
+msgstr ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit deleted"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Contact sales to upgrade"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution Charts"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create milestone"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downstream"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable error tracking"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Stopping"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error rendering markdown preview"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating %{issuableType}"
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find existing members by name"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish editing this message first!"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate key"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last repository check run"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Re-verification interval"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Given access %{time_ago}"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import project members"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include merge request description"
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed"
+msgstr ""
+
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes Clusters"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage two-factor authentication"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge commit message"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search files"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics for environment"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No details available"
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No errors to display"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No milestones to show"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No preview for this file type"
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No start date"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|@username"
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Social sign-in"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "Project:"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about environments"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register U2F device"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset key"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Restart Terminal"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reveal values"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners activated for this project"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search groups"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|No Vulnerabilities"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select members to invite"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new U2F device"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippet Contents"
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "Sort direction"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start cleanup"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Stopping..."
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no approvers"
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This 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. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To 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>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle commit list"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try again?"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "URL"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Upload object map"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "Used to help configure your identity provider"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various localization settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Report Type"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web Terminal"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "When:"
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "Will deploy to"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "allowed to fail"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "commented on %{link_to_project}"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "deleted"
+msgstr ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "group"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "image diff"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "none"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 82baa725e8d..39d0494790f 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:18\n"
+"PO-Revision-Date: 2019-02-11 08:08\n"
msgid " Status"
msgstr ""
@@ -35,22 +35,17 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -66,12 +61,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -101,6 +92,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -158,9 +156,12 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
-msgid "%{count} more assignees"
+msgid "%{count} more"
msgstr ""
+msgid "%{count} more assignees"
+msgstr "%{count} więcej beneficjentów"
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
@@ -181,12 +182,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -196,9 +203,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -208,6 +212,33 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -227,12 +258,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -322,10 +362,13 @@ msgstr[3] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -353,7 +396,7 @@ msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will ad
msgstr ""
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr ""
+msgstr "<strong>%{changedFilesLength} niezarejestrowane</strong> i <strong>%{stagedFilesLength} zarejestrowane</strong> zmiany"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
msgstr ""
@@ -367,7 +410,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -415,6 +458,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -451,10 +497,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -466,7 +512,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -499,6 +548,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -508,6 +560,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -523,9 +578,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -559,12 +611,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -577,15 +659,45 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
msgstr ""
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr "Zaawansowane pozwolenia, Magazyn Dużych Plików i Dwuczynnikowe ustawienia autoryzacji."
+
msgid "Advanced settings"
msgstr ""
@@ -596,6 +708,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -605,9 +720,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -624,11 +745,14 @@ msgid "Allow requests to the local network from hooks and services."
msgstr ""
msgid "Allow users to request access"
-msgstr ""
+msgstr "Zezwalaj użytkownikom na żądanie dostępu"
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -656,46 +780,19 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
-msgstr ""
+msgstr "Wystąpił błąd podczas dodawania wersji roboczej do dyskusji."
msgid "An error occurred adding a new draft."
+msgstr "Wystąpił błąd podczas dodawania nowej wersji roboczej."
+
+msgid "An error occurred creating the new branch."
msgstr ""
msgid "An error occurred previewing the blob"
@@ -711,7 +808,7 @@ msgid "An error occurred while adding approver"
msgstr ""
msgid "An error occurred while deleting the comment"
-msgstr ""
+msgstr "Wystąpił błąd podczas usuwania komentarza"
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -726,7 +823,7 @@ msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
-msgstr ""
+msgstr "Wystąpił błąd podczas pobierania oczekującego komentarza"
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -756,7 +853,7 @@ msgid "An error occurred while initializing path locks"
msgstr ""
msgid "An error occurred while loading chart data"
-msgstr ""
+msgstr "Wystąpił błąd podczas ładowania danych wykresu"
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -770,12 +867,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -801,14 +907,59 @@ msgid "An error occurred while unsubscribing to notifications."
msgstr ""
msgid "An error occurred while updating the comment"
-msgstr ""
+msgstr "Wystąpił błąd podczas aktualizacji komentarza"
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -839,6 +990,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -851,21 +1017,36 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
msgid "Are you sure you want to erase this build?"
-msgstr ""
+msgstr "Czy na pewno chcesz usunąć tę kompilację?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -876,11 +1057,14 @@ msgid "Are you sure you want to reset the health check token?"
msgstr ""
msgid "Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "Czy na pewno chcesz zatrzymać to środowisko?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -899,6 +1083,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -908,6 +1095,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -935,6 +1125,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -947,6 +1140,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -962,6 +1158,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -989,15 +1188,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -1017,7 +1207,7 @@ msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr ""
+msgstr "Proces Automatyczny DevOps został włączony i będzie używany, jeśli nie zostanie znaleziony alternatywny plik konfiguracyjny CI. %{more_information_link}"
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -1031,13 +1221,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1140,7 +1342,7 @@ msgid "BatchComments|Discard review?"
msgstr ""
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
-msgstr ""
+msgstr "Zamierzasz odrzucić swoją recenzję, co usunie wszystkie Twoje oczekujące komentarze. Usunięte komentarze %{strong_start}nie mogą%{strong_end} zostać przywrócone."
msgid "Begin with the selected commit"
msgstr ""
@@ -1223,6 +1425,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1232,13 +1440,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1392,21 +1593,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1435,7 +1651,7 @@ msgid "CICD|Continuous deployment to production"
msgstr ""
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "Ciągłe wdrażanie do produkcji przy użyciu stopniowego wdrażania przyrostowego"
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1443,12 +1659,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1456,20 +1666,29 @@ msgid "CICD|Learn more about Auto DevOps"
msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "Proces Automatyczny DevOps zostanie uruchomiony, jeśli nie zostanie znaleziony alternatywny plik konfiguracji CI."
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1482,12 +1701,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
-msgid "Certificate fingerprint"
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
msgstr ""
+msgid "Certificate fingerprint"
+msgstr "Certyfikat odcisku palca"
+
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1509,10 +1737,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1524,9 +1752,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1548,6 +1782,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1558,7 +1798,7 @@ msgid "Choose any color."
msgstr ""
msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
-msgstr ""
+msgstr "Wybierz pomiędzy <code>klonem</code> lub <code>pobierz</code> aby uzyskać najnowszy kod aplikacji"
msgid "Choose file..."
msgstr ""
@@ -1566,6 +1806,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1585,7 +1828,7 @@ msgid "CiStatusLabel|created"
msgstr ""
msgid "CiStatusLabel|delayed"
-msgstr ""
+msgstr "opóźniony"
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1606,7 +1849,7 @@ msgid "CiStatusLabel|skipped"
msgstr ""
msgid "CiStatusLabel|waiting for delayed job"
-msgstr ""
+msgstr "oczekiwanie na opóźnione zadanie"
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1621,7 +1864,7 @@ msgid "CiStatusText|created"
msgstr ""
msgid "CiStatusText|delayed"
-msgstr ""
+msgstr "opóźnione"
msgid "CiStatusText|failed"
msgstr ""
@@ -1657,9 +1900,9 @@ msgid "CiVariable|All environments"
msgstr ""
msgid "CiVariable|Create wildcard"
-msgstr ""
+msgstr "Utwórz symbole wieloznaczne"
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1669,7 +1912,7 @@ msgid "CiVariable|Protected"
msgstr ""
msgid "CiVariable|Search environments"
-msgstr ""
+msgstr "Szukaj środowisk"
msgid "CiVariable|Toggle protected"
msgstr ""
@@ -1678,6 +1921,12 @@ msgid "CiVariable|Validation failed"
msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr "jest niedostępna: %{reason}"
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
msgstr ""
msgid "Clear search"
@@ -1719,28 +1968,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
-msgstr ""
+msgstr "%{boldNotice} To spowoduje dodanie dodatkowych zasobów, takich jak moduł równoważenia obciążenia, co może wiązać się z dodatkowymi kosztami w zależności od dostawcy hostingu, na którym jest zainstalowany Twój klaster Kubernetes. Jeśli korzystasz z Google Kubernetes Engine, możesz %{pricingLink}."
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1750,48 +2023,66 @@ msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|Add a Kubernetes cluster integration"
-msgstr ""
+msgstr "Dodaj integracjÄ™ klastra 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 "Dodanie klastra Kubernetes do Twojej grupy spowoduje automatyczne udostępnienie klastra we wszystkich Twoich projektach. Korzystaj z aplikacji oceniających, wdrażaj aplikacje i łatwo uruchamiaj procesy dla wszystkich projektów korzystając z tego samego klastra."
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "Dodanie integracji do Twojej grupy spowoduje udostępnienie klastra we wszystkich Twoich projektach."
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr "Po zainstalowaniu Ingress będziesz musiał wskazać swoje symbole wieloznaczne DNS na wygenerowanym zewnętrzny adresie IP, aby zobaczyć swoją aplikację po jej wdrożeniu. %{ingressHelpLink}"
+
+msgid "ClusterIntegration|Alternatively"
msgstr ""
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
-msgstr ""
+msgstr "Wystąpił błąd podczas próby pobrania stref projektu: %{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr ""
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr "Wystąpił błąd podczas próby skontaktowania się z Google Cloud API. Spróbuj ponownie później."
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr ""
+msgstr "Wybierz aplikacje do zainstalowania w Twoim klastrze Kubernetes. Do zainstalowania dowolnej z poniższych aplikacji wymagany jest Helm Tiller."
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr "Wybierz, które z Twoich środowisk będą używać tego klastra."
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1806,6 +2097,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1819,10 +2113,10 @@ msgid "ClusterIntegration|Did you know?"
msgstr ""
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
-msgstr ""
+msgstr "Włącz lub wyłącz połączenie GitLab z klastrem Kubernetes."
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
-msgstr ""
+msgstr "Włącz to ustawienie, jeśli używasz kontroli dostępu opartej na roli (RBAC)."
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1833,15 +2127,24 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
-msgid "ClusterIntegration|Fetching machine types"
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
msgstr ""
-msgid "ClusterIntegration|Fetching projects"
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
msgstr ""
-msgid "ClusterIntegration|Fetching zones"
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
msgstr ""
+msgid "ClusterIntegration|Fetching machine types"
+msgstr "Pobieranie typów maszyn"
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr "Pobieranie projektów"
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr "Pobieranie stref"
+
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -1849,10 +2152,10 @@ msgid "ClusterIntegration|GitLab Runner"
msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
-msgstr ""
+msgstr "GitLab Runner łączy się z repozytorium tego projektu i wykonuje zadania CI/CD, przesyłając wyniki i wdrażając aplikacje do produkcji."
msgid "ClusterIntegration|Google Cloud Platform project"
-msgstr ""
+msgstr "Projekt Platformy Google Cloud"
msgid "ClusterIntegration|Google Kubernetes Engine"
msgstr ""
@@ -1861,37 +2164,37 @@ msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "Klaster grupowy"
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helm usprawnia instalację i zarządzanie aplikacjami Kubernetes. Tiller uruchamia się wewnątrz Klastra Kubernetes i zarządza publikacjami Twoich wykresów."
msgid "ClusterIntegration|Hide"
msgstr ""
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
-msgstr ""
+msgstr "Jeśli konfigurujesz wiele klastrów i używasz Auto DevOps, %{help_link_start}zapoznaj się najpierw z tym%{help_link_end}."
msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
-msgstr ""
+msgstr "Aby pokazać stan zdrowia klastra, musimy zaopatrzyć Twój klaster w Prometheus, aby zebrać wymagane dane."
msgid "ClusterIntegration|Ingress"
msgstr ""
msgid "ClusterIntegration|Ingress IP Address"
-msgstr ""
+msgstr "Wprowadź Address IP"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
-msgstr ""
+msgstr "Wprowadzanie umożliwia kierowanie żądań do usług na podstawie hosta lub ścieżki żądania, centralizując szereg usług w jeden punkt początkowy."
msgid "ClusterIntegration|Install"
msgstr ""
msgid "ClusterIntegration|Install Prometheus"
-msgstr ""
+msgstr "Zainstaluj Prometheus"
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1905,19 +2208,31 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
-msgid "ClusterIntegration|Jupyter Hostname"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
msgstr ""
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr "Nazwa hosta Jupyter"
+
msgid "ClusterIntegration|JupyterHub"
msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
-msgstr ""
+msgstr "JupyterHub, ośrodek z wieloma użytkownikami, namnaża, zarządza i zastępuje wiele przypadków jednoosobowego serwera notebooka Jupyter. JupyterHub może służyć do obsługi notebooków dla klasy studentów, korporacyjnej obsługi danych lub grupy badawczej."
msgid "ClusterIntegration|Knative"
-msgstr ""
+msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
+msgstr "Nazwa Domeny Knative:"
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster"
@@ -1927,7 +2242,7 @@ msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
+msgstr "Kondycja klastra Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr ""
@@ -1939,13 +2254,13 @@ msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
+msgstr "Klastry Kubernetes pozwalają Ci w łatwy sposób używać aplikacji oceniających, wdrażać aplikacje, uruchamiać procesy i wiele więcej."
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
-msgstr ""
+msgstr "Dowiedz się więcej o %{help_link_start_machine_type}rodzajach maszyn%{help_link_end} i %{help_link_start_pricing}cenniku%{help_link_end}."
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
@@ -1956,6 +2271,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -2034,6 +2352,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2076,12 +2397,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2097,6 +2424,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2109,6 +2448,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2136,6 +2478,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2148,9 +2493,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2170,16 +2524,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2243,6 +2596,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2270,12 +2626,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2309,6 +2671,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2357,6 +2722,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2372,7 +2740,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2408,13 +2776,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2423,6 +2794,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2447,9 +2821,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2471,6 +2842,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2480,6 +2854,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2519,6 +2896,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2585,9 +2965,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2603,6 +2980,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2612,6 +2992,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2642,6 +3028,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2651,6 +3040,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2663,6 +3055,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2672,6 +3067,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2681,6 +3082,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2711,6 +3115,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2847,6 +3257,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2874,6 +3287,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2904,6 +3320,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2925,15 +3347,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2961,6 +3392,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2985,6 +3422,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -3000,9 +3440,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3012,6 +3458,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -3021,6 +3473,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -3039,6 +3494,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -3063,6 +3521,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3078,9 +3539,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3093,6 +3563,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3108,9 +3584,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3186,6 +3680,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3198,9 +3695,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3210,7 +3704,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3237,9 +3731,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3282,9 +3782,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3294,6 +3800,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3315,6 +3827,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3324,9 +3842,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3339,6 +3887,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3360,9 +3914,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3402,6 +3968,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3411,28 +3980,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3444,7 +4025,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3456,30 +4040,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3498,6 +4100,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3507,13 +4124,35 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3531,12 +4170,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3549,12 +4206,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3600,6 +4263,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3624,6 +4290,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3675,6 +4344,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3765,7 +4437,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3840,6 +4515,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3885,6 +4563,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3921,6 +4602,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3999,9 +4683,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -4029,9 +4722,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4062,6 +4761,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4086,6 +4788,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4131,13 +4836,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4149,37 +4857,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4206,6 +4911,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4305,6 +5013,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4318,7 +5029,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4327,6 +5038,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4384,6 +5098,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4414,9 +5131,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4435,12 +5158,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4465,6 +5200,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4480,15 +5218,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4504,6 +5257,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4535,6 +5291,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4550,9 +5309,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4571,6 +5348,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4604,6 +5396,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4622,6 +5420,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4661,10 +5465,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4679,12 +5483,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4764,6 +5574,9 @@ msgstr[3] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4779,6 +5592,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4794,15 +5610,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4942,6 +5782,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -5008,6 +5854,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -5038,6 +5887,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -5074,9 +5926,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5098,13 +5947,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5113,9 +5965,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5128,19 +5989,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5158,6 +6031,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5167,6 +6058,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5185,7 +6079,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5194,6 +6088,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5203,7 +6103,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5215,22 +6115,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5245,10 +6139,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5269,21 +6163,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5356,6 +6241,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5416,6 +6313,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5428,6 +6328,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5444,6 +6347,12 @@ msgstr[3] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5462,6 +6371,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5483,6 +6395,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5510,6 +6425,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5519,6 +6437,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5531,15 +6452,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5552,6 +6482,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5561,10 +6494,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5585,6 +6521,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5594,12 +6533,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5624,6 +6557,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5654,6 +6590,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5754,21 +6696,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5802,16 +6759,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5859,6 +6813,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5871,12 +6831,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5898,9 +6873,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5916,6 +6888,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6102,6 +7080,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6114,9 +7095,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6129,6 +7116,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6171,6 +7161,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6192,9 +7185,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6210,15 +7212,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6237,6 +7254,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6246,6 +7266,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6282,10 +7308,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6294,7 +7323,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6303,10 +7332,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6333,12 +7365,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6357,16 +7392,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6375,6 +7413,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6432,12 +7476,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6582,9 +7632,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6609,6 +7656,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6738,6 +7788,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6777,21 +7830,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6820,6 +7882,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6850,6 +7915,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6859,6 +7930,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6889,9 +7966,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6932,16 +8015,16 @@ msgid "Reports|Test summary"
msgstr ""
msgid "Reports|Test summary failed loading results"
-msgstr ""
+msgstr "Reports|Podsumowanie testu nie załadowało wyników"
msgid "Reports|Test summary results are being parsed"
-msgstr ""
+msgstr "Wyniki podsumowania testu sÄ… analizowane"
msgid "Reports|Vulnerability"
-msgstr ""
+msgstr "Wrażliwość"
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "brak zmienionych wyników testów"
msgid "Repository"
msgstr ""
@@ -6952,9 +8035,15 @@ msgstr ""
msgid "Repository URL"
msgstr ""
-msgid "Repository has no locks."
+msgid "Repository cleanup"
msgstr ""
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr "Repozytorium nie ma blokad."
+
msgid "Repository maintenance"
msgstr ""
@@ -6965,48 +8054,78 @@ msgid "Repository storage"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
-msgstr ""
+msgstr "Wybierz"
msgid "Request Access"
msgstr ""
-msgid "Requests Profiles"
+msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requests Profiles"
+msgstr "Profile Żądań"
+
msgid "Require all users in this group to setup Two-factor authentication"
-msgstr ""
+msgstr "Wymagaj od wszystkich użytkowników w tej grupie do ustawienia uwierzytelniania Dwuczynnikowego"
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr "Wymagaj od wszystkich użytkowników akceptacji Warunków Usługi i Polityki Prywatności, gdy będą chcieli korzystać z GitLab."
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
msgstr ""
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
-msgid "Resolve all discussions in new issue"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
msgstr ""
+msgid "Resolve all discussions in new issue"
+msgstr "Rozwiąż wszystkie dyskusje w nowym zgłoszeniu"
+
msgid "Resolve conflicts on source branch"
-msgstr ""
+msgstr "Rozwiąż konflikty w gałęzi źródłowej"
msgid "Resolve discussion"
msgstr ""
-msgid "Response metrics (AWS ELB)"
+msgid "Resolved"
msgstr ""
-msgid "Response metrics (Custom)"
+msgid "Response"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr "Metryki odpowiedzi (AWS ELB)"
+
+msgid "Response metrics (Custom)"
+msgstr "Metryki odpowiedzi (Niestandardowe)"
+
msgid "Response metrics (HA Proxy)"
+msgstr "Metryki odpowiedzi (HA Proxy)"
+
+msgid "Response metrics (NGINX Ingress VTS)"
msgstr ""
msgid "Response metrics (NGINX Ingress)"
-msgstr ""
+msgstr "Metryki odpowiedzi (NGINX Ingress)"
msgid "Response metrics (NGINX)"
+msgstr "Metryki odpowiedzi (NGINX)"
+
+msgid "Restart Terminal"
msgstr ""
msgid "Resume"
@@ -7021,9 +8140,6 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
@@ -7031,6 +8147,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -7038,67 +8157,73 @@ msgid "Revert this merge request"
msgstr ""
msgid "Review"
-msgstr ""
+msgstr "Recenzja"
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 "Przejrzyj proces celem konfiguracji dostawców usług u swojego dostawcy tożsamości - w tym przypadku GitLab jest \"dostawcą usług\" lub \"wierzycielem\"."
msgid "Reviewing"
-msgstr ""
+msgstr "PrzeglÄ…d"
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr ""
+msgstr "Recenzowanie (żądanie scalenia !%{mergeRequestId})"
msgid "Revoke"
-msgstr ""
+msgstr "Cofnij"
msgid "Roadmap"
-msgstr ""
+msgstr "Harmonogram"
msgid "Run CI/CD pipelines for external repositories"
+msgstr "Uruchom procesy CI/CD dla zewnętrznych repozytoriów"
+
+msgid "Run tests against your code live using the Web Terminal"
msgstr ""
msgid "Run untagged jobs"
-msgstr ""
+msgstr "Uruchom nieoznaczone zadania"
msgid "Runner cannot be assigned to other projects"
-msgstr ""
+msgstr "Runner nie może być przypisany do innych projektów"
msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
+msgstr "Runner uruchamia zadania ze wszystkich nieprzypisanych projektów"
msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
+msgstr "Runner uruchamia zadania ze wszystkich nieprzypisanych projektów w swojej grupie"
msgid "Runner runs jobs from assigned projects"
-msgstr ""
+msgstr "Runner uruchamia zadania z przypisanych projektów"
msgid "Runner token"
-msgstr ""
+msgstr "Token robotnika"
msgid "Runner will not receive any new jobs"
-msgstr ""
+msgstr "Robotnik nie otrzyma żadnych nowych zadań"
msgid "Runners"
-msgstr ""
+msgstr "Robotnicy"
msgid "Runners API"
+msgstr "API Robotników"
+
+msgid "Runners activated for this project"
msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
+msgstr "Robotnicy mogą być przydzielani do oddzielnych użytkowników, serwerów, a nawet do Twojego lokalnego komputera."
msgid "Runners can be placed on separate users, servers, even on your local machine."
-msgstr ""
+msgstr "Robotnicy mogą być przydzielani do oddzielnych użytkowników, serwerów, a nawet do Twojego lokalnego komputera."
msgid "Runners currently online: %{active_runners_count}"
-msgstr ""
+msgstr "Liczba Robotników online: %{active_runners_count}"
msgid "Runners page"
-msgstr ""
+msgstr "Strona Robotników"
msgid "Runners page."
-msgstr ""
+msgstr "Strona Robotników."
msgid "Runners|You have used all your shared Runners pipeline minutes."
msgstr ""
@@ -7118,7 +8243,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7139,6 +8264,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7148,6 +8276,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7184,6 +8315,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7196,6 +8330,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7265,7 +8402,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7274,10 +8411,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7295,6 +8435,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7304,6 +8456,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7331,6 +8489,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7364,9 +8525,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7376,6 +8543,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7406,6 +8615,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7421,6 +8633,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7484,10 +8699,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7527,12 +8742,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7542,6 +8766,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7555,17 +8782,26 @@ msgid "Slack integration allows you to interact with GitLab via slash commands i
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
+msgstr "Wolniej, ale zapewnia, że ​​przestrzeń robocza projektu jest nieskazitelna, ponieważ klonuje repozytorium dla każdego zadania kompletnie od zera"
msgid "Smartcard"
msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr "Uwierzytelnianie karty inteligentnej nie powiodło się: brakuje nagłówka certyfikatu klienta."
+
+msgid "Snippet Contents"
msgstr ""
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7573,10 +8809,13 @@ msgid "Something went wrong on our end."
msgstr ""
msgid "Something went wrong on our end. Please try again!"
+msgstr "Coś poszło nie tak po naszej stronie. Spróbuj ponownie!"
+
+msgid "Something went wrong on our end. Please try again."
msgstr ""
msgid "Something went wrong trying to change the confidentiality of this issue"
-msgstr ""
+msgstr "Coś poszło nie tak przy próbie zmiany poziomu prywatności tego zgłoszenia"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
@@ -7584,9 +8823,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7594,10 +8839,10 @@ msgid "Something went wrong while fetching comments. Please try again."
msgstr ""
msgid "Something went wrong while fetching group member contributions"
-msgstr ""
+msgstr "Coś poszło nie tak podczas pobierania kontrybucji członków grupy"
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
-msgstr ""
+msgstr "Coś poszło nie tak podczas pobierania środowisk dla tego żądania scalenia. Spróbuj ponownie."
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -7605,33 +8850,42 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
-msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgid "Something went wrong while merging this merge request. Please try again."
msgstr ""
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr "Coś poszło nie tak podczas ponownego otwierania %{issuable}. Spróbuj ponownie później"
+
msgid "Something went wrong while resolving this discussion. Please try again."
-msgstr ""
+msgstr "Coś poszło nie tak podczas rozwiązywania tej dyskusji. Spróbuj ponownie."
msgid "Something went wrong, unable to add %{project} to dashboard"
-msgstr ""
+msgstr "Coś poszło nie tak, nie można dodać %{project} do pulpitu nawigacyjnego"
msgid "Something went wrong, unable to get operations projects"
-msgstr ""
+msgstr "Coś poszło nie tak, nie można uzyskać projektów operacyjnych"
msgid "Something went wrong, unable to remove project"
-msgstr ""
+msgstr "Coś poszło nie tak, nie można usunąć projektu"
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
-msgstr ""
+msgstr "Przepraszamy, żadne epiki nie pasują do Twoich wyszukiwań"
msgid "Sorry, no projects matched your search"
+msgstr "Przepraszamy, żadne projekty nie pasują do Twoich wyszukiwań"
+
+msgid "Sorry, your filter produced no results"
msgstr ""
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7660,7 +8914,7 @@ msgid "SortOptions|Largest repository"
msgstr ""
msgid "SortOptions|Last Contact"
-msgstr ""
+msgstr "Ostatni Kontakt"
msgid "SortOptions|Last created"
msgstr ""
@@ -7675,9 +8929,9 @@ msgid "SortOptions|Least popular"
msgstr ""
msgid "SortOptions|Less weight"
-msgstr ""
+msgstr "Mniej obciążenia"
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7687,7 +8941,7 @@ msgid "SortOptions|Milestone due soon"
msgstr ""
msgid "SortOptions|More weight"
-msgstr ""
+msgstr "Więcej obciążenia"
msgid "SortOptions|Most popular"
msgstr ""
@@ -7710,6 +8964,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7722,6 +8979,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7749,44 +9009,50 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
msgid "Spam and Anti-bot Protection"
-msgstr ""
+msgstr "Ochrona przed spamem i przed botami"
msgid "Specific Runners"
-msgstr ""
+msgstr "Określeni Wykonawcy"
msgid "Specify an e-mail address regex pattern to identify default internal users."
-msgstr ""
+msgstr "Określ wzór regex adresu e-mail, aby zidentyfikować domyślnych użytkowników wewnętrznych."
msgid "Specify the following URL during the Runner setup:"
msgstr ""
-msgid "Squash commits"
+msgid "Squash commit message"
msgstr ""
+msgid "Squash commits"
+msgstr "Angaże Squash"
+
msgid "Stage"
msgstr ""
msgid "Stage & Commit"
-msgstr ""
+msgstr "Etap i Angaż"
msgid "Stage all changes"
-msgstr ""
+msgstr "Zaplanuj wszystkie zmiany"
msgid "Stage changes"
-msgstr ""
+msgstr "Zaplanuj zmiany"
msgid "Staged"
-msgstr ""
+msgstr "Zaplanowane"
msgid "Staged %{type}"
-msgstr ""
+msgstr "Zaplanowane %{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
-msgstr ""
+msgstr "Oznacz etykietę gwiazdką, by nadać jej status priorytetowy. Zorganizuj etykiety priorytetowe celem zmiany ich względnej ważności, poprzez przeciągnięcie."
msgid "StarProject|Star"
msgstr ""
@@ -7795,23 +9061,41 @@ msgid "Starred Projects"
msgstr ""
msgid "Starred Projects' Activity"
-msgstr ""
+msgstr "Aktywność Projektów oznaczonych gwiazdką"
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
msgid "Start a review"
-msgstr ""
+msgstr "Rozpocznij recenzjÄ™"
msgid "Start and due date"
+msgstr "Data początkowa i końcowa"
+
+msgid "Start cleanup"
msgstr ""
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7821,21 +9105,36 @@ msgstr ""
msgid "Started"
msgstr ""
-msgid "Starts at (UTC)"
+msgid "Started %{startsIn}"
msgstr ""
-msgid "State your message to activate"
+msgid "Starting..."
msgstr ""
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr "Rozpoczyna siÄ™ o (UTC)"
+
+msgid "State your message to activate"
+msgstr "Określ swoją wiadomość, aby aktywować"
+
msgid "Status"
msgstr ""
-msgid "Stop environment"
+msgid "Status:"
msgstr ""
-msgid "Stop impersonation"
+msgid "Stop Terminal"
msgstr ""
+msgid "Stop environment"
+msgstr "Zatrzymaj środowisko"
+
+msgid "Stop impersonation"
+msgstr "Zatrzymaj impersonifikacjÄ™"
+
msgid "Stop this environment"
msgstr ""
@@ -7843,49 +9142,139 @@ msgid "Stopped"
msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr "Zatrzymanie tego środowiska nie jest obecnie możliwe, ponieważ wdrażanie jest w toku"
+
+msgid "Stopping..."
msgstr ""
msgid "Storage"
msgstr ""
msgid "Storage:"
-msgstr ""
+msgstr "Przechowywanie:"
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
-msgstr ""
+msgstr "Podgrupy i projekty"
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
msgid "Submit search"
-msgstr ""
+msgstr "Zatwierdź wyszukiwanie"
msgid "Subscribe"
msgstr ""
msgid "Subscribe at group level"
-msgstr ""
+msgstr "Subskrybuj na poziomie grupy"
msgid "Subscribe at project level"
+msgstr "Subskrybuj na poziomie projektu"
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
msgstr ""
msgid "Subscribed"
+msgstr "Subskrybowany"
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
msgstr ""
msgid "Sync information"
-msgstr ""
+msgstr "Synchronizuj informacje"
msgid "System Hooks"
msgstr ""
@@ -7893,21 +9282,23 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
msgstr ""
-msgid "System metrics (Custom)"
+msgid "System header and footer"
msgstr ""
+msgid "System metrics (Custom)"
+msgstr "Metryki systemowe (Niestandardowe)"
+
msgid "System metrics (Kubernetes)"
+msgstr "Metryki systemowe (Kubernetes)"
+
+msgid "Tag"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7982,7 +9373,7 @@ msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
msgid "TagsPage|Write your release notes or drag files here…"
-msgstr ""
+msgstr "Napisz swoje uwagi do wydania lub przeciągnij pliki tutaj…"
msgid "TagsPage|protected"
msgstr ""
@@ -8002,27 +9393,39 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
msgid "Terms of Service and Privacy Policy"
-msgstr ""
+msgstr "Warunki Użytkowania oraz Polityka Prywatności"
msgid "Test SAML SSO"
-msgstr ""
+msgstr "Przetestuj Logowanie Jednokrotne SAML"
msgid "Test coverage parsing"
-msgstr ""
+msgstr "Przetwarzanie pokrycia testowego"
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
msgstr ""
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr "Obiekty Git LFS <strong>nie będą</strong> zsynchronizowane."
+
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
msgstr ""
@@ -8030,10 +9433,10 @@ msgid "The Issue Tracker is the place to add things that need to be improved or
msgstr ""
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
+msgstr "Certyfikat X509 służy do użycia w przypadku, gdy do komunikacji z zewnętrzną usługą autoryzacji jest wymagany wspólny TLS. Jeśli pozostanie puste, certyfikat serwera będzie nadal sprawdzany podczas uzyskiwania dostępu za pośrednictwem protokołu HTTPS."
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 "Zakreślacz znaków pomaga ci utrzymać linię tematyczną do %{titleLength} znaków i zawinąć body do %{bodyLength}, aby można je było odczytać w git."
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr ""
@@ -8042,10 +9445,10 @@ msgid "The collection of events added to the data gathered for that stage."
msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr ""
+msgstr "Połączenie upłynie po %{timeout}. W przypadku repozytoriów, którym zajmuje to dłużej, użyj kombinacji klonuj/pchnij."
msgid "The deployment of this job to %{environmentLink} did not succeed."
-msgstr ""
+msgstr "Wdrożenie tego zadania do %{environmentLink} nie powiodło się."
msgid "The fork relationship has been removed."
msgstr ""
@@ -8056,6 +9459,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8069,13 +9475,13 @@ msgid "The phase of the development lifecycle."
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 "Harmonogram potoków uruchamia procesy w przyszłości, wielokrotnie, dla określonych branch'ów lub znaczników. Te zaplanowane procesy odziedziczą ograniczony dostęp do projektu na podstawie powiązanego użytkownika."
msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
+msgstr "Klucz prywatny służy do użycia w przypadku, gdy dostarczony jest certyfikat klienta. Ta wartość jest zaszyfrowana w trybie spoczynku."
msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr ""
@@ -8087,7 +9493,7 @@ msgid "The project can be accessed without any authentication."
msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
+msgstr "Zbiór danych pseudonimizera jest wyłączony. Po włączeniu GitLab uruchomi zadanie w tle, które będzie wytwarzać pseudonimiczne pliki CSV bazy danych GitLab, które zostaną przesłane do skonfigurowanego katalogu przechowywania obiektów."
msgid "The repository for this project does not exist."
msgstr ""
@@ -8099,7 +9505,7 @@ msgid "The repository must be accessible over <code>http://</code>, <code>https:
msgstr ""
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
-msgstr ""
+msgstr "Repozytorium musi być dostępne za pośrednictwem <code>http://</code>, <code>https://</code>, <code>ssh://</code> i <code>git://</code>."
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
@@ -8111,7 +9517,7 @@ msgid "The staging stage shows the time between merging the MR and deploying cod
msgstr ""
msgid "The tabs below will be removed in a future version"
-msgstr ""
+msgstr "Poniższe zakładki zostaną usunięte w przyszłej wersji"
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
@@ -8120,21 +9526,33 @@ msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr ""
+msgstr "Akcja aktualizacji zakończy się po upływie %{number_of_minutes} minut. W przypadku dużych repozytoriów użyj kombinacji klonuj/pchnij."
msgid "The usage ping is disabled, and cannot be configured through this form."
-msgstr ""
+msgstr "Polecenie ping jest wyłączone i nie można go skonfigurować za pomocą tego formularza."
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
-msgstr ""
+msgstr "Mapa użytkownika to dokument JSON mapujący użytkowników Google Code, którzy uczestniczyli w Twoich projektach, w celu zaimportowania ich adresów e-mail i nazw użytkowników do GitLab. Możesz to zmienić poprzez zmianę wartości po prawej stronie <code>:</code>. Pamiętaj, aby zachować występujące podwójne cudzysłowy, inną interpunkcję i adres e-mail lub nazwę użytkownika po lewej stronie."
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 "Mapa użytkownika to mapowanie użytkowników FogBugz, którzy uczestniczyli w Twoich projektach, w celu zaimportowania ich adresów e-mail i nazw użytkowników do GitLab. Możesz to zmienić, wypełniając poniższą tabelę."
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
+msgstr "Nie ma jeszcze projektów zarchiwizowanych"
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
msgstr ""
msgid "There are no issues to show"
@@ -8143,20 +9561,26 @@ msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
msgstr ""
-msgid "There are no projects shared with this group yet"
+msgid "There are no open merge requests"
msgstr ""
-msgid "There are no staged changes"
+msgid "There are no packages yet"
msgstr ""
+msgid "There are no projects shared with this group yet"
+msgstr "Nie ma jeszcze projektów udostępnionych w tej grupie"
+
+msgid "There are no staged changes"
+msgstr "Brak zaplanowanych zmian"
+
msgid "There are no unstaged changes"
-msgstr ""
+msgstr "Brak niezaplanowanych zmian"
msgid "There was an error adding a todo."
-msgstr ""
+msgstr "Wystąpił błąd podczas ładowania zadań do wykonania."
msgid "There was an error deleting the todo."
msgstr ""
@@ -8179,12 +9603,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8212,13 +9645,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8281,10 +9717,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8293,7 +9729,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8314,6 +9750,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8341,7 +9786,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8353,7 +9798,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8550,9 +9995,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8581,7 +10035,7 @@ msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal
msgstr ""
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
-msgstr ""
+msgstr "Aby usprawnić GitLab i doświadczenie jego użytkowników, GitLab będzie okresowo zbierać informacje o użytkowaniu."
msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
msgstr ""
@@ -8595,13 +10049,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8610,6 +10079,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8619,6 +10091,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8634,13 +10109,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8694,9 +10172,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8706,6 +10181,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8715,9 +10196,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8730,10 +10217,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8742,9 +10229,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8793,6 +10286,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8805,6 +10301,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8814,6 +10313,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8832,15 +10334,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8871,9 +10388,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8898,19 +10421,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8919,25 +10451,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8946,12 +10505,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8964,6 +10529,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -9003,6 +10574,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -9027,6 +10601,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9051,27 +10631,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9096,6 +10697,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9237,12 +10841,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9255,6 +10868,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9273,6 +10889,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9297,6 +10916,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9315,6 +10937,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9324,12 +10949,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9339,16 +10970,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9390,6 +11027,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9405,12 +11045,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9423,12 +11069,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9438,12 +11096,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9544,6 +11208,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9559,6 +11226,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9685,6 +11358,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9707,12 +11383,22 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "done"
msgstr ""
@@ -9726,6 +11412,15 @@ msgstr[3] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9735,21 +11430,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9766,9 +11479,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9781,6 +11512,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
@@ -9788,9 +11522,21 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9806,10 +11552,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9848,6 +11594,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9920,12 +11669,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9976,19 +11719,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9997,6 +11740,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -10009,10 +11755,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -10033,9 +11779,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -10059,6 +11817,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -10069,6 +11830,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -10081,6 +11848,9 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
@@ -10088,22 +11858,49 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -10112,9 +11909,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10125,3 +11928,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index dac92fe616e..c331c2e5cc6 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:17\n"
+"PO-Revision-Date: 2019-02-11 08:08\n"
msgid " Status"
msgstr " Status"
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] " melhorado em %d ponto"
msgstr[1] " melhorado em %d pontos"
-msgid "\"%{query}\" in projects"
-msgstr "\"%{query}\" em projetos"
+msgid " or "
+msgstr ""
+
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] "%d adição"
-msgstr[1] "%d adições"
+msgid " or <#issue id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] "%d arquivo modificado"
-msgstr[1] "%d arquivos modificados"
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" em projetos"
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] "%d commit atrás"
msgstr[1] "%d commits atrás"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] "%d excluído"
-msgstr[1] "%d excluídos"
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] "%d issue"
msgstr[1] "%d issues"
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d camada"
@@ -124,6 +126,9 @@ msgstr "%{counter_storage} (%{counter_repositories} repositórios, %{counter_bui
msgid "%{count} %{alerts}"
msgstr "%{count} %{alerts}"
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr "mais %{count} responsáveis"
@@ -143,12 +148,18 @@ msgstr "%{filePath} excluído"
msgid "%{firstLabel} +%{labelCount} more"
msgstr "%{firstLabel} +%{labelCount} mais"
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Grupos%{group_docs_link_end} permitem que você gerencie e colabore em vários projetos. Os membros de um grupo têm acesso a todos os seus projetos."
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} será removido! Você tem certeza?"
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Iniciado"
@@ -158,9 +169,6 @@ msgstr "%{lock_path} está bloqueado pelo usuário do GitLab %{lock_user_id}"
msgid "%{name}'s avatar"
msgstr "Avatar de %{name}"
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} pode ser utilizado como um domínio personalizado."
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits atrás de %{default_branch}, %{number_commits_ahead} commits à frente"
@@ -170,6 +178,27 @@ msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% completado"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text} %{files}"
@@ -187,17 +216,26 @@ msgstr "%{unstaged} mudanças fora e %{staged} mudanças dentro da lista de comm
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}Saiba mais%{usage_ping_link_end} sobre quais informações são compartilhadas com o GitLab Inc."
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr "+ %{count} mais"
msgid "+ %{moreCount} more"
msgstr "%{moreCount} mais"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
-msgstr "- O runner está ativo e pode processar novos jobs"
+msgstr "- O runner está ativo e pode processar novas tarefas"
msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- O runner está pausado e não receberá nenhum novo jobs"
+msgstr "- O runner está pausado e não receberá nenhuma tarefa nova"
msgid "- show less"
msgstr "- exibir menos"
@@ -260,11 +298,14 @@ msgstr[1] "%d usuários"
msgid "1st contribution!"
msgstr "1ª contribuição!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "Autenticação de 2 passos ativada"
-msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "Entre em contato com o administrador do GitLab para ter permissão."
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
msgid "403|You don't have the permission to access this page."
msgstr "Você não tem permissão para acessar essa página."
@@ -291,7 +332,7 @@ msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will ad
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> adicionará \"Por <a href=\"#\">johnsmith@example.com</a>\" a todas as issues e comentários originalmente criados por johnsmith@example.com. Por padrão, o endereço de e-mail ou nome de usuário é mascarado para garantir a privacidade do usuário. Use esta opção se você quiser mostrar o endereço de e-mail completo."
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr ""
+msgstr "<strong>%{changedFilesLength} fora da lista de commit</strong> e <strong>%{stagedFilesLength} na lista de commit</strong>"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
msgstr "<strong>%{created_count}</strong> criado(s), <strong>%{accepted_count}</strong> aceito(s)."
@@ -305,11 +346,11 @@ msgstr "Membros do grupo <strong>%{group_name}</strong>"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr "<strong>%{pushes}</strong> pushes, mais que <strong>%{commits}</strong> commits por <strong>%{people}</strong> contribuidores."
-msgid "<strong>Removes</strong> source branch"
-msgstr "<strong>Remover</strong> branch de origem"
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "'Runner' é um processo que executa um job. Você pode configurar quantos Runners você precisar."
+msgstr "'Runner' é um processo que executa uma tarefa. Você pode configurar quantos Runners você precisar."
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Uma coleção de gráficos sobre Integração Contínua"
@@ -353,6 +394,9 @@ msgstr "Relatórios de Abuso"
msgid "Abuse reports"
msgstr "Relatórios de abuso"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr "Aceitar os temos"
@@ -389,11 +433,11 @@ msgstr "Atividade"
msgid "Add"
msgstr "Adicionar"
-msgid "Add Changelog"
-msgstr "Adicionar registro de mudanças"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "Adicionar Guia de contribuição"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Adicione Webhooks de grupo e GitLab Enterprise Edition."
@@ -404,8 +448,11 @@ msgstr "Adicionar URL Jaeger"
msgid "Add Kubernetes cluster"
msgstr "Adicionar cluster Kubernetes"
-msgid "Add Readme"
-msgstr "Adicionar leia-me"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Adicione uma homepage ao seu wiki que contenha informações sobre o seu projeto e o GitLab irá exibi-lo aqui ao invés desta mensagem."
@@ -437,6 +484,9 @@ msgstr "Adicionar projetos"
msgid "Add reaction"
msgstr "Adicionar reação"
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr "Adicionar à revisão"
@@ -446,11 +496,14 @@ msgstr "Adicionar tarefa"
msgid "Add user(s) to the group:"
msgstr "Adicionar usuário(s) ao grupo:"
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr "Adicionar usuários ao grupo"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
-msgstr ""
+msgstr "A adição de novos aplicativos está desativada na sua instância do GitLab. Entre em contato com seu administrador do GitLab para obter a permissão"
msgid "Additional text"
msgstr "Texto adicional"
@@ -461,32 +514,29 @@ msgstr "Ãrea do Administrador"
msgid "Admin Overview"
msgstr "Visão Geral do Administrador"
-msgid "Admin area"
-msgstr "Ãrea do administrador"
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "Você está prestes a excluir permanentemente o usuário %{username}. Issues, merge requests, e grupos vinculados a ele serão transferidos para um \"usuário fantasma\" em todo o sistema. Para evitar a perda de dados, considere o uso do recurso %{strong_start}bloquear usuário%{strong_end}. Depois de %{strong_start}Deletar o usuário%{strong_end}, não será possível desfazer ou recuperá-lo."
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Você está prestes a excluir permanentemente o usuário(a) %{username}. Isso excluirá todos as Issues, merge requests e grupos vinculados a ele(a). Para evitar a perda de dados, considere o uso do recurso %{strong_start}bloquear usuário%{strong_end}. Uma vez que você%{strong_start}A deleção de usuário(a)%{strong_end}, não pode ser desfeita ou recuperada."
msgid "AdminArea|Stop all jobs"
-msgstr "Parar todos os processos"
+msgstr "Parar todas as tarefas"
msgid "AdminArea|Stop all jobs?"
-msgstr "Parar todos os processos?"
+msgstr "Parar todas as tarefas?"
msgid "AdminArea|Stop jobs"
-msgstr "Parar processos"
+msgstr "Parar tarefas"
msgid "AdminArea|Stopping jobs failed"
-msgstr "Erro ao parar processos"
+msgstr "Erro ao parar tarefas"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
-msgstr "Você parará todos os processos. Os processos em execução serão abruptamente interrompidos."
+msgstr "Você parará todas as tarefas. Os processos em execução serão abruptamente interrompidos."
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Você está prestes a excluir permanentemente o projeto %{projectName}, seu repositório e todos os recursos relacionados, incluindo issues, merge requests, etc. Uma vez que você confirmar e pressionar %{strong_start}Excluir projeto%{strong_end}, este não poderá ser desfeito ou recuperado."
msgid "AdminProjects|Delete"
msgstr "Excluir"
@@ -497,12 +547,42 @@ msgstr "Excluir o projeto %{projectName}?"
msgid "AdminProjects|Delete project"
msgstr "Excluir projeto"
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Especifique um domínio a ser usado por padrão para os estágios de Auto Review Application e Auto Deploy de cada projeto."
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Bloquear usuário"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "Excluir o usuário %{username} e suas contribuições?"
@@ -515,15 +595,45 @@ msgstr "Apagar usuário"
msgid "AdminUsers|Delete user and contributions"
msgstr "Excluir o usuário e suas contribuições"
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Para confirmar, digite %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Para confirmar, digite %{username}"
-msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgid "AdminUsers|User will be blocked"
msgstr ""
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr "Permissões avançadas, armazenamento de arquivos grandes e configurações de autenticação de dois fatores."
+
msgid "Advanced settings"
msgstr "Configurações avançadas"
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] "Alerta"
msgstr[1] "Alertas"
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr "Todos"
@@ -541,17 +654,23 @@ msgstr "Houve commit com todas as mudanças"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Todas as funcionalidades estão habilitadas para projetos em branco, a partir de templates ou ao importar, mas você pode desativá-los posteriormente nas configurações do projeto."
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr "Todos os usuários"
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr "Permitir commits de membros que podem fazer merge ao branch de destino."
msgid "Allow projects within this group to use Git LFS"
-msgstr ""
+msgstr "Permitir que projetos dentro deste grupo usem o Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
-msgstr "Permitir acesso público aos pipelines e detalhes de trabalho, incluindo logs de saída e artefatos"
+msgstr "Permitir acesso público aos pipelines e detalhes de tarefas, incluindo logs de saída e artefatos"
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Permitir renderização de diagramas PlantUML em documentos Asciidoc."
@@ -565,6 +684,9 @@ msgstr "Permitir que os usuários solicitem acesso"
msgid "Allow users to request access if visibility is public or internal."
msgstr "Permitir que os usuários solicitem acesso se a visibilidade for pública ou interna."
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Permite adicionar e gerenciar clusters do Kubernetes."
@@ -581,7 +703,7 @@ msgid "Alternatively, you can use a %{personal_access_token_link}. When you crea
msgstr "Alternativamente, você pode usar um %{personal_access_token_link}. Quando você cria seu Token de Acesso Pessoal, você precisará selecionar o escopo do <code>repositório</code>, para que possamos exibir uma lista de seus repositórios públicos e privados que estão disponíveis para se importar."
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
-msgstr ""
+msgstr "Quantidade de tempo (em horas) que os usuários podem ignorar a configuração forçada da autenticação de dois fatores"
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr "Uma chave SSH será gerada automaticamente quando o formulário for enviado. Para mais informações, consulte a documentação."
@@ -592,48 +714,21 @@ msgstr "Um aplicativo chamado %{link_to_client} está solicitando acesso à sua
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Um campo vazio do usuário do GitLab adicionará o nome completo do usuário do FogBugz (por exemplo, \"Por John Smith\") na descrição de todos os issues e comentários. Ele também irá associar e/ou atribuir essas issues e comentários ao criador do projeto."
-msgid "An error accured whilst committing your changes."
-msgstr "Ocorreu um erro ao fazer commit de suas alterações."
-
msgid "An error has occurred"
msgstr "Ocorreu um erro"
-msgid "An error occured creating the new branch."
-msgstr "Um erro ocorreu ao criar o novo branch."
-
-msgid "An error occured whilst fetching the job trace."
-msgstr "Ocorreu um erro ao carregar o rastro da tarefa."
-
-msgid "An error occured whilst fetching the latest pipeline."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
-msgid "An error occured whilst loading all the files."
-msgstr "Um erro ocorreu no carregamento de todos os arquivos."
-
-msgid "An error occured whilst loading the file content."
-msgstr "Um erro ocorreu no carregamento do conteúdo do arquivo."
-
-msgid "An error occured whilst loading the file."
-msgstr "Um erro ocorreu no carregamento do arquivo."
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr "Ocorreu um erro ao carregar as alterações do merge request."
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr "Ocorreu um erro ao carregar os dados da versão do merge request."
-
-msgid "An error occured whilst loading the merge request."
-msgstr "Ocorreu um erro ao carregar as alterações do merge request."
-
-msgid "An error occured whilst loading the pipelines jobs."
-msgstr "Ocorreu um erro ao carregar as tarefas de pipeline."
-
msgid "An error occurred adding a draft to the discussion."
msgstr "Ocorreu um erro ao adicionar um rascunho à discussão."
msgid "An error occurred adding a new draft."
msgstr "Ocorreu um erro ao adicionar um novo rascunho."
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Erro ao pré-visualizar o blob"
@@ -662,7 +757,7 @@ msgid "An error occurred while fetching markdown preview"
msgstr "Erro ao gerar pré-visualização do markdown"
msgid "An error occurred while fetching pending comments"
-msgstr ""
+msgstr "Ocorreu um erro ao recuperar os comentários pendentes"
msgid "An error occurred while fetching sidebar data"
msgstr "Erro ao recuperar informações da barra lateral"
@@ -671,13 +766,13 @@ msgid "An error occurred while fetching stages."
msgstr "Ocorreu um erro o enquanto busca estágios."
msgid "An error occurred while fetching the job log."
-msgstr "Ocorreu um erro enquanto busca logs do job."
+msgstr "Ocorreu um erro na recuperação de logs da tarefa."
msgid "An error occurred while fetching the job."
-msgstr "Ocorreu um erro enquanto busca o trabalho."
+msgstr "Ocorreu um erro ao recuperar a tarefa."
msgid "An error occurred while fetching the jobs."
-msgstr "Ocorreu um erro enquanto busca os trabalhos."
+msgstr "Ocorreu um erro ao recuperar as tarefas."
msgid "An error occurred while fetching the pipeline."
msgstr "Erro ao recuperar informações da pipeline."
@@ -692,7 +787,7 @@ msgid "An error occurred while initializing path locks"
msgstr "Ocorreu um erro ao inicializar travas de caminhos"
msgid "An error occurred while loading chart data"
-msgstr ""
+msgstr "Ocorreu um erro ao carregar os dados do gráfico"
msgid "An error occurred while loading commit signatures"
msgstr "Erro ao carregar as assinaturas de commit"
@@ -706,12 +801,21 @@ msgstr "Erro ao carregar nomes de arquivos"
msgid "An error occurred while loading the file"
msgstr "Erro ao carregar o arquivo"
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr "Erro ao fazer a requisição."
msgid "An error occurred while removing approver"
msgstr "Ocorreu um erro ao remover o aprovador"
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr "Erro ao renderizar o KaTeX"
@@ -737,17 +841,62 @@ msgid "An error occurred while unsubscribing to notifications."
msgstr "Ocorreu um erro ao desinscrever às notificações."
msgid "An error occurred while updating the comment"
-msgstr ""
+msgstr "Ocorreu um erro durante a atualização do comentário"
msgid "An error occurred while validating username"
msgstr "Erro ao validar o nome de usuário"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Ocorreu um erro. Tente novamente."
-msgid "Analytics"
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
msgstr ""
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "Analytics"
+msgstr "Telemetria"
+
msgid "Anonymous"
msgstr "Anônimo"
@@ -767,7 +916,7 @@ msgid "Application"
msgstr "Aplicativo"
msgid "Application ID"
-msgstr ""
+msgstr "ID da aplicação"
msgid "Application: %{name}"
msgstr "Aplicativo: %{name}"
@@ -775,6 +924,21 @@ msgstr "Aplicativo: %{name}"
msgid "Applications"
msgstr "Aplicações"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "Abr"
@@ -787,21 +951,36 @@ msgstr "Projeto arquivado! Repositório e outros recursos de projeto são soment
msgid "Archived projects"
msgstr "Projetos arquivados"
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Tem certeza que deseja excluir este agendamento de pipeline?"
msgid "Are you sure you want to erase this build?"
-msgstr ""
+msgstr "Tem certeza de que deseja limpar este build?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Você tem certeza de que quer perder as alterações não salvas?"
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr "Tem certeza de que deseja regenerar a chave pública? Você precisará atualizar a chave pública no servidor remote antes que o espelhamento funcione novamente."
+
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Você tem certeza que quer remover %{group_name}?"
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr "Você tem certeza de que deseja excluir este item?"
@@ -812,11 +991,14 @@ msgid "Are you sure you want to reset the health check token?"
msgstr "Você tem certeza que quer reiniciar o token de status de saúde?"
msgid "Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "Você tem certeza de que deseja parar este ambiente?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Você tem certeza que quer destravar %{path_lock_path}?"
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "Você tem certeza?"
@@ -835,6 +1017,9 @@ msgstr "Solicite a um mantenedor do grupo para configurar um Runner de grupo."
msgid "Assertion consumer service URL"
msgstr "URL de serviço do consumidor de asserção"
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "Coloque uma cor personalizada, como #FF0000"
@@ -842,7 +1027,10 @@ msgid "Assign labels"
msgstr "Atribuir etiquetas"
msgid "Assign milestone"
-msgstr "Atribuir milestone"
+msgstr "Atribuir marco"
+
+msgid "Assign some issues to this milestone."
+msgstr ""
msgid "Assign to"
msgstr "Atribuir à"
@@ -871,6 +1059,9 @@ msgstr "Listas de responsáveis mostram todas as issues atribuídas ao usuário
msgid "Assignee(s)"
msgstr "Responsável(is)"
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Para anexar arquivo, arraste e solte ou %{upload_link}"
@@ -883,6 +1074,9 @@ msgstr "Ago"
msgid "August"
msgstr "Agosto"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "Log de autenticação"
@@ -898,6 +1092,9 @@ msgstr "Autor"
msgid "Authorization code:"
msgstr "Código de autorização:"
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr "A autorização foi concedida digitando seu nome de usuário e senha no aplicativo."
@@ -923,16 +1120,7 @@ msgid "Auto DevOps enabled"
msgstr "Auto DevOps ativo"
msgid "Auto DevOps, runners and job artifacts"
-msgstr "Auto DevOps, runners e artefatos de builds"
-
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr "Apps de revisão e deploy automáticos precisam de um %{kubernetes} para funcionar corretamente."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr "Apps de revisão e deploy automáticos precisam de um nome de domínio e um %{kubernetes} para funcionar corretamente."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "Apps de revisão automática e Auto Deploy precisam de um nome de domínio para que funcione corretamente."
+msgstr "Auto DevOps, runners e artefatos de tarefas"
msgid "Auto-cancel redundant, pending pipelines"
msgstr "Cancelar automaticamente os pipelines redundantes pendentes"
@@ -953,7 +1141,7 @@ msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Saiba mais em %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr ""
+msgstr "A pipeline de Auto DevOps foi ativada e será usada se não for encontrada configuração CI alternativa nos arquivos. %{more_information_link}"
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr "Você pode automaticamente construir e testar sua aplicação, se você %{link_to_auto_devops_settings} para este projeto. Você pode também fazer o deploy automaticamente, se você %{link_to_add_kubernetes_cluster}."
@@ -967,14 +1155,26 @@ msgstr "ativar Auto DevOps"
msgid "Automatically marked as default internal user"
msgstr "Marcado automaticamente como interno de usuário padrão"
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "Disponível"
-msgid "Available group Runners : %{runners}"
-msgstr "Runners de grupo disponíveis: %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
-msgid "Available group Runners : %{runners}."
-msgstr "Runners de grupo disponíveis: %{runners}."
+msgid "Avatar for %{name}"
+msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr "Foto de perfil será removida. Tem certeza?"
@@ -1046,7 +1246,7 @@ msgid "Badges|Saving the badge failed, please check the entered URLs and try aga
msgstr "Erro ao salvar selo, por favor, cheque os URLs digitados e tente novamente."
msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "Badges | As variáveis de %{docsLinkStart}%{docsLinkEnd} oferece suporte a GitLab: %{placeholders}"
+msgstr "As %{docsLinkStart}variáveis%{docsLinkEnd} suportadas pelo GitLab: %{placeholders}"
msgid "Badges|The badge was deleted."
msgstr "O selo foi apagado."
@@ -1073,10 +1273,10 @@ msgid "BatchComments|Delete all pending comments"
msgstr "Excluir todos os comentários pendentes"
msgid "BatchComments|Discard review?"
-msgstr ""
+msgstr "Descartar revisão?"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
-msgstr ""
+msgstr "Você está prestes a descartar sua revisão, o que excluirá todos os seus comentários pendentes. Os comentários excluídos %{strong_start}não podem%{strong_end} ser restaurados."
msgid "Begin with the selected commit"
msgstr "Comece com o commit selecionado"
@@ -1159,6 +1359,12 @@ msgstr "Importação de Servidores Bitbucket"
msgid "Bitbucket import"
msgstr "Importar do Bitbucket"
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr "Blog"
@@ -1168,11 +1374,6 @@ msgstr "Painéis"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "O branch %{branchName} não foi encontrado no repositório deste projeto."
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] "Branch (%{branch_count})"
-msgstr[1] "Branches (%{branch_count})"
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "O branch <strong>%{branch_name}</strong> foi criado. Para configurar o deploy automático, selecione um modelo de Yaml do GitLab CI e commit suas mudanças. %{link_to_autodeploy_doc}"
@@ -1326,21 +1527,36 @@ msgstr "Acessar arquivos"
msgid "Browse files"
msgstr "Navegar pelos arquivos"
-msgid "Built-In"
-msgstr "Embutido"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
msgid "Business metrics (Custom)"
msgstr "Métricas de negócios (personalizadas)"
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "por"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr "Configurações de CI / CD"
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr "O CI será executado usando as credenciais atribuídas acima."
@@ -1369,46 +1585,49 @@ msgid "CICD|Continuous deployment to production"
msgstr "Deploy contínuo para produção"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "Entrega contínua para a produção usando deploy incremental cronometrado"
msgid "CICD|Default to Auto DevOps pipeline"
-msgstr ""
+msgstr "Padrão para o pipeline Auto DevOps"
msgid "CICD|Deployment strategy"
msgstr "Estratégia de deploy"
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr "Estratégia de deploy precisa de um nome de domínio para funcionar corretamente."
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr "Não configure um domínio aqui se você estiver configurando vários clusters de Kubernetes com o Auto DevOps."
-
msgid "CICD|Jobs"
-msgstr "Jobs"
+msgstr "Tarefas"
msgid "CICD|Learn more about Auto DevOps"
msgstr "Aprender mais sobre Auto DevOps"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "O pipeline de Auto DevOps será executado se nenhum arquivo de configuração de IC alternativo for encontrado."
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
-msgstr "Você precisa especificar um domínio se você quiser usar Apps de Revisão Automáticos e Estágios de Deploy automáticos."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
msgid "CICD|instance enabled"
msgstr "Instância habilitada"
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de Retorno"
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr "Não é possível encontrar o commit HEAD para este branch"
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "Cancelar"
msgid "Cancel this job"
-msgstr "Cancelar esse job"
+msgstr "Cancelar essa tarefa"
msgid "Cannot be merged automatically"
msgstr "Não pode ser feito o merge automaticamente"
@@ -1416,12 +1635,21 @@ msgstr "Não pode ser feito o merge automaticamente"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Não se pode modificar um cluster Kubernetes gerenciado"
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr "Impressão digital do certificado"
msgid "Change Weight"
msgstr "Alterar Peso"
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr "Mudar modelo"
@@ -1443,12 +1671,12 @@ msgstr "Reverter"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Isso criará um novo commit para reverter as mudanças existentes."
-msgid "Changelog"
-msgstr "Registro de mudanças"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "Mudanças serão mostradas se revisão de <b>origem</b> tiver sofrido merge na revisão <b>alvo</b>."
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "Gráficos"
@@ -1456,11 +1684,17 @@ msgid "Chat"
msgstr "Bate-papo"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr "Verifique a %{docs_link_start}documentação%{docs_link_end}."
+
+msgid "Check your .gitlab-ci.yml"
msgstr ""
msgid "Checking %{text} availability…"
msgstr "Verificando disponibilidade de %{text}…"
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "Verificando disponibilidade de branch..."
@@ -1482,6 +1716,12 @@ msgstr "Escolha o arquivo ..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Escolha a branch/tag (ex: %{master}) ou número do commit (ex: %{sha}) para ver o que mudou ou para criar um merge request."
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr "Escolha um modelo..."
@@ -1500,6 +1740,9 @@ msgstr "Escolha o arquivo..."
msgid "Choose the top-level group for your repository imports."
msgstr "Escolha o grupo principal para importar seus repositórios."
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr "Escolha quais grupos você deseja sincronizar nesse nó secundário."
@@ -1540,7 +1783,7 @@ msgid "CiStatusLabel|skipped"
msgstr "ignorado"
msgid "CiStatusLabel|waiting for delayed job"
-msgstr "aguardando trabalho atrasado"
+msgstr "aguardando tarefa atrasada"
msgid "CiStatusLabel|waiting for manual action"
msgstr "aguardando ação manual"
@@ -1593,8 +1836,8 @@ msgstr "Todos os ambientes"
msgid "CiVariable|Create wildcard"
msgstr "Criar curinga"
-msgid "CiVariable|Error occured while saving variables"
-msgstr "Erro ao salvar variáveis"
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
msgid "CiVariable|New environment"
msgstr "Novo ambiente"
@@ -1614,6 +1857,12 @@ msgstr "Falha na validação"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "está indisponível: %{reason}"
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr "Limpar Pesquisa"
@@ -1621,13 +1870,13 @@ msgid "Clear search input"
msgstr "Limpar campo de pesquisa"
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
-msgstr "Clique em qualquer <strong>nome de projeto</strong> na lista a seguir para navegar para o milestone do projeto."
+msgstr "Clique em qualquer <strong>nome de projeto</strong> na lista a seguir para navegar para o marco do projeto."
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr "Clique no botão <strong>Baixar</strong> e aguarde a conclusão do download."
msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
-msgstr "Clique no botão <strong>Promover</strong> no canto superior direito para promover a um milestone de grupo."
+msgstr "Clique no botão <strong>Promover</strong> no canto superior direito para promover a um marco de grupo."
msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
msgstr "Clique no botão à direita <strong>Selecionar nenhum</strong>, uma vez que só precisamos do \"Google Code Project Hosting\"."
@@ -1653,28 +1902,52 @@ msgstr "Senha da chave de autenticação do cliente"
msgid "Clients"
msgstr "Clientes"
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr "Clonar repositório"
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr "Fechar"
msgid "Close epic"
msgstr "Fechar épico"
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr "Fechado"
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr "Issues Fechadas"
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} foi instalado com sucesso no seu cluster Kubernetes"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
-msgstr ""
+msgstr "%{boldNotice} Isso adicionará alguns recursos extras, como um balanceador de carga, o que pode acarretar custos adicionais, dependendo do provedor de hospedagem em que o cluster do Kubernetes está instalado. Se você estiver usando o Google Kubernetes Engine, você pode %{pricingLink}."
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1684,48 +1957,66 @@ msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Adicionar cluster Kubernetes"
msgid "ClusterIntegration|Add a Kubernetes cluster integration"
-msgstr ""
+msgstr "Adicionar uma integração com cluster 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 "Adicionando um cluster kubernetes no seu grupo, irá compartilhar automaticamente o cluster entre todos os seus projetos. Utilize apps de revisão, faça deploy de suas aplicações e rode facilmente suas pipelines para todos os seus projetos usando o mesmo cluster."
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "Adicionando uma integração ao seu grupo irá compartilhar o cluster entre todos os seus projetos."
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Opções avançadas na integração deste cluster Kubernetes"
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr "Depois de instalar o Ingress, você precisará apontar seu DNS curinga para o endereço IP externo gerado, a fim de visualizar o aplicativo depois que ele for implantado. %{ingressHelpLink}"
+
+msgid "ClusterIntegration|Alternatively"
msgstr ""
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "Erro ao recuperar zonas de projeto: %{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr "Erro ao recuperar seus projetos: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr "Ocorreu um erro ao entrar em contato com a Google Cloud API. Por favor, tente novamente mais tarde."
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr "Aplicações"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr "Tem certeza de que deseja remover a integração deste cluster do Kubernetes? Isso não excluirá o seu cluster atual do Kubernetes."
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr "Certificado CA"
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Pacote de autoridade certificadora (Formato PEM)"
msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr ""
+msgstr "Escolha quais aplicativos instalar em seu cluster do Kubernetes. O Helm Tiller é necessário para instalar qualquer um dos seguintes aplicativos."
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr "Escolha quais dos seus ambientes usarão esse cluster."
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1740,6 +2031,9 @@ msgstr "Copiar o endereço IP de entrada para a área de transferência"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr "Copiar nome do host Jupyter para a área de transferência"
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Copiar nome do cluster Kubernetes"
@@ -1753,10 +2047,10 @@ msgid "ClusterIntegration|Did you know?"
msgstr "Você sabia?"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
-msgstr ""
+msgstr "Ative ou desative connexão do GitLab com seu cluster Kubernetes."
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
-msgstr ""
+msgstr "Habilite esta configuração se estiver usando o controle de acesso baseado em função (RBAC)."
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr "Digite detalhes para seu cluster Kubernetes"
@@ -1765,7 +2059,16 @@ msgid "ClusterIntegration|Environment scope"
msgstr "Escopo de ambiente"
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 "Cada nova conta no Google Cloud Plataform (GCP) recebe US$300 em créditos por se %{sign_up_link}. Em parceria com o Google, o Gitlab pode oferecer um adicional de US$200 para novas contas do GCP para começar a usar a integração GKE do GitLab."
+msgstr "Cada nova conta no Google Cloud Plataform (GCP) recebe US$300 em créditos por se %{sign_up_link}. Em parceria com o Google, o GitLab pode oferecer um adicional de US$200 para novas contas do GCP para começar a usar a integração GKE do GitLab."
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
msgid "ClusterIntegration|Fetching machine types"
msgstr "Recuperando tipos de máquina"
@@ -1783,7 +2086,7 @@ msgid "ClusterIntegration|GitLab Runner"
msgstr "Gitlab Runner"
msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
-msgstr ""
+msgstr "GitLab Runner se conecta ao repositório deste projeto e executa tarefas de CI/CD, retornando resultados e implementando, aplicativos para produção."
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform projeto"
@@ -1795,13 +2098,13 @@ msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Projeto do Google Kubernetes Engine"
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "Cluster de grupo"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helm simplifica a instalação e o gerenciamento de aplicativos do Kubernetes. O Tiller é executado dentro do seu Kubernetes Cluster e gerencia os lançamentos de seus gráficos."
msgid "ClusterIntegration|Hide"
msgstr "Ocultar"
@@ -1819,7 +2122,7 @@ msgid "ClusterIntegration|Ingress IP Address"
msgstr "Endereço IP de entrada"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
-msgstr ""
+msgstr "Ingress oferece uma maneira de rotear solicitações para serviços com base no host ou caminho da solicitação, centralizando diversos serviços em um único ponto de entrada."
msgid "ClusterIntegration|Install"
msgstr "Instalar"
@@ -1839,6 +2142,12 @@ msgstr "Integrar automação de cluster Kubernetes"
msgid "ClusterIntegration|Integration status"
msgstr "Status de integração"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Nome do host Jupyter"
@@ -1846,12 +2155,18 @@ msgid "ClusterIntegration|JupyterHub"
msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
-msgstr ""
+msgstr "JupyterHub, um concentrador multiusuário, gera, gerencia e faz proxy de várias instâncias do servidor de notebook Jupyter de usuário único. O JupyterHub pode ser usado para servir notebooks para uma classe de alunos, um grupo de ciência de dados corporativos ou um grupo de pesquisa científica."
msgid "ClusterIntegration|Knative"
-msgstr ""
+msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
+msgstr "Nome de domínio Knative:"
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster"
@@ -1873,7 +2188,7 @@ msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google
msgstr "Cluster Kubernetes foi criado com sucesso no Google Kubernetes Engine. Atualize a página para ver os detalhes do cluster"
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
+msgstr "Clusters Kubernetes permitem que você use apps de revisão, faça deploy de suas aplicações, execute suas pipelines e muito mais de um jeito mais simples."
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Cluster Kubernetes podem ser usados para publicar aplicações e permitir app de revisão para esse projeto"
@@ -1885,9 +2200,12 @@ msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_en
msgstr "Saiba mais sobre as %{help_link_start}zonas%{help_link_end}."
msgid "ClusterIntegration|Learn more about Kubernetes"
-msgstr ""
+msgstr "Saiba mais sobre os Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr "Saiba mais sobre grupo de cluster Kubernetes"
+
+msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1933,7 +2251,7 @@ msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in o
msgstr "Aponte um DNS curinga para esse endereço IP gerado para acessar sua aplicação depois que ele for lançado."
msgid "ClusterIntegration|Project cluster"
-msgstr ""
+msgstr "Cluster do Projeto"
msgid "ClusterIntegration|Project namespace"
msgstr "Namespace do projeto"
@@ -1948,7 +2266,7 @@ msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{
msgstr "Prometheus é um sistema de monitoramento de código aberto com %{gitlabIntegrationLink} para monitorar aplicações lançadas."
msgid "ClusterIntegration|RBAC-enabled cluster"
-msgstr ""
+msgstr "Cluster habilitado para RBAC"
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr "Leia nosso %{link_to_help_page} em integração de cluter Kubernetes."
@@ -1968,6 +2286,9 @@ msgstr "Substitua isso por seu próprio nome de host, se desejar. Se você fizer
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Solicitação para início de instalação falhou"
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr "Salvar alterações"
@@ -2010,12 +2331,18 @@ msgstr "Mostrar"
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Alguma coisa deu errado do nosso lado."
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr "Erro ao criar cluster Kubernetes no Google Kubernetes Engine"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Algo deu errado ao instalar %{title}"
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr "O endereço IP está em processo de atribuição. Verifique seu cluster ou cotas do Kubernetes no Google Kubernetes Engine se demorar muito."
@@ -2023,7 +2350,7 @@ msgid "ClusterIntegration|This account must have permissions to create a Kuberne
msgstr "Essa conta precisa de permissões para criar um cluster Kubernetes no %{link_to_container_project} especificado"
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
-msgstr ""
+msgstr "Esta opção permite-lhe instalar aplicações em clusters RBAC."
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Alternar cluster Kubernetes"
@@ -2031,6 +2358,18 @@ msgstr "Alternar cluster Kubernetes"
msgid "ClusterIntegration|Token"
msgstr "Token"
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr "Validando status de faturamento do projeto"
@@ -2041,6 +2380,9 @@ msgid "ClusterIntegration|With a Kubernetes cluster associated to this project,
msgstr "Com um cluster Kubernetes associado a esse projeto, você pode utilizar apps de revisão, publicar suas aplicações, executar suas pipelines e muito mais de um jeito simples."
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr "Você deve primeiro instalar o Helm Tiller antes de instalar os aplicativos abaixo"
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
@@ -2070,6 +2412,9 @@ msgstr "configurado corretamente"
msgid "ClusterIntegration|sign up"
msgstr "cadastrar"
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr "Proprietários de código"
@@ -2082,7 +2427,16 @@ msgstr "Recolher"
msgid "Collapse sidebar"
msgstr "Minimizar barra lateral"
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
+msgstr "Comentário"
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
msgstr ""
msgid "Comment & resolve discussion"
@@ -2092,7 +2446,7 @@ msgid "Comment & unresolve discussion"
msgstr "Comentar e marcar a discussão como não resolvida"
msgid "Comment form position"
-msgstr ""
+msgstr "Posição do formulário de comentários"
msgid "Comments"
msgstr "Comentários"
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] "Commit"
msgstr[1] "Commits"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] "Commit (%{commit_count})"
-msgstr[1] "Commits (%{commit_count})"
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "Mensagem de Commit"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "Duração do commit em minutos para os últimos 30 commits"
@@ -2173,6 +2528,9 @@ msgstr "Parar versões do Git"
msgid "Compare Revisions"
msgstr "Comparar revisões"
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr "Compare as mudanças do último commit"
@@ -2200,10 +2558,16 @@ msgstr "Confidencial"
msgid "Confidentiality"
msgstr "Confidencialidade"
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr "Configurar timeouts do Gitaly."
msgid "Configure Tracing"
+msgstr "Configurar rastreamento"
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2213,13 +2577,13 @@ msgid "Configure limits for web and API requests."
msgstr "Configurar limites para web e requisições para API."
msgid "Configure push mirrors."
-msgstr ""
+msgstr "Configurar espelhamento de push."
msgid "Configure storage path settings."
-msgstr ""
+msgstr "Definir configurações do caminho de armazenamento."
msgid "Configure the %{link} integration."
-msgstr ""
+msgstr "Configure a integração de %{link}."
msgid "Configure the way a user creates a new account."
msgstr "Configurar a forma como o usuário cria uma nova conta."
@@ -2239,6 +2603,9 @@ msgstr "Conecte seus repositórios externos e pipelines CI/CD vão ser executado
msgid "Connecting..."
msgstr "Conectando..."
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr "Container Registry"
@@ -2287,6 +2654,9 @@ msgstr "Com o Container Registry do Docker integrado ao Gitlab, todo projeto pod
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Você pode usar também um %{deploy_token} para acesso somente-leitura às imagens do registry."
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr "Continuar"
@@ -2302,11 +2672,11 @@ msgstr "Contribua para o GitLab"
msgid "Contribution"
msgstr "Contribuições"
-msgid "Contribution guide"
-msgstr "Guia de contribuição"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
-msgstr ""
+msgstr "Contribuições para <strong>%{calendar_date}</strong>"
msgid "Contributions per group member"
msgstr "Contribuições por membro do grupo"
@@ -2338,21 +2708,27 @@ msgstr "Controlar a concorrência máxima do enchimento do repositório para ess
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr "Controlar a concorrência máxima de operações de verificação para esse nó Geo"
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr "Ãndice ConvDev"
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Copiar URL de Clone do %{protocol}"
-msgid "Copy HTTPS clone URL"
-msgstr "Copiar URL de Clone do HTTPS"
-
msgid "Copy ID to clipboard"
-msgstr ""
+msgstr "Copiar ID para área de transferência"
msgid "Copy SSH clone URL"
msgstr "Copiar URL de Clone do SSH"
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr "Copiar chave pública SSH para área de transferência"
@@ -2375,16 +2751,13 @@ msgid "Copy incoming email address to clipboard"
msgstr "Copiar endereço de e-mail para a área de transferência"
msgid "Copy link"
-msgstr ""
-
-msgid "Copy name to clipboard"
-msgstr ""
+msgstr "Copiar link"
msgid "Copy reference to clipboard"
msgstr "Copiar referência para área de transferência"
msgid "Copy secret to clipboard"
-msgstr ""
+msgstr "Copiar segredo para a área de transferência"
msgid "Copy to clipboard"
msgstr "Copiar para área de transferência"
@@ -2393,7 +2766,7 @@ msgid "Copy token to clipboard"
msgstr "Copiar token para a área de transferência"
msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
-msgstr ""
+msgstr "Não foi possível recuperar o status do pipeline. Para solução de problemas, leia a %{linkStart}documentação.%{linkEnd}"
msgid "Create"
msgstr "Criar"
@@ -2401,6 +2774,9 @@ msgstr "Criar"
msgid "Create New Directory"
msgstr "Criar Novo Diretório"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr "Criar uma nova branch"
@@ -2410,6 +2786,9 @@ msgstr "Criar um novo branch e abrir merge request"
msgid "Create a new issue"
msgstr "Criar uma nova issue"
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Crie um token de acesso pessoal na sua conta para dar pull ou push via %{protocol}."
@@ -2449,6 +2828,9 @@ msgstr "Criar merge request"
msgid "Create merge request and branch"
msgstr "Abrir merge request e criar branch"
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "Criar novo branch"
@@ -2471,7 +2853,7 @@ msgid "Create project label"
msgstr "Criar etiqueta de projeto"
msgid "Create your first page"
-msgstr ""
+msgstr "Crie sua primeira página"
msgid "CreateTag|Tag"
msgstr "Tag"
@@ -2515,14 +2897,11 @@ msgstr "Perfil"
msgid "CurrentUser|Settings"
msgstr "Configurações"
-msgid "Custom"
-msgstr "Personalizado"
-
msgid "Custom CI config path"
msgstr "Caminho de configuração do IC personalizado"
msgid "Custom hostname (for private commit emails)"
-msgstr ""
+msgstr "Hostname personalizado (para e-mails de commit privado)"
msgid "Custom notification events"
msgstr "Eventos de notificação personalizados"
@@ -2533,6 +2912,9 @@ msgstr "Níveis de notificação personalizados são equivalentes a níveis de p
msgid "Custom project templates"
msgstr "Modelos de projetos personalizados"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr "Personalizar cores"
@@ -2542,14 +2924,20 @@ msgstr "Personalize como os endereços de e-mail e nomes de usuário do FogBugz
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "Personalize como os endereços de e-mail e nomes de usuário do Google Code são importados para o GitLab. Na próxima etapa, você poderá selecionar os projetos que deseja importar."
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize language and region related settings."
msgstr ""
+msgid "Customize your merge request approval settings."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr "Personalize a sua configuração, visualize o status da pipeline e relatório de cobertura."
+
msgid "Cycle Analytics"
msgstr "Análise de Ciclo"
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
-msgstr ""
+msgstr "A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora para ir para produção em seu projeto."
msgid "CycleAnalyticsStage|Code"
msgstr "Código"
@@ -2572,6 +2960,9 @@ msgstr "Homologação"
msgid "CycleAnalyticsStage|Test"
msgstr "Teste"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr "Dashboard"
@@ -2581,9 +2972,12 @@ msgstr "Todos"
msgid "DashboardProjects|Personal"
msgstr "Pessoal"
-msgid "Date picker"
+msgid "Data is still calculating..."
msgstr ""
+msgid "Date picker"
+msgstr "Seletor de data"
+
msgid "Debug"
msgstr "Depurar"
@@ -2593,6 +2987,9 @@ msgstr "Dez"
msgid "December"
msgstr "Dezembro"
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr "Recusar e sair"
@@ -2602,6 +2999,12 @@ msgstr "Branch padrão"
msgid "Default classification label"
msgstr "Etiqueta de classificação padrão"
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr "Padrão: Importar diretamente o endereço de e-mail ou nome de usuário do Google Code"
@@ -2611,20 +3014,23 @@ msgstr "Padrão: Mapeie uma ID de conta do FogBugz para um nome completo"
msgid "Define a custom pattern with cron syntax"
msgstr "Defina um padrão personalizado utilizando a sintaxe do cron"
-msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr "Você tem certeza que deseja executar %{jobName} imediatamente? Caso contrário, essa tarefa será executada automaticamente após seu tempo acabar."
+
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
-msgstr ""
+msgstr "Tem certeza que deseja executar %{job_name} imediatamente? Essa tarefa será executada automaticamente após seu tempo acabar."
msgid "DelayedJobs|Start now"
-msgstr ""
+msgstr "Iniciar agora"
msgid "DelayedJobs|Unschedule"
-msgstr ""
+msgstr "Desprogramar"
msgid "DelayedJobs|delayed"
-msgstr ""
+msgstr "atrasado"
msgid "Delete"
msgstr "Excluir"
@@ -2641,6 +3047,12 @@ msgstr "Excluir comentário"
msgid "Delete list"
msgstr "Excluir lista"
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr "Excluído"
@@ -2775,11 +3187,14 @@ msgstr "Seu novo token de deploy"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Seu novo token de deploy de projeto foi criado."
-msgid "Deployed to"
+msgid "Deployed"
msgstr ""
+msgid "Deployed to"
+msgstr "Deploy para"
+
msgid "Deploying to"
-msgstr ""
+msgstr "Fazer deploy para"
msgid "Deprioritize label"
msgstr "Despriorizar etiqueta"
@@ -2802,14 +3217,17 @@ msgstr "Destruir"
msgid "Details"
msgstr "Detalhes"
-msgid "Detect host keys"
+msgid "Details (default)"
msgstr ""
+msgid "Detect host keys"
+msgstr "Detectar chaves de host"
+
msgid "Diff content limits"
-msgstr ""
+msgstr "Diferenciar limite de conteúdo"
msgid "Diff limits"
-msgstr ""
+msgstr "Diferenciar limites"
msgid "Diffs|No file name available"
msgstr "Nenhum nome de arquivo disponível"
@@ -2818,7 +3236,7 @@ msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "Algo errado aconteceu ao buscar linhas de comparação."
msgid "Direction"
-msgstr ""
+msgstr "Direção"
msgid "Directory name"
msgstr "Nome do diretório"
@@ -2832,36 +3250,51 @@ msgstr "Desativar para este projeto"
msgid "Disable group Runners"
msgstr "Desabilitar runners de grupo"
-msgid "Discard"
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
msgstr ""
+msgid "Discard"
+msgstr "Descartar"
+
msgid "Discard all changes"
msgstr "Descartar todas as alterações"
msgid "Discard all unstaged changes?"
-msgstr ""
+msgstr "Descartar todas as alterações fora da lista para commit?"
msgid "Discard changes"
msgstr "Rejeitar alterações"
msgid "Discard changes to %{path}?"
-msgstr ""
+msgstr "Descartar as alterações para %{path}?"
msgid "Discard draft"
msgstr "Descartar rascunho"
msgid "Discard review"
-msgstr ""
+msgstr "Descartar revisão"
-msgid "Discover GitLab Geo."
-msgstr "Descubra o GitLab Geo."
+msgid "Discover GitLab Geo"
+msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "Descubra projetos, grupos e snippets. Compartilhe seus projetos com outras pessoas"
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr "Ignorar"
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "Ignorar introdução do Cycle Analytics"
@@ -2869,7 +3302,7 @@ msgid "Dismiss Merge Request promotion"
msgstr "Descartar promoção de Merge Request"
msgid "Dismiss trial promotion"
-msgstr ""
+msgstr "Ignorar promoção de avaliação"
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Deseja personalizar como os endereços de e-mail e nomes de usuário do Google Code são importados para o GitLab?"
@@ -2889,6 +3322,12 @@ msgstr "Pronto"
msgid "Download"
msgstr "Baixar"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "Baixar tar"
@@ -2913,6 +3352,9 @@ msgstr "Arquivo de texto com as mudanças"
msgid "DownloadSource|Download"
msgstr "Baixar"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr "Votos negativos"
@@ -2928,9 +3370,15 @@ msgstr "Cada runner pode estar em um dos seguintes estados:"
msgid "Edit"
msgstr "Alterar"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr "Editar etiqueta"
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Alterar Agendamento do Pipeline %{id}"
@@ -2940,6 +3388,12 @@ msgstr "Editar Snippet"
msgid "Edit application"
msgstr "Editar aplicativo"
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr "Alterar arquivos no editor e fazer commit das alterações aqui"
@@ -2949,11 +3403,14 @@ msgstr "Editar grupo: %{group_name}"
msgid "Edit identity for %{user_name}"
msgstr "Editar identidade para %{user_name}"
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr "Elasticsearch"
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
+msgstr "Integração com Elasticsearch. Elasticsearch AWS IAM."
msgid "Email"
msgstr "E-mail"
@@ -2962,11 +3419,14 @@ msgid "Email patch"
msgstr "Patch de email"
msgid "Emails"
-msgstr "Emails"
+msgstr "E-mails"
msgid "Embed"
msgstr "Embutido"
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr "Ativar"
@@ -2991,6 +3451,9 @@ msgstr "Ativar e configurar métricas do Prometheus."
msgid "Enable classification control using an external service"
msgstr "Ativar controle de classificação usando um serviço externo"
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr "Ativar para este projeto"
@@ -3006,14 +3469,23 @@ msgstr "Ativar ou desativar checagem de versão e uso de ping."
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "Ativar reCAPTCHA ou Akismet e definir seus limites de IP."
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr "Ative a barra de desempenho para um determinado grupo."
-msgid "Enable usage ping"
+msgid "Enable two-factor authentication"
msgstr ""
+msgid "Enable usage ping"
+msgstr "Ativar dados de uso"
+
msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
+msgstr "Ativar a dados de uso para obter uma visão geral de como você está usando GitLab a partir de uma perspectiva de recurso."
msgid "Enabled"
msgstr "Habilitado"
@@ -3021,9 +3493,15 @@ msgstr "Habilitado"
msgid "Ends at (UTC)"
msgstr "Termina em (UTC)"
-msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgid "Enforce SSO-only authentication for this group"
msgstr ""
+msgid "Enforced SSO"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr "Digite o seu URL do servidor do Bitbucket e o token de acesso pessoal abaixo"
+
msgid "Enter the issue description"
msgstr "Digite a descrição da issue"
@@ -3036,9 +3514,27 @@ msgstr "Digite a descrição do merge request"
msgid "Enter the merge request title"
msgstr "Digite o título do merge request"
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr "Ambientes"
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Um erro ocorreu ao recuperar ambientes."
@@ -3067,10 +3563,10 @@ msgid "Environments|Environments"
msgstr "Ambientes"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr ""
+msgstr "Ambientes são locais onde o deploy é feito, tais como homologação ou produção."
msgid "Environments|Job"
-msgstr "Job"
+msgstr "Tarefa"
msgid "Environments|Learn more about stopping environments"
msgstr "Saiba mais sobre como parar ambientes"
@@ -3085,7 +3581,7 @@ msgid "Environments|No pod name has been specified"
msgstr "Nenhum nome pod foi especificado"
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 ""
+msgstr "Observe que esta ação irá parar o ambiente mas %{emphasisStart}não%{emphasisEnd} terá efeito sobre qualquer deploy existente devido a \"ação de parar ambiente\" sendo definida no arquivo %{ciConfigLinkEnd}.gitlab-ci.yml%{ciConfigLinkStart}."
msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
msgstr "Observe que essa ação interromperá o ambiente, mas %{emphasis_start}não%{emphasis_end} terá efeito em qualquer implementação existente devido a nenhuma \"ação de parada do ambiente\" estar definida no arquivo %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end}."
@@ -3114,11 +3610,14 @@ msgstr "Parar"
msgid "Environments|Stop environment"
msgstr "Parar ambiente"
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Atualizado"
msgid "Environments|You don't have any environments right now"
-msgstr ""
+msgstr "Você não tem nenhum ambiente no momento"
msgid "Environments|protected"
msgstr "protegido"
@@ -3126,9 +3625,6 @@ msgstr "protegido"
msgid "Epic"
msgstr "Epic"
-msgid "Epic will be removed! Are you sure?"
-msgstr "Epic será removido! Tem certeza?"
-
msgid "Epics"
msgstr "Epics"
@@ -3138,7 +3634,7 @@ msgstr "Roadmap de epics"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Epics permitem gerenciar seu portfólio de projetos de forma mais eficiente e com menos esforço"
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3148,16 +3644,16 @@ msgid "Epics|More information"
msgstr "Mais informações"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
-msgstr ""
+msgstr "Essas datas afetam a maneira como seus épicos aparecem no planejamento. As datas dos marcos vêm dos marcos atribuídos aos problemas do épico. Você também pode definir datas fixas ou removê-las completamente."
msgid "Epics|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 "Para agendar o seu épico %{epicDateType} baseado em marcos temporais, atribua um marco com uma data %{epicDateType} a qualquer issue no épico."
msgid "Epics|due"
-msgstr ""
+msgstr "prazo"
msgid "Epics|start"
-msgstr ""
+msgstr "Iniciar"
msgid "Error"
msgstr "Erro"
@@ -3165,9 +3661,15 @@ msgstr "Erro"
msgid "Error Reporting and Logging"
msgstr "Relatório e registro de erros"
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr "Erro ao criar epic"
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr "Erro ao recuperar informações de contribuintes."
@@ -3187,7 +3689,7 @@ msgid "Error loading branch data. Please try again."
msgstr "Erro ao carregar dados de branch. Por favor, tente novamente."
msgid "Error loading branches."
-msgstr ""
+msgstr "Erro ao carregar os branches."
msgid "Error loading last commit."
msgstr "Erro ao carregar último commit."
@@ -3202,17 +3704,23 @@ msgid "Error loading project data. Please try again."
msgstr "Erro ao carregar dados do projeto. Por favor, tente novamente."
msgid "Error loading template types."
-msgstr ""
+msgstr "Erro ao carregar os tipos de modelo."
msgid "Error loading template."
-msgstr ""
+msgstr "Erro ao carregar o modelo."
msgid "Error occurred when toggling the notification subscription"
msgstr "Erro ao alterar configuração de notificação de assinatura"
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr "Erro ao salvar alteração de etiqueta."
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr "Erro ao atualizar status para todas as tarefas."
@@ -3220,6 +3728,12 @@ msgid "Error updating todo status."
msgstr "Erro ao atualizar status das tarefas."
msgid "Error while loading the merge request. Please try again."
+msgstr "Erro ao carregar o merge request. Por favor, tente novamente."
+
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
msgstr ""
msgid "Estimated"
@@ -3243,6 +3757,12 @@ msgstr "EventFilterBy|Filtrar por eventos de push"
msgid "EventFilterBy|Filter by team"
msgstr "EventFilterBy|Filtrar por equipe"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Todos os dias (às 4:00)"
@@ -3252,9 +3772,39 @@ msgstr "Todos os meses (no dia primeiro às 4:00)"
msgid "Every week (Sundays at 4:00am)"
msgstr "Toda semana (domingos às 4:00)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr "Todos podem contribuir"
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr "Expandir"
@@ -3265,11 +3815,17 @@ msgid "Expand sidebar"
msgstr "Expandir barra lateral"
msgid "Expiration date"
+msgstr "Data de validade"
+
+msgid "Expired %{expiredOn}"
msgstr ""
-msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr "Explique o problema. Se necessário, forneça um link para a issue ou comentário relevante."
+
msgid "Explore"
msgstr "Explorar"
@@ -3288,9 +3844,21 @@ msgstr "Explorar projetos"
msgid "Explore public groups"
msgstr "Explorar grupos públicos"
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr "Autorização de Política de Classificação Externa"
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr "Autenticação externa"
@@ -3316,7 +3884,7 @@ msgid "Failed"
msgstr "Falha"
msgid "Failed Jobs"
-msgstr "Jobs falharam"
+msgstr "Tarefas com falha"
msgid "Failed to change the owner"
msgstr "Erro ao alterar o proprietário"
@@ -3325,44 +3893,59 @@ msgid "Failed to check related branches."
msgstr "Falha ao procurar por branches relacionadas."
msgid "Failed to deploy to"
-msgstr ""
+msgstr "Falha ao fazer deploy para"
msgid "Failed to load emoji list."
+msgstr "Falha ao carregar a lista de emojis."
+
+msgid "Failed to load errors from Sentry"
msgstr ""
msgid "Failed to remove issue from board, please try again."
msgstr "Falha ao remover issue do painel, por favor, tente novamente."
msgid "Failed to remove mirror."
-msgstr ""
+msgstr "Falha ao remover a espelho."
msgid "Failed to remove the pipeline schedule"
msgstr "Erro ao excluir o agendamento do pipeline"
-msgid "Failed to signing using smartcard authentication"
+msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr "Falha ao entrar usando a autenticação de cartão inteligente"
+
msgid "Failed to update issues, please try again."
msgstr "Falha ao atualizar Issues. Por favor, tente novamente."
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr "Falha"
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "Mais rápido, uma vez que reutiliza o espaço de trabalho do projeto (voltando a clonar, se não existir)"
msgid "Feature Flags"
msgstr "Sinalizadores de recurso"
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
msgid "FeatureFlags|API URL"
msgstr "URL da API"
msgid "FeatureFlags|Active"
msgstr "Ativo"
-msgid "FeatureFlags|Application name"
-msgstr ""
-
msgid "FeatureFlags|Configure"
msgstr "Configurar"
@@ -3372,8 +3955,11 @@ msgstr "Configurar sinalizadores de recursos"
msgid "FeatureFlags|Create feature flag"
msgstr "Criar sinalizador de recurso"
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
-msgstr "Excluir %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
msgid "FeatureFlags|Description"
msgstr "Descrição"
@@ -3384,48 +3970,81 @@ msgstr "Editar %{feature_flag_name}"
msgid "FeatureFlags|Edit Feature Flag"
msgstr "Editar sinalizador de recurso"
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr "Sinalizador de recurso"
-msgid "FeatureFlags|Feature flag"
-msgstr "Sinalizador de recurso"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
-msgstr "O sinalizador de recurso %{feature_flag_name} será removido. Você tem certeza?"
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
-msgstr "Os sinalizadores de recursos permitem que você configure o seu código em diferentes versões alterando dinamicamente determinadas funcionalidades."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
-msgstr "Comece a usar os sinalizadores de recursos"
+msgid "FeatureFlags|Get started with Feature Flags"
+msgstr ""
msgid "FeatureFlags|Inactive"
msgstr "Inativo"
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr "Instale uma %{docs_link_start}biblioteca de cliente compatível%{docs_link_end} e especifique o URL da API, o nome do aplicativo e o ID da instância durante a configuração."
+
msgid "FeatureFlags|Instance ID"
+msgstr "ID da instância"
+
+msgid "FeatureFlags|Loading Feature Flags"
msgstr ""
-msgid "FeatureFlags|More information"
+msgid "FeatureFlags|More Information"
msgstr ""
+msgid "FeatureFlags|More information"
+msgstr "Mais informações"
+
msgid "FeatureFlags|Name"
-msgstr ""
+msgstr "Nome"
msgid "FeatureFlags|New"
-msgstr ""
+msgstr "Novo"
msgid "FeatureFlags|New Feature Flag"
-msgstr ""
+msgstr "Novo sinalizador de recurso"
msgid "FeatureFlags|Save changes"
-msgstr ""
+msgstr "Salvar alterações"
msgid "FeatureFlags|Status"
msgstr "Status"
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr "Fev"
@@ -3435,15 +4054,35 @@ msgstr "Fevereiro"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "Campos nessa página não são mais editáveis, você pode configurar"
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
+msgstr "Modelos de arquivos"
+
+msgid "File upload error."
msgstr ""
msgid "Files"
msgstr "Arquivos"
-msgid "Files (%{human_size})"
-msgstr "Arquivos (%{human_size})"
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "Preencha nos campos abaixo, ative o <strong>%{enable_label}</strong> e pressione <strong>%{save_changes}</strong>"
@@ -3451,20 +4090,38 @@ msgid "Filter"
msgstr "Filtro"
msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
+msgstr "Filtrar por %{issuable_type} que estão atualmente fechados."
msgid "Filter by %{issuable_type} that are currently opened."
-msgstr ""
+msgstr "Filtrar por %{issuable_type} que estão atualmente abertos."
msgid "Filter by commit message"
msgstr "Filtrar por mensagem de commit"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
+msgstr "Filtro..."
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
msgstr ""
msgid "Find by path"
msgstr "Localizar por caminho"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "Localizar arquivo"
@@ -3477,12 +4134,18 @@ msgstr "Encontre o arquivo recém-extraído <code>Takeout/Google Code Project Ho
msgid "Fingerprints"
msgstr "Impressões digitais"
-msgid "Finish review"
+msgid "Finish editing this message first!"
msgstr ""
+msgid "Finish review"
+msgstr "Concluir a revisão"
+
msgid "Finished"
msgstr "Finalizado"
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "Primeiro"
@@ -3493,13 +4156,13 @@ msgid "Fixed date"
msgstr "Data fixa"
msgid "Fixed due date"
-msgstr ""
+msgstr "Data de vencimento fixa"
msgid "Fixed start date"
msgstr "Data de início fixa"
msgid "Fixed:"
-msgstr ""
+msgstr "Fixo:"
msgid "FogBugz Email"
msgstr "E-mail do FogBugz"
@@ -3526,22 +4189,25 @@ msgid "Footer message"
msgstr "Mensagem do Rodapé"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
-msgstr "Para projetos internos, qualquer usuário conectado pode visualizar pipelines e acessar detalhes do job (logs de saída e artefatos)"
+msgstr "Para projetos internos, qualquer usuário conectado pode visualizar pipelines e acessar detalhes da tarefa (logs de saída e artefatos)"
+
+msgid "For more info, read the documentation."
+msgstr ""
msgid "For more information, go to the "
msgstr "Para mais informações, vá para o "
msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr ""
+msgstr "Para mais informações, por favor, revise a %{link_start_tag}documentação de configuração do Jaeger%{link_end_tag}"
msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
-msgstr ""
+msgstr "Para obter mais informações, consulte a documentação sobre %{deactivating_usage_ping_link_start}desativando dados de uso%{deactivating_usage_ping_link_end}."
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "Para projetos privados, qualquer membro (guest ou superior) pode visualizar pipelines e acessar detalhes do trabalho (logs de saída e artefatos)"
+msgstr "Para projetos privados, qualquer membro (guest ou superior) pode visualizar pipelines e acessar detalhes das tarefas (logs de saída e artefatos)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "Para projetos públicos, qualquer pessoa pode visualizar pipelines e acessar detalhes do trabalho (logs de saída e artefatos)"
+msgstr "Para projetos públicos, qualquer pessoa pode visualizar pipelines e acessar detalhes das tarefas (logs de saída e artefatos)"
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork criado a partir de"
@@ -3552,6 +4218,9 @@ msgstr "Fork a partir de %{project_name} (apagado)"
msgid "Forking in progress"
msgstr "Fork em andamento"
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "Formato"
@@ -3559,7 +4228,7 @@ msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Erros encontrados em seu .gitlab-ci.yml:"
msgid "Free Trial of GitLab.com Gold"
-msgstr ""
+msgstr "Avaliação gratuita do GitLab.com Gold"
msgid "From %{provider_title}"
msgstr "De %{provider_title}"
@@ -3586,7 +4255,7 @@ msgid "From merge request merge until deploy to production"
msgstr "Do merge request até a implantação em produção"
msgid "From milestones:"
-msgstr ""
+msgstr "A partir de marcos:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Na visualização de detalhes do cluster do Kubernetes, instale o Runner pela lista de aplicativos"
@@ -3603,6 +4272,9 @@ msgstr "Pipelines Gerais"
msgid "Generate a default set of labels"
msgstr "Gerar etiquetas padrão"
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr "Geo"
@@ -3693,8 +4365,11 @@ msgstr "Soma de verificação não conferida"
msgid "GeoNodes|Out of sync"
msgstr "Fora de sincronia"
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
-msgstr "A remoção de um nó interrompe o processo de sincronização. Você tem certeza?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
msgid "GeoNodes|Replication slot WAL"
msgstr "WAL de slots de replicação"
@@ -3768,44 +4443,47 @@ msgstr "Checksum realizado nas wikis para verificação com suas contrapartes no
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr "Wikis verificados com suas contrapartes no nó Primário"
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr "Você tem nós Geo configurados usando uma conexão HTTP insegura. Recomendamos o uso de HTTPS."
msgid "Geo|%{name} is scheduled for forced re-download"
-msgstr ""
+msgstr "%{name} está agendado para forçar download novamente"
msgid "Geo|%{name} is scheduled for re-check"
-msgstr ""
+msgstr "%{name} está agendado para verificar novamente"
msgid "Geo|%{name} is scheduled for re-sync"
-msgstr ""
+msgstr "%{name} está agendado para re-sincronização"
msgid "Geo|All"
-msgstr ""
+msgstr "Todos"
msgid "Geo|All projects"
msgstr "Todos os projetos"
msgid "Geo|All projects are being scheduled for re-check"
-msgstr ""
+msgstr "Todos os projetos estão sendo agendados para nova verificação"
msgid "Geo|All projects are being scheduled for re-sync"
-msgstr ""
+msgstr "Todos os projetos estão sendo agendados para re-sincronização"
msgid "Geo|Batch operations"
-msgstr ""
+msgstr "Operações em lote"
msgid "Geo|Could not remove tracking entry for an existing project."
-msgstr ""
+msgstr "Não foi possível remover o registro de rastreamento de um projeto existente."
msgid "Geo|Failed"
-msgstr ""
+msgstr "Falha"
msgid "Geo|File sync capacity"
msgstr "Capacidade de sincronização de arquivo"
msgid "Geo|Geo Status"
-msgstr ""
+msgstr "Geo Status"
msgid "Geo|Groups to synchronize"
msgstr "Grupos para sincronizar"
@@ -3813,11 +4491,14 @@ msgstr "Grupos para sincronizar"
msgid "Geo|In sync"
msgstr "Em sincronia"
-msgid "Geo|Last successful sync"
+msgid "Geo|Last repository check run"
msgstr ""
+msgid "Geo|Last successful sync"
+msgstr "Última sincronização com êxito"
+
msgid "Geo|Last sync attempt"
-msgstr ""
+msgstr "Última tentativa de sincronização"
msgid "Geo|Last time verified"
msgstr "Última vez verificada"
@@ -3826,10 +4507,10 @@ msgid "Geo|Never"
msgstr "Nunca"
msgid "Geo|Next sync scheduled at"
-msgstr ""
+msgstr "Próxima sincronização programada às"
msgid "Geo|Not synced yet"
-msgstr ""
+msgstr "Ainda não sincronizado"
msgid "Geo|Pending"
msgstr "Pendente"
@@ -3841,7 +4522,7 @@ msgid "Geo|Pending verification"
msgstr "Verificação pendente"
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 "Projeto (ID: %{project_id}) não existe mais no primário. É seguro remover esse registro, pois isso não removerá nenhum dado no disco."
msgid "Geo|Projects in certain groups"
msgstr "Projetos em certos grupos"
@@ -3849,29 +4530,32 @@ msgstr "Projetos em certos grupos"
msgid "Geo|Projects in certain storage shards"
msgstr "Projetos em certos pedaços de armazenamento"
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr "Verificar novamente"
msgid "Geo|Recheck all projects"
-msgstr ""
+msgstr "Verificar novamente todos os projetos"
msgid "Geo|Redownload"
msgstr "Baixar novamente"
msgid "Geo|Remove"
-msgstr ""
+msgstr "Remover"
msgid "Geo|Repository sync capacity"
msgstr "Capacidade de sincronização de repositório"
msgid "Geo|Resync"
-msgstr ""
+msgstr "Ressincronizar"
msgid "Geo|Resync all projects"
-msgstr ""
+msgstr "Sincronizar novamente todos os projetos"
msgid "Geo|Retry count"
-msgstr ""
+msgstr "Contagem de retentativas"
msgid "Geo|Select groups to replicate."
msgstr "Selecione grupos para replicar."
@@ -3880,56 +4564,65 @@ msgid "Geo|Shards to synchronize"
msgstr "Shards para sincronizar"
msgid "Geo|Status"
-msgstr ""
+msgstr "Status"
msgid "Geo|Synced"
-msgstr ""
+msgstr "Sincronizado"
msgid "Geo|Synchronization failed - %{error}"
-msgstr ""
+msgstr "Falha na sincronização - %{error}"
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
-msgstr ""
+msgstr "O registro de rastreamento do projeto (%{project_id}) foi removido com êxito."
msgid "Geo|Tracking entry will be removed. Are you sure?"
-msgstr ""
+msgstr "Registro de rastreamento será removido. Tem a certeza?"
msgid "Geo|Unknown state"
-msgstr ""
+msgstr "Estado desconhecido"
msgid "Geo|Verification capacity"
msgstr "Capacidade de verificação"
msgid "Geo|Verification failed - %{error}"
-msgstr ""
+msgstr "Falha na verificação - %{error}"
msgid "Geo|Waiting for scheduler"
-msgstr ""
+msgstr "Aguardando o agendador"
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
+msgstr "Você está em um nó Geo secundário <b>somente para leitura</b>. Se você quiser fazer mudanças, você deve visitar essa página no %{primary_node}."
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
-msgstr ""
+msgstr "Você está em um nó Geo secundário <b>somente para leitura </b>. Você pode ser capaz de fazer um número limitado de mudanças ou executar uma quantidade limitada de ações nessa página."
msgid "Geo|You need a different license to use Geo replication"
-msgstr ""
+msgstr "Você precisa de uma licença diferente para usar a replicação geográfica"
msgid "Geo|misconfigured"
-msgstr ""
+msgstr "mal configurado"
msgid "Geo|primary"
-msgstr ""
+msgstr "primário"
msgid "Geo|secondary"
-msgstr ""
+msgstr "secundário"
msgid "Get a free instance review"
+msgstr "Obter gratuitamente uma instância de revisão"
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
msgstr ""
msgid "Git"
msgstr "Git"
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr "URL do repositório Git"
@@ -3957,9 +4650,15 @@ msgstr "Os GitLab Group Runners podem executar código para todos os projetos ne
msgid "GitLab Import"
msgstr "Importação do GitLab"
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr "Usuário GitLab"
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr "Exportação do projeto GitLab"
@@ -3990,6 +4689,9 @@ msgstr "URL do host do Gitea"
msgid "Gitea Import"
msgstr "Importação do Gitea"
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr "Voltar"
@@ -4014,6 +4716,9 @@ msgstr "Autenticação do Google não está %{link_to_documentation}. Peça ao a
msgid "Got it!"
msgstr "Entendi!"
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr "Gráfico"
@@ -4033,19 +4738,19 @@ msgid "Group Runners"
msgstr "Group Runners"
msgid "Group SAML must be enabled to test"
-msgstr ""
+msgstr "O grupo SAML deve ser habilitado para testar"
msgid "Group URL"
-msgstr ""
+msgstr "URL do grupo"
msgid "Group avatar"
msgstr "Avatar do grupo"
msgid "Group description"
-msgstr ""
+msgstr "Descrição do grupo"
msgid "Group description (optional)"
-msgstr ""
+msgstr "Descrição do grupo (opcional)"
msgid "Group details"
msgstr "Detalhes do grupo"
@@ -4059,15 +4764,18 @@ msgstr "Os mantenedores podem registrar grupos de runners em %{link}"
msgid "Group name"
msgstr "Nome do grupo"
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr "Grupo: %{group_name}"
msgid "GroupRoadmap|From %{dateWord}"
msgstr "A partir de %{dateWord}"
-msgid "GroupRoadmap|Loading roadmap"
-msgstr "Carregando roadmap"
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Alguma coisa deu errada ao recuperar epics"
@@ -4077,39 +4785,36 @@ msgstr "Desculpe, nenhum epic corresponde à sua pesquisa"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "O roadmap mostra o progresso de seus epics ao longo de uma linha do tempo"
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Para ampliar sua pesquisa, alterar ou remover filtros. Na visão mensal, apenas epics no mês passado, no mês atual e nos próximos 5 meses são exibidos &ndash; de %{startDate} a %{endDate}."
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Para ampliar sua pesquisa, alterar ou remover filtros. Na visão trimestral, apenas epics no trimestre passado, no trimestre atual e nos próximos 4 trimestre são exibidos &ndash; de %{startDate} a %{endDate}."
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Para ampliar sua pesquisa, alterar ou remover filtros. Na visão semanal, apenas epics na semana passada, na semana atual e nas próximas 4 semanas são exibidos &ndash; de %{startDate} a %{endDate}."
-
msgid "GroupRoadmap|Until %{dateWord}"
msgstr "Até %{dateWord}"
msgid "GroupSettings|Badges"
msgstr "Selos"
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Custom project templates"
msgstr ""
+msgid "GroupSettings|Customize your group badges."
+msgstr "Personalize os selos do seu grupo."
+
msgid "GroupSettings|Learn more about badges."
+msgstr "Saiba mais sobre os selos."
+
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Bloquear compartilhamento de projetos do grupo %{group} com outros grupos"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Essa configuração é aplicada no grupo %{ancestor_group} e foi sobrescrita nesse subgrupo."
@@ -4134,6 +4839,9 @@ msgstr "Grupos"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "Grupos também podem ser aninhados criando %{subgroup_docs_link_start}subgrupos%{subgroup_docs_link_end}."
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr "Visitados frequentemente"
@@ -4168,7 +4876,7 @@ msgid "GroupsEmptyState|You can manage your group member’s permissions and acc
msgstr "Você pode gerenciar permissões de membros e acesso do seu grupo para cada projeto no grupo."
msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
-msgstr ""
+msgstr "Tem certeza que deseja sair do grupo \"%{fullName}\"?"
msgid "GroupsTree|Create a project in this group."
msgstr "Criar um projeto nesse grupo."
@@ -4189,13 +4897,13 @@ msgid "GroupsTree|Loading groups"
msgstr "Carregando grupos"
msgid "GroupsTree|No groups matched your search"
-msgstr ""
+msgstr "Nenhum grupo corresponde à sua pesquisa"
msgid "GroupsTree|No groups or projects matched your search"
-msgstr ""
+msgstr "Desculpe, nenhum grupo ou projeto correspondem à sua pesquisa"
msgid "GroupsTree|Search by name"
-msgstr ""
+msgstr "Procura por nome"
msgid "Have your users email"
msgstr "Tem o e-mail de seus usuários"
@@ -4231,21 +4939,24 @@ msgid "Help page text and support page url."
msgstr "Texto da página de ajuda e Url da página de suporte."
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr "Aqui está a chave SSH pública que precisa ser adicionada ao servidor remoto. Para mais informações, consulte a documentação."
+
+msgid "Hide file browser"
msgstr ""
msgid "Hide host keys manual input"
-msgstr ""
+msgstr "Ocultar entrada manual das teclas do host"
msgid "Hide payload"
-msgstr ""
+msgstr "Ocultar carga"
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Ocultar valor"
msgstr[1] "Ocultar valores"
-msgid "Hide whitespace changes"
-msgstr "Ocultar as alterações de espaço em branco"
+msgid "Hide values"
+msgstr ""
msgid "History"
msgstr "Histórico"
@@ -4253,6 +4964,9 @@ msgstr "Histórico"
msgid "Housekeeping successfully started"
msgstr "Manutenção iniciada com sucesso"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr "Eu aceito o %{terms_link}"
@@ -4263,13 +4977,13 @@ msgid "ID"
msgstr "ID"
msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
-msgstr ""
+msgstr "Permitir visualizações ao vivo de projetos JavaScript no Web IDE usando a avaliação do lado do cliente CodeSandbox."
msgid "IDE|Back"
-msgstr ""
+msgstr "Voltar"
msgid "IDE|Client side evaluation"
-msgstr ""
+msgstr "Avaliação do lado do cliente"
msgid "IDE|Commit"
msgstr "Commit"
@@ -4278,28 +4992,28 @@ msgid "IDE|Edit"
msgstr "Editar"
msgid "IDE|Get started with Live Preview"
-msgstr ""
+msgstr "Introdução ao Live Preview"
msgid "IDE|Go to project"
-msgstr ""
+msgstr "Ir para projeto"
msgid "IDE|Live Preview"
-msgstr ""
+msgstr "Pré-visualização ao vivo"
msgid "IDE|Open in file view"
msgstr "Abrir na visualização de arquivos"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
-msgstr ""
+msgstr "Visualize seu aplicativo da Web usando a avaliação do lado do cliente do Web IDE."
msgid "IDE|Refresh preview"
-msgstr ""
+msgstr "Atualizar visualização"
msgid "IDE|Review"
msgstr "Revisar"
msgid "IP Address"
-msgstr ""
+msgstr "Endereço IP"
msgid "Identifier"
msgstr "Identificador"
@@ -4310,9 +5024,12 @@ msgstr "Identidades"
msgid "Identity provider single sign on URL"
msgstr "URL de logon único de provedor de identidade"
-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."
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
msgstr ""
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr "Se desativada, um branch local divergente não será atualizada automaticamente com commits de sua contraparte remota, para evitar a perda de dados locais. Se o branch padrão (%{default_branch}) tiver divergido e não puder ser atualizado, o espelhamento falhará. Outras branches divergentes são silenciosamente ignoradas."
+
msgid "If disabled, the access level will depend on the user's permissions in the project."
msgstr "Se desativado, o nível de acesso irá depender das permissões do usuário no projeto."
@@ -4340,9 +5057,15 @@ msgstr "Onion skin"
msgid "ImageDiffViewer|Swipe"
msgstr "Deslizar"
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr "Importar"
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr "Importar projetos do Gitea"
@@ -4361,17 +5084,29 @@ msgstr "Importar um projeto GitLab exportado"
msgid "Import in progress"
msgstr "Importação em andamento"
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr "Importar vários repositórios fazendo o upload de um arquivo manifest."
msgid "Import project"
msgstr "Importar projeto"
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr "Importar projetos do Bitbucket"
msgid "Import projects from Bitbucket Server"
-msgstr ""
+msgstr "Importar projetos do servidor do Bitbucket"
msgid "Import projects from FogBugz"
msgstr "Importar projetos do FogBugz"
@@ -4383,7 +5118,7 @@ msgid "Import projects from Google Code"
msgstr "Importar projetos do Google Code"
msgid "Import repositories from Bitbucket Server"
-msgstr ""
+msgstr "Importar repositórios do servidor do Bitbucket"
msgid "Import repositories from GitHub"
msgstr "Importar repositórios do GitHub"
@@ -4391,6 +5126,9 @@ msgstr "Importar repositórios do GitHub"
msgid "Import repository"
msgstr "Importar repositório"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr "Conectar repositórios de"
@@ -4404,6 +5142,9 @@ msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition.
msgstr "Melhore a pesquisa com Advanced Global Search e GitLab Enterprise Edition."
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr "Para ativar a análise no nível da instância, peça a um administrador para ativar o %{usage_ping_link_start}dados de uso%{usage_ping_link_end}."
+
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
@@ -4412,22 +5153,37 @@ msgstr "Na próxima etapa, você poderá selecionar os projetos que deseja impor
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "Inclua um contrato de Termos de Serviço e uma Política de Privacidade que todos os usuários devem aceitar."
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr "Inclua o nome de usuário no URL, se necessário: <code>https: //username@gitlab.company.com/group/project.git</code>."
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
msgstr ""
msgid "Incompatible Project"
msgstr "Projeto Incompatível"
msgid "Indicates whether this runner can pick jobs without tags"
-msgstr ""
+msgstr "Indica se este runner pode escolher tarefas sem tags"
msgid "Inline"
msgstr "Em linha"
msgid "Input host keys manually"
-msgstr ""
+msgstr "Insira as chaves do host manualmente"
msgid "Input your repository URL"
+msgstr "Insira seu URL do repositório"
+
+msgid "Insert suggestion"
msgstr ""
msgid "Install GitLab Runner"
@@ -4442,10 +5198,10 @@ msgstr[0] "Instância"
msgstr[1] "Instâncias"
msgid "Instance Statistics"
-msgstr ""
+msgstr "Estatísticas de Instância"
msgid "Instance Statistics visibility"
-msgstr ""
+msgstr "Visibilidade de Estatísticas de Instância"
msgid "Instance does not support multiple Kubernetes clusters"
msgstr "A instância não suporta múltiplos clusters Kubernetes"
@@ -4459,6 +5215,9 @@ msgstr "Configurações de Integrações"
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "As partes interessadas podem até contribuir enviando commits, caso queiram."
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr "Interno - O grupo e projetos internos podem ser visualizados por qualquer usuário autenticado."
@@ -4474,9 +5233,27 @@ msgstr "Padrão de intervalo"
msgid "Introducing Cycle Analytics"
msgstr "Apresentando a Análise de Ciclo"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr "Convidar"
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr "Issue"
@@ -4495,6 +5272,21 @@ msgstr "Painel"
msgid "IssueBoards|Boards"
msgstr "Painéis"
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr "Issues"
@@ -4508,7 +5300,7 @@ msgid "Issues, merge requests, pushes and comments."
msgstr "Issues, merge requests, pushes e comentários."
msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
-msgstr ""
+msgstr "Depois que você começa a criar issues para seus projetos, podemos começar a acompanhar e exibir métricas para elas"
msgid "IssuesAnalytics|Issues Created"
msgstr "Issues criadas"
@@ -4528,12 +5320,18 @@ msgstr "Não há issues para os projetos no seu grupo"
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr "Para ampliar sua pesquisa, altere ou remova filtros na barra de filtros acima"
-msgid "Jaeger URL"
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
-msgid "Jaeger tracing"
+msgid "It's you"
msgstr ""
+msgid "Jaeger URL"
+msgstr "URL Jaeger"
+
+msgid "Jaeger tracing"
+msgstr "Rastreamento de Jeager"
+
msgid "Jan"
msgstr "Jan"
@@ -4544,10 +5342,16 @@ msgid "Job"
msgstr "Trabalho"
msgid "Job has been erased"
-msgstr "O job foi apagado"
+msgstr "A tarefa foi apagada"
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
msgid "Jobs"
-msgstr "Jobs"
+msgstr "Tarefas"
msgid "Job|Browse"
msgstr "Navegar"
@@ -4562,7 +5366,7 @@ msgid "Job|Erase job log"
msgstr "Apagar log da tarefa"
msgid "Job|Job artifacts"
-msgstr ""
+msgstr "Artefatos de tarefas"
msgid "Job|Job has been erased"
msgstr "A tarefa foi apagada"
@@ -4583,12 +5387,12 @@ msgid "Job|Show complete raw"
msgstr "Mostrar raw completo"
msgid "Job|The artifacts were removed"
-msgstr ""
+msgstr "Os artefatos foram removidos"
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr "Jun"
msgid "June"
msgstr "Junho"
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
msgid "Kubernetes Cluster"
msgstr "Cluster Kubernetes"
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "O tempo de criação do cluster de Kubernetes excedeu o tempo limite; %{timeout}"
@@ -4676,7 +5486,7 @@ msgid "Labels|Promoting %{labelTitle} will make it available for all projects in
msgstr "Promover %{labelTitle} irá disponibilizá-la para todos os projetos dentro de %{groupName}. Etiquetas de projetos existentes com o mesmo título serão mescladas. Esta ação não pode ser revertida."
msgid "Large File Storage"
-msgstr ""
+msgstr "Armazenamento de arquivos grandes"
msgid "Last %d day"
msgid_plural "Last %d days"
@@ -4686,6 +5496,9 @@ msgstr[1] "Últimos %d dias"
msgid "Last Pipeline"
msgstr "Último Pipeline"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "Último commit"
@@ -4699,6 +5512,9 @@ msgid "Last edited by %{name}"
msgstr "Última edição por %{name}"
msgid "Last reply by"
+msgstr "Última resposta de"
+
+msgid "Last seen"
msgstr ""
msgid "Last update"
@@ -4716,15 +5532,39 @@ msgstr "em"
msgid "Latest changes"
msgstr "Últimas modificações"
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr "Saiba mais"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
-msgstr "Saiba mais sobre %{issue_boards_url}, para acompanhar issues em diversas listas, usando etiquetas, atribuições e milestones. Se você notar algo faltando nos painéis, por favor, crie uma issue em %{gitlab_issues_url}."
+msgstr "Saiba mais sobre %{issue_boards_url}, para acompanhar issues em diversas listas, usando etiquetas, atribuições e marcos. Se você notar algo faltando nos painéis, por favor, crie uma issue em %{gitlab_issues_url}."
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
msgid "Learn more about Kubernetes"
msgstr "Saiba mais sobre o Kubernetes"
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr "Saiba mais sobre branches protegidos"
@@ -4750,13 +5590,13 @@ msgid "License"
msgstr "Licença"
msgid "LicenseManagement|Add a license"
-msgstr ""
+msgstr "Adicionar uma licença"
msgid "LicenseManagement|Add licenses manually to approve or blacklist"
-msgstr ""
+msgstr "Adicionar licenças manualmente para autorizar ou incluir em lista negra"
msgid "LicenseManagement|Approve"
-msgstr ""
+msgstr "Aprovar"
msgid "LicenseManagement|Approve license"
msgstr "Aprovar licença"
@@ -4768,10 +5608,10 @@ msgid "LicenseManagement|Approved"
msgstr "Aprovada"
msgid "LicenseManagement|Blacklist"
-msgstr ""
+msgstr "Lista Negra"
msgid "LicenseManagement|Blacklist license"
-msgstr ""
+msgstr "Licença de lista negra"
msgid "LicenseManagement|Blacklist license?"
msgstr "Adicionar licença à lista negra?"
@@ -4780,7 +5620,7 @@ msgid "LicenseManagement|Blacklisted"
msgstr "Na lista negra"
msgid "LicenseManagement|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "LicenseManagement|License"
msgstr "Licença"
@@ -4792,10 +5632,10 @@ msgid "LicenseManagement|License details"
msgstr "Detalhes da licença"
msgid "LicenseManagement|License name"
-msgstr ""
+msgstr "Nome da licença"
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
-msgstr ""
+msgstr "Gerencie licenças aprovadas e na lista negra para este projeto."
msgid "LicenseManagement|Packages"
msgstr "Pacotes"
@@ -4807,27 +5647,27 @@ msgid "LicenseManagement|Remove license?"
msgstr "Remover licença?"
msgid "LicenseManagement|Submit"
-msgstr ""
+msgstr "Enviar"
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
-msgstr ""
+msgstr "No momento não há licenças aprovadas ou na lista negra neste projeto."
msgid "LicenseManagement|This license already exists in this project."
-msgstr ""
+msgstr "Esta licença já existe neste projeto."
msgid "LicenseManagement|URL"
msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
-msgstr ""
+msgstr "Você está prestes a remover a licença %{name} deste projeto."
msgid "Licenses"
msgstr "Licenças"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Limitado a mostrar %d evento, no máximo"
+msgstr[1] "Limitado a mostrar %d eventos, no máximo"
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -4842,10 +5682,10 @@ msgid "List available repositories"
msgstr "Listar repositórios disponíveis"
msgid "List view"
-msgstr ""
+msgstr "Exibir em lista"
msgid "List your Bitbucket Server repositories"
-msgstr ""
+msgstr "Liste seus repositórios do servidor Bitbucket"
msgid "List your GitHub repositories"
msgstr "Listar os seus repositórios no GitHub"
@@ -4862,6 +5702,12 @@ msgstr "Carregando IDE do GitLab..."
msgid "Loading..."
msgstr "Carregando..."
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr "Bloquear"
@@ -4872,7 +5718,7 @@ msgid "Lock not found"
msgstr "Bloqueio não encontrado"
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr ""
+msgstr "Travar este %{issuableDisplayName}? Apenas <strong>membros do projeto</strong> poderão comentar."
msgid "Lock to current projects"
msgstr "Travar para projetos existentes"
@@ -4890,7 +5736,7 @@ msgid "Locks give the ability to lock specific file or folder."
msgstr "Travas possibilitam travar um arquivo ou uma pasta específica."
msgid "Login with smartcard"
-msgstr ""
+msgstr "Entrar com cartão inteligente"
msgid "Logs"
msgstr "Logs"
@@ -4928,6 +5774,9 @@ msgstr "Gerenciar etiquetas"
msgid "Manage project labels"
msgstr "Gerenciar etiquetas de projetos"
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr "Gerencie a qualidade de membros do seu grupo ao adicionar outro nível de segurança com o SAML."
@@ -4958,50 +5807,50 @@ msgstr "Março"
msgid "Mark todo as done"
msgstr "Marcar como concluído"
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr "Markdown habilitado"
msgid "MarkdownToolbar|Add a bullet list"
-msgstr ""
+msgstr "Adicionar uma lista de marcadores"
msgid "MarkdownToolbar|Add a link"
-msgstr ""
+msgstr "Adicionar um link"
msgid "MarkdownToolbar|Add a numbered list"
-msgstr ""
+msgstr "Adicionar uma lista numerada"
msgid "MarkdownToolbar|Add a table"
-msgstr ""
+msgstr "Adicionar uma tabela"
msgid "MarkdownToolbar|Add a task list"
-msgstr ""
+msgstr "Adicionar uma lista de tarefas"
msgid "MarkdownToolbar|Add bold text"
-msgstr ""
+msgstr "Adicionar texto em negrito"
msgid "MarkdownToolbar|Add italic text"
-msgstr ""
+msgstr "Adicionar texto em itálico"
msgid "MarkdownToolbar|Go full screen"
-msgstr ""
+msgstr "Ir para tela cheia"
msgid "MarkdownToolbar|Insert a quote"
-msgstr ""
+msgstr "Inserir uma citação"
msgid "MarkdownToolbar|Insert code"
-msgstr ""
+msgstr "Inserir código"
msgid "Maven Metadata"
-msgstr ""
-
-msgid "Maven package"
-msgstr ""
+msgstr "Metadado do Maven"
msgid "Max access level"
msgstr "Nível máximo de acesso"
msgid "Maximum job timeout"
-msgstr ""
+msgstr "Tempo limite máximo da tarefa"
msgid "May"
msgstr "Mai"
@@ -5010,7 +5859,7 @@ msgid "Median"
msgstr "Mediana"
msgid "Member lock"
-msgstr ""
+msgstr "Bloqueio de membro"
msgid "Member since %{date}"
msgstr "Membro desde %{date}"
@@ -5018,24 +5867,36 @@ msgstr "Membro desde %{date}"
msgid "Members"
msgstr "Membros"
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "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 "Membros serão encaminhados quando fizerem login no seu grupo. Obtenha isso pelo seu provedor de identidade, também chamado de \"SSO Service Location\", \"SAM Token Issuance Endpoint\", ou \"SAML 2.0/W-Federation URL\"."
msgid "Merge Request"
msgstr "Merge Request"
-msgid "Merge Request:"
-msgstr "Merge Request:"
-
msgid "Merge Requests"
msgstr "Merge Requests"
msgid "Merge Requests created"
msgstr "Merge Requests criadas"
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr "Eventos de merge"
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr "Merge requests"
@@ -5048,19 +5909,31 @@ msgstr "Merge requests"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "A tela de Merge request é um lugar para propor mudanças em um projeto e discutir essas mudanças com outros"
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr "Ocorreu um erro ao salvar o rascunho do comentário."
+
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,13 +5951,34 @@ msgstr "Visualizar o arquivo @ %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "Ver arquivo substituído @ %{commitId}"
-msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgid "MergeRequests|commented on commit %{commitLink}"
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequests|started a discussion"
msgstr ""
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr "%{paragraphStart}alterou a descrição %{descriptionChangedTimes} vezes %{timeDifferenceMinutes}%{paragraphEnd}"
+
+msgid "MergeRequest|Filter files"
+msgstr "Filtrar arquivos"
+
msgid "MergeRequest|No files found"
+msgstr "Nenhum arquivo encontrado"
+
+msgid "MergeRequest|Search files"
msgstr ""
msgid "Merged"
@@ -5103,10 +5997,10 @@ msgid "Metrics - Prometheus"
msgstr "Métricas - Prometheus"
msgid "Metrics and profiling"
-msgstr ""
+msgstr "Métricas e perfis"
-msgid "Metrics|Business"
-msgstr "Negócios"
+msgid "Metrics for environment"
+msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Confira a documentação de CI/CD sobre como implantar em um ambiente"
@@ -5114,6 +6008,12 @@ msgstr "Confira a documentação de CI/CD sobre como implantar em um ambiente"
msgid "Metrics|Create metric"
msgstr "Criar métricas"
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr "Editar métricas"
@@ -5123,8 +6023,8 @@ msgstr "Ambiente"
msgid "Metrics|For grouping similar metrics"
msgstr "Para agrupar métricas similares"
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
-msgstr "Rótulo do eixo vertical do gráfico. Geralmente, o tipo da unidade que está sendo mapeada. O eixo horizontal (eixo X) representa sempre o tempo."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
msgid "Metrics|Learn about environments"
msgstr "Aprenda sobre ambientes"
@@ -5135,24 +6035,18 @@ msgstr "Rótulo de legenda (opcional)"
msgid "Metrics|Must be a valid PromQL query."
msgstr "Deve ser uma consulta PromQL válida."
-msgid "Metrics|Name"
-msgstr "Nome"
-
msgid "Metrics|New metric"
msgstr "Nova métrica"
msgid "Metrics|No deployed environments"
msgstr "Nenhum ambiente implantado"
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
msgid "Metrics|Prometheus Query Documentation"
msgstr "Documentação de consulta do Prometheus"
-msgid "Metrics|Query"
-msgstr "Consulta"
-
-msgid "Metrics|Response"
-msgstr "Resposta"
-
msgid "Metrics|System"
msgstr "Sistema"
@@ -5165,12 +6059,12 @@ msgstr "Houve um erro ao obter informações de deploy."
msgid "Metrics|There was an error getting environments information."
msgstr "Houve um erro ao obter informações dos ambientes."
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
msgid "Metrics|There was an error while retrieving metrics"
msgstr "Ocorreu um erro ao recuperar as métricas"
-msgid "Metrics|Type"
-msgstr "Tipo"
-
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr "Resposta de dados de implantação inesperada da outra ponta do prometheus"
@@ -5189,83 +6083,74 @@ msgstr "Usado se a consulta retornar uma única série. Se ele retornar várias
msgid "Metrics|Y-axis label"
msgstr "Rótulo do eixo Y"
-msgid "Metrics|e.g. HTTP requests"
-msgstr "ex., requisições HTTP"
-
-msgid "Metrics|e.g. Requests/second"
-msgstr "ex., Requisições/segundo"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr "ex., Taxa de transferência"
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr "ex., rate(http_requests_total[5m])"
-
-msgid "Metrics|e.g. req/sec"
-msgstr "ex., req/seg"
-
msgid "Milestone"
-msgstr "Milestone"
+msgstr "Marco"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "Listas de marcos não estão disponíveis para a sua licença atual"
msgid "Milestone lists show all issues from the selected milestone."
-msgstr ""
+msgstr "As listas de marcos mostram todas as issues do marco selecionado."
msgid "Milestones"
msgstr "Marcos"
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 "Você está prestes a excluir permanentemente o marco %{milestoneTitle} e removê-lo de %{issuesWithCount} e %{mergeRequestsWithCount}. Uma vez excluído, não será possível desfazer ou recuperar."
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 "Você está prestes a excluir permanentemente o marco %{milestoneTitle}. Este marco não é usado atualmente em nenhuma issue ou merge requests."
msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
msgid "Milestones|Delete milestone"
-msgstr "Excluir Milestone"
+msgstr "Excluir marco"
msgid "Milestones|Delete milestone %{milestoneTitle}?"
-msgstr "Excluir Milestone %{milestoneTitle}?"
+msgstr "Excluir marco %{milestoneTitle}?"
msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
-msgstr "Falha ao excluir Milestone %{milestoneTitle}"
+msgstr "Falha ao excluir marco %{milestoneTitle}"
msgid "Milestones|Milestone %{milestoneTitle} was not found"
-msgstr "Milestone %{milestoneTitle} não foi encontrado"
+msgstr "Marco %{milestoneTitle} não foi encontrado"
msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
-msgstr "Promover Milestone %{milestoneTitle} de projeto para Milestone de grupo?"
+msgstr "Promover %{milestoneTitle} para marco de grupo?"
msgid "Milestones|Promote Milestone"
-msgstr "Promover Milestone"
+msgstr "Promover Marco"
msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr "Promover %{milestone} irá disponibilizá-lo para todos os projetos dentro de %{groupName}. Os milestones de projeto existentes com o mesmo nome serão mesclados. "
+msgstr "Promover %{milestone} irá disponibilizá-lo para todos os projetos dentro de %{groupName}. Os marcos de projeto existentes com o mesmo nome serão mesclados. "
msgid "Milestones|This action cannot be reversed."
msgstr "Essa ação não pode ser revertida."
msgid "Mirror a repository"
-msgstr ""
+msgstr "Espelhar um repositório"
msgid "Mirror direction"
-msgstr ""
+msgstr "Direção do espelho"
msgid "Mirror repository"
-msgstr ""
+msgstr "Espelhar repositório"
msgid "Mirror user"
-msgstr ""
+msgstr "Espelhar usuário"
msgid "Mirrored repositories"
-msgstr ""
+msgstr "Repositórios espelhados"
msgid "Mirroring repositories"
-msgstr ""
+msgstr "Espelhando repositórios"
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "adicione uma chave SSH"
@@ -5276,6 +6161,18 @@ msgstr "Cancelar"
msgid "Modal|Close"
msgstr "Fechar"
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "Monitoramento"
@@ -5322,7 +6219,7 @@ msgid "Name:"
msgstr "Nome:"
msgid "Naming, visibility"
-msgstr ""
+msgstr "Nomenclatura, visibilidade"
msgid "Nav|Help"
msgstr "Ajuda"
@@ -5336,6 +6233,9 @@ msgstr "Entrar / Registar"
msgid "Nav|Sign out and sign in with a different account"
msgstr "Saia e faça login com uma conta diferente"
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr "Rede"
@@ -5343,11 +6243,14 @@ msgid "Never"
msgstr "Nunca"
msgid "New"
-msgstr ""
+msgstr "Novo"
msgid "New Application"
msgstr "Novo aplicativo"
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr "Novo Grupo"
@@ -5362,6 +6265,12 @@ msgstr[1] "Novas Issues"
msgid "New Label"
msgstr "Nova etiqueta"
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "Novo Agendamento de Pipeline"
@@ -5380,6 +6289,9 @@ msgstr "Novo branch indisponível"
msgid "New directory"
msgstr "Novo diretório"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr "Novo épico"
@@ -5401,6 +6313,9 @@ msgstr "Nova etiqueta"
msgid "New merge request"
msgstr "Novo merge request"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "Novos pipelines cancelarão pipelines pendentes mais antigos no mesmo branch"
@@ -5428,36 +6343,51 @@ msgstr "Não"
msgid "No Label"
msgstr "Sem etiqueta"
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr "Sem responsável"
msgid "No branches found"
-msgstr ""
+msgstr "Nenhuma branch encontrada"
msgid "No changes"
msgstr "Sem alterarções"
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Nenhuma conexão pode ser feita para um servidor Gitaly, por favor check os logs!"
msgid "No container images stored for this project. Add one by following the instructions above."
-msgstr ""
+msgstr "Não há nenhuma imagem gravada neste projeto. Adicione uma seguindo as instruções acima."
msgid "No contributions were found"
-msgstr ""
+msgstr "Nenhuma contribuição foi encontrada"
msgid "No credit card required."
+msgstr "Não é necessário cartão de crédito."
+
+msgid "No details available"
msgstr ""
msgid "No due date"
msgstr "Sem validade"
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr "Sem estimativa de tempo gasto"
msgid "No file chosen"
msgstr "Nenhum arquivo escolhido"
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr "Nenhum arquivo encontrado."
@@ -5468,6 +6398,9 @@ msgid "No labels with such name or description"
msgstr "Sem etiquetas com esse nome ou descrição"
msgid "No license. All rights reserved"
+msgstr "Nenhuma licença. Todos os direitos reservados"
+
+msgid "No matching results"
msgstr ""
msgid "No merge requests for the selected time period."
@@ -5479,10 +6412,13 @@ msgstr "Nenhum merge requests encontrado"
msgid "No messages were logged"
msgstr "Nenhuma mensagem foi registrada"
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Sem outras etiquetas com esse nome ou descrição"
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5498,26 +6434,23 @@ msgid "No repository"
msgstr "Nenhum repositório"
msgid "No runners found"
-msgstr ""
+msgstr "Nenhum runner encontrado"
msgid "No schedules"
msgstr "Nenhum agendamento"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr "Não, importe diretamente os endereços de e-mail e nomes de usuários existentes."
msgid "Nodes"
-msgstr ""
+msgstr "Nós"
msgid "None"
msgstr "Nenhum"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr "Merge não permitido"
@@ -5542,6 +6475,9 @@ msgstr "Agora não"
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "Observe que o branch master é automaticamente protegido. %{link_to_protected_branches}"
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "Nota: Como administrador, você pode configurar o %{github_integration_link}, que permitirá o login via GitHub e permitirá a conexão com repositórios sem gerar um Token de Acesso Pessoal."
@@ -5558,20 +6494,26 @@ msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Você tem certeza que quer cancelar a criação deste comentário?"
msgid "Notes|Collapse replies"
-msgstr ""
+msgstr "Recolher respostas"
msgid "Notes|Show all activity"
-msgstr ""
+msgstr "Exibir todas as atividades"
msgid "Notes|Show comments only"
-msgstr ""
+msgstr "Mostrar apenas comentários"
msgid "Notes|Show history only"
-msgstr ""
+msgstr "Mostrar apenas histórico"
msgid "Notification events"
msgstr "Eventos de notificação"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Fechar issue"
@@ -5585,7 +6527,7 @@ msgid "NotificationEvent|Merge merge request"
msgstr "Aceitar merge request"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "Novo épico"
msgid "NotificationEvent|New issue"
msgstr "Nova issue"
@@ -5658,8 +6600,8 @@ msgstr "Uma vez importados, repositórios podem ser espelhados por SSH. Leia mai
msgid "One more item"
msgid_plural "%d more items"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Mais um item"
+msgstr[1] "Mais %d itens"
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Um ou mais dos seus projetos do Bitbucket não podem ser importados diretamente no GitLab porque eles usam Subversion ou Mercurial para o controle de versão, ao invés de Git."
@@ -5668,28 +6610,43 @@ msgid "One or more of your Google Code projects cannot be imported into GitLab d
msgstr "Um ou mais dos seus projetos do Google Code não podem ser importados diretamente no GitLab porque eles usam Subversion ou Mercurial para o controle de versão, ao invés de Git."
msgid "Only admins"
-msgstr ""
-
-msgid "Only comments from the following commit are shown below"
-msgstr "Somente comentários do commit a seguir são mostrados abaixo"
+msgstr "Apenas administradores"
msgid "Only mirror protected branches"
+msgstr "Apenas branches protegidos por espelho"
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr "Somente membros do projeto podem comentar."
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "Oops, você tem certeza?"
msgid "Open"
msgstr "Abrir"
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr "Abrir no Xcode"
msgid "Open projects"
-msgstr ""
+msgstr "Abrir projetos"
msgid "Open sidebar"
msgstr "Abrir barra lateral"
@@ -5716,18 +6673,15 @@ msgid "Operations"
msgstr "Operações"
msgid "Operations Dashboard"
-msgstr ""
-
-msgid "Operations Settings"
-msgstr ""
+msgstr "Painel de Operações"
msgid "OperationsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "Adicione um projeto ao painel"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
-msgstr ""
+msgstr "O painel de operações fornece um resumo da integridade operacional de cada projeto, incluindo status de pipeline e alerta."
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5758,7 +6712,7 @@ msgid "Overview"
msgstr "Visão geral"
msgid "Overwrite diverged branches"
-msgstr ""
+msgstr "Substituir branches divergentes"
msgid "Owner"
msgstr "Proprietário"
@@ -5775,6 +6729,12 @@ msgstr "Pacotes"
msgid "Pages"
msgstr "Páginas"
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Último >>"
@@ -5787,17 +6747,32 @@ msgstr "Anterior"
msgid "Pagination|« First"
msgstr "<< Primeiro"
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr "Parte das mudanças do merge request"
msgid "Password"
msgstr "Senha"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "Cole a sua chave SSH pública, que geralmente é encontrada no arquivo '~/.ssh/id_rsa.pub' e começa com 'ssh-rsa'. Não use a sua chave SSH privada."
msgid "Path, transfer, remove"
-msgstr ""
+msgstr "Caminho, transferir, remover"
msgid "Path:"
msgstr "Caminho:"
@@ -5806,16 +6781,13 @@ msgid "Pause"
msgstr "Pausar"
msgid "Paused Runners don't accept new jobs"
-msgstr ""
+msgstr "Runners pausados não aceitam novas tarefas"
msgid "Pending"
msgstr "Pendente"
msgid "People without permission will never get a notification and won't be able to comment."
-msgstr ""
-
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr "Por trabalho. Se um trabalho ultrapassar esse limite, ele será marcado como falho"
+msgstr "Pessoas sem permissão nunca receberão uma notificação e não serão capazes de comentar."
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "Execute opções avançadas, como alterar o caminho, transferir ou remover o grupo."
@@ -5827,11 +6799,17 @@ msgid "Permissions"
msgstr "Permissões"
msgid "Permissions, LFS, 2FA"
-msgstr ""
+msgstr "Permissões, LFS, 2FA"
msgid "Personal Access Token"
msgstr "Token de Acesso Pessoal"
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "Pipeline"
@@ -5845,7 +6823,7 @@ msgid "Pipeline Schedules"
msgstr "Agendamentos da Pipeline"
msgid "Pipeline quota"
-msgstr "Quota de pipeline"
+msgstr "Cota de pipeline"
msgid "Pipeline triggers"
msgstr "Gatilho de pipeline"
@@ -5923,7 +6901,7 @@ msgid "Pipelines|Clear Runner Caches"
msgstr "Limpar cache dos Runners"
msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
-msgstr ""
+msgstr "A integração contínua pode ajudar a capturar bugs, executando seus testes automaticamente enquanto a entrega contínua pode ajudá-lo a fornecer o código para o seu ambiente de produto."
msgid "Pipelines|Get started with Pipelines"
msgstr "Saiba como funcionam as pipelines"
@@ -5947,13 +6925,13 @@ msgid "Pipelines|There are currently no pipelines."
msgstr "Atualmente não há pipelines."
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar os pipelines. Tente novamente daqui a pouco ou entre em contato com sua equipe de suporte."
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Este projeto não está atualmente configurado para executar pipelines."
msgid "Pipeline|Commit"
-msgstr ""
+msgstr "Commit"
msgid "Pipeline|Create for"
msgstr "Criar para"
@@ -5962,13 +6940,13 @@ msgid "Pipeline|Create pipeline"
msgstr "Criar pipeline"
msgid "Pipeline|Duration"
-msgstr ""
+msgstr "Duração"
msgid "Pipeline|Existing branch name or tag"
msgstr "Nome de branch ou tag existente"
msgid "Pipeline|Pipeline"
-msgstr ""
+msgstr "Pipeline"
msgid "Pipeline|Run Pipeline"
msgstr "Executar Pipeline"
@@ -5983,7 +6961,7 @@ msgid "Pipeline|Stages"
msgstr "Estágios"
msgid "Pipeline|Status"
-msgstr ""
+msgstr "Estado"
msgid "Pipeline|Stop pipeline"
msgstr "Parar pipeline"
@@ -6018,6 +6996,9 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Iniciar"
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr "Por favor, aceite os Termos de Serviço antes de continuar."
@@ -6030,9 +7011,15 @@ msgstr "Por favor, converta-os para %{link_to_git} e passe pelo %{link_to_import
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "Por favor, converta-os em Git no Google Code e passe pelo %{link_to_import_flow} novamente."
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Por favor, preencha um nome descritivo para o seu grupo."
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Por favor, note que esse aplicativo não é fornecido pelo GitLab e você deve verificar a sua autenticidade antes de permitir o acesso."
@@ -6045,6 +7032,9 @@ msgstr "Por favor, resolva o reCAPTCHA"
msgid "Please try again"
msgstr "Por favor, tente novamente"
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr "Use este formulário para denunciar usuários ao GitLab que criam spam de issues, comentários ou se comportam de maneira inapropriada."
@@ -6064,13 +7054,13 @@ msgid "Press Enter or click to search"
msgstr "Pressione Enter ou clique para pesquisar"
msgid "Prevent adding new members to project membership within this group"
-msgstr ""
+msgstr "Impede a adição de novos membros ao projeto pertencentes a este grupo"
msgid "Preview"
msgstr "Pré-visualizar"
msgid "Preview payload"
-msgstr ""
+msgstr "Pré-visualização de carga"
msgid "Primary"
msgstr "Primário"
@@ -6087,6 +7077,9 @@ msgstr "Etiquetas priorizadas"
msgid "Prioritized label"
msgstr "Etiqueta priorizada"
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr "Privado - O acesso ao projeto deve ser concedido explicitamente para cada usuário."
@@ -6108,9 +7101,18 @@ msgstr "Você está prestes a excluir permanentemente a %{yourAccount}, e todas
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 "Você vai alterar o nome de usuário %{currentUsernameBold} para %{newUsernameBold}. O perfil e os projetos serão redirecionados para %{newUsername} mas esse redirecionamento expirará quando %{currentUsername} for registrado por outro usuário ou grupo. Por favor, atualize seus repositórios remotos Git o mais rápido possível."
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "Conta agendada para remoção."
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr "Adicionar chave"
@@ -6118,23 +7120,38 @@ msgid "Profiles|Add status emoji"
msgstr "Adicionar emoji de status"
msgid "Profiles|Avatar cropper"
-msgstr ""
+msgstr "Recortar Avatar"
msgid "Profiles|Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "O avatar será removido. Você tem certeza?"
msgid "Profiles|Change username"
msgstr "Alterar nome de usuário"
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr "Escolher arquivo..."
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr "Limpar status"
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Caminho atual: %{path}"
@@ -6151,7 +7168,10 @@ msgid "Profiles|Delete your account?"
msgstr "Deseja apagar sua conta?"
msgid "Profiles|Deleting an account has the following effects:"
-msgstr "Apagando conta tem os seguintes efeitos:"
+msgstr "A exclusão de uma conta tem os seguintes efeitos:"
+
+msgid "Profiles|Disconnect"
+msgstr ""
msgid "Profiles|Do not show on profile"
msgstr "Não mostrar no perfil"
@@ -6162,6 +7182,12 @@ msgstr "Não exibir informações pessoais relacionadas à atividade em seus per
msgid "Profiles|Edit Profile"
msgstr "Editar perfil"
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Senha inválida"
@@ -6198,11 +7224,14 @@ msgstr "Remover avatar"
msgid "Profiles|Set new profile picture"
msgstr "Definir nova foto de perfil"
-msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgid "Profiles|Social sign-in"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
-msgstr "Conte-nos sobre você em menos de 250 caracteres."
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr "Algumas opções estão indisponíveis para contas LDAP"
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "O tamanho máximo de arquivo permitido é de 200KB."
@@ -6210,8 +7239,8 @@ msgstr "O tamanho máximo de arquivo permitido é de 200KB."
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Isso não se parece com uma chave pública SSH, você tem certeza que gostaria de adicioná-la?"
-msgid "Profiles|This email will be displayed on your public profile."
-msgstr "Este e-mail será exibido no seu perfil público."
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
msgstr "Este e-mail será usado para operações baseadas na web, como edições e merges. %{learn_more}"
@@ -6219,11 +7248,14 @@ msgstr "Este e-mail será usado para operações baseadas na web, como edições
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr "Este emoji e mensagem aparecerão no seu perfil e em toda a interface."
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
-msgstr "Esta informação aparecerá no seu perfil."
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Escreva sua %{confirmationValue} para confirmar:"
@@ -6241,7 +7273,7 @@ msgid "Profiles|Upload new avatar"
msgstr "Enviar novo avatar"
msgid "Profiles|Use a private email - %{email}"
-msgstr ""
+msgstr "Utilize um email privado - %{email}"
msgid "Profiles|Username change failed - %{message}"
msgstr "Falha na alteração de nome de usuário - %{message}"
@@ -6249,23 +7281,26 @@ msgstr "Falha na alteração de nome de usuário - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "Alteração de nome de usuário realizada com sucesso"
-msgid "Profiles|Website"
-msgstr "Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
msgid "Profiles|What's your status?"
msgstr "Qual é o seu status?"
-msgid "Profiles|You can change your avatar here"
+msgid "Profiles|Who you represent or work for"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr "Você pode alterar o seu avatar aqui"
+
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
-msgstr ""
+msgstr "Você pode alterar o seu avatar aqui ou remover o avatar atual e reverter para %{gravatar_link}"
msgid "Profiles|You can upload your avatar here"
-msgstr ""
+msgstr "Você pode enviar o seu avatar aqui"
msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
-msgstr ""
+msgstr "Você pode enviar o seu avatar aqui ou alterá-lo em %{gravatar_link}"
msgid "Profiles|You don't have access to delete this user."
msgstr "Você não tem permissão para apagar esse usuário."
@@ -6273,16 +7308,19 @@ msgstr "Você não tem permissão para apagar esse usuário."
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "Você precisa delegar outro usuário para ser dono ou apagar esses grupos antes de excluir sua conta."
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Sua conta é atualmente proprietária dos seguintes grupos:"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr "Seu status"
msgid "Profiles|e.g. My MacBook key"
msgstr "por exemplo, Chave do meu MacBook"
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "sua conta"
@@ -6348,12 +7392,18 @@ msgstr "O link para a exportação do projeto expirou. Favor gerar uma nova expo
msgid "Project export started. A download link will be sent by email."
msgstr "Exportação do projeto iniciada. Um link para baixá-la será enviado por email."
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr "Nome do projeto"
msgid "Project slug"
msgstr "Slug do projeto"
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Inscreva-se"
@@ -6382,13 +7432,13 @@ msgid "ProjectLifecycle|Stage"
msgstr "Etapa"
msgid "ProjectOverview|Fork"
-msgstr ""
+msgstr "Fork"
msgid "ProjectOverview|Forks"
-msgstr ""
+msgstr "Forks"
msgid "ProjectOverview|Go to your fork"
-msgstr ""
+msgstr "Ir para seu fork"
msgid "ProjectOverview|Star"
msgstr "Marcar como favorito"
@@ -6397,7 +7447,7 @@ msgid "ProjectOverview|Unstar"
msgstr "Desmarcar como favorito"
msgid "ProjectOverview|You have reached your project limit"
-msgstr ""
+msgstr "Você atingiu seu limite de projetos"
msgid "ProjectOverview|You must sign in to star a project"
msgstr "Você precisa entrar para marcar um projeto como favorito"
@@ -6466,7 +7516,7 @@ msgid "ProjectsDropdown|Sorry, no projects matched your search"
msgstr "Desculpe, nenhum projeto corresponde a sua pesquisa"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "Esta funcionalidade necessita de suporte à localStorage do navegador"
msgid "PrometheusAlerts|Add alert"
msgstr "Adicionar alerta"
@@ -6498,9 +7548,6 @@ msgstr "Operador"
msgid "PrometheusAlerts|Threshold"
msgstr "Tolerância"
-msgid "PrometheusDashboard|Time"
-msgstr "Tempo"
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "%{exporters} com %{metrics} foram encontrados"
@@ -6525,6 +7572,9 @@ msgstr "Métricas comuns são monitoradas automaticamente com base em uma biblio
msgid "PrometheusService|Custom metrics"
msgstr "Métricas personalizadas"
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "Encontrando e configurando métricas..."
@@ -6577,10 +7627,10 @@ msgid "Promote"
msgstr "Promover"
msgid "Promote these project milestones into a group milestone."
-msgstr "Promova esses milestones de projeto em milestones de grupo."
+msgstr "Promova esses marcos de projeto em um marco de grupo."
msgid "Promote to Group Milestone"
-msgstr "Promover para Milestone de Grupo"
+msgstr "Promover para Marco de Grupo"
msgid "Promote to group label"
msgstr "Promover para etiqueta de grupo"
@@ -6589,7 +7639,7 @@ msgid "Promotions|Don't show me this again"
msgstr "Não me mostre isso novamente"
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 "Epics permitem que você gerencie seu portfólio de projetos com mais eficiência e com menos esforço rastreando grupos de issues que compartilham um tema, entre projetos e milestones."
+msgstr "Epics permitem que você gerencie seu portfólio de projetos com mais eficiência e com menos esforço rastreando grupos de issues que compartilham um tema, entre projetos e marcos."
msgid "Promotions|This feature is locked."
msgstr "Esse recurso está bloqueado."
@@ -6604,13 +7654,13 @@ msgid "Protected Environments"
msgstr "Ambientes Protegidos"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "%{environment_name} poderá ser editado por desenvolvedores. Tem certeza disso?"
msgid "ProtectedEnvironment|Allowed to deploy"
-msgstr ""
+msgstr "Permitido fazer deploy"
msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr ""
+msgstr "Escolher quem tem permissão para fazer deploy"
msgid "ProtectedEnvironment|Environment"
msgstr "Ambiente"
@@ -6619,31 +7669,31 @@ msgid "ProtectedEnvironment|Protect"
msgstr "Proteger"
msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
+msgstr "Proteger Ambientes, a fim de restringir quem pode executar deploy."
msgid "ProtectedEnvironment|Protect an environment"
-msgstr ""
+msgstr "Proteger um ambiente"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
-msgstr ""
+msgstr "Ambiente Protegido (%{protected_environments_count})"
msgid "ProtectedEnvironment|Select an environment"
-msgstr ""
+msgstr "Selecione um ambiente"
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr ""
+msgstr "Atualmente não existem ambientes protegidos, proteja um ambiente com o formulário acima."
msgid "ProtectedEnvironment|Unprotect"
msgstr "Desproteger"
msgid "ProtectedEnvironment|Your environment can't be unprotected"
-msgstr ""
+msgstr "Seu ambiente não pode ser desprotegido"
msgid "ProtectedEnvironment|Your environment has been protected."
-msgstr ""
+msgstr "Seu ambiente foi protegido."
msgid "ProtectedEnvironment|Your environment has been unprotected"
-msgstr ""
+msgstr "Seu ambiente foi desprotegido"
msgid "Protip:"
msgstr "Dicas:"
@@ -6654,6 +7704,9 @@ msgstr "Provedor"
msgid "Pseudonymizer data collection"
msgstr "Coleção de dados Pseudonymizer"
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "Público - O grupo e seus projetos podem ser visualizados por todos sem autenticação."
@@ -6693,26 +7746,35 @@ msgstr "Pushes"
msgid "Quarters"
msgstr "Trimestres"
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Ações rápidas podem ser usadas nas descrições das issues e nas caixas de comentário."
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "Leia mais"
+msgid "Read more about environments"
+msgstr ""
+
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr "Saiba mais sobre as permissões do projeto <strong>%{link_to_help}</strong>"
-msgid "Readme"
-msgstr "Leia-me"
-
msgid "Real-time features"
msgstr "Recursos em tempo real"
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr "Pesquisas recentes"
msgid "Redirect to SAML provider to test configuration"
-msgstr ""
+msgstr "Redirecionar para provedor SAML para testar configuração"
msgid "Reference:"
msgstr "Referência:"
@@ -6722,18 +7784,21 @@ msgstr "Atualizar"
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Atualizando em um segundo para mostrar o status atualizado..."
+msgstr[1] "Atualizando em %d segundos para mostrar o status atualizado..."
msgid "Regenerate key"
msgstr "Gerar uma nova chave"
msgid "Regex pattern"
-msgstr ""
+msgstr "Padrão Regex"
msgid "Register / Sign In"
msgstr "Registrar/Login"
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "Registre-se e veja seus runners para este grupo."
@@ -6764,6 +7829,12 @@ msgstr "Merge Requests Relacionados"
msgid "Related merge requests"
msgstr "Merge requests relacionados"
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "Lembrar mais tarde"
@@ -6773,6 +7844,12 @@ msgstr "Remover"
msgid "Remove Runner"
msgstr "Remover Runner"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Remover imagem"
@@ -6801,11 +7878,17 @@ msgid "Rename folder"
msgstr "Renomear pasta"
msgid "Reopen epic"
+msgstr "Reabrir epic"
+
+msgid "Reopen milestone"
msgstr ""
msgid "Repair authentication"
msgstr "Corrigir autenticação"
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr "Responda a este e-mail diretamente ou %{view_it_on_gitlab}."
@@ -6816,19 +7899,19 @@ msgid "Report abuse to GitLab"
msgstr "Denunciar abuso ao GitLab"
msgid "Reporting"
-msgstr ""
+msgstr "Reportando"
msgid "Reports|%{failedString} and %{resolvedString}"
-msgstr ""
+msgstr "%{failedString} e %{resolvedString}"
msgid "Reports|Actions"
-msgstr ""
+msgstr "Ações"
msgid "Reports|Class"
msgstr "Classe"
msgid "Reports|Confidence"
-msgstr ""
+msgstr "Confiança"
msgid "Reports|Execution time"
msgstr "Tempo de execução"
@@ -6852,10 +7935,10 @@ msgid "Reports|Test summary results are being parsed"
msgstr "Os resultados do resumo de teste estão sendo analisados"
msgid "Reports|Vulnerability"
-msgstr ""
+msgstr "Vulnerabilidade"
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "sem resultados de teste alterados"
msgid "Repository"
msgstr "Repositório"
@@ -6866,6 +7949,12 @@ msgstr "Configurações do Repositório"
msgid "Repository URL"
msgstr "URL do repositório"
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr "O repositório não possui bloqueios."
@@ -6884,21 +7973,39 @@ msgstr "Selecionar"
msgid "Request Access"
msgstr "Solicitar acesso"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr "Solicita Perfis"
msgid "Require all users in this group to setup Two-factor authentication"
-msgstr ""
+msgstr "Exigir que todos os usuários deste grupo configurem a autenticação de dois fatores"
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Exija que todos os usuários aceitem Termos de Serviço e Política de Privacidade quando acessarem o GitLab."
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr "Recriar o token de status de saúde"
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "Recriar o token de registro de runners"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr "Resolver todas discussões em novo issue"
@@ -6908,19 +8015,31 @@ msgstr "Resolver conflitos na branch de origem"
msgid "Resolve discussion"
msgstr "Resolver discussão"
-msgid "Response metrics (AWS ELB)"
+msgid "Resolved"
msgstr ""
+msgid "Response"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr "Métricas de resposta (AWS ELB)"
+
msgid "Response metrics (Custom)"
msgstr "Métricas de resposta (personalizadas)"
msgid "Response metrics (HA Proxy)"
+msgstr "Métricas de resposta (HA Proxy)"
+
+msgid "Response metrics (NGINX Ingress VTS)"
msgstr ""
msgid "Response metrics (NGINX Ingress)"
-msgstr ""
+msgstr "Métricas de resposta (NGINX Ingress)"
msgid "Response metrics (NGINX)"
+msgstr "Métricas de resposta (NGINX)"
+
+msgid "Restart Terminal"
msgstr ""
msgid "Resume"
@@ -6930,19 +8049,19 @@ msgid "Retry"
msgstr "Tentar novamente"
msgid "Retry this job"
-msgstr "Tentar novamente este trabalho"
+msgstr "Refazer tarefa"
msgid "Retry verification"
msgstr "Tentar novamente a verificação"
-msgid "Reveal Variables"
-msgstr "Revelar variáveis"
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] "Mostrar valor"
msgstr[1] "Mostrar valores"
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Reverter este commit"
@@ -6970,26 +8089,29 @@ msgstr "Roadmap"
msgid "Run CI/CD pipelines for external repositories"
msgstr "Executar pipelines CI/CD para repositórios externos"
-msgid "Run untagged jobs"
+msgid "Run tests against your code live using the Web Terminal"
msgstr ""
+msgid "Run untagged jobs"
+msgstr "Rodar tarefas sem tags"
+
msgid "Runner cannot be assigned to other projects"
-msgstr ""
+msgstr "Runner não pode ser atribuído a outros projetos"
msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
+msgstr "O runner executa tarefas de todos os projetos não atribuídos"
msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
+msgstr "O runner executa tarefas de todos os projetos não atribuídos em seu grupo"
msgid "Runner runs jobs from assigned projects"
-msgstr ""
+msgstr "O runner executa tarefas de projetos atribuídos"
msgid "Runner token"
msgstr "Token de runner"
msgid "Runner will not receive any new jobs"
-msgstr ""
+msgstr "O runner não receberá nenhuma tarefa nova"
msgid "Runners"
msgstr "Runners"
@@ -6997,14 +8119,17 @@ msgstr "Runners"
msgid "Runners API"
msgstr "Runners de API"
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Os corredores podem ser colocados em usuários, servidores e até mesmo em sua máquina local."
msgid "Runners can be placed on separate users, servers, even on your local machine."
-msgstr ""
+msgstr "Executores podem ser alocados em usuários separados, servidores, até mesmo em sua máquina local."
msgid "Runners currently online: %{active_runners_count}"
-msgstr ""
+msgstr "Executores online no momento: %{active_runners_count}"
msgid "Runners page"
msgstr "Página de runners"
@@ -7013,7 +8138,7 @@ msgid "Runners page."
msgstr "Página de runners."
msgid "Runners|You have used all your shared Runners pipeline minutes."
-msgstr ""
+msgstr "Você usou todos os seus minutos compartilhados para executores."
msgid "Running"
msgstr "Executando"
@@ -7030,8 +8155,8 @@ msgstr "SAML Single Sign On"
msgid "SAML Single Sign On Settings"
msgstr "Configurações de SAML Single Sign On"
-msgid "SAST"
-msgstr "SAST"
+msgid "SAML for %{group_name}"
+msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "Impressão digital SHA1 do certificado de assinatura de token SAML. Obtenha isso do seu provedor de identidade, onde ele também pode ser chamado de \"Thumbprint\"."
@@ -7040,7 +8165,7 @@ msgid "SSH Keys"
msgstr "Chaves SSH"
msgid "SSH host keys"
-msgstr ""
+msgstr "Chaves SSH do host"
msgid "SSH public key"
msgstr "Chave SSH pública"
@@ -7051,6 +8176,9 @@ msgstr "Verificação SSL"
msgid "Save"
msgstr "Salvar"
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr "Salvar aplicativo"
@@ -7058,6 +8186,9 @@ msgid "Save changes"
msgstr "Salvar alterações"
msgid "Save changes before testing"
+msgstr "Salvar alterações antes de testar"
+
+msgid "Save comment"
msgstr ""
msgid "Save pipeline schedule"
@@ -7096,6 +8227,9 @@ msgstr "Voltar ao topo"
msgid "Search"
msgstr "Pesquisar"
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr "Pesquisar branches"
@@ -7108,11 +8242,14 @@ msgstr "Procurar arquivos"
msgid "Search for projects, issues, etc."
msgstr "Pesquise por projetos, issues, etc."
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr "Pesquisar merge requests"
msgid "Search milestones"
-msgstr "Pesquisar milestones"
+msgstr "Pesquisar marcos"
msgid "Search or filter results..."
msgstr "Pesquisar ou filtrar resultados..."
@@ -7124,22 +8261,22 @@ msgid "Search project"
msgstr "Procurar projeto"
msgid "Search projects"
-msgstr ""
+msgstr "Pesquisar projetos"
msgid "Search users"
msgstr "Procurar usuários"
msgid "Search your projects"
-msgstr ""
+msgstr "Pesquisar nos seus projetos"
msgid "SearchAutocomplete|All GitLab"
msgstr "Todo o GitLab"
msgid "SearchAutocomplete|Issues I've created"
-msgstr ""
+msgstr "Issues que eu criei"
msgid "SearchAutocomplete|Issues assigned to me"
-msgstr ""
+msgstr "Issues atribuídas a mim"
msgid "SearchAutocomplete|Merge requests I've created"
msgstr "Merge requests que eu criei"
@@ -7166,56 +8303,77 @@ msgid "Security Dashboard"
msgstr "Painel de controle de segurança"
msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
-msgstr ""
+msgstr "Erro ao recuperar dados do dashboard. Por favor, verifique sua conexão de rede e tente novamente."
msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
-msgstr ""
+msgstr "Erro ao recuperar contagens de vulnerabilidades. Por favor, verifique sua conexão de rede e tente novamente."
msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
-msgstr ""
+msgstr "Erro ao recuperar lista de vulnerabilidades. Por favor, verifique sua conexão de rede e tente novamente."
msgid "Security Dashboard|Issue Created"
-msgstr ""
+msgstr "Issue criado"
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
-msgstr ""
+msgstr "Criar issue"
msgid "Security Reports|Dismiss vulnerability"
+msgstr "Ignorar vulnerabilidade"
+
+msgid "Security Reports|Learn more about setting up your dashboard"
msgstr ""
msgid "Security Reports|More info"
-msgstr ""
+msgstr "Mais informações"
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
-msgstr ""
+msgstr "Documentação do painel de segurança"
msgid "Security Reports|There was an error creating the issue."
-msgstr ""
+msgstr "Ocorreu um erro ao criar a issue."
msgid "Security Reports|There was an error dismissing the vulnerability."
-msgstr ""
+msgstr "Ocorreu um erro ao ignorar a vulnerabilidade."
msgid "Security Reports|There was an error reverting the dismissal."
-msgstr ""
+msgstr "Ocorreu um erro ao reverter o descarte."
msgid "Security Reports|There was an error reverting this dismissal."
+msgstr "Ocorreu um erro ao reverter este descarte."
+
+msgid "Security Reports|Undo dismiss"
msgstr ""
-msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
msgstr ""
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr "O painel de segurança exibe o último relatório de segurança. Use-o para encontrar e corrigir vulnerabilidades."
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "Monitorar vulnerabilidades no seu código"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "Pipeline %{pipelineLink} acionado"
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr "Selecionar"
@@ -7229,7 +8387,7 @@ msgid "Select a namespace to fork the project"
msgstr "Selecione um namespace para realizar o fork do projeto"
msgid "Select a template repository"
-msgstr ""
+msgstr "Selecione um repositório de modelos"
msgid "Select a timezone"
msgstr "Selecionar fuso horário"
@@ -7243,6 +8401,9 @@ msgstr "Selecione o responsável"
msgid "Select branch/tag"
msgstr "Selecionar o branch/tag"
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr "Selecionar projeto"
@@ -7262,10 +8423,10 @@ msgid "Select target branch"
msgstr "Selecionar branch de destino"
msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
+msgstr "Selecione o branch que você deseja definir como o padrão para este projeto. Todas os merges requests e commits serão feitos automaticamente nesse branch, a menos que você especifique um diferente."
msgid "Select the custom project template source group."
-msgstr ""
+msgstr "Selecione o grupo de origem dos modelos customizados de projeto."
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
msgstr "A seleção de um usuário do GitLab adicionará um link para o usuário do GitLab nas descrições de issues e comentários (por exemplo, \"Por <a href=\"#\">@johnsmith</a>\"). Isto também associará e/ou atribuirá esses issues e comentários ao usuário selecionado."
@@ -7276,7 +8437,13 @@ msgstr "Sincronização seletiva"
msgid "Send email"
msgstr "Enviar e-mail"
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
+msgstr "Enviar dados de uso"
+
+msgid "Sentry API URL"
msgstr ""
msgid "Sep"
@@ -7288,6 +8455,48 @@ msgstr "Setembro"
msgid "Server version"
msgstr "Versão do servidor"
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr "Balcão de Atendimento"
@@ -7304,13 +8513,13 @@ 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 a template repository for projects in this group"
-msgstr ""
+msgstr "Definir um repositório de modelos para projetos neste grupo"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Definir padrão e restringir os níveis de visibilidade. Configurar fontes de importação e protocolo de acesso git."
msgid "Set instance-wide template repository"
-msgstr ""
+msgstr "Definir repositório de modelos para toda a instância"
msgid "Set max session time for web terminal."
msgstr "Defina o tempo máximo da sessão para o terminal da web."
@@ -7318,6 +8527,9 @@ msgstr "Defina o tempo máximo da sessão para o terminal da web."
msgid "Set notification email for abuse reports."
msgstr "Definir notificação por e-mail para relatórios de abuso."
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "Definir requisitos para um usuário entrar. Ative a autenticação obrigatória de dois fatores."
@@ -7325,43 +8537,46 @@ msgid "Set up CI/CD"
msgstr "Configurar CI/CD"
msgid "Set up a %{type} Runner manually"
-msgstr ""
+msgstr "Configure o Runner %{type} manualmente"
msgid "Set up a specific Runner automatically"
-msgstr ""
+msgstr "Configurar um Runner específico automaticamente"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "Configurar asserções/atributos/alegações (email, first_name, last_name) e NameID de acordo com %{docsLinkStart}a documentação %{icon}%{docsLinkEnd}"
-msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgid "Set up new U2F device"
msgstr ""
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr "Configure seu projeto para fazer push e/ou pull de um repositório para outro automaticamente. Branches, tags e commits serão sincronizados automaticamente."
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "defina uma senha"
msgid "SetStatusModal|Add status emoji"
-msgstr ""
+msgstr "Adicionar emoji de status"
msgid "SetStatusModal|Clear status"
-msgstr ""
+msgstr "Limpar status"
msgid "SetStatusModal|Edit status"
-msgstr ""
+msgstr "Editar status"
msgid "SetStatusModal|Remove status"
-msgstr ""
+msgstr "Remover status"
msgid "SetStatusModal|Set a status"
-msgstr ""
+msgstr "Definir um status"
msgid "SetStatusModal|Set status"
-msgstr ""
+msgstr "Definir status"
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
-msgstr ""
+msgstr "Desculpe, nós não fomos capazes de definir o seu status. Por favor, tente novamente mais tarde."
msgid "SetStatusModal|What's your status?"
-msgstr ""
+msgstr "Qual é o seu status?"
msgid "Settings"
msgstr "Configurações"
@@ -7396,12 +8611,12 @@ msgstr "Exibir comando"
msgid "Show complete raw log"
msgstr "Visualizar raw log completo"
+msgid "Show file browser"
+msgstr ""
+
msgid "Show latest version"
msgstr "Mostrar a versão mais recente"
-msgid "Show latest version of the diff"
-msgstr "Mostrar a versão mais recente do diff"
-
msgid "Show parent pages"
msgstr "Mostrar páginas acima"
@@ -7437,12 +8652,21 @@ msgstr "Entrar"
msgid "Sign in / Register"
msgstr "Entrar / Criar conta"
-msgid "Sign in to %{group_name}"
-msgstr "Entre em %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
msgid "Sign in with Single Sign-On"
msgstr "Entre com logon único"
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr "Sair"
@@ -7452,6 +8676,9 @@ msgstr "Restrições de login"
msgid "Sign-up restrictions"
msgstr "Restrições de cadastro"
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr "Tamanho"
@@ -7468,14 +8695,23 @@ msgid "Slower but makes sure the project workspace is pristine as it clones the
msgstr "Mais lento, mas certifica-se que o espaço de trabalho do projeto está íntegro enquanto clona o repositório do zero para cada tarefa"
msgid "Smartcard"
-msgstr ""
+msgstr "Cartão inteligente"
msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr "A autenticação do cartão inteligente falhou: o cabeçalho do certificado do cliente está faltando."
+
+msgid "Snippet Contents"
msgstr ""
msgid "Snippets"
msgstr "Snippets"
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr "Algo deu errado do nosso lado"
@@ -7485,29 +8721,38 @@ msgstr "Algo deu errado do nosso lado."
msgid "Something went wrong on our end. Please try again!"
msgstr "Algo deu errado no nosso lado. Por favor, tente novamente!"
-msgid "Something went wrong trying to change the confidentiality of this issue"
+msgid "Something went wrong on our end. Please try again."
msgstr ""
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr "Ocorreu um erro ao tentar alterar a confidencialidade desta issue"
+
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
-msgstr ""
+msgstr "Algo deu errado ao tentar mudar o estado de bloqueio desse %{issuableDisplayName}"
msgid "Something went wrong when toggling the button"
msgstr "Algo deu errado ao alternar o botão"
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "Algo deu errado ao fechar o %{issuable}. Por favor, tente novamente depois"
-msgid "Something went wrong while fetching %{listType} list"
+msgid "Something went wrong while deleting the source branch. Please try again."
msgstr ""
+msgid "Something went wrong while fetching %{listType} list"
+msgstr "Algo deu errado ao recuperar a lista de %{listType}"
+
msgid "Something went wrong while fetching comments. Please try again."
-msgstr ""
+msgstr "Algo deu errado ao buscar os comentários. Por favor, tente novamente."
msgid "Something went wrong while fetching group member contributions"
msgstr "Algo deu errado ao obter as contribuições de membro do grupo"
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
-msgstr ""
+msgstr "Algo deu errado ao buscar os ambientes para esse merge request. Por favor, tente novamente."
msgid "Something went wrong while fetching the projects."
msgstr "Algo deu errado ao recuperar os projetos."
@@ -7515,6 +8760,9 @@ msgstr "Algo deu errado ao recuperar os projetos."
msgid "Something went wrong while fetching the registry list."
msgstr "Algo deu errado ao recuperar a lista de registro."
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr "Alguma coisa deu errado ao reabrir o %{issuable}. Por favor, tente novamente depois"
@@ -7522,13 +8770,13 @@ msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "Algo deu errado ao resolver essa discussão. Por favor, tente novamente."
msgid "Something went wrong, unable to add %{project} to dashboard"
-msgstr ""
+msgstr "Algo deu errado, incapaz de adicionar %{project} ao dashboard"
msgid "Something went wrong, unable to get operations projects"
-msgstr ""
+msgstr "Algo deu errado, não é possível obter os projetos de operações"
msgid "Something went wrong, unable to remove project"
-msgstr ""
+msgstr "Algo deu errado, não é possível remover o projeto"
msgid "Something went wrong. Please try again."
msgstr "Algo deu errado. Por favor, tente novamente."
@@ -7537,11 +8785,17 @@ msgid "Sorry, no epics matched your search"
msgstr "Desculpe, nenhum épico corresponde à sua pesquisa"
msgid "Sorry, no projects matched your search"
+msgstr "Desculpe, nenhum projeto corresponde à sua pesquisa"
+
+msgid "Sorry, your filter produced no results"
msgstr ""
msgid "Sort by"
msgstr "Ordenar por"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr "Nível de acesso, ascendente"
@@ -7570,7 +8824,7 @@ msgid "SortOptions|Largest repository"
msgstr "Maior repositório"
msgid "SortOptions|Last Contact"
-msgstr ""
+msgstr "Último contato"
msgid "SortOptions|Last created"
msgstr "Últimos criados"
@@ -7587,14 +8841,14 @@ msgstr "Menos populares"
msgid "SortOptions|Less weight"
msgstr "Menos peso"
-msgid "SortOptions|Milestone"
-msgstr "Milestone"
+msgid "SortOptions|Milestone due date"
+msgstr ""
msgid "SortOptions|Milestone due later"
-msgstr "Milestone de fim mais longo"
+msgstr "Marco de fim mais longo"
msgid "SortOptions|Milestone due soon"
-msgstr "Milestone de fim mais próximo"
+msgstr "Marco de fim mais próximo"
msgid "SortOptions|More weight"
msgstr "Mais peso"
@@ -7620,6 +8874,9 @@ msgstr "Criação mais antiga"
msgid "SortOptions|Oldest joined"
msgstr "Primeiros associados"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr "Assinados mais antigos"
@@ -7632,6 +8889,9 @@ msgstr "Popularidade"
msgid "SortOptions|Priority"
msgstr "Prioridade"
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr "Assinados mais novos"
@@ -7659,6 +8919,9 @@ msgstr "Código-fonte"
msgid "Source is not available"
msgstr "Origem não está disponível"
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr "Logs de spam"
@@ -7669,11 +8932,14 @@ msgid "Specific Runners"
msgstr "Runners Específicos"
msgid "Specify an e-mail address regex pattern to identify default internal users."
-msgstr ""
+msgstr "Especifique um padrão regex de endereço de e-mail para identificar usuários internos padrão."
msgid "Specify the following URL during the Runner setup:"
msgstr "Especifique o seguinte URL durante a configuração do Runner:"
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr "Squash commits"
@@ -7710,27 +8976,54 @@ msgstr "Atividade dos projetos favoritos"
msgid "Starred projects"
msgstr "Projetos favoritos"
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar um %{new_merge_request} a partir dessas alterações"
msgid "Start a review"
-msgstr ""
+msgstr "Iniciar uma revisão"
msgid "Start and due date"
+msgstr "Data de início e término"
+
+msgid "Start cleanup"
msgstr ""
msgid "Start date"
msgstr "Data de início"
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Inicie o Runner!"
msgid "Start your trial"
-msgstr ""
+msgstr "Iniciar sua avaliação"
msgid "Started"
msgstr "Iniciado"
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "Começa em (UTC)"
@@ -7740,9 +9033,15 @@ msgstr "Regitre sua mensagem para ativar"
msgid "Status"
msgstr "Status"
-msgid "Stop environment"
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
msgstr ""
+msgid "Stop environment"
+msgstr "Parar o ambiente"
+
msgid "Stop impersonation"
msgstr "Parar representação"
@@ -7753,6 +9052,9 @@ msgid "Stopped"
msgstr "Parado"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr "Não é possível parar esse ambiente no momento pois um deploy está em andamento"
+
+msgid "Stopping..."
msgstr ""
msgid "Storage"
@@ -7770,9 +9072,12 @@ msgstr "Subgrupos e projetos"
msgid "Submit as spam"
msgstr "Enviar como spam"
-msgid "Submit review"
+msgid "Submit feedback"
msgstr ""
+msgid "Submit review"
+msgstr "Enviar análise"
+
msgid "Submit search"
msgstr "Buscar"
@@ -7785,10 +9090,94 @@ msgstr "Inscrever-se no nível de grupo"
msgid "Subscribe at project level"
msgstr "Inscrever-se no nível do projeto"
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr "Inscrito"
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,19 +9192,23 @@ msgstr "Hooks do sistema"
msgid "System Info"
msgstr "Informações do Sistema"
-msgid "System header and footer:"
-msgstr "Cabeçalho e rodapé de sistema:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
msgid "System metrics (Custom)"
msgstr "Métricas de sistema (Personalizado)"
msgid "System metrics (Kubernetes)"
+msgstr "Métricas do sistema (Kubernetes)"
+
+msgid "Tag"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] "Tag (%{tag_count})"
-msgstr[1] "Tags (%{tag_count})"
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "Tags"
@@ -7910,6 +9303,12 @@ msgstr "Modelo"
msgid "Templates"
msgstr "Modelos"
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Contrato de Termos de Serviço e Política de Privacidade"
@@ -7917,7 +9316,7 @@ msgid "Terms of Service and Privacy Policy"
msgstr "Termos de Serviço e Política de Privacidade"
msgid "Test SAML SSO"
-msgstr ""
+msgstr "Teste de SSO SAML"
msgid "Test coverage parsing"
msgstr "Análise de cobertura de teste"
@@ -7925,23 +9324,29 @@ msgstr "Análise de cobertura de teste"
msgid "Thanks! Don't show me this again"
msgstr "Obrigado! Não me mostre isso novamente"
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global 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 "O Advanced Global Search no GitLab é um poderoso serviço de pesquisa que economiza seu tempo. Em vez de criar código duplicado e perder tempo, você pode agora procurar código dentro de outras equipes que podem ajudar seu próprio projeto."
-msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
msgstr ""
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr "Os objetos LFS do Git <strong>não</strong> serão sincronizados."
+
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
-msgstr "Issue Tracker é o lugar para adicionar coisas que precisam ser melhoradas ou resolvidas em um projeto"
+msgstr "O Rastreador de Issue é o lugar para adicionar coisas que precisam ser melhoradas ou resolvidas em um projeto"
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 "Issue Tracker é o lugar para adicionar coisas que precisam ser melhoradas ou resolvidas em um projeto. Você precisa se registrar ou fazer login para criar alguma Issue para este projeto."
+msgstr "O Rastreador de Issue é o lugar para adicionar coisas que precisam ser melhoradas ou resolvidas em um projeto. Você pode se registrar ou entrar para criar issues para este projeto."
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "O Certificado X509 a ser usado quando o TLS mútuo é necessário para se comunicar com o serviço de autorização externa. Se deixado em branco, o certificado do servidor ainda será validado ao acessar por HTTPS."
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 "O realçador de caracteres ajuda a manter a linha de assunto com %{titleLength} caracteres e quebra a linha do corpo em %{bodyLength} para que sejam legíveis no git."
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr "A etapa de codificação mostra o tempo desde a entrega do primeiro commit até a criação do merge request. Os dados serão automaticamente adicionados aqui desde o momento de criação do merge request."
@@ -7953,7 +9358,7 @@ msgid "The connection will time out after %{timeout}. For repositories that take
msgstr "A conexão expirará após %{timeout}. Para repositórios que demoram mais tempo, use a combinação clone/push."
msgid "The deployment of this job to %{environmentLink} did not succeed."
-msgstr ""
+msgstr "O deploy desta tarefa para o ambiente %{environmentLink} foi mal sucedida."
msgid "The fork relationship has been removed."
msgstr "O relacionamento como fork foi removido."
@@ -7962,7 +9367,10 @@ msgid "The import will time out after %{timeout}. For repositories that take lon
msgstr "A importação expirará após %{timeout}. Para repositórios que demoram mais tempo, use a combinação clone/push."
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
-msgstr "A etapa de planejamento mostra o tempo que se leva desde a criação de uma issue até sua atribuição à um milestone, ou sua adição a uma lista no seu painel. Comece a criar issues para ver dados para esta etapa."
+msgstr "A etapa de planejamento mostra o tempo que se leva desde a criação de uma issue até sua atribuição à um marco, ou sua adição a uma lista no seu painel. Comece a criar issues para ver dados para esta etapa."
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr "O tamanho máximo do arquivo é de 200KB."
@@ -7977,7 +9385,7 @@ msgid "The phase of the development lifecycle."
msgstr "A fase do ciclo de vida do desenvolvimento."
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 "Os agendamentos de pipelines rodam pipelines no futuro, de forma repetida, para branchs ou tags específicas. Esses agendamentos de pipeline terão acesso limitado com base no seu usuário associado."
msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "A etapa de planejamento mostra o tempo do passo anterior até a publicação de seu primeiro conjunto de mudanças. Este tempo será adicionado automaticamente assim que você enviar seu primeiro conjunto de mudanças."
@@ -7995,7 +9403,7 @@ msgid "The project can be accessed without any authentication."
msgstr "O projeto pode ser acessado sem a necessidade de autenticação."
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "A coleção de dados pseudonymizer está desativada. Quando ativada, o GitLab executará um trabalho em segundo plano que produzirá CSVs com pseudônimos do banco de dados do GitLab que serão carregados no diretório de armazenamento de objetos configurado."
+msgstr "A coleção de dados pseudonymizer está desativada. Quando ativada, o GitLab executará uma tarefa em segundo plano que produzirá CSVs com pseudônimos do banco de dados do GitLab que serão carregados no diretório de armazenamento de objetos configurado."
msgid "The repository for this project does not exist."
msgstr "Não existe repositório para este projeto."
@@ -8028,10 +9436,10 @@ msgid "The time taken by each data entry gathered by that stage."
msgstr "O tempo necessário por cada entrada de dados reunida por essa etapa."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr ""
+msgstr "A ação de atualização irá expirar depois de %{number_of_minutes} minutos. Para grandes repositórios, use uma combinação de clone/push."
msgid "The usage ping is disabled, and cannot be configured through this form."
-msgstr ""
+msgstr "Os dados de uso estão desabilitados, e não podem ser configurados por meio deste formulário."
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr "O mapa do usuário é um documento JSON que mapeia os usuários do Google Code que participaram de seus projetos para a maneira como seus endereços de e-mail e nomes de usuários são importados para o GitLab. Você pode mudar isso alterando o valor no lado direito de <code>:</code>. Certifique-se de preservar as aspas duplas adjacentes, outros sinais de pontuação e o endereço de e-mail ou nome de usuário no lado esquerdo."
@@ -8042,32 +9450,50 @@ msgstr "O mapa do usuário é um mapeamento dos usuários do FogBugz que partici
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "O valor situado no ponto médio de uma série de valores observados. Ex., entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Ainda não há projetos arquivados"
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr "Não há issues para mostrar"
msgid "There are no labels yet"
msgstr "Ainda não há etiquetas"
-msgid "There are no merge requests to show"
-msgstr "Não há merge requests pra mostrar"
+msgid "There are no open issues"
+msgstr ""
-msgid "There are no projects shared with this group yet"
+msgid "There are no open merge requests"
msgstr ""
-msgid "There are no staged changes"
+msgid "There are no packages yet"
msgstr ""
+msgid "There are no projects shared with this group yet"
+msgstr "Não há projetos compartilhados com esse grupo ainda"
+
+msgid "There are no staged changes"
+msgstr "Não há mudanças na lista para commit"
+
msgid "There are no unstaged changes"
-msgstr ""
+msgstr "Não há mudanças fora da lista para commit"
msgid "There was an error adding a todo."
-msgstr ""
+msgstr "Houve um erro ao adicionar uma tarefa."
msgid "There was an error deleting the todo."
-msgstr ""
+msgstr "Houve um erro ao excluir a tarefa."
msgid "There was an error loading users activity calendar."
msgstr "Erro ao carregar calendário de atividades."
@@ -8087,12 +9513,21 @@ msgstr "Erro ao se inscrever nessa etiqueta."
msgid "There was an error when unsubscribing from this label."
msgstr "Erro ao se anular a inscrição dessa etiqueta."
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr "Eles podem ser gerenciados usando o %{link}."
msgid "Third party offers"
msgstr "Ofertas de terceiros"
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "Esta instância do GitLab ainda não fornece nenhum Runner compartilhado. Os administradores da instância podem registrar os Runners compartilhados na área de administração."
@@ -8106,29 +9541,32 @@ msgid "This board's scope is reduced"
msgstr "O escopo deste painel está reduzido"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
-msgstr ""
+msgstr "Esse branch mudou desde quando você começou sua edição. Você quer criar um novo branch?"
msgid "This container registry has been scheduled for deletion."
-msgstr ""
+msgstr "Esse container registry foi agendado para exclusão."
msgid "This date is after the due date, so this epic won't appear in the roadmap."
-msgstr ""
+msgstr "Essa data é posterior à data de vencimento, portanto, esse épico não será exibido no planejamento."
msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr ""
+msgstr "Esta data é anterior a data de início, portanto este epic não aparecerá no planejamento."
msgid "This diff is collapsed."
msgstr "Esse diff está recolhido."
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr "Esse diretório"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
msgid "This group"
msgstr "Esse grupo"
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr "Este grupo permite que você entre com sua conta de logon único de %{group_name}. Isso irá redirecioná-lo para uma página de login externa."
-
msgid "This group does not provide any group Runners yet."
msgstr "Este grupo não fornece nenhum grupo de Runners ainda."
@@ -8136,7 +9574,7 @@ msgid "This is a confidential issue."
msgstr "Essa issue é confidencial."
msgid "This is a delayed job to run in %{remainingTime}"
-msgstr ""
+msgstr "Esta tarefa foi atrasada para executar em %{remainingTime}"
msgid "This is the author's first Merge Request to this project."
msgstr "Esse é o autor do primeiro merge request desse projeto."
@@ -8160,48 +9598,48 @@ msgid "This job does not have a trace."
msgstr "Esta tarefa não possui um traço."
msgid "This job has been canceled"
-msgstr "Esta etapa foi cancelada"
+msgstr "Esta tarefa foi cancelada"
msgid "This job has been skipped"
msgstr "Este trabalho foi pulado"
msgid "This job has not been triggered yet"
-msgstr "Esta build ainda não foi acionada"
+msgstr "Esta tarefa ainda não foi acionada"
msgid "This job has not started yet"
-msgstr "Esse processo ainda não começou"
+msgstr "Essa tarefa ainda não começou"
msgid "This job is an out-of-date deployment to %{environmentLink}."
-msgstr ""
+msgstr "Esta tarefa é um deploy desatualizado para o ambiente %{environmentLink}."
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
-msgstr ""
+msgstr "Esta tarefa é um deploy desatualizado para o ambiente %{environmentLink}. Confira os deploys mais recentes %{deploymentLink}."
msgid "This job is archived. Only the complete pipeline can be retried."
-msgstr ""
+msgstr "Esta tarefa foi arquivada. Apenas um pipeline completo pode ser repetido."
msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "Esta tarefa está criando um deploy para %{environmentLink} e substituirá o %{deploymentLink}."
msgid "This job is creating a deployment to %{environmentLink}."
-msgstr ""
+msgstr "Esta tarefa está criando um deploy para %{environmentLink}."
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "Esta tarefa está em estado pendente e está esperando para ser escolhido por um runner"
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
-msgstr ""
+msgstr "Essa tarefa é o deploy mais recente para %{link}."
msgid "This job requires a manual action"
-msgstr "Este Job exige uma ação manual"
+msgstr "Essa tarefa exige uma ação manual"
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8211,7 +9649,7 @@ msgid "This merge request is locked."
msgstr "Esse merge request está bloqueado."
msgid "This option is disabled as you don't have write permissions for the current branch"
-msgstr ""
+msgstr "Esta opção está desativada porque você não tem permissões de escrita para o branch atual"
msgid "This option is disabled while you still have unstaged changes"
msgstr "Esta opção ficará desativada enquanto você ainda tiver alterações fora da lista para commit"
@@ -8222,6 +9660,15 @@ msgstr "Esta página não está disponível porque você não tem permissão par
msgid "This page will be removed in a future release."
msgstr "Esta página será removida em uma versão futura."
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr "Esse projeto"
@@ -8229,40 +9676,40 @@ msgid "This project does not belong to a group and can therefore not make use of
msgstr "Este projeto não pertence a um grupo e, portanto, não pode usar os Runners do grupo."
msgid "This project does not have a wiki homepage yet"
-msgstr ""
+msgstr "Este projeto ainda não tem uma página inicial na wiki"
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
+msgstr "Este projeto não possui faturamento ativado. Para criar um cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">ative o faturamento <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> e tente novamente."
msgid "This repository"
msgstr "Esse repositório"
msgid "This runner will only run on pipelines triggered on protected branches"
-msgstr ""
+msgstr "Este Runner somente será executado em Pipelines acionados em branches protegidos"
msgid "This setting can be overridden in each project."
-msgstr ""
+msgstr "Essa configuração pode ser substituída em cada projeto."
msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
-msgstr ""
+msgstr "Essa configuração atualizará o hostname usado para gerar e-mails de commit privados. %{learn_more}"
msgid "This source diff could not be displayed because it is too large."
msgstr "Esse diff de origem não pôde ser exibido porque é muito grande."
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
msgstr "Esse usuário não tem identidades"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
-msgstr ""
+msgstr "Esse usuário será o autor de todos os eventos no feed de atividades que são o resultado de uma atualização, como novos branches sendo criados ou novos commits sendo enviados para os branches existentes."
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
-msgstr ""
+msgstr "Esse usuário será o autor de todos os eventos no feed de atividades que são o resultado de uma atualização, como novos branches sendo criados ou novos commits sendo enviados para os branches existentes. Na criação ou na redistribuição, você só pode se atribuir para ser o usuário espelho."
-msgid "This will delete the custom metric, Are you sure?"
-msgstr "Isso vai excluir a métrica personalizada. Você tem certeza?"
+msgid "This will redirect you to an external sign in page."
+msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "Esses e-mails se tornam automaticamente issues (com os comentários se tornando a conversa por e-mail) listados aqui."
@@ -8274,13 +9721,13 @@ msgid "Time before an issue starts implementation"
msgstr "Tempo até que uma issue comece a ser implementado"
msgid "Time before enforced"
-msgstr ""
+msgstr "Tempo antes de reforço"
msgid "Time between merge request creation and merge/close"
msgstr "Tempo entre a criação da solicitação de incorporação e a aceitação/fechamento"
msgid "Time estimate"
-msgstr ""
+msgstr "Estimativa de tempo"
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "Tempo em segundos o GitLab aguardará uma resposta do serviço externo. Quando o serviço não responder a tempo, o acesso será negado."
@@ -8454,9 +9901,18 @@ msgstr "Dica:"
msgid "Title"
msgstr "Título"
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr "Para o GitLab"
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "Para adicionar uma chave SSH, você precisa %{generate_link_start}gerar uma%{link_end} ou usar uma %{existing_link_start}chave existente%{link_end}."
@@ -8470,22 +9926,22 @@ msgid "To connect an SVN repository, check out %{svn_link}."
msgstr "Para conectar um repositório SVN, confira %{svn_link}."
msgid "To define internal users, first enable new users set to external"
-msgstr ""
+msgstr "Para definir usuários internos, primeiro ative os novos usuários definidos como externos"
msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
+msgstr "Para habilitá-lo e ver coortes de usuários, visite %{application_settings_link_start}configurações do aplicativo%{application_settings_link_end}."
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 "Para começar, insira seu URL do FogBugz e as informações de login abaixo. Nas próximas etapas, você poderá associar usuários e selecionar os projetos que deseja importar."
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
+msgstr "Para começar, vincule essa página ao seu servidor do Jaeger, ou descubra como %{link_start_tag}instalar o Jaeger%{link_end_tag}"
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Para começar, insira seu URL de Host do Gitea e um %{link_to_personal_token}."
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
-msgstr ""
+msgstr "Para ajudar a melhorar o GitLab e sua experiência de usuário, o GitLab coletará periodicamente informações de uso."
msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
msgstr "Para ajudar a melhorar o GitLab, gostaríamos de coletar periodicamente informações de uso. Isso pode ser alterado a qualquer momento em %{settings_link_start}Configurações%{link_end}. %{info_link_start}Mais informações%{link_end}"
@@ -8499,13 +9955,28 @@ msgstr "Para importar repositórios do GitHub, primeiro você precisa autorizar
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "Para importar um repositório SVN, confira %{svn_link}."
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr "Para mover ou copiar todo um projeto do GitLab de outra instalação do GitLab para esta, navegue até a página de configurações do projeto original, gere um arquivo de exportação e envie ele aqui."
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "Para usar apenas recursos CI/CD para um repositório externo, escolha <strong>CI/CD para repo externo</strong>."
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr "Para configurar a autenticação SAML para o seu grupo por meio de um pr
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Para começar a servir suas tarefas, você pode adicionar Runners ao seu grupo"
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr "Para esta instância do GitLab"
@@ -8521,6 +9995,9 @@ msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' in
msgstr "Para validar suas configurações de CI do GitLab, vá para 'CI/CD → Pipelines' dentro do seu projeto e clique no botão 'CI Lint'."
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr "Para visualizar o planejamento, adicione uma data de início ou fim para um de seus épicos nesse grupo ou seus subgrupos. No visualizador de meses, apenas épicos do mês passado, mês atual, e dos próximos 5 meses são exibidos."
+
+msgid "To widen your search, change or remove filters above"
msgstr ""
msgid "To widen your search, change or remove filters."
@@ -8538,15 +10015,18 @@ msgstr "Afazeres"
msgid "Toggle Sidebar"
msgstr "Alternar barra lateral"
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
+msgstr "Alternar descrição de commit"
+
+msgid "Toggle commit list"
msgstr ""
msgid "Toggle discussion"
msgstr "Alternar discussão"
-msgid "Toggle file browser"
-msgstr ""
-
msgid "Toggle navigation"
msgstr "Alternar navegação"
@@ -8581,45 +10061,54 @@ msgid "Total: %{total}"
msgstr "Total: %{total}"
msgid "Tracing"
-msgstr ""
+msgstr "Rastreamento"
msgid "Track activity with Contribution Analytics."
msgstr "Acompanhe atividades com a Análise de Contribuições."
msgid "Track groups of issues that share a theme, across projects and milestones"
-msgstr "Acompanhe grupos de issues que compartilhem um tema, em projetos e milestones"
+msgstr "Acompanhe grupos de issues que compartilhem um tema, em projetos e marcos"
msgid "Track time with quick actions"
msgstr "Acompanhe o tempo com ações rápidas"
msgid "Tree view"
-msgstr ""
+msgstr "Visão em árvore"
msgid "Trending"
msgstr "Mais populares"
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
-msgstr ""
+msgstr "Pipelines de disparo para atualizações de espelho"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
-msgstr ""
+msgstr "Ative os pipelines quando os branches ou tags forem atualizados a partir do repositório upstream. Dependendo da atividade do repositório upstream, isso pode aumentar bastante a carga nos seus runners de CI. Ative isso somente se você sabe que eles podem manipular a carga."
msgid "Trigger this manual action"
msgstr "Acionar esta ação manual"
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "Os gatilhos podem forçar uma build numa branch ou tag específica através da API. Esses tokens representarão seu usuário associado, incluindo seu acesso a projetos e suas permissões de projeto."
msgid "Troubleshoot and monitor your application with tracing"
-msgstr ""
+msgstr "Solucionar problemas e monitorar sua aplicação com rastreamento"
msgid "Try again"
msgstr "Tente novamente"
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
+msgstr "Use tudo que o GitLab tem para oferecer por 30 dias."
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
msgid "Turn on Service Desk"
@@ -8629,26 +10118,32 @@ msgid "Twitter"
msgstr "Twitter"
msgid "Two-factor authentication"
-msgstr ""
+msgstr "Autenticação de dois fatores"
msgid "Type"
msgstr "Tipo"
+msgid "URL"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Não é possível carregar o diff. %{button_try_again}"
-msgid "Unable to save your changes"
-msgstr ""
-
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Não é possível inscrever você no grupo com SAML devido a \"%{reason}\""
msgid "Unable to update this epic at this time."
+msgstr "Não é possível atualizar este épico neste momento."
+
+msgid "Unblock"
msgstr ""
msgid "Undo"
msgstr "Desfazer"
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr "Desconhecido"
@@ -8656,7 +10151,7 @@ msgid "Unlock"
msgstr "Desbloquear"
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr ""
+msgstr "Desbloquear este %{issuableDisplayName}? <strong>Todos</strong> poderão comentar."
msgid "Unlocked"
msgstr "Desbloqueado"
@@ -8665,10 +10160,10 @@ msgid "Unresolve discussion"
msgstr "Reabrir discussão"
msgid "Unschedule job"
-msgstr ""
+msgstr "Desprogramar tarefa"
msgid "Unstage"
-msgstr ""
+msgstr "Retirar da lista para commit"
msgid "Unstage all changes"
msgstr "Retirar tudo da lista para commit"
@@ -8697,6 +10192,9 @@ msgstr "Cancelar inscrição no nível do grupo"
msgid "Unsubscribe at project level"
msgstr "Cancelar inscrição no nível do projeto"
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr "Não verificado"
@@ -8709,15 +10207,21 @@ msgstr "Em breve"
msgid "Update"
msgstr "Atualizar"
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr "Atualizar agora"
msgid "Update your group name, description, avatar, and visibility."
-msgstr ""
+msgstr "Atualize o nome do seu grupo, descrição, avatar e visibilidade."
msgid "Updating"
msgstr "Atualizando"
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "Aprimore seu plano para ativar a Pesquisa Global Avançada."
@@ -8736,20 +10240,35 @@ msgstr "Faça upgrade de plano para melhorar os painéis."
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr "Envie o <code>GoogleCodeProjectHosting.json</code> aqui:"
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "Enviar Novo Arquivo"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "Enviar arquivo"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "clique para fazer upload"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr "Votos positivos"
msgid "Usage ping is not enabled"
-msgstr ""
+msgstr "Dados de uso não está habilitado"
msgid "Usage statistics"
msgstr "Estatísticas de uso"
@@ -8761,7 +10280,7 @@ msgid "Use Service Desk to connect with your users (e.g. to offer customer suppo
msgstr "Use o Balcão de Atendimento para se conectar com seus usuários (por exemplo, para oferecer suporte ao cliente) por email dentro do GitLab"
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
-msgstr "Use milestones de grupo para gerenciar problemas de vários projetos no mesmo milestone."
+msgstr "Use marcos de grupo para gerenciar issues de vários projetos no mesmo marco."
msgid "Use one line per URI"
msgstr "Use uma linha por URI"
@@ -8775,12 +10294,18 @@ msgstr "Use o seguinte token de registro durante a configuração:"
msgid "Use your global notification setting"
msgstr "Utilizar configuração de notificação global"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Utilizado pelos membros para entrar em seu grupo no GitLab"
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgid "Used to help configure your identity provider"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr "GrupoCoortes de usuário são mostradas somente quando os %{usage_ping_link_start}dados de uso%{usage_ping_link_end} são habilitados."
+
msgid "User Settings"
msgstr "Configurações do Usuário"
@@ -8791,58 +10316,94 @@ msgid "User map"
msgstr "Mapa do usuário"
msgid "UserProfile|Activity"
-msgstr ""
+msgstr "Atividade"
msgid "UserProfile|Already reported for abuse"
-msgstr ""
+msgstr "Já denunciado por abuso"
msgid "UserProfile|Contributed projects"
-msgstr ""
+msgstr "Projetos contribuídos"
msgid "UserProfile|Edit profile"
msgstr "Editar perfil"
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr "Grupos"
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr "Atividade mais recente"
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
+msgid "UserProfile|Overview"
+msgstr "Visão geral"
+
msgid "UserProfile|Personal projects"
msgstr "Projetos pessoais"
-msgid "UserProfile|Recent contributions"
-msgstr "Contribuições recentes"
-
msgid "UserProfile|Report abuse"
msgstr "Denunciar abuso"
msgid "UserProfile|Snippets"
msgstr "Snippets"
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr "Inscrever-se"
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr "Este usuário tem um perfil privado"
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "Ver tudo"
msgid "UserProfile|View user in admin area"
msgstr "Exibir usuário na área administrativa"
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr "Usuários"
-msgid "Variables"
-msgstr "Variáveis"
+msgid "Users requesting access to"
+msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr "As variáveis ​​são aplicadas aos ambientes por meio do runner. Eles podem ser protegidos apenas expondo-os a branches protegidas ou tags. Você pode usar variáveis ​​para senhas, chaves secretas ou o que você quiser."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
msgid "Various container registry settings."
msgstr "Várias configurações de registry container."
@@ -8850,12 +10411,18 @@ msgstr "Várias configurações de registry container."
msgid "Various email settings."
msgstr "Várias configurações de email."
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr "Várias configurações que afetam o desempenho do GitLab."
msgid "Verification information"
msgstr "Informação de verificação"
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr "Verificado"
@@ -8866,6 +10433,12 @@ msgid "View %{alerts}"
msgstr "Visualizar %{alerts}"
msgid "View app"
+msgstr "Exibir aplicativo"
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
msgstr ""
msgid "View documentation"
@@ -8907,6 +10480,9 @@ msgstr "Ver arquivo substituído @ "
msgid "View the documentation"
msgstr "Ver a documentação"
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "Visibilidade e controles de acesso"
@@ -8931,11 +10507,17 @@ msgstr "Público"
msgid "VisibilityLevel|Unknown"
msgstr "Desconhecido"
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr "Classe"
msgid "Vulnerability|Confidence"
-msgstr ""
+msgstr "Confiança"
msgid "Vulnerability|Description"
msgstr "Descrição"
@@ -8944,38 +10526,59 @@ msgid "Vulnerability|File"
msgstr "Arquivo"
msgid "Vulnerability|Identifiers"
-msgstr ""
+msgstr "Identificadores"
msgid "Vulnerability|Instances"
-msgstr ""
+msgstr "Instâncias"
msgid "Vulnerability|Links"
-msgstr ""
+msgstr "Links"
msgid "Vulnerability|Project"
msgstr "Projeto"
+msgid "Vulnerability|Report Type"
+msgstr ""
+
msgid "Vulnerability|Severity"
msgstr "Gravidade"
-msgid "Vulnerability|Solution"
-msgstr "Solução"
-
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Precisa visualizar os dados? Solicite acesso ao administrador."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Detectamos spam potencial no %{humanized_resource_name}. Por favor, resolva o reCAPTCHA para continuar."
msgid "We don't have enough data to show this stage."
msgstr "Esta etapa não possui dados suficientes para exibição."
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Queremos ter certeza de que é você, confirme que você não é um robô."
msgid "Web IDE"
msgstr "IDE Web"
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr "Terminal Web"
@@ -9000,6 +10603,9 @@ msgstr "Quando ativado, os usuários não podem usar o GitLab até que os termos
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Ao deixar o URL em branco, a classificação das etiquetas ainda podem ser especificadas sem desativar os recursos do projeto ou executar verificações de autorização externas."
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr "Quem pode ver esse grupo?"
@@ -9121,7 +10727,7 @@ msgid "Wiki|Create page"
msgstr "Criar página"
msgid "Wiki|Edit Page"
-msgstr "Ediar página"
+msgstr "Editar página"
msgid "Wiki|More Pages"
msgstr "Mais páginas"
@@ -9141,12 +10747,21 @@ msgstr "Páginas"
msgid "Wiki|Wiki Pages"
msgstr "Páginas Wiki"
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr "Com a análise de contribuições, você pode ter uma visão geral da atividade de issues, solicitações de merge e eventos de push da sua organização e de seus membros."
msgid "Withdraw Access Request"
msgstr "Remover Requisição de Acesso"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr "Sim"
@@ -9159,6 +10774,9 @@ msgstr "Sim, deixe-me associar usuários do Google Code para nomes completos ou
msgid "Yesterday"
msgstr "Ontem"
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Você é um administrador, o que significa que conceder acesso a <strong>%{client_name}</strong> permitirá que eles também interajam com o GitLab como administrador. Prossiga com cuidado."
@@ -9177,6 +10795,9 @@ msgstr "Você irá transferir %{project_full_name} para outro proprietário. Tem
msgid "You are on a read-only GitLab instance."
msgstr "Você está em uma instância somente-leitura do GitLab."
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "Você pode %{linkStart}visualizar o blob%{linkEnd} em vez disso."
@@ -9201,14 +10822,17 @@ msgstr "Você somente pode adicionar arquivos quando estiver em um branch"
msgid "You can only edit files when you are on a branch"
msgstr "Você só pode editar arquivos quando estiver em um branch"
+msgid "You can only merge once the items above are resolved"
+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 "Você pode resolver o conflito de merge usando o modo Interativo, escolhendo os botões %{use_ours} ou %{use_theirs} ou editando os arquivos diretamente. Confirme essas alterações em %{branch_name}"
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr ""
+msgstr "Você pode configurar tarefas para só usar os runners com tags específicas. Separe tags com vírgulas."
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
-msgstr ""
+msgstr "Você pode testar o seu .gitlab-ci.yml no %{linkStart}CI Lint%{linkEnd}."
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "Você não pode escrever numa instância secundária de somente leitura do GitLab Geo. Por favor use %{link_to_primary_node} em vez disso."
@@ -9219,6 +10843,9 @@ msgstr "Você não pode escrever nesta instância somente-leitura do GitLab."
msgid "You do not have any subscriptions yet"
msgstr "Você ainda não tem nenhuma inscrição"
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "Você não tem as permissões corretas para substituir as configurações de sincronização do grupo LDAP."
@@ -9228,12 +10855,18 @@ msgstr "Você não tem nenhum aplicativo"
msgid "You don't have any authorized applications"
msgstr "Você não tem nenhum aplicativo autorizado"
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr "Você não tem permissão"
msgid "You have reached your project limit"
msgstr "Você atingiu o limite de seu projeto"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr "Você deve aceitar nossos Termos de Serviço e política de privacidade para registrar uma conta"
@@ -9243,16 +10876,22 @@ msgstr "Você deve ter o acesso de mantenedor para apagar um bloqueio"
msgid "You need a different license to enable FileLocks feature"
msgstr "Você precisa de uma licença diferente para ativar o recurso FileLocks"
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr "Você precisa do git-lfs na versão %{min_git_lfs_version} (ou maior) para continuar. Por favor, visite https://git-lfs.github.com"
msgid "You need permission."
msgstr "Você precisa de permissão."
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr "Você está recebendo este e-mail devido à sua conta no %{host}. %{mana
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr "Seus Grupos"
@@ -9309,12 +10951,18 @@ msgstr "Atividade dos seus projetos"
msgid "Your Todos"
msgstr "Seus lembretes"
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr "Seus aplicativos (%{size})"
msgid "Your authorized applications"
msgstr "Seus aplicativos autorizados"
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "Você pode fazer commit de suas alterações para %{branch_name} porque um merge request está aberto."
@@ -9327,12 +10975,24 @@ msgstr "Suas alterações foram salvas"
msgid "Your comment will not be visible to the public."
msgstr "Seu comentário não estará visível ao público."
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "Seus grupos"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "Seu nome"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr "Seus projetos"
@@ -9342,12 +11002,18 @@ msgstr "um usuário excluído"
msgid "ago"
msgstr "atrás"
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr "entre outras coisas"
msgid "assign yourself"
msgstr "atribuir a si mesmo"
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr "nome da branch"
@@ -9374,30 +11040,30 @@ msgstr "mais %{remainingPackagesCount}"
msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} detectado de %{fixedCount} vulnerabilidade corrigida"
+msgstr[1] "%{reportType} %{status} detectado de %{fixedCount} vulnerabilidades corrigidas"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} detectado de %{newCount} nova vulnerabilidade"
+msgstr[1] "%{reportType} %{status} detectado de %{newCount} novas vulnerabilidades"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} detectado de %{newCount} nova, e %{fixedCount} vulnerabilidades concertadas"
msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} detectou apenas %{newCount} vulnerabilidade para o branch de origem"
+msgstr[1] "%{reportType} %{status} detectou apenas %{newCount} vulnerabilidades para o branch de origem"
msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} não detectou novas vulnerabilidades"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} não detectou vulnerabilidades"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
-msgstr ""
+msgstr "%{reportType} %{status} não detectou vulnerabilidades para somente o branch origem"
msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
@@ -9411,7 +11077,7 @@ msgid "ciReport|%{reportType} is loading"
msgstr "%{reportType} está carregando"
msgid "ciReport|%{reportType}: Loading resulted in an error"
-msgstr ""
+msgstr "%{reportType}: Carregamento resultou em um erro"
msgid "ciReport|(errors when loading results)"
msgstr "(erros ao carregar resultados)"
@@ -9432,19 +11098,22 @@ msgid "ciReport|Confidence"
msgstr "Confiança"
msgid "ciReport|Container scanning"
-msgstr ""
+msgstr "Fazer scan no container"
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr "A varredura de contêiner detectou vulnerabilidades conhecidas em suas imagens docker."
msgid "ciReport|DAST"
+msgstr "DAST"
+
+msgid "ciReport|Dependency Scanning"
msgstr ""
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
-msgstr ""
+msgstr "A verificação de dependência detecta vulnerabilidades conhecidas nas dependências do seu código-fonte."
msgid "ciReport|Dependency scanning"
-msgstr ""
+msgstr "Verificação de dependência"
msgid "ciReport|Description"
msgstr "Descrição"
@@ -9455,6 +11124,12 @@ msgstr "Ignorar vulnerabilidade"
msgid "ciReport|Dismissed by"
msgstr "Ignorado por"
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr "O Teste de Segurança de Aplicativos Dinâmicos (DAST) detecta vulnerabilidades conhecidas em seu aplicativo da web."
@@ -9478,16 +11153,16 @@ msgstr "Saiba mais sobre como interagir com relatórios de segurança (Alpha)."
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "O gerenciamento de licenças detectou apenas %d licença para o branch de origem"
+msgstr[1] "O gerenciamento de licenças detectou apenas %d licenças para o branch de origem"
msgid "ciReport|License management detected %d new license"
msgid_plural "ciReport|License management detected %d new licenses"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "O gerenciamento de licenças detectou %d nova licença"
+msgstr[1] "O gerenciamento de licenças detectou %d novas licenças"
msgid "ciReport|License management detected no licenses for the source branch only"
-msgstr ""
+msgstr "O gerenciamento de licenças não detectou licenças para somente o branch de origem"
msgid "ciReport|License management detected no new licenses"
msgstr "Gerenciamento de licenças não detectou novas licenças"
@@ -9520,7 +11195,7 @@ msgid "ciReport|Revert dismissal"
msgstr "Reverter ignorar"
msgid "ciReport|SAST"
-msgstr ""
+msgstr "SAST"
msgid "ciReport|Security scanning"
msgstr "Verificação de segurança"
@@ -9575,11 +11250,14 @@ msgstr "na pipeline"
msgid "command line instructions"
msgstr "instruções da linha de comando"
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgid "commented on %{link_to_project}"
msgstr ""
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr "Você está prestes a desligar a confidencialidade. Isso significa que <strong>todos</strong> serão capazes de ver e deixar comentários nesse issue."
+
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
+msgstr "Você está prestes a ligar a confidencialidade. Isso significa que apenas membros da equipe com <strong>ao menos acesso de Relator</strong> serão capazes de ver e deixar comentários nesse issue."
msgid "connecting"
msgstr "conectando"
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] "dia"
msgstr[1] "dias"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr "token de deploy"
msgid "disabled"
msgstr "desabilitado"
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr "concluído"
@@ -9612,6 +11298,15 @@ msgstr[1] "rascunhos"
msgid "enabled"
msgstr "habilitado"
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} irá atualizar o tempo estimado com o último comando."
@@ -9621,25 +11316,43 @@ msgstr "para este projeto"
msgid "from"
msgstr "de"
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr "ajuda"
msgid "here"
msgstr "aqui"
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://seu-servidor-do-bitbucket"
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr "fluxo de importação"
msgid "importing"
msgstr "importando"
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "instâncias completas"
+msgstr[1] "instâncias completas"
msgid "is invalid because there is downstream lock"
msgstr "é inválido porque há bloqueio no recebimento de dados"
@@ -9650,12 +11363,30 @@ msgstr "é inválido porque há bloqueio no envio de dados"
msgid "is not a valid X509 certificate."
msgstr "não é um certificado X509 válido."
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr "painéis"
-msgid "latest deployment"
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
msgstr ""
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr "deploy mais recente"
+
msgid "latest version"
msgstr "versão mais recente"
@@ -9665,14 +11396,29 @@ msgstr "gerenciamento de licenças"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "bloqueador por %{path_lock_user_name} %{created_at}"
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "merge request"
msgstr[1] "merge requests"
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Por favor, restaurar ou usar um branch %{missingBranchName} diferente"
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr "%{metricsLinkStart} Memória %{metricsLinkEnd} uso %{emphasisStart} diminuição %{emphasisEnd} de %{memoryFrom}MB para %{memoryTo}MB"
@@ -9688,10 +11434,10 @@ msgstr "Adicionar aprovação"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Permite commits de membros que podem fazer merge ao branch de destino"
-msgid "mrWidget|An error occured while removing your approval."
-msgstr "Ocorreu um erro ao remover sua aprovação."
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr "Fecha"
msgid "mrWidget|Create an issue to resolve them later"
msgstr "Criar uma issue para resolvê-los mais tarde"
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Estatísticas de deploy não estão disponíveis atualmente"
@@ -9743,7 +11492,7 @@ msgid "mrWidget|Failed to load deployment statistics"
msgstr "Falha ao carregar estatísticas de deploy"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr ""
+msgstr "Merge fast-forward não é possível. Para fazer merge, primeiramente faça rebase local."
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "Se o branch %{branch} existir em seu repositório local, você poderá fazer o merge request manualmente usando o"
@@ -9785,7 +11534,7 @@ msgid "mrWidget|Open in Web IDE"
msgstr "Abrir na Web IDE"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
+msgstr "Pipeline bloqueada. A pipeline para este merge request requer uma ação manual para continuar"
msgid "mrWidget|Plain diff"
msgstr "Diff em texto"
@@ -9802,12 +11551,6 @@ msgstr "Atualizar agora"
msgid "mrWidget|Refreshing now"
msgstr "Atualizando agora"
-msgid "mrWidget|Remove Source Branch"
-msgstr "Remover branch de origem"
-
-msgid "mrWidget|Remove source branch"
-msgstr "Remover branch de origem"
-
msgid "mrWidget|Remove your approval"
msgstr "Remover sua aprovação"
@@ -9828,7 +11571,7 @@ msgid "mrWidget|Resolve conflicts"
msgstr "Resolver conflitos"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
+msgstr "Resolva estes conflitos ou peça a alguém com acesso de escrita para este repositório realizar o merge localmente"
msgid "mrWidget|Revert"
msgstr "Reverter"
@@ -9849,25 +11592,25 @@ msgid "mrWidget|The changes will be merged into"
msgstr "Será feito merge das alterações em"
msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr ""
+msgstr "A pipeline para este merge request falhou. Por favor, tente re-executar a tarefa ou faça push de um novo commit para corrigir a falha"
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
-msgstr ""
+msgstr "O HEAD do branch origem foi modificado recentemente. Por favor, recarregue a página e revise as alterações antes de realizar o merge"
-msgid "mrWidget|The source branch has been removed"
-msgstr "O branch de origem foi removido"
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
-msgstr ""
+msgstr "O branch origem está %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} do branch destino"
-msgid "mrWidget|The source branch is being removed"
-msgstr "O branch de origem está sendo removido"
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
-msgid "mrWidget|The source branch will be removed"
-msgstr "O branch de origem será removido"
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
-msgid "mrWidget|The source branch will not be removed"
-msgstr "O branch de origem não será removido"
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "Existem conflitos de merge"
@@ -9875,6 +11618,9 @@ msgstr "Existem conflitos de merge"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "Há discussões não resolvidas. Por favor, resolva estas discussões"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Falha ao realizar merge automaticamente"
@@ -9885,14 +11631,14 @@ msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Este projeto está arquivado, a escrita foi desativada"
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr "Você não tem permissão para editar este projeto diretamente. Por favor, faça fork no projeto para fazer alterações."
+
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "Você pode fazer merge manualmente usando o"
-msgid "mrWidget|You can remove source branch now"
-msgstr "Agora você pode remover o branch de origem"
-
msgid "mrWidget|branch does not exist."
msgstr "branch não existe."
@@ -9911,8 +11657,20 @@ msgstr "n/a"
msgid "new merge request"
msgstr "novo merge request"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
-msgstr "emails de notificação"
+msgstr "e-mails de notificação"
+
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
msgid "or"
msgstr "ou"
@@ -9933,6 +11691,9 @@ msgstr "senha"
msgid "personal access token"
msgstr "token de acesso pessoal"
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr "chave privada não corresponde ao certificado."
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] "projeto"
msgstr[1] "projetos"
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr "restante"
@@ -9953,27 +11720,57 @@ msgstr "remover a data de vencimento"
msgid "remove weight"
msgstr "remover peso"
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] "resposta"
msgstr[1] "respostas"
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr "origem"
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} irá atualizar a soma do tempo gasto."
msgid "started"
msgstr "iniciado"
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr "este documento"
msgid "to help your contributors communicate effectively!"
msgstr "para ajudar seus contribuintes à se comunicar de maneira eficaz!"
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr "nome do usuário"
msgid "uses Kubernetes clusters to deploy your code!"
msgstr "use clusters Kubernetes para deploy do seu código!"
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "ver no GitLab"
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "com %{additions} adições, %{deletions} remoções."
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] "dentro de %d minuto "
msgstr[1] "dentro de %d minutos "
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index c283bd4de93..1584a4159cc 100644
--- a/locale/pt_PT/gitlab.po
+++ b/locale/pt_PT/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:18\n"
+"PO-Revision-Date: 2019-02-11 08:08\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index 29f15fc9067..17805691aff 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ro\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:18\n"
+"PO-Revision-Date: 2019-02-11 08:07\n"
msgid " Status"
msgstr ""
@@ -33,20 +33,17 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -60,11 +57,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -90,6 +84,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -141,6 +141,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -162,12 +165,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -177,9 +186,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -189,6 +195,30 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -207,12 +237,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -291,10 +330,13 @@ msgstr[2] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -336,7 +378,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -384,6 +426,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -420,10 +465,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -435,7 +480,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -468,6 +516,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -477,6 +528,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -492,9 +546,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -528,12 +579,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -546,12 +627,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -564,6 +675,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -573,9 +687,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -597,6 +717,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -624,40 +747,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -666,6 +759,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -738,12 +834,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -774,9 +879,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -807,6 +957,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -819,6 +984,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -828,12 +996,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -849,6 +1029,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -867,6 +1050,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -876,6 +1062,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -903,6 +1092,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -915,6 +1107,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -930,6 +1125,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -957,15 +1155,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -999,13 +1188,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1191,6 +1392,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1200,12 +1407,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1359,21 +1560,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1410,12 +1626,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1425,18 +1635,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1449,12 +1668,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1476,10 +1704,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1491,9 +1719,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1515,6 +1749,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1533,6 +1773,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1626,7 +1869,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1647,6 +1890,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1686,28 +1935,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1731,27 +2004,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1761,6 +2049,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1773,6 +2064,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1800,6 +2094,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1872,6 +2175,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1887,6 +2196,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1923,6 +2238,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -2001,6 +2319,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2043,12 +2364,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2064,6 +2391,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2076,6 +2415,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2103,6 +2445,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2115,9 +2460,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2136,15 +2490,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2208,6 +2562,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2235,12 +2592,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2274,6 +2637,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2322,6 +2688,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2337,7 +2706,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2373,13 +2742,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2388,6 +2760,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2412,9 +2787,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2436,6 +2808,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2445,6 +2820,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2484,6 +2862,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2550,9 +2931,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2568,6 +2946,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2577,6 +2958,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2607,6 +2994,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2616,6 +3006,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2628,6 +3021,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2637,6 +3033,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2646,6 +3048,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2676,6 +3081,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2811,6 +3222,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2838,6 +3252,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2868,6 +3285,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2889,15 +3312,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2925,6 +3357,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2949,6 +3387,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2964,9 +3405,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2976,6 +3423,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2985,6 +3438,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -3003,6 +3459,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -3027,6 +3486,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3042,9 +3504,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3057,6 +3528,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3072,9 +3549,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3150,6 +3645,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3162,9 +3660,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3174,7 +3669,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3201,9 +3696,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3246,9 +3747,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3258,6 +3765,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3279,6 +3792,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3288,9 +3807,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3303,6 +3852,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3324,9 +3879,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3366,6 +3933,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3375,28 +3945,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3408,7 +3990,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3420,30 +4005,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3462,6 +4065,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3471,13 +4089,34 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3495,12 +4134,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3513,12 +4170,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3564,6 +4227,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3588,6 +4254,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3639,6 +4308,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3729,7 +4401,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3804,6 +4479,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3849,6 +4527,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3885,6 +4566,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3963,9 +4647,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3993,9 +4686,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4026,6 +4725,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4050,6 +4752,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4095,13 +4800,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4113,37 +4821,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4170,6 +4875,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4269,6 +4977,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4281,7 +4992,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4290,6 +5001,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4347,6 +5061,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4377,9 +5094,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4398,12 +5121,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4428,6 +5163,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4443,15 +5181,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4467,6 +5220,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4497,6 +5253,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4512,9 +5271,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4533,6 +5310,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4566,6 +5358,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4584,6 +5382,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4623,10 +5427,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4641,12 +5445,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4725,6 +5535,9 @@ msgstr[2] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4740,6 +5553,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4755,15 +5571,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4902,6 +5742,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4968,6 +5814,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4998,6 +5847,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -5034,9 +5886,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5058,13 +5907,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5073,9 +5925,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5088,19 +5949,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5118,6 +5991,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5127,6 +6018,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5145,7 +6039,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5154,6 +6048,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5163,7 +6063,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5175,22 +6075,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Query"
-msgstr ""
-
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5205,10 +6099,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5229,21 +6123,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5316,6 +6201,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5376,6 +6273,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5388,6 +6288,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5403,6 +6306,12 @@ msgstr[2] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5421,6 +6330,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5442,6 +6354,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5469,6 +6384,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5478,6 +6396,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5490,15 +6411,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5511,6 +6441,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5520,10 +6453,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5544,6 +6480,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5553,12 +6492,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5583,6 +6516,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5613,6 +6549,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5712,21 +6654,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5760,16 +6717,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5817,6 +6771,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5829,12 +6789,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5856,9 +6831,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5874,6 +6846,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6060,6 +7038,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6072,9 +7053,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6087,6 +7074,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6129,6 +7119,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6150,9 +7143,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6168,15 +7170,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6195,6 +7212,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6204,6 +7224,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6240,10 +7266,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6252,7 +7281,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6261,10 +7290,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6291,12 +7323,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6315,16 +7350,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6333,6 +7371,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6390,12 +7434,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6540,9 +7590,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6567,6 +7614,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6696,6 +7746,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6735,21 +7788,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6777,6 +7839,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6807,6 +7872,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6816,6 +7887,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6846,9 +7923,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6909,6 +7992,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6927,6 +8016,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6936,12 +8028,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6951,6 +8058,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6960,12 +8073,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6978,15 +8097,15 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -7014,6 +8133,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -7041,6 +8163,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7074,7 +8199,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7095,6 +8220,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7104,6 +8232,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7140,6 +8271,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7152,6 +8286,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7221,7 +8358,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7230,10 +8367,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7251,6 +8391,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7260,6 +8412,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7287,6 +8445,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7320,9 +8481,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7332,6 +8499,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7362,6 +8571,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7377,6 +8589,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7440,10 +8655,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7482,12 +8697,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7497,6 +8721,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7518,9 +8745,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7530,6 +8766,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7539,9 +8778,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7560,6 +8805,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7584,9 +8832,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7632,7 +8886,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7665,6 +8919,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7677,6 +8934,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7704,6 +8964,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7719,6 +8982,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7755,6 +9021,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7764,9 +9036,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7776,6 +9060,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7785,6 +9078,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7800,6 +9099,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7815,6 +9117,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7830,10 +9135,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7848,7 +9237,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7857,11 +9249,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7956,6 +9348,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7971,9 +9369,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -8010,6 +9414,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8088,16 +9495,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8133,12 +9558,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8166,13 +9600,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8235,10 +9672,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8247,7 +9684,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8268,6 +9705,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8295,7 +9741,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8307,7 +9753,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8502,9 +9948,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8547,13 +10002,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8562,6 +10032,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8571,6 +10044,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8586,13 +10062,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8646,9 +10125,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8658,6 +10134,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8667,9 +10149,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8682,10 +10170,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8694,9 +10182,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8745,6 +10239,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8757,6 +10254,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8766,6 +10266,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8784,15 +10287,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8823,9 +10341,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8850,19 +10374,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8871,25 +10404,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8898,12 +10458,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8916,6 +10482,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8955,6 +10527,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8979,6 +10554,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9003,27 +10584,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9048,6 +10650,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9189,12 +10794,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9207,6 +10821,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9225,6 +10842,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9249,6 +10869,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9267,6 +10890,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9276,12 +10902,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9291,16 +10923,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9342,6 +10980,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9357,12 +10998,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9375,12 +11022,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9390,12 +11049,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9492,6 +11157,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9507,6 +11175,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9630,6 +11304,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9651,12 +11328,21 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "done"
msgstr ""
@@ -9669,6 +11355,15 @@ msgstr[2] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9678,21 +11373,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9708,9 +11421,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9723,15 +11454,30 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9747,10 +11493,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9789,6 +11535,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9861,12 +11610,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9915,19 +11658,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9936,6 +11679,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9948,10 +11694,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9972,9 +11718,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9996,6 +11754,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -10005,6 +11766,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -10017,28 +11784,58 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -10047,9 +11844,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10059,3 +11862,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 379e0ce8324..b5db3291862 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -13,44 +13,39 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:18\n"
+"PO-Revision-Date: 2019-02-11 08:09\n"
msgid " Status"
-msgstr ""
+msgstr " СтатуÑ"
msgid " and"
-msgstr ""
+msgstr " и"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] " ухудшилоÑÑŒ на %d пункт"
+msgstr[1] " ухудшилоÑÑŒ на %d пунктов"
+msgstr[2] " ухудшилоÑÑŒ на %d пунктов"
+msgstr[3] " ухудшилоÑÑŒ на %d пунктов"
msgid " improved on %d point"
msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] " улучшилоÑÑŒ на %d пункт"
+msgstr[1] " улучшилоÑÑŒ на %d пункта"
+msgstr[2] " улучшилоÑÑŒ на %d пунктов"
+msgstr[3] " улучшилоÑÑŒ на %d пунктов"
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" в проектах"
msgid "%d commit"
msgid_plural "%d commits"
@@ -66,12 +61,8 @@ msgstr[1] "на %d коммита позади"
msgstr[2] "на %d коммитов позади"
msgstr[3] "на %d коммитов позади"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -82,17 +73,17 @@ msgstr[3] "%d ÑкÑпортеров"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d упавший теÑÑ‚"
+msgstr[1] "%d упавших теÑта"
+msgstr[2] "%d упавших теÑтов"
+msgstr[3] "%d упавших теÑтов"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d иÑправленный результат теÑта"
+msgstr[1] "%d иÑправленных результатов теÑта"
+msgstr[2] "%d иÑправленных результатов теÑта"
+msgstr[3] "%d иÑправленные результаты теÑта"
msgid "%d issue"
msgid_plural "%d issues"
@@ -101,6 +92,13 @@ msgstr[1] "%d обÑуждений"
msgstr[2] "%d обÑуждений"
msgstr[3] "%d обÑуждений"
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d Ñлой"
@@ -147,19 +145,22 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
msgid "%{authorsName}'s discussion"
-msgstr ""
+msgstr "ОбÑуждение %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} Ñоздан %{commit_timeago}"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
+msgstr "%{counter_storage} (%{counter_repositories} репозиториев, %{counter_build_artifacts} Ñборок артефактов, %{counter_lfs_objects} LFS)"
msgid "%{count} %{alerts}"
+msgstr "%{count} %{alerts}"
+
+msgid "%{count} more"
msgstr ""
msgid "%{count} more assignees"
-msgstr ""
+msgstr "Ещё %{count} иÑполнителей"
msgid "%{count} participant"
msgid_plural "%{count} participants"
@@ -170,34 +171,37 @@ msgstr[3] "%{count} учаÑтников"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{count} комментарий в ожидании"
+msgstr[1] "%{count} комментариев в ожидании"
+msgstr[2] "%{count} комментариев в ожидании"
+msgstr[3] "%{count} комментарии в ожидании"
msgid "%{filePath} deleted"
-msgstr ""
+msgstr "%{filePath} удален"
msgid "%{firstLabel} +%{labelCount} more"
+msgstr "%{firstLabel} + ещё %{labelCount}"
+
+msgid "%{firstOption} +%{extraOptionCount} more"
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType} будет удален! Вы уверены?"
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
msgid "%{loadingIcon} Started"
-msgstr "%{loadingIcon} Запущено"
+msgstr "%{loadingIcon} Запущена"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} заблокирован пользователем GitLab %{lock_user_id}"
msgid "%{name}'s avatar"
-msgstr ""
-
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} может иÑпользоватьÑÑ ÐºÐ°Ðº альтернатива пользовательÑкому домену."
+msgstr "Ðватар Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{name}"
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "на %{number_commits_behind} коммитов позади %{default_branch}, на %{number_commits_ahead} коммитов впереди"
@@ -208,13 +212,40 @@ msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% выполнено"
-msgid "%{text} %{files}"
-msgid_plural "%{text} %{files} files"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] "%{text} %{files}"
+msgstr[1] "%{text} %{files} файлах"
+msgstr[2] "%{text} %{files} файлов"
+msgstr[3] "%{text} %{files} файлах"
+
msgid "%{text} is available"
msgstr "%{text} доÑтупен"
@@ -227,12 +258,21 @@ msgstr "%{unstaged} не зафикÑированных и %{staged} зафикÑ
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
-msgid "+ %{count} more"
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
msgstr ""
+msgid "+ %{count} more"
+msgstr "+ ещё %{count}"
+
msgid "+ %{moreCount} more"
msgstr "+ ещё %{moreCount}"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr "- Runner активен и может обрабатывать любые новые заданиÑ"
@@ -272,17 +312,17 @@ msgstr[3] "%d закрытых запроÑов на ÑлиÑние"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "1 группа"
+msgstr[1] "%d групп"
+msgstr[2] "%d групп"
+msgstr[3] "%d групп"
msgid "1 merged merge request"
msgid_plural "%d merged merge requests"
-msgstr[0] "1 объединенный Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ðµ ÑлиÑние"
-msgstr[1] "%d объединенных запроÑов не ÑлиÑние"
-msgstr[2] "%d объединенных запроÑов не ÑлиÑние"
-msgstr[3] "%d объединенных запроÑов не ÑлиÑние"
+msgstr[0] "1 объединенный Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgstr[1] "%d объединенных запроÑов на ÑлиÑние"
+msgstr[2] "%d объединенных запроÑов на ÑлиÑние"
+msgstr[3] "%d объединенные запроÑов на ÑлиÑние"
msgid "1 open issue"
msgid_plural "%d open issues"
@@ -307,26 +347,29 @@ msgstr[3] "%d Ñборочных линий"
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "1 роль"
+msgstr[1] "%d ролей"
+msgstr[2] "%d ролей"
+msgstr[3] "%d ролей"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "1 пользователь"
+msgstr[1] "%d пользователей"
+msgstr[2] "%d пользователей"
+msgstr[3] "%d пользователей"
msgid "1st contribution!"
msgstr "Первый вклад!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°"
-msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "ПожалуйÑта ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ админиÑтратором GitLab Ñервера чтобы получить разрешение к данному реÑурÑу."
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
msgid "403|You don't have the permission to access this page."
msgstr "У Ð’Ð°Ñ Ð½ÐµÑ‚ права доÑтупа к Ñтой Ñтранице."
@@ -338,7 +381,7 @@ msgid "404|Page Not Found"
msgstr "Страница Ðе Ðайдена"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "ПожалуйÑта ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ админиÑтратором GitLab Ñервера, еÑли вы Ñчитаете данное поведение ошибкой."
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
msgstr ""
@@ -367,8 +410,8 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
-msgstr "<strong>УдалÑет</strong> иÑходную ветку"
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -377,13 +420,13 @@ msgid "A collection of graphs regarding Continuous Integration"
msgstr "Графики непрерывной интеграции (CI)"
msgid "A default branch cannot be chosen for an empty project."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¿ÑƒÑтого проекта Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð±Ñ€Ð°Ñ‚ÑŒ ветку по умолчанию."
msgid "A deleted user"
-msgstr ""
+msgstr "Удаленный пользователь"
msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr ""
+msgstr "Сотрудник группы по борьбе Ñ Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸Ñми GitLab раÑÑмотрит ваш отчет так быÑтро, наÑколько Ñто возможно."
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -398,16 +441,16 @@ msgid "A user with write access to the source branch selected this option"
msgstr "Пользователь Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸ÐµÐ¼ на запиÑÑŒ в ветку иÑточника выбрал Ñтот вариант"
msgid "About GitLab"
-msgstr ""
+msgstr "О GitLab"
msgid "About GitLab CE"
-msgstr ""
+msgstr "О GitLab CE"
msgid "About auto deploy"
msgstr "Об автоматичеÑком развёртывании"
msgid "About this feature"
-msgstr ""
+msgstr "Об Ñтой функциональноÑти"
msgid "Abuse Reports"
msgstr "Отчёты о Жалобах"
@@ -415,11 +458,14 @@ msgstr "Отчёты о Жалобах"
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr "ПринÑÑ‚ÑŒ уÑловиÑ"
msgid "Accepted MR"
-msgstr ""
+msgstr "ПринÑтый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "Access Tokens"
msgstr "Токены ДоÑтупа"
@@ -428,16 +474,16 @@ msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
msgid "Access expiration date"
-msgstr ""
+msgstr "Дата Ð¿Ñ€ÐµÐºÑ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупа"
msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
+msgstr "ДоÑтуп к '%{classification_label}' не разрешён"
msgid "Account"
msgstr "Ð£Ñ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ"
msgid "Account and limit"
-msgstr ""
+msgstr "Ðккаунт и ограничениÑ"
msgid "Active"
msgstr "Ðктивный"
@@ -449,82 +495,88 @@ msgid "Activity"
msgstr "ÐктивноÑÑ‚ÑŒ"
msgid "Add"
-msgstr ""
+msgstr "Добавить"
-msgid "Add Changelog"
-msgstr "Добавить Журнал Изменений"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "Добавить РуководÑтво учаÑтника"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
msgid "Add Jaeger URL"
-msgstr ""
+msgstr "Добавить URL-Ð°Ð´Ñ€ÐµÑ Jaeger"
msgid "Add Kubernetes cluster"
msgstr "Добавить Kubernetes клаÑтер"
-msgid "Add Readme"
-msgstr "Добавить Информацию"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
msgid "Add a table"
-msgstr ""
+msgstr "Добавить таблицу"
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
msgid "Add comment now"
-msgstr ""
+msgstr "Добавить комментарий"
msgid "Add image comment"
-msgstr ""
+msgstr "Добавить комментарий к изображению"
msgid "Add license"
-msgstr ""
+msgstr "Добавить лицензию"
msgid "Add new application"
-msgstr ""
+msgstr "Добавить новое приложение"
msgid "Add new directory"
msgstr "Добавить новый каталог"
msgid "Add projects"
-msgstr ""
+msgstr "Добавить проекты"
msgid "Add reaction"
msgstr "Добавить реакцию"
-msgid "Add to review"
+msgid "Add to project"
msgstr ""
+msgid "Add to review"
+msgstr "Добавить к рецензированию"
+
msgid "Add todo"
msgstr "Добавить в дела"
msgid "Add user(s) to the group:"
+msgstr "Добавить пользовател(Ñ/ей) в группу:"
+
+msgid "Add users or groups who are allowed to approve every merge request"
msgstr ""
msgid "Add users to group"
-msgstr ""
+msgstr "Добавить пользователей в группу"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
msgid "Additional text"
-msgstr ""
+msgstr "Дополнительный текÑÑ‚"
msgid "Admin Area"
-msgstr ""
+msgstr "Панель админиÑтрированиÑ"
msgid "Admin Overview"
-msgstr ""
-
-msgid "Admin area"
-msgstr ""
+msgstr "Обзор ÐдминиÑтратора"
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -559,12 +611,42 @@ msgstr "Удалить Проект %{projectName}?"
msgid "AdminProjects|Delete project"
msgstr "Удалить проект"
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Укажите домен, который будет иÑпользоватьÑÑ Ð¿Ð¾ умолчанию Ð´Ð»Ñ Ð²Ñех проектов в Auto Review приложениÑÑ… и ÑтадиÑÑ… Auto Deploy."
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Заблокировать пользователÑ"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "Удалить ÐŸÐ¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username} и внеÑённые им Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ?"
@@ -577,12 +659,42 @@ msgstr "Удалить пользователÑ"
msgid "AdminUsers|Delete user and contributions"
msgstr "Удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ внеÑённые им изменениÑ"
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{username}"
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -591,10 +703,13 @@ msgstr "РаÑширенные наÑтройки"
msgid "Alert"
msgid_plural "Alerts"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Предупреждение"
+msgstr[1] "Предупреждений"
+msgstr[2] "Предупреждений"
+msgstr[3] "Предупреждений"
+
+msgid "Alerts"
+msgstr ""
msgid "All"
msgstr "Ð’Ñе"
@@ -605,11 +720,17 @@ msgstr "Ð’Ñе Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð°Ñ„Ð¸ÐºÑированы"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Ð’Ñе функции ÑиÑтемы включаютÑÑ Ð´Ð»Ñ Ð¿ÑƒÑÑ‚Ñ‹Ñ… проектов, Ñозданных из шаблонов или импортированных, но вы можете отключить их впоÑледÑтвии в наÑтройках проекта."
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
+msgstr "Ð’Ñе пользователи"
+
+msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
msgid "Allow commits from members who can merge to the target branch."
-msgstr ""
+msgstr "Разрешить коммиты от учаÑтников, которые могут выполнÑÑ‚ÑŒ ÑлиÑние Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ веткой."
msgid "Allow projects within this group to use Git LFS"
msgstr ""
@@ -624,9 +745,12 @@ msgid "Allow requests to the local network from hooks and services."
msgstr ""
msgid "Allow users to request access"
-msgstr ""
+msgstr "Разрешить пользователÑм запрашивать доÑтуп"
msgid "Allow users to request access if visibility is public or internal."
+msgstr "Разрешить пользователÑм запрашивать доÑтуп, еÑли видимоÑÑ‚ÑŒ ÑвлÑетÑÑ Ð¾Ð±Ñ‰ÐµÐ´Ð¾Ñтупной или внутренней."
+
+msgid "Allowed to fail"
msgstr ""
msgid "Allows you to add and manage Kubernetes clusters."
@@ -656,46 +780,19 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
-msgstr ""
-
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
+msgstr "Произошла ошибка"
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
-msgstr ""
+msgstr "Произошла ошибка Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€Ð½Ð¾Ð²Ð¸ÐºÐ° ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ðº диÑкуÑÑии."
msgid "An error occurred adding a new draft."
+msgstr "Произошла ошибка Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ черновика."
+
+msgid "An error occurred creating the new branch."
msgstr ""
msgid "An error occurred previewing the blob"
@@ -705,16 +802,16 @@ msgid "An error occurred when toggling the notification subscription"
msgstr "Произошла ошибка при переключении подпиÑки на оповещениÑ"
msgid "An error occurred when updating the issue weight"
-msgstr ""
+msgstr "Произошла ошибка при обновлении веÑа обÑуждениÑ"
msgid "An error occurred while adding approver"
-msgstr ""
+msgstr "Произошла ошибка при добавлении одобрÑющего"
msgid "An error occurred while deleting the comment"
-msgstr ""
+msgstr "Во Ð²Ñ€ÐµÐ¼Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° ошибка"
msgid "An error occurred while detecting host keys"
-msgstr ""
+msgstr "Произошла ошибка при обнаружении ключей хоÑта"
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
msgstr "При отключении Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° ошибка. Обновите Ñтраницу и повторите попытку."
@@ -732,7 +829,7 @@ msgid "An error occurred while fetching sidebar data"
msgstr "Произошла ошибка при получении денег данных Ð´Ð»Ñ Ð±Ð¾ÐºÐ¾Ð²Ð¾Ð¹ панели"
msgid "An error occurred while fetching stages."
-msgstr ""
+msgstr "Произошла ошибка при извлечении Ñтадий."
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -770,10 +867,19 @@ msgstr "Произошла ошибка при загрузке ÑпиÑка Ñ„Ð
msgid "An error occurred while loading the file"
msgstr "Произошла ошибка при загрузке файла"
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr "Произошла ошибка при выполнении запроÑа."
msgid "An error occurred while removing approver"
+msgstr "Произошла ошибка при удалении одобрÑющего"
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
msgstr ""
msgid "An error occurred while rendering KaTeX"
@@ -806,12 +912,57 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr "Произошла ошибка при проверке имени пользователÑ"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Произошла ошибка. ПожалуйÑта, попробуйте Ñнова."
-msgid "Analytics"
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
msgstr ""
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "Analytics"
+msgstr "Ðналитика"
+
msgid "Anonymous"
msgstr ""
@@ -819,26 +970,41 @@ msgid "Anti-spam verification"
msgstr ""
msgid "Any"
-msgstr ""
+msgstr "Любой"
msgid "Any Label"
-msgstr ""
+msgstr "Ð›ÑŽÐ±Ð°Ñ ÐœÐµÑ‚ÐºÐ°"
msgid "Appearance"
msgstr "Оформление"
msgid "Application"
-msgstr ""
+msgstr "Приложение"
msgid "Application ID"
-msgstr ""
+msgstr "Идентификатор приложениÑ"
msgid "Application: %{name}"
-msgstr ""
+msgstr "Приложение: %{name}"
msgid "Applications"
msgstr "ПриложениÑ"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "Ðпр."
@@ -849,49 +1015,67 @@ msgid "Archived project! Repository and other project resources are read-only"
msgstr "Ðрхивный проект! Репозиторий и другие реÑурÑÑ‹ проекта доÑтупны только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
msgid "Archived projects"
+msgstr "Ðрхивные проекты"
+
+msgid "Are you sure"
msgstr ""
msgid "Are you sure you want to delete this pipeline schedule?"
-msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить Ñто раÑпиÑание Ñборочной линии?"
+msgstr "Ð’Ñ‹ уверены, что вы хотите удалить Ñто раÑпиÑание Ñборочной линии?"
msgid "Are you sure you want to erase this build?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что вы хотите удалить Ñту Ñборку?"
msgid "Are you sure you want to lose unsaved changes?"
+msgstr "Ð’Ñ‹ уверены, что вы хотите потерÑÑ‚ÑŒ не Ñохранённые изменениÑ?"
+
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что вы хотите заново Ñгенерировать публичный ключ? Вам нужно будет обновить публичный ключ на удаленном Ñервере, прежде чем зеркалирование Ñнова будет работать."
msgid "Are you sure you want to remove %{group_name}?"
+msgstr "Вы уверены, что вы хотите удалить %{group_name}?"
+
+msgid "Are you sure you want to remove approver %{name}?"
msgstr ""
-msgid "Are you sure you want to remove this identity?"
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
msgstr ""
+msgid "Are you sure you want to remove this identity?"
+msgstr "Ð’Ñ‹ уверены, что вы хотите удалить Ñту идентификацию?"
+
msgid "Are you sure you want to reset registration token?"
-msgstr "Ð’Ñ‹ уверены, что хотите ÑброÑить Ñтот региÑтрационный токен?"
+msgstr "Ð’Ñ‹ уверены, что вы хотите ÑброÑить Ñтот региÑтрационный токен?"
msgid "Are you sure you want to reset the health check token?"
msgstr "Ð’Ñ‹ уверены, что хотите ÑброÑить Ñтот токен проверки работоÑпоÑобноÑти?"
msgid "Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что вы хотите оÑтановить Ñто окружение?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr "Вы уверены, что вы хотите разблокировать %{path_lock_path}?"
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
msgid "Are you sure?"
msgstr "Вы уверены?"
msgid "Artifact ID"
-msgstr ""
+msgstr "ID артефакта"
msgid "Artifacts"
msgstr "Ðртефакты"
msgid "Ascending"
-msgstr ""
+msgstr "По возраÑтанию"
msgid "Ask your group maintainer to set up a group Runner."
msgstr ""
@@ -899,6 +1083,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "Ðазначьте пользовательÑкий цвет, например #FF0000"
@@ -908,6 +1095,9 @@ msgstr "Ðазначить метки"
msgid "Assign milestone"
msgstr "Ðазначить Ñтап"
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr "Ðазначить"
@@ -935,6 +1125,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr "ОтветÑтвенный(ные)"
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Приложить файл через drag &amp; drop или %{upload_link}"
@@ -947,19 +1140,25 @@ msgstr "Ðвг."
msgid "August"
msgstr "ÐвгуÑÑ‚"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "Журнал аутентификации"
msgid "Authentication log"
-msgstr ""
+msgstr "Журнал аутентификации"
msgid "Authentication method"
-msgstr ""
+msgstr "Метод аутентификации"
msgid "Author"
msgstr "Ðвтор"
msgid "Authorization code:"
+msgstr "Код авторизации:"
+
+msgid "Authorization key"
msgstr ""
msgid "Authorization was granted by entering your username and password in the application."
@@ -975,13 +1174,13 @@ msgid "Authorized At"
msgstr ""
msgid "Authorized applications (%{size})"
-msgstr ""
+msgstr "Ðвторизованные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (%{size})"
msgid "Authors: %{authors}"
msgstr "Ðвторы: %{authors}"
msgid "Auto DevOps"
-msgstr ""
+msgstr "ÐвтоматичеÑкий DevOps"
msgid "Auto DevOps enabled"
msgstr "Auto DevOps включен"
@@ -989,15 +1188,6 @@ msgstr "Auto DevOps включен"
msgid "Auto DevOps, runners and job artifacts"
msgstr "ÐвтоматичеÑкий DevOps, обработчики и артефакты заданий"
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr "ÐŸÑ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого ревью и автоматичеÑкого Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÑŽÑ‚ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ %{kubernetes} Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð¹ работы."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr "ÐŸÑ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого ревью и автоматичеÑкого Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÑŽÑ‚ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ домена и %{kubernetes} Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð¹ работы."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "ÐŸÑ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого ревью и автоматичеÑкого Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÑŽÑ‚ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ домена Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð¹ работы."
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -1031,14 +1221,26 @@ msgstr " включить ÐвтоматичеÑкий DevOps"
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "ДоÑтупен"
-msgid "Available group Runners : %{runners}"
-msgstr "ДоÑтупные обработчики заданий Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
-msgid "Available group Runners : %{runners}."
-msgstr "ДоÑтупные обработчики заданий Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr "Ðватар будет удален. Ð’Ñ‹ уверены?"
@@ -1047,13 +1249,13 @@ msgid "Average per day: %{average}"
msgstr "Ð’ Ñреднем за день: %{average}"
msgid "Background Color"
-msgstr ""
+msgstr "Цвет Фона"
msgid "Background Jobs"
-msgstr ""
+msgstr "Фоновые заданиÑ"
msgid "Background color"
-msgstr ""
+msgstr "Цвет фона"
msgid "Badges"
msgstr "Значки"
@@ -1146,28 +1348,28 @@ msgid "Begin with the selected commit"
msgstr "Ðачать Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ коммита"
msgid "Below are examples of regex for existing tools:"
-msgstr ""
+msgstr "Ðиже приведены примеры регулÑрных выражений Ð´Ð»Ñ ÑущеÑтвующих инÑтрументов:"
msgid "Below you will find all the groups that are public."
msgstr ""
msgid "Billing"
-msgstr ""
+msgstr "Тарифы"
msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
-msgstr ""
+msgstr "%{group_name} иÑпользует тарифный план %{plan_link} на текущий момент."
msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
msgstr ""
msgid "BillingPlans|Current plan"
-msgstr ""
+msgstr "Текущий тарифный план"
msgid "BillingPlans|Customer Support"
-msgstr ""
+msgstr "Поддержка клиентов"
msgid "BillingPlans|Downgrade"
-msgstr ""
+msgstr "Перейти на более Ñкономный"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
msgstr ""
@@ -1176,10 +1378,10 @@ msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
msgstr ""
msgid "BillingPlans|Manage plan"
-msgstr ""
+msgstr "Управление тарифным планом"
msgid "BillingPlans|Please contact %{customer_support_link} in that case."
-msgstr ""
+msgstr "ПожалуйÑта, в Ñтом Ñлучае обратитеÑÑŒ в %{customer_support_link}."
msgid "BillingPlans|See all %{plan_name} features"
msgstr ""
@@ -1188,7 +1390,7 @@ msgid "BillingPlans|This group uses the plan associated with its parent group."
msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
-msgstr ""
+msgstr "Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð°Ñ€Ð¸Ñ„Ð½Ñ‹Ð¼ планом Ñтой группы поÑетите раздел тарификации %{parent_billing_page_link}."
msgid "BillingPlans|Upgrade"
msgstr ""
@@ -1203,19 +1405,19 @@ msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}
msgstr ""
msgid "BillingPlans|features"
-msgstr ""
+msgstr "возможноÑти"
msgid "BillingPlans|frequently asked questions"
-msgstr ""
+msgstr "чаÑто задаваемые вопроÑÑ‹"
msgid "BillingPlans|monthly"
-msgstr ""
+msgstr "ежемеÑÑчно"
msgid "BillingPlans|paid annually at %{price_per_year}"
-msgstr ""
+msgstr "Ð•Ð¶ÐµÐ³Ð¾Ð´Ð½Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð° ÑоÑтавит %{price_per_year}"
msgid "BillingPlans|per user"
-msgstr ""
+msgstr "на одного пользователÑ"
msgid "Bitbucket Server Import"
msgstr ""
@@ -1223,21 +1425,20 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
-msgid "Blog"
+msgid "Block"
msgstr ""
+msgid "Blocked"
+msgstr ""
+
+msgid "Blog"
+msgstr "Блог"
+
msgid "Boards"
msgstr "ДоÑки"
msgid "Branch %{branchName} was not found in this project's repository."
-msgstr ""
-
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] "Ветка (%{branch_count})"
-msgstr[1] "Ветки (%{branch_count})"
-msgstr[2] "Ветки (%{branch_count})"
-msgstr[3] "Ветки (%{branch_count})"
+msgstr "Ветка %{branchName} не найдена в репозитории проекта."
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "Ветка <strong>%{branch_name}</strong> Ñоздана. Ð”Ð»Ñ Ð½Ð°Ñтройки автоматичеÑкого Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ð±ÐµÑ€Ð¸Ñ‚Ðµ YAML-шаблон Ð´Ð»Ñ GitLab CI и зафикÑируйте Ñвои изменениÑ. %{link_to_autodeploy_doc}"
@@ -1312,7 +1513,7 @@ msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot
msgstr "Как только вы подтвердите и нажмёте %{delete_protected_branch}, данные будут удалены без возможноÑти воÑÑтановлениÑ."
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
-msgstr ""
+msgstr "Только Ñопровождающий проект или владелец может удалить защищенную ветвь"
msgid "Branches|Overview"
msgstr "Обзор"
@@ -1348,7 +1549,7 @@ msgid "Branches|Stale branches"
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 "Ветка \"по умолчанию\" не может быть удалена"
@@ -1363,13 +1564,13 @@ msgid "Branches|To confirm, type %{branch_name_confirmation}:"
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{branch_name_confirmation}:"
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|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ безвозвратно удалить защищённую ветку %{branch_name}."
msgid "Branches|diverged from upstream"
-msgstr ""
+msgstr "раÑходитÑÑ Ñ Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÑким репозиторием"
msgid "Branches|merged"
msgstr "влита"
@@ -1381,7 +1582,7 @@ msgid "Branches|protected"
msgstr "защищена"
msgid "Browse Directory"
-msgstr "Обзор каталога"
+msgstr "ПроÑмотр каталога"
msgid "Browse File"
msgstr "ПроÑмотр файла"
@@ -1392,32 +1593,47 @@ msgstr "ПроÑмотр файлов"
msgid "Browse files"
msgstr "ПроÑмотр файлов"
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "по автору"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
+msgstr "ÐаÑтройки CI / CD"
+
+msgid "CI Lint"
msgstr ""
msgid "CI will run using the credentials assigned above."
msgstr ""
msgid "CI/CD"
-msgstr ""
+msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ CI/CD"
msgid "CI/CD for external repo"
-msgstr ""
+msgstr "CI/CD Ð´Ð»Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ репозиториÑ"
msgid "CI/CD settings"
msgstr "ÐаÑтройки CI/CD"
@@ -1443,12 +1659,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr "ЗаданиÑ"
@@ -1458,18 +1668,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
+msgstr "URL обратного вызова"
+
+msgid "Can override approvers and approvals required per merge request"
msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "Отмена"
@@ -1482,14 +1701,23 @@ msgstr "Ðет возможноÑти объединить автоматичеÑ
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Ðевозможно изменить управлÑемый клаÑтер Kubernetes"
-msgid "Certificate fingerprint"
+msgid "Certificate"
msgstr ""
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr "Отпечаток Ñертификата"
+
msgid "Change Weight"
+msgstr "Изменить ВеÑ"
+
+msgid "Change permissions"
msgstr ""
msgid "Change template"
-msgstr ""
+msgstr "Изменить шаблон"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Измените Ñто значение, чтобы уÑтановить как чаÑто GitLab UI запрашивает обновлениÑ."
@@ -1509,12 +1737,12 @@ msgstr "Отменить"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Это ÑоздаÑÑ‚ новый коммит Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы откатить ÑущеÑтвующие изменениÑ."
-msgid "Changelog"
-msgstr "Журнал изменений"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "Диаграммы"
@@ -1524,9 +1752,15 @@ msgstr "Чат"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr "Проверка доÑтупноÑти %{text} ..."
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "Проверка доÑтупноÑти ветви..."
@@ -1548,12 +1782,18 @@ msgstr "Выберите Файл..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Выберите ветку/тег (например, %{master}) или введите коммит (например, %{sha}), чтобы увидеть, что изменилоÑÑŒ или Ñоздать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние."
-msgid "Choose a template..."
+msgid "Choose a file"
msgstr ""
-msgid "Choose a type..."
+msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template..."
+msgstr "Выберите шаблон..."
+
+msgid "Choose a type..."
+msgstr "Выберите тип..."
+
msgid "Choose any color."
msgstr "Выберите любой цвет."
@@ -1566,6 +1806,9 @@ msgstr "Выберите файл..."
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1659,8 +1902,8 @@ msgstr "Ð’Ñе Ñреды"
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
-msgstr "Произошла ошибка при Ñохранении переменных"
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
msgid "CiVariable|New environment"
msgstr ""
@@ -1680,9 +1923,15 @@ msgstr "Проверка не удалаÑÑŒ"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "Clear search"
+msgid "Clear"
msgstr ""
+msgid "Clear input"
+msgstr ""
+
+msgid "Clear search"
+msgstr "ОчиÑтить поиÑк"
+
msgid "Clear search input"
msgstr "ОчиÑтить Ñтроку поиÑка"
@@ -1702,7 +1951,7 @@ msgid "Click the button below to begin the install process by navigating to the
msgstr "Ðажмите кнопку ниже, чтобы начать процеÑÑ ÑƒÑтановки, Ð¿ÐµÑ€ÐµÐ¹Ð´Ñ Ð½Ð° Ñтраницу Kubernetes"
msgid "Click to expand it."
-msgstr ""
+msgstr "Ðажмите, чтобы развернуть."
msgid "Click to expand text"
msgstr "Ðажмите, чтобы раÑкрыть текÑÑ‚"
@@ -1717,21 +1966,45 @@ msgid "Client authentication key password"
msgstr ""
msgid "Clients"
+msgstr "Клиенты"
+
+msgid "Clone"
msgstr ""
msgid "Clone repository"
msgstr "Клонировать репозиторий"
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr "Закрыть"
msgid "Close epic"
+msgstr "Завершить цель"
+
+msgid "Close milestone"
msgstr ""
msgid "Closed"
+msgstr "Закрыто"
+
+msgid "Closed (moved)"
msgstr ""
msgid "Closed issues"
+msgstr "Закрытые обÑуждениÑ"
+
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
@@ -1740,7 +2013,7 @@ msgstr "%{appList} уÑпешно уÑтановлены на вашем клаÑ
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1764,27 +2037,42 @@ msgstr "Дополнительные опции Ð´Ð»Ñ Ñтой интеграц
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "Произошла ошибка при попытке Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð·Ð¾Ð½ проекта: %{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr "Произошла ошибка при попытке Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐ¸Ñ… проектов: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr "ПриложениÑ"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
-msgstr "Ð’Ñ‹ уверены, что хотите удалить интеграцию Ñ Ñтим клаÑтером Kubernetes? Это не приведет к удалению вашего клаÑтера Kubernetes."
+msgstr "Ð’Ñ‹ уверены, что вы хотите удалить интеграцию Ñ Ñтим клаÑтером Kubernetes? Это не приведет к удалению вашего клаÑтера Kubernetes."
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
msgid "ClusterIntegration|CA Certificate"
msgstr "Сертификат удоÑтоверÑющего центра"
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Комплект Ñертификатов удоÑтоверÑющего центра (формат PEM)"
@@ -1794,6 +2082,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Скопировать Ð°Ð´Ñ€ÐµÑ API"
@@ -1806,6 +2097,9 @@ msgstr "Скопировать IP-Ð°Ð´Ñ€ÐµÑ Ingress в буфер обмена"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Скопировать Ð¸Ð¼Ñ ÐºÐ»Ð°Ñтера Kubernetes"
@@ -1833,6 +2127,15 @@ msgstr "Среда окружениÑ"
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr "Получение типов машин клаÑтера"
@@ -1861,7 +2164,7 @@ msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Проект Google Kubernetes Engine"
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "КлаÑтер группы"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1870,7 +2173,7 @@ msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes ap
msgstr ""
msgid "ClusterIntegration|Hide"
-msgstr ""
+msgstr "Скрыть"
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -1905,6 +2208,12 @@ msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ð·Ð°Ñ†Ð¸Ð¸ клаÑтеров Kuber
msgid "ClusterIntegration|Integration status"
msgstr " Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¸Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ð¸"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Ð˜Ð¼Ñ Ñ…Ð¾Ñта ÑервиÑа Jupyter"
@@ -1920,6 +2229,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "КлаÑтер Kubernetes"
@@ -1956,6 +2271,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr "Тип машины"
@@ -2034,6 +2352,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Ðе удалоÑÑŒ выполнить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° запуÑк процеÑÑа уÑтановки"
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr "Сохранить изменениÑ"
@@ -2076,12 +2397,18 @@ msgstr "Показать"
msgid "ClusterIntegration|Something went wrong on our end."
msgstr " У Ð½Ð°Ñ Ñ‡Ñ‚Ð¾-то пошло не так."
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr "Что-то пошло не так при Ñоздании клаÑтера Kubernetes в Google Kubernetes Engine"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Произошли ошибки во Ð²Ñ€ÐµÐ¼Ñ ÑƒÑтановки %{title}"
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2097,6 +2424,18 @@ msgstr "Переключить клаÑтер Kubernetes"
msgid "ClusterIntegration|Token"
msgstr "Токен"
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr "Проверка ÑтатуÑа тарификации проекта"
@@ -2109,6 +2448,9 @@ msgstr "ЕÑли привÑзать клаÑтер Kubernetes к Ñтому пр
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ должна иметь %{link_to_kubernetes_engine}"
@@ -2136,11 +2478,14 @@ msgstr "правильно наÑтроен"
msgid "ClusterIntegration|sign up"
msgstr "зарегиÑтрироватьÑÑ"
-msgid "Code owners"
+msgid "Code"
msgstr ""
+msgid "Code owners"
+msgstr "Владельцы кода"
+
msgid "Cohorts"
-msgstr ""
+msgstr "Когорты"
msgid "Collapse"
msgstr "Свернуть"
@@ -2148,14 +2493,23 @@ msgstr "Свернуть"
msgid "Collapse sidebar"
msgstr "Свернуть боковую панель"
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
+msgstr "Комментарий"
+
+msgid "Comment & close %{noteable_name}"
msgstr ""
-msgid "Comment & resolve discussion"
+msgid "Comment & reopen %{noteable_name}"
msgstr ""
+msgid "Comment & resolve discussion"
+msgstr "Прокомментировать и закрыть диÑкуÑÑию"
+
msgid "Comment & unresolve discussion"
-msgstr ""
+msgstr "Прокомментировать и переоткрыть диÑкуÑÑию"
msgid "Comment form position"
msgstr ""
@@ -2168,18 +2522,17 @@ msgid_plural "Commits"
msgstr[0] "Коммит"
msgstr[1] "Коммита"
msgstr[2] "Коммитов"
-msgstr[3] "Коммиты"
+msgstr[3] "Коммитов"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] "Коммит (%{commit_count})"
-msgstr[1] "Коммита (%{commit_count})"
-msgstr[2] "Коммитов (%{commit_count})"
-msgstr[3] "Коммитов (%{commit_count})"
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "ОпиÑание Коммита"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "ПродолжительноÑÑ‚ÑŒ поÑледних 30 коммитов в минутах"
@@ -2190,7 +2543,7 @@ msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
msgstr "СтатиÑтика коммитов Ð´Ð»Ñ %{ref} в период Ñ %{start_time} по %{end_time}"
msgid "Commit to %{branchName} branch"
-msgstr ""
+msgstr "Коммит в ветку %{branchName}"
msgid "CommitBoxTitle|Commit"
msgstr "Коммит"
@@ -2243,6 +2596,9 @@ msgstr "Сравнение верÑий Git"
msgid "Compare Revisions"
msgstr "Сравнить верÑии"
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr "Сравнить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ñледним коммитом"
@@ -2270,12 +2626,18 @@ msgstr "Конфиденциально"
msgid "Confidentiality"
msgstr "КонфиденциальноÑÑ‚ÑŒ"
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr "ÐаÑтройка таймаутов Gitaly."
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2307,6 +2669,9 @@ msgid "Connect your external repositories, and CI/CD pipelines will run for new
msgstr ""
msgid "Connecting..."
+msgstr "Подключение..."
+
+msgid "Contact sales to upgrade"
msgstr ""
msgid "Container Registry"
@@ -2357,23 +2722,26 @@ msgstr "Когда рееÑÑ‚Ñ€ контейнеров Docker интегриро
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Ð’Ñ‹ также можете иÑпользовать %{deploy_token} Ð´Ð»Ñ Ð´Ð¾Ñтупа в режиме только чтение к рееÑтру образов."
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr "Продолжить"
msgid "Continue to the next step"
-msgstr ""
+msgstr "Перейти к Ñледующему шагу"
msgid "Continuous Integration and Deployment"
msgstr "ÐÐµÐ¿Ñ€ÐµÑ€Ñ‹Ð²Ð½Ð°Ñ Ð¸Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Ð¸ развертывание"
msgid "Contribute to GitLab"
-msgstr ""
+msgstr "ВнеÑти вклад в GitLab"
msgid "Contribution"
msgstr "УчаÑтие"
-msgid "Contribution guide"
-msgstr "РуководÑтво учаÑтника"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr ""
@@ -2408,13 +2776,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2423,6 +2794,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2445,10 +2819,7 @@ msgid "Copy incoming email address to clipboard"
msgstr ""
msgid "Copy link"
-msgstr ""
-
-msgid "Copy name to clipboard"
-msgstr ""
+msgstr "Копировать ÑÑылку"
msgid "Copy reference to clipboard"
msgstr "Скопировать ÑÑылку в буфер обмена"
@@ -2471,6 +2842,9 @@ msgstr "Создать"
msgid "Create New Directory"
msgstr "Создать Ðовый каталог"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr "Создать новую ветку"
@@ -2478,6 +2852,9 @@ msgid "Create a new branch and merge request"
msgstr "Создать новую ветку и Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "Create a new issue"
+msgstr "Создать новое обÑуждение"
+
+msgid "Create a new repository"
msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
@@ -2487,7 +2864,7 @@ msgid "Create branch"
msgstr "Создать ветку"
msgid "Create commit"
-msgstr ""
+msgstr "Создать коммит"
msgid "Create directory"
msgstr "Создать каталог"
@@ -2496,19 +2873,19 @@ msgid "Create empty repository"
msgstr "Создать пуÑтой репозиторий"
msgid "Create epic"
-msgstr ""
+msgstr "Создать цель"
msgid "Create file"
msgstr "Создать файл"
msgid "Create group"
-msgstr ""
+msgstr "Создать группу"
msgid "Create group label"
msgstr "Создать метку группы"
msgid "Create issue"
-msgstr ""
+msgstr "Создать обÑуждение"
msgid "Create lists from labels. Issues with that label appear in that list."
msgstr "Создать ÑпиÑок из меток. ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ Ñтой меткой поÑвлÑÑŽÑ‚ÑÑ Ð² Ñтом ÑпиÑке."
@@ -2519,6 +2896,9 @@ msgstr "Создать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "Create merge request and branch"
msgstr "Создать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние и ветку"
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "Создать новую ветку"
@@ -2529,7 +2909,7 @@ msgid "Create new file"
msgstr "Создать новый файл"
msgid "Create new file or directory"
-msgstr ""
+msgstr "Создать новый файл или каталог"
msgid "Create new label"
msgstr "Создать новую метку"
@@ -2541,7 +2921,7 @@ msgid "Create project label"
msgstr "Создать метку проекта"
msgid "Create your first page"
-msgstr ""
+msgstr "Создайте вашу первую Ñтраницу"
msgid "CreateTag|Tag"
msgstr "Тег"
@@ -2574,10 +2954,10 @@ msgid "Cron syntax"
msgstr "СинтакÑÐ¸Ñ Cron"
msgid "Current Branch"
-msgstr ""
+msgstr "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð’ÐµÑ‚ÐºÐ°"
msgid "Current node"
-msgstr ""
+msgstr "Текущий узел"
msgid "CurrentUser|Profile"
msgstr "Профиль"
@@ -2585,9 +2965,6 @@ msgstr "Профиль"
msgid "CurrentUser|Settings"
msgstr "ÐаÑтройки"
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2603,15 +2980,24 @@ msgstr "ÐаÑтраиваемые уровни уведомлений аналÐ
msgid "Custom project templates"
msgstr ""
-msgid "Customize colors"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
msgstr ""
+msgid "Customize colors"
+msgstr "ÐаÑтроить цвета"
+
msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2642,20 +3028,26 @@ msgstr "Приёмка"
msgid "CycleAnalyticsStage|Test"
msgstr "ТеÑтирование"
-msgid "Dashboard"
+msgid "DNS"
msgstr ""
+msgid "Dashboard"
+msgstr "Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ"
+
msgid "DashboardProjects|All"
msgstr "Ð’Ñе"
msgid "DashboardProjects|Personal"
msgstr "Личные"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
msgid "Debug"
-msgstr ""
+msgstr "Отладка"
msgid "Dec"
msgstr "Дек."
@@ -2663,15 +3055,24 @@ msgstr "Дек."
msgid "December"
msgstr "Декабрь"
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr "Отклонить и выйти"
msgid "Default Branch"
-msgstr ""
+msgstr "Ветка по умолчанию"
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2681,11 +3082,14 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Определить наÑтраиваемый шаблон Ñ ÑинтакÑиÑом cron"
-msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+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|Start now"
msgstr ""
@@ -2700,20 +3104,26 @@ msgid "Delete"
msgstr "Удалить"
msgid "Delete Package"
-msgstr ""
+msgstr "Удалить пакет"
msgid "Delete Snippet"
-msgstr ""
+msgstr "Удалить пример кода"
msgid "Delete comment"
-msgstr ""
+msgstr "Удалить комментарий"
msgid "Delete list"
msgstr "Удалить ÑпиÑок"
-msgid "Deleted"
+msgid "Delete source branch"
msgstr ""
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Deleted"
+msgstr "Удалено"
+
msgid "Deny"
msgstr ""
@@ -2847,6 +3257,9 @@ msgstr "Ваш Ðовый Токен РазвертываниÑ"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Создан новый токен Ð´Ð»Ñ Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°."
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2857,7 +3270,7 @@ msgid "Deprioritize label"
msgstr ""
msgid "Descending"
-msgstr ""
+msgstr "По убыванию"
msgid "Description"
msgstr "ОпиÑание"
@@ -2866,7 +3279,7 @@ msgid "Description templates allow you to define context-specific templates for
msgstr ""
msgid "Description:"
-msgstr ""
+msgstr "ОпиÑание:"
msgid "Destroy"
msgstr ""
@@ -2874,6 +3287,9 @@ msgstr ""
msgid "Details"
msgstr "ÐŸÐ¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2904,6 +3320,12 @@ msgstr "Отключить Ð´Ð»Ñ Ñтого проекта"
msgid "Disable group Runners"
msgstr "Выключить групповые обработчиков заданий"
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2925,15 +3347,24 @@ msgstr "Удалить черновик"
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr "ИÑÑледуйте проекты, группы и примеры кода. ПоделитеÑÑŒ вашими проектами Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ людьми"
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
msgstr ""
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "Отключить блок Ð²Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð² Ðналитику Цикла"
@@ -2961,6 +3392,12 @@ msgstr "Выполнено"
msgid "Download"
msgstr "Скачать"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "Скачать tar"
@@ -2985,6 +3422,9 @@ msgstr "ПроÑтой Diff"
msgid "DownloadSource|Download"
msgstr "Скачать"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr "ГолоÑа \"против\""
@@ -3000,18 +3440,30 @@ msgstr ""
msgid "Edit"
msgstr "Редактировать"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
+msgstr "Редактировать метку"
+
+msgid "Edit Milestone"
msgstr ""
msgid "Edit Pipeline Schedule %{id}"
msgstr "Изменить раÑпиÑание Ñборочной линии %{id}"
msgid "Edit Snippet"
-msgstr ""
+msgstr "Редактировать пример кода"
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr "Редактируйте файлы в редакторе и зафикÑируйте Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð´ÐµÑÑŒ"
@@ -3021,11 +3473,14 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
-msgid "Elasticsearch"
+msgid "Edit issues"
msgstr ""
+msgid "Elasticsearch"
+msgstr "Elasticsearch"
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
+msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Elasticsearch. Elasticsearch AWS IAM."
msgid "Email"
msgstr "Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð°"
@@ -3039,6 +3494,9 @@ msgstr "Email-адреÑа"
msgid "Embed"
msgstr "Ð’Ñтроить"
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr "Включить"
@@ -3063,6 +3521,9 @@ msgstr "Включить и наÑтроить метрики Prometheus."
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr "Включить Ð´Ð»Ñ Ñтого проекта"
@@ -3078,39 +3539,72 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr "Включите панель производительноÑти Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ группы."
-msgid "Enable usage ping"
+msgid "Enable two-factor authentication"
msgstr ""
+msgid "Enable usage ping"
+msgstr "Включить Ñбор ÑтатиÑтики иÑпользованиÑ"
+
msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
msgstr ""
msgid "Enabled"
-msgstr ""
+msgstr "Включено"
msgid "Ends at (UTC)"
msgstr "ЗаканчиваетÑÑ Ð² (UTC)"
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
msgid "Enter the issue description"
-msgstr ""
+msgstr "Введите опиÑание обÑуждениÑ"
msgid "Enter the issue title"
-msgstr ""
+msgstr "Введите заголовок обÑуждениÑ"
msgid "Enter the merge request description"
msgstr ""
msgid "Enter the merge request title"
+msgstr "Введите заголовок запроÑа на ÑлиÑние"
+
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
msgstr ""
msgid "Environments"
msgstr "Среды"
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Произошла ошибка при получении окружений."
@@ -3121,7 +3615,7 @@ msgid "Environments|An error occurred while stopping the environment, please try
msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что вы хотите оÑтановить Ñто окружение?"
msgid "Environments|Commit"
msgstr "Коммит"
@@ -3181,11 +3675,14 @@ msgid "Environments|Show all"
msgstr "Показать вÑе"
msgid "Environments|Stop"
-msgstr ""
+msgstr "ОÑтановить"
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Обновлено"
@@ -3196,21 +3693,18 @@ msgid "Environments|protected"
msgstr ""
msgid "Epic"
-msgstr ""
-
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
+msgstr "Цель"
msgid "Epics"
-msgstr ""
+msgstr "Цели"
msgid "Epics Roadmap"
msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
-msgstr ""
+msgstr "Цели позволÑÑ‚ вам управлÑÑ‚ÑŒ портфелем проектов более Ñффективно и Ñ Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼Ð¸ уÑилиÑми"
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3232,14 +3726,20 @@ msgid "Epics|start"
msgstr ""
msgid "Error"
-msgstr ""
+msgstr "Ошибка"
msgid "Error Reporting and Logging"
msgstr "Отчеты об ошибках и журналирование"
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… учаÑтников."
@@ -3268,7 +3768,7 @@ msgid "Error loading markdown preview"
msgstr ""
msgid "Error loading merge requests."
-msgstr ""
+msgstr "Ошибка загрузки запроÑов на ÑлиÑние."
msgid "Error loading project data. Please try again."
msgstr "Ошибка загрузки данных проекта. ПожалуйÑта, попробуйте еще раз."
@@ -3282,9 +3782,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr "Произошла ошибка при переключении подпиÑки на оповещение"
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr "Ошибка при обновлении метки."
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr "Ошибка при обновлении ÑтатуÑа Ð´Ð»Ñ Ð²Ñех дел."
@@ -3294,6 +3800,12 @@ msgstr "Ошибка при обновлении ÑтатуÑа дела."
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3315,6 +3827,12 @@ msgstr "Фильтр по ÑобытиÑм отправки"
msgid "EventFilterBy|Filter by team"
msgstr "Фильтр по команде"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Ежедневно (в 4:00)"
@@ -3324,9 +3842,39 @@ msgstr "ЕжемеÑÑчно (каждое 1-е чиÑло в 4:00)"
msgid "Every week (Sundays at 4:00am)"
msgstr "Еженедельно (по воÑкреÑениÑм в 4:00)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr "Развернуть"
@@ -3339,30 +3887,48 @@ msgstr "Развернуть боковую панель"
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
msgid "Explore"
-msgstr ""
+msgstr "Обзор"
msgid "Explore GitLab"
-msgstr ""
+msgstr "Обзор GitLab"
msgid "Explore Groups"
-msgstr ""
+msgstr "Обзор Групп"
msgid "Explore groups"
-msgstr ""
+msgstr "Обзор групп"
msgid "Explore projects"
msgstr "Обзор проектов"
msgid "Explore public groups"
-msgstr "ИÑÑледовать публичные группы"
+msgstr "Обзор публичных групп"
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3382,7 +3948,7 @@ msgid "ExternalAuthorizationService|When no classification label is set the defa
msgstr ""
msgid "Facebook"
-msgstr ""
+msgstr "Facebook"
msgid "Failed"
msgstr "Ðеудачно"
@@ -3402,6 +3968,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "Ошибка при удалении обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ Ð´Ð¾Ñки, повторите попытку."
@@ -3411,44 +3980,59 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Ðе удалоÑÑŒ удалить раÑпиÑание Ñборочной линии"
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr "Ошибка Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñуждений, пожалуйÑта, попробуйте Ñнова."
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
+msgstr "Функциональные опции"
+
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|API URL"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
msgstr ""
msgid "FeatureFlags|Configure feature flags"
-msgstr ""
+msgstr "ÐаÑтройка функциональных опций"
msgid "FeatureFlags|Create feature flag"
+msgstr "Создать функциональную опцию"
+
+msgid "FeatureFlags|Delete %{name}?"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
-msgstr ""
+msgstr "ОпиÑание"
msgid "FeatureFlags|Edit %{feature_flag_name}"
msgstr ""
@@ -3456,22 +4040,34 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
+msgstr "Ðеактивен"
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
@@ -3480,6 +4076,12 @@ msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3496,6 +4098,21 @@ msgid "FeatureFlags|Save changes"
msgstr ""
msgid "FeatureFlags|Status"
+msgstr "СтатуÑ"
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
msgid "Feb"
@@ -3507,20 +4124,42 @@ msgstr "Февраль"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "ÐŸÐ¾Ð»Ñ Ð½Ð° Ñтой Ñтранице ÑÐµÐ¹Ñ‡Ð°Ñ Ð½ÐµÐ´Ð¾Ñтупны Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ, вы можете наÑтроить"
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "Файлы"
-msgid "Files (%{human_size})"
-msgstr "Файлов (%{human_size})"
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
msgid "Filter"
-msgstr ""
+msgstr "Фильтр"
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -3531,12 +4170,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr "Фильтр по комментариÑми к коммитам"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
+msgstr "Фильтр..."
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
msgstr ""
msgid "Find by path"
msgstr "ПоиÑк по пути"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "Ðайти файл"
@@ -3549,12 +4206,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr "Завершено"
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "Первый"
@@ -3592,7 +4255,7 @@ msgid "Follow the steps below to export your Google Code project data."
msgstr ""
msgid "Font Color"
-msgstr ""
+msgstr "Цвет Шрифта"
msgid "Footer message"
msgstr ""
@@ -3600,6 +4263,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3624,6 +4290,9 @@ msgstr "Ответвление от %{project_name} (удалено)"
msgid "Forking in progress"
msgstr "ВыполнÑетÑÑ Ð¾Ñ‚Ð²ÐµÑ‚Ð²Ð»ÐµÐ½Ð¸Ðµ"
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "Формат"
@@ -3675,6 +4344,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "Создать Ñтандартный набор меток"
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3751,7 +4423,7 @@ msgid "GeoNodes|Local job artifacts"
msgstr ""
msgid "GeoNodes|New node"
-msgstr ""
+msgstr "Ðовый узел"
msgid "GeoNodes|Node Authentication was successfully repaired."
msgstr ""
@@ -3765,7 +4437,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3775,7 +4450,7 @@ msgid "GeoNodes|Replication slots"
msgstr ""
msgid "GeoNodes|Repositories"
-msgstr ""
+msgstr "Репозитории"
msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
msgstr ""
@@ -3840,6 +4515,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3856,7 +4534,7 @@ msgid "Geo|All"
msgstr ""
msgid "Geo|All projects"
-msgstr ""
+msgstr "Ð’Ñе проекты"
msgid "Geo|All projects are being scheduled for re-check"
msgstr ""
@@ -3885,6 +4563,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3921,6 +4602,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3999,7 +4683,16 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
+msgstr "Git"
+
+msgid "Git global setup"
msgstr ""
msgid "Git repository URL"
@@ -4029,9 +4722,15 @@ msgstr "Групповые Обработчики Заданий (GitLab Group R
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4062,6 +4761,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr "ВернутьÑÑ Ð½Ð°Ð·Ð°Ð´"
@@ -4086,11 +4788,14 @@ msgstr "ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Google не %{link_to_documentation}. ПоÐ
msgid "Got it!"
msgstr "ПонÑтно!"
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
msgid "Group"
-msgstr ""
+msgstr "Группа"
msgid "Group CI/CD settings"
msgstr ""
@@ -4111,13 +4816,13 @@ msgid "Group URL"
msgstr ""
msgid "Group avatar"
-msgstr ""
+msgstr "Ðватар группы"
msgid "Group description"
-msgstr ""
+msgstr "ОпиÑание группы"
msgid "Group description (optional)"
-msgstr ""
+msgstr "ОпиÑание группы (необÑзательно)"
msgid "Group details"
msgstr ""
@@ -4129,15 +4834,18 @@ msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
msgid "Group name"
+msgstr "Ðазвание группы"
+
+msgid "Group overview content"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group: %{group_name}"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4149,22 +4857,10 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|Until %{dateWord}"
@@ -4173,15 +4869,24 @@ msgstr ""
msgid "GroupSettings|Badges"
msgstr ""
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
msgid "GroupSettings|Customize your group badges."
msgstr ""
msgid "GroupSettings|Learn more about badges."
msgstr ""
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Запретить публикацию проектов из %{group} в других группах"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Эта наÑтройка применена в %{ancestor_group} и была переопределена в Ñтой подгруппе."
@@ -4201,11 +4906,14 @@ msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name
msgstr "удалить возможноÑÑ‚ÑŒ поделитьÑÑ Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¾Ð²Ð¾Ð¹ блокировкой из %{ancestor_group_name}"
msgid "Groups"
-msgstr ""
+msgstr "Группы"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4225,7 +4933,7 @@ msgid "GroupsDropdown|Sorry, no groups matched your search"
msgstr ""
msgid "GroupsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "Эта функциональноÑÑ‚ÑŒ требует поддержки localStorage в вашем браузере"
msgid "GroupsEmptyState|A group is a collection of several projects."
msgstr "Группа - Ñто набор из неÑкольких проектов."
@@ -4240,7 +4948,7 @@ msgid "GroupsEmptyState|You can manage your group member’s permissions and acc
msgstr "Ð’Ñ‹ можете управлÑÑ‚ÑŒ правами и доÑтупом учаÑтников вашей группы к каждому проекту в группе."
msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
-msgstr ""
+msgstr "Вы уверены, что вы хотите покинуть группу \"%{fullName}\"?"
msgid "GroupsTree|Create a project in this group."
msgstr "Создать проект в Ñтой группе."
@@ -4305,6 +5013,9 @@ msgstr "ТекÑÑ‚ Ñтраницы Ñправки и Url-Ð°Ð´Ñ€ÐµÑ ÑтранÐ
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4318,7 +5029,7 @@ msgstr[1] "Скрыть значениÑ"
msgstr[2] "Скрыть значениÑ"
msgstr[3] "Скрыть значениÑ"
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4327,6 +5038,9 @@ msgstr "ИÑториÑ"
msgid "Housekeeping successfully started"
msgstr "ОчиÑтка уÑпешно запущена"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4361,7 +5075,7 @@ msgid "IDE|Live Preview"
msgstr ""
msgid "IDE|Open in file view"
-msgstr ""
+msgstr "Открыть как файл"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
msgstr ""
@@ -4370,13 +5084,13 @@ msgid "IDE|Refresh preview"
msgstr ""
msgid "IDE|Review"
-msgstr "Обзор"
+msgstr "РецензиÑ"
msgid "IP Address"
msgstr ""
msgid "Identifier"
-msgstr ""
+msgstr "Идентификатор"
msgid "Identities"
msgstr ""
@@ -4384,6 +5098,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4391,7 +5108,7 @@ msgid "If disabled, the access level will depend on the user's permissions in th
msgstr ""
msgid "If enabled"
-msgstr ""
+msgstr "ЕÑли включено"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
@@ -4414,9 +5131,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr "Импортировать"
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4435,12 +5158,24 @@ msgstr ""
msgid "Import in progress"
msgstr "ВыполнÑетÑÑ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚"
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4465,6 +5200,9 @@ msgstr "Импорт репозиториев из GitHub"
msgid "Import repository"
msgstr "Импорт репозиториÑ"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4480,15 +5218,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4504,6 +5257,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4512,10 +5268,10 @@ msgstr "УÑтановить Runner на Kubernetes"
msgid "Instance"
msgid_plural "Instances"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ЭкземплÑÑ€"
+msgstr[1] "ЭкземплÑров"
+msgstr[2] "ЭкземплÑры"
+msgstr[3] "ЭкземплÑры"
msgid "Instance Statistics"
msgstr ""
@@ -4535,6 +5291,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "Желающие могут внеÑти Ñвой вклад, отправив коммит, еÑли захотÑÑ‚."
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr "Внутренний - Группу и включённые в неё проекты может видеть любой зарегиÑтрированный пользователь."
@@ -4550,15 +5309,33 @@ msgstr "Шаблон интервала"
msgid "Introducing Cycle Analytics"
msgstr "Внедрение Цикла Ðналитик"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
+msgstr "Приглашение"
+
+msgid "Invite group"
msgstr ""
-msgid "Issue"
+msgid "Invite member"
msgstr ""
-msgid "Issue Boards"
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
msgstr ""
+msgid "Issue"
+msgstr "ОбÑуждение"
+
+msgid "Issue Boards"
+msgstr "ДоÑки ОбÑуждений"
+
msgid "Issue board focus mode"
msgstr ""
@@ -4569,6 +5346,21 @@ msgid "IssueBoards|Board"
msgstr "ДоÑка"
msgid "IssueBoards|Boards"
+msgstr "ДоÑки"
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
msgstr ""
msgid "Issues"
@@ -4578,10 +5370,10 @@ msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are sear
msgstr "ОбÑуждениÑми могут быть ошибки, задачи или идеи. Также, по обÑуждениÑм можно выполнÑÑ‚ÑŒ поиÑк и отбор."
msgid "Issues closed"
-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 ""
@@ -4604,6 +5396,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4617,16 +5415,22 @@ msgid "January"
msgstr "Январь"
msgid "Job"
-msgstr ""
+msgstr "Задание"
msgid "Job has been erased"
msgstr "Фоновое задание было удалено"
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr "ЗаданиÑ"
msgid "Job|Browse"
-msgstr ""
+msgstr "ПроÑмотр"
msgid "Job|Complete Raw"
msgstr ""
@@ -4661,10 +5465,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4679,12 +5483,18 @@ msgstr "Июн."
msgid "June"
msgstr "Июнь"
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
msgid "Kubernetes Cluster"
msgstr "КлаÑтер Kubernetes"
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "Ð’Ñ€ÐµÐ¼Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ñтера Kubernetes превышает Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ; %{timeout}"
@@ -4704,7 +5514,7 @@ msgid "Kubernetes service integration has been deprecated. %{deprecated_message_
msgstr ""
msgid "LFS"
-msgstr ""
+msgstr "LFS"
msgid "LFSStatus|Disabled"
msgstr "Отключено"
@@ -4728,7 +5538,7 @@ msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
msgstr "%{labelsString} и еще %{remainingLabelCount} других"
msgid "LabelSelect|Labels"
-msgstr ""
+msgstr "Метки"
msgid "Labels"
msgstr "Метки"
@@ -4764,6 +5574,9 @@ msgstr[3] "ПоÑледние %d дни"
msgid "Last Pipeline"
msgstr "ПоÑледнÑÑ Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð›Ð¸Ð½Ð¸Ñ"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "ПоÑледний коммит"
@@ -4779,6 +5592,9 @@ msgstr "Ðвтор поÑледнего изменениÑ: %{name}"
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr "ПоÑледнее обновление"
@@ -4794,15 +5610,39 @@ msgstr "в"
msgid "Latest changes"
msgstr "ПоÑледние изменениÑ"
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr "Подробнее"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr "Подробнее о Kubernates"
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4825,28 +5665,28 @@ msgid "Leave the \"File type\" and \"Delivery method\" options on their default
msgstr ""
msgid "License"
-msgstr ""
+msgstr "ЛицензиÑ"
msgid "LicenseManagement|Add a license"
-msgstr ""
+msgstr "Добавить лицензию"
msgid "LicenseManagement|Add licenses manually to approve or blacklist"
-msgstr ""
+msgstr "Вручную добавить лицензии в одобренные или внеÑённые в черный ÑпиÑок"
msgid "LicenseManagement|Approve"
-msgstr ""
+msgstr "Одобрить"
msgid "LicenseManagement|Approve license"
-msgstr ""
+msgstr "Одобрить лицензию"
msgid "LicenseManagement|Approve license?"
-msgstr ""
+msgstr "Одобрить лицензию?"
msgid "LicenseManagement|Approved"
-msgstr ""
+msgstr "Одобрено"
msgid "LicenseManagement|Blacklist"
-msgstr ""
+msgstr "Черный ÑпиÑок"
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4858,10 +5698,10 @@ msgid "LicenseManagement|Blacklisted"
msgstr ""
msgid "LicenseManagement|Cancel"
-msgstr ""
+msgstr "Отмена"
msgid "LicenseManagement|License"
-msgstr ""
+msgstr "ЛицензиÑ"
msgid "LicenseManagement|License Management"
msgstr ""
@@ -4870,10 +5710,10 @@ msgid "LicenseManagement|License details"
msgstr ""
msgid "LicenseManagement|License name"
-msgstr ""
+msgstr "Ðаименование лицензии"
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
-msgstr ""
+msgstr "Управление одобренными и внеÑенными в черный ÑпиÑок лицензиÑм Ð´Ð»Ñ Ñтого проекта."
msgid "LicenseManagement|Packages"
msgstr ""
@@ -4885,10 +5725,10 @@ msgid "LicenseManagement|Remove license?"
msgstr ""
msgid "LicenseManagement|Submit"
-msgstr ""
+msgstr "Подтвердить"
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
-msgstr ""
+msgstr "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÑ‚ одобренных или внеÑенных в черный ÑпиÑок лицензий в Ñтом проекте."
msgid "LicenseManagement|This license already exists in this project."
msgstr ""
@@ -4900,7 +5740,7 @@ msgid "LicenseManagement|You are about to remove the license, %{name}, from this
msgstr ""
msgid "Licenses"
-msgstr ""
+msgstr "Лицензии"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
@@ -4910,13 +5750,13 @@ msgstr[2] ""
msgstr[3] ""
msgid "LinkedIn"
-msgstr ""
+msgstr "LinkedIn"
msgid "List"
msgstr "СпиÑок"
msgid "List Your Gitea Repositories"
-msgstr ""
+msgstr "СпиÑок репозиториев Gitea"
msgid "List available repositories"
msgstr ""
@@ -4931,7 +5771,7 @@ msgid "List your GitHub repositories"
msgstr "СпиÑок ваших репозиториев на GitHub"
msgid "Live preview"
-msgstr ""
+msgstr "Предварительный проÑмотр в реальном времени"
msgid "Loading contribution stats for group members"
msgstr ""
@@ -4942,6 +5782,12 @@ msgstr "Загрузка GitLab IDE..."
msgid "Loading..."
msgstr "Загрузка..."
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr "Блокировка"
@@ -4973,7 +5819,7 @@ msgid "Login with smartcard"
msgstr ""
msgid "Logs"
-msgstr ""
+msgstr "Журналы"
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
@@ -5008,14 +5854,17 @@ msgstr "Управление метками"
msgid "Manage project labels"
msgstr "Управление метками проекта"
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
msgid "Manifest"
-msgstr ""
+msgstr "МанифеÑÑ‚"
msgid "Manifest file import"
-msgstr ""
+msgstr "Импорт файла манифеÑта"
msgid "Map a FogBugz account ID to a GitLab user"
msgstr ""
@@ -5038,6 +5887,9 @@ msgstr "Март"
msgid "Mark todo as done"
msgstr "Отметить как Ñделанное"
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr "Включен режим Markdown"
@@ -5074,9 +5926,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5098,24 +5947,36 @@ msgstr ""
msgid "Members"
msgstr "УчаÑтники"
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
-msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние:"
+msgid "Merge Request"
+msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "Merge Requests"
msgstr "ЗапроÑÑ‹ на СлиÑние"
msgid "Merge Requests created"
+msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние Ñоздан"
+
+msgid "Merge commit message"
msgstr ""
msgid "Merge events"
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ ÑлиÑний"
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -5128,19 +5989,31 @@ msgstr "ЗапроÑÑ‹ на ÑлиÑние"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "ЗапроÑÑ‹ на ÑлиÑние- Ñто меÑто, где можно предлагать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð½Ð¾Ñимые в проект, и обÑуждать Ñти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸"
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5158,15 +6031,36 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
-msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
msgstr ""
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr "%{paragraphStart}изменил опиÑание %{descriptionChangedTimes} раз, за поÑледние %{timeDifferenceMinutes}%{paragraphEnd}"
+
msgid "MergeRequest|Filter files"
msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr "Слито"
@@ -5174,7 +6068,7 @@ msgid "Messages"
msgstr "СообщениÑ"
msgid "Metrics"
-msgstr ""
+msgstr "Метрики"
msgid "Metrics - Influx"
msgstr "Метрики - Influx"
@@ -5183,27 +6077,33 @@ msgid "Metrics - Prometheus"
msgstr "Метрики - Prometheus"
msgid "Metrics and profiling"
-msgstr ""
+msgstr "Метрики и профилирование"
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
msgid "Metrics|Create metric"
+msgstr "Создать метрику"
+
+msgid "Metrics|Delete metric"
msgstr ""
-msgid "Metrics|Edit metric"
+msgid "Metrics|Delete metric?"
msgstr ""
+msgid "Metrics|Edit metric"
+msgstr "Редактировать метрику"
+
msgid "Metrics|Environment"
msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5215,22 +6115,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
-msgstr ""
+msgstr "ÐÐ¾Ð²Ð°Ñ Ð¼ÐµÑ‚Ñ€Ð¸ÐºÐ°"
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Query"
-msgstr ""
-
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5245,10 +6139,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5269,21 +6163,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr "Этап"
@@ -5356,11 +6241,23 @@ msgstr "Отмена"
msgid "Modal|Close"
msgstr "Закрыть"
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "Мониторинг"
msgid "Months"
-msgstr ""
+msgstr "МеÑÑцы"
msgid "More"
msgstr ""
@@ -5399,7 +6296,7 @@ msgid "Name your individual key via a title"
msgstr ""
msgid "Name:"
-msgstr ""
+msgstr "Ðаименование:"
msgid "Naming, visibility"
msgstr ""
@@ -5416,20 +6313,26 @@ msgstr "Вход / РегиÑтрациÑ"
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
msgid "Never"
-msgstr ""
+msgstr "Ðикогда"
msgid "New"
-msgstr ""
+msgstr "Ðовый"
msgid "New Application"
+msgstr "Ðовое Приложение"
+
+msgid "New Environment"
msgstr ""
msgid "New Group"
-msgstr ""
+msgstr "ÐÐ¾Ð²Ð°Ñ Ð“Ñ€ÑƒÐ¿Ð¿Ð°"
msgid "New Identity"
msgstr ""
@@ -5444,14 +6347,20 @@ msgstr[3] "Ðовые ОбÑуждениÑ"
msgid "New Label"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð¼ÐµÑ‚ÐºÐ°"
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "Ðовое РаÑпиÑание Сборочной Линии"
msgid "New Snippet"
-msgstr ""
+msgstr "Ðовый пример кода"
msgid "New Snippets"
-msgstr ""
+msgstr "Ðовые примеры кода"
msgid "New branch"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð²ÐµÑ‚ÐºÐ°"
@@ -5462,9 +6371,12 @@ msgstr "ÐÐ¾Ð²Ð°Ñ Ð²ÐµÑ‚ÐºÐ° недоÑтупна"
msgid "New directory"
msgstr "Ðовый каталог"
-msgid "New epic"
+msgid "New environment"
msgstr ""
+msgid "New epic"
+msgstr "ÐÐ¾Ð²Ð°Ñ Ñ†ÐµÐ»ÑŒ"
+
msgid "New file"
msgstr "Ðовый файл"
@@ -5483,6 +6395,9 @@ msgstr "ÐÐ¾Ð²Ð°Ñ Ð¼ÐµÑ‚ÐºÐ°"
msgid "New merge request"
msgstr "Ðовый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5493,7 +6408,7 @@ msgid "New schedule"
msgstr "Ðовое раÑпиÑание"
msgid "New snippet"
-msgstr "Ðовый фрагмент"
+msgstr "Ðовый пример кода"
msgid "New subgroup"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð¿Ð¾Ð´Ð³Ñ€ÑƒÐ¿Ð¿Ð°"
@@ -5510,6 +6425,9 @@ msgstr "Ðет"
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr "Ðет ответÑтвенного"
@@ -5519,6 +6437,9 @@ msgstr ""
msgid "No changes"
msgstr "Ðет изменений"
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5531,15 +6452,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr "Плановый Ñрок не указан"
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr "Файл не выбран"
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr "Файлы не найдены."
@@ -5547,11 +6477,14 @@ msgid "No issues for the selected time period."
msgstr ""
msgid "No labels with such name or description"
-msgstr ""
+msgstr "Ðет меток Ñ Ñ‚Ð°ÐºÐ¸Ð¼ наименованием или опиÑанием"
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5561,14 +6494,17 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
-msgid "No other labels with such name or description"
+msgid "No milestones to show"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No other labels with such name or description"
+msgstr "Ðет других меток Ñ Ñ‚Ð°ÐºÐ¸Ð¼ наименованием или опиÑанием"
+
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
-msgstr ""
+msgstr "Ðет приоритезированных меток Ñ Ñ‚Ð°ÐºÐ¸Ð¼ наименованием и опиÑанием"
msgid "No public groups"
msgstr ""
@@ -5585,6 +6521,9 @@ msgstr ""
msgid "No schedules"
msgstr "Ðет раÑпиÑаний"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5594,12 +6533,6 @@ msgstr ""
msgid "None"
msgstr "ПуÑто"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr "СлиÑние не допуÑкаетÑÑ"
@@ -5624,6 +6557,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "Обратите внимание, что маÑтер ветка автоматичеÑки защищена. %{link_to_protected_branches}"
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5637,7 +6573,7 @@ msgid "Note: Consider asking your GitLab administrator to configure %{github_int
msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
-msgstr ""
+msgstr "Ð’Ñ‹ уверены, что вы хотите отменить Ñоздание Ñтого комментариÑ?"
msgid "Notes|Collapse replies"
msgstr ""
@@ -5654,6 +6590,12 @@ msgstr ""
msgid "Notification events"
msgstr "Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ ÑобытиÑÑ…"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "ОбÑуждение закрыто"
@@ -5724,7 +6666,7 @@ msgid "November"
msgstr "ÐоÑбрь"
msgid "OK"
-msgstr ""
+msgstr "ОК"
msgid "Oct"
msgstr "Окт."
@@ -5740,33 +6682,48 @@ msgstr ""
msgid "One more item"
msgid_plural "%d more items"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Еще один Ñлемент"
+msgstr[1] "Еще %d Ñлементов"
+msgstr[2] "Еще %d Ñлементов"
+msgstr[3] "Еще %d Ñлементов"
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
-msgstr ""
+msgstr "Один или неÑколько проектов Bitbucket не могут быть импортировать в GitLab, потому что они иÑпользуют Subversion или Mercurial Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑ€ÑиÑми, а не Git."
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
-msgstr ""
+msgstr "Один или неÑколько проектов Google Code не могут быть импортированы в GitLab, поÑкольку они иÑпользуют Subversion или Mercurial Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑ€ÑиÑми, а не Git."
msgid "Only admins"
+msgstr "Только админиÑтраторы"
+
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only policy:"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr "Только учаÑтники проекта могут оÑтавлÑÑ‚ÑŒ комментарии."
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
+msgstr "Открыть"
+
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
msgstr ""
msgid "Open in Xcode"
@@ -5788,7 +6745,7 @@ msgid "Opened MR"
msgstr ""
msgid "Opened issues"
-msgstr ""
+msgstr "Открытые обÑуждениÑ"
msgid "OpenedNDaysAgo|Opened"
msgstr "Открыто"
@@ -5802,16 +6759,13 @@ msgstr "Операции"
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5851,14 +6805,20 @@ msgid "Package information"
msgstr ""
msgid "Package was removed"
-msgstr ""
+msgstr "Пакет был удален"
msgid "Packages"
-msgstr ""
+msgstr "Пакеты"
msgid "Pages"
msgstr "Страницы"
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "ПоÑледнÑÑ Â»"
@@ -5871,20 +6831,35 @@ msgstr "ПредыдущаÑ"
msgid "Pagination|« First"
msgstr "« ПерваÑ"
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr "ЧаÑÑ‚ÑŒ изменений запроÑа на ÑлиÑние"
msgid "Password"
msgstr "Пароль"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path, transfer, remove"
-msgstr ""
+msgstr "Путь, перемещение, удаление"
msgid "Path:"
-msgstr ""
+msgstr "Путь:"
msgid "Pause"
msgstr "ПриоÑтановить"
@@ -5898,9 +6873,6 @@ msgstr "В ожидании"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5911,11 +6883,17 @@ msgid "Permissions"
msgstr "Права доÑтупа"
msgid "Permissions, LFS, 2FA"
-msgstr ""
+msgstr "РазрешениÑ, LFS, 2FA"
msgid "Personal Access Token"
msgstr "ПерÑональный Токен ДоÑтупа"
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
@@ -6064,7 +7042,7 @@ msgid "Pipeline|Specify variable values to be used in this run. The values speci
msgstr ""
msgid "Pipeline|Stages"
-msgstr ""
+msgstr "Стадии"
msgid "Pipeline|Status"
msgstr ""
@@ -6102,6 +7080,9 @@ msgstr "PlantUML"
msgid "Play"
msgstr "ЗапуÑк"
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6114,9 +7095,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6129,6 +7116,9 @@ msgstr "ПожалуйÑта, решите reCAPTCHA"
msgid "Please try again"
msgstr "ПожалуйÑта, попробуйте ещё раз"
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6151,7 +7141,7 @@ msgid "Prevent adding new members to project membership within this group"
msgstr ""
msgid "Preview"
-msgstr ""
+msgstr "Предварительный проÑмотр"
msgid "Preview payload"
msgstr ""
@@ -6171,6 +7161,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr "Приватный - ДоÑтуп к проекту должен предоÑтавлÑÑ‚ÑŒÑÑ Ñвно каждому пользователю."
@@ -6184,17 +7177,26 @@ msgid "Profile"
msgstr "Профиль"
msgid "Profile Settings"
-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 ""
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 "Ð’Ñ‹ ÑобираетеÑÑŒ изменить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{currentUsernameBold} на %{newUsernameBold}. Профиль и проекты будут перенаправлены в проÑтранÑтво имен %{newUsername}, но Ñто перенаправление переÑтанет дейÑтвовать, как только проÑтранÑтво имён %{currentUsername} будет зарегиÑтрировано другим пользователем или группой. ПожалуйÑта, как можно Ñкорее, обновите указатели на Ñвои удаленные репозитории Git."
+
+msgid "Profiles|@username"
msgstr ""
msgid "Profiles|Account scheduled for removal."
msgstr "Ð£Ñ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ запланирована к удалению."
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6210,15 +7212,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr "Изменить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Текущий путь: %{path}"
@@ -6237,6 +7254,9 @@ msgstr "Удалить Ñвою учетную запиÑÑŒ?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Удаление учетной запиÑи приведет к Ñледующим поÑледÑтвиÑм:"
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6246,6 +7266,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Ðеверный пароль"
@@ -6282,19 +7308,22 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
-msgstr ""
+msgstr "Это не выглÑдит как публичный SSH-ключ, вы уверены, что вы хотите добавить его?"
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6303,10 +7332,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6333,12 +7365,15 @@ msgstr "Ошибка Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ - %
msgid "Profiles|Username successfully changed"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÑпешно изменено"
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6357,16 +7392,19 @@ msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ прав на удаление Ñтого пользоÐ
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "Перед удалением учётной запиÑи, вам необходимо передать право Ð²Ð»Ð°Ð´ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ удалить Ñти группы."
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ ÑвлÑетÑÑ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†ÐµÐ¼ Ñледующих групп:"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6375,6 +7413,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ"
@@ -6406,16 +7450,16 @@ msgid "Project Badges"
msgstr "Значки Проекта"
msgid "Project URL"
-msgstr ""
+msgstr "ÐÐ´Ñ€ÐµÑ ÐŸÑ€Ð¾ÐµÐºÑ‚Ð°"
msgid "Project access must be granted explicitly to each user."
msgstr "ДоÑтуп к проекту должен предоÑтавлÑÑ‚ÑŒÑÑ Ñвно каждому пользователю."
msgid "Project avatar"
-msgstr ""
+msgstr "Ðватар проекта"
msgid "Project avatar in repository: %{link}"
-msgstr ""
+msgstr "Ðватар проекта в репозитории: %{link}"
msgid "Project details"
msgstr "Детали проекта"
@@ -6432,12 +7476,18 @@ msgstr "ИÑтек Ñрок дейÑÑ‚Ð²Ð¸Ñ ÑÑылки на проект. СÐ
msgid "Project export started. A download link will be sent by email."
msgstr "Ðачат ÑкÑпорт проекта. СÑылка Ð´Ð»Ñ ÑÐºÐ°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ отправлена по Ñлектронной почте."
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "ПодпиÑатьÑÑ"
@@ -6550,7 +7600,7 @@ msgid "ProjectsDropdown|Sorry, no projects matched your search"
msgstr "К Ñожалению, по вашему запроÑу проекты не найдены"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "Эта функциональноÑÑ‚ÑŒ требует поддержки localStorage в вашем браузере"
msgid "PrometheusAlerts|Add alert"
msgstr ""
@@ -6582,9 +7632,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr "ВремÑ"
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "Были найдены %{exporters} Ñ %{metrics}"
@@ -6609,6 +7656,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "Определение и наÑтройка метрик..."
@@ -6738,6 +7788,9 @@ msgstr "Провайдер"
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "Публичный - Группу и включённые в неё проекты могут видеть вÑе, без какой-либо проверки подлинноÑти."
@@ -6748,10 +7801,10 @@ msgid "Public pipelines"
msgstr ""
msgid "Pull"
-msgstr ""
+msgstr "Получить"
msgid "Push"
-msgstr ""
+msgstr "Отправить"
msgid "Push Rules"
msgstr ""
@@ -6777,21 +7830,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "БыÑтрые дейÑÑ‚Ð²Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ иÑпользоватьÑÑ Ð² опиÑании обÑуждений и комментариÑÑ…."
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "Подробнее"
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
-msgstr "ИнÑтрукциÑ"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6802,7 +7864,7 @@ msgid "Reference:"
msgstr "СÑылка:"
msgid "Refresh"
-msgstr ""
+msgstr "Обновить"
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
@@ -6820,6 +7882,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr "РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ / Вход"
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "ЗарегиÑтрируйте и проÑмотрите ваши обработчики заданий Ð´Ð»Ñ Ñтой группы."
@@ -6850,6 +7915,12 @@ msgstr "СвÑзанные Влитые ЗапроÑÑ‹"
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "Ðапомнить позже"
@@ -6859,6 +7930,12 @@ msgstr "Удалить"
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Удалить аватар"
@@ -6889,9 +7966,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6952,6 +8035,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6970,6 +8059,9 @@ msgstr ""
msgid "Request Access"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð¾Ñтупа"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6979,12 +8071,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr "СброÑить ключ доÑтупа проверки работоÑпоÑобноÑти"
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "СброÑить ключ региÑтрации обработчиков заданий"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6994,23 +8101,35 @@ msgstr ""
msgid "Resolve discussion"
msgstr "Закрыть диÑкуÑÑию"
-msgid "Response metrics (AWS ELB)"
+msgid "Resolved"
msgstr ""
-msgid "Response metrics (Custom)"
+msgid "Response"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr "Метрики откликов (AWS ELB)"
+
+msgid "Response metrics (Custom)"
+msgstr "Метрики откликов (наÑтраиваемые)"
+
msgid "Response metrics (HA Proxy)"
+msgstr "Метрики откликов (HA Proxy)"
+
+msgid "Response metrics (NGINX Ingress VTS)"
msgstr ""
msgid "Response metrics (NGINX Ingress)"
-msgstr ""
+msgstr "Метрики откликов (NGINX Ingress)"
msgid "Response metrics (NGINX)"
+msgstr "Метрики откликов (NGINX)"
+
+msgid "Restart Terminal"
msgstr ""
msgid "Resume"
-msgstr ""
+msgstr "Продолжить"
msgid "Retry"
msgstr "Повторить"
@@ -7021,9 +8140,6 @@ msgstr "Повторить Ñто фоновое задание"
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] "Показать значение"
@@ -7031,6 +8147,9 @@ msgstr[1] "Показать значениÑ"
msgstr[2] "Показать значениÑ"
msgstr[3] "Показать значениÑ"
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Отменить Ñто коммит"
@@ -7038,13 +8157,13 @@ msgid "Revert this merge request"
msgstr "Отменить Ñтот Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "Review"
-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 ""
msgid "Reviewing"
-msgstr ""
+msgstr "Рецензировать"
msgid "Reviewing (merge request !%{mergeRequestId})"
msgstr ""
@@ -7058,6 +8177,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -7085,6 +8207,9 @@ msgstr "Обработчики заданий"
msgid "Runners API"
msgstr "API обработчиков заданий"
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Обработчики заданий могут запуÑкатьÑÑ Ñƒ отдельных пользователей, Ñерверах и даже на вашей локальной машине."
@@ -7118,7 +8243,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7137,6 +8262,9 @@ msgid "SSL Verification"
msgstr ""
msgid "Save"
+msgstr "Сохранить"
+
+msgid "Save Changes"
msgstr ""
msgid "Save application"
@@ -7148,6 +8276,9 @@ msgstr "Сохранить изменениÑ"
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Сохранить раÑпиÑание Ñборочной лини"
@@ -7184,6 +8315,9 @@ msgstr ""
msgid "Search"
msgstr "ПоиÑк"
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7196,6 +8330,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr "ПоиÑк проектов, обÑуждений и Ñ‚.д."
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7265,7 +8402,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7274,10 +8411,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7295,6 +8435,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7304,6 +8456,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7331,6 +8489,9 @@ msgstr "Выбрать ответÑтвенного"
msgid "Select branch/tag"
msgstr "Выбрать ветку/тег"
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr "Выбрать проект"
@@ -7364,7 +8525,13 @@ msgstr ""
msgid "Send email"
msgstr "Отправить Ñлектронное пиÑьмо"
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
+msgstr "ОтправлÑÑ‚ÑŒ данные об иÑпользовании"
+
+msgid "Sentry API URL"
msgstr ""
msgid "Sep"
@@ -7376,6 +8543,48 @@ msgstr "СентÑбрь"
msgid "Server version"
msgstr "ВерÑÐ¸Ñ Ñервера"
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7406,6 +8615,9 @@ msgstr "УÑтановить макÑимальное Ð²Ñ€ÐµÐ¼Ñ ÑеанÑа д
msgid "Set notification email for abuse reports."
msgstr "ÐаÑтроить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте Ð´Ð»Ñ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ злоупотреблениÑÑ…."
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7421,6 +8633,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7437,7 +8652,7 @@ msgid "SetStatusModal|Edit status"
msgstr ""
msgid "SetStatusModal|Remove status"
-msgstr ""
+msgstr "Удалить ÑтатуÑ"
msgid "SetStatusModal|Set a status"
msgstr ""
@@ -7484,10 +8699,10 @@ msgstr "Показать команду"
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7522,17 +8737,26 @@ msgid "Sidebar|Weight"
msgstr ""
msgid "Sign in"
-msgstr ""
+msgstr "Вход"
msgid "Sign in / Register"
+msgstr "Вход / РегиÑтрациÑ"
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr "Выйти"
@@ -7542,6 +8766,9 @@ msgstr "ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð°"
msgid "Sign-up restrictions"
msgstr "ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ñ€ÐµÐ³Ð¸Ñтрации"
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7563,8 +8790,17 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
-msgstr "Сниппеты"
+msgstr "Примеры кода"
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
msgid "Something went wrong on our end"
msgstr "Что-то пошло не так Ñ Ð½Ð°ÑˆÐµÐ¹ Ñтороны"
@@ -7575,6 +8811,9 @@ msgstr "Что-то пошло не так Ñ Ð½Ð°ÑˆÐµÐ¹ Ñтороны."
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7584,9 +8823,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr "Что-то пошло не так при переключении кнопки"
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7605,6 +8850,9 @@ msgstr "Что-то пошло не так при получении проекÑ
msgid "Something went wrong while fetching the registry list."
msgstr "Что-то пошло не так при получении ÑпиÑка рееÑтров."
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7629,9 +8877,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr "Сортировать по"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr "Уровень доÑтупа, по возраÑтанию"
@@ -7677,8 +8931,8 @@ msgstr "Ðаименее популÑрный"
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
-msgstr "Веха"
+msgid "SortOptions|Milestone due date"
+msgstr ""
msgid "SortOptions|Milestone due later"
msgstr "Веха, наÑÑ‚ÑƒÐ¿Ð°ÑŽÑ‰Ð°Ñ Ð¿Ð¾Ð·Ð´Ð½ÐµÐµ"
@@ -7710,6 +8964,9 @@ msgstr "Старейшие из Ñозданных"
msgid "SortOptions|Oldest joined"
msgstr "Старейшие из приÑоединившихÑÑ"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr "Старейшие из заходивших"
@@ -7722,6 +8979,9 @@ msgstr "ПопулÑронÑÑ‚ÑŒ"
msgid "SortOptions|Priority"
msgstr "Приоритет"
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr "Ðедавно заходившие"
@@ -7749,6 +9009,9 @@ msgstr "ИÑходный код"
msgid "Source is not available"
msgstr "ИÑходный текÑÑ‚ недоÑтупен"
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr "Спам Логи"
@@ -7764,6 +9027,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr "Укажите Ñледующий URL во Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñтройки Gitlab Runner:"
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7800,16 +9066,34 @@ msgstr "ÐктивноÑÑ‚ÑŒ в избранных проектах"
msgid "Starred projects"
msgstr "Избранные проекты"
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "Ðачать %{new_merge_request} Ñ Ñтих изменений"
msgid "Start a review"
-msgstr ""
+msgstr "Ðачать рецензию"
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
+msgstr "Дата начала"
+
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
msgid "Start the Runner!"
@@ -7821,6 +9105,15 @@ msgstr ""
msgid "Started"
msgstr "Запущен"
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7830,6 +9123,12 @@ msgstr ""
msgid "Status"
msgstr "СтатуÑ"
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7845,6 +9144,9 @@ msgstr "ОÑтановлен"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr "Хранилище"
@@ -7860,6 +9162,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7875,10 +9180,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7891,9 +9280,12 @@ msgid "System Hooks"
msgstr "СиÑтемные Обработчики"
msgid "System Info"
+msgstr "Ð¡Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾ ÑиÑтеме"
+
+msgid "System default (%{default})"
msgstr ""
-msgid "System header and footer:"
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7902,12 +9294,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] "Тег (%{tag_count})"
-msgstr[1] "Тегов (%{tag_count})"
-msgstr[2] "Тегов (%{tag_count})"
-msgstr[3] "Тегов (%{tag_count})"
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "Теги"
@@ -7997,9 +9388,15 @@ msgid "Team"
msgstr "Команда"
msgid "Template"
-msgstr ""
+msgstr "Шаблон"
msgid "Templates"
+msgstr "Шаблоны"
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
msgstr ""
msgid "Terms of Service Agreement and Privacy Policy"
@@ -8017,9 +9414,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -8056,6 +9459,9 @@ msgstr "Импорт будет отключен поÑле %{timeout}. Ð”Ð»Ñ Ñ
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Ð¡Ñ‚Ð°Ð´Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ времÑ, которое потребуетÑÑ Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾ Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¾Ð±Ñуждению вехи, или Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð½Ð° вашу доÑку задач. Ðачните Ñоздавать обÑуждениÑ, чтобы увидеть ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой Ñтадии."
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr "МакÑимально допуÑтимый размер файла ÑоÑтавлÑет 200 Кб."
@@ -8134,16 +9540,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Среднее значение в Ñ€Ñду. Пример: между 3, 5, 9, Ñреднее 5, между 3, 5, 7, 8, Ñреднее (5+7)/2 = 6."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr "Ðет обÑуждений, которые можно показать"
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8179,12 +9603,21 @@ msgstr "При подпиÑке на Ñту метку произошла оши
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "Этот ÑкземплÑÑ€ GitLab пока не предоÑтавлÑет никаких общих обработчиков заданий. ÐдминиÑтраторы ÑкземплÑров могут региÑтрировать общие обработчики заданий в Ñекции админиÑтрированиÑ."
@@ -8212,13 +9645,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr "Этот каталог"
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8281,10 +9717,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "Это фоновое задание находитÑÑ Ð² ÑоÑтоÑнии Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð¸ ожидает запуÑка процеÑÑа иÑполнениÑ"
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8293,7 +9729,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr "Это фоновое задание требует ручных дейÑтвий"
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8314,6 +9750,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr "Этот проект"
@@ -8341,7 +9786,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8353,7 +9798,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8405,7 +9850,7 @@ msgid "Timeago|%s days remaining"
msgstr "ОÑталоÑÑŒ %s дней"
msgid "Timeago|%s hours ago"
-msgstr ""
+msgstr "%s чаÑов назад"
msgid "Timeago|%s hours remaining"
msgstr "ОÑталоÑÑŒ %s чаÑов"
@@ -8423,7 +9868,7 @@ msgid "Timeago|%s months remaining"
msgstr "ОÑталоÑÑŒ %s меÑÑцев"
msgid "Timeago|%s seconds ago"
-msgstr ""
+msgstr "%s Ñекунд назад"
msgid "Timeago|%s seconds remaining"
msgstr "ОÑталоÑÑŒ %s Ñекунд(Ñ‹)"
@@ -8441,37 +9886,37 @@ msgid "Timeago|%s years remaining"
msgstr "ОÑталоÑÑŒ %s лет"
msgid "Timeago|1 day ago"
-msgstr ""
+msgstr "1 день назад"
msgid "Timeago|1 day remaining"
msgstr "ОÑталÑÑ Ð´ÐµÐ½ÑŒ"
msgid "Timeago|1 hour ago"
-msgstr ""
+msgstr "1 Ñ‡Ð°Ñ Ð½Ð°Ð·Ð°Ð´"
msgid "Timeago|1 hour remaining"
msgstr "ОÑталÑÑ Ñ‡Ð°Ñ"
msgid "Timeago|1 minute ago"
-msgstr ""
+msgstr "1 минуту назад"
msgid "Timeago|1 minute remaining"
msgstr "ОÑталаÑÑŒ одна минута"
msgid "Timeago|1 month ago"
-msgstr ""
+msgstr "1 меÑÑц назад"
msgid "Timeago|1 month remaining"
msgstr "ОÑталÑÑ Ð¼ÐµÑÑц"
msgid "Timeago|1 week ago"
-msgstr ""
+msgstr "1 неделю назад"
msgid "Timeago|1 week remaining"
msgstr "ОÑталаÑÑŒ неделÑ"
msgid "Timeago|1 year ago"
-msgstr ""
+msgstr "1 год назад"
msgid "Timeago|1 year remaining"
msgstr "ОÑталÑÑ Ð³Ð¾Ð´"
@@ -8519,10 +9964,10 @@ msgid "Timeago|in 1 year"
msgstr "через год"
msgid "Timeago|just now"
-msgstr ""
+msgstr "Только что"
msgid "Timeago|right now"
-msgstr ""
+msgstr "ПрÑмо ÑейчаÑ"
msgid "Timeout"
msgstr ""
@@ -8548,14 +9993,23 @@ msgid "Tip:"
msgstr "Совет:"
msgid "Title"
+msgstr "Заголовок"
+
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
msgstr ""
msgid "To GitLab"
msgstr "Ð’ GitLab"
-msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgid "To access this domain create a new DNS record"
msgstr ""
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr "Чтобы добавить SSH-ключ вам нужно %{generate_link_start}Ñгенерировать его%{link_end} или иÑпользовать %{existing_link_start}ÑущеÑтвующий ключ%{link_end}."
+
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>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -8595,13 +10049,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8610,6 +10079,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Чтобы начать выполнÑÑ‚ÑŒ Ñвои заданиÑ, вы можете добавить обработчик заданий в вашу группу"
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8619,11 +10091,14 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
msgid "Today"
-msgstr ""
+msgstr "СегоднÑ"
msgid "Todo"
msgstr "Дела"
@@ -8634,13 +10109,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
-msgid "Toggle commit description"
+msgid "Toggle comments for this file"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit description"
+msgstr "Переключить опиÑание коммита"
+
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8659,13 +10137,13 @@ msgid "Token"
msgstr ""
msgid "Tomorrow"
-msgstr ""
+msgstr "Завтра"
msgid "Too many changes to show."
-msgstr ""
+msgstr "Слишком много изменений Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
msgid "Total Contributions"
-msgstr ""
+msgstr "Общий вклад"
msgid "Total Time"
msgstr "Общее времÑ"
@@ -8694,9 +10172,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8706,6 +10181,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr "ЗапуÑтить Ñто дейÑтвие вручную"
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8715,9 +10196,15 @@ msgstr ""
msgid "Try again"
msgstr "Попробовать Ñнова"
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8730,21 +10217,27 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "URL"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Ðе удаетÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ отличиÑ. %{button_try_again}"
-msgid "Unable to save your changes"
-msgstr ""
-
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8793,6 +10286,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr "Ðеподтверждено"
@@ -8803,17 +10299,23 @@ msgid "Upcoming"
msgstr ""
msgid "Update"
+msgstr "Обновить"
+
+msgid "Update failed"
msgstr ""
msgid "Update now"
msgstr ""
msgid "Update your group name, description, avatar, and visibility."
-msgstr ""
+msgstr "Обновить наименование вашей группы, её опиÑание, аватар и видимоÑÑ‚ÑŒ."
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8832,15 +10334,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "Загрузить новый файл"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "Загрузить файл"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "кликните Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr "ГолоÑа \"за\""
@@ -8871,9 +10388,15 @@ msgstr "ИÑпользуйте Ñледующий токен региÑтрацÐ
msgid "Use your global notification setting"
msgstr "ИÑпользуютÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ‹Ð¹ наÑтройки уведомлений"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8893,52 +10416,88 @@ msgid "UserProfile|Already reported for abuse"
msgstr ""
msgid "UserProfile|Contributed projects"
-msgstr ""
+msgstr "Вклад в проекты"
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
msgstr ""
msgid "UserProfile|Snippets"
+msgstr "Примеры кода"
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
msgstr ""
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr "Пользователи"
-msgid "Variables"
-msgstr "Переменные"
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr "Переменные применÑÑŽÑ‚ÑÑ Ðº Ñреде через обработчики заданий. Их можно защитить, Ð´ÐµÐ»Ð°Ñ Ð¸Ñ… доÑтупными только защищенным ветвÑм или меткам. Ð’Ñ‹ можете иÑпользовать переменные Ð´Ð»Ñ Ð¿Ð°Ñ€Ð¾Ð»ÐµÐ¹, Ñекретных ключей и прочего."
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
msgid "Various container registry settings."
msgstr ""
@@ -8946,17 +10505,23 @@ msgstr ""
msgid "Various email settings."
msgstr "Различные наÑтройки Ñлектронной почты."
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr "Различные наÑтройки, которые влиÑÑŽÑ‚ на производительноÑÑ‚ÑŒ GitLab."
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr "Проверено"
msgid "Version"
-msgstr ""
+msgstr "ВерÑиÑ"
msgid "View %{alerts}"
msgstr ""
@@ -8964,11 +10529,17 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
msgid "View epics list"
-msgstr ""
+msgstr "Показать ÑпиÑок целей"
msgid "View file @ "
msgstr "ПроÑмотр файла @ "
@@ -8977,7 +10548,7 @@ msgid "View group labels"
msgstr "ПроÑмотр меток группы"
msgid "View issue"
-msgstr ""
+msgstr "ПроÑмотр обÑуждениÑ"
msgid "View it on GitLab"
msgstr ""
@@ -9003,6 +10574,9 @@ msgstr "ПроÑмотр заменённого файла @ "
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -9027,6 +10601,12 @@ msgstr "Публичный"
msgid "VisibilityLevel|Unknown"
msgstr "Ðе определен"
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9034,7 +10614,7 @@ msgid "Vulnerability|Confidence"
msgstr ""
msgid "Vulnerability|Description"
-msgstr ""
+msgstr "ОпиÑание"
msgid "Vulnerability|File"
msgstr ""
@@ -9051,41 +10631,62 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Хотите увидеть данные? ОбратитеÑÑŒ к админиÑтратору за доÑтупом."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ð¾ Ñтапу отÑутÑтвует."
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Мы хотим быть уверены, что Ñто вы, пожалуйÑта, подтвердите, что вы не робот."
msgid "Web IDE"
msgstr "Web IDE"
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr "Web терминал"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
-msgstr ""
+msgstr "Веб-обработчики позволÑÑŽÑ‚ вам вызывать Ð°Ð´Ñ€ÐµÑ URL еÑли, например, отправлен новый код или Ñоздано новое обÑуждение. Ð’Ñ‹ можете наÑтроить веб-обработчики так, чтобы они реагировали на определённые ÑобытиÑ, такие как отправки кода, обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ запроÑÑ‹ на ÑлиÑние. Групповые веб-обработчики применÑÑŽÑ‚ÑÑ ÐºÐ¾ вÑем проектам в группе и позволÑÑŽÑ‚ вам Ñтандартизовать функциональноÑÑ‚ÑŒ веб-обработчиков Ð´Ð»Ñ Ð²Ñей вашей группы."
msgid "Weeks"
msgstr ""
msgid "Weight"
-msgstr ""
+msgstr "ВеÑ"
msgid "Weight %{weight}"
-msgstr ""
+msgstr "Ð’ÐµÑ %{weight}"
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Когда процеÑÑ Runner заблокирован, он не может быть назначен другим проектам"
@@ -9096,6 +10697,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9184,7 +10788,7 @@ msgid "WikiNewPageTitle|New Wiki Page"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð’Ð¸ÐºÐ¸ Страница"
msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
-msgstr "Ð’Ñ‹ уверены что хотите удалить Ñту Ñтраницу?"
+msgstr "Ð’Ñ‹ уверены, что вы хотите удалить Ñту Ñтраницу?"
msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
@@ -9237,12 +10841,21 @@ msgstr "Страницы"
msgid "Wiki|Wiki Pages"
msgstr "Вики Страницы"
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr "Отменить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð¾Ñтупа"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr "Да"
@@ -9253,6 +10866,9 @@ msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
msgid "Yesterday"
+msgstr "Вчера"
+
+msgid "You"
msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
@@ -9273,6 +10889,9 @@ msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ передать проект %{project_full
msgid "You are on a read-only GitLab instance."
msgstr "Ð’Ñ‹ иÑпользуете GitLab в режиме только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ."
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9283,7 +10902,7 @@ msgid "You can also star a label to make it a priority label."
msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
-msgstr ""
+msgstr "Ð’Ñ‹ можете легко внеÑти Ñвой вклад в них, попроÑив приÑоединить Ð²Ð°Ñ Ðº Ñтим группам."
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
@@ -9297,6 +10916,9 @@ msgstr "Ð’Ñ‹ можете добавлÑÑ‚ÑŒ только файлы, когда
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9315,6 +10937,9 @@ msgstr "Ð’Ñ‹ не можете запиÑывать на Ñтот Ñкземпл
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9324,12 +10949,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr "Ð’Ñ‹ доÑтигли Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð² вашем проекте"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9339,16 +10970,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr "Вам нужно разрешение."
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9388,6 +11025,9 @@ msgid "You're receiving this email because of your account on %{host}. %{manage_
msgstr "Ð’Ñ‹ получили Ñто Ñлектронное пиÑьмо из Ñвоей учетной запиÑи %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgid "YouTube"
+msgstr "YouTube"
+
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your Groups"
@@ -9400,17 +11040,23 @@ msgid "Your Projects (default)"
msgstr "Ваши проекты (по умолчанию)"
msgid "Your Projects' Activity"
-msgstr "ÐктивноÑÑ‚ÑŒ в ваших проектов"
+msgstr "ÐктивноÑÑ‚ÑŒ ваших проектов"
msgid "Your Todos"
msgstr "Ваши дела"
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9423,12 +11069,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr "Ваш комментарий не будет виден вÑем."
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "Ваши группы"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "Ваше имÑ"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr "Ваши проекты"
@@ -9438,12 +11096,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr "назначить ÑебÑ"
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr "Ð¸Ð¼Ñ Ð²ÐµÑ‚Ð²Ð¸"
@@ -9544,6 +11208,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9551,7 +11218,7 @@ msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
-msgstr ""
+msgstr "ОпиÑание"
msgid "ciReport|Dismiss vulnerability"
msgstr ""
@@ -9559,6 +11226,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9685,6 +11358,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9707,25 +11383,44 @@ msgstr[1] "дней"
msgstr[2] "дней"
msgstr[3] "дней"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr "отключено"
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "done"
msgstr ""
msgid "draft"
msgid_plural "drafts"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "черновик"
+msgstr[1] "черновиков"
+msgstr[2] "черновиков"
+msgstr[3] "черновики"
msgid "enabled"
msgstr "включено"
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9735,27 +11430,45 @@ msgstr ""
msgid "from"
msgstr ""
-msgid "help"
+msgid "group"
msgstr ""
+msgid "help"
+msgstr "помощь"
+
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "завершенный ÑкземплÑÑ€"
+msgstr[1] "завершенных ÑкземплÑров"
+msgstr[2] "завершенных ÑкземплÑров"
+msgstr[3] "завершенные ÑкземплÑры"
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -9766,14 +11479,32 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
msgid "latest version"
-msgstr ""
+msgstr "поÑледнÑÑ Ð²ÐµÑ€ÑиÑ"
msgid "license management"
msgstr ""
@@ -9781,6 +11512,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -9788,9 +11522,21 @@ msgstr[1] "запроÑов на ÑлиÑние"
msgstr[2] "запроÑов на ÑлиÑние"
msgstr[3] "запроÑов на ÑлиÑние"
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9806,20 +11552,20 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
msgid "mrWidget|Approve"
-msgstr ""
+msgstr "Одобрить"
msgid "mrWidget|Approved by"
-msgstr ""
+msgstr "Одобрено"
msgid "mrWidget|Cancel automatic merge"
msgstr "Отменить автоматичеÑкое ÑлиÑние"
@@ -9848,6 +11594,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr "Создать обÑуждение Ð´Ð»Ñ ÐµÐ³Ð¾ поÑледующего решениÑ"
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9885,10 +11634,10 @@ msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved"
-msgstr ""
+msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние одобрен"
msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
+msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние одобрен; вы можете дополнительно одобрить"
msgid "mrWidget|Merged by"
msgstr ""
@@ -9897,7 +11646,7 @@ msgid "mrWidget|No Approval required"
msgstr ""
msgid "mrWidget|No Approval required; you can still approve"
-msgstr ""
+msgstr "Одобрение не требуетÑÑ, Ñ…Ð¾Ñ‚Ñ Ð²Ñ‹ можете Ñто делать"
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -9920,12 +11669,6 @@ msgstr "Обновить ÑейчаÑ"
msgid "mrWidget|Refreshing now"
msgstr "ОбновлÑетÑÑ ÑейчаÑ"
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9934,17 +11677,17 @@ msgstr ""
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ТребуетÑÑ ÐµÑ‰Ðµ 1 разрешение"
+msgstr[1] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений"
+msgstr[2] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений"
+msgstr[3] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ТребуетÑÑ ÐµÑ‰Ðµ 1 разрешение пользователÑ"
+msgstr[1] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений пользователÑ"
+msgstr[2] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений пользователÑ"
+msgstr[3] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений пользователÑ"
msgid "mrWidget|Resolve conflicts"
msgstr "Разрешить конфликты"
@@ -9976,19 +11719,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9997,6 +11740,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -10009,10 +11755,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -10028,14 +11774,26 @@ msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
msgid "n/a"
-msgstr ""
+msgstr "н/д"
msgid "new merge request"
msgstr "новый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "email Ð´Ð»Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ð¹"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr "или"
@@ -10059,15 +11817,24 @@ msgstr "пароль"
msgid "personal access token"
msgstr "токен Ð´Ð»Ñ Ð¿ÐµÑ€Ñонального доÑтупа"
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
msgid "project"
msgid_plural "projects"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "проект"
+msgstr[1] "проектов"
+msgstr[2] "проектов"
+msgstr[3] "проектов"
+
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
msgid "remaining"
msgstr "оÑталоÑÑŒ"
@@ -10081,6 +11848,9 @@ msgstr "убрать плановый Ñрок"
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
@@ -10088,22 +11858,49 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr "иÑходный текÑÑ‚"
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
+msgstr "запущено"
+
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
msgstr ""
msgid "this document"
msgstr "Ñтот документ"
msgid "to help your contributors communicate effectively!"
+msgstr "чтобы помочь вашим учаÑтникам взаимодейÑтвовать Ñффективнее!"
+
+msgid "triggered"
msgstr ""
-msgid "toggle collapse"
+msgid "updated"
msgstr ""
msgid "username"
@@ -10112,9 +11909,15 @@ msgstr "Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10125,3 +11928,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index b8feb7a634b..a76359352a9 100644
--- a/locale/sk_SK/gitlab.po
+++ b/locale/sk_SK/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:19\n"
+"PO-Revision-Date: 2019-02-11 08:09\n"
msgid " Status"
msgstr ""
@@ -35,22 +35,17 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -66,12 +61,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -101,6 +92,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -158,6 +156,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -181,12 +182,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -196,9 +203,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -208,6 +212,33 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -227,12 +258,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -322,10 +362,13 @@ msgstr[3] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -367,7 +410,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -415,6 +458,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -451,10 +497,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -466,7 +512,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -499,6 +548,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -508,6 +560,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -523,9 +578,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -559,12 +611,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -577,12 +659,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -596,6 +708,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -605,9 +720,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -629,6 +750,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -656,40 +780,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -698,6 +792,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -770,12 +867,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -806,9 +912,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -839,6 +990,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -851,6 +1017,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -860,12 +1029,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -881,6 +1062,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -899,6 +1083,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -908,6 +1095,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -935,6 +1125,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -947,6 +1140,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -962,6 +1158,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -989,15 +1188,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -1031,13 +1221,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1223,6 +1425,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1232,13 +1440,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1392,21 +1593,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1443,12 +1659,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1458,18 +1668,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1482,12 +1701,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1509,10 +1737,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1524,9 +1752,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1548,6 +1782,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1566,6 +1806,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1659,7 +1902,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1680,6 +1923,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1719,28 +1968,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1764,27 +2037,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1794,6 +2082,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1806,6 +2097,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1833,6 +2127,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1905,6 +2208,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1920,6 +2229,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1956,6 +2271,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -2034,6 +2352,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2076,12 +2397,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2097,6 +2424,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2109,6 +2448,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2136,6 +2478,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2148,9 +2493,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2170,16 +2524,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2243,6 +2596,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2270,12 +2626,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2309,6 +2671,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2357,6 +2722,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2372,7 +2740,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2408,13 +2776,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2423,6 +2794,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2447,9 +2821,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2471,6 +2842,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2480,6 +2854,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2519,6 +2896,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2585,9 +2965,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2603,6 +2980,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2612,6 +2992,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2642,6 +3028,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2651,6 +3040,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2663,6 +3055,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2672,6 +3067,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2681,6 +3082,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2711,6 +3115,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2847,6 +3257,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2874,6 +3287,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2904,6 +3320,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2925,15 +3347,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2961,6 +3392,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2985,6 +3422,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -3000,9 +3440,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3012,6 +3458,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -3021,6 +3473,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -3039,6 +3494,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -3063,6 +3521,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3078,9 +3539,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3093,6 +3563,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3108,9 +3584,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3186,6 +3680,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3198,9 +3695,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3210,7 +3704,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3237,9 +3731,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3282,9 +3782,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3294,6 +3800,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3315,6 +3827,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3324,9 +3842,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3339,6 +3887,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3360,9 +3914,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3402,6 +3968,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3411,28 +3980,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3444,7 +4025,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3456,30 +4040,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3498,6 +4100,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3507,13 +4124,35 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3531,12 +4170,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3549,12 +4206,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3600,6 +4263,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3624,6 +4290,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3675,6 +4344,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3765,7 +4437,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3840,6 +4515,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3885,6 +4563,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3921,6 +4602,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3999,9 +4683,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -4029,9 +4722,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4062,6 +4761,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4086,6 +4788,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4131,13 +4836,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4149,37 +4857,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4206,6 +4911,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4305,6 +5013,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4318,7 +5029,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4327,6 +5038,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4384,6 +5098,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4414,9 +5131,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4435,12 +5158,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4465,6 +5200,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4480,15 +5218,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4504,6 +5257,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4535,6 +5291,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4550,9 +5309,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4571,6 +5348,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4604,6 +5396,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4622,6 +5420,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4661,10 +5465,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4679,12 +5483,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4764,6 +5574,9 @@ msgstr[3] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4779,6 +5592,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4794,15 +5610,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4942,6 +5782,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -5008,6 +5854,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -5038,6 +5887,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -5074,9 +5926,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5098,13 +5947,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5113,9 +5965,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5128,19 +5989,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5158,6 +6031,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5167,6 +6058,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5185,7 +6079,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5194,6 +6088,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5203,7 +6103,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5215,22 +6115,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5245,10 +6139,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5269,21 +6163,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5356,6 +6241,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5416,6 +6313,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5428,6 +6328,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5444,6 +6347,12 @@ msgstr[3] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5462,6 +6371,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5483,6 +6395,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5510,6 +6425,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5519,6 +6437,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5531,15 +6452,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5552,6 +6482,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5561,10 +6494,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5585,6 +6521,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5594,12 +6533,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5624,6 +6557,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5654,6 +6590,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5754,21 +6696,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5802,16 +6759,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5859,6 +6813,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5871,12 +6831,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5898,9 +6873,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5916,6 +6888,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6102,6 +7080,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6114,9 +7095,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6129,6 +7116,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6171,6 +7161,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6192,9 +7185,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6210,15 +7212,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6237,6 +7254,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6246,6 +7266,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6282,10 +7308,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6294,7 +7323,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6303,10 +7332,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6333,12 +7365,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6357,16 +7392,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6375,6 +7413,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6432,12 +7476,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6582,9 +7632,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6609,6 +7656,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6738,6 +7788,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6777,21 +7830,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6820,6 +7882,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6850,6 +7915,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6859,6 +7930,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6889,9 +7966,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6952,6 +8035,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6970,6 +8059,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6979,12 +8071,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6994,6 +8101,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -7003,12 +8116,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -7021,9 +8140,6 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
@@ -7031,6 +8147,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -7058,6 +8177,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -7085,6 +8207,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7118,7 +8243,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7139,6 +8264,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7148,6 +8276,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7184,6 +8315,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7196,6 +8330,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7265,7 +8402,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7274,10 +8411,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7295,6 +8435,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7304,6 +8456,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7331,6 +8489,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7364,9 +8525,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7376,6 +8543,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7406,6 +8615,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7421,6 +8633,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7484,10 +8699,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7527,12 +8742,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7542,6 +8766,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7563,9 +8790,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7575,6 +8811,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7584,9 +8823,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7605,6 +8850,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7629,9 +8877,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7677,7 +8931,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7710,6 +8964,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7722,6 +8979,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7749,6 +9009,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7764,6 +9027,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7800,6 +9066,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7809,9 +9081,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7821,6 +9105,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7830,6 +9123,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7845,6 +9144,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7860,6 +9162,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7875,10 +9180,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7893,7 +9282,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7902,12 +9294,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -8002,6 +9393,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -8017,9 +9414,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -8056,6 +9459,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8134,16 +9540,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8179,12 +9603,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8212,13 +9645,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8281,10 +9717,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8293,7 +9729,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8314,6 +9750,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8341,7 +9786,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8353,7 +9798,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8550,9 +9995,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8595,13 +10049,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8610,6 +10079,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8619,6 +10091,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8634,13 +10109,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8694,9 +10172,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8706,6 +10181,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8715,9 +10196,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8730,10 +10217,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8742,9 +10229,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8793,6 +10286,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8805,6 +10301,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8814,6 +10313,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8832,15 +10334,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8871,9 +10388,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8898,19 +10421,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8919,25 +10451,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8946,12 +10505,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8964,6 +10529,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -9003,6 +10574,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -9027,6 +10601,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9051,27 +10631,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9096,6 +10697,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9237,12 +10841,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9255,6 +10868,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9273,6 +10889,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9297,6 +10916,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9315,6 +10937,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9324,12 +10949,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9339,16 +10970,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9390,6 +11027,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9405,12 +11045,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9423,12 +11069,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9438,12 +11096,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9544,6 +11208,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9559,6 +11226,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9685,6 +11358,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9707,12 +11383,22 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "done"
msgstr ""
@@ -9726,6 +11412,15 @@ msgstr[3] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9735,21 +11430,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9766,9 +11479,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9781,6 +11512,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
@@ -9788,9 +11522,21 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9806,10 +11552,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9848,6 +11594,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9920,12 +11669,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9976,19 +11719,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9997,6 +11740,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -10009,10 +11755,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -10033,9 +11779,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -10059,6 +11817,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -10069,6 +11830,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -10081,6 +11848,9 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
@@ -10088,22 +11858,49 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -10112,9 +11909,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10125,3 +11928,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index e2282f23bea..3774bd3ad14 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sq\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:17\n"
+"PO-Revision-Date: 2019-02-11 08:07\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,10 +433,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -844,6 +1029,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -883,6 +1074,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -898,6 +1092,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
-msgid "Merge Request:"
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
-
-msgid "Metrics|Query"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index 4a1ed2a3b2c..85059aa0f90 100644
--- a/locale/sr_CS/gitlab.po
+++ b/locale/sr_CS/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sr-CS\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:19\n"
+"PO-Revision-Date: 2019-02-11 08:09\n"
msgid " Status"
msgstr ""
@@ -33,20 +33,17 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -60,11 +57,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -90,6 +84,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -141,6 +141,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -162,12 +165,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -177,9 +186,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -189,6 +195,30 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -207,12 +237,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -291,10 +330,13 @@ msgstr[2] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -336,7 +378,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -384,6 +426,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -420,10 +465,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -435,7 +480,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -468,6 +516,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -477,6 +528,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -492,9 +546,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -528,12 +579,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -546,12 +627,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -564,6 +675,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -573,9 +687,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -597,6 +717,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -624,40 +747,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -666,6 +759,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -738,12 +834,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -774,9 +879,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -807,6 +957,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -819,6 +984,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -828,12 +996,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -849,6 +1029,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -867,6 +1050,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -876,6 +1062,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -903,6 +1092,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -915,6 +1107,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -930,6 +1125,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -957,15 +1155,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -999,13 +1188,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1191,6 +1392,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1200,12 +1407,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1359,21 +1560,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1410,12 +1626,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1425,18 +1635,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1449,12 +1668,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1476,10 +1704,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1491,9 +1719,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1515,6 +1749,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1533,6 +1773,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1626,7 +1869,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1647,6 +1890,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1686,28 +1935,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1731,27 +2004,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1761,6 +2049,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1773,6 +2064,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1800,6 +2094,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1872,6 +2175,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1887,6 +2196,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1923,6 +2238,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -2001,6 +2319,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2043,12 +2364,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2064,6 +2391,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2076,6 +2415,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2103,6 +2445,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2115,9 +2460,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2136,15 +2490,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2208,6 +2562,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2235,12 +2592,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2274,6 +2637,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2322,6 +2688,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2337,7 +2706,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2373,13 +2742,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2388,6 +2760,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2412,9 +2787,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2436,6 +2808,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2445,6 +2820,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2484,6 +2862,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2550,9 +2931,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2568,6 +2946,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2577,6 +2958,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2607,6 +2994,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2616,6 +3006,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2628,6 +3021,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2637,6 +3033,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2646,6 +3048,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2676,6 +3081,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2811,6 +3222,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2838,6 +3252,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2868,6 +3285,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2889,15 +3312,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2925,6 +3357,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2949,6 +3387,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2964,9 +3405,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2976,6 +3423,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2985,6 +3438,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -3003,6 +3459,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -3027,6 +3486,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3042,9 +3504,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3057,6 +3528,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3072,9 +3549,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3150,6 +3645,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3162,9 +3660,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3174,7 +3669,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3201,9 +3696,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3246,9 +3747,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3258,6 +3765,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3279,6 +3792,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3288,9 +3807,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3303,6 +3852,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3324,9 +3879,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3366,6 +3933,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3375,28 +3945,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3408,7 +3990,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3420,30 +4005,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3462,6 +4065,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3471,13 +4089,34 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3495,12 +4134,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3513,12 +4170,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3564,6 +4227,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3588,6 +4254,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3639,6 +4308,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3729,7 +4401,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3804,6 +4479,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3849,6 +4527,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3885,6 +4566,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3963,9 +4647,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3993,9 +4686,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4026,6 +4725,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4050,6 +4752,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4095,13 +4800,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4113,37 +4821,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4170,6 +4875,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4269,6 +4977,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4281,7 +4992,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4290,6 +5001,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4347,6 +5061,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4377,9 +5094,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4398,12 +5121,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4428,6 +5163,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4443,15 +5181,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4467,6 +5220,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4497,6 +5253,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4512,9 +5271,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4533,6 +5310,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4566,6 +5358,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4584,6 +5382,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4623,10 +5427,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4641,12 +5445,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4725,6 +5535,9 @@ msgstr[2] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4740,6 +5553,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4755,15 +5571,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4902,6 +5742,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4968,6 +5814,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4998,6 +5847,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -5034,9 +5886,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5058,13 +5907,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5073,9 +5925,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5088,19 +5949,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5118,6 +5991,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5127,6 +6018,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5145,7 +6039,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5154,6 +6048,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5163,7 +6063,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5175,22 +6075,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Query"
-msgstr ""
-
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5205,10 +6099,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5229,21 +6123,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5316,6 +6201,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5376,6 +6273,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5388,6 +6288,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5403,6 +6306,12 @@ msgstr[2] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5421,6 +6330,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5442,6 +6354,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5469,6 +6384,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5478,6 +6396,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5490,15 +6411,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5511,6 +6441,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5520,10 +6453,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5544,6 +6480,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5553,12 +6492,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5583,6 +6516,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5613,6 +6549,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5712,21 +6654,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5760,16 +6717,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5817,6 +6771,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5829,12 +6789,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5856,9 +6831,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5874,6 +6846,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6060,6 +7038,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6072,9 +7053,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6087,6 +7074,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6129,6 +7119,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6150,9 +7143,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6168,15 +7170,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6195,6 +7212,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6204,6 +7224,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6240,10 +7266,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6252,7 +7281,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6261,10 +7290,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6291,12 +7323,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6315,16 +7350,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6333,6 +7371,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6390,12 +7434,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6540,9 +7590,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6567,6 +7614,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6696,6 +7746,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6735,21 +7788,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6777,6 +7839,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6807,6 +7872,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6816,6 +7887,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6846,9 +7923,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6909,6 +7992,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6927,6 +8016,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6936,12 +8028,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6951,6 +8058,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6960,12 +8073,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6978,15 +8097,15 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -7014,6 +8133,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -7041,6 +8163,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7074,7 +8199,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7095,6 +8220,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7104,6 +8232,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7140,6 +8271,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7152,6 +8286,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7221,7 +8358,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7230,10 +8367,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7251,6 +8391,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7260,6 +8412,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7287,6 +8445,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7320,9 +8481,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7332,6 +8499,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7362,6 +8571,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7377,6 +8589,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7440,10 +8655,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7482,12 +8697,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7497,6 +8721,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7518,9 +8745,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7530,6 +8766,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7539,9 +8778,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7560,6 +8805,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7584,9 +8832,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7632,7 +8886,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7665,6 +8919,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7677,6 +8934,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7704,6 +8964,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7719,6 +8982,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7755,6 +9021,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7764,9 +9036,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7776,6 +9060,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7785,6 +9078,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7800,6 +9099,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7815,6 +9117,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7830,10 +9135,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7848,7 +9237,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7857,11 +9249,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7956,6 +9348,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7971,9 +9369,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -8010,6 +9414,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8088,16 +9495,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8133,12 +9558,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8166,13 +9600,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8235,10 +9672,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8247,7 +9684,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8268,6 +9705,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8295,7 +9741,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8307,7 +9753,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8502,9 +9948,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8547,13 +10002,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8562,6 +10032,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8571,6 +10044,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8586,13 +10062,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8646,9 +10125,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8658,6 +10134,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8667,9 +10149,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8682,10 +10170,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8694,9 +10182,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8745,6 +10239,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8757,6 +10254,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8766,6 +10266,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8784,15 +10287,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8823,9 +10341,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8850,19 +10374,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8871,25 +10404,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8898,12 +10458,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8916,6 +10482,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8955,6 +10527,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8979,6 +10554,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9003,27 +10584,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9048,6 +10650,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9189,12 +10794,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9207,6 +10821,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9225,6 +10842,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9249,6 +10869,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9267,6 +10890,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9276,12 +10902,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9291,16 +10923,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9342,6 +10980,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9357,12 +10998,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9375,12 +11022,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9390,12 +11049,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9492,6 +11157,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9507,6 +11175,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9630,6 +11304,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9651,12 +11328,21 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "done"
msgstr ""
@@ -9669,6 +11355,15 @@ msgstr[2] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9678,21 +11373,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9708,9 +11421,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9723,15 +11454,30 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9747,10 +11493,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9789,6 +11535,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9861,12 +11610,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9915,19 +11658,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9936,6 +11679,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9948,10 +11694,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9972,9 +11718,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9996,6 +11754,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -10005,6 +11766,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -10017,28 +11784,58 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -10047,9 +11844,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10059,3 +11862,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 48a81762e69..1a877ebde6e 100644
--- a/locale/sr_SP/gitlab.po
+++ b/locale/sr_SP/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:19\n"
+"PO-Revision-Date: 2019-02-11 08:09\n"
msgid " Status"
msgstr ""
@@ -33,20 +33,17 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -60,11 +57,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -90,6 +84,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -141,6 +141,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -162,12 +165,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -177,9 +186,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -189,6 +195,30 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -207,12 +237,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -291,10 +330,13 @@ msgstr[2] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -336,7 +378,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -384,6 +426,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -420,10 +465,10 @@ msgstr ""
msgid "Add"
msgstr ""
-msgid "Add Changelog"
+msgid "Add CHANGELOG"
msgstr ""
-msgid "Add Contribution guide"
+msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
@@ -435,7 +480,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -468,6 +516,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -477,6 +528,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -492,9 +546,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -528,12 +579,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -546,12 +627,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -564,6 +675,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -573,9 +687,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -597,6 +717,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -624,40 +747,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -666,6 +759,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -738,12 +834,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -774,9 +879,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -807,6 +957,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -819,6 +984,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -828,12 +996,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -849,6 +1029,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -867,6 +1050,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -876,6 +1062,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -903,6 +1092,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -915,6 +1107,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -930,6 +1125,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -957,15 +1155,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -999,13 +1188,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1191,6 +1392,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1200,12 +1407,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1359,21 +1560,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1410,12 +1626,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1425,18 +1635,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1449,12 +1668,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1476,10 +1704,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1491,9 +1719,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1515,6 +1749,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1533,6 +1773,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1626,7 +1869,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1647,6 +1890,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1686,28 +1935,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1731,27 +2004,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1761,6 +2049,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1773,6 +2064,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1800,6 +2094,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1872,6 +2175,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1887,6 +2196,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1923,6 +2238,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -2001,6 +2319,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2043,12 +2364,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2064,6 +2391,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2076,6 +2415,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2103,6 +2445,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2115,9 +2460,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2136,15 +2490,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2208,6 +2562,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2235,12 +2592,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2274,6 +2637,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2322,6 +2688,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2337,7 +2706,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2373,13 +2742,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2388,6 +2760,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2412,9 +2787,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2436,6 +2808,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2445,6 +2820,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2484,6 +2862,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2550,9 +2931,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2568,6 +2946,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2577,6 +2958,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2607,6 +2994,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2616,6 +3006,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2628,6 +3021,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2637,6 +3033,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2646,6 +3048,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2676,6 +3081,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2811,6 +3222,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2838,6 +3252,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2868,6 +3285,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2889,15 +3312,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2925,6 +3357,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2949,6 +3387,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2964,9 +3405,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2976,6 +3423,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2985,6 +3438,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -3003,6 +3459,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -3027,6 +3486,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3042,9 +3504,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3057,6 +3528,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3072,9 +3549,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3150,6 +3645,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3162,9 +3660,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3174,7 +3669,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3201,9 +3696,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3246,9 +3747,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3258,6 +3765,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3279,6 +3792,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3288,9 +3807,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3303,6 +3852,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3324,9 +3879,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3366,6 +3933,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3375,28 +3945,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3408,7 +3990,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3420,30 +4005,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3462,6 +4065,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3471,13 +4089,34 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3495,12 +4134,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3513,12 +4170,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3564,6 +4227,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3588,6 +4254,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3639,6 +4308,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3729,7 +4401,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3804,6 +4479,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3849,6 +4527,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3885,6 +4566,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3963,9 +4647,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3993,9 +4686,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -4026,6 +4725,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4050,6 +4752,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4095,13 +4800,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4113,37 +4821,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4170,6 +4875,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4269,6 +4977,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4281,7 +4992,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4290,6 +5001,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4347,6 +5061,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4377,9 +5094,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4398,12 +5121,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4428,6 +5163,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4443,15 +5181,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4467,6 +5220,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4497,6 +5253,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4512,9 +5271,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4533,6 +5310,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4566,6 +5358,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4584,6 +5382,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4623,10 +5427,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4641,12 +5445,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4725,6 +5535,9 @@ msgstr[2] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4740,6 +5553,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4755,15 +5571,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4902,6 +5742,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4968,6 +5814,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4998,6 +5847,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -5034,9 +5886,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5058,13 +5907,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5073,9 +5925,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5088,19 +5949,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5118,6 +5991,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5127,6 +6018,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5145,7 +6039,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5154,6 +6048,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5163,7 +6063,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5175,22 +6075,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Query"
-msgstr ""
-
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5205,10 +6099,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5229,21 +6123,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5316,6 +6201,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5376,6 +6273,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5388,6 +6288,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5403,6 +6306,12 @@ msgstr[2] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5421,6 +6330,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5442,6 +6354,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5469,6 +6384,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5478,6 +6396,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5490,15 +6411,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5511,6 +6441,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5520,10 +6453,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5544,6 +6480,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5553,12 +6492,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5583,6 +6516,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5613,6 +6549,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5712,21 +6654,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5760,16 +6717,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5817,6 +6771,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5829,12 +6789,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5856,9 +6831,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5874,6 +6846,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6060,6 +7038,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6072,9 +7053,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6087,6 +7074,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6129,6 +7119,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6150,9 +7143,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6168,15 +7170,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6195,6 +7212,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6204,6 +7224,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6240,10 +7266,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6252,7 +7281,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6261,10 +7290,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6291,12 +7323,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6315,16 +7350,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6333,6 +7371,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6390,12 +7434,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6540,9 +7590,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6567,6 +7614,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6696,6 +7746,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6735,21 +7788,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6777,6 +7839,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6807,6 +7872,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6816,6 +7887,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6846,9 +7923,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6909,6 +7992,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6927,6 +8016,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6936,12 +8028,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6951,6 +8058,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6960,12 +8073,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6978,15 +8097,15 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -7014,6 +8133,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -7041,6 +8163,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7074,7 +8199,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7095,6 +8220,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7104,6 +8232,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7140,6 +8271,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7152,6 +8286,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7221,7 +8358,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7230,10 +8367,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7251,6 +8391,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7260,6 +8412,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7287,6 +8445,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7320,9 +8481,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7332,6 +8499,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7362,6 +8571,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7377,6 +8589,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7440,10 +8655,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7482,12 +8697,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7497,6 +8721,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7518,9 +8745,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7530,6 +8766,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7539,9 +8778,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7560,6 +8805,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7584,9 +8832,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7632,7 +8886,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7665,6 +8919,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7677,6 +8934,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7704,6 +8964,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7719,6 +8982,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7755,6 +9021,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7764,9 +9036,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7776,6 +9060,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7785,6 +9078,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7800,6 +9099,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7815,6 +9117,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7830,10 +9135,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7848,7 +9237,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7857,11 +9249,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7956,6 +9348,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7971,9 +9369,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -8010,6 +9414,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8088,16 +9495,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8133,12 +9558,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8166,13 +9600,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8235,10 +9672,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8247,7 +9684,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8268,6 +9705,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8295,7 +9741,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8307,7 +9753,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8502,9 +9948,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8547,13 +10002,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8562,6 +10032,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8571,6 +10044,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8586,13 +10062,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8646,9 +10125,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8658,6 +10134,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8667,9 +10149,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8682,10 +10170,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8694,9 +10182,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8745,6 +10239,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8757,6 +10254,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8766,6 +10266,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8784,15 +10287,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8823,9 +10341,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8850,19 +10374,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8871,25 +10404,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8898,12 +10458,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8916,6 +10482,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8955,6 +10527,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8979,6 +10554,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -9003,27 +10584,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9048,6 +10650,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9189,12 +10794,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9207,6 +10821,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9225,6 +10842,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9249,6 +10869,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9267,6 +10890,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9276,12 +10902,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9291,16 +10923,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9342,6 +10980,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9357,12 +10998,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9375,12 +11022,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9390,12 +11049,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9492,6 +11157,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9507,6 +11175,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9630,6 +11304,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9651,12 +11328,21 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "done"
msgstr ""
@@ -9669,6 +11355,15 @@ msgstr[2] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9678,21 +11373,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9708,9 +11421,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9723,15 +11454,30 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9747,10 +11493,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9789,6 +11535,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9861,12 +11610,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9915,19 +11658,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9936,6 +11679,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9948,10 +11694,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9972,9 +11718,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9996,6 +11754,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -10005,6 +11766,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -10017,28 +11784,58 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -10047,9 +11844,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -10059,3 +11862,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
new file mode 100644
index 00000000000..1d66cc3af44
--- /dev/null
+++ b/locale/sv_SE/gitlab.po
@@ -0,0 +1,11801 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Swedish\n"
+"Language: sv_SE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: sv-SE\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2019-02-11 08:10\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " or "
+msgstr ""
+
+msgid " or <#epic id>"
+msgstr ""
+
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commits"
+msgstr ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid ", or "
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add CHANGELOG"
+msgstr ""
+
+msgid "Add CONTRIBUTING"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to project"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Auth Token"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization key"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "By %{user_name}"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Charts"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI Lint"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "CONTRIBUTING"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change permissions"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking approval status"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed (moved)"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} upgraded successfully."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Command line instructions"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit %{commit_id}"
+msgstr ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit deleted"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Contact sales to upgrade"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution Charts"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create milestone"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downstream"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable error tracking"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Stopping"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error rendering markdown preview"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating %{issuableType}"
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find existing members by name"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish editing this message first!"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate key"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last repository check run"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Re-verification interval"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Given access %{time_ago}"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import project members"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include merge request description"
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed"
+msgstr ""
+
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes Clusters"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage two-factor authentication"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge commit message"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search files"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics for environment"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No details available"
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No errors to display"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No milestones to show"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No preview for this file type"
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No start date"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|@username"
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Social sign-in"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "Project:"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about environments"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register U2F device"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset key"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Restart Terminal"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reveal values"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners activated for this project"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search groups"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|No Vulnerabilities"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select members to invite"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new U2F device"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippet Contents"
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "Sort direction"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start cleanup"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Stopping..."
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no approvers"
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This 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. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To 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>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle commit list"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try again?"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "URL"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Upload object map"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "Used to help configure your identity provider"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various localization settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Report Type"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web Terminal"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "When:"
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "Will deploy to"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "allowed to fail"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "commented on %{link_to_project}"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "deleted"
+msgstr ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "group"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "image diff"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "none"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
new file mode 100644
index 00000000000..d6f57772b1b
--- /dev/null
+++ b/locale/sw_KE/gitlab.po
@@ -0,0 +1,11801 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Swahili\n"
+"Language: sw_KE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: sw\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2019-02-11 08:10\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " or "
+msgstr ""
+
+msgid " or <#epic id>"
+msgstr ""
+
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commits"
+msgstr ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid ", or "
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add CHANGELOG"
+msgstr ""
+
+msgid "Add CONTRIBUTING"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to project"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Auth Token"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization key"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "By %{user_name}"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Charts"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI Lint"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "CONTRIBUTING"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change permissions"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking approval status"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed (moved)"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} upgraded successfully."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Command line instructions"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit %{commit_id}"
+msgstr ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit deleted"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Contact sales to upgrade"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution Charts"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create milestone"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downstream"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable error tracking"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Stopping"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error rendering markdown preview"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating %{issuableType}"
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Get started with Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find existing members by name"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish editing this message first!"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate key"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last repository check run"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Re-verification interval"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Given access %{time_ago}"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import project members"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include merge request description"
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed"
+msgstr ""
+
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes Clusters"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage two-factor authentication"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge commit message"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search files"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics for environment"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No details available"
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No errors to display"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No milestones to show"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No preview for this file type"
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No start date"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|@username"
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Social sign-in"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "Project:"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about environments"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register U2F device"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset key"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Restart Terminal"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reveal values"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners activated for this project"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search groups"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|No Vulnerabilities"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select members to invite"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new U2F device"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippet Contents"
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "Sort direction"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start cleanup"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Stopping..."
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no approvers"
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This 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. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To 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>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle commit list"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try again?"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "URL"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Upload object map"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "Used to help configure your identity provider"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various localization settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Report Type"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web Terminal"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "When:"
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "Will deploy to"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "allowed to fail"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "commented on %{link_to_project}"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "deleted"
+msgstr ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "group"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "image diff"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "none"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index 8a666a6737d..dcdc049d9a6 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: tr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:19\n"
+"PO-Revision-Date: 2019-02-11 08:10\n"
msgid " Status"
msgstr ""
@@ -31,18 +31,17 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -54,10 +53,8 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -79,6 +76,11 @@ msgid_plural "%d issues"
msgstr[0] ""
msgstr[1] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -124,6 +126,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -143,12 +148,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -158,9 +169,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -170,6 +178,27 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -187,12 +216,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} daha fazla"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -260,10 +298,13 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr "İlk katkı!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -305,7 +346,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -353,6 +394,9 @@ msgstr "Kötüye Kullanım Raporları"
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -389,11 +433,11 @@ msgstr "Etkinlik"
msgid "Add"
msgstr ""
-msgid "Add Changelog"
-msgstr "DeÄŸiÅŸiklik Bilgisi Ekle"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "Katkı kılavuzu ekle"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -404,7 +448,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -437,6 +484,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -446,6 +496,9 @@ msgstr "Yapılacaklara Ekle"
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -461,9 +514,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -497,12 +547,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -515,12 +595,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -532,6 +642,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr "Tümü"
@@ -541,9 +654,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -565,6 +684,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Kubernetes kümelerini eklemeye ve yönetmenize olanak tanır."
@@ -592,40 +714,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -634,6 +726,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -706,12 +801,21 @@ msgstr "Dosya isimleri yüklenirken bir hata oluştu"
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr "KaTeX'i iÅŸlerken bir hata oluÅŸtu"
@@ -742,9 +846,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr "Kullanıcı adı doğrulanırken bir hata oluştu"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Bir hata oluştu. Lütfen tekrar deneyin."
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -775,6 +924,21 @@ msgstr ""
msgid "Applications"
msgstr "Uygulamalar"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "Nis"
@@ -787,6 +951,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -796,12 +963,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -817,6 +996,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "Emin misiniz?"
@@ -835,6 +1017,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "#FF0000 gibi özel renk ata"
@@ -844,6 +1029,9 @@ msgstr "Etiket tanımla"
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr "Ata"
@@ -871,6 +1059,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Sürükleyip bırakarak bir dosya ekle veya %{upload_link}"
@@ -883,6 +1074,9 @@ msgstr "AÄŸustos"
msgid "August"
msgstr "AÄŸustos"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "Kimlik Doğrulama Günlüğü"
@@ -898,6 +1092,9 @@ msgstr "Yazar"
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -925,15 +1122,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -967,13 +1155,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "Kullanılabilir"
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1159,6 +1359,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1168,11 +1374,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
@@ -1326,21 +1527,36 @@ msgstr ""
msgid "Browse files"
msgstr ""
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1377,12 +1593,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1392,18 +1602,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1416,12 +1635,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1443,10 +1671,10 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
-msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Charts"
@@ -1458,9 +1686,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1482,6 +1716,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1500,6 +1740,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1593,7 +1836,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1614,6 +1857,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1653,28 +1902,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1698,27 +1971,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1728,6 +2016,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1740,6 +2031,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1767,6 +2061,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1839,6 +2142,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1854,6 +2163,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1890,6 +2205,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1968,6 +2286,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -2010,12 +2331,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -2031,6 +2358,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2043,6 +2382,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2070,6 +2412,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2082,9 +2427,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2102,14 +2456,15 @@ msgid_plural "Commits"
msgstr[0] ""
msgstr[1] ""
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr ""
@@ -2173,6 +2528,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2200,12 +2558,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2239,6 +2603,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2287,6 +2654,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2302,7 +2672,7 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
+msgid "Contribution Charts"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
@@ -2338,13 +2708,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2353,6 +2726,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2377,9 +2753,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2401,6 +2774,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2410,6 +2786,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -2449,6 +2828,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2515,9 +2897,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2533,6 +2912,9 @@ msgstr ""
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2542,6 +2924,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2572,6 +2960,9 @@ msgstr ""
msgid "CycleAnalyticsStage|Test"
msgstr ""
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2581,6 +2972,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2593,6 +2987,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2602,6 +2999,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2611,6 +3014,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2641,6 +3047,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2775,6 +3187,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2802,6 +3217,9 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2832,6 +3250,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2853,15 +3277,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2889,6 +3322,12 @@ msgstr ""
msgid "Download"
msgstr ""
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr ""
@@ -2913,6 +3352,9 @@ msgstr ""
msgid "DownloadSource|Download"
msgstr ""
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2928,9 +3370,15 @@ msgstr ""
msgid "Edit"
msgstr ""
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -2940,6 +3388,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2949,6 +3403,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2967,6 +3424,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2991,6 +3451,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -3006,9 +3469,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -3021,6 +3493,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3036,9 +3514,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3114,6 +3610,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3126,9 +3625,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3138,7 +3634,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3165,9 +3661,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3210,9 +3712,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3222,6 +3730,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3243,6 +3757,12 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -3252,9 +3772,39 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3267,6 +3817,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3288,9 +3844,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3330,6 +3898,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3339,28 +3910,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3372,7 +3955,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3384,30 +3970,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3426,6 +4030,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3435,13 +4054,33 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
-msgid "Files"
+msgid "File upload error."
msgstr ""
-msgid "Files (%{human_size})"
+msgid "Files"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
@@ -3459,12 +4098,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr ""
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr ""
@@ -3477,12 +4134,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr ""
@@ -3528,6 +4191,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3552,6 +4218,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3603,6 +4272,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3693,7 +4365,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3768,6 +4443,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3813,6 +4491,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3849,6 +4530,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3927,9 +4611,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3957,9 +4650,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3990,6 +4689,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4014,6 +4716,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4059,13 +4764,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
+msgstr ""
+
+msgid "Group: %{group_name}"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4077,37 +4785,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4134,6 +4839,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4233,6 +4941,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4244,7 +4955,7 @@ msgid_plural "Hide values"
msgstr[0] ""
msgstr[1] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4253,6 +4964,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4310,6 +5024,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4340,9 +5057,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4361,12 +5084,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4391,6 +5126,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4406,15 +5144,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4430,6 +5183,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4459,6 +5215,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4474,9 +5233,27 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4495,6 +5272,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4528,6 +5320,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4546,6 +5344,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4585,10 +5389,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4603,12 +5407,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4686,6 +5496,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr ""
@@ -4701,6 +5514,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4716,15 +5532,39 @@ msgstr ""
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4862,6 +5702,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4928,6 +5774,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4958,6 +5807,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4994,9 +5846,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -5018,13 +5867,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -5033,9 +5885,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr ""
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5048,19 +5909,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5078,6 +5951,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5087,6 +5978,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5105,7 +5999,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5114,6 +6008,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5123,7 +6023,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5135,22 +6035,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Query"
-msgstr ""
-
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5165,10 +6059,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5189,21 +6083,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5276,6 +6161,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5336,6 +6233,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5348,6 +6248,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5362,6 +6265,12 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr ""
@@ -5380,6 +6289,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5401,6 +6313,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5428,6 +6343,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5437,6 +6355,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5449,15 +6370,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5470,6 +6400,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5479,10 +6412,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5503,6 +6439,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5512,12 +6451,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5542,6 +6475,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5572,6 +6508,12 @@ msgstr ""
msgid "Notification events"
msgstr ""
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -5670,21 +6612,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5718,16 +6675,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5775,6 +6729,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5787,12 +6747,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5814,9 +6789,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5832,6 +6804,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -6018,6 +6996,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -6030,9 +7011,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6045,6 +7032,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6087,6 +7077,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6108,9 +7101,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6126,15 +7128,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6153,6 +7170,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6162,6 +7182,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6198,10 +7224,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6210,7 +7239,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6219,10 +7248,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6249,12 +7281,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6273,16 +7308,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6291,6 +7329,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6348,12 +7392,18 @@ msgstr ""
msgid "Project export started. A download link will be sent by email."
msgstr ""
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -6498,9 +7548,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6525,6 +7572,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6654,6 +7704,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6693,21 +7746,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr ""
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6734,6 +7796,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6764,6 +7829,12 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -6773,6 +7844,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6803,9 +7880,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6866,6 +7949,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6884,6 +7973,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6893,12 +7985,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr ""
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr ""
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6908,6 +8015,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6917,12 +8030,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6935,14 +8054,14 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
msgstr[1] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -6970,6 +8089,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6997,6 +8119,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -7030,7 +8155,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7051,6 +8176,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7060,6 +8188,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7096,6 +8227,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7108,6 +8242,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7177,7 +8314,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7186,10 +8323,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7207,6 +8347,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7216,6 +8368,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7243,6 +8401,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7276,9 +8437,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7288,6 +8455,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7318,6 +8527,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7333,6 +8545,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7396,10 +8611,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7437,12 +8652,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7452,6 +8676,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7473,9 +8700,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7485,6 +8721,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7494,9 +8733,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7515,6 +8760,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7539,9 +8787,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7587,7 +8841,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7620,6 +8874,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7632,6 +8889,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7659,6 +8919,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7674,6 +8937,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr ""
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7710,6 +8976,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -7719,9 +8991,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -7731,6 +9015,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7740,6 +9033,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7755,6 +9054,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7770,6 +9072,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7785,10 +9090,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7803,7 +9192,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7812,10 +9204,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr ""
@@ -7910,6 +9303,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7925,9 +9324,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7964,6 +9369,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -8042,16 +9450,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8087,12 +9513,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8120,13 +9555,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8189,10 +9627,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8201,7 +9639,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8222,6 +9660,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8249,7 +9696,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8261,7 +9708,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8454,9 +9901,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8499,13 +9955,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8514,6 +9985,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8523,6 +9997,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8538,13 +10015,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8598,9 +10078,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8610,6 +10087,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8619,9 +10102,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8634,10 +10123,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8646,9 +10135,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8697,6 +10192,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8709,6 +10207,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8718,6 +10219,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8736,15 +10240,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr ""
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr ""
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8775,9 +10294,15 @@ msgstr ""
msgid "Use your global notification setting"
msgstr ""
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8802,19 +10327,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8823,25 +10357,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8850,12 +10411,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8868,6 +10435,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8907,6 +10480,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8931,6 +10507,12 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8955,27 +10537,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -9000,6 +10603,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9141,12 +10747,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr ""
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9159,6 +10774,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9177,6 +10795,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9201,6 +10822,9 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9219,6 +10843,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9228,12 +10855,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9243,16 +10876,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr ""
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9294,6 +10933,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9309,12 +10951,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9327,12 +10975,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr ""
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9342,12 +11002,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9440,6 +11106,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9455,6 +11124,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9575,6 +11250,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9595,12 +11273,20 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
@@ -9612,6 +11298,15 @@ msgstr[1] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9621,21 +11316,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9650,9 +11363,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9665,14 +11396,29 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9688,10 +11434,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9730,6 +11476,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9802,12 +11551,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9854,19 +11597,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9875,6 +11618,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9887,10 +11633,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9911,9 +11657,21 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr ""
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9933,6 +11691,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9941,6 +11702,12 @@ msgid_plural "projects"
msgstr[0] ""
msgstr[1] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9953,27 +11720,57 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9982,9 +11779,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9993,3 +11796,6 @@ msgid_plural "within %d minutes "
msgstr[0] ""
msgstr[1] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index b61022903da..67d9a556621 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: uk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:20\n"
+"PO-Revision-Date: 2019-02-11 08:11\n"
msgid " Status"
msgstr " СтатуÑ"
@@ -35,22 +35,17 @@ msgstr[1] " покращилоÑÑ Ð½Ð° %d одиниць"
msgstr[2] " покращилоÑÑ Ð½Ð° %d одиниць"
msgstr[3] " покращилоÑÑ Ð½Ð° %d одиниць"
-msgid "\"%{query}\" in projects"
-msgstr "\"%{query}\" в проектах"
+msgid " or "
+msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] "%d доповненнÑ"
-msgstr[1] "%d доповненнÑ"
-msgstr[2] "%d доповнень"
-msgstr[3] "%d доповнень"
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] "%d змінений файл"
-msgstr[1] "%d змінених файли"
-msgstr[2] "%d змінених файлів"
-msgstr[3] "%d змінених файлів"
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" в проектах"
msgid "%d commit"
msgid_plural "%d commits"
@@ -66,12 +61,8 @@ msgstr[1] "%d коміта позаду"
msgstr[2] "%d комітів позаду"
msgstr[3] "%d комітів позаду"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] "%d видаленнÑ"
-msgstr[1] "%d видаленнÑ"
-msgstr[2] "%d видалень"
-msgstr[3] "%d видалень"
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -96,10 +87,17 @@ msgstr[3] "%d виправлених результатів теÑту"
msgid "%d issue"
msgid_plural "%d issues"
-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 "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "%d layer"
msgid_plural "%d layers"
@@ -158,6 +156,9 @@ msgstr "%{counter_storage} (%{counter_repositories} репозиторій, %{co
msgid "%{count} %{alerts}"
msgstr "%{count} %{alerts}"
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr "%{count} більше виконавців"
@@ -170,10 +171,10 @@ msgstr[3] "%{count} учаÑтників"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{count} коментар в очікуванні"
+msgstr[1] "%{count} коментарі в очікуванні"
+msgstr[2] "%{count} коментарів в очікуванні"
+msgstr[3] "%{count} коментарів в очікуванні"
msgid "%{filePath} deleted"
msgstr "%{filePath} видалено"
@@ -181,12 +182,18 @@ msgstr "%{filePath} видалено"
msgid "%{firstLabel} +%{labelCount} more"
msgstr "%{firstLabel} +%{labelCount} більше"
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Групи%{group_docs_link_end} дозволÑÑŽÑ‚ÑŒ вам керувати Ñ– взаємодіÑти між кількома проектами. Члени групи мають доÑтуп до уÑÑ–Ñ… Ñ—Ñ— проектів."
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} буде видалено! Ви впевнені?"
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Початок"
@@ -196,9 +203,6 @@ msgstr "%{lock_path} заблоковано кориÑтувачем GitLab %{lo
msgid "%{name}'s avatar"
msgstr "Ðватар %{name}"
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} може бути викориÑтана Ñк альтернатива влаÑному домену."
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "на %{number_commits_behind} комітів позаду %{default_branch}, на %{number_commits_ahead} комітів попереду"
@@ -208,6 +212,33 @@ msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% завершено"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text} %{files}"
@@ -227,12 +258,21 @@ msgstr "%{unstaged} неіндекÑованих та %{staged} проіндек
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}ДовідатиÑÑŒ більше%{usage_ping_link_end} про те, Ñкою інформацією Ви ділитеÑÑŒ із GitLab Inc."
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr "+ ще %{count}"
msgid "+ %{moreCount} more"
msgstr "+ ще %{moreCount}"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr "- Runner активний Ñ– може виконувати нові завданнÑ"
@@ -258,10 +298,10 @@ msgstr[3] "%{count} %{type} змін"
msgid "1 closed issue"
msgid_plural "%d closed issues"
-msgstr[0] "1 закрита проблема"
-msgstr[1] "%d закриті проблеми"
-msgstr[2] "%d закритих проблем"
-msgstr[3] "%d закритих проблем"
+msgstr[0] "1 закрита задача"
+msgstr[1] "%d закриті задачі"
+msgstr[2] "%d закритих задач"
+msgstr[3] "%d закритих задач"
msgid "1 closed merge request"
msgid_plural "%d closed merge requests"
@@ -286,10 +326,10 @@ msgstr[3] "%d заÑтоÑованих запитів на злиттÑ"
msgid "1 open issue"
msgid_plural "%d open issues"
-msgstr[0] "1 відкрита проблема"
-msgstr[1] "%d відкриті проблеми"
-msgstr[2] "%d відкритих проблем"
-msgstr[3] "%d відкритих проблем"
+msgstr[0] "1 відкрита задача"
+msgstr[1] "%d відкриті задачі"
+msgstr[2] "%d відкритих задач"
+msgstr[3] "%d відкритих задач"
msgid "1 open merge request"
msgid_plural "%d open merge requests"
@@ -322,11 +362,14 @@ msgstr[3] "%d кориÑтувачів"
msgid "1st contribution!"
msgstr "Перший внеÑок!"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "Двоетапна Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð°"
-msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтратора GitLab, щоб отримати дозвіл."
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
msgid "403|You don't have the permission to access this page."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтупу до цієї Ñторінки."
@@ -341,16 +384,16 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтратора GitLab, Ñкщо ви вважаєте, що це помилка."
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> додаÑÑ‚ÑŒ \"<a href=\"#\">@johnsmith</a>\" до вÑÑ–Ñ… проблем та коментарів, що були Ñтворені johnsmith@example.com, а також призначить на <a href=\"#\">@johnsmith</a> уÑÑ– проблеми, Ñкі були призначені на на johnsmith@example.com."
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> додаÑÑ‚ÑŒ \"<a href=\"#\">@johnsmith</a>\" до вÑÑ–Ñ… задач та коментарів, що були Ñтворені johnsmith@example.com, а також призначить на <a href=\"#\">@johnsmith</a> уÑÑ– задачі, Ñкі були призначені на на johnsmith@example.com."
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> додаÑÑ‚ÑŒ \"John Smith\" до уÑÑ–Ñ… проблем та коментарів, Ñкі були Ñтворені johnsmith@example.com."
+msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> додаÑÑ‚ÑŒ \"John Smith\" до уÑÑ–Ñ… задач та коментарів, Ñкі були Ñтворені johnsmith@example.com."
msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> додаÑÑ‚ÑŒ \"johnsm...@example.com\" до уÑÑ–Ñ… проблем та коментарів, Ñкі були Ñтворені johnsmith@example.com. Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та його електронна адреÑа замаÑковані Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ÑÑ‚Ñ–."
+msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> додаÑÑ‚ÑŒ \"johnsm...@example.com\" до уÑÑ–Ñ… задач та коментарів, Ñкі були Ñтворені johnsmith@example.com. Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та його електронна адреÑа замаÑковані Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ÑÑ‚Ñ–."
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
-msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> додаÑÑ‚ÑŒ \"<a href=\"#\">johnsmith@example.com</a>\" до вÑÑ–Ñ… проблем та коментарів, Ñкі були Ñтворені johnsmith@example.com. За замовчуваннÑм Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та його електронна адреÑа заблоковані Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ÑÑ‚Ñ–. ВикориÑтовуйте цю опцію, Ñкщо ви хочете показувати електронну адреÑу повніÑÑ‚ÑŽ."
+msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> додаÑÑ‚ÑŒ \"<a href=\"#\">johnsmith@example.com</a>\" до вÑÑ–Ñ… задач та коментарів, Ñкі були Ñтворені johnsmith@example.com. За замовчуваннÑм Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та його електронна адреÑа заблоковані Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ÑÑ‚Ñ–. ВикориÑтовуйте цю опцію, Ñкщо ви хочете показувати електронну адреÑу повніÑÑ‚ÑŽ."
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>%{changedFilesLength} неіндекÑованих</strong> та <strong>%{stagedFilesLength} індекÑованих</strong> змін"
@@ -367,8 +410,8 @@ msgstr "<strong>%{group_name}</strong> кориÑтувачі групи"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr "<strong>%{pushes}</strong> відправок (push), більше ніж <strong>%{commits}</strong> зафікÑовано<strong>%{people}</strong> учаÑниками."
-msgid "<strong>Removes</strong> source branch"
-msgstr "<strong>ВидалÑÑ”</strong> гілку-джерело"
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "'Runner' — це процеÑ, Ñкий виконує завданнÑ. Ви можете Ñтворити потрібну кількіÑÑ‚ÑŒ Runner'ів."
@@ -383,13 +426,13 @@ msgid "A deleted user"
msgstr "Видалений кориÑтувач"
msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr ""
+msgstr "УчаÑник команди GitLab по боротьбі з порушеннÑми розглÑне ваш звіт Ñкомога швидше."
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "У вашому форку буде Ñтворено нову гілку, а також буде ініційований новий запит на злиттÑ."
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "Проект — це міÑце де ви можете розміщувати Ñвої файли (репозиторій), планувати роботу (проблеми) Ñ– публікувати документацію (вікі), %{among_other_things_link}."
+msgstr "Проект — це міÑце де ви можете розміщувати Ñвої файли (репозиторій), планувати роботу (задачі) Ñ– публікувати документацію (вікі), %{among_other_things_link}."
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
msgstr "РегулÑрний вираз, Ñкий буде викориÑтовуватиÑÑ Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами в завданні. Залиште пуÑтим Ð´Ð»Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ"
@@ -415,6 +458,9 @@ msgstr "Звіти про зловживаннÑ"
msgid "Abuse reports"
msgstr "Звіти про зловживаннÑ"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr "ПрийнÑти умови"
@@ -451,11 +497,11 @@ msgstr "ÐктивніÑÑ‚ÑŒ"
msgid "Add"
msgstr "Додати"
-msgid "Add Changelog"
-msgstr "Додати ÑпиÑок змін"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "Додати керівництво Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Додайте групові веб-гуки та GitLab Enterprise Edition."
@@ -466,8 +512,11 @@ msgstr "Додати URL-Ð°Ð´Ñ€ÐµÑ Jaeger"
msgid "Add Kubernetes cluster"
msgstr "Додати Kubernetes-клаÑтер"
-msgid "Add Readme"
-msgstr "Додати інÑтрукцію"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Додати домашню Ñторінку в вікі, Ñка міÑтить інформацію про ваш проект, Ñ– GitLab відображатиме його тут заміÑÑ‚ÑŒ цього повідомленнÑ."
@@ -482,7 +531,7 @@ msgid "Add comment now"
msgstr "Додати коментар"
msgid "Add image comment"
-msgstr ""
+msgstr "Додати коментар до зображеннÑ"
msgid "Add license"
msgstr "Додати ліцензію"
@@ -499,15 +548,21 @@ msgstr "Додати проекти"
msgid "Add reaction"
msgstr "Додати реакцію"
-msgid "Add to review"
+msgid "Add to project"
msgstr ""
+msgid "Add to review"
+msgstr "Додати до перевірки"
+
msgid "Add todo"
msgstr "Додати задачу"
msgid "Add user(s) to the group:"
msgstr "Додати кориÑтувачів до групу:"
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr "Додати кориÑтувача до групи"
@@ -523,14 +578,11 @@ msgstr "ОблаÑÑ‚ÑŒ адмініÑтратора"
msgid "Admin Overview"
msgstr "ОглÑд адмініÑтратора"
-msgid "Admin area"
-msgstr "ОблаÑÑ‚ÑŒ адмініÑтратора"
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити кориÑтувача %{username}. Пов’Ñзані з ним проблеми, запити на злиттÑ, Ñ– групи будуть переведені на ÑиÑтемного кориÑтувача \"Ghost-user\". Щоб уникнути втрати даних, розглÑньте можливіÑÑ‚ÑŒ %{strong_start}Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end} заміÑÑ‚ÑŒ видаленнÑ. ПіÑÐ»Ñ %{strong_start}Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end}, його неможливо буде відновити."
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити кориÑтувача %{username}. Пов’Ñзані з ним задачі, запити на злиттÑ, Ñ– групи будуть переведені на ÑиÑтемного кориÑтувача \"Ghost-user\". Щоб уникнути втрати даних, розглÑньте можливіÑÑ‚ÑŒ %{strong_start}Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end} заміÑÑ‚ÑŒ видаленнÑ. ПіÑÐ»Ñ %{strong_start}Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end}, його неможливо буде відновити."
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити кориÑтувача %{username}. Ð¦Ñ Ð´Ñ–Ñ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚ÑŒ уÑÑ– проблеми, запити на злиттÑ, Ñ– пов'Ñзані з ним групи. Щоб уникнути втрати даних, розглÑньте можливіÑÑ‚ÑŒ %{strong_start}Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end} заміÑÑ‚ÑŒ видаленнÑ. ПіÑÐ»Ñ %{strong_start}Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end}, його неможливо буде відновити."
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити кориÑтувача %{username}. Ð¦Ñ Ð´Ñ–Ñ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚ÑŒ уÑÑ– задачі, запити на злиттÑ, Ñ– пов'Ñзані з ним групи. Щоб уникнути втрати даних, розглÑньте можливіÑÑ‚ÑŒ %{strong_start}Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end} заміÑÑ‚ÑŒ видаленнÑ. ПіÑÐ»Ñ %{strong_start}Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end}, його неможливо буде відновити."
msgid "AdminArea|Stop all jobs"
msgstr "Зупинити вÑÑ– завданнÑ"
@@ -548,7 +600,7 @@ msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs
msgstr "Зараз ви зупинете вÑÑ– завданнÑ. Це обірве уÑÑ– запущені завданнÑ."
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити проект %{projectName}, його репозиторій та вÑÑ– пов'Ñзані реÑурÑи, включаючи проблеми, запити на злиттÑ, тощо. ПіÑÐ»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° натиÑÐ½ÐµÐ½Ð½Ñ Ð½Ð° кнопку %{strong_start}Видалити проект%{strong_end}, його неможливо буде відновити."
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити проект %{projectName}, його репозиторій та вÑÑ– пов'Ñзані реÑурÑи, включаючи задачі, запити на злиттÑ, тощо. ПіÑÐ»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° натиÑÐ½ÐµÐ½Ð½Ñ Ð½Ð° кнопку %{strong_start}Видалити проект%{strong_end}, його неможливо буде відновити."
msgid "AdminProjects|Delete"
msgstr "Видалити"
@@ -559,12 +611,42 @@ msgstr "Видалити проект %{projectName}?"
msgid "AdminProjects|Delete project"
msgstr "Видалити проект"
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Вкажіть домен, Ñкий буде викориÑтовуватиÑÑ Ð² проекті за замовчуваннÑм Ð´Ð»Ñ Ñтадій Auto Review Apps Ñ– Auto Deploy."
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "Заблоквати кориÑтувача"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "Видалити кориÑтувача %{username} та його внеÑки?"
@@ -577,15 +659,45 @@ msgstr "Видалити кориÑтувача"
msgid "AdminUsers|Delete user and contributions"
msgstr "Видалити кориÑтувача Ñ– його внеÑки"
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ %{username}"
-msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgid "AdminUsers|User will be blocked"
msgstr ""
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr "Додаткові дозволи, Ñховище великих файлів (LFS) Ñ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації."
+
msgid "Advanced settings"
msgstr "Додаткові параметри"
@@ -596,6 +708,9 @@ msgstr[1] "ПопередженнÑ"
msgstr[2] "Попереджень"
msgstr[3] "Попереджень"
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr "Ð’ÑÑ–"
@@ -605,14 +720,20 @@ msgstr "Ð’ÑÑ– зміни закомічені"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Ð’ÑÑ– функції Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проектів берутьÑÑ Ñ–Ð· шаблонів або під Ñ‡Ð°Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ, але ви можете вимикати Ñ—Ñ… пізніше в налаштуваннÑÑ… проекту."
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr "Ð’ÑÑ– кориÑтувачі"
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr "Дозволити коміти від учаÑників, Ñкі можуть зливати в цільову гілку."
msgid "Allow projects within this group to use Git LFS"
-msgstr ""
+msgstr "Дозволити проектам в цій групі викориÑтовувати Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr "Дозволити публічний доÑтуп до конвеєрів Ñ– завдань, включно з логами та артефактами"
@@ -627,6 +748,9 @@ msgid "Allow users to request access"
msgstr "Дозволити кориÑтувачам запитувати доÑтуп"
msgid "Allow users to request access if visibility is public or internal."
+msgstr "Дозволити кориÑтувачам запрошувати доÑтуп, Ñкщо видиміÑÑ‚ÑŒ загальнодоÑтупна або внутрішнÑ."
+
+msgid "Allowed to fail"
msgstr ""
msgid "Allows you to add and manage Kubernetes clusters."
@@ -645,7 +769,7 @@ msgid "Alternatively, you can use a %{personal_access_token_link}. When you crea
msgstr "Крім того, ви можете викориÑтовувати %{personal_access_token_link}. Коли ви Ñтворюватимете Ñвій перÑональний токен доÑтупу, вам потрібно буде вибрати облаÑÑ‚ÑŒ <code>repo</code>, щоб ми могли відобразити ÑпиÑок ваших публічних та приватних репозиторіїв, доÑтупних Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ."
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
-msgstr ""
+msgstr "Ð§Ð°Ñ (в годинах), впродовж Ñкого кориÑтувачам дозволено пропуÑкати примуÑове Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації"
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr "ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð¸ буде автоматично згенеровано SSH ключ. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, звернітьÑÑ Ð´Ð¾ документіції."
@@ -654,50 +778,23 @@ msgid "An application called %{link_to_client} is requesting access to your GitL
msgstr "Додаток під назвою %{link_to_client} запитує доÑтуп до вашого GitLab аккаунту."
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
-msgstr "Порожнє поле Gitlab-кориÑтувача буде заповнено іменем кориÑтувача з FogBugz (наприклад \"John Smith\") в опиÑÑ– вÑÑ–Ñ… проблем та коментарів. Крім того ці проблеми та коментарі будуть аÑоційовані з та/або призначені на автора проекту."
-
-msgid "An error accured whilst committing your changes."
-msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при коміті ваших змін."
+msgstr "Порожнє поле Gitlab-кориÑтувача буде заповнено іменем кориÑтувача з FogBugz (наприклад \"John Smith\") в опиÑÑ– вÑÑ–Ñ… задач та коментарів. Крім того ці задачі та коментарі будуть аÑоційовані з та/або призначені на автора проекту."
msgid "An error has occurred"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
-msgid "An error occured creating the new branch."
-msgstr "Помилка при Ñтворенні нової гілки."
-
-msgid "An error occured whilst fetching the job trace."
-msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні логу завданнÑ."
-
-msgid "An error occured whilst fetching the latest pipeline."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
-msgid "An error occured whilst loading all the files."
-msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні вÑÑ–Ñ… файлів."
-
-msgid "An error occured whilst loading the file content."
-msgstr "Помилка при завантаженні вміÑту файлу."
-
-msgid "An error occured whilst loading the file."
-msgstr "Помилка при завантаженні файлу."
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні змін запиту на злиттÑ."
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні даних верÑÑ–Ñ— запиту на злиттÑ."
-
-msgid "An error occured whilst loading the merge request."
-msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні запиту на злиттÑ."
-
-msgid "An error occured whilst loading the pipelines jobs."
-msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні завдань конвеєру."
-
msgid "An error occurred adding a draft to the discussion."
-msgstr ""
+msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€Ð½ÐµÑ‚ÐºÐ¸ до обговореннÑ."
msgid "An error occurred adding a new draft."
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¾Ñ— чернетки."
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду об'єкта"
@@ -705,7 +802,7 @@ msgid "An error occurred when toggling the notification subscription"
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð¼Ñ–Ð½Ð¸ підпиÑки на ÑповіщеннÑ"
msgid "An error occurred when updating the issue weight"
-msgstr "Збій під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°Ð³Ð¸ проблеми"
+msgstr "Збій під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°Ð³Ð¸ задачі"
msgid "An error occurred while adding approver"
msgstr "Помилка при додаванні учаÑника Ð´Ð»Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ"
@@ -726,7 +823,7 @@ msgid "An error occurred while fetching markdown preview"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при попередньому переглÑді markdown"
msgid "An error occurred while fetching pending comments"
-msgstr ""
+msgstr "Помилка при отриманні коментарів в очікуванні"
msgid "An error occurred while fetching sidebar data"
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… Ð´Ð»Ñ Ð±Ñ–Ñ‡Ð½Ð¾Ñ— панелі"
@@ -756,7 +853,7 @@ msgid "An error occurred while initializing path locks"
msgstr "Помилка при ініціалізації Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð¸Ñ… шлÑхів"
msgid "An error occurred while loading chart data"
-msgstr ""
+msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… діаграми"
msgid "An error occurred while loading commit signatures"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні Ñигнатур коміту"
@@ -770,12 +867,21 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні файлі
msgid "An error occurred while loading the file"
msgstr "Помилка при завантаженні файлу"
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr "Помилка при Ñтворенні запиту."
msgid "An error occurred while removing approver"
msgstr "Помилка при видаленні учаÑника Ð´Ð»Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ"
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при рендерингу KaTeX"
@@ -806,9 +912,54 @@ msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ ÑталаÑÑ Ð¿Ð¾Ð
msgid "An error occurred while validating username"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ імені кориÑтувача"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "СталаÑÑŒ помилка. Спробуйте ще раз."
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr "Ðналітика"
@@ -831,7 +982,7 @@ msgid "Application"
msgstr "Додаток"
msgid "Application ID"
-msgstr ""
+msgstr "Ідентифікатор заÑтоÑунку"
msgid "Application: %{name}"
msgstr "Додаток: %{name}"
@@ -839,6 +990,21 @@ msgstr "Додаток: %{name}"
msgid "Applications"
msgstr "ЗаÑтоÑунки"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "квіт."
@@ -851,21 +1017,36 @@ msgstr "Ðрхівований проект! Репозиторій та іншÑ
msgid "Archived projects"
msgstr "Заархівовані проекти"
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ви впевнені, що хочете видалити цей розклад Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°?"
msgid "Are you sure you want to erase this build?"
-msgstr ""
+msgstr "Ви впевнені, що хочете видалити цей білд?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Ви впевнені, що бажаєте втратити незбережені зміни?"
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "Ви впевнені, що хочете повторно згенерувати відкритий ключ? Вам доведетьÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ відкритий ключ на віддаленому Ñервері, перш ніж Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ñ€Ð°Ñ†ÑŽÑ” знову."
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Ви впевнені, що хочете видалити %{group_name}?"
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr "Ви впевнені, що хочете видалити цю ідентифікацію?"
@@ -881,6 +1062,9 @@ msgstr "Ви впевнені що хочете зупинити це Ñеред
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Ви впевнені, що хочете розблокувати %{path_lock_path}?"
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "Ви впевнені?"
@@ -899,6 +1083,9 @@ msgstr "ЗвернітьÑÑ Ð´Ð¾ керівника групи, щоб нала
msgid "Assertion consumer service URL"
msgstr "URL-адреÑа Ñлужби обробника тверджень"
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "Призначити влаÑний колір типу #FF0000"
@@ -908,11 +1095,14 @@ msgstr "Призначити мітку"
msgid "Assign milestone"
msgstr "Призначити етап"
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr "Призначити"
msgid "Assigned Issues"
-msgstr "Призначені проблеми"
+msgstr "Призначені задачі"
msgid "Assigned Merge Requests"
msgstr "Призначені запити на злиттÑ"
@@ -930,11 +1120,14 @@ msgid "Assignee lists not available with your current license"
msgstr "СпиÑки виконавців не доÑтупні з вашою поточною ліцензією"
msgid "Assignee lists show all issues assigned to the selected user."
-msgstr "СпиÑки виконавців показують уÑÑ– проблеми, призначені вибраному кориÑтувачу."
+msgstr "СпиÑки виконавців показують уÑÑ– задачі, призначені вибраному кориÑтувачу."
msgid "Assignee(s)"
msgstr "Виконавець(ці)"
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Прикріпити файл за допомогою перетÑÐ³ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ %{upload_link}"
@@ -947,6 +1140,9 @@ msgstr "Ñерп."
msgid "August"
msgstr "Ñерпень"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr "Журнал автентифікації"
@@ -962,6 +1158,9 @@ msgstr "Ðвтор"
msgid "Authorization code:"
msgstr "Код авторизації:"
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr "ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ Ð²Ñ–Ð´Ð±ÑƒÐ»Ð°ÑÑ Ð¿Ñ–ÑÐ»Ñ Ð²Ð²Ð¾Ð´Ñƒ вашого імені та паролю у заÑтоÑунку."
@@ -989,15 +1188,6 @@ msgstr "Auto DevOps увімкнено"
msgid "Auto DevOps, runners and job artifacts"
msgstr "Auto DevOps, runner'и і артефакти завдань"
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr "Ð”Ð»Ñ ÐºÐ¾Ñ€ÐµÐºÑ‚Ð½Ð¾Ñ— роботи Auto Review Apps та Auto Deploy необхіден %{kubernetes}."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr "Ð”Ð»Ñ ÐºÐ¾Ñ€ÐµÐºÑ‚Ð½Ð¾Ñ— роботи Auto Review Apps та Auto Deploy необхідно вказати доменне Ñ–Ð¼â€™Ñ Ñ‚Ð° %{kubernetes}."
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "Ð”Ð»Ñ ÐºÐ¾Ñ€ÐµÐºÑ‚Ð½Ð¾Ñ— роботи Auto Review Apps та Auto Deploy необхідно вказати доменне ім’Ñ."
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr "Ðвтоматичне ÑкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð´Ð»Ð¸ÑˆÐºÐ¾Ð²Ð¸Ñ…, очікуючих конвеєрів"
@@ -1031,14 +1221,26 @@ msgstr "Увімкнути Auto DevOps"
msgid "Automatically marked as default internal user"
msgstr "Ðвтоматично позначено Ñк внутрішній кориÑтувач за замовчуваннÑм"
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "ДоÑтупно"
-msgid "Available group Runners : %{runners}"
-msgstr "ДоÑтупні групові Runner'и: %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
-msgid "Available group Runners : %{runners}."
-msgstr "ДоÑтупні групові Runner'и: %{runners}."
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr "Ðватар буде видалено. Ви впевнені?"
@@ -1134,13 +1336,13 @@ msgid "Badges|e.g. %{exampleUrl}"
msgstr "напр. %{exampleUrl}"
msgid "BatchComments|Delete all pending comments"
-msgstr ""
+msgstr "Видалити вÑÑ– коментарі в очікуванні"
msgid "BatchComments|Discard review?"
-msgstr ""
+msgstr "Відхилити відгук?"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð²Ñ–Ð´Ñ…Ð¸Ð»Ð¸Ñ‚Ð¸ ваш відгук, що призведе до Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ… ваших коментарів в очікуванні. Видалені коментарі %{strong_start}не можливо%{strong_end} буде відновити."
msgid "Begin with the selected commit"
msgstr "Почати із виділеного коміту"
@@ -1223,6 +1425,12 @@ msgstr "Імпорт з Bitbucket Server"
msgid "Bitbucket import"
msgstr "Імпорт з Bitbucket"
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr "Блог"
@@ -1232,13 +1440,6 @@ msgstr "Дошки"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Гілка %{branchName} відÑÑƒÑ‚Ð½Ñ Ð² репозиторії цього проекту."
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] "Гілка (%{branch_count})"
-msgstr[1] "Гілки (%{branch_count})"
-msgstr[2] "Гілок (%{branch_count})"
-msgstr[3] "Гілок (%{branch_count})"
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "Гілка <strong>%{branch_name}</strong> Ñтворена. Ð”Ð»Ñ Ð½Ð°Ñтройки автоматичного Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð±ÐµÑ€Ñ–Ñ‚ÑŒ GitLab CI Yaml-шаблон Ñ– закомітьте зміни. %{link_to_autodeploy_doc}"
@@ -1392,21 +1593,36 @@ msgstr "ПереглÑд файлів"
msgid "Browse files"
msgstr "ПереглÑд файлів"
-msgid "Built-In"
-msgstr "Вбудований"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
msgid "Business metrics (Custom)"
msgstr "Ð‘Ñ–Ð·Ð½ÐµÑ Ð¼ÐµÑ‚Ñ€Ð¸ÐºÐ¸ (ВлаÑні)"
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "від"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr "CI буде працювати з викориÑтаннÑм облікових даних, визначених вище."
@@ -1426,7 +1642,7 @@ msgid "CICD|Auto DevOps"
msgstr "Auto DevOps"
msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
-msgstr "Auto DevOps буду автоматично збирати, теÑтувати та розгортати ваш заÑтоÑунок на оÑнові Ñтандартної конфігурації неперервної інтеграції та розгортаннÑ."
+msgstr "Auto DevOps буде автоматично збирати, теÑтувати та розгортати ваш заÑтоÑунок на оÑнові Ñтандартної конфігурації неперервної інтеграції та розгортаннÑ."
msgid "CICD|Automatic deployment to staging, manual deployment to production"
msgstr "Ðвтоматичне Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° staging, ручне Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production"
@@ -1435,7 +1651,7 @@ msgid "CICD|Continuous deployment to production"
msgstr "Безперервне Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "Безперервне Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production за допомогою поÑтупового інкрементного розгортаннÑ"
msgid "CICD|Default to Auto DevOps pipeline"
msgstr "За замовчуваннÑм Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð° Auto DevOps"
@@ -1443,12 +1659,6 @@ msgstr "За замовчуваннÑм Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð° Auto DevOps"
msgid "CICD|Deployment strategy"
msgstr "Ð¡Ñ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr "Ðеобхідно вказати доменне Ñ–Ð¼â€™Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€ÐµÐºÑ‚Ð½Ð¾Ñ— роботи Ñтратегії розгортаннÑ."
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr "Ðе вказуйте тут домен, Ñкщо ви налаштовуєте декілька клаÑтерів Kubernetes за допомогою Auto DevOps."
-
msgid "CICD|Jobs"
msgstr "ЗавданнÑ"
@@ -1458,18 +1668,27 @@ msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Auto DevOps"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr "Конвеєр Auto DevOps буде запущено, Ñкщо не буде знайдено альтернативного файлу конфігуріції CI."
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
-msgstr "Вам потрібно вказати домен, Ñкщо ви хочете викориÑтовувати Auto Review Apps та Auto Deploy."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
msgid "CICD|instance enabled"
msgstr "ІнÑÑ‚Ð°Ð½Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾"
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL зворотнього виклику"
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr "Ðе можу знайти HEAD-коміт Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гілки"
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "СкаÑувати"
@@ -1482,12 +1701,21 @@ msgstr "Ðеможливо злити автоматично"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Ðеможливо змінити керований клаÑтер Kubernetes"
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr "Відбиток Ñертифіката"
msgid "Change Weight"
msgstr "Змінити вагу"
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr "Змінити шаблон"
@@ -1509,12 +1737,12 @@ msgstr "Ðнулювати коміт"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Це Ñтворить новий коміт, щоб анулювати Ñ–Ñнуючі зміни."
-msgid "Changelog"
-msgstr "СпиÑок змін"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "Зміни відображаютьÑÑ Ñ‚Ð°Ðº, ніби <b>редакціÑ-джерело</b> була злита в <b>цільову редакцію</b>."
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "СтатиÑтика"
@@ -1522,11 +1750,17 @@ msgid "Chat"
msgstr "Чат"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr "ПереглÑньте %{docs_link_start}документацію%{docs_link_end}."
+
+msgid "Check your .gitlab-ci.yml"
msgstr ""
msgid "Checking %{text} availability…"
msgstr "Перевірка доÑтупноÑÑ‚Ñ– %{text}…"
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "Перевірка доÑтупноÑÑ‚Ñ– гілки..."
@@ -1548,6 +1782,12 @@ msgstr "Виберіть файл ..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Виберіть гілку чи тег (напр. %{master}) або введіть коміт (напр. %{sha}) Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду змін або Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ."
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr "Виберіть тему-шаблон..."
@@ -1566,6 +1806,9 @@ msgstr "Виберіть файл..."
msgid "Choose the top-level group for your repository imports."
msgstr "Оберіть групу найвищого Ñ€Ñ–Ð²Ð½Ñ Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ репозиторіїв."
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr "Виберіть групи Ð´Ð»Ñ Ñинхронізації на цей вторинний вузол."
@@ -1585,7 +1828,7 @@ msgid "CiStatusLabel|created"
msgstr "Ñтворено"
msgid "CiStatusLabel|delayed"
-msgstr ""
+msgstr "відкладено"
msgid "CiStatusLabel|failed"
msgstr "невдало"
@@ -1606,7 +1849,7 @@ msgid "CiStatusLabel|skipped"
msgstr "пропущено"
msgid "CiStatusLabel|waiting for delayed job"
-msgstr ""
+msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´ÐºÐ»Ð°Ð´ÐµÐ½Ð¾Ð³Ð¾ завданнÑ"
msgid "CiStatusLabel|waiting for manual action"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÑƒÑ‡Ð½Ð¸Ñ… дій"
@@ -1621,7 +1864,7 @@ msgid "CiStatusText|created"
msgstr "Ñтворено"
msgid "CiStatusText|delayed"
-msgstr ""
+msgstr "відкладено"
msgid "CiStatusText|failed"
msgstr "невдало"
@@ -1659,8 +1902,8 @@ msgstr "Ð’ÑÑ– Ñередовища"
msgid "CiVariable|Create wildcard"
msgstr "Створити шаблон"
-msgid "CiVariable|Error occured while saving variables"
-msgstr "Помилка при збереженні змінних"
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
msgid "CiVariable|New environment"
msgstr "Ðове Ñередовище"
@@ -1680,6 +1923,12 @@ msgstr "Перевірка невдала"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "не доÑтупно: %{reason}"
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr "ОчиÑтити пошук"
@@ -1719,20 +1968,44 @@ msgstr "Пароль ключа аутентифікації клієнта"
msgid "Clients"
msgstr "Клієнти"
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr "Клонувати репозиторій"
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr "Закрити"
msgid "Close epic"
msgstr "Закрити епік"
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr "Закрито"
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
-msgstr "Закриті проблеми"
+msgstr "Закриті задачі"
+
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} були уÑпішно вÑтановлені на ваш Kubernetes-клаÑтер"
@@ -1740,7 +2013,7 @@ msgstr "%{appList} були уÑпішно вÑтановлені на ваш Ku
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr "%{boldNotice} Це додаÑÑ‚ÑŒ додаткові реÑурÑи, такі Ñк баланÑувальник навантаженнÑ, Ñкий може збільшити витрати в залежноÑÑ‚Ñ– від провайдера хоÑтингу, на Ñкому вÑтановлено клаÑтер Kubernetes. Якщо ви викориÑтовуєте Google Kubernetes Engine, ви можете %{pricingLink}."
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1753,10 +2026,10 @@ msgid "ClusterIntegration|Add a Kubernetes cluster integration"
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 до вашої групи автоматично зробить його доÑтупним у вÑÑ–Ñ… ваших проектах. ВикориÑтовуйте Review Apps, розгортайте заÑтоÑунки Ñ– легко запуÑкайте Ñвої конвеєри Ð´Ð»Ñ Ð²ÑÑ–Ñ… проектів з викориÑтаннÑм цього клаÑтера."
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— до вашої групи надаÑÑ‚ÑŒ доÑтуп до клаÑтера у вÑÑ–Ñ… ваших проектах."
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Детальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— із цим Kubernetes-клаÑтером"
@@ -1764,27 +2037,42 @@ msgstr "Детальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— із ци
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr "ПіÑÐ»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ingress, вам необхідно направити Ñвій DNS на згенеровану зовнішню IP-адреÑу, щоб переглÑнути ваш заÑтоÑунок піÑÐ»Ñ Ð¹Ð¾Ð³Ð¾ розгортаннÑ. %{ingressHelpLink}"
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "Помилка при отриманні зон проекту: %{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr "Помилка при отриманні ваших проектів: %{error}"
-
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
-msgstr "Помилка при отриманні типів машин зони: %{error}"
-
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr "Помилка під Ñ‡Ð°Ñ Ð·'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· Google Cloud API. Будь лаÑка, Ñпробуйте знову пізніше."
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "ЗаÑтоÑунки"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr "Ви впевнені, що хочете видалити інтеграцію із цим Kubernetes-клаÑтером? Це не призведе до Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñамого клаÑтера."
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr "Сертифікат центру Ñертифікації"
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Ðабір Ñертифікатів (формат PEM)"
@@ -1794,6 +2082,9 @@ msgstr "Виберіть, Ñкі заÑтоÑунки необхідно вÑÑ‚Ð
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Виберіть, Ñке із ваших Ñередовищ буде викориÑтовувати цей клаÑтер."
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Скопіювати API URL"
@@ -1806,6 +2097,9 @@ msgstr "Копіювати IP-адреÑу Ingress в буфер обміну"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr "Скопіювати Ñ–Ð¼â€™Ñ Ñ…Ð¾Ñта Jupyter в буфер обміну"
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Скопіювати Ñ–Ð¼â€™Ñ Kubernetes-клаÑтера"
@@ -1833,6 +2127,15 @@ 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 "Кожен новий обліковий Ð·Ð°Ð¿Ð¸Ñ Ð² Google Cloud Platform (GCP) отримує $300 на Ñвій рахунок при %{sign_up_link}. GitLab (у партнерÑтві із Google) пропонує додаткові $200 Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… облікових запиÑів GCP, Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸ÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ”ÑŽ GitLab з Google Kubernetes Engine."
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr "ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ‚Ð¸Ð¿Ñ–Ð² машин"
@@ -1861,13 +2164,13 @@ msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "проекті Google Kubernetes Engine"
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "КлаÑтер групи"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helm Ñпрощує вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°ÑтоÑунками Kubernetes. Tiller працює вÑередині вашого клаÑтеру Kubernetes Ñ– керує релізами charts."
msgid "ClusterIntegration|Hide"
msgstr "Приховати"
@@ -1885,7 +2188,7 @@ msgid "ClusterIntegration|Ingress IP Address"
msgstr "Ingress IP-адреÑа"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
-msgstr ""
+msgstr "Ingress дозволÑÑ” вам маршрутизувати запити до Ñлужб на оÑнові запитаного хоÑта або шлÑху, об'єднуючи Ñ€Ñд ÑервіÑів в одну точку входу."
msgid "ClusterIntegration|Install"
msgstr "Ð’Ñтановити"
@@ -1905,6 +2208,12 @@ msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ ÐºÐ»Ð°Ñтерної автоматизації Kub
msgid "ClusterIntegration|Integration status"
msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ—"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Ð†Ð¼â€™Ñ Ñ…Ð¾Ñта Jupyter"
@@ -1912,12 +2221,18 @@ msgid "ClusterIntegration|JupyterHub"
msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
-msgstr ""
+msgstr "JupyterHub, багатокориÑтувацький Хаб, Ñкий Ñтворює, керує Ñ– перенаправлÑÑ” запити між багатьма екземплÑрами однокориÑтувацьких Ñерверів Jupyter. JupyterHub може викориÑтовуватиÑÑ Ð´Ð»Ñ Ð¾Ð±ÑÐ»ÑƒÐ³Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¸Ñ… блокнотів групи Ñтудентів, корпоративної групи аналітиків даних, науково-доÑлідницької групи."
msgid "ClusterIntegration|Knative"
msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
+msgstr "Доменне ім'Ñ Knative:"
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster"
@@ -1939,7 +2254,7 @@ msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google
msgstr "Kubernetes-клаÑтер був уÑпішно Ñтворений на Google Kubernetes Engine. Оновіть Ñторінку, щоб побачити параметри клаÑтера"
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
+msgstr "Kubernetes-клаÑтери дозволÑÑŽÑ‚ÑŒ вам викориÑтовувати Review Apps, розгортати ваші заÑтоÑунки, запуÑкати конвеєри Ñ– багато іншого проÑтим ÑпоÑобом."
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Kubernetes-клаÑтери можуть бути викориÑтані Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð·Ð°ÑтоÑунків Ñ– викориÑÑ‚Ð°Ð½Ð½Ñ Review Apps Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
@@ -1954,6 +2269,9 @@ msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про групові клаÑтери Kubernetes"
+
+msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1996,7 +2314,7 @@ msgid "ClusterIntegration|Please make sure that your Google account meets the fo
msgstr "Будь-лаÑка впевнітьÑÑ, що ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Google задовольнÑÑ” наÑтупним вимогам:"
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
-msgstr ""
+msgstr "Ðаправте ваш DNS на цю згенеровану IP-адреÑу, щоб отримати доÑтуп до вашого додатку, піÑÐ»Ñ Ð¹Ð¾Ð³Ð¾ розгортаннÑ."
msgid "ClusterIntegration|Project cluster"
msgstr "КлаÑтер проекту"
@@ -2011,7 +2329,7 @@ msgid "ClusterIntegration|Prometheus"
msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
-msgstr ""
+msgstr "Prometheus — це ÑиÑтема моніторингу з відкритим вихідним кодом з %{gitlabIntegrationLink} Ð´Ð»Ñ Ð¼Ð¾Ð½Ñ–Ñ‚Ð¾Ñ€Ð¸Ð½Ð³Ñƒ розгорнутих додатків."
msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr "КлаÑтер з підтримкою RBAC"
@@ -2029,11 +2347,14 @@ msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from th
msgstr "Видалити конфігурацію Kubernetes-клаÑтера Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту. Це не призведе до Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñамого клаÑтера."
msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
-msgstr ""
+msgstr "При бажанні ви можете замінити це на ваше влаÑне ім'Ñ Ñ…Ð¾Ñта. Якщо ви це зробите, ÑпрÑмуйте ім'Ñ Ñ…Ð¾Ñта на IP-адреÑу Ingress зверху."
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Запит про початок вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ðµ виконано"
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr "Зберегти зміни"
@@ -2076,15 +2397,21 @@ msgstr "Показати"
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "ЩоÑÑŒ пішло не так з нашого боку."
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr "Помилка при Ñтворенні вашого Kubernetes-клаÑтера на Google Kubernetes Engine"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Під Ñ‡Ð°Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ %{title} ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
-msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr "ВідбуваєтьÑÑ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ IP-адреÑи. Будь лаÑка, перевірте квоти вашого Kubernetes клаÑтера на Google Kubernetes Engine, Ñкщо це займає багато чаÑу."
+
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "Цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати наÑтупні права Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Kubernetes-клаÑтера в %{link_to_container_project}"
@@ -2097,6 +2424,18 @@ msgstr "Увімкнути/вимкнути Kubernetes-клаÑтер"
msgid "ClusterIntegration|Token"
msgstr "Токен"
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr "Перевірка Ñтану білінгу проекта"
@@ -2109,6 +2448,9 @@ msgstr "За допомогою підключеного до цього проÐ
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "Перед вÑтановленнÑм заÑтоÑунків нижче, необхідно вÑтановити Helm Tiller"
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати %{link_to_kubernetes_engine}"
@@ -2136,6 +2478,9 @@ msgstr "правильно налаштований"
msgid "ClusterIntegration|sign up"
msgstr "реєÑтрації"
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr "ВлаÑники коду"
@@ -2148,9 +2493,18 @@ msgstr "Згорнути"
msgid "Collapse sidebar"
msgstr "Згорнути панель"
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr "Коментар"
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr "Залишити коментар Ñ– завершити обговореннÑ"
@@ -2158,7 +2512,7 @@ msgid "Comment & unresolve discussion"
msgstr "Залишити коментар Ñ– повторно відкрити обговореннÑ"
msgid "Comment form position"
-msgstr ""
+msgstr "Ð Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð¸ коментарÑ"
msgid "Comments"
msgstr "Коментарі"
@@ -2170,16 +2524,15 @@ msgstr[1] "Коміта"
msgstr[2] "Комітів"
msgstr[3] "Комітів"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] "Коміт (%{commit_count})"
-msgstr[1] "Коміта (%{commit_count})"
-msgstr[2] "Комітів (%{commit_count})"
-msgstr[3] "Комітів (%{commit_count})"
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "Коміт-повідомелннÑ"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "ТриваліÑÑ‚ÑŒ оÑтанніх 30 комітів у хвилинах"
@@ -2243,6 +2596,9 @@ msgstr "ПорівнÑти Git-редакції"
msgid "Compare Revisions"
msgstr "ПорівнÑÐ½Ð½Ñ Ñ€ÐµÐ´Ð°ÐºÑ†Ñ–Ð¹"
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr "ПорівнÑти зміни з оÑтаннім комітом"
@@ -2270,10 +2626,16 @@ msgstr "Конфіденційний"
msgid "Confidentiality"
msgstr "КонфіденційніÑÑ‚ÑŒ"
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr "Ðалаштувати таймаути Gitaly."
msgid "Configure Tracing"
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð’Ñ–Ð´ÑтеженнÑ"
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2286,10 +2648,10 @@ msgid "Configure push mirrors."
msgstr "Ðалаштуйте вихідні дзеркала."
msgid "Configure storage path settings."
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑˆÐ»Ñху Ñховища."
msgid "Configure the %{link} integration."
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— з %{link}."
msgid "Configure the way a user creates a new account."
msgstr "Ðалаштувати ÑпоÑіб ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачем нового облікового запиÑу."
@@ -2309,6 +2671,9 @@ msgstr "Підключіть ваші зовнішні репозиторії, Ñ
msgid "Connecting..."
msgstr "З'єднаннÑ..."
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr "РеєÑÑ‚Ñ€ Контейнерів"
@@ -2357,6 +2722,9 @@ msgstr "За допомогою вбудованого в GitLab реєÑтру
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Ви також можете викориÑтовувати %{deploy_token} Ð´Ð»Ñ Ð´Ð¾Ñтупу тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾ образів у реєÑтрі."
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr "Продовжити"
@@ -2372,8 +2740,8 @@ msgstr "Зробити внеÑок в GitLab"
msgid "Contribution"
msgstr "ВнеÑок"
-msgid "Contribution guide"
-msgstr "ІнÑÑ‚Ñ€ÑƒÐºÑ†Ñ–Ñ Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr "ВнеÑки за <strong>%{calendar_date}</strong>"
@@ -2408,21 +2776,27 @@ msgstr "Задати макÑимальну кількіÑÑ‚ÑŒ потоків д
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr "Ð’Ñтановіть макÑимальну кількіÑÑ‚ÑŒ паралельних операцій перевірки Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Geo-вузла"
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr "Ð†Ð½Ð´ÐµÐºÑ ConvDev"
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %{protocol}"
-msgid "Copy HTTPS clone URL"
-msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· HTTPS"
-
msgid "Copy ID to clipboard"
msgstr "Скопіювати ID в буфер обміну"
msgid "Copy SSH clone URL"
msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· SSH"
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr "Скопіюйте відкритий SSH-ключ в буфер обміну"
@@ -2447,14 +2821,11 @@ msgstr "Копіювати адреÑу електронної пошти у бÑ
msgid "Copy link"
msgstr "Скопіювати поÑиланнÑ"
-msgid "Copy name to clipboard"
-msgstr "Скопіювати ім'Ñ Ð² буфер обміну"
-
msgid "Copy reference to clipboard"
msgstr "Скопіювати поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð² буфер обміну"
msgid "Copy secret to clipboard"
-msgstr ""
+msgstr "Скопіювати Ñекрет в буфер обміну"
msgid "Copy to clipboard"
msgstr "Копіювати в буфер обміну"
@@ -2463,7 +2834,7 @@ msgid "Copy token to clipboard"
msgstr "Скопіювати токен в буфер обміну"
msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°. Ð”Ð»Ñ ÑƒÑÑƒÐ½ÐµÐ½Ð½Ñ Ð½ÐµÐ¿Ð¾Ð»Ð°Ð´Ð¾Ðº, прочитайте %{linkStart}документацію%{linkEnd}"
msgid "Create"
msgstr "Створити"
@@ -2471,6 +2842,9 @@ msgstr "Створити"
msgid "Create New Directory"
msgstr "Створити новий каталог"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr "Створити нову гілку"
@@ -2478,7 +2852,10 @@ msgid "Create a new branch and merge request"
msgstr "Створити нову гілку Ñ– запит на злиттÑ"
msgid "Create a new issue"
-msgstr "Створити нову проблему"
+msgstr "Створити нову задачу"
+
+msgid "Create a new repository"
+msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Створіть токен доÑтупу Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ аккаунта, щоб відправлÑти та отримувати через %{protocol}."
@@ -2508,10 +2885,10 @@ msgid "Create group label"
msgstr "Створити мітку групи"
msgid "Create issue"
-msgstr "Створити проблему"
+msgstr "Створити задачу"
msgid "Create lists from labels. Issues with that label appear in that list."
-msgstr "Створити ÑпиÑок на оÑнові міток. Ð’ ньому будуть проблеми з такими мітками."
+msgstr "Створити ÑпиÑок на оÑнові міток. Ð’ ньому будуть задачі з такими мітками."
msgid "Create merge request"
msgstr "Створити запит на злиттÑ"
@@ -2519,6 +2896,9 @@ msgstr "Створити запит на злиттÑ"
msgid "Create merge request and branch"
msgstr "Створити запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° гілку"
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "Створити нову гілку"
@@ -2585,14 +2965,11 @@ msgstr "Профіль"
msgid "CurrentUser|Settings"
msgstr "ÐалаштуваннÑ"
-msgid "Custom"
-msgstr "ВлаÑний"
-
msgid "Custom CI config path"
msgstr "КориÑтувацький шлÑÑ… до CI config"
msgid "Custom hostname (for private commit emails)"
-msgstr ""
+msgstr "ВлаÑне ім'Ñ Ñ…Ð¾Ñта (Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¸Ñ… повідомлень електронної пошти)"
msgid "Custom notification events"
msgstr "КориÑтувацькі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ про події"
@@ -2603,6 +2980,9 @@ msgstr "Спеціальні рівні Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÑпівпадÐ
msgid "Custom project templates"
msgstr "ВлаÑні шаблони проектів"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²"
@@ -2612,9 +2992,15 @@ msgstr "Ðалаштуйте, Ñк адреÑи електронної поштÐ
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "Ðалаштуйте, Ñк адреÑи електронної пошти та імена кориÑтувачів Google Code імпортуютьÑÑ Ð² GitLab. Ðа наÑтупному кроці ви зможете вибрати проекти, Ñкі потрібно імпортувати."
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize language and region related settings."
msgstr ""
+msgid "Customize your merge request approval settings."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr "Ðалаштуйте конфігурацію конвеєра, переглÑньте Ñтан Ñвого конвеєра Ñ– звіт про покриттÑ."
+
msgid "Cycle Analytics"
msgstr "Ðналіз циклу"
@@ -2625,7 +3011,7 @@ msgid "CycleAnalyticsStage|Code"
msgstr "ÐапиÑÐ°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ"
msgid "CycleAnalyticsStage|Issue"
-msgstr "Проблема"
+msgstr "Задача"
msgid "CycleAnalyticsStage|Plan"
msgstr "ПлануваннÑ"
@@ -2634,7 +3020,7 @@ msgid "CycleAnalyticsStage|Production"
msgstr "Production"
msgid "CycleAnalyticsStage|Review"
-msgstr "ЗатвердженнÑ"
+msgstr "Перевірка"
msgid "CycleAnalyticsStage|Staging"
msgstr "Staging"
@@ -2642,6 +3028,9 @@ msgstr "Staging"
msgid "CycleAnalyticsStage|Test"
msgstr "ТеÑтуваннÑ"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr "Панель керуваннÑ"
@@ -2651,6 +3040,9 @@ msgstr "Ð’ÑÑ–"
msgid "DashboardProjects|Personal"
msgstr "ОÑобиÑÑ‚Ñ–"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr "Вибір дати"
@@ -2663,6 +3055,9 @@ msgstr "груд."
msgid "December"
msgstr "грудень"
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr "Відхити та вийти"
@@ -2672,6 +3067,12 @@ msgstr "Гілка за замовчуваннÑм"
msgid "Default classification label"
msgstr "Мітка клаÑифікації за замовчуваннÑм"
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr "За замовчуваннÑм: безпоÑередньо імпортувати адреÑу електронної пошти або ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Google Code"
@@ -2681,17 +3082,20 @@ msgstr "По замовчуванню: викориÑтовувати ідент
msgid "Define a custom pattern with cron syntax"
msgstr "Визначте влаÑний шаблон за допомогою ÑинтакÑиÑу cron"
-msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+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|Start now"
msgstr "Почати зараз"
msgid "DelayedJobs|Unschedule"
-msgstr ""
+msgstr "СкаÑувати Розклад"
msgid "DelayedJobs|delayed"
msgstr "відкладено"
@@ -2711,6 +3115,12 @@ msgstr "Видалити коментар"
msgid "Delete list"
msgstr "Видалити ÑпиÑок"
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr "Видалено"
@@ -2847,11 +3257,14 @@ msgstr "Ваш новий токер розгортаннÑ"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Створено ваш новий токен Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ."
-msgid "Deployed to"
+msgid "Deployed"
msgstr ""
+msgid "Deployed to"
+msgstr "Розгорнуто на"
+
msgid "Deploying to"
-msgstr ""
+msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾"
msgid "Deprioritize label"
msgstr "Зменшити пріоритет мітки"
@@ -2863,7 +3276,7 @@ msgid "Description"
msgstr "ОпиÑ"
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
-msgstr "Шаблони опиÑу дозволÑÑŽÑ‚ÑŒ визначити конкретні шаблони обговорень та запитів на Ð·Ð»Ð¸Ð²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проекту."
+msgstr "Шаблони опиÑу дозволÑÑŽÑ‚ÑŒ визначити конкретні шаблони задач та запитів на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проекту."
msgid "Description:"
msgstr "ОпиÑ:"
@@ -2874,14 +3287,17 @@ msgstr "Знищити"
msgid "Details"
msgstr "Деталі"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr "ВиÑÐ²Ð»ÐµÐ½Ð½Ñ ÐºÐ»ÑŽÑ‡Ñ–Ð² хоÑта"
msgid "Diff content limits"
-msgstr ""
+msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ñ–Ð²Ð½ÑÐ½Ð½Ñ Ð·Ð¼Ñ–Ñту"
msgid "Diff limits"
-msgstr ""
+msgstr "Diff обмеженнÑ"
msgid "Diffs|No file name available"
msgstr "Ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ не доÑтупне"
@@ -2904,36 +3320,51 @@ msgstr "Вимкнути Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
msgid "Disable group Runners"
msgstr "Вимкнути групові Runner'и"
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
-msgstr "СкаÑувати"
+msgstr "Відхилити"
msgid "Discard all changes"
-msgstr "СкаÑувати вÑÑ– зміни"
+msgstr "Відхилити вÑÑ– зміни"
msgid "Discard all unstaged changes?"
-msgstr "СкаÑувати вÑÑ– неіндекÑовані зміни?"
+msgstr "Відхилити вÑÑ– неіндекÑовані зміни?"
msgid "Discard changes"
msgstr "Відхилити зміни"
msgid "Discard changes to %{path}?"
-msgstr "СкаÑувати зміни до %{path}?"
+msgstr "Відхилити зміни до %{path}?"
msgid "Discard draft"
msgstr "Видалити чернетку"
msgid "Discard review"
-msgstr ""
+msgstr "Відхилити перевірку"
-msgid "Discover GitLab Geo."
-msgstr "Відкрийте GitLab Geo."
+msgid "Discover GitLab Geo"
+msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "Відкрийте Ð´Ð»Ñ Ñебе групи, проекти та фрагменти коду. ПоділітьÑÑ Ñвоїми проектами з іншими"
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr "Відхилити"
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "Відхилити блок вÑтупу до Ðналитики Циклу"
@@ -2941,7 +3372,7 @@ msgid "Dismiss Merge Request promotion"
msgstr "Видалити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ запит на злиттÑ"
msgid "Dismiss trial promotion"
-msgstr ""
+msgstr "Відхилити пробну верÑÑ–ÑŽ"
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Ви хочете налаштувати, Ñк адреÑи електронної пошти та імена кориÑтувачів будуть імпортовані з Google Code в GitLab?"
@@ -2961,6 +3392,12 @@ msgstr "Готово"
msgid "Download"
msgstr "Завантажити"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "Завантажити tar"
@@ -2985,6 +3422,9 @@ msgstr "ПроÑте порівнÑÐ½Ð½Ñ (diff)"
msgid "DownloadSource|Download"
msgstr "Завантажити"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr "Дизлайки"
@@ -3000,9 +3440,15 @@ msgstr "Кожен Runner може бути в одному із таких ÑÑ‚
msgid "Edit"
msgstr "Редагувати"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr "Редагувати мітку"
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Редагувати Розклад Конвеєра %{id}"
@@ -3012,6 +3458,12 @@ msgstr "Редагувати Ñніпет"
msgid "Edit application"
msgstr "Редагувати заÑтоÑунок"
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr "Редагуйте файли в редакторі і закомітьте зміни тут"
@@ -3021,11 +3473,14 @@ msgstr "Редагувати групу: %{group_name}"
msgid "Edit identity for %{user_name}"
msgstr "Редагувати ідентифікацію Ð´Ð»Ñ %{user_name}"
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr "Elasticsearch"
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
+msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð· Elasticsearch. Elasticsearch AWS IAM."
msgid "Email"
msgstr "Електронна пошта"
@@ -3039,6 +3494,9 @@ msgstr "ÐдреÑи електронної пошти"
msgid "Embed"
msgstr "Вбудувати"
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr "Увімкнути"
@@ -3063,6 +3521,9 @@ msgstr "Включити і налаштувати метрики Prometheus."
msgid "Enable classification control using an external service"
msgstr "Увімкнути контроль за клаÑифікацією за допомогою зовнішньої Ñлужби"
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr "Увімкнути Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
@@ -3078,9 +3539,18 @@ msgstr "Увімкнути чи вимкнути перевірку верÑÑ–Ñ—
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "Увімкнути reCAPTCHA або Akismet та вÑтановити Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾ IP."
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr "Увімкнути панель продуктивноÑÑ‚Ñ– Ð´Ð»Ñ Ð´Ð°Ð½Ð¾Ñ— групи."
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr "Увімкнути викориÑÑ‚Ð°Ð½Ð½Ñ ping"
@@ -3093,14 +3563,20 @@ msgstr "Увімкнено"
msgid "Ends at (UTC)"
msgstr "ЗавершуєтьÑÑ Ð¾ (за Грінвічем)"
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "Введіть URL-адреÑу вашого Bitbucket Server Ñ– ключ доÑтупу"
msgid "Enter the issue description"
-msgstr "Введіть Ð¾Ð¿Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸"
+msgstr "Введіть Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ–"
msgid "Enter the issue title"
-msgstr "Введіть назву проблеми"
+msgstr "Введіть назву задачі"
msgid "Enter the merge request description"
msgstr "Введіть Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ"
@@ -3108,9 +3584,27 @@ msgstr "Введіть Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ"
msgid "Enter the merge request title"
msgstr "Введіть назву запиту на злиттÑ"
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr "Середовища"
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Виникла помилка при завантаженні Ñередовищ."
@@ -3186,6 +3680,9 @@ msgstr "Зупинити"
msgid "Environments|Stop environment"
msgstr "Зупинити Ñередовище"
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Оновлено"
@@ -3198,9 +3695,6 @@ msgstr "захищені"
msgid "Epic"
msgstr "Епік"
-msgid "Epic will be removed! Are you sure?"
-msgstr "Епік буде видалено! Ви впевнені?"
-
msgid "Epics"
msgstr "Епіки"
@@ -3210,8 +3704,8 @@ msgstr "План-графік епіків"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Епіки дозволÑÑŽÑ‚ÑŒ керувати вашим портфелем проектів ефективніше та з меншими зуÑиллÑми"
-msgid "Epics|An error occurred while saving %{epicDateType} date"
-msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при збереженні дати %{epicDateType}"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
msgid "Epics|How can I solve this?"
msgstr "Як Ñ Ð¼Ð¾Ð¶Ñƒ це вирішити?"
@@ -3220,16 +3714,16 @@ msgid "Epics|More information"
msgstr "Детальніше"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
-msgstr ""
+msgstr "Ці дати впливають на те, Ñк ваші епіки відображатимутьÑÑ Ð½Ð° плані-графіку. Дати з етапів берутьÑÑ Ð· етапів, призначених до задач у цьому епіку. Ви також можете задавати фікÑовані дати, або видалÑти Ñ—Ñ…."
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
-msgstr ""
+msgstr "Щоб запланувати %{epicDateType} дату вашого епіку на оÑнові етапів, призначте етап з %{epicDateType} датою Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-Ñкої задачі в цьому епіку."
msgid "Epics|due"
-msgstr ""
+msgstr "закінченнÑ"
msgid "Epics|start"
-msgstr ""
+msgstr "початок"
msgid "Error"
msgstr "Помилка"
@@ -3237,9 +3731,15 @@ msgstr "Помилка"
msgid "Error Reporting and Logging"
msgstr "Звіти про помилки та логуваннÑ"
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr "Помилка при Ñтворенні епіку"
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr "Помилка Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… учаÑників."
@@ -3282,9 +3782,15 @@ msgstr "Помилка при завантаженні шаблону."
msgid "Error occurred when toggling the notification subscription"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñки на ÑповіщеннÑ"
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr "Помилка при збереженні мітки."
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr "Помилка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑтатуÑу Ð´Ð»Ñ Ð²ÑÑ–Ñ… задач."
@@ -3294,6 +3800,12 @@ msgstr "Помилка при оновленні ÑтатуÑу задачі."
msgid "Error while loading the merge request. Please try again."
msgstr "Помилка при завантаженні запита на злиттÑ. Будь лаÑка, Ñпробуйте знову."
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr "За оцінками"
@@ -3304,7 +3816,7 @@ msgid "EventFilterBy|Filter by comments"
msgstr "Фільтрувати по коментарÑм"
msgid "EventFilterBy|Filter by issue events"
-msgstr "Фільтрувати по проблемах"
+msgstr "Фільтрувати по задачах"
msgid "EventFilterBy|Filter by merge events"
msgstr "Фільтрувати по запитам на злиттÑ"
@@ -3315,6 +3827,12 @@ msgstr "Фільтрувати за подіÑми Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ (pus
msgid "EventFilterBy|Filter by team"
msgstr "Фільтрувати по команді"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Кожен день (в 4:00 ранку)"
@@ -3324,9 +3842,39 @@ msgstr "Кожен міÑÑць (1-го чиÑла о 4:00 ранку)"
msgid "Every week (Sundays at 4:00am)"
msgstr "Ð©Ð¾Ñ‚Ð¸Ð¶Ð½Ñ (в неділю о 4:00 ранку)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr "Кожен може зробити Ñвій внеÑок"
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr "Розгорнути"
@@ -3339,9 +3887,15 @@ msgstr "Розгорніть бічну панель"
msgid "Expiration date"
msgstr "Термін дії"
-msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgid "Expired %{expiredOn}"
msgstr ""
+msgid "Expires in %{expires_at}"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr "ПоÑÑніть проблему. У разі необхідноÑÑ‚Ñ– надайте поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° відповідну задачу або коментар."
+
msgid "Explore"
msgstr "ОглÑд"
@@ -3360,9 +3914,21 @@ msgstr "ОглÑд проектів"
msgid "Explore public groups"
msgstr "ПереглÑнути публічні групи"
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ ÐšÐ»Ð°ÑÐ¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ ÐŸÐ¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ Ðвторизації"
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ"
@@ -3397,13 +3963,16 @@ msgid "Failed to check related branches."
msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€Ð¸Ñ‚Ð¸ пов’Ñзані гілки."
msgid "Failed to deploy to"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ð½ÑƒÑ‚Ð¸ до"
msgid "Failed to load emoji list."
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑпиÑок Ñмайликів."
+
+msgid "Failed to load errors from Sentry"
msgstr ""
msgid "Failed to remove issue from board, please try again."
-msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ проблему з дошки, будь лаÑка, Ñпробуйте ще раз."
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ задачу з дошки, будь лаÑка, Ñпробуйте ще раз."
msgid "Failed to remove mirror."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ дзеркало."
@@ -3411,19 +3980,34 @@ msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ дзеркало."
msgid "Failed to remove the pipeline schedule"
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ розклад конвеєра"
-msgid "Failed to signing using smartcard authentication"
+msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr "Ðе вдалоÑÑ Ð¿Ñ–Ð´Ð¿Ð¸Ñати з викориÑтаннÑм перевірки автентичноÑÑ‚Ñ– Ñмарт-карти"
+
msgid "Failed to update issues, please try again."
-msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ проблеми. Будь лаÑка, Ñпробуйте ще раз."
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ задачі. Будь лаÑка, Ñпробуйте ще раз."
+
+msgid "Failed to upload object map file"
+msgstr ""
msgid "Failure"
msgstr "Помилка"
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "Швидше, бо повтоно викориÑтовує робочу облаÑÑ‚ÑŒ проекту (викориÑтовуючи clone, Ñкщо та відÑутнÑ)"
msgid "Feature Flags"
+msgstr "Перемикачі функцій"
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
msgstr ""
msgid "FeatureFlags|API URL"
@@ -3432,57 +4016,75 @@ msgstr "URL-адреÑа API"
msgid "FeatureFlags|Active"
msgstr "Ðктивний"
-msgid "FeatureFlags|Application name"
-msgstr ""
-
msgid "FeatureFlags|Configure"
msgstr "ÐалаштуваннÑ"
msgid "FeatureFlags|Configure feature flags"
-msgstr ""
+msgstr "Ðалаштувати перемикачі функцій"
msgid "FeatureFlags|Create feature flag"
+msgstr "Створити перемикач функції"
+
+msgid "FeatureFlags|Delete %{name}?"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
msgstr "ОпиÑ"
msgid "FeatureFlags|Edit %{feature_flag_name}"
-msgstr ""
+msgstr "Редагувати %{feature_flag_name}"
msgid "FeatureFlags|Edit Feature Flag"
+msgstr "Редагувати перемикач функції"
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
msgstr ""
msgid "FeatureFlags|Feature Flag"
+msgstr "Перемикач функції"
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr "Ðеактивний"
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr "Ð’Ñтановіть %{docs_link_start}ÑуміÑну клієнтÑьку бібліотеку%{docs_link_end} Ñ– вкажіть URL адреÑу API, назву заÑтоÑунку та ідентифікатор інÑтанÑа під Ñ‡Ð°Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ."
+
msgid "FeatureFlags|Instance ID"
+msgstr "Ідентифікатор ІнÑтанÑу"
+
+msgid "FeatureFlags|Loading Feature Flags"
msgstr ""
-msgid "FeatureFlags|More information"
+msgid "FeatureFlags|More Information"
msgstr ""
+msgid "FeatureFlags|More information"
+msgstr "Більше інформації"
+
msgid "FeatureFlags|Name"
msgstr "Ðазва"
@@ -3490,14 +4092,29 @@ msgid "FeatureFlags|New"
msgstr "Ðовий"
msgid "FeatureFlags|New Feature Flag"
-msgstr ""
+msgstr "Ðовий перемикач функції"
msgid "FeatureFlags|Save changes"
-msgstr ""
+msgstr "Зберегти зміни"
msgid "FeatureFlags|Status"
msgstr "СтатуÑ"
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr "лют."
@@ -3507,15 +4124,37 @@ msgstr "лютий"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "ÐŸÐ¾Ð»Ñ Ð½Ð° цій Ñторінці зараз недоÑтупні Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ, ви можете налаштувати"
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr "Шаблони файлів"
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "Файли"
-msgid "Files (%{human_size})"
-msgstr "Файлів на %{human_size}"
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "Заповніть Ð¿Ð¾Ð»Ñ Ð½Ð¸Ð¶Ñ‡Ðµ, увімкніть <strong>%{enable_label}</strong> та натиÑніть <strong>%{save_changes}</strong>"
@@ -3531,12 +4170,30 @@ msgstr "Фільтрувати відкриті за %{issuable_type}."
msgid "Filter by commit message"
msgstr "Фільтрувати за коміт-повідомленнÑм"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr "Фільтр..."
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "Пошук по шлÑху"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "Знайти файл"
@@ -3549,12 +4206,18 @@ msgstr "Знайдіть щойно розпакований <code>Takeout/Googl
msgid "Fingerprints"
msgstr "Відбитки пальців"
-msgid "Finish review"
+msgid "Finish editing this message first!"
msgstr ""
+msgid "Finish review"
+msgstr "Завершити перевірку"
+
msgid "Finished"
msgstr "Завершено"
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "Перший"
@@ -3600,11 +4263,14 @@ msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð² футері"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "Ð”Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ–Ñ… проектів будь-Ñкий зареєÑтрований кориÑтувач може переглÑдати конвеєри та отримати доÑтуп до інформації про роботу (логи та артефакти)"
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, відвідайте "
msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, будь лаÑка, ознайомтеÑÑ Ð· %{link_start_tag}документацією по налаштуванню Jaeger%{link_end_tag}"
msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, переглÑньте документацію по %{deactivating_usage_ping_link_start}деактивації даних про викориÑтаннÑ%{deactivating_usage_ping_link_end}."
@@ -3624,6 +4290,9 @@ msgstr "Форк із %{project_name} (видалено)"
msgid "Forking in progress"
msgstr "ВідбуваєтьÑÑ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€ÐºÑƒ"
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "Формат"
@@ -3631,7 +4300,7 @@ msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Знайдено помилки у вашому .gitlab-ci.yml:"
msgid "Free Trial of GitLab.com Gold"
-msgstr ""
+msgstr "Безкоштовна пробна верÑÑ–Ñ GitLab.com Gold"
msgid "From %{provider_title}"
msgstr "З %{provider_title}"
@@ -3652,7 +4321,7 @@ msgid "From Google Code"
msgstr "З Google Code"
msgid "From issue creation until deploy to production"
-msgstr "З моменту ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ до Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production"
+msgstr "З моменту ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– до Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production"
msgid "From merge request merge until deploy to production"
msgstr "Від Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð¾ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production"
@@ -3675,6 +4344,9 @@ msgstr "Загальні конвеєри"
msgid "Generate a default set of labels"
msgstr "Створити Ñтандартний набір міток"
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr "Geo"
@@ -3765,8 +4437,11 @@ msgstr "Без контрольної Ñуми"
msgid "GeoNodes|Out of sync"
msgstr "РозÑинхронізовані"
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
-msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²ÑƒÐ·Ð»Ð° зупинÑÑ” Ð¿Ñ€Ð¾Ñ†ÐµÑ Ñинхронізації. Ви впевнені?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
msgid "GeoNodes|Replication slot WAL"
msgstr "Слот реплікації WAL"
@@ -3840,6 +4515,9 @@ msgstr "Контрольні Ñуми вікі обчиÑлено Ð´Ð»Ñ Ð¿ÐµÑ€Ð
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr "Вікі перевірено із їхніми копіÑми на первинному вузлі"
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr "Ви налаштували Geo-вузли через незахищене HTTP-з’єднаннÑ. Ми рекомендуємо викориÑтовувати HTTPS."
@@ -3859,16 +4537,16 @@ msgid "Geo|All projects"
msgstr "Ð’ÑÑ– проекти"
msgid "Geo|All projects are being scheduled for re-check"
-msgstr ""
+msgstr "Ð’ÑÑ– проекти плануютьÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ñ— перевірки"
msgid "Geo|All projects are being scheduled for re-sync"
-msgstr ""
+msgstr "Ð’ÑÑ– проекти плануютьÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ñ— Ñинхронізації"
msgid "Geo|Batch operations"
-msgstr ""
+msgstr "Групові операції"
msgid "Geo|Could not remove tracking entry for an existing project."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´ÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ–Ñнуючого проекту."
msgid "Geo|Failed"
msgstr "Ðевдало"
@@ -3877,7 +4555,7 @@ msgid "Geo|File sync capacity"
msgstr "ПропуÑкна здатніÑÑ‚ÑŒ Ñинхронізації файлів"
msgid "Geo|Geo Status"
-msgstr ""
+msgstr "Geo ÑтатуÑ"
msgid "Geo|Groups to synchronize"
msgstr "Групи Ð´Ð»Ñ Ñинхронізації"
@@ -3885,6 +4563,9 @@ msgstr "Групи Ð´Ð»Ñ Ñинхронізації"
msgid "Geo|In sync"
msgstr "Синхронізовано"
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ ÑƒÑпішна ÑинхронізаціÑ"
@@ -3901,7 +4582,7 @@ msgid "Geo|Next sync scheduled at"
msgstr "ÐаÑтупна ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¾Ð²Ð°Ð½Ð° на"
msgid "Geo|Not synced yet"
-msgstr ""
+msgstr "Ðе Ñинхронізовано"
msgid "Geo|Pending"
msgstr "В очікуванні"
@@ -3913,7 +4594,7 @@ msgid "Geo|Pending verification"
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 "Проекти в певних групах"
@@ -3921,11 +4602,14 @@ msgstr "Проекти в певних групах"
msgid "Geo|Projects in certain storage shards"
msgstr "Проекти в певних Ñегментах Ñховищ"
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr "Повторна перевірка"
msgid "Geo|Recheck all projects"
-msgstr ""
+msgstr "Перевірити ще раз вÑÑ– проекти"
msgid "Geo|Redownload"
msgstr "Повторне завантаженнÑ"
@@ -3940,7 +4624,7 @@ msgid "Geo|Resync"
msgstr "Повторна ÑинхронізаціÑ"
msgid "Geo|Resync all projects"
-msgstr ""
+msgstr "Повторна ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð²ÑÑ–Ñ… проектів"
msgid "Geo|Retry count"
msgstr "КількіÑÑ‚ÑŒ Ñпроб"
@@ -3961,10 +4645,10 @@ msgid "Geo|Synchronization failed - %{error}"
msgstr "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ð°: %{error}"
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
-msgstr ""
+msgstr "Ð—Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´ÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ (%{project_id}) уÑпішно видалено."
msgid "Geo|Tracking entry will be removed. Are you sure?"
-msgstr ""
+msgstr "Буде видалено Ð·Ð°Ð¿Ð¸Ñ Ð¿Ñ€Ð¾ відÑтеженнÑ. Ви впевнені?"
msgid "Geo|Unknown state"
msgstr "Ðевідомий Ñтан"
@@ -3979,29 +4663,38 @@ msgid "Geo|Waiting for scheduler"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð»ÑŒÐ½Ð¸ÐºÐ°"
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
+msgstr "Ви знаходитеÑÑŒ на вторинному <b>лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ</b> Geo-вузлі. Якщо ви хочете внеÑти будь-Ñкі зміни, ви повинні відвідати %{primary_node}."
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
-msgstr ""
+msgstr "Ви знаходитеÑÑŒ на вторинному <b>лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ</b> Geo-вузлі. Ви зможете вноÑити лише обмежену кількіÑÑ‚ÑŒ змін та виконувати обмежений набір операцій з цієї Ñторінки."
msgid "Geo|You need a different license to use Geo replication"
msgstr "Вам потрібна інша Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ Ð½Ð° викориÑÑ‚Ð°Ð½Ð½Ñ Ð³ÐµÐ¾Ð³Ñ€Ð°Ñ„Ñ–Ñ‡Ð½Ð¾Ñ— реплікації"
msgid "Geo|misconfigured"
-msgstr ""
+msgstr "неправильно налаштований"
msgid "Geo|primary"
-msgstr ""
+msgstr "оÑновний"
msgid "Geo|secondary"
-msgstr ""
+msgstr "вторинний"
msgid "Get a free instance review"
+msgstr "Отримайте безкоштовну оцінку інÑтанÑа"
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
msgstr ""
msgid "Git"
msgstr "Git"
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr "URL Git-репозиторіÑ"
@@ -4029,9 +4722,15 @@ msgstr "Групові Runner'и Gitlab можуть виконувати код
msgid "GitLab Import"
msgstr "Імпорт з GitLab"
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr "GitLab КориÑтувач"
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr "ЕкÑпорт проекту GitLab"
@@ -4045,7 +4744,7 @@ msgid "GitLab.com import"
msgstr "Імпорт з GitLab.com"
msgid "GitLab’s issue tracker"
-msgstr "Трекер проблем GitLab"
+msgstr "Трекер задач GitLab"
msgid "Gitaly"
msgstr "Gitaly"
@@ -4062,6 +4761,9 @@ msgstr "URL-адреÑа хоÑту Gitea"
msgid "Gitea Import"
msgstr "Імпорт з Gitea"
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr "ПовернутиÑÑ"
@@ -4086,6 +4788,9 @@ msgstr "ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Google не %{link_to_documentation}. ПоÐ
msgid "Got it!"
msgstr "Зрозуміло!"
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr "Графік"
@@ -4105,7 +4810,7 @@ msgid "Group Runners"
msgstr "Групові Runner'и"
msgid "Group SAML must be enabled to test"
-msgstr ""
+msgstr "SAML Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸ повинна бути включена Ð´Ð»Ñ Ñ‚ÐµÑтуваннÑ"
msgid "Group URL"
msgstr "URL-адреÑа групи"
@@ -4117,7 +4822,7 @@ msgid "Group description"
msgstr "ÐžÐ¿Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¸"
msgid "Group description (optional)"
-msgstr ""
+msgstr "ÐžÐ¿Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¸ (необов'Ñзково)"
msgid "Group details"
msgstr "Деталі групи"
@@ -4131,15 +4836,18 @@ msgstr "Керівники групи можуть зареєÑтрувати г
msgid "Group name"
msgstr "Ðазва групи"
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr "Група: %{group_name}"
msgid "GroupRoadmap|From %{dateWord}"
msgstr "Від %{dateWord}"
-msgid "GroupRoadmap|Loading roadmap"
-msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð»Ð°Ð½Ñƒ-графіку"
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Проблема при завантаженні епіків"
@@ -4149,39 +4857,36 @@ msgstr "Вибачте, жоден епік не задовольнÑÑ” крит
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "План-графік епіків відображає Ñтан ваших епіків у чаÑÑ–"
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Ð”Ð»Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ змініть або видаліть фільтри. При поміÑÑчному переглÑді показуютьÑÑ ÐµÐ¿Ñ–ÐºÐ¸ лише за попередній, поточний та наÑтупні 5 міÑÑців: &ndash; від %{startDate} до %{endDate}."
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Ð”Ð»Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ змініть або видаліть фільтри. При поквартальному переглÑді показуютьÑÑ ÐµÐ¿Ñ–ÐºÐ¸ лише за попередній, поточний та наÑтупні 4 квартали: &ndash; від %{startDate} до %{endDate}."
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Ð”Ð»Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ змініть або видаліть фільтри. При потижневому переглÑді показуютьÑÑ ÐµÐ¿Ñ–ÐºÐ¸ лише за попередній, поточний та наÑтупні 4 тижні: &ndash; від %{startDate} до %{endDate}."
-
msgid "GroupRoadmap|Until %{dateWord}"
msgstr "До %{dateWord}"
msgid "GroupSettings|Badges"
msgstr "Значки"
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
msgid "GroupSettings|Customize your group badges."
msgstr "Ðалаштувати значки групи."
msgid "GroupSettings|Learn more about badges."
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про значки."
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Заборонити Ñпільний доÑтуп до проекту в рамках %{group} з іншими групами"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Цей параметр заÑтоÑовано до %{ancestor_group} Ñ– його було перевизначено в цій підгрупі."
@@ -4206,6 +4911,9 @@ msgstr "Групи"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "Групи також можуть бути вкладеними при викориÑтанні %{subgroup_docs_link_start}підгруп%{subgroup_docs_link_end}."
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr "ЧаÑто відвідувані"
@@ -4305,6 +5013,9 @@ msgstr "ТекÑÑ‚ Ñторінки довідки та url-адреÑа ÑтоÑ
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr "Це відкритий (публічний) SSH ключ, Ñкий потрібно додати на віддалений Ñервер. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, звернітьÑÑ Ð´Ð¾ документації."
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr "Сховати ввід ключів хоÑта"
@@ -4318,8 +5029,8 @@ msgstr[1] "Сховати значеннÑ"
msgstr[2] "Сховати значень"
msgstr[3] "Сховати значень"
-msgid "Hide whitespace changes"
-msgstr "Приховати зміни пробілів"
+msgid "Hide values"
+msgstr ""
msgid "History"
msgstr "ІÑторіÑ"
@@ -4327,6 +5038,9 @@ msgstr "ІÑторіÑ"
msgid "Housekeeping successfully started"
msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ ÑƒÑпішно розпочато"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr "Я приймаю %{terms_link}"
@@ -4384,6 +5098,9 @@ msgstr "ІдентифікаціÑ"
msgid "Identity provider single sign on URL"
msgstr "URL єдиного входу провайдера ідентифікації"
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr "Якщо вимкнено, локальна гілка зі змінами не буде автоматично підтÑгувати коміти з віддаленої гілки, щоб уникнути втрати локальних даних. Якщо гілка за замовчуваннÑм (%{default_branch}) міÑтить зміни Ñ– не може бути оновлена, тоді Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ неможливим. Інші гілки зі змінами автоматично ігноруютьÑÑ."
@@ -4414,9 +5131,15 @@ msgstr "Ðакладені (прозоріÑÑ‚ÑŒ)"
msgid "ImageDiffViewer|Swipe"
msgstr "Ðакладені (проведеннÑ)"
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr "Імпорт"
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr "Імпортувати проекти з Gitea"
@@ -4435,12 +5158,24 @@ msgstr "Імпортувати екÑпортований проект GitLab"
msgid "Import in progress"
msgstr "Імпорт триває"
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr "Імпортувати кілька репозиторіїв, надіÑлавши файл маніфеÑту."
msgid "Import project"
msgstr "Імпорт проекту"
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr "Імпортувати проекти з Bitbucket"
@@ -4465,6 +5200,9 @@ msgstr "Імпорт репозиторіїв з GitHub"
msgid "Import repository"
msgstr "Імпорт репозиторію"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr "Підключити репозиторії із"
@@ -4472,12 +5210,15 @@ msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr "Покращити дошки обговорень за допомогою верÑÑ–Ñ— GitLab Enterprise Edition."
msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
-msgstr "Покращити ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð°Ð¼Ð¸ з можливіÑÑ‚ÑŽ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð°Ð³Ð¸ проблеми за допомогою GitLab Enterprise Edition."
+msgstr "Покращити ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ð°Ð¼Ð¸ з можливіÑÑ‚ÑŽ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð°Ð³Ð¸ задач за допомогою GitLab Enterprise Edition."
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr "Покращити пошук за допомогою розширеного глобального пошук в верÑÑ–Ñ— GitLab Enterprise Edition."
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr "Щоб увімкнути ÑтатиÑтику на рівні інÑтанÑа, звернітьÑÑ Ð´Ð¾ адмініÑтратора, щоб увімкнути %{usage_ping_link_start}дані про викориÑтаннÑ%{usage_ping_link_end}."
+
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
@@ -4486,7 +5227,19 @@ msgstr "Ðа наÑтупному кроці ви зможете вибрати
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "Включити угоду про Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг та правила конфіденційноÑÑ‚Ñ–, Ñкі повинні прийнÑти вÑÑ– кориÑтувачі."
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr "Якщо необхідно додайте ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача в URL: <code>https: //username@gitlab.company.com/group/project.git</code>."
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
msgstr ""
msgid "Incompatible Project"
@@ -4504,6 +5257,9 @@ msgstr "Введіть ключі хоÑта вручну"
msgid "Input your repository URL"
msgstr "Введіть ваш URL репозиторію"
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "Ð’Ñтановити GitLab Runner"
@@ -4521,7 +5277,7 @@ msgid "Instance Statistics"
msgstr "СтатиÑтика інÑтанÑа"
msgid "Instance Statistics visibility"
-msgstr ""
+msgstr "СтатиÑтика видимоÑÑ‚Ñ– інÑтанÑа"
msgid "Instance does not support multiple Kubernetes clusters"
msgstr "Цей інÑÑ‚Ð°Ð½Ñ Ð½Ðµ підтримує декілька Kubernetes-клаÑтерів"
@@ -4535,6 +5291,9 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ—"
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "Зацікавлені Ñторони за бажаннÑм можуть навіть робити внеÑки шлÑхом Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð²."
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr "Ð’Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ â€” будь-Ñкий автентифікований кориÑтувач має доÑтуп до цієї групи та уÑÑ–Ñ… Ñ—Ñ— внутрішніх проектів."
@@ -4550,20 +5309,38 @@ msgstr "Шаблон інтервалу"
msgid "Introducing Cycle Analytics"
msgstr "ПредÑтавлÑємо аналітику циклу"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr "ЗапрошеннÑ"
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
-msgstr "Проблема"
+msgstr "Задача"
msgid "Issue Boards"
-msgstr "Дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼"
+msgstr "Дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡"
msgid "Issue board focus mode"
-msgstr "Режим фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð´Ð¾ÑˆÐºÐ¸ обговорень"
+msgstr "Режим фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð´Ð¾ÑˆÐºÐ¸ задач"
msgid "Issue events"
-msgstr "Проблеми"
+msgstr "Задачі"
msgid "IssueBoards|Board"
msgstr "Дошка"
@@ -4571,44 +5348,65 @@ msgstr "Дошка"
msgid "IssueBoards|Boards"
msgstr "Дошки"
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
-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, 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|Issues Created"
-msgstr ""
+msgstr "Створені Задачі"
msgid "IssuesAnalytics|Issues created per month"
-msgstr ""
+msgstr "Створені задачі за міÑÑць"
msgid "IssuesAnalytics|Last 12 months"
msgstr "ОÑтанні 12 міÑÑців"
msgid "IssuesAnalytics|Sorry, your filter produced no results"
-msgstr ""
+msgstr "Ðа жаль, немає результатів, Ñкі відповідають фільтру"
msgid "IssuesAnalytics|There are no issues for the projects in your group"
-msgstr ""
+msgstr "Ðемає задач Ð´Ð»Ñ Ð²ÑÑ–Ñ… проектів у групі"
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr "Щоб розширити пошук, будь лаÑка, змініть або видаліть фільтр вище"
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
-msgid "Jaeger URL"
+msgid "It's you"
msgstr ""
+msgid "Jaeger URL"
+msgstr "URL-адреÑа Jaeger"
+
msgid "Jaeger tracing"
-msgstr ""
+msgstr "ВідÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Jaeger"
msgid "Jan"
msgstr "Ñіч."
@@ -4622,6 +5420,12 @@ msgstr "ЗавданнÑ"
msgid "Job has been erased"
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ Ñтерте"
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr "ЗавданнÑ"
@@ -4661,11 +5465,11 @@ msgstr "Показати повний неформатований"
msgid "Job|The artifacts were removed"
msgstr "Ðртефакти були видалені"
-msgid "Job|The artifacts will be removed in"
-msgstr "Ðртефакти будуть видалені в"
+msgid "Job|The artifacts will be removed"
+msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
-msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ, тому що цей проект не має жодник runner'ів призначених Ð´Ð»Ñ Ð½ÑŒÐ¾Ð³Ð¾."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
msgid "Jul"
msgstr "лип."
@@ -4679,12 +5483,18 @@ msgstr "чер."
msgid "June"
msgstr "червень"
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
msgid "Kubernetes Cluster"
msgstr "КлаÑтер Kubernetes"
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "ÐŸÐµÑ€ÐµÐ²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð»Ñ–Ð¼Ñ–Ñ‚Ñƒ чаÑу при Ñтворенні Kubernetes-клаÑтера; %{timeout}"
@@ -4719,7 +5529,7 @@ msgid "Label actions dropdown"
msgstr "Випадаючий ÑпиÑок дій із мітками"
msgid "Label lists show all issues with the selected label."
-msgstr "Ð’ ÑпиÑках на оÑнові міток відображаютьÑÑ Ð»Ð¸ÑˆÐµ Ñ‚Ñ– проблеми, Ñкі мають вибрану мітку."
+msgstr "Ð’ ÑпиÑках на оÑнові міток відображаютьÑÑ Ð»Ð¸ÑˆÐµ Ñ‚Ñ– задачі, Ñкі мають вибрану мітку."
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
msgstr "%{firstLabelName} + %{remainingLabelCount} ще"
@@ -4737,10 +5547,10 @@ msgid "Labels can be applied to %{features}. Group labels are available for any
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|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
msgstr "<span>ПеренеÑти мітку</span> %{labelTitle} <span>на рівень групи?</span>"
@@ -4749,10 +5559,10 @@ msgid "Labels|Promote Label"
msgstr "ПеренеÑти мітку"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
-msgstr ""
+msgstr "ПеренеÑÐµÐ½Ð½Ñ %{labelTitle} на рівень групи зробить Ñ—Ñ— доÑтупною Ð´Ð»Ñ Ð²ÑÑ–Ñ… проектів в групі %{groupName}. ІÑнуючі проектні мітки із такими ж іменами будуть об'єднані. Дана Ð´Ñ–Ñ Ð½Ðµ може бути ÑкаÑована."
msgid "Large File Storage"
-msgstr ""
+msgstr "Сховище великих файлів (LFS)"
msgid "Last %d day"
msgid_plural "Last %d days"
@@ -4764,6 +5574,9 @@ msgstr[3] "ОÑтанніх %d днів"
msgid "Last Pipeline"
msgstr "ОÑтанній Конвеєр"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "ОÑтанній коміт"
@@ -4777,6 +5590,9 @@ msgid "Last edited by %{name}"
msgstr "ОÑтанні зміни від %{name}"
msgid "Last reply by"
+msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´ÑŒ від"
+
+msgid "Last seen"
msgstr ""
msgid "Last update"
@@ -4794,15 +5610,39 @@ msgstr "в"
msgid "Latest changes"
msgstr "ОÑтанні зміни"
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про %{issue_boards_url}, щоб Ñтежити за проблемами в кількох ÑпиÑках, викориÑтовуючи мітки, виконавців та етапи. Якщо вам чогоÑÑŒ не виÑтачає в дошках обговорень проблем, Ñтворіть проблему на %{gitlab_issues_url}."
+msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про %{issue_boards_url}, щоб Ñтежити за задачами в кількох ÑпиÑках, викориÑтовуючи мітки, виконавців та етапи. Якщо вам чогоÑÑŒ не виÑтачає в дошках обговорень задач, Ñтворіть задачу на %{gitlab_issues_url}."
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
msgid "Learn more about Kubernetes"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Kubernetes"
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про захищені гілки"
@@ -4828,10 +5668,10 @@ msgid "License"
msgstr "ЛіцензіÑ"
msgid "LicenseManagement|Add a license"
-msgstr ""
+msgstr "Додати ліцензію"
msgid "LicenseManagement|Add licenses manually to approve or blacklist"
-msgstr ""
+msgstr "Вручну додайте ліцензії Ð´Ð»Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð°Ð±Ð¾ внеÑÑ–Ñ‚ÑŒ в чорний ÑпиÑок"
msgid "LicenseManagement|Approve"
msgstr "Затвердити"
@@ -4870,7 +5710,7 @@ msgid "LicenseManagement|License details"
msgstr "Деталі ліцензії"
msgid "LicenseManagement|License name"
-msgstr ""
+msgstr "Ðазва ліцензії"
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr "Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð¸Ð¼Ð¸ ліцензіÑми та чорним ÑпиÑком ліцензій Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
@@ -4891,7 +5731,7 @@ msgid "LicenseManagement|There are currently no approved or blacklisted licenses
msgstr "Ðаразі немає затверджених ліцензій чи ліцензій в чорному ÑпиÑку Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
msgid "LicenseManagement|This license already exists in this project."
-msgstr ""
+msgstr "Ð¦Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ Ð²Ð¶Ðµ Ñ” в цьому проекті."
msgid "LicenseManagement|URL"
msgstr "URL"
@@ -4904,10 +5744,10 @@ msgstr "Ліцензії"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Показ обмежено тільки %d подією"
+msgstr[1] "Показ обмежено тільки %d подіÑми"
+msgstr[2] "Показ обмежено тільки %d подіÑми"
+msgstr[3] "Показ обмежено тільки %d подіÑми"
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -4942,8 +5782,14 @@ msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ IDE GitLab..."
msgid "Loading..."
msgstr "ЗавантаженнÑ..."
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
-msgstr "БлокуваннÑ"
+msgstr "Блокувати"
msgid "Lock %{issuableDisplayName}"
msgstr "Заблокувати %{issuableDisplayName}"
@@ -4970,7 +5816,7 @@ msgid "Locks give the ability to lock specific file or folder."
msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð¶Ðµ бути заÑтоÑоване до конкретного файлу або директорії."
msgid "Login with smartcard"
-msgstr ""
+msgstr "Вхід за допомогою Ñмарт-картки"
msgid "Logs"
msgstr "Логи"
@@ -4982,7 +5828,7 @@ msgid "Make sure you're logged into the account that owns the projects you'd lik
msgstr "ПереконайтеÑÑ, що ви ввійшли за допомогою облікового запиÑу, Ñкому належать проекти, що потрібно імпортувати."
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
-msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñми Git за допомогою детального контролю доÑтупу збереже ваш код в безпеці. Виконуйте переглÑд коду та покращуйте Ñпівпрацю за допомогою запитів на злиттÑ. Кожен проект може також мати трекер проблем та вікі."
+msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñми Git за допомогою детального контролю доÑтупу збереже ваш код в безпеці. Виконуйте переглÑд коду та покращуйте Ñпівпрацю за допомогою запитів на злиттÑ. Кожен проект може також мати трекер задач та вікі."
msgid "Manage Web IDE features"
msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñми веб-IDE"
@@ -5008,6 +5854,9 @@ msgstr "Керувати мітками"
msgid "Manage project labels"
msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ñ–Ñ‚ÐºÐ°Ð¼Ð¸ проекту"
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr "Керуйте членÑтвом у вашій групі додаючи ще один рівень безпеки із SAML."
@@ -5038,45 +5887,45 @@ msgstr "березень"
msgid "Mark todo as done"
msgstr "Відмітити Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¸Ð¼"
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr "Markdown увімкнено"
msgid "MarkdownToolbar|Add a bullet list"
-msgstr ""
+msgstr "Додати ненумерований ÑпиÑок"
msgid "MarkdownToolbar|Add a link"
msgstr "Додати поÑиланнÑ"
msgid "MarkdownToolbar|Add a numbered list"
-msgstr ""
+msgstr "Додати нумерований ÑпиÑок"
msgid "MarkdownToolbar|Add a table"
msgstr "Додати таблицю"
msgid "MarkdownToolbar|Add a task list"
-msgstr ""
+msgstr "Додати ÑпиÑок завдань"
msgid "MarkdownToolbar|Add bold text"
-msgstr ""
+msgstr "Додати жирний текÑÑ‚"
msgid "MarkdownToolbar|Add italic text"
-msgstr ""
+msgstr "Додати курÑивний текÑÑ‚"
msgid "MarkdownToolbar|Go full screen"
-msgstr ""
+msgstr "Повний екран"
msgid "MarkdownToolbar|Insert a quote"
-msgstr ""
+msgstr "Ð’Ñтавити цитату"
msgid "MarkdownToolbar|Insert code"
-msgstr ""
+msgstr "Ð’Ñтавити код"
msgid "Maven Metadata"
msgstr "Maven-метадані"
-msgid "Maven package"
-msgstr "Пакет Maven"
-
msgid "Max access level"
msgstr "МакÑимальний рівень доÑтупу"
@@ -5090,32 +5939,44 @@ msgid "Median"
msgstr "Медіана"
msgid "Member lock"
-msgstr ""
+msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÑ‡Ð°Ñників"
msgid "Member since %{date}"
-msgstr ""
+msgstr "УчаÑник з %{date}"
msgid "Members"
msgstr "КориÑтувачі"
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "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 "УчаÑники будуть перенаправлені Ñюди, коли будуть заходити до вашої групи. Отримайте його від Ñвого провайдера ідентифікації, де вона також може називатиÑÑ \"SSO Service Location\", \"SAML Token Issuance Endpoint\", або \"SAML 2.0/W-Federation URL\"."
msgid "Merge Request"
msgstr "Запит на злиттÑ"
-msgid "Merge Request:"
-msgstr "Запит на злиттÑ:"
-
msgid "Merge Requests"
msgstr "Запити на злиттÑ"
msgid "Merge Requests created"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ»Ð¾ Ñтворено"
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr "Події злиттÑ"
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr "Запит на злиттÑ"
@@ -5128,23 +5989,35 @@ msgstr "Запити на злиттÑ"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ â€” це ÑпоÑіб запропонувати Ñвої зміни до проекту Ñ– обговорити Ñ—Ñ… із іншими"
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð½ÐµÑ‚ÐºÐ¸ коментарÑ."
+
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
-msgstr "Вирішити це Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð² новій проблемі"
+msgstr "Вирішити це Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð² новій задачі"
msgid "MergeRequests|Saving the comment failed"
msgstr "Помилка при збереженні коментарÑ"
@@ -5158,13 +6031,34 @@ msgstr "ПереглÑнути файл @ %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "ПереглÑнути замінений файл Ñтаном на %{commitId}"
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
-msgstr "%{paragraphStart} Ð¾Ð¿Ð¸Ñ Ð·Ð¼Ñ–Ð½ÐµÐ½Ð¾ %{descriptionChangedTimes} разів %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr "%{paragraphStart} Ð¾Ð¿Ð¸Ñ Ð·Ð¼Ñ–Ð½ÐµÐ½Ð¾ %{descriptionChangedTimes} раз(а,ів) %{timeDifferenceMinutes}%{paragraphEnd}"
msgid "MergeRequest|Filter files"
-msgstr ""
+msgstr "Фільтр файлів"
msgid "MergeRequest|No files found"
+msgstr "Файлів не знайдено"
+
+msgid "MergeRequest|Search files"
msgstr ""
msgid "Merged"
@@ -5185,8 +6079,8 @@ msgstr "Метрики - Prometheus"
msgid "Metrics and profiling"
msgstr "Метрики та профілюваннÑ"
-msgid "Metrics|Business"
-msgstr "БізнеÑ"
+msgid "Metrics for environment"
+msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Перевірте документацію CI/CD щодо Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð² Ñередовищі"
@@ -5194,6 +6088,12 @@ msgstr "Перевірте документацію CI/CD щодо розгорÑ
msgid "Metrics|Create metric"
msgstr "Створити метрику"
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr "Редагувати метрику"
@@ -5203,8 +6103,8 @@ msgstr "Середовище"
msgid "Metrics|For grouping similar metrics"
msgstr "Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ð±Ð½Ð¸Ñ… метрик"
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
-msgstr "Ðазва вертикальної оÑÑ– графіка. Зазвичай це — одиниці вимірюваннÑ. Горизонтальна віÑÑŒ (віÑÑŒ X) завжди відображає чаÑ."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
msgid "Metrics|Learn about environments"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ñередовища"
@@ -5215,24 +6115,18 @@ msgstr "Заголовок легенди (необов’Ñзковий)"
msgid "Metrics|Must be a valid PromQL query."
msgstr "Має бути коректним запитом PromQL."
-msgid "Metrics|Name"
-msgstr "Ім'Ñ"
-
msgid "Metrics|New metric"
msgstr "Ðова метрика"
msgid "Metrics|No deployed environments"
msgstr "Ðемає розгорнутих Ñередовищ"
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
msgid "Metrics|Prometheus Query Documentation"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð¿Ð¾ запитам Prometheus"
-msgid "Metrics|Query"
-msgstr "Запит"
-
-msgid "Metrics|Response"
-msgstr "Відповідь"
-
msgid "Metrics|System"
msgstr "СиÑтема"
@@ -5245,12 +6139,12 @@ msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ–Ð½Ñ
msgid "Metrics|There was an error getting environments information."
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ— про Ñередовища."
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
msgid "Metrics|There was an error while retrieving metrics"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¼ÐµÑ‚Ñ€Ð¸Ðº"
-msgid "Metrics|Type"
-msgstr "Тип"
-
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr "Ðеочікувана відповідь про Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð´ ендпойнта Prometheus"
@@ -5269,21 +6163,12 @@ msgstr "ВикориÑтовуєтьÑÑ, Ñкщо запит повертає Ñ
msgid "Metrics|Y-axis label"
msgstr "Ðазва оÑÑ– Y"
-msgid "Metrics|e.g. HTTP requests"
-msgstr "напр. HTTP-запити"
-
-msgid "Metrics|e.g. Requests/second"
-msgstr "напр. запитів/Ñек"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr "напр. пропуÑкна здатніÑÑ‚ÑŒ"
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr "напр. rate(http_requests_total[5m])"
-
-msgid "Metrics|e.g. req/sec"
-msgstr "напр. зап/Ñек"
-
msgid "Milestone"
msgstr "Етап"
@@ -5291,7 +6176,7 @@ msgid "Milestone lists not available with your current license"
msgstr "СпиÑки етапів не доÑтупні з вашою поточною ліцензією"
msgid "Milestone lists show all issues from the selected milestone."
-msgstr ""
+msgstr "У ÑпиÑках етапу відображаютьÑÑ Ð²ÑÑ– задачі Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ етапу."
msgid "Milestones"
msgstr "Етапи"
@@ -5300,7 +6185,7 @@ msgid "Milestones| You’re about to permanently delete the milestone %{mileston
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 "Ви збираєтеÑÑ Ð¾Ñтаточно видалити етап %{milestoneTitle}. Ðаразі цей етап не викориÑтовуєтьÑÑ Ð² жодних проблемах або запитах на злиттÑ."
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити етап %{milestoneTitle}. Ðаразі цей етап не викориÑтовуєтьÑÑ Ð² жодних задачах або запитах на злиттÑ."
msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
@@ -5324,7 +6209,7 @@ msgid "Milestones|Promote Milestone"
msgstr "ПеренеÑти етап"
msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr ""
+msgstr "ПеренеÑÐµÐ½Ð½Ñ %{milestone} на рівень групи зробить його доÑтупним Ð´Ð»Ñ Ð²ÑÑ–Ñ… проектів в групі %{groupName}. ІÑнуючі проектні етапи з такими ж іменами будуть об'єднані. "
msgid "Milestones|This action cannot be reversed."
msgstr "Цю дію не можна ÑкаÑувати."
@@ -5356,6 +6241,18 @@ msgstr "СкаÑувати"
msgid "Modal|Close"
msgstr "Закрити"
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "Моніторинг"
@@ -5378,13 +6275,13 @@ msgid "More information is available|here"
msgstr "тут"
msgid "Most stars"
-msgstr ""
+msgstr "Ðайбільше в обраних"
msgid "Move"
msgstr "ПереміÑтити"
msgid "Move issue"
-msgstr "ПереміÑтити проблему"
+msgstr "ПереміÑтити задачу"
msgid "Multiple issue boards"
msgstr "Кілька дошок обговореннÑ"
@@ -5402,7 +6299,7 @@ msgid "Name:"
msgstr "Ім’Ñ:"
msgid "Naming, visibility"
-msgstr ""
+msgstr "ÐайменуваннÑ, видиміÑÑ‚ÑŒ"
msgid "Nav|Help"
msgstr "Допомога"
@@ -5414,7 +6311,10 @@ msgid "Nav|Sign In / Register"
msgstr "Увійти / зареєÑтруватиÑÑ"
msgid "Nav|Sign out and sign in with a different account"
-msgstr "Вийти із зайти під інший обліковим запиÑом"
+msgstr "Вийти Ñ– зайти під іншим обліковим запиÑом"
+
+msgid "Need help?"
+msgstr ""
msgid "Network"
msgstr "Мережа"
@@ -5428,6 +6328,9 @@ msgstr "Ðовий"
msgid "New Application"
msgstr "Ðовий додаток"
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr "Ðова група"
@@ -5436,14 +6339,20 @@ msgstr "Ðова ідентифікаціÑ"
msgid "New Issue"
msgid_plural "New Issues"
-msgstr[0] "Ðова проблема"
-msgstr[1] "Ðові проблеми"
-msgstr[2] "Ðових проблем"
-msgstr[3] "Ðових проблем"
+msgstr[0] "Ðова задача"
+msgstr[1] "Ðові задачі"
+msgstr[2] "Ðових задач"
+msgstr[3] "Ðових задач"
msgid "New Label"
msgstr "Ðова мітка"
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "Ðовий розклад Конвеєра"
@@ -5462,6 +6371,9 @@ msgstr "Ðова гілка недоÑтупна"
msgid "New directory"
msgstr "Ðовий каталог"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr "Ðовий епік"
@@ -5475,7 +6387,7 @@ msgid "New identity"
msgstr "Ðова ідентифікаціÑ"
msgid "New issue"
-msgstr "Ðова проблема"
+msgstr "Ðова задача"
msgid "New label"
msgstr "Ðова мітка"
@@ -5483,6 +6395,9 @@ msgstr "Ðова мітка"
msgid "New merge request"
msgstr "Ðовий запит на злиттÑ"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "Ðові конвеєри ÑкаÑують Ñтарі, що очікують на тій же гілці"
@@ -5510,6 +6425,9 @@ msgstr "ÐÑ–"
msgid "No Label"
msgstr "Без Мітки"
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr "Ðемає виконавцÑ"
@@ -5519,6 +6437,9 @@ msgstr "Гілок не знайдено"
msgid "No changes"
msgstr "Ðемає змін"
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Ðеможливо з'єднатиÑÑŒ із Ñервером Gitaly, будь лаÑка, перевірте логи!"
@@ -5529,22 +6450,31 @@ msgid "No contributions were found"
msgstr "ВнеÑки не знайдено"
msgid "No credit card required."
+msgstr "Ðе потрібна кредитна картка."
+
+msgid "No details available"
msgstr ""
msgid "No due date"
msgstr "Ðемає"
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr "Ðемає запланованого або витраченого чаÑу"
msgid "No file chosen"
msgstr "Файл не вибрано"
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr "Ðе знайдено жодного файлу."
msgid "No issues for the selected time period."
-msgstr "Ðемає проблем за вибраний період чаÑу."
+msgstr "Ðемає задач за вибраний період чаÑу."
msgid "No labels with such name or description"
msgstr "Ðемає міток з таким іменем або опиÑом"
@@ -5552,6 +6482,9 @@ msgstr "Ðемає міток з таким іменем або опиÑом"
msgid "No license. All rights reserved"
msgstr "Ðемає ліцензії. Ð’ÑÑ– права захищені"
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr "Ðемає запитів на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð° вибраний період чаÑу."
@@ -5561,11 +6494,14 @@ msgstr "Ðе знайдено жодного запиту на злиттÑ"
msgid "No messages were logged"
msgstr "Ðемає повідомлень у журналі"
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "Ðемає інших міток з таким іменем або опиÑом"
-msgid "No packages stored for this project."
-msgstr "В цьому проекті немає пакетів."
+msgid "No preview for this file type"
+msgstr ""
msgid "No prioritised labels with such name or description"
msgstr "Ðемає пріоритетних міток з таким іменем або опиÑом"
@@ -5585,6 +6521,9 @@ msgstr "Runner'ів не знайдено"
msgid "No schedules"
msgstr "Ðемає розкладів"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr "ÐÑ–, безпоÑередньо імпортувати Ñ–Ñнуючі адреÑи електронної пошти та імена кориÑтувачів."
@@ -5594,12 +6533,6 @@ msgstr "Вузли"
msgid "None"
msgstr "Ðемає"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ðµ допуÑкаєтьÑÑ"
@@ -5624,6 +6557,9 @@ msgstr "Пізніше"
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "Майте на увазі, що гілка master захищена автоматично. %{link_to_protected_branches}"
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "Примітка: Ñк адмініÑтратор ви можете налаштувати %{github_integration_link}, що дозволить входити через GitHub Ñ– підключати репозиторії без ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾ÑобиÑтого токену доÑтупу."
@@ -5640,22 +6576,28 @@ msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Ви впевнені, що хочете ÑкаÑувати цей коментар?"
msgid "Notes|Collapse replies"
-msgstr ""
+msgstr "Згорнути відповіді"
msgid "Notes|Show all activity"
-msgstr ""
+msgstr "Показати вÑÑŽ активніÑÑ‚ÑŒ"
msgid "Notes|Show comments only"
-msgstr ""
+msgstr "Показати тільки коментарі"
msgid "Notes|Show history only"
-msgstr ""
+msgstr "Показати лише Ñ–Ñторію"
msgid "Notification events"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ події"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
-msgstr "Проблема закрита"
+msgstr "Задача закрита"
msgid "NotificationEvent|Close merge request"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°ÐºÑ€Ð¸Ñ‚Ð¸Ð¹"
@@ -5670,7 +6612,7 @@ msgid "NotificationEvent|New epic"
msgstr "Ðовий епік"
msgid "NotificationEvent|New issue"
-msgstr "Ðова проблема"
+msgstr "Ðова задача"
msgid "NotificationEvent|New merge request"
msgstr "Ðовий запит на злиттÑ"
@@ -5679,13 +6621,13 @@ msgid "NotificationEvent|New note"
msgstr "Ðова нотатка"
msgid "NotificationEvent|Reassign issue"
-msgstr "Перепризначити проблему"
+msgstr "Перепризначити задачу"
msgid "NotificationEvent|Reassign merge request"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿ÐµÑ€ÐµÐ¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¾"
msgid "NotificationEvent|Reopen issue"
-msgstr "Повторне Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ñƒ"
+msgstr "Повторне Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ–"
msgid "NotificationEvent|Successful pipeline"
msgstr "УÑпішно в Конвеєрі"
@@ -5754,21 +6696,36 @@ msgstr "Один або декілька ваших проектів Google Code
msgid "Only admins"
msgstr "Тільки Ðдміни"
-msgid "Only comments from the following commit are shown below"
-msgstr "Ðижче наведено лише коментарі з наÑтупного коміту"
-
msgid "Only mirror protected branches"
msgstr "Віддзеркалювати лише захищені гілки"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
msgid "Only project members can comment."
msgstr "Тільки учаÑники проекту можуть залишати коментарі."
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "Ой, а ви впевнені?"
msgid "Open"
msgstr "Відкриті"
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr "Відкрити в Xcode"
@@ -5788,7 +6745,7 @@ msgid "Opened MR"
msgstr "Відкритий запит на злиттÑ"
msgid "Opened issues"
-msgstr "Відкриті проблеми"
+msgstr "Відкриті задачі"
msgid "OpenedNDaysAgo|Opened"
msgstr "Відкрито"
@@ -5800,19 +6757,16 @@ msgid "Operations"
msgstr "Операції"
msgid "Operations Dashboard"
-msgstr ""
-
-msgid "Operations Settings"
-msgstr ""
+msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми"
msgid "OperationsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "Додайте проект до панелі керуваннÑ"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
-msgstr ""
+msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми міÑтить інформацію про Ñтан кожного з проектів разом зі Ñтаном його конвеєрів та попереджень."
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
-msgstr "Ðеможливо додати %{invalidProjects}. Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми доÑтупна Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñ–Ð² з Gold підпиÑкою."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "За необхідноÑÑ‚Ñ– ви можете %{link_to_customize} Ñк адреÑи електронної почти та імена кориÑтувачів FobBugz будуть імпортовані у GitLab."
@@ -5842,7 +6796,7 @@ msgid "Overview"
msgstr "ОглÑд"
msgid "Overwrite diverged branches"
-msgstr ""
+msgstr "ПерезапиÑати розбіжні гілки"
msgid "Owner"
msgstr "ВлаÑник"
@@ -5859,6 +6813,12 @@ msgstr "Пакети"
msgid "Pages"
msgstr "Сторінки"
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Â»"
@@ -5871,17 +6831,32 @@ msgstr "ПопереднÑ"
msgid "Pagination|« First"
msgstr "« Перша"
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr "ЧаÑтина змін у запиті на злиттÑ"
msgid "Password"
msgstr "Пароль"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "Ð’Ñтавте Ñвій відкритий ключ SSH, Ñкий зазвичай знаходитьÑÑ Ñƒ файлі '~/.ssh/id_rsa.pub' Ñ– починаєтьÑÑ Ð· 'ssh-rsa'. Ðе викориÑтовуйте Ñвій приватний ключ SSH."
msgid "Path, transfer, remove"
-msgstr ""
+msgstr "ШлÑÑ…, передача, видаленнÑ"
msgid "Path:"
msgstr "ШлÑÑ…:"
@@ -5890,7 +6865,7 @@ msgid "Pause"
msgstr "Призупинити"
msgid "Paused Runners don't accept new jobs"
-msgstr ""
+msgstr "Призупинені Runner'и не приймають нові завданнÑ"
msgid "Pending"
msgstr "В очікуванні"
@@ -5898,9 +6873,6 @@ msgstr "В очікуванні"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Люди без дозволу ніколи не отримуватимуть Ñповіщень Ñ– не зможуть коментувати."
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr "За завданнÑ. Якщо воно переходить цей поріг, то Ñтає позначеним Ñк невдале"
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "Виконуйте такі розширені операції, Ñк зміна шлÑху, перенеÑÐµÐ½Ð½Ñ Ñ‡Ð¸ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸."
@@ -5911,11 +6883,17 @@ msgid "Permissions"
msgstr "Права доÑтупу"
msgid "Permissions, LFS, 2FA"
-msgstr ""
+msgstr "Дозволи, LFS, 2FA"
msgid "Personal Access Token"
msgstr "Токену перÑонального доÑтупу"
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "Конвеєр"
@@ -6007,7 +6985,7 @@ msgid "Pipelines|Clear Runner Caches"
msgstr "ОчиÑтити кеш Runner'ів"
msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
-msgstr ""
+msgstr "Безперервно Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð°Ð³Ð°Ñ” знаходити помилки шлÑхом автоматичного запуÑку теÑтів, а безперервне Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ â€” вÑтановлювати код на цільове Ñеридовище."
msgid "Pipelines|Get started with Pipelines"
msgstr "Розпочати роботу з Конвеєрами"
@@ -6031,7 +7009,7 @@ msgid "Pipelines|There are currently no pipelines."
msgstr "Ð’ даний Ñ‡Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” конвеєрів."
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
-msgstr ""
+msgstr "Помилка при отриманні конвеєрів. Спробуйте знову через декілька хвилин, або звернітьÑÑ Ð´Ð¾ Ñлужби підтримки."
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Цей проект в даний Ñ‡Ð°Ñ Ð½Ðµ налаштований Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку конвеєрів."
@@ -6102,11 +7080,14 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Відтворити"
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr "Будь лаÑка, Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð¹Ð¼Ñ–Ñ‚ÑŒ умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг."
msgid "Please choose a group URL with no special characters."
-msgstr ""
+msgstr "Будь лаÑка задайте URL групи без Ñпеціальних Ñимволів."
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr "Будь лаÑка Ñконвертуйте Ñ—Ñ… в %{link_to_git} Ñ– виконайте знову %{link_to_import_flow}."
@@ -6114,7 +7095,13 @@ msgstr "Будь лаÑка Ñконвертуйте Ñ—Ñ… в %{link_to_git} Ñ– Ð
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "Будь лаÑка Ñконвертуйте Ñ—Ñ… в Git на Google Code, Ñ– виконайте знову %{link_to_import_flow}."
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
+msgstr "Введіть опиÑове ім'Ñ Ð³Ñ€ÑƒÐ¿Ð¸."
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
@@ -6129,8 +7116,11 @@ msgstr "Будь лаÑка, пройдіть reCAPTCHA"
msgid "Please try again"
msgstr "Будь лаÑка, Ñпробуйте ще раз"
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
-msgstr "Будь лаÑка, викориÑтовуйте цю форму, щоб повідомлÑти GitLab про кориÑтувачів, Ñкі Ñтворюють Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ– коментарі зі Ñпамом, або поводÑÑ‚ÑŒÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾."
+msgstr "Будь лаÑка, викориÑтовуйте цю форму, щоб повідомлÑти GitLab про кориÑтувачів, Ñкі Ñтворюють задачі Ñ– коментарі зі Ñпамом, або поводÑÑ‚ÑŒÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾."
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "Будь лаÑка, почекайте поки ми з’єднуємоÑÑ Ñ–Ð· вашим репозиторієм. Оновлюйте Ñторінку за бажаннÑм."
@@ -6148,7 +7138,7 @@ msgid "Press Enter or click to search"
msgstr "Ð”Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ натиÑніть Enter або клікніть"
msgid "Prevent adding new members to project membership within this group"
-msgstr ""
+msgstr "Заборонити Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… учаÑників до членÑтва в цій групі"
msgid "Preview"
msgstr "Попередній переглÑд"
@@ -6171,6 +7161,9 @@ msgstr "Пріоритетні мітки"
msgid "Prioritized label"
msgstr "Пріоритетні мітки"
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr "Приватний — доÑтуп до проекту повинен надаватиÑÑ ÐºÐ¾Ð¶Ð½Ð¾Ð¼Ñƒ кориÑтувачеві."
@@ -6187,14 +7180,23 @@ msgid "Profile Settings"
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 "Ви збираєтеÑÑ Ð¾Ñтаточно видалити %{yourAccount}, а також вÑÑ– проблеми, запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° групи, пов'Ñзані з вашим обліковим запиÑом. ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ %{deleteAccount}, його неможливо буде відновити."
+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 "Ви збираєтеÑÑ Ð·Ð¼Ñ–Ð½Ð¸Ñ‚Ð¸ ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача %{currentUsernameBold} на %{newUsernameBold}. Профіль та проекти будуть перенаправлÑтиÑÑ Ð½Ð° проÑÑ‚Ñ–Ñ€ імен %{newUsername}, але таке Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ñ‚ÑŒÑÑ, коли проÑÑ‚Ñ–Ñ€ імен %{currentUsername} буде зареєÑтровано на іншого кориÑтувача або групу. Будь лаÑка, оновіть віддалені адреÑи в репозиторіÑÑ… Git Ñкомога швидше."
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¾Ð²Ð°Ð½Ð¸Ð¹ Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ."
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr "Додати ключ"
@@ -6210,15 +7212,30 @@ msgstr "Ðватар буде видалено. Ви впевнені?"
msgid "Profiles|Change username"
msgstr "Змінити ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr "Вибрати файл..."
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
-msgstr "Виберіть Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ внеÑків до приватних репозиторіїв у вашому публічному профілі без інформації про проекти, репозиторії або організації."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
msgid "Profiles|Clear status"
msgstr "ОчиÑтити ÑтатуÑ"
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Поточний шлÑÑ…: %{path}"
@@ -6237,6 +7254,9 @@ msgstr "Видалити ваш обліковий запиÑ?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу неÑе наÑтупні наÑлідки:"
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr "Ðе відображати у профілі"
@@ -6246,6 +7266,12 @@ msgstr "Ðе відображати оÑобиÑту інформацію, поÐ
msgid "Profiles|Edit Profile"
msgstr "Редагувати профіль"
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Ðеправильний пароль"
@@ -6282,11 +7308,14 @@ msgstr "Видалити аватар"
msgid "Profiles|Set new profile picture"
msgstr "Ð’Ñтановити нове Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr "ДеÑкі параметри недоÑтупні Ð´Ð»Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¸Ñ… запиÑів LDAP"
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
-msgstr "Розкажіть про Ñебе в межах 250 Ñимволів."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "МакÑимальний розмір файлу 200КБ."
@@ -6294,20 +7323,23 @@ msgstr "МакÑимальний розмір файлу 200КБ."
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Це не Ñхоже на публічниц ключ SSH. Ви впевнені, що хочете його додати?"
-msgid "Profiles|This email will be displayed on your public profile."
-msgstr "Ð¦Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð° адреÑа буде відображатиÑÑ Ñƒ вашому публічному профілі."
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
-msgstr ""
+msgstr "Ð¦Ñ Ð°Ð´Ñ€ÐµÑа електронної пошти буде викориÑтовуватиÑÑ Ð´Ð»Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð½Ð¸Ñ… операцій, таких Ñк Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° злиттÑ. %{learn_more}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr "Цей Ñмайлик та Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑƒÑ‚ÑŒ показані у вашому профілі та в інтерфейÑÑ–."
-msgid "Profiles|This feature is experimental and translations are not complete yet."
-msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ñ” екÑпериментальною Ñ– переклади ще не завершені."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
-msgid "Profiles|This information will appear on your profile."
-msgstr "Ð¦Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ відображатиÑÑ Ñƒ вашому профілі."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Введіть ваш %{confirmationValue} Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ:"
@@ -6325,7 +7357,7 @@ msgid "Profiles|Upload new avatar"
msgstr "Завантажити новий аватар"
msgid "Profiles|Use a private email - %{email}"
-msgstr ""
+msgstr "ВикориÑтовувати приватну адреÑу електронної пошти - %{email}"
msgid "Profiles|Username change failed - %{message}"
msgstr "Помилка при збереженні імені кориÑтувача - %{message}"
@@ -6333,12 +7365,15 @@ msgstr "Помилка при збереженні імені кориÑтува
msgid "Profiles|Username successfully changed"
msgstr "Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача уÑпішно збережено"
-msgid "Profiles|Website"
-msgstr "ВебÑайт"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
msgid "Profiles|What's your status?"
msgstr "Який ваш ÑтатуÑ?"
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr "Тут ви можете змінити Ñвій аватар"
@@ -6357,17 +7392,20 @@ msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтупу Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "Вам необхідно змінити влаÑника або видалити ці групи перед тим Ñк видалити ваш обліковий запиÑ."
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ” влаÑником в цих групах:"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
-msgstr "Ваша адреÑа електронної пошти була автоматично вÑтановлена на оÑнові вашого облікового запиÑу %{provider_label}."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
-msgstr "Ваше міÑÑ†ÐµÐ·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ автоматично вÑтановлено на оÑнові вашого облікового запиÑу %{provider_label}."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
-msgstr "Ваше Ñ–Ð¼â€™Ñ Ð±ÑƒÐ»Ð¾ автоматично вÑтановлено на оÑнові вашого облікового запиÑу %{provider_label} щоб люди могли Ð²Ð°Ñ Ð²Ð¿Ñ–Ð·Ð½Ð°Ñ‚Ð¸."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
msgid "Profiles|Your status"
msgstr "Ваш ÑтатуÑ"
@@ -6375,6 +7413,12 @@ msgstr "Ваш ÑтатуÑ"
msgid "Profiles|e.g. My MacBook key"
msgstr "наприклад, мій ключ MacBook"
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "ваш обліковий запиÑ"
@@ -6432,12 +7476,18 @@ msgstr "ЗакінчивÑÑ Ñ‚ÐµÑ€Ð¼Ñ–Ð½ дії поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° проÐ
msgid "Project export started. A download link will be sent by email."
msgstr "Розпочато екÑпорт проекту. ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑÐºÐ°Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ надіÑлана електронною поштою."
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr "Ðазва проекту"
msgid "Project slug"
msgstr "ШлÑÑ… проекту"
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "ПідпиÑатиÑÑ"
@@ -6529,7 +7579,7 @@ msgid "Projects shared with %{group_name}"
msgstr "Спільні проекти з %{group_name}"
msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
+msgstr "Проекти, що належать до групи, викориÑтовують Ñ—Ñ— ім'Ñ Ñк префікÑ. ІÑнуючі проекти можуть бути переміщені в групу."
msgid "ProjectsDropdown|Frequently visited"
msgstr "ЧаÑто відвідувані"
@@ -6582,9 +7632,6 @@ msgstr "Оператор"
msgid "PrometheusAlerts|Threshold"
msgstr "Поріг"
-msgid "PrometheusDashboard|Time"
-msgstr "ЧаÑ"
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "було знайдено %{exporters} з %{metrics}"
@@ -6609,6 +7656,9 @@ msgstr "Загальні метрики автоматично збираютьÑ
msgid "PrometheusService|Custom metrics"
msgstr "ВлаÑні метрики"
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "Пошук та Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼ÐµÑ‚Ñ€Ð¸Ðº..."
@@ -6673,7 +7723,7 @@ msgid "Promotions|Don't show me this again"
msgstr "Більше не показувати це"
msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
-msgstr "Епіки дозволÑÑŽÑ‚ÑŒ вам більш ефективно та з меншими зуÑиллÑми керувати портфелÑми проектів, відÑлідковуючи групи Ñпоріднених питань у етапах та проектах."
+msgstr "Епіки дозволÑÑŽÑ‚ÑŒ вам більш ефективно та з меншими зуÑиллÑми керувати портфелÑми проектів, відÑлідковуючи групи Ñпоріднених задач у етапах та проектах."
msgid "Promotions|This feature is locked."
msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð°."
@@ -6738,6 +7788,9 @@ msgstr "ПоÑтачальник"
msgid "Pseudonymizer data collection"
msgstr "Збір даних Pseudonymizer"
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "Публічна — група та вÑÑ– публічні проекти можуть переглÑдатиÑÑ Ð±ÐµÐ· автентифікації."
@@ -6777,26 +7830,35 @@ msgstr "Відправки (push)"
msgid "Quarters"
msgstr "Квартали"
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
-msgstr "Швидкі дії можна викориÑтовувати в опиÑах проблем Ñ– коментарÑÑ…."
+msgstr "Швидкі дії можна викориÑтовувати в опиÑах задач Ñ– коментарÑÑ…."
+
+msgid "README"
+msgstr ""
msgid "Read more"
msgstr "Докладніше"
+msgid "Read more about environments"
+msgstr ""
+
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про права доÑтупу в проекті <strong>%{link_to_help}</strong>"
-msgid "Readme"
-msgstr "ІнÑтрукціÑ"
-
msgid "Real-time features"
msgstr "Фунції реального чаÑу"
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr "ОÑтанні пошукові запити"
msgid "Redirect to SAML provider to test configuration"
-msgstr ""
+msgstr "Перенаправити до SAML провайдера Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ конфігурації"
msgid "Reference:"
msgstr "ПоÑиланнÑ:"
@@ -6820,6 +7882,9 @@ msgstr "Шаблон у виглÑді регулÑрного виразу"
msgid "Register / Sign In"
msgstr "ЗареєÑтруватиÑÑ / Увійти"
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "ЗареєÑтруйте Ñ– переглÑдайте ваші Runner’и Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи."
@@ -6836,7 +7901,7 @@ msgid "Related Deployed Jobs"
msgstr "Пов’Ñзані розгорнуті Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ (Jobs)"
msgid "Related Issues"
-msgstr "Пов’Ñзані Проблеми (Issues)"
+msgstr "Пов’Ñзані задачі"
msgid "Related Jobs"
msgstr "Пов’Ñзані Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ (Jobs)"
@@ -6850,6 +7915,12 @@ msgstr "Пов'Ñзані виконані запити"
msgid "Related merge requests"
msgstr "Пов'Ñзані запити на злиттÑ"
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "Ðагадати пізніше"
@@ -6859,6 +7930,12 @@ msgstr "Видалити"
msgid "Remove Runner"
msgstr "Видалити Runner"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Видалити аватар"
@@ -6872,10 +7949,10 @@ msgid "Remove project"
msgstr "Видалити проект"
msgid "Removed group can not be restored!"
-msgstr ""
+msgstr "Видалену групу неможливо відновити!"
msgid "Removing group will cause all child projects and resources to be removed."
-msgstr ""
+msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸ призведе до Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ… Ñ—Ñ— дочірніх проектів Ñ– реÑурÑів."
msgid "Rename"
msgstr "Перейменувати"
@@ -6889,9 +7966,15 @@ msgstr "Перейменувати папку"
msgid "Reopen epic"
msgstr "Повторне Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐµÐ¿Ñ–ÐºÑƒ"
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr "Відновити аутентифікацію"
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr "ВідповіÑти на це електронне Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿Ð¾Ñередньо або %{view_it_on_gitlab}."
@@ -6952,6 +8035,12 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ"
msgid "Repository URL"
msgstr "URL репозиторіÑ"
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr "Репозиторій не має блокувань."
@@ -6970,23 +8059,41 @@ msgstr "Вибрати"
msgid "Request Access"
msgstr "Запит доÑтупу"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr "ÐŸÑ€Ð¾Ñ„Ñ–Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð²"
msgid "Require all users in this group to setup Two-factor authentication"
-msgstr ""
+msgstr "Вимагати від вÑÑ–Ñ… кориÑтувачів цієї групи налаштувати двофакторну автентифікацію"
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Вимагати від уÑÑ–Ñ… кориÑтувачів приймати умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг та політику конфіденційноÑÑ‚Ñ–, коли вони отримують доÑтуп до GitLab."
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr "Оновити токен доÑтупу Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ працездатноÑÑ‚Ñ–"
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "Перегенерувати реєÑтраційний токен runner-ів"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
-msgstr "Вирішити вÑÑ– Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð² новій проблемі"
+msgstr "Вирішити вÑÑ– Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð² новій задачі"
msgid "Resolve conflicts on source branch"
msgstr "Вирішити конфлікти у гілці-джерелі"
@@ -6994,6 +8101,12 @@ msgstr "Вирішити конфлікти у гілці-джерелі"
msgid "Resolve discussion"
msgstr "Завершити обговореннÑ"
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr "Метрики відповідей (AWS ELB)"
@@ -7003,12 +8116,18 @@ msgstr "Метрики відповідей (ВлаÑні)"
msgid "Response metrics (HA Proxy)"
msgstr "Метрики відповідей (HA Proxy)"
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr "Метрики відповідей (NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Метрики відповідей (NGINX)"
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr "Продовжити"
@@ -7021,9 +8140,6 @@ msgstr "Повторити це завданнÑ"
msgid "Retry verification"
msgstr "Повторити перевірку"
-msgid "Reveal Variables"
-msgstr "Відкрити змінні"
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] "Показати значеннÑ"
@@ -7031,6 +8147,9 @@ msgstr[1] "Показати значеннÑ"
msgstr[2] "Показати значень"
msgstr[3] "Показати значень"
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Ðнулювати цей коміт"
@@ -7038,16 +8157,16 @@ msgid "Revert this merge request"
msgstr "Ðнулювати цей запит на злиттÑ"
msgid "Review"
-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 Ñ” \"провайдером поÑлуг\" або \"довірÑючою Ñтороною\"."
msgid "Reviewing"
-msgstr "ЗатвердженнÑ"
+msgstr "Перевірка"
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ (запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ !%{mergeRequestId})"
+msgstr "Перевірка (запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ !%{mergeRequestId})"
msgid "Revoke"
msgstr "Відкликати"
@@ -7058,6 +8177,9 @@ msgstr "План-графік"
msgid "Run CI/CD pipelines for external repositories"
msgstr "ЗапуÑтити CI/CD конвеєри Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ–Ñ… репозиторіїв"
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr "Виконати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÐµÐ· тегів"
@@ -7065,10 +8187,10 @@ msgid "Runner cannot be assigned to other projects"
msgstr "Runner не може бути призначено Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¸Ñ… проектів"
msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
+msgstr "Runner запуÑкає Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ñ– вÑÑ–Ñ… непризначених проектів"
msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
+msgstr "Runner запуÑкає Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ñ– вÑÑ–Ñ… непризначених проектів в його групі"
msgid "Runner runs jobs from assigned projects"
msgstr "Runner виконує завданні із призначених проектів"
@@ -7085,6 +8207,9 @@ msgstr "Runner'и"
msgid "Runners API"
msgstr "API Runner’ів"
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Runner’и можуть розміщуватиÑÑ Ñƒ різних кориÑтувачів, на Ñерверах Ñ– навіть на вашій локальній машині."
@@ -7118,8 +8243,8 @@ msgstr "Єдиний вхід SAML"
msgid "SAML Single Sign On Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ”Ð´Ð¸Ð½Ð¾Ð³Ð¾ входу SAML"
-msgid "SAST"
-msgstr "SAST"
+msgid "SAML for %{group_name}"
+msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "Відбиток SHA1 Ñертифікату Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸ÑÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð¾ÐºÐµÐ½Ñ–Ð² SAML. Отримайте його від провайдера ідентифікації, де він також може називатиÑÑ \"Thumbprint\"."
@@ -7139,6 +8264,9 @@ msgstr "Перевірка SSL"
msgid "Save"
msgstr "Зберегти"
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr "Зберегти заÑтоÑунок"
@@ -7146,6 +8274,9 @@ msgid "Save changes"
msgstr "Зберегти зміни"
msgid "Save changes before testing"
+msgstr "Зберегти зміни перед теÑтуваннÑм"
+
+msgid "Save comment"
msgstr ""
msgid "Save pipeline schedule"
@@ -7170,7 +8301,7 @@ msgid "Scope"
msgstr "ОбÑÑг"
msgid "Scoped issue boards"
-msgstr "Тематичні дошки проблем"
+msgstr "Тематичні дошки задач"
msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
msgstr "Прокрутіть вниз до <strong>Google Code Project Hosting</strong> і увімкніть перемикач праворуч."
@@ -7184,6 +8315,9 @@ msgstr "Прокрутити вгору"
msgid "Search"
msgstr "Пошук"
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr "Пошук у гілках"
@@ -7194,7 +8328,10 @@ msgid "Search files"
msgstr "Пошук файлів"
msgid "Search for projects, issues, etc."
-msgstr "Пошук в проектах, проблемах і т. д."
+msgstr "Пошук в проектах, задачах і т. д."
+
+msgid "Search groups"
+msgstr ""
msgid "Search merge requests"
msgstr "Пошук у запитах на злиттÑ"
@@ -7218,16 +8355,16 @@ msgid "Search users"
msgstr "Пошук кориÑтувачів"
msgid "Search your projects"
-msgstr ""
+msgstr "Пошук у ваших проектах"
msgid "SearchAutocomplete|All GitLab"
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 "Запити на злиттÑ, Ñтворені мною"
@@ -7254,45 +8391,60 @@ msgid "Security Dashboard"
msgstr "Панель безпеки"
msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
-msgstr ""
+msgstr "Помилка під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… панелі керуваннÑ. Будь лаÑка, перевірте ваше з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· мережею Ñ– Ñпробуйте знову."
msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
-msgstr ""
+msgstr "Помилка під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÐºÑ–Ð»ÑŒÐºÐ¾ÑÑ‚Ñ– вразливоÑтей. Будь лаÑка, перевірте ваше з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· мережею Ñ– Ñпробуйте знову."
msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
-msgstr ""
+msgstr "Помилка під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÑпиÑку вразливоÑтей. Будь лаÑка, перевірте ваше з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· мережею Ñ– Ñпробуйте знову."
msgid "Security Dashboard|Issue Created"
-msgstr "Створено проблему"
+msgstr "Створено задачу"
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
-msgstr ""
+msgstr "Створити задачу"
msgid "Security Reports|Dismiss vulnerability"
+msgstr "Відхилити вразливіÑÑ‚ÑŒ"
+
+msgid "Security Reports|Learn more about setting up your dashboard"
msgstr ""
msgid "Security Reports|More info"
msgstr "Детальніше"
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
-msgstr ""
+msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð´Ð¾ панелі безпеки"
msgid "Security Reports|There was an error creating the issue."
-msgstr ""
+msgstr "Помилка при Ñтворенні задачі."
msgid "Security Reports|There was an error dismissing the vulnerability."
-msgstr ""
+msgstr "Помилка при відхиленні вразливоÑÑ‚Ñ–."
msgid "Security Reports|There was an error reverting the dismissal."
-msgstr ""
+msgstr "Помилка при анулюванні відхиленнÑ."
msgid "Security Reports|There was an error reverting this dismissal."
+msgstr "Помилка при анулюванні цього відхиленнÑ."
+
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -7304,6 +8456,12 @@ msgstr "Моніторинг вразливоÑтей у вашому коді"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "Конвеєр %{pipelineLink} запущено"
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr "Вибрати"
@@ -7317,7 +8475,7 @@ msgid "Select a namespace to fork the project"
msgstr "Виберіть проÑÑ‚Ñ–Ñ€ імен Ð´Ð»Ñ Ñ„Ð¾Ñ€ÐºÑƒ проекту"
msgid "Select a template repository"
-msgstr ""
+msgstr "Вибрати шаблон репозиторію"
msgid "Select a timezone"
msgstr "Вибрати чаÑовий поÑÑ"
@@ -7331,6 +8489,9 @@ msgstr "Виберіть виконавцÑ"
msgid "Select branch/tag"
msgstr "Виберіть гілку або тег"
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr "Вибрати проект"
@@ -7353,10 +8514,10 @@ msgid "Select the branch you want to set as the default for this project. All me
msgstr "Виберіть гілку по замовчанню Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту. Ð’ÑÑ– запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° коміти будуть автоматично зроблені в ній, Ñкщо ви тільки не виберете іншу."
msgid "Select the custom project template source group."
-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 <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
-msgstr "При виборі кориÑтувача Gitlab поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° нього буде додане до опиÑу проблем та коментарів (напр. \"<a href=\"#\"> @johnsmith</a>\"). Також це призведе до аÑоціації та/або Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ†Ð¸Ñ… проблем та коментарів на вибраного кориÑтувача."
+msgstr "При виборі кориÑтувача Gitlab поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° нього буде додане до опиÑу задачі та коментарів (напр. \"<a href=\"#\"> @johnsmith</a>\"). Також це призведе до аÑоціації та/або Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ†Ð¸Ñ… задач та коментарів на вибраного кориÑтувача."
msgid "Selective synchronization"
msgstr "Вибіркова ÑинхронізаціÑ"
@@ -7364,9 +8525,15 @@ msgstr "Вибіркова ÑинхронізаціÑ"
msgid "Send email"
msgstr "ÐадіÑлати лиÑта"
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr "Відправити дані про викориÑтаннÑ"
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr "вер."
@@ -7376,6 +8543,48 @@ msgstr "вереÑень"
msgid "Server version"
msgstr "ВерÑÑ–Ñ Ñервера"
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr "Service Desk"
@@ -7392,13 +8601,13 @@ msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Ð’Ñтановіть пароль Ð´Ð»Ñ Ñвого облікового запиÑу, щоб мати можливіÑÑ‚ÑŒ відправлÑти та отримувати через %{protocol}."
msgid "Set a template repository for projects in this group"
-msgstr ""
+msgstr "Вибрати шаблон репозиторію Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñ–Ð² у цій групі"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Ð’Ñтановіть Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм Ñ– обмежте рівні видимоÑÑ‚Ñ–. Ðалаштуйте джерела імпорту Ñ– протокол доÑтупу git."
msgid "Set instance-wide template repository"
-msgstr ""
+msgstr "Ð’Ñтановити репозиторій шаблонів Ð´Ð»Ñ Ð²Ñього інÑтанÑу"
msgid "Set max session time for web terminal."
msgstr "МакÑимальний термін дії ÑеÑÑ–Ñ— Ð´Ð»Ñ Ð²ÐµÐ±-терміналу."
@@ -7406,6 +8615,9 @@ msgstr "МакÑимальний термін дії ÑеÑÑ–Ñ— Ð´Ð»Ñ Ð²ÐµÐ±-Ñ‚
msgid "Set notification email for abuse reports."
msgstr "Ðалаштувати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ð¾ електронній пошті Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ про зловживаннÑ."
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "Ð’Ñтановіть вимоги Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ кориÑтувачів. Увімкніть обов’Ñзкову двофакторну автентифікацію."
@@ -7421,6 +8633,9 @@ msgstr "Ðвтоматично налаштувати Ñпецифічний run
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "Ðалаштуйте твердженнÑ/атрибути (email, ім'Ñ, прізвище) Ñ– NameID відповідно до %{docsLinkStart} документації %{icon}%{docsLinkEnd}"
+msgid "Set up new U2F device"
+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 "Ðалаштуйте Ñвій проект, щоб автоматично відправлÑти/отримувати зміни з іншого репозиторію. Гілки, теги та коміти автоматично будуть ÑинхронізуватиÑÑ."
@@ -7484,12 +8699,12 @@ msgstr "Показати команду"
msgid "Show complete raw log"
msgstr "Показати повний неформатований журнал"
+msgid "Show file browser"
+msgstr ""
+
msgid "Show latest version"
msgstr "Показати оÑтанню верÑÑ–ÑŽ"
-msgid "Show latest version of the diff"
-msgstr "Показати оÑтанню верÑÑ–ÑŽ порівнÑннÑ"
-
msgid "Show parent pages"
msgstr "Показати батьківÑькі Ñторінки"
@@ -7527,12 +8742,21 @@ msgstr "Увійти"
msgid "Sign in / Register"
msgstr "Увійти або зареєÑтруватиÑÑ"
-msgid "Sign in to %{group_name}"
-msgstr "Увійти в %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
msgid "Sign in with Single Sign-On"
msgstr "Увійти за допомогою єдиного входу"
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr "Вийти"
@@ -7542,6 +8766,9 @@ msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ"
msgid "Sign-up restrictions"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr "Розмір"
@@ -7558,14 +8785,23 @@ msgid "Slower but makes sure the project workspace is pristine as it clones the
msgstr "Повільніше, але гарантує, що робоча облаÑÑ‚ÑŒ проекту чиÑтою, оÑкільки воно клонує Ñховище з Ð½ÑƒÐ»Ñ Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ завданнÑ"
msgid "Smartcard"
-msgstr ""
+msgstr "Смарт-карта"
msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr "Ðе вдалоÑÑ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ñмарт-карту: відÑутній заголовок в Ñертифікаті клієнта."
+
+msgid "Snippet Contents"
msgstr ""
msgid "Snippets"
msgstr "Сніпети"
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr "ЩоÑÑŒ пішло не так з нашого боку"
@@ -7575,8 +8811,11 @@ msgstr "ЩоÑÑŒ пішло не так з нашого боку."
msgid "Something went wrong on our end. Please try again!"
msgstr "ЩоÑÑŒ пішло не так на нашій Ñтороні. Будь-лаÑка, Ñпробуйте ще раз!"
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
-msgstr "Помилка при зміні конфіденційноÑÑ‚Ñ– цієї проблеми"
+msgstr "Помилка при зміні конфіденційноÑÑ‚Ñ– цієї задачі"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "ЩоÑÑŒ пішло не так, при Ñпробі зміни Ñтану Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ %{issuableDisplayName}"
@@ -7584,9 +8823,15 @@ msgstr "ЩоÑÑŒ пішло не так, при Ñпробі зміни Ñтан
msgid "Something went wrong when toggling the button"
msgstr "Помилка при перемиканні кнопки"
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "Помилка при закритті %{issuable}. Будь лаÑка, Ñпробуйте пізніше"
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr "Помилка при отриманні ÑпиÑку %{listType}"
@@ -7605,6 +8850,9 @@ msgstr "ЩоÑÑŒ пішло не так під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð
msgid "Something went wrong while fetching the registry list."
msgstr "ЩоÑÑŒ пішло не так при отриманні ÑпиÑку із реєÑтру."
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr "Помилка при повторному відкритті %{issuable}. Будь лаÑка, Ñпробуйте пізніше"
@@ -7615,7 +8863,7 @@ msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "Проблема, не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %{project} до панелі керуваннÑ"
msgid "Something went wrong, unable to get operations projects"
-msgstr ""
+msgstr "Проблема, не вдаєтьÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ операційні проекти"
msgid "Something went wrong, unable to remove project"
msgstr "Проблема, не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ проект"
@@ -7629,9 +8877,15 @@ msgstr "Вибачте, жоден епік не задовольнÑÑ” крит
msgid "Sorry, no projects matched your search"
msgstr "Ðа жаль жоден проект не задовольнÑÑ” критеріÑм вашого пошуку"
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr "Сортувати за"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr "Рівень доÑтупу, в порÑдку зроÑтаннÑ"
@@ -7677,8 +8931,8 @@ msgstr "Ðайменш популÑрний"
msgid "SortOptions|Less weight"
msgstr "Менша вага"
-msgid "SortOptions|Milestone"
-msgstr "Етап"
+msgid "SortOptions|Milestone due date"
+msgstr ""
msgid "SortOptions|Milestone due later"
msgstr "Етап запланований на пізніше"
@@ -7710,6 +8964,9 @@ msgstr "ÐайÑтаріший з Ñтворених"
msgid "SortOptions|Oldest joined"
msgstr "Приєднаний найраніше"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr "Залогінений найраніше"
@@ -7722,6 +8979,9 @@ msgstr "ПопулÑрніÑÑ‚ÑŒ"
msgid "SortOptions|Priority"
msgstr "Пріоритет"
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr "Ðещодавно зареєÑтровані"
@@ -7749,6 +9009,9 @@ msgstr "Код"
msgid "Source is not available"
msgstr "Джерело недоÑтупне"
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr "Спам-журнал"
@@ -7764,6 +9027,9 @@ msgstr "Вкажіть шаблон адреÑи електронної пошт
msgid "Specify the following URL during the Runner setup:"
msgstr "Зазначте наÑтупний URL під Ñ‡Ð°Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Runner-а:"
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr "Виконати об'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ (squash) комітів"
@@ -7800,27 +9066,54 @@ msgstr "ÐктивніÑÑ‚ÑŒ в обраних проектах"
msgid "Starred projects"
msgstr "Обрані проекти"
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "Почати %{new_merge_request} з цими змінами"
msgid "Start a review"
-msgstr ""
+msgstr "Розпочати перевірку"
msgid "Start and due date"
+msgstr "Дата початку та завершеннÑ"
+
+msgid "Start cleanup"
msgstr ""
msgid "Start date"
msgstr "Дата початку"
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "ЗапуÑÑ‚Ñ–Ñ‚ÑŒ Runner!"
msgid "Start your trial"
-msgstr ""
+msgstr "Розпочати пробний період"
msgid "Started"
msgstr "Запущений"
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "ПочинаєтьÑÑ Ð¾ (за Грінвічем)"
@@ -7830,6 +9123,12 @@ msgstr "Залиште Ñвоє Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–
msgid "Status"
msgstr "СтатуÑ"
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr "Зупинити Ñередовище"
@@ -7845,6 +9144,9 @@ msgstr "Зупинено"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr "Зупинка Ñередовища наразі неможлива, тому що відбуваєтьÑÑ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr "Сховище"
@@ -7860,9 +9162,12 @@ msgstr "Підгрупи та проекти"
msgid "Submit as spam"
msgstr "Позначити Ñк Ñпам"
-msgid "Submit review"
+msgid "Submit feedback"
msgstr ""
+msgid "Submit review"
+msgstr "ÐадіÑлати перевірку"
+
msgid "Submit search"
msgstr "ÐадіÑлати пошук"
@@ -7875,10 +9180,94 @@ msgstr "ПідпиÑатиÑÑ Ð½Ð° рівні групи"
msgid "Subscribe at project level"
msgstr "ПідпиÑатиÑÑ Ð½Ð° рівні проекту"
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
+msgstr "Ви підпиÑані"
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7893,8 +9282,11 @@ msgstr "СиÑтемні гуки"
msgid "System Info"
msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ ÑиÑтему"
-msgid "System header and footer:"
-msgstr "Заголовок Ñ– футер ÑиÑтеми:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
msgid "System metrics (Custom)"
msgstr "СиÑтемні метрики (ВлаÑні)"
@@ -7902,12 +9294,11 @@ msgstr "СиÑтемні метрики (ВлаÑні)"
msgid "System metrics (Kubernetes)"
msgstr "СиÑтемні метрики (Kubernetes)"
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] "Тег (%{tag_count})"
-msgstr[1] "Тега (%{tag_count})"
-msgstr[2] "Тегів (%{tag_count})"
-msgstr[3] "Тегів (%{tag_count})"
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "Теги"
@@ -8002,6 +9393,12 @@ msgstr "Шаблон"
msgid "Templates"
msgstr "Шаблони"
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Угода про Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг Ñ– політика конфіденційноÑÑ‚Ñ–"
@@ -8017,23 +9414,29 @@ msgstr "Пошук результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами"
msgid "Thanks! Don't show me this again"
msgstr "ДÑкую! Більше не показувати це повідомленнÑ"
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr "Розширений глобальний пошук в GitLab — це потужний інÑтрумент Ñкий заощаджує ваш чаÑ. ЗаміÑÑ‚ÑŒ Ð´ÑƒÐ±Ð»ÑŽÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ Ñ– витрати чаÑу, ви можете шукати код інших команд, Ñкий може допомогти у вашому проекті."
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr "Об'єкти Git LFS <strong>не</strong> будуть ÑинхронізуватиÑÑ."
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 X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Сертифікат X509 викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð²Ð·Ð°Ñ”Ð¼Ð½Ð¾Ñ— перевірки автентичноÑÑ‚Ñ– TLS Ñ– необхідний Ð´Ð»Ñ Ð·Ð²'Ñзку з зовнішньою Ñлужбою авторизації. Якщо залишити порожнім, Ñертифікат Ñервера буде перевірÑтиÑÑŒ при доÑтупі через HTTPS."
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 coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ ÐапиÑÐ°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ показує Ñ‡Ð°Ñ Ð²Ñ–Ð´ першого коміту до ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ. Дані будуть автоматично додані піÑÐ»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ першого запиту на злиттÑ."
@@ -8054,7 +9457,10 @@ msgid "The import will time out after %{timeout}. For repositories that take lon
msgstr "Імпорт буде припинено піÑÐ»Ñ %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð², Ñким потрібно більше чаÑу, викориÑтовуйте комбінацію clone/push."
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
-msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ ÐŸÑ€Ð¾Ð±Ð»ÐµÐ¼Ð° показує, Ñкільки чаÑу потрібно від ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ до Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ñ—Ñ— до ÑкогоÑÑŒ етапу, або Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ на дошку. Почніть Ñтворювати проблеми, щоб переглÑдати дані Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñтадії."
+msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð—Ð°Ð´Ð°Ñ‡Ð° показує, Ñкільки чаÑу потрібно від ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– до Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ñ—Ñ— до ÑкогоÑÑŒ етапу, або Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– на дошку. Почніть Ñтворювати задачі, щоб переглÑдати дані Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñтадії."
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr "МакÑимальний розмір файлу — 200 Кб."
@@ -8078,7 +9484,7 @@ msgid "The private key to use when a client certificate is provided. This value
msgstr "Приватний ключ, Ñкий викориÑтовуєтьÑÑ Ð¿Ñ€Ð¸ наданні клієнтÑького Ñертифіката. Його Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð°ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¾."
msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
-msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Production показує загальний Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ ÑтвореннÑм проблеми та розгортаннÑм коду у production. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ð½Ð¾Ñ— ідеї до production циклу."
+msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Production показує загальний Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ ÑтвореннÑм задачі та розгортаннÑм коду у production. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ð½Ð¾Ñ— ідеї до production циклу."
msgid "The project can be accessed by any logged in user."
msgstr "ДоÑтуп до проекту можливий будь-Ñким зареєÑтрованим кориÑтувачем."
@@ -8099,10 +9505,10 @@ msgid "The repository must be accessible over <code>http://</code>, <code>https:
msgstr "Репозиторій має бути доÑтупним через <code>http://</code>, <code>https://</code> або <code>git://</code>."
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
-msgstr ""
+msgstr "Репозиторій має бути доÑтупним через <code>http://</code>, <code>https: //</code>, <code>ssh: //</code> Ñ– <code>git: //</code>."
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
-msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑ” Ñ‡Ð°Ñ Ð²Ñ–Ð´ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ про об'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ його виконаннÑ. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ запиту на злиттÑ."
+msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ ÐŸÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ° показує Ñ‡Ð°Ñ Ð²Ñ–Ð´ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ про об'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ його виконаннÑ. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ запиту на злиттÑ."
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "План-графік показує Ñтан ваших епіків у чаÑÑ–"
@@ -8120,7 +9526,7 @@ msgid "The time taken by each data entry gathered by that stage."
msgstr "ЧаÑ, витрачений на кожен елемент, зібраний на цій Ñтадії."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr ""
+msgstr "Ð§Ð°Ñ Ð´Ñ–Ñ— Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñплине через %{number_of_minutes} хвилин. Ð”Ð»Ñ Ð²ÐµÐ»Ð¸ÐºÐ¸Ñ… репозиторіїв викориÑтовуйте комбінацію clone/push."
msgid "The usage ping is disabled, and cannot be configured through this form."
msgstr "Збір даних про викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾, Ñ– це не можна налаштувати через цю форму."
@@ -8134,21 +9540,39 @@ msgstr "Мапа кориÑтувачів — це правила імпорту
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Середнє Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð² Ñ€Ñдку. Приклад: між 3, 5, 9, Ñередніми 5, між 3, 5, 7, 8, Ñередніми (5 + 7) / 2 = 6."
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Ðаразі немає жодного архівованого проекту"
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
-msgstr "Ðемає проблем Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
+msgstr "Ðемає задач Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
msgid "There are no labels yet"
msgstr "Тут ще немає міток"
-msgid "There are no merge requests to show"
-msgstr "Ðемає запитів на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
+msgid "There are no open issues"
+msgstr ""
-msgid "There are no projects shared with this group yet"
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
+msgid "There are no projects shared with this group yet"
+msgstr "Ще немає Ñпільних проектів з цією групою"
+
msgid "There are no staged changes"
msgstr "Ðемає індекÑованих змін"
@@ -8179,12 +9603,21 @@ msgstr "Помилка при підпиÑці на цю мітку."
msgid "There was an error when unsubscribing from this label."
msgstr "Помилка при відпиÑці від цієї мітки."
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr "Ðими можна керувати за допомогою %{link}."
msgid "Third party offers"
msgstr "Сторонні пропозиції"
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "Цей інÑÑ‚Ð°Ð½Ñ GitLab ще немає загальних Runner'ів. ÐдмініÑтратори можуть Ñ—Ñ… зареєÑтрувати у Ñпеціальному розділі конфігурації."
@@ -8204,43 +9637,46 @@ msgid "This container registry has been scheduled for deletion."
msgstr "Заплановане Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ реєÑтру контейнерів."
msgid "This date is after the due date, so this epic won't appear in the roadmap."
-msgstr ""
+msgstr "Ð¦Ñ Ð´Ð°Ñ‚Ð° наÑтупає пізніше дати закінченнÑ, тому цей епік не буде відображатиÑÑ Ð² плані-графіку."
msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr ""
+msgstr "Ð¦Ñ Ð´Ð°Ñ‚Ð° Ñ” більш ранньою, ніж дата початку, тому цей епік не відображатиметьÑÑ Ð² плані-графіку."
msgid "This diff is collapsed."
msgstr "Це порівнÑÐ½Ð½Ñ Ð·Ð³Ð¾Ñ€Ð½ÑƒÑ‚Ð¾."
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr "Цей каталог"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
msgid "This group"
msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð°"
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° дозволÑÑ” вхід через обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ”Ð´Ð¸Ð½Ð¾Ð³Ð¾ входу %{group_name}. Ви будете перенаправлені на зовнішню Ñторінку авторизації."
-
msgid "This group does not provide any group Runners yet."
msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° ще не має жодного групового Runner’а."
msgid "This is a confidential issue."
-msgstr "Це конфіденційна проблема."
+msgstr "Це конфіденційна задача."
msgid "This is a delayed job to run in %{remainingTime}"
-msgstr ""
+msgstr "Це завданнÑ, відкладено на %{remainingTime}"
msgid "This is the author's first Merge Request to this project."
msgstr "Це перший запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ–Ð´ цього автора Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
msgid "This issue is confidential"
-msgstr "Ð¦Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð° Ñ” конфіденційною"
+msgstr "Ð¦Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° Ñ” конфіденційною"
msgid "This issue is confidential and locked."
-msgstr "Ð¦Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð° конфіденційна Ñ– заблокована."
+msgstr "Ð¦Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° конфіденційна Ñ– заблокована."
msgid "This issue is locked."
-msgstr "Ð¦Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð° заблокована."
+msgstr "Ð¦Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° заблокована."
msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð¿ÑƒÑкаєтьÑÑ ÐºÐ¾Ñ€Ð¸Ñтувачем. ЧаÑто вони викориÑтовуютьÑÑ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ на production"
@@ -8270,10 +9706,10 @@ msgid "This job is an out-of-date deployment to %{environmentLink}. View the mos
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} and will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñтворює Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° %{environmentLink} Ñ– перезапише %{deploymentLink}."
msgid "This job is creating a deployment to %{environmentLink}."
msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñтворює Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° %{environmentLink}."
@@ -8281,11 +9717,11 @@ msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñтворює Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° %{envir
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ±ÑƒÐ²Ð°Ñ” в Ñтані Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ– чекає на запуÑк Runner"
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
-msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ, тому що немає активних runner'ів, Ñкі могли б його виконати."
+msgid "This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
msgid "This job is the most recent deployment to %{link}."
msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ” оÑтаннім розгортаннÑм на %{link}."
@@ -8293,7 +9729,7 @@ msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ” оÑтаннім розгортаннÑм на
msgid "This job requires a manual action"
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼Ð°Ð³Ð°Ñ” ручних дій"
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8314,6 +9750,15 @@ msgstr "Ð¦Ñ Ñторінка недоÑтупна, тому що ви не мо
msgid "This page will be removed in a future release."
msgstr "Цю Ñторінку буде видалено у майбутній верÑÑ–Ñ—."
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr "Цей проект"
@@ -8321,7 +9766,7 @@ msgid "This project does not belong to a group and can therefore not make use of
msgstr "Цей проект не входить до жодної групи Ñ– тому не може викориÑтовувати групові Runner’и."
msgid "This project does not have a wiki homepage yet"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту немає домашньої Ñторінки вікі"
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr "Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту вимкнено білінг. Щоб Ñтворити клаÑтер, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">увімкніть білінг <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> Ñ– Ñпробуйте знову."
@@ -8330,43 +9775,43 @@ msgid "This repository"
msgstr "Цей репозиторій"
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 will update the hostname that is used to generate private commit emails. %{learn_more}"
-msgstr ""
+msgstr "Цей параметр оновить назву хоÑта, Ñка викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ñ–Ñ— приватних email-Ð°Ð´Ñ€ÐµÑ Ð² підпиÑах комітів. %{learn_more}"
msgid "This source diff could not be displayed because it is too large."
msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð·Ð¸Ñ‚Ð¸ порівнÑннÑ, оÑкільки воно завелике."
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
msgstr "Цей кориÑтувач не має ідентифікацій"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
-msgstr ""
+msgstr "Цей кориÑтувач буде автором вÑÑ–Ñ… подій в Ñтрічці активноÑÑ‚Ñ–, Ñка генеруєтьÑÑ Ð½Ð° оÑнові оновлень, таких Ñк ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… гілок чи нових комітів, Ñкі відправлÑтимутьÑÑ Ð² Ñ–Ñнуючі гілки."
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr "Цей кориÑтувач буде автором вÑÑ–Ñ… подій в каналі активноÑÑ‚Ñ–, Ñкі Ñ” результатом оновленнÑ, наприклад ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… гілок або Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… комітів до Ñ–Ñнуючих гілок. При Ñтворенні або перепризначенні ви зможете призначити лише Ñебе кориÑтувачем Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ."
-msgid "This will delete the custom metric, Are you sure?"
-msgstr "Це призведе до Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñної метрики, ви впевнені?"
+msgid "This will redirect you to an external sign in page."
+msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
-msgstr "Ці Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти автоматично Ñтануть обговореннÑми проблем, Ñкі відображатимутьÑÑ Ñ‚ÑƒÑ‚ (причому коментарі Ñтануть чаÑтиною перепиÑки)."
+msgstr "Ці Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти автоматично Ñтануть обговореннÑми задач, Ñкі відображатимутьÑÑ Ñ‚ÑƒÑ‚ (причому коментарі Ñтануть чаÑтиною перепиÑки)."
msgid "Time before an issue gets scheduled"
-msgstr "Ð§Ð°Ñ Ð´Ð¾ початку потраплÑÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ в планувальник"
+msgstr "Ð§Ð°Ñ Ð´Ð¾ початку потраплÑÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ в планувальник"
msgid "Time before an issue starts implementation"
-msgstr "Ð§Ð°Ñ Ð´Ð¾ початку роботи над проблемою"
+msgstr "Ð§Ð°Ñ Ð´Ð¾ початку роботи над задачою"
msgid "Time before enforced"
-msgstr ""
+msgstr "Ð§Ð°Ñ Ð´Ð¾ примуÑового запуÑку"
msgid "Time between merge request creation and merge/close"
msgstr "Ð§Ð°Ñ Ð¼Ñ–Ð¶ ÑтвореннÑм запиту Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ– його виконаннÑм або закриттÑм"
@@ -8453,7 +9898,7 @@ msgid "Timeago|1 hour remaining"
msgstr "ЗалишилаÑÑŒ 1 година"
msgid "Timeago|1 minute ago"
-msgstr "1 хвилина тому"
+msgstr "1 хвилину тому"
msgid "Timeago|1 minute remaining"
msgstr "ЗалишилаÑÑŒ 1 хвилина"
@@ -8550,9 +9995,18 @@ msgstr "Порада:"
msgid "Title"
msgstr "Заголовок"
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr "Ð’ GitLab"
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб додати ключ SSH вам необхідно %{generate_link_start}згенерувати його%{link_end} або викориÑтати %{existing_link_start}Ñ–Ñнуючий ключ%{link_end}."
@@ -8566,16 +10020,16 @@ msgid "To connect an SVN repository, check out %{svn_link}."
msgstr "Ð”Ð»Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ SVN-репозиторію, переглÑньте %{svn_link}."
msgid "To define internal users, first enable new users set to external"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ–Ñ… кориÑтувачів, Ñпочатку вÑтановіть Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… кориÑтувачів \"зовнішній по замовчанню\""
msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
+msgstr "Щоб увімкнути це Ñ– побачити Когорти КориÑтувачів, перейдіть в %{application_settings_link_start}Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°ÑтоÑунку%{application_settings_link_end}."
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 "Ð”Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ введіть URL-адреÑу FogBugz та параметри входу нижче. Далі ви зможете перенеÑти кориÑтувачів та вибрати проекти Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ."
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
+msgstr "Щоб почати роботу, з'єднайте цю Ñторінку з Ñервером Jaeger, або дізнайтеÑÑ, Ñк %{link_start_tag}вÑтановити Jaeger%{link_end_tag}"
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Спочатку введіть адреÑу Ñервера GÑ–tea Ñ– %{link_to_personal_token}."
@@ -8595,13 +10049,28 @@ msgstr "Ð”Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ репозиторіїв з GitHub, ви ÑпочÐ
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "Ð”Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ SVN-репозиторію, переглÑньте %{svn_link}."
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr "Щоб переміÑтити або Ñкопіювати веÑÑŒ проект GitLab з іншої інÑталÑції GitLab до цього, перейдіть на Ñторінку налаштувань оригіналу проекту, Ñтворіть файл екÑпорту та надішліть його Ñюди."
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "Щоб викориÑтовувати лише функції CI/CD Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ репозиторію, виберіть <strong>CI/CD Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ репозиторію</strong>."
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8610,6 +10079,9 @@ msgstr "Щоб налаштувати аутентифікацію SAML Ð´Ð»Ñ Ð
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… завдань ви можете додати Runner’и до вашої групи"
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr "До цього інÑтанÑу GitLab"
@@ -8617,6 +10089,9 @@ msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' in
msgstr "Щоб перевірити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ GitLab CI, перейдіть до \"CI / CD → Конвеєри\" у вашому проекті та натиÑніть кнопку \"Перевірка конфігурації (CI Lint)\"."
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку, додайте дату початку чи Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾ одного з ваших епіків в цій групі або Ñ—Ñ— підгрупах. При поміÑÑчному переглÑді показуютьÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ епіки за попередній, поточний, та наÑтупні 5 міÑÑців."
+
+msgid "To widen your search, change or remove filters above"
msgstr ""
msgid "To widen your search, change or remove filters."
@@ -8634,15 +10109,18 @@ msgstr "Задачі"
msgid "Toggle Sidebar"
msgstr "Перемикач бічної панелі"
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
+msgstr "Перемкнути Ð¾Ð¿Ð¸Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð²"
+
+msgid "Toggle commit list"
msgstr ""
msgid "Toggle discussion"
msgstr "Перемикач диÑкуÑÑ–Ñ—"
-msgid "Toggle file browser"
-msgstr ""
-
msgid "Toggle navigation"
msgstr "Переключити навігацію"
@@ -8677,45 +10155,54 @@ msgid "Total: %{total}"
msgstr "Ð’Ñього: %{total}"
msgid "Tracing"
-msgstr ""
+msgstr "ВідÑтеженнÑ"
msgid "Track activity with Contribution Analytics."
msgstr "ВідÑтежувати активніÑÑ‚ÑŒ за допомогою аналітики учаÑників."
msgid "Track groups of issues that share a theme, across projects and milestones"
-msgstr "ВідÑтежуйте групи проблем зі Ñпільною темою з різних проектів та етапів"
+msgstr "ВідÑтежуйте групи задач зі Ñпільною темою з різних проектів та етапів"
msgid "Track time with quick actions"
msgstr "ВідÑтежуйте Ñ‡Ð°Ñ Ð·Ð° допомогою швидких дій"
msgid "Tree view"
-msgstr ""
+msgstr "У виглÑді дерева"
msgid "Trending"
msgstr "ПопулÑрні"
-msgid "Trigger"
-msgstr "Тригер"
-
msgid "Trigger pipelines for mirror updates"
msgstr "ЗапуÑкати конвеєри Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð¸Ñ… змін"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
-msgstr ""
+msgstr "Викликати конвеєри, коли гілки або теги оновлюютьÑÑ Ð² репозиторії upstream. Ð’ залежноÑÑ‚Ñ– від активноÑÑ‚Ñ– в репозиторії upstream, це може значно збільшити Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð° CI runner'и. Вмикайте це тільки тоді, коли знаєте, що вони впораютьÑÑ Ð· навантаженнÑм."
msgid "Trigger this manual action"
msgstr "ЗапуÑтити цю ручну дію"
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "Тригери можуть примуÑово перезібрати гілку або тег через API. Ці токени дозволÑÑŽÑ‚ÑŒ діÑти від імені кориÑтувача: в тому чиÑлі отримувати доÑтуп до його проектів та проектних прав доÑтупу."
msgid "Troubleshoot and monitor your application with tracing"
-msgstr ""
+msgstr "УÑÑƒÐ½ÐµÐ½Ð½Ñ Ð½ÐµÐ¿Ð¾Ð»Ð°Ð´Ð¾Ðº Ñ– моніторинг вашого заÑтоÑунку за допомогою відÑтеженнÑ"
msgid "Try again"
msgstr "Спробуйте ще раз"
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
+msgstr "Спробуйте вÑÑ– функції GitLab протÑгом 30 днів."
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
msgid "Turn on Service Desk"
@@ -8725,26 +10212,32 @@ msgid "Twitter"
msgstr "Twitter"
msgid "Two-factor authentication"
-msgstr "Двофакторна аутентифікаціÑ"
+msgstr "Двофакторна автентифікаціÑ"
msgid "Type"
msgstr "Тип"
+msgid "URL"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Ðеможливо завантажити порівнÑÐ½Ð½Ñ (diff). %{button_try_again}"
-msgid "Unable to save your changes"
-msgstr ""
-
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Ðеможливо увійти до групи за допомогою SAML через \"%{reason}\""
msgid "Unable to update this epic at this time."
msgstr "Ðеможливо оновити цей епік в даний момент."
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr "СкаÑувати"
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr "Ðевідомо"
@@ -8761,7 +10254,7 @@ msgid "Unresolve discussion"
msgstr "Повторно відкрити обговореннÑ"
msgid "Unschedule job"
-msgstr ""
+msgstr "СкаÑувати заплановане завданнÑ"
msgid "Unstage"
msgstr "Ðе індекÑувати"
@@ -8776,7 +10269,7 @@ msgid "Unstaged"
msgstr "ÐеіндекÑовано"
msgid "Unstaged %{type}"
-msgstr "ÐеіндекÑовано %{type}"
+msgstr "ÐеіндекÑовані %{type}"
msgid "Unstaged and staged %{type}"
msgstr "ÐеіндекÑовані та проіндекÑовані %{type}"
@@ -8793,6 +10286,9 @@ msgstr "ВідпиÑатиÑÑ Ð½Ð° рівні групи"
msgid "Unsubscribe at project level"
msgstr "ВідпиÑатиÑÑ Ð½Ð° рівні проекту"
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr "Ðепідтверджено"
@@ -8800,11 +10296,14 @@ msgid "Up to date"
msgstr "Ðктуальний"
msgid "Upcoming"
-msgstr ""
+msgstr "Ðезабаром"
msgid "Update"
msgstr "Оновити"
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr "Оновити зараз"
@@ -8814,6 +10313,9 @@ msgstr "Оновіть Ñ–Ð¼â€™Ñ Ð³Ñ€ÑƒÐ¿Ð¸, опиÑ, аватар та видÐ
msgid "Updating"
msgstr "ОновленнÑ"
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "Перейдіть на вищий тарифний план щоб активувати Покращений Глобальний Пошук."
@@ -8824,23 +10326,38 @@ msgid "Upgrade your plan to activate Group Webhooks."
msgstr "Перейдіть на вищий тарифний план щоб активувати групові веб-гуки."
msgid "Upgrade your plan to activate Issue weight."
-msgstr "Перейдіть на вищий тарифний план щоб активувати вагу обговорень проблем."
+msgstr "Перейдіть на вищий тарифний план щоб активувати вагу обговорень задач."
msgid "Upgrade your plan to improve Issue boards."
-msgstr "Перейдіть на вищий тарифний план щоб покращити дошки обговорень."
+msgstr "Перейдіть на вищий тарифний план щоб покращити дошки задач."
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr "ÐадіÑлати <code>GoogleCodeProjectHosting.json</code> тут:"
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "ÐадіÑлати новий файл"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "ÐадіÑлати файл"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "ÐатиÑніть, щоб надіÑлати"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr "Лайки"
@@ -8857,7 +10374,7 @@ msgid "Use Service Desk to connect with your users (e.g. to offer customer suppo
msgstr "ВикориÑтовуйте Service Desk Ð´Ð»Ñ Ð·Ð²â€™Ñзку з вашими кориÑтувачами (наприклад, щоб запропонувати клієнтÑьку підтримку) через електронну пошту безпоÑередньо із GitLab"
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
-msgstr "ВикориÑтовуйте групові етапи, щоб керувати у одному етапі проблеми з різних проектів."
+msgstr "ВикориÑтовуйте групові етапи, щоб керувати у одному етапі задачі з різних проектів."
msgid "Use one line per URI"
msgstr "ВикориÑтовуйте один Ñ€Ñдок Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ URI"
@@ -8871,11 +10388,17 @@ msgstr "ВикориÑтовувати токен під Ñ‡Ð°Ñ ÑƒÑтановк
msgid "Use your global notification setting"
msgstr "ВикориÑтовуютьÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "ВикориÑтовуєтьÑÑ ÑƒÑ‡Ð°Ñниками Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ у вашу групу в GitLab"
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr "Когорти КориÑтувача показуютьÑÑ Ð»Ð¸ÑˆÐµ тоді, коли увімкнено %{usage_ping_link_start}збір даних про викориÑтаннÑ%{usage_ping_link_end}."
+msgstr "Когорти КориÑтувачів показуютьÑÑ Ð»Ð¸ÑˆÐµ тоді, коли увімкнено %{usage_ping_link_start}збір даних про викориÑтаннÑ%{usage_ping_link_end}."
msgid "User Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
@@ -8893,52 +10416,88 @@ msgid "UserProfile|Already reported for abuse"
msgstr "Вже повідомлено про зловживаннÑ"
msgid "UserProfile|Contributed projects"
-msgstr ""
+msgstr "ВнеÑки в проекти"
msgid "UserProfile|Edit profile"
msgstr "Редагувати профіль"
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr "Групи"
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ–ÑÑ‚ÑŒ"
+msgid "UserProfile|No snippets found."
+msgstr ""
+
msgid "UserProfile|Overview"
msgstr "ОглÑд"
msgid "UserProfile|Personal projects"
msgstr "ОÑобиÑÑ‚Ñ– проекти"
-msgid "UserProfile|Recent contributions"
-msgstr "ОÑтанні внеÑки"
-
msgid "UserProfile|Report abuse"
msgstr "Повідомити про зловживаннÑ"
msgid "UserProfile|Snippets"
msgstr "Сніпети"
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr "ПідпиÑатиÑÑ"
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr "Цей кориÑтувач має приватний профіль"
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "ПереглÑнути вÑе"
msgid "UserProfile|View user in admin area"
msgstr "ПереглÑнути кориÑтувача в адмінці"
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr "КориÑтувачі"
-msgid "Variables"
-msgstr "Змінні"
+msgid "Users requesting access to"
+msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr "Змінні заÑтоÑовуютьÑÑ Ð´Ð¾ Ñередовищ через runner. Вони можуть бути захищені, в такому випадку вони доÑтупні тільки Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñ‰ÐµÐ½Ð¸Ñ… гілок та тегів. Ви можете викориÑтовувати змінні Ð´Ð»Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ–Ð², Ñекретний ключів тощо."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
msgid "Various container registry settings."
msgstr "Різноманітні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÑ”Ñтру контейнерів."
@@ -8946,12 +10505,18 @@ msgstr "Різноманітні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÑ”Ñтру конÑ
msgid "Various email settings."
msgstr "Різноманітні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾ÑˆÑ‚Ð¸."
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr "Різноманітні налаштуваннÑ, що впливають на продуктивніÑÑ‚ÑŒ GitLab."
msgid "Verification information"
msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ перевірку"
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr "Підтверджено"
@@ -8964,6 +10529,12 @@ msgstr "ПереглÑнути %{alerts}"
msgid "View app"
msgstr "ПереглÑнути заÑтоÑунок"
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr "ПереглÑнути документацію"
@@ -8977,7 +10548,7 @@ msgid "View group labels"
msgstr "ПереглÑнути мітки групи"
msgid "View issue"
-msgstr "ПереглÑнути проблему"
+msgstr "ПереглÑнути задачу"
msgid "View it on GitLab"
msgstr "ПереглÑнути це на GitLab"
@@ -9003,6 +10574,9 @@ msgstr "ПереглÑд заміненого файлу @ "
msgid "View the documentation"
msgstr "ПереглÑнути документацію"
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑ‚Ñ– та доÑтупу"
@@ -9027,11 +10601,17 @@ msgstr "Публічний"
msgid "VisibilityLevel|Unknown"
msgstr "Ðевідомий"
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr "КлаÑ"
msgid "Vulnerability|Confidence"
-msgstr ""
+msgstr "ВпевненіÑÑ‚ÑŒ"
msgid "Vulnerability|Description"
msgstr "ОпиÑ"
@@ -9040,43 +10620,64 @@ msgid "Vulnerability|File"
msgstr "Файл"
msgid "Vulnerability|Identifiers"
-msgstr ""
+msgstr "Ідентифікатори"
msgid "Vulnerability|Instances"
-msgstr ""
+msgstr "ІнÑтанÑи"
msgid "Vulnerability|Links"
-msgstr ""
+msgstr "ПоÑиланнÑ"
msgid "Vulnerability|Project"
msgstr "Проект"
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
-msgstr "РішеннÑ"
+msgid "Vulnerability|Severity"
+msgstr "Рівень"
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Хочете побачити дані? Будь лаÑка, попроÑить у адмініÑтратора доÑтуп."
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Ми виÑвили потенційний Ñпам у %{humanized_resource_name}. Будь лаÑка, введіть цей код Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ reCAPTCHA, щоб продовжити."
msgid "We don't have enough data to show this stage."
msgstr "Ми не маємо доÑтатньо даних Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— Ñтадії."
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Ми хочемо бути впевнені, що це ви, будь лаÑка, підтвердіть, що ви не робот."
msgid "Web IDE"
msgstr "Веб-IDE"
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr "Веб-термінал"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
-msgstr "Веб-гук дозволÑÑ” вам викликати URL Ñкщо, наприклад, був відправлений новий код або Ñтворено нову проблему. Ви можете налаштувати його так, щоб він реагував на певні події (відправки коду, проблеми або запити на злиттÑ). Групові веб-гуки заÑтоÑовуютьÑÑ Ð´Ð¾ вÑÑ–Ñ… проектів в групі Ñ– дозволÑÑŽÑ‚ÑŒ вам Ñтандартизувати Ñ—Ñ… Ð´Ð»Ñ Ð²Ñієї вашої групи."
+msgstr "Веб-гук дозволÑÑ” вам викликати URL Ñкщо, наприклад, був відправлений новий код або Ñтворено нову задачу. Ви можете налаштувати його так, щоб він реагував на певні події (відправки коду, задачі або запити на злиттÑ). Групові веб-гуки заÑтоÑовуютьÑÑ Ð´Ð¾ вÑÑ–Ñ… проектів в групі Ñ– дозволÑÑŽÑ‚ÑŒ вам Ñтандартизувати Ñ—Ñ… Ð´Ð»Ñ Ð²Ñієї вашої групи."
msgid "Weeks"
msgstr "Тижні"
@@ -9096,6 +10697,9 @@ msgstr "Якщо увімкнено, кориÑтувачі не можуть в
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Якщо залишити URL порожнім, можна вÑтановлювати мітки клаÑифікації без Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ð¹ проекту та Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ñ— авторизації."
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr "Хто може бачити цю групу?"
@@ -9130,10 +10734,10 @@ msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
msgstr "Запропонувати Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–ÐºÑ–"
msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
-msgstr "Ви маєте бути учаÑником проекту Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб додавати вікі Ñторінки. Якщо у Ð²Ð°Ñ Ñ” пропозиції ÑтоÑовно Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–ÐºÑ– цього проекту, відкрийте проблему в %{issues_link}."
+msgstr "Ви маєте бути учаÑником проекту Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб додавати вікі Ñторінки. Якщо у Ð²Ð°Ñ Ñ” пропозиції ÑтоÑовно Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–ÐºÑ– цього проекту, відкрийте задачу в %{issues_link}."
msgid "WikiEmptyIssueMessage|issue tracker"
-msgstr "РеєÑÑ‚Ñ€ проблем"
+msgstr "РеєÑÑ‚Ñ€ задач"
msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
msgstr "Вікі дозволÑÑ” зберігати інформацію про ваш проект. Ðаприклад причину ÑтвореннÑ, принципи, Ñк його викориÑтовувати Ñ– Ñ‚. д."
@@ -9237,12 +10841,21 @@ msgstr "Сторінки"
msgid "Wiki|Wiki Pages"
msgstr "Вікі-Ñторінки"
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
-msgstr "З аналітикою контриб’юторів ви може вивчати активніÑÑ‚ÑŒ в обговореннÑÑ…, запитах на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ– подій відправки коду Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— організації Ñ– Ñ—Ñ— учаÑників."
+msgstr "З аналітикою контриб’юторів ви може вивчати активніÑÑ‚ÑŒ в задачах, запитах на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ– подій відправки коду Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— організації Ñ– Ñ—Ñ— учаÑників."
msgid "Withdraw Access Request"
msgstr "СкаÑувати запит доÑтупу"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr "Так"
@@ -9255,6 +10868,9 @@ msgstr "Так, дозволити мені зв’Ñзати кориÑтува
msgid "Yesterday"
msgstr "Вчора"
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Ви — адмініÑтратор, а це означає, що Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу Ð´Ð»Ñ <strong>%{client_name}</strong> дозволить їм взаємодіÑти з GitLab Ñк адмініÑтратору. Продовжуйте обережно."
@@ -9273,6 +10889,9 @@ msgstr "Ви збираєтеÑÑ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‚Ð¸ проект %{project_full_n
msgid "You are on a read-only GitLab instance."
msgstr "Ви знаходитеÑÑ Ð½Ð° інÑтанÑÑ– Gitlab \"тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ\"."
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "ЗаміÑÑ‚ÑŒ цього ви можете %{linkStart}переглÑнути бінарні дані%{linkEnd}."
@@ -9297,6 +10916,9 @@ msgstr "Ви можете додавати файли тільки коли пе
msgid "You can only edit files when you are on a branch"
msgstr "Ви можете редагувати файли, лише перебуваючи у ÑкійÑÑŒ гілці"
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Ви можете розв’Ñзати цей конфлікт Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð° допомогою інтерактивного режиму (викориÑтовуючи кнопки %{use_ours} та %{use_theirs}), або безпоÑередньо редагуючи файли. Закомітити зміни у %{branch_name}"
@@ -9315,6 +10937,9 @@ msgstr "Ви не можете запиÑувати на цей \"тільки Ð
msgid "You do not have any subscriptions yet"
msgstr "У Ð²Ð°Ñ Ñ‰Ðµ немає підпиÑок"
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” необхідних прав доÑтупу, щоб перевизначити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізації LDAP-груп."
@@ -9324,12 +10949,18 @@ msgstr "Ви не маєте ніÑких заÑтоÑунків"
msgid "You don't have any authorized applications"
msgstr "Ви не маєте ніÑких авторизованих заÑтоÑунків"
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” прав доÑтупу"
msgid "You have reached your project limit"
msgstr "Ви доÑÑгли Ñвого ліміту по кількоÑÑ‚Ñ– проектів"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr "Ви повинні прийнÑти правила кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑервіÑом Ñ– політику конфіденційноÑÑ‚Ñ– Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб Ñтворити обліковий запиÑ"
@@ -9339,17 +10970,23 @@ msgstr "Ви повинні мати доÑтуп керівника Ð´Ð»Ñ Ð¿Ñ€
msgid "You need a different license to enable FileLocks feature"
msgstr "Ð”Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— функції Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¤Ð°Ð¹Ð»Ñ–Ð² вам потрібна інша ліцензіÑ"
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr "Вам потрібна верÑÑ–Ñ git-lfs верÑÑ–Ñ— %{min_git_lfs_version} (або новіша), щоб продовжити. Будь лаÑка, відвідайте Ñторінку https://git-lfs.github.com"
msgid "You need permission."
msgstr "Вам потрібен дозвіл"
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
-msgstr "Ви втратите вÑÑ– зміни, внеÑені вами в цей файл. Цю дію не можна ÑкаÑувати."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
-msgstr "Ви втратите вÑÑ– неіндекÑовані зміни, внеÑені вами в цей проект. Цю дію не можна ÑкаÑувати."
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
msgid "You will not get any notifications via email"
msgstr "Ви не отримаєте ніÑких повідомлень по електронній пошті"
@@ -9390,6 +11027,9 @@ msgstr "Ви отримали це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· ваш о
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr "Ваші групи"
@@ -9405,12 +11045,18 @@ msgstr "ÐктивніÑÑ‚ÑŒ ваших проектів"
msgid "Your Todos"
msgstr "Ваші Задачі"
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr "Ваші заÑтоÑунки (%{size})"
msgid "Your authorized applications"
msgstr "Ваші авторизовані заÑтоÑунки"
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "Ваші зміни можуть бути закомічені до %{branch_name}, оÑкільки запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸Ð¹."
@@ -9423,12 +11069,24 @@ msgstr "Ваші зміни було збережено"
msgid "Your comment will not be visible to the public."
msgstr "Ваш коментар не буде видимим Ð´Ð»Ñ Ð²ÑÑ–Ñ…."
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "Ваші групи"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "Ваше ім'Ñ"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr "Ваші проекти"
@@ -9438,12 +11096,18 @@ msgstr "видалений кориÑтувач"
msgid "ago"
msgstr "тому"
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr "тощо"
msgid "assign yourself"
msgstr "призначити Ñебе"
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr "ім'Ñ Ð³Ñ–Ð»ÐºÐ¸"
@@ -9544,6 +11208,9 @@ msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð² виÑвлÑÑ” відомі
msgid "ciReport|DAST"
msgstr "DAST"
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей виÑвлÑÑ” відомі вразливоÑÑ‚Ñ– у залежноÑÑ‚ÑÑ… вашого коду."
@@ -9559,6 +11226,12 @@ msgstr "Відхилити вразливіÑÑ‚ÑŒ"
msgid "ciReport|Dismissed by"
msgstr "Відхилено"
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr "Динамічне теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ заÑтоÑунків (DAST) виÑвлÑÑ” відомі вразливоÑÑ‚Ñ– у вашому веб-заÑтоÑунку."
@@ -9595,7 +11268,7 @@ msgstr[2] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d нових
msgstr[3] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d нових ліцензій"
msgid "ciReport|License management detected no licenses for the source branch only"
-msgstr ""
+msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми не виÑвило ліцензій Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
msgid "ciReport|License management detected no new licenses"
msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми не виÑвило нових ліцензій"
@@ -9646,7 +11319,7 @@ msgid "ciReport|Static Application Security Testing (SAST) detects known vulnera
msgstr "Статичне теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ заÑтоÑунків (SAST) виÑвлÑÑ” відомі вразливоÑÑ‚Ñ– у вашому коді."
msgid "ciReport|There was an error creating the issue. Please try again."
-msgstr "Помилка при Ñтворенні проблеми. Будь лаÑка Ñпробуйте знову."
+msgstr "Помилка при Ñтворенні задачі. Будь лаÑка Ñпробуйте знову."
msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
msgstr "Помилка при відхиленні вразливоÑÑ‚Ñ–. Будь лаÑка, Ñпробуйте знову."
@@ -9685,11 +11358,14 @@ msgstr "в конвеєрі"
msgid "command line instructions"
msgstr "інÑтрукції Ð´Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¾Ð³Ð¾ Ñ€Ñдка"
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr "Ви вимикаєте конфіденційніÑÑ‚ÑŒ. Це означає, що <strong>будь-хто</strong> зможе бачити Ñ– залишати коментарі Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— проблеми."
+msgstr "Ви вимикаєте конфіденційніÑÑ‚ÑŒ. Це означає, що <strong>будь-хто</strong> зможе бачити Ñ– залишати коментарі Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— задачі."
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr "Ви вмикаєте конфіденційніÑÑ‚ÑŒ. Це означає що лише члени команди <strong>Ñ€Ñ–Ð²Ð½Ñ Ñ€ÐµÐ¿Ð¾Ñ€Ñ‚ÐµÑ€ або вище</strong> матимуть змогу бачити та залишати коментарі Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— проблеми."
+msgstr "Ви вмикаєте конфіденційніÑÑ‚ÑŒ. Це означає що лише учаÑники команди <strong>Ñ€Ñ–Ð²Ð½Ñ Ñ€ÐµÐ¿Ð¾Ñ€Ñ‚ÐµÑ€ або вище</strong> матимуть змогу бачити та залишати коментарі Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— задачі."
msgid "connecting"
msgstr "з'єднаннÑ"
@@ -9707,12 +11383,22 @@ msgstr[1] "дні"
msgstr[2] "днів"
msgstr[3] "днів"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr "токен Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
msgid "disabled"
msgstr "вимкнено"
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "done"
msgstr "готово"
@@ -9726,6 +11412,15 @@ msgstr[3] "чернеток"
msgid "enabled"
msgstr "увімкнено"
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} перезапиÑує запланований Ñ‡Ð°Ñ Ð¾Ñтаннім значеннÑм."
@@ -9735,21 +11430,39 @@ msgstr "Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
msgid "from"
msgstr "від"
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr "допомога"
msgid "here"
msgstr "тут"
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr "процедура імпорту"
msgid "importing"
msgstr "імпорт"
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "завершений інÑтанÑ"
@@ -9766,8 +11479,26 @@ msgstr "неправильний через наÑвніÑÑ‚ÑŒ блокуванÑ
msgid "is not a valid X509 certificate."
msgstr "не відповідний Ñертифікат X509."
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
-msgstr "дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼"
+msgstr "дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡"
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
msgid "latest deployment"
msgstr "оÑтаннє розгортаннÑ"
@@ -9781,6 +11512,9 @@ msgstr "керувати ліцензіÑми"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "заблоковано %{path_lock_user_name} %{created_at}"
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "запит на злиттÑ"
@@ -9788,9 +11522,21 @@ msgstr[1] "запити на злиттÑ"
msgstr[2] "запитів на злиттÑ"
msgstr[3] "запитів на злиттÑ"
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Будь лаÑка відновіть Ñ—Ñ— або викориÑтовуйте іншу %{missingBranchName} гілку"
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ %{metricsLinkStart} пам’ÑÑ‚Ñ– %{metricsLinkEnd} %{emphasisStart} впало %{emphasisEnd} з %{memoryFrom}Мб до %{memoryTo}Мб"
@@ -9806,11 +11552,11 @@ msgstr "Додати затвердженнÑ"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "ДозволÑÑ” коміти від учаÑників, Ñкі можуть зливати до цільової гілки"
-msgid "mrWidget|An error occured while removing your approval."
-msgstr "Під Ñ‡Ð°Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
-msgstr "Помилка при отриманні даних про Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту на злиттÑ."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Помилка при обробці вашого затвердженнÑ."
@@ -9846,7 +11592,10 @@ msgid "mrWidget|Closes"
msgstr "Закриває"
msgid "mrWidget|Create an issue to resolve them later"
-msgstr "Створіть проблему, щоб вирішити їх пізніше"
+msgstr "Створіть задачу, щоб вирішити їх пізніше"
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "СтатиÑтика Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– недоÑтупна"
@@ -9920,12 +11669,6 @@ msgstr "Оновити зараз"
msgid "mrWidget|Refreshing now"
msgstr "ВідбуваєтьÑÑ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ"
-msgid "mrWidget|Remove Source Branch"
-msgstr "Видалити гілку-джерело"
-
-msgid "mrWidget|Remove source branch"
-msgstr "Видалити гілку-джерело"
-
msgid "mrWidget|Remove your approval"
msgstr "Видалити ваше затвердженнÑ"
@@ -9976,20 +11719,20 @@ msgstr "Конвеєр Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð²Ðµ
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "HEAD гілки-джерела нещодавно було змінено. Будь лаÑка оновіть Ñторінку Ñ– переглÑньте зміни перед злиттÑм"
-msgid "mrWidget|The source branch has been removed"
-msgstr "Гілку-джерело видалено"
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr "Гілка-джерело на %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} цільової гілки"
-msgid "mrWidget|The source branch is being removed"
-msgstr "Гілка-джерело в процеÑÑ– видаленнÑ"
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
-msgid "mrWidget|The source branch will be removed"
-msgstr "Гілку-джерело буде видалено"
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
-msgid "mrWidget|The source branch will not be removed"
-msgstr "Гілку-джерело не буде видалено"
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "Ñ–Ñнують конфлікти при злитті"
@@ -9997,6 +11740,9 @@ msgstr "Ñ–Ñнують конфлікти при злитті"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "ПриÑутні незавершені обговореннÑ. Будь лаÑка завершіть Ñ—Ñ…"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "ВідбулаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при автоматичному злитті цього запиту"
@@ -10009,12 +11755,12 @@ msgstr "Цей проект заархівований, доÑтуп до зап
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr "Ви не можете безпоÑередньо редагувати цей проект. Будь лаÑка, зробіть форк, щоб внеÑти зміни."
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "Ви можете прийнÑти цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ за допомогою"
-msgid "mrWidget|You can remove source branch now"
-msgstr "Тепер ви можете видалити гілку-джерело"
-
msgid "mrWidget|branch does not exist."
msgstr "гілка не Ñ–Ñнує."
@@ -10033,9 +11779,21 @@ msgstr "н/д"
msgid "new merge request"
msgstr "Ðовий запит на злиттÑ"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr "або"
@@ -10059,6 +11817,9 @@ msgstr "пароль"
msgid "personal access token"
msgstr "оÑобиÑтий токен доÑтупу"
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr "приватний ключ не відповідає Ñертифікату."
@@ -10069,6 +11830,12 @@ msgstr[1] "проекти"
msgstr[2] "проектів"
msgstr[3] "проектів"
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr "залишилоÑÑŒ"
@@ -10081,6 +11848,9 @@ msgstr "видалити заплановану дату завершеннÑ"
msgid "remove weight"
msgstr "видалити вагу"
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] "відповідь"
@@ -10088,23 +11858,50 @@ msgstr[1] "відповіді"
msgstr[2] "відповідей"
msgstr[3] "відповідей"
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr "джерело"
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} оновлює Ñуму витраченого чаÑу."
msgid "started"
msgstr "розпочато"
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr "цей документ"
msgid "to help your contributors communicate effectively!"
msgstr "щоб допомогти вашим контриб’юторам ефективно ÑпілкуватиÑÑ!"
-msgid "toggle collapse"
-msgstr "згорнути/розгорнути"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
+msgstr ""
msgid "username"
msgstr "ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
@@ -10112,9 +11909,15 @@ msgstr "ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "uses Kubernetes clusters to deploy your code!"
msgstr "викориÑтовує клаÑтери Kubernetes Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ!"
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "переглÑнути це на GitLab"
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "з %{additions} додаваннÑми Ñ– %{deletions} видаленнÑми."
@@ -10125,3 +11928,6 @@ msgstr[1] "протÑгом %d хвилин "
msgstr[2] "протÑгом %d хвилин "
msgstr[3] "протÑгом %d хвилин "
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 49f27159396..522946d739f 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:21\n"
+"PO-Revision-Date: 2019-02-11 08:12\n"
msgid " Status"
msgstr "状æ€"
@@ -29,16 +29,17 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] " æ高 %d 点"
-msgid "\"%{query}\" in projects"
+msgid " or "
+msgstr ""
+
+msgid " or <#epic id>"
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] "%d 处新增"
+msgid " or <#issue id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] "%d 个已更改的文件"
+msgid "\"%{query}\" in projects"
+msgstr "在项目中\"%{query}\""
msgid "%d commit"
msgid_plural "%d commits"
@@ -48,9 +49,8 @@ msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] "è½åŽ %d 个æ交"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] "%d 处删除"
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -68,6 +68,10 @@ msgid "%d issue"
msgid_plural "%d issues"
msgstr[0] "%d 个议题"
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d 个层"
@@ -107,6 +111,9 @@ msgstr "%{counter_storage} (%{counter_repositories} 个存储库, %{counter_bu
msgid "%{count} %{alerts}"
msgstr "%{count}个%{alerts}"
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr "åŠå…¶ä»–%{count}å指派人"
@@ -124,12 +131,18 @@ msgstr "%{filePath} 已删除"
msgid "%{firstLabel} +%{labelCount} more"
msgstr "%{firstLabel} +%{labelCount} 更多"
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}群组%{group_docs_link_end} å…许您管ç†ã€å作多个项目。群组的æˆå‘˜å¯ä»¥è®¿é—®ç¾¤ç»„下的所有项目。"
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} 将被删除ï¼æ‚¨ç¡®å®šå—?"
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 已开始"
@@ -139,9 +152,6 @@ msgstr "%{lock_path} 被GitLab用户 %{lock_user_id} é”定"
msgid "%{name}'s avatar"
msgstr "%{name} 的头åƒ"
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} å¯ä»¥æ›¿ä»£è‡ªå®šä¹‰åŸŸä½¿ç”¨ã€‚"
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} 个è½åŽ %{default_branch} 分支的æ交, %{number_commits_ahead} 个超å‰çš„æ交"
@@ -151,6 +161,24 @@ msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "å·²å®Œæˆ %{percent}%%"
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text}%{files}"
@@ -167,12 +195,21 @@ msgstr "%{unstaged}个未暂存的更改åŠ%{staged}个已暂存的更改"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end}关于GitLab Inc.的共享信æ¯ã€‚"
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr "+ 其余 %{count} 项"
msgid "+ %{moreCount} more"
msgstr "+ 其余 %{moreCount} 项"
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr "- Runnerå·²å¯ç”¨ï¼Œéšæ—¶å¯ä»¥å¤„ç†æ–°ä½œä¸š"
@@ -229,11 +266,14 @@ msgstr[0] "%d ä½ç”¨æˆ·"
msgid "1st contribution!"
msgstr "最高贡献"
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr "å¯ç”¨åŒé‡è®¤è¯"
-msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "请è”系您的 GitLab 管ç†å‘˜èŽ·å–访问æƒé™ã€‚"
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
msgid "403|You don't have the permission to access this page."
msgstr "您没有æƒé™è®¿é—®æ­¤é¡µé¢ã€‚"
@@ -272,10 +312,10 @@ msgid "<strong>%{group_name}</strong> group members"
msgstr "<strong>%{group_name}</strong> 群组æˆå‘˜"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
-msgstr "<strong>%{pushes}</strong> 个推é€ï¼Œè¶…å‰ <strong>%{people}</strong> å贡献者的 <strong>%{commits}</strong> 个æ交。"
+msgstr "<strong>%{pushes}</strong>次推é€ï¼Œå«æ¥è‡ª<strong>%{people}</strong> å贡献者的<strong>%{commits}</strong>次以上æ交。"
-msgid "<strong>Removes</strong> source branch"
-msgstr "<strong>删除</strong>æºåˆ†æ”¯"
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "Runner是一个执行任务的进程。您å¯ä»¥æ ¹æ®éœ€è¦é…置任æ„æ•°é‡çš„Runner。"
@@ -322,6 +362,9 @@ msgstr "滥用报告"
msgid "Abuse reports"
msgstr "滥用报告"
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr "接å—æ¡æ¬¾"
@@ -358,11 +401,11 @@ msgstr "活动"
msgid "Add"
msgstr "添加"
-msgid "Add Changelog"
-msgstr "添加更新日志"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "添加贡献指å—"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "添加组 Webhooks å’Œ GitLab ä¼ä¸šç‰ˆã€‚"
@@ -373,8 +416,11 @@ msgstr "增加 Jaeger 地å€"
msgid "Add Kubernetes cluster"
msgstr "添加 Kubernetes 集群"
-msgid "Add Readme"
-msgstr "添加自述文件"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "在wiki中添加一个主页,其中包å«æœ‰å…³é¡¹ç›®çš„ä¿¡æ¯ï¼ŒGitLab将在此处显示该主页,而ä¸æ˜¯æ­¤æ¶ˆæ¯ã€‚"
@@ -406,6 +452,9 @@ msgstr "添加项目"
msgid "Add reaction"
msgstr "添加回应"
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr "添加到评审"
@@ -415,6 +464,9 @@ msgstr "添加待办事项"
msgid "Add user(s) to the group:"
msgstr "å‘群组添加用户"
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr "将用户加入群组"
@@ -430,9 +482,6 @@ msgstr "管ç†ä¸­å¿ƒ"
msgid "Admin Overview"
msgstr "管ç†æ¦‚览"
-msgid "Admin area"
-msgstr "管ç†ä¸­å¿ƒ"
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。该用户的议题ã€åˆå¹¶è¯·æ±‚以åŠé“¾æŽ¥åˆ°è¯¥ç”¨æˆ·çš„群组将被转移到系统的“Ghost用户â€ã€‚为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strong_start}ç¦ç”¨ç”¨æˆ·%{strong_end} 功能。一旦您 %{strong_start}删除用户%{strong_end},将无法撤消或æ¢å¤ã€‚"
@@ -466,12 +515,42 @@ msgstr "删除项目 %{projectName}?"
msgid "AdminProjects|Delete project"
msgstr "删除项目"
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "为æ¯ä¸ªé¡¹ç›®çš„自动审阅应用 (Auto Review Apps) 和自动部署 (Auto Deploy) 阶段指定一个默认使用的域。"
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr "ç¦ç”¨ç”¨æˆ·"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "删除用户 %{username} 以åŠç›¸å…³è´¡çŒ®å—?"
@@ -484,12 +563,42 @@ msgstr "删除用户"
msgid "AdminUsers|Delete user and contributions"
msgstr "删除用户åŠç›¸å…³è´¡çŒ®"
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "请输入 %{projectName} æ¥ç¡®è®¤"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "请输入 %{username} æ¥ç¡®è®¤"
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "高级æƒé™ï¼Œå¤§æ–‡ä»¶å­˜å‚¨å’ŒåŒé‡è®¤è¯è®¾ç½®ã€‚"
@@ -500,6 +609,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "警报"
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr "全部"
@@ -509,11 +621,17 @@ msgstr "所有更改å‡å·²æ交"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "从模æ¿æˆ–导入时为空白项目将å¯ç”¨æ‰€æœ‰åŠŸèƒ½ï¼Œä½†å¯ä»¥åœ¨é¡¹ç›®è®¾ç½®ä¸­å°†å…¶ç¦ç”¨ã€‚"
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr "所有用户"
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
-msgstr "具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜å…许æ交"
+msgstr "å…许具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜æ交"
msgid "Allow projects within this group to use Git LFS"
msgstr "å…许该群组中的项目使用Git LFS"
@@ -533,6 +651,9 @@ msgstr "å…许用户请求访问æƒé™"
msgid "Allow users to request access if visibility is public or internal."
msgstr "如果是公开或内部å¯è§æ€§ï¼Œåˆ™å…许用户请求访问æƒé™ã€‚"
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "这里å¯ä»¥æ·»åŠ å’Œç®¡ç† Kubernetes 集群。"
@@ -560,48 +681,21 @@ msgstr "应用%{link_to_client}请求访问您的 GitLab å¸æˆ·ã€‚"
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "空GitLab用户字段将在所有问题和注释的æ述中添加FogBugz用户的全å(例如“By John Smithâ€ï¼‰ã€‚它还将与项目创建者关è”å’Œ/或分é…这些问题和评论。"
-msgid "An error accured whilst committing your changes."
-msgstr "æ交更改时å‘生错误。"
-
msgid "An error has occurred"
msgstr "å‘生错误"
-msgid "An error occured creating the new branch."
-msgstr "创建分支时å‘生错误。"
-
-msgid "An error occured whilst fetching the job trace."
-msgstr "获å–作业日志时å‘生错误。"
-
-msgid "An error occured whilst fetching the latest pipeline."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
-msgid "An error occured whilst loading all the files."
-msgstr "加载文件时å‘生错误。"
-
-msgid "An error occured whilst loading the file content."
-msgstr "加载文件评论时å‘生错误。"
-
-msgid "An error occured whilst loading the file."
-msgstr "加载文件时å‘生错误。"
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr "加载åˆå¹¶è¯·æ±‚å˜æ›´å†…容时å‘生错误。"
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr "加载åˆå¹¶è¯·æ±‚的版本数æ®æ—¶å‘生错误。"
-
-msgid "An error occured whilst loading the merge request."
-msgstr "加载åˆå¹¶è¯·æ±‚æ—¶å‘生错误。"
-
-msgid "An error occured whilst loading the pipelines jobs."
-msgstr "加载æµæ°´çº¿ä½œä¸šæ—¶å‘生错误。"
-
msgid "An error occurred adding a draft to the discussion."
msgstr "å‘讨论添加è‰ç¨¿æ—¶å‡ºé”™ã€‚"
msgid "An error occurred adding a new draft."
msgstr "添加新è‰ç¨¿æ—¶å‡ºé”™ã€‚"
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "预览 blob 时出错"
@@ -674,12 +768,21 @@ msgstr "加载文件åæ—¶å‘生错误"
msgid "An error occurred while loading the file"
msgstr "加载文件时å‘生错误"
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr "å‘é€è¯·æ±‚æ—¶å‘生错误。"
msgid "An error occurred while removing approver"
msgstr "删除批准者时å‘生错误"
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr "渲染KaTeXæ—¶å‘生错误"
@@ -710,9 +813,54 @@ msgstr "更新评论时å‘生错误"
msgid "An error occurred while validating username"
msgstr "验è¯ç”¨æˆ·åæ—¶å‘生错误"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "å‘生了错误,请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr "分æž"
@@ -743,17 +891,35 @@ msgstr "应用:%{name}"
msgid "Applications"
msgstr "应用"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
-msgstr "å››"
+msgstr "4月"
msgid "April"
-msgstr "四月"
+msgstr "4月"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "已归档项目ï¼ä»“库和其他项目资æºå‡ä¸ºåªè¯»"
msgid "Archived projects"
-msgstr "已存档项目"
+msgstr "归档项目"
+
+msgid "Are you sure"
+msgstr ""
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "确定è¦åˆ é™¤æ­¤æµæ°´çº¿è®¡åˆ’å—?"
@@ -764,12 +930,24 @@ msgstr "您确定è¦åˆ é™¤è¿™ä¸ªæž„建å—?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "确定è¦æ”¾å¼ƒæœªä¿å­˜çš„更改å—?"
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "您确定è¦é‡æ–°ç”Ÿæˆå…¬é’¥å—?在镜åƒå†æ¬¡è¿è¡Œä¹‹å‰ï¼Œæ‚¨å¿…须更新远程æœåŠ¡å™¨ä¸Šçš„公钥。"
msgid "Are you sure you want to remove %{group_name}?"
msgstr "确定移除群组 %{group_name} å—?"
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr "你确定è¦åˆ é™¤è¿™ä¸ªèº«ä»½æ ‡è¯†å—?"
@@ -785,6 +963,9 @@ msgstr "是å¦ç¡®å®šç»ˆæ­¢å½“å‰çŽ¯å¢ƒï¼Ÿ"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "你确定è¦è§£é” %{path_lock_path} å—?"
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "确定å—?"
@@ -803,6 +984,9 @@ msgstr "请群组维护者é…置一个群组级 Runner。"
msgid "Assertion consumer service URL"
msgstr "断言消费者æœåŠ¡ URL"
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "分é…自定义颜色,如FF0000"
@@ -812,6 +996,9 @@ msgstr "指派标记"
msgid "Assign milestone"
msgstr "分é…里程碑"
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr "分é…到"
@@ -839,6 +1026,9 @@ msgstr "指派列表显示分é…给选定用户的所有议题。"
msgid "Assignee(s)"
msgstr "指派"
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "拖放文件到此处或者 %{upload_link}"
@@ -846,10 +1036,13 @@ msgid "Audit Events"
msgstr "审计事件"
msgid "Aug"
-msgstr "å…«"
+msgstr "8月"
msgid "August"
-msgstr "八月"
+msgstr "8 月"
+
+msgid "Auth Token"
+msgstr ""
msgid "Authentication Log"
msgstr "认è¯æ—¥å¿—"
@@ -866,6 +1059,9 @@ msgstr "作者"
msgid "Authorization code:"
msgstr "授æƒç ï¼š"
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr "在应用中输入您的用户å和密ç å³å®ŒæˆæŽˆæƒã€‚"
@@ -893,17 +1089,8 @@ msgstr "å¯ç”¨Auto DevOps"
msgid "Auto DevOps, runners and job artifacts"
msgstr "Auto DevOps, runnersåŠä½œä¸šäº§ç‰©"
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr "自动审阅程åºå’Œè‡ªåŠ¨éƒ¨ç½²ç¨‹åºéœ€è¦ %{kubernetes} æ‰èƒ½æ­£å¸¸å·¥ä½œã€‚"
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr "自动审阅程åºå’Œè‡ªåŠ¨éƒ¨ç½²ç¨‹åºéœ€è¦ä¸€ä¸ªåŸŸåå’Œ %{kubernetes} æ‰èƒ½æ­£å¸¸å·¥ä½œã€‚"
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "自动审阅程åºå’Œè‡ªåŠ¨éƒ¨ç½²ç¨‹åºéœ€è¦ä¸€ä¸ªåŸŸåæ‰èƒ½æ­£å¸¸å·¥ä½œã€‚"
-
msgid "Auto-cancel redundant, pending pipelines"
-msgstr "自动å–消多余的和挂起的æµæ°´çº¿"
+msgstr "自动å–消多余且处于等待状æ€çš„æµæ°´çº¿"
msgid "AutoDevOps|Auto DevOps"
msgstr "Auto DevOps"
@@ -935,14 +1122,26 @@ msgstr "å¯ç”¨Auto DevOps"
msgid "Automatically marked as default internal user"
msgstr "自动标记为默认内部用户"
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr "å¯ç”¨çš„"
-msgid "Available group Runners : %{runners}"
-msgstr "å¯ç”¨çš„群组Runner: %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
-msgid "Available group Runners : %{runners}."
-msgstr "å¯ç”¨çš„群组Runner: %{runners}."
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr "å³å°†åˆ é™¤å¤´åƒã€‚确定继续å—?"
@@ -972,10 +1171,10 @@ msgid "Badges|Adding the badge failed, please check the entered URLs and try aga
msgstr "添加徽章失败,请检查输入的网å€å¹¶é‡è¯•ã€‚"
msgid "Badges|Badge image URL"
-msgstr "徽章图åƒç½‘å€"
+msgstr "徽章图片网å€"
msgid "Badges|Badge image preview"
-msgstr "徽章图åƒé¢„览"
+msgstr "徽章图片预览"
msgid "Badges|Delete badge"
msgstr "删除徽章"
@@ -993,10 +1192,10 @@ msgid "Badges|Link"
msgstr "链接"
msgid "Badges|No badge image"
-msgstr "无徽章图åƒ"
+msgstr "无徽章图片"
msgid "Badges|No image to preview"
-msgstr "无图åƒå¯é¢„览"
+msgstr "无图片å¯é¢„览"
msgid "Badges|Please fill in a valid URL"
msgstr "请输入正确的 URL"
@@ -1005,7 +1204,7 @@ msgid "Badges|Project Badge"
msgstr "项目徽章"
msgid "Badges|Reload badge image"
-msgstr "é‡æ–°åŠ è½½å¾½ç« å›¾åƒ"
+msgstr "é‡æ–°åŠ è½½å¾½ç« å›¾ç‰‡"
msgid "Badges|Save changes"
msgstr "ä¿å­˜æ›´æ”¹"
@@ -1014,7 +1213,7 @@ msgid "Badges|Saving the badge failed, please check the entered URLs and try aga
msgstr "ä¿å­˜å¾½ç« å¤±è´¥ï¼Œè¯·æ£€æŸ¥è¾“入的网å€å¹¶é‡è¯•ã€‚"
msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "%{docsLinkStart}å˜é‡%{docsLinkEnd} GitLab支æŒï¼š %{placeholders}"
+msgstr "GitLab支æŒçš„%{docsLinkStart}å˜é‡%{docsLinkEnd}: %{placeholders}"
msgid "Badges|The badge was deleted."
msgstr "徽章已删除。"
@@ -1059,13 +1258,13 @@ msgid "Billing"
msgstr "计费"
msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
-msgstr "%{group_name} 正在使用 %{plan_link} 方案。"
+msgstr "%{group_name} 正在使用 %{plan_link}计划。"
msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
msgstr "ç›®å‰æ— æ³•è‡ªåŠ¨é™çº§æˆ–å‡çº§åˆ°æŸäº›è®¡åˆ’。"
msgid "BillingPlans|Current plan"
-msgstr "当å‰æ–¹æ¡ˆ"
+msgstr "当å‰è®¡åˆ’"
msgid "BillingPlans|Customer Support"
msgstr "客户支æŒ"
@@ -1074,13 +1273,13 @@ msgid "BillingPlans|Downgrade"
msgstr "é™çº§"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
-msgstr "通过阅读我们的 %{faq_link}了解有关æ¯ä¸ªè®¡åˆ’的更多信æ¯ï¼Œæˆ–者开始å…费试用GitLab.comçš„Gold计划30天。"
+msgstr "请查阅%{faq_link}æ¥äº†è§£æœ‰å…³å„订阅计划的更多信æ¯ã€‚您å¯ä»¥é€šè¿‡ä»¥ä¸‹é“¾æŽ¥å…费试用GitLab.comçš„Gold计划30天。"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
msgstr "请查阅%{faq_link} 进一步了解æ¯ä¸ªè®¡åˆ’的相关信æ¯ã€‚"
msgid "BillingPlans|Manage plan"
-msgstr "管ç†æ–¹æ¡ˆ"
+msgstr "管ç†è®¡åˆ’"
msgid "BillingPlans|Please contact %{customer_support_link} in that case."
msgstr "在这ç§æƒ…况下请è”ç³»%{customer_support_link}。"
@@ -1089,16 +1288,16 @@ msgid "BillingPlans|See all %{plan_name} features"
msgstr "查看 %{plan_name} 计划中的功能"
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 "访问 %{parent_billing_page_link} 以管ç†è¯¥é¡¹ç›®çš„计费方案。"
+msgstr "访问%{parent_billing_page_link}的计费部分以管ç†è¯¥é¡¹ç›®çš„订阅计划。"
msgid "BillingPlans|Upgrade"
msgstr "å‡çº§"
msgid "BillingPlans|You are currently on the %{plan_link} plan."
-msgstr "您目å‰æ­£åœ¨ä½¿ç”¨ %{plan_link} 方案。"
+msgstr "您目å‰æ­£åœ¨ä½¿ç”¨%{plan_link}计划。"
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
msgstr "您的GitLab.com试用期已在%{expiration_date}结æŸã€‚%{learn_more_text}"
@@ -1110,7 +1309,7 @@ msgid "BillingPlans|features"
msgstr "功能"
msgid "BillingPlans|frequently asked questions"
-msgstr "常问问题"
+msgstr "常è§é—®é¢˜"
msgid "BillingPlans|monthly"
msgstr "æ¯æœˆ"
@@ -1127,6 +1326,12 @@ msgstr "BitbucketæœåŠ¡å™¨å¯¼å…¥"
msgid "Bitbucket import"
msgstr "从 Bitbucket 导入"
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr "åšå®¢"
@@ -1136,10 +1341,6 @@ msgstr "看æ¿"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "未在此项目的仓库中找到 %{branchName} 分支。"
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] "分支(%{branch_count})"
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "已创建分支 <strong>%{branch_name}</strong> 。如需设置自动部署, 请选择åˆé€‚çš„ GitLab CI Yaml 模æ¿å¹¶æ交更改。%{link_to_autodeploy_doc}"
@@ -1293,26 +1494,41 @@ msgstr "æµè§ˆæ–‡ä»¶"
msgid "Browse files"
msgstr "æµè§ˆæ–‡ä»¶"
-msgid "Built-In"
-msgstr "内置"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
msgid "Business metrics (Custom)"
msgstr "业务指标(自定义)"
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr "CI/CD 设置"
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr "CI将使用上é¢æŒ‡å®šçš„凭æ®è¿è¡Œã€‚"
msgid "CI/CD"
-msgstr "æŒç»­é›†æˆ/æŒç»­éƒ¨ç½²"
+msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "CI/CD é…ç½®"
@@ -1344,12 +1560,6 @@ msgstr "默认为Auto DevOpsæµæ°´çº¿"
msgid "CICD|Deployment strategy"
msgstr "部署策略"
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr "部署策略需è¦ä¸€ä¸ªåŸŸåæ‰èƒ½æ­£å¸¸å·¥ä½œã€‚"
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr "如果您使用Auto DevOps设置多个Kubernetes群集,请ä¸è¦åœ¨æ­¤å¤„设置域。"
-
msgid "CICD|Jobs"
msgstr "作业"
@@ -1359,18 +1569,27 @@ msgstr "了解更多Auto DevOps的相关信æ¯"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr "在未找到备用CIé…置文件时使用Auto DevOpsæµæ°´çº¿ã€‚"
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
-msgstr "如需使用自动化应用程åºè¯„审和自动部署,请指定域å。"
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
msgid "CICD|instance enabled"
msgstr "å·²å¯ç”¨çš„实例"
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr "回调 URL"
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr "无法找到此分支的 HEAD æ交"
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "å–消"
@@ -1383,12 +1602,21 @@ msgstr "无法自动åˆå¹¶"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "无法修改托管的 Kubernetes 集群"
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr "è¯ä¹¦æŒ‡çº¹"
msgid "Change Weight"
msgstr "更改æƒé‡"
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr "更改模æ¿"
@@ -1410,12 +1638,12 @@ msgstr "还原"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "这将创建一个新的æ交, æ¥è¿˜åŽŸçŽ°æœ‰çš„更改。"
-msgid "Changelog"
-msgstr "更新日志"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "差异显示方å¼ä¾<b>æº</b>版本åˆå¹¶åˆ°<b>目标</b>版本的形å¼ã€‚"
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "统计图"
@@ -1425,9 +1653,15 @@ msgstr "å³æ—¶é€šè®¯"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "查看%{docs_link_start}文档%{docs_link_end}。"
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr "正在检查%{text}çš„å¯ç”¨æ€§..."
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr "正在检查分支的å¯ç”¨æ€§..."
@@ -1449,6 +1683,12 @@ msgstr "选择文件 ……"
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "选择分支/标签(例如%{master})或输入æ交(例如%{sha})以查看更改内容或创建åˆå¹¶è¯·æ±‚。"
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr "选择模æ¿..."
@@ -1467,6 +1707,9 @@ msgstr "选择文件..."
msgid "Choose the top-level group for your repository imports."
msgstr "选择存储库导入的顶级群组。"
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr "选择您希望与此次è¦èŠ‚点åŒæ­¥çš„群组。"
@@ -1560,8 +1803,8 @@ msgstr "所有环境"
msgid "CiVariable|Create wildcard"
msgstr "创建通é…符"
-msgid "CiVariable|Error occured while saving variables"
-msgstr "ä¿å­˜å˜é‡æ—¶å‘生错误"
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
msgid "CiVariable|New environment"
msgstr "新建环境"
@@ -1581,6 +1824,12 @@ msgstr "验è¯å¤±è´¥"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "ä¸å¯ç”¨: %{reason}"
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr "清除æœç´¢"
@@ -1620,29 +1869,53 @@ msgstr "客户端认è¯å¯†é’¥å¯†ç "
msgid "Clients"
msgstr "客户端"
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr "克隆仓库"
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr "关闭"
msgid "Close epic"
msgstr "关闭å²è¯—故事"
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr "已关闭"
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr "已关闭议题"
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} å·²æˆåŠŸå®‰è£…到Kubernetes集群上"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr "%{boldNotice} 这将添加一些é¢å¤–的资æºï¼Œå¦‚è´Ÿè½½å‡è¡¡å™¨ï¼Œè¿™å¯èƒ½ä¼šäº§ç”Ÿé¢å¤–çš„æˆæœ¬ï¼Œå…·ä½“å–决于您安装Kubernetes集群的托管æœåŠ¡æ供商。如果您使用的是Google Kubernetes Engine,则å¯ä»¥ %{pricingLink}。"
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
-msgstr "Knative构建扩展了Kubernetes,并利用现有的Kubernetes原语为您æ供从æºä»£ç æž„建è¿è¡ŒäºŽç¾¤é›†ä¸Šå®¹å™¨çš„能力。例如,您å¯ä»¥ç¼–写一个构建,该构建使用 Kubernetes原生资æºä»Žå­˜å‚¨åº“中获å–æºä»£ç ï¼Œå°†å…¶æž„建到容器中,然åŽè¿è¡Œè¯¥é•œåƒã€‚"
+msgid "ClusterIntegration|%{title} upgraded successfully."
+msgstr ""
msgid "ClusterIntegration|API URL"
msgstr "API地å€"
@@ -1665,27 +1938,42 @@ msgstr "Kubernetes集群集æˆçš„高级选项"
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr "安装IngressåŽï¼Œæ‚¨éœ€è¦åœ¨ç”Ÿæˆçš„外部IP地å€ä¸ŠæŒ‡å‘DNS,以便在部署åŽæŸ¥çœ‹æ‚¨çš„应用程åºã€‚ %{ingressHelpLink}"
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "å°è¯•èŽ·å–项目地域时å‘生错误:%{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr "å°è¯•èŽ·å–您的项目时å‘生错误:%{error}"
-
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
-msgstr "å°è¯•èŽ·å–设备类型时å‘生错误:%{error}"
-
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr "å°è¯•è”ç³»Google Cloud APIæ—¶å‘生错误。请ç¨åŽå†è¯•ã€‚"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "应用程åº"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr "确定è¦åˆ é™¤æ­¤Kubernetes集群的集æˆå—?注æ„这并ä¸ä¼šåˆ é™¤å®žé™…çš„Kubernetes集群本身。"
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr "CAè¯ä¹¦"
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "è¯ä¹¦æŽˆæƒåŒ…(PEMæ ¼å¼)"
@@ -1695,6 +1983,9 @@ msgstr "选择è¦åœ¨ Kubernetes 群集上安装的应用程åºã€‚安装以下任
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "请选择使用此Kubernetes群集的环境。"
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "å¤åˆ¶API地å€"
@@ -1707,6 +1998,9 @@ msgstr "å¤åˆ¶Ingress IP地å€åˆ°å‰ªè´´æ¿"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr "å°†Jupyter主机åå¤åˆ¶åˆ°å‰ªè´´æ¿"
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "å¤åˆ¶Kubernetes集群å称"
@@ -1717,7 +2011,7 @@ msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "创建Kubernetes集群"
msgid "ClusterIntegration|Did you know?"
-msgstr "你是å¦äº†è§£ï¼Ÿ"
+msgstr "您了解å—?"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
msgstr "å¯ç”¨æˆ–ç¦ç”¨GitLab与Kubernetes群集的连接。"
@@ -1732,7 +2026,16 @@ msgid "ClusterIntegration|Environment scope"
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 "æ¯ä¸ªæ–°çš„ Google äº‘å¹³å° (GCP) å¸æˆ·ä½¿ç”¨æ­¤é“¾æŽ¥ %{sign_up_link} å¯ä»¥æ”¶åˆ° 300 美元的赠金。因为与 Google çš„åˆä½œå…³ç³»ï¼ŒGitLab 能够为新的和现有的 GCP å¸æˆ·æä¾›é¢å¤– 200 美元的赠金,以便于开始将 GitLab 集æˆåˆ° Google Kubernetes 引擎。"
+msgstr "æ¯ä¸ªæ–°çš„ Google äº‘å¹³å° (GCP) å¸æˆ·ä½¿ç”¨æ­¤é“¾æŽ¥ %{sign_up_link} å¯ä»¥æ”¶åˆ° 价值300美元的å…è´¹é¢åº¦ã€‚通过与Google çš„åˆä½œï¼ŒGitLabå¯ä»¥ä¸ºæ–°æ³¨å†Œçš„和现有的 GCP å¸æˆ·æä¾›é¢å¤– 200 美元的é¢åº¦ï¼Œä»¥æ–¹ä¾¿å®žçŽ°GitLabå’Œ Google Kubernetes引擎的集æˆã€‚"
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
msgid "ClusterIntegration|Fetching machine types"
msgstr "正在获å–实例类型"
@@ -1806,6 +2109,12 @@ msgstr "集æˆKubernetes集群自动化"
msgid "ClusterIntegration|Integration status"
msgstr "集æˆçŠ¶æ€"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Jupyter主机å"
@@ -1821,6 +2130,12 @@ msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
msgstr "Knative域å:"
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Kubernetes 集群"
@@ -1857,11 +2172,14 @@ msgstr "了解更多的Kubernetesä¿¡æ¯"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "了解更多的群组级Kubernetes集群信æ¯"
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr "机器类型"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
-msgstr "请确ä¿æ‚¨çš„å¸æˆ· %{link_to_requirements} å¯ä»¥åˆ›å»º Kubernetes 集群"
+msgstr "请确ä¿æ‚¨çš„å¸æˆ·%{link_to_requirements}å¯ä»¥åˆ›å»º Kubernetes 集群"
msgid "ClusterIntegration|Manage"
msgstr "管ç†"
@@ -1935,6 +2253,9 @@ msgstr "如果需è¦ï¼Œå¯å°†å…¶æ›¿æ¢ä¸ºæ‚¨è‡ªå·±çš„主机å。如果这样åš
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "请求安装失败"
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr "ä¿å­˜æ›´æ”¹"
@@ -1977,17 +2298,23 @@ msgstr "显示"
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "å‘生了内部错误"
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr "在 Google Kubernetes Engine 上创建Kubernetes集群时å‘生错误"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "安装 %{title} æ—¶å‘生故障"
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr "IP地å€æ­£åœ¨åˆ†é…中。如果花费时间过长,请检查您的Kubernetes集群或谷歌Kubernetes引擎(GKE) 上的é…é¢ã€‚"
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
-msgstr "该å¸æˆ·éœ€å…·å¤‡åœ¨ä¸‹é¢æŒ‡å®šçš„%{link_to_container_project}中创建 Kubernetes集群的æƒé™"
+msgstr "该å¸æˆ·éœ€å…·å¤‡åœ¨å¦‚下指定的%{link_to_container_project}中创建 Kubernetes集群的æƒé™"
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr "此选项å…许您在å¯ç”¨RBAC的群集上安装应用程åºã€‚"
@@ -1998,6 +2325,18 @@ msgstr "开关Kubernetes 集群"
msgid "ClusterIntegration|Token"
msgstr "令牌"
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr "验è¯é¡¹ç›®è´¦å•çŠ¶æ€"
@@ -2010,8 +2349,11 @@ msgstr "使用与此项目关è”çš„Kubernetes集群,å¯ä»¥æ–¹ä¾¿åœ°ä½¿ç”¨å®¡é˜
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "在安装以下应用程åºä¹‹å‰ï¼Œå¿…须先安装Helm Tiller"
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
-msgstr "您的å¸æˆ·å¿…须拥有%{link_to_kubernetes_engine}"
+msgstr "您的å¸æˆ·å¿…须有æƒé™%{link_to_kubernetes_engine}"
msgid "ClusterIntegration|Zone"
msgstr "地域"
@@ -2029,7 +2371,7 @@ msgid "ClusterIntegration|help page"
msgstr "帮助页é¢"
msgid "ClusterIntegration|meets the requirements"
-msgstr "符åˆè¦æ±‚"
+msgstr "符åˆç›¸å…³è¦æ±‚"
msgid "ClusterIntegration|properly configured"
msgstr "正确é…ç½®"
@@ -2037,6 +2379,9 @@ msgstr "正确é…ç½®"
msgid "ClusterIntegration|sign up"
msgstr "注册"
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr "代ç æ‰€æœ‰è€…"
@@ -2044,19 +2389,28 @@ msgid "Cohorts"
msgstr "世代表"
msgid "Collapse"
-msgstr "折å "
+msgstr "收起"
msgid "Collapse sidebar"
-msgstr "折å ä¾§è¾¹æ "
+msgstr "收起侧边æ "
+
+msgid "Command line instructions"
+msgstr ""
msgid "Comment"
-msgstr "评论"
+msgstr "添加评论"
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
msgid "Comment & resolve discussion"
-msgstr "评论并解决讨论"
+msgstr "添加评论并解决讨论"
msgid "Comment & unresolve discussion"
-msgstr "评论并将讨论å˜ä¸ºæœªå†³"
+msgstr "添加评论并将讨论å˜ä¸ºæœªå†³"
msgid "Comment form position"
msgstr "评论框ä½ç½®"
@@ -2068,13 +2422,15 @@ msgid "Commit"
msgid_plural "Commits"
msgstr[0] "æ交"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] "æ交(%{commit_count})"
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr "æ交消æ¯"
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "最近30次æ交相应æŒç»­é›†æˆèŠ±è´¹çš„时间(分钟)"
@@ -2138,6 +2494,9 @@ msgstr "比较Gitæ交版本"
msgid "Compare Revisions"
msgstr "比较版本"
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr "与上个æ交比较å˜æ›´å†…容"
@@ -2165,12 +2524,18 @@ msgstr "机密"
msgid "Confidentiality"
msgstr "ä¿å¯†æ€§"
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr "é…ç½®Gitaly超时时间。"
msgid "Configure Tracing"
msgstr "é…置跟踪"
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "在仓库上é…置自动git检查和仓库整ç†ã€‚"
@@ -2204,6 +2569,9 @@ msgstr "连接外部仓库åŽï¼Œæ–°æ交将会å¯åŠ¨CI/CDæµæ°´çº¿ã€‚ä»…å¯ç”¨C
msgid "Connecting..."
msgstr "正在连接..."
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr "容器注册表"
@@ -2247,11 +2615,14 @@ msgid "ContainerRegistry|Use different image names"
msgstr "使用ä¸åŒçš„é•œåƒå称"
msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
-msgstr "å°† Docker 容器注册表集æˆåˆ° GitLab 中,æ¯ä¸ªé¡¹ç›®éƒ½å¯ä»¥æœ‰å„自的空间æ¥å­˜å‚¨ Docker çš„é•œåƒã€‚"
+msgstr "通过使用GitLab内置的Docker容器注册表,æ¯ä¸ªé¡¹ç›®éƒ½å¯ä»¥æœ‰ç‹¬ç«‹çš„空间æ¥å­˜å‚¨Dockeré•œåƒã€‚"
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "您也å¯ä»¥ä½¿ç”¨ %{deploy_token} 以åªè¯»æ–¹å¼è®¿é—®é•œåƒåº“çš„é•œåƒã€‚"
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr "继续"
@@ -2267,14 +2638,14 @@ msgstr "为 GitLab æ交贡献"
msgid "Contribution"
msgstr "贡献"
-msgid "Contribution guide"
-msgstr "贡献指å—"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr "<strong>%{calendar_date}</strong>的贡献"
msgid "Contributions per group member"
-msgstr "æ¯å群组æˆå‘˜çš„贡献"
+msgstr "群组æˆå‘˜è´¡çŒ®è¯¦æƒ…"
msgid "Contributors"
msgstr "贡献者"
@@ -2303,21 +2674,27 @@ msgstr "控制此次è¦èŠ‚点的åŒæ­¥å­˜å‚¨åº“的最大并å‘"
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr "控制此Geo节点的校验æ“作的最大并å‘性"
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr "ConvDev指数"
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "å¤åˆ¶ %{protocol} 克隆URL"
-msgid "Copy HTTPS clone URL"
-msgstr "å¤åˆ¶HTTPS克隆URL"
-
msgid "Copy ID to clipboard"
msgstr "å¤åˆ¶ID到剪贴æ¿"
msgid "Copy SSH clone URL"
msgstr "å¤åˆ¶SSH克隆URL"
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr "å°† SSH 公钥å¤åˆ¶åˆ°å‰ªè´´æ¿"
@@ -2342,11 +2719,8 @@ msgstr "将接收邮件地å€å¤åˆ¶åˆ°å‰ªè´´æ¿"
msgid "Copy link"
msgstr "å¤åˆ¶é“¾æŽ¥"
-msgid "Copy name to clipboard"
-msgstr "å¤åˆ¶å称到剪贴æ¿"
-
msgid "Copy reference to clipboard"
-msgstr "将索引å¤åˆ¶åˆ°å‰ªè´´æ¿"
+msgstr "将标识å¤åˆ¶åˆ°å‰ªè´´æ¿"
msgid "Copy secret to clipboard"
msgstr "å¤åˆ¶å¯†ç åˆ°å‰ªè´´æ¿"
@@ -2366,6 +2740,9 @@ msgstr "创建"
msgid "Create New Directory"
msgstr "创建新目录"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr "创建一个新分支"
@@ -2375,6 +2752,9 @@ msgstr "创建一个新的分支åŠåˆå¹¶è¯·æ±‚"
msgid "Create a new issue"
msgstr "创建新议题"
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "在å¸æˆ·ä¸Šåˆ›å»ºä¸ªäººè®¿é—®ä»¤ç‰Œï¼Œä»¥é€šè¿‡ %{protocol} æ¥æ‹‰å–或推é€ã€‚"
@@ -2414,6 +2794,9 @@ msgstr "创建åˆå¹¶è¯·æ±‚"
msgid "Create merge request and branch"
msgstr "创建åˆå¹¶è¯·æ±‚åŠåˆ†æ”¯"
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "创建新分支"
@@ -2480,9 +2863,6 @@ msgstr "用户资料"
msgid "CurrentUser|Settings"
msgstr "设置"
-msgid "Custom"
-msgstr "自定义"
-
msgid "Custom CI config path"
msgstr "自定义CIé…置路径"
@@ -2498,6 +2878,9 @@ msgstr "自定义通知级别继承自å‚与级别。使用自定义通知级别
msgid "Custom project templates"
msgstr "自定义项目模æ¿"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr "自定义颜色"
@@ -2507,6 +2890,12 @@ msgstr "自定义如何将FogBugz电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å导入GitLab。ä¸
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "自定义如何将Google Code电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å导入GitLab。下一步将选择è¦å¯¼å…¥çš„项目。"
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr "自定义æµæ°´çº¿é…置,查看æµæ°´çº¿çŠ¶æ€å’Œè¦†ç›–率报告。"
@@ -2537,8 +2926,11 @@ msgstr "预å‘布"
msgid "CycleAnalyticsStage|Test"
msgstr "测试"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
-msgstr "仪表盘"
+msgstr "仪表æ¿"
msgid "DashboardProjects|All"
msgstr "所有"
@@ -2546,6 +2938,9 @@ msgstr "所有"
msgid "DashboardProjects|Personal"
msgstr "个人"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr "日期选择器"
@@ -2553,10 +2948,13 @@ msgid "Debug"
msgstr "调试"
msgid "Dec"
-msgstr "å二"
+msgstr "12月"
msgid "December"
-msgstr "å二月"
+msgstr "12月"
+
+msgid "Decline"
+msgstr ""
msgid "Decline and sign out"
msgstr "æ‹’ç»å¹¶é€€å‡º"
@@ -2567,6 +2965,12 @@ msgstr "默认分支"
msgid "Default classification label"
msgstr "默认分类标记"
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr "默认:直接导入Google Code电å­é‚®ä»¶åœ°å€æˆ–用户å"
@@ -2576,6 +2980,9 @@ msgstr "默认:将FogBugzå¸æˆ·ID映射为全å"
msgid "Define a custom pattern with cron syntax"
msgstr "使用 Cron 语法定义自定义模å¼"
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr "您确定è¦ç«‹å³è¿è¡Œ %{jobName} å—?å¦åˆ™çš„è¯ï¼Œè¯¥ä½œä¸šå°†åœ¨è®¡æ—¶ç»“æŸåŽè‡ªåŠ¨è¿è¡Œã€‚"
@@ -2606,6 +3013,12 @@ msgstr "删除评论"
msgid "Delete list"
msgstr "删除列表"
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr "已删除"
@@ -2719,7 +3132,7 @@ msgid "DeployTokens|This action cannot be undone."
msgstr "æ­¤æ“作无法撤消。"
msgid "DeployTokens|This project has no active Deploy Tokens."
-msgstr "该项目没有å¯ç”¨çš„部署令牌。"
+msgstr "该项目无å¯ç”¨çš„部署令牌。"
msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
msgstr "此令牌和密ç ä½œç”¨ä¸€æ ·ã€‚当å‰çª—å£å…³é—­åŽå°†æ— æ³•å†æ¬¡æŸ¥çœ‹ä»¤ç‰Œå†…容,请立å³å¦¥å–„ä¿å­˜ã€‚"
@@ -2739,6 +3152,9 @@ msgstr "新部署令牌"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "新项目部署令牌已创建。"
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr "已部署到"
@@ -2766,6 +3182,9 @@ msgstr "删除"
msgid "Details"
msgstr "详情"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr "检测主机密钥"
@@ -2776,7 +3195,7 @@ msgid "Diff limits"
msgstr "差异é™åˆ¶"
msgid "Diffs|No file name available"
-msgstr "没有å¯ç”¨çš„文件å"
+msgstr "æ— å¯ç”¨çš„文件å"
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "获å–差异线时å‘生错误。"
@@ -2796,6 +3215,12 @@ msgstr "在此项目中ç¦ç”¨"
msgid "Disable group Runners"
msgstr "ç¦ç”¨ç¾¤ç»„Runner"
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr "放弃"
@@ -2817,15 +3242,24 @@ msgstr "å–消"
msgid "Discard review"
msgstr "放弃评审"
-msgid "Discover GitLab Geo."
-msgstr "å‘现GitLab Geo。"
+msgid "Discover GitLab Geo"
+msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "æµè§ˆé¡¹ç›®ï¼Œç¾¤ç»„和代ç ç‰‡æ®µã€‚与他人分享您的项目"
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr "忽略"
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "关闭循环分æžä»‹ç»æ¡†"
@@ -2833,7 +3267,7 @@ msgid "Dismiss Merge Request promotion"
msgstr "关闭åˆå¹¶è¯·æ±‚推广"
msgid "Dismiss trial promotion"
-msgstr ""
+msgstr "关闭试用推è"
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "您想自定义如何将Google Code电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å导入GitLabå—?"
@@ -2853,6 +3287,12 @@ msgstr "完æˆ"
msgid "Download"
msgstr "下载"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "下载 tar"
@@ -2877,6 +3317,9 @@ msgstr "差异文件"
msgid "DownloadSource|Download"
msgstr "下载"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr "踩"
@@ -2892,9 +3335,15 @@ msgstr "æ¯ä¸ªRunnerå¯ä»¥å¤„于以下状æ€ä¸­çš„其中一ç§ï¼š"
msgid "Edit"
msgstr "编辑"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr "编辑标签"
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "编辑 %{id} æµæ°´çº¿è®¡åˆ’"
@@ -2904,6 +3353,12 @@ msgstr "编辑代ç ç‰‡æ®µ"
msgid "Edit application"
msgstr "编辑应用"
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr "在编辑器中编辑文件并在这里​​æ交å˜æ›´å†…容"
@@ -2913,11 +3368,14 @@ msgstr "编辑群组:%{group_name}"
msgid "Edit identity for %{user_name}"
msgstr "编辑 %{user_name} 的身份信æ¯"
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr "Elasticsearch"
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
+msgstr "Elasticsearch集æˆåŠElasticsearch AWS IAM。"
msgid "Email"
msgstr "电å­é‚®ä»¶"
@@ -2931,6 +3389,9 @@ msgstr "电å­é‚®ä»¶"
msgid "Embed"
msgstr "嵌入"
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr "å¯ç”¨"
@@ -2955,6 +3416,9 @@ msgstr "å¯ç”¨å¹¶é…ç½®Prometheus指标。"
msgid "Enable classification control using an external service"
msgstr "使用外部æœåŠ¡å¯ç”¨åˆ†ç±»æŽ§åˆ¶"
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr "在此项目中å¯ç”¨"
@@ -2970,9 +3434,18 @@ msgstr "å¯ç”¨æˆ–ç¦ç”¨ç‰ˆæœ¬æ£€æŸ¥åŠä½¿ç”¨æƒ…况检测(usage ping)。"
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "å¯ç”¨reCAPTCHA或Akismet并设置IPé™åˆ¶ã€‚"
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr "对指定群组å¯ç”¨æ€§èƒ½æ ã€‚"
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)"
@@ -2985,6 +3458,12 @@ msgstr "å·²å¯ç”¨"
msgid "Ends at (UTC)"
msgstr "结æŸäºŽ(UTC)"
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "输入您的BitbucketæœåŠ¡å™¨URL和个人访问令牌"
@@ -3000,9 +3479,27 @@ msgstr "输入åˆå¹¶è¯·æ±‚说明"
msgid "Enter the merge request title"
msgstr "输入åˆå¹¶è¯·æ±‚标题"
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr "环境"
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "获å–环境时å‘生错误。"
@@ -3078,8 +3575,11 @@ msgstr "终止"
msgid "Environments|Stop environment"
msgstr "终止环境"
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
-msgstr "已更新"
+msgstr "更新于"
msgid "Environments|You don't have any environments right now"
msgstr "当å‰æœªè®¾ç½®çŽ¯å¢ƒ"
@@ -3090,9 +3590,6 @@ msgstr "å—ä¿æŠ¤çš„"
msgid "Epic"
msgstr "å²è¯—故事"
-msgid "Epic will be removed! Are you sure?"
-msgstr "å²è¯—故事将被删除! 是å¦ç¡®å®šï¼Ÿ"
-
msgid "Epics"
msgstr "å²è¯—故事"
@@ -3102,8 +3599,8 @@ msgstr "å²è¯—故事路线图"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "利用å²è¯—故事(Epics),产å“线管ç†ä¼šå˜å¾—æ›´è½»æ¾ä¸”更高效"
-msgid "Epics|An error occurred while saving %{epicDateType} date"
-msgstr "ä¿å­˜ %{epicDateType} 日期时å‘生错误"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
msgid "Epics|How can I solve this?"
msgstr "我该如何解决该问题?"
@@ -3129,9 +3626,15 @@ msgstr "错误"
msgid "Error Reporting and Logging"
msgstr "错误报告和日志记录"
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr "创建å²è¯—故事时出错"
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr "获å–贡献者数æ®æ—¶å‡ºé”™ã€‚"
@@ -3174,9 +3677,15 @@ msgstr "加载模æ¿æ—¶å‡ºé”™ã€‚"
msgid "Error occurred when toggling the notification subscription"
msgstr "切æ¢é€šçŸ¥è®¢é˜…æ—¶å‘生错误"
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr "ä¿å­˜æ ‡è®°æ›´æ–°æ—¶å‡ºé”™ã€‚"
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr "更新所有待办事项的状æ€æ—¶å‡ºé”™ã€‚"
@@ -3186,6 +3695,12 @@ msgstr "更新待办事项状æ€æ—¶å‡ºé”™ã€‚"
msgid "Error while loading the merge request. Please try again."
msgstr "加载åˆå¹¶è¯·æ±‚时出错。请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr "预计"
@@ -3207,6 +3722,12 @@ msgstr "åªæ˜¾ç¤ºæŽ¨é€äº‹ä»¶"
msgid "EventFilterBy|Filter by team"
msgstr "åªæ˜¾ç¤ºå›¢é˜Ÿäº‹ä»¶"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "æ¯æ—¥æ‰§è¡Œï¼ˆå‡Œæ™¨ 4 点)"
@@ -3216,9 +3737,39 @@ msgstr "æ¯æœˆæ‰§è¡Œï¼ˆæ¯æœˆ 1 日凌晨 4 点)"
msgid "Every week (Sundays at 4:00am)"
msgstr "æ¯å‘¨æ‰§è¡Œï¼ˆå‘¨æ—¥å‡Œæ™¨ 4 点)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr "人人皆å¯è´¡çŒ®"
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr "展开"
@@ -3231,6 +3782,12 @@ msgstr "展开侧边æ "
msgid "Expiration date"
msgstr "到期时间"
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr "请解释此问题。如适用,å¯æ供相关议题或评论的链接。"
@@ -3250,11 +3807,23 @@ msgid "Explore projects"
msgstr "æµè§ˆé¡¹ç›®"
msgid "Explore public groups"
-msgstr "æœç´¢å…¬å…±ç¾¤ç»„"
+msgstr "æœç´¢å…¬å¼€ç¾¤ç»„"
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
msgid "External Classification Policy Authorization"
msgstr "外部分类政策授æƒ"
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr "外部身份验è¯"
@@ -3294,6 +3863,9 @@ msgstr "无法部署到"
msgid "Failed to load emoji list."
msgstr "无法加载表情列表。"
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "无法从看æ¿ç§»é™¤è®®é¢˜ï¼Œè¯·é‡è¯•ã€‚"
@@ -3303,30 +3875,42 @@ msgstr "删除镜åƒå¤±è´¥ã€‚"
msgid "Failed to remove the pipeline schedule"
msgstr "无法删除æµæ°´çº¿è®¡åˆ’"
-msgid "Failed to signing using smartcard authentication"
+msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr "无法使用智能å¡èº«ä»½éªŒè¯è¿›è¡Œç™»å½•"
+
msgid "Failed to update issues, please try again."
msgstr "更新议题失败, 请é‡è¯•"
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr "失败"
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "速度更快,因其é‡ç”¨äº†é¡¹ç›®çš„工作空间(如果它ä¸å­˜åœ¨ï¼Œå°†å›žé€€åˆ°å…‹éš†ï¼‰"
msgid "Feature Flags"
msgstr "功能标志"
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
msgid "FeatureFlags|API URL"
msgstr "API URL"
msgid "FeatureFlags|Active"
msgstr "å·²å¯ç”¨"
-msgid "FeatureFlags|Application name"
-msgstr "应用å称"
-
msgid "FeatureFlags|Configure"
msgstr "é…ç½®"
@@ -3336,8 +3920,11 @@ msgstr "é…置功能标志"
msgid "FeatureFlags|Create feature flag"
msgstr "创建功能标志"
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
-msgstr "删除 %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
msgid "FeatureFlags|Description"
msgstr "æè¿°"
@@ -3348,30 +3935,48 @@ msgstr "编辑 %{feature_flag_name}"
msgid "FeatureFlags|Edit Feature Flag"
msgstr "编辑功能标志"
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr "功能标志"
-msgid "FeatureFlags|Feature flag"
-msgstr "功能标志"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
-msgstr "功能标志 %{feature_flag_name} å³å°†è¢«åˆ é™¤ã€‚确定继续å—?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
-msgstr "功能标志å…许您通过动æ€å¼€å…³æŸäº›åŠŸèƒ½å°†ä»£ç é…置为ä¸åŒçš„特性组åˆã€‚"
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
-msgstr "功能标志入门"
+msgid "FeatureFlags|Get started with Feature Flags"
+msgstr ""
msgid "FeatureFlags|Inactive"
msgstr "未å¯ç”¨"
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr "安装 %{docs_link_start}兼容的客户端库%{docs_link_end} ,并在é…置指定API URLã€åº”用å称和实例ID。"
msgid "FeatureFlags|Instance ID"
msgstr "实例ID"
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr "更多信æ¯"
@@ -3390,24 +3995,58 @@ msgstr "ä¿å­˜æ›´æ”¹"
msgid "FeatureFlags|Status"
msgstr "状æ€"
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
-msgstr "二"
+msgstr "2月"
msgid "February"
-msgstr "二月"
+msgstr "2月"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "当å‰é¡µé¢ä¸Šçš„字段ä¸å¯ç¼–辑,å¯ä»¥é…ç½®"
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr "文件模æ¿"
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "文件"
-msgid "Files (%{human_size})"
-msgstr "文件(%{human_size})"
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "填写下é¢çš„字段,å¯ç”¨<strong>%{enable_label}</strong>,然åŽç‚¹å‡»<strong>%{save_changes}</strong>"
@@ -3423,12 +4062,30 @@ msgstr "过滤器%{issuable_type}当å‰å¼€å¯ã€‚"
msgid "Filter by commit message"
msgstr "按æ交消æ¯è¿‡æ»¤"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr "过滤..."
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "按路径查找"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "查找文件"
@@ -3441,12 +4098,18 @@ msgstr "查找新æå–çš„ <code>Takeout/Google Code项目托管/GoogleCodeProje
msgid "Fingerprints"
msgstr "指纹"
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr "完æˆè¯„审"
msgid "Finished"
msgstr "已完æˆ"
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "首次推é€"
@@ -3492,6 +4155,9 @@ msgstr "页脚消æ¯"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "对于内部项目,任何已登录的用户都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和工件)"
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr "如需了解详细信æ¯ï¼Œè¯·å‚阅"
@@ -3505,7 +4171,7 @@ msgid "For private projects, any member (guest or higher) can view pipelines and
msgstr "对于ç§æœ‰é¡¹ç›®ï¼Œä»»ä½•æˆå‘˜ï¼ˆè®¿å®¢æˆ–更高级别)都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和工件)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "对于公共项目,任何人都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和工件)"
+msgstr "对于公开项目,任何人都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和工件)"
msgid "ForkedFromProjectPath|Forked from"
msgstr "派生自"
@@ -3516,6 +4182,9 @@ msgstr "派生自 %{project_name} (已删除)"
msgid "Forking in progress"
msgstr "派生(Fork)中"
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "æ ¼å¼"
@@ -3523,7 +4192,7 @@ msgid "Found errors in your .gitlab-ci.yml:"
msgstr "在.gitlab-ci.yml中å‘现错误:"
msgid "Free Trial of GitLab.com Gold"
-msgstr ""
+msgstr "å…费试用gitlab.comçš„Gold计划"
msgid "From %{provider_title}"
msgstr "æ¥è‡ª %{provider_title}"
@@ -3567,6 +4236,9 @@ msgstr "一般æµæ°´çº¿"
msgid "Generate a default set of labels"
msgstr "生æˆä¸€ç»„默认的标记"
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr "Geo"
@@ -3657,8 +4329,11 @@ msgstr "未校验"
msgid "GeoNodes|Out of sync"
msgstr "ä¸åŒæ­¥"
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
-msgstr "删除节点会åœæ­¢åŒæ­¥ã€‚确定继续?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
msgid "GeoNodes|Replication slot WAL"
msgstr "å¤åˆ¶æ§½ WAL"
@@ -3732,6 +4407,9 @@ msgstr "已计算与主节点对应项验è¯æ ¡éªŒå’Œçš„Wiki"
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr "已与主节点上对应项验è¯çš„Wiki"
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr "当å‰Geo节点é…置使用ä¸å®‰å…¨çš„HTTP连接, 建议使用HTTPS。"
@@ -3777,6 +4455,9 @@ msgstr "需åŒæ­¥çš„群组"
msgid "Geo|In sync"
msgstr "å·²åŒæ­¥"
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr "最近一次æˆåŠŸçš„åŒæ­¥"
@@ -3813,6 +4494,9 @@ msgstr "指定群组中的项目"
msgid "Geo|Projects in certain storage shards"
msgstr "特定存储片中的项目"
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr "é‡æ–°æ£€æŸ¥"
@@ -3871,29 +4555,38 @@ msgid "Geo|Waiting for scheduler"
msgstr "等待调度"
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
+msgstr "当å‰æ­£åœ¨è®¿é—®Geoæ¬¡è¦ <b>åªè¯» </b>节点。如需进行任何写入æ“作,必须访问%{primary_node}。"
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
-msgstr ""
+msgstr "当å‰æ­£åœ¨è®¿é—®Geoæ¬¡è¦ <b>åªè¯» </b>节点。您å¯ä»¥åœ¨æ­¤é¡µé¢ä¸Šè¿›è¡Œæœ‰é™çš„更改或执行有é™çš„æ“作。"
msgid "Geo|You need a different license to use Geo replication"
msgstr "您需è¦ä¸åŒçš„许å¯è¯æ‰èƒ½ä½¿ç”¨ geo å¤åˆ¶"
msgid "Geo|misconfigured"
-msgstr ""
+msgstr "é…置错误"
msgid "Geo|primary"
-msgstr ""
+msgstr "主è¦èŠ‚点"
msgid "Geo|secondary"
-msgstr ""
+msgstr "次è¦èŠ‚点"
msgid "Get a free instance review"
msgstr "获得å…费的实例评估"
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr "Git"
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr "Git仓库URL"
@@ -3921,9 +4614,15 @@ msgstr "Gitlab群组Runnerå¯ä»¥ç”¨æ¥è¿è¡Œç¾¤ç»„内所有项目的代ç ã€‚"
msgid "GitLab Import"
msgstr "GitLab导入"
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr "GitLab用户"
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr "GitLab项目导出"
@@ -3954,6 +4653,9 @@ msgstr "Gitea 主机地å€"
msgid "Gitea Import"
msgstr "从Gitea导入"
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr "返回"
@@ -3973,13 +4675,16 @@ msgid "Google Takeout"
msgstr "Google Takeout"
msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
-msgstr "Google 身份验è¯ä¸æ˜¯%{link_to_documentation}。如果您想使用此æœåŠ¡ï¼Œè¯·å’¨è¯¢æ‚¨çš„ GitLab 管ç†å‘˜ã€‚"
+msgstr "Google身份验è¯æœª%{link_to_documentation}。如需使用此æœåŠ¡ï¼Œè¯·å’¨è¯¢GitLab管ç†å‘˜ã€‚"
msgid "Got it!"
msgstr "了解ï¼"
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
-msgstr "分æžå›¾"
+msgstr "分支图"
msgid "Group"
msgstr "群组"
@@ -3997,7 +4702,7 @@ msgid "Group Runners"
msgstr "群组Runner"
msgid "Group SAML must be enabled to test"
-msgstr ""
+msgstr "å¿…é¡»å¯ç”¨ç¾¤ç»„SAMLæ‰èƒ½è¿›è¡Œæµ‹è¯•"
msgid "Group URL"
msgstr "群组URL"
@@ -4023,41 +4728,32 @@ msgstr "群组维护者å¯ä»¥åœ¨é€šè¿‡ %{link} 注册群组级 Runner"
msgid "Group name"
msgstr "群组å称"
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr "群组:%{group_name}"
msgid "GroupRoadmap|From %{dateWord}"
msgstr "从 %{dateWord} 起"
-msgid "GroupRoadmap|Loading roadmap"
-msgstr "载入路线图中"
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
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 "路线图显示了å²è¯—故事沿ç€æ—¶é—´çº¿çš„进展情况"
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "如需查看路线图,请将开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在月视图中,åªæ˜¾ç¤ºä¸Šä¸ªæœˆï¼Œæœ¬æœˆä»¥åŠæŽ¥ä¸‹æ¥5个月的å²è¯—故事&ndash; 从 %{startDate} 至 %{endDate}."
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "如需查看路线图,请将开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在季度视图中,åªæ˜¾ç¤ºä¸Šä¸ªå­£åº¦ï¼Œæœ¬å­£åº¦ä»¥åŠæŽ¥ä¸‹æ¥4个季度的å²è¯—故事&ndash; 从 %{startDate} 至 %{endDate}."
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "如需查看路线图,请将开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在周视图中,åªæ˜¾ç¤ºä¸Šå‘¨ï¼Œæœ¬å‘¨ä»¥åŠæŽ¥ä¸‹æ¥å››å‘¨çš„å²è¯—故事&ndash; 从 %{startDate} 至 %{endDate}."
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除过滤器。在月视图中,åªæ˜¾ç¤ºä¸Šæœˆï¼Œæœ¬æœˆå’ŒæŽ¥ä¸‹æ¥çš„四个月的å²è¯—故事 &ndash; 从 %{startDate} 到 %{endDate} 。"
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除过滤器。在季度视图中,åªæ˜¾ç¤ºä¸Šä¸ªå­£åº¦ï¼Œæœ¬å­£åº¦å’ŒæŽ¥ä¸‹æ¥çš„四个季度的å²è¯—故事 &ndash; 从 %{startDate} 到 %{endDate} 。"
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除过滤器。在周视图中,åªæ˜¾ç¤ºä¸Šå‘¨ï¼Œæœ¬å‘¨å’ŒæŽ¥ä¸‹æ¥çš„四周的å²è¯—故事 &ndash; 从 %{startDate} 到 %{endDate} 。"
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
msgid "GroupRoadmap|Until %{dateWord}"
msgstr "直到 %{dateWord}"
@@ -4065,15 +4761,24 @@ msgstr "直到 %{dateWord}"
msgid "GroupSettings|Badges"
msgstr "徽章"
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
msgid "GroupSettings|Customize your group badges."
msgstr "自定义群组徽章。"
msgid "GroupSettings|Learn more about badges."
msgstr "了解有关徽章的更多信æ¯ã€‚"
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "ç¦æ­¢ä¸Žå…¶ä»–群组共享 %{group} 中的项目"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "此设置已ç»åº”用于 %{ancestor_group},并已覆盖此å­ç»„的设置。"
@@ -4098,6 +4803,9 @@ msgstr "群组"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "也å¯ä»¥é€šè¿‡åˆ›å»º %{subgroup_docs_link_start}å­ç¾¤ç»„æ¥åµŒå¥—群组%{subgroup_docs_link_end}。"
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr "ç»å¸¸è®¿é—®çš„群组"
@@ -4114,7 +4822,7 @@ msgid "GroupsDropdown|Something went wrong on our end."
msgstr "å‘生了内部错误."
msgid "GroupsDropdown|Sorry, no groups matched your search"
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰æœç´¢åˆ°ä»»ä½•ç¬¦åˆçš„群组"
+msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆçš„群组"
msgid "GroupsDropdown|This feature requires browser localStorage support"
msgstr "此功能需è¦æµè§ˆå™¨æœ¬åœ°å­˜å‚¨æ”¯æŒ"
@@ -4180,7 +4888,7 @@ msgid "HealthCheck|Healthy"
msgstr "å¥åº·"
msgid "HealthCheck|No Health Problems Detected"
-msgstr "没有检测到è¿è¡ŒçŠ¶å†µé—®é¢˜"
+msgstr "未检测到è¿è¡ŒçŠ¶å†µé—®é¢˜"
msgid "HealthCheck|Unhealthy"
msgstr "éžå¥åº·"
@@ -4197,18 +4905,21 @@ msgstr "帮助页é¢æ–‡æœ¬å’Œæ”¯æŒé¡µé¢ç½‘å€ã€‚"
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr "以下是需è¦æ·»åŠ åˆ°è¿œç¨‹æœåŠ¡å™¨çš„SSH公钥。有关更多信æ¯ï¼Œè¯·å‚阅文档。"
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
-msgstr "手工输入éšè—热键"
+msgstr "éšè—主机密钥手动输入"
msgid "Hide payload"
-msgstr "éšè—有效数æ®"
+msgstr "éšè—上传数æ®"
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éšè—值"
-msgid "Hide whitespace changes"
-msgstr "éšè—空白å˜æ›´å†…容"
+msgid "Hide values"
+msgstr ""
msgid "History"
msgstr "历å²"
@@ -4216,6 +4927,9 @@ msgstr "历å²"
msgid "Housekeeping successfully started"
msgstr "已开始维护"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr "æˆ‘æŽ¥å— %{terms_link}"
@@ -4273,6 +4987,9 @@ msgstr "身份标识"
msgid "Identity provider single sign on URL"
msgstr "身份验è¯æ供商å•ç‚¹ç™»å½•URL"
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr "如果ç¦ç”¨ï¼Œåˆ™ä¸ä¼šä½¿ç”¨è¿œç¨‹å‰¯æœ¬çš„æ交自动更新分å‰çš„本地分支,以防止本地数æ®ä¸¢å¤±ã€‚如果默认分支 (%{default_branch}) 已分å‰ä¸”无法更新,则镜åƒå°†å¤±è´¥ã€‚其他分å‰çš„分支默默被忽略。"
@@ -4303,9 +5020,15 @@ msgstr "分帧(Onion skin)"
msgid "ImageDiffViewer|Swipe"
msgstr "滑动"
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr "导入"
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr "从Gitea导入项目"
@@ -4324,12 +5047,24 @@ msgstr "导入一个从GitLab导出的项目"
msgid "Import in progress"
msgstr "正在导入"
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr "通过上传manifest文件导入多个仓库"
msgid "Import project"
msgstr "导入项目"
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr "从Bitbucket导入项目"
@@ -4354,6 +5089,9 @@ msgstr "从 GitHub 导入仓库"
msgid "Import repository"
msgstr "导入仓库"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr "用以下方å¼è¿žæŽ¥å‚¨å­˜åº“"
@@ -4369,20 +5107,35 @@ msgstr "使用GitLabä¼ä¸šç‰ˆå…¨å±€æœç´¢å¸¦æ¥çš„增强æœç´¢åŠŸèƒ½"
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr "è¦å¯ç”¨å®žä¾‹çº§åˆ†æžï¼Œè¯·è¦æ±‚管ç†å‘˜å¯ç”¨ %{usage_ping_link_start}使用情况检测(usage ping)%{usage_ping_link_end}。"
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "继续下一步,选择想è¦å¯¼å…¥çš„项目"
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "包括所有用户必须接å—çš„æœåŠ¡æ¡æ¬¾å议和éšç§æ”¿ç­–。"
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr "如果需è¦ï¼Œè¯·åœ¨URL中包å«ç”¨æˆ·å: <code>https://username@gitlab.company.com/group/project.git</code>。"
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr "ä¸å…¼å®¹çš„项目"
msgid "Indicates whether this runner can pick jobs without tags"
-msgstr "指示此runner是å¦å¯ä»¥é€‰æ‹©æ²¡æœ‰æ ‡è®°çš„作业"
+msgstr "指示此runner是å¦å¯ä»¥é€‰æ‹©æ— æ ‡è®°çš„作业"
msgid "Inline"
msgstr "内è”"
@@ -4393,6 +5146,9 @@ msgstr "手动输入主机密钥"
msgid "Input your repository URL"
msgstr "输入您的存储库URL"
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "安装GitLab Runner"
@@ -4421,6 +5177,9 @@ msgstr "集æˆè®¾ç½®"
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "相关人员甚至å¯ä»¥é€šè¿‡æŽ¨é€æ交æ¥ä¸ºé¡¹ç›®ä½œå‡ºè´¡çŒ®ã€‚"
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr "内部 - 任何登录的用户都å¯ä»¥æŸ¥çœ‹è¯¥ç¾¤ç»„和任何内部项目。"
@@ -4436,9 +5195,27 @@ msgstr "循环周期"
msgid "Introducing Cycle Analytics"
msgstr "周期分æžç®€ä»‹"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr "邀请"
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr "议题"
@@ -4457,6 +5234,21 @@ msgstr "看æ¿"
msgid "IssueBoards|Boards"
msgstr "看æ¿"
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr "议题"
@@ -4482,14 +5274,20 @@ msgid "IssuesAnalytics|Last 12 months"
msgstr "最近12个月"
msgid "IssuesAnalytics|Sorry, your filter produced no results"
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆè¿‡æ»¤å™¨çš„任何结果"
+msgstr "对ä¸èµ·ï¼Œæ— ç¬¦åˆè¿‡æ»¤å™¨çš„结果"
msgid "IssuesAnalytics|There are no issues for the projects in your group"
-msgstr "群组中的项目没有任何议题"
+msgstr "群组中的项目无任何议题"
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤æ¡ä»¶"
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr "Jaeger 地å€"
@@ -4497,10 +5295,10 @@ msgid "Jaeger tracing"
msgstr "Jaeger 跟踪"
msgid "Jan"
-msgstr "一"
+msgstr "1月"
msgid "January"
-msgstr "一月"
+msgstr "1月"
msgid "Job"
msgstr "作业"
@@ -4508,6 +5306,12 @@ msgstr "作业"
msgid "Job has been erased"
msgstr "作业已被删除"
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr "作业"
@@ -4547,23 +5351,26 @@ msgstr "显示完整æº"
msgid "Job|The artifacts were removed"
msgstr "作业产物已被删除"
-msgid "Job|The artifacts will be removed in"
-msgstr "作业产物将被删除于"
+msgid "Job|The artifacts will be removed"
+msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
-msgstr "此作业已åœæ­¢ï¼Œå› ä¸ºæ²¡æœ‰ä»»ä½•åœ¨çº¿çš„runner被分é…给该项目。"
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
msgid "Jul"
-msgstr "七"
+msgstr "7月"
msgid "July"
-msgstr "七月"
+msgstr "7月"
msgid "Jun"
-msgstr "å…­"
+msgstr "6月"
msgid "June"
-msgstr "六月"
+msgstr "6月"
+
+msgid "Key (PEM)"
+msgstr ""
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -4571,6 +5378,9 @@ msgstr "Kubernetes"
msgid "Kubernetes Cluster"
msgstr "Kubernetes集群"
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "Kubernetes集群创建时间超过超时; %{timeout}"
@@ -4647,6 +5457,9 @@ msgstr[0] "最近 %d 天"
msgid "Last Pipeline"
msgstr "最新æµæ°´çº¿"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "最åŽæ交"
@@ -4654,13 +5467,16 @@ msgid "Last contact"
msgstr "最åŽè”ç³»"
msgid "Last edited %{date}"
-msgstr "最åŽä¿®æ”¹ %{date}"
+msgstr "最åŽä¿®æ”¹äºŽ%{date}"
msgid "Last edited by %{name}"
-msgstr "最åŽä¿®æ”¹äºº %{name}"
+msgstr "最åŽä¿®æ”¹æ¥è‡ªäºŽ%{name}"
msgid "Last reply by"
-msgstr "最åŽå›žå¤è€…"
+msgstr "最åŽå›žå¤æ¥è‡ªäºŽ"
+
+msgid "Last seen"
+msgstr ""
msgid "Last update"
msgstr "最åŽæ›´æ–°"
@@ -4677,15 +5493,39 @@ msgstr "于"
msgid "Latest changes"
msgstr "最新更改"
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr "进一步了解"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr "为了了解更多关于 %{issue_boards_url},在多个列表中ä¿æŒå¯¹è®®é¢˜çš„追踪,您å¯ä»¥ä½¿ç”¨ä½¿ç”¨æ ‡è®°ï¼ŒæŒ‡æ´¾äººï¼Œå’Œé‡Œç¨‹ç¢‘。 如果你å‘现议题看æ¿ä¸Šä¸¢å¤±äº†ä¸€äº›ä¿¡æ¯ï¼Œè¯·åœ¨ %{gitlab_issues_url} 创建一个议题。"
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr "进一步了解关于Kubernetesçš„ä¿¡æ¯"
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr "进一步了解ä¿æŠ¤åˆ†æ”¯"
@@ -4771,7 +5611,7 @@ msgid "LicenseManagement|Submit"
msgstr "æ交"
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
-msgstr "此项目目å‰æ²¡æœ‰å·²æ‰¹å‡†æˆ–列入黑åå•çš„许å¯è¯ã€‚"
+msgstr "此项目目å‰æ— å·²æ‰¹å‡†æˆ–列入黑åå•çš„许å¯è¯ã€‚"
msgid "LicenseManagement|This license already exists in this project."
msgstr "此许å¯è¯å·²å­˜åœ¨äºŽå½“å‰é¡¹ç›®ä¸­ã€‚"
@@ -4822,6 +5662,12 @@ msgstr "加载GitLab IDE..."
msgid "Loading..."
msgstr "正在加载..."
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr "é”定"
@@ -4850,7 +5696,7 @@ msgid "Locks give the ability to lock specific file or folder."
msgstr "加é”å¯ä»¥é”定特定的文件或文件夹。"
msgid "Login with smartcard"
-msgstr ""
+msgstr "使用智能å¡ç™»å½•"
msgid "Logs"
msgstr "日志"
@@ -4888,6 +5734,9 @@ msgstr "管ç†æ ‡è®°"
msgid "Manage project labels"
msgstr "管ç†é¡¹ç›®æ ‡è®°"
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr "通过SAML管ç†ç¾¤ç»„æˆå‘˜ï¼Œè¿›ä¸€æ­¥æ高安全性。"
@@ -4910,14 +5759,17 @@ msgid "Map a Google Code user to a full name"
msgstr "å°†Google Code用户映射为全å"
msgid "Mar"
-msgstr "三"
+msgstr "3月"
msgid "March"
-msgstr "三月"
+msgstr "3月"
msgid "Mark todo as done"
msgstr "标记为已完æˆ"
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr "支æŒMarkdownæ ¼å¼"
@@ -4954,9 +5806,6 @@ msgstr "æ’入代ç "
msgid "Maven Metadata"
msgstr "Maven 元数æ®"
-msgid "Maven package"
-msgstr "Maven 包"
-
msgid "Max access level"
msgstr "最高访问级别"
@@ -4964,7 +5813,7 @@ msgid "Maximum job timeout"
msgstr "最大作业超时"
msgid "May"
-msgstr "五"
+msgstr "5月"
msgid "Median"
msgstr "中ä½æ•°"
@@ -4973,29 +5822,41 @@ msgid "Member lock"
msgstr "æˆå‘˜é”"
msgid "Member since %{date}"
-msgstr ""
+msgstr "加入于 %{date}"
msgid "Members"
msgstr "æˆå‘˜"
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "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 "群组在登录您的群组时会跳转到此处。请从您的身份认è¯æ供商处获得该信æ¯ã€‚它å¯èƒ½å«åšâ€œSSOæœåŠ¡ä½ç½®ï¼ˆSSO Service Location)â€ï¼Œâ€œSAML令牌é¢å‘点(SAML Token Issuance Endpoint)â€æˆ–“SAML 2.0/W-Federation URLâ€ã€‚"
msgid "Merge Request"
msgstr "åˆå¹¶è¯·æ±‚"
-msgid "Merge Request:"
-msgstr "åˆå¹¶è¯·æ±‚:"
-
msgid "Merge Requests"
msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge Requests created"
msgstr "创建åˆå¹¶è¯·æ±‚"
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr "åˆå¹¶äº‹ä»¶"
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr "åˆå¹¶è¯·æ±‚"
@@ -5008,20 +5869,32 @@ msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "åˆå¹¶è¯·æ±‚用于æ出对项目的更改与他人讨论"
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr "ä¿å­˜è¯„论è‰ç¨¿æ—¶å‘生错误。"
-msgid "MergeRequests|Discussion stays resolved."
-msgstr "评论ä¿æŒè§£å†³çŠ¶æ€ã€‚"
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
-msgstr "评论ä¿æŒæœªè§£å†³çŠ¶æ€"
+msgid "MergeRequests|Discussion will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved"
+msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
-msgstr "评论将å˜ä¸ºè§£å†³çŠ¶æ€ã€‚"
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
-msgstr "评论将å˜ä¸ºæœªè§£å†³çŠ¶æ€ã€‚"
+msgid "MergeRequests|Reply..."
+msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "在新议题中解决此讨论"
@@ -5030,7 +5903,7 @@ msgid "MergeRequests|Saving the comment failed"
msgstr "ä¿å­˜è¯„论失败"
msgid "MergeRequests|Toggle comments for this file"
-msgstr "切æ¢æ­¤æ–‡ä»¶çš„讨论"
+msgstr "开关此文件的讨论"
msgid "MergeRequests|View file @ %{commitId}"
msgstr "查看文件 @ %{commitId}"
@@ -5038,8 +5911,26 @@ msgstr "查看文件 @ %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "查看已替æ¢æ–‡ä»¶ @ %{commitId}"
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
-msgstr " %{paragraphStart}å°†æ述更改为 %{descriptionChangedTimes} 次 %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr "%{paragraphStart}%{timeDifferenceMinutes}%{descriptionChangedTimes}次更改了æè¿°%{paragraphEnd}"
msgid "MergeRequest|Filter files"
msgstr "过滤文件"
@@ -5047,6 +5938,9 @@ msgstr "过滤文件"
msgid "MergeRequest|No files found"
msgstr "未找到任何文件"
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr "å·²åˆå¹¶"
@@ -5065,8 +5959,8 @@ msgstr "指标 - Prometheus"
msgid "Metrics and profiling"
msgstr "指标和分æž"
-msgid "Metrics|Business"
-msgstr "业务"
+msgid "Metrics for environment"
+msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "查看有关部署到环境的CI/CD文档"
@@ -5074,6 +5968,12 @@ msgstr "查看有关部署到环境的CI/CD文档"
msgid "Metrics|Create metric"
msgstr "创建指标"
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr "编辑指标"
@@ -5083,8 +5983,8 @@ msgstr "环境"
msgid "Metrics|For grouping similar metrics"
msgstr "用于分组类似指标"
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
-msgstr "图表纵轴的标签。通常表示绘制å•ä½ã€‚水平轴(X轴)一般表示时间。"
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
msgid "Metrics|Learn about environments"
msgstr "了解环境"
@@ -5095,24 +5995,18 @@ msgstr "图例标签(å¯é€‰ï¼‰"
msgid "Metrics|Must be a valid PromQL query."
msgstr "必须是有效的 PromQL 查询。"
-msgid "Metrics|Name"
-msgstr "å称"
-
msgid "Metrics|New metric"
msgstr "创建指标"
msgid "Metrics|No deployed environments"
-msgstr "应用没有部署到任何环境"
+msgstr "应用未部署到任何环境"
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr "Prometheus查询文档"
-msgid "Metrics|Query"
-msgstr "查询"
-
-msgid "Metrics|Response"
-msgstr "å“应"
-
msgid "Metrics|System"
msgstr "系统"
@@ -5125,12 +6019,12 @@ msgstr "获å–部署信æ¯æ—¶å‡ºé”™ã€‚"
msgid "Metrics|There was an error getting environments information."
msgstr "获å–环境信æ¯æ—¶å‡ºé”™ã€‚"
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
msgid "Metrics|There was an error while retrieving metrics"
msgstr "读å–指标时出错"
-msgid "Metrics|Type"
-msgstr "类型"
-
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr "æ¥è‡ªPrometheus终端节点的æ„外部署数æ®å“应"
@@ -5149,21 +6043,12 @@ msgstr "用于查询返回å•ä¸ªç³»åˆ—时。如果返回多个系列,相应的
msgid "Metrics|Y-axis label"
msgstr "Y轴标签"
-msgid "Metrics|e.g. HTTP requests"
-msgstr "例如:HTTP 请求"
-
-msgid "Metrics|e.g. Requests/second"
-msgstr "例如:次请求/秒"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr "例如:åžåé‡"
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr "例如:速率(5分钟内所有http请求)"
-
-msgid "Metrics|e.g. req/sec"
-msgstr "例如:次请求/秒"
-
msgid "Milestone"
msgstr "里程碑"
@@ -5236,6 +6121,18 @@ msgstr "å–消"
msgid "Modal|Close"
msgstr "关闭"
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "监控"
@@ -5270,7 +6167,7 @@ msgid "Multiple issue boards"
msgstr "多é‡è®®é¢˜çœ‹æ¿"
msgid "Name"
-msgstr "姓å"
+msgstr "å称"
msgid "Name new label"
msgstr "命å新标记"
@@ -5282,7 +6179,7 @@ msgid "Name:"
msgstr "å称:"
msgid "Naming, visibility"
-msgstr ""
+msgstr "å称,å¯è§æ€§"
msgid "Nav|Help"
msgstr "帮助"
@@ -5296,6 +6193,9 @@ msgstr "注册/登录"
msgid "Nav|Sign out and sign in with a different account"
msgstr "退出并登录到其他账å·"
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr "网络"
@@ -5308,6 +6208,9 @@ msgstr "新增事项"
msgid "New Application"
msgstr "新建应用"
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr "新建群组"
@@ -5321,6 +6224,12 @@ msgstr[0] "新建议题"
msgid "New Label"
msgstr "新标签"
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "创建æµæ°´çº¿è®¡åˆ’"
@@ -5339,6 +6248,9 @@ msgstr "新分支ä¸å¯ç”¨"
msgid "New directory"
msgstr "新建目录"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr "新建å²è¯—故事"
@@ -5349,7 +6261,7 @@ msgid "New group"
msgstr "新建群组"
msgid "New identity"
-msgstr "新身份标识"
+msgstr "新建身份标识"
msgid "New issue"
msgstr "新建议题"
@@ -5360,6 +6272,9 @@ msgstr "新建标记"
msgid "New merge request"
msgstr "新建åˆå¹¶è¯·æ±‚"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "æ–°æµæ°´çº¿å°†å–消åŒä¸€åˆ†æ”¯ä¸Šè¾ƒæ—§çš„待处ç†æµæ°´çº¿"
@@ -5387,6 +6302,9 @@ msgstr "å¦"
msgid "No Label"
msgstr "无标记"
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr "未指派"
@@ -5396,6 +6314,9 @@ msgstr "未å‘现分支"
msgid "No changes"
msgstr "æ— å˜æ›´å†…容"
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "无法连接到GitalyæœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥ç›¸å…³æ—¥å¿—ï¼"
@@ -5406,31 +6327,43 @@ msgid "No contributions were found"
msgstr "未找到任何贡献者"
msgid "No credit card required."
+msgstr "无需信用å¡ã€‚"
+
+msgid "No details available"
msgstr ""
msgid "No due date"
msgstr "无截止日期"
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr "无预计或已用时间"
msgid "No file chosen"
msgstr "未选定任何文件"
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
-msgstr "没有找到文件。"
+msgstr "未找到文件。"
msgid "No issues for the selected time period."
-msgstr "所选时间段没有议题。"
+msgstr "所选时间段无议题。"
msgid "No labels with such name or description"
msgstr "没有具有此类å称或æ述的标记"
msgid "No license. All rights reserved"
-msgstr "没有许å¯è¯ã€‚ 所有æƒä¿ç•™"
+msgstr "未设定许å¯è¯ã€‚版æƒæ‰€æœ‰ã€‚"
+
+msgid "No matching results"
+msgstr ""
msgid "No merge requests for the selected time period."
-msgstr "所选时间段没有åˆå¹¶è¯·æ±‚。"
+msgstr "所选时间段无åˆå¹¶è¯·æ±‚。"
msgid "No merge requests found"
msgstr "找ä¸åˆ°åˆå¹¶è¯·æ±‚"
@@ -5438,29 +6371,35 @@ msgstr "找ä¸åˆ°åˆå¹¶è¯·æ±‚"
msgid "No messages were logged"
msgstr "未记录任何消æ¯"
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr "没有其他具有此类å称或æ述的标记"
-msgid "No packages stored for this project."
-msgstr "没有为此项目存储的包。"
+msgid "No preview for this file type"
+msgstr ""
msgid "No prioritised labels with such name or description"
-msgstr "没有具有此类å称或æ述的优先标记"
+msgstr "无具有此类å称或æ述的优先标记"
msgid "No public groups"
-msgstr "无公共群组"
+msgstr "无公开群组"
msgid "No pushes for the selected time period."
-msgstr "所选时间段没有推é€ã€‚"
+msgstr "所选时间段无推é€ã€‚"
msgid "No repository"
-msgstr "没有仓库"
+msgstr "无仓库"
msgid "No runners found"
-msgstr "没有å‘现Runner"
+msgstr "未找到Runner"
msgid "No schedules"
-msgstr "没有计划"
+msgstr "无计划"
+
+msgid "No start date"
+msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr "å¦, 请直接导入现有电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å。"
@@ -5471,12 +6410,6 @@ msgstr "节点"
msgid "None"
msgstr "æ— "
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr "并éžæ‰€æœ‰æ³¨é‡Šéƒ½ä¼šæ˜¾ç¤ºï¼Œå› ä¸ºæ‚¨æ­£åœ¨æ¯”较两个版本的差异。"
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr "并éžæ‰€æœ‰æ³¨é‡Šéƒ½æ˜¾ç¤ºï¼Œå› ä¸ºæ‚¨æ­£åœ¨æŸ¥çœ‹æ—§ç‰ˆæœ¬çš„差异。"
-
msgid "Not allowed to merge"
msgstr "ä¸å…许åˆå¹¶"
@@ -5501,6 +6434,9 @@ msgstr "æš‚ä¸"
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "请注æ„,master分支自动å—ä¿æŠ¤ã€‚%{link_to_protected_branches}"
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "æ示:作为GitLab管ç†å‘˜ï¼Œå¯ä»¥é…ç½® %{github_integration_link},这将å…许通过GitHub登录并å…许连接Github代ç ä»“库而ä¸éœ€è¦ä¸ªäººè®¿é—®ä»¤ç‰Œã€‚"
@@ -5517,7 +6453,7 @@ msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "确定è¦å–消此评论å—?"
msgid "Notes|Collapse replies"
-msgstr "折å å›žå¤"
+msgstr "收起回å¤"
msgid "Notes|Show all activity"
msgstr "显示所有活动"
@@ -5531,6 +6467,12 @@ msgstr "仅显示历å²è®°å½•"
msgid "Notification events"
msgstr "通知事件"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "关闭议题"
@@ -5604,10 +6546,10 @@ msgid "OK"
msgstr "确定"
msgid "Oct"
-msgstr "å"
+msgstr "10月"
msgid "October"
-msgstr "å月"
+msgstr "10月"
msgid "OfSearchInADropdown|Filter"
msgstr "过滤"
@@ -5617,7 +6559,7 @@ msgstr "仓库导入åŽï¼Œå¯ä»¥é€šè¿‡ SSH 拉å–é•œåƒã€‚了解更多 %{ssh_lin
msgid "One more item"
msgid_plural "%d more items"
-msgstr[0] ""
+msgstr[0] "其余%d项"
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "您的一个或多个Bitbucket项目无法直接导入GitLab,因为它们使用Subversion或Mercurial进行版本控制,而ä¸æ˜¯Git。"
@@ -5628,26 +6570,41 @@ msgstr "您的一个或多个Google Code项目无法直接导入GitLab,因为å
msgid "Only admins"
msgstr "仅管ç†å‘˜"
-msgid "Only comments from the following commit are shown below"
-msgstr "下é¢ä»…显示æ¥è‡ªä»¥ä¸‹æ交的评论"
-
msgid "Only mirror protected branches"
msgstr "åªé•œåƒå—ä¿æŠ¤çš„分支"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
msgid "Only project members can comment."
msgstr "åªæœ‰é¡¹ç›®æˆå‘˜å¯ä»¥å‘表评论。"
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "å•Š~~, 确定å—?"
msgid "Open"
msgstr "展开"
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr "用Xcode打开"
msgid "Open projects"
-msgstr ""
+msgstr "打开项目"
msgid "Open sidebar"
msgstr "打开侧边æ "
@@ -5674,18 +6631,15 @@ msgid "Operations"
msgstr "è¿ç»´"
msgid "Operations Dashboard"
-msgstr ""
-
-msgid "Operations Settings"
-msgstr "æ“作设置"
+msgstr "è¿ç»´ä»ªè¡¨æ¿"
msgid "OperationsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "将项目添加到仪表æ¿"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
-msgstr ""
+msgstr "è¿ç»´ä»ªè¡¨æ¿æä¾›æ¯ä¸ªé¡¹ç›®çš„è¿è¡ŒçŠ¶å†µçš„摘è¦ï¼ŒåŒ…括æµæ°´çº¿å’Œè­¦æŠ¥çŠ¶æ€ã€‚"
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5733,6 +6687,12 @@ msgstr "软件包"
msgid "Pages"
msgstr "Pages"
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "尾页 »"
@@ -5745,12 +6705,27 @@ msgstr "上一页"
msgid "Pagination|« First"
msgstr "« 首页"
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr "包å«äºŽåˆå¹¶è¯·æ±‚å˜æ›´ä¸­"
msgid "Password"
msgstr "密ç "
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "粘贴您的 SSH 公钥,通常包å«åœ¨ '~/.ssh/id_rsa.pub' 文件中,并以 'ssh-rsa' 开头。ä¸è¦ä½¿ç”¨æ‚¨çš„ SSH ç§é’¥ã€‚"
@@ -5772,9 +6747,6 @@ msgstr "等待中"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "未ç»è®¸å¯çš„用户将无法收到通知,也无法评论。"
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr "æ¯ä¸ªä½œä¸šã€‚如果作业超过此阈值,则会将其标记为失败"
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "执行高级选项,例如更改路径,移动或删除群组。"
@@ -5790,6 +6762,12 @@ msgstr "æƒé™ï¼ŒLFS,2FA"
msgid "Personal Access Token"
msgstr "个人访问凭è¯"
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "æµæ°´çº¿"
@@ -5899,10 +6877,10 @@ msgid "Pipelines|Something went wrong while cleaning runners cache."
msgstr "清ç†runner缓存时å‘生错误。"
msgid "Pipelines|There are currently no %{scope} pipelines."
-msgstr "当å‰æ²¡æœ‰ %{scope}çš„æµæ°´çº¿ã€‚"
+msgstr "当å‰æ— %{scope}çš„æµæ°´çº¿ã€‚"
msgid "Pipelines|There are currently no pipelines."
-msgstr "当å‰æ²¡æœ‰æµæ°´çº¿ã€‚"
+msgstr "当å‰æ— æµæ°´çº¿ã€‚"
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "获å–æµæ°´çº¿æ—¶å‡ºçŽ°é”™è¯¯ã€‚请ç¨åŽé‡è¯•æˆ–å°è¯•è”系您的支æŒå›¢é˜Ÿã€‚"
@@ -5920,7 +6898,7 @@ msgid "Pipeline|Create pipeline"
msgstr "创建æµæ°´çº¿"
msgid "Pipeline|Duration"
-msgstr ""
+msgstr "时长"
msgid "Pipeline|Existing branch name or tag"
msgstr "现有分支å称或者标签"
@@ -5976,11 +6954,14 @@ msgstr "PlantUML"
msgid "Play"
msgstr "è¿è¡Œ"
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr "请接å—æœåŠ¡æ¡æ¬¾ä»¥ç»§ç»­ã€‚"
msgid "Please choose a group URL with no special characters."
-msgstr "请选择没有特殊字符的群组URL。"
+msgstr "请选择无特殊字符的群组URL。"
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr "请将它们先%{link_to_git}, 然åŽå†æ¬¡ä½¿ç”¨%{link_to_import_flow}。"
@@ -5988,9 +6969,15 @@ msgstr "请将它们先%{link_to_git}, 然åŽå†æ¬¡ä½¿ç”¨%{link_to_import_flow}ã
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "请将它们先在Google Code中转为Git, 然åŽå†æ¬¡ä½¿ç”¨%{link_to_import_flow}。"
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "请为您的群组填写æ述性å称。"
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "请注æ„,GitLabä¸æ供此应用程åºï¼Œæ‚¨åº”该在å…许访问之å‰éªŒè¯å…¶çœŸå®žæ€§ã€‚"
@@ -6003,6 +6990,9 @@ msgstr "请填写验è¯ç ã€‚"
msgid "Please try again"
msgstr "请å†è¯•ä¸€æ¬¡"
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr "请使用此表å•å‘GitLab报告创建垃圾议题ã€è¯„论或有ä¸å½“行为的用户。"
@@ -6028,7 +7018,7 @@ msgid "Preview"
msgstr "预览"
msgid "Preview payload"
-msgstr "预览有效负载"
+msgstr "预览上传数æ®"
msgid "Primary"
msgstr "主è¦"
@@ -6040,10 +7030,13 @@ msgid "Prioritize label"
msgstr "优先标记"
msgid "Prioritized Labels"
-msgstr "优先的标记"
+msgstr "优先标记"
msgid "Prioritized label"
-msgstr "优先的标记"
+msgstr "优先标记"
+
+msgid "Private"
+msgstr ""
msgid "Private - Project access must be granted explicitly to each user."
msgstr "ç§äºº - å¿…é¡»å‘æ¯ä¸ªç”¨æˆ·æ˜Žç¡®æŽˆäºˆé¡¹ç›®è®¿é—®æƒé™ã€‚"
@@ -6066,9 +7059,18 @@ msgstr "您å³å°†æ°¸ä¹…删除 %{yourAccount},以åŠä¸Žæ‚¨çš„å¸æˆ·å…³è”的所
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 "您将更改用户å %{currentUsernameBold} 为 %{newUsernameBold}。é…置文件和项目将é‡å®šå‘到 %{newUsername} 命å空间,但是一旦 %{currentUsername} 命å空间被å¦ä¸€ä¸ªç”¨æˆ·æˆ–组注册,此é‡å®šå‘将过期。请尽快更新您的远端Git仓库。"
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "å¸æˆ·å·²å®‰æŽ’被删除。"
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr "添加密钥"
@@ -6084,15 +7086,30 @@ msgstr "å³å°†åˆ é™¤å¤´åƒã€‚确定继续å—?"
msgid "Profiles|Change username"
msgstr "更改用户å"
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr "选择文件..."
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
-msgstr "选择在公开个人资料中显示ç§æœ‰é¡¹ç›®çš„贡献,但ä¸æ˜¾ç¤ºä»»ä½•é¡¹ç›®ï¼Œå­˜å‚¨åº“或组织信æ¯ã€‚"
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
msgid "Profiles|Clear status"
msgstr "清除状æ€"
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "当å‰è·¯å¾„: %{path}"
@@ -6111,6 +7128,9 @@ msgstr "删除您的å¸æˆ·?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "删除å¸æˆ·å…·æœ‰ä»¥ä¸‹æ•ˆæžœï¼š"
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr "ä¸åœ¨ä¸ªäººèµ„料中显示"
@@ -6120,6 +7140,12 @@ msgstr "ä¸è¦åœ¨ä¸ªäººèµ„料上显示与活动相关的个人信æ¯"
msgid "Profiles|Edit Profile"
msgstr "编辑个人资料"
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "密ç æ— æ•ˆ"
@@ -6148,7 +7174,7 @@ msgid "Profiles|Private contributions"
msgstr "éžå…¬å¼€è´¡çŒ®"
msgid "Profiles|Public Avatar"
-msgstr "公共头åƒ"
+msgstr "公开头åƒ"
msgid "Profiles|Remove avatar"
msgstr "删除头åƒ"
@@ -6156,11 +7182,14 @@ msgstr "删除头åƒ"
msgid "Profiles|Set new profile picture"
msgstr "设置新个人资料图片"
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr "æŸäº›é€‰é¡¹å¯¹äºŽ LDAP å¸æˆ·ä¸å¯ç”¨"
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
-msgstr "在少于250个字符的情况下介ç»æ‚¨è‡ªå·±ã€‚"
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "å…许的最大文件大å°ä¸º200KB。"
@@ -6168,20 +7197,23 @@ msgstr "å…许的最大文件大å°ä¸º200KB。"
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "这看起æ¥ä¸åƒ SSH 公钥,确定è¦æ·»åŠ å®ƒå—?"
-msgid "Profiles|This email will be displayed on your public profile."
-msgstr "此电å­é‚®ä»¶å°†æ˜¾ç¤ºåœ¨æ‚¨çš„公开个人资料中。"
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
msgstr "此电å­é‚®ä»¶å°†ç”¨äºŽåŸºäºŽWebçš„æ“作,例如编辑和åˆå¹¶ã€‚ %{learn_more}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
-msgstr "这个表情符å·å’Œè¿™æ¡æ¶ˆæ¯ä¼šåœ¨æ‚¨çš„个人资料和整个工作界é¢ä¸­å‡ºçŽ°ã€‚"
+msgstr "此表情符å·å’Œæ¶ˆæ¯ä¼šæ˜¾ç¤ºåœ¨æ‚¨çš„个人资料和界é¢ä¸­ã€‚"
-msgid "Profiles|This feature is experimental and translations are not complete yet."
-msgstr "此功能当åˆå¤„于实验阶段,翻译尚未全部完æˆã€‚"
+msgid "Profiles|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
-msgid "Profiles|This information will appear on your profile."
-msgstr "此信æ¯å°†æ˜¾ç¤ºåœ¨æ‚¨çš„个人资料中。"
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "键入您的 %{confirmationValue} 以确认:"
@@ -6207,12 +7239,15 @@ msgstr "用户å更改失败 - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "用户å更改æˆåŠŸ"
-msgid "Profiles|Website"
-msgstr "网站"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
msgid "Profiles|What's your status?"
msgstr "你当å‰çš„状æ€ï¼Ÿ"
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr "å¯ä»¥åœ¨è¿™é‡Œä¿®æ”¹æ‚¨çš„头åƒ"
@@ -6231,17 +7266,20 @@ msgstr "您无æƒåˆ é™¤æ­¤ç”¨æˆ·ã€‚"
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "您必须转移所有æƒæˆ–删除这些群组,然åŽæ‰èƒ½åˆ é™¤æ‚¨çš„å¸æˆ·ã€‚"
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "您的å¸æˆ·ç›®å‰æ˜¯è¿™äº›ç¾¤ç»„的所有者:"
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
-msgstr "您的邮件地å€æ˜¯æ ¹æ®æ‚¨çš„ %{provider_label} å¸æˆ·è‡ªåŠ¨è®¾ç½®çš„。"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
-msgstr "您的ä½ç½®æ˜¯åŸºäºŽæ‚¨çš„ %{provider_label} å¸æˆ·è‡ªåŠ¨è®¾ç½®çš„。"
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
-msgstr "您的姓å是根æ®æ‚¨çš„ %{provider_label} å¸æˆ·è‡ªåŠ¨è®¾ç½®çš„,因此您认识的人å¯ä»¥è¯†åˆ«æ‚¨ã€‚"
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
msgid "Profiles|Your status"
msgstr "你的状æ€"
@@ -6249,6 +7287,12 @@ msgstr "你的状æ€"
msgid "Profiles|e.g. My MacBook key"
msgstr "例如: My MacBook Key"
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "您的å¸æˆ·"
@@ -6306,12 +7350,18 @@ msgstr "项目导出链接已过期。请从项目设置中é‡æ–°ç”Ÿæˆé¡¹ç›®å¯¼
msgid "Project export started. A download link will be sent by email."
msgstr "项目导出已开始。下载链接将通过电å­é‚®ä»¶å‘é€ã€‚"
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr "项目å称"
msgid "Project slug"
msgstr "项目标识串"
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "订阅"
@@ -6403,7 +7453,7 @@ msgid "Projects shared with %{group_name}"
msgstr "与 %{group_name} 共享的项目"
msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
+msgstr "属于群组的项目以群组å称为å‰ç¼€ã€‚现有项目å¯ä»¥ç§»åŠ¨åˆ°ä¸€ä¸ªç¾¤ç»„中。"
msgid "ProjectsDropdown|Frequently visited"
msgstr "ç»å¸¸è®¿é—®"
@@ -6421,7 +7471,7 @@ msgid "ProjectsDropdown|Something went wrong on our end."
msgstr "å‘生了内部错误"
msgid "ProjectsDropdown|Sorry, no projects matched your search"
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰æœç´¢åˆ°ç¬¦åˆæ¡ä»¶çš„项目"
+msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ç¬¦åˆæ¡ä»¶çš„项目"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
msgstr "此功能需è¦æµè§ˆå™¨æ”¯æŒæœ¬åœ°å­˜å‚¨"
@@ -6456,9 +7506,6 @@ msgstr "æ“作符"
msgid "PrometheusAlerts|Threshold"
msgstr "阈值"
-msgid "PrometheusDashboard|Time"
-msgstr "时间"
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "找到%{exporters} åŠ %{metrics}"
@@ -6483,6 +7530,9 @@ msgstr "常用指标会根æ®åº”用广泛的导出器指标库自动监控。"
msgid "PrometheusService|Custom metrics"
msgstr "自定义指标"
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "查找和é…置指标..."
@@ -6502,7 +7552,7 @@ msgid "PrometheusService|Metrics"
msgstr "指标"
msgid "PrometheusService|Missing environment variable"
-msgstr "没有环境å˜é‡"
+msgstr "无环境å˜é‡"
msgid "PrometheusService|More information"
msgstr "更多的信æ¯"
@@ -6589,7 +7639,7 @@ msgid "ProtectedEnvironment|Select an environment"
msgstr "选择一个环境"
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr "ç›®å‰æ²¡æœ‰å—ä¿æŠ¤çš„环境,请使用上述表å•ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒã€‚"
+msgstr "ç›®å‰æ— å—ä¿æŠ¤çš„环境,请使用上述表å•ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒã€‚"
msgid "ProtectedEnvironment|Unprotect"
msgstr "å–消ä¿æŠ¤"
@@ -6604,7 +7654,7 @@ msgid "ProtectedEnvironment|Your environment has been unprotected"
msgstr "环境已ç»ä¸è¢«ä¿æŠ¤"
msgid "Protip:"
-msgstr "专家æ示:"
+msgstr "æ示:"
msgid "Provider"
msgstr "æ供者"
@@ -6612,14 +7662,17 @@ msgstr "æ供者"
msgid "Pseudonymizer data collection"
msgstr "匿å化数æ®æ”¶é›†"
+msgid "Public"
+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 "公开 - 无需任何身份验è¯å³å¯è®¿é—®è¯¥é¡¹ç›®ã€‚"
msgid "Public pipelines"
-msgstr "公共æµæ°´çº¿"
+msgstr "公开æµæ°´çº¿"
msgid "Pull"
msgstr "拉å–"
@@ -6651,29 +7704,38 @@ msgstr "推é€"
msgid "Quarters"
msgstr "季度"
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "快速æ“作å¯ç”¨äºŽè®®é¢˜æ述和评论框。"
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "进一步了解"
+msgid "Read more about environments"
+msgstr ""
+
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr "了解有关项目æƒé™çš„æ›´å¤šä¿¡æ¯ <strong>%{link_to_help}</strong>"
-msgid "Readme"
-msgstr "自述文件"
-
msgid "Real-time features"
msgstr "实时功能"
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr "最近的æœç´¢"
msgid "Redirect to SAML provider to test configuration"
-msgstr ""
+msgstr "跳转到SAML供应商以测试é…ç½®"
msgid "Reference:"
-msgstr "引用:"
+msgstr "标识:"
msgid "Refresh"
msgstr "刷新"
@@ -6691,6 +7753,9 @@ msgstr "正则表达å¼"
msgid "Register / Sign In"
msgstr "注册/登录"
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "注册并查看当å‰ç¾¤ç»„çš„Runner。"
@@ -6721,6 +7786,12 @@ msgstr "相关已åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
msgid "Related merge requests"
msgstr "相关åˆå¹¶è¯·æ±‚"
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "ç¨åŽæ醒"
@@ -6730,6 +7801,12 @@ msgstr "删除"
msgid "Remove Runner"
msgstr "移除Runner"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr "删除头åƒ"
@@ -6760,9 +7837,15 @@ msgstr "é‡å‘½å文件夹"
msgid "Reopen epic"
msgstr "é‡æ–°å¼€å¯å²è¯—"
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr "ä¿®å¤è®¤è¯"
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr "直接回å¤æ­¤é‚®ä»¶æˆ– %{view_it_on_gitlab}。"
@@ -6779,7 +7862,7 @@ msgid "Reports|%{failedString} and %{resolvedString}"
msgstr "%{failedString} 和 %{resolvedString}"
msgid "Reports|Actions"
-msgstr ""
+msgstr "æ“作"
msgid "Reports|Class"
msgstr "ç±»"
@@ -6800,19 +7883,19 @@ msgid "Reports|System output"
msgstr "系统输出"
msgid "Reports|Test summary"
-msgstr "测试摘è¦"
+msgstr "测试总结报告"
msgid "Reports|Test summary failed loading results"
-msgstr "测试摘è¦åŠ è½½å¤±è´¥"
+msgstr "测试总结报告加载失败"
msgid "Reports|Test summary results are being parsed"
-msgstr "正在分æžæµ‹è¯•æ‘˜è¦"
+msgstr "测试总结报告解æžä¸­"
msgid "Reports|Vulnerability"
msgstr "æ¼æ´ž"
msgid "Reports|no changed test results"
-msgstr "测试结果没有å˜åŒ–"
+msgstr "未å‘生å˜åŒ–的测试结果"
msgid "Repository"
msgstr "仓库"
@@ -6823,6 +7906,12 @@ msgstr "存储库设置"
msgid "Repository URL"
msgstr "仓库地å€"
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr "当å‰ä»“库无加é”文件。"
@@ -6841,6 +7930,9 @@ msgstr "选择"
msgid "Request Access"
msgstr "申请æƒé™"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr "请求分æž"
@@ -6850,12 +7942,27 @@ msgstr "è¦æ±‚此群组中的所有用户都å¯ç”¨åŒé‡è®¤è¯"
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "è¦æ±‚所有用户在访问GitLab时接å—æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–。"
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr "é‡ç½®è¿è¡ŒçŠ¶å†µæ£€æŸ¥è®¿é—®ä»¤ç‰Œ"
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "é‡ç½® Runner 注册令牌"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr "在新议题中解决所有讨论"
@@ -6865,6 +7972,12 @@ msgstr "在æºåˆ†æ”¯ä¸Šè§£å†³å†²çª"
msgid "Resolve discussion"
msgstr "解决讨论"
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr "å“应指标(AWS ELB)"
@@ -6874,12 +7987,18 @@ msgstr "å“应指标(自定义)"
msgid "Response metrics (HA Proxy)"
msgstr "å“应指标(HA Proxy)"
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr "å“应指标(NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "å“应指标(NGINX)"
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr "æ¢å¤"
@@ -6892,13 +8011,13 @@ msgstr "é‡è¯•å½“å‰ä½œä¸š"
msgid "Retry verification"
msgstr "é‡è¯•éªŒè¯"
-msgid "Reveal Variables"
-msgstr "显示å˜é‡"
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] "显示值"
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "还原此æ交"
@@ -6926,6 +8045,9 @@ msgstr "路线图"
msgid "Run CI/CD pipelines for external repositories"
msgstr "使用外部仓库的CI/CDæµæ°´çº¿"
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr "è¿è¡Œæœªæ ‡è®°çš„作业"
@@ -6953,6 +8075,9 @@ msgstr "Runner"
msgid "Runners API"
msgstr "Runners API"
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Runnerå¯ä»¥æ”¾åœ¨ä¸åŒçš„用户ã€æœåŠ¡å™¨ï¼Œç”šè‡³æœ¬åœ°æœºå™¨ä¸Šã€‚"
@@ -6963,10 +8088,10 @@ msgid "Runners currently online: %{active_runners_count}"
msgstr "当å‰åœ¨çº¿Runner: %{active_runners_count}"
msgid "Runners page"
-msgstr "è¿è¡Œå™¨é¡µé¢"
+msgstr "Runner页é¢"
msgid "Runners page."
-msgstr "è¿è¡Œå™¨é¡µé¢ã€‚"
+msgstr "Runner页é¢."
msgid "Runners|You have used all your shared Runners pipeline minutes."
msgstr "您已ç»ä½¿ç”¨äº†æ‰€æœ‰å…±äº«Runnerçš„æµæ°´çº¿æ—¶é—´ã€‚"
@@ -6986,8 +8111,8 @@ msgstr "SAML å•ç‚¹ç™»å½•"
msgid "SAML Single Sign On Settings"
msgstr "SAML å•ç‚¹ç™»å½•è®¾ç½®"
-msgid "SAST"
-msgstr "SAST"
+msgid "SAML for %{group_name}"
+msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "SAML令牌签åè¯ä¹¦çš„SHA1指纹。请从身份验è¯æ供商处获å–(也å¯ä»¥è¢«ç§°ä¸ºâ€œæŒ‡çº¹â€ï¼‰ã€‚"
@@ -7007,6 +8132,9 @@ msgstr "SSL验è¯"
msgid "Save"
msgstr "ä¿å­˜"
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr "ä¿å­˜åº”用"
@@ -7016,6 +8144,9 @@ msgstr "ä¿å­˜ä¿®æ”¹"
msgid "Save changes before testing"
msgstr "测试å‰ä¿å­˜æ›´æ”¹"
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "ä¿å­˜æµæ°´çº¿è®¡åˆ’"
@@ -7052,6 +8183,9 @@ msgstr "滚动到顶部"
msgid "Search"
msgstr "æœç´¢"
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr "æœç´¢åˆ†æ”¯"
@@ -7064,6 +8198,9 @@ msgstr "æœç´¢æ–‡ä»¶"
msgid "Search for projects, issues, etc."
msgstr "æœç´¢é¡¹ç›®ã€è®®é¢˜ç­‰ç­‰â€¦"
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr "æœç´¢åˆå¹¶è¯·æ±‚"
@@ -7119,48 +8256,63 @@ msgid "Security"
msgstr "安全"
msgid "Security Dashboard"
-msgstr "安全仪表盘"
+msgstr "安全仪表æ¿"
msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
-msgstr ""
+msgstr "获å–仪表æ¿æ•°æ®æ—¶å‡ºé”™ã€‚请检查您的网络连接,然åŽé‡è¯•ã€‚"
msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
-msgstr ""
+msgstr "获å–æ¼æ´žæ•°é‡æ—¶å‡ºé”™ã€‚请检查您的网络连接,然åŽé‡è¯•ã€‚"
msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
-msgstr ""
+msgstr "获å–æ¼æ´žåˆ—表时出错。请检查您的网络连接,然åŽé‡è¯•ã€‚"
msgid "Security Dashboard|Issue Created"
-msgstr ""
+msgstr "已创建议题"
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
-msgstr ""
+msgstr "创建议题"
msgid "Security Reports|Dismiss vulnerability"
+msgstr "忽略æ¼æ´ž"
+
+msgid "Security Reports|Learn more about setting up your dashboard"
msgstr ""
msgid "Security Reports|More info"
-msgstr ""
+msgstr "更多信æ¯"
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
-msgstr ""
+msgstr "安全仪表æ¿æ–‡æ¡£"
msgid "Security Reports|There was an error creating the issue."
-msgstr ""
+msgstr "创建议题时出错。"
msgid "Security Reports|There was an error dismissing the vulnerability."
-msgstr ""
+msgstr "忽略æ¼æ´žæ—¶å‡ºé”™ã€‚"
msgid "Security Reports|There was an error reverting the dismissal."
-msgstr ""
+msgstr "å–消忽略时出错。"
msgid "Security Reports|There was an error reverting this dismissal."
+msgstr "å–消忽略时出错。"
+
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -7172,6 +8324,12 @@ msgstr "监控代ç ä¸­çš„æ¼æ´ž"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "æµæ°´çº¿ %{pipelineLink} 已触å‘"
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr "选择"
@@ -7199,6 +8357,9 @@ msgstr "选择指派人"
msgid "Select branch/tag"
msgstr "选择分支/标签"
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr "选择项目"
@@ -7232,18 +8393,66 @@ msgstr "选择性åŒæ­¥"
msgid "Send email"
msgstr "å‘é€ç”µå­é‚®ä»¶"
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr "å‘é€çš„使用情况数æ®"
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
-msgstr "ä¹"
+msgstr "9月"
msgid "September"
-msgstr "ä¹æœˆ"
+msgstr "9月"
msgid "Server version"
msgstr "æœåŠ¡å™¨ç‰ˆæœ¬"
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr "æœåŠ¡å°"
@@ -7274,6 +8483,9 @@ msgstr "为Web终端设置最长会è¯æ—¶é—´ã€‚"
msgid "Set notification email for abuse reports."
msgstr "为滥用报告设置通知电å­é‚®ä»¶ã€‚"
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "设定用户登录的æ¡ä»¶ã€‚å¯ç”¨å¼ºåˆ¶åŒé‡è®¤è¯ã€‚"
@@ -7281,7 +8493,7 @@ msgid "Set up CI/CD"
msgstr "é…ç½® CI/CD"
msgid "Set up a %{type} Runner manually"
-msgstr "手动设置%{type}Runner "
+msgstr "手动设置%{type} Runner "
msgid "Set up a specific Runner automatically"
msgstr "自动创建专用Runner"
@@ -7289,6 +8501,9 @@ msgstr "自动创建专用Runner"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "æ ¹æ®%{docsLinkStart}文档%{icon}%{docsLinkEnd}设置断言/属性/声明(email,first_name,last_name)和NameID"
+msgid "Set up new U2F device"
+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 "设置项目以自动推é€å’Œ/或从å¦ä¸€ä¸ªå­˜å‚¨åº“中æå–更改。分支,标签和æ交将自动åŒæ­¥ã€‚"
@@ -7314,10 +8529,10 @@ msgid "SetStatusModal|Set status"
msgstr "设置状æ€"
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
-msgstr ""
+msgstr "对ä¸èµ·ï¼Œæˆ‘们无法设置您的状æ€ã€‚请ç¨åŽå†è¯•ã€‚"
msgid "SetStatusModal|What's your status?"
-msgstr ""
+msgstr "你的状æ€æ˜¯ä»€ä¹ˆï¼Ÿ"
msgid "Settings"
msgstr "设置"
@@ -7332,7 +8547,7 @@ msgid "Shared Runners"
msgstr "共享Runner"
msgid "Shared projects"
-msgstr "已分享项目"
+msgstr "分享项目"
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "通过é‡ç½®æ­¤å‘½å空间的æµæ°´çº¿åˆ†é’Ÿæ•°ï¼Œå½“å‰ä½¿ç”¨çš„分钟数将被归零。"
@@ -7352,12 +8567,12 @@ msgstr "显示相关命令"
msgid "Show complete raw log"
msgstr "显示完整的原始日志"
+msgid "Show file browser"
+msgstr ""
+
msgid "Show latest version"
msgstr "显示最新版本"
-msgid "Show latest version of the diff"
-msgstr "显示最新版本的差异"
-
msgid "Show parent pages"
msgstr "查看上级页é¢"
@@ -7392,12 +8607,21 @@ msgstr "登录"
msgid "Sign in / Register"
msgstr "登录/注册"
-msgid "Sign in to %{group_name}"
-msgstr "登录到 %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
msgid "Sign in with Single Sign-On"
msgstr "使用å•ç‚¹ç™»å½•(SSO)进行登录"
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr "退出"
@@ -7407,6 +8631,9 @@ msgstr "登录é™åˆ¶"
msgid "Sign-up restrictions"
msgstr "注册é™åˆ¶"
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr "大å°"
@@ -7423,14 +8650,23 @@ msgid "Slower but makes sure the project workspace is pristine as it clones the
msgstr "更慢,但能确ä¿é¡¹ç›®å·¥ä½œç©ºé—´ä¸ŽåŽŸå§‹ç‰ˆæœ¬ä¸€è‡´ï¼›å› å…¶å¯¹æ¯ä¸ªä½œä¸šå‡ä»Žå¤´å¼€å§‹å…‹éš†ä»“库"
msgid "Smartcard"
-msgstr ""
+msgstr "智能å¡"
msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr "智能å¡èº«ä»½éªŒè¯å¤±è´¥ï¼šç¼ºå°‘客户端è¯ä¹¦æŠ¥å¤´ã€‚"
+
+msgid "Snippet Contents"
msgstr ""
msgid "Snippets"
msgstr "代ç ç‰‡æ®µ"
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr "出错了,抱歉。"
@@ -7440,6 +8676,9 @@ msgstr "出错了,抱歉。"
msgid "Something went wrong on our end. Please try again!"
msgstr "æœåŠ¡å™¨ç«¯å‡ºçŽ°é—®é¢˜ï¼Œè¯·é‡è¯•ã€‚"
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr "试图改å˜è¿™ä¸ªè®®é¢˜çš„ç§å¯†æ€§æ—¶å‡ºçŽ°é”™è¯¯"
@@ -7449,9 +8688,15 @@ msgstr "è¯•å›¾æ”¹å˜ %{issuableDisplayName} çš„é”定状æ€æ—¶å‡ºé”™äº†"
msgid "Something went wrong when toggling the button"
msgstr "点击按钮时出错"
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "关闭 %{issuable} 时出错。请ç¨åŽé‡è¯•"
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr "åœ¨èŽ·å– %{listType} 列表时出错了"
@@ -7470,6 +8715,9 @@ msgstr "拉å–项目时å‘生错误。"
msgid "Something went wrong while fetching the registry list."
msgstr "拉å–注册表列表时å‘生错误。"
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr "é‡æ–°å¼€å¯ %{issuable} 时出错。请ç¨åŽå†è¯•"
@@ -7477,7 +8725,7 @@ msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "解决当å‰è®¨è®ºæ—¶å‡ºé”™ï¼Œè¯·é‡è¯•ã€‚"
msgid "Something went wrong, unable to add %{project} to dashboard"
-msgstr "将%{project} 添加到仪表盘时出错"
+msgstr "å°†%{project} 添加到仪表æ¿æ—¶å‡ºé”™"
msgid "Something went wrong, unable to get operations projects"
msgstr "获å–æ“作项目时出错"
@@ -7489,14 +8737,20 @@ msgid "Something went wrong. Please try again."
msgstr "出现错误。请é‡è¯•ã€‚"
msgid "Sorry, no epics matched your search"
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰æœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„å²è¯—故事"
+msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„å²è¯—故事"
msgid "Sorry, no projects matched your search"
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰æœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„项目"
+msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„项目"
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
msgid "Sort by"
msgstr "排åº"
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr "访问级别,å‡åºæŽ’列"
@@ -7542,8 +8796,8 @@ msgstr "最ä¸å—欢迎"
msgid "SortOptions|Less weight"
msgstr "é™ä½Žæƒé‡"
-msgid "SortOptions|Milestone"
-msgstr "里程碑"
+msgid "SortOptions|Milestone due date"
+msgstr ""
msgid "SortOptions|Milestone due later"
msgstr "里程碑截止日期"
@@ -7575,6 +8829,9 @@ msgstr "最早创建"
msgid "SortOptions|Oldest joined"
msgstr "最早的加入"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr "最早的登录"
@@ -7587,6 +8844,9 @@ msgstr "人气"
msgid "SortOptions|Priority"
msgstr "优先"
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr "最近登录"
@@ -7614,6 +8874,9 @@ msgstr "æºä»£ç "
msgid "Source is not available"
msgstr "æºä¸å¯ç”¨"
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr "垃圾信æ¯æ—¥å¿—"
@@ -7629,11 +8892,14 @@ msgstr "指定电å­é‚®ä»¶åœ°å€æ­£åˆ™è¡¨è¾¾å¼æ¨¡å¼ä»¥æ ‡è¯†é»˜è®¤å†…部用户
msgid "Specify the following URL during the Runner setup:"
msgstr "在 Runner 设置时指定以下 URL:"
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr "åˆå¹¶æ交"
msgid "Stage"
-msgstr "阶段"
+msgstr "æš‚å­˜"
msgid "Stage & Commit"
msgstr "æš‚å­˜ & æ交"
@@ -7665,6 +8931,12 @@ msgstr "已星标项目的活动"
msgid "Starred projects"
msgstr "已星标项目"
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
@@ -7674,27 +8946,54 @@ msgstr "开始一个评审"
msgid "Start and due date"
msgstr "开始和截止日期"
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr "开始日期"
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "å¯åŠ¨ Runner!"
msgid "Start your trial"
-msgstr ""
+msgstr "开始试用"
msgid "Started"
msgstr "å·²å¯åŠ¨"
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "开始于(UTC)"
msgid "State your message to activate"
-msgstr "输入消æ¯ä»¥æ¿€æ´»"
+msgstr "输入消æ¯ä»¥å¯ç”¨"
msgid "Status"
msgstr "状æ€"
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr "终止环境"
@@ -7710,6 +9009,9 @@ msgstr "å·²åœæ­¢"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr "由于部署正在进行,目å‰æ— æ³•ç»ˆæ­¢æ­¤çŽ¯å¢ƒ"
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr "存储"
@@ -7725,6 +9027,9 @@ msgstr "å­ç»„和项目"
msgid "Submit as spam"
msgstr "垃圾信æ¯ä¸¾æŠ¥"
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr "æ交评审"
@@ -7740,10 +9045,94 @@ msgstr "在群组级别订阅"
msgid "Subscribe at project level"
msgstr "在项目级别订阅"
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr "已订阅"
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7758,8 +9147,11 @@ msgstr "系统钩å­"
msgid "System Info"
msgstr "系统信æ¯"
-msgid "System header and footer:"
-msgstr "系统页头和页尾:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
msgid "System metrics (Custom)"
msgstr "系统指标(自定义)"
@@ -7767,9 +9159,11 @@ msgstr "系统指标(自定义)"
msgid "System metrics (Kubernetes)"
msgstr "系统指标(Kubernetes)"
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] "标签(%{tag_count})"
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "标签"
@@ -7838,7 +9232,7 @@ msgid "TagsPage|Tags give the ability to mark specific points in history as bein
msgstr "使用标签,å¯ä»¥æ ‡è®°æ交历å²ä¸Šçš„特定点为é‡è¦æ交"
msgid "TagsPage|This tag has no release notes."
-msgstr "此标签没有å‘行说明。"
+msgstr "此标签无å‘行说明。"
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "使用git tag命令添加一个:"
@@ -7864,6 +9258,12 @@ msgstr "模æ¿"
msgid "Templates"
msgstr "模æ¿"
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "æœåŠ¡æ¡æ¬¾å议和éšç§æ”¿ç­–"
@@ -7871,7 +9271,7 @@ msgid "Terms of Service and Privacy Policy"
msgstr "æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–"
msgid "Test SAML SSO"
-msgstr ""
+msgstr "测试 SAML SSO"
msgid "Test coverage parsing"
msgstr "测试覆盖率解æž"
@@ -7879,9 +9279,15 @@ msgstr "测试覆盖率解æž"
msgid "Thanks! Don't show me this again"
msgstr "ä¸å†æ˜¾ç¤º"
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr "GitLab 中的高级全局æœç´¢åŠŸèƒ½æ˜¯ä¸€ä¸ªå¼ºå¤§ä¸”节çœæ‚¨çš„时间的æœç´¢æœåŠ¡ã€‚您å¯ä»¥æœç´¢å…¶ä»–团队的代ç ä»¥å¸®åŠ©æ‚¨å®Œå–„自己项目中的代ç ã€‚从而é¿å…创建é‡å¤çš„代ç æˆ–浪费时间。"
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr "Git LFS对象将<strong>ä¸ä¼š</strong>被åŒæ­¥ã€‚"
@@ -7918,6 +9324,9 @@ msgstr "该导入过程将在 %{timeout}åŽè¶…时。对于需è¦é•¿äºŽè¯¥æ—¶é—´æ
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "议题阶段概述了从创建议题到将议题添加到里程碑或议题看æ¿æ‰€èŠ±è´¹çš„时间。创建第一个议题åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„.。"
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr "文件大å°é™åˆ¶ä¸º 200KB。"
@@ -7931,7 +9340,7 @@ msgid "The phase of the development lifecycle."
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 planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "计划阶段概述了从议题添加到日程到推é€é¦–次æ交的时间。当首次推é€æ交åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
@@ -7996,26 +9405,44 @@ msgstr "用户映射是å‚与项目的 FogBugz 用户的电å­é‚®ä»¶åœ°å€å’Œç”¨
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•°æ˜¯ä¸€ä¸ªæ•°åˆ—中最中间的值。例如在 3ã€5ã€9 之间,中ä½æ•°æ˜¯ 5。在 3ã€5ã€7ã€8 之间,中ä½æ•°æ˜¯ (5 + 7)/ 2 = 6。"
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
-msgstr "ç›®å‰è¿˜æ²¡æœ‰å·²å½’档的项目"
+msgstr "当å‰å°šæ— å·²å½’档的项目"
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
msgid "There are no issues to show"
msgstr "当å‰æ— è®®é¢˜"
msgid "There are no labels yet"
-msgstr "ç›®å‰è¿˜æ²¡æœ‰æ ‡ç­¾"
+msgstr "ç›®å‰æ— æ ‡è®°"
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
-msgid "There are no merge requests to show"
-msgstr "当å‰æ— åˆå¹¶è¯·æ±‚"
+msgid "There are no packages yet"
+msgstr ""
msgid "There are no projects shared with this group yet"
-msgstr "还没有与该群组共享的项目"
+msgstr "当å‰å°šæ— åˆ†äº«ç»™è¯¥ç¾¤ç»„的项目"
msgid "There are no staged changes"
-msgstr "没有已暂存的修改"
+msgstr "无已暂存的修改"
msgid "There are no unstaged changes"
-msgstr "没有未暂存的修改"
+msgstr "无未暂存的修改"
msgid "There was an error adding a todo."
msgstr "添加待办事项时出现错误"
@@ -8041,12 +9468,21 @@ msgstr "订阅此标记时出错。"
msgid "There was an error when unsubscribing from this label."
msgstr "å–消订阅此标记时出错。"
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr "他们å¯ä»¥é€šè¿‡ %{link} 进行管ç†ã€‚"
msgid "Third party offers"
msgstr "第三方优惠"
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "æ­¤GitLab实例尚未æ供任何共享Runner。管ç†å‘˜å¯ä»¥åœ¨ç®¡ç†åŒºåŸŸä¸­æ³¨å†Œå…±äº«Runner。"
@@ -8074,15 +9510,18 @@ msgstr "此日期在开始日期之å‰ï¼Œå› æ­¤è¯¥å²è¯—故事ä¸ä¼šå‡ºçŽ°åœ¨è·¯
msgid "This diff is collapsed."
msgstr "此差异已折å ã€‚"
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr "当å‰ç›®å½•"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
msgid "This group"
msgstr "当å‰ç¾¤ç»„"
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr "此群组å…许您使用%{group_name} å•ç‚¹ç™»å½•å¸æˆ·ç™»å½•ã€‚这将会é‡å®šå‘到外部登录页é¢ã€‚"
-
msgid "This group does not provide any group Runners yet."
msgstr "该群组未æ供任何群组Runner。"
@@ -8111,7 +9550,7 @@ msgid "This job depends on upstream jobs that need to succeed in order for this
msgstr "当å‰ä½œä¸šéœ€åœ¨ä¸Šçº§ä½œä¸šæˆåŠŸåŽæ‰å¯è¢«å¯åŠ¨ã€‚"
msgid "This job does not have a trace."
-msgstr "此作业没有输出日志。"
+msgstr "此作业无输出日志。"
msgid "This job has been canceled"
msgstr "此作业已å–消"
@@ -8135,7 +9574,7 @@ msgid "This job is archived. Only the complete pipeline can be retried."
msgstr "这个作业已归档。åªèƒ½é‡è¯•æ•´ä¸ªæµæ°´çº¿ã€‚"
msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "此作业将创建部署到 %{environmentLink} 并将覆盖已有部署%{deploymentLink} 。"
msgid "This job is creating a deployment to %{environmentLink}."
msgstr "这项工作正在创建一个 %{environmentLink}的部署。"
@@ -8143,19 +9582,19 @@ msgstr "这项工作正在创建一个 %{environmentLink}的部署。"
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "作业挂起中,等待进入队列"
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
-msgstr "此作业已åœæ­¢ã€‚因为分é…有如下标签的Runner都ä¸åœ¨çº¿ï¼š"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
-msgstr "此作业已åœæ­¢ã€‚因为没有活动的Runnerå¯ä»¥å¤„ç†æ­¤é¡¹ä½œä¸šã€‚"
+msgid "This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
msgid "This job is the most recent deployment to %{link}."
msgstr "此作业最近部署到 %{link}。"
msgid "This job requires a manual action"
-msgstr "作业需手工æ“作"
+msgstr "作业需手动æ“作"
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8176,6 +9615,15 @@ msgstr "此页é¢ä¸å¯ç”¨ï¼Œæ‚¨æ— æƒè·¨é¡¹ç›®é˜…读相关信æ¯ã€‚"
msgid "This page will be removed in a future release."
msgstr "此页é¢å°†åœ¨å°†æ¥çš„版本中删除。"
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr "当å‰é¡¹ç›®"
@@ -8183,7 +9631,7 @@ msgid "This project does not belong to a group and can therefore not make use of
msgstr "该项目ä¸å±žäºŽä»»ä½•ç¾¤ç»„,因此ä¸èƒ½ä½¿ç”¨ç¾¤ç»„Runner。"
msgid "This project does not have a wiki homepage yet"
-msgstr "该项目还没有wiki主页"
+msgstr "该项目尚无wiki主页"
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr "此项目未å¯ç”¨è´¦å•ã€‚è¦åˆ›å»ºç¾¤é›†ï¼Œè¯· <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">å¯ç”¨è´¦å• <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> 并é‡è¯•ã€‚"
@@ -8203,11 +9651,11 @@ msgstr "此设置将更新用于生æˆç§æœ‰æ交电å­é‚®ä»¶çš„主机å。 %{
msgid "This source diff could not be displayed because it is too large."
msgstr "此代ç å·®å¼‚无法显示,因为它太大了。"
-msgid "This timeout will take precedence when lower than Project-defined timeout"
-msgstr "当低于项目定义的超时时间时,此超时将优先"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
+msgstr ""
msgid "This user has no identities"
-msgstr "该用户没有身份标识"
+msgstr "该用户无身份标识"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr "此用户将æˆä¸ºæ´»åŠ¨æµä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如创建新分支或者推é€æ–°æ交到现有分支。"
@@ -8215,8 +9663,8 @@ msgstr "此用户将æˆä¸ºæ´»åŠ¨æµä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如创建新分
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr "此用户将æˆä¸ºæ´»åŠ¨æµä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如创建新分支或者推é€æ–°æ交到现有分支。在创建或é‡æ–°æŒ‡å®šæ—¶æ‚¨ä»…å¯å°†è‡ªå·±æŒ‡å®šä¸ºé•œåƒç”¨æˆ·ã€‚"
-msgid "This will delete the custom metric, Are you sure?"
-msgstr "æ­¤æ“作将删除自定义指标,确定继续å—?"
+msgid "This will redirect you to an external sign in page."
+msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "这些电å­é‚®ä»¶è‡ªåŠ¨ç”Ÿæˆä¸ºè®®é¢˜(评论生æˆä¸ºç”µå­é‚®ä»¶ä¼šè¯)并在此处列出。"
@@ -8228,13 +9676,13 @@ msgid "Time before an issue starts implementation"
msgstr "开始进行编ç å‰çš„时间"
msgid "Time before enforced"
-msgstr ""
+msgstr "强制å‰æ—¶é—´"
msgid "Time between merge request creation and merge/close"
msgstr "从创建åˆå¹¶è¯·æ±‚到被åˆå¹¶æˆ–关闭的时间"
msgid "Time estimate"
-msgstr ""
+msgstr "预计时间"
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "GitLab等待外部æœåŠ¡çš„å“应时间(秒)。当æœåŠ¡æ²¡æœ‰åŠæ—¶å“应时,访问将被拒ç»ã€‚"
@@ -8406,14 +9854,23 @@ msgstr "æ示:"
msgid "Title"
msgstr "标题"
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr "到GitLab"
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "è¦æ·»åŠ ä¸€ä¸ª SSH 密钥, æ‚¨éœ€è¦ %{generate_link_start} 生æˆä¸€ä¸ª %{link_end} 或使用一个 %{existing_link_start} 现有的 key%{link_end}。"
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>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr "å¯ä»¥ä½¿ç”¨ %{personal_access_token_link} 连接GitHub仓库。当创建个人访问令牌时,需è¦é€‰æ‹© <code>repo</code> 范围,以显示å¯ä¾›è¿žæŽ¥çš„公共和ç§æœ‰çš„仓库列表。"
+msgstr "å¯ä»¥ä½¿ç”¨ %{personal_access_token_link} 连接GitHub仓库。当创建个人访问令牌时,需è¦é€‰æ‹© <code>repo</code> 范围,以显示å¯ä¾›è¿žæŽ¥çš„公开和ç§æœ‰çš„仓库列表。"
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
msgstr "è¦è¿žæŽ¥GitHub存储库,首先需è¦æŽˆæƒGitLab访问列表中的GitHub仓库:"
@@ -8443,7 +9900,7 @@ msgid "To help improve GitLab, we would like to periodically collect usage infor
msgstr "为了帮助改进GitLab,我们希望定期收集使用信æ¯ã€‚è¿™å¯ä»¥é€šè¿‡ %{settings_link_start}设置%{link_end}éšæ—¶æ›´æ”¹ã€‚ %{info_link_start}更多信æ¯%{link_end}"
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
-msgstr "å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}导入GitHub仓库。当创建个人访问令牌时,需è¦é€‰æ‹© <code>repo</code> 范围,以显示å¯å¯¼å…¥çš„公共和ç§æœ‰çš„仓库列表。"
+msgstr "å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}导入GitHub仓库。当创建个人访问令牌时,需è¦é€‰æ‹© <code>repo</code> 范围,以显示å¯å¯¼å…¥çš„公开和ç§æœ‰çš„仓库列表。"
msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
msgstr "è¦å¯¼å…¥GitHub仓库,首先需è¦æŽˆæƒGitLab访问列表中的GitHub仓库:"
@@ -8451,14 +9908,29 @@ msgstr "è¦å¯¼å…¥GitHub仓库,首先需è¦æŽˆæƒGitLab访问列表中的GitHub
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "è¦å¯¼å…¥SVN仓库,请查看 %{svn_link}。"
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr "如需将整个GitLab项目从å¦ä¸€ä¸ªGitLabæœåŠ¡å™¨ç§»åŠ¨æˆ–å¤åˆ¶åˆ°æ­¤æœåŠ¡å™¨ï¼Œè¯·è®¿é—®åŽŸé¡¹ç›®çš„设置页é¢ï¼Œç”Ÿæˆå¯¼å‡ºæ–‡ä»¶ï¼Œç„¶åŽåœ¨æ­¤å¤„上载。"
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "è¦ä»…为外部仓库使用CI / CD功能时,请选择</strong>使用外部仓库è¿è¡ŒCI/CD<strong>。"
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
-msgstr "请将%{start_tag}跟踪%{end_tag}页é¢è¿žæŽ¥åˆ°æ‚¨çš„ Jaeger æœåŠ¡å™¨ï¼Œä»¥ä¾¿åœ¨ GitLab 打开并轻æ¾æŸ¥çœ‹è·Ÿè¸ª"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "通过Azure,Okta,Onelogin,Ping Identity或自定义SAML 2.0等身份验è¯ç¨‹åºä¸ºæ‚¨çš„群组设置SAML身份验è¯ï¼š"
@@ -8466,6 +9938,9 @@ msgstr "通过Azure,Okta,Onelogin,Ping Identity或自定义SAML 2.0等身ä
msgid "To start serving your jobs you can add Runners to your group"
msgstr "è¦å¼€å§‹æ‰§è¡Œä»»åŠ¡ï¼Œè¯·æŠŠRunner加到群组中"
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr "转至此GitLab实例"
@@ -8475,6 +9950,9 @@ msgstr "如需验è¯GitLab CI设置,请访问当å‰é¡¹ç›®çš„'CI/CD → æµæ°´ç
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在月视图中,åªæ˜¾ç¤ºä¸Šä¸ªæœˆï¼Œæœ¬æœˆä»¥åŠæŽ¥ä¸‹æ¥5个月的å²è¯—故事."
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr "需è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–移除过滤æ¡ä»¶ã€‚"
@@ -8490,15 +9968,18 @@ msgstr "待办事项"
msgid "Toggle Sidebar"
msgstr "切æ¢ä¾§è¾¹æ "
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr "切æ¢æ交æè¿°"
+msgid "Toggle commit list"
+msgstr ""
+
msgid "Toggle discussion"
msgstr "开关讨论"
-msgid "Toggle file browser"
-msgstr ""
-
msgid "Toggle navigation"
msgstr "切æ¢å¯¼èˆª"
@@ -8506,10 +9987,10 @@ msgid "Toggle sidebar"
msgstr "切æ¢è¾¹æ "
msgid "ToggleButton|Toggle Status: OFF"
-msgstr "切æ¢çŠ¶æ€ï¼šå…³é—­"
+msgstr "开关状æ€ï¼šå…³é—­"
msgid "ToggleButton|Toggle Status: ON"
-msgstr "切æ¢çŠ¶æ€ï¼šå¼€å¯"
+msgstr "开关状æ€ï¼šå¼€å¯"
msgid "Token"
msgstr "令牌"
@@ -8533,7 +10014,7 @@ msgid "Total: %{total}"
msgstr "总计:%{total}"
msgid "Tracing"
-msgstr ""
+msgstr "跟踪"
msgid "Track activity with Contribution Analytics."
msgstr "通过贡献度分æžäº†è§£ç”¨æˆ·æ´»è·ƒåº¦ã€‚"
@@ -8548,20 +10029,23 @@ msgid "Tree view"
msgstr "树形视图"
msgid "Trending"
-msgstr "趋势"
-
-msgid "Trigger"
-msgstr "触å‘器"
+msgstr "热门"
msgid "Trigger pipelines for mirror updates"
msgstr "触å‘é•œåƒæ›´æ–°çš„æµæ°´çº¿"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
-msgstr "从上游存储库更新分支或标记时触å‘æµæ°´çº¿ã€‚如果上游存储库更新频ç¹ï¼Œè¿™å¯èƒ½ä¼šå¤§å¤§å¢žåŠ CI Runnerçš„è´Ÿè·ã€‚åªæœ‰å½“你知é“CI Runner的处ç†èƒ½åŠ›èƒ½å¤Ÿæ‰¿å—这样的负è·æ—¶ï¼Œä½ æ‰åº”å¯ç”¨æ­¤åŠŸèƒ½ã€‚"
+msgstr "从上游仓库更新分支或标记时触å‘æµæ°´çº¿ã€‚如上游仓库更新频ç¹ï¼ŒCI Runnerçš„è´Ÿè·å¯èƒ½ä¼šå¤§å¤§å¢žåŠ ã€‚åªæœ‰æ˜Žç¡®CI Runner的处ç†èƒ½åŠ›èƒ½å¤Ÿæ‰¿å—这样的负è·æ—¶ï¼Œæ‰åº”å¯ç”¨æ­¤åŠŸèƒ½ã€‚"
msgid "Trigger this manual action"
msgstr "触å‘此手动æ“作"
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "触å‘器å¯ä»¥é€šè¿‡ API 调用使特定的分支或标记被é‡æ–°æž„建,这些 token å¯ä»£è¡¨ä¸Žå…¶å…³è”的用户(包括该用户对项目的访问æƒé™ï¼‰"
@@ -8571,7 +10055,13 @@ msgstr "使用跟踪对应用程åºè¿›è¡Œæ•…障排除与监控"
msgid "Try again"
msgstr "请é‡è¯•"
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
+msgstr "30天内体验GitLab的所有功能。"
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
msgid "Turn on Service Desk"
@@ -8586,21 +10076,27 @@ msgstr "åŒé‡è®¤è¯"
msgid "Type"
msgstr "类型"
+msgid "URL"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "无法加载差异。 %{button_try_again}"
-msgid "Unable to save your changes"
-msgstr "无法ä¿å­˜æ›´æ”¹"
-
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "由于\"%{reason}\"的原因,您暂时ä¸èƒ½è¿›å…¥é…置了SAML 的群组"
msgid "Unable to update this epic at this time."
msgstr "当å‰æ— æ³•æ›´æ–°æ­¤å²è¯—故事。"
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr "撤消"
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr "未知的"
@@ -8617,7 +10113,7 @@ msgid "Unresolve discussion"
msgstr "待解决的讨论"
msgid "Unschedule job"
-msgstr ""
+msgstr "å–消作业计划"
msgid "Unstage"
msgstr "å–消暂存"
@@ -8649,6 +10145,9 @@ msgstr "在群组级别å–消订阅"
msgid "Unsubscribe at project level"
msgstr "在项目级别å–消订阅"
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr "未验è¯"
@@ -8656,11 +10155,14 @@ msgid "Up to date"
msgstr "已是最新"
msgid "Upcoming"
-msgstr ""
+msgstr "å³å°†å¼€å§‹"
msgid "Update"
msgstr "æ›´æ–°"
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr "ç«‹å³æ›´æ–°"
@@ -8670,6 +10172,9 @@ msgstr "更新您的群组å称ã€è¯´æ˜Žã€å¤´åƒä»¥åŠå¯è§æ€§ã€‚"
msgid "Updating"
msgstr "更新中"
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨é«˜çº§å…¨å±€æœç´¢ã€‚"
@@ -8677,10 +10182,10 @@ msgid "Upgrade your plan to activate Contribution Analytics."
msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨è´¡çŒ®åˆ†æžã€‚"
msgid "Upgrade your plan to activate Group Webhooks."
-msgstr "å‡çº§æ‚¨çš„订阅计划以激活Group Webhooks 。"
+msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨ç¾¤ç»„Webhook。"
msgid "Upgrade your plan to activate Issue weight."
-msgstr "å‡çº§æ‚¨çš„订阅计划以激活议题æƒé‡ã€‚"
+msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨è®®é¢˜æƒé‡ã€‚"
msgid "Upgrade your plan to improve Issue boards."
msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的议题看æ¿ã€‚"
@@ -8688,15 +10193,30 @@ msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的议题看æ¿ã€‚"
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr "在这里上传 <code>GoogleCodeProjectHosting.json</code>:"
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "上传新文件"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "上传文件"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "点击上传"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr "顶"
@@ -8727,9 +10247,15 @@ msgstr "在安装过程中使用以下注册令牌:"
msgid "Use your global notification setting"
msgstr "使用全局通知设置"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "ä¾›æˆå‘˜ç™»å½•æ‚¨çš„GitLab群组"
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr "用户世代表仅在å¯ç”¨ %{usage_ping_link_start}使用情况检测(usage ping)%{usage_ping_link_end} 时显示。"
@@ -8754,47 +10280,83 @@ msgstr "å‚与贡献的项目"
msgid "UserProfile|Edit profile"
msgstr "编辑个人资料"
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr "群组"
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr "最新活动"
+msgid "UserProfile|No snippets found."
+msgstr ""
+
msgid "UserProfile|Overview"
msgstr "概览"
msgid "UserProfile|Personal projects"
msgstr "个人项目"
-msgid "UserProfile|Recent contributions"
-msgstr "最新贡献"
-
msgid "UserProfile|Report abuse"
msgstr "举报滥用行为"
msgid "UserProfile|Snippets"
-msgstr "片段"
+msgstr "代ç ç‰‡æ®µ"
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
msgid "UserProfile|Subscribe"
msgstr "关注"
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr "此用户具有éžå…¬å¼€ä¸ªäººèµ„料设置"
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "查看全部"
msgid "UserProfile|View user in admin area"
msgstr "在管ç†åŒºåŸŸä¸­æŸ¥çœ‹ç”¨æˆ·"
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr "用户"
-msgid "Variables"
-msgstr "å˜é‡"
+msgid "Users requesting access to"
+msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr "å˜é‡é€šè¿‡runner作用于环境中。å¯å°†å˜é‡é™åˆ¶ä¸ºä»…å—ä¿æŠ¤çš„分支或标签å¯ä»¥è®¿é—®ã€‚å¯ä»¥ä½¿ç”¨å˜é‡æ¥ä¿å­˜å¯†ç ã€å¯†é’¥æˆ–任何其他内容。"
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
msgid "Various container registry settings."
msgstr "容器注册表相关设置。"
@@ -8802,12 +10364,18 @@ msgstr "容器注册表相关设置。"
msgid "Various email settings."
msgstr "电å­é‚®ä»¶ç›¸å…³è®¾ç½®"
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr "å½±å“GitLab性能相关设置。"
msgid "Verification information"
msgstr "验è¯ä¿¡æ¯"
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr "已验è¯"
@@ -8815,9 +10383,15 @@ msgid "Version"
msgstr "版本"
msgid "View %{alerts}"
-msgstr ""
+msgstr "查看 %{alerts}"
msgid "View app"
+msgstr "查看应用程åº"
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
msgstr ""
msgid "View documentation"
@@ -8859,6 +10433,9 @@ msgstr "查看替æ¢æ–‡ä»¶ @ "
msgid "View the documentation"
msgstr "查看文档"
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "å¯è§æ€§ä¸Žè®¿é—®æŽ§åˆ¶"
@@ -8883,51 +10460,78 @@ msgstr "公开"
msgid "VisibilityLevel|Unknown"
msgstr "未知"
-msgid "Vulnerability|Class"
+msgid "Vulnerability Chart"
msgstr ""
-msgid "Vulnerability|Confidence"
+msgid "Vulnerability List"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr "类型"
+
+msgid "Vulnerability|Confidence"
+msgstr "置信度"
+
msgid "Vulnerability|Description"
-msgstr ""
+msgstr "说明"
msgid "Vulnerability|File"
-msgstr ""
+msgstr "文件"
msgid "Vulnerability|Identifiers"
-msgstr ""
+msgstr "标识"
msgid "Vulnerability|Instances"
-msgstr ""
+msgstr "实例"
msgid "Vulnerability|Links"
-msgstr ""
+msgstr "链接"
msgid "Vulnerability|Project"
+msgstr "项目"
+
+msgid "Vulnerability|Report Type"
msgstr ""
msgid "Vulnerability|Severity"
+msgstr "严é‡æ€§"
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr "æƒé™ä¸è¶³ã€‚如需查看相关数æ®ï¼Œè¯·å‘管ç†å‘˜ç”³è¯·æƒé™ã€‚"
+
+msgid "We can't find an epic that matches what you are looking for."
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "We can't find an issue that matches what you are looking for."
msgstr ""
-msgid "Want to see the data? Please ask an administrator for access."
-msgstr "æƒé™ä¸è¶³ã€‚如需查看相关数æ®ï¼Œè¯·å‘管ç†å‘˜ç”³è¯·æƒé™ã€‚"
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
-msgstr "我们在 %{humanized_resource_name} 检测到潜在滥用行为。请输入此reCAPTCHA验è¯ç å¹¶ç»§ç»­ã€‚"
+msgstr "我们在%{humanized_resource_name}检测到潜在滥用行为。请输入此reCAPTCHA验è¯ç å¹¶ç»§ç»­ã€‚"
msgid "We don't have enough data to show this stage."
msgstr "该阶段的数æ®ä¸è¶³ï¼Œæ— æ³•æ˜¾ç¤ºã€‚"
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "我们è¦ç¡®å®šä½ æ˜¯ä¸æ˜¯æœºå™¨äººã€‚"
msgid "Web IDE"
msgstr "Web IDE"
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr "Web终端"
@@ -8952,11 +10556,14 @@ msgstr "该项å¯ç”¨åŽï¼Œç”¨æˆ·åœ¨æŽ¥å—æ¡æ¬¾è¢«å‰å°†ä¸èƒ½ä½¿ç”¨GitLab。"
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "å°†URLä¿ç•™ä¸ºç©ºç™½æ—¶ï¼Œä»å¯æŒ‡å®šåˆ†ç±»æ ‡ç­¾ï¼Œè€Œæ— éœ€ç¦ç”¨è·¨é¡¹ç›®åŠŸèƒ½æˆ–执行外部授æƒæ£€æŸ¥ã€‚"
-msgid "Who can see this group?"
+msgid "When:"
msgstr ""
+msgid "Who can see this group?"
+msgstr "哪些人å¯ä»¥çœ‹åˆ°è¿™ä¸ªç¾¤ç»„?"
+
msgid "Who will be able to see this group?"
-msgstr ""
+msgstr "哪些人å¯ä»¥çœ‹åˆ°è¿™ä¸ªç¾¤ç»„?"
msgid "Wiki"
msgstr "Wiki"
@@ -9004,7 +10611,7 @@ msgid "WikiEmpty|The wiki lets you write documentation for your project"
msgstr "您å¯ä»¥ä½¿ç”¨ Wiki 为您的项目编写文档"
msgid "WikiEmpty|This project has no wiki pages"
-msgstr "该项目没有任何 Wiki 页é¢"
+msgstr "该项目无任何 Wiki 页é¢"
msgid "WikiEmpty|You must be a project member in order to add wiki pages."
msgstr "åªæœ‰é¡¹ç›®æˆå‘˜æ‰å¯ä»¥æ·»åŠ  Wiki 页é¢ã€‚"
@@ -9093,12 +10700,21 @@ msgstr "页é¢"
msgid "Wiki|Wiki Pages"
msgstr "Wiki 页é¢"
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr "通过贡献分æžï¼Œæ‚¨å¯ä»¥ä»Žæ€»ä½“上了解您的组织åŠå…¶æˆå‘˜çš„议题〠åˆå¹¶è¯·æ±‚和推é€æ´»åŠ¨çš„情况。"
msgid "Withdraw Access Request"
msgstr "å–消æƒé™ç”³è¯·"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr "是"
@@ -9111,6 +10727,9 @@ msgstr "是的,让我将Google Code用户映射到全å或GitLab用户。"
msgid "Yesterday"
msgstr "昨天"
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "您是一å管ç†å‘˜ï¼Œè¿™æ„味ç€æŽˆäºˆå¯¹ <strong>%{client_name}</strong> 访问æƒé™å°†å…许他们作为管ç†å‘˜ä¸ŽGitLab进行交互。请谨慎æ“作。"
@@ -9129,6 +10748,9 @@ msgstr "å°†è¦æŠŠ %{project_full_name} 转移给å¦ä¸€ä¸ªæ‰€æœ‰è€…。确定执è¡
msgid "You are on a read-only GitLab instance."
msgstr "当å‰æ­£åœ¨è®¿é—®åªè¯» GitLab 实例。"
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "您å¯ä»¥ %{linkStart}查看BLOB%{linkEnd} 代替。"
@@ -9153,6 +10775,9 @@ msgstr "åªèƒ½åœ¨åˆ†æ”¯ä¸Šæ·»åŠ æ–‡ä»¶"
msgid "You can only edit files when you are on a branch"
msgstr "åªèƒ½åœ¨åˆ†æ”¯ä¸Šç¼–辑文件"
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "您å¯ä»¥ä½¿ç”¨äº¤äº’模å¼ï¼Œé€šè¿‡é€‰æ‹© %{use_ours} 或 %{use_theirs} 按钮æ¥è§£å†³åˆå¹¶å†²çªã€‚也å¯ä»¥é€šè¿‡ç›´æŽ¥ç¼–辑文件æ¥è§£å†³åˆå¹¶å†²çªã€‚然åŽå°†è¿™äº›æ›´æ”¹æ交到 %{branch_name}"
@@ -9169,10 +10794,13 @@ msgid "You cannot write to this read-only GitLab instance."
msgstr "您ä¸èƒ½å†™å…¥è¿™ä¸ªåªè¯»çš„ GitLab 实例。"
msgid "You do not have any subscriptions yet"
+msgstr "您当å‰å°šæœªè®¢é˜…任何计划"
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr "您没有正确的æƒé™æ¥æ›´æ”¹LDAP组åŒæ­¥ä¸­çš„设置。"
+msgstr "您没有更改LDAP组åŒæ­¥ä¸­è®¾ç½®çš„相应æƒé™ã€‚"
msgid "You don't have any applications"
msgstr "你没有任何应用程åº"
@@ -9180,12 +10808,18 @@ msgstr "你没有任何应用程åº"
msgid "You don't have any authorized applications"
msgstr "您没有任何授æƒçš„应用"
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr "没有æƒé™"
msgid "You have reached your project limit"
msgstr "您已达到项目数é‡é™åˆ¶"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr "您必须接å—我们的æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–æ‰èƒ½æ³¨å†Œå¸æˆ·"
@@ -9195,17 +10829,23 @@ msgstr "必须拥有维护者æƒé™æ‰èƒ½å¼ºåˆ¶åˆ é™¤é”"
msgid "You need a different license to enable FileLocks feature"
msgstr "需è¦ä½¿ç”¨ä¸Žå½“å‰ä¸åŒçš„许å¯(license) æ‰èƒ½å¯ç”¨FileLocks功能"
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr "您需è¦git-lfs版本 %{min_git_lfs_version} (或更高版本)æ‰èƒ½ç»§ç»­ã€‚请访问https://git-lfs.github.com"
msgid "You need permission."
msgstr "需è¦ç›¸å…³çš„æƒé™ã€‚"
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
-msgstr "您将丢失对此文件所åšçš„所有更改。此æ“作无法撤消。"
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
-msgstr "您将丢失在此项目中所åšçš„所有未暂存的修改,此æ“作无法撤消。"
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
msgid "You will not get any notifications via email"
msgstr "ä¸ä¼šæ”¶åˆ°ä»»ä½•é€šçŸ¥é‚®ä»¶"
@@ -9246,6 +10886,9 @@ msgstr "您收到这å°ç”µå­é‚®ä»¶æ˜¯å› ä¸ºä½ åœ¨ %{host} 拥有å¸æˆ·ã€‚ %{man
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr "您的群组"
@@ -9261,12 +10904,18 @@ msgstr "您的项目活动"
msgid "Your Todos"
msgstr "您的待办事项"
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr "你的应用程åº(%{size})"
msgid "Your authorized applications"
msgstr "您已授æƒçš„应用"
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "åˆå¹¶è¯·æ±‚已开å¯ï¼Œå¯ä»¥æ交å˜æ›´åˆ°%{branch_name}。"
@@ -9279,12 +10928,24 @@ msgstr "您的更改已ä¿å­˜"
msgid "Your comment will not be visible to the public."
msgstr "您的评论将ä¸ä¼šå…¬å¼€æ˜¾ç¤ºã€‚"
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "您的群组"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "您的åå­—"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr "您的项目"
@@ -9294,12 +10955,18 @@ msgstr "已删除的用户"
msgid "ago"
msgstr "å‰"
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr "åŠå…¶ä»–功能"
msgid "assign yourself"
msgstr "分é…给自己"
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr "分支å称"
@@ -9326,27 +10993,27 @@ msgstr "还有%{remainingPackagesCount} 个"
msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
-msgstr[0] "%{reportType} %{status} 检测到%{fixedCount}个安全æ¼æ´žå·²ä¿®å¤ã€‚"
+msgstr[0] "%{reportType}%{status} 检测到%{fixedCount}个安全æ¼æ´žå·²ä¿®å¤ã€‚"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
-msgstr[0] "%{reportType} %{status} 检测到%{newCount}个新的安全æ¼æ´žã€‚"
+msgstr[0] "%{reportType}%{status} 检测到%{newCount}个新的安全æ¼æ´žã€‚"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
-msgstr "%{reportType} %{status} 检测到 %{newCount} 新的安全æ¼æ´žå’Œ %{fixedCount} 个已修å¤æ¼æ´ž"
+msgstr "%{reportType}%{status}检测到%{newCount}个新的安全æ¼æ´žå’Œ%{fixedCount}个已修å¤æ¼æ´ž"
msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
-msgstr[0] "%{reportType} %{status} 检测到æºåˆ†æ”¯æœ‰%{newCount} 个安全æ¼æ´ž"
+msgstr[0] "%{reportType}%{status}检测到æºåˆ†æ”¯æœ‰%{newCount} 个安全æ¼æ´ž"
msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
-msgstr "%{reportType} %{status} 未å‘现新的安全æ¼æ´ž"
+msgstr "%{reportType}%{status}未å‘现新的安全æ¼æ´ž"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr "%{reportType} %{status} 未å‘现安全æ¼æ´ž"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
-msgstr "%{reportType} %{status} 检测到æºåˆ†æ”¯æ²¡æœ‰å®‰å…¨æ¼æ´ž"
+msgstr "%{reportType}%{status}检测到æºåˆ†æ”¯æ— å®‰å…¨æ¼æ´ž"
msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
@@ -9388,6 +11055,9 @@ msgstr "容器扫æå¯ä»¥æ£€æµ‹Dockeré•œåƒä¸­ä¸­å·²çŸ¥çš„安全æ¼æ´žã€‚"
msgid "ciReport|DAST"
msgstr "DAST"
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr "ä¾èµ–项扫æå¯ä»¥æ£€æµ‹æºä»£ç ä¾èµ–项中已知的æ¼æ´žã€‚"
@@ -9403,6 +11073,12 @@ msgstr "忽略æ¼æ´ž"
msgid "ciReport|Dismissed by"
msgstr "忽略æ“作æ¥è‡ª"
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr "动æ€åº”用程åºå®‰å…¨æµ‹è¯•ï¼ˆDAST)å¯æ£€æµ‹Web应用程åºä¸­çš„已知æ¼æ´žã€‚"
@@ -9426,11 +11102,11 @@ msgstr "了解有关安全报告(Alpha)的更多信æ¯ã€‚"
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
-msgstr[0] "许å¯è¯ç®¡ç†ä»…检测到æºåˆ†æ”¯çš„ %d 许å¯è¯"
+msgstr[0] "许å¯è¯ç®¡ç†ä»…检测到æºåˆ†æ”¯çš„%d个许å¯è¯"
msgid "ciReport|License management detected %d new license"
msgid_plural "ciReport|License management detected %d new licenses"
-msgstr[0] "许å¯è¯ç®¡ç†æ£€æµ‹åˆ° %d 个新的许å¯è¯"
+msgstr[0] "许å¯è¯ç®¡ç†æ£€æµ‹åˆ°%d个新的许å¯è¯"
msgid "ciReport|License management detected no licenses for the source branch only"
msgstr "许å¯è¯ç®¡ç†ä»…未检测到æºåˆ†æ”¯ä¸Šçš„许å¯è¯"
@@ -9445,7 +11121,7 @@ msgid "ciReport|Loading %{reportName} report"
msgstr "载入%{reportName} 报告"
msgid "ciReport|Manage licenses"
-msgstr "管ç†è®¸å¯"
+msgstr "管ç†è®¸å¯è¯"
msgid "ciReport|Method"
msgstr "方法"
@@ -9520,6 +11196,9 @@ msgstr "于æµæ°´çº¿"
msgid "command line instructions"
msgstr "命令行指å—"
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr "å³å°†å…³é—­ç§å¯†æ€§ã€‚这将使得 <strong>所有用户</strong>都å¯ä»¥æŸ¥çœ‹å¹¶ä¸”评论当å‰è®®é¢˜ã€‚"
@@ -9539,12 +11218,19 @@ msgid "day"
msgid_plural "days"
msgstr[0] "天"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr "部署令牌"
msgid "disabled"
msgstr "å·²ç¦ç”¨"
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+
msgid "done"
msgstr "完æˆ"
@@ -9555,6 +11241,15 @@ msgstr[0] "è‰ç¨¿"
msgid "enabled"
msgstr "å·²å¯ç”¨"
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "最åŽä¸€æ¬¡%{slash_command} 命令将更新预计时间。"
@@ -9564,21 +11259,39 @@ msgstr "对于这个项目"
msgid "from"
msgstr "æ¥è‡ª"
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr "帮助"
msgid "here"
msgstr "此处"
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr "导入æµç¨‹"
msgid "importing"
msgstr "导入中"
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "实例已完æˆ"
@@ -9592,9 +11305,27 @@ msgstr "因上游é”定而无效"
msgid "is not a valid X509 certificate."
msgstr "ä¸æ˜¯æœ‰æ•ˆçš„X509è¯ä¹¦ã€‚"
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr "议题看æ¿"
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr "最新部署"
@@ -9607,13 +11338,28 @@ msgstr "许å¯è¯ç®¡ç†"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "被 %{path_lock_user_name} 在 %{created_at} é”定"
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "åˆå¹¶è¯·æ±‚"
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "请æ¢å¤æ­¤åˆ†æ”¯æˆ–使用其他的 %{missingBranchName} 分支"
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr "%{metricsLinkStart} 内存 %{metricsLinkEnd} å ç”¨ %{emphasisStart} ä¸‹é™ %{emphasisEnd},从 %{memoryFrom}MB 到 %{memoryTo}MB"
@@ -9627,13 +11373,13 @@ msgid "mrWidget|Add approval"
msgstr "添加批准"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr "具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜å…许æ交"
+msgstr "å…许具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜æ交"
-msgid "mrWidget|An error occured while removing your approval."
-msgstr "删除您的批准时å‘生错误。"
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
-msgstr "读å–æ­¤åˆå¹¶è¯·æ±‚的批准数æ®æ—¶å‘生错误。"
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "æ交批准时å‘生错误。"
@@ -9671,11 +11417,14 @@ msgstr "关闭"
msgid "mrWidget|Create an issue to resolve them later"
msgstr "创建议题以便åŽç»­å¤„ç†"
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "部署统计信æ¯å½“å‰ä¸å¯ç”¨"
msgid "mrWidget|Did not close"
-msgstr "没有关闭"
+msgstr "未关闭"
msgid "mrWidget|Email patches"
msgstr "通过电å­é‚®ä»¶å‘出补ä¸"
@@ -9732,7 +11481,7 @@ msgid "mrWidget|Plain diff"
msgstr "文本差异"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
-msgstr "准备自动åˆå¹¶ã€‚询问具有此存储库的写访问æƒé™çš„人æ¥åˆå¹¶æ­¤è¯·æ±‚"
+msgstr "å·²å¯è‡ªåŠ¨åˆå¹¶ã€‚ 请具有仓库写入æƒé™çš„用户æ¥åˆå¹¶æ­¤è¯·æ±‚"
msgid "mrWidget|Refresh"
msgstr "刷新"
@@ -9743,12 +11492,6 @@ msgstr "ç«‹å³åˆ·æ–°"
msgid "mrWidget|Refreshing now"
msgstr "ç«‹å³åˆ·æ–°"
-msgid "mrWidget|Remove Source Branch"
-msgstr "删除æºåˆ†æ”¯"
-
-msgid "mrWidget|Remove source branch"
-msgstr "删除æºåˆ†æ”¯"
-
msgid "mrWidget|Remove your approval"
msgstr "删除您的批准"
@@ -9757,7 +11500,7 @@ msgstr "请求åˆå¹¶"
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "éœ€è¦ %d 次批准"
+msgstr[0] "还需è¦%d个批准"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
@@ -9767,7 +11510,7 @@ msgid "mrWidget|Resolve conflicts"
msgstr "解决冲çª"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr "解决这些冲çªæˆ–询问对此存储库具有写入æƒé™çš„人员在本地åˆå¹¶å®ƒ"
+msgstr "请解决这些冲çªæˆ–请具有仓库写入æƒé™çš„用户在本地进行åˆå¹¶"
msgid "mrWidget|Revert"
msgstr "还原"
@@ -9793,20 +11536,20 @@ msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿å¤±è´¥ã€‚请é‡è¯•è¯¥ä½œä¸šæˆ–推é€æ–°çš„æ
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "æºåˆ†æ”¯HEAD最近已更改。请在é‡æ–°åˆå¹¶ä¹‹å‰é‡æ–°åŠ è½½é¡µé¢å¹¶æŸ¥çœ‹æ›´æ”¹"
-msgid "mrWidget|The source branch has been removed"
-msgstr "æºåˆ†æ”¯å·²è¢«åˆ é™¤"
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
-msgstr "æºåˆ†æ”¯æ˜¯ %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} 的目标分支"
+msgstr "æºåˆ†æ”¯æ˜¯æ¯”目标分支%{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd}"
-msgid "mrWidget|The source branch is being removed"
-msgstr "æºåˆ†æ”¯æ­£åœ¨è¢«åˆ é™¤"
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
-msgid "mrWidget|The source branch will be removed"
-msgstr "æºåˆ†æ”¯å°†è¢«åˆ é™¤"
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
-msgid "mrWidget|The source branch will not be removed"
-msgstr "æºåˆ†æ”¯ä¸ä¼šè¢«åˆ é™¤"
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "存在åˆå¹¶å†²çª"
@@ -9814,6 +11557,9 @@ msgstr "存在åˆå¹¶å†²çª"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "存在尚未解决的讨论。请先解决这些讨论。"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "该åˆå¹¶è¯·æ±‚未能自动åˆå¹¶"
@@ -9826,11 +11572,11 @@ msgstr "该项目已存档,ç¦æ­¢å†™å…¥"
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr "ä¸å…许直接编辑此项目。请派生(fork)åŽè¿›è¡Œæ›´æ”¹ã€‚"
-msgid "mrWidget|You can merge this merge request manually using the"
-msgstr "å¯ä»¥æ‰‹åŠ¨åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚,使用以下"
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
-msgid "mrWidget|You can remove source branch now"
-msgstr "当å‰å·²å¯ä»¥åˆ é™¤æºåˆ†æ”¯"
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr "æ­¤åˆå¹¶è¯·æ±‚å¯ä»¥æ‰‹åŠ¨åˆå¹¶ï¼Œè¯·ä½¿ç”¨ä»¥ä¸‹"
msgid "mrWidget|branch does not exist."
msgstr "分支ä¸å­˜åœ¨"
@@ -9850,15 +11596,27 @@ msgstr "ä¸é€‚用"
msgid "new merge request"
msgstr "新建åˆå¹¶è¯·æ±‚"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "通知邮件"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr "或"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
-msgstr[0] "总共 %d 次测试中"
+msgstr[0] "于总计%d个测试中"
msgid "parent"
msgid_plural "parents"
@@ -9870,6 +11628,9 @@ msgstr "密ç "
msgid "personal access token"
msgstr "个人访问令牌"
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr "ç§é’¥ä¸Žè¯ä¹¦ä¸åŒ¹é…。"
@@ -9877,6 +11638,12 @@ msgid "project"
msgid_plural "projects"
msgstr[0] "项目"
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr "剩余"
@@ -9889,27 +11656,57 @@ msgstr "删除截止日期"
msgid "remove weight"
msgstr "移除æƒé‡"
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
-msgstr[0] "回å¤"
+msgstr[0] "æ¡å›žå¤"
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
msgid "source"
msgstr "æº"
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} 将会更新消耗的总时长。"
msgid "started"
msgstr "已开始"
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr "此文档"
msgid "to help your contributors communicate effectively!"
msgstr "帮助您的贡献者进行有效沟通ï¼"
-msgid "toggle collapse"
-msgstr "切æ¢æŠ˜å "
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
+msgstr ""
msgid "username"
msgstr "用户å"
@@ -9917,9 +11714,15 @@ msgstr "用户å"
msgid "uses Kubernetes clusters to deploy your code!"
msgstr "使用 Kubernetes 集群æ¥éƒ¨ç½²ä»£ç ï¼"
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "使用GitLab查看"
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "å…± %{additions} æ¡æ–°å¢ž, %{deletions} æ¡åˆ é™¤."
@@ -9927,3 +11730,6 @@ msgid "within %d minute "
msgid_plural "within %d minutes "
msgstr[0] "在 %d 分钟内 "
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 4425bb7be10..a6dfd5f6139 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: zh-HK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:21\n"
+"PO-Revision-Date: 2019-02-11 08:13\n"
msgid " Status"
msgstr ""
@@ -29,16 +29,17 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] ""
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] ""
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
msgid "%d commit"
msgid_plural "%d commits"
@@ -48,9 +49,8 @@ msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] ""
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -68,6 +68,10 @@ msgid "%d issue"
msgid_plural "%d issues"
msgstr[0] ""
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -107,6 +111,9 @@ msgstr ""
msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more"
+msgstr ""
+
msgid "%{count} more assignees"
msgstr ""
@@ -124,12 +131,18 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
+
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,9 +152,6 @@ msgstr ""
msgid "%{name}'s avatar"
msgstr ""
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
-
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -151,6 +161,24 @@ msgstr ""
msgid "%{percent}%% complete"
msgstr ""
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,12 +195,21 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
+msgid ", or "
+msgstr ""
+
msgid "- Runner is active and can process any new jobs"
msgstr ""
@@ -229,10 +266,13 @@ msgstr[0] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
-msgid "403|Please contact your GitLab administrator to get the permission."
+msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
msgid "403|You don't have the permission to access this page."
@@ -274,7 +314,7 @@ msgstr ""
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
-msgid "<strong>Removes</strong> source branch"
+msgid "<strong>Deletes</strong> source branch"
msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
@@ -322,6 +362,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -358,11 +401,11 @@ msgstr "活動"
msgid "Add"
msgstr ""
-msgid "Add Changelog"
-msgstr "添加更新日誌"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "添加貢ç»æŒ‡å—"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -373,7 +416,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
-msgid "Add Readme"
+msgid "Add README"
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
@@ -406,6 +452,9 @@ msgstr ""
msgid "Add reaction"
msgstr ""
+msgid "Add to project"
+msgstr ""
+
msgid "Add to review"
msgstr ""
@@ -415,6 +464,9 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr ""
@@ -430,9 +482,6 @@ msgstr ""
msgid "Admin Overview"
msgstr ""
-msgid "Admin area"
-msgstr ""
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -466,12 +515,42 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr ""
@@ -484,12 +563,42 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -500,6 +609,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr "全部"
@@ -509,9 +621,15 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -533,6 +651,9 @@ msgstr ""
msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allowed to fail"
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -560,40 +681,10 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
-msgstr ""
-
-msgid "An error occured whilst fetching the latest pipeline."
-msgstr ""
-
-msgid "An error occured whilst loading all the files."
-msgstr ""
-
-msgid "An error occured whilst loading the file content."
-msgstr ""
-
-msgid "An error occured whilst loading the file."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr ""
-
-msgid "An error occured whilst loading the merge request."
-msgstr ""
-
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
@@ -602,6 +693,9 @@ msgstr ""
msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred creating the new branch."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -674,12 +768,21 @@ msgstr ""
msgid "An error occurred while loading the file"
msgstr ""
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr ""
msgid "An error occurred while removing approver"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -710,9 +813,54 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
msgid "Analytics"
msgstr ""
@@ -743,6 +891,21 @@ msgstr ""
msgid "Applications"
msgstr ""
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -755,6 +918,9 @@ msgstr ""
msgid "Archived projects"
msgstr ""
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "確定è¦åˆªé™¤æ­¤æµæ°´ç·šè¨ˆåŠƒå—Žï¼Ÿ"
@@ -764,12 +930,24 @@ msgstr ""
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr ""
@@ -785,6 +963,9 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
msgid "Are you sure?"
msgstr "確定嗎?"
@@ -803,6 +984,9 @@ msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -812,6 +996,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -839,6 +1026,9 @@ msgstr ""
msgid "Assignee(s)"
msgstr ""
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "拖放文件到此處或者 %{upload_link}"
@@ -851,6 +1041,9 @@ msgstr ""
msgid "August"
msgstr ""
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
msgstr ""
@@ -866,6 +1059,9 @@ msgstr ""
msgid "Authorization code:"
msgstr ""
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -893,15 +1089,6 @@ msgstr ""
msgid "Auto DevOps, runners and job artifacts"
msgstr ""
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
-
msgid "Auto-cancel redundant, pending pipelines"
msgstr ""
@@ -935,13 +1122,25 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
-msgid "Available group Runners : %{runners}"
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
msgstr ""
-msgid "Available group Runners : %{runners}."
+msgid "Avatar for %{name}"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
@@ -1127,6 +1326,12 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1136,10 +1341,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "分支 <strong>%{branch_name}</strong> 已創建。如需設置自動部署, è«‹é¸æ“‡åˆé©çš„ GitLab CI Yaml 模æ¿ä½µæ交更改。%{link_to_autodeploy_doc}"
@@ -1293,21 +1494,36 @@ msgstr "ç€è¦½æ–‡ä»¶"
msgid "Browse files"
msgstr "ç€è¦½æ–‡ä»¶"
-msgid "Built-In"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr ""
@@ -1344,12 +1560,6 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
-
msgid "CICD|Jobs"
msgstr ""
@@ -1359,18 +1569,27 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
+
msgid "Cancel"
msgstr "å–消"
@@ -1383,12 +1602,21 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
msgid "Certificate fingerprint"
msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1410,12 +1638,12 @@ msgstr "還原"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
-msgid "Changelog"
-msgstr "更新日誌"
-
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr "統計圖"
@@ -1425,9 +1653,15 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check your .gitlab-ci.yml"
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
+msgid "Checking approval status"
+msgstr ""
+
msgid "Checking branch availability..."
msgstr ""
@@ -1449,6 +1683,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1467,6 +1707,9 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1560,7 +1803,7 @@ msgstr ""
msgid "CiVariable|Create wildcard"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|New environment"
@@ -1581,6 +1824,12 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -1620,28 +1869,52 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clone"
+msgstr ""
+
msgid "Clone repository"
msgstr ""
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
msgid "Close"
msgstr ""
msgid "Close epic"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1665,27 +1938,42 @@ msgstr ""
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
+msgid "ClusterIntegration|Alternatively"
+msgstr ""
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr ""
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr ""
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1695,6 +1983,9 @@ msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -1707,6 +1998,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1734,6 +2028,15 @@ msgstr ""
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr ""
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
msgstr ""
@@ -1806,6 +2109,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
@@ -1821,6 +2130,12 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
@@ -1857,6 +2172,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr ""
+
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -1935,6 +2253,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
+
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -1977,12 +2298,18 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
+
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr ""
+
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
@@ -1998,6 +2325,18 @@ msgstr ""
msgid "ClusterIntegration|Token"
msgstr ""
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
+
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
@@ -2010,6 +2349,9 @@ msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2037,6 +2379,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
msgstr ""
@@ -2049,9 +2394,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
msgstr ""
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
@@ -2068,13 +2422,15 @@ msgid "Commit"
msgid_plural "Commits"
msgstr[0] "æ交"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
msgstr ""
+msgid "Commit deleted"
+msgstr ""
+
msgid "Commit duration in minutes for last 30 commits"
msgstr "最近30次æ交花費的時間(分é˜ï¼‰"
@@ -2138,6 +2494,9 @@ msgstr ""
msgid "Compare Revisions"
msgstr ""
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
msgstr ""
@@ -2165,12 +2524,18 @@ msgstr ""
msgid "Confidentiality"
msgstr ""
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Tracing"
msgstr ""
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2204,6 +2569,9 @@ msgstr ""
msgid "Connecting..."
msgstr ""
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2252,6 +2620,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr ""
@@ -2267,8 +2638,8 @@ msgstr ""
msgid "Contribution"
msgstr ""
-msgid "Contribution guide"
-msgstr "è²¢ç»æŒ‡å—"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr ""
@@ -2303,13 +2674,16 @@ msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr ""
-msgid "Copy %{protocol} clone URL"
+msgid "Copy %{http_label} clone URL"
msgstr ""
-msgid "Copy HTTPS clone URL"
+msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy ID to clipboard"
@@ -2318,6 +2692,9 @@ msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2342,9 +2719,6 @@ msgstr ""
msgid "Copy link"
msgstr ""
-msgid "Copy name to clipboard"
-msgstr ""
-
msgid "Copy reference to clipboard"
msgstr ""
@@ -2366,6 +2740,9 @@ msgstr ""
msgid "Create New Directory"
msgstr "創建新目錄"
+msgid "Create New Domain"
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
@@ -2375,6 +2752,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "在帳戶上創建個人訪å•ä»¤ç‰Œï¼Œä»¥é€šéŽ %{protocol} 來拉å–或推é€ã€‚"
@@ -2414,6 +2794,9 @@ msgstr "創建åˆä½µè«‹æ±‚"
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2480,9 +2863,6 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "Custom"
-msgstr ""
-
msgid "Custom CI config path"
msgstr ""
@@ -2498,6 +2878,9 @@ msgstr "自定義通知級別繼承自åƒèˆ‡ç´šåˆ¥ã€‚使用自定義通知級別
msgid "Custom project templates"
msgstr ""
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -2507,6 +2890,12 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
+msgstr ""
+
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
@@ -2537,6 +2926,9 @@ msgstr "é ç™¼å¸ƒ"
msgid "CycleAnalyticsStage|Test"
msgstr "測試"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -2546,6 +2938,9 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -2558,6 +2953,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2567,6 +2965,12 @@ msgstr ""
msgid "Default classification label"
msgstr ""
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -2576,6 +2980,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "使用 Cron 語法定義自定義模å¼"
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2606,6 +3013,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -2739,6 +3152,9 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed"
+msgstr ""
+
msgid "Deployed to"
msgstr ""
@@ -2766,6 +3182,9 @@ msgstr ""
msgid "Details"
msgstr "詳情"
+msgid "Details (default)"
+msgstr ""
+
msgid "Detect host keys"
msgstr ""
@@ -2796,6 +3215,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2817,15 +3242,24 @@ msgstr ""
msgid "Discard review"
msgstr ""
-msgid "Discover GitLab Geo."
+msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
@@ -2853,6 +3287,12 @@ msgstr ""
msgid "Download"
msgstr "下載"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "下載 tar"
@@ -2877,6 +3317,9 @@ msgstr "差異文件"
msgid "DownloadSource|Download"
msgstr "下載"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr ""
@@ -2892,9 +3335,15 @@ msgstr ""
msgid "Edit"
msgstr "編輯"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "編輯 %{id} æµæ°´ç·šè¨ˆåŠƒ"
@@ -2904,6 +3353,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2913,6 +3368,9 @@ msgstr ""
msgid "Edit identity for %{user_name}"
msgstr ""
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr ""
@@ -2931,6 +3389,9 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr ""
@@ -2955,6 +3416,9 @@ msgstr ""
msgid "Enable classification control using an external service"
msgstr ""
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -2970,9 +3434,18 @@ msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -2985,6 +3458,12 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
@@ -3000,9 +3479,27 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -3078,6 +3575,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -3090,9 +3590,6 @@ msgstr ""
msgid "Epic"
msgstr ""
-msgid "Epic will be removed! Are you sure?"
-msgstr ""
-
msgid "Epics"
msgstr ""
@@ -3102,7 +3599,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -3129,9 +3626,15 @@ msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
+msgid "Error Tracking"
+msgstr ""
+
msgid "Error creating epic"
msgstr ""
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
msgstr ""
@@ -3174,9 +3677,15 @@ msgstr ""
msgid "Error occurred when toggling the notification subscription"
msgstr ""
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
msgstr ""
+msgid "Error updating %{issuableType}"
+msgstr ""
+
msgid "Error updating status for all todos."
msgstr ""
@@ -3186,6 +3695,12 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
msgid "Estimated"
msgstr ""
@@ -3207,6 +3722,12 @@ msgstr "按推é€äº‹ä»¶ (push event) éŽæ¿¾"
msgid "EventFilterBy|Filter by team"
msgstr "按團隊éŽæ¿¾"
+msgid "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "æ¯æ—¥åŸ·è¡Œï¼ˆæ·©æ™¨ 4 點)"
@@ -3216,9 +3737,39 @@ msgstr "æ¯æœˆåŸ·è¡Œï¼ˆæ¯æœˆ 1 日淩晨 4 點)"
msgid "Every week (Sundays at 4:00am)"
msgstr "æ¯é€±åŸ·è¡Œï¼ˆå‘¨æ—¥æ·©æ™¨ 4 點)"
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr ""
@@ -3231,6 +3782,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
@@ -3252,9 +3809,21 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr ""
@@ -3294,6 +3863,9 @@ msgstr ""
msgid "Failed to load emoji list."
msgstr ""
+msgid "Failed to load errors from Sentry"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3303,28 +3875,40 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "無法刪除æµæ°´ç·šè¨ˆåŠƒ"
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
msgid "Failed to signing using smartcard authentication"
msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr ""
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
msgid "Feature Flags"
msgstr ""
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Configure"
@@ -3336,7 +3920,10 @@ msgstr ""
msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
@@ -3348,30 +3935,48 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag"
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
msgstr ""
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr ""
+msgid "FeatureFlags|Loading Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|More Information"
+msgstr ""
+
msgid "FeatureFlags|More information"
msgstr ""
@@ -3390,6 +3995,21 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3399,15 +4019,34 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
+msgid "File upload error."
+msgstr ""
+
msgid "Files"
msgstr "文件"
-msgid "Files (%{human_size})"
-msgstr ""
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -3423,12 +4062,30 @@ msgstr ""
msgid "Filter by commit message"
msgstr "按æ交消æ¯éŽæ¿¾"
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
msgid "Filter..."
msgstr ""
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
+msgstr ""
+
msgid "Find by path"
msgstr "按路徑查找"
+msgid "Find existing members by name"
+msgstr ""
+
msgid "Find file"
msgstr "查找文件"
@@ -3441,12 +4098,18 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish editing this message first!"
+msgstr ""
+
msgid "Finish review"
msgstr ""
msgid "Finished"
msgstr ""
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
msgstr "首次推é€"
@@ -3492,6 +4155,9 @@ msgstr ""
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "For more info, read the documentation."
+msgstr ""
+
msgid "For more information, go to the "
msgstr ""
@@ -3516,6 +4182,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr ""
@@ -3567,6 +4236,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Generate key"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -3657,7 +4329,10 @@ msgstr ""
msgid "GeoNodes|Out of sync"
msgstr ""
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
msgstr ""
msgid "GeoNodes|Replication slot WAL"
@@ -3732,6 +4407,9 @@ msgstr ""
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr ""
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr ""
@@ -3777,6 +4455,9 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Last repository check run"
+msgstr ""
+
msgid "Geo|Last successful sync"
msgstr ""
@@ -3813,6 +4494,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Re-verification interval"
+msgstr ""
+
msgid "Geo|Recheck"
msgstr ""
@@ -3891,9 +4575,18 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
msgstr ""
@@ -3921,9 +4614,15 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr ""
@@ -3954,6 +4653,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -3978,6 +4680,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -4023,13 +4728,16 @@ msgstr ""
msgid "Group name"
msgstr ""
-msgid "Group: %{group_name}"
+msgid "Group overview content"
msgstr ""
-msgid "GroupRoadmap|From %{dateWord}"
+msgid "Group:"
msgstr ""
-msgid "GroupRoadmap|Loading roadmap"
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
@@ -4041,37 +4749,34 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Badges"
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupRoadmap|Until %{dateWord}"
+msgid "GroupSettings|Customize your group badges."
msgstr ""
-msgid "GroupSettings|Badges"
+msgid "GroupSettings|Learn more about badges."
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
@@ -4098,6 +4803,9 @@ msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -4197,6 +4905,9 @@ msgstr ""
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
msgstr ""
+msgid "Hide file browser"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4207,7 +4918,7 @@ msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
-msgid "Hide whitespace changes"
+msgid "Hide values"
msgstr ""
msgid "History"
@@ -4216,6 +4927,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr "已開始維護"
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -4273,6 +4987,9 @@ msgstr ""
msgid "Identity provider single sign on URL"
msgstr ""
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
@@ -4303,9 +5020,15 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr ""
@@ -4324,12 +5047,24 @@ msgstr ""
msgid "Import in progress"
msgstr ""
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
msgstr ""
+msgid "Import project members"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -4354,6 +5089,9 @@ msgstr ""
msgid "Import repository"
msgstr "導入存儲庫"
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -4369,15 +5107,30 @@ msgstr ""
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
+msgid "Include merge request description"
+msgstr ""
+
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
msgid "Incompatible Project"
msgstr ""
@@ -4393,6 +5146,9 @@ msgstr ""
msgid "Input your repository URL"
msgstr ""
+msgid "Insert suggestion"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
@@ -4421,6 +5177,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -4436,9 +5195,27 @@ msgstr "循環週期"
msgid "Introducing Cycle Analytics"
msgstr "週期分æžç°¡ä»‹"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -4457,6 +5234,21 @@ msgstr ""
msgid "IssueBoards|Boards"
msgstr ""
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr ""
@@ -4490,6 +5282,12 @@ msgstr ""
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jaeger URL"
msgstr ""
@@ -4508,6 +5306,12 @@ msgstr ""
msgid "Job has been erased"
msgstr ""
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -4547,10 +5351,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4565,12 +5369,18 @@ msgstr ""
msgid "June"
msgstr ""
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
msgid "Kubernetes Cluster"
msgstr ""
+msgid "Kubernetes Clusters"
+msgstr ""
+
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr ""
@@ -4647,6 +5457,9 @@ msgstr[0] "最近 %d 天"
msgid "Last Pipeline"
msgstr "最新æµæ°´ç·š"
+msgid "Last activity"
+msgstr ""
+
msgid "Last commit"
msgstr "最後æ交"
@@ -4662,6 +5475,9 @@ msgstr ""
msgid "Last reply by"
msgstr ""
+msgid "Last seen"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4677,15 +5493,39 @@ msgstr "在"
msgid "Latest changes"
msgstr ""
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr ""
@@ -4822,6 +5662,12 @@ msgstr ""
msgid "Loading..."
msgstr ""
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr ""
@@ -4888,6 +5734,9 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -4918,6 +5767,9 @@ msgstr ""
msgid "Mark todo as done"
msgstr ""
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr ""
@@ -4954,9 +5806,6 @@ msgstr ""
msgid "Maven Metadata"
msgstr ""
-msgid "Maven package"
-msgstr ""
-
msgid "Max access level"
msgstr ""
@@ -4978,13 +5827,16 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "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\"."
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
msgstr ""
-msgid "Merge Request"
+msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request:"
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
msgstr ""
msgid "Merge Requests"
@@ -4993,9 +5845,18 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr "åˆä½µäº‹ä»¶ (merge event)"
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr ""
@@ -5008,19 +5869,31 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -5038,6 +5911,24 @@ msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
@@ -5047,6 +5938,9 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
+msgid "MergeRequest|Search files"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -5065,7 +5959,7 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics|Business"
+msgid "Metrics for environment"
msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
@@ -5074,6 +5968,12 @@ msgstr ""
msgid "Metrics|Create metric"
msgstr ""
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr ""
@@ -5083,7 +5983,7 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
@@ -5095,22 +5995,16 @@ msgstr ""
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
-msgid "Metrics|Name"
-msgstr ""
-
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Prometheus Query Documentation"
+msgid "Metrics|PromQL query is valid"
msgstr ""
-msgid "Metrics|Query"
-msgstr ""
-
-msgid "Metrics|Response"
+msgid "Metrics|Prometheus Query Documentation"
msgstr ""
msgid "Metrics|System"
@@ -5125,10 +6019,10 @@ msgstr ""
msgid "Metrics|There was an error getting environments information."
msgstr ""
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
+msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
@@ -5149,21 +6043,12 @@ msgstr ""
msgid "Metrics|Y-axis label"
msgstr ""
-msgid "Metrics|e.g. HTTP requests"
-msgstr ""
-
-msgid "Metrics|e.g. Requests/second"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr ""
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
-
-msgid "Metrics|e.g. req/sec"
-msgstr ""
-
msgid "Milestone"
msgstr ""
@@ -5236,6 +6121,18 @@ msgstr ""
msgid "Modal|Close"
msgstr ""
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr ""
@@ -5296,6 +6193,9 @@ msgstr ""
msgid "Nav|Sign out and sign in with a different account"
msgstr ""
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr ""
@@ -5308,6 +6208,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -5321,6 +6224,12 @@ msgstr[0] "新建議題"
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
msgstr "創建æµæ°´ç·šè¨ˆåŠƒ"
@@ -5339,6 +6248,9 @@ msgstr ""
msgid "New directory"
msgstr "新增目錄"
+msgid "New environment"
+msgstr ""
+
msgid "New epic"
msgstr ""
@@ -5360,6 +6272,9 @@ msgstr ""
msgid "New merge request"
msgstr "新增åˆä½µè«‹æ±‚"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5387,6 +6302,9 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -5396,6 +6314,9 @@ msgstr ""
msgid "No changes"
msgstr ""
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -5408,15 +6329,24 @@ msgstr ""
msgid "No credit card required."
msgstr ""
+msgid "No details available"
+msgstr ""
+
msgid "No due date"
msgstr ""
+msgid "No errors to display"
+msgstr ""
+
msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen"
msgstr ""
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5429,6 +6359,9 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
+msgid "No matching results"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5438,10 +6371,13 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
@@ -5462,6 +6398,9 @@ msgstr ""
msgid "No schedules"
msgstr "沒有計劃"
+msgid "No start date"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -5471,12 +6410,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -5501,6 +6434,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
@@ -5531,6 +6467,12 @@ msgstr ""
msgid "Notification events"
msgstr "通知事件"
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "關閉議題"
@@ -5628,21 +6570,36 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
+msgid "Only mirror protected branches"
msgstr ""
-msgid "Only mirror protected branches"
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
msgstr ""
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5676,16 +6633,13 @@ msgstr ""
msgid "Operations Dashboard"
msgstr ""
-msgid "Operations Settings"
-msgstr ""
-
msgid "OperationsDashboard|Add a project to the dashboard"
msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
@@ -5733,6 +6687,12 @@ msgstr ""
msgid "Pages"
msgstr ""
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -5745,12 +6705,27 @@ msgstr ""
msgid "Pagination|« First"
msgstr ""
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5772,9 +6747,6 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
-
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -5790,6 +6762,12 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr "æµæ°´ç·š"
@@ -5976,6 +6954,9 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -5988,9 +6969,15 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -6003,6 +6990,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
+msgstr ""
+
msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
@@ -6045,6 +7035,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -6066,9 +7059,18 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|@username"
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
msgid "Profiles|Add key"
msgstr ""
@@ -6084,15 +7086,30 @@ msgstr ""
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
msgstr ""
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -6111,6 +7128,9 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Disconnect"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -6120,6 +7140,12 @@ msgstr ""
msgid "Profiles|Edit Profile"
msgstr ""
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -6156,10 +7182,13 @@ msgstr ""
msgid "Profiles|Set new profile picture"
msgstr ""
+msgid "Profiles|Social sign-in"
+msgstr ""
+
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
@@ -6168,7 +7197,7 @@ msgstr ""
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
@@ -6177,10 +7206,13 @@ msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
@@ -6207,12 +7239,15 @@ msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -6231,16 +7266,19 @@ msgstr ""
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr ""
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
-msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
@@ -6249,6 +7287,12 @@ msgstr ""
msgid "Profiles|e.g. My MacBook key"
msgstr ""
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr ""
@@ -6306,12 +7350,18 @@ msgstr "項目導出éˆæŽ¥å·²éŽæœŸã€‚請從項目設置中é‡æ–°ç”Ÿæˆé …目導
msgid "Project export started. A download link will be sent by email."
msgstr "項目導出已開始。下載éˆæŽ¥å°‡é€šéŽé›»å­éƒµä»¶ç™¼é€ã€‚"
+msgid "Project members"
+msgstr ""
+
msgid "Project name"
msgstr ""
msgid "Project slug"
msgstr ""
+msgid "Project:"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "訂閱"
@@ -6456,9 +7506,6 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusDashboard|Time"
-msgstr ""
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -6483,6 +7530,9 @@ msgstr ""
msgid "PrometheusService|Custom metrics"
msgstr ""
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -6612,6 +7662,9 @@ msgstr ""
msgid "Pseudonymizer data collection"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -6651,21 +7704,30 @@ msgstr ""
msgid "Quarters"
msgstr ""
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "README"
+msgstr ""
+
msgid "Read more"
msgstr "了解更多"
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
-msgstr "自述文件"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -6691,6 +7753,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -6721,6 +7786,12 @@ msgstr "相關已åˆä½µçš„åˆä½µè«‹æ±‚"
msgid "Related merge requests"
msgstr ""
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "ç¨å¾Œæ醒"
@@ -6730,6 +7801,12 @@ msgstr ""
msgid "Remove Runner"
msgstr ""
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -6760,9 +7837,15 @@ msgstr ""
msgid "Reopen epic"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
+msgid "Reply to comment"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -6823,6 +7906,12 @@ msgstr ""
msgid "Repository URL"
msgstr ""
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr ""
@@ -6841,6 +7930,9 @@ msgstr ""
msgid "Request Access"
msgstr "申請權é™"
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
@@ -6850,12 +7942,27 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
msgid "Reset health check access token"
msgstr "é‡ç½®å¥åº·æª¢æŸ¥è¨ªå•ä»¤ç‰Œ"
+msgid "Reset key"
+msgstr ""
+
msgid "Reset runners registration token"
msgstr "é‡ç½® Runner 註冊令牌"
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -6865,6 +7972,12 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -6874,12 +7987,18 @@ msgstr ""
msgid "Response metrics (HA Proxy)"
msgstr ""
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Restart Terminal"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6892,13 +8011,13 @@ msgstr ""
msgid "Retry verification"
msgstr ""
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
msgstr[0] ""
+msgid "Reveal values"
+msgstr ""
+
msgid "Revert this commit"
msgstr "還原此æ交"
@@ -6926,6 +8045,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
msgid "Run untagged jobs"
msgstr ""
@@ -6953,6 +8075,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -6986,7 +8111,7 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -7007,6 +8132,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7016,6 +8144,9 @@ msgstr ""
msgid "Save changes before testing"
msgstr ""
+msgid "Save comment"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "ä¿å­˜æµæ°´ç·šè¨ˆåŠƒ"
@@ -7052,6 +8183,9 @@ msgstr ""
msgid "Search"
msgstr ""
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -7064,6 +8198,9 @@ msgstr ""
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr ""
@@ -7133,7 +8270,7 @@ msgstr ""
msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
@@ -7142,10 +8279,13 @@ msgstr ""
msgid "Security Reports|Dismiss vulnerability"
msgstr ""
+msgid "Security Reports|Learn more about setting up your dashboard"
+msgstr ""
+
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
@@ -7163,6 +8303,18 @@ msgstr ""
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "Security Reports|Undo dismiss"
+msgstr ""
+
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
@@ -7172,6 +8324,12 @@ msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -7199,6 +8357,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select members to invite"
+msgstr ""
+
msgid "Select project"
msgstr ""
@@ -7232,9 +8393,15 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
+msgid "Sentry API URL"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -7244,6 +8411,48 @@ msgstr ""
msgid "Server version"
msgstr ""
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -7274,6 +8483,9 @@ msgstr ""
msgid "Set notification email for abuse reports."
msgstr ""
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -7289,6 +8501,9 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
+msgid "Set up new U2F device"
+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 ""
@@ -7352,10 +8567,10 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show latest version"
+msgid "Show file browser"
msgstr ""
-msgid "Show latest version of the diff"
+msgid "Show latest version"
msgstr ""
msgid "Show parent pages"
@@ -7392,12 +8607,21 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
-msgid "Sign in to %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with Single Sign-On"
msgstr ""
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -7407,6 +8631,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -7428,9 +8655,18 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet Contents"
+msgstr ""
+
msgid "Snippets"
msgstr ""
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr ""
@@ -7440,6 +8676,9 @@ msgstr ""
msgid "Something went wrong on our end. Please try again!"
msgstr ""
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr ""
@@ -7449,9 +8688,15 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
@@ -7470,6 +8715,9 @@ msgstr ""
msgid "Something went wrong while fetching the registry list."
msgstr ""
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr ""
@@ -7494,9 +8742,15 @@ msgstr ""
msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
+msgid "Sort direction"
+msgstr ""
+
msgid "SortOptions|Access level, ascending"
msgstr ""
@@ -7542,7 +8796,7 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
@@ -7575,6 +8829,9 @@ msgstr ""
msgid "SortOptions|Oldest joined"
msgstr ""
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr ""
@@ -7587,6 +8844,9 @@ msgstr ""
msgid "SortOptions|Priority"
msgstr ""
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr ""
@@ -7614,6 +8874,9 @@ msgstr "æºä»£ç¢¼"
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -7629,6 +8892,9 @@ msgstr ""
msgid "Specify the following URL during the Runner setup:"
msgstr "在 Runner 設置時指定以下 URL:"
+msgid "Squash commit message"
+msgstr ""
+
msgid "Squash commits"
msgstr ""
@@ -7665,6 +8931,12 @@ msgstr ""
msgid "Starred projects"
msgstr ""
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
@@ -7674,9 +8946,21 @@ msgstr ""
msgid "Start and due date"
msgstr ""
+msgid "Start cleanup"
+msgstr ""
+
msgid "Start date"
msgstr ""
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "é‹ä½œ Runner!"
@@ -7686,6 +8970,15 @@ msgstr ""
msgid "Started"
msgstr ""
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
@@ -7695,6 +8988,12 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -7710,6 +9009,9 @@ msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
+msgid "Stopping..."
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7725,6 +9027,9 @@ msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit feedback"
+msgstr ""
+
msgid "Submit review"
msgstr ""
@@ -7740,10 +9045,94 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7758,7 +9147,10 @@ msgstr ""
msgid "System Info"
msgstr ""
-msgid "System header and footer:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
msgstr ""
msgid "System metrics (Custom)"
@@ -7767,9 +9159,11 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "標籤"
@@ -7864,6 +9258,12 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -7879,9 +9279,15 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
+msgstr ""
+
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
@@ -7918,6 +9324,9 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "議題階段概述了從創建議題到將議題添加到è£ç¨‹ç¢‘或議題看æ¿æ‰€èŠ±è²»çš„時間。創建第壹個議題後,數據將自動添加到此處.。"
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr ""
@@ -7996,16 +9405,34 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•¸æ˜¯å£¹å€‹æ•¸åˆ—中最中間的值。例如在 3ã€5ã€9 之間,中ä½æ•¸æ˜¯ 5。在 3ã€5ã€7ã€8 之間,中ä½æ•¸æ˜¯ (5 + 7)/ 2 = 6。"
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no packages yet"
msgstr ""
msgid "There are no projects shared with this group yet"
@@ -8041,12 +9468,21 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -8074,13 +9510,16 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
-msgid "This group"
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgid "This group"
msgstr ""
msgid "This group does not provide any group Runners yet."
@@ -8143,10 +9582,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -8155,7 +9594,7 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -8176,6 +9615,15 @@ msgstr ""
msgid "This page will be removed in a future release."
msgstr ""
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr ""
@@ -8203,7 +9651,7 @@ msgstr ""
msgid "This source diff could not be displayed because it is too large."
msgstr ""
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
@@ -8215,7 +9663,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
-msgid "This will delete the custom metric, Are you sure?"
+msgid "This will redirect you to an external sign in page."
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
@@ -8406,9 +9854,18 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr ""
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
@@ -8451,13 +9908,28 @@ msgstr ""
msgid "To import an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8466,6 +9938,9 @@ msgstr ""
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
@@ -8475,6 +9950,9 @@ msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
msgid "To widen your search, change or remove filters."
msgstr ""
@@ -8490,13 +9968,16 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
msgstr ""
-msgid "Toggle discussion"
+msgid "Toggle commit list"
msgstr ""
-msgid "Toggle file browser"
+msgid "Toggle discussion"
msgstr ""
msgid "Toggle navigation"
@@ -8550,9 +10031,6 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -8562,6 +10040,12 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
@@ -8571,9 +10055,15 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
@@ -8586,10 +10076,10 @@ msgstr ""
msgid "Type"
msgstr ""
-msgid "Unable to load the diff. %{button_try_again}"
+msgid "URL"
msgstr ""
-msgid "Unable to save your changes"
+msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
@@ -8598,9 +10088,15 @@ msgstr ""
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unblock"
+msgstr ""
+
msgid "Undo"
msgstr ""
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -8649,6 +10145,9 @@ msgstr ""
msgid "Unsubscribe at project level"
msgstr ""
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -8661,6 +10160,9 @@ msgstr ""
msgid "Update"
msgstr ""
+msgid "Update failed"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -8670,6 +10172,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
@@ -8688,15 +10193,30 @@ msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
+msgid "Upload CSV file"
+msgstr ""
+
msgid "Upload New File"
msgstr "上傳新文件"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "上傳文件"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
msgstr "點擊上傳"
+msgid "Upstream"
+msgstr ""
+
msgid "Upvotes"
msgstr ""
@@ -8727,9 +10247,15 @@ msgstr "在安è£éŽç¨‹ä¸­ä½¿ç”¨ä»¥ä¸‹è¨»å†Šä»¤ç‰Œï¼š"
msgid "Use your global notification setting"
msgstr "使用全局通知設置"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used to help configure your identity provider"
+msgstr ""
+
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
@@ -8754,19 +10280,28 @@ msgstr ""
msgid "UserProfile|Edit profile"
msgstr ""
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
msgid "UserProfile|Groups"
msgstr ""
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "UserProfile|Overview"
+msgid "UserProfile|No snippets found."
msgstr ""
-msgid "UserProfile|Personal projects"
+msgid "UserProfile|Overview"
msgstr ""
-msgid "UserProfile|Recent contributions"
+msgid "UserProfile|Personal projects"
msgstr ""
msgid "UserProfile|Report abuse"
@@ -8775,25 +10310,52 @@ msgstr ""
msgid "UserProfile|Snippets"
msgstr ""
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
msgid "UserProfile|This user has a private profile"
msgstr ""
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
msgid "UserProfile|View user in admin area"
msgstr ""
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
msgid "Users"
msgstr ""
-msgid "Variables"
+msgid "Users requesting access to"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
msgstr ""
msgid "Various container registry settings."
@@ -8802,12 +10364,18 @@ msgstr ""
msgid "Various email settings."
msgstr ""
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr ""
msgid "Verification information"
msgstr ""
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -8820,6 +10388,12 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View documentation"
msgstr ""
@@ -8859,6 +10433,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -8883,6 +10460,12 @@ msgstr "公開"
msgid "VisibilityLevel|Unknown"
msgstr "未知"
+msgid "Vulnerability Chart"
+msgstr ""
+
+msgid "Vulnerability List"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -8907,27 +10490,48 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Severity"
+msgid "Vulnerability|Report Type"
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "Vulnerability|Severity"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "權é™ä¸è¶³ã€‚如需查看相關數據,請å‘管ç†å“¡ç”³è«‹æ¬Šé™ã€‚"
+msgid "We can't find an epic that matches what you are looking for."
+msgstr ""
+
+msgid "We can't find an issue that matches what you are looking for."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "該階段的數據ä¸è¶³ï¼Œç„¡æ³•é¡¯ç¤ºã€‚"
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
msgstr ""
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr ""
@@ -8952,6 +10556,9 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "When:"
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -9093,12 +10700,21 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr ""
msgid "Withdraw Access Request"
msgstr "å–消權é™ç”³è¯·"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
@@ -9111,6 +10727,9 @@ msgstr ""
msgid "Yesterday"
msgstr ""
+msgid "You"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -9129,6 +10748,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -9153,6 +10775,9 @@ msgstr "åªèƒ½åœ¨åˆ†æ”¯ä¸Šæ·»åŠ æ–‡ä»¶"
msgid "You can only edit files when you are on a branch"
msgstr ""
+msgid "You can only merge once the items above are resolved"
+msgstr ""
+
msgid "You can 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 ""
@@ -9171,6 +10796,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -9180,12 +10808,18 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
msgid "You have reached your project limit"
msgstr "您已é”到項目數é‡é™åˆ¶"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
@@ -9195,16 +10829,22 @@ msgstr ""
msgid "You need a different license to enable FileLocks feature"
msgstr ""
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr ""
msgid "You need permission."
msgstr "需è¦ç›¸é—œçš„權é™ã€‚"
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9246,6 +10886,9 @@ msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
msgid "Your Groups"
msgstr ""
@@ -9261,12 +10904,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -9279,12 +10928,24 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "您的åå­—"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
msgstr ""
@@ -9294,12 +10955,18 @@ msgstr ""
msgid "ago"
msgstr ""
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr ""
@@ -9388,6 +11055,9 @@ msgstr ""
msgid "ciReport|DAST"
msgstr ""
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
@@ -9403,6 +11073,12 @@ msgstr ""
msgid "ciReport|Dismissed by"
msgstr ""
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr ""
@@ -9520,6 +11196,9 @@ msgstr ""
msgid "command line instructions"
msgstr ""
+msgid "commented on %{link_to_project}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -9539,12 +11218,19 @@ msgid "day"
msgid_plural "days"
msgstr[0] "天"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+
msgid "done"
msgstr ""
@@ -9555,6 +11241,15 @@ msgstr[0] ""
msgid "enabled"
msgstr ""
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -9564,21 +11259,39 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "group"
+msgstr ""
+
msgid "help"
msgstr ""
msgid "here"
msgstr ""
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "image diff"
+msgstr ""
+
msgid "import flow"
msgstr ""
msgid "importing"
msgstr ""
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -9592,9 +11305,27 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
msgstr ""
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
msgid "latest deployment"
msgstr ""
@@ -9607,13 +11338,28 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr ""
@@ -9629,10 +11375,10 @@ msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
-msgid "mrWidget|An error occured while removing your approval."
+msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
@@ -9671,6 +11417,9 @@ msgstr ""
msgid "mrWidget|Create an issue to resolve them later"
msgstr ""
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -9743,12 +11492,6 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove Source Branch"
-msgstr ""
-
-msgid "mrWidget|Remove source branch"
-msgstr ""
-
msgid "mrWidget|Remove your approval"
msgstr ""
@@ -9793,19 +11536,19 @@ msgstr ""
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr ""
-msgid "mrWidget|The source branch has been removed"
+msgid "mrWidget|The source branch has been deleted"
msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being removed"
+msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be removed"
+msgid "mrWidget|The source branch will be deleted"
msgstr ""
-msgid "mrWidget|The source branch will not be removed"
+msgid "mrWidget|The source branch will not be deleted"
msgstr ""
msgid "mrWidget|There are merge conflicts"
@@ -9814,6 +11557,9 @@ msgstr ""
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr ""
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -9826,10 +11572,10 @@ msgstr ""
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
-msgid "mrWidget|You can remove source branch now"
+msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|branch does not exist."
@@ -9850,9 +11596,21 @@ msgstr ""
msgid "new merge request"
msgstr "新建åˆä½µè«‹æ±‚"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "通知郵件"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr ""
@@ -9870,6 +11628,9 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr ""
@@ -9877,6 +11638,12 @@ msgid "project"
msgid_plural "projects"
msgstr[0] ""
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
msgid "remaining"
msgstr ""
@@ -9889,26 +11656,56 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
msgid "source"
msgstr ""
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
msgid "this document"
msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9917,9 +11714,15 @@ msgstr ""
msgid "uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
+msgid "view the blob"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
@@ -9927,3 +11730,6 @@ msgid "within %d minute "
msgid_plural "within %d minutes "
msgstr[0] ""
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 47646afb0a9..c4a58650dae 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-11-19 17:21\n"
+"PO-Revision-Date: 2019-02-11 10:20\n"
msgid " Status"
msgstr " 狀態"
@@ -23,34 +23,34 @@ msgstr " 和"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
-msgstr[0] " 在 %d 點上é™ç´š"
+msgstr[0] " 劣化了 %d 點"
msgid " improved on %d point"
msgid_plural " improved on %d points"
-msgstr[0] " 在 %d 點上改善"
+msgstr[0] " 改善了 %d 點"
-msgid "\"%{query}\" in projects"
+msgid " or "
msgstr ""
-msgid "%d addition"
-msgid_plural "%d additions"
-msgstr[0] ""
+msgid " or <#epic id>"
+msgstr ""
-msgid "%d changed file"
-msgid_plural "%d changed files"
-msgstr[0] "%d 個已變更檔案"
+msgid " or <#issue id>"
+msgstr ""
+
+msgid "\"%{query}\" in projects"
+msgstr "在專案中查詢「%{query}ã€"
msgid "%d commit"
msgid_plural "%d commits"
-msgstr[0] "%d 個æ交紀錄"
+msgstr[0] "%d 則æ交"
msgid "%d commit behind"
msgid_plural "%d commits behind"
-msgstr[0] "è½å¾Œ %d 個æ交紀錄"
+msgstr[0] "è½å¾Œäº† %d 則æ交"
-msgid "%d deleted"
-msgid_plural "%d deletions"
-msgstr[0] ""
+msgid "%d commits"
+msgstr ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -58,15 +58,19 @@ msgstr[0] "%d 個匯出工具"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] "%d 個失敗的測試çµæžœ"
+msgstr[0] "%d 項測試失敗çµæžœ"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] "%d 個修復的測試çµæžœ"
+msgstr[0] "%d 項已修復測試çµæžœ"
msgid "%d issue"
msgid_plural "%d issues"
-msgstr[0] "%d 個議題"
+msgstr[0] "%d 則議題"
+
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
msgid "%d layer"
msgid_plural "%d layers"
@@ -90,109 +94,142 @@ msgstr[0] "%d 個未暫存變更"
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] "因效能考é‡ï¼Œå·²éš±è— %s 個更動 (commit)。"
+msgstr[0] "為é¿å…效能å•é¡Œï¼Œå·²éš±è— %s 則é¡å¤–çš„æ交記錄。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
msgid "%{authorsName}'s discussion"
-msgstr ""
+msgstr "%{authorsName} 建立的討論"
msgid "%{commit_author_link} authored %{commit_timeago}"
-msgstr "%{commit_author_link} æ–¼ %{commit_timeago} æ交"
+msgstr "%{commit_author_link} 已在 %{commit_timeago} é€äº¤"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} 個版本庫ã€%{counter_build_artifacts} 個編譯產物ã€å’Œ %{counter_lfs_objects} 個 LFS)"
+msgstr "%{counter_storage}ï¼ˆå…§å« %{counter_repositories} 個版本庫ã€%{counter_build_artifacts} 個編譯æˆå“ä»¥åŠ %{counter_lfs_objects} 個 LFS 儲存空間)"
msgid "%{count} %{alerts}"
+msgstr "%{count} 個 %{alerts} æ醒"
+
+msgid "%{count} more"
msgstr ""
msgid "%{count} more assignees"
-msgstr ""
+msgstr "%{count} å以上的被指派者"
msgid "%{count} participant"
msgid_plural "%{count} participants"
-msgstr[0] "%{count} åƒèˆ‡è€…"
+msgstr[0] "%{count} ä½åƒèˆ‡è€…"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
-msgstr[0] ""
+msgstr[0] "%{count} 則待檢閱留言"
msgid "%{filePath} deleted"
-msgstr "已刪除 %{filePath}"
+msgstr "已刪除 %{filePath} 檔案"
msgid "%{firstLabel} +%{labelCount} more"
-msgstr "%{firstLabel} +%{labelCount} 更多"
+msgstr "%{firstLabel}(內å«å‰©é¤˜çš„ %{labelCount} 個)"
+
+msgid "%{firstOption} +%{extraOptionCount} more"
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}群組%{group_docs_link_end} å…許您管ç†ã€å”作多個專案。群組的æˆå“¡å¯ä»¥å­˜å–群組下的所有專案。"
+msgstr "%{group_docs_link_start}群組%{group_docs_link_end} 讓您能跨管ç†ä»¥åŠå”作多個專案。群組的æˆå“¡å¯ä»¥å­˜å–群組之下的所有專案。"
msgid "%{issuableType} will be removed! Are you sure?"
-msgstr "將會移除 %{issuableType}ï¼ç¢ºå®šï¼Ÿ"
+msgstr "將移除 %{issuableType}ï¼ç¢ºå®šï¼Ÿ"
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
msgid "%{loadingIcon} Started"
-msgstr "%{loadingIcon} 開始"
+msgstr "%{loadingIcon} 已開始程å¼"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} 被 GitLab 使用者 %{lock_user_id} 鎖定"
msgid "%{name}'s avatar"
-msgstr "%{name} çš„é ­è²¼"
-
-msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} å¯ä»¥ç•¶ä½œè‡ªè¨‚網域的替代方案。"
+msgstr "%{name} 的大頭貼"
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
-msgstr "%{number_commits_behind} 個è½å¾Œ %{default_branch} 分支的æ交記錄,%{number_commits_ahead} 個超å‰çš„æ交記錄"
+msgstr "與 %{default_branch} 比較è½å¾Œ %{number_commits_behind} 個æ交,但領先 %{number_commits_ahead} 個æ交"
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
-msgstr "å®Œæˆ %{percent}%%"
+msgstr "å·²å®Œæˆ %{percent}%%"
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text} %{files} 個檔案"
msgid "%{text} is available"
-msgstr "%{text} å¯ç”¨"
+msgstr "%{text} å¯ä¾›ä½¿ç”¨"
msgid "%{title} changes"
msgstr "%{title} 變更"
msgid "%{unstaged} unstaged and %{staged} staged changes"
-msgstr "%{unstaged} 個未暫存和 %{staged} 個已暫存變更"
+msgstr "%{unstaged} å€‹æœªæš«å­˜ä»¥åŠ %{staged} 個已暫存變更"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
-msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end}會與 GitLab å…¬å¸åˆ†äº«çš„資料。"
+msgstr "%{usage_ping_link_start}得知更多%{usage_ping_link_end}會分享給 GitLab å…¬å¸çš„資料。"
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
msgid "+ %{count} more"
-msgstr "+ %{count} 更多"
+msgstr "(還有 %{count} 個)"
msgid "+ %{moreCount} more"
-msgstr "+ %{moreCount} 更多"
+msgstr "(還有 %{moreCount} 個)"
+
+msgid ", or "
+msgstr ""
msgid "- Runner is active and can process any new jobs"
-msgstr "- Runner 為啟用狀態,並且å¯ä»¥è™•ç†ä»»ä½•æ–°çš„工作"
+msgstr "-執行器為啟動狀態,å¯ä¾›è™•ç†æ–°çš„作業"
msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Runner 為暫åœç‹€æ…‹ï¼Œä¸”å°‡ä¸æœƒæŽ¥å—任何新的工作"
+msgstr "-執行器為暫åœç‹€æ…‹ï¼Œå°‡ä¸æŽ¥æ”¶æ–°çš„作業"
msgid "- show less"
-msgstr "- 顯示較少"
+msgstr "- 顯示較少內容"
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
-msgstr[0] "%{count}%{type} 個附加項目"
+msgstr[0] "%{count} 個 %{type} 新增"
msgid "1 %{type} modification"
msgid_plural "%{count} %{type} modifications"
-msgstr[0] "%{count}%{type} 個變更項目"
+msgstr[0] "%{count} 個 %{type} 變更"
msgid "1 closed issue"
msgid_plural "%d closed issues"
-msgstr[0] "%d 個關閉議題"
+msgstr[0] "%d 個關閉的議題"
msgid "1 closed merge request"
msgid_plural "%d closed merge requests"
@@ -208,15 +245,15 @@ msgstr[0] "%d 個已åˆä½µçš„åˆä½µè«‹æ±‚"
msgid "1 open issue"
msgid_plural "%d open issues"
-msgstr[0] "%d 個開放中的議題"
+msgstr[0] "%d 個進行中議題"
msgid "1 open merge request"
msgid_plural "%d open merge requests"
-msgstr[0] "%d 個開放中åˆä½µè«‹æ±‚"
+msgstr[0] "%d 個進行中åˆä½µè«‹æ±‚"
msgid "1 pipeline"
msgid_plural "%d pipelines"
-msgstr[0] "%d æ¢æµæ°´ç·š"
+msgstr[0] "%d æ¢ç®¡ç·š"
msgid "1 role"
msgid_plural "%d roles"
@@ -227,28 +264,31 @@ msgid_plural "%d users"
msgstr[0] "%d ä½ä½¿ç”¨è€…"
msgid "1st contribution!"
-msgstr "第一次å”作ï¼"
+msgstr "您的第一次貢ç»ï¼"
+
+msgid "2FA"
+msgstr ""
msgid "2FA enabled"
-msgstr "已啟用雙é‡èªè­‰"
+msgstr "已啟用兩步驟驗證"
-msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "è«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡ä»¥å–得權é™ã€‚"
+msgid "403|Please contact your GitLab administrator to get permission."
+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 "請確ä¿ç¶²å€æ­£ç¢ºä¸”網é æ²’被移動。"
msgid "404|Page Not Found"
-msgstr "找ä¸åˆ°ç¶²é "
+msgstr "未找到é é¢"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr "如果您èªç‚ºé€™æ˜¯å€‹éŒ¯èª¤ï¼Œè«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡ã€‚"
+msgstr "若您èªç‚ºé€™ä¸æ‡‰ç™¼ç”Ÿï¼Œè«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡ã€‚"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 <a href=\"#\">@johnsmith</a>ã€ä¸¦å°‡åŽŸæœ¬åˆ†é…給 johnsmith@example.com 的所有議題設定 <a href=\"#\">@johnsmith</a> 為å—讓人。"
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 <a href=\"#\">@johnsmith</a>ã€ä¸¦å°‡åŽŸæœ¬åˆ†é…給 johnsmith@example.com 的所有議題設定 <a href=\"#\">@johnsmith</a> 為被指派者。"
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 John Smithã€ã€‚"
@@ -260,49 +300,49 @@ msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will ad
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 <a href=\"#\">johnsmith@example.com</a>ã€ã€‚é è¨­ç‹€æ…‹é›»å­ä¿¡ç®±ä½å€æˆ–使用者å稱將被é®è”½ä»¥ä¿è­·ä½¿ç”¨è€…çš„éš±ç§å®‰å…¨ï¼Œå¦‚果您想è¦é¡¯ç¤ºå®Œæ•´çš„é›»å­ä¿¡ç®±ä½å€ï¼Œè«‹ä½¿ç”¨æ­¤é¸é …。"
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr "<strong>%{changedFilesLength} 個未暫存</strong>和 <strong>%{stagedFilesLength} 個已暫存</strong> 變更"
+msgstr "<strong>%{changedFilesLength} 個未暫存</strong>和 <strong>%{stagedFilesLength} 個已暫存</strong>變更"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
-msgstr "已建立 <strong>%{created_count}</strong> 個和åŒæ„ <strong>%{accepted_count}</strong> 個。"
+msgstr "已建立 <strong>%{created_count}</strong> 個,已接å—<strong>%{accepted_count}</strong> 個。"
msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
-msgstr "建立 <strong>%{created_count}</strong> 個和關閉 <strong>%{closed_count}</strong> 個。"
+msgstr "已建立 <strong>%{created_count}</strong> 個,已關閉 <strong>%{closed_count}</strong> 個。"
msgid "<strong>%{group_name}</strong> group members"
-msgstr "<strong>%{group_name}</strong> 群組æˆå“¡"
+msgstr "<strong>%{group_name}</strong> 群組的æˆå“¡"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
-msgstr "æŽ¨é€ <strong>%{pushes}</strong> 個,<strong>%{people}</strong> 個貢ç»è€…æäº¤äº†è¶…éŽ <strong>%{commits}</strong> 個æ交。"
+msgstr "å·²æŽ¨é€ <strong>%{pushes}</strong> 個,<strong>%{people}</strong> ä½è²¢ç»è€…æäº¤äº†è¶…éŽ <strong>%{commits}</strong> 個æ交。"
-msgid "<strong>Removes</strong> source branch"
-msgstr "<strong>移除</strong>來æºåˆ†æ”¯"
+msgid "<strong>Deletes</strong> source branch"
+msgstr ""
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "一個「執行器ã€æ˜¯ä¸€å€‹åŸ·è¡Œå·¥ä½œçš„程åºã€‚ä½ å¯ä»¥è¨­å®šä½ æ‰€éœ€çš„執行器數é‡ã€‚"
+msgstr "「執行器ã€æ˜¯å€‹ç”¨ä¾†åŸ·è¡Œä½œæ¥­çš„程å¼ã€‚你能設定你所需的多個執行器。"
msgid "A collection of graphs regarding Continuous Integration"
-msgstr "Continuous æ•´åˆç›¸é—œåœ–表"
+msgstr "ä¸é–“æ–·æ•´åˆçš„圖表集åˆ"
msgid "A default branch cannot be chosen for an empty project."
-msgstr "無法å°ä¸€å€‹ç©ºå°ˆæ¡ˆé¸å®šé è¨­åˆ†æ”¯ã€‚"
+msgstr "無法å°ä¸€å€‹ç©ºå°ˆæ¡ˆé¸æ“‡é è¨­åˆ†æ”¯ã€‚"
msgid "A deleted user"
-msgstr "已刪除的使用者"
+msgstr "已刪除使用者"
msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr ""
+msgstr "GitLab 濫用檢閱團隊的æˆå“¡å°‡æœƒç›¡å¿«æª¢é–±ä½ çš„回報。"
msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "將會在您的分支中建立一個新的分支,並建立一個新的åˆä½µè«‹æ±‚。"
+msgstr "將會在您的 fork 中建立一個新分支,並開啟新的åˆä½µè«‹æ±‚。"
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "專案å¯ä»¥è®“你存放您的檔案(版本庫)ã€è¨ˆåŠƒæ‚¨çš„工作(議題)與發佈文件(Wiki),還有 %{among_other_things_link}。"
+msgstr "專案å¯è®“您存放檔案(版本庫)ã€è¨ˆåŠƒå·¥ä½œï¼ˆè­°é¡Œï¼‰ã€ç™¼ä½ˆæª”案(Wiki),還有這些:%{among_other_things_link}。"
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
-msgstr "æ­£è¦è¡¨é”å¼å°‡æœƒç”¨ä¾†å°‹æ‰¾å·¥ä½œè¿½è¹¤ä¸­çš„測試覆蓋輸出。留白以åœç”¨"
+msgstr "æ­£è¦è¡¨ç¤ºå¼å°‡æœƒç”¨ä¾†å°‹æ‰¾ä½œæ¥­è¿½è¹¤ä¸­çš„測試涵蓋範åœè¼¸å‡ºã€‚留空å³åœç”¨æ­¤åŠŸèƒ½ã€‚"
msgid "A user with write access to the source branch selected this option"
-msgstr "一個有來æºåˆ†æ”¯å¯«å…¥æ¬Šé™çš„使用者é¸æ“‡äº†é€™å€‹é¸é …"
+msgstr "一ä½æœ‰ä¾†æºåˆ†æ”¯å¯«å…¥æ¬Šé™çš„使用者é¸æ“‡äº†é€™å€‹é¸é …"
msgid "About GitLab"
msgstr "關於 GitLab"
@@ -317,10 +357,13 @@ msgid "About this feature"
msgstr "關於此功能"
msgid "Abuse Reports"
-msgstr "回報濫用"
+msgstr "濫用回報"
msgid "Abuse reports"
-msgstr "回報濫用"
+msgstr "濫用回報"
+
+msgid "Accept invitation"
+msgstr ""
msgid "Accept terms"
msgstr "接å—æ¢æ¬¾"
@@ -332,25 +375,25 @@ msgid "Access Tokens"
msgstr "å­˜å–憑證"
msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "å­˜å–被拒ï¼è«‹ç¢ºèªæ‚¨æ˜¯å¦å¯ä»¥åœ¨æ­¤ç‰ˆæœ¬åº«éƒ¨å±¬é‡‘鑰。"
+msgstr "å­˜å–被拒ï¼è«‹æª¢æŸ¥æ‚¨æ˜¯å¦å¯ä»¥åœ¨æ­¤ç‰ˆæœ¬åº«éƒ¨å±¬é‡‘鑰。"
msgid "Access expiration date"
msgstr "å­˜å–éŽæœŸæ—¥æœŸ"
msgid "Access to '%{classification_label}' not allowed"
-msgstr "ä¸å…許存å–「%{classification_label}ã€"
+msgstr "您ä¸å…許存å–「%{classification_label}ã€"
msgid "Account"
msgstr "帳號"
msgid "Account and limit"
-msgstr "帳戶與é™åˆ¶"
+msgstr "帳號與é™åˆ¶"
msgid "Active"
-msgstr "啟用"
+msgstr "使用中"
msgid "Active Sessions"
-msgstr "連線階段"
+msgstr "使用中階段"
msgid "Activity"
msgstr "活動"
@@ -358,68 +401,77 @@ msgstr "活動"
msgid "Add"
msgstr "新增"
-msgid "Add Changelog"
-msgstr "新增變更記錄"
+msgid "Add CHANGELOG"
+msgstr ""
-msgid "Add Contribution guide"
-msgstr "新增貢ç»æŒ‡å—"
+msgid "Add CONTRIBUTING"
+msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "新增群組 Webhook å’Œ GitLab ä¼æ¥­ç‰ˆæœ¬ã€‚"
msgid "Add Jaeger URL"
-msgstr ""
+msgstr "新增 Jaeger 網å€"
msgid "Add Kubernetes cluster"
-msgstr "增加 Kubernetes å¢é›†"
+msgstr "新增 Kubernetes å¢é›†"
-msgid "Add Readme"
-msgstr "增加說明檔案"
+msgid "Add README"
+msgstr ""
-msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgid "Add a general comment to this %{noteable_name}."
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr "在 Wiki 中新增包å«æ‚¨å°ˆæ¡ˆç›¸é—œè³‡è¨Šçš„首é ï¼Œä¹‹å¾Œ GitLab 將會顯示 Wiki 首é æ–¼æ­¤è™•è€Œéžé€™å‰‡è¨Šæ¯ã€‚"
+
msgid "Add a table"
-msgstr ""
+msgstr "新增表格"
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
-msgstr "增加顯示於所有電å­éƒµä»¶å°è©±çš„附加文字。最多 %{character_limit} 個字元。"
+msgstr "新增顯示於所有電å­éƒµä»¶å°è©±çš„附加文字。最多 %{character_limit} 個字元。"
msgid "Add comment now"
-msgstr ""
+msgstr "ç«‹å³ç•™è¨€"
msgid "Add image comment"
-msgstr ""
+msgstr "增加圖片留言"
msgid "Add license"
-msgstr "新增授權"
+msgstr "新增授權資訊"
msgid "Add new application"
-msgstr "建立新應用程å¼"
+msgstr "新增應用程å¼"
msgid "Add new directory"
-msgstr "建立新目錄"
+msgstr "新增資料夾"
msgid "Add projects"
-msgstr ""
+msgstr "新增專案"
msgid "Add reaction"
-msgstr "建立回應"
+msgstr "新增回應"
-msgid "Add to review"
+msgid "Add to project"
msgstr ""
+msgid "Add to review"
+msgstr "新增è¦åŠ å…¥åˆ°æª¢é–±çš„內容"
+
msgid "Add todo"
-msgstr "建立待辦事項"
+msgstr "新增待辦事項"
msgid "Add user(s) to the group:"
msgstr "將使用者加到群組:"
+msgid "Add users or groups who are allowed to approve every merge request"
+msgstr ""
+
msgid "Add users to group"
msgstr "將使用者加到群組"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
-msgstr "您的 GitLab 實例已經åœç”¨ã€Œå»ºç«‹æ–°æ‡‰ç”¨ç¨‹å¼ã€åŠŸèƒ½ã€‚è«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡ä»¥å–得此權é™"
+msgstr "您的 GitLab 執行個體已åœç”¨ã€Œæ–°å¢žæ‡‰ç”¨ç¨‹å¼ã€åŠŸèƒ½ã€‚è«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡å–得新增權é™"
msgid "Additional text"
msgstr "附加文字"
@@ -430,129 +482,198 @@ msgstr "管ç†å€å¡Š"
msgid "Admin Overview"
msgstr "管ç†æ¦‚覽"
-msgid "Admin area"
-msgstr "管ç†å€å¡Š"
-
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr "您正打算永久刪除 %{username} 使用者。連çµä»–們的議題ã€åˆä½µè«‹æ±‚與群組將會移轉到系統全域的一ä½ä½¿ç”¨è€…「Ghost-userã€ã€‚è‹¥è¦é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strong_start}å°éŽ–使用者%{strong_end}功能。當你執行了%{strong_start}刪除使用者%{strong_end},則該動作將無法復原。"
+msgstr "您正打算永久刪除 %{username} 使用者。連çµåˆ°é€™äº›ä½¿ç”¨è€…çš„è­°é¡Œã€åˆä½µè«‹æ±‚與群組將會移轉到系統全域的使用者「Ghost-userã€ã€‚è‹¥è¦é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strong_start}å°éŽ–使用者%{strong_end}功能,因為%{strong_start}刪除使用者%{strong_end} 動作一執行就無法復原。"
msgid "AdminArea| 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr "您正打算永久刪除 %{username} 使用者。這將會刪除連çµä»–們的議題ã€åˆä½µè«‹æ±‚與群組。若è¦é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strong_start}å°éŽ–使用者%{strong_end}功能。當你執行了%{strong_start}刪除使用者%{strong_end},則該動作將無法復原。"
+msgstr "您正打算永久刪除 %{username} 使用者。這將會刪除連çµåˆ°é€™äº›ä½¿ç”¨è€…的所有議題ã€åˆä½µè«‹æ±‚與群組。若è¦é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strong_start}å°éŽ–使用者%{strong_end}功能,因為%{strong_start}刪除使用者%{strong_end}動作一執行就無法復原。"
msgid "AdminArea|Stop all jobs"
-msgstr "åœæ­¢æ‰€æœ‰ä»»å‹™"
+msgstr "åœæ­¢æ‰€æœ‰ä½œæ¥­"
msgid "AdminArea|Stop all jobs?"
-msgstr "è¦åœæ­¢æ‰€æœ‰ä»»å‹™å—Žï¼Ÿ"
+msgstr "確定åœæ­¢æ‰€æœ‰ä½œæ¥­ï¼Ÿ"
msgid "AdminArea|Stop jobs"
-msgstr "åœæ­¢ä»»å‹™"
+msgstr "åœæ­¢ä½œæ¥­"
msgid "AdminArea|Stopping jobs failed"
-msgstr "åœæ­¢ä»»å‹™å¤±æ•—"
+msgstr "åœæ­¢ä½œæ¥­å¤±æ•—"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
-msgstr "您打算è¦åœæ­¢æ‰€æœ‰ä»»å‹™ï¼Œé€™å°‡æœƒæš«åœæ‰€æœ‰æ­£åœ¨åŸ·è¡Œä¸­çš„任務。"
+msgstr "您正打算åœæ­¢æ‰€æœ‰ä½œæ¥­ï¼Œé€™å°‡æš«åœæ‰€æœ‰æ­£åœ¨åŸ·è¡Œä¸­çš„作業。"
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr "您正打算永久刪除 %{projectName} 專案ã€èˆ‡å…¶ç‰ˆæœ¬åº«ã€å’Œæ‰€æœ‰ç›¸é—œçš„資æºï¼Œä¾‹å¦‚è­°é¡Œã€åˆä½µè«‹æ±‚等等…當您確èªä¸¦æŒ‰ä¸‹%{strong_start}刪除專案%{strong_end},該動作將無法復原。"
+msgstr "您正打算永久刪除 %{projectName} 專案與其版本庫ã€å’Œæ‰€æœ‰ç›¸é—œçš„資æºï¼ŒåŒ…å«è­°é¡Œã€åˆä½µè«‹æ±‚等等…當您確èªä¸¦æŒ‰ä¸‹%{strong_start}刪除專案%{strong_end},將無法復原此動作。"
msgid "AdminProjects|Delete"
msgstr "刪除"
msgid "AdminProjects|Delete Project %{projectName}?"
-msgstr "刪除專案 %{projectName} ?"
+msgstr "刪除專案 %{projectName}?"
msgid "AdminProjects|Delete project"
msgstr "刪除專案"
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
-msgstr "為æ¯å€‹å°ˆæ¡ˆçš„自動審閱應用程å¼åŠè‡ªå‹•éƒ¨ç½²éšŽæ®µæŒ‡å®šä¸€å€‹é è¨­çš„網域"
+msgstr "å°æ¯å€‹å°ˆæ¡ˆçš„「自動檢閱應用程å¼ç¨‹å¼ã€å’Œã€Œè‡ªå‹•éƒ¨å±¬éšŽæ®µã€æŒ‡å®šé è¨­ç¶²åŸŸã€‚"
+
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
msgid "AdminUsers|Block user"
msgstr "å°éŽ–使用者"
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
msgid "AdminUsers|Delete User %{username} and contributions?"
-msgstr "刪除使用者 %{username} åŠå…¶è²¢ç»ï¼Ÿ"
+msgstr "刪除使用者 %{username} åŠå…¶è²¢ç»è¨˜éŒ„?"
msgid "AdminUsers|Delete User %{username}?"
-msgstr "刪除使用者 %{username} ?"
+msgstr "刪除使用者 %{username}?"
msgid "AdminUsers|Delete user"
msgstr "刪除使用者"
msgid "AdminUsers|Delete user and contributions"
-msgstr "刪除使用者åŠå…¶è²¢ç»"
+msgstr "刪除使用者åŠå…¶è²¢ç»è¨˜éŒ„"
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
msgid "AdminUsers|To confirm, type %{projectName}"
-msgstr "請輸入 %{projectName} 進行確èª"
+msgstr "請輸入 %{projectName} 確èªæ­¤å‹•ä½œ"
msgid "AdminUsers|To confirm, type %{username}"
-msgstr "請輸入 %{username} 進行確èª"
+msgstr "請輸入 %{username} 確èªæ­¤å‹•ä½œ"
-msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
msgstr ""
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr "進階權é™ï¼Œã€ã€Œå¤§åž‹æª”案儲存空間 (LFS)ã€å’Œã€Œå…©æ­¥é©Ÿé©—è­‰ã€è¨­å®šã€‚"
+
msgid "Advanced settings"
msgstr "進階設定"
msgid "Alert"
msgid_plural "Alerts"
-msgstr[0] ""
+msgstr[0] "通知"
+
+msgid "Alerts"
+msgstr ""
msgid "All"
msgstr "全部"
msgid "All changes are committed"
-msgstr "所有變更都已經æ交"
+msgstr "å·²æ交所有變更"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "已經å°ç©ºç™½ã€ä¾†è‡ªæ¨¡æ¿æˆ–匯入的專案啟用了所有功能,但你能在之後於專案設定åœç”¨å®ƒå€‘。"
+msgstr "已經å°ç©ºç™½ã€ä¾†è‡ªæ¨¡æ¿ä»¥åŠåŒ¯å…¥çš„專案啟用所有功能,但您ä»ä¹‹å¾Œåœ¨ã€Œå°ˆæ¡ˆè¨­å®šã€åœç”¨ä¸æƒ³è¦çš„功能。"
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
msgid "All users"
msgstr "所有使用者"
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
-msgstr "å…許å¯ä»¥åˆä½µè‡³ç›®æ¨™åˆ†æ”¯çš„æˆå“¡æ交"
+msgstr "å…許能åˆä½µè‡³ç›®æ¨™åˆ†æ”¯çš„æˆå“¡æ交"
msgid "Allow projects within this group to use Git LFS"
-msgstr ""
+msgstr "å…許該群組中的專案使用 Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
-msgstr "å…許公開存å–æµæ°´ç·šå’Œä»»å‹™è©³ç´°è³‡è¨Šï¼ŒåŒ…å«è¼¸å‡ºæ—¥èªŒå’Œç”¢ç‰©"
+msgstr "å…許公開存å–管線和作業詳細資訊,包å«è¼¸å‡ºè¨˜éŒ„å’Œæˆå“"
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
-msgstr "å…許在 Asciidoc 文件中繪製 PlantUML64 圖。"
+msgstr "å…許在 Asciidoc 檔案繪製 PlantUML 圖片。"
msgid "Allow requests to the local network from hooks and services."
-msgstr "å…許來自觸發器和æœå‹™å°æœ¬æ©Ÿç¶²è·¯çš„請求。"
+msgstr "å…許觸發器和æœå‹™å‘本機網路傳é€è«‹æ±‚。"
msgid "Allow users to request access"
-msgstr ""
+msgstr "å…許使用者請求存å–權é™"
msgid "Allow users to request access if visibility is public or internal."
+msgstr "若為公開或內部å¯è¦‹ï¼Œå‰‡å…許使用者請求存å–權é™ã€‚"
+
+msgid "Allowed to fail"
msgstr ""
msgid "Allows you to add and manage Kubernetes clusters."
-msgstr "å…è¨±æ‚¨å¢žåŠ å’Œç®¡ç† Kubernetes å¢é›†ã€‚"
+msgstr "å…è¨±æ‚¨æ–°å¢žä¸¦ç®¡ç† Kubernetes å¢é›†ã€‚"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
-msgstr "也被稱為「議題æ“有者ã€æˆ–「ä¾è³´æ–¹ä¿¡ä»»èº«ä»½è­˜åˆ¥ã€"
+msgstr "也被稱為「議題開啟者ã€æˆ–「信賴憑證者信任識別碼ã€"
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
-msgstr "也稱為「ä¾è³´æ–¹æœå‹™ URLã€æˆ–「回覆 URLã€"
+msgstr "也稱為「信賴憑證者æœå‹™ URLã€æˆ–「回覆 URLã€"
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr "或者,你å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。當你建立你的個人存å–憑證時,你將需è¦é¸æ“‡<code>版本庫</code>範åœï¼Œæ‰€ä»¥æˆ‘們å¯ä»¥é¡¯ç¤ºä½ å¯ä»¥é€£ç·šä¹‹å…¬é–‹åŠç§å¯†çš„版本庫清單。"
+msgstr "或者,你能使用 %{personal_access_token_link} 連çµã€‚當你è¦å»ºç«‹å€‹äººå­˜å–憑證時,將需è¦é¸æ“‡<code>版本庫</code>範åœï¼Œæˆ‘們æ‰èƒ½é¡¯ç¤ºå¯é€£ç·šçš„公開åŠç§äººç‰ˆæœ¬åº«åˆ—表。"
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
-msgstr "或者,你å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。當你建立你的個人存å–憑證時,你將需è¦é¸æ“‡<code>版本庫</code>範åœï¼Œæ‰€ä»¥æˆ‘們將會顯示能匯入的公開åŠç§å¯†çš„版本庫清單。"
+msgstr "或者,你能使用 %{personal_access_token_link} 連çµã€‚當你è¦å»ºç«‹å€‹äººå­˜å–憑證時,將需è¦é¸æ“‡<code>版本庫</code>範åœï¼Œæˆ‘們æ‰èƒ½é¡¯ç¤ºå¯åŒ¯å…¥çš„公開åŠç§äººç‰ˆæœ¬åº«åˆ—表。"
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
-msgstr ""
+msgstr "å…許使用者跳éŽå¼·åˆ¶è¨­å®šå…©æ­¥é©Ÿé©—證的時間(å°æ™‚)"
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "æ交此表單時將會自動產生 SSH 金鑰。若須更多資訊請åƒè€ƒæ–‡ä»¶ã€‚"
+msgstr "æ交此表單時將會自動產生 SSH 金鑰。若須更多資訊請åƒè€ƒæª”案。"
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "一個自稱 %{link_to_client} 的應用程å¼è«‹æ±‚您 GitLab 帳號的存å–權。"
@@ -560,46 +681,19 @@ msgstr "一個自稱 %{link_to_client} 的應用程å¼è«‹æ±‚您 GitLab 帳號的
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "空的 GitLab 使用者欄ä½å°‡æœƒåœ¨æ‰€æœ‰è­°é¡Œèˆ‡èªªæ˜Žçš„說明欄增加 FogBugz 使用者的完整å稱 (例如:「來自 John Smithã€)。其也將與專案建立者關è¯ä¸¦ (或) 分é…這些議題以åŠç•™è¨€ã€‚"
-msgid "An error accured whilst committing your changes."
-msgstr "æ交您的變更時發生錯誤"
-
msgid "An error has occurred"
msgstr "發生了一個錯誤"
-msgid "An error occured creating the new branch."
-msgstr "創建新分支時發生錯誤。"
-
-msgid "An error occured whilst fetching the job trace."
-msgstr "å–得工作追蹤資訊時發生錯誤"
-
-msgid "An error occured whilst fetching the latest pipeline."
+msgid "An error occured while fetching the releases. Please try again."
msgstr ""
-msgid "An error occured whilst loading all the files."
-msgstr "讀å–檔案時發生錯誤。"
-
-msgid "An error occured whilst loading the file content."
-msgstr "讀å–檔案內容時發生錯誤。"
-
-msgid "An error occured whilst loading the file."
-msgstr "讀å–檔案時發生錯誤。"
-
-msgid "An error occured whilst loading the merge request changes."
-msgstr "讀å–åˆä½µè«‹æ±‚的更改時發生錯誤。"
-
-msgid "An error occured whilst loading the merge request version data."
-msgstr "讀å–åˆä½µè«‹æ±‚的版本資訊時發生錯誤。"
-
-msgid "An error occured whilst loading the merge request."
-msgstr "讀å–åˆä½µè«‹æ±‚時發生錯誤。"
-
-msgid "An error occured whilst loading the pipelines jobs."
-msgstr "載入æµæ°´ç·šå·¥ä½œçš„åŒæ™‚發生了錯誤"
-
msgid "An error occurred adding a draft to the discussion."
-msgstr ""
+msgstr "新增è‰ç¨¿åœ¨è¨Žè«–串時發生錯誤。"
msgid "An error occurred adding a new draft."
+msgstr "新增è‰ç¨¿æ™‚發生錯誤。"
+
+msgid "An error occurred creating the new branch."
msgstr ""
msgid "An error occurred previewing the blob"
@@ -615,22 +709,22 @@ msgid "An error occurred while adding approver"
msgstr "增加審核者時發生錯誤"
msgid "An error occurred while deleting the comment"
-msgstr ""
+msgstr "刪除留言時發生錯誤"
msgid "An error occurred while detecting host keys"
msgstr "åµæ¸¬ä¸»æ©Ÿé‡‘鑰時發生錯誤"
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
-msgstr "當解除通知時錯誤發生。請嘗試é‡æ–°æ•´ç†é é¢ä¸¦é‡è©¦ã€‚"
+msgstr "當關閉通知時發生錯誤。請嘗試é‡æ–°æ•´ç†é é¢ä¸¦é‡è©¦ã€‚"
msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
-msgstr "解除亮高顯示時發生錯誤,請é‡æ–°æ•´ç†é é¢å†æ¬¡å˜—試。"
+msgstr "解除çªé¡¯é¡¯ç¤ºæ™‚發生錯誤,請é‡æ–°æ•´ç†é é¢å¾Œå†æ¬¡å˜—試。"
msgid "An error occurred while fetching markdown preview"
-msgstr "è®€å– markdown é è¦½æ™‚發生錯誤"
+msgstr "å–å¾— Markdown é è¦½çµæžœæ™‚發生錯誤"
msgid "An error occurred while fetching pending comments"
-msgstr ""
+msgstr "讀å–待處ç†ç•™è¨€æ™‚發生錯誤"
msgid "An error occurred while fetching sidebar data"
msgstr "讀å–å´é‚Šæ¬„資料時發生錯誤"
@@ -639,7 +733,7 @@ msgid "An error occurred while fetching stages."
msgstr "抓å–狀態時發生錯誤。"
msgid "An error occurred while fetching the job log."
-msgstr "抓å–工作日誌時發生錯誤。"
+msgstr "抓å–工作記錄時發生錯誤。"
msgid "An error occurred while fetching the job."
msgstr "抓å–工作時發生錯誤。"
@@ -648,10 +742,10 @@ msgid "An error occurred while fetching the jobs."
msgstr "抓å–工作時發生錯誤。"
msgid "An error occurred while fetching the pipeline."
-msgstr "讀å–æµæ°´ç·šæ™‚發生錯誤"
+msgstr "讀å–管線時發生錯誤"
msgid "An error occurred while getting projects"
-msgstr "讀å–專案時發生錯誤"
+msgstr "å–得專案時發生錯誤"
msgid "An error occurred while importing project: %{details}"
msgstr "匯入專案時發生錯誤:%{details}"
@@ -660,7 +754,7 @@ msgid "An error occurred while initializing path locks"
msgstr "åˆå§‹åŒ–路徑鎖時發生錯誤"
msgid "An error occurred while loading chart data"
-msgstr ""
+msgstr "讀å–圖表資料時發生錯誤"
msgid "An error occurred while loading commit signatures"
msgstr "載入æ交簽å時發生錯誤"
@@ -669,28 +763,37 @@ msgid "An error occurred while loading diff"
msgstr "讀å–差異檔時發生錯誤"
msgid "An error occurred while loading filenames"
-msgstr "讀å–檔案å稱時發生錯誤"
+msgstr "載入檔案å稱時發生錯誤"
msgid "An error occurred while loading the file"
msgstr "讀å–檔案時發生錯誤"
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
msgid "An error occurred while making the request."
msgstr "建立請求時發生錯誤"
msgid "An error occurred while removing approver"
msgstr "刪除審核者時發生錯誤"
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
-msgstr "渲染 KaTex 時發生錯誤"
+msgstr "繪製 KaTex 時發生錯誤"
msgid "An error occurred while rendering preview broadcast message"
-msgstr "在產生廣播消æ¯æ™‚發生錯誤"
+msgstr "在繪製é è¦½å»£æ’­è¨Šæ¯æ™‚發生錯誤"
msgid "An error occurred while retrieving calendar activity"
-msgstr "讀å–行事曆時發生錯誤"
+msgstr "讀å–行事曆活動時發生錯誤"
msgid "An error occurred while retrieving diff"
-msgstr "讀å–差異檔時發生錯誤"
+msgstr "接收差異檔時發生錯誤"
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr "儲存 LDAP 覆蓋狀態時發生錯誤,請é‡è©¦ã€‚"
@@ -705,17 +808,62 @@ msgid "An error occurred while unsubscribing to notifications."
msgstr "當å–消訂閱通知時發生錯誤"
msgid "An error occurred while updating the comment"
-msgstr ""
+msgstr "更新留言時發生錯誤"
msgid "An error occurred while validating username"
msgstr "驗證使用者å稱時發生錯誤"
+msgid "An error occurred whilst committing your changes."
+msgstr ""
+
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "發生錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
-msgid "Analytics"
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
msgstr ""
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "Analytics"
+msgstr "分æž"
+
msgid "Anonymous"
msgstr "匿å"
@@ -735,7 +883,7 @@ msgid "Application"
msgstr "應用程å¼"
msgid "Application ID"
-msgstr ""
+msgstr "æ‡‰ç”¨ç¨‹å¼ ID"
msgid "Application: %{name}"
msgstr "應用程å¼ï¼š%{name}"
@@ -743,6 +891,21 @@ msgstr "應用程å¼ï¼š%{name}"
msgid "Applications"
msgstr "應用程å¼"
+msgid "Applied"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Approvals"
+msgstr ""
+
+msgid "Approvals required"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
msgid "Apr"
msgstr "四月"
@@ -750,49 +913,67 @@ msgid "April"
msgstr "四月"
msgid "Archived project! Repository and other project resources are read-only"
-msgstr "這是個已經å°å­˜çš„專案ï¼å…¶æª”案庫與其其他專案資æºç‚ºå”¯è®€ç‹€æ…‹ã€‚"
+msgstr "這是個已經å°å­˜çš„專案ï¼å…¶ç‰ˆæœ¬åº«èˆ‡å…¶å…¶ä»–專案資æºç‚ºå”¯è®€ç‹€æ…‹ã€‚"
msgid "Archived projects"
msgstr "å·²å°å­˜çš„專案"
+msgid "Are you sure"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
-msgstr "確定è¦åˆªé™¤æ­¤æµæ°´ç·šæŽ’程嗎?"
+msgstr "確定è¦åˆªé™¤æ­¤æŽ’程管線嗎?"
msgid "Are you sure you want to erase this build?"
-msgstr ""
+msgstr "你確定è¦åˆªé™¤é€™å€‹ç‰ˆæœ¬å—Žï¼Ÿ"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "您確定è¦æ”¾æ£„未儲存的變更嗎?"
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "確èªé‡æ–°ç”¢ç”Ÿå…¬é‘°ï¼Ÿæ‚¨å°‡éœ€è¦åœ¨é‡æ–°é‹ä½œé¡åƒå‰ï¼Œæ›´æ–°é ç«¯ä¼ºæœå™¨ä¸Šçš„公鑰。"
msgid "Are you sure you want to remove %{group_name}?"
msgstr "確定移除 %{group_name}?"
+msgid "Are you sure you want to remove approver %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove group %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
msgid "Are you sure you want to remove this identity?"
msgstr "您確定è¦åˆªé™¤æ­¤èº«ä»½å—Ž?"
msgid "Are you sure you want to reset registration token?"
-msgstr "確定è¦é‡ç½®è¨»å†Šæ†‘證嗎?"
+msgstr "確定è¦é‡è¨­è¨»å†Šæ†‘證嗎?"
msgid "Are you sure you want to reset the health check token?"
-msgstr "確定è¦é‡ç½®å¥åº·æª¢æŸ¥å­˜å–憑證嗎?"
+msgstr "確定è¦é‡è¨­å¥åº·æª¢æŸ¥å­˜å–憑證嗎?"
msgid "Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "確定è¦åœæ­¢æ­¤ç’°å¢ƒå—Žï¼Ÿ"
msgid "Are you sure you want to unlock %{path_lock_path}?"
-msgstr "你確定è¦è§£éŽ– %{path_lock_path} ?"
+msgstr "你確定è¦è§£éŽ– %{path_lock_path}?"
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
msgid "Are you sure?"
-msgstr "確定嗎?"
+msgstr "確定?"
msgid "Artifact ID"
msgstr "æˆå“ ID"
msgid "Artifacts"
-msgstr "產物"
+msgstr "æˆå“"
msgid "Ascending"
msgstr "é †åº"
@@ -803,8 +984,11 @@ msgstr "è©¢å•æ‚¨çš„群組維護者以安è£ç¾¤çµ„執行器。"
msgid "Assertion consumer service URL"
msgstr "Assertion 客戶æœå‹™é€£çµ"
+msgid "Assets"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
-msgstr "自定義é¡è‰²ï¼Œä¾‹å¦‚ #FF0000"
+msgstr "指定自訂é¡è‰²ï¼Œä¾‹å¦‚ #FF0000"
msgid "Assign labels"
msgstr "指派標籤"
@@ -812,8 +996,11 @@ msgstr "指派標籤"
msgid "Assign milestone"
msgstr "指派里程碑"
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
-msgstr "指派給"
+msgstr "指派å°è±¡"
msgid "Assigned Issues"
msgstr "已指派的議題"
@@ -839,8 +1026,11 @@ msgstr "指派列表顯示了分é…給é¸å®šä½¿ç”¨è€…的所有議題"
msgid "Assignee(s)"
msgstr "執行者"
+msgid "Attach a file"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
-msgstr "拖放檔案到此處或者 %{upload_link}"
+msgstr "拖放檔案或者使用 %{upload_link} 連çµé™„加檔案"
msgid "Audit Events"
msgstr "審計活動"
@@ -851,8 +1041,11 @@ msgstr "八月"
msgid "August"
msgstr "八月"
+msgid "Auth Token"
+msgstr ""
+
msgid "Authentication Log"
-msgstr "登入紀錄"
+msgstr "驗證紀錄"
msgid "Authentication log"
msgstr "èªè­‰è¨˜éŒ„"
@@ -866,6 +1059,9 @@ msgstr "作者"
msgid "Authorization code:"
msgstr "授權碼:"
+msgid "Authorization key"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr "é€éŽåœ¨æ‡‰ç”¨ç¨‹å¼ä¸­è¼¸å…¥æ‚¨çš„使用者帳號與密碼,以給予授權權é™ã€‚"
@@ -893,41 +1089,32 @@ msgstr "啟動自動 DevOps"
msgid "Auto DevOps, runners and job artifacts"
msgstr "自動 DevOpsã€åŸ·è¡Œå™¨èˆ‡å·¥ä½œç”¢å‡ºç‰©"
-msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr "自動複閱應用åŠè‡ªå‹•éƒ¨ç½²éœ€è¦ %{kubernetes} æ‰èƒ½æ­£å¸¸å·¥ä½œã€‚"
-
-msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr "自動復閱åŠè‡ªå‹•éƒ¨ç½²éœ€è¦ä¸€å€‹ç¶²åŸŸå’Œ %{kubernetes} æ‰èƒ½æ­£å¸¸å·¥ä½œ"
-
-msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr "自動複閱應用與自動部署需è¦ç¶²åŸŸæ‰èƒ½é‹ä½œã€‚"
-
msgid "Auto-cancel redundant, pending pipelines"
-msgstr "自動å–消多餘ã€å¾…處ç†çš„æµæ°´ç·š"
+msgstr "自動å–消多餘ã€å¾…處ç†çš„管線"
msgid "AutoDevOps|Auto DevOps"
msgstr "自動 DevOps"
msgid "AutoDevOps|Auto DevOps documentation"
-msgstr "「DevOps 自動化〠文件"
+msgstr "「自動 DevOpsã€èªªæ˜Žæ–‡ä»¶"
msgid "AutoDevOps|Enable in settings"
msgstr "在設定中啟用"
msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
-msgstr "將根據設定的的 CI / CD æµç¨‹è‡ªå‹•å»ºæ§‹ã€æ¸¬è©¦å’Œéƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ã€‚"
+msgstr "將根據é å…ˆè¨­å®šçš„ CI / CD 組態檔案來自動編譯ã€æ¸¬è©¦ä»¥åŠéƒ¨å±¬æ‚¨çš„應用程å¼ã€‚"
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
-msgstr "了解更多於 %{link_to_documentation}"
+msgstr "在 %{link_to_documentation} 了解更多"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr "自動 DevOps æµæ°´ç·šå·²ç¶“啟用,且會在沒有替代 CI 組態檔案å¯ç”¨çš„情æ³ä¸‹ä½¿ç”¨ã€‚%{more_information_link}"
+msgstr "自動 DevOps 管線已經啟用,且會在沒有替代 CI 組態檔案å¯ç”¨çš„情æ³ä¸‹ä½¿ç”¨ã€‚%{more_information_link}"
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr "如果 %{link_to_auto_devops_settings} 這個專案,您å¯ä»¥è‡ªå‹•å»ºç½®å’Œæ¸¬è©¦ä½ çš„æ‡‰ç”¨ç¨‹å¼ %{link_to_add_kubernetes_cluster} 則å¯ä»¥è®“你自動部署"
msgid "AutoDevOps|add a Kubernetes cluster"
-msgstr "添加 Kubernetes å¢é›†"
+msgstr "新增 Kubernetes å¢é›†"
msgid "AutoDevOps|enable Auto DevOps"
msgstr "啟用自動 DevOps"
@@ -935,17 +1122,29 @@ msgstr "啟用自動 DevOps"
msgid "Automatically marked as default internal user"
msgstr "自動標記為é è¨­æœ¬æ©Ÿä½¿ç”¨è€…"
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
-msgstr "能é‹åšçš„"
+msgstr "å¯ä½¿ç”¨çš„"
+
+msgid "Available group Runners: %{runners}"
+msgstr ""
-msgid "Available group Runners : %{runners}"
-msgstr "å¯ä½¿ç”¨çš„群組執行器:%{runners}"
+msgid "Available shared Runners:"
+msgstr ""
-msgid "Available group Runners : %{runners}."
-msgstr "å¯ä½¿ç”¨çš„群組執行器:%{runners}。"
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
msgid "Avatar will be removed. Are you sure?"
-msgstr "大頭貼將被刪除。你確定嗎?"
+msgstr "將移除大頭貼。確定?"
msgid "Average per day: %{average}"
msgstr "å¹³å‡æ¯å¤©ï¼š%{average}"
@@ -963,7 +1162,7 @@ msgid "Badges"
msgstr "徽章"
msgid "Badges|A new badge was added."
-msgstr "添加了新的徽章"
+msgstr "新增了新的徽章"
msgid "Badges|Add badge"
msgstr "新增徽章"
@@ -1038,19 +1237,19 @@ msgid "Badges|e.g. %{exampleUrl}"
msgstr "例如 %{exampleUrl}"
msgid "BatchComments|Delete all pending comments"
-msgstr ""
+msgstr "刪除所有待處ç†çš„留言"
msgid "BatchComments|Discard review?"
-msgstr ""
+msgstr "放棄檢閱?"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
-msgstr ""
+msgstr "ä½ å³å°‡æ”¾æ£„你的檢閱,這將刪除所有待處ç†çš„留言。刪除的留言 %{strong_start} ä¸èƒ½ %{strong_end} 復原。"
msgid "Begin with the selected commit"
-msgstr "從é¸å®šçš„變更紀錄開始"
+msgstr "從é¸å®šçš„æ交記錄開始"
msgid "Below are examples of regex for existing tools:"
-msgstr "以下是ç¾æœ‰å·¥å…·çš„æ­£è¦è¡¨é”å¼ç¤ºä¾‹ï¼š"
+msgstr "以下是ç¾æœ‰å·¥å…·çš„æ­£è¦è¡¨ç¤ºå¼ç¯„例:"
msgid "Below you will find all the groups that are public."
msgstr "您將會在底下找到所有公開的群組。"
@@ -1086,7 +1285,7 @@ msgid "BillingPlans|Please contact %{customer_support_link} in that case."
msgstr "在這情æ³ä¸‹ï¼Œè«‹è¯ç¹« %{customer_support_link}"
msgid "BillingPlans|See all %{plan_name} features"
-msgstr "查看更多 %{plan_name} 功能"
+msgstr "檢視更多 %{plan_name} 功能"
msgid "BillingPlans|This group uses the plan associated with its parent group."
msgstr "此群組使用和上層群組相關的方案。"
@@ -1127,6 +1326,12 @@ msgstr "匯入 BitBucket 伺æœå™¨"
msgid "Bitbucket import"
msgstr "匯入 Bitbucket"
+msgid "Block"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr "部è½æ ¼"
@@ -1134,20 +1339,16 @@ msgid "Boards"
msgstr "看æ¿"
msgid "Branch %{branchName} was not found in this project's repository."
-msgstr "在這個專案的檔案庫中找ä¸åˆ° %{branchName} 分支。"
-
-msgid "Branch (%{branch_count})"
-msgid_plural "Branches (%{branch_count})"
-msgstr[0] "分支 (%{branch_count})"
+msgstr "在這個專案的版本庫中找ä¸åˆ° %{branchName} 分支。"
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "已建立分支 <strong>%{branch_name}</strong> 。如需設定自動部署, 在é¸æ“‡åˆé©çš„ GitLab CI Yaml 模æ¿å¾Œï¼Œè«‹æ交您的編輯內容。%{link_to_autodeploy_doc}"
+msgstr "已建立分支 <strong>%{branch_name}</strong>。如需設定自動部署,請在é¸æ“‡ GitLab CI Yaml 模æ¿å¾Œæ交您的變更。å¯åƒé–±ï¼š%{link_to_autodeploy_doc}"
msgid "Branch has changed"
msgstr "分支已變更"
msgid "Branch is already taken"
-msgstr "分支已經被更新éŽã€‚"
+msgstr "å·²é¸æ“‡æ­¤åˆ†æ”¯ã€‚"
msgid "Branch name"
msgstr "分支å稱"
@@ -1171,34 +1372,34 @@ msgid "Branches|All"
msgstr "全部"
msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "找ä¸åˆ°æ­¤åˆ†æ”¯çš„ HEAD 更動。"
+msgstr "找ä¸åˆ°æ­¤åˆ†æ”¯çš„ HEAD æ交。"
msgid "Branches|Compare"
msgstr "比較"
msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
-msgstr "移除所有已經åˆä½µåˆ° %{default_branch} 的分支。"
+msgstr "刪除所有已經åˆä½µåˆ°ã€Œ%{default_branch}ã€åˆ†æ”¯çš„分支。"
msgid "Branches|Delete branch"
-msgstr "移除分支"
+msgstr "刪除分支"
msgid "Branches|Delete merged branches"
-msgstr "移除已經åˆä½µçš„分支"
+msgstr "刪除已åˆä½µåˆ†æ”¯"
msgid "Branches|Delete protected branch"
-msgstr "移除å—ä¿è­·çš„分支"
+msgstr "刪除å—ä¿è­·åˆ†æ”¯"
msgid "Branches|Delete protected branch '%{branch_name}'?"
-msgstr "確定移除å—ä¿è­·çš„分支 %{branch_name} ?"
+msgstr "確定刪除å—ä¿è­·åˆ†æ”¯ %{branch_name}?"
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
-msgstr "移除 %{branch_name} 分支將無法還原,確定嗎?"
+msgstr "移除 %{branch_name} 將無法復原分支,確定嗎?"
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 "å·²åˆä½µè‡³ %{default_branch}"
@@ -1207,13 +1408,13 @@ msgid "Branches|New branch"
msgstr "新增分支"
msgid "Branches|No branches to show"
-msgstr "找ä¸åˆ°åˆ†æ”¯"
+msgstr "未找到分支"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
-msgstr "一旦你確èªä¸¦æŒ‰ä¸‹ %{delete_protected_branch} 之後,此動作將無法撤銷或還原。"
+msgstr "一旦你確èªä¸¦æŒ‰ä¸‹ %{delete_protected_branch} 之後,此動作將無法復原。"
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
-msgstr "åªæœ‰å°ˆæ¡ˆç¶­è­·è€…或æ“有者å¯ä»¥ç§»é™¤å—ä¿è­·çš„分支。"
+msgstr "åªæœ‰å°ˆæ¡ˆç¶­è­·è€…或所有者å¯ä»¥ç§»é™¤å—ä¿è­·çš„分支。"
msgid "Branches|Overview"
msgstr "概覽"
@@ -1231,22 +1432,22 @@ msgid "Branches|Show more active branches"
msgstr "顯示更多活èºçš„分支"
msgid "Branches|Show more stale branches"
-msgstr "顯示更多沉éœçš„分支"
+msgstr "顯示更多éŽæ™‚分支"
msgid "Branches|Show overview of the branches"
msgstr "顯示分支概覽"
msgid "Branches|Show stale branches"
-msgstr "顯示沉éœçš„分支"
+msgstr "顯示éŽæ™‚分支"
msgid "Branches|Sort by"
-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 "分支無法自動更新,因為與上游分支存在差異。"
@@ -1255,19 +1456,19 @@ msgid "Branches|The default branch cannot be deleted"
msgstr "無法刪除é è¨­åˆ†æ”¯"
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
-msgstr "這個分支尚未åˆä½µåˆ° %{default_branch}"
+msgstr "這個分支尚未åˆä½µåˆ° %{default_branch}。"
msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr "為é¿å…資料éºå¤±ï¼Œè«‹åˆä½µè©²åˆ†æ”¯å¾Œå†å°‡å®ƒåˆªé™¤ã€‚"
+msgstr "為é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®å…ˆåˆä½µè©²åˆ†æ”¯å¾Œå†åˆªé™¤ã€‚"
msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-msgstr "請輸入 %{branch_name_confirmation} ä»¥é€²è¡Œç¢ºèª ï¼š"
+msgstr "請輸入 %{branch_name_confirmation} 確èªå‹•ä½œï¼š"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "è‹¥è¦æ”¾æ£„本機變更並使用上游版本覆寫這個分支,請先從這裡刪除å†æŒ‰ä¸‹ä¸Šæ–¹çš„「立刻更新ã€ã€‚"
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
-msgstr "你將永久刪除å—ä¿è­·çš„ %{branch_name} 分支。"
+msgstr "你正打算永久刪除å—ä¿è­·çš„ %{branch_name} 分支。"
msgid "Branches|diverged from upstream"
msgstr "與上游存在差異"
@@ -1279,10 +1480,10 @@ msgid "Branches|project settings"
msgstr "專案設定"
msgid "Branches|protected"
-msgstr "å—ä¿è­·çš„"
+msgstr "å—ä¿è­·"
msgid "Browse Directory"
-msgstr "ç€è¦½ç›®éŒ„"
+msgstr "ç€è¦½è³‡æ–™å¤¾"
msgid "Browse File"
msgstr "ç€è¦½æª”案"
@@ -1293,21 +1494,36 @@ msgstr "ç€è¦½æª”案"
msgid "Browse files"
msgstr "ç€è¦½æª”案"
-msgid "Built-In"
-msgstr "内建"
+msgid "Built-in"
+msgstr ""
+
+msgid "Business"
+msgstr ""
msgid "Business metrics (Custom)"
msgstr "ä¼æ¥­æŒ‡æ¨™ï¼ˆè‡ªè¨‚)"
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
+msgid "CHANGELOG"
+msgstr ""
+
msgid "CI / CD"
msgstr "CI / CD"
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr "CI / CD 設定"
+msgid "CI Lint"
+msgstr ""
+
msgid "CI will run using the credentials assigned above."
msgstr "CI 將會使用底下指定的憑證執行。"
@@ -1315,10 +1531,10 @@ msgid "CI/CD"
msgstr "CI / CD"
msgid "CI/CD configuration"
-msgstr "CI/CD 設定"
+msgstr "CI / CD 設定"
msgid "CI/CD for external repo"
-msgstr "外部儲存庫的 CI / CD"
+msgstr "外部版本庫的 CI / CD"
msgid "CI/CD settings"
msgstr "CI / CD 設定"
@@ -1327,7 +1543,7 @@ msgid "CICD|Auto DevOps"
msgstr "自動 DevOps"
msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
-msgstr "自動 DevOps 將會自動編譯ã€æ¸¬è©¦ã€ä¸¦åœ¨åŸºæ–¼é ç·¨è­¯ã€ŒæŒçºŒæ•´åˆã€å’Œã€Œå‚³éžã€è¨­å®šçš„環境部署您的應用程å¼"
+msgstr "自動 DevOps 將會自動編譯ã€æ¸¬è©¦ã€ä¸¦åœ¨åŸºæ–¼é ç·¨è­¯ã€Œä¸é–“æ–·æ•´åˆã€å’Œã€Œå‚³éžã€è¨­å®šçš„環境部署您的應用程å¼"
msgid "CICD|Automatic deployment to staging, manual deployment to production"
msgstr "至動部屬到模擬環境,手動部屬到正å¼ç’°å¢ƒ"
@@ -1336,20 +1552,14 @@ msgid "CICD|Continuous deployment to production"
msgstr "æŒçºŒéƒ¨å±¬åˆ°æ­£å¼ç’°å¢ƒ"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "使用定時增é‡éƒ¨ç½²ï¼ŒæŒçºŒéƒ¨ç½²åˆ°æ­£å¼ç’°å¢ƒ"
msgid "CICD|Default to Auto DevOps pipeline"
-msgstr "é è¨­ä½¿ç”¨è‡ªå‹• DevOps æµæ°´ç·š"
+msgstr "é è¨­ä½¿ç”¨è‡ªå‹• DevOps 管線"
msgid "CICD|Deployment strategy"
msgstr "部屬策略"
-msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr "部屬策略需è¦ç¶²åŸŸæ‰èƒ½æ­£å¸¸å·¥ä½œ"
-
-msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr "如果你設定了多個使用「自動 DevOpsã€çš„ Kubernetes å¢é›†ï¼Œè«‹ä¸è¦åœ¨é€™è£¡è¨­å®šç¶²åŸŸã€‚"
-
msgid "CICD|Jobs"
msgstr "作業"
@@ -1357,31 +1567,46 @@ msgid "CICD|Learn more about Auto DevOps"
msgstr "學習更多關於 Auto DevOps 的相關訊æ¯"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr "自動 DevOps æµæ°´ç·šå°‡æœƒåœ¨æ²’有替代 CI 組態檔案的情æ³ä¸‹åŸ·è¡Œã€‚"
+msgstr "自動 DevOps 管線將會在沒有替代 CI 組態檔案的情æ³ä¸‹åŸ·è¡Œã€‚"
-msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
-msgstr "如果你想è¦ä½¿ç”¨è‡ªå‹•è¤‡é–±ç¨‹å¼åŠè‡ªå‹•éƒ¨ç½²ï¼Œè«‹æŒ‡å®šç¶²åŸŸã€‚"
+msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgstr ""
msgid "CICD|instance enabled"
msgstr "已啟用實例"
+msgid "CONTRIBUTING"
+msgstr ""
+
msgid "Callback URL"
msgstr "回呼 URL"
+msgid "Can override approvers and approvals required per merge request"
+msgstr ""
+
msgid "Can't find HEAD commit for this branch"
-msgstr "找ä¸åˆ°æ­¤åˆ†æ”¯çš„ HEAD 更動。"
+msgstr "找ä¸åˆ°æ­¤åˆ†æ”¯çš„ HEAD 變更。"
+
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr ""
msgid "Cancel"
msgstr "å–消"
msgid "Cancel this job"
-msgstr "å–消此任務"
+msgstr "å–消此作業"
msgid "Cannot be merged automatically"
msgstr "ä¸èƒ½è‡ªå‹•åˆä½µ"
msgid "Cannot modify managed Kubernetes cluster"
-msgstr "無法變更託管的 Kubernetes å¢é›†"
+msgstr "無法變更被管ç†çš„ Kubernetes å¢é›†"
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
msgid "Certificate fingerprint"
msgstr "憑證指紋"
@@ -1389,53 +1614,62 @@ msgstr "憑證指紋"
msgid "Change Weight"
msgstr "變更權é‡"
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr "變更模æ¿"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
-msgstr "更改此數值將影響到 GitLab UI 拉å–更新的頻率。"
+msgstr "變更此數值將影響到 GitLab UI 拉å–更新的頻率。"
msgid "ChangeTypeActionLabel|Pick into branch"
-msgstr "挑é¸åˆ°åˆ†æ”¯"
+msgstr "æ€é¸è‡³åˆ†æ”¯"
msgid "ChangeTypeActionLabel|Revert in branch"
-msgstr "還原分支"
+msgstr "復原分支動作"
msgid "ChangeTypeAction|Cherry-pick"
-msgstr "挑é¸"
+msgstr "æ€é¸"
msgid "ChangeTypeAction|Revert"
-msgstr "還原"
+msgstr "復原"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
-msgstr "這將會建立新的更動紀錄,以還原ç¾æœ‰çš„更改。"
-
-msgid "Changelog"
-msgstr "更新日誌"
+msgstr "這將會建立新的æ交記錄,以還原ç¾æœ‰çš„變更。"
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
-msgstr "顯示更改,如果<b>來æº</b>修訂版正在åˆä½µåˆ°<b>目標</b>中修訂版本。"
+msgstr "è‹¥<b>來æº</b>修訂版正è¦åˆä½µåˆ°<b>目標</b>修訂版時顯示變更比較。"
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
msgid "Charts"
-msgstr "統計圖"
+msgstr "統計圖表"
msgid "Chat"
msgstr "å³æ™‚通訊"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr "檢查 %{docs_link_start} 檔案 %{docs_link_end}"
+
+msgid "Check your .gitlab-ci.yml"
msgstr ""
msgid "Checking %{text} availability…"
-msgstr "正在檢查%{text} å¯ç”¨æ€§.."
+msgstr "正在檢查 %{text} çš„å¯ç”¨æ€§â€¦"
+
+msgid "Checking approval status"
+msgstr ""
msgid "Checking branch availability..."
-msgstr "正在檢查分支是å¦å·²ç¶“有人使用..."
+msgstr "正在檢查分支å¯ç”¨æ€§â€¦"
msgid "Cherry-pick this commit"
-msgstr "挑é¸æ­¤æ›´å‹•è¨˜éŒ„"
+msgstr "æ€é¸æ­¤æ交"
msgid "Cherry-pick this merge request"
-msgstr "挑é¸æ­¤åˆä½µè«‹æ±‚"
+msgstr "æ€é¸æ­¤åˆä½µè«‹æ±‚"
msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
msgstr "é¸æ“‡ <strong>建立å°å­˜æª”</strong> 並等待å°å­˜å®Œæˆã€‚"
@@ -1447,7 +1681,13 @@ msgid "Choose File ..."
msgstr "é¸æ“‡æª”案⋯"
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "é¸æ“‡åˆ†æ”¯/標籤(例如:%{master})或者輸入更動紀錄(例如:%{sha})以查看更改內容或建立åˆä½µè«‹æ±‚。"
+msgstr "é¸æ“‡åˆ†æ”¯æˆ–標籤(例如:%{master}),或者輸入æ交代碼(例如:%{sha})以檢視變更比較或建立åˆä½µè«‹æ±‚。"
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
msgid "Choose a template..."
msgstr "é¸æ“‡æ¨¡æ¿â€¦"
@@ -1459,7 +1699,7 @@ msgid "Choose any color."
msgstr "é¸å–é¡è‰²ã€‚"
msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
-msgstr "é¸æ“‡ <code>複製</code> 或 <code>抓å–</code> 以ç²å–最新的應用程å¼åŽŸå§‹ç¢¼"
+msgstr "é¸æ“‡ <code>複製</code> 或 <code>抓å–</code> 以å–得最新的應用程å¼åŽŸå§‹ç¢¼"
msgid "Choose file..."
msgstr "é¸æ“‡æª”案⋯"
@@ -1467,35 +1707,38 @@ msgstr "é¸æ“‡æª”案⋯"
msgid "Choose the top-level group for your repository imports."
msgstr "é¸æ“‡æ‚¨ç‰ˆæœ¬åº«åŒ¯å…¥é …目的頂級群組。"
+msgid "Choose what content you want to see on a group’s overview page"
+msgstr ""
+
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr "é¸æ“‡æ‚¨å¸Œæœ›èˆ‡é€™å€‹æ¬¡è¦ç¯€é»žåŒæ­¥çš„群組"
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
-msgstr "é¸æ“‡ä½ æƒ³è¦é€£ç·šä¸¦åŸ·è¡Œ CI / CD æµæ°´ç·šçš„版本庫。"
+msgstr "é¸æ“‡ä½ æƒ³è¦é€£ç·šä¸¦åŸ·è¡Œ CI / CD 管線的版本庫。"
msgid "Choose which repositories you want to import."
-msgstr "é¸æ“‡ä½ æƒ³åŒ¯å…¥çš„檔案庫。"
+msgstr "é¸æ“‡ä½ æƒ³åŒ¯å…¥çš„版本庫。"
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr "é¸æ“‡ä½ æƒ³è¦ç”¨ä¾†èˆ‡é€™å€‹æ¬¡è¦ç¯€é»žåŒæ­¥çš„碎片 (shards)。"
msgid "CiStatusLabel|canceled"
-msgstr "å·²å–消"
+msgstr "å–消"
msgid "CiStatusLabel|created"
msgstr "已建立"
msgid "CiStatusLabel|delayed"
-msgstr ""
+msgstr "已延é²"
msgid "CiStatusLabel|failed"
msgstr "失敗"
msgid "CiStatusLabel|manual action"
-msgstr "手動æ“作"
+msgstr "需手動æ“作"
msgid "CiStatusLabel|passed"
-msgstr "已通éŽ"
+msgstr "通éŽ"
msgid "CiStatusLabel|passed with warnings"
msgstr "通éŽï¼Œä½†æœ‰è­¦å‘Šè¨Šæ¯"
@@ -1504,25 +1747,25 @@ msgid "CiStatusLabel|pending"
msgstr "等待中"
msgid "CiStatusLabel|skipped"
-msgstr "已略éŽ"
+msgstr "已跳éŽ"
msgid "CiStatusLabel|waiting for delayed job"
-msgstr ""
+msgstr "等待已延é²çš„作業"
msgid "CiStatusLabel|waiting for manual action"
msgstr "等待手動æ“作"
msgid "CiStatusText|blocked"
-msgstr "已阻擋"
+msgstr "阻擋"
msgid "CiStatusText|canceled"
-msgstr "å·²å–消"
+msgstr "å–消"
msgid "CiStatusText|created"
msgstr "已建立"
msgid "CiStatusText|delayed"
-msgstr ""
+msgstr "已延é²"
msgid "CiStatusText|failed"
msgstr "失敗"
@@ -1531,13 +1774,13 @@ msgid "CiStatusText|manual"
msgstr "手動æ“作"
msgid "CiStatusText|passed"
-msgstr "已通éŽ"
+msgstr "通éŽ"
msgid "CiStatusText|pending"
msgstr "等待中"
msgid "CiStatusText|skipped"
-msgstr "已略éŽ"
+msgstr "已跳éŽ"
msgid "CiStatus|running"
msgstr "執行中"
@@ -1546,13 +1789,13 @@ msgid "CiVariables|Input variable key"
msgstr "輸入變數å稱"
msgid "CiVariables|Input variable value"
-msgstr "輸入變數的值"
+msgstr "輸入變數值"
msgid "CiVariables|Remove variable row"
-msgstr "刪除變數"
+msgstr "移除變數欄"
msgid "CiVariable|* (All environments)"
-msgstr "* (所有環境)"
+msgstr "*(所有環境)"
msgid "CiVariable|All environments"
msgstr "所有環境"
@@ -1560,68 +1803,83 @@ msgstr "所有環境"
msgid "CiVariable|Create wildcard"
msgstr "建立è¬ç”¨å­—å…ƒ"
-msgid "CiVariable|Error occured while saving variables"
-msgstr "儲存變數時發生錯誤"
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
msgid "CiVariable|New environment"
msgstr "建立新的環境"
msgid "CiVariable|Protected"
-msgstr "å—ä¿è­·çš„"
+msgstr "å—ä¿è­·"
msgid "CiVariable|Search environments"
msgstr "æœå°‹ç’°å¢ƒ"
msgid "CiVariable|Toggle protected"
-msgstr "切æ›ç‚ºä¿è­·ç‹€æ…‹"
+msgstr "切æ›ç‚ºå—ä¿è­·ç‹€æ…‹"
msgid "CiVariable|Validation failed"
-msgstr "驗證失敗"
+msgstr "有效性驗證失敗"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "無法使用:%{reason}"
-msgid "Clear search"
+msgid "Clear"
+msgstr ""
+
+msgid "Clear input"
msgstr ""
+msgid "Clear search"
+msgstr "清除æœå°‹"
+
msgid "Clear search input"
msgstr "清除æœå°‹ç´€éŒ„"
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
-msgstr "在專案列表點擊任何<strong>專案å稱</strong>,將轉跳到專案的里程碑。"
+msgstr "在專案列表點é¸ä»»ä½•<strong>專案å稱</strong>,將轉跳到專案的里程碑。"
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
-msgstr "點擊 <strong>下載</strong> 按鈕並等待下載完æˆã€‚"
+msgstr "é»žé¸ <strong>下載</strong> 按鈕並等待下載完æˆã€‚"
msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
-msgstr "點擊左上角的<strong>å‡ç´š</strong>按鈕,將æå‡è‡³ç¾¤çµ„里程碑。"
+msgstr "點é¸å·¦ä¸Šè§’çš„<strong>å‡ç´š</strong>按鈕,將æå‡è‡³ç¾¤çµ„里程碑。"
msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
-msgstr "點擊å³å´çš„ <strong>ä¸é¸æ“‡</strong> 按鈕,因為我們åªéœ€è¦ã€ŒGoogle Code 專案寄存ã€ã€‚"
+msgstr "點é¸å³å´çš„ <strong>ä¸é¸æ“‡</strong> 按鈕,因為我們åªéœ€è¦ã€ŒGoogle Code 專案寄存ã€ã€‚"
msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "點擊下é¢çš„按鈕,連çµåˆ° Kubernetes é é¢é–‹å§‹å®‰è£ã€‚"
+msgstr "點é¸ä¸‹é¢çš„按鈕,連çµåˆ° Kubernetes é é¢é–‹å§‹å®‰è£ã€‚"
msgid "Click to expand it."
msgstr "按一下以展開。"
msgid "Click to expand text"
-msgstr "點擊以展開內容"
+msgstr "點é¸ä»¥å±•é–‹æ–‡å­—"
msgid "Client authentication certificate"
-msgstr "客戶端èªè­‰æ†‘è­‰"
+msgstr "使用者端èªè­‰æ†‘è­‰"
msgid "Client authentication key"
-msgstr "客戶端驗證金鑰"
+msgstr "使用者端驗證金鑰"
msgid "Client authentication key password"
-msgstr "客戶端驗證金鑰密碼"
+msgstr "使用者端驗證金鑰密碼"
msgid "Clients"
-msgstr "客戶端"
+msgstr "使用者端"
+
+msgid "Clone"
+msgstr ""
msgid "Clone repository"
-msgstr "複製檔案庫"
+msgstr "複製版本庫"
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
msgid "Close"
msgstr "關閉"
@@ -1629,70 +1887,103 @@ msgstr "關閉"
msgid "Close epic"
msgstr "關閉 Epic"
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr "已關閉"
+msgid "Closed (moved)"
+msgstr ""
+
msgid "Closed issues"
msgstr "已關閉議題"
+msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgstr ""
+
+msgid "ClusterIntegration| can be used instead of a custom domain."
+msgstr ""
+
+msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
-msgstr "%{appList} 已經æˆåŠŸå®‰è£åˆ°æ‚¨çš„ Kubernetes å¢é›†"
+msgstr "%{appList} 已順利安è£åˆ°æ‚¨çš„ Kubernetes å¢é›†"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
-msgstr ""
+msgstr "%{boldNotice} 這將新增一些é¡å¤–的資æºï¼Œå¦‚負載平衡器,這å¯èƒ½æœƒç”¢ç”Ÿé¡å¤–çš„æˆæœ¬ï¼Œå…·é«”å–決於您安è£Kubernetes å¢é›†çš„æœå‹™æ供商。如果您使用的是 Google Kubernetes Engine,å¯ä»¥åƒè€ƒ %{pricingLink}。"
-msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgid "ClusterIntegration|%{title} upgraded successfully."
msgstr ""
msgid "ClusterIntegration|API URL"
-msgstr "Api 網å€"
+msgstr "API 網å€"
msgid "ClusterIntegration|Add Kubernetes cluster"
-msgstr "增加 Kubernetes å¢é›†"
+msgstr "新增 Kubernetes å¢é›†"
msgid "ClusterIntegration|Add a Kubernetes cluster integration"
-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 an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "增加整åˆåˆ°ä½ çš„群組,以便在群組中的專案分享å¢é›†ã€‚"
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Kubernetes å¢é›†æ•´åˆçš„進階設定"
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr "å®‰è£ Ingress 後,您需è¦åœ¨ç”Ÿæˆçš„外部 IP ä½ç½®ä¸ŠæŒ‡å‘ DNS,以便在部署後檢視您的應用程å¼ã€‚ %{ingressHelpLink}"
+
+msgid "ClusterIntegration|Alternatively"
msgstr ""
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
-msgstr "當嘗試ç²å–專案å€åŸŸæ™‚錯誤發生:%{error}"
+msgstr "當嘗試å–得專案å€åŸŸæ™‚錯誤發生:%{error}"
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr "當嘗試ç²å–您的專案時發生錯誤:%{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr "嘗試連線到 Google Cloud API 時出錯,請ç¨å€™å†è©¦ã€‚"
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr "應用程å¼"
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
-msgstr "您確定è¦åˆªé™¤æ­¤ Kubernetes å¢é›†çš„æ•´åˆè¨­å®šå—Žï¼Ÿ 這將會刪除您實際的 Kubernetes å¢é›†ã€‚"
+msgstr "確定è¦åˆªé™¤æ­¤ Kubernetes å¢é›†æ•´åˆå—Žï¼Ÿ 這將會刪除實際的 Kubernetes å¢é›†ã€‚"
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
msgid "ClusterIntegration|CA Certificate"
-msgstr "CAèªè­‰"
+msgstr "CA 憑證"
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
+msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
-msgstr "憑證 (PEMæ ¼å¼)"
+msgstr "憑證 (PEM æ ¼å¼)"
msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr ""
+msgstr "é¸æ“‡è¦å®‰è£åœ¨æ‚¨ Kubernetes å¢é›†ä¸Šçš„應用程å¼ã€‚Helm Tiller 需è¦å®‰è£ä»»ä½•ä¸€å€‹ä»¥ä¸‹çš„程å¼ã€‚"
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr "é¸æ“‡è¦ä½¿ç”¨åœ¨æ­¤å¢é›†çš„環境。"
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1707,11 +1998,14 @@ msgstr "è¤‡è£½å…¥å£ IP ä½ç½®åˆ°å‰ªè²¼è¤²"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr "複製 Jupyter 主機å稱至剪貼簿"
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "複製 Kubernetes å¢é›†å稱"
msgid "ClusterIntegration|Copy Token"
-msgstr "複製權æ–"
+msgstr "複製憑證"
msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "建立 Kubernetes å¢é›†"
@@ -1720,13 +2014,13 @@ msgid "ClusterIntegration|Did you know?"
msgstr "你知é“嗎?"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
-msgstr ""
+msgstr "啟用或åœç”¨æ‚¨ Kubernetes å¢é›†çš„ GitLab 連線。"
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
-msgstr ""
+msgstr "若使用基於角色的權é™æŽ§åˆ¶ (RBAC) 則請啟用此設定。"
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
-msgstr "輸入您的 Kubernetes å¢é›†è©³ç´°è³‡è¨Š"
+msgstr "輸入您 Kubernetes å¢é›†çš„詳細資訊"
msgid "ClusterIntegration|Environment scope"
msgstr "環境範åœ"
@@ -1734,23 +2028,32 @@ 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 "æ¯å€‹æ–°çš„ Google Cloud Platform (GCP) 帳號都會在 %{sign_up_link} 收到 300 元的優惠。因與 Google åˆä½œï¼ŒGitLab å°‡å¯ä»¥ç‚ºæ–°å»ºç«‹åŠç¾æœ‰çš„ GCP 帳號æä¾›é¡å¤–çš„ 200 元優惠,以嘗試 GitLab çš„ Google Kubernetes Engine æ•´åˆã€‚"
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
msgid "ClusterIntegration|Fetching machine types"
-msgstr "正在ç²å–機器類型"
+msgstr "正在å–得機器類型"
msgid "ClusterIntegration|Fetching projects"
-msgstr "正在ç²å–專案"
+msgstr "正在å–得專案"
msgid "ClusterIntegration|Fetching zones"
-msgstr "正在ç²å–å€åŸŸ"
+msgstr "正在å–å¾—å€åŸŸ"
msgid "ClusterIntegration|GitLab Integration"
msgstr "GitLab æ•´åˆ"
msgid "ClusterIntegration|GitLab Runner"
-msgstr "Gitlab Runner"
+msgstr "GitLab 執行器"
msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
-msgstr ""
+msgstr "GitLab 執行器連çµå°ˆæ¡ˆçš„版本庫,並執行 CI / CD 作業ã€æŽ¨é€çµæžœä¸¦ä½ˆç½²æ‡‰ç”¨ç¨‹å¼è‡³ç”Ÿç”¢ç’°å¢ƒã€‚"
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google 雲端專案"
@@ -1762,13 +2065,13 @@ msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Google Kubernetes Engine 專案"
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "群組整åˆ"
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helm 簡化了安è£èˆ‡ç®¡ç† Kubernetes 應用程å¼çš„步驟。Tiller 在您的 Kubernetes å¢é›†å…§éƒ¨åŸ·è¡Œï¼Œä¸¦ç®¡ç†åœ–表的發佈。"
msgid "ClusterIntegration|Hide"
msgstr "éš±è—"
@@ -1780,13 +2083,13 @@ msgid "ClusterIntegration|In order to show the health of the cluster, we'll need
msgstr "為了è¦é¡¯ç¤ºå¢é›†çš„å¥åº·ç‹€æ³ï¼Œæˆ‘們需è¦ç‚ºæ‚¨çš„å¢é›†è¨­å®š Prometheus 以收集所需的資訊。"
msgid "ClusterIntegration|Ingress"
-msgstr "å…¥å£"
+msgstr "輸入"
msgid "ClusterIntegration|Ingress IP Address"
msgstr "å…¥å£ IP ä½ç½®"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
-msgstr ""
+msgstr "Ingress 為您æ供了一種將請求伺æœå™¨æˆ–路徑路由到æœå‹™çš„方法,將多個æœå‹™é›†ä¸­åˆ°ä¸€å€‹å…¥å£é»žã€‚"
msgid "ClusterIntegration|Install"
msgstr "安è£"
@@ -1801,11 +2104,17 @@ msgid "ClusterIntegration|Installing"
msgstr "安è£ä¸­"
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
-msgstr "æ•´åˆ Kubernetes å¢é›†è‡ªå‹•åŒ–"
+msgstr "è‡ªå‹•æ•´åˆ Kubernetes å¢é›†"
msgid "ClusterIntegration|Integration status"
msgstr "æ•´åˆç‹€æ…‹"
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
+msgstr ""
+
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Jupyter 主機å稱"
@@ -1813,12 +2122,18 @@ msgid "ClusterIntegration|JupyterHub"
msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
-msgstr ""
+msgstr "JupyterHub 是一個多使用者的 Hub,它負責生æˆã€ç®¡ç†ã€ä»£ç†å–®å€‹ä½¿ç”¨è€… Jupyter notebook 伺æœå™¨çš„多個實例。JupytherHub å¯ä»¥æ›¿ä¸€å€‹ç­ç´šçš„學生,ä¼æ¥­è³‡æ–™ç§‘å­¸å°çµ„或資料研究å°çµ„æä¾› Jupyter notebook 。"
msgid "ClusterIntegration|Knative"
-msgstr ""
+msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
+msgstr "Knative 網域å稱"
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster"
@@ -1831,46 +2146,49 @@ msgid "ClusterIntegration|Kubernetes cluster health"
msgstr "Kubernetes å¢é›†å¥åº·ç¨‹åº¦"
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
-msgstr "Kubernetes å¢é›†å·²ç¶“在 Google Kubernetes Engine 上被建立"
+msgstr "Kubernetes å¢é›†å·²ç¶“在 Google Kubernetes Engine 建立"
msgid "ClusterIntegration|Kubernetes cluster name"
msgstr "Kubernetes å¢é›†å稱"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
-msgstr "Kubernetes å¢é›†å·²ç¶“æˆåŠŸè¢«å»ºç«‹æ–¼ Google Kubernetes Engine,é‡æ–°æ•´ç†æ­¤é é¢æ‚¨å°‡æœƒçœ‹åˆ° Kubernetes å¢é›†çš„詳細資訊"
+msgstr "Kubernetes å¢é›†å·²ç¶“æˆåŠŸåœ¨ Google Kubernetes Engine 建立,é‡æ–°æ•´ç†æ­¤é é¢å¾Œå°‡å¯çœ‹åˆ° Kubernetes å¢é›†çš„詳細資訊"
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
+msgstr "é€éŽ Kubernetes å¢é›†æ•´åˆï¼Œå¯ä»¥è®“你輕鬆使用程å¼ç¢¼æª¢é–±å·¥å…·ã€éƒ¨ç½²æ‚¨çš„應用程å¼ã€åŸ·è¡Œç®¡ç·šç­‰ã€‚"
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
-msgstr "Kubernetes å¢é›†å¯ä»¥ç”¨æ–¼éƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ä»¥åŠç‚ºæ­¤å°ˆæ¡ˆæ供代碼審查工具"
+msgstr "Kubernetes å¢é›†å¯ä»¥ç”¨æ–¼éƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ã€ä»¥åŠæ供此專案程å¼ç¢¼æª¢é–±å·¥å…·"
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
-msgstr "瞭解有關 %{help_link_start_machine_type}機器類型%{help_link_end} 和 %{help_link_start_pricing}定價%{help_link_end} 的詳細資訊。"
+msgstr "了解有關 %{help_link_start_machine_type}機器類型%{help_link_end} 和 %{help_link_start_pricing}定價%{help_link_end} 的詳細資訊。"
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
-msgstr "瞭解有關 %{help_link_start}å€åŸŸ%{help_link_end} 的詳細資訊。"
+msgstr "了解有關 %{help_link_start}å€åŸŸ%{help_link_end} 的詳細資訊。"
msgid "ClusterIntegration|Learn more about Kubernetes"
-msgstr ""
+msgstr "了解關於 Kubernetes 的更多資訊"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr "了解關於群組 Kubernetes å¢é›†çš„更多資訊"
+
+msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
msgid "ClusterIntegration|Machine type"
-msgstr "機器型別"
+msgstr "機器類型"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
-msgstr "請確èªæ‚¨çš„帳戶中 %{link_to_requirements} 是å¦å¯ä»¥å»ºç«‹ Kubernetes å¢é›†"
+msgstr "請確èªæ‚¨çš„帳號 %{link_to_requirements} 是å¦å¯ä»¥å»ºç«‹ Kubernetes å¢é›†"
msgid "ClusterIntegration|Manage"
msgstr "管ç†"
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
-msgstr "請至 %{link_gke} 管ç†æ‚¨çš„ Kubernetes å¢é›†"
+msgstr "請造訪 %{link_gke} 管ç†æ‚¨çš„ Kubernetes å¢é›†"
msgid "ClusterIntegration|More information"
-msgstr "詳細資料"
+msgstr "更多資訊"
msgid "ClusterIntegration|No machine types matched your search"
msgstr "沒有機器類型符åˆæ‚¨çš„æœå°‹"
@@ -1885,22 +2203,22 @@ msgid "ClusterIntegration|No zones matched your search"
msgstr "沒有å€åŸŸç¬¦åˆæ‚¨çš„æœå°‹"
msgid "ClusterIntegration|Note:"
-msgstr "注æ„:"
+msgstr "註:"
msgid "ClusterIntegration|Number of nodes"
-msgstr "所有的端點數é‡"
+msgstr "節點數"
msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr "請為你的 Kubernetes å¢é›†è¼¸å…¥å­˜å–訊æ¯ï¼Œå¦‚果你需è¦å¹«åŠ©ï¼Œå¯ä»¥é–±è®€æˆ‘們關於 Kubernetes å¢é›†çš„ %{link_to_help_page}"
+msgstr "請輸入您 Kubernetes å¢é›†çš„å­˜å–資訊,若需幫助,å¯ä»¥é–±è®€é—œæ–¼ GitLab 有關 Kubernetes å¢é›†çš„說明é é¢ï¼š%{link_to_help_page}"
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
-msgstr "請確èªä½ çš„ Google 帳號是å¦ç¬¦åˆé€™äº›æ¢ä»¶"
+msgstr "請確èªä½ çš„ Google 帳號是å¦ç¬¦åˆé€™äº›æ¢ä»¶ï¼š"
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
-msgstr ""
+msgstr "å°æ‡‰è¬ç”¨å­—å…ƒ DNS 至生æˆçš„ IP ä½å€ï¼Œä»¥åœ¨æ‚¨æ‡‰ç”¨ç¨‹å¼ä½ˆç½²å¾Œï¼Œå­˜å–您的應用程å¼ã€‚"
msgid "ClusterIntegration|Project cluster"
-msgstr ""
+msgstr "專案å¢é›†"
msgid "ClusterIntegration|Project namespace"
msgstr "專案命å空間"
@@ -1912,31 +2230,34 @@ msgid "ClusterIntegration|Prometheus"
msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
-msgstr ""
+msgstr "Prometheus 是個與 %{gitlabIntegrationLink} æ­é…的開放原始碼監視系統,以監視已佈署的應用程å¼ã€‚"
msgid "ClusterIntegration|RBAC-enabled cluster"
-msgstr ""
+msgstr "啟用 RBAC å¢é›†"
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
-msgstr "閱讀我們關於 Kubernetes å¢é›†æ•´åˆçš„ %{link_to_help_page}。"
+msgstr "閱讀 GitLab 關於 Kubernetes å¢é›†æ•´åˆçš„資訊:%{link_to_help_page} 。"
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
-msgstr "刪除 Kubernetes å¢é›†æ•´åˆ"
+msgstr "移除 Kubernetes å¢é›†æ•´åˆ"
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 "刪除此 Kubernetes å¢é›†è¨­å®šï¼Œé€™ä¸æœƒåˆªé™¤å¯¦éš›çš„ Kubernetes å¢é›†ã€‚"
+msgstr "從此專案移除 Kubernetes å¢é›†è¨­å®šï¼Œé€™ä¸æœƒåˆªé™¤å¯¦éš›çš„ Kubernetes å¢é›†ã€‚"
msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
-msgstr ""
+msgstr "若想è¦è«‹å–代此為您自己的主機å稱。如果您這麼åšï¼Œè«‹å¾žä¸Šæ–¹å°‡ä¸»æ©Ÿå稱å°æ‡‰åˆ° Ingress IP ä½å€ã€‚"
msgid "ClusterIntegration|Request to begin installing failed"
-msgstr "請求安è£å¤±æ•—"
+msgstr "請求開始安è£å¤±æ•—"
+
+msgid "ClusterIntegration|Retry upgrade"
+msgstr ""
msgid "ClusterIntegration|Save changes"
-msgstr "儲存修改"
+msgstr "儲存變更"
msgid "ClusterIntegration|Search machine types"
msgstr "æœå°‹æ©Ÿå™¨é¡žåž‹"
@@ -1948,7 +2269,7 @@ msgid "ClusterIntegration|Search zones"
msgstr "æœå°‹å€åŸŸ"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
-msgstr "查看與編輯您的 Kubernetes å¢é›†è©³ç´°è³‡è¨Š"
+msgstr "檢視與編輯 Kubernetes å¢é›†è©³ç´°è³‡è¨Š"
msgid "ClusterIntegration|Select machine type"
msgstr "é¸æ“‡æ©Ÿå™¨é¡žåž‹"
@@ -1969,45 +2290,66 @@ msgid "ClusterIntegration|Select zone to choose machine type"
msgstr "é¸æ“‡å€åŸŸä¾†é¸æ“‡æ©Ÿå™¨é¡žåž‹"
msgid "ClusterIntegration|Service token"
-msgstr "æœå‹™æ¬Šæ–"
+msgstr "æœå‹™æ†‘è­‰"
msgid "ClusterIntegration|Show"
msgstr "顯示"
msgid "ClusterIntegration|Something went wrong on our end."
-msgstr "內部發生了錯誤"
+msgstr "內部發生錯誤"
+
+msgid "ClusterIntegration|Something went wrong when upgrading %{title}. Please check the logs and try again."
+msgstr ""
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
-msgstr "在 Google Kubernetes Engine 上建立å¢é›†æ™‚發生錯誤"
+msgstr "在 Google Kubernetes Engine 建立å¢é›†æ™‚發生錯誤"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "å®‰è£ %{title} 時發生錯誤"
-msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr "IP ä½å€æ­£åœ¨åˆ†é…當中。如果分é…的時間太長,請檢查您的 Kubernetes å¢é›†èˆ‡ Google Kubernetes Engine 上的é™é¡ã€‚"
+
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
-msgstr "此帳戶必須æ“有在 %{link_to_container_project} 中建立 Kubernetes å¢é›†çš„權é™"
+msgstr "此帳號必須è¦æœ‰ %{link_to_container_project} 底下è¦æ±‚的權é™æ‰èƒ½å»ºç«‹ Kubernetes å¢é›†"
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
-msgstr ""
+msgstr "æ­¤é¸é …å…許您在 RBAC å¢é›†ä¸Šå®‰è£æ‡‰ç”¨ç¨‹å¼ã€‚"
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "åˆ‡æ› Kubernetes å¢é›†"
msgid "ClusterIntegration|Token"
-msgstr "權æ–"
+msgstr "憑證"
+
+msgid "ClusterIntegration|Upgrade"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrade failed"
+msgstr ""
+
+msgid "ClusterIntegration|Upgraded"
+msgstr ""
+
+msgid "ClusterIntegration|Upgrading"
+msgstr ""
msgid "ClusterIntegration|Validating project billing status"
msgstr "正在驗證è£ç½®è¨ˆè²»ç‹€æ…‹"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
-msgstr ""
+msgstr "我們無法驗證您其中一個在 GCP 上的專案是å¦å•Ÿç”¨å¸³å–®åŠŸèƒ½ã€‚è«‹é‡è©¦ã€‚"
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "當å¢é›†é€£çµåˆ°æ­¤å°ˆæ¡ˆï¼Œä½ å¯ä»¥ä½¿ç”¨è¤‡é–±æ‡‰ç”¨ï¼Œéƒ¨ç½²ä½ çš„應用程å¼ï¼ŒåŸ·è¡Œä½ çš„æµæ°´ç·šï¼Œé‚„有更多容易上手的方å¼å¯ä»¥ä½¿ç”¨ã€‚"
+msgstr "當 Kubernetes 節點關è¯åˆ°æ­¤å°ˆæ¡ˆï¼Œå³å¯æª¢é–±å’Œéƒ¨å±¬æ‡‰ç”¨ç¨‹å¼ã€åŸ·è¡Œç®¡ç·šä»¥åŠç”¨æ›´ç°¡å–®çš„æ–¹å¼åšæ›´å¤šçš„事情。"
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr "在安è£ä¸‹æ–¹çš„應用程å¼å‰ï¼Œæ‚¨å¿…é ˆå…ˆå®‰è£ Helm Tiller"
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
@@ -2029,7 +2371,7 @@ msgid "ClusterIntegration|help page"
msgstr "說明é é¢"
msgid "ClusterIntegration|meets the requirements"
-msgstr "符åˆéœ€æ±‚"
+msgstr "é”到需求"
msgid "ClusterIntegration|properly configured"
msgstr "設定正確"
@@ -2037,85 +2379,99 @@ msgstr "設定正確"
msgid "ClusterIntegration|sign up"
msgstr "註冊"
+msgid "Code"
+msgstr ""
+
msgid "Code owners"
-msgstr "代碼所有者"
+msgstr "程å¼ç¢¼æ‰€æœ‰è€…"
msgid "Cohorts"
msgstr "Cohorts"
msgid "Collapse"
-msgstr "收起"
+msgstr "收縮"
msgid "Collapse sidebar"
msgstr "收起å´é‚Šæ¬„"
+msgid "Command line instructions"
+msgstr ""
+
msgid "Comment"
+msgstr "留言"
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
msgstr ""
msgid "Comment & resolve discussion"
-msgstr "評論並關閉討論"
+msgstr "留言並關閉討論"
msgid "Comment & unresolve discussion"
-msgstr "評論並é‡æ–°è¨Žè«–"
+msgstr "留言並é‡æ–°è¨Žè«–"
msgid "Comment form position"
-msgstr ""
+msgstr "留言框ä½ç½®"
msgid "Comments"
msgstr "留言"
msgid "Commit"
msgid_plural "Commits"
-msgstr[0] "更動記錄"
+msgstr[0] "æ交記錄"
-msgid "Commit (%{commit_count})"
-msgid_plural "Commits (%{commit_count})"
-msgstr[0] "更動紀錄 (%{commit_count})"
+msgid "Commit %{commit_id}"
+msgstr ""
msgid "Commit Message"
-msgstr "更動訊æ¯"
+msgstr "æ交訊æ¯"
+
+msgid "Commit deleted"
+msgstr ""
msgid "Commit duration in minutes for last 30 commits"
-msgstr "最近 30 次更動所花費的時間(分é˜ï¼‰"
+msgstr "最近 30 次æ交所花費的時間(分é˜ï¼‰"
msgid "Commit message"
-msgstr "更動說明"
+msgstr "æ交訊æ¯"
msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
-msgstr "更動紀錄統計 %{ref} %{start_time} - %{end_time}"
+msgstr "%{ref} çš„æ交統計,時間範åœï¼š%{start_time} - %{end_time}"
msgid "Commit to %{branchName} branch"
msgstr "æ交至 %{branchName} 分支"
msgid "CommitBoxTitle|Commit"
-msgstr "é€äº¤"
+msgstr "æ交"
msgid "CommitMessage|Add %{file_name}"
-msgstr "建立 %{file_name}"
+msgstr "新增 %{file_name}"
msgid "CommitWidget|authored"
msgstr "創作"
msgid "Commits"
-msgstr "更動記錄"
+msgstr "æ交記錄"
msgid "Commits feed"
-msgstr "更動摘è¦"
+msgstr "æ交摘è¦"
msgid "Commits per day hour (UTC)"
-msgstr "ä¾å°æ™‚統計æ交次數(UTC)"
+msgstr "ä¾ 24 å°æ™‚統計的æ交次數 (UTC)"
msgid "Commits per day of month"
-msgstr "ä¾æ—¥æœŸçµ±è¨ˆæ交次數"
+msgstr "ä¾æ¯æœˆå¤©æ•¸çµ±è¨ˆçš„æ交次數 (UTC)"
msgid "Commits per weekday"
-msgstr "ä¾æ˜ŸæœŸçµ±è¨ˆæ交次數"
+msgstr "ä¾å·¥ä½œæ—¥çµ±è¨ˆçš„æ交次數"
msgid "Commits|An error occurred while fetching merge requests data."
-msgstr "讀å–請求åˆä½µè³‡æ–™æ™‚發生錯誤"
+msgstr "抓å–åˆä½µè«‹æ±‚資料時發生錯誤"
msgid "Commits|Commit: %{commitText}"
-msgstr "更動紀錄: %{commitText}"
+msgstr "æ交:%{commitText}"
msgid "Commits|History"
msgstr "æ­·å²ç´€éŒ„"
@@ -2124,7 +2480,7 @@ msgid "Commits|No related merge requests found"
msgstr "找ä¸åˆ°ç›¸é—œçš„åˆä½µè«‹æ±‚"
msgid "Committed by"
-msgstr "é€äº¤è€…為 "
+msgstr "æ交者:"
msgid "Commit…"
msgstr "æ交…"
@@ -2133,19 +2489,22 @@ msgid "Compare"
msgstr "比較"
msgid "Compare Git revisions"
-msgstr "比較 Git 修訂版本"
+msgstr "比較 Git 修訂版"
msgid "Compare Revisions"
msgstr "比較修訂版本"
+msgid "Compare changes"
+msgstr ""
+
msgid "Compare changes with the last commit"
-msgstr "與上一次的更動紀錄進行比較"
+msgstr "與上一次的æ交記錄進行比較"
msgid "Compare changes with the merge request target branch"
-msgstr "將更改與åˆä½µè«‹æ±‚目標分支進行比較"
+msgstr "將變更與åˆä½µè«‹æ±‚目標分支進行比較"
msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
-msgstr "%{source_branch} 和 %{target_branch} 是一樣的"
+msgstr "%{source_branch} 和 %{target_branch} 內容一致。"
msgid "CompareBranches|Compare"
msgstr "比較"
@@ -2157,22 +2516,28 @@ msgid "CompareBranches|Target"
msgstr "目標"
msgid "CompareBranches|There isn't anything to compare."
-msgstr "沒有任何地方å¯ä»¥æ¯”較的"
+msgstr "沒有å¯æ¯”較的內容。"
msgid "Confidential"
msgstr "機密"
msgid "Confidentiality"
-msgstr "機密的"
+msgstr "機密性"
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
msgid "Configure Gitaly timeouts."
msgstr "設定 Gitaly 延é²éŽä¹…。"
msgid "Configure Tracing"
+msgstr "設定追蹤"
+
+msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
-msgstr "於檔案庫上設定自動 Git 檢查與內務管ç†"
+msgstr "於版本庫上設定自動 Git 檢查與內務管ç†"
msgid "Configure limits for web and API requests."
msgstr "為網路與 API 請求設定é™åˆ¶ã€‚"
@@ -2181,10 +2546,10 @@ msgid "Configure push mirrors."
msgstr "設定推é€é¡åƒã€‚"
msgid "Configure storage path settings."
-msgstr ""
+msgstr "設定儲存路徑。"
msgid "Configure the %{link} integration."
-msgstr ""
+msgstr "設定 %{link} å¢é›†ã€‚"
msgid "Configure the way a user creates a new account."
msgstr "設定使用者建立新帳號的方å¼ã€‚"
@@ -2193,46 +2558,49 @@ msgid "Connect"
msgstr "連線"
msgid "Connect all repositories"
-msgstr "連接所有版本庫"
+msgstr "連線所有版本庫"
msgid "Connect repositories from GitHub"
-msgstr "é€£çµ GitHub 檔案庫"
+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 "連çµæ‚¨çš„外部版本庫,CI / CD æµæ°´ç·šå°‡æœƒç‚ºæ–°çš„æ交執行。åªæœƒå»ºç«‹åªå•Ÿç”¨ CI / CD 功能的 GitLab 專案。"
+msgstr "連çµæ‚¨çš„外部版本庫,CI / CD 管線將會為新的æ交執行。åªæœƒå»ºç«‹åªå•Ÿç”¨ CI / CD 功能的 GitLab 專案。"
msgid "Connecting..."
msgstr "正在連çµâ€¦"
+msgid "Contact sales to upgrade"
+msgstr ""
+
msgid "Container Registry"
-msgstr "Container Registry"
+msgstr "容器登錄表"
msgid "ContainerRegistry|Created"
msgstr "已建立"
msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
-msgstr "請先使用你的 Gitlab 帳號來登入 Gitlab 的 Container Registry。如果你有 %{link_2fa} ,你必須使用 %{link_token}:"
+msgstr "請先使用您的 GitLab 帳號登入到 GitLab 的容器登錄表。若您有設定 %{link_2fa} ,則必須使用 %{link_token}:"
msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
-msgstr "GitLab 支æ´å¤šé” 3 級的映åƒæª”å稱。以下映åƒæª”範例å°æ‚¨çš„專案有幫助:"
+msgstr "GitLab 支æ´å¤šé” 3 級的映åƒå稱。以下的映åƒç¯„例å°æ‚¨çš„專案有效:"
msgid "ContainerRegistry|How to use the Container Registry"
-msgstr "如何使用 Container Registry"
+msgstr "如何使用容器登錄表"
msgid "ContainerRegistry|Learn more about"
msgstr "了解更多"
msgid "ContainerRegistry|No tags in Container Registry for this container image."
-msgstr "在這個 Container Registry 中ä¸åŒ…å«ä»»ä½•æœ‰æ¨™ç±¤çš„容器映åƒæª”"
+msgstr "在這個容器登錄表中ä¸åŒ…å«æœ‰æ¨™ç±¤çš„容器映åƒ"
msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
-msgstr "當您登入後,您å¯ä»¥é€éŽ %{build} å’Œ %{push} 指令來自由建立和上傳容器映åƒæª”"
+msgstr "當您登入後,您å¯ä»¥é€éŽå¸¸è¦‹çš„ %{build} å’Œ %{push} 指令自由建立和上傳容器映åƒ"
msgid "ContainerRegistry|Remove repository"
-msgstr "刪除檔案庫"
+msgstr "移除版本庫"
msgid "ContainerRegistry|Remove tag"
-msgstr "刪除標籤"
+msgstr "移除標籤"
msgid "ContainerRegistry|Size"
msgstr "大å°"
@@ -2244,14 +2612,17 @@ msgid "ContainerRegistry|Tag ID"
msgstr "標籤 ID"
msgid "ContainerRegistry|Use different image names"
-msgstr "使用ä¸åŒçš„映åƒæª”å稱"
+msgstr "使用ä¸åŒçš„映åƒå稱"
msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
-msgstr "å°‡ Docker Container Registry æ•´åˆåˆ° GitLab 中後,æ¯å€‹å°ˆæ¡ˆéƒ½å¯ä»¥æœ‰è‡ªå·±çš„空間來儲存 Docker 的映åƒæª”"
+msgstr "å°‡ Docker 容器登錄表整åˆåˆ° GitLab 後,æ¯å€‹å°ˆæ¡ˆéƒ½èƒ½æœ‰è‡ªå·±çš„空間來儲存 Docker 映åƒæª”。"
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "您也å¯ä»¥ä½¿ç”¨ %{deploy_token} 為 Registry 映åƒæª”進行唯讀存å–"
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
msgid "Continue"
msgstr "繼續"
@@ -2259,7 +2630,7 @@ msgid "Continue to the next step"
msgstr "繼續下個步驟"
msgid "Continuous Integration and Deployment"
-msgstr "æŒçºŒæ•´åˆèˆ‡éƒ¨å±¬"
+msgstr "ä¸é–“æ–·æ•´åˆèˆ‡éƒ¨å±¬"
msgid "Contribute to GitLab"
msgstr "è²¢ç»çµ¦GitLab"
@@ -2267,8 +2638,8 @@ msgstr "è²¢ç»çµ¦GitLab"
msgid "Contribution"
msgstr "è²¢ç»"
-msgid "Contribution guide"
-msgstr "å”作指å—"
+msgid "Contribution Charts"
+msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr "<strong>%{calendar_date}</strong> çš„è²¢ç»ç´€éŒ„"
@@ -2277,19 +2648,19 @@ msgid "Contributions per group member"
msgstr "æ¯å€‹ç¾¤çµ„æˆå“¡çš„è²¢ç»"
msgid "Contributors"
-msgstr "å”作者"
+msgstr "è²¢ç»è€…"
msgid "ContributorsPage|%{startDate} – %{endDate}"
msgstr "%{startDate} - %{endDate}"
msgid "ContributorsPage|Building repository graph."
-msgstr "建立檔案庫的圖形"
+msgstr "建立版本庫的圖表。"
msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
-msgstr "æ交到%{branch_name},ä¸åŒ…å«åˆä½µæ交,é™åˆ¶æ–¼ 6,000 次更動。"
+msgstr "æ交到 %{branch_name},ä¸åŒ…å«åˆä½µæ交。é™åˆ¶æœ€å¤šé¡¯ç¤º 6,000 個æ交。"
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
-msgstr "è«‹ç¨ç­‰ç‰‡åˆ»ï¼Œé€™å€‹é é¢æœƒæº–備好時自動刷新。"
+msgstr "è«‹ç¨å¾…片刻,這個é é¢åœ¨æº–備好後自動é‡æ–°æ•´ç†ã€‚"
msgid "Control the display of third party offers."
msgstr "控制第三方æ供的顯示方å¼ã€‚"
@@ -2303,21 +2674,27 @@ msgstr "控制此次è¦ç¯€é»žçš„版本庫最大並行é‡"
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr "控制此 Geo 節點驗證æ“作的最大並行é‡"
+msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
+msgstr ""
+
msgid "ConvDev Index"
msgstr "ConvDev 索引"
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "複製 %{protocol} 的複製 (clone) URL"
-msgid "Copy HTTPS clone URL"
-msgstr "複製 HTTPS 的複製 (clone) URL"
-
msgid "Copy ID to clipboard"
-msgstr ""
+msgstr "複製 ID 到剪貼簿"
msgid "Copy SSH clone URL"
msgstr "複製 SSH 的複製 (clone) URL"
+msgid "Copy SSH public key"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr "複製 SSH 公鑰到剪貼簿"
@@ -2325,13 +2702,13 @@ msgid "Copy URL to clipboard"
msgstr "複製網å€åˆ°å‰ªè²¼ç°¿"
msgid "Copy branch name to clipboard"
-msgstr "複製分支å稱"
+msgstr "複製分支å稱到剪貼簿"
msgid "Copy command to clipboard"
msgstr "複製指令"
msgid "Copy commit SHA to clipboard"
-msgstr "複製更動記錄的 SHA 值到剪貼簿"
+msgstr "複製æ交記錄的 SHA 值到剪貼簿"
msgid "Copy file path to clipboard"
msgstr "複製檔案路徑到剪貼簿"
@@ -2340,16 +2717,13 @@ msgid "Copy incoming email address to clipboard"
msgstr "複製接收到的電å­ä¿¡ç®±ä½å€åˆ°å‰ªè²¼ç°¿"
msgid "Copy link"
-msgstr ""
-
-msgid "Copy name to clipboard"
-msgstr ""
+msgstr "複製連çµ"
msgid "Copy reference to clipboard"
-msgstr "複製連çµ"
+msgstr "複製åƒç…§åˆ°å‰ªè²¼ç°¿"
msgid "Copy secret to clipboard"
-msgstr ""
+msgstr "複製密碼到剪貼簿"
msgid "Copy to clipboard"
msgstr "複製至剪貼簿"
@@ -2358,13 +2732,16 @@ msgid "Copy token to clipboard"
msgstr "複製憑證到剪貼簿"
msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
-msgstr ""
+msgstr "無法讀管線狀態。有關故障排除的步驟,請åƒè€ƒ%{linkStart}檔案%{linkEnd}。"
msgid "Create"
msgstr "建立"
msgid "Create New Directory"
-msgstr "建立新目錄"
+msgstr "建立新資料夾"
+
+msgid "Create New Domain"
+msgstr ""
msgid "Create a new branch"
msgstr "建立新分支"
@@ -2375,8 +2752,11 @@ msgstr "建立新分支åŠåˆä½µè«‹æ±‚"
msgid "Create a new issue"
msgstr "建立新議題"
+msgid "Create a new repository"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
-msgstr "建立個人存å–憑證以使用 %{protocol} 來上傳或下載。"
+msgstr "建立您帳號的個人存å–憑證以é€éŽ %{protocol} 上傳或下載。"
msgid "Create branch"
msgstr "建立分支"
@@ -2385,10 +2765,10 @@ msgid "Create commit"
msgstr "建立æ交"
msgid "Create directory"
-msgstr "建立目錄"
+msgstr "建立資料夾"
msgid "Create empty repository"
-msgstr "建立空的檔案庫"
+msgstr "建立空的版本庫"
msgid "Create epic"
msgstr "建立 epic"
@@ -2409,11 +2789,14 @@ msgid "Create lists from labels. Issues with that label appear in that list."
msgstr "建立標籤列表。å«æœ‰æ­¤æ¨™ç±¤çš„議題將會顯示於清單中。"
msgid "Create merge request"
-msgstr "發出åˆä½µè«‹æ±‚"
+msgstr "建立åˆä½µè«‹æ±‚"
msgid "Create merge request and branch"
msgstr "建立åˆä½µè«‹æ±‚åŠåˆ†æ”¯"
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr "新增分支"
@@ -2424,22 +2807,22 @@ msgid "Create new file"
msgstr "新增檔案"
msgid "Create new file or directory"
-msgstr "建立新檔案或目錄"
+msgstr "建立新檔案或資料夾"
msgid "Create new label"
-msgstr "建立新的標籤"
+msgstr "建立新標籤"
msgid "Create new..."
-msgstr "建立..."
+msgstr "建立…"
msgid "Create project label"
msgstr "建立專案標籤"
msgid "Create your first page"
-msgstr ""
+msgstr "建立您的第一個é é¢"
msgid "CreateTag|Tag"
-msgstr "建立標籤"
+msgstr "標籤"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "建立個人存å–憑證"
@@ -2451,7 +2834,7 @@ msgid "Created At"
msgstr "建立於"
msgid "Created by me"
-msgstr "由我創建"
+msgstr "由我建立"
msgid "Created on"
msgstr "建立於"
@@ -2480,24 +2863,24 @@ msgstr "個人資料"
msgid "CurrentUser|Settings"
msgstr "設定"
-msgid "Custom"
-msgstr "自訂"
-
msgid "Custom CI config path"
-msgstr "自定義 CI é…置路徑"
+msgstr "自訂 CI 設定路徑"
msgid "Custom hostname (for private commit emails)"
-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 %{notification_link}."
-msgstr "自訂通知的等級與åƒèˆ‡åº¦è¨­å®šç›¸åŒã€‚使用自訂通知讓你åªæ”¶åˆ°ç‰¹å®šçš„事件通知。想了解更多資訊,請查閱 %{notification_link} 。"
+msgstr "自訂通知等級與åƒèˆ‡ç­‰ç´šç›¸åŒã€‚使用自訂通知等級以åªæŽ¥æ”¶åˆ°é¸å–事件的通知。若想了解更多資訊,請造訪 %{notification_link}。"
msgid "Custom project templates"
msgstr "自訂專案模æ¿"
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
msgid "Customize colors"
msgstr "自訂é¡è‰²"
@@ -2507,9 +2890,15 @@ msgstr "自訂把 FogBugz é›»å­ä¿¡ç®±ç¶²å€å’Œä½¿ç”¨è€…å稱匯入到 GitLab ç
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "自訂把 Google Code çš„é›»å­ä¿¡ç®±ç¶²å€å’Œä½¿ç”¨è€…å稱匯入到 GitLab çš„æ–¹å¼ã€‚下個步驟中,您將å¯ä»¥é¸æ“‡æ¬²åŒ¯å…¥çš„專案。"
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize your merge request approval settings."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr "å­˜å–您執行器憑證,自訂您的管線設定,並檢視你的æµæ°´ç¾ç‹€æ…‹åŠæ¸¬è©¦æ¶µè“‹çŽ‡å ±å‘Šã€‚"
+
msgid "Cycle Analytics"
msgstr "週期分æž"
@@ -2517,7 +2906,7 @@ msgid "Cycle Analytics gives an overview of how much time it takes to go from id
msgstr "「週期統計ã€æ供了您專案從想法到生產環境所花費時間的概覽"
msgid "CycleAnalyticsStage|Code"
-msgstr "程å¼é–‹ç™¼"
+msgstr "程å¼ç¢¼"
msgid "CycleAnalyticsStage|Issue"
msgstr "議題"
@@ -2526,10 +2915,10 @@ msgid "CycleAnalyticsStage|Plan"
msgstr "計劃"
msgid "CycleAnalyticsStage|Production"
-msgstr "營é‹"
+msgstr "生產環境"
msgid "CycleAnalyticsStage|Review"
-msgstr "複閱"
+msgstr "檢閱"
msgid "CycleAnalyticsStage|Staging"
msgstr "試營é‹"
@@ -2537,6 +2926,9 @@ msgstr "試營é‹"
msgid "CycleAnalyticsStage|Test"
msgstr "測試"
+msgid "DNS"
+msgstr ""
+
msgid "Dashboard"
msgstr "監控é¢æ¿"
@@ -2546,6 +2938,9 @@ msgstr "全部"
msgid "DashboardProjects|Personal"
msgstr "個人"
+msgid "Data is still calculating..."
+msgstr ""
+
msgid "Date picker"
msgstr "日期é¸æ“‡å™¨"
@@ -2558,6 +2953,9 @@ msgstr "å二月"
msgid "December"
msgstr "å二月"
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr "拒絕並登出"
@@ -2567,29 +2965,38 @@ msgstr "é è¨­åˆ†æ”¯"
msgid "Default classification label"
msgstr "é è¨­åˆ†é¡žæ¨™ç±¤"
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
-msgstr "é è¨­å€¼ï¼šç›´æŽ¥åŒ¯å…¥ Google Code çš„é›»å­éƒµä»¶åœ°å€æˆ–使用者å稱"
+msgstr "é è¨­å€¼ï¼šç›´æŽ¥åŒ¯å…¥ Google Code çš„é›»å­éƒµä»¶ä½å€æˆ–使用者å稱"
msgid "Default: Map a FogBugz account ID to a full name"
msgstr "é è¨­å€¼ï¼šå°‡ FogBugz 的帳號å°æ‡‰ç‚ºå…¨å"
msgid "Define a custom pattern with cron syntax"
-msgstr "使用 Cron 語法自訂排程"
+msgstr "使用 Cron 語法定義自訂樣å¼"
-msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+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|Start now"
-msgstr ""
+msgstr "ç«‹å³é–‹å§‹"
msgid "DelayedJobs|Unschedule"
-msgstr ""
+msgstr "å–消計畫"
msgid "DelayedJobs|delayed"
-msgstr ""
+msgstr "已延é²"
msgid "Delete"
msgstr "刪除"
@@ -2601,11 +3008,17 @@ msgid "Delete Snippet"
msgstr "刪除片段"
msgid "Delete comment"
-msgstr ""
+msgstr "刪除留言"
msgid "Delete list"
msgstr "刪除清單"
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
msgid "Deleted"
msgstr "已刪除"
@@ -2659,13 +3072,13 @@ msgid "DeployKeys|Publicly accessible deploy keys"
msgstr "å¯å­˜å–的公開部署金鑰"
msgid "DeployKeys|Read access only"
-msgstr "åªè®€å­˜å–"
+msgstr "唯讀存å–"
msgid "DeployKeys|Write access allowed"
msgstr "å·²å…許寫入權é™"
msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
-msgstr "你準備è¦ç§»é™¤é€™å€‹éƒ¨ç½²é‡‘鑰,你確定嗎?"
+msgstr "你準備è¦ç§»é™¤é€™å€‹éƒ¨ç½²é‡‘鑰,確定?"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "啟用部屬憑證(%{active_tokens})"
@@ -2674,10 +3087,10 @@ msgid "DeployTokens|Add a deploy token"
msgstr "建立一個部屬憑證"
msgid "DeployTokens|Allows read-only access to the registry images"
-msgstr "å…許 Registry 映åƒæª”çš„åªè®€å­˜å–"
+msgstr "å…許 Registry 映åƒæª”的唯讀存å–"
msgid "DeployTokens|Allows read-only access to the repository"
-msgstr "å…許此檔案庫的åªè®€å­˜å–"
+msgstr "å…許此版本庫的唯讀存å–"
msgid "DeployTokens|Copy deploy token to clipboard"
msgstr "複製部署憑證至剪貼簿"
@@ -2695,7 +3108,7 @@ msgid "DeployTokens|Deploy Tokens"
msgstr "部屬憑證"
msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
-msgstr "部屬憑證å…許您檔案庫的åªè®€å­˜å–與 Registry 映åƒæª”。"
+msgstr "部屬憑證å…許您版本庫的唯讀存å–與 Registry 映åƒæª”。"
msgid "DeployTokens|Expires"
msgstr "éŽæœŸçš„"
@@ -2731,7 +3144,7 @@ msgid "DeployTokens|Username"
msgstr "使用者å稱"
msgid "DeployTokens|You are about to revoke"
-msgstr "您正打算撤銷"
+msgstr "您正打算復原"
msgid "DeployTokens|Your New Deploy Token"
msgstr "您的新部屬憑證"
@@ -2739,11 +3152,14 @@ msgstr "您的新部屬憑證"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "您的新專案部屬憑證已經建立。"
-msgid "Deployed to"
+msgid "Deployed"
msgstr ""
+msgid "Deployed to"
+msgstr "已部署到"
+
msgid "Deploying to"
-msgstr ""
+msgstr "正在部署到"
msgid "Deprioritize label"
msgstr "優先標籤"
@@ -2755,7 +3171,7 @@ msgid "Description"
msgstr "æè¿°"
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
-msgstr "《æ述範本》å…許你為您專案的議題或åˆä½µè«‹æ±‚之æ述欄ä½å®šç¾©ç¬¦åˆä¸Šä¸‹æ–‡çš„範本。"
+msgstr "《æ述模æ¿ã€‹å…許你為您專案的議題或åˆä½µè«‹æ±‚之æ述欄ä½å®šç¾©ç¬¦åˆä¸Šä¸‹æ–‡çš„模æ¿ã€‚"
msgid "Description:"
msgstr "說明:"
@@ -2764,16 +3180,19 @@ msgid "Destroy"
msgstr "銷毀"
msgid "Details"
-msgstr "細節"
+msgstr "詳細資訊"
+
+msgid "Details (default)"
+msgstr ""
msgid "Detect host keys"
msgstr "åµæ¸¬ä¸»æ©Ÿé‡‘é‘°"
msgid "Diff content limits"
-msgstr ""
+msgstr "差異內容é™åˆ¶"
msgid "Diff limits"
-msgstr ""
+msgstr "差異é™åˆ¶"
msgid "Diffs|No file name available"
msgstr "沒有å¯ç”¨çš„檔案å稱"
@@ -2785,7 +3204,7 @@ msgid "Direction"
msgstr "æ–¹å‘"
msgid "Directory name"
-msgstr "目錄å稱"
+msgstr "資料夾å稱"
msgid "Disable"
msgstr "åœç”¨"
@@ -2796,6 +3215,12 @@ msgstr "為此專案åœç”¨"
msgid "Disable group Runners"
msgstr "åœç”¨ç¾¤çµ„執行器"
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr "æ¨æ£„"
@@ -2806,7 +3231,7 @@ msgid "Discard all unstaged changes?"
msgstr "æ¨æ£„所有未暫存變更?"
msgid "Discard changes"
-msgstr "撤銷變更"
+msgstr "復原變更"
msgid "Discard changes to %{path}?"
msgstr "æ¨æ£„ %{path} 的變更?"
@@ -2815,17 +3240,26 @@ msgid "Discard draft"
msgstr "放棄è‰ç¨¿"
msgid "Discard review"
-msgstr ""
+msgstr "放棄檢閱"
-msgid "Discover GitLab Geo."
-msgstr "探索 GitLab Geo。"
+msgid "Discover GitLab Geo"
+msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "探索專案,群組和程å¼ç¢¼ç‰‡æ®µã€‚與他人分享您的專案"
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
msgid "Dismiss"
msgstr "忽略"
+msgid "Dismiss ConvDev introduction"
+msgstr ""
+
msgid "Dismiss Cycle Analytics introduction box"
msgstr "關閉循環分æžä»‹ç´¹è¦–窗"
@@ -2833,13 +3267,13 @@ msgid "Dismiss Merge Request promotion"
msgstr "忽略åˆä½µè«‹æ±‚的促銷廣告"
msgid "Dismiss trial promotion"
-msgstr ""
+msgstr "å–消試用版å‡ç´š"
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "是å¦è¦è‡ªè¨‚å°‡ Google Code çš„é›»å­ä¿¡ç®±ä½å€å’Œä½¿ç”¨è€…å稱匯入到 GitLab çš„æ–¹å¼ï¼Ÿ"
msgid "Documentation for popular identity providers"
-msgstr "知å身份æ供商的文件"
+msgstr "知å身份æ供商的檔案"
msgid "Domain"
msgstr "網域"
@@ -2853,6 +3287,12 @@ msgstr "完æˆ"
msgid "Download"
msgstr "下載"
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
msgid "Download tar"
msgstr "下載 tar"
@@ -2872,11 +3312,14 @@ msgid "DownloadCommit|Email Patches"
msgstr "é›»å­éƒµä»¶ä¿®è£œæª”案"
msgid "DownloadCommit|Plain Diff"
-msgstr "差異檔"
+msgstr "純文字差異檔"
msgid "DownloadSource|Download"
msgstr "下載原始碼"
+msgid "Downstream"
+msgstr ""
+
msgid "Downvotes"
msgstr "噓"
@@ -2892,11 +3335,17 @@ msgstr "æ¯å€‹åŸ·è¡Œå™¨å¯ä»¥è™•æ–¼ä»¥ä¸‹ç‹€æ…‹ä¹‹ä¸€ï¼š"
msgid "Edit"
msgstr "編輯"
+msgid "Edit %{name}"
+msgstr ""
+
msgid "Edit Label"
msgstr "編輯標籤"
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
-msgstr "編輯 %{id} æµæ°´ç·šæŽ’程"
+msgstr "編輯排程管線 %{id}"
msgid "Edit Snippet"
msgstr "編輯片段"
@@ -2904,8 +3353,14 @@ msgstr "編輯片段"
msgid "Edit application"
msgstr "編輯應用程å¼"
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
-msgstr "在編輯器中編輯æ交更動紀錄"
+msgstr "在編輯器中編輯檔案,並在此處æ交變更"
msgid "Edit group: %{group_name}"
msgstr "編輯群組:%{group_name}"
@@ -2913,11 +3368,14 @@ msgstr "編輯群組:%{group_name}"
msgid "Edit identity for %{user_name}"
msgstr "編輯 %{user_name} 的身份"
+msgid "Edit issues"
+msgstr ""
+
msgid "Elasticsearch"
msgstr "Elasticsearch"
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
+msgstr "Elasticsearch æ•´åˆã€‚ Elasticsearch AWS IAM。"
msgid "Email"
msgstr "é›»å­ä¿¡ç®±"
@@ -2931,6 +3389,9 @@ msgstr "é›»å­éƒµä»¶"
msgid "Embed"
msgstr "內嵌"
+msgid "Empty file"
+msgstr ""
+
msgid "Enable"
msgstr "啟用"
@@ -2944,7 +3405,7 @@ msgid "Enable SAML authentication for this group"
msgstr "為此群組啟用 SAML 驗證"
msgid "Enable Sentry for error reporting and logging."
-msgstr "為錯誤報告與日誌啟用 Sentry。"
+msgstr "為錯誤報告與記錄啟用 Sentry。"
msgid "Enable and configure InfluxDB metrics."
msgstr "啟用與設定 InfluxDB 指標。"
@@ -2955,6 +3416,9 @@ msgstr "啟用與設定 Prometheus 指標。"
msgid "Enable classification control using an external service"
msgstr "使用外部æœå‹™é€²è¡Œåˆ†é¡žæŽ§åˆ¶"
+msgid "Enable error tracking"
+msgstr ""
+
msgid "Enable for this project"
msgstr "為此專案啟用"
@@ -2970,9 +3434,18 @@ msgstr "啟用或åœç”¨ç‰ˆæœ¬æª¢æŸ¥å’Œä½¿ç”¨ ping。"
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "啟用 reCAPTCHA 或 Akismet 並設定 IP 上é™ã€‚"
+msgid "Enable self approval of merge requests"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr "啟用æ供群組的效能桿。"
+msgid "Enable two-factor authentication"
+msgstr ""
+
msgid "Enable usage ping"
msgstr "å•Ÿç”¨ä½¿ç”¨æƒ…æ³ Ping"
@@ -2985,8 +3458,14 @@ msgstr "已啟用"
msgid "Ends at (UTC)"
msgstr "æ–¼ (UTC) çµæŸ"
+msgid "Enforce SSO-only authentication for this group"
+msgstr ""
+
+msgid "Enforced SSO"
+msgstr ""
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
-msgstr "在底下輸入您的 BitBucket 伺æœå™¨ URL 和個人存å–權æ–"
+msgstr "在底下輸入您的 BitBucket 伺æœå™¨ URL 和個人存å–憑證"
msgid "Enter the issue description"
msgstr "請輸入å•é¡Œèªªæ˜Ž"
@@ -3000,14 +3479,32 @@ msgstr "請輸入åˆä½µè«‹æ±‚說明"
msgid "Enter the merge request title"
msgstr "請請輸入åˆä½µè«‹æ±‚標題"
+msgid "Enter your Sentry API URL"
+msgstr ""
+
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
msgid "Environments"
msgstr "環境"
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+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 stopping the environment, please try again"
msgstr "åœæ­¢ç’°å¢ƒæ™‚發生錯誤,請é‡è©¦"
@@ -3016,7 +3513,7 @@ msgid "Environments|Are you sure you want to stop this environment?"
msgstr "確定è¦åœæ­¢æ­¤ç’°å¢ƒå—Žï¼Ÿ"
msgid "Environments|Commit"
-msgstr "æ›´å‹•"
+msgstr "æ交"
msgid "Environments|Deploy to..."
msgstr "部屬到…"
@@ -3031,16 +3528,16 @@ msgid "Environments|Environments"
msgstr "環境"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr "《環境》是部署代碼的ä½ç½®ï¼Œä¾‹å¦‚階段或生產環境。"
+msgstr "《環境》是部署程å¼ç¢¼çš„ä½ç½®ï¼Œä¾‹å¦‚階段或生產環境。"
msgid "Environments|Job"
-msgstr "任務"
+msgstr "作業"
msgid "Environments|Learn more about stopping environments"
msgstr "了解有關åœæ­¢ç’°å¢ƒçš„更多資訊"
msgid "Environments|New environment"
-msgstr "新建環境"
+msgstr "建立環境"
msgid "Environments|No deployments yet"
msgstr "尚未部署"
@@ -3058,19 +3555,19 @@ msgid "Environments|Open live environment"
msgstr "打開實æ³ç’°å¢ƒ"
msgid "Environments|Pod logs from"
-msgstr "Pod 日誌由"
+msgstr "Pod 記錄由"
msgid "Environments|Re-deploy to environment"
msgstr "é‡æ–°éƒ¨å±¬ç’°å¢ƒ"
msgid "Environments|Read more about environments"
-msgstr "了解有關環境的更多訊æ¯"
+msgstr "了解有關環境的更多資訊"
msgid "Environments|Rollback environment"
msgstr "回退環境"
msgid "Environments|Show all"
-msgstr "顯示全部"
+msgstr "顯示所有內容"
msgid "Environments|Stop"
msgstr "åœæ­¢"
@@ -3078,11 +3575,14 @@ msgstr "åœæ­¢"
msgid "Environments|Stop environment"
msgstr "åœæ­¢ç’°å¢ƒ"
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "已更新"
msgid "Environments|You don't have any environments right now"
-msgstr ""
+msgstr "你還沒有設定環境"
msgid "Environments|protected"
msgstr "å—ä¿è­·çš„"
@@ -3090,9 +3590,6 @@ msgstr "å—ä¿è­·çš„"
msgid "Epic"
msgstr "Epic"
-msgid "Epic will be removed! Are you sure?"
-msgstr "將會移除 Epicï¼æ‚¨ç¢ºå®šå—Žï¼Ÿ"
-
msgid "Epics"
msgstr "Epic"
@@ -3102,8 +3599,8 @@ msgstr "Epics 開發è—圖"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Epics 讓你能更有效率且花費更少功夫的管ç†æ‚¨å°ˆæ¡ˆçš„組åˆã€‚"
-msgid "Epics|An error occurred while saving %{epicDateType} date"
-msgstr "儲存 %{epicDateType} 日期時出錯"
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
msgid "Epics|How can I solve this?"
msgstr "該怎麼解決這個?"
@@ -3112,10 +3609,10 @@ msgid "Epics|More information"
msgstr "更多資訊"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
-msgstr ""
+msgstr "這些日期會影響在開發è—圖中 Epic 的顯示方å¼ã€‚來自里程碑的日期來自å°æ‡‰åˆ° Epic 中議題的里程碑。您也å¯ä»¥è¨­å®šå›ºå®šæ—¥æœŸã€æˆ–是完全移除它們。"
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 "è‹¥è¦æŽ’程基於里程碑的 Epic %{epicDateType} 日期,請å°ä»»ä½• Epic 中的議題指定 %{epicDateType} 日期的里程碑。"
msgid "Epics|due"
msgstr "截止"
@@ -3127,22 +3624,28 @@ msgid "Error"
msgstr "錯誤"
msgid "Error Reporting and Logging"
-msgstr "錯誤報告與日誌"
+msgstr "錯誤報告與記錄"
+
+msgid "Error Tracking"
+msgstr ""
msgid "Error creating epic"
msgstr "建立 epic 時發生錯誤"
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
msgid "Error fetching contributors data."
-msgstr "讀å–è²¢ç»è€…資料時發生錯誤。"
+msgstr "抓å–è²¢ç»è€…資料時發生錯誤。"
msgid "Error fetching labels."
-msgstr "讀å–標籤時發生錯誤。"
+msgstr "抓å–標籤時發生錯誤。"
msgid "Error fetching network graph."
-msgstr "讀å–分支圖時發生錯誤。"
+msgstr "抓å–分支圖時發生錯誤。"
msgid "Error fetching refs"
-msgstr "讀å–分支資料時發生錯誤。"
+msgstr "抓å–åƒç…§æ™‚發生錯誤。"
msgid "Error fetching usage ping data."
msgstr "讀å–ä½¿ç”¨æƒ…æ³ ping 資料時發生錯誤。"
@@ -3154,7 +3657,7 @@ msgid "Error loading branches."
msgstr "載入分支時發生錯誤。"
msgid "Error loading last commit."
-msgstr "載入最新更動紀錄時失敗。"
+msgstr "載入最新æ交記錄時失敗。"
msgid "Error loading markdown preview"
msgstr "載入 Markdown é è¦½æ™‚發生å•é¡Œ"
@@ -3166,59 +3669,107 @@ msgid "Error loading project data. Please try again."
msgstr "載入專案資料時錯誤,請é‡è©¦ã€‚"
msgid "Error loading template types."
-msgstr ""
+msgstr "載入模æ¿é¡žåž‹æ™‚發生錯誤。"
msgid "Error loading template."
-msgstr ""
+msgstr "載入模æ¿æ™‚發生錯誤。"
msgid "Error occurred when toggling the notification subscription"
msgstr "切æ›è¨‚閱通知時發生錯誤"
+msgid "Error rendering markdown preview"
+msgstr ""
+
msgid "Error saving label update."
-msgstr "更新標籤時發生錯誤。"
+msgstr "儲存標籤更新時發生錯誤。"
+
+msgid "Error updating %{issuableType}"
+msgstr ""
msgid "Error updating status for all todos."
-msgstr "更新代辦事項清單時發生錯誤"
+msgstr "更新所有待辦事項的狀態時發生錯誤"
msgid "Error updating todo status."
-msgstr "更新代辦事項時發生錯誤。"
+msgstr "更新待辦事項狀態時發生錯誤。"
msgid "Error while loading the merge request. Please try again."
+msgstr "載入åˆä½µè«‹æ±‚時出錯。請é‡è©¦ã€‚"
+
+msgid "Error:"
+msgstr ""
+
+msgid "Errors"
msgstr ""
msgid "Estimated"
msgstr "é ä¼°"
msgid "EventFilterBy|Filter by all"
-msgstr "顯示全部"
+msgstr "全部篩é¸"
msgid "EventFilterBy|Filter by comments"
-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 "Events"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
msgid "Every day (at 4:00am)"
-msgstr "æ¯æ—¥åŸ·è¡Œï¼ˆæ·©æ™¨å››é»žï¼‰"
+msgstr "æ¯æ—¥åŸ·è¡Œï¼ˆå‡Œæ™¨å››é»žï¼‰"
msgid "Every month (on the 1st at 4:00am)"
-msgstr "æ¯æœˆåŸ·è¡Œï¼ˆæ¯æœˆä¸€æ—¥æ·©æ™¨å››é»žï¼‰"
+msgstr "æ¯æœˆåŸ·è¡Œï¼ˆæ¯æœˆç¬¬ä¸€å¤©çš„凌晨四點)"
msgid "Every week (Sundays at 4:00am)"
-msgstr "æ¯é€±åŸ·è¡Œï¼ˆé€±æ—¥æ·©æ™¨ 四點)"
+msgstr "æ¯é€±åŸ·è¡Œï¼ˆé€±æ—¥å‡Œæ™¨å››é»žï¼‰"
+
+msgid "Everyone"
+msgstr ""
msgid "Everyone can contribute"
msgstr "æ¯å€‹äººéƒ½èƒ½è²¢ç»"
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Existing Git repository"
+msgstr ""
+
+msgid "Existing folder"
+msgstr ""
+
+msgid "Existing members and groups"
+msgstr ""
+
msgid "Expand"
msgstr "展開"
@@ -3229,11 +3780,17 @@ msgid "Expand sidebar"
msgstr "展開å´é‚Šæ¬„"
msgid "Expiration date"
+msgstr "截止日期"
+
+msgid "Expired %{expiredOn}"
msgstr ""
-msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr "請解釋此å•é¡Œã€‚如果å¯ä»¥è«‹æ供相關議題或留言的連çµã€‚"
+
msgid "Explore"
msgstr "ç€è¦½"
@@ -3250,11 +3807,23 @@ msgid "Explore projects"
msgstr "ç€è¦½å°ˆæ¡ˆ"
msgid "Explore public groups"
-msgstr "æœå°‹å…¬é–‹çš„群組"
+msgstr "ç€è¦½å…¬é–‹ç¾¤çµ„"
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
msgid "External Classification Policy Authorization"
msgstr "外部分類策略èªè­‰"
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
msgid "External authentication"
msgstr "外部èªè­‰"
@@ -3280,114 +3849,165 @@ msgid "Failed"
msgstr "失敗"
msgid "Failed Jobs"
-msgstr "失敗的任務"
+msgstr "失敗的作業"
msgid "Failed to change the owner"
-msgstr "無法變更所有權"
+msgstr "無法變更所有者"
msgid "Failed to check related branches."
msgstr "檢查相關分支失敗。"
msgid "Failed to deploy to"
-msgstr ""
+msgstr "無法部署到"
msgid "Failed to load emoji list."
+msgstr "無法讀å–表情符號列表。"
+
+msgid "Failed to load errors from Sentry"
msgstr ""
msgid "Failed to remove issue from board, please try again."
msgstr "從看æ¿åˆªé™¤è­°é¡Œæ™‚發生錯誤,請ç¨å€™é‡è©¦"
msgid "Failed to remove mirror."
-msgstr ""
+msgstr "未能刪除é¡åƒ"
msgid "Failed to remove the pipeline schedule"
-msgstr "無法刪除æµæ°´ç·šæŽ’程"
+msgstr "無法移除排程管線"
-msgid "Failed to signing using smartcard authentication"
+msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr "無法é€éŽ smartcard 進行èªè­‰"
+
msgid "Failed to update issues, please try again."
msgstr "更新議題時發生錯誤,請ç¨å¾Œé‡è©¦ã€‚"
+msgid "Failed to upload object map file"
+msgstr ""
+
msgid "Failure"
msgstr "失敗"
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "較快,因為它å†æ¬¡ä½¿ç”¨å°ˆæ¡ˆå·¥ä½œç©ºé–“ (如果它ä¸å­˜åœ¨ï¼Œå‰‡è¿”回到複製)"
msgid "Feature Flags"
-msgstr ""
+msgstr "功能標籤"
-msgid "FeatureFlags|API URL"
+msgid "FeatureFlags|* (All Environments)"
msgstr ""
-msgid "FeatureFlags|Active"
+msgid "FeatureFlags|* (All environments)"
msgstr ""
-msgid "FeatureFlags|Application name"
-msgstr ""
+msgid "FeatureFlags|API URL"
+msgstr "API URL"
+
+msgid "FeatureFlags|Active"
+msgstr "活動"
msgid "FeatureFlags|Configure"
-msgstr ""
+msgstr "設定"
msgid "FeatureFlags|Configure feature flags"
-msgstr ""
+msgstr "設定功能標籤"
msgid "FeatureFlags|Create feature flag"
+msgstr "建立功能標籤"
+
+msgid "FeatureFlags|Delete %{name}?"
msgstr ""
-msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgid "FeatureFlags|Delete feature flag"
msgstr ""
msgid "FeatureFlags|Description"
-msgstr ""
+msgstr "說明"
msgid "FeatureFlags|Edit %{feature_flag_name}"
-msgstr ""
+msgstr "編輯 %{feature_flag_name}"
msgid "FeatureFlags|Edit Feature Flag"
+msgstr "編輯功能標籤"
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
msgstr ""
msgid "FeatureFlags|Feature Flag"
+msgstr "功能標籤"
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
-msgid "FeatureFlags|Feature flag"
+msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
msgstr ""
-msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
-msgid "FeatureFlags|Get started with feature flags"
+msgid "FeatureFlags|Get started with Feature Flags"
msgstr ""
msgid "FeatureFlags|Inactive"
+msgstr "åœç”¨"
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr ""
+msgstr "å®‰è£ %{docs_link_start} 相容的使用者端 %{docs_link_end},並在設定é é¢æŒ‡å®š API URLã€æ‡‰ç”¨ç¨‹å¼å’Œå¯¦ä¾‹ ID。"
msgid "FeatureFlags|Instance ID"
+msgstr "實例 ID"
+
+msgid "FeatureFlags|Loading Feature Flags"
msgstr ""
-msgid "FeatureFlags|More information"
+msgid "FeatureFlags|More Information"
msgstr ""
+msgid "FeatureFlags|More information"
+msgstr "更多資訊"
+
msgid "FeatureFlags|Name"
-msgstr ""
+msgstr "å稱"
msgid "FeatureFlags|New"
-msgstr ""
+msgstr "æ–°"
msgid "FeatureFlags|New Feature Flag"
-msgstr ""
+msgstr "新增功能標籤"
msgid "FeatureFlags|Save changes"
-msgstr ""
+msgstr "儲存"
msgid "FeatureFlags|Status"
+msgstr "狀態"
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There are no active Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There are no inactive Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
msgid "Feb"
@@ -3397,73 +4017,116 @@ msgid "February"
msgstr "二月"
msgid "Fields on this page are now uneditable, you can configure"
-msgstr "æ­¤é é¢æ¬„ä½ç¾åœ¨ç„¡æ³•ç·¨è¼¯ï¼Œä½ å¯ä»¥è¨­ç½®"
+msgstr "æ­¤é é¢çš„欄ä½ç›®å‰ç„¡æ³•ç·¨è¼¯ï¼Œä½†ä½ èƒ½è¨­å®š"
+
+msgid "File"
+msgid_plural "Files"
+msgstr[0] ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
msgid "File templates"
+msgstr "檔案模æ¿"
+
+msgid "File upload error."
msgstr ""
msgid "Files"
msgstr "檔案"
-msgid "Files (%{human_size})"
-msgstr "檔案 (%{human_size})"
-
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "填寫以下的欄ä½ï¼Œé–‹å•Ÿ <strong>%{enable_label}</strong> 後按下 <strong>%{save_changes}</strong>"
msgid "Filter"
-msgstr ""
+msgstr "篩é¸"
msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
+msgstr "ä¾ç›®å‰é—œé–‰çš„ %{issuable_type} 篩é¸ã€‚"
msgid "Filter by %{issuable_type} that are currently opened."
-msgstr ""
+msgstr "ä¾ç›®å‰é–‹æ”¾çš„ %{issuable_type} 篩é¸ã€‚"
msgid "Filter by commit message"
-msgstr "以更動說明篩é¸"
+msgstr "僅篩é¸æ交訊æ¯"
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
msgid "Filter..."
+msgstr "篩é¸â€¦"
+
+msgid "Find and manage Auth Tokens in your Sentry account settings page."
msgstr ""
msgid "Find by path"
-msgstr "以路徑æœå°‹"
+msgstr "ä¾è·¯å¾‘æœå°‹"
+
+msgid "Find existing members by name"
+msgstr ""
msgid "Find file"
msgstr "æœå°‹æª”案"
msgid "Find the downloaded ZIP file and decompress it."
-msgstr ""
+msgstr "找到下載的ZIP檔案並解壓縮它。"
msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
-msgstr ""
+msgstr "找到新æå–çš„ <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> 檔案。"
msgid "Fingerprints"
+msgstr "數ä½æŒ‡ç´‹:"
+
+msgid "Finish editing this message first!"
msgstr ""
msgid "Finish review"
-msgstr ""
+msgstr "完æˆæª¢é–±"
msgid "Finished"
msgstr "已完æˆ"
+msgid "First day of the week"
+msgstr ""
+
msgid "FirstPushedBy|First"
-msgstr "首次"
+msgstr "第一次"
msgid "FirstPushedBy|pushed by"
msgstr "推é€è€…:"
msgid "Fixed date"
-msgstr ""
+msgstr "修復日期"
msgid "Fixed due date"
-msgstr ""
+msgstr "修復的截止日期"
msgid "Fixed start date"
-msgstr ""
+msgstr "修復的開始日期"
msgid "Fixed:"
-msgstr ""
+msgstr "已修復:"
msgid "FogBugz Email"
msgstr "FogBugz é›»å­ä¿¡ç®±"
@@ -3481,7 +4144,7 @@ msgid "FogBugz import"
msgstr "匯入 FogBugz"
msgid "Follow the steps below to export your Google Code project data."
-msgstr ""
+msgstr "請按照以下步驟會出您的 Google Code 專案資料。"
msgid "Font Color"
msgstr "å­—é«”é¡è‰²"
@@ -3490,32 +4153,38 @@ msgid "Footer message"
msgstr "é å°¾è¨Šæ¯"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
-msgstr "å°æ–¼å…§éƒ¨å°ˆæ¡ˆï¼Œä»»ä½•ç™»éŒ„的使用者都å¯ä»¥æŸ¥çœ‹æµæ°´ç·šä¸¦å­˜å–工作詳細資訊 (輸出日誌和產物)"
+msgstr "å°æ–¼å…§éƒ¨å°ˆæ¡ˆï¼Œä»»ä½•ç™»å…¥çš„使用者都å¯ä»¥æª¢è¦–管線並存å–工作詳細資訊 (輸出記錄和æˆå“)"
-msgid "For more information, go to the "
+msgid "For more info, read the documentation."
msgstr ""
+msgid "For more information, go to the "
+msgstr "欲知更多資訊,請å‰å¾€ "
+
msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr ""
+msgstr "更多訊æ¯è«‹æŸ¥é–± %{link_start_tag} Jaeger 的設定檔案 %{link_end_tag}"
msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
-msgstr ""
+msgstr "欲知更多資訊,請檢視 %{deactivating_usage_ping_link_start}åœç”¨ä½¿ç”¨æƒ…æ³ Ping%{deactivating_usage_ping_link_end} 的檔案。"
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "å°æ–¼ç§äººå°ˆæ¡ˆï¼Œä»»ä½•æˆå“¡ (訪客或以上) 都å¯ä»¥æŸ¥çœ‹æµæ°´ç·šä¸¦å­˜å–工作詳細資訊 (輸出日誌和產物)"
+msgstr "å°æ–¼ç§äººå°ˆæ¡ˆï¼Œä»»ä½•æˆå“¡ (訪客或以上) 都å¯ä»¥æª¢è¦–管線並存å–工作詳細資訊 (輸出記錄和æˆå“)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "å°æ–¼å…¬é–‹å°ˆæ¡ˆï¼Œä»»ä½•äººéƒ½å¯ä»¥æŸ¥çœ‹æµæ°´ç·šä¸¦å­˜å–工作詳細資訊 (輸出日誌和產物)"
+msgstr "å°æ–¼å…¬é–‹å°ˆæ¡ˆï¼Œä»»ä½•äººéƒ½å¯ä»¥æª¢è¦–管線並存å–工作詳細資訊 (輸出記錄和æˆå“)"
msgid "ForkedFromProjectPath|Forked from"
msgstr "分支自"
msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
-msgstr "從 %{project_name} 分支. (已刪除)"
+msgstr "從 %{project_name} 分支(已刪除)"
msgid "Forking in progress"
msgstr "正在建立分å‰"
+msgid "Forks"
+msgstr ""
+
msgid "Format"
msgstr "æ ¼å¼"
@@ -3523,7 +4192,7 @@ msgid "Found errors in your .gitlab-ci.yml:"
msgstr "在您的 .gitlab-ci.yml 中找到錯誤:"
msgid "Free Trial of GitLab.com Gold"
-msgstr ""
+msgstr "å…費試用 GitLab.com 黃金計畫"
msgid "From %{provider_title}"
msgstr "來自 %{provider_title}"
@@ -3532,7 +4201,7 @@ msgid "From Bitbucket"
msgstr "從 Bitbucket"
msgid "From Bitbucket Server"
-msgstr ""
+msgstr "來自 BitBucket 伺æœå™¨"
msgid "From FogBugz"
msgstr "從 FogBugz"
@@ -3544,16 +4213,16 @@ msgid "From Google Code"
msgstr "從 Google Code"
msgid "From issue creation until deploy to production"
-msgstr "從議題建立直到部署至營é‹ç’°å¢ƒ"
+msgstr "從議題建立直到部署至生產環境"
msgid "From merge request merge until deploy to production"
-msgstr "從請求被åˆä½µå¾Œç›´åˆ°éƒ¨ç½²è‡³ç‡Ÿé‹ç’°å¢ƒ"
+msgstr "從åˆä½µè«‹æ±‚被åˆä½µï¼Œåˆ°éƒ¨å±¬åˆ°ç”Ÿç”¢ç’°å¢ƒæœŸé–“"
msgid "From milestones:"
-msgstr ""
+msgstr "來自里程碑:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr "從 Kubernetes å¢é›†è©³ç´°è³‡æ–™é ï¼Œå¾žæ‡‰ç”¨ç¨‹å¼åˆ—表中安è£é‹è¡Œå™¨"
+msgstr "從 Kubernetes å¢é›†è©³ç´°è³‡æ–™é ï¼Œå¾žæ‡‰ç”¨ç¨‹å¼åˆ—表中安è£åŸ·è¡Œå™¨"
msgid "GPG Keys"
msgstr "GPG 金鑰"
@@ -3562,14 +4231,17 @@ msgid "General"
msgstr "一般"
msgid "General pipelines"
-msgstr "一般æµæ°´ç·š"
+msgstr "一般管線"
msgid "Generate a default set of labels"
-msgstr "產生é è¨­çš„標籤"
+msgstr "產生é è¨­æ¨™ç±¤é›†"
-msgid "Geo"
+msgid "Generate key"
msgstr ""
+msgid "Geo"
+msgstr "地ç†ä½ç½®"
+
msgid "Geo Nodes"
msgstr "Geo 節點"
@@ -3592,10 +4264,10 @@ msgid "GeoNodes|Data replication lag"
msgstr "資料複製延é²"
msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
-msgstr "åœç”¨ç¯€é»žå°‡æœƒåœæ­¢åŒæ­¥ç¨‹åºï¼Œæ‚¨ç¢ºå®šè¦é€™éº¼åšå—Žï¼Ÿ"
+msgstr "åœç”¨ç¯€é»žå°‡æœƒåœæ­¢åŒæ­¥ç¨‹å¼ï¼Œæ‚¨ç¢ºå®šè¦é€™éº¼åšå—Žï¼Ÿ"
msgid "GeoNodes|Does not match the primary storage configuration"
-msgstr "ä¸ç¬¦åˆä¸»è¦å„²å­˜ç©ºé–“é…ç½®"
+msgstr "ä¸ç¬¦åˆä¸»è¦å„²å­˜ç©ºé–“設定"
msgid "GeoNodes|Failed"
msgstr "失敗"
@@ -3640,7 +4312,7 @@ msgid "GeoNodes|Local attachments"
msgstr "本機附件"
msgid "GeoNodes|Local job artifacts"
-msgstr "本機任務文件"
+msgstr "本機作業檔案"
msgid "GeoNodes|New node"
msgstr "新增節點"
@@ -3657,8 +4329,11 @@ msgstr "未檢查雜湊值"
msgid "GeoNodes|Out of sync"
msgstr "ä¸åŒæ­¥"
-msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
-msgstr "移除節點將會åœæ­¢åŒæ­¥ç¨‹åºï¼Œç¢ºå®šï¼Ÿ"
+msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
+msgstr ""
msgid "GeoNodes|Replication slot WAL"
msgstr "複製 WAL æ’槽"
@@ -3676,10 +4351,10 @@ msgid "GeoNodes|Repositories verified with their counterparts on the Primary nod
msgstr "主節點上與å°æ‡‰æ–¹çš„版本庫已驗證"
msgid "GeoNodes|Repository checksum progress"
-msgstr "版本庫雜湊值程åº"
+msgstr "版本庫雜湊值程å¼"
msgid "GeoNodes|Repository verification progress"
-msgstr "版本庫驗證程åº"
+msgstr "版本庫驗證程å¼"
msgid "GeoNodes|Selective"
msgstr "é¸æ“‡"
@@ -3732,80 +4407,86 @@ msgstr "主節點上與å°æ‡‰æ–¹é©—證的維基已算出雜湊值"
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr "Wiki 已在主è¦ç¯€é»žçš„å°æ‡‰æ–¹é©—證完æˆ"
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr "您使用ä¸å®‰å…¨çš„ HTTP 連線設定 Geo 節點。我們建議使用 HTTPS。"
msgid "Geo|%{name} is scheduled for forced re-download"
-msgstr ""
+msgstr "%{name} 已經排定以用來強制é‡æ–°ä¸‹è¼‰"
msgid "Geo|%{name} is scheduled for re-check"
-msgstr ""
+msgstr "%{name} 已經排定以用來é‡æ–°æª¢æŸ¥"
msgid "Geo|%{name} is scheduled for re-sync"
-msgstr ""
+msgstr "%{name} 已經排定以用來é‡æ–°åŒæ­¥"
msgid "Geo|All"
-msgstr ""
+msgstr "全部"
msgid "Geo|All projects"
msgstr "所有專案"
msgid "Geo|All projects are being scheduled for re-check"
-msgstr ""
+msgstr "正在計畫é‡æ–°æª¢æŸ¥æ‰€æœ‰çš„專案"
msgid "Geo|All projects are being scheduled for re-sync"
-msgstr ""
+msgstr "正在計畫é‡æ–°åŒæ­¥æ‰€æœ‰å°ˆæ¡ˆ"
msgid "Geo|Batch operations"
-msgstr ""
+msgstr "批次æ“作"
msgid "Geo|Could not remove tracking entry for an existing project."
-msgstr ""
+msgstr "無法從存在專案移除追蹤項目。"
msgid "Geo|Failed"
-msgstr ""
+msgstr "失敗"
msgid "Geo|File sync capacity"
msgstr "檔案åŒæ­¥é‡"
msgid "Geo|Geo Status"
-msgstr ""
+msgstr "Geo 狀態"
msgid "Geo|Groups to synchronize"
msgstr "è¦åŒæ­¥çš„群組"
msgid "Geo|In sync"
+msgstr "åŒæ­¥ä¸­"
+
+msgid "Geo|Last repository check run"
msgstr ""
msgid "Geo|Last successful sync"
-msgstr ""
+msgstr "上次æˆåŠŸåŒæ­¥"
msgid "Geo|Last sync attempt"
-msgstr ""
+msgstr "上次嘗試åŒæ­¥"
msgid "Geo|Last time verified"
-msgstr ""
+msgstr "上次驗證時間"
msgid "Geo|Never"
-msgstr ""
+msgstr "æ°¸ä¸"
msgid "Geo|Next sync scheduled at"
-msgstr ""
+msgstr "下次åŒæ­¥æŽ’定於"
msgid "Geo|Not synced yet"
-msgstr ""
+msgstr "尚未åŒæ­¥"
msgid "Geo|Pending"
-msgstr ""
+msgstr "等待中"
msgid "Geo|Pending synchronization"
-msgstr ""
+msgstr "等待åŒæ­¥ä¸­"
msgid "Geo|Pending verification"
-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 "æŸäº›ç¾¤çµ„中的專案"
@@ -3813,29 +4494,32 @@ msgstr "æŸäº›ç¾¤çµ„中的專案"
msgid "Geo|Projects in certain storage shards"
msgstr "æŸäº›å„²å­˜ç©ºé–“碎片中的專案"
-msgid "Geo|Recheck"
+msgid "Geo|Re-verification interval"
msgstr ""
+msgid "Geo|Recheck"
+msgstr "é‡æ–°æª¢æŸ¥"
+
msgid "Geo|Recheck all projects"
-msgstr ""
+msgstr "é‡æ–°æª¢æŸ¥æ‰€æœ‰å°ˆæ¡ˆ"
msgid "Geo|Redownload"
-msgstr ""
+msgstr "é‡æ–°ä¸‹è¼‰"
msgid "Geo|Remove"
-msgstr ""
+msgstr "移除"
msgid "Geo|Repository sync capacity"
msgstr "版本庫åŒæ­¥é‡"
msgid "Geo|Resync"
-msgstr ""
+msgstr "é‡æ–°åŒæ­¥"
msgid "Geo|Resync all projects"
-msgstr ""
+msgstr "é‡æ–°åŒæ­¥æ‰€æœ‰å°ˆæ¡ˆ"
msgid "Geo|Retry count"
-msgstr ""
+msgstr "é‡è©¦æ¬¡æ•¸"
msgid "Geo|Select groups to replicate."
msgstr "é¸æ“‡è¦è¤‡è£½çš„群組。"
@@ -3844,64 +4528,73 @@ msgid "Geo|Shards to synchronize"
msgstr "è¦åŒæ­¥çš„碎片"
msgid "Geo|Status"
-msgstr ""
+msgstr "狀態"
msgid "Geo|Synced"
-msgstr ""
+msgstr "å·²åŒæ­¥"
msgid "Geo|Synchronization failed - %{error}"
-msgstr ""
+msgstr "åŒæ­¥å¤±æ•— - %{error}"
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
-msgstr ""
+msgstr "專案 (%{project_id}) 的追蹤項目已經順利移除。"
msgid "Geo|Tracking entry will be removed. Are you sure?"
-msgstr ""
+msgstr "將會移除追蹤項目,確定?"
msgid "Geo|Unknown state"
-msgstr ""
+msgstr "未知狀態"
msgid "Geo|Verification capacity"
msgstr "驗證能力"
msgid "Geo|Verification failed - %{error}"
-msgstr ""
+msgstr "驗證失敗 - %{error}"
msgid "Geo|Waiting for scheduler"
-msgstr ""
+msgstr "等待排定器"
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
+msgstr "ç›®å‰æ­£åœ¨ç€è¦½æ¬¡è¦çš„ Geo <b>唯讀</b>節點,如果你想è¦é€²è¡Œä»»ä½•å¯«å…¥æ“ä½œï¼Œå¿…é ˆè¨ªå• %{primary_node}。"
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
-msgstr ""
+msgstr "ç›®å‰æ­£åœ¨ç€è¦½æ¬¡è¦çš„ Geo <b>唯讀</b>節點,你å¯ä»¥åœ¨æ­¤é é¢é€²è¡Œæœ‰é™çš„變更或執行有é™çš„æ“作。"
msgid "Geo|You need a different license to use Geo replication"
-msgstr ""
+msgstr "您需è¦ä¸åŒçš„授權以使用 Geo 副本"
msgid "Geo|misconfigured"
-msgstr ""
+msgstr "設定錯誤"
msgid "Geo|primary"
-msgstr ""
+msgstr "主è¦"
msgid "Geo|secondary"
-msgstr ""
+msgstr "次è¦"
msgid "Get a free instance review"
+msgstr "å–å¾—å…費試用評估"
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Getting started with releases"
msgstr ""
msgid "Git"
msgstr "Git"
+msgid "Git global setup"
+msgstr ""
+
msgid "Git repository URL"
-msgstr "Git 檔案庫網å€"
+msgstr "Git 版本庫網å€"
msgid "Git revision"
-msgstr "Git 修訂版本"
+msgstr "Git 修訂版"
msgid "Git strategy for pipelines"
-msgstr "Git æµæ°´ç·šç­–ç•¥"
+msgstr "Git 管線策略"
msgid "Git version"
msgstr "Git 版本"
@@ -3921,9 +4614,15 @@ msgstr "GitLab 群組執行器å¯ä»¥ç‚ºæ­¤ç¾¤çµ„的所有專案執行程å¼ç¢¼ã€
msgid "GitLab Import"
msgstr "匯入 GitLab"
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr "GitLab 使用者"
+msgid "GitLab metadata URL"
+msgstr ""
+
msgid "GitLab project export"
msgstr "匯出 GitLab 專案"
@@ -3931,13 +4630,13 @@ msgid "GitLab single sign on URL"
msgstr "GitLab URL 單一登入"
msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "GitLab 將會在後å°é€²è¡Œç”¢ç”Ÿ GitLab 資料庫å‡å CSV 的作業,該資料庫將會上傳到您設定的å°è±¡å„²å­˜ç›®éŒ„。"
+msgstr "GitLab 將會在後å°é€²è¡Œç”¢ç”Ÿ GitLab 資料庫å‡å CSV 的作業,該資料庫將會上傳到您設定的物件儲存資料夾。"
msgid "GitLab.com import"
msgstr "匯入 GitLab.com"
msgid "GitLab’s issue tracker"
-msgstr ""
+msgstr "GitLab çš„å•é¡Œè¿½è¹¤å™¨"
msgid "Gitaly"
msgstr "Gitaly"
@@ -3946,7 +4645,7 @@ msgid "Gitaly Servers"
msgstr "Gitaly 伺æœå™¨"
msgid "Gitaly|Address"
-msgstr "地å€"
+msgstr "ä½å€"
msgid "Gitea Host URL"
msgstr "Gitea 主機 URL"
@@ -3954,6 +4653,9 @@ msgstr "Gitea 主機 URL"
msgid "Gitea Import"
msgstr "匯入 Gitea"
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr "返回"
@@ -3961,10 +4663,10 @@ msgid "Go back"
msgstr "上一é "
msgid "Go to"
-msgstr ""
+msgstr "å‰å¾€"
msgid "Go to %{link_to_google_takeout}."
-msgstr ""
+msgstr "å‰å¾€ %{link_to_google_takeout}。"
msgid "Google Code import"
msgstr "匯入 Google Code"
@@ -3973,10 +4675,13 @@ msgid "Google Takeout"
msgstr "Google Takeout"
msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
-msgstr "Google 身份驗證ä¸æ˜¯ %{link_to_documentation}。如果您想使用此æœå‹™ï¼Œè«‹è«®è©¢ç®¡ç†å“¡ã€‚"
+msgstr "Google 身份驗證ä¸æ˜¯ %{link_to_documentation}。如果您想使用此æœå‹™ï¼Œè«‹è«®è©¢ GitLab 管ç†å“¡ã€‚"
msgid "Got it!"
-msgstr "明白ï¼"
+msgstr "了解ï¼"
+
+msgid "Grant access"
+msgstr ""
msgid "Graph"
msgstr "圖表"
@@ -3997,19 +4702,19 @@ msgid "Group Runners"
msgstr "群組執行器"
msgid "Group SAML must be enabled to test"
-msgstr ""
+msgstr "必須啟動 SAML æ‰èƒ½é€²è¡Œæ¸¬è©¦"
msgid "Group URL"
-msgstr ""
+msgstr "群組 URL"
msgid "Group avatar"
msgstr "群組頭åƒ"
msgid "Group description"
-msgstr ""
+msgstr "群組說明"
msgid "Group description (optional)"
-msgstr ""
+msgstr "群組說明 (é¸å¡«)"
msgid "Group details"
msgstr "群組詳細資訊"
@@ -4021,6 +4726,12 @@ msgid "Group maintainers can register group runners in the %{link}"
msgstr "群組維護者å¯ä»¥åœ¨ %{link} 註冊群組執行器"
msgid "Group name"
+msgstr "群組å稱"
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group:"
msgstr ""
msgid "Group: %{group_name}"
@@ -4029,9 +4740,6 @@ msgstr "群組:%{group_name}"
msgid "GroupRoadmap|From %{dateWord}"
msgstr "從 %{dateWord}"
-msgid "GroupRoadmap|Loading roadmap"
-msgstr "正在讀å–開發è—圖"
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "å–å¾— Epic 時發生錯誤。"
@@ -4041,62 +4749,62 @@ msgstr "抱歉,沒有任何 Epic 符åˆæ‚¨çš„æœå°‹ã€‚"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "開發è—圖顯示時間軸上您的 Epic 進度"
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
-
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "è‹¥è¦æ“´å¤§æ‚¨çš„æœå°‹ï¼Œè«‹å˜—試修改或移除篩é¸å™¨ã€‚月檢視中,åªæœƒé¡¯ç¤ºä¸Šå€‹æœˆã€é€™å€‹æœˆã€å’ŒæŽ¥ä¸‹ä¾†äº”個月的 Epic &ndash; 從 %{startDate} 到 %{endDate}。"
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "è‹¥è¦æ“´å¤§æ‚¨çš„æœå°‹ï¼Œè«‹å˜—試修改或移除篩é¸å™¨ã€‚季度檢視中,åªæœƒé¡¯ç¤ºä¸Šå€‹å­£åº¦ã€é€™å€‹å­£åº¦ã€å’ŒæŽ¥ä¸‹ä¾†å››å€‹å­£åº¦çš„ Epic &ndash; 從 %{startDate} 到 %{endDate}。"
-
-msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "è‹¥è¦æ“´å¤§æ‚¨çš„æœå°‹ï¼Œè«‹å˜—試修改或移除篩é¸å™¨ã€‚週檢視中,åªæœƒé¡¯ç¤ºä¸Šé€±ã€é€™é€±ã€å’ŒæŽ¥ä¸‹ä¾†å››é€±çš„ Epic &ndash; 從 %{startDate} 到 %{endDate}。"
-
msgid "GroupRoadmap|Until %{dateWord}"
msgstr "直到 %{dateWord}"
msgid "GroupSettings|Badges"
+msgstr "徵章"
+
+msgid "GroupSettings|Custom project templates"
msgstr ""
msgid "GroupSettings|Customize your group badges."
-msgstr ""
+msgstr "自訂您的群組徵章。"
msgid "GroupSettings|Learn more about badges."
+msgstr "了解關於徵章的更多資訊。"
+
+msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
-msgstr "ç¦æ­¢èˆ‡å…¶ä»–群組共享 %{group} 中的專案"
+msgstr "ç¦æ­¢èˆ‡å…¶ä»–群組分享 %{group} 中的專案"
+
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
-msgstr "這個設定已經套用至 %{ancestor_group},並覆蓋了它的å­ç¾¤çµ„設定。"
+msgstr "這個設定已經套用至 %{ancestor_group},並已覆蓋了å­ç¾¤çµ„設定。"
msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
-msgstr "此設定已經套用在 %{ancestor_group}。若è¦èˆ‡å…¶ä»–群組共享此群組中的專案,請è¯ç¹«æ“有者覆蓋這個設定或者 %{remove_ancestor_share_with_group_lock}"
+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 "此設定已經套用至 %{ancestor_group}。你å¯ä»¥è¦†è“‹æ­¤è¨­å®šæˆ–是 %{remove_ancestor_share_with_group_lock}"
+msgstr "此設定已經套用至 %{ancestor_group}。你å¯ä»¥è¦†è“‹æ­¤è¨­å®šæˆ–是執行 %{remove_ancestor_share_with_group_lock}"
msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
-msgstr "除éžç¾¤çµ„æ“有者覆蓋此設定,å¦å‰‡æ­¤è¨­å®šå°‡å¥—用在所有å­ç¾¤çµ„。此外,如果沒有手動移除原本已經æ“有ç€è¦½å°ˆæ¡ˆæ¬Šé™çš„群組,這些群組ä»å¯ç¹¼çºŒç€è¦½ã€‚"
+msgstr "除éžç¾¤çµ„所有者覆蓋了設定,å¦å‰‡æ­¤è¨­å®šå°‡å¥—用到所有å­ç¾¤çµ„。先å‰èƒ½å­˜å–此專案的群組ä»å¯ç¹¼çºŒå­˜å–,除éžæ‰‹å‹•ç§»é™¤å­˜å–權é™ã€‚"
msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
-msgstr "無法啟用上級群組的「共享群組鎖ã€ã€‚åªæœ‰ä¸Šç´šç¾¤çµ„的所有者æ‰å¯å•Ÿç”¨ã€‚"
+msgstr "當上層群組的「群組分享鎖ã€å•Ÿç”¨æ™‚,除了上層群組的所有者以外的人都ä¸èƒ½åœç”¨ã€‚"
msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
-msgstr "從 %{ancestor_group_name} 中移除共享群組鎖"
+msgstr "移除 %{ancestor_group_name} 的群組分享鎖"
msgid "Groups"
msgstr "群組"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr "群組也å¯ä»¥å‰µå»º %{subgroup_docs_link_start}å­ç¾¤çµ„%{subgroup_docs_link_end}。"
+msgstr "群組也å¯ä»¥å»ºç«‹ %{subgroup_docs_link_start}å­ç¾¤çµ„%{subgroup_docs_link_end}。"
+
+msgid "Groups with access to <strong>%{project_name}</strong>"
+msgstr ""
msgid "GroupsDropdown|Frequently visited"
msgstr "最近ç€è¦½"
@@ -4123,43 +4831,43 @@ msgid "GroupsEmptyState|A group is a collection of several projects."
msgstr "群組是數個專案的集åˆã€‚"
msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
-msgstr "當你在群組下建立一個專案,這個專案的é‹ä½œæ–¹å¼å°±å¦‚åŒä¸€å€‹è³‡æ–™å¤¾ã€‚"
+msgstr "當你在群組下組織一個專案,這個專案的é‹ä½œæ–¹å¼å°±å¦‚åŒè³‡æ–™å¤¾èˆ¬ã€‚"
msgid "GroupsEmptyState|No groups found"
msgstr "找ä¸åˆ°ç¾¤çµ„"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
-msgstr "ä½ å¯ä»¥ç®¡ç†ç¾¤çµ„內所有æˆå“¡çš„æ¯å€‹å°ˆæ¡ˆçš„å­˜å–權é™"
+msgstr "您能管ç†ç¾¤çµ„æˆå“¡çš„權é™ï¼Œä¸¦å¯å­˜å–群組中的æ¯å€‹å°ˆæ¡ˆã€‚"
msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
-msgstr ""
+msgstr "確定退出「%{fullName}ã€ç¾¤çµ„?"
msgid "GroupsTree|Create a project in this group."
-msgstr "在此群組建立新的專案"
+msgstr "在此群組建立新專案。"
msgid "GroupsTree|Create a subgroup in this group."
-msgstr "在此群組中建立å­ç¾¤çµ„"
+msgstr "在此群組中建立å­ç¾¤çµ„。"
msgid "GroupsTree|Edit group"
msgstr "編輯群組"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
-msgstr "無法離開群組,請確ä¿æ‚¨ä¸æ˜¯å”¯ä¸€çš„æ“有者。"
+msgstr "無法退出群組。請確ä¿æ‚¨ä¸æ˜¯å”¯ä¸€çš„所有者。"
msgid "GroupsTree|Leave this group"
-msgstr "離開此群組"
+msgstr "退出此群組"
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|Search by name"
-msgstr ""
+msgstr "ä¾å稱æœå°‹"
msgid "Have your users email"
msgstr "有來自您使用者的信件"
@@ -4171,22 +4879,22 @@ msgid "Health Check"
msgstr "å¥åº·æª¢æŸ¥"
msgid "Health information can be retrieved from the following endpoints. More information is available"
-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 "Help"
-msgstr "説明"
+msgstr "說明"
msgid "Help page"
msgstr "說明é é¢"
@@ -4195,26 +4903,32 @@ msgid "Help page text and support page url."
msgstr "說明é é¢æ–‡å­—與支æ´é é¢é€£çµ"
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr "這裡是è¦åŠ é€²åŽ»é ç«¯ä¼ºæœå™¨çš„公共 SSH 金鑰。欲知更多資訊,請åƒè€ƒæª”案。"
+
+msgid "Hide file browser"
msgstr ""
msgid "Hide host keys manual input"
-msgstr ""
+msgstr "éš±è—主機金鑰手動輸入"
msgid "Hide payload"
-msgstr ""
+msgstr "éš±è—酬載"
msgid "Hide value"
msgid_plural "Hide values"
-msgstr[0] "éš±è—資料"
+msgstr[0] "éš±è—數值"
-msgid "Hide whitespace changes"
-msgstr "éš±è—空白變化"
+msgid "Hide values"
+msgstr ""
msgid "History"
-msgstr "æ­·å²"
+msgstr "æ­·å²è¨˜éŒ„"
msgid "Housekeeping successfully started"
-msgstr "已開始維護"
+msgstr "已順利開始維護程åº"
+
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
msgid "I accept the %{terms_link}"
msgstr "æˆ‘æŽ¥å— %{terms_link}"
@@ -4226,13 +4940,13 @@ msgid "ID"
msgstr "ID"
msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
-msgstr ""
+msgstr "å…許使用 CodeSandbox ä½¿ç”¨è€…ç«¯è©•ä¼°ç‰ˆåœ¨ç¶²é  IDE 來å³æ™‚é è¦½ JavaScript 專案"
msgid "IDE|Back"
-msgstr ""
+msgstr "IDE|返回"
msgid "IDE|Client side evaluation"
-msgstr ""
+msgstr "IDE|使用者端評估"
msgid "IDE|Commit"
msgstr "æ交"
@@ -4241,28 +4955,28 @@ msgid "IDE|Edit"
msgstr "編輯"
msgid "IDE|Get started with Live Preview"
-msgstr ""
+msgstr "IDE|開始å³æ™‚é è¦½"
msgid "IDE|Go to project"
-msgstr ""
+msgstr "å‰å¾€å°ˆæ¡ˆ"
msgid "IDE|Live Preview"
-msgstr ""
+msgstr "IDE|å³æ™‚é è¦½"
msgid "IDE|Open in file view"
msgstr "以檔案顯示開啟"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
-msgstr ""
+msgstr "ä½¿ç”¨ç¶²é  IDE 使用者端評估版來é è¦½æ‚¨çš„網é æ‡‰ç”¨ç¨‹å¼"
msgid "IDE|Refresh preview"
-msgstr ""
+msgstr "é‡æ–°è¼‰å…¥é è¦½"
msgid "IDE|Review"
-msgstr "審閱"
+msgstr "檢閱"
msgid "IP Address"
-msgstr ""
+msgstr "IP ä½å€"
msgid "Identifier"
msgstr "識別碼"
@@ -4273,9 +4987,12 @@ msgstr "身份"
msgid "Identity provider single sign on URL"
msgstr "身份æ供者的 URL 單一登入"
-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."
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
msgstr ""
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr "如果åœç”¨ï¼Œå‰‡ä¸æœƒä½¿ç”¨é ç«¯å‰¯æœ¬çš„æ交自動更新分支的本機分支,以防止本機資料被刪除。如果é è¨­åˆ†æ”¯ (%{default_branch}) 已被å†åˆ†æ”¯ä¸”無法更新時,則é¡åƒå°‡æœƒå¤±æ•—。其他å†åˆ†æ”¯çš„分支自動被忽略。"
+
msgid "If disabled, the access level will depend on the user's permissions in the project."
msgstr "如果ç¦ç”¨ï¼Œå­˜å–等級將å–決於使用者在專案中的權é™ã€‚"
@@ -4286,13 +5003,13 @@ msgid "If enabled, access to projects will be validated on an external service u
msgstr "如果啟用,將會使用其分類標籤在外部æœå‹™ä¸Šé©—證專案的存å–。"
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
-msgstr "如果使用 GitHub,你將會看到用於æ交與推é€è«‹æ±‚çš„ GitHub æµæ°´ç·šç‹€æ…‹ã€‚%{more_info_link}"
+msgstr "如果使用 GitHub,你將會看到用於æ交與推é€è«‹æ±‚çš„ GitHub 管線狀態。%{more_info_link}"
msgid "If you already have files you can push them using the %{link_to_cli} below."
msgstr "如果你已經æ“有檔案,你å¯ä»¥ä½¿ç”¨ %{link_to_cli} 推é€ä»–們。"
msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr "如果你的 HTTP 檔案庫沒有公開存å–,請增加驗證欄ä½åˆ°ç¶²å€ä¸Šï¼š<code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr "如果你的 HTTP 版本庫沒有公開存å–,請增加驗證欄ä½åˆ°ç¶²å€ä¸Šï¼š<code>https://username:password@gitlab.company.com/group/project.git</code>."
msgid "ImageDiffViewer|2-up"
msgstr "2-up"
@@ -4303,9 +5020,15 @@ msgstr "Onion 主題"
msgid "ImageDiffViewer|Swipe"
msgstr "Swipe"
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr "匯入"
+msgid "Import CSV"
+msgstr ""
+
msgid "Import Projects from Gitea"
msgstr "從 Gitea 匯入專案"
@@ -4316,43 +5039,58 @@ msgid "Import all projects"
msgstr "匯入所有專案"
msgid "Import all repositories"
-msgstr "匯入所有檔案庫"
+msgstr "匯入所有版本庫"
msgid "Import an exported GitLab project"
-msgstr ""
+msgstr "匯入一個已經匯出的 GitLab 專案"
msgid "Import in progress"
-msgstr "匯入中..."
+msgstr "匯入中…"
-msgid "Import multiple repositories by uploading a manifest file."
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
msgstr ""
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr "é€éŽä¸Šå‚³ manifest 檔案,匯入多個版本庫。"
+
msgid "Import project"
msgstr "匯入專案"
-msgid "Import projects from Bitbucket"
+msgid "Import project members"
msgstr ""
+msgid "Import projects from Bitbucket"
+msgstr "從 Bitbucket 匯入專案"
+
msgid "Import projects from Bitbucket Server"
-msgstr ""
+msgstr "從 Bitbucket 匯入專案"
msgid "Import projects from FogBugz"
msgstr "從 FogBugz 匯入專案"
msgid "Import projects from GitLab.com"
-msgstr ""
+msgstr "從 GitLab.com 匯入專案"
msgid "Import projects from Google Code"
-msgstr ""
+msgstr "從 Google Code 匯入專案"
msgid "Import repositories from Bitbucket Server"
-msgstr ""
+msgstr "從 Bitbucket 匯入版本庫"
msgid "Import repositories from GitHub"
-msgstr "從 GitHub 匯入檔案庫"
+msgstr "從 GitHub 匯入版本庫"
msgid "Import repository"
-msgstr "匯入檔案庫"
+msgstr "匯入版本庫"
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr "連線版本庫自"
@@ -4367,50 +5105,68 @@ msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition.
msgstr "使用進階全域æœå°‹å’Œ GitLab ä¼æ¥­ç‰ˆæœ¬ä¾†æ”¹é€²æœå°‹ã€‚"
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr "為了è¦å•Ÿç”¨å¯¦ä¾‹ç­‰ç´šçš„統計,請詢å•ç®¡ç†å“¡ä»¥å•Ÿç”¨%{usage_ping_link_start}ä½¿ç”¨æƒ…æ³ ping%{usage_ping_link_end}。"
+
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
-msgstr ""
+msgstr "在下一步中,你將能é¸æ“‡è¦åŒ¯å…¥çš„專案。"
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
-msgstr "包括所有用戶必須接å—çš„æœå‹™æ¢æ¬¾å”議和隱ç§æ”¿ç­–。"
+msgstr "包括所有使用者必須接å—çš„æœå‹™æ¢æ¬¾å”議和隱ç§æ”¿ç­–。"
+
+msgid "Include merge request description"
+msgstr ""
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr "如果需è¦ï¼Œè«‹åœ¨URL中夾帶使用者å稱: <code>https://username@gitlab.company.com/group/project.git</code>。"
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
msgstr ""
msgid "Incompatible Project"
msgstr "ä¸ç›¸å®¹çš„專案"
msgid "Indicates whether this runner can pick jobs without tags"
-msgstr ""
+msgstr "指示這個執行器是å¦èƒ½é¸æ“‡æ²’有標籤的工作"
msgid "Inline"
msgstr "內嵌"
msgid "Input host keys manually"
-msgstr ""
+msgstr "手動輸入主機金鑰"
msgid "Input your repository URL"
+msgstr "輸入您的版本庫URL"
+
+msgid "Insert suggestion"
msgstr ""
msgid "Install GitLab Runner"
msgstr "å®‰è£ GitLab 執行器"
msgid "Install Runner on Kubernetes"
-msgstr "在 Kubernetes 上安è£é‹è¡Œå™¨"
+msgstr "在 Kubernetes 上安è£åŸ·è¡Œå™¨"
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "實例"
msgid "Instance Statistics"
-msgstr ""
+msgstr "實例統計"
msgid "Instance Statistics visibility"
-msgstr ""
+msgstr "實例統計å¯è¦‹åº¦"
msgid "Instance does not support multiple Kubernetes clusters"
-msgstr "主機沒有支æ´å¤šå€‹ Kubernetes å¢é›†"
+msgstr "主機ä¸æ”¯æ´å¤šå€‹ Kubernetes å¢é›†"
msgid "Integrations"
msgstr "æ•´åˆ"
@@ -4419,29 +5175,50 @@ msgid "Integrations Settings"
msgstr "æ•´åˆè¨­å®š"
msgid "Interested parties can even contribute by pushing commits if they want to."
-msgstr "有興趣的人甚至å¯ä»¥é€šéŽæŽ¨é€æ›´å‹•ç´€éŒ„åšå‡ºè²¢ç»ï¼Œå¦‚果他們願æ„的話。"
+msgstr "有興趣的使用者甚至å¯ä»¥é€éŽæŽ¨é€æ交åšå‡ºè²¢ç»ï¼Œå¦‚果他們願æ„的話。"
+
+msgid "Internal"
+msgstr ""
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
-msgstr "內部 - 任何登入的使用者都å¯ä»¥æŸ¥çœ‹è©²ç¾¤çµ„åŠå…¶å°ˆæ¡ˆ"
+msgstr "內部專案 - 任何登入的使用者都能檢視該群組åŠå…¶å°ˆæ¡ˆ"
msgid "Internal - The project can be accessed by any logged in user."
-msgstr "內部 - 任何登入的使用者都å¯ä»¥å­˜å–此專案"
+msgstr "內部專案 - 任何登入的使用者都能存å–此專案"
msgid "Internal users"
-msgstr ""
+msgstr "內部使用者"
msgid "Interval Pattern"
-msgstr "循環週期"
+msgstr "循環樣å¼"
msgid "Introducing Cycle Analytics"
msgstr "週期分æžç°¡ä»‹"
+msgid "Introducing Your Conversational Development Index"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
+msgstr "邀請"
+
+msgid "Invite group"
msgstr ""
-msgid "Issue"
+msgid "Invite member"
+msgstr ""
+
+msgid "Invoke Count"
msgstr ""
+msgid "Invoke Time"
+msgstr ""
+
+msgid "Issue"
+msgstr "å•é¡Œ"
+
msgid "Issue Boards"
msgstr "議題看æ¿"
@@ -4457,44 +5234,65 @@ msgstr "看æ¿"
msgid "IssueBoards|Boards"
msgstr "看æ¿"
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
msgid "Issues"
msgstr "議題"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
-msgstr "è­°é¡Œå¯ä»¥æ˜¯bug,任務或想法來討論。此外,å•é¡Œæ˜¯å¯æœå°‹å’ŒéŽæ¿¾çš„。"
+msgstr "è­°é¡Œå¯ä»¥è¨Žè«–臭蟲ã€å·¥ä½œä»¥åŠæƒ³æ³•ã€‚此外,å•é¡Œæ˜¯å¯æœå°‹å’ŒéŽæ¿¾çš„。"
msgid "Issues closed"
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|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 "è¦åœ¨ä¸Šé¢çš„篩é¸æ¢ä»¶ä¸­æ“´å¤§æœå°‹ç¯„åœï¼Œè®Šæ›´æˆ–刪除篩é¸æ¢ä»¶"
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
-msgid "Jaeger URL"
+msgid "It's you"
msgstr ""
+msgid "Jaeger URL"
+msgstr "Jaeger 網å€"
+
msgid "Jaeger tracing"
-msgstr ""
+msgstr "Jaeger 追蹤"
msgid "Jan"
msgstr "一月"
@@ -4503,54 +5301,60 @@ msgid "January"
msgstr "一月"
msgid "Job"
-msgstr "任務"
+msgstr "作業"
msgid "Job has been erased"
msgstr "工作已被抹除"
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
msgid "Jobs"
-msgstr "任務"
+msgstr "作業"
msgid "Job|Browse"
-msgstr ""
+msgstr "工作|ç€è¦½"
msgid "Job|Complete Raw"
-msgstr ""
+msgstr "工作|完全Raw"
msgid "Job|Download"
-msgstr ""
+msgstr "工作|下載"
msgid "Job|Erase job log"
-msgstr ""
+msgstr "工作|刪除工作記錄"
msgid "Job|Job artifacts"
-msgstr ""
+msgstr "工作æˆå“"
msgid "Job|Job has been erased"
-msgstr ""
+msgstr "工作|工作已被刪除"
msgid "Job|Job has been erased by"
-msgstr ""
+msgstr "工作|工作已被刪除,刪除者:"
msgid "Job|Keep"
-msgstr ""
+msgstr "工作|ä¿æŒ"
msgid "Job|Scroll to bottom"
-msgstr ""
+msgstr "工作|移到底部"
msgid "Job|Scroll to top"
-msgstr ""
+msgstr "工作|回到頂部"
msgid "Job|Show complete raw"
-msgstr ""
+msgstr "顯示完æˆçš„ Raw"
msgid "Job|The artifacts were removed"
-msgstr ""
+msgstr "已刪除æˆå“"
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -4565,29 +5369,35 @@ msgstr "六月"
msgid "June"
msgstr "六月"
+msgid "Key (PEM)"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
msgid "Kubernetes Cluster"
-msgstr "Kuberneteså¢é›†"
+msgstr "Kubernetes å¢é›†"
+
+msgid "Kubernetes Clusters"
+msgstr ""
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
-msgstr "Kuberneteså¢é›†å»ºç«‹è¶…時;%{timeout}"
+msgstr "Kubernetes å¢é›†å»ºç«‹ç­‰å¾…時間逾時;%{timeout}"
msgid "Kubernetes cluster integration was not removed."
-msgstr "Kubernetes å¢é›†æ•´åˆæœªè¢«åˆªé™¤ã€‚"
+msgstr "Kubernetes å¢é›†æ•´åˆæœªç§»é™¤ã€‚"
msgid "Kubernetes cluster integration was successfully removed."
-msgstr "Kubernetes å¢é›†æ•´åˆå·²æˆåŠŸè¢«åˆªé™¤ã€‚"
+msgstr "Kubernetes å¢é›†æ•´åˆå·²æˆåŠŸç§»é™¤ã€‚"
msgid "Kubernetes cluster was successfully updated."
msgstr "Kubernetes å¢é›†å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Kubernetes configured"
-msgstr "Kubernetes å·²é…ç½®"
+msgstr "Kubernetes 已設定"
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
-msgstr "Kubernetesæœå‹™æ•´åˆå·²è¢«æ£„用。 %{deprecated_message_content} 您的 Kubernetes å¢é›†ä½¿ç”¨æ–°çš„ <a href=\"%{url}\"/>Kubernetes å¢é›†</a> é é¢"
+msgstr "Kubernetes æœå‹™æ•´åˆå·²è¢«æ£„用。%{deprecated_message_content} 而ç¾åœ¨æ‚¨çš„ Kubernetes å¢é›†å·²æ”¹ç”¨æ–°çš„ <a href=\"%{url}\"/>Kubernetes å¢é›†</a> é é¢"
msgid "LFS"
msgstr "LFS"
@@ -4602,7 +5412,7 @@ msgid "Label"
msgstr "標籤"
msgid "Label actions dropdown"
-msgstr "標籤æ“作下拉èœå–®"
+msgstr "標籤æ“作下拉é¸å–®"
msgid "Label lists show all issues with the selected label."
msgstr "標籤列表顯示了é¸å–標籤的所有å•é¡Œã€‚"
@@ -4623,7 +5433,7 @@ msgid "Labels can be applied to %{features}. Group labels are available for any
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 "標籤å¯ä»¥ç”¨æ–¼è­°é¡Œå’Œåˆä½µè«‹æ±‚。"
@@ -4635,31 +5445,37 @@ msgid "Labels|Promote Label"
msgstr "æå‡æ¨™ç±¤"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
-msgstr ""
+msgstr "æå‡ %{labelTitle} å°‡å¯ä»¥è®“所有 %{groupName} 內的專案都使用此標籤。ç¾æœ‰ç›¸åŒå稱的標籤將被åˆä½µã€‚該æ“作ä¸å¯å¾©åŽŸã€‚"
msgid "Large File Storage"
-msgstr ""
+msgstr "大檔案儲存"
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "最近 %d 天"
msgid "Last Pipeline"
-msgstr "最新æµæ°´ç·š"
+msgstr "最近一次管線"
+
+msgid "Last activity"
+msgstr ""
msgid "Last commit"
-msgstr "最後更動記錄"
+msgstr "最後一次æ交"
msgid "Last contact"
-msgstr ""
+msgstr "上次è¯ç¹«æ–¼"
msgid "Last edited %{date}"
-msgstr "最後編輯於 %{date}"
+msgstr "最後編輯時間:%{date}"
msgid "Last edited by %{name}"
msgstr "最後由 %{name} 編輯"
msgid "Last reply by"
+msgstr "最後回應由"
+
+msgid "Last seen"
msgstr ""
msgid "Last update"
@@ -4669,7 +5485,7 @@ msgid "Last updated"
msgstr "上次更新"
msgid "LastPushEvent|You pushed to"
-msgstr "您上傳了"
+msgstr "您推é€äº†"
msgid "LastPushEvent|at"
msgstr "æ–¼"
@@ -4677,26 +5493,50 @@ msgstr "æ–¼"
msgid "Latest changes"
msgstr "最新修改"
+msgid "Latest pipeline for this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
msgid "Learn more"
msgstr "進一步了解"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr "了解更多有關 %{issue_boards_url} 的資訊,å¯ä»¥é€éŽæ¨™ç±¤ã€è² è²¬äººã€é‡Œç¨‹ç¢‘來建立追蹤議題列表。如果您發ç¾è­°é¡Œçœ‹æ¿ä¸Šå°‘了一些資訊,請在 %{gitlab_issues_url} 建立議題。"
+
+msgid "Learn more about Auto DevOps"
msgstr ""
msgid "Learn more about Kubernetes"
msgstr "了解更多端於 Kubernetes 的資訊"
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about incoming email addresses"
+msgstr ""
+
msgid "Learn more about protected branches"
msgstr "進一步了解å—ä¿è­·çš„分支"
msgid "Learn more in the"
-msgstr "了解更多"
+msgstr "進一步了解於"
msgid "Learn more in the|pipeline schedules documentation"
-msgstr "æµæ°´ç·šæŽ’程說明文件"
+msgstr "排程管線說明文件"
msgid "Leave"
-msgstr "離開"
+msgstr "退出"
msgid "Leave group"
msgstr "退出群組"
@@ -4705,89 +5545,89 @@ msgid "Leave project"
msgstr "退出專案"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
-msgstr ""
+msgstr "å°‡\"檔案類型\"å’Œ\"傳éžæ–¹æ³•\"é¸é …ä¿ç•™ç‚ºå…¶é è¨­å€¼ã€‚"
msgid "License"
msgstr "授權"
msgid "LicenseManagement|Add a license"
-msgstr ""
+msgstr "增加許å¯è­‰"
msgid "LicenseManagement|Add licenses manually to approve or blacklist"
-msgstr ""
+msgstr "手動增加許å¯è­‰ä»¥æ‰¹å‡†æˆ–å°éŽ–"
msgid "LicenseManagement|Approve"
-msgstr ""
+msgstr "批准"
msgid "LicenseManagement|Approve license"
-msgstr ""
+msgstr "批准授權"
msgid "LicenseManagement|Approve license?"
-msgstr ""
+msgstr "是å¦æ‰¹å‡†æŽˆæ¬Šï¼Ÿ"
msgid "LicenseManagement|Approved"
-msgstr ""
+msgstr "已批准"
msgid "LicenseManagement|Blacklist"
-msgstr ""
+msgstr "黑åå–®"
msgid "LicenseManagement|Blacklist license"
-msgstr ""
+msgstr "將授權加入到黑åå–®"
msgid "LicenseManagement|Blacklist license?"
-msgstr ""
+msgstr "是å¦å°‡æŽˆæ¬ŠåŠ å…¥åˆ°é»‘å單?"
msgid "LicenseManagement|Blacklisted"
-msgstr ""
+msgstr "已加入到黑åå–®"
msgid "LicenseManagement|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "LicenseManagement|License"
-msgstr ""
+msgstr "授權"
msgid "LicenseManagement|License Management"
-msgstr ""
+msgstr "授權管ç†"
msgid "LicenseManagement|License details"
-msgstr ""
+msgstr "授權詳細資訊"
msgid "LicenseManagement|License name"
-msgstr ""
+msgstr "許å¯è­‰å稱"
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
-msgstr ""
+msgstr "管ç†æ­¤å°ˆæ¡ˆä¸­å·²æ‰¹å‡†å’Œå·²åŠ åˆ°é»‘å單的授權"
msgid "LicenseManagement|Packages"
-msgstr ""
+msgstr "套件"
msgid "LicenseManagement|Remove license"
-msgstr ""
+msgstr "移除授權"
msgid "LicenseManagement|Remove license?"
-msgstr ""
+msgstr "是å¦ç§»é™¤æŽˆæ¬Šï¼Ÿ"
msgid "LicenseManagement|Submit"
-msgstr ""
+msgstr "é€å‡º"
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
-msgstr ""
+msgstr "此專案目å‰æ²’有已批准或已加到黑å單的授權"
msgid "LicenseManagement|This license already exists in this project."
-msgstr ""
+msgstr "此許å¯è­‰å·²ç¶“存在此專案中。"
msgid "LicenseManagement|URL"
-msgstr ""
+msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
-msgstr ""
+msgstr "您正打算從此專案移除此授權:%{name}"
msgid "Licenses"
-msgstr ""
+msgstr "授權"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
-msgstr[0] ""
+msgstr[0] "é™åˆ¶æœ€å¤šé¡¯ç¤º %d 個活動"
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -4802,26 +5642,32 @@ msgid "List available repositories"
msgstr "列出å¯ç”¨çš„版本庫"
msgid "List view"
-msgstr ""
+msgstr "列表顯示"
msgid "List your Bitbucket Server repositories"
-msgstr ""
+msgstr "列出 BitBucket 伺æœå™¨ç‰ˆæœ¬åº«"
msgid "List your GitHub repositories"
-msgstr "列出您 GitHub 的檔案庫"
+msgstr "列出您 GitHub 的版本庫"
msgid "Live preview"
-msgstr ""
+msgstr "å³æ™‚é è¦½"
msgid "Loading contribution stats for group members"
msgstr "正在讀å–群組æˆå“¡çš„è²¢ç»çµ±è¨ˆ"
msgid "Loading the GitLab IDE..."
-msgstr "è®€å– GitLab IDE..."
+msgstr "è®€å– GitLab IDE…"
msgid "Loading..."
msgstr "載入中…"
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
msgid "Lock"
msgstr "鎖定"
@@ -4832,13 +5678,13 @@ msgid "Lock not found"
msgstr "找ä¸åˆ°éŽ–定的檔案"
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr ""
+msgstr "鎖定此 %{issuableDisplayName}? åªæœ‰ <strong>專案æˆå“¡</strong>æ‰å¯ä»¥ç™¼è¡¨ç•™è¨€ã€‚"
msgid "Lock to current projects"
msgstr "鎖定目å‰å°ˆæ¡ˆ"
msgid "Locked"
-msgstr "鎖定"
+msgstr "已鎖定"
msgid "Locked Files"
msgstr "鎖定的檔案"
@@ -4850,7 +5696,7 @@ msgid "Locks give the ability to lock specific file or folder."
msgstr "《鎖定》æ供了鎖定特定檔案或資料夾的能力。"
msgid "Login with smartcard"
-msgstr ""
+msgstr "使用 smartcard 登入"
msgid "Logs"
msgstr "記錄檔"
@@ -4859,13 +5705,13 @@ msgid "Make everyone on your team more productive regardless of their location.
msgstr "無論身在何處,都能讓您團隊中的æ¯å€‹äººéƒ½æ›´æœ‰æ•ˆçŽ‡ã€‚GitLab Geo 建立了您 GitLab 主機的唯讀é¡åƒï¼Œæ‰€ä»¥æ‚¨å¯ä»¥ç¸®çŸ­è¤‡è£½å’ŒæŠ“å–大型版本庫的時間。"
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
-msgstr ""
+msgstr "請確ä¿æ‚¨å·²ç¶“登入æ“有您è¦åŒ¯å…¥çš„專案的帳號。"
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
-msgstr ""
+msgstr "使用細粒度的訪å•æŽ§åˆ¶ä¾†ç®¡ç† Git 版本庫,從而確ä¿æ‚¨çš„程å¼ç¢¼å®‰å…¨ã€‚執行程å¼ç¢¼æª¢é–±ä¸¦å¢žå¼·èˆ‡åˆä½µè«‹æ±‚çš„åˆä½œã€‚æ¯å€‹å°ˆæ¡ˆé‚„å¯ä»¥æœ‰å•é¡Œè¿½è¹¤å’Œç¶­åŸºç™¾ç§‘。"
msgid "Manage Web IDE features"
-msgstr ""
+msgstr "ç®¡ç† Web IDE 功能"
msgid "Manage access"
msgstr "管ç†å­˜å–"
@@ -4874,10 +5720,10 @@ msgid "Manage all notifications"
msgstr "管ç†æ‰€æœ‰é€šçŸ¥"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
-msgstr ""
+msgstr "管ç†å¯ä»¥å°‡ GitLab 作為 OAuth 的應用程å¼ï¼Œä»¥åŠæ‚¨å·²æŽˆæ¬Šä½¿ç”¨æ‚¨å¸³è™Ÿçš„應用程å¼ã€‚"
msgid "Manage applications that you've authorized to use your account."
-msgstr ""
+msgstr "管ç†æ‚¨æŽˆæ¬Šä½¿ç”¨å¸³è™Ÿçš„應用程å¼ã€‚"
msgid "Manage group labels"
msgstr "管ç†ç¾¤çµ„標籤"
@@ -4888,6 +5734,9 @@ msgstr "管ç†æ¨™ç±¤"
msgid "Manage project labels"
msgstr "管ç†å°ˆæ¡ˆæ¨™ç±¤"
+msgid "Manage two-factor authentication"
+msgstr ""
+
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr "當é€éŽ SAML 增加其他安全性等級時,管ç†æ‚¨çš„群組æˆå“¡èº«ä»½ã€‚"
@@ -4898,16 +5747,16 @@ msgid "Manifest file import"
msgstr "匯入 Manifest 檔案"
msgid "Map a FogBugz account ID to a GitLab user"
-msgstr ""
+msgstr "å°‡ FogBugz 的帳號å°æ‡‰åˆ° GitLab 使用者"
msgid "Map a Google Code user to a GitLab user"
msgstr "å°æ‡‰Google Code åŠ GitLab 中的使用者"
msgid "Map a Google Code user to a full email address"
-msgstr ""
+msgstr "å°‡ Google Code 中的使用者å°æ‡‰åˆ°å®Œæ•´çš„é›»å­ä¿¡ç®±"
msgid "Map a Google Code user to a full name"
-msgstr ""
+msgstr "å°‡ Google Code 中的使用者å°æ‡‰åˆ°å®Œæ•´çš„姓å"
msgid "Mar"
msgstr "三月"
@@ -4918,50 +5767,50 @@ msgstr "三月"
msgid "Mark todo as done"
msgstr "標記「å³å°‡å®Œæˆã€ç‚ºå®Œæˆã€‚"
+msgid "Markdown"
+msgstr ""
+
msgid "Markdown enabled"
msgstr "已啟用 Markdown"
msgid "MarkdownToolbar|Add a bullet list"
-msgstr ""
+msgstr "增加項目清單"
msgid "MarkdownToolbar|Add a link"
-msgstr ""
+msgstr "增加連çµ"
msgid "MarkdownToolbar|Add a numbered list"
-msgstr ""
+msgstr "增加åºåˆ—清單"
msgid "MarkdownToolbar|Add a table"
-msgstr ""
+msgstr "增加表格"
msgid "MarkdownToolbar|Add a task list"
-msgstr ""
+msgstr "增加作業清單"
msgid "MarkdownToolbar|Add bold text"
-msgstr ""
+msgstr "增加粗體文字"
msgid "MarkdownToolbar|Add italic text"
-msgstr ""
+msgstr "增加斜體文字"
msgid "MarkdownToolbar|Go full screen"
-msgstr ""
+msgstr "全螢幕顯示"
msgid "MarkdownToolbar|Insert a quote"
-msgstr ""
+msgstr "æ’入引用"
msgid "MarkdownToolbar|Insert code"
-msgstr ""
+msgstr "æ’入程å¼ç¢¼"
msgid "Maven Metadata"
-msgstr ""
-
-msgid "Maven package"
-msgstr ""
+msgstr "Maven 詮釋資料"
msgid "Max access level"
-msgstr ""
+msgstr "最大存å–等級"
msgid "Maximum job timeout"
-msgstr ""
+msgstr "最大工作逾時"
msgid "May"
msgstr "五月"
@@ -4970,32 +5819,44 @@ msgid "Median"
msgstr "中ä½æ•¸"
msgid "Member lock"
-msgstr ""
+msgstr "æˆå“¡éŽ–定"
msgid "Member since %{date}"
-msgstr ""
+msgstr "會員開始於 %{date}"
msgid "Members"
msgstr "æˆå“¡"
+msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
+msgstr ""
+
+msgid "Members of <strong>%{project_name}</strong>"
+msgstr ""
+
msgid "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 "當登入至您的群組,æˆå“¡å€‘將會被轉移到這裡。從您的身份æä¾›å–得這個,其å¯èƒ½è¢«ç¨±ç‚ºã€ŒSSO æœå‹™ä½ç½®ã€ã€ã€ŒSAML 憑證頒發端點ã€æˆ–「SAML 2.0/W-Federation URLã€ã€‚"
+msgstr "當登入至您的群組,æˆå“¡å€‘將會被轉移到這裡。從您的身份æä¾›å–得這個,其å¯èƒ½è¢«ç¨±ç‚ºã€ŒSSO æœå‹™ä½ç½®ã€ã€ã€ŒSAML 憑證頒發節點ã€æˆ–「SAML 2.0/W-Federation URLã€ã€‚"
msgid "Merge Request"
msgstr "åˆä½µè«‹æ±‚"
-msgid "Merge Request:"
-msgstr "åˆä½µè«‹æ±‚:"
-
msgid "Merge Requests"
msgstr "åˆä½µè«‹æ±‚"
msgid "Merge Requests created"
msgstr "已建立åˆä½µè«‹æ±‚"
+msgid "Merge commit message"
+msgstr ""
+
msgid "Merge events"
msgstr "åˆä½µäº‹ä»¶"
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
msgid "Merge request"
msgstr "åˆä½µè«‹æ±‚"
@@ -5006,52 +5867,85 @@ msgid "Merge requests"
msgstr "åˆä½µè«‹æ±‚"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
-msgstr "åˆä½µè«‹æ±‚是一個讓其他人æ出更改建議並討論的地方"
+msgstr "「åˆä½µè«‹æ±‚ã€æ˜¯ä¸€å€‹è®“其他人æ出變更建議並討論的地方"
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr "儲存留言è‰ç¨¿æ™‚發生錯誤。"
+
+msgid "MergeRequests|Discussion stays resolved"
msgstr ""
-msgid "MergeRequests|Discussion stays resolved."
+msgid "MergeRequests|Discussion stays unresolved"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved."
+msgid "MergeRequests|Discussion will be resolved"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved."
+msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
-msgid "MergeRequests|Discussion will be unresolved."
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "在新議題中解決此討論"
msgid "MergeRequests|Saving the comment failed"
-msgstr "儲存評論失敗"
+msgstr "儲存留言失敗"
msgid "MergeRequests|Toggle comments for this file"
-msgstr "切æ›æ­¤æ–‡ä»¶çš„註釋"
+msgstr "切æ›æ­¤æª”案的註釋"
msgid "MergeRequests|View file @ %{commitId}"
-msgstr "查看文件@ %{commitId}"
+msgstr "檢視檔案@ %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
-msgstr "查看替æ›æ–‡ä»¶@ %{commitId}"
+msgstr "檢視å–代檔案@ %{commitId}"
-msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgid "MergeRequests|commented on commit %{commitLink}"
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
msgstr ""
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr "%{paragraphStart} 將說明改為 %{descriptionChangedTimes} : %{timeDifferenceMinutes} %{paragraphEnd}"
+
+msgid "MergeRequest|Filter files"
+msgstr "篩é¸æª”案"
+
msgid "MergeRequest|No files found"
+msgstr "沒有找到任何檔案"
+
+msgid "MergeRequest|Search files"
msgstr ""
msgid "Merged"
msgstr "å·²åˆä½µ"
msgid "Messages"
-msgstr "公告"
+msgstr "訊æ¯"
msgid "Metrics"
msgstr "指標"
@@ -5063,17 +5957,23 @@ msgid "Metrics - Prometheus"
msgstr "指標 - Prometheus"
msgid "Metrics and profiling"
-msgstr ""
+msgstr "指標和分æž"
-msgid "Metrics|Business"
-msgstr "ä¼æ¥­"
+msgid "Metrics for environment"
+msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
-msgstr "查看有關部署到環境的 CI / CD 文件。"
+msgstr "檢視有關部署到環境的 CI / CD 檔案。"
msgid "Metrics|Create metric"
msgstr "建立指標"
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgstr "編輯指標"
@@ -5083,8 +5983,8 @@ msgstr "環境"
msgid "Metrics|For grouping similar metrics"
msgstr "å°ç›¸ä¼¼çš„指標進行分組"
-msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
-msgstr "圖表垂直軸的標籤,通常是繪製單ä½çš„類型。水平軸 (X 軸) 總是表示時間。"
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
msgid "Metrics|Learn about environments"
msgstr "了解關於環境的資訊"
@@ -5095,23 +5995,17 @@ msgstr "圖例標籤(éžå¿…è¦ï¼‰"
msgid "Metrics|Must be a valid PromQL query."
msgstr "必須是有效的 PromQL 查詢。"
-msgid "Metrics|Name"
-msgstr "å稱"
-
msgid "Metrics|New metric"
msgstr "建立指標"
msgid "Metrics|No deployed environments"
msgstr "沒有已經佈署的環境"
-msgid "Metrics|Prometheus Query Documentation"
-msgstr "Prometheus 查詢文件"
-
-msgid "Metrics|Query"
-msgstr "查詢"
+msgid "Metrics|PromQL query is valid"
+msgstr ""
-msgid "Metrics|Response"
-msgstr "回應"
+msgid "Metrics|Prometheus Query Documentation"
+msgstr "Prometheus 查詢檔案"
msgid "Metrics|System"
msgstr "系統"
@@ -5125,17 +6019,17 @@ msgstr "å–得部署資訊時發生錯誤。"
msgid "Metrics|There was an error getting environments information."
msgstr "å–得部署資訊時發生錯誤。"
-msgid "Metrics|There was an error while retrieving metrics"
+msgid "Metrics|There was an error trying to validate your query"
msgstr ""
-msgid "Metrics|Type"
-msgstr "類別"
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr "檢索度é‡æ¨™æº–時出錯"
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
-msgstr "來自 Prometheus 端點的éžé æœŸéƒ¨å±¬è³‡æ–™å›žæ‡‰"
+msgstr "來自 Prometheus 節點的éžé æœŸéƒ¨å±¬è³‡æ–™å›žæ‡‰"
msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
-msgstr "來自 Prometheus 端點的éžé æœŸæŒ‡æ¨™è³‡æ–™å›žæ‡‰"
+msgstr "來自 Prometheus 節點的éžé æœŸæŒ‡æ¨™è³‡æ–™å›žæ‡‰"
msgid "Metrics|Unit label"
msgstr "å–®ä½æ¨™ç±¤"
@@ -5149,50 +6043,41 @@ msgstr "如果查詢回傳了單個åºåˆ—則使用,如果其回傳多個åºåˆ—
msgid "Metrics|Y-axis label"
msgstr "Y 軸標籤"
-msgid "Metrics|e.g. HTTP requests"
-msgstr "例如 HTTP 請求"
-
-msgid "Metrics|e.g. Requests/second"
-msgstr "例如:æ¯ç§’請求"
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
msgid "Metrics|e.g. Throughput"
msgstr "例如:Throughput"
-msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr "例如:rate(http_requests_total[5m])"
-
-msgid "Metrics|e.g. req/sec"
-msgstr "例如:æ¯ç§’請求"
-
msgid "Milestone"
msgstr "里程碑"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "ç›®å‰è¨±å¯è­‰ç„¡æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
msgid "Milestone lists show all issues from the selected milestone."
-msgstr ""
+msgstr "里程碑列表將顯示所é¸é‡Œç¨‹ç¢‘的所有議題"
msgid "Milestones"
msgstr "里程碑"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
-msgstr ""
+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|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
+msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
msgid "Milestones|Delete milestone"
msgstr "刪除里程碑"
msgid "Milestones|Delete milestone %{milestoneTitle}?"
-msgstr "刪除里程碑 %{milestoneTitle} ?"
+msgstr "刪除里程碑 %{milestoneTitle}?"
msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
-msgstr "刪除里程碑 %{milestoneTitle} 時發生錯誤"
+msgstr "刪除里程碑 %{milestoneTitle} 失敗"
msgid "Milestones|Milestone %{milestoneTitle} was not found"
msgstr "找ä¸åˆ°é‡Œç¨‹ç¢‘ %{milestoneTitle}"
@@ -5204,28 +6089,28 @@ msgid "Milestones|Promote Milestone"
msgstr "推動里程碑"
msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr ""
+msgstr "æå‡ %{milestone} 後,所有 %{groupName} 裡的專案都å¯ä»¥ä½¿ç”¨è©²é‡Œç¨‹ç¢‘。如果已經有相åŒå稱的里程碑將會兩者åˆä½µã€‚ "
msgid "Milestones|This action cannot be reversed."
msgstr "這動作無法復原。"
msgid "Mirror a repository"
-msgstr ""
+msgstr "å°ä¸€å€‹ç‰ˆæœ¬åº«é¡åƒ"
msgid "Mirror direction"
-msgstr ""
+msgstr "é¡åƒæ–¹å‘"
msgid "Mirror repository"
-msgstr ""
+msgstr "é¡åƒç‰ˆæœ¬åº«"
msgid "Mirror user"
-msgstr ""
+msgstr "é¡åƒä½¿ç”¨è€…"
msgid "Mirrored repositories"
-msgstr ""
+msgstr "å·²é¡åƒçš„版本庫"
msgid "Mirroring repositories"
-msgstr ""
+msgstr "正在é¡åƒç‰ˆæœ¬åº«"
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "新增 SSH 金鑰"
@@ -5236,6 +6121,18 @@ msgstr "å–消"
msgid "Modal|Close"
msgstr "關閉"
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry"
+msgstr ""
+
msgid "Monitoring"
msgstr "監控"
@@ -5246,7 +6143,7 @@ msgid "More"
msgstr "更多"
msgid "More actions"
-msgstr ""
+msgstr "更多動作"
msgid "More info"
msgstr "更多資訊"
@@ -5255,7 +6152,7 @@ msgid "More information"
msgstr "更多資訊"
msgid "More information is available|here"
-msgstr "å¥åº·æª¢æŸ¥"
+msgstr "此處"
msgid "Most stars"
msgstr "最多星數"
@@ -5282,7 +6179,7 @@ msgid "Name:"
msgstr "å稱:"
msgid "Naming, visibility"
-msgstr ""
+msgstr "å稱,å¯è¦‹æ€§"
msgid "Nav|Help"
msgstr "幫助"
@@ -5296,11 +6193,14 @@ msgstr "註冊 / 登入"
msgid "Nav|Sign out and sign in with a different account"
msgstr "登出,並使用其他帳號登入"
+msgid "Need help?"
+msgstr ""
+
msgid "Network"
msgstr "網路"
msgid "Never"
-msgstr ""
+msgstr "從ä¸"
msgid "New"
msgstr "新增"
@@ -5308,6 +6208,9 @@ msgstr "新增"
msgid "New Application"
msgstr "新增應用程å¼"
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr "新增群組"
@@ -5321,8 +6224,14 @@ msgstr[0] "建立議題"
msgid "New Label"
msgstr "新增標籤"
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
msgid "New Pipeline Schedule"
-msgstr "建立æµæ°´ç·šæŽ’程"
+msgstr "建立排程管線"
msgid "New Snippet"
msgstr "新增片段"
@@ -5334,10 +6243,13 @@ msgid "New branch"
msgstr "新分支"
msgid "New branch unavailable"
-msgstr "新的分支ä¸å¯ç”¨"
+msgstr "無法使用新分支"
msgid "New directory"
-msgstr "新增目錄"
+msgstr "新增資料夾"
+
+msgid "New environment"
+msgstr ""
msgid "New epic"
msgstr "æ–°çš„ Epic"
@@ -5346,7 +6258,7 @@ msgid "New file"
msgstr "新增檔案"
msgid "New group"
-msgstr "新群組"
+msgstr "新增群組"
msgid "New identity"
msgstr "新增身份"
@@ -5355,25 +6267,28 @@ msgid "New issue"
msgstr "新增議題"
msgid "New label"
-msgstr "建立標籤"
+msgstr "新增標籤"
msgid "New merge request"
msgstr "新增åˆä½µè«‹æ±‚"
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "æ–°çš„æµæ°´ç·šå°‡å–消åŒä¸€åˆ†æ”¯ä¸Šè¼ƒèˆŠã€æœªè§£æ±ºçš„æµæ°´ç·š"
+msgstr "新的管線將å–消åŒä¸€åˆ†æ”¯ä¸Šè¼ƒèˆŠã€æœªè§£æ±ºçš„管線"
msgid "New project"
-msgstr "新專案"
+msgstr "新增專案"
msgid "New schedule"
msgstr "新增排程"
msgid "New snippet"
-msgstr "新文字片段"
+msgstr "新增文字片段"
msgid "New subgroup"
-msgstr "æ–°å­ç¾¤çµ„"
+msgstr "新增å­ç¾¤çµ„"
msgid "New tag"
msgstr "新增標籤"
@@ -5387,29 +6302,41 @@ msgstr "å¦"
msgid "No Label"
msgstr "沒有標籤"
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
-msgstr "未指派"
+msgstr "無被指派人"
msgid "No branches found"
-msgstr ""
+msgstr "找ä¸åˆ°åˆ†æ”¯"
msgid "No changes"
msgstr "沒有改變"
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
-msgstr "無法連接到 Gitaly 伺æœå™¨ï¼Œè«‹æª¢æŸ¥æ‚¨çš„日誌ï¼"
+msgstr "無法連線到 Gitaly 伺æœå™¨ï¼Œè«‹æª¢æŸ¥æ—¥èªŒè¨˜éŒ„ï¼"
msgid "No container images stored for this project. Add one by following the instructions above."
-msgstr ""
+msgstr "此專案目å‰æ²’有儲存容器映åƒï¼Œè«‹ä¾ç…§ä¸Šè¿°èªªæ˜Žæ–°å¢žå®¹å™¨æ˜ åƒã€‚"
msgid "No contributions were found"
-msgstr ""
+msgstr "找ä¸åˆ°è²¢ç»"
msgid "No credit card required."
+msgstr "無需信用å¡ã€‚"
+
+msgid "No details available"
msgstr ""
msgid "No due date"
-msgstr "沒有到期日"
+msgstr "沒有到期時間"
+
+msgid "No errors to display"
+msgstr ""
msgid "No estimate or time spent"
msgstr "沒有é ä¼°æˆ–花費時間"
@@ -5417,6 +6344,9 @@ msgstr "沒有é ä¼°æˆ–花費時間"
msgid "No file chosen"
msgstr "未é¸æ“‡ä»»ä½•æª”案"
+msgid "No file selected"
+msgstr ""
+
msgid "No files found."
msgstr "找ä¸åˆ°ä»»ä½•æª”案"
@@ -5424,9 +6354,12 @@ msgid "No issues for the selected time period."
msgstr "é¸å–的時間範åœä¸­æ²’有議題。"
msgid "No labels with such name or description"
-msgstr ""
+msgstr "沒有具有此類å稱或æ述的標籤"
msgid "No license. All rights reserved"
+msgstr "沒有授權æ¢æ¬¾ã€‚ä¿ç•™ä¸€åˆ‡è‘—作權"
+
+msgid "No matching results"
msgstr ""
msgid "No merge requests for the selected time period."
@@ -5436,16 +6369,19 @@ msgid "No merge requests found"
msgstr "找ä¸åˆ°åˆä½µè«‹æ±‚"
msgid "No messages were logged"
-msgstr "沒有消æ¯è¢«è¨˜éŒ„"
+msgstr "沒有訊æ¯è¢«è¨˜éŒ„"
-msgid "No other labels with such name or description"
+msgid "No milestones to show"
msgstr ""
-msgid "No packages stored for this project."
+msgid "No other labels with such name or description"
+msgstr "沒有其他具有此類å稱或æ述的標籤"
+
+msgid "No preview for this file type"
msgstr ""
msgid "No prioritised labels with such name or description"
-msgstr ""
+msgstr "沒有具有此類å稱或æ述的優先標籤"
msgid "No public groups"
msgstr "沒有公開群組"
@@ -5454,29 +6390,26 @@ msgid "No pushes for the selected time period."
msgstr "é¸å–的時間範åœä¸­æ²’有推é€ã€‚"
msgid "No repository"
-msgstr "找ä¸åˆ°æª”案庫"
+msgstr "找ä¸åˆ°ç‰ˆæœ¬åº«"
msgid "No runners found"
-msgstr ""
+msgstr "找ä¸åˆ°åŸ·è¡Œå™¨"
msgid "No schedules"
-msgstr "沒有排程"
+msgstr "找ä¸åˆ°æŽ’程"
-msgid "No, directly import the existing email addresses and usernames."
+msgid "No start date"
msgstr ""
+msgid "No, directly import the existing email addresses and usernames."
+msgstr "ä¸ï¼Œç›´æŽ¥åŒ¯å…¥ç¾æœ‰çš„é›»å­éƒµä»¶ä½å€å’Œä½¿ç”¨è€…å稱。"
+
msgid "Nodes"
-msgstr ""
+msgstr "節點"
msgid "None"
msgstr "ç„¡"
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr "ä¸å…許åˆä½µ"
@@ -5496,40 +6429,49 @@ msgid "Not enough data"
msgstr "資料ä¸è¶³"
msgid "Not now"
-msgstr ""
+msgstr "ä¸æ˜¯ç¾åœ¨"
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "請注æ„,master 分支é è¨­ç‚ºå—ä¿è­·çš„。 %{link_to_protected_branches}"
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "注æ„:作為管ç†å“¡ï¼Œæ‚¨å¯èƒ½å¸Œæœ›è¨­å®š %{github_integration_link},其å¯ä»¥å…許é€éŽ 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 "注æ„:作為管ç†å“¡ï¼Œæ‚¨å¯èƒ½å¸Œæœ›é…ç½® %{github_integration_link},這將å…è¨±é€šéŽ GitHub 登入並å…許匯入存儲庫而ä¸ç”Ÿæˆå€‹äººå­˜å–憑證。"
+msgstr "注æ„:作為管ç†å“¡ï¼Œæ‚¨å¯èƒ½å¸Œæœ›è¨­å®š %{github_integration_link},這將å…許é€éŽ 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 "注æ„:請考慮讓您的 GitLab 管ç†å“¡è¨­å®š %{github_integration_link},讓其å…許é€éŽ 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 "注æ„:請考慮讓您的 GitLab 管ç†å“¡è¨­å®š %{github_integration_link},這將å…許使用者é€éŽ GitHub 登入並å…許匯入儲存庫而ä¸ç”Ÿæˆå€‹äººå­˜å–憑證。"
+msgstr "注æ„:請考慮讓您的 GitLab 管ç†å“¡è¨­å®š %{github_integration_link},這將å…許使用者é€éŽ GitHub 登入並å…許匯入版本庫而ä¸ç”Ÿæˆå€‹äººå­˜å–憑證。"
msgid "Notes|Are you sure you want to cancel creating this comment?"
-msgstr ""
+msgstr "您確定è¦å–消建立此留言嗎?"
msgid "Notes|Collapse replies"
-msgstr ""
+msgstr "折疊回覆"
msgid "Notes|Show all activity"
-msgstr ""
+msgstr "顯示所有活動"
msgid "Notes|Show comments only"
-msgstr ""
+msgstr "åªé¡¯ç¤ºç•™è¨€"
msgid "Notes|Show history only"
-msgstr ""
+msgstr "åªé¡¯ç¤ºæ­·å²ç´€éŒ„"
msgid "Notification events"
-msgstr "事件通知"
+msgstr "通知事件"
+
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
msgid "NotificationEvent|Close issue"
msgstr "關閉議題"
@@ -5538,13 +6480,13 @@ msgid "NotificationEvent|Close merge request"
msgstr "關閉åˆä½µè«‹æ±‚"
msgid "NotificationEvent|Failed pipeline"
-msgstr "æµæ°´ç·šå¤±æ•—"
+msgstr "管線執行失敗"
msgid "NotificationEvent|Merge merge request"
-msgstr "åˆä½µè«‹æ±‚被åˆä½µ"
+msgstr "åˆä½µåˆä½µè«‹æ±‚"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "建立 epic"
msgid "NotificationEvent|New issue"
msgstr "新增議題"
@@ -5553,7 +6495,7 @@ msgid "NotificationEvent|New merge request"
msgstr "新增åˆä½µè«‹æ±‚"
msgid "NotificationEvent|New note"
-msgstr "新增評論"
+msgstr "新增留言"
msgid "NotificationEvent|Reassign issue"
msgstr "é‡æ–°æŒ‡æ´¾è­°é¡Œ"
@@ -5562,10 +6504,10 @@ msgid "NotificationEvent|Reassign merge request"
msgstr "é‡æ–°æŒ‡æ´¾åˆä½µè«‹æ±‚"
msgid "NotificationEvent|Reopen issue"
-msgstr "é‡å•Ÿè­°é¡Œ"
+msgstr "é‡é–‹è­°é¡Œ"
msgid "NotificationEvent|Successful pipeline"
-msgstr "æµæ°´ç·šæˆåŠŸå®Œæˆ"
+msgstr "管線執行æˆåŠŸ"
msgid "NotificationLevel|Custom"
msgstr "自訂"
@@ -5577,7 +6519,7 @@ msgid "NotificationLevel|Global"
msgstr "全域"
msgid "NotificationLevel|On mention"
-msgstr "æåŠ"
+msgstr "被æåŠ"
msgid "NotificationLevel|Participate"
msgstr "åƒèˆ‡"
@@ -5617,43 +6559,58 @@ msgstr "一旦匯入,就å¯ä»¥é€éŽ SSH é¡åƒç‰ˆæœ¬åº«ã€‚閱讀 %{ssh_link}
msgid "One more item"
msgid_plural "%d more items"
-msgstr[0] ""
+msgstr[0] "其餘 %d 項"
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
-msgstr ""
+msgstr "您的一個或多個 Bitbucket 專案無法直接匯入 GitLab,因為它們使用 Subversion 或 Mercurial 進行版本控管,而ä¸æ˜¯Git。"
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
-msgstr ""
+msgstr "您的一個或多個 Google Code 專案無法直接匯入 GitLab,因為它們使用 Subversion 或 Mercurial 進行版本控管,而ä¸æ˜¯Git。"
msgid "Only admins"
-msgstr ""
-
-msgid "Only comments from the following commit are shown below"
-msgstr "下é¢åƒ…顯示來自以下æ交的註釋"
+msgstr "僅管ç†å“¡"
msgid "Only mirror protected branches"
+msgstr "僅é¡åƒè¢«ä¿è­·çš„分支"
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
msgid "Only project members can comment."
-msgstr "åªæœ‰ç¾¤çµ„æˆå“¡æ‰èƒ½ç•™è¨€ã€‚"
+msgstr "僅群組æˆå“¡æ‰èƒ½ç•™è¨€ã€‚"
+
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
msgid "Oops, are you sure?"
-msgstr "喔喔…你確定嗎?"
+msgstr "喔喔…確定?"
msgid "Open"
msgstr "é–‹å•Ÿ"
+msgid "Open Documentation"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
msgid "Open in Xcode"
msgstr "在 Xcode 開啟"
msgid "Open projects"
-msgstr ""
+msgstr "打開專案"
msgid "Open sidebar"
msgstr "é–‹å•Ÿå´é‚Šæ¬„"
msgid "Open source software to collaborate on code"
-msgstr ""
+msgstr "é–‹æºè»Ÿé«”,以å”作程å¼ç¢¼"
msgid "Opened"
msgstr "é–‹å•Ÿçš„"
@@ -5665,34 +6622,31 @@ msgid "Opened issues"
msgstr "開啟的議題"
msgid "OpenedNDaysAgo|Opened"
-msgstr "開始於"
+msgstr "開啟時間"
msgid "Opens in a new window"
-msgstr "於新視窗開啟"
+msgstr "在新視窗開啟"
msgid "Operations"
msgstr "動作"
msgid "Operations Dashboard"
-msgstr ""
-
-msgid "Operations Settings"
-msgstr ""
+msgstr "維é‹å„€è¡¨æ¿"
msgid "OperationsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "新增專案到儀表æ¿"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
-msgstr ""
+msgstr "維é‹å„€è¡¨æ¿æä¾›æ¯å€‹å°ˆæ¡ˆçš„執行狀æ³æ‘˜è¦ï¼ŒåŒ…括管線和警示狀態。"
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
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 "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
-msgstr ""
+msgstr "ä½ å¯ä»¥é¸æ“‡ %{link_to_customize} 如何將 Google Code çš„é›»å­ä¿¡ç®±åŠä½¿ç”¨è€…å稱匯入 GitLab 。"
msgid "Options"
msgstr "é¸é …"
@@ -5713,26 +6667,32 @@ msgid "Outbound requests"
msgstr "Outbound 請求"
msgid "Overview"
-msgstr "總覽"
+msgstr "概覽"
msgid "Overwrite diverged branches"
-msgstr ""
+msgstr "覆寫有分歧的分支"
msgid "Owner"
-msgstr "所有權"
+msgstr "所有者"
msgid "Package information"
-msgstr ""
+msgstr "軟體包資訊"
msgid "Package was removed"
-msgstr ""
+msgstr "軟體包被移除"
msgid "Packages"
-msgstr ""
+msgstr "軟體包"
msgid "Pages"
msgstr "é é¢"
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages Domains"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "æœ€æœ«é  Â»"
@@ -5745,17 +6705,32 @@ msgstr "上一é "
msgid "Pagination|« First"
msgstr "« 第一é "
+msgid "Parameter"
+msgstr ""
+
+msgid "Parent epic"
+msgstr ""
+
msgid "Part of merge request changes"
-msgstr "åˆä½µè«‹æ±‚更改的部分"
+msgstr "åˆä½µè«‹æ±‚變更的部分"
msgid "Password"
msgstr "密碼"
+msgid "Past due"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "貼上您的SSH公鑰,通常放置在 '~/.ssh/id_rsa.pub',並以 'ssh-rsa' 開頭。ä¸è¦ä½¿ç”¨æ‚¨çš„SSHç§é‘°ã€‚"
msgid "Path, transfer, remove"
-msgstr ""
+msgstr "路徑,移轉,刪除"
msgid "Path:"
msgstr "ä½ç½®ï¼š"
@@ -5764,19 +6739,16 @@ msgid "Pause"
msgstr "æš«åœ"
msgid "Paused Runners don't accept new jobs"
-msgstr ""
+msgstr "已暫åœçš„執行器ä¸æœƒæŽ¥å—新工作"
msgid "Pending"
msgstr "等待處ç†"
msgid "People without permission will never get a notification and won't be able to comment."
-msgstr ""
-
-msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr "æ¯ä»½ä»»å‹™ã€‚如果任務通éŽæ­¤é–¾å€¼ï¼Œå®ƒå°‡è¢«æ¨™è¨˜ç‚ºå¤±æ•—"
+msgstr "未經許å¯çš„使用者將無法收到通知也無法留言。"
msgid "Perform advanced options such as changing path, transferring, or removing the group."
-msgstr "執行進階é¸é …,例如更改路徑ã€å‚³è¼¸æˆ–移除群組。"
+msgstr "執行進階é¸é …,例如變更路徑ã€å‚³è¼¸æˆ–移除群組。"
msgid "Performance optimization"
msgstr "效能最佳化"
@@ -5785,37 +6757,43 @@ msgid "Permissions"
msgstr "權é™"
msgid "Permissions, LFS, 2FA"
-msgstr ""
+msgstr "權é™, 大檔案儲存(LFS), 兩步驟驗證(2FA)"
msgid "Personal Access Token"
msgstr "個人訪å•æ†‘è­‰"
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
-msgstr "æµæ°´ç·š"
+msgstr "管線"
msgid "Pipeline Health"
-msgstr "æµæ°´ç·šå¥åº·æŒ‡æ•¸"
+msgstr "管線å¥åº·æŒ‡æ•¸"
msgid "Pipeline Schedule"
-msgstr "æµæ°´ç·šæŽ’程"
+msgstr "排程管線"
msgid "Pipeline Schedules"
-msgstr "æµæ°´ç·šæŽ’程"
+msgstr "排程管線"
msgid "Pipeline quota"
-msgstr "æµæ°´ç·šé¡åº¦"
+msgstr "管線é¡åº¦"
msgid "Pipeline triggers"
-msgstr "æµæ°´ç·šè§¸ç™¼å™¨"
+msgstr "管線觸發器"
msgid "PipelineCharts|Failed:"
msgstr "失敗:"
msgid "PipelineCharts|Overall statistics"
-msgstr "總體統計"
+msgstr "整體統計"
msgid "PipelineCharts|Success ratio:"
-msgstr "æˆåŠŸæ¯”率:"
+msgstr "æˆåŠŸæ¯”例:"
msgid "PipelineCharts|Successful:"
msgstr "æˆåŠŸï¼š"
@@ -5824,13 +6802,13 @@ msgid "PipelineCharts|Total:"
msgstr "總計:"
msgid "PipelineSchedules|Activated"
-msgstr "是å¦å•Ÿç”¨"
+msgstr "已啟用"
msgid "PipelineSchedules|Active"
-msgstr "已啟用"
+msgstr "使用中"
msgid "PipelineSchedules|All"
-msgstr "所有"
+msgstr "全部"
msgid "PipelineSchedules|Inactive"
msgstr "未啟用"
@@ -5842,7 +6820,7 @@ msgid "PipelineSchedules|None"
msgstr "ç„¡"
msgid "PipelineSchedules|Provide a short description for this pipeline"
-msgstr "請簡單說明此æµæ°´ç·š"
+msgstr "請簡單說明這個管線的用途"
msgid "PipelineSchedules|Take ownership"
msgstr "å–得所有權"
@@ -5857,79 +6835,79 @@ msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "自訂"
msgid "Pipelines"
-msgstr "æµæ°´ç·š"
+msgstr "管線"
msgid "Pipelines charts"
-msgstr "æµæ°´ç·šåœ–表"
+msgstr "管線圖表"
msgid "Pipelines for last month"
-msgstr "上個月的æµæ°´ç·š"
+msgstr "上個月的管線"
msgid "Pipelines for last week"
-msgstr "上週的æµæ°´ç·š"
+msgstr "上週的管線"
msgid "Pipelines for last year"
-msgstr "去年的æµæ°´ç·š"
+msgstr "去年的管線"
msgid "Pipelines|Build with confidence"
-msgstr "信心滿滿的建立"
+msgstr "信任編譯"
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
msgid "Pipelines|Clear Runner Caches"
-msgstr "清除é‹è¡Œå™¨å¿«å–"
+msgstr "清除執行器快å–"
msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
-msgstr ""
+msgstr "ä¸é–“æ–·æ•´åˆå¯ä»¥é€éŽè‡ªå‹•æ¸¬è©¦ä¾†å¹«åŠ©æ•æ‰éŒ¯èª¤ï¼Œè€ŒæŒçºŒéƒ¨ç½²å¯ä»¥å¹«åŠ©ä½ äº¤ä»˜ç”¢å“至正å¼ç’°å¢ƒã€‚"
msgid "Pipelines|Get started with Pipelines"
-msgstr "開始"
+msgstr "嘗試管線功能"
msgid "Pipelines|Loading Pipelines"
-msgstr "讀å–æµæ°´ç·š"
+msgstr "讀å–管線"
msgid "Pipelines|Project cache successfully reset."
-msgstr "專案快å–已經æˆåŠŸé‡ç½®ã€‚"
+msgstr "專案快å–已經æˆåŠŸé‡è¨­ã€‚"
msgid "Pipelines|Run Pipeline"
-msgstr "執行æµæ°´ç·š"
+msgstr "執行管線"
msgid "Pipelines|Something went wrong while cleaning runners cache."
-msgstr "清除é‹è¡Œå™¨å¿«å–時發生錯誤。"
+msgstr "清除執行器快å–時發生錯誤。"
msgid "Pipelines|There are currently no %{scope} pipelines."
-msgstr "ç›®å‰æ²’有 %{scope} æµæ°´ç·šã€‚"
+msgstr "ç›®å‰æ²’有 %{scope} 管線。"
msgid "Pipelines|There are currently no pipelines."
-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 project is not currently set up to run pipelines."
-msgstr "這個專案目å‰é‚„沒設定æµæ°´ç·šã€‚"
+msgstr "這個專案目å‰é‚„沒設定管線。"
msgid "Pipeline|Commit"
-msgstr ""
+msgstr "æ交"
msgid "Pipeline|Create for"
msgstr "建立"
msgid "Pipeline|Create pipeline"
-msgstr "建立æµæ°´ç·š"
+msgstr "建立管線"
msgid "Pipeline|Duration"
-msgstr ""
+msgstr "耗時"
msgid "Pipeline|Existing branch name or tag"
msgstr "存在的分支å稱或標籤"
msgid "Pipeline|Pipeline"
-msgstr ""
+msgstr "管線"
msgid "Pipeline|Run Pipeline"
-msgstr "執行æµæ°´ç·š"
+msgstr "執行管線"
msgid "Pipeline|Search branches"
msgstr "æœå°‹åˆ†æ”¯"
@@ -5938,34 +6916,34 @@ msgid "Pipeline|Specify variable values to be used in this run. The values speci
msgstr "指定è¦ä½¿ç”¨åœ¨æ­¤æ¬¡åŸ·è¡Œçš„變數值。%{settings_link} 中指定的值將會使用為é è¨­å€¼ã€‚"
msgid "Pipeline|Stages"
-msgstr ""
+msgstr "階段"
msgid "Pipeline|Status"
-msgstr ""
+msgstr "狀態"
msgid "Pipeline|Stop pipeline"
-msgstr "åœæ­¢æµæ°´ç·š"
+msgstr "åœæ­¢ç®¡ç·š"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
-msgstr "åœæ­¢æµæ°´ç·š #%{pipelineId}?"
+msgstr "åœæ­¢ç®¡ç·š #%{pipelineId}?"
msgid "Pipeline|Variables"
msgstr "變數"
msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
-msgstr "ä½ å°‡åœæ­¢æµæ°´ç·š %{pipelineId}。"
+msgstr "ä½ å°‡åœæ­¢ç®¡ç·š %{pipelineId}。"
msgid "Pipeline|all"
-msgstr "所有"
+msgstr "全部"
msgid "Pipeline|success"
msgstr "æˆåŠŸ"
msgid "Pipeline|with stage"
-msgstr "於階段"
+msgstr "與階段"
msgid "Pipeline|with stages"
-msgstr "於階段"
+msgstr "與階段"
msgid "Plain diff"
msgstr "本文差異"
@@ -5976,41 +6954,53 @@ msgstr "PlantUML"
msgid "Play"
msgstr "執行"
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
msgid "Please accept the Terms of Service before continuing."
msgstr "在繼續之å‰ï¼Œè«‹åŒæ„æœå‹™æ¢æ¬¾"
msgid "Please choose a group URL with no special characters."
-msgstr ""
+msgstr "è«‹é¸æ“‡æ²’有特殊符號的群組網å€ã€‚"
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
-msgstr ""
+msgstr "請將它們轉為 %{link_to_git} ,然後å†æ¬¡é€éŽ %{link_to_import_flow} 。"
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr "請將它們在 Google Code 上轉為 Git,然後å†æ¬¡é€éŽ %{link_to_import_flow} 。"
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
msgstr ""
msgid "Please fill in a descriptive name for your group."
+msgstr "請為您的群組填寫æ述性å稱。"
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
-msgstr ""
+msgstr "請注æ„,這個應用程å¼ä¸æ˜¯ç”± GitLab 所æ供的,您應該在å…許訪å•ä¹‹å‰é©—證其真實性。"
msgid "Please select at least one filter to see results"
msgstr "è«‹é¸æ“‡è‡³å°‘一個篩é¸å™¨ä»¥æª¢è¦–çµæžœ"
msgid "Please solve the reCAPTCHA"
-msgstr "請填寫驗證碼"
+msgstr "請填寫此驗證碼"
msgid "Please try again"
msgstr "è«‹å†è©¦ä¸€æ¬¡"
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr "è«‹ä½¿ç”¨æ­¤è¡¨å–®å‘ GitLab 報告建立垃圾議題ã€ç•™è¨€æˆ–有ä¸ç•¶è¡Œç‚ºçš„使用者。"
+
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 "Preferences"
msgstr "å好設定"
@@ -6019,16 +7009,16 @@ msgid "Preferences|Navigation theme"
msgstr "導航主題"
msgid "Press Enter or click to search"
-msgstr ""
+msgstr "按下 Enter 或點é¸ä»¥æœå°‹"
msgid "Prevent adding new members to project membership within this group"
-msgstr ""
+msgstr "ç¦æ­¢å‘ç›®å‰ç¾¤çµ„新增使用者"
msgid "Preview"
-msgstr ""
+msgstr "é è¦½"
msgid "Preview payload"
-msgstr ""
+msgstr "é è¦½æœ‰æ•ˆè² è¼‰"
msgid "Primary"
msgstr "主è¦"
@@ -6045,11 +7035,14 @@ msgstr "優先標籤"
msgid "Prioritized label"
msgstr "優先標籤"
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
-msgstr "ç§æœ‰ - 專案權é™å¿…須一一指派給æ¯å€‹ä½¿ç”¨è€…"
+msgstr "ç§äººå°ˆæ¡ˆ - 專案權é™å¿…須明確指派給æ¯ä½ä½¿ç”¨è€…"
msgid "Private - The group and its projects can only be viewed by members."
-msgstr "ç§æœ‰ - 群組åŠæ——下專案åªèƒ½è¢«è©²ç¾¤çµ„æˆå“¡æŸ¥çœ‹"
+msgstr "ç§äººå°ˆæ¡ˆ - 群組與å­å°ˆæ¡ˆåªèƒ½è¢«ç¾¤çµ„æˆå“¡æª¢è¦–。"
msgid "Private projects can be created in your personal namespace with:"
msgstr "å¯ä»¥åœ¨æ‚¨çš„個人命å空間中建立ç§äººå°ˆæ¡ˆ:"
@@ -6061,43 +7054,67 @@ msgid "Profile Settings"
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 "ä½ å°‡è¦æŠŠä½¿ç”¨è€…å稱從 %{currentUsernameBold} æ”¹æˆ %{newUsernameBold}。個人é é¢åŠå°ˆæ¡ˆå°‡æœƒé‡æ–°å°Žå‘到 %{newUsername} 命å空間,直到 %{currentUsername} 命å空間被其他使用或群組註冊 。請盡快更新您的 Git é ç«¯å„²å­˜å€‰åº«ã€‚"
+
+msgid "Profiles|@username"
msgstr ""
msgid "Profiles|Account scheduled for removal."
-msgstr "帳號將會被刪除"
+msgstr "已排程移除帳號程åº"
+
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
msgid "Profiles|Add key"
msgstr "新增金鑰"
msgid "Profiles|Add status emoji"
-msgstr ""
+msgstr "增加狀態表情符號"
msgid "Profiles|Avatar cropper"
-msgstr ""
+msgstr "è£å‰ªé ­è²¼"
msgid "Profiles|Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "將會移除頭貼,確定?"
msgid "Profiles|Change username"
msgstr "變更使用者å稱"
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
msgid "Profiles|Choose file..."
+msgstr "é¸æ“‡æª”案…"
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
msgstr ""
-msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgid "Profiles|City, country"
msgstr ""
msgid "Profiles|Clear status"
+msgstr "清除狀態"
+
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr "ç›®å‰è·¯å¾‘:%{path}"
msgid "Profiles|Current status"
-msgstr ""
+msgstr "ç›®å‰ç‹€æ…‹"
msgid "Profiles|Delete Account"
msgstr "刪除帳號"
@@ -6106,149 +7123,176 @@ msgid "Profiles|Delete account"
msgstr "刪除帳號"
msgid "Profiles|Delete your account?"
-msgstr "刪除您的帳號?"
+msgstr "刪除帳號?"
msgid "Profiles|Deleting an account has the following effects:"
-msgstr "刪除帳號將會造æˆä»¥ä¸‹å½±éŸ¿ï¼š"
+msgstr "刪除帳號將會造æˆé€™äº›å½±éŸ¿ï¼š"
-msgid "Profiles|Do not show on profile"
+msgid "Profiles|Disconnect"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr "ä¸è¦åœ¨å€‹äººæª”案上顯示"
+
msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr ""
+msgstr "ä¸è¦åœ¨å€‹äººæª”案上顯示與活動相關的個人資訊"
msgid "Profiles|Edit Profile"
+msgstr "編輯個人檔案"
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
msgid "Profiles|Invalid password"
-msgstr "無效的密碼"
+msgstr "密碼無效"
msgid "Profiles|Invalid username"
-msgstr "無效的使用者å稱"
+msgstr "使用者å稱無效"
msgid "Profiles|Learn more"
-msgstr ""
+msgstr "了解更多"
msgid "Profiles|Made a private contribution"
-msgstr ""
+msgstr "ç§äººè²¢ç»"
msgid "Profiles|Main settings"
-msgstr ""
+msgstr "主è¦è¨­å®š"
msgid "Profiles|No file chosen"
-msgstr ""
+msgstr "未é¸æ“‡æª”案"
msgid "Profiles|Path"
msgstr "ä½ç½®"
msgid "Profiles|Position and size your new avatar"
-msgstr ""
+msgstr "定ä½ä¸¦èª¿æ•´æ‚¨æ–°é ­è²¼çš„大å°"
msgid "Profiles|Private contributions"
-msgstr ""
+msgstr "ç§äººè²¢ç»"
msgid "Profiles|Public Avatar"
-msgstr ""
+msgstr "公開頭貼"
msgid "Profiles|Remove avatar"
-msgstr ""
+msgstr "移除頭貼"
msgid "Profiles|Set new profile picture"
+msgstr "設定新設定檔圖åƒ"
+
+msgid "Profiles|Social sign-in"
msgstr ""
msgid "Profiles|Some options are unavailable for LDAP accounts"
-msgstr ""
+msgstr "部份é¸é …ä¸æ”¯æ´ LDAP 帳號"
-msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
-msgstr ""
+msgstr "檔案必須è¦åœ¨ 200KB 以下。"
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "這看起來ä¸åƒæ˜¯ SSH 公鑰,您確定è¦å¢žåŠ å®ƒå—Žï¼Ÿ"
-msgid "Profiles|This email will be displayed on your public profile."
+msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
-msgstr ""
+msgstr "這個電å­éƒµä»¶å°‡ç”¨æ–¼Web的任何æ“作,例如編輯和åˆä½µã€‚%{learn_more}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr "這個表情符號和訊æ¯å°‡é¡¯ç¤ºæ–¼æ‚¨çš„個人資料和整個工作介é¢ä¸­ã€‚"
+
+msgid "Profiles|This feature is experimental and translations are not complete yet"
msgstr ""
-msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgid "Profiles|This information will appear on your profile"
msgstr ""
-msgid "Profiles|This information will appear on your profile."
+msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
-msgstr "輸入您的 %{confirmationValue} 以確èªï¼š"
+msgstr "輸入 %{confirmationValue} 確èªï¼š"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr "通常以 \"ssh-rsa …\" 起頭"
msgid "Profiles|Update profile settings"
-msgstr ""
+msgstr "更新個人資料設定"
msgid "Profiles|Update username"
msgstr "更新使用者å稱"
msgid "Profiles|Upload new avatar"
-msgstr ""
+msgstr "上傳新的頭åƒ"
msgid "Profiles|Use a private email - %{email}"
-msgstr ""
+msgstr "使用ç§äººé›»å­éƒµä»¶ - %{email}"
msgid "Profiles|Username change failed - %{message}"
-msgstr "使用者å稱更改失敗 - %{message}"
+msgstr "使用者å稱變更失敗 - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "使用者å稱順利變更"
-msgid "Profiles|Website"
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|What's your status?"
+msgstr "ä½ ç›®å‰çš„狀態?"
+
+msgid "Profiles|Who you represent or work for"
msgstr ""
msgid "Profiles|You can change your avatar here"
-msgstr ""
+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 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 ""
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."
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr ""
-msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
msgstr ""
msgid "Profiles|Your status"
-msgstr ""
+msgstr "你的狀態"
msgid "Profiles|e.g. My MacBook key"
msgstr "例如:我的 MacBook 金鑰"
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
msgid "Profiles|your account"
msgstr "你的帳號"
@@ -6256,7 +7300,7 @@ msgid "Profiling - Performance bar"
msgstr "效能欄"
msgid "Programming languages used in this repository"
-msgstr "在這個檔案庫中使用的程å¼èªžè¨€"
+msgstr "此版本庫所包å«çš„程å¼èªžè¨€"
msgid "Progress"
msgstr "進度"
@@ -6265,51 +7309,57 @@ msgid "Project"
msgstr "專案"
msgid "Project '%{project_name}' is in the process of being deleted."
-msgstr "專案 \"%{project_name}\" 正在被刪除。"
+msgstr "正在刪除專案「%{project_name}ã€ã€‚"
msgid "Project '%{project_name}' queued for deletion."
-msgstr "專案 '%{project_name}' 已加入刪除佇列。"
+msgstr "專案「%{project_name}ã€å·²åŠ å…¥åˆªé™¤ä½‡åˆ—。"
msgid "Project '%{project_name}' was successfully created."
-msgstr "專案 '%{project_name}' 建立完æˆã€‚"
+msgstr "專案「%{project_name}ã€å»ºç«‹æˆåŠŸã€‚"
msgid "Project '%{project_name}' was successfully updated."
-msgstr "專案 '%{project_name}' 更新完æˆã€‚"
+msgstr "專案「%{project_name}ã€æ›´æ–°æˆåŠŸã€‚"
msgid "Project Badges"
msgstr "專案徽章"
msgid "Project URL"
-msgstr ""
+msgstr "專案 URL"
msgid "Project access must be granted explicitly to each user."
-msgstr "專案權é™å¿…須一一指派給æ¯å€‹ä½¿ç”¨è€…。"
+msgstr "專案權é™å¿…須明確指派給æ¯ä½ä½¿ç”¨è€…。"
msgid "Project avatar"
-msgstr "專案圖åƒ"
+msgstr "專案大頭貼"
msgid "Project avatar in repository: %{link}"
-msgstr "專案圖åƒåœ¨æª”案庫中: %{link}"
+msgstr "此版本庫的專案大頭貼:%{link}"
msgid "Project details"
-msgstr "專案細節"
+msgstr "專案詳細資訊"
msgid "Project export could not be deleted."
-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 started. A download link will be sent by email."
-msgstr "專案導出已開始。完æˆå¾Œä¸‹è¼‰é€£çµæœƒé€åˆ°æ‚¨çš„信箱。"
+msgstr "已開始專案匯出程åºã€‚完æˆå¾Œä¸‹è¼‰é€£çµå°‡é€åˆ°æ‚¨çš„信箱。"
+
+msgid "Project members"
+msgstr ""
msgid "Project name"
msgstr "專案å稱"
msgid "Project slug"
+msgstr "專案識別文字"
+
+msgid "Project:"
msgstr ""
msgid "ProjectActivityRSS|Subscribe"
@@ -6340,37 +7390,37 @@ msgid "ProjectLifecycle|Stage"
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|Unstar"
-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|Project ID: %{project_id}"
-msgstr ""
+msgstr "專案編號:%{project_id}"
msgid "ProjectSettings|Badges"
-msgstr ""
+msgstr "徵章"
msgid "ProjectSettings|Contact an admin to change this setting."
msgstr "è¯çµ¡ç®¡ç†å“¡ä»¥è®Šæ›´é€™å€‹è¨­å®šã€‚"
msgid "ProjectSettings|Customize your project badges."
-msgstr ""
+msgstr "自訂您專案的徵章。"
msgid "ProjectSettings|Failed to protect the tag"
msgstr "無法ä¿è­·æ¨™ç±¤"
@@ -6379,7 +7429,7 @@ msgid "ProjectSettings|Failed to update tag!"
msgstr "無法更新標籤ï¼"
msgid "ProjectSettings|Learn more about badges."
-msgstr ""
+msgstr "關於徵章的更多資訊。"
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "åªæœ‰å·²ç°½ç½²çš„變更æ‰èƒ½æŽ¨é€åˆ°ç‰ˆæœ¬åº«ã€‚"
@@ -6400,31 +7450,31 @@ msgid "Projects"
msgstr "專案"
msgid "Projects shared with %{group_name}"
-msgstr ""
+msgstr "與 %{group_name} 分享的專案"
msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-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 "æœå°‹æ‚¨çš„專案"
msgid "ProjectsDropdown|Something went wrong on our end."
-msgstr "發生了內部錯誤"
+msgstr "發生內部錯誤。"
msgid "ProjectsDropdown|Sorry, no projects matched your search"
msgstr "抱歉,沒有符åˆæœå°‹æ¢ä»¶çš„專案"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "此功能需è¦ç€è¦½å™¨çš„ localStorage 支æ´"
msgid "PrometheusAlerts|Add alert"
msgstr "增加警報"
@@ -6436,16 +7486,16 @@ msgid "PrometheusAlerts|Edit alert"
msgstr "編輯警報"
msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
+msgstr "建立警示時發生錯誤"
msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
+msgstr "刪除警示時發生錯誤"
msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
+msgstr "讀å–警示時發生錯誤"
msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
+msgstr "儲存警示時發生錯誤"
msgid "PrometheusAlerts|No alert set"
msgstr "未設定警報"
@@ -6456,9 +7506,6 @@ msgstr "æ“作者"
msgid "PrometheusAlerts|Threshold"
msgstr "門檻"
-msgid "PrometheusDashboard|Time"
-msgstr "時間"
-
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "ç™¼ç¾ %{exporters} åŠ %{metrics}"
@@ -6472,7 +7519,7 @@ msgid "PrometheusService|Auto configuration"
msgstr "自動設定"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
-msgstr "在你的群集上自動部署和é…ç½® Prometheus 以監控您的專案環境"
+msgstr "在你的群集上自動部署和設定 Prometheus 以監控您的專案環境"
msgid "PrometheusService|Common metrics"
msgstr "常見指標"
@@ -6483,8 +7530,11 @@ msgstr "常用的指標會根據å—匯出者歡迎的指標庫來自動監控。
msgid "PrometheusService|Custom metrics"
msgstr "自訂指標"
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
-msgstr "尋找和é…置指標⋯⋯"
+msgstr "正在尋找並設定指標⋯⋯"
msgid "PrometheusService|Finding custom metrics..."
msgstr "正在æœå°‹è‡ªè¨‚指標…"
@@ -6496,7 +7546,7 @@ msgid "PrometheusService|Manage clusters"
msgstr "管ç†å¢é›†"
msgid "PrometheusService|Manual configuration"
-msgstr "手動設置"
+msgstr "手動設定"
msgid "PrometheusService|Metrics"
msgstr "指標"
@@ -6505,13 +7555,13 @@ msgid "PrometheusService|Missing environment variable"
msgstr "缺少環境變數"
msgid "PrometheusService|More information"
-msgstr "更多訊æ¯"
+msgstr "更多資訊"
msgid "PrometheusService|New metric"
msgstr "新增指標"
msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
-msgstr "Prometheus API 地å€ï¼Œä¾‹å¦‚ http://prometheus.example.com/"
+msgstr "Prometheus API ä½å€ï¼Œä¾‹å¦‚ http://prometheus.example.com/"
msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
msgstr "Prometheus 正在自動管ç†æ‚¨çš„å¢é›†"
@@ -6520,13 +7570,13 @@ msgid "PrometheusService|These metrics will only be monitored after your first d
msgstr "這些指標åªæœƒåœ¨ä½ ç¬¬ä¸€æ¬¡éƒ¨å±¬ç’°å¢ƒæ™‚æ‰æœƒç›£æŽ§"
msgid "PrometheusService|Time-series monitoring service"
-msgstr "時間監控æœå‹™"
+msgstr "時間åºåˆ—監控æœå‹™"
msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
-msgstr "è¦èµ·ç”¨æ‰‹å‹•é…置,請從群集中å¸è¼‰ Prometheus"
+msgstr "è¦èµ·ç”¨æ‰‹å‹•è¨­å®šï¼Œè«‹å¾žç¾¤é›†ä¸­ç§»é™¤ Prometheus"
msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
-msgstr "如果å…è¨±å®‰è£ Prometheus 在您的群集上,請å–消下é¢çš„手動é…ç½®"
+msgstr "如果å…è¨±å®‰è£ Prometheus 在您的群集上,請å–消下é¢çš„手動設定"
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
msgstr "等您首次部署到環境後以查詢常用指標"
@@ -6556,52 +7606,52 @@ msgid "Promotions|Upgrade plan"
msgstr "å‡ç´šæ–¹æ¡ˆ"
msgid "Protected"
-msgstr ""
+msgstr "å—ä¿è­·"
msgid "Protected Environments"
-msgstr ""
+msgstr "å—ä¿è­·ç’°å¢ƒ"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "%{environment_name} 將開放開發者的寫入權é™ï¼Œç¢ºèªï¼Ÿ"
msgid "ProtectedEnvironment|Allowed to deploy"
-msgstr ""
+msgstr "å…許佈署"
msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr ""
+msgstr "é¸æ“‡å…許佈署的æˆå“¡"
msgid "ProtectedEnvironment|Environment"
-msgstr ""
+msgstr "環境"
msgid "ProtectedEnvironment|Protect"
-msgstr ""
+msgstr "ä¿è­·"
msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
+msgstr "ä¿è­·ç’°å¢ƒæ˜¯ç‚ºäº†è¦é™åˆ¶èƒ½åŸ·è¡Œä½ˆç½²çš„æˆå“¡ã€‚"
msgid "ProtectedEnvironment|Protect an environment"
-msgstr ""
+msgstr "ä¿è­·ç’°å¢ƒ"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
-msgstr ""
+msgstr "ä¿è­·ç’°å¢ƒ (%{protected_environments_count})"
msgid "ProtectedEnvironment|Select an environment"
-msgstr ""
+msgstr "é¸æ“‡ç’°å¢ƒ"
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-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 "Protip:"
msgstr "æ示:"
@@ -6612,20 +7662,23 @@ msgstr "æ供者"
msgid "Pseudonymizer data collection"
msgstr "Pseudonymizer 資料收集"
+msgid "Public"
+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 pipelines"
-msgstr "公共æµæ°´ç·š"
+msgstr "公共管線"
msgid "Pull"
-msgstr ""
+msgstr "拉å–"
msgid "Push"
-msgstr ""
+msgstr "推é€"
msgid "Push Rules"
msgstr "推é€è¦å‰‡"
@@ -6651,46 +7704,58 @@ msgstr "推é€"
msgid "Quarters"
msgstr "季度"
+msgid "Query"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
-msgstr "快速æ“作å¯ä»¥ç”¨æ–¼å•é¡Œæ述和評論框。"
+msgstr "「快速æ“作ã€èƒ½ç”¨æ–¼è­°é¡Œæ述和留言框。"
+
+msgid "README"
+msgstr ""
msgid "Read more"
-msgstr "瞭解更多"
+msgstr "了解更多"
-msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgid "Read more about environments"
msgstr ""
-msgid "Readme"
-msgstr "說明檔"
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr "閱讀有關專案權é™çš„ç›¸é—œè¨Šæ¯ <strong>%{link_to_help}</strong>"
msgid "Real-time features"
msgstr "å³æ™‚功能"
-msgid "Recent searches"
+msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Recent searches"
+msgstr "最近æœå°‹"
+
msgid "Redirect to SAML provider to test configuration"
-msgstr ""
+msgstr "é‡æ–°å°Žå‘到 SAML 供應商,以測試設定"
msgid "Reference:"
-msgstr "åƒè€ƒä¾†æº:"
+msgstr "åƒè€ƒä¾†æºï¼š"
msgid "Refresh"
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 key"
-msgstr ""
+msgstr "é‡æ–°ç”¢ç”Ÿé‡‘é‘°"
msgid "Regex pattern"
-msgstr ""
+msgstr "æ­£è¦è¡¨ç¤ºå¼"
msgid "Register / Sign In"
msgstr "註冊 / 登入"
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "註冊ã€ä¸¦è§€å¯Ÿæ‚¨åœ¨é€™å€‹ç¾¤çµ„的執行器。"
@@ -6701,160 +7766,202 @@ msgid "Registry"
msgstr "註冊表"
msgid "Related Commits"
-msgstr "相關的更動記錄"
+msgstr "相關æ交"
msgid "Related Deployed Jobs"
-msgstr "相關的部署作業"
+msgstr "相關部署作業"
msgid "Related Issues"
-msgstr "相關的議題"
+msgstr "相關議題"
msgid "Related Jobs"
-msgstr "相關的作業"
+msgstr "相關作業"
msgid "Related Merge Requests"
-msgstr "相關的åˆä½µè«‹æ±‚"
+msgstr "相關åˆä½µè«‹æ±‚"
msgid "Related Merged Requests"
-msgstr "相關已åˆä½µçš„請求"
+msgstr "相關已åˆä½µè«‹æ±‚"
msgid "Related merge requests"
msgstr "相關的åˆä½µè«‹æ±‚"
+msgid "Releases"
+msgstr ""
+
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr "ç¨å¾Œæ醒"
msgid "Remove"
-msgstr "刪除"
+msgstr "移除"
msgid "Remove Runner"
msgstr "移除執行器"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove avatar"
-msgstr "刪除大頭貼"
+msgstr "移除大頭貼"
msgid "Remove group"
-msgstr ""
+msgstr "刪除群組"
msgid "Remove priority"
msgstr "刪除優先權"
msgid "Remove project"
-msgstr "刪除專案"
+msgstr "移除專案"
msgid "Removed group can not be restored!"
-msgstr ""
+msgstr "刪除的群組將無法復原ï¼"
msgid "Removing group will cause all child projects and resources to be removed."
-msgstr ""
+msgstr "刪除群組將導致所有å­å°ˆæ¡ˆå’Œè³‡æºè¢«åˆªé™¤ã€‚"
msgid "Rename"
-msgstr ""
+msgstr "é‡æ–°å‘½å"
msgid "Rename file"
-msgstr ""
+msgstr "é‡æ–°å‘½å檔案"
msgid "Rename folder"
-msgstr ""
+msgstr "é‡æ–°å‘½å資料夾"
msgid "Reopen epic"
+msgstr "é‡æ–°é–‹å•Ÿ Epic"
+
+msgid "Reopen milestone"
msgstr ""
msgid "Repair authentication"
msgstr "修復èªè­‰"
-msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgid "Reply to comment"
msgstr ""
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr "直接回復此電å­ä¿¡ç®±æˆ– %{view_it_on_gitlab}。"
+
msgid "Repo by URL"
msgstr "來自 URL 的版本庫"
msgid "Report abuse to GitLab"
-msgstr ""
+msgstr "å‘ GitLab 回報濫用行為"
msgid "Reporting"
-msgstr ""
+msgstr "正在回報"
msgid "Reports|%{failedString} and %{resolvedString}"
-msgstr ""
+msgstr "%{failedString} 和 %{resolvedString}"
msgid "Reports|Actions"
-msgstr ""
+msgstr "æ“作"
msgid "Reports|Class"
-msgstr ""
+msgstr "類別"
msgid "Reports|Confidence"
-msgstr ""
+msgstr "ä¿¡ä»»"
msgid "Reports|Execution time"
-msgstr ""
+msgstr "執行時間"
msgid "Reports|Failure"
-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 results are being parsed"
-msgstr ""
+msgstr "正在解æžæ¸¬è©¦æ‘˜è¦çµæžœ"
msgid "Reports|Vulnerability"
-msgstr ""
+msgstr "風險"
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "沒有變更的測試çµæžœ"
msgid "Repository"
-msgstr "檔案庫"
+msgstr "版本庫"
msgid "Repository Settings"
-msgstr "檔案庫設置"
+msgstr "版本庫設定"
msgid "Repository URL"
msgstr "版本庫 URL"
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
msgid "Repository has no locks."
msgstr "版本庫沒有上鎖。"
msgid "Repository maintenance"
-msgstr "檔案庫維護"
+msgstr "版本庫維護"
msgid "Repository mirror"
-msgstr "é¡åƒæª”案庫"
+msgstr "é¡åƒç‰ˆæœ¬åº«"
msgid "Repository storage"
-msgstr "檔案庫儲存空間"
+msgstr "版本庫儲存空間"
msgid "RepositorySettingsAccessLevel|Select"
msgstr "é¸æ“‡"
msgid "Request Access"
-msgstr "申請權é™"
+msgstr "申請存å–權é™"
+
+msgid "Requested %{time_ago}"
+msgstr ""
msgid "Requests Profiles"
msgstr "請求個人資料"
msgid "Require all users in this group to setup Two-factor authentication"
-msgstr ""
+msgstr "è¦æ±‚此群組中的所有使用者啟用兩步驟驗證"
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
-msgstr "è¦æ±‚所有用戶在訪å•GitLab時接å—æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–。"
+msgstr "è¦æ±‚所有使用者在訪å•GitLab時接å—æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–。"
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
msgid "Reset health check access token"
-msgstr "é‡ç½®å¥åº·æª¢æŸ¥å­˜å–憑證"
+msgstr "é‡è¨­å¥åº·æª¢æŸ¥å­˜å–憑證"
+
+msgid "Reset key"
+msgstr ""
msgid "Reset runners registration token"
-msgstr "é‡ç½® Runner 註冊憑證"
+msgstr "é‡è¨­åŸ·è¡Œå™¨è¨»å†Šæ†‘è­‰"
+
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
msgid "Resolve all discussions in new issue"
msgstr "建立新議題以解決所有討論"
@@ -6865,19 +7972,31 @@ msgstr "解決來æºåˆ†æ”¯ä¸Šçš„è¡çª"
msgid "Resolve discussion"
msgstr "關閉討論"
-msgid "Response metrics (AWS ELB)"
+msgid "Resolved"
+msgstr ""
+
+msgid "Response"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr "回應指標 (AWS ELB)"
+
msgid "Response metrics (Custom)"
msgstr "接收指標 (自訂)"
msgid "Response metrics (HA Proxy)"
+msgstr "回應指標 (HA 代ç†ä¼ºæœå™¨)"
+
+msgid "Response metrics (NGINX Ingress VTS)"
msgstr ""
msgid "Response metrics (NGINX Ingress)"
-msgstr ""
+msgstr "回應指標 (NGINX Ingress)"
msgid "Response metrics (NGINX)"
+msgstr "回應指標 (NGINX)"
+
+msgid "Restart Terminal"
msgstr ""
msgid "Resume"
@@ -6892,30 +8011,30 @@ msgstr "é‡è©¦æ­¤å·¥ä½œ"
msgid "Retry verification"
msgstr "é‡è©¦é©—è­‰"
-msgid "Reveal Variables"
-msgstr ""
-
msgid "Reveal value"
msgid_plural "Reveal values"
-msgstr[0] "顯示隱è—的資料"
+msgstr[0] "æ­ç¤ºæ•¸å€¼"
+
+msgid "Reveal values"
+msgstr ""
msgid "Revert this commit"
-msgstr "還原此更動記錄"
+msgstr "還原此æ交"
msgid "Revert this merge request"
-msgstr "還原此åˆä½µ"
+msgstr "還原此åˆä½µè«‹æ±‚"
msgid "Review"
-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 就是「æœå‹™æ供者ã€æˆ–「ä¾è³´æ–¹ã€ã€‚"
+msgstr "檢閱您的身份æ供者中設定æœå‹™æ供者的éŽç¨‹ -- 如果這樣,GitLab 就是「æœå‹™æ供者ã€æˆ–「ä¾è³´æ–¹ã€ã€‚"
msgid "Reviewing"
-msgstr "審查"
+msgstr "檢閱"
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr "正在審閱中(åˆä½µè«‹æ±‚ !%{mergeRequestId})"
+msgstr "正在檢閱中(åˆä½µè«‹æ±‚ !%{mergeRequestId})"
msgid "Revoke"
msgstr "撤回"
@@ -6924,28 +8043,31 @@ msgid "Roadmap"
msgstr "開發è—圖"
msgid "Run CI/CD pipelines for external repositories"
-msgstr "執行外部版本庫的 CI / CD æµæ°´ç·šã€‚"
+msgstr "執行外部版本庫的 CI / CD 管線。"
-msgid "Run untagged jobs"
+msgid "Run tests against your code live using the Web Terminal"
msgstr ""
+msgid "Run untagged jobs"
+msgstr "執行未標記的工作"
+
msgid "Runner cannot be assigned to other projects"
-msgstr ""
+msgstr "無法分é…執行器給其他專案"
msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
+msgstr "執行器將執行所有未指定的專案的作業"
msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
+msgstr "執行器將執行所有群組中未指定的專案的作業"
msgid "Runner runs jobs from assigned projects"
-msgstr ""
+msgstr "執行器將執行指定專案的工作"
msgid "Runner token"
msgstr "執行器憑證"
msgid "Runner will not receive any new jobs"
-msgstr ""
+msgstr "執行器將ä¸æœƒæŽ¥å—新的工作"
msgid "Runners"
msgstr "執行器"
@@ -6953,23 +8075,26 @@ msgstr "執行器"
msgid "Runners API"
msgstr "執行器 API"
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "執行器å¯æ”¾ç½®æ–¼ä¸åŒçš„使用者ã€ä¼ºæœå™¨ï¼Œç”šè‡³åœ¨æ‚¨çš„本地機器上。"
+msgstr "執行器å¯æ”¾ç½®æ–¼ä¸åŒçš„使用者ã€ä¼ºæœå™¨ï¼Œç”šè‡³åœ¨æ‚¨çš„本機機器上。"
msgid "Runners can be placed on separate users, servers, even on your local machine."
-msgstr ""
+msgstr "執行器å¯ä»¥åŸ·è¡Œåœ¨ä¸åŒçš„使用者ã€ä¼ºæœå™¨ã€ç”šè‡³æ˜¯æ‚¨æœ¬æ©Ÿçš„電腦。"
msgid "Runners currently online: %{active_runners_count}"
-msgstr ""
+msgstr "ç›®å‰ç·šä¸Šçš„執行器:%{active_runners_count}"
msgid "Runners page"
-msgstr ""
+msgstr "執行器é é¢"
msgid "Runners page."
-msgstr ""
+msgstr "執行器é é¢ã€‚"
msgid "Runners|You have used all your shared Runners pipeline minutes."
-msgstr ""
+msgstr "您已經使用了所有分享的執行器多久的時間。"
msgid "Running"
msgstr "執行中"
@@ -6986,7 +8111,7 @@ msgstr "SAML 單一登入"
msgid "SAML Single Sign On Settings"
msgstr "SAML 單一登入設定"
-msgid "SAST"
+msgid "SAML for %{group_name}"
msgstr ""
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
@@ -6996,10 +8121,10 @@ msgid "SSH Keys"
msgstr "SSH 金鑰"
msgid "SSH host keys"
-msgstr ""
+msgstr "SSH 主機金鑰"
msgid "SSH public key"
-msgstr ""
+msgstr "SSH 公鑰"
msgid "SSL Verification"
msgstr "SSL é©—è­‰"
@@ -7007,6 +8132,9 @@ msgstr "SSL é©—è­‰"
msgid "Save"
msgstr "儲存"
+msgid "Save Changes"
+msgstr ""
+
msgid "Save application"
msgstr "儲存應用程å¼"
@@ -7014,16 +8142,19 @@ msgid "Save changes"
msgstr "儲存變更"
msgid "Save changes before testing"
+msgstr "測試å‰å„²å­˜ä¿®æ”¹"
+
+msgid "Save comment"
msgstr ""
msgid "Save pipeline schedule"
-msgstr "儲存æµæ°´ç·šæŽ’程"
+msgstr "儲存排程管線"
msgid "Save variables"
msgstr "儲存變數"
msgid "Schedule a new pipeline"
-msgstr "建立æµæ°´ç·šæŽ’程"
+msgstr "排程新管線"
msgid "Scheduled"
msgstr "已排程"
@@ -7032,7 +8163,7 @@ msgid "Schedules"
msgstr "排程"
msgid "Scheduling Pipelines"
-msgstr "æµæ°´ç·šæŽ’程"
+msgstr "排程管線"
msgid "Scope"
msgstr "範åœ"
@@ -7041,7 +8172,7 @@ msgid "Scoped issue boards"
msgstr "å€åŸŸæ€§çš„議題看æ¿"
msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
-msgstr ""
+msgstr "å‘下滾動到 <strong>Google Code Project Hosting</strong> 並啟用å³å´çš„開關。"
msgid "Scroll to bottom"
msgstr "滾到底部"
@@ -7052,6 +8183,9 @@ msgstr "滾到頂部"
msgid "Search"
msgstr "æœå°‹"
+msgid "Search an environment spec"
+msgstr ""
+
msgid "Search branches"
msgstr "æœå°‹åˆ†æ”¯"
@@ -7064,6 +8198,9 @@ msgstr "æœå°‹æª”案"
msgid "Search for projects, issues, etc."
msgstr "æœå°‹å°ˆæ¡ˆã€è­°é¡Œç­‰ç­‰"
+msgid "Search groups"
+msgstr ""
+
msgid "Search merge requests"
msgstr "æœå°‹åˆä½µè«‹æ±‚"
@@ -7071,121 +8208,142 @@ msgid "Search milestones"
msgstr "æœå°‹é‡Œç¨‹ç¢‘"
msgid "Search or filter results..."
-msgstr ""
+msgstr "æœå°‹æˆ–篩é¸çµæžœâ€¦"
msgid "Search or jump to…"
-msgstr ""
+msgstr "æœå°‹æˆ–轉到…"
msgid "Search project"
msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "Search projects"
-msgstr ""
+msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "Search users"
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|in all GitLab"
-msgstr ""
+msgstr "在整個 GitLab"
msgid "SearchAutocomplete|in this group"
-msgstr ""
+msgstr "在這個群組"
msgid "SearchAutocomplete|in this project"
-msgstr ""
+msgstr "在這個專案"
msgid "Secret"
-msgstr ""
+msgstr "密碼"
msgid "Security"
-msgstr ""
+msgstr "安全"
msgid "Security Dashboard"
msgstr "安全儀表æ¿"
msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
-msgstr ""
+msgstr "讀å–儀表æ¿è³‡æ–™æ™‚發生錯誤,請檢查您的網路連線,然後é‡æ–°å˜—試。"
msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
-msgstr ""
+msgstr "讀å–æ¼æ´žè³‡è¨Šæ™‚發生錯誤,請檢查您的網路連線,然後é‡æ–°å˜—試。"
msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
-msgstr ""
+msgstr "讀å–æ¼æ´žåˆ—表時發生錯誤,請檢查您的網路連線,然後é‡æ–°å˜—試。"
msgid "Security Dashboard|Issue Created"
-msgstr ""
+msgstr "已建立å•é¡Œ"
-msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgid "Security Reports|At this time, the security dashboard only supports SAST and dependency scanning."
msgstr ""
msgid "Security Reports|Create issue"
-msgstr ""
+msgstr "建立å•é¡Œ"
msgid "Security Reports|Dismiss vulnerability"
+msgstr "忽略æ¼æ´ž"
+
+msgid "Security Reports|Learn more about setting up your dashboard"
msgstr ""
msgid "Security Reports|More info"
-msgstr ""
+msgstr "更多資訊"
-msgid "Security Reports|Revert dismissal"
+msgid "Security Reports|No Vulnerabilities"
msgstr ""
msgid "Security Reports|Security dashboard documentation"
-msgstr ""
+msgstr "安全儀表æ¿æª”案"
msgid "Security Reports|There was an error creating the issue."
-msgstr ""
+msgstr "建立議題時發生錯誤。"
msgid "Security Reports|There was an error dismissing the vulnerability."
-msgstr ""
+msgstr "忽略æ¼æ´žæ™‚發生錯誤。"
msgid "Security Reports|There was an error reverting the dismissal."
-msgstr ""
+msgstr "å–消忽略時發生錯誤"
msgid "Security Reports|There was an error reverting this dismissal."
+msgstr "å–消忽略時發生錯誤。"
+
+msgid "Security Reports|Undo dismiss"
msgstr ""
-msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgid "Security Reports|We've found no vulnerabilities for your group"
+msgstr ""
+
+msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Security dashboard"
msgstr ""
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr "安全儀表æ¿å°‡é¡¯ç¤ºæœ€æ–°çš„安全報告。用它來尋找和修補æ¼æ´žã€‚"
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "監控程å¼ç¢¼ä¸­çš„æ¼æ´ž"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
-msgstr "觸發了æµæ°´ç·š %{pipelineLink}"
+msgstr "觸發了管線 %{pipelineLink}"
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
msgid "Select"
msgstr "é¸æ“‡"
msgid "Select Archive Format"
-msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
+msgstr "é¸æ“‡å°å­˜æª”æ ¼å¼"
msgid "Select a group to invite"
-msgstr ""
+msgstr "é¸æ“‡è¦é‚€è«‹çš„群組"
msgid "Select a namespace to fork the project"
msgstr "é¸æ“‡ä¸€å€‹å‘½å空間,以複製這個專案"
msgid "Select a template repository"
-msgstr ""
+msgstr "é¸æ“‡æ¨¡æ¿ç‰ˆæœ¬åº«"
msgid "Select a timezone"
msgstr "é¸æ“‡æ™‚å€"
@@ -7194,10 +8352,13 @@ msgid "Select an existing Kubernetes cluster or create a new one"
msgstr "é¸æ“‡ä¸€å€‹ç¾æœ‰çš„ Kubernetes å¢é›†æˆ–新增一個"
msgid "Select assignee"
-msgstr "é¸æ“‡æŒ‡æ´¾äºº"
+msgstr "é¸æ“‡è¢«æŒ‡æ´¾äºº"
msgid "Select branch/tag"
-msgstr "é¸æ“‡åˆ†æ”¯/標籤"
+msgstr "é¸æ“‡åˆ†æ”¯æˆ–標籤"
+
+msgid "Select members to invite"
+msgstr ""
msgid "Select project"
msgstr "é¸æ“‡å°ˆæ¡ˆ"
@@ -7209,7 +8370,7 @@ msgid "Select project to choose zone"
msgstr "é¸æ“‡å°ˆæ¡ˆä»¥é¸æ“‡ä½ç½®"
msgid "Select projects you want to import."
-msgstr ""
+msgstr "é¸æ“‡ä½ æƒ³è¦åŒ¯å…¥çš„專案。"
msgid "Select source branch"
msgstr "é¸æ“‡ä¾†æºåˆ†æ”¯"
@@ -7218,13 +8379,13 @@ msgid "Select target branch"
msgstr "é¸æ“‡ç›®æ¨™åˆ†æ”¯"
msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
+msgstr "é¸æ“‡æ­¤å°ˆæ¡ˆçš„é è¨­åˆ†æ”¯ã€‚除éžæœ‰é¡å¤–設定,å¦å‰‡æ‰€æœ‰åˆä½µè«‹æ±‚å’Œæ交都會指å‘此分支。"
msgid "Select the custom project template source group."
-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 <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
-msgstr ""
+msgstr "é¸æ“‡ GitLab 使用者將在議題和留言的æè¿°ä¸­æ–°å¢žæŒ‡å‘ GitLab 使用者的超連çµï¼ˆä¾‹å¦‚\"ç”± <a href=\"#\">@johnsmith</a>\")。它還將與所é¸ä½¿ç”¨è€…é—œè¯/分é…這些議題和留言。"
msgid "Selective synchronization"
msgstr "é¸æ“‡æ€§åŒæ­¥"
@@ -7232,7 +8393,13 @@ msgstr "é¸æ“‡æ€§åŒæ­¥"
msgid "Send email"
msgstr "傳é€é›»å­éƒµä»¶"
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
+msgstr "寄é€ä½¿ç”¨æƒ…æ³è³‡æ–™"
+
+msgid "Sentry API URL"
msgstr ""
msgid "Sep"
@@ -7244,11 +8411,53 @@ msgstr "ä¹æœˆ"
msgid "Server version"
msgstr "伺æœå™¨ç‰ˆæœ¬"
+msgid "Serverless"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL to clipboard"
+msgstr ""
+
+msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
+msgstr ""
+
+msgid "Serverless|An error occurred while retrieving serverless components"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
msgid "Service Desk"
msgstr "æœå‹™å€"
msgid "Service Templates"
-msgstr "æœå‹™ç¯„本"
+msgstr "æœå‹™æ¨¡æ¿"
msgid "Service URL"
msgstr "æœå‹™ URL"
@@ -7257,16 +8466,16 @@ msgid "Session expiration, projects limit and attachment size."
msgstr "éŽæœŸå·¥ä½œéšŽæ®µã€å°ˆæ¡ˆä¸Šé™èˆ‡é™„件大å°ã€‚"
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr "請先設定密碼,æ‰èƒ½ä½¿ç”¨ %{protocol} 來上傳或下載。"
+msgstr "請先設定密碼,æ‰èƒ½ä½¿ç”¨ %{protocol} 上傳或下載。"
msgid "Set a template repository for projects in this group"
-msgstr ""
+msgstr "為該群組中的專案設定模æ¿ç‰ˆæœ¬åº«"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
-msgstr "設定為é è¨­å€¼ï¼Œä¸¦é™åˆ¶å¯è¦‹ç­‰ç´šã€‚設定匯入來æºå’Œ git å­˜å–連接å”定。"
+msgstr "設定為é è¨­å€¼ï¼Œä¸¦é™åˆ¶å¯è¦‹ç­‰ç´šã€‚設定匯入來æºå’Œ git å­˜å–連線å”定。"
msgid "Set instance-wide template repository"
-msgstr ""
+msgstr "設定實例範åœçš„模æ¿ç‰ˆæœ¬åº«"
msgid "Set max session time for web terminal."
msgstr "為網é çµ‚端器設定最長工作階段時間"
@@ -7274,50 +8483,56 @@ msgstr "為網é çµ‚端器設定最長工作階段時間"
msgid "Set notification email for abuse reports."
msgstr "為濫用回報設定通知電å­ä¿¡ç®±ã€‚"
+msgid "Set number of approvers required before open merge requests can be merged"
+msgstr ""
+
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "設定使用者登入的需求。啟用強制性的兩步驟驗證。"
msgid "Set up CI/CD"
-msgstr "設定 CI/CD"
+msgstr "設定 CI / CD"
msgid "Set up a %{type} Runner manually"
-msgstr ""
+msgstr "手動設定 %{type} 執行器"
msgid "Set up a specific Runner automatically"
-msgstr ""
+msgstr "自動設定特定的執行器"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
-msgstr "根據 %{docsLinkStart}這個文件%{icon}%{docsLinkEnd} 設定斷言 / 屬性 / è²æ˜Ž (email, first_name, last_name) å’Œ NameID"
+msgstr "根據 %{docsLinkStart}這個檔案%{icon}%{docsLinkEnd} 設定斷言 / 屬性 / è²æ˜Ž (email, first_name, last_name) å’Œ NameID"
-msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgid "Set up new U2F device"
msgstr ""
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr "設定你的專案以自動推é€å’Œ/或從å¦ä¸€å€‹ç‰ˆæœ¬åº«æ‹‰å–變更。分支ã€æ¨™ç±¤åŠæ交將會自動åŒæ­¥ã€‚"
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "設定密碼"
msgid "SetStatusModal|Add status emoji"
-msgstr ""
+msgstr "增加狀態表情符號"
msgid "SetStatusModal|Clear status"
-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|What's your status?"
-msgstr ""
+msgstr "你的狀態是什麼?"
msgid "Settings"
msgstr "設定"
@@ -7332,16 +8547,16 @@ msgid "Shared Runners"
msgstr "分享的執行器"
msgid "Shared projects"
-msgstr ""
+msgstr "已分享專案"
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 "Sherlock Transactions"
msgstr "Sherlock 交易"
@@ -7350,19 +8565,19 @@ msgid "Show command"
msgstr "顯示指令"
msgid "Show complete raw log"
-msgstr "顯示完整的原始日誌"
+msgstr "顯示完整的原始記錄"
+
+msgid "Show file browser"
+msgstr ""
msgid "Show latest version"
msgstr "顯示最新版本"
-msgid "Show latest version of the diff"
-msgstr "顯示與最新版本的差異"
-
msgid "Show parent pages"
msgstr "顯示上層é é¢"
msgid "Show parent subgroups"
-msgstr "顯示群組中的å­ç¾¤çµ„"
+msgstr "顯示上層å­ç¾¤çµ„"
msgid "Show whitespace changes"
msgstr "顯示空白變化"
@@ -7392,24 +8607,36 @@ msgstr "登入"
msgid "Sign in / Register"
msgstr "登入 / 註冊"
-msgid "Sign in to %{group_name}"
-msgstr "登入至 %{group_name}"
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
msgid "Sign in with Single Sign-On"
msgstr "é€éŽå–®ä¸€ç™»å…¥é€²è¡Œç™»å…¥"
+msgid "Sign in with smart card"
+msgstr ""
+
msgid "Sign out"
msgstr "登出"
msgid "Sign-in restrictions"
-msgstr "登錄é™åˆ¶"
+msgstr "登入é™åˆ¶"
msgid "Sign-up restrictions"
msgstr "註冊é™åˆ¶"
-msgid "Size"
+msgid "Similar issues"
msgstr ""
+msgid "Size"
+msgstr "大å°"
+
msgid "Size and domain settings for static websites"
msgstr "為éœæ…‹ç¶²ç«™çš„大å°èˆ‡ç¶²åŸŸè¨­å®š"
@@ -7417,22 +8644,31 @@ msgid "Slack application"
msgstr "Slack 應用程å¼"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
-msgstr ""
+msgstr "Slack æ•´åˆå…許您é€éŽèŠå¤©è¦–窗中的斜線指令與GitLab進行整åˆã€‚"
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "速度較慢,但確ä¿é …目工作空間是原始的,因為它為æ¯é …工作從頭開始複製檔案庫"
+msgstr "速度較慢,但確ä¿å°ˆæ¡ˆå·¥ä½œç©ºé–“是原始的,因為它為æ¯é …工作從頭開始複製版本庫"
msgid "Smartcard"
-msgstr ""
+msgstr "Smartcard"
msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr "Smartcard èªè­‰å¤±æ•—:使用者端缺少èªè­‰æ¨™é ­ã€‚"
+
+msgid "Snippet Contents"
msgstr ""
msgid "Snippets"
msgstr "程å¼ç¢¼ç‰‡æ®µ"
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
msgid "Something went wrong on our end"
-msgstr "發生了錯誤。"
+msgstr "內部發生錯誤"
msgid "Something went wrong on our end."
msgstr "發生了錯誤。"
@@ -7440,35 +8676,47 @@ msgstr "發生了錯誤。"
msgid "Something went wrong on our end. Please try again!"
msgstr "未知錯誤,請é‡è©¦!"
-msgid "Something went wrong trying to change the confidentiality of this issue"
+msgid "Something went wrong on our end. Please try again."
msgstr ""
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr "試圖改變這個議題的隱ç§è¨­å®šæ™‚發生錯誤"
+
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
-msgstr ""
+msgstr "試圖改變 %{issuableDisplayName} 的鎖定狀態時發生錯誤"
msgid "Something went wrong when toggling the button"
-msgstr "切æ›æŒ‰éˆ•æ™‚發生未知的錯誤"
+msgstr "切æ›æŒ‰éˆ•æ™‚發生錯誤"
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "在關閉議題 %{issuable} 時出ç¾å•é¡Œï¼Œè«‹ç¨å¾Œå†è©¦"
-msgid "Something went wrong while fetching %{listType} list"
+msgid "Something went wrong while deleting the source branch. Please try again."
msgstr ""
+msgid "Something went wrong while fetching %{listType} list"
+msgstr "è®€å– %{listType} 列表時發生錯誤"
+
msgid "Something went wrong while fetching comments. Please try again."
-msgstr ""
+msgstr "讀å–留言時發生錯誤,請ç¨å€™é‡è©¦ã€‚"
msgid "Something went wrong while fetching group member contributions"
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 projects."
-msgstr "讀å–專案時發生錯誤。"
+msgstr "抓å–專案時發生錯誤。"
msgid "Something went wrong while fetching the registry list."
-msgstr "讀å–註冊列表時發生錯誤。"
+msgstr "抓å–註冊表列表時發生錯誤。"
+
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr "é‡æ–°é–‹å•Ÿ %{issuable} 議題時發生錯誤。請ç¨å¾Œå†è©¦"
@@ -7477,31 +8725,37 @@ msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "解決此議題時出ç¾å•é¡Œã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "Something went wrong, unable to add %{project} to dashboard"
-msgstr ""
+msgstr "å°‡ %{project} 新增到儀表æ¿æ™‚發生錯誤"
msgid "Something went wrong, unable to get operations projects"
-msgstr ""
+msgstr "讀å–專案時發生錯誤"
msgid "Something went wrong, unable to remove project"
-msgstr ""
+msgstr "刪除專案時發生錯誤"
msgid "Something went wrong. Please try again."
-msgstr "發生了未知的錯誤,請ç¨å¾Œå†è©¦"
+msgstr "發生未知錯誤,請ç¨å¾Œå†è©¦ã€‚"
msgid "Sorry, no epics matched your search"
msgstr "抱歉,沒有符åˆæ‚¨æœå°‹çš„ Epic"
msgid "Sorry, no projects matched your search"
+msgstr "抱歉,沒有符åˆæ‚¨æœå°‹çš„專案"
+
+msgid "Sorry, your filter produced no results"
msgstr ""
msgid "Sort by"
-msgstr "排åº"
+msgstr "排åºæ–¹å¼"
+
+msgid "Sort direction"
+msgstr ""
msgid "SortOptions|Access level, ascending"
-msgstr "å­˜å–層級,以å‡å†ªæŽ’列"
+msgstr "å­˜å–層級(å‡å†ªï¼‰"
msgid "SortOptions|Access level, descending"
-msgstr "å­˜å–層級,以é™å†ªæŽ’列"
+msgstr "å­˜å–層級(é™å†ªï¼‰"
msgid "SortOptions|Created date"
msgstr "建立日期"
@@ -7510,10 +8764,10 @@ msgid "SortOptions|Due date"
msgstr "截止日期"
msgid "SortOptions|Due later"
-msgstr "已截止"
+msgstr "已截止日期"
msgid "SortOptions|Due soon"
-msgstr "å³å°‡æˆªæ­¢"
+msgstr "å³å°‡æˆªæ­¢æ—¥æœŸ"
msgid "SortOptions|Label priority"
msgstr "標籤優先"
@@ -7522,13 +8776,13 @@ msgid "SortOptions|Largest group"
msgstr "最大群組"
msgid "SortOptions|Largest repository"
-msgstr "最大儲存庫"
+msgstr "最大版本庫"
msgid "SortOptions|Last Contact"
-msgstr ""
+msgstr "最後è¯çµ¡äºº"
msgid "SortOptions|Last created"
-msgstr "最近建立"
+msgstr "最近建立時間"
msgid "SortOptions|Last joined"
msgstr "最近加入"
@@ -7542,8 +8796,8 @@ msgstr "最ä¸å—æ­¡è¿Ž"
msgid "SortOptions|Less weight"
msgstr "é™ä½Žæ¬Šé‡"
-msgid "SortOptions|Milestone"
-msgstr "里程碑"
+msgid "SortOptions|Milestone due date"
+msgstr ""
msgid "SortOptions|Milestone due later"
msgstr "里程碑截止日期"
@@ -7558,16 +8812,16 @@ msgid "SortOptions|Most popular"
msgstr "最å—æ­¡è¿Ž"
msgid "SortOptions|Most stars"
-msgstr ""
+msgstr "最多星星"
msgid "SortOptions|Name"
msgstr "å稱"
msgid "SortOptions|Name, ascending"
-msgstr "å稱ã€å‡å†ªæŽ’列"
+msgstr "å稱(å‡å†ªï¼‰"
msgid "SortOptions|Name, descending"
-msgstr "å稱ã€é™å†ªæŽ’列"
+msgstr "å稱(é™å†ªï¼‰"
msgid "SortOptions|Oldest created"
msgstr "最早建立"
@@ -7575,11 +8829,14 @@ msgstr "最早建立"
msgid "SortOptions|Oldest joined"
msgstr "最早加入"
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
msgid "SortOptions|Oldest sign in"
msgstr "最早登入"
msgid "SortOptions|Oldest updated"
-msgstr "最早æ交"
+msgstr "最早更新"
msgid "SortOptions|Popularity"
msgstr "最有人氣"
@@ -7587,11 +8844,14 @@ msgstr "最有人氣"
msgid "SortOptions|Priority"
msgstr "優先"
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
msgid "SortOptions|Recent sign in"
msgstr "最近登入"
msgid "SortOptions|Start date"
-msgstr ""
+msgstr "開始日期"
msgid "SortOptions|Start later"
msgstr "ç¨å¾Œé–‹å§‹"
@@ -7612,7 +8872,10 @@ msgid "Source code"
msgstr "原始碼"
msgid "Source is not available"
-msgstr "來æºä¸å¯ç”¨"
+msgstr "來æºç„¡æ³•ä½¿ç”¨"
+
+msgid "Source project cannot be found."
+msgstr ""
msgid "Spam Logs"
msgstr "垃圾訊æ¯è¨˜éŒ„"
@@ -7624,10 +8887,13 @@ msgid "Specific Runners"
msgstr "指定執行器"
msgid "Specify an e-mail address regex pattern to identify default internal users."
-msgstr ""
+msgstr "指定電å­éƒµä»¶ä½å€æ­£è¦è¡¨ç¤ºå¼ä»¥è­˜åˆ¥é è¨­å…§éƒ¨ä½¿ç”¨è€…。"
msgid "Specify the following URL during the Runner setup:"
-msgstr "åœ¨å®‰è£ Runner 時指定以下 URL:"
+msgstr "在安è£åŸ·è¡Œå™¨æ™‚指定以下 URL:"
+
+msgid "Squash commit message"
+msgstr ""
msgid "Squash commits"
msgstr "åˆä½µæ交"
@@ -7651,41 +8917,68 @@ msgid "Staged %{type}"
msgstr "已暫存的 %{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
-msgstr "為一個標籤標上星號,使其æˆç‚ºå„ªå…ˆæ¨™ç±¤ã€‚通éŽæ‹–動命令優先標籤更改其相å°å„ªå…ˆç´šã€‚"
+msgstr "為一個標籤標上星號,使其æˆç‚ºå„ªå…ˆæ¨™ç±¤ã€‚é€éŽæ‹–動指令優先標籤變更其相å°å„ªå…ˆåº¦ã€‚"
msgid "StarProject|Star"
msgstr "收è—"
msgid "Starred Projects"
-msgstr "已星標的專案"
+msgstr "已收è—的專案"
msgid "Starred Projects' Activity"
-msgstr "已星標的專案活動"
+msgstr "已收è—的專案活動"
msgid "Starred projects"
-msgstr "星標項目"
+msgstr "收è—專案"
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
msgid "Start a %{new_merge_request} with these changes"
-msgstr "以這些改動建立一個新的 %{new_merge_request} "
+msgstr "建立包å«é€™äº›è®Šå‹•çš„ %{new_merge_request}"
msgid "Start a review"
-msgstr ""
+msgstr "開始檢閱"
msgid "Start and due date"
+msgstr "開始和截止日期"
+
+msgid "Start cleanup"
msgstr ""
msgid "Start date"
+msgstr "開始日期"
+
+msgid "Start discussion"
+msgstr ""
+
+msgid "Start discussion & close %{noteable_name}"
+msgstr ""
+
+msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
msgid "Start the Runner!"
-msgstr "å•Ÿå‹• Runner!"
+msgstr "啟動執行器ï¼"
msgid "Start your trial"
-msgstr ""
+msgstr "開始試用"
msgid "Started"
msgstr "已開始"
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "開始於 (UTC)"
@@ -7695,9 +8988,15 @@ msgstr "暫存您的訊æ¯ä»¥å•Ÿç”¨"
msgid "Status"
msgstr "狀態"
-msgid "Stop environment"
+msgid "Status:"
+msgstr ""
+
+msgid "Stop Terminal"
msgstr ""
+msgid "Stop environment"
+msgstr "åœæ­¢ç’°å¢ƒ"
+
msgid "Stop impersonation"
msgstr "åœæ­¢æ¨¡æ“¬"
@@ -7708,10 +9007,13 @@ msgid "Stopped"
msgstr "å·²åœæ­¢"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr "由於該環境正在部署,所以目å‰ç„¡æ³•åœæ­¢"
+
+msgid "Stopping..."
msgstr ""
msgid "Storage"
-msgstr "儲存"
+msgstr "儲存空間"
msgid "Storage:"
msgstr "儲存空間:"
@@ -7720,16 +9022,19 @@ msgid "Subgroups"
msgstr "å­ç¾¤çµ„"
msgid "Subgroups and projects"
-msgstr ""
+msgstr "å­ç¾¤çµ„和專案"
msgid "Submit as spam"
msgstr "以垃圾訊æ¯æ交"
-msgid "Submit review"
+msgid "Submit feedback"
msgstr ""
+msgid "Submit review"
+msgstr "æ交檢閱"
+
msgid "Submit search"
-msgstr ""
+msgstr "æ交æœå°‹"
msgid "Subscribe"
msgstr "訂閱"
@@ -7740,10 +9045,94 @@ msgstr "訂閱群組"
msgid "Subscribe at project level"
msgstr "訂閱專案"
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
msgid "Subscribed"
+msgstr "已訂閱"
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+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|GitLab.com %{planName} %{suffix}"
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
msgid "Switch branch/tag"
@@ -7753,41 +9142,46 @@ msgid "Sync information"
msgstr "åŒæ­¥è©³ç´°è³‡è¨Š"
msgid "System Hooks"
-msgstr "系統鉤å­"
+msgstr "系統觸發器"
msgid "System Info"
msgstr "系統資訊"
-msgid "System header and footer:"
-msgstr "系統標頭與尾端:"
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
msgid "System metrics (Custom)"
msgstr "系統指標 (自訂)"
msgid "System metrics (Kubernetes)"
+msgstr "系統指標 (Kubernetes)"
+
+msgid "Tag"
msgstr ""
-msgid "Tag (%{tag_count})"
-msgid_plural "Tags (%{tag_count})"
-msgstr[0] "標籤(%{tag_count})"
+msgid "Tag list:"
+msgstr ""
msgid "Tags"
msgstr "標籤"
msgid "Tags feed"
-msgstr ""
+msgstr "標籤動態"
msgid "Tags:"
msgstr "標籤:"
msgid "TagsPage|Browse commits"
-msgstr "ç€è¦½æ›´å‹•"
+msgstr "ç€è¦½æ交記錄"
msgid "TagsPage|Browse files"
msgstr "ç€è¦½æª”案"
msgid "TagsPage|Can't find HEAD commit for this tag"
-msgstr "無法找到此標籤的更動"
+msgstr "找ä¸åˆ°æ­¤æ¨™ç±¤çš„ HEAD æ交"
msgid "TagsPage|Cancel"
msgstr "å–消"
@@ -7799,55 +9193,55 @@ msgid "TagsPage|Delete tag"
msgstr "刪除標籤"
msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
-msgstr "刪除 %{tag_name} 後將無法æ¢å¾©ï¼Œæ‚¨ç¢ºå®šå—Žï¼Ÿ"
+msgstr "刪除 %{tag_name} 後將無法復原,確定?"
msgid "TagsPage|Edit release notes"
msgstr "編輯發佈訊æ¯"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
-msgstr "已存在分支å稱ã€æ¨™ç±¤æˆ–者更動SHA"
+msgstr "已存在分支å稱ã€æ¨™ç±¤æˆ–者æ交 SHA 碼"
msgid "TagsPage|Filter by tag name"
-msgstr "根據標籤å稱塞é¸"
+msgstr "僅篩é¸æ¨™ç±¤å稱"
msgid "TagsPage|New Tag"
-msgstr "新標籤"
+msgstr "新增標籤"
msgid "TagsPage|New tag"
-msgstr "新標籤"
+msgstr "新增標籤"
msgid "TagsPage|Optionally, add a message to the tag."
-msgstr "增加標籤的說明(å¯é¸ï¼‰"
+msgstr "新增標籤æ述(å¯é¸ï¼‰"
msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
-msgstr "增加標籤的發佈說明,這將會被儲存在Gitlab資料庫中,並顯示於標籤é ã€‚(å¯é¸ï¼‰"
+msgstr "新增標籤發佈說明(å¯é¸ï¼‰ï¼Œé€™å°‡å„²å­˜åˆ° GitLab 資料庫並在「標籤ã€é é¢é¡¯ç¤ºã€‚"
msgid "TagsPage|Release notes"
msgstr "發佈說明"
msgid "TagsPage|Repository has no tags yet."
-msgstr "檔案庫還沒有任何標籤。"
+msgstr "版本庫還沒有任何標籤。"
msgid "TagsPage|Sort by"
-msgstr "ä¾ç…§æŽ’åº"
+msgstr "排åºæ–¹å¼"
msgid "TagsPage|Tags"
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|Use git tag command to add a new one:"
-msgstr "使用 git tag 指令增加一個新的標籤:"
+msgstr "使用 git tag 指令增加新標籤:"
msgid "TagsPage|Write your release notes or drag files here…"
-msgstr "撰寫發行說明或拖放文件到這裡⋯"
+msgstr "撰寫發行說明或拖放檔案到這裡⋯"
msgid "TagsPage|protected"
-msgstr "ä¿è­·"
+msgstr "å—ä¿è­·"
msgid "Target Branch"
msgstr "目標分支"
@@ -7859,9 +9253,15 @@ msgid "Team"
msgstr "團隊"
msgid "Template"
-msgstr ""
+msgstr "模æ¿"
msgid "Templates"
+msgstr "模æ¿"
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
msgstr ""
msgid "Terms of Service Agreement and Privacy Policy"
@@ -7871,7 +9271,7 @@ msgid "Terms of Service and Privacy Policy"
msgstr "æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–"
msgid "Test SAML SSO"
-msgstr ""
+msgstr "測試 SAML SSO"
msgid "Test coverage parsing"
msgstr "測試覆蓋率分æž"
@@ -7879,45 +9279,54 @@ msgstr "測試覆蓋率分æž"
msgid "Thanks! Don't show me this again"
msgstr "æ„Ÿè¬ï¼è«‹ä¸è¦å†æ¬¡é¡¯ç¤º"
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
-msgstr "GitLab 的進階全域æœå°‹åŠŸèƒ½æ˜¯éžå¸¸å¼·å¤§çš„æœå°‹æœå‹™ã€‚您å¯ä»¥ç«‹åˆ»æœå°‹å…¶ä»–團隊的代碼以幫助您完善自己項目中的代碼。從而é¿å…建立é‡è¤‡çš„程å¼ç¢¼æµªè²»æ™‚間。"
+msgstr "GitLab 的進階全域æœå°‹åŠŸèƒ½æ˜¯éžå¸¸å¼·å¤§çš„æœå°‹æœå‹™ã€‚您å¯ä»¥ç«‹åˆ»æœå°‹å…¶ä»–團隊的程å¼ç¢¼ä»¥å¹«åŠ©æ‚¨å®Œå–„自己項目中的程å¼ç¢¼ã€‚從而é¿å…建立é‡è¤‡çš„程å¼ç¢¼æµªè²»æ™‚間。"
-msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
msgstr ""
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr "Git LFS 物件將<strong>ä¸æœƒ</strong>åŒæ­¥ã€‚"
+
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 X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "當需è¦ç›¸äº’ TLS 與外部èªè­‰æœå‹™è¯çµ¡æ™‚,所使用的 X509 憑證。如果留白,使用 HTTPS 連線時伺æœå™¨çš„憑證ä»ç„¶ç‚ºã€Œå·²èªè­‰ã€ã€‚"
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 coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
-msgstr "程å¼é–‹ç™¼éšŽæ®µé¡¯ç¤ºå¾žç¬¬ä¸€æ¬¡æ›´å‹•è¨˜éŒ„到建立åˆä½µè«‹æ±‚的時間。建立第一個åˆä½µè«‹æ±‚後,資料將自動填入。"
+msgstr "程å¼é–‹ç™¼éšŽæ®µé¡¯ç¤ºå¾žç¬¬ä¸€æ¬¡æ交記錄到建立åˆä½µè«‹æ±‚的時間。建立第一個åˆä½µè«‹æ±‚後,資料將自動填入。"
msgid "The collection of events added to the data gathered for that stage."
msgstr "該階段中的相關事件集åˆã€‚"
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr "該連線將在 %{timeout} 之後超時。å°æ–¼éœ€è¦ä½¿ç”¨æ›´é•·æ™‚間的版本庫,請使用 clone / push 組åˆã€‚"
+msgstr "該連線將在 %{timeout} 之後逾時。å°æ–¼éœ€è¦ä½¿ç”¨æ›´é•·æ™‚間的版本庫,請使用 clone / push 組åˆã€‚"
msgid "The deployment of this job to %{environmentLink} did not succeed."
-msgstr ""
+msgstr "å° %{environmentLink} 作業的佈署並未æˆåŠŸã€‚"
msgid "The fork relationship has been removed."
msgstr "分支與主幹間的關è¯å·²è¢«åˆªé™¤ã€‚"
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr "匯入將在 %{timeout} 之後超時。å°æ–¼éœ€è¦æ›´é•·æ™‚間的存儲庫,請使用 clone / push 組åˆã€‚"
+msgstr "匯入將在 %{timeout} 之後逾時。å°æ–¼éœ€è¦æ›´é•·æ™‚間的存儲庫,請使用 clone / push 組åˆã€‚"
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "議題階段顯示從議題建立到設定里程碑所花的時間,或是議題被分類到議題看æ¿ä¸­æ‰€èŠ±çš„時間。建立第一個議題後,資料將自動填入。"
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
msgid "The maximum file size allowed is 200KB."
msgstr "最大檔案大å°ç‚º 200KB"
@@ -7925,19 +9334,19 @@ msgid "The passphrase required to decrypt the private key. This is optional and
msgstr "解密ç§é‘°æ‰€éœ€çš„密碼。這是é¸ç”¨ä¸”該值將會被加密儲存。"
msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
-msgstr "CI 設定檔的路徑。默èªç‚º <code>.gitlab-ci.yml</code>"
+msgstr "CI 設定檔的路徑。é è¨­ç‚º <code>.gitlab-ci.yml</code>"
msgid "The phase of the development lifecycle."
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 planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
-msgstr "計劃階段顯示從更動記錄被排程至第一個推é€çš„時間。第一次推é€ä¹‹å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥ã€‚"
+msgstr "計劃階段顯示從æ交記錄被排程至第一個推é€çš„時間。第一次推é€ä¹‹å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥ã€‚"
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr "æ供客戶端憑證時所使用的ç§é‘°ã€‚æ­¤ç§é‘°å°‡æœƒè¢«åŠ å¯†å„²å­˜ã€‚"
+msgstr "æ供使用者端憑證時所使用的ç§é‘°ã€‚æ­¤ç§é‘°å°‡æœƒè¢«åŠ å¯†å„²å­˜ã€‚"
msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr "營é‹éšŽæ®µé¡¯ç¤ºå¾žå»ºç«‹è­°é¡Œåˆ°éƒ¨ç½²ç¨‹å¼ä¸Šç·šæ‰€èŠ±çš„時間。完æˆå¾žç™¼æƒ³åˆ°ä¸Šç·šçš„完整開發週期後,資料將自動填入。"
@@ -7949,22 +9358,22 @@ msgid "The project can be accessed without any authentication."
msgstr "本專案å¯è®“任何人存å–"
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "Pseudonymizer 資料è’集已經åœç”¨ã€‚如果啟用,GitLab 將會執行一個背景作業 -- 其將會產生 GitLab 資料庫的å‡å CSV,使其å¯ä»¥ä¸Šå‚³åˆ°æ‚¨è¨­å®šçš„å°è±¡å„²å­˜ç›®éŒ„。"
+msgstr "Pseudonymizer 資料è’集已經åœç”¨ã€‚如果啟用,GitLab 將會執行一個背景作業 -- 其將會產生 GitLab 資料庫的å‡å CSV,使其å¯ä»¥ä¸Šå‚³åˆ°æ‚¨è¨­å®šçš„物件儲存資料夾。"
msgid "The repository for this project does not exist."
-msgstr "本專案沒有檔案庫"
+msgstr "本專案沒有版本庫"
msgid "The repository for this project is empty"
-msgstr "這個專案的檔案庫是空的"
+msgstr "這個專案的版本庫是空的"
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
-msgstr "該存儲庫必須å¯é€šéŽ <code>http://</code>, <code>https://</code> 或 <code>git://</code>訪å•ã€‚"
+msgstr "該存儲庫必須å¯é€éŽ <code>http://</code>, <code>https://</code> 或 <code>git://</code>訪å•ã€‚"
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
-msgstr ""
+msgstr "版本庫必須能以 <code>http://</code>ã€<code>https://</code>ã€<code>ssh://</code> å’Œ <code>git://</code> 通訊å”定存å–。"
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
-msgstr "複閱階段顯示從åˆä½µè«‹æ±‚建立後至被åˆä½µçš„時間。當建立第一個åˆä½µè«‹æ±‚後,資料將自動填入。"
+msgstr "檢閱階段顯示從åˆä½µè«‹æ±‚建立後至被åˆä½µçš„時間。當建立第一個åˆä½µè«‹æ±‚後,資料將自動填入。"
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "開發è—圖顯示了時間軸上您的 Epic 的進度"
@@ -7973,30 +9382,42 @@ msgid "The staging stage shows the time between merging the MR and deploying cod
msgstr "試營é‹æ®µé¡¯ç¤ºå¾žåˆä½µè«‹æ±‚被åˆä½µå¾Œè‡³éƒ¨ç½²ç‡Ÿé‹çš„時間。當第一次部署營é‹å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥"
msgid "The tabs below will be removed in a future version"
-msgstr ""
+msgstr "底下的分é å°‡æœƒåœ¨æœªä¾†ç‰ˆæœ¬ä¸­ç§»é™¤"
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
-msgstr "測試階段顯示相關åˆä½µè«‹æ±‚çš„æµæ°´ç·šæ‰€èŠ±çš„時間。當第一個æµæ°´ç·šåŸ·è¡Œå®Œç•¢å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥ã€‚"
+msgstr "測試階段顯示相關åˆä½µè«‹æ±‚的管線所花的時間。當第一個管線執行完畢後,資料將自動填入。"
msgid "The time taken by each data entry gathered by that stage."
msgstr "該階段中æ¯ä¸€å€‹è³‡æ–™é …目所花的時間。"
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr ""
+msgstr "更新動作將會在 %{number_of_minutes} 分é˜å¾Œé€¾æ™‚。å°æ–¼å¤§åž‹ç‰ˆæœ¬åº«ï¼Œè«‹ä½¿ç”¨ clone/push 組åˆã€‚"
msgid "The usage ping is disabled, and cannot be configured through this form."
-msgstr ""
+msgstr "å·²åœç”¨ä½¿ç”¨æƒ…æ³ Ping 功能,且無法é€éŽæ­¤è¡¨å–®è¨­å®šã€‚"
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
-msgstr ""
+msgstr "å°æ‡‰ä½¿ç”¨è€…是一個JSON檔,是將åƒèˆ‡å°ˆæ¡ˆçš„ Google Code 使用者å°æ‡‰åˆ°ä»–們的電å­éƒµä»¶å’Œä½¿ç”¨è€…å稱並匯入GitLab çš„æ–¹å¼ã€‚您å¯ä»¥é€éŽè®Šæ›´ <code>:</code>å³å´çš„值來變更此å°æ‡‰ã€‚請務必在左å´ä¿ç•™å‘¨åœçš„雙引號ã€å…¶ä»–標點符號以åŠé›»å­éƒµä»¶ä½å€æˆ–使用者å稱。"
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
-msgstr ""
+msgstr "使用者å°æ‡‰æ˜¯å°‡åƒèˆ‡å°ˆæ¡ˆçš„ FogBugz 使用者與其電å­éƒµä»¶å’Œä½¿ç”¨è€…å稱匯入 GitLab çš„æ–¹å¼ã€‚您å¯ä»¥é€éŽå¡«å¯«ä¸‹æ–¹çš„表單來變更此設定。"
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•¸æ˜¯ä¸€å€‹æ•¸åˆ—中最中間的值。例如在 3ã€5ã€9 之間,中ä½æ•¸æ˜¯ 5。在 3ã€5ã€7ã€8 之間,中ä½æ•¸æ˜¯ (5 + 7)/ 2 = 6。"
+msgid "There are no approvers"
+msgstr ""
+
msgid "There are no archived projects yet"
+msgstr "此處沒有已å°å­˜å°ˆæ¡ˆ"
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
msgstr ""
msgid "There are no issues to show"
@@ -8005,35 +9426,41 @@ msgstr "沒有å¯ä»¥é¡¯ç¤ºçš„è­°é¡Œ"
msgid "There are no labels yet"
msgstr "ç›®å‰é‚„沒有標籤"
-msgid "There are no merge requests to show"
-msgstr "沒有任何的åˆä½µè«‹æ±‚"
+msgid "There are no open issues"
+msgstr ""
-msgid "There are no projects shared with this group yet"
+msgid "There are no open merge requests"
msgstr ""
-msgid "There are no staged changes"
+msgid "There are no packages yet"
msgstr ""
+msgid "There are no projects shared with this group yet"
+msgstr "此處沒有與此群組分享的專案"
+
+msgid "There are no staged changes"
+msgstr "此處沒有暫存的變更"
+
msgid "There are no unstaged changes"
-msgstr ""
+msgstr "此處沒有未暫存的變更"
msgid "There was an error adding a todo."
-msgstr ""
+msgstr "加入待辦事項時出錯。"
msgid "There was an error deleting the todo."
-msgstr ""
+msgstr "刪除待辦事項時出錯。"
msgid "There was an error loading users activity calendar."
msgstr "讀å–使用者行事曆活動時發生錯誤"
msgid "There was an error saving your notification settings."
-msgstr "ä¿å­˜æ‚¨çš„通知設置時發生錯誤。"
+msgstr "儲存您的通知設定時發生錯誤。"
msgid "There was an error subscribing to this label."
msgstr "訂閱此標籤時發生錯誤。"
msgid "There was an error when reseting email token."
-msgstr "é‡ç½®é›»å­éƒµä»¶æ†‘證時發生錯誤。"
+msgstr "é‡è¨­é›»å­éƒµä»¶æ†‘證時發生錯誤。"
msgid "There was an error when subscribing to this label."
msgstr "訂閱此標籤時出ç¾éŒ¯èª¤ã€‚"
@@ -8041,48 +9468,60 @@ msgstr "訂閱此標籤時出ç¾éŒ¯èª¤ã€‚"
msgid "There was an error when unsubscribing from this label."
msgstr "å–消訂閱此標籤時出ç¾éŒ¯èª¤ã€‚"
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr "å…¶å¯ä»¥ä½¿ç”¨ %{link} 進行管ç†ã€‚"
msgid "Third party offers"
msgstr "第三方æä¾›"
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "æ­¤ GitLab 實例ä¸æ供任何分享的執行器。實例管ç†å“¡å¯ä»¥åœ¨ç®¡ç†å“¡å€åŸŸè¨»å†Šåˆ†äº«çš„執行器。"
msgid "This application was created by %{link_to_owner}."
-msgstr ""
+msgstr "這個應用程å¼æ˜¯ç”± %{link_to_owner} 建立的。"
msgid "This application will be able to:"
-msgstr ""
+msgstr "此應用程å¼å°‡å¯ä»¥ï¼š"
msgid "This board's scope is reduced"
msgstr "已縮å°æ­¤çœ‹æ¿ç¯„åœ"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
-msgstr ""
+msgstr "自上次編輯以來此分支已經變更éŽã€‚是å¦å»ºç«‹æ–°åˆ†æ”¯ï¼Ÿ"
msgid "This container registry has been scheduled for deletion."
-msgstr ""
+msgstr "此容器登入表已經排定刪除。"
msgid "This date is after the due date, so this epic won't appear in the roadmap."
-msgstr ""
+msgstr "此日期晚於çµæŸæ—¥æœŸï¼Œå› æ­¤é€™å€‹ Epic å°‡ä¸æœƒåœ¨é–‹ç™¼è—圖中顯示。"
msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr ""
+msgstr "此日期早於開始日期,因此這個 Epic å°‡ä¸æœƒåœ¨é–‹ç™¼è—圖中顯示。"
msgid "This diff is collapsed."
msgstr "此差異已折疊。"
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
-msgstr "這個目錄"
+msgstr "這個資料夾"
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
msgid "This group"
msgstr "此群組"
-msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr "此群組å…許您以您的 %{group_name} 單一登入帳號登入。這將會é‡æ–°å°Žå‘您到外部登入é é¢ã€‚"
-
msgid "This group does not provide any group Runners yet."
msgstr "這群組尚未æ供任何群組執行器。"
@@ -8090,7 +9529,7 @@ msgid "This is a confidential issue."
msgstr "這是個隱密å•é¡Œã€‚"
msgid "This is a delayed job to run in %{remainingTime}"
-msgstr ""
+msgstr "這這是一個延é²æ€§çš„工作,將在 %{remainingTime} 後執行"
msgid "This is the author's first Merge Request to this project."
msgstr "這是作者第一次åˆä½µè«‹æ±‚至本專案。"
@@ -8105,7 +9544,7 @@ msgid "This issue is locked."
msgstr "這個å•é¡Œå·²è¢«éŽ–定。"
msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
-msgstr "這項任務將由使用者觸發,這通常用於部署應用程å¼åˆ°æ­£å¼ç’°å¢ƒ"
+msgstr "這項作業將由使用者觸發,這通常用於部署應用程å¼åˆ°æ­£å¼ç’°å¢ƒ"
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
msgstr "這項工作需è¦ä¸Šä¸€å€‹å·¥ä½œæˆåŠŸæ™‚æ‰èƒ½è§¸ç™¼åŸ·è¡Œå·¥ä½œ"
@@ -8120,62 +9559,71 @@ msgid "This job has been skipped"
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}."
-msgstr ""
+msgstr "這個工作已經逾時,無法部署到 %{environmentLink}。"
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{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} and will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "這個工作將部署到 %{environmentLink} 並將覆蓋既有的部署 %{deploymentLink}。"
msgid "This job is creating a deployment to %{environmentLink}."
-msgstr ""
+msgstr "這個工作正在部署到 %{environmentLink}。"
msgid "This job is in pending state and is waiting to be picked by a runner"
-msgstr "這份任務ä½æ–¼ç­‰å¾…狀態,等待 Runner 來執行"
+msgstr "這份作業ä½æ–¼ç­‰å¾…狀態,等待執行器來執行"
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
-msgstr ""
+msgstr "這個工作最近部署到 %{link}。"
msgid "This job requires a manual action"
-msgstr "這份任務需è¦æ‰‹å‹•åŸ·è¡Œ"
+msgstr "這份作業需è¦æ‰‹å‹•åŸ·è¡Œ"
-msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
-msgstr "這代表在您建立一個空的檔案庫或是匯入一個ç¾å­˜çš„檔案庫之å‰ï¼Œæ‚¨å°‡ç„¡æ³•ä¸Šå‚³æ›´æ–°ã€‚"
+msgstr "這代表在您建立一個空的版本庫或是匯入一個ç¾å­˜çš„版本庫之å‰ï¼Œæ‚¨å°‡ç„¡æ³•ä¸Šå‚³æ›´æ–°ã€‚"
msgid "This merge request is locked."
msgstr "這個åˆä½µè«‹æ±‚已被鎖定。"
msgid "This option is disabled as you don't have write permissions for the current branch"
-msgstr ""
+msgstr "由於您沒有此分支的寫入權é™ï¼Œå› æ­¤ç¦ç”¨æ­¤é¸é …。"
msgid "This option is disabled while you still have unstaged changes"
msgstr "當您ä»æ“有未暫存的變更時,此é¸é …將會是åœç”¨çš„"
msgid "This page is unavailable because you are not allowed to read information across multiple projects."
-msgstr "æ­¤é é¢ä¸å¯ç”¨ï¼Œå› ç‚ºæ‚¨ä¸å…許跨多個專案閱讀信æ¯ã€‚"
+msgstr "æ­¤é é¢ä¸å¯ç”¨ï¼Œå› ç‚ºæ‚¨ä¸å…許跨多個專案閱讀訊æ¯ã€‚"
msgid "This page will be removed in a future release."
msgstr "æ­¤é é¢å°‡æœƒåœ¨æœªä¾†ç‰ˆæœ¬ä¸­ç§»é™¤ã€‚"
+msgid "This pipeline is run in a merge request context"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
+msgstr ""
+
msgid "This project"
msgstr "這個專案"
@@ -8183,40 +9631,40 @@ msgid "This project does not belong to a group and can therefore not make use of
msgstr "此專案ä¸å±¬æ–¼ä¸€å€‹ç¾¤çµ„,因此ä¸èƒ½ä½¿ç”¨ç¾¤çµ„執行器。"
msgid "This project does not have a wiki homepage yet"
-msgstr ""
+msgstr "此專案還沒有維基首é "
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
+msgstr "此專案未啟用帳單。如果è¦å»ºç«‹ç¾¤é›†ï¼Œè«‹ <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\"> 啟用帳單 <i class=\"fa fa-external-link\" aria-hidden=\"true\"> 並é‡æ–°å»ºç«‹ç¾¤é›†ã€‚"
msgid "This repository"
-msgstr "這個檔案庫"
+msgstr "這個版本庫"
msgid "This runner will only run on pipelines triggered on protected branches"
-msgstr ""
+msgstr "此執行器將åªåŸ·è¡Œè¢«ä¿è­·çš„分支所觸發的管線"
msgid "This setting can be overridden in each project."
-msgstr ""
+msgstr "ç›®å‰è¨­å®šå¯ä»¥åœ¨æ¯å€‹å°ˆæ¡ˆä¸­é€²è¡Œè¤‡å¯«ã€‚"
msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
-msgstr ""
+msgstr "此設定將更新你用來產生ç§äººæ交æ交的電å­éƒµä»¶çš„主機域å。%{learn_more}"
msgid "This source diff could not be displayed because it is too large."
msgstr "此原始碼差異無法顯示,因為它太大。"
-msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
msgstr ""
msgid "This user has no identities"
msgstr "該使用者沒有身份"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
-msgstr ""
+msgstr "此使用者將æˆç‚ºæ´»å‹•æ‘˜è¦ä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如建立新分支或推é€æ交到ç¾æœ‰åˆ†æ”¯ã€‚"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
-msgstr ""
+msgstr "此使用者將æˆç‚ºæ´»å‹•æ‘˜è¦ä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如建立新分支或推é€æ交到ç¾æœ‰åˆ†æ”¯ã€‚在建立或é‡æ–°æŒ‡å®šæ™‚您åªå¯ä»¥å°‡è‡ªå·±æŒ‡å®šç‚ºé¡åƒä½¿ç”¨è€…。"
-msgid "This will delete the custom metric, Are you sure?"
-msgstr "這會刪除自訂指標資料,你確定嗎?"
+msgid "This will redirect you to an external sign in page."
+msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "這裡列出了那些自動æˆç‚ºè­°é¡Œçš„é›»å­éƒµä»¶ï¼ˆå¾žç•™è¨€è®Šæˆçš„é›»å­éƒµä»¶å°è©±ï¼‰"
@@ -8228,13 +9676,13 @@ msgid "Time before an issue starts implementation"
msgstr "議題等待開始實作的時間"
msgid "Time before enforced"
-msgstr ""
+msgstr "強制目å‰æ™‚é–“"
msgid "Time between merge request creation and merge/close"
msgstr "åˆä½µè«‹æ±‚從建立到被åˆä½µæˆ–是關閉的時間"
msgid "Time estimate"
-msgstr ""
+msgstr "é è¨ˆæ™‚é–“"
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "GitLab 等待外部æœå‹™çš„回應時間(秒)。當æœå‹™æ²’有在時間內回應時,存å–將被拒絕。"
@@ -8406,58 +9854,82 @@ msgstr "æ示:"
msgid "Title"
msgstr "標題"
+msgid "Titles and Filenames"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
msgid "To GitLab"
msgstr "到 GitLab"
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr "è¦æ·»åŠ SSHå¯†é‘°ï¼Œä½ éœ€è¦ %{generate_link_start}產生一個%{link_end} 或使用 %{existing_link_start}ç¾æœ‰çš„密鑰%{link_end}。"
+msgstr "è¦æ–°å¢žSSHå¯†é‘°ï¼Œä½ éœ€è¦ %{generate_link_start}產生一個%{link_end} 或使用 %{existing_link_start}ç¾æœ‰çš„密鑰%{link_end}。"
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>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr "è‹¥è¦é€£ç·šåˆ° GitHub 版本庫,您å¯ä»¥ä½¿ç”¨ %{personal_access_token_link} 連çµã€‚當您建立了您的個人存å–憑證,您將需è¦é¸æ“‡ <code>版本庫</code> 範åœï¼Œæ‰€ä»¥æˆ‘們å¯ä»¥é¡¯ç¤ºæ‚¨å¯ä¾›é€£ç·šçš„公開與ç§å¯†ç‰ˆæœ¬åº«åˆ—表。"
+msgstr "è‹¥è¦é€£ç·šåˆ° GitHub 版本庫,您å¯ä»¥ä½¿ç”¨ %{personal_access_token_link} 連çµã€‚當您建立了您的個人存å–憑證,您將需è¦é¸æ“‡ <code>版本庫</code> 範åœï¼Œæ‰€ä»¥æˆ‘們å¯ä»¥é¡¯ç¤ºæ‚¨å¯ä¾›é€£ç·šçš„公開與ç§äººç‰ˆæœ¬åº«åˆ—表。"
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr "è¦é€£æŽ¥ GitHub 版本庫,您首先需è¦æŽˆæ¬Š GitLab å­˜å–您的 GitHub 版本庫列表:"
+msgstr "è¦é€£ç·š GitHub 版本庫,您首先需è¦æŽˆæ¬Š GitLab å­˜å–您的 GitHub 版本庫列表:"
msgid "To connect an SVN repository, check out %{svn_link}."
-msgstr "è‹¥è¦é€£æŽ¥åˆ°ä¸€å€‹ SVN 版本庫,請åƒé–± %{svn_link}。"
+msgstr "è‹¥è¦é€£ç·šåˆ°ä¸€å€‹ SVN 版本庫,請åƒé–± %{svn_link}。"
msgid "To define internal users, first enable new users set to external"
-msgstr ""
+msgstr "è¦å®šç¾©å…§éƒ¨ä½¿ç”¨è€…,請先啟用將新使用者設定為外部使用者"
msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
+msgstr "如è¦å•Ÿç”¨ä¸¦æª¢è¦–使用者世代,請到%{application_settings_link_start}應用程å¼è¨­å®š%{application_settings_link_end}。"
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 網å€å’Œç™»å…¥è³‡è¨Šã€‚在接下來的步驟中,您將能夠å°æ‡‰ä½¿ç”¨è€…並é¸æ“‡è¦åŒ¯å…¥çš„專案。"
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
+msgstr "首先請先將本é é¢èˆ‡æ‚¨çš„ Jaeger 伺æœå™¨é€£ç·šï¼Œæˆ–者了解一下如何%{link_start_tag}å®‰è£ Jaeger%{link_end_tag}"
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
-msgstr ""
+msgstr "è¦é–‹å§‹ä½¿ç”¨ï¼Œè«‹è¼¸å…¥æ‚¨çš„ Gitea 主機網å€å’Œ %{link_to_personal_token}。"
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
-msgstr ""
+msgstr "為了幫助改進 GitLab åŠå…¶ä½¿ç”¨è€…體驗,GitLab 將定期收集使用者資訊。"
msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
-msgstr ""
+msgstr "為了幫助改進 GitLab åŠå…¶ä½¿ç”¨è€…體驗,我們希望定期收集使用者資訊。這å¯ä»¥åœ¨%{settings_link_start}設定%{link_end}隨時變更。%{info_link_start}更多資訊%{link_end}"
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
-msgstr "è¦åŒ¯å…¥ GitHub 存儲庫,你å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。當你建立你的個人存å–權æ–時,你將需è¦é¸æ“‡<code>檔案庫</code>範åœï¼Œæ‰€ä»¥æˆ‘們將會顯示你公開åŠç§äººçš„檔案庫清單進行匯入。"
+msgstr "è¦åŒ¯å…¥ GitHub 存儲庫,你å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。當你建立你的個人存å–憑證時,你將需è¦é¸æ“‡<code>版本庫</code>範åœï¼Œæ‰€ä»¥æˆ‘們將會顯示你公開åŠç§äººçš„版本庫清單進行匯入。"
msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
msgstr "è¦åŒ¯å…¥ GitHub 存儲庫,您首先需è¦æŽˆæ¬Š GitLab 訪å•æ‚¨çš„ GitHub 存儲庫列表:"
msgid "To import an SVN repository, check out %{svn_link}."
-msgstr "è¦åŒ¯å…¥SVN存儲庫,請查看 %{svn_link}。"
+msgstr "è¦åŒ¯å…¥SVN存儲庫,請檢視 %{svn_link}。"
-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."
+msgid "To keep this project going, create a new issue"
msgstr ""
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr "è¦å°‡æ•´å€‹ GitLab 專案從å¦ä¸€å€‹ GitLab 上移動或複製到此專案,請至原始專案的設定é é¢ï¼ŒåŒ¯å‡ºæª”案,然後在此處上傳。"
+
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
-msgstr "è‹¥è¦åªå°å¤–部版本庫使用 CI / CD 功能,請é¸æ“‡ <strong>為外部版本庫的 CI/CD</strong>"
+msgstr "è‹¥è¦åªå°å¤–部版本庫使用 CI / CD 功能,請é¸æ“‡ <strong>為外部版本庫的 CI / CD</strong>"
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
@@ -8466,20 +9938,26 @@ msgstr "è‹¥è¦é€éŽèº«ä»½æ供者(例如 Azureã€Oktaã€Oneloginã€Ping Iden
msgid "To start serving your jobs you can add Runners to your group"
msgstr "è‹¥è¦é–‹å§‹æ供您的工作,您å¯ä»¥å¢žåŠ åŸ·è¡Œå™¨è‡³é€™å€‹ç¾¤çµ„"
-msgid "To this GitLab instance"
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
msgstr ""
+msgid "To this GitLab instance"
+msgstr "至此 GitLab 實例"
+
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
-msgstr "è‹¥è¦é©—證您的 GitLab CI 設定,請å‰å¾€æ‚¨å°ˆæ¡ˆå…§çš„「CI/CD → æµæ°´ç·šã€ï¼Œä¸¦æŒ‰ä¸‹ã€ŒCI Lintã€æŒ‰éˆ•ã€‚"
+msgstr "è‹¥è¦é©—證您的 GitLab CI 設定,請å‰å¾€æ‚¨å°ˆæ¡ˆå…§çš„「CI / CD → 管線ã€ï¼Œä¸¦æŒ‰ä¸‹ã€ŒCI Lintã€æŒ‰éˆ•ã€‚"
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr "如果è¦æª¢è¦–計畫è—圖,請將此群組或其å­ç¾¤çµ„中的æŸå€‹ epics 設定開始或çµæŸæ™‚間。在æ¯æœˆè¨ˆç•«è—圖中,åªé¡¯ç¤ºä¸Šå€‹æœˆã€æœ¬æœˆåŠæŽ¥ä¸‹ä¾†äº”個月的 epic。"
+
+msgid "To widen your search, change or remove filters above"
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr "è‹¥è¦æ“´å¤§æœå°‹ç¯„åœï¼Œè«‹è®Šæ›´æˆ–移除篩é¸å™¨ã€‚"
msgid "Today"
-msgstr ""
+msgstr "今天"
msgid "Todo"
msgstr "待辦事項"
@@ -8490,15 +9968,18 @@ msgstr "待辦事項"
msgid "Toggle Sidebar"
msgstr "展開 / 收起å´é‚Šæ¬„"
+msgid "Toggle comments for this file"
+msgstr ""
+
msgid "Toggle commit description"
+msgstr "切æ›æ交說明"
+
+msgid "Toggle commit list"
msgstr ""
msgid "Toggle discussion"
msgstr "切æ›è¨Žè«–"
-msgid "Toggle file browser"
-msgstr ""
-
msgid "Toggle navigation"
msgstr "切æ›å°Žèˆªæ¬„"
@@ -8512,13 +9993,13 @@ msgid "ToggleButton|Toggle Status: ON"
msgstr "切æ›ç‹€æ…‹ï¼šé–‹å•Ÿ"
msgid "Token"
-msgstr ""
+msgstr "憑證"
msgid "Tomorrow"
-msgstr ""
+msgstr "明天"
msgid "Too many changes to show."
-msgstr "太多的更改。"
+msgstr "太多的變更。"
msgid "Total Contributions"
msgstr "總計貢ç»"
@@ -8527,13 +10008,13 @@ msgid "Total Time"
msgstr "總時間"
msgid "Total test time for all commits/merges"
-msgstr "åˆä½µ/更動記錄的總測試時間"
+msgstr "åˆä½µ/æ交記錄的總測試時間"
msgid "Total: %{total}"
msgstr "總計: %{total}"
msgid "Tracing"
-msgstr ""
+msgstr "追蹤"
msgid "Track activity with Contribution Analytics."
msgstr "追蹤貢ç»åˆ†æžçš„相關動態"
@@ -8545,33 +10026,42 @@ msgid "Track time with quick actions"
msgstr "快速使用時間追蹤工具"
msgid "Tree view"
-msgstr ""
+msgstr "樹狀顯示"
msgid "Trending"
msgstr "趨勢分æž"
-msgid "Trigger"
-msgstr ""
-
msgid "Trigger pipelines for mirror updates"
-msgstr ""
+msgstr "觸發é¡åƒæ›´æ–°çš„管線"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
-msgstr ""
+msgstr "從上游版本庫更新分支或標記時觸發管線。如果上游版本庫更新頻ç¹ï¼Œé€™å¯èƒ½æœƒå¤§å¤§å¢žåŠ CI執行器的負擔。如果è¦å•Ÿç”¨æ­¤åŠŸèƒ½ï¼Œè«‹å…ˆç¢ºä¿æ‚¨çš„CI執行器處ç†èƒ½åŠ›èƒ½å¤ æ‰¿å—這樣的負擔。"
msgid "Trigger this manual action"
-msgstr "啟動此任務"
+msgstr "啟動此作業"
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
-msgstr "觸發器å¯ä»¥å¼·åˆ¶ä½¿ç”¨API​​調用é‡å»ºç‰¹å®šçš„分支或標記。這些令牌將模仿他們的關è¯ç”¨æˆ¶ï¼ŒåŒ…括他們å°é …目的訪å•æ¬Šé™ã€‚"
+msgstr "觸發器å¯ä»¥å¼·åˆ¶ä½¿ç”¨API​​呼å«é‡å»ºç‰¹å®šçš„分支或標記。這些令牌將模仿他們的關è¯ä½¿ç”¨è€…,包括他們å°é …目的訪å•æ¬Šé™ã€‚"
msgid "Troubleshoot and monitor your application with tracing"
-msgstr ""
+msgstr "é€éŽè¿½è¹¤å°æ‡‰ç”¨ç¨‹å¼é€²è¡Œæ•…障排除和監控"
msgid "Try again"
msgstr "é‡è©¦"
+msgid "Try again?"
+msgstr ""
+
msgid "Try all GitLab has to offer for 30 days."
+msgstr "試用 GitLab 的所有功能 30 天。"
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
msgid "Turn on Service Desk"
@@ -8581,24 +10071,30 @@ msgid "Twitter"
msgstr "Twitter"
msgid "Two-factor authentication"
-msgstr ""
+msgstr "兩步驟驗證"
msgid "Type"
+msgstr "é¡žåž‹"
+
+msgid "URL"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr "無法載入差異。%{button_try_again}"
-msgid "Unable to save your changes"
-msgstr ""
-
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "因為「%{reason}ã€ï¼Œæ‰€ä»¥ç„¡æ³•è®“ä½ é€éŽ SAML 登入這個群組。"
msgid "Unable to update this epic at this time."
+msgstr "ç›®å‰ç„¡æ³•æ›´æ–°æ­¤ epic。"
+
+msgid "Unblock"
msgstr ""
msgid "Undo"
+msgstr "復原"
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
msgid "Unknown"
@@ -8608,7 +10104,7 @@ msgid "Unlock"
msgstr "解鎖"
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr ""
+msgstr "解鎖這個%{issuableDisplayName}?<strong>所有人</strong>都å¯ä»¥ç™¼è¡¨ç•™è¨€ã€‚"
msgid "Unlocked"
msgstr "已解鎖"
@@ -8617,10 +10113,10 @@ msgid "Unresolve discussion"
msgstr "é‡æ–°è¨Žè«–"
msgid "Unschedule job"
-msgstr ""
+msgstr "未排定工作"
msgid "Unstage"
-msgstr ""
+msgstr "å–消暫存"
msgid "Unstage all changes"
msgstr "å–消暫存所有變更"
@@ -8649,6 +10145,9 @@ msgstr "解除群組訂閱"
msgid "Unsubscribe at project level"
msgstr "解除專案訂閱"
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
msgid "Unverified"
msgstr "未驗證"
@@ -8656,22 +10155,28 @@ msgid "Up to date"
msgstr "已經是最新"
msgid "Upcoming"
-msgstr ""
+msgstr "å³å°‡é–‹å§‹"
msgid "Update"
msgstr "æ›´æ–°"
-msgid "Update now"
+msgid "Update failed"
msgstr ""
+msgid "Update now"
+msgstr "ç«‹å³æ›´æ–°"
+
msgid "Update your group name, description, avatar, and visibility."
-msgstr ""
+msgstr "更新你的群組å稱ã€èªªæ˜Žã€é ­åƒåŠå¯è¦‹æ€§ã€‚"
msgid "Updating"
+msgstr "更新中"
+
+msgid "Upgrade plan to unlock Canary Deployments feature"
msgstr ""
msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "å‡ç´šæ‚¨çš„方案以啟用進階全局æœå°‹ã€‚"
+msgstr "å‡ç´šæ‚¨çš„方案以啟用進階全域æœå°‹ã€‚"
msgid "Upgrade your plan to activate Contribution Analytics."
msgstr "å‡ç´šæ‚¨çš„方案以啟用貢ç»åˆ†æžã€‚"
@@ -8686,28 +10191,43 @@ msgid "Upgrade your plan to improve Issue boards."
msgstr "å‡ç´šæ‚¨çš„方案以改善議題看æ¿ã€‚"
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr "在這裡上傳 <code>GoogleCodeProjectHosting.json</code>:"
+
+msgid "Upload CSV file"
msgstr ""
msgid "Upload New File"
msgstr "上傳新檔案"
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
msgid "Upload file"
msgstr "上傳檔案"
+msgid "Upload object map"
+msgstr ""
+
msgid "UploadLink|click to upload"
-msgstr "點擊上傳"
+msgstr "點é¸ä¸Šå‚³"
+
+msgid "Upstream"
+msgstr ""
msgid "Upvotes"
-msgstr "讚"
+msgstr "è´Š"
msgid "Usage ping is not enabled"
-msgstr ""
+msgstr "使用情æ³åµæ¸¬æœªå•Ÿå‹•"
msgid "Usage statistics"
msgstr "使用情形統計資料"
msgid "Use <code>%{native_redirect_uri}</code> for local tests"
-msgstr ""
+msgstr "使用 <code>%{native_redirect_uri}</code> 進行本機測試"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "使用æœå‹™å°åœ¨ GitLab 內部é€éŽé›»å­éƒµä»¶èˆ‡ä½¿ç”¨è€…è¯çµ¡ (例如æ供客戶æœå‹™)"
@@ -8719,7 +10239,7 @@ msgid "Use one line per URI"
msgstr "æ¯å€‹ URL 使用一行"
msgid "Use template"
-msgstr ""
+msgstr "使用模æ¿"
msgid "Use the following registration token during setup:"
msgstr "在安è£éŽç¨‹ä¸­ä½¿ç”¨æ­¤è¨»å†Šæ†‘è­‰:"
@@ -8727,12 +10247,18 @@ msgstr "在安è£éŽç¨‹ä¸­ä½¿ç”¨æ­¤è¨»å†Šæ†‘è­‰:"
msgid "Use your global notification setting"
msgstr "使用全域通知設定"
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "用來讓æˆå“¡ç™»å…¥æ‚¨åœ¨ GitLab 的群組"
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgid "Used to help configure your identity provider"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr "使用者群組åªåœ¨å•Ÿç”¨ %{usage_ping_link_start} 使用情æ³åµæ¸¬ %{usage_ping_link_end} 時顯示。"
+
msgid "User Settings"
msgstr "使用者設定"
@@ -8740,89 +10266,137 @@ msgid "User and IP Rate Limits"
msgstr "使用者與 IP 速率é™åˆ¶"
msgid "User map"
-msgstr ""
+msgstr "使用者地圖"
msgid "UserProfile|Activity"
-msgstr ""
+msgstr "活動"
msgid "UserProfile|Already reported for abuse"
-msgstr ""
+msgstr "已回報濫用"
msgid "UserProfile|Contributed projects"
-msgstr ""
+msgstr "è²¢ç»çš„專案"
msgid "UserProfile|Edit profile"
+msgstr "編輯個人資料"
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr ""
msgid "UserProfile|Groups"
+msgstr "群組"
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
msgstr ""
msgid "UserProfile|Most Recent Activity"
+msgstr "最新活動"
+
+msgid "UserProfile|No snippets found."
msgstr ""
msgid "UserProfile|Overview"
-msgstr ""
+msgstr "概述"
msgid "UserProfile|Personal projects"
-msgstr ""
-
-msgid "UserProfile|Recent contributions"
-msgstr ""
+msgstr "個人專案"
msgid "UserProfile|Report abuse"
-msgstr ""
+msgstr "回報濫用行為"
msgid "UserProfile|Snippets"
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
msgstr ""
msgid "UserProfile|Subscribe"
+msgstr "訂閱"
+
+msgid "UserProfile|This user doesn't have any personal projects"
msgstr ""
msgid "UserProfile|This user has a private profile"
+msgstr "此使用者具有ç§äººæª”案"
+
+msgid "UserProfile|This user hasn't contributed to any projects"
msgstr ""
msgid "UserProfile|View all"
-msgstr ""
+msgstr "檢視全部"
msgid "UserProfile|View user in admin area"
+msgstr "在管ç†å€åŸŸä¸­æª¢è¦–使用者"
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
msgid "Users"
msgstr "使用者"
-msgid "Variables"
-msgstr "變數"
+msgid "Users requesting access to"
+msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr "變數通éŽé‹è¡Œå™¨æ‡‰ç”¨æ–¼ç’°å¢ƒã€‚å—ä¿è­·çš„變數將åªæ‡‰ç”¨æ–¼å—ä¿è­·çš„分支或標籤。你å¯ä»¥ç”¨æ–¼å„²å­˜å¯†ç¢¼ï¼Œå¯†é‘°æˆ–任何你想è¦çš„變數。"
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Value"
+msgstr ""
msgid "Various container registry settings."
-msgstr "å„種容器的登錄表設定。"
+msgstr "å„種容器的登入表設定。"
msgid "Various email settings."
msgstr "å„種電å­ä¿¡ç®±è¨­å®šã€‚"
+msgid "Various localization settings."
+msgstr ""
+
msgid "Various settings that affect GitLab performance."
msgstr "å„種會影響 GitLab 效能的設定。"
msgid "Verification information"
msgstr "èªè­‰è³‡è¨Š"
+msgid "Verification status"
+msgstr ""
+
msgid "Verified"
msgstr "已驗證"
msgid "Version"
-msgstr ""
+msgstr "版本"
msgid "View %{alerts}"
-msgstr ""
+msgstr "檢視 %{alerts}"
msgid "View app"
+msgstr "檢視應用程å¼"
+
+msgid "View deployment"
msgstr ""
-msgid "View documentation"
+msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr "檢視檔案"
+
msgid "View epics list"
msgstr "檢視 Epic 列表"
@@ -8830,7 +10404,7 @@ msgid "View file @ "
msgstr "ç€è¦½æª”案 @ "
msgid "View group labels"
-msgstr "查看群組標籤"
+msgstr "檢視群組標籤"
msgid "View issue"
msgstr "檢視議題"
@@ -8839,43 +10413,46 @@ msgid "View it on GitLab"
msgstr "在 GitLab 上檢視"
msgid "View jobs"
-msgstr "查看工作"
+msgstr "檢視工作"
msgid "View labels"
msgstr "顯示標籤"
msgid "View log"
-msgstr "查看日誌"
+msgstr "檢視記錄"
msgid "View open merge request"
-msgstr "查看此分支的åˆä½µè«‹æ±‚"
+msgstr "檢視此分支的åˆä½µè«‹æ±‚"
msgid "View project labels"
-msgstr "查看專案標籤"
+msgstr "檢視專案標籤"
msgid "View replaced file @ "
-msgstr "ç€è¦½å·²æ›¿æ›æª”案 @ "
+msgstr "ç€è¦½å·²å–代檔案 @ "
msgid "View the documentation"
+msgstr "檢視檔案"
+
+msgid "Viewing commit"
msgstr ""
msgid "Visibility and access controls"
msgstr "å¯è¦‹æ€§èˆ‡å­˜å–控制"
msgid "Visibility level"
-msgstr ""
+msgstr "å¯è¦–級別"
msgid "Visibility level:"
-msgstr ""
+msgstr "å¯è¦‹ç­‰ç´šï¼š"
msgid "Visibility:"
-msgstr ""
+msgstr "å¯è¦‹æ€§ï¼š"
msgid "VisibilityLevel|Internal"
msgstr "內部"
msgid "VisibilityLevel|Private"
-msgstr "ç§æœ‰"
+msgstr "ç§äºº"
msgid "VisibilityLevel|Public"
msgstr "公開"
@@ -8883,44 +10460,68 @@ msgstr "公開"
msgid "VisibilityLevel|Unknown"
msgstr "ä¸æ˜Ž"
-msgid "Vulnerability|Class"
+msgid "Vulnerability Chart"
msgstr ""
-msgid "Vulnerability|Confidence"
+msgid "Vulnerability List"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr "é¡žåž‹"
+
+msgid "Vulnerability|Confidence"
+msgstr "機密"
+
msgid "Vulnerability|Description"
-msgstr ""
+msgstr "說明"
msgid "Vulnerability|File"
-msgstr ""
+msgstr "檔案"
msgid "Vulnerability|Identifiers"
-msgstr ""
+msgstr "標示"
msgid "Vulnerability|Instances"
-msgstr ""
+msgstr "實例"
msgid "Vulnerability|Links"
-msgstr ""
+msgstr "連çµ"
msgid "Vulnerability|Project"
+msgstr "專案"
+
+msgid "Vulnerability|Report Type"
msgstr ""
msgid "Vulnerability|Severity"
+msgstr "åš´é‡æ€§"
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr "權é™ä¸è¶³ã€‚如需檢視相關資料,請å‘管ç†å“¡ç”³è«‹æ¬Šé™ã€‚"
+
+msgid "We can't find an epic that matches what you are looking for."
msgstr ""
-msgid "Vulnerability|Solution"
+msgid "We can't find an issue that matches what you are looking for."
msgstr ""
-msgid "Want to see the data? Please ask an administrator for access."
-msgstr "權é™ä¸è¶³ã€‚如需查看相關資料,請å‘管ç†å“¡ç”³è«‹æ¬Šé™ã€‚"
+msgid "We could not determine the path to remove the epic"
+msgstr ""
-msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any results matching"
msgstr ""
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr "我們åµæ¸¬åˆ° %{humanized_resource_name} 潛在垃圾郵件。請驗證 reCAPTCHA 之後å†ç¹¼çºŒã€‚"
+
msgid "We don't have enough data to show this stage."
-msgstr "因該階段的資料ä¸è¶³è€Œç„¡æ³•é¡¯ç¤ºç›¸é—œè³‡è¨Š"
+msgstr "應該階段的資料ä¸è¶³è€Œç„¡æ³•é¡¯ç¤ºç›¸é—œè³‡è¨Š"
+
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "我們è¦ç¢ºå®šä½ ä¸æ˜¯æ©Ÿå™¨äººã€‚"
@@ -8928,6 +10529,9 @@ msgstr "我們è¦ç¢ºå®šä½ ä¸æ˜¯æ©Ÿå™¨äººã€‚"
msgid "Web IDE"
msgstr "ç¶²é  IDE"
+msgid "Web Terminal"
+msgstr ""
+
msgid "Web terminal"
msgstr "網é çµ‚端器"
@@ -8952,11 +10556,14 @@ msgstr "當啟用,使用者在接å—æ¢æ¬¾ä¹‹å‰éƒ½ä¸èƒ½ä½¿ç”¨ GitLab。"
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "當 URL 留空時,還是å¯ä»¥æŒ‡å®šåˆ†é¡žæ¨™ç±¤ï¼Œè€Œä¸”ä¸å¿…åœç”¨è·¨å°ˆæ¡ˆåŠŸèƒ½æˆ–執行外部授權檢查。"
-msgid "Who can see this group?"
+msgid "When:"
msgstr ""
+msgid "Who can see this group?"
+msgstr "誰å¯ä»¥çœ‹åˆ°é€™å€‹ç¾¤çµ„?"
+
msgid "Who will be able to see this group?"
-msgstr ""
+msgstr "誰å¯ä»¥çœ‹åˆ°é€™å€‹ç¾¤çµ„?"
msgid "Wiki"
msgstr "Wiki"
@@ -9001,7 +10608,7 @@ msgid "WikiEmpty|Suggest wiki improvement"
msgstr "建議 Wiki 改善"
msgid "WikiEmpty|The wiki lets you write documentation for your project"
-msgstr "Wiki å…許您為您的專案撰寫文件"
+msgstr "Wiki å…許您為您的專案撰寫檔案"
msgid "WikiEmpty|This project has no wiki pages"
msgstr "此專案沒有任何 Wiki é é¢"
@@ -9013,7 +10620,7 @@ msgid "WikiHistoricalPage|This is an old version of this page."
msgstr "這個é é¢è¼ƒèˆŠçš„版本。"
msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
-msgstr "ä½ å¯ä»¥æŸ¥çœ‹ %{most_recent_link} 或是ç€è¦½ %{history_link} 。"
+msgstr "ä½ å¯ä»¥æª¢è¦– %{most_recent_link} 或是ç€è¦½ %{history_link} 。"
msgid "WikiHistoricalPage|history"
msgstr "æ­·å²"
@@ -9025,7 +10632,7 @@ msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
msgstr "更多範例在 %{docs_link}"
msgid "WikiMarkdownDocs|documentation"
-msgstr "文件"
+msgstr "檔案"
msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
msgstr "è‹¥è¦é€£çµåˆ°ä¸€å€‹æ–°çš„é é¢ï¼Œåªè¦ç°¡å–®çš„輸入 %{link_example}。"
@@ -9034,7 +10641,7 @@ msgid "WikiNewPagePlaceholder|how-to-setup"
msgstr "如何安è£"
msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
-msgstr "å°æ示: ä½ å¯ä»¥æŒ‡å®šæ–°æª”案的絕å°è·¯å¾‘。我們會自動建立所有ä¸å­˜åœ¨çš„目錄。"
+msgstr "å°æ示: ä½ å¯ä»¥æŒ‡å®šæ–°æª”案的絕å°è·¯å¾‘。我們會自動建立所有ä¸å­˜åœ¨çš„資料夾。"
msgid "WikiNewPageTitle|New Wiki Page"
msgstr "新的維基é é¢"
@@ -9064,7 +10671,7 @@ msgid "WikiPage|Page slug"
msgstr "é é¢ slug"
msgid "WikiPage|Write your content or drag files here…"
-msgstr "填寫內容或拖曳檔案至此..."
+msgstr "填寫內容或拖曳檔案至此…"
msgid "Wiki|Create Page"
msgstr "建立é é¢"
@@ -9093,12 +10700,21 @@ msgstr "é é¢"
msgid "Wiki|Wiki Pages"
msgstr "維基é é¢"
+msgid "Will deploy to"
+msgstr ""
+
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
msgstr "é€éŽè²¢ç»åˆ†æžï¼Œæ‚¨å¯ä»¥å–得活動概覽,其包å«äº†æ‚¨çš„組織和其æˆå“¡çš„è­°é¡Œã€åˆä½µè«‹æ±‚與推é€æ´»å‹•ã€‚"
msgid "Withdraw Access Request"
msgstr "å–消權é™ç”³è«‹"
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr "是"
@@ -9106,13 +10722,16 @@ msgid "Yes, add it"
msgstr "是的,新增它"
msgid "Yes, let me map Google Code users to full names or GitLab users."
-msgstr ""
+msgstr "是的,讓我將 Google Code 使用者å°æ‡‰åˆ°å…¨å或 GitLab 使用者。"
msgid "Yesterday"
+msgstr "昨天"
+
+msgid "You"
msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
-msgstr ""
+msgstr "您是一å管ç†å“¡ï¼Œé€™æ„味著如果授予 <strong>%{client_name}</strong> 訪å•æ¬Šé™ï¼Œå°‡å…許他們作為管ç†å“¡èˆ‡GitLab進行互動。請謹慎行事。"
msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "å°‡è¦åˆªé™¤ %{group_name}。被刪除的群組無法復原ï¼çœŸçš„「確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
@@ -9129,8 +10748,11 @@ msgstr "å°‡è¦æŠŠ %{project_full_name} 的所有權轉移給å¦ä¸€å€‹äººã€‚真çš
msgid "You are on a read-only GitLab instance."
msgstr "您在唯讀的 GitLab 主機上。"
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
-msgstr "您å¯ä»¥ %{linkStart}查看BLOB%{linkEnd} 。"
+msgstr "您å¯ä»¥ %{linkStart}檢視BLOB%{linkEnd} 。"
msgid "You can also create a project from the command line."
msgstr "您也å¯ä»¥å¾žæŒ‡ä»¤æ–°å¢žä¸€å€‹å°ˆæ¡ˆã€‚"
@@ -9139,10 +10761,10 @@ msgid "You can also star a label to make it a priority label."
msgstr "您還å¯ä»¥ç‚ºæŸå€‹æ¨™ç±¤åŠ ä¸Šæ˜Ÿæ˜Ÿï¼Œä½¿å…¶æˆç‚ºå„ªå…ˆæ¨™ç±¤ã€‚"
msgid "You can easily contribute to them by requesting to join these groups."
-msgstr ""
+msgstr "您å¯ä»¥é€éŽè«‹æ±‚加入這些群組,來輕鬆地為他們åšå‡ºè²¢ç»ã€‚"
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "您å¯ä»¥è¼•é¬†åœ°åœ¨ Kubernetes å¢é›†ä¸Šå®‰è£é‹è¡Œå™¨ã€‚ %{link_to_help_page}"
+msgstr "您å¯ä»¥è¼•é¬†åœ°åœ¨ Kubernetes å¢é›†ä¸Šå®‰è£åŸ·è¡Œå™¨ã€‚ %{link_to_help_page}"
msgid "You can move around the graph by using the arrow keys."
msgstr "您å¯ä»¥ä½¿ç”¨ä¸Šä¸‹å·¦å³éµç§»å‹•åœ–形。"
@@ -9151,16 +10773,19 @@ msgid "You can only add files when you are on a branch"
msgstr "åªèƒ½åœ¨åˆ†æ”¯ä¸Šå»ºç«‹æª”案"
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 ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "您å¯ä»¥é€éŽä½¿ç”¨äº’動模å¼é¸æ“‡ %{use_ours} 或 %{use_theirs} 按鈕ã€æˆ–者是直接編輯檔案來解決åˆä½µè¡çªï¼Œä¸¦å°‡é€™äº›è®Šæ›´æ交到 %{branch_name}。"
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr ""
+msgstr "您å¯ä»¥å°‡å·¥ä½œè¨­å®šç‚ºæ­¢ä½¿ç”¨å…·æœ‰ç‰¹åˆ¥æ¨™ç±¤çš„執行器。請使用逗號分隔ä¸åŒçš„標籤。"
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
-msgstr ""
+msgstr "您å¯ä»¥é€éŽ %{linkStart}CI Lint%{linkEnd} 測試 .gitlab-ci.yml"
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "您ä¸èƒ½å¯«å…¥åˆ°å”¯è®€çš„æ¬¡è¦ GitLab Geo 主機。請改用 %{link_to_primary_node}。"
@@ -9169,15 +10794,21 @@ msgid "You cannot write to this read-only GitLab instance."
msgstr "您ä¸èƒ½ä¿®æ”¹é€™å€‹å”¯è®€çš„ GitLab 主機。"
msgid "You do not have any subscriptions yet"
+msgstr "你還沒有任何訂閱"
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "您沒有權é™ä¾†è¦†è“‹ LDAP 群組åŒæ­¥è¨­å®šã€‚"
msgid "You don't have any applications"
-msgstr ""
+msgstr "您沒有任何應用程å¼"
msgid "You don't have any authorized applications"
+msgstr "您沒有任何已授權的應用程å¼"
+
+msgid "You don't have any deployments right now."
msgstr ""
msgid "You have no permissions"
@@ -9186,8 +10817,11 @@ msgstr "你沒有權é™"
msgid "You have reached your project limit"
msgstr "您已é”到專案數é‡é™åˆ¶"
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
-msgstr "您必須接å—我們的æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–æ‰èƒ½è¨»å†Šå¸³æˆ¶"
+msgstr "您必須接å—我們的æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–æ‰èƒ½è¨»å†Šå¸³è™Ÿ"
msgid "You must have maintainer access to force delete a lock"
msgstr "您必須æ“有維護者存å–æ‰èƒ½å¼·åˆ¶ç§»é™¤éŽ–定"
@@ -9195,16 +10829,22 @@ msgstr "您必須æ“有維護者存å–æ‰èƒ½å¼·åˆ¶ç§»é™¤éŽ–定"
msgid "You need a different license to enable FileLocks feature"
msgstr "您需è¦ä½¿ç”¨ä¸åŒçš„授權以啟用 FileLocks 功能"
+msgid "You need a different license to enable Geo replication."
+msgstr ""
+
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr "æ‚¨éœ€è¦ git-lfs 版本 %{min_git_lfs_version} (或更高版本) æ‰èƒ½ç¹¼çºŒã€‚è«‹å‰å¾€ https://git-lfs.github.com"
msgid "You need permission."
msgstr "需è¦æ¬Šé™æ‰èƒ½é€™éº¼åšã€‚"
-msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
-msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
msgstr ""
msgid "You will not get any notifications via email"
@@ -9220,7 +10860,7 @@ msgid "You will receive notifications for any activity"
msgstr "接收所有活動的通知"
msgid "You will receive notifications only for comments in which you were @mentioned"
-msgstr "åªæŽ¥æ”¶è©•è«–中æåŠ(@)您的通知"
+msgstr "åªæŽ¥æ”¶ç•™è¨€ä¸­æåŠ(@)您的通知"
msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
msgstr "在帳號上 %{set_password_link} 之å‰ï¼Œ 將無法使用 %{protocol} 上傳或下載程å¼ç¢¼ã€‚"
@@ -9229,28 +10869,31 @@ msgid "You won't be able to pull or push project code via SSH until you %{add_ss
msgstr "在個人帳號中 %{add_ssh_key_link} 之å‰ï¼Œ 將無法使用 SSH 上傳或下載程å¼ç¢¼ã€‚"
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
-msgstr "在您的個人資料中添加 SSH 密鑰之å‰ï¼Œä½ ä¸èƒ½é€éŽ SSH 來拉å–或推é€å°ˆæ¡ˆç¨‹å¼ç¢¼ã€‚"
+msgstr "在您的個人資料中新增 SSH 密鑰之å‰ï¼Œä½ ä¸èƒ½é€éŽ SSH 來拉å–或推é€å°ˆæ¡ˆç¨‹å¼ç¢¼ã€‚"
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "你需è¦é¸æ“‡å…©å€‹ä¸åŒçš„分支,æ‰èƒ½é€²è¡Œæ¯”較。"
msgid "You're receiving this email because %{reason}."
-msgstr ""
+msgstr "您因為%{reason}收到此電å­éƒµä»¶ã€‚"
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_notifications_link} &middot; %{help_link}"
-msgstr "你收到此電å­éƒµä»¶æ˜¯å› ç‚ºä½ çš„帳戶在 %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr "你收到此電å­éƒµä»¶æ˜¯å› ç‚ºä½ çš„帳號在 %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgid "YouTube"
+msgstr "YouTube"
+
+msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your Groups"
msgstr "你的群組"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
-msgstr "您的Kuberneteså¢é›†è³‡è¨Šä»ç„¶å¯ä»¥ç·¨è¼¯ï¼Œä½†å»ºè­°æ‚¨ç¦ç”¨ä¸¦é‡æ–°è¨­ç½®ã€‚"
+msgstr "您的Kuberneteså¢é›†è³‡è¨Šä»ç„¶å¯ä»¥ç·¨è¼¯ï¼Œä½†å»ºè­°æ‚¨ç¦ç”¨ä¸¦é‡æ–°è¨­å®šã€‚"
msgid "Your Projects (default)"
msgstr "您的專案(é è¨­å€¼ï¼‰"
@@ -9261,45 +10904,69 @@ msgstr "您的專案活動"
msgid "Your Todos"
msgstr "您的待辦事項"
-msgid "Your applications (%{size})"
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
+msgid "Your applications (%{size})"
+msgstr "æ‚¨çš„æ‡‰ç”¨ç¨‹å¼ (%{size})"
+
msgid "Your authorized applications"
+msgstr "您的已èªè­‰æ‡‰ç”¨ç¨‹å¼"
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
-msgstr "你的更改將å¯ä»¥æ交到 %{branch_name} 因為åˆä½µè«‹æ±‚已打開。"
+msgstr "你的變更將å¯ä»¥æ交到 %{branch_name} 因為åˆä½µè«‹æ±‚已打開。"
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
-msgstr "您的更改已被æ交。更動紀錄 %{commitId} %{commitStats}"
+msgstr "您的變更已被æ交。æ交記錄 %{commitId} %{commitStats}"
msgid "Your changes have been saved"
-msgstr ""
+msgstr "您的修改已經儲存"
msgid "Your comment will not be visible to the public."
msgstr "你的留言將ä¸æœƒè¢«å…¬é–‹ã€‚"
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr "您的群組"
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
msgid "Your name"
msgstr "您的åå­—"
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
msgid "Your projects"
-msgstr "你的計劃"
+msgstr "您的專案"
msgid "a deleted user"
-msgstr ""
+msgstr "已刪除的使用者"
msgid "ago"
msgstr "之å‰"
+msgid "allowed to fail"
+msgstr ""
+
msgid "among other things"
msgstr "除了其他事情"
msgid "assign yourself"
msgstr "指派給自己"
+msgid "attach a new file"
+msgstr ""
+
msgid "branch name"
msgstr "分支å稱"
@@ -9326,49 +10993,49 @@ msgstr "%{remainingPackagesCount} 更多"
msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
-msgstr[0] ""
+msgstr[0] "%{reportType} %{status} åµæ¸¬åˆ° %{fixedCount} 個已修復的安全æ¼æ´žã€‚"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
-msgstr[0] ""
+msgstr[0] "%{reportType} %{status} åµæ¸¬åˆ° %{newCount} 個新的安全æ¼æ´ž"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} åµæ¸¬åˆ° %{newCount} 新的安全æ¼æ´žå’Œ %{fixedCount} 個已修復的æ¼æ´ž"
msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
-msgstr[0] ""
+msgstr[0] "%{reportType} %{status} åµæ¸¬åˆ°ä¾†æºåˆ†ä¹‹æœ‰ %{newCount} 個安全æ¼æ´ž"
msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} 未發ç¾æ–°çš„安全æ¼æ´ž"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
-msgstr ""
+msgstr "ciReport|%{reportType} %{status} 未åµæ¸¬åˆ°æ¼æ´ž"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
-msgstr ""
+msgstr "ciReport|%{reportType} %{status} 僅在此來æºåˆ†æ”¯æ²’åµæ¸¬åˆ°æ¼æ´ž"
msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
+msgstr[0] "%{reportType} åµæ¸¬åˆ° %{vulnerabilityCount} 個æ¼æ´ž"
msgid "ciReport|%{reportType} detected no vulnerabilities"
-msgstr ""
+msgstr "%{reportType} 未åµæ¸¬åˆ°æ¼æ´ž"
msgid "ciReport|%{reportType} is loading"
-msgstr ""
+msgstr "%{reportType} 載入中"
msgid "ciReport|%{reportType}: Loading resulted in an error"
-msgstr ""
+msgstr "%{reportType}:因載入導致錯誤"
msgid "ciReport|(errors when loading results)"
-msgstr ""
+msgstr "(載入çµæžœæ™‚發生錯誤)"
msgid "ciReport|(is loading)"
-msgstr ""
+msgstr "(正在載入)"
msgid "ciReport|(is loading, errors when loading results)"
-msgstr ""
+msgstr "(正在載入,當載入çµæžœæ™‚發生錯誤)"
msgid "ciReport|Class"
msgstr "類別"
@@ -9380,19 +11047,22 @@ msgid "ciReport|Confidence"
msgstr "ä¿¡ä»»"
msgid "ciReport|Container scanning"
-msgstr ""
+msgstr "正在掃æ容器"
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr "容器掃æåµæ¸¬åœ¨æ‚¨çš„ Docker 映åƒä¸­çš„已知æ¼æ´žã€‚"
msgid "ciReport|DAST"
+msgstr "DAST"
+
+msgid "ciReport|Dependency Scanning"
msgstr ""
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
-msgstr ""
+msgstr "ä¾è³´é—œä¿‚掃æ在您原始碼的ä¾è³´é—œä¿‚中åµæ¸¬åˆ°å·²çŸ¥æ¼æ´žã€‚"
msgid "ciReport|Dependency scanning"
-msgstr ""
+msgstr "正在掃æä¾è³´é—œä¿‚"
msgid "ciReport|Description"
msgstr "說明"
@@ -9403,6 +11073,12 @@ msgstr "忽略æ¼æ´ž"
msgid "ciReport|Dismissed by"
msgstr "忽略由"
+msgid "ciReport|Download and apply the patch to fix this vulnerability."
+msgstr ""
+
+msgid "ciReport|Download patch"
+msgstr ""
+
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr "動態應用程å¼å®‰å…¨æ€§æ¸¬è©¦ (DAST) 在您的網é æ‡‰ç”¨ç¨‹å¼ä¸­åµæ¸¬åˆ°å·²çŸ¥æ¼æ´žã€‚"
@@ -9426,14 +11102,14 @@ msgstr "了解關於和安全性報告 (Alpha) 互動的更多資訊。"
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
-msgstr[0] ""
+msgstr[0] "授權管ç†åµæ¸¬åˆ° %d 個åªèƒ½åœ¨ä¾†æºåˆ†æ”¯ä½¿ç”¨çš„授權"
msgid "ciReport|License management detected %d new license"
msgid_plural "ciReport|License management detected %d new licenses"
-msgstr[0] ""
+msgstr[0] "授權管ç†åµæ¸¬åˆ° %d 個新授權"
msgid "ciReport|License management detected no licenses for the source branch only"
-msgstr ""
+msgstr "授權管ç†æœªåµæ¸¬åˆ°åªèƒ½ç”¨æ–¼ä¾†æºåˆ†æ”¯çš„授權"
msgid "ciReport|License management detected no new licenses"
msgstr "授權管ç†æœªåµæ¸¬åˆ°æ–°æŽˆæ¬Š"
@@ -9445,7 +11121,7 @@ msgid "ciReport|Loading %{reportName} report"
msgstr "正在載入 %{reportName} 報告"
msgid "ciReport|Manage licenses"
-msgstr ""
+msgstr "管ç†è¨±å¯è­‰"
msgid "ciReport|Method"
msgstr "方法"
@@ -9454,7 +11130,7 @@ msgid "ciReport|Namespace"
msgstr "命å空間"
msgid "ciReport|No changes to code quality"
-msgstr "沒有程å¼ç¢¼å“質的更動"
+msgstr "沒有程å¼ç¢¼å“質的變更"
msgid "ciReport|No changes to performance metrics"
msgstr "沒有效能指標的變動"
@@ -9466,7 +11142,7 @@ msgid "ciReport|Revert dismissal"
msgstr "撤回忽略"
msgid "ciReport|SAST"
-msgstr ""
+msgstr "SAST"
msgid "ciReport|Security scanning"
msgstr "安全性掃æ"
@@ -9509,22 +11185,25 @@ msgstr "å°‡ %{name} 從 %{version} å‡ç´šåˆ° %{fixed}。"
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|on pipeline"
-msgstr "æµæ°´ç·šä¸Š"
+msgstr "管線上"
msgid "command line instructions"
msgstr "指令說明"
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgid "commented on %{link_to_project}"
msgstr ""
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr "å³å°‡é—œé–‰éš±ç§æ€§ï¼Œé€™å°‡è®“ <strong>所有使用者</strong> 都å¯ä»¥æª¢è¦–並留言目å‰çš„議題。"
+
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
+msgstr "å³å°‡é–‹å•Ÿéš±ç§æ€§ï¼Œé€™å°‡è®“ <strong>至少有回報者權é™çš„人</strong> æ‰å¯ä»¥æª¢è¦–åŠç•™è¨€ç›®å‰çš„議題。"
msgid "connecting"
msgstr "連線中"
@@ -9533,28 +11212,44 @@ msgid "could not read private key, is the passphrase correct?"
msgstr "無法存å–ç§é‘°ï¼Œæª¢æŸ¥å¯†ç¢¼æ˜¯å¦æ­£ç¢ºï¼Ÿ"
msgid "customize"
-msgstr ""
+msgstr "自訂"
msgid "day"
msgid_plural "days"
msgstr[0] "æ—¥"
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr "部署憑證"
msgid "disabled"
msgstr "å·²åœç”¨"
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+
msgid "done"
-msgstr ""
+msgstr "完æˆ"
msgid "draft"
msgid_plural "drafts"
-msgstr[0] ""
+msgstr[0] "è‰ç¨¿"
msgid "enabled"
msgstr "已啟用"
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} 將更新é ä¼°èŠ±è²»æ™‚間。"
@@ -9562,26 +11257,44 @@ msgid "for this project"
msgstr "為此專案"
msgid "from"
+msgstr "來自"
+
+msgid "group"
msgstr ""
msgid "help"
-msgstr ""
+msgstr "幫助"
msgid "here"
msgstr "這裡"
+msgid "http://<sentry-host>/api/0/projects/{organization_slug}/{project_slug}/"
+msgstr ""
+
msgid "https://your-bitbucket-server"
+msgstr "https://your-bitbucket-server"
+
+msgid "image diff"
msgstr ""
msgid "import flow"
-msgstr ""
+msgstr "匯入æµç¨‹"
msgid "importing"
msgstr "輸入"
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "index"
+msgstr ""
+
msgid "instance completed"
msgid_plural "instances completed"
-msgstr[0] ""
+msgstr[0] "實例完æˆ"
msgid "is invalid because there is downstream lock"
msgstr "因為下游鎖定,所以無效"
@@ -9592,27 +11305,60 @@ msgstr "因上游鎖定而無效"
msgid "is not a valid X509 certificate."
msgstr "éžæœ‰æ•ˆ X509 憑證。"
+msgid "is out of the hierarchy of the Group owning the template"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
msgid "issue boards"
+msgstr "議題看æ¿"
+
+msgid "it is stored externally"
msgstr ""
-msgid "latest deployment"
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
msgstr ""
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr "最新的部署"
+
msgid "latest version"
msgstr "最新版本"
msgid "license management"
-msgstr ""
+msgstr "授權管ç†"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "由 %{path_lock_user_name} 於 %{created_at} 鎖定"
+msgid "manual"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "åˆä½µè«‹æ±‚"
+msgid "missing"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr "è«‹æ¢å¾©å®ƒæˆ–使用一個ä¸åŒ %{missingBranchName} 的分支"
+msgstr "請復原它或使用一個ä¸åŒ %{missingBranchName} 的分支"
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr "%{metricsLinkStart} 記憶體 %{metricsLinkEnd} 使用 %{emphasisStart} ä¸‹é™ %{emphasisEnd} 從 %{memoryFrom} MB 到 %{memoryTo} MB"
@@ -9629,14 +11375,14 @@ msgstr "新增批准"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "å…許å¯ä»¥åˆä½µåˆ°ç›®æ¨™åˆ†æ”¯çš„æˆå“¡æ交"
-msgid "mrWidget|An error occured while removing your approval."
-msgstr "移除您的批准時發生錯誤。"
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
-msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
-msgstr ""
+msgstr "æ交你的請批準時發生錯誤。"
msgid "mrWidget|Approve"
msgstr "批准"
@@ -9654,10 +11400,10 @@ msgid "mrWidget|Checking ability to merge automatically"
msgstr "檢查是å¦å¯ä»¥è‡ªå‹•åˆä½µ"
msgid "mrWidget|Cherry-pick"
-msgstr "挑é¸"
+msgstr "æ€é¸"
msgid "mrWidget|Cherry-pick this merge request in a new merge request"
-msgstr "挑é¸æ­¤åˆä½µè«‹æ±‚的修訂版本以建立新的åˆä½µè«‹æ±‚"
+msgstr "æ€é¸æ­¤åˆä½µè«‹æ±‚的修訂版本以建立新的åˆä½µè«‹æ±‚"
msgid "mrWidget|Closed"
msgstr "關閉"
@@ -9671,6 +11417,9 @@ msgstr "關閉"
msgid "mrWidget|Create an issue to resolve them later"
msgstr "建立一個議題,以在ç¨å€™è§£æ±º"
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "ç›®å‰ç„¡æ³•ä½¿ç”¨éƒ¨ç½²çš„統計資料"
@@ -9684,13 +11433,13 @@ msgid "mrWidget|Failed to load deployment statistics"
msgstr "讀å–部署統計資料時發生錯誤"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr ""
+msgstr "無法進行快速åˆä½µã€‚è¦åˆä½µæ­¤è«‹æ±‚,請先在本定進行 rebase。"
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
-msgstr "如果 %{branch} 分支存在於您的本地檔案庫,你å¯ä»¥æ‰‹å‹•åˆä½µæ­¤åˆä½µè«‹æ±‚,藉由"
+msgstr "如果 %{branch} 分支存在於您的本機版本庫,你å¯ä»¥æ‰‹å‹•åˆä½µæ­¤åˆä½µè«‹æ±‚,藉由"
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
-msgstr "如果 %{missingBranchName} 分支徂在於您的本地檔案庫,您å¯ä»¥æ‰‹å‹•åˆä½µæ­¤åˆä½µè«‹æ±‚藉由此指令"
+msgstr "如果 %{missingBranchName} 分支徂在於您的本機版本庫,您å¯ä»¥æ‰‹å‹•åˆä½µæ­¤åˆä½µè«‹æ±‚藉由此指令"
msgid "mrWidget|Loading deployment statistics"
msgstr "讀å–部署統計資料"
@@ -9705,13 +11454,13 @@ msgid "mrWidget|Merge failed."
msgstr "åˆä½µå¤±æ•—"
msgid "mrWidget|Merge locally"
-msgstr "本地åˆä½µ"
+msgstr "本機åˆä½µ"
msgid "mrWidget|Merge request approved"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已經批准"
msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已經被批准; ä½ å¯ä»¥å¦å¤–批准"
msgid "mrWidget|Merged by"
msgstr "åˆä½µè€…"
@@ -9726,13 +11475,13 @@ msgid "mrWidget|Open in Web IDE"
msgstr "åœ¨ç¶²é  IDE 中開啟"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
+msgstr "管線被終止。此åˆä½µè«‹æ±‚的管線需è¦æ‰‹å‹•æ“作æ‰èƒ½ç¹¼çºŒ"
msgid "mrWidget|Plain diff"
msgstr "本文差異"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
-msgstr ""
+msgstr "準備自動åˆä½µã€‚è©¢å•å…·æœ‰æ­¤ç‰ˆæœ¬åº«æœ‰å¯«å…¥æ¬Šé™çš„人來åˆä½µæ­¤è«‹æ±‚"
msgid "mrWidget|Refresh"
msgstr "é‡æ–°æ•´ç†"
@@ -9743,12 +11492,6 @@ msgstr "ç«‹å³é‡æ–°æ•´ç†"
msgid "mrWidget|Refreshing now"
msgstr "ç«‹å³é‡æ–°æ•´ç†"
-msgid "mrWidget|Remove Source Branch"
-msgstr "刪除原始分支"
-
-msgid "mrWidget|Remove source branch"
-msgstr "刪除原始分支"
-
msgid "mrWidget|Remove your approval"
msgstr "移除您的批准"
@@ -9757,56 +11500,56 @@ msgstr "請求åˆä½µ"
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
+msgstr[0] "éœ€è¦ %d 個批准"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
+msgstr[0] "éœ€è¦ %d 個來自該使用者的批准:"
msgid "mrWidget|Resolve conflicts"
msgstr "解決è¡çª"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
+msgstr "解決這些è¡çªæˆ–è©¢å•å°æ­¤ç‰ˆæœ¬åº«æœ‰å¯«å…¥æ¬Šé™çš„人員在本機åˆä½µå®ƒ"
msgid "mrWidget|Revert"
msgstr "還原"
msgid "mrWidget|Revert this merge request in a new merge request"
-msgstr "é€éŽæ–°çš„åˆä½µè«‹æ±‚還原此åˆä½µè«‹æ±‚æ›´å‹•çš„é …ç›®"
+msgstr "é€éŽæ–°çš„åˆä½µè«‹æ±‚還原此åˆä½µè«‹æ±‚變更的項目"
msgid "mrWidget|Set by"
-msgstr "設置者"
+msgstr "設定者"
msgid "mrWidget|The changes were merged into"
-msgstr "這些更改將會åˆä½µåˆ°"
+msgstr "這些變更將會åˆä½µåˆ°"
msgid "mrWidget|The changes were not merged into"
-msgstr "這些更改將ä¸æœƒåˆä½µåˆ°"
+msgstr "這些變更將ä¸æœƒåˆä½µåˆ°"
msgid "mrWidget|The changes will be merged into"
-msgstr "這些更改將會åˆä½µåˆ°"
+msgstr "這些變更將會åˆä½µåˆ°"
msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr ""
+msgstr "æ­¤åˆä½µè«‹æ±‚的管線失敗。請é‡è©¦è©²å·¥ä½œæˆ–推é€æ–°çš„æ交以修復失敗"
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
-msgstr ""
+msgstr "æºçš„分支 HEAD 最近已變更。請å†é‡æ–°åˆä½µä¹‹å‰é‡æ–°æ•´ç†é é¢ä¸¦æª¢é–±è®Šæ›´"
-msgid "mrWidget|The source branch has been removed"
-msgstr "來æºåˆ†æ”¯å·²ç¶“被刪除"
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
-msgstr ""
+msgstr "æºåˆ†æ”¯æ˜¯ %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} 的目標分支"
-msgid "mrWidget|The source branch is being removed"
-msgstr "來æºåˆ†æ”¯æ­£åœ¨è¢«åˆªé™¤"
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
-msgid "mrWidget|The source branch will be removed"
-msgstr "來æºåˆ†æ”¯å°‡æœƒè¢«åˆªé™¤"
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
-msgid "mrWidget|The source branch will not be removed"
-msgstr "來æºåˆ†æ”¯å°‡ä¸æœƒè¢«åˆªé™¤"
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "發生åˆä½µè¡çª"
@@ -9814,6 +11557,9 @@ msgstr "發生åˆä½µè¡çª"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "有個未解決的討論,請解決這些討論。"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "æ­¤åˆä½µè«‹æ±‚未能自動åˆä½µ"
@@ -9824,14 +11570,14 @@ msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "這個專案已經被打包,無法寫入"
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr "你沒有權é™ç›´æŽ¥ç·¨è¼¯æ­¤å°ˆæ¡ˆï¼Œè«‹åˆ†å‰å¾Œå†é€²è¡Œè®Šæ›´ã€‚"
+
+msgid "mrWidget|You can delete the source branch now"
msgstr ""
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "ä½ å¯ä»¥æ‰‹å‹•åˆä½µé€™å€‹åˆä½µè«‹æ±‚,藉由"
-msgid "mrWidget|You can remove source branch now"
-msgstr "ä½ ç¾åœ¨å¯ä»¥åˆªé™¤ä¾†æºåˆ†æ”¯"
-
msgid "mrWidget|branch does not exist."
msgstr "分支並ä¸å­˜åœ¨"
@@ -9842,23 +11588,35 @@ msgid "mrWidget|into"
msgstr "進入"
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
-msgstr "當æµæ°´ç·šå®Œæˆæ™‚將會被自動åˆä½µ"
+msgstr "當管線完æˆæ™‚將會被自動åˆä½µ"
msgid "n/a"
-msgstr ""
+msgstr "未知"
msgid "new merge request"
msgstr "建立åˆä½µè«‹æ±‚"
+msgid "none"
+msgstr ""
+
msgid "notification emails"
msgstr "通知信"
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
msgid "or"
msgstr "或"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
-msgstr[0] ""
+msgstr[0] "超出 %d 個總測試"
msgid "parent"
msgid_plural "parents"
@@ -9870,18 +11628,27 @@ msgstr "密碼"
msgid "personal access token"
msgstr "ç§äººå­˜å–憑證"
+msgid "private"
+msgstr ""
+
msgid "private key does not match certificate."
msgstr "ç§é‘°ä¸ç¬¦åˆæ†‘證。"
msgid "project"
msgid_plural "projects"
-msgstr[0] ""
+msgstr[0] "專案"
+
+msgid "quick actions"
+msgstr ""
+
+msgid "register"
+msgstr ""
msgid "remaining"
msgstr "剩餘"
msgid "remove"
-msgstr ""
+msgstr "移除"
msgid "remove due date"
msgstr "刪除截止日期"
@@ -9889,26 +11656,56 @@ msgstr "刪除截止日期"
msgid "remove weight"
msgstr "移除權é‡"
+msgid "rendered diff"
+msgstr ""
+
msgid "reply"
msgid_plural "replies"
-msgstr[0] ""
+msgstr[0] "回應"
+
+msgid "score"
+msgstr ""
+
+msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
msgid "source"
msgstr "來æº"
+msgid "source diff"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} 將會更新ã€åŠ ç¸½æ‰€èŠ±è²»çš„時間"
msgid "started"
+msgstr "已開始"
+
+msgid "stuck"
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
msgstr ""
msgid "this document"
-msgstr "這份文件"
+msgstr "這份檔案"
msgid "to help your contributors communicate effectively!"
msgstr "å”助你的貢ç»è€…進行有效的æºé€šï¼"
-msgid "toggle collapse"
+msgid "triggered"
+msgstr ""
+
+msgid "updated"
msgstr ""
msgid "username"
@@ -9917,7 +11714,13 @@ msgstr "使用者å稱"
msgid "uses Kubernetes clusters to deploy your code!"
msgstr "使用 Kubernetes å¢é›†éƒ¨ç½²æ‚¨çš„程å¼ç¢¼!"
+msgid "verify ownership"
+msgstr ""
+
msgid "view it on GitLab"
+msgstr "在 GitLab 上檢視"
+
+msgid "view the blob"
msgstr ""
msgid "with %{additions} additions, %{deletions} deletions."
@@ -9927,3 +11730,6 @@ msgid "within %d minute "
msgid_plural "within %d minutes "
msgstr[0] "在 %d 分é˜å…§ "
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/package.json b/package.json
index 1dc9797c59b..b9dc2220f56 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"eslint-fix": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue --fix .",
"eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html --no-inline-config .",
"jest": "BABEL_ENV=jest jest",
+ "jsdoc": "jsdoc -c config/jsdocs.config.js",
"karma": "BABEL_ENV=${BABEL_ENV:=karma} karma start --single-run true config/karma.config.js",
"karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
"karma-start": "BABEL_ENV=karma karma start config/karma.config.js",
@@ -15,28 +16,30 @@
"prettier-staged-save": "node ./scripts/frontend/prettier.js save",
"prettier-all": "node ./scripts/frontend/prettier.js check-all",
"prettier-all-save": "node ./scripts/frontend/prettier.js save-all",
+ "stylelint": "node node_modules/stylelint/bin/stylelint.js app/assets/stylesheets/**/*.* --custom-formatter node_modules/stylelint-error-string-formatter",
"webpack": "webpack --config config/webpack.config.js",
"webpack-prod": "NODE_ENV=production webpack --config config/webpack.config.js"
},
"dependencies": {
- "@babel/core": "^7.1.2",
- "@babel/plugin-proposal-class-properties": "^7.1.0",
- "@babel/plugin-proposal-json-strings": "^7.0.0",
- "@babel/plugin-syntax-dynamic-import": "^7.0.0",
- "@babel/plugin-syntax-import-meta": "^7.0.0",
- "@babel/preset-env": "^7.1.0",
+ "@babel/core": "^7.2.2",
+ "@babel/plugin-proposal-class-properties": "^7.3.0",
+ "@babel/plugin-proposal-json-strings": "^7.2.0",
+ "@babel/plugin-proposal-private-methods": "^7.3.0",
+ "@babel/plugin-syntax-dynamic-import": "^7.2.0",
+ "@babel/plugin-syntax-import-meta": "^7.2.0",
+ "@babel/preset-env": "^7.3.1",
"@gitlab/csslab": "^1.8.0",
- "@gitlab/svgs": "^1.43.0",
- "@gitlab/ui": "^1.18.0",
- "apollo-boost": "^0.1.20",
- "apollo-client": "^2.4.5",
+ "@gitlab/svgs": "^1.54.0",
+ "@gitlab/ui": "^2.2.1",
+ "apollo-boost": "^0.3.1",
+ "apollo-client": "^2.5.1",
"autosize": "^4.0.0",
"axios": "^0.17.1",
- "babel-loader": "^8.0.4",
+ "babel-loader": "^8.0.5",
"bootstrap": "4.1.3",
"brace-expansion": "^1.1.8",
- "cache-loader": "^1.2.2",
- "chart.js": "1.0.2",
+ "cache-loader": "^2.0.1",
+ "chart.js": "2.7.2",
"classlist-polyfill": "^1.2.0",
"clipboard": "^1.7.1",
"codesandbox-api": "^0.0.20",
@@ -54,90 +57,96 @@
"d3-time": "^1.0.8",
"d3-time-format": "^2.1.1",
"dateformat": "^3.0.3",
- "deckar01-task_list": "^2.0.0",
+ "deckar01-task_list": "^2.2.0",
"diff": "^3.4.0",
- "document-register-element": "1.3.0",
+ "document-register-element": "1.13.1",
"dropzone": "^4.2.0",
"echarts": "^4.2.0-rc.2",
+ "emoji-regex": "^7.0.3",
"emoji-unicode-version": "^0.2.1",
"exports-loader": "^0.7.0",
- "file-loader": "^2.0.0",
+ "file-loader": "^3.0.1",
"formdata-polyfill": "^3.0.11",
"fuzzaldrin-plus": "^0.5.0",
"glob": "^7.1.2",
"graphql": "^14.0.2",
"imports-loader": "^0.8.0",
"jed": "^1.1.1",
+ "jest-transform-graphql": "^2.1.0",
"jquery": "^3.2.1",
"jquery-ujs": "1.2.2",
"jquery.waitforimages": "^2.2.0",
"js-cookie": "^2.1.3",
"jszip": "^3.1.3",
"jszip-utils": "^0.0.2",
- "katex": "^0.9.0",
+ "katex": "^0.10.0",
"marked": "^0.3.12",
"mermaid": "^8.0.0-rc.8",
- "monaco-editor": "^0.14.3",
- "monaco-editor-webpack-plugin": "^1.5.4",
+ "monaco-editor": "^0.15.6",
+ "monaco-editor-webpack-plugin": "^1.7.0",
"mousetrap": "^1.4.6",
"pikaday": "^1.6.1",
"popper.js": "^1.14.3",
"prismjs": "^1.6.0",
+ "prosemirror-markdown": "^1.3.0",
+ "prosemirror-model": "^1.6.4",
"raphael": "^2.2.7",
"raven-js": "^3.22.1",
- "raw-loader": "^0.5.1",
+ "raw-loader": "^1.0.0",
"sanitize-html": "^1.16.1",
"select2": "3.5.2-browserify",
"sha1": "^1.1.1",
- "smooshpack": "^0.0.53",
+ "smooshpack": "^0.0.54",
"sortablejs": "^1.7.0",
"sql.js": "^0.4.0",
"stickyfilljs": "^2.0.5",
- "style-loader": "^0.23.0",
+ "style-loader": "^0.23.1",
+ "stylelint-error-string-formatter": "^1.0.1",
"svg4everybody": "2.1.9",
"three": "^0.84.0",
"three-orbit-controls": "^82.1.0",
"three-stl-loader": "^1.0.4",
"timeago.js": "^3.0.2",
+ "tiptap": "^1.8.0",
+ "tiptap-commands": "^1.4.0",
+ "tiptap-extensions": "^1.8.0",
"underscore": "^1.9.0",
- "url-loader": "^1.1.1",
+ "url-loader": "^1.1.2",
"visibilityjs": "^1.2.4",
- "vue": "^2.5.17",
- "vue-apollo": "^3.0.0-beta.25",
+ "vue": "^2.5.21",
+ "vue-apollo": "^3.0.0-beta.28",
"vue-loader": "^15.4.2",
- "vue-resource": "^1.5.0",
- "vue-router": "^3.0.1",
- "vue-template-compiler": "^2.5.17",
+ "vue-resource": "^1.5.1",
+ "vue-router": "^3.0.2",
+ "vue-template-compiler": "^2.5.21",
"vue-virtual-scroll-list": "^1.2.5",
"vuex": "^3.0.1",
- "webpack": "^4.19.1",
- "webpack-bundle-analyzer": "^3.0.2",
- "webpack-cli": "^3.1.0",
+ "webpack": "^4.29.0",
+ "webpack-bundle-analyzer": "^3.0.3",
+ "webpack-cli": "^3.2.1",
"webpack-stats-plugin": "^0.2.1",
"worker-loader": "^2.0.0",
"xterm": "^3.5.0"
},
"devDependencies": {
+ "@babel/plugin-transform-modules-commonjs": "^7.2.0",
"@gitlab/eslint-config": "^1.4.0",
"@vue/test-utils": "^1.0.0-beta.25",
"axios-mock-adapter": "^1.15.0",
- "babel-core": "^7.0.0-bridge",
- "babel-jest": "^23.6.0",
+ "babel-jest": "^24.1.0",
"babel-plugin-dynamic-import-node": "^2.2.0",
"babel-plugin-istanbul": "^5.1.0",
"babel-plugin-rewire": "^1.2.0",
- "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
- "babel-template": "^6.26.0",
- "babel-types": "^6.26.0",
"chalk": "^2.4.1",
"commander": "^2.18.0",
+ "docdash": "^1.0.2",
"eslint": "~5.9.0",
"eslint-import-resolver-jest": "^2.1.1",
"eslint-import-resolver-webpack": "^0.10.1",
"eslint-plugin-html": "5.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jasmine": "^2.10.1",
- "eslint-plugin-jest": "^22.1.0",
+ "eslint-plugin-jest": "^22.3.0",
"gettext-extractor": "^3.3.2",
"gettext-extractor-vue": "^4.0.1",
"graphql-tag": "^2.10.0",
@@ -145,8 +154,10 @@
"jasmine-core": "^2.9.0",
"jasmine-diff": "^0.1.3",
"jasmine-jquery": "^2.1.1",
- "jest": "^23.6.0",
- "jest-junit": "^5.2.0",
+ "jest": "^24.1.0",
+ "jest-junit": "^6.3.0",
+ "jsdoc": "^3.5.5",
+ "jsdoc-vue": "^1.0.0",
"karma": "^3.0.0",
"karma-chrome-launcher": "^2.2.0",
"karma-coverage-istanbul-reporter": "^2.0.4",
@@ -155,13 +166,22 @@
"karma-mocha-reporter": "^2.2.5",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^4.0.0-beta.0",
- "nodemon": "^1.18.4",
- "prettier": "1.15.2",
- "vue-jest": "^3.0.1",
- "webpack-dev-server": "^3.1.10",
- "yarn-deduplicate": "^1.0.5"
+ "nodemon": "^1.18.9",
+ "pixelmatch": "^4.0.2",
+ "postcss": "^7.0.14",
+ "prettier": "1.16.1",
+ "stylelint": "^9.10.1",
+ "stylelint-config-recommended": "^2.1.0",
+ "stylelint-scss": "^3.5.3",
+ "vue-jest": "^4.0.0-beta.2",
+ "webpack-dev-server": "^3.1.14",
+ "yarn-deduplicate": "^1.1.0"
+ },
+ "resolutions": {
+ "vue-jest/ts-jest": "24.0.0"
},
"engines": {
+ "node": ">=8.10.0",
"yarn": "^1.10.0"
}
}
diff --git a/app/assets/images/emoji/100.png b/public/-/emojis/1/100.png
index 6903ff0304a..6903ff0304a 100644
--- a/app/assets/images/emoji/100.png
+++ b/public/-/emojis/1/100.png
Binary files differ
diff --git a/app/assets/images/emoji/1234.png b/public/-/emojis/1/1234.png
index 248dc7e55b6..248dc7e55b6 100644
--- a/app/assets/images/emoji/1234.png
+++ b/public/-/emojis/1/1234.png
Binary files differ
diff --git a/app/assets/images/emoji/1F627.png b/public/-/emojis/1/1F627.png
index f99026a3bc7..f99026a3bc7 100644
--- a/app/assets/images/emoji/1F627.png
+++ b/public/-/emojis/1/1F627.png
Binary files differ
diff --git a/app/assets/images/emoji/8ball.png b/public/-/emojis/1/8ball.png
index 38ca662eded..38ca662eded 100644
--- a/app/assets/images/emoji/8ball.png
+++ b/public/-/emojis/1/8ball.png
Binary files differ
diff --git a/app/assets/images/emoji/a.png b/public/-/emojis/1/a.png
index 8603ff05a17..8603ff05a17 100644
--- a/app/assets/images/emoji/a.png
+++ b/public/-/emojis/1/a.png
Binary files differ
diff --git a/app/assets/images/emoji/ab.png b/public/-/emojis/1/ab.png
index d9f2d17dea0..d9f2d17dea0 100644
--- a/app/assets/images/emoji/ab.png
+++ b/public/-/emojis/1/ab.png
Binary files differ
diff --git a/app/assets/images/emoji/abc.png b/public/-/emojis/1/abc.png
index 7688de692a9..7688de692a9 100644
--- a/app/assets/images/emoji/abc.png
+++ b/public/-/emojis/1/abc.png
Binary files differ
diff --git a/app/assets/images/emoji/abcd.png b/public/-/emojis/1/abcd.png
index 0996a870570..0996a870570 100644
--- a/app/assets/images/emoji/abcd.png
+++ b/public/-/emojis/1/abcd.png
Binary files differ
diff --git a/app/assets/images/emoji/accept.png b/public/-/emojis/1/accept.png
index 8afd7ce99cf..8afd7ce99cf 100644
--- a/app/assets/images/emoji/accept.png
+++ b/public/-/emojis/1/accept.png
Binary files differ
diff --git a/app/assets/images/emoji/aerial_tramway.png b/public/-/emojis/1/aerial_tramway.png
index 3eb4b61bf1d..3eb4b61bf1d 100644
--- a/app/assets/images/emoji/aerial_tramway.png
+++ b/public/-/emojis/1/aerial_tramway.png
Binary files differ
diff --git a/app/assets/images/emoji/airplane.png b/public/-/emojis/1/airplane.png
index 268d2ac3c8e..268d2ac3c8e 100644
--- a/app/assets/images/emoji/airplane.png
+++ b/public/-/emojis/1/airplane.png
Binary files differ
diff --git a/app/assets/images/emoji/airplane_arriving.png b/public/-/emojis/1/airplane_arriving.png
index d66841962f2..d66841962f2 100644
--- a/app/assets/images/emoji/airplane_arriving.png
+++ b/public/-/emojis/1/airplane_arriving.png
Binary files differ
diff --git a/app/assets/images/emoji/airplane_departure.png b/public/-/emojis/1/airplane_departure.png
index a5766f9f4ae..a5766f9f4ae 100644
--- a/app/assets/images/emoji/airplane_departure.png
+++ b/public/-/emojis/1/airplane_departure.png
Binary files differ
diff --git a/app/assets/images/emoji/airplane_small.png b/public/-/emojis/1/airplane_small.png
index b731b15e3a8..b731b15e3a8 100644
--- a/app/assets/images/emoji/airplane_small.png
+++ b/public/-/emojis/1/airplane_small.png
Binary files differ
diff --git a/app/assets/images/emoji/alarm_clock.png b/public/-/emojis/1/alarm_clock.png
index cdbc2fbb950..cdbc2fbb950 100644
--- a/app/assets/images/emoji/alarm_clock.png
+++ b/public/-/emojis/1/alarm_clock.png
Binary files differ
diff --git a/app/assets/images/emoji/alembic.png b/public/-/emojis/1/alembic.png
index 307a7324249..307a7324249 100644
--- a/app/assets/images/emoji/alembic.png
+++ b/public/-/emojis/1/alembic.png
Binary files differ
diff --git a/app/assets/images/emoji/alien.png b/public/-/emojis/1/alien.png
index 3b90e97433b..3b90e97433b 100644
--- a/app/assets/images/emoji/alien.png
+++ b/public/-/emojis/1/alien.png
Binary files differ
diff --git a/app/assets/images/emoji/ambulance.png b/public/-/emojis/1/ambulance.png
index 6fb8076d766..6fb8076d766 100644
--- a/app/assets/images/emoji/ambulance.png
+++ b/public/-/emojis/1/ambulance.png
Binary files differ
diff --git a/app/assets/images/emoji/amphora.png b/public/-/emojis/1/amphora.png
index 96de5056059..96de5056059 100644
--- a/app/assets/images/emoji/amphora.png
+++ b/public/-/emojis/1/amphora.png
Binary files differ
diff --git a/app/assets/images/emoji/anchor.png b/public/-/emojis/1/anchor.png
index b036f70a00b..b036f70a00b 100644
--- a/app/assets/images/emoji/anchor.png
+++ b/public/-/emojis/1/anchor.png
Binary files differ
diff --git a/app/assets/images/emoji/angel.png b/public/-/emojis/1/angel.png
index 66ea97a3b99..66ea97a3b99 100644
--- a/app/assets/images/emoji/angel.png
+++ b/public/-/emojis/1/angel.png
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone1.png b/public/-/emojis/1/angel_tone1.png
index 391694dc07e..391694dc07e 100644
--- a/app/assets/images/emoji/angel_tone1.png
+++ b/public/-/emojis/1/angel_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone2.png b/public/-/emojis/1/angel_tone2.png
index 700cbe6ed2c..700cbe6ed2c 100644
--- a/app/assets/images/emoji/angel_tone2.png
+++ b/public/-/emojis/1/angel_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone3.png b/public/-/emojis/1/angel_tone3.png
index be597437d25..be597437d25 100644
--- a/app/assets/images/emoji/angel_tone3.png
+++ b/public/-/emojis/1/angel_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone4.png b/public/-/emojis/1/angel_tone4.png
index b06d3c853ef..b06d3c853ef 100644
--- a/app/assets/images/emoji/angel_tone4.png
+++ b/public/-/emojis/1/angel_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone5.png b/public/-/emojis/1/angel_tone5.png
index 17bd677e334..17bd677e334 100644
--- a/app/assets/images/emoji/angel_tone5.png
+++ b/public/-/emojis/1/angel_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/anger.png b/public/-/emojis/1/anger.png
index d63c2e000e4..d63c2e000e4 100644
--- a/app/assets/images/emoji/anger.png
+++ b/public/-/emojis/1/anger.png
Binary files differ
diff --git a/app/assets/images/emoji/anger_right.png b/public/-/emojis/1/anger_right.png
index f5c97c4d297..f5c97c4d297 100644
--- a/app/assets/images/emoji/anger_right.png
+++ b/public/-/emojis/1/anger_right.png
Binary files differ
diff --git a/app/assets/images/emoji/angry.png b/public/-/emojis/1/angry.png
index cfc4a6ecde5..cfc4a6ecde5 100644
--- a/app/assets/images/emoji/angry.png
+++ b/public/-/emojis/1/angry.png
Binary files differ
diff --git a/app/assets/images/emoji/ant.png b/public/-/emojis/1/ant.png
index 994127ed6b3..994127ed6b3 100644
--- a/app/assets/images/emoji/ant.png
+++ b/public/-/emojis/1/ant.png
Binary files differ
diff --git a/app/assets/images/emoji/apple.png b/public/-/emojis/1/apple.png
index da650c60f62..da650c60f62 100644
--- a/app/assets/images/emoji/apple.png
+++ b/public/-/emojis/1/apple.png
Binary files differ
diff --git a/app/assets/images/emoji/aquarius.png b/public/-/emojis/1/aquarius.png
index 641a4f68889..641a4f68889 100644
--- a/app/assets/images/emoji/aquarius.png
+++ b/public/-/emojis/1/aquarius.png
Binary files differ
diff --git a/app/assets/images/emoji/aries.png b/public/-/emojis/1/aries.png
index 21a189d0ede..21a189d0ede 100644
--- a/app/assets/images/emoji/aries.png
+++ b/public/-/emojis/1/aries.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_backward.png b/public/-/emojis/1/arrow_backward.png
index ee38e3b038e..ee38e3b038e 100644
--- a/app/assets/images/emoji/arrow_backward.png
+++ b/public/-/emojis/1/arrow_backward.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_double_down.png b/public/-/emojis/1/arrow_double_down.png
index 90193bfcb40..90193bfcb40 100644
--- a/app/assets/images/emoji/arrow_double_down.png
+++ b/public/-/emojis/1/arrow_double_down.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_double_up.png b/public/-/emojis/1/arrow_double_up.png
index 13543d5eef2..13543d5eef2 100644
--- a/app/assets/images/emoji/arrow_double_up.png
+++ b/public/-/emojis/1/arrow_double_up.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_down.png b/public/-/emojis/1/arrow_down.png
index b8eefd0b19f..b8eefd0b19f 100644
--- a/app/assets/images/emoji/arrow_down.png
+++ b/public/-/emojis/1/arrow_down.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_down_small.png b/public/-/emojis/1/arrow_down_small.png
index 5870b9a2241..5870b9a2241 100644
--- a/app/assets/images/emoji/arrow_down_small.png
+++ b/public/-/emojis/1/arrow_down_small.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_forward.png b/public/-/emojis/1/arrow_forward.png
index 4e2b682857c..4e2b682857c 100644
--- a/app/assets/images/emoji/arrow_forward.png
+++ b/public/-/emojis/1/arrow_forward.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_heading_down.png b/public/-/emojis/1/arrow_heading_down.png
index 2d9d24bca80..2d9d24bca80 100644
--- a/app/assets/images/emoji/arrow_heading_down.png
+++ b/public/-/emojis/1/arrow_heading_down.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_heading_up.png b/public/-/emojis/1/arrow_heading_up.png
index f29bfcfc0de..f29bfcfc0de 100644
--- a/app/assets/images/emoji/arrow_heading_up.png
+++ b/public/-/emojis/1/arrow_heading_up.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_left.png b/public/-/emojis/1/arrow_left.png
index 8c685e0a81b..8c685e0a81b 100644
--- a/app/assets/images/emoji/arrow_left.png
+++ b/public/-/emojis/1/arrow_left.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_lower_left.png b/public/-/emojis/1/arrow_lower_left.png
index 88b37716078..88b37716078 100644
--- a/app/assets/images/emoji/arrow_lower_left.png
+++ b/public/-/emojis/1/arrow_lower_left.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_lower_right.png b/public/-/emojis/1/arrow_lower_right.png
index 7e807da7392..7e807da7392 100644
--- a/app/assets/images/emoji/arrow_lower_right.png
+++ b/public/-/emojis/1/arrow_lower_right.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_right.png b/public/-/emojis/1/arrow_right.png
index 4755670b5cc..4755670b5cc 100644
--- a/app/assets/images/emoji/arrow_right.png
+++ b/public/-/emojis/1/arrow_right.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_right_hook.png b/public/-/emojis/1/arrow_right_hook.png
index e7258ad3268..e7258ad3268 100644
--- a/app/assets/images/emoji/arrow_right_hook.png
+++ b/public/-/emojis/1/arrow_right_hook.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_up.png b/public/-/emojis/1/arrow_up.png
index af8218a87f7..af8218a87f7 100644
--- a/app/assets/images/emoji/arrow_up.png
+++ b/public/-/emojis/1/arrow_up.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_up_down.png b/public/-/emojis/1/arrow_up_down.png
index dfa32b97186..dfa32b97186 100644
--- a/app/assets/images/emoji/arrow_up_down.png
+++ b/public/-/emojis/1/arrow_up_down.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_up_small.png b/public/-/emojis/1/arrow_up_small.png
index 20a13dcd5cd..20a13dcd5cd 100644
--- a/app/assets/images/emoji/arrow_up_small.png
+++ b/public/-/emojis/1/arrow_up_small.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_upper_left.png b/public/-/emojis/1/arrow_upper_left.png
index f38718fbe34..f38718fbe34 100644
--- a/app/assets/images/emoji/arrow_upper_left.png
+++ b/public/-/emojis/1/arrow_upper_left.png
Binary files differ
diff --git a/app/assets/images/emoji/arrow_upper_right.png b/public/-/emojis/1/arrow_upper_right.png
index c43e12d0f64..c43e12d0f64 100644
--- a/app/assets/images/emoji/arrow_upper_right.png
+++ b/public/-/emojis/1/arrow_upper_right.png
Binary files differ
diff --git a/app/assets/images/emoji/arrows_clockwise.png b/public/-/emojis/1/arrows_clockwise.png
index 26e49c38388..26e49c38388 100644
--- a/app/assets/images/emoji/arrows_clockwise.png
+++ b/public/-/emojis/1/arrows_clockwise.png
Binary files differ
diff --git a/app/assets/images/emoji/arrows_counterclockwise.png b/public/-/emojis/1/arrows_counterclockwise.png
index 8d06d8e0912..8d06d8e0912 100644
--- a/app/assets/images/emoji/arrows_counterclockwise.png
+++ b/public/-/emojis/1/arrows_counterclockwise.png
Binary files differ
diff --git a/app/assets/images/emoji/art.png b/public/-/emojis/1/art.png
index bd6afe9ff06..bd6afe9ff06 100644
--- a/app/assets/images/emoji/art.png
+++ b/public/-/emojis/1/art.png
Binary files differ
diff --git a/app/assets/images/emoji/articulated_lorry.png b/public/-/emojis/1/articulated_lorry.png
index c8217317132..c8217317132 100644
--- a/app/assets/images/emoji/articulated_lorry.png
+++ b/public/-/emojis/1/articulated_lorry.png
Binary files differ
diff --git a/app/assets/images/emoji/asterisk.png b/public/-/emojis/1/asterisk.png
index 2f8e5113803..2f8e5113803 100644
--- a/app/assets/images/emoji/asterisk.png
+++ b/public/-/emojis/1/asterisk.png
Binary files differ
diff --git a/app/assets/images/emoji/astonished.png b/public/-/emojis/1/astonished.png
index bd0ac55ec8e..bd0ac55ec8e 100644
--- a/app/assets/images/emoji/astonished.png
+++ b/public/-/emojis/1/astonished.png
Binary files differ
diff --git a/app/assets/images/emoji/athletic_shoe.png b/public/-/emojis/1/athletic_shoe.png
index 423fa07dd5d..423fa07dd5d 100644
--- a/app/assets/images/emoji/athletic_shoe.png
+++ b/public/-/emojis/1/athletic_shoe.png
Binary files differ
diff --git a/app/assets/images/emoji/atm.png b/public/-/emojis/1/atm.png
index 4d935307b94..4d935307b94 100644
--- a/app/assets/images/emoji/atm.png
+++ b/public/-/emojis/1/atm.png
Binary files differ
diff --git a/app/assets/images/emoji/atom.png b/public/-/emojis/1/atom.png
index 5f4567aa093..5f4567aa093 100644
--- a/app/assets/images/emoji/atom.png
+++ b/public/-/emojis/1/atom.png
Binary files differ
diff --git a/app/assets/images/emoji/avocado.png b/public/-/emojis/1/avocado.png
index 06f0d124aed..06f0d124aed 100644
--- a/app/assets/images/emoji/avocado.png
+++ b/public/-/emojis/1/avocado.png
Binary files differ
diff --git a/app/assets/images/emoji/b.png b/public/-/emojis/1/b.png
index 25875bc6a14..25875bc6a14 100644
--- a/app/assets/images/emoji/b.png
+++ b/public/-/emojis/1/b.png
Binary files differ
diff --git a/app/assets/images/emoji/baby.png b/public/-/emojis/1/baby.png
index a4af92c63c7..a4af92c63c7 100644
--- a/app/assets/images/emoji/baby.png
+++ b/public/-/emojis/1/baby.png
Binary files differ
diff --git a/app/assets/images/emoji/baby_bottle.png b/public/-/emojis/1/baby_bottle.png
index 2bd10524180..2bd10524180 100644
--- a/app/assets/images/emoji/baby_bottle.png
+++ b/public/-/emojis/1/baby_bottle.png
Binary files differ
diff --git a/app/assets/images/emoji/baby_chick.png b/public/-/emojis/1/baby_chick.png
index dccd96576ea..dccd96576ea 100644
--- a/app/assets/images/emoji/baby_chick.png
+++ b/public/-/emojis/1/baby_chick.png
Binary files differ
diff --git a/app/assets/images/emoji/baby_symbol.png b/public/-/emojis/1/baby_symbol.png
index 64a10b71710..64a10b71710 100644
--- a/app/assets/images/emoji/baby_symbol.png
+++ b/public/-/emojis/1/baby_symbol.png
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone1.png b/public/-/emojis/1/baby_tone1.png
index d20911d40db..d20911d40db 100644
--- a/app/assets/images/emoji/baby_tone1.png
+++ b/public/-/emojis/1/baby_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone2.png b/public/-/emojis/1/baby_tone2.png
index b0a9b30ed17..b0a9b30ed17 100644
--- a/app/assets/images/emoji/baby_tone2.png
+++ b/public/-/emojis/1/baby_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone3.png b/public/-/emojis/1/baby_tone3.png
index 7de5286fac1..7de5286fac1 100644
--- a/app/assets/images/emoji/baby_tone3.png
+++ b/public/-/emojis/1/baby_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone4.png b/public/-/emojis/1/baby_tone4.png
index 9b7a86ac615..9b7a86ac615 100644
--- a/app/assets/images/emoji/baby_tone4.png
+++ b/public/-/emojis/1/baby_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone5.png b/public/-/emojis/1/baby_tone5.png
index fe1be34cb88..fe1be34cb88 100644
--- a/app/assets/images/emoji/baby_tone5.png
+++ b/public/-/emojis/1/baby_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/back.png b/public/-/emojis/1/back.png
index d32c5d4f17f..d32c5d4f17f 100644
--- a/app/assets/images/emoji/back.png
+++ b/public/-/emojis/1/back.png
Binary files differ
diff --git a/app/assets/images/emoji/bacon.png b/public/-/emojis/1/bacon.png
index f38a485fbe4..f38a485fbe4 100644
--- a/app/assets/images/emoji/bacon.png
+++ b/public/-/emojis/1/bacon.png
Binary files differ
diff --git a/app/assets/images/emoji/badminton.png b/public/-/emojis/1/badminton.png
index 7ba15708990..7ba15708990 100644
--- a/app/assets/images/emoji/badminton.png
+++ b/public/-/emojis/1/badminton.png
Binary files differ
diff --git a/app/assets/images/emoji/baggage_claim.png b/public/-/emojis/1/baggage_claim.png
index 409b593e78a..409b593e78a 100644
--- a/app/assets/images/emoji/baggage_claim.png
+++ b/public/-/emojis/1/baggage_claim.png
Binary files differ
diff --git a/app/assets/images/emoji/balloon.png b/public/-/emojis/1/balloon.png
index 07916fe6df1..07916fe6df1 100644
--- a/app/assets/images/emoji/balloon.png
+++ b/public/-/emojis/1/balloon.png
Binary files differ
diff --git a/app/assets/images/emoji/ballot_box.png b/public/-/emojis/1/ballot_box.png
index 9b6767aea9e..9b6767aea9e 100644
--- a/app/assets/images/emoji/ballot_box.png
+++ b/public/-/emojis/1/ballot_box.png
Binary files differ
diff --git a/app/assets/images/emoji/ballot_box_with_check.png b/public/-/emojis/1/ballot_box_with_check.png
index 284d9573847..284d9573847 100644
--- a/app/assets/images/emoji/ballot_box_with_check.png
+++ b/public/-/emojis/1/ballot_box_with_check.png
Binary files differ
diff --git a/app/assets/images/emoji/bamboo.png b/public/-/emojis/1/bamboo.png
index 5d5e0e728a0..5d5e0e728a0 100644
--- a/app/assets/images/emoji/bamboo.png
+++ b/public/-/emojis/1/bamboo.png
Binary files differ
diff --git a/app/assets/images/emoji/banana.png b/public/-/emojis/1/banana.png
index f4987279580..f4987279580 100644
--- a/app/assets/images/emoji/banana.png
+++ b/public/-/emojis/1/banana.png
Binary files differ
diff --git a/app/assets/images/emoji/bangbang.png b/public/-/emojis/1/bangbang.png
index 58a9c528fca..58a9c528fca 100644
--- a/app/assets/images/emoji/bangbang.png
+++ b/public/-/emojis/1/bangbang.png
Binary files differ
diff --git a/app/assets/images/emoji/bank.png b/public/-/emojis/1/bank.png
index dffdcef36a1..dffdcef36a1 100644
--- a/app/assets/images/emoji/bank.png
+++ b/public/-/emojis/1/bank.png
Binary files differ
diff --git a/app/assets/images/emoji/bar_chart.png b/public/-/emojis/1/bar_chart.png
index 53c89455008..53c89455008 100644
--- a/app/assets/images/emoji/bar_chart.png
+++ b/public/-/emojis/1/bar_chart.png
Binary files differ
diff --git a/app/assets/images/emoji/barber.png b/public/-/emojis/1/barber.png
index 896f4d716cf..896f4d716cf 100644
--- a/app/assets/images/emoji/barber.png
+++ b/public/-/emojis/1/barber.png
Binary files differ
diff --git a/app/assets/images/emoji/baseball.png b/public/-/emojis/1/baseball.png
index f8463f1538b..f8463f1538b 100644
--- a/app/assets/images/emoji/baseball.png
+++ b/public/-/emojis/1/baseball.png
Binary files differ
diff --git a/app/assets/images/emoji/basketball.png b/public/-/emojis/1/basketball.png
index 64c76b79c6d..64c76b79c6d 100644
--- a/app/assets/images/emoji/basketball.png
+++ b/public/-/emojis/1/basketball.png
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player.png b/public/-/emojis/1/basketball_player.png
index 8ce90c5cad6..8ce90c5cad6 100644
--- a/app/assets/images/emoji/basketball_player.png
+++ b/public/-/emojis/1/basketball_player.png
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone1.png b/public/-/emojis/1/basketball_player_tone1.png
index cd12c7ab9bf..cd12c7ab9bf 100644
--- a/app/assets/images/emoji/basketball_player_tone1.png
+++ b/public/-/emojis/1/basketball_player_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone2.png b/public/-/emojis/1/basketball_player_tone2.png
index f892fd596da..f892fd596da 100644
--- a/app/assets/images/emoji/basketball_player_tone2.png
+++ b/public/-/emojis/1/basketball_player_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone3.png b/public/-/emojis/1/basketball_player_tone3.png
index e109997a91a..e109997a91a 100644
--- a/app/assets/images/emoji/basketball_player_tone3.png
+++ b/public/-/emojis/1/basketball_player_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone4.png b/public/-/emojis/1/basketball_player_tone4.png
index 3b90b946af4..3b90b946af4 100644
--- a/app/assets/images/emoji/basketball_player_tone4.png
+++ b/public/-/emojis/1/basketball_player_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone5.png b/public/-/emojis/1/basketball_player_tone5.png
index bafed7828a7..bafed7828a7 100644
--- a/app/assets/images/emoji/basketball_player_tone5.png
+++ b/public/-/emojis/1/basketball_player_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/bat.png b/public/-/emojis/1/bat.png
index 3152c047e00..3152c047e00 100644
--- a/app/assets/images/emoji/bat.png
+++ b/public/-/emojis/1/bat.png
Binary files differ
diff --git a/app/assets/images/emoji/bath.png b/public/-/emojis/1/bath.png
index 43fba5c8a28..43fba5c8a28 100644
--- a/app/assets/images/emoji/bath.png
+++ b/public/-/emojis/1/bath.png
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone1.png b/public/-/emojis/1/bath_tone1.png
index 2152eabf2f5..2152eabf2f5 100644
--- a/app/assets/images/emoji/bath_tone1.png
+++ b/public/-/emojis/1/bath_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone2.png b/public/-/emojis/1/bath_tone2.png
index 2102e6133e3..2102e6133e3 100644
--- a/app/assets/images/emoji/bath_tone2.png
+++ b/public/-/emojis/1/bath_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone3.png b/public/-/emojis/1/bath_tone3.png
index fae66181e9f..fae66181e9f 100644
--- a/app/assets/images/emoji/bath_tone3.png
+++ b/public/-/emojis/1/bath_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone4.png b/public/-/emojis/1/bath_tone4.png
index 1f8959d0d99..1f8959d0d99 100644
--- a/app/assets/images/emoji/bath_tone4.png
+++ b/public/-/emojis/1/bath_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone5.png b/public/-/emojis/1/bath_tone5.png
index c8a08e84f25..c8a08e84f25 100644
--- a/app/assets/images/emoji/bath_tone5.png
+++ b/public/-/emojis/1/bath_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/bathtub.png b/public/-/emojis/1/bathtub.png
index 9a5f09361eb..9a5f09361eb 100644
--- a/app/assets/images/emoji/bathtub.png
+++ b/public/-/emojis/1/bathtub.png
Binary files differ
diff --git a/app/assets/images/emoji/battery.png b/public/-/emojis/1/battery.png
index f593e2bdb65..f593e2bdb65 100644
--- a/app/assets/images/emoji/battery.png
+++ b/public/-/emojis/1/battery.png
Binary files differ
diff --git a/app/assets/images/emoji/beach.png b/public/-/emojis/1/beach.png
index 69108c8ea10..69108c8ea10 100644
--- a/app/assets/images/emoji/beach.png
+++ b/public/-/emojis/1/beach.png
Binary files differ
diff --git a/app/assets/images/emoji/beach_umbrella.png b/public/-/emojis/1/beach_umbrella.png
index 220a74f8132..220a74f8132 100644
--- a/app/assets/images/emoji/beach_umbrella.png
+++ b/public/-/emojis/1/beach_umbrella.png
Binary files differ
diff --git a/app/assets/images/emoji/bear.png b/public/-/emojis/1/bear.png
index 272d56bbbcc..272d56bbbcc 100644
--- a/app/assets/images/emoji/bear.png
+++ b/public/-/emojis/1/bear.png
Binary files differ
diff --git a/app/assets/images/emoji/bed.png b/public/-/emojis/1/bed.png
index 86f964e245d..86f964e245d 100644
--- a/app/assets/images/emoji/bed.png
+++ b/public/-/emojis/1/bed.png
Binary files differ
diff --git a/app/assets/images/emoji/bee.png b/public/-/emojis/1/bee.png
index 46156060096..46156060096 100644
--- a/app/assets/images/emoji/bee.png
+++ b/public/-/emojis/1/bee.png
Binary files differ
diff --git a/app/assets/images/emoji/beer.png b/public/-/emojis/1/beer.png
index b6d73dc0b7a..b6d73dc0b7a 100644
--- a/app/assets/images/emoji/beer.png
+++ b/public/-/emojis/1/beer.png
Binary files differ
diff --git a/app/assets/images/emoji/beers.png b/public/-/emojis/1/beers.png
index b55deb66b41..b55deb66b41 100644
--- a/app/assets/images/emoji/beers.png
+++ b/public/-/emojis/1/beers.png
Binary files differ
diff --git a/app/assets/images/emoji/beetle.png b/public/-/emojis/1/beetle.png
index 3d93174d7fc..3d93174d7fc 100644
--- a/app/assets/images/emoji/beetle.png
+++ b/public/-/emojis/1/beetle.png
Binary files differ
diff --git a/app/assets/images/emoji/beginner.png b/public/-/emojis/1/beginner.png
index bc434fb7cb5..bc434fb7cb5 100644
--- a/app/assets/images/emoji/beginner.png
+++ b/public/-/emojis/1/beginner.png
Binary files differ
diff --git a/app/assets/images/emoji/bell.png b/public/-/emojis/1/bell.png
index 5b3b0461999..5b3b0461999 100644
--- a/app/assets/images/emoji/bell.png
+++ b/public/-/emojis/1/bell.png
Binary files differ
diff --git a/app/assets/images/emoji/bellhop.png b/public/-/emojis/1/bellhop.png
index 6b3297ceaf7..6b3297ceaf7 100644
--- a/app/assets/images/emoji/bellhop.png
+++ b/public/-/emojis/1/bellhop.png
Binary files differ
diff --git a/app/assets/images/emoji/bento.png b/public/-/emojis/1/bento.png
index 83d41ca7eb9..83d41ca7eb9 100644
--- a/app/assets/images/emoji/bento.png
+++ b/public/-/emojis/1/bento.png
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist.png b/public/-/emojis/1/bicyclist.png
index 9274da11048..9274da11048 100644
--- a/app/assets/images/emoji/bicyclist.png
+++ b/public/-/emojis/1/bicyclist.png
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone1.png b/public/-/emojis/1/bicyclist_tone1.png
index decc2f728fe..decc2f728fe 100644
--- a/app/assets/images/emoji/bicyclist_tone1.png
+++ b/public/-/emojis/1/bicyclist_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone2.png b/public/-/emojis/1/bicyclist_tone2.png
index 0067717b80a..0067717b80a 100644
--- a/app/assets/images/emoji/bicyclist_tone2.png
+++ b/public/-/emojis/1/bicyclist_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone3.png b/public/-/emojis/1/bicyclist_tone3.png
index a4f7b5e2776..a4f7b5e2776 100644
--- a/app/assets/images/emoji/bicyclist_tone3.png
+++ b/public/-/emojis/1/bicyclist_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone4.png b/public/-/emojis/1/bicyclist_tone4.png
index a3c8a797db4..a3c8a797db4 100644
--- a/app/assets/images/emoji/bicyclist_tone4.png
+++ b/public/-/emojis/1/bicyclist_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone5.png b/public/-/emojis/1/bicyclist_tone5.png
index 1606a874051..1606a874051 100644
--- a/app/assets/images/emoji/bicyclist_tone5.png
+++ b/public/-/emojis/1/bicyclist_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/bike.png b/public/-/emojis/1/bike.png
index 556ed70f1a7..556ed70f1a7 100644
--- a/app/assets/images/emoji/bike.png
+++ b/public/-/emojis/1/bike.png
Binary files differ
diff --git a/app/assets/images/emoji/bikini.png b/public/-/emojis/1/bikini.png
index 77a8a0aae5b..77a8a0aae5b 100644
--- a/app/assets/images/emoji/bikini.png
+++ b/public/-/emojis/1/bikini.png
Binary files differ
diff --git a/app/assets/images/emoji/biohazard.png b/public/-/emojis/1/biohazard.png
index 007b4fc2d85..007b4fc2d85 100644
--- a/app/assets/images/emoji/biohazard.png
+++ b/public/-/emojis/1/biohazard.png
Binary files differ
diff --git a/app/assets/images/emoji/bird.png b/public/-/emojis/1/bird.png
index e201c22be33..e201c22be33 100644
--- a/app/assets/images/emoji/bird.png
+++ b/public/-/emojis/1/bird.png
Binary files differ
diff --git a/app/assets/images/emoji/birthday.png b/public/-/emojis/1/birthday.png
index 317e9a41949..317e9a41949 100644
--- a/app/assets/images/emoji/birthday.png
+++ b/public/-/emojis/1/birthday.png
Binary files differ
diff --git a/app/assets/images/emoji/black_circle.png b/public/-/emojis/1/black_circle.png
index b62b87170e8..b62b87170e8 100644
--- a/app/assets/images/emoji/black_circle.png
+++ b/public/-/emojis/1/black_circle.png
Binary files differ
diff --git a/app/assets/images/emoji/black_heart.png b/public/-/emojis/1/black_heart.png
index b4068c3e6e8..b4068c3e6e8 100644
--- a/app/assets/images/emoji/black_heart.png
+++ b/public/-/emojis/1/black_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/black_joker.png b/public/-/emojis/1/black_joker.png
index 3d0924b68aa..3d0924b68aa 100644
--- a/app/assets/images/emoji/black_joker.png
+++ b/public/-/emojis/1/black_joker.png
Binary files differ
diff --git a/app/assets/images/emoji/black_large_square.png b/public/-/emojis/1/black_large_square.png
index 162f2bb4290..162f2bb4290 100644
--- a/app/assets/images/emoji/black_large_square.png
+++ b/public/-/emojis/1/black_large_square.png
Binary files differ
diff --git a/app/assets/images/emoji/black_medium_small_square.png b/public/-/emojis/1/black_medium_small_square.png
index 39765bba610..39765bba610 100644
--- a/app/assets/images/emoji/black_medium_small_square.png
+++ b/public/-/emojis/1/black_medium_small_square.png
Binary files differ
diff --git a/app/assets/images/emoji/black_medium_square.png b/public/-/emojis/1/black_medium_square.png
index 05a30a6aa2d..05a30a6aa2d 100644
--- a/app/assets/images/emoji/black_medium_square.png
+++ b/public/-/emojis/1/black_medium_square.png
Binary files differ
diff --git a/app/assets/images/emoji/black_nib.png b/public/-/emojis/1/black_nib.png
index 872d0ae1598..872d0ae1598 100644
--- a/app/assets/images/emoji/black_nib.png
+++ b/public/-/emojis/1/black_nib.png
Binary files differ
diff --git a/app/assets/images/emoji/black_small_square.png b/public/-/emojis/1/black_small_square.png
index 48595d3e1a9..48595d3e1a9 100644
--- a/app/assets/images/emoji/black_small_square.png
+++ b/public/-/emojis/1/black_small_square.png
Binary files differ
diff --git a/app/assets/images/emoji/black_square_button.png b/public/-/emojis/1/black_square_button.png
index a78fc2f6b63..a78fc2f6b63 100644
--- a/app/assets/images/emoji/black_square_button.png
+++ b/public/-/emojis/1/black_square_button.png
Binary files differ
diff --git a/app/assets/images/emoji/blossom.png b/public/-/emojis/1/blossom.png
index 4083026c157..4083026c157 100644
--- a/app/assets/images/emoji/blossom.png
+++ b/public/-/emojis/1/blossom.png
Binary files differ
diff --git a/app/assets/images/emoji/blowfish.png b/public/-/emojis/1/blowfish.png
index a10f4f84e35..a10f4f84e35 100644
--- a/app/assets/images/emoji/blowfish.png
+++ b/public/-/emojis/1/blowfish.png
Binary files differ
diff --git a/app/assets/images/emoji/blue_book.png b/public/-/emojis/1/blue_book.png
index e1e455401cc..e1e455401cc 100644
--- a/app/assets/images/emoji/blue_book.png
+++ b/public/-/emojis/1/blue_book.png
Binary files differ
diff --git a/app/assets/images/emoji/blue_car.png b/public/-/emojis/1/blue_car.png
index e8ba817d393..e8ba817d393 100644
--- a/app/assets/images/emoji/blue_car.png
+++ b/public/-/emojis/1/blue_car.png
Binary files differ
diff --git a/app/assets/images/emoji/blue_heart.png b/public/-/emojis/1/blue_heart.png
index bdf1287e55e..bdf1287e55e 100644
--- a/app/assets/images/emoji/blue_heart.png
+++ b/public/-/emojis/1/blue_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/blush.png b/public/-/emojis/1/blush.png
index aac1a424ad4..aac1a424ad4 100644
--- a/app/assets/images/emoji/blush.png
+++ b/public/-/emojis/1/blush.png
Binary files differ
diff --git a/app/assets/images/emoji/boar.png b/public/-/emojis/1/boar.png
index fead972633c..fead972633c 100644
--- a/app/assets/images/emoji/boar.png
+++ b/public/-/emojis/1/boar.png
Binary files differ
diff --git a/app/assets/images/emoji/bomb.png b/public/-/emojis/1/bomb.png
index c7f8f81c939..c7f8f81c939 100644
--- a/app/assets/images/emoji/bomb.png
+++ b/public/-/emojis/1/bomb.png
Binary files differ
diff --git a/app/assets/images/emoji/book.png b/public/-/emojis/1/book.png
index 0f4447ed396..0f4447ed396 100644
--- a/app/assets/images/emoji/book.png
+++ b/public/-/emojis/1/book.png
Binary files differ
diff --git a/app/assets/images/emoji/bookmark.png b/public/-/emojis/1/bookmark.png
index bbb444611f0..bbb444611f0 100644
--- a/app/assets/images/emoji/bookmark.png
+++ b/public/-/emojis/1/bookmark.png
Binary files differ
diff --git a/app/assets/images/emoji/bookmark_tabs.png b/public/-/emojis/1/bookmark_tabs.png
index f8d9e01b428..f8d9e01b428 100644
--- a/app/assets/images/emoji/bookmark_tabs.png
+++ b/public/-/emojis/1/bookmark_tabs.png
Binary files differ
diff --git a/app/assets/images/emoji/books.png b/public/-/emojis/1/books.png
index 59a8bafeb0d..59a8bafeb0d 100644
--- a/app/assets/images/emoji/books.png
+++ b/public/-/emojis/1/books.png
Binary files differ
diff --git a/app/assets/images/emoji/boom.png b/public/-/emojis/1/boom.png
index 9b0f027b1a8..9b0f027b1a8 100644
--- a/app/assets/images/emoji/boom.png
+++ b/public/-/emojis/1/boom.png
Binary files differ
diff --git a/app/assets/images/emoji/boot.png b/public/-/emojis/1/boot.png
index 11f1065ed07..11f1065ed07 100644
--- a/app/assets/images/emoji/boot.png
+++ b/public/-/emojis/1/boot.png
Binary files differ
diff --git a/app/assets/images/emoji/bouquet.png b/public/-/emojis/1/bouquet.png
index 11455af6df4..11455af6df4 100644
--- a/app/assets/images/emoji/bouquet.png
+++ b/public/-/emojis/1/bouquet.png
Binary files differ
diff --git a/app/assets/images/emoji/bow.png b/public/-/emojis/1/bow.png
index d8f793088dc..d8f793088dc 100644
--- a/app/assets/images/emoji/bow.png
+++ b/public/-/emojis/1/bow.png
Binary files differ
diff --git a/app/assets/images/emoji/bow_and_arrow.png b/public/-/emojis/1/bow_and_arrow.png
index 6a538bf475f..6a538bf475f 100644
--- a/app/assets/images/emoji/bow_and_arrow.png
+++ b/public/-/emojis/1/bow_and_arrow.png
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone1.png b/public/-/emojis/1/bow_tone1.png
index 87afb7b54cf..87afb7b54cf 100644
--- a/app/assets/images/emoji/bow_tone1.png
+++ b/public/-/emojis/1/bow_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone2.png b/public/-/emojis/1/bow_tone2.png
index 3ccf7dc0850..3ccf7dc0850 100644
--- a/app/assets/images/emoji/bow_tone2.png
+++ b/public/-/emojis/1/bow_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone3.png b/public/-/emojis/1/bow_tone3.png
index 8b9eb64f926..8b9eb64f926 100644
--- a/app/assets/images/emoji/bow_tone3.png
+++ b/public/-/emojis/1/bow_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone4.png b/public/-/emojis/1/bow_tone4.png
index 683795ff40d..683795ff40d 100644
--- a/app/assets/images/emoji/bow_tone4.png
+++ b/public/-/emojis/1/bow_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone5.png b/public/-/emojis/1/bow_tone5.png
index 7969d971752..7969d971752 100644
--- a/app/assets/images/emoji/bow_tone5.png
+++ b/public/-/emojis/1/bow_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/bowling.png b/public/-/emojis/1/bowling.png
index 63add89e53b..63add89e53b 100644
--- a/app/assets/images/emoji/bowling.png
+++ b/public/-/emojis/1/bowling.png
Binary files differ
diff --git a/app/assets/images/emoji/boxing_glove.png b/public/-/emojis/1/boxing_glove.png
index 9838f24e51a..9838f24e51a 100644
--- a/app/assets/images/emoji/boxing_glove.png
+++ b/public/-/emojis/1/boxing_glove.png
Binary files differ
diff --git a/app/assets/images/emoji/boy.png b/public/-/emojis/1/boy.png
index 8ecfb0a4e92..8ecfb0a4e92 100644
--- a/app/assets/images/emoji/boy.png
+++ b/public/-/emojis/1/boy.png
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone1.png b/public/-/emojis/1/boy_tone1.png
index 2fc436ea512..2fc436ea512 100644
--- a/app/assets/images/emoji/boy_tone1.png
+++ b/public/-/emojis/1/boy_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone2.png b/public/-/emojis/1/boy_tone2.png
index 09a5f18d360..09a5f18d360 100644
--- a/app/assets/images/emoji/boy_tone2.png
+++ b/public/-/emojis/1/boy_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone3.png b/public/-/emojis/1/boy_tone3.png
index 3cfe675dd3a..3cfe675dd3a 100644
--- a/app/assets/images/emoji/boy_tone3.png
+++ b/public/-/emojis/1/boy_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone4.png b/public/-/emojis/1/boy_tone4.png
index 780be0ace36..780be0ace36 100644
--- a/app/assets/images/emoji/boy_tone4.png
+++ b/public/-/emojis/1/boy_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone5.png b/public/-/emojis/1/boy_tone5.png
index f32fe22e35c..f32fe22e35c 100644
--- a/app/assets/images/emoji/boy_tone5.png
+++ b/public/-/emojis/1/boy_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/bread.png b/public/-/emojis/1/bread.png
index 6676510aaa5..6676510aaa5 100644
--- a/app/assets/images/emoji/bread.png
+++ b/public/-/emojis/1/bread.png
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil.png b/public/-/emojis/1/bride_with_veil.png
index eaf4bd97890..eaf4bd97890 100644
--- a/app/assets/images/emoji/bride_with_veil.png
+++ b/public/-/emojis/1/bride_with_veil.png
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone1.png b/public/-/emojis/1/bride_with_veil_tone1.png
index c4fb141ae8f..c4fb141ae8f 100644
--- a/app/assets/images/emoji/bride_with_veil_tone1.png
+++ b/public/-/emojis/1/bride_with_veil_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone2.png b/public/-/emojis/1/bride_with_veil_tone2.png
index c248769fc06..c248769fc06 100644
--- a/app/assets/images/emoji/bride_with_veil_tone2.png
+++ b/public/-/emojis/1/bride_with_veil_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone3.png b/public/-/emojis/1/bride_with_veil_tone3.png
index 962c0a6eedb..962c0a6eedb 100644
--- a/app/assets/images/emoji/bride_with_veil_tone3.png
+++ b/public/-/emojis/1/bride_with_veil_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone4.png b/public/-/emojis/1/bride_with_veil_tone4.png
index 740ca208cd4..740ca208cd4 100644
--- a/app/assets/images/emoji/bride_with_veil_tone4.png
+++ b/public/-/emojis/1/bride_with_veil_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone5.png b/public/-/emojis/1/bride_with_veil_tone5.png
index 5cc5598587d..5cc5598587d 100644
--- a/app/assets/images/emoji/bride_with_veil_tone5.png
+++ b/public/-/emojis/1/bride_with_veil_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/bridge_at_night.png b/public/-/emojis/1/bridge_at_night.png
index 1d444e0be65..1d444e0be65 100644
--- a/app/assets/images/emoji/bridge_at_night.png
+++ b/public/-/emojis/1/bridge_at_night.png
Binary files differ
diff --git a/app/assets/images/emoji/briefcase.png b/public/-/emojis/1/briefcase.png
index b9912ba2148..b9912ba2148 100644
--- a/app/assets/images/emoji/briefcase.png
+++ b/public/-/emojis/1/briefcase.png
Binary files differ
diff --git a/app/assets/images/emoji/broken_heart.png b/public/-/emojis/1/broken_heart.png
index 718e26ee122..718e26ee122 100644
--- a/app/assets/images/emoji/broken_heart.png
+++ b/public/-/emojis/1/broken_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/bug.png b/public/-/emojis/1/bug.png
index e64e72f259a..e64e72f259a 100644
--- a/app/assets/images/emoji/bug.png
+++ b/public/-/emojis/1/bug.png
Binary files differ
diff --git a/app/assets/images/emoji/bulb.png b/public/-/emojis/1/bulb.png
index 38e32e02d9f..38e32e02d9f 100644
--- a/app/assets/images/emoji/bulb.png
+++ b/public/-/emojis/1/bulb.png
Binary files differ
diff --git a/app/assets/images/emoji/bullettrain_front.png b/public/-/emojis/1/bullettrain_front.png
index 4f698e056fa..4f698e056fa 100644
--- a/app/assets/images/emoji/bullettrain_front.png
+++ b/public/-/emojis/1/bullettrain_front.png
Binary files differ
diff --git a/app/assets/images/emoji/bullettrain_side.png b/public/-/emojis/1/bullettrain_side.png
index ed61c67bf07..ed61c67bf07 100644
--- a/app/assets/images/emoji/bullettrain_side.png
+++ b/public/-/emojis/1/bullettrain_side.png
Binary files differ
diff --git a/app/assets/images/emoji/burrito.png b/public/-/emojis/1/burrito.png
index 02bd5601df7..02bd5601df7 100644
--- a/app/assets/images/emoji/burrito.png
+++ b/public/-/emojis/1/burrito.png
Binary files differ
diff --git a/app/assets/images/emoji/bus.png b/public/-/emojis/1/bus.png
index 641ddc56ca7..641ddc56ca7 100644
--- a/app/assets/images/emoji/bus.png
+++ b/public/-/emojis/1/bus.png
Binary files differ
diff --git a/app/assets/images/emoji/busstop.png b/public/-/emojis/1/busstop.png
index b2b62208bfd..b2b62208bfd 100644
--- a/app/assets/images/emoji/busstop.png
+++ b/public/-/emojis/1/busstop.png
Binary files differ
diff --git a/app/assets/images/emoji/bust_in_silhouette.png b/public/-/emojis/1/bust_in_silhouette.png
index 123b2cbe1fb..123b2cbe1fb 100644
--- a/app/assets/images/emoji/bust_in_silhouette.png
+++ b/public/-/emojis/1/bust_in_silhouette.png
Binary files differ
diff --git a/app/assets/images/emoji/busts_in_silhouette.png b/public/-/emojis/1/busts_in_silhouette.png
index d7656860a1c..d7656860a1c 100644
--- a/app/assets/images/emoji/busts_in_silhouette.png
+++ b/public/-/emojis/1/busts_in_silhouette.png
Binary files differ
diff --git a/app/assets/images/emoji/butterfly.png b/public/-/emojis/1/butterfly.png
index 5631fe99226..5631fe99226 100644
--- a/app/assets/images/emoji/butterfly.png
+++ b/public/-/emojis/1/butterfly.png
Binary files differ
diff --git a/app/assets/images/emoji/cactus.png b/public/-/emojis/1/cactus.png
index 9b48ccf3d0c..9b48ccf3d0c 100644
--- a/app/assets/images/emoji/cactus.png
+++ b/public/-/emojis/1/cactus.png
Binary files differ
diff --git a/app/assets/images/emoji/cake.png b/public/-/emojis/1/cake.png
index 4368177be9a..4368177be9a 100644
--- a/app/assets/images/emoji/cake.png
+++ b/public/-/emojis/1/cake.png
Binary files differ
diff --git a/app/assets/images/emoji/calendar.png b/public/-/emojis/1/calendar.png
index 47353b74447..47353b74447 100644
--- a/app/assets/images/emoji/calendar.png
+++ b/public/-/emojis/1/calendar.png
Binary files differ
diff --git a/app/assets/images/emoji/calendar_spiral.png b/public/-/emojis/1/calendar_spiral.png
index dec8d49bfa8..dec8d49bfa8 100644
--- a/app/assets/images/emoji/calendar_spiral.png
+++ b/public/-/emojis/1/calendar_spiral.png
Binary files differ
diff --git a/app/assets/images/emoji/call_me.png b/public/-/emojis/1/call_me.png
index a10c59ba711..a10c59ba711 100644
--- a/app/assets/images/emoji/call_me.png
+++ b/public/-/emojis/1/call_me.png
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone1.png b/public/-/emojis/1/call_me_tone1.png
index 2c93201181a..2c93201181a 100644
--- a/app/assets/images/emoji/call_me_tone1.png
+++ b/public/-/emojis/1/call_me_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone2.png b/public/-/emojis/1/call_me_tone2.png
index c39f45a41ed..c39f45a41ed 100644
--- a/app/assets/images/emoji/call_me_tone2.png
+++ b/public/-/emojis/1/call_me_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone3.png b/public/-/emojis/1/call_me_tone3.png
index 83a57f63c29..83a57f63c29 100644
--- a/app/assets/images/emoji/call_me_tone3.png
+++ b/public/-/emojis/1/call_me_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone4.png b/public/-/emojis/1/call_me_tone4.png
index 65b3468fe44..65b3468fe44 100644
--- a/app/assets/images/emoji/call_me_tone4.png
+++ b/public/-/emojis/1/call_me_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone5.png b/public/-/emojis/1/call_me_tone5.png
index 94ef68ff3b3..94ef68ff3b3 100644
--- a/app/assets/images/emoji/call_me_tone5.png
+++ b/public/-/emojis/1/call_me_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/calling.png b/public/-/emojis/1/calling.png
index e2f308f8e46..e2f308f8e46 100644
--- a/app/assets/images/emoji/calling.png
+++ b/public/-/emojis/1/calling.png
Binary files differ
diff --git a/app/assets/images/emoji/camel.png b/public/-/emojis/1/camel.png
index b421d07a805..b421d07a805 100644
--- a/app/assets/images/emoji/camel.png
+++ b/public/-/emojis/1/camel.png
Binary files differ
diff --git a/app/assets/images/emoji/camera.png b/public/-/emojis/1/camera.png
index 0a3429f72ef..0a3429f72ef 100644
--- a/app/assets/images/emoji/camera.png
+++ b/public/-/emojis/1/camera.png
Binary files differ
diff --git a/app/assets/images/emoji/camera_with_flash.png b/public/-/emojis/1/camera_with_flash.png
index 27471da2029..27471da2029 100644
--- a/app/assets/images/emoji/camera_with_flash.png
+++ b/public/-/emojis/1/camera_with_flash.png
Binary files differ
diff --git a/app/assets/images/emoji/camping.png b/public/-/emojis/1/camping.png
index d589cc1f44b..d589cc1f44b 100644
--- a/app/assets/images/emoji/camping.png
+++ b/public/-/emojis/1/camping.png
Binary files differ
diff --git a/app/assets/images/emoji/cancer.png b/public/-/emojis/1/cancer.png
index a64af07cb5f..a64af07cb5f 100644
--- a/app/assets/images/emoji/cancer.png
+++ b/public/-/emojis/1/cancer.png
Binary files differ
diff --git a/app/assets/images/emoji/candle.png b/public/-/emojis/1/candle.png
index 0b56444e355..0b56444e355 100644
--- a/app/assets/images/emoji/candle.png
+++ b/public/-/emojis/1/candle.png
Binary files differ
diff --git a/app/assets/images/emoji/candy.png b/public/-/emojis/1/candy.png
index 8c67ace3a35..8c67ace3a35 100644
--- a/app/assets/images/emoji/candy.png
+++ b/public/-/emojis/1/candy.png
Binary files differ
diff --git a/app/assets/images/emoji/canoe.png b/public/-/emojis/1/canoe.png
index e26cdb9da69..e26cdb9da69 100644
--- a/app/assets/images/emoji/canoe.png
+++ b/public/-/emojis/1/canoe.png
Binary files differ
diff --git a/app/assets/images/emoji/capital_abcd.png b/public/-/emojis/1/capital_abcd.png
index fe9482d2d8a..fe9482d2d8a 100644
--- a/app/assets/images/emoji/capital_abcd.png
+++ b/public/-/emojis/1/capital_abcd.png
Binary files differ
diff --git a/app/assets/images/emoji/capricorn.png b/public/-/emojis/1/capricorn.png
index 6293d31d4b1..6293d31d4b1 100644
--- a/app/assets/images/emoji/capricorn.png
+++ b/public/-/emojis/1/capricorn.png
Binary files differ
diff --git a/app/assets/images/emoji/card_box.png b/public/-/emojis/1/card_box.png
index f2e764ce59d..f2e764ce59d 100644
--- a/app/assets/images/emoji/card_box.png
+++ b/public/-/emojis/1/card_box.png
Binary files differ
diff --git a/app/assets/images/emoji/card_index.png b/public/-/emojis/1/card_index.png
index 151e11cb3b4..151e11cb3b4 100644
--- a/app/assets/images/emoji/card_index.png
+++ b/public/-/emojis/1/card_index.png
Binary files differ
diff --git a/app/assets/images/emoji/carousel_horse.png b/public/-/emojis/1/carousel_horse.png
index a17074edf05..a17074edf05 100644
--- a/app/assets/images/emoji/carousel_horse.png
+++ b/public/-/emojis/1/carousel_horse.png
Binary files differ
diff --git a/app/assets/images/emoji/carrot.png b/public/-/emojis/1/carrot.png
index c68829b58e7..c68829b58e7 100644
--- a/app/assets/images/emoji/carrot.png
+++ b/public/-/emojis/1/carrot.png
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel.png b/public/-/emojis/1/cartwheel.png
index cbcaa578253..cbcaa578253 100644
--- a/app/assets/images/emoji/cartwheel.png
+++ b/public/-/emojis/1/cartwheel.png
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone1.png b/public/-/emojis/1/cartwheel_tone1.png
index db6d65895fb..db6d65895fb 100644
--- a/app/assets/images/emoji/cartwheel_tone1.png
+++ b/public/-/emojis/1/cartwheel_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone2.png b/public/-/emojis/1/cartwheel_tone2.png
index e00ffbc27a8..e00ffbc27a8 100644
--- a/app/assets/images/emoji/cartwheel_tone2.png
+++ b/public/-/emojis/1/cartwheel_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone3.png b/public/-/emojis/1/cartwheel_tone3.png
index 49321be391f..49321be391f 100644
--- a/app/assets/images/emoji/cartwheel_tone3.png
+++ b/public/-/emojis/1/cartwheel_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone4.png b/public/-/emojis/1/cartwheel_tone4.png
index d4562b5e3dd..d4562b5e3dd 100644
--- a/app/assets/images/emoji/cartwheel_tone4.png
+++ b/public/-/emojis/1/cartwheel_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone5.png b/public/-/emojis/1/cartwheel_tone5.png
index 6e09a870767..6e09a870767 100644
--- a/app/assets/images/emoji/cartwheel_tone5.png
+++ b/public/-/emojis/1/cartwheel_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/cat.png b/public/-/emojis/1/cat.png
index efd82c2abf3..efd82c2abf3 100644
--- a/app/assets/images/emoji/cat.png
+++ b/public/-/emojis/1/cat.png
Binary files differ
diff --git a/app/assets/images/emoji/cat2.png b/public/-/emojis/1/cat2.png
index 46abe8cbc14..46abe8cbc14 100644
--- a/app/assets/images/emoji/cat2.png
+++ b/public/-/emojis/1/cat2.png
Binary files differ
diff --git a/app/assets/images/emoji/cd.png b/public/-/emojis/1/cd.png
index e6b01449cd9..e6b01449cd9 100644
--- a/app/assets/images/emoji/cd.png
+++ b/public/-/emojis/1/cd.png
Binary files differ
diff --git a/app/assets/images/emoji/chains.png b/public/-/emojis/1/chains.png
index 57f46139a06..57f46139a06 100644
--- a/app/assets/images/emoji/chains.png
+++ b/public/-/emojis/1/chains.png
Binary files differ
diff --git a/app/assets/images/emoji/champagne.png b/public/-/emojis/1/champagne.png
index 285a79a93d0..285a79a93d0 100644
--- a/app/assets/images/emoji/champagne.png
+++ b/public/-/emojis/1/champagne.png
Binary files differ
diff --git a/app/assets/images/emoji/champagne_glass.png b/public/-/emojis/1/champagne_glass.png
index 31937ae9392..31937ae9392 100644
--- a/app/assets/images/emoji/champagne_glass.png
+++ b/public/-/emojis/1/champagne_glass.png
Binary files differ
diff --git a/app/assets/images/emoji/chart.png b/public/-/emojis/1/chart.png
index 9773f03be22..9773f03be22 100644
--- a/app/assets/images/emoji/chart.png
+++ b/public/-/emojis/1/chart.png
Binary files differ
diff --git a/app/assets/images/emoji/chart_with_downwards_trend.png b/public/-/emojis/1/chart_with_downwards_trend.png
index 5222ec72d85..5222ec72d85 100644
--- a/app/assets/images/emoji/chart_with_downwards_trend.png
+++ b/public/-/emojis/1/chart_with_downwards_trend.png
Binary files differ
diff --git a/app/assets/images/emoji/chart_with_upwards_trend.png b/public/-/emojis/1/chart_with_upwards_trend.png
index f13cfcf9956..f13cfcf9956 100644
--- a/app/assets/images/emoji/chart_with_upwards_trend.png
+++ b/public/-/emojis/1/chart_with_upwards_trend.png
Binary files differ
diff --git a/app/assets/images/emoji/checkered_flag.png b/public/-/emojis/1/checkered_flag.png
index 5a71eecb89b..5a71eecb89b 100644
--- a/app/assets/images/emoji/checkered_flag.png
+++ b/public/-/emojis/1/checkered_flag.png
Binary files differ
diff --git a/app/assets/images/emoji/cheese.png b/public/-/emojis/1/cheese.png
index 00e99762286..00e99762286 100644
--- a/app/assets/images/emoji/cheese.png
+++ b/public/-/emojis/1/cheese.png
Binary files differ
diff --git a/app/assets/images/emoji/cherries.png b/public/-/emojis/1/cherries.png
index 9b10cbaac5e..9b10cbaac5e 100644
--- a/app/assets/images/emoji/cherries.png
+++ b/public/-/emojis/1/cherries.png
Binary files differ
diff --git a/app/assets/images/emoji/cherry_blossom.png b/public/-/emojis/1/cherry_blossom.png
index 282f3e7bc81..282f3e7bc81 100644
--- a/app/assets/images/emoji/cherry_blossom.png
+++ b/public/-/emojis/1/cherry_blossom.png
Binary files differ
diff --git a/app/assets/images/emoji/chestnut.png b/public/-/emojis/1/chestnut.png
index e9fb40468ed..e9fb40468ed 100644
--- a/app/assets/images/emoji/chestnut.png
+++ b/public/-/emojis/1/chestnut.png
Binary files differ
diff --git a/app/assets/images/emoji/chicken.png b/public/-/emojis/1/chicken.png
index 9a6992e55ba..9a6992e55ba 100644
--- a/app/assets/images/emoji/chicken.png
+++ b/public/-/emojis/1/chicken.png
Binary files differ
diff --git a/app/assets/images/emoji/children_crossing.png b/public/-/emojis/1/children_crossing.png
index fa4c091c7c3..fa4c091c7c3 100644
--- a/app/assets/images/emoji/children_crossing.png
+++ b/public/-/emojis/1/children_crossing.png
Binary files differ
diff --git a/app/assets/images/emoji/chipmunk.png b/public/-/emojis/1/chipmunk.png
index 2aac560cb22..2aac560cb22 100644
--- a/app/assets/images/emoji/chipmunk.png
+++ b/public/-/emojis/1/chipmunk.png
Binary files differ
diff --git a/app/assets/images/emoji/chocolate_bar.png b/public/-/emojis/1/chocolate_bar.png
index 318bbd40ef9..318bbd40ef9 100644
--- a/app/assets/images/emoji/chocolate_bar.png
+++ b/public/-/emojis/1/chocolate_bar.png
Binary files differ
diff --git a/app/assets/images/emoji/christmas_tree.png b/public/-/emojis/1/christmas_tree.png
index 4197d37a52b..4197d37a52b 100644
--- a/app/assets/images/emoji/christmas_tree.png
+++ b/public/-/emojis/1/christmas_tree.png
Binary files differ
diff --git a/app/assets/images/emoji/church.png b/public/-/emojis/1/church.png
index 8242fd272b3..8242fd272b3 100644
--- a/app/assets/images/emoji/church.png
+++ b/public/-/emojis/1/church.png
Binary files differ
diff --git a/app/assets/images/emoji/cinema.png b/public/-/emojis/1/cinema.png
index 65f27b386f2..65f27b386f2 100644
--- a/app/assets/images/emoji/cinema.png
+++ b/public/-/emojis/1/cinema.png
Binary files differ
diff --git a/app/assets/images/emoji/circus_tent.png b/public/-/emojis/1/circus_tent.png
index b0379775b12..b0379775b12 100644
--- a/app/assets/images/emoji/circus_tent.png
+++ b/public/-/emojis/1/circus_tent.png
Binary files differ
diff --git a/app/assets/images/emoji/city_dusk.png b/public/-/emojis/1/city_dusk.png
index 80cdff7cf5d..80cdff7cf5d 100644
--- a/app/assets/images/emoji/city_dusk.png
+++ b/public/-/emojis/1/city_dusk.png
Binary files differ
diff --git a/app/assets/images/emoji/city_sunset.png b/public/-/emojis/1/city_sunset.png
index 7cded0ba55b..7cded0ba55b 100644
--- a/app/assets/images/emoji/city_sunset.png
+++ b/public/-/emojis/1/city_sunset.png
Binary files differ
diff --git a/app/assets/images/emoji/cityscape.png b/public/-/emojis/1/cityscape.png
index d7b9844a0b4..d7b9844a0b4 100644
--- a/app/assets/images/emoji/cityscape.png
+++ b/public/-/emojis/1/cityscape.png
Binary files differ
diff --git a/app/assets/images/emoji/cl.png b/public/-/emojis/1/cl.png
index 8b01b4343e2..8b01b4343e2 100644
--- a/app/assets/images/emoji/cl.png
+++ b/public/-/emojis/1/cl.png
Binary files differ
diff --git a/app/assets/images/emoji/clap.png b/public/-/emojis/1/clap.png
index b0ffe928920..b0ffe928920 100644
--- a/app/assets/images/emoji/clap.png
+++ b/public/-/emojis/1/clap.png
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone1.png b/public/-/emojis/1/clap_tone1.png
index de4bc837b96..de4bc837b96 100644
--- a/app/assets/images/emoji/clap_tone1.png
+++ b/public/-/emojis/1/clap_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone2.png b/public/-/emojis/1/clap_tone2.png
index 1323de775ba..1323de775ba 100644
--- a/app/assets/images/emoji/clap_tone2.png
+++ b/public/-/emojis/1/clap_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone3.png b/public/-/emojis/1/clap_tone3.png
index d448ca19dde..d448ca19dde 100644
--- a/app/assets/images/emoji/clap_tone3.png
+++ b/public/-/emojis/1/clap_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone4.png b/public/-/emojis/1/clap_tone4.png
index c49f44ee91d..c49f44ee91d 100644
--- a/app/assets/images/emoji/clap_tone4.png
+++ b/public/-/emojis/1/clap_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone5.png b/public/-/emojis/1/clap_tone5.png
index 29ee9bdf37c..29ee9bdf37c 100644
--- a/app/assets/images/emoji/clap_tone5.png
+++ b/public/-/emojis/1/clap_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/clapper.png b/public/-/emojis/1/clapper.png
index 81390883111..81390883111 100644
--- a/app/assets/images/emoji/clapper.png
+++ b/public/-/emojis/1/clapper.png
Binary files differ
diff --git a/app/assets/images/emoji/classical_building.png b/public/-/emojis/1/classical_building.png
index de7b559daaf..de7b559daaf 100644
--- a/app/assets/images/emoji/classical_building.png
+++ b/public/-/emojis/1/classical_building.png
Binary files differ
diff --git a/app/assets/images/emoji/clipboard.png b/public/-/emojis/1/clipboard.png
index 7edcfc52509..7edcfc52509 100644
--- a/app/assets/images/emoji/clipboard.png
+++ b/public/-/emojis/1/clipboard.png
Binary files differ
diff --git a/app/assets/images/emoji/clock.png b/public/-/emojis/1/clock.png
index ffdb451e3a8..ffdb451e3a8 100644
--- a/app/assets/images/emoji/clock.png
+++ b/public/-/emojis/1/clock.png
Binary files differ
diff --git a/app/assets/images/emoji/clock1.png b/public/-/emojis/1/clock1.png
index d6e34941f23..d6e34941f23 100644
--- a/app/assets/images/emoji/clock1.png
+++ b/public/-/emojis/1/clock1.png
Binary files differ
diff --git a/app/assets/images/emoji/clock10.png b/public/-/emojis/1/clock10.png
index e62b245cdbe..e62b245cdbe 100644
--- a/app/assets/images/emoji/clock10.png
+++ b/public/-/emojis/1/clock10.png
Binary files differ
diff --git a/app/assets/images/emoji/clock1030.png b/public/-/emojis/1/clock1030.png
index 0802b3c65b9..0802b3c65b9 100644
--- a/app/assets/images/emoji/clock1030.png
+++ b/public/-/emojis/1/clock1030.png
Binary files differ
diff --git a/app/assets/images/emoji/clock11.png b/public/-/emojis/1/clock11.png
index 0983345273b..0983345273b 100644
--- a/app/assets/images/emoji/clock11.png
+++ b/public/-/emojis/1/clock11.png
Binary files differ
diff --git a/app/assets/images/emoji/clock1130.png b/public/-/emojis/1/clock1130.png
index d970d03b809..d970d03b809 100644
--- a/app/assets/images/emoji/clock1130.png
+++ b/public/-/emojis/1/clock1130.png
Binary files differ
diff --git a/app/assets/images/emoji/clock12.png b/public/-/emojis/1/clock12.png
index e61caa4b3e2..e61caa4b3e2 100644
--- a/app/assets/images/emoji/clock12.png
+++ b/public/-/emojis/1/clock12.png
Binary files differ
diff --git a/app/assets/images/emoji/clock1230.png b/public/-/emojis/1/clock1230.png
index f2b1d261721..f2b1d261721 100644
--- a/app/assets/images/emoji/clock1230.png
+++ b/public/-/emojis/1/clock1230.png
Binary files differ
diff --git a/app/assets/images/emoji/clock130.png b/public/-/emojis/1/clock130.png
index 86b7689b84e..86b7689b84e 100644
--- a/app/assets/images/emoji/clock130.png
+++ b/public/-/emojis/1/clock130.png
Binary files differ
diff --git a/app/assets/images/emoji/clock2.png b/public/-/emojis/1/clock2.png
index a54253d7d57..a54253d7d57 100644
--- a/app/assets/images/emoji/clock2.png
+++ b/public/-/emojis/1/clock2.png
Binary files differ
diff --git a/app/assets/images/emoji/clock230.png b/public/-/emojis/1/clock230.png
index 7a787e018e6..7a787e018e6 100644
--- a/app/assets/images/emoji/clock230.png
+++ b/public/-/emojis/1/clock230.png
Binary files differ
diff --git a/app/assets/images/emoji/clock3.png b/public/-/emojis/1/clock3.png
index 27ec4b1f514..27ec4b1f514 100644
--- a/app/assets/images/emoji/clock3.png
+++ b/public/-/emojis/1/clock3.png
Binary files differ
diff --git a/app/assets/images/emoji/clock330.png b/public/-/emojis/1/clock330.png
index c6860395cec..c6860395cec 100644
--- a/app/assets/images/emoji/clock330.png
+++ b/public/-/emojis/1/clock330.png
Binary files differ
diff --git a/app/assets/images/emoji/clock4.png b/public/-/emojis/1/clock4.png
index 60a1ef4cc13..60a1ef4cc13 100644
--- a/app/assets/images/emoji/clock4.png
+++ b/public/-/emojis/1/clock4.png
Binary files differ
diff --git a/app/assets/images/emoji/clock430.png b/public/-/emojis/1/clock430.png
index 3c05b362122..3c05b362122 100644
--- a/app/assets/images/emoji/clock430.png
+++ b/public/-/emojis/1/clock430.png
Binary files differ
diff --git a/app/assets/images/emoji/clock5.png b/public/-/emojis/1/clock5.png
index c9382d1e094..c9382d1e094 100644
--- a/app/assets/images/emoji/clock5.png
+++ b/public/-/emojis/1/clock5.png
Binary files differ
diff --git a/app/assets/images/emoji/clock530.png b/public/-/emojis/1/clock530.png
index c21fa926db2..c21fa926db2 100644
--- a/app/assets/images/emoji/clock530.png
+++ b/public/-/emojis/1/clock530.png
Binary files differ
diff --git a/app/assets/images/emoji/clock6.png b/public/-/emojis/1/clock6.png
index 8fd5d3f5bd7..8fd5d3f5bd7 100644
--- a/app/assets/images/emoji/clock6.png
+++ b/public/-/emojis/1/clock6.png
Binary files differ
diff --git a/app/assets/images/emoji/clock630.png b/public/-/emojis/1/clock630.png
index 2aec87fefcf..2aec87fefcf 100644
--- a/app/assets/images/emoji/clock630.png
+++ b/public/-/emojis/1/clock630.png
Binary files differ
diff --git a/app/assets/images/emoji/clock7.png b/public/-/emojis/1/clock7.png
index 8c7084036f2..8c7084036f2 100644
--- a/app/assets/images/emoji/clock7.png
+++ b/public/-/emojis/1/clock7.png
Binary files differ
diff --git a/app/assets/images/emoji/clock730.png b/public/-/emojis/1/clock730.png
index f7a1135e03f..f7a1135e03f 100644
--- a/app/assets/images/emoji/clock730.png
+++ b/public/-/emojis/1/clock730.png
Binary files differ
diff --git a/app/assets/images/emoji/clock8.png b/public/-/emojis/1/clock8.png
index fcddf722e95..fcddf722e95 100644
--- a/app/assets/images/emoji/clock8.png
+++ b/public/-/emojis/1/clock8.png
Binary files differ
diff --git a/app/assets/images/emoji/clock830.png b/public/-/emojis/1/clock830.png
index 799b4aebc08..799b4aebc08 100644
--- a/app/assets/images/emoji/clock830.png
+++ b/public/-/emojis/1/clock830.png
Binary files differ
diff --git a/app/assets/images/emoji/clock9.png b/public/-/emojis/1/clock9.png
index dfbe0117981..dfbe0117981 100644
--- a/app/assets/images/emoji/clock9.png
+++ b/public/-/emojis/1/clock9.png
Binary files differ
diff --git a/app/assets/images/emoji/clock930.png b/public/-/emojis/1/clock930.png
index 4a2092ee6f0..4a2092ee6f0 100644
--- a/app/assets/images/emoji/clock930.png
+++ b/public/-/emojis/1/clock930.png
Binary files differ
diff --git a/app/assets/images/emoji/closed_book.png b/public/-/emojis/1/closed_book.png
index 6395cf2151e..6395cf2151e 100644
--- a/app/assets/images/emoji/closed_book.png
+++ b/public/-/emojis/1/closed_book.png
Binary files differ
diff --git a/app/assets/images/emoji/closed_lock_with_key.png b/public/-/emojis/1/closed_lock_with_key.png
index 1c1cd5d0741..1c1cd5d0741 100644
--- a/app/assets/images/emoji/closed_lock_with_key.png
+++ b/public/-/emojis/1/closed_lock_with_key.png
Binary files differ
diff --git a/app/assets/images/emoji/closed_umbrella.png b/public/-/emojis/1/closed_umbrella.png
index ecefba9e446..ecefba9e446 100644
--- a/app/assets/images/emoji/closed_umbrella.png
+++ b/public/-/emojis/1/closed_umbrella.png
Binary files differ
diff --git a/app/assets/images/emoji/cloud.png b/public/-/emojis/1/cloud.png
index 5b4f57f77ba..5b4f57f77ba 100644
--- a/app/assets/images/emoji/cloud.png
+++ b/public/-/emojis/1/cloud.png
Binary files differ
diff --git a/app/assets/images/emoji/cloud_lightning.png b/public/-/emojis/1/cloud_lightning.png
index 0831e88aa31..0831e88aa31 100644
--- a/app/assets/images/emoji/cloud_lightning.png
+++ b/public/-/emojis/1/cloud_lightning.png
Binary files differ
diff --git a/app/assets/images/emoji/cloud_rain.png b/public/-/emojis/1/cloud_rain.png
index 385685e0512..385685e0512 100644
--- a/app/assets/images/emoji/cloud_rain.png
+++ b/public/-/emojis/1/cloud_rain.png
Binary files differ
diff --git a/app/assets/images/emoji/cloud_snow.png b/public/-/emojis/1/cloud_snow.png
index 9720384eb99..9720384eb99 100644
--- a/app/assets/images/emoji/cloud_snow.png
+++ b/public/-/emojis/1/cloud_snow.png
Binary files differ
diff --git a/app/assets/images/emoji/cloud_tornado.png b/public/-/emojis/1/cloud_tornado.png
index 4821c89da1e..4821c89da1e 100644
--- a/app/assets/images/emoji/cloud_tornado.png
+++ b/public/-/emojis/1/cloud_tornado.png
Binary files differ
diff --git a/app/assets/images/emoji/clown.png b/public/-/emojis/1/clown.png
index 02b7ff70049..02b7ff70049 100644
--- a/app/assets/images/emoji/clown.png
+++ b/public/-/emojis/1/clown.png
Binary files differ
diff --git a/app/assets/images/emoji/clubs.png b/public/-/emojis/1/clubs.png
index 4f2abf791ca..4f2abf791ca 100644
--- a/app/assets/images/emoji/clubs.png
+++ b/public/-/emojis/1/clubs.png
Binary files differ
diff --git a/app/assets/images/emoji/cocktail.png b/public/-/emojis/1/cocktail.png
index 2e50c57e98d..2e50c57e98d 100644
--- a/app/assets/images/emoji/cocktail.png
+++ b/public/-/emojis/1/cocktail.png
Binary files differ
diff --git a/app/assets/images/emoji/coffee.png b/public/-/emojis/1/coffee.png
index 553061471b1..553061471b1 100644
--- a/app/assets/images/emoji/coffee.png
+++ b/public/-/emojis/1/coffee.png
Binary files differ
diff --git a/app/assets/images/emoji/coffin.png b/public/-/emojis/1/coffin.png
index fb2932aa5f6..fb2932aa5f6 100644
--- a/app/assets/images/emoji/coffin.png
+++ b/public/-/emojis/1/coffin.png
Binary files differ
diff --git a/app/assets/images/emoji/cold_sweat.png b/public/-/emojis/1/cold_sweat.png
index 85b2231bbf6..85b2231bbf6 100644
--- a/app/assets/images/emoji/cold_sweat.png
+++ b/public/-/emojis/1/cold_sweat.png
Binary files differ
diff --git a/app/assets/images/emoji/comet.png b/public/-/emojis/1/comet.png
index a99751f79be..a99751f79be 100644
--- a/app/assets/images/emoji/comet.png
+++ b/public/-/emojis/1/comet.png
Binary files differ
diff --git a/app/assets/images/emoji/compression.png b/public/-/emojis/1/compression.png
index d7eda7f362a..d7eda7f362a 100644
--- a/app/assets/images/emoji/compression.png
+++ b/public/-/emojis/1/compression.png
Binary files differ
diff --git a/app/assets/images/emoji/computer.png b/public/-/emojis/1/computer.png
index c1fee27e3a9..c1fee27e3a9 100644
--- a/app/assets/images/emoji/computer.png
+++ b/public/-/emojis/1/computer.png
Binary files differ
diff --git a/app/assets/images/emoji/confetti_ball.png b/public/-/emojis/1/confetti_ball.png
index ba4fd9b12be..ba4fd9b12be 100644
--- a/app/assets/images/emoji/confetti_ball.png
+++ b/public/-/emojis/1/confetti_ball.png
Binary files differ
diff --git a/app/assets/images/emoji/confounded.png b/public/-/emojis/1/confounded.png
index aa4b29e9375..aa4b29e9375 100644
--- a/app/assets/images/emoji/confounded.png
+++ b/public/-/emojis/1/confounded.png
Binary files differ
diff --git a/app/assets/images/emoji/confused.png b/public/-/emojis/1/confused.png
index 502b6bf0e0b..502b6bf0e0b 100644
--- a/app/assets/images/emoji/confused.png
+++ b/public/-/emojis/1/confused.png
Binary files differ
diff --git a/app/assets/images/emoji/congratulations.png b/public/-/emojis/1/congratulations.png
index ba8c89d95ee..ba8c89d95ee 100644
--- a/app/assets/images/emoji/congratulations.png
+++ b/public/-/emojis/1/congratulations.png
Binary files differ
diff --git a/app/assets/images/emoji/construction.png b/public/-/emojis/1/construction.png
index ef8db5f471c..ef8db5f471c 100644
--- a/app/assets/images/emoji/construction.png
+++ b/public/-/emojis/1/construction.png
Binary files differ
diff --git a/app/assets/images/emoji/construction_site.png b/public/-/emojis/1/construction_site.png
index 8206a20f63f..8206a20f63f 100644
--- a/app/assets/images/emoji/construction_site.png
+++ b/public/-/emojis/1/construction_site.png
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker.png b/public/-/emojis/1/construction_worker.png
index a9970a89005..a9970a89005 100644
--- a/app/assets/images/emoji/construction_worker.png
+++ b/public/-/emojis/1/construction_worker.png
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone1.png b/public/-/emojis/1/construction_worker_tone1.png
index 2f24a2bab24..2f24a2bab24 100644
--- a/app/assets/images/emoji/construction_worker_tone1.png
+++ b/public/-/emojis/1/construction_worker_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone2.png b/public/-/emojis/1/construction_worker_tone2.png
index 93c8fec5a75..93c8fec5a75 100644
--- a/app/assets/images/emoji/construction_worker_tone2.png
+++ b/public/-/emojis/1/construction_worker_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone3.png b/public/-/emojis/1/construction_worker_tone3.png
index abc1f2af2e0..abc1f2af2e0 100644
--- a/app/assets/images/emoji/construction_worker_tone3.png
+++ b/public/-/emojis/1/construction_worker_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone4.png b/public/-/emojis/1/construction_worker_tone4.png
index eed83289aeb..eed83289aeb 100644
--- a/app/assets/images/emoji/construction_worker_tone4.png
+++ b/public/-/emojis/1/construction_worker_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone5.png b/public/-/emojis/1/construction_worker_tone5.png
index acbb220b8bb..acbb220b8bb 100644
--- a/app/assets/images/emoji/construction_worker_tone5.png
+++ b/public/-/emojis/1/construction_worker_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/control_knobs.png b/public/-/emojis/1/control_knobs.png
index 6635ac93b50..6635ac93b50 100644
--- a/app/assets/images/emoji/control_knobs.png
+++ b/public/-/emojis/1/control_knobs.png
Binary files differ
diff --git a/app/assets/images/emoji/convenience_store.png b/public/-/emojis/1/convenience_store.png
index 26b53b5669e..26b53b5669e 100644
--- a/app/assets/images/emoji/convenience_store.png
+++ b/public/-/emojis/1/convenience_store.png
Binary files differ
diff --git a/app/assets/images/emoji/cookie.png b/public/-/emojis/1/cookie.png
index 1b6bcb1554f..1b6bcb1554f 100644
--- a/app/assets/images/emoji/cookie.png
+++ b/public/-/emojis/1/cookie.png
Binary files differ
diff --git a/app/assets/images/emoji/cooking.png b/public/-/emojis/1/cooking.png
index 918c980577a..918c980577a 100644
--- a/app/assets/images/emoji/cooking.png
+++ b/public/-/emojis/1/cooking.png
Binary files differ
diff --git a/app/assets/images/emoji/cool.png b/public/-/emojis/1/cool.png
index 74674978d00..74674978d00 100644
--- a/app/assets/images/emoji/cool.png
+++ b/public/-/emojis/1/cool.png
Binary files differ
diff --git a/app/assets/images/emoji/cop.png b/public/-/emojis/1/cop.png
index 0b16d7c17b7..0b16d7c17b7 100644
--- a/app/assets/images/emoji/cop.png
+++ b/public/-/emojis/1/cop.png
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone1.png b/public/-/emojis/1/cop_tone1.png
index 6ccba3879dc..6ccba3879dc 100644
--- a/app/assets/images/emoji/cop_tone1.png
+++ b/public/-/emojis/1/cop_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone2.png b/public/-/emojis/1/cop_tone2.png
index 7814ea9f52d..7814ea9f52d 100644
--- a/app/assets/images/emoji/cop_tone2.png
+++ b/public/-/emojis/1/cop_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone3.png b/public/-/emojis/1/cop_tone3.png
index d78e88ec872..d78e88ec872 100644
--- a/app/assets/images/emoji/cop_tone3.png
+++ b/public/-/emojis/1/cop_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone4.png b/public/-/emojis/1/cop_tone4.png
index 2e13c508315..2e13c508315 100644
--- a/app/assets/images/emoji/cop_tone4.png
+++ b/public/-/emojis/1/cop_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone5.png b/public/-/emojis/1/cop_tone5.png
index 2980d61cc2e..2980d61cc2e 100644
--- a/app/assets/images/emoji/cop_tone5.png
+++ b/public/-/emojis/1/cop_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/copyright.png b/public/-/emojis/1/copyright.png
index 6b9a6adbfd2..6b9a6adbfd2 100644
--- a/app/assets/images/emoji/copyright.png
+++ b/public/-/emojis/1/copyright.png
Binary files differ
diff --git a/app/assets/images/emoji/corn.png b/public/-/emojis/1/corn.png
index 36e20127931..36e20127931 100644
--- a/app/assets/images/emoji/corn.png
+++ b/public/-/emojis/1/corn.png
Binary files differ
diff --git a/app/assets/images/emoji/couch.png b/public/-/emojis/1/couch.png
index 27b19b13bb0..27b19b13bb0 100644
--- a/app/assets/images/emoji/couch.png
+++ b/public/-/emojis/1/couch.png
Binary files differ
diff --git a/app/assets/images/emoji/couple.png b/public/-/emojis/1/couple.png
index 960323f3c16..960323f3c16 100644
--- a/app/assets/images/emoji/couple.png
+++ b/public/-/emojis/1/couple.png
Binary files differ
diff --git a/app/assets/images/emoji/couple_mm.png b/public/-/emojis/1/couple_mm.png
index 8759fa5db87..8759fa5db87 100644
--- a/app/assets/images/emoji/couple_mm.png
+++ b/public/-/emojis/1/couple_mm.png
Binary files differ
diff --git a/app/assets/images/emoji/couple_with_heart.png b/public/-/emojis/1/couple_with_heart.png
index 62111601b36..62111601b36 100644
--- a/app/assets/images/emoji/couple_with_heart.png
+++ b/public/-/emojis/1/couple_with_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/couple_ww.png b/public/-/emojis/1/couple_ww.png
index 08fdabcdc5c..08fdabcdc5c 100644
--- a/app/assets/images/emoji/couple_ww.png
+++ b/public/-/emojis/1/couple_ww.png
Binary files differ
diff --git a/app/assets/images/emoji/couplekiss.png b/public/-/emojis/1/couplekiss.png
index 9aa519da9e8..9aa519da9e8 100644
--- a/app/assets/images/emoji/couplekiss.png
+++ b/public/-/emojis/1/couplekiss.png
Binary files differ
diff --git a/app/assets/images/emoji/cow.png b/public/-/emojis/1/cow.png
index 718a3986d64..718a3986d64 100644
--- a/app/assets/images/emoji/cow.png
+++ b/public/-/emojis/1/cow.png
Binary files differ
diff --git a/app/assets/images/emoji/cow2.png b/public/-/emojis/1/cow2.png
index 4d0ca534ff1..4d0ca534ff1 100644
--- a/app/assets/images/emoji/cow2.png
+++ b/public/-/emojis/1/cow2.png
Binary files differ
diff --git a/app/assets/images/emoji/cowboy.png b/public/-/emojis/1/cowboy.png
index 70dd5d0d9d1..70dd5d0d9d1 100644
--- a/app/assets/images/emoji/cowboy.png
+++ b/public/-/emojis/1/cowboy.png
Binary files differ
diff --git a/app/assets/images/emoji/crab.png b/public/-/emojis/1/crab.png
index 19f3047ab61..19f3047ab61 100644
--- a/app/assets/images/emoji/crab.png
+++ b/public/-/emojis/1/crab.png
Binary files differ
diff --git a/app/assets/images/emoji/crayon.png b/public/-/emojis/1/crayon.png
index 8d7b427aaa3..8d7b427aaa3 100644
--- a/app/assets/images/emoji/crayon.png
+++ b/public/-/emojis/1/crayon.png
Binary files differ
diff --git a/app/assets/images/emoji/credit_card.png b/public/-/emojis/1/credit_card.png
index 372777d5c61..372777d5c61 100644
--- a/app/assets/images/emoji/credit_card.png
+++ b/public/-/emojis/1/credit_card.png
Binary files differ
diff --git a/app/assets/images/emoji/crescent_moon.png b/public/-/emojis/1/crescent_moon.png
index 765420ecec7..765420ecec7 100644
--- a/app/assets/images/emoji/crescent_moon.png
+++ b/public/-/emojis/1/crescent_moon.png
Binary files differ
diff --git a/app/assets/images/emoji/cricket.png b/public/-/emojis/1/cricket.png
index d602294a2cd..d602294a2cd 100644
--- a/app/assets/images/emoji/cricket.png
+++ b/public/-/emojis/1/cricket.png
Binary files differ
diff --git a/app/assets/images/emoji/crocodile.png b/public/-/emojis/1/crocodile.png
index 3005c46f176..3005c46f176 100644
--- a/app/assets/images/emoji/crocodile.png
+++ b/public/-/emojis/1/crocodile.png
Binary files differ
diff --git a/app/assets/images/emoji/croissant.png b/public/-/emojis/1/croissant.png
index fb33feb1a38..fb33feb1a38 100644
--- a/app/assets/images/emoji/croissant.png
+++ b/public/-/emojis/1/croissant.png
Binary files differ
diff --git a/app/assets/images/emoji/cross.png b/public/-/emojis/1/cross.png
index 42b10e82257..42b10e82257 100644
--- a/app/assets/images/emoji/cross.png
+++ b/public/-/emojis/1/cross.png
Binary files differ
diff --git a/app/assets/images/emoji/crossed_flags.png b/public/-/emojis/1/crossed_flags.png
index 273bd0f0fe5..273bd0f0fe5 100644
--- a/app/assets/images/emoji/crossed_flags.png
+++ b/public/-/emojis/1/crossed_flags.png
Binary files differ
diff --git a/app/assets/images/emoji/crossed_swords.png b/public/-/emojis/1/crossed_swords.png
index 907e9607134..907e9607134 100644
--- a/app/assets/images/emoji/crossed_swords.png
+++ b/public/-/emojis/1/crossed_swords.png
Binary files differ
diff --git a/app/assets/images/emoji/crown.png b/public/-/emojis/1/crown.png
index 93b82d92f04..93b82d92f04 100644
--- a/app/assets/images/emoji/crown.png
+++ b/public/-/emojis/1/crown.png
Binary files differ
diff --git a/app/assets/images/emoji/cruise_ship.png b/public/-/emojis/1/cruise_ship.png
index 19d4acbe40c..19d4acbe40c 100644
--- a/app/assets/images/emoji/cruise_ship.png
+++ b/public/-/emojis/1/cruise_ship.png
Binary files differ
diff --git a/app/assets/images/emoji/cry.png b/public/-/emojis/1/cry.png
index b7877f8a173..b7877f8a173 100644
--- a/app/assets/images/emoji/cry.png
+++ b/public/-/emojis/1/cry.png
Binary files differ
diff --git a/app/assets/images/emoji/crying_cat_face.png b/public/-/emojis/1/crying_cat_face.png
index b4f49715e00..b4f49715e00 100644
--- a/app/assets/images/emoji/crying_cat_face.png
+++ b/public/-/emojis/1/crying_cat_face.png
Binary files differ
diff --git a/app/assets/images/emoji/crystal_ball.png b/public/-/emojis/1/crystal_ball.png
index 485d5c888f1..485d5c888f1 100644
--- a/app/assets/images/emoji/crystal_ball.png
+++ b/public/-/emojis/1/crystal_ball.png
Binary files differ
diff --git a/app/assets/images/emoji/cucumber.png b/public/-/emojis/1/cucumber.png
index 500807059d2..500807059d2 100644
--- a/app/assets/images/emoji/cucumber.png
+++ b/public/-/emojis/1/cucumber.png
Binary files differ
diff --git a/app/assets/images/emoji/cupid.png b/public/-/emojis/1/cupid.png
index 2df0078ddd1..2df0078ddd1 100644
--- a/app/assets/images/emoji/cupid.png
+++ b/public/-/emojis/1/cupid.png
Binary files differ
diff --git a/app/assets/images/emoji/curly_loop.png b/public/-/emojis/1/curly_loop.png
index 440aa56d50e..440aa56d50e 100644
--- a/app/assets/images/emoji/curly_loop.png
+++ b/public/-/emojis/1/curly_loop.png
Binary files differ
diff --git a/app/assets/images/emoji/currency_exchange.png b/public/-/emojis/1/currency_exchange.png
index 4d46c6050e7..4d46c6050e7 100644
--- a/app/assets/images/emoji/currency_exchange.png
+++ b/public/-/emojis/1/currency_exchange.png
Binary files differ
diff --git a/app/assets/images/emoji/curry.png b/public/-/emojis/1/curry.png
index 69657ca8103..69657ca8103 100644
--- a/app/assets/images/emoji/curry.png
+++ b/public/-/emojis/1/curry.png
Binary files differ
diff --git a/app/assets/images/emoji/custard.png b/public/-/emojis/1/custard.png
index fa3df67b8f6..fa3df67b8f6 100644
--- a/app/assets/images/emoji/custard.png
+++ b/public/-/emojis/1/custard.png
Binary files differ
diff --git a/app/assets/images/emoji/customs.png b/public/-/emojis/1/customs.png
index 21b7ce2c69e..21b7ce2c69e 100644
--- a/app/assets/images/emoji/customs.png
+++ b/public/-/emojis/1/customs.png
Binary files differ
diff --git a/app/assets/images/emoji/cyclone.png b/public/-/emojis/1/cyclone.png
index ff00b1afe70..ff00b1afe70 100644
--- a/app/assets/images/emoji/cyclone.png
+++ b/public/-/emojis/1/cyclone.png
Binary files differ
diff --git a/app/assets/images/emoji/dagger.png b/public/-/emojis/1/dagger.png
index 66e97b0aa25..66e97b0aa25 100644
--- a/app/assets/images/emoji/dagger.png
+++ b/public/-/emojis/1/dagger.png
Binary files differ
diff --git a/app/assets/images/emoji/dancer.png b/public/-/emojis/1/dancer.png
index 04b166991cb..04b166991cb 100644
--- a/app/assets/images/emoji/dancer.png
+++ b/public/-/emojis/1/dancer.png
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone1.png b/public/-/emojis/1/dancer_tone1.png
index 2c7b11c3a6e..2c7b11c3a6e 100644
--- a/app/assets/images/emoji/dancer_tone1.png
+++ b/public/-/emojis/1/dancer_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone2.png b/public/-/emojis/1/dancer_tone2.png
index cb04b1f907e..cb04b1f907e 100644
--- a/app/assets/images/emoji/dancer_tone2.png
+++ b/public/-/emojis/1/dancer_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone3.png b/public/-/emojis/1/dancer_tone3.png
index 98c5bca7b64..98c5bca7b64 100644
--- a/app/assets/images/emoji/dancer_tone3.png
+++ b/public/-/emojis/1/dancer_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone4.png b/public/-/emojis/1/dancer_tone4.png
index fdb1e00cbba..fdb1e00cbba 100644
--- a/app/assets/images/emoji/dancer_tone4.png
+++ b/public/-/emojis/1/dancer_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone5.png b/public/-/emojis/1/dancer_tone5.png
index 0e34e0e23f0..0e34e0e23f0 100644
--- a/app/assets/images/emoji/dancer_tone5.png
+++ b/public/-/emojis/1/dancer_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/dancers.png b/public/-/emojis/1/dancers.png
index 67e6ffacb76..67e6ffacb76 100644
--- a/app/assets/images/emoji/dancers.png
+++ b/public/-/emojis/1/dancers.png
Binary files differ
diff --git a/app/assets/images/emoji/dango.png b/public/-/emojis/1/dango.png
index f73f37b01c7..f73f37b01c7 100644
--- a/app/assets/images/emoji/dango.png
+++ b/public/-/emojis/1/dango.png
Binary files differ
diff --git a/app/assets/images/emoji/dark_sunglasses.png b/public/-/emojis/1/dark_sunglasses.png
index b1b6db0acff..b1b6db0acff 100644
--- a/app/assets/images/emoji/dark_sunglasses.png
+++ b/public/-/emojis/1/dark_sunglasses.png
Binary files differ
diff --git a/app/assets/images/emoji/dart.png b/public/-/emojis/1/dart.png
index f6704aeb8ba..f6704aeb8ba 100644
--- a/app/assets/images/emoji/dart.png
+++ b/public/-/emojis/1/dart.png
Binary files differ
diff --git a/app/assets/images/emoji/dash.png b/public/-/emojis/1/dash.png
index 064b8525c12..064b8525c12 100644
--- a/app/assets/images/emoji/dash.png
+++ b/public/-/emojis/1/dash.png
Binary files differ
diff --git a/app/assets/images/emoji/date.png b/public/-/emojis/1/date.png
index f05b3da97b8..f05b3da97b8 100644
--- a/app/assets/images/emoji/date.png
+++ b/public/-/emojis/1/date.png
Binary files differ
diff --git a/app/assets/images/emoji/deciduous_tree.png b/public/-/emojis/1/deciduous_tree.png
index 785fc1c30ea..785fc1c30ea 100644
--- a/app/assets/images/emoji/deciduous_tree.png
+++ b/public/-/emojis/1/deciduous_tree.png
Binary files differ
diff --git a/app/assets/images/emoji/deer.png b/public/-/emojis/1/deer.png
index d8698195ff0..d8698195ff0 100644
--- a/app/assets/images/emoji/deer.png
+++ b/public/-/emojis/1/deer.png
Binary files differ
diff --git a/app/assets/images/emoji/department_store.png b/public/-/emojis/1/department_store.png
index 58867c7a6e1..58867c7a6e1 100644
--- a/app/assets/images/emoji/department_store.png
+++ b/public/-/emojis/1/department_store.png
Binary files differ
diff --git a/app/assets/images/emoji/desert.png b/public/-/emojis/1/desert.png
index e9966ff8c65..e9966ff8c65 100644
--- a/app/assets/images/emoji/desert.png
+++ b/public/-/emojis/1/desert.png
Binary files differ
diff --git a/app/assets/images/emoji/desktop.png b/public/-/emojis/1/desktop.png
index 909bd42b5e1..909bd42b5e1 100644
--- a/app/assets/images/emoji/desktop.png
+++ b/public/-/emojis/1/desktop.png
Binary files differ
diff --git a/app/assets/images/emoji/diamond_shape_with_a_dot_inside.png b/public/-/emojis/1/diamond_shape_with_a_dot_inside.png
index 2a22a26d1e2..2a22a26d1e2 100644
--- a/app/assets/images/emoji/diamond_shape_with_a_dot_inside.png
+++ b/public/-/emojis/1/diamond_shape_with_a_dot_inside.png
Binary files differ
diff --git a/app/assets/images/emoji/diamonds.png b/public/-/emojis/1/diamonds.png
index 1f25f51f97a..1f25f51f97a 100644
--- a/app/assets/images/emoji/diamonds.png
+++ b/public/-/emojis/1/diamonds.png
Binary files differ
diff --git a/app/assets/images/emoji/disappointed.png b/public/-/emojis/1/disappointed.png
index efe4e67e23c..efe4e67e23c 100644
--- a/app/assets/images/emoji/disappointed.png
+++ b/public/-/emojis/1/disappointed.png
Binary files differ
diff --git a/app/assets/images/emoji/disappointed_relieved.png b/public/-/emojis/1/disappointed_relieved.png
index aef864d2b3d..aef864d2b3d 100644
--- a/app/assets/images/emoji/disappointed_relieved.png
+++ b/public/-/emojis/1/disappointed_relieved.png
Binary files differ
diff --git a/app/assets/images/emoji/dividers.png b/public/-/emojis/1/dividers.png
index 46a7e403f9d..46a7e403f9d 100644
--- a/app/assets/images/emoji/dividers.png
+++ b/public/-/emojis/1/dividers.png
Binary files differ
diff --git a/app/assets/images/emoji/dizzy.png b/public/-/emojis/1/dizzy.png
index 85f52efad24..85f52efad24 100644
--- a/app/assets/images/emoji/dizzy.png
+++ b/public/-/emojis/1/dizzy.png
Binary files differ
diff --git a/app/assets/images/emoji/dizzy_face.png b/public/-/emojis/1/dizzy_face.png
index 3120316ab5e..3120316ab5e 100644
--- a/app/assets/images/emoji/dizzy_face.png
+++ b/public/-/emojis/1/dizzy_face.png
Binary files differ
diff --git a/app/assets/images/emoji/do_not_litter.png b/public/-/emojis/1/do_not_litter.png
index 341d2575f4f..341d2575f4f 100644
--- a/app/assets/images/emoji/do_not_litter.png
+++ b/public/-/emojis/1/do_not_litter.png
Binary files differ
diff --git a/app/assets/images/emoji/dog.png b/public/-/emojis/1/dog.png
index 281b81d58bd..281b81d58bd 100644
--- a/app/assets/images/emoji/dog.png
+++ b/public/-/emojis/1/dog.png
Binary files differ
diff --git a/app/assets/images/emoji/dog2.png b/public/-/emojis/1/dog2.png
index 976143dbdbe..976143dbdbe 100644
--- a/app/assets/images/emoji/dog2.png
+++ b/public/-/emojis/1/dog2.png
Binary files differ
diff --git a/app/assets/images/emoji/dollar.png b/public/-/emojis/1/dollar.png
index a9904c28293..a9904c28293 100644
--- a/app/assets/images/emoji/dollar.png
+++ b/public/-/emojis/1/dollar.png
Binary files differ
diff --git a/app/assets/images/emoji/dolls.png b/public/-/emojis/1/dolls.png
index 10955615110..10955615110 100644
--- a/app/assets/images/emoji/dolls.png
+++ b/public/-/emojis/1/dolls.png
Binary files differ
diff --git a/app/assets/images/emoji/dolphin.png b/public/-/emojis/1/dolphin.png
index 81434809003..81434809003 100644
--- a/app/assets/images/emoji/dolphin.png
+++ b/public/-/emojis/1/dolphin.png
Binary files differ
diff --git a/app/assets/images/emoji/door.png b/public/-/emojis/1/door.png
index 36ae3e27494..36ae3e27494 100644
--- a/app/assets/images/emoji/door.png
+++ b/public/-/emojis/1/door.png
Binary files differ
diff --git a/app/assets/images/emoji/doughnut.png b/public/-/emojis/1/doughnut.png
index 0ca4cd0bde8..0ca4cd0bde8 100644
--- a/app/assets/images/emoji/doughnut.png
+++ b/public/-/emojis/1/doughnut.png
Binary files differ
diff --git a/app/assets/images/emoji/dove.png b/public/-/emojis/1/dove.png
index 9580c4917d7..9580c4917d7 100644
--- a/app/assets/images/emoji/dove.png
+++ b/public/-/emojis/1/dove.png
Binary files differ
diff --git a/app/assets/images/emoji/dragon.png b/public/-/emojis/1/dragon.png
index d6311cf5429..d6311cf5429 100644
--- a/app/assets/images/emoji/dragon.png
+++ b/public/-/emojis/1/dragon.png
Binary files differ
diff --git a/app/assets/images/emoji/dragon_face.png b/public/-/emojis/1/dragon_face.png
index 3c2720446c6..3c2720446c6 100644
--- a/app/assets/images/emoji/dragon_face.png
+++ b/public/-/emojis/1/dragon_face.png
Binary files differ
diff --git a/app/assets/images/emoji/dress.png b/public/-/emojis/1/dress.png
index a697ca5c57d..a697ca5c57d 100644
--- a/app/assets/images/emoji/dress.png
+++ b/public/-/emojis/1/dress.png
Binary files differ
diff --git a/app/assets/images/emoji/dromedary_camel.png b/public/-/emojis/1/dromedary_camel.png
index 5271637c7c4..5271637c7c4 100644
--- a/app/assets/images/emoji/dromedary_camel.png
+++ b/public/-/emojis/1/dromedary_camel.png
Binary files differ
diff --git a/app/assets/images/emoji/drooling_face.png b/public/-/emojis/1/drooling_face.png
index a5460532597..a5460532597 100644
--- a/app/assets/images/emoji/drooling_face.png
+++ b/public/-/emojis/1/drooling_face.png
Binary files differ
diff --git a/app/assets/images/emoji/droplet.png b/public/-/emojis/1/droplet.png
index 71241ec3061..71241ec3061 100644
--- a/app/assets/images/emoji/droplet.png
+++ b/public/-/emojis/1/droplet.png
Binary files differ
diff --git a/app/assets/images/emoji/drum.png b/public/-/emojis/1/drum.png
index b038727cc99..b038727cc99 100644
--- a/app/assets/images/emoji/drum.png
+++ b/public/-/emojis/1/drum.png
Binary files differ
diff --git a/app/assets/images/emoji/duck.png b/public/-/emojis/1/duck.png
index 74330b77ca3..74330b77ca3 100644
--- a/app/assets/images/emoji/duck.png
+++ b/public/-/emojis/1/duck.png
Binary files differ
diff --git a/app/assets/images/emoji/dvd.png b/public/-/emojis/1/dvd.png
index 045a6f7a08d..045a6f7a08d 100644
--- a/app/assets/images/emoji/dvd.png
+++ b/public/-/emojis/1/dvd.png
Binary files differ
diff --git a/app/assets/images/emoji/e-mail.png b/public/-/emojis/1/e-mail.png
index d22e654a20b..d22e654a20b 100644
--- a/app/assets/images/emoji/e-mail.png
+++ b/public/-/emojis/1/e-mail.png
Binary files differ
diff --git a/app/assets/images/emoji/eagle.png b/public/-/emojis/1/eagle.png
index 4f277debeef..4f277debeef 100644
--- a/app/assets/images/emoji/eagle.png
+++ b/public/-/emojis/1/eagle.png
Binary files differ
diff --git a/app/assets/images/emoji/ear.png b/public/-/emojis/1/ear.png
index f84f9ff154a..f84f9ff154a 100644
--- a/app/assets/images/emoji/ear.png
+++ b/public/-/emojis/1/ear.png
Binary files differ
diff --git a/app/assets/images/emoji/ear_of_rice.png b/public/-/emojis/1/ear_of_rice.png
index 3564d9d643a..3564d9d643a 100644
--- a/app/assets/images/emoji/ear_of_rice.png
+++ b/public/-/emojis/1/ear_of_rice.png
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone1.png b/public/-/emojis/1/ear_tone1.png
index d09e1e41996..d09e1e41996 100644
--- a/app/assets/images/emoji/ear_tone1.png
+++ b/public/-/emojis/1/ear_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone2.png b/public/-/emojis/1/ear_tone2.png
index 300d60a9948..300d60a9948 100644
--- a/app/assets/images/emoji/ear_tone2.png
+++ b/public/-/emojis/1/ear_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone3.png b/public/-/emojis/1/ear_tone3.png
index 2a56eebe445..2a56eebe445 100644
--- a/app/assets/images/emoji/ear_tone3.png
+++ b/public/-/emojis/1/ear_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone4.png b/public/-/emojis/1/ear_tone4.png
index bd270f7763e..bd270f7763e 100644
--- a/app/assets/images/emoji/ear_tone4.png
+++ b/public/-/emojis/1/ear_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone5.png b/public/-/emojis/1/ear_tone5.png
index b96bb441dff..b96bb441dff 100644
--- a/app/assets/images/emoji/ear_tone5.png
+++ b/public/-/emojis/1/ear_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/earth_africa.png b/public/-/emojis/1/earth_africa.png
index 66c3348c23a..66c3348c23a 100644
--- a/app/assets/images/emoji/earth_africa.png
+++ b/public/-/emojis/1/earth_africa.png
Binary files differ
diff --git a/app/assets/images/emoji/earth_americas.png b/public/-/emojis/1/earth_americas.png
index 538c3cddd68..538c3cddd68 100644
--- a/app/assets/images/emoji/earth_americas.png
+++ b/public/-/emojis/1/earth_americas.png
Binary files differ
diff --git a/app/assets/images/emoji/earth_asia.png b/public/-/emojis/1/earth_asia.png
index d8df97fec3c..d8df97fec3c 100644
--- a/app/assets/images/emoji/earth_asia.png
+++ b/public/-/emojis/1/earth_asia.png
Binary files differ
diff --git a/app/assets/images/emoji/egg.png b/public/-/emojis/1/egg.png
index c171974d993..c171974d993 100644
--- a/app/assets/images/emoji/egg.png
+++ b/public/-/emojis/1/egg.png
Binary files differ
diff --git a/app/assets/images/emoji/eggplant.png b/public/-/emojis/1/eggplant.png
index fafd7c1a14c..fafd7c1a14c 100644
--- a/app/assets/images/emoji/eggplant.png
+++ b/public/-/emojis/1/eggplant.png
Binary files differ
diff --git a/app/assets/images/emoji/eight.png b/public/-/emojis/1/eight.png
index 8c95874d4c5..8c95874d4c5 100644
--- a/app/assets/images/emoji/eight.png
+++ b/public/-/emojis/1/eight.png
Binary files differ
diff --git a/app/assets/images/emoji/eight_pointed_black_star.png b/public/-/emojis/1/eight_pointed_black_star.png
index 820179bda50..820179bda50 100644
--- a/app/assets/images/emoji/eight_pointed_black_star.png
+++ b/public/-/emojis/1/eight_pointed_black_star.png
Binary files differ
diff --git a/app/assets/images/emoji/eight_spoked_asterisk.png b/public/-/emojis/1/eight_spoked_asterisk.png
index 3307ffa62ee..3307ffa62ee 100644
--- a/app/assets/images/emoji/eight_spoked_asterisk.png
+++ b/public/-/emojis/1/eight_spoked_asterisk.png
Binary files differ
diff --git a/app/assets/images/emoji/eject.png b/public/-/emojis/1/eject.png
index ec5cfc48973..ec5cfc48973 100644
--- a/app/assets/images/emoji/eject.png
+++ b/public/-/emojis/1/eject.png
Binary files differ
diff --git a/app/assets/images/emoji/electric_plug.png b/public/-/emojis/1/electric_plug.png
index 31d1eb215b4..31d1eb215b4 100644
--- a/app/assets/images/emoji/electric_plug.png
+++ b/public/-/emojis/1/electric_plug.png
Binary files differ
diff --git a/app/assets/images/emoji/elephant.png b/public/-/emojis/1/elephant.png
index b8a6d140595..b8a6d140595 100644
--- a/app/assets/images/emoji/elephant.png
+++ b/public/-/emojis/1/elephant.png
Binary files differ
diff --git a/public/-/emojis/1/emojis.json b/public/-/emojis/1/emojis.json
new file mode 100644
index 00000000000..20a564720d1
--- /dev/null
+++ b/public/-/emojis/1/emojis.json
@@ -0,0 +1,10760 @@
+{
+ "100": {
+ "c": "symbols",
+ "e": "💯",
+ "d": "hundred points symbol",
+ "u": "6.0"
+ },
+ "1234": {
+ "c": "symbols",
+ "e": "🔢",
+ "d": "input symbol for numbers",
+ "u": "6.0"
+ },
+ "8ball": {
+ "c": "activity",
+ "e": "🎱",
+ "d": "billiards",
+ "u": "6.0"
+ },
+ "a": {
+ "c": "symbols",
+ "e": "🅰",
+ "d": "negative squared latin capital letter a",
+ "u": "6.0"
+ },
+ "ab": {
+ "c": "symbols",
+ "e": "🆎",
+ "d": "negative squared ab",
+ "u": "6.0"
+ },
+ "abc": {
+ "c": "symbols",
+ "e": "🔤",
+ "d": "input symbol for latin letters",
+ "u": "6.0"
+ },
+ "abcd": {
+ "c": "symbols",
+ "e": "🔡",
+ "d": "input symbol for latin small letters",
+ "u": "6.0"
+ },
+ "accept": {
+ "c": "symbols",
+ "e": "🉑",
+ "d": "circled ideograph accept",
+ "u": "6.0"
+ },
+ "aerial_tramway": {
+ "c": "travel",
+ "e": "🚡",
+ "d": "aerial tramway",
+ "u": "6.0"
+ },
+ "airplane": {
+ "c": "travel",
+ "e": "✈",
+ "d": "airplane",
+ "u": "1.1"
+ },
+ "airplane_arriving": {
+ "c": "travel",
+ "e": "🛬",
+ "d": "airplane arriving",
+ "u": "7.0"
+ },
+ "airplane_departure": {
+ "c": "travel",
+ "e": "🛫",
+ "d": "airplane departure",
+ "u": "7.0"
+ },
+ "airplane_small": {
+ "c": "travel",
+ "e": "🛩",
+ "d": "small airplane",
+ "u": "7.0"
+ },
+ "alarm_clock": {
+ "c": "objects",
+ "e": "â°",
+ "d": "alarm clock",
+ "u": "6.0"
+ },
+ "alembic": {
+ "c": "objects",
+ "e": "âš—",
+ "d": "alembic",
+ "u": "4.1"
+ },
+ "alien": {
+ "c": "people",
+ "e": "👽",
+ "d": "extraterrestrial alien",
+ "u": "6.0"
+ },
+ "ambulance": {
+ "c": "travel",
+ "e": "🚑",
+ "d": "ambulance",
+ "u": "6.0"
+ },
+ "amphora": {
+ "c": "objects",
+ "e": "ðŸº",
+ "d": "amphora",
+ "u": "8.0"
+ },
+ "anchor": {
+ "c": "travel",
+ "e": "âš“",
+ "d": "anchor",
+ "u": "4.1"
+ },
+ "angel": {
+ "c": "people",
+ "e": "👼",
+ "d": "baby angel",
+ "u": "6.0"
+ },
+ "angel_tone1": {
+ "c": "people",
+ "e": "👼ðŸ»",
+ "d": "baby angel tone 1",
+ "u": "8.0"
+ },
+ "angel_tone2": {
+ "c": "people",
+ "e": "👼ðŸ¼",
+ "d": "baby angel tone 2",
+ "u": "8.0"
+ },
+ "angel_tone3": {
+ "c": "people",
+ "e": "👼ðŸ½",
+ "d": "baby angel tone 3",
+ "u": "8.0"
+ },
+ "angel_tone4": {
+ "c": "people",
+ "e": "👼ðŸ¾",
+ "d": "baby angel tone 4",
+ "u": "8.0"
+ },
+ "angel_tone5": {
+ "c": "people",
+ "e": "👼ðŸ¿",
+ "d": "baby angel tone 5",
+ "u": "8.0"
+ },
+ "anger": {
+ "c": "symbols",
+ "e": "💢",
+ "d": "anger symbol",
+ "u": "6.0"
+ },
+ "anger_right": {
+ "c": "symbols",
+ "e": "🗯",
+ "d": "right anger bubble",
+ "u": "7.0"
+ },
+ "angry": {
+ "c": "people",
+ "e": "😠",
+ "d": "angry face",
+ "u": "6.0"
+ },
+ "ant": {
+ "c": "nature",
+ "e": "ðŸœ",
+ "d": "ant",
+ "u": "6.0"
+ },
+ "apple": {
+ "c": "food",
+ "e": "ðŸŽ",
+ "d": "red apple",
+ "u": "6.0"
+ },
+ "aquarius": {
+ "c": "symbols",
+ "e": "â™’",
+ "d": "aquarius",
+ "u": "1.1"
+ },
+ "aries": {
+ "c": "symbols",
+ "e": "♈",
+ "d": "aries",
+ "u": "1.1"
+ },
+ "arrow_backward": {
+ "c": "symbols",
+ "e": "â—€",
+ "d": "black left-pointing triangle",
+ "u": "1.1"
+ },
+ "arrow_double_down": {
+ "c": "symbols",
+ "e": "â¬",
+ "d": "black down-pointing double triangle",
+ "u": "6.0"
+ },
+ "arrow_double_up": {
+ "c": "symbols",
+ "e": "â«",
+ "d": "black up-pointing double triangle",
+ "u": "6.0"
+ },
+ "arrow_down": {
+ "c": "symbols",
+ "e": "⬇",
+ "d": "downwards black arrow",
+ "u": "4.0"
+ },
+ "arrow_down_small": {
+ "c": "symbols",
+ "e": "🔽",
+ "d": "down-pointing small red triangle",
+ "u": "6.0"
+ },
+ "arrow_forward": {
+ "c": "symbols",
+ "e": "â–¶",
+ "d": "black right-pointing triangle",
+ "u": "1.1"
+ },
+ "arrow_heading_down": {
+ "c": "symbols",
+ "e": "⤵",
+ "d": "arrow pointing rightwards then curving downwards",
+ "u": "3.2"
+ },
+ "arrow_heading_up": {
+ "c": "symbols",
+ "e": "⤴",
+ "d": "arrow pointing rightwards then curving upwards",
+ "u": "3.2"
+ },
+ "arrow_left": {
+ "c": "symbols",
+ "e": "⬅",
+ "d": "leftwards black arrow",
+ "u": "4.0"
+ },
+ "arrow_lower_left": {
+ "c": "symbols",
+ "e": "↙",
+ "d": "south west arrow",
+ "u": "1.1"
+ },
+ "arrow_lower_right": {
+ "c": "symbols",
+ "e": "↘",
+ "d": "south east arrow",
+ "u": "1.1"
+ },
+ "arrow_right": {
+ "c": "symbols",
+ "e": "âž¡",
+ "d": "black rightwards arrow",
+ "u": "1.1"
+ },
+ "arrow_right_hook": {
+ "c": "symbols",
+ "e": "↪",
+ "d": "rightwards arrow with hook",
+ "u": "1.1"
+ },
+ "arrow_up": {
+ "c": "symbols",
+ "e": "⬆",
+ "d": "upwards black arrow",
+ "u": "4.0"
+ },
+ "arrow_up_down": {
+ "c": "symbols",
+ "e": "↕",
+ "d": "up down arrow",
+ "u": "1.1"
+ },
+ "arrow_up_small": {
+ "c": "symbols",
+ "e": "🔼",
+ "d": "up-pointing small red triangle",
+ "u": "6.0"
+ },
+ "arrow_upper_left": {
+ "c": "symbols",
+ "e": "↖",
+ "d": "north west arrow",
+ "u": "1.1"
+ },
+ "arrow_upper_right": {
+ "c": "symbols",
+ "e": "↗",
+ "d": "north east arrow",
+ "u": "1.1"
+ },
+ "arrows_clockwise": {
+ "c": "symbols",
+ "e": "🔃",
+ "d": "clockwise downwards and upwards open circle arrows",
+ "u": "6.0"
+ },
+ "arrows_counterclockwise": {
+ "c": "symbols",
+ "e": "🔄",
+ "d": "anticlockwise downwards and upwards open circle ar",
+ "u": "6.0"
+ },
+ "art": {
+ "c": "activity",
+ "e": "🎨",
+ "d": "artist palette",
+ "u": "6.0"
+ },
+ "articulated_lorry": {
+ "c": "travel",
+ "e": "🚛",
+ "d": "articulated lorry",
+ "u": "6.0"
+ },
+ "asterisk": {
+ "c": "symbols",
+ "e": "*⃣",
+ "d": "keycap asterisk",
+ "u": "3.0"
+ },
+ "astonished": {
+ "c": "people",
+ "e": "😲",
+ "d": "astonished face",
+ "u": "6.0"
+ },
+ "athletic_shoe": {
+ "c": "people",
+ "e": "👟",
+ "d": "athletic shoe",
+ "u": "6.0"
+ },
+ "atm": {
+ "c": "symbols",
+ "e": "ðŸ§",
+ "d": "automated teller machine",
+ "u": "6.0"
+ },
+ "atom": {
+ "c": "symbols",
+ "e": "âš›",
+ "d": "atom symbol",
+ "u": "4.1"
+ },
+ "avocado": {
+ "c": "food",
+ "e": "🥑",
+ "d": "avocado",
+ "u": "9.0"
+ },
+ "b": {
+ "c": "symbols",
+ "e": "🅱",
+ "d": "negative squared latin capital letter b",
+ "u": "6.0"
+ },
+ "baby": {
+ "c": "people",
+ "e": "👶",
+ "d": "baby",
+ "u": "6.0"
+ },
+ "baby_bottle": {
+ "c": "food",
+ "e": "ðŸ¼",
+ "d": "baby bottle",
+ "u": "6.0"
+ },
+ "baby_chick": {
+ "c": "nature",
+ "e": "ðŸ¤",
+ "d": "baby chick",
+ "u": "6.0"
+ },
+ "baby_symbol": {
+ "c": "symbols",
+ "e": "🚼",
+ "d": "baby symbol",
+ "u": "6.0"
+ },
+ "baby_tone1": {
+ "c": "people",
+ "e": "👶ðŸ»",
+ "d": "baby tone 1",
+ "u": "8.0"
+ },
+ "baby_tone2": {
+ "c": "people",
+ "e": "👶ðŸ¼",
+ "d": "baby tone 2",
+ "u": "8.0"
+ },
+ "baby_tone3": {
+ "c": "people",
+ "e": "👶ðŸ½",
+ "d": "baby tone 3",
+ "u": "8.0"
+ },
+ "baby_tone4": {
+ "c": "people",
+ "e": "👶ðŸ¾",
+ "d": "baby tone 4",
+ "u": "8.0"
+ },
+ "baby_tone5": {
+ "c": "people",
+ "e": "👶ðŸ¿",
+ "d": "baby tone 5",
+ "u": "8.0"
+ },
+ "back": {
+ "c": "symbols",
+ "e": "🔙",
+ "d": "back with leftwards arrow above",
+ "u": "6.0"
+ },
+ "bacon": {
+ "c": "food",
+ "e": "🥓",
+ "d": "bacon",
+ "u": "9.0"
+ },
+ "badminton": {
+ "c": "activity",
+ "e": "ðŸ¸",
+ "d": "badminton racquet",
+ "u": "8.0"
+ },
+ "baggage_claim": {
+ "c": "symbols",
+ "e": "🛄",
+ "d": "baggage claim",
+ "u": "6.0"
+ },
+ "balloon": {
+ "c": "objects",
+ "e": "🎈",
+ "d": "balloon",
+ "u": "6.0"
+ },
+ "ballot_box": {
+ "c": "objects",
+ "e": "🗳",
+ "d": "ballot box with ballot",
+ "u": "7.0"
+ },
+ "ballot_box_with_check": {
+ "c": "symbols",
+ "e": "☑",
+ "d": "ballot box with check",
+ "u": "1.1"
+ },
+ "bamboo": {
+ "c": "nature",
+ "e": "ðŸŽ",
+ "d": "pine decoration",
+ "u": "6.0"
+ },
+ "banana": {
+ "c": "food",
+ "e": "ðŸŒ",
+ "d": "banana",
+ "u": "6.0"
+ },
+ "bangbang": {
+ "c": "symbols",
+ "e": "‼",
+ "d": "double exclamation mark",
+ "u": "1.1"
+ },
+ "bank": {
+ "c": "travel",
+ "e": "ðŸ¦",
+ "d": "bank",
+ "u": "6.0"
+ },
+ "bar_chart": {
+ "c": "objects",
+ "e": "📊",
+ "d": "bar chart",
+ "u": "6.0"
+ },
+ "barber": {
+ "c": "objects",
+ "e": "💈",
+ "d": "barber pole",
+ "u": "6.0"
+ },
+ "baseball": {
+ "c": "activity",
+ "e": "âš¾",
+ "d": "baseball",
+ "u": "5.2"
+ },
+ "basketball": {
+ "c": "activity",
+ "e": "ðŸ€",
+ "d": "basketball and hoop",
+ "u": "6.0"
+ },
+ "basketball_player": {
+ "c": "activity",
+ "e": "⛹",
+ "d": "person with ball",
+ "u": "5.2"
+ },
+ "basketball_player_tone1": {
+ "c": "activity",
+ "e": "⛹ðŸ»",
+ "d": "person with ball tone 1",
+ "u": "8.0"
+ },
+ "basketball_player_tone2": {
+ "c": "activity",
+ "e": "⛹ðŸ¼",
+ "d": "person with ball tone 2",
+ "u": "8.0"
+ },
+ "basketball_player_tone3": {
+ "c": "activity",
+ "e": "⛹ðŸ½",
+ "d": "person with ball tone 3",
+ "u": "8.0"
+ },
+ "basketball_player_tone4": {
+ "c": "activity",
+ "e": "⛹ðŸ¾",
+ "d": "person with ball tone 4",
+ "u": "8.0"
+ },
+ "basketball_player_tone5": {
+ "c": "activity",
+ "e": "⛹ðŸ¿",
+ "d": "person with ball tone 5",
+ "u": "8.0"
+ },
+ "bat": {
+ "c": "nature",
+ "e": "🦇",
+ "d": "bat",
+ "u": "9.0"
+ },
+ "bath": {
+ "c": "activity",
+ "e": "🛀",
+ "d": "bath",
+ "u": "6.0"
+ },
+ "bath_tone1": {
+ "c": "activity",
+ "e": "🛀ðŸ»",
+ "d": "bath tone 1",
+ "u": "8.0"
+ },
+ "bath_tone2": {
+ "c": "activity",
+ "e": "🛀ðŸ¼",
+ "d": "bath tone 2",
+ "u": "8.0"
+ },
+ "bath_tone3": {
+ "c": "activity",
+ "e": "🛀ðŸ½",
+ "d": "bath tone 3",
+ "u": "8.0"
+ },
+ "bath_tone4": {
+ "c": "activity",
+ "e": "🛀ðŸ¾",
+ "d": "bath tone 4",
+ "u": "8.0"
+ },
+ "bath_tone5": {
+ "c": "activity",
+ "e": "🛀ðŸ¿",
+ "d": "bath tone 5",
+ "u": "8.0"
+ },
+ "bathtub": {
+ "c": "objects",
+ "e": "ðŸ›",
+ "d": "bathtub",
+ "u": "6.0"
+ },
+ "battery": {
+ "c": "objects",
+ "e": "🔋",
+ "d": "battery",
+ "u": "6.0"
+ },
+ "beach": {
+ "c": "travel",
+ "e": "ðŸ–",
+ "d": "beach with umbrella",
+ "u": "7.0"
+ },
+ "beach_umbrella": {
+ "c": "objects",
+ "e": "â›±",
+ "d": "umbrella on ground",
+ "u": "5.2"
+ },
+ "bear": {
+ "c": "nature",
+ "e": "ðŸ»",
+ "d": "bear face",
+ "u": "6.0"
+ },
+ "bed": {
+ "c": "objects",
+ "e": "ðŸ›",
+ "d": "bed",
+ "u": "7.0"
+ },
+ "bee": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "honeybee",
+ "u": "6.0"
+ },
+ "beer": {
+ "c": "food",
+ "e": "ðŸº",
+ "d": "beer mug",
+ "u": "6.0"
+ },
+ "beers": {
+ "c": "food",
+ "e": "ðŸ»",
+ "d": "clinking beer mugs",
+ "u": "6.0"
+ },
+ "beetle": {
+ "c": "nature",
+ "e": "ðŸž",
+ "d": "lady beetle",
+ "u": "6.0"
+ },
+ "beginner": {
+ "c": "symbols",
+ "e": "🔰",
+ "d": "japanese symbol for beginner",
+ "u": "6.0"
+ },
+ "bell": {
+ "c": "symbols",
+ "e": "🔔",
+ "d": "bell",
+ "u": "6.0"
+ },
+ "bellhop": {
+ "c": "objects",
+ "e": "🛎",
+ "d": "bellhop bell",
+ "u": "7.0"
+ },
+ "bento": {
+ "c": "food",
+ "e": "ðŸ±",
+ "d": "bento box",
+ "u": "6.0"
+ },
+ "bicyclist": {
+ "c": "activity",
+ "e": "🚴",
+ "d": "bicyclist",
+ "u": "6.0"
+ },
+ "bicyclist_tone1": {
+ "c": "activity",
+ "e": "🚴ðŸ»",
+ "d": "bicyclist tone 1",
+ "u": "8.0"
+ },
+ "bicyclist_tone2": {
+ "c": "activity",
+ "e": "🚴ðŸ¼",
+ "d": "bicyclist tone 2",
+ "u": "8.0"
+ },
+ "bicyclist_tone3": {
+ "c": "activity",
+ "e": "🚴ðŸ½",
+ "d": "bicyclist tone 3",
+ "u": "8.0"
+ },
+ "bicyclist_tone4": {
+ "c": "activity",
+ "e": "🚴ðŸ¾",
+ "d": "bicyclist tone 4",
+ "u": "8.0"
+ },
+ "bicyclist_tone5": {
+ "c": "activity",
+ "e": "🚴ðŸ¿",
+ "d": "bicyclist tone 5",
+ "u": "8.0"
+ },
+ "bike": {
+ "c": "travel",
+ "e": "🚲",
+ "d": "bicycle",
+ "u": "6.0"
+ },
+ "bikini": {
+ "c": "people",
+ "e": "👙",
+ "d": "bikini",
+ "u": "6.0"
+ },
+ "biohazard": {
+ "c": "symbols",
+ "e": "☣",
+ "d": "biohazard sign",
+ "u": "1.1"
+ },
+ "bird": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "bird",
+ "u": "6.0"
+ },
+ "birthday": {
+ "c": "food",
+ "e": "🎂",
+ "d": "birthday cake",
+ "u": "6.0"
+ },
+ "black_circle": {
+ "c": "symbols",
+ "e": "âš«",
+ "d": "medium black circle",
+ "u": "4.1"
+ },
+ "black_heart": {
+ "c": "symbols",
+ "e": "🖤",
+ "d": "black heart",
+ "u": "9.0"
+ },
+ "black_joker": {
+ "c": "symbols",
+ "e": "ðŸƒ",
+ "d": "playing card black joker",
+ "u": "6.0"
+ },
+ "black_large_square": {
+ "c": "symbols",
+ "e": "⬛",
+ "d": "black large square",
+ "u": "5.1"
+ },
+ "black_medium_small_square": {
+ "c": "symbols",
+ "e": "â—¾",
+ "d": "black medium small square",
+ "u": "3.2"
+ },
+ "black_medium_square": {
+ "c": "symbols",
+ "e": "â—¼",
+ "d": "black medium square",
+ "u": "3.2"
+ },
+ "black_nib": {
+ "c": "objects",
+ "e": "✒",
+ "d": "black nib",
+ "u": "1.1"
+ },
+ "black_small_square": {
+ "c": "symbols",
+ "e": "â–ª",
+ "d": "black small square",
+ "u": "1.1"
+ },
+ "black_square_button": {
+ "c": "symbols",
+ "e": "🔲",
+ "d": "black square button",
+ "u": "6.0"
+ },
+ "blossom": {
+ "c": "nature",
+ "e": "🌼",
+ "d": "blossom",
+ "u": "6.0"
+ },
+ "blowfish": {
+ "c": "nature",
+ "e": "ðŸ¡",
+ "d": "blowfish",
+ "u": "6.0"
+ },
+ "blue_book": {
+ "c": "objects",
+ "e": "📘",
+ "d": "blue book",
+ "u": "6.0"
+ },
+ "blue_car": {
+ "c": "travel",
+ "e": "🚙",
+ "d": "recreational vehicle",
+ "u": "6.0"
+ },
+ "blue_heart": {
+ "c": "symbols",
+ "e": "💙",
+ "d": "blue heart",
+ "u": "6.0"
+ },
+ "blush": {
+ "c": "people",
+ "e": "😊",
+ "d": "smiling face with smiling eyes",
+ "u": "6.0"
+ },
+ "boar": {
+ "c": "nature",
+ "e": "ðŸ—",
+ "d": "boar",
+ "u": "6.0"
+ },
+ "bomb": {
+ "c": "objects",
+ "e": "💣",
+ "d": "bomb",
+ "u": "6.0"
+ },
+ "book": {
+ "c": "objects",
+ "e": "📖",
+ "d": "open book",
+ "u": "6.0"
+ },
+ "bookmark": {
+ "c": "objects",
+ "e": "🔖",
+ "d": "bookmark",
+ "u": "6.0"
+ },
+ "bookmark_tabs": {
+ "c": "objects",
+ "e": "📑",
+ "d": "bookmark tabs",
+ "u": "6.0"
+ },
+ "books": {
+ "c": "objects",
+ "e": "📚",
+ "d": "books",
+ "u": "6.0"
+ },
+ "boom": {
+ "c": "nature",
+ "e": "💥",
+ "d": "collision symbol",
+ "u": "6.0"
+ },
+ "boot": {
+ "c": "people",
+ "e": "👢",
+ "d": "womans boots",
+ "u": "6.0"
+ },
+ "bouquet": {
+ "c": "nature",
+ "e": "ðŸ’",
+ "d": "bouquet",
+ "u": "6.0"
+ },
+ "bow": {
+ "c": "people",
+ "e": "🙇",
+ "d": "person bowing deeply",
+ "u": "6.0"
+ },
+ "bow_and_arrow": {
+ "c": "activity",
+ "e": "ðŸ¹",
+ "d": "bow and arrow",
+ "u": "8.0"
+ },
+ "bow_tone1": {
+ "c": "people",
+ "e": "🙇ðŸ»",
+ "d": "person bowing deeply tone 1",
+ "u": "8.0"
+ },
+ "bow_tone2": {
+ "c": "people",
+ "e": "🙇ðŸ¼",
+ "d": "person bowing deeply tone 2",
+ "u": "8.0"
+ },
+ "bow_tone3": {
+ "c": "people",
+ "e": "🙇ðŸ½",
+ "d": "person bowing deeply tone 3",
+ "u": "8.0"
+ },
+ "bow_tone4": {
+ "c": "people",
+ "e": "🙇ðŸ¾",
+ "d": "person bowing deeply tone 4",
+ "u": "8.0"
+ },
+ "bow_tone5": {
+ "c": "people",
+ "e": "🙇ðŸ¿",
+ "d": "person bowing deeply tone 5",
+ "u": "8.0"
+ },
+ "bowling": {
+ "c": "activity",
+ "e": "🎳",
+ "d": "bowling",
+ "u": "6.0"
+ },
+ "boxing_glove": {
+ "c": "activity",
+ "e": "🥊",
+ "d": "boxing glove",
+ "u": "9.0"
+ },
+ "boy": {
+ "c": "people",
+ "e": "👦",
+ "d": "boy",
+ "u": "6.0"
+ },
+ "boy_tone1": {
+ "c": "people",
+ "e": "👦ðŸ»",
+ "d": "boy tone 1",
+ "u": "8.0"
+ },
+ "boy_tone2": {
+ "c": "people",
+ "e": "👦ðŸ¼",
+ "d": "boy tone 2",
+ "u": "8.0"
+ },
+ "boy_tone3": {
+ "c": "people",
+ "e": "👦ðŸ½",
+ "d": "boy tone 3",
+ "u": "8.0"
+ },
+ "boy_tone4": {
+ "c": "people",
+ "e": "👦ðŸ¾",
+ "d": "boy tone 4",
+ "u": "8.0"
+ },
+ "boy_tone5": {
+ "c": "people",
+ "e": "👦ðŸ¿",
+ "d": "boy tone 5",
+ "u": "8.0"
+ },
+ "bread": {
+ "c": "food",
+ "e": "ðŸž",
+ "d": "bread",
+ "u": "6.0"
+ },
+ "bride_with_veil": {
+ "c": "people",
+ "e": "👰",
+ "d": "bride with veil",
+ "u": "6.0"
+ },
+ "bride_with_veil_tone1": {
+ "c": "people",
+ "e": "👰ðŸ»",
+ "d": "bride with veil tone 1",
+ "u": "8.0"
+ },
+ "bride_with_veil_tone2": {
+ "c": "people",
+ "e": "👰ðŸ¼",
+ "d": "bride with veil tone 2",
+ "u": "8.0"
+ },
+ "bride_with_veil_tone3": {
+ "c": "people",
+ "e": "👰ðŸ½",
+ "d": "bride with veil tone 3",
+ "u": "8.0"
+ },
+ "bride_with_veil_tone4": {
+ "c": "people",
+ "e": "👰ðŸ¾",
+ "d": "bride with veil tone 4",
+ "u": "8.0"
+ },
+ "bride_with_veil_tone5": {
+ "c": "people",
+ "e": "👰ðŸ¿",
+ "d": "bride with veil tone 5",
+ "u": "8.0"
+ },
+ "bridge_at_night": {
+ "c": "travel",
+ "e": "🌉",
+ "d": "bridge at night",
+ "u": "6.0"
+ },
+ "briefcase": {
+ "c": "people",
+ "e": "💼",
+ "d": "briefcase",
+ "u": "6.0"
+ },
+ "broken_heart": {
+ "c": "symbols",
+ "e": "💔",
+ "d": "broken heart",
+ "u": "6.0"
+ },
+ "bug": {
+ "c": "nature",
+ "e": "ðŸ›",
+ "d": "bug",
+ "u": "6.0"
+ },
+ "bulb": {
+ "c": "objects",
+ "e": "💡",
+ "d": "electric light bulb",
+ "u": "6.0"
+ },
+ "bullettrain_front": {
+ "c": "travel",
+ "e": "🚅",
+ "d": "high-speed train with bullet nose",
+ "u": "6.0"
+ },
+ "bullettrain_side": {
+ "c": "travel",
+ "e": "🚄",
+ "d": "high-speed train",
+ "u": "6.0"
+ },
+ "burrito": {
+ "c": "food",
+ "e": "🌯",
+ "d": "burrito",
+ "u": "8.0"
+ },
+ "bus": {
+ "c": "travel",
+ "e": "🚌",
+ "d": "bus",
+ "u": "6.0"
+ },
+ "busstop": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "bus stop",
+ "u": "6.0"
+ },
+ "bust_in_silhouette": {
+ "c": "people",
+ "e": "👤",
+ "d": "bust in silhouette",
+ "u": "6.0"
+ },
+ "busts_in_silhouette": {
+ "c": "people",
+ "e": "👥",
+ "d": "busts in silhouette",
+ "u": "6.0"
+ },
+ "butterfly": {
+ "c": "nature",
+ "e": "🦋",
+ "d": "butterfly",
+ "u": "9.0"
+ },
+ "cactus": {
+ "c": "nature",
+ "e": "🌵",
+ "d": "cactus",
+ "u": "6.0"
+ },
+ "cake": {
+ "c": "food",
+ "e": "ðŸ°",
+ "d": "shortcake",
+ "u": "6.0"
+ },
+ "calendar": {
+ "c": "objects",
+ "e": "📆",
+ "d": "tear-off calendar",
+ "u": "6.0"
+ },
+ "calendar_spiral": {
+ "c": "objects",
+ "e": "🗓",
+ "d": "spiral calendar pad",
+ "u": "7.0"
+ },
+ "call_me": {
+ "c": "people",
+ "e": "🤙",
+ "d": "call me hand",
+ "u": "9.0"
+ },
+ "call_me_tone1": {
+ "c": "people",
+ "e": "🤙ðŸ»",
+ "d": "call me hand tone 1",
+ "u": "9.0"
+ },
+ "call_me_tone2": {
+ "c": "people",
+ "e": "🤙ðŸ¼",
+ "d": "call me hand tone 2",
+ "u": "9.0"
+ },
+ "call_me_tone3": {
+ "c": "people",
+ "e": "🤙ðŸ½",
+ "d": "call me hand tone 3",
+ "u": "9.0"
+ },
+ "call_me_tone4": {
+ "c": "people",
+ "e": "🤙ðŸ¾",
+ "d": "call me hand tone 4",
+ "u": "9.0"
+ },
+ "call_me_tone5": {
+ "c": "people",
+ "e": "🤙ðŸ¿",
+ "d": "call me hand tone 5",
+ "u": "9.0"
+ },
+ "calling": {
+ "c": "objects",
+ "e": "📲",
+ "d": "mobile phone with rightwards arrow at left",
+ "u": "6.0"
+ },
+ "camel": {
+ "c": "nature",
+ "e": "ðŸ«",
+ "d": "bactrian camel",
+ "u": "6.0"
+ },
+ "camera": {
+ "c": "objects",
+ "e": "📷",
+ "d": "camera",
+ "u": "6.0"
+ },
+ "camera_with_flash": {
+ "c": "objects",
+ "e": "📸",
+ "d": "camera with flash",
+ "u": "7.0"
+ },
+ "camping": {
+ "c": "travel",
+ "e": "ðŸ•",
+ "d": "camping",
+ "u": "7.0"
+ },
+ "cancer": {
+ "c": "symbols",
+ "e": "♋",
+ "d": "cancer",
+ "u": "1.1"
+ },
+ "candle": {
+ "c": "objects",
+ "e": "🕯",
+ "d": "candle",
+ "u": "7.0"
+ },
+ "candy": {
+ "c": "food",
+ "e": "ðŸ¬",
+ "d": "candy",
+ "u": "6.0"
+ },
+ "canoe": {
+ "c": "travel",
+ "e": "🛶",
+ "d": "canoe",
+ "u": "9.0"
+ },
+ "capital_abcd": {
+ "c": "symbols",
+ "e": "🔠",
+ "d": "input symbol for latin capital letters",
+ "u": "6.0"
+ },
+ "capricorn": {
+ "c": "symbols",
+ "e": "♑",
+ "d": "capricorn",
+ "u": "1.1"
+ },
+ "card_box": {
+ "c": "objects",
+ "e": "🗃",
+ "d": "card file box",
+ "u": "7.0"
+ },
+ "card_index": {
+ "c": "objects",
+ "e": "📇",
+ "d": "card index",
+ "u": "6.0"
+ },
+ "carousel_horse": {
+ "c": "travel",
+ "e": "🎠",
+ "d": "carousel horse",
+ "u": "6.0"
+ },
+ "carrot": {
+ "c": "food",
+ "e": "🥕",
+ "d": "carrot",
+ "u": "9.0"
+ },
+ "cartwheel": {
+ "c": "activity",
+ "e": "🤸",
+ "d": "person doing cartwheel",
+ "u": "9.0"
+ },
+ "cartwheel_tone1": {
+ "c": "activity",
+ "e": "🤸ðŸ»",
+ "d": "person doing cartwheel tone 1",
+ "u": "9.0"
+ },
+ "cartwheel_tone2": {
+ "c": "activity",
+ "e": "🤸ðŸ¼",
+ "d": "person doing cartwheel tone 2",
+ "u": "9.0"
+ },
+ "cartwheel_tone3": {
+ "c": "activity",
+ "e": "🤸ðŸ½",
+ "d": "person doing cartwheel tone 3",
+ "u": "9.0"
+ },
+ "cartwheel_tone4": {
+ "c": "activity",
+ "e": "🤸ðŸ¾",
+ "d": "person doing cartwheel tone 4",
+ "u": "9.0"
+ },
+ "cartwheel_tone5": {
+ "c": "activity",
+ "e": "🤸ðŸ¿",
+ "d": "person doing cartwheel tone 5",
+ "u": "9.0"
+ },
+ "cat": {
+ "c": "nature",
+ "e": "ðŸ±",
+ "d": "cat face",
+ "u": "6.0"
+ },
+ "cat2": {
+ "c": "nature",
+ "e": "ðŸˆ",
+ "d": "cat",
+ "u": "6.0"
+ },
+ "cd": {
+ "c": "objects",
+ "e": "💿",
+ "d": "optical disc",
+ "u": "6.0"
+ },
+ "chains": {
+ "c": "objects",
+ "e": "⛓",
+ "d": "chains",
+ "u": "5.2"
+ },
+ "champagne": {
+ "c": "food",
+ "e": "ðŸ¾",
+ "d": "bottle with popping cork",
+ "u": "8.0"
+ },
+ "champagne_glass": {
+ "c": "food",
+ "e": "🥂",
+ "d": "clinking glasses",
+ "u": "9.0"
+ },
+ "chart": {
+ "c": "symbols",
+ "e": "💹",
+ "d": "chart with upwards trend and yen sign",
+ "u": "6.0"
+ },
+ "chart_with_downwards_trend": {
+ "c": "objects",
+ "e": "📉",
+ "d": "chart with downwards trend",
+ "u": "6.0"
+ },
+ "chart_with_upwards_trend": {
+ "c": "objects",
+ "e": "📈",
+ "d": "chart with upwards trend",
+ "u": "6.0"
+ },
+ "checkered_flag": {
+ "c": "travel",
+ "e": "ðŸ",
+ "d": "chequered flag",
+ "u": "6.0"
+ },
+ "cheese": {
+ "c": "food",
+ "e": "🧀",
+ "d": "cheese wedge",
+ "u": "8.0"
+ },
+ "cherries": {
+ "c": "food",
+ "e": "ðŸ’",
+ "d": "cherries",
+ "u": "6.0"
+ },
+ "cherry_blossom": {
+ "c": "nature",
+ "e": "🌸",
+ "d": "cherry blossom",
+ "u": "6.0"
+ },
+ "chestnut": {
+ "c": "nature",
+ "e": "🌰",
+ "d": "chestnut",
+ "u": "6.0"
+ },
+ "chicken": {
+ "c": "nature",
+ "e": "ðŸ”",
+ "d": "chicken",
+ "u": "6.0"
+ },
+ "children_crossing": {
+ "c": "symbols",
+ "e": "🚸",
+ "d": "children crossing",
+ "u": "6.0"
+ },
+ "chipmunk": {
+ "c": "nature",
+ "e": "ðŸ¿",
+ "d": "chipmunk",
+ "u": "7.0"
+ },
+ "chocolate_bar": {
+ "c": "food",
+ "e": "ðŸ«",
+ "d": "chocolate bar",
+ "u": "6.0"
+ },
+ "christmas_tree": {
+ "c": "nature",
+ "e": "🎄",
+ "d": "christmas tree",
+ "u": "6.0"
+ },
+ "church": {
+ "c": "travel",
+ "e": "⛪",
+ "d": "church",
+ "u": "5.2"
+ },
+ "cinema": {
+ "c": "symbols",
+ "e": "🎦",
+ "d": "cinema",
+ "u": "6.0"
+ },
+ "circus_tent": {
+ "c": "activity",
+ "e": "🎪",
+ "d": "circus tent",
+ "u": "6.0"
+ },
+ "city_dusk": {
+ "c": "travel",
+ "e": "🌆",
+ "d": "cityscape at dusk",
+ "u": "6.0"
+ },
+ "city_sunset": {
+ "c": "travel",
+ "e": "🌇",
+ "d": "sunset over buildings",
+ "u": "6.0"
+ },
+ "cityscape": {
+ "c": "travel",
+ "e": "ðŸ™",
+ "d": "cityscape",
+ "u": "7.0"
+ },
+ "cl": {
+ "c": "symbols",
+ "e": "🆑",
+ "d": "squared cl",
+ "u": "6.0"
+ },
+ "clap": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "clapping hands sign",
+ "u": "6.0"
+ },
+ "clap_tone1": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ»",
+ "d": "clapping hands sign tone 1",
+ "u": "8.0"
+ },
+ "clap_tone2": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¼",
+ "d": "clapping hands sign tone 2",
+ "u": "8.0"
+ },
+ "clap_tone3": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ½",
+ "d": "clapping hands sign tone 3",
+ "u": "8.0"
+ },
+ "clap_tone4": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¾",
+ "d": "clapping hands sign tone 4",
+ "u": "8.0"
+ },
+ "clap_tone5": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¿",
+ "d": "clapping hands sign tone 5",
+ "u": "8.0"
+ },
+ "clapper": {
+ "c": "activity",
+ "e": "🎬",
+ "d": "clapper board",
+ "u": "6.0"
+ },
+ "classical_building": {
+ "c": "travel",
+ "e": "ðŸ›",
+ "d": "classical building",
+ "u": "7.0"
+ },
+ "clipboard": {
+ "c": "objects",
+ "e": "📋",
+ "d": "clipboard",
+ "u": "6.0"
+ },
+ "clock": {
+ "c": "objects",
+ "e": "🕰",
+ "d": "mantlepiece clock",
+ "u": "7.0"
+ },
+ "clock1": {
+ "c": "symbols",
+ "e": "ðŸ•",
+ "d": "clock face one oclock",
+ "u": "6.0"
+ },
+ "clock10": {
+ "c": "symbols",
+ "e": "🕙",
+ "d": "clock face ten oclock",
+ "u": "6.0"
+ },
+ "clock1030": {
+ "c": "symbols",
+ "e": "🕥",
+ "d": "clock face ten-thirty",
+ "u": "6.0"
+ },
+ "clock11": {
+ "c": "symbols",
+ "e": "🕚",
+ "d": "clock face eleven oclock",
+ "u": "6.0"
+ },
+ "clock1130": {
+ "c": "symbols",
+ "e": "🕦",
+ "d": "clock face eleven-thirty",
+ "u": "6.0"
+ },
+ "clock12": {
+ "c": "symbols",
+ "e": "🕛",
+ "d": "clock face twelve oclock",
+ "u": "6.0"
+ },
+ "clock1230": {
+ "c": "symbols",
+ "e": "🕧",
+ "d": "clock face twelve-thirty",
+ "u": "6.0"
+ },
+ "clock130": {
+ "c": "symbols",
+ "e": "🕜",
+ "d": "clock face one-thirty",
+ "u": "6.0"
+ },
+ "clock2": {
+ "c": "symbols",
+ "e": "🕑",
+ "d": "clock face two oclock",
+ "u": "6.0"
+ },
+ "clock230": {
+ "c": "symbols",
+ "e": "ðŸ•",
+ "d": "clock face two-thirty",
+ "u": "6.0"
+ },
+ "clock3": {
+ "c": "symbols",
+ "e": "🕒",
+ "d": "clock face three oclock",
+ "u": "6.0"
+ },
+ "clock330": {
+ "c": "symbols",
+ "e": "🕞",
+ "d": "clock face three-thirty",
+ "u": "6.0"
+ },
+ "clock4": {
+ "c": "symbols",
+ "e": "🕓",
+ "d": "clock face four oclock",
+ "u": "6.0"
+ },
+ "clock430": {
+ "c": "symbols",
+ "e": "🕟",
+ "d": "clock face four-thirty",
+ "u": "6.0"
+ },
+ "clock5": {
+ "c": "symbols",
+ "e": "🕔",
+ "d": "clock face five oclock",
+ "u": "6.0"
+ },
+ "clock530": {
+ "c": "symbols",
+ "e": "🕠",
+ "d": "clock face five-thirty",
+ "u": "6.0"
+ },
+ "clock6": {
+ "c": "symbols",
+ "e": "🕕",
+ "d": "clock face six oclock",
+ "u": "6.0"
+ },
+ "clock630": {
+ "c": "symbols",
+ "e": "🕡",
+ "d": "clock face six-thirty",
+ "u": "6.0"
+ },
+ "clock7": {
+ "c": "symbols",
+ "e": "🕖",
+ "d": "clock face seven oclock",
+ "u": "6.0"
+ },
+ "clock730": {
+ "c": "symbols",
+ "e": "🕢",
+ "d": "clock face seven-thirty",
+ "u": "6.0"
+ },
+ "clock8": {
+ "c": "symbols",
+ "e": "🕗",
+ "d": "clock face eight oclock",
+ "u": "6.0"
+ },
+ "clock830": {
+ "c": "symbols",
+ "e": "🕣",
+ "d": "clock face eight-thirty",
+ "u": "6.0"
+ },
+ "clock9": {
+ "c": "symbols",
+ "e": "🕘",
+ "d": "clock face nine oclock",
+ "u": "6.0"
+ },
+ "clock930": {
+ "c": "symbols",
+ "e": "🕤",
+ "d": "clock face nine-thirty",
+ "u": "6.0"
+ },
+ "closed_book": {
+ "c": "objects",
+ "e": "📕",
+ "d": "closed book",
+ "u": "6.0"
+ },
+ "closed_lock_with_key": {
+ "c": "objects",
+ "e": "ðŸ”",
+ "d": "closed lock with key",
+ "u": "6.0"
+ },
+ "closed_umbrella": {
+ "c": "people",
+ "e": "🌂",
+ "d": "closed umbrella",
+ "u": "6.0"
+ },
+ "cloud": {
+ "c": "nature",
+ "e": "â˜",
+ "d": "cloud",
+ "u": "1.1"
+ },
+ "cloud_lightning": {
+ "c": "nature",
+ "e": "🌩",
+ "d": "cloud with lightning",
+ "u": "7.0"
+ },
+ "cloud_rain": {
+ "c": "nature",
+ "e": "🌧",
+ "d": "cloud with rain",
+ "u": "7.0"
+ },
+ "cloud_snow": {
+ "c": "nature",
+ "e": "🌨",
+ "d": "cloud with snow",
+ "u": "7.0"
+ },
+ "cloud_tornado": {
+ "c": "nature",
+ "e": "🌪",
+ "d": "cloud with tornado",
+ "u": "7.0"
+ },
+ "clown": {
+ "c": "people",
+ "e": "🤡",
+ "d": "clown face",
+ "u": "9.0"
+ },
+ "clubs": {
+ "c": "symbols",
+ "e": "♣",
+ "d": "black club suit",
+ "u": "1.1"
+ },
+ "cocktail": {
+ "c": "food",
+ "e": "ðŸ¸",
+ "d": "cocktail glass",
+ "u": "6.0"
+ },
+ "coffee": {
+ "c": "food",
+ "e": "☕",
+ "d": "hot beverage",
+ "u": "4.0"
+ },
+ "coffin": {
+ "c": "objects",
+ "e": "âš°",
+ "d": "coffin",
+ "u": "4.1"
+ },
+ "cold_sweat": {
+ "c": "people",
+ "e": "😰",
+ "d": "face with open mouth and cold sweat",
+ "u": "6.0"
+ },
+ "comet": {
+ "c": "nature",
+ "e": "☄",
+ "d": "comet",
+ "u": "1.1"
+ },
+ "compression": {
+ "c": "objects",
+ "e": "🗜",
+ "d": "compression",
+ "u": "7.0"
+ },
+ "computer": {
+ "c": "objects",
+ "e": "💻",
+ "d": "personal computer",
+ "u": "6.0"
+ },
+ "confetti_ball": {
+ "c": "objects",
+ "e": "🎊",
+ "d": "confetti ball",
+ "u": "6.0"
+ },
+ "confounded": {
+ "c": "people",
+ "e": "😖",
+ "d": "confounded face",
+ "u": "6.0"
+ },
+ "confused": {
+ "c": "people",
+ "e": "😕",
+ "d": "confused face",
+ "u": "6.1"
+ },
+ "congratulations": {
+ "c": "symbols",
+ "e": "㊗",
+ "d": "circled ideograph congratulation",
+ "u": "1.1"
+ },
+ "construction": {
+ "c": "travel",
+ "e": "🚧",
+ "d": "construction sign",
+ "u": "6.0"
+ },
+ "construction_site": {
+ "c": "travel",
+ "e": "ðŸ—",
+ "d": "building construction",
+ "u": "7.0"
+ },
+ "construction_worker": {
+ "c": "people",
+ "e": "👷",
+ "d": "construction worker",
+ "u": "6.0"
+ },
+ "construction_worker_tone1": {
+ "c": "people",
+ "e": "👷ðŸ»",
+ "d": "construction worker tone 1",
+ "u": "8.0"
+ },
+ "construction_worker_tone2": {
+ "c": "people",
+ "e": "👷ðŸ¼",
+ "d": "construction worker tone 2",
+ "u": "8.0"
+ },
+ "construction_worker_tone3": {
+ "c": "people",
+ "e": "👷ðŸ½",
+ "d": "construction worker tone 3",
+ "u": "8.0"
+ },
+ "construction_worker_tone4": {
+ "c": "people",
+ "e": "👷ðŸ¾",
+ "d": "construction worker tone 4",
+ "u": "8.0"
+ },
+ "construction_worker_tone5": {
+ "c": "people",
+ "e": "👷ðŸ¿",
+ "d": "construction worker tone 5",
+ "u": "8.0"
+ },
+ "control_knobs": {
+ "c": "objects",
+ "e": "🎛",
+ "d": "control knobs",
+ "u": "7.0"
+ },
+ "convenience_store": {
+ "c": "travel",
+ "e": "ðŸª",
+ "d": "convenience store",
+ "u": "6.0"
+ },
+ "cookie": {
+ "c": "food",
+ "e": "ðŸª",
+ "d": "cookie",
+ "u": "6.0"
+ },
+ "cooking": {
+ "c": "food",
+ "e": "ðŸ³",
+ "d": "cooking",
+ "u": "6.0"
+ },
+ "cool": {
+ "c": "symbols",
+ "e": "🆒",
+ "d": "squared cool",
+ "u": "6.0"
+ },
+ "cop": {
+ "c": "people",
+ "e": "👮",
+ "d": "police officer",
+ "u": "6.0"
+ },
+ "cop_tone1": {
+ "c": "people",
+ "e": "👮ðŸ»",
+ "d": "police officer tone 1",
+ "u": "8.0"
+ },
+ "cop_tone2": {
+ "c": "people",
+ "e": "👮ðŸ¼",
+ "d": "police officer tone 2",
+ "u": "8.0"
+ },
+ "cop_tone3": {
+ "c": "people",
+ "e": "👮ðŸ½",
+ "d": "police officer tone 3",
+ "u": "8.0"
+ },
+ "cop_tone4": {
+ "c": "people",
+ "e": "👮ðŸ¾",
+ "d": "police officer tone 4",
+ "u": "8.0"
+ },
+ "cop_tone5": {
+ "c": "people",
+ "e": "👮ðŸ¿",
+ "d": "police officer tone 5",
+ "u": "8.0"
+ },
+ "copyright": {
+ "c": "symbols",
+ "e": "©",
+ "d": "copyright sign",
+ "u": "1.1"
+ },
+ "corn": {
+ "c": "food",
+ "e": "🌽",
+ "d": "ear of maize",
+ "u": "6.0"
+ },
+ "couch": {
+ "c": "objects",
+ "e": "🛋",
+ "d": "couch and lamp",
+ "u": "7.0"
+ },
+ "couple": {
+ "c": "people",
+ "e": "👫",
+ "d": "man and woman holding hands",
+ "u": "6.0"
+ },
+ "couple_mm": {
+ "c": "people",
+ "e": "👨â€â¤ï¸â€ðŸ‘¨",
+ "d": "couple (man,man)",
+ "u": "6.0"
+ },
+ "couple_with_heart": {
+ "c": "people",
+ "e": "💑",
+ "d": "couple with heart",
+ "u": "6.0"
+ },
+ "couple_ww": {
+ "c": "people",
+ "e": "👩â€â¤ï¸â€ðŸ‘©",
+ "d": "couple (woman,woman)",
+ "u": "6.0"
+ },
+ "couplekiss": {
+ "c": "people",
+ "e": "ðŸ’",
+ "d": "kiss",
+ "u": "6.0"
+ },
+ "cow": {
+ "c": "nature",
+ "e": "ðŸ®",
+ "d": "cow face",
+ "u": "6.0"
+ },
+ "cow2": {
+ "c": "nature",
+ "e": "ðŸ„",
+ "d": "cow",
+ "u": "6.0"
+ },
+ "cowboy": {
+ "c": "people",
+ "e": "🤠",
+ "d": "face with cowboy hat",
+ "u": "9.0"
+ },
+ "crab": {
+ "c": "nature",
+ "e": "🦀",
+ "d": "crab",
+ "u": "8.0"
+ },
+ "crayon": {
+ "c": "objects",
+ "e": "ðŸ–",
+ "d": "lower left crayon",
+ "u": "7.0"
+ },
+ "credit_card": {
+ "c": "objects",
+ "e": "💳",
+ "d": "credit card",
+ "u": "6.0"
+ },
+ "crescent_moon": {
+ "c": "nature",
+ "e": "🌙",
+ "d": "crescent moon",
+ "u": "6.0"
+ },
+ "cricket": {
+ "c": "activity",
+ "e": "ðŸ",
+ "d": "cricket bat and ball",
+ "u": "8.0"
+ },
+ "crocodile": {
+ "c": "nature",
+ "e": "ðŸŠ",
+ "d": "crocodile",
+ "u": "6.0"
+ },
+ "croissant": {
+ "c": "food",
+ "e": "ðŸ¥",
+ "d": "croissant",
+ "u": "9.0"
+ },
+ "cross": {
+ "c": "symbols",
+ "e": "âœ",
+ "d": "latin cross",
+ "u": "1.1"
+ },
+ "crossed_flags": {
+ "c": "objects",
+ "e": "🎌",
+ "d": "crossed flags",
+ "u": "6.0"
+ },
+ "crossed_swords": {
+ "c": "objects",
+ "e": "âš”",
+ "d": "crossed swords",
+ "u": "4.1"
+ },
+ "crown": {
+ "c": "people",
+ "e": "👑",
+ "d": "crown",
+ "u": "6.0"
+ },
+ "cruise_ship": {
+ "c": "travel",
+ "e": "🛳",
+ "d": "passenger ship",
+ "u": "7.0"
+ },
+ "cry": {
+ "c": "people",
+ "e": "😢",
+ "d": "crying face",
+ "u": "6.0"
+ },
+ "crying_cat_face": {
+ "c": "people",
+ "e": "😿",
+ "d": "crying cat face",
+ "u": "6.0"
+ },
+ "crystal_ball": {
+ "c": "objects",
+ "e": "🔮",
+ "d": "crystal ball",
+ "u": "6.0"
+ },
+ "cucumber": {
+ "c": "food",
+ "e": "🥒",
+ "d": "cucumber",
+ "u": "9.0"
+ },
+ "cupid": {
+ "c": "symbols",
+ "e": "💘",
+ "d": "heart with arrow",
+ "u": "6.0"
+ },
+ "curly_loop": {
+ "c": "symbols",
+ "e": "âž°",
+ "d": "curly loop",
+ "u": "6.0"
+ },
+ "currency_exchange": {
+ "c": "symbols",
+ "e": "💱",
+ "d": "currency exchange",
+ "u": "6.0"
+ },
+ "curry": {
+ "c": "food",
+ "e": "ðŸ›",
+ "d": "curry and rice",
+ "u": "6.0"
+ },
+ "custard": {
+ "c": "food",
+ "e": "ðŸ®",
+ "d": "custard",
+ "u": "6.0"
+ },
+ "customs": {
+ "c": "symbols",
+ "e": "🛃",
+ "d": "customs",
+ "u": "6.0"
+ },
+ "cyclone": {
+ "c": "symbols",
+ "e": "🌀",
+ "d": "cyclone",
+ "u": "6.0"
+ },
+ "dagger": {
+ "c": "objects",
+ "e": "🗡",
+ "d": "dagger knife",
+ "u": "7.0"
+ },
+ "dancer": {
+ "c": "people",
+ "e": "💃",
+ "d": "dancer",
+ "u": "6.0"
+ },
+ "dancer_tone1": {
+ "c": "people",
+ "e": "💃ðŸ»",
+ "d": "dancer tone 1",
+ "u": "8.0"
+ },
+ "dancer_tone2": {
+ "c": "people",
+ "e": "💃ðŸ¼",
+ "d": "dancer tone 2",
+ "u": "8.0"
+ },
+ "dancer_tone3": {
+ "c": "people",
+ "e": "💃ðŸ½",
+ "d": "dancer tone 3",
+ "u": "8.0"
+ },
+ "dancer_tone4": {
+ "c": "people",
+ "e": "💃ðŸ¾",
+ "d": "dancer tone 4",
+ "u": "8.0"
+ },
+ "dancer_tone5": {
+ "c": "people",
+ "e": "💃ðŸ¿",
+ "d": "dancer tone 5",
+ "u": "8.0"
+ },
+ "dancers": {
+ "c": "people",
+ "e": "👯",
+ "d": "woman with bunny ears",
+ "u": "6.0"
+ },
+ "dango": {
+ "c": "food",
+ "e": "ðŸ¡",
+ "d": "dango",
+ "u": "6.0"
+ },
+ "dark_sunglasses": {
+ "c": "people",
+ "e": "🕶",
+ "d": "dark sunglasses",
+ "u": "7.0"
+ },
+ "dart": {
+ "c": "activity",
+ "e": "🎯",
+ "d": "direct hit",
+ "u": "6.0"
+ },
+ "dash": {
+ "c": "nature",
+ "e": "💨",
+ "d": "dash symbol",
+ "u": "6.0"
+ },
+ "date": {
+ "c": "objects",
+ "e": "📅",
+ "d": "calendar",
+ "u": "6.0"
+ },
+ "deciduous_tree": {
+ "c": "nature",
+ "e": "🌳",
+ "d": "deciduous tree",
+ "u": "6.0"
+ },
+ "deer": {
+ "c": "nature",
+ "e": "🦌",
+ "d": "deer",
+ "u": "9.0"
+ },
+ "department_store": {
+ "c": "travel",
+ "e": "ðŸ¬",
+ "d": "department store",
+ "u": "6.0"
+ },
+ "desert": {
+ "c": "travel",
+ "e": "ðŸœ",
+ "d": "desert",
+ "u": "7.0"
+ },
+ "desktop": {
+ "c": "objects",
+ "e": "🖥",
+ "d": "desktop computer",
+ "u": "7.0"
+ },
+ "diamond_shape_with_a_dot_inside": {
+ "c": "symbols",
+ "e": "💠",
+ "d": "diamond shape with a dot inside",
+ "u": "6.0"
+ },
+ "diamonds": {
+ "c": "symbols",
+ "e": "♦",
+ "d": "black diamond suit",
+ "u": "1.1"
+ },
+ "disappointed": {
+ "c": "people",
+ "e": "😞",
+ "d": "disappointed face",
+ "u": "6.0"
+ },
+ "disappointed_relieved": {
+ "c": "people",
+ "e": "😥",
+ "d": "disappointed but relieved face",
+ "u": "6.0"
+ },
+ "dividers": {
+ "c": "objects",
+ "e": "🗂",
+ "d": "card index dividers",
+ "u": "7.0"
+ },
+ "dizzy": {
+ "c": "nature",
+ "e": "💫",
+ "d": "dizzy symbol",
+ "u": "6.0"
+ },
+ "dizzy_face": {
+ "c": "people",
+ "e": "😵",
+ "d": "dizzy face",
+ "u": "6.0"
+ },
+ "do_not_litter": {
+ "c": "symbols",
+ "e": "🚯",
+ "d": "do not litter symbol",
+ "u": "6.0"
+ },
+ "dog": {
+ "c": "nature",
+ "e": "ðŸ¶",
+ "d": "dog face",
+ "u": "6.0"
+ },
+ "dog2": {
+ "c": "nature",
+ "e": "ðŸ•",
+ "d": "dog",
+ "u": "6.0"
+ },
+ "dollar": {
+ "c": "objects",
+ "e": "💵",
+ "d": "banknote with dollar sign",
+ "u": "6.0"
+ },
+ "dolls": {
+ "c": "objects",
+ "e": "🎎",
+ "d": "japanese dolls",
+ "u": "6.0"
+ },
+ "dolphin": {
+ "c": "nature",
+ "e": "ðŸ¬",
+ "d": "dolphin",
+ "u": "6.0"
+ },
+ "door": {
+ "c": "objects",
+ "e": "🚪",
+ "d": "door",
+ "u": "6.0"
+ },
+ "doughnut": {
+ "c": "food",
+ "e": "ðŸ©",
+ "d": "doughnut",
+ "u": "6.0"
+ },
+ "dove": {
+ "c": "nature",
+ "e": "🕊",
+ "d": "dove of peace",
+ "u": "7.0"
+ },
+ "dragon": {
+ "c": "nature",
+ "e": "ðŸ‰",
+ "d": "dragon",
+ "u": "6.0"
+ },
+ "dragon_face": {
+ "c": "nature",
+ "e": "ðŸ²",
+ "d": "dragon face",
+ "u": "6.0"
+ },
+ "dress": {
+ "c": "people",
+ "e": "👗",
+ "d": "dress",
+ "u": "6.0"
+ },
+ "dromedary_camel": {
+ "c": "nature",
+ "e": "ðŸª",
+ "d": "dromedary camel",
+ "u": "6.0"
+ },
+ "drooling_face": {
+ "c": "people",
+ "e": "🤤",
+ "d": "drooling face",
+ "u": "9.0"
+ },
+ "droplet": {
+ "c": "nature",
+ "e": "💧",
+ "d": "droplet",
+ "u": "6.0"
+ },
+ "drum": {
+ "c": "activity",
+ "e": "ðŸ¥",
+ "d": "drum with drumsticks",
+ "u": "9.0"
+ },
+ "duck": {
+ "c": "nature",
+ "e": "🦆",
+ "d": "duck",
+ "u": "9.0"
+ },
+ "dvd": {
+ "c": "objects",
+ "e": "📀",
+ "d": "dvd",
+ "u": "6.0"
+ },
+ "e-mail": {
+ "c": "objects",
+ "e": "📧",
+ "d": "e-mail symbol",
+ "u": "6.0"
+ },
+ "eagle": {
+ "c": "nature",
+ "e": "🦅",
+ "d": "eagle",
+ "u": "9.0"
+ },
+ "ear": {
+ "c": "people",
+ "e": "👂",
+ "d": "ear",
+ "u": "6.0"
+ },
+ "ear_of_rice": {
+ "c": "nature",
+ "e": "🌾",
+ "d": "ear of rice",
+ "u": "6.0"
+ },
+ "ear_tone1": {
+ "c": "people",
+ "e": "👂ðŸ»",
+ "d": "ear tone 1",
+ "u": "8.0"
+ },
+ "ear_tone2": {
+ "c": "people",
+ "e": "👂ðŸ¼",
+ "d": "ear tone 2",
+ "u": "8.0"
+ },
+ "ear_tone3": {
+ "c": "people",
+ "e": "👂ðŸ½",
+ "d": "ear tone 3",
+ "u": "8.0"
+ },
+ "ear_tone4": {
+ "c": "people",
+ "e": "👂ðŸ¾",
+ "d": "ear tone 4",
+ "u": "8.0"
+ },
+ "ear_tone5": {
+ "c": "people",
+ "e": "👂ðŸ¿",
+ "d": "ear tone 5",
+ "u": "8.0"
+ },
+ "earth_africa": {
+ "c": "nature",
+ "e": "ðŸŒ",
+ "d": "earth globe europe-africa",
+ "u": "6.0"
+ },
+ "earth_americas": {
+ "c": "nature",
+ "e": "🌎",
+ "d": "earth globe americas",
+ "u": "6.0"
+ },
+ "earth_asia": {
+ "c": "nature",
+ "e": "ðŸŒ",
+ "d": "earth globe asia-australia",
+ "u": "6.0"
+ },
+ "egg": {
+ "c": "food",
+ "e": "🥚",
+ "d": "egg",
+ "u": "9.0"
+ },
+ "eggplant": {
+ "c": "food",
+ "e": "ðŸ†",
+ "d": "aubergine",
+ "u": "6.0"
+ },
+ "eight": {
+ "c": "symbols",
+ "e": "8ï¸âƒ£",
+ "d": "keycap digit eight",
+ "u": "3.0"
+ },
+ "eight_pointed_black_star": {
+ "c": "symbols",
+ "e": "✴",
+ "d": "eight pointed black star",
+ "u": "1.1"
+ },
+ "eight_spoked_asterisk": {
+ "c": "symbols",
+ "e": "✳",
+ "d": "eight spoked asterisk",
+ "u": "1.1"
+ },
+ "eject": {
+ "c": "symbols",
+ "e": "â",
+ "d": "eject symbol",
+ "u": "4.0"
+ },
+ "electric_plug": {
+ "c": "objects",
+ "e": "🔌",
+ "d": "electric plug",
+ "u": "6.0"
+ },
+ "elephant": {
+ "c": "nature",
+ "e": "ðŸ˜",
+ "d": "elephant",
+ "u": "6.0"
+ },
+ "end": {
+ "c": "symbols",
+ "e": "🔚",
+ "d": "end with leftwards arrow above",
+ "u": "6.0"
+ },
+ "envelope": {
+ "c": "objects",
+ "e": "✉",
+ "d": "envelope",
+ "u": "1.1"
+ },
+ "envelope_with_arrow": {
+ "c": "objects",
+ "e": "📩",
+ "d": "envelope with downwards arrow above",
+ "u": "6.0"
+ },
+ "euro": {
+ "c": "objects",
+ "e": "💶",
+ "d": "banknote with euro sign",
+ "u": "6.0"
+ },
+ "european_castle": {
+ "c": "travel",
+ "e": "ðŸ°",
+ "d": "european castle",
+ "u": "6.0"
+ },
+ "european_post_office": {
+ "c": "travel",
+ "e": "ðŸ¤",
+ "d": "european post office",
+ "u": "6.0"
+ },
+ "evergreen_tree": {
+ "c": "nature",
+ "e": "🌲",
+ "d": "evergreen tree",
+ "u": "6.0"
+ },
+ "exclamation": {
+ "c": "symbols",
+ "e": "â—",
+ "d": "heavy exclamation mark symbol",
+ "u": "5.2"
+ },
+ "expressionless": {
+ "c": "people",
+ "e": "😑",
+ "d": "expressionless face",
+ "u": "6.1"
+ },
+ "eye": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "eye",
+ "u": "7.0"
+ },
+ "eye_in_speech_bubble": {
+ "c": "symbols",
+ "e": "ðŸ‘â€ðŸ—¨",
+ "d": "eye in speech bubble",
+ "u": "7.0"
+ },
+ "eyeglasses": {
+ "c": "people",
+ "e": "👓",
+ "d": "eyeglasses",
+ "u": "6.0"
+ },
+ "eyes": {
+ "c": "people",
+ "e": "👀",
+ "d": "eyes",
+ "u": "6.0"
+ },
+ "face_palm": {
+ "c": "people",
+ "e": "🤦",
+ "d": "face palm",
+ "u": "9.0"
+ },
+ "face_palm_tone1": {
+ "c": "people",
+ "e": "🤦ðŸ»",
+ "d": "face palm tone 1",
+ "u": "9.0"
+ },
+ "face_palm_tone2": {
+ "c": "people",
+ "e": "🤦ðŸ¼",
+ "d": "face palm tone 2",
+ "u": "9.0"
+ },
+ "face_palm_tone3": {
+ "c": "people",
+ "e": "🤦ðŸ½",
+ "d": "face palm tone 3",
+ "u": "9.0"
+ },
+ "face_palm_tone4": {
+ "c": "people",
+ "e": "🤦ðŸ¾",
+ "d": "face palm tone 4",
+ "u": "9.0"
+ },
+ "face_palm_tone5": {
+ "c": "people",
+ "e": "🤦ðŸ¿",
+ "d": "face palm tone 5",
+ "u": "9.0"
+ },
+ "factory": {
+ "c": "travel",
+ "e": "ðŸ­",
+ "d": "factory",
+ "u": "6.0"
+ },
+ "fallen_leaf": {
+ "c": "nature",
+ "e": "ðŸ‚",
+ "d": "fallen leaf",
+ "u": "6.0"
+ },
+ "family": {
+ "c": "people",
+ "e": "👪",
+ "d": "family",
+ "u": "6.0"
+ },
+ "family_mmb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘¦",
+ "d": "family (man,man,boy)",
+ "u": "6.0"
+ },
+ "family_mmbb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘¦â€ðŸ‘¦",
+ "d": "family (man,man,boy,boy)",
+ "u": "6.0"
+ },
+ "family_mmg": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘§",
+ "d": "family (man,man,girl)",
+ "u": "6.0"
+ },
+ "family_mmgb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘§â€ðŸ‘¦",
+ "d": "family (man,man,girl,boy)",
+ "u": "6.0"
+ },
+ "family_mmgg": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘§â€ðŸ‘§",
+ "d": "family (man,man,girl,girl)",
+ "u": "6.0"
+ },
+ "family_mwbb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘©â€ðŸ‘¦â€ðŸ‘¦",
+ "d": "family (man,woman,boy,boy)",
+ "u": "6.0"
+ },
+ "family_mwg": {
+ "c": "people",
+ "e": "👨â€ðŸ‘©â€ðŸ‘§",
+ "d": "family (man,woman,girl)",
+ "u": "6.0"
+ },
+ "family_mwgb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦",
+ "d": "family (man,woman,girl,boy)",
+ "u": "6.0"
+ },
+ "family_mwgg": {
+ "c": "people",
+ "e": "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§",
+ "d": "family (man,woman,girl,girl)",
+ "u": "6.0"
+ },
+ "family_wwb": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘¦",
+ "d": "family (woman,woman,boy)",
+ "u": "6.0"
+ },
+ "family_wwbb": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘¦â€ðŸ‘¦",
+ "d": "family (woman,woman,boy,boy)",
+ "u": "6.0"
+ },
+ "family_wwg": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘§",
+ "d": "family (woman,woman,girl)",
+ "u": "6.0"
+ },
+ "family_wwgb": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦",
+ "d": "family (woman,woman,girl,boy)",
+ "u": "6.0"
+ },
+ "family_wwgg": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§",
+ "d": "family (woman,woman,girl,girl)",
+ "u": "6.0"
+ },
+ "fast_forward": {
+ "c": "symbols",
+ "e": "â©",
+ "d": "black right-pointing double triangle",
+ "u": "6.0"
+ },
+ "fax": {
+ "c": "objects",
+ "e": "📠",
+ "d": "fax machine",
+ "u": "6.0"
+ },
+ "fearful": {
+ "c": "people",
+ "e": "😨",
+ "d": "fearful face",
+ "u": "6.0"
+ },
+ "feet": {
+ "c": "nature",
+ "e": "ðŸ¾",
+ "d": "paw prints",
+ "u": "6.0"
+ },
+ "fencer": {
+ "c": "activity",
+ "e": "🤺",
+ "d": "fencer",
+ "u": "9.0"
+ },
+ "ferris_wheel": {
+ "c": "travel",
+ "e": "🎡",
+ "d": "ferris wheel",
+ "u": "6.0"
+ },
+ "ferry": {
+ "c": "travel",
+ "e": "â›´",
+ "d": "ferry",
+ "u": "5.2"
+ },
+ "field_hockey": {
+ "c": "activity",
+ "e": "ðŸ‘",
+ "d": "field hockey stick and ball",
+ "u": "8.0"
+ },
+ "file_cabinet": {
+ "c": "objects",
+ "e": "🗄",
+ "d": "file cabinet",
+ "u": "7.0"
+ },
+ "file_folder": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "file folder",
+ "u": "6.0"
+ },
+ "film_frames": {
+ "c": "objects",
+ "e": "🎞",
+ "d": "film frames",
+ "u": "7.0"
+ },
+ "fingers_crossed": {
+ "c": "people",
+ "e": "🤞",
+ "d": "hand with first and index finger crossed",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone1": {
+ "c": "people",
+ "e": "🤞ðŸ»",
+ "d": "hand with index and middle fingers crossed tone 1",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone2": {
+ "c": "people",
+ "e": "🤞ðŸ¼",
+ "d": "hand with index and middle fingers crossed tone 2",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone3": {
+ "c": "people",
+ "e": "🤞ðŸ½",
+ "d": "hand with index and middle fingers crossed tone 3",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone4": {
+ "c": "people",
+ "e": "🤞ðŸ¾",
+ "d": "hand with index and middle fingers crossed tone 4",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone5": {
+ "c": "people",
+ "e": "🤞ðŸ¿",
+ "d": "hand with index and middle fingers crossed tone 5",
+ "u": "9.0"
+ },
+ "fire": {
+ "c": "nature",
+ "e": "🔥",
+ "d": "fire",
+ "u": "6.0"
+ },
+ "fire_engine": {
+ "c": "travel",
+ "e": "🚒",
+ "d": "fire engine",
+ "u": "6.0"
+ },
+ "fireworks": {
+ "c": "travel",
+ "e": "🎆",
+ "d": "fireworks",
+ "u": "6.0"
+ },
+ "first_place": {
+ "c": "activity",
+ "e": "🥇",
+ "d": "first place medal",
+ "u": "9.0"
+ },
+ "first_quarter_moon": {
+ "c": "nature",
+ "e": "🌓",
+ "d": "first quarter moon symbol",
+ "u": "6.0"
+ },
+ "first_quarter_moon_with_face": {
+ "c": "nature",
+ "e": "🌛",
+ "d": "first quarter moon with face",
+ "u": "6.0"
+ },
+ "fish": {
+ "c": "nature",
+ "e": "ðŸŸ",
+ "d": "fish",
+ "u": "6.0"
+ },
+ "fish_cake": {
+ "c": "food",
+ "e": "ðŸ¥",
+ "d": "fish cake with swirl design",
+ "u": "6.0"
+ },
+ "fishing_pole_and_fish": {
+ "c": "activity",
+ "e": "🎣",
+ "d": "fishing pole and fish",
+ "u": "6.0"
+ },
+ "fist": {
+ "c": "people",
+ "e": "✊",
+ "d": "raised fist",
+ "u": "6.0"
+ },
+ "fist_tone1": {
+ "c": "people",
+ "e": "✊ðŸ»",
+ "d": "raised fist tone 1",
+ "u": "8.0"
+ },
+ "fist_tone2": {
+ "c": "people",
+ "e": "✊ðŸ¼",
+ "d": "raised fist tone 2",
+ "u": "8.0"
+ },
+ "fist_tone3": {
+ "c": "people",
+ "e": "✊ðŸ½",
+ "d": "raised fist tone 3",
+ "u": "8.0"
+ },
+ "fist_tone4": {
+ "c": "people",
+ "e": "✊ðŸ¾",
+ "d": "raised fist tone 4",
+ "u": "8.0"
+ },
+ "fist_tone5": {
+ "c": "people",
+ "e": "✊ðŸ¿",
+ "d": "raised fist tone 5",
+ "u": "8.0"
+ },
+ "five": {
+ "c": "symbols",
+ "e": "5ï¸âƒ£",
+ "d": "keycap digit five",
+ "u": "3.0"
+ },
+ "flag_ac": {
+ "c": "flags",
+ "e": "🇦🇨",
+ "d": "ascension",
+ "u": "6.0"
+ },
+ "flag_ad": {
+ "c": "flags",
+ "e": "🇦🇩",
+ "d": "andorra",
+ "u": "6.0"
+ },
+ "flag_ae": {
+ "c": "flags",
+ "e": "🇦🇪",
+ "d": "the united arab emirates",
+ "u": "6.0"
+ },
+ "flag_af": {
+ "c": "flags",
+ "e": "🇦🇫",
+ "d": "afghanistan",
+ "u": "6.0"
+ },
+ "flag_ag": {
+ "c": "flags",
+ "e": "🇦🇬",
+ "d": "antigua and barbuda",
+ "u": "6.0"
+ },
+ "flag_ai": {
+ "c": "flags",
+ "e": "🇦🇮",
+ "d": "anguilla",
+ "u": "6.0"
+ },
+ "flag_al": {
+ "c": "flags",
+ "e": "🇦🇱",
+ "d": "albania",
+ "u": "6.0"
+ },
+ "flag_am": {
+ "c": "flags",
+ "e": "🇦🇲",
+ "d": "armenia",
+ "u": "6.0"
+ },
+ "flag_ao": {
+ "c": "flags",
+ "e": "🇦🇴",
+ "d": "angola",
+ "u": "6.0"
+ },
+ "flag_aq": {
+ "c": "flags",
+ "e": "🇦🇶",
+ "d": "antarctica",
+ "u": "6.0"
+ },
+ "flag_ar": {
+ "c": "flags",
+ "e": "🇦🇷",
+ "d": "argentina",
+ "u": "6.0"
+ },
+ "flag_as": {
+ "c": "flags",
+ "e": "🇦🇸",
+ "d": "american samoa",
+ "u": "6.0"
+ },
+ "flag_at": {
+ "c": "flags",
+ "e": "🇦🇹",
+ "d": "austria",
+ "u": "6.0"
+ },
+ "flag_au": {
+ "c": "flags",
+ "e": "🇦🇺",
+ "d": "australia",
+ "u": "6.0"
+ },
+ "flag_aw": {
+ "c": "flags",
+ "e": "🇦🇼",
+ "d": "aruba",
+ "u": "6.0"
+ },
+ "flag_ax": {
+ "c": "flags",
+ "e": "🇦🇽",
+ "d": "Ã¥land islands",
+ "u": "6.0"
+ },
+ "flag_az": {
+ "c": "flags",
+ "e": "🇦🇿",
+ "d": "azerbaijan",
+ "u": "6.0"
+ },
+ "flag_ba": {
+ "c": "flags",
+ "e": "🇧🇦",
+ "d": "bosnia and herzegovina",
+ "u": "6.0"
+ },
+ "flag_bb": {
+ "c": "flags",
+ "e": "🇧🇧",
+ "d": "barbados",
+ "u": "6.0"
+ },
+ "flag_bd": {
+ "c": "flags",
+ "e": "🇧🇩",
+ "d": "bangladesh",
+ "u": "6.0"
+ },
+ "flag_be": {
+ "c": "flags",
+ "e": "🇧🇪",
+ "d": "belgium",
+ "u": "6.0"
+ },
+ "flag_bf": {
+ "c": "flags",
+ "e": "🇧🇫",
+ "d": "burkina faso",
+ "u": "6.0"
+ },
+ "flag_bg": {
+ "c": "flags",
+ "e": "🇧🇬",
+ "d": "bulgaria",
+ "u": "6.0"
+ },
+ "flag_bh": {
+ "c": "flags",
+ "e": "🇧🇭",
+ "d": "bahrain",
+ "u": "6.0"
+ },
+ "flag_bi": {
+ "c": "flags",
+ "e": "🇧🇮",
+ "d": "burundi",
+ "u": "6.0"
+ },
+ "flag_bj": {
+ "c": "flags",
+ "e": "🇧🇯",
+ "d": "benin",
+ "u": "6.0"
+ },
+ "flag_bl": {
+ "c": "flags",
+ "e": "🇧🇱",
+ "d": "saint barthélemy",
+ "u": "6.0"
+ },
+ "flag_black": {
+ "c": "objects",
+ "e": "ðŸ´",
+ "d": "waving black flag",
+ "u": "6.0"
+ },
+ "flag_bm": {
+ "c": "flags",
+ "e": "🇧🇲",
+ "d": "bermuda",
+ "u": "6.0"
+ },
+ "flag_bn": {
+ "c": "flags",
+ "e": "🇧🇳",
+ "d": "brunei",
+ "u": "6.0"
+ },
+ "flag_bo": {
+ "c": "flags",
+ "e": "🇧🇴",
+ "d": "bolivia",
+ "u": "6.0"
+ },
+ "flag_bq": {
+ "c": "flags",
+ "e": "🇧🇶",
+ "d": "caribbean netherlands",
+ "u": "6.0"
+ },
+ "flag_br": {
+ "c": "flags",
+ "e": "🇧🇷",
+ "d": "brazil",
+ "u": "6.0"
+ },
+ "flag_bs": {
+ "c": "flags",
+ "e": "🇧🇸",
+ "d": "the bahamas",
+ "u": "6.0"
+ },
+ "flag_bt": {
+ "c": "flags",
+ "e": "🇧🇹",
+ "d": "bhutan",
+ "u": "6.0"
+ },
+ "flag_bv": {
+ "c": "flags",
+ "e": "🇧🇻",
+ "d": "bouvet island",
+ "u": "6.0"
+ },
+ "flag_bw": {
+ "c": "flags",
+ "e": "🇧🇼",
+ "d": "botswana",
+ "u": "6.0"
+ },
+ "flag_by": {
+ "c": "flags",
+ "e": "🇧🇾",
+ "d": "belarus",
+ "u": "6.0"
+ },
+ "flag_bz": {
+ "c": "flags",
+ "e": "🇧🇿",
+ "d": "belize",
+ "u": "6.0"
+ },
+ "flag_ca": {
+ "c": "flags",
+ "e": "🇨🇦",
+ "d": "canada",
+ "u": "6.0"
+ },
+ "flag_cc": {
+ "c": "flags",
+ "e": "🇨🇨",
+ "d": "cocos (keeling) islands",
+ "u": "6.0"
+ },
+ "flag_cd": {
+ "c": "flags",
+ "e": "🇨🇩",
+ "d": "the democratic republic of the congo",
+ "u": "6.0"
+ },
+ "flag_cf": {
+ "c": "flags",
+ "e": "🇨🇫",
+ "d": "central african republic",
+ "u": "6.0"
+ },
+ "flag_cg": {
+ "c": "flags",
+ "e": "🇨🇬",
+ "d": "the republic of the congo",
+ "u": "6.0"
+ },
+ "flag_ch": {
+ "c": "flags",
+ "e": "🇨🇭",
+ "d": "switzerland",
+ "u": "6.0"
+ },
+ "flag_ci": {
+ "c": "flags",
+ "e": "🇨🇮",
+ "d": "cote d'ivoire",
+ "u": "6.0"
+ },
+ "flag_ck": {
+ "c": "flags",
+ "e": "🇨🇰",
+ "d": "cook islands",
+ "u": "6.0"
+ },
+ "flag_cl": {
+ "c": "flags",
+ "e": "🇨🇱",
+ "d": "chile",
+ "u": "6.0"
+ },
+ "flag_cm": {
+ "c": "flags",
+ "e": "🇨🇲",
+ "d": "cameroon",
+ "u": "6.0"
+ },
+ "flag_cn": {
+ "c": "flags",
+ "e": "🇨🇳",
+ "d": "china",
+ "u": "6.0"
+ },
+ "flag_co": {
+ "c": "flags",
+ "e": "🇨🇴",
+ "d": "colombia",
+ "u": "6.0"
+ },
+ "flag_cp": {
+ "c": "flags",
+ "e": "🇨🇵",
+ "d": "clipperton island",
+ "u": "6.0"
+ },
+ "flag_cr": {
+ "c": "flags",
+ "e": "🇨🇷",
+ "d": "costa rica",
+ "u": "6.0"
+ },
+ "flag_cu": {
+ "c": "flags",
+ "e": "🇨🇺",
+ "d": "cuba",
+ "u": "6.0"
+ },
+ "flag_cv": {
+ "c": "flags",
+ "e": "🇨🇻",
+ "d": "cape verde",
+ "u": "6.0"
+ },
+ "flag_cw": {
+ "c": "flags",
+ "e": "🇨🇼",
+ "d": "curaçao",
+ "u": "6.0"
+ },
+ "flag_cx": {
+ "c": "flags",
+ "e": "🇨🇽",
+ "d": "christmas island",
+ "u": "6.0"
+ },
+ "flag_cy": {
+ "c": "flags",
+ "e": "🇨🇾",
+ "d": "cyprus",
+ "u": "6.0"
+ },
+ "flag_cz": {
+ "c": "flags",
+ "e": "🇨🇿",
+ "d": "the czech republic",
+ "u": "6.0"
+ },
+ "flag_de": {
+ "c": "flags",
+ "e": "🇩🇪",
+ "d": "germany",
+ "u": "6.0"
+ },
+ "flag_dg": {
+ "c": "flags",
+ "e": "🇩🇬",
+ "d": "diego garcia",
+ "u": "6.0"
+ },
+ "flag_dj": {
+ "c": "flags",
+ "e": "🇩🇯",
+ "d": "djibouti",
+ "u": "6.0"
+ },
+ "flag_dk": {
+ "c": "flags",
+ "e": "🇩🇰",
+ "d": "denmark",
+ "u": "6.0"
+ },
+ "flag_dm": {
+ "c": "flags",
+ "e": "🇩🇲",
+ "d": "dominica",
+ "u": "6.0"
+ },
+ "flag_do": {
+ "c": "flags",
+ "e": "🇩🇴",
+ "d": "the dominican republic",
+ "u": "6.0"
+ },
+ "flag_dz": {
+ "c": "flags",
+ "e": "🇩🇿",
+ "d": "algeria",
+ "u": "6.0"
+ },
+ "flag_ea": {
+ "c": "flags",
+ "e": "🇪🇦",
+ "d": "ceuta, melilla",
+ "u": "6.0"
+ },
+ "flag_ec": {
+ "c": "flags",
+ "e": "🇪🇨",
+ "d": "ecuador",
+ "u": "6.0"
+ },
+ "flag_ee": {
+ "c": "flags",
+ "e": "🇪🇪",
+ "d": "estonia",
+ "u": "6.0"
+ },
+ "flag_eg": {
+ "c": "flags",
+ "e": "🇪🇬",
+ "d": "egypt",
+ "u": "6.0"
+ },
+ "flag_eh": {
+ "c": "flags",
+ "e": "🇪🇭",
+ "d": "western sahara",
+ "u": "6.0"
+ },
+ "flag_er": {
+ "c": "flags",
+ "e": "🇪🇷",
+ "d": "eritrea",
+ "u": "6.0"
+ },
+ "flag_es": {
+ "c": "flags",
+ "e": "🇪🇸",
+ "d": "spain",
+ "u": "6.0"
+ },
+ "flag_et": {
+ "c": "flags",
+ "e": "🇪🇹",
+ "d": "ethiopia",
+ "u": "6.0"
+ },
+ "flag_eu": {
+ "c": "flags",
+ "e": "🇪🇺",
+ "d": "european union",
+ "u": "6.0"
+ },
+ "flag_fi": {
+ "c": "flags",
+ "e": "🇫🇮",
+ "d": "finland",
+ "u": "6.0"
+ },
+ "flag_fj": {
+ "c": "flags",
+ "e": "🇫🇯",
+ "d": "fiji",
+ "u": "6.0"
+ },
+ "flag_fk": {
+ "c": "flags",
+ "e": "🇫🇰",
+ "d": "falkland islands",
+ "u": "6.0"
+ },
+ "flag_fm": {
+ "c": "flags",
+ "e": "🇫🇲",
+ "d": "micronesia",
+ "u": "6.0"
+ },
+ "flag_fo": {
+ "c": "flags",
+ "e": "🇫🇴",
+ "d": "faroe islands",
+ "u": "6.0"
+ },
+ "flag_fr": {
+ "c": "flags",
+ "e": "🇫🇷",
+ "d": "france",
+ "u": "6.0"
+ },
+ "flag_ga": {
+ "c": "flags",
+ "e": "🇬🇦",
+ "d": "gabon",
+ "u": "6.0"
+ },
+ "flag_gb": {
+ "c": "flags",
+ "e": "🇬🇧",
+ "d": "great britain",
+ "u": "6.0"
+ },
+ "flag_gd": {
+ "c": "flags",
+ "e": "🇬🇩",
+ "d": "grenada",
+ "u": "6.0"
+ },
+ "flag_ge": {
+ "c": "flags",
+ "e": "🇬🇪",
+ "d": "georgia",
+ "u": "6.0"
+ },
+ "flag_gf": {
+ "c": "flags",
+ "e": "🇬🇫",
+ "d": "french guiana",
+ "u": "6.0"
+ },
+ "flag_gg": {
+ "c": "flags",
+ "e": "🇬🇬",
+ "d": "guernsey",
+ "u": "6.0"
+ },
+ "flag_gh": {
+ "c": "flags",
+ "e": "🇬🇭",
+ "d": "ghana",
+ "u": "6.0"
+ },
+ "flag_gi": {
+ "c": "flags",
+ "e": "🇬🇮",
+ "d": "gibraltar",
+ "u": "6.0"
+ },
+ "flag_gl": {
+ "c": "flags",
+ "e": "🇬🇱",
+ "d": "greenland",
+ "u": "6.0"
+ },
+ "flag_gm": {
+ "c": "flags",
+ "e": "🇬🇲",
+ "d": "the gambia",
+ "u": "6.0"
+ },
+ "flag_gn": {
+ "c": "flags",
+ "e": "🇬🇳",
+ "d": "guinea",
+ "u": "6.0"
+ },
+ "flag_gp": {
+ "c": "flags",
+ "e": "🇬🇵",
+ "d": "guadeloupe",
+ "u": "6.0"
+ },
+ "flag_gq": {
+ "c": "flags",
+ "e": "🇬🇶",
+ "d": "equatorial guinea",
+ "u": "6.0"
+ },
+ "flag_gr": {
+ "c": "flags",
+ "e": "🇬🇷",
+ "d": "greece",
+ "u": "6.0"
+ },
+ "flag_gs": {
+ "c": "flags",
+ "e": "🇬🇸",
+ "d": "south georgia",
+ "u": "6.0"
+ },
+ "flag_gt": {
+ "c": "flags",
+ "e": "🇬🇹",
+ "d": "guatemala",
+ "u": "6.0"
+ },
+ "flag_gu": {
+ "c": "flags",
+ "e": "🇬🇺",
+ "d": "guam",
+ "u": "6.0"
+ },
+ "flag_gw": {
+ "c": "flags",
+ "e": "🇬🇼",
+ "d": "guinea-bissau",
+ "u": "6.0"
+ },
+ "flag_gy": {
+ "c": "flags",
+ "e": "🇬🇾",
+ "d": "guyana",
+ "u": "6.0"
+ },
+ "flag_hk": {
+ "c": "flags",
+ "e": "🇭🇰",
+ "d": "hong kong",
+ "u": "6.0"
+ },
+ "flag_hm": {
+ "c": "flags",
+ "e": "🇭🇲",
+ "d": "heard island and mcdonald islands",
+ "u": "6.0"
+ },
+ "flag_hn": {
+ "c": "flags",
+ "e": "🇭🇳",
+ "d": "honduras",
+ "u": "6.0"
+ },
+ "flag_hr": {
+ "c": "flags",
+ "e": "🇭🇷",
+ "d": "croatia",
+ "u": "6.0"
+ },
+ "flag_ht": {
+ "c": "flags",
+ "e": "🇭🇹",
+ "d": "haiti",
+ "u": "6.0"
+ },
+ "flag_hu": {
+ "c": "flags",
+ "e": "🇭🇺",
+ "d": "hungary",
+ "u": "6.0"
+ },
+ "flag_ic": {
+ "c": "flags",
+ "e": "🇮🇨",
+ "d": "canary islands",
+ "u": "6.0"
+ },
+ "flag_id": {
+ "c": "flags",
+ "e": "🇮🇩",
+ "d": "indonesia",
+ "u": "6.0"
+ },
+ "flag_ie": {
+ "c": "flags",
+ "e": "🇮🇪",
+ "d": "ireland",
+ "u": "6.0"
+ },
+ "flag_il": {
+ "c": "flags",
+ "e": "🇮🇱",
+ "d": "israel",
+ "u": "6.0"
+ },
+ "flag_im": {
+ "c": "flags",
+ "e": "🇮🇲",
+ "d": "isle of man",
+ "u": "6.0"
+ },
+ "flag_in": {
+ "c": "flags",
+ "e": "🇮🇳",
+ "d": "india",
+ "u": "6.0"
+ },
+ "flag_io": {
+ "c": "flags",
+ "e": "🇮🇴",
+ "d": "british indian ocean territory",
+ "u": "6.0"
+ },
+ "flag_iq": {
+ "c": "flags",
+ "e": "🇮🇶",
+ "d": "iraq",
+ "u": "6.0"
+ },
+ "flag_ir": {
+ "c": "flags",
+ "e": "🇮🇷",
+ "d": "iran",
+ "u": "6.0"
+ },
+ "flag_is": {
+ "c": "flags",
+ "e": "🇮🇸",
+ "d": "iceland",
+ "u": "6.0"
+ },
+ "flag_it": {
+ "c": "flags",
+ "e": "🇮🇹",
+ "d": "italy",
+ "u": "6.0"
+ },
+ "flag_je": {
+ "c": "flags",
+ "e": "🇯🇪",
+ "d": "jersey",
+ "u": "6.0"
+ },
+ "flag_jm": {
+ "c": "flags",
+ "e": "🇯🇲",
+ "d": "jamaica",
+ "u": "6.0"
+ },
+ "flag_jo": {
+ "c": "flags",
+ "e": "🇯🇴",
+ "d": "jordan",
+ "u": "6.0"
+ },
+ "flag_jp": {
+ "c": "flags",
+ "e": "🇯🇵",
+ "d": "japan",
+ "u": "6.0"
+ },
+ "flag_ke": {
+ "c": "flags",
+ "e": "🇰🇪",
+ "d": "kenya",
+ "u": "6.0"
+ },
+ "flag_kg": {
+ "c": "flags",
+ "e": "🇰🇬",
+ "d": "kyrgyzstan",
+ "u": "6.0"
+ },
+ "flag_kh": {
+ "c": "flags",
+ "e": "🇰🇭",
+ "d": "cambodia",
+ "u": "6.0"
+ },
+ "flag_ki": {
+ "c": "flags",
+ "e": "🇰🇮",
+ "d": "kiribati",
+ "u": "6.0"
+ },
+ "flag_km": {
+ "c": "flags",
+ "e": "🇰🇲",
+ "d": "the comoros",
+ "u": "6.0"
+ },
+ "flag_kn": {
+ "c": "flags",
+ "e": "🇰🇳",
+ "d": "saint kitts and nevis",
+ "u": "6.0"
+ },
+ "flag_kp": {
+ "c": "flags",
+ "e": "🇰🇵",
+ "d": "north korea",
+ "u": "6.0"
+ },
+ "flag_kr": {
+ "c": "flags",
+ "e": "🇰🇷",
+ "d": "korea",
+ "u": "6.0"
+ },
+ "flag_kw": {
+ "c": "flags",
+ "e": "🇰🇼",
+ "d": "kuwait",
+ "u": "6.0"
+ },
+ "flag_ky": {
+ "c": "flags",
+ "e": "🇰🇾",
+ "d": "cayman islands",
+ "u": "6.0"
+ },
+ "flag_kz": {
+ "c": "flags",
+ "e": "🇰🇿",
+ "d": "kazakhstan",
+ "u": "6.0"
+ },
+ "flag_la": {
+ "c": "flags",
+ "e": "🇱🇦",
+ "d": "laos",
+ "u": "6.0"
+ },
+ "flag_lb": {
+ "c": "flags",
+ "e": "🇱🇧",
+ "d": "lebanon",
+ "u": "6.0"
+ },
+ "flag_lc": {
+ "c": "flags",
+ "e": "🇱🇨",
+ "d": "saint lucia",
+ "u": "6.0"
+ },
+ "flag_li": {
+ "c": "flags",
+ "e": "🇱🇮",
+ "d": "liechtenstein",
+ "u": "6.0"
+ },
+ "flag_lk": {
+ "c": "flags",
+ "e": "🇱🇰",
+ "d": "sri lanka",
+ "u": "6.0"
+ },
+ "flag_lr": {
+ "c": "flags",
+ "e": "🇱🇷",
+ "d": "liberia",
+ "u": "6.0"
+ },
+ "flag_ls": {
+ "c": "flags",
+ "e": "🇱🇸",
+ "d": "lesotho",
+ "u": "6.0"
+ },
+ "flag_lt": {
+ "c": "flags",
+ "e": "🇱🇹",
+ "d": "lithuania",
+ "u": "6.0"
+ },
+ "flag_lu": {
+ "c": "flags",
+ "e": "🇱🇺",
+ "d": "luxembourg",
+ "u": "6.0"
+ },
+ "flag_lv": {
+ "c": "flags",
+ "e": "🇱🇻",
+ "d": "latvia",
+ "u": "6.0"
+ },
+ "flag_ly": {
+ "c": "flags",
+ "e": "🇱🇾",
+ "d": "libya",
+ "u": "6.0"
+ },
+ "flag_ma": {
+ "c": "flags",
+ "e": "🇲🇦",
+ "d": "morocco",
+ "u": "6.0"
+ },
+ "flag_mc": {
+ "c": "flags",
+ "e": "🇲🇨",
+ "d": "monaco",
+ "u": "6.0"
+ },
+ "flag_md": {
+ "c": "flags",
+ "e": "🇲🇩",
+ "d": "moldova",
+ "u": "6.0"
+ },
+ "flag_me": {
+ "c": "flags",
+ "e": "🇲🇪",
+ "d": "montenegro",
+ "u": "6.0"
+ },
+ "flag_mf": {
+ "c": "flags",
+ "e": "🇲🇫",
+ "d": "saint martin",
+ "u": "6.0"
+ },
+ "flag_mg": {
+ "c": "flags",
+ "e": "🇲🇬",
+ "d": "madagascar",
+ "u": "6.0"
+ },
+ "flag_mh": {
+ "c": "flags",
+ "e": "🇲🇭",
+ "d": "the marshall islands",
+ "u": "6.0"
+ },
+ "flag_mk": {
+ "c": "flags",
+ "e": "🇲🇰",
+ "d": "macedonia",
+ "u": "6.0"
+ },
+ "flag_ml": {
+ "c": "flags",
+ "e": "🇲🇱",
+ "d": "mali",
+ "u": "6.0"
+ },
+ "flag_mm": {
+ "c": "flags",
+ "e": "🇲🇲",
+ "d": "myanmar",
+ "u": "6.0"
+ },
+ "flag_mn": {
+ "c": "flags",
+ "e": "🇲🇳",
+ "d": "mongolia",
+ "u": "6.0"
+ },
+ "flag_mo": {
+ "c": "flags",
+ "e": "🇲🇴",
+ "d": "macau",
+ "u": "6.0"
+ },
+ "flag_mp": {
+ "c": "flags",
+ "e": "🇲🇵",
+ "d": "northern mariana islands",
+ "u": "6.0"
+ },
+ "flag_mq": {
+ "c": "flags",
+ "e": "🇲🇶",
+ "d": "martinique",
+ "u": "6.0"
+ },
+ "flag_mr": {
+ "c": "flags",
+ "e": "🇲🇷",
+ "d": "mauritania",
+ "u": "6.0"
+ },
+ "flag_ms": {
+ "c": "flags",
+ "e": "🇲🇸",
+ "d": "montserrat",
+ "u": "6.0"
+ },
+ "flag_mt": {
+ "c": "flags",
+ "e": "🇲🇹",
+ "d": "malta",
+ "u": "6.0"
+ },
+ "flag_mu": {
+ "c": "flags",
+ "e": "🇲🇺",
+ "d": "mauritius",
+ "u": "6.0"
+ },
+ "flag_mv": {
+ "c": "flags",
+ "e": "🇲🇻",
+ "d": "maldives",
+ "u": "6.0"
+ },
+ "flag_mw": {
+ "c": "flags",
+ "e": "🇲🇼",
+ "d": "malawi",
+ "u": "6.0"
+ },
+ "flag_mx": {
+ "c": "flags",
+ "e": "🇲🇽",
+ "d": "mexico",
+ "u": "6.0"
+ },
+ "flag_my": {
+ "c": "flags",
+ "e": "🇲🇾",
+ "d": "malaysia",
+ "u": "6.0"
+ },
+ "flag_mz": {
+ "c": "flags",
+ "e": "🇲🇿",
+ "d": "mozambique",
+ "u": "6.0"
+ },
+ "flag_na": {
+ "c": "flags",
+ "e": "🇳🇦",
+ "d": "namibia",
+ "u": "6.0"
+ },
+ "flag_nc": {
+ "c": "flags",
+ "e": "🇳🇨",
+ "d": "new caledonia",
+ "u": "6.0"
+ },
+ "flag_ne": {
+ "c": "flags",
+ "e": "🇳🇪",
+ "d": "niger",
+ "u": "6.0"
+ },
+ "flag_nf": {
+ "c": "flags",
+ "e": "🇳🇫",
+ "d": "norfolk island",
+ "u": "6.0"
+ },
+ "flag_ng": {
+ "c": "flags",
+ "e": "🇳🇬",
+ "d": "nigeria",
+ "u": "6.0"
+ },
+ "flag_ni": {
+ "c": "flags",
+ "e": "🇳🇮",
+ "d": "nicaragua",
+ "u": "6.0"
+ },
+ "flag_nl": {
+ "c": "flags",
+ "e": "🇳🇱",
+ "d": "the netherlands",
+ "u": "6.0"
+ },
+ "flag_no": {
+ "c": "flags",
+ "e": "🇳🇴",
+ "d": "norway",
+ "u": "6.0"
+ },
+ "flag_np": {
+ "c": "flags",
+ "e": "🇳🇵",
+ "d": "nepal",
+ "u": "6.0"
+ },
+ "flag_nr": {
+ "c": "flags",
+ "e": "🇳🇷",
+ "d": "nauru",
+ "u": "6.0"
+ },
+ "flag_nu": {
+ "c": "flags",
+ "e": "🇳🇺",
+ "d": "niue",
+ "u": "6.0"
+ },
+ "flag_nz": {
+ "c": "flags",
+ "e": "🇳🇿",
+ "d": "new zealand",
+ "u": "6.0"
+ },
+ "flag_om": {
+ "c": "flags",
+ "e": "🇴🇲",
+ "d": "oman",
+ "u": "6.0"
+ },
+ "flag_pa": {
+ "c": "flags",
+ "e": "🇵🇦",
+ "d": "panama",
+ "u": "6.0"
+ },
+ "flag_pe": {
+ "c": "flags",
+ "e": "🇵🇪",
+ "d": "peru",
+ "u": "6.0"
+ },
+ "flag_pf": {
+ "c": "flags",
+ "e": "🇵🇫",
+ "d": "french polynesia",
+ "u": "6.0"
+ },
+ "flag_pg": {
+ "c": "flags",
+ "e": "🇵🇬",
+ "d": "papua new guinea",
+ "u": "6.0"
+ },
+ "flag_ph": {
+ "c": "flags",
+ "e": "🇵🇭",
+ "d": "the philippines",
+ "u": "6.0"
+ },
+ "flag_pk": {
+ "c": "flags",
+ "e": "🇵🇰",
+ "d": "pakistan",
+ "u": "6.0"
+ },
+ "flag_pl": {
+ "c": "flags",
+ "e": "🇵🇱",
+ "d": "poland",
+ "u": "6.0"
+ },
+ "flag_pm": {
+ "c": "flags",
+ "e": "🇵🇲",
+ "d": "saint pierre and miquelon",
+ "u": "6.0"
+ },
+ "flag_pn": {
+ "c": "flags",
+ "e": "🇵🇳",
+ "d": "pitcairn",
+ "u": "6.0"
+ },
+ "flag_pr": {
+ "c": "flags",
+ "e": "🇵🇷",
+ "d": "puerto rico",
+ "u": "6.0"
+ },
+ "flag_ps": {
+ "c": "flags",
+ "e": "🇵🇸",
+ "d": "palestinian authority",
+ "u": "6.0"
+ },
+ "flag_pt": {
+ "c": "flags",
+ "e": "🇵🇹",
+ "d": "portugal",
+ "u": "6.0"
+ },
+ "flag_pw": {
+ "c": "flags",
+ "e": "🇵🇼",
+ "d": "palau",
+ "u": "6.0"
+ },
+ "flag_py": {
+ "c": "flags",
+ "e": "🇵🇾",
+ "d": "paraguay",
+ "u": "6.0"
+ },
+ "flag_qa": {
+ "c": "flags",
+ "e": "🇶🇦",
+ "d": "qatar",
+ "u": "6.0"
+ },
+ "flag_re": {
+ "c": "flags",
+ "e": "🇷🇪",
+ "d": "réunion",
+ "u": "6.0"
+ },
+ "flag_ro": {
+ "c": "flags",
+ "e": "🇷🇴",
+ "d": "romania",
+ "u": "6.0"
+ },
+ "flag_rs": {
+ "c": "flags",
+ "e": "🇷🇸",
+ "d": "serbia",
+ "u": "6.0"
+ },
+ "flag_ru": {
+ "c": "flags",
+ "e": "🇷🇺",
+ "d": "russia",
+ "u": "6.0"
+ },
+ "flag_rw": {
+ "c": "flags",
+ "e": "🇷🇼",
+ "d": "rwanda",
+ "u": "6.0"
+ },
+ "flag_sa": {
+ "c": "flags",
+ "e": "🇸🇦",
+ "d": "saudi arabia",
+ "u": "6.0"
+ },
+ "flag_sb": {
+ "c": "flags",
+ "e": "🇸🇧",
+ "d": "the solomon islands",
+ "u": "6.0"
+ },
+ "flag_sc": {
+ "c": "flags",
+ "e": "🇸🇨",
+ "d": "the seychelles",
+ "u": "6.0"
+ },
+ "flag_sd": {
+ "c": "flags",
+ "e": "🇸🇩",
+ "d": "sudan",
+ "u": "6.0"
+ },
+ "flag_se": {
+ "c": "flags",
+ "e": "🇸🇪",
+ "d": "sweden",
+ "u": "6.0"
+ },
+ "flag_sg": {
+ "c": "flags",
+ "e": "🇸🇬",
+ "d": "singapore",
+ "u": "6.0"
+ },
+ "flag_sh": {
+ "c": "flags",
+ "e": "🇸🇭",
+ "d": "saint helena",
+ "u": "6.0"
+ },
+ "flag_si": {
+ "c": "flags",
+ "e": "🇸🇮",
+ "d": "slovenia",
+ "u": "6.0"
+ },
+ "flag_sj": {
+ "c": "flags",
+ "e": "🇸🇯",
+ "d": "svalbard and jan mayen",
+ "u": "6.0"
+ },
+ "flag_sk": {
+ "c": "flags",
+ "e": "🇸🇰",
+ "d": "slovakia",
+ "u": "6.0"
+ },
+ "flag_sl": {
+ "c": "flags",
+ "e": "🇸🇱",
+ "d": "sierra leone",
+ "u": "6.0"
+ },
+ "flag_sm": {
+ "c": "flags",
+ "e": "🇸🇲",
+ "d": "san marino",
+ "u": "6.0"
+ },
+ "flag_sn": {
+ "c": "flags",
+ "e": "🇸🇳",
+ "d": "senegal",
+ "u": "6.0"
+ },
+ "flag_so": {
+ "c": "flags",
+ "e": "🇸🇴",
+ "d": "somalia",
+ "u": "6.0"
+ },
+ "flag_sr": {
+ "c": "flags",
+ "e": "🇸🇷",
+ "d": "suriname",
+ "u": "6.0"
+ },
+ "flag_ss": {
+ "c": "flags",
+ "e": "🇸🇸",
+ "d": "south sudan",
+ "u": "6.0"
+ },
+ "flag_st": {
+ "c": "flags",
+ "e": "🇸🇹",
+ "d": "sao tome and principe",
+ "u": "6.0"
+ },
+ "flag_sv": {
+ "c": "flags",
+ "e": "🇸🇻",
+ "d": "el salvador",
+ "u": "6.0"
+ },
+ "flag_sx": {
+ "c": "flags",
+ "e": "🇸🇽",
+ "d": "sint maarten",
+ "u": "6.0"
+ },
+ "flag_sy": {
+ "c": "flags",
+ "e": "🇸🇾",
+ "d": "syria",
+ "u": "6.0"
+ },
+ "flag_sz": {
+ "c": "flags",
+ "e": "🇸🇿",
+ "d": "swaziland",
+ "u": "6.0"
+ },
+ "flag_ta": {
+ "c": "flags",
+ "e": "🇹🇦",
+ "d": "tristan da cunha",
+ "u": "6.0"
+ },
+ "flag_tc": {
+ "c": "flags",
+ "e": "🇹🇨",
+ "d": "turks and caicos islands",
+ "u": "6.0"
+ },
+ "flag_td": {
+ "c": "flags",
+ "e": "🇹🇩",
+ "d": "chad",
+ "u": "6.0"
+ },
+ "flag_tf": {
+ "c": "flags",
+ "e": "🇹🇫",
+ "d": "french southern territories",
+ "u": "6.0"
+ },
+ "flag_tg": {
+ "c": "flags",
+ "e": "🇹🇬",
+ "d": "togo",
+ "u": "6.0"
+ },
+ "flag_th": {
+ "c": "flags",
+ "e": "🇹🇭",
+ "d": "thailand",
+ "u": "6.0"
+ },
+ "flag_tj": {
+ "c": "flags",
+ "e": "🇹🇯",
+ "d": "tajikistan",
+ "u": "6.0"
+ },
+ "flag_tk": {
+ "c": "flags",
+ "e": "🇹🇰",
+ "d": "tokelau",
+ "u": "6.0"
+ },
+ "flag_tl": {
+ "c": "flags",
+ "e": "🇹🇱",
+ "d": "east timor",
+ "u": "6.0"
+ },
+ "flag_tm": {
+ "c": "flags",
+ "e": "🇹🇲",
+ "d": "turkmenistan",
+ "u": "6.0"
+ },
+ "flag_tn": {
+ "c": "flags",
+ "e": "🇹🇳",
+ "d": "tunisia",
+ "u": "6.0"
+ },
+ "flag_to": {
+ "c": "flags",
+ "e": "🇹🇴",
+ "d": "tonga",
+ "u": "6.0"
+ },
+ "flag_tr": {
+ "c": "flags",
+ "e": "🇹🇷",
+ "d": "turkey",
+ "u": "6.0"
+ },
+ "flag_tt": {
+ "c": "flags",
+ "e": "🇹🇹",
+ "d": "trinidad and tobago",
+ "u": "6.0"
+ },
+ "flag_tv": {
+ "c": "flags",
+ "e": "🇹🇻",
+ "d": "tuvalu",
+ "u": "6.0"
+ },
+ "flag_tw": {
+ "c": "flags",
+ "e": "🇹🇼",
+ "d": "the republic of china",
+ "u": "6.0"
+ },
+ "flag_tz": {
+ "c": "flags",
+ "e": "🇹🇿",
+ "d": "tanzania",
+ "u": "6.0"
+ },
+ "flag_ua": {
+ "c": "flags",
+ "e": "🇺🇦",
+ "d": "ukraine",
+ "u": "6.0"
+ },
+ "flag_ug": {
+ "c": "flags",
+ "e": "🇺🇬",
+ "d": "uganda",
+ "u": "6.0"
+ },
+ "flag_um": {
+ "c": "flags",
+ "e": "🇺🇲",
+ "d": "united states minor outlying islands",
+ "u": "6.0"
+ },
+ "flag_us": {
+ "c": "flags",
+ "e": "🇺🇸",
+ "d": "united states",
+ "u": "6.0"
+ },
+ "flag_uy": {
+ "c": "flags",
+ "e": "🇺🇾",
+ "d": "uruguay",
+ "u": "6.0"
+ },
+ "flag_uz": {
+ "c": "flags",
+ "e": "🇺🇿",
+ "d": "uzbekistan",
+ "u": "6.0"
+ },
+ "flag_va": {
+ "c": "flags",
+ "e": "🇻🇦",
+ "d": "the vatican city",
+ "u": "6.0"
+ },
+ "flag_vc": {
+ "c": "flags",
+ "e": "🇻🇨",
+ "d": "saint vincent and the grenadines",
+ "u": "6.0"
+ },
+ "flag_ve": {
+ "c": "flags",
+ "e": "🇻🇪",
+ "d": "venezuela",
+ "u": "6.0"
+ },
+ "flag_vg": {
+ "c": "flags",
+ "e": "🇻🇬",
+ "d": "british virgin islands",
+ "u": "6.0"
+ },
+ "flag_vi": {
+ "c": "flags",
+ "e": "🇻🇮",
+ "d": "u.s. virgin islands",
+ "u": "6.0"
+ },
+ "flag_vn": {
+ "c": "flags",
+ "e": "🇻🇳",
+ "d": "vietnam",
+ "u": "6.0"
+ },
+ "flag_vu": {
+ "c": "flags",
+ "e": "🇻🇺",
+ "d": "vanuatu",
+ "u": "6.0"
+ },
+ "flag_wf": {
+ "c": "flags",
+ "e": "🇼🇫",
+ "d": "wallis and futuna",
+ "u": "6.0"
+ },
+ "flag_white": {
+ "c": "objects",
+ "e": "ðŸ³",
+ "d": "waving white flag",
+ "u": "6.0"
+ },
+ "flag_ws": {
+ "c": "flags",
+ "e": "🇼🇸",
+ "d": "samoa",
+ "u": "6.0"
+ },
+ "flag_xk": {
+ "c": "flags",
+ "e": "🇽🇰",
+ "d": "kosovo",
+ "u": "6.0"
+ },
+ "flag_ye": {
+ "c": "flags",
+ "e": "🇾🇪",
+ "d": "yemen",
+ "u": "6.0"
+ },
+ "flag_yt": {
+ "c": "flags",
+ "e": "🇾🇹",
+ "d": "mayotte",
+ "u": "6.0"
+ },
+ "flag_za": {
+ "c": "flags",
+ "e": "🇿🇦",
+ "d": "south africa",
+ "u": "6.0"
+ },
+ "flag_zm": {
+ "c": "flags",
+ "e": "🇿🇲",
+ "d": "zambia",
+ "u": "6.0"
+ },
+ "flag_zw": {
+ "c": "flags",
+ "e": "🇿🇼",
+ "d": "zimbabwe",
+ "u": "6.0"
+ },
+ "flags": {
+ "c": "objects",
+ "e": "ðŸŽ",
+ "d": "carp streamer",
+ "u": "6.0"
+ },
+ "flashlight": {
+ "c": "objects",
+ "e": "🔦",
+ "d": "electric torch",
+ "u": "6.0"
+ },
+ "fleur-de-lis": {
+ "c": "symbols",
+ "e": "⚜",
+ "d": "fleur-de-lis",
+ "u": "4.1"
+ },
+ "floppy_disk": {
+ "c": "objects",
+ "e": "💾",
+ "d": "floppy disk",
+ "u": "6.0"
+ },
+ "flower_playing_cards": {
+ "c": "symbols",
+ "e": "🎴",
+ "d": "flower playing cards",
+ "u": "6.0"
+ },
+ "flushed": {
+ "c": "people",
+ "e": "😳",
+ "d": "flushed face",
+ "u": "6.0"
+ },
+ "fog": {
+ "c": "nature",
+ "e": "🌫",
+ "d": "fog",
+ "u": "7.0"
+ },
+ "foggy": {
+ "c": "travel",
+ "e": "ðŸŒ",
+ "d": "foggy",
+ "u": "6.0"
+ },
+ "football": {
+ "c": "activity",
+ "e": "ðŸˆ",
+ "d": "american football",
+ "u": "6.0"
+ },
+ "footprints": {
+ "c": "people",
+ "e": "👣",
+ "d": "footprints",
+ "u": "6.0"
+ },
+ "fork_and_knife": {
+ "c": "food",
+ "e": "ðŸ´",
+ "d": "fork and knife",
+ "u": "6.0"
+ },
+ "fork_knife_plate": {
+ "c": "food",
+ "e": "ðŸ½",
+ "d": "fork and knife with plate",
+ "u": "7.0"
+ },
+ "fountain": {
+ "c": "travel",
+ "e": "⛲",
+ "d": "fountain",
+ "u": "5.2"
+ },
+ "four": {
+ "c": "symbols",
+ "e": "4ï¸âƒ£",
+ "d": "keycap digit four",
+ "u": "3.0"
+ },
+ "four_leaf_clover": {
+ "c": "nature",
+ "e": "ðŸ€",
+ "d": "four leaf clover",
+ "u": "6.0"
+ },
+ "fox": {
+ "c": "nature",
+ "e": "🦊",
+ "d": "fox face",
+ "u": "9.0"
+ },
+ "frame_photo": {
+ "c": "objects",
+ "e": "🖼",
+ "d": "frame with picture",
+ "u": "7.0"
+ },
+ "free": {
+ "c": "symbols",
+ "e": "🆓",
+ "d": "squared free",
+ "u": "6.0"
+ },
+ "french_bread": {
+ "c": "food",
+ "e": "🥖",
+ "d": "baguette bread",
+ "u": "9.0"
+ },
+ "fried_shrimp": {
+ "c": "food",
+ "e": "ðŸ¤",
+ "d": "fried shrimp",
+ "u": "6.0"
+ },
+ "fries": {
+ "c": "food",
+ "e": "ðŸŸ",
+ "d": "french fries",
+ "u": "6.0"
+ },
+ "frog": {
+ "c": "nature",
+ "e": "ðŸ¸",
+ "d": "frog face",
+ "u": "6.0"
+ },
+ "frowning": {
+ "c": "people",
+ "e": "😦",
+ "d": "frowning face with open mouth",
+ "u": "6.1"
+ },
+ "frowning2": {
+ "c": "people",
+ "e": "☹",
+ "d": "white frowning face",
+ "u": "1.1"
+ },
+ "fuelpump": {
+ "c": "travel",
+ "e": "⛽",
+ "d": "fuel pump",
+ "u": "5.2"
+ },
+ "full_moon": {
+ "c": "nature",
+ "e": "🌕",
+ "d": "full moon symbol",
+ "u": "6.0"
+ },
+ "full_moon_with_face": {
+ "c": "nature",
+ "e": "ðŸŒ",
+ "d": "full moon with face",
+ "u": "6.0"
+ },
+ "game_die": {
+ "c": "activity",
+ "e": "🎲",
+ "d": "game die",
+ "u": "6.0"
+ },
+ "gear": {
+ "c": "objects",
+ "e": "âš™",
+ "d": "gear",
+ "u": "4.1"
+ },
+ "gem": {
+ "c": "objects",
+ "e": "💎",
+ "d": "gem stone",
+ "u": "6.0"
+ },
+ "gay_pride_flag": {
+ "c": "flags",
+ "e": "ðŸ³ðŸŒˆ",
+ "d": "gay_pride_flag",
+ "u": "6.0"
+ },
+ "gemini": {
+ "c": "symbols",
+ "e": "♊",
+ "d": "gemini",
+ "u": "1.1"
+ },
+ "ghost": {
+ "c": "people",
+ "e": "👻",
+ "d": "ghost",
+ "u": "6.0"
+ },
+ "gift": {
+ "c": "objects",
+ "e": "ðŸŽ",
+ "d": "wrapped present",
+ "u": "6.0"
+ },
+ "gift_heart": {
+ "c": "symbols",
+ "e": "ðŸ’",
+ "d": "heart with ribbon",
+ "u": "6.0"
+ },
+ "girl": {
+ "c": "people",
+ "e": "👧",
+ "d": "girl",
+ "u": "6.0"
+ },
+ "girl_tone1": {
+ "c": "people",
+ "e": "👧ðŸ»",
+ "d": "girl tone 1",
+ "u": "8.0"
+ },
+ "girl_tone2": {
+ "c": "people",
+ "e": "👧ðŸ¼",
+ "d": "girl tone 2",
+ "u": "8.0"
+ },
+ "girl_tone3": {
+ "c": "people",
+ "e": "👧ðŸ½",
+ "d": "girl tone 3",
+ "u": "8.0"
+ },
+ "girl_tone4": {
+ "c": "people",
+ "e": "👧ðŸ¾",
+ "d": "girl tone 4",
+ "u": "8.0"
+ },
+ "girl_tone5": {
+ "c": "people",
+ "e": "👧ðŸ¿",
+ "d": "girl tone 5",
+ "u": "8.0"
+ },
+ "globe_with_meridians": {
+ "c": "symbols",
+ "e": "ðŸŒ",
+ "d": "globe with meridians",
+ "u": "6.0"
+ },
+ "goal": {
+ "c": "activity",
+ "e": "🥅",
+ "d": "goal net",
+ "u": "9.0"
+ },
+ "goat": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "goat",
+ "u": "6.0"
+ },
+ "golf": {
+ "c": "activity",
+ "e": "⛳",
+ "d": "flag in hole",
+ "u": "5.2"
+ },
+ "golfer": {
+ "c": "activity",
+ "e": "ðŸŒ",
+ "d": "golfer",
+ "u": "7.0"
+ },
+ "gorilla": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "gorilla",
+ "u": "9.0"
+ },
+ "grapes": {
+ "c": "food",
+ "e": "ðŸ‡",
+ "d": "grapes",
+ "u": "6.0"
+ },
+ "green_apple": {
+ "c": "food",
+ "e": "ðŸ",
+ "d": "green apple",
+ "u": "6.0"
+ },
+ "green_book": {
+ "c": "objects",
+ "e": "📗",
+ "d": "green book",
+ "u": "6.0"
+ },
+ "green_heart": {
+ "c": "symbols",
+ "e": "💚",
+ "d": "green heart",
+ "u": "6.0"
+ },
+ "grey_exclamation": {
+ "c": "symbols",
+ "e": "â•",
+ "d": "white exclamation mark ornament",
+ "u": "6.0"
+ },
+ "grey_question": {
+ "c": "symbols",
+ "e": "â”",
+ "d": "white question mark ornament",
+ "u": "6.0"
+ },
+ "grimacing": {
+ "c": "people",
+ "e": "😬",
+ "d": "grimacing face",
+ "u": "6.1"
+ },
+ "grin": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "grinning face with smiling eyes",
+ "u": "6.0"
+ },
+ "grinning": {
+ "c": "people",
+ "e": "😀",
+ "d": "grinning face",
+ "u": "6.1"
+ },
+ "guardsman": {
+ "c": "people",
+ "e": "💂",
+ "d": "guardsman",
+ "u": "6.0"
+ },
+ "guardsman_tone1": {
+ "c": "people",
+ "e": "💂ðŸ»",
+ "d": "guardsman tone 1",
+ "u": "8.0"
+ },
+ "guardsman_tone2": {
+ "c": "people",
+ "e": "💂ðŸ¼",
+ "d": "guardsman tone 2",
+ "u": "8.0"
+ },
+ "guardsman_tone3": {
+ "c": "people",
+ "e": "💂ðŸ½",
+ "d": "guardsman tone 3",
+ "u": "8.0"
+ },
+ "guardsman_tone4": {
+ "c": "people",
+ "e": "💂ðŸ¾",
+ "d": "guardsman tone 4",
+ "u": "8.0"
+ },
+ "guardsman_tone5": {
+ "c": "people",
+ "e": "💂ðŸ¿",
+ "d": "guardsman tone 5",
+ "u": "8.0"
+ },
+ "guitar": {
+ "c": "activity",
+ "e": "🎸",
+ "d": "guitar",
+ "u": "6.0"
+ },
+ "gun": {
+ "c": "objects",
+ "e": "🔫",
+ "d": "pistol",
+ "u": "6.0"
+ },
+ "haircut": {
+ "c": "people",
+ "e": "💇",
+ "d": "haircut",
+ "u": "6.0"
+ },
+ "haircut_tone1": {
+ "c": "people",
+ "e": "💇ðŸ»",
+ "d": "haircut tone 1",
+ "u": "8.0"
+ },
+ "haircut_tone2": {
+ "c": "people",
+ "e": "💇ðŸ¼",
+ "d": "haircut tone 2",
+ "u": "8.0"
+ },
+ "haircut_tone3": {
+ "c": "people",
+ "e": "💇ðŸ½",
+ "d": "haircut tone 3",
+ "u": "8.0"
+ },
+ "haircut_tone4": {
+ "c": "people",
+ "e": "💇ðŸ¾",
+ "d": "haircut tone 4",
+ "u": "8.0"
+ },
+ "haircut_tone5": {
+ "c": "people",
+ "e": "💇ðŸ¿",
+ "d": "haircut tone 5",
+ "u": "8.0"
+ },
+ "hamburger": {
+ "c": "food",
+ "e": "ðŸ”",
+ "d": "hamburger",
+ "u": "6.0"
+ },
+ "hammer": {
+ "c": "objects",
+ "e": "🔨",
+ "d": "hammer",
+ "u": "6.0"
+ },
+ "hammer_pick": {
+ "c": "objects",
+ "e": "âš’",
+ "d": "hammer and pick",
+ "u": "4.1"
+ },
+ "hamster": {
+ "c": "nature",
+ "e": "ðŸ¹",
+ "d": "hamster face",
+ "u": "6.0"
+ },
+ "hand_splayed": {
+ "c": "people",
+ "e": "ðŸ–",
+ "d": "raised hand with fingers splayed",
+ "u": "7.0"
+ },
+ "hand_splayed_tone1": {
+ "c": "people",
+ "e": "ðŸ–ðŸ»",
+ "d": "raised hand with fingers splayed tone 1",
+ "u": "8.0"
+ },
+ "hand_splayed_tone2": {
+ "c": "people",
+ "e": "ðŸ–ðŸ¼",
+ "d": "raised hand with fingers splayed tone 2",
+ "u": "8.0"
+ },
+ "hand_splayed_tone3": {
+ "c": "people",
+ "e": "ðŸ–ðŸ½",
+ "d": "raised hand with fingers splayed tone 3",
+ "u": "8.0"
+ },
+ "hand_splayed_tone4": {
+ "c": "people",
+ "e": "ðŸ–ðŸ¾",
+ "d": "raised hand with fingers splayed tone 4",
+ "u": "8.0"
+ },
+ "hand_splayed_tone5": {
+ "c": "people",
+ "e": "ðŸ–ðŸ¿",
+ "d": "raised hand with fingers splayed tone 5",
+ "u": "8.0"
+ },
+ "handbag": {
+ "c": "people",
+ "e": "👜",
+ "d": "handbag",
+ "u": "6.0"
+ },
+ "handball": {
+ "c": "activity",
+ "e": "🤾",
+ "d": "handball",
+ "u": "9.0"
+ },
+ "handball_tone1": {
+ "c": "activity",
+ "e": "🤾ðŸ»",
+ "d": "handball tone 1",
+ "u": "9.0"
+ },
+ "handball_tone2": {
+ "c": "activity",
+ "e": "🤾ðŸ¼",
+ "d": "handball tone 2",
+ "u": "9.0"
+ },
+ "handball_tone3": {
+ "c": "activity",
+ "e": "🤾ðŸ½",
+ "d": "handball tone 3",
+ "u": "9.0"
+ },
+ "handball_tone4": {
+ "c": "activity",
+ "e": "🤾ðŸ¾",
+ "d": "handball tone 4",
+ "u": "9.0"
+ },
+ "handball_tone5": {
+ "c": "activity",
+ "e": "🤾ðŸ¿",
+ "d": "handball tone 5",
+ "u": "9.0"
+ },
+ "handshake": {
+ "c": "people",
+ "e": "ðŸ¤",
+ "d": "handshake",
+ "u": "9.0"
+ },
+ "handshake_tone1": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ»",
+ "d": "handshake tone 1",
+ "u": "9.0"
+ },
+ "handshake_tone2": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ¼",
+ "d": "handshake tone 2",
+ "u": "9.0"
+ },
+ "handshake_tone3": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ½",
+ "d": "handshake tone 3",
+ "u": "9.0"
+ },
+ "handshake_tone4": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ¾",
+ "d": "handshake tone 4",
+ "u": "9.0"
+ },
+ "handshake_tone5": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ¿",
+ "d": "handshake tone 5",
+ "u": "9.0"
+ },
+ "hash": {
+ "c": "symbols",
+ "e": "#⃣",
+ "d": "number sign",
+ "u": "3.0"
+ },
+ "hatched_chick": {
+ "c": "nature",
+ "e": "ðŸ¥",
+ "d": "front-facing baby chick",
+ "u": "6.0"
+ },
+ "hatching_chick": {
+ "c": "nature",
+ "e": "ðŸ£",
+ "d": "hatching chick",
+ "u": "6.0"
+ },
+ "head_bandage": {
+ "c": "people",
+ "e": "🤕",
+ "d": "face with head-bandage",
+ "u": "8.0"
+ },
+ "headphones": {
+ "c": "activity",
+ "e": "🎧",
+ "d": "headphone",
+ "u": "6.0"
+ },
+ "hear_no_evil": {
+ "c": "nature",
+ "e": "🙉",
+ "d": "hear-no-evil monkey",
+ "u": "6.0"
+ },
+ "heart": {
+ "c": "symbols",
+ "e": "â¤",
+ "d": "heavy black heart",
+ "u": "1.1"
+ },
+ "heart_decoration": {
+ "c": "symbols",
+ "e": "💟",
+ "d": "heart decoration",
+ "u": "6.0"
+ },
+ "heart_exclamation": {
+ "c": "symbols",
+ "e": "â£",
+ "d": "heavy heart exclamation mark ornament",
+ "u": "1.1"
+ },
+ "heart_eyes": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "smiling face with heart-shaped eyes",
+ "u": "6.0"
+ },
+ "heart_eyes_cat": {
+ "c": "people",
+ "e": "😻",
+ "d": "smiling cat face with heart-shaped eyes",
+ "u": "6.0"
+ },
+ "heartbeat": {
+ "c": "symbols",
+ "e": "💓",
+ "d": "beating heart",
+ "u": "6.0"
+ },
+ "heartpulse": {
+ "c": "symbols",
+ "e": "💗",
+ "d": "growing heart",
+ "u": "6.0"
+ },
+ "hearts": {
+ "c": "symbols",
+ "e": "♥",
+ "d": "black heart suit",
+ "u": "1.1"
+ },
+ "heavy_check_mark": {
+ "c": "symbols",
+ "e": "✔",
+ "d": "heavy check mark",
+ "u": "1.1"
+ },
+ "heavy_division_sign": {
+ "c": "symbols",
+ "e": "âž—",
+ "d": "heavy division sign",
+ "u": "6.0"
+ },
+ "heavy_dollar_sign": {
+ "c": "symbols",
+ "e": "💲",
+ "d": "heavy dollar sign",
+ "u": "6.0"
+ },
+ "heavy_minus_sign": {
+ "c": "symbols",
+ "e": "âž–",
+ "d": "heavy minus sign",
+ "u": "6.0"
+ },
+ "heavy_multiplication_x": {
+ "c": "symbols",
+ "e": "✖",
+ "d": "heavy multiplication x",
+ "u": "1.1"
+ },
+ "heavy_plus_sign": {
+ "c": "symbols",
+ "e": "âž•",
+ "d": "heavy plus sign",
+ "u": "6.0"
+ },
+ "helicopter": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "helicopter",
+ "u": "6.0"
+ },
+ "helmet_with_cross": {
+ "c": "people",
+ "e": "⛑",
+ "d": "helmet with white cross",
+ "u": "5.2"
+ },
+ "herb": {
+ "c": "nature",
+ "e": "🌿",
+ "d": "herb",
+ "u": "6.0"
+ },
+ "hibiscus": {
+ "c": "nature",
+ "e": "🌺",
+ "d": "hibiscus",
+ "u": "6.0"
+ },
+ "high_brightness": {
+ "c": "symbols",
+ "e": "🔆",
+ "d": "high brightness symbol",
+ "u": "6.0"
+ },
+ "high_heel": {
+ "c": "people",
+ "e": "👠",
+ "d": "high-heeled shoe",
+ "u": "6.0"
+ },
+ "hockey": {
+ "c": "activity",
+ "e": "ðŸ’",
+ "d": "ice hockey stick and puck",
+ "u": "8.0"
+ },
+ "hole": {
+ "c": "objects",
+ "e": "🕳",
+ "d": "hole",
+ "u": "7.0"
+ },
+ "homes": {
+ "c": "travel",
+ "e": "ðŸ˜",
+ "d": "house buildings",
+ "u": "7.0"
+ },
+ "honey_pot": {
+ "c": "food",
+ "e": "ðŸ¯",
+ "d": "honey pot",
+ "u": "6.0"
+ },
+ "horse": {
+ "c": "nature",
+ "e": "ðŸ´",
+ "d": "horse face",
+ "u": "6.0"
+ },
+ "horse_racing": {
+ "c": "activity",
+ "e": "ðŸ‡",
+ "d": "horse racing",
+ "u": "6.0"
+ },
+ "horse_racing_tone1": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ»",
+ "d": "horse racing tone 1",
+ "u": "8.0"
+ },
+ "horse_racing_tone2": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ¼",
+ "d": "horse racing tone 2",
+ "u": "8.0"
+ },
+ "horse_racing_tone3": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ½",
+ "d": "horse racing tone 3",
+ "u": "8.0"
+ },
+ "horse_racing_tone4": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ¾",
+ "d": "horse racing tone 4",
+ "u": "8.0"
+ },
+ "horse_racing_tone5": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ¿",
+ "d": "horse racing tone 5",
+ "u": "8.0"
+ },
+ "hospital": {
+ "c": "travel",
+ "e": "ðŸ¥",
+ "d": "hospital",
+ "u": "6.0"
+ },
+ "hot_pepper": {
+ "c": "food",
+ "e": "🌶",
+ "d": "hot pepper",
+ "u": "7.0"
+ },
+ "hotdog": {
+ "c": "food",
+ "e": "🌭",
+ "d": "hot dog",
+ "u": "8.0"
+ },
+ "hotel": {
+ "c": "travel",
+ "e": "ðŸ¨",
+ "d": "hotel",
+ "u": "6.0"
+ },
+ "hotsprings": {
+ "c": "symbols",
+ "e": "♨",
+ "d": "hot springs",
+ "u": "1.1"
+ },
+ "hourglass": {
+ "c": "objects",
+ "e": "⌛",
+ "d": "hourglass",
+ "u": "1.1"
+ },
+ "hourglass_flowing_sand": {
+ "c": "objects",
+ "e": "â³",
+ "d": "hourglass with flowing sand",
+ "u": "6.0"
+ },
+ "house": {
+ "c": "travel",
+ "e": "ðŸ ",
+ "d": "house building",
+ "u": "6.0"
+ },
+ "house_abandoned": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "derelict house building",
+ "u": "7.0"
+ },
+ "house_with_garden": {
+ "c": "travel",
+ "e": "ðŸ¡",
+ "d": "house with garden",
+ "u": "6.0"
+ },
+ "hugging": {
+ "c": "people",
+ "e": "🤗",
+ "d": "hugging face",
+ "u": "8.0"
+ },
+ "hushed": {
+ "c": "people",
+ "e": "😯",
+ "d": "hushed face",
+ "u": "6.1"
+ },
+ "ice_cream": {
+ "c": "food",
+ "e": "ðŸ¨",
+ "d": "ice cream",
+ "u": "6.0"
+ },
+ "ice_skate": {
+ "c": "activity",
+ "e": "⛸",
+ "d": "ice skate",
+ "u": "5.2"
+ },
+ "icecream": {
+ "c": "food",
+ "e": "ðŸ¦",
+ "d": "soft ice cream",
+ "u": "6.0"
+ },
+ "id": {
+ "c": "symbols",
+ "e": "🆔",
+ "d": "squared id",
+ "u": "6.0"
+ },
+ "ideograph_advantage": {
+ "c": "symbols",
+ "e": "ðŸ‰",
+ "d": "circled ideograph advantage",
+ "u": "6.0"
+ },
+ "imp": {
+ "c": "people",
+ "e": "👿",
+ "d": "imp",
+ "u": "6.0"
+ },
+ "inbox_tray": {
+ "c": "objects",
+ "e": "📥",
+ "d": "inbox tray",
+ "u": "6.0"
+ },
+ "incoming_envelope": {
+ "c": "objects",
+ "e": "📨",
+ "d": "incoming envelope",
+ "u": "6.0"
+ },
+ "information_desk_person": {
+ "c": "people",
+ "e": "ðŸ’",
+ "d": "information desk person",
+ "u": "6.0"
+ },
+ "information_desk_person_tone1": {
+ "c": "people",
+ "e": "ðŸ’ðŸ»",
+ "d": "information desk person tone 1",
+ "u": "8.0"
+ },
+ "information_desk_person_tone2": {
+ "c": "people",
+ "e": "ðŸ’ðŸ¼",
+ "d": "information desk person tone 2",
+ "u": "8.0"
+ },
+ "information_desk_person_tone3": {
+ "c": "people",
+ "e": "ðŸ’ðŸ½",
+ "d": "information desk person tone 3",
+ "u": "8.0"
+ },
+ "information_desk_person_tone4": {
+ "c": "people",
+ "e": "ðŸ’ðŸ¾",
+ "d": "information desk person tone 4",
+ "u": "8.0"
+ },
+ "information_desk_person_tone5": {
+ "c": "people",
+ "e": "ðŸ’ðŸ¿",
+ "d": "information desk person tone 5",
+ "u": "8.0"
+ },
+ "information_source": {
+ "c": "symbols",
+ "e": "ℹ",
+ "d": "information source",
+ "u": "3.0"
+ },
+ "innocent": {
+ "c": "people",
+ "e": "😇",
+ "d": "smiling face with halo",
+ "u": "6.0"
+ },
+ "interrobang": {
+ "c": "symbols",
+ "e": "â‰",
+ "d": "exclamation question mark",
+ "u": "3.0"
+ },
+ "iphone": {
+ "c": "objects",
+ "e": "📱",
+ "d": "mobile phone",
+ "u": "6.0"
+ },
+ "island": {
+ "c": "travel",
+ "e": "ðŸ",
+ "d": "desert island",
+ "u": "7.0"
+ },
+ "izakaya_lantern": {
+ "c": "objects",
+ "e": "ðŸ®",
+ "d": "izakaya lantern",
+ "u": "6.0"
+ },
+ "jack_o_lantern": {
+ "c": "nature",
+ "e": "🎃",
+ "d": "jack-o-lantern",
+ "u": "6.0"
+ },
+ "japan": {
+ "c": "travel",
+ "e": "🗾",
+ "d": "silhouette of japan",
+ "u": "6.0"
+ },
+ "japanese_castle": {
+ "c": "travel",
+ "e": "ðŸ¯",
+ "d": "japanese castle",
+ "u": "6.0"
+ },
+ "japanese_goblin": {
+ "c": "people",
+ "e": "👺",
+ "d": "japanese goblin",
+ "u": "6.0"
+ },
+ "japanese_ogre": {
+ "c": "people",
+ "e": "👹",
+ "d": "japanese ogre",
+ "u": "6.0"
+ },
+ "jeans": {
+ "c": "people",
+ "e": "👖",
+ "d": "jeans",
+ "u": "6.0"
+ },
+ "joy": {
+ "c": "people",
+ "e": "😂",
+ "d": "face with tears of joy",
+ "u": "6.0"
+ },
+ "joy_cat": {
+ "c": "people",
+ "e": "😹",
+ "d": "cat face with tears of joy",
+ "u": "6.0"
+ },
+ "joystick": {
+ "c": "objects",
+ "e": "🕹",
+ "d": "joystick",
+ "u": "7.0"
+ },
+ "juggling": {
+ "c": "activity",
+ "e": "🤹",
+ "d": "juggling",
+ "u": "9.0"
+ },
+ "juggling_tone1": {
+ "c": "activity",
+ "e": "🤹ðŸ»",
+ "d": "juggling tone 1",
+ "u": "9.0"
+ },
+ "juggling_tone2": {
+ "c": "activity",
+ "e": "🤹ðŸ¼",
+ "d": "juggling tone 2",
+ "u": "9.0"
+ },
+ "juggling_tone3": {
+ "c": "activity",
+ "e": "🤹ðŸ½",
+ "d": "juggling tone 3",
+ "u": "9.0"
+ },
+ "juggling_tone4": {
+ "c": "activity",
+ "e": "🤹ðŸ¾",
+ "d": "juggling tone 4",
+ "u": "9.0"
+ },
+ "juggling_tone5": {
+ "c": "activity",
+ "e": "🤹ðŸ¿",
+ "d": "juggling tone 5",
+ "u": "9.0"
+ },
+ "kaaba": {
+ "c": "travel",
+ "e": "🕋",
+ "d": "kaaba",
+ "u": "8.0"
+ },
+ "key": {
+ "c": "objects",
+ "e": "🔑",
+ "d": "key",
+ "u": "6.0"
+ },
+ "key2": {
+ "c": "objects",
+ "e": "ðŸ—",
+ "d": "old key",
+ "u": "7.0"
+ },
+ "keyboard": {
+ "c": "objects",
+ "e": "⌨",
+ "d": "keyboard",
+ "u": "1.1"
+ },
+ "kimono": {
+ "c": "people",
+ "e": "👘",
+ "d": "kimono",
+ "u": "6.0"
+ },
+ "kiss": {
+ "c": "people",
+ "e": "💋",
+ "d": "kiss mark",
+ "u": "6.0"
+ },
+ "kiss_mm": {
+ "c": "people",
+ "e": "👨â€â¤ï¸â€ðŸ’‹â€ðŸ‘¨",
+ "d": "kiss (man,man)",
+ "u": "6.0"
+ },
+ "kiss_ww": {
+ "c": "people",
+ "e": "👩â€â¤ï¸â€ðŸ’‹â€ðŸ‘©",
+ "d": "kiss (woman,woman)",
+ "u": "6.0"
+ },
+ "kissing": {
+ "c": "people",
+ "e": "😗",
+ "d": "kissing face",
+ "u": "6.1"
+ },
+ "kissing_cat": {
+ "c": "people",
+ "e": "😽",
+ "d": "kissing cat face with closed eyes",
+ "u": "6.0"
+ },
+ "kissing_closed_eyes": {
+ "c": "people",
+ "e": "😚",
+ "d": "kissing face with closed eyes",
+ "u": "6.0"
+ },
+ "kissing_heart": {
+ "c": "people",
+ "e": "😘",
+ "d": "face throwing a kiss",
+ "u": "6.0"
+ },
+ "kissing_smiling_eyes": {
+ "c": "people",
+ "e": "😙",
+ "d": "kissing face with smiling eyes",
+ "u": "6.1"
+ },
+ "kiwi": {
+ "c": "food",
+ "e": "ðŸ¥",
+ "d": "kiwifruit",
+ "u": "9.0"
+ },
+ "knife": {
+ "c": "objects",
+ "e": "🔪",
+ "d": "hocho",
+ "u": "6.0"
+ },
+ "koala": {
+ "c": "nature",
+ "e": "ðŸ¨",
+ "d": "koala",
+ "u": "6.0"
+ },
+ "koko": {
+ "c": "symbols",
+ "e": "ðŸˆ",
+ "d": "squared katakana koko",
+ "u": "6.0"
+ },
+ "label": {
+ "c": "objects",
+ "e": "ðŸ·",
+ "d": "label",
+ "u": "7.0"
+ },
+ "large_blue_circle": {
+ "c": "symbols",
+ "e": "🔵",
+ "d": "large blue circle",
+ "u": "6.0"
+ },
+ "large_blue_diamond": {
+ "c": "symbols",
+ "e": "🔷",
+ "d": "large blue diamond",
+ "u": "6.0"
+ },
+ "large_orange_diamond": {
+ "c": "symbols",
+ "e": "🔶",
+ "d": "large orange diamond",
+ "u": "6.0"
+ },
+ "last_quarter_moon": {
+ "c": "nature",
+ "e": "🌗",
+ "d": "last quarter moon symbol",
+ "u": "6.0"
+ },
+ "last_quarter_moon_with_face": {
+ "c": "nature",
+ "e": "🌜",
+ "d": "last quarter moon with face",
+ "u": "6.0"
+ },
+ "laughing": {
+ "c": "people",
+ "e": "😆",
+ "d": "smiling face with open mouth and tightly-closed ey",
+ "u": "6.0"
+ },
+ "leaves": {
+ "c": "nature",
+ "e": "ðŸƒ",
+ "d": "leaf fluttering in wind",
+ "u": "6.0"
+ },
+ "ledger": {
+ "c": "objects",
+ "e": "📒",
+ "d": "ledger",
+ "u": "6.0"
+ },
+ "left_facing_fist": {
+ "c": "people",
+ "e": "🤛",
+ "d": "left-facing fist",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone1": {
+ "c": "people",
+ "e": "🤛ðŸ»",
+ "d": "left facing fist tone 1",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone2": {
+ "c": "people",
+ "e": "🤛ðŸ¼",
+ "d": "left facing fist tone 2",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone3": {
+ "c": "people",
+ "e": "🤛ðŸ½",
+ "d": "left facing fist tone 3",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone4": {
+ "c": "people",
+ "e": "🤛ðŸ¾",
+ "d": "left facing fist tone 4",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone5": {
+ "c": "people",
+ "e": "🤛ðŸ¿",
+ "d": "left facing fist tone 5",
+ "u": "9.0"
+ },
+ "left_luggage": {
+ "c": "symbols",
+ "e": "🛅",
+ "d": "left luggage",
+ "u": "6.0"
+ },
+ "left_right_arrow": {
+ "c": "symbols",
+ "e": "↔",
+ "d": "left right arrow",
+ "u": "1.1"
+ },
+ "leftwards_arrow_with_hook": {
+ "c": "symbols",
+ "e": "↩",
+ "d": "leftwards arrow with hook",
+ "u": "1.1"
+ },
+ "lemon": {
+ "c": "food",
+ "e": "ðŸ‹",
+ "d": "lemon",
+ "u": "6.0"
+ },
+ "leo": {
+ "c": "symbols",
+ "e": "♌",
+ "d": "leo",
+ "u": "1.1"
+ },
+ "leopard": {
+ "c": "nature",
+ "e": "ðŸ†",
+ "d": "leopard",
+ "u": "6.0"
+ },
+ "level_slider": {
+ "c": "objects",
+ "e": "🎚",
+ "d": "level slider",
+ "u": "7.0"
+ },
+ "levitate": {
+ "c": "activity",
+ "e": "🕴",
+ "d": "man in business suit levitating",
+ "u": "7.0"
+ },
+ "libra": {
+ "c": "symbols",
+ "e": "♎",
+ "d": "libra",
+ "u": "1.1"
+ },
+ "lifter": {
+ "c": "activity",
+ "e": "ðŸ‹",
+ "d": "weight lifter",
+ "u": "7.0"
+ },
+ "lifter_tone1": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ»",
+ "d": "weight lifter tone 1",
+ "u": "8.0"
+ },
+ "lifter_tone2": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ¼",
+ "d": "weight lifter tone 2",
+ "u": "8.0"
+ },
+ "lifter_tone3": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ½",
+ "d": "weight lifter tone 3",
+ "u": "8.0"
+ },
+ "lifter_tone4": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ¾",
+ "d": "weight lifter tone 4",
+ "u": "8.0"
+ },
+ "lifter_tone5": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ¿",
+ "d": "weight lifter tone 5",
+ "u": "8.0"
+ },
+ "light_rail": {
+ "c": "travel",
+ "e": "🚈",
+ "d": "light rail",
+ "u": "6.0"
+ },
+ "link": {
+ "c": "objects",
+ "e": "🔗",
+ "d": "link symbol",
+ "u": "6.0"
+ },
+ "lion_face": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "lion face",
+ "u": "8.0"
+ },
+ "lips": {
+ "c": "people",
+ "e": "👄",
+ "d": "mouth",
+ "u": "6.0"
+ },
+ "lipstick": {
+ "c": "people",
+ "e": "💄",
+ "d": "lipstick",
+ "u": "6.0"
+ },
+ "lizard": {
+ "c": "nature",
+ "e": "🦎",
+ "d": "lizard",
+ "u": "9.0"
+ },
+ "lock": {
+ "c": "objects",
+ "e": "🔒",
+ "d": "lock",
+ "u": "6.0"
+ },
+ "lock_with_ink_pen": {
+ "c": "objects",
+ "e": "ðŸ”",
+ "d": "lock with ink pen",
+ "u": "6.0"
+ },
+ "lollipop": {
+ "c": "food",
+ "e": "ðŸ­",
+ "d": "lollipop",
+ "u": "6.0"
+ },
+ "loop": {
+ "c": "symbols",
+ "e": "âž¿",
+ "d": "double curly loop",
+ "u": "6.0"
+ },
+ "loud_sound": {
+ "c": "symbols",
+ "e": "🔊",
+ "d": "speaker with three sound waves",
+ "u": "6.0"
+ },
+ "loudspeaker": {
+ "c": "symbols",
+ "e": "📢",
+ "d": "public address loudspeaker",
+ "u": "6.0"
+ },
+ "love_hotel": {
+ "c": "travel",
+ "e": "ðŸ©",
+ "d": "love hotel",
+ "u": "6.0"
+ },
+ "love_letter": {
+ "c": "objects",
+ "e": "💌",
+ "d": "love letter",
+ "u": "6.0"
+ },
+ "low_brightness": {
+ "c": "symbols",
+ "e": "🔅",
+ "d": "low brightness symbol",
+ "u": "6.0"
+ },
+ "lying_face": {
+ "c": "people",
+ "e": "🤥",
+ "d": "lying face",
+ "u": "9.0"
+ },
+ "m": {
+ "c": "symbols",
+ "e": "â“‚",
+ "d": "circled latin capital letter m",
+ "u": "1.1"
+ },
+ "mag": {
+ "c": "objects",
+ "e": "ðŸ”",
+ "d": "left-pointing magnifying glass",
+ "u": "6.0"
+ },
+ "mag_right": {
+ "c": "objects",
+ "e": "🔎",
+ "d": "right-pointing magnifying glass",
+ "u": "6.0"
+ },
+ "mahjong": {
+ "c": "symbols",
+ "e": "🀄",
+ "d": "mahjong tile red dragon",
+ "u": "5.1"
+ },
+ "mailbox": {
+ "c": "objects",
+ "e": "📫",
+ "d": "closed mailbox with raised flag",
+ "u": "6.0"
+ },
+ "mailbox_closed": {
+ "c": "objects",
+ "e": "📪",
+ "d": "closed mailbox with lowered flag",
+ "u": "6.0"
+ },
+ "mailbox_with_mail": {
+ "c": "objects",
+ "e": "📬",
+ "d": "open mailbox with raised flag",
+ "u": "6.0"
+ },
+ "mailbox_with_no_mail": {
+ "c": "objects",
+ "e": "📭",
+ "d": "open mailbox with lowered flag",
+ "u": "6.0"
+ },
+ "man": {
+ "c": "people",
+ "e": "👨",
+ "d": "man",
+ "u": "6.0"
+ },
+ "man_dancing": {
+ "c": "people",
+ "e": "🕺",
+ "d": "man dancing",
+ "u": "9.0"
+ },
+ "man_dancing_tone1": {
+ "c": "activity",
+ "e": "🕺ðŸ»",
+ "d": "man dancing tone 1",
+ "u": "9.0"
+ },
+ "man_dancing_tone2": {
+ "c": "activity",
+ "e": "🕺ðŸ¼",
+ "d": "man dancing tone 2",
+ "u": "9.0"
+ },
+ "man_dancing_tone3": {
+ "c": "activity",
+ "e": "🕺ðŸ½",
+ "d": "man dancing tone 3",
+ "u": "9.0"
+ },
+ "man_dancing_tone4": {
+ "c": "activity",
+ "e": "🕺ðŸ¾",
+ "d": "man dancing tone 4",
+ "u": "9.0"
+ },
+ "man_dancing_tone5": {
+ "c": "activity",
+ "e": "🕺ðŸ¿",
+ "d": "man dancing tone 5",
+ "u": "9.0"
+ },
+ "man_in_tuxedo": {
+ "c": "people",
+ "e": "🤵",
+ "d": "man in tuxedo",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone1": {
+ "c": "people",
+ "e": "🤵ðŸ»",
+ "d": "man in tuxedo tone 1",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone2": {
+ "c": "people",
+ "e": "🤵ðŸ¼",
+ "d": "man in tuxedo tone 2",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone3": {
+ "c": "people",
+ "e": "🤵ðŸ½",
+ "d": "man in tuxedo tone 3",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone4": {
+ "c": "people",
+ "e": "🤵ðŸ¾",
+ "d": "man in tuxedo tone 4",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone5": {
+ "c": "people",
+ "e": "🤵ðŸ¿",
+ "d": "man in tuxedo tone 5",
+ "u": "9.0"
+ },
+ "man_tone1": {
+ "c": "people",
+ "e": "👨ðŸ»",
+ "d": "man tone 1",
+ "u": "8.0"
+ },
+ "man_tone2": {
+ "c": "people",
+ "e": "👨ðŸ¼",
+ "d": "man tone 2",
+ "u": "8.0"
+ },
+ "man_tone3": {
+ "c": "people",
+ "e": "👨ðŸ½",
+ "d": "man tone 3",
+ "u": "8.0"
+ },
+ "man_tone4": {
+ "c": "people",
+ "e": "👨ðŸ¾",
+ "d": "man tone 4",
+ "u": "8.0"
+ },
+ "man_tone5": {
+ "c": "people",
+ "e": "👨ðŸ¿",
+ "d": "man tone 5",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao": {
+ "c": "people",
+ "e": "👲",
+ "d": "man with gua pi mao",
+ "u": "6.0"
+ },
+ "man_with_gua_pi_mao_tone1": {
+ "c": "people",
+ "e": "👲ðŸ»",
+ "d": "man with gua pi mao tone 1",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao_tone2": {
+ "c": "people",
+ "e": "👲ðŸ¼",
+ "d": "man with gua pi mao tone 2",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao_tone3": {
+ "c": "people",
+ "e": "👲ðŸ½",
+ "d": "man with gua pi mao tone 3",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao_tone4": {
+ "c": "people",
+ "e": "👲ðŸ¾",
+ "d": "man with gua pi mao tone 4",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao_tone5": {
+ "c": "people",
+ "e": "👲ðŸ¿",
+ "d": "man with gua pi mao tone 5",
+ "u": "8.0"
+ },
+ "man_with_turban": {
+ "c": "people",
+ "e": "👳",
+ "d": "man with turban",
+ "u": "6.0"
+ },
+ "man_with_turban_tone1": {
+ "c": "people",
+ "e": "👳ðŸ»",
+ "d": "man with turban tone 1",
+ "u": "8.0"
+ },
+ "man_with_turban_tone2": {
+ "c": "people",
+ "e": "👳ðŸ¼",
+ "d": "man with turban tone 2",
+ "u": "8.0"
+ },
+ "man_with_turban_tone3": {
+ "c": "people",
+ "e": "👳ðŸ½",
+ "d": "man with turban tone 3",
+ "u": "8.0"
+ },
+ "man_with_turban_tone4": {
+ "c": "people",
+ "e": "👳ðŸ¾",
+ "d": "man with turban tone 4",
+ "u": "8.0"
+ },
+ "man_with_turban_tone5": {
+ "c": "people",
+ "e": "👳ðŸ¿",
+ "d": "man with turban tone 5",
+ "u": "8.0"
+ },
+ "mans_shoe": {
+ "c": "people",
+ "e": "👞",
+ "d": "mans shoe",
+ "u": "6.0"
+ },
+ "map": {
+ "c": "objects",
+ "e": "🗺",
+ "d": "world map",
+ "u": "7.0"
+ },
+ "maple_leaf": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "maple leaf",
+ "u": "6.0"
+ },
+ "martial_arts_uniform": {
+ "c": "activity",
+ "e": "🥋",
+ "d": "martial arts uniform",
+ "u": "9.0"
+ },
+ "mask": {
+ "c": "people",
+ "e": "😷",
+ "d": "face with medical mask",
+ "u": "6.0"
+ },
+ "massage": {
+ "c": "people",
+ "e": "💆",
+ "d": "face massage",
+ "u": "6.0"
+ },
+ "massage_tone1": {
+ "c": "people",
+ "e": "💆ðŸ»",
+ "d": "face massage tone 1",
+ "u": "8.0"
+ },
+ "massage_tone2": {
+ "c": "people",
+ "e": "💆ðŸ¼",
+ "d": "face massage tone 2",
+ "u": "8.0"
+ },
+ "massage_tone3": {
+ "c": "people",
+ "e": "💆ðŸ½",
+ "d": "face massage tone 3",
+ "u": "8.0"
+ },
+ "massage_tone4": {
+ "c": "people",
+ "e": "💆ðŸ¾",
+ "d": "face massage tone 4",
+ "u": "8.0"
+ },
+ "massage_tone5": {
+ "c": "people",
+ "e": "💆ðŸ¿",
+ "d": "face massage tone 5",
+ "u": "8.0"
+ },
+ "meat_on_bone": {
+ "c": "food",
+ "e": "ðŸ–",
+ "d": "meat on bone",
+ "u": "6.0"
+ },
+ "medal": {
+ "c": "activity",
+ "e": "ðŸ…",
+ "d": "sports medal",
+ "u": "7.0"
+ },
+ "mega": {
+ "c": "symbols",
+ "e": "📣",
+ "d": "cheering megaphone",
+ "u": "6.0"
+ },
+ "melon": {
+ "c": "food",
+ "e": "ðŸˆ",
+ "d": "melon",
+ "u": "6.0"
+ },
+ "menorah": {
+ "c": "symbols",
+ "e": "🕎",
+ "d": "menorah with nine branches",
+ "u": "8.0"
+ },
+ "mens": {
+ "c": "symbols",
+ "e": "🚹",
+ "d": "mens symbol",
+ "u": "6.0"
+ },
+ "metal": {
+ "c": "people",
+ "e": "🤘",
+ "d": "sign of the horns",
+ "u": "8.0"
+ },
+ "metal_tone1": {
+ "c": "people",
+ "e": "🤘ðŸ»",
+ "d": "sign of the horns tone 1",
+ "u": "8.0"
+ },
+ "metal_tone2": {
+ "c": "people",
+ "e": "🤘ðŸ¼",
+ "d": "sign of the horns tone 2",
+ "u": "8.0"
+ },
+ "metal_tone3": {
+ "c": "people",
+ "e": "🤘ðŸ½",
+ "d": "sign of the horns tone 3",
+ "u": "8.0"
+ },
+ "metal_tone4": {
+ "c": "people",
+ "e": "🤘ðŸ¾",
+ "d": "sign of the horns tone 4",
+ "u": "8.0"
+ },
+ "metal_tone5": {
+ "c": "people",
+ "e": "🤘ðŸ¿",
+ "d": "sign of the horns tone 5",
+ "u": "8.0"
+ },
+ "metro": {
+ "c": "travel",
+ "e": "🚇",
+ "d": "metro",
+ "u": "6.0"
+ },
+ "microphone": {
+ "c": "activity",
+ "e": "🎤",
+ "d": "microphone",
+ "u": "6.0"
+ },
+ "microphone2": {
+ "c": "objects",
+ "e": "🎙",
+ "d": "studio microphone",
+ "u": "7.0"
+ },
+ "microscope": {
+ "c": "objects",
+ "e": "🔬",
+ "d": "microscope",
+ "u": "6.0"
+ },
+ "middle_finger": {
+ "c": "people",
+ "e": "🖕",
+ "d": "reversed hand with middle finger extended",
+ "u": "7.0"
+ },
+ "middle_finger_tone1": {
+ "c": "people",
+ "e": "🖕ðŸ»",
+ "d": "reversed hand with middle finger extended tone 1",
+ "u": "8.0"
+ },
+ "middle_finger_tone2": {
+ "c": "people",
+ "e": "🖕ðŸ¼",
+ "d": "reversed hand with middle finger extended tone 2",
+ "u": "8.0"
+ },
+ "middle_finger_tone3": {
+ "c": "people",
+ "e": "🖕ðŸ½",
+ "d": "reversed hand with middle finger extended tone 3",
+ "u": "8.0"
+ },
+ "middle_finger_tone4": {
+ "c": "people",
+ "e": "🖕ðŸ¾",
+ "d": "reversed hand with middle finger extended tone 4",
+ "u": "8.0"
+ },
+ "middle_finger_tone5": {
+ "c": "people",
+ "e": "🖕ðŸ¿",
+ "d": "reversed hand with middle finger extended tone 5",
+ "u": "8.0"
+ },
+ "military_medal": {
+ "c": "activity",
+ "e": "🎖",
+ "d": "military medal",
+ "u": "7.0"
+ },
+ "milk": {
+ "c": "food",
+ "e": "🥛",
+ "d": "glass of milk",
+ "u": "9.0"
+ },
+ "milky_way": {
+ "c": "travel",
+ "e": "🌌",
+ "d": "milky way",
+ "u": "6.0"
+ },
+ "minibus": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "minibus",
+ "u": "6.0"
+ },
+ "minidisc": {
+ "c": "objects",
+ "e": "💽",
+ "d": "minidisc",
+ "u": "6.0"
+ },
+ "mobile_phone_off": {
+ "c": "symbols",
+ "e": "📴",
+ "d": "mobile phone off",
+ "u": "6.0"
+ },
+ "money_mouth": {
+ "c": "people",
+ "e": "🤑",
+ "d": "money-mouth face",
+ "u": "8.0"
+ },
+ "money_with_wings": {
+ "c": "objects",
+ "e": "💸",
+ "d": "money with wings",
+ "u": "6.0"
+ },
+ "moneybag": {
+ "c": "objects",
+ "e": "💰",
+ "d": "money bag",
+ "u": "6.0"
+ },
+ "monkey": {
+ "c": "nature",
+ "e": "ðŸ’",
+ "d": "monkey",
+ "u": "6.0"
+ },
+ "monkey_face": {
+ "c": "nature",
+ "e": "ðŸµ",
+ "d": "monkey face",
+ "u": "6.0"
+ },
+ "monorail": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "monorail",
+ "u": "6.0"
+ },
+ "mortar_board": {
+ "c": "people",
+ "e": "🎓",
+ "d": "graduation cap",
+ "u": "6.0"
+ },
+ "mosque": {
+ "c": "travel",
+ "e": "🕌",
+ "d": "mosque",
+ "u": "8.0"
+ },
+ "motor_scooter": {
+ "c": "travel",
+ "e": "🛵",
+ "d": "motor scooter",
+ "u": "9.0"
+ },
+ "motorboat": {
+ "c": "travel",
+ "e": "🛥",
+ "d": "motorboat",
+ "u": "7.0"
+ },
+ "motorcycle": {
+ "c": "travel",
+ "e": "ðŸ",
+ "d": "racing motorcycle",
+ "u": "7.0"
+ },
+ "motorway": {
+ "c": "travel",
+ "e": "🛣",
+ "d": "motorway",
+ "u": "7.0"
+ },
+ "mount_fuji": {
+ "c": "travel",
+ "e": "🗻",
+ "d": "mount fuji",
+ "u": "6.0"
+ },
+ "mountain": {
+ "c": "travel",
+ "e": "â›°",
+ "d": "mountain",
+ "u": "5.2"
+ },
+ "mountain_bicyclist": {
+ "c": "activity",
+ "e": "🚵",
+ "d": "mountain bicyclist",
+ "u": "6.0"
+ },
+ "mountain_bicyclist_tone1": {
+ "c": "activity",
+ "e": "🚵ðŸ»",
+ "d": "mountain bicyclist tone 1",
+ "u": "8.0"
+ },
+ "mountain_bicyclist_tone2": {
+ "c": "activity",
+ "e": "🚵ðŸ¼",
+ "d": "mountain bicyclist tone 2",
+ "u": "8.0"
+ },
+ "mountain_bicyclist_tone3": {
+ "c": "activity",
+ "e": "🚵ðŸ½",
+ "d": "mountain bicyclist tone 3",
+ "u": "8.0"
+ },
+ "mountain_bicyclist_tone4": {
+ "c": "activity",
+ "e": "🚵ðŸ¾",
+ "d": "mountain bicyclist tone 4",
+ "u": "8.0"
+ },
+ "mountain_bicyclist_tone5": {
+ "c": "activity",
+ "e": "🚵ðŸ¿",
+ "d": "mountain bicyclist tone 5",
+ "u": "8.0"
+ },
+ "mountain_cableway": {
+ "c": "travel",
+ "e": "🚠",
+ "d": "mountain cableway",
+ "u": "6.0"
+ },
+ "mountain_railway": {
+ "c": "travel",
+ "e": "🚞",
+ "d": "mountain railway",
+ "u": "6.0"
+ },
+ "mountain_snow": {
+ "c": "travel",
+ "e": "ðŸ”",
+ "d": "snow capped mountain",
+ "u": "7.0"
+ },
+ "mouse": {
+ "c": "nature",
+ "e": "ðŸ­",
+ "d": "mouse face",
+ "u": "6.0"
+ },
+ "mouse2": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "mouse",
+ "u": "6.0"
+ },
+ "mouse_three_button": {
+ "c": "objects",
+ "e": "🖱",
+ "d": "three button mouse",
+ "u": "7.0"
+ },
+ "movie_camera": {
+ "c": "objects",
+ "e": "🎥",
+ "d": "movie camera",
+ "u": "6.0"
+ },
+ "moyai": {
+ "c": "objects",
+ "e": "🗿",
+ "d": "moyai",
+ "u": "6.0"
+ },
+ "mrs_claus": {
+ "c": "people",
+ "e": "🤶",
+ "d": "mother christmas",
+ "u": "9.0"
+ },
+ "mrs_claus_tone1": {
+ "c": "people",
+ "e": "🤶ðŸ»",
+ "d": "mother christmas tone 1",
+ "u": "9.0"
+ },
+ "mrs_claus_tone2": {
+ "c": "people",
+ "e": "🤶ðŸ¼",
+ "d": "mother christmas tone 2",
+ "u": "9.0"
+ },
+ "mrs_claus_tone3": {
+ "c": "people",
+ "e": "🤶ðŸ½",
+ "d": "mother christmas tone 3",
+ "u": "9.0"
+ },
+ "mrs_claus_tone4": {
+ "c": "people",
+ "e": "🤶ðŸ¾",
+ "d": "mother christmas tone 4",
+ "u": "9.0"
+ },
+ "mrs_claus_tone5": {
+ "c": "people",
+ "e": "🤶ðŸ¿",
+ "d": "mother christmas tone 5",
+ "u": "9.0"
+ },
+ "muscle": {
+ "c": "people",
+ "e": "💪",
+ "d": "flexed biceps",
+ "u": "6.0"
+ },
+ "muscle_tone1": {
+ "c": "people",
+ "e": "💪ðŸ»",
+ "d": "flexed biceps tone 1",
+ "u": "8.0"
+ },
+ "muscle_tone2": {
+ "c": "people",
+ "e": "💪ðŸ¼",
+ "d": "flexed biceps tone 2",
+ "u": "8.0"
+ },
+ "muscle_tone3": {
+ "c": "people",
+ "e": "💪ðŸ½",
+ "d": "flexed biceps tone 3",
+ "u": "8.0"
+ },
+ "muscle_tone4": {
+ "c": "people",
+ "e": "💪ðŸ¾",
+ "d": "flexed biceps tone 4",
+ "u": "8.0"
+ },
+ "muscle_tone5": {
+ "c": "people",
+ "e": "💪ðŸ¿",
+ "d": "flexed biceps tone 5",
+ "u": "8.0"
+ },
+ "mushroom": {
+ "c": "nature",
+ "e": "ðŸ„",
+ "d": "mushroom",
+ "u": "6.0"
+ },
+ "musical_keyboard": {
+ "c": "activity",
+ "e": "🎹",
+ "d": "musical keyboard",
+ "u": "6.0"
+ },
+ "musical_note": {
+ "c": "symbols",
+ "e": "🎵",
+ "d": "musical note",
+ "u": "6.0"
+ },
+ "musical_score": {
+ "c": "activity",
+ "e": "🎼",
+ "d": "musical score",
+ "u": "6.0"
+ },
+ "mute": {
+ "c": "symbols",
+ "e": "🔇",
+ "d": "speaker with cancellation stroke",
+ "u": "6.0"
+ },
+ "nail_care": {
+ "c": "people",
+ "e": "💅",
+ "d": "nail polish",
+ "u": "6.0"
+ },
+ "nail_care_tone1": {
+ "c": "people",
+ "e": "💅ðŸ»",
+ "d": "nail polish tone 1",
+ "u": "8.0"
+ },
+ "nail_care_tone2": {
+ "c": "people",
+ "e": "💅ðŸ¼",
+ "d": "nail polish tone 2",
+ "u": "8.0"
+ },
+ "nail_care_tone3": {
+ "c": "people",
+ "e": "💅ðŸ½",
+ "d": "nail polish tone 3",
+ "u": "8.0"
+ },
+ "nail_care_tone4": {
+ "c": "people",
+ "e": "💅ðŸ¾",
+ "d": "nail polish tone 4",
+ "u": "8.0"
+ },
+ "nail_care_tone5": {
+ "c": "people",
+ "e": "💅ðŸ¿",
+ "d": "nail polish tone 5",
+ "u": "8.0"
+ },
+ "name_badge": {
+ "c": "symbols",
+ "e": "📛",
+ "d": "name badge",
+ "u": "6.0"
+ },
+ "nauseated_face": {
+ "c": "people",
+ "e": "🤢",
+ "d": "nauseated face",
+ "u": "9.0"
+ },
+ "necktie": {
+ "c": "people",
+ "e": "👔",
+ "d": "necktie",
+ "u": "6.0"
+ },
+ "negative_squared_cross_mark": {
+ "c": "symbols",
+ "e": "âŽ",
+ "d": "negative squared cross mark",
+ "u": "6.0"
+ },
+ "nerd": {
+ "c": "people",
+ "e": "🤓",
+ "d": "nerd face",
+ "u": "8.0"
+ },
+ "neutral_face": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "neutral face",
+ "u": "6.0"
+ },
+ "new": {
+ "c": "symbols",
+ "e": "🆕",
+ "d": "squared new",
+ "u": "6.0"
+ },
+ "new_moon": {
+ "c": "nature",
+ "e": "🌑",
+ "d": "new moon symbol",
+ "u": "6.0"
+ },
+ "new_moon_with_face": {
+ "c": "nature",
+ "e": "🌚",
+ "d": "new moon with face",
+ "u": "6.0"
+ },
+ "newspaper": {
+ "c": "objects",
+ "e": "📰",
+ "d": "newspaper",
+ "u": "6.0"
+ },
+ "newspaper2": {
+ "c": "objects",
+ "e": "🗞",
+ "d": "rolled-up newspaper",
+ "u": "7.0"
+ },
+ "ng": {
+ "c": "symbols",
+ "e": "🆖",
+ "d": "squared ng",
+ "u": "6.0"
+ },
+ "night_with_stars": {
+ "c": "travel",
+ "e": "🌃",
+ "d": "night with stars",
+ "u": "6.0"
+ },
+ "nine": {
+ "c": "symbols",
+ "e": "9ï¸âƒ£",
+ "d": "keycap digit nine",
+ "u": "3.0"
+ },
+ "no_bell": {
+ "c": "symbols",
+ "e": "🔕",
+ "d": "bell with cancellation stroke",
+ "u": "6.0"
+ },
+ "no_bicycles": {
+ "c": "symbols",
+ "e": "🚳",
+ "d": "no bicycles",
+ "u": "6.0"
+ },
+ "no_entry": {
+ "c": "symbols",
+ "e": "â›”",
+ "d": "no entry",
+ "u": "5.2"
+ },
+ "no_entry_sign": {
+ "c": "symbols",
+ "e": "🚫",
+ "d": "no entry sign",
+ "u": "6.0"
+ },
+ "no_good": {
+ "c": "people",
+ "e": "🙅",
+ "d": "face with no good gesture",
+ "u": "6.0"
+ },
+ "no_good_tone1": {
+ "c": "people",
+ "e": "🙅ðŸ»",
+ "d": "face with no good gesture tone 1",
+ "u": "8.0"
+ },
+ "no_good_tone2": {
+ "c": "people",
+ "e": "🙅ðŸ¼",
+ "d": "face with no good gesture tone 2",
+ "u": "8.0"
+ },
+ "no_good_tone3": {
+ "c": "people",
+ "e": "🙅ðŸ½",
+ "d": "face with no good gesture tone 3",
+ "u": "8.0"
+ },
+ "no_good_tone4": {
+ "c": "people",
+ "e": "🙅ðŸ¾",
+ "d": "face with no good gesture tone 4",
+ "u": "8.0"
+ },
+ "no_good_tone5": {
+ "c": "people",
+ "e": "🙅ðŸ¿",
+ "d": "face with no good gesture tone 5",
+ "u": "8.0"
+ },
+ "no_mobile_phones": {
+ "c": "symbols",
+ "e": "📵",
+ "d": "no mobile phones",
+ "u": "6.0"
+ },
+ "no_mouth": {
+ "c": "people",
+ "e": "😶",
+ "d": "face without mouth",
+ "u": "6.0"
+ },
+ "no_pedestrians": {
+ "c": "symbols",
+ "e": "🚷",
+ "d": "no pedestrians",
+ "u": "6.0"
+ },
+ "no_smoking": {
+ "c": "symbols",
+ "e": "🚭",
+ "d": "no smoking symbol",
+ "u": "6.0"
+ },
+ "non-potable_water": {
+ "c": "symbols",
+ "e": "🚱",
+ "d": "non-potable water symbol",
+ "u": "6.0"
+ },
+ "nose": {
+ "c": "people",
+ "e": "👃",
+ "d": "nose",
+ "u": "6.0"
+ },
+ "nose_tone1": {
+ "c": "people",
+ "e": "👃ðŸ»",
+ "d": "nose tone 1",
+ "u": "8.0"
+ },
+ "nose_tone2": {
+ "c": "people",
+ "e": "👃ðŸ¼",
+ "d": "nose tone 2",
+ "u": "8.0"
+ },
+ "nose_tone3": {
+ "c": "people",
+ "e": "👃ðŸ½",
+ "d": "nose tone 3",
+ "u": "8.0"
+ },
+ "nose_tone4": {
+ "c": "people",
+ "e": "👃ðŸ¾",
+ "d": "nose tone 4",
+ "u": "8.0"
+ },
+ "nose_tone5": {
+ "c": "people",
+ "e": "👃ðŸ¿",
+ "d": "nose tone 5",
+ "u": "8.0"
+ },
+ "notebook": {
+ "c": "objects",
+ "e": "📓",
+ "d": "notebook",
+ "u": "6.0"
+ },
+ "notebook_with_decorative_cover": {
+ "c": "objects",
+ "e": "📔",
+ "d": "notebook with decorative cover",
+ "u": "6.0"
+ },
+ "notepad_spiral": {
+ "c": "objects",
+ "e": "🗒",
+ "d": "spiral note pad",
+ "u": "7.0"
+ },
+ "notes": {
+ "c": "symbols",
+ "e": "🎶",
+ "d": "multiple musical notes",
+ "u": "6.0"
+ },
+ "nut_and_bolt": {
+ "c": "objects",
+ "e": "🔩",
+ "d": "nut and bolt",
+ "u": "6.0"
+ },
+ "o": {
+ "c": "symbols",
+ "e": "â­•",
+ "d": "heavy large circle",
+ "u": "5.2"
+ },
+ "o2": {
+ "c": "symbols",
+ "e": "🅾",
+ "d": "negative squared latin capital letter o",
+ "u": "6.0"
+ },
+ "ocean": {
+ "c": "nature",
+ "e": "🌊",
+ "d": "water wave",
+ "u": "6.0"
+ },
+ "octagonal_sign": {
+ "c": "symbols",
+ "e": "🛑",
+ "d": "octagonal sign",
+ "u": "9.0"
+ },
+ "octopus": {
+ "c": "nature",
+ "e": "ðŸ™",
+ "d": "octopus",
+ "u": "6.0"
+ },
+ "oden": {
+ "c": "food",
+ "e": "ðŸ¢",
+ "d": "oden",
+ "u": "6.0"
+ },
+ "office": {
+ "c": "travel",
+ "e": "ðŸ¢",
+ "d": "office building",
+ "u": "6.0"
+ },
+ "oil": {
+ "c": "objects",
+ "e": "🛢",
+ "d": "oil drum",
+ "u": "7.0"
+ },
+ "ok": {
+ "c": "symbols",
+ "e": "🆗",
+ "d": "squared ok",
+ "u": "6.0"
+ },
+ "ok_hand": {
+ "c": "people",
+ "e": "👌",
+ "d": "ok hand sign",
+ "u": "6.0"
+ },
+ "ok_hand_tone1": {
+ "c": "people",
+ "e": "👌ðŸ»",
+ "d": "ok hand sign tone 1",
+ "u": "8.0"
+ },
+ "ok_hand_tone2": {
+ "c": "people",
+ "e": "👌ðŸ¼",
+ "d": "ok hand sign tone 2",
+ "u": "8.0"
+ },
+ "ok_hand_tone3": {
+ "c": "people",
+ "e": "👌ðŸ½",
+ "d": "ok hand sign tone 3",
+ "u": "8.0"
+ },
+ "ok_hand_tone4": {
+ "c": "people",
+ "e": "👌ðŸ¾",
+ "d": "ok hand sign tone 4",
+ "u": "8.0"
+ },
+ "ok_hand_tone5": {
+ "c": "people",
+ "e": "👌ðŸ¿",
+ "d": "ok hand sign tone 5",
+ "u": "8.0"
+ },
+ "ok_woman": {
+ "c": "people",
+ "e": "🙆",
+ "d": "face with ok gesture",
+ "u": "6.0"
+ },
+ "ok_woman_tone1": {
+ "c": "people",
+ "e": "🙆ðŸ»",
+ "d": "face with ok gesture tone1",
+ "u": "8.0"
+ },
+ "ok_woman_tone2": {
+ "c": "people",
+ "e": "🙆ðŸ¼",
+ "d": "face with ok gesture tone2",
+ "u": "8.0"
+ },
+ "ok_woman_tone3": {
+ "c": "people",
+ "e": "🙆ðŸ½",
+ "d": "face with ok gesture tone3",
+ "u": "8.0"
+ },
+ "ok_woman_tone4": {
+ "c": "people",
+ "e": "🙆ðŸ¾",
+ "d": "face with ok gesture tone4",
+ "u": "8.0"
+ },
+ "ok_woman_tone5": {
+ "c": "people",
+ "e": "🙆ðŸ¿",
+ "d": "face with ok gesture tone5",
+ "u": "8.0"
+ },
+ "older_man": {
+ "c": "people",
+ "e": "👴",
+ "d": "older man",
+ "u": "6.0"
+ },
+ "older_man_tone1": {
+ "c": "people",
+ "e": "👴ðŸ»",
+ "d": "older man tone 1",
+ "u": "8.0"
+ },
+ "older_man_tone2": {
+ "c": "people",
+ "e": "👴ðŸ¼",
+ "d": "older man tone 2",
+ "u": "8.0"
+ },
+ "older_man_tone3": {
+ "c": "people",
+ "e": "👴ðŸ½",
+ "d": "older man tone 3",
+ "u": "8.0"
+ },
+ "older_man_tone4": {
+ "c": "people",
+ "e": "👴ðŸ¾",
+ "d": "older man tone 4",
+ "u": "8.0"
+ },
+ "older_man_tone5": {
+ "c": "people",
+ "e": "👴ðŸ¿",
+ "d": "older man tone 5",
+ "u": "8.0"
+ },
+ "older_woman": {
+ "c": "people",
+ "e": "👵",
+ "d": "older woman",
+ "u": "6.0"
+ },
+ "older_woman_tone1": {
+ "c": "people",
+ "e": "👵ðŸ»",
+ "d": "older woman tone 1",
+ "u": "8.0"
+ },
+ "older_woman_tone2": {
+ "c": "people",
+ "e": "👵ðŸ¼",
+ "d": "older woman tone 2",
+ "u": "8.0"
+ },
+ "older_woman_tone3": {
+ "c": "people",
+ "e": "👵ðŸ½",
+ "d": "older woman tone 3",
+ "u": "8.0"
+ },
+ "older_woman_tone4": {
+ "c": "people",
+ "e": "👵ðŸ¾",
+ "d": "older woman tone 4",
+ "u": "8.0"
+ },
+ "older_woman_tone5": {
+ "c": "people",
+ "e": "👵ðŸ¿",
+ "d": "older woman tone 5",
+ "u": "8.0"
+ },
+ "om_symbol": {
+ "c": "symbols",
+ "e": "🕉",
+ "d": "om symbol",
+ "u": "7.0"
+ },
+ "on": {
+ "c": "symbols",
+ "e": "🔛",
+ "d": "on with exclamation mark with left right arrow abo",
+ "u": "6.0"
+ },
+ "oncoming_automobile": {
+ "c": "travel",
+ "e": "🚘",
+ "d": "oncoming automobile",
+ "u": "6.0"
+ },
+ "oncoming_bus": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "oncoming bus",
+ "u": "6.0"
+ },
+ "oncoming_police_car": {
+ "c": "travel",
+ "e": "🚔",
+ "d": "oncoming police car",
+ "u": "6.0"
+ },
+ "oncoming_taxi": {
+ "c": "travel",
+ "e": "🚖",
+ "d": "oncoming taxi",
+ "u": "6.0"
+ },
+ "one": {
+ "c": "symbols",
+ "e": "1ï¸âƒ£",
+ "d": "keycap digit one",
+ "u": "3.0"
+ },
+ "open_file_folder": {
+ "c": "objects",
+ "e": "📂",
+ "d": "open file folder",
+ "u": "6.0"
+ },
+ "open_hands": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "open hands sign",
+ "u": "6.0"
+ },
+ "open_hands_tone1": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ»",
+ "d": "open hands sign tone 1",
+ "u": "8.0"
+ },
+ "open_hands_tone2": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¼",
+ "d": "open hands sign tone 2",
+ "u": "8.0"
+ },
+ "open_hands_tone3": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ½",
+ "d": "open hands sign tone 3",
+ "u": "8.0"
+ },
+ "open_hands_tone4": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¾",
+ "d": "open hands sign tone 4",
+ "u": "8.0"
+ },
+ "open_hands_tone5": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¿",
+ "d": "open hands sign tone 5",
+ "u": "8.0"
+ },
+ "open_mouth": {
+ "c": "people",
+ "e": "😮",
+ "d": "face with open mouth",
+ "u": "6.1"
+ },
+ "ophiuchus": {
+ "c": "symbols",
+ "e": "⛎",
+ "d": "ophiuchus",
+ "u": "6.0"
+ },
+ "orange_book": {
+ "c": "objects",
+ "e": "📙",
+ "d": "orange book",
+ "u": "6.0"
+ },
+ "orthodox_cross": {
+ "c": "symbols",
+ "e": "☦",
+ "d": "orthodox cross",
+ "u": "1.1"
+ },
+ "outbox_tray": {
+ "c": "objects",
+ "e": "📤",
+ "d": "outbox tray",
+ "u": "6.0"
+ },
+ "owl": {
+ "c": "nature",
+ "e": "🦉",
+ "d": "owl",
+ "u": "9.0"
+ },
+ "ox": {
+ "c": "nature",
+ "e": "ðŸ‚",
+ "d": "ox",
+ "u": "6.0"
+ },
+ "package": {
+ "c": "objects",
+ "e": "📦",
+ "d": "package",
+ "u": "6.0"
+ },
+ "page_facing_up": {
+ "c": "objects",
+ "e": "📄",
+ "d": "page facing up",
+ "u": "6.0"
+ },
+ "page_with_curl": {
+ "c": "objects",
+ "e": "📃",
+ "d": "page with curl",
+ "u": "6.0"
+ },
+ "pager": {
+ "c": "objects",
+ "e": "📟",
+ "d": "pager",
+ "u": "6.0"
+ },
+ "paintbrush": {
+ "c": "objects",
+ "e": "🖌",
+ "d": "lower left paintbrush",
+ "u": "7.0"
+ },
+ "palm_tree": {
+ "c": "nature",
+ "e": "🌴",
+ "d": "palm tree",
+ "u": "6.0"
+ },
+ "pancakes": {
+ "c": "food",
+ "e": "🥞",
+ "d": "pancakes",
+ "u": "9.0"
+ },
+ "panda_face": {
+ "c": "nature",
+ "e": "ðŸ¼",
+ "d": "panda face",
+ "u": "6.0"
+ },
+ "paperclip": {
+ "c": "objects",
+ "e": "📎",
+ "d": "paperclip",
+ "u": "6.0"
+ },
+ "paperclips": {
+ "c": "objects",
+ "e": "🖇",
+ "d": "linked paperclips",
+ "u": "7.0"
+ },
+ "park": {
+ "c": "travel",
+ "e": "ðŸž",
+ "d": "national park",
+ "u": "7.0"
+ },
+ "parking": {
+ "c": "symbols",
+ "e": "🅿",
+ "d": "negative squared latin capital letter p",
+ "u": "5.2"
+ },
+ "part_alternation_mark": {
+ "c": "symbols",
+ "e": "〽",
+ "d": "part alternation mark",
+ "u": "3.2"
+ },
+ "partly_sunny": {
+ "c": "nature",
+ "e": "â›…",
+ "d": "sun behind cloud",
+ "u": "5.2"
+ },
+ "passport_control": {
+ "c": "symbols",
+ "e": "🛂",
+ "d": "passport control",
+ "u": "6.0"
+ },
+ "pause_button": {
+ "c": "symbols",
+ "e": "â¸",
+ "d": "double vertical bar",
+ "u": "7.0"
+ },
+ "peace": {
+ "c": "symbols",
+ "e": "☮",
+ "d": "peace symbol",
+ "u": "1.1"
+ },
+ "peach": {
+ "c": "food",
+ "e": "ðŸ‘",
+ "d": "peach",
+ "u": "6.0"
+ },
+ "peanuts": {
+ "c": "food",
+ "e": "🥜",
+ "d": "peanuts",
+ "u": "9.0"
+ },
+ "pear": {
+ "c": "food",
+ "e": "ðŸ",
+ "d": "pear",
+ "u": "6.0"
+ },
+ "pen_ballpoint": {
+ "c": "objects",
+ "e": "🖊",
+ "d": "lower left ballpoint pen",
+ "u": "7.0"
+ },
+ "pen_fountain": {
+ "c": "objects",
+ "e": "🖋",
+ "d": "lower left fountain pen",
+ "u": "7.0"
+ },
+ "pencil": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "memo",
+ "u": "6.0"
+ },
+ "pencil2": {
+ "c": "objects",
+ "e": "âœ",
+ "d": "pencil",
+ "u": "1.1"
+ },
+ "penguin": {
+ "c": "nature",
+ "e": "ðŸ§",
+ "d": "penguin",
+ "u": "6.0"
+ },
+ "pensive": {
+ "c": "people",
+ "e": "😔",
+ "d": "pensive face",
+ "u": "6.0"
+ },
+ "performing_arts": {
+ "c": "activity",
+ "e": "🎭",
+ "d": "performing arts",
+ "u": "6.0"
+ },
+ "persevere": {
+ "c": "people",
+ "e": "😣",
+ "d": "persevering face",
+ "u": "6.0"
+ },
+ "person_frowning": {
+ "c": "people",
+ "e": "ðŸ™",
+ "d": "person frowning",
+ "u": "6.0"
+ },
+ "person_frowning_tone1": {
+ "c": "people",
+ "e": "ðŸ™ðŸ»",
+ "d": "person frowning tone 1",
+ "u": "8.0"
+ },
+ "person_frowning_tone2": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¼",
+ "d": "person frowning tone 2",
+ "u": "8.0"
+ },
+ "person_frowning_tone3": {
+ "c": "people",
+ "e": "ðŸ™ðŸ½",
+ "d": "person frowning tone 3",
+ "u": "8.0"
+ },
+ "person_frowning_tone4": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¾",
+ "d": "person frowning tone 4",
+ "u": "8.0"
+ },
+ "person_frowning_tone5": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¿",
+ "d": "person frowning tone 5",
+ "u": "8.0"
+ },
+ "person_with_blond_hair": {
+ "c": "people",
+ "e": "👱",
+ "d": "person with blond hair",
+ "u": "6.0"
+ },
+ "person_with_blond_hair_tone1": {
+ "c": "people",
+ "e": "👱ðŸ»",
+ "d": "person with blond hair tone 1",
+ "u": "8.0"
+ },
+ "person_with_blond_hair_tone2": {
+ "c": "people",
+ "e": "👱ðŸ¼",
+ "d": "person with blond hair tone 2",
+ "u": "8.0"
+ },
+ "person_with_blond_hair_tone3": {
+ "c": "people",
+ "e": "👱ðŸ½",
+ "d": "person with blond hair tone 3",
+ "u": "8.0"
+ },
+ "person_with_blond_hair_tone4": {
+ "c": "people",
+ "e": "👱ðŸ¾",
+ "d": "person with blond hair tone 4",
+ "u": "8.0"
+ },
+ "person_with_blond_hair_tone5": {
+ "c": "people",
+ "e": "👱ðŸ¿",
+ "d": "person with blond hair tone 5",
+ "u": "8.0"
+ },
+ "person_with_pouting_face": {
+ "c": "people",
+ "e": "🙎",
+ "d": "person with pouting face",
+ "u": "6.0"
+ },
+ "person_with_pouting_face_tone1": {
+ "c": "people",
+ "e": "🙎ðŸ»",
+ "d": "person with pouting face tone1",
+ "u": "8.0"
+ },
+ "person_with_pouting_face_tone2": {
+ "c": "people",
+ "e": "🙎ðŸ¼",
+ "d": "person with pouting face tone2",
+ "u": "8.0"
+ },
+ "person_with_pouting_face_tone3": {
+ "c": "people",
+ "e": "🙎ðŸ½",
+ "d": "person with pouting face tone3",
+ "u": "8.0"
+ },
+ "person_with_pouting_face_tone4": {
+ "c": "people",
+ "e": "🙎ðŸ¾",
+ "d": "person with pouting face tone4",
+ "u": "8.0"
+ },
+ "person_with_pouting_face_tone5": {
+ "c": "people",
+ "e": "🙎ðŸ¿",
+ "d": "person with pouting face tone5",
+ "u": "8.0"
+ },
+ "pick": {
+ "c": "objects",
+ "e": "â›",
+ "d": "pick",
+ "u": "5.2"
+ },
+ "pig": {
+ "c": "nature",
+ "e": "ðŸ·",
+ "d": "pig face",
+ "u": "6.0"
+ },
+ "pig2": {
+ "c": "nature",
+ "e": "ðŸ–",
+ "d": "pig",
+ "u": "6.0"
+ },
+ "pig_nose": {
+ "c": "nature",
+ "e": "ðŸ½",
+ "d": "pig nose",
+ "u": "6.0"
+ },
+ "pill": {
+ "c": "objects",
+ "e": "💊",
+ "d": "pill",
+ "u": "6.0"
+ },
+ "pineapple": {
+ "c": "food",
+ "e": "ðŸ",
+ "d": "pineapple",
+ "u": "6.0"
+ },
+ "ping_pong": {
+ "c": "activity",
+ "e": "ðŸ“",
+ "d": "table tennis paddle and ball",
+ "u": "8.0"
+ },
+ "pisces": {
+ "c": "symbols",
+ "e": "♓",
+ "d": "pisces",
+ "u": "1.1"
+ },
+ "pizza": {
+ "c": "food",
+ "e": "ðŸ•",
+ "d": "slice of pizza",
+ "u": "6.0"
+ },
+ "place_of_worship": {
+ "c": "symbols",
+ "e": "ðŸ›",
+ "d": "place of worship",
+ "u": "8.0"
+ },
+ "play_pause": {
+ "c": "symbols",
+ "e": "â¯",
+ "d": "black right-pointing double triangle with double vertical bar",
+ "u": "6.0"
+ },
+ "point_down": {
+ "c": "people",
+ "e": "👇",
+ "d": "white down pointing backhand index",
+ "u": "6.0"
+ },
+ "point_down_tone1": {
+ "c": "people",
+ "e": "👇ðŸ»",
+ "d": "white down pointing backhand index tone 1",
+ "u": "8.0"
+ },
+ "point_down_tone2": {
+ "c": "people",
+ "e": "👇ðŸ¼",
+ "d": "white down pointing backhand index tone 2",
+ "u": "8.0"
+ },
+ "point_down_tone3": {
+ "c": "people",
+ "e": "👇ðŸ½",
+ "d": "white down pointing backhand index tone 3",
+ "u": "8.0"
+ },
+ "point_down_tone4": {
+ "c": "people",
+ "e": "👇ðŸ¾",
+ "d": "white down pointing backhand index tone 4",
+ "u": "8.0"
+ },
+ "point_down_tone5": {
+ "c": "people",
+ "e": "👇ðŸ¿",
+ "d": "white down pointing backhand index tone 5",
+ "u": "8.0"
+ },
+ "point_left": {
+ "c": "people",
+ "e": "👈",
+ "d": "white left pointing backhand index",
+ "u": "6.0"
+ },
+ "point_left_tone1": {
+ "c": "people",
+ "e": "👈ðŸ»",
+ "d": "white left pointing backhand index tone 1",
+ "u": "8.0"
+ },
+ "point_left_tone2": {
+ "c": "people",
+ "e": "👈ðŸ¼",
+ "d": "white left pointing backhand index tone 2",
+ "u": "8.0"
+ },
+ "point_left_tone3": {
+ "c": "people",
+ "e": "👈ðŸ½",
+ "d": "white left pointing backhand index tone 3",
+ "u": "8.0"
+ },
+ "point_left_tone4": {
+ "c": "people",
+ "e": "👈ðŸ¾",
+ "d": "white left pointing backhand index tone 4",
+ "u": "8.0"
+ },
+ "point_left_tone5": {
+ "c": "people",
+ "e": "👈ðŸ¿",
+ "d": "white left pointing backhand index tone 5",
+ "u": "8.0"
+ },
+ "point_right": {
+ "c": "people",
+ "e": "👉",
+ "d": "white right pointing backhand index",
+ "u": "6.0"
+ },
+ "point_right_tone1": {
+ "c": "people",
+ "e": "👉ðŸ»",
+ "d": "white right pointing backhand index tone 1",
+ "u": "8.0"
+ },
+ "point_right_tone2": {
+ "c": "people",
+ "e": "👉ðŸ¼",
+ "d": "white right pointing backhand index tone 2",
+ "u": "8.0"
+ },
+ "point_right_tone3": {
+ "c": "people",
+ "e": "👉ðŸ½",
+ "d": "white right pointing backhand index tone 3",
+ "u": "8.0"
+ },
+ "point_right_tone4": {
+ "c": "people",
+ "e": "👉ðŸ¾",
+ "d": "white right pointing backhand index tone 4",
+ "u": "8.0"
+ },
+ "point_right_tone5": {
+ "c": "people",
+ "e": "👉ðŸ¿",
+ "d": "white right pointing backhand index tone 5",
+ "u": "8.0"
+ },
+ "point_up": {
+ "c": "people",
+ "e": "â˜",
+ "d": "white up pointing index",
+ "u": "1.1"
+ },
+ "point_up_2": {
+ "c": "people",
+ "e": "👆",
+ "d": "white up pointing backhand index",
+ "u": "6.0"
+ },
+ "point_up_2_tone1": {
+ "c": "people",
+ "e": "👆ðŸ»",
+ "d": "white up pointing backhand index tone 1",
+ "u": "8.0"
+ },
+ "point_up_2_tone2": {
+ "c": "people",
+ "e": "👆ðŸ¼",
+ "d": "white up pointing backhand index tone 2",
+ "u": "8.0"
+ },
+ "point_up_2_tone3": {
+ "c": "people",
+ "e": "👆ðŸ½",
+ "d": "white up pointing backhand index tone 3",
+ "u": "8.0"
+ },
+ "point_up_2_tone4": {
+ "c": "people",
+ "e": "👆ðŸ¾",
+ "d": "white up pointing backhand index tone 4",
+ "u": "8.0"
+ },
+ "point_up_2_tone5": {
+ "c": "people",
+ "e": "👆ðŸ¿",
+ "d": "white up pointing backhand index tone 5",
+ "u": "8.0"
+ },
+ "point_up_tone1": {
+ "c": "people",
+ "e": "â˜ðŸ»",
+ "d": "white up pointing index tone 1",
+ "u": "8.0"
+ },
+ "point_up_tone2": {
+ "c": "people",
+ "e": "â˜ðŸ¼",
+ "d": "white up pointing index tone 2",
+ "u": "8.0"
+ },
+ "point_up_tone3": {
+ "c": "people",
+ "e": "â˜ðŸ½",
+ "d": "white up pointing index tone 3",
+ "u": "8.0"
+ },
+ "point_up_tone4": {
+ "c": "people",
+ "e": "â˜ðŸ¾",
+ "d": "white up pointing index tone 4",
+ "u": "8.0"
+ },
+ "point_up_tone5": {
+ "c": "people",
+ "e": "â˜ðŸ¿",
+ "d": "white up pointing index tone 5",
+ "u": "8.0"
+ },
+ "police_car": {
+ "c": "travel",
+ "e": "🚓",
+ "d": "police car",
+ "u": "6.0"
+ },
+ "poodle": {
+ "c": "nature",
+ "e": "ðŸ©",
+ "d": "poodle",
+ "u": "6.0"
+ },
+ "poop": {
+ "c": "people",
+ "e": "💩",
+ "d": "pile of poo",
+ "u": "6.0"
+ },
+ "popcorn": {
+ "c": "food",
+ "e": "ðŸ¿",
+ "d": "popcorn",
+ "u": "8.0"
+ },
+ "post_office": {
+ "c": "travel",
+ "e": "ðŸ£",
+ "d": "japanese post office",
+ "u": "6.0"
+ },
+ "postal_horn": {
+ "c": "objects",
+ "e": "📯",
+ "d": "postal horn",
+ "u": "6.0"
+ },
+ "postbox": {
+ "c": "objects",
+ "e": "📮",
+ "d": "postbox",
+ "u": "6.0"
+ },
+ "potable_water": {
+ "c": "symbols",
+ "e": "🚰",
+ "d": "potable water symbol",
+ "u": "6.0"
+ },
+ "potato": {
+ "c": "food",
+ "e": "🥔",
+ "d": "potato",
+ "u": "9.0"
+ },
+ "pouch": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "pouch",
+ "u": "6.0"
+ },
+ "poultry_leg": {
+ "c": "food",
+ "e": "ðŸ—",
+ "d": "poultry leg",
+ "u": "6.0"
+ },
+ "pound": {
+ "c": "objects",
+ "e": "💷",
+ "d": "banknote with pound sign",
+ "u": "6.0"
+ },
+ "pouting_cat": {
+ "c": "people",
+ "e": "😾",
+ "d": "pouting cat face",
+ "u": "6.0"
+ },
+ "pray": {
+ "c": "people",
+ "e": "ðŸ™",
+ "d": "person with folded hands",
+ "u": "6.0"
+ },
+ "pray_tone1": {
+ "c": "people",
+ "e": "ðŸ™ðŸ»",
+ "d": "person with folded hands tone 1",
+ "u": "8.0"
+ },
+ "pray_tone2": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¼",
+ "d": "person with folded hands tone 2",
+ "u": "8.0"
+ },
+ "pray_tone3": {
+ "c": "people",
+ "e": "ðŸ™ðŸ½",
+ "d": "person with folded hands tone 3",
+ "u": "8.0"
+ },
+ "pray_tone4": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¾",
+ "d": "person with folded hands tone 4",
+ "u": "8.0"
+ },
+ "pray_tone5": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¿",
+ "d": "person with folded hands tone 5",
+ "u": "8.0"
+ },
+ "prayer_beads": {
+ "c": "objects",
+ "e": "📿",
+ "d": "prayer beads",
+ "u": "8.0"
+ },
+ "pregnant_woman": {
+ "c": "people",
+ "e": "🤰",
+ "d": "pregnant woman",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone1": {
+ "c": "people",
+ "e": "🤰ðŸ»",
+ "d": "pregnant woman tone 1",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone2": {
+ "c": "people",
+ "e": "🤰ðŸ¼",
+ "d": "pregnant woman tone 2",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone3": {
+ "c": "people",
+ "e": "🤰ðŸ½",
+ "d": "pregnant woman tone 3",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone4": {
+ "c": "people",
+ "e": "🤰ðŸ¾",
+ "d": "pregnant woman tone 4",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone5": {
+ "c": "people",
+ "e": "🤰ðŸ¿",
+ "d": "pregnant woman tone 5",
+ "u": "9.0"
+ },
+ "prince": {
+ "c": "people",
+ "e": "🤴",
+ "d": "prince",
+ "u": "9.0"
+ },
+ "prince_tone1": {
+ "c": "people",
+ "e": "🤴ðŸ»",
+ "d": "prince tone 1",
+ "u": "9.0"
+ },
+ "prince_tone2": {
+ "c": "people",
+ "e": "🤴ðŸ¼",
+ "d": "prince tone 2",
+ "u": "9.0"
+ },
+ "prince_tone3": {
+ "c": "people",
+ "e": "🤴ðŸ½",
+ "d": "prince tone 3",
+ "u": "9.0"
+ },
+ "prince_tone4": {
+ "c": "people",
+ "e": "🤴ðŸ¾",
+ "d": "prince tone 4",
+ "u": "9.0"
+ },
+ "prince_tone5": {
+ "c": "people",
+ "e": "🤴ðŸ¿",
+ "d": "prince tone 5",
+ "u": "9.0"
+ },
+ "princess": {
+ "c": "people",
+ "e": "👸",
+ "d": "princess",
+ "u": "6.0"
+ },
+ "princess_tone1": {
+ "c": "people",
+ "e": "👸ðŸ»",
+ "d": "princess tone 1",
+ "u": "8.0"
+ },
+ "princess_tone2": {
+ "c": "people",
+ "e": "👸ðŸ¼",
+ "d": "princess tone 2",
+ "u": "8.0"
+ },
+ "princess_tone3": {
+ "c": "people",
+ "e": "👸ðŸ½",
+ "d": "princess tone 3",
+ "u": "8.0"
+ },
+ "princess_tone4": {
+ "c": "people",
+ "e": "👸ðŸ¾",
+ "d": "princess tone 4",
+ "u": "8.0"
+ },
+ "princess_tone5": {
+ "c": "people",
+ "e": "👸ðŸ¿",
+ "d": "princess tone 5",
+ "u": "8.0"
+ },
+ "printer": {
+ "c": "objects",
+ "e": "🖨",
+ "d": "printer",
+ "u": "7.0"
+ },
+ "projector": {
+ "c": "objects",
+ "e": "📽",
+ "d": "film projector",
+ "u": "7.0"
+ },
+ "punch": {
+ "c": "people",
+ "e": "👊",
+ "d": "fisted hand sign",
+ "u": "6.0"
+ },
+ "punch_tone1": {
+ "c": "people",
+ "e": "👊ðŸ»",
+ "d": "fisted hand sign tone 1",
+ "u": "8.0"
+ },
+ "punch_tone2": {
+ "c": "people",
+ "e": "👊ðŸ¼",
+ "d": "fisted hand sign tone 2",
+ "u": "8.0"
+ },
+ "punch_tone3": {
+ "c": "people",
+ "e": "👊ðŸ½",
+ "d": "fisted hand sign tone 3",
+ "u": "8.0"
+ },
+ "punch_tone4": {
+ "c": "people",
+ "e": "👊ðŸ¾",
+ "d": "fisted hand sign tone 4",
+ "u": "8.0"
+ },
+ "punch_tone5": {
+ "c": "people",
+ "e": "👊ðŸ¿",
+ "d": "fisted hand sign tone 5",
+ "u": "8.0"
+ },
+ "purple_heart": {
+ "c": "symbols",
+ "e": "💜",
+ "d": "purple heart",
+ "u": "6.0"
+ },
+ "purse": {
+ "c": "people",
+ "e": "👛",
+ "d": "purse",
+ "u": "6.0"
+ },
+ "pushpin": {
+ "c": "objects",
+ "e": "📌",
+ "d": "pushpin",
+ "u": "6.0"
+ },
+ "put_litter_in_its_place": {
+ "c": "symbols",
+ "e": "🚮",
+ "d": "put litter in its place symbol",
+ "u": "6.0"
+ },
+ "question": {
+ "c": "symbols",
+ "e": "â“",
+ "d": "black question mark ornament",
+ "u": "6.0"
+ },
+ "rabbit": {
+ "c": "nature",
+ "e": "ðŸ°",
+ "d": "rabbit face",
+ "u": "6.0"
+ },
+ "rabbit2": {
+ "c": "nature",
+ "e": "ðŸ‡",
+ "d": "rabbit",
+ "u": "6.0"
+ },
+ "race_car": {
+ "c": "travel",
+ "e": "ðŸŽ",
+ "d": "racing car",
+ "u": "7.0"
+ },
+ "racehorse": {
+ "c": "nature",
+ "e": "ðŸŽ",
+ "d": "horse",
+ "u": "6.0"
+ },
+ "radio": {
+ "c": "objects",
+ "e": "📻",
+ "d": "radio",
+ "u": "6.0"
+ },
+ "radio_button": {
+ "c": "symbols",
+ "e": "🔘",
+ "d": "radio button",
+ "u": "6.0"
+ },
+ "radioactive": {
+ "c": "symbols",
+ "e": "☢",
+ "d": "radioactive sign",
+ "u": "1.1"
+ },
+ "rage": {
+ "c": "people",
+ "e": "😡",
+ "d": "pouting face",
+ "u": "6.0"
+ },
+ "railway_car": {
+ "c": "travel",
+ "e": "🚃",
+ "d": "railway car",
+ "u": "6.0"
+ },
+ "railway_track": {
+ "c": "travel",
+ "e": "🛤",
+ "d": "railway track",
+ "u": "7.0"
+ },
+ "rainbow": {
+ "c": "travel",
+ "e": "🌈",
+ "d": "rainbow",
+ "u": "6.0"
+ },
+ "raised_back_of_hand": {
+ "c": "people",
+ "e": "🤚",
+ "d": "raised back of hand",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone1": {
+ "c": "people",
+ "e": "🤚ðŸ»",
+ "d": "raised back of hand tone 1",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone2": {
+ "c": "people",
+ "e": "🤚ðŸ¼",
+ "d": "raised back of hand tone 2",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone3": {
+ "c": "people",
+ "e": "🤚ðŸ½",
+ "d": "raised back of hand tone 3",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone4": {
+ "c": "people",
+ "e": "🤚ðŸ¾",
+ "d": "raised back of hand tone 4",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone5": {
+ "c": "people",
+ "e": "🤚ðŸ¿",
+ "d": "raised back of hand tone 5",
+ "u": "9.0"
+ },
+ "raised_hand": {
+ "c": "people",
+ "e": "✋",
+ "d": "raised hand",
+ "u": "6.0"
+ },
+ "raised_hand_tone1": {
+ "c": "people",
+ "e": "✋ðŸ»",
+ "d": "raised hand tone 1",
+ "u": "8.0"
+ },
+ "raised_hand_tone2": {
+ "c": "people",
+ "e": "✋ðŸ¼",
+ "d": "raised hand tone 2",
+ "u": "8.0"
+ },
+ "raised_hand_tone3": {
+ "c": "people",
+ "e": "✋ðŸ½",
+ "d": "raised hand tone 3",
+ "u": "8.0"
+ },
+ "raised_hand_tone4": {
+ "c": "people",
+ "e": "✋ðŸ¾",
+ "d": "raised hand tone 4",
+ "u": "8.0"
+ },
+ "raised_hand_tone5": {
+ "c": "people",
+ "e": "✋ðŸ¿",
+ "d": "raised hand tone 5",
+ "u": "8.0"
+ },
+ "raised_hands": {
+ "c": "people",
+ "e": "🙌",
+ "d": "person raising both hands in celebration",
+ "u": "6.0"
+ },
+ "raised_hands_tone1": {
+ "c": "people",
+ "e": "🙌ðŸ»",
+ "d": "person raising both hands in celebration tone 1",
+ "u": "8.0"
+ },
+ "raised_hands_tone2": {
+ "c": "people",
+ "e": "🙌ðŸ¼",
+ "d": "person raising both hands in celebration tone 2",
+ "u": "8.0"
+ },
+ "raised_hands_tone3": {
+ "c": "people",
+ "e": "🙌ðŸ½",
+ "d": "person raising both hands in celebration tone 3",
+ "u": "8.0"
+ },
+ "raised_hands_tone4": {
+ "c": "people",
+ "e": "🙌ðŸ¾",
+ "d": "person raising both hands in celebration tone 4",
+ "u": "8.0"
+ },
+ "raised_hands_tone5": {
+ "c": "people",
+ "e": "🙌ðŸ¿",
+ "d": "person raising both hands in celebration tone 5",
+ "u": "8.0"
+ },
+ "raising_hand": {
+ "c": "people",
+ "e": "🙋",
+ "d": "happy person raising one hand",
+ "u": "6.0"
+ },
+ "raising_hand_tone1": {
+ "c": "people",
+ "e": "🙋ðŸ»",
+ "d": "happy person raising one hand tone1",
+ "u": "8.0"
+ },
+ "raising_hand_tone2": {
+ "c": "people",
+ "e": "🙋ðŸ¼",
+ "d": "happy person raising one hand tone2",
+ "u": "8.0"
+ },
+ "raising_hand_tone3": {
+ "c": "people",
+ "e": "🙋ðŸ½",
+ "d": "happy person raising one hand tone3",
+ "u": "8.0"
+ },
+ "raising_hand_tone4": {
+ "c": "people",
+ "e": "🙋ðŸ¾",
+ "d": "happy person raising one hand tone4",
+ "u": "8.0"
+ },
+ "raising_hand_tone5": {
+ "c": "people",
+ "e": "🙋ðŸ¿",
+ "d": "happy person raising one hand tone5",
+ "u": "8.0"
+ },
+ "ram": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "ram",
+ "u": "6.0"
+ },
+ "ramen": {
+ "c": "food",
+ "e": "ðŸœ",
+ "d": "steaming bowl",
+ "u": "6.0"
+ },
+ "rat": {
+ "c": "nature",
+ "e": "ðŸ€",
+ "d": "rat",
+ "u": "6.0"
+ },
+ "record_button": {
+ "c": "symbols",
+ "e": "âº",
+ "d": "black circle for record",
+ "u": "7.0"
+ },
+ "recycle": {
+ "c": "symbols",
+ "e": "â™»",
+ "d": "black universal recycling symbol",
+ "u": "3.2"
+ },
+ "red_car": {
+ "c": "travel",
+ "e": "🚗",
+ "d": "automobile",
+ "u": "6.0"
+ },
+ "red_circle": {
+ "c": "symbols",
+ "e": "🔴",
+ "d": "large red circle",
+ "u": "6.0"
+ },
+ "registered": {
+ "c": "symbols",
+ "e": "®",
+ "d": "registered sign",
+ "u": "1.1"
+ },
+ "relaxed": {
+ "c": "people",
+ "e": "☺",
+ "d": "white smiling face",
+ "u": "1.1"
+ },
+ "relieved": {
+ "c": "people",
+ "e": "😌",
+ "d": "relieved face",
+ "u": "6.0"
+ },
+ "reminder_ribbon": {
+ "c": "activity",
+ "e": "🎗",
+ "d": "reminder ribbon",
+ "u": "7.0"
+ },
+ "repeat": {
+ "c": "symbols",
+ "e": "ðŸ”",
+ "d": "clockwise rightwards and leftwards open circle arr",
+ "u": "6.0"
+ },
+ "repeat_one": {
+ "c": "symbols",
+ "e": "🔂",
+ "d": "clockwise rightwards and leftwards open circle arr",
+ "u": "6.0"
+ },
+ "restroom": {
+ "c": "symbols",
+ "e": "🚻",
+ "d": "restroom",
+ "u": "6.0"
+ },
+ "revolving_hearts": {
+ "c": "symbols",
+ "e": "💞",
+ "d": "revolving hearts",
+ "u": "6.0"
+ },
+ "rewind": {
+ "c": "symbols",
+ "e": "âª",
+ "d": "black left-pointing double triangle",
+ "u": "6.0"
+ },
+ "rhino": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "rhinoceros",
+ "u": "9.0"
+ },
+ "ribbon": {
+ "c": "objects",
+ "e": "🎀",
+ "d": "ribbon",
+ "u": "6.0"
+ },
+ "rice": {
+ "c": "food",
+ "e": "ðŸš",
+ "d": "cooked rice",
+ "u": "6.0"
+ },
+ "rice_ball": {
+ "c": "food",
+ "e": "ðŸ™",
+ "d": "rice ball",
+ "u": "6.0"
+ },
+ "rice_cracker": {
+ "c": "food",
+ "e": "ðŸ˜",
+ "d": "rice cracker",
+ "u": "6.0"
+ },
+ "rice_scene": {
+ "c": "travel",
+ "e": "🎑",
+ "d": "moon viewing ceremony",
+ "u": "6.0"
+ },
+ "right_facing_fist": {
+ "c": "people",
+ "e": "🤜",
+ "d": "right-facing fist",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone1": {
+ "c": "people",
+ "e": "🤜ðŸ»",
+ "d": "right facing fist tone 1",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone2": {
+ "c": "people",
+ "e": "🤜ðŸ¼",
+ "d": "right facing fist tone 2",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone3": {
+ "c": "people",
+ "e": "🤜ðŸ½",
+ "d": "right facing fist tone 3",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone4": {
+ "c": "people",
+ "e": "🤜ðŸ¾",
+ "d": "right facing fist tone 4",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone5": {
+ "c": "people",
+ "e": "🤜ðŸ¿",
+ "d": "right facing fist tone 5",
+ "u": "9.0"
+ },
+ "ring": {
+ "c": "people",
+ "e": "ðŸ’",
+ "d": "ring",
+ "u": "6.0"
+ },
+ "robot": {
+ "c": "people",
+ "e": "🤖",
+ "d": "robot face",
+ "u": "8.0"
+ },
+ "rocket": {
+ "c": "travel",
+ "e": "🚀",
+ "d": "rocket",
+ "u": "6.0"
+ },
+ "rofl": {
+ "c": "people",
+ "e": "🤣",
+ "d": "rolling on the floor laughing",
+ "u": "9.0"
+ },
+ "roller_coaster": {
+ "c": "travel",
+ "e": "🎢",
+ "d": "roller coaster",
+ "u": "6.0"
+ },
+ "rolling_eyes": {
+ "c": "people",
+ "e": "🙄",
+ "d": "face with rolling eyes",
+ "u": "8.0"
+ },
+ "rooster": {
+ "c": "nature",
+ "e": "ðŸ“",
+ "d": "rooster",
+ "u": "6.0"
+ },
+ "rose": {
+ "c": "nature",
+ "e": "🌹",
+ "d": "rose",
+ "u": "6.0"
+ },
+ "rosette": {
+ "c": "activity",
+ "e": "ðŸµ",
+ "d": "rosette",
+ "u": "7.0"
+ },
+ "rotating_light": {
+ "c": "travel",
+ "e": "🚨",
+ "d": "police cars revolving light",
+ "u": "6.0"
+ },
+ "round_pushpin": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "round pushpin",
+ "u": "6.0"
+ },
+ "rowboat": {
+ "c": "activity",
+ "e": "🚣",
+ "d": "rowboat",
+ "u": "6.0"
+ },
+ "rowboat_tone1": {
+ "c": "activity",
+ "e": "🚣ðŸ»",
+ "d": "rowboat tone 1",
+ "u": "8.0"
+ },
+ "rowboat_tone2": {
+ "c": "activity",
+ "e": "🚣ðŸ¼",
+ "d": "rowboat tone 2",
+ "u": "8.0"
+ },
+ "rowboat_tone3": {
+ "c": "activity",
+ "e": "🚣ðŸ½",
+ "d": "rowboat tone 3",
+ "u": "8.0"
+ },
+ "rowboat_tone4": {
+ "c": "activity",
+ "e": "🚣ðŸ¾",
+ "d": "rowboat tone 4",
+ "u": "8.0"
+ },
+ "rowboat_tone5": {
+ "c": "activity",
+ "e": "🚣ðŸ¿",
+ "d": "rowboat tone 5",
+ "u": "8.0"
+ },
+ "rugby_football": {
+ "c": "activity",
+ "e": "ðŸ‰",
+ "d": "rugby football",
+ "u": "6.0"
+ },
+ "runner": {
+ "c": "people",
+ "e": "ðŸƒ",
+ "d": "runner",
+ "u": "6.0"
+ },
+ "runner_tone1": {
+ "c": "people",
+ "e": "ðŸƒðŸ»",
+ "d": "runner tone 1",
+ "u": "8.0"
+ },
+ "runner_tone2": {
+ "c": "people",
+ "e": "ðŸƒðŸ¼",
+ "d": "runner tone 2",
+ "u": "8.0"
+ },
+ "runner_tone3": {
+ "c": "people",
+ "e": "ðŸƒðŸ½",
+ "d": "runner tone 3",
+ "u": "8.0"
+ },
+ "runner_tone4": {
+ "c": "people",
+ "e": "ðŸƒðŸ¾",
+ "d": "runner tone 4",
+ "u": "8.0"
+ },
+ "runner_tone5": {
+ "c": "people",
+ "e": "ðŸƒðŸ¿",
+ "d": "runner tone 5",
+ "u": "8.0"
+ },
+ "running_shirt_with_sash": {
+ "c": "activity",
+ "e": "🎽",
+ "d": "running shirt with sash",
+ "u": "6.0"
+ },
+ "sa": {
+ "c": "symbols",
+ "e": "🈂",
+ "d": "squared katakana sa",
+ "u": "6.0"
+ },
+ "sagittarius": {
+ "c": "symbols",
+ "e": "â™",
+ "d": "sagittarius",
+ "u": "1.1"
+ },
+ "sailboat": {
+ "c": "travel",
+ "e": "⛵",
+ "d": "sailboat",
+ "u": "5.2"
+ },
+ "sake": {
+ "c": "food",
+ "e": "ðŸ¶",
+ "d": "sake bottle and cup",
+ "u": "6.0"
+ },
+ "salad": {
+ "c": "food",
+ "e": "🥗",
+ "d": "green salad",
+ "u": "9.0"
+ },
+ "sandal": {
+ "c": "people",
+ "e": "👡",
+ "d": "womans sandal",
+ "u": "6.0"
+ },
+ "santa": {
+ "c": "people",
+ "e": "🎅",
+ "d": "father christmas",
+ "u": "6.0"
+ },
+ "santa_tone1": {
+ "c": "people",
+ "e": "🎅ðŸ»",
+ "d": "father christmas tone 1",
+ "u": "8.0"
+ },
+ "santa_tone2": {
+ "c": "people",
+ "e": "🎅ðŸ¼",
+ "d": "father christmas tone 2",
+ "u": "8.0"
+ },
+ "santa_tone3": {
+ "c": "people",
+ "e": "🎅ðŸ½",
+ "d": "father christmas tone 3",
+ "u": "8.0"
+ },
+ "santa_tone4": {
+ "c": "people",
+ "e": "🎅ðŸ¾",
+ "d": "father christmas tone 4",
+ "u": "8.0"
+ },
+ "santa_tone5": {
+ "c": "people",
+ "e": "🎅ðŸ¿",
+ "d": "father christmas tone 5",
+ "u": "8.0"
+ },
+ "satellite": {
+ "c": "objects",
+ "e": "📡",
+ "d": "satellite antenna",
+ "u": "6.0"
+ },
+ "satellite_orbital": {
+ "c": "travel",
+ "e": "🛰",
+ "d": "satellite",
+ "u": "7.0"
+ },
+ "saxophone": {
+ "c": "activity",
+ "e": "🎷",
+ "d": "saxophone",
+ "u": "6.0"
+ },
+ "scales": {
+ "c": "objects",
+ "e": "âš–",
+ "d": "scales",
+ "u": "4.1"
+ },
+ "school": {
+ "c": "travel",
+ "e": "ðŸ«",
+ "d": "school",
+ "u": "6.0"
+ },
+ "school_satchel": {
+ "c": "people",
+ "e": "🎒",
+ "d": "school satchel",
+ "u": "6.0"
+ },
+ "scissors": {
+ "c": "objects",
+ "e": "✂",
+ "d": "black scissors",
+ "u": "1.1"
+ },
+ "scooter": {
+ "c": "travel",
+ "e": "🛴",
+ "d": "scooter",
+ "u": "9.0"
+ },
+ "scorpion": {
+ "c": "nature",
+ "e": "🦂",
+ "d": "scorpion",
+ "u": "8.0"
+ },
+ "scorpius": {
+ "c": "symbols",
+ "e": "â™",
+ "d": "scorpius",
+ "u": "1.1"
+ },
+ "scream": {
+ "c": "people",
+ "e": "😱",
+ "d": "face screaming in fear",
+ "u": "6.0"
+ },
+ "scream_cat": {
+ "c": "people",
+ "e": "🙀",
+ "d": "weary cat face",
+ "u": "6.0"
+ },
+ "scroll": {
+ "c": "objects",
+ "e": "📜",
+ "d": "scroll",
+ "u": "6.0"
+ },
+ "seat": {
+ "c": "travel",
+ "e": "💺",
+ "d": "seat",
+ "u": "6.0"
+ },
+ "second_place": {
+ "c": "activity",
+ "e": "🥈",
+ "d": "second place medal",
+ "u": "9.0"
+ },
+ "secret": {
+ "c": "symbols",
+ "e": "㊙",
+ "d": "circled ideograph secret",
+ "u": "1.1"
+ },
+ "see_no_evil": {
+ "c": "nature",
+ "e": "🙈",
+ "d": "see-no-evil monkey",
+ "u": "6.0"
+ },
+ "seedling": {
+ "c": "nature",
+ "e": "🌱",
+ "d": "seedling",
+ "u": "6.0"
+ },
+ "selfie": {
+ "c": "people",
+ "e": "🤳",
+ "d": "selfie",
+ "u": "9.0"
+ },
+ "selfie_tone1": {
+ "c": "people",
+ "e": "🤳ðŸ»",
+ "d": "selfie tone 1",
+ "u": "9.0"
+ },
+ "selfie_tone2": {
+ "c": "people",
+ "e": "🤳ðŸ¼",
+ "d": "selfie tone 2",
+ "u": "9.0"
+ },
+ "selfie_tone3": {
+ "c": "people",
+ "e": "🤳ðŸ½",
+ "d": "selfie tone 3",
+ "u": "9.0"
+ },
+ "selfie_tone4": {
+ "c": "people",
+ "e": "🤳ðŸ¾",
+ "d": "selfie tone 4",
+ "u": "9.0"
+ },
+ "selfie_tone5": {
+ "c": "people",
+ "e": "🤳ðŸ¿",
+ "d": "selfie tone 5",
+ "u": "9.0"
+ },
+ "seven": {
+ "c": "symbols",
+ "e": "7ï¸âƒ£",
+ "d": "keycap digit seven",
+ "u": "3.0"
+ },
+ "shallow_pan_of_food": {
+ "c": "food",
+ "e": "🥘",
+ "d": "shallow pan of food",
+ "u": "9.0"
+ },
+ "shamrock": {
+ "c": "nature",
+ "e": "☘",
+ "d": "shamrock",
+ "u": "4.1"
+ },
+ "shark": {
+ "c": "nature",
+ "e": "🦈",
+ "d": "shark",
+ "u": "9.0"
+ },
+ "shaved_ice": {
+ "c": "food",
+ "e": "ðŸ§",
+ "d": "shaved ice",
+ "u": "6.0"
+ },
+ "sheep": {
+ "c": "nature",
+ "e": "ðŸ‘",
+ "d": "sheep",
+ "u": "6.0"
+ },
+ "shell": {
+ "c": "nature",
+ "e": "ðŸš",
+ "d": "spiral shell",
+ "u": "6.0"
+ },
+ "shield": {
+ "c": "objects",
+ "e": "🛡",
+ "d": "shield",
+ "u": "7.0"
+ },
+ "shinto_shrine": {
+ "c": "travel",
+ "e": "⛩",
+ "d": "shinto shrine",
+ "u": "5.2"
+ },
+ "ship": {
+ "c": "travel",
+ "e": "🚢",
+ "d": "ship",
+ "u": "6.0"
+ },
+ "shirt": {
+ "c": "people",
+ "e": "👕",
+ "d": "t-shirt",
+ "u": "6.0"
+ },
+ "shopping_bags": {
+ "c": "objects",
+ "e": "ðŸ›",
+ "d": "shopping bags",
+ "u": "7.0"
+ },
+ "shopping_cart": {
+ "c": "objects",
+ "e": "🛒",
+ "d": "shopping trolley",
+ "u": "9.0"
+ },
+ "shower": {
+ "c": "objects",
+ "e": "🚿",
+ "d": "shower",
+ "u": "6.0"
+ },
+ "shrimp": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "shrimp",
+ "u": "9.0"
+ },
+ "shrug": {
+ "c": "people",
+ "e": "🤷",
+ "d": "shrug",
+ "u": "9.0"
+ },
+ "shrug_tone1": {
+ "c": "people",
+ "e": "🤷ðŸ»",
+ "d": "shrug tone 1",
+ "u": "9.0"
+ },
+ "shrug_tone2": {
+ "c": "people",
+ "e": "🤷ðŸ¼",
+ "d": "shrug tone 2",
+ "u": "9.0"
+ },
+ "shrug_tone3": {
+ "c": "people",
+ "e": "🤷ðŸ½",
+ "d": "shrug tone 3",
+ "u": "9.0"
+ },
+ "shrug_tone4": {
+ "c": "people",
+ "e": "🤷ðŸ¾",
+ "d": "shrug tone 4",
+ "u": "9.0"
+ },
+ "shrug_tone5": {
+ "c": "people",
+ "e": "🤷ðŸ¿",
+ "d": "shrug tone 5",
+ "u": "9.0"
+ },
+ "signal_strength": {
+ "c": "symbols",
+ "e": "📶",
+ "d": "antenna with bars",
+ "u": "6.0"
+ },
+ "six": {
+ "c": "symbols",
+ "e": "6ï¸âƒ£",
+ "d": "keycap digit six",
+ "u": "3.0"
+ },
+ "six_pointed_star": {
+ "c": "symbols",
+ "e": "🔯",
+ "d": "six pointed star with middle dot",
+ "u": "6.0"
+ },
+ "ski": {
+ "c": "activity",
+ "e": "🎿",
+ "d": "ski and ski boot",
+ "u": "6.0"
+ },
+ "skier": {
+ "c": "activity",
+ "e": "â›·",
+ "d": "skier",
+ "u": "5.2"
+ },
+ "skull": {
+ "c": "people",
+ "e": "💀",
+ "d": "skull",
+ "u": "6.0"
+ },
+ "skull_crossbones": {
+ "c": "objects",
+ "e": "☠",
+ "d": "skull and crossbones",
+ "u": "1.1"
+ },
+ "sleeping": {
+ "c": "people",
+ "e": "😴",
+ "d": "sleeping face",
+ "u": "6.1"
+ },
+ "sleeping_accommodation": {
+ "c": "objects",
+ "e": "🛌",
+ "d": "sleeping accommodation",
+ "u": "7.0"
+ },
+ "sleepy": {
+ "c": "people",
+ "e": "😪",
+ "d": "sleepy face",
+ "u": "6.0"
+ },
+ "slight_frown": {
+ "c": "people",
+ "e": "ðŸ™",
+ "d": "slightly frowning face",
+ "u": "7.0"
+ },
+ "slight_smile": {
+ "c": "people",
+ "e": "🙂",
+ "d": "slightly smiling face",
+ "u": "7.0"
+ },
+ "slot_machine": {
+ "c": "activity",
+ "e": "🎰",
+ "d": "slot machine",
+ "u": "6.0"
+ },
+ "small_blue_diamond": {
+ "c": "symbols",
+ "e": "🔹",
+ "d": "small blue diamond",
+ "u": "6.0"
+ },
+ "small_orange_diamond": {
+ "c": "symbols",
+ "e": "🔸",
+ "d": "small orange diamond",
+ "u": "6.0"
+ },
+ "small_red_triangle": {
+ "c": "symbols",
+ "e": "🔺",
+ "d": "up-pointing red triangle",
+ "u": "6.0"
+ },
+ "small_red_triangle_down": {
+ "c": "symbols",
+ "e": "🔻",
+ "d": "down-pointing red triangle",
+ "u": "6.0"
+ },
+ "smile": {
+ "c": "people",
+ "e": "😄",
+ "d": "smiling face with open mouth and smiling eyes",
+ "u": "6.0"
+ },
+ "smile_cat": {
+ "c": "people",
+ "e": "😸",
+ "d": "grinning cat face with smiling eyes",
+ "u": "6.0"
+ },
+ "smiley": {
+ "c": "people",
+ "e": "😃",
+ "d": "smiling face with open mouth",
+ "u": "6.0"
+ },
+ "smiley_cat": {
+ "c": "people",
+ "e": "😺",
+ "d": "smiling cat face with open mouth",
+ "u": "6.0"
+ },
+ "smiling_imp": {
+ "c": "people",
+ "e": "😈",
+ "d": "smiling face with horns",
+ "u": "6.0"
+ },
+ "smirk": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "smirking face",
+ "u": "6.0"
+ },
+ "smirk_cat": {
+ "c": "people",
+ "e": "😼",
+ "d": "cat face with wry smile",
+ "u": "6.0"
+ },
+ "smoking": {
+ "c": "objects",
+ "e": "🚬",
+ "d": "smoking symbol",
+ "u": "6.0"
+ },
+ "snail": {
+ "c": "nature",
+ "e": "ðŸŒ",
+ "d": "snail",
+ "u": "6.0"
+ },
+ "snake": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "snake",
+ "u": "6.0"
+ },
+ "sneezing_face": {
+ "c": "people",
+ "e": "🤧",
+ "d": "sneezing face",
+ "u": "9.0"
+ },
+ "snowboarder": {
+ "c": "activity",
+ "e": "ðŸ‚",
+ "d": "snowboarder",
+ "u": "6.0"
+ },
+ "snowflake": {
+ "c": "nature",
+ "e": "â„",
+ "d": "snowflake",
+ "u": "1.1"
+ },
+ "snowman": {
+ "c": "nature",
+ "e": "⛄",
+ "d": "snowman without snow",
+ "u": "5.2"
+ },
+ "snowman2": {
+ "c": "nature",
+ "e": "☃",
+ "d": "snowman",
+ "u": "1.1"
+ },
+ "sob": {
+ "c": "people",
+ "e": "😭",
+ "d": "loudly crying face",
+ "u": "6.0"
+ },
+ "soccer": {
+ "c": "activity",
+ "e": "âš½",
+ "d": "soccer ball",
+ "u": "5.2"
+ },
+ "soon": {
+ "c": "symbols",
+ "e": "🔜",
+ "d": "soon with rightwards arrow above",
+ "u": "6.0"
+ },
+ "sos": {
+ "c": "symbols",
+ "e": "🆘",
+ "d": "squared sos",
+ "u": "6.0"
+ },
+ "sound": {
+ "c": "symbols",
+ "e": "🔉",
+ "d": "speaker with one sound wave",
+ "u": "6.0"
+ },
+ "space_invader": {
+ "c": "activity",
+ "e": "👾",
+ "d": "alien monster",
+ "u": "6.0"
+ },
+ "spades": {
+ "c": "symbols",
+ "e": "â™ ",
+ "d": "black spade suit",
+ "u": "1.1"
+ },
+ "spaghetti": {
+ "c": "food",
+ "e": "ðŸ",
+ "d": "spaghetti",
+ "u": "6.0"
+ },
+ "sparkle": {
+ "c": "symbols",
+ "e": "â‡",
+ "d": "sparkle",
+ "u": "1.1"
+ },
+ "sparkler": {
+ "c": "travel",
+ "e": "🎇",
+ "d": "firework sparkler",
+ "u": "6.0"
+ },
+ "sparkles": {
+ "c": "nature",
+ "e": "✨",
+ "d": "sparkles",
+ "u": "6.0"
+ },
+ "sparkling_heart": {
+ "c": "symbols",
+ "e": "💖",
+ "d": "sparkling heart",
+ "u": "6.0"
+ },
+ "speak_no_evil": {
+ "c": "nature",
+ "e": "🙊",
+ "d": "speak-no-evil monkey",
+ "u": "6.0"
+ },
+ "speaker": {
+ "c": "symbols",
+ "e": "🔈",
+ "d": "speaker",
+ "u": "6.0"
+ },
+ "speaking_head": {
+ "c": "people",
+ "e": "🗣",
+ "d": "speaking head in silhouette",
+ "u": "7.0"
+ },
+ "speech_balloon": {
+ "c": "symbols",
+ "e": "💬",
+ "d": "speech balloon",
+ "u": "6.0"
+ },
+ "speech_left": {
+ "c": "symbols",
+ "e": "🗨",
+ "d": "left speech bubble",
+ "u": "7.0"
+ },
+ "speedboat": {
+ "c": "travel",
+ "e": "🚤",
+ "d": "speedboat",
+ "u": "6.0"
+ },
+ "spider": {
+ "c": "nature",
+ "e": "🕷",
+ "d": "spider",
+ "u": "7.0"
+ },
+ "spider_web": {
+ "c": "nature",
+ "e": "🕸",
+ "d": "spider web",
+ "u": "7.0"
+ },
+ "spoon": {
+ "c": "food",
+ "e": "🥄",
+ "d": "spoon",
+ "u": "9.0"
+ },
+ "spy": {
+ "c": "people",
+ "e": "🕵",
+ "d": "sleuth or spy",
+ "u": "7.0"
+ },
+ "spy_tone1": {
+ "c": "people",
+ "e": "🕵ðŸ»",
+ "d": "sleuth or spy tone 1",
+ "u": "8.0"
+ },
+ "spy_tone2": {
+ "c": "people",
+ "e": "🕵ðŸ¼",
+ "d": "sleuth or spy tone 2",
+ "u": "8.0"
+ },
+ "spy_tone3": {
+ "c": "people",
+ "e": "🕵ðŸ½",
+ "d": "sleuth or spy tone 3",
+ "u": "8.0"
+ },
+ "spy_tone4": {
+ "c": "people",
+ "e": "🕵ðŸ¾",
+ "d": "sleuth or spy tone 4",
+ "u": "8.0"
+ },
+ "spy_tone5": {
+ "c": "people",
+ "e": "🕵ðŸ¿",
+ "d": "sleuth or spy tone 5",
+ "u": "8.0"
+ },
+ "squid": {
+ "c": "nature",
+ "e": "🦑",
+ "d": "squid",
+ "u": "9.0"
+ },
+ "stadium": {
+ "c": "travel",
+ "e": "ðŸŸ",
+ "d": "stadium",
+ "u": "7.0"
+ },
+ "star": {
+ "c": "nature",
+ "e": "â­",
+ "d": "white medium star",
+ "u": "5.1"
+ },
+ "star2": {
+ "c": "nature",
+ "e": "🌟",
+ "d": "glowing star",
+ "u": "6.0"
+ },
+ "star_and_crescent": {
+ "c": "symbols",
+ "e": "☪",
+ "d": "star and crescent",
+ "u": "1.1"
+ },
+ "star_of_david": {
+ "c": "symbols",
+ "e": "✡",
+ "d": "star of david",
+ "u": "1.1"
+ },
+ "stars": {
+ "c": "travel",
+ "e": "🌠",
+ "d": "shooting star",
+ "u": "6.0"
+ },
+ "station": {
+ "c": "travel",
+ "e": "🚉",
+ "d": "station",
+ "u": "6.0"
+ },
+ "statue_of_liberty": {
+ "c": "travel",
+ "e": "🗽",
+ "d": "statue of liberty",
+ "u": "6.0"
+ },
+ "steam_locomotive": {
+ "c": "travel",
+ "e": "🚂",
+ "d": "steam locomotive",
+ "u": "6.0"
+ },
+ "stew": {
+ "c": "food",
+ "e": "ðŸ²",
+ "d": "pot of food",
+ "u": "6.0"
+ },
+ "stop_button": {
+ "c": "symbols",
+ "e": "â¹",
+ "d": "black square for stop",
+ "u": "7.0"
+ },
+ "stopwatch": {
+ "c": "objects",
+ "e": "â±",
+ "d": "stopwatch",
+ "u": "6.0"
+ },
+ "straight_ruler": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "straight ruler",
+ "u": "6.0"
+ },
+ "strawberry": {
+ "c": "food",
+ "e": "ðŸ“",
+ "d": "strawberry",
+ "u": "6.0"
+ },
+ "stuck_out_tongue": {
+ "c": "people",
+ "e": "😛",
+ "d": "face with stuck-out tongue",
+ "u": "6.1"
+ },
+ "stuck_out_tongue_closed_eyes": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "face with stuck-out tongue and tightly-closed eyes",
+ "u": "6.0"
+ },
+ "stuck_out_tongue_winking_eye": {
+ "c": "people",
+ "e": "😜",
+ "d": "face with stuck-out tongue and winking eye",
+ "u": "6.0"
+ },
+ "stuffed_flatbread": {
+ "c": "food",
+ "e": "🥙",
+ "d": "stuffed flatbread",
+ "u": "9.0"
+ },
+ "sun_with_face": {
+ "c": "nature",
+ "e": "🌞",
+ "d": "sun with face",
+ "u": "6.0"
+ },
+ "sunflower": {
+ "c": "nature",
+ "e": "🌻",
+ "d": "sunflower",
+ "u": "6.0"
+ },
+ "sunglasses": {
+ "c": "people",
+ "e": "😎",
+ "d": "smiling face with sunglasses",
+ "u": "6.0"
+ },
+ "sunny": {
+ "c": "nature",
+ "e": "☀",
+ "d": "black sun with rays",
+ "u": "1.1"
+ },
+ "sunrise": {
+ "c": "travel",
+ "e": "🌅",
+ "d": "sunrise",
+ "u": "6.0"
+ },
+ "sunrise_over_mountains": {
+ "c": "travel",
+ "e": "🌄",
+ "d": "sunrise over mountains",
+ "u": "6.0"
+ },
+ "surfer": {
+ "c": "activity",
+ "e": "ðŸ„",
+ "d": "surfer",
+ "u": "6.0"
+ },
+ "surfer_tone1": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ»",
+ "d": "surfer tone 1",
+ "u": "8.0"
+ },
+ "surfer_tone2": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ¼",
+ "d": "surfer tone 2",
+ "u": "8.0"
+ },
+ "surfer_tone3": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ½",
+ "d": "surfer tone 3",
+ "u": "8.0"
+ },
+ "surfer_tone4": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ¾",
+ "d": "surfer tone 4",
+ "u": "8.0"
+ },
+ "surfer_tone5": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ¿",
+ "d": "surfer tone 5",
+ "u": "8.0"
+ },
+ "sushi": {
+ "c": "food",
+ "e": "ðŸ£",
+ "d": "sushi",
+ "u": "6.0"
+ },
+ "suspension_railway": {
+ "c": "travel",
+ "e": "🚟",
+ "d": "suspension railway",
+ "u": "6.0"
+ },
+ "sweat": {
+ "c": "people",
+ "e": "😓",
+ "d": "face with cold sweat",
+ "u": "6.0"
+ },
+ "sweat_drops": {
+ "c": "nature",
+ "e": "💦",
+ "d": "splashing sweat symbol",
+ "u": "6.0"
+ },
+ "sweat_smile": {
+ "c": "people",
+ "e": "😅",
+ "d": "smiling face with open mouth and cold sweat",
+ "u": "6.0"
+ },
+ "sweet_potato": {
+ "c": "food",
+ "e": "ðŸ ",
+ "d": "roasted sweet potato",
+ "u": "6.0"
+ },
+ "swimmer": {
+ "c": "activity",
+ "e": "ðŸŠ",
+ "d": "swimmer",
+ "u": "6.0"
+ },
+ "swimmer_tone1": {
+ "c": "activity",
+ "e": "ðŸŠðŸ»",
+ "d": "swimmer tone 1",
+ "u": "8.0"
+ },
+ "swimmer_tone2": {
+ "c": "activity",
+ "e": "ðŸŠðŸ¼",
+ "d": "swimmer tone 2",
+ "u": "8.0"
+ },
+ "swimmer_tone3": {
+ "c": "activity",
+ "e": "ðŸŠðŸ½",
+ "d": "swimmer tone 3",
+ "u": "8.0"
+ },
+ "swimmer_tone4": {
+ "c": "activity",
+ "e": "ðŸŠðŸ¾",
+ "d": "swimmer tone 4",
+ "u": "8.0"
+ },
+ "swimmer_tone5": {
+ "c": "activity",
+ "e": "ðŸŠðŸ¿",
+ "d": "swimmer tone 5",
+ "u": "8.0"
+ },
+ "symbols": {
+ "c": "symbols",
+ "e": "🔣",
+ "d": "input symbol for symbols",
+ "u": "6.0"
+ },
+ "synagogue": {
+ "c": "travel",
+ "e": "ðŸ•",
+ "d": "synagogue",
+ "u": "8.0"
+ },
+ "syringe": {
+ "c": "objects",
+ "e": "💉",
+ "d": "syringe",
+ "u": "6.0"
+ },
+ "taco": {
+ "c": "food",
+ "e": "🌮",
+ "d": "taco",
+ "u": "8.0"
+ },
+ "tada": {
+ "c": "objects",
+ "e": "🎉",
+ "d": "party popper",
+ "u": "6.0"
+ },
+ "tanabata_tree": {
+ "c": "nature",
+ "e": "🎋",
+ "d": "tanabata tree",
+ "u": "6.0"
+ },
+ "tangerine": {
+ "c": "food",
+ "e": "ðŸŠ",
+ "d": "tangerine",
+ "u": "6.0"
+ },
+ "taurus": {
+ "c": "symbols",
+ "e": "♉",
+ "d": "taurus",
+ "u": "1.1"
+ },
+ "taxi": {
+ "c": "travel",
+ "e": "🚕",
+ "d": "taxi",
+ "u": "6.0"
+ },
+ "tea": {
+ "c": "food",
+ "e": "ðŸµ",
+ "d": "teacup without handle",
+ "u": "6.0"
+ },
+ "telephone": {
+ "c": "objects",
+ "e": "☎",
+ "d": "black telephone",
+ "u": "1.1"
+ },
+ "telephone_receiver": {
+ "c": "objects",
+ "e": "📞",
+ "d": "telephone receiver",
+ "u": "6.0"
+ },
+ "telescope": {
+ "c": "objects",
+ "e": "🔭",
+ "d": "telescope",
+ "u": "6.0"
+ },
+ "ten": {
+ "c": "symbols",
+ "e": "🔟",
+ "d": "keycap ten",
+ "u": "6.0"
+ },
+ "tennis": {
+ "c": "activity",
+ "e": "🎾",
+ "d": "tennis racquet and ball",
+ "u": "6.0"
+ },
+ "tent": {
+ "c": "travel",
+ "e": "⛺",
+ "d": "tent",
+ "u": "5.2"
+ },
+ "thermometer": {
+ "c": "objects",
+ "e": "🌡",
+ "d": "thermometer",
+ "u": "7.0"
+ },
+ "thermometer_face": {
+ "c": "people",
+ "e": "🤒",
+ "d": "face with thermometer",
+ "u": "8.0"
+ },
+ "thinking": {
+ "c": "people",
+ "e": "🤔",
+ "d": "thinking face",
+ "u": "8.0"
+ },
+ "third_place": {
+ "c": "activity",
+ "e": "🥉",
+ "d": "third place medal",
+ "u": "9.0"
+ },
+ "thought_balloon": {
+ "c": "symbols",
+ "e": "💭",
+ "d": "thought balloon",
+ "u": "6.0"
+ },
+ "three": {
+ "c": "symbols",
+ "e": "3ï¸âƒ£",
+ "d": "keycap digit three",
+ "u": "3.0"
+ },
+ "thumbsdown": {
+ "c": "people",
+ "e": "👎",
+ "d": "thumbs down sign",
+ "u": "6.0"
+ },
+ "thumbsdown_tone1": {
+ "c": "people",
+ "e": "👎ðŸ»",
+ "d": "thumbs down sign tone 1",
+ "u": "8.0"
+ },
+ "thumbsdown_tone2": {
+ "c": "people",
+ "e": "👎ðŸ¼",
+ "d": "thumbs down sign tone 2",
+ "u": "8.0"
+ },
+ "thumbsdown_tone3": {
+ "c": "people",
+ "e": "👎ðŸ½",
+ "d": "thumbs down sign tone 3",
+ "u": "8.0"
+ },
+ "thumbsdown_tone4": {
+ "c": "people",
+ "e": "👎ðŸ¾",
+ "d": "thumbs down sign tone 4",
+ "u": "8.0"
+ },
+ "thumbsdown_tone5": {
+ "c": "people",
+ "e": "👎ðŸ¿",
+ "d": "thumbs down sign tone 5",
+ "u": "8.0"
+ },
+ "thumbsup": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "thumbs up sign",
+ "u": "6.0"
+ },
+ "thumbsup_tone1": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ»",
+ "d": "thumbs up sign tone 1",
+ "u": "8.0"
+ },
+ "thumbsup_tone2": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¼",
+ "d": "thumbs up sign tone 2",
+ "u": "8.0"
+ },
+ "thumbsup_tone3": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ½",
+ "d": "thumbs up sign tone 3",
+ "u": "8.0"
+ },
+ "thumbsup_tone4": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¾",
+ "d": "thumbs up sign tone 4",
+ "u": "8.0"
+ },
+ "thumbsup_tone5": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¿",
+ "d": "thumbs up sign tone 5",
+ "u": "8.0"
+ },
+ "thunder_cloud_rain": {
+ "c": "nature",
+ "e": "⛈",
+ "d": "thunder cloud and rain",
+ "u": "5.2"
+ },
+ "ticket": {
+ "c": "activity",
+ "e": "🎫",
+ "d": "ticket",
+ "u": "6.0"
+ },
+ "tickets": {
+ "c": "activity",
+ "e": "🎟",
+ "d": "admission tickets",
+ "u": "7.0"
+ },
+ "tiger": {
+ "c": "nature",
+ "e": "ðŸ¯",
+ "d": "tiger face",
+ "u": "6.0"
+ },
+ "tiger2": {
+ "c": "nature",
+ "e": "ðŸ…",
+ "d": "tiger",
+ "u": "6.0"
+ },
+ "timer": {
+ "c": "objects",
+ "e": "â²",
+ "d": "timer clock",
+ "u": "6.0"
+ },
+ "tired_face": {
+ "c": "people",
+ "e": "😫",
+ "d": "tired face",
+ "u": "6.0"
+ },
+ "tm": {
+ "c": "symbols",
+ "e": "â„¢",
+ "d": "trade mark sign",
+ "u": "1.1"
+ },
+ "toilet": {
+ "c": "objects",
+ "e": "🚽",
+ "d": "toilet",
+ "u": "6.0"
+ },
+ "tokyo_tower": {
+ "c": "travel",
+ "e": "🗼",
+ "d": "tokyo tower",
+ "u": "6.0"
+ },
+ "tomato": {
+ "c": "food",
+ "e": "ðŸ…",
+ "d": "tomato",
+ "u": "6.0"
+ },
+ "tone1": {
+ "c": "modifier",
+ "e": "ðŸ»",
+ "d": "emoji modifier Fitzpatrick type-1-2",
+ "u": "8.0"
+ },
+ "tone2": {
+ "c": "modifier",
+ "e": "ðŸ¼",
+ "d": "emoji modifier Fitzpatrick type-3",
+ "u": "8.0"
+ },
+ "tone3": {
+ "c": "modifier",
+ "e": "ðŸ½",
+ "d": "emoji modifier Fitzpatrick type-4",
+ "u": "8.0"
+ },
+ "tone4": {
+ "c": "modifier",
+ "e": "ðŸ¾",
+ "d": "emoji modifier Fitzpatrick type-5",
+ "u": "8.0"
+ },
+ "tone5": {
+ "c": "modifier",
+ "e": "ðŸ¿",
+ "d": "emoji modifier Fitzpatrick type-6",
+ "u": "8.0"
+ },
+ "tongue": {
+ "c": "people",
+ "e": "👅",
+ "d": "tongue",
+ "u": "6.0"
+ },
+ "tools": {
+ "c": "objects",
+ "e": "🛠",
+ "d": "hammer and wrench",
+ "u": "7.0"
+ },
+ "top": {
+ "c": "symbols",
+ "e": "ðŸ”",
+ "d": "top with upwards arrow above",
+ "u": "6.0"
+ },
+ "tophat": {
+ "c": "people",
+ "e": "🎩",
+ "d": "top hat",
+ "u": "6.0"
+ },
+ "track_next": {
+ "c": "symbols",
+ "e": "â­",
+ "d": "black right-pointing double triangle with vertical bar",
+ "u": "6.0"
+ },
+ "track_previous": {
+ "c": "symbols",
+ "e": "â®",
+ "d": "black left-pointing double triangle with vertical bar",
+ "u": "6.0"
+ },
+ "trackball": {
+ "c": "objects",
+ "e": "🖲",
+ "d": "trackball",
+ "u": "7.0"
+ },
+ "tractor": {
+ "c": "travel",
+ "e": "🚜",
+ "d": "tractor",
+ "u": "6.0"
+ },
+ "traffic_light": {
+ "c": "travel",
+ "e": "🚥",
+ "d": "horizontal traffic light",
+ "u": "6.0"
+ },
+ "train": {
+ "c": "travel",
+ "e": "🚋",
+ "d": "Tram Car",
+ "u": "6.0"
+ },
+ "train2": {
+ "c": "travel",
+ "e": "🚆",
+ "d": "train",
+ "u": "6.0"
+ },
+ "tram": {
+ "c": "travel",
+ "e": "🚊",
+ "d": "tram",
+ "u": "6.0"
+ },
+ "triangular_flag_on_post": {
+ "c": "objects",
+ "e": "🚩",
+ "d": "triangular flag on post",
+ "u": "6.0"
+ },
+ "triangular_ruler": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "triangular ruler",
+ "u": "6.0"
+ },
+ "trident": {
+ "c": "symbols",
+ "e": "🔱",
+ "d": "trident emblem",
+ "u": "6.0"
+ },
+ "triumph": {
+ "c": "people",
+ "e": "😤",
+ "d": "face with look of triumph",
+ "u": "6.0"
+ },
+ "trolleybus": {
+ "c": "travel",
+ "e": "🚎",
+ "d": "trolleybus",
+ "u": "6.0"
+ },
+ "trophy": {
+ "c": "activity",
+ "e": "ðŸ†",
+ "d": "trophy",
+ "u": "6.0"
+ },
+ "tropical_drink": {
+ "c": "food",
+ "e": "ðŸ¹",
+ "d": "tropical drink",
+ "u": "6.0"
+ },
+ "tropical_fish": {
+ "c": "nature",
+ "e": "ðŸ ",
+ "d": "tropical fish",
+ "u": "6.0"
+ },
+ "truck": {
+ "c": "travel",
+ "e": "🚚",
+ "d": "delivery truck",
+ "u": "6.0"
+ },
+ "trumpet": {
+ "c": "activity",
+ "e": "🎺",
+ "d": "trumpet",
+ "u": "6.0"
+ },
+ "tulip": {
+ "c": "nature",
+ "e": "🌷",
+ "d": "tulip",
+ "u": "6.0"
+ },
+ "tumbler_glass": {
+ "c": "food",
+ "e": "🥃",
+ "d": "tumbler glass",
+ "u": "9.0"
+ },
+ "turkey": {
+ "c": "nature",
+ "e": "🦃",
+ "d": "turkey",
+ "u": "8.0"
+ },
+ "turtle": {
+ "c": "nature",
+ "e": "ðŸ¢",
+ "d": "turtle",
+ "u": "6.0"
+ },
+ "tv": {
+ "c": "objects",
+ "e": "📺",
+ "d": "television",
+ "u": "6.0"
+ },
+ "twisted_rightwards_arrows": {
+ "c": "symbols",
+ "e": "🔀",
+ "d": "twisted rightwards arrows",
+ "u": "6.0"
+ },
+ "two": {
+ "c": "symbols",
+ "e": "2ï¸âƒ£",
+ "d": "keycap digit two",
+ "u": "3.0"
+ },
+ "two_hearts": {
+ "c": "symbols",
+ "e": "💕",
+ "d": "two hearts",
+ "u": "6.0"
+ },
+ "two_men_holding_hands": {
+ "c": "people",
+ "e": "👬",
+ "d": "two men holding hands",
+ "u": "6.0"
+ },
+ "two_women_holding_hands": {
+ "c": "people",
+ "e": "👭",
+ "d": "two women holding hands",
+ "u": "6.0"
+ },
+ "u5272": {
+ "c": "symbols",
+ "e": "🈹",
+ "d": "squared cjk unified ideograph-5272",
+ "u": "6.0"
+ },
+ "u5408": {
+ "c": "symbols",
+ "e": "🈴",
+ "d": "squared cjk unified ideograph-5408",
+ "u": "6.0"
+ },
+ "u55b6": {
+ "c": "symbols",
+ "e": "🈺",
+ "d": "squared cjk unified ideograph-55b6",
+ "u": "6.0"
+ },
+ "u6307": {
+ "c": "symbols",
+ "e": "🈯",
+ "d": "squared cjk unified ideograph-6307",
+ "u": "5.2"
+ },
+ "u6708": {
+ "c": "symbols",
+ "e": "🈷",
+ "d": "squared cjk unified ideograph-6708",
+ "u": "6.0"
+ },
+ "u6709": {
+ "c": "symbols",
+ "e": "🈶",
+ "d": "squared cjk unified ideograph-6709",
+ "u": "6.0"
+ },
+ "u6e80": {
+ "c": "symbols",
+ "e": "🈵",
+ "d": "squared cjk unified ideograph-6e80",
+ "u": "6.0"
+ },
+ "u7121": {
+ "c": "symbols",
+ "e": "🈚",
+ "d": "squared cjk unified ideograph-7121",
+ "u": "5.2"
+ },
+ "u7533": {
+ "c": "symbols",
+ "e": "🈸",
+ "d": "squared cjk unified ideograph-7533",
+ "u": "6.0"
+ },
+ "u7981": {
+ "c": "symbols",
+ "e": "🈲",
+ "d": "squared cjk unified ideograph-7981",
+ "u": "6.0"
+ },
+ "u7a7a": {
+ "c": "symbols",
+ "e": "🈳",
+ "d": "squared cjk unified ideograph-7a7a",
+ "u": "6.0"
+ },
+ "umbrella": {
+ "c": "nature",
+ "e": "☔",
+ "d": "umbrella with rain drops",
+ "u": "4.0"
+ },
+ "umbrella2": {
+ "c": "nature",
+ "e": "☂",
+ "d": "umbrella",
+ "u": "1.1"
+ },
+ "unamused": {
+ "c": "people",
+ "e": "😒",
+ "d": "unamused face",
+ "u": "6.0"
+ },
+ "underage": {
+ "c": "symbols",
+ "e": "🔞",
+ "d": "no one under eighteen symbol",
+ "u": "6.0"
+ },
+ "unicorn": {
+ "c": "nature",
+ "e": "🦄",
+ "d": "unicorn face",
+ "u": "8.0"
+ },
+ "unlock": {
+ "c": "objects",
+ "e": "🔓",
+ "d": "open lock",
+ "u": "6.0"
+ },
+ "up": {
+ "c": "symbols",
+ "e": "🆙",
+ "d": "squared up with exclamation mark",
+ "u": "6.0"
+ },
+ "upside_down": {
+ "c": "people",
+ "e": "🙃",
+ "d": "upside-down face",
+ "u": "8.0"
+ },
+ "urn": {
+ "c": "objects",
+ "e": "âš±",
+ "d": "funeral urn",
+ "u": "4.1"
+ },
+ "v": {
+ "c": "people",
+ "e": "✌",
+ "d": "victory hand",
+ "u": "1.1"
+ },
+ "v_tone1": {
+ "c": "people",
+ "e": "✌ðŸ»",
+ "d": "victory hand tone 1",
+ "u": "8.0"
+ },
+ "v_tone2": {
+ "c": "people",
+ "e": "✌ðŸ¼",
+ "d": "victory hand tone 2",
+ "u": "8.0"
+ },
+ "v_tone3": {
+ "c": "people",
+ "e": "✌ðŸ½",
+ "d": "victory hand tone 3",
+ "u": "8.0"
+ },
+ "v_tone4": {
+ "c": "people",
+ "e": "✌ðŸ¾",
+ "d": "victory hand tone 4",
+ "u": "8.0"
+ },
+ "v_tone5": {
+ "c": "people",
+ "e": "✌ðŸ¿",
+ "d": "victory hand tone 5",
+ "u": "8.0"
+ },
+ "vertical_traffic_light": {
+ "c": "travel",
+ "e": "🚦",
+ "d": "vertical traffic light",
+ "u": "6.0"
+ },
+ "vhs": {
+ "c": "objects",
+ "e": "📼",
+ "d": "videocassette",
+ "u": "6.0"
+ },
+ "vibration_mode": {
+ "c": "symbols",
+ "e": "📳",
+ "d": "vibration mode",
+ "u": "6.0"
+ },
+ "video_camera": {
+ "c": "objects",
+ "e": "📹",
+ "d": "video camera",
+ "u": "6.0"
+ },
+ "video_game": {
+ "c": "activity",
+ "e": "🎮",
+ "d": "video game",
+ "u": "6.0"
+ },
+ "violin": {
+ "c": "activity",
+ "e": "🎻",
+ "d": "violin",
+ "u": "6.0"
+ },
+ "virgo": {
+ "c": "symbols",
+ "e": "â™",
+ "d": "virgo",
+ "u": "1.1"
+ },
+ "volcano": {
+ "c": "travel",
+ "e": "🌋",
+ "d": "volcano",
+ "u": "6.0"
+ },
+ "volleyball": {
+ "c": "activity",
+ "e": "ðŸ",
+ "d": "volleyball",
+ "u": "8.0"
+ },
+ "vs": {
+ "c": "symbols",
+ "e": "🆚",
+ "d": "squared vs",
+ "u": "6.0"
+ },
+ "vulcan": {
+ "c": "people",
+ "e": "🖖",
+ "d": "raised hand with part between middle and ring fingers",
+ "u": "7.0"
+ },
+ "vulcan_tone1": {
+ "c": "people",
+ "e": "🖖ðŸ»",
+ "d": "raised hand with part between middle and ring fingers tone 1",
+ "u": "8.0"
+ },
+ "vulcan_tone2": {
+ "c": "people",
+ "e": "🖖ðŸ¼",
+ "d": "raised hand with part between middle and ring fingers tone 2",
+ "u": "8.0"
+ },
+ "vulcan_tone3": {
+ "c": "people",
+ "e": "🖖ðŸ½",
+ "d": "raised hand with part between middle and ring fingers tone 3",
+ "u": "8.0"
+ },
+ "vulcan_tone4": {
+ "c": "people",
+ "e": "🖖ðŸ¾",
+ "d": "raised hand with part between middle and ring fingers tone 4",
+ "u": "8.0"
+ },
+ "vulcan_tone5": {
+ "c": "people",
+ "e": "🖖ðŸ¿",
+ "d": "raised hand with part between middle and ring fingers tone 5",
+ "u": "8.0"
+ },
+ "walking": {
+ "c": "people",
+ "e": "🚶",
+ "d": "pedestrian",
+ "u": "6.0"
+ },
+ "walking_tone1": {
+ "c": "people",
+ "e": "🚶ðŸ»",
+ "d": "pedestrian tone 1",
+ "u": "8.0"
+ },
+ "walking_tone2": {
+ "c": "people",
+ "e": "🚶ðŸ¼",
+ "d": "pedestrian tone 2",
+ "u": "8.0"
+ },
+ "walking_tone3": {
+ "c": "people",
+ "e": "🚶ðŸ½",
+ "d": "pedestrian tone 3",
+ "u": "8.0"
+ },
+ "walking_tone4": {
+ "c": "people",
+ "e": "🚶ðŸ¾",
+ "d": "pedestrian tone 4",
+ "u": "8.0"
+ },
+ "walking_tone5": {
+ "c": "people",
+ "e": "🚶ðŸ¿",
+ "d": "pedestrian tone 5",
+ "u": "8.0"
+ },
+ "waning_crescent_moon": {
+ "c": "nature",
+ "e": "🌘",
+ "d": "waning crescent moon symbol",
+ "u": "6.0"
+ },
+ "waning_gibbous_moon": {
+ "c": "nature",
+ "e": "🌖",
+ "d": "waning gibbous moon symbol",
+ "u": "6.0"
+ },
+ "warning": {
+ "c": "symbols",
+ "e": "âš ",
+ "d": "warning sign",
+ "u": "4.0"
+ },
+ "wastebasket": {
+ "c": "objects",
+ "e": "🗑",
+ "d": "wastebasket",
+ "u": "7.0"
+ },
+ "watch": {
+ "c": "objects",
+ "e": "⌚",
+ "d": "watch",
+ "u": "1.1"
+ },
+ "water_buffalo": {
+ "c": "nature",
+ "e": "ðŸƒ",
+ "d": "water buffalo",
+ "u": "6.0"
+ },
+ "water_polo": {
+ "c": "activity",
+ "e": "🤽",
+ "d": "water polo",
+ "u": "9.0"
+ },
+ "water_polo_tone1": {
+ "c": "activity",
+ "e": "🤽ðŸ»",
+ "d": "water polo tone 1",
+ "u": "9.0"
+ },
+ "water_polo_tone2": {
+ "c": "activity",
+ "e": "🤽ðŸ¼",
+ "d": "water polo tone 2",
+ "u": "9.0"
+ },
+ "water_polo_tone3": {
+ "c": "activity",
+ "e": "🤽ðŸ½",
+ "d": "water polo tone 3",
+ "u": "9.0"
+ },
+ "water_polo_tone4": {
+ "c": "activity",
+ "e": "🤽ðŸ¾",
+ "d": "water polo tone 4",
+ "u": "9.0"
+ },
+ "water_polo_tone5": {
+ "c": "activity",
+ "e": "🤽ðŸ¿",
+ "d": "water polo tone 5",
+ "u": "9.0"
+ },
+ "watermelon": {
+ "c": "food",
+ "e": "ðŸ‰",
+ "d": "watermelon",
+ "u": "6.0"
+ },
+ "wave": {
+ "c": "people",
+ "e": "👋",
+ "d": "waving hand sign",
+ "u": "6.0"
+ },
+ "wave_tone1": {
+ "c": "people",
+ "e": "👋ðŸ»",
+ "d": "waving hand sign tone 1",
+ "u": "8.0"
+ },
+ "wave_tone2": {
+ "c": "people",
+ "e": "👋ðŸ¼",
+ "d": "waving hand sign tone 2",
+ "u": "8.0"
+ },
+ "wave_tone3": {
+ "c": "people",
+ "e": "👋ðŸ½",
+ "d": "waving hand sign tone 3",
+ "u": "8.0"
+ },
+ "wave_tone4": {
+ "c": "people",
+ "e": "👋ðŸ¾",
+ "d": "waving hand sign tone 4",
+ "u": "8.0"
+ },
+ "wave_tone5": {
+ "c": "people",
+ "e": "👋ðŸ¿",
+ "d": "waving hand sign tone 5",
+ "u": "8.0"
+ },
+ "wavy_dash": {
+ "c": "symbols",
+ "e": "〰",
+ "d": "wavy dash",
+ "u": "1.1"
+ },
+ "waxing_crescent_moon": {
+ "c": "nature",
+ "e": "🌒",
+ "d": "waxing crescent moon symbol",
+ "u": "6.0"
+ },
+ "waxing_gibbous_moon": {
+ "c": "nature",
+ "e": "🌔",
+ "d": "waxing gibbous moon symbol",
+ "u": "6.0"
+ },
+ "wc": {
+ "c": "symbols",
+ "e": "🚾",
+ "d": "water closet",
+ "u": "6.0"
+ },
+ "weary": {
+ "c": "people",
+ "e": "😩",
+ "d": "weary face",
+ "u": "6.0"
+ },
+ "wedding": {
+ "c": "travel",
+ "e": "💒",
+ "d": "wedding",
+ "u": "6.0"
+ },
+ "whale": {
+ "c": "nature",
+ "e": "ðŸ³",
+ "d": "spouting whale",
+ "u": "6.0"
+ },
+ "whale2": {
+ "c": "nature",
+ "e": "ðŸ‹",
+ "d": "whale",
+ "u": "6.0"
+ },
+ "wheel_of_dharma": {
+ "c": "symbols",
+ "e": "☸",
+ "d": "wheel of dharma",
+ "u": "1.1"
+ },
+ "wheelchair": {
+ "c": "symbols",
+ "e": "♿",
+ "d": "wheelchair symbol",
+ "u": "4.1"
+ },
+ "white_check_mark": {
+ "c": "symbols",
+ "e": "✅",
+ "d": "white heavy check mark",
+ "u": "6.0"
+ },
+ "white_circle": {
+ "c": "symbols",
+ "e": "⚪",
+ "d": "medium white circle",
+ "u": "4.1"
+ },
+ "white_flower": {
+ "c": "symbols",
+ "e": "💮",
+ "d": "white flower",
+ "u": "6.0"
+ },
+ "white_large_square": {
+ "c": "symbols",
+ "e": "⬜",
+ "d": "white large square",
+ "u": "5.1"
+ },
+ "white_medium_small_square": {
+ "c": "symbols",
+ "e": "â—½",
+ "d": "white medium small square",
+ "u": "3.2"
+ },
+ "white_medium_square": {
+ "c": "symbols",
+ "e": "â—»",
+ "d": "white medium square",
+ "u": "3.2"
+ },
+ "white_small_square": {
+ "c": "symbols",
+ "e": "â–«",
+ "d": "white small square",
+ "u": "1.1"
+ },
+ "white_square_button": {
+ "c": "symbols",
+ "e": "🔳",
+ "d": "white square button",
+ "u": "6.0"
+ },
+ "white_sun_cloud": {
+ "c": "nature",
+ "e": "🌥",
+ "d": "white sun behind cloud",
+ "u": "7.0"
+ },
+ "white_sun_rain_cloud": {
+ "c": "nature",
+ "e": "🌦",
+ "d": "white sun behind cloud with rain",
+ "u": "7.0"
+ },
+ "white_sun_small_cloud": {
+ "c": "nature",
+ "e": "🌤",
+ "d": "white sun with small cloud",
+ "u": "7.0"
+ },
+ "wilted_rose": {
+ "c": "nature",
+ "e": "🥀",
+ "d": "wilted flower",
+ "u": "9.0"
+ },
+ "wind_blowing_face": {
+ "c": "nature",
+ "e": "🌬",
+ "d": "wind blowing face",
+ "u": "7.0"
+ },
+ "wind_chime": {
+ "c": "objects",
+ "e": "ðŸŽ",
+ "d": "wind chime",
+ "u": "6.0"
+ },
+ "wine_glass": {
+ "c": "food",
+ "e": "ðŸ·",
+ "d": "wine glass",
+ "u": "6.0"
+ },
+ "wink": {
+ "c": "people",
+ "e": "😉",
+ "d": "winking face",
+ "u": "6.0"
+ },
+ "wolf": {
+ "c": "nature",
+ "e": "ðŸº",
+ "d": "wolf face",
+ "u": "6.0"
+ },
+ "woman": {
+ "c": "people",
+ "e": "👩",
+ "d": "woman",
+ "u": "6.0"
+ },
+ "woman_tone1": {
+ "c": "people",
+ "e": "👩ðŸ»",
+ "d": "woman tone 1",
+ "u": "8.0"
+ },
+ "woman_tone2": {
+ "c": "people",
+ "e": "👩ðŸ¼",
+ "d": "woman tone 2",
+ "u": "8.0"
+ },
+ "woman_tone3": {
+ "c": "people",
+ "e": "👩ðŸ½",
+ "d": "woman tone 3",
+ "u": "8.0"
+ },
+ "woman_tone4": {
+ "c": "people",
+ "e": "👩ðŸ¾",
+ "d": "woman tone 4",
+ "u": "8.0"
+ },
+ "woman_tone5": {
+ "c": "people",
+ "e": "👩ðŸ¿",
+ "d": "woman tone 5",
+ "u": "8.0"
+ },
+ "womans_clothes": {
+ "c": "people",
+ "e": "👚",
+ "d": "womans clothes",
+ "u": "6.0"
+ },
+ "womans_hat": {
+ "c": "people",
+ "e": "👒",
+ "d": "womans hat",
+ "u": "6.0"
+ },
+ "womens": {
+ "c": "symbols",
+ "e": "🚺",
+ "d": "womens symbol",
+ "u": "6.0"
+ },
+ "worried": {
+ "c": "people",
+ "e": "😟",
+ "d": "worried face",
+ "u": "6.1"
+ },
+ "wrench": {
+ "c": "objects",
+ "e": "🔧",
+ "d": "wrench",
+ "u": "6.0"
+ },
+ "wrestlers": {
+ "c": "activity",
+ "e": "🤼",
+ "d": "wrestlers",
+ "u": "9.0"
+ },
+ "wrestlers_tone1": {
+ "c": "activity",
+ "e": "🤼ðŸ»",
+ "d": "wrestlers tone 1",
+ "u": "9.0"
+ },
+ "wrestlers_tone2": {
+ "c": "activity",
+ "e": "🤼ðŸ¼",
+ "d": "wrestlers tone 2",
+ "u": "9.0"
+ },
+ "wrestlers_tone3": {
+ "c": "activity",
+ "e": "🤼ðŸ½",
+ "d": "wrestlers tone 3",
+ "u": "9.0"
+ },
+ "wrestlers_tone4": {
+ "c": "activity",
+ "e": "🤼ðŸ¾",
+ "d": "wrestlers tone 4",
+ "u": "9.0"
+ },
+ "wrestlers_tone5": {
+ "c": "activity",
+ "e": "🤼ðŸ¿",
+ "d": "wrestlers tone 5",
+ "u": "9.0"
+ },
+ "writing_hand": {
+ "c": "people",
+ "e": "âœ",
+ "d": "writing hand",
+ "u": "1.1"
+ },
+ "writing_hand_tone1": {
+ "c": "people",
+ "e": "âœðŸ»",
+ "d": "writing hand tone 1",
+ "u": "8.0"
+ },
+ "writing_hand_tone2": {
+ "c": "people",
+ "e": "âœðŸ¼",
+ "d": "writing hand tone 2",
+ "u": "8.0"
+ },
+ "writing_hand_tone3": {
+ "c": "people",
+ "e": "âœðŸ½",
+ "d": "writing hand tone 3",
+ "u": "8.0"
+ },
+ "writing_hand_tone4": {
+ "c": "people",
+ "e": "âœðŸ¾",
+ "d": "writing hand tone 4",
+ "u": "8.0"
+ },
+ "writing_hand_tone5": {
+ "c": "people",
+ "e": "âœðŸ¿",
+ "d": "writing hand tone 5",
+ "u": "8.0"
+ },
+ "x": {
+ "c": "symbols",
+ "e": "âŒ",
+ "d": "cross mark",
+ "u": "6.0"
+ },
+ "yellow_heart": {
+ "c": "symbols",
+ "e": "💛",
+ "d": "yellow heart",
+ "u": "6.0"
+ },
+ "yen": {
+ "c": "objects",
+ "e": "💴",
+ "d": "banknote with yen sign",
+ "u": "6.0"
+ },
+ "yin_yang": {
+ "c": "symbols",
+ "e": "☯",
+ "d": "yin yang",
+ "u": "1.1"
+ },
+ "yum": {
+ "c": "people",
+ "e": "😋",
+ "d": "face savouring delicious food",
+ "u": "6.0"
+ },
+ "zap": {
+ "c": "nature",
+ "e": "âš¡",
+ "d": "high voltage sign",
+ "u": "4.0"
+ },
+ "zero": {
+ "c": "symbols",
+ "e": "0ï¸âƒ£",
+ "d": "keycap digit zero",
+ "u": "3.0"
+ },
+ "zipper_mouth": {
+ "c": "people",
+ "e": "ðŸ¤",
+ "d": "zipper-mouth face",
+ "u": "8.0"
+ },
+ "zzz": {
+ "c": "people",
+ "e": "💤",
+ "d": "sleeping symbol",
+ "u": "6.0"
+ }
+} \ No newline at end of file
diff --git a/app/assets/images/emoji/end.png b/public/-/emojis/1/end.png
index ef3ccd5f367..ef3ccd5f367 100644
--- a/app/assets/images/emoji/end.png
+++ b/public/-/emojis/1/end.png
Binary files differ
diff --git a/app/assets/images/emoji/envelope.png b/public/-/emojis/1/envelope.png
index ec77ac375a4..ec77ac375a4 100644
--- a/app/assets/images/emoji/envelope.png
+++ b/public/-/emojis/1/envelope.png
Binary files differ
diff --git a/app/assets/images/emoji/envelope_with_arrow.png b/public/-/emojis/1/envelope_with_arrow.png
index 7448a6b7673..7448a6b7673 100644
--- a/app/assets/images/emoji/envelope_with_arrow.png
+++ b/public/-/emojis/1/envelope_with_arrow.png
Binary files differ
diff --git a/app/assets/images/emoji/euro.png b/public/-/emojis/1/euro.png
index a49020820e1..a49020820e1 100644
--- a/app/assets/images/emoji/euro.png
+++ b/public/-/emojis/1/euro.png
Binary files differ
diff --git a/app/assets/images/emoji/european_castle.png b/public/-/emojis/1/european_castle.png
index 888d11332ce..888d11332ce 100644
--- a/app/assets/images/emoji/european_castle.png
+++ b/public/-/emojis/1/european_castle.png
Binary files differ
diff --git a/app/assets/images/emoji/european_post_office.png b/public/-/emojis/1/european_post_office.png
index 3745aff8dd2..3745aff8dd2 100644
--- a/app/assets/images/emoji/european_post_office.png
+++ b/public/-/emojis/1/european_post_office.png
Binary files differ
diff --git a/app/assets/images/emoji/evergreen_tree.png b/public/-/emojis/1/evergreen_tree.png
index f679d8dd772..f679d8dd772 100644
--- a/app/assets/images/emoji/evergreen_tree.png
+++ b/public/-/emojis/1/evergreen_tree.png
Binary files differ
diff --git a/app/assets/images/emoji/exclamation.png b/public/-/emojis/1/exclamation.png
index 2c14406422f..2c14406422f 100644
--- a/app/assets/images/emoji/exclamation.png
+++ b/public/-/emojis/1/exclamation.png
Binary files differ
diff --git a/app/assets/images/emoji/expressionless.png b/public/-/emojis/1/expressionless.png
index 2954017f6c2..2954017f6c2 100644
--- a/app/assets/images/emoji/expressionless.png
+++ b/public/-/emojis/1/expressionless.png
Binary files differ
diff --git a/app/assets/images/emoji/eye.png b/public/-/emojis/1/eye.png
index 9d989cdd375..9d989cdd375 100644
--- a/app/assets/images/emoji/eye.png
+++ b/public/-/emojis/1/eye.png
Binary files differ
diff --git a/app/assets/images/emoji/eye_in_speech_bubble.png b/public/-/emojis/1/eye_in_speech_bubble.png
index 21bd22bbcce..21bd22bbcce 100644
--- a/app/assets/images/emoji/eye_in_speech_bubble.png
+++ b/public/-/emojis/1/eye_in_speech_bubble.png
Binary files differ
diff --git a/app/assets/images/emoji/eyeglasses.png b/public/-/emojis/1/eyeglasses.png
index 865d8274acf..865d8274acf 100644
--- a/app/assets/images/emoji/eyeglasses.png
+++ b/public/-/emojis/1/eyeglasses.png
Binary files differ
diff --git a/app/assets/images/emoji/eyes.png b/public/-/emojis/1/eyes.png
index 2102ada7e09..2102ada7e09 100644
--- a/app/assets/images/emoji/eyes.png
+++ b/public/-/emojis/1/eyes.png
Binary files differ
diff --git a/app/assets/images/emoji/face_palm.png b/public/-/emojis/1/face_palm.png
index defc796cf16..defc796cf16 100644
--- a/app/assets/images/emoji/face_palm.png
+++ b/public/-/emojis/1/face_palm.png
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone1.png b/public/-/emojis/1/face_palm_tone1.png
index 2f4b010bb40..2f4b010bb40 100644
--- a/app/assets/images/emoji/face_palm_tone1.png
+++ b/public/-/emojis/1/face_palm_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone2.png b/public/-/emojis/1/face_palm_tone2.png
index 97fb6831687..97fb6831687 100644
--- a/app/assets/images/emoji/face_palm_tone2.png
+++ b/public/-/emojis/1/face_palm_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone3.png b/public/-/emojis/1/face_palm_tone3.png
index b5b5c1e5306..b5b5c1e5306 100644
--- a/app/assets/images/emoji/face_palm_tone3.png
+++ b/public/-/emojis/1/face_palm_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone4.png b/public/-/emojis/1/face_palm_tone4.png
index 2840b113483..2840b113483 100644
--- a/app/assets/images/emoji/face_palm_tone4.png
+++ b/public/-/emojis/1/face_palm_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone5.png b/public/-/emojis/1/face_palm_tone5.png
index 6f070db98be..6f070db98be 100644
--- a/app/assets/images/emoji/face_palm_tone5.png
+++ b/public/-/emojis/1/face_palm_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/factory.png b/public/-/emojis/1/factory.png
index e1d2ddf4a27..e1d2ddf4a27 100644
--- a/app/assets/images/emoji/factory.png
+++ b/public/-/emojis/1/factory.png
Binary files differ
diff --git a/app/assets/images/emoji/fallen_leaf.png b/public/-/emojis/1/fallen_leaf.png
index 0d60e7bdf2d..0d60e7bdf2d 100644
--- a/app/assets/images/emoji/fallen_leaf.png
+++ b/public/-/emojis/1/fallen_leaf.png
Binary files differ
diff --git a/app/assets/images/emoji/family.png b/public/-/emojis/1/family.png
index 26421965791..26421965791 100644
--- a/app/assets/images/emoji/family.png
+++ b/public/-/emojis/1/family.png
Binary files differ
diff --git a/app/assets/images/emoji/family_mmb.png b/public/-/emojis/1/family_mmb.png
index 7a2e4e2c491..7a2e4e2c491 100644
--- a/app/assets/images/emoji/family_mmb.png
+++ b/public/-/emojis/1/family_mmb.png
Binary files differ
diff --git a/app/assets/images/emoji/family_mmbb.png b/public/-/emojis/1/family_mmbb.png
index 81e6c0fc0ee..81e6c0fc0ee 100644
--- a/app/assets/images/emoji/family_mmbb.png
+++ b/public/-/emojis/1/family_mmbb.png
Binary files differ
diff --git a/app/assets/images/emoji/family_mmg.png b/public/-/emojis/1/family_mmg.png
index 932a85e1fe5..932a85e1fe5 100644
--- a/app/assets/images/emoji/family_mmg.png
+++ b/public/-/emojis/1/family_mmg.png
Binary files differ
diff --git a/app/assets/images/emoji/family_mmgb.png b/public/-/emojis/1/family_mmgb.png
index 41e35166670..41e35166670 100644
--- a/app/assets/images/emoji/family_mmgb.png
+++ b/public/-/emojis/1/family_mmgb.png
Binary files differ
diff --git a/app/assets/images/emoji/family_mmgg.png b/public/-/emojis/1/family_mmgg.png
index 8e8ccfe6c7f..8e8ccfe6c7f 100644
--- a/app/assets/images/emoji/family_mmgg.png
+++ b/public/-/emojis/1/family_mmgg.png
Binary files differ
diff --git a/app/assets/images/emoji/family_mwbb.png b/public/-/emojis/1/family_mwbb.png
index b544fbe573f..b544fbe573f 100644
--- a/app/assets/images/emoji/family_mwbb.png
+++ b/public/-/emojis/1/family_mwbb.png
Binary files differ
diff --git a/app/assets/images/emoji/family_mwg.png b/public/-/emojis/1/family_mwg.png
index 71d2681c32a..71d2681c32a 100644
--- a/app/assets/images/emoji/family_mwg.png
+++ b/public/-/emojis/1/family_mwg.png
Binary files differ
diff --git a/app/assets/images/emoji/family_mwgb.png b/public/-/emojis/1/family_mwgb.png
index 40dbf1f7a18..40dbf1f7a18 100644
--- a/app/assets/images/emoji/family_mwgb.png
+++ b/public/-/emojis/1/family_mwgb.png
Binary files differ
diff --git a/app/assets/images/emoji/family_mwgg.png b/public/-/emojis/1/family_mwgg.png
index bfefa4879cb..bfefa4879cb 100644
--- a/app/assets/images/emoji/family_mwgg.png
+++ b/public/-/emojis/1/family_mwgg.png
Binary files differ
diff --git a/app/assets/images/emoji/family_wwb.png b/public/-/emojis/1/family_wwb.png
index 836feae7c78..836feae7c78 100644
--- a/app/assets/images/emoji/family_wwb.png
+++ b/public/-/emojis/1/family_wwb.png
Binary files differ
diff --git a/app/assets/images/emoji/family_wwbb.png b/public/-/emojis/1/family_wwbb.png
index 6c6ba45e7bb..6c6ba45e7bb 100644
--- a/app/assets/images/emoji/family_wwbb.png
+++ b/public/-/emojis/1/family_wwbb.png
Binary files differ
diff --git a/app/assets/images/emoji/family_wwg.png b/public/-/emojis/1/family_wwg.png
index 41225c6fa5a..41225c6fa5a 100644
--- a/app/assets/images/emoji/family_wwg.png
+++ b/public/-/emojis/1/family_wwg.png
Binary files differ
diff --git a/app/assets/images/emoji/family_wwgb.png b/public/-/emojis/1/family_wwgb.png
index 284d29ab5da..284d29ab5da 100644
--- a/app/assets/images/emoji/family_wwgb.png
+++ b/public/-/emojis/1/family_wwgb.png
Binary files differ
diff --git a/app/assets/images/emoji/family_wwgg.png b/public/-/emojis/1/family_wwgg.png
index d8d3f49b85f..d8d3f49b85f 100644
--- a/app/assets/images/emoji/family_wwgg.png
+++ b/public/-/emojis/1/family_wwgg.png
Binary files differ
diff --git a/app/assets/images/emoji/fast_forward.png b/public/-/emojis/1/fast_forward.png
index c406fedfdb1..c406fedfdb1 100644
--- a/app/assets/images/emoji/fast_forward.png
+++ b/public/-/emojis/1/fast_forward.png
Binary files differ
diff --git a/app/assets/images/emoji/fax.png b/public/-/emojis/1/fax.png
index 6f929e294c2..6f929e294c2 100644
--- a/app/assets/images/emoji/fax.png
+++ b/public/-/emojis/1/fax.png
Binary files differ
diff --git a/app/assets/images/emoji/fearful.png b/public/-/emojis/1/fearful.png
index eb8b347cef9..eb8b347cef9 100644
--- a/app/assets/images/emoji/fearful.png
+++ b/public/-/emojis/1/fearful.png
Binary files differ
diff --git a/app/assets/images/emoji/feet.png b/public/-/emojis/1/feet.png
index 5fe568cee93..5fe568cee93 100644
--- a/app/assets/images/emoji/feet.png
+++ b/public/-/emojis/1/feet.png
Binary files differ
diff --git a/app/assets/images/emoji/fencer.png b/public/-/emojis/1/fencer.png
index 5288c920eb9..5288c920eb9 100644
--- a/app/assets/images/emoji/fencer.png
+++ b/public/-/emojis/1/fencer.png
Binary files differ
diff --git a/app/assets/images/emoji/ferris_wheel.png b/public/-/emojis/1/ferris_wheel.png
index 55c8ff0475b..55c8ff0475b 100644
--- a/app/assets/images/emoji/ferris_wheel.png
+++ b/public/-/emojis/1/ferris_wheel.png
Binary files differ
diff --git a/app/assets/images/emoji/ferry.png b/public/-/emojis/1/ferry.png
index 41816b3ae34..41816b3ae34 100644
--- a/app/assets/images/emoji/ferry.png
+++ b/public/-/emojis/1/ferry.png
Binary files differ
diff --git a/app/assets/images/emoji/field_hockey.png b/public/-/emojis/1/field_hockey.png
index 839637716ee..839637716ee 100644
--- a/app/assets/images/emoji/field_hockey.png
+++ b/public/-/emojis/1/field_hockey.png
Binary files differ
diff --git a/app/assets/images/emoji/file_cabinet.png b/public/-/emojis/1/file_cabinet.png
index fddc65dde96..fddc65dde96 100644
--- a/app/assets/images/emoji/file_cabinet.png
+++ b/public/-/emojis/1/file_cabinet.png
Binary files differ
diff --git a/app/assets/images/emoji/file_folder.png b/public/-/emojis/1/file_folder.png
index addedaf0870..addedaf0870 100644
--- a/app/assets/images/emoji/file_folder.png
+++ b/public/-/emojis/1/file_folder.png
Binary files differ
diff --git a/app/assets/images/emoji/film_frames.png b/public/-/emojis/1/film_frames.png
index 30143aedbe6..30143aedbe6 100644
--- a/app/assets/images/emoji/film_frames.png
+++ b/public/-/emojis/1/film_frames.png
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed.png b/public/-/emojis/1/fingers_crossed.png
index 4cd18514ea3..4cd18514ea3 100644
--- a/app/assets/images/emoji/fingers_crossed.png
+++ b/public/-/emojis/1/fingers_crossed.png
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone1.png b/public/-/emojis/1/fingers_crossed_tone1.png
index dd2384a6cd5..dd2384a6cd5 100644
--- a/app/assets/images/emoji/fingers_crossed_tone1.png
+++ b/public/-/emojis/1/fingers_crossed_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone2.png b/public/-/emojis/1/fingers_crossed_tone2.png
index 6228401befe..6228401befe 100644
--- a/app/assets/images/emoji/fingers_crossed_tone2.png
+++ b/public/-/emojis/1/fingers_crossed_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone3.png b/public/-/emojis/1/fingers_crossed_tone3.png
index b1074da15f5..b1074da15f5 100644
--- a/app/assets/images/emoji/fingers_crossed_tone3.png
+++ b/public/-/emojis/1/fingers_crossed_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone4.png b/public/-/emojis/1/fingers_crossed_tone4.png
index 75e05e4d332..75e05e4d332 100644
--- a/app/assets/images/emoji/fingers_crossed_tone4.png
+++ b/public/-/emojis/1/fingers_crossed_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone5.png b/public/-/emojis/1/fingers_crossed_tone5.png
index 761aebdc30f..761aebdc30f 100644
--- a/app/assets/images/emoji/fingers_crossed_tone5.png
+++ b/public/-/emojis/1/fingers_crossed_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/fire.png b/public/-/emojis/1/fire.png
index bd3775a460b..bd3775a460b 100644
--- a/app/assets/images/emoji/fire.png
+++ b/public/-/emojis/1/fire.png
Binary files differ
diff --git a/app/assets/images/emoji/fire_engine.png b/public/-/emojis/1/fire_engine.png
index 2cd45b7cf7e..2cd45b7cf7e 100644
--- a/app/assets/images/emoji/fire_engine.png
+++ b/public/-/emojis/1/fire_engine.png
Binary files differ
diff --git a/app/assets/images/emoji/fireworks.png b/public/-/emojis/1/fireworks.png
index 176c8b58265..176c8b58265 100644
--- a/app/assets/images/emoji/fireworks.png
+++ b/public/-/emojis/1/fireworks.png
Binary files differ
diff --git a/app/assets/images/emoji/first_place.png b/public/-/emojis/1/first_place.png
index 15612b66492..15612b66492 100644
--- a/app/assets/images/emoji/first_place.png
+++ b/public/-/emojis/1/first_place.png
Binary files differ
diff --git a/app/assets/images/emoji/first_quarter_moon.png b/public/-/emojis/1/first_quarter_moon.png
index 5dccaf72a4f..5dccaf72a4f 100644
--- a/app/assets/images/emoji/first_quarter_moon.png
+++ b/public/-/emojis/1/first_quarter_moon.png
Binary files differ
diff --git a/app/assets/images/emoji/first_quarter_moon_with_face.png b/public/-/emojis/1/first_quarter_moon_with_face.png
index cd8a3d7acd8..cd8a3d7acd8 100644
--- a/app/assets/images/emoji/first_quarter_moon_with_face.png
+++ b/public/-/emojis/1/first_quarter_moon_with_face.png
Binary files differ
diff --git a/app/assets/images/emoji/fish.png b/public/-/emojis/1/fish.png
index c2d2faaacd4..c2d2faaacd4 100644
--- a/app/assets/images/emoji/fish.png
+++ b/public/-/emojis/1/fish.png
Binary files differ
diff --git a/app/assets/images/emoji/fish_cake.png b/public/-/emojis/1/fish_cake.png
index 157bded65db..157bded65db 100644
--- a/app/assets/images/emoji/fish_cake.png
+++ b/public/-/emojis/1/fish_cake.png
Binary files differ
diff --git a/app/assets/images/emoji/fishing_pole_and_fish.png b/public/-/emojis/1/fishing_pole_and_fish.png
index dfcdf07eb50..dfcdf07eb50 100644
--- a/app/assets/images/emoji/fishing_pole_and_fish.png
+++ b/public/-/emojis/1/fishing_pole_and_fish.png
Binary files differ
diff --git a/app/assets/images/emoji/fist.png b/public/-/emojis/1/fist.png
index de33592bf98..de33592bf98 100644
--- a/app/assets/images/emoji/fist.png
+++ b/public/-/emojis/1/fist.png
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone1.png b/public/-/emojis/1/fist_tone1.png
index 02809e2dd68..02809e2dd68 100644
--- a/app/assets/images/emoji/fist_tone1.png
+++ b/public/-/emojis/1/fist_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone2.png b/public/-/emojis/1/fist_tone2.png
index 5de34810383..5de34810383 100644
--- a/app/assets/images/emoji/fist_tone2.png
+++ b/public/-/emojis/1/fist_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone3.png b/public/-/emojis/1/fist_tone3.png
index 0d5240129b1..0d5240129b1 100644
--- a/app/assets/images/emoji/fist_tone3.png
+++ b/public/-/emojis/1/fist_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone4.png b/public/-/emojis/1/fist_tone4.png
index a95c0dd634b..a95c0dd634b 100644
--- a/app/assets/images/emoji/fist_tone4.png
+++ b/public/-/emojis/1/fist_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone5.png b/public/-/emojis/1/fist_tone5.png
index a2f092fd8c7..a2f092fd8c7 100644
--- a/app/assets/images/emoji/fist_tone5.png
+++ b/public/-/emojis/1/fist_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/five.png b/public/-/emojis/1/five.png
index d14371f3f27..d14371f3f27 100644
--- a/app/assets/images/emoji/five.png
+++ b/public/-/emojis/1/five.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ac.png b/public/-/emojis/1/flag_ac.png
index 286239920c7..286239920c7 100644
--- a/app/assets/images/emoji/flag_ac.png
+++ b/public/-/emojis/1/flag_ac.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ad.png b/public/-/emojis/1/flag_ad.png
index 20f4b14e8ad..20f4b14e8ad 100644
--- a/app/assets/images/emoji/flag_ad.png
+++ b/public/-/emojis/1/flag_ad.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ae.png b/public/-/emojis/1/flag_ae.png
index d16ffe4b862..d16ffe4b862 100644
--- a/app/assets/images/emoji/flag_ae.png
+++ b/public/-/emojis/1/flag_ae.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_af.png b/public/-/emojis/1/flag_af.png
index a51533b554d..a51533b554d 100644
--- a/app/assets/images/emoji/flag_af.png
+++ b/public/-/emojis/1/flag_af.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ag.png b/public/-/emojis/1/flag_ag.png
index 07f2ce397d0..07f2ce397d0 100644
--- a/app/assets/images/emoji/flag_ag.png
+++ b/public/-/emojis/1/flag_ag.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ai.png b/public/-/emojis/1/flag_ai.png
index 500b5ab09fb..500b5ab09fb 100644
--- a/app/assets/images/emoji/flag_ai.png
+++ b/public/-/emojis/1/flag_ai.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_al.png b/public/-/emojis/1/flag_al.png
index 03a20132cc6..03a20132cc6 100644
--- a/app/assets/images/emoji/flag_al.png
+++ b/public/-/emojis/1/flag_al.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_am.png b/public/-/emojis/1/flag_am.png
index 2ad60a273ec..2ad60a273ec 100644
--- a/app/assets/images/emoji/flag_am.png
+++ b/public/-/emojis/1/flag_am.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ao.png b/public/-/emojis/1/flag_ao.png
index cb46c31f862..cb46c31f862 100644
--- a/app/assets/images/emoji/flag_ao.png
+++ b/public/-/emojis/1/flag_ao.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_aq.png b/public/-/emojis/1/flag_aq.png
index b272021d375..b272021d375 100644
--- a/app/assets/images/emoji/flag_aq.png
+++ b/public/-/emojis/1/flag_aq.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ar.png b/public/-/emojis/1/flag_ar.png
index 73136caf3b7..73136caf3b7 100644
--- a/app/assets/images/emoji/flag_ar.png
+++ b/public/-/emojis/1/flag_ar.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_as.png b/public/-/emojis/1/flag_as.png
index 3db45a0d9f3..3db45a0d9f3 100644
--- a/app/assets/images/emoji/flag_as.png
+++ b/public/-/emojis/1/flag_as.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_at.png b/public/-/emojis/1/flag_at.png
index c43769dcb19..c43769dcb19 100644
--- a/app/assets/images/emoji/flag_at.png
+++ b/public/-/emojis/1/flag_at.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_au.png b/public/-/emojis/1/flag_au.png
index 7794309c78c..7794309c78c 100644
--- a/app/assets/images/emoji/flag_au.png
+++ b/public/-/emojis/1/flag_au.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_aw.png b/public/-/emojis/1/flag_aw.png
index 02c840d12c9..02c840d12c9 100644
--- a/app/assets/images/emoji/flag_aw.png
+++ b/public/-/emojis/1/flag_aw.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ax.png b/public/-/emojis/1/flag_ax.png
index fc5466174bb..fc5466174bb 100644
--- a/app/assets/images/emoji/flag_ax.png
+++ b/public/-/emojis/1/flag_ax.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_az.png b/public/-/emojis/1/flag_az.png
index 89d3d15fd9f..89d3d15fd9f 100644
--- a/app/assets/images/emoji/flag_az.png
+++ b/public/-/emojis/1/flag_az.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ba.png b/public/-/emojis/1/flag_ba.png
index 25fe407e13c..25fe407e13c 100644
--- a/app/assets/images/emoji/flag_ba.png
+++ b/public/-/emojis/1/flag_ba.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bb.png b/public/-/emojis/1/flag_bb.png
index bccd8c5c9b0..bccd8c5c9b0 100644
--- a/app/assets/images/emoji/flag_bb.png
+++ b/public/-/emojis/1/flag_bb.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bd.png b/public/-/emojis/1/flag_bd.png
index b0597a3149b..b0597a3149b 100644
--- a/app/assets/images/emoji/flag_bd.png
+++ b/public/-/emojis/1/flag_bd.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_be.png b/public/-/emojis/1/flag_be.png
index 551f086e3c4..551f086e3c4 100644
--- a/app/assets/images/emoji/flag_be.png
+++ b/public/-/emojis/1/flag_be.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bf.png b/public/-/emojis/1/flag_bf.png
index 444d4829f94..444d4829f94 100644
--- a/app/assets/images/emoji/flag_bf.png
+++ b/public/-/emojis/1/flag_bf.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bg.png b/public/-/emojis/1/flag_bg.png
index 821eee5e170..821eee5e170 100644
--- a/app/assets/images/emoji/flag_bg.png
+++ b/public/-/emojis/1/flag_bg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bh.png b/public/-/emojis/1/flag_bh.png
index f33724249f0..f33724249f0 100644
--- a/app/assets/images/emoji/flag_bh.png
+++ b/public/-/emojis/1/flag_bh.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bi.png b/public/-/emojis/1/flag_bi.png
index ea20ac93211..ea20ac93211 100644
--- a/app/assets/images/emoji/flag_bi.png
+++ b/public/-/emojis/1/flag_bi.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bj.png b/public/-/emojis/1/flag_bj.png
index 7cca4f80457..7cca4f80457 100644
--- a/app/assets/images/emoji/flag_bj.png
+++ b/public/-/emojis/1/flag_bj.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bl.png b/public/-/emojis/1/flag_bl.png
index 1082e78999f..1082e78999f 100644
--- a/app/assets/images/emoji/flag_bl.png
+++ b/public/-/emojis/1/flag_bl.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_black.png b/public/-/emojis/1/flag_black.png
index 0e28d05d5ac..0e28d05d5ac 100644
--- a/app/assets/images/emoji/flag_black.png
+++ b/public/-/emojis/1/flag_black.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bm.png b/public/-/emojis/1/flag_bm.png
index ab8cafdac63..ab8cafdac63 100644
--- a/app/assets/images/emoji/flag_bm.png
+++ b/public/-/emojis/1/flag_bm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bn.png b/public/-/emojis/1/flag_bn.png
index caa9329a896..caa9329a896 100644
--- a/app/assets/images/emoji/flag_bn.png
+++ b/public/-/emojis/1/flag_bn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bo.png b/public/-/emojis/1/flag_bo.png
index 98af62b3da7..98af62b3da7 100644
--- a/app/assets/images/emoji/flag_bo.png
+++ b/public/-/emojis/1/flag_bo.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bq.png b/public/-/emojis/1/flag_bq.png
index cb978ef9de9..cb978ef9de9 100644
--- a/app/assets/images/emoji/flag_bq.png
+++ b/public/-/emojis/1/flag_bq.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_br.png b/public/-/emojis/1/flag_br.png
index b139366a42b..b139366a42b 100644
--- a/app/assets/images/emoji/flag_br.png
+++ b/public/-/emojis/1/flag_br.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bs.png b/public/-/emojis/1/flag_bs.png
index d36bcd2fb52..d36bcd2fb52 100644
--- a/app/assets/images/emoji/flag_bs.png
+++ b/public/-/emojis/1/flag_bs.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bt.png b/public/-/emojis/1/flag_bt.png
index ed57aa0360e..ed57aa0360e 100644
--- a/app/assets/images/emoji/flag_bt.png
+++ b/public/-/emojis/1/flag_bt.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bv.png b/public/-/emojis/1/flag_bv.png
index 5884e648228..5884e648228 100644
--- a/app/assets/images/emoji/flag_bv.png
+++ b/public/-/emojis/1/flag_bv.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bw.png b/public/-/emojis/1/flag_bw.png
index cb12f34739d..cb12f34739d 100644
--- a/app/assets/images/emoji/flag_bw.png
+++ b/public/-/emojis/1/flag_bw.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_by.png b/public/-/emojis/1/flag_by.png
index 859c05beb13..859c05beb13 100644
--- a/app/assets/images/emoji/flag_by.png
+++ b/public/-/emojis/1/flag_by.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_bz.png b/public/-/emojis/1/flag_bz.png
index 34761cd03d8..34761cd03d8 100644
--- a/app/assets/images/emoji/flag_bz.png
+++ b/public/-/emojis/1/flag_bz.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ca.png b/public/-/emojis/1/flag_ca.png
index 7c5b390e85b..7c5b390e85b 100644
--- a/app/assets/images/emoji/flag_ca.png
+++ b/public/-/emojis/1/flag_ca.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cc.png b/public/-/emojis/1/flag_cc.png
index b6555a23d83..b6555a23d83 100644
--- a/app/assets/images/emoji/flag_cc.png
+++ b/public/-/emojis/1/flag_cc.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cd.png b/public/-/emojis/1/flag_cd.png
index fa92009771d..fa92009771d 100644
--- a/app/assets/images/emoji/flag_cd.png
+++ b/public/-/emojis/1/flag_cd.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cf.png b/public/-/emojis/1/flag_cf.png
index b969ae29ea9..b969ae29ea9 100644
--- a/app/assets/images/emoji/flag_cf.png
+++ b/public/-/emojis/1/flag_cf.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cg.png b/public/-/emojis/1/flag_cg.png
index 3a38a40a95e..3a38a40a95e 100644
--- a/app/assets/images/emoji/flag_cg.png
+++ b/public/-/emojis/1/flag_cg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ch.png b/public/-/emojis/1/flag_ch.png
index 5ff86b8a3b7..5ff86b8a3b7 100644
--- a/app/assets/images/emoji/flag_ch.png
+++ b/public/-/emojis/1/flag_ch.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ci.png b/public/-/emojis/1/flag_ci.png
index e3b4d15c7f1..e3b4d15c7f1 100644
--- a/app/assets/images/emoji/flag_ci.png
+++ b/public/-/emojis/1/flag_ci.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ck.png b/public/-/emojis/1/flag_ck.png
index b6b53dbc1c4..b6b53dbc1c4 100644
--- a/app/assets/images/emoji/flag_ck.png
+++ b/public/-/emojis/1/flag_ck.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cl.png b/public/-/emojis/1/flag_cl.png
index c9390da5499..c9390da5499 100644
--- a/app/assets/images/emoji/flag_cl.png
+++ b/public/-/emojis/1/flag_cl.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cm.png b/public/-/emojis/1/flag_cm.png
index 2d3f6ec4518..2d3f6ec4518 100644
--- a/app/assets/images/emoji/flag_cm.png
+++ b/public/-/emojis/1/flag_cm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cn.png b/public/-/emojis/1/flag_cn.png
index 0a7f350a6d2..0a7f350a6d2 100644
--- a/app/assets/images/emoji/flag_cn.png
+++ b/public/-/emojis/1/flag_cn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_co.png b/public/-/emojis/1/flag_co.png
index 7e0f5e0dc3c..7e0f5e0dc3c 100644
--- a/app/assets/images/emoji/flag_co.png
+++ b/public/-/emojis/1/flag_co.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cp.png b/public/-/emojis/1/flag_cp.png
index 70c761036bd..70c761036bd 100644
--- a/app/assets/images/emoji/flag_cp.png
+++ b/public/-/emojis/1/flag_cp.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cr.png b/public/-/emojis/1/flag_cr.png
index a5fce126515..a5fce126515 100644
--- a/app/assets/images/emoji/flag_cr.png
+++ b/public/-/emojis/1/flag_cr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cu.png b/public/-/emojis/1/flag_cu.png
index 447328f7dfd..447328f7dfd 100644
--- a/app/assets/images/emoji/flag_cu.png
+++ b/public/-/emojis/1/flag_cu.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cv.png b/public/-/emojis/1/flag_cv.png
index 43faf4d64d5..43faf4d64d5 100644
--- a/app/assets/images/emoji/flag_cv.png
+++ b/public/-/emojis/1/flag_cv.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cw.png b/public/-/emojis/1/flag_cw.png
index eb39e8d0078..eb39e8d0078 100644
--- a/app/assets/images/emoji/flag_cw.png
+++ b/public/-/emojis/1/flag_cw.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cx.png b/public/-/emojis/1/flag_cx.png
index 09d21359f3a..09d21359f3a 100644
--- a/app/assets/images/emoji/flag_cx.png
+++ b/public/-/emojis/1/flag_cx.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cy.png b/public/-/emojis/1/flag_cy.png
index 154a7aa3176..154a7aa3176 100644
--- a/app/assets/images/emoji/flag_cy.png
+++ b/public/-/emojis/1/flag_cy.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_cz.png b/public/-/emojis/1/flag_cz.png
index 9737ca223c7..9737ca223c7 100644
--- a/app/assets/images/emoji/flag_cz.png
+++ b/public/-/emojis/1/flag_cz.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_de.png b/public/-/emojis/1/flag_de.png
index 98ed76b3bab..98ed76b3bab 100644
--- a/app/assets/images/emoji/flag_de.png
+++ b/public/-/emojis/1/flag_de.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_dg.png b/public/-/emojis/1/flag_dg.png
index aae927d14b8..aae927d14b8 100644
--- a/app/assets/images/emoji/flag_dg.png
+++ b/public/-/emojis/1/flag_dg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_dj.png b/public/-/emojis/1/flag_dj.png
index 73c2a2acbd9..73c2a2acbd9 100644
--- a/app/assets/images/emoji/flag_dj.png
+++ b/public/-/emojis/1/flag_dj.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_dk.png b/public/-/emojis/1/flag_dk.png
index e5a60b06256..e5a60b06256 100644
--- a/app/assets/images/emoji/flag_dk.png
+++ b/public/-/emojis/1/flag_dk.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_dm.png b/public/-/emojis/1/flag_dm.png
index 50f8a53981d..50f8a53981d 100644
--- a/app/assets/images/emoji/flag_dm.png
+++ b/public/-/emojis/1/flag_dm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_do.png b/public/-/emojis/1/flag_do.png
index 037a45d7c26..037a45d7c26 100644
--- a/app/assets/images/emoji/flag_do.png
+++ b/public/-/emojis/1/flag_do.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_dz.png b/public/-/emojis/1/flag_dz.png
index 24945b10f2d..24945b10f2d 100644
--- a/app/assets/images/emoji/flag_dz.png
+++ b/public/-/emojis/1/flag_dz.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ea.png b/public/-/emojis/1/flag_ea.png
index 356ff347838..356ff347838 100644
--- a/app/assets/images/emoji/flag_ea.png
+++ b/public/-/emojis/1/flag_ea.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ec.png b/public/-/emojis/1/flag_ec.png
index 13814594619..13814594619 100644
--- a/app/assets/images/emoji/flag_ec.png
+++ b/public/-/emojis/1/flag_ec.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ee.png b/public/-/emojis/1/flag_ee.png
index 84f317e7747..84f317e7747 100644
--- a/app/assets/images/emoji/flag_ee.png
+++ b/public/-/emojis/1/flag_ee.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_eg.png b/public/-/emojis/1/flag_eg.png
index 57786064a95..57786064a95 100644
--- a/app/assets/images/emoji/flag_eg.png
+++ b/public/-/emojis/1/flag_eg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_eh.png b/public/-/emojis/1/flag_eh.png
index 4d7a76687f6..4d7a76687f6 100644
--- a/app/assets/images/emoji/flag_eh.png
+++ b/public/-/emojis/1/flag_eh.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_er.png b/public/-/emojis/1/flag_er.png
index 0c3c724c1fb..0c3c724c1fb 100644
--- a/app/assets/images/emoji/flag_er.png
+++ b/public/-/emojis/1/flag_er.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_es.png b/public/-/emojis/1/flag_es.png
index 3e73597a225..3e73597a225 100644
--- a/app/assets/images/emoji/flag_es.png
+++ b/public/-/emojis/1/flag_es.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_et.png b/public/-/emojis/1/flag_et.png
index 9560a134c97..9560a134c97 100644
--- a/app/assets/images/emoji/flag_et.png
+++ b/public/-/emojis/1/flag_et.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_eu.png b/public/-/emojis/1/flag_eu.png
index 0b456cf3330..0b456cf3330 100644
--- a/app/assets/images/emoji/flag_eu.png
+++ b/public/-/emojis/1/flag_eu.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_fi.png b/public/-/emojis/1/flag_fi.png
index ebcf58abfc5..ebcf58abfc5 100644
--- a/app/assets/images/emoji/flag_fi.png
+++ b/public/-/emojis/1/flag_fi.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_fj.png b/public/-/emojis/1/flag_fj.png
index 9cc8c37fe37..9cc8c37fe37 100644
--- a/app/assets/images/emoji/flag_fj.png
+++ b/public/-/emojis/1/flag_fj.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_fk.png b/public/-/emojis/1/flag_fk.png
index 61372fd2549..61372fd2549 100644
--- a/app/assets/images/emoji/flag_fk.png
+++ b/public/-/emojis/1/flag_fk.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_fm.png b/public/-/emojis/1/flag_fm.png
index 0889825c8e1..0889825c8e1 100644
--- a/app/assets/images/emoji/flag_fm.png
+++ b/public/-/emojis/1/flag_fm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_fo.png b/public/-/emojis/1/flag_fo.png
index 9a4431b0831..9a4431b0831 100644
--- a/app/assets/images/emoji/flag_fo.png
+++ b/public/-/emojis/1/flag_fo.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_fr.png b/public/-/emojis/1/flag_fr.png
index 62ca19c3fcf..62ca19c3fcf 100644
--- a/app/assets/images/emoji/flag_fr.png
+++ b/public/-/emojis/1/flag_fr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ga.png b/public/-/emojis/1/flag_ga.png
index 2e68e527a3e..2e68e527a3e 100644
--- a/app/assets/images/emoji/flag_ga.png
+++ b/public/-/emojis/1/flag_ga.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gb.png b/public/-/emojis/1/flag_gb.png
index 3ed10f62347..3ed10f62347 100644
--- a/app/assets/images/emoji/flag_gb.png
+++ b/public/-/emojis/1/flag_gb.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gd.png b/public/-/emojis/1/flag_gd.png
index 527aad33807..527aad33807 100644
--- a/app/assets/images/emoji/flag_gd.png
+++ b/public/-/emojis/1/flag_gd.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ge.png b/public/-/emojis/1/flag_ge.png
index a75d142480d..a75d142480d 100644
--- a/app/assets/images/emoji/flag_ge.png
+++ b/public/-/emojis/1/flag_ge.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gf.png b/public/-/emojis/1/flag_gf.png
index 0cf96f327c0..0cf96f327c0 100644
--- a/app/assets/images/emoji/flag_gf.png
+++ b/public/-/emojis/1/flag_gf.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gg.png b/public/-/emojis/1/flag_gg.png
index 970002c7f76..970002c7f76 100644
--- a/app/assets/images/emoji/flag_gg.png
+++ b/public/-/emojis/1/flag_gg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gh.png b/public/-/emojis/1/flag_gh.png
index f31b5eb7b45..f31b5eb7b45 100644
--- a/app/assets/images/emoji/flag_gh.png
+++ b/public/-/emojis/1/flag_gh.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gi.png b/public/-/emojis/1/flag_gi.png
index e554a2a1d0c..e554a2a1d0c 100644
--- a/app/assets/images/emoji/flag_gi.png
+++ b/public/-/emojis/1/flag_gi.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gl.png b/public/-/emojis/1/flag_gl.png
index 2e795dd4e33..2e795dd4e33 100644
--- a/app/assets/images/emoji/flag_gl.png
+++ b/public/-/emojis/1/flag_gl.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gm.png b/public/-/emojis/1/flag_gm.png
index bb69c0975a3..bb69c0975a3 100644
--- a/app/assets/images/emoji/flag_gm.png
+++ b/public/-/emojis/1/flag_gm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gn.png b/public/-/emojis/1/flag_gn.png
index 1981f61dbf5..1981f61dbf5 100644
--- a/app/assets/images/emoji/flag_gn.png
+++ b/public/-/emojis/1/flag_gn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gp.png b/public/-/emojis/1/flag_gp.png
index 10e42e672bd..10e42e672bd 100644
--- a/app/assets/images/emoji/flag_gp.png
+++ b/public/-/emojis/1/flag_gp.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gq.png b/public/-/emojis/1/flag_gq.png
index 11475e61eeb..11475e61eeb 100644
--- a/app/assets/images/emoji/flag_gq.png
+++ b/public/-/emojis/1/flag_gq.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gr.png b/public/-/emojis/1/flag_gr.png
index 0f6bb1b6b94..0f6bb1b6b94 100644
--- a/app/assets/images/emoji/flag_gr.png
+++ b/public/-/emojis/1/flag_gr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gs.png b/public/-/emojis/1/flag_gs.png
index 6fc92780453..6fc92780453 100644
--- a/app/assets/images/emoji/flag_gs.png
+++ b/public/-/emojis/1/flag_gs.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gt.png b/public/-/emojis/1/flag_gt.png
index 7213d4139ed..7213d4139ed 100644
--- a/app/assets/images/emoji/flag_gt.png
+++ b/public/-/emojis/1/flag_gt.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gu.png b/public/-/emojis/1/flag_gu.png
index 4027549ca3c..4027549ca3c 100644
--- a/app/assets/images/emoji/flag_gu.png
+++ b/public/-/emojis/1/flag_gu.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gw.png b/public/-/emojis/1/flag_gw.png
index 6357f6225f4..6357f6225f4 100644
--- a/app/assets/images/emoji/flag_gw.png
+++ b/public/-/emojis/1/flag_gw.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_gy.png b/public/-/emojis/1/flag_gy.png
index 746e2fb7e44..746e2fb7e44 100644
--- a/app/assets/images/emoji/flag_gy.png
+++ b/public/-/emojis/1/flag_gy.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_hk.png b/public/-/emojis/1/flag_hk.png
index cf0c7151b56..cf0c7151b56 100644
--- a/app/assets/images/emoji/flag_hk.png
+++ b/public/-/emojis/1/flag_hk.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_hm.png b/public/-/emojis/1/flag_hm.png
index b613509e466..b613509e466 100644
--- a/app/assets/images/emoji/flag_hm.png
+++ b/public/-/emojis/1/flag_hm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_hn.png b/public/-/emojis/1/flag_hn.png
index 402cdcefdf8..402cdcefdf8 100644
--- a/app/assets/images/emoji/flag_hn.png
+++ b/public/-/emojis/1/flag_hn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_hr.png b/public/-/emojis/1/flag_hr.png
index 46f4f06b4f2..46f4f06b4f2 100644
--- a/app/assets/images/emoji/flag_hr.png
+++ b/public/-/emojis/1/flag_hr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ht.png b/public/-/emojis/1/flag_ht.png
index d8d0c888498..d8d0c888498 100644
--- a/app/assets/images/emoji/flag_ht.png
+++ b/public/-/emojis/1/flag_ht.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_hu.png b/public/-/emojis/1/flag_hu.png
index a898de636a5..a898de636a5 100644
--- a/app/assets/images/emoji/flag_hu.png
+++ b/public/-/emojis/1/flag_hu.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ic.png b/public/-/emojis/1/flag_ic.png
index 69fd990aa95..69fd990aa95 100644
--- a/app/assets/images/emoji/flag_ic.png
+++ b/public/-/emojis/1/flag_ic.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_id.png b/public/-/emojis/1/flag_id.png
index 85b4c063a45..85b4c063a45 100644
--- a/app/assets/images/emoji/flag_id.png
+++ b/public/-/emojis/1/flag_id.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ie.png b/public/-/emojis/1/flag_ie.png
index a28295838cc..a28295838cc 100644
--- a/app/assets/images/emoji/flag_ie.png
+++ b/public/-/emojis/1/flag_ie.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_il.png b/public/-/emojis/1/flag_il.png
index 85c410d45fb..85c410d45fb 100644
--- a/app/assets/images/emoji/flag_il.png
+++ b/public/-/emojis/1/flag_il.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_im.png b/public/-/emojis/1/flag_im.png
index 60a2458e38e..60a2458e38e 100644
--- a/app/assets/images/emoji/flag_im.png
+++ b/public/-/emojis/1/flag_im.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_in.png b/public/-/emojis/1/flag_in.png
index feccc8952ce..feccc8952ce 100644
--- a/app/assets/images/emoji/flag_in.png
+++ b/public/-/emojis/1/flag_in.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_io.png b/public/-/emojis/1/flag_io.png
index aae927d14b8..aae927d14b8 100644
--- a/app/assets/images/emoji/flag_io.png
+++ b/public/-/emojis/1/flag_io.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_iq.png b/public/-/emojis/1/flag_iq.png
index 41fd1db6f86..41fd1db6f86 100644
--- a/app/assets/images/emoji/flag_iq.png
+++ b/public/-/emojis/1/flag_iq.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ir.png b/public/-/emojis/1/flag_ir.png
index ff7aaf62ba6..ff7aaf62ba6 100644
--- a/app/assets/images/emoji/flag_ir.png
+++ b/public/-/emojis/1/flag_ir.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_is.png b/public/-/emojis/1/flag_is.png
index ad8d4131dd2..ad8d4131dd2 100644
--- a/app/assets/images/emoji/flag_is.png
+++ b/public/-/emojis/1/flag_is.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_it.png b/public/-/emojis/1/flag_it.png
index f21563ec533..f21563ec533 100644
--- a/app/assets/images/emoji/flag_it.png
+++ b/public/-/emojis/1/flag_it.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_je.png b/public/-/emojis/1/flag_je.png
index 198a918f6a4..198a918f6a4 100644
--- a/app/assets/images/emoji/flag_je.png
+++ b/public/-/emojis/1/flag_je.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_jm.png b/public/-/emojis/1/flag_jm.png
index f84e4f9e8db..f84e4f9e8db 100644
--- a/app/assets/images/emoji/flag_jm.png
+++ b/public/-/emojis/1/flag_jm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_jo.png b/public/-/emojis/1/flag_jo.png
index 20bfa147e3e..20bfa147e3e 100644
--- a/app/assets/images/emoji/flag_jo.png
+++ b/public/-/emojis/1/flag_jo.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_jp.png b/public/-/emojis/1/flag_jp.png
index 8d8838e4708..8d8838e4708 100644
--- a/app/assets/images/emoji/flag_jp.png
+++ b/public/-/emojis/1/flag_jp.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ke.png b/public/-/emojis/1/flag_ke.png
index 9e417ab3009..9e417ab3009 100644
--- a/app/assets/images/emoji/flag_ke.png
+++ b/public/-/emojis/1/flag_ke.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_kg.png b/public/-/emojis/1/flag_kg.png
index 2f2d848fe58..2f2d848fe58 100644
--- a/app/assets/images/emoji/flag_kg.png
+++ b/public/-/emojis/1/flag_kg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_kh.png b/public/-/emojis/1/flag_kh.png
index 9a2877dd620..9a2877dd620 100644
--- a/app/assets/images/emoji/flag_kh.png
+++ b/public/-/emojis/1/flag_kh.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ki.png b/public/-/emojis/1/flag_ki.png
index 10e507e3245..10e507e3245 100644
--- a/app/assets/images/emoji/flag_ki.png
+++ b/public/-/emojis/1/flag_ki.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_km.png b/public/-/emojis/1/flag_km.png
index bd5a0588e03..bd5a0588e03 100644
--- a/app/assets/images/emoji/flag_km.png
+++ b/public/-/emojis/1/flag_km.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_kn.png b/public/-/emojis/1/flag_kn.png
index 776207c9605..776207c9605 100644
--- a/app/assets/images/emoji/flag_kn.png
+++ b/public/-/emojis/1/flag_kn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_kp.png b/public/-/emojis/1/flag_kp.png
index 6b3fd89eaaa..6b3fd89eaaa 100644
--- a/app/assets/images/emoji/flag_kp.png
+++ b/public/-/emojis/1/flag_kp.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_kr.png b/public/-/emojis/1/flag_kr.png
index 833a88116e1..833a88116e1 100644
--- a/app/assets/images/emoji/flag_kr.png
+++ b/public/-/emojis/1/flag_kr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_kw.png b/public/-/emojis/1/flag_kw.png
index 4d19bfa6ca7..4d19bfa6ca7 100644
--- a/app/assets/images/emoji/flag_kw.png
+++ b/public/-/emojis/1/flag_kw.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ky.png b/public/-/emojis/1/flag_ky.png
index 40daa4da597..40daa4da597 100644
--- a/app/assets/images/emoji/flag_ky.png
+++ b/public/-/emojis/1/flag_ky.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_kz.png b/public/-/emojis/1/flag_kz.png
index 2f97a8fd3c6..2f97a8fd3c6 100644
--- a/app/assets/images/emoji/flag_kz.png
+++ b/public/-/emojis/1/flag_kz.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_la.png b/public/-/emojis/1/flag_la.png
index 4d4179f34f6..4d4179f34f6 100644
--- a/app/assets/images/emoji/flag_la.png
+++ b/public/-/emojis/1/flag_la.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_lb.png b/public/-/emojis/1/flag_lb.png
index 3d594467011..3d594467011 100644
--- a/app/assets/images/emoji/flag_lb.png
+++ b/public/-/emojis/1/flag_lb.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_lc.png b/public/-/emojis/1/flag_lc.png
index 45547b1e439..45547b1e439 100644
--- a/app/assets/images/emoji/flag_lc.png
+++ b/public/-/emojis/1/flag_lc.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_li.png b/public/-/emojis/1/flag_li.png
index 0eafa6a2215..0eafa6a2215 100644
--- a/app/assets/images/emoji/flag_li.png
+++ b/public/-/emojis/1/flag_li.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_lk.png b/public/-/emojis/1/flag_lk.png
index ab4fe10c40c..ab4fe10c40c 100644
--- a/app/assets/images/emoji/flag_lk.png
+++ b/public/-/emojis/1/flag_lk.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_lr.png b/public/-/emojis/1/flag_lr.png
index f66f267fea2..f66f267fea2 100644
--- a/app/assets/images/emoji/flag_lr.png
+++ b/public/-/emojis/1/flag_lr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ls.png b/public/-/emojis/1/flag_ls.png
index 24745631e3c..24745631e3c 100644
--- a/app/assets/images/emoji/flag_ls.png
+++ b/public/-/emojis/1/flag_ls.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_lt.png b/public/-/emojis/1/flag_lt.png
index d644b56d62a..d644b56d62a 100644
--- a/app/assets/images/emoji/flag_lt.png
+++ b/public/-/emojis/1/flag_lt.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_lu.png b/public/-/emojis/1/flag_lu.png
index a2df9c92994..a2df9c92994 100644
--- a/app/assets/images/emoji/flag_lu.png
+++ b/public/-/emojis/1/flag_lu.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_lv.png b/public/-/emojis/1/flag_lv.png
index ae680d5f0e3..ae680d5f0e3 100644
--- a/app/assets/images/emoji/flag_lv.png
+++ b/public/-/emojis/1/flag_lv.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ly.png b/public/-/emojis/1/flag_ly.png
index f6e77b0f3ba..f6e77b0f3ba 100644
--- a/app/assets/images/emoji/flag_ly.png
+++ b/public/-/emojis/1/flag_ly.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ma.png b/public/-/emojis/1/flag_ma.png
index c4a056722cd..c4a056722cd 100644
--- a/app/assets/images/emoji/flag_ma.png
+++ b/public/-/emojis/1/flag_ma.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mc.png b/public/-/emojis/1/flag_mc.png
index d479eab98cb..d479eab98cb 100644
--- a/app/assets/images/emoji/flag_mc.png
+++ b/public/-/emojis/1/flag_mc.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_md.png b/public/-/emojis/1/flag_md.png
index a7a72539872..a7a72539872 100644
--- a/app/assets/images/emoji/flag_md.png
+++ b/public/-/emojis/1/flag_md.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_me.png b/public/-/emojis/1/flag_me.png
index 7c771e7e120..7c771e7e120 100644
--- a/app/assets/images/emoji/flag_me.png
+++ b/public/-/emojis/1/flag_me.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mf.png b/public/-/emojis/1/flag_mf.png
index 70c761036bd..70c761036bd 100644
--- a/app/assets/images/emoji/flag_mf.png
+++ b/public/-/emojis/1/flag_mf.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mg.png b/public/-/emojis/1/flag_mg.png
index 2f3ccdda76f..2f3ccdda76f 100644
--- a/app/assets/images/emoji/flag_mg.png
+++ b/public/-/emojis/1/flag_mg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mh.png b/public/-/emojis/1/flag_mh.png
index 598016481c1..598016481c1 100644
--- a/app/assets/images/emoji/flag_mh.png
+++ b/public/-/emojis/1/flag_mh.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mk.png b/public/-/emojis/1/flag_mk.png
index 7ba775ee75c..7ba775ee75c 100644
--- a/app/assets/images/emoji/flag_mk.png
+++ b/public/-/emojis/1/flag_mk.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ml.png b/public/-/emojis/1/flag_ml.png
index 68343785468..68343785468 100644
--- a/app/assets/images/emoji/flag_ml.png
+++ b/public/-/emojis/1/flag_ml.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mm.png b/public/-/emojis/1/flag_mm.png
index 37dc7d71591..37dc7d71591 100644
--- a/app/assets/images/emoji/flag_mm.png
+++ b/public/-/emojis/1/flag_mm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mn.png b/public/-/emojis/1/flag_mn.png
index 1f146bbcd1a..1f146bbcd1a 100644
--- a/app/assets/images/emoji/flag_mn.png
+++ b/public/-/emojis/1/flag_mn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mo.png b/public/-/emojis/1/flag_mo.png
index 7edde31f64b..7edde31f64b 100644
--- a/app/assets/images/emoji/flag_mo.png
+++ b/public/-/emojis/1/flag_mo.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mp.png b/public/-/emojis/1/flag_mp.png
index 17ec1c441ed..17ec1c441ed 100644
--- a/app/assets/images/emoji/flag_mp.png
+++ b/public/-/emojis/1/flag_mp.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mq.png b/public/-/emojis/1/flag_mq.png
index 1e672dc9087..1e672dc9087 100644
--- a/app/assets/images/emoji/flag_mq.png
+++ b/public/-/emojis/1/flag_mq.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mr.png b/public/-/emojis/1/flag_mr.png
index f87de46effe..f87de46effe 100644
--- a/app/assets/images/emoji/flag_mr.png
+++ b/public/-/emojis/1/flag_mr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ms.png b/public/-/emojis/1/flag_ms.png
index 480b0d4ebda..480b0d4ebda 100644
--- a/app/assets/images/emoji/flag_ms.png
+++ b/public/-/emojis/1/flag_ms.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mt.png b/public/-/emojis/1/flag_mt.png
index c9e1dbdce82..c9e1dbdce82 100644
--- a/app/assets/images/emoji/flag_mt.png
+++ b/public/-/emojis/1/flag_mt.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mu.png b/public/-/emojis/1/flag_mu.png
index 55b33cb7c33..55b33cb7c33 100644
--- a/app/assets/images/emoji/flag_mu.png
+++ b/public/-/emojis/1/flag_mu.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mv.png b/public/-/emojis/1/flag_mv.png
index ce5867126ae..ce5867126ae 100644
--- a/app/assets/images/emoji/flag_mv.png
+++ b/public/-/emojis/1/flag_mv.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mw.png b/public/-/emojis/1/flag_mw.png
index 003d8548401..003d8548401 100644
--- a/app/assets/images/emoji/flag_mw.png
+++ b/public/-/emojis/1/flag_mw.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mx.png b/public/-/emojis/1/flag_mx.png
index 42572bcd0ba..42572bcd0ba 100644
--- a/app/assets/images/emoji/flag_mx.png
+++ b/public/-/emojis/1/flag_mx.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_my.png b/public/-/emojis/1/flag_my.png
index 17526c26742..17526c26742 100644
--- a/app/assets/images/emoji/flag_my.png
+++ b/public/-/emojis/1/flag_my.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_mz.png b/public/-/emojis/1/flag_mz.png
index 2352a78e786..2352a78e786 100644
--- a/app/assets/images/emoji/flag_mz.png
+++ b/public/-/emojis/1/flag_mz.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_na.png b/public/-/emojis/1/flag_na.png
index ed31c3df04d..ed31c3df04d 100644
--- a/app/assets/images/emoji/flag_na.png
+++ b/public/-/emojis/1/flag_na.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_nc.png b/public/-/emojis/1/flag_nc.png
index 90b3afebfa3..90b3afebfa3 100644
--- a/app/assets/images/emoji/flag_nc.png
+++ b/public/-/emojis/1/flag_nc.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ne.png b/public/-/emojis/1/flag_ne.png
index f98a1173c2a..f98a1173c2a 100644
--- a/app/assets/images/emoji/flag_ne.png
+++ b/public/-/emojis/1/flag_ne.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_nf.png b/public/-/emojis/1/flag_nf.png
index 9099e767420..9099e767420 100644
--- a/app/assets/images/emoji/flag_nf.png
+++ b/public/-/emojis/1/flag_nf.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ng.png b/public/-/emojis/1/flag_ng.png
index ea0abeff1a1..ea0abeff1a1 100644
--- a/app/assets/images/emoji/flag_ng.png
+++ b/public/-/emojis/1/flag_ng.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ni.png b/public/-/emojis/1/flag_ni.png
index 772920dfa10..772920dfa10 100644
--- a/app/assets/images/emoji/flag_ni.png
+++ b/public/-/emojis/1/flag_ni.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_nl.png b/public/-/emojis/1/flag_nl.png
index 83a0e817e41..83a0e817e41 100644
--- a/app/assets/images/emoji/flag_nl.png
+++ b/public/-/emojis/1/flag_nl.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_no.png b/public/-/emojis/1/flag_no.png
index 99d3142eb7b..99d3142eb7b 100644
--- a/app/assets/images/emoji/flag_no.png
+++ b/public/-/emojis/1/flag_no.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_np.png b/public/-/emojis/1/flag_np.png
index 87425a8dfef..87425a8dfef 100644
--- a/app/assets/images/emoji/flag_np.png
+++ b/public/-/emojis/1/flag_np.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_nr.png b/public/-/emojis/1/flag_nr.png
index b3e3a5d5621..b3e3a5d5621 100644
--- a/app/assets/images/emoji/flag_nr.png
+++ b/public/-/emojis/1/flag_nr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_nu.png b/public/-/emojis/1/flag_nu.png
index f03614443ee..f03614443ee 100644
--- a/app/assets/images/emoji/flag_nu.png
+++ b/public/-/emojis/1/flag_nu.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_nz.png b/public/-/emojis/1/flag_nz.png
index a4eeeab9cd9..a4eeeab9cd9 100644
--- a/app/assets/images/emoji/flag_nz.png
+++ b/public/-/emojis/1/flag_nz.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_om.png b/public/-/emojis/1/flag_om.png
index ea824ba31e7..ea824ba31e7 100644
--- a/app/assets/images/emoji/flag_om.png
+++ b/public/-/emojis/1/flag_om.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pa.png b/public/-/emojis/1/flag_pa.png
index c3091d89889..c3091d89889 100644
--- a/app/assets/images/emoji/flag_pa.png
+++ b/public/-/emojis/1/flag_pa.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pe.png b/public/-/emojis/1/flag_pe.png
index 39223aa9dbb..39223aa9dbb 100644
--- a/app/assets/images/emoji/flag_pe.png
+++ b/public/-/emojis/1/flag_pe.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pf.png b/public/-/emojis/1/flag_pf.png
index 113445f8f6e..113445f8f6e 100644
--- a/app/assets/images/emoji/flag_pf.png
+++ b/public/-/emojis/1/flag_pf.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pg.png b/public/-/emojis/1/flag_pg.png
index 825e9dcb762..825e9dcb762 100644
--- a/app/assets/images/emoji/flag_pg.png
+++ b/public/-/emojis/1/flag_pg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ph.png b/public/-/emojis/1/flag_ph.png
index 8260e15bd2c..8260e15bd2c 100644
--- a/app/assets/images/emoji/flag_ph.png
+++ b/public/-/emojis/1/flag_ph.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pk.png b/public/-/emojis/1/flag_pk.png
index a7b6a1c5074..a7b6a1c5074 100644
--- a/app/assets/images/emoji/flag_pk.png
+++ b/public/-/emojis/1/flag_pk.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pl.png b/public/-/emojis/1/flag_pl.png
index 19de2edec11..19de2edec11 100644
--- a/app/assets/images/emoji/flag_pl.png
+++ b/public/-/emojis/1/flag_pl.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pm.png b/public/-/emojis/1/flag_pm.png
index 2ca60554193..2ca60554193 100644
--- a/app/assets/images/emoji/flag_pm.png
+++ b/public/-/emojis/1/flag_pm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pn.png b/public/-/emojis/1/flag_pn.png
index f2263b154bc..f2263b154bc 100644
--- a/app/assets/images/emoji/flag_pn.png
+++ b/public/-/emojis/1/flag_pn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pr.png b/public/-/emojis/1/flag_pr.png
index d0209cddb79..d0209cddb79 100644
--- a/app/assets/images/emoji/flag_pr.png
+++ b/public/-/emojis/1/flag_pr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ps.png b/public/-/emojis/1/flag_ps.png
index 7ccab09778b..7ccab09778b 100644
--- a/app/assets/images/emoji/flag_ps.png
+++ b/public/-/emojis/1/flag_ps.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pt.png b/public/-/emojis/1/flag_pt.png
index cc93f27c64b..cc93f27c64b 100644
--- a/app/assets/images/emoji/flag_pt.png
+++ b/public/-/emojis/1/flag_pt.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_pw.png b/public/-/emojis/1/flag_pw.png
index 154b2f12d3c..154b2f12d3c 100644
--- a/app/assets/images/emoji/flag_pw.png
+++ b/public/-/emojis/1/flag_pw.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_py.png b/public/-/emojis/1/flag_py.png
index 662ad2f6ff1..662ad2f6ff1 100644
--- a/app/assets/images/emoji/flag_py.png
+++ b/public/-/emojis/1/flag_py.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_qa.png b/public/-/emojis/1/flag_qa.png
index a01d8b05cc7..a01d8b05cc7 100644
--- a/app/assets/images/emoji/flag_qa.png
+++ b/public/-/emojis/1/flag_qa.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_re.png b/public/-/emojis/1/flag_re.png
index 57f2bbe9df8..57f2bbe9df8 100644
--- a/app/assets/images/emoji/flag_re.png
+++ b/public/-/emojis/1/flag_re.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ro.png b/public/-/emojis/1/flag_ro.png
index 3e48c447706..3e48c447706 100644
--- a/app/assets/images/emoji/flag_ro.png
+++ b/public/-/emojis/1/flag_ro.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_rs.png b/public/-/emojis/1/flag_rs.png
index 9df6c9a5235..9df6c9a5235 100644
--- a/app/assets/images/emoji/flag_rs.png
+++ b/public/-/emojis/1/flag_rs.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ru.png b/public/-/emojis/1/flag_ru.png
index e50c9db90e7..e50c9db90e7 100644
--- a/app/assets/images/emoji/flag_ru.png
+++ b/public/-/emojis/1/flag_ru.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_rw.png b/public/-/emojis/1/flag_rw.png
index c238c874e1d..c238c874e1d 100644
--- a/app/assets/images/emoji/flag_rw.png
+++ b/public/-/emojis/1/flag_rw.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sa.png b/public/-/emojis/1/flag_sa.png
index 4941be7d198..4941be7d198 100644
--- a/app/assets/images/emoji/flag_sa.png
+++ b/public/-/emojis/1/flag_sa.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sb.png b/public/-/emojis/1/flag_sb.png
index 7d8f1ac6130..7d8f1ac6130 100644
--- a/app/assets/images/emoji/flag_sb.png
+++ b/public/-/emojis/1/flag_sb.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sc.png b/public/-/emojis/1/flag_sc.png
index 6ae4d90765e..6ae4d90765e 100644
--- a/app/assets/images/emoji/flag_sc.png
+++ b/public/-/emojis/1/flag_sc.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sd.png b/public/-/emojis/1/flag_sd.png
index 963be1b36fb..963be1b36fb 100644
--- a/app/assets/images/emoji/flag_sd.png
+++ b/public/-/emojis/1/flag_sd.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_se.png b/public/-/emojis/1/flag_se.png
index fc0d0e0ce89..fc0d0e0ce89 100644
--- a/app/assets/images/emoji/flag_se.png
+++ b/public/-/emojis/1/flag_se.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sg.png b/public/-/emojis/1/flag_sg.png
index de3c7737c42..de3c7737c42 100644
--- a/app/assets/images/emoji/flag_sg.png
+++ b/public/-/emojis/1/flag_sg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sh.png b/public/-/emojis/1/flag_sh.png
index 40cd9e44e96..40cd9e44e96 100644
--- a/app/assets/images/emoji/flag_sh.png
+++ b/public/-/emojis/1/flag_sh.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_si.png b/public/-/emojis/1/flag_si.png
index e308999dba2..e308999dba2 100644
--- a/app/assets/images/emoji/flag_si.png
+++ b/public/-/emojis/1/flag_si.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sj.png b/public/-/emojis/1/flag_sj.png
index 5884e648228..5884e648228 100644
--- a/app/assets/images/emoji/flag_sj.png
+++ b/public/-/emojis/1/flag_sj.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sk.png b/public/-/emojis/1/flag_sk.png
index 4259d0e1418..4259d0e1418 100644
--- a/app/assets/images/emoji/flag_sk.png
+++ b/public/-/emojis/1/flag_sk.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sl.png b/public/-/emojis/1/flag_sl.png
index d2cc68830ab..d2cc68830ab 100644
--- a/app/assets/images/emoji/flag_sl.png
+++ b/public/-/emojis/1/flag_sl.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sm.png b/public/-/emojis/1/flag_sm.png
index 03b8708754e..03b8708754e 100644
--- a/app/assets/images/emoji/flag_sm.png
+++ b/public/-/emojis/1/flag_sm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sn.png b/public/-/emojis/1/flag_sn.png
index 5368bbe93df..5368bbe93df 100644
--- a/app/assets/images/emoji/flag_sn.png
+++ b/public/-/emojis/1/flag_sn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_so.png b/public/-/emojis/1/flag_so.png
index 68a0597365a..68a0597365a 100644
--- a/app/assets/images/emoji/flag_so.png
+++ b/public/-/emojis/1/flag_so.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sr.png b/public/-/emojis/1/flag_sr.png
index d3251327035..d3251327035 100644
--- a/app/assets/images/emoji/flag_sr.png
+++ b/public/-/emojis/1/flag_sr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ss.png b/public/-/emojis/1/flag_ss.png
index 122977e798f..122977e798f 100644
--- a/app/assets/images/emoji/flag_ss.png
+++ b/public/-/emojis/1/flag_ss.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_st.png b/public/-/emojis/1/flag_st.png
index f83a863d612..f83a863d612 100644
--- a/app/assets/images/emoji/flag_st.png
+++ b/public/-/emojis/1/flag_st.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sv.png b/public/-/emojis/1/flag_sv.png
index efb83e2f253..efb83e2f253 100644
--- a/app/assets/images/emoji/flag_sv.png
+++ b/public/-/emojis/1/flag_sv.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sx.png b/public/-/emojis/1/flag_sx.png
index 94b760fbedf..94b760fbedf 100644
--- a/app/assets/images/emoji/flag_sx.png
+++ b/public/-/emojis/1/flag_sx.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sy.png b/public/-/emojis/1/flag_sy.png
index 09a8ee8f78c..09a8ee8f78c 100644
--- a/app/assets/images/emoji/flag_sy.png
+++ b/public/-/emojis/1/flag_sy.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_sz.png b/public/-/emojis/1/flag_sz.png
index f74e82ea1fd..f74e82ea1fd 100644
--- a/app/assets/images/emoji/flag_sz.png
+++ b/public/-/emojis/1/flag_sz.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ta.png b/public/-/emojis/1/flag_ta.png
index b44283e90e2..b44283e90e2 100644
--- a/app/assets/images/emoji/flag_ta.png
+++ b/public/-/emojis/1/flag_ta.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tc.png b/public/-/emojis/1/flag_tc.png
index 156b33d1ba6..156b33d1ba6 100644
--- a/app/assets/images/emoji/flag_tc.png
+++ b/public/-/emojis/1/flag_tc.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_td.png b/public/-/emojis/1/flag_td.png
index ebe7f592828..ebe7f592828 100644
--- a/app/assets/images/emoji/flag_td.png
+++ b/public/-/emojis/1/flag_td.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tf.png b/public/-/emojis/1/flag_tf.png
index a1a3ad68ee2..a1a3ad68ee2 100644
--- a/app/assets/images/emoji/flag_tf.png
+++ b/public/-/emojis/1/flag_tf.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tg.png b/public/-/emojis/1/flag_tg.png
index 826b73c9ac5..826b73c9ac5 100644
--- a/app/assets/images/emoji/flag_tg.png
+++ b/public/-/emojis/1/flag_tg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_th.png b/public/-/emojis/1/flag_th.png
index 93ff542c5a6..93ff542c5a6 100644
--- a/app/assets/images/emoji/flag_th.png
+++ b/public/-/emojis/1/flag_th.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tj.png b/public/-/emojis/1/flag_tj.png
index 7a8a0b6190a..7a8a0b6190a 100644
--- a/app/assets/images/emoji/flag_tj.png
+++ b/public/-/emojis/1/flag_tj.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tk.png b/public/-/emojis/1/flag_tk.png
index 2fa5a21b1bb..2fa5a21b1bb 100644
--- a/app/assets/images/emoji/flag_tk.png
+++ b/public/-/emojis/1/flag_tk.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tl.png b/public/-/emojis/1/flag_tl.png
index 5b120eccc6f..5b120eccc6f 100644
--- a/app/assets/images/emoji/flag_tl.png
+++ b/public/-/emojis/1/flag_tl.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tm.png b/public/-/emojis/1/flag_tm.png
index c3c4f532302..c3c4f532302 100644
--- a/app/assets/images/emoji/flag_tm.png
+++ b/public/-/emojis/1/flag_tm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tn.png b/public/-/emojis/1/flag_tn.png
index 58ef161229f..58ef161229f 100644
--- a/app/assets/images/emoji/flag_tn.png
+++ b/public/-/emojis/1/flag_tn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_to.png b/public/-/emojis/1/flag_to.png
index 1ffa7bb9d19..1ffa7bb9d19 100644
--- a/app/assets/images/emoji/flag_to.png
+++ b/public/-/emojis/1/flag_to.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tr.png b/public/-/emojis/1/flag_tr.png
index 325251fae88..325251fae88 100644
--- a/app/assets/images/emoji/flag_tr.png
+++ b/public/-/emojis/1/flag_tr.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tt.png b/public/-/emojis/1/flag_tt.png
index ed3bb39a300..ed3bb39a300 100644
--- a/app/assets/images/emoji/flag_tt.png
+++ b/public/-/emojis/1/flag_tt.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tv.png b/public/-/emojis/1/flag_tv.png
index e82c65c7bb9..e82c65c7bb9 100644
--- a/app/assets/images/emoji/flag_tv.png
+++ b/public/-/emojis/1/flag_tv.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tw.png b/public/-/emojis/1/flag_tw.png
index 3a8f00b5928..3a8f00b5928 100644
--- a/app/assets/images/emoji/flag_tw.png
+++ b/public/-/emojis/1/flag_tw.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_tz.png b/public/-/emojis/1/flag_tz.png
index 2a020853d4e..2a020853d4e 100644
--- a/app/assets/images/emoji/flag_tz.png
+++ b/public/-/emojis/1/flag_tz.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ua.png b/public/-/emojis/1/flag_ua.png
index cd84d1bbd36..cd84d1bbd36 100644
--- a/app/assets/images/emoji/flag_ua.png
+++ b/public/-/emojis/1/flag_ua.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ug.png b/public/-/emojis/1/flag_ug.png
index dc97690eb55..dc97690eb55 100644
--- a/app/assets/images/emoji/flag_ug.png
+++ b/public/-/emojis/1/flag_ug.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_um.png b/public/-/emojis/1/flag_um.png
index 4a7ee3cdf13..4a7ee3cdf13 100644
--- a/app/assets/images/emoji/flag_um.png
+++ b/public/-/emojis/1/flag_um.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_us.png b/public/-/emojis/1/flag_us.png
index 9f730305860..9f730305860 100644
--- a/app/assets/images/emoji/flag_us.png
+++ b/public/-/emojis/1/flag_us.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_uy.png b/public/-/emojis/1/flag_uy.png
index b8002a697a6..b8002a697a6 100644
--- a/app/assets/images/emoji/flag_uy.png
+++ b/public/-/emojis/1/flag_uy.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_uz.png b/public/-/emojis/1/flag_uz.png
index d56ca9bc424..d56ca9bc424 100644
--- a/app/assets/images/emoji/flag_uz.png
+++ b/public/-/emojis/1/flag_uz.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_va.png b/public/-/emojis/1/flag_va.png
index ddaf5e3141b..ddaf5e3141b 100644
--- a/app/assets/images/emoji/flag_va.png
+++ b/public/-/emojis/1/flag_va.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_vc.png b/public/-/emojis/1/flag_vc.png
index 43703c62a71..43703c62a71 100644
--- a/app/assets/images/emoji/flag_vc.png
+++ b/public/-/emojis/1/flag_vc.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ve.png b/public/-/emojis/1/flag_ve.png
index 1b62796824e..1b62796824e 100644
--- a/app/assets/images/emoji/flag_ve.png
+++ b/public/-/emojis/1/flag_ve.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_vg.png b/public/-/emojis/1/flag_vg.png
index 536f780f1c0..536f780f1c0 100644
--- a/app/assets/images/emoji/flag_vg.png
+++ b/public/-/emojis/1/flag_vg.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_vi.png b/public/-/emojis/1/flag_vi.png
index 64102012cfe..64102012cfe 100644
--- a/app/assets/images/emoji/flag_vi.png
+++ b/public/-/emojis/1/flag_vi.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_vn.png b/public/-/emojis/1/flag_vn.png
index 427036046b6..427036046b6 100644
--- a/app/assets/images/emoji/flag_vn.png
+++ b/public/-/emojis/1/flag_vn.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_vu.png b/public/-/emojis/1/flag_vu.png
index 706eba44070..706eba44070 100644
--- a/app/assets/images/emoji/flag_vu.png
+++ b/public/-/emojis/1/flag_vu.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_wf.png b/public/-/emojis/1/flag_wf.png
index 70c761036bd..70c761036bd 100644
--- a/app/assets/images/emoji/flag_wf.png
+++ b/public/-/emojis/1/flag_wf.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_white.png b/public/-/emojis/1/flag_white.png
index 86d6e96d5e9..86d6e96d5e9 100644
--- a/app/assets/images/emoji/flag_white.png
+++ b/public/-/emojis/1/flag_white.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ws.png b/public/-/emojis/1/flag_ws.png
index a1ea0703141..a1ea0703141 100644
--- a/app/assets/images/emoji/flag_ws.png
+++ b/public/-/emojis/1/flag_ws.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_xk.png b/public/-/emojis/1/flag_xk.png
index e587a446632..e587a446632 100644
--- a/app/assets/images/emoji/flag_xk.png
+++ b/public/-/emojis/1/flag_xk.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_ye.png b/public/-/emojis/1/flag_ye.png
index eadfebd5f67..eadfebd5f67 100644
--- a/app/assets/images/emoji/flag_ye.png
+++ b/public/-/emojis/1/flag_ye.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_yt.png b/public/-/emojis/1/flag_yt.png
index c81fa6d886e..c81fa6d886e 100644
--- a/app/assets/images/emoji/flag_yt.png
+++ b/public/-/emojis/1/flag_yt.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_za.png b/public/-/emojis/1/flag_za.png
index f397ef5072f..f397ef5072f 100644
--- a/app/assets/images/emoji/flag_za.png
+++ b/public/-/emojis/1/flag_za.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_zm.png b/public/-/emojis/1/flag_zm.png
index 2494a31f662..2494a31f662 100644
--- a/app/assets/images/emoji/flag_zm.png
+++ b/public/-/emojis/1/flag_zm.png
Binary files differ
diff --git a/app/assets/images/emoji/flag_zw.png b/public/-/emojis/1/flag_zw.png
index e09b9652be6..e09b9652be6 100644
--- a/app/assets/images/emoji/flag_zw.png
+++ b/public/-/emojis/1/flag_zw.png
Binary files differ
diff --git a/app/assets/images/emoji/flags.png b/public/-/emojis/1/flags.png
index 3b451035a3a..3b451035a3a 100644
--- a/app/assets/images/emoji/flags.png
+++ b/public/-/emojis/1/flags.png
Binary files differ
diff --git a/app/assets/images/emoji/flashlight.png b/public/-/emojis/1/flashlight.png
index eee36c25067..eee36c25067 100644
--- a/app/assets/images/emoji/flashlight.png
+++ b/public/-/emojis/1/flashlight.png
Binary files differ
diff --git a/app/assets/images/emoji/fleur-de-lis.png b/public/-/emojis/1/fleur-de-lis.png
index c9250d27fa7..c9250d27fa7 100644
--- a/app/assets/images/emoji/fleur-de-lis.png
+++ b/public/-/emojis/1/fleur-de-lis.png
Binary files differ
diff --git a/app/assets/images/emoji/floppy_disk.png b/public/-/emojis/1/floppy_disk.png
index 072a76d3c13..072a76d3c13 100644
--- a/app/assets/images/emoji/floppy_disk.png
+++ b/public/-/emojis/1/floppy_disk.png
Binary files differ
diff --git a/app/assets/images/emoji/flower_playing_cards.png b/public/-/emojis/1/flower_playing_cards.png
index 6766b044d95..6766b044d95 100644
--- a/app/assets/images/emoji/flower_playing_cards.png
+++ b/public/-/emojis/1/flower_playing_cards.png
Binary files differ
diff --git a/app/assets/images/emoji/flushed.png b/public/-/emojis/1/flushed.png
index 829220bc470..829220bc470 100644
--- a/app/assets/images/emoji/flushed.png
+++ b/public/-/emojis/1/flushed.png
Binary files differ
diff --git a/app/assets/images/emoji/fog.png b/public/-/emojis/1/fog.png
index 4e73c2de272..4e73c2de272 100644
--- a/app/assets/images/emoji/fog.png
+++ b/public/-/emojis/1/fog.png
Binary files differ
diff --git a/app/assets/images/emoji/foggy.png b/public/-/emojis/1/foggy.png
index 57702d8d3ac..57702d8d3ac 100644
--- a/app/assets/images/emoji/foggy.png
+++ b/public/-/emojis/1/foggy.png
Binary files differ
diff --git a/app/assets/images/emoji/football.png b/public/-/emojis/1/football.png
index 10366f41fce..10366f41fce 100644
--- a/app/assets/images/emoji/football.png
+++ b/public/-/emojis/1/football.png
Binary files differ
diff --git a/app/assets/images/emoji/footprints.png b/public/-/emojis/1/footprints.png
index b2673c5a1a8..b2673c5a1a8 100644
--- a/app/assets/images/emoji/footprints.png
+++ b/public/-/emojis/1/footprints.png
Binary files differ
diff --git a/app/assets/images/emoji/fork_and_knife.png b/public/-/emojis/1/fork_and_knife.png
index 09f1feaea1c..09f1feaea1c 100644
--- a/app/assets/images/emoji/fork_and_knife.png
+++ b/public/-/emojis/1/fork_and_knife.png
Binary files differ
diff --git a/app/assets/images/emoji/fork_knife_plate.png b/public/-/emojis/1/fork_knife_plate.png
index 7411755f708..7411755f708 100644
--- a/app/assets/images/emoji/fork_knife_plate.png
+++ b/public/-/emojis/1/fork_knife_plate.png
Binary files differ
diff --git a/app/assets/images/emoji/fountain.png b/public/-/emojis/1/fountain.png
index 293f5d91c0f..293f5d91c0f 100644
--- a/app/assets/images/emoji/fountain.png
+++ b/public/-/emojis/1/fountain.png
Binary files differ
diff --git a/app/assets/images/emoji/four.png b/public/-/emojis/1/four.png
index b0e914aac45..b0e914aac45 100644
--- a/app/assets/images/emoji/four.png
+++ b/public/-/emojis/1/four.png
Binary files differ
diff --git a/app/assets/images/emoji/four_leaf_clover.png b/public/-/emojis/1/four_leaf_clover.png
index fdedfcc2b4e..fdedfcc2b4e 100644
--- a/app/assets/images/emoji/four_leaf_clover.png
+++ b/public/-/emojis/1/four_leaf_clover.png
Binary files differ
diff --git a/app/assets/images/emoji/fox.png b/public/-/emojis/1/fox.png
index 1ab339bf054..1ab339bf054 100644
--- a/app/assets/images/emoji/fox.png
+++ b/public/-/emojis/1/fox.png
Binary files differ
diff --git a/app/assets/images/emoji/frame_photo.png b/public/-/emojis/1/frame_photo.png
index 9fe84607bfd..9fe84607bfd 100644
--- a/app/assets/images/emoji/frame_photo.png
+++ b/public/-/emojis/1/frame_photo.png
Binary files differ
diff --git a/app/assets/images/emoji/free.png b/public/-/emojis/1/free.png
index b71956eb48a..b71956eb48a 100644
--- a/app/assets/images/emoji/free.png
+++ b/public/-/emojis/1/free.png
Binary files differ
diff --git a/app/assets/images/emoji/french_bread.png b/public/-/emojis/1/french_bread.png
index 4c2c5639822..4c2c5639822 100644
--- a/app/assets/images/emoji/french_bread.png
+++ b/public/-/emojis/1/french_bread.png
Binary files differ
diff --git a/app/assets/images/emoji/fried_shrimp.png b/public/-/emojis/1/fried_shrimp.png
index 752ba7f1398..752ba7f1398 100644
--- a/app/assets/images/emoji/fried_shrimp.png
+++ b/public/-/emojis/1/fried_shrimp.png
Binary files differ
diff --git a/app/assets/images/emoji/fries.png b/public/-/emojis/1/fries.png
index 4e2a4caacef..4e2a4caacef 100644
--- a/app/assets/images/emoji/fries.png
+++ b/public/-/emojis/1/fries.png
Binary files differ
diff --git a/app/assets/images/emoji/frog.png b/public/-/emojis/1/frog.png
index 8825d1ad577..8825d1ad577 100644
--- a/app/assets/images/emoji/frog.png
+++ b/public/-/emojis/1/frog.png
Binary files differ
diff --git a/app/assets/images/emoji/frowning.png b/public/-/emojis/1/frowning.png
index 43ab6b0a1c1..43ab6b0a1c1 100644
--- a/app/assets/images/emoji/frowning.png
+++ b/public/-/emojis/1/frowning.png
Binary files differ
diff --git a/app/assets/images/emoji/frowning2.png b/public/-/emojis/1/frowning2.png
index 6ae71f233b9..6ae71f233b9 100644
--- a/app/assets/images/emoji/frowning2.png
+++ b/public/-/emojis/1/frowning2.png
Binary files differ
diff --git a/app/assets/images/emoji/fuelpump.png b/public/-/emojis/1/fuelpump.png
index 05b18794474..05b18794474 100644
--- a/app/assets/images/emoji/fuelpump.png
+++ b/public/-/emojis/1/fuelpump.png
Binary files differ
diff --git a/app/assets/images/emoji/full_moon.png b/public/-/emojis/1/full_moon.png
index c9a2d6aa7c9..c9a2d6aa7c9 100644
--- a/app/assets/images/emoji/full_moon.png
+++ b/public/-/emojis/1/full_moon.png
Binary files differ
diff --git a/app/assets/images/emoji/full_moon_with_face.png b/public/-/emojis/1/full_moon_with_face.png
index a5c25bbaf64..a5c25bbaf64 100644
--- a/app/assets/images/emoji/full_moon_with_face.png
+++ b/public/-/emojis/1/full_moon_with_face.png
Binary files differ
diff --git a/app/assets/images/emoji/game_die.png b/public/-/emojis/1/game_die.png
index ad3626fe5e5..ad3626fe5e5 100644
--- a/app/assets/images/emoji/game_die.png
+++ b/public/-/emojis/1/game_die.png
Binary files differ
diff --git a/app/assets/images/emoji/gay_pride_flag.png b/public/-/emojis/1/gay_pride_flag.png
index 1bec5f2ffd7..1bec5f2ffd7 100644
--- a/app/assets/images/emoji/gay_pride_flag.png
+++ b/public/-/emojis/1/gay_pride_flag.png
Binary files differ
diff --git a/app/assets/images/emoji/gear.png b/public/-/emojis/1/gear.png
index 2a1cc2c0ff4..2a1cc2c0ff4 100644
--- a/app/assets/images/emoji/gear.png
+++ b/public/-/emojis/1/gear.png
Binary files differ
diff --git a/app/assets/images/emoji/gem.png b/public/-/emojis/1/gem.png
index db122d26a19..db122d26a19 100644
--- a/app/assets/images/emoji/gem.png
+++ b/public/-/emojis/1/gem.png
Binary files differ
diff --git a/app/assets/images/emoji/gemini.png b/public/-/emojis/1/gemini.png
index 1a09698cf00..1a09698cf00 100644
--- a/app/assets/images/emoji/gemini.png
+++ b/public/-/emojis/1/gemini.png
Binary files differ
diff --git a/app/assets/images/emoji/ghost.png b/public/-/emojis/1/ghost.png
index 5650bc0ed18..5650bc0ed18 100644
--- a/app/assets/images/emoji/ghost.png
+++ b/public/-/emojis/1/ghost.png
Binary files differ
diff --git a/app/assets/images/emoji/gift.png b/public/-/emojis/1/gift.png
index 844e2164560..844e2164560 100644
--- a/app/assets/images/emoji/gift.png
+++ b/public/-/emojis/1/gift.png
Binary files differ
diff --git a/app/assets/images/emoji/gift_heart.png b/public/-/emojis/1/gift_heart.png
index 902ceafe4d1..902ceafe4d1 100644
--- a/app/assets/images/emoji/gift_heart.png
+++ b/public/-/emojis/1/gift_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/girl.png b/public/-/emojis/1/girl.png
index dc1d4d08b39..dc1d4d08b39 100644
--- a/app/assets/images/emoji/girl.png
+++ b/public/-/emojis/1/girl.png
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone1.png b/public/-/emojis/1/girl_tone1.png
index bb667e88651..bb667e88651 100644
--- a/app/assets/images/emoji/girl_tone1.png
+++ b/public/-/emojis/1/girl_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone2.png b/public/-/emojis/1/girl_tone2.png
index a59ed4a3f0d..a59ed4a3f0d 100644
--- a/app/assets/images/emoji/girl_tone2.png
+++ b/public/-/emojis/1/girl_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone3.png b/public/-/emojis/1/girl_tone3.png
index 517e7f2a7b0..517e7f2a7b0 100644
--- a/app/assets/images/emoji/girl_tone3.png
+++ b/public/-/emojis/1/girl_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone4.png b/public/-/emojis/1/girl_tone4.png
index 542d96c8487..542d96c8487 100644
--- a/app/assets/images/emoji/girl_tone4.png
+++ b/public/-/emojis/1/girl_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone5.png b/public/-/emojis/1/girl_tone5.png
index 66b7c28c2df..66b7c28c2df 100644
--- a/app/assets/images/emoji/girl_tone5.png
+++ b/public/-/emojis/1/girl_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/globe_with_meridians.png b/public/-/emojis/1/globe_with_meridians.png
index 82450c1a4ba..82450c1a4ba 100644
--- a/app/assets/images/emoji/globe_with_meridians.png
+++ b/public/-/emojis/1/globe_with_meridians.png
Binary files differ
diff --git a/app/assets/images/emoji/goal.png b/public/-/emojis/1/goal.png
index df3a53da0fb..df3a53da0fb 100644
--- a/app/assets/images/emoji/goal.png
+++ b/public/-/emojis/1/goal.png
Binary files differ
diff --git a/app/assets/images/emoji/goat.png b/public/-/emojis/1/goat.png
index f9d9e38a128..f9d9e38a128 100644
--- a/app/assets/images/emoji/goat.png
+++ b/public/-/emojis/1/goat.png
Binary files differ
diff --git a/app/assets/images/emoji/golf.png b/public/-/emojis/1/golf.png
index f65a21d8a46..f65a21d8a46 100644
--- a/app/assets/images/emoji/golf.png
+++ b/public/-/emojis/1/golf.png
Binary files differ
diff --git a/app/assets/images/emoji/golfer.png b/public/-/emojis/1/golfer.png
index 39c552de86d..39c552de86d 100644
--- a/app/assets/images/emoji/golfer.png
+++ b/public/-/emojis/1/golfer.png
Binary files differ
diff --git a/app/assets/images/emoji/gorilla.png b/public/-/emojis/1/gorilla.png
index acc51e13622..acc51e13622 100644
--- a/app/assets/images/emoji/gorilla.png
+++ b/public/-/emojis/1/gorilla.png
Binary files differ
diff --git a/app/assets/images/emoji/grapes.png b/public/-/emojis/1/grapes.png
index 30d22218896..30d22218896 100644
--- a/app/assets/images/emoji/grapes.png
+++ b/public/-/emojis/1/grapes.png
Binary files differ
diff --git a/app/assets/images/emoji/green_apple.png b/public/-/emojis/1/green_apple.png
index 5fd51bd3915..5fd51bd3915 100644
--- a/app/assets/images/emoji/green_apple.png
+++ b/public/-/emojis/1/green_apple.png
Binary files differ
diff --git a/app/assets/images/emoji/green_book.png b/public/-/emojis/1/green_book.png
index e5e411cf3b5..e5e411cf3b5 100644
--- a/app/assets/images/emoji/green_book.png
+++ b/public/-/emojis/1/green_book.png
Binary files differ
diff --git a/app/assets/images/emoji/green_heart.png b/public/-/emojis/1/green_heart.png
index c52d60a58be..c52d60a58be 100644
--- a/app/assets/images/emoji/green_heart.png
+++ b/public/-/emojis/1/green_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/grey_exclamation.png b/public/-/emojis/1/grey_exclamation.png
index 9b64da8bf7f..9b64da8bf7f 100644
--- a/app/assets/images/emoji/grey_exclamation.png
+++ b/public/-/emojis/1/grey_exclamation.png
Binary files differ
diff --git a/app/assets/images/emoji/grey_question.png b/public/-/emojis/1/grey_question.png
index 6e7824c75f6..6e7824c75f6 100644
--- a/app/assets/images/emoji/grey_question.png
+++ b/public/-/emojis/1/grey_question.png
Binary files differ
diff --git a/app/assets/images/emoji/grimacing.png b/public/-/emojis/1/grimacing.png
index 871b2f071c9..871b2f071c9 100644
--- a/app/assets/images/emoji/grimacing.png
+++ b/public/-/emojis/1/grimacing.png
Binary files differ
diff --git a/app/assets/images/emoji/grin.png b/public/-/emojis/1/grin.png
index 418d94c811b..418d94c811b 100644
--- a/app/assets/images/emoji/grin.png
+++ b/public/-/emojis/1/grin.png
Binary files differ
diff --git a/app/assets/images/emoji/grinning.png b/public/-/emojis/1/grinning.png
index 3e8e0dab78c..3e8e0dab78c 100644
--- a/app/assets/images/emoji/grinning.png
+++ b/public/-/emojis/1/grinning.png
Binary files differ
diff --git a/app/assets/images/emoji/guardsman.png b/public/-/emojis/1/guardsman.png
index 8d7ab3c473c..8d7ab3c473c 100644
--- a/app/assets/images/emoji/guardsman.png
+++ b/public/-/emojis/1/guardsman.png
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone1.png b/public/-/emojis/1/guardsman_tone1.png
index cea9ba27468..cea9ba27468 100644
--- a/app/assets/images/emoji/guardsman_tone1.png
+++ b/public/-/emojis/1/guardsman_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone2.png b/public/-/emojis/1/guardsman_tone2.png
index 037464e4028..037464e4028 100644
--- a/app/assets/images/emoji/guardsman_tone2.png
+++ b/public/-/emojis/1/guardsman_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone3.png b/public/-/emojis/1/guardsman_tone3.png
index 0f6726fbe87..0f6726fbe87 100644
--- a/app/assets/images/emoji/guardsman_tone3.png
+++ b/public/-/emojis/1/guardsman_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone4.png b/public/-/emojis/1/guardsman_tone4.png
index 85fcf9a3b97..85fcf9a3b97 100644
--- a/app/assets/images/emoji/guardsman_tone4.png
+++ b/public/-/emojis/1/guardsman_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone5.png b/public/-/emojis/1/guardsman_tone5.png
index e5f9ca7d5a2..e5f9ca7d5a2 100644
--- a/app/assets/images/emoji/guardsman_tone5.png
+++ b/public/-/emojis/1/guardsman_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/guitar.png b/public/-/emojis/1/guitar.png
index 43d752f1e3d..43d752f1e3d 100644
--- a/app/assets/images/emoji/guitar.png
+++ b/public/-/emojis/1/guitar.png
Binary files differ
diff --git a/app/assets/images/emoji/gun.png b/public/-/emojis/1/gun.png
index 89c5c244c7b..89c5c244c7b 100644
--- a/app/assets/images/emoji/gun.png
+++ b/public/-/emojis/1/gun.png
Binary files differ
diff --git a/app/assets/images/emoji/haircut.png b/public/-/emojis/1/haircut.png
index 91266b12930..91266b12930 100644
--- a/app/assets/images/emoji/haircut.png
+++ b/public/-/emojis/1/haircut.png
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone1.png b/public/-/emojis/1/haircut_tone1.png
index c743b74abeb..c743b74abeb 100644
--- a/app/assets/images/emoji/haircut_tone1.png
+++ b/public/-/emojis/1/haircut_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone2.png b/public/-/emojis/1/haircut_tone2.png
index f144f8e55ce..f144f8e55ce 100644
--- a/app/assets/images/emoji/haircut_tone2.png
+++ b/public/-/emojis/1/haircut_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone3.png b/public/-/emojis/1/haircut_tone3.png
index d5ad19563ac..d5ad19563ac 100644
--- a/app/assets/images/emoji/haircut_tone3.png
+++ b/public/-/emojis/1/haircut_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone4.png b/public/-/emojis/1/haircut_tone4.png
index 244fd3af008..244fd3af008 100644
--- a/app/assets/images/emoji/haircut_tone4.png
+++ b/public/-/emojis/1/haircut_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone5.png b/public/-/emojis/1/haircut_tone5.png
index 20a94a88623..20a94a88623 100644
--- a/app/assets/images/emoji/haircut_tone5.png
+++ b/public/-/emojis/1/haircut_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/hamburger.png b/public/-/emojis/1/hamburger.png
index 3573b28a1fd..3573b28a1fd 100644
--- a/app/assets/images/emoji/hamburger.png
+++ b/public/-/emojis/1/hamburger.png
Binary files differ
diff --git a/app/assets/images/emoji/hammer.png b/public/-/emojis/1/hammer.png
index 00736cce47d..00736cce47d 100644
--- a/app/assets/images/emoji/hammer.png
+++ b/public/-/emojis/1/hammer.png
Binary files differ
diff --git a/app/assets/images/emoji/hammer_pick.png b/public/-/emojis/1/hammer_pick.png
index 3bee30ec588..3bee30ec588 100644
--- a/app/assets/images/emoji/hammer_pick.png
+++ b/public/-/emojis/1/hammer_pick.png
Binary files differ
diff --git a/app/assets/images/emoji/hamster.png b/public/-/emojis/1/hamster.png
index 9a04388e4e7..9a04388e4e7 100644
--- a/app/assets/images/emoji/hamster.png
+++ b/public/-/emojis/1/hamster.png
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed.png b/public/-/emojis/1/hand_splayed.png
index fb5ae8ebb5a..fb5ae8ebb5a 100644
--- a/app/assets/images/emoji/hand_splayed.png
+++ b/public/-/emojis/1/hand_splayed.png
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone1.png b/public/-/emojis/1/hand_splayed_tone1.png
index a7888e6bd23..a7888e6bd23 100644
--- a/app/assets/images/emoji/hand_splayed_tone1.png
+++ b/public/-/emojis/1/hand_splayed_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone2.png b/public/-/emojis/1/hand_splayed_tone2.png
index cc10fbc272d..cc10fbc272d 100644
--- a/app/assets/images/emoji/hand_splayed_tone2.png
+++ b/public/-/emojis/1/hand_splayed_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone3.png b/public/-/emojis/1/hand_splayed_tone3.png
index 707236ae8a4..707236ae8a4 100644
--- a/app/assets/images/emoji/hand_splayed_tone3.png
+++ b/public/-/emojis/1/hand_splayed_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone4.png b/public/-/emojis/1/hand_splayed_tone4.png
index 1430df9c61f..1430df9c61f 100644
--- a/app/assets/images/emoji/hand_splayed_tone4.png
+++ b/public/-/emojis/1/hand_splayed_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone5.png b/public/-/emojis/1/hand_splayed_tone5.png
index 80bec971b6b..80bec971b6b 100644
--- a/app/assets/images/emoji/hand_splayed_tone5.png
+++ b/public/-/emojis/1/hand_splayed_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/handbag.png b/public/-/emojis/1/handbag.png
index cbf75c5d25e..cbf75c5d25e 100644
--- a/app/assets/images/emoji/handbag.png
+++ b/public/-/emojis/1/handbag.png
Binary files differ
diff --git a/app/assets/images/emoji/handball.png b/public/-/emojis/1/handball.png
index 1152f1344c7..1152f1344c7 100644
--- a/app/assets/images/emoji/handball.png
+++ b/public/-/emojis/1/handball.png
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone1.png b/public/-/emojis/1/handball_tone1.png
index c26cac2df98..c26cac2df98 100644
--- a/app/assets/images/emoji/handball_tone1.png
+++ b/public/-/emojis/1/handball_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone2.png b/public/-/emojis/1/handball_tone2.png
index 7baaf95a9a2..7baaf95a9a2 100644
--- a/app/assets/images/emoji/handball_tone2.png
+++ b/public/-/emojis/1/handball_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone3.png b/public/-/emojis/1/handball_tone3.png
index 0e3a37c3d40..0e3a37c3d40 100644
--- a/app/assets/images/emoji/handball_tone3.png
+++ b/public/-/emojis/1/handball_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone4.png b/public/-/emojis/1/handball_tone4.png
index e1233f38266..e1233f38266 100644
--- a/app/assets/images/emoji/handball_tone4.png
+++ b/public/-/emojis/1/handball_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone5.png b/public/-/emojis/1/handball_tone5.png
index 6b1eb9b64b0..6b1eb9b64b0 100644
--- a/app/assets/images/emoji/handball_tone5.png
+++ b/public/-/emojis/1/handball_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/handshake.png b/public/-/emojis/1/handshake.png
index c5d35fd8138..c5d35fd8138 100644
--- a/app/assets/images/emoji/handshake.png
+++ b/public/-/emojis/1/handshake.png
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone1.png b/public/-/emojis/1/handshake_tone1.png
index 8f8fbb9bdca..8f8fbb9bdca 100644
--- a/app/assets/images/emoji/handshake_tone1.png
+++ b/public/-/emojis/1/handshake_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone2.png b/public/-/emojis/1/handshake_tone2.png
index 336a77a6d78..336a77a6d78 100644
--- a/app/assets/images/emoji/handshake_tone2.png
+++ b/public/-/emojis/1/handshake_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone3.png b/public/-/emojis/1/handshake_tone3.png
index 95f62d4fecd..95f62d4fecd 100644
--- a/app/assets/images/emoji/handshake_tone3.png
+++ b/public/-/emojis/1/handshake_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone4.png b/public/-/emojis/1/handshake_tone4.png
index 2b0a6433886..2b0a6433886 100644
--- a/app/assets/images/emoji/handshake_tone4.png
+++ b/public/-/emojis/1/handshake_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone5.png b/public/-/emojis/1/handshake_tone5.png
index 40189ee68e4..40189ee68e4 100644
--- a/app/assets/images/emoji/handshake_tone5.png
+++ b/public/-/emojis/1/handshake_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/hash.png b/public/-/emojis/1/hash.png
index 6e26f0070b0..6e26f0070b0 100644
--- a/app/assets/images/emoji/hash.png
+++ b/public/-/emojis/1/hash.png
Binary files differ
diff --git a/app/assets/images/emoji/hatched_chick.png b/public/-/emojis/1/hatched_chick.png
index 31dfb511e0e..31dfb511e0e 100644
--- a/app/assets/images/emoji/hatched_chick.png
+++ b/public/-/emojis/1/hatched_chick.png
Binary files differ
diff --git a/app/assets/images/emoji/hatching_chick.png b/public/-/emojis/1/hatching_chick.png
index c5b0e8f3bcc..c5b0e8f3bcc 100644
--- a/app/assets/images/emoji/hatching_chick.png
+++ b/public/-/emojis/1/hatching_chick.png
Binary files differ
diff --git a/app/assets/images/emoji/head_bandage.png b/public/-/emojis/1/head_bandage.png
index 0be723085e0..0be723085e0 100644
--- a/app/assets/images/emoji/head_bandage.png
+++ b/public/-/emojis/1/head_bandage.png
Binary files differ
diff --git a/app/assets/images/emoji/headphones.png b/public/-/emojis/1/headphones.png
index e9fd34041d8..e9fd34041d8 100644
--- a/app/assets/images/emoji/headphones.png
+++ b/public/-/emojis/1/headphones.png
Binary files differ
diff --git a/app/assets/images/emoji/hear_no_evil.png b/public/-/emojis/1/hear_no_evil.png
index 74b6be0c6c5..74b6be0c6c5 100644
--- a/app/assets/images/emoji/hear_no_evil.png
+++ b/public/-/emojis/1/hear_no_evil.png
Binary files differ
diff --git a/app/assets/images/emoji/heart.png b/public/-/emojis/1/heart.png
index 638cb72dc4e..638cb72dc4e 100644
--- a/app/assets/images/emoji/heart.png
+++ b/public/-/emojis/1/heart.png
Binary files differ
diff --git a/app/assets/images/emoji/heart_decoration.png b/public/-/emojis/1/heart_decoration.png
index 5443f60bc63..5443f60bc63 100644
--- a/app/assets/images/emoji/heart_decoration.png
+++ b/public/-/emojis/1/heart_decoration.png
Binary files differ
diff --git a/app/assets/images/emoji/heart_exclamation.png b/public/-/emojis/1/heart_exclamation.png
index 91b520be40b..91b520be40b 100644
--- a/app/assets/images/emoji/heart_exclamation.png
+++ b/public/-/emojis/1/heart_exclamation.png
Binary files differ
diff --git a/app/assets/images/emoji/heart_eyes.png b/public/-/emojis/1/heart_eyes.png
index 73fbee29d4e..73fbee29d4e 100644
--- a/app/assets/images/emoji/heart_eyes.png
+++ b/public/-/emojis/1/heart_eyes.png
Binary files differ
diff --git a/app/assets/images/emoji/heart_eyes_cat.png b/public/-/emojis/1/heart_eyes_cat.png
index bc5a833f9a1..bc5a833f9a1 100644
--- a/app/assets/images/emoji/heart_eyes_cat.png
+++ b/public/-/emojis/1/heart_eyes_cat.png
Binary files differ
diff --git a/app/assets/images/emoji/heartbeat.png b/public/-/emojis/1/heartbeat.png
index 0bcf2d1d567..0bcf2d1d567 100644
--- a/app/assets/images/emoji/heartbeat.png
+++ b/public/-/emojis/1/heartbeat.png
Binary files differ
diff --git a/app/assets/images/emoji/heartpulse.png b/public/-/emojis/1/heartpulse.png
index d6e694e972f..d6e694e972f 100644
--- a/app/assets/images/emoji/heartpulse.png
+++ b/public/-/emojis/1/heartpulse.png
Binary files differ
diff --git a/app/assets/images/emoji/hearts.png b/public/-/emojis/1/hearts.png
index 393c3ed5267..393c3ed5267 100644
--- a/app/assets/images/emoji/hearts.png
+++ b/public/-/emojis/1/hearts.png
Binary files differ
diff --git a/app/assets/images/emoji/heavy_check_mark.png b/public/-/emojis/1/heavy_check_mark.png
index 03bd695377e..03bd695377e 100644
--- a/app/assets/images/emoji/heavy_check_mark.png
+++ b/public/-/emojis/1/heavy_check_mark.png
Binary files differ
diff --git a/app/assets/images/emoji/heavy_division_sign.png b/public/-/emojis/1/heavy_division_sign.png
index df32ab21bea..df32ab21bea 100644
--- a/app/assets/images/emoji/heavy_division_sign.png
+++ b/public/-/emojis/1/heavy_division_sign.png
Binary files differ
diff --git a/app/assets/images/emoji/heavy_dollar_sign.png b/public/-/emojis/1/heavy_dollar_sign.png
index ef2c2e20590..ef2c2e20590 100644
--- a/app/assets/images/emoji/heavy_dollar_sign.png
+++ b/public/-/emojis/1/heavy_dollar_sign.png
Binary files differ
diff --git a/app/assets/images/emoji/heavy_minus_sign.png b/public/-/emojis/1/heavy_minus_sign.png
index 054211caf12..054211caf12 100644
--- a/app/assets/images/emoji/heavy_minus_sign.png
+++ b/public/-/emojis/1/heavy_minus_sign.png
Binary files differ
diff --git a/app/assets/images/emoji/heavy_multiplication_x.png b/public/-/emojis/1/heavy_multiplication_x.png
index e47cc1b685d..e47cc1b685d 100644
--- a/app/assets/images/emoji/heavy_multiplication_x.png
+++ b/public/-/emojis/1/heavy_multiplication_x.png
Binary files differ
diff --git a/app/assets/images/emoji/heavy_plus_sign.png b/public/-/emojis/1/heavy_plus_sign.png
index 40799798aaf..40799798aaf 100644
--- a/app/assets/images/emoji/heavy_plus_sign.png
+++ b/public/-/emojis/1/heavy_plus_sign.png
Binary files differ
diff --git a/app/assets/images/emoji/helicopter.png b/public/-/emojis/1/helicopter.png
index 7ec5f39a51a..7ec5f39a51a 100644
--- a/app/assets/images/emoji/helicopter.png
+++ b/public/-/emojis/1/helicopter.png
Binary files differ
diff --git a/app/assets/images/emoji/helmet_with_cross.png b/public/-/emojis/1/helmet_with_cross.png
index 7140a676038..7140a676038 100644
--- a/app/assets/images/emoji/helmet_with_cross.png
+++ b/public/-/emojis/1/helmet_with_cross.png
Binary files differ
diff --git a/app/assets/images/emoji/herb.png b/public/-/emojis/1/herb.png
index d984d1562bb..d984d1562bb 100644
--- a/app/assets/images/emoji/herb.png
+++ b/public/-/emojis/1/herb.png
Binary files differ
diff --git a/app/assets/images/emoji/hibiscus.png b/public/-/emojis/1/hibiscus.png
index 39dd3524233..39dd3524233 100644
--- a/app/assets/images/emoji/hibiscus.png
+++ b/public/-/emojis/1/hibiscus.png
Binary files differ
diff --git a/app/assets/images/emoji/high_brightness.png b/public/-/emojis/1/high_brightness.png
index c41f2d5fd50..c41f2d5fd50 100644
--- a/app/assets/images/emoji/high_brightness.png
+++ b/public/-/emojis/1/high_brightness.png
Binary files differ
diff --git a/app/assets/images/emoji/high_heel.png b/public/-/emojis/1/high_heel.png
index b331cbccc9d..b331cbccc9d 100644
--- a/app/assets/images/emoji/high_heel.png
+++ b/public/-/emojis/1/high_heel.png
Binary files differ
diff --git a/app/assets/images/emoji/hockey.png b/public/-/emojis/1/hockey.png
index be94e9cbf73..be94e9cbf73 100644
--- a/app/assets/images/emoji/hockey.png
+++ b/public/-/emojis/1/hockey.png
Binary files differ
diff --git a/app/assets/images/emoji/hole.png b/public/-/emojis/1/hole.png
index 517d2ae0deb..517d2ae0deb 100644
--- a/app/assets/images/emoji/hole.png
+++ b/public/-/emojis/1/hole.png
Binary files differ
diff --git a/app/assets/images/emoji/homes.png b/public/-/emojis/1/homes.png
index 6ab4a2a2651..6ab4a2a2651 100644
--- a/app/assets/images/emoji/homes.png
+++ b/public/-/emojis/1/homes.png
Binary files differ
diff --git a/app/assets/images/emoji/honey_pot.png b/public/-/emojis/1/honey_pot.png
index 9d8f592955e..9d8f592955e 100644
--- a/app/assets/images/emoji/honey_pot.png
+++ b/public/-/emojis/1/honey_pot.png
Binary files differ
diff --git a/app/assets/images/emoji/horse.png b/public/-/emojis/1/horse.png
index 7cb1172f4e4..7cb1172f4e4 100644
--- a/app/assets/images/emoji/horse.png
+++ b/public/-/emojis/1/horse.png
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing.png b/public/-/emojis/1/horse_racing.png
index addf9edac56..addf9edac56 100644
--- a/app/assets/images/emoji/horse_racing.png
+++ b/public/-/emojis/1/horse_racing.png
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone1.png b/public/-/emojis/1/horse_racing_tone1.png
index e9bf4092e98..e9bf4092e98 100644
--- a/app/assets/images/emoji/horse_racing_tone1.png
+++ b/public/-/emojis/1/horse_racing_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone2.png b/public/-/emojis/1/horse_racing_tone2.png
index 031bbc3d867..031bbc3d867 100644
--- a/app/assets/images/emoji/horse_racing_tone2.png
+++ b/public/-/emojis/1/horse_racing_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone3.png b/public/-/emojis/1/horse_racing_tone3.png
index b40ef891f9b..b40ef891f9b 100644
--- a/app/assets/images/emoji/horse_racing_tone3.png
+++ b/public/-/emojis/1/horse_racing_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone4.png b/public/-/emojis/1/horse_racing_tone4.png
index e286cb85065..e286cb85065 100644
--- a/app/assets/images/emoji/horse_racing_tone4.png
+++ b/public/-/emojis/1/horse_racing_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone5.png b/public/-/emojis/1/horse_racing_tone5.png
index 453c51c6007..453c51c6007 100644
--- a/app/assets/images/emoji/horse_racing_tone5.png
+++ b/public/-/emojis/1/horse_racing_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/hospital.png b/public/-/emojis/1/hospital.png
index 1cbce4ae767..1cbce4ae767 100644
--- a/app/assets/images/emoji/hospital.png
+++ b/public/-/emojis/1/hospital.png
Binary files differ
diff --git a/app/assets/images/emoji/hot_pepper.png b/public/-/emojis/1/hot_pepper.png
index 266675bd577..266675bd577 100644
--- a/app/assets/images/emoji/hot_pepper.png
+++ b/public/-/emojis/1/hot_pepper.png
Binary files differ
diff --git a/app/assets/images/emoji/hotdog.png b/public/-/emojis/1/hotdog.png
index 3c3354d94cb..3c3354d94cb 100644
--- a/app/assets/images/emoji/hotdog.png
+++ b/public/-/emojis/1/hotdog.png
Binary files differ
diff --git a/app/assets/images/emoji/hotel.png b/public/-/emojis/1/hotel.png
index ea8f4c4979a..ea8f4c4979a 100644
--- a/app/assets/images/emoji/hotel.png
+++ b/public/-/emojis/1/hotel.png
Binary files differ
diff --git a/app/assets/images/emoji/hotsprings.png b/public/-/emojis/1/hotsprings.png
index 3d9df2d9475..3d9df2d9475 100644
--- a/app/assets/images/emoji/hotsprings.png
+++ b/public/-/emojis/1/hotsprings.png
Binary files differ
diff --git a/app/assets/images/emoji/hourglass.png b/public/-/emojis/1/hourglass.png
index a5db2d1d3f4..a5db2d1d3f4 100644
--- a/app/assets/images/emoji/hourglass.png
+++ b/public/-/emojis/1/hourglass.png
Binary files differ
diff --git a/app/assets/images/emoji/hourglass_flowing_sand.png b/public/-/emojis/1/hourglass_flowing_sand.png
index b93b15ed6d8..b93b15ed6d8 100644
--- a/app/assets/images/emoji/hourglass_flowing_sand.png
+++ b/public/-/emojis/1/hourglass_flowing_sand.png
Binary files differ
diff --git a/app/assets/images/emoji/house.png b/public/-/emojis/1/house.png
index 01c98a0ba92..01c98a0ba92 100644
--- a/app/assets/images/emoji/house.png
+++ b/public/-/emojis/1/house.png
Binary files differ
diff --git a/app/assets/images/emoji/house_abandoned.png b/public/-/emojis/1/house_abandoned.png
index c55e81de990..c55e81de990 100644
--- a/app/assets/images/emoji/house_abandoned.png
+++ b/public/-/emojis/1/house_abandoned.png
Binary files differ
diff --git a/app/assets/images/emoji/house_with_garden.png b/public/-/emojis/1/house_with_garden.png
index 0aae41598ef..0aae41598ef 100644
--- a/app/assets/images/emoji/house_with_garden.png
+++ b/public/-/emojis/1/house_with_garden.png
Binary files differ
diff --git a/app/assets/images/emoji/hugging.png b/public/-/emojis/1/hugging.png
index 5bba6dc6d51..5bba6dc6d51 100644
--- a/app/assets/images/emoji/hugging.png
+++ b/public/-/emojis/1/hugging.png
Binary files differ
diff --git a/app/assets/images/emoji/hushed.png b/public/-/emojis/1/hushed.png
index cad0e23132e..cad0e23132e 100644
--- a/app/assets/images/emoji/hushed.png
+++ b/public/-/emojis/1/hushed.png
Binary files differ
diff --git a/app/assets/images/emoji/ice_cream.png b/public/-/emojis/1/ice_cream.png
index 94267b9c434..94267b9c434 100644
--- a/app/assets/images/emoji/ice_cream.png
+++ b/public/-/emojis/1/ice_cream.png
Binary files differ
diff --git a/app/assets/images/emoji/ice_skate.png b/public/-/emojis/1/ice_skate.png
index 8c449b0c039..8c449b0c039 100644
--- a/app/assets/images/emoji/ice_skate.png
+++ b/public/-/emojis/1/ice_skate.png
Binary files differ
diff --git a/app/assets/images/emoji/icecream.png b/public/-/emojis/1/icecream.png
index 8f6546e31a5..8f6546e31a5 100644
--- a/app/assets/images/emoji/icecream.png
+++ b/public/-/emojis/1/icecream.png
Binary files differ
diff --git a/app/assets/images/emoji/id.png b/public/-/emojis/1/id.png
index 5bf69bf7ba8..5bf69bf7ba8 100644
--- a/app/assets/images/emoji/id.png
+++ b/public/-/emojis/1/id.png
Binary files differ
diff --git a/app/assets/images/emoji/ideograph_advantage.png b/public/-/emojis/1/ideograph_advantage.png
index 0c0d589caf0..0c0d589caf0 100644
--- a/app/assets/images/emoji/ideograph_advantage.png
+++ b/public/-/emojis/1/ideograph_advantage.png
Binary files differ
diff --git a/app/assets/images/emoji/imp.png b/public/-/emojis/1/imp.png
index 9f9a9605539..9f9a9605539 100644
--- a/app/assets/images/emoji/imp.png
+++ b/public/-/emojis/1/imp.png
Binary files differ
diff --git a/app/assets/images/emoji/inbox_tray.png b/public/-/emojis/1/inbox_tray.png
index 41a6be2b0ee..41a6be2b0ee 100644
--- a/app/assets/images/emoji/inbox_tray.png
+++ b/public/-/emojis/1/inbox_tray.png
Binary files differ
diff --git a/app/assets/images/emoji/incoming_envelope.png b/public/-/emojis/1/incoming_envelope.png
index fd22e88182e..fd22e88182e 100644
--- a/app/assets/images/emoji/incoming_envelope.png
+++ b/public/-/emojis/1/incoming_envelope.png
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person.png b/public/-/emojis/1/information_desk_person.png
index 55fc6294d25..55fc6294d25 100644
--- a/app/assets/images/emoji/information_desk_person.png
+++ b/public/-/emojis/1/information_desk_person.png
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone1.png b/public/-/emojis/1/information_desk_person_tone1.png
index 3d9e2247940..3d9e2247940 100644
--- a/app/assets/images/emoji/information_desk_person_tone1.png
+++ b/public/-/emojis/1/information_desk_person_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone2.png b/public/-/emojis/1/information_desk_person_tone2.png
index 879e8b7966d..879e8b7966d 100644
--- a/app/assets/images/emoji/information_desk_person_tone2.png
+++ b/public/-/emojis/1/information_desk_person_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone3.png b/public/-/emojis/1/information_desk_person_tone3.png
index 307514eab67..307514eab67 100644
--- a/app/assets/images/emoji/information_desk_person_tone3.png
+++ b/public/-/emojis/1/information_desk_person_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone4.png b/public/-/emojis/1/information_desk_person_tone4.png
index 297395dcb3f..297395dcb3f 100644
--- a/app/assets/images/emoji/information_desk_person_tone4.png
+++ b/public/-/emojis/1/information_desk_person_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone5.png b/public/-/emojis/1/information_desk_person_tone5.png
index 26f8f22b28b..26f8f22b28b 100644
--- a/app/assets/images/emoji/information_desk_person_tone5.png
+++ b/public/-/emojis/1/information_desk_person_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/information_source.png b/public/-/emojis/1/information_source.png
index 871f2db9314..871f2db9314 100644
--- a/app/assets/images/emoji/information_source.png
+++ b/public/-/emojis/1/information_source.png
Binary files differ
diff --git a/app/assets/images/emoji/innocent.png b/public/-/emojis/1/innocent.png
index 57f5151124f..57f5151124f 100644
--- a/app/assets/images/emoji/innocent.png
+++ b/public/-/emojis/1/innocent.png
Binary files differ
diff --git a/app/assets/images/emoji/interrobang.png b/public/-/emojis/1/interrobang.png
index 509813e9bb2..509813e9bb2 100644
--- a/app/assets/images/emoji/interrobang.png
+++ b/public/-/emojis/1/interrobang.png
Binary files differ
diff --git a/app/assets/images/emoji/iphone.png b/public/-/emojis/1/iphone.png
index fd377acf872..fd377acf872 100644
--- a/app/assets/images/emoji/iphone.png
+++ b/public/-/emojis/1/iphone.png
Binary files differ
diff --git a/app/assets/images/emoji/island.png b/public/-/emojis/1/island.png
index 7fd834389b7..7fd834389b7 100644
--- a/app/assets/images/emoji/island.png
+++ b/public/-/emojis/1/island.png
Binary files differ
diff --git a/app/assets/images/emoji/izakaya_lantern.png b/public/-/emojis/1/izakaya_lantern.png
index dfd933f6f36..dfd933f6f36 100644
--- a/app/assets/images/emoji/izakaya_lantern.png
+++ b/public/-/emojis/1/izakaya_lantern.png
Binary files differ
diff --git a/app/assets/images/emoji/jack_o_lantern.png b/public/-/emojis/1/jack_o_lantern.png
index 44c3fc0aec9..44c3fc0aec9 100644
--- a/app/assets/images/emoji/jack_o_lantern.png
+++ b/public/-/emojis/1/jack_o_lantern.png
Binary files differ
diff --git a/app/assets/images/emoji/japan.png b/public/-/emojis/1/japan.png
index d86d0a59e12..d86d0a59e12 100644
--- a/app/assets/images/emoji/japan.png
+++ b/public/-/emojis/1/japan.png
Binary files differ
diff --git a/app/assets/images/emoji/japanese_castle.png b/public/-/emojis/1/japanese_castle.png
index 64b4e33a1ae..64b4e33a1ae 100644
--- a/app/assets/images/emoji/japanese_castle.png
+++ b/public/-/emojis/1/japanese_castle.png
Binary files differ
diff --git a/app/assets/images/emoji/japanese_goblin.png b/public/-/emojis/1/japanese_goblin.png
index 515c6a2250e..515c6a2250e 100644
--- a/app/assets/images/emoji/japanese_goblin.png
+++ b/public/-/emojis/1/japanese_goblin.png
Binary files differ
diff --git a/app/assets/images/emoji/japanese_ogre.png b/public/-/emojis/1/japanese_ogre.png
index fe8670fdaf1..fe8670fdaf1 100644
--- a/app/assets/images/emoji/japanese_ogre.png
+++ b/public/-/emojis/1/japanese_ogre.png
Binary files differ
diff --git a/app/assets/images/emoji/jeans.png b/public/-/emojis/1/jeans.png
index 2a6869d674c..2a6869d674c 100644
--- a/app/assets/images/emoji/jeans.png
+++ b/public/-/emojis/1/jeans.png
Binary files differ
diff --git a/app/assets/images/emoji/joy.png b/public/-/emojis/1/joy.png
index 0ba3b1859d8..0ba3b1859d8 100644
--- a/app/assets/images/emoji/joy.png
+++ b/public/-/emojis/1/joy.png
Binary files differ
diff --git a/app/assets/images/emoji/joy_cat.png b/public/-/emojis/1/joy_cat.png
index aac353179aa..aac353179aa 100644
--- a/app/assets/images/emoji/joy_cat.png
+++ b/public/-/emojis/1/joy_cat.png
Binary files differ
diff --git a/app/assets/images/emoji/joystick.png b/public/-/emojis/1/joystick.png
index 1ee1905434e..1ee1905434e 100644
--- a/app/assets/images/emoji/joystick.png
+++ b/public/-/emojis/1/joystick.png
Binary files differ
diff --git a/app/assets/images/emoji/juggling.png b/public/-/emojis/1/juggling.png
index a37f6224a42..a37f6224a42 100644
--- a/app/assets/images/emoji/juggling.png
+++ b/public/-/emojis/1/juggling.png
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone1.png b/public/-/emojis/1/juggling_tone1.png
index c18eda40031..c18eda40031 100644
--- a/app/assets/images/emoji/juggling_tone1.png
+++ b/public/-/emojis/1/juggling_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone2.png b/public/-/emojis/1/juggling_tone2.png
index de3b7a555b6..de3b7a555b6 100644
--- a/app/assets/images/emoji/juggling_tone2.png
+++ b/public/-/emojis/1/juggling_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone3.png b/public/-/emojis/1/juggling_tone3.png
index 74ab6d85458..74ab6d85458 100644
--- a/app/assets/images/emoji/juggling_tone3.png
+++ b/public/-/emojis/1/juggling_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone4.png b/public/-/emojis/1/juggling_tone4.png
index 1c57823203f..1c57823203f 100644
--- a/app/assets/images/emoji/juggling_tone4.png
+++ b/public/-/emojis/1/juggling_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone5.png b/public/-/emojis/1/juggling_tone5.png
index c343d6ee98a..c343d6ee98a 100644
--- a/app/assets/images/emoji/juggling_tone5.png
+++ b/public/-/emojis/1/juggling_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/kaaba.png b/public/-/emojis/1/kaaba.png
index 1778c1138e4..1778c1138e4 100644
--- a/app/assets/images/emoji/kaaba.png
+++ b/public/-/emojis/1/kaaba.png
Binary files differ
diff --git a/app/assets/images/emoji/key.png b/public/-/emojis/1/key.png
index 319cd1b884c..319cd1b884c 100644
--- a/app/assets/images/emoji/key.png
+++ b/public/-/emojis/1/key.png
Binary files differ
diff --git a/app/assets/images/emoji/key2.png b/public/-/emojis/1/key2.png
index e11d706c6c8..e11d706c6c8 100644
--- a/app/assets/images/emoji/key2.png
+++ b/public/-/emojis/1/key2.png
Binary files differ
diff --git a/app/assets/images/emoji/keyboard.png b/public/-/emojis/1/keyboard.png
index 75027cb9af7..75027cb9af7 100644
--- a/app/assets/images/emoji/keyboard.png
+++ b/public/-/emojis/1/keyboard.png
Binary files differ
diff --git a/app/assets/images/emoji/kimono.png b/public/-/emojis/1/kimono.png
index abe851115d1..abe851115d1 100644
--- a/app/assets/images/emoji/kimono.png
+++ b/public/-/emojis/1/kimono.png
Binary files differ
diff --git a/app/assets/images/emoji/kiss.png b/public/-/emojis/1/kiss.png
index 85e6dcfc4e8..85e6dcfc4e8 100644
--- a/app/assets/images/emoji/kiss.png
+++ b/public/-/emojis/1/kiss.png
Binary files differ
diff --git a/app/assets/images/emoji/kiss_mm.png b/public/-/emojis/1/kiss_mm.png
index a9a0edae17c..a9a0edae17c 100644
--- a/app/assets/images/emoji/kiss_mm.png
+++ b/public/-/emojis/1/kiss_mm.png
Binary files differ
diff --git a/app/assets/images/emoji/kiss_ww.png b/public/-/emojis/1/kiss_ww.png
index fdac73cbb1d..fdac73cbb1d 100644
--- a/app/assets/images/emoji/kiss_ww.png
+++ b/public/-/emojis/1/kiss_ww.png
Binary files differ
diff --git a/app/assets/images/emoji/kissing.png b/public/-/emojis/1/kissing.png
index 39d325fd8e3..39d325fd8e3 100644
--- a/app/assets/images/emoji/kissing.png
+++ b/public/-/emojis/1/kissing.png
Binary files differ
diff --git a/app/assets/images/emoji/kissing_cat.png b/public/-/emojis/1/kissing_cat.png
index 6e0bcc77540..6e0bcc77540 100644
--- a/app/assets/images/emoji/kissing_cat.png
+++ b/public/-/emojis/1/kissing_cat.png
Binary files differ
diff --git a/app/assets/images/emoji/kissing_closed_eyes.png b/public/-/emojis/1/kissing_closed_eyes.png
index b684d7d4d6c..b684d7d4d6c 100644
--- a/app/assets/images/emoji/kissing_closed_eyes.png
+++ b/public/-/emojis/1/kissing_closed_eyes.png
Binary files differ
diff --git a/app/assets/images/emoji/kissing_heart.png b/public/-/emojis/1/kissing_heart.png
index 0ff808fd614..0ff808fd614 100644
--- a/app/assets/images/emoji/kissing_heart.png
+++ b/public/-/emojis/1/kissing_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/kissing_smiling_eyes.png b/public/-/emojis/1/kissing_smiling_eyes.png
index e181f17099d..e181f17099d 100644
--- a/app/assets/images/emoji/kissing_smiling_eyes.png
+++ b/public/-/emojis/1/kissing_smiling_eyes.png
Binary files differ
diff --git a/app/assets/images/emoji/kiwi.png b/public/-/emojis/1/kiwi.png
index dfbd8258074..dfbd8258074 100644
--- a/app/assets/images/emoji/kiwi.png
+++ b/public/-/emojis/1/kiwi.png
Binary files differ
diff --git a/app/assets/images/emoji/knife.png b/public/-/emojis/1/knife.png
index 1acb9f3077b..1acb9f3077b 100644
--- a/app/assets/images/emoji/knife.png
+++ b/public/-/emojis/1/knife.png
Binary files differ
diff --git a/app/assets/images/emoji/koala.png b/public/-/emojis/1/koala.png
index a0aa437a98c..a0aa437a98c 100644
--- a/app/assets/images/emoji/koala.png
+++ b/public/-/emojis/1/koala.png
Binary files differ
diff --git a/app/assets/images/emoji/koko.png b/public/-/emojis/1/koko.png
index 6450eb44d90..6450eb44d90 100644
--- a/app/assets/images/emoji/koko.png
+++ b/public/-/emojis/1/koko.png
Binary files differ
diff --git a/app/assets/images/emoji/label.png b/public/-/emojis/1/label.png
index d41c9b4f1e1..d41c9b4f1e1 100644
--- a/app/assets/images/emoji/label.png
+++ b/public/-/emojis/1/label.png
Binary files differ
diff --git a/app/assets/images/emoji/large_blue_circle.png b/public/-/emojis/1/large_blue_circle.png
index 84078ef3127..84078ef3127 100644
--- a/app/assets/images/emoji/large_blue_circle.png
+++ b/public/-/emojis/1/large_blue_circle.png
Binary files differ
diff --git a/app/assets/images/emoji/large_blue_diamond.png b/public/-/emojis/1/large_blue_diamond.png
index 416a58bd5a8..416a58bd5a8 100644
--- a/app/assets/images/emoji/large_blue_diamond.png
+++ b/public/-/emojis/1/large_blue_diamond.png
Binary files differ
diff --git a/app/assets/images/emoji/large_orange_diamond.png b/public/-/emojis/1/large_orange_diamond.png
index 73ff0ac36c8..73ff0ac36c8 100644
--- a/app/assets/images/emoji/large_orange_diamond.png
+++ b/public/-/emojis/1/large_orange_diamond.png
Binary files differ
diff --git a/app/assets/images/emoji/last_quarter_moon.png b/public/-/emojis/1/last_quarter_moon.png
index 0842a0dd408..0842a0dd408 100644
--- a/app/assets/images/emoji/last_quarter_moon.png
+++ b/public/-/emojis/1/last_quarter_moon.png
Binary files differ
diff --git a/app/assets/images/emoji/last_quarter_moon_with_face.png b/public/-/emojis/1/last_quarter_moon_with_face.png
index 94099343c5d..94099343c5d 100644
--- a/app/assets/images/emoji/last_quarter_moon_with_face.png
+++ b/public/-/emojis/1/last_quarter_moon_with_face.png
Binary files differ
diff --git a/app/assets/images/emoji/laughing.png b/public/-/emojis/1/laughing.png
index d94e9505ba1..d94e9505ba1 100644
--- a/app/assets/images/emoji/laughing.png
+++ b/public/-/emojis/1/laughing.png
Binary files differ
diff --git a/app/assets/images/emoji/leaves.png b/public/-/emojis/1/leaves.png
index 1e43e1af820..1e43e1af820 100644
--- a/app/assets/images/emoji/leaves.png
+++ b/public/-/emojis/1/leaves.png
Binary files differ
diff --git a/app/assets/images/emoji/ledger.png b/public/-/emojis/1/ledger.png
index 13e7561a4bd..13e7561a4bd 100644
--- a/app/assets/images/emoji/ledger.png
+++ b/public/-/emojis/1/ledger.png
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist.png b/public/-/emojis/1/left_facing_fist.png
index a9d9fd8d59c..a9d9fd8d59c 100644
--- a/app/assets/images/emoji/left_facing_fist.png
+++ b/public/-/emojis/1/left_facing_fist.png
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone1.png b/public/-/emojis/1/left_facing_fist_tone1.png
index 1262a6b4b69..1262a6b4b69 100644
--- a/app/assets/images/emoji/left_facing_fist_tone1.png
+++ b/public/-/emojis/1/left_facing_fist_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone2.png b/public/-/emojis/1/left_facing_fist_tone2.png
index 40bf70b82b2..40bf70b82b2 100644
--- a/app/assets/images/emoji/left_facing_fist_tone2.png
+++ b/public/-/emojis/1/left_facing_fist_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone3.png b/public/-/emojis/1/left_facing_fist_tone3.png
index 93f58145111..93f58145111 100644
--- a/app/assets/images/emoji/left_facing_fist_tone3.png
+++ b/public/-/emojis/1/left_facing_fist_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone4.png b/public/-/emojis/1/left_facing_fist_tone4.png
index d82b5ec91f0..d82b5ec91f0 100644
--- a/app/assets/images/emoji/left_facing_fist_tone4.png
+++ b/public/-/emojis/1/left_facing_fist_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone5.png b/public/-/emojis/1/left_facing_fist_tone5.png
index 09ae4cd492b..09ae4cd492b 100644
--- a/app/assets/images/emoji/left_facing_fist_tone5.png
+++ b/public/-/emojis/1/left_facing_fist_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/left_luggage.png b/public/-/emojis/1/left_luggage.png
index 887b23f3f25..887b23f3f25 100644
--- a/app/assets/images/emoji/left_luggage.png
+++ b/public/-/emojis/1/left_luggage.png
Binary files differ
diff --git a/app/assets/images/emoji/left_right_arrow.png b/public/-/emojis/1/left_right_arrow.png
index 7937f24f2ac..7937f24f2ac 100644
--- a/app/assets/images/emoji/left_right_arrow.png
+++ b/public/-/emojis/1/left_right_arrow.png
Binary files differ
diff --git a/app/assets/images/emoji/leftwards_arrow_with_hook.png b/public/-/emojis/1/leftwards_arrow_with_hook.png
index ba45c2ad9e9..ba45c2ad9e9 100644
--- a/app/assets/images/emoji/leftwards_arrow_with_hook.png
+++ b/public/-/emojis/1/leftwards_arrow_with_hook.png
Binary files differ
diff --git a/app/assets/images/emoji/lemon.png b/public/-/emojis/1/lemon.png
index 9a7d95ca220..9a7d95ca220 100644
--- a/app/assets/images/emoji/lemon.png
+++ b/public/-/emojis/1/lemon.png
Binary files differ
diff --git a/app/assets/images/emoji/leo.png b/public/-/emojis/1/leo.png
index 30158d34de9..30158d34de9 100644
--- a/app/assets/images/emoji/leo.png
+++ b/public/-/emojis/1/leo.png
Binary files differ
diff --git a/app/assets/images/emoji/leopard.png b/public/-/emojis/1/leopard.png
index 8aac3d49448..8aac3d49448 100644
--- a/app/assets/images/emoji/leopard.png
+++ b/public/-/emojis/1/leopard.png
Binary files differ
diff --git a/app/assets/images/emoji/level_slider.png b/public/-/emojis/1/level_slider.png
index 720a3b34119..720a3b34119 100644
--- a/app/assets/images/emoji/level_slider.png
+++ b/public/-/emojis/1/level_slider.png
Binary files differ
diff --git a/app/assets/images/emoji/levitate.png b/public/-/emojis/1/levitate.png
index 3dc315a3d91..3dc315a3d91 100644
--- a/app/assets/images/emoji/levitate.png
+++ b/public/-/emojis/1/levitate.png
Binary files differ
diff --git a/app/assets/images/emoji/libra.png b/public/-/emojis/1/libra.png
index 8fd133a357c..8fd133a357c 100644
--- a/app/assets/images/emoji/libra.png
+++ b/public/-/emojis/1/libra.png
Binary files differ
diff --git a/app/assets/images/emoji/lifter.png b/public/-/emojis/1/lifter.png
index afdeaa476af..afdeaa476af 100644
--- a/app/assets/images/emoji/lifter.png
+++ b/public/-/emojis/1/lifter.png
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone1.png b/public/-/emojis/1/lifter_tone1.png
index febaad123ec..febaad123ec 100644
--- a/app/assets/images/emoji/lifter_tone1.png
+++ b/public/-/emojis/1/lifter_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone2.png b/public/-/emojis/1/lifter_tone2.png
index 27ae794a18e..27ae794a18e 100644
--- a/app/assets/images/emoji/lifter_tone2.png
+++ b/public/-/emojis/1/lifter_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone3.png b/public/-/emojis/1/lifter_tone3.png
index 45c4c22c709..45c4c22c709 100644
--- a/app/assets/images/emoji/lifter_tone3.png
+++ b/public/-/emojis/1/lifter_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone4.png b/public/-/emojis/1/lifter_tone4.png
index 67dd21d2464..67dd21d2464 100644
--- a/app/assets/images/emoji/lifter_tone4.png
+++ b/public/-/emojis/1/lifter_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone5.png b/public/-/emojis/1/lifter_tone5.png
index fa0152038b6..fa0152038b6 100644
--- a/app/assets/images/emoji/lifter_tone5.png
+++ b/public/-/emojis/1/lifter_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/light_rail.png b/public/-/emojis/1/light_rail.png
index a64829f5078..a64829f5078 100644
--- a/app/assets/images/emoji/light_rail.png
+++ b/public/-/emojis/1/light_rail.png
Binary files differ
diff --git a/app/assets/images/emoji/link.png b/public/-/emojis/1/link.png
index ae20f0f8eec..ae20f0f8eec 100644
--- a/app/assets/images/emoji/link.png
+++ b/public/-/emojis/1/link.png
Binary files differ
diff --git a/app/assets/images/emoji/lion_face.png b/public/-/emojis/1/lion_face.png
index 5062ab47ecf..5062ab47ecf 100644
--- a/app/assets/images/emoji/lion_face.png
+++ b/public/-/emojis/1/lion_face.png
Binary files differ
diff --git a/app/assets/images/emoji/lips.png b/public/-/emojis/1/lips.png
index 35f3cc2006f..35f3cc2006f 100644
--- a/app/assets/images/emoji/lips.png
+++ b/public/-/emojis/1/lips.png
Binary files differ
diff --git a/app/assets/images/emoji/lipstick.png b/public/-/emojis/1/lipstick.png
index 61a0c084c99..61a0c084c99 100644
--- a/app/assets/images/emoji/lipstick.png
+++ b/public/-/emojis/1/lipstick.png
Binary files differ
diff --git a/app/assets/images/emoji/lizard.png b/public/-/emojis/1/lizard.png
index 8363876050e..8363876050e 100644
--- a/app/assets/images/emoji/lizard.png
+++ b/public/-/emojis/1/lizard.png
Binary files differ
diff --git a/app/assets/images/emoji/lock.png b/public/-/emojis/1/lock.png
index 5a739c46644..5a739c46644 100644
--- a/app/assets/images/emoji/lock.png
+++ b/public/-/emojis/1/lock.png
Binary files differ
diff --git a/app/assets/images/emoji/lock_with_ink_pen.png b/public/-/emojis/1/lock_with_ink_pen.png
index 19a07d162fb..19a07d162fb 100644
--- a/app/assets/images/emoji/lock_with_ink_pen.png
+++ b/public/-/emojis/1/lock_with_ink_pen.png
Binary files differ
diff --git a/app/assets/images/emoji/lollipop.png b/public/-/emojis/1/lollipop.png
index ad76d7bf916..ad76d7bf916 100644
--- a/app/assets/images/emoji/lollipop.png
+++ b/public/-/emojis/1/lollipop.png
Binary files differ
diff --git a/app/assets/images/emoji/loop.png b/public/-/emojis/1/loop.png
index 0b82c8fe315..0b82c8fe315 100644
--- a/app/assets/images/emoji/loop.png
+++ b/public/-/emojis/1/loop.png
Binary files differ
diff --git a/app/assets/images/emoji/loud_sound.png b/public/-/emojis/1/loud_sound.png
index 8370033a539..8370033a539 100644
--- a/app/assets/images/emoji/loud_sound.png
+++ b/public/-/emojis/1/loud_sound.png
Binary files differ
diff --git a/app/assets/images/emoji/loudspeaker.png b/public/-/emojis/1/loudspeaker.png
index 5fd76a95b82..5fd76a95b82 100644
--- a/app/assets/images/emoji/loudspeaker.png
+++ b/public/-/emojis/1/loudspeaker.png
Binary files differ
diff --git a/app/assets/images/emoji/love_hotel.png b/public/-/emojis/1/love_hotel.png
index 5e136be6f8b..5e136be6f8b 100644
--- a/app/assets/images/emoji/love_hotel.png
+++ b/public/-/emojis/1/love_hotel.png
Binary files differ
diff --git a/app/assets/images/emoji/love_letter.png b/public/-/emojis/1/love_letter.png
index 3c3c767e784..3c3c767e784 100644
--- a/app/assets/images/emoji/love_letter.png
+++ b/public/-/emojis/1/love_letter.png
Binary files differ
diff --git a/app/assets/images/emoji/low_brightness.png b/public/-/emojis/1/low_brightness.png
index 543011d3961..543011d3961 100644
--- a/app/assets/images/emoji/low_brightness.png
+++ b/public/-/emojis/1/low_brightness.png
Binary files differ
diff --git a/app/assets/images/emoji/lying_face.png b/public/-/emojis/1/lying_face.png
index 02827e2628b..02827e2628b 100644
--- a/app/assets/images/emoji/lying_face.png
+++ b/public/-/emojis/1/lying_face.png
Binary files differ
diff --git a/app/assets/images/emoji/m.png b/public/-/emojis/1/m.png
index 8a3506fc1d7..8a3506fc1d7 100644
--- a/app/assets/images/emoji/m.png
+++ b/public/-/emojis/1/m.png
Binary files differ
diff --git a/app/assets/images/emoji/mag.png b/public/-/emojis/1/mag.png
index 55487156ac6..55487156ac6 100644
--- a/app/assets/images/emoji/mag.png
+++ b/public/-/emojis/1/mag.png
Binary files differ
diff --git a/app/assets/images/emoji/mag_right.png b/public/-/emojis/1/mag_right.png
index 0f4b1bca876..0f4b1bca876 100644
--- a/app/assets/images/emoji/mag_right.png
+++ b/public/-/emojis/1/mag_right.png
Binary files differ
diff --git a/app/assets/images/emoji/mahjong.png b/public/-/emojis/1/mahjong.png
index 66fd32025b2..66fd32025b2 100644
--- a/app/assets/images/emoji/mahjong.png
+++ b/public/-/emojis/1/mahjong.png
Binary files differ
diff --git a/app/assets/images/emoji/mailbox.png b/public/-/emojis/1/mailbox.png
index ef5174e40dd..ef5174e40dd 100644
--- a/app/assets/images/emoji/mailbox.png
+++ b/public/-/emojis/1/mailbox.png
Binary files differ
diff --git a/app/assets/images/emoji/mailbox_closed.png b/public/-/emojis/1/mailbox_closed.png
index ddc705db0d8..ddc705db0d8 100644
--- a/app/assets/images/emoji/mailbox_closed.png
+++ b/public/-/emojis/1/mailbox_closed.png
Binary files differ
diff --git a/app/assets/images/emoji/mailbox_with_mail.png b/public/-/emojis/1/mailbox_with_mail.png
index 5460616a5b1..5460616a5b1 100644
--- a/app/assets/images/emoji/mailbox_with_mail.png
+++ b/public/-/emojis/1/mailbox_with_mail.png
Binary files differ
diff --git a/app/assets/images/emoji/mailbox_with_no_mail.png b/public/-/emojis/1/mailbox_with_no_mail.png
index f9aeee6b15a..f9aeee6b15a 100644
--- a/app/assets/images/emoji/mailbox_with_no_mail.png
+++ b/public/-/emojis/1/mailbox_with_no_mail.png
Binary files differ
diff --git a/app/assets/images/emoji/man.png b/public/-/emojis/1/man.png
index 857a02e5146..857a02e5146 100644
--- a/app/assets/images/emoji/man.png
+++ b/public/-/emojis/1/man.png
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing.png b/public/-/emojis/1/man_dancing.png
index ccff3bede5a..ccff3bede5a 100644
--- a/app/assets/images/emoji/man_dancing.png
+++ b/public/-/emojis/1/man_dancing.png
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone1.png b/public/-/emojis/1/man_dancing_tone1.png
index e0b9f82d905..e0b9f82d905 100644
--- a/app/assets/images/emoji/man_dancing_tone1.png
+++ b/public/-/emojis/1/man_dancing_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone2.png b/public/-/emojis/1/man_dancing_tone2.png
index a5beed56e2e..a5beed56e2e 100644
--- a/app/assets/images/emoji/man_dancing_tone2.png
+++ b/public/-/emojis/1/man_dancing_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone3.png b/public/-/emojis/1/man_dancing_tone3.png
index 2fa20180a6e..2fa20180a6e 100644
--- a/app/assets/images/emoji/man_dancing_tone3.png
+++ b/public/-/emojis/1/man_dancing_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone4.png b/public/-/emojis/1/man_dancing_tone4.png
index bd3528c83ba..bd3528c83ba 100644
--- a/app/assets/images/emoji/man_dancing_tone4.png
+++ b/public/-/emojis/1/man_dancing_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone5.png b/public/-/emojis/1/man_dancing_tone5.png
index 41fd4f880c9..41fd4f880c9 100644
--- a/app/assets/images/emoji/man_dancing_tone5.png
+++ b/public/-/emojis/1/man_dancing_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo.png b/public/-/emojis/1/man_in_tuxedo.png
index 5f7e9303f89..5f7e9303f89 100644
--- a/app/assets/images/emoji/man_in_tuxedo.png
+++ b/public/-/emojis/1/man_in_tuxedo.png
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone1.png b/public/-/emojis/1/man_in_tuxedo_tone1.png
index 7b6b3acd99b..7b6b3acd99b 100644
--- a/app/assets/images/emoji/man_in_tuxedo_tone1.png
+++ b/public/-/emojis/1/man_in_tuxedo_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone2.png b/public/-/emojis/1/man_in_tuxedo_tone2.png
index 7975191b360..7975191b360 100644
--- a/app/assets/images/emoji/man_in_tuxedo_tone2.png
+++ b/public/-/emojis/1/man_in_tuxedo_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone3.png b/public/-/emojis/1/man_in_tuxedo_tone3.png
index a2816f600ae..a2816f600ae 100644
--- a/app/assets/images/emoji/man_in_tuxedo_tone3.png
+++ b/public/-/emojis/1/man_in_tuxedo_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone4.png b/public/-/emojis/1/man_in_tuxedo_tone4.png
index ea8291760f9..ea8291760f9 100644
--- a/app/assets/images/emoji/man_in_tuxedo_tone4.png
+++ b/public/-/emojis/1/man_in_tuxedo_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone5.png b/public/-/emojis/1/man_in_tuxedo_tone5.png
index c743e05fc5e..c743e05fc5e 100644
--- a/app/assets/images/emoji/man_in_tuxedo_tone5.png
+++ b/public/-/emojis/1/man_in_tuxedo_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/man_tone1.png b/public/-/emojis/1/man_tone1.png
index bb86e963a80..bb86e963a80 100644
--- a/app/assets/images/emoji/man_tone1.png
+++ b/public/-/emojis/1/man_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/man_tone2.png b/public/-/emojis/1/man_tone2.png
index fdeeaff46f5..fdeeaff46f5 100644
--- a/app/assets/images/emoji/man_tone2.png
+++ b/public/-/emojis/1/man_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/man_tone3.png b/public/-/emojis/1/man_tone3.png
index 7ae0b5df9cf..7ae0b5df9cf 100644
--- a/app/assets/images/emoji/man_tone3.png
+++ b/public/-/emojis/1/man_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/man_tone4.png b/public/-/emojis/1/man_tone4.png
index db14cde99b8..db14cde99b8 100644
--- a/app/assets/images/emoji/man_tone4.png
+++ b/public/-/emojis/1/man_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/man_tone5.png b/public/-/emojis/1/man_tone5.png
index 7c67a70529c..7c67a70529c 100644
--- a/app/assets/images/emoji/man_tone5.png
+++ b/public/-/emojis/1/man_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao.png b/public/-/emojis/1/man_with_gua_pi_mao.png
index 7841e13608d..7841e13608d 100644
--- a/app/assets/images/emoji/man_with_gua_pi_mao.png
+++ b/public/-/emojis/1/man_with_gua_pi_mao.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone1.png b/public/-/emojis/1/man_with_gua_pi_mao_tone1.png
index 5b7b3def19c..5b7b3def19c 100644
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone1.png
+++ b/public/-/emojis/1/man_with_gua_pi_mao_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone2.png b/public/-/emojis/1/man_with_gua_pi_mao_tone2.png
index c8b9cf87f4b..c8b9cf87f4b 100644
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone2.png
+++ b/public/-/emojis/1/man_with_gua_pi_mao_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone3.png b/public/-/emojis/1/man_with_gua_pi_mao_tone3.png
index effdd0c4c84..effdd0c4c84 100644
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone3.png
+++ b/public/-/emojis/1/man_with_gua_pi_mao_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone4.png b/public/-/emojis/1/man_with_gua_pi_mao_tone4.png
index f885ff46fa1..f885ff46fa1 100644
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone4.png
+++ b/public/-/emojis/1/man_with_gua_pi_mao_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone5.png b/public/-/emojis/1/man_with_gua_pi_mao_tone5.png
index a6d55ca1380..a6d55ca1380 100644
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone5.png
+++ b/public/-/emojis/1/man_with_gua_pi_mao_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban.png b/public/-/emojis/1/man_with_turban.png
index 51cf047f966..51cf047f966 100644
--- a/app/assets/images/emoji/man_with_turban.png
+++ b/public/-/emojis/1/man_with_turban.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone1.png b/public/-/emojis/1/man_with_turban_tone1.png
index 1e12ee4b231..1e12ee4b231 100644
--- a/app/assets/images/emoji/man_with_turban_tone1.png
+++ b/public/-/emojis/1/man_with_turban_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone2.png b/public/-/emojis/1/man_with_turban_tone2.png
index 37de4cceb23..37de4cceb23 100644
--- a/app/assets/images/emoji/man_with_turban_tone2.png
+++ b/public/-/emojis/1/man_with_turban_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone3.png b/public/-/emojis/1/man_with_turban_tone3.png
index f607afd3450..f607afd3450 100644
--- a/app/assets/images/emoji/man_with_turban_tone3.png
+++ b/public/-/emojis/1/man_with_turban_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone4.png b/public/-/emojis/1/man_with_turban_tone4.png
index c05695888af..c05695888af 100644
--- a/app/assets/images/emoji/man_with_turban_tone4.png
+++ b/public/-/emojis/1/man_with_turban_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone5.png b/public/-/emojis/1/man_with_turban_tone5.png
index 4b4ff64720b..4b4ff64720b 100644
--- a/app/assets/images/emoji/man_with_turban_tone5.png
+++ b/public/-/emojis/1/man_with_turban_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/mans_shoe.png b/public/-/emojis/1/mans_shoe.png
index 4bf7541032c..4bf7541032c 100644
--- a/app/assets/images/emoji/mans_shoe.png
+++ b/public/-/emojis/1/mans_shoe.png
Binary files differ
diff --git a/app/assets/images/emoji/map.png b/public/-/emojis/1/map.png
index 15efe32c798..15efe32c798 100644
--- a/app/assets/images/emoji/map.png
+++ b/public/-/emojis/1/map.png
Binary files differ
diff --git a/app/assets/images/emoji/maple_leaf.png b/public/-/emojis/1/maple_leaf.png
index c49acea67f7..c49acea67f7 100644
--- a/app/assets/images/emoji/maple_leaf.png
+++ b/public/-/emojis/1/maple_leaf.png
Binary files differ
diff --git a/app/assets/images/emoji/martial_arts_uniform.png b/public/-/emojis/1/martial_arts_uniform.png
index 8d6114761f6..8d6114761f6 100644
--- a/app/assets/images/emoji/martial_arts_uniform.png
+++ b/public/-/emojis/1/martial_arts_uniform.png
Binary files differ
diff --git a/app/assets/images/emoji/mask.png b/public/-/emojis/1/mask.png
index 1e800acd1c0..1e800acd1c0 100644
--- a/app/assets/images/emoji/mask.png
+++ b/public/-/emojis/1/mask.png
Binary files differ
diff --git a/app/assets/images/emoji/massage.png b/public/-/emojis/1/massage.png
index b91d845e374..b91d845e374 100644
--- a/app/assets/images/emoji/massage.png
+++ b/public/-/emojis/1/massage.png
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone1.png b/public/-/emojis/1/massage_tone1.png
index e0f415d3186..e0f415d3186 100644
--- a/app/assets/images/emoji/massage_tone1.png
+++ b/public/-/emojis/1/massage_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone2.png b/public/-/emojis/1/massage_tone2.png
index 0bb244a270b..0bb244a270b 100644
--- a/app/assets/images/emoji/massage_tone2.png
+++ b/public/-/emojis/1/massage_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone3.png b/public/-/emojis/1/massage_tone3.png
index a117ee81a22..a117ee81a22 100644
--- a/app/assets/images/emoji/massage_tone3.png
+++ b/public/-/emojis/1/massage_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone4.png b/public/-/emojis/1/massage_tone4.png
index 6f42ab017f4..6f42ab017f4 100644
--- a/app/assets/images/emoji/massage_tone4.png
+++ b/public/-/emojis/1/massage_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone5.png b/public/-/emojis/1/massage_tone5.png
index 6a388c0d0b5..6a388c0d0b5 100644
--- a/app/assets/images/emoji/massage_tone5.png
+++ b/public/-/emojis/1/massage_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/meat_on_bone.png b/public/-/emojis/1/meat_on_bone.png
index b20a59d1690..b20a59d1690 100644
--- a/app/assets/images/emoji/meat_on_bone.png
+++ b/public/-/emojis/1/meat_on_bone.png
Binary files differ
diff --git a/app/assets/images/emoji/medal.png b/public/-/emojis/1/medal.png
index b85896b14da..b85896b14da 100644
--- a/app/assets/images/emoji/medal.png
+++ b/public/-/emojis/1/medal.png
Binary files differ
diff --git a/app/assets/images/emoji/mega.png b/public/-/emojis/1/mega.png
index 4e6735188e3..4e6735188e3 100644
--- a/app/assets/images/emoji/mega.png
+++ b/public/-/emojis/1/mega.png
Binary files differ
diff --git a/app/assets/images/emoji/melon.png b/public/-/emojis/1/melon.png
index c01232d419d..c01232d419d 100644
--- a/app/assets/images/emoji/melon.png
+++ b/public/-/emojis/1/melon.png
Binary files differ
diff --git a/app/assets/images/emoji/menorah.png b/public/-/emojis/1/menorah.png
index b4297362869..b4297362869 100644
--- a/app/assets/images/emoji/menorah.png
+++ b/public/-/emojis/1/menorah.png
Binary files differ
diff --git a/app/assets/images/emoji/mens.png b/public/-/emojis/1/mens.png
index f5a1e1ba0cd..f5a1e1ba0cd 100644
--- a/app/assets/images/emoji/mens.png
+++ b/public/-/emojis/1/mens.png
Binary files differ
diff --git a/app/assets/images/emoji/metal.png b/public/-/emojis/1/metal.png
index 4aa6e7e0a44..4aa6e7e0a44 100644
--- a/app/assets/images/emoji/metal.png
+++ b/public/-/emojis/1/metal.png
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone1.png b/public/-/emojis/1/metal_tone1.png
index c080d2addbd..c080d2addbd 100644
--- a/app/assets/images/emoji/metal_tone1.png
+++ b/public/-/emojis/1/metal_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone2.png b/public/-/emojis/1/metal_tone2.png
index 12313529bcf..12313529bcf 100644
--- a/app/assets/images/emoji/metal_tone2.png
+++ b/public/-/emojis/1/metal_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone3.png b/public/-/emojis/1/metal_tone3.png
index ca9be6ae67b..ca9be6ae67b 100644
--- a/app/assets/images/emoji/metal_tone3.png
+++ b/public/-/emojis/1/metal_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone4.png b/public/-/emojis/1/metal_tone4.png
index abe28cbf890..abe28cbf890 100644
--- a/app/assets/images/emoji/metal_tone4.png
+++ b/public/-/emojis/1/metal_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone5.png b/public/-/emojis/1/metal_tone5.png
index 0c6b5dd34ed..0c6b5dd34ed 100644
--- a/app/assets/images/emoji/metal_tone5.png
+++ b/public/-/emojis/1/metal_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/metro.png b/public/-/emojis/1/metro.png
index 1de8f0551f3..1de8f0551f3 100644
--- a/app/assets/images/emoji/metro.png
+++ b/public/-/emojis/1/metro.png
Binary files differ
diff --git a/app/assets/images/emoji/microphone.png b/public/-/emojis/1/microphone.png
index d4e6b0def25..d4e6b0def25 100644
--- a/app/assets/images/emoji/microphone.png
+++ b/public/-/emojis/1/microphone.png
Binary files differ
diff --git a/app/assets/images/emoji/microphone2.png b/public/-/emojis/1/microphone2.png
index cd9167654ff..cd9167654ff 100644
--- a/app/assets/images/emoji/microphone2.png
+++ b/public/-/emojis/1/microphone2.png
Binary files differ
diff --git a/app/assets/images/emoji/microscope.png b/public/-/emojis/1/microscope.png
index 90f5acf6a78..90f5acf6a78 100644
--- a/app/assets/images/emoji/microscope.png
+++ b/public/-/emojis/1/microscope.png
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger.png b/public/-/emojis/1/middle_finger.png
index 697f7a25eb2..697f7a25eb2 100644
--- a/app/assets/images/emoji/middle_finger.png
+++ b/public/-/emojis/1/middle_finger.png
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone1.png b/public/-/emojis/1/middle_finger_tone1.png
index 61ef12a1548..61ef12a1548 100644
--- a/app/assets/images/emoji/middle_finger_tone1.png
+++ b/public/-/emojis/1/middle_finger_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone2.png b/public/-/emojis/1/middle_finger_tone2.png
index c31a69be9af..c31a69be9af 100644
--- a/app/assets/images/emoji/middle_finger_tone2.png
+++ b/public/-/emojis/1/middle_finger_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone3.png b/public/-/emojis/1/middle_finger_tone3.png
index 73ac216ce63..73ac216ce63 100644
--- a/app/assets/images/emoji/middle_finger_tone3.png
+++ b/public/-/emojis/1/middle_finger_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone4.png b/public/-/emojis/1/middle_finger_tone4.png
index 80b8ab7706d..80b8ab7706d 100644
--- a/app/assets/images/emoji/middle_finger_tone4.png
+++ b/public/-/emojis/1/middle_finger_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone5.png b/public/-/emojis/1/middle_finger_tone5.png
index a8826b196e8..a8826b196e8 100644
--- a/app/assets/images/emoji/middle_finger_tone5.png
+++ b/public/-/emojis/1/middle_finger_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/military_medal.png b/public/-/emojis/1/military_medal.png
index ecd3fb03584..ecd3fb03584 100644
--- a/app/assets/images/emoji/military_medal.png
+++ b/public/-/emojis/1/military_medal.png
Binary files differ
diff --git a/app/assets/images/emoji/milk.png b/public/-/emojis/1/milk.png
index e4fcf2e64f3..e4fcf2e64f3 100644
--- a/app/assets/images/emoji/milk.png
+++ b/public/-/emojis/1/milk.png
Binary files differ
diff --git a/app/assets/images/emoji/milky_way.png b/public/-/emojis/1/milky_way.png
index b2b8ac59c5e..b2b8ac59c5e 100644
--- a/app/assets/images/emoji/milky_way.png
+++ b/public/-/emojis/1/milky_way.png
Binary files differ
diff --git a/app/assets/images/emoji/minibus.png b/public/-/emojis/1/minibus.png
index c60dd8f47ab..c60dd8f47ab 100644
--- a/app/assets/images/emoji/minibus.png
+++ b/public/-/emojis/1/minibus.png
Binary files differ
diff --git a/app/assets/images/emoji/minidisc.png b/public/-/emojis/1/minidisc.png
index 9fa94cfbe74..9fa94cfbe74 100644
--- a/app/assets/images/emoji/minidisc.png
+++ b/public/-/emojis/1/minidisc.png
Binary files differ
diff --git a/app/assets/images/emoji/mobile_phone_off.png b/public/-/emojis/1/mobile_phone_off.png
index 8b661ec1c94..8b661ec1c94 100644
--- a/app/assets/images/emoji/mobile_phone_off.png
+++ b/public/-/emojis/1/mobile_phone_off.png
Binary files differ
diff --git a/app/assets/images/emoji/money_mouth.png b/public/-/emojis/1/money_mouth.png
index 75fd1e90cb0..75fd1e90cb0 100644
--- a/app/assets/images/emoji/money_mouth.png
+++ b/public/-/emojis/1/money_mouth.png
Binary files differ
diff --git a/app/assets/images/emoji/money_with_wings.png b/public/-/emojis/1/money_with_wings.png
index f022b04b3c2..f022b04b3c2 100644
--- a/app/assets/images/emoji/money_with_wings.png
+++ b/public/-/emojis/1/money_with_wings.png
Binary files differ
diff --git a/app/assets/images/emoji/moneybag.png b/public/-/emojis/1/moneybag.png
index b9296be0902..b9296be0902 100644
--- a/app/assets/images/emoji/moneybag.png
+++ b/public/-/emojis/1/moneybag.png
Binary files differ
diff --git a/app/assets/images/emoji/monkey.png b/public/-/emojis/1/monkey.png
index 9fae29448e3..9fae29448e3 100644
--- a/app/assets/images/emoji/monkey.png
+++ b/public/-/emojis/1/monkey.png
Binary files differ
diff --git a/app/assets/images/emoji/monkey_face.png b/public/-/emojis/1/monkey_face.png
index 7cab9b91a82..7cab9b91a82 100644
--- a/app/assets/images/emoji/monkey_face.png
+++ b/public/-/emojis/1/monkey_face.png
Binary files differ
diff --git a/app/assets/images/emoji/monorail.png b/public/-/emojis/1/monorail.png
index 11eb1f574bf..11eb1f574bf 100644
--- a/app/assets/images/emoji/monorail.png
+++ b/public/-/emojis/1/monorail.png
Binary files differ
diff --git a/app/assets/images/emoji/mortar_board.png b/public/-/emojis/1/mortar_board.png
index 8b17ddd9d00..8b17ddd9d00 100644
--- a/app/assets/images/emoji/mortar_board.png
+++ b/public/-/emojis/1/mortar_board.png
Binary files differ
diff --git a/app/assets/images/emoji/mosque.png b/public/-/emojis/1/mosque.png
index ef770b26d96..ef770b26d96 100644
--- a/app/assets/images/emoji/mosque.png
+++ b/public/-/emojis/1/mosque.png
Binary files differ
diff --git a/app/assets/images/emoji/motor_scooter.png b/public/-/emojis/1/motor_scooter.png
index c5afa72d807..c5afa72d807 100644
--- a/app/assets/images/emoji/motor_scooter.png
+++ b/public/-/emojis/1/motor_scooter.png
Binary files differ
diff --git a/app/assets/images/emoji/motorboat.png b/public/-/emojis/1/motorboat.png
index 0506db1a40f..0506db1a40f 100644
--- a/app/assets/images/emoji/motorboat.png
+++ b/public/-/emojis/1/motorboat.png
Binary files differ
diff --git a/app/assets/images/emoji/motorcycle.png b/public/-/emojis/1/motorcycle.png
index 3d1d567e8ec..3d1d567e8ec 100644
--- a/app/assets/images/emoji/motorcycle.png
+++ b/public/-/emojis/1/motorcycle.png
Binary files differ
diff --git a/app/assets/images/emoji/motorway.png b/public/-/emojis/1/motorway.png
index 8c3d3d03e3f..8c3d3d03e3f 100644
--- a/app/assets/images/emoji/motorway.png
+++ b/public/-/emojis/1/motorway.png
Binary files differ
diff --git a/app/assets/images/emoji/mount_fuji.png b/public/-/emojis/1/mount_fuji.png
index 88a54752458..88a54752458 100644
--- a/app/assets/images/emoji/mount_fuji.png
+++ b/public/-/emojis/1/mount_fuji.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain.png b/public/-/emojis/1/mountain.png
index 6722ebdd294..6722ebdd294 100644
--- a/app/assets/images/emoji/mountain.png
+++ b/public/-/emojis/1/mountain.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist.png b/public/-/emojis/1/mountain_bicyclist.png
index 41d3dc3ac6f..41d3dc3ac6f 100644
--- a/app/assets/images/emoji/mountain_bicyclist.png
+++ b/public/-/emojis/1/mountain_bicyclist.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone1.png b/public/-/emojis/1/mountain_bicyclist_tone1.png
index e9f1daf5e40..e9f1daf5e40 100644
--- a/app/assets/images/emoji/mountain_bicyclist_tone1.png
+++ b/public/-/emojis/1/mountain_bicyclist_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone2.png b/public/-/emojis/1/mountain_bicyclist_tone2.png
index 555b9e29d4d..555b9e29d4d 100644
--- a/app/assets/images/emoji/mountain_bicyclist_tone2.png
+++ b/public/-/emojis/1/mountain_bicyclist_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone3.png b/public/-/emojis/1/mountain_bicyclist_tone3.png
index 7df5508ec8c..7df5508ec8c 100644
--- a/app/assets/images/emoji/mountain_bicyclist_tone3.png
+++ b/public/-/emojis/1/mountain_bicyclist_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone4.png b/public/-/emojis/1/mountain_bicyclist_tone4.png
index f94b3450697..f94b3450697 100644
--- a/app/assets/images/emoji/mountain_bicyclist_tone4.png
+++ b/public/-/emojis/1/mountain_bicyclist_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone5.png b/public/-/emojis/1/mountain_bicyclist_tone5.png
index 16a45861e1f..16a45861e1f 100644
--- a/app/assets/images/emoji/mountain_bicyclist_tone5.png
+++ b/public/-/emojis/1/mountain_bicyclist_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain_cableway.png b/public/-/emojis/1/mountain_cableway.png
index 1dea73ca53b..1dea73ca53b 100644
--- a/app/assets/images/emoji/mountain_cableway.png
+++ b/public/-/emojis/1/mountain_cableway.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain_railway.png b/public/-/emojis/1/mountain_railway.png
index ade2218e469..ade2218e469 100644
--- a/app/assets/images/emoji/mountain_railway.png
+++ b/public/-/emojis/1/mountain_railway.png
Binary files differ
diff --git a/app/assets/images/emoji/mountain_snow.png b/public/-/emojis/1/mountain_snow.png
index 76e1cfd8313..76e1cfd8313 100644
--- a/app/assets/images/emoji/mountain_snow.png
+++ b/public/-/emojis/1/mountain_snow.png
Binary files differ
diff --git a/app/assets/images/emoji/mouse.png b/public/-/emojis/1/mouse.png
index 50afcd3262e..50afcd3262e 100644
--- a/app/assets/images/emoji/mouse.png
+++ b/public/-/emojis/1/mouse.png
Binary files differ
diff --git a/app/assets/images/emoji/mouse2.png b/public/-/emojis/1/mouse2.png
index 20fb041f09f..20fb041f09f 100644
--- a/app/assets/images/emoji/mouse2.png
+++ b/public/-/emojis/1/mouse2.png
Binary files differ
diff --git a/app/assets/images/emoji/mouse_three_button.png b/public/-/emojis/1/mouse_three_button.png
index e84e96ff6e8..e84e96ff6e8 100644
--- a/app/assets/images/emoji/mouse_three_button.png
+++ b/public/-/emojis/1/mouse_three_button.png
Binary files differ
diff --git a/app/assets/images/emoji/movie_camera.png b/public/-/emojis/1/movie_camera.png
index 4e73b130155..4e73b130155 100644
--- a/app/assets/images/emoji/movie_camera.png
+++ b/public/-/emojis/1/movie_camera.png
Binary files differ
diff --git a/app/assets/images/emoji/moyai.png b/public/-/emojis/1/moyai.png
index e6a7779c45b..e6a7779c45b 100644
--- a/app/assets/images/emoji/moyai.png
+++ b/public/-/emojis/1/moyai.png
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus.png b/public/-/emojis/1/mrs_claus.png
index 9cf2458df1a..9cf2458df1a 100644
--- a/app/assets/images/emoji/mrs_claus.png
+++ b/public/-/emojis/1/mrs_claus.png
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone1.png b/public/-/emojis/1/mrs_claus_tone1.png
index d8a695d7035..d8a695d7035 100644
--- a/app/assets/images/emoji/mrs_claus_tone1.png
+++ b/public/-/emojis/1/mrs_claus_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone2.png b/public/-/emojis/1/mrs_claus_tone2.png
index 0e17e8c51f3..0e17e8c51f3 100644
--- a/app/assets/images/emoji/mrs_claus_tone2.png
+++ b/public/-/emojis/1/mrs_claus_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone3.png b/public/-/emojis/1/mrs_claus_tone3.png
index c3ee4d1dfae..c3ee4d1dfae 100644
--- a/app/assets/images/emoji/mrs_claus_tone3.png
+++ b/public/-/emojis/1/mrs_claus_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone4.png b/public/-/emojis/1/mrs_claus_tone4.png
index 68a556da2fe..68a556da2fe 100644
--- a/app/assets/images/emoji/mrs_claus_tone4.png
+++ b/public/-/emojis/1/mrs_claus_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone5.png b/public/-/emojis/1/mrs_claus_tone5.png
index ccab3c40ff2..ccab3c40ff2 100644
--- a/app/assets/images/emoji/mrs_claus_tone5.png
+++ b/public/-/emojis/1/mrs_claus_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/muscle.png b/public/-/emojis/1/muscle.png
index 7e67c1880f7..7e67c1880f7 100644
--- a/app/assets/images/emoji/muscle.png
+++ b/public/-/emojis/1/muscle.png
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone1.png b/public/-/emojis/1/muscle_tone1.png
index 1522942ce51..1522942ce51 100644
--- a/app/assets/images/emoji/muscle_tone1.png
+++ b/public/-/emojis/1/muscle_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone2.png b/public/-/emojis/1/muscle_tone2.png
index 569c6e832ca..569c6e832ca 100644
--- a/app/assets/images/emoji/muscle_tone2.png
+++ b/public/-/emojis/1/muscle_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone3.png b/public/-/emojis/1/muscle_tone3.png
index 0a76b00fa89..0a76b00fa89 100644
--- a/app/assets/images/emoji/muscle_tone3.png
+++ b/public/-/emojis/1/muscle_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone4.png b/public/-/emojis/1/muscle_tone4.png
index f0cf31328e0..f0cf31328e0 100644
--- a/app/assets/images/emoji/muscle_tone4.png
+++ b/public/-/emojis/1/muscle_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone5.png b/public/-/emojis/1/muscle_tone5.png
index 4fda92460e8..4fda92460e8 100644
--- a/app/assets/images/emoji/muscle_tone5.png
+++ b/public/-/emojis/1/muscle_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/mushroom.png b/public/-/emojis/1/mushroom.png
index dd85742ba2c..dd85742ba2c 100644
--- a/app/assets/images/emoji/mushroom.png
+++ b/public/-/emojis/1/mushroom.png
Binary files differ
diff --git a/app/assets/images/emoji/musical_keyboard.png b/public/-/emojis/1/musical_keyboard.png
index 442b7456842..442b7456842 100644
--- a/app/assets/images/emoji/musical_keyboard.png
+++ b/public/-/emojis/1/musical_keyboard.png
Binary files differ
diff --git a/app/assets/images/emoji/musical_note.png b/public/-/emojis/1/musical_note.png
index 06691ef61bb..06691ef61bb 100644
--- a/app/assets/images/emoji/musical_note.png
+++ b/public/-/emojis/1/musical_note.png
Binary files differ
diff --git a/app/assets/images/emoji/musical_score.png b/public/-/emojis/1/musical_score.png
index 47dc05a8ef5..47dc05a8ef5 100644
--- a/app/assets/images/emoji/musical_score.png
+++ b/public/-/emojis/1/musical_score.png
Binary files differ
diff --git a/app/assets/images/emoji/mute.png b/public/-/emojis/1/mute.png
index 7c1788e5075..7c1788e5075 100644
--- a/app/assets/images/emoji/mute.png
+++ b/public/-/emojis/1/mute.png
Binary files differ
diff --git a/app/assets/images/emoji/nail_care.png b/public/-/emojis/1/nail_care.png
index aa52af7050d..aa52af7050d 100644
--- a/app/assets/images/emoji/nail_care.png
+++ b/public/-/emojis/1/nail_care.png
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone1.png b/public/-/emojis/1/nail_care_tone1.png
index 26e883dd244..26e883dd244 100644
--- a/app/assets/images/emoji/nail_care_tone1.png
+++ b/public/-/emojis/1/nail_care_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone2.png b/public/-/emojis/1/nail_care_tone2.png
index 61257b47ea3..61257b47ea3 100644
--- a/app/assets/images/emoji/nail_care_tone2.png
+++ b/public/-/emojis/1/nail_care_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone3.png b/public/-/emojis/1/nail_care_tone3.png
index 29871b05f62..29871b05f62 100644
--- a/app/assets/images/emoji/nail_care_tone3.png
+++ b/public/-/emojis/1/nail_care_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone4.png b/public/-/emojis/1/nail_care_tone4.png
index 2881de0b17d..2881de0b17d 100644
--- a/app/assets/images/emoji/nail_care_tone4.png
+++ b/public/-/emojis/1/nail_care_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone5.png b/public/-/emojis/1/nail_care_tone5.png
index a0b7c0a45a6..a0b7c0a45a6 100644
--- a/app/assets/images/emoji/nail_care_tone5.png
+++ b/public/-/emojis/1/nail_care_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/name_badge.png b/public/-/emojis/1/name_badge.png
index ec5ee213e20..ec5ee213e20 100644
--- a/app/assets/images/emoji/name_badge.png
+++ b/public/-/emojis/1/name_badge.png
Binary files differ
diff --git a/app/assets/images/emoji/nauseated_face.png b/public/-/emojis/1/nauseated_face.png
index a566c109c28..a566c109c28 100644
--- a/app/assets/images/emoji/nauseated_face.png
+++ b/public/-/emojis/1/nauseated_face.png
Binary files differ
diff --git a/app/assets/images/emoji/necktie.png b/public/-/emojis/1/necktie.png
index 1804e7f3ff3..1804e7f3ff3 100644
--- a/app/assets/images/emoji/necktie.png
+++ b/public/-/emojis/1/necktie.png
Binary files differ
diff --git a/app/assets/images/emoji/negative_squared_cross_mark.png b/public/-/emojis/1/negative_squared_cross_mark.png
index dae487f1f98..dae487f1f98 100644
--- a/app/assets/images/emoji/negative_squared_cross_mark.png
+++ b/public/-/emojis/1/negative_squared_cross_mark.png
Binary files differ
diff --git a/app/assets/images/emoji/nerd.png b/public/-/emojis/1/nerd.png
index 7820bd581dc..7820bd581dc 100644
--- a/app/assets/images/emoji/nerd.png
+++ b/public/-/emojis/1/nerd.png
Binary files differ
diff --git a/app/assets/images/emoji/neutral_face.png b/public/-/emojis/1/neutral_face.png
index 065d193afe4..065d193afe4 100644
--- a/app/assets/images/emoji/neutral_face.png
+++ b/public/-/emojis/1/neutral_face.png
Binary files differ
diff --git a/app/assets/images/emoji/new.png b/public/-/emojis/1/new.png
index b4f85488d1a..b4f85488d1a 100644
--- a/app/assets/images/emoji/new.png
+++ b/public/-/emojis/1/new.png
Binary files differ
diff --git a/app/assets/images/emoji/new_moon.png b/public/-/emojis/1/new_moon.png
index ecff72caa42..ecff72caa42 100644
--- a/app/assets/images/emoji/new_moon.png
+++ b/public/-/emojis/1/new_moon.png
Binary files differ
diff --git a/app/assets/images/emoji/new_moon_with_face.png b/public/-/emojis/1/new_moon_with_face.png
index 150dd12400c..150dd12400c 100644
--- a/app/assets/images/emoji/new_moon_with_face.png
+++ b/public/-/emojis/1/new_moon_with_face.png
Binary files differ
diff --git a/app/assets/images/emoji/newspaper.png b/public/-/emojis/1/newspaper.png
index 2aa8f060bde..2aa8f060bde 100644
--- a/app/assets/images/emoji/newspaper.png
+++ b/public/-/emojis/1/newspaper.png
Binary files differ
diff --git a/app/assets/images/emoji/newspaper2.png b/public/-/emojis/1/newspaper2.png
index f64748df2b2..f64748df2b2 100644
--- a/app/assets/images/emoji/newspaper2.png
+++ b/public/-/emojis/1/newspaper2.png
Binary files differ
diff --git a/app/assets/images/emoji/ng.png b/public/-/emojis/1/ng.png
index ee8d20f5ebc..ee8d20f5ebc 100644
--- a/app/assets/images/emoji/ng.png
+++ b/public/-/emojis/1/ng.png
Binary files differ
diff --git a/app/assets/images/emoji/night_with_stars.png b/public/-/emojis/1/night_with_stars.png
index ca2018f456d..ca2018f456d 100644
--- a/app/assets/images/emoji/night_with_stars.png
+++ b/public/-/emojis/1/night_with_stars.png
Binary files differ
diff --git a/app/assets/images/emoji/nine.png b/public/-/emojis/1/nine.png
index 9fce3d1eca9..9fce3d1eca9 100644
--- a/app/assets/images/emoji/nine.png
+++ b/public/-/emojis/1/nine.png
Binary files differ
diff --git a/app/assets/images/emoji/no_bell.png b/public/-/emojis/1/no_bell.png
index 15cb38dd1e7..15cb38dd1e7 100644
--- a/app/assets/images/emoji/no_bell.png
+++ b/public/-/emojis/1/no_bell.png
Binary files differ
diff --git a/app/assets/images/emoji/no_bicycles.png b/public/-/emojis/1/no_bicycles.png
index 19c85421ce9..19c85421ce9 100644
--- a/app/assets/images/emoji/no_bicycles.png
+++ b/public/-/emojis/1/no_bicycles.png
Binary files differ
diff --git a/app/assets/images/emoji/no_entry.png b/public/-/emojis/1/no_entry.png
index 476800fc5c6..476800fc5c6 100644
--- a/app/assets/images/emoji/no_entry.png
+++ b/public/-/emojis/1/no_entry.png
Binary files differ
diff --git a/app/assets/images/emoji/no_entry_sign.png b/public/-/emojis/1/no_entry_sign.png
index d2efd65e74b..d2efd65e74b 100644
--- a/app/assets/images/emoji/no_entry_sign.png
+++ b/public/-/emojis/1/no_entry_sign.png
Binary files differ
diff --git a/app/assets/images/emoji/no_good.png b/public/-/emojis/1/no_good.png
index ed577100322..ed577100322 100644
--- a/app/assets/images/emoji/no_good.png
+++ b/public/-/emojis/1/no_good.png
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone1.png b/public/-/emojis/1/no_good_tone1.png
index 5c1a3cbb884..5c1a3cbb884 100644
--- a/app/assets/images/emoji/no_good_tone1.png
+++ b/public/-/emojis/1/no_good_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone2.png b/public/-/emojis/1/no_good_tone2.png
index 80d8021f8fe..80d8021f8fe 100644
--- a/app/assets/images/emoji/no_good_tone2.png
+++ b/public/-/emojis/1/no_good_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone3.png b/public/-/emojis/1/no_good_tone3.png
index 635e6a00815..635e6a00815 100644
--- a/app/assets/images/emoji/no_good_tone3.png
+++ b/public/-/emojis/1/no_good_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone4.png b/public/-/emojis/1/no_good_tone4.png
index b96e412a374..b96e412a374 100644
--- a/app/assets/images/emoji/no_good_tone4.png
+++ b/public/-/emojis/1/no_good_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone5.png b/public/-/emojis/1/no_good_tone5.png
index 9a7084afa0a..9a7084afa0a 100644
--- a/app/assets/images/emoji/no_good_tone5.png
+++ b/public/-/emojis/1/no_good_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/no_mobile_phones.png b/public/-/emojis/1/no_mobile_phones.png
index 7b1ae6ea579..7b1ae6ea579 100644
--- a/app/assets/images/emoji/no_mobile_phones.png
+++ b/public/-/emojis/1/no_mobile_phones.png
Binary files differ
diff --git a/app/assets/images/emoji/no_mouth.png b/public/-/emojis/1/no_mouth.png
index b642f6c1172..b642f6c1172 100644
--- a/app/assets/images/emoji/no_mouth.png
+++ b/public/-/emojis/1/no_mouth.png
Binary files differ
diff --git a/app/assets/images/emoji/no_pedestrians.png b/public/-/emojis/1/no_pedestrians.png
index 286aa577a23..286aa577a23 100644
--- a/app/assets/images/emoji/no_pedestrians.png
+++ b/public/-/emojis/1/no_pedestrians.png
Binary files differ
diff --git a/app/assets/images/emoji/no_smoking.png b/public/-/emojis/1/no_smoking.png
index 586b8d29d05..586b8d29d05 100644
--- a/app/assets/images/emoji/no_smoking.png
+++ b/public/-/emojis/1/no_smoking.png
Binary files differ
diff --git a/app/assets/images/emoji/non-potable_water.png b/public/-/emojis/1/non-potable_water.png
index 827d4193f4e..827d4193f4e 100644
--- a/app/assets/images/emoji/non-potable_water.png
+++ b/public/-/emojis/1/non-potable_water.png
Binary files differ
diff --git a/app/assets/images/emoji/nose.png b/public/-/emojis/1/nose.png
index 2f04ac5f98f..2f04ac5f98f 100644
--- a/app/assets/images/emoji/nose.png
+++ b/public/-/emojis/1/nose.png
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone1.png b/public/-/emojis/1/nose_tone1.png
index 8008d17506e..8008d17506e 100644
--- a/app/assets/images/emoji/nose_tone1.png
+++ b/public/-/emojis/1/nose_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone2.png b/public/-/emojis/1/nose_tone2.png
index ac17f26e827..ac17f26e827 100644
--- a/app/assets/images/emoji/nose_tone2.png
+++ b/public/-/emojis/1/nose_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone3.png b/public/-/emojis/1/nose_tone3.png
index d8b6cbe0f8e..d8b6cbe0f8e 100644
--- a/app/assets/images/emoji/nose_tone3.png
+++ b/public/-/emojis/1/nose_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone4.png b/public/-/emojis/1/nose_tone4.png
index 004b2631e2e..004b2631e2e 100644
--- a/app/assets/images/emoji/nose_tone4.png
+++ b/public/-/emojis/1/nose_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone5.png b/public/-/emojis/1/nose_tone5.png
index 7b33821f6c9..7b33821f6c9 100644
--- a/app/assets/images/emoji/nose_tone5.png
+++ b/public/-/emojis/1/nose_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/notebook.png b/public/-/emojis/1/notebook.png
index f6c28b4915d..f6c28b4915d 100644
--- a/app/assets/images/emoji/notebook.png
+++ b/public/-/emojis/1/notebook.png
Binary files differ
diff --git a/app/assets/images/emoji/notebook_with_decorative_cover.png b/public/-/emojis/1/notebook_with_decorative_cover.png
index 03f566b6d2c..03f566b6d2c 100644
--- a/app/assets/images/emoji/notebook_with_decorative_cover.png
+++ b/public/-/emojis/1/notebook_with_decorative_cover.png
Binary files differ
diff --git a/app/assets/images/emoji/notepad_spiral.png b/public/-/emojis/1/notepad_spiral.png
index 85faa10d8ea..85faa10d8ea 100644
--- a/app/assets/images/emoji/notepad_spiral.png
+++ b/public/-/emojis/1/notepad_spiral.png
Binary files differ
diff --git a/app/assets/images/emoji/notes.png b/public/-/emojis/1/notes.png
index 57d499aa181..57d499aa181 100644
--- a/app/assets/images/emoji/notes.png
+++ b/public/-/emojis/1/notes.png
Binary files differ
diff --git a/app/assets/images/emoji/nut_and_bolt.png b/public/-/emojis/1/nut_and_bolt.png
index 4b9ae155319..4b9ae155319 100644
--- a/app/assets/images/emoji/nut_and_bolt.png
+++ b/public/-/emojis/1/nut_and_bolt.png
Binary files differ
diff --git a/app/assets/images/emoji/o.png b/public/-/emojis/1/o.png
index 3fe75ce4675..3fe75ce4675 100644
--- a/app/assets/images/emoji/o.png
+++ b/public/-/emojis/1/o.png
Binary files differ
diff --git a/app/assets/images/emoji/o2.png b/public/-/emojis/1/o2.png
index 73278ba194a..73278ba194a 100644
--- a/app/assets/images/emoji/o2.png
+++ b/public/-/emojis/1/o2.png
Binary files differ
diff --git a/app/assets/images/emoji/ocean.png b/public/-/emojis/1/ocean.png
index 45ff1e87703..45ff1e87703 100644
--- a/app/assets/images/emoji/ocean.png
+++ b/public/-/emojis/1/ocean.png
Binary files differ
diff --git a/app/assets/images/emoji/octagonal_sign.png b/public/-/emojis/1/octagonal_sign.png
index 5ed61004045..5ed61004045 100644
--- a/app/assets/images/emoji/octagonal_sign.png
+++ b/public/-/emojis/1/octagonal_sign.png
Binary files differ
diff --git a/app/assets/images/emoji/octopus.png b/public/-/emojis/1/octopus.png
index 72c84074aac..72c84074aac 100644
--- a/app/assets/images/emoji/octopus.png
+++ b/public/-/emojis/1/octopus.png
Binary files differ
diff --git a/app/assets/images/emoji/oden.png b/public/-/emojis/1/oden.png
index d38a849fece..d38a849fece 100644
--- a/app/assets/images/emoji/oden.png
+++ b/public/-/emojis/1/oden.png
Binary files differ
diff --git a/app/assets/images/emoji/office.png b/public/-/emojis/1/office.png
index 7eee927d1b0..7eee927d1b0 100644
--- a/app/assets/images/emoji/office.png
+++ b/public/-/emojis/1/office.png
Binary files differ
diff --git a/app/assets/images/emoji/oil.png b/public/-/emojis/1/oil.png
index c4c4d42da8b..c4c4d42da8b 100644
--- a/app/assets/images/emoji/oil.png
+++ b/public/-/emojis/1/oil.png
Binary files differ
diff --git a/app/assets/images/emoji/ok.png b/public/-/emojis/1/ok.png
index d0d775532ff..d0d775532ff 100644
--- a/app/assets/images/emoji/ok.png
+++ b/public/-/emojis/1/ok.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand.png b/public/-/emojis/1/ok_hand.png
index 028d69b0de3..028d69b0de3 100644
--- a/app/assets/images/emoji/ok_hand.png
+++ b/public/-/emojis/1/ok_hand.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone1.png b/public/-/emojis/1/ok_hand_tone1.png
index cecf7b2ab5a..cecf7b2ab5a 100644
--- a/app/assets/images/emoji/ok_hand_tone1.png
+++ b/public/-/emojis/1/ok_hand_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone2.png b/public/-/emojis/1/ok_hand_tone2.png
index c19239bcd3d..c19239bcd3d 100644
--- a/app/assets/images/emoji/ok_hand_tone2.png
+++ b/public/-/emojis/1/ok_hand_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone3.png b/public/-/emojis/1/ok_hand_tone3.png
index 94b65b03ecd..94b65b03ecd 100644
--- a/app/assets/images/emoji/ok_hand_tone3.png
+++ b/public/-/emojis/1/ok_hand_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone4.png b/public/-/emojis/1/ok_hand_tone4.png
index 03d26f08e6a..03d26f08e6a 100644
--- a/app/assets/images/emoji/ok_hand_tone4.png
+++ b/public/-/emojis/1/ok_hand_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone5.png b/public/-/emojis/1/ok_hand_tone5.png
index d4b24086364..d4b24086364 100644
--- a/app/assets/images/emoji/ok_hand_tone5.png
+++ b/public/-/emojis/1/ok_hand_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman.png b/public/-/emojis/1/ok_woman.png
index 90a2c7469c4..90a2c7469c4 100644
--- a/app/assets/images/emoji/ok_woman.png
+++ b/public/-/emojis/1/ok_woman.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone1.png b/public/-/emojis/1/ok_woman_tone1.png
index c99543e785b..c99543e785b 100644
--- a/app/assets/images/emoji/ok_woman_tone1.png
+++ b/public/-/emojis/1/ok_woman_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone2.png b/public/-/emojis/1/ok_woman_tone2.png
index ad5fae813db..ad5fae813db 100644
--- a/app/assets/images/emoji/ok_woman_tone2.png
+++ b/public/-/emojis/1/ok_woman_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone3.png b/public/-/emojis/1/ok_woman_tone3.png
index 51bf4fab406..51bf4fab406 100644
--- a/app/assets/images/emoji/ok_woman_tone3.png
+++ b/public/-/emojis/1/ok_woman_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone4.png b/public/-/emojis/1/ok_woman_tone4.png
index ee3f9dc640a..ee3f9dc640a 100644
--- a/app/assets/images/emoji/ok_woman_tone4.png
+++ b/public/-/emojis/1/ok_woman_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone5.png b/public/-/emojis/1/ok_woman_tone5.png
index 62a9d9237f7..62a9d9237f7 100644
--- a/app/assets/images/emoji/ok_woman_tone5.png
+++ b/public/-/emojis/1/ok_woman_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/older_man.png b/public/-/emojis/1/older_man.png
index 4ace4e6f308..4ace4e6f308 100644
--- a/app/assets/images/emoji/older_man.png
+++ b/public/-/emojis/1/older_man.png
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone1.png b/public/-/emojis/1/older_man_tone1.png
index ab459baace8..ab459baace8 100644
--- a/app/assets/images/emoji/older_man_tone1.png
+++ b/public/-/emojis/1/older_man_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone2.png b/public/-/emojis/1/older_man_tone2.png
index f4dfc7694ea..f4dfc7694ea 100644
--- a/app/assets/images/emoji/older_man_tone2.png
+++ b/public/-/emojis/1/older_man_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone3.png b/public/-/emojis/1/older_man_tone3.png
index 5ffd11792f4..5ffd11792f4 100644
--- a/app/assets/images/emoji/older_man_tone3.png
+++ b/public/-/emojis/1/older_man_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone4.png b/public/-/emojis/1/older_man_tone4.png
index b350a764bfd..b350a764bfd 100644
--- a/app/assets/images/emoji/older_man_tone4.png
+++ b/public/-/emojis/1/older_man_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone5.png b/public/-/emojis/1/older_man_tone5.png
index 05fe24a1708..05fe24a1708 100644
--- a/app/assets/images/emoji/older_man_tone5.png
+++ b/public/-/emojis/1/older_man_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/older_woman.png b/public/-/emojis/1/older_woman.png
index 52dc4987143..52dc4987143 100644
--- a/app/assets/images/emoji/older_woman.png
+++ b/public/-/emojis/1/older_woman.png
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone1.png b/public/-/emojis/1/older_woman_tone1.png
index b49e821402c..b49e821402c 100644
--- a/app/assets/images/emoji/older_woman_tone1.png
+++ b/public/-/emojis/1/older_woman_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone2.png b/public/-/emojis/1/older_woman_tone2.png
index e86bf5ab3b7..e86bf5ab3b7 100644
--- a/app/assets/images/emoji/older_woman_tone2.png
+++ b/public/-/emojis/1/older_woman_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone3.png b/public/-/emojis/1/older_woman_tone3.png
index 83fc14b0874..83fc14b0874 100644
--- a/app/assets/images/emoji/older_woman_tone3.png
+++ b/public/-/emojis/1/older_woman_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone4.png b/public/-/emojis/1/older_woman_tone4.png
index e4aa8a424d4..e4aa8a424d4 100644
--- a/app/assets/images/emoji/older_woman_tone4.png
+++ b/public/-/emojis/1/older_woman_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone5.png b/public/-/emojis/1/older_woman_tone5.png
index 4009012bb0a..4009012bb0a 100644
--- a/app/assets/images/emoji/older_woman_tone5.png
+++ b/public/-/emojis/1/older_woman_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/om_symbol.png b/public/-/emojis/1/om_symbol.png
index a35c63c459c..a35c63c459c 100644
--- a/app/assets/images/emoji/om_symbol.png
+++ b/public/-/emojis/1/om_symbol.png
Binary files differ
diff --git a/app/assets/images/emoji/on.png b/public/-/emojis/1/on.png
index a0c371ae21e..a0c371ae21e 100644
--- a/app/assets/images/emoji/on.png
+++ b/public/-/emojis/1/on.png
Binary files differ
diff --git a/app/assets/images/emoji/oncoming_automobile.png b/public/-/emojis/1/oncoming_automobile.png
index 3c7e1d52e63..3c7e1d52e63 100644
--- a/app/assets/images/emoji/oncoming_automobile.png
+++ b/public/-/emojis/1/oncoming_automobile.png
Binary files differ
diff --git a/app/assets/images/emoji/oncoming_bus.png b/public/-/emojis/1/oncoming_bus.png
index ad91e256c7f..ad91e256c7f 100644
--- a/app/assets/images/emoji/oncoming_bus.png
+++ b/public/-/emojis/1/oncoming_bus.png
Binary files differ
diff --git a/app/assets/images/emoji/oncoming_police_car.png b/public/-/emojis/1/oncoming_police_car.png
index c9109c85b5d..c9109c85b5d 100644
--- a/app/assets/images/emoji/oncoming_police_car.png
+++ b/public/-/emojis/1/oncoming_police_car.png
Binary files differ
diff --git a/app/assets/images/emoji/oncoming_taxi.png b/public/-/emojis/1/oncoming_taxi.png
index fea14e45846..fea14e45846 100644
--- a/app/assets/images/emoji/oncoming_taxi.png
+++ b/public/-/emojis/1/oncoming_taxi.png
Binary files differ
diff --git a/app/assets/images/emoji/one.png b/public/-/emojis/1/one.png
index e6d84b80128..e6d84b80128 100644
--- a/app/assets/images/emoji/one.png
+++ b/public/-/emojis/1/one.png
Binary files differ
diff --git a/app/assets/images/emoji/open_file_folder.png b/public/-/emojis/1/open_file_folder.png
index 3993b09222f..3993b09222f 100644
--- a/app/assets/images/emoji/open_file_folder.png
+++ b/public/-/emojis/1/open_file_folder.png
Binary files differ
diff --git a/app/assets/images/emoji/open_hands.png b/public/-/emojis/1/open_hands.png
index 1cf75c9101e..1cf75c9101e 100644
--- a/app/assets/images/emoji/open_hands.png
+++ b/public/-/emojis/1/open_hands.png
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone1.png b/public/-/emojis/1/open_hands_tone1.png
index 352d2614f11..352d2614f11 100644
--- a/app/assets/images/emoji/open_hands_tone1.png
+++ b/public/-/emojis/1/open_hands_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone2.png b/public/-/emojis/1/open_hands_tone2.png
index 70824a50c73..70824a50c73 100644
--- a/app/assets/images/emoji/open_hands_tone2.png
+++ b/public/-/emojis/1/open_hands_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone3.png b/public/-/emojis/1/open_hands_tone3.png
index d7d136bd3db..d7d136bd3db 100644
--- a/app/assets/images/emoji/open_hands_tone3.png
+++ b/public/-/emojis/1/open_hands_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone4.png b/public/-/emojis/1/open_hands_tone4.png
index df4eaa711e7..df4eaa711e7 100644
--- a/app/assets/images/emoji/open_hands_tone4.png
+++ b/public/-/emojis/1/open_hands_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone5.png b/public/-/emojis/1/open_hands_tone5.png
index 7dc04eaebd8..7dc04eaebd8 100644
--- a/app/assets/images/emoji/open_hands_tone5.png
+++ b/public/-/emojis/1/open_hands_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/open_mouth.png b/public/-/emojis/1/open_mouth.png
index a62cd27e148..a62cd27e148 100644
--- a/app/assets/images/emoji/open_mouth.png
+++ b/public/-/emojis/1/open_mouth.png
Binary files differ
diff --git a/app/assets/images/emoji/ophiuchus.png b/public/-/emojis/1/ophiuchus.png
index 0a780a700da..0a780a700da 100644
--- a/app/assets/images/emoji/ophiuchus.png
+++ b/public/-/emojis/1/ophiuchus.png
Binary files differ
diff --git a/app/assets/images/emoji/orange_book.png b/public/-/emojis/1/orange_book.png
index ab40e6ae6a2..ab40e6ae6a2 100644
--- a/app/assets/images/emoji/orange_book.png
+++ b/public/-/emojis/1/orange_book.png
Binary files differ
diff --git a/app/assets/images/emoji/orthodox_cross.png b/public/-/emojis/1/orthodox_cross.png
index 0530e33a4d4..0530e33a4d4 100644
--- a/app/assets/images/emoji/orthodox_cross.png
+++ b/public/-/emojis/1/orthodox_cross.png
Binary files differ
diff --git a/app/assets/images/emoji/outbox_tray.png b/public/-/emojis/1/outbox_tray.png
index 46493ed5b2c..46493ed5b2c 100644
--- a/app/assets/images/emoji/outbox_tray.png
+++ b/public/-/emojis/1/outbox_tray.png
Binary files differ
diff --git a/app/assets/images/emoji/owl.png b/public/-/emojis/1/owl.png
index fa6815480c3..fa6815480c3 100644
--- a/app/assets/images/emoji/owl.png
+++ b/public/-/emojis/1/owl.png
Binary files differ
diff --git a/app/assets/images/emoji/ox.png b/public/-/emojis/1/ox.png
index badf5708f2f..badf5708f2f 100644
--- a/app/assets/images/emoji/ox.png
+++ b/public/-/emojis/1/ox.png
Binary files differ
diff --git a/app/assets/images/emoji/package.png b/public/-/emojis/1/package.png
index 85431756ad8..85431756ad8 100644
--- a/app/assets/images/emoji/package.png
+++ b/public/-/emojis/1/package.png
Binary files differ
diff --git a/app/assets/images/emoji/page_facing_up.png b/public/-/emojis/1/page_facing_up.png
index ba4ed757e01..ba4ed757e01 100644
--- a/app/assets/images/emoji/page_facing_up.png
+++ b/public/-/emojis/1/page_facing_up.png
Binary files differ
diff --git a/app/assets/images/emoji/page_with_curl.png b/public/-/emojis/1/page_with_curl.png
index 06355319c74..06355319c74 100644
--- a/app/assets/images/emoji/page_with_curl.png
+++ b/public/-/emojis/1/page_with_curl.png
Binary files differ
diff --git a/app/assets/images/emoji/pager.png b/public/-/emojis/1/pager.png
index b24b99306a2..b24b99306a2 100644
--- a/app/assets/images/emoji/pager.png
+++ b/public/-/emojis/1/pager.png
Binary files differ
diff --git a/app/assets/images/emoji/paintbrush.png b/public/-/emojis/1/paintbrush.png
index 28bffbaa3c9..28bffbaa3c9 100644
--- a/app/assets/images/emoji/paintbrush.png
+++ b/public/-/emojis/1/paintbrush.png
Binary files differ
diff --git a/app/assets/images/emoji/palm_tree.png b/public/-/emojis/1/palm_tree.png
index 4bbb10f4f19..4bbb10f4f19 100644
--- a/app/assets/images/emoji/palm_tree.png
+++ b/public/-/emojis/1/palm_tree.png
Binary files differ
diff --git a/app/assets/images/emoji/pancakes.png b/public/-/emojis/1/pancakes.png
index 6223d1a28e9..6223d1a28e9 100644
--- a/app/assets/images/emoji/pancakes.png
+++ b/public/-/emojis/1/pancakes.png
Binary files differ
diff --git a/app/assets/images/emoji/panda_face.png b/public/-/emojis/1/panda_face.png
index 978382775ce..978382775ce 100644
--- a/app/assets/images/emoji/panda_face.png
+++ b/public/-/emojis/1/panda_face.png
Binary files differ
diff --git a/app/assets/images/emoji/paperclip.png b/public/-/emojis/1/paperclip.png
index 8cd8d4f8750..8cd8d4f8750 100644
--- a/app/assets/images/emoji/paperclip.png
+++ b/public/-/emojis/1/paperclip.png
Binary files differ
diff --git a/app/assets/images/emoji/paperclips.png b/public/-/emojis/1/paperclips.png
index 76021e8c705..76021e8c705 100644
--- a/app/assets/images/emoji/paperclips.png
+++ b/public/-/emojis/1/paperclips.png
Binary files differ
diff --git a/app/assets/images/emoji/park.png b/public/-/emojis/1/park.png
index 63ec7016301..63ec7016301 100644
--- a/app/assets/images/emoji/park.png
+++ b/public/-/emojis/1/park.png
Binary files differ
diff --git a/app/assets/images/emoji/parking.png b/public/-/emojis/1/parking.png
index 7be7dac27e8..7be7dac27e8 100644
--- a/app/assets/images/emoji/parking.png
+++ b/public/-/emojis/1/parking.png
Binary files differ
diff --git a/app/assets/images/emoji/part_alternation_mark.png b/public/-/emojis/1/part_alternation_mark.png
index 70453d41528..70453d41528 100644
--- a/app/assets/images/emoji/part_alternation_mark.png
+++ b/public/-/emojis/1/part_alternation_mark.png
Binary files differ
diff --git a/app/assets/images/emoji/partly_sunny.png b/public/-/emojis/1/partly_sunny.png
index a55e59c344c..a55e59c344c 100644
--- a/app/assets/images/emoji/partly_sunny.png
+++ b/public/-/emojis/1/partly_sunny.png
Binary files differ
diff --git a/app/assets/images/emoji/passport_control.png b/public/-/emojis/1/passport_control.png
index 079e34ee4d4..079e34ee4d4 100644
--- a/app/assets/images/emoji/passport_control.png
+++ b/public/-/emojis/1/passport_control.png
Binary files differ
diff --git a/app/assets/images/emoji/pause_button.png b/public/-/emojis/1/pause_button.png
index 4f07e7ebfd7..4f07e7ebfd7 100644
--- a/app/assets/images/emoji/pause_button.png
+++ b/public/-/emojis/1/pause_button.png
Binary files differ
diff --git a/app/assets/images/emoji/peace.png b/public/-/emojis/1/peace.png
index 86033faf477..86033faf477 100644
--- a/app/assets/images/emoji/peace.png
+++ b/public/-/emojis/1/peace.png
Binary files differ
diff --git a/app/assets/images/emoji/peach.png b/public/-/emojis/1/peach.png
index 9ab57cbb758..9ab57cbb758 100644
--- a/app/assets/images/emoji/peach.png
+++ b/public/-/emojis/1/peach.png
Binary files differ
diff --git a/app/assets/images/emoji/peanuts.png b/public/-/emojis/1/peanuts.png
index b64fadad010..b64fadad010 100644
--- a/app/assets/images/emoji/peanuts.png
+++ b/public/-/emojis/1/peanuts.png
Binary files differ
diff --git a/app/assets/images/emoji/pear.png b/public/-/emojis/1/pear.png
index 3869f718bcf..3869f718bcf 100644
--- a/app/assets/images/emoji/pear.png
+++ b/public/-/emojis/1/pear.png
Binary files differ
diff --git a/app/assets/images/emoji/pen_ballpoint.png b/public/-/emojis/1/pen_ballpoint.png
index 6ef7a342433..6ef7a342433 100644
--- a/app/assets/images/emoji/pen_ballpoint.png
+++ b/public/-/emojis/1/pen_ballpoint.png
Binary files differ
diff --git a/app/assets/images/emoji/pen_fountain.png b/public/-/emojis/1/pen_fountain.png
index 3ca4bd2c231..3ca4bd2c231 100644
--- a/app/assets/images/emoji/pen_fountain.png
+++ b/public/-/emojis/1/pen_fountain.png
Binary files differ
diff --git a/app/assets/images/emoji/pencil.png b/public/-/emojis/1/pencil.png
index edc6155e168..edc6155e168 100644
--- a/app/assets/images/emoji/pencil.png
+++ b/public/-/emojis/1/pencil.png
Binary files differ
diff --git a/app/assets/images/emoji/pencil2.png b/public/-/emojis/1/pencil2.png
index 3833d590fa2..3833d590fa2 100644
--- a/app/assets/images/emoji/pencil2.png
+++ b/public/-/emojis/1/pencil2.png
Binary files differ
diff --git a/app/assets/images/emoji/penguin.png b/public/-/emojis/1/penguin.png
index c0064fb9734..c0064fb9734 100644
--- a/app/assets/images/emoji/penguin.png
+++ b/public/-/emojis/1/penguin.png
Binary files differ
diff --git a/app/assets/images/emoji/pensive.png b/public/-/emojis/1/pensive.png
index 490fb566954..490fb566954 100644
--- a/app/assets/images/emoji/pensive.png
+++ b/public/-/emojis/1/pensive.png
Binary files differ
diff --git a/app/assets/images/emoji/performing_arts.png b/public/-/emojis/1/performing_arts.png
index 685441fdaa1..685441fdaa1 100644
--- a/app/assets/images/emoji/performing_arts.png
+++ b/public/-/emojis/1/performing_arts.png
Binary files differ
diff --git a/app/assets/images/emoji/persevere.png b/public/-/emojis/1/persevere.png
index 646a05fe908..646a05fe908 100644
--- a/app/assets/images/emoji/persevere.png
+++ b/public/-/emojis/1/persevere.png
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning.png b/public/-/emojis/1/person_frowning.png
index 579324959a1..579324959a1 100644
--- a/app/assets/images/emoji/person_frowning.png
+++ b/public/-/emojis/1/person_frowning.png
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone1.png b/public/-/emojis/1/person_frowning_tone1.png
index 21d3bb43923..21d3bb43923 100644
--- a/app/assets/images/emoji/person_frowning_tone1.png
+++ b/public/-/emojis/1/person_frowning_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone2.png b/public/-/emojis/1/person_frowning_tone2.png
index 973f5fc8382..973f5fc8382 100644
--- a/app/assets/images/emoji/person_frowning_tone2.png
+++ b/public/-/emojis/1/person_frowning_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone3.png b/public/-/emojis/1/person_frowning_tone3.png
index 41fbcc78816..41fbcc78816 100644
--- a/app/assets/images/emoji/person_frowning_tone3.png
+++ b/public/-/emojis/1/person_frowning_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone4.png b/public/-/emojis/1/person_frowning_tone4.png
index 5a37c741030..5a37c741030 100644
--- a/app/assets/images/emoji/person_frowning_tone4.png
+++ b/public/-/emojis/1/person_frowning_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone5.png b/public/-/emojis/1/person_frowning_tone5.png
index e08141f3efe..e08141f3efe 100644
--- a/app/assets/images/emoji/person_frowning_tone5.png
+++ b/public/-/emojis/1/person_frowning_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair.png b/public/-/emojis/1/person_with_blond_hair.png
index ad6f01a7dda..ad6f01a7dda 100644
--- a/app/assets/images/emoji/person_with_blond_hair.png
+++ b/public/-/emojis/1/person_with_blond_hair.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone1.png b/public/-/emojis/1/person_with_blond_hair_tone1.png
index 7d18ef24445..7d18ef24445 100644
--- a/app/assets/images/emoji/person_with_blond_hair_tone1.png
+++ b/public/-/emojis/1/person_with_blond_hair_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone2.png b/public/-/emojis/1/person_with_blond_hair_tone2.png
index dae1307315c..dae1307315c 100644
--- a/app/assets/images/emoji/person_with_blond_hair_tone2.png
+++ b/public/-/emojis/1/person_with_blond_hair_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone3.png b/public/-/emojis/1/person_with_blond_hair_tone3.png
index 684677e8e5a..684677e8e5a 100644
--- a/app/assets/images/emoji/person_with_blond_hair_tone3.png
+++ b/public/-/emojis/1/person_with_blond_hair_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone4.png b/public/-/emojis/1/person_with_blond_hair_tone4.png
index 012be0b51f8..012be0b51f8 100644
--- a/app/assets/images/emoji/person_with_blond_hair_tone4.png
+++ b/public/-/emojis/1/person_with_blond_hair_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone5.png b/public/-/emojis/1/person_with_blond_hair_tone5.png
index d4ecc4cf44b..d4ecc4cf44b 100644
--- a/app/assets/images/emoji/person_with_blond_hair_tone5.png
+++ b/public/-/emojis/1/person_with_blond_hair_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face.png b/public/-/emojis/1/person_with_pouting_face.png
index 10eb0571078..10eb0571078 100644
--- a/app/assets/images/emoji/person_with_pouting_face.png
+++ b/public/-/emojis/1/person_with_pouting_face.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone1.png b/public/-/emojis/1/person_with_pouting_face_tone1.png
index 57e826b75a4..57e826b75a4 100644
--- a/app/assets/images/emoji/person_with_pouting_face_tone1.png
+++ b/public/-/emojis/1/person_with_pouting_face_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone2.png b/public/-/emojis/1/person_with_pouting_face_tone2.png
index 3f317c0c25f..3f317c0c25f 100644
--- a/app/assets/images/emoji/person_with_pouting_face_tone2.png
+++ b/public/-/emojis/1/person_with_pouting_face_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone3.png b/public/-/emojis/1/person_with_pouting_face_tone3.png
index d2fbb6c20bf..d2fbb6c20bf 100644
--- a/app/assets/images/emoji/person_with_pouting_face_tone3.png
+++ b/public/-/emojis/1/person_with_pouting_face_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone4.png b/public/-/emojis/1/person_with_pouting_face_tone4.png
index 643ceb4a5c5..643ceb4a5c5 100644
--- a/app/assets/images/emoji/person_with_pouting_face_tone4.png
+++ b/public/-/emojis/1/person_with_pouting_face_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone5.png b/public/-/emojis/1/person_with_pouting_face_tone5.png
index b2eb6859c32..b2eb6859c32 100644
--- a/app/assets/images/emoji/person_with_pouting_face_tone5.png
+++ b/public/-/emojis/1/person_with_pouting_face_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/pick.png b/public/-/emojis/1/pick.png
index 6370fe6d791..6370fe6d791 100644
--- a/app/assets/images/emoji/pick.png
+++ b/public/-/emojis/1/pick.png
Binary files differ
diff --git a/app/assets/images/emoji/pig.png b/public/-/emojis/1/pig.png
index afe05ca1676..afe05ca1676 100644
--- a/app/assets/images/emoji/pig.png
+++ b/public/-/emojis/1/pig.png
Binary files differ
diff --git a/app/assets/images/emoji/pig2.png b/public/-/emojis/1/pig2.png
index 5f31c1a2d75..5f31c1a2d75 100644
--- a/app/assets/images/emoji/pig2.png
+++ b/public/-/emojis/1/pig2.png
Binary files differ
diff --git a/app/assets/images/emoji/pig_nose.png b/public/-/emojis/1/pig_nose.png
index 3610ae4a910..3610ae4a910 100644
--- a/app/assets/images/emoji/pig_nose.png
+++ b/public/-/emojis/1/pig_nose.png
Binary files differ
diff --git a/app/assets/images/emoji/pill.png b/public/-/emojis/1/pill.png
index 1d4530e77a3..1d4530e77a3 100644
--- a/app/assets/images/emoji/pill.png
+++ b/public/-/emojis/1/pill.png
Binary files differ
diff --git a/app/assets/images/emoji/pineapple.png b/public/-/emojis/1/pineapple.png
index c89a1606462..c89a1606462 100644
--- a/app/assets/images/emoji/pineapple.png
+++ b/public/-/emojis/1/pineapple.png
Binary files differ
diff --git a/app/assets/images/emoji/ping_pong.png b/public/-/emojis/1/ping_pong.png
index ff3c51727d1..ff3c51727d1 100644
--- a/app/assets/images/emoji/ping_pong.png
+++ b/public/-/emojis/1/ping_pong.png
Binary files differ
diff --git a/app/assets/images/emoji/pisces.png b/public/-/emojis/1/pisces.png
index 7f6f646a95c..7f6f646a95c 100644
--- a/app/assets/images/emoji/pisces.png
+++ b/public/-/emojis/1/pisces.png
Binary files differ
diff --git a/app/assets/images/emoji/pizza.png b/public/-/emojis/1/pizza.png
index e07365cb398..e07365cb398 100644
--- a/app/assets/images/emoji/pizza.png
+++ b/public/-/emojis/1/pizza.png
Binary files differ
diff --git a/app/assets/images/emoji/place_of_worship.png b/public/-/emojis/1/place_of_worship.png
index 207d59cce85..207d59cce85 100644
--- a/app/assets/images/emoji/place_of_worship.png
+++ b/public/-/emojis/1/place_of_worship.png
Binary files differ
diff --git a/app/assets/images/emoji/play_pause.png b/public/-/emojis/1/play_pause.png
index a9f857139ac..a9f857139ac 100644
--- a/app/assets/images/emoji/play_pause.png
+++ b/public/-/emojis/1/play_pause.png
Binary files differ
diff --git a/app/assets/images/emoji/point_down.png b/public/-/emojis/1/point_down.png
index 00d3d13ab5c..00d3d13ab5c 100644
--- a/app/assets/images/emoji/point_down.png
+++ b/public/-/emojis/1/point_down.png
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone1.png b/public/-/emojis/1/point_down_tone1.png
index 140f157d8c7..140f157d8c7 100644
--- a/app/assets/images/emoji/point_down_tone1.png
+++ b/public/-/emojis/1/point_down_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone2.png b/public/-/emojis/1/point_down_tone2.png
index d518544f7fa..d518544f7fa 100644
--- a/app/assets/images/emoji/point_down_tone2.png
+++ b/public/-/emojis/1/point_down_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone3.png b/public/-/emojis/1/point_down_tone3.png
index 018b688b8b7..018b688b8b7 100644
--- a/app/assets/images/emoji/point_down_tone3.png
+++ b/public/-/emojis/1/point_down_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone4.png b/public/-/emojis/1/point_down_tone4.png
index 98845bf6f72..98845bf6f72 100644
--- a/app/assets/images/emoji/point_down_tone4.png
+++ b/public/-/emojis/1/point_down_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone5.png b/public/-/emojis/1/point_down_tone5.png
index 9a9b039a9fc..9a9b039a9fc 100644
--- a/app/assets/images/emoji/point_down_tone5.png
+++ b/public/-/emojis/1/point_down_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/point_left.png b/public/-/emojis/1/point_left.png
index 599fa2e3cf1..599fa2e3cf1 100644
--- a/app/assets/images/emoji/point_left.png
+++ b/public/-/emojis/1/point_left.png
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone1.png b/public/-/emojis/1/point_left_tone1.png
index 88e2c306076..88e2c306076 100644
--- a/app/assets/images/emoji/point_left_tone1.png
+++ b/public/-/emojis/1/point_left_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone2.png b/public/-/emojis/1/point_left_tone2.png
index d3c89d87c5f..d3c89d87c5f 100644
--- a/app/assets/images/emoji/point_left_tone2.png
+++ b/public/-/emojis/1/point_left_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone3.png b/public/-/emojis/1/point_left_tone3.png
index b23b9167358..b23b9167358 100644
--- a/app/assets/images/emoji/point_left_tone3.png
+++ b/public/-/emojis/1/point_left_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone4.png b/public/-/emojis/1/point_left_tone4.png
index 3093f325c27..3093f325c27 100644
--- a/app/assets/images/emoji/point_left_tone4.png
+++ b/public/-/emojis/1/point_left_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone5.png b/public/-/emojis/1/point_left_tone5.png
index 2b4cbfa120c..2b4cbfa120c 100644
--- a/app/assets/images/emoji/point_left_tone5.png
+++ b/public/-/emojis/1/point_left_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/point_right.png b/public/-/emojis/1/point_right.png
index 93a3cd34aa5..93a3cd34aa5 100644
--- a/app/assets/images/emoji/point_right.png
+++ b/public/-/emojis/1/point_right.png
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone1.png b/public/-/emojis/1/point_right_tone1.png
index 4a28c6bbc89..4a28c6bbc89 100644
--- a/app/assets/images/emoji/point_right_tone1.png
+++ b/public/-/emojis/1/point_right_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone2.png b/public/-/emojis/1/point_right_tone2.png
index 7cb13231733..7cb13231733 100644
--- a/app/assets/images/emoji/point_right_tone2.png
+++ b/public/-/emojis/1/point_right_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone3.png b/public/-/emojis/1/point_right_tone3.png
index 5514807d71a..5514807d71a 100644
--- a/app/assets/images/emoji/point_right_tone3.png
+++ b/public/-/emojis/1/point_right_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone4.png b/public/-/emojis/1/point_right_tone4.png
index b8541d6440d..b8541d6440d 100644
--- a/app/assets/images/emoji/point_right_tone4.png
+++ b/public/-/emojis/1/point_right_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone5.png b/public/-/emojis/1/point_right_tone5.png
index 1b7aab07bb1..1b7aab07bb1 100644
--- a/app/assets/images/emoji/point_right_tone5.png
+++ b/public/-/emojis/1/point_right_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up.png b/public/-/emojis/1/point_up.png
index f4978ff0f00..f4978ff0f00 100644
--- a/app/assets/images/emoji/point_up.png
+++ b/public/-/emojis/1/point_up.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2.png b/public/-/emojis/1/point_up_2.png
index bc496dfeae4..bc496dfeae4 100644
--- a/app/assets/images/emoji/point_up_2.png
+++ b/public/-/emojis/1/point_up_2.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone1.png b/public/-/emojis/1/point_up_2_tone1.png
index a12a7e78430..a12a7e78430 100644
--- a/app/assets/images/emoji/point_up_2_tone1.png
+++ b/public/-/emojis/1/point_up_2_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone2.png b/public/-/emojis/1/point_up_2_tone2.png
index cdff40ceab0..cdff40ceab0 100644
--- a/app/assets/images/emoji/point_up_2_tone2.png
+++ b/public/-/emojis/1/point_up_2_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone3.png b/public/-/emojis/1/point_up_2_tone3.png
index a07ce9e5ae8..a07ce9e5ae8 100644
--- a/app/assets/images/emoji/point_up_2_tone3.png
+++ b/public/-/emojis/1/point_up_2_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone4.png b/public/-/emojis/1/point_up_2_tone4.png
index 4f86c88ba42..4f86c88ba42 100644
--- a/app/assets/images/emoji/point_up_2_tone4.png
+++ b/public/-/emojis/1/point_up_2_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone5.png b/public/-/emojis/1/point_up_2_tone5.png
index ed1b26c35d3..ed1b26c35d3 100644
--- a/app/assets/images/emoji/point_up_2_tone5.png
+++ b/public/-/emojis/1/point_up_2_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone1.png b/public/-/emojis/1/point_up_tone1.png
index 6a9db21d64c..6a9db21d64c 100644
--- a/app/assets/images/emoji/point_up_tone1.png
+++ b/public/-/emojis/1/point_up_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone2.png b/public/-/emojis/1/point_up_tone2.png
index 15aa9ea0e05..15aa9ea0e05 100644
--- a/app/assets/images/emoji/point_up_tone2.png
+++ b/public/-/emojis/1/point_up_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone3.png b/public/-/emojis/1/point_up_tone3.png
index 652b73a9c5d..652b73a9c5d 100644
--- a/app/assets/images/emoji/point_up_tone3.png
+++ b/public/-/emojis/1/point_up_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone4.png b/public/-/emojis/1/point_up_tone4.png
index 692bad926e9..692bad926e9 100644
--- a/app/assets/images/emoji/point_up_tone4.png
+++ b/public/-/emojis/1/point_up_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone5.png b/public/-/emojis/1/point_up_tone5.png
index 1e1b10fb71c..1e1b10fb71c 100644
--- a/app/assets/images/emoji/point_up_tone5.png
+++ b/public/-/emojis/1/point_up_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/police_car.png b/public/-/emojis/1/police_car.png
index 3da4253de7e..3da4253de7e 100644
--- a/app/assets/images/emoji/police_car.png
+++ b/public/-/emojis/1/police_car.png
Binary files differ
diff --git a/app/assets/images/emoji/poodle.png b/public/-/emojis/1/poodle.png
index 8ec39e396af..8ec39e396af 100644
--- a/app/assets/images/emoji/poodle.png
+++ b/public/-/emojis/1/poodle.png
Binary files differ
diff --git a/app/assets/images/emoji/poop.png b/public/-/emojis/1/poop.png
index 10b15e72d56..10b15e72d56 100644
--- a/app/assets/images/emoji/poop.png
+++ b/public/-/emojis/1/poop.png
Binary files differ
diff --git a/app/assets/images/emoji/popcorn.png b/public/-/emojis/1/popcorn.png
index 36853e381d4..36853e381d4 100644
--- a/app/assets/images/emoji/popcorn.png
+++ b/public/-/emojis/1/popcorn.png
Binary files differ
diff --git a/app/assets/images/emoji/post_office.png b/public/-/emojis/1/post_office.png
index a23848f9aa0..a23848f9aa0 100644
--- a/app/assets/images/emoji/post_office.png
+++ b/public/-/emojis/1/post_office.png
Binary files differ
diff --git a/app/assets/images/emoji/postal_horn.png b/public/-/emojis/1/postal_horn.png
index c173b8dbd67..c173b8dbd67 100644
--- a/app/assets/images/emoji/postal_horn.png
+++ b/public/-/emojis/1/postal_horn.png
Binary files differ
diff --git a/app/assets/images/emoji/postbox.png b/public/-/emojis/1/postbox.png
index 07c9c4ab3d6..07c9c4ab3d6 100644
--- a/app/assets/images/emoji/postbox.png
+++ b/public/-/emojis/1/postbox.png
Binary files differ
diff --git a/app/assets/images/emoji/potable_water.png b/public/-/emojis/1/potable_water.png
index 2c610049459..2c610049459 100644
--- a/app/assets/images/emoji/potable_water.png
+++ b/public/-/emojis/1/potable_water.png
Binary files differ
diff --git a/app/assets/images/emoji/potato.png b/public/-/emojis/1/potato.png
index 70350ca2c0a..70350ca2c0a 100644
--- a/app/assets/images/emoji/potato.png
+++ b/public/-/emojis/1/potato.png
Binary files differ
diff --git a/app/assets/images/emoji/pouch.png b/public/-/emojis/1/pouch.png
index 8795c6c66ff..8795c6c66ff 100644
--- a/app/assets/images/emoji/pouch.png
+++ b/public/-/emojis/1/pouch.png
Binary files differ
diff --git a/app/assets/images/emoji/poultry_leg.png b/public/-/emojis/1/poultry_leg.png
index eea4a53a2f9..eea4a53a2f9 100644
--- a/app/assets/images/emoji/poultry_leg.png
+++ b/public/-/emojis/1/poultry_leg.png
Binary files differ
diff --git a/app/assets/images/emoji/pound.png b/public/-/emojis/1/pound.png
index a0d4c4099e9..a0d4c4099e9 100644
--- a/app/assets/images/emoji/pound.png
+++ b/public/-/emojis/1/pound.png
Binary files differ
diff --git a/app/assets/images/emoji/pouting_cat.png b/public/-/emojis/1/pouting_cat.png
index 41ddfeab42b..41ddfeab42b 100644
--- a/app/assets/images/emoji/pouting_cat.png
+++ b/public/-/emojis/1/pouting_cat.png
Binary files differ
diff --git a/app/assets/images/emoji/pray.png b/public/-/emojis/1/pray.png
index 8347f2435be..8347f2435be 100644
--- a/app/assets/images/emoji/pray.png
+++ b/public/-/emojis/1/pray.png
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone1.png b/public/-/emojis/1/pray_tone1.png
index 060ef257172..060ef257172 100644
--- a/app/assets/images/emoji/pray_tone1.png
+++ b/public/-/emojis/1/pray_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone2.png b/public/-/emojis/1/pray_tone2.png
index 56dc607c07a..56dc607c07a 100644
--- a/app/assets/images/emoji/pray_tone2.png
+++ b/public/-/emojis/1/pray_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone3.png b/public/-/emojis/1/pray_tone3.png
index 0f33b862008..0f33b862008 100644
--- a/app/assets/images/emoji/pray_tone3.png
+++ b/public/-/emojis/1/pray_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone4.png b/public/-/emojis/1/pray_tone4.png
index 2ea8dc11657..2ea8dc11657 100644
--- a/app/assets/images/emoji/pray_tone4.png
+++ b/public/-/emojis/1/pray_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone5.png b/public/-/emojis/1/pray_tone5.png
index 2128a6c4703..2128a6c4703 100644
--- a/app/assets/images/emoji/pray_tone5.png
+++ b/public/-/emojis/1/pray_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/prayer_beads.png b/public/-/emojis/1/prayer_beads.png
index a4b6dfcc62e..a4b6dfcc62e 100644
--- a/app/assets/images/emoji/prayer_beads.png
+++ b/public/-/emojis/1/prayer_beads.png
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman.png b/public/-/emojis/1/pregnant_woman.png
index 084e83a414a..084e83a414a 100644
--- a/app/assets/images/emoji/pregnant_woman.png
+++ b/public/-/emojis/1/pregnant_woman.png
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone1.png b/public/-/emojis/1/pregnant_woman_tone1.png
index a78703b33aa..a78703b33aa 100644
--- a/app/assets/images/emoji/pregnant_woman_tone1.png
+++ b/public/-/emojis/1/pregnant_woman_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone2.png b/public/-/emojis/1/pregnant_woman_tone2.png
index 0068c6c4a77..0068c6c4a77 100644
--- a/app/assets/images/emoji/pregnant_woman_tone2.png
+++ b/public/-/emojis/1/pregnant_woman_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone3.png b/public/-/emojis/1/pregnant_woman_tone3.png
index 3206296b684..3206296b684 100644
--- a/app/assets/images/emoji/pregnant_woman_tone3.png
+++ b/public/-/emojis/1/pregnant_woman_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone4.png b/public/-/emojis/1/pregnant_woman_tone4.png
index 120fda5cd8c..120fda5cd8c 100644
--- a/app/assets/images/emoji/pregnant_woman_tone4.png
+++ b/public/-/emojis/1/pregnant_woman_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone5.png b/public/-/emojis/1/pregnant_woman_tone5.png
index 569bfdf05ce..569bfdf05ce 100644
--- a/app/assets/images/emoji/pregnant_woman_tone5.png
+++ b/public/-/emojis/1/pregnant_woman_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/prince.png b/public/-/emojis/1/prince.png
index 38d69344c84..38d69344c84 100644
--- a/app/assets/images/emoji/prince.png
+++ b/public/-/emojis/1/prince.png
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone1.png b/public/-/emojis/1/prince_tone1.png
index 849930c8887..849930c8887 100644
--- a/app/assets/images/emoji/prince_tone1.png
+++ b/public/-/emojis/1/prince_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone2.png b/public/-/emojis/1/prince_tone2.png
index 23d8b3b1285..23d8b3b1285 100644
--- a/app/assets/images/emoji/prince_tone2.png
+++ b/public/-/emojis/1/prince_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone3.png b/public/-/emojis/1/prince_tone3.png
index db6dfff0647..db6dfff0647 100644
--- a/app/assets/images/emoji/prince_tone3.png
+++ b/public/-/emojis/1/prince_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone4.png b/public/-/emojis/1/prince_tone4.png
index 8e10f8be6a8..8e10f8be6a8 100644
--- a/app/assets/images/emoji/prince_tone4.png
+++ b/public/-/emojis/1/prince_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone5.png b/public/-/emojis/1/prince_tone5.png
index 138d4ea7048..138d4ea7048 100644
--- a/app/assets/images/emoji/prince_tone5.png
+++ b/public/-/emojis/1/prince_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/princess.png b/public/-/emojis/1/princess.png
index 879e9fa8c5d..879e9fa8c5d 100644
--- a/app/assets/images/emoji/princess.png
+++ b/public/-/emojis/1/princess.png
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone1.png b/public/-/emojis/1/princess_tone1.png
index c28078cdc36..c28078cdc36 100644
--- a/app/assets/images/emoji/princess_tone1.png
+++ b/public/-/emojis/1/princess_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone2.png b/public/-/emojis/1/princess_tone2.png
index dcd20e6ecd4..dcd20e6ecd4 100644
--- a/app/assets/images/emoji/princess_tone2.png
+++ b/public/-/emojis/1/princess_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone3.png b/public/-/emojis/1/princess_tone3.png
index cde6f315c56..cde6f315c56 100644
--- a/app/assets/images/emoji/princess_tone3.png
+++ b/public/-/emojis/1/princess_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone4.png b/public/-/emojis/1/princess_tone4.png
index c71e69caaef..c71e69caaef 100644
--- a/app/assets/images/emoji/princess_tone4.png
+++ b/public/-/emojis/1/princess_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone5.png b/public/-/emojis/1/princess_tone5.png
index 063e2645910..063e2645910 100644
--- a/app/assets/images/emoji/princess_tone5.png
+++ b/public/-/emojis/1/princess_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/printer.png b/public/-/emojis/1/printer.png
index 027c830f0fe..027c830f0fe 100644
--- a/app/assets/images/emoji/printer.png
+++ b/public/-/emojis/1/printer.png
Binary files differ
diff --git a/app/assets/images/emoji/projector.png b/public/-/emojis/1/projector.png
index ce9ab0daa28..ce9ab0daa28 100644
--- a/app/assets/images/emoji/projector.png
+++ b/public/-/emojis/1/projector.png
Binary files differ
diff --git a/app/assets/images/emoji/punch.png b/public/-/emojis/1/punch.png
index b14ca5f5211..b14ca5f5211 100644
--- a/app/assets/images/emoji/punch.png
+++ b/public/-/emojis/1/punch.png
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone1.png b/public/-/emojis/1/punch_tone1.png
index 93c7d17fb47..93c7d17fb47 100644
--- a/app/assets/images/emoji/punch_tone1.png
+++ b/public/-/emojis/1/punch_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone2.png b/public/-/emojis/1/punch_tone2.png
index c0a1af6e10a..c0a1af6e10a 100644
--- a/app/assets/images/emoji/punch_tone2.png
+++ b/public/-/emojis/1/punch_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone3.png b/public/-/emojis/1/punch_tone3.png
index 1458b021201..1458b021201 100644
--- a/app/assets/images/emoji/punch_tone3.png
+++ b/public/-/emojis/1/punch_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone4.png b/public/-/emojis/1/punch_tone4.png
index c1466bfcdef..c1466bfcdef 100644
--- a/app/assets/images/emoji/punch_tone4.png
+++ b/public/-/emojis/1/punch_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone5.png b/public/-/emojis/1/punch_tone5.png
index 00b4ddb8953..00b4ddb8953 100644
--- a/app/assets/images/emoji/punch_tone5.png
+++ b/public/-/emojis/1/punch_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/purple_heart.png b/public/-/emojis/1/purple_heart.png
index 95c53a9ade6..95c53a9ade6 100644
--- a/app/assets/images/emoji/purple_heart.png
+++ b/public/-/emojis/1/purple_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/purse.png b/public/-/emojis/1/purse.png
index 981346193c5..981346193c5 100644
--- a/app/assets/images/emoji/purse.png
+++ b/public/-/emojis/1/purse.png
Binary files differ
diff --git a/app/assets/images/emoji/pushpin.png b/public/-/emojis/1/pushpin.png
index 57e07d7f4cc..57e07d7f4cc 100644
--- a/app/assets/images/emoji/pushpin.png
+++ b/public/-/emojis/1/pushpin.png
Binary files differ
diff --git a/app/assets/images/emoji/put_litter_in_its_place.png b/public/-/emojis/1/put_litter_in_its_place.png
index 82a84f9a375..82a84f9a375 100644
--- a/app/assets/images/emoji/put_litter_in_its_place.png
+++ b/public/-/emojis/1/put_litter_in_its_place.png
Binary files differ
diff --git a/app/assets/images/emoji/question.png b/public/-/emojis/1/question.png
index 5a58f3458aa..5a58f3458aa 100644
--- a/app/assets/images/emoji/question.png
+++ b/public/-/emojis/1/question.png
Binary files differ
diff --git a/app/assets/images/emoji/rabbit.png b/public/-/emojis/1/rabbit.png
index ea75ab0426e..ea75ab0426e 100644
--- a/app/assets/images/emoji/rabbit.png
+++ b/public/-/emojis/1/rabbit.png
Binary files differ
diff --git a/app/assets/images/emoji/rabbit2.png b/public/-/emojis/1/rabbit2.png
index 2c8a29c642f..2c8a29c642f 100644
--- a/app/assets/images/emoji/rabbit2.png
+++ b/public/-/emojis/1/rabbit2.png
Binary files differ
diff --git a/app/assets/images/emoji/race_car.png b/public/-/emojis/1/race_car.png
index fe3f045f446..fe3f045f446 100644
--- a/app/assets/images/emoji/race_car.png
+++ b/public/-/emojis/1/race_car.png
Binary files differ
diff --git a/app/assets/images/emoji/racehorse.png b/public/-/emojis/1/racehorse.png
index b3e73cc8903..b3e73cc8903 100644
--- a/app/assets/images/emoji/racehorse.png
+++ b/public/-/emojis/1/racehorse.png
Binary files differ
diff --git a/app/assets/images/emoji/radio.png b/public/-/emojis/1/radio.png
index dec381fa242..dec381fa242 100644
--- a/app/assets/images/emoji/radio.png
+++ b/public/-/emojis/1/radio.png
Binary files differ
diff --git a/app/assets/images/emoji/radio_button.png b/public/-/emojis/1/radio_button.png
index 3a23449d917..3a23449d917 100644
--- a/app/assets/images/emoji/radio_button.png
+++ b/public/-/emojis/1/radio_button.png
Binary files differ
diff --git a/app/assets/images/emoji/radioactive.png b/public/-/emojis/1/radioactive.png
index 3b46199fe37..3b46199fe37 100644
--- a/app/assets/images/emoji/radioactive.png
+++ b/public/-/emojis/1/radioactive.png
Binary files differ
diff --git a/app/assets/images/emoji/rage.png b/public/-/emojis/1/rage.png
index 9d739bd40ad..9d739bd40ad 100644
--- a/app/assets/images/emoji/rage.png
+++ b/public/-/emojis/1/rage.png
Binary files differ
diff --git a/app/assets/images/emoji/railway_car.png b/public/-/emojis/1/railway_car.png
index a9acbf13008..a9acbf13008 100644
--- a/app/assets/images/emoji/railway_car.png
+++ b/public/-/emojis/1/railway_car.png
Binary files differ
diff --git a/app/assets/images/emoji/railway_track.png b/public/-/emojis/1/railway_track.png
index e1a7a0d1430..e1a7a0d1430 100644
--- a/app/assets/images/emoji/railway_track.png
+++ b/public/-/emojis/1/railway_track.png
Binary files differ
diff --git a/app/assets/images/emoji/rainbow.png b/public/-/emojis/1/rainbow.png
index 154735d7147..154735d7147 100644
--- a/app/assets/images/emoji/rainbow.png
+++ b/public/-/emojis/1/rainbow.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand.png b/public/-/emojis/1/raised_back_of_hand.png
index 479234294b4..479234294b4 100644
--- a/app/assets/images/emoji/raised_back_of_hand.png
+++ b/public/-/emojis/1/raised_back_of_hand.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone1.png b/public/-/emojis/1/raised_back_of_hand_tone1.png
index 813d28499b5..813d28499b5 100644
--- a/app/assets/images/emoji/raised_back_of_hand_tone1.png
+++ b/public/-/emojis/1/raised_back_of_hand_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone2.png b/public/-/emojis/1/raised_back_of_hand_tone2.png
index 192ff795e37..192ff795e37 100644
--- a/app/assets/images/emoji/raised_back_of_hand_tone2.png
+++ b/public/-/emojis/1/raised_back_of_hand_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone3.png b/public/-/emojis/1/raised_back_of_hand_tone3.png
index 61a727abe6b..61a727abe6b 100644
--- a/app/assets/images/emoji/raised_back_of_hand_tone3.png
+++ b/public/-/emojis/1/raised_back_of_hand_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone4.png b/public/-/emojis/1/raised_back_of_hand_tone4.png
index 2e83da511f5..2e83da511f5 100644
--- a/app/assets/images/emoji/raised_back_of_hand_tone4.png
+++ b/public/-/emojis/1/raised_back_of_hand_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone5.png b/public/-/emojis/1/raised_back_of_hand_tone5.png
index d7a5b95a02c..d7a5b95a02c 100644
--- a/app/assets/images/emoji/raised_back_of_hand_tone5.png
+++ b/public/-/emojis/1/raised_back_of_hand_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand.png b/public/-/emojis/1/raised_hand.png
index 6b2954315d1..6b2954315d1 100644
--- a/app/assets/images/emoji/raised_hand.png
+++ b/public/-/emojis/1/raised_hand.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone1.png b/public/-/emojis/1/raised_hand_tone1.png
index 3b752902c07..3b752902c07 100644
--- a/app/assets/images/emoji/raised_hand_tone1.png
+++ b/public/-/emojis/1/raised_hand_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone2.png b/public/-/emojis/1/raised_hand_tone2.png
index 44e2a514c60..44e2a514c60 100644
--- a/app/assets/images/emoji/raised_hand_tone2.png
+++ b/public/-/emojis/1/raised_hand_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone3.png b/public/-/emojis/1/raised_hand_tone3.png
index 5bb62a7528a..5bb62a7528a 100644
--- a/app/assets/images/emoji/raised_hand_tone3.png
+++ b/public/-/emojis/1/raised_hand_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone4.png b/public/-/emojis/1/raised_hand_tone4.png
index c7f8c9ec270..c7f8c9ec270 100644
--- a/app/assets/images/emoji/raised_hand_tone4.png
+++ b/public/-/emojis/1/raised_hand_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone5.png b/public/-/emojis/1/raised_hand_tone5.png
index c601b58a73e..c601b58a73e 100644
--- a/app/assets/images/emoji/raised_hand_tone5.png
+++ b/public/-/emojis/1/raised_hand_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands.png b/public/-/emojis/1/raised_hands.png
index c0155f728e7..c0155f728e7 100644
--- a/app/assets/images/emoji/raised_hands.png
+++ b/public/-/emojis/1/raised_hands.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone1.png b/public/-/emojis/1/raised_hands_tone1.png
index 1168b8236b6..1168b8236b6 100644
--- a/app/assets/images/emoji/raised_hands_tone1.png
+++ b/public/-/emojis/1/raised_hands_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone2.png b/public/-/emojis/1/raised_hands_tone2.png
index 322de622903..322de622903 100644
--- a/app/assets/images/emoji/raised_hands_tone2.png
+++ b/public/-/emojis/1/raised_hands_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone3.png b/public/-/emojis/1/raised_hands_tone3.png
index 2aa24e05ae1..2aa24e05ae1 100644
--- a/app/assets/images/emoji/raised_hands_tone3.png
+++ b/public/-/emojis/1/raised_hands_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone4.png b/public/-/emojis/1/raised_hands_tone4.png
index f31bf0db992..f31bf0db992 100644
--- a/app/assets/images/emoji/raised_hands_tone4.png
+++ b/public/-/emojis/1/raised_hands_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone5.png b/public/-/emojis/1/raised_hands_tone5.png
index 5e95067f98b..5e95067f98b 100644
--- a/app/assets/images/emoji/raised_hands_tone5.png
+++ b/public/-/emojis/1/raised_hands_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand.png b/public/-/emojis/1/raising_hand.png
index 2880708c0cc..2880708c0cc 100644
--- a/app/assets/images/emoji/raising_hand.png
+++ b/public/-/emojis/1/raising_hand.png
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone1.png b/public/-/emojis/1/raising_hand_tone1.png
index 1c90e3e2689..1c90e3e2689 100644
--- a/app/assets/images/emoji/raising_hand_tone1.png
+++ b/public/-/emojis/1/raising_hand_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone2.png b/public/-/emojis/1/raising_hand_tone2.png
index 82c3ef2bfc5..82c3ef2bfc5 100644
--- a/app/assets/images/emoji/raising_hand_tone2.png
+++ b/public/-/emojis/1/raising_hand_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone3.png b/public/-/emojis/1/raising_hand_tone3.png
index 1b1da2aa0ca..1b1da2aa0ca 100644
--- a/app/assets/images/emoji/raising_hand_tone3.png
+++ b/public/-/emojis/1/raising_hand_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone4.png b/public/-/emojis/1/raising_hand_tone4.png
index e453855c01f..e453855c01f 100644
--- a/app/assets/images/emoji/raising_hand_tone4.png
+++ b/public/-/emojis/1/raising_hand_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone5.png b/public/-/emojis/1/raising_hand_tone5.png
index b86200fd844..b86200fd844 100644
--- a/app/assets/images/emoji/raising_hand_tone5.png
+++ b/public/-/emojis/1/raising_hand_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/ram.png b/public/-/emojis/1/ram.png
index 52a44464c9b..52a44464c9b 100644
--- a/app/assets/images/emoji/ram.png
+++ b/public/-/emojis/1/ram.png
Binary files differ
diff --git a/app/assets/images/emoji/ramen.png b/public/-/emojis/1/ramen.png
index c1cb7cd7384..c1cb7cd7384 100644
--- a/app/assets/images/emoji/ramen.png
+++ b/public/-/emojis/1/ramen.png
Binary files differ
diff --git a/app/assets/images/emoji/rat.png b/public/-/emojis/1/rat.png
index 86219144f10..86219144f10 100644
--- a/app/assets/images/emoji/rat.png
+++ b/public/-/emojis/1/rat.png
Binary files differ
diff --git a/app/assets/images/emoji/record_button.png b/public/-/emojis/1/record_button.png
index ada52830fce..ada52830fce 100644
--- a/app/assets/images/emoji/record_button.png
+++ b/public/-/emojis/1/record_button.png
Binary files differ
diff --git a/app/assets/images/emoji/recycle.png b/public/-/emojis/1/recycle.png
index 9221f095c37..9221f095c37 100644
--- a/app/assets/images/emoji/recycle.png
+++ b/public/-/emojis/1/recycle.png
Binary files differ
diff --git a/app/assets/images/emoji/red_car.png b/public/-/emojis/1/red_car.png
index b3e6a774dea..b3e6a774dea 100644
--- a/app/assets/images/emoji/red_car.png
+++ b/public/-/emojis/1/red_car.png
Binary files differ
diff --git a/app/assets/images/emoji/red_circle.png b/public/-/emojis/1/red_circle.png
index 4bef930d92f..4bef930d92f 100644
--- a/app/assets/images/emoji/red_circle.png
+++ b/public/-/emojis/1/red_circle.png
Binary files differ
diff --git a/app/assets/images/emoji/registered.png b/public/-/emojis/1/registered.png
index 53ef9f2d4e6..53ef9f2d4e6 100644
--- a/app/assets/images/emoji/registered.png
+++ b/public/-/emojis/1/registered.png
Binary files differ
diff --git a/app/assets/images/emoji/relaxed.png b/public/-/emojis/1/relaxed.png
index e9e53c03d45..e9e53c03d45 100644
--- a/app/assets/images/emoji/relaxed.png
+++ b/public/-/emojis/1/relaxed.png
Binary files differ
diff --git a/app/assets/images/emoji/relieved.png b/public/-/emojis/1/relieved.png
index 715ad0bf53f..715ad0bf53f 100644
--- a/app/assets/images/emoji/relieved.png
+++ b/public/-/emojis/1/relieved.png
Binary files differ
diff --git a/app/assets/images/emoji/reminder_ribbon.png b/public/-/emojis/1/reminder_ribbon.png
index 3988bbd094c..3988bbd094c 100644
--- a/app/assets/images/emoji/reminder_ribbon.png
+++ b/public/-/emojis/1/reminder_ribbon.png
Binary files differ
diff --git a/app/assets/images/emoji/repeat.png b/public/-/emojis/1/repeat.png
index 540ce4e0fba..540ce4e0fba 100644
--- a/app/assets/images/emoji/repeat.png
+++ b/public/-/emojis/1/repeat.png
Binary files differ
diff --git a/app/assets/images/emoji/repeat_one.png b/public/-/emojis/1/repeat_one.png
index 9567e83337f..9567e83337f 100644
--- a/app/assets/images/emoji/repeat_one.png
+++ b/public/-/emojis/1/repeat_one.png
Binary files differ
diff --git a/app/assets/images/emoji/restroom.png b/public/-/emojis/1/restroom.png
index 9588e0f0ef7..9588e0f0ef7 100644
--- a/app/assets/images/emoji/restroom.png
+++ b/public/-/emojis/1/restroom.png
Binary files differ
diff --git a/app/assets/images/emoji/revolving_hearts.png b/public/-/emojis/1/revolving_hearts.png
index 7b9d1948f73..7b9d1948f73 100644
--- a/app/assets/images/emoji/revolving_hearts.png
+++ b/public/-/emojis/1/revolving_hearts.png
Binary files differ
diff --git a/app/assets/images/emoji/rewind.png b/public/-/emojis/1/rewind.png
index e22e2bd3da5..e22e2bd3da5 100644
--- a/app/assets/images/emoji/rewind.png
+++ b/public/-/emojis/1/rewind.png
Binary files differ
diff --git a/app/assets/images/emoji/rhino.png b/public/-/emojis/1/rhino.png
index 12f4e0d9d9b..12f4e0d9d9b 100644
--- a/app/assets/images/emoji/rhino.png
+++ b/public/-/emojis/1/rhino.png
Binary files differ
diff --git a/app/assets/images/emoji/ribbon.png b/public/-/emojis/1/ribbon.png
index 0f253c3d8c8..0f253c3d8c8 100644
--- a/app/assets/images/emoji/ribbon.png
+++ b/public/-/emojis/1/ribbon.png
Binary files differ
diff --git a/app/assets/images/emoji/rice.png b/public/-/emojis/1/rice.png
index 6e3ac7956b1..6e3ac7956b1 100644
--- a/app/assets/images/emoji/rice.png
+++ b/public/-/emojis/1/rice.png
Binary files differ
diff --git a/app/assets/images/emoji/rice_ball.png b/public/-/emojis/1/rice_ball.png
index d3d8ee25cb8..d3d8ee25cb8 100644
--- a/app/assets/images/emoji/rice_ball.png
+++ b/public/-/emojis/1/rice_ball.png
Binary files differ
diff --git a/app/assets/images/emoji/rice_cracker.png b/public/-/emojis/1/rice_cracker.png
index 7fbd08e4ff9..7fbd08e4ff9 100644
--- a/app/assets/images/emoji/rice_cracker.png
+++ b/public/-/emojis/1/rice_cracker.png
Binary files differ
diff --git a/app/assets/images/emoji/rice_scene.png b/public/-/emojis/1/rice_scene.png
index 1a28426592a..1a28426592a 100644
--- a/app/assets/images/emoji/rice_scene.png
+++ b/public/-/emojis/1/rice_scene.png
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist.png b/public/-/emojis/1/right_facing_fist.png
index 754ed066d2c..754ed066d2c 100644
--- a/app/assets/images/emoji/right_facing_fist.png
+++ b/public/-/emojis/1/right_facing_fist.png
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone1.png b/public/-/emojis/1/right_facing_fist_tone1.png
index 33ded2f61a6..33ded2f61a6 100644
--- a/app/assets/images/emoji/right_facing_fist_tone1.png
+++ b/public/-/emojis/1/right_facing_fist_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone2.png b/public/-/emojis/1/right_facing_fist_tone2.png
index 88054e335c7..88054e335c7 100644
--- a/app/assets/images/emoji/right_facing_fist_tone2.png
+++ b/public/-/emojis/1/right_facing_fist_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone3.png b/public/-/emojis/1/right_facing_fist_tone3.png
index 84b9f5da7f7..84b9f5da7f7 100644
--- a/app/assets/images/emoji/right_facing_fist_tone3.png
+++ b/public/-/emojis/1/right_facing_fist_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone4.png b/public/-/emojis/1/right_facing_fist_tone4.png
index e741cfea68b..e741cfea68b 100644
--- a/app/assets/images/emoji/right_facing_fist_tone4.png
+++ b/public/-/emojis/1/right_facing_fist_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone5.png b/public/-/emojis/1/right_facing_fist_tone5.png
index cf66d760c1f..cf66d760c1f 100644
--- a/app/assets/images/emoji/right_facing_fist_tone5.png
+++ b/public/-/emojis/1/right_facing_fist_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/ring.png b/public/-/emojis/1/ring.png
index 87d227adb74..87d227adb74 100644
--- a/app/assets/images/emoji/ring.png
+++ b/public/-/emojis/1/ring.png
Binary files differ
diff --git a/app/assets/images/emoji/robot.png b/public/-/emojis/1/robot.png
index 7cc62612c6a..7cc62612c6a 100644
--- a/app/assets/images/emoji/robot.png
+++ b/public/-/emojis/1/robot.png
Binary files differ
diff --git a/app/assets/images/emoji/rocket.png b/public/-/emojis/1/rocket.png
index 0d8da089a37..0d8da089a37 100644
--- a/app/assets/images/emoji/rocket.png
+++ b/public/-/emojis/1/rocket.png
Binary files differ
diff --git a/app/assets/images/emoji/rofl.png b/public/-/emojis/1/rofl.png
index b1736fedfeb..b1736fedfeb 100644
--- a/app/assets/images/emoji/rofl.png
+++ b/public/-/emojis/1/rofl.png
Binary files differ
diff --git a/app/assets/images/emoji/roller_coaster.png b/public/-/emojis/1/roller_coaster.png
index 5b849e071e8..5b849e071e8 100644
--- a/app/assets/images/emoji/roller_coaster.png
+++ b/public/-/emojis/1/roller_coaster.png
Binary files differ
diff --git a/app/assets/images/emoji/rolling_eyes.png b/public/-/emojis/1/rolling_eyes.png
index 2f77b9fc3b9..2f77b9fc3b9 100644
--- a/app/assets/images/emoji/rolling_eyes.png
+++ b/public/-/emojis/1/rolling_eyes.png
Binary files differ
diff --git a/app/assets/images/emoji/rooster.png b/public/-/emojis/1/rooster.png
index bbf2bbff97a..bbf2bbff97a 100644
--- a/app/assets/images/emoji/rooster.png
+++ b/public/-/emojis/1/rooster.png
Binary files differ
diff --git a/app/assets/images/emoji/rose.png b/public/-/emojis/1/rose.png
index 52c286d31ce..52c286d31ce 100644
--- a/app/assets/images/emoji/rose.png
+++ b/public/-/emojis/1/rose.png
Binary files differ
diff --git a/app/assets/images/emoji/rosette.png b/public/-/emojis/1/rosette.png
index 8030e494bcf..8030e494bcf 100644
--- a/app/assets/images/emoji/rosette.png
+++ b/public/-/emojis/1/rosette.png
Binary files differ
diff --git a/app/assets/images/emoji/rotating_light.png b/public/-/emojis/1/rotating_light.png
index cad66b0afef..cad66b0afef 100644
--- a/app/assets/images/emoji/rotating_light.png
+++ b/public/-/emojis/1/rotating_light.png
Binary files differ
diff --git a/app/assets/images/emoji/round_pushpin.png b/public/-/emojis/1/round_pushpin.png
index 28b9d72866e..28b9d72866e 100644
--- a/app/assets/images/emoji/round_pushpin.png
+++ b/public/-/emojis/1/round_pushpin.png
Binary files differ
diff --git a/app/assets/images/emoji/rowboat.png b/public/-/emojis/1/rowboat.png
index dd4dfc095d9..dd4dfc095d9 100644
--- a/app/assets/images/emoji/rowboat.png
+++ b/public/-/emojis/1/rowboat.png
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone1.png b/public/-/emojis/1/rowboat_tone1.png
index 5e5d18548cb..5e5d18548cb 100644
--- a/app/assets/images/emoji/rowboat_tone1.png
+++ b/public/-/emojis/1/rowboat_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone2.png b/public/-/emojis/1/rowboat_tone2.png
index 9b123ef8871..9b123ef8871 100644
--- a/app/assets/images/emoji/rowboat_tone2.png
+++ b/public/-/emojis/1/rowboat_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone3.png b/public/-/emojis/1/rowboat_tone3.png
index 8ebd89a55f5..8ebd89a55f5 100644
--- a/app/assets/images/emoji/rowboat_tone3.png
+++ b/public/-/emojis/1/rowboat_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone4.png b/public/-/emojis/1/rowboat_tone4.png
index 2b0d04f8725..2b0d04f8725 100644
--- a/app/assets/images/emoji/rowboat_tone4.png
+++ b/public/-/emojis/1/rowboat_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone5.png b/public/-/emojis/1/rowboat_tone5.png
index b346f2dfc84..b346f2dfc84 100644
--- a/app/assets/images/emoji/rowboat_tone5.png
+++ b/public/-/emojis/1/rowboat_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/rugby_football.png b/public/-/emojis/1/rugby_football.png
index b1872273436..b1872273436 100644
--- a/app/assets/images/emoji/rugby_football.png
+++ b/public/-/emojis/1/rugby_football.png
Binary files differ
diff --git a/app/assets/images/emoji/runner.png b/public/-/emojis/1/runner.png
index e914915976a..e914915976a 100644
--- a/app/assets/images/emoji/runner.png
+++ b/public/-/emojis/1/runner.png
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone1.png b/public/-/emojis/1/runner_tone1.png
index 9355239a52d..9355239a52d 100644
--- a/app/assets/images/emoji/runner_tone1.png
+++ b/public/-/emojis/1/runner_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone2.png b/public/-/emojis/1/runner_tone2.png
index 6112fd5c376..6112fd5c376 100644
--- a/app/assets/images/emoji/runner_tone2.png
+++ b/public/-/emojis/1/runner_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone3.png b/public/-/emojis/1/runner_tone3.png
index 625ec708f48..625ec708f48 100644
--- a/app/assets/images/emoji/runner_tone3.png
+++ b/public/-/emojis/1/runner_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone4.png b/public/-/emojis/1/runner_tone4.png
index 242f1b56337..242f1b56337 100644
--- a/app/assets/images/emoji/runner_tone4.png
+++ b/public/-/emojis/1/runner_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone5.png b/public/-/emojis/1/runner_tone5.png
index 2976c6f019f..2976c6f019f 100644
--- a/app/assets/images/emoji/runner_tone5.png
+++ b/public/-/emojis/1/runner_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/running_shirt_with_sash.png b/public/-/emojis/1/running_shirt_with_sash.png
index 6d83c06b803..6d83c06b803 100644
--- a/app/assets/images/emoji/running_shirt_with_sash.png
+++ b/public/-/emojis/1/running_shirt_with_sash.png
Binary files differ
diff --git a/app/assets/images/emoji/sa.png b/public/-/emojis/1/sa.png
index 900f9633247..900f9633247 100644
--- a/app/assets/images/emoji/sa.png
+++ b/public/-/emojis/1/sa.png
Binary files differ
diff --git a/app/assets/images/emoji/sagittarius.png b/public/-/emojis/1/sagittarius.png
index f8d94ff2923..f8d94ff2923 100644
--- a/app/assets/images/emoji/sagittarius.png
+++ b/public/-/emojis/1/sagittarius.png
Binary files differ
diff --git a/app/assets/images/emoji/sailboat.png b/public/-/emojis/1/sailboat.png
index 772ef11da5d..772ef11da5d 100644
--- a/app/assets/images/emoji/sailboat.png
+++ b/public/-/emojis/1/sailboat.png
Binary files differ
diff --git a/app/assets/images/emoji/sake.png b/public/-/emojis/1/sake.png
index 2933f5672c4..2933f5672c4 100644
--- a/app/assets/images/emoji/sake.png
+++ b/public/-/emojis/1/sake.png
Binary files differ
diff --git a/app/assets/images/emoji/salad.png b/public/-/emojis/1/salad.png
index c89f9341158..c89f9341158 100644
--- a/app/assets/images/emoji/salad.png
+++ b/public/-/emojis/1/salad.png
Binary files differ
diff --git a/app/assets/images/emoji/sandal.png b/public/-/emojis/1/sandal.png
index 9d9f5122b7a..9d9f5122b7a 100644
--- a/app/assets/images/emoji/sandal.png
+++ b/public/-/emojis/1/sandal.png
Binary files differ
diff --git a/app/assets/images/emoji/santa.png b/public/-/emojis/1/santa.png
index bc83ab80d52..bc83ab80d52 100644
--- a/app/assets/images/emoji/santa.png
+++ b/public/-/emojis/1/santa.png
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone1.png b/public/-/emojis/1/santa_tone1.png
index 5233ffb7174..5233ffb7174 100644
--- a/app/assets/images/emoji/santa_tone1.png
+++ b/public/-/emojis/1/santa_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone2.png b/public/-/emojis/1/santa_tone2.png
index 4e845438197..4e845438197 100644
--- a/app/assets/images/emoji/santa_tone2.png
+++ b/public/-/emojis/1/santa_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone3.png b/public/-/emojis/1/santa_tone3.png
index 7fc4f33b60f..7fc4f33b60f 100644
--- a/app/assets/images/emoji/santa_tone3.png
+++ b/public/-/emojis/1/santa_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone4.png b/public/-/emojis/1/santa_tone4.png
index d1d5a15132d..d1d5a15132d 100644
--- a/app/assets/images/emoji/santa_tone4.png
+++ b/public/-/emojis/1/santa_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone5.png b/public/-/emojis/1/santa_tone5.png
index 4d697a01f24..4d697a01f24 100644
--- a/app/assets/images/emoji/santa_tone5.png
+++ b/public/-/emojis/1/santa_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/satellite.png b/public/-/emojis/1/satellite.png
index db0372795f4..db0372795f4 100644
--- a/app/assets/images/emoji/satellite.png
+++ b/public/-/emojis/1/satellite.png
Binary files differ
diff --git a/app/assets/images/emoji/satellite_orbital.png b/public/-/emojis/1/satellite_orbital.png
index 4ba55d6e297..4ba55d6e297 100644
--- a/app/assets/images/emoji/satellite_orbital.png
+++ b/public/-/emojis/1/satellite_orbital.png
Binary files differ
diff --git a/app/assets/images/emoji/saxophone.png b/public/-/emojis/1/saxophone.png
index a392faec291..a392faec291 100644
--- a/app/assets/images/emoji/saxophone.png
+++ b/public/-/emojis/1/saxophone.png
Binary files differ
diff --git a/app/assets/images/emoji/scales.png b/public/-/emojis/1/scales.png
index 0757eda1684..0757eda1684 100644
--- a/app/assets/images/emoji/scales.png
+++ b/public/-/emojis/1/scales.png
Binary files differ
diff --git a/app/assets/images/emoji/school.png b/public/-/emojis/1/school.png
index 269759534f0..269759534f0 100644
--- a/app/assets/images/emoji/school.png
+++ b/public/-/emojis/1/school.png
Binary files differ
diff --git a/app/assets/images/emoji/school_satchel.png b/public/-/emojis/1/school_satchel.png
index 9997c86e7dc..9997c86e7dc 100644
--- a/app/assets/images/emoji/school_satchel.png
+++ b/public/-/emojis/1/school_satchel.png
Binary files differ
diff --git a/app/assets/images/emoji/scissors.png b/public/-/emojis/1/scissors.png
index 270571c8cdd..270571c8cdd 100644
--- a/app/assets/images/emoji/scissors.png
+++ b/public/-/emojis/1/scissors.png
Binary files differ
diff --git a/app/assets/images/emoji/scooter.png b/public/-/emojis/1/scooter.png
index 4ab7ef59cd2..4ab7ef59cd2 100644
--- a/app/assets/images/emoji/scooter.png
+++ b/public/-/emojis/1/scooter.png
Binary files differ
diff --git a/app/assets/images/emoji/scorpion.png b/public/-/emojis/1/scorpion.png
index 449a6b281c9..449a6b281c9 100644
--- a/app/assets/images/emoji/scorpion.png
+++ b/public/-/emojis/1/scorpion.png
Binary files differ
diff --git a/app/assets/images/emoji/scorpius.png b/public/-/emojis/1/scorpius.png
index c31a9920455..c31a9920455 100644
--- a/app/assets/images/emoji/scorpius.png
+++ b/public/-/emojis/1/scorpius.png
Binary files differ
diff --git a/app/assets/images/emoji/scream.png b/public/-/emojis/1/scream.png
index c3bea9f2510..c3bea9f2510 100644
--- a/app/assets/images/emoji/scream.png
+++ b/public/-/emojis/1/scream.png
Binary files differ
diff --git a/app/assets/images/emoji/scream_cat.png b/public/-/emojis/1/scream_cat.png
index 15803ad8e6e..15803ad8e6e 100644
--- a/app/assets/images/emoji/scream_cat.png
+++ b/public/-/emojis/1/scream_cat.png
Binary files differ
diff --git a/app/assets/images/emoji/scroll.png b/public/-/emojis/1/scroll.png
index 50ee5dcd4b9..50ee5dcd4b9 100644
--- a/app/assets/images/emoji/scroll.png
+++ b/public/-/emojis/1/scroll.png
Binary files differ
diff --git a/app/assets/images/emoji/seat.png b/public/-/emojis/1/seat.png
index a6d72d95adb..a6d72d95adb 100644
--- a/app/assets/images/emoji/seat.png
+++ b/public/-/emojis/1/seat.png
Binary files differ
diff --git a/app/assets/images/emoji/second_place.png b/public/-/emojis/1/second_place.png
index 17b011268b6..17b011268b6 100644
--- a/app/assets/images/emoji/second_place.png
+++ b/public/-/emojis/1/second_place.png
Binary files differ
diff --git a/app/assets/images/emoji/secret.png b/public/-/emojis/1/secret.png
index 5fd72608e60..5fd72608e60 100644
--- a/app/assets/images/emoji/secret.png
+++ b/public/-/emojis/1/secret.png
Binary files differ
diff --git a/app/assets/images/emoji/see_no_evil.png b/public/-/emojis/1/see_no_evil.png
index 5187e474531..5187e474531 100644
--- a/app/assets/images/emoji/see_no_evil.png
+++ b/public/-/emojis/1/see_no_evil.png
Binary files differ
diff --git a/app/assets/images/emoji/seedling.png b/public/-/emojis/1/seedling.png
index ae0948bcfd6..ae0948bcfd6 100644
--- a/app/assets/images/emoji/seedling.png
+++ b/public/-/emojis/1/seedling.png
Binary files differ
diff --git a/app/assets/images/emoji/selfie.png b/public/-/emojis/1/selfie.png
index 6a1ba75c7e3..6a1ba75c7e3 100644
--- a/app/assets/images/emoji/selfie.png
+++ b/public/-/emojis/1/selfie.png
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone1.png b/public/-/emojis/1/selfie_tone1.png
index 290e075b56f..290e075b56f 100644
--- a/app/assets/images/emoji/selfie_tone1.png
+++ b/public/-/emojis/1/selfie_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone2.png b/public/-/emojis/1/selfie_tone2.png
index fcd9595b643..fcd9595b643 100644
--- a/app/assets/images/emoji/selfie_tone2.png
+++ b/public/-/emojis/1/selfie_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone3.png b/public/-/emojis/1/selfie_tone3.png
index f3a22fdf435..f3a22fdf435 100644
--- a/app/assets/images/emoji/selfie_tone3.png
+++ b/public/-/emojis/1/selfie_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone4.png b/public/-/emojis/1/selfie_tone4.png
index cdecf6d9f4e..cdecf6d9f4e 100644
--- a/app/assets/images/emoji/selfie_tone4.png
+++ b/public/-/emojis/1/selfie_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone5.png b/public/-/emojis/1/selfie_tone5.png
index 86acbb6c202..86acbb6c202 100644
--- a/app/assets/images/emoji/selfie_tone5.png
+++ b/public/-/emojis/1/selfie_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/seven.png b/public/-/emojis/1/seven.png
index 9b3476ae7c7..9b3476ae7c7 100644
--- a/app/assets/images/emoji/seven.png
+++ b/public/-/emojis/1/seven.png
Binary files differ
diff --git a/app/assets/images/emoji/shallow_pan_of_food.png b/public/-/emojis/1/shallow_pan_of_food.png
index 663a1006acd..663a1006acd 100644
--- a/app/assets/images/emoji/shallow_pan_of_food.png
+++ b/public/-/emojis/1/shallow_pan_of_food.png
Binary files differ
diff --git a/app/assets/images/emoji/shamrock.png b/public/-/emojis/1/shamrock.png
index f202aecfe6f..f202aecfe6f 100644
--- a/app/assets/images/emoji/shamrock.png
+++ b/public/-/emojis/1/shamrock.png
Binary files differ
diff --git a/app/assets/images/emoji/shark.png b/public/-/emojis/1/shark.png
index c75076d57d8..c75076d57d8 100644
--- a/app/assets/images/emoji/shark.png
+++ b/public/-/emojis/1/shark.png
Binary files differ
diff --git a/app/assets/images/emoji/shaved_ice.png b/public/-/emojis/1/shaved_ice.png
index 36dfb53ca93..36dfb53ca93 100644
--- a/app/assets/images/emoji/shaved_ice.png
+++ b/public/-/emojis/1/shaved_ice.png
Binary files differ
diff --git a/app/assets/images/emoji/sheep.png b/public/-/emojis/1/sheep.png
index 102b8a52b28..102b8a52b28 100644
--- a/app/assets/images/emoji/sheep.png
+++ b/public/-/emojis/1/sheep.png
Binary files differ
diff --git a/app/assets/images/emoji/shell.png b/public/-/emojis/1/shell.png
index 55721629f62..55721629f62 100644
--- a/app/assets/images/emoji/shell.png
+++ b/public/-/emojis/1/shell.png
Binary files differ
diff --git a/app/assets/images/emoji/shield.png b/public/-/emojis/1/shield.png
index 610bf033ce0..610bf033ce0 100644
--- a/app/assets/images/emoji/shield.png
+++ b/public/-/emojis/1/shield.png
Binary files differ
diff --git a/app/assets/images/emoji/shinto_shrine.png b/public/-/emojis/1/shinto_shrine.png
index 5a344975bf3..5a344975bf3 100644
--- a/app/assets/images/emoji/shinto_shrine.png
+++ b/public/-/emojis/1/shinto_shrine.png
Binary files differ
diff --git a/app/assets/images/emoji/ship.png b/public/-/emojis/1/ship.png
index 62d54f7d6c9..62d54f7d6c9 100644
--- a/app/assets/images/emoji/ship.png
+++ b/public/-/emojis/1/ship.png
Binary files differ
diff --git a/app/assets/images/emoji/shirt.png b/public/-/emojis/1/shirt.png
index af08dec8b59..af08dec8b59 100644
--- a/app/assets/images/emoji/shirt.png
+++ b/public/-/emojis/1/shirt.png
Binary files differ
diff --git a/app/assets/images/emoji/shopping_bags.png b/public/-/emojis/1/shopping_bags.png
index 99f2a2b13ac..99f2a2b13ac 100644
--- a/app/assets/images/emoji/shopping_bags.png
+++ b/public/-/emojis/1/shopping_bags.png
Binary files differ
diff --git a/app/assets/images/emoji/shopping_cart.png b/public/-/emojis/1/shopping_cart.png
index 1086fe6e456..1086fe6e456 100644
--- a/app/assets/images/emoji/shopping_cart.png
+++ b/public/-/emojis/1/shopping_cart.png
Binary files differ
diff --git a/app/assets/images/emoji/shower.png b/public/-/emojis/1/shower.png
index 156776a2e52..156776a2e52 100644
--- a/app/assets/images/emoji/shower.png
+++ b/public/-/emojis/1/shower.png
Binary files differ
diff --git a/app/assets/images/emoji/shrimp.png b/public/-/emojis/1/shrimp.png
index 49eff28a71e..49eff28a71e 100644
--- a/app/assets/images/emoji/shrimp.png
+++ b/public/-/emojis/1/shrimp.png
Binary files differ
diff --git a/app/assets/images/emoji/shrug.png b/public/-/emojis/1/shrug.png
index 76e63bfac77..76e63bfac77 100644
--- a/app/assets/images/emoji/shrug.png
+++ b/public/-/emojis/1/shrug.png
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone1.png b/public/-/emojis/1/shrug_tone1.png
index 1c895e64468..1c895e64468 100644
--- a/app/assets/images/emoji/shrug_tone1.png
+++ b/public/-/emojis/1/shrug_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone2.png b/public/-/emojis/1/shrug_tone2.png
index 4e3ca8f8bac..4e3ca8f8bac 100644
--- a/app/assets/images/emoji/shrug_tone2.png
+++ b/public/-/emojis/1/shrug_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone3.png b/public/-/emojis/1/shrug_tone3.png
index d1b16a19bb5..d1b16a19bb5 100644
--- a/app/assets/images/emoji/shrug_tone3.png
+++ b/public/-/emojis/1/shrug_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone4.png b/public/-/emojis/1/shrug_tone4.png
index 5fbef3f2255..5fbef3f2255 100644
--- a/app/assets/images/emoji/shrug_tone4.png
+++ b/public/-/emojis/1/shrug_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone5.png b/public/-/emojis/1/shrug_tone5.png
index 4af2e28bc5c..4af2e28bc5c 100644
--- a/app/assets/images/emoji/shrug_tone5.png
+++ b/public/-/emojis/1/shrug_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/signal_strength.png b/public/-/emojis/1/signal_strength.png
index ee2b5a4b519..ee2b5a4b519 100644
--- a/app/assets/images/emoji/signal_strength.png
+++ b/public/-/emojis/1/signal_strength.png
Binary files differ
diff --git a/app/assets/images/emoji/six.png b/public/-/emojis/1/six.png
index 371b3acef2c..371b3acef2c 100644
--- a/app/assets/images/emoji/six.png
+++ b/public/-/emojis/1/six.png
Binary files differ
diff --git a/app/assets/images/emoji/six_pointed_star.png b/public/-/emojis/1/six_pointed_star.png
index 2eb1707458b..2eb1707458b 100644
--- a/app/assets/images/emoji/six_pointed_star.png
+++ b/public/-/emojis/1/six_pointed_star.png
Binary files differ
diff --git a/app/assets/images/emoji/ski.png b/public/-/emojis/1/ski.png
index 4a2d2c12306..4a2d2c12306 100644
--- a/app/assets/images/emoji/ski.png
+++ b/public/-/emojis/1/ski.png
Binary files differ
diff --git a/app/assets/images/emoji/skier.png b/public/-/emojis/1/skier.png
index 2eb3bdce2af..2eb3bdce2af 100644
--- a/app/assets/images/emoji/skier.png
+++ b/public/-/emojis/1/skier.png
Binary files differ
diff --git a/app/assets/images/emoji/skull.png b/public/-/emojis/1/skull.png
index 26abb17296a..26abb17296a 100644
--- a/app/assets/images/emoji/skull.png
+++ b/public/-/emojis/1/skull.png
Binary files differ
diff --git a/app/assets/images/emoji/skull_crossbones.png b/public/-/emojis/1/skull_crossbones.png
index b459df9227a..b459df9227a 100644
--- a/app/assets/images/emoji/skull_crossbones.png
+++ b/public/-/emojis/1/skull_crossbones.png
Binary files differ
diff --git a/app/assets/images/emoji/sleeping.png b/public/-/emojis/1/sleeping.png
index 9ecf600d6d8..9ecf600d6d8 100644
--- a/app/assets/images/emoji/sleeping.png
+++ b/public/-/emojis/1/sleeping.png
Binary files differ
diff --git a/app/assets/images/emoji/sleeping_accommodation.png b/public/-/emojis/1/sleeping_accommodation.png
index c739e7fb69b..c739e7fb69b 100644
--- a/app/assets/images/emoji/sleeping_accommodation.png
+++ b/public/-/emojis/1/sleeping_accommodation.png
Binary files differ
diff --git a/app/assets/images/emoji/sleepy.png b/public/-/emojis/1/sleepy.png
index 836b4107717..836b4107717 100644
--- a/app/assets/images/emoji/sleepy.png
+++ b/public/-/emojis/1/sleepy.png
Binary files differ
diff --git a/app/assets/images/emoji/slight_frown.png b/public/-/emojis/1/slight_frown.png
index b2f1d983d36..b2f1d983d36 100644
--- a/app/assets/images/emoji/slight_frown.png
+++ b/public/-/emojis/1/slight_frown.png
Binary files differ
diff --git a/app/assets/images/emoji/slight_smile.png b/public/-/emojis/1/slight_smile.png
index ddd7d65dd3d..ddd7d65dd3d 100644
--- a/app/assets/images/emoji/slight_smile.png
+++ b/public/-/emojis/1/slight_smile.png
Binary files differ
diff --git a/app/assets/images/emoji/slot_machine.png b/public/-/emojis/1/slot_machine.png
index ee71b6c268c..ee71b6c268c 100644
--- a/app/assets/images/emoji/slot_machine.png
+++ b/public/-/emojis/1/slot_machine.png
Binary files differ
diff --git a/app/assets/images/emoji/small_blue_diamond.png b/public/-/emojis/1/small_blue_diamond.png
index b86b5bc4db3..b86b5bc4db3 100644
--- a/app/assets/images/emoji/small_blue_diamond.png
+++ b/public/-/emojis/1/small_blue_diamond.png
Binary files differ
diff --git a/app/assets/images/emoji/small_orange_diamond.png b/public/-/emojis/1/small_orange_diamond.png
index e1c6ed9b2f8..e1c6ed9b2f8 100644
--- a/app/assets/images/emoji/small_orange_diamond.png
+++ b/public/-/emojis/1/small_orange_diamond.png
Binary files differ
diff --git a/app/assets/images/emoji/small_red_triangle.png b/public/-/emojis/1/small_red_triangle.png
index 785887c195a..785887c195a 100644
--- a/app/assets/images/emoji/small_red_triangle.png
+++ b/public/-/emojis/1/small_red_triangle.png
Binary files differ
diff --git a/app/assets/images/emoji/small_red_triangle_down.png b/public/-/emojis/1/small_red_triangle_down.png
index a83beff1914..a83beff1914 100644
--- a/app/assets/images/emoji/small_red_triangle_down.png
+++ b/public/-/emojis/1/small_red_triangle_down.png
Binary files differ
diff --git a/app/assets/images/emoji/smile.png b/public/-/emojis/1/smile.png
index aa47ffe978c..aa47ffe978c 100644
--- a/app/assets/images/emoji/smile.png
+++ b/public/-/emojis/1/smile.png
Binary files differ
diff --git a/app/assets/images/emoji/smile_cat.png b/public/-/emojis/1/smile_cat.png
index 6f25f11dd3a..6f25f11dd3a 100644
--- a/app/assets/images/emoji/smile_cat.png
+++ b/public/-/emojis/1/smile_cat.png
Binary files differ
diff --git a/app/assets/images/emoji/smiley.png b/public/-/emojis/1/smiley.png
index 30957a65968..30957a65968 100644
--- a/app/assets/images/emoji/smiley.png
+++ b/public/-/emojis/1/smiley.png
Binary files differ
diff --git a/app/assets/images/emoji/smiley_cat.png b/public/-/emojis/1/smiley_cat.png
index 163b57a3427..163b57a3427 100644
--- a/app/assets/images/emoji/smiley_cat.png
+++ b/public/-/emojis/1/smiley_cat.png
Binary files differ
diff --git a/app/assets/images/emoji/smiling_imp.png b/public/-/emojis/1/smiling_imp.png
index cc2c5f1ec72..cc2c5f1ec72 100644
--- a/app/assets/images/emoji/smiling_imp.png
+++ b/public/-/emojis/1/smiling_imp.png
Binary files differ
diff --git a/app/assets/images/emoji/smirk.png b/public/-/emojis/1/smirk.png
index 87852109988..87852109988 100644
--- a/app/assets/images/emoji/smirk.png
+++ b/public/-/emojis/1/smirk.png
Binary files differ
diff --git a/app/assets/images/emoji/smirk_cat.png b/public/-/emojis/1/smirk_cat.png
index 9ac5954c199..9ac5954c199 100644
--- a/app/assets/images/emoji/smirk_cat.png
+++ b/public/-/emojis/1/smirk_cat.png
Binary files differ
diff --git a/app/assets/images/emoji/smoking.png b/public/-/emojis/1/smoking.png
index 910f648c8f9..910f648c8f9 100644
--- a/app/assets/images/emoji/smoking.png
+++ b/public/-/emojis/1/smoking.png
Binary files differ
diff --git a/app/assets/images/emoji/snail.png b/public/-/emojis/1/snail.png
index f4ea071e2d3..f4ea071e2d3 100644
--- a/app/assets/images/emoji/snail.png
+++ b/public/-/emojis/1/snail.png
Binary files differ
diff --git a/app/assets/images/emoji/snake.png b/public/-/emojis/1/snake.png
index d0278a28d8c..d0278a28d8c 100644
--- a/app/assets/images/emoji/snake.png
+++ b/public/-/emojis/1/snake.png
Binary files differ
diff --git a/app/assets/images/emoji/sneezing_face.png b/public/-/emojis/1/sneezing_face.png
index ccf07d4b64d..ccf07d4b64d 100644
--- a/app/assets/images/emoji/sneezing_face.png
+++ b/public/-/emojis/1/sneezing_face.png
Binary files differ
diff --git a/app/assets/images/emoji/snowboarder.png b/public/-/emojis/1/snowboarder.png
index 6361c0f2c9d..6361c0f2c9d 100644
--- a/app/assets/images/emoji/snowboarder.png
+++ b/public/-/emojis/1/snowboarder.png
Binary files differ
diff --git a/app/assets/images/emoji/snowflake.png b/public/-/emojis/1/snowflake.png
index db319a77ec6..db319a77ec6 100644
--- a/app/assets/images/emoji/snowflake.png
+++ b/public/-/emojis/1/snowflake.png
Binary files differ
diff --git a/app/assets/images/emoji/snowman.png b/public/-/emojis/1/snowman.png
index 20c177c2aff..20c177c2aff 100644
--- a/app/assets/images/emoji/snowman.png
+++ b/public/-/emojis/1/snowman.png
Binary files differ
diff --git a/app/assets/images/emoji/snowman2.png b/public/-/emojis/1/snowman2.png
index 896f28502af..896f28502af 100644
--- a/app/assets/images/emoji/snowman2.png
+++ b/public/-/emojis/1/snowman2.png
Binary files differ
diff --git a/app/assets/images/emoji/sob.png b/public/-/emojis/1/sob.png
index 52e3517a1ee..52e3517a1ee 100644
--- a/app/assets/images/emoji/sob.png
+++ b/public/-/emojis/1/sob.png
Binary files differ
diff --git a/app/assets/images/emoji/soccer.png b/public/-/emojis/1/soccer.png
index 28cfa218d6d..28cfa218d6d 100644
--- a/app/assets/images/emoji/soccer.png
+++ b/public/-/emojis/1/soccer.png
Binary files differ
diff --git a/app/assets/images/emoji/soon.png b/public/-/emojis/1/soon.png
index 8cdfd86690d..8cdfd86690d 100644
--- a/app/assets/images/emoji/soon.png
+++ b/public/-/emojis/1/soon.png
Binary files differ
diff --git a/app/assets/images/emoji/sos.png b/public/-/emojis/1/sos.png
index d7d8c9953e4..d7d8c9953e4 100644
--- a/app/assets/images/emoji/sos.png
+++ b/public/-/emojis/1/sos.png
Binary files differ
diff --git a/app/assets/images/emoji/sound.png b/public/-/emojis/1/sound.png
index e75ddca53ba..e75ddca53ba 100644
--- a/app/assets/images/emoji/sound.png
+++ b/public/-/emojis/1/sound.png
Binary files differ
diff --git a/app/assets/images/emoji/space_invader.png b/public/-/emojis/1/space_invader.png
index 2e73f5f32e5..2e73f5f32e5 100644
--- a/app/assets/images/emoji/space_invader.png
+++ b/public/-/emojis/1/space_invader.png
Binary files differ
diff --git a/app/assets/images/emoji/spades.png b/public/-/emojis/1/spades.png
index f822f184cb0..f822f184cb0 100644
--- a/app/assets/images/emoji/spades.png
+++ b/public/-/emojis/1/spades.png
Binary files differ
diff --git a/app/assets/images/emoji/spaghetti.png b/public/-/emojis/1/spaghetti.png
index 89c24a321f1..89c24a321f1 100644
--- a/app/assets/images/emoji/spaghetti.png
+++ b/public/-/emojis/1/spaghetti.png
Binary files differ
diff --git a/app/assets/images/emoji/sparkle.png b/public/-/emojis/1/sparkle.png
index 6aa7b6ec9cf..6aa7b6ec9cf 100644
--- a/app/assets/images/emoji/sparkle.png
+++ b/public/-/emojis/1/sparkle.png
Binary files differ
diff --git a/app/assets/images/emoji/sparkler.png b/public/-/emojis/1/sparkler.png
index 30339cd6e09..30339cd6e09 100644
--- a/app/assets/images/emoji/sparkler.png
+++ b/public/-/emojis/1/sparkler.png
Binary files differ
diff --git a/app/assets/images/emoji/sparkles.png b/public/-/emojis/1/sparkles.png
index 169bc10b023..169bc10b023 100644
--- a/app/assets/images/emoji/sparkles.png
+++ b/public/-/emojis/1/sparkles.png
Binary files differ
diff --git a/app/assets/images/emoji/sparkling_heart.png b/public/-/emojis/1/sparkling_heart.png
index 6709269454e..6709269454e 100644
--- a/app/assets/images/emoji/sparkling_heart.png
+++ b/public/-/emojis/1/sparkling_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/speak_no_evil.png b/public/-/emojis/1/speak_no_evil.png
index 9d9e07c974b..9d9e07c974b 100644
--- a/app/assets/images/emoji/speak_no_evil.png
+++ b/public/-/emojis/1/speak_no_evil.png
Binary files differ
diff --git a/app/assets/images/emoji/speaker.png b/public/-/emojis/1/speaker.png
index 7bcffb8fc43..7bcffb8fc43 100644
--- a/app/assets/images/emoji/speaker.png
+++ b/public/-/emojis/1/speaker.png
Binary files differ
diff --git a/app/assets/images/emoji/speaking_head.png b/public/-/emojis/1/speaking_head.png
index 2df93aaae09..2df93aaae09 100644
--- a/app/assets/images/emoji/speaking_head.png
+++ b/public/-/emojis/1/speaking_head.png
Binary files differ
diff --git a/app/assets/images/emoji/speech_balloon.png b/public/-/emojis/1/speech_balloon.png
index a34ef741733..a34ef741733 100644
--- a/app/assets/images/emoji/speech_balloon.png
+++ b/public/-/emojis/1/speech_balloon.png
Binary files differ
diff --git a/app/assets/images/emoji/speech_left.png b/public/-/emojis/1/speech_left.png
index 00c05959bcd..00c05959bcd 100644
--- a/app/assets/images/emoji/speech_left.png
+++ b/public/-/emojis/1/speech_left.png
Binary files differ
diff --git a/app/assets/images/emoji/speedboat.png b/public/-/emojis/1/speedboat.png
index 74059d12de1..74059d12de1 100644
--- a/app/assets/images/emoji/speedboat.png
+++ b/public/-/emojis/1/speedboat.png
Binary files differ
diff --git a/app/assets/images/emoji/spider.png b/public/-/emojis/1/spider.png
index 3849fa90b94..3849fa90b94 100644
--- a/app/assets/images/emoji/spider.png
+++ b/public/-/emojis/1/spider.png
Binary files differ
diff --git a/app/assets/images/emoji/spider_web.png b/public/-/emojis/1/spider_web.png
index ba448ee7fba..ba448ee7fba 100644
--- a/app/assets/images/emoji/spider_web.png
+++ b/public/-/emojis/1/spider_web.png
Binary files differ
diff --git a/app/assets/images/emoji/spoon.png b/public/-/emojis/1/spoon.png
index 3c4da766aee..3c4da766aee 100644
--- a/app/assets/images/emoji/spoon.png
+++ b/public/-/emojis/1/spoon.png
Binary files differ
diff --git a/app/assets/images/emoji/spy.png b/public/-/emojis/1/spy.png
index a729e9584d6..a729e9584d6 100644
--- a/app/assets/images/emoji/spy.png
+++ b/public/-/emojis/1/spy.png
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone1.png b/public/-/emojis/1/spy_tone1.png
index 2d1c022caee..2d1c022caee 100644
--- a/app/assets/images/emoji/spy_tone1.png
+++ b/public/-/emojis/1/spy_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone2.png b/public/-/emojis/1/spy_tone2.png
index 548b9c26f5d..548b9c26f5d 100644
--- a/app/assets/images/emoji/spy_tone2.png
+++ b/public/-/emojis/1/spy_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone3.png b/public/-/emojis/1/spy_tone3.png
index b023f4b18e1..b023f4b18e1 100644
--- a/app/assets/images/emoji/spy_tone3.png
+++ b/public/-/emojis/1/spy_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone4.png b/public/-/emojis/1/spy_tone4.png
index d8300af492d..d8300af492d 100644
--- a/app/assets/images/emoji/spy_tone4.png
+++ b/public/-/emojis/1/spy_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone5.png b/public/-/emojis/1/spy_tone5.png
index ca1462595fa..ca1462595fa 100644
--- a/app/assets/images/emoji/spy_tone5.png
+++ b/public/-/emojis/1/spy_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/squid.png b/public/-/emojis/1/squid.png
index d2af223f0cb..d2af223f0cb 100644
--- a/app/assets/images/emoji/squid.png
+++ b/public/-/emojis/1/squid.png
Binary files differ
diff --git a/app/assets/images/emoji/stadium.png b/public/-/emojis/1/stadium.png
index 00cd6db5e29..00cd6db5e29 100644
--- a/app/assets/images/emoji/stadium.png
+++ b/public/-/emojis/1/stadium.png
Binary files differ
diff --git a/app/assets/images/emoji/star.png b/public/-/emojis/1/star.png
index c930947076e..c930947076e 100644
--- a/app/assets/images/emoji/star.png
+++ b/public/-/emojis/1/star.png
Binary files differ
diff --git a/app/assets/images/emoji/star2.png b/public/-/emojis/1/star2.png
index 2f5cba592db..2f5cba592db 100644
--- a/app/assets/images/emoji/star2.png
+++ b/public/-/emojis/1/star2.png
Binary files differ
diff --git a/app/assets/images/emoji/star_and_crescent.png b/public/-/emojis/1/star_and_crescent.png
index e182636457d..e182636457d 100644
--- a/app/assets/images/emoji/star_and_crescent.png
+++ b/public/-/emojis/1/star_and_crescent.png
Binary files differ
diff --git a/app/assets/images/emoji/star_of_david.png b/public/-/emojis/1/star_of_david.png
index fc59d0dde24..fc59d0dde24 100644
--- a/app/assets/images/emoji/star_of_david.png
+++ b/public/-/emojis/1/star_of_david.png
Binary files differ
diff --git a/app/assets/images/emoji/stars.png b/public/-/emojis/1/stars.png
index aa45384d1c6..aa45384d1c6 100644
--- a/app/assets/images/emoji/stars.png
+++ b/public/-/emojis/1/stars.png
Binary files differ
diff --git a/app/assets/images/emoji/station.png b/public/-/emojis/1/station.png
index 5c26fee529c..5c26fee529c 100644
--- a/app/assets/images/emoji/station.png
+++ b/public/-/emojis/1/station.png
Binary files differ
diff --git a/app/assets/images/emoji/statue_of_liberty.png b/public/-/emojis/1/statue_of_liberty.png
index 05df8289b59..05df8289b59 100644
--- a/app/assets/images/emoji/statue_of_liberty.png
+++ b/public/-/emojis/1/statue_of_liberty.png
Binary files differ
diff --git a/app/assets/images/emoji/steam_locomotive.png b/public/-/emojis/1/steam_locomotive.png
index 9ac0d999c4c..9ac0d999c4c 100644
--- a/app/assets/images/emoji/steam_locomotive.png
+++ b/public/-/emojis/1/steam_locomotive.png
Binary files differ
diff --git a/app/assets/images/emoji/stew.png b/public/-/emojis/1/stew.png
index 6b3f010c17a..6b3f010c17a 100644
--- a/app/assets/images/emoji/stew.png
+++ b/public/-/emojis/1/stew.png
Binary files differ
diff --git a/app/assets/images/emoji/stop_button.png b/public/-/emojis/1/stop_button.png
index cfa99988ac2..cfa99988ac2 100644
--- a/app/assets/images/emoji/stop_button.png
+++ b/public/-/emojis/1/stop_button.png
Binary files differ
diff --git a/app/assets/images/emoji/stopwatch.png b/public/-/emojis/1/stopwatch.png
index 8fae1c9a898..8fae1c9a898 100644
--- a/app/assets/images/emoji/stopwatch.png
+++ b/public/-/emojis/1/stopwatch.png
Binary files differ
diff --git a/app/assets/images/emoji/straight_ruler.png b/public/-/emojis/1/straight_ruler.png
index 1017b7433a1..1017b7433a1 100644
--- a/app/assets/images/emoji/straight_ruler.png
+++ b/public/-/emojis/1/straight_ruler.png
Binary files differ
diff --git a/app/assets/images/emoji/strawberry.png b/public/-/emojis/1/strawberry.png
index 7bb86f0b29c..7bb86f0b29c 100644
--- a/app/assets/images/emoji/strawberry.png
+++ b/public/-/emojis/1/strawberry.png
Binary files differ
diff --git a/app/assets/images/emoji/stuck_out_tongue.png b/public/-/emojis/1/stuck_out_tongue.png
index 25757341f96..25757341f96 100644
--- a/app/assets/images/emoji/stuck_out_tongue.png
+++ b/public/-/emojis/1/stuck_out_tongue.png
Binary files differ
diff --git a/app/assets/images/emoji/stuck_out_tongue_closed_eyes.png b/public/-/emojis/1/stuck_out_tongue_closed_eyes.png
index 5c0401e9b1d..5c0401e9b1d 100644
--- a/app/assets/images/emoji/stuck_out_tongue_closed_eyes.png
+++ b/public/-/emojis/1/stuck_out_tongue_closed_eyes.png
Binary files differ
diff --git a/app/assets/images/emoji/stuck_out_tongue_winking_eye.png b/public/-/emojis/1/stuck_out_tongue_winking_eye.png
index 4817eaa3dc6..4817eaa3dc6 100644
--- a/app/assets/images/emoji/stuck_out_tongue_winking_eye.png
+++ b/public/-/emojis/1/stuck_out_tongue_winking_eye.png
Binary files differ
diff --git a/app/assets/images/emoji/stuffed_flatbread.png b/public/-/emojis/1/stuffed_flatbread.png
index a2e10df40a5..a2e10df40a5 100644
--- a/app/assets/images/emoji/stuffed_flatbread.png
+++ b/public/-/emojis/1/stuffed_flatbread.png
Binary files differ
diff --git a/app/assets/images/emoji/sun_with_face.png b/public/-/emojis/1/sun_with_face.png
index 14a4ea971db..14a4ea971db 100644
--- a/app/assets/images/emoji/sun_with_face.png
+++ b/public/-/emojis/1/sun_with_face.png
Binary files differ
diff --git a/app/assets/images/emoji/sunflower.png b/public/-/emojis/1/sunflower.png
index 08cc07761ea..08cc07761ea 100644
--- a/app/assets/images/emoji/sunflower.png
+++ b/public/-/emojis/1/sunflower.png
Binary files differ
diff --git a/app/assets/images/emoji/sunglasses.png b/public/-/emojis/1/sunglasses.png
index 20011735110..20011735110 100644
--- a/app/assets/images/emoji/sunglasses.png
+++ b/public/-/emojis/1/sunglasses.png
Binary files differ
diff --git a/app/assets/images/emoji/sunny.png b/public/-/emojis/1/sunny.png
index fd521ae31a7..fd521ae31a7 100644
--- a/app/assets/images/emoji/sunny.png
+++ b/public/-/emojis/1/sunny.png
Binary files differ
diff --git a/app/assets/images/emoji/sunrise.png b/public/-/emojis/1/sunrise.png
index 4ad36003c20..4ad36003c20 100644
--- a/app/assets/images/emoji/sunrise.png
+++ b/public/-/emojis/1/sunrise.png
Binary files differ
diff --git a/app/assets/images/emoji/sunrise_over_mountains.png b/public/-/emojis/1/sunrise_over_mountains.png
index 2b99307344d..2b99307344d 100644
--- a/app/assets/images/emoji/sunrise_over_mountains.png
+++ b/public/-/emojis/1/sunrise_over_mountains.png
Binary files differ
diff --git a/app/assets/images/emoji/surfer.png b/public/-/emojis/1/surfer.png
index 3ab017adf4b..3ab017adf4b 100644
--- a/app/assets/images/emoji/surfer.png
+++ b/public/-/emojis/1/surfer.png
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone1.png b/public/-/emojis/1/surfer_tone1.png
index b5faaa524cc..b5faaa524cc 100644
--- a/app/assets/images/emoji/surfer_tone1.png
+++ b/public/-/emojis/1/surfer_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone2.png b/public/-/emojis/1/surfer_tone2.png
index 6d92e412ff1..6d92e412ff1 100644
--- a/app/assets/images/emoji/surfer_tone2.png
+++ b/public/-/emojis/1/surfer_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone3.png b/public/-/emojis/1/surfer_tone3.png
index f05ef59496e..f05ef59496e 100644
--- a/app/assets/images/emoji/surfer_tone3.png
+++ b/public/-/emojis/1/surfer_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone4.png b/public/-/emojis/1/surfer_tone4.png
index 35e143d19dc..35e143d19dc 100644
--- a/app/assets/images/emoji/surfer_tone4.png
+++ b/public/-/emojis/1/surfer_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone5.png b/public/-/emojis/1/surfer_tone5.png
index 38917658eac..38917658eac 100644
--- a/app/assets/images/emoji/surfer_tone5.png
+++ b/public/-/emojis/1/surfer_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/sushi.png b/public/-/emojis/1/sushi.png
index f171fd2f7a1..f171fd2f7a1 100644
--- a/app/assets/images/emoji/sushi.png
+++ b/public/-/emojis/1/sushi.png
Binary files differ
diff --git a/app/assets/images/emoji/suspension_railway.png b/public/-/emojis/1/suspension_railway.png
index a59d5f48c24..a59d5f48c24 100644
--- a/app/assets/images/emoji/suspension_railway.png
+++ b/public/-/emojis/1/suspension_railway.png
Binary files differ
diff --git a/app/assets/images/emoji/sweat.png b/public/-/emojis/1/sweat.png
index f0dae7b7893..f0dae7b7893 100644
--- a/app/assets/images/emoji/sweat.png
+++ b/public/-/emojis/1/sweat.png
Binary files differ
diff --git a/app/assets/images/emoji/sweat_drops.png b/public/-/emojis/1/sweat_drops.png
index 4106117ebc8..4106117ebc8 100644
--- a/app/assets/images/emoji/sweat_drops.png
+++ b/public/-/emojis/1/sweat_drops.png
Binary files differ
diff --git a/app/assets/images/emoji/sweat_smile.png b/public/-/emojis/1/sweat_smile.png
index cb18d9c899b..cb18d9c899b 100644
--- a/app/assets/images/emoji/sweat_smile.png
+++ b/public/-/emojis/1/sweat_smile.png
Binary files differ
diff --git a/app/assets/images/emoji/sweet_potato.png b/public/-/emojis/1/sweet_potato.png
index 92a425f2e20..92a425f2e20 100644
--- a/app/assets/images/emoji/sweet_potato.png
+++ b/public/-/emojis/1/sweet_potato.png
Binary files differ
diff --git a/app/assets/images/emoji/swimmer.png b/public/-/emojis/1/swimmer.png
index 55b4d72f9a7..55b4d72f9a7 100644
--- a/app/assets/images/emoji/swimmer.png
+++ b/public/-/emojis/1/swimmer.png
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone1.png b/public/-/emojis/1/swimmer_tone1.png
index 38441c9ca9a..38441c9ca9a 100644
--- a/app/assets/images/emoji/swimmer_tone1.png
+++ b/public/-/emojis/1/swimmer_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone2.png b/public/-/emojis/1/swimmer_tone2.png
index b0d43112444..b0d43112444 100644
--- a/app/assets/images/emoji/swimmer_tone2.png
+++ b/public/-/emojis/1/swimmer_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone3.png b/public/-/emojis/1/swimmer_tone3.png
index 211e77e2aa0..211e77e2aa0 100644
--- a/app/assets/images/emoji/swimmer_tone3.png
+++ b/public/-/emojis/1/swimmer_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone4.png b/public/-/emojis/1/swimmer_tone4.png
index f34c34db9d2..f34c34db9d2 100644
--- a/app/assets/images/emoji/swimmer_tone4.png
+++ b/public/-/emojis/1/swimmer_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone5.png b/public/-/emojis/1/swimmer_tone5.png
index 3e9231ff868..3e9231ff868 100644
--- a/app/assets/images/emoji/swimmer_tone5.png
+++ b/public/-/emojis/1/swimmer_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/symbols.png b/public/-/emojis/1/symbols.png
index ac2fc1f358f..ac2fc1f358f 100644
--- a/app/assets/images/emoji/symbols.png
+++ b/public/-/emojis/1/symbols.png
Binary files differ
diff --git a/app/assets/images/emoji/synagogue.png b/public/-/emojis/1/synagogue.png
index ee347904c80..ee347904c80 100644
--- a/app/assets/images/emoji/synagogue.png
+++ b/public/-/emojis/1/synagogue.png
Binary files differ
diff --git a/app/assets/images/emoji/syringe.png b/public/-/emojis/1/syringe.png
index 71c1a9528d5..71c1a9528d5 100644
--- a/app/assets/images/emoji/syringe.png
+++ b/public/-/emojis/1/syringe.png
Binary files differ
diff --git a/app/assets/images/emoji/taco.png b/public/-/emojis/1/taco.png
index 10e847a4619..10e847a4619 100644
--- a/app/assets/images/emoji/taco.png
+++ b/public/-/emojis/1/taco.png
Binary files differ
diff --git a/app/assets/images/emoji/tada.png b/public/-/emojis/1/tada.png
index 0244d60f269..0244d60f269 100644
--- a/app/assets/images/emoji/tada.png
+++ b/public/-/emojis/1/tada.png
Binary files differ
diff --git a/app/assets/images/emoji/tanabata_tree.png b/public/-/emojis/1/tanabata_tree.png
index 46fcb3a1aac..46fcb3a1aac 100644
--- a/app/assets/images/emoji/tanabata_tree.png
+++ b/public/-/emojis/1/tanabata_tree.png
Binary files differ
diff --git a/app/assets/images/emoji/tangerine.png b/public/-/emojis/1/tangerine.png
index ab14e5378db..ab14e5378db 100644
--- a/app/assets/images/emoji/tangerine.png
+++ b/public/-/emojis/1/tangerine.png
Binary files differ
diff --git a/app/assets/images/emoji/taurus.png b/public/-/emojis/1/taurus.png
index b2a370df42b..b2a370df42b 100644
--- a/app/assets/images/emoji/taurus.png
+++ b/public/-/emojis/1/taurus.png
Binary files differ
diff --git a/app/assets/images/emoji/taxi.png b/public/-/emojis/1/taxi.png
index 55f4cc84797..55f4cc84797 100644
--- a/app/assets/images/emoji/taxi.png
+++ b/public/-/emojis/1/taxi.png
Binary files differ
diff --git a/app/assets/images/emoji/tea.png b/public/-/emojis/1/tea.png
index b53b98f0c45..b53b98f0c45 100644
--- a/app/assets/images/emoji/tea.png
+++ b/public/-/emojis/1/tea.png
Binary files differ
diff --git a/app/assets/images/emoji/telephone.png b/public/-/emojis/1/telephone.png
index a1e69f566bc..a1e69f566bc 100644
--- a/app/assets/images/emoji/telephone.png
+++ b/public/-/emojis/1/telephone.png
Binary files differ
diff --git a/app/assets/images/emoji/telephone_receiver.png b/public/-/emojis/1/telephone_receiver.png
index 69388316c35..69388316c35 100644
--- a/app/assets/images/emoji/telephone_receiver.png
+++ b/public/-/emojis/1/telephone_receiver.png
Binary files differ
diff --git a/app/assets/images/emoji/telescope.png b/public/-/emojis/1/telescope.png
index d63154614b5..d63154614b5 100644
--- a/app/assets/images/emoji/telescope.png
+++ b/public/-/emojis/1/telescope.png
Binary files differ
diff --git a/app/assets/images/emoji/ten.png b/public/-/emojis/1/ten.png
index 782d4004962..782d4004962 100644
--- a/app/assets/images/emoji/ten.png
+++ b/public/-/emojis/1/ten.png
Binary files differ
diff --git a/app/assets/images/emoji/tennis.png b/public/-/emojis/1/tennis.png
index 7e68ba8f301..7e68ba8f301 100644
--- a/app/assets/images/emoji/tennis.png
+++ b/public/-/emojis/1/tennis.png
Binary files differ
diff --git a/app/assets/images/emoji/tent.png b/public/-/emojis/1/tent.png
index 3fddcfc56eb..3fddcfc56eb 100644
--- a/app/assets/images/emoji/tent.png
+++ b/public/-/emojis/1/tent.png
Binary files differ
diff --git a/app/assets/images/emoji/thermometer.png b/public/-/emojis/1/thermometer.png
index b1147392426..b1147392426 100644
--- a/app/assets/images/emoji/thermometer.png
+++ b/public/-/emojis/1/thermometer.png
Binary files differ
diff --git a/app/assets/images/emoji/thermometer_face.png b/public/-/emojis/1/thermometer_face.png
index 8fc57387563..8fc57387563 100644
--- a/app/assets/images/emoji/thermometer_face.png
+++ b/public/-/emojis/1/thermometer_face.png
Binary files differ
diff --git a/app/assets/images/emoji/thinking.png b/public/-/emojis/1/thinking.png
index c18f6fd14ad..c18f6fd14ad 100644
--- a/app/assets/images/emoji/thinking.png
+++ b/public/-/emojis/1/thinking.png
Binary files differ
diff --git a/app/assets/images/emoji/third_place.png b/public/-/emojis/1/third_place.png
index 636e04a5950..636e04a5950 100644
--- a/app/assets/images/emoji/third_place.png
+++ b/public/-/emojis/1/third_place.png
Binary files differ
diff --git a/app/assets/images/emoji/thought_balloon.png b/public/-/emojis/1/thought_balloon.png
index 72fe8fa7022..72fe8fa7022 100644
--- a/app/assets/images/emoji/thought_balloon.png
+++ b/public/-/emojis/1/thought_balloon.png
Binary files differ
diff --git a/app/assets/images/emoji/three.png b/public/-/emojis/1/three.png
index dbaa6183e72..dbaa6183e72 100644
--- a/app/assets/images/emoji/three.png
+++ b/public/-/emojis/1/three.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown.png b/public/-/emojis/1/thumbsdown.png
index b63da2f20a8..b63da2f20a8 100644
--- a/app/assets/images/emoji/thumbsdown.png
+++ b/public/-/emojis/1/thumbsdown.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone1.png b/public/-/emojis/1/thumbsdown_tone1.png
index a1631af8e92..a1631af8e92 100644
--- a/app/assets/images/emoji/thumbsdown_tone1.png
+++ b/public/-/emojis/1/thumbsdown_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone2.png b/public/-/emojis/1/thumbsdown_tone2.png
index 85fff82d595..85fff82d595 100644
--- a/app/assets/images/emoji/thumbsdown_tone2.png
+++ b/public/-/emojis/1/thumbsdown_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone3.png b/public/-/emojis/1/thumbsdown_tone3.png
index eeba3be80fd..eeba3be80fd 100644
--- a/app/assets/images/emoji/thumbsdown_tone3.png
+++ b/public/-/emojis/1/thumbsdown_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone4.png b/public/-/emojis/1/thumbsdown_tone4.png
index 1addafdaed0..1addafdaed0 100644
--- a/app/assets/images/emoji/thumbsdown_tone4.png
+++ b/public/-/emojis/1/thumbsdown_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone5.png b/public/-/emojis/1/thumbsdown_tone5.png
index 37ec07b5721..37ec07b5721 100644
--- a/app/assets/images/emoji/thumbsdown_tone5.png
+++ b/public/-/emojis/1/thumbsdown_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup.png b/public/-/emojis/1/thumbsup.png
index f9e6f13a34f..f9e6f13a34f 100644
--- a/app/assets/images/emoji/thumbsup.png
+++ b/public/-/emojis/1/thumbsup.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone1.png b/public/-/emojis/1/thumbsup_tone1.png
index 39684cd5cc7..39684cd5cc7 100644
--- a/app/assets/images/emoji/thumbsup_tone1.png
+++ b/public/-/emojis/1/thumbsup_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone2.png b/public/-/emojis/1/thumbsup_tone2.png
index a9b59723573..a9b59723573 100644
--- a/app/assets/images/emoji/thumbsup_tone2.png
+++ b/public/-/emojis/1/thumbsup_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone3.png b/public/-/emojis/1/thumbsup_tone3.png
index c5e29167015..c5e29167015 100644
--- a/app/assets/images/emoji/thumbsup_tone3.png
+++ b/public/-/emojis/1/thumbsup_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone4.png b/public/-/emojis/1/thumbsup_tone4.png
index 5bf4857a884..5bf4857a884 100644
--- a/app/assets/images/emoji/thumbsup_tone4.png
+++ b/public/-/emojis/1/thumbsup_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone5.png b/public/-/emojis/1/thumbsup_tone5.png
index d829f787c61..d829f787c61 100644
--- a/app/assets/images/emoji/thumbsup_tone5.png
+++ b/public/-/emojis/1/thumbsup_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/thunder_cloud_rain.png b/public/-/emojis/1/thunder_cloud_rain.png
index 31a26a1b6ee..31a26a1b6ee 100644
--- a/app/assets/images/emoji/thunder_cloud_rain.png
+++ b/public/-/emojis/1/thunder_cloud_rain.png
Binary files differ
diff --git a/app/assets/images/emoji/ticket.png b/public/-/emojis/1/ticket.png
index 605936bb6b3..605936bb6b3 100644
--- a/app/assets/images/emoji/ticket.png
+++ b/public/-/emojis/1/ticket.png
Binary files differ
diff --git a/app/assets/images/emoji/tickets.png b/public/-/emojis/1/tickets.png
index e510f4a7a50..e510f4a7a50 100644
--- a/app/assets/images/emoji/tickets.png
+++ b/public/-/emojis/1/tickets.png
Binary files differ
diff --git a/app/assets/images/emoji/tiger.png b/public/-/emojis/1/tiger.png
index a4d3ef086d4..a4d3ef086d4 100644
--- a/app/assets/images/emoji/tiger.png
+++ b/public/-/emojis/1/tiger.png
Binary files differ
diff --git a/app/assets/images/emoji/tiger2.png b/public/-/emojis/1/tiger2.png
index 871a8b74d56..871a8b74d56 100644
--- a/app/assets/images/emoji/tiger2.png
+++ b/public/-/emojis/1/tiger2.png
Binary files differ
diff --git a/app/assets/images/emoji/timer.png b/public/-/emojis/1/timer.png
index 8a3be574c24..8a3be574c24 100644
--- a/app/assets/images/emoji/timer.png
+++ b/public/-/emojis/1/timer.png
Binary files differ
diff --git a/app/assets/images/emoji/tired_face.png b/public/-/emojis/1/tired_face.png
index 4e01eff5b23..4e01eff5b23 100644
--- a/app/assets/images/emoji/tired_face.png
+++ b/public/-/emojis/1/tired_face.png
Binary files differ
diff --git a/app/assets/images/emoji/tm.png b/public/-/emojis/1/tm.png
index 7a0c44a2c2b..7a0c44a2c2b 100644
--- a/app/assets/images/emoji/tm.png
+++ b/public/-/emojis/1/tm.png
Binary files differ
diff --git a/app/assets/images/emoji/toilet.png b/public/-/emojis/1/toilet.png
index 1392f761835..1392f761835 100644
--- a/app/assets/images/emoji/toilet.png
+++ b/public/-/emojis/1/toilet.png
Binary files differ
diff --git a/app/assets/images/emoji/tokyo_tower.png b/public/-/emojis/1/tokyo_tower.png
index 37df7fc65b1..37df7fc65b1 100644
--- a/app/assets/images/emoji/tokyo_tower.png
+++ b/public/-/emojis/1/tokyo_tower.png
Binary files differ
diff --git a/app/assets/images/emoji/tomato.png b/public/-/emojis/1/tomato.png
index 497da8f6b22..497da8f6b22 100644
--- a/app/assets/images/emoji/tomato.png
+++ b/public/-/emojis/1/tomato.png
Binary files differ
diff --git a/app/assets/images/emoji/tone1.png b/public/-/emojis/1/tone1.png
index c395f3d0d68..c395f3d0d68 100644
--- a/app/assets/images/emoji/tone1.png
+++ b/public/-/emojis/1/tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/tone2.png b/public/-/emojis/1/tone2.png
index 080847431c1..080847431c1 100644
--- a/app/assets/images/emoji/tone2.png
+++ b/public/-/emojis/1/tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/tone3.png b/public/-/emojis/1/tone3.png
index 482dd403475..482dd403475 100644
--- a/app/assets/images/emoji/tone3.png
+++ b/public/-/emojis/1/tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/tone4.png b/public/-/emojis/1/tone4.png
index 5cae8bb20b0..5cae8bb20b0 100644
--- a/app/assets/images/emoji/tone4.png
+++ b/public/-/emojis/1/tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/tone5.png b/public/-/emojis/1/tone5.png
index 49d1a8c3a64..49d1a8c3a64 100644
--- a/app/assets/images/emoji/tone5.png
+++ b/public/-/emojis/1/tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/tongue.png b/public/-/emojis/1/tongue.png
index 70ce9c1225f..70ce9c1225f 100644
--- a/app/assets/images/emoji/tongue.png
+++ b/public/-/emojis/1/tongue.png
Binary files differ
diff --git a/app/assets/images/emoji/tools.png b/public/-/emojis/1/tools.png
index 3c6049273a9..3c6049273a9 100644
--- a/app/assets/images/emoji/tools.png
+++ b/public/-/emojis/1/tools.png
Binary files differ
diff --git a/app/assets/images/emoji/top.png b/public/-/emojis/1/top.png
index 49dea8c08b5..49dea8c08b5 100644
--- a/app/assets/images/emoji/top.png
+++ b/public/-/emojis/1/top.png
Binary files differ
diff --git a/app/assets/images/emoji/tophat.png b/public/-/emojis/1/tophat.png
index 131b657b109..131b657b109 100644
--- a/app/assets/images/emoji/tophat.png
+++ b/public/-/emojis/1/tophat.png
Binary files differ
diff --git a/app/assets/images/emoji/track_next.png b/public/-/emojis/1/track_next.png
index f8880d33bab..f8880d33bab 100644
--- a/app/assets/images/emoji/track_next.png
+++ b/public/-/emojis/1/track_next.png
Binary files differ
diff --git a/app/assets/images/emoji/track_previous.png b/public/-/emojis/1/track_previous.png
index 1ffd0566cfc..1ffd0566cfc 100644
--- a/app/assets/images/emoji/track_previous.png
+++ b/public/-/emojis/1/track_previous.png
Binary files differ
diff --git a/app/assets/images/emoji/trackball.png b/public/-/emojis/1/trackball.png
index 3bea84ad7ce..3bea84ad7ce 100644
--- a/app/assets/images/emoji/trackball.png
+++ b/public/-/emojis/1/trackball.png
Binary files differ
diff --git a/app/assets/images/emoji/tractor.png b/public/-/emojis/1/tractor.png
index c1bf8cae44f..c1bf8cae44f 100644
--- a/app/assets/images/emoji/tractor.png
+++ b/public/-/emojis/1/tractor.png
Binary files differ
diff --git a/app/assets/images/emoji/traffic_light.png b/public/-/emojis/1/traffic_light.png
index 6b312285b00..6b312285b00 100644
--- a/app/assets/images/emoji/traffic_light.png
+++ b/public/-/emojis/1/traffic_light.png
Binary files differ
diff --git a/app/assets/images/emoji/train.png b/public/-/emojis/1/train.png
index 3c80321f7e8..3c80321f7e8 100644
--- a/app/assets/images/emoji/train.png
+++ b/public/-/emojis/1/train.png
Binary files differ
diff --git a/app/assets/images/emoji/train2.png b/public/-/emojis/1/train2.png
index 367c7bc5d39..367c7bc5d39 100644
--- a/app/assets/images/emoji/train2.png
+++ b/public/-/emojis/1/train2.png
Binary files differ
diff --git a/app/assets/images/emoji/tram.png b/public/-/emojis/1/tram.png
index b6f0e69038f..b6f0e69038f 100644
--- a/app/assets/images/emoji/tram.png
+++ b/public/-/emojis/1/tram.png
Binary files differ
diff --git a/app/assets/images/emoji/triangular_flag_on_post.png b/public/-/emojis/1/triangular_flag_on_post.png
index c12d8b06886..c12d8b06886 100644
--- a/app/assets/images/emoji/triangular_flag_on_post.png
+++ b/public/-/emojis/1/triangular_flag_on_post.png
Binary files differ
diff --git a/app/assets/images/emoji/triangular_ruler.png b/public/-/emojis/1/triangular_ruler.png
index 77dee9ee843..77dee9ee843 100644
--- a/app/assets/images/emoji/triangular_ruler.png
+++ b/public/-/emojis/1/triangular_ruler.png
Binary files differ
diff --git a/app/assets/images/emoji/trident.png b/public/-/emojis/1/trident.png
index 777a1dad121..777a1dad121 100644
--- a/app/assets/images/emoji/trident.png
+++ b/public/-/emojis/1/trident.png
Binary files differ
diff --git a/app/assets/images/emoji/triumph.png b/public/-/emojis/1/triumph.png
index 0be7a501969..0be7a501969 100644
--- a/app/assets/images/emoji/triumph.png
+++ b/public/-/emojis/1/triumph.png
Binary files differ
diff --git a/app/assets/images/emoji/trolleybus.png b/public/-/emojis/1/trolleybus.png
index 139a9931b52..139a9931b52 100644
--- a/app/assets/images/emoji/trolleybus.png
+++ b/public/-/emojis/1/trolleybus.png
Binary files differ
diff --git a/app/assets/images/emoji/trophy.png b/public/-/emojis/1/trophy.png
index ac2895c1896..ac2895c1896 100644
--- a/app/assets/images/emoji/trophy.png
+++ b/public/-/emojis/1/trophy.png
Binary files differ
diff --git a/app/assets/images/emoji/tropical_drink.png b/public/-/emojis/1/tropical_drink.png
index cd714f81b36..cd714f81b36 100644
--- a/app/assets/images/emoji/tropical_drink.png
+++ b/public/-/emojis/1/tropical_drink.png
Binary files differ
diff --git a/app/assets/images/emoji/tropical_fish.png b/public/-/emojis/1/tropical_fish.png
index 252105235a6..252105235a6 100644
--- a/app/assets/images/emoji/tropical_fish.png
+++ b/public/-/emojis/1/tropical_fish.png
Binary files differ
diff --git a/app/assets/images/emoji/truck.png b/public/-/emojis/1/truck.png
index 130de047f8b..130de047f8b 100644
--- a/app/assets/images/emoji/truck.png
+++ b/public/-/emojis/1/truck.png
Binary files differ
diff --git a/app/assets/images/emoji/trumpet.png b/public/-/emojis/1/trumpet.png
index 864ccbcd04a..864ccbcd04a 100644
--- a/app/assets/images/emoji/trumpet.png
+++ b/public/-/emojis/1/trumpet.png
Binary files differ
diff --git a/app/assets/images/emoji/tulip.png b/public/-/emojis/1/tulip.png
index f799d75c182..f799d75c182 100644
--- a/app/assets/images/emoji/tulip.png
+++ b/public/-/emojis/1/tulip.png
Binary files differ
diff --git a/app/assets/images/emoji/tumbler_glass.png b/public/-/emojis/1/tumbler_glass.png
index 7bf09229879..7bf09229879 100644
--- a/app/assets/images/emoji/tumbler_glass.png
+++ b/public/-/emojis/1/tumbler_glass.png
Binary files differ
diff --git a/app/assets/images/emoji/turkey.png b/public/-/emojis/1/turkey.png
index 344af94c9ec..344af94c9ec 100644
--- a/app/assets/images/emoji/turkey.png
+++ b/public/-/emojis/1/turkey.png
Binary files differ
diff --git a/app/assets/images/emoji/turtle.png b/public/-/emojis/1/turtle.png
index c22f7519fe8..c22f7519fe8 100644
--- a/app/assets/images/emoji/turtle.png
+++ b/public/-/emojis/1/turtle.png
Binary files differ
diff --git a/app/assets/images/emoji/tv.png b/public/-/emojis/1/tv.png
index 999f1fb5c6d..999f1fb5c6d 100644
--- a/app/assets/images/emoji/tv.png
+++ b/public/-/emojis/1/tv.png
Binary files differ
diff --git a/app/assets/images/emoji/twisted_rightwards_arrows.png b/public/-/emojis/1/twisted_rightwards_arrows.png
index 5904badde65..5904badde65 100644
--- a/app/assets/images/emoji/twisted_rightwards_arrows.png
+++ b/public/-/emojis/1/twisted_rightwards_arrows.png
Binary files differ
diff --git a/app/assets/images/emoji/two.png b/public/-/emojis/1/two.png
index 927339c9bff..927339c9bff 100644
--- a/app/assets/images/emoji/two.png
+++ b/public/-/emojis/1/two.png
Binary files differ
diff --git a/app/assets/images/emoji/two_hearts.png b/public/-/emojis/1/two_hearts.png
index 4d8c3386042..4d8c3386042 100644
--- a/app/assets/images/emoji/two_hearts.png
+++ b/public/-/emojis/1/two_hearts.png
Binary files differ
diff --git a/app/assets/images/emoji/two_men_holding_hands.png b/public/-/emojis/1/two_men_holding_hands.png
index a511fda822a..a511fda822a 100644
--- a/app/assets/images/emoji/two_men_holding_hands.png
+++ b/public/-/emojis/1/two_men_holding_hands.png
Binary files differ
diff --git a/app/assets/images/emoji/two_women_holding_hands.png b/public/-/emojis/1/two_women_holding_hands.png
index b077cd3e40f..b077cd3e40f 100644
--- a/app/assets/images/emoji/two_women_holding_hands.png
+++ b/public/-/emojis/1/two_women_holding_hands.png
Binary files differ
diff --git a/app/assets/images/emoji/u5272.png b/public/-/emojis/1/u5272.png
index c4f837fe684..c4f837fe684 100644
--- a/app/assets/images/emoji/u5272.png
+++ b/public/-/emojis/1/u5272.png
Binary files differ
diff --git a/app/assets/images/emoji/u5408.png b/public/-/emojis/1/u5408.png
index 8375ad9d9af..8375ad9d9af 100644
--- a/app/assets/images/emoji/u5408.png
+++ b/public/-/emojis/1/u5408.png
Binary files differ
diff --git a/app/assets/images/emoji/u55b6.png b/public/-/emojis/1/u55b6.png
index d21cb30eaf3..d21cb30eaf3 100644
--- a/app/assets/images/emoji/u55b6.png
+++ b/public/-/emojis/1/u55b6.png
Binary files differ
diff --git a/app/assets/images/emoji/u6307.png b/public/-/emojis/1/u6307.png
index 078e23e4ff3..078e23e4ff3 100644
--- a/app/assets/images/emoji/u6307.png
+++ b/public/-/emojis/1/u6307.png
Binary files differ
diff --git a/app/assets/images/emoji/u6708.png b/public/-/emojis/1/u6708.png
index c41bd36a26a..c41bd36a26a 100644
--- a/app/assets/images/emoji/u6708.png
+++ b/public/-/emojis/1/u6708.png
Binary files differ
diff --git a/app/assets/images/emoji/u6709.png b/public/-/emojis/1/u6709.png
index a4510de41c0..a4510de41c0 100644
--- a/app/assets/images/emoji/u6709.png
+++ b/public/-/emojis/1/u6709.png
Binary files differ
diff --git a/app/assets/images/emoji/u6e80.png b/public/-/emojis/1/u6e80.png
index f9dea8b8833..f9dea8b8833 100644
--- a/app/assets/images/emoji/u6e80.png
+++ b/public/-/emojis/1/u6e80.png
Binary files differ
diff --git a/app/assets/images/emoji/u7121.png b/public/-/emojis/1/u7121.png
index d3a19b420de..d3a19b420de 100644
--- a/app/assets/images/emoji/u7121.png
+++ b/public/-/emojis/1/u7121.png
Binary files differ
diff --git a/app/assets/images/emoji/u7533.png b/public/-/emojis/1/u7533.png
index 6b7af0ee222..6b7af0ee222 100644
--- a/app/assets/images/emoji/u7533.png
+++ b/public/-/emojis/1/u7533.png
Binary files differ
diff --git a/app/assets/images/emoji/u7981.png b/public/-/emojis/1/u7981.png
index 4c704e03433..4c704e03433 100644
--- a/app/assets/images/emoji/u7981.png
+++ b/public/-/emojis/1/u7981.png
Binary files differ
diff --git a/app/assets/images/emoji/u7a7a.png b/public/-/emojis/1/u7a7a.png
index 47966c1ea93..47966c1ea93 100644
--- a/app/assets/images/emoji/u7a7a.png
+++ b/public/-/emojis/1/u7a7a.png
Binary files differ
diff --git a/app/assets/images/emoji/umbrella.png b/public/-/emojis/1/umbrella.png
index 5b35b7ff6a4..5b35b7ff6a4 100644
--- a/app/assets/images/emoji/umbrella.png
+++ b/public/-/emojis/1/umbrella.png
Binary files differ
diff --git a/app/assets/images/emoji/umbrella2.png b/public/-/emojis/1/umbrella2.png
index 97fe859e74f..97fe859e74f 100644
--- a/app/assets/images/emoji/umbrella2.png
+++ b/public/-/emojis/1/umbrella2.png
Binary files differ
diff --git a/app/assets/images/emoji/unamused.png b/public/-/emojis/1/unamused.png
index 25e3677f2eb..25e3677f2eb 100644
--- a/app/assets/images/emoji/unamused.png
+++ b/public/-/emojis/1/unamused.png
Binary files differ
diff --git a/app/assets/images/emoji/underage.png b/public/-/emojis/1/underage.png
index 6dfe6da51e2..6dfe6da51e2 100644
--- a/app/assets/images/emoji/underage.png
+++ b/public/-/emojis/1/underage.png
Binary files differ
diff --git a/app/assets/images/emoji/unicorn.png b/public/-/emojis/1/unicorn.png
index 05a97969f7e..05a97969f7e 100644
--- a/app/assets/images/emoji/unicorn.png
+++ b/public/-/emojis/1/unicorn.png
Binary files differ
diff --git a/app/assets/images/emoji/unlock.png b/public/-/emojis/1/unlock.png
index 4a74a693911..4a74a693911 100644
--- a/app/assets/images/emoji/unlock.png
+++ b/public/-/emojis/1/unlock.png
Binary files differ
diff --git a/app/assets/images/emoji/up.png b/public/-/emojis/1/up.png
index 0d42142ba04..0d42142ba04 100644
--- a/app/assets/images/emoji/up.png
+++ b/public/-/emojis/1/up.png
Binary files differ
diff --git a/app/assets/images/emoji/upside_down.png b/public/-/emojis/1/upside_down.png
index 128f31c9828..128f31c9828 100644
--- a/app/assets/images/emoji/upside_down.png
+++ b/public/-/emojis/1/upside_down.png
Binary files differ
diff --git a/app/assets/images/emoji/urn.png b/public/-/emojis/1/urn.png
index 6b5b3503438..6b5b3503438 100644
--- a/app/assets/images/emoji/urn.png
+++ b/public/-/emojis/1/urn.png
Binary files differ
diff --git a/app/assets/images/emoji/v.png b/public/-/emojis/1/v.png
index 70c5516ffee..70c5516ffee 100644
--- a/app/assets/images/emoji/v.png
+++ b/public/-/emojis/1/v.png
Binary files differ
diff --git a/app/assets/images/emoji/v_tone1.png b/public/-/emojis/1/v_tone1.png
index 6ac54a745f4..6ac54a745f4 100644
--- a/app/assets/images/emoji/v_tone1.png
+++ b/public/-/emojis/1/v_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/v_tone2.png b/public/-/emojis/1/v_tone2.png
index 6dd9669866d..6dd9669866d 100644
--- a/app/assets/images/emoji/v_tone2.png
+++ b/public/-/emojis/1/v_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/v_tone3.png b/public/-/emojis/1/v_tone3.png
index a615e53f02f..a615e53f02f 100644
--- a/app/assets/images/emoji/v_tone3.png
+++ b/public/-/emojis/1/v_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/v_tone4.png b/public/-/emojis/1/v_tone4.png
index 33a34bd5a78..33a34bd5a78 100644
--- a/app/assets/images/emoji/v_tone4.png
+++ b/public/-/emojis/1/v_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/v_tone5.png b/public/-/emojis/1/v_tone5.png
index 45ad14b6c9c..45ad14b6c9c 100644
--- a/app/assets/images/emoji/v_tone5.png
+++ b/public/-/emojis/1/v_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/vertical_traffic_light.png b/public/-/emojis/1/vertical_traffic_light.png
index 8085973eecf..8085973eecf 100644
--- a/app/assets/images/emoji/vertical_traffic_light.png
+++ b/public/-/emojis/1/vertical_traffic_light.png
Binary files differ
diff --git a/app/assets/images/emoji/vhs.png b/public/-/emojis/1/vhs.png
index b9eb78ecd92..b9eb78ecd92 100644
--- a/app/assets/images/emoji/vhs.png
+++ b/public/-/emojis/1/vhs.png
Binary files differ
diff --git a/app/assets/images/emoji/vibration_mode.png b/public/-/emojis/1/vibration_mode.png
index cc46510e48e..cc46510e48e 100644
--- a/app/assets/images/emoji/vibration_mode.png
+++ b/public/-/emojis/1/vibration_mode.png
Binary files differ
diff --git a/app/assets/images/emoji/video_camera.png b/public/-/emojis/1/video_camera.png
index 85b300d425c..85b300d425c 100644
--- a/app/assets/images/emoji/video_camera.png
+++ b/public/-/emojis/1/video_camera.png
Binary files differ
diff --git a/app/assets/images/emoji/video_game.png b/public/-/emojis/1/video_game.png
index 316a9106a55..316a9106a55 100644
--- a/app/assets/images/emoji/video_game.png
+++ b/public/-/emojis/1/video_game.png
Binary files differ
diff --git a/app/assets/images/emoji/violin.png b/public/-/emojis/1/violin.png
index e1e76cce242..e1e76cce242 100644
--- a/app/assets/images/emoji/violin.png
+++ b/public/-/emojis/1/violin.png
Binary files differ
diff --git a/app/assets/images/emoji/virgo.png b/public/-/emojis/1/virgo.png
index a6b56c2cb5e..a6b56c2cb5e 100644
--- a/app/assets/images/emoji/virgo.png
+++ b/public/-/emojis/1/virgo.png
Binary files differ
diff --git a/app/assets/images/emoji/volcano.png b/public/-/emojis/1/volcano.png
index 931d569294c..931d569294c 100644
--- a/app/assets/images/emoji/volcano.png
+++ b/public/-/emojis/1/volcano.png
Binary files differ
diff --git a/app/assets/images/emoji/volleyball.png b/public/-/emojis/1/volleyball.png
index 7a0e49d4b07..7a0e49d4b07 100644
--- a/app/assets/images/emoji/volleyball.png
+++ b/public/-/emojis/1/volleyball.png
Binary files differ
diff --git a/app/assets/images/emoji/vs.png b/public/-/emojis/1/vs.png
index e1180f4a464..e1180f4a464 100644
--- a/app/assets/images/emoji/vs.png
+++ b/public/-/emojis/1/vs.png
Binary files differ
diff --git a/app/assets/images/emoji/vulcan.png b/public/-/emojis/1/vulcan.png
index 54728bcaf5c..54728bcaf5c 100644
--- a/app/assets/images/emoji/vulcan.png
+++ b/public/-/emojis/1/vulcan.png
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone1.png b/public/-/emojis/1/vulcan_tone1.png
index 8aff5d8fa16..8aff5d8fa16 100644
--- a/app/assets/images/emoji/vulcan_tone1.png
+++ b/public/-/emojis/1/vulcan_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone2.png b/public/-/emojis/1/vulcan_tone2.png
index 82b7ad519b4..82b7ad519b4 100644
--- a/app/assets/images/emoji/vulcan_tone2.png
+++ b/public/-/emojis/1/vulcan_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone3.png b/public/-/emojis/1/vulcan_tone3.png
index d1400e1dd28..d1400e1dd28 100644
--- a/app/assets/images/emoji/vulcan_tone3.png
+++ b/public/-/emojis/1/vulcan_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone4.png b/public/-/emojis/1/vulcan_tone4.png
index 47e2b280148..47e2b280148 100644
--- a/app/assets/images/emoji/vulcan_tone4.png
+++ b/public/-/emojis/1/vulcan_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone5.png b/public/-/emojis/1/vulcan_tone5.png
index 60b5c6077be..60b5c6077be 100644
--- a/app/assets/images/emoji/vulcan_tone5.png
+++ b/public/-/emojis/1/vulcan_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/walking.png b/public/-/emojis/1/walking.png
index 06dc169a3fd..06dc169a3fd 100644
--- a/app/assets/images/emoji/walking.png
+++ b/public/-/emojis/1/walking.png
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone1.png b/public/-/emojis/1/walking_tone1.png
index 4e391b45a0b..4e391b45a0b 100644
--- a/app/assets/images/emoji/walking_tone1.png
+++ b/public/-/emojis/1/walking_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone2.png b/public/-/emojis/1/walking_tone2.png
index 31f94a1bce1..31f94a1bce1 100644
--- a/app/assets/images/emoji/walking_tone2.png
+++ b/public/-/emojis/1/walking_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone3.png b/public/-/emojis/1/walking_tone3.png
index f7ed8e39c2e..f7ed8e39c2e 100644
--- a/app/assets/images/emoji/walking_tone3.png
+++ b/public/-/emojis/1/walking_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone4.png b/public/-/emojis/1/walking_tone4.png
index e58dc04c7b2..e58dc04c7b2 100644
--- a/app/assets/images/emoji/walking_tone4.png
+++ b/public/-/emojis/1/walking_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone5.png b/public/-/emojis/1/walking_tone5.png
index ba4e1b58fcb..ba4e1b58fcb 100644
--- a/app/assets/images/emoji/walking_tone5.png
+++ b/public/-/emojis/1/walking_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/waning_crescent_moon.png b/public/-/emojis/1/waning_crescent_moon.png
index cf68706b871..cf68706b871 100644
--- a/app/assets/images/emoji/waning_crescent_moon.png
+++ b/public/-/emojis/1/waning_crescent_moon.png
Binary files differ
diff --git a/app/assets/images/emoji/waning_gibbous_moon.png b/public/-/emojis/1/waning_gibbous_moon.png
index 24e16266119..24e16266119 100644
--- a/app/assets/images/emoji/waning_gibbous_moon.png
+++ b/public/-/emojis/1/waning_gibbous_moon.png
Binary files differ
diff --git a/app/assets/images/emoji/warning.png b/public/-/emojis/1/warning.png
index 35691c2ed97..35691c2ed97 100644
--- a/app/assets/images/emoji/warning.png
+++ b/public/-/emojis/1/warning.png
Binary files differ
diff --git a/app/assets/images/emoji/wastebasket.png b/public/-/emojis/1/wastebasket.png
index 2b3c484b498..2b3c484b498 100644
--- a/app/assets/images/emoji/wastebasket.png
+++ b/public/-/emojis/1/wastebasket.png
Binary files differ
diff --git a/app/assets/images/emoji/watch.png b/public/-/emojis/1/watch.png
index 64819bc6e21..64819bc6e21 100644
--- a/app/assets/images/emoji/watch.png
+++ b/public/-/emojis/1/watch.png
Binary files differ
diff --git a/app/assets/images/emoji/water_buffalo.png b/public/-/emojis/1/water_buffalo.png
index 80446615caf..80446615caf 100644
--- a/app/assets/images/emoji/water_buffalo.png
+++ b/public/-/emojis/1/water_buffalo.png
Binary files differ
diff --git a/app/assets/images/emoji/water_polo.png b/public/-/emojis/1/water_polo.png
index cb44576780d..cb44576780d 100644
--- a/app/assets/images/emoji/water_polo.png
+++ b/public/-/emojis/1/water_polo.png
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone1.png b/public/-/emojis/1/water_polo_tone1.png
index bed1a908d6a..bed1a908d6a 100644
--- a/app/assets/images/emoji/water_polo_tone1.png
+++ b/public/-/emojis/1/water_polo_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone2.png b/public/-/emojis/1/water_polo_tone2.png
index ec5a43b4d4a..ec5a43b4d4a 100644
--- a/app/assets/images/emoji/water_polo_tone2.png
+++ b/public/-/emojis/1/water_polo_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone3.png b/public/-/emojis/1/water_polo_tone3.png
index b081a4a5a96..b081a4a5a96 100644
--- a/app/assets/images/emoji/water_polo_tone3.png
+++ b/public/-/emojis/1/water_polo_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone4.png b/public/-/emojis/1/water_polo_tone4.png
index 82cfbc3b0c7..82cfbc3b0c7 100644
--- a/app/assets/images/emoji/water_polo_tone4.png
+++ b/public/-/emojis/1/water_polo_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone5.png b/public/-/emojis/1/water_polo_tone5.png
index bd3366eb06c..bd3366eb06c 100644
--- a/app/assets/images/emoji/water_polo_tone5.png
+++ b/public/-/emojis/1/water_polo_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/watermelon.png b/public/-/emojis/1/watermelon.png
index 0761488b4c9..0761488b4c9 100644
--- a/app/assets/images/emoji/watermelon.png
+++ b/public/-/emojis/1/watermelon.png
Binary files differ
diff --git a/app/assets/images/emoji/wave.png b/public/-/emojis/1/wave.png
index e0cd79b45f5..e0cd79b45f5 100644
--- a/app/assets/images/emoji/wave.png
+++ b/public/-/emojis/1/wave.png
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone1.png b/public/-/emojis/1/wave_tone1.png
index 6b2b34b106e..6b2b34b106e 100644
--- a/app/assets/images/emoji/wave_tone1.png
+++ b/public/-/emojis/1/wave_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone2.png b/public/-/emojis/1/wave_tone2.png
index b857119732e..b857119732e 100644
--- a/app/assets/images/emoji/wave_tone2.png
+++ b/public/-/emojis/1/wave_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone3.png b/public/-/emojis/1/wave_tone3.png
index 6283b670f43..6283b670f43 100644
--- a/app/assets/images/emoji/wave_tone3.png
+++ b/public/-/emojis/1/wave_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone4.png b/public/-/emojis/1/wave_tone4.png
index fe6b2baa747..fe6b2baa747 100644
--- a/app/assets/images/emoji/wave_tone4.png
+++ b/public/-/emojis/1/wave_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone5.png b/public/-/emojis/1/wave_tone5.png
index 4bd168ebb78..4bd168ebb78 100644
--- a/app/assets/images/emoji/wave_tone5.png
+++ b/public/-/emojis/1/wave_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/wavy_dash.png b/public/-/emojis/1/wavy_dash.png
index 001c8d6e47d..001c8d6e47d 100644
--- a/app/assets/images/emoji/wavy_dash.png
+++ b/public/-/emojis/1/wavy_dash.png
Binary files differ
diff --git a/app/assets/images/emoji/waxing_crescent_moon.png b/public/-/emojis/1/waxing_crescent_moon.png
index 687125173d9..687125173d9 100644
--- a/app/assets/images/emoji/waxing_crescent_moon.png
+++ b/public/-/emojis/1/waxing_crescent_moon.png
Binary files differ
diff --git a/app/assets/images/emoji/waxing_gibbous_moon.png b/public/-/emojis/1/waxing_gibbous_moon.png
index 3a808156318..3a808156318 100644
--- a/app/assets/images/emoji/waxing_gibbous_moon.png
+++ b/public/-/emojis/1/waxing_gibbous_moon.png
Binary files differ
diff --git a/app/assets/images/emoji/wc.png b/public/-/emojis/1/wc.png
index aa433e84ba6..aa433e84ba6 100644
--- a/app/assets/images/emoji/wc.png
+++ b/public/-/emojis/1/wc.png
Binary files differ
diff --git a/app/assets/images/emoji/weary.png b/public/-/emojis/1/weary.png
index 98bfbd24a16..98bfbd24a16 100644
--- a/app/assets/images/emoji/weary.png
+++ b/public/-/emojis/1/weary.png
Binary files differ
diff --git a/app/assets/images/emoji/wedding.png b/public/-/emojis/1/wedding.png
index d0d8aa0bfae..d0d8aa0bfae 100644
--- a/app/assets/images/emoji/wedding.png
+++ b/public/-/emojis/1/wedding.png
Binary files differ
diff --git a/app/assets/images/emoji/whale.png b/public/-/emojis/1/whale.png
index 9f19b44257c..9f19b44257c 100644
--- a/app/assets/images/emoji/whale.png
+++ b/public/-/emojis/1/whale.png
Binary files differ
diff --git a/app/assets/images/emoji/whale2.png b/public/-/emojis/1/whale2.png
index 0df9d3c73a4..0df9d3c73a4 100644
--- a/app/assets/images/emoji/whale2.png
+++ b/public/-/emojis/1/whale2.png
Binary files differ
diff --git a/app/assets/images/emoji/wheel_of_dharma.png b/public/-/emojis/1/wheel_of_dharma.png
index 3666db0016b..3666db0016b 100644
--- a/app/assets/images/emoji/wheel_of_dharma.png
+++ b/public/-/emojis/1/wheel_of_dharma.png
Binary files differ
diff --git a/app/assets/images/emoji/wheelchair.png b/public/-/emojis/1/wheelchair.png
index 4e5b2698eac..4e5b2698eac 100644
--- a/app/assets/images/emoji/wheelchair.png
+++ b/public/-/emojis/1/wheelchair.png
Binary files differ
diff --git a/app/assets/images/emoji/white_check_mark.png b/public/-/emojis/1/white_check_mark.png
index e55f087e544..e55f087e544 100644
--- a/app/assets/images/emoji/white_check_mark.png
+++ b/public/-/emojis/1/white_check_mark.png
Binary files differ
diff --git a/app/assets/images/emoji/white_circle.png b/public/-/emojis/1/white_circle.png
index c19e15684dd..c19e15684dd 100644
--- a/app/assets/images/emoji/white_circle.png
+++ b/public/-/emojis/1/white_circle.png
Binary files differ
diff --git a/app/assets/images/emoji/white_flower.png b/public/-/emojis/1/white_flower.png
index d6af8b60077..d6af8b60077 100644
--- a/app/assets/images/emoji/white_flower.png
+++ b/public/-/emojis/1/white_flower.png
Binary files differ
diff --git a/app/assets/images/emoji/white_large_square.png b/public/-/emojis/1/white_large_square.png
index 6f06c1c79de..6f06c1c79de 100644
--- a/app/assets/images/emoji/white_large_square.png
+++ b/public/-/emojis/1/white_large_square.png
Binary files differ
diff --git a/app/assets/images/emoji/white_medium_small_square.png b/public/-/emojis/1/white_medium_small_square.png
index ae874126750..ae874126750 100644
--- a/app/assets/images/emoji/white_medium_small_square.png
+++ b/public/-/emojis/1/white_medium_small_square.png
Binary files differ
diff --git a/app/assets/images/emoji/white_medium_square.png b/public/-/emojis/1/white_medium_square.png
index 8daacf57059..8daacf57059 100644
--- a/app/assets/images/emoji/white_medium_square.png
+++ b/public/-/emojis/1/white_medium_square.png
Binary files differ
diff --git a/app/assets/images/emoji/white_small_square.png b/public/-/emojis/1/white_small_square.png
index d7ebdb0c0ed..d7ebdb0c0ed 100644
--- a/app/assets/images/emoji/white_small_square.png
+++ b/public/-/emojis/1/white_small_square.png
Binary files differ
diff --git a/app/assets/images/emoji/white_square_button.png b/public/-/emojis/1/white_square_button.png
index 934b1cedfd2..934b1cedfd2 100644
--- a/app/assets/images/emoji/white_square_button.png
+++ b/public/-/emojis/1/white_square_button.png
Binary files differ
diff --git a/app/assets/images/emoji/white_sun_cloud.png b/public/-/emojis/1/white_sun_cloud.png
index 0a4cc100269..0a4cc100269 100644
--- a/app/assets/images/emoji/white_sun_cloud.png
+++ b/public/-/emojis/1/white_sun_cloud.png
Binary files differ
diff --git a/app/assets/images/emoji/white_sun_rain_cloud.png b/public/-/emojis/1/white_sun_rain_cloud.png
index 491f9ca4839..491f9ca4839 100644
--- a/app/assets/images/emoji/white_sun_rain_cloud.png
+++ b/public/-/emojis/1/white_sun_rain_cloud.png
Binary files differ
diff --git a/app/assets/images/emoji/white_sun_small_cloud.png b/public/-/emojis/1/white_sun_small_cloud.png
index cead0bfa521..cead0bfa521 100644
--- a/app/assets/images/emoji/white_sun_small_cloud.png
+++ b/public/-/emojis/1/white_sun_small_cloud.png
Binary files differ
diff --git a/app/assets/images/emoji/wilted_rose.png b/public/-/emojis/1/wilted_rose.png
index 62412b143ae..62412b143ae 100644
--- a/app/assets/images/emoji/wilted_rose.png
+++ b/public/-/emojis/1/wilted_rose.png
Binary files differ
diff --git a/app/assets/images/emoji/wind_blowing_face.png b/public/-/emojis/1/wind_blowing_face.png
index df81b652eb6..df81b652eb6 100644
--- a/app/assets/images/emoji/wind_blowing_face.png
+++ b/public/-/emojis/1/wind_blowing_face.png
Binary files differ
diff --git a/app/assets/images/emoji/wind_chime.png b/public/-/emojis/1/wind_chime.png
index 3c9ef3a95f6..3c9ef3a95f6 100644
--- a/app/assets/images/emoji/wind_chime.png
+++ b/public/-/emojis/1/wind_chime.png
Binary files differ
diff --git a/app/assets/images/emoji/wine_glass.png b/public/-/emojis/1/wine_glass.png
index 3cc98689192..3cc98689192 100644
--- a/app/assets/images/emoji/wine_glass.png
+++ b/public/-/emojis/1/wine_glass.png
Binary files differ
diff --git a/app/assets/images/emoji/wink.png b/public/-/emojis/1/wink.png
index 7ea7810a37d..7ea7810a37d 100644
--- a/app/assets/images/emoji/wink.png
+++ b/public/-/emojis/1/wink.png
Binary files differ
diff --git a/app/assets/images/emoji/wolf.png b/public/-/emojis/1/wolf.png
index ba7220f2de9..ba7220f2de9 100644
--- a/app/assets/images/emoji/wolf.png
+++ b/public/-/emojis/1/wolf.png
Binary files differ
diff --git a/app/assets/images/emoji/woman.png b/public/-/emojis/1/woman.png
index ece440e7a61..ece440e7a61 100644
--- a/app/assets/images/emoji/woman.png
+++ b/public/-/emojis/1/woman.png
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone1.png b/public/-/emojis/1/woman_tone1.png
index ff089b8889b..ff089b8889b 100644
--- a/app/assets/images/emoji/woman_tone1.png
+++ b/public/-/emojis/1/woman_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone2.png b/public/-/emojis/1/woman_tone2.png
index 0719c378016..0719c378016 100644
--- a/app/assets/images/emoji/woman_tone2.png
+++ b/public/-/emojis/1/woman_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone3.png b/public/-/emojis/1/woman_tone3.png
index 5672e2fd52d..5672e2fd52d 100644
--- a/app/assets/images/emoji/woman_tone3.png
+++ b/public/-/emojis/1/woman_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone4.png b/public/-/emojis/1/woman_tone4.png
index 5754aab558b..5754aab558b 100644
--- a/app/assets/images/emoji/woman_tone4.png
+++ b/public/-/emojis/1/woman_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone5.png b/public/-/emojis/1/woman_tone5.png
index fc252af3a39..fc252af3a39 100644
--- a/app/assets/images/emoji/woman_tone5.png
+++ b/public/-/emojis/1/woman_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/womans_clothes.png b/public/-/emojis/1/womans_clothes.png
index 01410dc8107..01410dc8107 100644
--- a/app/assets/images/emoji/womans_clothes.png
+++ b/public/-/emojis/1/womans_clothes.png
Binary files differ
diff --git a/app/assets/images/emoji/womans_hat.png b/public/-/emojis/1/womans_hat.png
index b837b6a2e47..b837b6a2e47 100644
--- a/app/assets/images/emoji/womans_hat.png
+++ b/public/-/emojis/1/womans_hat.png
Binary files differ
diff --git a/app/assets/images/emoji/womens.png b/public/-/emojis/1/womens.png
index d4ecc22e7b3..d4ecc22e7b3 100644
--- a/app/assets/images/emoji/womens.png
+++ b/public/-/emojis/1/womens.png
Binary files differ
diff --git a/app/assets/images/emoji/worried.png b/public/-/emojis/1/worried.png
index 7074afcf5b7..7074afcf5b7 100644
--- a/app/assets/images/emoji/worried.png
+++ b/public/-/emojis/1/worried.png
Binary files differ
diff --git a/app/assets/images/emoji/wrench.png b/public/-/emojis/1/wrench.png
index c16b7439697..c16b7439697 100644
--- a/app/assets/images/emoji/wrench.png
+++ b/public/-/emojis/1/wrench.png
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers.png b/public/-/emojis/1/wrestlers.png
index 71e67cfad85..71e67cfad85 100644
--- a/app/assets/images/emoji/wrestlers.png
+++ b/public/-/emojis/1/wrestlers.png
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone1.png b/public/-/emojis/1/wrestlers_tone1.png
index 379070fd03b..379070fd03b 100644
--- a/app/assets/images/emoji/wrestlers_tone1.png
+++ b/public/-/emojis/1/wrestlers_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone2.png b/public/-/emojis/1/wrestlers_tone2.png
index 6863ea9209d..6863ea9209d 100644
--- a/app/assets/images/emoji/wrestlers_tone2.png
+++ b/public/-/emojis/1/wrestlers_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone3.png b/public/-/emojis/1/wrestlers_tone3.png
index b7e62910127..b7e62910127 100644
--- a/app/assets/images/emoji/wrestlers_tone3.png
+++ b/public/-/emojis/1/wrestlers_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone4.png b/public/-/emojis/1/wrestlers_tone4.png
index 750f9589233..750f9589233 100644
--- a/app/assets/images/emoji/wrestlers_tone4.png
+++ b/public/-/emojis/1/wrestlers_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone5.png b/public/-/emojis/1/wrestlers_tone5.png
index 36ab9bb3f42..36ab9bb3f42 100644
--- a/app/assets/images/emoji/wrestlers_tone5.png
+++ b/public/-/emojis/1/wrestlers_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand.png b/public/-/emojis/1/writing_hand.png
index 85639f8ac40..85639f8ac40 100644
--- a/app/assets/images/emoji/writing_hand.png
+++ b/public/-/emojis/1/writing_hand.png
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone1.png b/public/-/emojis/1/writing_hand_tone1.png
index 7923d8ebb17..7923d8ebb17 100644
--- a/app/assets/images/emoji/writing_hand_tone1.png
+++ b/public/-/emojis/1/writing_hand_tone1.png
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone2.png b/public/-/emojis/1/writing_hand_tone2.png
index bcb304e15d2..bcb304e15d2 100644
--- a/app/assets/images/emoji/writing_hand_tone2.png
+++ b/public/-/emojis/1/writing_hand_tone2.png
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone3.png b/public/-/emojis/1/writing_hand_tone3.png
index fd885fd2d90..fd885fd2d90 100644
--- a/app/assets/images/emoji/writing_hand_tone3.png
+++ b/public/-/emojis/1/writing_hand_tone3.png
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone4.png b/public/-/emojis/1/writing_hand_tone4.png
index d065b8c64ab..d065b8c64ab 100644
--- a/app/assets/images/emoji/writing_hand_tone4.png
+++ b/public/-/emojis/1/writing_hand_tone4.png
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone5.png b/public/-/emojis/1/writing_hand_tone5.png
index a44b3dd757c..a44b3dd757c 100644
--- a/app/assets/images/emoji/writing_hand_tone5.png
+++ b/public/-/emojis/1/writing_hand_tone5.png
Binary files differ
diff --git a/app/assets/images/emoji/x.png b/public/-/emojis/1/x.png
index 9f9ed0f7ad2..9f9ed0f7ad2 100644
--- a/app/assets/images/emoji/x.png
+++ b/public/-/emojis/1/x.png
Binary files differ
diff --git a/app/assets/images/emoji/yellow_heart.png b/public/-/emojis/1/yellow_heart.png
index 7901a9d0103..7901a9d0103 100644
--- a/app/assets/images/emoji/yellow_heart.png
+++ b/public/-/emojis/1/yellow_heart.png
Binary files differ
diff --git a/app/assets/images/emoji/yen.png b/public/-/emojis/1/yen.png
index 63ee4799d66..63ee4799d66 100644
--- a/app/assets/images/emoji/yen.png
+++ b/public/-/emojis/1/yen.png
Binary files differ
diff --git a/app/assets/images/emoji/yin_yang.png b/public/-/emojis/1/yin_yang.png
index f2900f6338f..f2900f6338f 100644
--- a/app/assets/images/emoji/yin_yang.png
+++ b/public/-/emojis/1/yin_yang.png
Binary files differ
diff --git a/app/assets/images/emoji/yum.png b/public/-/emojis/1/yum.png
index 2df15753ca1..2df15753ca1 100644
--- a/app/assets/images/emoji/yum.png
+++ b/public/-/emojis/1/yum.png
Binary files differ
diff --git a/app/assets/images/emoji/zap.png b/public/-/emojis/1/zap.png
index 47e68e48e49..47e68e48e49 100644
--- a/app/assets/images/emoji/zap.png
+++ b/public/-/emojis/1/zap.png
Binary files differ
diff --git a/app/assets/images/emoji/zero.png b/public/-/emojis/1/zero.png
index 13aca83e018..13aca83e018 100644
--- a/app/assets/images/emoji/zero.png
+++ b/public/-/emojis/1/zero.png
Binary files differ
diff --git a/app/assets/images/emoji/zipper_mouth.png b/public/-/emojis/1/zipper_mouth.png
index f8ced2502a7..f8ced2502a7 100644
--- a/app/assets/images/emoji/zipper_mouth.png
+++ b/public/-/emojis/1/zipper_mouth.png
Binary files differ
diff --git a/app/assets/images/emoji/zzz.png b/public/-/emojis/1/zzz.png
index 9bc72b4469f..9bc72b4469f 100644
--- a/app/assets/images/emoji/zzz.png
+++ b/public/-/emojis/1/zzz.png
Binary files differ
diff --git a/qa/.gitignore b/qa/.gitignore
index 19ec17d0005..102f7e5e54d 100644
--- a/qa/.gitignore
+++ b/qa/.gitignore
@@ -1,2 +1,3 @@
tmp/
.ruby-version
+urls.txt
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 9956ced0ef6..ca7f9accb70 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:2.4-stretch
+FROM ruby:2.5-stretch
LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>"
ENV DEBIAN_FRONTEND noninteractive
diff --git a/qa/Gemfile b/qa/Gemfile
index d69c71003ae..38e95ba2d65 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -5,5 +5,8 @@ gem 'capybara', '~> 2.16.1'
gem 'capybara-screenshot', '~> 1.0.18'
gem 'rake', '~> 12.3.0'
gem 'rspec', '~> 3.7'
-gem 'selenium-webdriver', '~> 3.8.0'
+gem 'selenium-webdriver', '~> 3.12'
gem 'airborne', '~> 0.2.13'
+gem 'nokogiri', '~> 1.10.1'
+gem 'rspec-retry', '~> 0.6.1'
+gem 'faker', '~> 1.6', '>= 1.6.6'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index d61ecf8fbb5..c9b0db6a272 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -25,13 +25,15 @@ GEM
capybara-screenshot (1.0.18)
capybara (>= 1.0, < 3)
launchy
- childprocess (0.8.0)
+ childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
coderay (1.1.2)
concurrent-ruby (1.0.5)
diff-lcs (1.3)
domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
+ faker (1.9.3)
+ i18n (>= 0.7)
ffi (1.9.25)
http-cookie (1.0.3)
domain_name (~> 0.5)
@@ -44,11 +46,11 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_mime (1.0.0)
- mini_portile2 (2.3.0)
+ mini_portile2 (2.4.0)
minitest (5.11.1)
netrc (0.11.0)
- nokogiri (1.8.2)
- mini_portile2 (~> 2.3.0)
+ nokogiri (1.10.1)
+ mini_portile2 (~> 2.4.0)
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
@@ -76,11 +78,13 @@ GEM
rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
+ rspec-retry (0.6.1)
+ rspec-core (> 3.3)
rspec-support (3.7.0)
rubyzip (1.2.2)
- selenium-webdriver (3.8.0)
+ selenium-webdriver (3.141.0)
childprocess (~> 0.5)
- rubyzip (~> 1.0)
+ rubyzip (~> 1.2, >= 1.2.2)
thread_safe (0.3.6)
tzinfo (1.2.4)
thread_safe (~> 0.1)
@@ -97,10 +101,13 @@ DEPENDENCIES
airborne (~> 0.2.13)
capybara (~> 2.16.1)
capybara-screenshot (~> 1.0.18)
+ faker (~> 1.6, >= 1.6.6)
+ nokogiri (~> 1.10.1)
pry-byebug (~> 3.5.1)
rake (~> 12.3.0)
rspec (~> 3.7)
- selenium-webdriver (~> 3.8.0)
+ rspec-retry (~> 0.6.1)
+ selenium-webdriver (~> 3.12)
BUNDLED WITH
- 1.17.1
+ 1.17.3
diff --git a/qa/README.md b/qa/README.md
index 08ba59e117d..735868e7640 100644
--- a/qa/README.md
+++ b/qa/README.md
@@ -1,21 +1,25 @@
-# GitLab QA - Integration tests for GitLab
+# GitLab QA - End-to-end tests for GitLab
-This directory contains integration tests for GitLab.
+This directory contains [end-to-end tests](doc/development/testing_guide/end_to_end_tests.md)
+for GitLab. It includes the test framework and the tests themselves.
+
+The tests can be found in `qa/specs/features` (not to be confused with the unit
+tests for the test framework, which are in `spec/`).
It is part of the [GitLab QA project](https://gitlab.com/gitlab-org/gitlab-qa).
## What is it?
-GitLab QA is an integration tests suite for GitLab.
+GitLab QA is an end-to-end tests suite for GitLab.
-These are black-box and entirely click-driven integration tests you can run
+These are black-box and entirely click-driven end-to-end tests you can run
against any existing instance.
## How does it work?
1. When we release a new version of GitLab, we build a Docker images for it.
1. Along with GitLab Docker Images we also build and publish GitLab QA images.
-1. GitLab QA project uses these images to execute integration tests.
+1. GitLab QA project uses these images to execute end-to-end tests.
## Validating GitLab views / partials / selectors in merge requests
@@ -38,6 +42,9 @@ following call would login to a local [GDK] instance and run all specs in
bin/qa Test::Instance::All http://localhost:3000
```
+Note: If you want to run tests requiring SSH against GDK, you
+will need to [modify your GDK setup](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md).
+
### Writing tests
1. [Using page objects](qa/page/README.md)
@@ -86,7 +93,7 @@ The environment variable `QA_COOKIES` can be set to send additional cookies
on every request. This is necessary on gitlab.com to direct traffic to the
canary fleet. To do this set `QA_COOKIES="gitlab_canary=true"`.
-To set multiple cookies, separate them with the `;` character, for example: `QA_COOKIES="cookie1=value;cookie2=value2"`
+To set multiple cookies, separate them with the `;` character, for example: `QA_COOKIES="cookie1=value;cookie2=value2"`
### Building a Docker image to test
@@ -100,3 +107,24 @@ docker build -t gitlab/gitlab-ce-qa:nightly .
```
[GDK]: https://gitlab.com/gitlab-org/gitlab-development-kit/
+
+### Quarantined tests
+
+Tests can be put in quarantine by assigning `:quarantine` metadata. This means
+they will be skipped unless run with `--tag quarantine`. This can be used for
+tests that are expected to fail while a fix is in progress (similar to how
+[`skip` or `pending`](https://relishapp.com/rspec/rspec-core/v/3-8/docs/pending-and-skipped-examples)
+ can be used).
+
+```
+bin/qa Test::Instance::All http://localhost --tag quarantine
+```
+
+If `quarantine` is used with other tags, tests will only be run if they have at
+least one of the tags other than `quarantine`. This is different from how RSpec
+tags usually work, where all tags are inclusive.
+
+For example, suppose one test has `:smoke` and `:quarantine` metadata, and
+another test has `:ldap` and `:quarantine` metadata. If the tests are run with
+`--tag smoke --tag quarantine`, only the first test will run. The test with
+`:ldap` will not run even though it also has `:quarantine`.
diff --git a/qa/Rakefile b/qa/Rakefile
new file mode 100644
index 00000000000..b6ad09f9b00
--- /dev/null
+++ b/qa/Rakefile
@@ -0,0 +1,18 @@
+require_relative 'qa/tools/revoke_all_personal_access_tokens'
+require_relative 'qa/tools/delete_subgroups'
+require_relative 'qa/tools/generate_perf_testdata'
+
+desc "Revokes all personal access tokens"
+task :revoke_personal_access_tokens do
+ QA::Tools::RevokeAllPersonalAccessTokens.new.run
+end
+
+desc "Deletes subgroups within a provided group"
+task :delete_subgroups do
+ QA::Tools::DeleteSubgroups.new.run
+end
+
+desc "Generate Performance Testdata"
+task :generate_perf_testdata do
+ QA::Tools::GeneratePerfTestdata.new.run
+end
diff --git a/qa/qa.rb b/qa/qa.rb
index bf05b6b53ca..2b3ffabbbaa 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -62,6 +62,11 @@ module QA
autoload :Fork, 'qa/resource/fork'
autoload :SSHKey, 'qa/resource/ssh_key'
+ module Events
+ autoload :Base, 'qa/resource/events/base'
+ autoload :Project, 'qa/resource/events/project'
+ end
+
module Repository
autoload :Push, 'qa/resource/repository/push'
autoload :ProjectPush, 'qa/resource/repository/project_push'
@@ -99,6 +104,7 @@ module QA
autoload :LDAPNoTLS, 'qa/scenario/test/integration/ldap_no_tls'
autoload :LDAPTLS, 'qa/scenario/test/integration/ldap_tls'
autoload :InstanceSAML, 'qa/scenario/test/integration/instance_saml'
+ autoload :OAuth, 'qa/scenario/test/integration/oauth'
autoload :Kubernetes, 'qa/scenario/test/integration/kubernetes'
autoload :Mattermost, 'qa/scenario/test/integration/mattermost'
autoload :ObjectStorage, 'qa/scenario/test/integration/object_storage'
@@ -158,6 +164,10 @@ module QA
autoload :Activity, 'qa/page/project/activity'
autoload :Menu, 'qa/page/project/menu'
+ module Branches
+ autoload :Show, 'qa/page/project/branches/show'
+ end
+
module Commit
autoload :Show, 'qa/page/project/commit/show'
end
@@ -191,6 +201,15 @@ module QA
autoload :MirroringRepositories, 'qa/page/project/settings/mirroring_repositories'
end
+ module SubMenus
+ autoload :CiCd, 'qa/page/project/sub_menus/ci_cd'
+ autoload :Common, 'qa/page/project/sub_menus/common'
+ autoload :Issues, 'qa/page/project/sub_menus/issues'
+ autoload :Operations, 'qa/page/project/sub_menus/operations'
+ autoload :Repository, 'qa/page/project/sub_menus/repository'
+ autoload :Settings, 'qa/page/project/sub_menus/settings'
+ end
+
module Issue
autoload :New, 'qa/page/project/issue/new'
autoload :Show, 'qa/page/project/issue/show'
@@ -241,6 +260,10 @@ module QA
autoload :Sidebar, 'qa/page/issuable/sidebar'
end
+ module Alert
+ autoload :AutoDevopsAlert, 'qa/page/alert/auto_devops_alert'
+ end
+
module Layout
autoload :Banner, 'qa/page/layout/banner'
end
@@ -260,9 +283,11 @@ module QA
module Settings
autoload :Repository, 'qa/page/admin/settings/repository'
+ autoload :General, 'qa/page/admin/settings/general'
module Component
autoload :RepositoryStorage, 'qa/page/admin/settings/component/repository_storage'
+ autoload :AccountAndLimit, 'qa/page/admin/settings/component/account_and_limit'
end
end
end
@@ -277,12 +302,14 @@ module QA
#
module Component
autoload :ClonePanel, 'qa/page/component/clone_panel'
+ autoload :LazyLoader, 'qa/page/component/lazy_loader'
autoload :LegacyClonePanel, 'qa/page/component/legacy_clone_panel'
autoload :Dropzone, 'qa/page/component/dropzone'
autoload :GroupsFilter, 'qa/page/component/groups_filter'
autoload :Select2, 'qa/page/component/select2'
autoload :DropdownFilter, 'qa/page/component/dropdown_filter'
autoload :UsersSelect, 'qa/page/component/users_select'
+ autoload :Note, 'qa/page/component/note'
module Issuable
autoload :Common, 'qa/page/component/issuable/common'
@@ -327,6 +354,13 @@ module QA
autoload :Login, 'qa/vendor/saml_idp/page/login'
end
end
+
+ module Github
+ module Page
+ autoload :Base, 'qa/vendor/github/page/base'
+ autoload :Login, 'qa/vendor/github/page/login'
+ end
+ end
end
# Classes that provide support to other parts of the framework.
@@ -336,6 +370,8 @@ module QA
autoload :Logging, 'qa/support/page/logging'
end
autoload :Api, 'qa/support/api'
+ autoload :Waiter, 'qa/support/waiter'
+ autoload :Retrier, 'qa/support/retrier'
end
end
diff --git a/qa/qa/ce/strategy.rb b/qa/qa/ce/strategy.rb
index 6d1601dfa48..e0fbbed2567 100644
--- a/qa/qa/ce/strategy.rb
+++ b/qa/qa/ce/strategy.rb
@@ -8,7 +8,10 @@ module QA
end
def perform_before_hooks
- # noop
+ # 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::Browser.visit(:gitlab, QA::Page::Main::Login)
+ QA::Page::Main::Login.perform(&:assert_page_loaded)
end
end
end
diff --git a/qa/qa/fixtures/auto_devops_rack/config.ru b/qa/qa/fixtures/auto_devops_rack/config.ru
index bde8e15488a..e990662145a 100644
--- a/qa/qa/fixtures/auto_devops_rack/config.ru
+++ b/qa/qa/fixtures/auto_devops_rack/config.ru
@@ -1 +1 @@
-run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, StringIO.new("Hello World!\n")] }
+run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, StringIO.new("Hello World! #{ENV['OPTIONAL_MESSAGE']}\n")] }
diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb
index 7f959441dac..b3bad40a90f 100644
--- a/qa/qa/git/repository.rb
+++ b/qa/qa/git/repository.rb
@@ -5,20 +5,26 @@ require 'uri'
require 'open3'
require 'fileutils'
require 'tmpdir'
+require 'tempfile'
+require 'securerandom'
module QA
module Git
class Repository
include Scenario::Actable
+ RepositoryCommandError = Class.new(StandardError)
- attr_writer :password
+ attr_writer :use_lfs
attr_accessor :env_vars
+ InvalidCredentialsError = Class.new(RuntimeError)
+
def initialize
# We set HOME to the current working directory (which is a
# temporary directory created in .perform()) so the temporarily dropped
# .netrc can be utilised
- self.env_vars = [%Q{HOME="#{File.dirname(netrc_file_path)}"}]
+ self.env_vars = [%Q{HOME="#{tmp_home_dir}"}]
+ @use_lfs = false
end
def self.perform(*args)
@@ -27,31 +33,41 @@ module QA
end
end
+ def password=(password)
+ @password = password
+
+ raise InvalidCredentialsError, "Please provide a username when setting a password" unless username
+
+ try_add_credentials_to_netrc
+ end
+
def uri=(address)
@uri = URI(address)
end
def username=(username)
@username = username
- @uri.user = username
+ # Only include the user in the URI if we're using HTTP as this breaks
+ # SSH authentication.
+ @uri.user = username unless ssh_key_set?
end
def use_default_credentials
self.username, self.password = default_credentials
-
- add_credentials_to_netrc unless ssh_key_set?
end
def clone(opts = '')
- run("git clone #{opts} #{uri} ./")
- end
+ clone_result = run("git clone #{opts} #{uri} ./")
+ return clone_result.response unless clone_result.success
- def checkout(branch_name)
- run(%Q{git checkout "#{branch_name}"})
+ enable_lfs_result = enable_lfs if use_lfs?
+
+ clone_result.to_s + enable_lfs_result.to_s
end
- def checkout_new_branch(branch_name)
- run(%Q{git checkout -b "#{branch_name}"})
+ def checkout(branch_name, new_branch: false)
+ opts = new_branch ? '-b' : ''
+ run(%Q{git checkout #{opts} "#{branch_name}"}).to_s
end
def shallow_clone
@@ -61,8 +77,6 @@ module QA
def configure_identity(name, email)
run(%Q{git config user.name #{name}})
run(%Q{git config user.email #{email}})
-
- add_credentials_to_netrc
end
def commit_file(name, contents, message)
@@ -73,19 +87,30 @@ module QA
def add_file(name, contents)
::File.write(name, contents)
- run(%Q{git add #{name}})
+ if use_lfs?
+ git_lfs_track_result = run(%Q{git lfs track #{name} --lockable})
+ return git_lfs_track_result.response unless git_lfs_track_result.success
+ end
+
+ git_add_result = run(%Q{git add #{name}})
+
+ git_lfs_track_result.to_s + git_add_result.to_s
end
def commit(message)
- run(%Q{git commit -m "#{message}"})
+ run(%Q{git commit -m "#{message}"}).to_s
end
def push_changes(branch = 'master')
- run("git push #{uri} #{branch}")
+ run("git push #{uri} #{branch}").to_s
+ end
+
+ def merge(branch)
+ run("git merge #{branch}")
end
def commits
- run('git log --oneline').split("\n")
+ run('git log --oneline').to_s.split("\n")
end
def use_ssh_key(key)
@@ -97,7 +122,8 @@ module QA
keyscan_params = ['-H']
keyscan_params << "-p #{uri.port}" if uri.port
keyscan_params << uri.host
- run("ssh-keyscan #{keyscan_params.join(' ')} >> #{known_hosts_file.path}")
+ res = run("ssh-keyscan #{keyscan_params.join(' ')} >> #{known_hosts_file.path}")
+ return res.response unless res.success?
self.env_vars << %Q{GIT_SSH_COMMAND="ssh -i #{private_key_file.path} -o UserKnownHostsFile=#{known_hosts_file.path}"}
end
@@ -131,23 +157,60 @@ module QA
output[/git< version (\d+)/, 1] || 'unknown'
end
+ def try_add_credentials_to_netrc
+ return unless add_credentials?
+ return if netrc_already_contains_content?
+
+ save_netrc_content
+ end
+
private
- attr_reader :uri, :username, :password, :known_hosts_file, :private_key_file
+ attr_reader :uri, :username, :password, :known_hosts_file,
+ :private_key_file, :use_lfs
+
+ alias_method :use_lfs?, :use_lfs
+
+ Result = Struct.new(:success, :response) do
+ alias_method :success?, :success
+ alias_method :to_s, :response
+ end
+
+ def add_credentials?
+ return false if !username || !password
+ return true unless ssh_key_set?
+
+ false
+ end
def ssh_key_set?
!private_key_file.nil?
end
+ def enable_lfs
+ # git lfs install *needs* a .gitconfig defined at ${HOME}/.gitconfig
+ FileUtils.mkdir_p(tmp_home_dir)
+ touch_gitconfig_result = run("touch #{tmp_home_dir}/.gitconfig")
+ return touch_gitconfig_result.response unless touch_gitconfig_result.success?
+
+ git_lfs_install_result = run('git lfs install')
+
+ touch_gitconfig_result.to_s + git_lfs_install_result.to_s
+ end
+
def run(command_str, *extra_env)
command = [env_vars, *extra_env, command_str, '2>&1'].compact.join(' ')
- Runtime::Logger.debug "Git: command=[#{command}]"
+ Runtime::Logger.debug "Git: pwd=[#{Dir.pwd}], command=[#{command}]"
+
+ output, status = Open3.capture2e(command)
+ output.chomp!
+ Runtime::Logger.debug "Git: output=[#{output}], exitstatus=[#{status.exitstatus}]"
- output, _ = Open3.capture2(command)
- output = output.chomp.gsub(/\s+$/, '')
- Runtime::Logger.debug "Git: output=[#{output}]"
+ unless status.success?
+ raise RepositoryCommandError, "The command #{command} failed (#{status.exitstatus}) with the following output:\n#{output}"
+ end
- output
+ Result.new(status.exitstatus == 0, output)
end
def default_credentials
@@ -158,24 +221,11 @@ module QA
end
end
- def tmp_netrc_directory
- @tmp_netrc_directory ||= File.join(Dir.tmpdir, "qa-netrc-credentials", $$.to_s)
- end
-
- def netrc_file_path
- @netrc_file_path ||= File.join(tmp_netrc_directory, '.netrc')
- end
-
- def netrc_content
- "machine #{uri.host} login #{username} password #{password}"
+ def read_netrc_content
+ File.exist?(netrc_file_path) ? File.readlines(netrc_file_path) : []
end
- def netrc_already_contains_content?
- File.exist?(netrc_file_path) &&
- File.readlines(netrc_file_path).grep(/^#{netrc_content}$/).any?
- end
-
- def add_credentials_to_netrc
+ def save_netrc_content
# Despite libcurl supporting a custom .netrc location through the
# CURLOPT_NETRC_FILE environment variable, git does not support it :(
# Info: https://curl.haxx.se/libcurl/c/CURLOPT_NETRC_FILE.html
@@ -183,12 +233,26 @@ module QA
# This will create a .netrc in the correct working directory, which is
# a temporary directory created in .perform()
#
- return if netrc_already_contains_content?
-
- FileUtils.mkdir_p(tmp_netrc_directory)
+ FileUtils.mkdir_p(tmp_home_dir)
File.open(netrc_file_path, 'a') { |file| file.puts(netrc_content) }
File.chmod(0600, netrc_file_path)
end
+
+ def tmp_home_dir
+ @tmp_home_dir ||= File.join(Dir.tmpdir, "qa-netrc-credentials", $$.to_s)
+ end
+
+ def netrc_file_path
+ @netrc_file_path ||= File.join(tmp_home_dir, '.netrc')
+ end
+
+ def netrc_content
+ "machine #{uri.host} login #{username} password #{password}"
+ end
+
+ def netrc_already_contains_content?
+ read_netrc_content.grep(/^#{netrc_content}$/).any?
+ end
end
end
end
diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb
index e8c7d274966..25564f2dc6e 100644
--- a/qa/qa/page/admin/menu.rb
+++ b/qa/qa/page/admin/menu.rb
@@ -9,6 +9,7 @@ module QA
element :admin_sidebar_submenu
element :admin_settings_item
element :admin_settings_repository_item
+ element :admin_settings_general_item
end
def go_to_repository_settings
@@ -19,6 +20,14 @@ module QA
end
end
+ def go_to_general_settings
+ hover_settings do
+ within_submenu do
+ click_element :admin_settings_general_item
+ end
+ end
+ end
+
private
def hover_settings
diff --git a/qa/qa/page/admin/settings/component/account_and_limit.rb b/qa/qa/page/admin/settings/component/account_and_limit.rb
new file mode 100644
index 00000000000..a61c8cc77cd
--- /dev/null
+++ b/qa/qa/page/admin/settings/component/account_and_limit.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Settings
+ module Component
+ class AccountAndLimit < Page::Base
+ view 'app/views/admin/application_settings/_account_and_limit.html.haml' do
+ element :receive_max_input_size_field
+ element :save_changes_button
+ end
+
+ def set_max_file_size(size)
+ fill_element :receive_max_input_size_field, size
+ end
+
+ def save_settings
+ click_element :save_changes_button
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/settings/general.rb b/qa/qa/page/admin/settings/general.rb
new file mode 100644
index 00000000000..93b290f7e03
--- /dev/null
+++ b/qa/qa/page/admin/settings/general.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Settings
+ class General < Page::Base
+ include QA::Page::Settings::Common
+
+ view 'app/views/admin/application_settings/show.html.haml' do
+ element :account_and_limit_settings
+ end
+
+ def expand_account_and_limit(&block)
+ expand_section(:account_and_limit_settings) do
+ Component::AccountAndLimit.perform(&block)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/alert/auto_devops_alert.rb b/qa/qa/page/alert/auto_devops_alert.rb
new file mode 100644
index 00000000000..8f66c805b77
--- /dev/null
+++ b/qa/qa/page/alert/auto_devops_alert.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Alert
+ class AutoDevopsAlert < Page::Base
+ view 'app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml' do
+ element :auto_devops_banner
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 5788dceaaae..9fabf83e2ce 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -18,22 +18,13 @@ module QA
page.refresh
end
- def wait(max: 60, time: 0.1, reload: true)
- start = Time.now
-
- while Time.now - start < max
- result = yield
- return result if result
-
- sleep(time)
-
- refresh if reload
+ def wait(max: 60, interval: 0.1, reload: true)
+ QA::Support::Waiter.wait(max: max, interval: interval) do
+ yield || (reload && refresh && false)
end
-
- false
end
- def with_retry(max_attempts: 3, reload: false)
+ def retry_until(max_attempts: 3, reload: false)
attempts = 0
while attempts < max_attempts
@@ -48,6 +39,12 @@ module QA
false
end
+ def retry_on_exception(max_attempts: 3, reload: false, sleep_interval: 0.5)
+ QA::Support::Retrier.retry_on_exception(max_attempts: max_attempts, reload_page: (reload && self), sleep_interval: sleep_interval) do
+ yield
+ end
+ end
+
def scroll_to(selector, text: nil)
page.execute_script <<~JS
var elements = Array.from(document.querySelectorAll('#{selector}'));
@@ -73,15 +70,15 @@ module QA
xhr.send();
JS
- return false unless wait(time: 0.5, max: 60, reload: false) do
+ return false unless wait(interval: 0.5, max: 60, reload: false) do
page.evaluate_script('xhr.readyState == XMLHttpRequest.DONE')
end
page.evaluate_script('xhr.status') == 200
end
- def find_element(name, text_filter = nil, wait: Capybara.default_max_wait_time)
- find(element_selector_css(name), wait: wait, text: text_filter)
+ def find_element(name, text: nil, wait: Capybara.default_max_wait_time)
+ find(element_selector_css(name), wait: wait, text: text)
end
def all_elements(name)
@@ -92,6 +89,10 @@ module QA
find_element(name).set(true)
end
+ def uncheck_element(name)
+ find_element(name).set(false)
+ end
+
def click_element(name)
find_element(name).click
end
@@ -108,14 +109,26 @@ module QA
element.select value.to_s.capitalize
end
- def has_element?(name, wait: Capybara.default_max_wait_time)
- has_css?(element_selector_css(name), wait: wait)
+ def has_element?(name, text: nil, wait: Capybara.default_max_wait_time)
+ has_css?(element_selector_css(name), wait: wait, text: text)
+ end
+
+ def has_no_element?(name, wait: Capybara.default_max_wait_time)
+ has_no_css?(element_selector_css(name), wait: wait)
+ end
+
+ def has_text?(text)
+ page.has_text? text
end
def has_no_text?(text)
page.has_no_text? text
end
+ def finished_loading?
+ has_no_css?('.fa-spinner', wait: Capybara.default_max_wait_time)
+ end
+
def within_element(name)
page.within(element_selector_css(name)) do
yield
@@ -140,6 +153,14 @@ module QA
click_link text
end
+ def click_body
+ find('body').click
+ end
+
+ def visit_link_in_element(name)
+ visit find_element(name)['href']
+ end
+
def self.path
raise NotImplementedError
end
diff --git a/qa/qa/page/component/clone_panel.rb b/qa/qa/page/component/clone_panel.rb
index d37b63c716a..b80877f5ecd 100644
--- a/qa/qa/page/component/clone_panel.rb
+++ b/qa/qa/page/component/clone_panel.rb
@@ -21,11 +21,6 @@ module QA
repository_clone_location(:ssh_clone_url)
end
- def wait_for_push
- sleep 5
- refresh
- end
-
private
def repository_clone_location(kind)
diff --git a/qa/qa/page/component/lazy_loader.rb b/qa/qa/page/component/lazy_loader.rb
new file mode 100644
index 00000000000..6f74a4691ba
--- /dev/null
+++ b/qa/qa/page/component/lazy_loader.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module LazyLoader
+ def self.included(base)
+ base.view 'app/assets/javascripts/lazy_loader.js' do
+ element :js_lazy_loaded
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/legacy_clone_panel.rb b/qa/qa/page/component/legacy_clone_panel.rb
index 99132190f3f..e495cf4ef04 100644
--- a/qa/qa/page/component/legacy_clone_panel.rb
+++ b/qa/qa/page/component/legacy_clone_panel.rb
@@ -27,11 +27,6 @@ module QA
Git::Location.new(find('#project_clone').value)
end
- def wait_for_push
- sleep 5
- refresh
- end
-
private
def choose_repository_clone(kind, detect_text)
diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb
new file mode 100644
index 00000000000..f5add6bc9b5
--- /dev/null
+++ b/qa/qa/page/component/note.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module Note
+ def self.included(base)
+ base.view 'app/assets/javascripts/notes/components/comment_form.vue' do
+ element :note_dropdown
+ element :discussion_option
+ end
+
+ base.view 'app/assets/javascripts/notes/components/note_form.vue' do
+ element :reply_input
+ element :reply_comment_button
+ end
+
+ base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
+ element :discussion_reply
+ end
+
+ base.view 'app/assets/javascripts/notes/components/toggle_replies_widget.vue' do
+ element :expand_replies
+ element :collapse_replies
+ end
+ end
+
+ def start_discussion(text)
+ fill_element :comment_input, text
+ click_element :note_dropdown
+ click_element :discussion_option
+ click_element :comment_button
+ end
+
+ def type_reply_to_discussion(reply_text)
+ all_elements(:discussion_reply).last.click
+ fill_element :reply_input, reply_text
+ end
+
+ def reply_to_discussion(reply_text)
+ type_reply_to_discussion(reply_text)
+ click_element :reply_comment_button
+ end
+
+ def collapse_replies
+ click_element :collapse_replies
+ end
+
+ def expand_replies
+ click_element :expand_replies
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/select2.rb b/qa/qa/page/component/select2.rb
index 6d07d5a10e6..98bcb96b92c 100644
--- a/qa/qa/page/component/select2.rb
+++ b/qa/qa/page/component/select2.rb
@@ -6,6 +6,12 @@ module QA
find('.select2-result-label', text: item_text).click
end
+ def clear_current_selection_if_present
+ if has_css?('a > abbr.select2-search-choice-close', wait: 1.0)
+ find('a > abbr.select2-search-choice-close').click
+ end
+ end
+
def search_and_select(item_text)
find('.select2-input').set(item_text)
select_item(item_text)
diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb
index 0f0ab81a4ef..41716326685 100644
--- a/qa/qa/page/group/show.rb
+++ b/qa/qa/page/group/show.rb
@@ -6,7 +6,7 @@ module QA
class Show < Page::Base
include Page::Component::GroupsFilter
- view 'app/views/groups/show.html.haml' do
+ view 'app/views/groups/_home_panel.html.haml' do
element :new_project_or_subgroup_dropdown
element :new_project_or_subgroup_dropdown_toggle
element :new_project_option
@@ -45,15 +45,17 @@ module QA
private
def select_kind(kind)
- within_element(:new_project_or_subgroup_dropdown) do
- # May need to click again because it is possible to click the button quicker than the JS is bound
- wait(reload: false) do
- click_element :new_project_or_subgroup_dropdown_toggle
+ QA::Support::Retrier.retry_on_exception(sleep_interval: 1.0) do
+ within_element(:new_project_or_subgroup_dropdown) do
+ # May need to click again because it is possible to click the button quicker than the JS is bound
+ wait(reload: false) do
+ click_element :new_project_or_subgroup_dropdown_toggle
- has_element?(kind)
- end
+ has_element?(kind)
+ end
- click_element kind
+ click_element kind
+ end
end
end
end
diff --git a/qa/qa/page/label/index.rb b/qa/qa/page/label/index.rb
index 323acd57743..de0cfa9f293 100644
--- a/qa/qa/page/label/index.rb
+++ b/qa/qa/page/label/index.rb
@@ -1,12 +1,31 @@
+# frozen_string_literal: true
+
module QA
module Page
module Label
class Index < Page::Base
- view 'app/views/projects/labels/index.html.haml' do
+ include Component::LazyLoader
+
+ view 'app/views/shared/labels/_nav.html.haml' do
element :label_create_new
end
+ view 'app/views/shared/empty_states/_labels.html.haml' do
+ element :label_svg
+ end
+
+ view 'app/views/shared/empty_states/_priority_labels.html.haml' do
+ element :label_svg
+ end
+
def go_to_new_label
+ # 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
+ has_element?(:js_lazy_loaded)
+ end
+
click_element :label_create_new
end
end
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index cb83ace20b6..e03fe9ab83a 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -31,25 +31,24 @@ module QA
element :register_tab
end
- view 'app/views/devise/shared/_omniauth_box.html.haml' do
+ view 'app/helpers/auth_helper.rb' do
element :saml_login_button
+ element :github_login_button
end
view 'app/views/layouts/devise.html.haml' do
element :login_page
end
- def initialize
- # The login page is usually the entry point for all the scenarios so
- # we need to wait for the instance to start. That said, in some cases
- # we are already logged-in so we check both cases here.
- # Check if we're already logged in first. If we don't then we have to
- # wait 10 seconds for the check for the login page to fail every time
- # we use this class when we're already logged in (E.g., whenever we
- # create a personal access token to use for API access).
- wait(max: 500) do
- Page::Main::Menu.act { has_personal_area?(wait: 0) } ||
- has_element?(:login_page)
+ def assert_page_loaded
+ unless page_loaded?
+ raise QA::Runtime::Browser::NotRespondingError, "Login page did not load at #{QA::Page::Main::Login.perform(&:current_url)}"
+ end
+ end
+
+ def page_loaded?
+ wait(max: 60) do
+ has_element?(:login_page)
end
end
@@ -132,6 +131,16 @@ module QA
click_element :standard_tab
end
+ def sign_in_with_github
+ set_initial_password_if_present
+ click_element :github_login_button
+ end
+
+ def sign_in_with_saml
+ set_initial_password_if_present
+ click_element :saml_login_button
+ end
+
private
def sign_in_using_ldap_credentials
@@ -142,11 +151,6 @@ module QA
click_element :sign_in_button
end
- def sign_in_with_saml
- set_initial_password_if_present
- click_element :saml_login_button
- end
-
def sign_in_using_gitlab_credentials(user)
switch_to_sign_in_tab if has_sign_in_tab?
switch_to_standard_tab if has_standard_tab?
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index 6804cc8fb20..55500e831c6 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -57,8 +57,12 @@ module QA
end
def go_to_profile_settings
- within_user_menu do
- click_link 'Settings'
+ retry_until(reload: false) do
+ within_user_menu do
+ click_link 'Settings'
+ end
+
+ has_text?('User Settings')
end
end
diff --git a/qa/qa/page/main/sign_up.rb b/qa/qa/page/main/sign_up.rb
index 9ca498012eb..46a105003d0 100644
--- a/qa/qa/page/main/sign_up.rb
+++ b/qa/qa/page/main/sign_up.rb
@@ -23,7 +23,7 @@ module QA
check_element :new_user_accept_terms if has_element?(:new_user_accept_terms)
- signed_in = with_retry do
+ signed_in = retry_until do
click_element :new_user_register_button
Page::Main::Menu.act { has_personal_area? }
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 869dc0b9d21..c0411db6505 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -4,6 +4,8 @@ module QA
module Page
module MergeRequest
class Show < Page::Base
+ include Page::Component::Note
+
view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do
element :merge_button
element :fast_forward_message, 'Fast-forward merge without a merge commit' # rubocop:disable QA/ElementWithPattern
@@ -25,6 +27,12 @@ module QA
element :squash_checkbox
end
+ view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue' do
+ element :dropdown_toggle
+ element :download_email_patches
+ element :download_plain_diff
+ end
+
view 'app/views/projects/merge_requests/show.html.haml' do
element :notes_tab
element :diffs_tab
@@ -34,19 +42,6 @@ module QA
element :diff_comment
end
- view 'app/assets/javascripts/notes/components/comment_form.vue' do
- element :note_dropdown
- element :discussion_option
- end
-
- view 'app/assets/javascripts/notes/components/note_form.vue' do
- element :reply_input
- end
-
- view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
- element :discussion_reply
- end
-
view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do
element :new_diff_line
end
@@ -61,17 +56,17 @@ module QA
end
def fast_forward_possible?
- !has_text?('Fast-forward merge is not possible')
+ has_no_text?('Fast-forward merge is not possible')
end
def has_merge_button?
refresh
- has_css?(element_selector_css(:merge_button))
+ has_element?(:merge_button)
end
def has_merge_options?
- has_css?(element_selector_css(:merge_moment_dropdown))
+ has_element?(:merge_moment_dropdown)
end
def merge_immediately
@@ -86,19 +81,21 @@ module QA
def rebase!
# The rebase button is disabled on load
wait do
- has_css?(element_selector_css(:mr_rebase_button))
+ has_element?(:mr_rebase_button)
end
# The rebase button is enabled via JS
wait(reload: false) do
- !first(element_selector_css(:mr_rebase_button)).disabled?
+ !find_element(:mr_rebase_button).disabled?
end
click_element :mr_rebase_button
- wait(reload: false) do
+ success = wait do
has_text?('Fast-forward merge without a merge commit')
end
+
+ raise "Rebase did not appear to be successful" unless success
end
def has_assignee?(username)
@@ -117,30 +114,32 @@ module QA
def merge!
# The merge button is disabled on load
wait do
- has_css?(element_selector_css(:merge_button))
+ has_element?(:merge_button)
end
# The merge button is enabled via JS
wait(reload: false) do
- !first(element_selector_css(:merge_button)).disabled?
+ !find_element(:merge_button).disabled?
end
merge_immediately
- wait(reload: false) do
+ success = wait do
has_text?('The changes were merged into')
end
+
+ raise "Merge did not appear to be successful" unless success
end
def mark_to_squash
# The squash checkbox is disabled on load
wait do
- has_css?(element_selector_css(:squash_checkbox))
+ has_element?(:squash_checkbox)
end
# The squash checkbox is enabled via JS
wait(reload: false) do
- !first(element_selector_css(:squash_checkbox)).disabled?
+ !find_element(:squash_checkbox).disabled?
end
click_element :squash_checkbox
@@ -155,28 +154,26 @@ module QA
end
def add_comment_to_diff(text)
- wait(time: 5) do
- page.has_text?("No newline at end of file")
+ wait(interval: 5) do
+ has_text?("No newline at end of file")
end
all_elements(:new_diff_line).first.hover
click_element :diff_comment
fill_element :reply_input, text
end
- def start_discussion(text)
- fill_element :comment_input, text
- click_element :note_dropdown
- click_element :discussion_option
- click_element :comment_button
+ def edit!
+ click_element :edit_button
end
- def reply_to_discussion(reply_text)
- all_elements(:discussion_reply).last.click
- fill_element :reply_input, reply_text
+ def view_email_patches
+ click_element :dropdown_toggle
+ visit_link_in_element(:download_email_patches)
end
- def edit!
- click_element :edit_button
+ def view_plain_diff
+ click_element :dropdown_toggle
+ visit_link_in_element(:download_plain_diff)
end
end
end
diff --git a/qa/qa/page/profile/personal_access_tokens.rb b/qa/qa/page/profile/personal_access_tokens.rb
index 9191dbe9cf3..8c12eff5cf1 100644
--- a/qa/qa/page/profile/personal_access_tokens.rb
+++ b/qa/qa/page/profile/personal_access_tokens.rb
@@ -3,29 +3,51 @@ module QA
module Profile
class PersonalAccessTokens < Page::Base
view 'app/views/shared/_personal_access_tokens_form.html.haml' do
- element :personal_access_token_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern
- element :create_token_button, 'submit "Create #{type} token"' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
- element :scopes_api_radios, "label :scopes" # rubocop:disable QA/ElementWithPattern
+ element :personal_access_token_name_field
+ element :create_token_button
+ end
+
+ view 'app/views/shared/tokens/_scopes_form.html.haml' do
+ element :api_radio, 'qa-#{scope}-radio' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
end
view 'app/views/shared/_personal_access_tokens_created_container.html.haml' do
- element :create_token_field, "text_field_tag 'created-personal-access-token'" # rubocop:disable QA/ElementWithPattern
+ element :created_personal_access_token
+ end
+ view 'app/views/shared/_personal_access_tokens_table.html.haml' do
+ element :revoke_button
end
def fill_token_name(name)
- fill_in 'personal_access_token_name', with: name
+ fill_element(:personal_access_token_name_field, name)
end
def check_api
- check 'personal_access_token_scopes_api'
+ check_element(:api_radio)
end
def create_token
- click_on 'Create personal access token'
+ click_element(:create_token_button)
end
def created_access_token
- page.find('#created-personal-access-token').value
+ find_element(:created_personal_access_token, wait: 30).value
+ end
+
+ def has_token_row_for_name?(token_name)
+ page.has_css?('tr', text: token_name, wait: 1.0)
+ end
+
+ def first_token_row_for_name(token_name)
+ page.find('tr', text: token_name, match: :first, wait: 1.0)
+ end
+
+ def revoke_first_token_with_name(token_name)
+ within first_token_row_for_name(token_name) do
+ accept_confirm do
+ click_element(:revoke_button)
+ end
+ end
end
end
end
diff --git a/qa/qa/page/project/branches/show.rb b/qa/qa/page/project/branches/show.rb
new file mode 100644
index 00000000000..922a6ddb086
--- /dev/null
+++ b/qa/qa/page/project/branches/show.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Branches
+ class Show < Page::Base
+ view 'app/views/projects/branches/_branch.html.haml' do
+ element :remove_btn
+ end
+ view 'app/views/projects/branches/_panel.html.haml' do
+ element :all_branches
+ end
+ view 'app/views/projects/branches/index.html.haml' do
+ element :delete_merged_branches
+ end
+
+ def delete_branch(branch_name)
+ within_element(:all_branches) do
+ within(".js-branch-#{branch_name}") do
+ accept_alert do
+ click_element(:remove_btn)
+ end
+ end
+ end
+
+ finished_loading?
+ end
+
+ def has_branch_title?(branch_title)
+ within_element(:all_branches) do
+ within(".item-title") do
+ has_text?(branch_title)
+ end
+ end
+ end
+
+ def has_branch_with_badge?(branch_name, badge)
+ within_element(:all_branches) do
+ within(".js-branch-#{branch_name} .badge") do
+ has_text?(badge)
+ end
+ end
+ end
+
+ def delete_merged_branches
+ accept_alert do
+ click_element(:delete_merged_branches)
+ end
+ end
+
+ def wait_for_texts_not_to_be_visible(texts)
+ text_not_visible = wait do
+ texts.all? do |text|
+ has_no_text?(text)
+ end
+ end
+ raise "Expected text(s) #{texts} not to be visible" unless text_not_visible
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb
index a3cde73d3f2..45c8d834a74 100644
--- a/qa/qa/page/project/import/github.rb
+++ b/qa/qa/page/project/import/github.rb
@@ -10,12 +10,11 @@ module QA
element :list_repos_button, "submit_tag _('List your GitHub repositories')" # rubocop:disable QA/ElementWithPattern
end
- view 'app/views/import/_githubish_status.html.haml' do
- element :project_import_row, 'data: { qa: { repo_path: repo.full_name } }' # rubocop:disable QA/ElementWithPattern
+ view 'app/assets/javascripts/import_projects/components/provider_repo_table_row.vue' do
+ element :project_import_row
element :project_namespace_select
- element :project_namespace_field, 'select_tag :namespace_id' # rubocop:disable QA/ElementWithPattern
- element :project_path_field, 'text_field_tag :path, sanitize_project_name(repo.name)' # rubocop:disable QA/ElementWithPattern
- element :import_button, "_('Import')" # rubocop:disable QA/ElementWithPattern
+ element :project_path_field
+ element :import_button
end
def add_personal_access_token(personal_access_token)
@@ -30,12 +29,19 @@ module QA
choose_test_namespace(full_path)
set_path(full_path, name)
import_project(full_path)
+ wait_for_success
end
private
def within_repo_path(full_path)
- page.within(%Q(tr[data-qa-repo-path="#{full_path}"])) do
+ wait(reload: false) do
+ has_element?(:project_import_row, text: full_path)
+ end
+
+ project_import_row = find_element(:project_import_row, text: full_path)
+
+ within(project_import_row) do
yield
end
end
@@ -45,18 +51,24 @@ module QA
click_element :project_namespace_select
end
- select_item(Runtime::Namespace.path)
+ search_and_select(Runtime::Namespace.path)
end
def set_path(full_path, name)
within_repo_path(full_path) do
- fill_in 'path', with: name
+ fill_element(:project_path_field, name)
end
end
def import_project(full_path)
within_repo_path(full_path) do
- click_button 'Import'
+ click_element(:import_button)
+ end
+ end
+
+ def wait_for_success
+ wait(max: 60, interval: 1.0, reload: false) do
+ page.has_content?('Done', wait: 1.0)
end
end
end
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 9ec6d90719e..9df3db1bba0 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -6,6 +6,7 @@ module QA
module Issue
class Show < Page::Base
include Page::Component::Issuable::Common
+ include Page::Component::Note
view 'app/views/shared/notes/_form.html.haml' do
element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern
@@ -22,6 +23,10 @@ module QA
element :filter_options
end
+ view 'app/assets/javascripts/notes/components/noteable_note.vue' do
+ element :noteable_note_item
+ end
+
# Adds a comment to an issue
# attachment option should be an absolute path
def comment(text, attachment: nil)
@@ -35,19 +40,32 @@ module QA
click_element :comment_button
end
+ def has_comment?(comment_text)
+ wait(reload: false) do
+ has_element?(:noteable_note_item, text: comment_text)
+ end
+ end
+
def select_comments_only_filter
- click_element :discussion_filter
- find_element(:filter_options, "Show comments only").click
+ select_filter_with_text('Show comments only')
end
def select_history_only_filter
- click_element :discussion_filter
- find_element(:filter_options, "Show history only").click
+ select_filter_with_text('Show history only')
end
def select_all_activities_filter
- click_element :discussion_filter
- find_element(:filter_options, "Show all activity").click
+ select_filter_with_text('Show all activity')
+ end
+
+ private
+
+ def select_filter_with_text(text)
+ retry_on_exception do
+ click_body
+ click_element :discussion_filter
+ find_element(:filter_options, text: text).click
+ end
end
end
end
diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb
index d688f15914c..9c218f4ed8b 100644
--- a/qa/qa/page/project/job/show.rb
+++ b/qa/qa/page/project/job/show.rb
@@ -4,10 +4,6 @@ module QA::Page
COMPLETED_STATUSES = %w[passed failed canceled blocked skipped manual].freeze # excludes created, pending, running
PASSED_STATUS = 'passed'.freeze
- view 'app/assets/javascripts/jobs/components/job_app.vue' do
- element :loading_animation
- end
-
view 'app/assets/javascripts/jobs/components/job_log.vue' do
element :build_trace
end
@@ -16,16 +12,15 @@ module QA::Page
element :status_badge
end
- def completed?
- COMPLETED_STATUSES.include?(status_badge)
+ view 'app/assets/javascripts/jobs/components/stages_dropdown.vue' do
+ element :pipeline_path
end
- def passed?
- status_badge == PASSED_STATUS
- end
+ def successful?(timeout: 60)
+ raise "Timed out waiting for the build trace to load" unless loaded?
+ raise "Timed out waiting for the status to be a valid completed state" unless completed?(timeout: timeout)
- def trace_loading?
- has_element?(:loading_animation)
+ status_badge == PASSED_STATUS
end
# Reminder: You may wish to wait for a particular job status before checking output
@@ -35,6 +30,16 @@ module QA::Page
private
+ def loaded?(wait: 60)
+ has_element?(:build_trace, wait: wait)
+ end
+
+ def completed?(timeout: 60)
+ wait(reload: false, max: timeout) do
+ COMPLETED_STATUSES.include?(status_badge)
+ end
+ end
+
def status_badge
find_element(:status_badge).text
end
diff --git a/qa/qa/page/project/menu.rb b/qa/qa/page/project/menu.rb
index 835e1ed00b5..46dfe87fe25 100644
--- a/qa/qa/page/project/menu.rb
+++ b/qa/qa/page/project/menu.rb
@@ -4,162 +4,35 @@ module QA
module Page
module Project
class Menu < Page::Base
- view 'app/views/layouts/nav/sidebar/_project.html.haml' do
- element :settings_item
- element :settings_link, 'link_to edit_project_path' # rubocop:disable QA/ElementWithPattern
- element :repository_link, "title: _('Repository')" # rubocop:disable QA/ElementWithPattern
- element :link_pipelines
- element :link_members_settings
- element :pipelines_settings_link, "title: _('CI / CD')" # rubocop:disable QA/ElementWithPattern
- element :operations_kubernetes_link, "title: _('Kubernetes')" # rubocop:disable QA/ElementWithPattern
- element :operations_environments_link
- element :issues_link, /link_to.*shortcuts-issues/ # rubocop:disable QA/ElementWithPattern
- element :issues_link_text, "Issues" # rubocop:disable QA/ElementWithPattern
- element :merge_requests_link, /link_to.*shortcuts-merge_requests/ # rubocop:disable QA/ElementWithPattern
- element :merge_requests_link_text, "Merge Requests" # rubocop:disable QA/ElementWithPattern
- element :top_level_items, '.sidebar-top-level-items' # rubocop:disable QA/ElementWithPattern
- element :operations_section, "class: 'shortcuts-operations'" # rubocop:disable QA/ElementWithPattern
- element :activity_link, "title: _('Activity')" # rubocop:disable QA/ElementWithPattern
- element :wiki_link_text, "Wiki" # rubocop:disable QA/ElementWithPattern
- element :milestones_link
- element :labels_link
- end
-
- view 'app/assets/javascripts/fly_out_nav.js' do
- element :fly_out, "classList.add('fly-out-list')" # rubocop:disable QA/ElementWithPattern
- end
-
- def click_ci_cd_pipelines
- within_sidebar do
- click_element :link_pipelines
- end
- end
+ include SubMenus::Common
- def click_ci_cd_settings
- hover_settings do
- within_submenu do
- click_link('CI / CD')
- end
- end
- end
-
- def click_issues
- within_sidebar do
- click_link('Issues')
- end
- end
+ include SubMenus::CiCd
+ include SubMenus::Issues
+ include SubMenus::Operations
+ include SubMenus::Repository
+ include SubMenus::Settings
- def click_members_settings
- hover_settings do
- within_submenu do
- click_element :link_members_settings
- end
- end
+ view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ element :activity_link
+ element :merge_requests_link
+ element :wiki_link
end
def click_merge_requests
within_sidebar do
- click_link('Merge Requests')
- end
- end
-
- def click_operations_environments
- hover_operations do
- within_submenu do
- click_element(:operations_environments_link)
- end
- end
- end
-
- def click_operations_kubernetes
- hover_operations do
- within_submenu do
- click_link('Kubernetes')
- end
- end
- end
-
- def click_milestones
- within_sidebar do
- click_element :milestones_link
- end
- end
-
- def click_repository
- within_sidebar do
- click_link('Repository')
- end
- end
-
- def click_repository_settings
- hover_settings do
- within_submenu do
- click_link('Repository')
- end
+ click_element(:merge_requests_link)
end
end
def click_wiki
within_sidebar do
- click_link('Wiki')
+ click_element(:wiki_link)
end
end
def go_to_activity
within_sidebar do
- click_on 'Activity'
- end
- end
-
- def go_to_labels
- hover_issues do
- within_submenu do
- click_element(:labels_link)
- end
- end
- end
-
- def go_to_settings
- within_sidebar do
- click_on 'Settings'
- end
- end
-
- private
-
- def hover_issues
- within_sidebar do
- find_element(:issues_item).hover
-
- yield
- end
- end
-
- def hover_operations
- within_sidebar do
- find('.shortcuts-operations').hover
-
- yield
- end
- end
-
- def hover_settings
- within_sidebar do
- find('.qa-settings-item').hover
-
- yield
- end
- end
-
- def within_sidebar
- page.within('.sidebar-top-level-items') do
- yield
- end
- end
-
- def within_submenu
- page.within('.fly-out-list') do
- yield
+ click_element(:activity_link)
end
end
end
diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb
index 6acc413b586..eabeae1acc4 100644
--- a/qa/qa/page/project/new.rb
+++ b/qa/qa/page/project/new.rb
@@ -5,6 +5,7 @@ module QA
include Page::Component::Select2
view 'app/views/projects/new.html.haml' do
+ element :project_create_from_template_tab
element :import_project_tab, "Import project" # rubocop:disable QA/ElementWithPattern
end
@@ -23,9 +24,12 @@ module QA
end
def choose_test_namespace
- click_element :project_namespace_select
+ retry_on_exception do
+ click_body
+ click_element :project_namespace_select
- select_item(Runtime::Namespace.path)
+ search_and_select(Runtime::Namespace.path)
+ end
end
def go_to_import_project
@@ -44,6 +48,10 @@ module QA
click_on 'Create project'
end
+ def go_to_create_from_template
+ click_element(:project_create_from_template_tab)
+ end
+
def set_visibility(visibility)
choose visibility
end
diff --git a/qa/qa/page/project/operations/kubernetes/add_existing.rb b/qa/qa/page/project/operations/kubernetes/add_existing.rb
index f3ab636ecc1..ffd5b36e1ae 100644
--- a/qa/qa/page/project/operations/kubernetes/add_existing.rb
+++ b/qa/qa/page/project/operations/kubernetes/add_existing.rb
@@ -33,8 +33,8 @@ module QA
click_on 'Add Kubernetes cluster'
end
- def check_rbac!
- check_element :rbac_checkbox
+ def uncheck_rbac!
+ uncheck_element :rbac_checkbox
end
end
end
diff --git a/qa/qa/page/project/operations/kubernetes/show.rb b/qa/qa/page/project/operations/kubernetes/show.rb
index 9e8f9ba79d7..d4e1679b6bf 100644
--- a/qa/qa/page/project/operations/kubernetes/show.rb
+++ b/qa/qa/page/project/operations/kubernetes/show.rb
@@ -14,6 +14,11 @@ module QA
element :ingress_ip_address, 'id="ingress-ip-address"' # rubocop:disable QA/ElementWithPattern
end
+ view 'app/views/clusters/clusters/_form.html.haml' do
+ element :base_domain
+ element :save_domain
+ end
+
def install!(application_name)
within(".js-cluster-application-row-#{application_name}") do
page.has_button?('Install', wait: 30)
@@ -30,7 +35,15 @@ module QA
def ingress_ip
# We need to wait longer since it can take some time before the
# ip address is assigned for the ingress controller
- page.find('#ingress-ip-address', wait: 500).value
+ page.find('#ingress-ip-address', wait: 1200).value
+ end
+
+ def set_domain(domain)
+ fill_element :base_domain, domain
+ end
+
+ def save_domain
+ click_element :save_domain
end
end
end
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index b22396fd67a..6f8a66bf527 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -11,13 +11,17 @@ module QA::Page
view 'app/assets/javascripts/pipelines/components/graph/job_item.vue' do
element :job_component, /class.*ci-job-component.*/ # rubocop:disable QA/ElementWithPattern
- element :job_link, /class.*js-pipeline-graph-job-link.*/ # rubocop:disable QA/ElementWithPattern
+ element :job_link
end
view 'app/assets/javascripts/vue_shared/components/ci_icon.vue' do
element :status_icon, 'ci-status-icon-${status}' # rubocop:disable QA/ElementWithPattern
end
+ view 'app/views/projects/pipelines/_info.html.haml' do
+ element :pipeline_badges
+ end
+
def running?
within('.ci-header-container') do
page.has_content?('running')
@@ -32,6 +36,16 @@ module QA::Page
end
end
+ def has_tag?(tag_name)
+ within_element(:pipeline_badges) do
+ has_selector?('.badge', text: tag_name)
+ end
+ end
+
+ def go_to_job(job_name)
+ find_element(:job_link, text: job_name).click
+ end
+
def go_to_first_job
css = '.js-pipeline-graph-job-link'
diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb
index 12c2409a5a7..2de39b8ebf5 100644
--- a/qa/qa/page/project/settings/ci_cd.rb
+++ b/qa/qa/page/project/settings/ci_cd.rb
@@ -13,9 +13,7 @@ module QA # rubocop:disable Naming/FileName
view 'app/views/projects/settings/ci_cd/_autodevops_form.html.haml' do
element :enable_auto_devops_field, 'check_box :enabled' # rubocop:disable QA/ElementWithPattern
- element :domain_field, 'text_field :domain' # rubocop:disable QA/ElementWithPattern
element :enable_auto_devops_button, "%strong= s_('CICD|Default to Auto DevOps pipeline')" # rubocop:disable QA/ElementWithPattern
- element :domain_input, "%strong= _('Domain')" # rubocop:disable QA/ElementWithPattern
element :save_changes_button, "submit _('Save changes')" # rubocop:disable QA/ElementWithPattern
end
@@ -31,10 +29,9 @@ module QA # rubocop:disable Naming/FileName
end
end
- def enable_auto_devops_with_domain(domain)
+ def enable_auto_devops
expand_section(:autodevops_settings) do
check 'Default to Auto DevOps pipeline'
- fill_in 'Domain', with: domain
click_on 'Save changes'
end
end
diff --git a/qa/qa/page/project/settings/deploy_keys.rb b/qa/qa/page/project/settings/deploy_keys.rb
index 3c8c0cbdf7c..e0f9e84096d 100644
--- a/qa/qa/page/project/settings/deploy_keys.rb
+++ b/qa/qa/page/project/settings/deploy_keys.rb
@@ -14,8 +14,13 @@ module QA
end
view 'app/assets/javascripts/deploy_keys/components/key.vue' do
- element :key_title, /class=".*qa-key-title.*"/ # rubocop:disable QA/ElementWithPattern
- element :key_fingerprint, /class=".*qa-key-fingerprint.*"/ # rubocop:disable QA/ElementWithPattern
+ element :key
+ element :key_title
+ element :key_fingerprint
+ end
+
+ def add_key
+ click_on 'Add key'
end
def fill_key_title(title)
@@ -26,31 +31,29 @@ module QA
fill_in 'deploy_key_key', with: key
end
- def add_key
- click_on 'Add key'
- end
-
- def key_title
+ def find_fingerprint(title)
within_project_deploy_keys do
- find_element(:key_title).text
+ find_element(:key, text: title)
+ .find(element_selector_css(:key_fingerprint)).text
end
end
- def key_fingerprint
+ def has_key?(title, fingerprint)
within_project_deploy_keys do
- find_element(:key_fingerprint).text
+ find_element(:key, text: title)
+ .has_css?(element_selector_css(:key_fingerprint), text: fingerprint)
end
end
- def key_titles
+ def key_title
within_project_deploy_keys do
- all_elements(:key_title)
+ find_element(:key_title).text
end
end
- def key_fingerprints
+ def key_fingerprint
within_project_deploy_keys do
- all_elements(:key_fingerprint)
+ find_element(:key_fingerprint).text
end
end
@@ -58,7 +61,7 @@ module QA
def within_project_deploy_keys
wait(reload: false) do
- has_css?(element_selector_css(:project_deploy_keys))
+ has_element?(:project_deploy_keys)
end
within_element(:project_deploy_keys) do
diff --git a/qa/qa/page/project/settings/mirroring_repositories.rb b/qa/qa/page/project/settings/mirroring_repositories.rb
index a73be7dfeda..831166f6373 100644
--- a/qa/qa/page/project/settings/mirroring_repositories.rb
+++ b/qa/qa/page/project/settings/mirroring_repositories.rb
@@ -62,7 +62,7 @@ module QA
sleep 5
refresh
- wait(time: 1) do
+ wait(interval: 1) do
within_element_by_index(:mirrored_repository_row, row_index) do
last_update = find_element(:mirror_last_update_at, wait: 0)
last_update.has_text?('just now') || last_update.has_text?('seconds')
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 945b244df15..9c21d9ddbfa 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -51,6 +51,16 @@ module QA
element :branches_dropdown
end
+ view 'app/views/projects/blob/viewers/_loading.html.haml' do
+ element :spinner
+ end
+
+ def wait_for_viewers_to_load
+ wait(reload: false) do
+ has_no_element?(:spinner)
+ end
+ end
+
def create_first_new_file!
within_element(:quick_actions) do
click_link_with_text 'New file'
diff --git a/qa/qa/page/project/sub_menus/ci_cd.rb b/qa/qa/page/project/sub_menus/ci_cd.rb
new file mode 100644
index 00000000000..adae2ce08c4
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/ci_cd.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module CiCd
+ def self.included(base)
+ base.class_eval do
+ view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ element :link_pipelines
+ end
+ end
+ end
+
+ def click_ci_cd_pipelines
+ within_sidebar do
+ click_element :link_pipelines
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/common.rb b/qa/qa/page/project/sub_menus/common.rb
new file mode 100644
index 00000000000..c94e1e85256
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/common.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module Common
+ def within_sidebar
+ within('.sidebar-top-level-items') do
+ yield
+ end
+ end
+
+ def within_submenu
+ within('.fly-out-list') do
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/issues.rb b/qa/qa/page/project/sub_menus/issues.rb
new file mode 100644
index 00000000000..f81e4f34909
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/issues.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module Issues
+ def self.included(base)
+ base.class_eval do
+ view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ element :issues_item
+ element :labels_link
+ element :milestones_link
+ end
+ end
+ end
+
+ def click_issues
+ within_sidebar do
+ click_link('Issues')
+ end
+ end
+
+ def click_milestones
+ within_sidebar do
+ click_element :milestones_link
+ end
+ end
+
+ def go_to_labels
+ hover_issues do
+ within_submenu do
+ click_element(:labels_link)
+ end
+ end
+ end
+
+ private
+
+ def hover_issues
+ within_sidebar do
+ scroll_to_element(:issues_item)
+ find_element(:issues_item).hover
+
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/operations.rb b/qa/qa/page/project/sub_menus/operations.rb
new file mode 100644
index 00000000000..cf9fc453565
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/operations.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module Operations
+ def self.included(base)
+ base.class_eval do
+ view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ element :link_operations
+ element :operations_environments_link
+ end
+ end
+ end
+
+ def click_operations_environments
+ hover_operations do
+ within_submenu do
+ click_element(:operations_environments_link)
+ end
+ end
+ end
+
+ def click_operations_kubernetes
+ hover_operations do
+ within_submenu do
+ click_link('Kubernetes')
+ end
+ end
+ end
+
+ private
+
+ def hover_operations
+ within_sidebar do
+ scroll_to_element(:link_operations)
+ find_element(:link_operations).hover
+
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/repository.rb b/qa/qa/page/project/sub_menus/repository.rb
new file mode 100644
index 00000000000..29eaa9a74de
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/repository.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module Repository
+ def self.included(base)
+ base.class_eval do
+ view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ element :project_menu_repo
+ element :branches_link
+ end
+ end
+ end
+
+ def click_repository
+ within_sidebar do
+ click_element(:project_menu_repo)
+ end
+ end
+
+ def click_repository_branches
+ hover_repository do
+ within_submenu do
+ click_element(:branches_link)
+ end
+ end
+ end
+
+ private
+
+ def hover_repository
+ within_sidebar do
+ find_element(:project_menu_repo).hover
+
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/settings.rb b/qa/qa/page/project/sub_menus/settings.rb
new file mode 100644
index 00000000000..62c594c0210
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/settings.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module Settings
+ def self.included(base)
+ base.class_eval do
+ view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ element :settings_item
+ element :link_members_settings
+ end
+ end
+ end
+
+ def click_ci_cd_settings
+ hover_settings do
+ within_submenu do
+ click_link('CI / CD')
+ end
+ end
+ end
+
+ def click_members_settings
+ hover_settings do
+ within_submenu do
+ click_element :link_members_settings
+ end
+ end
+ end
+
+ def click_repository_settings
+ hover_settings do
+ within_submenu do
+ click_link('Repository')
+ end
+ end
+ end
+
+ def go_to_settings
+ within_sidebar do
+ click_on 'Settings'
+ end
+ end
+
+ private
+
+ def hover_settings
+ within_sidebar do
+ scroll_to_element(:settings_item)
+ find_element(:settings_item).hover
+
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index 23e580b81b6..2b6c01888d5 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -66,11 +66,29 @@ module QA
def commit_changes
click_element :begin_commit_button
- click_element :commit_button
+ # After clicking :begin_commit_button there is an animation that
+ # hides :begin_commit_button and shows :commit_button
+ #
+ # Wait for the animation to complete before clicking :commit_button
+ # otherwise the click will quietly do nothing.
wait(reload: false) do
- page.has_content?('Your changes have been committed')
+ has_no_element?(:begin_commit_button) &&
+ has_element?(:commit_button)
end
+
+ # Retry the attempt to click :commit_button just in case part of the
+ # animation is still in process even when the buttons have the
+ # expected visibility.
+ commit_success_msg_shown = retry_until do
+ click_element :commit_button
+
+ wait(reload: false) do
+ has_text?('Your changes have been committed')
+ end
+ end
+
+ raise "The changes do not appear to have been committed successfully." unless commit_success_msg_shown
end
end
end
diff --git a/qa/qa/page/project/wiki/new.rb b/qa/qa/page/project/wiki/new.rb
index 2498af8600c..b90e03be36a 100644
--- a/qa/qa/page/project/wiki/new.rb
+++ b/qa/qa/page/project/wiki/new.rb
@@ -1,42 +1,58 @@
+# frozen_string_literal: true
+
module QA
module Page
module Project
module Wiki
class New < Page::Base
+ include Component::LazyLoader
+
view 'app/views/projects/wikis/_form.html.haml' do
- element :wiki_title_textbox, 'text_field :title' # rubocop:disable QA/ElementWithPattern
- element :wiki_content_textarea, "render 'projects/zen', f: f, attr: :content" # rubocop:disable QA/ElementWithPattern
- element :wiki_message_textbox, 'text_field :message' # rubocop:disable QA/ElementWithPattern
- element :save_changes_button, 'submit _("Save changes")' # rubocop:disable QA/ElementWithPattern
- element :create_page_button, 'submit s_("Wiki|Create page")' # rubocop:disable QA/ElementWithPattern
+ element :wiki_title_textbox
+ element :wiki_content_textarea
+ element :wiki_message_textbox
+ element :save_changes_button
+ element :create_page_button
end
view 'app/views/shared/empty_states/_wikis.html.haml' do
- element :create_link, 'Create your first page' # rubocop:disable QA/ElementWithPattern
+ element :create_first_page_link
+ end
+
+ view 'app/views/shared/empty_states/_wikis_layout.html.haml' do
+ element :svg_content
end
def go_to_create_first_page
- click_link 'Create your first page'
+ # The svg takes a fraction of a second to load after which the
+ # "Create your first page" button shifts up a bit. This can cause
+ # webdriver to miss the hit so we wait for the svg to load before
+ # clicking the button.
+ within_element(:svg_content) do
+ has_element? :js_lazy_loaded
+ end
+
+ click_element :create_first_page_link
end
def set_title(title)
- fill_in 'wiki_title', with: title
+ fill_element :wiki_title_textbox, title
end
def set_content(content)
- fill_in 'wiki_content', with: content
+ fill_element :wiki_content_textarea, content
end
def set_message(message)
- fill_in 'wiki_message', with: message
+ fill_element :wiki_message_textbox, message
end
def save_changes
- click_on 'Save changes'
+ click_element :save_changes_button
end
def create_new_page
- click_on 'Create page'
+ click_element :create_page_button
end
end
end
diff --git a/qa/qa/page/settings/common.rb b/qa/qa/page/settings/common.rb
index f9f71aa4a72..9fea74eabc9 100644
--- a/qa/qa/page/settings/common.rb
+++ b/qa/qa/page/settings/common.rb
@@ -11,7 +11,7 @@ module QA
wait(reload: false) do
click_button 'Expand' unless first('button', text: 'Collapse')
- page.has_content?('Collapse')
+ has_content?('Collapse')
end
yield if block_given?
diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb
index dcea144ab74..523d92c7ef3 100644
--- a/qa/qa/resource/base.rb
+++ b/qa/qa/resource/base.rb
@@ -27,6 +27,10 @@ module QA
attributes.each(&method(:public_send))
end
+ def wait(max: 60, interval: 0.1)
+ QA::Support::Waiter.wait(max: max, interval: interval)
+ end
+
private
def populate_attribute(name, block)
@@ -116,27 +120,13 @@ module QA
end
private_class_method :evaluator
- def self.dynamic_attributes
- const_get(:DynamicAttributes)
- rescue NameError
- mod = const_set(:DynamicAttributes, Module.new)
-
- include mod
-
- mod
- end
-
- def self.attributes_names
- dynamic_attributes.instance_methods(false).sort.grep_v(/=$/)
- end
-
class DSL
def initialize(base)
@base = base
end
def attribute(name, &block)
- @base.dynamic_attributes.module_eval do
+ @base.module_eval do
attr_writer(name)
define_method(name) do
diff --git a/qa/qa/resource/deploy_key.rb b/qa/qa/resource/deploy_key.rb
index 9ed8fb7726e..9565598efb0 100644
--- a/qa/qa/resource/deploy_key.rb
+++ b/qa/qa/resource/deploy_key.rb
@@ -8,11 +8,7 @@ module QA
attribute :fingerprint do
Page::Project::Settings::Repository.perform do |setting|
setting.expand_deploy_keys do |key|
- key_offset = key.key_titles.index do |key_title|
- key_title.text == title
- end
-
- key.key_fingerprints[key_offset].text
+ key.find_fingerprint(title)
end
end
end
diff --git a/qa/qa/resource/events/base.rb b/qa/qa/resource/events/base.rb
new file mode 100644
index 00000000000..b50b620b143
--- /dev/null
+++ b/qa/qa/resource/events/base.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Events
+ MAX_WAIT = 10
+
+ EventNotFoundError = Class.new(RuntimeError)
+
+ module Base
+ def events(action: nil)
+ path = [api_get_events]
+ path << "?action=#{CGI.escape(action)}" if action
+ parse_body(api_get_from("#{path.join}"))
+ end
+
+ private
+
+ def api_get_events
+ "#{api_get_path}/events"
+ end
+
+ def wait_for_event
+ event_found = QA::Support::Waiter.wait(max: max_wait) do
+ yield
+ end
+
+ raise EventNotFoundError, "Timed out waiting for event" unless event_found
+ end
+
+ def max_wait
+ MAX_WAIT
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/events/project.rb b/qa/qa/resource/events/project.rb
new file mode 100644
index 00000000000..99c78254f42
--- /dev/null
+++ b/qa/qa/resource/events/project.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Events
+ module Project
+ include Events::Base
+
+ def wait_for_push(commit_message)
+ QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_push with commit message "#{commit_message}"])
+ wait_for_event do
+ events(action: 'pushed').any? { |event| event.dig(:push_data, :commit_title) == commit_message }
+ end
+ end
+
+ def wait_for_push_new_branch(branch_name = "master")
+ QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_push_new_branch with branch_name "#{branch_name}"])
+ wait_for_event do
+ events(action: 'pushed').any? { |event| event.dig(:push_data, :ref) == branch_name }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/fork.rb b/qa/qa/resource/fork.rb
index 9fd66f3a36a..03bc1f0820b 100644
--- a/qa/qa/resource/fork.rb
+++ b/qa/qa/resource/fork.rb
@@ -3,7 +3,14 @@
module QA
module Resource
class Fork < Base
- attribute :push do
+ attribute :project do
+ Resource::Project.fabricate! do |resource|
+ resource.name = upstream.project.name
+ resource.path_with_namespace = "#{user.name}/#{upstream.project.name}"
+ end
+ end
+
+ attribute :upstream do
Repository::ProjectPush.fabricate!
end
@@ -17,7 +24,7 @@ module QA
end
def fabricate!
- populate(:push, :user)
+ populate(:upstream, :user)
# Sign out as admin and sign is as the fork user
Page::Main::Menu.perform(&:sign_out)
@@ -26,7 +33,7 @@ module QA
login.sign_in_using_credentials(user)
end
- push.project.visit!
+ upstream.project.visit!
Page::Project::Show.perform(&:fork_project)
@@ -37,6 +44,8 @@ module QA
Page::Layout::Banner.perform do |page|
page.has_notice?('The project was successfully forked.')
end
+
+ populate(:project)
end
end
end
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index a7a6f931e28..d7f9ec6a836 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -33,7 +33,7 @@ module QA
end
# Ensure that the group was actually created
- group_show.wait(time: 1) do
+ group_show.wait(interval: 1) do
group_show.has_text?(path) &&
group_show.has_new_project_or_subgroup_dropdown?
end
diff --git a/qa/qa/resource/kubernetes_cluster.rb b/qa/qa/resource/kubernetes_cluster.rb
index 96c8843fb99..93a06be6818 100644
--- a/qa/qa/resource/kubernetes_cluster.rb
+++ b/qa/qa/resource/kubernetes_cluster.rb
@@ -6,7 +6,7 @@ module QA
module Resource
class KubernetesCluster < Base
attr_writer :project, :cluster,
- :install_helm_tiller, :install_ingress, :install_prometheus, :install_runner
+ :install_helm_tiller, :install_ingress, :install_prometheus, :install_runner, :domain
attribute :ingress_ip do
Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip)
@@ -29,7 +29,7 @@ module QA
page.set_api_url(@cluster.api_url)
page.set_ca_certificate(@cluster.ca_certificate)
page.set_token(@cluster.token)
- page.check_rbac! if @cluster.rbac
+ page.uncheck_rbac! unless @cluster.rbac
page.add_cluster!
end
@@ -49,6 +49,12 @@ module QA
page.await_installed(:ingress) if @install_ingress
page.await_installed(:prometheus) if @install_prometheus
page.await_installed(:runner) if @install_runner
+
+ if @install_ingress
+ populate(:ingress_ip)
+ page.set_domain("#{ingress_ip}.nip.io")
+ page.save_domain
+ end
end
end
end
diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb
index 7150098a00a..45cb317e0eb 100644
--- a/qa/qa/resource/merge_request.rb
+++ b/qa/qa/resource/merge_request.rb
@@ -58,10 +58,7 @@ module QA
populate(:target, :source)
project.visit!
- Page::Project::Show.perform do |project|
- project.wait_for_push
- project.new_merge_request
- end
+ Page::Project::Show.perform(&:new_merge_request)
Page::MergeRequest::New.perform do |page|
page.fill_title(@title)
page.fill_description(@description)
diff --git a/qa/qa/resource/merge_request_from_fork.rb b/qa/qa/resource/merge_request_from_fork.rb
index f91ae299d76..5d20a6e9c75 100644
--- a/qa/qa/resource/merge_request_from_fork.rb
+++ b/qa/qa/resource/merge_request_from_fork.rb
@@ -11,7 +11,7 @@ module QA
attribute :push do
Repository::ProjectPush.fabricate! do |resource|
- resource.project = fork
+ resource.project = fork.project
resource.branch_name = fork_branch
resource.file_name = 'file2.txt'
resource.user = fork.user
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 1fafbf5d73e..de1e9f04c36 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -5,6 +5,8 @@ require 'securerandom'
module QA
module Resource
class Project < Base
+ include Events::Project
+
attribute :name
attribute :description
@@ -12,6 +14,10 @@ module QA
Group.fabricate!
end
+ attribute :path_with_namespace do
+ "#{group.sandbox.path}/#{group.path}/#{name}" if group
+ end
+
attribute :repository_ssh_location do
Page::Project::Show.perform do |page|
page.repository_clone_ssh_location
@@ -46,8 +52,14 @@ module QA
end
end
+ def fabricate_via_api!
+ resource_web_url(api_get)
+ rescue ResourceNotFoundError
+ super
+ end
+
def api_get_path
- "/projects/#{name}"
+ "/projects/#{CGI.escape(path_with_namespace)}"
end
def api_post_path
diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb
index 3f02fe885a9..0d25e7dd842 100644
--- a/qa/qa/resource/project_imported_from_github.rb
+++ b/qa/qa/resource/project_imported_from_github.rb
@@ -4,7 +4,7 @@ require 'securerandom'
module QA
module Resource
- class ProjectImportedFromGithub < Project
+ class ProjectImportedFromGithub < Base
attr_accessor :name
attr_writer :personal_access_token, :github_repository_path
diff --git a/qa/qa/resource/repository/project_push.rb b/qa/qa/resource/repository/project_push.rb
index f4692c3dd4d..cad89ebb0bb 100644
--- a/qa/qa/resource/repository/project_push.rb
+++ b/qa/qa/resource/repository/project_push.rb
@@ -4,6 +4,8 @@ module QA
module Resource
module Repository
class ProjectPush < Repository::Push
+ attr_writer :wait_for_push
+
attribute :project do
Project.fabricate! do |resource|
resource.name = 'project-with-code'
@@ -17,6 +19,7 @@ module QA
@commit_message = "This is a test commit"
@branch_name = 'master'
@new_branch = true
+ @wait_for_push = true
end
def repository_http_uri
@@ -30,6 +33,7 @@ module QA
def fabricate!
super
project.visit!
+ project.wait_for_push @commit_message if @wait_for_push
end
end
end
diff --git a/qa/qa/resource/repository/push.rb b/qa/qa/resource/repository/push.rb
index c14d97ff7fb..a5827fb6e73 100644
--- a/qa/qa/resource/repository/push.rb
+++ b/qa/qa/resource/repository/push.rb
@@ -8,7 +8,7 @@ module QA
class Push < Base
attr_accessor :file_name, :file_content, :commit_message,
:branch_name, :new_branch, :output, :repository_http_uri,
- :repository_ssh_uri, :ssh_key, :user
+ :repository_ssh_uri, :ssh_key, :user, :use_lfs
attr_writer :remote_branch
@@ -20,6 +20,7 @@ module QA
@new_branch = true
@repository_http_uri = ""
@ssh_key = nil
+ @use_lfs = false
end
def remote_branch
@@ -33,7 +34,9 @@ module QA
end
def files=(files)
- if !files.is_a?(Array) || files.empty?
+ if !files.is_a?(Array) ||
+ files.empty? ||
+ files.any? { |file| !file.has_key?(:name) || !file.has_key?(:content) }
raise ArgumentError, "Please provide an array of hashes e.g.: [{name: 'file1', content: 'foo'}]"
end
@@ -42,6 +45,8 @@ module QA
def fabricate!
Git::Repository.perform do |repository|
+ @output = ''
+
if ssh_key
repository.uri = repository_ssh_uri
repository.use_ssh_key(ssh_key)
@@ -50,6 +55,8 @@ module QA
repository.use_default_credentials unless user
end
+ repository.use_lfs = use_lfs
+
username = 'GitLab QA'
email = 'root@gitlab.com'
@@ -60,29 +67,25 @@ module QA
email = user.email
end
- repository.clone
+ @output += repository.clone
repository.configure_identity(username, email)
- if new_branch
- repository.checkout_new_branch(branch_name)
- else
- repository.checkout(branch_name)
- end
+ @output += repository.checkout(branch_name, new_branch: new_branch)
if @directory
@directory.each_child do |f|
- repository.add_file(f.basename, f.read) if f.file?
+ @output += repository.add_file(f.basename, f.read) if f.file?
end
elsif @files
@files.each do |f|
repository.add_file(f[:name], f[:content])
end
else
- repository.add_file(file_name, file_content)
+ @output += repository.add_file(file_name, file_content)
end
- repository.commit(commit_message)
- @output = repository.push_changes("#{branch_name}:#{remote_branch}")
+ @output += repository.commit(commit_message)
+ @output += repository.push_changes("#{branch_name}:#{remote_branch}")
repository.delete_ssh_key
end
diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb
index c26f0c84a1f..6c5e91b6488 100644
--- a/qa/qa/resource/user.rb
+++ b/qa/qa/resource/user.rb
@@ -6,29 +6,40 @@ module QA
module Resource
class User < Base
attr_reader :unique_id
- attr_writer :username, :password, :name, :email
+ attr_writer :username, :password
attr_accessor :provider, :extern_uid
+ attribute :name
+ attribute :email
+
def initialize
@unique_id = SecureRandom.hex(8)
end
def username
- @username ||= "qa-user-#{unique_id}"
+ @username || "qa-user-#{unique_id}"
end
def password
- @password ||= 'password'
+ @password || 'password'
end
def name
- @name ||= username
+ @name ||= api_resource&.dig(:name) || username
end
def email
@email ||= "#{username}@example.com"
end
+ def public_email
+ @public_email ||= begin
+ api_public_email = api_resource&.dig(:public_email)
+
+ api_public_email && api_public_email != '' ? api_public_email : Runtime::User.default_email
+ end
+ end
+
def credentials_given?
defined?(@username) && defined?(@password)
end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index b706d6565d2..0b805b855ac 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -8,6 +8,8 @@ module QA
class Browser
include QA::Scenario::Actable
+ NotRespondingError = Class.new(RuntimeError)
+
def initialize
self.class.configure!
end
@@ -40,34 +42,38 @@ module QA
return if Capybara.drivers.include?(:chrome)
- Capybara.register_driver :chrome do |app|
- capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
- # This enables access to logs with `page.driver.manage.get_log(:browser)`
- loggingPrefs: {
- browser: "ALL",
- client: "ALL",
- driver: "ALL",
- server: "ALL"
- }
- )
+ Capybara.register_driver QA::Runtime::Env.browser do |app|
+ capabilities = Selenium::WebDriver::Remote::Capabilities.send(QA::Runtime::Env.browser,
+ # This enables access to logs with `page.driver.manage.get_log(:browser)`
+ loggingPrefs: {
+ browser: "ALL",
+ client: "ALL",
+ driver: "ALL",
+ server: "ALL"
+ })
if QA::Runtime::Env.accept_insecure_certs?
capabilities['acceptInsecureCerts'] = true
end
- options = Selenium::WebDriver::Chrome::Options.new
- options.add_argument("window-size=1240,1680")
+ # QA::Runtime::Env.browser.capitalize will work for every driver type except PhantomJS.
+ # We will have no use to use PhantomJS so this shouldn't be a problem.
+ options = Selenium::WebDriver.const_get(QA::Runtime::Env.browser.capitalize)::Options.new
+
+ if QA::Runtime::Env.browser == :chrome
+ options.add_argument("window-size=1240,1680")
- # Chrome won't work properly in a Docker container in sandbox mode
- options.add_argument("no-sandbox")
+ # Chrome won't work properly in a Docker container in sandbox mode
+ options.add_argument("no-sandbox")
- # Run headless by default unless CHROME_HEADLESS is false
- if QA::Runtime::Env.chrome_headless?
- options.add_argument("headless")
+ # Run headless by default unless CHROME_HEADLESS is false
+ if QA::Runtime::Env.chrome_headless?
+ options.add_argument("headless")
- # Chrome documentation says this flag is needed for now
- # https://developers.google.com/web/updates/2017/04/headless-chrome#cli
- options.add_argument("disable-gpu")
+ # Chrome documentation says this flag is needed for now
+ # https://developers.google.com/web/updates/2017/04/headless-chrome#cli
+ options.add_argument("disable-gpu")
+ end
end
# Use the same profile on QA runs if CHROME_REUSE_PROFILE is true.
@@ -80,12 +86,18 @@ module QA
# Disable /dev/shm use in CI. See https://gitlab.com/gitlab-org/gitlab-ee/issues/4252
options.add_argument("disable-dev-shm-usage") if QA::Runtime::Env.running_in_ci?
- Capybara::Selenium::Driver.new(
- app,
- browser: :chrome,
+ selenium_options = {
+ browser: QA::Runtime::Env.browser,
clear_local_storage: true,
desired_capabilities: capabilities,
options: options
+ }
+
+ selenium_options[:url] = QA::Runtime::Env.remote_grid if QA::Runtime::Env.remote_grid
+
+ Capybara::Selenium::Driver.new(
+ app,
+ selenium_options
)
end
@@ -93,7 +105,7 @@ module QA
Capybara::Screenshot.prune_strategy = :keep_last_run
# From https://github.com/mattheworiordan/capybara-screenshot/issues/84#issuecomment-41219326
- Capybara::Screenshot.register_driver(:chrome) do |driver, path|
+ Capybara::Screenshot.register_driver(QA::Runtime::Env.browser) do |driver, path|
driver.browser.save_screenshot(path)
end
@@ -102,8 +114,8 @@ module QA
end
Capybara.configure do |config|
- config.default_driver = :chrome
- config.javascript_driver = :chrome
+ config.default_driver = QA::Runtime::Env.browser
+ config.javascript_driver = QA::Runtime::Env.browser
config.default_max_wait_time = 10
# https://github.com/mattheworiordan/capybara-screenshot/issues/164
config.save_path = ::File.expand_path('../../tmp', __dir__)
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index dae5aa3f794..dd0ddbdbd6b 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -56,6 +56,34 @@ module QA
@personal_access_token ||= ENV['PERSONAL_ACCESS_TOKEN']
end
+ def remote_grid
+ # if username specified, password/auth token is required
+ # can be
+ # - "http://user:pass@somehost.com/wd/hub"
+ # - "https://user:pass@somehost.com:443/wd/hub"
+ # - "http://localhost:4444/wd/hub"
+
+ return if (ENV['QA_REMOTE_GRID'] || '').empty?
+
+ "#{remote_grid_protocol}://#{remote_grid_credentials}#{ENV['QA_REMOTE_GRID']}/wd/hub"
+ end
+
+ def remote_grid_username
+ ENV['QA_REMOTE_GRID_USERNAME']
+ end
+
+ def remote_grid_access_key
+ ENV['QA_REMOTE_GRID_ACCESS_KEY']
+ end
+
+ def remote_grid_protocol
+ ENV['QA_REMOTE_GRID_PROTOCOL'] || 'http'
+ end
+
+ def browser
+ ENV['QA_BROWSER'].nil? ? :chrome : ENV['QA_BROWSER'].to_sym
+ end
+
def user_username
ENV['GITLAB_USERNAME']
end
@@ -72,6 +100,14 @@ module QA
ENV['GITLAB_ADMIN_PASSWORD']
end
+ def github_username
+ ENV['GITHUB_USERNAME']
+ end
+
+ def github_password
+ ENV['GITHUB_PASSWORD']
+ end
+
def forker?
!!(forker_username && forker_password)
end
@@ -158,6 +194,16 @@ module QA
private
+ def remote_grid_credentials
+ if remote_grid_username
+ raise ArgumentError, %Q(Please provide an access key for user "#{remote_grid_username}") unless remote_grid_access_key
+
+ return "#{remote_grid_username}:#{remote_grid_access_key}@"
+ end
+
+ ''
+ end
+
def enabled?(value, default: true)
return default if value.nil?
diff --git a/qa/qa/runtime/namespace.rb b/qa/qa/runtime/namespace.rb
index 704c65467e0..9d7c1aea508 100644
--- a/qa/qa/runtime/namespace.rb
+++ b/qa/qa/runtime/namespace.rb
@@ -8,7 +8,9 @@ module QA
end
def name
- Runtime::Env.namespace_name || "qa-test-#{time.strftime('%Y-%m-%d-%H-%M-%S')}"
+ # If any changes are made to the name tag, following script has to be considered:
+ # https://ops.gitlab.net/gitlab-com/gl-infra/traffic-generator/blob/master/bin/janitor.bash
+ @name ||= Runtime::Env.namespace_name || "qa-test-#{time.strftime('%Y-%m-%d-%H-%M-%S')}-#{SecureRandom.hex(8)}"
end
def path
diff --git a/qa/qa/runtime/user.rb b/qa/qa/runtime/user.rb
index 5eb7a210fce..e8bcb8a9f50 100644
--- a/qa/qa/runtime/user.rb
+++ b/qa/qa/runtime/user.rb
@@ -7,6 +7,10 @@ module QA
'root'
end
+ def default_email
+ 'admin@example.com'
+ end
+
def default_password
'5iveL!fe'
end
diff --git a/qa/qa/scenario/test/integration/oauth.rb b/qa/qa/scenario/test/integration/oauth.rb
new file mode 100644
index 00000000000..912156fbc29
--- /dev/null
+++ b/qa/qa/scenario/test/integration/oauth.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Integration
+ class OAuth < Test::Instance::All
+ tags :oauth
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/service/kubernetes_cluster.rb b/qa/qa/service/kubernetes_cluster.rb
index c5f12255d72..41ab702d8b2 100644
--- a/qa/qa/service/kubernetes_cluster.rb
+++ b/qa/qa/service/kubernetes_cluster.rb
@@ -9,7 +9,7 @@ module QA
attr_reader :api_url, :ca_certificate, :token, :rbac
- def initialize(rbac: false)
+ def initialize(rbac: true)
@rbac = rbac
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
new file mode 100644
index 00000000000..a118176eb8a
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Manage', :orchestrated, :oauth do
+ describe 'OAuth login' do
+ it 'User logs in to GitLab with GitHub OAuth' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+
+ Page::Main::Login.perform(&:sign_in_with_github)
+ Vendor::Github::Page::Login.perform(&:login)
+
+ expect(page).to have_content('Welcome to GitLab')
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
index 3ce48de2c25..a9eafd61a91 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module QA
- context 'Manage', :orchestrated, :github do
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/58158
+ context 'Manage', :github, :quarantine do
describe 'Project import from GitHub' do
let(:imported_project) do
Resource::ProjectImportedFromGithub.fabricate! do |project|
@@ -48,20 +49,26 @@ module QA
end
def verify_issues_import
- Page::Project::Menu.act { click_issues }
- expect(page).to have_content('This is a sample issue')
+ QA::Support::Retrier.retry_on_exception do
+ Page::Project::Menu.act { click_issues }
+ expect(page).to have_content('This is a sample issue')
- click_link 'This is a sample issue'
+ click_link 'This is a sample issue'
- expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.')
+ expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.')
- # Comments
- expect(page).to have_content('This is a comment from @rymai.')
+ # Comments
+ comment_text = 'This is a comment from @rymai.'
- Page::Issuable::Sidebar.perform do |issuable|
- expect(issuable).to have_label('enhancement')
- expect(issuable).to have_label('help wanted')
- expect(issuable).to have_label('good first issue')
+ Page::Project::Issue::Show.perform do |issue_page|
+ expect(issue_page).to have_comment(comment_text)
+ end
+
+ Page::Issuable::Sidebar.perform do |issuable|
+ expect(issuable).to have_label('enhancement')
+ expect(issuable).to have_label('help wanted')
+ expect(issuable).to have_label('good first issue')
+ end
end
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
new file mode 100644
index 00000000000..fa779bd1f4e
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Plan' do
+ describe 'collapse comments in issue discussions' do
+ let(:issue_title) { 'issue title' }
+
+ it 'user collapses reply for comments in an issue' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ Resource::Issue.fabricate! do |issue|
+ issue.title = issue_title
+ end
+
+ expect(page).to have_content(issue_title)
+
+ Page::Project::Issue::Show.perform do |show_page|
+ show_page.select_all_activities_filter
+ show_page.start_discussion("My first discussion")
+ expect(show_page).to have_content("My first discussion")
+
+ show_page.reply_to_discussion("My First Reply")
+ expect(show_page).to have_content("My First Reply")
+
+ show_page.collapse_replies
+ expect(show_page).to have_content("1 reply")
+ expect(show_page).not_to have_content("My First Reply")
+
+ show_page.expand_replies
+ expect(show_page).to have_content("My First Reply")
+ expect(show_page).not_to have_content("1 reply")
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index 6ddd7dde2cf..c06f13ee204 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -3,7 +3,7 @@
module QA
context 'Create' do
describe 'Merge request creation' do
- it 'user creates a new merge request' do
+ it 'user creates a new merge request' do
gitlab_account_username = "@#{Runtime::User.username}"
Runtime::Browser.visit(:gitlab, Page::Main::Login)
@@ -49,7 +49,7 @@ module QA
end
describe 'creates a merge request', :smoke do
- it 'user creates a new merge request' do
+ it 'user creates a new merge request' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
index 6dcd74471fe..6ca7af8a3af 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
@@ -5,18 +5,18 @@ module QA
describe 'Merge request creation from fork' do
it 'user forks a project, submits a merge request and maintainer merges it' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
merge_request = Resource::MergeRequestFromFork.fabricate! do |merge_request|
merge_request.fork_branch = 'feature-branch'
end
- Page::Main::Menu.perform { |main| main.sign_out }
- Page::Main::Login.perform { |login| login.sign_in_using_credentials }
+ Page::Main::Menu.perform(&:sign_out)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
merge_request.visit!
- Page::MergeRequest::Show.perform { |show| show.merge! }
+ Page::MergeRequest::Show.perform(&:merge!)
expect(page).to have_content('The changes were merged')
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index e2d639fd150..3fbcd77dac6 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -3,17 +3,17 @@
module QA
context 'Create' do
describe 'Merge request rebasing' do
- it 'user rebases source branch of merge request' do
+ it 'user rebases source branch of merge request' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
project = Resource::Project.fabricate! do |project|
project.name = "only-fast-forward"
end
project.visit!
- Page::Project::Menu.act { go_to_settings }
- Page::Project::Settings::MergeRequest.act { enable_ff_only }
+ Page::Project::Menu.perform(&:go_to_settings)
+ Page::Project::Settings::MergeRequest.perform(&:enable_ff_only)
merge_request = Resource::MergeRequest.fabricate! do |merge_request|
merge_request.project = project
@@ -38,7 +38,7 @@ module QA
merge_request.rebase!
expect(merge_request).to have_merge_button
- expect(merge_request.fast_forward_possible?).to be_truthy
+ expect(merge_request).to be_fast_forward_possible
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
index 4126f967ee2..f146636c49a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
module QA
+ # Failure issue: https://gitlab.com/gitlab-org/quality/staging/issues/31
context 'Create' do
describe 'Merge request squashing' do
- it 'user squashes commits while merging' do
+ it 'user squashes commits while merging' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
@@ -25,7 +26,6 @@ module QA
push.file_content = "Test with unicode characters â¤âœ“€â„"
end
- Page::Project::Show.perform(&:wait_for_push)
merge_request.visit!
expect(page).to have_text('to be squashed')
@@ -37,9 +37,7 @@ module QA
merge_request.project.visit!
Git::Repository.perform do |repository|
- repository.uri = Page::Project::Show.act do
- repository_clone_http_location.uri
- end
+ repository.uri = merge_request.project.repository_http_location.uri
repository.use_default_credentials
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
new file mode 100644
index 00000000000..9e48ee7ca2a
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Create' do
+ describe 'Download merge request patch and diff' do
+ before(:context) do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ @merge_request = Resource::MergeRequest.fabricate! do |merge_request|
+ merge_request.title = 'This is a merge request'
+ merge_request.description = 'For downloading patches and diffs'
+ end
+ end
+
+ it 'user views merge request email patches' do
+ @merge_request.visit!
+ Page::MergeRequest::Show.perform(&:view_email_patches)
+
+ expect(page.text).to start_with('From')
+ expect(page).to have_content('Subject: [PATCH] This is a test commit')
+ expect(page).to have_content('diff --git a/added_file.txt b/added_file.txt')
+ end
+
+ it 'user views merge request plain diff' do
+ @merge_request.visit!
+ Page::MergeRequest::Show.perform(&:view_plain_diff)
+
+ expect(page.text).to start_with('diff --git a/added_file.txt b/added_file.txt')
+ expect(page).to have_content('+File Added')
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
new file mode 100644
index 00000000000..8e181eb28c6
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Create' do
+ describe 'Create, list, and delete branches via web' do
+ master_branch = 'master'
+ second_branch = 'second-branch'
+ third_branch = 'third-branch'
+ file_1_master = 'file.txt'
+ file_2_master = 'other-file.txt'
+ file_second_branch = 'file-2.txt'
+ file_third_branch = 'file-3.txt'
+ first_commit_message_of_master_branch = "Add #{file_1_master}"
+ second_commit_message_of_master_branch = "Add #{file_2_master}"
+ commit_message_of_second_branch = "Add #{file_second_branch}"
+ commit_message_of_third_branch = "Add #{file_third_branch}"
+
+ before do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ project = Resource::Project.fabricate! do |proj|
+ proj.name = 'project-qa-test'
+ proj.description = 'project for qa test'
+ end
+
+ Git::Repository.perform do |repository|
+ repository.uri = project.repository_http_location.uri
+ repository.use_default_credentials
+ repository.try_add_credentials_to_netrc
+
+ repository.act do
+ clone
+ configure_identity('GitLab QA', 'root@gitlab.com')
+ commit_file(file_1_master, 'Test file content', first_commit_message_of_master_branch)
+ push_changes
+ checkout(second_branch, new_branch: true)
+ commit_file(file_second_branch, 'File 2 content', commit_message_of_second_branch)
+ push_changes(second_branch)
+ checkout(master_branch)
+ # This second commit on master is needed for the master branch to be ahead
+ # of the second branch, and when the second branch is merged to master it will
+ # show the 'merged' badge on it.
+ # Refer to the below issue note:
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/55524#note_126100848
+ commit_file(file_2_master, 'Other test file content', second_commit_message_of_master_branch)
+ push_changes
+ merge(second_branch)
+ push_changes
+ checkout(third_branch, new_branch: true)
+ commit_file(file_third_branch, 'File 3 content', commit_message_of_third_branch)
+ push_changes(third_branch)
+ end
+ end
+ project.wait_for_push commit_message_of_third_branch
+ project.visit!
+ end
+
+ it 'branches are correctly listed after CRUD operations' do
+ Page::Project::Menu.perform(&:click_repository_branches)
+
+ expect(page).to have_content(master_branch)
+ expect(page).to have_content(second_branch)
+ expect(page).to have_content(third_branch)
+ expect(page).to have_content("Merge branch 'second-branch'")
+ expect(page).to have_content(commit_message_of_second_branch)
+ expect(page).to have_content(commit_message_of_third_branch)
+
+ Page::Project::Branches::Show.perform do |branches|
+ expect(branches).to have_branch_with_badge(second_branch, 'merged')
+ end
+
+ Page::Project::Branches::Show.perform do |branches_view|
+ branches_view.delete_branch(third_branch)
+ end
+
+ expect(page).not_to have_content(third_branch)
+
+ Page::Project::Branches::Show.perform(&:delete_merged_branches)
+
+ expect(page).to have_content(
+ 'Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes.'
+ )
+
+ page.refresh
+ Page::Project::Branches::Show.perform do |branches_view|
+ branches_view.wait_for_texts_not_to_be_visible([commit_message_of_second_branch])
+ expect(branches_view).not_to have_branch_title(second_branch)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
index 571cae4a3c5..f2584f55a60 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
@@ -3,22 +3,18 @@
module QA
context 'Create' do
describe 'Git clone over HTTP', :ldap_no_tls do
- let(:location) do
- Page::Project::Show.perform(&:repository_clone_http_location).uri
- end
-
- before do
+ before(:all) do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
- project = Resource::Project.fabricate! do |scenario|
+ @project = Resource::Project.fabricate! do |scenario|
scenario.name = 'project-with-code'
scenario.description = 'project for git clone tests'
end
- project.visit!
+ @project.visit!
Git::Repository.perform do |repository|
- repository.uri = location
+ repository.uri = @project.repository_http_location.uri
repository.use_default_credentials
repository.act do
@@ -29,12 +25,12 @@ module QA
push_changes
end
end
- Page::Project::Show.perform(&:wait_for_push)
+ @project.wait_for_push_new_branch
end
it 'user performs a deep clone' do
Git::Repository.perform do |repository|
- repository.uri = location
+ repository.uri = @project.repository_http_location.uri
repository.use_default_credentials
repository.clone
@@ -45,7 +41,7 @@ module QA
it 'user performs a shallow clone' do
Git::Repository.perform do |repository|
- repository.uri = location
+ repository.uri = @project.repository_http_location.uri
repository.use_default_credentials
repository.shallow_clone
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
index 43894372cf5..01a367fceac 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
@@ -1,7 +1,9 @@
# frozen_string_literal: true
module QA
- context 'Create' do
+ # Git protocol v2 is temporarily disabled
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/55769 (confidential)
+ context 'Create', :quarantine do
describe 'Push over HTTP using Git protocol version 2', :requires_git_protocol_v2 do
it 'user pushes to the repository' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
@@ -35,7 +37,7 @@ module QA
end
project.visit!
- Page::Project::Show.perform(&:wait_for_push)
+ project.wait_for_push_new_branch
# Check that the push worked
expect(page).to have_content(file_name)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
index 135925c007f..eb59b54e9ab 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
@@ -1,7 +1,9 @@
# frozen_string_literal: true
module QA
- context 'Create' do
+ # Git protocol v2 is temporarily disabled
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/55769 (confidential)
+ context 'Create', :quarantine do
describe 'Push over SSH using Git protocol version 2', :requires_git_protocol_v2 do
# Note: If you run this test against GDK make sure you've enabled sshd and
# enabled setting the Git protocol by adding `AcceptEnv GIT_PROTOCOL` to
@@ -70,7 +72,7 @@ module QA
end
project.visit!
- Page::Project::Show.perform(&:wait_for_push)
+ project.wait_for_push_new_branch
# Check that the push worked
expect(page).to have_content(file_name)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
index a63b7dce8d6..1f4fb08accc 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
@@ -3,7 +3,7 @@
module QA
context 'Create' do
describe 'Git push over HTTP', :ldap_no_tls do
- it 'user using a personal access token pushes code to the repository' do
+ it 'user using a personal access token pushes code to the repository' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
@@ -22,7 +22,8 @@ module QA
end
push.project.visit!
- Page::Project::Show.perform(&:wait_for_push)
+
+ Page::Project::Show.perform(&:wait_for_viewers_to_load)
expect(page).to have_content('README.md')
expect(page).to have_content('This is a test project')
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
index 2d0e281ab59..99601e3d230 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
module QA
- context 'Create' do
+ # https://gitlab.com/gitlab-org/quality/staging/issues/40
+ context 'Create', :quarantine do
describe 'Push mirror a repository over HTTP' do
- it 'configures and syncs a (push) mirrored repository' do
+ it 'configures and syncs a (push) mirrored repository' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
@@ -20,8 +21,6 @@ module QA
end
source_project_push.project.visit!
- Page::Project::Show.perform(&:wait_for_push)
-
Page::Project::Menu.perform(&:click_repository_settings)
Page::Project::Settings::Repository.perform do |settings|
settings.expand_mirroring_repositories do |mirror_settings|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
new file mode 100644
index 00000000000..243f0b83b77
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module QA
+ # Failure issue: https://gitlab.com/gitlab-org/quality/staging/issues/37
+ context 'Create', :quarantine do
+ describe 'push after setting the file size limit via admin/application_settings' do
+ before(:all) do
+ push = Resource::Repository::ProjectPush.fabricate! do |p|
+ p.file_name = 'README.md'
+ p.file_content = '# This is a test project'
+ p.commit_message = 'Add README.md'
+ end
+
+ @project = push.project
+ end
+
+ before do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+ end
+
+ after(:all) do
+ # need to set the default value after test
+ # default value for file size limit is empty
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ set_file_size_limit('')
+ end
+
+ it 'push successful when the file size is under the limit' do
+ set_file_size_limit(5)
+ expect(page).to have_content("Application settings saved successfully")
+
+ push = push_new_file('oversize_file_1.bin', wait_for_push: true)
+ expect(push.output).not_to have_content 'remote: fatal: pack exceeds maximum allowed size'
+ end
+
+ it 'push fails when the file size is above the limit' do
+ set_file_size_limit(1)
+ expect(page).to have_content("Application settings saved successfully")
+
+ push = push_new_file('oversize_file_2.bin', wait_for_push: false)
+ expect(push.output).to have_content 'remote: fatal: pack exceeds maximum allowed size'
+ end
+
+ def set_file_size_limit(limit)
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_general_settings)
+
+ Page::Admin::Settings::General.perform do |setting|
+ setting.expand_account_and_limit do |page|
+ page.set_max_file_size(limit)
+ page.save_settings
+ end
+ end
+ end
+
+ def push_new_file(file_name, wait_for_push: true)
+ @project.visit!
+
+ Resource::Repository::ProjectPush.fabricate! do |p|
+ p.project = @project
+ p.file_name = file_name
+ p.file_content = SecureRandom.random_bytes(2000000)
+ p.commit_message = 'Adding a new file'
+ p.wait_for_push = wait_for_push
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
index ad6426df420..58e6c160a3a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
@@ -3,9 +3,9 @@
module QA
context 'Create' do
describe 'Git push over HTTP', :ldap_no_tls do
- it 'user pushes code to the repository' do
+ it 'user pushes code to the repository' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
project_push = Resource::Repository::ProjectPush.fabricate! do |push|
push.file_name = 'README.md'
@@ -13,7 +13,6 @@ module QA
push.commit_message = 'Add README.md'
end
project_push.project.visit!
- Page::Project::Show.act { wait_for_push }
expect(page).to have_content('README.md')
expect(page).to have_content('This is a test project')
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
index 73a3dc14a65..6aebd04af03 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
@@ -37,12 +37,7 @@ module QA
it 'user without push rights fails to push to the protected branch' do
create_protected_branch(allow_to_push: false)
- push = push_new_file(branch_name)
-
- expect(push.output)
- .to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/)
- expect(push.output)
- .to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/)
+ expect { push_new_file(branch_name) }.to raise_error(QA::Git::Repository::RepositoryCommandError, /remote: GitLab: You are not allowed to push code to protected branches on this project\.([\s\S]+)\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/)
end
end
@@ -63,6 +58,7 @@ module QA
resource.commit_message = 'Add new_file.md'
resource.branch_name = branch_name
resource.new_branch = false
+ resource.wait_for_push = false
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb
index 509a639c130..a8a00296881 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module QA
- context 'Create' do
+ # Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/84
+ context 'Create', :quarantine do
describe 'SSH key support' do
# Note: If you run this test against GDK make sure you've enabled sshd
# See: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md
@@ -10,7 +11,7 @@ module QA
it 'user adds an ssh key and pushes code to the repository' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
key = Resource::SSHKey.fabricate! do |resource|
resource.title = key_title
@@ -24,13 +25,12 @@ module QA
end
project_push.project.visit!
- Page::Project::Show.act { wait_for_push }
expect(page).to have_content('README.md')
expect(page).to have_content('Test Use SSH Key')
- Page::Main::Menu.act { go_to_profile_settings }
- Page::Profile::Menu.act { click_ssh_keys }
+ Page::Main::Menu.perform(&:go_to_profile_settings)
+ Page::Profile::Menu.perform(&:click_ssh_keys)
Page::Profile::SSHKeys.perform do |ssh_keys|
ssh_keys.remove_key(key_title)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
new file mode 100644
index 00000000000..b862a7bd1ed
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Create' do
+ # failure reported: https://gitlab.com/gitlab-org/quality/nightly/issues/42
+ # also failing in staging until the fix is picked into the next release:
+ # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24533
+ describe 'Commit data', :quarantine do
+ before(:context) do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ project_push = Resource::Repository::ProjectPush.fabricate! do |push|
+ push.file_name = 'README.md'
+ push.file_content = '# This is a test project'
+ push.commit_message = 'Add README.md'
+ end
+ @project = project_push.project
+
+ # first file added has no parent commit, thus no diff data
+ # add second file to repo to enable diff from initial commit
+ @commit_message = 'Add second file'
+
+ Page::Project::Show.perform(&:create_new_file!)
+ Page::File::Form.perform do |f|
+ f.add_name('second')
+ f.add_content('second file content')
+ f.add_commit_message(@commit_message)
+ f.commit_changes
+ end
+ end
+
+ def view_commit
+ @project.visit!
+ Page::Project::Show.perform do |page|
+ page.go_to_commit(@commit_message)
+ end
+ end
+
+ def raw_content
+ find('pre').text
+ end
+
+ it 'user views raw email patch' do
+ user = Resource::User.fabricate_via_api! do |user|
+ user.username = Runtime::User.username
+ end
+
+ view_commit
+
+ Page::Project::Commit::Show.perform(&:select_email_patches)
+
+ expect(page).to have_content("From: #{user.name} <#{user.public_email}>")
+ expect(page).to have_content('Subject: [PATCH] Add second file')
+ expect(page).to have_content('diff --git a/second b/second')
+ end
+
+ it 'user views raw commit diff' do
+ view_commit
+
+ Page::Project::Commit::Show.perform(&:select_plain_diff)
+
+ expect(raw_content).to start_with('diff --git a/second b/second')
+ expect(page).to have_content('+second file content')
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb
deleted file mode 100644
index 203338ddf77..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- context 'Create' do
- describe 'Commit data' do
- before(:context) do
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.perform(&:sign_in_using_credentials)
-
- project_push = Resource::Repository::ProjectPush.fabricate! do |push|
- push.file_name = 'README.md'
- push.file_content = '# This is a test project'
- push.commit_message = 'Add README.md'
- end
- @project = project_push.project
-
- # first file added has no parent commit, thus no diff data
- # add second file to repo to enable diff from initial commit
- @commit_message = 'Add second file'
-
- Page::Project::Show.perform(&:create_new_file!)
- Page::File::Form.perform do |f|
- f.add_name('second')
- f.add_content('second file content')
- f.add_commit_message(@commit_message)
- f.commit_changes
- end
- end
-
- def view_commit
- @project.visit!
- Page::Project::Show.perform do |page|
- page.go_to_commit(@commit_message)
- end
- end
-
- def raw_content
- find('pre').text
- end
-
- it 'user views raw email patch' do
- view_commit
-
- Page::Project::Commit::Show.perform(&:select_email_patches)
-
- expect(page).to have_content('From: Administrator <admin@example.com>')
- expect(page).to have_content('Subject: [PATCH] Add second file')
- expect(page).to have_content('diff --git a/second b/second')
- end
-
- it 'user views raw commit diff' do
- view_commit
-
- Page::Project::Commit::Show.perform(&:select_plain_diff)
-
- expect(raw_content).to start_with('diff --git a/second b/second')
- expect(page).to have_content('+second file content')
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb
index 210271705d9..29589ec870a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb
@@ -3,21 +3,15 @@
module QA
context 'Create' do
describe 'Wiki management' do
- def login
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
- end
-
def validate_content(content)
expect(page).to have_content('Wiki was successfully updated')
expect(page).to have_content(/#{content}/)
end
- before do
- login
- end
-
it 'user creates, edits, clones, and pushes to the wiki' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
wiki = Resource::Wiki.fabricate! do |resource|
resource.title = 'Home'
resource.content = '# My First Wiki Content'
@@ -26,7 +20,7 @@ module QA
validate_content('My First Wiki Content')
- Page::Project::Wiki::Edit.act { go_to_edit_page }
+ Page::Project::Wiki::Edit.perform(&:go_to_edit_page)
Page::Project::Wiki::New.perform do |page|
page.set_content("My Second Wiki Content")
page.save_changes
@@ -40,7 +34,7 @@ module QA
push.file_content = '# My Third Wiki Content'
push.commit_message = 'Update Home.md'
end
- Page::Project::Menu.act { click_wiki }
+ Page::Project::Menu.perform(&:click_wiki)
expect(page).to have_content('My Third Wiki Content')
end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
index 25cbe41c684..2238d6c382e 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
@@ -11,7 +11,7 @@ module QA
it 'users creates a pipeline which gets processed' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
project = Resource::Project.fabricate! do |project|
project.name = 'project-with-pipelines'
@@ -60,11 +60,9 @@ module QA
EOF
end
- Page::Project::Show.act { wait_for_push }
-
expect(page).to have_content('Add .gitlab-ci.yml')
- Page::Project::Menu.act { click_ci_cd_pipelines }
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
expect(page).to have_content('All 1')
expect(page).to have_content('Add .gitlab-ci.yml')
@@ -72,7 +70,7 @@ module QA
puts 'Waiting for the runner to process the pipeline'
sleep 15 # Runner should process all jobs within 15 seconds.
- Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
+ Page::Project::Pipeline::Index.perform(&:go_to_latest_pipeline)
Page::Project::Pipeline::Show.perform do |pipeline|
expect(pipeline).to be_running
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
index 84757f25379..aa01e5a618e 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
module QA
- context 'Release' do
+ # Failure issue: https://gitlab.com/gitlab-org/quality/staging/issues/26
+ context 'Release', :quarantine do
describe 'Deploy key creation' do
it 'user adds a deploy key' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
key = Runtime::Key::RSA.new
deploy_key_title = 'deploy key title'
@@ -16,7 +17,13 @@ module QA
resource.key = deploy_key_value
end
- expect(deploy_key.fingerprint).to eq(key.fingerprint)
+ expect(deploy_key.fingerprint).to eq key.fingerprint
+
+ Page::Project::Settings::Repository.perform do |setting|
+ setting.expand_deploy_keys do |keys|
+ expect(keys).to have_key(deploy_key_title, key.fingerprint)
+ end
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
index e2320c92343..3f65eabc756 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
@@ -3,11 +3,12 @@
require 'digest/sha1'
module QA
- context 'Release', :docker do
+ # Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/70
+ context 'Release', :docker, :quarantine do
describe 'Git clone using a deploy key' do
def login
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
end
before(:all) do
@@ -28,7 +29,7 @@ module QA
resource.image = 'gitlab/gitlab-runner:ubuntu'
end
- Page::Main::Menu.act { sign_out }
+ Page::Main::Menu.perform(&:sign_out)
end
after(:all) do
@@ -89,17 +90,12 @@ module QA
sha1sum = Digest::SHA1.hexdigest(gitlab_ci)
- Page::Project::Show.act { wait_for_push }
- Page::Project::Menu.act { click_ci_cd_pipelines }
- Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
- Page::Project::Pipeline::Show.act { go_to_first_job }
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Pipeline::Index.perform(&:go_to_latest_pipeline)
+ Page::Project::Pipeline::Show.perform(&:go_to_first_job)
Page::Project::Job::Show.perform do |job|
- job.wait(reload: false) do
- job.completed? && !job.trace_loading?
- end
-
- expect(job.passed?).to be_truthy, "Job status did not become \"passed\"."
+ expect(job).to be_successful
expect(job.output).to include(sha1sum)
end
end
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 b0c277a48c3..4212a2b0392 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
@@ -3,83 +3,193 @@
require 'pathname'
module QA
- context 'Configure', :orchestrated, :kubernetes do
- describe 'Auto DevOps support' do
- after do
- @cluster&.remove!
- end
+ # Transient failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/68
+ context 'Configure' do
+ def login
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+ end
- [true, false].each do |rbac|
- context "when rbac is #{rbac ? 'enabled' : 'disabled'}" do
- it 'user creates a new project and runs auto devops' do
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ describe 'Auto DevOps support', :orchestrated, :kubernetes, :quarantine do
+ context 'when rbac is enabled' do
+ before(:all) do
+ login
- project = Resource::Project.fabricate! do |p|
- p.name = Runtime::Env.auto_devops_project_name || 'project-with-autodevops'
- p.description = 'Project with Auto Devops'
- end
+ @project = Resource::Project.fabricate! do |p|
+ p.name = Runtime::Env.auto_devops_project_name || 'project-with-autodevops'
+ p.description = 'Project with Auto DevOps'
+ end
- # Disable code_quality check in Auto DevOps pipeline as it takes
- # too long and times out the test
- Resource::CiVariable.fabricate! do |resource|
- resource.project = project
- resource.key = 'CODE_QUALITY_DISABLED'
- resource.value = '1'
- end
+ # Disable code_quality check in Auto DevOps pipeline as it takes
+ # too long and times out the test
+ Resource::CiVariable.fabricate! do |resource|
+ resource.project = @project
+ resource.key = 'CODE_QUALITY_DISABLED'
+ resource.value = '1'
+ end
- # Create Auto Devops compatible repo
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = project
- push.directory = Pathname
- .new(__dir__)
- .join('../../../../../fixtures/auto_devops_rack')
- push.commit_message = 'Create Auto DevOps compatible rack application'
- end
+ # Create and connect K8s cluster
+ @cluster = Service::KubernetesCluster.new.create!
+ Resource::KubernetesCluster.fabricate! do |cluster|
+ cluster.project = @project
+ cluster.cluster = @cluster
+ cluster.install_helm_tiller = true
+ cluster.install_ingress = true
+ cluster.install_prometheus = true
+ cluster.install_runner = true
+ end
- Page::Project::Show.act { wait_for_push }
-
- # Create and connect K8s cluster
- @cluster = Service::KubernetesCluster.new(rbac: rbac).create!
- kubernetes_cluster = Resource::KubernetesCluster.fabricate! do |cluster|
- cluster.project = project
- cluster.cluster = @cluster
- cluster.install_helm_tiller = true
- cluster.install_ingress = true
- cluster.install_prometheus = true
- cluster.install_runner = true
- end
- kubernetes_cluster.populate(:ingress_ip)
+ # Create Auto DevOps compatible repo
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = @project
+ push.directory = Pathname
+ .new(__dir__)
+ .join('../../../../../fixtures/auto_devops_rack')
+ push.commit_message = 'Create Auto DevOps compatible rack application'
+ end
+ end
- project.visit!
- Page::Project::Menu.act { click_ci_cd_settings }
- Page::Project::Settings::CICD.perform do |p|
- p.enable_auto_devops_with_domain(
- "#{kubernetes_cluster.ingress_ip}.nip.io")
- end
+ after(:all) do
+ @cluster&.remove!
+ end
- project.visit!
- Page::Project::Menu.act { click_ci_cd_pipelines }
- Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
+ it 'runs auto devops' do
+ @project.visit!
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Pipeline::Index.perform(&:go_to_latest_pipeline)
- Page::Project::Pipeline::Show.perform do |pipeline|
- expect(pipeline).to have_build('build', status: :success, wait: 600)
- expect(pipeline).to have_build('test', status: :success, wait: 600)
- expect(pipeline).to have_build('production', status: :success, wait: 1200)
- end
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.go_to_job('build')
+ end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 600)
- Page::Project::Menu.act { click_operations_environments }
- Page::Project::Operations::Environments::Index.perform do |index|
- index.go_to_environment('production')
+ job.click_element(:pipeline_path)
+ end
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.go_to_job('test')
+ end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 600)
+
+ job.click_element(:pipeline_path)
+ end
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.go_to_job('production')
+ end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 1200)
+
+ job.click_element(:pipeline_path)
+ end
+
+ Page::Project::Menu.perform(&:click_operations_environments)
+ Page::Project::Operations::Environments::Index.perform do |index|
+ index.go_to_environment('production')
+ end
+ Page::Project::Operations::Environments::Show.perform do |show|
+ show.view_deployment do
+ expect(page).to have_content('Hello World!')
end
- Page::Project::Operations::Environments::Show.perform do |show|
- show.view_deployment do
- expect(page).to have_content('Hello World!')
- end
+ end
+ end
+
+ it 'user sets application secret variable and Auto DevOps passes it to container' do
+ # Set an application secret CI variable (prefixed with K8S_SECRET_)
+ Resource::CiVariable.fabricate! do |resource|
+ resource.project = @project
+ resource.key = 'K8S_SECRET_OPTIONAL_MESSAGE'
+ resource.value = 'You can see this application secret'
+ end
+
+ # Our current Auto DevOps implementation won't update the production
+ # app if we only update a CI variable with no code change.
+ #
+ # Workaround: push new code and use the resultant pipeline.
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = @project
+ push.commit_message = 'Force a Deployment change by pushing new code'
+ push.file_name = 'new_file.txt'
+ push.file_content = 'new file contents'
+ end
+
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Pipeline::Index.perform(&:go_to_latest_pipeline)
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.go_to_job('build')
+ end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 600)
+
+ job.click_element(:pipeline_path)
+ end
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.go_to_job('test')
+ end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 600)
+
+ job.click_element(:pipeline_path)
+ end
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.go_to_job('production')
+ end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 1200)
+ end
+
+ Page::Project::Menu.perform(&:click_operations_environments)
+
+ Page::Project::Operations::Environments::Index.perform do |index|
+ index.go_to_environment('production')
+ end
+
+ Page::Project::Operations::Environments::Show.perform do |show|
+ show.view_deployment do
+ expect(page).to have_content('Hello World!')
+ expect(page).to have_content('You can see this application secret')
end
end
end
end
end
+
+ describe 'Auto DevOps', :smoke do
+ it 'enables AutoDevOps by default' do
+ login
+
+ project = Resource::Project.fabricate! do |p|
+ p.name = Runtime::Env.auto_devops_project_name || 'project-with-autodevops'
+ p.description = 'Project with AutoDevOps'
+ end
+
+ project.visit!
+
+ Page::Alert::AutoDevopsAlert.perform do |alert|
+ expect(alert).to have_text(/.*The Auto DevOps pipeline has been enabled.*/)
+ end
+
+ # Create AutoDevOps repo
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = project
+ push.directory = Pathname
+ .new(__dir__)
+ .join('../../../../../fixtures/auto_devops_rack')
+ push.commit_message = 'Create AutoDevOps compatible Project'
+ end
+
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Pipeline::Index.perform(&:go_to_latest_pipeline)
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ expect(pipeline).to have_tag('Auto DevOps')
+ end
+ end
+ end
end
end
diff --git a/qa/qa/support/api.rb b/qa/qa/support/api.rb
index 1107d43161e..229bfb44fa5 100644
--- a/qa/qa/support/api.rb
+++ b/qa/qa/support/api.rb
@@ -20,6 +20,34 @@ module QA
e.response
end
+ def put(url, payload)
+ RestClient::Request.execute(
+ method: :put,
+ url: url,
+ payload: payload,
+ verify_ssl: false)
+ rescue RestClient::ExceptionWithResponse => e
+ e.response
+ end
+
+ def delete(url)
+ RestClient::Request.execute(
+ method: :delete,
+ url: url,
+ verify_ssl: false)
+ rescue RestClient::ExceptionWithResponse => e
+ e.response
+ end
+
+ def head(url)
+ RestClient::Request.execute(
+ method: :head,
+ url: url,
+ verify_ssl: false)
+ rescue RestClient::ExceptionWithResponse => e
+ e.response
+ end
+
def parse_body(response)
JSON.parse(response.body, symbolize_names: true)
end
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index df3b794b14b..69b6332ecce 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -10,15 +10,11 @@ module QA
super
end
- def wait(max: 60, time: 0.1, reload: true)
- log("with wait: max #{max}; time #{time}; reload #{reload}")
- now = Time.now
-
- element = super
-
- log("ended wait after #{Time.now - now} seconds")
+ def wait(max: 60, interval: 0.1, reload: true)
+ log("next wait uses reload: #{reload}")
+ # Logging of wait start/end/duration is handled by QA::Support::Waiter
- element
+ super
end
def scroll_to(selector, text: nil)
@@ -37,8 +33,11 @@ module QA
exists
end
- def find_element(name, wait: Capybara.default_max_wait_time)
- log("finding :#{name} (wait: #{wait})")
+ def find_element(name, text: nil, wait: Capybara.default_max_wait_time)
+ msg = ["finding :#{name}"]
+ msg << %Q(with text "#{text}") if text
+ msg << "(wait: #{wait})"
+ log(msg.compact.join(' '))
element = super
@@ -77,10 +76,31 @@ module QA
super
end
- def has_element?(name, wait: Capybara.default_max_wait_time)
+ def has_element?(name, text: nil, wait: Capybara.default_max_wait_time)
+ found = super
+
+ msg = ["has_element? :#{name}"]
+ msg << %Q(with text "#{text}") if text
+ msg << "(wait: #{wait})"
+ msg << "returned: #{found}"
+
+ log(msg.compact.join(' '))
+
+ found
+ end
+
+ def has_no_element?(name, wait: Capybara.default_max_wait_time)
found = super
- log("has_element? :#{name} returned #{found}")
+ log("has_no_element? :#{name} returned #{found}")
+
+ found
+ end
+
+ def has_text?(text)
+ found = super
+
+ log(%Q{has_text?('#{text}') returned #{found}})
found
end
@@ -93,6 +113,17 @@ module QA
found
end
+ def finished_loading?
+ log('waiting for loading to complete...')
+ now = Time.now
+
+ loaded = super
+
+ log("loading complete after #{Time.now - now} seconds")
+
+ loaded
+ end
+
def within_element(name)
log("within element :#{name}")
diff --git a/qa/qa/support/retrier.rb b/qa/qa/support/retrier.rb
new file mode 100644
index 00000000000..8be4e9f5365
--- /dev/null
+++ b/qa/qa/support/retrier.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module QA
+ module Support
+ module Retrier
+ module_function
+
+ def retry_on_exception(max_attempts: 3, reload_page: nil, sleep_interval: 0.5)
+ QA::Runtime::Logger.debug("with retry_on_exception: max_attempts #{max_attempts}; sleep_interval #{sleep_interval}")
+
+ attempts = 0
+
+ begin
+ QA::Runtime::Logger.debug("Attempt number #{attempts + 1}")
+ yield
+ rescue StandardError, RSpec::Expectations::ExpectationNotMetError
+ sleep sleep_interval
+ reload_page.refresh if reload_page
+ attempts += 1
+
+ retry if attempts < max_attempts
+ QA::Runtime::Logger.debug("Raising exception after #{max_attempts} attempts")
+ raise
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/support/waiter.rb b/qa/qa/support/waiter.rb
new file mode 100644
index 00000000000..21a399b4a5f
--- /dev/null
+++ b/qa/qa/support/waiter.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module QA
+ module Support
+ module Waiter
+ module_function
+
+ def wait(max: 60, interval: 0.1)
+ QA::Runtime::Logger.debug("with wait: max #{max}; interval #{interval}")
+ start = Time.now
+
+ while Time.now - start < max
+ result = yield
+ if result
+ log_end(Time.now - start)
+ return result
+ end
+
+ sleep(interval)
+ end
+ log_end(Time.now - start)
+
+ false
+ end
+
+ def self.log_end(duration)
+ QA::Runtime::Logger.debug("ended wait after #{duration} seconds")
+ end
+ end
+ end
+end
diff --git a/qa/qa/tools/delete_subgroups.rb b/qa/qa/tools/delete_subgroups.rb
new file mode 100644
index 00000000000..c5c48e77ade
--- /dev/null
+++ b/qa/qa/tools/delete_subgroups.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require_relative '../../qa'
+
+# This script deletes all subgroups of a group specified by ENV['GROUP_NAME_OR_PATH']
+# Required environment variables: PERSONAL_ACCESS_TOKEN and GITLAB_ADDRESS
+# Optional environment variable: GROUP_NAME_OR_PATH (defaults to 'gitlab-qa-sandbox-group')
+# Run `rake delete_subgroups`
+
+module QA
+ module Tools
+ class DeleteSubgroups
+ include Support::Api
+
+ def initialize
+ raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
+ raise ArgumentError, "Please provide PERSONAL_ACCESS_TOKEN" unless ENV['PERSONAL_ACCESS_TOKEN']
+
+ @api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['PERSONAL_ACCESS_TOKEN'])
+ end
+
+ def run
+ STDOUT.puts 'Running...'
+
+ # Fetch group's id
+ group_id = fetch_group_id
+
+ sub_groups_head_response = head Runtime::API::Request.new(@api_client, "/groups/#{group_id}/subgroups", per_page: "100").url
+ total_sub_groups = sub_groups_head_response.headers[:x_total]
+ total_sub_group_pages = sub_groups_head_response.headers[:x_total_pages]
+
+ STDOUT.puts "total_sub_groups: #{total_sub_groups}"
+ STDOUT.puts "total_sub_group_pages: #{total_sub_group_pages}"
+
+ total_sub_group_pages.to_i.times do |page_no|
+ # Fetch all subgroups for the top level group
+ sub_groups_response = get Runtime::API::Request.new(@api_client, "/groups/#{group_id}/subgroups", per_page: "100").url
+
+ sub_group_ids = JSON.parse(sub_groups_response.body).map { |subgroup| subgroup["id"] }
+
+ if sub_group_ids.any?
+ STDOUT.puts "\n==== Current Page: #{page_no + 1} ====\n"
+
+ delete_subgroups(sub_group_ids)
+ end
+ end
+ STDOUT.puts "\nDone"
+ end
+
+ private
+
+ def delete_subgroups(sub_group_ids)
+ sub_group_ids.each do |subgroup_id|
+ delete_response = delete Runtime::API::Request.new(@api_client, "/groups/#{subgroup_id}").url
+ dot_or_f = delete_response.code == 202 ? "\e[32m.\e[0m" : "\e[31mF\e[0m"
+ print dot_or_f
+ end
+ end
+
+ def fetch_group_id
+ group_search_response = get Runtime::API::Request.new(@api_client, "/groups", search: ENV['GROUP_NAME_OR_PATH'] || 'gitlab-qa-sandbox-group').url
+ JSON.parse(group_search_response.body).first["id"]
+ end
+ end
+ end
+end
diff --git a/qa/qa/tools/generate_perf_testdata.rb b/qa/qa/tools/generate_perf_testdata.rb
new file mode 100644
index 00000000000..ad515014794
--- /dev/null
+++ b/qa/qa/tools/generate_perf_testdata.rb
@@ -0,0 +1,141 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+require 'faker'
+require_relative '../../qa'
+# This script generates testdata for Performance Testing.
+# Required environment variables: PERSONAL_ACCESS_TOKEN and GITLAB_ADDRESS
+# This job creates a urls.txt which contains a hash of all the URLs needed for Performance Testing
+# Run `rake generate_perf_testdata`
+
+module QA
+ module Tools
+ class GeneratePerfTestdata
+ include Support::Api
+
+ def initialize
+ raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
+ raise ArgumentError, "Please provide PERSONAL_ACCESS_TOKEN" unless ENV['PERSONAL_ACCESS_TOKEN']
+
+ @api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['PERSONAL_ACCESS_TOKEN'])
+ @group_name = "gitlab-qa-perf-sandbox-#{SecureRandom.hex(8)}"
+ @project_name = "my-test-project-#{SecureRandom.hex(8)}"
+ @urls = {}
+ end
+
+ def run
+ STDOUT.puts 'Running...'
+ group_id = create_group
+ create_project(group_id)
+ create_branch
+ add_new_file
+ methods_arr = [
+ method(:create_issues),
+ method(:create_todos),
+ method(:create_merge_requests),
+ method(:create_issue_with_500_discussions),
+ method(:create_mr_with_large_files)
+ ]
+ threads_arr = []
+
+ methods_arr.each do |m|
+ threads_arr << Thread.new {m.call}
+ end
+
+ threads_arr.each(&:join)
+ STDOUT.puts "\nURLs: #{@urls}"
+ File.open("urls.txt", "w") { |file| file.puts @urls.to_s}
+ STDOUT.puts "\nDone"
+ end
+
+ private
+
+ def create_group
+ group_search_response = post Runtime::API::Request.new(@api_client, "/groups").url, "name=#{@group_name}&path=#{@group_name}"
+ group = JSON.parse(group_search_response.body)
+ @urls[:group_page] = group["web_url"]
+ group["id"]
+ end
+
+ def create_project(group_id)
+ create_project_response = post Runtime::API::Request.new(@api_client, "/projects").url, "name=#{@project_name}&namespace_id=#{group_id}"
+ @urls[:project_page] = JSON.parse(create_project_response.body)["web_url"]
+ end
+
+ def create_issues
+ 30.times do |i|
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/issues").url, "title=issue#{i}&description=desc#{i}"
+ end
+ @urls[:issues_list_page] = @urls[:project_page] + "/issues"
+ STDOUT.puts "Created Issues"
+ end
+
+ def create_todos
+ 30.times do |i|
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/issues/#{i + 1}/todo").url, nil
+ end
+ @urls[:todos_page] = ENV['GITLAB_ADDRESS'] + "/dashboard/todos"
+ STDOUT.puts "Created todos"
+ end
+
+ def create_merge_requests
+ 30.times do |i|
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/merge_requests").url, "source_branch=branch#{i}&target_branch=master&title=MR#{i}"
+ end
+ @urls[:mr_list_page] = @urls[:project_page] + "/merge_requests"
+ STDOUT.puts "Created MRs"
+ end
+
+ def add_new_file
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/files/hello.txt").url, "branch=master&commit_message=\"hello\"&content=\"my new content\""
+ 30.times do |i|
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/files/hello#{i}.txt").url, "branch=branch#{i}&commit_message=\"hello\"&content=\"my new content\""
+ end
+ STDOUT.puts "Added Files"
+ end
+
+ def create_branch
+ 30.times do |i|
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/branches").url, "branch=branch#{i}&ref=master"
+ end
+ STDOUT.puts "Created branches"
+ end
+
+ def create_issue_with_500_discussions
+ issue_id = 1
+ 500.times do
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/issues/#{issue_id}/discussions").url, "body=\"Let us discuss\""
+ end
+ @urls[:large_issue] = @urls[:project_page] + "/issues/#{issue_id}"
+ STDOUT.puts "Created Issue with 500 Discussions"
+ end
+
+ def create_mr_with_large_files
+ content_arr = []
+ 20.times do |i|
+ faker_line_arr = Faker::Lorem.sentences(1500)
+ content = faker_line_arr.join("\n\r")
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/files/hello#{i}.txt").url, "branch=master&commit_message=\"Add hello#{i}.txt\"&content=#{content}"
+ content_arr[i] = faker_line_arr
+ end
+
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/branches").url, "branch=performance&ref=master"
+
+ 20.times do |i|
+ missed_line_array = content_arr[i].each_slice(2).map(&:first)
+ content = missed_line_array.join("\n\rIm new!:D \n\r ")
+ put Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/files/hello#{i}.txt").url, "branch=performance&commit_message=\"Update hello#{i}.txt\"&content=#{content}"
+ end
+
+ create_mr_response = post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/merge_requests").url, "source_branch=performance&target_branch=master&title=Large_MR"
+
+ iid = JSON.parse(create_mr_response.body)["iid"]
+ 500.times do
+ post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/merge_requests/#{iid}/discussions").url, "body=\"Let us discuss\""
+ end
+ @urls[:large_mr] = JSON.parse(create_mr_response.body)["web_url"]
+ STDOUT.puts "Created MR with 500 Discussions and 20 Very Large Files"
+ end
+ end
+ end
+end
diff --git a/qa/qa/tools/revoke_all_personal_access_tokens.rb b/qa/qa/tools/revoke_all_personal_access_tokens.rb
new file mode 100644
index 00000000000..7484b633bf6
--- /dev/null
+++ b/qa/qa/tools/revoke_all_personal_access_tokens.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require_relative '../../qa'
+require 'net/protocol.rb'
+# This script revokes all personal access tokens with the name of 'api-test-token' on the host specified by GITLAB_ADDRESS
+# Required environment variables: GITLAB_USERNAME, GITLAB_PASSWORD and GITLAB_ADDRESS
+# Run `rake revoke_personal_access_tokens`
+
+module QA
+ module Tools
+ class RevokeAllPersonalAccessTokens
+ def run
+ do_run
+ rescue Net::ReadTimeout
+ STDOUT.puts 'Net::ReadTimeout during run. Trying again'
+ run
+ end
+
+ private
+
+ def do_run
+ raise ArgumentError, "Please provide GITLAB_USERNAME" unless ENV['GITLAB_USERNAME']
+ raise ArgumentError, "Please provide GITLAB_PASSWORD" unless ENV['GITLAB_PASSWORD']
+ raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
+
+ STDOUT.puts 'Running...'
+
+ Runtime::Browser.visit(ENV['GITLAB_ADDRESS'], Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+ Page::Main::Menu.perform(&:go_to_profile_settings)
+ Page::Profile::Menu.perform(&:click_access_tokens)
+
+ token_name = 'api-test-token'
+
+ Page::Profile::PersonalAccessTokens.perform do |page|
+ while page.has_token_row_for_name?(token_name)
+ page.revoke_first_token_with_name(token_name)
+ print "\e[32m.\e[0m"
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/github/page/base.rb b/qa/qa/vendor/github/page/base.rb
new file mode 100644
index 00000000000..3b96180afe9
--- /dev/null
+++ b/qa/qa/vendor/github/page/base.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module Github
+ module Page
+ class Base
+ include Capybara::DSL
+ include Scenario::Actable
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/github/page/login.rb b/qa/qa/vendor/github/page/login.rb
new file mode 100644
index 00000000000..6d8f9aa7c12
--- /dev/null
+++ b/qa/qa/vendor/github/page/login.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'capybara/dsl'
+
+module QA
+ module Vendor
+ module Github
+ module Page
+ class Login < Page::Base
+ def login
+ fill_in 'login', with: QA::Runtime::Env.github_username
+ fill_in 'password', with: QA::Runtime::Env.github_password
+ click_on 'Sign in'
+
+ unless has_no_text?("Authorize GitLab-OAuth")
+ click_on 'Authorize gitlab-qa' if has_button?('Authorize gitlab-qa')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/spec/git/repository_spec.rb b/qa/spec/git/repository_spec.rb
index faa154c78da..0ded33a73a2 100644
--- a/qa/spec/git/repository_spec.rb
+++ b/qa/spec/git/repository_spec.rb
@@ -1,69 +1,119 @@
describe QA::Git::Repository do
- include Support::StubENV
+ include Helpers::StubENV
- let(:repository) { described_class.new }
+ shared_context 'git directory' do
+ let(:repository) { described_class.new }
+ let(:tmp_git_dir) { Dir.mktmpdir }
+ let(:tmp_netrc_dir) { Dir.mktmpdir }
- before do
- stub_env('GITLAB_USERNAME', 'root')
- cd_empty_temp_directory
- set_bad_uri
- repository.use_default_credentials
- end
+ before do
+ stub_env('GITLAB_USERNAME', 'root')
+ cd_empty_temp_directory
+ set_bad_uri
- describe '#clone' do
- it 'is unable to resolve host' do
- expect(repository.clone).to include("fatal: unable to access 'http://root@foo/bar.git/'")
+ allow(repository).to receive(:tmp_home_dir).and_return(tmp_netrc_dir)
end
- end
- describe '#push_changes' do
- before do
- `git init` # need a repo to push from
+ after do
+ # Switch to a safe dir before deleting tmp dirs to avoid dir access errors
+ FileUtils.cd __dir__
+ FileUtils.remove_entry_secure(tmp_git_dir, true)
+ FileUtils.remove_entry_secure(tmp_netrc_dir, true)
end
- it 'fails to push changes' do
- expect(repository.push_changes).to include("error: failed to push some refs to 'http://root@foo/bar.git'")
+ def cd_empty_temp_directory
+ FileUtils.cd tmp_git_dir
+ end
+
+ def set_bad_uri
+ repository.uri = 'http://foo/bar.git'
end
end
- describe '#git_protocol=' do
- [0, 1, 2].each do |version|
- it "configures git to use protocol version #{version}" do
- expect(repository).to receive(:run).with("git config protocol.version #{version}")
- repository.git_protocol = version
+ context 'with default credentials' do
+ include_context 'git directory' do
+ before do
+ repository.use_default_credentials
end
end
- it 'raises an error if the version is unsupported' do
- expect { repository.git_protocol = 'foo' }.to raise_error(ArgumentError, "Please specify the protocol you would like to use: 0, 1, or 2")
+ describe '#clone' do
+ it 'is unable to resolve host' do
+ expect { repository.clone }.to raise_error(described_class::RepositoryCommandError, /The command .* failed \(128\) with the following output/)
+ end
end
- end
- describe '#fetch_supported_git_protocol' do
- it "reports the detected version" do
- expect(repository).to receive(:run).and_return("packet: git< version 2")
- expect(repository.fetch_supported_git_protocol).to eq('2')
+ describe '#push_changes' do
+ before do
+ `git init` # need a repo to push from
+ end
+
+ it 'fails to push changes' do
+ expect { repository.push_changes }.to raise_error(described_class::RepositoryCommandError, /The command .* failed \(1\) with the following output/)
+ end
end
- it 'reports unknown if version is unknown' do
- expect(repository).to receive(:run).and_return("packet: git< version -1")
- expect(repository.fetch_supported_git_protocol).to eq('unknown')
+ describe '#git_protocol=' do
+ [0, 1, 2].each do |version|
+ it "configures git to use protocol version #{version}" do
+ expect(repository).to receive(:run).with("git config protocol.version #{version}")
+ repository.git_protocol = version
+ end
+ end
+
+ it 'raises an error if the version is unsupported' do
+ expect { repository.git_protocol = 'foo' }.to raise_error(ArgumentError, "Please specify the protocol you would like to use: 0, 1, or 2")
+ end
end
- it 'reports unknown if content does not identify a version' do
- expect(repository).to receive(:run).and_return("foo")
- expect(repository.fetch_supported_git_protocol).to eq('unknown')
+ describe '#fetch_supported_git_protocol' do
+ it "reports the detected version" do
+ expect(repository).to receive(:run).and_return("packet: git< version 2")
+ expect(repository.fetch_supported_git_protocol).to eq('2')
+ end
+
+ it 'reports unknown if version is unknown' do
+ expect(repository).to receive(:run).and_return("packet: git< version -1")
+ expect(repository.fetch_supported_git_protocol).to eq('unknown')
+ end
+
+ it 'reports unknown if content does not identify a version' do
+ expect(repository).to receive(:run).and_return("foo")
+ expect(repository.fetch_supported_git_protocol).to eq('unknown')
+ end
end
- end
- def cd_empty_temp_directory
- tmp_dir = 'tmp/git-repository-spec/'
- FileUtils.rm_rf(tmp_dir) if ::File.exist?(tmp_dir)
- FileUtils.mkdir_p tmp_dir
- FileUtils.cd tmp_dir
+ describe '#use_default_credentials' do
+ it 'adds credentials to .netrc' do
+ expect(File.read(File.join(tmp_netrc_dir, '.netrc')))
+ .to eq("machine foo login #{QA::Runtime::User.default_username} password #{QA::Runtime::User.default_password}\n")
+ end
+ end
end
- def set_bad_uri
- repository.uri = 'http://foo/bar.git'
+ context 'with specific credentials' do
+ include_context 'git directory'
+
+ context 'before setting credentials' do
+ it 'does not add credentials to .netrc' do
+ expect(repository).not_to receive(:save_netrc_content)
+ end
+ end
+
+ describe '#password=' do
+ it 'raises an error if no username was given' do
+ expect { repository.password = 'foo' }
+ .to raise_error(QA::Git::Repository::InvalidCredentialsError,
+ "Please provide a username when setting a password")
+ end
+
+ it 'adds credentials to .netrc' do
+ repository.username = 'user'
+ repository.password = 'foo'
+
+ expect(File.read(File.join(tmp_netrc_dir, '.netrc')))
+ .to eq("machine foo login user password foo\n")
+ end
+ end
end
end
diff --git a/qa/spec/helpers/stub_env.rb b/qa/spec/helpers/stub_env.rb
new file mode 100644
index 00000000000..62b4a1df787
--- /dev/null
+++ b/qa/spec/helpers/stub_env.rb
@@ -0,0 +1,40 @@
+# Inspired by https://github.com/ljkbennett/stub_env/blob/master/lib/stub_env/helpers.rb
+module Helpers
+ module StubENV
+ def stub_env(key_or_hash, value = nil)
+ init_stub unless env_stubbed?
+
+ if key_or_hash.is_a? Hash
+ key_or_hash.each { |k, v| add_stubbed_value(k, v) }
+ else
+ add_stubbed_value key_or_hash, value
+ end
+ end
+
+ private
+
+ STUBBED_KEY = '__STUBBED__'.freeze
+
+ def add_stubbed_value(key, value)
+ allow(ENV).to receive(:[]).with(key).and_return(value)
+ allow(ENV).to receive(:key?).with(key).and_return(true)
+ allow(ENV).to receive(:fetch).with(key).and_return(value)
+ allow(ENV).to receive(:fetch).with(key, anything) do |_, default_val|
+ value || default_val
+ end
+ end
+
+ def env_stubbed?
+ ENV[STUBBED_KEY]
+ end
+
+ def init_stub
+ allow(ENV).to receive(:[]).and_call_original
+ allow(ENV).to receive(:key?).and_call_original
+ allow(ENV).to receive(:fetch).and_call_original
+ # Prevent secrets from leaking in CI
+ allow(ENV).to receive(:inspect).and_return([])
+ add_stubbed_value(STUBBED_KEY, true)
+ end
+ end
+end
diff --git a/qa/spec/page/base_spec.rb b/qa/spec/page/base_spec.rb
index 076a8087db5..32a350f2154 100644
--- a/qa/spec/page/base_spec.rb
+++ b/qa/spec/page/base_spec.rb
@@ -59,4 +59,34 @@ describe QA::Page::Base do
end
end
end
+
+ describe '#wait' do
+ subject { Class.new(described_class).new }
+
+ context 'when the condition is true' do
+ it 'does not refresh' do
+ expect(subject).not_to receive(:refresh)
+
+ subject.wait(max: 0.01) { true }
+ end
+
+ it 'returns true' do
+ expect(subject.wait(max: 0.1) { true }).to be_truthy
+ end
+ end
+
+ context 'when the condition is false' do
+ it 'refreshes' do
+ expect(subject).to receive(:refresh).at_least(:once)
+
+ subject.wait(max: 0.01) { false }
+ end
+
+ it 'returns false' do
+ allow(subject).to receive(:refresh)
+
+ expect(subject.wait(max: 0.01) { false }).to be_falsey
+ end
+ end
+ end
end
diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb
index a54ff424f53..707a7ff6d98 100644
--- a/qa/spec/page/logging_spec.rb
+++ b/qa/spec/page/logging_spec.rb
@@ -1,14 +1,13 @@
# frozen_string_literal: true
require 'capybara/dsl'
+require 'logger'
describe QA::Support::Page::Logging do
- include Support::StubENV
-
- let(:page) { double().as_null_object }
+ let(:page) { double.as_null_object }
before do
- logger = Logger.new $stdout
+ logger = ::Logger.new $stdout
logger.level = ::Logger::DEBUG
QA::Runtime::Logger.logger = logger
@@ -30,11 +29,22 @@ describe QA::Support::Page::Logging do
it 'logs wait' do
expect { subject.wait(max: 0) {} }
+ .to output(/next wait uses reload: true/).to_stdout_from_any_process
+ expect { subject.wait(max: 0) {} }
.to output(/with wait/).to_stdout_from_any_process
expect { subject.wait(max: 0) {} }
.to output(/ended wait after .* seconds$/).to_stdout_from_any_process
end
+ it 'logs wait with reload false' do
+ expect { subject.wait(max: 0, reload: false) {} }
+ .to output(/next wait uses reload: false/).to_stdout_from_any_process
+ expect { subject.wait(max: 0, reload: false) {} }
+ .to output(/with wait/).to_stdout_from_any_process
+ expect { subject.wait(max: 0, reload: false) {} }
+ .to output(/ended wait after .* seconds$/).to_stdout_from_any_process
+ end
+
it 'logs scroll_to' do
expect { subject.scroll_to(:element) }
.to output(/scrolling to :element/).to_stdout_from_any_process
@@ -47,6 +57,15 @@ describe QA::Support::Page::Logging do
it 'logs find_element' do
expect { subject.find_element(:element) }
+ .to output(/finding :element/).to_stdout_from_any_process
+ expect { subject.find_element(:element) }
+ .to output(/found :element/).to_stdout_from_any_process
+ end
+
+ it 'logs find_element with text' do
+ expect { subject.find_element(:element, text: 'foo') }
+ .to output(/finding :element with text "foo"/).to_stdout_from_any_process
+ expect { subject.find_element(:element, text: 'foo') }
.to output(/found :element/).to_stdout_from_any_process
end
@@ -62,7 +81,26 @@ describe QA::Support::Page::Logging do
it 'logs has_element?' do
expect { subject.has_element?(:element) }
- .to output(/has_element\? :element returned true/).to_stdout_from_any_process
+ .to output(/has_element\? :element \(wait: 2\) returned: true/).to_stdout_from_any_process
+ end
+
+ it 'logs has_element? with text' do
+ expect { subject.has_element?(:element, text: "some text") }
+ .to output(/has_element\? :element with text \"some text\" \(wait: 2\) returned: true/).to_stdout_from_any_process
+ end
+
+ it 'logs has_no_element?' do
+ allow(page).to receive(:has_no_css?).and_return(true)
+
+ expect { subject.has_no_element?(:element) }
+ .to output(/has_no_element\? :element returned true/).to_stdout_from_any_process
+ end
+
+ it 'logs has_text?' do
+ allow(page).to receive(:has_text?).and_return(true)
+
+ expect { subject.has_text? 'foo' }
+ .to output(/has_text\?\('foo'\) returned true/).to_stdout_from_any_process
end
it 'logs has_no_text?' do
@@ -72,6 +110,13 @@ describe QA::Support::Page::Logging do
.to output(/has_no_text\?\('foo'\) returned true/).to_stdout_from_any_process
end
+ it 'logs finished_loading?' do
+ expect { subject.finished_loading? }
+ .to output(/waiting for loading to complete\.\.\./).to_stdout_from_any_process
+ expect { subject.finished_loading? }
+ .to output(/loading complete after .* seconds$/).to_stdout_from_any_process
+ end
+
it 'logs within_element' do
expect { subject.within_element(:element) }
.to output(/within element :element/).to_stdout_from_any_process
diff --git a/qa/spec/resource/base_spec.rb b/qa/spec/resource/base_spec.rb
index dc9e16792d3..4a6b76c869f 100644
--- a/qa/spec/resource/base_spec.rb
+++ b/qa/spec/resource/base_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
describe QA::Resource::Base do
- include Support::StubENV
+ include Helpers::StubENV
let(:resource) { spy('resource') }
let(:location) { 'http://location' }
@@ -138,10 +138,6 @@ describe QA::Resource::Base do
describe '.attribute' do
include_context 'simple resource'
- it 'appends new attribute' do
- expect(subject.attributes_names).to eq([:no_block, :test, :web_url])
- end
-
context 'when the attribute is populated via a block' do
it 'returns value from the block' do
result = subject.fabricate!(resource: resource)
@@ -217,6 +213,42 @@ describe QA::Resource::Base do
.to raise_error(described_class::NoValueError, "No value was computed for no_block of #{resource.class.name}.")
end
end
+
+ context 'when multiple resources have the same attribute name' do
+ let(:base) do
+ Class.new(QA::Resource::Base) do
+ def fabricate!
+ 'any'
+ end
+
+ def self.current_url
+ 'http://stub'
+ end
+ end
+ end
+ let(:first_resource) do
+ Class.new(base) do
+ attribute :test do
+ 'first block'
+ end
+ end
+ end
+ let(:second_resource) do
+ Class.new(base) do
+ attribute :test do
+ 'second block'
+ end
+ end
+ end
+
+ it 'has unique attribute values' do
+ first_result = first_resource.fabricate!(resource: first_resource.new)
+ second_result = second_resource.fabricate!(resource: second_resource.new)
+
+ expect(first_result.test).to eq 'first block'
+ expect(second_result.test).to eq 'second block'
+ end
+ end
end
describe '#web_url' do
diff --git a/qa/spec/resource/events/base_spec.rb b/qa/spec/resource/events/base_spec.rb
new file mode 100644
index 00000000000..9cdf4785092
--- /dev/null
+++ b/qa/spec/resource/events/base_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+describe QA::Resource::Events::Base do
+ let(:resource) do
+ Class.new(QA::Resource::Base) do
+ def api_get_path
+ '/foo'
+ end
+ end
+ end
+
+ subject { resource.tap { |f| f.include(described_class) }.new }
+
+ describe "#events" do
+ it 'fetches all events when called without parameters' do
+ allow(subject).to receive(:parse_body).and_return('returned')
+
+ expect(subject).to receive(:api_get_from).with('/foo/events')
+ expect(subject.events).to eq('returned')
+ end
+
+ it 'fetches events with a specified action type' do
+ allow(subject).to receive(:parse_body).and_return('returned')
+
+ expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed')
+ expect(subject.events(action: 'pushed')).to eq('returned')
+ end
+ end
+end
diff --git a/qa/spec/resource/events/project_spec.rb b/qa/spec/resource/events/project_spec.rb
new file mode 100644
index 00000000000..b3efdb518f3
--- /dev/null
+++ b/qa/spec/resource/events/project_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+describe QA::Resource::Events::Project do
+ let(:resource) do
+ Class.new(QA::Resource::Base) do
+ def api_get_path
+ '/foo'
+ end
+ end
+ end
+ let(:all_events) do
+ [
+ {
+ "action_name": "pushed",
+ "push_data": {
+ "commit_title": "foo commit"
+ }
+ },
+ {
+ "action_name": "pushed",
+ "push_data": {
+ "ref": "master"
+ }
+ },
+ {
+ "action_name": "pushed",
+ "push_data": {
+ "ref": "another-branch"
+ }
+ }
+ ]
+ end
+
+ before do
+ allow(subject).to receive(:max_wait).and_return(0.01)
+ allow(subject).to receive(:parse_body).and_return(all_events)
+ end
+
+ subject { resource.tap { |f| f.include(described_class) }.new }
+
+ describe "#wait_for_push" do
+ it 'waits for a push with a specified commit message' do
+ expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed')
+ expect { subject.wait_for_push('foo commit') }.not_to raise_error
+ end
+
+ it 'raises an error if a push with the specified commit message is not found' do
+ expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed').at_least(:once)
+ expect { subject.wait_for_push('bar') }.to raise_error(QA::Resource::Events::EventNotFoundError)
+ end
+ end
+
+ describe "#wait_for_push_new_branch" do
+ it 'waits for a push to master if no branch is given' do
+ expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed')
+ expect { subject.wait_for_push_new_branch }.not_to raise_error
+ end
+
+ it 'waits for a push to the given branch' do
+ expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed')
+ expect { subject.wait_for_push_new_branch('another-branch') }.not_to raise_error
+ end
+
+ it 'raises an error if a push with the specified branch is not found' do
+ expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed').at_least(:once)
+ expect { subject.wait_for_push_new_branch('bar') }.to raise_error(QA::Resource::Events::EventNotFoundError)
+ end
+ end
+end
diff --git a/qa/spec/resource/user_spec.rb b/qa/spec/resource/user_spec.rb
new file mode 100644
index 00000000000..d612dfc530e
--- /dev/null
+++ b/qa/spec/resource/user_spec.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+describe QA::Resource::User do
+ let(:api_resource) do
+ {
+ name: "GitLab QA",
+ username: "gitlab-qa",
+ web_url: "https://staging.gitlab.com/gitlab-qa",
+ public_email: "1614863-gitlab-qa@users.noreply.staging.gitlab.com"
+ }
+ end
+
+ describe '#username' do
+ it 'generates a default username' do
+ expect(subject.username).to match(/qa-user-\w+/)
+ end
+
+ it 'is possible to set the username' do
+ subject.username = 'johndoe'
+
+ expect(subject.username).to eq('johndoe')
+ end
+ end
+
+ describe '#password' do
+ it 'generates a default password' do
+ expect(subject.password).to eq('password')
+ end
+
+ it 'is possible to set the password' do
+ subject.password = 'secret'
+
+ expect(subject.password).to eq('secret')
+ end
+ end
+
+ describe '#name' do
+ it 'defaults to the username' do
+ expect(subject.name).to eq(subject.username)
+ end
+
+ it 'retrieves the name from the api_resource if present' do
+ subject.__send__(:api_resource=, api_resource)
+
+ expect(subject.name).to eq(api_resource[:name])
+ end
+
+ it 'is possible to set the name' do
+ subject.name = 'John Doe'
+
+ expect(subject.name).to eq('John Doe')
+ end
+ end
+
+ describe '#email' do
+ it 'defaults to the <username>@example.com' do
+ expect(subject.email).to eq("#{subject.username}@example.com")
+ end
+
+ it 'is possible to set the email' do
+ subject.email = 'johndoe@example.org'
+
+ expect(subject.email).to eq('johndoe@example.org')
+ end
+ end
+
+ describe '#public_email' do
+ it 'defaults to QA::Runtime::User.default_email' do
+ expect(subject.public_email).to eq(QA::Runtime::User.default_email)
+ end
+
+ it 'retrieves the public_email from the api_resource if present' do
+ subject.__send__(:api_resource=, api_resource)
+
+ expect(subject.public_email).to eq(api_resource[:public_email])
+ end
+
+ it 'defaults to QA::Runtime::User.default_email if the public_email from the api_resource is blank' do
+ subject.__send__(:api_resource=, api_resource.merge(public_email: ''))
+
+ expect(subject.public_email).to eq(QA::Runtime::User.default_email)
+ end
+ end
+
+ describe '#credentials_given?' do
+ it 'returns false when username and email have not been overridden' do
+ expect(subject).not_to be_credentials_given
+ end
+
+ it 'returns false even after username and email have been called' do
+ # Call #username and #password to ensure this doesn't set their respective
+ # instance variable.
+ subject.username
+ subject.password
+
+ expect(subject).not_to be_credentials_given
+ end
+
+ it 'returns false if only the username has been overridden' do
+ subject.username = 'johndoe'
+
+ expect(subject).not_to be_credentials_given
+ end
+
+ it 'returns false if only the password has been overridden' do
+ subject.password = 'secret'
+
+ expect(subject).not_to be_credentials_given
+ end
+
+ it 'returns true if both the username and password have been overridden' do
+ subject.username = 'johndoe'
+ subject.password = 'secret'
+
+ expect(subject).to be_credentials_given
+ end
+ end
+end
diff --git a/qa/spec/runtime/api/client_spec.rb b/qa/spec/runtime/api/client_spec.rb
index 975586b505f..af43facc73d 100644
--- a/qa/spec/runtime/api/client_spec.rb
+++ b/qa/spec/runtime/api/client_spec.rb
@@ -1,5 +1,5 @@
describe QA::Runtime::API::Client do
- include Support::StubENV
+ include Helpers::StubENV
describe 'initialization' do
it 'defaults to :gitlab address' do
diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb
index ded51d5bb7c..fc51f45c3a1 100644
--- a/qa/spec/runtime/env_spec.rb
+++ b/qa/spec/runtime/env_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
describe QA::Runtime::Env do
- include Support::StubENV
+ include Helpers::StubENV
shared_examples 'boolean method' do |**kwargs|
it_behaves_like 'boolean method with parameter', kwargs
@@ -207,4 +207,63 @@ describe QA::Runtime::Env do
expect { described_class.can_test? :foo }.to raise_error(ArgumentError, 'Unknown feature "foo"')
end
end
+
+ describe 'remote grid credentials' do
+ it 'is blank if username is empty' do
+ stub_env('QA_REMOTE_GRID_USERNAME', nil)
+
+ expect(described_class.send(:remote_grid_credentials)).to eq('')
+ end
+
+ it 'throws ArgumentError if GRID_ACCESS_KEY is not specified with USERNAME' do
+ stub_env('QA_REMOTE_GRID_USERNAME', 'foo')
+
+ expect { described_class.send(:remote_grid_credentials) }.to raise_error(ArgumentError, 'Please provide an access key for user "foo"')
+ end
+
+ it 'returns a user:key@ combination when all args are satiated' do
+ stub_env('QA_REMOTE_GRID_USERNAME', 'foo')
+ stub_env('QA_REMOTE_GRID_ACCESS_KEY', 'bar')
+
+ expect(described_class.send(:remote_grid_credentials)).to eq('foo:bar@')
+ end
+ end
+
+ describe '.remote_grid_protocol' do
+ it 'defaults protocol to http' do
+ stub_env('QA_REMOTE_GRID_PROTOCOL', nil)
+ expect(described_class.remote_grid_protocol).to eq('http')
+ end
+ end
+
+ describe '.remote_grid' do
+ it 'is falsey if QA_REMOTE_GRID is not set' do
+ expect(described_class.remote_grid).to be_falsey
+ end
+
+ it 'accepts https protocol' do
+ stub_env('QA_REMOTE_GRID', 'localhost:4444')
+ stub_env('QA_REMOTE_GRID_PROTOCOL', 'https')
+
+ expect(described_class.remote_grid).to eq('https://localhost:4444/wd/hub')
+ end
+
+ context 'with credentials' do
+ it 'has a grid of http://user:key@grid/wd/hub' do
+ stub_env('QA_REMOTE_GRID_USERNAME', 'foo')
+ stub_env('QA_REMOTE_GRID_ACCESS_KEY', 'bar')
+ stub_env('QA_REMOTE_GRID', 'localhost:4444')
+
+ expect(described_class.remote_grid).to eq('http://foo:bar@localhost:4444/wd/hub')
+ end
+ end
+
+ context 'without credentials' do
+ it 'has a grid of http://grid/wd/hub' do
+ stub_env('QA_REMOTE_GRID', 'localhost:4444')
+
+ expect(described_class.remote_grid).to eq('http://localhost:4444/wd/hub')
+ end
+ end
+ end
end
diff --git a/qa/spec/scenario/test/integration/oauth_spec.rb b/qa/spec/scenario/test/integration/oauth_spec.rb
new file mode 100644
index 00000000000..c1c320be576
--- /dev/null
+++ b/qa/spec/scenario/test/integration/oauth_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+describe QA::Scenario::Test::Integration::OAuth do
+ context '#perform' do
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:oauth] }
+ end
+ end
+end
diff --git a/qa/spec/support/shared_examples/scenario_shared_examples.rb b/qa/spec/shared_examples/scenario_shared_examples.rb
index 5fd55d7d96b..5fd55d7d96b 100644
--- a/qa/spec/support/shared_examples/scenario_shared_examples.rb
+++ b/qa/spec/shared_examples/scenario_shared_examples.rb
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 8e01da01340..cbdd6e881b1 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -1,10 +1,21 @@
require_relative '../qa'
+require 'rspec/retry'
-Dir[::File.join(__dir__, 'support', '**', '*.rb')].each { |f| require f }
+%w[helpers shared_examples].each do |d|
+ Dir[::File.join(__dir__, d, '**', '*.rb')].each { |f| require f }
+end
RSpec.configure do |config|
+ config.before(:context) do
+ if self.class.metadata.keys.include?(:quarantine)
+ skip_or_run_quarantined_tests(self.class.metadata.keys, config.inclusion_filter.rules.keys)
+ end
+ end
+
config.before do |example|
QA::Runtime::Logger.debug("Starting test: #{example.full_description}") if QA::Runtime::Env.debug?
+
+ skip_or_run_quarantined_tests(example.metadata.keys, config.inclusion_filter.rules.keys)
end
config.expect_with :rspec do |expectations|
@@ -21,4 +32,54 @@ RSpec.configure do |config|
config.profile_examples = 10
config.order = :random
Kernel.srand config.seed
+
+ # show retry status in spec process
+ config.verbose_retry = true
+
+ # show exception that triggers a retry if verbose_retry is set to true
+ config.display_try_failure_messages = true
+
+ config.around do |example|
+ retry_times = example.metadata.keys.include?(:quarantine) ? 1 : 3
+ example.run_with_retry retry: retry_times
+ end
+end
+
+# Skip tests in quarantine unless we explicitly focus on them.
+# Skip the entire context if a context is tagged. This avoids running before
+# blocks unnecessarily.
+# If quarantine is focussed, skip tests/contexts that have other metadata
+# unless they're also focussed. This lets us run quarantined tests in a
+# particular category without running tests in other categories.
+# E.g., if a test is tagged 'smoke' and 'quarantine', and another is tagged
+# 'ldap' and 'quarantine', if we wanted to run just quarantined smoke tests
+# using `--tag quarantine --tag smoke`, without this check we'd end up
+# running that ldap test as well.
+# We could use an exclusion filter, but this way the test report will list
+# the quarantined tests when they're not run so that we're aware of them
+def skip_or_run_quarantined_tests(metadata_keys, filter_keys)
+ included_filters = filters_other_than_quarantine(filter_keys)
+
+ if filter_keys.include?(:quarantine)
+ skip("Only running tests tagged with :quarantine and any of #{included_filters}") unless quarantine_and_optional_other_tag?(metadata_keys, included_filters)
+ else
+ skip('In quarantine') if metadata_keys.include?(:quarantine)
+ end
+end
+
+def filters_other_than_quarantine(filter_keys)
+ filter_keys.reject { |key| key == :quarantine }
+end
+
+# Checks if a test has the 'quarantine' tag and other tags in the inclusion filter.
+#
+# Returns true if
+# - the metadata includes the quarantine tag
+# - and the metadata and inclusion filter both have any other tag
+# - or no other tags are in the inclusion filter
+def quarantine_and_optional_other_tag?(metadata_keys, included_filters)
+ return false unless metadata_keys.include? :quarantine
+ return true if included_filters.empty?
+
+ included_filters.any? { |key| metadata_keys.include? key }
end
diff --git a/qa/spec/spec_helper_spec.rb b/qa/spec/spec_helper_spec.rb
new file mode 100644
index 00000000000..27ec1ec80fe
--- /dev/null
+++ b/qa/spec/spec_helper_spec.rb
@@ -0,0 +1,355 @@
+# frozen_string_literal: true
+
+describe 'rspec config tests' do
+ let(:group) do
+ RSpec.describe do
+ shared_examples 'passing tests' do
+ example 'not in quarantine' do
+ end
+ example 'in quarantine', :quarantine do
+ end
+ end
+
+ context 'default' do
+ it_behaves_like 'passing tests'
+ end
+
+ context 'foo', :foo do
+ it_behaves_like 'passing tests'
+ end
+
+ context 'quarantine', :quarantine do
+ it_behaves_like 'passing tests'
+ end
+
+ context 'bar quarantine', :bar, :quarantine do
+ it_behaves_like 'passing tests'
+ end
+ end
+ end
+
+ let(:group_2) do
+ RSpec.describe do
+ before(:all) do
+ @expectations = [1, 2, 3]
+ end
+
+ example 'not in quarantine' do
+ expect(@expectations.shift).to be(3)
+ end
+
+ example 'in quarantine', :quarantine do
+ expect(@expectations.shift).to be(3)
+ end
+ end
+ end
+
+ context 'with no tags focussed' do
+ before do
+ group.run
+ end
+
+ context 'in a context tagged :foo' do
+ it 'skips tests in quarantine' do
+ context = group.children.find { |c| c.description == "foo" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to eq(2)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ expect(ex.execution_result.pending_message).to eq('In quarantine')
+ end
+ end
+
+ context 'in an untagged context' do
+ it 'skips tests in quarantine' do
+ context = group.children.find { |c| c.description == "default" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to eq(2)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ expect(ex.execution_result.pending_message).to eq('In quarantine')
+ end
+ end
+
+ context 'in a context tagged :quarantine' do
+ it 'skips all tests' do
+ context = group.children.find { |c| c.description == "quarantine" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to eq(2)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ expect(ex.execution_result.pending_message).to eq('In quarantine')
+ end
+ end
+ end
+
+ context 'with :quarantine focussed' do
+ before do
+ RSpec.configure do |config|
+ config.inclusion_filter = :quarantine
+ end
+
+ group.run
+ end
+ after do
+ RSpec.configure do |config|
+ config.inclusion_filter.clear
+ end
+ end
+
+ context 'in an untagged context' do
+ it 'only runs quarantined tests' do
+ context = group.children.find { |c| c.description == "default" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(1)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+ end
+ end
+
+ context 'in a context tagged :foo' do
+ it 'only runs quarantined tests' do
+ context = group.children.find { |c| c.description == "foo" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(1)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+ end
+ end
+
+ context 'in a context tagged :quarantine' do
+ it 'runs all tests' do
+ context = group.children.find { |c| c.description == "quarantine" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(2)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+ end
+ end
+ end
+
+ context 'with a non-quarantine tag (:foo) focussed' do
+ before do
+ RSpec.configure do |config|
+ config.inclusion_filter = :foo
+ end
+
+ group.run
+ end
+ after do
+ RSpec.configure do |config|
+ config.inclusion_filter.clear
+ end
+ end
+
+ context 'in an untagged context' do
+ it 'runs no tests' do
+ context = group.children.find { |c| c.description == "default" }
+ expect(context.descendant_filtered_examples.count).to eq(0)
+ end
+ end
+
+ context 'in a context tagged :foo' do
+ it 'skips quarantined tests' do
+ context = group.children.find { |c| c.description == "foo" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(2)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ expect(ex.execution_result.pending_message).to eq('In quarantine')
+ end
+ end
+
+ context 'in a context tagged :quarantine' do
+ it 'runs no tests' do
+ context = group.children.find { |c| c.description == "quarantine" }
+ expect(context.descendant_filtered_examples.count).to eq(0)
+ end
+ end
+ end
+
+ context 'with :quarantine and a non-quarantine tag (:foo) focussed' do
+ before do
+ RSpec.configure do |config|
+ config.inclusion_filter = { quarantine: true, foo: true }
+ end
+
+ group.run
+ end
+ after do
+ RSpec.configure do |config|
+ config.inclusion_filter.clear
+ end
+ end
+
+ context 'in an untagged context' do
+ it 'ignores untagged tests and skips tests even if in quarantine' do
+ context = group.children.find { |c| c.description == "default" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to eq(1)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ end
+ end
+
+ context 'in a context tagged :foo' do
+ it 'only runs quarantined tests' do
+ context = group.children.find { |c| c.description == "foo" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(2)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ end
+ end
+
+ context 'in a context tagged :quarantine' do
+ it 'skips all tests' do
+ context = group.children.find { |c| c.description == "quarantine" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(2)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ end
+ end
+
+ context 'in a context tagged :bar and :quarantine' do
+ it 'skips all tests' do
+ context = group.children.find { |c| c.description == "quarantine" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(2)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ end
+ end
+ end
+
+ context 'with :quarantine and multiple non-quarantine tags focussed' do
+ before do
+ RSpec.configure do |config|
+ config.inclusion_filter = { bar: true, foo: true, quarantine: true }
+ end
+
+ group.run
+ end
+ after do
+ RSpec.configure do |config|
+ config.inclusion_filter.clear
+ end
+ end
+
+ context 'in a context tagged :foo' do
+ it 'only runs quarantined tests' do
+ context = group.children.find { |c| c.description == "foo" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(2)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ expect(ex.execution_result.pending_message).to eq('Only running tests tagged with :quarantine and any of [:bar, :foo]')
+ end
+ end
+
+ context 'in a context tagged :quarantine' do
+ it 'skips all tests' do
+ context = group.children.find { |c| c.description == "quarantine" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(2)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ expect(ex.execution_result.pending_message).to eq('Only running tests tagged with :quarantine and any of [:bar, :foo]')
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:pending)
+ expect(ex.execution_result.pending_message).to eq('Only running tests tagged with :quarantine and any of [:bar, :foo]')
+ end
+ end
+
+ context 'in a context tagged :bar and :quarantine' do
+ it 'runs all tests' do
+ context = group.children.find { |c| c.description == "bar quarantine" }
+ examples = context.descendant_filtered_examples
+ expect(examples.count).to be(2)
+
+ ex = examples.find { |e| e.description == "in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+
+ ex = examples.find { |e| e.description == "not in quarantine" }
+ expect(ex.execution_result.status).to eq(:passed)
+ end
+ end
+ end
+
+ context 'rspec retry' do
+ context 'in an untagged context' do
+ before do
+ group_2.run
+ end
+
+ it 'should run example :retry times' do
+ examples = group_2.descendant_filtered_examples
+ ex = examples.find { |e| e.description == 'not in quarantine' }
+ expect(ex.execution_result.status).to eq(:passed)
+ end
+ end
+
+ context 'with :quarantine focussed' do
+ before do
+ RSpec.configure do |config|
+ config.inclusion_filter = :quarantine
+ end
+ group_2.run
+ end
+
+ after do
+ RSpec.configure do |config|
+ config.inclusion_filter.clear
+ end
+ end
+
+ it 'should run example once only' do
+ examples = group_2.descendant_filtered_examples
+ ex = examples.find { |e| e.description == 'in quarantine' }
+ expect(ex.execution_result.status).to eq(:failed)
+ end
+ end
+ end
+end
diff --git a/qa/spec/support/stub_env.rb b/qa/spec/support/stub_env.rb
deleted file mode 100644
index 044804cd599..00000000000
--- a/qa/spec/support/stub_env.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# Inspired by https://github.com/ljkbennett/stub_env/blob/master/lib/stub_env/helpers.rb
-module Support
- module StubENV
- def stub_env(key_or_hash, value = nil)
- init_stub unless env_stubbed?
-
- if key_or_hash.is_a? Hash
- key_or_hash.each { |k, v| add_stubbed_value(k, v) }
- else
- add_stubbed_value key_or_hash, value
- end
- end
-
- private
-
- STUBBED_KEY = '__STUBBED__'.freeze
-
- def add_stubbed_value(key, value)
- allow(ENV).to receive(:[]).with(key).and_return(value)
- allow(ENV).to receive(:key?).with(key).and_return(true)
- allow(ENV).to receive(:fetch).with(key).and_return(value)
- allow(ENV).to receive(:fetch).with(key, anything()) do |_, default_val|
- value || default_val
- end
- end
-
- def env_stubbed?
- ENV[STUBBED_KEY]
- end
-
- def init_stub
- allow(ENV).to receive(:[]).and_call_original
- allow(ENV).to receive(:key?).and_call_original
- allow(ENV).to receive(:fetch).and_call_original
- # Prevent secrets from leaking in CI
- allow(ENV).to receive(:inspect).and_return([])
- add_stubbed_value(STUBBED_KEY, true)
- end
- end
-end
diff --git a/qa/spec/support/waiter_spec.rb b/qa/spec/support/waiter_spec.rb
new file mode 100644
index 00000000000..8283b65e1be
--- /dev/null
+++ b/qa/spec/support/waiter_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'logger'
+
+describe QA::Support::Waiter do
+ before do
+ logger = ::Logger.new $stdout
+ logger.level = ::Logger::DEBUG
+ QA::Runtime::Logger.logger = logger
+ end
+
+ describe '.wait' do
+ context 'when the condition is true' do
+ it 'logs the start' do
+ expect { subject.wait(max: 0) {} }
+ .to output(/with wait: max 0; interval 0.1/).to_stdout_from_any_process
+ end
+
+ it 'logs the end' do
+ expect { subject.wait(max: 0) {} }
+ .to output(/ended wait after .* seconds$/).to_stdout_from_any_process
+ end
+ end
+
+ context 'when the condition is false' do
+ it 'logs the start' do
+ expect { subject.wait(max: 0) { false } }
+ .to output(/with wait: max 0; interval 0.1/).to_stdout_from_any_process
+ end
+
+ it 'logs the end' do
+ expect { subject.wait(max: 0) { false } }
+ .to output(/ended wait after .* seconds$/).to_stdout_from_any_process
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/inject_enterprise_edition_module.rb b/rubocop/cop/inject_enterprise_edition_module.rb
index c8b8aca51ab..1d37b1bd12d 100644
--- a/rubocop/cop/inject_enterprise_edition_module.rb
+++ b/rubocop/cop/inject_enterprise_edition_module.rb
@@ -11,9 +11,13 @@ module RuboCop
METHODS = Set.new(%i[include extend prepend]).freeze
- def_node_matcher :ee_const?, <<~PATTERN
- (const (const _ :EE) _)
- PATTERN
+ def ee_const?(node)
+ line = node.location.expression.source_line
+
+ # We use `match?` here instead of RuboCop's AST matching, as this makes
+ # it far easier to handle nested constants such as `EE::Foo::Bar::Baz`.
+ line.match?(/(\s|\()(::)?EE::/)
+ end
def on_send(node)
return unless METHODS.include?(node.children[1])
diff --git a/rubocop/spec_helpers.rb b/rubocop/spec_helpers.rb
index 9bf5f1e3b18..63c1b975a65 100644
--- a/rubocop/spec_helpers.rb
+++ b/rubocop/spec_helpers.rb
@@ -1,6 +1,7 @@
module RuboCop
module SpecHelpers
SPEC_HELPERS = %w[fast_spec_helper.rb rails_helper.rb spec_helper.rb].freeze
+ MIGRATION_SPEC_DIRECTORIES = ['spec/migrations', 'spec/lib/gitlab/background_migration'].freeze
# Returns true if the given node originated from the spec directory.
def in_spec?(node)
@@ -10,14 +11,18 @@ module RuboCop
path.start_with?(File.join(Dir.pwd, 'spec'), File.join(Dir.pwd, 'ee', 'spec'))
end
+ def migration_directories
+ @migration_directories ||= MIGRATION_SPEC_DIRECTORIES.map do |dir|
+ [File.join(Dir.pwd, dir), File.join(Dir.pwd, 'ee', dir)]
+ end.flatten
+ end
+
# Returns true if the given node originated from a migration spec.
def in_migration_spec?(node)
path = node.location.expression.source_buffer.name
in_spec?(node) &&
- path.start_with?(
- File.join(Dir.pwd, 'spec', 'migrations'),
- File.join(Dir.pwd, 'ee', 'spec', 'migrations'))
+ path.start_with?(*migration_directories)
end
end
end
diff --git a/scripts/build_assets_image b/scripts/build_assets_image
index 4e5ef977161..9afada244c8 100755
--- a/scripts/build_assets_image
+++ b/scripts/build_assets_image
@@ -22,6 +22,8 @@ mkdir -p assets_container.build/public
cp -r public/assets assets_container.build/public/
cp Dockerfile.assets assets_container.build/
docker build -t ${ASSETS_IMAGE_PATH}:${CI_COMMIT_REF_SLUG} -f assets_container.build/Dockerfile.assets assets_container.build/
+docker tag ${ASSETS_IMAGE_PATH}:${CI_COMMIT_REF_SLUG} ${ASSETS_IMAGE_PATH}:${CI_COMMIT_SHA}
docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
-docker push ${ASSETS_IMAGE_PATH}
+docker push ${ASSETS_IMAGE_PATH}:${CI_COMMIT_REF_SLUG}
+docker push ${ASSETS_IMAGE_PATH}:${CI_COMMIT_SHA}
diff --git a/scripts/clean-old-cached-assets b/scripts/clean-old-cached-assets
new file mode 100755
index 00000000000..7a3a62a477a
--- /dev/null
+++ b/scripts/clean-old-cached-assets
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+# Clean up cached files that are older than 1 week
+find tmp/cache/assets/sprockets/ -type f -mtime +7 -execdir rm -- "{}" \;
+
+du -d 0 -h tmp/cache/assets/sprockets | cut -f1 | xargs -I % echo "tmp/cache/assets/sprockets/ is currently %"
diff --git a/scripts/lint-changelog-yaml b/scripts/lint-changelog-yaml
index 6553e02ffca..06d502c4676 100755
--- a/scripts/lint-changelog-yaml
+++ b/scripts/lint-changelog-yaml
@@ -3,7 +3,7 @@
require 'yaml'
invalid_changelogs = Dir['changelogs/**/*'].reject do |changelog|
- next true if changelog =~ /(archive\.md|unreleased(-ee)?)$/
+ next true if changelog =~ /((README|archive)\.md|unreleased(-ee)?)$/
next false unless changelog.end_with?('.yml')
begin
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index 848364b4a9b..bc73225c1bf 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -35,7 +35,7 @@ fi
# Do not use 'README.md', instead use 'index.md'
# Number of 'README.md's as of 2018-03-26
-NUMBER_READMES_CE=42
+NUMBER_READMES_CE=43
NUMBER_READMES_EE=46
FIND_READMES=$(find doc/ -name "README.md" | wc -l)
echo '=> Checking for new README.md files...'
diff --git a/scripts/lint-rugged b/scripts/lint-rugged
index 22e3e1f1505..9466c62a415 100755
--- a/scripts/lint-rugged
+++ b/scripts/lint-rugged
@@ -5,12 +5,18 @@ ALLOWED = [
'lib/gitlab/bare_repository_import/repository.rb',
# Needed to avoid using the git binary to validate a branch name
- 'lib/gitlab/git_ref_validator.rb'
+ 'lib/gitlab/git_ref_validator.rb',
+
+ # Reverted Rugged calls due to Gitaly atop NFS performance
+ # See https://docs.gitlab.com/ee/development/gitaly.html#legacy-rugged-code.
+ 'lib/gitlab/git/rugged_impl/',
+ 'lib/gitlab/gitaly_client/storage_settings.rb'
].freeze
rugged_lines = IO.popen(%w[git grep -i -n rugged -- app config lib], &:read).lines
rugged_lines = rugged_lines.select { |l| /^[^:]*\.rb:/ =~ l }
rugged_lines = rugged_lines.reject { |l| l.start_with?(*ALLOWED) }
+rugged_lines = rugged_lines.reject { |l| /(include|prepend) Gitlab::Git::RuggedImpl/ =~ l}
rugged_lines = rugged_lines.reject do |line|
code, _comment = line.split('# ', 2)
code !~ /rugged/i
diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh
index d85c53090a4..58b74f2f07d 100644
--- a/scripts/prepare_build.sh
+++ b/scripts/prepare_build.sh
@@ -10,7 +10,7 @@ fi
# Only install knapsack after bundle install! Otherwise oddly some native
# gems could not be found under some circumstance. No idea why, hours wasted.
-retry gem install knapsack --no-ri --no-rdoc
+retry gem install knapsack --no-document
cp config/gitlab.yml.example config/gitlab.yml
sed -i 's/bin_path: \/usr\/bin\/git/bin_path: \/usr\/local\/bin\/git/' config/gitlab.yml
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 9e52366f800..f610485a700 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -2,6 +2,7 @@
export TILLER_NAMESPACE="$KUBE_NAMESPACE"
function echoerr() { printf "\033[0;31m%s\n\033[0m" "$*" >&2; }
+function echoinfo() { printf "\033[0;33m%s\n\033[0m" "$*" >&2; }
function check_kube_domain() {
if [ -z ${REVIEW_APPS_DOMAIN+x} ]; then
@@ -31,7 +32,9 @@ function ensure_namespace() {
function install_tiller() {
echo "Checking Tiller..."
- helm init --upgrade
+ helm init \
+ --upgrade \
+ --replicas 2
kubectl rollout status -n "$TILLER_NAMESPACE" -w "deployment/tiller-deploy"
if ! helm version --debug; then
echo "Failed to init Tiller."
@@ -140,28 +143,33 @@ HELM_CMD=$(cat << EOF
--set global.hosts.hostSuffix="$HOST_SUFFIX" \
--set global.hosts.domain="$REVIEW_APPS_DOMAIN" \
--set certmanager.install=false \
+ --set prometheus.install=false \
--set global.ingress.configureCertmanager=false \
--set global.ingress.tls.secretName=tls-cert \
--set global.ingress.annotations."external-dns\.alpha\.kubernetes\.io/ttl"="10"
+ --set nginx-ingress.defaultBackend.resources.requests.memory=7Mi \
+ --set nginx-ingress.controller.resources.requests.memory=440M \
+ --set nginx-ingress.controller.replicaCount=2 \
--set gitlab.unicorn.resources.requests.cpu=200m \
--set gitlab.sidekiq.resources.requests.cpu=100m \
+ --set gitlab.sidekiq.resources.requests.memory=800M \
--set gitlab.gitlab-shell.resources.requests.cpu=100m \
--set redis.resources.requests.cpu=100m \
--set minio.resources.requests.cpu=100m \
--set gitlab.migrations.image.repository="$gitlab_migrations_image_repository" \
- --set gitlab.migrations.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.migrations.image.tag="$CI_COMMIT_REF_SLUG" \
--set gitlab.sidekiq.image.repository="$gitlab_sidekiq_image_repository" \
- --set gitlab.sidekiq.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.sidekiq.image.tag="$CI_COMMIT_REF_SLUG" \
--set gitlab.unicorn.image.repository="$gitlab_unicorn_image_repository" \
- --set gitlab.unicorn.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.unicorn.image.tag="$CI_COMMIT_REF_SLUG" \
--set gitlab.task-runner.image.repository="$gitlab_task_runner_image_repository" \
- --set gitlab.task-runner.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.task-runner.image.tag="$CI_COMMIT_REF_SLUG" \
--set gitlab.gitaly.image.repository="registry.gitlab.com/gitlab-org/build/cng-mirror/gitaly" \
--set gitlab.gitaly.image.tag="v$GITALY_VERSION" \
--set gitlab.gitlab-shell.image.repository="registry.gitlab.com/gitlab-org/build/cng-mirror/gitlab-shell" \
--set gitlab.gitlab-shell.image.tag="v$GITLAB_SHELL_VERSION" \
--set gitlab.unicorn.workhorse.image="$gitlab_workhorse_image_repository" \
- --set gitlab.unicorn.workhorse.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.unicorn.workhorse.tag="$CI_COMMIT_REF_SLUG" \
--set nginx-ingress.controller.config.ssl-ciphers="ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4" \
--namespace="$KUBE_NAMESPACE" \
--version="$CI_PIPELINE_ID-$CI_JOB_ID" \
@@ -236,17 +244,17 @@ function get_pod() {
local app_name="${1}"
local status="${2-Running}"
get_pod_cmd="kubectl get pods -n ${KUBE_NAMESPACE} --field-selector=status.phase=${status} -lapp=${app_name},release=${CI_ENVIRONMENT_SLUG} --no-headers -o=custom-columns=NAME:.metadata.name"
- echoerr "Running '${get_pod_cmd}'"
+ echoinfo "Running '${get_pod_cmd}'"
while true; do
local pod_name="$(eval $get_pod_cmd)"
[[ "${pod_name}" == "" ]] || break
- echoerr "Waiting till '${app_name}' pod is ready";
+ echoinfo "Waiting till '${app_name}' pod is ready";
sleep 5;
done
- echoerr "The pod name is '${pod_name}'."
+ echoinfo "The pod name is '${pod_name}'."
echo "${pod_name}"
}
@@ -288,7 +296,7 @@ function get_job_id() {
while true; do
local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs?per_page=100&page=${page}${query_string}"
- echoerr "GET ${url}"
+ echoinfo "GET ${url}"
local job_id=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${API_TOKEN}" "${url}" | jq "map(select(.name == \"${job_name}\")) | map(.id) | last")
[[ "${job_id}" == "null" && "${page}" -lt "$max_page" ]] || break
@@ -299,7 +307,7 @@ function get_job_id() {
if [[ "${job_id}" == "" ]]; then
echoerr "The '${job_name}' job ID couldn't be retrieved!"
else
- echoerr "The '${job_name}' job ID is ${job_id}"
+ echoinfo "The '${job_name}' job ID is ${job_id}"
echo "${job_id}"
fi
}
@@ -310,10 +318,10 @@ function play_job() {
if [ -z "${job_id}" ]; then return; fi
local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}/play"
- echoerr "POST ${url}"
+ echoinfo "POST ${url}"
local job_url=$(curl --silent --show-error --request POST --header "PRIVATE-TOKEN: ${API_TOKEN}" "${url}" | jq ".web_url")
- echo "Manual job '${job_name}' started at: ${job_url}"
+ echoinfo "Manual job '${job_name}' started at: ${job_url}"
}
function wait_for_job_to_be_done() {
@@ -322,10 +330,10 @@ function wait_for_job_to_be_done() {
local job_id=$(get_job_id "${job_name}" "${query_string}");
if [ -z "${job_id}" ]; then return; fi
- echoerr "Waiting for the '${job_name}' job to finish..."
+ echoinfo "Waiting for the '${job_name}' job to finish..."
local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}"
- echo "GET ${url}"
+ echoinfo "GET ${url}"
# In case the job hasn't finished yet. Keep trying until the job times out.
local interval=30
@@ -340,13 +348,13 @@ function wait_for_job_to_be_done() {
done
local elapsed_minutes=$((elapsed_seconds / 60))
- echoerr "Waited '${job_name}' for ${elapsed_minutes} minutes."
+ echoinfo "Waited '${job_name}' for ${elapsed_minutes} minutes."
if [[ "${job_status}" == "failed" ]]; then
- echo "The '${job_name}' failed."
+ echoerr "The '${job_name}' failed."
elif [[ "${job_status}" == "manual" ]]; then
- echo "The '${job_name}' is manual."
+ echoinfo "The '${job_name}' is manual."
else
- echo "The '${job_name}' passed."
+ echoinfo "The '${job_name}' passed."
fi
}
diff --git a/scripts/security-harness b/scripts/security-harness
index c60b3410095..8369cf06223 100755
--- a/scripts/security-harness
+++ b/scripts/security-harness
@@ -37,7 +37,7 @@ else
end
__END__
-#!/bin/sh
+#!/bin/bash
set -e
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 25ba7ec6c8e..642c50ec0a8 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -29,6 +29,7 @@ tasks = [
%w[bin/rake lint:all],
%w[bundle exec license_finder],
%w[yarn run eslint],
+ %w[yarn run stylelint],
%w[yarn run prettier-all],
%w[bundle exec rubocop --parallel],
%w[scripts/lint-conflicts.sh],
diff --git a/scripts/trigger-build b/scripts/trigger-build
index 4032ba853e6..9dbafffddfc 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -68,7 +68,7 @@ module Trigger
def base_variables
{
- 'GITLAB_REF_SLUG' => ENV['CI_COMMIT_REF_SLUG'],
+ 'GITLAB_REF_SLUG' => ENV['CI_COMMIT_TAG'] ? ENV['CI_COMMIT_REF_NAME'] : ENV['CI_COMMIT_REF_SLUG'],
'TRIGGERED_USER' => ENV['TRIGGERED_USER'] || ENV['GITLAB_USER_NAME'],
'TRIGGER_SOURCE' => ENV['CI_JOB_URL'],
'TOP_UPSTREAM_SOURCE_PROJECT' => ENV['CI_PROJECT_PATH'],
@@ -137,7 +137,11 @@ module Trigger
edition = Trigger.ee? ? 'EE' : 'CE'
{
+ # Back-compatibility until https://gitlab.com/gitlab-org/build/CNG/merge_requests/189 is merged
"GITLAB_#{edition}_VERSION" => ENV['CI_COMMIT_REF_NAME'],
+ "GITLAB_VERSION" => ENV['CI_COMMIT_REF_NAME'],
+ "GITLAB_TAG" => ENV['CI_COMMIT_TAG'],
+ "GITLAB_ASSETS_TAG" => ENV['CI_COMMIT_REF_SLUG'],
"#{edition}_PIPELINE" => 'true'
}
end
diff --git a/spec/bin/changelog_spec.rb b/spec/bin/changelog_spec.rb
index c59add88a82..b2c2fb810e8 100644
--- a/spec/bin/changelog_spec.rb
+++ b/spec/bin/changelog_spec.rb
@@ -80,7 +80,7 @@ describe 'bin/changelog' do
end
end
- describe '.read_type' do
+ describe '.read_type' do
let(:type) { '1' }
it 'reads type from $stdin' do
diff --git a/spec/config/application_spec.rb b/spec/config/application_spec.rb
new file mode 100644
index 00000000000..01ed81964c3
--- /dev/null
+++ b/spec/config/application_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Application do # rubocop:disable RSpec/FilePath
+ using RSpec::Parameterized::TableSyntax
+
+ FILTERED_PARAM = ActionDispatch::Http::ParameterFilter::FILTERED
+
+ context 'when parameters are logged' do
+ describe 'rails does not leak confidential parameters' do
+ def request_for_url(input_url)
+ env = Rack::MockRequest.env_for(input_url)
+ env['action_dispatch.parameter_filter'] = described_class.config.filter_parameters
+
+ ActionDispatch::Request.new(env)
+ end
+
+ where(:input_url, :output_query) do
+ '/' | {}
+ '/?safe=1' | { 'safe' => '1' }
+ '/?private_token=secret' | { 'private_token' => FILTERED_PARAM }
+ '/?mixed=1&private_token=secret' | { 'mixed' => '1', 'private_token' => FILTERED_PARAM }
+ '/?note=secret&noteable=1&prefix_note=2' | { 'note' => FILTERED_PARAM, 'noteable' => '1', 'prefix_note' => '2' }
+ '/?note[note]=secret&target_type=1' | { 'note' => FILTERED_PARAM, 'target_type' => '1' }
+ '/?safe[note]=secret&target_type=1' | { 'safe' => { 'note' => FILTERED_PARAM }, 'target_type' => '1' }
+ end
+
+ with_them do
+ it { expect(request_for_url(input_url).filtered_parameters).to eq(output_query) }
+ end
+ end
+ end
+end
diff --git a/spec/controllers/admin/appearances_controller_spec.rb b/spec/controllers/admin/appearances_controller_spec.rb
new file mode 100644
index 00000000000..621aa148301
--- /dev/null
+++ b/spec/controllers/admin/appearances_controller_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Admin::AppearancesController do
+ let(:admin) { create(:admin) }
+ let(:header_message) { 'Header message' }
+ let(:footer_message) { 'Footer' }
+
+ describe 'POST #create' do
+ let(:create_params) do
+ {
+ title: 'Foo',
+ description: 'Bar',
+ header_message: header_message,
+ footer_message: footer_message
+ }
+ end
+
+ before do
+ sign_in(admin)
+ end
+
+ it 'creates appearance with footer and header message' do
+ post :create, params: { appearance: create_params }
+
+ expect(Appearance.current).to have_attributes(
+ header_message: header_message,
+ footer_message: footer_message,
+ email_header_and_footer_enabled: false,
+ message_background_color: '#E75E40',
+ message_font_color: '#FFFFFF'
+ )
+ end
+
+ context 'when enabling header and footer in email' do
+ it 'creates appearance with enabled flag' do
+ create_params[:email_header_and_footer_enabled] = true
+
+ post :create, params: { appearance: create_params }
+
+ expect(Appearance.current).to have_attributes(
+ header_message: header_message,
+ footer_message: footer_message,
+ email_header_and_footer_enabled: true
+ )
+ end
+ end
+ end
+
+ describe 'PUT #update' do
+ let(:update_params) do
+ {
+ header_message: header_message,
+ footer_message: footer_message
+ }
+ end
+
+ before do
+ create(:appearance)
+
+ sign_in(admin)
+ end
+
+ it 'updates appearance with footer and header message' do
+ put :update, params: { appearance: update_params }
+
+ expect(Appearance.current).to have_attributes(
+ header_message: header_message,
+ footer_message: footer_message,
+ email_header_and_footer_enabled: false,
+ message_background_color: '#E75E40',
+ message_font_color: '#FFFFFF'
+ )
+ end
+
+ context 'when enabling header and footer in email' do
+ it 'updates appearance with enabled flag' do
+ update_params[:email_header_and_footer_enabled] = true
+
+ post :update, params: { appearance: update_params }
+
+ expect(Appearance.current).to have_attributes(
+ header_message: header_message,
+ footer_message: footer_message,
+ email_header_and_footer_enabled: true
+ )
+ end
+ end
+ end
+end
diff --git a/spec/controllers/admin/requests_profiles_controller_spec.rb b/spec/controllers/admin/requests_profiles_controller_spec.rb
new file mode 100644
index 00000000000..10850cb4603
--- /dev/null
+++ b/spec/controllers/admin/requests_profiles_controller_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Admin::RequestsProfilesController do
+ set(:admin) { create(:admin) }
+
+ before do
+ sign_in(admin)
+ end
+
+ describe '#show' do
+ let(:basename) { "profile_#{Time.now.to_i}.html" }
+ let(:tmpdir) { Dir.mktmpdir('profiler-test') }
+ let(:test_file) { File.join(tmpdir, basename) }
+ let(:profile) { Gitlab::RequestProfiler::Profile.new(basename) }
+ let(:sample_data) do
+ <<~HTML
+ <!DOCTYPE html>
+ <html>
+ <body>
+ <h1>My First Heading</h1>
+ <p>My first paragraph.</p>
+ </body>
+ </html>
+ HTML
+ end
+
+ before do
+ stub_const('Gitlab::RequestProfiler::PROFILES_DIR', tmpdir)
+ output = File.open(test_file, 'w')
+ output.write(sample_data)
+ output.close
+ end
+
+ after do
+ File.unlink(test_file)
+ end
+
+ it 'loads an HTML profile' do
+ get :show, params: { name: basename }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.body).to eq(sample_data)
+ end
+ end
+end
diff --git a/spec/controllers/admin/runners_controller_spec.rb b/spec/controllers/admin/runners_controller_spec.rb
index 4cf14030ca1..82e24213408 100644
--- a/spec/controllers/admin/runners_controller_spec.rb
+++ b/spec/controllers/admin/runners_controller_spec.rb
@@ -1,18 +1,35 @@
require 'spec_helper'
describe Admin::RunnersController do
- let(:runner) { create(:ci_runner) }
+ let!(:runner) { create(:ci_runner) }
before do
sign_in(create(:admin))
end
describe '#index' do
+ render_views
+
it 'lists all runners' do
get :index
expect(response).to have_gitlab_http_status(200)
end
+
+ it 'avoids N+1 queries', :request_store do
+ get :index
+
+ control_count = ActiveRecord::QueryRecorder.new { get :index }.count
+
+ create(:ci_runner, :tagged_only)
+
+ # There is still an N+1 query for `runner.builds.count`
+ expect { get :index }.not_to exceed_query_limit(control_count + 1)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.body).to have_content('tag1')
+ expect(response.body).to have_content('tag2')
+ end
end
describe '#show' do
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index 6b66cbd2651..cb24a6ef142 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -8,6 +8,31 @@ describe Admin::UsersController do
sign_in(admin)
end
+ describe 'GET #index' do
+ it 'retrieves all users' do
+ get :index
+
+ expect(assigns(:users)).to match_array([user, admin])
+ end
+
+ it 'filters by admins' do
+ get :index, params: { filter: 'admins' }
+
+ expect(assigns(:users)).to eq([admin])
+ end
+ end
+
+ describe 'GET :id' do
+ it 'finds a user case-insensitively' do
+ user = create(:user, username: 'CaseSensitive')
+
+ get :show, params: { id: user.username.downcase }
+
+ expect(response).to be_redirect
+ expect(response.location).to end_with(user.username)
+ end
+ end
+
describe 'DELETE #user with projects' do
let(:project) { create(:project, namespace: user.namespace) }
let!(:issue) { create(:issue, author: user) }
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 43f561f7a25..dca74bd5f84 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -423,7 +423,7 @@ describe ApplicationController do
enforce_terms
end
- it 'redirects if the user did not accept the terms' do
+ it 'redirects if the user did not accept the terms' do
get :index
expect(response).to have_gitlab_http_status(302)
@@ -519,12 +519,14 @@ describe ApplicationController do
get :index
expect(response).to have_gitlab_http_status(404)
+ expect(response).to render_template('errors/not_found')
end
it 'renders a 403 when a message is passed to access denied' do
get :index, params: { message: 'None shall pass' }
expect(response).to have_gitlab_http_status(403)
+ expect(response).to render_template('errors/access_denied')
end
it 'renders a status passed to access denied' do
@@ -663,6 +665,14 @@ describe ApplicationController do
expect(response.headers['Cache-Control']).to eq 'max-age=0, private, must-revalidate, no-store'
end
+
+ it 'does not set the "no-store" header for XHR requests' do
+ sign_in(user)
+
+ get :index, xhr: true
+
+ expect(response.headers['Cache-Control']).to eq 'max-age=0, private, must-revalidate'
+ end
end
end
end
diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb
index 8657fc2ebc0..5eb05f01b8d 100644
--- a/spec/controllers/boards/issues_controller_spec.rb
+++ b/spec/controllers/boards/issues_controller_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Boards::IssuesController do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :private) }
let(:board) { create(:board, project: project) }
let(:user) { create(:user) }
let(:guest) { create(:user) }
@@ -127,14 +127,10 @@ describe Boards::IssuesController do
end
context 'with unauthorized user' do
- before do
- allow(Ability).to receive(:allowed?).and_call_original
- allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
- allow(Ability).to receive(:allowed?).with(user, :read_issue, project).and_return(false)
- end
+ let(:unauth_user) { create(:user) }
it 'returns a forbidden 403 response' do
- list_issues user: user, board: board, list: list2
+ list_issues user: unauth_user, board: board, list: list2
expect(response).to have_gitlab_http_status(403)
end
@@ -233,7 +229,7 @@ describe Boards::IssuesController do
post :create, params: {
board_id: board.to_param,
list_id: list.to_param,
- issue: { title: title, project_id: project.id }
+ issue: { title: title, project_id: project.id }
},
format: :json
end
diff --git a/spec/controllers/boards/lists_controller_spec.rb b/spec/controllers/boards/lists_controller_spec.rb
index 70033857168..e5b8aa2e678 100644
--- a/spec/controllers/boards/lists_controller_spec.rb
+++ b/spec/controllers/boards/lists_controller_spec.rb
@@ -31,13 +31,10 @@ describe Boards::ListsController do
end
context 'with unauthorized user' do
- before do
- allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
- allow(Ability).to receive(:allowed?).with(user, :read_list, project).and_return(false)
- end
+ let(:unauth_user) { create(:user) }
it 'returns a forbidden 403 response' do
- read_board_list user: user, board: board
+ read_board_list user: unauth_user, board: board
expect(response).to have_gitlab_http_status(403)
end
diff --git a/spec/controllers/concerns/checks_collaboration_spec.rb b/spec/controllers/concerns/checks_collaboration_spec.rb
index 1bd764290ae..d7f110e11f3 100644
--- a/spec/controllers/concerns/checks_collaboration_spec.rb
+++ b/spec/controllers/concerns/checks_collaboration_spec.rb
@@ -22,7 +22,7 @@ describe ChecksCollaboration do
end
end
- it 'is true if the user can push to the project' do
+ it 'is true if the user can push to the project' do
project.add_developer(user)
expect(helper.can_collaborate_with_project?(project)).to be_truthy
diff --git a/spec/controllers/concerns/issuable_collections_spec.rb b/spec/controllers/concerns/issuable_collections_spec.rb
index 5a3a7a15f5a..8580900215c 100644
--- a/spec/controllers/concerns/issuable_collections_spec.rb
+++ b/spec/controllers/concerns/issuable_collections_spec.rb
@@ -17,10 +17,55 @@ describe IssuableCollections do
controller = klass.new
allow(controller).to receive(:params).and_return(ActionController::Parameters.new(params))
+ allow(controller).to receive(:current_user).and_return(user)
controller
end
+ describe '#set_sort_order_from_user_preference' do
+ describe 'when sort param given' do
+ let(:params) { { sort: 'updated_desc' } }
+
+ context 'when issuable_sorting_field is defined' do
+ before do
+ controller.class.define_method(:issuable_sorting_field) { :issues_sort}
+ end
+
+ it 'sets user_preference with the right value' do
+ controller.send(:set_sort_order_from_user_preference)
+
+ expect(user.user_preference.reload.issues_sort).to eq('updated_desc')
+ end
+ end
+
+ context 'when no issuable_sorting_field is defined on the controller' do
+ it 'does not touch user_preference' do
+ allow(user).to receive(:user_preference)
+
+ controller.send(:set_sort_order_from_user_preference)
+
+ expect(user).not_to have_received(:user_preference)
+ end
+ end
+ end
+
+ context 'when a user sorting preference exists' do
+ let(:params) { {} }
+
+ before do
+ controller.class.define_method(:issuable_sorting_field) { :issues_sort }
+ end
+
+ it 'returns the set preference' do
+ user.user_preference.update(issues_sort: 'updated_asc')
+
+ sort_preference = controller.send(:set_sort_order_from_user_preference)
+
+ expect(sort_preference).to eq('updated_asc')
+ end
+ end
+ end
+
describe '#set_set_order_from_cookie' do
describe 'when sort param given' do
let(:cookies) { {} }
@@ -67,7 +112,8 @@ describe IssuableCollections do
assignee_username: 'user1',
author_id: '2',
author_username: 'user2',
- authorized_only: 'true',
+ authorized_only: 'yes',
+ confidential: true,
due_date: '2017-01-01',
group_id: '3',
iids: '4',
@@ -95,6 +141,7 @@ describe IssuableCollections do
'assignee_username' => 'user1',
'author_id' => '2',
'author_username' => 'user2',
+ 'confidential' => true,
'label_name' => 'foo',
'milestone_title' => 'bar',
'my_reaction_emoji' => 'thumbsup',
diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb
index 379b2d6b935..aa71a247956 100644
--- a/spec/controllers/concerns/send_file_upload_spec.rb
+++ b/spec/controllers/concerns/send_file_upload_spec.rb
@@ -52,20 +52,56 @@ describe SendFileUpload do
end
end
+ context 'with inline image' do
+ let(:filename) { 'test.png' }
+ let(:params) { { disposition: 'inline', attachment: filename } }
+
+ it 'sends a file with inline disposition' do
+ # Notice the filename= is omitted from the disposition; this is because
+ # Rails 5 will append this header in send_file
+ expected_params = {
+ filename: 'test.png',
+ disposition: "inline; filename*=UTF-8''test.png"
+ }
+ expect(controller).to receive(:send_file).with(uploader.path, expected_params)
+
+ subject
+ end
+ end
+
context 'with attachment' do
- let(:params) { { attachment: 'test.js' } }
+ let(:filename) { 'test.js' }
+ let(:params) { { attachment: filename } }
it 'sends a file with content-type of text/plain' do
+ # Notice the filename= is omitted from the disposition; this is because
+ # Rails 5 will append this header in send_file
expected_params = {
content_type: 'text/plain',
filename: 'test.js',
- disposition: 'attachment'
+ disposition: "attachment; filename*=UTF-8''test.js"
}
expect(controller).to receive(:send_file).with(uploader.path, expected_params)
subject
end
+ context 'with non-ASCII encoded filename' do
+ let(:filename) { 'テスト.txt' }
+
+ # Notice the filename= is omitted from the disposition; this is because
+ # Rails 5 will append this header in send_file
+ it 'sends content-disposition for non-ASCII encoded filenames' do
+ expected_params = {
+ filename: filename,
+ disposition: "attachment; filename*=UTF-8''%E3%83%86%E3%82%B9%E3%83%88.txt"
+ }
+ expect(controller).to receive(:send_file).with(uploader.path, expected_params)
+
+ subject
+ end
+ end
+
context 'with a proxied file in object storage' do
before do
stub_uploads_object_storage(uploader: uploader_class)
@@ -76,7 +112,7 @@ describe SendFileUpload do
it 'sends a file with a custom type' do
headers = double
- expected_headers = %r(response-content-disposition=attachment%3Bfilename%3D%22test.js%22&response-content-type=application/ecmascript)
+ expected_headers = /response-content-disposition=attachment%3B%20filename%3D%22test.js%22%3B%20filename%2A%3DUTF-8%27%27test.js&response-content-type=application%2Fecmascript/
expect(Gitlab::Workhorse).to receive(:send_url).with(expected_headers).and_call_original
expect(headers).to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-url:/)
diff --git a/spec/controllers/dashboard/milestones_controller_spec.rb b/spec/controllers/dashboard/milestones_controller_spec.rb
index 8a8cc14fd4c..ab40b4eb178 100644
--- a/spec/controllers/dashboard/milestones_controller_spec.rb
+++ b/spec/controllers/dashboard/milestones_controller_spec.rb
@@ -3,11 +3,9 @@ require 'spec_helper'
describe Dashboard::MilestonesController do
let(:project) { create(:project) }
let(:group) { create(:group) }
- let(:public_group) { create(:group, :public) }
let(:user) { create(:user) }
let(:project_milestone) { create(:milestone, project: project) }
let(:group_milestone) { create(:milestone, group: group) }
- let!(:public_milestone) { create(:milestone, group: public_group) }
let(:milestone) do
DashboardMilestone.build(
[project],
@@ -15,7 +13,7 @@ describe Dashboard::MilestonesController do
)
end
let(:issue) { create(:issue, project: project, milestone: project_milestone) }
- let(:group_issue) { create(:issue, milestone: group_milestone) }
+ let(:group_issue) { create(:issue, milestone: group_milestone, project: create(:project, group: group)) }
let!(:label) { create(:label, project: project, title: 'Issue Label', issues: [issue]) }
let!(:group_label) { create(:group_label, group: group, title: 'Group Issue Label', issues: [group_issue]) }
@@ -45,6 +43,9 @@ describe Dashboard::MilestonesController do
end
describe "#index" do
+ let(:public_group) { create(:group, :public) }
+ let!(:public_milestone) { create(:milestone, group: public_group) }
+
render_views
it 'returns group and project milestones to which the user belongs' do
@@ -52,14 +53,32 @@ describe Dashboard::MilestonesController do
expect(response).to have_gitlab_http_status(200)
expect(json_response.size).to eq(2)
- expect(json_response.map { |i| i["first_milestone"]["id"] }).to match_array([group_milestone.id, project_milestone.id])
+ expect(json_response.map { |i| i["name"] }).to match_array([group_milestone.name, project_milestone.name])
expect(json_response.map { |i| i["group_name"] }.compact).to match_array(group.name)
end
- it 'should contain group and project milestones to which the user belongs to' do
+ it 'searches legacy project milestones by title when search_title is given' do
+ project_milestone = create(:milestone, title: 'Project milestone title', project: project)
+
+ get :index, params: { search_title: 'Project mil' }
+
+ expect(response.body).to include(project_milestone.title)
+ expect(response.body).not_to include(group_milestone.title)
+ end
+
+ it 'searches group milestones by title when search_title is given' do
+ group_milestone = create(:milestone, title: 'Group milestone title', group: group)
+
+ get :index, params: { search_title: 'Group mil' }
+
+ expect(response.body).to include(group_milestone.title)
+ expect(response.body).not_to include(project_milestone.title)
+ end
+
+ it 'should show counts of group and project milestones to which the user belongs to' do
get :index
- expect(response.body).to include("Open\n<span class=\"badge badge-pill\">3</span>")
+ expect(response.body).to include("Open\n<span class=\"badge badge-pill\">2</span>")
expect(response.body).to include("Closed\n<span class=\"badge badge-pill\">0</span>")
end
end
diff --git a/spec/controllers/google_api/authorizations_controller_spec.rb b/spec/controllers/google_api/authorizations_controller_spec.rb
index 1e8e82da4f3..d9ba85cf56a 100644
--- a/spec/controllers/google_api/authorizations_controller_spec.rb
+++ b/spec/controllers/google_api/authorizations_controller_spec.rb
@@ -6,7 +6,7 @@ describe GoogleApi::AuthorizationsController do
let(:token) { 'token' }
let(:expires_at) { 1.hour.since.strftime('%s') }
- subject { get :callback, params: { code: 'xxx', state: @state } }
+ subject { get :callback, params: { code: 'xxx', state: state } }
before do
sign_in(user)
@@ -15,35 +15,57 @@ describe GoogleApi::AuthorizationsController do
.to receive(:get_token).and_return([token, expires_at])
end
- it 'sets token and expires_at in session' do
- subject
+ shared_examples_for 'access denied' do
+ it 'returns a 404' do
+ subject
- expect(session[GoogleApi::CloudPlatform::Client.session_key_for_token])
- .to eq(token)
- expect(session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at])
- .to eq(expires_at)
+ expect(session[GoogleApi::CloudPlatform::Client.session_key_for_token]).to be_nil
+ expect(response).to have_http_status(:not_found)
+ end
end
- context 'when redirect uri key is stored in state' do
- set(:project) { create(:project) }
- let(:redirect_uri) { project_clusters_url(project).to_s }
+ context 'session key is present' do
+ let(:session_key) { 'session-key' }
+ let(:redirect_uri) { 'example.com' }
before do
- @state = GoogleApi::CloudPlatform::Client
- .new_session_key_for_redirect_uri do |key|
- session[key] = redirect_uri
+ session[GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(session_key)] = redirect_uri
+ end
+
+ context 'session key matches state param' do
+ let(:state) { session_key }
+
+ it 'sets token and expires_at in session' do
+ subject
+
+ expect(session[GoogleApi::CloudPlatform::Client.session_key_for_token])
+ .to eq(token)
+ expect(session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at])
+ .to eq(expires_at)
+ end
+
+ it 'redirects to the URL stored in state param' do
+ expect(subject).to redirect_to(redirect_uri)
end
end
- it 'redirects to the URL stored in state param' do
- expect(subject).to redirect_to(redirect_uri)
+ context 'session key does not match state param' do
+ let(:state) { 'bad-key' }
+
+ it_behaves_like 'access denied'
end
- end
- context 'when redirection url is not stored in state' do
- it 'redirects to root_path' do
- expect(subject).to redirect_to(root_path)
+ context 'state param is blank' do
+ let(:state) { '' }
+
+ it_behaves_like 'access denied'
end
end
+
+ context 'state param is present, but session key is blank' do
+ let(:state) { 'session-key' }
+
+ it_behaves_like 'access denied'
+ end
end
end
diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb
deleted file mode 100644
index a0f40874db1..00000000000
--- a/spec/controllers/graphql_controller_spec.rb
+++ /dev/null
@@ -1,112 +0,0 @@
-require 'spec_helper'
-
-describe GraphqlController do
- describe 'execute' do
- let(:user) { nil }
-
- before do
- sign_in(user) if user
-
- run_test_query!
- end
-
- subject { query_response }
-
- context 'graphql is disabled by feature flag' do
- let(:user) { nil }
-
- before do
- stub_feature_flags(graphql: false)
- end
-
- it 'returns 404' do
- run_test_query!
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'signed out' do
- let(:user) { nil }
-
- it 'runs the query with current_user: nil' do
- is_expected.to eq('echo' => 'nil says: test success')
- end
- end
-
- context 'signed in' do
- let(:user) { create(:user, username: 'Simon') }
-
- it 'runs the query with current_user set' do
- is_expected.to eq('echo' => '"Simon" says: test success')
- end
- end
-
- context 'invalid variables' do
- it 'returns an error' do
- run_test_query!(variables: "This is not JSON")
-
- expect(response).to have_gitlab_http_status(422)
- expect(json_response['errors'].first['message']).not_to be_nil
- end
- end
- end
-
- context 'token authentication' do
- before do
- stub_authentication_activity_metrics(debug: false)
- end
-
- let(:user) { create(:user, username: 'Simon') }
- let(:personal_access_token) { create(:personal_access_token, user: user) }
-
- context "when the 'personal_access_token' param is populated with the personal access token" do
- it 'logs the user in' do
- expect(authentication_metrics)
- .to increment(:user_authenticated_counter)
- .and increment(:user_session_override_counter)
- .and increment(:user_sessionless_authentication_counter)
-
- run_test_query!(private_token: personal_access_token.token)
-
- expect(response).to have_gitlab_http_status(200)
- expect(query_response).to eq('echo' => '"Simon" says: test success')
- end
- end
-
- context 'when the personal access token has no api scope' do
- it 'does not log the user in' do
- personal_access_token.update(scopes: [:read_user])
-
- run_test_query!(private_token: personal_access_token.token)
-
- expect(response).to have_gitlab_http_status(200)
-
- expect(query_response).to eq('echo' => 'nil says: test success')
- end
- end
-
- context 'without token' do
- it 'shows public data' do
- run_test_query!
-
- expect(query_response).to eq('echo' => 'nil says: test success')
- end
- end
- end
-
- # Chosen to exercise all the moving parts in GraphqlController#execute
- def run_test_query!(variables: { 'text' => 'test success' }, private_token: nil)
- query = <<~QUERY
- query Echo($text: String) {
- echo(text: $text)
- }
- QUERY
-
- post :execute, params: { query: query, operationName: 'Echo', variables: variables, private_token: private_token }
- end
-
- def query_response
- json_response['data']
- end
-end
diff --git a/spec/controllers/groups/children_controller_spec.rb b/spec/controllers/groups/children_controller_spec.rb
index 4d5bb1488ab..e1b97013408 100644
--- a/spec/controllers/groups/children_controller_spec.rb
+++ b/spec/controllers/groups/children_controller_spec.rb
@@ -110,7 +110,7 @@ describe Groups::ChildrenController do
matched_project_1 = create(:project, :public, namespace: shared_subgroup, name: 'mobile-soc')
l2_subgroup = create(:group, :public, parent: shared_subgroup, path: 'broadcom')
- l3_subgroup = create(:group, :public, parent: l2_subgroup, path: 'wifi-group')
+ l3_subgroup = create(:group, :public, parent: l2_subgroup, path: 'wifi-group')
matched_project_2 = create(:project, :public, namespace: l3_subgroup, name: 'mobile')
get :index, params: { group_id: group.to_param, filter: 'mobile' }, format: :json
@@ -289,7 +289,7 @@ describe Groups::ChildrenController do
end
context 'with subgroups and projects', :nested_groups do
- let!(:first_page_subgroups) { create_list(:group, per_page, :public, parent: group) }
+ let!(:first_page_subgroups) { create_list(:group, per_page, :public, parent: group) }
let!(:other_subgroup) { create(:group, :public, parent: group) }
let!(:next_page_projects) { create_list(:project, per_page, :public, namespace: group) }
@@ -306,7 +306,7 @@ describe Groups::ChildrenController do
end
context 'with a mixed first page' do
- let!(:first_page_subgroups) { [create(:group, :public, parent: group)] }
+ let!(:first_page_subgroups) { [create(:group, :public, parent: group)] }
let!(:first_page_projects) { create_list(:project, per_page, :public, namespace: group) }
it 'correctly calculates the counts' do
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
index 0f28499194e..ef23ffaa843 100644
--- a/spec/controllers/groups/clusters_controller_spec.rb
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -429,12 +429,14 @@ describe Groups::ClustersController do
end
let(:cluster) { create(:cluster, :provided_by_user, cluster_type: :group_type, groups: [group]) }
+ let(:domain) { 'test-domain.com' }
let(:params) do
{
cluster: {
enabled: false,
- name: 'my-new-cluster-name'
+ name: 'my-new-cluster-name',
+ base_domain: domain
}
}
end
@@ -447,6 +449,20 @@ describe Groups::ClustersController do
expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster.domain).to eq('test-domain.com')
+ end
+
+ context 'when domain is invalid' do
+ let(:domain) { 'http://not-a-valid-domain' }
+
+ it 'should not update cluster attributes' do
+ go
+
+ cluster.reload
+ expect(response).to render_template(:show)
+ expect(cluster.name).not_to eq('my-new-cluster-name')
+ expect(cluster.domain).not_to eq('test-domain.com')
+ end
end
context 'when format is json' do
@@ -456,7 +472,8 @@ describe Groups::ClustersController do
{
cluster: {
enabled: false,
- name: 'my-new-cluster-name'
+ name: 'my-new-cluster-name',
+ domain: domain
}
}
end
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index ed38dadfd6b..3a801fabafc 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -126,7 +126,7 @@ describe Groups::GroupMembersController do
it '[HTML] removes user from members' do
delete :destroy, params: { group_id: group, id: member }
- expect(response).to set_flash.to 'User was successfully removed from group.'
+ expect(response).to set_flash.to 'User was successfully removed from group and any subresources.'
expect(response).to redirect_to(group_group_members_path(group))
expect(group.members).not_to include member
end
diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb
index b8e1e08cff7..043cf28514b 100644
--- a/spec/controllers/groups/milestones_controller_spec.rb
+++ b/spec/controllers/groups/milestones_controller_spec.rb
@@ -32,10 +32,35 @@ describe Groups::MilestonesController do
end
describe '#index' do
- it 'shows group milestones page' do
- get :index, params: { group_id: group.to_param }
+ describe 'as HTML' do
+ render_views
- expect(response).to have_gitlab_http_status(200)
+ it 'shows group milestones page' do
+ milestone
+
+ get :index, params: { group_id: group.to_param }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.body).to include(milestone.title)
+ end
+
+ it 'searches legacy milestones by title when search_title is given' do
+ project_milestone = create(:milestone, project: project, title: 'Project milestone title')
+
+ get :index, params: { group_id: group.to_param, search_title: 'Project mil' }
+
+ expect(response.body).to include(project_milestone.title)
+ expect(response.body).not_to include(milestone.title)
+ end
+
+ it 'searches group milestones by title when search_title is given' do
+ group_milestone = create(:milestone, title: 'Group milestone title', group: group)
+
+ get :index, params: { group_id: group.to_param, search_title: 'Group mil' }
+
+ expect(response.body).to include(group_milestone.title)
+ expect(response.body).not_to include(milestone.title)
+ end
end
context 'as JSON' do
@@ -64,7 +89,7 @@ describe Groups::MilestonesController do
context 'when there is a title parameter' do
it 'searches for a legacy group milestone' do
- expect(GlobalMilestone).to receive(:build)
+ expect(GroupMilestone).to receive(:build)
expect(Milestone).not_to receive(:find_by_iid)
get :show, params: { group_id: group.to_param, id: title, title: milestone1.safe_title }
diff --git a/spec/controllers/groups/settings/ci_cd_controller_spec.rb b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
index b7f04f732b9..40673d10b91 100644
--- a/spec/controllers/groups/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
@@ -5,30 +5,65 @@ describe Groups::Settings::CiCdController do
let(:user) { create(:user) }
before do
- group.add_maintainer(user)
sign_in(user)
end
describe 'GET #show' do
- it 'renders show with 200 status code' do
- get :show, params: { group_id: group }
+ context 'when user is owner' do
+ before do
+ group.add_owner(user)
+ end
- expect(response).to have_gitlab_http_status(200)
- expect(response).to render_template(:show)
+ it 'renders show with 200 status code' do
+ get :show, params: { group_id: group }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to render_template(:show)
+ end
+ end
+
+ context 'when user is not owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'renders a 404' do
+ get :show, params: { group_id: group }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
end
end
describe 'PUT #reset_registration_token' do
subject { put :reset_registration_token, params: { group_id: group } }
- it 'resets runner registration token' do
- expect { subject }.to change { group.reload.runners_token }
+ context 'when user is owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'resets runner registration token' do
+ expect { subject }.to change { group.reload.runners_token }
+ end
+
+ it 'redirects the user to admin runners page' do
+ subject
+
+ expect(response).to redirect_to(group_settings_ci_cd_path)
+ end
end
- it 'redirects the user to admin runners page' do
- subject
+ context 'when user is not owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'renders a 404' do
+ subject
- expect(response).to redirect_to(group_settings_ci_cd_path)
+ expect(response).to have_gitlab_http_status(404)
+ end
end
end
end
diff --git a/spec/controllers/groups/shared_projects_controller_spec.rb b/spec/controllers/groups/shared_projects_controller_spec.rb
index dab7700cf64..b0c20fb5a90 100644
--- a/spec/controllers/groups/shared_projects_controller_spec.rb
+++ b/spec/controllers/groups/shared_projects_controller_spec.rb
@@ -6,6 +6,8 @@ describe Groups::SharedProjectsController do
end
def share_project(project)
+ group.add_developer(user)
+
Projects::GroupLinks::CreateService.new(
project,
user,
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 7d87b33e503..21e5122c06b 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -227,9 +227,7 @@ describe GroupsController do
context 'searching' do
before do
- # Remove in https://gitlab.com/gitlab-org/gitlab-ce/issues/54643
- stub_feature_flags(use_cte_for_group_issues_search: false)
- stub_feature_flags(use_subquery_for_group_issues_search: true)
+ stub_feature_flags(attempt_group_search_optimizations: true)
end
it 'works with popularity sort' do
diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb
index 5cb284e7e2d..dca67c18caa 100644
--- a/spec/controllers/help_controller_spec.rb
+++ b/spec/controllers/help_controller_spec.rb
@@ -37,6 +37,46 @@ describe HelpController do
expect(assigns[:help_index]).to eq '[external](https://some.external.link)'
end
end
+
+ context 'when relative url with external on same line' do
+ it 'prefix it with /help/' do
+ stub_readme("[API](api/README.md) [external](https://some.external.link)")
+
+ get :index
+
+ expect(assigns[:help_index]).to eq '[API](/help/api/README.md) [external](https://some.external.link)'
+ end
+ end
+
+ context 'when relative url with http:// in query' do
+ it 'prefix it with /help/' do
+ stub_readme("[API](api/README.md?go=https://example.com/)")
+
+ get :index
+
+ expect(assigns[:help_index]).to eq '[API](/help/api/README.md?go=https://example.com/)'
+ end
+ end
+
+ context 'when mailto URL' do
+ it 'do not change it' do
+ stub_readme("[report bug](mailto:bugs@example.com)")
+
+ get :index
+
+ expect(assigns[:help_index]).to eq '[report bug](mailto:bugs@example.com)'
+ end
+ end
+
+ context 'when protocol-relative link' do
+ it 'do not change it' do
+ stub_readme("[protocol-relative](//example.com)")
+
+ get :index
+
+ expect(assigns[:help_index]).to eq '[protocol-relative](//example.com)'
+ end
+ end
end
describe 'GET #show' do
diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb
index 51793f2c048..0bc09c86939 100644
--- a/spec/controllers/import/bitbucket_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_controller_spec.rb
@@ -8,6 +8,7 @@ describe Import::BitbucketController do
let(:secret) { "sekrettt" }
let(:refresh_token) { SecureRandom.hex(15) }
let(:access_params) { { token: token, expires_at: nil, expires_in: nil, refresh_token: nil } }
+ let(:code) { SecureRandom.hex(8) }
def assign_session_tokens
session[:bitbucket_token] = token
@@ -32,10 +33,16 @@ describe Import::BitbucketController do
expires_in: expires_in,
refresh_token: refresh_token)
allow_any_instance_of(OAuth2::Client)
- .to receive(:get_token).and_return(access_token)
+ .to receive(:get_token)
+ .with(hash_including(
+ 'grant_type' => 'authorization_code',
+ 'code' => code,
+ redirect_uri: users_import_bitbucket_callback_url),
+ {})
+ .and_return(access_token)
stub_omniauth_provider('bitbucket')
- get :callback
+ get :callback, params: { code: code }
expect(session[:bitbucket_token]).to eq(token)
expect(session[:bitbucket_refresh_token]).to eq(refresh_token)
diff --git a/spec/controllers/import/bitbucket_server_controller_spec.rb b/spec/controllers/import/bitbucket_server_controller_spec.rb
index 73195463a50..a125e6ed16d 100644
--- a/spec/controllers/import/bitbucket_server_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_server_controller_spec.rb
@@ -28,9 +28,11 @@ describe Import::BitbucketServerController do
end
describe 'POST create' do
+ let(:project_name) { "my-project_123" }
+
before do
allow(controller).to receive(:bitbucket_client).and_return(client)
- repo = double(name: 'my-project')
+ repo = double(name: project_name)
allow(client).to receive(:repo).with(project_key, repo_slug).and_return(repo)
assign_session_tokens
end
@@ -39,7 +41,7 @@ describe Import::BitbucketServerController do
it 'returns the new project' do
allow(Gitlab::BitbucketServerImport::ProjectCreator)
- .to receive(:new).with(project_key, repo_slug, anything, 'my-project', user.namespace, user, anything)
+ .to receive(:new).with(project_key, repo_slug, anything, project_name, user.namespace, user, anything)
.and_return(double(execute: project))
post :create, params: { project: project_key, repository: repo_slug }, format: :json
@@ -47,6 +49,20 @@ describe Import::BitbucketServerController do
expect(response).to have_gitlab_http_status(200)
end
+ context 'with project key with tildes' do
+ let(:project_key) { '~someuser_123' }
+
+ it 'successfully creates a project' do
+ allow(Gitlab::BitbucketServerImport::ProjectCreator)
+ .to receive(:new).with(project_key, repo_slug, anything, project_name, user.namespace, user, anything)
+ .and_return(double(execute: project))
+
+ post :create, params: { project: project_key, repository: repo_slug, format: :json }
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
it 'returns an error when an invalid project key is used' do
post :create, params: { project: 'some&project' }
@@ -69,7 +85,7 @@ describe Import::BitbucketServerController do
it 'returns an error when the project cannot be saved' do
allow(Gitlab::BitbucketServerImport::ProjectCreator)
- .to receive(:new).with(project_key, repo_slug, anything, 'my-project', user.namespace, user, anything)
+ .to receive(:new).with(project_key, repo_slug, anything, project_name, user.namespace, user, anything)
.and_return(double(execute: build(:project)))
post :create, params: { project: project_key, repository: repo_slug }, format: :json
@@ -78,7 +94,7 @@ describe Import::BitbucketServerController do
end
it "returns an error when the server can't be contacted" do
- expect(client).to receive(:repo).with(project_key, repo_slug).and_raise(BitbucketServer::Client::ServerError)
+ expect(client).to receive(:repo).with(project_key, repo_slug).and_raise(::BitbucketServer::Connection::ConnectionError)
post :create, params: { project: project_key, repository: repo_slug }, format: :json
diff --git a/spec/controllers/import/gitea_controller_spec.rb b/spec/controllers/import/gitea_controller_spec.rb
index 5ba64ab3eed..8cbec79095f 100644
--- a/spec/controllers/import/gitea_controller_spec.rb
+++ b/spec/controllers/import/gitea_controller_spec.rb
@@ -40,4 +40,12 @@ describe Import::GiteaController do
end
end
end
+
+ describe "GET realtime_changes" do
+ it_behaves_like 'a GitHub-ish import controller: GET realtime_changes' do
+ before do
+ assign_host_url
+ end
+ end
+ end
end
diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb
index 780e49f7b93..162dff98ec5 100644
--- a/spec/controllers/import/github_controller_spec.rb
+++ b/spec/controllers/import/github_controller_spec.rb
@@ -12,9 +12,15 @@ describe Import::GithubController do
it "redirects to GitHub for an access token if logged in with GitHub" do
allow(controller).to receive(:logged_in_with_provider?).and_return(true)
- expect(controller).to receive(:go_to_provider_for_permissions)
+ expect(controller).to receive(:go_to_provider_for_permissions).and_call_original
+ allow_any_instance_of(Gitlab::LegacyGithubImport::Client)
+ .to receive(:authorize_url)
+ .with(users_import_github_callback_url)
+ .and_call_original
get :new
+
+ expect(response).to have_http_status(302)
end
it "prompts for an access token if GitHub not configured" do
@@ -54,4 +60,8 @@ describe Import::GithubController do
describe "POST create" do
it_behaves_like 'a GitHub-ish import controller: POST create'
end
+
+ describe "GET realtime_changes" do
+ it_behaves_like 'a GitHub-ish import controller: GET realtime_changes'
+ end
end
diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb
index d377d69457f..e0da23ca0b8 100644
--- a/spec/controllers/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/omniauth_callbacks_controller_spec.rb
@@ -45,6 +45,63 @@ describe OmniauthCallbacksController, type: :controller do
end
end
+ context 'when sign in fails' do
+ include RoutesHelpers
+
+ let(:extern_uid) { 'my-uid' }
+ let(:provider) { :saml }
+
+ def stub_route_as(path)
+ allow(@routes).to receive(:generate_extras) { [path, []] }
+ end
+
+ it 'it calls through to the failure handler' do
+ request.env['omniauth.error'] = OneLogin::RubySaml::ValidationError.new("Fingerprint mismatch")
+ request.env['omniauth.error.strategy'] = OmniAuth::Strategies::SAML.new(nil)
+ stub_route_as('/users/auth/saml/callback')
+
+ ForgeryProtection.with_forgery_protection do
+ post :failure
+ end
+
+ expect(flash[:alert]).to match(/Fingerprint mismatch/)
+ end
+ end
+
+ context 'when a redirect fragment is provided' do
+ let(:provider) { :jwt }
+ let(:extern_uid) { 'my-uid' }
+
+ before do
+ request.env['omniauth.params'] = { 'redirect_fragment' => 'L101' }
+ end
+
+ context 'when a redirect url is stored' do
+ it 'redirects with fragment' do
+ post provider, session: { user_return_to: '/fake/url' }
+
+ expect(response).to redirect_to('/fake/url#L101')
+ end
+ end
+
+ context 'when a redirect url with a fragment is stored' do
+ it 'redirects with the new fragment' do
+ post provider, session: { user_return_to: '/fake/url#replaceme' }
+
+ expect(response).to redirect_to('/fake/url#L101')
+ end
+ end
+
+ context 'when no redirect url is stored' do
+ it 'does not redirect with the fragment' do
+ post provider
+
+ expect(response.redirect?).to be true
+ expect(response.location).not_to include('#L101')
+ end
+ end
+ end
+
context 'strategies' do
context 'github' do
let(:extern_uid) { 'my-uid' }
@@ -136,7 +193,7 @@ describe OmniauthCallbacksController, type: :controller do
before do
stub_omniauth_saml_config({ enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'],
providers: [saml_config] })
- mock_auth_hash('saml', 'my-uid', user.email, mock_saml_response)
+ mock_auth_hash_with_saml_xml('saml', 'my-uid', user.email, mock_saml_response)
request.env["devise.mapping"] = Devise.mappings[:user]
request.env['omniauth.auth'] = Rails.application.env_config['omniauth.auth']
post :saml, params: { SAMLResponse: mock_saml_response }
diff --git a/spec/controllers/profiles/avatars_controller_spec.rb b/spec/controllers/profiles/avatars_controller_spec.rb
index 909709e1103..1ee0bf44e92 100644
--- a/spec/controllers/profiles/avatars_controller_spec.rb
+++ b/spec/controllers/profiles/avatars_controller_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Profiles::AvatarsController do
- let(:user) { create(:user, avatar: fixture_file_upload("spec/fixtures/dk.png")) }
+ let(:user) { create(:user, avatar: fixture_file_upload("spec/fixtures/dk.png")) }
before do
sign_in(user)
diff --git a/spec/controllers/profiles/preferences_controller_spec.rb b/spec/controllers/profiles/preferences_controller_spec.rb
index 012f016b091..ee881f85233 100644
--- a/spec/controllers/profiles/preferences_controller_spec.rb
+++ b/spec/controllers/profiles/preferences_controller_spec.rb
@@ -42,7 +42,9 @@ describe Profiles::PreferencesController do
prefs = {
color_scheme_id: '1',
dashboard: 'stars',
- theme_id: '2'
+ theme_id: '2',
+ first_day_of_week: '1',
+ preferred_language: 'jp'
}.with_indifferent_access
expect(user).to receive(:assign_attributes).with(ActionController::Parameters.new(prefs).permit!)
diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb
index bd10de45b67..29df00e6bb0 100644
--- a/spec/controllers/projects/artifacts_controller_spec.rb
+++ b/spec/controllers/projects/artifacts_controller_spec.rb
@@ -26,8 +26,15 @@ describe Projects::ArtifactsController do
end
context 'when no file type is supplied' do
+ let(:filename) { job.artifacts_file.filename }
+
it 'sends the artifacts file' do
- expect(controller).to receive(:send_file).with(job.artifacts_file.path, hash_including(disposition: 'attachment')).and_call_original
+ # Notice the filename= is omitted from the disposition; this is because
+ # Rails 5 will append this header in send_file
+ expect(controller).to receive(:send_file)
+ .with(
+ job.artifacts_file.file.path,
+ hash_including(disposition: %Q(attachment; filename*=UTF-8''#{filename}))).and_call_original
download_artifact
end
@@ -46,6 +53,7 @@ describe Projects::ArtifactsController do
context 'when codequality file type is supplied' do
let(:file_type) { 'codequality' }
+ let(:filename) { job.job_artifacts_codequality.filename }
context 'when file is stored locally' do
before do
@@ -53,7 +61,11 @@ describe Projects::ArtifactsController do
end
it 'sends the codequality report' do
- expect(controller).to receive(:send_file).with(job.job_artifacts_codequality.file.path, hash_including(disposition: 'attachment')).and_call_original
+ # Notice the filename= is omitted from the disposition; this is because
+ # Rails 5 will append this header in send_file
+ expect(controller).to receive(:send_file)
+ .with(job.job_artifacts_codequality.file.path,
+ hash_including(disposition: %Q(attachment; filename*=UTF-8''#{filename}))).and_call_original
download_artifact(file_type: file_type)
end
diff --git a/spec/controllers/projects/autocomplete_sources_controller_spec.rb b/spec/controllers/projects/autocomplete_sources_controller_spec.rb
new file mode 100644
index 00000000000..a9a058e7e17
--- /dev/null
+++ b/spec/controllers/projects/autocomplete_sources_controller_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::AutocompleteSourcesController do
+ set(:group) { create(:group) }
+ set(:project) { create(:project, namespace: group) }
+ set(:issue) { create(:issue, project: project) }
+ set(:user) { create(:user) }
+
+ describe 'GET members' do
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'returns an array of member object' do
+ get :members, format: :json, params: { namespace_id: group.path, project_id: project.path, type: issue.class.name, type_id: issue.id }
+
+ all = json_response.find {|member| member["username"] == 'all'}
+ the_group = json_response.find {|member| member["username"] == group.full_path}
+ the_user = json_response.find {|member| member["username"] == user.username}
+
+ expect(all.symbolize_keys).to include(username: 'all',
+ name: 'All Project and Group Members',
+ count: 1)
+
+ expect(the_group.symbolize_keys).to include(type: group.class.name,
+ name: group.full_name,
+ avatar_url: group.avatar_url,
+ count: 1)
+
+ expect(the_user.symbolize_keys).to include(type: user.class.name,
+ name: user.name,
+ avatar_url: user.avatar_url)
+ end
+ end
+
+ describe 'GET milestones' do
+ let(:group) { create(:group, :public) }
+ let(:project) { create(:project, :public, namespace: group) }
+ let!(:project_milestone) { create(:milestone, project: project) }
+ let!(:group_milestone) { create(:milestone, group: group) }
+
+ before do
+ sign_in(user)
+ end
+
+ it 'lists milestones' do
+ group.add_owner(user)
+
+ get :milestones, format: :json, params: { namespace_id: group.path, project_id: project.path }
+
+ milestone_titles = json_response.map { |milestone| milestone["title"] }
+ expect(milestone_titles).to match_array([project_milestone.title, group_milestone.title])
+ end
+
+ context 'when user cannot read project issues and merge requests' do
+ it 'renders 404' do
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+
+ get :milestones, format: :json, params: { namespace_id: group.path, project_id: project.path }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/avatars_controller_spec.rb b/spec/controllers/projects/avatars_controller_spec.rb
index 40ab81395ea..95b7ae5885a 100644
--- a/spec/controllers/projects/avatars_controller_spec.rb
+++ b/spec/controllers/projects/avatars_controller_spec.rb
@@ -26,37 +26,13 @@ describe Projects::AvatarsController do
context 'when the avatar is stored in the repository' do
let(:filepath) { 'files/images/logo-white.png' }
- context 'when feature flag workhorse_set_content_type is' do
- before do
- stub_feature_flags(workhorse_set_content_type: flag_value)
- end
+ it 'sends the avatar' do
+ subject
- context 'enabled' do
- let(:flag_value) { true }
-
- it 'sends the avatar' do
- subject
-
- expect(response).to have_gitlab_http_status(200)
- expect(response.header['Content-Disposition']).to eq('inline')
- expect(response.header['Content-Type']).to eq 'image/png'
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
- end
- end
-
- context 'disabled' do
- let(:flag_value) { false }
-
- it 'sends the avatar' do
- subject
-
- expect(response).to have_gitlab_http_status(200)
- expect(response.header['Content-Type']).to eq('image/png')
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq nil
- end
- end
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.header['Content-Disposition']).to eq('inline')
+ expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
+ expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
end
diff --git a/spec/controllers/projects/badges_controller_spec.rb b/spec/controllers/projects/badges_controller_spec.rb
index 2556bc3ae50..8eac3d9a459 100644
--- a/spec/controllers/projects/badges_controller_spec.rb
+++ b/spec/controllers/projects/badges_controller_spec.rb
@@ -22,7 +22,44 @@ describe Projects::BadgesController do
expect(response).to have_gitlab_http_status(:ok)
end
- def get_badge(badge)
- get badge, params: { namespace_id: project.namespace.to_param, project_id: project, ref: pipeline.ref }, format: :svg
+ it 'renders the `flat` badge layout by default' do
+ get_badge(:coverage)
+
+ expect(response).to render_template('projects/badges/badge')
+ end
+
+ context 'when style param is set to `flat`' do
+ it 'renders the `flat` badge layout' do
+ get_badge(:coverage, 'flat')
+
+ expect(response).to render_template('projects/badges/badge')
+ end
+ end
+
+ context 'when style param is set to an invalid type' do
+ it 'renders the `flat` (default) badge layout' do
+ get_badge(:coverage, 'xxx')
+
+ expect(response).to render_template('projects/badges/badge')
+ end
+ end
+
+ context 'when style param is set to `flat-square`' do
+ it 'renders the `flat-square` badge layout' do
+ get_badge(:coverage, 'flat-square')
+
+ expect(response).to render_template('projects/badges/badge_flat-square')
+ end
+ end
+
+ def get_badge(badge, style = nil)
+ params = {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ ref: pipeline.ref,
+ style: style
+ }
+
+ get badge, params: params, format: :svg
end
end
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index 02b3d5269a6..52a20fa8d07 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -331,7 +331,7 @@ describe Projects::BranchesController do
let(:branch) { "feature" }
it 'returns JSON response with message' do
- expect(json_response).to eql("message" => 'Branch was removed')
+ expect(json_response).to eql("message" => 'Branch was deleted')
end
it { expect(response).to have_gitlab_http_status(200) }
@@ -341,7 +341,7 @@ describe Projects::BranchesController do
let(:branch) { "improve/awesome" }
it 'returns JSON response with message' do
- expect(json_response).to eql('message' => 'Branch was removed')
+ expect(json_response).to eql('message' => 'Branch was deleted')
end
it { expect(response).to have_gitlab_http_status(200) }
@@ -351,7 +351,7 @@ describe Projects::BranchesController do
let(:branch) { 'improve%2Fawesome' }
it 'returns JSON response with message' do
- expect(json_response).to eql('message' => 'Branch was removed')
+ expect(json_response).to eql('message' => 'Branch was deleted')
end
it { expect(response).to have_gitlab_http_status(200) }
diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb
index 82c1374aa4f..cfa010c2d1c 100644
--- a/spec/controllers/projects/ci/lints_controller_spec.rb
+++ b/spec/controllers/projects/ci/lints_controller_spec.rb
@@ -51,7 +51,6 @@ describe Projects::Ci::LintsController do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
HEREDOC
end
diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb
index 26eec90da06..19cac47325c 100644
--- a/spec/controllers/projects/commit_controller_spec.rb
+++ b/spec/controllers/projects/commit_controller_spec.rb
@@ -5,7 +5,7 @@ describe Projects::CommitController do
set(:user) { create(:user) }
let(:commit) { project.commit("master") }
let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
- let(:master_pickable_commit) { project.commit(master_pickable_sha) }
+ let(:master_pickable_commit) { project.commit(master_pickable_sha) }
before do
sign_in(user)
diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb
index 94fb85f217c..36ce1119100 100644
--- a/spec/controllers/projects/environments_controller_spec.rb
+++ b/spec/controllers/projects/environments_controller_spec.rb
@@ -47,9 +47,43 @@ describe Projects::EnvironmentsController do
let(:environments) { json_response['environments'] }
+ context 'with default parameters' do
+ before do
+ get :index, params: environment_params(format: :json)
+ end
+
+ it 'responds with a flat payload describing available environments' do
+ expect(environments.count).to eq 3
+ expect(environments.first).to include('name' => 'production', 'name_without_type' => 'production')
+ expect(environments.second).to include('name' => 'staging/review-1', 'name_without_type' => 'review-1')
+ expect(environments.third).to include('name' => 'staging/review-2', 'name_without_type' => 'review-2')
+ expect(json_response['available_count']).to eq 3
+ expect(json_response['stopped_count']).to eq 1
+ end
+
+ it 'sets the polling interval header' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers['Poll-Interval']).to eq("3000")
+ end
+ end
+
+ context 'when a folder-based nested structure is requested' do
+ before do
+ get :index, params: environment_params(format: :json, nested: true)
+ end
+
+ it 'responds with a payload containing the latest environment for each folder' do
+ expect(environments.count).to eq 2
+ expect(environments.first['name']).to eq 'production'
+ expect(environments.second['name']).to eq 'staging'
+ expect(environments.second['size']).to eq 2
+ expect(environments.second['latest']['name']).to eq 'staging/review-2'
+ end
+ end
+
context 'when requesting available environments scope' do
before do
- get :index, params: environment_params(format: :json, scope: :available)
+ get :index, params: environment_params(format: :json, nested: true, scope: :available)
end
it 'responds with a payload describing available environments' do
@@ -64,16 +98,11 @@ describe Projects::EnvironmentsController do
expect(json_response['available_count']).to eq 3
expect(json_response['stopped_count']).to eq 1
end
-
- it 'sets the polling interval header' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers['Poll-Interval']).to eq("3000")
- end
end
context 'when requesting stopped environments scope' do
before do
- get :index, params: environment_params(format: :json, scope: :stopped)
+ get :index, params: environment_params(format: :json, nested: true, scope: :stopped)
end
it 'responds with a payload describing stopped environments' do
@@ -126,9 +155,9 @@ describe Projects::EnvironmentsController do
expect(response).to be_ok
expect(response).not_to render_template 'folder'
expect(json_response['environments'][0])
- .to include('name' => 'staging-1.0/review')
+ .to include('name' => 'staging-1.0/review', 'name_without_type' => 'review')
expect(json_response['environments'][1])
- .to include('name' => 'staging-1.0/zzz')
+ .to include('name' => 'staging-1.0/zzz', 'name_without_type' => 'zzz')
end
end
end
@@ -393,6 +422,79 @@ describe Projects::EnvironmentsController do
end
end
+ describe 'GET #search' do
+ before do
+ create(:environment, name: 'staging', project: project)
+ create(:environment, name: 'review/patch-1', project: project)
+ create(:environment, name: 'review/patch-2', project: project)
+ end
+
+ let(:query) { 'pro' }
+
+ it 'responds with status code 200' do
+ get :search, params: environment_params(format: :json, query: query)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'returns matched results' do
+ get :search, params: environment_params(format: :json, query: query)
+
+ expect(json_response).to contain_exactly('production')
+ end
+
+ context 'when query is review' do
+ let(:query) { 'review' }
+
+ it 'returns matched results' do
+ get :search, params: environment_params(format: :json, query: query)
+
+ expect(json_response).to contain_exactly('review/patch-1', 'review/patch-2')
+ end
+ end
+
+ context 'when query is empty' do
+ let(:query) { '' }
+
+ it 'returns matched results' do
+ get :search, params: environment_params(format: :json, query: query)
+
+ expect(json_response)
+ .to contain_exactly('production', 'staging', 'review/patch-1', 'review/patch-2')
+ end
+ end
+
+ context 'when query is review/patch-3' do
+ let(:query) { 'review/patch-3' }
+
+ it 'responds with status code 204' do
+ get :search, params: environment_params(format: :json, query: query)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+
+ context 'when query is partially matched in the middle of environment name' do
+ let(:query) { 'patch' }
+
+ it 'responds with status code 204' do
+ get :search, params: environment_params(format: :json, query: query)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+
+ context 'when query contains a wildcard character' do
+ let(:query) { 'review%' }
+
+ it 'prevents wildcard injection' do
+ get :search, params: environment_params(format: :json, query: query)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+ end
+
def environment_params(opts = {})
opts.reverse_merge(namespace_id: project.namespace,
project_id: project,
diff --git a/spec/controllers/projects/error_tracking_controller_spec.rb b/spec/controllers/projects/error_tracking_controller_spec.rb
new file mode 100644
index 00000000000..844c61f1ace
--- /dev/null
+++ b/spec/controllers/projects/error_tracking_controller_spec.rb
@@ -0,0 +1,240 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Projects::ErrorTrackingController do
+ set(:project) { create(:project) }
+ set(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ project.add_maintainer(user)
+ end
+
+ describe 'GET #index' do
+ describe 'html' do
+ it 'renders index with 200 status code' do
+ get :index, params: project_params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:index)
+ end
+
+ context 'with insufficient permissions' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns 404' do
+ get :index, params: project_params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'with an anonymous user' do
+ before do
+ sign_out(user)
+ end
+
+ it 'redirects to sign-in page' do
+ get :index, params: project_params
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ describe 'format json' do
+ shared_examples 'no data' do
+ it 'returns no data' do
+ get :index, params: project_params(format: :json)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('error_tracking/index')
+ expect(json_response['external_url']).to be_nil
+ expect(json_response['errors']).to eq([])
+ end
+ end
+
+ let(:list_issues_service) { spy(:list_issues_service) }
+ let(:external_url) { 'http://example.com' }
+
+ before do
+ expect(ErrorTracking::ListIssuesService)
+ .to receive(:new).with(project, user)
+ .and_return(list_issues_service)
+ end
+
+ context 'service result is successful' do
+ before do
+ expect(list_issues_service).to receive(:execute)
+ .and_return(status: :success, issues: [error])
+ expect(list_issues_service).to receive(:external_url)
+ .and_return(external_url)
+ end
+
+ let(:error) { build(:error_tracking_error) }
+
+ it 'returns a list of errors' do
+ get :index, params: project_params(format: :json)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('error_tracking/index')
+ expect(json_response['external_url']).to eq(external_url)
+ expect(json_response['errors']).to eq([error].as_json)
+ end
+ end
+
+ context 'service result is erroneous' do
+ let(:error_message) { 'error message' }
+
+ context 'without http_status' do
+ before do
+ expect(list_issues_service).to receive(:execute)
+ .and_return(status: :error, message: error_message)
+ end
+
+ it 'returns 400 with message' do
+ get :index, params: project_params(format: :json)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to eq(error_message)
+ end
+ end
+
+ context 'with explicit http_status' do
+ let(:http_status) { :no_content }
+
+ before do
+ expect(list_issues_service).to receive(:execute).and_return(
+ status: :error,
+ message: error_message,
+ http_status: http_status
+ )
+ end
+
+ it 'returns http_status with message' do
+ get :index, params: project_params(format: :json)
+
+ expect(response).to have_gitlab_http_status(http_status)
+ expect(json_response['message']).to eq(error_message)
+ end
+ end
+ end
+ end
+ end
+
+ describe 'POST #list_projects' do
+ context 'with insufficient permissions' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns 404' do
+ post :list_projects, params: list_projects_params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'with an anonymous user' do
+ before do
+ sign_out(user)
+ end
+
+ it 'redirects to sign-in page' do
+ post :list_projects, params: list_projects_params
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'with authorized user' do
+ let(:list_projects_service) { spy(:list_projects_service) }
+ let(:sentry_project) { build(:error_tracking_project) }
+
+ let(:permitted_params) do
+ ActionController::Parameters.new(
+ list_projects_params[:error_tracking_setting]
+ ).permit!
+ end
+
+ before do
+ allow(ErrorTracking::ListProjectsService)
+ .to receive(:new).with(project, user, permitted_params)
+ .and_return(list_projects_service)
+ end
+
+ context 'service result is successful' do
+ before do
+ expect(list_projects_service).to receive(:execute)
+ .and_return(status: :success, projects: [sentry_project])
+ end
+
+ it 'returns a list of projects' do
+ post :list_projects, params: list_projects_params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('error_tracking/list_projects')
+ expect(json_response['projects']).to eq([sentry_project].as_json)
+ end
+ end
+
+ context 'service result is erroneous' do
+ let(:error_message) { 'error message' }
+
+ context 'without http_status' do
+ before do
+ expect(list_projects_service).to receive(:execute)
+ .and_return(status: :error, message: error_message)
+ end
+
+ it 'returns 400 with message' do
+ get :list_projects, params: list_projects_params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to eq(error_message)
+ end
+ end
+
+ context 'with explicit http_status' do
+ let(:http_status) { :no_content }
+
+ before do
+ expect(list_projects_service).to receive(:execute).and_return(
+ status: :error,
+ message: error_message,
+ http_status: http_status
+ )
+ end
+
+ it 'returns http_status with message' do
+ get :list_projects, params: list_projects_params
+
+ expect(response).to have_gitlab_http_status(http_status)
+ expect(json_response['message']).to eq(error_message)
+ end
+ end
+ end
+ end
+
+ private
+
+ def list_projects_params(opts = {})
+ project_params(
+ format: :json,
+ error_tracking_setting: {
+ api_host: 'gitlab.com',
+ token: 'token'
+ }
+ )
+ end
+ end
+
+ private
+
+ def project_params(opts = {})
+ opts.reverse_merge(namespace_id: project.namespace, project_id: project)
+ end
+end
diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb
index 73fb7307e11..8decd8f1382 100644
--- a/spec/controllers/projects/graphs_controller_spec.rb
+++ b/spec/controllers/projects/graphs_controller_spec.rb
@@ -24,4 +24,20 @@ describe Projects::GraphsController do
expect(response).to redirect_to action: :charts
end
end
+
+ describe 'charts' do
+ context 'when languages were previously detected' do
+ let!(:repository_language) { create(:repository_language, project: project) }
+
+ it 'sets the languages properly' do
+ get(:charts, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' })
+
+ expect(assigns[:languages]).to eq(
+ [value: repository_language.share,
+ label: repository_language.name,
+ color: repository_language.color,
+ highlight: repository_language.color])
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb
index 675eeff8d12..ce021b2f085 100644
--- a/spec/controllers/projects/group_links_controller_spec.rb
+++ b/spec/controllers/projects/group_links_controller_spec.rb
@@ -65,8 +65,24 @@ describe Projects::GroupLinksController do
end
end
+ context 'when user does not have access to the public group' do
+ let(:group) { create(:group, :public) }
+
+ include_context 'link project to group'
+
+ it 'renders 404' do
+ expect(response.status).to eq 404
+ end
+
+ it 'does not share project with that group' do
+ expect(group.shared_projects).not_to include project
+ end
+ end
+
context 'when project group id equal link group id' do
before do
+ group2.add_developer(user)
+
post(:create, params: {
namespace_id: project.namespace,
project_id: project,
@@ -102,5 +118,26 @@ describe Projects::GroupLinksController do
expect(flash[:alert]).to eq('Please select a group.')
end
end
+
+ context 'when link is not persisted in the database' do
+ before do
+ allow(::Projects::GroupLinks::CreateService).to receive_message_chain(:new, :execute)
+ .and_return({ status: :error, http_status: 409, message: 'error' })
+
+ post(:create, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ link_group_id: group.id,
+ link_group_access: ProjectGroupLink.default_access
+ })
+ end
+
+ it 'redirects to project group links page' do
+ expect(response).to redirect_to(
+ project_project_members_path(project)
+ )
+ expect(flash[:alert]).to eq('error')
+ end
+ end
end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index a239ac16c0d..c34d7c13d57 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -42,7 +42,9 @@ describe Projects::IssuesController do
it_behaves_like "issuables list meta-data", :issue
- it_behaves_like 'set sort order from user preference'
+ it_behaves_like 'set sort order from user preference' do
+ let(:sorting_param) { 'updated_asc' }
+ end
it "returns index" do
get :index, params: { namespace_id: project.namespace, project_id: project }
@@ -66,7 +68,7 @@ describe Projects::IssuesController do
end
context 'with page param' do
- let(:last_page) { project.issues.page().total_pages }
+ let(:last_page) { project.issues.page.total_pages }
let!(:issue_list) { create_list(:issue, 2, project: project) }
before do
@@ -131,7 +133,7 @@ describe Projects::IssuesController do
it 'redirects to signin if not logged in' do
get :new, params: { namespace_id: project.namespace, project_id: project }
- expect(flash[:notice]).to eq 'Please sign in to create the new issue.'
+ expect(flash[:alert]).to eq 'You need to sign in or sign up before continuing.'
expect(response).to redirect_to(new_user_session_path)
end
@@ -377,6 +379,23 @@ describe Projects::IssuesController do
expect(response).to have_gitlab_http_status(200)
end
end
+
+ context 'when getting the changes' do
+ before do
+ project.add_developer(user)
+
+ sign_in(user)
+ end
+
+ it 'returns the necessary data' do
+ go(id: issue.iid)
+
+ data = JSON.parse(response.body)
+
+ expect(data).to include('title_text', 'description', 'description_text')
+ expect(data).to include('task_status', 'lock_version')
+ end
+ end
end
describe 'Confidential Issues' do
@@ -1026,6 +1045,59 @@ describe Projects::IssuesController do
end
end
+ describe 'POST #import_csv' do
+ let(:project) { create(:project, :public) }
+ let(:file) { fixture_file_upload('spec/fixtures/csv_comma.csv') }
+
+ context 'unauthorized' do
+ it 'returns 404 for guests' do
+ sign_out(:user)
+
+ import_csv
+
+ expect(response).to have_gitlab_http_status :not_found
+ end
+
+ it 'returns 404 for project members with reporter role' do
+ sign_in(user)
+ project.add_reporter(user)
+
+ import_csv
+
+ expect(response).to have_gitlab_http_status :not_found
+ end
+ end
+
+ context 'authorized' do
+ before do
+ sign_in(user)
+ project.add_developer(user)
+ end
+
+ it "returns 302 for project members with developer role" do
+ import_csv
+
+ expect(flash[:notice]).to include('Your issues are being imported')
+ expect(response).to redirect_to(project_issues_path(project))
+ end
+
+ it "shows error when upload fails" do
+ allow_any_instance_of(UploadService).to receive(:execute).and_return(nil)
+
+ import_csv
+
+ expect(flash[:alert]).to include('File upload error.')
+ expect(response).to redirect_to(project_issues_path(project))
+ end
+ end
+
+ def import_csv
+ post :import_csv, params: { namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ file: file }
+ end
+ end
+
describe 'GET #discussions' do
let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
context 'when authenticated' do
@@ -1065,6 +1137,7 @@ describe Projects::IssuesController do
context 'when user is setting notes filters' do
let(:issuable) { issue }
+ let(:issuable_parent) { project }
let!(:discussion_note) { create(:discussion_note_on_issue, :system, noteable: issuable, project: project) }
it_behaves_like 'issuable notes filter'
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index e1133fdd562..d8a331b3cf0 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -770,50 +770,6 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
- describe 'POST cancel_all' do
- before do
- project.add_developer(user)
- sign_in(user)
- end
-
- context 'when jobs are cancelable' do
- before do
- create_list(:ci_build, 2, :cancelable, pipeline: pipeline)
-
- post_cancel_all
- end
-
- it 'redirects to a index page' do
- expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to(namespace_project_jobs_path)
- end
-
- it 'transits to canceled' do
- expect(Ci::Build.all).to all(be_canceled)
- end
- end
-
- context 'when jobs are not cancelable' do
- before do
- create_list(:ci_build, 2, :canceled, pipeline: pipeline)
-
- post_cancel_all
- end
-
- it 'redirects to a index page' do
- expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to(namespace_project_jobs_path)
- end
- end
-
- def post_cancel_all
- post :cancel_all, params: {
- namespace_id: project.namespace,
- project_id: project
- }
- end
- end
-
describe 'POST erase' do
let(:role) { :maintainer }
@@ -892,36 +848,13 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context "when job has a trace artifact" do
let(:job) { create(:ci_build, :trace_artifact, pipeline: pipeline) }
- context 'when feature flag workhorse_set_content_type is' do
- before do
- stub_feature_flags(workhorse_set_content_type: flag_value)
- end
-
- context 'enabled' do
- let(:flag_value) { true }
-
- it "sets #{Gitlab::Workhorse::DETECT_HEADER} header" do
- response = subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers["Content-Type"]).to eq("text/plain; charset=utf-8")
- expect(response.body).to eq(job.job_artifacts_trace.open.read)
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
- end
- end
-
- context 'disabled' do
- let(:flag_value) { false }
-
- it 'returns a trace' do
- response = subject
+ it "sets #{Gitlab::Workhorse::DETECT_HEADER} header" do
+ response = subject
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers["Content-Type"]).to eq("text/plain; charset=utf-8")
- expect(response.body).to eq(job.job_artifacts_trace.open.read)
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to be nil
- end
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers["Content-Type"]).to eq("text/plain; charset=utf-8")
+ expect(response.body).to eq(job.job_artifacts_trace.open.read)
+ expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
end
diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb
index ac93393ac3a..f031a74c5bd 100644
--- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb
@@ -71,7 +71,7 @@ describe Projects::MergeRequests::CreationsController do
expect(response).to be_success
total = assigns(:total_commit_count)
- expect(assigns(:commits)).to be_an Array
+ expect(assigns(:commits)).to be_an CommitCollection
expect(total).to be > 0
expect(assigns(:hidden_commit_count)).to eq(0)
expect(response).to have_gitlab_http_status(200)
diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
index a6017d8e5e6..e85f32d6e30 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -4,10 +4,11 @@ describe Projects::MergeRequests::DiffsController do
include ProjectForksHelper
let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let(:user) { create(:user) }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
before do
+ project.add_maintainer(user)
sign_in(user)
end
@@ -114,16 +115,6 @@ describe Projects::MergeRequests::DiffsController do
expect(paths).to include(existing_path)
end
end
-
- context 'when the path does not exist in the diff' do
- before do
- diff_for_path(old_path: 'files/ruby/nopen.rb', new_path: 'files/ruby/nopen.rb')
- end
-
- it 'returns a 404' do
- expect(response).to have_gitlab_http_status(404)
- end
- end
end
context 'when the user cannot view the merge request' do
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 759a4b8bdce..79f97aa4170 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -78,6 +78,7 @@ describe Projects::MergeRequestsController do
context 'when user is setting notes filters' do
let(:issuable) { merge_request }
+ let(:issuable_parent) { project }
let!(:discussion_note) { create(:discussion_note_on_merge_request, :system, noteable: issuable, project: project) }
let!(:discussion_comment) { create(:discussion_note_on_merge_request, noteable: issuable, project: project) }
@@ -152,10 +153,12 @@ describe Projects::MergeRequestsController do
it_behaves_like "issuables list meta-data", :merge_request
- it_behaves_like 'set sort order from user preference'
+ it_behaves_like 'set sort order from user preference' do
+ let(:sorting_param) { 'updated_asc' }
+ end
context 'when page param' do
- let(:last_page) { project.merge_requests.page().total_pages }
+ let(:last_page) { project.merge_requests.page.total_pages }
let!(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
it 'redirects to last_page if page number is larger than number of pages' do
@@ -252,8 +255,8 @@ describe Projects::MergeRequestsController do
end
context 'there is no source project' do
- let(:project) { create(:project, :repository) }
- let(:forked_project) { fork_project_with_submodules(project) }
+ let(:project) { create(:project, :repository) }
+ let(:forked_project) { fork_project_with_submodules(project) }
let!(:merge_request) { create(:merge_request, source_project: forked_project, source_branch: 'add-submodule-version-bump', target_branch: 'master', target_project: project) }
before do
@@ -384,6 +387,23 @@ describe Projects::MergeRequestsController do
end
end
+ context 'when a squash commit message is passed' do
+ let(:message) { 'My custom squash commit message' }
+
+ it 'passes the same message to SquashService' do
+ params = { squash: '1', squash_commit_message: message }
+
+ expect_next_instance_of(MergeRequests::SquashService, project, user, params.merge(merge_request: merge_request)) do |squash_service|
+ expect(squash_service).to receive(:execute).and_return({
+ status: :success,
+ squash_sha: SecureRandom.hex(20)
+ })
+ end
+
+ merge_with_sha(params)
+ end
+ end
+
context 'when the pipeline succeeds is passed' do
let!(:head_pipeline) do
create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch, head_pipeline_of: merge_request)
@@ -883,7 +903,7 @@ describe Projects::MergeRequestsController do
end
describe 'POST #rebase' do
- let(:viewer) { user }
+ let(:viewer) { user }
def post_rebase
post :rebase, params: { namespace_id: project.namespace, project_id: project, id: merge_request }
@@ -942,6 +962,70 @@ describe Projects::MergeRequestsController do
end
end
+ describe 'GET discussions' do
+ context 'when authenticated' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+ end
+
+ it 'returns 200' do
+ get :discussions, params: { namespace_id: project.namespace, project_id: project, id: merge_request.iid }
+
+ expect(response.status).to eq(200)
+ end
+
+ context 'highlight preloading' do
+ context 'with commit diff notes' do
+ let!(:commit_diff_note) do
+ create(:diff_note_on_commit, project: merge_request.project)
+ end
+
+ it 'preloads notes diffs highlights' do
+ expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
+ note_diff_file = commit_diff_note.note_diff_file
+
+ expect(collection).to receive(:load_highlight).with([note_diff_file.id]).and_call_original
+ expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original
+ end
+
+ get :discussions, params: { namespace_id: project.namespace, project_id: project, id: merge_request.iid }
+ end
+ end
+
+ context 'with diff notes' do
+ let!(:diff_note) do
+ create(:diff_note_on_merge_request, noteable: merge_request, project: merge_request.project)
+ end
+
+ it 'preloads notes diffs highlights' do
+ expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
+ note_diff_file = diff_note.note_diff_file
+
+ expect(collection).to receive(:load_highlight).with([note_diff_file.id]).and_call_original
+ expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original
+ end
+
+ get :discussions, params: { namespace_id: project.namespace, project_id: project, id: merge_request.iid }
+ end
+
+ it 'does not preload highlights when diff note is resolved' do
+ Notes::ResolveService.new(diff_note.project, user).execute(diff_note)
+
+ expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
+ note_diff_file = diff_note.note_diff_file
+
+ expect(collection).to receive(:load_highlight).with([]).and_call_original
+ expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original
+ end
+
+ get :discussions, params: { namespace_id: project.namespace, project_id: project, id: merge_request.iid }
+ end
+ end
+ end
+ end
+ end
+
describe 'GET edit' do
it 'responds successfully' do
get :edit, params: { namespace_id: project.namespace, project_id: project, id: merge_request }
diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb
index 5892024e756..ac54b3c3952 100644
--- a/spec/controllers/projects/milestones_controller_spec.rb
+++ b/spec/controllers/projects/milestones_controller_spec.rb
@@ -42,10 +42,11 @@ describe Projects::MilestonesController do
describe "#index" do
context "as html" do
- def render_index(project:, page:)
+ def render_index(project:, page:, search_title: '')
get :index, params: {
namespace_id: project.namespace.id,
project_id: project.id,
+ search_title: search_title,
page: page
}
end
@@ -59,6 +60,15 @@ describe Projects::MilestonesController do
expect(milestones.where(project_id: nil)).to be_empty
end
+ it 'searches milestones by title when search_title is given' do
+ milestone1 = create(:milestone, title: 'Project milestone title', project: project)
+
+ render_index project: project, page: 1, search_title: 'Project mile'
+
+ milestones = assigns(:milestones)
+ expect(milestones).to eq([milestone1])
+ end
+
it 'renders paginated milestones without missing or duplicates' do
allow(Milestone).to receive(:default_per_page).and_return(2)
create_list(:milestone, 5, project: project)
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index 81892575889..0b0f5117784 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -252,8 +252,8 @@ describe Projects::NotesController do
note: 'some note',
noteable_id: merge_request.id.to_s,
noteable_type: 'MergeRequest',
- merge_request_diff_head_sha: 'sha',
- in_reply_to_discussion_id: nil
+ commit_id: nil,
+ merge_request_diff_head_sha: 'sha'
}).permit!
expect(Notes::CreateService).to receive(:new).with(project, user, service_params).and_return(double(execute: true))
@@ -266,6 +266,22 @@ describe Projects::NotesController do
end
end
+ context 'when creating a comment on a commit with SHA1 starting with a large number' do
+ let(:commit) { create(:commit, project: project, id: '842616594688d2351480dfebd67b3d8d15571e6d') }
+
+ it 'creates a note successfully' do
+ expect do
+ post :create, params: {
+ note: { note: 'some note', commit_id: commit.id },
+ namespace_id: project.namespace,
+ project_id: project,
+ target_type: 'commit',
+ target_id: commit.id
+ }
+ end.to change { Note.count }.by(1)
+ end
+ end
+
context 'when creating a commit comment from an MR fork' do
let(:project) { create(:project, :repository) }
diff --git a/spec/controllers/projects/pages_controller_spec.rb b/spec/controllers/projects/pages_controller_spec.rb
index 382c1b5d124..d6eece47804 100644
--- a/spec/controllers/projects/pages_controller_spec.rb
+++ b/spec/controllers/projects/pages_controller_spec.rb
@@ -28,10 +28,10 @@ describe Projects::PagesController do
let(:group) { create(:group, :nested) }
let(:project) { create(:project, namespace: group) }
- it 'returns a 404 status code' do
+ it 'returns a 200 status code' do
get :show, params: request_params
- expect(response).to have_gitlab_http_status(404)
+ expect(response).to have_gitlab_http_status(200)
end
end
end
@@ -42,6 +42,18 @@ describe Projects::PagesController do
expect(response).to have_gitlab_http_status(302)
end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'returns 404 status' do
+ delete :destroy, params: request_params
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
end
context 'pages disabled' do
diff --git a/spec/controllers/projects/pages_domains_controller_spec.rb b/spec/controllers/projects/pages_domains_controller_spec.rb
index 8b7f7587701..ffb9867a203 100644
--- a/spec/controllers/projects/pages_domains_controller_spec.rb
+++ b/spec/controllers/projects/pages_domains_controller_spec.rb
@@ -23,12 +23,27 @@ describe Projects::PagesDomainsController do
end
describe 'GET show' do
- it "displays the 'show' page" do
+ def make_request
get(:show, params: request_params.merge(id: pages_domain.domain))
+ end
+ it "displays the 'show' page" do
+ make_request
expect(response).to have_gitlab_http_status(200)
expect(response).to render_template('show')
end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'renders 404 page' do
+ make_request
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
end
describe 'GET new' do
diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
index 80506249ea9..fa732437fc1 100644
--- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb
+++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
@@ -3,9 +3,14 @@ require 'spec_helper'
describe Projects::PipelineSchedulesController do
include AccessMatchersForController
+ set(:user) { create(:user) }
set(:project) { create(:project, :public, :repository) }
set(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project) }
+ before do
+ project.add_developer(user)
+ end
+
describe 'GET #index' do
render_views
@@ -14,6 +19,10 @@ describe Projects::PipelineSchedulesController do
create(:ci_pipeline_schedule, :inactive, project: project)
end
+ before do
+ sign_in(user)
+ end
+
it 'renders the index view' do
visit_pipelines_schedules
@@ -21,7 +30,7 @@ describe Projects::PipelineSchedulesController do
expect(response).to render_template(:index)
end
- it 'avoids N + 1 queries' do
+ it 'avoids N + 1 queries', :request_store do
control_count = ActiveRecord::QueryRecorder.new { visit_pipelines_schedules }.count
create_list(:ci_pipeline_schedule, 2, project: project)
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index 0bb3ef76a3b..ece8532cb84 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -5,7 +5,7 @@ describe Projects::PipelinesController do
set(:user) { create(:user) }
let(:project) { create(:project, :public, :repository) }
- let(:feature) { ProjectFeature::DISABLED }
+ let(:feature) { ProjectFeature::ENABLED }
before do
stub_not_protect_default_branch
@@ -50,7 +50,7 @@ describe Projects::PipelinesController do
end
end
- context 'when using legacy stages', :request_store do
+ context 'when using legacy stages', :request_store do
before do
stub_feature_flags(ci_pipeline_persisted_stages: false)
end
@@ -186,6 +186,27 @@ describe Projects::PipelinesController do
end
end
+ context 'when builds are disabled' do
+ let(:feature) { ProjectFeature::DISABLED }
+
+ it 'users can not see internal pipelines' do
+ get_pipeline_json
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when pipeline is external' do
+ let(:pipeline) { create(:ci_pipeline, source: :external, project: project) }
+
+ it 'users can see the external pipeline' do
+ get_pipeline_json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['id']).to be(pipeline.id)
+ end
+ end
+ end
+
def get_pipeline_json
get :show, params: { namespace_id: project.namespace, project_id: project, id: pipeline }, format: :json
end
@@ -326,16 +347,14 @@ describe Projects::PipelinesController do
format: :json
end
- context 'when builds are enabled' do
- let(:feature) { ProjectFeature::ENABLED }
-
- it 'retries a pipeline without returning any content' do
- expect(response).to have_gitlab_http_status(:no_content)
- expect(build.reload).to be_retried
- end
+ it 'retries a pipeline without returning any content' do
+ expect(response).to have_gitlab_http_status(:no_content)
+ expect(build.reload).to be_retried
end
context 'when builds are disabled' do
+ let(:feature) { ProjectFeature::DISABLED }
+
it 'fails to retry pipeline' do
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -355,16 +374,14 @@ describe Projects::PipelinesController do
format: :json
end
- context 'when builds are enabled' do
- let(:feature) { ProjectFeature::ENABLED }
-
- it 'cancels a pipeline without returning any content' do
- expect(response).to have_gitlab_http_status(:no_content)
- expect(pipeline.reload).to be_canceled
- end
+ it 'cancels a pipeline without returning any content' do
+ expect(response).to have_gitlab_http_status(:no_content)
+ expect(pipeline.reload).to be_canceled
end
context 'when builds are disabled' do
+ let(:feature) { ProjectFeature::DISABLED }
+
it 'fails to retry pipeline' do
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb
index 24e2441cf9d..cffdf30da6b 100644
--- a/spec/controllers/projects/raw_controller_spec.rb
+++ b/spec/controllers/projects/raw_controller_spec.rb
@@ -16,74 +16,27 @@ describe Projects::RawController do
context 'regular filename' do
let(:filepath) { 'master/README.md' }
- context 'when feature flag workhorse_set_content_type is' do
- before do
- stub_feature_flags(workhorse_set_content_type: flag_value)
-
- subject
- end
-
- context 'enabled' do
- let(:flag_value) { true }
-
- it 'delivers ASCII file' do
- expect(response).to have_gitlab_http_status(200)
- expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(response.header['Content-Disposition']).to eq('inline')
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
- end
- end
-
- context 'disabled' do
- let(:flag_value) { false }
-
- it 'delivers ASCII file' do
- expect(response).to have_gitlab_http_status(200)
- expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(response.header['Content-Disposition']).to eq('inline')
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq nil
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
- end
- end
+ it 'delivers ASCII file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
+ expect(response.header['Content-Disposition']).to eq('inline')
+ expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
end
end
context 'image header' do
let(:filepath) { 'master/files/images/6049019_460s.jpg' }
- context 'when feature flag workhorse_set_content_type is' do
- before do
- stub_feature_flags(workhorse_set_content_type: flag_value)
- end
-
- context 'enabled' do
- let(:flag_value) { true }
-
- it 'leaves image content disposition' do
- subject
-
- expect(response).to have_gitlab_http_status(200)
- expect(response.header['Content-Type']).to eq('image/jpeg')
- expect(response.header['Content-Disposition']).to eq('inline')
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
- end
- end
-
- context 'disabled' do
- let(:flag_value) { false }
-
- it 'sets image content type header' do
- subject
+ it 'leaves image content disposition' do
+ subject
- expect(response).to have_gitlab_http_status(200)
- expect(response.header['Content-Type']).to eq('image/jpeg')
- expect(response.header['Content-Disposition']).to eq('inline')
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq nil
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
- end
- end
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.header['Content-Disposition']).to eq('inline')
+ expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
end
end
diff --git a/spec/controllers/projects/registry/tags_controller_spec.rb b/spec/controllers/projects/registry/tags_controller_spec.rb
index ed0197afcfc..74ed89ba1c3 100644
--- a/spec/controllers/projects/registry/tags_controller_spec.rb
+++ b/spec/controllers/projects/registry/tags_controller_spec.rb
@@ -19,7 +19,7 @@ describe Projects::Registry::TagsController do
end
before do
- stub_container_registry_tags(repository: /image/, tags: tags)
+ stub_container_registry_tags(repository: /image/, tags: tags, with_manifest: true)
end
context 'when user can control the registry' do
diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb
index f170a2ab613..5b9d21d3d5b 100644
--- a/spec/controllers/projects/releases_controller_spec.rb
+++ b/spec/controllers/projects/releases_controller_spec.rb
@@ -6,10 +6,6 @@ describe Projects::ReleasesController do
let!(:project) { create(:project, :repository, :public) }
let!(:user) { create(:user) }
- before do
- stub_feature_flags(releases_page: true)
- end
-
describe 'GET #index' do
it 'renders a 200' do
get_index
@@ -43,18 +39,6 @@ describe Projects::ReleasesController do
expect(response.status).to eq(404)
end
end
-
- context 'when releases_page feature flag is disabled' do
- before do
- stub_feature_flags(releases_page: false)
- end
-
- it 'renders a 404' do
- get_index
-
- expect(response.status).to eq(404)
- end
- end
end
private
diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb
index a9759c4fbd8..276cf340962 100644
--- a/spec/controllers/projects/serverless/functions_controller_spec.rb
+++ b/spec/controllers/projects/serverless/functions_controller_spec.rb
@@ -45,13 +45,49 @@ describe Projects::Serverless::FunctionsController do
end
end
+ describe 'GET #show' do
+ context 'invalid data' do
+ it 'has a bad function name' do
+ get :show, params: params({ format: :json, environment_id: "*", id: "foo" })
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'valid data', :use_clean_rails_memory_store_caching do
+ before do
+ stub_kubeclient_service_pods
+ stub_reactive_cache(knative,
+ {
+ services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
+ pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
+ })
+ end
+
+ it 'has a valid function name' do
+ get :show, params: params({ format: :json, environment_id: "*", id: cluster.project.name })
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response).to include(
+ "name" => project.name,
+ "url" => "http://#{project.name}.#{namespace.namespace}.example.com",
+ "podcount" => 1
+ )
+ end
+ end
+ end
+
describe 'GET #index with data', :use_clean_rails_memory_store_caching do
before do
- stub_reactive_cache(knative, services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"])
+ stub_kubeclient_service_pods
+ stub_reactive_cache(knative,
+ {
+ services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
+ pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
+ })
end
it 'has data' do
- get :index, params: params({ format: :json })
+ get :index, params: params({ format: :json })
expect(response).to have_gitlab_http_status(200)
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index 4a5d2bdecb7..601a292bf54 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -152,6 +152,16 @@ describe Projects::ServicesController do
expect(service.namespace).not_to eq('updated_namespace')
end
end
+
+ context 'when activating JIRA service from a template' do
+ let(:template_service) { create(:jira_service, project: project, template: true) }
+
+ it 'activate JIRA service from template' do
+ put :update, params: { namespace_id: project.namespace, project_id: project, id: service.to_param, service: { active: true } }
+
+ expect(flash[:notice]).to eq 'JIRA activated.'
+ end
+ end
end
describe "GET #edit" do
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
new file mode 100644
index 00000000000..02a392f23c2
--- /dev/null
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -0,0 +1,174 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::Settings::OperationsController do
+ set(:user) { create(:user) }
+ set(:project) { create(:project) }
+
+ before do
+ sign_in(user)
+ project.add_maintainer(user)
+ end
+
+ context 'error tracking' do
+ describe 'GET #show' do
+ it 'renders show template' do
+ get :show, params: project_params(project)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:show)
+ end
+
+ context 'with existing setting' do
+ let!(:error_tracking_setting) do
+ create(:project_error_tracking_setting, project: project)
+ end
+
+ it 'loads existing setting' do
+ get :show, params: project_params(project)
+
+ expect(controller.helpers.error_tracking_setting)
+ .to eq(error_tracking_setting)
+ end
+ end
+
+ context 'without an existing setting' do
+ it 'builds a new setting' do
+ get :show, params: project_params(project)
+
+ expect(controller.helpers.error_tracking_setting).to be_new_record
+ end
+ end
+
+ context 'with insufficient permissions' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'renders 404' do
+ get :show, params: project_params(project)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'as an anonymous user' do
+ before do
+ sign_out(user)
+ end
+
+ it 'redirects to signup page' do
+ get :show, params: project_params(project)
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ describe 'PATCH #update' do
+ let(:operations_update_service) { spy(:operations_update_service) }
+ let(:operations_url) { project_settings_operations_url(project) }
+
+ let(:error_tracking_params) do
+ {
+ error_tracking_setting_attributes: {
+ enabled: '1',
+ api_host: 'http://url',
+ token: 'token',
+ project: {
+ slug: 'sentry-project',
+ name: 'Sentry Project',
+ organization_slug: 'sentry-org',
+ organization_name: 'Sentry Org'
+ }
+ }
+ }
+ end
+
+ let(:error_tracking_permitted) do
+ ActionController::Parameters.new(error_tracking_params).permit!
+ end
+
+ context 'format json' do
+ context 'when update succeeds' do
+ before do
+ stub_operations_update_service_returning(status: :success)
+ end
+
+ it 'returns success status' do
+ patch :update,
+ params: project_params(project, error_tracking_params),
+ format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq('status' => 'success')
+ expect(flash[:notice]).to eq('Your changes have been saved')
+ end
+ end
+
+ context 'when update fails' do
+ before do
+ stub_operations_update_service_returning(
+ status: :error,
+ message: 'error message'
+ )
+ end
+
+ it 'returns error' do
+ patch :update,
+ params: project_params(project, error_tracking_params),
+ format: :json
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).not_to be_nil
+ end
+ end
+ end
+
+ context 'with insufficient permissions' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'renders 404' do
+ patch :update, params: project_params(project)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'as an anonymous user' do
+ before do
+ sign_out(user)
+ end
+
+ it 'redirects to signup page' do
+ patch :update, params: project_params(project)
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ private
+
+ def stub_operations_update_service_returning(return_value = {})
+ expect(::Projects::Operations::UpdateService)
+ .to receive(:new).with(project, user, error_tracking_permitted)
+ .and_return(operations_update_service)
+ expect(operations_update_service).to receive(:execute)
+ .and_return(return_value)
+ end
+ end
+
+ private
+
+ def project_params(project, params = {})
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ project: params
+ }
+ end
+end
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index 1a3fb4da15f..8d9cb2c8ac0 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -12,7 +12,7 @@ describe Projects::SnippetsController do
describe 'GET #index' do
context 'when page param' do
- let(:last_page) { project.snippets.page().total_pages }
+ let(:last_page) { project.snippets.page.total_pages }
let!(:project_snippet) { create(:project_snippet, :public, project: project, author: user) }
it 'redirects to last_page if page number is larger than number of pages' do
@@ -379,6 +379,46 @@ describe Projects::SnippetsController do
end
end
+ describe "GET #show for embeddable content" do
+ let(:project_snippet) { create(:project_snippet, snippet_permission, project: project, author: user) }
+
+ before do
+ sign_in(user)
+
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: project_snippet.to_param }, format: :js
+ end
+
+ context 'when snippet is private' do
+ let(:snippet_permission) { :private }
+
+ it 'responds with status 404' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when snippet is public' do
+ let(:snippet_permission) { :public }
+
+ it 'responds with status 200' do
+ expect(assigns(:snippet)).to eq(project_snippet)
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
+ context 'when the project is private' do
+ let(:project) { create(:project_empty_repo, :private) }
+
+ context 'when snippet is public' do
+ let(:project_snippet) { create(:project_snippet, :public, project: project, author: user) }
+
+ it 'responds with status 404' do
+ expect(assigns(:snippet)).to eq(project_snippet)
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+ end
+
describe 'GET #raw' do
let(:project_snippet) do
create(
diff --git a/spec/controllers/projects/wikis_controller_spec.rb b/spec/controllers/projects/wikis_controller_spec.rb
index 341bf244397..b2f40231796 100644
--- a/spec/controllers/projects/wikis_controller_spec.rb
+++ b/spec/controllers/projects/wikis_controller_spec.rb
@@ -52,56 +52,24 @@ describe Projects::WikisController do
let(:path) { upload_file_to_wiki(project, user, file_name) }
- subject { get :show, params: { namespace_id: project.namespace, project_id: project, id: path } }
+ before do
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: path }
+ end
context 'when file is an image' do
let(:file_name) { 'dk.png' }
- context 'when feature flag workhorse_set_content_type is' do
- before do
- stub_feature_flags(workhorse_set_content_type: flag_value)
-
- subject
- end
-
- context 'enabled' do
- let(:flag_value) { true }
-
- it 'delivers the image' do
- expect(response.headers['Content-Type']).to eq('image/png')
- expect(response.headers['Content-Disposition']).to match(/^inline/)
- expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
- end
-
- context 'when file is a svg' do
- let(:file_name) { 'unsanitized.svg' }
-
- it 'delivers the image' do
- expect(response.headers['Content-Type']).to eq('image/svg+xml')
- expect(response.headers['Content-Disposition']).to match(/^attachment/)
- expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
- end
- end
- end
-
- context 'disabled' do
- let(:flag_value) { false }
-
- it 'renders the content inline' do
- expect(response.headers['Content-Type']).to eq('image/png')
- expect(response.headers['Content-Disposition']).to match(/^inline/)
- expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq nil
- end
+ it 'delivers the image' do
+ expect(response.headers['Content-Disposition']).to match(/^inline/)
+ expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ end
- context 'when file is a svg' do
- let(:file_name) { 'unsanitized.svg' }
+ context 'when file is a svg' do
+ let(:file_name) { 'unsanitized.svg' }
- it 'renders the content as an attachment' do
- expect(response.headers['Content-Type']).to eq('image/svg+xml')
- expect(response.headers['Content-Disposition']).to match(/^attachment/)
- expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq nil
- end
- end
+ it 'delivers the image' do
+ expect(response.headers['Content-Disposition']).to match(/^inline/)
+ expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
end
end
@@ -109,32 +77,9 @@ describe Projects::WikisController do
context 'when file is a pdf' do
let(:file_name) { 'git-cheat-sheet.pdf' }
- context 'when feature flag workhorse_set_content_type is' do
- before do
- stub_feature_flags(workhorse_set_content_type: flag_value)
-
- subject
- end
-
- context 'enabled' do
- let(:flag_value) { true }
-
- it 'sets the content type to sets the content response headers' do
- expect(response.headers['Content-Type']).to eq 'application/octet-stream'
- expect(response.headers['Content-Disposition']).to match(/^inline/)
- expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
- end
- end
-
- context 'disabled' do
- let(:flag_value) { false }
-
- it 'sets the content response headers' do
- expect(response.headers['Content-Type']).to eq 'application/octet-stream'
- expect(response.headers['Content-Disposition']).to match(/^inline/)
- expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq nil
- end
- end
+ it 'sets the content type to sets the content response headers' do
+ expect(response.headers['Content-Disposition']).to match(/^inline/)
+ expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
end
end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index ea067a01295..a1662658ade 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -456,7 +456,7 @@ describe ProjectsController do
end
context "when the project is forked" do
- let(:project) { create(:project, :repository) }
+ let(:project) { create(:project, :repository) }
let(:forked_project) { fork_project(project, nil, repository: true) }
let(:merge_request) do
create(:merge_request,
@@ -621,10 +621,10 @@ describe ProjectsController do
end
describe "GET refs" do
- let(:public_project) { create(:project, :public, :repository) }
+ let(:project) { create(:project, :public, :repository) }
it 'gets a list of branches and tags' do
- get :refs, params: { namespace_id: public_project.namespace, id: public_project, sort: 'updated_desc' }
+ get :refs, params: { namespace_id: project.namespace, id: project, sort: 'updated_desc' }
parsed_body = JSON.parse(response.body)
expect(parsed_body['Branches']).to include('master')
@@ -634,7 +634,7 @@ describe ProjectsController do
end
it "gets a list of branches, tags and commits" do
- get :refs, params: { namespace_id: public_project.namespace, id: public_project, ref: "123456" }
+ get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
parsed_body = JSON.parse(response.body)
expect(parsed_body["Branches"]).to include("master")
@@ -649,7 +649,7 @@ describe ProjectsController do
end
it "gets a list of branches, tags and commits" do
- get :refs, params: { namespace_id: public_project.namespace, id: public_project, ref: "123456" }
+ get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
parsed_body = JSON.parse(response.body)
expect(parsed_body["Branches"]).to include("master")
@@ -657,6 +657,22 @@ describe ProjectsController do
expect(parsed_body["Commits"]).to include("123456")
end
end
+
+ context 'when private project' do
+ let(:project) { create(:project, :repository) }
+
+ context 'as a guest' do
+ it 'renders forbidden' do
+ user = create(:user)
+ project.add_guest(user)
+
+ sign_in(user)
+ get :refs, params: { namespace_id: project.namespace, id: project }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
end
describe 'POST #preview_markdown' do
@@ -939,6 +955,59 @@ describe ProjectsController do
end
end
+ describe 'GET resolve' do
+ shared_examples 'resolvable endpoint' do
+ it 'redirects to the project page' do
+ get :resolve, params: { id: project.id }
+
+ expect(response).to have_gitlab_http_status(302)
+ expect(response).to redirect_to(project_path(project))
+ end
+ end
+
+ context 'with an authenticated user' do
+ before do
+ sign_in(user)
+ end
+
+ context 'when user has access to the project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'resolvable endpoint'
+ end
+
+ context 'when user has no access to the project' do
+ it 'gives 404 for existing project' do
+ get :resolve, params: { id: project.id }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ it 'gives 404 for non-existing project' do
+ get :resolve, params: { id: '0' }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'non authenticated user' do
+ context 'with a public project' do
+ let(:project) { public_project }
+
+ it_behaves_like 'resolvable endpoint'
+ end
+
+ it 'gives 404 for private project' do
+ get :resolve, params: { id: project.id }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
def project_moved_message(redirect_route, project)
"Project '#{redirect_route.path}' was moved to '#{project.full_path}'. Please update any links and bookmarks that may still have the old path."
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index c9b53336fd1..02a0cfe0272 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe SearchController do
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
before do
sign_in(user)
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index 01a5161f775..77a94f26d8c 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -80,6 +80,12 @@ describe SnippetsController do
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_gitlab_http_status(200)
end
+
+ it 'responds with status 404 when embeddable content is requested' do
+ get :show, params: { id: personal_snippet.to_param }, format: :js
+
+ expect(response).to have_gitlab_http_status(404)
+ end
end
end
@@ -106,6 +112,12 @@ describe SnippetsController do
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_gitlab_http_status(200)
end
+
+ it 'responds with status 404 when embeddable content is requested' do
+ get :show, params: { id: personal_snippet.to_param }, format: :js
+
+ expect(response).to have_gitlab_http_status(404)
+ end
end
context 'when not signed in' do
@@ -131,6 +143,13 @@ describe SnippetsController do
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_gitlab_http_status(200)
end
+
+ it 'responds with status 200 when embeddable content is requested' do
+ get :show, params: { id: personal_snippet.to_param }, format: :js
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response).to have_gitlab_http_status(200)
+ end
end
context 'when not signed in' do
@@ -186,6 +205,8 @@ describe SnippetsController do
end
context 'when the snippet description contains a file' do
+ include FileMoverHelpers
+
let(:picture_file) { '/-/system/temp/secret56/picture.jpg' }
let(:text_file) { '/-/system/temp/secret78/text.txt' }
let(:description) do
@@ -196,6 +217,8 @@ describe SnippetsController do
before do
allow(FileUtils).to receive(:mkdir_p)
allow(FileUtils).to receive(:move)
+ stub_file_mover(text_file)
+ stub_file_mover(picture_file)
end
subject { create_snippet({ description: description }, { files: [picture_file, text_file] }) }
@@ -437,10 +460,7 @@ describe SnippetsController do
end
context 'when signed in user is the author' do
- let(:flag_value) { false }
-
before do
- stub_feature_flags(workhorse_set_content_type: flag_value)
get :raw, params: { id: personal_snippet.to_param }
end
@@ -455,22 +475,9 @@ describe SnippetsController do
expect(response.header['Content-Disposition']).to match(/inline/)
end
- context 'when feature flag workhorse_set_content_type is' do
- context 'enabled' do
- let(:flag_value) { true }
-
- it "sets #{Gitlab::Workhorse::DETECT_HEADER} header" do
- expect(response).to have_gitlab_http_status(200)
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
- end
- end
-
- context 'disabled' do
- it "does not set #{Gitlab::Workhorse::DETECT_HEADER} header" do
- expect(response).to have_gitlab_http_status(200)
- expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to be nil
- end
- end
+ it "sets #{Gitlab::Workhorse::DETECT_HEADER} header" do
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
end
end
diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb
index 19142aa1272..e52a5fe42f2 100644
--- a/spec/controllers/uploads_controller_spec.rb
+++ b/spec/controllers/uploads_controller_spec.rb
@@ -12,6 +12,12 @@ shared_examples 'content not cached without revalidation and no-store' do
end
end
+shared_examples 'content publicly cached' do
+ it 'ensures content is publicly cached' do
+ expect(subject['Cache-Control']).to eq('max-age=300, public')
+ end
+end
+
describe UploadsController do
let!(:user) { create(:user, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) }
@@ -184,7 +190,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation and no-store' do
+ it_behaves_like 'content publicly cached' do
subject do
get :show, params: { model: 'user', mounted_as: 'avatar', id: user.id, filename: 'dk.png' }
@@ -201,7 +207,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content publicly cached' do
subject do
get :show, params: { model: 'user', mounted_as: 'avatar', id: user.id, filename: 'dk.png' }
@@ -321,7 +327,7 @@ describe UploadsController do
end
context "when viewing a group avatar" do
- let!(:group) { create(:group, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) }
+ let!(:group) { create(:group, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) }
context "when the group is public" do
context "when not signed in" do
@@ -537,7 +543,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content publicly cached' do
subject do
get :show, params: { model: 'appearance', mounted_as: 'header_logo', id: appearance.id, filename: 'dk.png' }
@@ -557,7 +563,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content publicly cached' do
subject do
get :show, params: { model: 'appearance', mounted_as: 'logo', id: appearance.id, filename: 'dk.png' }
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index 27edf226ca3..4f6a6881193 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -185,13 +185,32 @@ describe UsersController do
context 'for user' do
context 'with public profile' do
- it 'renders calendar_activities' do
- push_data = Gitlab::DataBuilder::Push.build_sample(project, public_user)
- EventCreateService.new.push(project, public_user, push_data)
+ let(:issue) { create(:issue, project: project, author: user) }
+ let(:note) { create(:note, noteable: issue, author: user, project: project) }
+ render_views
+
+ before do
+ create_push_event
+ create_note_event
+ end
+
+ it 'renders calendar_activities' do
get :calendar_activities, params: { username: public_user.username }
+
expect(assigns[:events]).not_to be_empty
end
+
+ it 'avoids N+1 queries', :request_store do
+ get :calendar_activities, params: { username: public_user.username }
+
+ control = ActiveRecord::QueryRecorder.new { get :calendar_activities, params: { username: public_user.username } }
+
+ create_push_event
+ create_note_event
+
+ expect { get :calendar_activities, params: { username: public_user.username } }.not_to exceed_query_limit(control)
+ end
end
context 'with private profile' do
@@ -203,6 +222,47 @@ describe UsersController do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ def create_push_event
+ push_data = Gitlab::DataBuilder::Push.build_sample(project, public_user)
+ EventCreateService.new.push(project, public_user, push_data)
+ end
+
+ def create_note_event
+ EventCreateService.new.leave_note(note, public_user)
+ end
+ end
+ end
+
+ describe 'GET #contributed' do
+ let(:project) { create(:project, :public) }
+ let(:current_user) { create(:user) }
+
+ before do
+ sign_in(current_user)
+
+ project.add_developer(public_user)
+ project.add_developer(private_user)
+ end
+
+ context 'with public profile' do
+ it 'renders contributed projects' do
+ create(:push_event, project: project, author: public_user)
+
+ get :contributed, params: { username: public_user.username }
+
+ expect(assigns[:contributed_projects]).not_to be_empty
+ end
+ end
+
+ context 'with private profile' do
+ it 'does not render contributed projects' do
+ create(:push_event, project: project, author: private_user)
+
+ get :contributed, params: { username: private_user.username }
+
+ expect(assigns[:contributed_projects]).to be_empty
+ end
end
end
diff --git a/spec/db/importers/common_metrics_importer_spec.rb b/spec/db/importers/common_metrics_importer_spec.rb
index 68260820958..6133b17ac61 100644
--- a/spec/db/importers/common_metrics_importer_spec.rb
+++ b/spec/db/importers/common_metrics_importer_spec.rb
@@ -4,12 +4,18 @@ require 'rails_helper'
require Rails.root.join("db", "importers", "common_metrics_importer.rb")
describe Importers::PrometheusMetric do
+ let(:existing_group_titles) do
+ ::PrometheusMetric::GROUP_DETAILS.each_with_object({}) do |(key, value), memo|
+ memo[key] = value[:group_title]
+ end
+ end
+
it 'group enum equals ::PrometheusMetric' do
expect(described_class.groups).to eq(::PrometheusMetric.groups)
end
it 'GROUP_TITLES equals ::PrometheusMetric' do
- expect(described_class::GROUP_TITLES).to eq(::PrometheusMetric::GROUP_TITLES)
+ expect(described_class::GROUP_TITLES).to eq(existing_group_titles)
end
end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 7c505ee0d43..897b4411055 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -64,6 +64,7 @@ describe 'Database schema' do
let(:indexes) { connection.indexes(table) }
let(:columns) { connection.columns(table) }
let(:foreign_keys) { connection.foreign_keys(table) }
+ let(:primary_key_column) { connection.primary_key(table) }
context 'all foreign keys' do
# for index to be effective, the FK constraint has to be at first place
@@ -71,6 +72,12 @@ describe 'Database schema' do
first_indexed_column = indexes.map(&:columns).map(&:first)
foreign_keys_columns = foreign_keys.map(&:column)
+ # Add the primary key column to the list of indexed columns because
+ # postgres and mysql both automatically create an index on the primary
+ # key. Also, the rails connection.indexes() method does not return
+ # automatically generated indexes (like the primary key index).
+ first_indexed_column = first_indexed_column.push(primary_key_column)
+
expect(first_indexed_column.uniq).to include(*foreign_keys_columns)
end
end
diff --git a/spec/factories/appearances.rb b/spec/factories/appearances.rb
index 18c7453bd1b..dd5129229d4 100644
--- a/spec/factories/appearances.rb
+++ b/spec/factories/appearances.rb
@@ -15,6 +15,10 @@ FactoryBot.define do
header_logo { fixture_file_upload('spec/fixtures/dk.png') }
end
+ trait :with_favicon do
+ favicon { fixture_file_upload('spec/fixtures/dk.png') }
+ end
+
trait :with_logos do
with_logo
with_header_logo
diff --git a/spec/factories/ci/bridge.rb b/spec/factories/ci/bridge.rb
index 5f83b80ad7b..b1d82b98411 100644
--- a/spec/factories/ci/bridge.rb
+++ b/spec/factories/ci/bridge.rb
@@ -10,8 +10,20 @@ FactoryBot.define do
pipeline factory: :ci_pipeline
+ trait :variables do
+ yaml_variables [{ key: 'BRIDGE', value: 'cross', public: true }]
+ end
+
+ transient { downstream nil }
+
after(:build) do |bridge, evaluator|
bridge.project ||= bridge.pipeline.project
+
+ if evaluator.downstream.present?
+ bridge.options = bridge.options.to_h.merge(
+ trigger: { project: evaluator.downstream.full_path }
+ )
+ end
end
end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 07c1fc31152..0b3e67b4987 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -7,7 +7,6 @@ FactoryBot.define do
stage_idx 0
ref 'master'
tag false
- commands 'ls -a'
protected false
created_at 'Di 29. Okt 09:50:00 CET 2013'
pending
@@ -15,7 +14,8 @@ FactoryBot.define do
options do
{
image: 'ruby:2.1',
- services: ['postgres']
+ services: ['postgres'],
+ script: ['ls -a']
}
end
@@ -28,7 +28,6 @@ FactoryBot.define do
pipeline factory: :ci_pipeline
trait :degenerated do
- commands nil
options nil
yaml_variables nil
end
@@ -79,7 +78,7 @@ FactoryBot.define do
trait :scheduled do
schedulable
status 'scheduled'
- scheduled_at { 1.minute.since }
+ scheduled_at { 1.minute.since }
end
trait :expired_scheduled do
@@ -95,33 +94,53 @@ FactoryBot.define do
trait :teardown_environment do
environment 'staging'
- options environment: { name: 'staging',
- action: 'stop',
- url: 'http://staging.example.com/$CI_JOB_NAME' }
+ options do
+ {
+ script: %w(ls),
+ environment: { name: 'staging',
+ action: 'stop',
+ url: 'http://staging.example.com/$CI_JOB_NAME' }
+ }
+ end
end
trait :deploy_to_production do
environment 'production'
- options environment: { name: 'production',
- url: 'http://prd.example.com/$CI_JOB_NAME' }
+ options do
+ {
+ script: %w(ls),
+ environment: { name: 'production',
+ url: 'http://prd.example.com/$CI_JOB_NAME' }
+ }
+ end
end
trait :start_review_app do
environment 'review/$CI_COMMIT_REF_NAME'
- options environment: { name: 'review/$CI_COMMIT_REF_NAME',
- url: 'http://staging.example.com/$CI_JOB_NAME',
- on_stop: 'stop_review_app' }
+ options do
+ {
+ script: %w(ls),
+ environment: { name: 'review/$CI_COMMIT_REF_NAME',
+ url: 'http://staging.example.com/$CI_JOB_NAME',
+ on_stop: 'stop_review_app' }
+ }
+ end
end
trait :stop_review_app do
name 'stop_review_app'
environment 'review/$CI_COMMIT_REF_NAME'
- options environment: { name: 'review/$CI_COMMIT_REF_NAME',
- url: 'http://staging.example.com/$CI_JOB_NAME',
- action: 'stop' }
+ options do
+ {
+ script: %w(ls),
+ environment: { name: 'review/$CI_COMMIT_REF_NAME',
+ url: 'http://staging.example.com/$CI_JOB_NAME',
+ action: 'stop' }
+ }
+ end
end
trait :allowed_to_fail do
@@ -142,7 +161,13 @@ FactoryBot.define do
trait :schedulable do
self.when 'delayed'
- options start_in: '1 minute'
+
+ options do
+ {
+ script: ['ls -a'],
+ start_in: '1 minute'
+ }
+ end
end
trait :actionable do
@@ -265,6 +290,7 @@ FactoryBot.define do
{
image: { name: 'ruby:2.1', entrypoint: '/bin/sh' },
services: ['postgres', { name: 'docker:stable-dind', entrypoint: '/bin/sh', command: 'sleep 30', alias: 'docker' }],
+ script: %w(echo),
after_script: %w(ls date),
artifacts: {
name: 'artifacts_file',
diff --git a/spec/factories/ci/group_variables.rb b/spec/factories/ci/group_variables.rb
index 64716842b12..9bf520a2c0a 100644
--- a/spec/factories/ci/group_variables.rb
+++ b/spec/factories/ci/group_variables.rb
@@ -2,6 +2,7 @@ FactoryBot.define do
factory :ci_group_variable, class: Ci::GroupVariable do
sequence(:key) { |n| "VARIABLE_#{n}" }
value 'VARIABLE_VALUE'
+ masked false
trait(:protected) do
protected true
diff --git a/spec/factories/ci/variables.rb b/spec/factories/ci/variables.rb
index 3d014b9b54f..97a7c9ba252 100644
--- a/spec/factories/ci/variables.rb
+++ b/spec/factories/ci/variables.rb
@@ -2,6 +2,7 @@ FactoryBot.define do
factory :ci_variable, class: Ci::Variable do
sequence(:key) { |n| "VARIABLE_#{n}" }
value 'VARIABLE_VALUE'
+ masked false
trait(:protected) do
protected true
diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb
index c9f5d0a813e..a2e5f4862db 100644
--- a/spec/factories/clusters/clusters.rb
+++ b/spec/factories/clusters/clusters.rb
@@ -44,6 +44,10 @@ FactoryBot.define do
provider_gcp factory: [:cluster_provider_gcp, :creating]
end
+ trait :rbac_disabled do
+ platform_kubernetes factory: [:cluster_platform_kubernetes, :configured, :rbac_disabled]
+ end
+
trait :disabled do
enabled false
end
@@ -55,5 +59,9 @@ FactoryBot.define do
trait :with_installed_helm do
application_helm factory: %i(clusters_applications_helm installed)
end
+
+ trait :with_domain do
+ domain 'example.com'
+ end
end
end
diff --git a/spec/factories/clusters/platforms/kubernetes.rb b/spec/factories/clusters/platforms/kubernetes.rb
index 8169c457ab7..bf30a9c3a61 100644
--- a/spec/factories/clusters/platforms/kubernetes.rb
+++ b/spec/factories/clusters/platforms/kubernetes.rb
@@ -16,8 +16,8 @@ FactoryBot.define do
end
end
- trait :rbac_enabled do
- authorization_type :rbac
+ trait :rbac_disabled do
+ authorization_type :abac
end
end
end
diff --git a/spec/factories/commits.rb b/spec/factories/commits.rb
index 818f7b046f6..2bcc4b6cf52 100644
--- a/spec/factories/commits.rb
+++ b/spec/factories/commits.rb
@@ -16,14 +16,24 @@ FactoryBot.define do
commit
end
+
project
+ skip_create # Commits cannot be persisted
+
initialize_with do
new(git_commit, project)
end
after(:build) do |commit, evaluator|
allow(commit).to receive(:author).and_return(evaluator.author || build_stubbed(:author))
+ allow(commit).to receive(:parent_ids).and_return([])
+ end
+
+ trait :merge_commit do
+ after(:build) do |commit|
+ allow(commit).to receive(:parent_ids).and_return(Array.new(2) { SecureRandom.hex(20) })
+ end
end
trait :without_author do
diff --git a/spec/factories/container_repositories.rb b/spec/factories/container_repositories.rb
index 62a89a12ef5..00fad7975c9 100644
--- a/spec/factories/container_repositories.rb
+++ b/spec/factories/container_repositories.rb
@@ -1,6 +1,6 @@
FactoryBot.define do
factory :container_repository do
- name 'test_container_image'
+ name 'test_image'
project
transient do
diff --git a/spec/factories/error_tracking/error.rb b/spec/factories/error_tracking/error.rb
new file mode 100644
index 00000000000..ff883a3d22c
--- /dev/null
+++ b/spec/factories/error_tracking/error.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :error_tracking_error, class: Gitlab::ErrorTracking::Error do
+ id 'id'
+ title 'title'
+ type 'error'
+ user_count 1
+ count 2
+ first_seen { Time.now }
+ last_seen { Time.now }
+ message 'message'
+ culprit 'culprit'
+ external_url 'http://example.com/id'
+ project_id 'project1'
+ project_name 'project name'
+ project_slug 'project_name'
+ short_id 'ID'
+ status 'unresolved'
+ frequency []
+
+ skip_create
+ end
+end
diff --git a/spec/factories/error_tracking/project.rb b/spec/factories/error_tracking/project.rb
new file mode 100644
index 00000000000..5e9219b241f
--- /dev/null
+++ b/spec/factories/error_tracking/project.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :error_tracking_project, class: Gitlab::ErrorTracking::Project do
+ id '1'
+ name 'Sentry Example'
+ slug 'sentry-example'
+ status 'active'
+ organization_name 'Sentry'
+ organization_id '1'
+ organization_slug 'sentry'
+
+ skip_create
+ end
+end
diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb
index 12be63e5d92..077c6ddc5ae 100644
--- a/spec/factories/group_members.rb
+++ b/spec/factories/group_members.rb
@@ -8,7 +8,7 @@ FactoryBot.define do
trait(:reporter) { access_level GroupMember::REPORTER }
trait(:developer) { access_level GroupMember::DEVELOPER }
trait(:maintainer) { access_level GroupMember::MAINTAINER }
- trait(:owner) { access_level GroupMember::OWNER }
+ trait(:owner) { access_level GroupMember::OWNER }
trait(:access_request) { requested_at { Time.now } }
trait(:invited) do
diff --git a/spec/factories/import_state.rb b/spec/factories/import_states.rb
index d6de26dccbc..d6de26dccbc 100644
--- a/spec/factories/import_state.rb
+++ b/spec/factories/import_states.rb
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index 2392bfc4a53..18f724770b5 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -101,6 +101,15 @@ FactoryBot.define do
end
end
+ trait :with_merge_request_pipeline do
+ after(:build) do |merge_request|
+ merge_request.merge_request_pipelines << build(:ci_pipeline,
+ source: :merge_request_event,
+ merge_request: merge_request,
+ project: merge_request.source_project)
+ end
+ end
+
trait :deployed_review_app do
target_branch 'pages-deploy-target'
diff --git a/spec/factories/personal_access_tokens.rb b/spec/factories/personal_access_tokens.rb
index 1b12f84d7b8..e7fd22a96b2 100644
--- a/spec/factories/personal_access_tokens.rb
+++ b/spec/factories/personal_access_tokens.rb
@@ -1,13 +1,14 @@
FactoryBot.define do
factory :personal_access_token do
user
- token { SecureRandom.hex(50) }
sequence(:name) { |n| "PAT #{n}" }
revoked false
expires_at { 5.days.from_now }
scopes ['api']
impersonation false
+ after(:build) { |personal_access_token| personal_access_token.ensure_token }
+
trait :impersonation do
impersonation true
end
@@ -21,7 +22,7 @@ FactoryBot.define do
end
trait :invalid do
- token nil
+ token_digest nil
end
end
end
diff --git a/spec/factories/project_daily_statistics.rb b/spec/factories/project_daily_statistics.rb
new file mode 100644
index 00000000000..7e4142fa401
--- /dev/null
+++ b/spec/factories/project_daily_statistics.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :project_daily_statistic do
+ project
+ fetch_count 1
+ end
+end
diff --git a/spec/factories/project_error_tracking_settings.rb b/spec/factories/project_error_tracking_settings.rb
new file mode 100644
index 00000000000..be30bd0260a
--- /dev/null
+++ b/spec/factories/project_error_tracking_settings.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :project_error_tracking_setting, class: ErrorTracking::ProjectErrorTrackingSetting do
+ project
+ api_url 'https://gitlab.com/api/0/projects/sentry-org/sentry-project'
+ enabled true
+ token 'access_token_123'
+ project_name 'Sentry Project'
+ organization_name 'Sentry Org'
+ end
+end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 1906c06a211..30d3b22d868 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -1,7 +1,7 @@
require_relative '../support/helpers/test_env'
FactoryBot.define do
- PAGES_ACCESS_LEVEL_SCHEMA_VERSION = 20180423204600
+ PAGES_ACCESS_LEVEL_SCHEMA_VERSION ||= 20180423204600
# Project without repository
#
@@ -313,6 +313,20 @@ FactoryBot.define do
end
end
+ factory :youtrack_project, parent: :project do
+ has_external_issue_tracker true
+
+ after :create do |project|
+ project.create_youtrack_service(
+ active: true,
+ properties: {
+ 'project_url' => 'http://youtrack/projects/project_guid_in_youtrack',
+ 'issues_url' => 'http://youtrack/issues/:id'
+ }
+ )
+ end
+ end
+
factory :jira_project, parent: :project do
has_external_issue_tracker true
jira_service
@@ -322,6 +336,10 @@ FactoryBot.define do
kubernetes_service
end
+ factory :mock_deployment_project, parent: :project do
+ mock_deployment_service
+ end
+
factory :prometheus_project, parent: :project do
after :create do |project|
project.create_prometheus_service(
diff --git a/spec/factories/releases.rb b/spec/factories/releases.rb
index 18047c74a5d..cab6b4a811f 100644
--- a/spec/factories/releases.rb
+++ b/spec/factories/releases.rb
@@ -1,8 +1,15 @@
FactoryBot.define do
factory :release do
tag "v1.1.0"
+ sha 'b83d6e391c22777fca1ed3012fce84f633d7fed0'
name { tag }
description "Awesome release"
project
+ author
+
+ trait :legacy do
+ sha nil
+ author nil
+ end
end
end
diff --git a/spec/factories/releases/link.rb b/spec/factories/releases/link.rb
new file mode 100644
index 00000000000..d23db6d4bad
--- /dev/null
+++ b/spec/factories/releases/link.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :release_link, class: ::Releases::Link do
+ release
+ sequence(:name) { |n| "release-18.#{n}.dmg" }
+ sequence(:url) { |n| "https://example.com/scrambled-url/app-#{n}.zip" }
+ end
+end
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 5be56a49903..70c34f8640b 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -26,6 +26,12 @@ FactoryBot.define do
})
end
+ factory :mock_deployment_service do
+ project
+ type 'MockDeploymentService'
+ active true
+ end
+
factory :prometheus_service do
project
active true
@@ -56,10 +62,4 @@ FactoryBot.define do
project_key: 'jira-key'
)
end
-
- factory :hipchat_service do
- project
- type 'HipchatService'
- token 'test_token'
- end
end
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index a47bd7cafca..1d2b724a5e5 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -73,11 +73,16 @@ FactoryBot.define do
end
after(:create) do |user, evaluator|
- user.identities << create(
- :identity,
+ identity_attrs = {
provider: evaluator.provider,
extern_uid: evaluator.extern_uid
- )
+ }
+
+ if evaluator.respond_to?(:saml_provider)
+ identity_attrs[:saml_provider] = evaluator.saml_provider
+ end
+
+ user.identities << create(:identity, identity_attrs)
end
end
diff --git a/spec/factories/wiki_pages.rb b/spec/factories/wiki_pages.rb
index 2335b5118dd..ae257d769e8 100644
--- a/spec/factories/wiki_pages.rb
+++ b/spec/factories/wiki_pages.rb
@@ -5,7 +5,7 @@ FactoryBot.define do
transient do
attrs do
{
- title: 'Title',
+ title: 'Title.with.dot',
content: 'Content for wiki page',
format: 'markdown'
}
diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb
index d8fcdebfc6d..3ff1a66b0b2 100644
--- a/spec/features/admin/admin_abuse_reports_spec.rb
+++ b/spec/features/admin/admin_abuse_reports_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Admin::AbuseReports", :js do
+describe "Admin::AbuseReports", :js do
let(:user) { create(:user) }
context 'as an admin' do
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index 3c2ae5b3c6a..83cd686818c 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -10,10 +10,10 @@ describe 'Admin Appearance' do
fill_in 'appearance_title', with: 'MyCompany'
fill_in 'appearance_description', with: 'dev server'
fill_in 'appearance_new_project_guidelines', with: 'Custom project guidelines'
- click_button 'Save'
+ click_button 'Update appearance settings'
expect(current_path).to eq admin_appearances_path
- expect(page).to have_content 'Appearance settings'
+ 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')
@@ -39,6 +39,38 @@ describe 'Admin Appearance' do
expect_custom_new_project_appearance(appearance)
end
+ context 'Custom system header and footer' do
+ before do
+ sign_in(create(:admin))
+ end
+
+ context 'when system header and footer messages are empty' do
+ it 'shows custom system header and footer fields' do
+ visit admin_appearances_path
+
+ 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
+
+ context 'when system header and footer messages are not empty' do
+ before do
+ appearance.update(header_message: 'Foo', footer_message: 'Bar')
+ end
+
+ it 'shows custom system header and footer fields' do
+ visit admin_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')
+ end
+ end
+ end
+
it 'Custom sign-in page' do
visit new_user_session_path
@@ -57,7 +89,7 @@ describe 'Admin Appearance' do
visit admin_appearances_path
attach_file(:appearance_logo, logo_fixture)
- click_button 'Save'
+ click_button 'Update appearance settings'
expect(page).to have_css(logo_selector)
click_link 'Remove logo'
@@ -69,7 +101,7 @@ describe 'Admin Appearance' do
visit admin_appearances_path
attach_file(:appearance_header_logo, logo_fixture)
- click_button 'Save'
+ click_button 'Update appearance settings'
expect(page).to have_css(header_logo_selector)
click_link 'Remove header logo'
@@ -81,7 +113,7 @@ describe 'Admin Appearance' do
visit admin_appearances_path
attach_file(:appearance_favicon, logo_fixture)
- click_button 'Save'
+ click_button 'Update appearance settings'
expect(page).to have_css('.appearance-light-logo-preview')
@@ -91,7 +123,7 @@ describe 'Admin Appearance' do
# allowed file types
attach_file(:appearance_favicon, Rails.root.join('spec', 'fixtures', 'sanitized.svg'))
- click_button 'Save'
+ click_button 'Update appearance settings'
expect(page).to have_content 'Favicon You are not allowed to upload "svg" files, allowed types: png, ico'
end
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index d6ee256f5b5..2b6bfa40beb 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Admin::Projects" do
+describe "Admin::Projects" do
include Select2Helper
let(:user) { create :user }
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index ed9c0ea9ac0..97b432a6751 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -141,6 +141,56 @@ describe "Admin Runners" do
end
end
+ describe 'filter by tag', :js do
+ it 'shows correct runner when tag matches' do
+ create :ci_runner, description: 'runner-blue', tag_list: ['blue']
+ create :ci_runner, description: 'runner-red', tag_list: ['red']
+
+ visit admin_runners_path
+
+ expect(page).to have_content 'runner-blue'
+ expect(page).to have_content 'runner-red'
+
+ input_filtered_search_keys('tag:blue')
+
+ expect(page).to have_content 'runner-blue'
+ expect(page).not_to have_content 'runner-red'
+ end
+
+ it 'shows no runner when tag does not match' do
+ create :ci_runner, description: 'runner-blue', tag_list: ['blue']
+ create :ci_runner, description: 'runner-red', tag_list: ['blue']
+
+ visit admin_runners_path
+
+ input_filtered_search_keys('tag:red')
+
+ expect(page).not_to have_content 'runner-blue'
+ expect(page).not_to have_content 'runner-blue'
+ expect(page).to have_text 'No runners found'
+ end
+
+ it 'shows correct runner when tag is selected and search term is entered' do
+ create :ci_runner, description: 'runner-a-1', tag_list: ['blue']
+ create :ci_runner, description: 'runner-a-2', tag_list: ['red']
+ create :ci_runner, description: 'runner-b-1', tag_list: ['blue']
+
+ visit admin_runners_path
+
+ input_filtered_search_keys('tag:blue')
+
+ expect(page).to have_content 'runner-a-1'
+ expect(page).to have_content 'runner-b-1'
+ expect(page).not_to have_content 'runner-a-2'
+
+ input_filtered_search_keys('tag:blue runner-a')
+
+ expect(page).to have_content 'runner-a-1'
+ expect(page).not_to have_content 'runner-b-1'
+ expect(page).not_to have_content 'runner-a-2'
+ end
+ end
+
it 'sorts by last contact date', :js do
create(:ci_runner, description: 'runner-1', created_at: '2018-07-12 15:37', contacted_at: '2018-07-12 15:37')
create(:ci_runner, description: 'runner-2', created_at: '2018-07-12 16:37', contacted_at: '2018-07-12 16:37')
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 0a69a26eb3e..04f39b807d7 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -238,7 +238,7 @@ describe 'Admin updates settings' do
page.within('.as-ci-cd') do
check 'Default to Auto DevOps pipeline for all projects'
- fill_in 'Auto devops domain', with: 'domain.com'
+ fill_in 'application_setting_auto_devops_domain', with: 'domain.com'
click_button 'Save changes'
end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 931095936a6..b1c6f308bc6 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -1,13 +1,13 @@
require 'spec_helper'
describe "Admin::Users" do
- include Spec::Support::Helpers::Features::ListRowsHelpers
+ include Spec::Support::Helpers::Features::ResponsiveTableHelpers
let!(:user) do
create(:omniauth_user, provider: 'twitter', extern_uid: '123456')
end
- let!(:current_user) { create(:admin) }
+ let!(:current_user) { create(:admin, last_activity_on: 5.days.ago) }
before do
sign_in(current_user)
@@ -25,6 +25,8 @@ describe "Admin::Users" do
it "has users list" do
expect(page).to have_content(current_user.email)
expect(page).to have_content(current_user.name)
+ expect(page).to have_content(current_user.created_at.strftime("%e %b, %Y"))
+ expect(page).to have_content(current_user.last_activity_on.strftime("%e %b, %Y"))
expect(page).to have_content(user.email)
expect(page).to have_content(user.name)
expect(page).to have_link('Block', href: block_admin_user_path(user))
@@ -32,10 +34,24 @@ describe "Admin::Users" do
expect(page).to have_button('Delete user and contributions')
end
+ describe "view extra user information", :js do
+ it 'does not have the user popover open' do
+ expect(page).not_to have_selector('#__BV_popover_1__')
+ end
+
+ it 'shows the user popover on hover' do
+ first_user_link = page.first('.js-user-link')
+
+ first_user_link.hover
+
+ expect(page).to have_selector('#__BV_popover_1__')
+ end
+ end
+
describe 'search and sort' do
before do
- create(:user, name: 'Foo Bar')
- create(:user, name: 'Foo Baz')
+ create(:user, name: 'Foo Bar', last_activity_on: 3.days.ago)
+ create(:user, name: 'Foo Baz', last_activity_on: 2.days.ago)
create(:user, name: 'Dmitriy')
end
@@ -75,6 +91,24 @@ describe "Admin::Users" do
expect(first_row.text).to include('Foo Bar')
expect(second_row.text).to include('Foo Baz')
end
+
+ it 'sorts users by recent last activity' do
+ visit admin_users_path(search_query: 'Foo')
+
+ sort_by('Recent last activity')
+
+ expect(first_row.text).to include('Foo Baz')
+ expect(second_row.text).to include('Foo Bar')
+ end
+
+ it 'sorts users by oldest last activity' do
+ visit admin_users_path(search_query: 'Foo')
+
+ sort_by('Oldest last activity')
+
+ expect(first_row.text).to include('Foo Bar')
+ expect(second_row.text).to include('Foo Baz')
+ end
end
describe 'Two-factor Authentication filters' do
diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb
index 5fa1a26f1a6..dfa1c92ea49 100644
--- a/spec/features/atom/dashboard_issues_spec.rb
+++ b/spec/features/atom/dashboard_issues_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Dashboard Issues Feed" do
+describe "Dashboard Issues Feed" do
describe "GET /issues" do
let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
diff --git a/spec/features/atom/dashboard_spec.rb b/spec/features/atom/dashboard_spec.rb
index 86b3f88298f..947587220a9 100644
--- a/spec/features/atom/dashboard_spec.rb
+++ b/spec/features/atom/dashboard_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Dashboard Feed" do
+describe "Dashboard Feed" do
describe "GET /" do
let!(:user) { create(:user, name: "Jonh") }
diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb
index ee3570a5b2b..714a9885caa 100644
--- a/spec/features/atom/issues_spec.rb
+++ b/spec/features/atom/issues_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'Issues Feed' do
+describe 'Issues Feed' do
describe 'GET /issues' do
let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb
index 8d7df346abb..7de8bea5049 100644
--- a/spec/features/atom/users_spec.rb
+++ b/spec/features/atom/users_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "User Feed" do
+describe "User Feed" do
describe "GET /" do
let!(:user) { create(:user) }
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index baa2b1d8af5..ea69ec0319b 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -68,7 +68,7 @@ describe 'Issue Boards', :js do
let(:bug) { create(:label, project: project, name: 'Bug') }
let!(:backlog) { create(:label, project: project, name: 'Backlog') }
let!(:closed) { create(:label, project: project, name: 'Closed') }
- let!(:accepting) { create(:label, project: project, name: 'Accepting Merge Requests') }
+ let!(:accepting) { create(:label, project: project, name: 'Accepting Merge Requests') }
let!(:a_plus) { create(:label, project: project, name: 'A+') }
let!(:list1) { create(:list, board: board, label: planning, position: 0) }
@@ -97,7 +97,7 @@ describe 'Issue Boards', :js do
expect(find('.board:nth-child(4)')).to have_selector('.board-card')
end
- it 'shows description tooltip on list title' do
+ it 'shows description tooltip on list title', :quarantine do
page.within('.board:nth-child(2)') do
expect(find('.board-title span.has-tooltip')[:title]).to eq('Test')
end
@@ -411,7 +411,7 @@ describe 'Issue Boards', :js do
wait_for_empty_boards((2..4))
end
- it 'filters by label with space after reload' do
+ it 'filters by label with space after reload', :quarantine do
set_filter("label", "\"#{accepting.title}")
click_filter_link(accepting.title)
submit_filter
@@ -477,7 +477,7 @@ describe 'Issue Boards', :js do
end
end
- it 'filters by multiple labels' do
+ it 'filters by multiple labels', :quarantine do
set_filter("label", testing.title)
click_filter_link(testing.title)
diff --git a/spec/features/boards/modal_filter_spec.rb b/spec/features/boards/modal_filter_spec.rb
index d96707e55fd..e42d18b457e 100644
--- a/spec/features/boards/modal_filter_spec.rb
+++ b/spec/features/boards/modal_filter_spec.rb
@@ -112,7 +112,7 @@ describe 'Issue Boards add issue modal filtering', :js do
page.within('.add-issues-modal') do
wait_for_requests
- expect(page).to have_selector('.js-visual-token', text: 'none')
+ expect(page).to have_selector('.js-visual-token', text: 'None')
expect(page).to have_selector('.board-card', count: 1)
end
end
@@ -147,7 +147,7 @@ describe 'Issue Boards add issue modal filtering', :js do
page.within('.add-issues-modal') do
wait_for_requests
- expect(page).to have_selector('.js-visual-token', text: 'upcoming')
+ expect(page).to have_selector('.js-visual-token', text: 'Upcoming')
expect(page).to have_selector('.board-card', count: 0)
end
end
@@ -182,7 +182,7 @@ describe 'Issue Boards add issue modal filtering', :js do
page.within('.add-issues-modal') do
wait_for_requests
- expect(page).to have_selector('.js-visual-token', text: 'none')
+ expect(page).to have_selector('.js-visual-token', text: 'None')
expect(page).to have_selector('.board-card', count: 1)
end
end
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index 164442a47f5..d0c4534e317 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -86,6 +86,27 @@ describe 'Issue Boards new issue', :js do
expect(page).to have_selector('.issue-boards-sidebar')
end
+
+ it 'successfuly loads labels to be added to newly created issue' do
+ page.within(first('.board')) do
+ find('.issue-count-badge-add-button').click
+ end
+
+ page.within(first('.board-new-issue-form')) do
+ find('.form-control').set('new issue')
+ click_button 'Submit issue'
+ end
+
+ wait_for_requests
+
+ page.within(first('.issue-boards-sidebar')) do
+ find('.labels .edit-link').click
+
+ wait_for_requests
+
+ expect(page).to have_selector('.labels .dropdown-content li a')
+ end
+ end
end
context 'unauthorized user' do
diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb
new file mode 100644
index 00000000000..0a9c4bcaf12
--- /dev/null
+++ b/spec/features/clusters/cluster_detail_page_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Clusterable > Show page' do
+ let(:current_user) { create(:user) }
+
+ before do
+ sign_in(current_user)
+ end
+
+ shared_examples 'editing domain' do
+ before do
+ clusterable.add_maintainer(current_user)
+ end
+
+ it 'allow the user to set domain' do
+ visit cluster_path
+
+ within '#cluster-integration' do
+ fill_in('cluster_base_domain', with: 'test.com')
+ click_on 'Save changes'
+ end
+
+ expect(page.status_code).to eq(200)
+ expect(page).to have_content('Kubernetes cluster was successfully updated.')
+ end
+
+ context 'when there is a cluster with ingress and external ip' do
+ before do
+ cluster.create_application_ingress!(external_ip: '192.168.1.100')
+
+ visit cluster_path
+ end
+
+ it 'shows help text with the domain as an alternative to custom domain' do
+ within '#cluster-integration' do
+ expect(page).to have_content('Alternatively 192.168.1.100.nip.io can be used instead of a custom domain')
+ end
+ end
+ end
+
+ context 'when there is no ingress' do
+ it 'alternative to custom domain is not shown' do
+ visit cluster_path
+
+ within '#cluster-integration' do
+ expect(page).not_to have_content('can be used instead of a custom domain.')
+ end
+ end
+ end
+ end
+
+ context 'when clusterable is a project' do
+ it_behaves_like 'editing domain' do
+ let(:clusterable) { create(:project) }
+ let(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [clusterable]) }
+ let(:cluster_path) { project_cluster_path(clusterable, cluster) }
+ end
+ end
+
+ context 'when clusterable is a group' do
+ it_behaves_like 'editing domain' do
+ let(:clusterable) { create(:group) }
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group, groups: [clusterable]) }
+ let(:cluster_path) { group_cluster_path(clusterable, cluster) }
+ end
+ end
+end
diff --git a/spec/features/container_registry_spec.rb b/spec/features/container_registry_spec.rb
index 9986206f619..6f9901815e1 100644
--- a/spec/features/container_registry_spec.rb
+++ b/spec/features/container_registry_spec.rb
@@ -25,7 +25,7 @@ describe "Container Registry", :js do
context 'when there are image repositories' do
before do
- stub_container_registry_tags(repository: %r{my/image}, tags: %w[latest])
+ stub_container_registry_tags(repository: %r{my/image}, tags: %w[latest], with_manifest: true)
project.container_repositories << container_repository
end
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
index 32c75cae0a1..f4b2b9033ab 100644
--- a/spec/features/cycle_analytics_spec.rb
+++ b/spec/features/cycle_analytics_spec.rb
@@ -11,7 +11,7 @@ describe 'Cycle Analytics', :js do
context 'as an allowed user' do
context 'when project is new' do
- before do
+ before do
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index 0db8093411b..f44bd55ecf6 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -15,7 +15,7 @@ describe 'Tooltips on .timeago dates', :js do
sign_in user
visit user_activity_path(user)
- wait_for_requests()
+ wait_for_requests
page.find('.js-timeago').hover
end
@@ -32,7 +32,7 @@ describe 'Tooltips on .timeago dates', :js do
sign_in user
visit user_snippets_path(user)
- wait_for_requests()
+ wait_for_requests
page.find('.js-timeago.snippet-created-ago').hover
end
diff --git a/spec/features/dashboard/help_spec.rb b/spec/features/dashboard/help_spec.rb
index 68bfbf22736..467a503a62d 100644
--- a/spec/features/dashboard/help_spec.rb
+++ b/spec/features/dashboard/help_spec.rb
@@ -5,13 +5,15 @@ RSpec.describe 'Dashboard Help' do
sign_in(create(:user))
end
- it 'renders correctly markdown' do
- visit help_page_path("administration/raketasks/maintenance")
+ context 'documentation' do
+ it 'renders correctly markdown' do
+ visit help_page_path("administration/raketasks/maintenance")
- expect(page).to have_content('Gather information about GitLab and the system it runs on')
+ expect(page).to have_content('Gather information about GitLab and the system it runs on')
- node = find('.documentation h2 a#user-content-check-gitlab-configuration')
- expect(node[:href]).to eq '#check-gitlab-configuration'
- expect(find(:xpath, "#{node.path}/..").text).to eq 'Check GitLab configuration'
+ node = find('.documentation h2 a#user-content-check-gitlab-configuration')
+ expect(node[:href]).to eq '#check-gitlab-configuration'
+ expect(find(:xpath, "#{node.path}/..").text).to eq 'Check GitLab configuration'
+ end
end
end
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index 282bf542e77..9ffa75aee47 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -6,6 +6,7 @@ describe 'Dashboard Merge Requests' do
include ProjectForksHelper
let(:current_user) { create :user }
+ let(:user) { current_user }
let(:project) { create(:project) }
let(:public_project) { create(:project, :public, :repository) }
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index 975b7944741..9d1c1e3acc7 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -91,6 +91,7 @@ describe 'Dashboard Projects' do
visit dashboard_projects_path
expect(page).to have_content(project.name)
+ expect(find('.nav-links li:nth-child(1) .badge-pill')).to have_content(1)
end
it 'shows personal projects on personal projects tab', :js do
@@ -113,7 +114,16 @@ describe 'Dashboard Projects' do
end
end
- context 'when on Starred projects tab' do
+ context 'when on Starred projects tab', :js do
+ it 'shows the empty state when there are no starred projects' do
+ visit(starred_dashboard_projects_path)
+
+ element = page.find('.row.empty-state')
+
+ expect(element).to have_content("You don't have starred projects yet.")
+ expect(element.find('.svg-content img')['src']).to have_content('illustrations/starred_empty')
+ end
+
it 'shows only starred projects' do
user.toggle_star(project2)
@@ -121,6 +131,8 @@ describe 'Dashboard Projects' do
expect(page).not_to have_content(project.name)
expect(page).to have_content(project2.name)
+ expect(find('.nav-links li:nth-child(1) .badge-pill')).to have_content(1)
+ expect(find('.nav-links li:nth-child(2) .badge-pill')).to have_content(1)
end
end
@@ -144,6 +156,27 @@ describe 'Dashboard Projects' do
expect(page).to have_link('Commit: passed')
end
end
+
+ context 'guest user of project and project has private pipelines' do
+ let(:guest_user) { create(:user) }
+
+ before do
+ project.update(public_builds: false)
+ project.add_guest(guest_user)
+ sign_in(guest_user)
+ end
+
+ it 'shows that the last pipeline passed' do
+ visit dashboard_projects_path
+
+ page.within('.controls') do
+ expect(page).not_to have_xpath("//a[@href='#{pipelines_project_commit_path(project, project.commit, ref: pipeline.ref)}']")
+ expect(page).not_to have_css('.ci-status-link')
+ expect(page).not_to have_css('.ci-status-icon-success')
+ expect(page).not_to have_link('Commit: passed')
+ end
+ end
+ end
end
context 'last push widget', :use_clean_rails_memory_store_caching do
diff --git a/spec/features/dashboard/root_explore_spec.rb b/spec/features/dashboard/root_explore_spec.rb
new file mode 100644
index 00000000000..5b686d8b6f1
--- /dev/null
+++ b/spec/features/dashboard/root_explore_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Root explore' do
+ set(:public_project) { create(:project, :public) }
+ set(:archived_project) { create(:project, :archived) }
+ set(:internal_project) { create(:project, :internal) }
+ set(:private_project) { create(:project, :private) }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ context 'when logged in' do
+ set(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ visit explore_projects_path
+ end
+
+ include_examples 'shows public and internal projects'
+ end
+
+ context 'when not logged in' do
+ before do
+ visit explore_projects_path
+ end
+
+ include_examples 'shows public projects'
+ end
+end
diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb
index 31a1dcf826d..55f5ff04d01 100644
--- a/spec/features/dashboard/shortcuts_spec.rb
+++ b/spec/features/dashboard/shortcuts_spec.rb
@@ -44,12 +44,12 @@ describe 'Dashboard shortcuts', :js do
find('body').send_keys([:shift, 'S'])
find('.nothing-here-block')
- expect(page).to have_selector('.snippets-list-holder')
+ expect(page).to have_content('No snippets found')
find('body').send_keys([:shift, 'P'])
find('.nothing-here-block')
- expect(page).to have_content('No projects found')
+ expect(page).to have_content('This user doesn\'t have any personal projects')
end
end
diff --git a/spec/features/dashboard/snippets_spec.rb b/spec/features/dashboard/snippets_spec.rb
index fb4263d74c4..0e248c8732d 100644
--- a/spec/features/dashboard/snippets_spec.rb
+++ b/spec/features/dashboard/snippets_spec.rb
@@ -13,6 +13,21 @@ describe 'Dashboard snippets' do
it_behaves_like 'paginated snippets'
end
+ context 'when there are no project snippets', :js do
+ let(:project) { create(:project, :public) }
+ before do
+ sign_in(project.owner)
+ visit dashboard_snippets_path
+ end
+
+ it 'shows the empty state when there are no snippets' do
+ element = page.find('.row.empty-state')
+
+ expect(element).to have_content("Snippets are small pieces of code or notes that you want to keep.")
+ expect(element.find('.svg-content img')['src']).to have_content('illustrations/snippets_empty')
+ end
+ end
+
context 'filtering by visibility' do
let(:user) { create(:user) }
let!(:snippets) do
diff --git a/spec/features/dashboard/todos/todos_spec.rb b/spec/features/dashboard/todos/todos_spec.rb
index 96b22a0f64b..fd8677feab5 100644
--- a/spec/features/dashboard/todos/todos_spec.rb
+++ b/spec/features/dashboard/todos/todos_spec.rb
@@ -112,7 +112,7 @@ describe 'Dashboard Todos' do
end
it 'shows issue assigned to yourself message' do
- page.within('.js-todos-all') do
+ page.within('.js-todos-all') do
expect(page).to have_content("You assigned issue #{issue.to_reference(full: true)} to yourself")
end
end
@@ -125,8 +125,8 @@ describe 'Dashboard Todos' do
end
it 'shows you added a todo message' do
- page.within('.js-todos-all') do
- expect(page).to have_content("You added a todo for issue #{issue.to_reference(full: true)}")
+ page.within('.js-todos-all') do
+ expect(page).to have_content("You added a todo for issue #{issue.to_reference(full: true)}")
expect(page).not_to have_content('to yourself')
end
end
@@ -139,8 +139,8 @@ describe 'Dashboard Todos' do
end
it 'shows you mentioned yourself message' do
- page.within('.js-todos-all') do
- expect(page).to have_content("You mentioned yourself on issue #{issue.to_reference(full: true)}")
+ page.within('.js-todos-all') do
+ expect(page).to have_content("You mentioned yourself on issue #{issue.to_reference(full: true)}")
expect(page).not_to have_content('to yourself')
end
end
@@ -153,8 +153,8 @@ describe 'Dashboard Todos' do
end
it 'shows you directly addressed yourself message' do
- page.within('.js-todos-all') do
- expect(page).to have_content("You directly addressed yourself on issue #{issue.to_reference(full: true)}")
+ page.within('.js-todos-all') do
+ expect(page).to have_content("You directly addressed yourself on issue #{issue.to_reference(full: true)}")
expect(page).not_to have_content('to yourself')
end
end
@@ -169,8 +169,8 @@ describe 'Dashboard Todos' do
end
it 'shows you set yourself as an approver message' do
- page.within('.js-todos-all') do
- expect(page).to have_content("You set yourself as an approver for merge request #{merge_request.to_reference(full: true)}")
+ page.within('.js-todos-all') do
+ expect(page).to have_content("You set yourself as an approver for merge request #{merge_request.to_reference(full: true)}")
expect(page).not_to have_content('to yourself')
end
end
@@ -332,7 +332,7 @@ describe 'Dashboard Todos' do
it 'links to the pipelines for the merge request' do
href = pipelines_project_merge_request_path(project, todo.target)
- expect(page).to have_link "merge request #{todo.target.to_reference(full: true)}", href
+ expect(page).to have_link "merge request #{todo.target.to_reference(full: true)}", href: href
end
end
end
diff --git a/spec/features/dashboard/user_filters_projects_spec.rb b/spec/features/dashboard/user_filters_projects_spec.rb
index 3746d37b9cd..cc86114e436 100644
--- a/spec/features/dashboard/user_filters_projects_spec.rb
+++ b/spec/features/dashboard/user_filters_projects_spec.rb
@@ -38,7 +38,7 @@ describe 'Dashboard > User filters projects' do
it 'returns message when starred projects fitler returns no results' do
fill_in 'project-filter-form-field', with: 'Beta\n'
- expect(page).to have_content('No projects found')
+ expect(page).to have_content('This user doesn\'t have any personal projects')
expect(page).not_to have_content('You don\'t have starred projects yet')
end
end
diff --git a/spec/features/display_system_header_and_footer_bar_spec.rb b/spec/features/display_system_header_and_footer_bar_spec.rb
new file mode 100644
index 00000000000..af9d9a5834f
--- /dev/null
+++ b/spec/features/display_system_header_and_footer_bar_spec.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Display system header and footer bar' do
+ let(:header_message) { "Foo" }
+ let(:footer_message) { "Bar" }
+
+ shared_examples 'system header is configured' do
+ it 'shows system header' do
+ expect(page).to have_css('.header-message')
+ end
+
+ it 'shows the correct content' do
+ page.within('.header-message') do
+ expect(page).to have_content(header_message)
+ end
+ end
+ end
+
+ shared_examples 'system footer is configured' do
+ it 'shows system footer' do
+ expect(page).to have_css('.footer-message')
+ end
+
+ it 'shows the correct content' do
+ page.within('.footer-message') do
+ expect(page).to have_content(footer_message)
+ end
+ end
+ end
+
+ shared_examples 'system header is not configured' do
+ it 'does not show system header' do
+ expect(page).not_to have_css('.header-message')
+ end
+ end
+
+ shared_examples 'system footer is not configured' do
+ it 'does not show system footer' do
+ expect(page).not_to have_css('.footer-message')
+ end
+ end
+
+ context 'when authenticated' do
+ context 'when system header and footer are not configured' do
+ before do
+ sign_in(create(:user))
+
+ visit root_path
+ end
+
+ it_behaves_like 'system header is not configured'
+ it_behaves_like 'system footer is not configured'
+ end
+
+ context 'when only system header is defined' do
+ before do
+ create(:appearance, header_message: header_message)
+
+ sign_in(create(:user))
+ visit root_path
+ end
+
+ it_behaves_like 'system header is configured'
+ it_behaves_like 'system footer is not configured'
+ end
+
+ context 'when only system footer is defined' do
+ before do
+ create(:appearance, footer_message: footer_message)
+
+ sign_in(create(:user))
+ visit root_path
+ end
+
+ it_behaves_like 'system header is not configured'
+ it_behaves_like 'system footer is configured'
+ end
+
+ context 'when system header and footer are defined' do
+ before do
+ create(:appearance, header_message: header_message, footer_message: footer_message)
+
+ sign_in(create(:user))
+ visit root_path
+ end
+
+ it_behaves_like 'system header is configured'
+ it_behaves_like 'system footer is configured'
+ end
+ end
+
+ context 'when not authenticated' do
+ context 'when system header and footer are not configured' do
+ before do
+ visit root_path
+ end
+
+ it_behaves_like 'system header is not configured'
+ it_behaves_like 'system footer is not configured'
+ end
+
+ context 'when only system header is defined' do
+ before do
+ create(:appearance, header_message: header_message)
+
+ visit root_path
+ end
+
+ it_behaves_like 'system header is configured'
+ it_behaves_like 'system footer is not configured'
+ end
+
+ context 'when only system footer is defined' do
+ before do
+ create(:appearance, footer_message: footer_message)
+
+ visit root_path
+ end
+
+ it_behaves_like 'system header is not configured'
+ it_behaves_like 'system footer is configured'
+ end
+
+ context 'when system header and footer are defined' do
+ before do
+ create(:appearance, header_message: header_message, footer_message: footer_message)
+
+ visit root_path
+ end
+
+ it_behaves_like 'system header is configured'
+ it_behaves_like 'system footer is configured'
+ end
+ end
+end
diff --git a/spec/features/explore/user_explores_projects_spec.rb b/spec/features/explore/user_explores_projects_spec.rb
index 6ac9497b024..c724c3d17f8 100644
--- a/spec/features/explore/user_explores_projects_spec.rb
+++ b/spec/features/explore/user_explores_projects_spec.rb
@@ -6,24 +6,6 @@ describe 'User explores projects' do
set(:private_project) { create(:project, :private) }
set(:public_project) { create(:project, :public) }
- shared_examples_for 'shows public projects' do
- it 'shows projects' do
- expect(page).to have_content(public_project.title)
- expect(page).not_to have_content(internal_project.title)
- expect(page).not_to have_content(private_project.title)
- expect(page).not_to have_content(archived_project.title)
- end
- end
-
- shared_examples_for 'shows public and internal projects' do
- it 'shows projects' do
- expect(page).to have_content(public_project.title)
- expect(page).to have_content(internal_project.title)
- expect(page).not_to have_content(private_project.title)
- expect(page).not_to have_content(archived_project.title)
- end
- end
-
context 'when not signed in' do
context 'when viewing public projects' do
before do
diff --git a/spec/features/group_variables_spec.rb b/spec/features/group_variables_spec.rb
index 89e0cdd8ed7..1a53e7c9512 100644
--- a/spec/features/group_variables_spec.rb
+++ b/spec/features/group_variables_spec.rb
@@ -3,11 +3,11 @@ require 'spec_helper'
describe 'Group variables', :js do
let(:user) { create(:user) }
let(:group) { create(:group) }
- let!(:variable) { create(:ci_group_variable, key: 'test_key', value: 'test value', group: group) }
+ let!(:variable) { create(:ci_group_variable, key: 'test_key', value: 'test_value', group: group) }
let(:page_path) { group_settings_ci_cd_path(group) }
before do
- group.add_maintainer(user)
+ group.add_owner(user)
gitlab_sign_in(user)
visit page_path
diff --git a/spec/features/groups/empty_states_spec.rb b/spec/features/groups/empty_states_spec.rb
index 8f5ca781b2c..e4eb0d355d1 100644
--- a/spec/features/groups/empty_states_spec.rb
+++ b/spec/features/groups/empty_states_spec.rb
@@ -23,14 +23,52 @@ describe 'Group empty states' do
end
context "the project has #{issuable_name}s" do
- before do
+ it 'does not display an empty state' do
create(issuable, project_relation => project)
visit path
+ expect(page).not_to have_selector('.empty-state')
end
- it 'does not display an empty state' do
- expect(page).not_to have_selector('.empty-state')
+ it "displays link to create new #{issuable} when no open #{issuable} is found" do
+ create("closed_#{issuable}", project_relation => project)
+ issuable_link_fn = "project_#{issuable}s_path"
+
+ visit public_send(issuable_link_fn, project)
+
+ page.within(find('.empty-state')) do
+ expect(page).to have_content(/There are no open #{issuable.to_s.humanize.downcase}/)
+ expect(page).to have_selector("#new_#{issuable}_body_link")
+ end
+ end
+
+ it 'displays link to create new issue when the current search gave no results' do
+ create(issuable, project_relation => project)
+
+ issuable_link_fn = "project_#{issuable}s_path"
+
+ visit public_send(issuable_link_fn, project, author_username: 'foo', scope: 'all', state: 'opened')
+
+ page.within(find('.empty-state')) do
+ expect(page).to have_content(/Sorry, your filter produced no results/)
+ new_issuable_path = issuable == :issue ? 'new_project_issue_path' : 'project_new_merge_request_path'
+
+ path = public_send(new_issuable_path, project)
+
+ expect(page).to have_selector("#new_#{issuable}_body_link[href='#{path}']")
+ end
+ end
+
+ it "displays conditional text when no closed #{issuable} is found" do
+ create(issuable, project_relation => project)
+
+ issuable_link_fn = "project_#{issuable}s_path"
+
+ visit public_send(issuable_link_fn, project, state: 'closed')
+
+ page.within(find('.empty-state')) do
+ expect(page).to have_content(/There are no closed #{issuable.to_s.humanize.downcase}/)
+ end
end
end
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 2cdbdcffbc3..378e4d5febc 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -18,14 +18,14 @@ describe 'Edit group settings' do
update_path(new_group_path)
visit new_group_full_path
expect(current_path).to eq(new_group_full_path)
- expect(find('h1.group-title')).to have_content(group.name)
+ expect(find('h1.home-panel-title')).to have_content(group.name)
end
it 'the old group path redirects to the new path' do
update_path(new_group_path)
visit old_group_full_path
expect(current_path).to eq(new_group_full_path)
- expect(find('h1.group-title')).to have_content(group.name)
+ expect(find('h1.home-panel-title')).to have_content(group.name)
end
context 'with a subgroup' do
@@ -37,14 +37,14 @@ describe 'Edit group settings' do
update_path(new_group_path)
visit new_subgroup_full_path
expect(current_path).to eq(new_subgroup_full_path)
- expect(find('h1.group-title')).to have_content(subgroup.name)
+ expect(find('h1.home-panel-title')).to have_content(subgroup.name)
end
it 'the old subgroup path redirects to the new path' do
update_path(new_group_path)
visit old_subgroup_full_path
expect(current_path).to eq(new_subgroup_full_path)
- expect(find('h1.group-title')).to have_content(subgroup.name)
+ expect(find('h1.home-panel-title')).to have_content(subgroup.name)
end
end
diff --git a/spec/features/groups/labels/create_spec.rb b/spec/features/groups/labels/create_spec.rb
new file mode 100644
index 00000000000..f5062a65321
--- /dev/null
+++ b/spec/features/groups/labels/create_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Create a group label' do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ visit group_labels_path(group)
+ end
+
+ it 'creates a new label' do
+ click_link 'New label'
+ fill_in 'Title', with: 'test-label'
+ click_button 'Create label'
+
+ expect(page).to have_content 'test-label'
+ expect(current_path).to eq(group_labels_path(group))
+ end
+end
diff --git a/spec/features/groups/labels/index_spec.rb b/spec/features/groups/labels/index_spec.rb
index 0ce7dad4040..62308d3b518 100644
--- a/spec/features/groups/labels/index_spec.rb
+++ b/spec/features/groups/labels/index_spec.rb
@@ -1,9 +1,12 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Group labels' do
let(:user) { create(:user) }
let(:group) { create(:group) }
let!(:label) { create(:group_label, group: group) }
+ let!(:label2) { create(:group_label) }
before do
group.add_owner(user)
@@ -11,7 +14,16 @@ describe 'Group labels' do
visit group_labels_path(group)
end
- it 'label has edit button', :js do
+ it 'shows labels that belong to the group' do
+ expect(page).to have_content(label.name)
+ expect(page).not_to have_content(label2.name)
+ end
+
+ it 'shows a new label button' do
+ expect(page).to have_link('New label')
+ end
+
+ it 'shows an edit label button', :js do
expect(page).to have_selector('.label-action.edit')
end
end
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index 174840794ed..d57eb87ca77 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -81,7 +81,7 @@ describe 'Group milestones' do
description: 'Lorem Ipsum is simply dummy text'
)
end
- let!(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.0') }
+ let!(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.1') }
let!(:closed_project_milestone1) { create(:milestone, project: project, state: 'closed', title: 'v2.0') }
let!(:closed_project_milestone2) { create(:milestone, project: other_project, state: 'closed', title: 'v2.0') }
let!(:active_group_milestone) { create(:milestone, group: group, state: 'active', title: 'GL-113') }
@@ -104,7 +104,7 @@ describe 'Group milestones' do
legacy_milestone = GroupMilestone.build_collection(group, group.projects, { state: 'active' }).first
expect(page).to have_selector("#milestone_#{active_group_milestone.id}", count: 1)
- expect(page).to have_selector("#milestone_#{legacy_milestone.milestones.first.id}", count: 1)
+ expect(page).to have_selector("#milestone_#{legacy_milestone.milestone.id}", count: 1)
end
it 'shows milestone detail and supports its edit' do
@@ -121,6 +121,7 @@ describe 'Group milestones' do
it 'renders milestones' do
expect(page).to have_content('v1.0')
+ expect(page).to have_content('v1.1')
expect(page).to have_content('GL-113')
expect(page).to have_link(
'1 Issue',
diff --git a/spec/features/groups/milestones_sorting_spec.rb b/spec/features/groups/milestones_sorting_spec.rb
index bc226ff41c1..7bc015ea28f 100644
--- a/spec/features/groups/milestones_sorting_spec.rb
+++ b/spec/features/groups/milestones_sorting_spec.rb
@@ -42,6 +42,7 @@ describe 'Milestones sorting', :js do
expect(page).to have_button('Due later')
+ # assert descending sorting
within '.milestones' do
expect(page.all('ul.content-list > li').first.text).to include('v1.0')
expect(page.all('ul.content-list > li')[1].text).to include('v3.0')
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index d01fc04311a..c2f32c76422 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -154,7 +154,7 @@ describe 'Group' do
end
describe 'group edit', :js do
- let(:group) { create(:group) }
+ let(:group) { create(:group, :public) }
let(:path) { edit_group_path(group) }
let(:new_name) { 'new-name' }
@@ -163,6 +163,8 @@ describe 'Group' do
end
it_behaves_like 'dirty submit form', [{ form: '.js-general-settings-form', input: 'input[name="group[name]"]' },
+ { form: '.js-general-settings-form', input: '#group_visibility_level_0' },
+ { form: '.js-general-permissions-form', input: '#group_request_access_enabled' },
{ form: '.js-general-permissions-form', input: 'input[name="group[two_factor_grace_period]"]' }]
it 'saves new settings' do
@@ -201,7 +203,7 @@ describe 'Group' do
visit path
- expect(page).to have_css('.group-home-desc > p > strong')
+ expect(page).to have_css('.home-panel-description-markdown > p > strong')
end
it 'passes through html-pipeline' do
@@ -209,7 +211,7 @@ describe 'Group' do
visit path
- expect(page).to have_css('.group-home-desc > p > gl-emoji')
+ expect(page).to have_css('.home-panel-description-markdown > p > gl-emoji')
end
it 'sanitizes unwanted tags' do
@@ -217,7 +219,7 @@ describe 'Group' do
visit path
- expect(page).not_to have_css('.group-home-desc h1')
+ expect(page).not_to have_css('.home-panel-description-markdown h1')
end
it 'permits `rel` attribute on links' do
@@ -225,7 +227,7 @@ describe 'Group' do
visit path
- expect(page).to have_css('.group-home-desc a[rel]')
+ expect(page).to have_css('.home-panel-description-markdown a[rel]')
end
end
@@ -233,7 +235,7 @@ describe 'Group' do
let!(:group) { create(:group) }
let!(:nested_group) { create(:group, parent: group) }
let!(:project) { create(:project, namespace: group) }
- let!(:path) { group_path(group) }
+ let!(:path) { group_path(group) }
it 'it renders projects and groups on the page' do
visit path
diff --git a/spec/features/ics/dashboard_issues_spec.rb b/spec/features/ics/dashboard_issues_spec.rb
index ea714934ae7..debae0ea930 100644
--- a/spec/features/ics/dashboard_issues_spec.rb
+++ b/spec/features/ics/dashboard_issues_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'Dashboard Issues Calendar Feed' do
+describe 'Dashboard Issues Calendar Feed' do
describe 'GET /issues' do
let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
diff --git a/spec/features/ics/group_issues_spec.rb b/spec/features/ics/group_issues_spec.rb
index 24de5b4b7c6..4177c7f8704 100644
--- a/spec/features/ics/group_issues_spec.rb
+++ b/spec/features/ics/group_issues_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'Group Issues Calendar Feed' do
+describe 'Group Issues Calendar Feed' do
describe 'GET /issues' do
let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
diff --git a/spec/features/ics/project_issues_spec.rb b/spec/features/ics/project_issues_spec.rb
index 54143595e6b..0d9844be099 100644
--- a/spec/features/ics/project_issues_spec.rb
+++ b/spec/features/ics/project_issues_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'Project Issues Calendar Feed' do
+describe 'Project Issues Calendar Feed' do
describe 'GET /issues' do
let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb
index 2f45ef856a5..7b6e9cd66b2 100644
--- a/spec/features/issuables/issuable_list_spec.rb
+++ b/spec/features/issuables/issuable_list_spec.rb
@@ -28,6 +28,22 @@ describe 'issuable list' do
expect(first('.fa-thumbs-down').find(:xpath, '..')).to have_content(1)
expect(first('.fa-comments').find(:xpath, '..')).to have_content(2)
end
+
+ it 'sorts labels alphabetically' do
+ label1 = create(:label, project: project, title: 'a')
+ label2 = create(:label, project: project, title: 'z')
+ label3 = create(:label, project: project, title: 'X')
+ label4 = create(:label, project: project, title: 'B')
+ issuable = create_issuable(issuable_type)
+ issuable.labels << [label1, label2, label3, label4]
+
+ visit_issuable_list(issuable_type)
+
+ expect(all('.label-link')[0].text).to have_content('B')
+ expect(all('.label-link')[1].text).to have_content('X')
+ expect(all('.label-link')[2].text).to have_content('a')
+ expect(all('.label-link')[3].text).to have_content('z')
+ end
end
it "counts merge requests closing issues icons for each issue" do
@@ -45,6 +61,14 @@ describe 'issuable list' do
end
end
+ def create_issuable(issuable_type)
+ if issuable_type == :issue
+ create(:issue, project: project)
+ else
+ create(:merge_request, source_project: project)
+ end
+ end
+
def create_issuables(issuable_type)
3.times do |n|
issuable =
diff --git a/spec/features/issuables/markdown_references/internal_references_spec.rb b/spec/features/issuables/markdown_references/internal_references_spec.rb
index 9613e22bf24..23385ba65fc 100644
--- a/spec/features/issuables/markdown_references/internal_references_spec.rb
+++ b/spec/features/issuables/markdown_references/internal_references_spec.rb
@@ -64,11 +64,13 @@ describe "Internal references", :js do
it "shows references" do
page.within("#merge-requests .merge-requests-title") do
- expect(page).to have_content("1 Related Merge Request")
+ expect(page).to have_content("Related merge requests")
+ expect(page).to have_css(".mr-count-badge")
end
page.within("#merge-requests ul") do
expect(page).to have_content(private_project_merge_request.title)
+ expect(page).to have_css(".merge-request-status")
end
expect(page).to have_content("mentioned in merge request #{private_project_merge_request.to_reference(public_project)}")
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index e910fb54d23..e0b1e286dee 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -37,7 +37,7 @@ describe 'Dropdown assignee', :js do
end
it 'closes when the search bar is unfocused' do
- find('body').click()
+ find('body').click
expect(page).to have_css(js_dropdown_assignee, visible: false)
end
@@ -160,7 +160,7 @@ describe 'Dropdown assignee', :js do
find('#js-dropdown-assignee .filter-dropdown-item', text: 'None').click
expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([assignee_token('none')])
+ expect_tokens([assignee_token('None')])
expect_filtered_search_input_empty
end
@@ -168,7 +168,7 @@ describe 'Dropdown assignee', :js do
find('#js-dropdown-assignee .filter-dropdown-item', text: 'Any').click
expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([assignee_token('any')])
+ expect_tokens([assignee_token('Any')])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb
index 50d819a6161..bedc61b9eed 100644
--- a/spec/features/issues/filtered_search/dropdown_author_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb
@@ -45,7 +45,7 @@ describe 'Dropdown author', :js do
end
it 'closes when the search bar is unfocused' do
- find('body').click()
+ find('body').click
expect(page).to have_css(js_dropdown_author, visible: false)
end
diff --git a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
index 97dd0afd002..f36d4e8f23f 100644
--- a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
@@ -64,7 +64,7 @@ describe 'Dropdown emoji', :js do
end
it 'closes when the search bar is unfocused' do
- find('body').click()
+ find('body').click
expect(page).to have_css(js_dropdown_emoji, visible: false)
end
@@ -125,7 +125,7 @@ describe 'Dropdown emoji', :js do
find('#js-dropdown-my-reaction .filter-dropdown-item', text: 'None').click
expect(page).to have_css(js_dropdown_emoji, visible: false)
- expect_tokens([reaction_token('none', false)])
+ expect_tokens([reaction_token('None', false)])
expect_filtered_search_input_empty
end
@@ -133,7 +133,7 @@ describe 'Dropdown emoji', :js do
find('#js-dropdown-my-reaction .filter-dropdown-item', text: 'Any').click
expect(page).to have_css(js_dropdown_emoji, visible: false)
- expect_tokens([reaction_token('any', false)])
+ expect_tokens([reaction_token('Any', false)])
expect_filtered_search_input_empty
end
diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
index 0e296ab2109..096756f19cc 100644
--- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
@@ -66,7 +66,7 @@ describe 'Dropdown hint', :js do
it 'filters with text' do
filtered_search.set('a')
- expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 4)
+ expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 5)
end
end
@@ -119,6 +119,15 @@ describe 'Dropdown hint', :js do
expect_tokens([{ name: 'my-reaction' }])
expect_filtered_search_input_empty
end
+
+ it 'opens the yes-no dropdown when you click on confidential' do
+ click_hint('confidential')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-confidential', visible: true)
+ expect_tokens([{ name: 'confidential' }])
+ expect_filtered_search_input_empty
+ end
end
describe 'selecting from dropdown with some input' do
diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb
index b25b1514d62..f502061dfce 100644
--- a/spec/features/issues/filtered_search/dropdown_label_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb
@@ -238,7 +238,7 @@ describe 'Dropdown label', :js do
find("#{js_dropdown_label} .filter-dropdown-item", text: 'None').click
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token('none', false)])
+ expect_tokens([label_token('None', false)])
expect_filtered_search_input_empty
end
@@ -246,7 +246,7 @@ describe 'Dropdown label', :js do
find("#{js_dropdown_label} .filter-dropdown-item", text: 'Any').click
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token('any', false)])
+ expect_tokens([label_token('Any', false)])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
index ef5801e61e8..b330eafe1d1 100644
--- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
@@ -44,7 +44,7 @@ describe 'Dropdown milestone', :js do
end
it 'closes when the search bar is unfocused' do
- find('body').click()
+ find('body').click
expect(page).to have_css(js_dropdown_milestone, visible: false)
end
@@ -192,7 +192,7 @@ describe 'Dropdown milestone', :js do
click_static_milestone('None')
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token('none', false)])
+ expect_tokens([milestone_token('None', false)])
expect_filtered_search_input_empty
end
@@ -200,7 +200,7 @@ describe 'Dropdown milestone', :js do
click_static_milestone('Any')
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token('any', false)])
+ expect_tokens([milestone_token('Any', false)])
expect_filtered_search_input_empty
end
@@ -208,7 +208,7 @@ describe 'Dropdown milestone', :js do
click_static_milestone('Upcoming')
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token('upcoming', false)])
+ expect_tokens([milestone_token('Upcoming', false)])
expect_filtered_search_input_empty
end
@@ -216,7 +216,7 @@ describe 'Dropdown milestone', :js do
click_static_milestone('Started')
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token('started', false)])
+ expect_tokens([milestone_token('Started', false)])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index a29380a180e..fa8e5cb0ca9 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -108,7 +108,7 @@ describe 'Filter issues', :js do
it 'filters issues by no assignee' do
input_filtered_search('assignee:none')
- expect_tokens([assignee_token('none')])
+ expect_tokens([assignee_token('None')])
expect_issues_list_count(3)
expect_filtered_search_input_empty
end
@@ -146,7 +146,7 @@ describe 'Filter issues', :js do
it 'filters issues by no label' do
input_filtered_search('label:none')
- expect_tokens([label_token('none', false)])
+ expect_tokens([label_token('None', false)])
expect_issues_list_count(4)
expect_filtered_search_input_empty
end
@@ -287,7 +287,7 @@ describe 'Filter issues', :js do
it 'filters issues by no milestone' do
input_filtered_search("milestone:none")
- expect_tokens([milestone_token('none', false)])
+ expect_tokens([milestone_token('None', false)])
expect_issues_list_count(3)
expect_filtered_search_input_empty
end
@@ -299,7 +299,7 @@ describe 'Filter issues', :js do
input_filtered_search("milestone:upcoming")
- expect_tokens([milestone_token('upcoming', false)])
+ expect_tokens([milestone_token('Upcoming', false)])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
@@ -307,7 +307,7 @@ describe 'Filter issues', :js do
it 'filters issues by started milestones' do
input_filtered_search("milestone:started")
- expect_tokens([milestone_token('started', false)])
+ expect_tokens([milestone_token('Started', false)])
expect_issues_list_count(5)
expect_filtered_search_input_empty
end
diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb
index 8abab3f35d6..da23aea1fc9 100644
--- a/spec/features/issues/filtered_search/search_bar_spec.rb
+++ b/spec/features/issues/filtered_search/search_bar_spec.rb
@@ -86,7 +86,7 @@ describe 'Search bar', :js do
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: original_size)
end
- it 'resets the dropdown filters' do
+ it 'resets the dropdown filters', :quarantine do
filtered_search.click
hint_offset = get_left_style(find('#js-dropdown-hint')['style'])
@@ -100,7 +100,7 @@ describe 'Search bar', :js do
find('.filtered-search-box .clear-search').click
filtered_search.click
- expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 5)
+ expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 6)
expect(get_left_style(find('#js-dropdown-hint')['style'])).to eq(hint_offset)
end
end
diff --git a/spec/features/issues/filtered_search/visual_tokens_spec.rb b/spec/features/issues/filtered_search/visual_tokens_spec.rb
index 1e1dd5691ab..9fd661d80ae 100644
--- a/spec/features/issues/filtered_search/visual_tokens_spec.rb
+++ b/spec/features/issues/filtered_search/visual_tokens_spec.rb
@@ -59,13 +59,6 @@ describe 'Visual tokens', :js do
expect(page).to have_css('#js-dropdown-author', visible: false)
end
- it 'ends editing mode when scroll container is clicked' do
- find('.scroll-container').click
-
- expect_filtered_search_input_empty
- expect(page).to have_css('#js-dropdown-author', visible: false)
- end
-
describe 'selecting different author from dropdown' do
before do
filter_author_dropdown.find('.filter-dropdown-item .dropdown-light-content', text: "@#{user_rock.username}").click
@@ -109,20 +102,13 @@ describe 'Visual tokens', :js do
expect(page).to have_css('#js-dropdown-assignee', visible: false)
end
- it 'ends editing mode when scroll container is clicked' do
- find('.scroll-container').click
-
- expect_filtered_search_input_empty
- expect(page).to have_css('#js-dropdown-assignee', visible: false)
- end
-
describe 'selecting static option from dropdown' do
before do
find("#js-dropdown-assignee").find('.filter-dropdown-item', text: 'None').click
end
it 'changes value in visual token' do
- expect(first('.tokens-container .filtered-search-token .value').text).to eq('none')
+ expect(first('.tokens-container .filtered-search-token .value').text).to eq('None')
end
it 'moves input to the right' do
@@ -147,7 +133,7 @@ describe 'Visual tokens', :js do
it 'selects static option from dropdown' do
find("#js-dropdown-milestone").find('.filter-dropdown-item', text: 'Upcoming').click
- expect(first('.tokens-container .filtered-search-token .value').text).to eq('upcoming')
+ expect(first('.tokens-container .filtered-search-token .value').text).to eq('Upcoming')
expect(is_input_focused).to eq(true)
end
@@ -167,13 +153,6 @@ describe 'Visual tokens', :js do
expect_filtered_search_input_empty
expect(page).to have_css('#js-dropdown-milestone', visible: false)
end
-
- it 'ends editing mode when scroll container is clicked' do
- find('.scroll-container').click
-
- expect_filtered_search_input_empty
- expect(page).to have_css('#js-dropdown-milestone', visible: false)
- end
end
describe 'editing label token' do
@@ -348,7 +327,7 @@ describe 'Visual tokens', :js do
it 'tokenizes the search term to complete visual token' do
expect_tokens([
author_token(user.name),
- assignee_token('none')
+ assignee_token('None')
])
end
end
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index d7531d5fcd9..986f3823275 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -3,6 +3,8 @@ require 'rails_helper'
describe 'GFM autocomplete', :js do
let(:issue_xss_title) { 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
let(:user_xss_title) { 'eve <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
+ let(:label_xss_title) { 'alert label &lt;img src=x onerror="alert(\'Hello xss\');" a'}
+ let(:milestone_xss_title) { 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a' }
let(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') }
let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
@@ -25,10 +27,14 @@ describe 'GFM autocomplete', :js do
simulate_input('#issue-description', "@#{user.name[0...3]}")
+ wait_for_requests
+
find('.atwho-view .cur').click
click_button 'Save changes'
+ wait_for_requests
+
expect(find('.description')).to have_content(user.to_reference)
end
@@ -47,6 +53,8 @@ describe 'GFM autocomplete', :js do
find('#note-body').native.send_keys('#')
end
+ wait_for_requests
+
expect(page).to have_selector('.atwho-container')
page.within '.atwho-container #at-view-issues' do
@@ -59,6 +67,8 @@ describe 'GFM autocomplete', :js do
find('#note-body').native.send_keys('@ev')
end
+ wait_for_requests
+
expect(page).to have_selector('.atwho-container')
page.within '.atwho-container #at-view-users' do
@@ -66,6 +76,22 @@ describe 'GFM autocomplete', :js do
end
end
+ it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
+ create(:milestone, project: project, title: milestone_xss_title)
+
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys('%')
+ end
+
+ wait_for_requests
+
+ expect(page).to have_selector('.atwho-container')
+
+ page.within '.atwho-container #at-view-milestones' do
+ expect(find('li').text).to have_content('alert milestone')
+ end
+ end
+
it 'doesnt open autocomplete menu character is prefixed with text' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('testing')
@@ -252,18 +278,34 @@ describe 'GFM autocomplete', :js do
end
end
- # This context has jsut one example in each contexts in order to improve spec performance.
- context 'labels' do
+ # This context has just one example in each contexts in order to improve spec performance.
+ context 'labels', :quarantine do
let!(:backend) { create(:label, project: project, title: 'backend') }
let!(:bug) { create(:label, project: project, title: 'bug') }
let!(:feature_proposal) { create(:label, project: project, title: 'feature proposal') }
+ it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
+ create(:label, project: project, title: label_xss_title)
+
+ note = find('#note-body')
+
+ # It should show all the labels on "~".
+ type(note, '~')
+
+ wait_for_requests
+
+ page.within '.atwho-container #at-view-labels' do
+ expect(find('.atwho-view-ul').text).to have_content('alert label')
+ end
+ end
+
context 'when no labels are assigned' do
it 'shows labels' do
note = find('#note-body')
# It should show all the labels on "~".
type(note, '~')
+ wait_for_requests
expect_labels(shown: [backend, bug, feature_proposal])
# It should show all the labels on "/label ~".
@@ -290,6 +332,7 @@ describe 'GFM autocomplete', :js do
# It should show all the labels on "~".
type(note, '~')
+ wait_for_requests
expect_labels(shown: [backend, bug, feature_proposal])
# It should show only unset labels on "/label ~".
@@ -316,6 +359,7 @@ describe 'GFM autocomplete', :js do
# It should show all the labels on "~".
type(note, '~')
+ wait_for_requests
expect_labels(shown: [backend, bug, feature_proposal])
# It should show no labels on "/label ~".
diff --git a/spec/features/issues/resource_label_events_spec.rb b/spec/features/issues/resource_label_events_spec.rb
index b0764db7751..3d380c183ec 100644
--- a/spec/features/issues/resource_label_events_spec.rb
+++ b/spec/features/issues/resource_label_events_spec.rb
@@ -6,7 +6,7 @@ describe 'List issue resource label events', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
let(:issue) { create(:issue, project: project, author: user) }
- let!(:label) { create(:label, project: project, title: 'foo') }
+ let!(:label) { create(:label, project: project, title: 'foo') }
let!(:user_status) { create(:user_status, user: user) }
context 'when user displays the issue' do
diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
index 32bc851f00f..693ad89069c 100644
--- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
@@ -141,7 +141,7 @@ describe 'User creates branch and merge request on issue page', :js do
it 'disables the create branch button' do
expect(page).to have_css('.create-mr-dropdown-wrap .unavailable:not(.hidden)')
expect(page).to have_css('.create-mr-dropdown-wrap .available.hidden', visible: false)
- expect(page).to have_content /1 Related Merge Request/
+ expect(page).to have_content /Related merge requests/
end
end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index e60486f6dcb..0f604db870f 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -93,4 +93,22 @@ describe "User creates issue" do
end
end
end
+
+ context "when signed in as user with special characters in their name" do
+ let(:user_special) { create(:user, name: "Jon O'Shea") }
+
+ before do
+ project.add_developer(user_special)
+ sign_in(user_special)
+
+ visit(new_project_issue_path(project))
+ end
+
+ it "will correctly escape user names with an apostrophe when clicking 'Assign to me'", :js do
+ first('.assign-to-me-link').click
+
+ expect(page).to have_content(user_special.name)
+ expect(page.find('input[name="issue[assignee_ids][]"]', visible: false)['data-meta']).to eq(user_special.name)
+ end
+ end
end
diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb
index 27cffdc5f8b..b5e7c3954e2 100644
--- a/spec/features/issues/user_uses_quick_actions_spec.rb
+++ b/spec/features/issues/user_uses_quick_actions_spec.rb
@@ -243,7 +243,9 @@ describe 'Issues > User uses quick actions', :js do
it 'does not move the issue' do
add_note("/move not/valid")
- expect(page).not_to have_content 'Commands applied'
+ wait_for_requests
+
+ expect(page).to have_content 'Commands applied'
expect(issue.reload).to be_open
end
end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 406e80e91aa..9bc340ed4bb 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -233,8 +233,8 @@ describe 'Issues' do
created_at: Time.now - (index * 60))
end
end
- let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') }
- let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') }
+ let(:newer_due_milestone) { create(:milestone, project: project, due_date: '2013-12-11') }
+ let(:later_due_milestone) { create(:milestone, project: project, due_date: '2013-12-12') }
it 'sorts by newest' do
visit project_issues_path(project, sort: sort_value_created_date)
diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb
index 09904cb907f..7c31e67a7fa 100644
--- a/spec/features/labels_hierarchy_spec.rb
+++ b/spec/features/labels_hierarchy_spec.rb
@@ -179,7 +179,7 @@ describe 'Labels Hierarchy', :js, :nested_groups do
end
context 'on project board issue sidebar' do
- let(:board) { create(:board, project: project_1) }
+ let(:board) { create(:board, project: project_1) }
before do
project_1.add_developer(user)
@@ -195,7 +195,7 @@ describe 'Labels Hierarchy', :js, :nested_groups do
end
context 'on group board issue sidebar' do
- let(:board) { create(:board, group: parent) }
+ let(:board) { create(:board, group: parent) }
before do
parent.add_developer(user)
diff --git a/spec/features/markdown/copy_as_gfm_spec.rb b/spec/features/markdown/copy_as_gfm_spec.rb
index 05228e27963..c30ac9c4ae2 100644
--- a/spec/features/markdown/copy_as_gfm_spec.rb
+++ b/spec/features/markdown/copy_as_gfm_spec.rb
@@ -19,9 +19,9 @@ describe 'Copy as GFM', :js do
visit project_issue_path(@project, @feat.issue)
end
- # The filters referenced in lib/banzai/pipeline/gfm_pipeline.rb convert GitLab Flavored Markdown (GFM) to HTML.
- # The handlers defined in app/assets/javascripts/behaviors/markdown/copy_as_gfm.js consequently convert that same HTML to GFM.
- # To make sure these filters and handlers are properly aligned, this spec tests the GFM-to-HTML-to-GFM cycle
+ # The filters referenced in lib/banzai/pipeline/gfm_pipeline.rb transform GitLab Flavored Markdown (GFM) to HTML.
+ # The nodes and marks referenced in app/assets/javascripts/behaviors/markdown/editor_extensions.js consequently transform that same HTML to GFM.
+ # To make sure these filters and nodes/marks are properly aligned, this spec tests the GFM-to-HTML-to-GFM cycle
# by verifying (`html_to_gfm(gfm_to_html(gfm)) == gfm`) for a number of examples of GFM for every filter, using the `verify` helper.
# These are all in a single `it` for performance reasons.
@@ -35,12 +35,15 @@ describe 'Copy as GFM', :js do
verify(
'a real world example from the gitlab-ce README',
- <<-GFM.strip_heredoc
+ <<~GFM
# GitLab
[![Build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
+
[![CE coverage report](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage)](https://gitlab-org.gitlab.io/gitlab-ce/coverage-ruby)
+
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
+
[![Core Infrastructure Initiative Best Practices](https://bestpractices.coreinfrastructure.org/projects/42/badge)](https://bestpractices.coreinfrastructure.org/projects/42)
## Canonical source
@@ -51,27 +54,26 @@ describe 'Copy as GFM', :js do
To see how GitLab looks please see the [features page on our website](https://about.gitlab.com/features/).
- - Manage Git repositories with fine grained access controls that keep your code secure
-
- - Perform code reviews and enhance collaboration with merge requests
-
- - Complete continuous integration (CI) and CD pipelines to builds, test, and deploy your applications
-
- - Each project can also have an issue tracker, issue board, and a wiki
-
- - Used by more than 100,000 organizations, GitLab is the most popular solution to manage Git repositories on-premises
-
- - Completely free and open source (MIT Expat license)
+ * Manage Git repositories with fine grained access controls that keep your code secure
+ * Perform code reviews and enhance collaboration with merge requests
+ * Complete continuous integration (CI) and CD pipelines to builds, test, and deploy your applications
+ * Each project can also have an issue tracker, issue board, and a wiki
+ * Used by more than 100,000 organizations, GitLab is the most popular solution to manage Git repositories on-premises
+ * Completely free and open source (MIT Expat license)
GFM
)
aggregate_failures('an accidentally selected empty element') do
gfm = '# Heading1'
- html = <<-HTML.strip_heredoc
+ html = <<~HTML
<h1>Heading1</h1>
<h2></h2>
+
+ <blockquote></blockquote>
+
+ <pre class="code highlight"></pre>
HTML
output_gfm = html_to_gfm(html)
@@ -81,7 +83,7 @@ describe 'Copy as GFM', :js do
aggregate_failures('an accidentally selected other element') do
gfm = 'Test comment with **Markdown!**'
- html = <<-HTML.strip_heredoc
+ html = <<~HTML
<li class="note">
<div class="md">
<p>
@@ -107,10 +109,15 @@ describe 'Copy as GFM', :js do
verify(
'TaskListFilter',
- '- [ ] Unchecked task',
- '- [x] Checked task',
- '1. [ ] Unchecked numbered task',
- '1. [x] Checked numbered task'
+ <<~GFM,
+ * [ ] Unchecked task
+ * [x] Checked task
+ GFM
+
+ <<~GFM
+ 1. [ ] Unchecked ordered task
+ 1. [x] Checked ordered task
+ GFM
)
verify(
@@ -139,7 +146,16 @@ describe 'Copy as GFM', :js do
verify(
'TableOfContentsFilter',
- '[[_TOC_]]'
+ <<~GFM,
+ [[_TOC_]]
+
+ # Heading 1
+
+ ## Heading 2
+ GFM
+
+ pipeline: :wiki,
+ project_wiki: @project.wiki
)
verify(
@@ -166,7 +182,7 @@ describe 'Copy as GFM', :js do
'$`c = \pm\sqrt{a^2 + b^2}`$',
# math block
- <<-GFM.strip_heredoc
+ <<~GFM
```math
c = \pm\sqrt{a^2 + b^2}
```
@@ -176,7 +192,7 @@ describe 'Copy as GFM', :js do
aggregate_failures('MathFilter: math as transformed from HTML to KaTeX') do
gfm = '$`c = \pm\sqrt{a^2 + b^2}`$'
- html = <<-HTML.strip_heredoc
+ html = <<~HTML
<span class="katex">
<span class="katex-mathml">
<math>
@@ -287,7 +303,7 @@ describe 'Copy as GFM', :js do
verify(
'MermaidFilter: mermaid as converted from GFM to HTML',
- <<-GFM.strip_heredoc
+ <<~GFM
```mermaid
graph TD;
A-->B;
@@ -296,14 +312,14 @@ describe 'Copy as GFM', :js do
)
aggregate_failures('MermaidFilter: mermaid as transformed from HTML to SVG') do
- gfm = <<-GFM.strip_heredoc
+ gfm = <<~GFM
```mermaid
graph TD;
A-->B;
```
GFM
- html = <<-HTML.strip_heredoc
+ html = <<~HTML
<svg id="mermaidChart1" xmlns="http://www.w3.org/2000/svg" height="100%" viewBox="0 0 87.234375 174" style="max-width:87.234375px;" class="mermaid">
<style>
.mermaid {
@@ -371,8 +387,7 @@ describe 'Copy as GFM', :js do
</g>
</g>
<text class="source" display="none">graph TD;
- A--&gt;B;
- </text>
+ A--&gt;B;</text>
</svg>
HTML
@@ -381,13 +396,82 @@ describe 'Copy as GFM', :js do
end
verify(
+ 'SuggestionFilter: suggestion as converted from GFM to HTML',
+
+ <<~GFM
+ ```suggestion
+ New
+ And newer
+ ```
+ GFM
+ )
+
+ aggregate_failures('SuggestionFilter: suggestion as transformed from HTML to Vue component') do
+ gfm = <<~GFM
+ ```suggestion
+ New
+ And newer
+ ```
+ GFM
+
+ html = <<~HTML
+ <div class="md-suggestion">
+ <div class="md-suggestion-header border-bottom-0 mt-2 qa-suggestion-diff-header">
+ <div class="qa-suggestion-diff-header font-weight-bold">
+ Suggested change
+ <a href="/gitlab/help/user/discussions/index.md#suggest-changes" aria-label="Help" class="js-help-btn">
+ <svg aria-hidden="true" class="s16 ic-question-o link-highlight">
+ <use xlink:href="/gitlab/assets/icons.svg#question-o"></use>
+ </svg>
+ </a>
+ </div>
+ <!---->
+ <button type="button" class="btn qa-apply-btn">Apply suggestion</button>
+ </div>
+ <table class="mb-3 md-suggestion-diff js-syntax-highlight code white">
+ <tbody>
+ <tr class="line_holder old">
+ <td class="diff-line-num old_line qa-old-diff-line-number old">9</td>
+ <td class="diff-line-num new_line old"></td>
+ <td class="line_content old"><span>Old
+ </span></td>
+ </tr>
+ <tr class="line_holder new">
+ <td class="diff-line-num old_line new"></td>
+ <td class="diff-line-num new_line qa-new-diff-line-number new">9</td>
+ <td class="line_content new"><span>New
+ </span></td>
+ </tr>
+ <tr class="line_holder new">
+ <td class="diff-line-num old_line new"></td>
+ <td class="diff-line-num new_line qa-new-diff-line-number new">10</td>
+ <td class="line_content new"><span> And newer
+ </span></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ HTML
+
+ output_gfm = html_to_gfm(html)
+ expect(output_gfm.strip).to eq(gfm.strip)
+ end
+
+ verify(
'SanitizationFilter',
- <<-GFM.strip_heredoc
+ <<~GFM
<sub>sub</sub>
<dl>
<dt>dt</dt>
+ <dt>dt</dt>
+ <dd>dd</dd>
+ <dd>dd</dd>
+
+ <dt>dt</dt>
+ <dt>dt</dt>
+ <dd>dd</dd>
<dd>dd</dd>
</dl>
@@ -399,30 +483,26 @@ describe 'Copy as GFM', :js do
<var>var</var>
- <ruby>ruby</ruby>
-
- <rt>rt</rt>
-
- <rp>rp</rp>
+ <abbr title="HyperText &quot;Markup&quot; Language">HTML</abbr>
- <abbr>abbr</abbr>
+ <details>
+ <summary>summary></summary>
- <summary>summary</summary>
-
- <details>details</details>
+ details
+ </details>
GFM
)
verify(
'SanitizationFilter',
- <<-GFM.strip_heredoc,
+ <<~GFM,
```
Plain text
```
GFM
- <<-GFM.strip_heredoc,
+ <<~GFM,
```ruby
def foo
bar
@@ -430,11 +510,9 @@ describe 'Copy as GFM', :js do
```
GFM
- <<-GFM.strip_heredoc
+ <<~GFM
Foo
- This is an example of GFM
-
```js
Code goes here
```
@@ -452,9 +530,8 @@ describe 'Copy as GFM', :js do
'> Quote',
# multiline quote
- <<-GFM.strip_heredoc,
- > Multiline
- > Quote
+ <<~GFM,
+ > Multiline Quote
>
> With multiple paragraphs
GFM
@@ -465,48 +542,54 @@ describe 'Copy as GFM', :js do
'[Link](https://example.com)',
- '- List item',
+ <<~GFM,
+ * List item
+ * List item 2
+ GFM
# multiline list item
- <<-GFM.strip_heredoc,
- - Multiline
- List item
+ <<~GFM,
+ * Multiline
+
+ List item
GFM
# nested lists
- <<-GFM.strip_heredoc,
- - Nested
-
- - Lists
+ <<~GFM,
+ * Nested
+ * Lists
GFM
# list with blockquote
- <<-GFM.strip_heredoc,
- - List
+ <<~GFM,
+ * List
- > Blockquote
+ > Blockquote
GFM
- '1. Numbered list item',
+ <<~GFM,
+ 1. Ordered list item
+ 1. Ordered list item 2
+ GFM
- # multiline numbered list item
- <<-GFM.strip_heredoc,
+ # multiline ordered list item
+ <<~GFM,
1. Multiline
- Numbered list item
+
+ Ordered list item
GFM
- # nested numbered list
- <<-GFM.strip_heredoc,
+ # nested ordered list
+ <<~GFM,
1. Nested
-
- 1. Numbered lists
+ 1. Ordered lists
GFM
# list item followed by an HR
- <<-GFM.strip_heredoc,
- - list item
+ <<~GFM,
+ * list item
- -----
+ ---
GFM
'# Heading',
@@ -518,14 +601,14 @@ describe 'Copy as GFM', :js do
'**Bold**',
- '_Italics_',
+ '*Italics*',
'~~Strikethrough~~',
- '-----',
+ '---',
# table
- <<-GFM.strip_heredoc,
+ <<~GFM,
| Centered | Right | Left |
|:--------:|------:|------|
| Foo | Bar | **Baz** |
@@ -533,9 +616,9 @@ describe 'Copy as GFM', :js do
GFM
# table with empty heading
- <<-GFM.strip_heredoc,
+ <<~GFM,
| | x | y |
- |---|---|---|
+ |--|---|---|
| a | 1 | 0 |
| b | 0 | 1 |
GFM
@@ -545,9 +628,11 @@ describe 'Copy as GFM', :js do
alias_method :gfm_to_html, :markdown
def verify(label, *gfms)
+ markdown_options = gfms.extract_options!
+
aggregate_failures(label) do
gfms.each do |gfm|
- html = gfm_to_html(gfm).gsub(/\A&#x000A;|&#x000A;\z/, '')
+ html = gfm_to_html(gfm, markdown_options).gsub(/\A&#x000A;|&#x000A;\z/, '')
output_gfm = html_to_gfm(html)
expect(output_gfm.strip).to eq(gfm.strip)
end
@@ -594,7 +679,7 @@ describe 'Copy as GFM', :js do
verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]',
- <<-GFM.strip_heredoc,
+ <<~GFM,
```ruby
raise RuntimeError, "System commands must be given as an array of strings"
end
@@ -627,7 +712,7 @@ describe 'Copy as GFM', :js do
verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]',
- <<-GFM.strip_heredoc,
+ <<~GFM,
```ruby
unless cmd.is_a?(Array)
raise "System commands must be given as an array of strings"
@@ -645,7 +730,7 @@ describe 'Copy as GFM', :js do
verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]',
- <<-GFM.strip_heredoc,
+ <<~GFM,
```ruby
unless cmd.is_a?(Array)
raise RuntimeError, "System commands must be given as an array of strings"
@@ -691,7 +776,7 @@ describe 'Copy as GFM', :js do
verify(
'.line[id="LC9"], .line[id="LC10"]',
- <<-GFM.strip_heredoc,
+ <<~GFM,
```ruby
raise RuntimeError, "System commands must be given as an array of strings"
end
@@ -733,7 +818,7 @@ describe 'Copy as GFM', :js do
verify(
'.line[id="LC27"], .line[id="LC28"]',
- <<-GFM.strip_heredoc,
+ <<~GFM,
```json
"bio": null,
"skype": "",
@@ -747,12 +832,13 @@ describe 'Copy as GFM', :js do
def verify(selector, gfm, target: nil)
html = html_for_selector(selector)
output_gfm = html_to_gfm(html, 'transformCodeSelection', target: target)
+ wait_for_requests
expect(output_gfm.strip).to eq(gfm.strip)
end
end
def html_for_selector(selector)
- js = <<-JS.strip_heredoc
+ js = <<~JS
(function(selector) {
var els = document.querySelectorAll(selector);
var htmls = [].slice.call(els).map(function(el) { return el.outerHTML; });
@@ -763,8 +849,11 @@ describe 'Copy as GFM', :js do
end
def html_to_gfm(html, transformer = 'transformGFMSelection', target: nil)
- js = <<-JS.strip_heredoc
+ js = <<~JS
(function(html) {
+ // Setting it off so the import already starts
+ window.CopyAsGFM.nodeToGFM(document.createElement('div'));
+
var transformer = window.CopyAsGFM[#{transformer.inspect}];
var node = document.createElement('div');
@@ -779,9 +868,18 @@ describe 'Copy as GFM', :js do
node = transformer(node, target);
if (!node) return null;
- return window.CopyAsGFM.nodeToGFM(node);
+
+ window.gfmCopytestRes = null;
+ window.CopyAsGFM.nodeToGFM(node)
+ .then((res) => {
+ window.gfmCopytestRes = res;
+ });
})("#{escape_javascript(html)}")
JS
- page.evaluate_script(js)
+ page.execute_script(js)
+
+ loop until page.evaluate_script('window.gfmCopytestRes !== null')
+
+ page.evaluate_script('window.gfmCopytestRes')
end
end
diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb
index 3b37ede8579..8815643ca96 100644
--- a/spec/features/markdown/markdown_spec.rb
+++ b/spec/features/markdown/markdown_spec.rb
@@ -13,7 +13,7 @@ require 'erb'
#
# Raw Markdown
# -> `markdown` helper
-# -> Redcarpet::Render::GitlabHTML converts Markdown to HTML
+# -> CommonMark::Render::GitlabHTML converts Markdown to HTML
# -> Post-process HTML
# -> `gfm` helper
# -> HTML::Pipeline
@@ -324,31 +324,6 @@ describe 'GitLab Markdown', :aggregate_failures do
end
end
- context 'Redcarpet documents' do
- before do
- allow_any_instance_of(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('Redcarpet')
- @html = markdown(@feat.raw_markdown)
- end
-
- it 'processes certain elements differently' do
- aggregate_failures 'parses superscript' do
- expect(doc).to have_selector('sup', count: 3)
- end
-
- aggregate_failures 'permits style attribute in th elements' do
- expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center'
- expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right'
- expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left'
- end
-
- aggregate_failures 'permits style attribute in td elements' do
- expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center'
- expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right'
- expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left'
- end
- end
- end
-
# Fake a `current_user` helper
def current_user
@feat.user
diff --git a/spec/features/markdown/math_spec.rb b/spec/features/markdown/math_spec.rb
index 6a23d6b78ab..16ad0d456be 100644
--- a/spec/features/markdown/math_spec.rb
+++ b/spec/features/markdown/math_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe 'Math rendering', :js do
+ let!(:project) { create(:project, :public) }
+
it 'renders inline and display math correctly' do
description = <<~MATH
This math is inline $`a^2+b^2=c^2`$.
@@ -11,12 +13,26 @@ describe 'Math rendering', :js do
```
MATH
- project = create(:project, :public)
issue = create(:issue, project: project, description: description)
visit project_issue_path(project, issue)
- expect(page).to have_selector('.katex .mord.mathit', text: 'b')
- expect(page).to have_selector('.katex-display .mord.mathit', text: 'b')
+ expect(page).to have_selector('.katex .mord.mathdefault', text: 'b')
+ expect(page).to have_selector('.katex-display .mord.mathdefault', text: 'b')
+ end
+
+ it 'only renders non XSS links' do
+ description = <<~MATH
+ This link is valid $`\\href{javascript:alert('xss');}{xss}`$.
+
+ This link is valid $`\\href{https://gitlab.com}{Gitlab}`$.
+ MATH
+
+ issue = create(:issue, project: project, description: description)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_selector('.katex-error', text: "\href{javascript:alert('xss');}{xss}")
+ expect(page).to have_selector('.katex-html a', text: 'Gitlab')
end
end
diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb
index 7839b97122c..aead98dae23 100644
--- a/spec/features/merge_request/maintainer_edits_fork_spec.rb
+++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb
@@ -18,6 +18,8 @@ describe 'a maintainer edits files on a source-branch of an MR from a fork', :js
end
before do
+ stub_feature_flags(web_ide_default: false)
+
target_project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb
index 01aeed93947..5fa23dbb998 100644
--- a/spec/features/merge_request/user_accepts_merge_request_spec.rb
+++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb
@@ -25,7 +25,7 @@ describe 'User accepts a merge request', :js do
end
it 'accepts a merge request' do
- check('Remove source branch')
+ check('Delete source branch')
click_button('Merge')
expect(page).to have_content('The changes were merged into')
@@ -60,7 +60,7 @@ describe 'User accepts a merge request', :js do
end
it 'accepts a merge request' do
- check('Remove source branch')
+ check('Delete source branch')
click_button('Merge')
expect(page).to have_content('The changes were merged into')
@@ -80,8 +80,8 @@ describe 'User accepts a merge request', :js do
end
it 'accepts a merge request' do
- click_button('Modify commit message')
- fill_in('Commit message', with: 'wow such merge')
+ find('.js-mr-widget-commits-count').click
+ fill_in('merge-message-edit', with: 'wow such merge')
click_button('Merge')
diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb
index 00cf368e8c9..eb4b2cf5bd0 100644
--- a/spec/features/merge_request/user_comments_on_diff_spec.rb
+++ b/spec/features/merge_request/user_comments_on_diff_spec.rb
@@ -91,6 +91,7 @@ describe 'User comments on a diff', :js do
# Check the same comments in the side-by-side view.
execute_script("window.scrollTo(0,0);")
+ find('.js-show-diff-settings').click
click_button 'Side-by-side'
wait_for_requests
diff --git a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
index d790bdc82ce..c837a6752f9 100644
--- a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
@@ -90,9 +90,6 @@ describe 'Merge request > User creates image diff notes', :js do
%w(inline parallel).each do |view|
context "#{view} view" do
- let(:merge_request) { create(:merge_request_with_diffs, :with_image_diffs, source_project: project, author: user) }
- let(:path) { "files/images/ee_repo_logo.png" }
-
let(:position) do
Gitlab::Diff::Position.new(
old_path: path,
@@ -108,9 +105,11 @@ describe 'Merge request > User creates image diff notes', :js do
let!(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request, position: position) }
- describe 'creating a new diff note' do
+ shared_examples 'creates image diff note' do
before do
visit diffs_project_merge_request_path(project, merge_request, view: view)
+ wait_for_requests
+
create_image_diff_note
end
@@ -132,6 +131,32 @@ describe 'Merge request > User creates image diff notes', :js do
expect(page).to have_content('image diff test comment')
end
end
+
+ context 'when images are not stored in LFS' do
+ let(:merge_request) { create(:merge_request_with_diffs, :with_image_diffs, source_project: project, author: user) }
+ let(:path) { 'files/images/ee_repo_logo.png' }
+
+ it_behaves_like 'creates image diff note'
+ end
+
+ context 'when images are stored in LFS' do
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project, source_branch: 'png-lfs', target_branch: 'master', author: user) }
+ let(:path) { 'files/images/logo-black.png' }
+
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
+ end
+
+ it 'shows lfs badges' do
+ visit diffs_project_merge_request_path(project, merge_request, view: view)
+ wait_for_requests
+
+ expect(page.all('.diff-file span.label-lfs', visible: :all)).not_to be_empty
+ end
+
+ it_behaves_like 'creates image diff note'
+ end
end
end
@@ -197,6 +222,11 @@ describe 'Merge request > User creates image diff notes', :js do
end
def create_image_diff_note
+ expand_text = 'Click to expand it.'
+ page.all('a', text: expand_text).each do |element|
+ element.click
+ end
+
find('.js-add-image-diff-note-button', match: :first).click
find('.diff-content .note-textarea').native.send_keys('image diff test comment')
click_button 'Comment'
diff --git a/spec/features/merge_request/user_creates_merge_request_spec.rb b/spec/features/merge_request/user_creates_merge_request_spec.rb
index 38b4e4a6d1b..ea2bb1503bb 100644
--- a/spec/features/merge_request/user_creates_merge_request_spec.rb
+++ b/spec/features/merge_request/user_creates_merge_request_spec.rb
@@ -8,6 +8,8 @@ describe "User creates a merge request", :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(approval_rules: false)
+
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/features/merge_request/user_creates_mr_spec.rb b/spec/features/merge_request/user_creates_mr_spec.rb
index 9d2a94a4a41..c169a68cd1c 100644
--- a/spec/features/merge_request/user_creates_mr_spec.rb
+++ b/spec/features/merge_request/user_creates_mr_spec.rb
@@ -30,7 +30,7 @@ describe 'Merge request > User creates MR' do
end
context 'source project', :js do
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
let(:target_project) { create(:project, :public, :repository) }
let(:source_project) { target_project }
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 8d2d4279d3c..c6b11fce388 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
@@ -13,7 +13,7 @@ describe 'Merge request < User customizes merge commit message', :js do
description: "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}"
)
end
- let(:textbox) { page.find(:css, '.js-commit-message', visible: false) }
+ let(:textbox) { page.find(:css, '#merge-message-edit', visible: false) }
let(:default_message) do
[
"Merge branch 'feature' into 'master'",
@@ -38,16 +38,16 @@ describe 'Merge request < User customizes merge commit message', :js do
end
it 'toggles commit message between message with description and without description' do
- expect(page).not_to have_selector('.js-commit-message')
- click_button "Modify commit message"
+ expect(page).not_to have_selector('#merge-message-edit')
+ first('.js-mr-widget-commits-count').click
expect(textbox).to be_visible
expect(textbox.value).to eq(default_message)
- click_link "Include description in commit message"
+ check('Include merge request description')
expect(textbox.value).to eq(message_with_description)
- click_link "Don't include description in commit message"
+ uncheck('Include merge request description')
expect(textbox.value).to eq(default_message)
end
diff --git a/spec/features/merge_request/user_merges_immediately_spec.rb b/spec/features/merge_request/user_merges_immediately_spec.rb
index ea61f9675bc..84636ae355c 100644
--- a/spec/features/merge_request/user_merges_immediately_spec.rb
+++ b/spec/features/merge_request/user_merges_immediately_spec.rb
@@ -25,6 +25,8 @@ describe 'Merge requests > User merges immediately', :js do
end
it 'enables merge immediately' do
+ wait_for_requests
+
page.within '.mr-widget-body' do
find('.dropdown-toggle').click
diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
index 29b3d2b629b..6e54aa6006b 100644
--- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
@@ -33,7 +33,7 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
click_button "Merge when pipeline succeeds"
expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds"
- expect(page).to have_content "The source branch will not be removed"
+ expect(page).to have_content "The source branch will not be deleted"
expect(page).to have_selector ".js-cancel-auto-merge"
visit project_merge_request_path(project, merge_request) # Needed to refresh the page
expect(page).to have_content /enabled an automatic merge when the pipeline for \h{8} succeeds/i
@@ -94,7 +94,7 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
click_link 'Merge when pipeline succeeds'
expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds"
- expect(page).to have_content "The source branch will not be removed"
+ expect(page).to have_content "The source branch will not be deleted"
expect(page).to have_link "Cancel automatic merge"
end
end
@@ -127,10 +127,10 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
expect(page).to have_content "canceled the automatic merge"
end
- it 'allows to remove source branch' do
- click_link "Remove source branch"
+ it 'allows to delete source branch' do
+ click_link "Delete source branch"
- expect(page).to have_content "The source branch will be removed"
+ expect(page).to have_content "The source branch will be deleted"
end
context 'when pipeline succeeds' do
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 51b78d3e7d1..19edce1b562 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -178,7 +178,7 @@ describe 'Merge request > User posts diff notes', :js do
end
end
- describe 'with muliple note forms' do
+ describe 'with multiple note forms' do
before do
visit diffs_project_merge_request_path(project, merge_request, view: 'inline')
click_diff_line(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb
index ee5f5377ca6..1bbcf455ac7 100644
--- a/spec/features/merge_request/user_posts_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_notes_spec.rb
@@ -66,6 +66,38 @@ describe 'Merge request > User posts notes', :js do
is_expected.to have_css('.js-note-text', visible: true)
end
end
+
+ describe 'when reply_to_individual_notes feature flag is not set' do
+ before do
+ stub_feature_flags(reply_to_individual_notes: false)
+ visit project_merge_request_path(project, merge_request)
+ end
+
+ it 'does not show a reply button' do
+ expect(page).to have_no_selector('.js-reply-button')
+ end
+ end
+
+ describe 'when reply_to_individual_notes feature flag is set' do
+ before do
+ stub_feature_flags(reply_to_individual_notes: true)
+ visit project_merge_request_path(project, merge_request)
+ end
+
+ it 'shows a reply button' do
+ reply_button = find('.js-reply-button', match: :first)
+
+ expect(reply_button).to have_selector('.ic-comment')
+ end
+
+ it 'shows reply placeholder when clicking reply button' do
+ reply_button = find('.js-reply-button', match: :first)
+
+ reply_button.click
+
+ expect(page).to have_selector('.discussion-reply-holder')
+ end
+ end
end
describe 'when previewing a note' do
diff --git a/spec/features/merge_request/user_resolves_conflicts_spec.rb b/spec/features/merge_request/user_resolves_conflicts_spec.rb
index 50c723776a3..16c058ab6bd 100644
--- a/spec/features/merge_request/user_resolves_conflicts_spec.rb
+++ b/spec/features/merge_request/user_resolves_conflicts_spec.rb
@@ -37,6 +37,8 @@ describe 'Merge request > User resolves conflicts', :js do
click_on 'Changes'
wait_for_requests
+ find('.js-toggle-tree-list').click
+
within find('.diff-file', text: 'files/ruby/popen.rb') do
expect(page).to have_selector('.line_content.new', text: "vars = { 'PWD' => path }")
expect(page).to have_selector('.line_content.new', text: "options = { chdir: path }")
diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
index ba4806821f9..08fa4a98feb 100644
--- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
+++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
@@ -126,6 +126,7 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
describe 'side-by-side view' do
before do
page.within('.merge-request-tabs') { click_link 'Changes' }
+ find('.js-show-diff-settings').click
page.find('#parallel-diff-btn').click
end
diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb
index 0df9e4bbc1a..04b07525919 100644
--- a/spec/features/merge_request/user_sees_diff_spec.rb
+++ b/spec/features/merge_request/user_sees_diff_spec.rb
@@ -87,20 +87,6 @@ describe 'Merge request > User sees diff', :js do
let(:current_user) { project.owner }
let(:branch_name) {"test_branch"}
- def create_file(branch_name, file_name, content)
- Files::CreateService.new(
- project,
- current_user,
- start_branch: branch_name,
- branch_name: branch_name,
- commit_message: "Create file",
- file_path: file_name,
- file_content: content
- ).execute
-
- project.commit(branch_name)
- end
-
it 'escapes any HTML special characters in the diff chunk header' do
file_content =
<<~CONTENT
@@ -136,5 +122,61 @@ describe 'Merge request > User sees diff', :js do
expect(page).to have_css(".line[lang='rust'] .k")
end
end
+
+ context 'when file is stored in LFS' do
+ let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:current_user) { project.owner }
+
+ context 'when LFS is enabled on the project' do
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
+
+ create_file('master', file_name, project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data)
+
+ visit diffs_project_merge_request_path(project, merge_request)
+ end
+
+ context 'when file is an image', :js do
+ let(:file_name) { 'files/lfs/image.png' }
+
+ it 'shows an error message' do
+ expect(page).not_to have_content('could not be displayed because it is stored in LFS')
+ end
+ end
+
+ context 'when file is not an image' do
+ let(:file_name) { 'files/lfs/ruby.rb' }
+
+ it 'shows an error message' do
+ expect(page).to have_content('This source diff could not be displayed because it is stored in LFS')
+ end
+ end
+ end
+
+ context 'when LFS is not enabled' do
+ before do
+ visit diffs_project_merge_request_path(project, merge_request)
+ end
+
+ it 'displays the diff' do
+ expect(page).to have_content('size 1575078')
+ end
+ end
+ end
+
+ def create_file(branch_name, file_name, content)
+ Files::CreateService.new(
+ project,
+ current_user,
+ start_branch: branch_name,
+ branch_name: branch_name,
+ commit_message: "Create file",
+ file_path: file_name,
+ file_content: content
+ ).execute
+
+ project.commit(branch_name)
+ end
end
end
diff --git a/spec/features/merge_request/user_sees_discussions_spec.rb b/spec/features/merge_request/user_sees_discussions_spec.rb
index 4ab9a87ad4b..57be1d06708 100644
--- a/spec/features/merge_request/user_sees_discussions_spec.rb
+++ b/spec/features/merge_request/user_sees_discussions_spec.rb
@@ -88,5 +88,17 @@ describe 'Merge request > User sees discussions', :js do
expect(page).to have_content "started a discussion on commit #{note.commit_id[0...7]}"
end
end
+
+ context 'a commit non-diff discussion' do
+ let(:note) { create(:discussion_note_on_commit, project: project) }
+
+ it 'displays correct header' do
+ page.within(find("#note_#{note.id}", match: :first)) do
+ refresh # Trigger a refresh of notes.
+ wait_for_requests
+ expect(page).to have_content "commented on commit #{note.commit_id[0...7]}"
+ end
+ end
+ end
end
end
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
index 7b473faa884..97b2aa82fce 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
@@ -49,7 +49,7 @@ describe 'Merge request > User sees merge request pipelines', :js do
let!(:merge_request_pipeline) do
Ci::CreatePipelineService.new(project, user, ref: 'feature')
- .execute(:merge_request, merge_request: merge_request)
+ .execute(:merge_request_event, merge_request: merge_request)
end
before do
@@ -81,7 +81,7 @@ describe 'Merge request > User sees merge request pipelines', :js do
let!(:merge_request_pipeline_2) do
Ci::CreatePipelineService.new(project, user, ref: 'feature')
- .execute(:merge_request, merge_request: merge_request)
+ .execute(:merge_request_event, merge_request: merge_request)
end
before do
@@ -220,7 +220,7 @@ describe 'Merge request > User sees merge request pipelines', :js do
let!(:merge_request_pipeline) do
Ci::CreatePipelineService.new(forked_project, user2, ref: 'feature')
- .execute(:merge_request, merge_request: merge_request)
+ .execute(:merge_request_event, merge_request: merge_request)
end
let(:forked_project) { fork_project(project, user2, repository: true) }
@@ -263,7 +263,7 @@ describe 'Merge request > User sees merge request pipelines', :js do
let!(:merge_request_pipeline_2) do
Ci::CreatePipelineService.new(forked_project, user2, ref: 'feature')
- .execute(:merge_request, merge_request: merge_request)
+ .execute(:merge_request_event, merge_request: merge_request)
end
before do
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index d8ebd3c92af..afb978d7c45 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -316,7 +316,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'user cannot remove source branch' do
expect(page).not_to have_field('remove-source-branch-input')
- expect(page).to have_content('Removes source branch')
+ expect(page).to have_content('Deletes source branch')
end
end
diff --git a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
index 0272d300e06..5188dc3625f 100644
--- a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
+++ b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
@@ -5,7 +5,7 @@ describe 'Merge request < User sees mini pipeline graph', :js do
let(:user) { project.creator }
let(:merge_request) { create(:merge_request, source_project: project, head_pipeline: pipeline) }
let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: 'master', status: 'running', sha: project.commit.id) }
- let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test', commands: 'test') }
+ let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test') }
before do
build.run
@@ -51,22 +51,52 @@ describe 'Merge request < User sees mini pipeline graph', :js do
first('.mini-pipeline-graph-dropdown-toggle')
end
- it 'expands when hovered' do
+ # Status icon button styles should update as described in
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/42769
+ it 'has unique styles for default, :hover, :active, and :focus states' do
find('.mini-pipeline-graph-dropdown-toggle')
- before_width = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').outerWidth();")
+ default_background_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('background-color');")
+ default_foreground_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible svg').css('fill');")
+ default_box_shadow = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('box-shadow');")
toggle.hover
find('.mini-pipeline-graph-dropdown-toggle')
- after_width = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').outerWidth();")
+ hover_background_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('background-color');")
+ hover_foreground_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible svg').css('fill');")
+ hover_box_shadow = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('box-shadow');")
- expect(before_width).to be < after_width
- end
+ page.driver.browser.action.click_and_hold(toggle.native).perform
- it 'shows dropdown caret when hovered' do
- toggle.hover
+ find('.mini-pipeline-graph-dropdown-toggle')
+ active_background_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('background-color');")
+ active_foreground_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible svg').css('fill');")
+ active_box_shadow = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('box-shadow');")
+
+ page.driver.browser.action.release(toggle.native)
+ .move_by(100, 100)
+ .perform
+
+ find('.mini-pipeline-graph-dropdown-toggle')
+ focus_background_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('background-color');")
+ focus_foreground_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible svg').css('fill');")
+ focus_box_shadow = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('box-shadow');")
+
+ expect(default_background_color).not_to eq(hover_background_color)
+ expect(hover_background_color).not_to eq(active_background_color)
+ expect(default_background_color).not_to eq(active_background_color)
+
+ expect(default_foreground_color).not_to eq(hover_foreground_color)
+ expect(hover_foreground_color).not_to eq(active_foreground_color)
+ expect(default_foreground_color).not_to eq(active_foreground_color)
+
+ expect(focus_background_color).to eq(hover_background_color)
+ expect(focus_foreground_color).to eq(hover_foreground_color)
- expect(toggle).to have_selector('.fa-caret-down')
+ expect(default_box_shadow).to eq('none')
+ expect(hover_box_shadow).to eq('none')
+ expect(active_box_shadow).not_to eq('none')
+ expect(focus_box_shadow).not_to eq('none')
end
it 'shows tooltip when hovered' do
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index f7512294bef..5c45e363997 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -1,7 +1,11 @@
require 'rails_helper'
describe 'Merge request > User sees versions', :js do
- let(:merge_request) { create(:merge_request, importing: true) }
+ let(:merge_request) do
+ create(:merge_request).tap do |mr|
+ mr.merge_request_diff.destroy
+ end
+ end
let(:project) { merge_request.source_project }
let(:user) { project.creator }
let!(:merge_request_diff1) { merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
@@ -42,7 +46,7 @@ describe 'Merge request > User sees versions', :js do
expect(page).to have_content 'latest version'
end
- expect(page).to have_content '8 changed files'
+ expect(page).to have_content '8 Files'
end
it_behaves_like 'allows commenting',
@@ -64,8 +68,19 @@ describe 'Merge request > User sees versions', :js do
end
end
+ it 'shows the commit SHAs for every version in the dropdown' do
+ page.within '.mr-version-dropdown' do
+ find('.btn-default').click
+
+ page.within('.dropdown-content') do
+ shas = merge_request.merge_request_diffs.map { |diff| Commit.truncate_sha(diff.head_commit_sha) }
+ shas.each { |sha| expect(page).to have_content(sha) }
+ end
+ end
+ end
+
it 'shows comments that were last relevant at that version' do
- expect(page).to have_content '5 changed files'
+ expect(page).to have_content '5 Files'
position = Gitlab::Diff::Position.new(
old_path: ".gitmodules",
@@ -109,8 +124,15 @@ describe 'Merge request > User sees versions', :js do
diff_id: merge_request_diff3.id,
start_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9'
)
- expect(page).to have_content '4 changed files'
- expect(page).to have_content '15 additions 6 deletions'
+ expect(page).to have_content '4 Files'
+
+ additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-addition')
+ .ancestor('.diff-stats-group').text
+ deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-deletion')
+ .ancestor('.diff-stats-group').text
+
+ expect(additions_content).to eq '15'
+ expect(deletions_content).to eq '6'
position = Gitlab::Diff::Position.new(
old_path: ".gitmodules",
@@ -130,8 +152,14 @@ describe 'Merge request > User sees versions', :js do
end
it 'show diff between new and old version' do
- expect(page).to have_content '4 changed files'
- expect(page).to have_content '15 additions 6 deletions'
+ additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-addition')
+ .ancestor('.diff-stats-group').text
+ deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-deletion')
+ .ancestor('.diff-stats-group').text
+
+ expect(page).to have_content '4 Files'
+ expect(additions_content).to eq '15'
+ expect(deletions_content).to eq '6'
end
it 'returns to latest version when "Show latest version" button is clicked' do
@@ -139,7 +167,7 @@ describe 'Merge request > User sees versions', :js do
page.within '.mr-version-dropdown' do
expect(page).to have_content 'latest version'
end
- expect(page).to have_content '8 changed files'
+ expect(page).to have_content '8 Files'
end
it_behaves_like 'allows commenting',
@@ -165,7 +193,7 @@ describe 'Merge request > User sees versions', :js do
find('.btn-default').click
click_link 'version 1'
end
- expect(page).to have_content '0 changed files'
+ expect(page).to have_content '0 Files'
end
end
@@ -191,7 +219,7 @@ describe 'Merge request > User sees versions', :js do
expect(page).to have_content 'version 1'
end
- expect(page).to have_content '0 changed files'
+ expect(page).to have_content '0 Files'
end
end
diff --git a/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb b/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb
index dd860382daa..0decdfe3a14 100644
--- a/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb
+++ b/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb
@@ -9,17 +9,23 @@ describe 'Merge request > User toggles whitespace changes', :js do
project.add_maintainer(user)
sign_in(user)
visit diffs_project_merge_request_path(project, merge_request)
+
+ find('.js-show-diff-settings').click
end
it 'has a button to toggle whitespace changes' do
- expect(page).to have_content 'Hide whitespace changes'
+ expect(page).to have_content 'Show whitespace changes'
end
describe 'clicking "Hide whitespace changes" button' do
it 'toggles the "Hide whitespace changes" button' do
- click_link 'Hide whitespace changes'
+ find('#show-whitespace').click
+
+ visit diffs_project_merge_request_path(project, merge_request)
+
+ find('.js-show-diff-settings').click
- expect(page).to have_content 'Show whitespace changes'
+ expect(find('#show-whitespace')).to be_checked
end
end
end
diff --git a/spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb b/spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb
new file mode 100644
index 00000000000..9318b5f1ebb
--- /dev/null
+++ b/spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe 'Merge Request > Tries to access private repo of public project' do
+ let(:current_user) { create(:user) }
+ let(:private_project) do
+ create(:project, :public, :repository,
+ path: 'nothing-to-see-here',
+ name: 'nothing to see here',
+ repository_access_level: ProjectFeature::PRIVATE)
+ end
+ let(:owned_project) do
+ create(:project, :public, :repository,
+ namespace: current_user.namespace,
+ creator: current_user)
+ end
+
+ context 'when the user enters the querystring info for the other project' do
+ let(:mr_path) do
+ project_new_merge_request_diffs_path(
+ owned_project,
+ merge_request: {
+ source_project_id: private_project.id,
+ source_branch: 'feature'
+ }
+ )
+ end
+
+ before do
+ sign_in current_user
+ visit mr_path
+ end
+
+ it "does not mention the project the user can't see the repo of" do
+ expect(page).not_to have_content('nothing-to-see-here')
+ end
+ end
+end
diff --git a/spec/features/merge_request/user_views_diffs_spec.rb b/spec/features/merge_request/user_views_diffs_spec.rb
index 7f95a1282f9..0434db04113 100644
--- a/spec/features/merge_request/user_views_diffs_spec.rb
+++ b/spec/features/merge_request/user_views_diffs_spec.rb
@@ -23,6 +23,8 @@ describe 'User views diffs', :js do
end
it 'shows diffs' do
+ find('.js-show-diff-settings').click
+
expect(page).to have_css('.tab-content #diffs.active')
expect(page).to have_css('#parallel-diff-btn', count: 1)
expect(page).to have_css('#inline-diff-btn', count: 1)
@@ -38,6 +40,8 @@ describe 'User views diffs', :js do
context 'when in the side-by-side view' do
before do
+ find('.js-show-diff-settings').click
+
click_button 'Side-by-side'
wait_for_requests
diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
index ef7ae490b0f..c691011b9ca 100644
--- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb
+++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
@@ -13,7 +13,7 @@ describe 'Merge requests > User lists merge requests' do
source_project: project,
source_branch: 'fix',
assignee: user,
- milestone: create(:milestone, due_date: '2013-12-11'),
+ milestone: create(:milestone, project: project, due_date: '2013-12-11'),
created_at: 1.minute.ago,
updated_at: 1.minute.ago)
create(:merge_request,
@@ -21,7 +21,7 @@ describe 'Merge requests > User lists merge requests' do
source_project: project,
source_branch: 'markdown',
assignee: user,
- milestone: create(:milestone, due_date: '2013-12-12'),
+ milestone: create(:milestone, project: project, due_date: '2013-12-12'),
created_at: 2.minutes.ago,
updated_at: 2.minutes.ago)
create(: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 cb6603d3f50..e535c7e5811 100644
--- a/spec/features/merge_requests/user_mass_updates_spec.rb
+++ b/spec/features/merge_requests/user_mass_updates_spec.rb
@@ -68,7 +68,7 @@ describe 'Merge requests > User mass updates', :js do
end
context 'milestone' do
- let(:milestone) { create(:milestone, project: project) }
+ let(:milestone) { create(:milestone, project: project) }
describe 'set milestone' do
before do
diff --git a/spec/features/merge_requests/user_squashes_merge_request_spec.rb b/spec/features/merge_requests/user_squashes_merge_request_spec.rb
index ec1153b7f7f..bf9c55cf22c 100644
--- a/spec/features/merge_requests/user_squashes_merge_request_spec.rb
+++ b/spec/features/merge_requests/user_squashes_merge_request_spec.rb
@@ -14,7 +14,7 @@ describe 'User squashes a merge request', :js do
latest_master_commits = project.repository.commits_between(original_head.sha, 'master').map(&:raw)
squash_commit = an_object_having_attributes(sha: a_string_matching(/\h{40}/),
- message: "Csv\n",
+ message: a_string_starting_with(project.merge_requests.first.default_squash_commit_message),
author_name: user.name,
committer_name: user.name)
@@ -38,7 +38,7 @@ describe 'User squashes a merge request', :js do
def accept_mr
expect(page).to have_button('Merge')
- uncheck 'Remove source branch'
+ uncheck 'Delete source branch'
click_on 'Merge'
end
diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb
index a0673b12738..6e349395017 100644
--- a/spec/features/milestone_spec.rb
+++ b/spec/features/milestone_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
describe 'Milestone' do
let(:group) { create(:group, :public) }
let(:project) { create(:project, :public, namespace: group) }
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
before do
create(:group_member, group: group, user: user)
diff --git a/spec/features/profiles/active_sessions_spec.rb b/spec/features/profiles/active_sessions_spec.rb
index d3050760c06..2aa0177af5d 100644
--- a/spec/features/profiles/active_sessions_spec.rb
+++ b/spec/features/profiles/active_sessions_spec.rb
@@ -7,6 +7,8 @@ describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do
end
end
+ let(:admin) { create(:admin) }
+
around do |example|
Timecop.freeze(Time.zone.parse('2018-03-12 09:06')) do
example.run
@@ -16,6 +18,7 @@ describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do
it 'User sees their active sessions' do
Capybara::Session.new(:session1)
Capybara::Session.new(:session2)
+ Capybara::Session.new(:session3)
# note: headers can only be set on the non-js (aka. rack-test) driver
using_session :session1 do
@@ -37,9 +40,27 @@ describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do
gitlab_sign_in(user)
end
+ # set an admin session impersonating the user
+ using_session :session3 do
+ Capybara.page.driver.header(
+ 'User-Agent',
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
+ )
+
+ gitlab_sign_in(admin)
+
+ visit admin_user_path(user)
+
+ click_link 'Impersonate'
+ end
+
using_session :session1 do
visit profile_active_sessions_path
+ expect(page).to(
+ have_selector('ul.list-group li.list-group-item', { text: 'Signed in on',
+ count: 2 }))
+
expect(page).to have_content(
'127.0.0.1 ' \
'This is your current session ' \
@@ -57,33 +78,8 @@ describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do
)
expect(page).to have_selector '[title="Smartphone"]', count: 1
- end
- end
-
- it 'User can revoke a session', :js, :redis_session_store do
- Capybara::Session.new(:session1)
- Capybara::Session.new(:session2)
-
- # set an additional session in another browser
- using_session :session2 do
- gitlab_sign_in(user)
- end
-
- using_session :session1 do
- gitlab_sign_in(user)
- visit profile_active_sessions_path
-
- expect(page).to have_link('Revoke', count: 1)
-
- accept_confirm { click_on 'Revoke' }
-
- expect(page).not_to have_link('Revoke')
- end
-
- using_session :session2 do
- visit profile_active_sessions_path
- expect(page).to have_content('You need to sign in or sign up before continuing.')
+ expect(page).not_to have_content('Chrome on Windows')
end
end
end
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index 5e0434c1c2c..b43711f6ef6 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -10,6 +10,7 @@ describe 'User edit profile' do
def submit_settings
click_button 'Update profile settings'
+ wait_for_requests if respond_to?(:wait_for_requests)
end
it 'changes user profile' do
@@ -35,6 +36,17 @@ describe 'User edit profile' do
expect(page).to have_content('Profile was successfully updated')
end
+ it 'shows an error if the full name contains an emoji', :js do
+ simulate_input('#user_name', 'Martin 😀')
+ submit_settings
+
+ page.within('.qa-full-name') do
+ expect(page).to have_css '.gl-field-error-outline'
+ expect(find('.gl-field-error')).not_to have_selector('.hidden')
+ expect(find('.gl-field-error')).to have_content('Using emojis in names seems fun, but please try to set a status message instead')
+ end
+ end
+
context 'user avatar' do
before do
attach_file(:user_avatar, Rails.root.join('spec', 'fixtures', 'banana_sample.gif'))
@@ -61,6 +73,11 @@ describe 'User edit profile' do
end
context 'user status', :js do
+ def visit_user
+ visit user_path(user)
+ wait_for_requests
+ end
+
def select_emoji(emoji_name, is_modal = false)
emoji_menu_class = is_modal ? '.js-modal-status-emoji-menu' : '.js-status-emoji-menu'
toggle_button = find('.js-toggle-emoji-menu')
@@ -71,18 +88,16 @@ describe 'User edit profile' do
context 'profile edit form' do
it 'shows the user status form' do
- visit(profile_path)
-
expect(page).to have_content('Current status')
end
it 'adds emoji to user status' do
emoji = 'biohazard'
- visit(profile_path)
select_emoji(emoji)
submit_settings
- visit user_path(user)
+ visit_user
+
within('.cover-status') do
expect(page).to have_emoji(emoji)
end
@@ -90,11 +105,11 @@ describe 'User edit profile' do
it 'adds message to user status' do
message = 'I have something to say'
- visit(profile_path)
fill_in 'js-status-message-field', with: message
submit_settings
- visit user_path(user)
+ visit_user
+
within('.cover-status') do
expect(page).to have_emoji('speech_balloon')
expect(page).to have_content message
@@ -104,12 +119,12 @@ describe 'User edit profile' do
it 'adds message and emoji to user status' do
emoji = 'tanabata_tree'
message = 'Playing outside'
- visit(profile_path)
select_emoji(emoji)
fill_in 'js-status-message-field', with: message
submit_settings
- visit user_path(user)
+ visit_user
+
within('.cover-status') do
expect(page).to have_emoji(emoji)
expect(page).to have_content message
@@ -119,7 +134,8 @@ describe 'User edit profile' do
it 'clears the user status' do
user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
- visit user_path(user)
+ visit_user
+
within('.cover-status') do
expect(page).to have_emoji(user_status.emoji)
expect(page).to have_content user_status.message
@@ -129,15 +145,13 @@ describe 'User edit profile' do
click_button 'js-clear-user-status-button'
submit_settings
- wait_for_requests
+ visit_user
- visit user_path(user)
expect(page).not_to have_selector '.cover-status'
end
it 'displays a default emoji if only message is entered' do
message = 'a status without emoji'
- visit(profile_path)
fill_in 'js-status-message-field', with: message
within('.js-toggle-emoji-menu') do
@@ -147,6 +161,9 @@ describe 'User edit profile' do
end
context 'user menu' do
+ let(:issue) { create(:issue, project: project)}
+ let(:project) { create(:project) }
+
def open_user_status_modal
find('.header-user-dropdown-toggle').click
@@ -159,6 +176,7 @@ describe 'User edit profile' do
page.within "#set-user-status-modal" do
click_button 'Set status'
end
+ wait_for_requests
end
before do
@@ -199,19 +217,32 @@ describe 'User edit profile' do
select_emoji(emoji, true)
set_user_status_in_modal
- visit user_path(user)
+ visit_user
+
within('.cover-status') do
expect(page).to have_emoji(emoji)
end
end
+ it 'does not update the awards panel emoji' do
+ project.add_maintainer(user)
+ visit(project_issue_path(project, issue))
+
+ emoji = 'biohazard'
+ open_user_status_modal
+ select_emoji(emoji, true)
+
+ expect(page.all('.award-control .js-counter')).to all(have_content('0'))
+ end
+
it 'adds message to user status' do
message = 'I have something to say'
open_user_status_modal
find('.js-status-message-field').native.send_keys(message)
set_user_status_in_modal
- visit user_path(user)
+ visit_user
+
within('.cover-status') do
expect(page).to have_emoji('speech_balloon')
expect(page).to have_content message
@@ -226,7 +257,8 @@ describe 'User edit profile' do
find('.js-status-message-field').native.send_keys(message)
set_user_status_in_modal
- visit user_path(user)
+ visit_user
+
within('.cover-status') do
expect(page).to have_emoji(emoji)
expect(page).to have_content message
@@ -236,7 +268,9 @@ describe 'User edit profile' do
it 'clears the user status with the "X" button' do
user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
- visit user_path(user)
+ visit_user
+ wait_for_requests
+
within('.cover-status') do
expect(page).to have_emoji(user_status.emoji)
expect(page).to have_content user_status.message
@@ -251,14 +285,18 @@ describe 'User edit profile' do
find('.js-clear-user-status-button').click
set_user_status_in_modal
- visit user_path(user)
+ visit_user
+ wait_for_requests
+
expect(page).not_to have_selector '.cover-status'
end
it 'clears the user status with the "Remove status" button' do
user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
- visit user_path(user)
+ visit_user
+ wait_for_requests
+
within('.cover-status') do
expect(page).to have_emoji(user_status.emoji)
expect(page).to have_content user_status.message
@@ -274,7 +312,8 @@ describe 'User edit profile' do
click_button 'Remove status'
end
- visit user_path(user)
+ visit_user
+
expect(page).not_to have_selector '.cover-status'
end
diff --git a/spec/features/profiles/user_visits_profile_preferences_page_spec.rb b/spec/features/profiles/user_visits_profile_preferences_page_spec.rb
index 90d6841af0e..9909bfb5904 100644
--- a/spec/features/profiles/user_visits_profile_preferences_page_spec.rb
+++ b/spec/features/profiles/user_visits_profile_preferences_page_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe 'User visits the profile preferences page' do
+ include Select2Helper
+
let(:user) { create(:user) }
before do
@@ -60,6 +62,28 @@ describe 'User visits the profile preferences page' do
end
end
+ describe 'User changes their language', :js do
+ it 'creates a flash message' do
+ select2('en', from: '#user_preferred_language')
+ click_button 'Save'
+
+ wait_for_requests
+
+ expect_preferences_saved_message
+ end
+
+ it 'updates their preference' do
+ wait_for_requests
+ select2('eo', from: '#user_preferred_language')
+ click_button 'Save'
+
+ wait_for_requests
+ refresh
+
+ expect(page).to have_css('html[lang="eo"]')
+ end
+ end
+
def expect_preferences_saved_message
page.within('.flash-container') do
expect(page).to have_content('Preferences saved.')
diff --git a/spec/features/project_variables_spec.rb b/spec/features/project_variables_spec.rb
index a93df3696d2..6bdf5df1036 100644
--- a/spec/features/project_variables_spec.rb
+++ b/spec/features/project_variables_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'Project variables', :js do
let(:user) { create(:user) }
let(:project) { create(:project) }
- let(:variable) { create(:ci_variable, key: 'test_key', value: 'test value') }
+ let(:variable) { create(:ci_variable, key: 'test_key', value: 'test_value') }
let(:page_path) { project_settings_ci_cd_path(project) }
before do
diff --git a/spec/features/projects/artifacts/user_browses_artifacts_spec.rb b/spec/features/projects/artifacts/user_browses_artifacts_spec.rb
index 9ebbbaea911..5f630c9ffa4 100644
--- a/spec/features/projects/artifacts/user_browses_artifacts_spec.rb
+++ b/spec/features/projects/artifacts/user_browses_artifacts_spec.rb
@@ -25,8 +25,8 @@ describe "User browses artifacts" do
page.within(".tree-table") do
expect(page).to have_no_content("..")
.and have_content("other_artifacts_0.1.2")
- .and have_content("ci_artifacts.txt")
- .and have_content("rails_sample.jpg")
+ .and have_content("ci_artifacts.txt 27 Bytes")
+ .and have_content("rails_sample.jpg 34.4 KB")
end
page.within(".build-header") do
diff --git a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
index 554f0b49052..5cb015e80be 100644
--- a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
+++ b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
@@ -7,7 +7,7 @@ describe "User downloads artifacts" do
shared_examples "downloading" do
it "downloads the zip" do
- expect(page.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"})
+ expect(page.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename*=UTF-8''#{job.artifacts_file.filename}; filename="#{job.artifacts_file.filename}"})
expect(page.response_headers['Content-Transfer-Encoding']).to eq("binary")
expect(page.response_headers['Content-Type']).to eq("application/zip")
expect(page.source.b).to eq(job.artifacts_file.file.read.b)
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index e2f9e7e9cc5..a7aa63018fd 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -5,8 +5,8 @@ describe 'File blob', :js do
let(:project) { create(:project, :public, :repository) }
- def visit_blob(path, anchor: nil, ref: 'master', legacy_render: nil)
- visit project_blob_path(project, File.join(ref, path), anchor: anchor, legacy_render: legacy_render)
+ def visit_blob(path, anchor: nil, ref: 'master')
+ visit project_blob_path(project, File.join(ref, path), anchor: anchor)
wait_for_requests
end
@@ -171,21 +171,6 @@ describe 'File blob', :js do
end
end
end
-
- context 'when rendering legacy markdown' do
- before do
- visit_blob('files/commonmark/file.md', legacy_render: 1)
-
- wait_for_requests
- end
-
- it 'renders using RedCarpet' do
- aggregate_failures do
- expect(page).to have_content("sublist")
- expect(page).to have_xpath("//ol//li//ul")
- end
- end
- end
end
context 'Markdown file (stored in LFS)' do
@@ -563,10 +548,7 @@ describe 'File blob', :js do
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows names of dependency manager and package
- expect(page).to have_content('This project manages its dependencies using RubyGems and defines a gem named activerecord.')
-
- # shows a link to the gem
- expect(page).to have_link('activerecord', href: 'https://rubygems.org/gems/activerecord')
+ expect(page).to have_content('This project manages its dependencies using RubyGems.')
# shows a learn more link
expect(page).to have_link('Learn more', href: 'https://rubygems.org/')
diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb
index d5b20605860..828f6f9921e 100644
--- a/spec/features/projects/blobs/edit_spec.rb
+++ b/spec/features/projects/blobs/edit_spec.rb
@@ -9,6 +9,10 @@ describe 'Editing file blob', :js do
let(:file_path) { project.repository.ls_files(project.repository.root_ref)[1] }
let(:readme_file_path) { 'README.md' }
+ before do
+ stub_feature_flags(web_ide_default: false)
+ end
+
context 'as a developer' do
let(:user) { create(:user) }
let(:role) { :developer }
@@ -77,21 +81,10 @@ describe 'Editing file blob', :js do
click_link 'Preview'
wait_for_requests
- # the above generates two seperate lists (not embedded) in CommonMark
+ # the above generates two separate lists (not embedded) in CommonMark
expect(page).to have_content("sublist")
expect(page).not_to have_xpath("//ol//li//ul")
end
-
- it 'renders content with RedCarpet when legacy_render is set' do
- visit project_edit_blob_path(project, tree_join(branch, readme_file_path), legacy_render: 1)
- fill_editor(content: "1. one\\n - sublist\\n")
- click_link 'Preview'
- wait_for_requests
-
- # the above generates a sublist list in RedCarpet
- expect(page).to have_content("sublist")
- expect(page).to have_xpath("//ol//li//ul")
- end
end
end
diff --git a/spec/features/projects/branches/user_views_branches_spec.rb b/spec/features/projects/branches/user_views_branches_spec.rb
index 62ae793151c..777d30fdffd 100644
--- a/spec/features/projects/branches/user_views_branches_spec.rb
+++ b/spec/features/projects/branches/user_views_branches_spec.rb
@@ -15,6 +15,8 @@ describe "User views branches" do
it "shows branches" do
expect(page).to have_content("Branches").and have_content("master")
+
+ expect(page.all(".graph-side")).to all( have_content(/\d+/) )
end
end
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index 97757e8da92..ee71c843b80 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -229,6 +229,38 @@ describe 'Branches' do
end
end
+ describe 'comparing branches' do
+ before do
+ sign_in(user)
+ project.add_developer(user)
+ end
+
+ shared_examples 'compares branches' do
+ it 'compares branches' do
+ visit project_branches_path(project)
+
+ page.within first('.all-branches li') do
+ click_link 'Compare'
+ end
+
+ expect(page).to have_content 'Commits'
+ expect(page).to have_link 'Create merge request'
+ end
+ end
+
+ context 'on a read-only instance' do
+ before do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(true)
+ end
+
+ it_behaves_like 'compares branches'
+ end
+
+ context 'on a read-write instance' do
+ it_behaves_like 'compares branches'
+ end
+ end
+
def sorted_branches(repository, count:, sort_by:, state: nil)
branches = repository.branches_sorted_by(sort_by)
branches = branches.select { |b| state == 'active' ? b.active? : b.stale? } if state
diff --git a/spec/features/projects/clusters/applications_spec.rb b/spec/features/projects/clusters/applications_spec.rb
index 8918a7b7b9c..2c8d014c36d 100644
--- a/spec/features/projects/clusters/applications_spec.rb
+++ b/spec/features/projects/clusters/applications_spec.rb
@@ -48,9 +48,9 @@ describe 'Clusters Applications', :js do
it 'they see status transition' do
page.within('.js-cluster-application-row-helm') do
- # FE sends request and gets the response, then the buttons is "Install"
+ # FE sends request and gets the response, then the buttons is "Installing"
expect(page.find(:css, '.js-cluster-application-install-button')['disabled']).to eq('true')
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Install')
+ expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
wait_until_helm_created!
@@ -70,6 +70,34 @@ describe 'Clusters Applications', :js do
end
end
+ context 'when user installs Knative' do
+ before do
+ create(:clusters_applications_helm, :installed, cluster: cluster)
+ end
+
+ context 'on an abac cluster' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :rbac_disabled, projects: [project])}
+
+ it 'should show info block and not be installable' do
+ page.within('.js-cluster-application-row-knative') do
+ expect(page).to have_css('.bs-callout-info')
+ expect(page.find(:css, '.js-cluster-application-install-button')['disabled']).to eq('true')
+ end
+ end
+ end
+
+ context 'on an rbac cluster' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project])}
+
+ it 'should not show callout block and be installable' do
+ page.within('.js-cluster-application-row-knative') do
+ expect(page).not_to have_css('.bs-callout-info')
+ expect(page).to have_css('.js-cluster-application-install-button:not([disabled])')
+ end
+ end
+ end
+ end
+
context 'when user installs Cert Manager' do
before do
allow(ClusterInstallAppWorker).to receive(:perform_async)
@@ -90,7 +118,7 @@ describe 'Clusters Applications', :js do
page.within('.js-cluster-application-row-cert_manager') do
expect(email_form_value).to eq(cluster.user.email)
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Install')
+ expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
page.find('.js-email').set("new_email@example.org")
Clusters::Cluster.last.application_cert_manager.make_installing!
@@ -125,9 +153,9 @@ describe 'Clusters Applications', :js do
it 'they see status transition' do
page.within('.js-cluster-application-row-ingress') do
- # FE sends request and gets the response, then the buttons is "Install"
+ # FE sends request and gets the response, then the buttons is "Installing"
expect(page).to have_css('.js-cluster-application-install-button[disabled]')
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Install')
+ expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
Clusters::Cluster.last.application_ingress.make_installing!
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index 06e30571336..9322e29d744 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -33,32 +33,6 @@ describe 'Gcp Cluster', :js do
context 'when user filled form with valid parameters' do
subject { click_button 'Create Kubernetes cluster' }
- shared_examples 'valid cluster gcp form' do
- it 'users sees a form with the GCP token' do
- expect(page).to have_selector(:css, 'form[data-token="token"]')
- end
-
- it 'user sees a cluster details page and creation status' do
- subject
-
- expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...')
-
- Clusters::Cluster.last.provider.make_created!
-
- expect(page).to have_content('Kubernetes cluster was successfully created on Google Kubernetes Engine')
- end
-
- it 'user sees a error if something wrong during creation' do
- subject
-
- expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...')
-
- Clusters::Cluster.last.provider.make_errored!('Something wrong!')
-
- expect(page).to have_content('Something wrong!')
- end
- end
-
before do
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
.to receive(:projects_zones_clusters_create) do
@@ -82,14 +56,32 @@ describe 'Gcp Cluster', :js do
fill_in 'cluster[provider_gcp_attributes][machine_type]', with: 'n1-standard-2'
end
- it_behaves_like 'valid cluster gcp form'
+ it 'users sees a form with the GCP token' do
+ expect(page).to have_selector(:css, 'form[data-token="token"]')
+ end
- context 'RBAC is enabled for the cluster' do
- before do
- check 'cluster_provider_gcp_attributes_legacy_abac'
- end
+ it 'user sees a cluster details page and creation status' do
+ subject
+
+ expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...')
+
+ Clusters::Cluster.last.provider.make_created!
+
+ expect(page).to have_content('Kubernetes cluster was successfully created on Google Kubernetes Engine')
+ end
+
+ it 'user sees a error if something wrong during creation' do
+ subject
+
+ expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...')
+
+ Clusters::Cluster.last.provider.make_errored!('Something wrong!')
+
+ expect(page).to have_content('Something wrong!')
+ end
- it_behaves_like 'valid cluster gcp form'
+ it 'user sees RBAC is enabled by default' do
+ expect(page).to have_checked_field('RBAC-enabled cluster')
end
end
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index 250c964cc32..1f2f7592d8b 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -23,19 +23,6 @@ describe 'User Cluster', :js do
end
context 'when user filled form with valid parameters' do
- shared_examples 'valid cluster user form' do
- it 'user sees a cluster details page' do
- subject
-
- expect(page).to have_content('Kubernetes cluster integration')
- expect(page.find_field('cluster[name]').value).to eq('dev-cluster')
- expect(page.find_field('cluster[platform_kubernetes_attributes][api_url]').value)
- .to have_content('http://example.com')
- expect(page.find_field('cluster[platform_kubernetes_attributes][token]').value)
- .to have_content('my-token')
- end
- end
-
before do
fill_in 'cluster_name', with: 'dev-cluster'
fill_in 'cluster_platform_kubernetes_attributes_api_url', with: 'http://example.com'
@@ -44,20 +31,19 @@ describe 'User Cluster', :js do
subject { click_button 'Add Kubernetes cluster' }
- it_behaves_like 'valid cluster user form'
-
- context 'RBAC is enabled for the cluster' do
- before do
- check 'cluster_platform_kubernetes_attributes_authorization_type'
- end
-
- it_behaves_like 'valid cluster user form'
+ it 'user sees a cluster details page' do
+ subject
- it 'user sees a cluster details page with RBAC enabled' do
- subject
+ expect(page).to have_content('Kubernetes cluster integration')
+ expect(page.find_field('cluster[name]').value).to eq('dev-cluster')
+ expect(page.find_field('cluster[platform_kubernetes_attributes][api_url]').value)
+ .to have_content('http://example.com')
+ expect(page.find_field('cluster[platform_kubernetes_attributes][token]').value)
+ .to have_content('my-token')
+ end
- expect(page.find_field('cluster[platform_kubernetes_attributes][authorization_type]', disabled: true)).to be_checked
- end
+ it 'user sees RBAC is enabled by default' do
+ expect(page).to have_checked_field('RBAC-enabled cluster')
end
end
diff --git a/spec/features/projects/commit/builds_spec.rb b/spec/features/projects/commit/builds_spec.rb
index caf69796d52..d72476f36a9 100644
--- a/spec/features/projects/commit/builds_spec.rb
+++ b/spec/features/projects/commit/builds_spec.rb
@@ -20,7 +20,7 @@ describe 'project commit pipelines', :js do
visit pipelines_project_commit_path(project, project.commit.sha)
page.within('.table-holder') do
- expect(page).to have_content project.ci_pipelines[0].id # pipeline ids
+ expect(page).to have_content project.ci_pipelines[0].id # pipeline ids
end
end
end
diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb
index a61b614dbc8..acfb582dba9 100644
--- a/spec/features/projects/commit/cherry_pick_spec.rb
+++ b/spec/features/projects/commit/cherry_pick_spec.rb
@@ -4,8 +4,8 @@ describe 'Cherry-pick Commits' do
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:project) { create(:project, :repository, namespace: group) }
- let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
- let(:master_pickable_merge) { project.commit('e56497bb5f03a90a51293fc6d516788730953899') }
+ let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
+ let(:master_pickable_merge) { project.commit('e56497bb5f03a90a51293fc6d516788730953899') }
before do
sign_in(user)
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 2159adf49fc..574a8aefd63 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -93,7 +93,7 @@ describe 'User browses commits' do
it 'shows a blank label' do
allow_any_instance_of(Gitlab::Diff::File).to receive(:blob).and_return(nil)
- allow_any_instance_of(Gitlab::Diff::File).to receive(:raw_binary?).and_return(true)
+ allow_any_instance_of(Gitlab::Diff::File).to receive(:binary?).and_return(true)
visit(project_commit_path(project, commit))
diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb
index 69600884909..5f7cf68987e 100644
--- a/spec/features/projects/compare_spec.rb
+++ b/spec/features/projects/compare_spec.rb
@@ -87,6 +87,21 @@ describe "Compare", :js do
expect(find(".js-compare-from-dropdown .dropdown-content")).to have_selector("li", count: 3)
end
+
+ context 'when commit has overflow', :js do
+ it 'displays warning' do
+ visit project_compare_index_path(project, from: "feature", to: "master")
+
+ allow(Commit).to receive(:max_diff_options).and_return(max_files: 3)
+ allow_any_instance_of(DiffHelper).to receive(:render_overflow_warning?).and_return(true)
+
+ click_button('Compare')
+
+ page.within('.alert') do
+ expect(page).to have_text("Too many changes to show. To preserve performance only 3 of 3+ files are displayed.")
+ end
+ end
+ end
end
describe "tags" do
diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb
index e12532e97fa..1fa9babaff5 100644
--- a/spec/features/projects/deploy_keys_spec.rb
+++ b/spec/features/projects/deploy_keys_spec.rb
@@ -20,7 +20,7 @@ describe 'Project deploy keys', :js do
page.within(find('.deploy-keys')) do
expect(page).to have_selector('.deploy-key', count: 1)
- accept_confirm { find('.ic-remove').click() }
+ accept_confirm { find('.ic-remove').click }
wait_for_requests
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index a8a3b6910fb..3090f1a2131 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -120,7 +120,7 @@ describe 'Environment' do
end
it 'does show a play button' do
- expect(page).to have_link(action.name.humanize)
+ expect(page).to have_link(action.name)
end
it 'does allow to play manual action', :js do
@@ -128,7 +128,7 @@ describe 'Environment' do
find('button.dropdown').click
- expect { click_link(action.name.humanize) }
+ expect { click_link(action.name) }
.not_to change { Ci::Pipeline.count }
wait_for_all_requests
@@ -140,7 +140,7 @@ describe 'Environment' do
context 'when user has no ability to trigger a deployment' do
it 'does not show a play button' do
- expect(page).not_to have_link(action.name.humanize)
+ expect(page).not_to have_link(action.name)
end
end
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index 89954d35f91..b2a435e554d 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -38,6 +38,23 @@ describe 'Environments page', :js do
end
end
+ describe 'with environments spanning multiple pages', :js do
+ before do
+ allow(Kaminari.config).to receive(:default_per_page).and_return(3)
+ create_list(:environment, 4, project: project, state: :available)
+ end
+
+ it 'should render second page of pipelines' do
+ visit_environments(project, scope: 'available')
+
+ find('.js-next-button').click
+ wait_for_requests
+
+ expect(page).to have_selector('.gl-pagination .page', count: 2)
+ expect(find('.gl-pagination .page-item.active .page-link').text).to eq("2")
+ end
+ end
+
describe 'in stopped tab page' do
it 'should show no environments' do
visit_environments(project, scope: 'stopped')
@@ -166,14 +183,14 @@ describe 'Environments page', :js do
it 'shows a play button' do
find('.js-environment-actions-dropdown').click
- expect(page).to have_content(action.name.humanize)
+ expect(page).to have_content(action.name)
end
it 'allows to play a manual action', :js do
expect(action).to be_manual
find('.js-environment-actions-dropdown').click
- expect(page).to have_content(action.name.humanize)
+ expect(page).to have_content(action.name)
expect { find('.js-manual-action-link').click }
.not_to change { Ci::Pipeline.count }
@@ -272,8 +289,7 @@ describe 'Environments page', :js do
create(:ci_build, :scheduled,
pipeline: pipeline,
name: 'delayed job',
- stage: 'test',
- commands: 'test')
+ stage: 'test')
end
let!(:deployment) do
@@ -295,7 +311,7 @@ describe 'Environments page', :js do
it "has link to the delayed job's action" do
find('.js-environment-actions-dropdown').click
- expect(page).to have_button('Delayed job')
+ expect(page).to have_button('delayed job')
expect(page).to have_content(/\d{2}:\d{2}:\d{2}/)
end
@@ -304,8 +320,7 @@ describe 'Environments page', :js do
create(:ci_build, :expired_scheduled,
pipeline: pipeline,
name: 'delayed job',
- stage: 'test',
- commands: 'test')
+ stage: 'test')
end
it "shows 00:00:00 as the remaining time" do
@@ -318,7 +333,7 @@ describe 'Environments page', :js do
context 'when user played a delayed job immediately' do
before do
find('.js-environment-actions-dropdown').click
- page.accept_confirm { click_button('Delayed job') }
+ page.accept_confirm { click_button('delayed job') }
wait_for_requests
end
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
index 5de0bc009fb..fa785ed10ef 100644
--- a/spec/features/projects/files/undo_template_spec.rb
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -50,7 +50,7 @@ end
def check_content_reverted(template_content)
find('.template-selectors-undo-menu .btn-info').click
expect(page).not_to have_content(template_content)
- expect(find('.template-type-selector .dropdown-toggle-text')).to have_content()
+ expect(find('.template-type-selector .dropdown-toggle-text')).to have_content
end
def select_file_template(template_selector_selector, template_name)
diff --git a/spec/features/projects/files/user_browses_lfs_files_spec.rb b/spec/features/projects/files/user_browses_lfs_files_spec.rb
index c559a301ca1..d56476adb05 100644
--- a/spec/features/projects/files/user_browses_lfs_files_spec.rb
+++ b/spec/features/projects/files/user_browses_lfs_files_spec.rb
@@ -12,6 +12,7 @@ describe 'Projects > Files > User browses LFS files' do
before do
allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(false)
visit project_tree_path(project, 'lfs')
+ wait_for_requests
end
it 'is possible to see raw content of LFS pointer' do
@@ -26,10 +27,11 @@ describe 'Projects > Files > User browses LFS files' do
end
end
- context 'when LFS is enabled' do
+ context 'when LFS is enabled', :js do
before do
allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(true)
visit project_tree_path(project, 'lfs')
+ wait_for_requests
end
it 'shows an LFS object' do
diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb
index a4f94b7a76d..dd2964c2186 100644
--- a/spec/features/projects/files/user_creates_files_spec.rb
+++ b/spec/features/projects/files/user_creates_files_spec.rb
@@ -12,6 +12,8 @@ describe 'Projects > Files > User creates files' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(web_ide_default: false)
+
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/features/projects/files/user_edits_files_spec.rb b/spec/features/projects/files/user_edits_files_spec.rb
index 9eb65ec159c..ec3930c26db 100644
--- a/spec/features/projects/files/user_edits_files_spec.rb
+++ b/spec/features/projects/files/user_edits_files_spec.rb
@@ -9,6 +9,8 @@ describe 'Projects > Files > User edits files', :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(web_ide_default: false)
+
sign_in(user)
end
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 60f37f4b74a..65ce872363f 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -28,7 +28,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it "shows Pending tab jobs" do
- expect(page).to have_link 'Cancel running'
expect(page).to have_selector('.nav-links li.active', text: 'Pending')
expect(page).to have_content job.short_sha
expect(page).to have_content job.ref
@@ -44,7 +43,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it "shows Running tab jobs" do
expect(page).to have_selector('.nav-links li.active', text: 'Running')
- expect(page).to have_link 'Cancel running'
expect(page).to have_content job.short_sha
expect(page).to have_content job.ref
expect(page).to have_content job.name
@@ -60,7 +58,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it "shows Finished tab jobs" do
expect(page).to have_selector('.nav-links li.active', text: 'Finished')
expect(page).to have_content 'No jobs to show'
- expect(page).to have_link 'Cancel running'
end
end
@@ -75,7 +72,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
expect(page).to have_content job.short_sha
expect(page).to have_content job.ref
expect(page).to have_content job.name
- expect(page).not_to have_link 'Cancel running'
end
end
@@ -94,23 +90,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- describe "POST /:project/jobs/:id/cancel_all" do
- before do
- job.run!
- visit project_jobs_path(project)
- click_link "Cancel running"
- end
-
- it 'shows all necessary content' do
- expect(page).to have_selector('.nav-links li.active', text: 'All')
- expect(page).to have_content 'canceled'
- expect(page).to have_content job.short_sha
- expect(page).to have_content job.ref
- expect(page).to have_content job.name
- expect(page).not_to have_link 'Cancel running'
- end
- end
-
describe "GET /:project/jobs/:id" do
context "Job from project" do
let(:job) { create(:ci_build, :success, :trace_live, pipeline: pipeline) }
@@ -124,7 +103,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it 'shows commit`s data', :js do
- requests = inspect_requests() do
+ requests = inspect_requests do
visit project_job_path(project, job)
end
@@ -191,7 +170,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
href = new_project_issue_path(project, options)
- page.within('.header-action-buttons') do
+ page.within('.build-sidebar') do
expect(find('.js-new-issue')['href']).to include(href)
end
end
@@ -235,13 +214,13 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it 'downloads the zip file when user clicks the download button' do
- requests = inspect_requests() do
+ requests = inspect_requests do
click_link 'Download'
end
artifact_request = requests.find { |req| req.url.match(%r{artifacts/download}) }
- expect(artifact_request.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"})
+ expect(artifact_request.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename*=UTF-8''#{job.artifacts_file.filename}; filename="#{job.artifacts_file.filename}"})
expect(artifact_request.response_headers['Content-Transfer-Encoding']).to eq("binary")
expect(artifact_request.response_headers['Content-Type']).to eq("image/gif")
expect(artifact_request.body).to eq(job.artifacts_file.file.read.b)
@@ -845,7 +824,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
before do
job.run!
visit project_job_path(project, job)
- find('.js-cancel-job').click()
+ find('.js-cancel-job').click
end
it 'loads the page and shows all needed controls' do
@@ -905,7 +884,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it do
- requests = inspect_requests() do
+ requests = inspect_requests do
visit download_project_job_artifacts_path(project, job2)
end
diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb
index 055a0c83a11..d36f043f880 100644
--- a/spec/features/projects/labels/update_prioritization_spec.rb
+++ b/spec/features/projects/labels/update_prioritization_spec.rb
@@ -125,7 +125,7 @@ describe 'Prioritize labels' do
wait_for_requests
end
- page.within('.breadcrumbs-container') do
+ page.within('.top-area') do
expect(page).to have_link('New label')
end
end
diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb
index fceead0b45e..b2d2dba55f1 100644
--- a/spec/features/projects/members/invite_group_spec.rb
+++ b/spec/features/projects/members/invite_group_spec.rb
@@ -27,6 +27,7 @@ describe 'Project > Members > Invite group', :js do
before do
project.add_maintainer(maintainer)
+ group_to_share_with.add_guest(maintainer)
sign_in(maintainer)
end
@@ -112,6 +113,7 @@ describe 'Project > Members > Invite group', :js do
before do
project.add_maintainer(maintainer)
+ group.add_guest(maintainer)
sign_in(maintainer)
visit project_settings_members_path(project)
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
index 435fb229b69..f564ae34f11 100644
--- a/spec/features/projects/pages_spec.rb
+++ b/spec/features/projects/pages_spec.rb
@@ -13,16 +13,6 @@ describe 'Pages' do
sign_in(user)
end
- shared_examples 'no pages deployed' do
- 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')
- expect(page).not_to have_text('Only the project owner can remove pages')
- end
- end
-
context 'when user is the owner' do
before do
project.namespace.update(owner: user)
@@ -181,7 +171,12 @@ describe 'Pages' do
end
end
- it_behaves_like 'no pages deployed'
+ 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
@@ -208,22 +203,6 @@ describe 'Pages' do
end
end
- context 'when the user is not the owner' do
- context 'when pages deployed' do
- before do
- allow_any_instance_of(Project).to receive(:pages_deployed?) { true }
- end
-
- it 'sees "Only the project owner can remove pages" text' do
- visit project_pages_path(project)
-
- expect(page).to have_text('Only the project owner can remove pages')
- end
- end
-
- it_behaves_like 'no pages deployed'
- end
-
describe 'HTTPS settings', :js, :https_pages_enabled do
before do
project.namespace.update(owner: user)
@@ -233,7 +212,7 @@ describe 'Pages' do
it 'tries to change the setting' do
visit project_pages_path(project)
- expect(page).to have_content("Force domains with SSL certificates to use HTTPS")
+ expect(page).to have_content("Force HTTPS (requires valid certificates)")
uncheck :project_pages_https_only
@@ -282,58 +261,52 @@ describe 'Pages' do
visit project_pages_path(project)
expect(page).not_to have_field(:project_pages_https_only)
- expect(page).not_to have_content('Force domains with SSL certificates to use HTTPS')
+ expect(page).not_to have_content('Force HTTPS (requires valid certificates)')
expect(page).not_to have_button('Save')
end
end
end
describe 'Remove page' do
- context 'when user is the owner' do
- let(:project) { create :project, :repository }
-
- before do
- project.namespace.update(owner: user)
+ let(:project) { create :project, :repository }
+
+ context 'when pages are deployed' do
+ let(:pipeline) do
+ commit_sha = project.commit('HEAD').sha
+
+ project.ci_pipelines.create(
+ ref: 'HEAD',
+ sha: commit_sha,
+ source: :push,
+ protected: false
+ )
end
- context 'when pages are deployed' do
- let(:pipeline) do
- commit_sha = project.commit('HEAD').sha
-
- project.ci_pipelines.create(
- ref: 'HEAD',
- sha: commit_sha,
- source: :push,
- protected: false
- )
- end
-
- let(:ci_build) do
- create(
- :ci_build,
- project: project,
- pipeline: pipeline,
- ref: 'HEAD',
- legacy_artifacts_file: fixture_file_upload(File.join('spec/fixtures/pages.zip')),
- legacy_artifacts_metadata: fixture_file_upload(File.join('spec/fixtures/pages.zip.meta'))
- )
- end
+ let(:ci_build) do
+ create(
+ :ci_build,
+ project: project,
+ pipeline: pipeline,
+ ref: 'HEAD',
+ legacy_artifacts_file: fixture_file_upload(File.join('spec/fixtures/pages.zip')),
+ legacy_artifacts_metadata: fixture_file_upload(File.join('spec/fixtures/pages.zip.meta'))
+ )
+ end
- before do
- result = Projects::UpdatePagesService.new(project, ci_build).execute
- expect(result[:status]).to eq(:success)
- expect(project).to be_pages_deployed
- end
+ before do
+ result = Projects::UpdatePagesService.new(project, ci_build).execute
+ expect(result[:status]).to eq(:success)
+ expect(project).to be_pages_deployed
+ end
- it 'removes the pages' do
- visit project_pages_path(project)
+ it 'removes the pages' do
+ visit project_pages_path(project)
- expect(page).to have_link('Remove pages')
+ expect(page).to have_link('Remove pages')
- click_link 'Remove pages'
+ click_link 'Remove pages'
- expect(project.pages_deployed?).to be_falsey
- end
+ expect(project.pages_deployed?).to be_falsey
end
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index a37ad9c3f43..36b8c15b8b6 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -18,7 +18,7 @@ describe 'Pipeline', :js do
let!(:build_failed) do
create(:ci_build, :failed,
- pipeline: pipeline, stage: 'test', name: 'test', commands: 'test')
+ pipeline: pipeline, stage: 'test', name: 'test')
end
let!(:build_running) do
@@ -286,6 +286,49 @@ describe 'Pipeline', :js do
end
end
+ context 'when a bridge job exists' do
+ include_context 'pipeline builds'
+
+ let(:project) { create(:project, :repository) }
+ let(:downstream) { create(:project, :repository) }
+
+ let(:pipeline) do
+ create(:ci_pipeline, project: project,
+ ref: 'master',
+ sha: project.commit.id,
+ user: user)
+ end
+
+ let!(:bridge) do
+ create(:ci_bridge, pipeline: pipeline,
+ name: 'cross-build',
+ user: user,
+ downstream: downstream)
+ end
+
+ describe 'GET /:project/pipelines/:id' do
+ before do
+ visit project_pipeline_path(project, pipeline)
+ end
+
+ it 'shows the pipeline with a bridge job' do
+ expect(page).to have_selector('.pipeline-visualization')
+ expect(page).to have_content('cross-build')
+ end
+ end
+
+ describe 'GET /:project/pipelines/:id/builds' do
+ before do
+ visit builds_project_pipeline_path(project, pipeline)
+ end
+
+ it 'shows a bridge job on a list' do
+ expect(page).to have_content('cross-build')
+ expect(page).to have_content(bridge.id)
+ end
+ end
+ end
+
describe 'GET /:project/pipelines/:id/builds' do
include_context 'pipeline builds'
@@ -477,10 +520,11 @@ describe 'Pipeline', :js do
end
context 'when accessing failed jobs page' do
- it 'fails to access the page' do
- subject
+ it 'renders a 404 page' do
+ requests = inspect_requests { subject }
- expect(page).to have_title('Access Denied')
+ expect(page).to have_title('Not Found')
+ expect(requests.first.status_code).to eq(404)
end
end
end
@@ -622,7 +666,7 @@ describe 'Pipeline', :js do
let(:pipeline) do
create(:ci_pipeline,
- source: :merge_request,
+ source: :merge_request_event,
project: merge_request.source_project,
ref: 'feature',
sha: merge_request.diff_head_sha,
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 17772a35779..88d7c9ef8bd 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -109,8 +109,7 @@ describe 'Pipelines', :js do
context 'when pipeline is cancelable' do
let!(:build) do
create(:ci_build, pipeline: pipeline,
- stage: 'test',
- commands: 'test')
+ stage: 'test')
end
before do
@@ -140,8 +139,7 @@ describe 'Pipelines', :js do
context 'when pipeline is retryable' do
let!(:build) do
create(:ci_build, pipeline: pipeline,
- stage: 'test',
- commands: 'test')
+ stage: 'test')
end
before do
@@ -202,8 +200,7 @@ describe 'Pipelines', :js do
create(:ci_build, :manual,
pipeline: pipeline,
name: 'manual build',
- stage: 'test',
- commands: 'test')
+ stage: 'test')
end
before do
@@ -237,8 +234,7 @@ describe 'Pipelines', :js do
create(:ci_build, :scheduled,
pipeline: pipeline,
name: 'delayed job',
- stage: 'test',
- commands: 'test')
+ stage: 'test')
end
before do
@@ -262,8 +258,7 @@ describe 'Pipelines', :js do
create(:ci_build, :expired_scheduled,
pipeline: pipeline,
name: 'delayed job',
- stage: 'test',
- commands: 'test')
+ stage: 'test')
end
it "shows 00:00:00 as the remaining time" do
@@ -470,7 +465,7 @@ describe 'Pipelines', :js do
context 'with pagination' do
before do
allow(Ci::Pipeline).to receive(:default_per_page).and_return(1)
- create(:ci_empty_pipeline, project: project)
+ create(:ci_empty_pipeline, project: project)
end
it 'should render pagination' do
@@ -490,7 +485,7 @@ describe 'Pipelines', :js do
it 'should show updated content' do
visit project_pipelines_path(project)
wait_for_requests
- page.find('.js-next-button a').click
+ page.find('.js-next-button .page-link').click
expect(page).to have_selector('.gl-pagination .page', count: 2)
end
diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb
new file mode 100644
index 00000000000..317ffb6a2ff
--- /dev/null
+++ b/spec/features/projects/releases/user_views_releases_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+
+describe 'User views releases', :js do
+ let!(:project) { create(:project, :repository) }
+ let!(:release) { create(:release, project: project ) }
+ let!(:user) { create(:user) }
+
+ before do
+ project.add_maintainer(user)
+
+ gitlab_sign_in(user)
+ end
+
+ it 'sees the release' do
+ visit project_releases_path(project)
+
+ expect(page).to have_content(release.name)
+ expect(page).to have_content(release.tag)
+ end
+
+ context 'when there is a link as an asset' do
+ let!(:release_link) { create(:release_link, release: release, url: url ) }
+ let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
+
+ it 'sees the link' do
+ visit project_releases_path(project)
+
+ page.within('.js-assets-list') do
+ expect(page).to have_link release_link.name, href: release_link.url
+ expect(page).not_to have_content('(external source)')
+ end
+ end
+
+ context 'when url points to external resource' do
+ let(:url) { 'http://google.com/download' }
+
+ it 'sees that the link is external resource' do
+ visit project_releases_path(project)
+
+ page.within('.js-assets-list') do
+ expect(page).to have_content('(external source)')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/serverless/functions_spec.rb b/spec/features/projects/serverless/functions_spec.rb
index 766c63725b3..aa71669de98 100644
--- a/spec/features/projects/serverless/functions_spec.rb
+++ b/spec/features/projects/serverless/functions_spec.rb
@@ -1,6 +1,10 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Functions', :js do
+ include KubernetesHelpers
+
let(:project) { create(:project) }
let(:user) { create(:user) }
@@ -34,11 +38,14 @@ describe 'Functions', :js do
end
context 'when the user has a cluster and knative installed and visits the serverless page' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:service) { cluster.platform_kubernetes }
let(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) }
let(:project) { knative.cluster.project }
before do
+ stub_kubeclient_knative_services
+ stub_kubeclient_service_pods
visit project_serverless_functions_path(project)
end
diff --git a/spec/features/projects/services/disable_triggers_spec.rb b/spec/features/projects/services/disable_triggers_spec.rb
index 1a13fe03a67..65b597da269 100644
--- a/spec/features/projects/services/disable_triggers_spec.rb
+++ b/spec/features/projects/services/disable_triggers_spec.rb
@@ -14,10 +14,11 @@ describe 'Disable individual triggers' do
end
context 'service has multiple supported events' do
- let(:service_name) { 'HipChat' }
+ let(:service_name) { 'JIRA' }
it 'shows trigger checkboxes' do
- event_count = HipchatService.supported_events.count
+ event_count = JiraService.supported_events.count
+ expect(event_count).to be > 1
expect(page).to have_content "Trigger"
expect(page).to have_css(checkbox_selector, count: event_count)
diff --git a/spec/features/projects/services/user_activates_hipchat_spec.rb b/spec/features/projects/services/user_activates_hipchat_spec.rb
deleted file mode 100644
index 2f5313c91f9..00000000000
--- a/spec/features/projects/services/user_activates_hipchat_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-require 'spec_helper'
-
-describe 'User activates HipChat' do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
-
- visit(project_settings_integrations_path(project))
-
- click_link('HipChat')
- end
-
- context 'with standart settings' do
- it 'activates service' do
- check('Active')
- fill_in('Room', with: 'gitlab')
- fill_in('Token', with: 'verySecret')
- click_button('Save')
-
- expect(page).to have_content('HipChat activated.')
- end
- end
-
- context 'with custom settings' do
- it 'activates service' do
- check('Active')
- fill_in('Room', with: 'gitlab_custom')
- fill_in('Token', with: 'secretCustom')
- fill_in('Server', with: 'https://chat.example.com')
- click_button('Save')
-
- expect(page).to have_content('HipChat activated.')
- end
- end
-end
diff --git a/spec/features/projects/services/user_activates_issue_tracker_spec.rb b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
index 7cd5b12802b..74b9a2b20cd 100644
--- a/spec/features/projects/services/user_activates_issue_tracker_spec.rb
+++ b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
@@ -6,11 +6,17 @@ describe 'User activates issue tracker', :js do
let(:url) { 'http://tracker.example.com' }
- def fill_form(active = true)
+ def fill_short_form(active = true)
check 'Active' if active
fill_in 'service_project_url', with: url
fill_in 'service_issues_url', with: "#{url}/:id"
+ end
+
+ def fill_full_form(active = true)
+ fill_short_form(active)
+ check 'Active' if active
+
fill_in 'service_new_issue_url', with: url
end
@@ -21,14 +27,20 @@ describe 'User activates issue tracker', :js do
visit project_settings_integrations_path(project)
end
- shared_examples 'external issue tracker activation' do |tracker:|
+ shared_examples 'external issue tracker activation' do |tracker:, skip_new_issue_url: false|
describe 'user sets and activates the Service' do
context 'when the connection test succeeds' do
before do
stub_request(:head, url).to_return(headers: { 'Content-Type' => 'application/json' })
click_link(tracker)
- fill_form
+
+ if skip_new_issue_url
+ fill_short_form
+ else
+ fill_full_form
+ end
+
click_button('Test settings and save changes')
wait_for_requests
end
@@ -50,7 +62,13 @@ describe 'User activates issue tracker', :js do
stub_request(:head, url).to_raise(HTTParty::Error)
click_link(tracker)
- fill_form
+
+ if skip_new_issue_url
+ fill_short_form
+ else
+ fill_full_form
+ end
+
click_button('Test settings and save changes')
wait_for_requests
@@ -69,7 +87,13 @@ describe 'User activates issue tracker', :js do
describe 'user sets the service but keeps it disabled' do
before do
click_link(tracker)
- fill_form(false)
+
+ if skip_new_issue_url
+ fill_short_form(false)
+ else
+ fill_full_form(false)
+ end
+
click_button('Save changes')
end
@@ -87,6 +111,7 @@ describe 'User activates issue tracker', :js do
end
it_behaves_like 'external issue tracker activation', tracker: 'Redmine'
+ it_behaves_like 'external issue tracker activation', tracker: 'YouTrack', skip_new_issue_url: true
it_behaves_like 'external issue tracker activation', tracker: 'Bugzilla'
it_behaves_like 'external issue tracker activation', tracker: 'Custom Issue Tracker'
end
diff --git a/spec/features/projects/services/user_activates_youtrack_spec.rb b/spec/features/projects/services/user_activates_youtrack_spec.rb
new file mode 100644
index 00000000000..bb6a030c1cf
--- /dev/null
+++ b/spec/features/projects/services/user_activates_youtrack_spec.rb
@@ -0,0 +1,89 @@
+require 'spec_helper'
+
+describe 'User activates issue tracker', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+
+ let(:url) { 'http://tracker.example.com' }
+
+ def fill_form(active = true)
+ check 'Active' if active
+
+ fill_in 'service_project_url', with: url
+ fill_in 'service_issues_url', with: "#{url}/:id"
+ end
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+
+ visit project_settings_integrations_path(project)
+ end
+
+ shared_examples 'external issue tracker activation' do |tracker:|
+ describe 'user sets and activates the Service' do
+ context 'when the connection test succeeds' do
+ before do
+ stub_request(:head, url).to_return(headers: { 'Content-Type' => 'application/json' })
+
+ click_link(tracker)
+ fill_form
+ click_button('Test settings and save changes')
+ wait_for_requests
+ end
+
+ it 'activates the service' do
+ expect(page).to have_content("#{tracker} activated.")
+ expect(current_path).to eq(project_settings_integrations_path(project))
+ end
+
+ it 'shows the link in the menu' do
+ page.within('.nav-sidebar') do
+ expect(page).to have_link(tracker, href: url)
+ end
+ end
+ end
+
+ context 'when the connection test fails' do
+ it 'activates the service' do
+ stub_request(:head, url).to_raise(HTTParty::Error)
+
+ click_link(tracker)
+ fill_form
+ click_button('Test settings and save changes')
+ wait_for_requests
+
+ expect(find('.flash-container-page')).to have_content 'Test failed.'
+ expect(find('.flash-container-page')).to have_content 'Save anyway'
+
+ find('.flash-alert .flash-action').click
+ wait_for_requests
+
+ expect(page).to have_content("#{tracker} activated.")
+ expect(current_path).to eq(project_settings_integrations_path(project))
+ end
+ end
+ end
+
+ describe 'user sets the service but keeps it disabled' do
+ before do
+ click_link(tracker)
+ fill_form(false)
+ click_button('Save changes')
+ end
+
+ it 'saves but does not activate the service' do
+ expect(page).to have_content("#{tracker} settings saved, but not activated.")
+ expect(current_path).to eq(project_settings_integrations_path(project))
+ end
+
+ it 'does not show the external tracker link in the menu' do
+ page.within('.nav-sidebar') do
+ expect(page).not_to have_link(tracker, href: url)
+ end
+ end
+ end
+ end
+
+ it_behaves_like 'external issue tracker activation', tracker: 'YouTrack'
+end
diff --git a/spec/features/projects/services/user_views_services_spec.rb b/spec/features/projects/services/user_views_services_spec.rb
index e9c8cf0fe34..b0a838a7d2b 100644
--- a/spec/features/projects/services/user_views_services_spec.rb
+++ b/spec/features/projects/services/user_views_services_spec.rb
@@ -14,7 +14,6 @@ describe 'User views services' do
it 'shows the list of available services' do
expect(page).to have_content('Project services')
expect(page).to have_content('Campfire')
- expect(page).to have_content('HipChat')
expect(page).to have_content('Assembla')
expect(page).to have_content('Pushover')
expect(page).to have_content('Atlassian Bamboo')
@@ -22,5 +21,7 @@ describe 'User views services' do
expect(page).to have_content('Asana')
expect(page).to have_content('Irker (IRC gateway)')
expect(page).to have_content('Packagist')
+ expect(page).to have_content('Mattermost')
+ expect(page).to have_content('Slack')
end
end
diff --git a/spec/features/projects/settings/forked_project_settings_spec.rb b/spec/features/projects/settings/forked_project_settings_spec.rb
index df33d215602..dc0278370aa 100644
--- a/spec/features/projects/settings/forked_project_settings_spec.rb
+++ b/spec/features/projects/settings/forked_project_settings_spec.rb
@@ -7,6 +7,7 @@ describe 'Projects > Settings > For a forked project', :js do
let(:forked_project) { fork_project(original_project, user) }
before do
+ stub_feature_flags(approval_rules: false)
original_project.add_maintainer(user)
forked_project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/projects/settings/operations_settings_spec.rb b/spec/features/projects/settings/operations_settings_spec.rb
new file mode 100644
index 00000000000..af56cb0d4ee
--- /dev/null
+++ b/spec/features/projects/settings/operations_settings_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Projects > Settings > For a forked project', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:role) { :maintainer }
+
+ before do
+ sign_in(user)
+ project.add_role(user, role)
+ end
+
+ describe 'Sidebar > Operations' do
+ it 'renders the settings link in the sidebar' do
+ visit project_path(project)
+ wait_for_requests
+
+ expect(page).to have_selector('a[title="Operations"]', visible: false)
+ end
+ end
+
+ describe 'Settings > Operations' do
+ context 'error tracking settings form' do
+ let(:sentry_list_projects_url) { 'http://sentry.example.com/api/0/projects/' }
+
+ context 'success path' do
+ let(:projects_sample_response) do
+ Gitlab::Utils.deep_indifferent_access(
+ JSON.parse(fixture_file('sentry/list_projects_sample_response.json'))
+ )
+ end
+
+ before do
+ WebMock.stub_request(:get, sentry_list_projects_url)
+ .to_return(
+ status: 200,
+ headers: { 'Content-Type' => 'application/json' },
+ body: projects_sample_response.to_json
+ )
+ end
+
+ it 'successfully fills and submits the form' do
+ visit project_settings_operations_path(project)
+
+ wait_for_requests
+
+ expect(page).to have_content('Sentry API URL')
+ expect(page.body).to include('Error Tracking')
+ expect(page).to have_button('Connect')
+
+ check('Active')
+ fill_in('error-tracking-api-host', with: 'http://sentry.example.com')
+ fill_in('error-tracking-token', with: 'token')
+
+ click_button('Connect')
+
+ within('div#project-dropdown') do
+ click_button('Select project')
+ click_button('Sentry | Internal')
+ end
+
+ click_button('Save changes')
+
+ wait_for_requests
+
+ assert_text('Your changes have been saved')
+ end
+ end
+
+ context 'project dropdown fails to load' do
+ before do
+ WebMock.stub_request(:get, sentry_list_projects_url)
+ .to_return(
+ status: 400,
+ headers: { 'Content-Type' => 'application/json' },
+ body: {
+ message: 'Sentry response code: 401'
+ }.to_json
+ )
+ end
+
+ it 'displays error message' do
+ visit project_settings_operations_path(project)
+
+ wait_for_requests
+
+ check('Active')
+ fill_in('error-tracking-api-host', with: 'http://sentry.example.com')
+ fill_in('error-tracking-token', with: 'token')
+
+ click_button('Connect')
+
+ assert_text('Connection has failed. Re-check Auth Token and try again.')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb
index 6f8ec0015ad..4c85abe9971 100644
--- a/spec/features/projects/settings/pipelines_settings_spec.rb
+++ b/spec/features/projects/settings/pipelines_settings_spec.rb
@@ -98,14 +98,12 @@ describe "Projects > Settings > Pipelines settings" do
expect(page).not_to have_content('instance enabled')
expect(find_field('project_auto_devops_attributes_enabled')).not_to be_checked
check 'Default to Auto DevOps pipeline'
- fill_in('project_auto_devops_attributes_domain', with: 'test.com')
click_on 'Save changes'
end
expect(page.status_code).to eq(200)
expect(project.auto_devops).to be_present
expect(project.auto_devops).to be_enabled
- expect(project.auto_devops.domain).to eq('test.com')
page.within '#autodevops-settings' do
expect(find_field('project_auto_devops_attributes_enabled')).to be_checked
@@ -113,29 +111,6 @@ describe "Projects > Settings > Pipelines settings" do
end
end
end
-
- context 'when there is a cluster with ingress and external_ip' do
- before do
- cluster = create(:cluster, projects: [project])
- cluster.create_application_ingress!(external_ip: '192.168.1.100')
- end
-
- it 'shows the help text with the nip.io domain as an alternative to custom domain' do
- visit project_settings_ci_cd_path(project)
- expect(page).to have_content('192.168.1.100.nip.io can be used as an alternative to a custom domain')
- end
- end
-
- context 'when there is no ingress' do
- before do
- create(:cluster, projects: [project])
- end
-
- it 'alternative to custom domain is not shown' do
- visit project_settings_ci_cd_path(project)
- expect(page).not_to have_content('can be used as an alternative to a custom domain')
- end
- end
end
describe 'runners registration token' do
diff --git a/spec/features/projects/settings/project_settings_spec.rb b/spec/features/projects/settings/project_settings_spec.rb
new file mode 100644
index 00000000000..7afddc0e712
--- /dev/null
+++ b/spec/features/projects/settings/project_settings_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Projects settings' do
+ set(:project) { create(:project) }
+ let(:user) { project.owner }
+ let(:panel) { find('.general-settings', match: :first) }
+ let(:button) { panel.find('.btn.js-settings-toggle') }
+ let(:title) { panel.find('.settings-title') }
+
+ before do
+ sign_in(user)
+ visit edit_project_path(project)
+ end
+
+ it 'can toggle sections by clicking the title or button', :js do
+ expect_toggle_state(:expanded)
+
+ button.click
+
+ expect_toggle_state(:collapsed)
+
+ button.click
+
+ expect_toggle_state(:expanded)
+
+ title.click
+
+ expect_toggle_state(:collapsed)
+
+ title.click
+
+ expect_toggle_state(:expanded)
+ end
+
+ def expect_toggle_state(state)
+ is_collapsed = state == :collapsed
+
+ expect(button).to have_content(is_collapsed ? 'Expand' : 'Collapse')
+ expect(panel[:class]).send(is_collapsed ? 'not_to' : 'to', include('expanded'))
+ end
+end
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 1982136b89d..1259ad45791 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -54,7 +54,7 @@ describe 'Projects > Settings > Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
- find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click()
+ find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click
fill_in 'deploy_key_title', with: 'updated_deploy_key'
check 'deploy_key_deploy_keys_projects_attributes_0_can_push'
@@ -71,14 +71,14 @@ describe 'Projects > Settings > Repository settings' do
visit project_settings_repository_path(project)
- find('.js-deployKeys-tab-available_project_keys').click()
+ find('.js-deployKeys-tab-available_project_keys').click
- find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click()
+ find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click
fill_in 'deploy_key_title', with: 'updated_deploy_key'
click_button 'Save changes'
- find('.js-deployKeys-tab-available_project_keys').click()
+ find('.js-deployKeys-tab-available_project_keys').click
expect(page).to have_content('updated_deploy_key')
end
@@ -87,7 +87,7 @@ describe 'Projects > Settings > Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
- accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('.ic-remove').click() }
+ accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('.ic-remove').click }
expect(page).not_to have_content(private_deploy_key.title)
end
diff --git a/spec/features/projects/settings/user_changes_default_branch_spec.rb b/spec/features/projects/settings/user_changes_default_branch_spec.rb
index fcf05e04a5c..7dc18601f50 100644
--- a/spec/features/projects/settings/user_changes_default_branch_spec.rb
+++ b/spec/features/projects/settings/user_changes_default_branch_spec.rb
@@ -15,6 +15,9 @@ describe 'Projects > Settings > User changes default branch' do
let(:project) { create(:project, :repository, namespace: user.namespace) }
it 'allows to change the default branch', :js do
+ # Otherwise, running JS may overwrite our change to project_default_branch
+ wait_for_requests
+
select2('fix', from: '#project_default_branch')
page.within '#default-branch-settings' do
diff --git a/spec/features/projects/settings/user_manages_group_links_spec.rb b/spec/features/projects/settings/user_manages_group_links_spec.rb
index 676659b90c3..e5a58c44e41 100644
--- a/spec/features/projects/settings/user_manages_group_links_spec.rb
+++ b/spec/features/projects/settings/user_manages_group_links_spec.rb
@@ -10,6 +10,7 @@ describe 'Projects > Settings > User manages group links' do
before do
project.add_maintainer(user)
+ group_market.add_guest(user)
sign_in(user)
share_link = project.project_group_links.new(group_access: Gitlab::Access::MAINTAINER)
diff --git a/spec/features/projects/settings/user_tags_project_spec.rb b/spec/features/projects/settings/user_tags_project_spec.rb
index 9357215ae6f..e3f06c042b9 100644
--- a/spec/features/projects/settings/user_tags_project_spec.rb
+++ b/spec/features/projects/settings/user_tags_project_spec.rb
@@ -9,13 +9,13 @@ describe 'Projects > Settings > User tags a project' do
visit edit_project_path(project)
end
- it 'sets project tags' do
- fill_in 'Tags', with: 'tag1, tag2'
+ it 'sets project topics' do
+ fill_in 'Topics', with: 'topic1, topic2'
page.within '.general-settings' do
click_button 'Save changes'
end
- expect(find_field('Tags').value).to eq 'tag1, tag2'
+ expect(find_field('Topics').value).to eq 'topic1, topic2'
end
end
diff --git a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
index d82e350e0f7..9c1ef78b0ca 100644
--- a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
@@ -31,7 +31,7 @@ describe 'Projects > Snippets > User comments on a snippet', :js do
end
it 'should have zen mode' do
- find('.js-zen-enter').click()
+ find('.js-zen-enter').click
expect(page).to have_selector('.fullscreen')
end
end
diff --git a/spec/features/projects/tags/user_edits_tags_spec.rb b/spec/features/projects/tags/user_edits_tags_spec.rb
new file mode 100644
index 00000000000..ebb2844d17f
--- /dev/null
+++ b/spec/features/projects/tags/user_edits_tags_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Project > Tags', :js do
+ include DropzoneHelper
+
+ let(:user) { create(:user) }
+ let(:role) { :developer }
+ let(:project) { create(:project, :repository) }
+
+ before do
+ sign_in(user)
+ project.add_role(user, role)
+ end
+
+ describe 'when opening project tags' do
+ before do
+ visit project_tags_path(project)
+ end
+
+ context 'page with tags list' do
+ it 'shows tag name' do
+ page.within first('.tags > .content-list > li') do
+ expect(page.find('.row-main-content')).to have_content 'v1.1.0 Version 1.1.0'
+ end
+ end
+
+ it 'shows tag edit button' do
+ page.within first('.tags > .content-list > li') do
+ edit_btn = page.find('.row-fixed-content.controls a.btn-edit')
+
+ expect(edit_btn['href']).to have_content '/tags/v1.1.0/release/edit'
+ end
+ end
+ end
+
+ context 'edit tag release notes' do
+ before do
+ find('.tags > .content-list > li:first-child .row-fixed-content.controls a.btn-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.toolbar-btn: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 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/user_sees_sidebar_spec.rb b/spec/features/projects/user_sees_sidebar_spec.rb
index ee5734a9bf1..383e8824b7b 100644
--- a/spec/features/projects/user_sees_sidebar_spec.rb
+++ b/spec/features/projects/user_sees_sidebar_spec.rb
@@ -4,6 +4,108 @@ describe 'Projects > User sees sidebar' do
let(:user) { create(:user) }
let(:project) { create(:project, :private, public_builds: false, namespace: user.namespace) }
+ # NOTE: See documented behaviour https://design.gitlab.com/regions/navigation#contextual-navigation
+ context 'on different viewports', :js do
+ include MobileHelpers
+
+ before do
+ sign_in(user)
+ end
+
+ shared_examples 'has a expanded nav sidebar' do
+ it 'has a expanded desktop nav-sidebar on load' do
+ expect(page).to have_content('Collapse sidebar')
+ expect(page).not_to have_selector('.sidebar-collapsed-desktop')
+ expect(page).not_to have_selector('.sidebar-expanded-mobile')
+ end
+
+ it 'can collapse the nav-sidebar' do
+ page.find('.nav-sidebar .js-toggle-sidebar').click
+ expect(page).to have_selector('.sidebar-collapsed-desktop')
+ expect(page).not_to have_content('Collapse sidebar')
+ expect(page).not_to have_selector('.sidebar-expanded-mobile')
+ end
+ end
+
+ shared_examples 'has a collapsed nav sidebar' do
+ it 'has a collapsed desktop nav-sidebar on load' do
+ expect(page).not_to have_content('Collapse sidebar')
+ expect(page).not_to have_selector('.sidebar-expanded-mobile')
+ end
+
+ it 'can expand the nav-sidebar' do
+ page.find('.nav-sidebar .js-toggle-sidebar').click
+ expect(page).to have_selector('.sidebar-expanded-mobile')
+ expect(page).to have_content('Collapse sidebar')
+ end
+ end
+
+ shared_examples 'has a mobile nav-sidebar' do
+ it 'has a hidden nav-sidebar on load' do
+ expect(page).not_to have_content('.mobile-nav-open')
+ expect(page).not_to have_selector('.sidebar-expanded-mobile')
+ end
+
+ it 'can expand the nav-sidebar' do
+ page.find('.toggle-mobile-nav').click
+ expect(page).to have_selector('.mobile-nav-open')
+ expect(page).to have_selector('.sidebar-expanded-mobile')
+ end
+ end
+
+ context 'with a extra small viewport' do
+ before do
+ resize_screen_xs
+ visit project_path(project)
+ expect(page).to have_selector('.nav-sidebar')
+ expect(page).to have_selector('.toggle-mobile-nav')
+ end
+
+ it_behaves_like 'has a mobile nav-sidebar'
+ end
+
+ context 'with a small size viewport' do
+ before do
+ resize_screen_sm
+ visit project_path(project)
+ expect(page).to have_selector('.nav-sidebar')
+ expect(page).to have_selector('.toggle-mobile-nav')
+ end
+
+ it_behaves_like 'has a mobile nav-sidebar'
+ end
+
+ context 'with medium size viewport' do
+ before do
+ resize_window(768, 800)
+ visit project_path(project)
+ expect(page).to have_selector('.nav-sidebar')
+ end
+
+ it_behaves_like 'has a collapsed nav sidebar'
+ end
+
+ context 'with viewport size 1199px' do
+ before do
+ resize_window(1199, 800)
+ visit project_path(project)
+ expect(page).to have_selector('.nav-sidebar')
+ end
+
+ it_behaves_like 'has a collapsed nav sidebar'
+ end
+
+ context 'with a extra large viewport' do
+ before do
+ resize_window(1200, 800)
+ visit project_path(project)
+ expect(page).to have_selector('.nav-sidebar')
+ end
+
+ it_behaves_like 'has a expanded nav sidebar'
+ end
+ end
+
context 'as owner' do
before do
sign_in(user)
diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb
index f505023d1d0..49058d1372a 100644
--- a/spec/features/projects/wiki/markdown_preview_spec.rb
+++ b/spec/features/projects/wiki/markdown_preview_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
describe 'Projects > Wiki > User previews markdown changes', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' }) }
let(:wiki_content) do
<<-HEREDOC
[regular link](regular)
@@ -18,9 +19,7 @@ describe 'Projects > Wiki > User previews markdown changes', :js do
sign_in(user)
- visit project_path(project)
- find('.shortcuts-wiki').click
- click_link "Create your first page"
+ visit project_wiki_path(project, wiki_page)
end
context "while creating a new wiki page" do
@@ -171,24 +170,10 @@ describe 'Projects > Wiki > User previews markdown changes', :js do
fill_in :wiki_content, with: "1. one\n - sublist\n"
click_on "Preview"
- # the above generates two seperate lists (not embedded) in CommonMark
+ # the above generates two separate lists (not embedded) in CommonMark
expect(page).to have_content("sublist")
expect(page).not_to have_xpath("//ol//li//ul")
end
-
- it 'renders content with RedCarpet when legacy_render is set' do
- wiki_page = create(:wiki_page,
- wiki: project.wiki,
- attrs: { title: 'home', content: "Empty content" })
- visit(project_wiki_edit_path(project, wiki_page, legacy_render: 1))
-
- fill_in :wiki_content, with: "1. one\n - sublist\n"
- click_on "Preview"
-
- # the above generates a sublist list in RedCarpet
- expect(page).to have_content("sublist")
- expect(page).to have_xpath("//ol//li//ul")
- end
end
end
diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
index 48a0d675f2d..b1a7f167977 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -44,13 +44,7 @@ describe "User creates wiki page" do
end
it "shows non-escaped link in the pages list", :js do
- click_link("New page")
-
- page.within("#modal-new-wiki") do
- fill_in(:new_wiki_path, with: "one/two/three-test")
-
- click_on("Create page")
- end
+ fill_in(:wiki_title, with: "one/two/three-test")
page.within(".wiki-form") do
fill_in(:wiki_content, with: "wiki content")
diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
index f76e577b0d6..dbf8af3e5bb 100644
--- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
@@ -26,12 +26,7 @@ describe 'User updates wiki page' do
end
it 'updates a page that has a path', :js do
- click_on('New page')
-
- page.within('#modal-new-wiki') do
- fill_in(:new_wiki_path, with: 'one/two/three-test')
- click_on('Create page')
- end
+ fill_in(:wiki_title, with: 'one/two/three-test')
page.within '.wiki-form' do
fill_in(:wiki_content, with: 'wiki content')
diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
index d4691b669c1..6e28ec0d7b2 100644
--- a/spec/features/projects/wiki/user_views_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
@@ -22,12 +22,7 @@ describe 'User views a wiki page' do
visit(project_wikis_path(project))
click_link "Create your first page"
- click_on('New page')
-
- page.within('#modal-new-wiki') do
- fill_in(:new_wiki_path, with: 'one/two/three-test')
- click_on('Create page')
- end
+ fill_in(:wiki_title, with: 'one/two/three-test')
page.within('.wiki-form') do
fill_in(:wiki_content, with: 'wiki content')
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index b56bb272b46..dbf0d427976 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -4,8 +4,12 @@ describe 'Project' do
include ProjectForksHelper
include MobileHelpers
+ before do
+ stub_feature_flags(approval_rules: false)
+ end
+
describe 'creating from template' do
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
let(:template) { Gitlab::ProjectTemplate.find(:rails) }
before do
@@ -55,30 +59,30 @@ describe 'Project' do
it 'parses Markdown' do
project.update_attribute(:description, 'This is **my** project')
visit path
- expect(page).to have_css('.project-description > .project-description-markdown > p > strong')
+ expect(page).to have_css('.home-panel-description > .home-panel-description-markdown > p > strong')
end
it 'passes through html-pipeline' do
project.update_attribute(:description, 'This project is the :poop:')
visit path
- expect(page).to have_css('.project-description > .project-description-markdown > p > gl-emoji')
+ expect(page).to have_css('.home-panel-description > .home-panel-description-markdown > p > gl-emoji')
end
it 'sanitizes unwanted tags' do
project.update_attribute(:description, "```\ncode\n```")
visit path
- expect(page).not_to have_css('.project-description code')
+ expect(page).not_to have_css('.home-panel-description code')
end
it 'permits `rel` attribute on links' do
project.update_attribute(:description, 'https://google.com/')
visit path
- expect(page).to have_css('.project-description a[rel]')
+ expect(page).to have_css('.home-panel-description a[rel]')
end
context 'read more', :js do
let(:read_more_selector) { '.read-more-container' }
- let(:read_more_trigger_selector) { '.project-home-desc .js-read-more-trigger' }
+ let(:read_more_trigger_selector) { '.home-panel-home-desc .js-read-more-trigger' }
it 'does not display "read more" link on desktop breakpoint' do
project.update_attribute(:description, 'This is **my** project')
@@ -94,11 +98,42 @@ describe 'Project' do
find(read_more_trigger_selector).click
- expect(page).to have_css('.project-description .is-expanded')
+ expect(page).to have_css('.home-panel-description .is-expanded')
end
end
end
+ describe 'project topics' do
+ let(:project) { create(:project, :repository) }
+ let(:path) { project_path(project) }
+
+ before do
+ sign_in(create(:admin))
+ visit path
+ end
+
+ it 'shows project topics' do
+ project.update_attribute(:tag_list, 'topic1')
+
+ visit path
+
+ expect(page).to have_css('.home-panel-topic-list')
+ expect(page).to have_link('Topic1', href: explore_projects_path(tag: 'topic1'))
+ end
+
+ it 'shows up to 3 project tags' do
+ project.update_attribute(:tag_list, 'topic1, topic2, topic3, topic4')
+
+ visit path
+
+ expect(page).to have_css('.home-panel-topic-list')
+ expect(page).to have_link('Topic1', href: explore_projects_path(tag: 'topic1'))
+ expect(page).to have_link('Topic2', href: explore_projects_path(tag: 'topic2'))
+ expect(page).to have_link('Topic3', href: explore_projects_path(tag: 'topic3'))
+ expect(page).to have_content('+ 1 more')
+ end
+ end
+
describe 'copy clone URL to clipboard', :js do
let(:project) { create(:project, :repository) }
let(:path) { project_path(project) }
@@ -146,7 +181,7 @@ describe 'Project' do
describe 'showing information about source of a project fork' do
let(:user) { create(:user) }
- let(:base_project) { create(:project, :public, :repository) }
+ let(:base_project) { create(:project, :public, :repository) }
let(:forked_project) { fork_project(base_project, user, repository: true) }
before do
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index 63c38a25f4b..0aff916ec83 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -97,7 +97,7 @@ describe 'Protected Branches', :js do
set_protected_branch_name('some-branch')
click_on "Protect"
- within(".protected-branches-list") { expect(page).to have_content('branch was removed') }
+ within(".protected-branches-list") { expect(page).to have_content('branch was deleted') }
end
end
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index cb7a912946c..6eae0be4b9f 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -236,7 +236,7 @@ describe 'Runners' do
it 'group runners are available' do
visit project_runners_path(project)
- expect(page).to have_content 'Available group Runners : 1'
+ expect(page).to have_content 'Available group Runners: 1'
expect(page).to have_content 'group-runner'
end
@@ -259,8 +259,9 @@ describe 'Runners' do
context 'group runners in group settings' do
let(:group) { create(:group) }
+
before do
- group.add_maintainer(user)
+ group.add_owner(user)
end
context 'group with no runners' do
@@ -278,7 +279,7 @@ describe 'Runners' do
visit group_settings_ci_cd_path(group)
expect(page).not_to have_content 'This group does not provide any group Runners yet'
- expect(page).to have_content 'Available group Runners : 1'
+ expect(page).to have_content 'Available group Runners: 1'
expect(page).to have_content 'group-runner'
end
diff --git a/spec/features/security/admin_access_spec.rb b/spec/features/security/admin_access_spec.rb
index 3ca1303bda6..ff679034a36 100644
--- a/spec/features/security/admin_access_spec.rb
+++ b/spec/features/security/admin_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Admin::Projects" do
+describe "Admin::Projects" do
include AccessMatchers
describe "GET /admin/projects" do
diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb
index 0c893e65d9c..07cddc92ac4 100644
--- a/spec/features/security/dashboard_access_spec.rb
+++ b/spec/features/security/dashboard_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Dashboard access" do
+describe "Dashboard access" do
include AccessMatchers
describe "GET /dashboard" do
diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb
index 4705cd12d23..3238e07fe15 100644
--- a/spec/features/security/group/private_access_spec.rb
+++ b/spec/features/security/group/private_access_spec.rb
@@ -27,7 +27,7 @@ describe 'Private Group access' do
it { is_expected.to be_allowed_for(:developer).of(group) }
it { is_expected.to be_allowed_for(:reporter).of(group) }
it { is_expected.to be_allowed_for(:guest).of(group) }
- it { is_expected.to be_allowed_for(project_guest) }
+ it { is_expected.to be_denied_for(project_guest) }
it { is_expected.to be_denied_for(:user) }
it { is_expected.to be_denied_for(:external) }
it { is_expected.to be_denied_for(:visitor) }
@@ -42,7 +42,7 @@ describe 'Private Group access' do
it { is_expected.to be_allowed_for(:developer).of(group) }
it { is_expected.to be_allowed_for(:reporter).of(group) }
it { is_expected.to be_allowed_for(:guest).of(group) }
- it { is_expected.to be_allowed_for(project_guest) }
+ it { is_expected.to be_denied_for(project_guest) }
it { is_expected.to be_denied_for(:user) }
it { is_expected.to be_denied_for(:external) }
it { is_expected.to be_denied_for(:visitor) }
@@ -58,7 +58,7 @@ describe 'Private Group access' do
it { is_expected.to be_allowed_for(:developer).of(group) }
it { is_expected.to be_allowed_for(:reporter).of(group) }
it { is_expected.to be_allowed_for(:guest).of(group) }
- it { is_expected.to be_allowed_for(project_guest) }
+ it { is_expected.to be_denied_for(project_guest) }
it { is_expected.to be_denied_for(:user) }
it { is_expected.to be_denied_for(:external) }
it { is_expected.to be_denied_for(:visitor) }
@@ -73,7 +73,7 @@ describe 'Private Group access' do
it { is_expected.to be_allowed_for(:developer).of(group) }
it { is_expected.to be_allowed_for(:reporter).of(group) }
it { is_expected.to be_allowed_for(:guest).of(group) }
- it { is_expected.to be_allowed_for(project_guest) }
+ it { is_expected.to be_denied_for(project_guest) }
it { is_expected.to be_denied_for(:user) }
it { is_expected.to be_denied_for(:external) }
it { is_expected.to be_denied_for(:visitor) }
@@ -93,4 +93,28 @@ describe 'Private Group access' do
it { is_expected.to be_denied_for(:visitor) }
it { is_expected.to be_denied_for(:external) }
end
+
+ describe 'GET /groups/:path for shared projects' do
+ let(:project) { create(:project, :public) }
+ before do
+ Projects::GroupLinks::CreateService.new(
+ project,
+ create(:user),
+ link_group_access: ProjectGroupLink::DEVELOPER
+ ).execute(group)
+ end
+
+ subject { group_path(group) }
+
+ it { is_expected.to be_allowed_for(:admin) }
+ it { is_expected.to be_allowed_for(:owner).of(group) }
+ it { is_expected.to be_allowed_for(:maintainer).of(group) }
+ it { is_expected.to be_allowed_for(:developer).of(group) }
+ it { is_expected.to be_allowed_for(:reporter).of(group) }
+ it { is_expected.to be_allowed_for(:guest).of(group) }
+ it { is_expected.to be_denied_for(project_guest) }
+ it { is_expected.to be_denied_for(:user) }
+ it { is_expected.to be_denied_for(:external) }
+ it { is_expected.to be_denied_for(:visitor) }
+ end
end
diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb
index 41eb7b26578..a198e65046f 100644
--- a/spec/features/security/profile_access_spec.rb
+++ b/spec/features/security/profile_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Profile access" do
+describe "Profile access" do
include AccessMatchers
describe "GET /profile/keys" do
diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb
index 001e6c10eb2..e23000fa676 100644
--- a/spec/features/security/project/internal_access_spec.rb
+++ b/spec/features/security/project/internal_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Internal Project Access" do
+describe "Internal Project Access" do
include AccessMatchers
set(:project) { create(:project, :internal, :repository) }
@@ -452,9 +452,9 @@ describe "Internal Project Access" do
it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:maintainer).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) }
- it { is_expected.to be_allowed_for(:reporter).of(project) }
- it { is_expected.to be_allowed_for(:guest).of(project) }
- it { is_expected.to be_allowed_for(:user) }
+ it { is_expected.to be_denied_for(:reporter).of(project) }
+ it { is_expected.to be_denied_for(:guest).of(project) }
+ it { is_expected.to be_denied_for(:user) }
it { is_expected.to be_denied_for(:external) }
it { is_expected.to be_denied_for(:visitor) }
end
diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb
index c6618355eea..f380bc122a7 100644
--- a/spec/features/security/project/private_access_spec.rb
+++ b/spec/features/security/project/private_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Private Project Access" do
+describe "Private Project Access" do
include AccessMatchers
set(:project) { create(:project, :private, :repository, public_builds: false) }
@@ -485,7 +485,7 @@ describe "Private Project Access" do
it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:maintainer).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) }
- it { is_expected.to be_allowed_for(:reporter).of(project) }
+ it { is_expected.to be_denied_for(:reporter).of(project) }
it { is_expected.to be_denied_for(:guest).of(project) }
it { is_expected.to be_denied_for(:user) }
it { is_expected.to be_denied_for(:external) }
diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb
index 3717dc13f1e..57d56371719 100644
--- a/spec/features/security/project/public_access_spec.rb
+++ b/spec/features/security/project/public_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Public Project Access" do
+describe "Public Project Access" do
include AccessMatchers
set(:project) { create(:project, :public, :repository) }
@@ -272,11 +272,11 @@ describe "Public Project Access" do
it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:maintainer).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) }
- it { is_expected.to be_allowed_for(:reporter).of(project) }
- it { is_expected.to be_allowed_for(:guest).of(project) }
- it { is_expected.to be_allowed_for(:user) }
- it { is_expected.to be_allowed_for(:external) }
- it { is_expected.to be_allowed_for(:visitor) }
+ it { is_expected.to be_denied_for(:reporter).of(project) }
+ it { is_expected.to be_denied_for(:guest).of(project) }
+ it { is_expected.to be_denied_for(:user) }
+ it { is_expected.to be_denied_for(:external) }
+ it { is_expected.to be_denied_for(:visitor) }
end
describe "GET /:project_path/environments" do
diff --git a/spec/features/security/project/snippet/internal_access_spec.rb b/spec/features/security/project/snippet/internal_access_spec.rb
index b87eb86b88b..0c58fdf2f12 100644
--- a/spec/features/security/project/snippet/internal_access_spec.rb
+++ b/spec/features/security/project/snippet/internal_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Internal Project Snippets Access" do
+describe "Internal Project Snippets Access" do
include AccessMatchers
let(:project) { create(:project, :internal) }
diff --git a/spec/features/security/project/snippet/private_access_spec.rb b/spec/features/security/project/snippet/private_access_spec.rb
index ead91d9a5fa..420f1938763 100644
--- a/spec/features/security/project/snippet/private_access_spec.rb
+++ b/spec/features/security/project/snippet/private_access_spec.rb
@@ -1,11 +1,11 @@
require 'spec_helper'
-describe "Private Project Snippets Access" do
+describe "Private Project Snippets Access" do
include AccessMatchers
let(:project) { create(:project, :private) }
- let(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) }
+ let(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) }
describe "GET /:project_path/snippets" do
subject { project_snippets_path(project) }
diff --git a/spec/features/security/project/snippet/public_access_spec.rb b/spec/features/security/project/snippet/public_access_spec.rb
index 9bab3a474b8..6c75902c6e9 100644
--- a/spec/features/security/project/snippet/public_access_spec.rb
+++ b/spec/features/security/project/snippet/public_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Public Project Snippets Access" do
+describe "Public Project Snippets Access" do
include AccessMatchers
let(:project) { create(:project, :public) }
diff --git a/spec/features/snippets/show_spec.rb b/spec/features/snippets/show_spec.rb
index 367a479f62a..74fdfcf492e 100644
--- a/spec/features/snippets/show_spec.rb
+++ b/spec/features/snippets/show_spec.rb
@@ -79,35 +79,6 @@ describe 'Snippet', :js do
expect(page).not_to have_xpath("//ol//li//ul")
end
end
-
- context 'when rendering legacy markdown' do
- before do
- visit snippet_path(snippet, legacy_render: 1)
-
- wait_for_requests
- end
-
- it 'renders using RedCarpet' do
- expect(page).to have_content("sublist")
- expect(page).to have_xpath("//ol//li//ul")
- end
- end
-
- context 'with cached CommonMark html' do
- let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content, cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION) }
-
- it 'renders correctly' do
- expect(page).not_to have_xpath("//ol//li//ul")
- end
- end
-
- context 'with cached Redcarpet html' do
- let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content, cached_markdown_version: CacheMarkdownField::CACHE_REDCARPET_VERSION) }
-
- it 'renders correctly' do
- expect(page).to have_xpath("//ol//li//ul")
- end
- end
end
context 'switching to the simple viewer' do
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index 9c9127980a1..6fe840dccf6 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -36,19 +36,6 @@ describe 'Task Lists' do
MARKDOWN
end
- let(:nested_tasks_markdown_redcarpet) do
- <<-EOT.strip_heredoc
- - [ ] Task a
- - [x] Task a.1
- - [ ] Task a.2
- - [ ] Task b
-
- 1. [ ] Task 1
- 1. [ ] Task 1.1
- 1. [x] Task 1.2
- EOT
- end
-
let(:nested_tasks_markdown) do
<<-EOT.strip_heredoc
- [ ] Task a
@@ -153,59 +140,6 @@ describe 'Task Lists' do
expect(page).to have_content("1 of 1 task completed")
end
end
-
- shared_examples 'shared nested tasks' do
- before do
- allow(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('Redcarpet')
- visit_issue(project, issue)
- end
- it 'renders' do
- expect(page).to have_selector('ul.task-list', count: 2)
- expect(page).to have_selector('li.task-list-item', count: 7)
- expect(page).to have_selector('ul input[checked]', count: 1)
- expect(page).to have_selector('ol input[checked]', count: 1)
- end
-
- it 'solves tasks' do
- expect(page).to have_content("2 of 7 tasks completed")
-
- page.find('li.task-list-item', text: 'Task b').find('input').click
- page.find('li.task-list-item ul li.task-list-item', text: 'Task a.2').find('input').click
- page.find('li.task-list-item ol li.task-list-item', text: 'Task 1.1').find('input').click
-
- expect(page).to have_content("5 of 7 tasks completed")
-
- visit_issue(project, issue) # reload to see new system notes
-
- expect(page).to have_content('marked the task Task b as complete')
- expect(page).to have_content('marked the task Task a.2 as complete')
- expect(page).to have_content('marked the task Task 1.1 as complete')
- end
- end
-
- describe 'nested tasks', :js do
- context 'with Redcarpet' do
- let(:issue) { create(:issue, description: nested_tasks_markdown_redcarpet, author: user, project: project) }
-
- before do
- allow_any_instance_of(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('Redcarpet')
- visit_issue(project, issue)
- end
-
- it_behaves_like 'shared nested tasks'
- end
-
- context 'with CommonMark' do
- let(:issue) { create(:issue, description: nested_tasks_markdown, author: user, project: project) }
-
- before do
- allow_any_instance_of(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('CommonMark')
- visit_issue(project, issue)
- end
-
- it_behaves_like 'shared nested tasks'
- end
- end
end
describe 'for Notes' do
diff --git a/spec/features/users/overview_spec.rb b/spec/features/users/overview_spec.rb
index 873de85708a..3db9ae7a951 100644
--- a/spec/features/users/overview_spec.rb
+++ b/spec/features/users/overview_spec.rb
@@ -33,6 +33,8 @@ describe 'Overview tab on a user profile', :js do
it 'does not show any entries in the list of activities' do
page.within('.activities-block') do
+ expect(page).to have_selector('.loading', visible: false)
+ expect(page).to have_content('Join or create a group to start contributing by commenting on issues or submitting merge requests!')
expect(page).not_to have_selector('.event-item')
end
end
@@ -93,7 +95,8 @@ describe 'Overview tab on a user profile', :js do
it 'it shows an empty project list with an info message' do
page.within('.projects-block') do
- expect(page).to have_content('No projects found')
+ expect(page).to have_selector('.loading', visible: false)
+ expect(page).to have_content('You haven\'t created any personal projects.')
expect(page).not_to have_selector('.project-row')
end
end
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index bfe11ddf673..957c3cfc583 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -49,6 +49,34 @@ describe 'Signup' do
expect(page).to have_content("Please create a username with only alphanumeric characters.")
end
+
+ it 'shows an error border if the username contains emojis' do
+ simulate_input('#new_user_username', 'ehsan😀')
+
+ expect(find('.username')).to have_css '.gl-field-error-outline'
+ end
+
+ it 'shows an error message if the username contains emojis' do
+ simulate_input('#new_user_username', 'ehsan😀')
+
+ expect(page).to have_content("Invalid input, please avoid emojis")
+ end
+ end
+
+ describe 'user\'s full name validation', :js do
+ before do
+ visit root_path
+ click_link 'Register'
+ simulate_input('#new_user_name', 'Ehsan 🦋')
+ end
+
+ it 'shows an error border if the user\'s fullname contains an emoji' do
+ expect(find('.name')).to have_css '.gl-field-error-outline'
+ end
+
+ it 'shows an error message if the username contains emojis' do
+ expect(page).to have_content("Invalid input, please avoid emojis")
+ end
end
context 'with no errors' do
diff --git a/spec/features/users/terms_spec.rb b/spec/features/users/terms_spec.rb
index 5b2e7605c4d..84df1016594 100644
--- a/spec/features/users/terms_spec.rb
+++ b/spec/features/users/terms_spec.rb
@@ -76,7 +76,7 @@ describe 'Users > Terms' do
project.add_developer(user)
end
- it 'redirects to terms and back to where the user was going' do
+ it 'redirects to terms and back to where the user was going' do
visit project_path(project)
enforce_terms
diff --git a/spec/finders/admin/runners_finder_spec.rb b/spec/finders/admin/runners_finder_spec.rb
index 0b2325cc7ca..94ccb398801 100644
--- a/spec/finders/admin/runners_finder_spec.rb
+++ b/spec/finders/admin/runners_finder_spec.rb
@@ -37,6 +37,14 @@ describe Admin::RunnersFinder do
end
end
+ context 'filter by tag_name' do
+ it 'calls the corresponding scope on Ci::Runner' do
+ expect(Ci::Runner).to receive(:tagged_with).with(%w[tag1 tag2]).and_call_original
+
+ described_class.new(params: { tag_name: %w[tag1 tag2] }).execute
+ end
+ end
+
context 'sort' do
context 'without sort param' do
it 'sorts by created_at' do
diff --git a/spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb b/spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb
new file mode 100644
index 00000000000..79d2f9cdb45
--- /dev/null
+++ b/spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Autocomplete::ActsAsTaggableOn::TagsFinder do
+ describe '#execute' do
+ context 'with empty params' do
+ it 'returns all tags' do
+ tag1 = ActsAsTaggableOn::Tag.create!(name: 'tag1')
+ tag2 = ActsAsTaggableOn::Tag.create!(name: 'tag2')
+
+ tags = described_class.new(params: {}).execute
+
+ expect(tags).to match_array [tag1, tag2]
+ end
+ end
+
+ context 'filter by search' do
+ context 'with an empty search term' do
+ it 'returns an empty collection' do
+ ActsAsTaggableOn::Tag.create!(name: 'tag1')
+ ActsAsTaggableOn::Tag.create!(name: 'tag2')
+
+ tags = described_class.new(params: { search: '' }).execute
+
+ expect(tags).to be_empty
+ end
+ end
+
+ context 'with a search containing 2 characters' do
+ it 'returns the tag that strictly matches the search term' do
+ tag1 = ActsAsTaggableOn::Tag.create!(name: 't1')
+ ActsAsTaggableOn::Tag.create!(name: 't11')
+
+ tags = described_class.new(params: { search: 't1' }).execute
+
+ expect(tags).to match_array [tag1]
+ end
+ end
+
+ context 'with a search containing 3 characters' do
+ it 'returns the tag that partially matches the search term' do
+ tag1 = ActsAsTaggableOn::Tag.create!(name: 'tag1')
+ tag2 = ActsAsTaggableOn::Tag.create!(name: 'tag11')
+
+ tags = described_class.new(params: { search: 'ag1' }).execute
+
+ expect(tags).to match_array [tag1, tag2]
+ end
+ end
+ end
+
+ context 'limit' do
+ it 'limits the result set by the limit constant' do
+ stub_const("#{described_class}::LIMIT", 1)
+
+ ActsAsTaggableOn::Tag.create!(name: 'tag1')
+ ActsAsTaggableOn::Tag.create!(name: 'tag2')
+
+ tags = described_class.new(params: { search: 'tag' }).execute
+
+ expect(tags.count).to eq 1
+ end
+ end
+ end
+end
diff --git a/spec/finders/concerns/finder_methods_spec.rb b/spec/finders/concerns/finder_methods_spec.rb
index a4ad331f613..e074e53c2c5 100644
--- a/spec/finders/concerns/finder_methods_spec.rb
+++ b/spec/finders/concerns/finder_methods_spec.rb
@@ -12,7 +12,7 @@ describe FinderMethods do
end
def execute
- Project.all
+ Project.all.order(id: :desc)
end
end
end
@@ -38,6 +38,16 @@ describe FinderMethods do
it 'raises not found the user does not have access' do
expect { finder.find_by!(id: unauthorized_project.id) }.to raise_error(ActiveRecord::RecordNotFound)
end
+
+ it 'ignores ordering' do
+ # Memoise the finder result so we can add message expectations to it
+ relation = finder.execute
+ allow(finder).to receive(:execute).and_return(relation)
+
+ expect(relation).to receive(:reorder).with(nil).and_call_original
+
+ finder.find_by!(id: authorized_project.id)
+ end
end
describe '#find' do
@@ -66,5 +76,15 @@ describe FinderMethods do
it 'returns nil when the user does not have access' do
expect(finder.find_by(id: unauthorized_project.id)).to be_nil
end
+
+ it 'ignores ordering' do
+ # Memoise the finder result so we can add message expectations to it
+ relation = finder.execute
+ allow(finder).to receive(:execute).and_return(relation)
+
+ expect(relation).to receive(:reorder).with(nil).and_call_original
+
+ finder.find_by(id: authorized_project.id)
+ end
end
end
diff --git a/spec/finders/contributed_projects_finder_spec.rb b/spec/finders/contributed_projects_finder_spec.rb
index 81fb4e3561c..ee84fd067d4 100644
--- a/spec/finders/contributed_projects_finder_spec.rb
+++ b/spec/finders/contributed_projects_finder_spec.rb
@@ -31,4 +31,16 @@ describe ContributedProjectsFinder do
it { is_expected.to match_array([private_project, internal_project, public_project]) }
end
+
+ context 'user with private profile' do
+ it 'does not return contributed projects' do
+ private_user = create(:user, private_profile: true)
+ public_project.add_maintainer(private_user)
+ create(:push_event, project: public_project, author: private_user)
+
+ projects = described_class.new(private_user).execute(current_user)
+
+ expect(projects).to be_empty
+ end
+ end
end
diff --git a/spec/finders/groups_finder_spec.rb b/spec/finders/groups_finder_spec.rb
index 16c0d418d98..367ca43bdfe 100644
--- a/spec/finders/groups_finder_spec.rb
+++ b/spec/finders/groups_finder_spec.rb
@@ -8,22 +8,22 @@ describe GroupsFinder do
using RSpec::Parameterized::TableSyntax
where(:user_type, :params, :results) do
- nil | { all_available: true } | %i(public_group user_public_group)
- nil | { all_available: false } | %i(public_group user_public_group)
+ nil | { all_available: true } | %i(public_group user_public_group)
+ nil | { all_available: false } | %i(public_group user_public_group)
nil | {} | %i(public_group user_public_group)
- :regular | { all_available: true } | %i(public_group internal_group user_public_group user_internal_group
- user_private_group)
- :regular | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
+ :regular | { all_available: true } | %i(public_group internal_group user_public_group user_internal_group
+ user_private_group)
+ :regular | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
:regular | {} | %i(public_group internal_group user_public_group user_internal_group user_private_group)
- :external | { all_available: true } | %i(public_group user_public_group user_internal_group user_private_group)
- :external | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
+ :external | { all_available: true } | %i(public_group user_public_group user_internal_group user_private_group)
+ :external | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
:external | {} | %i(public_group user_public_group user_internal_group user_private_group)
- :admin | { all_available: true } | %i(public_group internal_group private_group user_public_group
- user_internal_group user_private_group)
- :admin | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
+ :admin | { all_available: true } | %i(public_group internal_group private_group user_public_group
+ user_internal_group user_private_group)
+ :admin | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
:admin | {} | %i(public_group internal_group private_group user_public_group user_internal_group
user_private_group)
end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 80f7232f282..55efab7dec3 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -174,9 +174,13 @@ describe IssuesFinder do
context 'filtering by upcoming milestone' do
let(:params) { { milestone_title: Milestone::Upcoming.name } }
+ let!(:group) { create(:group, :public) }
+ let!(:group_member) { create(:group_member, group: group, user: user) }
+
let(:project_no_upcoming_milestones) { create(:project, :public) }
let(:project_next_1_1) { create(:project, :public) }
let(:project_next_8_8) { create(:project, :public) }
+ let(:project_in_group) { create(:project, :public, namespace: group) }
let(:yesterday) { Date.today - 1.day }
let(:tomorrow) { Date.today + 1.day }
@@ -187,21 +191,22 @@ describe IssuesFinder do
[
create(:milestone, :closed, project: project_no_upcoming_milestones),
create(:milestone, project: project_next_1_1, title: '1.1', due_date: two_days_from_now),
- create(:milestone, project: project_next_1_1, title: '8.8', due_date: ten_days_from_now),
- create(:milestone, project: project_next_8_8, title: '1.1', due_date: yesterday),
- create(:milestone, project: project_next_8_8, title: '8.8', due_date: tomorrow)
+ create(:milestone, project: project_next_1_1, title: '8.9', due_date: ten_days_from_now),
+ create(:milestone, project: project_next_8_8, title: '1.2', due_date: yesterday),
+ create(:milestone, project: project_next_8_8, title: '8.8', due_date: tomorrow),
+ create(:milestone, group: group, title: '9.9', due_date: tomorrow)
]
end
before do
milestones.each do |milestone|
- create(:issue, project: milestone.project, milestone: milestone, author: user, assignees: [user])
+ create(:issue, project: milestone.project || project_in_group, milestone: milestone, author: user, assignees: [user])
end
end
- it 'returns issues in the upcoming milestone for each project' do
- expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.1', '8.8')
- expect(issues.map { |issue| issue.milestone.due_date }).to contain_exactly(tomorrow, two_days_from_now)
+ it 'returns issues in the upcoming milestone for each project or group' do
+ expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.1', '8.8', '9.9')
+ expect(issues.map { |issue| issue.milestone.due_date }).to contain_exactly(tomorrow, two_days_from_now, tomorrow)
end
end
@@ -309,6 +314,14 @@ describe IssuesFinder do
end
end
+ context 'filtering by issue term in title' do
+ let(:params) { { search: 'git', in: 'title' } }
+
+ it 'returns issues with title match for search term' do
+ expect(issues).to contain_exactly(issue1)
+ end
+ end
+
context 'filtering by issues iids' do
let(:params) { { iids: issue3.iid } }
@@ -403,6 +416,36 @@ describe IssuesFinder do
end
end
+ context 'filtering by closed_at' do
+ let!(:closed_issue1) { create(:issue, project: project1, state: :closed, closed_at: 1.week.ago) }
+ let!(:closed_issue2) { create(:issue, project: project2, state: :closed, closed_at: 1.week.from_now) }
+ let!(:closed_issue3) { create(:issue, project: project2, state: :closed, closed_at: 2.weeks.from_now) }
+
+ context 'through closed_after' do
+ let(:params) { { state: :closed, closed_after: closed_issue3.closed_at } }
+
+ it 'returns issues closed on or after the given date' do
+ expect(issues).to contain_exactly(closed_issue3)
+ end
+ end
+
+ context 'through closed_before' do
+ let(:params) { { state: :closed, closed_before: closed_issue1.closed_at } }
+
+ it 'returns issues closed on or before the given date' do
+ expect(issues).to contain_exactly(closed_issue1)
+ end
+ end
+
+ context 'through closed_after and closed_before' do
+ let(:params) { { state: :closed, closed_after: closed_issue2.closed_at, closed_before: closed_issue3.closed_at } }
+
+ it 'returns issues closed between the given dates' do
+ expect(issues).to contain_exactly(closed_issue2, closed_issue3)
+ end
+ end
+ end
+
context 'filtering by reaction name' do
context 'user searches by no reaction' do
let(:params) { { my_reaction_emoji: 'None' } }
@@ -447,6 +490,32 @@ describe IssuesFinder do
end
end
+ context 'filtering by confidential' do
+ set(:confidential_issue) { create(:issue, project: project1, confidential: true) }
+
+ context 'no filtering' do
+ it 'returns all issues' do
+ expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, confidential_issue)
+ end
+ end
+
+ context 'user filters confidential issues' do
+ let(:params) { { confidential: true } }
+
+ it 'returns only confdential issues' do
+ expect(issues).to contain_exactly(confidential_issue)
+ end
+ end
+
+ context 'user filters only public issues' do
+ let(:params) { { confidential: false } }
+
+ it 'returns only confdential issues' do
+ expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
+ end
+ end
+ end
+
context 'when the user is unauthorized' do
let(:search_user) { nil }
@@ -513,7 +582,7 @@ describe IssuesFinder do
it 'returns the number of rows for the default state' do
finder = described_class.new(user)
- expect(finder.row_count).to eq(4)
+ expect(finder.row_count).to eq(5)
end
it 'returns the number of rows for a given state' do
@@ -646,7 +715,7 @@ describe IssuesFinder do
before do
allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
- stub_feature_flags(use_subquery_for_group_issues_search: true)
+ stub_feature_flags(attempt_group_search_optimizations: true)
end
context 'when there is no search param' do
@@ -677,11 +746,11 @@ describe IssuesFinder do
end
end
- context 'when the use_subquery_for_group_issues_search flag is disabled' do
+ context 'when the attempt_group_search_optimizations flag is disabled' do
let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
before do
- stub_feature_flags(use_subquery_for_group_issues_search: false)
+ stub_feature_flags(attempt_group_search_optimizations: false)
end
it 'returns false' do
@@ -689,6 +758,14 @@ describe IssuesFinder do
end
end
+ context 'when force_cte? is true' do
+ let(:params) { { search: 'foo', attempt_group_search_optimizations: true, force_cte: true } }
+
+ it 'returns false' do
+ expect(finder.use_subquery_for_search?).to be_falsey
+ end
+ end
+
context 'when all conditions are met' do
let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
@@ -698,72 +775,59 @@ describe IssuesFinder do
end
end
- describe '#use_cte_for_search?' do
+ describe '#use_cte_for_count?' do
let(:finder) { described_class.new(nil, params) }
before do
allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
- stub_feature_flags(use_cte_for_group_issues_search: true)
- stub_feature_flags(use_subquery_for_group_issues_search: false)
+ stub_feature_flags(attempt_group_search_optimizations: true)
end
context 'when there is no search param' do
- let(:params) { { attempt_group_search_optimizations: true } }
+ let(:params) { { attempt_group_search_optimizations: true, force_cte: true } }
it 'returns false' do
- expect(finder.use_cte_for_search?).to be_falsey
+ expect(finder.use_cte_for_count?).to be_falsey
end
end
context 'when the database is not Postgres' do
- let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
+ let(:params) { { search: 'foo', force_cte: true, attempt_group_search_optimizations: true } }
before do
allow(Gitlab::Database).to receive(:postgresql?).and_return(false)
end
it 'returns false' do
- expect(finder.use_cte_for_search?).to be_falsey
+ expect(finder.use_cte_for_count?).to be_falsey
end
end
- context 'when the attempt_group_search_optimizations param is falsey' do
+ context 'when the force_cte param is falsey' do
let(:params) { { search: 'foo' } }
it 'returns false' do
- expect(finder.use_cte_for_search?).to be_falsey
- end
- end
-
- context 'when the use_cte_for_group_issues_search flag is disabled' do
- let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
-
- before do
- stub_feature_flags(use_cte_for_group_issues_search: false)
- end
-
- it 'returns false' do
- expect(finder.use_cte_for_search?).to be_falsey
+ expect(finder.use_cte_for_count?).to be_falsey
end
end
- context 'when use_subquery_for_search? is true' do
- let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
+ context 'when the attempt_group_search_optimizations flag is disabled' do
+ let(:params) { { search: 'foo', force_cte: true, attempt_group_search_optimizations: true } }
before do
- stub_feature_flags(use_subquery_for_group_issues_search: true)
+ stub_feature_flags(attempt_group_search_optimizations: false)
end
it 'returns false' do
- expect(finder.use_cte_for_search?).to be_falsey
+ expect(finder.use_cte_for_count?).to be_falsey
end
end
context 'when all conditions are met' do
- let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
+ let(:params) { { search: 'foo', force_cte: true, attempt_group_search_optimizations: true } }
it 'returns true' do
- expect(finder.use_cte_for_search?).to be_truthy
+ expect(finder.use_cte_for_count?).to be_truthy
end
end
end
diff --git a/spec/finders/merge_request_target_project_finder_spec.rb b/spec/finders/merge_request_target_project_finder_spec.rb
index f302cf80ce8..d26a75179de 100644
--- a/spec/finders/merge_request_target_project_finder_spec.rb
+++ b/spec/finders/merge_request_target_project_finder_spec.rb
@@ -7,7 +7,7 @@ describe MergeRequestTargetProjectFinder do
subject(:finder) { described_class.new(current_user: user, source_project: forked_project) }
shared_examples 'finding related projects' do
- it 'finds sibling projects and base project' do
+ it 'finds sibling projects and base project' do
other_fork
expect(finder.execute).to contain_exactly(base_project, other_fork, forked_project)
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index ff4c6b8dd42..503b88fcbad 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -13,261 +13,409 @@ describe MergeRequestsFinder do
end
end
- let(:user) { create :user }
- let(:user2) { create :user }
-
- let(:group) { create(:group) }
- let(:subgroup) { create(:group, parent: group) }
- let(:project1) { create_project_without_n_plus_1(group: group) }
- let(:project2) do
- Gitlab::GitalyClient.allow_n_plus_1_calls do
- fork_project(project1, user)
- end
- end
- let(:project3) do
- Gitlab::GitalyClient.allow_n_plus_1_calls do
- p = fork_project(project1, user)
- p.update!(archived: true)
- p
+ context "multiple projects with merge requests" do
+ let(:user) { create :user }
+ let(:user2) { create :user }
+
+ let(:group) { create(:group) }
+ let(:subgroup) { create(:group, parent: group) }
+ let(:project1) { create_project_without_n_plus_1(group: group) }
+ let(:project2) do
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ fork_project(project1, user)
+ end
end
- end
- let(:project4) { create_project_without_n_plus_1(group: subgroup) }
- let(:project5) { create_project_without_n_plus_1(group: subgroup) }
- let(:project6) { create_project_without_n_plus_1(group: subgroup) }
-
- let!(:merge_request1) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project1) }
- let!(:merge_request2) { create(:merge_request, :conflict, author: user, source_project: project2, target_project: project1, state: 'closed') }
- let!(:merge_request3) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project2, state: 'locked', title: 'thing WIP thing') }
- let!(:merge_request4) { create(:merge_request, :simple, author: user, source_project: project3, target_project: project3, title: 'WIP thing') }
- let!(:merge_request5) { create(:merge_request, :simple, author: user, source_project: project4, target_project: project4, title: '[WIP]') }
- let!(:merge_request6) { create(:merge_request, :simple, author: user, source_project: project5, target_project: project5, title: 'WIP: thing') }
- let!(:merge_request7) { create(:merge_request, :simple, author: user, source_project: project6, target_project: project6, title: 'wip thing') }
- let!(:merge_request8) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project1, title: '[wip] thing') }
- let!(:merge_request9) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project2, title: 'wip: thing') }
-
- before do
- project1.add_maintainer(user)
- project2.add_developer(user)
- project3.add_developer(user)
- project2.add_developer(user2)
- project4.add_developer(user)
- project5.add_developer(user)
- project6.add_developer(user)
- end
-
- describe "#execute" do
- it 'filters by scope' do
- params = { scope: 'authored', state: 'opened' }
- merge_requests = described_class.new(user, params).execute
- expect(merge_requests.size).to eq(7)
+ let(:project3) do
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ p = fork_project(project1, user)
+ p.update!(archived: true)
+ p
+ end
end
-
- it 'filters by project' do
- params = { project_id: project1.id, scope: 'authored', state: 'opened' }
- merge_requests = described_class.new(user, params).execute
- expect(merge_requests.size).to eq(2)
+ let(:project4) { create_project_without_n_plus_1(:repository, group: subgroup) }
+ let(:project5) { create_project_without_n_plus_1(group: subgroup) }
+ let(:project6) { create_project_without_n_plus_1(group: subgroup) }
+
+ let!(:merge_request1) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project1) }
+ let!(:merge_request2) { create(:merge_request, :conflict, author: user, source_project: project2, target_project: project1, state: 'closed') }
+ let!(:merge_request3) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project2, state: 'locked', title: 'thing WIP thing') }
+ let!(:merge_request4) { create(:merge_request, :simple, author: user, source_project: project3, target_project: project3, title: 'WIP thing') }
+ let!(:merge_request5) { create(:merge_request, :simple, author: user, source_project: project4, target_project: project4, title: '[WIP]') }
+ let!(:merge_request6) { create(:merge_request, :simple, author: user, source_project: project5, target_project: project5, title: 'WIP: thing') }
+ let!(:merge_request7) { create(:merge_request, :simple, author: user, source_project: project6, target_project: project6, title: 'wip thing') }
+ let!(:merge_request8) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project1, title: '[wip] thing') }
+ let!(:merge_request9) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project2, title: 'wip: thing') }
+
+ before do
+ project1.add_maintainer(user)
+ project2.add_developer(user)
+ project3.add_developer(user)
+ project2.add_developer(user2)
+ project4.add_developer(user)
+ project5.add_developer(user)
+ project6.add_developer(user)
end
- it 'filters by group' do
- params = { group_id: group.id }
+ describe '#execute' do
+ it 'filters by scope' do
+ params = { scope: 'authored', state: 'opened' }
+ merge_requests = described_class.new(user, params).execute
+ expect(merge_requests.size).to eq(7)
+ end
- merge_requests = described_class.new(user, params).execute
+ it 'filters by project' do
+ params = { project_id: project1.id, scope: 'authored', state: 'opened' }
+ merge_requests = described_class.new(user, params).execute
+ expect(merge_requests.size).to eq(2)
+ end
- expect(merge_requests.size).to eq(3)
- end
+ it 'filters by commit sha' do
+ merge_requests = described_class.new(
+ user,
+ commit_sha: merge_request5.merge_request_diff.last_commit_sha
+ ).execute
- it 'filters by group including subgroups', :nested_groups do
- params = { group_id: group.id, include_subgroups: true }
+ expect(merge_requests).to contain_exactly(merge_request5)
+ end
- merge_requests = described_class.new(user, params).execute
+ context 'filtering by group' do
+ it 'includes all merge requests when user has access' do
+ params = { group_id: group.id }
- expect(merge_requests.size).to eq(6)
- end
+ merge_requests = described_class.new(user, params).execute
- it 'filters by non_archived' do
- params = { non_archived: true }
- merge_requests = described_class.new(user, params).execute
- expect(merge_requests.size).to eq(8)
- end
+ expect(merge_requests.size).to eq(3)
+ end
- it 'filters by iid' do
- params = { project_id: project1.id, iids: merge_request1.iid }
+ it 'excludes merge requests from projects the user does not have access to' do
+ private_project = create_project_without_n_plus_1(:private, group: group)
+ private_mr = create(:merge_request, :simple, author: user, source_project: private_project, target_project: private_project)
+ params = { group_id: group.id }
- merge_requests = described_class.new(user, params).execute
+ private_project.add_guest(user)
+ merge_requests = described_class.new(user, params).execute
- expect(merge_requests).to contain_exactly(merge_request1)
- end
+ expect(merge_requests.size).to eq(3)
+ expect(merge_requests).not_to include(private_mr)
+ end
- it 'filters by source branch' do
- params = { source_branch: merge_request2.source_branch }
+ it 'filters by group including subgroups', :nested_groups do
+ params = { group_id: group.id, include_subgroups: true }
- merge_requests = described_class.new(user, params).execute
+ merge_requests = described_class.new(user, params).execute
- expect(merge_requests).to contain_exactly(merge_request2)
- end
+ expect(merge_requests.size).to eq(6)
+ end
+ end
- it 'filters by target branch' do
- params = { target_branch: merge_request2.target_branch }
+ it 'filters by non_archived' do
+ params = { non_archived: true }
+ merge_requests = described_class.new(user, params).execute
+ expect(merge_requests.size).to eq(8)
+ end
- merge_requests = described_class.new(user, params).execute
+ it 'filters by iid' do
+ params = { project_id: project1.id, iids: merge_request1.iid }
- expect(merge_requests).to contain_exactly(merge_request2)
- end
+ merge_requests = described_class.new(user, params).execute
- it 'filters by state' do
- params = { state: 'locked' }
+ expect(merge_requests).to contain_exactly(merge_request1)
+ end
- merge_requests = described_class.new(user, params).execute
+ it 'filters by source branch' do
+ params = { source_branch: merge_request2.source_branch }
- expect(merge_requests).to contain_exactly(merge_request3)
- end
+ merge_requests = described_class.new(user, params).execute
- it 'filters by wip' do
- params = { wip: 'yes' }
+ expect(merge_requests).to contain_exactly(merge_request2)
+ end
- merge_requests = described_class.new(user, params).execute
+ it 'filters by target branch' do
+ params = { target_branch: merge_request2.target_branch }
- expect(merge_requests).to contain_exactly(merge_request4, merge_request5, merge_request6, merge_request7, merge_request8, merge_request9)
- end
+ merge_requests = described_class.new(user, params).execute
- it 'filters by not wip' do
- params = { wip: 'no' }
+ expect(merge_requests).to contain_exactly(merge_request2)
+ end
- merge_requests = described_class.new(user, params).execute
+ it 'filters by state' do
+ params = { state: 'locked' }
- expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3)
- end
+ merge_requests = described_class.new(user, params).execute
- it 'returns all items if no valid wip param exists' do
- params = { wip: '' }
+ expect(merge_requests).to contain_exactly(merge_request3)
+ end
- merge_requests = described_class.new(user, params).execute
+ it 'filters by wip' do
+ params = { wip: 'yes' }
- expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5, merge_request6, merge_request7, merge_request8, merge_request9)
- end
+ merge_requests = described_class.new(user, params).execute
- it 'adds wip to scalar params' do
- scalar_params = described_class.scalar_params
+ expect(merge_requests).to contain_exactly(merge_request4, merge_request5, merge_request6, merge_request7, merge_request8, merge_request9)
+ end
- expect(scalar_params).to include(:wip, :assignee_id)
- end
+ it 'filters by not wip' do
+ params = { wip: 'no' }
- context 'filtering by group milestone' do
- let!(:group) { create(:group, :public) }
- let(:group_milestone) { create(:milestone, group: group) }
- let!(:group_member) { create(:group_member, group: group, user: user) }
- let(:params) { { milestone_title: group_milestone.title } }
+ merge_requests = described_class.new(user, params).execute
- before do
- project2.update(namespace: group)
- merge_request2.update(milestone: group_milestone)
- merge_request3.update(milestone: group_milestone)
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3)
end
- it 'returns issues assigned to that group milestone' do
+ it 'returns all items if no valid wip param exists' do
+ params = { wip: '' }
+
merge_requests = described_class.new(user, params).execute
- expect(merge_requests).to contain_exactly(merge_request2, merge_request3)
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5, merge_request6, merge_request7, merge_request8, merge_request9)
end
- end
- context 'filtering by created_at/updated_at' do
- let(:new_project) { create(:project, forked_from_project: project1) }
-
- let!(:new_merge_request) do
- create(:merge_request,
- :simple,
- author: user,
- created_at: 1.week.from_now,
- updated_at: 1.week.from_now,
- source_project: new_project,
- target_project: new_project)
- end
+ it 'adds wip to scalar params' do
+ scalar_params = described_class.scalar_params
- let!(:old_merge_request) do
- create(:merge_request,
- :simple,
- author: user,
- source_branch: 'feature_1',
- created_at: 1.week.ago,
- updated_at: 1.week.ago,
- source_project: new_project,
- target_project: new_project)
+ expect(scalar_params).to include(:wip, :assignee_id)
end
- before do
- new_project.add_maintainer(user)
- end
+ context 'filtering by group milestone' do
+ let!(:group) { create(:group, :public) }
+ let(:group_milestone) { create(:milestone, group: group) }
+ let!(:group_member) { create(:group_member, group: group, user: user) }
+ let(:params) { { milestone_title: group_milestone.title } }
- it 'filters by created_after' do
- params = { project_id: new_project.id, created_after: new_merge_request.created_at }
+ before do
+ project2.update(namespace: group)
+ merge_request2.update(milestone: group_milestone)
+ merge_request3.update(milestone: group_milestone)
+ end
- merge_requests = described_class.new(user, params).execute
+ it 'returns issues assigned to that group milestone' do
+ merge_requests = described_class.new(user, params).execute
- expect(merge_requests).to contain_exactly(new_merge_request)
+ expect(merge_requests).to contain_exactly(merge_request2, merge_request3)
+ end
end
- it 'filters by created_before' do
- params = { project_id: new_project.id, created_before: old_merge_request.created_at }
+ context 'filtering by created_at/updated_at' do
+ let(:new_project) { create(:project, forked_from_project: project1) }
- merge_requests = described_class.new(user, params).execute
+ let!(:new_merge_request) do
+ create(:merge_request,
+ :simple,
+ author: user,
+ created_at: 1.week.from_now,
+ updated_at: 1.week.from_now,
+ source_project: new_project,
+ target_project: new_project)
+ end
- expect(merge_requests).to contain_exactly(old_merge_request)
- end
+ let!(:old_merge_request) do
+ create(:merge_request,
+ :simple,
+ author: user,
+ source_branch: 'feature_1',
+ created_at: 1.week.ago,
+ updated_at: 1.week.ago,
+ source_project: new_project,
+ target_project: new_project)
+ end
- it 'filters by created_after and created_before' do
- params = {
- project_id: new_project.id,
- created_after: old_merge_request.created_at,
- created_before: new_merge_request.created_at
- }
+ before do
+ new_project.add_maintainer(user)
+ end
- merge_requests = described_class.new(user, params).execute
+ it 'filters by created_after' do
+ params = { project_id: new_project.id, created_after: new_merge_request.created_at }
+
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(new_merge_request)
+ end
+
+ it 'filters by created_before' do
+ params = { project_id: new_project.id, created_before: old_merge_request.created_at }
+
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(old_merge_request)
+ end
+
+ it 'filters by created_after and created_before' do
+ params = {
+ project_id: new_project.id,
+ created_after: old_merge_request.created_at,
+ created_before: new_merge_request.created_at
+ }
+
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(old_merge_request, new_merge_request)
+ end
+
+ it 'filters by updated_after' do
+ params = { project_id: new_project.id, updated_after: new_merge_request.updated_at }
+
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(new_merge_request)
+ end
+
+ it 'filters by updated_before' do
+ params = { project_id: new_project.id, updated_before: old_merge_request.updated_at }
+
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(old_merge_request)
+ end
+
+ it 'filters by updated_after and updated_before' do
+ params = {
+ project_id: new_project.id,
+ updated_after: old_merge_request.updated_at,
+ updated_before: new_merge_request.updated_at
+ }
- expect(merge_requests).to contain_exactly(old_merge_request, new_merge_request)
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(old_merge_request, new_merge_request)
+ end
end
+ end
- it 'filters by updated_after' do
- params = { project_id: new_project.id, updated_after: new_merge_request.updated_at }
+ describe '#row_count', :request_store do
+ it 'returns the number of rows for the default state' do
+ finder = described_class.new(user)
- merge_requests = described_class.new(user, params).execute
+ expect(finder.row_count).to eq(7)
+ end
+
+ it 'returns the number of rows for a given state' do
+ finder = described_class.new(user, state: 'closed')
- expect(merge_requests).to contain_exactly(new_merge_request)
+ expect(finder.row_count).to eq(1)
end
+ end
+ end
- it 'filters by updated_before' do
- params = { project_id: new_project.id, updated_before: old_merge_request.updated_at }
+ context 'when projects require different access levels for merge requests' do
+ let(:user) { create(:user) }
- merge_requests = described_class.new(user, params).execute
+ let(:public_project) { create(:project, :public) }
+ let(:internal) { create(:project, :internal) }
+ let(:private_project) { create(:project, :private) }
+ let(:public_with_private_repo) { create(:project, :public, :repository, :repository_private) }
+ let(:internal_with_private_repo) { create(:project, :internal, :repository, :repository_private) }
+
+ let(:merge_requests) { described_class.new(user, {}).execute }
+
+ let!(:mr_public) { create(:merge_request, source_project: public_project) }
+ let!(:mr_private) { create(:merge_request, source_project: private_project) }
+ let!(:mr_internal) { create(:merge_request, source_project: internal) }
+ let!(:mr_private_repo_access) { create(:merge_request, source_project: public_with_private_repo) }
+ let!(:mr_internal_private_repo_access) { create(:merge_request, source_project: internal_with_private_repo) }
+
+ context 'with admin user' do
+ let(:user) { create(:user, :admin) }
- expect(merge_requests).to contain_exactly(old_merge_request)
+ it 'returns all merge requests' do
+ expect(merge_requests).to eq(
+ [mr_internal_private_repo_access, mr_private_repo_access, mr_internal, mr_private, mr_public]
+ )
end
+ end
- it 'filters by updated_after and updated_before' do
- params = {
- project_id: new_project.id,
- updated_after: old_merge_request.updated_at,
- updated_before: new_merge_request.updated_at
- }
+ context 'when project restricts merge requests' do
+ let(:non_member) { create(:user) }
+ let(:project) { create(:project, :repository, :public, :merge_requests_private) }
+ let!(:merge_request) { create(:merge_request, source_project: project) }
- merge_requests = described_class.new(user, params).execute
+ it "returns nothing to to non members" do
+ merge_requests = described_class.new(
+ non_member,
+ project_id: project.id
+ ).execute
- expect(merge_requests).to contain_exactly(old_merge_request, new_merge_request)
+ expect(merge_requests).to be_empty
end
end
- end
- describe '#row_count', :request_store do
- it 'returns the number of rows for the default state' do
- finder = described_class.new(user)
+ context 'with external user' do
+ let(:user) { create(:user, :external) }
- expect(finder.row_count).to eq(7)
+ it 'returns only public merge requests' do
+ expect(merge_requests).to eq([mr_public])
+ end
end
- it 'returns the number of rows for a given state' do
- finder = described_class.new(user, state: 'closed')
+ context 'with authenticated user' do
+ it 'returns public and internal merge requests' do
+ expect(merge_requests).to eq([mr_internal, mr_public])
+ end
+
+ context 'being added to the private project' do
+ context 'as a guest' do
+ before do
+ private_project.add_guest(user)
+ end
+
+ it 'does not return merge requests from the private project' do
+ expect(merge_requests).to eq([mr_internal, mr_public])
+ end
+ end
+
+ context 'as a developer' do
+ before do
+ private_project.add_developer(user)
+ end
+
+ it 'returns merge requests from the private project' do
+ expect(merge_requests).to eq([mr_internal, mr_private, mr_public])
+ end
+ end
+ end
- expect(finder.row_count).to eq(1)
+ context 'being added to the public project with private repo access' do
+ context 'as a guest' do
+ before do
+ public_with_private_repo.add_guest(user)
+ end
+
+ it 'returns merge requests from the project' do
+ expect(merge_requests).to eq([mr_internal, mr_public])
+ end
+ end
+
+ context 'as a reporter' do
+ before do
+ public_with_private_repo.add_reporter(user)
+ end
+
+ it 'returns merge requests from the project' do
+ expect(merge_requests).to eq([mr_private_repo_access, mr_internal, mr_public])
+ end
+ end
+ end
+
+ context 'being added to the internal project with private repo access' do
+ context 'as a guest' do
+ before do
+ internal_with_private_repo.add_guest(user)
+ end
+
+ it 'returns merge requests from the project' do
+ expect(merge_requests).to eq([mr_internal, mr_public])
+ end
+ end
+
+ context 'as a reporter' do
+ before do
+ internal_with_private_repo.add_reporter(user)
+ end
+
+ it 'returns merge requests from the project' do
+ expect(merge_requests).to eq([mr_internal_private_repo_access, mr_internal, mr_public])
+ end
+ end
+ end
end
end
end
diff --git a/spec/finders/milestones_finder_spec.rb b/spec/finders/milestones_finder_spec.rb
index 656d120311a..ecffbb9e197 100644
--- a/spec/finders/milestones_finder_spec.rb
+++ b/spec/finders/milestones_finder_spec.rb
@@ -69,6 +69,12 @@ describe MilestonesFinder do
expect(result.to_a).to contain_exactly(milestone_1)
end
+
+ it 'filters by search_title' do
+ result = described_class.new(params.merge(search_title: 'one t')).execute
+
+ expect(result.to_a).to contain_exactly(milestone_1)
+ end
end
describe '#find_by' do
diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb
index b51f1955ac4..0a685152cf9 100644
--- a/spec/finders/notes_finder_spec.rb
+++ b/spec/finders/notes_finder_spec.rb
@@ -121,7 +121,7 @@ describe NotesFinder do
let(:note1) { create :note_on_commit, project: project }
let(:note2) { create :note_on_commit, project: project }
let(:commit) { note1.noteable }
- let(:params) { { target_id: commit.id, target_type: 'commit', last_fetched_at: 1.hour.ago.to_i } }
+ let(:params) { { target_id: commit.id, target_type: 'commit', last_fetched_at: 1.hour.ago.to_i } }
before do
note1
diff --git a/spec/finders/projects/serverless/functions_finder_spec.rb b/spec/finders/projects/serverless/functions_finder_spec.rb
index 60d02b12054..35279906854 100644
--- a/spec/finders/projects/serverless/functions_finder_spec.rb
+++ b/spec/finders/projects/serverless/functions_finder_spec.rb
@@ -29,15 +29,34 @@ describe Projects::Serverless::FunctionsFinder do
context 'has knative installed' do
let!(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) }
+ let(:finder) { described_class.new(project.clusters) }
it 'there are no functions' do
- expect(described_class.new(project.clusters).execute).to be_empty
+ expect(finder.execute).to be_empty
end
it 'there are functions', :use_clean_rails_memory_store_caching do
- stub_reactive_cache(knative, services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"])
+ stub_kubeclient_service_pods
+ stub_reactive_cache(knative,
+ {
+ services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
+ pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
+ })
- expect(described_class.new(project.clusters).execute).not_to be_empty
+ expect(finder.execute).not_to be_empty
+ end
+
+ it 'has a function', :use_clean_rails_memory_store_caching do
+ stub_kubeclient_service_pods
+ stub_reactive_cache(knative,
+ {
+ services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
+ pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
+ })
+
+ result = finder.service(cluster.environment_scope, cluster.project.name)
+ expect(result).not_to be_empty
+ expect(result["metadata"]["name"]).to be_eql(cluster.project.name)
end
end
end
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 590e838f13e..ac866e49fcd 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -137,7 +137,7 @@ describe ProjectsFinder do
end
describe 'filter by trending' do
- let!(:trending_project) { create(:trending_project, project: public_project) }
+ let!(:trending_project) { create(:trending_project, project: public_project) }
let(:params) { { trending: true } }
it { is_expected.to eq([public_project]) }
diff --git a/spec/finders/releases_finder_spec.rb b/spec/finders/releases_finder_spec.rb
new file mode 100644
index 00000000000..32ee15134a2
--- /dev/null
+++ b/spec/finders/releases_finder_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ReleasesFinder do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:v1_0_0) { create(:release, project: project, tag: 'v1.0.0') }
+ let(:v1_1_0) { create(:release, project: project, tag: 'v1.1.0') }
+
+ subject { described_class.new(project, user)}
+
+ before do
+ v1_0_0.update_attribute(:created_at, 2.days.ago)
+ v1_1_0.update_attribute(:created_at, 1.day.ago)
+ end
+
+ describe '#execute' do
+ context 'when the user is not part of the project' do
+ it 'returns no releases' do
+ releases = subject.execute
+
+ expect(releases).to be_empty
+ end
+ end
+
+ context 'when the user is a project developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'sorts by creation date' do
+ releases = subject.execute
+
+ expect(releases).to be_present
+ expect(releases.size).to eq(2)
+ expect(releases).to eq([v1_1_0, v1_0_0])
+ end
+ end
+ end
+end
diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb
index dfeeb3040c6..134fb5f2c04 100644
--- a/spec/finders/snippets_finder_spec.rb
+++ b/spec/finders/snippets_finder_spec.rb
@@ -107,7 +107,7 @@ describe SnippetsFinder do
context 'filter by project' do
let(:user) { create :user }
let(:group) { create :group, :public }
- let(:project1) { create(:project, :public, group: group) }
+ let(:project1) { create(:project, :public, group: group) }
before do
@snippet1 = create(:project_snippet, :private, project: project1)
diff --git a/spec/fixtures/api/schemas/cluster_status.json b/spec/fixtures/api/schemas/cluster_status.json
index 3d9e0628f63..5ebc09a96dc 100644
--- a/spec/fixtures/api/schemas/cluster_status.json
+++ b/spec/fixtures/api/schemas/cluster_status.json
@@ -30,10 +30,12 @@
]
}
},
+ "version": { "type": "string" },
"status_reason": { "type": ["string", "null"] },
"external_ip": { "type": ["string", "null"] },
"hostname": { "type": ["string", "null"] },
- "email": { "type": ["string", "null"] }
+ "email": { "type": ["string", "null"] },
+ "update_available": { "type": ["boolean", "null"] }
},
"required" : [ "name", "status" ]
}
diff --git a/spec/fixtures/api/schemas/entities/diff_viewer.json b/spec/fixtures/api/schemas/entities/diff_viewer.json
index 19780f49a88..ae0fb32d3ac 100644
--- a/spec/fixtures/api/schemas/entities/diff_viewer.json
+++ b/spec/fixtures/api/schemas/entities/diff_viewer.json
@@ -1,8 +1,31 @@
{
"type": "object",
- "required": ["name"],
+ "required": [
+ "name"
+ ],
"properties": {
- "name": { "type": ["string"] }
+ "name": {
+ "type": [
+ "string"
+ ]
+ },
+ "error": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "error_message": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "collapsed": {
+ "type": [
+ "boolean"
+ ]
+ }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/entities/merge_request_basic.json b/spec/fixtures/api/schemas/entities/merge_request_basic.json
index 4c04c838cb8..3006b482d41 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_basic.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_basic.json
@@ -22,7 +22,8 @@
"type": [ "array", "null" ]
},
"task_status": { "type": "string" },
- "task_status_short": { "type": "string" }
+ "task_status_short": { "type": "string" },
+ "lock_version": { "type": ["string", "null"] }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/entities/merge_request_widget.json b/spec/fixtures/api/schemas/entities/merge_request_widget.json
index 193ab6821a5..67c209f3fc3 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_widget.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_widget.json
@@ -44,7 +44,7 @@
"merge_user": { "type": ["object", "null"] },
"diff_head_sha": { "type": ["string", "null"] },
"diff_head_commit_short_id": { "type": ["string", "null"] },
- "merge_commit_message": { "type": ["string", "null"] },
+ "default_merge_commit_message": { "type": ["string", "null"] },
"pipeline": { "type": ["object", "null"] },
"merge_pipeline": { "type": ["object", "null"] },
"work_in_progress": { "type": "boolean" },
@@ -102,7 +102,9 @@
"new_blob_path": { "type": ["string", "null"] },
"merge_check_path": { "type": "string" },
"ci_environments_status_path": { "type": "string" },
- "merge_commit_message_with_description": { "type": "string" },
+ "default_merge_commit_message_with_description": { "type": "string" },
+ "default_squash_commit_message": { "type": "string" },
+ "commits_without_merge_commits": { "type": "array" },
"diverged_commits_count": { "type": "integer" },
"commit_change_content_path": { "type": "string" },
"merge_commit_path": { "type": ["string", "null"] },
@@ -120,7 +122,9 @@
"rebase_path": { "type": ["string", "null"] },
"squash": { "type": "boolean" },
"test_reports_path": { "type": ["string", "null"] },
- "can_receive_suggestion": { "type": "boolean" }
+ "can_receive_suggestion": { "type": "boolean" },
+ "source_branch_protected": { "type": "boolean" },
+ "conflicts_docs_path": { "type": ["string", "null"] }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/environment.json b/spec/fixtures/api/schemas/environment.json
index f1d33e3ce7b..9a10ab18c30 100644
--- a/spec/fixtures/api/schemas/environment.json
+++ b/spec/fixtures/api/schemas/environment.json
@@ -20,6 +20,7 @@
"state": { "type": "string" },
"external_url": { "$ref": "types/nullable_string.json" },
"environment_type": { "$ref": "types/nullable_string.json" },
+ "name_without_type": { "type": "string" },
"has_stop_action": { "type": "boolean" },
"environment_path": { "type": "string" },
"stop_path": { "type": "string" },
diff --git a/spec/fixtures/api/schemas/error_tracking/error.json b/spec/fixtures/api/schemas/error_tracking/error.json
new file mode 100644
index 00000000000..df2c02d7d5d
--- /dev/null
+++ b/spec/fixtures/api/schemas/error_tracking/error.json
@@ -0,0 +1,21 @@
+{
+ "type": "object",
+ "required" : [
+ "external_url",
+ "last_seen",
+ "message",
+ "type"
+ ],
+ "properties" : {
+ "id": { "type": "string"},
+ "first_seen": { "type": "string", "format": "date-time" },
+ "last_seen": { "type": "string", "format": "date-time" },
+ "type": { "type": "string" },
+ "message": { "type": "string" },
+ "culprit": { "type": "string" },
+ "count": { "type": "integer"},
+ "external_url": { "type": "string" },
+ "user_count": { "type": "integer"}
+ },
+ "additionalProperties": true
+}
diff --git a/spec/fixtures/api/schemas/error_tracking/index.json b/spec/fixtures/api/schemas/error_tracking/index.json
new file mode 100644
index 00000000000..d3abc29ffa7
--- /dev/null
+++ b/spec/fixtures/api/schemas/error_tracking/index.json
@@ -0,0 +1,15 @@
+{
+ "type": "object",
+ "required": [
+ "external_url",
+ "errors"
+ ],
+ "properties": {
+ "external_url": { "type": ["string", "null"] },
+ "errors": {
+ "type": "array",
+ "items": { "$ref": "error.json" }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/error_tracking/list_projects.json b/spec/fixtures/api/schemas/error_tracking/list_projects.json
new file mode 100644
index 00000000000..2aaa525e38f
--- /dev/null
+++ b/spec/fixtures/api/schemas/error_tracking/list_projects.json
@@ -0,0 +1,13 @@
+{
+ "type": "object",
+ "required": [
+ "projects"
+ ],
+ "properties": {
+ "projects": {
+ "type": "array",
+ "items": { "$ref": "project.json" }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/error_tracking/project.json b/spec/fixtures/api/schemas/error_tracking/project.json
new file mode 100644
index 00000000000..f6d611133c7
--- /dev/null
+++ b/spec/fixtures/api/schemas/error_tracking/project.json
@@ -0,0 +1,19 @@
+{
+ "type": "object",
+ "required" : [
+ "id",
+ "slug",
+ "organization_slug",
+ "name"
+ ],
+ "properties" : {
+ "id": { "type": "string"},
+ "name": { "type": "string" },
+ "slug": { "type": "string" },
+ "status": { "type": "string" },
+ "organization_name": { "type": "string" },
+ "organization_slug": { "type": "string" },
+ "organization_id": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/group_labels.json b/spec/fixtures/api/schemas/public_api/v4/group_labels.json
new file mode 100644
index 00000000000..fbde45f2904
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/group_labels.json
@@ -0,0 +1,19 @@
+{
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties" : {
+ "id" : { "type": "integer" },
+ "name" : { "type": "string "},
+ "color" : { "type": "string "},
+ "text_color" : { "type": "string "},
+ "description" : { "type": "string "},
+ "open_issues_count" : { "type": "integer "},
+ "closed_issues_count" : { "type": "integer "},
+ "open_merge_requests_count" : { "type": "integer "},
+ "subscribed" : { "type": "boolean" },
+ "priority" : { "type": "null" }
+ },
+ "additionalProperties": false
+ }
+}
diff --git a/spec/fixtures/api/schemas/registry/repository.json b/spec/fixtures/api/schemas/registry/repository.json
index 4175642eb00..e0fd4620c43 100644
--- a/spec/fixtures/api/schemas/registry/repository.json
+++ b/spec/fixtures/api/schemas/registry/repository.json
@@ -2,20 +2,27 @@
"type": "object",
"required" : [
"id",
+ "name",
"path",
"location",
- "tags_path"
+ "created_at"
],
"properties" : {
"id": {
"type": "integer"
},
+ "name": {
+ "type": "string"
+ },
"path": {
"type": "string"
},
"location": {
"type": "string"
},
+ "created_at": {
+ "type": "date-time"
+ },
"tags_path": {
"type": "string"
},
diff --git a/spec/fixtures/api/schemas/registry/tag.json b/spec/fixtures/api/schemas/registry/tag.json
index 3a2c88791e1..48f8402b65b 100644
--- a/spec/fixtures/api/schemas/registry/tag.json
+++ b/spec/fixtures/api/schemas/registry/tag.json
@@ -2,15 +2,22 @@
"type": "object",
"required" : [
"name",
+ "path",
"location"
],
"properties" : {
"name": {
"type": "string"
},
+ "path": {
+ "type": "string"
+ },
"location": {
"type": "string"
},
+ "digest": {
+ "type": "string"
+ },
"revision": {
"type": "string"
},
diff --git a/spec/fixtures/api/schemas/release.json b/spec/fixtures/api/schemas/release.json
new file mode 100644
index 00000000000..86f0f27606c
--- /dev/null
+++ b/spec/fixtures/api/schemas/release.json
@@ -0,0 +1,29 @@
+{
+ "type": "object",
+ "required": ["name", "tag_name"],
+ "properties": {
+ "name": { "type": "string" },
+ "tag_name": { "type": "string" },
+ "description": { "type": "string" },
+ "description_html": { "type": "string" },
+ "created_at": { "type": "date" },
+ "commit": {
+ "oneOf": [{ "type": "null" }, { "$ref": "public_api/v4/commit/basic.json" }]
+ },
+ "author": {
+ "oneOf": [{ "type": "null" }, { "$ref": "public_api/v4/user/basic.json" }]
+ },
+ "assets": {
+ "count": { "type": "integer" },
+ "links": { "$ref": "release/links.json" },
+ "sources": {
+ "type": "array",
+ "items": {
+ "format": "zip",
+ "url": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/release/link.json b/spec/fixtures/api/schemas/release/link.json
new file mode 100644
index 00000000000..97347cb91cc
--- /dev/null
+++ b/spec/fixtures/api/schemas/release/link.json
@@ -0,0 +1,11 @@
+{
+ "type": "object",
+ "required": ["name", "url"],
+ "properties": {
+ "id": { "type": "integer" },
+ "name": { "type": "string" },
+ "url": { "type": "string" },
+ "external": { "type": "boolean" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/release/links.json b/spec/fixtures/api/schemas/release/links.json
new file mode 100644
index 00000000000..766bc7ce20a
--- /dev/null
+++ b/spec/fixtures/api/schemas/release/links.json
@@ -0,0 +1,4 @@
+{
+ "type": "array",
+ "items": { "$ref": "link.json" }
+}
diff --git a/spec/fixtures/api/schemas/releases.json b/spec/fixtures/api/schemas/releases.json
new file mode 100644
index 00000000000..e26215707fe
--- /dev/null
+++ b/spec/fixtures/api/schemas/releases.json
@@ -0,0 +1,4 @@
+{
+ "type": "array",
+ "items": { "$ref": "release.json" }
+}
diff --git a/spec/fixtures/clusters/sample_cert.pem b/spec/fixtures/clusters/sample_cert.pem
index e39a2b34416..00e6ce44d87 100644
--- a/spec/fixtures/clusters/sample_cert.pem
+++ b/spec/fixtures/clusters/sample_cert.pem
@@ -30,4 +30,4 @@ TkIdFE47ZisEDhIdF6wC1izEMLeMEsPAO7/Y6MY4nRxsinSe95lRaw+yQpzx+mvJ
Q7n1kiHI9Pd5M3+CiQda0d/GO1o5ORJnUGJRvr9HKuNmE7Lif0As/N0AlywjzE7A
6Z8AEiWyRV1ffshu1k2UKmzvZuZeGGKRtrIjbJIRAtpRVtVZZGzhq5/sojCLoJ+u
texqFBUo/4mFRZa4pDItUdyOlDy2/LO/ag==
------END CERTIFICATE-----
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/spec/fixtures/csv_comma.csv b/spec/fixtures/csv_comma.csv
new file mode 100644
index 00000000000..e477a27d243
--- /dev/null
+++ b/spec/fixtures/csv_comma.csv
@@ -0,0 +1,4 @@
+title,description
+Issue in 中文,Test description
+"Hello","World"
+"Title with quote""",Description
diff --git a/spec/fixtures/csv_semicolon.csv b/spec/fixtures/csv_semicolon.csv
new file mode 100644
index 00000000000..679797489e2
--- /dev/null
+++ b/spec/fixtures/csv_semicolon.csv
@@ -0,0 +1,5 @@
+title;description
+Issue in 中文;Test description
+Title with, comma;"Description"
+
+"Hello";"World"
diff --git a/spec/fixtures/csv_tab.csv b/spec/fixtures/csv_tab.csv
new file mode 100644
index 00000000000..f801794ea9c
--- /dev/null
+++ b/spec/fixtures/csv_tab.csv
@@ -0,0 +1,4 @@
+title description
+Issue in 中文 Test description
+ "Error Row"
+"Hello" "World"
diff --git a/spec/fixtures/emails/merge_request_multiple_patches.eml b/spec/fixtures/emails/merge_request_multiple_patches.eml
index 311b99a525d..7d2e0cd4e50 100644
--- a/spec/fixtures/emails/merge_request_multiple_patches.eml
+++ b/spec/fixtures/emails/merge_request_multiple_patches.eml
@@ -1,5 +1,5 @@
From: "Jake the Dog" <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-merge-request@appmail.adventuretime.ooo
Subject: new-branch-with-a-patch
Date: Wed, 31 Oct 2018 17:27:52 +0100
X-Mailer: MailMate (1.12r5523)
diff --git a/spec/fixtures/emails/merge_request_with_conflicting_patch.eml b/spec/fixtures/emails/merge_request_with_conflicting_patch.eml
index ddfdfe9e24a..5c9eda640bc 100644
--- a/spec/fixtures/emails/merge_request_with_conflicting_patch.eml
+++ b/spec/fixtures/emails/merge_request_with_conflicting_patch.eml
@@ -1,5 +1,5 @@
From: "Jake the Dog" <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-merge-request@appmail.adventuretime.ooo
Subject: feature
Date: Wed, 31 Oct 2018 17:27:52 +0100
X-Mailer: MailMate (1.12r5523)
diff --git a/spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml b/spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml
index 965658721cd..9fabfc23e3b 100644
--- a/spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml
+++ b/spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml
@@ -1,5 +1,5 @@
From: "Jake the Dog" <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-merge-request@appmail.adventuretime.ooo
Subject: new-branch-with-a-patch
Date: Wed, 24 Oct 2018 16:39:49 +0200
X-Mailer: MailMate (1.12r5523)
diff --git a/spec/fixtures/emails/valid_merge_request_with_patch.eml b/spec/fixtures/emails/valid_merge_request_with_patch.eml
index 143fa77d1fa..e0f406639a3 100644
--- a/spec/fixtures/emails/valid_merge_request_with_patch.eml
+++ b/spec/fixtures/emails/valid_merge_request_with_patch.eml
@@ -1,5 +1,5 @@
From: "Jake the Dog" <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-merge-request@appmail.adventuretime.ooo
Subject: new-branch-with-a-patch
Date: Wed, 24 Oct 2018 16:39:49 +0200
X-Mailer: MailMate (1.12r5523)
diff --git a/spec/fixtures/emails/valid_new_issue.eml b/spec/fixtures/emails/valid_new_issue.eml
index 3cf53a656a5..7d63016ed04 100644
--- a/spec/fixtures/emails/valid_new_issue.eml
+++ b/spec/fixtures/emails/valid_new_issue.eml
@@ -1,11 +1,11 @@
Return-Path: <jake@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
-Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-issue@appmail.adventuretime.ooo
Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
Subject: New Issue by email
Mime-Version: 1.0
diff --git a/spec/fixtures/emails/valid_new_issue_empty.eml b/spec/fixtures/emails/valid_new_issue_empty.eml
index fc1d52a3f42..58a6ef29d69 100644
--- a/spec/fixtures/emails/valid_new_issue_empty.eml
+++ b/spec/fixtures/emails/valid_new_issue_empty.eml
@@ -1,11 +1,11 @@
Return-Path: <jake@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
-Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-issue@appmail.adventuretime.ooo
Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
Subject: New Issue by email
Mime-Version: 1.0
diff --git a/spec/fixtures/emails/valid_new_issue_legacy.eml b/spec/fixtures/emails/valid_new_issue_legacy.eml
new file mode 100644
index 00000000000..3cf53a656a5
--- /dev/null
+++ b/spec/fixtures/emails/valid_new_issue_legacy.eml
@@ -0,0 +1,23 @@
+Return-Path: <jake@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+Date: Thu, 13 Jun 2013 17:03:48 -0400
+From: Jake the Dog <jake@adventuretime.ooo>
+To: incoming+gitlabhq/gitlabhq+auth_token@appmail.adventuretime.ooo
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: New Issue by email
+Mime-Version: 1.0
+Content-Type: text/plain;
+ charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-Sieve: CMU Sieve 2.2
+X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
+ 13 Jun 2013 14:03:48 -0700 (PDT)
+X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
+
+The reply by email functionality should be extended to allow creating a new issue by email.
+
+* Allow an admin to specify which project the issue should be created under by checking the sender domain.
+* Possibly allow the use of regular expression matches within the subject/body to specify which project the issue should be created under.
diff --git a/spec/fixtures/emails/valid_new_issue_with_quote.eml b/spec/fixtures/emails/valid_new_issue_with_quote.eml
index 0caf8ed4e9e..3a9b9dbbba5 100644
--- a/spec/fixtures/emails/valid_new_issue_with_quote.eml
+++ b/spec/fixtures/emails/valid_new_issue_with_quote.eml
@@ -1,11 +1,11 @@
Return-Path: <jake@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
-Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-issue@appmail.adventuretime.ooo
Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
Subject: New Issue by email
Mime-Version: 1.0
diff --git a/spec/fixtures/emails/valid_new_merge_request.eml b/spec/fixtures/emails/valid_new_merge_request.eml
index 729df674604..e12843ea76b 100644
--- a/spec/fixtures/emails/valid_new_merge_request.eml
+++ b/spec/fixtures/emails/valid_new_merge_request.eml
@@ -1,11 +1,11 @@
Return-Path: <jake@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
-Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
-Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-merge-request@appmail.adventuretime.ooo
Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
Subject: feature
Mime-Version: 1.0
diff --git a/spec/fixtures/emails/valid_new_merge_request_legacy.eml b/spec/fixtures/emails/valid_new_merge_request_legacy.eml
new file mode 100644
index 00000000000..b6cf064af19
--- /dev/null
+++ b/spec/fixtures/emails/valid_new_merge_request_legacy.eml
@@ -0,0 +1,20 @@
+Return-Path: <jake@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+Date: Thu, 13 Jun 2013 17:03:48 -0400
+From: Jake the Dog <jake@adventuretime.ooo>
+To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: feature
+Mime-Version: 1.0
+Content-Type: text/plain;
+ charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-Sieve: CMU Sieve 2.2
+X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
+ 13 Jun 2013 14:03:48 -0700 (PDT)
+X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
+
+Merge request description
diff --git a/spec/fixtures/emails/valid_new_merge_request_no_description.eml b/spec/fixtures/emails/valid_new_merge_request_no_description.eml
index 480675a6d7e..3ac0ea191a9 100644
--- a/spec/fixtures/emails/valid_new_merge_request_no_description.eml
+++ b/spec/fixtures/emails/valid_new_merge_request_no_description.eml
@@ -1,11 +1,11 @@
Return-Path: <jake@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
-Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-merge-request@appmail.adventuretime.ooo
Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
Subject: feature
Mime-Version: 1.0
diff --git a/spec/fixtures/emails/valid_new_merge_request_no_subject.eml b/spec/fixtures/emails/valid_new_merge_request_no_subject.eml
index 27eb1b7d922..c2735ccb08a 100644
--- a/spec/fixtures/emails/valid_new_merge_request_no_subject.eml
+++ b/spec/fixtures/emails/valid_new_merge_request_no_subject.eml
@@ -1,11 +1,11 @@
Return-Path: <jake@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
-Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-merge-request@appmail.adventuretime.ooo
Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
Subject:
Mime-Version: 1.0
diff --git a/spec/fixtures/emails/wrong_incoming_email_token.eml b/spec/fixtures/emails/wrong_incoming_email_token.eml
deleted file mode 100644
index 0994c2f7775..00000000000
--- a/spec/fixtures/emails/wrong_incoming_email_token.eml
+++ /dev/null
@@ -1,18 +0,0 @@
-Return-Path: <jake@adventuretime.ooo>
-Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
-Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
-Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
-Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
-Date: Thu, 13 Jun 2013 17:03:48 -0400
-From: Jake the Dog <jake@adventuretime.ooo>
-To: incoming+gitlabhq/gitlabhq+bad_token@appmail.adventuretime.ooo
-Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
-Subject: New Issue by email
-Mime-Version: 1.0
-Content-Type: text/plain;
- charset=ISO-8859-1
-Content-Transfer-Encoding: 7bit
-X-Sieve: CMU Sieve 2.2
-X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
- 13 Jun 2013 14:03:48 -0700 (PDT)
-X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
diff --git a/spec/fixtures/emails/wrong_issue_incoming_email_token.eml b/spec/fixtures/emails/wrong_issue_incoming_email_token.eml
new file mode 100644
index 00000000000..d3ba6943a90
--- /dev/null
+++ b/spec/fixtures/emails/wrong_issue_incoming_email_token.eml
@@ -0,0 +1,18 @@
+Return-Path: <jake@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+Date: Thu, 13 Jun 2013 17:03:48 -0400
+From: Jake the Dog <jake@adventuretime.ooo>
+To: incoming+gitlabhq-gitlabhq-project_id-bad_token-issue@appmail.adventuretime.ooo
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: New Issue by email
+Mime-Version: 1.0
+Content-Type: text/plain;
+ charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-Sieve: CMU Sieve 2.2
+X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
+ 13 Jun 2013 14:03:48 -0700 (PDT)
+X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
diff --git a/spec/fixtures/emails/wrong_merge_request_incoming_email_token.eml b/spec/fixtures/emails/wrong_merge_request_incoming_email_token.eml
new file mode 100644
index 00000000000..c7b758b8f1f
--- /dev/null
+++ b/spec/fixtures/emails/wrong_merge_request_incoming_email_token.eml
@@ -0,0 +1,18 @@
+Return-Path: <jake@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+Date: Thu, 13 Jun 2013 17:03:48 -0400
+From: Jake the Dog <jake@adventuretime.ooo>
+To: incoming+gitlabhq-gitlabhq-project_id-bad_token-merge-request@appmail.adventuretime.ooo
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: New Issue by email
+Mime-Version: 1.0
+Content-Type: text/plain;
+ charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-Sieve: CMU Sieve 2.2
+X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
+ 13 Jun 2013 14:03:48 -0700 (PDT)
+X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
diff --git a/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml b/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml
index 0bab94a7c2e..1e88cd120aa 100644
--- a/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml
+++ b/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml
@@ -2,7 +2,6 @@ before_script:
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
rspec:
diff --git a/spec/fixtures/malicious.bundle b/spec/fixtures/malicious.bundle
new file mode 100644
index 00000000000..7ba47932906
--- /dev/null
+++ b/spec/fixtures/malicious.bundle
@@ -0,0 +1 @@
+gitdir: foo.git
diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb
index e5d01c3bd03..bbeacf1707b 100644
--- a/spec/fixtures/markdown.md.erb
+++ b/spec/fixtures/markdown.md.erb
@@ -6,7 +6,7 @@ started.
## Markdown
-GitLab uses [Redcarpet](http://git.io/ld_NVQ) to parse all Markdown into
+GitLab uses [Commonmark](https://git.io/fhDag) to parse all Markdown into
HTML.
It has some special features. Let's try 'em out!
diff --git a/spec/fixtures/pages_non_writeable.zip b/spec/fixtures/pages_non_writeable.zip
new file mode 100644
index 00000000000..69f175d8504
--- /dev/null
+++ b/spec/fixtures/pages_non_writeable.zip
Binary files differ
diff --git a/spec/fixtures/safe_zip/invalid-symlink-does-not-exist.zip b/spec/fixtures/safe_zip/invalid-symlink-does-not-exist.zip
new file mode 100644
index 00000000000..b9ae1548713
--- /dev/null
+++ b/spec/fixtures/safe_zip/invalid-symlink-does-not-exist.zip
Binary files differ
diff --git a/spec/fixtures/safe_zip/invalid-symlinks-outside.zip b/spec/fixtures/safe_zip/invalid-symlinks-outside.zip
new file mode 100644
index 00000000000..c184a1dafe2
--- /dev/null
+++ b/spec/fixtures/safe_zip/invalid-symlinks-outside.zip
Binary files differ
diff --git a/spec/fixtures/safe_zip/valid-non-writeable.zip b/spec/fixtures/safe_zip/valid-non-writeable.zip
new file mode 100644
index 00000000000..69f175d8504
--- /dev/null
+++ b/spec/fixtures/safe_zip/valid-non-writeable.zip
Binary files differ
diff --git a/spec/fixtures/safe_zip/valid-simple.zip b/spec/fixtures/safe_zip/valid-simple.zip
new file mode 100644
index 00000000000..a56b8b41dcc
--- /dev/null
+++ b/spec/fixtures/safe_zip/valid-simple.zip
Binary files differ
diff --git a/spec/fixtures/safe_zip/valid-symlinks-first.zip b/spec/fixtures/safe_zip/valid-symlinks-first.zip
new file mode 100644
index 00000000000..f5952ef71c9
--- /dev/null
+++ b/spec/fixtures/safe_zip/valid-symlinks-first.zip
Binary files differ
diff --git a/spec/fixtures/security-reports/deprecated/gl-dependency-scanning-report.json b/spec/fixtures/security-reports/deprecated/gl-dependency-scanning-report.json
new file mode 100644
index 00000000000..ce66f562175
--- /dev/null
+++ b/spec/fixtures/security-reports/deprecated/gl-dependency-scanning-report.json
@@ -0,0 +1,178 @@
+[
+ {
+ "category": "dependency_scanning",
+ "name": "io.netty/netty - CVE-2014-3488",
+ "message": "DoS by CPU exhaustion when using malicious SSL packets",
+ "cve": "app/pom.xml:io.netty/netty@3.9.1.Final:CVE-2014-3488",
+ "severity": "Unknown",
+ "solution": "Upgrade to the latest version",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/pom.xml",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "value": "d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "url": "https://deps.sec.gitlab.com/packages/maven/io.netty/netty/versions/3.9.1.Final/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2014-3488",
+ "value": "CVE-2014-3488",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3488"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488"
+ },
+ {
+ "url": "http://netty.io/news/2014/06/11/3.html"
+ },
+ {
+ "url": "https://github.com/netty/netty/issues/2562"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/pom.xml",
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488",
+ "tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Django - CVE-2017-12794",
+ "message": "Possible XSS in traceback section of technical 500 debug page",
+ "cve": "app/requirements.txt:Django@1.11.3:CVE-2017-12794",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version or apply patch.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/requirements.txt",
+ "dependency": {
+ "package": {
+ "name": "Django"
+ },
+ "version": "1.11.3"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-6162a015-8635-4a15-8d7c-dc9321db366f",
+ "value": "6162a015-8635-4a15-8d7c-dc9321db366f",
+ "url": "https://deps.sec.gitlab.com/packages/pypi/Django/versions/1.11.3/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-12794",
+ "value": "CVE-2017-12794",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12794"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/requirements.txt",
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/",
+ "tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "nokogiri - USN-3424-1",
+ "message": "Vulnerabilities in libxml2",
+ "cve": "rails/Gemfile.lock:nokogiri@1.8.0:USN-3424-1",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "nokogiri"
+ },
+ "version": "1.8.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
+ "value": "06565b64-486d-4326-b906-890d9915804d",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ },
+ {
+ "type": "usn",
+ "name": "USN-3424-1",
+ "value": "USN-3424-1",
+ "url": "https://usn.ubuntu.com/3424-1/"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "rails/Gemfile.lock",
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673",
+ "tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "ffi - CVE-2018-1000201",
+ "message": "ruby-ffi DDL loading issue on Windows OS",
+ "cve": "ffi:1.9.18:CVE-2018-1000201",
+ "severity": "High",
+ "solution": "upgrade to \u003e= 1.9.24",
+ "scanner": {
+ "id": "bundler_audit",
+ "name": "bundler-audit"
+ },
+ "location": {
+ "file": "sast-sample-rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "ffi"
+ },
+ "version": "1.9.18"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "cve",
+ "name": "CVE-2018-1000201",
+ "value": "CVE-2018-1000201",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000201"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24"
+ }
+ ],
+ "priority": "High",
+ "file": "sast-sample-rails/Gemfile.lock",
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24",
+ "tool": "bundler_audit"
+ }
+]
diff --git a/spec/fixtures/security-reports/deprecated/gl-sast-report.json b/spec/fixtures/security-reports/deprecated/gl-sast-report.json
new file mode 100644
index 00000000000..a85b9be8b5f
--- /dev/null
+++ b/spec/fixtures/security-reports/deprecated/gl-sast-report.json
@@ -0,0 +1,944 @@
+[
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 1,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 47,
+ "end_line": 47,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken2"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 47,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 41,
+ "end_line": 41,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken1"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 41,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 11,
+ "end_line": 11
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 11,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 12,
+ "end_line": 12
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 12,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 13,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 14,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Pickle library appears to be in use, possible security issue.",
+ "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 15,
+ "end_line": 15
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B301",
+ "value": "B301"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 15,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "ECB mode is insecure",
+ "message": "ECB mode is insecure",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-ECB_MODE",
+ "value": "ECB_MODE",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Cipher with no integrity",
+ "message": "Cipher with no integrity",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-CIPHER_INTEGRITY",
+ "value": "CIPHER_INTEGRITY",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 14,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 10,
+ "end_line": 10
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 10,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports.py",
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports.py",
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 22,
+ "end_line": 22
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B106",
+ "value": "B106",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 22,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'root'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 5,
+ "end_line": 5
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 5,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: ''",
+ "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 13,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 23,
+ "end_line": 23
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 23,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 24,
+ "end_line": 24
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 24,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-function.py",
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-function.py",
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 7,
+ "end_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
+ "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B602",
+ "value": "B602",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 1,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 7,
+ "end_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with loads module.",
+ "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "c/subdir/utils.c",
+ "line": 4,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
+ "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
+ "confidence": "Low",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-362",
+ "value": "362",
+ "url": "https://cwe.mitre.org/data/definitions/362.html"
+ }
+ ],
+ "file": "c/subdir/utils.c",
+ "line": 8,
+ "url": "https://cwe.mitre.org/data/definitions/362.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "cplusplus/src/hello.cpp",
+ "line": 6,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
+ "confidence": "Low",
+ "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "cplusplus/src/hello.cpp",
+ "line": 7,
+ "url": "https://cwe.mitre.org/data/definitions/120.html",
+ "tool": "flawfinder"
+ }
+]
diff --git a/spec/fixtures/security-reports/feature-branch.zip b/spec/fixtures/security-reports/feature-branch.zip
index 730ce3dc5f8..dd49f4e9e1d 100644
--- a/spec/fixtures/security-reports/feature-branch.zip
+++ b/spec/fixtures/security-reports/feature-branch.zip
Binary files differ
diff --git a/spec/fixtures/security-reports/feature-branch/gl-container-scanning-report.json b/spec/fixtures/security-reports/feature-branch/gl-container-scanning-report.json
index 9840382df6f..6f89d20d4bf 100644
--- a/spec/fixtures/security-reports/feature-branch/gl-container-scanning-report.json
+++ b/spec/fixtures/security-reports/feature-branch/gl-container-scanning-report.json
@@ -1,18 +1,16 @@
{
- "image": "registry.gitlab.com/bikebilly/auto-devops-10-6/feature-branch:e7315ba964febb11bac8f5cd6ec433db8a3a1583",
- "unapproved": [
- "CVE-2017-15650"
- ],
- "vulnerabilities": [
- {
- "featurename": "musl",
- "featureversion": "1.1.14-r15",
- "vulnerability": "CVE-2017-15650",
- "namespace": "alpine:v3.4",
- "description": "",
- "link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15650",
- "severity": "Medium",
- "fixedby": "1.1.14-r16"
- }
- ]
+ "image": "registry.gitlab.com/bikebilly/auto-devops-10-6/feature-branch:e7315ba964febb11bac8f5cd6ec433db8a3a1583",
+ "unapproved": ["CVE-2017-15650"],
+ "vulnerabilities": [
+ {
+ "featurename": "musl",
+ "featureversion": "1.1.14-r15",
+ "vulnerability": "CVE-2017-15650",
+ "namespace": "alpine:v3.4",
+ "description": "",
+ "link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15650",
+ "severity": "Medium",
+ "fixedby": "1.1.14-r16"
+ }
+ ]
}
diff --git a/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json b/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json
index ce66f562175..8555be6618c 100644
--- a/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json
+++ b/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json
@@ -1,178 +1,181 @@
-[
- {
- "category": "dependency_scanning",
- "name": "io.netty/netty - CVE-2014-3488",
- "message": "DoS by CPU exhaustion when using malicious SSL packets",
- "cve": "app/pom.xml:io.netty/netty@3.9.1.Final:CVE-2014-3488",
- "severity": "Unknown",
- "solution": "Upgrade to the latest version",
- "scanner": {
- "id": "gemnasium",
- "name": "Gemnasium"
- },
- "location": {
- "file": "app/pom.xml",
- "dependency": {
- "package": {
- "name": "io.netty/netty"
+{
+ "version": "1.3",
+ "vulnerabilities": [
+ {
+ "category": "dependency_scanning",
+ "name": "io.netty/netty - CVE-2014-3488",
+ "message": "DoS by CPU exhaustion when using malicious SSL packets",
+ "cve": "app/pom.xml:io.netty/netty@3.9.1.Final:CVE-2014-3488",
+ "severity": "Unknown",
+ "solution": "Upgrade to the latest version",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/pom.xml",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "value": "d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "url": "https://deps.sec.gitlab.com/packages/maven/io.netty/netty/versions/3.9.1.Final/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2014-3488",
+ "value": "CVE-2014-3488",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3488"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488"
},
- "version": "3.9.1.Final"
- }
+ {
+ "url": "http://netty.io/news/2014/06/11/3.html"
+ },
+ {
+ "url": "https://github.com/netty/netty/issues/2562"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/pom.xml",
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488",
+ "tool": "gemnasium"
},
- "identifiers": [
- {
- "type": "gemnasium",
- "name": "Gemnasium-d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
- "value": "d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
- "url": "https://deps.sec.gitlab.com/packages/maven/io.netty/netty/versions/3.9.1.Final/advisories"
- },
- {
- "type": "cve",
- "name": "CVE-2014-3488",
- "value": "CVE-2014-3488",
- "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3488"
- }
- ],
- "links": [
- {
- "url": "https://bugzilla.redhat.com/CVE-2014-3488"
+ {
+ "category": "dependency_scanning",
+ "name": "Django - CVE-2017-12794",
+ "message": "Possible XSS in traceback section of technical 500 debug page",
+ "cve": "app/requirements.txt:Django@1.11.3:CVE-2017-12794",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version or apply patch.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
},
- {
- "url": "http://netty.io/news/2014/06/11/3.html"
+ "location": {
+ "file": "app/requirements.txt",
+ "dependency": {
+ "package": {
+ "name": "Django"
+ },
+ "version": "1.11.3"
+ }
},
- {
- "url": "https://github.com/netty/netty/issues/2562"
- }
- ],
- "priority": "Unknown",
- "file": "app/pom.xml",
- "url": "https://bugzilla.redhat.com/CVE-2014-3488",
- "tool": "gemnasium"
- },
- {
- "category": "dependency_scanning",
- "name": "Django - CVE-2017-12794",
- "message": "Possible XSS in traceback section of technical 500 debug page",
- "cve": "app/requirements.txt:Django@1.11.3:CVE-2017-12794",
- "severity": "Unknown",
- "solution": "Upgrade to latest version or apply patch.",
- "scanner": {
- "id": "gemnasium",
- "name": "Gemnasium"
- },
- "location": {
- "file": "app/requirements.txt",
- "dependency": {
- "package": {
- "name": "Django"
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-6162a015-8635-4a15-8d7c-dc9321db366f",
+ "value": "6162a015-8635-4a15-8d7c-dc9321db366f",
+ "url": "https://deps.sec.gitlab.com/packages/pypi/Django/versions/1.11.3/advisories"
},
- "version": "1.11.3"
- }
+ {
+ "type": "cve",
+ "name": "CVE-2017-12794",
+ "value": "CVE-2017-12794",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12794"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/requirements.txt",
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/",
+ "tool": "gemnasium"
},
- "identifiers": [
- {
- "type": "gemnasium",
- "name": "Gemnasium-6162a015-8635-4a15-8d7c-dc9321db366f",
- "value": "6162a015-8635-4a15-8d7c-dc9321db366f",
- "url": "https://deps.sec.gitlab.com/packages/pypi/Django/versions/1.11.3/advisories"
+ {
+ "category": "dependency_scanning",
+ "name": "nokogiri - USN-3424-1",
+ "message": "Vulnerabilities in libxml2",
+ "cve": "rails/Gemfile.lock:nokogiri@1.8.0:USN-3424-1",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
},
- {
- "type": "cve",
- "name": "CVE-2017-12794",
- "value": "CVE-2017-12794",
- "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12794"
- }
- ],
- "links": [
- {
- "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/"
- }
- ],
- "priority": "Unknown",
- "file": "app/requirements.txt",
- "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/",
- "tool": "gemnasium"
- },
- {
- "category": "dependency_scanning",
- "name": "nokogiri - USN-3424-1",
- "message": "Vulnerabilities in libxml2",
- "cve": "rails/Gemfile.lock:nokogiri@1.8.0:USN-3424-1",
- "severity": "Unknown",
- "solution": "Upgrade to latest version.",
- "scanner": {
- "id": "gemnasium",
- "name": "Gemnasium"
- },
- "location": {
- "file": "rails/Gemfile.lock",
- "dependency": {
- "package": {
- "name": "nokogiri"
+ "location": {
+ "file": "rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "nokogiri"
+ },
+ "version": "1.8.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
+ "value": "06565b64-486d-4326-b906-890d9915804d",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
},
- "version": "1.8.0"
- }
+ {
+ "type": "usn",
+ "name": "USN-3424-1",
+ "value": "USN-3424-1",
+ "url": "https://usn.ubuntu.com/3424-1/"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "rails/Gemfile.lock",
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673",
+ "tool": "gemnasium"
},
- "identifiers": [
- {
- "type": "gemnasium",
- "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
- "value": "06565b64-486d-4326-b906-890d9915804d",
- "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ {
+ "category": "dependency_scanning",
+ "name": "ffi - CVE-2018-1000201",
+ "message": "ruby-ffi DDL loading issue on Windows OS",
+ "cve": "ffi:1.9.18:CVE-2018-1000201",
+ "severity": "High",
+ "solution": "upgrade to \u003e= 1.9.24",
+ "scanner": {
+ "id": "bundler_audit",
+ "name": "bundler-audit"
},
- {
- "type": "usn",
- "name": "USN-3424-1",
- "value": "USN-3424-1",
- "url": "https://usn.ubuntu.com/3424-1/"
- }
- ],
- "links": [
- {
- "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
- }
- ],
- "priority": "Unknown",
- "file": "rails/Gemfile.lock",
- "url": "https://github.com/sparklemotion/nokogiri/issues/1673",
- "tool": "gemnasium"
- },
- {
- "category": "dependency_scanning",
- "name": "ffi - CVE-2018-1000201",
- "message": "ruby-ffi DDL loading issue on Windows OS",
- "cve": "ffi:1.9.18:CVE-2018-1000201",
- "severity": "High",
- "solution": "upgrade to \u003e= 1.9.24",
- "scanner": {
- "id": "bundler_audit",
- "name": "bundler-audit"
- },
- "location": {
+ "location": {
+ "file": "sast-sample-rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "ffi"
+ },
+ "version": "1.9.18"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "cve",
+ "name": "CVE-2018-1000201",
+ "value": "CVE-2018-1000201",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000201"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24"
+ }
+ ],
+ "priority": "High",
"file": "sast-sample-rails/Gemfile.lock",
- "dependency": {
- "package": {
- "name": "ffi"
- },
- "version": "1.9.18"
- }
- },
- "identifiers": [
- {
- "type": "cve",
- "name": "CVE-2018-1000201",
- "value": "CVE-2018-1000201",
- "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000201"
- }
- ],
- "links": [
- {
- "url": "https://github.com/ffi/ffi/releases/tag/1.9.24"
- }
- ],
- "priority": "High",
- "file": "sast-sample-rails/Gemfile.lock",
- "url": "https://github.com/ffi/ffi/releases/tag/1.9.24",
- "tool": "bundler_audit"
- }
-]
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24",
+ "tool": "bundler_audit"
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/feature-branch/gl-license-management-report.json b/spec/fixtures/security-reports/feature-branch/gl-license-management-report.json
index c1d20fa02fa..5fd81fd69bd 100644
--- a/spec/fixtures/security-reports/feature-branch/gl-license-management-report.json
+++ b/spec/fixtures/security-reports/feature-branch/gl-license-management-report.json
@@ -1,16 +1,12 @@
{
"licenses": [
{
- "count": 13,
- "name": "MIT"
- },
- {
- "count": 2,
- "name": "New BSD"
+ "count": 1,
+ "name": "WTFPL"
},
{
"count": 1,
- "name": "LGPL"
+ "name": "MIT"
}
],
"dependencies": [
@@ -20,107 +16,9 @@
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
- "name": "bundler",
- "url": "http://bundler.io",
- "description": "The best way to manage your application's dependencies",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "concurrent-ruby",
- "url": "http://www.concurrent-ruby.com",
- "description": "Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell, F#, C#, Java, and classic concurrency patterns.",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "connection_pool",
- "url": "https://github.com/mperham/connection_pool",
- "description": "Generic connection pool for Ruby",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "mini_portile2",
- "url": "http://github.com/flavorjones/mini_portile",
- "description": "Simplistic port-like solution for developers",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "mustermann",
- "url": "https://github.com/sinatra/mustermann",
- "description": "Your personal string matching expert.",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "nokogiri",
- "url": "http://nokogiri.org",
- "description": "Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "New BSD",
- "url": "http://opensource.org/licenses/BSD-3-Clause"
- },
- "dependency": {
- "name": "pg",
- "url": "https://bitbucket.org/ged/ruby-pg",
- "description": "Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/]",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "New BSD",
- "url": "http://opensource.org/licenses/BSD-3-Clause"
- },
- "dependency": {
- "name": "puma",
- "url": "http://puma.io",
- "description": "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications",
+ "name": "actioncable",
+ "url": "http://rubyonrails.org",
+ "description": "WebSocket framework for Rails.",
"pathes": [
"."
]
@@ -128,111 +26,13 @@
},
{
"license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "rack",
- "url": "https://rack.github.io/",
- "description": "a modular Ruby webserver interface",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "rack-protection",
- "url": "http://github.com/sinatra/sinatra/tree/master/rack-protection",
- "description": "Protect against typical web attacks, works with all Rack apps, including Rails.",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "redis",
- "url": "https://github.com/redis/redis-rb",
- "description": "A Ruby client library for Redis",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "LGPL",
- "url": "http://www.gnu.org/licenses/lgpl.txt"
- },
- "dependency": {
- "name": "sidekiq",
- "url": "http://sidekiq.org",
- "description": "Simple, efficient background processing for Ruby",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "sinatra",
- "url": "http://www.sinatrarb.com/",
- "description": "Classy web-development dressed in a DSL",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "slim",
- "url": "http://slim-lang.com/",
- "description": "Slim is a template language.",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
- },
- "dependency": {
- "name": "temple",
- "url": "https://github.com/judofyr/temple",
- "description": "Template compilation framework in Ruby",
- "pathes": [
- "."
- ]
- }
- },
- {
- "license": {
- "name": "MIT",
- "url": "http://opensource.org/licenses/mit-license"
+ "name": "WTFPL",
+ "url": "http://www.wtfpl.net/"
},
"dependency": {
- "name": "tilt",
- "url": "http://github.com/rtomayko/tilt/",
- "description": "Generic interface to multiple Ruby template engines",
+ "name": "wtfpl_init",
+ "url": "https://rubygems.org/gems/wtfpl_init",
+ "description": "Download WTFPL license file and rename to LICENSE.md or something",
"pathes": [
"."
]
diff --git a/spec/fixtures/security-reports/feature-branch/gl-sast-report.json b/spec/fixtures/security-reports/feature-branch/gl-sast-report.json
index a85b9be8b5f..4bef3d22f70 100644
--- a/spec/fixtures/security-reports/feature-branch/gl-sast-report.json
+++ b/spec/fixtures/security-reports/feature-branch/gl-sast-report.json
@@ -1,944 +1,947 @@
-[
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+{
+ "version": "1.2",
+ "vulnerabilities": [
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 1,
- "end_line": 1
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 1,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "name": "Predictable pseudorandom number generator",
- "message": "Predictable pseudorandom number generator",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
+ "line": 1,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 47,
+ "end_line": 47,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken2"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 47,
- "end_line": 47,
- "class": "com.gitlab.security_products.tests.App",
- "method": "generateSecretToken2"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-PREDICTABLE_RANDOM",
- "value": "PREDICTABLE_RANDOM",
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 47,
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "name": "Predictable pseudorandom number generator",
- "message": "Predictable pseudorandom number generator",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
+ "line": 47,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 41,
+ "end_line": 41,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken1"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 41,
- "end_line": 41,
- "class": "com.gitlab.security_products.tests.App",
- "method": "generateSecretToken1"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-PREDICTABLE_RANDOM",
- "value": "PREDICTABLE_RANDOM",
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 41,
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 41,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 11,
+ "end_line": 11
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 11,
- "end_line": 11
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 11,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 11,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 12,
+ "end_line": 12
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 12,
- "end_line": 12
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 12,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 12,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 13,
- "end_line": 13
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 13,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 13,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 14,
- "end_line": 14
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 14,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Pickle library appears to be in use, possible security issue.",
- "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 14,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Pickle library appears to be in use, possible security issue.",
+ "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 15,
+ "end_line": 15
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B301",
+ "value": "B301"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 15,
- "end_line": 15
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B301",
- "value": "B301"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 15,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "name": "ECB mode is insecure",
- "message": "ECB mode is insecure",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
+ "line": 15,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "ECB mode is insecure",
+ "message": "ECB mode is insecure",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-ECB_MODE",
+ "value": "ECB_MODE",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
+ }
+ ],
+ "priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 29,
- "end_line": 29,
- "class": "com.gitlab.security_products.tests.App",
- "method": "insecureCypher"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-ECB_MODE",
- "value": "ECB_MODE",
- "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 29,
- "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "name": "Cipher with no integrity",
- "message": "Cipher with no integrity",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Cipher with no integrity",
+ "message": "Cipher with no integrity",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-CIPHER_INTEGRITY",
+ "value": "CIPHER_INTEGRITY",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
+ }
+ ],
+ "priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 29,
- "end_line": 29,
- "class": "com.gitlab.security_products.tests.App",
- "method": "insecureCypher"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-CIPHER_INTEGRITY",
- "value": "CIPHER_INTEGRITY",
- "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 29,
- "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 14,
- "end_line": 14
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 14,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 14,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 10,
+ "end_line": 10
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 10,
- "end_line": 10
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 10,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 10,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-aliases.py",
- "start_line": 1,
- "end_line": 1
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 1,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports.py",
- "start_line": 2,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports.py",
- "line": 2,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports.py",
- "start_line": 4,
- "end_line": 4
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports.py",
- "line": 4,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 22,
+ "end_line": 22
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B106",
+ "value": "B106",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 22,
- "end_line": 22
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B106",
- "value": "B106",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 22,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'root'",
- "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 22,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'root'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 5,
+ "end_line": 5
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 5,
- "end_line": 5
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 5,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: ''",
- "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 5,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: ''",
+ "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 9,
- "end_line": 9
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 9,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 13,
- "end_line": 13
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 13,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 13,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 23,
+ "end_line": 23
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 23,
- "end_line": 23
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 23,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 23,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 24,
+ "end_line": 24
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 24,
- "end_line": 24
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 24,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 24,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-function.py",
- "start_line": 4,
- "end_line": 4
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-function.py",
- "line": 4,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-function.py",
- "start_line": 2,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-function.py",
- "line": 2,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 7,
+ "end_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-from.py",
- "start_line": 7,
- "end_line": 7
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 7,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
- "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
+ "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B602",
+ "value": "B602",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-aliases.py",
- "start_line": 9,
- "end_line": 9
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B602",
- "value": "B602",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 9,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-from.py",
- "start_line": 6,
- "end_line": 6
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 6,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 1,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-from.py",
- "start_line": 1,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 1,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 7,
+ "end_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-aliases.py",
- "start_line": 7,
- "end_line": 8
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 7,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with loads module.",
- "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with loads module.",
+ "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-aliases.py",
- "start_line": 6,
- "end_line": 6
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 6,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
- "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
- "confidence": "Low",
- "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
"file": "c/subdir/utils.c",
- "start_line": 4
- },
- "identifiers": [
- {
- "type": "cwe",
- "name": "CWE-119",
- "value": "119",
- "url": "https://cwe.mitre.org/data/definitions/119.html"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "c/subdir/utils.c",
- "line": 4,
- "url": "https://cwe.mitre.org/data/definitions/119.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
- "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
- "confidence": "Low",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
+ "line": 4,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
+ "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
+ "confidence": "Low",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-362",
+ "value": "362",
+ "url": "https://cwe.mitre.org/data/definitions/362.html"
+ }
+ ],
"file": "c/subdir/utils.c",
- "start_line": 8
- },
- "identifiers": [
- {
- "type": "cwe",
- "name": "CWE-362",
- "value": "362",
- "url": "https://cwe.mitre.org/data/definitions/362.html"
- }
- ],
- "file": "c/subdir/utils.c",
- "line": 8,
- "url": "https://cwe.mitre.org/data/definitions/362.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
- "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
- "confidence": "Low",
- "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
+ "line": 8,
+ "url": "https://cwe.mitre.org/data/definitions/362.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
"file": "cplusplus/src/hello.cpp",
- "start_line": 6
- },
- "identifiers": [
- {
- "type": "cwe",
- "name": "CWE-119",
- "value": "119",
- "url": "https://cwe.mitre.org/data/definitions/119.html"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "cplusplus/src/hello.cpp",
- "line": 6,
- "url": "https://cwe.mitre.org/data/definitions/119.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
- "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
- "confidence": "Low",
- "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
+ "line": 6,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
+ "confidence": "Low",
+ "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
"file": "cplusplus/src/hello.cpp",
- "start_line": 7
- },
- "identifiers": [
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "cplusplus/src/hello.cpp",
- "line": 7,
- "url": "https://cwe.mitre.org/data/definitions/120.html",
- "tool": "flawfinder"
- }
-]
+ "line": 7,
+ "url": "https://cwe.mitre.org/data/definitions/120.html",
+ "tool": "flawfinder"
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/master.zip b/spec/fixtures/security-reports/master.zip
index 4684aecb738..2261b5a1674 100644
--- a/spec/fixtures/security-reports/master.zip
+++ b/spec/fixtures/security-reports/master.zip
Binary files differ
diff --git a/spec/fixtures/security-reports/master/gl-container-scanning-report.json b/spec/fixtures/security-reports/master/gl-container-scanning-report.json
index 500c19e3abb..03dfc647162 100644
--- a/spec/fixtures/security-reports/master/gl-container-scanning-report.json
+++ b/spec/fixtures/security-reports/master/gl-container-scanning-report.json
@@ -1,18 +1,105 @@
{
- "image": "registry.gitlab.com/bikebilly/auto-devops-10-6/feature-branch:e7315ba964febb11bac8f5cd6ec433db8a3a1583",
- "unapproved": [
- "CVE-2017-15651"
- ],
- "vulnerabilities": [
- {
- "featurename": "musl",
- "featureversion": "1.1.14-r15",
- "vulnerability": "CVE-2017-15651",
- "namespace": "alpine:v3.4",
- "description": "",
- "link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15651",
- "severity": "Medium",
- "fixedby": "1.1.14-r16"
- }
- ]
+ "image": "registry.gitlab.com/groulot/container-scanning-test/master:5f21de6956aee99ddb68ae49498662d9872f50ff",
+ "unapproved": [
+ "CVE-2017-18269",
+ "CVE-2017-16997",
+ "CVE-2018-1000001",
+ "CVE-2016-10228",
+ "CVE-2018-18520",
+ "CVE-2010-4052",
+ "CVE-2018-16869",
+ "CVE-2018-18311"
+ ],
+ "vulnerabilities": [
+ {
+ "featurename": "glibc",
+ "featureversion": "2.24-11+deb9u3",
+ "vulnerability": "CVE-2017-18269",
+ "namespace": "debian:9",
+ "description": "SSE2-optimized memmove implementation problem.",
+ "link": "https://security-tracker.debian.org/tracker/CVE-2017-18269",
+ "severity": "Defcon1",
+ "fixedby": "2.24-11+deb9u4"
+ },
+ {
+ "featurename": "glibc",
+ "featureversion": "2.24-11+deb9u3",
+ "vulnerability": "CVE-2017-16997",
+ "namespace": "debian:9",
+ "description": "elf/dl-load.c in the GNU C Library (aka glibc or libc6) 2.19 through 2.26 mishandles RPATH and RUNPATH containing $ORIGIN for a privileged (setuid or AT_SECURE) program, which allows local users to gain privileges via a Trojan horse library in the current working directory, related to the fillin_rpath and decompose_rpath functions. This is associated with misinterpretion of an empty RPATH/RUNPATH token as the \"./\" directory. NOTE: this configuration of RPATH/RUNPATH for a privileged program is apparently very uncommon; most likely, no such program is shipped with any common Linux distribution.",
+ "link": "https://security-tracker.debian.org/tracker/CVE-2017-16997",
+ "severity": "Critical",
+ "fixedby": ""
+ },
+ {
+ "featurename": "glibc",
+ "featureversion": "2.24-11+deb9u3",
+ "vulnerability": "CVE-2018-1000001",
+ "namespace": "debian:9",
+ "description": "In glibc 2.26 and earlier there is confusion in the usage of getcwd() by realpath() which can be used to write before the destination buffer leading to a buffer underflow and potential code execution.",
+ "link": "https://security-tracker.debian.org/tracker/CVE-2018-1000001",
+ "severity": "High",
+ "fixedby": ""
+ },
+ {
+ "featurename": "glibc",
+ "featureversion": "2.24-11+deb9u3",
+ "vulnerability": "CVE-2016-10228",
+ "namespace": "debian:9",
+ "description": "The iconv program in the GNU C Library (aka glibc or libc6) 2.25 and earlier, when invoked with the -c option, enters an infinite loop when processing invalid multi-byte input sequences, leading to a denial of service.",
+ "link": "https://security-tracker.debian.org/tracker/CVE-2016-10228",
+ "severity": "Medium",
+ "fixedby": ""
+ },
+ {
+ "featurename": "elfutils",
+ "featureversion": "0.168-1",
+ "vulnerability": "CVE-2018-18520",
+ "namespace": "debian:9",
+ "description": "An Invalid Memory Address Dereference exists in the function elf_end in libelf in elfutils through v0.174. Although eu-size is intended to support ar files inside ar files, handle_ar in size.c closes the outer ar file before handling all inner entries. The vulnerability allows attackers to cause a denial of service (application crash) with a crafted ELF file.",
+ "link": "https://security-tracker.debian.org/tracker/CVE-2018-18520",
+ "severity": "Low",
+ "fixedby": ""
+ },
+ {
+ "featurename": "glibc",
+ "featureversion": "2.24-11+deb9u3",
+ "vulnerability": "CVE-2010-4052",
+ "namespace": "debian:9",
+ "description": "Stack consumption vulnerability in the regcomp implementation in the GNU C Library (aka glibc or libc6) through 2.11.3, and 2.12.x through 2.12.2, allows context-dependent attackers to cause a denial of service (resource exhaustion) via a regular expression containing adjacent repetition operators, as demonstrated by a {10,}{10,}{10,}{10,} sequence in the proftpd.gnu.c exploit for ProFTPD.",
+ "link": "https://security-tracker.debian.org/tracker/CVE-2010-4052",
+ "severity": "Negligible",
+ "fixedby": ""
+ },
+ {
+ "featurename": "nettle",
+ "featureversion": "3.3-1",
+ "vulnerability": "CVE-2018-16869",
+ "namespace": "debian:9",
+ "description": "A Bleichenbacher type side-channel based padding oracle attack was found in the way nettle handles endian conversion of RSA decrypted PKCS#1 v1.5 data. An attacker who is able to run a process on the same physical core as the victim process, could use this flaw extract plaintext or in some cases downgrade any TLS connections to a vulnerable server.",
+ "link": "https://security-tracker.debian.org/tracker/CVE-2018-16869",
+ "severity": "Unknown",
+ "fixedby": ""
+ },
+ {
+ "featurename": "perl",
+ "featureversion": "5.24.1-3+deb9u4",
+ "vulnerability": "CVE-2018-18311",
+ "namespace": "debian:9",
+ "description": "Perl before 5.26.3 and 5.28.x before 5.28.1 has a buffer overflow via a crafted regular expression that triggers invalid write operations.",
+ "link": "https://security-tracker.debian.org/tracker/CVE-2018-18311",
+ "severity": "Unknown",
+ "fixedby": "5.24.1-3+deb9u5"
+ },
+ {
+ "featurename": "foo",
+ "featureversion": "1.3",
+ "vulnerability": "CVE-2018-666",
+ "namespace": "debian:9",
+ "description": "Foo has a vulnerability nobody cares about and whitelist.",
+ "link": "https://security-tracker.debian.org/tracker/CVE-2018-666",
+ "severity": "Unknown",
+ "fixedby": "1.4"
+ }
+ ]
}
diff --git a/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json b/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json
index ce66f562175..8555be6618c 100644
--- a/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json
+++ b/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json
@@ -1,178 +1,181 @@
-[
- {
- "category": "dependency_scanning",
- "name": "io.netty/netty - CVE-2014-3488",
- "message": "DoS by CPU exhaustion when using malicious SSL packets",
- "cve": "app/pom.xml:io.netty/netty@3.9.1.Final:CVE-2014-3488",
- "severity": "Unknown",
- "solution": "Upgrade to the latest version",
- "scanner": {
- "id": "gemnasium",
- "name": "Gemnasium"
- },
- "location": {
- "file": "app/pom.xml",
- "dependency": {
- "package": {
- "name": "io.netty/netty"
+{
+ "version": "1.3",
+ "vulnerabilities": [
+ {
+ "category": "dependency_scanning",
+ "name": "io.netty/netty - CVE-2014-3488",
+ "message": "DoS by CPU exhaustion when using malicious SSL packets",
+ "cve": "app/pom.xml:io.netty/netty@3.9.1.Final:CVE-2014-3488",
+ "severity": "Unknown",
+ "solution": "Upgrade to the latest version",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/pom.xml",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "value": "d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "url": "https://deps.sec.gitlab.com/packages/maven/io.netty/netty/versions/3.9.1.Final/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2014-3488",
+ "value": "CVE-2014-3488",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3488"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488"
},
- "version": "3.9.1.Final"
- }
+ {
+ "url": "http://netty.io/news/2014/06/11/3.html"
+ },
+ {
+ "url": "https://github.com/netty/netty/issues/2562"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/pom.xml",
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488",
+ "tool": "gemnasium"
},
- "identifiers": [
- {
- "type": "gemnasium",
- "name": "Gemnasium-d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
- "value": "d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
- "url": "https://deps.sec.gitlab.com/packages/maven/io.netty/netty/versions/3.9.1.Final/advisories"
- },
- {
- "type": "cve",
- "name": "CVE-2014-3488",
- "value": "CVE-2014-3488",
- "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3488"
- }
- ],
- "links": [
- {
- "url": "https://bugzilla.redhat.com/CVE-2014-3488"
+ {
+ "category": "dependency_scanning",
+ "name": "Django - CVE-2017-12794",
+ "message": "Possible XSS in traceback section of technical 500 debug page",
+ "cve": "app/requirements.txt:Django@1.11.3:CVE-2017-12794",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version or apply patch.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
},
- {
- "url": "http://netty.io/news/2014/06/11/3.html"
+ "location": {
+ "file": "app/requirements.txt",
+ "dependency": {
+ "package": {
+ "name": "Django"
+ },
+ "version": "1.11.3"
+ }
},
- {
- "url": "https://github.com/netty/netty/issues/2562"
- }
- ],
- "priority": "Unknown",
- "file": "app/pom.xml",
- "url": "https://bugzilla.redhat.com/CVE-2014-3488",
- "tool": "gemnasium"
- },
- {
- "category": "dependency_scanning",
- "name": "Django - CVE-2017-12794",
- "message": "Possible XSS in traceback section of technical 500 debug page",
- "cve": "app/requirements.txt:Django@1.11.3:CVE-2017-12794",
- "severity": "Unknown",
- "solution": "Upgrade to latest version or apply patch.",
- "scanner": {
- "id": "gemnasium",
- "name": "Gemnasium"
- },
- "location": {
- "file": "app/requirements.txt",
- "dependency": {
- "package": {
- "name": "Django"
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-6162a015-8635-4a15-8d7c-dc9321db366f",
+ "value": "6162a015-8635-4a15-8d7c-dc9321db366f",
+ "url": "https://deps.sec.gitlab.com/packages/pypi/Django/versions/1.11.3/advisories"
},
- "version": "1.11.3"
- }
+ {
+ "type": "cve",
+ "name": "CVE-2017-12794",
+ "value": "CVE-2017-12794",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12794"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/requirements.txt",
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/",
+ "tool": "gemnasium"
},
- "identifiers": [
- {
- "type": "gemnasium",
- "name": "Gemnasium-6162a015-8635-4a15-8d7c-dc9321db366f",
- "value": "6162a015-8635-4a15-8d7c-dc9321db366f",
- "url": "https://deps.sec.gitlab.com/packages/pypi/Django/versions/1.11.3/advisories"
+ {
+ "category": "dependency_scanning",
+ "name": "nokogiri - USN-3424-1",
+ "message": "Vulnerabilities in libxml2",
+ "cve": "rails/Gemfile.lock:nokogiri@1.8.0:USN-3424-1",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
},
- {
- "type": "cve",
- "name": "CVE-2017-12794",
- "value": "CVE-2017-12794",
- "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12794"
- }
- ],
- "links": [
- {
- "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/"
- }
- ],
- "priority": "Unknown",
- "file": "app/requirements.txt",
- "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/",
- "tool": "gemnasium"
- },
- {
- "category": "dependency_scanning",
- "name": "nokogiri - USN-3424-1",
- "message": "Vulnerabilities in libxml2",
- "cve": "rails/Gemfile.lock:nokogiri@1.8.0:USN-3424-1",
- "severity": "Unknown",
- "solution": "Upgrade to latest version.",
- "scanner": {
- "id": "gemnasium",
- "name": "Gemnasium"
- },
- "location": {
- "file": "rails/Gemfile.lock",
- "dependency": {
- "package": {
- "name": "nokogiri"
+ "location": {
+ "file": "rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "nokogiri"
+ },
+ "version": "1.8.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
+ "value": "06565b64-486d-4326-b906-890d9915804d",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
},
- "version": "1.8.0"
- }
+ {
+ "type": "usn",
+ "name": "USN-3424-1",
+ "value": "USN-3424-1",
+ "url": "https://usn.ubuntu.com/3424-1/"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "rails/Gemfile.lock",
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673",
+ "tool": "gemnasium"
},
- "identifiers": [
- {
- "type": "gemnasium",
- "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
- "value": "06565b64-486d-4326-b906-890d9915804d",
- "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ {
+ "category": "dependency_scanning",
+ "name": "ffi - CVE-2018-1000201",
+ "message": "ruby-ffi DDL loading issue on Windows OS",
+ "cve": "ffi:1.9.18:CVE-2018-1000201",
+ "severity": "High",
+ "solution": "upgrade to \u003e= 1.9.24",
+ "scanner": {
+ "id": "bundler_audit",
+ "name": "bundler-audit"
},
- {
- "type": "usn",
- "name": "USN-3424-1",
- "value": "USN-3424-1",
- "url": "https://usn.ubuntu.com/3424-1/"
- }
- ],
- "links": [
- {
- "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
- }
- ],
- "priority": "Unknown",
- "file": "rails/Gemfile.lock",
- "url": "https://github.com/sparklemotion/nokogiri/issues/1673",
- "tool": "gemnasium"
- },
- {
- "category": "dependency_scanning",
- "name": "ffi - CVE-2018-1000201",
- "message": "ruby-ffi DDL loading issue on Windows OS",
- "cve": "ffi:1.9.18:CVE-2018-1000201",
- "severity": "High",
- "solution": "upgrade to \u003e= 1.9.24",
- "scanner": {
- "id": "bundler_audit",
- "name": "bundler-audit"
- },
- "location": {
+ "location": {
+ "file": "sast-sample-rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "ffi"
+ },
+ "version": "1.9.18"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "cve",
+ "name": "CVE-2018-1000201",
+ "value": "CVE-2018-1000201",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000201"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24"
+ }
+ ],
+ "priority": "High",
"file": "sast-sample-rails/Gemfile.lock",
- "dependency": {
- "package": {
- "name": "ffi"
- },
- "version": "1.9.18"
- }
- },
- "identifiers": [
- {
- "type": "cve",
- "name": "CVE-2018-1000201",
- "value": "CVE-2018-1000201",
- "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000201"
- }
- ],
- "links": [
- {
- "url": "https://github.com/ffi/ffi/releases/tag/1.9.24"
- }
- ],
- "priority": "High",
- "file": "sast-sample-rails/Gemfile.lock",
- "url": "https://github.com/ffi/ffi/releases/tag/1.9.24",
- "tool": "bundler_audit"
- }
-]
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24",
+ "tool": "bundler_audit"
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/master/gl-license-management-report.json b/spec/fixtures/security-reports/master/gl-license-management-report.json
index fe91e4fb7ee..e0de6f58fdf 100644
--- a/spec/fixtures/security-reports/master/gl-license-management-report.json
+++ b/spec/fixtures/security-reports/master/gl-license-management-report.json
@@ -1,8 +1,20 @@
{
"licenses": [
{
- "count": 10,
+ "count": 52,
"name": "MIT"
+ },
+ {
+ "count": 3,
+ "name": "New BSD"
+ },
+ {
+ "count": 1,
+ "name": "Apache 2.0"
+ },
+ {
+ "count": 1,
+ "name": "unknown"
}
],
"dependencies": [
@@ -12,6 +24,369 @@
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
+ "name": "actioncable",
+ "url": "http://rubyonrails.org",
+ "description": "WebSocket framework for Rails.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "actionmailer",
+ "url": "http://rubyonrails.org",
+ "description": "Email composition, delivery, and receiving framework (part of Rails).",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "actionpack",
+ "url": "http://rubyonrails.org",
+ "description": "Web-flow and rendering framework putting the VC in MVC (part of Rails).",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "actionview",
+ "url": "http://rubyonrails.org",
+ "description": "Rendering framework putting the V in MVC (part of Rails).",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "activejob",
+ "url": "http://rubyonrails.org",
+ "description": "Job framework with pluggable queues.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "activemodel",
+ "url": "http://rubyonrails.org",
+ "description": "A toolkit for building modeling frameworks (part of Rails).",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "activerecord",
+ "url": "http://rubyonrails.org",
+ "description": "Object-relational mapper framework (part of Rails).",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "activesupport",
+ "url": "http://rubyonrails.org",
+ "description": "A toolkit of support libraries and Ruby core extensions extracted from the Rails framework.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "arel",
+ "url": "https://github.com/rails/arel",
+ "description": "Arel Really Exasperates Logicians Arel is a SQL AST manager for Ruby",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "builder",
+ "url": "http://onestepback.org",
+ "description": "Builders for MarkUp.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "bundler",
+ "url": "http://bundler.io",
+ "description": "The best way to manage your application's dependencies",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "coffee-rails",
+ "url": "https://github.com/rails/coffee-rails",
+ "description": "CoffeeScript adapter for the Rails asset pipeline.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "coffee-script",
+ "url": "http://github.com/josh/ruby-coffee-script",
+ "description": "Ruby CoffeeScript Compiler",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "coffee-script-source",
+ "url": "http://coffeescript.org",
+ "description": "The CoffeeScript Compiler",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "concurrent-ruby",
+ "url": "http://www.concurrent-ruby.com",
+ "description": "Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell, F#, C#, Java, and classic concurrency patterns.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "crass",
+ "url": "https://github.com/rgrove/crass/",
+ "description": "CSS parser based on the CSS Syntax Level 3 spec.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "erubis",
+ "url": "http://www.kuwata-lab.com/erubis/",
+ "description": "a fast and extensible eRuby implementation which supports multi-language",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "execjs",
+ "url": "https://github.com/rails/execjs",
+ "description": "Run JavaScript code from Ruby",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "New BSD",
+ "url": "http://opensource.org/licenses/BSD-3-Clause"
+ },
+ "dependency": {
+ "name": "ffi",
+ "url": "http://wiki.github.com/ffi/ffi",
+ "description": "Ruby FFI",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "globalid",
+ "url": "http://www.rubyonrails.org",
+ "description": "Refer to any model with a URI: gid://app/class/id",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "i18n",
+ "url": "http://github.com/svenfuchs/i18n",
+ "description": "New wave Internationalization support for Ruby",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "jbuilder",
+ "url": "https://github.com/rails/jbuilder",
+ "description": "Create JSON structures via a Builder-style DSL",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "loofah",
+ "description": "",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "mail",
+ "url": "https://github.com/mikel/mail",
+ "description": "Mail provides a nice Ruby DSL for making, sending and reading emails.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "method_source",
+ "url": "http://banisterfiend.wordpress.com",
+ "description": "retrieve the sourcecode for a method",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "mini_mime",
+ "url": "https://github.com/discourse/mini_mime",
+ "description": "A lightweight mime type lookup toy",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
"name": "mini_portile2",
"url": "http://github.com/flavorjones/mini_portile",
"description": "Simplistic port-like solution for developers",
@@ -26,9 +401,37 @@
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
- "name": "mustermann",
- "url": "https://github.com/sinatra/mustermann",
- "description": "Your personal string matching expert.",
+ "name": "minitest",
+ "url": "https://github.com/seattlerb/minitest",
+ "description": "minitest provides a complete suite of testing facilities supporting TDD, BDD, mocking, and benchmarking",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "multi_json",
+ "url": "http://github.com/intridea/multi_json",
+ "description": "A common interface to multiple JSON libraries.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "nio4r",
+ "url": "https://github.com/celluloid/nio4r",
+ "description": "NIO provides a high performance selector API for monitoring IO objects",
"pathes": [
"."
]
@@ -50,6 +453,20 @@
},
{
"license": {
+ "name": "New BSD",
+ "url": "http://opensource.org/licenses/BSD-3-Clause"
+ },
+ "dependency": {
+ "name": "puma",
+ "url": "http://puma.io",
+ "description": "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
@@ -68,9 +485,147 @@
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
- "name": "rack-protection",
- "url": "http://github.com/sinatra/sinatra/tree/master/rack-protection",
- "description": "Protect against typical web attacks, works with all Rack apps, including Rails.",
+ "name": "rack-test",
+ "url": "http://github.com/brynary/rack-test",
+ "description": "Simple testing API built on Rack",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rails",
+ "url": "http://rubyonrails.org",
+ "description": "Full-stack web application framework.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rails-dom-testing",
+ "url": "https://github.com/rails/rails-dom-testing",
+ "description": "Dom and Selector assertions for Rails applications",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rails-html-sanitizer",
+ "url": "https://github.com/rails/rails-html-sanitizer",
+ "description": "This gem is responsible to sanitize HTML fragments in Rails applications.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "railties",
+ "url": "http://rubyonrails.org",
+ "description": "Tools for creating, working with, and running Rails applications.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rake",
+ "url": "https://github.com/ruby/rake",
+ "description": "Rake is a Make-like program implemented in Ruby",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rb-fsevent",
+ "url": "http://rubygems.org/gems/rb-fsevent",
+ "description": "Very simple & usable FSEvents API",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rb-inotify",
+ "url": "https://github.com/guard/rb-inotify",
+ "description": "A Ruby wrapper for Linux inotify, using FFI",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "unknown"
+ },
+ "dependency": {
+ "name": "ruby-bundler-rails",
+ "description": "",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "sass",
+ "url": "http://sass-lang.com/",
+ "description": "A powerful but elegant CSS compiler that makes CSS fun again.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "sass-listen",
+ "url": "https://github.com/sass/listen",
+ "description": "Fork of guard/listen",
"pathes": [
"."
]
@@ -82,9 +637,9 @@
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
- "name": "redis",
- "url": "https://github.com/redis/redis-rb",
- "description": "A Ruby client library for Redis",
+ "name": "sass-rails",
+ "url": "https://github.com/rails/sass-rails",
+ "description": "Sass adapter for the Rails asset pipeline.",
"pathes": [
"."
]
@@ -96,9 +651,9 @@
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
- "name": "sinatra",
- "url": "http://www.sinatrarb.com/",
- "description": "Classy web-development dressed in a DSL",
+ "name": "sprockets",
+ "url": "https://github.com/rails/sprockets",
+ "description": "Rack-based asset packaging system",
"pathes": [
"."
]
@@ -110,9 +665,23 @@
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
- "name": "slim",
- "url": "http://slim-lang.com/",
- "description": "Slim is a template language.",
+ "name": "sprockets-rails",
+ "url": "https://github.com/rails/sprockets-rails",
+ "description": "Sprockets Rails integration",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "New BSD",
+ "url": "http://opensource.org/licenses/BSD-3-Clause"
+ },
+ "dependency": {
+ "name": "sqlite3",
+ "url": "https://github.com/sparklemotion/sqlite3-ruby",
+ "description": "This module allows Ruby programs to interface with the SQLite3 database engine (http://www.sqlite.org)",
"pathes": [
"."
]
@@ -124,9 +693,23 @@
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
- "name": "temple",
- "url": "https://github.com/judofyr/temple",
- "description": "Template compilation framework in Ruby",
+ "name": "thor",
+ "url": "http://whatisthor.com/",
+ "description": "Thor is a toolkit for building powerful command-line interfaces.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.txt"
+ },
+ "dependency": {
+ "name": "thread_safe",
+ "url": "https://github.com/ruby-concurrency/thread_safe",
+ "description": "Thread-safe collections and utilities for Ruby",
"pathes": [
"."
]
@@ -145,6 +728,90 @@
"."
]
}
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "turbolinks",
+ "url": "https://github.com/turbolinks/turbolinks",
+ "description": "Turbolinks makes navigating your web application faster",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "turbolinks-source",
+ "url": "https://github.com/turbolinks/turbolinks-source-gem",
+ "description": "Turbolinks JavaScript assets",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "tzinfo",
+ "url": "http://tzinfo.github.io",
+ "description": "Daylight savings aware timezone library",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "uglifier",
+ "url": "http://github.com/lautis/uglifier",
+ "description": "Ruby wrapper for UglifyJS JavaScript compressor",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "websocket-driver",
+ "url": "http://github.com/faye/websocket-driver-ruby",
+ "description": "WebSocket protocol handler with pluggable I/O",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "websocket-extensions",
+ "url": "https://github.com/faye/websocket-extensions-ruby",
+ "description": "Generic extension manager for WebSocket connections",
+ "pathes": [
+ "."
+ ]
+ }
}
]
}
diff --git a/spec/fixtures/security-reports/master/gl-sast-report.json b/spec/fixtures/security-reports/master/gl-sast-report.json
index a85b9be8b5f..4bef3d22f70 100644
--- a/spec/fixtures/security-reports/master/gl-sast-report.json
+++ b/spec/fixtures/security-reports/master/gl-sast-report.json
@@ -1,944 +1,947 @@
-[
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+{
+ "version": "1.2",
+ "vulnerabilities": [
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 1,
- "end_line": 1
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 1,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "name": "Predictable pseudorandom number generator",
- "message": "Predictable pseudorandom number generator",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
+ "line": 1,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 47,
+ "end_line": 47,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken2"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 47,
- "end_line": 47,
- "class": "com.gitlab.security_products.tests.App",
- "method": "generateSecretToken2"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-PREDICTABLE_RANDOM",
- "value": "PREDICTABLE_RANDOM",
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 47,
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "name": "Predictable pseudorandom number generator",
- "message": "Predictable pseudorandom number generator",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
+ "line": 47,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 41,
+ "end_line": 41,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken1"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 41,
- "end_line": 41,
- "class": "com.gitlab.security_products.tests.App",
- "method": "generateSecretToken1"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-PREDICTABLE_RANDOM",
- "value": "PREDICTABLE_RANDOM",
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 41,
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 41,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 11,
+ "end_line": 11
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 11,
- "end_line": 11
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 11,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 11,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 12,
+ "end_line": 12
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 12,
- "end_line": 12
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 12,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 12,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 13,
- "end_line": 13
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 13,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 13,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 14,
- "end_line": 14
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 14,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Pickle library appears to be in use, possible security issue.",
- "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 14,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Pickle library appears to be in use, possible security issue.",
+ "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 15,
+ "end_line": 15
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B301",
+ "value": "B301"
+ }
+ ],
+ "priority": "Medium",
"file": "python/imports/imports-aliases.py",
- "start_line": 15,
- "end_line": 15
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B301",
- "value": "B301"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 15,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "name": "ECB mode is insecure",
- "message": "ECB mode is insecure",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
+ "line": 15,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "ECB mode is insecure",
+ "message": "ECB mode is insecure",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-ECB_MODE",
+ "value": "ECB_MODE",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
+ }
+ ],
+ "priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 29,
- "end_line": 29,
- "class": "com.gitlab.security_products.tests.App",
- "method": "insecureCypher"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-ECB_MODE",
- "value": "ECB_MODE",
- "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 29,
- "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "name": "Cipher with no integrity",
- "message": "Cipher with no integrity",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Cipher with no integrity",
+ "message": "Cipher with no integrity",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-CIPHER_INTEGRITY",
+ "value": "CIPHER_INTEGRITY",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
+ }
+ ],
+ "priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 29,
- "end_line": 29,
- "class": "com.gitlab.security_products.tests.App",
- "method": "insecureCypher"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-CIPHER_INTEGRITY",
- "value": "CIPHER_INTEGRITY",
- "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 29,
- "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 14,
- "end_line": 14
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 14,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 14,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 10,
+ "end_line": 10
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 10,
- "end_line": 10
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 10,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 10,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-aliases.py",
- "start_line": 1,
- "end_line": 1
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 1,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports.py",
- "start_line": 2,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports.py",
- "line": 2,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports.py",
- "start_line": 4,
- "end_line": 4
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports.py",
- "line": 4,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 22,
+ "end_line": 22
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B106",
+ "value": "B106",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 22,
- "end_line": 22
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B106",
- "value": "B106",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 22,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'root'",
- "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 22,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'root'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 5,
+ "end_line": 5
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 5,
- "end_line": 5
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 5,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: ''",
- "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 5,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: ''",
+ "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 9,
- "end_line": 9
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 9,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 13,
- "end_line": 13
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 13,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 13,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 23,
+ "end_line": 23
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 23,
- "end_line": 23
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 23,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 23,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 24,
+ "end_line": 24
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 24,
- "end_line": 24
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 24,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 24,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-function.py",
- "start_line": 4,
- "end_line": 4
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-function.py",
- "line": 4,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-function.py",
- "start_line": 2,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-function.py",
- "line": 2,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 7,
+ "end_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-from.py",
- "start_line": 7,
- "end_line": 7
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 7,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
- "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
+ "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B602",
+ "value": "B602",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-aliases.py",
- "start_line": 9,
- "end_line": 9
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B602",
- "value": "B602",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 9,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-from.py",
- "start_line": 6,
- "end_line": 6
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 6,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 1,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-from.py",
- "start_line": 1,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 1,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 7,
+ "end_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-aliases.py",
- "start_line": 7,
- "end_line": 8
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 7,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with loads module.",
- "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with loads module.",
+ "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
"file": "python/imports/imports-aliases.py",
- "start_line": 6,
- "end_line": 6
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 6,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
- "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
- "confidence": "Low",
- "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
"file": "c/subdir/utils.c",
- "start_line": 4
- },
- "identifiers": [
- {
- "type": "cwe",
- "name": "CWE-119",
- "value": "119",
- "url": "https://cwe.mitre.org/data/definitions/119.html"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "c/subdir/utils.c",
- "line": 4,
- "url": "https://cwe.mitre.org/data/definitions/119.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
- "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
- "confidence": "Low",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
+ "line": 4,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
+ "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
+ "confidence": "Low",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-362",
+ "value": "362",
+ "url": "https://cwe.mitre.org/data/definitions/362.html"
+ }
+ ],
"file": "c/subdir/utils.c",
- "start_line": 8
- },
- "identifiers": [
- {
- "type": "cwe",
- "name": "CWE-362",
- "value": "362",
- "url": "https://cwe.mitre.org/data/definitions/362.html"
- }
- ],
- "file": "c/subdir/utils.c",
- "line": 8,
- "url": "https://cwe.mitre.org/data/definitions/362.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
- "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
- "confidence": "Low",
- "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
+ "line": 8,
+ "url": "https://cwe.mitre.org/data/definitions/362.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
"file": "cplusplus/src/hello.cpp",
- "start_line": 6
- },
- "identifiers": [
- {
- "type": "cwe",
- "name": "CWE-119",
- "value": "119",
- "url": "https://cwe.mitre.org/data/definitions/119.html"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "cplusplus/src/hello.cpp",
- "line": 6,
- "url": "https://cwe.mitre.org/data/definitions/119.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
- "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
- "confidence": "Low",
- "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
+ "line": 6,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
+ "confidence": "Low",
+ "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
"file": "cplusplus/src/hello.cpp",
- "start_line": 7
- },
- "identifiers": [
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "cplusplus/src/hello.cpp",
- "line": 7,
- "url": "https://cwe.mitre.org/data/definitions/120.html",
- "tool": "flawfinder"
- }
-]
+ "line": 7,
+ "url": "https://cwe.mitre.org/data/definitions/120.html",
+ "tool": "flawfinder"
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/remediations/gl-dependency-scanning-report.json b/spec/fixtures/security-reports/remediations/gl-dependency-scanning-report.json
new file mode 100644
index 00000000000..c96e831b027
--- /dev/null
+++ b/spec/fixtures/security-reports/remediations/gl-dependency-scanning-report.json
@@ -0,0 +1,104 @@
+{
+ "version": "2.0",
+ "vulnerabilities": [
+ {
+ "category": "dependency_scanning",
+ "name": "Regular Expression Denial of Service",
+ "message": "Regular Expression Denial of Service in debug",
+ "description": "The debug module is vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter. It takes around 50k characters to block for 2 seconds making this a low severity issue.",
+ "cve": "yarn.lock:debug:gemnasium:37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest versions.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "debug"
+ },
+ "version": "1.0.5"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "value": "37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "url": "https://deps.sec.gitlab.com/packages/npm/debug/versions/1.0.5/advisories"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://nodesecurity.io/advisories/534"
+ },
+ {
+ "url": "https://github.com/visionmedia/debug/issues/501"
+ },
+ {
+ "url": "https://github.com/visionmedia/debug/pull/504"
+ }
+ ]
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Authentication bypass via incorrect DOM traversal and canonicalization",
+ "message": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js",
+ "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.",
+ "cve": "yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98",
+ "severity": "Unknown",
+ "solution": "Upgrade to fixed version.\r\n",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "saml2-js"
+ },
+ "version": "1.5.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98",
+ "value": "9952e574-7b5b-46fa-a270-aeb694198a98",
+ "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-11429",
+ "value": "CVE-2017-11429",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279"
+ },
+ {
+ "url": "https://github.com/Clever/saml2/issues/127"
+ },
+ {
+ "url": "https://www.kb.cert.org/vuls/id/475445"
+ }
+ ]
+ }
+ ],
+ "remediations": [
+ {
+ "fixes": [
+ {
+ "cve": "yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98"
+ }
+ ],
+ "summary": "Upgrade saml2-js",
+ "diff": "ZGlmZiAtLWdpdCBhL3lhcm4ubG9jayBiL3lhcm4ubG9jawppbmRleCAwZWNjOTJmLi43ZmE0NTU0IDEwMDY0NAotLS0gYS95YXJuLmxvY2sKKysrIGIveWFybi5sb2NrCkBAIC0yLDEwMyArMiwxMjQgQEAKICMgeWFybiBsb2NrZmlsZSB2MQogCiAKLWFzeW5jQH4wLjIuNzoKLSAgdmVyc2lvbiAiMC4yLjEwIgotICByZXNvbHZlZCAiaHR0cDovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9hc3luYy8tL2FzeW5jLTAuMi4xMC50Z3ojYjZiYmUwYjA2NzRiOWQ3MTk3MDhjYTM4ZGU4YzIzN2NiNTI2YzNkMSIKLQotYXN5bmNAfjEuNS4yOgotICB2ZXJzaW9uICIxLjUuMiIKLSAgcmVzb2x2ZWQgImh0dHA6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvYXN5bmMvLS9hc3luYy0xLjUuMi50Z3ojZWM2YTYxYWU1NjQ4MGMwYzNjYjI0MWM5NTYxOGUyMDg5MmY5NjcyYSIKK2FzeW5jQF4yLjEuNSwgYXN5bmNAXjIuNS4wOgorICB2ZXJzaW9uICIyLjYuMSIKKyAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20vYXN5bmMvLS9hc3luYy0yLjYuMS50Z3ojYjI0NWEyM2NhNzE5MzAwNDRlYzUzZmE0NmFhMDBhM2U4N2M2YTYxMCIKKyAgaW50ZWdyaXR5IHNoYTUxMi1mTkVpTDIrQVp0NkFsQXcvMjlDcjBVRGU0c1JBSENwRUhoNTRXTXorQmI3UWZOY0Z3NGgzbG9vZnlKcExlUXM0WXg3eXVxdS8yZExnTTVoS09zNkhsUT09CisgIGRlcGVuZGVuY2llczoKKyAgICBsb2Rhc2ggIl40LjE3LjEwIgogCi1kZWJ1Z0BeMS4wLjQ6Ci0gIHZlcnNpb24gIjEuMC41IgotICByZXNvbHZlZCAiaHR0cHM6Ly9yZWdpc3RyeS55YXJucGtnLmNvbS9kZWJ1Zy8tL2RlYnVnLTEuMC41LnRneiNmNzI0MTIxNzQzMGY5OWRlYzRjMmI0NzNlYWI5MjIyOGU4NzRjMmFjIgorZGVidWdAXjIuNi4wOgorICB2ZXJzaW9uICIyLjYuOSIKKyAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20vZGVidWcvLS9kZWJ1Zy0yLjYuOS50Z3ojNWQxMjg1MTVkZjEzNGZmMzI3ZTkwYTRjOTNmNGUwNzdhNTM2MzQxZiIKKyAgaW50ZWdyaXR5IHNoYTUxMi1iQzdFbHJkSmFKblBiQVArMUVvdFl2cVpzYjNlY2w1d2k2QmZpNkJKVFVjTm93cDZjdnNwZzBqWHpuUlRLRGptL0U3QWRnRkJWZUFQVk1OY0tHc0hNQT09CiAgIGRlcGVuZGVuY2llczoKICAgICBtcyAiMi4wLjAiCiAKLWVqc0B+MC44LjM6Ci0gIHZlcnNpb24gIjAuOC44IgotICByZXNvbHZlZCAiaHR0cHM6Ly9yZWdpc3RyeS55YXJucGtnLmNvbS9lanMvLS9lanMtMC44LjgudGd6I2ZmZGM1NmRjYzM1ZDAyOTI2ZGQ1MGFkMTM0MzliYmM1NDA2MWQ1OTgiCitlanNAXjIuNS42OgorICB2ZXJzaW9uICIyLjYuMSIKKyAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20vZWpzLy0vZWpzLTIuNi4xLnRneiM0OThlYzBkNDk1NjU1YWJjNmYyM2NkNjE4NjhkOTI2NDY0MDcxYWEwIgorICBpbnRlZ3JpdHkgc2hhNTEyLTB4eTRBL3R3ZnJSQ25raGZrOEVyRGk1RHFkQXNBcWVHeGh0NHhrQ1Vyc3ZoaGJRTnM3RSs0alYwQ043K05LSVkwYUhFNzIrWHZxdEJJWHpEMzFaYlhRPT0KKworbG9kYXNoLW5vZGVAfjIuNC4xOgorICB2ZXJzaW9uICIyLjQuMSIKKyAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20vbG9kYXNoLW5vZGUvLS9sb2Rhc2gtbm9kZS0yLjQuMS50Z3ojZWE4MmY3YjEwMGM3MzNkMWE0MmFmNzY4MDFlNTA2MTA1ZTJhODBlYyIKKyAgaW50ZWdyaXR5IHNoYTEtNm9MM3NRREhNOUdrS3Zkb0FlVUdFRjRxZ093PQorCitsb2Rhc2hAXjQuMTcuMTA6CisgIHZlcnNpb24gIjQuMTcuMTEiCisgIHJlc29sdmVkICJodHRwczovL3JlZ2lzdHJ5Lnlhcm5wa2cuY29tL2xvZGFzaC8tL2xvZGFzaC00LjE3LjExLnRneiNiMzllYTYyMjllZjYwN2VjZDg5ZTJjOGRmMTI1MzY4OTFjYWM5YjhkIgorICBpbnRlZ3JpdHkgc2hhNTEyLWNRS2g4aWdvNVFVaFo3bGczOERZV0F4TXZqU0FLRzBBOHdHU1ZpbVAwN1NJVUVLMlVPK2FyU1JLYlJaV3RlbE10TjVWMEhrd2g1cnlPdG8vU3NoWUlnPT0KIAogbXNAMi4wLjA6CiAgIHZlcnNpb24gIjIuMC4wIgogICByZXNvbHZlZCAiaHR0cHM6Ly9yZWdpc3RyeS55YXJucGtnLmNvbS9tcy8tL21zLTIuMC4wLnRneiM1NjA4YWVhZGZjMDBiZTZjMjkwMWRmNWY5ODYxNzg4ZGUwZDU5N2M4IgorICBpbnRlZ3JpdHkgc2hhMS1WZ2l1cmZ3QXZtd3BBZDlmbUdGNGplRFZsOGc9CiAKLW5vZGUtZm9yZ2VAMC4yLjI0OgotICB2ZXJzaW9uICIwLjIuMjQiCi0gIHJlc29sdmVkICJodHRwczovL3JlZ2lzdHJ5Lnlhcm5wa2cuY29tL25vZGUtZm9yZ2UvLS9ub2RlLWZvcmdlLTAuMi4yNC50Z3ojZmE2Zjg0NmY0MmZhOTNmNjNhMGEzMGM5ZmJmZjdiNGUxMzBlMDg1OCIKK25vZGUtZm9yZ2VAXjAuNy4wOgorICB2ZXJzaW9uICIwLjcuNiIKKyAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20vbm9kZS1mb3JnZS8tL25vZGUtZm9yZ2UtMC43LjYudGd6I2ZkZjNiNDE4YWVlMWY5NGYwZWY2NDJjZDYzNDg2Yzc3Y2E5NzI0YWMiCisgIGludGVncml0eSBzaGE1MTItc29sMzBMVXB6MWpRRkJqT0t3Ymp4aWppRTNiNnBqZDc0WXdmRDBmSk9LUGpGK2ZPTktiMllnOHJZZ1M2K2JLNlZEbCsvd2ZyNElZcEM3akR6TFVJZnc9PQogCiBzYW1sMi1qc0BeMS41LjA6Ci0gIHZlcnNpb24gIjEuNS4wIgotICByZXNvbHZlZCAiaHR0cHM6Ly9yZWdpc3RyeS55YXJucGtnLmNvbS9zYW1sMi1qcy8tL3NhbWwyLWpzLTEuNS4wLnRneiNjMGQyMjY4YTE3OWU3MzI5ZDI5ZWIyNWFhODJkZjU1MDM3NzRiMGQ5IgorICB2ZXJzaW9uICIxLjEyLjQiCisgIHJlc29sdmVkICJodHRwczovL3JlZ2lzdHJ5Lnlhcm5wa2cuY29tL3NhbWwyLWpzLy0vc2FtbDItanMtMS4xMi40LnRneiNjMjg4ZjIwYmRhNmQyYjkxMDczYjE2Yzk0ZWE3MmYyMjM0OWFjM2IzIgorICBpbnRlZ3JpdHkgc2hhMS13b2p5QzlwdEs1RUhPeGJKVHFjdklqU2F3N009CiAgIGRlcGVuZGVuY2llczoKLSAgICBhc3luYyAifjEuNS4yIgotICAgIGRlYnVnICJeMS4wLjQiCi0gICAgdW5kZXJzY29yZSAifjEuNi4wIgotICAgIHhtbC1jcnlwdG8gIl4wLjguMSIKLSAgICB4bWwtZW5jcnlwdGlvbiAifjAuNy40IgotICAgIHhtbDJqcyAifjAuNC4xIgotICAgIHhtbGJ1aWxkZXIgIn4yLjEuMCIKLSAgICB4bWxkb20gIn4wLjEuMTkiCisgICAgYXN5bmMgIl4yLjUuMCIKKyAgICBkZWJ1ZyAiXjIuNi4wIgorICAgIHVuZGVyc2NvcmUgIl4xLjguMCIKKyAgICB4bWwtY3J5cHRvICJeMC4xMC4wIgorICAgIHhtbC1lbmNyeXB0aW9uICJeMC4xMS4wIgorICAgIHhtbDJqcyAiXjAuNC4wIgorICAgIHhtbGJ1aWxkZXIgIn4yLjIuMCIKKyAgICB4bWxkb20gIl4wLjEuMCIKIAogc2F4QD49MC42LjA6CiAgIHZlcnNpb24gIjEuMi40IgogICByZXNvbHZlZCAiaHR0cHM6Ly9yZWdpc3RyeS55YXJucGtnLmNvbS9zYXgvLS9zYXgtMS4yLjQudGd6IzI4MTYyMzRlMjM3OGJkZGM0ZTUzNTRmYWI1Y2FhODk1ZGY3MTAwZDkiCisgIGludGVncml0eSBzaGE1MTItTnFWRHY5VHBBTlVqRm0wTjh1TTVHeEwzNlVnS2k5L2F0WncreDdZRm5ROGNrd0ZHS3JsNHhYNHlXdHJleTNVSm01blAxa1VibllnTG9wcVdOU1JoV3c9PQogCi11bmRlcnNjb3JlQD49MS41Lng6Cit1bmRlcnNjb3JlQF4xLjguMDoKICAgdmVyc2lvbiAiMS45LjEiCiAgIHJlc29sdmVkICJodHRwczovL3JlZ2lzdHJ5Lnlhcm5wa2cuY29tL3VuZGVyc2NvcmUvLS91bmRlcnNjb3JlLTEuOS4xLnRneiMwNmRjZTM0YTBlNjhhN2JhYmMyOWIzNjViOGU3NGI4OTI1MjAzOTYxIgorICBpbnRlZ3JpdHkgc2hhNTEyLTUvNGV0bkNrZDljOGd3Z293aTUvb20vbVlPNWFqQ2FPZ2R6ai9vVyswZVFWOVd4S0JEWnc1K3ljbUttZWFUWGpJblMvVzBCenBHTG8yeFIyYUJ3WmRnPT0KIAotdW5kZXJzY29yZUB+MS42LjA6Ci0gIHZlcnNpb24gIjEuNi4wIgotICByZXNvbHZlZCAiaHR0cHM6Ly9yZWdpc3RyeS55YXJucGtnLmNvbS91bmRlcnNjb3JlLy0vdW5kZXJzY29yZS0xLjYuMC50Z3ojOGIzOGIxMGNhY2RlZjYzMzM3YjhiMjRlNGZmODZkNDVhZWE1MjlhOCIKLQoteG1sLWNyeXB0b0BeMC44LjE6Ci0gIHZlcnNpb24gIjAuOC41IgotICByZXNvbHZlZCAiaHR0cDovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy94bWwtY3J5cHRvLy0veG1sLWNyeXB0by0wLjguNS50Z3ojMmJiY2ZiM2ViMzNmM2E4MmEyMThiODIyYmY2NzJiNmIxYzIwZTUzOCIKK3htbC1jcnlwdG9AXjAuMTAuMDoKKyAgdmVyc2lvbiAiMC4xMC4xIgorICByZXNvbHZlZCAiaHR0cHM6Ly9yZWdpc3RyeS55YXJucGtnLmNvbS94bWwtY3J5cHRvLy0veG1sLWNyeXB0by0wLjEwLjEudGd6I2Y4MzJmNzRjY2Y1NmYyNGFmY2FlMTE2M2ExZmNhYjQ0ZDk2Nzc0YTgiCisgIGludGVncml0eSBzaGExLStETDNUTTlXOGtyOHJoRmpvZnlyUk5sbmRLZz0KICAgZGVwZW5kZW5jaWVzOgogICAgIHhtbGRvbSAiPTAuMS4xOSIKICAgICB4cGF0aC5qcyAiPj0wLjAuMyIKIAoteG1sLWVuY3J5cHRpb25AfjAuNy40OgotICB2ZXJzaW9uICIwLjcuNCIKLSAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20veG1sLWVuY3J5cHRpb24vLS94bWwtZW5jcnlwdGlvbi0wLjcuNC50Z3ojNDI3OTFlYzY0ZDU1NmQyNDU1ZGNiOWRhMGE1NDEyMzY2NWFjNjVjNyIKK3htbC1lbmNyeXB0aW9uQF4wLjExLjA6CisgIHZlcnNpb24gIjAuMTEuMiIKKyAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20veG1sLWVuY3J5cHRpb24vLS94bWwtZW5jcnlwdGlvbi0wLjExLjIudGd6I2MyMTdmNTUwOTU0N2UzNGI1MDBiODI5ZjJjMGJjYTg1Y2NhNzNhMjEiCisgIGludGVncml0eSBzaGE1MTItalZ2RVM3aTVvdmRPN04rTmpnbmNBMzI2eFlLamhxZUFubnZJZ1JuWTdST0xDZkZxRURMd1AwU3hwLzMwU0hHMEFYUVYxMDQ4VDV5aW5PRnl2d0dGemc9PQogICBkZXBlbmRlbmNpZXM6Ci0gICAgYXN5bmMgIn4wLjIuNyIKLSAgICBlanMgIn4wLjguMyIKLSAgICBub2RlLWZvcmdlICIwLjIuMjQiCisgICAgYXN5bmMgIl4yLjEuNSIKKyAgICBlanMgIl4yLjUuNiIKKyAgICBub2RlLWZvcmdlICJeMC43LjAiCiAgICAgeG1sZG9tICJ+MC4xLjE1IgotICAgIHhwYXRoICIwLjAuNSIKKyAgICB4cGF0aCAiMC4wLjI3IgogCi14bWwyanNAfjAuNC4xOgoreG1sMmpzQF4wLjQuMDoKICAgdmVyc2lvbiAiMC40LjE5IgogICByZXNvbHZlZCAiaHR0cHM6Ly9yZWdpc3RyeS55YXJucGtnLmNvbS94bWwyanMvLS94bWwyanMtMC40LjE5LnRneiM2ODZjMjBmMjEzMjA5ZTk0YWJmMGQxYmNmMWVmYWEyOTFjNzgyN2E3IgorICBpbnRlZ3JpdHkgc2hhNTEyLWVzWm5KWkpPaUpSOXdXS015dXZTRTF5NkRxNUxDdUphbnFoeHNsSDJieE02ZHVhaE5aK0hNcENMaEJRR1prYlg2eFJmOHgxWTJlSmxndDJxM3FvNDlRPT0KICAgZGVwZW5kZW5jaWVzOgogICAgIHNheCAiPj0wLjYuMCIKICAgICB4bWxidWlsZGVyICJ+OS4wLjEiCiAKLXhtbGJ1aWxkZXJAfjIuMS4wOgotICB2ZXJzaW9uICIyLjEuMCIKLSAgcmVzb2x2ZWQgImh0dHA6Ly9yZWdpc3RyeS5ucG1qcy5vcmcveG1sYnVpbGRlci8tL3htbGJ1aWxkZXItMi4xLjAudGd6IzZkZGFlMzE2ODNiNmRmMTIxMDBiMjlmYzhhMGQ0ZjQ2MzQ5YWJiZWQiCit4bWxidWlsZGVyQH4yLjIuMDoKKyAgdmVyc2lvbiAiMi4yLjEiCisgIHJlc29sdmVkICJodHRwczovL3JlZ2lzdHJ5Lnlhcm5wa2cuY29tL3htbGJ1aWxkZXIvLS94bWxidWlsZGVyLTIuMi4xLnRneiM5MzI2NDMwZjEzMGQ4NzQzNWQ0YzQwODY2NDNhYTI5MjZlMTA1YTMyIgorICBpbnRlZ3JpdHkgc2hhMS1reVpERHhNTmgwTmRURUNHWkRxaWttNFFXakk9CiAgIGRlcGVuZGVuY2llczoKLSAgICB1bmRlcnNjb3JlICI+PTEuNS54IgorICAgIGxvZGFzaC1ub2RlICJ+Mi40LjEiCiAKIHhtbGJ1aWxkZXJAfjkuMC4xOgogICB2ZXJzaW9uICI5LjAuNyIKLSAgcmVzb2x2ZWQgImh0dHA6Ly9yZWdpc3RyeS5ucG1qcy5vcmcveG1sYnVpbGRlci8tL3htbGJ1aWxkZXItOS4wLjcudGd6IzEzMmVlNjNkMmVjNTU2NWM1NTdlMjBmNGMyMmRmOWFjYTY4NmIxMGQiCisgIHJlc29sdmVkICJodHRwczovL3JlZ2lzdHJ5Lnlhcm5wa2cuY29tL3htbGJ1aWxkZXIvLS94bWxidWlsZGVyLTkuMC43LnRneiMxMzJlZTYzZDJlYzU1NjVjNTU3ZTIwZjRjMjJkZjlhY2E2ODZiMTBkIgorICBpbnRlZ3JpdHkgc2hhMS1FeTdtUFM3RlZseFZmaUQwd2kzNXJLYUdzUTA9CiAKIHhtbGRvbUA9MC4xLjE5OgogICB2ZXJzaW9uICIwLjEuMTkiCiAgIHJlc29sdmVkICJodHRwczovL3JlZ2lzdHJ5Lnlhcm5wa2cuY29tL3htbGRvbS8tL3htbGRvbS0wLjEuMTkudGd6IzYzMWZjMDc3NzZlZmQ4NDExOGJmMjUxNzFiMzdlZDRkMDc1YTBhYmMiCisgIGludGVncml0eSBzaGExLVl4L0FkM2J2MkVFWXZ5VVhHemZ0VFFkYUNydz0KIAoteG1sZG9tQH4wLjEuMTUsIHhtbGRvbUB+MC4xLjE5OgoreG1sZG9tQF4wLjEuMCwgeG1sZG9tQH4wLjEuMTU6CiAgIHZlcnNpb24gIjAuMS4yNyIKICAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20veG1sZG9tLy0veG1sZG9tLTAuMS4yNy50Z3ojZDUwMWY5N2IzYmRiNDAzYWY4ZWY5ZWNjMjA1NzMxODdhYWRhYzBlOSIKKyAgaW50ZWdyaXR5IHNoYTEtMVFINWV6dmJRRHI0NzU3TUlGY3hoNnJhd09rPQogCiB4cGF0aC5qc0A+PTAuMC4zOgogICB2ZXJzaW9uICIxLjEuMCIKICAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20veHBhdGguanMvLS94cGF0aC5qcy0xLjEuMC50Z3ojMzgxNmE0NGVkNGJiMzUyMDkxMDgzZDAwMmEzODNkZDUxMDRhNWZmMSIKKyAgaW50ZWdyaXR5IHNoYTUxMi1qZytxa2ZTNEs4RTc5NjVzcWFVbDhtUm5nWGlLYjNXWkdmT05nRTE4cHIwM0ZVUWl1U1Y2RytFajR0UzU1QitySVFTRkVJdzNwaGRWQVE0cFBxTldmUT09CiAKLXhwYXRoQDAuMC41OgotICB2ZXJzaW9uICIwLjAuNSIKLSAgcmVzb2x2ZWQgImh0dHBzOi8vcmVnaXN0cnkueWFybnBrZy5jb20veHBhdGgvLS94cGF0aC0wLjAuNS50Z3ojNDU0MDM2ZjZlZjBmM2RmNWFmNWQ0YmE0YTExOWZiNzU2NzRiM2U2YyIKK3hwYXRoQDAuMC4yNzoKKyAgdmVyc2lvbiAiMC4wLjI3IgorICByZXNvbHZlZCAiaHR0cHM6Ly9yZWdpc3RyeS55YXJucGtnLmNvbS94cGF0aC8tL3hwYXRoLTAuMC4yNy50Z3ojZGQzNDIxZmJkY2M1NjQ2YWMzMmM0ODUzMWI0ZDdlOWQwYzJjZmE5MiIKKyAgaW50ZWdyaXR5IHNoYTUxMi1mZzAzV1J4dGtDVjZvaENsZVBOQUVDWXNtcEtLVHY1TDh5L1gzRG4xaFFyZWMzUE94MmpIWi8wUDJxUTZIdnNyVTFCbWVxWGNvZjNOR0d1ZUc2THh3UT09Cg=="
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/remediations/remediation.patch b/spec/fixtures/security-reports/remediations/remediation.patch
new file mode 100644
index 00000000000..bbfb6874627
--- /dev/null
+++ b/spec/fixtures/security-reports/remediations/remediation.patch
@@ -0,0 +1,180 @@
+diff --git a/yarn.lock b/yarn.lock
+index 0ecc92f..7fa4554 100644
+--- a/yarn.lock
++++ b/yarn.lock
+@@ -2,103 +2,124 @@
+ # yarn lockfile v1
+
+
+-async@~0.2.7:
+- version "0.2.10"
+- resolved "http://registry.npmjs.org/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
+-
+-async@~1.5.2:
+- version "1.5.2"
+- resolved "http://registry.npmjs.org/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
++async@^2.1.5, async@^2.5.0:
++ version "2.6.1"
++ resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
++ integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==
++ dependencies:
++ lodash "^4.17.10"
+
+-debug@^1.0.4:
+- version "1.0.5"
+- resolved "https://registry.yarnpkg.com/debug/-/debug-1.0.5.tgz#f7241217430f99dec4c2b473eab92228e874c2ac"
++debug@^2.6.0:
++ version "2.6.9"
++ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
++ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+-ejs@~0.8.3:
+- version "0.8.8"
+- resolved "https://registry.yarnpkg.com/ejs/-/ejs-0.8.8.tgz#ffdc56dcc35d02926dd50ad13439bbc54061d598"
++ejs@^2.5.6:
++ version "2.6.1"
++ resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
++ integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==
++
++lodash-node@~2.4.1:
++ version "2.4.1"
++ resolved "https://registry.yarnpkg.com/lodash-node/-/lodash-node-2.4.1.tgz#ea82f7b100c733d1a42af76801e506105e2a80ec"
++ integrity sha1-6oL3sQDHM9GkKvdoAeUGEF4qgOw=
++
++lodash@^4.17.10:
++ version "4.17.11"
++ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
++ integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
+
+ ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
++ integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
+-node-forge@0.2.24:
+- version "0.2.24"
+- resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.2.24.tgz#fa6f846f42fa93f63a0a30c9fbff7b4e130e0858"
++node-forge@^0.7.0:
++ version "0.7.6"
++ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac"
++ integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==
+
+ saml2-js@^1.5.0:
+- version "1.5.0"
+- resolved "https://registry.yarnpkg.com/saml2-js/-/saml2-js-1.5.0.tgz#c0d2268a179e7329d29eb25aa82df5503774b0d9"
++ version "1.12.4"
++ resolved "https://registry.yarnpkg.com/saml2-js/-/saml2-js-1.12.4.tgz#c288f20bda6d2b91073b16c94ea72f22349ac3b3"
++ integrity sha1-wojyC9ptK5EHOxbJTqcvIjSaw7M=
+ dependencies:
+- async "~1.5.2"
+- debug "^1.0.4"
+- underscore "~1.6.0"
+- xml-crypto "^0.8.1"
+- xml-encryption "~0.7.4"
+- xml2js "~0.4.1"
+- xmlbuilder "~2.1.0"
+- xmldom "~0.1.19"
++ async "^2.5.0"
++ debug "^2.6.0"
++ underscore "^1.8.0"
++ xml-crypto "^0.10.0"
++ xml-encryption "^0.11.0"
++ xml2js "^0.4.0"
++ xmlbuilder "~2.2.0"
++ xmldom "^0.1.0"
+
+ sax@>=0.6.0:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
++ integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+-underscore@>=1.5.x:
++underscore@^1.8.0:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961"
++ integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==
+
+-underscore@~1.6.0:
+- version "1.6.0"
+- resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
+-
+-xml-crypto@^0.8.1:
+- version "0.8.5"
+- resolved "http://registry.npmjs.org/xml-crypto/-/xml-crypto-0.8.5.tgz#2bbcfb3eb33f3a82a218b822bf672b6b1c20e538"
++xml-crypto@^0.10.0:
++ version "0.10.1"
++ resolved "https://registry.yarnpkg.com/xml-crypto/-/xml-crypto-0.10.1.tgz#f832f74ccf56f24afcae1163a1fcab44d96774a8"
++ integrity sha1-+DL3TM9W8kr8rhFjofyrRNlndKg=
+ dependencies:
+ xmldom "=0.1.19"
+ xpath.js ">=0.0.3"
+
+-xml-encryption@~0.7.4:
+- version "0.7.4"
+- resolved "https://registry.yarnpkg.com/xml-encryption/-/xml-encryption-0.7.4.tgz#42791ec64d556d2455dcb9da0a54123665ac65c7"
++xml-encryption@^0.11.0:
++ version "0.11.2"
++ resolved "https://registry.yarnpkg.com/xml-encryption/-/xml-encryption-0.11.2.tgz#c217f5509547e34b500b829f2c0bca85cca73a21"
++ integrity sha512-jVvES7i5ovdO7N+NjgncA326xYKjhqeAnnvIgRnY7ROLCfFqEDLwP0Sxp/30SHG0AXQV1048T5yinOFyvwGFzg==
+ dependencies:
+- async "~0.2.7"
+- ejs "~0.8.3"
+- node-forge "0.2.24"
++ async "^2.1.5"
++ ejs "^2.5.6"
++ node-forge "^0.7.0"
+ xmldom "~0.1.15"
+- xpath "0.0.5"
++ xpath "0.0.27"
+
+-xml2js@~0.4.1:
++xml2js@^0.4.0:
+ 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"
+
+-xmlbuilder@~2.1.0:
+- version "2.1.0"
+- resolved "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.1.0.tgz#6ddae31683b6df12100b29fc8a0d4f46349abbed"
++xmlbuilder@~2.2.0:
++ version "2.2.1"
++ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-2.2.1.tgz#9326430f130d87435d4c4086643aa2926e105a32"
++ integrity sha1-kyZDDxMNh0NdTECGZDqikm4QWjI=
+ dependencies:
+- underscore ">=1.5.x"
++ lodash-node "~2.4.1"
+
+ xmlbuilder@~9.0.1:
+ version "9.0.7"
+- resolved "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
++ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
++ integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=
+
+ xmldom@=0.1.19:
+ version "0.1.19"
+ resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.19.tgz#631fc07776efd84118bf25171b37ed4d075a0abc"
++ integrity sha1-Yx/Ad3bv2EEYvyUXGzftTQdaCrw=
+
+-xmldom@~0.1.15, xmldom@~0.1.19:
++xmldom@^0.1.0, xmldom@~0.1.15:
+ version "0.1.27"
+ resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
++ integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk=
+
+ xpath.js@>=0.0.3:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/xpath.js/-/xpath.js-1.1.0.tgz#3816a44ed4bb352091083d002a383dd5104a5ff1"
++ integrity sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==
+
+-xpath@0.0.5:
+- version "0.0.5"
+- resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.5.tgz#454036f6ef0f3df5af5d4ba4a119fb75674b3e6c"
++xpath@0.0.27:
++ version "0.0.27"
++ resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.27.tgz#dd3421fbdcc5646ac32c48531b4d7e9d0c2cfa92"
++ integrity sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==
diff --git a/spec/fixtures/security-reports/remediations/yarn.lock b/spec/fixtures/security-reports/remediations/yarn.lock
new file mode 100644
index 00000000000..0ecc92fb711
--- /dev/null
+++ b/spec/fixtures/security-reports/remediations/yarn.lock
@@ -0,0 +1,104 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+async@~0.2.7:
+ version "0.2.10"
+ resolved "http://registry.npmjs.org/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
+
+async@~1.5.2:
+ version "1.5.2"
+ resolved "http://registry.npmjs.org/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+
+debug@^1.0.4:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-1.0.5.tgz#f7241217430f99dec4c2b473eab92228e874c2ac"
+ dependencies:
+ ms "2.0.0"
+
+ejs@~0.8.3:
+ version "0.8.8"
+ resolved "https://registry.yarnpkg.com/ejs/-/ejs-0.8.8.tgz#ffdc56dcc35d02926dd50ad13439bbc54061d598"
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+
+node-forge@0.2.24:
+ version "0.2.24"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.2.24.tgz#fa6f846f42fa93f63a0a30c9fbff7b4e130e0858"
+
+saml2-js@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/saml2-js/-/saml2-js-1.5.0.tgz#c0d2268a179e7329d29eb25aa82df5503774b0d9"
+ dependencies:
+ async "~1.5.2"
+ debug "^1.0.4"
+ underscore "~1.6.0"
+ xml-crypto "^0.8.1"
+ xml-encryption "~0.7.4"
+ xml2js "~0.4.1"
+ xmlbuilder "~2.1.0"
+ xmldom "~0.1.19"
+
+sax@>=0.6.0:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+
+underscore@>=1.5.x:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961"
+
+underscore@~1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
+
+xml-crypto@^0.8.1:
+ version "0.8.5"
+ resolved "http://registry.npmjs.org/xml-crypto/-/xml-crypto-0.8.5.tgz#2bbcfb3eb33f3a82a218b822bf672b6b1c20e538"
+ dependencies:
+ xmldom "=0.1.19"
+ xpath.js ">=0.0.3"
+
+xml-encryption@~0.7.4:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/xml-encryption/-/xml-encryption-0.7.4.tgz#42791ec64d556d2455dcb9da0a54123665ac65c7"
+ dependencies:
+ async "~0.2.7"
+ ejs "~0.8.3"
+ node-forge "0.2.24"
+ xmldom "~0.1.15"
+ xpath "0.0.5"
+
+xml2js@~0.4.1:
+ version "0.4.19"
+ resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
+ dependencies:
+ sax ">=0.6.0"
+ xmlbuilder "~9.0.1"
+
+xmlbuilder@~2.1.0:
+ version "2.1.0"
+ resolved "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.1.0.tgz#6ddae31683b6df12100b29fc8a0d4f46349abbed"
+ dependencies:
+ underscore ">=1.5.x"
+
+xmlbuilder@~9.0.1:
+ version "9.0.7"
+ resolved "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
+
+xmldom@=0.1.19:
+ version "0.1.19"
+ resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.19.tgz#631fc07776efd84118bf25171b37ed4d075a0abc"
+
+xmldom@~0.1.15, xmldom@~0.1.19:
+ version "0.1.27"
+ resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
+
+xpath.js@>=0.0.3:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/xpath.js/-/xpath.js-1.1.0.tgz#3816a44ed4bb352091083d002a383dd5104a5ff1"
+
+xpath@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.5.tgz#454036f6ef0f3df5af5d4ba4a119fb75674b3e6c"
diff --git a/spec/fixtures/sentry/issues_sample_response.json b/spec/fixtures/sentry/issues_sample_response.json
new file mode 100644
index 00000000000..ed22499cfa1
--- /dev/null
+++ b/spec/fixtures/sentry/issues_sample_response.json
@@ -0,0 +1,42 @@
+[{
+ "lastSeen": "2018-12-31T12:00:11Z",
+ "numComments": 0,
+ "userCount": 0,
+ "stats": {
+ "24h": [
+ [
+ 1546437600,
+ 0
+ ]
+ ]
+ },
+ "culprit": "sentry.tasks.reports.deliver_organization_user_report",
+ "title": "gaierror: [Errno -2] Name or service not known",
+ "id": "11",
+ "assignedTo": null,
+ "logger": null,
+ "type": "error",
+ "annotations": [],
+ "metadata": {
+ "type": "gaierror",
+ "value": "[Errno -2] Name or service not known"
+ },
+ "status": "unresolved",
+ "subscriptionDetails": null,
+ "isPublic": false,
+ "hasSeen": false,
+ "shortId": "INTERNAL-4",
+ "shareId": null,
+ "firstSeen": "2018-12-17T12:00:14Z",
+ "count": "21",
+ "permalink": "35.228.54.90/sentry/internal/issues/11/",
+ "level": "error",
+ "isSubscribed": true,
+ "isBookmarked": false,
+ "project": {
+ "slug": "internal",
+ "id": "1",
+ "name": "Internal"
+ },
+ "statusDetails": {}
+ }]
diff --git a/spec/fixtures/sentry/list_projects_sample_response.json b/spec/fixtures/sentry/list_projects_sample_response.json
new file mode 100644
index 00000000000..fd79b0d0f30
--- /dev/null
+++ b/spec/fixtures/sentry/list_projects_sample_response.json
@@ -0,0 +1,81 @@
+[
+ {
+ "status": "active",
+ "features": [
+ "data-forwarding",
+ "rate-limits",
+ "releases"
+ ],
+ "color": "#5c3fbf",
+ "isInternal": false,
+ "isPublic": false,
+ "dateCreated": "2018-12-11T10:41:22.476Z",
+ "id": "2",
+ "slug": "sentry-example",
+ "name": "sentry-example",
+ "hasAccess": true,
+ "isBookmarked": false,
+ "platform": "node",
+ "firstEvent": "2018-12-12T15:07:18Z",
+ "avatar": {
+ "avatarUuid": null,
+ "avatarType": "letter_avatar"
+ },
+ "isMember": true,
+ "organization": {
+ "status": {
+ "id": "active",
+ "name": "active"
+ },
+ "require2FA": false,
+ "avatar": {
+ "avatarUuid": null,
+ "avatarType": "letter_avatar"
+ },
+ "name": "Sentry",
+ "dateCreated": "2018-12-11T10:21:47.431Z",
+ "id": "1",
+ "isEarlyAdopter": false,
+ "slug": "sentry"
+ }
+ },
+ {
+ "status": "active",
+ "features": [
+ "data-forwarding",
+ "rate-limits"
+ ],
+ "color": "#bf873f",
+ "isInternal": true,
+ "isPublic": false,
+ "dateCreated": "2018-12-11T10:21:47.440Z",
+ "id": "1",
+ "slug": "internal",
+ "name": "Internal",
+ "hasAccess": true,
+ "isBookmarked": false,
+ "platform": null,
+ "firstEvent": "2018-12-11T10:54:35Z",
+ "avatar": {
+ "avatarUuid": null,
+ "avatarType": "letter_avatar"
+ },
+ "isMember": true,
+ "organization": {
+ "status": {
+ "id": "active",
+ "name": "active"
+ },
+ "require2FA": false,
+ "avatar": {
+ "avatarUuid": null,
+ "avatarType": "letter_avatar"
+ },
+ "name": "Sentry",
+ "dateCreated": "2018-12-11T10:21:47.431Z",
+ "id": "1",
+ "isEarlyAdopter": false,
+ "slug": "sentry"
+ }
+ }
+]
diff --git a/spec/fixtures/trace/sample_trace b/spec/fixtures/trace/sample_trace
index 3d8beb0dec2..8f9747f8143 100644
--- a/spec/fixtures/trace/sample_trace
+++ b/spec/fixtures/trace/sample_trace
@@ -1795,7 +1795,7 @@ GroupsController
when requesting a redirected path
returns not found
PUT transfer
- when transfering to a subgroup goes right
+ when transferring to a subgroup goes right
should return a notice (PENDING: around hook at ./spec/spec_helper.rb:190 did not execute the example)
should redirect to the new path (PENDING: around hook at ./spec/spec_helper.rb:190 did not execute the example)
when converting to a root group goes right
@@ -2299,7 +2299,7 @@ Groups::TransferService
should update subgroups path (PENDING: around hook at ./spec/spec_helper.rb:190 did not execute the example)
should update projects path (PENDING: around hook at ./spec/spec_helper.rb:190 did not execute the example)
should create redirect for the subgroups and projects (PENDING: around hook at ./spec/spec_helper.rb:190 did not execute the example)
- when transfering a group with nested groups and projects
+ when transferring a group with nested groups and projects
should update subgroups path (PENDING: around hook at ./spec/spec_helper.rb:190 did not execute the example)
should update projects path (PENDING: around hook at ./spec/spec_helper.rb:190 did not execute the example)
should create redirect for the subgroups and projects (PENDING: around hook at ./spec/spec_helper.rb:190 did not execute the example)
@@ -2426,9 +2426,9 @@ Groups::MilestonesController
lists legacy group milestones and group milestones
#show
when there is a title parameter
- searchs for a legacy group milestone
+ searches for a legacy group milestone
when there is not a title parameter
- searchs for a group milestone
+ searches for a group milestone
behaves like milestone tabs
#merge_requests
as html
@@ -3109,11 +3109,11 @@ Pending: (Failures listed here are expected and do not affect your suite's statu
# around hook at ./spec/spec_helper.rb:186 did not execute the example
# ./spec/controllers/groups_controller_spec.rb:129
- 15) GroupsController PUT transfer when transfering to a subgroup goes right should return a notice
+ 15) GroupsController PUT transfer when transferring to a subgroup goes right should return a notice
# around hook at ./spec/spec_helper.rb:190 did not execute the example
# ./spec/controllers/groups_controller_spec.rb:516
- 16) GroupsController PUT transfer when transfering to a subgroup goes right should redirect to the new path
+ 16) GroupsController PUT transfer when transferring to a subgroup goes right should redirect to the new path
# around hook at ./spec/spec_helper.rb:190 did not execute the example
# ./spec/controllers/groups_controller_spec.rb:520
@@ -3301,15 +3301,15 @@ Pending: (Failures listed here are expected and do not affect your suite's statu
# around hook at ./spec/spec_helper.rb:190 did not execute the example
# ./spec/services/groups/transfer_service_spec.rb:341
- 63) Groups::TransferService#execute when transferring a subgroup into another group when transfering a group with nested groups and projects should update subgroups path
+ 63) Groups::TransferService#execute when transferring a subgroup into another group when transferring a group with nested groups and projects should update subgroups path
# around hook at ./spec/spec_helper.rb:190 did not execute the example
# ./spec/services/groups/transfer_service_spec.rb:363
- 64) Groups::TransferService#execute when transferring a subgroup into another group when transfering a group with nested groups and projects should update projects path
+ 64) Groups::TransferService#execute when transferring a subgroup into another group when transferring a group with nested groups and projects should update projects path
# around hook at ./spec/spec_helper.rb:190 did not execute the example
# ./spec/services/groups/transfer_service_spec.rb:375
- 65) Groups::TransferService#execute when transferring a subgroup into another group when transfering a group with nested groups and projects should create redirect for the subgroups and projects
+ 65) Groups::TransferService#execute when transferring a subgroup into another group when transferring a group with nested groups and projects should create redirect for the subgroups and projects
# around hook at ./spec/spec_helper.rb:190 did not execute the example
# ./spec/services/groups/transfer_service_spec.rb:383
diff --git a/spec/frontend/__mocks__/file_mock.js b/spec/frontend/__mocks__/file_mock.js
new file mode 100644
index 00000000000..08d725cd4e4
--- /dev/null
+++ b/spec/frontend/__mocks__/file_mock.js
@@ -0,0 +1 @@
+export default '';
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
new file mode 100644
index 00000000000..c7008c780d6
--- /dev/null
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -0,0 +1,253 @@
+/* eslint no-param-reassign: "off" */
+
+import $ from 'jquery';
+import GfmAutoComplete from '~/gfm_auto_complete';
+
+import 'vendor/jquery.caret';
+import 'vendor/jquery.atwho';
+
+describe('GfmAutoComplete', () => {
+ const gfmAutoCompleteCallbacks = GfmAutoComplete.prototype.getDefaultCallbacks.call({
+ fetchData: () => {},
+ });
+
+ let atwhoInstance;
+ let items;
+ let sorterValue;
+
+ describe('DefaultOptions.sorter', () => {
+ describe('assets loading', () => {
+ beforeEach(() => {
+ jest.spyOn(GfmAutoComplete, 'isLoading').mockReturnValue(true);
+
+ atwhoInstance = { setting: {} };
+ items = [];
+
+ sorterValue = gfmAutoCompleteCallbacks.sorter.call(atwhoInstance, '', items);
+ });
+
+ it('should disable highlightFirst', () => {
+ expect(atwhoInstance.setting.highlightFirst).toBe(false);
+ });
+
+ it('should return the passed unfiltered items', () => {
+ expect(sorterValue).toEqual(items);
+ });
+ });
+
+ describe('assets finished loading', () => {
+ beforeEach(() => {
+ jest.spyOn(GfmAutoComplete, 'isLoading').mockReturnValue(false);
+ jest.spyOn($.fn.atwho.default.callbacks, 'sorter').mockImplementation(() => {});
+ });
+
+ it('should enable highlightFirst if alwaysHighlightFirst is set', () => {
+ atwhoInstance = { setting: { alwaysHighlightFirst: true } };
+
+ gfmAutoCompleteCallbacks.sorter.call(atwhoInstance);
+
+ expect(atwhoInstance.setting.highlightFirst).toBe(true);
+ });
+
+ it('should enable highlightFirst if a query is present', () => {
+ atwhoInstance = { setting: {} };
+
+ gfmAutoCompleteCallbacks.sorter.call(atwhoInstance, 'query');
+
+ expect(atwhoInstance.setting.highlightFirst).toBe(true);
+ });
+
+ it('should call the default atwho sorter', () => {
+ atwhoInstance = { setting: {} };
+
+ const query = 'query';
+ items = [];
+ const searchKey = 'searchKey';
+
+ gfmAutoCompleteCallbacks.sorter.call(atwhoInstance, query, items, searchKey);
+
+ expect($.fn.atwho.default.callbacks.sorter).toHaveBeenCalledWith(query, items, searchKey);
+ });
+ });
+ });
+
+ describe('DefaultOptions.beforeInsert', () => {
+ const beforeInsert = (context, value) =>
+ gfmAutoCompleteCallbacks.beforeInsert.call(context, value);
+
+ beforeEach(() => {
+ atwhoInstance = { setting: { skipSpecialCharacterTest: false } };
+ });
+
+ it('should not quote if value only contains alphanumeric charecters', () => {
+ expect(beforeInsert(atwhoInstance, '@user1')).toBe('@user1');
+ expect(beforeInsert(atwhoInstance, '~label1')).toBe('~label1');
+ });
+
+ it('should quote if value contains any non-alphanumeric characters', () => {
+ expect(beforeInsert(atwhoInstance, '~label-20')).toBe('~"label\\-20"');
+ expect(beforeInsert(atwhoInstance, '~label 20')).toBe('~"label 20"');
+ });
+
+ it('should quote integer labels', () => {
+ expect(beforeInsert(atwhoInstance, '~1234')).toBe('~"1234"');
+ });
+
+ it('should escape Markdown emphasis characters, except in the first character', () => {
+ expect(beforeInsert(atwhoInstance, '@_group')).toEqual('@\\_group');
+ expect(beforeInsert(atwhoInstance, '~_bug')).toEqual('~\\_bug');
+ expect(beforeInsert(atwhoInstance, '~a `bug`')).toEqual('~"a \\`bug\\`"');
+ expect(beforeInsert(atwhoInstance, '~a ~bug')).toEqual('~"a \\~bug"');
+ expect(beforeInsert(atwhoInstance, '~a **bug')).toEqual('~"a \\*\\*bug"');
+ });
+ });
+
+ describe('DefaultOptions.matcher', () => {
+ const defaultMatcher = (context, flag, subtext) =>
+ gfmAutoCompleteCallbacks.matcher.call(context, flag, subtext);
+
+ const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%', '$'];
+ const otherFlags = ['/', ':'];
+ const flags = flagsUseDefaultMatcher.concat(otherFlags);
+
+ const flagsHash = flags.reduce((hash, el) => {
+ hash[el] = null;
+ return hash;
+ }, {});
+
+ beforeEach(() => {
+ atwhoInstance = { setting: {}, app: { controllers: flagsHash } };
+ });
+
+ const minLen = 1;
+ const maxLen = 20;
+ const argumentSize = [minLen, maxLen / 2, maxLen];
+
+ const allowedSymbols = [
+ '',
+ 'a',
+ 'n',
+ 'z',
+ 'A',
+ 'Z',
+ 'N',
+ '0',
+ '5',
+ '9',
+ 'Ð',
+ 'а',
+ 'Я',
+ 'Ñ',
+ '.',
+ "'",
+ '+',
+ '-',
+ '_',
+ ];
+ const jointAllowedSymbols = allowedSymbols.join('');
+
+ describe('should match regular symbols', () => {
+ flagsUseDefaultMatcher.forEach(flag => {
+ allowedSymbols.forEach(symbol => {
+ argumentSize.forEach(size => {
+ const query = new Array(size + 1).join(symbol);
+ const subtext = flag + query;
+
+ it(`matches argument "${flag}" with query "${subtext}"`, () => {
+ expect(defaultMatcher(atwhoInstance, flag, subtext)).toBe(query);
+ });
+ });
+ });
+
+ it(`matches combination of allowed symbols for flag "${flag}"`, () => {
+ const subtext = flag + jointAllowedSymbols;
+
+ expect(defaultMatcher(atwhoInstance, flag, subtext)).toBe(jointAllowedSymbols);
+ });
+ });
+ });
+
+ describe('should not match special sequences', () => {
+ const shouldNotBeFollowedBy = flags.concat(['\x00', '\x10', '\x3f', '\n', ' ']);
+ const shouldNotBePrependedBy = ['`'];
+
+ flagsUseDefaultMatcher.forEach(atSign => {
+ shouldNotBeFollowedBy.forEach(followedSymbol => {
+ const seq = atSign + followedSymbol;
+
+ it(`should not match ${JSON.stringify(seq)}`, () => {
+ expect(defaultMatcher(atwhoInstance, atSign, seq)).toBe(null);
+ });
+ });
+
+ shouldNotBePrependedBy.forEach(prependedSymbol => {
+ const seq = prependedSymbol + atSign;
+
+ it(`should not match "${seq}"`, () => {
+ expect(defaultMatcher(atwhoInstance, atSign, seq)).toBe(null);
+ });
+ });
+ });
+ });
+ });
+
+ describe('isLoading', () => {
+ it('should be true with loading data object item', () => {
+ expect(GfmAutoComplete.isLoading({ name: 'loading' })).toBe(true);
+ });
+
+ it('should be true with loading data array', () => {
+ expect(GfmAutoComplete.isLoading(['loading'])).toBe(true);
+ });
+
+ it('should be true with loading data object array', () => {
+ expect(GfmAutoComplete.isLoading([{ name: 'loading' }])).toBe(true);
+ });
+
+ it('should be false with actual array data', () => {
+ expect(
+ GfmAutoComplete.isLoading([{ title: 'Foo' }, { title: 'Bar' }, { title: 'Qux' }]),
+ ).toBe(false);
+ });
+
+ it('should be false with actual data item', () => {
+ expect(GfmAutoComplete.isLoading({ title: 'Foo' })).toBe(false);
+ });
+ });
+
+ describe('Issues.insertTemplateFunction', () => {
+ it('should return default template', () => {
+ expect(GfmAutoComplete.Issues.insertTemplateFunction({ id: 5, title: 'Some Issue' })).toBe(
+ '${atwho-at}${id}', // eslint-disable-line no-template-curly-in-string
+ );
+ });
+
+ it('should return reference when reference is set', () => {
+ expect(
+ GfmAutoComplete.Issues.insertTemplateFunction({
+ id: 5,
+ title: 'Some Issue',
+ reference: 'grp/proj#5',
+ }),
+ ).toBe('grp/proj#5');
+ });
+ });
+
+ describe('Issues.templateFunction', () => {
+ it('should return html with id and title', () => {
+ expect(GfmAutoComplete.Issues.templateFunction({ id: 5, title: 'Some Issue' })).toBe(
+ '<li><small>5</small> Some Issue</li>',
+ );
+ });
+
+ it('should replace id with reference if reference is set', () => {
+ expect(
+ GfmAutoComplete.Issues.templateFunction({
+ id: 5,
+ title: 'Some Issue',
+ reference: 'grp/proj#5',
+ }),
+ ).toBe('<li><small>grp/proj#5</small> Some Issue</li>');
+ });
+ });
+});
diff --git a/spec/javascripts/issuable_suggestions/components/app_spec.js b/spec/frontend/issuable_suggestions/components/app_spec.js
index 7bb8e26b81a..7bb8e26b81a 100644
--- a/spec/javascripts/issuable_suggestions/components/app_spec.js
+++ b/spec/frontend/issuable_suggestions/components/app_spec.js
diff --git a/spec/javascripts/issuable_suggestions/components/item_spec.js b/spec/frontend/issuable_suggestions/components/item_spec.js
index 7bd1fe678f4..7bd1fe678f4 100644
--- a/spec/javascripts/issuable_suggestions/components/item_spec.js
+++ b/spec/frontend/issuable_suggestions/components/item_spec.js
diff --git a/spec/javascripts/issuable_suggestions/mock_data.js b/spec/frontend/issuable_suggestions/mock_data.js
index 4f0f9ef8d62..4f0f9ef8d62 100644
--- a/spec/javascripts/issuable_suggestions/mock_data.js
+++ b/spec/frontend/issuable_suggestions/mock_data.js
diff --git a/spec/frontend/lib/utils/ajax_cache_spec.js b/spec/frontend/lib/utils/ajax_cache_spec.js
new file mode 100644
index 00000000000..e2ee70b9d69
--- /dev/null
+++ b/spec/frontend/lib/utils/ajax_cache_spec.js
@@ -0,0 +1,161 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import AjaxCache from '~/lib/utils/ajax_cache';
+
+describe('AjaxCache', () => {
+ const dummyEndpoint = '/AjaxCache/dummyEndpoint';
+ const dummyResponse = {
+ important: 'dummy data',
+ };
+
+ beforeEach(() => {
+ AjaxCache.internalStorage = {};
+ AjaxCache.pendingRequests = {};
+ });
+
+ describe('get', () => {
+ it('returns undefined if cache is empty', () => {
+ const data = AjaxCache.get(dummyEndpoint);
+
+ expect(data).toBe(undefined);
+ });
+
+ it('returns undefined if cache contains no matching data', () => {
+ AjaxCache.internalStorage['not matching'] = dummyResponse;
+
+ const data = AjaxCache.get(dummyEndpoint);
+
+ expect(data).toBe(undefined);
+ });
+
+ it('returns matching data', () => {
+ AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
+
+ const data = AjaxCache.get(dummyEndpoint);
+
+ expect(data).toBe(dummyResponse);
+ });
+ });
+
+ describe('hasData', () => {
+ it('returns false if cache is empty', () => {
+ expect(AjaxCache.hasData(dummyEndpoint)).toBe(false);
+ });
+
+ it('returns false if cache contains no matching data', () => {
+ AjaxCache.internalStorage['not matching'] = dummyResponse;
+
+ expect(AjaxCache.hasData(dummyEndpoint)).toBe(false);
+ });
+
+ it('returns true if data is available', () => {
+ AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
+
+ expect(AjaxCache.hasData(dummyEndpoint)).toBe(true);
+ });
+ });
+
+ describe('remove', () => {
+ it('does nothing if cache is empty', () => {
+ AjaxCache.remove(dummyEndpoint);
+
+ expect(AjaxCache.internalStorage).toEqual({});
+ });
+
+ it('does nothing if cache contains no matching data', () => {
+ AjaxCache.internalStorage['not matching'] = dummyResponse;
+
+ AjaxCache.remove(dummyEndpoint);
+
+ expect(AjaxCache.internalStorage['not matching']).toBe(dummyResponse);
+ });
+
+ it('removes matching data', () => {
+ AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
+
+ AjaxCache.remove(dummyEndpoint);
+
+ expect(AjaxCache.internalStorage).toEqual({});
+ });
+ });
+
+ describe('override', () => {
+ it('overrides existing cache', () => {
+ AjaxCache.internalStorage.endpoint = 'existing-endpoint';
+ AjaxCache.override('endpoint', 'new-endpoint');
+
+ expect(AjaxCache.internalStorage.endpoint).toEqual('new-endpoint');
+ });
+ });
+
+ describe('retrieve', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+
+ jest.spyOn(axios, 'get');
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ it('stores and returns data from Ajax call if cache is empty', () => {
+ mock.onGet(dummyEndpoint).reply(200, dummyResponse);
+
+ return AjaxCache.retrieve(dummyEndpoint).then(data => {
+ expect(data).toEqual(dummyResponse);
+ expect(AjaxCache.internalStorage[dummyEndpoint]).toEqual(dummyResponse);
+ });
+ });
+
+ it('makes no Ajax call if request is pending', () => {
+ mock.onGet(dummyEndpoint).reply(200, dummyResponse);
+
+ return Promise.all([
+ AjaxCache.retrieve(dummyEndpoint),
+ AjaxCache.retrieve(dummyEndpoint),
+ ]).then(() => {
+ expect(axios.get).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ it('returns undefined if Ajax call fails and cache is empty', () => {
+ const errorMessage = 'Network Error';
+ mock.onGet(dummyEndpoint).networkError();
+
+ expect.assertions(2);
+ return AjaxCache.retrieve(dummyEndpoint).catch(error => {
+ expect(error.message).toBe(`${dummyEndpoint}: ${errorMessage}`);
+ expect(error.textStatus).toBe(errorMessage);
+ });
+ });
+
+ it('makes no Ajax call if matching data exists', () => {
+ AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
+
+ return AjaxCache.retrieve(dummyEndpoint).then(data => {
+ expect(data).toBe(dummyResponse);
+ expect(axios.get).not.toHaveBeenCalled();
+ });
+ });
+
+ it('makes Ajax call even if matching data exists when forceRequest parameter is provided', () => {
+ const oldDummyResponse = {
+ important: 'old dummy data',
+ };
+
+ AjaxCache.internalStorage[dummyEndpoint] = oldDummyResponse;
+
+ mock.onGet(dummyEndpoint).reply(200, dummyResponse);
+
+ return Promise.all([
+ AjaxCache.retrieve(dummyEndpoint),
+ AjaxCache.retrieve(dummyEndpoint, true),
+ ]).then(data => {
+ expect(data).toEqual([oldDummyResponse, dummyResponse]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap b/spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap
new file mode 100644
index 00000000000..11d65ced180
--- /dev/null
+++ b/spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap
@@ -0,0 +1,20 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`JumpToNextDiscussionButton matches the snapshot 1`] = `
+<div
+ class="btn-group"
+ role="group"
+>
+ <button
+ class="btn btn-default discussion-next-btn"
+ data-original-title="Jump to next unresolved discussion"
+ title=""
+ >
+ <icon-stub
+ cssclasses=""
+ name="comment-next"
+ size="16"
+ />
+ </button>
+</div>
+`;
diff --git a/spec/frontend/notes/components/discussion_jump_to_next_button_spec.js b/spec/frontend/notes/components/discussion_jump_to_next_button_spec.js
new file mode 100644
index 00000000000..989b0458481
--- /dev/null
+++ b/spec/frontend/notes/components/discussion_jump_to_next_button_spec.js
@@ -0,0 +1,30 @@
+import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue';
+import { shallowMount } from '@vue/test-utils';
+
+describe('JumpToNextDiscussionButton', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = shallowMount(JumpToNextDiscussionButton, {
+ sync: false,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('matches the snapshot', () => {
+ expect(wrapper.vm.$el).toMatchSnapshot();
+ });
+
+ it('emits onClick event on button click', () => {
+ const button = wrapper.find({ ref: 'button' });
+
+ button.trigger('click');
+
+ expect(wrapper.emitted()).toEqual({
+ onClick: [[]],
+ });
+ });
+});
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index 7ad2e97e7e6..d892889b98d 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -1,3 +1,7 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import axios from '~/lib/utils/axios_utils';
+
const testTimeoutInMs = 300;
jest.setTimeout(testTimeoutInMs);
@@ -14,3 +18,17 @@ afterEach(() => {
throw new Error(`Test took too long (${elapsedTimeInMs}ms > ${testTimeoutInMs}ms)!`);
}
});
+
+// fail tests for unmocked requests
+beforeEach(done => {
+ axios.defaults.adapter = config => {
+ const error = new Error(`Unexpected unmocked request: ${JSON.stringify(config, null, 2)}`);
+ error.config = config;
+ done.fail(error);
+ return Promise.reject(error);
+ };
+
+ done();
+});
+
+Vue.use(Translate);
diff --git a/spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap
new file mode 100644
index 00000000000..26eae2d5e61
--- /dev/null
+++ b/spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap
@@ -0,0 +1,37 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`File row header component adds multiple ellipsises after 40 characters 1`] = `
+<div
+ class="file-row-header bg-white sticky-top p-2 js-file-row-header"
+>
+ <span
+ class="bold"
+ >
+ app/assets/javascripts/…/…/diffs/notes
+ </span>
+</div>
+`;
+
+exports[`File row header component renders file path 1`] = `
+<div
+ class="file-row-header bg-white sticky-top p-2 js-file-row-header"
+>
+ <span
+ class="bold"
+ >
+ app/assets
+ </span>
+</div>
+`;
+
+exports[`File row header component trucates path after 40 characters 1`] = `
+<div
+ class="file-row-header bg-white sticky-top p-2 js-file-row-header"
+>
+ <span
+ class="bold"
+ >
+ app/assets/javascripts/merge_requests
+ </span>
+</div>
+`;
diff --git a/spec/frontend/vue_shared/components/file_row_header_spec.js b/spec/frontend/vue_shared/components/file_row_header_spec.js
new file mode 100644
index 00000000000..80f4c275dcc
--- /dev/null
+++ b/spec/frontend/vue_shared/components/file_row_header_spec.js
@@ -0,0 +1,36 @@
+import { shallowMount } from '@vue/test-utils';
+import FileRowHeader from '~/vue_shared/components/file_row_header.vue';
+
+describe('File row header component', () => {
+ let vm;
+
+ function createComponent(path) {
+ vm = shallowMount(FileRowHeader, {
+ propsData: {
+ path,
+ },
+ });
+ }
+
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ it('renders file path', () => {
+ createComponent('app/assets');
+
+ expect(vm.element).toMatchSnapshot();
+ });
+
+ it('trucates path after 40 characters', () => {
+ createComponent('app/assets/javascripts/merge_requests');
+
+ expect(vm.element).toMatchSnapshot();
+ });
+
+ it('adds multiple ellipsises after 40 characters', () => {
+ createComponent('app/assets/javascripts/merge_requests/widget/diffs/notes');
+
+ expect(vm.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/graphql/features/authorization_spec.rb b/spec/graphql/features/authorization_spec.rb
new file mode 100644
index 00000000000..a229d29afa6
--- /dev/null
+++ b/spec/graphql/features/authorization_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Gitlab::Graphql::Authorization' do
+ set(:user) { create(:user) }
+
+ let(:test_object) { double(name: 'My name') }
+ let(:object_type) { object_type_class }
+ let(:query_type) { query_type_class(object_type, test_object) }
+ let(:schema) { schema_class(query_type) }
+
+ let(:execute) do
+ schema.execute(
+ query_string,
+ context: { current_user: user },
+ variables: {}
+ )
+ end
+
+ let(:result) { execute['data'] }
+
+ before do
+ # By default, disallow all permissions.
+ allow(Ability).to receive(:allowed?).and_return(false)
+ end
+
+ describe 'authorizing with a single permission' do
+ let(:query_string) { '{ singlePermission() { name } }' }
+
+ subject { result['singlePermission'] }
+
+ it 'should return the protected field when user has permission' do
+ permit(:foo)
+
+ expect(subject['name']).to eq(test_object.name)
+ end
+
+ it 'should return nil when user is not authorized' do
+ expect(subject).to be_nil
+ end
+ end
+
+ describe 'authorizing with an Array of permissions' do
+ let(:query_string) { '{ permissionCollection() { name } }' }
+
+ subject { result['permissionCollection'] }
+
+ it 'should return the protected field when user has all permissions' do
+ permit(:foo, :bar)
+
+ expect(subject['name']).to eq(test_object.name)
+ end
+
+ it 'should return nil when user only has one of the permissions' do
+ permit(:foo)
+
+ expect(subject).to be_nil
+ end
+
+ it 'should return nil when user only has none of the permissions' do
+ expect(subject).to be_nil
+ end
+ end
+
+ private
+
+ def permit(*permissions)
+ permissions.each do |permission|
+ allow(Ability).to receive(:allowed?).with(user, permission, test_object).and_return(true)
+ end
+ end
+
+ def object_type_class
+ Class.new(Types::BaseObject) do
+ graphql_name 'TestObject'
+
+ field :name, GraphQL::STRING_TYPE, null: true
+ end
+ end
+
+ def query_type_class(type, object)
+ Class.new(Types::BaseObject) do
+ graphql_name 'TestQuery'
+
+ field :single_permission, type,
+ null: true,
+ authorize: :foo,
+ resolve: ->(obj, args, ctx) { object }
+
+ field :permission_collection, type,
+ null: true,
+ resolve: ->(obj, args, ctx) { object } do
+ authorize [:foo, :bar]
+ end
+ end
+ end
+
+ def schema_class(query)
+ Class.new(GraphQL::Schema) do
+ use Gitlab::Graphql::Authorize
+
+ query(query)
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/base_resolver_spec.rb b/spec/graphql/resolvers/base_resolver_spec.rb
new file mode 100644
index 00000000000..e3a34762b62
--- /dev/null
+++ b/spec/graphql/resolvers/base_resolver_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::BaseResolver do
+ include GraphqlHelpers
+
+ let(:resolver) do
+ Class.new(described_class) do
+ def resolve(**args)
+ [args, args]
+ end
+ end
+ end
+
+ describe '.single' do
+ it 'returns a subclass from the resolver' do
+ expect(resolver.single.superclass).to eq(resolver)
+ end
+
+ it 'returns the same subclass every time' do
+ expect(resolver.single.object_id).to eq(resolver.single.object_id)
+ end
+
+ it 'returns a resolver that gives the first result from the original resolver' do
+ result = resolve(resolver.single, args: { test: 1 })
+
+ expect(result).to eq(test: 1)
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index ca90673521c..5f9c180cbb7 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -5,16 +5,63 @@ describe Resolvers::IssuesResolver do
let(:current_user) { create(:user) }
set(:project) { create(:project) }
- set(:issue) { create(:issue, project: project) }
- set(:issue2) { create(:issue, project: project, title: 'foo') }
+ set(:issue1) { create(:issue, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago) }
+ set(:issue2) { create(:issue, project: project, state: :closed, title: 'foo', created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago) }
+ set(:label1) { create(:label, project: project) }
+ set(:label2) { create(:label, project: project) }
before do
project.add_developer(current_user)
+ create(:label_link, label: label1, target: issue1)
+ create(:label_link, label: label1, target: issue2)
+ create(:label_link, label: label2, target: issue2)
end
describe '#resolve' do
it 'finds all issues' do
- expect(resolve_issues).to contain_exactly(issue, issue2)
+ expect(resolve_issues).to contain_exactly(issue1, issue2)
+ end
+
+ it 'filters by state' do
+ expect(resolve_issues(state: 'opened')).to contain_exactly(issue1)
+ expect(resolve_issues(state: 'closed')).to contain_exactly(issue2)
+ end
+
+ it 'filters by labels' do
+ expect(resolve_issues(label_name: [label1.title])).to contain_exactly(issue1, issue2)
+ expect(resolve_issues(label_name: [label1.title, label2.title])).to contain_exactly(issue2)
+ end
+
+ describe 'filters by created_at' do
+ it 'filters by created_before' do
+ expect(resolve_issues(created_before: 2.hours.ago)).to contain_exactly(issue1)
+ end
+
+ it 'filters by created_after' do
+ expect(resolve_issues(created_after: 2.hours.ago)).to contain_exactly(issue2)
+ end
+ end
+
+ describe 'filters by updated_at' do
+ it 'filters by updated_before' do
+ expect(resolve_issues(updated_before: 2.hours.ago)).to contain_exactly(issue1)
+ end
+
+ it 'filters by updated_after' do
+ expect(resolve_issues(updated_after: 2.hours.ago)).to contain_exactly(issue2)
+ end
+ end
+
+ describe 'filters by closed_at' do
+ let!(:issue3) { create(:issue, project: project, state: :closed, closed_at: 3.hours.ago) }
+
+ it 'filters by closed_before' do
+ expect(resolve_issues(closed_before: 2.hours.ago)).to contain_exactly(issue3)
+ end
+
+ it 'filters by closed_after' do
+ expect(resolve_issues(closed_after: 2.hours.ago)).to contain_exactly(issue2)
+ end
end
it 'searches issues' do
@@ -22,7 +69,7 @@ describe Resolvers::IssuesResolver do
end
it 'sort issues' do
- expect(resolve_issues(sort: 'created_desc')).to eq [issue2, issue]
+ expect(resolve_issues(sort: 'created_desc')).to eq [issue2, issue1]
end
it 'returns issues user can see' do
@@ -30,7 +77,31 @@ describe Resolvers::IssuesResolver do
create(:issue, confidential: true)
- expect(resolve_issues).to contain_exactly(issue, issue2)
+ expect(resolve_issues).to contain_exactly(issue1, issue2)
+ end
+
+ it 'finds a specific issue with iid' do
+ expect(resolve_issues(iid: issue1.iid)).to contain_exactly(issue1)
+ end
+
+ it 'finds a specific issue with iids' do
+ expect(resolve_issues(iids: issue1.iid)).to contain_exactly(issue1)
+ end
+
+ it 'finds multiple issues with iids' do
+ expect(resolve_issues(iids: [issue1.iid, issue2.iid]))
+ .to contain_exactly(issue1, issue2)
+ end
+
+ it 'finds only the issues within the project we are looking at' do
+ another_project = create(:project)
+ iids = [issue1, issue2].map(&:iid)
+
+ iids.each do |iid|
+ create(:issue, project: another_project, iid: iid)
+ end
+
+ expect(resolve_issues(iids: iids)).to contain_exactly(issue1, issue2)
end
end
diff --git a/spec/graphql/resolvers/merge_request_resolver_spec.rb b/spec/graphql/resolvers/merge_request_resolver_spec.rb
deleted file mode 100644
index 73993b3a039..00000000000
--- a/spec/graphql/resolvers/merge_request_resolver_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-require 'spec_helper'
-
-describe Resolvers::MergeRequestResolver do
- include GraphqlHelpers
-
- set(:project) { create(:project, :repository) }
- set(:merge_request_1) { create(:merge_request, :simple, source_project: project, target_project: project) }
- set(:merge_request_2) { create(:merge_request, :rebased, source_project: project, target_project: project) }
-
- set(:other_project) { create(:project, :repository) }
- set(:other_merge_request) { create(:merge_request, source_project: other_project, target_project: other_project) }
-
- let(:iid_1) { merge_request_1.iid }
- let(:iid_2) { merge_request_2.iid }
-
- let(:other_iid) { other_merge_request.iid }
-
- describe '#resolve' do
- it 'batch-resolves merge requests by target project full path and IID' do
- result = batch(max_queries: 2) do
- [resolve_mr(project, iid_1), resolve_mr(project, iid_2)]
- end
-
- expect(result).to contain_exactly(merge_request_1, merge_request_2)
- end
-
- it 'can batch-resolve merge requests from different projects' do
- result = batch(max_queries: 3) do
- [resolve_mr(project, iid_1), resolve_mr(project, iid_2), resolve_mr(other_project, other_iid)]
- end
-
- expect(result).to contain_exactly(merge_request_1, merge_request_2, other_merge_request)
- end
-
- it 'resolves an unknown iid to nil' do
- result = batch { resolve_mr(project, -1) }
-
- expect(result).to be_nil
- end
- end
-
- def resolve_mr(project, iid)
- resolve(described_class, obj: project, args: { iid: iid })
- end
-end
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
new file mode 100644
index 00000000000..ab3c426b2cd
--- /dev/null
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+describe Resolvers::MergeRequestsResolver do
+ include GraphqlHelpers
+
+ set(:project) { create(:project, :repository) }
+ set(:merge_request_1) { create(:merge_request, :simple, source_project: project, target_project: project) }
+ set(:merge_request_2) { create(:merge_request, :rebased, source_project: project, target_project: project) }
+
+ set(:other_project) { create(:project, :repository) }
+ set(:other_merge_request) { create(:merge_request, source_project: other_project, target_project: other_project) }
+
+ let(:iid_1) { merge_request_1.iid }
+ let(:iid_2) { merge_request_2.iid }
+
+ let(:other_iid) { other_merge_request.iid }
+
+ describe '#resolve' do
+ it 'batch-resolves by target project full path and individual IID' do
+ result = batch(max_queries: 2) do
+ resolve_mr(project, iid: iid_1) + resolve_mr(project, iid: iid_2)
+ end
+
+ expect(result).to contain_exactly(merge_request_1, merge_request_2)
+ end
+
+ it 'batch-resolves by target project full path and IIDS' do
+ result = batch(max_queries: 2) do
+ resolve_mr(project, iids: [iid_1, iid_2])
+ end
+
+ expect(result).to contain_exactly(merge_request_1, merge_request_2)
+ end
+
+ it 'can batch-resolve merge requests from different projects' do
+ result = batch(max_queries: 3) do
+ resolve_mr(project, iid: iid_1) +
+ resolve_mr(project, iid: iid_2) +
+ resolve_mr(other_project, iid: other_iid)
+ end
+
+ expect(result).to contain_exactly(merge_request_1, merge_request_2, other_merge_request)
+ end
+
+ it 'resolves an unknown iid to be empty' do
+ result = batch { resolve_mr(project, iid: -1) }
+
+ expect(result).to be_empty
+ end
+
+ it 'resolves empty iids to be empty' do
+ result = batch { resolve_mr(project, iids: []) }
+
+ expect(result).to be_empty
+ end
+ end
+
+ def resolve_mr(project, args)
+ resolve(described_class, obj: project, args: args)
+ end
+end
diff --git a/spec/graphql/resolvers/metadata_resolver_spec.rb b/spec/graphql/resolvers/metadata_resolver_spec.rb
new file mode 100644
index 00000000000..e662ed127a5
--- /dev/null
+++ b/spec/graphql/resolvers/metadata_resolver_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe Resolvers::MetadataResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ it 'returns version and revision' do
+ expect(resolve(described_class)).to eq(version: Gitlab::VERSION, revision: Gitlab.revision)
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/project_pipelines_resolver_spec.rb b/spec/graphql/resolvers/project_pipelines_resolver_spec.rb
index 407ca2f9d78..6862ae8a5ed 100644
--- a/spec/graphql/resolvers/project_pipelines_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_pipelines_resolver_spec.rb
@@ -4,7 +4,7 @@ describe Resolvers::ProjectPipelinesResolver do
include GraphqlHelpers
set(:project) { create(:project) }
- set(:pipeline) { create(:ci_pipeline, project: project) }
+ set(:pipeline) { create(:ci_pipeline, project: project) }
set(:other_pipeline) { create(:ci_pipeline) }
let(:current_user) { create(:user) }
diff --git a/spec/graphql/types/issuable_state_enum_spec.rb b/spec/graphql/types/issuable_state_enum_spec.rb
new file mode 100644
index 00000000000..65a80fa4176
--- /dev/null
+++ b/spec/graphql/types/issuable_state_enum_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GitlabSchema.types['IssuableState'] do
+ it { expect(described_class.graphql_name).to eq('IssuableState') }
+
+ it_behaves_like 'issuable state'
+end
diff --git a/spec/graphql/types/issue_state_enum_spec.rb b/spec/graphql/types/issue_state_enum_spec.rb
new file mode 100644
index 00000000000..de19e6fc505
--- /dev/null
+++ b/spec/graphql/types/issue_state_enum_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GitlabSchema.types['IssueState'] do
+ it { expect(described_class.graphql_name).to eq('IssueState') }
+
+ it_behaves_like 'issuable state'
+end
diff --git a/spec/graphql/types/merge_request_state_enum_spec.rb b/spec/graphql/types/merge_request_state_enum_spec.rb
new file mode 100644
index 00000000000..626e33b18d3
--- /dev/null
+++ b/spec/graphql/types/merge_request_state_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GitlabSchema.types['MergeRequestState'] do
+ it { expect(described_class.graphql_name).to eq('MergeRequestState') }
+
+ it_behaves_like 'issuable state'
+
+ it 'exposes all the existing merge request states' do
+ expect(described_class.values.keys).to include('merged')
+ end
+end
diff --git a/spec/graphql/types/metadata_type_spec.rb b/spec/graphql/types/metadata_type_spec.rb
new file mode 100644
index 00000000000..55205bf5b6a
--- /dev/null
+++ b/spec/graphql/types/metadata_type_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe GitlabSchema.types['Metadata'] do
+ it { expect(described_class.graphql_name).to eq('Metadata') }
+end
diff --git a/spec/graphql/types/permission_types/base_permission_type_spec.rb b/spec/graphql/types/permission_types/base_permission_type_spec.rb
index a7e51797047..0ee8b883d51 100644
--- a/spec/graphql/types/permission_types/base_permission_type_spec.rb
+++ b/spec/graphql/types/permission_types/base_permission_type_spec.rb
@@ -8,7 +8,7 @@ describe Types::PermissionTypes::BasePermissionType do
Class.new(described_class) do
graphql_name 'TestClass'
- permission_field :do_stuff, resolve: -> (_, _, _) { true }
+ permission_field :do_stuff, resolve: -> (_, _, _) { true }
ability_field(:read_issue)
abilities :admin_issue
end
diff --git a/spec/graphql/types/permission_types/project_spec.rb b/spec/graphql/types/permission_types/project_spec.rb
index 927153adc5b..4288412eda3 100644
--- a/spec/graphql/types/permission_types/project_spec.rb
+++ b/spec/graphql/types/permission_types/project_spec.rb
@@ -5,7 +5,7 @@ describe Types::PermissionTypes::Project do
expected_permissions = [
:change_namespace, :change_visibility_level, :rename_project, :remove_project, :archive_project,
:remove_fork_project, :remove_pages, :read_project, :create_merge_request_in,
- :read_wiki, :read_project_member, :create_issue, :upload_file, :read_cycle_analytics,
+ :read_wiki, :read_project_member, :create_issue, :upload_file, :read_cycle_analytics,
:download_code, :download_wiki_code, :fork_project, :create_project_snippet,
:read_commit_status, :request_access, :create_pipeline, :create_pipeline_schedule,
:create_merge_request_from, :create_wiki, :push_code, :create_deployment, :push_to_delete_protected_branch,
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 61d4c42665a..e8f1c84f8d6 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -6,11 +6,17 @@ describe GitlabSchema.types['Project'] do
it { expect(described_class.graphql_name).to eq('Project') }
describe 'nested merge request' do
+ it { expect(described_class).to have_graphql_field(:merge_requests) }
it { expect(described_class).to have_graphql_field(:merge_request) }
it 'authorizes the merge request' do
expect(described_class.fields['mergeRequest'])
- .to require_graphql_authorizations(:read_merge_request)
+ .to require_graphql_authorizations(:read_merge_request)
+ end
+
+ it 'authorizes the merge requests' do
+ expect(described_class.fields['mergeRequests'])
+ .to require_graphql_authorizations(:read_merge_request)
end
end
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index e1df6f9811d..07c61ea7647 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -5,7 +5,7 @@ describe GitlabSchema.types['Query'] do
expect(described_class.graphql_name).to eq('Query')
end
- it { is_expected.to have_graphql_fields(:project, :echo) }
+ it { is_expected.to have_graphql_fields(:project, :echo, :metadata) }
describe 'project field' do
subject { described_class.fields['project'] }
@@ -20,4 +20,17 @@ describe GitlabSchema.types['Query'] do
is_expected.to require_graphql_authorizations(:read_project)
end
end
+
+ describe 'metadata field' do
+ subject { described_class.fields['metadata'] }
+
+ it 'returns metadata' do
+ is_expected.to have_graphql_type(Types::MetadataType)
+ is_expected.to have_graphql_resolver(Resolvers::MetadataResolver)
+ end
+
+ it 'authorizes with read_instance_metadata' do
+ is_expected.to require_graphql_authorizations(:read_instance_metadata)
+ end
+ end
end
diff --git a/spec/helpers/appearances_helper_spec.rb b/spec/helpers/appearances_helper_spec.rb
new file mode 100644
index 00000000000..8d717b968dd
--- /dev/null
+++ b/spec/helpers/appearances_helper_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe AppearancesHelper do
+ before do
+ user = create(:user)
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ describe '#header_message' do
+ it 'returns nil when header message field is not set' do
+ create(:appearance)
+
+ expect(helper.header_message).to be_nil
+ end
+
+ context 'when header message is set' do
+ it 'includes current message' do
+ message = "Foo bar"
+ create(:appearance, header_message: message)
+
+ expect(helper.header_message).to include(message)
+ end
+ end
+ end
+
+ describe '#footer_message' do
+ it 'returns nil when footer message field is not set' do
+ create(:appearance)
+
+ expect(helper.footer_message).to be_nil
+ end
+
+ context 'when footer message is set' do
+ it 'includes current message' do
+ message = "Foo bar"
+ create(:appearance, footer_message: message)
+
+ expect(helper.footer_message).to include(message)
+ end
+ end
+ end
+
+ describe '#brand_image' do
+ let!(:appearance) { create(:appearance, :with_logo) }
+
+ context 'when there is a logo' do
+ it 'returns a path' do
+ expect(helper.brand_image).to match(%r(img data-src="/uploads/-/system/appearance/.*png))
+ end
+ end
+
+ context 'when there is a logo but no associated upload' do
+ before do
+ # Legacy attachments were not tracked in the uploads table
+ appearance.logo.upload.destroy
+ appearance.reload
+ end
+
+ it 'falls back to using the original path' do
+ expect(helper.brand_image).to match(%r(img data-src="/uploads/-/system/appearance/.*png))
+ end
+ end
+ end
+
+ describe '#brand_title' do
+ it 'returns the default CE title when no appearance is present' do
+ allow(helper)
+ .to receive(:current_appearance)
+ .and_return(nil)
+
+ expect(helper.brand_title).to eq('GitLab Community Edition')
+ end
+ end
+end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 4135f31e051..b81249a1e29 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -168,6 +168,21 @@ describe ApplicationHelper do
end
end
+ describe '#client_class_list' do
+ it 'returns string containing CSS classes representing client browser and platform' do
+ class_list = helper.client_class_list
+ expect(class_list).to eq('gl-browser-generic gl-platform-other')
+ end
+ end
+
+ describe '#client_js_flags' do
+ it 'returns map containing JS flags representing client browser and platform' do
+ flags_list = helper.client_js_flags
+ expect(flags_list[:isGeneric]).to eq(true)
+ expect(flags_list[:isOther]).to eq(true)
+ end
+ end
+
describe '#autocomplete_data_sources' do
let(:project) { create(:project) }
let(:noteable_type) { Issue }
diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb
new file mode 100644
index 00000000000..705523f1110
--- /dev/null
+++ b/spec/helpers/application_settings_helper_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ApplicationSettingsHelper do
+ context 'when all protocols in use' do
+ before do
+ stub_application_setting(enabled_git_access_protocol: '')
+ end
+
+ it { expect(all_protocols_enabled?).to be_truthy }
+ it { expect(http_enabled?).to be_truthy }
+ it { expect(ssh_enabled?).to be_truthy }
+ end
+
+ context 'when SSH is only in use' do
+ before do
+ stub_application_setting(enabled_git_access_protocol: 'ssh')
+ end
+
+ it { expect(all_protocols_enabled?).to be_falsey }
+ it { expect(http_enabled?).to be_falsey }
+ it { expect(ssh_enabled?).to be_truthy }
+ end
+
+ shared_examples 'when HTTP protocol is in use' do |protocol|
+ before do
+ allow(Gitlab.config.gitlab).to receive(:protocol).and_return(protocol)
+ stub_application_setting(enabled_git_access_protocol: 'http')
+ end
+
+ it { expect(all_protocols_enabled?).to be_falsey }
+ it { expect(http_enabled?).to be_truthy }
+ it { expect(ssh_enabled?).to be_falsey }
+ end
+
+ it_behaves_like 'when HTTP protocol is in use', 'https'
+ it_behaves_like 'when HTTP protocol is in use', 'http'
+end
diff --git a/spec/helpers/auto_devops_helper_spec.rb b/spec/helpers/auto_devops_helper_spec.rb
index 75c30dbfe48..223e562238d 100644
--- a/spec/helpers/auto_devops_helper_spec.rb
+++ b/spec/helpers/auto_devops_helper_spec.rb
@@ -90,39 +90,4 @@ describe AutoDevopsHelper do
it { is_expected.to eq(false) }
end
end
-
- describe '.auto_devops_warning_message' do
- subject { helper.auto_devops_warning_message(project) }
-
- context 'when the service is missing' do
- before do
- allow(helper).to receive(:missing_auto_devops_service?).and_return(true)
- end
-
- context 'when the domain is missing' do
- before do
- allow(helper).to receive(:missing_auto_devops_domain?).and_return(true)
- end
-
- it { is_expected.to match(/Auto Review Apps and Auto Deploy need a domain name and a .* to work correctly./) }
- end
-
- context 'when the domain is not missing' do
- before do
- allow(helper).to receive(:missing_auto_devops_domain?).and_return(false)
- end
-
- it { is_expected.to match(/Auto Review Apps and Auto Deploy need a .* to work correctly./) }
- end
- end
-
- context 'when the domain is missing' do
- before do
- allow(helper).to receive(:missing_auto_devops_service?).and_return(false)
- allow(helper).to receive(:missing_auto_devops_domain?).and_return(true)
- end
-
- it { is_expected.to eq('Auto Review Apps and Auto Deploy need a domain name to work correctly.') }
- end
- end
end
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index f709f152c92..2bc3933809f 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -50,12 +50,20 @@ describe BlobHelper do
end
it 'returns a link with the proper route' do
+ stub_feature_flags(web_ide_default: false)
link = edit_blob_button(project, 'master', 'README.md')
expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/edit/master/README.md")
end
+ it 'returns a link with a Web IDE route' do
+ link = edit_blob_button(project, 'master', 'README.md')
+
+ expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/-/ide/project/#{project.full_path}/edit/master/-/README.md")
+ end
+
it 'returns a link with the passed link_opts on the expected route' do
+ stub_feature_flags(web_ide_default: false)
link = edit_blob_button(project, 'master', 'README.md', link_opts: { mr_id: 10 })
expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/edit/master/README.md?mr_id=10")
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index 9c0e55739d6..824b3ab4fc1 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -21,7 +21,7 @@ describe CommitsHelper do
expect(helper.commit_author_link(commit))
.to include('Foo &lt;script&gt;')
expect(helper.commit_author_link(commit, avatar: true))
- .to include('commit-author-name', 'Foo &lt;script&gt;')
+ .to include('commit-author-name', 'js-user-link', 'Foo &lt;script&gt;')
end
end
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index 53c010fa0db..5396243f44d 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -256,43 +256,6 @@ describe DiffHelper do
end
end
- context 'viewer related' do
- let(:viewer) { diff_file.simple_viewer }
-
- before do
- assign(:project, project)
- end
-
- describe '#diff_render_error_reason' do
- context 'for error :too_large' do
- before do
- expect(viewer).to receive(:render_error).and_return(:too_large)
- end
-
- it 'returns an error message' do
- expect(helper.diff_render_error_reason(viewer)).to eq('it is too large')
- end
- end
-
- context 'for error :server_side_but_stored_externally' do
- before do
- expect(viewer).to receive(:render_error).and_return(:server_side_but_stored_externally)
- expect(diff_file).to receive(:external_storage).and_return(:lfs)
- end
-
- it 'returns an error message' do
- expect(helper.diff_render_error_reason(viewer)).to eq('it is stored in LFS')
- end
- end
- end
-
- describe '#diff_render_error_options' do
- it 'includes a "view the blob" link' do
- expect(helper.diff_render_error_options(viewer)).to include(/view the blob/)
- end
- end
- end
-
context '#diff_file_path_text' do
it 'returns full path by default' do
expect(diff_file_path_text(diff_file)).to eq(diff_file.new_path)
diff --git a/spec/helpers/emails_helper_spec.rb b/spec/helpers/emails_helper_spec.rb
index 3820cf5cb9d..03b4c19ec22 100644
--- a/spec/helpers/emails_helper_spec.rb
+++ b/spec/helpers/emails_helper_spec.rb
@@ -1,6 +1,20 @@
require 'spec_helper'
describe EmailsHelper do
+ describe 'sanitize_name' do
+ context 'when name contains a valid URL string' do
+ it 'returns name with `.` replaced with `_` to prevent mail clients from auto-linking URLs' do
+ expect(sanitize_name('https://about.gitlab.com')).to eq('https://about_gitlab_com')
+ expect(sanitize_name('www.gitlab.com')).to eq('www_gitlab_com')
+ expect(sanitize_name('//about.gitlab.com/handbook/security/#best-practices')).to eq('//about_gitlab_com/handbook/security/#best-practices')
+ end
+
+ it 'returns name as it is when it does not contain a URL' do
+ expect(sanitize_name('Foo Bar')).to eq('Foo Bar')
+ end
+ end
+ end
+
describe 'password_reset_token_valid_time' do
def validate_time_string(time_limit, expected_string)
Devise.reset_password_within = time_limit
@@ -128,4 +142,58 @@ describe EmailsHelper do
end
end
end
+
+ describe 'header and footer messages' do
+ context 'when email_header_and_footer_enabled is enabled' do
+ it 'returns header and footer messages' do
+ create :appearance, header_message: 'Foo', footer_message: 'Bar', email_header_and_footer_enabled: true
+
+ aggregate_failures do
+ expect(html_header_message).to eq(%{<div class="header-message" style=""><p>Foo</p></div>})
+ expect(html_footer_message).to eq(%{<div class="footer-message" style=""><p>Bar</p></div>})
+ expect(text_header_message).to eq('Foo')
+ expect(text_footer_message).to eq('Bar')
+ end
+ end
+
+ context 'when header and footer messages are empty' do
+ it 'returns nil' do
+ create :appearance, header_message: '', footer_message: '', email_header_and_footer_enabled: true
+
+ aggregate_failures do
+ expect(html_header_message).to eq(nil)
+ expect(html_footer_message).to eq(nil)
+ expect(text_header_message).to eq(nil)
+ expect(text_footer_message).to eq(nil)
+ end
+ end
+ end
+
+ context 'when header and footer messages are nil' do
+ it 'returns nil' do
+ create :appearance, header_message: nil, footer_message: nil, email_header_and_footer_enabled: true
+
+ aggregate_failures do
+ expect(html_header_message).to eq(nil)
+ expect(html_footer_message).to eq(nil)
+ expect(text_header_message).to eq(nil)
+ expect(text_footer_message).to eq(nil)
+ end
+ end
+ end
+ end
+
+ context 'when email_header_and_footer_enabled is disabled' do
+ it 'returns header and footer messages' do
+ create :appearance, header_message: 'Foo', footer_message: 'Bar', email_header_and_footer_enabled: false
+
+ aggregate_failures do
+ expect(html_header_message).to eq(nil)
+ expect(html_footer_message).to eq(nil)
+ expect(text_header_message).to eq(nil)
+ expect(text_footer_message).to eq(nil)
+ end
+ end
+ end
+ end
end
diff --git a/spec/helpers/import_helper_spec.rb b/spec/helpers/import_helper_spec.rb
index cb0ea4e26ba..6e8c13db9fe 100644
--- a/spec/helpers/import_helper_spec.rb
+++ b/spec/helpers/import_helper_spec.rb
@@ -2,6 +2,10 @@ require 'rails_helper'
describe ImportHelper do
describe '#sanitize_project_name' do
+ it 'removes leading tildes' do
+ expect(helper.sanitize_project_name('~~root')).to eq('root')
+ end
+
it 'removes whitespace' do
expect(helper.sanitize_project_name('my test repo')).to eq('my-test-repo')
end
@@ -35,59 +39,12 @@ describe ImportHelper do
end
end
- describe '#provider_project_link' do
- context 'when provider is "github"' do
- let(:github_server_url) { nil }
- let(:provider) { OpenStruct.new(name: 'github', url: github_server_url) }
-
- before do
- stub_omniauth_setting(providers: [provider])
- end
-
- context 'when provider does not specify a custom URL' do
- it 'uses default GitHub URL' do
- expect(helper.provider_project_link('github', 'octocat/Hello-World'))
- .to include('href="https://github.com/octocat/Hello-World"')
- end
- end
-
- context 'when provider specify a custom URL' do
- let(:github_server_url) { 'https://github.company.com' }
-
- it 'uses custom URL' do
- expect(helper.provider_project_link('github', 'octocat/Hello-World'))
- .to include('href="https://github.company.com/octocat/Hello-World"')
- end
- end
-
- context "when custom URL contains a '/' char at the end" do
- let(:github_server_url) { 'https://github.company.com/' }
+ describe '#provider_project_link_url' do
+ let(:full_path) { '/repo/path' }
+ let(:host_url) { 'http://provider.com/' }
- it "doesn't render double slash" do
- expect(helper.provider_project_link('github', 'octocat/Hello-World'))
- .to include('href="https://github.company.com/octocat/Hello-World"')
- end
- end
-
- context 'when provider is missing' do
- it 'uses the default URL' do
- allow(Gitlab.config.omniauth).to receive(:providers).and_return([])
-
- expect(helper.provider_project_link('github', 'octocat/Hello-World'))
- .to include('href="https://github.com/octocat/Hello-World"')
- end
- end
- end
-
- context 'when provider is "gitea"' do
- before do
- assign(:gitea_host_url, 'https://try.gitea.io/')
- end
-
- it 'uses given host' do
- expect(helper.provider_project_link('gitea', 'octocat/Hello-World'))
- .to include('href="https://try.gitea.io/octocat/Hello-World"')
- end
+ it 'appends repo full path to provider host url' do
+ expect(helper.provider_project_link_url(host_url, full_path)).to match('http://provider.com/repo/path')
end
end
end
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index 81231cca085..8b82dea2524 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -5,8 +5,8 @@ describe IssuablesHelper do
let(:label2) { build_stubbed(:label) }
describe '#users_dropdown_label' do
- let(:user) { build_stubbed(:user) }
- let(:user2) { build_stubbed(:user) }
+ let(:user) { build_stubbed(:user) }
+ let(:user2) { build_stubbed(:user) }
it 'returns unassigned' do
expect(users_dropdown_label([])).to eq('Unassigned')
@@ -22,7 +22,7 @@ describe IssuablesHelper do
end
describe '#group_dropdown_label' do
- let(:group) { create(:group) }
+ let(:group) { create(:group) }
let(:default) { 'default label' }
it 'returns default group label when group_id is nil' do
@@ -173,6 +173,7 @@ describe IssuablesHelper do
before do
allow(helper).to receive(:current_user).and_return(user)
allow(helper).to receive(:can?).and_return(true)
+ stub_commonmark_sourcepos_disabled
end
it 'returns the correct json for an issue' do
@@ -187,8 +188,8 @@ describe IssuablesHelper do
issuableRef: "##{issue.iid}",
markdownPreviewPath: "/#{@project.full_path}/preview_markdown",
markdownDocsPath: '/help/user/markdown',
- markdownVersion: CacheMarkdownField::CACHE_COMMONMARK_VERSION,
issuableTemplates: [],
+ lockVersion: issue.lock_version,
projectPath: @project.path,
projectNamespace: @project.namespace.path,
initialTitleHtml: issue.title,
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 8bb2e234e9a..039143eb8d7 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -148,7 +148,7 @@ describe IssuesHelper do
end
describe "when passing a discussion" do
- let(:diff_note) { create(:diff_note_on_merge_request) }
+ let(:diff_note) { create(:diff_note_on_merge_request) }
let(:merge_request) { diff_note.noteable }
let(:discussion) { diff_note.to_discussion }
diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb
index c04f679bcf0..012678db9c2 100644
--- a/spec/helpers/labels_helper_spec.rb
+++ b/spec/helpers/labels_helper_spec.rb
@@ -236,4 +236,17 @@ describe LabelsHelper do
expect(labels_filter_path(format: :json)).to eq(dashboard_labels_path(format: :json))
end
end
+
+ describe 'labels_sorted_by_title' do
+ it 'sorts labels alphabetically' do
+ label1 = double(:label, title: 'a')
+ label2 = double(:label, title: 'B')
+ label3 = double(:label, title: 'c')
+ label4 = double(:label, title: 'D')
+ labels = [label1, label2, label3, label4]
+
+ expect(labels_sorted_by_title(labels))
+ .to match_array([label2, label4, label1, label3])
+ end
+ end
end
diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb
index a0c0af94fa5..c3956ba08fd 100644
--- a/spec/helpers/markup_helper_spec.rb
+++ b/spec/helpers/markup_helper_spec.rb
@@ -212,17 +212,6 @@ describe MarkupHelper do
helper.render_wiki_content(@wiki)
end
- it 'uses Wiki pipeline for markdown files with RedCarpet if feature disabled' do
- stub_feature_flags(commonmark_for_repositories: false)
- allow(@wiki).to receive(:format).and_return(:markdown)
-
- expect(helper).to receive(:markdown_unsafe).with('wiki content',
- pipeline: :wiki, project: project, project_wiki: @wiki, page_slug: "nested/page",
- issuable_state_filter_enabled: true, markdown_engine: :redcarpet)
-
- helper.render_wiki_content(@wiki)
- end
-
it "uses Asciidoctor for asciidoc files" do
allow(@wiki).to receive(:format).and_return(:asciidoc)
@@ -273,16 +262,6 @@ describe MarkupHelper do
it 'defaults to CommonMark' do
expect(helper.markup('foo.md', 'x^2')).to include('x^2')
end
-
- it 'honors markdown_engine for RedCarpet' do
- expect(helper.markup('foo.md', 'x^2', { markdown_engine: :redcarpet })).to include('x<sup>2</sup>')
- end
-
- it 'uses RedCarpet if feature disabled' do
- stub_feature_flags(commonmark_for_repositories: false)
-
- expect(helper.markup('foo.md', 'x^2', { markdown_engine: :redcarpet })).to include('x<sup>2</sup>')
- end
end
describe '#first_line_in_markdown' do
diff --git a/spec/helpers/members_helper_spec.rb b/spec/helpers/members_helper_spec.rb
index 4590904c93d..908e8960f37 100644
--- a/spec/helpers/members_helper_spec.rb
+++ b/spec/helpers/members_helper_spec.rb
@@ -16,7 +16,7 @@ describe MembersHelper do
it { expect(remove_member_message(project_member_invite)).to eq "Are you sure you want to revoke the invitation for #{project_member_invite.invite_email} to join the #{project.full_name} project?" }
it { expect(remove_member_message(project_member_request)).to eq "Are you sure you want to deny #{requester.name}'s request to join the #{project.full_name} project?" }
it { expect(remove_member_message(project_member_request, user: requester)).to eq "Are you sure you want to withdraw your access request for the #{project.full_name} project?" }
- it { expect(remove_member_message(group_member)).to eq "Are you sure you want to remove #{group_member.user.name} from the #{group.name} group?" }
+ it { expect(remove_member_message(group_member)).to eq "Are you sure you want to remove #{group_member.user.name} from the #{group.name} group and any subresources?" }
it { expect(remove_member_message(group_member_invite)).to eq "Are you sure you want to revoke the invitation for #{group_member_invite.invite_email} to join the #{group.name} group?" }
it { expect(remove_member_message(group_member_request)).to eq "Are you sure you want to deny #{requester.name}'s request to join the #{group.name} group?" }
it { expect(remove_member_message(group_member_request, user: requester)).to eq "Are you sure you want to withdraw your access request for the #{group.name} group?" }
@@ -33,7 +33,7 @@ describe MembersHelper do
it { expect(remove_member_title(project_member)).to eq 'Remove user from project' }
it { expect(remove_member_title(project_member_request)).to eq 'Deny access request from project' }
- it { expect(remove_member_title(group_member)).to eq 'Remove user from group' }
+ it { expect(remove_member_title(group_member)).to eq 'Remove user from group and any subresources' }
it { expect(remove_member_title(group_member_request)).to eq 'Deny access request from group' }
end
diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb
index 21461e46cf4..0715f34dafe 100644
--- a/spec/helpers/notes_helper_spec.rb
+++ b/spec/helpers/notes_helper_spec.rb
@@ -185,8 +185,8 @@ describe NotesHelper do
context 'for a non-diff discussion' do
let(:discussion) { create(:discussion_note_on_commit, project: project).to_discussion }
- it 'returns the commit path' do
- expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit))
+ it 'returns the commit path with the note anchor' do
+ expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: "note_#{discussion.first_note.id}"))
end
end
end
diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb
index c112c8ed633..db0d45c3692 100644
--- a/spec/helpers/preferences_helper_spec.rb
+++ b/spec/helpers/preferences_helper_spec.rb
@@ -35,6 +35,38 @@ describe PreferencesHelper do
end
end
+ describe '#first_day_of_week_choices' do
+ it 'returns Saturday, Sunday and Monday as choices' do
+ expect(helper.first_day_of_week_choices).to eq [
+ ['Sunday', 0],
+ ['Monday', 1],
+ ['Saturday', 6]
+ ]
+ end
+ end
+
+ describe '#first_day_of_week_choices_with_default' do
+ it 'returns choices including system default' do
+ expect(helper.first_day_of_week_choices_with_default).to eq [
+ ['System default (Sunday)', nil], ['Sunday', 0], ['Monday', 1], ['Saturday', 6]
+ ]
+ end
+
+ it 'returns choices including system default set to Monday' do
+ stub_application_setting(first_day_of_week: 1)
+ expect(helper.first_day_of_week_choices_with_default).to eq [
+ ['System default (Monday)', nil], ['Sunday', 0], ['Monday', 1], ['Saturday', 6]
+ ]
+ end
+
+ it 'returns choices including system default set to Saturday' do
+ stub_application_setting(first_day_of_week: 6)
+ expect(helper.first_day_of_week_choices_with_default).to eq [
+ ['System default (Saturday)', nil], ['Sunday', 0], ['Monday', 1], ['Saturday', 6]
+ ]
+ end
+ end
+
describe '#user_application_theme' do
context 'with a user' do
it "returns user's theme's css_class" do
@@ -86,6 +118,13 @@ describe PreferencesHelper do
end
end
+ describe '#language_choices' do
+ it 'returns an array of all available languages' do
+ expect(helper.language_choices).to be_an(Array)
+ expect(helper.language_choices.map(&:second)).to eq(Gitlab::I18n.available_locales)
+ end
+ end
+
def stub_user(messages = {})
if messages.empty?
allow(helper).to receive(:current_user).and_return(nil)
diff --git a/spec/helpers/projects/error_tracking_helper_spec.rb b/spec/helpers/projects/error_tracking_helper_spec.rb
new file mode 100644
index 00000000000..7516a636c93
--- /dev/null
+++ b/spec/helpers/projects/error_tracking_helper_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::ErrorTrackingHelper do
+ include Gitlab::Routing.url_helpers
+
+ set(:project) { create(:project) }
+
+ describe '#error_tracking_data' do
+ let(:setting_path) { project_settings_operations_path(project) }
+
+ let(:index_path) do
+ project_error_tracking_index_path(project, format: :json)
+ end
+
+ context 'without error_tracking_setting' do
+ it 'returns frontend configuration' do
+ expect(error_tracking_data(project)).to eq(
+ 'index-path' => index_path,
+ 'enable-error-tracking-link' => setting_path,
+ 'error-tracking-enabled' => 'false',
+ "illustration-path" => "/images/illustrations/cluster_popover.svg"
+ )
+ end
+ end
+
+ context 'with error_tracking_setting' do
+ let(:error_tracking_setting) do
+ create(:project_error_tracking_setting, project: project)
+ end
+
+ context 'when enabled' do
+ before do
+ error_tracking_setting.update!(enabled: true)
+ end
+
+ it 'show error tracking enabled' do
+ expect(error_tracking_data(project)).to include(
+ 'error-tracking-enabled' => 'true'
+ )
+ end
+ end
+
+ context 'when disabled' do
+ before do
+ error_tracking_setting.update!(enabled: false)
+ end
+
+ it 'show error tracking not enabled' do
+ expect(error_tracking_data(project)).to include(
+ 'error-tracking-enabled' => 'false'
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index edd680ee1d1..291eafece94 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -3,6 +3,56 @@ require 'spec_helper'
describe ProjectsHelper do
include ProjectForksHelper
+ describe '#error_tracking_setting_project_json' do
+ let(:project) { create(:project) }
+
+ context 'error tracking setting does not exist' do
+ before do
+ helper.instance_variable_set(:@project, project)
+ end
+
+ it 'returns nil' do
+ expect(helper.error_tracking_setting_project_json).to be_nil
+ end
+ end
+
+ context 'error tracking setting exists' do
+ let!(:error_tracking_setting) { create(:project_error_tracking_setting, project: project) }
+
+ context 'api_url present' do
+ let(:json) do
+ {
+ name: error_tracking_setting.project_name,
+ organization_name: error_tracking_setting.organization_name,
+ organization_slug: error_tracking_setting.organization_slug,
+ slug: error_tracking_setting.project_slug
+ }.to_json
+ end
+
+ before do
+ helper.instance_variable_set(:@project, project)
+ end
+
+ it 'returns error tracking json' do
+ expect(helper.error_tracking_setting_project_json).to eq(json)
+ end
+ end
+
+ context 'api_url not present' do
+ before do
+ project.error_tracking_setting.api_url = nil
+ project.error_tracking_setting.enabled = false
+
+ helper.instance_variable_set(:@project, project)
+ end
+
+ it 'returns nil' do
+ expect(helper.error_tracking_setting_project_json).to be_nil
+ end
+ end
+ end
+ end
+
describe "#project_status_css_class" do
it "returns appropriate class" do
expect(project_status_css_class("started")).to eq("table-active")
@@ -354,8 +404,35 @@ describe ProjectsHelper do
allow(project).to receive(:builds_enabled?).and_return(false)
end
- it "do not include pipelines tab" do
- is_expected.not_to include(:pipelines)
+ context 'when user has access to builds' do
+ it "does include pipelines tab" do
+ is_expected.to include(:pipelines)
+ end
+ end
+
+ context 'when user does not have access to builds' do
+ before do
+ allow(helper).to receive(:can?) { false }
+ end
+
+ it "does not include pipelines tab" do
+ is_expected.not_to include(:pipelines)
+ end
+ end
+ end
+
+ context 'when project has external wiki' do
+ it 'includes external wiki tab' do
+ project.create_external_wiki_service(active: true, properties: { 'external_wiki_url' => 'https://gitlab.com' })
+
+ is_expected.to include(:external_wiki)
+ end
+ end
+
+ context 'when project does not have external wiki' do
+ it 'does not include external wiki tab' do
+ expect(project.external_wiki).to be_nil
+ is_expected.not_to include(:external_wiki)
end
end
end
@@ -508,18 +585,6 @@ describe ProjectsHelper do
end
end
- describe '#legacy_render_context' do
- it 'returns the redcarpet engine' do
- params = { legacy_render: '1' }
-
- expect(helper.legacy_render_context(params)).to include(markdown_engine: :redcarpet)
- end
-
- it 'returns nothing' do
- expect(helper.legacy_render_context({})).to be_empty
- end
- end
-
describe '#explore_projects_tab?' do
subject { helper.explore_projects_tab? }
@@ -629,4 +694,103 @@ describe ProjectsHelper do
end
end
end
+
+ describe '#show_auto_devops_implicitly_enabled_banner?' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:user) { create(:user) }
+
+ let(:feature_visibilities) do
+ {
+ enabled: ProjectFeature::ENABLED,
+ disabled: ProjectFeature::DISABLED
+ }
+ end
+
+ where(:global_setting, :project_setting, :builds_visibility, :gitlab_ci_yml, :user_access, :result) do
+ # With ADO implicitly enabled scenarios
+ true | nil | :disabled | true | :developer | false
+ true | nil | :disabled | true | :maintainer | false
+ true | nil | :disabled | true | :owner | false
+
+ true | nil | :disabled | false | :developer | false
+ true | nil | :disabled | false | :maintainer | false
+ true | nil | :disabled | false | :owner | false
+
+ true | nil | :enabled | true | :developer | false
+ true | nil | :enabled | true | :maintainer | false
+ true | nil | :enabled | true | :owner | false
+
+ true | nil | :enabled | false | :developer | false
+ true | nil | :enabled | false | :maintainer | true
+ true | nil | :enabled | false | :owner | true
+
+ # With ADO enabled scenarios
+ true | true | :disabled | true | :developer | false
+ true | true | :disabled | true | :maintainer | false
+ true | true | :disabled | true | :owner | false
+
+ true | true | :disabled | false | :developer | false
+ true | true | :disabled | false | :maintainer | false
+ true | true | :disabled | false | :owner | false
+
+ true | true | :enabled | true | :developer | false
+ true | true | :enabled | true | :maintainer | false
+ true | true | :enabled | true | :owner | false
+
+ true | true | :enabled | false | :developer | false
+ true | true | :enabled | false | :maintainer | false
+ true | true | :enabled | false | :owner | false
+
+ # With ADO disabled scenarios
+ true | false | :disabled | true | :developer | false
+ true | false | :disabled | true | :maintainer | false
+ true | false | :disabled | true | :owner | false
+
+ true | false | :disabled | false | :developer | false
+ true | false | :disabled | false | :maintainer | false
+ true | false | :disabled | false | :owner | false
+
+ true | false | :enabled | true | :developer | false
+ true | false | :enabled | true | :maintainer | false
+ true | false | :enabled | true | :owner | false
+
+ true | false | :enabled | false | :developer | false
+ true | false | :enabled | false | :maintainer | false
+ true | false | :enabled | false | :owner | false
+ end
+
+ def grant_user_access(project, user, access)
+ case access
+ when :developer, :maintainer
+ project.add_user(user, access)
+ when :owner
+ project.namespace.update(owner: user)
+ end
+ end
+
+ with_them do
+ let(:project) do
+ if project_setting.nil?
+ create(:project, :repository)
+ else
+ create(:project, :repository, :auto_devops)
+ end
+ end
+
+ before do
+ stub_application_setting(auto_devops_enabled: global_setting)
+
+ allow_any_instance_of(Repository).to receive(:gitlab_ci_yml).and_return(gitlab_ci_yml)
+
+ grant_user_access(project, user, user_access)
+ project.project_feature.update_attribute(:builds_access_level, feature_visibilities[builds_visibility])
+ project.auto_devops.update_attribute(:enabled, project_setting) unless project_setting.nil?
+ end
+
+ subject { helper.show_auto_devops_implicitly_enabled_banner?(project, user) }
+
+ it { is_expected.to eq(result) }
+ end
+ end
end
diff --git a/spec/helpers/runners_helper_spec.rb b/spec/helpers/runners_helper_spec.rb
index a4a483e68a8..bf00841fcb6 100644
--- a/spec/helpers/runners_helper_spec.rb
+++ b/spec/helpers/runners_helper_spec.rb
@@ -15,4 +15,40 @@ describe RunnersHelper do
runner = FactoryBot.build(:ci_runner, contacted_at: 1.second.ago, active: true)
expect(runner_status_icon(runner)).to include("Runner is online")
end
+
+ describe '#runner_contacted_at' do
+ let(:contacted_at_stored) { 1.hour.ago.change(usec: 0) }
+ let(:contacted_at_cached) { 1.second.ago.change(usec: 0) }
+ let(:runner) { create(:ci_runner, contacted_at: contacted_at_stored) }
+
+ before do
+ runner.cache_attributes(contacted_at: contacted_at_cached)
+ end
+
+ context 'without sorting' do
+ it 'returns cached value' do
+ expect(runner_contacted_at(runner)).to eq(contacted_at_cached)
+ end
+ end
+
+ context 'with sorting set to created_date' do
+ before do
+ controller.params[:sort] = 'created_date'
+ end
+
+ it 'returns cached value' do
+ expect(runner_contacted_at(runner)).to eq(contacted_at_cached)
+ end
+ end
+
+ context 'with sorting set to contacted_asc' do
+ before do
+ controller.params[:sort] = 'contacted_asc'
+ end
+
+ it 'returns stored value' do
+ expect(runner_contacted_at(runner)).to eq(contacted_at_stored)
+ end
+ end
+ end
end
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 4945749f524..9cff0291250 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -18,7 +18,7 @@ describe SearchHelper do
end
context "with a standard user" do
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
before do
allow(self).to receive(:current_user).and_return(user)
diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb
index 8662cadc7a0..ea48c69e0ae 100644
--- a/spec/helpers/submodule_helper_spec.rb
+++ b/spec/helpers/submodule_helper_spec.rb
@@ -6,7 +6,7 @@ describe SubmoduleHelper do
describe 'submodule links' do
let(:submodule_item) { double(id: 'hash', path: 'rack') }
let(:config) { Gitlab.config.gitlab }
- let(:repo) { double() }
+ let(:repo) { double }
before do
self.instance_variable_set(:@repository, repo)
diff --git a/spec/helpers/user_callouts_helper_spec.rb b/spec/helpers/user_callouts_helper_spec.rb
index 27455705d23..8fa479a4474 100644
--- a/spec/helpers/user_callouts_helper_spec.rb
+++ b/spec/helpers/user_callouts_helper_spec.rb
@@ -44,4 +44,13 @@ describe UserCalloutsHelper do
it { is_expected.to be false }
end
end
+
+ describe '.render_flash_user_callout' do
+ it 'renders the flash_user_callout partial' do
+ expect(helper).to receive(:render)
+ .with(/flash_user_callout/, flash_type: :warning, message: 'foo', feature_name: 'bar')
+
+ helper.render_flash_user_callout(:warning, 'foo', 'bar')
+ end
+ end
end
diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb
index 34d9115a1f6..f3649495493 100644
--- a/spec/helpers/users_helper_spec.rb
+++ b/spec/helpers/users_helper_spec.rb
@@ -51,7 +51,7 @@ describe UsersHelper do
false | 'mockRegexPattern' | { user_internal_regex_pattern: nil, user_internal_regex_options: nil }
true | nil | { user_internal_regex_pattern: nil, user_internal_regex_options: nil }
true | '' | { user_internal_regex_pattern: nil, user_internal_regex_options: nil }
- true | 'mockRegexPattern' | { user_internal_regex_pattern: 'mockRegexPattern', user_internal_regex_options: 'gi' }
+ true | 'mockRegexPattern' | { user_internal_regex_pattern: 'mockRegexPattern', user_internal_regex_options: 'i' }
end
with_them do
@@ -100,4 +100,72 @@ describe UsersHelper do
end
end
end
+
+ describe '#user_badges_in_admin_section' do
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'with a blocked user' do
+ it "returns the blocked badge" do
+ blocked_user = create(:user, state: 'blocked')
+
+ badges = helper.user_badges_in_admin_section(blocked_user)
+
+ expect(badges).to eq([text: "Blocked", variant: "danger"])
+ end
+ end
+
+ context 'with an admin user' do
+ it "returns the admin badge" do
+ admin_user = create(:admin)
+
+ badges = helper.user_badges_in_admin_section(admin_user)
+
+ expect(badges).to eq([text: "Admin", variant: "success"])
+ end
+ end
+
+ context 'with an external user' do
+ it 'returns the external badge' do
+ external_user = create(:user, external: true)
+
+ badges = helper.user_badges_in_admin_section(external_user)
+
+ expect(badges).to eq([text: "External", variant: "secondary"])
+ end
+ end
+
+ context 'with the current user' do
+ it 'returns the "It\'s You" badge' do
+ badges = helper.user_badges_in_admin_section(user)
+
+ expect(badges).to eq([text: "It's you!", variant: nil])
+ end
+ end
+
+ context 'with an external blocked admin' do
+ it 'returns the blocked, admin and external badges' do
+ user = create(:admin, state: 'blocked', external: true)
+
+ badges = helper.user_badges_in_admin_section(user)
+
+ expect(badges).to eq([
+ { text: "Blocked", variant: "danger" },
+ { text: "Admin", variant: "success" },
+ { text: "External", variant: "secondary" }
+ ])
+ end
+ end
+
+ context 'get badges for normal user' do
+ it 'returns no badges' do
+ user = create(:user)
+
+ badges = helper.user_badges_in_admin_section(user)
+
+ expect(badges).to be_empty
+ end
+ end
+ end
end
diff --git a/spec/initializers/active_record_locking_spec.rb b/spec/initializers/active_record_locking_spec.rb
new file mode 100644
index 00000000000..5a16aef78e6
--- /dev/null
+++ b/spec/initializers/active_record_locking_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'ActiveRecord locking' do
+ let(:issue) { create(:issue) }
+
+ shared_examples 'locked model' do
+ before do
+ issue.update_column(:lock_version, start_lock_version)
+ end
+
+ it 'can be updated' do
+ issue.update(title: "New title")
+
+ expect(issue.reload.lock_version).to eq(new_lock_version)
+ end
+
+ it 'can be deleted' do
+ expect { issue.destroy }.to change { Issue.count }.by(-1)
+ end
+ end
+
+ context 'when lock_version is NULL' do
+ let(:start_lock_version) { nil }
+ let(:new_lock_version) { 1 }
+
+ it_behaves_like 'locked model'
+ end
+
+ context 'when lock_version is 0' do
+ let(:start_lock_version) { 0 }
+ let(:new_lock_version) { 1 }
+
+ it_behaves_like 'locked model'
+ end
+
+ context 'when lock_version is 1' do
+ let(:start_lock_version) { 1 }
+ let(:new_lock_version) { 2 }
+
+ it_behaves_like 'locked model'
+ end
+end
diff --git a/spec/javascripts/api_spec.js b/spec/javascripts/api_spec.js
index 9d55c615450..e537e0e8afc 100644
--- a/spec/javascripts/api_spec.js
+++ b/spec/javascripts/api_spec.js
@@ -49,6 +49,22 @@ describe('Api', () => {
});
});
+ describe('groupMembers', () => {
+ it('fetches group members', done => {
+ const groupId = '54321';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/members`;
+ const expectedData = [{ id: 7 }];
+ mock.onGet(expectedUrl).reply(200, expectedData);
+
+ Api.groupMembers(groupId)
+ .then(({ data }) => {
+ expect(data).toEqual(expectedData);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
describe('groups', () => {
it('fetches groups', done => {
const query = 'dummy query';
@@ -123,6 +139,40 @@ describe('Api', () => {
});
});
+ describe('projectMergeRequests', () => {
+ const projectPath = 'abc';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests`;
+
+ it('fetches all merge requests for a project', done => {
+ const mockData = [{ source_branch: 'foo' }, { source_branch: 'bar' }];
+ mock.onGet(expectedUrl).reply(200, mockData);
+ Api.projectMergeRequests(projectPath)
+ .then(({ data }) => {
+ expect(data.length).toEqual(2);
+ expect(data[0].source_branch).toBe('foo');
+ expect(data[1].source_branch).toBe('bar');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('fetches merge requests filtered with passed params', done => {
+ const params = {
+ source_branch: 'bar',
+ };
+ const mockData = [{ source_branch: 'bar' }];
+ mock.onGet(expectedUrl, { params }).reply(200, mockData);
+
+ Api.projectMergeRequests(projectPath, params)
+ .then(({ data }) => {
+ expect(data.length).toEqual(1);
+ expect(data[0].source_branch).toBe('bar');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
describe('projectMergeRequest', () => {
it('fetches a merge request', done => {
const projectPath = 'abc';
diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js
index ce5d2022441..e5b5707dcef 100644
--- a/spec/javascripts/awards_handler_spec.js
+++ b/spec/javascripts/awards_handler_spec.js
@@ -1,12 +1,16 @@
import $ from 'jquery';
import Cookies from 'js-cookie';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
import loadAwardsHandler from '~/awards_handler';
import '~/lib/utils/common_utils';
+import { EMOJI_VERSION } from '~/emoji';
window.gl = window.gl || {};
window.gon = window.gon || {};
let openAndWaitForEmojiMenu;
+let mock;
let awardsHandler = null;
const urlRoot = gon.relative_url_root;
@@ -19,8 +23,13 @@ const lazyAssert = function(done, assertFn) {
};
describe('AwardsHandler', function() {
+ const emojiData = getJSONFixture('emojis/emojis.json');
preloadFixtures('snippets/show.html.raw');
+
beforeEach(function(done) {
+ mock = new MockAdapter(axios);
+ mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, emojiData);
+
loadFixtures('snippets/show.html.raw');
loadAwardsHandler(true)
.then(obj => {
@@ -53,6 +62,8 @@ describe('AwardsHandler', function() {
// restore original url root value
gon.relative_url_root = urlRoot;
+ mock.restore();
+
// Undo what we did to the shared <body>
$('body').removeAttr('data-page');
diff --git a/spec/javascripts/badges/store/actions_spec.js b/spec/javascripts/badges/store/actions_spec.js
index 2623465ebd6..e8d5f8c3aac 100644
--- a/spec/javascripts/badges/store/actions_spec.js
+++ b/spec/javascripts/badges/store/actions_spec.js
@@ -411,7 +411,7 @@ describe('Badges store actions', () => {
it('escapes user input', done => {
spyOn(axios, 'get').and.callFake(() => Promise.resolve({ data: createDummyBadgeResponse() }));
- badgeInForm.imageUrl = '&make-sandwhich=true';
+ badgeInForm.imageUrl = '&make-sandwich=true';
badgeInForm.linkUrl = '<script>I am dangerous!</script>';
actions
@@ -422,7 +422,7 @@ describe('Badges store actions', () => {
expect(url).toMatch(`^${dummyEndpointUrl}/render?`);
expect(url).toMatch('\\?link_url=%3Cscript%3EI%20am%20dangerous!%3C%2Fscript%3E&');
- expect(url).toMatch('&image_url=%26make-sandwhich%3Dtrue$');
+ expect(url).toMatch('&image_url=%26make-sandwich%3Dtrue$');
})
.then(done)
.catch(done.fail);
diff --git a/spec/javascripts/behaviors/copy_as_gfm_spec.js b/spec/javascripts/behaviors/copy_as_gfm_spec.js
index cf8c1b77861..d653fca0988 100644
--- a/spec/javascripts/behaviors/copy_as_gfm_spec.js
+++ b/spec/javascripts/behaviors/copy_as_gfm_spec.js
@@ -1,4 +1,4 @@
-import { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
+import initCopyAsGFM, { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
describe('CopyAsGFM', () => {
describe('CopyAsGFM.pasteGFM', () => {
@@ -79,27 +79,46 @@ describe('CopyAsGFM', () => {
return clipboardData;
};
+ beforeAll(done => {
+ initCopyAsGFM();
+
+ // Fake call to nodeToGfm so the import of lazy bundle happened
+ CopyAsGFM.nodeToGFM(document.createElement('div'))
+ .then(() => {
+ done();
+ })
+ .catch(done.fail);
+ });
+
beforeEach(() => spyOn(clipboardData, 'setData'));
describe('list handling', () => {
- it('uses correct gfm for unordered lists', () => {
+ it('uses correct gfm for unordered lists', done => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'UL');
+
spyOn(window, 'getSelection').and.returnValue(selection);
simulateCopy();
- const expectedGFM = '- List Item1\n- List Item2';
+ setTimeout(() => {
+ const expectedGFM = '* List Item1\n* List Item2';
- expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
+ expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
+ done();
+ });
});
- it('uses correct gfm for ordered lists', () => {
+ it('uses correct gfm for ordered lists', done => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'OL');
+
spyOn(window, 'getSelection').and.returnValue(selection);
simulateCopy();
- const expectedGFM = '1. List Item1\n1. List Item2';
+ setTimeout(() => {
+ const expectedGFM = '1. List Item1\n1. List Item2';
- expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
+ expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js b/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
index b709b937180..4843a0386b5 100644
--- a/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
+++ b/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
@@ -3,17 +3,26 @@
*/
import $ from 'jquery';
-import initCopyAsGFM from '~/behaviors/markdown/copy_as_gfm';
+import initCopyAsGFM, { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
-initCopyAsGFM();
-
const FORM_SELECTOR = '.js-main-target-form .js-vue-comment-form';
describe('ShortcutsIssuable', function() {
const fixtureName = 'snippets/show.html.raw';
preloadFixtures(fixtureName);
+ beforeAll(done => {
+ initCopyAsGFM();
+
+ // Fake call to nodeToGfm so the import of lazy bundle happened
+ CopyAsGFM.nodeToGFM(document.createElement('div'))
+ .then(() => {
+ done();
+ })
+ .catch(done.fail);
+ });
+
beforeEach(() => {
loadFixtures(fixtureName);
$('body').append(
@@ -63,17 +72,22 @@ describe('ShortcutsIssuable', function() {
stubSelection('<p>Selected text.</p>');
});
- it('leaves existing input intact', () => {
+ it('leaves existing input intact', done => {
$(FORM_SELECTOR).val('This text was already here.');
expect($(FORM_SELECTOR).val()).toBe('This text was already here.');
ShortcutsIssuable.replyWithSelectedText(true);
- expect($(FORM_SELECTOR).val()).toBe('This text was already here.\n\n> Selected text.\n\n');
+ setTimeout(() => {
+ expect($(FORM_SELECTOR).val()).toBe(
+ 'This text was already here.\n\n> Selected text.\n\n',
+ );
+ done();
+ });
});
- it('triggers `input`', () => {
+ it('triggers `input`', done => {
let triggered = false;
$(FORM_SELECTOR).on('input', () => {
triggered = true;
@@ -81,36 +95,48 @@ describe('ShortcutsIssuable', function() {
ShortcutsIssuable.replyWithSelectedText(true);
- expect(triggered).toBe(true);
+ setTimeout(() => {
+ expect(triggered).toBe(true);
+ done();
+ });
});
- it('triggers `focus`', () => {
+ it('triggers `focus`', done => {
const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- expect(spy).toHaveBeenCalled();
+ setTimeout(() => {
+ expect(spy).toHaveBeenCalled();
+ done();
+ });
});
});
describe('with a one-line selection', () => {
- it('quotes the selection', () => {
+ it('quotes the selection', done => {
stubSelection('<p>This text has been selected.</p>');
ShortcutsIssuable.replyWithSelectedText(true);
- expect($(FORM_SELECTOR).val()).toBe('> This text has been selected.\n\n');
+ setTimeout(() => {
+ expect($(FORM_SELECTOR).val()).toBe('> This text has been selected.\n\n');
+ done();
+ });
});
});
describe('with a multi-line selection', () => {
- it('quotes the selected lines as a group', () => {
+ it('quotes the selected lines as a group', done => {
stubSelection(
'<p>Selected line one.</p>\n<p>Selected line two.</p>\n<p>Selected line three.</p>',
);
ShortcutsIssuable.replyWithSelectedText(true);
- expect($(FORM_SELECTOR).val()).toBe(
- '> Selected line one.\n>\n> Selected line two.\n>\n> Selected line three.\n\n',
- );
+ setTimeout(() => {
+ expect($(FORM_SELECTOR).val()).toBe(
+ '> Selected line one.\n>\n> Selected line two.\n>\n> Selected line three.\n\n',
+ );
+ done();
+ });
});
});
@@ -119,17 +145,23 @@ describe('ShortcutsIssuable', function() {
stubSelection('<p>Selected text.</p>', true);
});
- it('does not add anything to the input', () => {
+ it('does not add anything to the input', done => {
ShortcutsIssuable.replyWithSelectedText(true);
- expect($(FORM_SELECTOR).val()).toBe('');
+ setTimeout(() => {
+ expect($(FORM_SELECTOR).val()).toBe('');
+ done();
+ });
});
- it('triggers `focus`', () => {
+ it('triggers `focus`', done => {
const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- expect(spy).toHaveBeenCalled();
+ setTimeout(() => {
+ expect(spy).toHaveBeenCalled();
+ done();
+ });
});
});
@@ -138,20 +170,26 @@ describe('ShortcutsIssuable', function() {
stubSelection('<div class="md">Selected text.</div><p>Invalid selected text.</p>', true);
});
- it('only adds the valid part to the input', () => {
+ it('only adds the valid part to the input', done => {
ShortcutsIssuable.replyWithSelectedText(true);
- expect($(FORM_SELECTOR).val()).toBe('> Selected text.\n\n');
+ setTimeout(() => {
+ expect($(FORM_SELECTOR).val()).toBe('> Selected text.\n\n');
+ done();
+ });
});
- it('triggers `focus`', () => {
+ it('triggers `focus`', done => {
const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- expect(spy).toHaveBeenCalled();
+ setTimeout(() => {
+ expect(spy).toHaveBeenCalled();
+ done();
+ });
});
- it('triggers `input`', () => {
+ it('triggers `input`', done => {
let triggered = false;
$(FORM_SELECTOR).on('input', () => {
triggered = true;
@@ -159,7 +197,10 @@ describe('ShortcutsIssuable', function() {
ShortcutsIssuable.replyWithSelectedText(true);
- expect(triggered).toBe(true);
+ setTimeout(() => {
+ expect(triggered).toBe(true);
+ done();
+ });
});
});
@@ -183,20 +224,26 @@ describe('ShortcutsIssuable', function() {
});
});
- it('adds the quoted selection to the input', () => {
+ it('adds the quoted selection to the input', done => {
ShortcutsIssuable.replyWithSelectedText(true);
- expect($(FORM_SELECTOR).val()).toBe('> _Selected text._\n\n');
+ setTimeout(() => {
+ expect($(FORM_SELECTOR).val()).toBe('> *Selected text.*\n\n');
+ done();
+ });
});
- it('triggers `focus`', () => {
+ it('triggers `focus`', done => {
const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- expect(spy).toHaveBeenCalled();
+ setTimeout(() => {
+ expect(spy).toHaveBeenCalled();
+ done();
+ });
});
- it('triggers `input`', () => {
+ it('triggers `input`', done => {
let triggered = false;
$(FORM_SELECTOR).on('input', () => {
triggered = true;
@@ -204,7 +251,10 @@ describe('ShortcutsIssuable', function() {
ShortcutsIssuable.replyWithSelectedText(true);
- expect(triggered).toBe(true);
+ setTimeout(() => {
+ expect(triggered).toBe(true);
+ done();
+ });
});
});
@@ -228,17 +278,23 @@ describe('ShortcutsIssuable', function() {
});
});
- it('does not add anything to the input', () => {
+ it('does not add anything to the input', done => {
ShortcutsIssuable.replyWithSelectedText(true);
- expect($(FORM_SELECTOR).val()).toBe('');
+ setTimeout(() => {
+ expect($(FORM_SELECTOR).val()).toBe('');
+ done();
+ });
});
- it('triggers `focus`', () => {
+ it('triggers `focus`', done => {
const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- expect(spy).toHaveBeenCalled();
+ setTimeout(() => {
+ expect(spy).toHaveBeenCalled();
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/blob_edit/blob_bundle_spec.js b/spec/javascripts/blob_edit/blob_bundle_spec.js
index 57f60a4a3dd..48af0148e3f 100644
--- a/spec/javascripts/blob_edit/blob_bundle_spec.js
+++ b/spec/javascripts/blob_edit/blob_bundle_spec.js
@@ -1,18 +1,11 @@
import blobBundle from '~/blob_edit/blob_bundle';
import $ from 'jquery';
-window.ace = {
- config: {
- set: () => {},
- loadModule: () => {},
- },
- edit: () => ({ focus: () => {} }),
-};
-
-describe('EditBlob', () => {
+describe('BlobBundle', () => {
beforeEach(() => {
+ spyOnDependency(blobBundle, 'EditBlob').and.stub();
setFixtures(`
- <div class="js-edit-blob-form">
+ <div class="js-edit-blob-form" data-blob-filename="blah">
<button class="js-commit-button"></button>
<a class="btn btn-cancel" href="#"></a>
</div>`);
diff --git a/spec/javascripts/boards/components/issue_due_date_spec.js b/spec/javascripts/boards/components/issue_due_date_spec.js
index 054cf8c5b7d..68e26b68f04 100644
--- a/spec/javascripts/boards/components/issue_due_date_spec.js
+++ b/spec/javascripts/boards/components/issue_due_date_spec.js
@@ -43,7 +43,7 @@ describe('Issue Due Date component', () => {
date.setDate(date.getDate() + 5);
vm = createComponent(date);
- expect(vm.$el.querySelector('time').textContent.trim()).toEqual(dateFormat(date, 'dddd', true));
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual(dateFormat(date, 'dddd'));
});
it('should render month and day for other dates', () => {
@@ -53,7 +53,7 @@ describe('Issue Due Date component', () => {
const isDueInCurrentYear = today.getFullYear() === date.getFullYear();
const format = isDueInCurrentYear ? 'mmm d' : 'mmm d, yyyy';
- expect(vm.$el.querySelector('time').textContent.trim()).toEqual(dateFormat(date, format, true));
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual(dateFormat(date, format));
});
it('should contain the correct `.text-danger` css class for overdue issue', () => {
diff --git a/spec/javascripts/clusters/clusters_bundle_spec.js b/spec/javascripts/clusters/clusters_bundle_spec.js
index 880b469284b..7928feeadfa 100644
--- a/spec/javascripts/clusters/clusters_bundle_spec.js
+++ b/spec/javascripts/clusters/clusters_bundle_spec.js
@@ -1,10 +1,5 @@
import Clusters from '~/clusters/clusters_bundle';
-import {
- REQUEST_LOADING,
- REQUEST_SUCCESS,
- REQUEST_FAILURE,
- APPLICATION_STATUS,
-} from '~/clusters/constants';
+import { REQUEST_SUBMITTED, REQUEST_FAILURE, APPLICATION_STATUS } from '~/clusters/constants';
import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
describe('Clusters', () => {
@@ -196,67 +191,43 @@ describe('Clusters', () => {
});
describe('installApplication', () => {
- it('tries to install helm', done => {
+ it('tries to install helm', () => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
cluster.installApplication({ id: 'helm' });
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalledWith('helm', undefined);
-
- getSetTimeoutPromise()
- .then(() => {
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUCCESS);
- expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
- })
- .then(done)
- .catch(done.fail);
});
- it('tries to install ingress', done => {
+ it('tries to install ingress', () => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.ingress.requestStatus).toEqual(null);
cluster.installApplication({ id: 'ingress' });
- expect(cluster.store.state.applications.ingress.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.ingress.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.ingress.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalledWith('ingress', undefined);
-
- getSetTimeoutPromise()
- .then(() => {
- expect(cluster.store.state.applications.ingress.requestStatus).toEqual(REQUEST_SUCCESS);
- expect(cluster.store.state.applications.ingress.requestReason).toEqual(null);
- })
- .then(done)
- .catch(done.fail);
});
- it('tries to install runner', done => {
+ it('tries to install runner', () => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.runner.requestStatus).toEqual(null);
cluster.installApplication({ id: 'runner' });
- expect(cluster.store.state.applications.runner.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.runner.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.runner.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalledWith('runner', undefined);
-
- getSetTimeoutPromise()
- .then(() => {
- expect(cluster.store.state.applications.runner.requestStatus).toEqual(REQUEST_SUCCESS);
- expect(cluster.store.state.applications.runner.requestReason).toEqual(null);
- })
- .then(done)
- .catch(done.fail);
});
- it('tries to install jupyter', done => {
+ it('tries to install jupyter', () => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(null);
@@ -265,19 +236,11 @@ describe('Clusters', () => {
params: { hostname: cluster.store.state.applications.jupyter.hostname },
});
- expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.jupyter.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalledWith('jupyter', {
hostname: cluster.store.state.applications.jupyter.hostname,
});
-
- getSetTimeoutPromise()
- .then(() => {
- expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_SUCCESS);
- expect(cluster.store.state.applications.jupyter.requestReason).toEqual(null);
- })
- .then(done)
- .catch(done.fail);
});
it('sets error request status when the request fails', done => {
@@ -289,7 +252,7 @@ describe('Clusters', () => {
cluster.installApplication({ id: 'helm' });
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalled();
diff --git a/spec/javascripts/clusters/components/application_row_spec.js b/spec/javascripts/clusters/components/application_row_spec.js
index 45d56514930..8cb9713964e 100644
--- a/spec/javascripts/clusters/components/application_row_spec.js
+++ b/spec/javascripts/clusters/components/application_row_spec.js
@@ -1,11 +1,6 @@
import Vue from 'vue';
import eventHub from '~/clusters/event_hub';
-import {
- APPLICATION_STATUS,
- REQUEST_LOADING,
- REQUEST_SUCCESS,
- REQUEST_FAILURE,
-} from '~/clusters/constants';
+import { APPLICATION_STATUS, REQUEST_SUBMITTED, REQUEST_FAILURE } from '~/clusters/constants';
import applicationRow from '~/clusters/components/application_row.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { DEFAULT_APPLICATION_STATE } from '../services/mock_data';
@@ -57,6 +52,12 @@ describe('Application Row', () => {
expect(vm.installButtonLabel).toBeUndefined();
});
+ it('has install button', () => {
+ const installationBtn = vm.$el.querySelector('.js-cluster-application-install-button');
+
+ expect(installationBtn).not.toBe(null);
+ });
+
it('has disabled "Install" when APPLICATION_STATUS.NOT_INSTALLABLE', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
@@ -101,6 +102,18 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true);
});
+ it('has loading "Installing" when REQUEST_SUBMITTED', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ requestStatus: REQUEST_SUBMITTED,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Installing');
+ expect(vm.installButtonLoading).toEqual(true);
+ expect(vm.installButtonDisabled).toEqual(true);
+ });
+
it('has disabled "Installed" when APPLICATION_STATUS.INSTALLED', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
@@ -134,30 +147,6 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(false);
});
- it('has loading "Install" when REQUEST_LOADING', () => {
- vm = mountComponent(ApplicationRow, {
- ...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.INSTALLABLE,
- requestStatus: REQUEST_LOADING,
- });
-
- expect(vm.installButtonLabel).toEqual('Install');
- expect(vm.installButtonLoading).toEqual(true);
- expect(vm.installButtonDisabled).toEqual(true);
- });
-
- it('has disabled "Install" when REQUEST_SUCCESS', () => {
- vm = mountComponent(ApplicationRow, {
- ...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.INSTALLABLE,
- requestStatus: REQUEST_SUCCESS,
- });
-
- expect(vm.installButtonLabel).toEqual('Install');
- expect(vm.installButtonLoading).toEqual(false);
- expect(vm.installButtonDisabled).toEqual(true);
- });
-
it('has enabled "Install" when REQUEST_FAILURE (so you can try installing again)', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
@@ -219,6 +208,144 @@ describe('Application Row', () => {
});
});
+ describe('Upgrade button', () => {
+ it('has indeterminate state on page load', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: null,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ expect(upgradeBtn).toBe(null);
+ });
+
+ it('has enabled "Upgrade" when "upgradeAvailable" is true', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ upgradeAvailable: true,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ expect(upgradeBtn).not.toBe(null);
+ expect(upgradeBtn.innerHTML).toContain('Upgrade');
+ });
+
+ it('has enabled "Retry upgrade" when APPLICATION_STATUS.UPDATE_ERRORED', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATE_ERRORED,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ expect(upgradeBtn).not.toBe(null);
+ expect(vm.upgradeFailed).toBe(true);
+ expect(upgradeBtn.innerHTML).toContain('Retry upgrade');
+ });
+
+ it('has disabled "Retry upgrade" when APPLICATION_STATUS.UPDATING', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATING,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ expect(upgradeBtn).not.toBe(null);
+ expect(vm.isUpgrading).toBe(true);
+ expect(upgradeBtn.innerHTML).toContain('Upgrading');
+ });
+
+ it('clicking upgrade button emits event', () => {
+ spyOn(eventHub, '$emit');
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATE_ERRORED,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ upgradeBtn.click();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('upgradeApplication', {
+ id: DEFAULT_APPLICATION_STATE.id,
+ params: {},
+ });
+ });
+
+ it('clicking disabled upgrade button emits nothing', () => {
+ spyOn(eventHub, '$emit');
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATING,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ upgradeBtn.click();
+
+ expect(eventHub.$emit).not.toHaveBeenCalled();
+ });
+
+ it('displays an error message if application upgrade failed', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ title: 'GitLab Runner',
+ status: APPLICATION_STATUS.UPDATE_ERRORED,
+ });
+ const failureMessage = vm.$el.querySelector(
+ '.js-cluster-application-upgrade-failure-message',
+ );
+
+ expect(failureMessage).not.toBe(null);
+ expect(failureMessage.innerHTML).toContain(
+ 'Something went wrong when upgrading GitLab Runner. Please check the logs and try again.',
+ );
+ });
+ });
+
+ describe('Version', () => {
+ it('displays a version number if application has been upgraded', () => {
+ const version = '0.1.45';
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATED,
+ version,
+ });
+ const upgradeDetails = vm.$el.querySelector('.js-cluster-application-upgrade-details');
+ const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
+
+ expect(upgradeDetails.innerHTML).toContain('Upgraded');
+ expect(versionEl).not.toBe(null);
+ expect(versionEl.innerHTML).toContain(version);
+ });
+
+ it('contains a link to the chart repo if application has been upgraded', () => {
+ const version = '0.1.45';
+ const chartRepo = 'https://gitlab.com/charts/gitlab-runner';
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATED,
+ chartRepo,
+ version,
+ });
+ const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
+
+ expect(versionEl.href).toEqual(chartRepo);
+ expect(versionEl.target).toEqual('_blank');
+ });
+
+ it('does not display a version number if application upgrade failed', () => {
+ const version = '0.1.45';
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATE_ERRORED,
+ version,
+ });
+ const upgradeDetails = vm.$el.querySelector('.js-cluster-application-upgrade-details');
+ const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
+
+ expect(upgradeDetails.innerHTML).toContain('failed');
+ expect(versionEl).toBe(null);
+ });
+ });
+
describe('Error block', () => {
it('does not show error block when there is no error', () => {
vm = mountComponent(ApplicationRow, {
diff --git a/spec/javascripts/clusters/stores/clusters_store_spec.js b/spec/javascripts/clusters/stores/clusters_store_spec.js
index 1ca55549094..37a4d6614f6 100644
--- a/spec/javascripts/clusters/stores/clusters_store_spec.js
+++ b/spec/javascripts/clusters/stores/clusters_store_spec.js
@@ -62,6 +62,7 @@ describe('Clusters Store', () => {
ingressHelpPath: null,
status: mockResponseData.status,
statusReason: mockResponseData.status_reason,
+ rbac: false,
applications: {
helm: {
title: 'Helm Tiller',
@@ -84,6 +85,9 @@ describe('Clusters Store', () => {
statusReason: mockResponseData.applications[2].status_reason,
requestStatus: null,
requestReason: null,
+ version: mockResponseData.applications[2].version,
+ upgradeAvailable: mockResponseData.applications[2].update_available,
+ chartRepo: 'https://gitlab.com/charts/gitlab-runner',
},
prometheus: {
title: 'Prometheus',
diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js b/spec/javascripts/commit/pipelines/pipelines_spec.js
index 04c8ab44405..fec01b1f0a3 100644
--- a/spec/javascripts/commit/pipelines/pipelines_spec.js
+++ b/spec/javascripts/commit/pipelines/pipelines_spec.js
@@ -87,7 +87,7 @@ describe('Pipelines table in Commits and Merge requests', function() {
};
vm.$nextTick(() => {
- vm.$el.querySelector('.js-next-button a').click();
+ vm.$el.querySelector('.js-next-button .page-link').click();
expect(vm.updateContent).toHaveBeenCalledWith({ page: '2' });
done();
diff --git a/spec/javascripts/diffs/components/app_spec.js b/spec/javascripts/diffs/components/app_spec.js
index a2cbc0f3c72..d81c433cca6 100644
--- a/spec/javascripts/diffs/components/app_spec.js
+++ b/spec/javascripts/diffs/components/app_spec.js
@@ -1,15 +1,24 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlLoadingIcon } from '@gitlab/ui';
import { TEST_HOST } from 'spec/test_constants';
import App from '~/diffs/components/app.vue';
import NoChanges from '~/diffs/components/no_changes.vue';
import DiffFile from '~/diffs/components/diff_file.vue';
+import Mousetrap from 'mousetrap';
+import CompareVersions from '~/diffs/components/compare_versions.vue';
+import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue';
+import CommitWidget from '~/diffs/components/commit_widget.vue';
+import TreeList from '~/diffs/components/tree_list.vue';
import createDiffsStore from '../create_diffs_store';
+import diffsMockData from '../mock_data/merge_request_diffs';
+
+const mergeRequestDiff = { version_index: 1 };
describe('diffs/components/app', () => {
const oldMrTabs = window.mrTabs;
let store;
- let vm;
+ let wrapper;
function createComponent(props = {}, extendStore = () => {}) {
const localVue = createLocalVue();
@@ -21,7 +30,7 @@ describe('diffs/components/app', () => {
extendStore(store);
- vm = shallowMount(localVue.extend(App), {
+ wrapper = shallowMount(localVue.extend(App), {
localVue,
propsData: {
endpoint: `${TEST_HOST}/diff/endpoint`,
@@ -38,7 +47,6 @@ describe('diffs/components/app', () => {
// setup globals (needed for component to mount :/)
window.mrTabs = jasmine.createSpyObj('mrTabs', ['resetViewContainer']);
window.mrTabs.expandViewContainer = jasmine.createSpy();
- window.location.hash = 'ABC_123';
});
afterEach(() => {
@@ -46,23 +54,96 @@ describe('diffs/components/app', () => {
window.mrTabs = oldMrTabs;
// reset component
- vm.destroy();
+ wrapper.destroy();
+ });
+
+ it('displays loading icon on loading', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.isLoading = true;
+ });
+
+ expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ });
+
+ it('displays diffs container when not loading', () => {
+ createComponent();
+
+ expect(wrapper.contains(GlLoadingIcon)).toBe(false);
+ expect(wrapper.contains('#diffs')).toBe(true);
});
it('does not show commit info', () => {
createComponent();
- expect(vm.contains('.blob-commit-info')).toBe(false);
+ expect(wrapper.contains('.blob-commit-info')).toBe(false);
+ });
+
+ describe('row highlighting', () => {
+ beforeEach(() => {
+ window.location.hash = 'ABC_123';
+ });
+
+ it('sets highlighted row if hash exists in location object', done => {
+ createComponent({
+ shouldShow: true,
+ });
+
+ // Component uses $nextTick so we wait until that has finished
+ setTimeout(() => {
+ expect(store.state.diffs.highlightedRow).toBe('ABC_123');
+
+ done();
+ });
+ });
+
+ it('marks current diff file based on currently highlighted row', done => {
+ createComponent({
+ shouldShow: true,
+ });
+
+ // Component uses $nextTick so we wait until that has finished
+ setTimeout(() => {
+ expect(store.state.diffs.currentDiffFileId).toBe('ABC');
+
+ done();
+ });
+ });
+ });
+
+ describe('resizable', () => {
+ afterEach(() => {
+ localStorage.removeItem('mr_tree_list_width');
+ });
+
+ it('sets initial width when no localStorage has been set', () => {
+ createComponent();
+
+ expect(wrapper.vm.treeWidth).toEqual(320);
+ });
+
+ it('sets initial width to localStorage size', () => {
+ localStorage.setItem('mr_tree_list_width', '200');
+
+ createComponent();
+
+ expect(wrapper.vm.treeWidth).toEqual(200);
+ });
+
+ it('sets width of tree list', () => {
+ createComponent();
+
+ expect(wrapper.find('.js-diff-tree-list').element.style.width).toEqual('320px');
+ });
});
- it('sets highlighted row if hash exists in location object', done => {
+ it('marks current diff file based on currently highlighted row', done => {
createComponent({
shouldShow: true,
});
// Component uses $nextTick so we wait until that has finished
setTimeout(() => {
- expect(store.state.diffs.highlightedRow).toBe('ABC_123');
+ expect(store.state.diffs.currentDiffFileId).toBe('ABC');
done();
});
@@ -72,27 +153,248 @@ describe('diffs/components/app', () => {
it('renders empty state when no diff files exist', () => {
createComponent();
- expect(vm.contains(NoChanges)).toBe(true);
+ expect(wrapper.contains(NoChanges)).toBe(true);
});
it('does not render empty state when diff files exist', () => {
- createComponent({}, () => {
- store.state.diffs.diffFiles.push({
+ createComponent({}, ({ state }) => {
+ state.diffs.diffFiles.push({
id: 1,
});
});
- expect(vm.contains(NoChanges)).toBe(false);
- expect(vm.findAll(DiffFile).length).toBe(1);
+ expect(wrapper.contains(NoChanges)).toBe(false);
+ expect(wrapper.findAll(DiffFile).length).toBe(1);
});
it('does not render empty state when versions match', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.startVersion = mergeRequestDiff;
+ state.diffs.mergeRequestDiff = mergeRequestDiff;
+ });
+
+ expect(wrapper.contains(NoChanges)).toBe(false);
+ });
+ });
+
+ describe('keyboard shortcut navigation', () => {
+ const mappings = {
+ '[': -1,
+ k: -1,
+ ']': +1,
+ j: +1,
+ };
+ let spy;
+
+ describe('visible app', () => {
+ beforeEach(() => {
+ spy = jasmine.createSpy('spy');
+
+ createComponent({
+ shouldShow: true,
+ });
+ wrapper.setMethods({
+ jumpToFile: spy,
+ });
+ });
+
+ it('calls `jumpToFile()` with correct parameter whenever pre-defined key is pressed', done => {
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ Object.keys(mappings).forEach(function(key) {
+ Mousetrap.trigger(key);
+
+ expect(spy.calls.mostRecent().args).toEqual([mappings[key]]);
+ });
+
+ expect(spy.calls.count()).toEqual(Object.keys(mappings).length);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('does not call `jumpToFile()` when unknown key is pressed', done => {
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ Mousetrap.trigger('d');
+
+ expect(spy).not.toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('hideen app', () => {
+ beforeEach(() => {
+ spy = jasmine.createSpy('spy');
+
+ createComponent({
+ shouldShow: false,
+ });
+ wrapper.setMethods({
+ jumpToFile: spy,
+ });
+ });
+
+ it('stops calling `jumpToFile()` when application is hidden', done => {
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ Object.keys(mappings).forEach(function(key) {
+ Mousetrap.trigger(key);
+
+ expect(spy).not.toHaveBeenCalled();
+ });
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+ });
+
+ describe('jumpToFile', () => {
+ let spy;
+
+ beforeEach(() => {
+ spy = jasmine.createSpy();
+
createComponent({}, () => {
- store.state.diffs.startVersion = { version_index: 1 };
- store.state.diffs.mergeRequestDiff = { version_index: 1 };
+ store.state.diffs.diffFiles = [
+ { file_hash: '111', file_path: '111.js' },
+ { file_hash: '222', file_path: '222.js' },
+ { file_hash: '333', file_path: '333.js' },
+ ];
+ });
+
+ wrapper.setMethods({
+ scrollToFile: spy,
});
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('jumps to next and previous files in the list', done => {
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ wrapper.vm.jumpToFile(+1);
+
+ expect(spy.calls.mostRecent().args).toEqual(['222.js']);
+ store.state.diffs.currentDiffFileId = '222';
+ wrapper.vm.jumpToFile(+1);
+
+ expect(spy.calls.mostRecent().args).toEqual(['333.js']);
+ store.state.diffs.currentDiffFileId = '333';
+ wrapper.vm.jumpToFile(-1);
+
+ expect(spy.calls.mostRecent().args).toEqual(['222.js']);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('does not jump to previous file from the first one', done => {
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ store.state.diffs.currentDiffFileId = '333';
+
+ expect(wrapper.vm.currentDiffIndex).toEqual(2);
+
+ wrapper.vm.jumpToFile(+1);
+
+ expect(wrapper.vm.currentDiffIndex).toEqual(2);
+ expect(spy).not.toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('does not jump to next file from the last one', done => {
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ expect(wrapper.vm.currentDiffIndex).toEqual(0);
+
+ wrapper.vm.jumpToFile(-1);
+
+ expect(wrapper.vm.currentDiffIndex).toEqual(0);
+ expect(spy).not.toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('diffs', () => {
+ it('should render compare versions component', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.mergeRequestDiffs = diffsMockData;
+ state.diffs.targetBranchName = 'target-branch';
+ state.diffs.mergeRequestDiff = mergeRequestDiff;
+ });
+
+ expect(wrapper.contains(CompareVersions)).toBe(true);
+ expect(wrapper.find(CompareVersions).props()).toEqual(
+ jasmine.objectContaining({
+ targetBranch: {
+ branchName: 'target-branch',
+ versionIndex: -1,
+ path: '',
+ },
+ mergeRequestDiffs: diffsMockData,
+ mergeRequestDiff,
+ }),
+ );
+ });
+
+ it('should render hidden files warning if render overflow warning is present', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.renderOverflowWarning = true;
+ state.diffs.realSize = '5';
+ state.diffs.plainDiffPath = 'plain diff path';
+ state.diffs.emailPatchPath = 'email patch path';
+ state.diffs.size = 1;
+ });
+
+ expect(wrapper.contains(HiddenFilesWarning)).toBe(true);
+ expect(wrapper.find(HiddenFilesWarning).props()).toEqual(
+ jasmine.objectContaining({
+ total: '5',
+ plainDiffPath: 'plain diff path',
+ emailPatchPath: 'email patch path',
+ visible: 1,
+ }),
+ );
+ });
+
+ it('should display commit widget if store has a commit', () => {
+ createComponent({}, () => {
+ store.state.diffs.commit = {
+ author: 'John Doe',
+ };
+ });
+
+ expect(wrapper.contains(CommitWidget)).toBe(true);
+ });
+
+ it('should display diff file if there are diff files', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.diffFiles.push({ sha: '123' });
+ });
+
+ expect(wrapper.contains(DiffFile)).toBe(true);
+ });
+
+ it('should render tree list', () => {
+ createComponent();
- expect(vm.contains(NoChanges)).toBe(false);
+ expect(wrapper.find(TreeList).exists()).toBe(true);
});
});
});
diff --git a/spec/javascripts/diffs/components/changed_files_dropdown_spec.js b/spec/javascripts/diffs/components/changed_files_dropdown_spec.js
deleted file mode 100644
index 7237274eb43..00000000000
--- a/spec/javascripts/diffs/components/changed_files_dropdown_spec.js
+++ /dev/null
@@ -1 +0,0 @@
-// TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
diff --git a/spec/javascripts/diffs/components/commit_item_spec.js b/spec/javascripts/diffs/components/commit_item_spec.js
index 8b2ca6506c4..50e45f48af3 100644
--- a/spec/javascripts/diffs/components/commit_item_spec.js
+++ b/spec/javascripts/diffs/components/commit_item_spec.js
@@ -80,6 +80,8 @@ describe('diffs/components/commit_item', () => {
expect(trimText(committerElement.textContent)).toEqual(expectedText);
expect(nameElement).toHaveAttr('href', commit.author.web_url);
expect(nameElement).toHaveText(commit.author.name);
+ expect(nameElement).toHaveClass('js-user-link');
+ expect(nameElement.dataset.userId).toEqual(commit.author.id.toString());
});
describe('without commit description', () => {
diff --git a/spec/javascripts/diffs/components/compare_versions_dropdown_spec.js b/spec/javascripts/diffs/components/compare_versions_dropdown_spec.js
index 7237274eb43..8a3834d542f 100644
--- a/spec/javascripts/diffs/components/compare_versions_dropdown_spec.js
+++ b/spec/javascripts/diffs/components/compare_versions_dropdown_spec.js
@@ -1 +1,161 @@
-// TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import CompareVersionsDropdown from '~/diffs/components/compare_versions_dropdown.vue';
+import diffsMockData from '../mock_data/merge_request_diffs';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+
+const localVue = createLocalVue();
+const targetBranch = { branchName: 'tmp-wine-dev', versionIndex: -1 };
+const startVersion = { version_index: 4 };
+const mergeRequestVersion = {
+ version_path: '123',
+};
+const baseVersionPath = '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37';
+
+describe('CompareVersionsDropdown', () => {
+ let wrapper;
+
+ const findSelectedVersion = () => wrapper.find('.dropdown-menu-toggle');
+ const findVersionsListElements = () => wrapper.findAll('li');
+ const findLinkElement = index =>
+ findVersionsListElements()
+ .at(index)
+ .find('a');
+ const findLastLink = () => findLinkElement(findVersionsListElements().length - 1);
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(localVue.extend(CompareVersionsDropdown), {
+ localVue,
+ sync: false,
+ propsData: { ...props },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('selected version name', () => {
+ it('shows latest version when latest is selected', () => {
+ createComponent({
+ mergeRequestVersion,
+ startVersion,
+ otherVersions: diffsMockData,
+ });
+
+ expect(findSelectedVersion().text()).toBe('latest version');
+ });
+
+ it('shows target branch name for base branch', () => {
+ createComponent({
+ targetBranch,
+ });
+
+ expect(findSelectedVersion().text()).toBe('tmp-wine-dev');
+ });
+
+ it('shows correct version for non-base and non-latest branches', () => {
+ createComponent({
+ startVersion,
+ targetBranch,
+ });
+
+ expect(findSelectedVersion().text()).toBe(`version ${startVersion.version_index}`);
+ });
+ });
+
+ describe('target versions list', () => {
+ it('should have the same length as otherVersions if merge request version is present', () => {
+ createComponent({
+ mergeRequestVersion,
+ otherVersions: diffsMockData,
+ });
+
+ expect(findVersionsListElements().length).toEqual(diffsMockData.length);
+ });
+
+ it('should have an otherVersions length plus 1 if no merge request version is present', () => {
+ createComponent({
+ targetBranch,
+ otherVersions: diffsMockData,
+ });
+
+ expect(findVersionsListElements().length).toEqual(diffsMockData.length + 1);
+ });
+
+ it('should have base branch link as active on base branch', () => {
+ createComponent({
+ targetBranch,
+ otherVersions: diffsMockData,
+ });
+
+ expect(findLastLink().classes()).toContain('is-active');
+ });
+
+ it('should have correct branch link as active if start version present', () => {
+ createComponent({
+ targetBranch,
+ startVersion,
+ otherVersions: diffsMockData,
+ });
+
+ expect(findLinkElement(0).classes()).toContain('is-active');
+ });
+
+ it('should render a correct base version link', () => {
+ createComponent({
+ baseVersionPath,
+ otherVersions: diffsMockData.slice(1),
+ targetBranch,
+ });
+
+ expect(findLastLink().attributes('href')).toEqual(baseVersionPath);
+ expect(findLastLink().text()).toContain('(base)');
+ });
+
+ it('should not render commits count if no showCommitsCount is passed', () => {
+ createComponent({
+ otherVersions: diffsMockData,
+ targetBranch,
+ });
+
+ const commitsCount = diffsMockData[0].commits_count;
+
+ expect(findLinkElement(0).text()).not.toContain(`${commitsCount} commit`);
+ });
+
+ it('should render correct commits count if showCommitsCount is passed', () => {
+ createComponent({
+ otherVersions: diffsMockData,
+ targetBranch,
+ showCommitCount: true,
+ });
+
+ const commitsCount = diffsMockData[0].commits_count;
+
+ expect(findLinkElement(0).text()).toContain(`${commitsCount} commit`);
+ });
+
+ it('should render correct commit sha', () => {
+ createComponent({
+ otherVersions: diffsMockData,
+ targetBranch,
+ });
+
+ const commitShaElement = findLinkElement(0).find('.commit-sha');
+
+ expect(commitShaElement.text()).toBe(diffsMockData[0].short_commit_sha);
+ });
+
+ it('should render correct time-ago ', () => {
+ createComponent({
+ otherVersions: diffsMockData,
+ targetBranch,
+ });
+
+ const timeAgoElement = findLinkElement(0).find(TimeAgo);
+
+ expect(timeAgoElement.exists()).toBe(true);
+ expect(timeAgoElement.props('time')).toBe(diffsMockData[0].created_at);
+ });
+ });
+});
diff --git a/spec/javascripts/diffs/components/compare_versions_spec.js b/spec/javascripts/diffs/components/compare_versions_spec.js
index 75c66e9ca82..e886f962d2f 100644
--- a/spec/javascripts/diffs/components/compare_versions_spec.js
+++ b/spec/javascripts/diffs/components/compare_versions_spec.js
@@ -10,6 +10,10 @@ describe('CompareVersions', () => {
const targetBranch = { branchName: 'tmp-wine-dev', versionIndex: -1 };
beforeEach(() => {
+ store.state.diffs.addedLines = 10;
+ store.state.diffs.removedLines = 20;
+ store.state.diffs.diffFiles.push('test');
+
vm = createComponentWithStore(Vue.extend(CompareVersionsComponent), store, {
mergeRequestDiffs: diffsMockData,
mergeRequestDiff: diffsMockData[0],
@@ -22,10 +26,10 @@ describe('CompareVersions', () => {
const treeListBtn = vm.$el.querySelector('.js-toggle-tree-list');
expect(treeListBtn).not.toBeNull();
- expect(treeListBtn.dataset.originalTitle).toBe('Toggle file browser');
+ expect(treeListBtn.dataset.originalTitle).toBe('Hide file browser');
expect(treeListBtn.querySelectorAll('svg use').length).not.toBe(0);
expect(treeListBtn.querySelector('svg use').getAttribute('xlink:href')).toContain(
- '#hamburger',
+ '#collapse-left',
);
});
@@ -51,15 +55,6 @@ describe('CompareVersions', () => {
});
});
- it('should render whitespace toggle button with correct attributes', () => {
- const whitespaceBtn = vm.$el.querySelector('.qa-toggle-whitespace');
- const href = vm.toggleWhitespacePath;
-
- expect(whitespaceBtn).not.toBeNull();
- expect(whitespaceBtn.getAttribute('href')).toEqual(href);
- expect(whitespaceBtn.innerHTML).toContain('Hide whitespace changes');
- });
-
it('should render view types buttons with correct values', () => {
const inlineBtn = vm.$el.querySelector('#inline-diff-btn');
const parallelBtn = vm.$el.querySelector('#parallel-diff-btn');
@@ -100,27 +95,9 @@ describe('CompareVersions', () => {
});
});
- describe('isWhitespaceVisible', () => {
- const originalHref = window.location.href;
-
- afterEach(() => {
- window.history.replaceState({}, null, originalHref);
- });
-
- it('should return "true" when no "w" flag is present in the URL (default)', () => {
- expect(vm.isWhitespaceVisible()).toBe(true);
- });
-
- it('should return "false" when the flag is set to "1" in the URL', () => {
- window.history.replaceState({}, null, '?w=1');
-
- expect(vm.isWhitespaceVisible()).toBe(false);
- });
-
- it('should return "true" when the flag is set to "0" in the URL', () => {
- window.history.replaceState({}, null, '?w=0');
-
- expect(vm.isWhitespaceVisible()).toBe(true);
+ describe('baseVersionPath', () => {
+ it('should be set correctly from mergeRequestDiff', () => {
+ expect(vm.baseVersionPath).toEqual(vm.mergeRequestDiff.base_version_path);
});
});
diff --git a/spec/javascripts/diffs/components/diff_content_spec.js b/spec/javascripts/diffs/components/diff_content_spec.js
index 9e158327a77..bc9288e4150 100644
--- a/spec/javascripts/diffs/components/diff_content_spec.js
+++ b/spec/javascripts/diffs/components/diff_content_spec.js
@@ -1,11 +1,12 @@
import Vue from 'vue';
import DiffContentComponent from '~/diffs/components/diff_content.vue';
-import { createStore } from '~/mr_notes/stores';
+import { createStore } from 'ee_else_ce/mr_notes/stores';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
import '~/behaviors/markdown/render_gfm';
import diffFileMockData from '../mock_data/diff_file';
import discussionsMockData from '../mock_data/diff_discussions';
+import { diffViewerModes } from '~/ide/constants';
describe('DiffContent', () => {
const Component = Vue.extend(DiffContentComponent);
@@ -52,26 +53,39 @@ describe('DiffContent', () => {
describe('empty files', () => {
beforeEach(() => {
- vm.diffFile.empty = true;
vm.diffFile.highlighted_diff_lines = [];
vm.diffFile.parallel_diff_lines = [];
});
- it('should render a message', done => {
+ it('should render a no preview message if viewer returns no preview', done => {
+ vm.diffFile.viewer.name = diffViewerModes.no_preview;
vm.$nextTick(() => {
const block = vm.$el.querySelector('.diff-viewer .nothing-here-block');
expect(block).not.toBe(null);
- expect(block.textContent.trim()).toContain('Empty file');
+ expect(block.textContent.trim()).toContain('No preview for this file type');
+
+ done();
+ });
+ });
+
+ it('should render a not diffable message if viewer returns not diffable', done => {
+ vm.diffFile.viewer.name = diffViewerModes.not_diffable;
+ vm.$nextTick(() => {
+ const block = vm.$el.querySelector('.diff-viewer .nothing-here-block');
+
+ expect(block).not.toBe(null);
+ expect(block.textContent.trim()).toContain(
+ 'This diff was suppressed by a .gitattributes entry',
+ );
done();
});
});
it('should not render multiple messages', done => {
- vm.diffFile.mode_changed = true;
vm.diffFile.b_mode = '100755';
- vm.diffFile.viewer.name = 'mode_changed';
+ vm.diffFile.viewer.name = diffViewerModes.mode_changed;
vm.$nextTick(() => {
expect(vm.$el.querySelectorAll('.nothing-here-block').length).toBe(1);
@@ -81,6 +95,7 @@ describe('DiffContent', () => {
});
it('should not render diff table', done => {
+ vm.diffFile.viewer.name = diffViewerModes.no_preview;
vm.$nextTick(() => {
expect(vm.$el.querySelector('table')).toBe(null);
@@ -157,6 +172,7 @@ describe('DiffContent', () => {
vm.diffFile.new_sha = 'DEF';
vm.diffFile.old_path = 'test.abc';
vm.diffFile.old_sha = 'ABC';
+ vm.diffFile.viewer.name = diffViewerModes.added;
vm.$nextTick(() => {
expect(el.querySelectorAll('.js-diff-inline-view').length).toEqual(0);
diff --git a/spec/javascripts/diffs/components/diff_file_header_spec.js b/spec/javascripts/diffs/components/diff_file_header_spec.js
index b77907ff26f..1201f066d2f 100644
--- a/spec/javascripts/diffs/components/diff_file_header_spec.js
+++ b/spec/javascripts/diffs/components/diff_file_header_spec.js
@@ -4,15 +4,15 @@ import diffsModule from '~/diffs/store/modules';
import notesModule from '~/notes/stores/modules';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import diffDiscussionsMockData from '../mock_data/diff_discussions';
+import { diffViewerModes } from '~/ide/constants';
Vue.use(Vuex);
-const discussionFixture = 'merge_requests/diff_discussion.json';
-
describe('diff_file_header', () => {
let vm;
let props;
- const diffDiscussionMock = getJSONFixture(discussionFixture)[0];
+ const diffDiscussionMock = diffDiscussionsMockData;
const Component = Vue.extend(DiffFileHeader);
const store = new Vuex.Store({
@@ -24,6 +24,10 @@ describe('diff_file_header', () => {
beforeEach(() => {
const diffFile = diffDiscussionMock.diff_file;
+
+ diffFile.added_lines = 2;
+ diffFile.removed_lines = 1;
+
props = {
diffFile: { ...diffFile },
canCurrentUserFork: false,
@@ -299,13 +303,13 @@ describe('diff_file_header', () => {
});
it('displays old and new path if the file was renamed', () => {
- props.diffFile.renamed_file = true;
+ props.diffFile.viewer.name = diffViewerModes.renamed;
vm = mountComponentWithStore(Component, { props, store });
expect(filePaths()).toHaveLength(2);
- expect(filePaths()[0]).toHaveText(props.diffFile.old_path);
- expect(filePaths()[1]).toHaveText(props.diffFile.new_path);
+ expect(filePaths()[0]).toHaveText(props.diffFile.old_path_html);
+ expect(filePaths()[1]).toHaveText(props.diffFile.new_path_html);
});
});
@@ -315,14 +319,12 @@ describe('diff_file_header', () => {
const button = vm.$el.querySelector('.btn-clipboard');
expect(button).not.toBe(null);
- expect(button.dataset.clipboardText).toBe(
- '{"text":"files/ruby/popen.rb","gfm":"`files/ruby/popen.rb`"}',
- );
+ expect(button.dataset.clipboardText).toBe('{"text":"CHANGELOG.rb","gfm":"`CHANGELOG.rb`"}');
});
describe('file mode', () => {
it('it displays old and new file mode if it changed', () => {
- props.diffFile.mode_changed = true;
+ props.diffFile.viewer.name = diffViewerModes.mode_changed;
vm = mountComponentWithStore(Component, { props, store });
@@ -334,7 +336,7 @@ describe('diff_file_header', () => {
});
it('does not display the file mode if it has not changed', () => {
- props.diffFile.mode_changed = false;
+ props.diffFile.viewer.name = diffViewerModes.text;
vm = mountComponentWithStore(Component, { props, store });
@@ -489,5 +491,89 @@ describe('diff_file_header', () => {
});
});
});
+
+ describe('file actions', () => {
+ it('should not render if diff file has a submodule', () => {
+ props.diffFile.submodule = 'submodule';
+ vm = mountComponentWithStore(Component, { props, store });
+
+ expect(vm.$el.querySelector('.file-actions')).toEqual(null);
+ });
+
+ it('should not render if add merge request buttons is false', () => {
+ props.addMergeRequestButtons = false;
+ vm = mountComponentWithStore(Component, { props, store });
+
+ expect(vm.$el.querySelector('.file-actions')).toEqual(null);
+ });
+
+ describe('with add merge request buttons enabled', () => {
+ beforeEach(() => {
+ props.addMergeRequestButtons = true;
+ props.diffFile.edit_path = 'edit-path';
+ });
+
+ const viewReplacedFileButton = () => vm.$el.querySelector('.js-view-replaced-file');
+ const viewFileButton = () => vm.$el.querySelector('.js-view-file-button');
+ const externalUrl = () => vm.$el.querySelector('.js-external-url');
+
+ it('should render if add merge request buttons is true and diff file does not have a submodule', () => {
+ vm = mountComponentWithStore(Component, { props, store });
+
+ expect(vm.$el.querySelector('.file-actions')).not.toEqual(null);
+ });
+
+ it('should not render view replaced file button if no replaced view path is present', () => {
+ vm = mountComponentWithStore(Component, { props, store });
+
+ expect(viewReplacedFileButton()).toEqual(null);
+ });
+
+ it('should render view replaced file button if replaced view path is present', () => {
+ props.diffFile.replaced_view_path = 'replaced-view-path';
+ vm = mountComponentWithStore(Component, { props, store });
+
+ expect(viewReplacedFileButton()).not.toEqual(null);
+ expect(viewReplacedFileButton().getAttribute('href')).toBe('replaced-view-path');
+ });
+
+ it('should render correct file view button path', () => {
+ props.diffFile.view_path = 'view-path';
+ vm = mountComponentWithStore(Component, { props, store });
+
+ expect(viewFileButton().getAttribute('href')).toBe('view-path');
+ });
+
+ it('should not render external url view link if diff file has no external url', () => {
+ vm = mountComponentWithStore(Component, { props, store });
+
+ expect(externalUrl()).toEqual(null);
+ });
+
+ it('should render external url view link if diff file has external url', () => {
+ props.diffFile.external_url = 'external_url';
+ vm = mountComponentWithStore(Component, { props, store });
+
+ expect(externalUrl()).not.toEqual(null);
+ expect(externalUrl().getAttribute('href')).toBe('external_url');
+ });
+ });
+
+ describe('without file blob', () => {
+ beforeEach(() => {
+ props.diffFile.blob = null;
+ props.addMergeRequestButtons = true;
+ vm = mountComponentWithStore(Component, { props, store });
+ });
+
+ it('should not render toggle discussions button', () => {
+ expect(vm.$el.querySelector('.js-btn-vue-toggle-comments')).toEqual(null);
+ });
+
+ it('should not render edit button', () => {
+ expect(vm.$el.querySelector('.js-edit-blob')).toEqual(null);
+ });
+ });
+ });
});
});
diff --git a/spec/javascripts/diffs/components/diff_file_spec.js b/spec/javascripts/diffs/components/diff_file_spec.js
index 1af49282c36..ba04c8c4a4c 100644
--- a/spec/javascripts/diffs/components/diff_file_spec.js
+++ b/spec/javascripts/diffs/components/diff_file_spec.js
@@ -1,6 +1,7 @@
import Vue from 'vue';
import DiffFileComponent from '~/diffs/components/diff_file.vue';
-import store from '~/mr_notes/stores';
+import { diffViewerModes, diffViewerErrors } from '~/ide/constants';
+import store from 'ee_else_ce/mr_notes/stores';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
@@ -27,7 +28,6 @@ describe('DiffFile', () => {
expect(el.querySelector('.file-title-name').innerText.indexOf(file_path)).toBeGreaterThan(-1);
expect(el.querySelector('.js-syntax-highlight')).toBeDefined();
- expect(vm.file.renderIt).toEqual(false);
vm.file.renderIt = true;
vm.$nextTick(() => {
@@ -38,8 +38,8 @@ describe('DiffFile', () => {
describe('collapsed', () => {
it('should not have file content', done => {
expect(vm.$el.querySelectorAll('.diff-content').length).toEqual(1);
- expect(vm.file.collapsed).toEqual(false);
- vm.file.collapsed = true;
+ expect(vm.isCollapsed).toEqual(false);
+ vm.isCollapsed = true;
vm.file.renderIt = true;
vm.$nextTick(() => {
@@ -50,9 +50,8 @@ describe('DiffFile', () => {
});
it('should have collapsed text and link', done => {
- vm.file.renderIt = true;
- vm.file.collapsed = false;
- vm.file.highlighted_diff_lines = null;
+ vm.renderIt = true;
+ vm.isCollapsed = true;
vm.$nextTick(() => {
expect(vm.$el.innerText).toContain('This diff is collapsed');
@@ -63,8 +62,8 @@ describe('DiffFile', () => {
});
it('should have collapsed text and link even before rendered', done => {
- vm.file.renderIt = false;
- vm.file.collapsed = true;
+ vm.renderIt = false;
+ vm.isCollapsed = true;
vm.$nextTick(() => {
expect(vm.$el.innerText).toContain('This diff is collapsed');
@@ -75,10 +74,10 @@ describe('DiffFile', () => {
});
it('should be collapsed for renamed files', done => {
- vm.file.renderIt = true;
- vm.file.collapsed = false;
+ vm.renderIt = true;
+ vm.isCollapsed = false;
vm.file.highlighted_diff_lines = null;
- vm.file.renamed_file = true;
+ vm.file.viewer.name = diffViewerModes.renamed;
vm.$nextTick(() => {
expect(vm.$el.innerText).not.toContain('This diff is collapsed');
@@ -88,10 +87,10 @@ describe('DiffFile', () => {
});
it('should be collapsed for mode changed files', done => {
- vm.file.renderIt = true;
- vm.file.collapsed = false;
+ vm.renderIt = true;
+ vm.isCollapsed = false;
vm.file.highlighted_diff_lines = null;
- vm.file.mode_changed = true;
+ vm.file.viewer.name = diffViewerModes.mode_changed;
vm.$nextTick(() => {
expect(vm.$el.innerText).not.toContain('This diff is collapsed');
@@ -101,7 +100,7 @@ describe('DiffFile', () => {
});
it('should have loading icon while loading a collapsed diffs', done => {
- vm.file.collapsed = true;
+ vm.isCollapsed = true;
vm.isLoadingCollapsedDiff = true;
vm.$nextTick(() => {
@@ -116,7 +115,7 @@ describe('DiffFile', () => {
describe('too large diff', () => {
it('should have too large warning and blob link', done => {
const BLOB_LINK = '/file/view/path';
- vm.file.too_large = true;
+ vm.file.viewer.error = diffViewerErrors.too_large;
vm.file.view_path = BLOB_LINK;
vm.$nextTick(() => {
@@ -140,11 +139,11 @@ describe('DiffFile', () => {
vm.file.highlighted_diff_lines = undefined;
vm.file.parallel_diff_lines = [];
- vm.file.collapsed = true;
+ vm.isCollapsed = true;
vm.$nextTick()
.then(() => {
- vm.file.collapsed = false;
+ vm.isCollapsed = false;
return vm.$nextTick();
})
diff --git a/spec/javascripts/diffs/components/diff_stats_spec.js b/spec/javascripts/diffs/components/diff_stats_spec.js
new file mode 100644
index 00000000000..984b3026209
--- /dev/null
+++ b/spec/javascripts/diffs/components/diff_stats_spec.js
@@ -0,0 +1,33 @@
+import { shallowMount } from '@vue/test-utils';
+import DiffStats from '~/diffs/components/diff_stats.vue';
+
+describe('diff_stats', () => {
+ it('does not render a group if diffFileLengths is not passed in', () => {
+ const wrapper = shallowMount(DiffStats, {
+ propsData: {
+ addedLines: 1,
+ removedLines: 2,
+ },
+ });
+ const groups = wrapper.findAll('.diff-stats-group');
+
+ expect(groups.length).toBe(2);
+ });
+
+ it('shows amount of files changed, lines added and lines removed when passed all props', () => {
+ const wrapper = shallowMount(DiffStats, {
+ propsData: {
+ addedLines: 100,
+ removedLines: 200,
+ diffFilesLength: 300,
+ },
+ });
+ const additions = wrapper.find('icon-stub[name="file-addition"]').element.parentNode;
+ const deletions = wrapper.find('icon-stub[name="file-deletion"]').element.parentNode;
+ const filesChanged = wrapper.find('icon-stub[name="doc-code"]').element.parentNode;
+
+ expect(additions.textContent).toContain('100');
+ expect(deletions.textContent).toContain('200');
+ expect(filesChanged.textContent).toContain('300');
+ });
+});
diff --git a/spec/javascripts/diffs/components/edit_button_spec.js b/spec/javascripts/diffs/components/edit_button_spec.js
index 7237274eb43..ccdae4cb312 100644
--- a/spec/javascripts/diffs/components/edit_button_spec.js
+++ b/spec/javascripts/diffs/components/edit_button_spec.js
@@ -1 +1,61 @@
-// TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import EditButton from '~/diffs/components/edit_button.vue';
+
+const localVue = createLocalVue();
+const editPath = 'test-path';
+
+describe('EditButton', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(EditButton, {
+ localVue,
+ sync: false,
+ propsData: { ...props },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('has correct href attribute', () => {
+ createComponent({
+ editPath,
+ canCurrentUserFork: false,
+ });
+
+ expect(wrapper.attributes('href')).toBe(editPath);
+ });
+
+ it('emits a show fork message event if current user can fork', () => {
+ createComponent({
+ editPath,
+ canCurrentUserFork: true,
+ });
+ wrapper.trigger('click');
+
+ expect(wrapper.emitted('showForkMessage')).toBeTruthy();
+ });
+
+ it('doesnt emit a show fork message event if current user cannot fork', () => {
+ createComponent({
+ editPath,
+ canCurrentUserFork: false,
+ });
+ wrapper.trigger('click');
+
+ expect(wrapper.emitted('showForkMessage')).toBeFalsy();
+ });
+
+ it('doesnt emit a show fork message event if current user can modify blob', () => {
+ createComponent({
+ editPath,
+ canCurrentUserFork: true,
+ canModifyBlob: true,
+ });
+ wrapper.trigger('click');
+
+ expect(wrapper.emitted('showForkMessage')).toBeFalsy();
+ });
+});
diff --git a/spec/javascripts/diffs/components/hidden_files_warning_spec.js b/spec/javascripts/diffs/components/hidden_files_warning_spec.js
index 7237274eb43..5bf5ddd27bd 100644
--- a/spec/javascripts/diffs/components/hidden_files_warning_spec.js
+++ b/spec/javascripts/diffs/components/hidden_files_warning_spec.js
@@ -1 +1,48 @@
-// TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue';
+
+const localVue = createLocalVue();
+const propsData = {
+ total: '10',
+ visible: 5,
+ plainDiffPath: 'plain-diff-path',
+ emailPatchPath: 'email-patch-path',
+};
+
+describe('HiddenFilesWarning', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(HiddenFilesWarning, {
+ localVue,
+ sync: false,
+ propsData,
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('has a correct plain diff URL', () => {
+ const plainDiffLink = wrapper.findAll('a').wrappers.filter(x => x.text() === 'Plain diff')[0];
+
+ expect(plainDiffLink.attributes('href')).toBe(propsData.plainDiffPath);
+ });
+
+ it('has a correct email patch URL', () => {
+ const emailPatchLink = wrapper.findAll('a').wrappers.filter(x => x.text() === 'Email patch')[0];
+
+ expect(emailPatchLink.attributes('href')).toBe(propsData.emailPatchPath);
+ });
+
+ it('has a correct visible/total files text', () => {
+ const filesText = wrapper.find('strong');
+
+ expect(filesText.text()).toBe('5 of 10');
+ });
+});
diff --git a/spec/javascripts/diffs/components/inline_diff_view_spec.js b/spec/javascripts/diffs/components/inline_diff_view_spec.js
index 2316ee29106..4452106580a 100644
--- a/spec/javascripts/diffs/components/inline_diff_view_spec.js
+++ b/spec/javascripts/diffs/components/inline_diff_view_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import '~/behaviors/markdown/render_gfm';
import InlineDiffView from '~/diffs/components/inline_diff_view.vue';
-import store from '~/mr_notes/stores';
+import store from 'ee_else_ce/mr_notes/stores';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
import discussionsMockData from '../mock_data/diff_discussions';
diff --git a/spec/javascripts/diffs/components/parallel_diff_view_spec.js b/spec/javascripts/diffs/components/parallel_diff_view_spec.js
index 6f6b1c41915..236bda96145 100644
--- a/spec/javascripts/diffs/components/parallel_diff_view_spec.js
+++ b/spec/javascripts/diffs/components/parallel_diff_view_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue';
-import store from '~/mr_notes/stores';
+import store from 'ee_else_ce/mr_notes/stores';
import * as constants from '~/diffs/constants';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
@@ -18,6 +18,10 @@ describe('ParallelDiffView', () => {
}).$mount();
});
+ afterEach(() => {
+ component.$destroy();
+ });
+
describe('assigned', () => {
describe('diffLines', () => {
it('should normalize lines for empty cells', () => {
diff --git a/spec/javascripts/diffs/components/settings_dropdown_spec.js b/spec/javascripts/diffs/components/settings_dropdown_spec.js
new file mode 100644
index 00000000000..5031846cff0
--- /dev/null
+++ b/spec/javascripts/diffs/components/settings_dropdown_spec.js
@@ -0,0 +1,167 @@
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import diffModule from '~/diffs/store/modules';
+import SettingsDropdown from '~/diffs/components/settings_dropdown.vue';
+import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
+
+describe('Diff settiings dropdown component', () => {
+ let vm;
+ let actions;
+
+ function createComponent(extendStore = () => {}) {
+ const localVue = createLocalVue();
+
+ localVue.use(Vuex);
+
+ const store = new Vuex.Store({
+ modules: {
+ diffs: {
+ namespaced: true,
+ actions,
+ state: diffModule().state,
+ getters: diffModule().getters,
+ },
+ },
+ });
+
+ extendStore(store);
+
+ vm = mount(SettingsDropdown, {
+ localVue,
+ store,
+ });
+ }
+
+ beforeEach(() => {
+ actions = {
+ setInlineDiffViewType: jasmine.createSpy('setInlineDiffViewType'),
+ setParallelDiffViewType: jasmine.createSpy('setParallelDiffViewType'),
+ setRenderTreeList: jasmine.createSpy('setRenderTreeList'),
+ setShowWhitespace: jasmine.createSpy('setShowWhitespace'),
+ };
+ });
+
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ describe('tree view buttons', () => {
+ it('list view button dispatches setRenderTreeList with false', () => {
+ createComponent();
+
+ vm.find('.js-list-view').trigger('click');
+
+ expect(actions.setRenderTreeList).toHaveBeenCalledWith(jasmine.anything(), false, undefined);
+ });
+
+ it('tree view button dispatches setRenderTreeList with true', () => {
+ createComponent();
+
+ vm.find('.js-tree-view').trigger('click');
+
+ expect(actions.setRenderTreeList).toHaveBeenCalledWith(jasmine.anything(), true, undefined);
+ });
+
+ it('sets list button as active when renderTreeList is false', () => {
+ createComponent(store => {
+ Object.assign(store.state.diffs, {
+ renderTreeList: false,
+ });
+ });
+
+ expect(vm.find('.js-list-view').classes('active')).toBe(true);
+ expect(vm.find('.js-tree-view').classes('active')).toBe(false);
+ });
+
+ it('sets tree button as active when renderTreeList is true', () => {
+ createComponent(store => {
+ Object.assign(store.state.diffs, {
+ renderTreeList: true,
+ });
+ });
+
+ expect(vm.find('.js-list-view').classes('active')).toBe(false);
+ expect(vm.find('.js-tree-view').classes('active')).toBe(true);
+ });
+ });
+
+ describe('compare changes', () => {
+ it('sets inline button as active', () => {
+ createComponent(store => {
+ Object.assign(store.state.diffs, {
+ diffViewType: INLINE_DIFF_VIEW_TYPE,
+ });
+ });
+
+ expect(vm.find('.js-inline-diff-button').classes('active')).toBe(true);
+ expect(vm.find('.js-parallel-diff-button').classes('active')).toBe(false);
+ });
+
+ it('sets parallel button as active', () => {
+ createComponent(store => {
+ Object.assign(store.state.diffs, {
+ diffViewType: PARALLEL_DIFF_VIEW_TYPE,
+ });
+ });
+
+ expect(vm.find('.js-inline-diff-button').classes('active')).toBe(false);
+ expect(vm.find('.js-parallel-diff-button').classes('active')).toBe(true);
+ });
+
+ it('calls setInlineDiffViewType when clicking inline button', () => {
+ createComponent();
+
+ vm.find('.js-inline-diff-button').trigger('click');
+
+ expect(actions.setInlineDiffViewType).toHaveBeenCalled();
+ });
+
+ it('calls setParallelDiffViewType when clicking parallel button', () => {
+ createComponent();
+
+ vm.find('.js-parallel-diff-button').trigger('click');
+
+ expect(actions.setParallelDiffViewType).toHaveBeenCalled();
+ });
+ });
+
+ describe('whitespace toggle', () => {
+ it('does not set as checked when showWhitespace is false', () => {
+ createComponent(store => {
+ Object.assign(store.state.diffs, {
+ showWhitespace: false,
+ });
+ });
+
+ expect(vm.find('#show-whitespace').element.checked).toBe(false);
+ });
+
+ it('sets as checked when showWhitespace is true', () => {
+ createComponent(store => {
+ Object.assign(store.state.diffs, {
+ showWhitespace: true,
+ });
+ });
+
+ expect(vm.find('#show-whitespace').element.checked).toBe(true);
+ });
+
+ it('calls setShowWhitespace on change', () => {
+ createComponent();
+
+ const checkbox = vm.find('#show-whitespace');
+
+ checkbox.element.checked = true;
+ checkbox.trigger('change');
+
+ expect(actions.setShowWhitespace).toHaveBeenCalledWith(
+ jasmine.anything(),
+ {
+ showWhitespace: true,
+ pushState: true,
+ },
+ undefined,
+ );
+ });
+ });
+});
diff --git a/spec/javascripts/diffs/components/tree_list_spec.js b/spec/javascripts/diffs/components/tree_list_spec.js
index a0b380adfd6..cd7bf6405e5 100644
--- a/spec/javascripts/diffs/components/tree_list_spec.js
+++ b/spec/javascripts/diffs/components/tree_list_spec.js
@@ -26,19 +26,15 @@ describe('Diffs tree list component', () => {
store.state.diffs.removedLines = 20;
store.state.diffs.diffFiles.push('test');
- vm = mountComponentWithStore(Component, { store });
+ localStorage.removeItem('mr_diff_tree_list');
+
+ vm = mountComponentWithStore(Component, { store, props: { hideFileStats: false } });
});
afterEach(() => {
vm.$destroy();
});
- it('renders diff stats', () => {
- expect(vm.$el.textContent).toContain('1 changed file');
- expect(vm.$el.textContent).toContain('10 additions');
- expect(vm.$el.textContent).toContain('20 deletions');
- });
-
it('renders empty text', () => {
expect(vm.$el.textContent).toContain('No files found');
});
@@ -57,6 +53,7 @@ describe('Diffs tree list component', () => {
removedLines: 0,
tempFile: true,
type: 'blob',
+ parentPath: 'app',
},
app: {
key: 'app',
@@ -80,12 +77,11 @@ describe('Diffs tree list component', () => {
expect(vm.$el.querySelectorAll('.file-row')[1].textContent).toContain('app');
});
- it('filters tree list to blobs matching search', done => {
- vm.search = 'app/index';
+ it('hides file stats', done => {
+ vm.hideFileStats = true;
vm.$nextTick(() => {
- expect(vm.$el.querySelectorAll('.file-row').length).toBe(1);
- expect(vm.$el.querySelectorAll('.file-row')[0].textContent).toContain('index.js');
+ expect(vm.$el.querySelector('.file-row-stats')).toBe(null);
done();
});
@@ -108,7 +104,7 @@ describe('Diffs tree list component', () => {
});
it('renders as file list when renderTreeList is false', done => {
- vm.renderTreeList = false;
+ vm.$store.state.diffs.renderTreeList = false;
vm.$nextTick(() => {
expect(vm.$el.querySelectorAll('.file-row').length).toBe(1);
@@ -118,71 +114,13 @@ describe('Diffs tree list component', () => {
});
it('renders file paths when renderTreeList is false', done => {
- vm.renderTreeList = false;
+ vm.$store.state.diffs.renderTreeList = false;
vm.$nextTick(() => {
- expect(vm.$el.querySelector('.file-row').textContent).toContain('app/index.js');
+ expect(vm.$el.querySelector('.file-row').textContent).toContain('index.js');
done();
});
});
-
- it('hides render buttons when input is focused', done => {
- const focusEvent = new Event('focus');
-
- vm.$el.querySelector('.form-control').dispatchEvent(focusEvent);
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.tree-list-view-toggle').style.display).toBe('none');
-
- done();
- });
- });
-
- it('shows render buttons when input is blurred', done => {
- const blurEvent = new Event('blur');
- vm.focusSearch = true;
-
- vm.$nextTick()
- .then(() => {
- vm.$el.querySelector('.form-control').dispatchEvent(blurEvent);
- })
- .then(vm.$nextTick)
- .then(() => {
- expect(vm.$el.querySelector('.tree-list-view-toggle').style.display).not.toBe('none');
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('clearSearch', () => {
- it('resets search', () => {
- vm.search = 'test';
-
- vm.$el.querySelector('.tree-list-clear-icon').click();
-
- expect(vm.search).toBe('');
- });
- });
-
- describe('toggleRenderTreeList', () => {
- it('updates renderTreeList', () => {
- expect(vm.renderTreeList).toBe(true);
-
- vm.toggleRenderTreeList(false);
-
- expect(vm.renderTreeList).toBe(false);
- });
- });
-
- describe('toggleFocusSearch', () => {
- it('updates focusSearch', () => {
- expect(vm.focusSearch).toBe(false);
-
- vm.toggleFocusSearch(true);
-
- expect(vm.focusSearch).toBe(true);
- });
});
});
diff --git a/spec/javascripts/diffs/mock_data/diff_discussions.js b/spec/javascripts/diffs/mock_data/diff_discussions.js
index c1e9f791925..4a091b4580b 100644
--- a/spec/javascripts/diffs/mock_data/diff_discussions.js
+++ b/spec/javascripts/diffs/mock_data/diff_discussions.js
@@ -266,7 +266,7 @@ export default {
blob_name: 'CHANGELOG',
blob_icon: '<i aria-hidden="true" data-hidden="true" class="fa fa-file-text-o fa-fw"></i>',
file_hash: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a',
- file_path: 'CHANGELOG',
+ file_path: 'CHANGELOG.rb',
new_file: false,
deleted_file: false,
renamed_file: false,
@@ -286,7 +286,7 @@ export default {
content_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
stored_externally: null,
external_storage: null,
- old_path_html: ['CHANGELOG', 'CHANGELOG'],
+ old_path_html: 'CHANGELOG_OLD',
new_path_html: 'CHANGELOG',
context_lines_path:
'/gitlab-org/gitlab-test/blob/c48ee0d1bf3b30453f5b32250ce03134beaa6d13/CHANGELOG/diff',
@@ -485,6 +485,10 @@ export default {
},
},
],
+ viewer: {
+ name: 'text',
+ error: null,
+ },
},
diff_discussion: true,
truncated_diff_lines: [
diff --git a/spec/javascripts/diffs/mock_data/diff_file.js b/spec/javascripts/diffs/mock_data/diff_file.js
index 031c9842f2f..32af9ea8ddd 100644
--- a/spec/javascripts/diffs/mock_data/diff_file.js
+++ b/spec/javascripts/diffs/mock_data/diff_file.js
@@ -25,6 +25,8 @@ export default {
text: true,
viewer: {
name: 'text',
+ error: null,
+ collapsed: false,
},
added_lines: 2,
removed_lines: 0,
diff --git a/spec/javascripts/diffs/mock_data/merge_request_diffs.js b/spec/javascripts/diffs/mock_data/merge_request_diffs.js
index d72ad7818dd..4bbef146336 100644
--- a/spec/javascripts/diffs/mock_data/merge_request_diffs.js
+++ b/spec/javascripts/diffs/mock_data/merge_request_diffs.js
@@ -1,42 +1,46 @@
export default [
{
- versionIndex: 4,
- createdAt: '2018-10-23T11:49:16.611Z',
- commitsCount: 4,
+ base_version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37',
+ version_index: 4,
+ created_at: '2018-10-23T11:49:16.611Z',
+ commits_count: 4,
latest: true,
- shortCommitSha: 'de7a8f7f',
- versionPath: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37',
- comparePath:
+ short_commit_sha: 'de7a8f7f',
+ version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37',
+ compare_path:
'/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=de7a8f7f20c3ea2e0bef3ba01cfd41c21f6b4995',
},
{
- versionIndex: 3,
- createdAt: '2018-10-23T11:46:40.617Z',
- commitsCount: 3,
+ base_version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=36',
+ version_index: 3,
+ created_at: '2018-10-23T11:46:40.617Z',
+ commits_count: 3,
latest: false,
- shortCommitSha: 'e78fc18f',
- versionPath: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=36',
- comparePath:
+ short_commit_sha: 'e78fc18f',
+ version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=36',
+ compare_path:
'/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=e78fc18fa37acb2185c59ca94d4a964464feb50e',
},
{
- versionIndex: 2,
- createdAt: '2018-10-04T09:57:39.648Z',
- commitsCount: 2,
+ base_version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=35',
+ version_index: 2,
+ created_at: '2018-10-04T09:57:39.648Z',
+ commits_count: 2,
latest: false,
- shortCommitSha: '48da7e7e',
- versionPath: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=35',
- comparePath:
+ short_commit_sha: '48da7e7e',
+ version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=35',
+ compare_path:
'/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=48da7e7e9a99d41c852578bd9cb541ca4d864b3e',
},
{
- versionIndex: 1,
- createdAt: '2018-09-25T20:30:39.493Z',
- commitsCount: 1,
+ base_version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=20',
+ version_index: 1,
+ created_at: '2018-09-25T20:30:39.493Z',
+ commits_count: 1,
latest: false,
- shortCommitSha: '47bac2ed',
- versionPath: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=20',
- comparePath:
+ short_commit_sha: '47bac2ed',
+ version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=20',
+ compare_path:
'/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=47bac2ed972c5bee344c1cea159a22cd7f711dc0',
},
];
diff --git a/spec/javascripts/diffs/store/actions_spec.js b/spec/javascripts/diffs/store/actions_spec.js
index 033b5e86dbe..e47c7906fcb 100644
--- a/spec/javascripts/diffs/store/actions_spec.js
+++ b/spec/javascripts/diffs/store/actions_spec.js
@@ -27,6 +27,9 @@ import actions, {
scrollToFile,
toggleShowTreeList,
renderFileForDiscussionId,
+ setRenderTreeList,
+ setShowWhitespace,
+ setRenderIt,
} from '~/diffs/store/actions';
import eventHub from '~/notes/event_hub';
import * as types from '~/diffs/store/mutation_types';
@@ -97,9 +100,10 @@ describe('DiffsStoreActions', () => {
});
describe('setHighlightedRow', () => {
- it('should set lineHash and fileHash of highlightedRow', () => {
+ it('should mark currently selected diff and set lineHash and fileHash of highlightedRow', () => {
testAction(setHighlightedRow, 'ABC_123', {}, [
{ type: types.SET_HIGHLIGHTED_ROW, payload: 'ABC_123' },
+ { type: types.UPDATE_CURRENT_DIFF_FILE_ID, payload: 'ABC' },
]);
});
});
@@ -260,12 +264,16 @@ describe('DiffsStoreActions', () => {
{
id: 1,
renderIt: false,
- collapsed: false,
+ viewer: {
+ collapsed: false,
+ },
},
{
id: 2,
renderIt: false,
- collapsed: false,
+ viewer: {
+ collapsed: false,
+ },
},
],
};
@@ -706,22 +714,6 @@ describe('DiffsStoreActions', () => {
expect(commit).toHaveBeenCalledWith(types.UPDATE_CURRENT_DIFF_FILE_ID, 'test');
});
-
- it('resets currentDiffId after timeout', () => {
- const state = {
- treeEntries: {
- path: {
- fileHash: 'test',
- },
- },
- };
-
- scrollToFile({ state, commit }, 'path');
-
- jasmine.clock().tick(1000);
-
- expect(commit.calls.argsFor(1)).toEqual([types.UPDATE_CURRENT_DIFF_FILE_ID, '']);
- });
});
describe('toggleShowTreeList', () => {
@@ -764,7 +756,9 @@ describe('DiffsStoreActions', () => {
diffFiles: [
{
file_hash: 'HASH',
- collapsed,
+ viewer: {
+ collapsed,
+ },
renderIt,
},
],
@@ -796,4 +790,61 @@ describe('DiffsStoreActions', () => {
expect(scrollToElement).not.toHaveBeenCalled();
});
});
+
+ describe('setRenderTreeList', () => {
+ it('commits SET_RENDER_TREE_LIST', done => {
+ testAction(
+ setRenderTreeList,
+ true,
+ {},
+ [{ type: types.SET_RENDER_TREE_LIST, payload: true }],
+ [],
+ done,
+ );
+ });
+
+ it('sets localStorage', () => {
+ spyOn(localStorage, 'setItem').and.stub();
+
+ setRenderTreeList({ commit() {} }, true);
+
+ expect(localStorage.setItem).toHaveBeenCalledWith('mr_diff_tree_list', true);
+ });
+ });
+
+ describe('setShowWhitespace', () => {
+ it('commits SET_SHOW_WHITESPACE', done => {
+ testAction(
+ setShowWhitespace,
+ { showWhitespace: true },
+ {},
+ [{ type: types.SET_SHOW_WHITESPACE, payload: true }],
+ [],
+ done,
+ );
+ });
+
+ it('sets localStorage', () => {
+ spyOn(localStorage, 'setItem').and.stub();
+
+ setShowWhitespace({ commit() {} }, { showWhitespace: true });
+
+ expect(localStorage.setItem).toHaveBeenCalledWith('mr_show_whitespace', true);
+ });
+
+ it('calls history pushState', () => {
+ spyOn(localStorage, 'setItem').and.stub();
+ spyOn(window.history, 'pushState').and.stub();
+
+ setShowWhitespace({ commit() {} }, { showWhitespace: true, pushState: true });
+
+ expect(window.history.pushState).toHaveBeenCalled();
+ });
+ });
+
+ describe('setRenderIt', () => {
+ it('commits RENDER_FILE', done => {
+ testAction(setRenderIt, 'file', {}, [{ type: types.RENDER_FILE, payload: 'file' }], [], done);
+ });
+ });
});
diff --git a/spec/javascripts/diffs/store/getters_spec.js b/spec/javascripts/diffs/store/getters_spec.js
index 582535e0a53..eab5703dfb2 100644
--- a/spec/javascripts/diffs/store/getters_spec.js
+++ b/spec/javascripts/diffs/store/getters_spec.js
@@ -51,13 +51,13 @@ describe('Diffs Module Getters', () => {
describe('hasCollapsedFile', () => {
it('returns true when all files are collapsed', () => {
- localState.diffFiles = [{ collapsed: true }, { collapsed: true }];
+ localState.diffFiles = [{ viewer: { collapsed: true } }, { viewer: { collapsed: true } }];
expect(getters.hasCollapsedFile(localState)).toEqual(true);
});
it('returns true when at least one file is collapsed', () => {
- localState.diffFiles = [{ collapsed: false }, { collapsed: true }];
+ localState.diffFiles = [{ viewer: { collapsed: false } }, { viewer: { collapsed: true } }];
expect(getters.hasCollapsedFile(localState)).toEqual(true);
});
@@ -230,15 +230,34 @@ describe('Diffs Module Getters', () => {
localState.treeEntries = {
file: {
type: 'blob',
+ path: 'file',
+ parentPath: '/',
+ tree: [],
},
tree: {
type: 'tree',
+ path: 'tree',
+ parentPath: '/',
+ tree: [],
},
};
- expect(getters.allBlobs(localState)).toEqual([
+ expect(
+ getters.allBlobs(localState, {
+ flatBlobsList: getters.flatBlobsList(localState),
+ }),
+ ).toEqual([
{
- type: 'blob',
+ isHeader: true,
+ path: '/',
+ tree: [
+ {
+ parentPath: '/',
+ path: 'file',
+ tree: [],
+ type: 'blob',
+ },
+ ],
},
]);
});
@@ -251,4 +270,24 @@ describe('Diffs Module Getters', () => {
expect(getters.diffFilesLength(localState)).toBe(2);
});
});
+
+ describe('currentDiffIndex', () => {
+ it('returns index of currently selected diff in diffList', () => {
+ localState.diffFiles = [{ file_hash: '111' }, { file_hash: '222' }, { file_hash: '333' }];
+ localState.currentDiffFileId = '222';
+
+ expect(getters.currentDiffIndex(localState)).toEqual(1);
+
+ localState.currentDiffFileId = '333';
+
+ expect(getters.currentDiffIndex(localState)).toEqual(2);
+ });
+
+ it('returns 0 if no diff is selected yet or diff is not found', () => {
+ localState.diffFiles = [{ file_hash: '111' }, { file_hash: '222' }, { file_hash: '333' }];
+ localState.currentDiffFileId = '';
+
+ expect(getters.currentDiffIndex(localState)).toEqual(0);
+ });
+ });
});
diff --git a/spec/javascripts/diffs/store/mutations_spec.js b/spec/javascripts/diffs/store/mutations_spec.js
index d8733941181..09ee691b602 100644
--- a/spec/javascripts/diffs/store/mutations_spec.js
+++ b/spec/javascripts/diffs/store/mutations_spec.js
@@ -121,8 +121,14 @@ describe('DiffsStoreMutations', () => {
describe('ADD_COLLAPSED_DIFFS', () => {
it('should update the state with the given data for the given file hash', () => {
const fileHash = 123;
- const state = { diffFiles: [{}, { file_hash: fileHash, existing_field: 0 }] };
- const data = { diff_files: [{ file_hash: fileHash, extra_field: 1, existing_field: 1 }] };
+ const state = {
+ diffFiles: [{}, { file_hash: fileHash, existing_field: 0 }],
+ };
+ const data = {
+ diff_files: [
+ { file_hash: fileHash, extra_field: 1, existing_field: 1, viewer: { name: 'text' } },
+ ],
+ };
mutations[types.ADD_COLLAPSED_DIFFS](state, { file: state.diffFiles[1], data });
@@ -628,4 +634,50 @@ describe('DiffsStoreMutations', () => {
expect(file.parallel_diff_lines[1].right.hasForm).toBe(false);
});
});
+
+ describe('SET_TREE_DATA', () => {
+ it('sets treeEntries and tree in state', () => {
+ const state = {
+ treeEntries: {},
+ tree: [],
+ };
+
+ mutations[types.SET_TREE_DATA](state, {
+ treeEntries: { file: { name: 'index.js' } },
+ tree: ['tree'],
+ });
+
+ expect(state.treeEntries).toEqual({
+ file: {
+ name: 'index.js',
+ },
+ });
+
+ expect(state.tree).toEqual(['tree']);
+ });
+ });
+
+ describe('SET_RENDER_TREE_LIST', () => {
+ it('sets renderTreeList', () => {
+ const state = {
+ renderTreeList: true,
+ };
+
+ mutations[types.SET_RENDER_TREE_LIST](state, false);
+
+ expect(state.renderTreeList).toBe(false);
+ });
+ });
+
+ describe('SET_SHOW_WHITESPACE', () => {
+ it('sets showWhitespace', () => {
+ const state = {
+ showWhitespace: true,
+ };
+
+ mutations[types.SET_SHOW_WHITESPACE](state, false);
+
+ expect(state.showWhitespace).toBe(false);
+ });
+ });
});
diff --git a/spec/javascripts/diffs/store/utils_spec.js b/spec/javascripts/diffs/store/utils_spec.js
index 4268634d302..599ea9cd420 100644
--- a/spec/javascripts/diffs/store/utils_spec.js
+++ b/spec/javascripts/diffs/store/utils_spec.js
@@ -14,7 +14,7 @@ import { MERGE_REQUEST_NOTEABLE_TYPE } from '~/notes/constants';
import diffFileMockData from '../mock_data/diff_file';
import { noteableDataMock } from '../../notes/mock_data';
-const getDiffFileMock = () => Object.assign({}, diffFileMockData);
+const getDiffFileMock = () => JSON.parse(JSON.stringify(diffFileMockData));
describe('DiffsStoreUtils', () => {
describe('findDiffFile', () => {
@@ -80,30 +80,44 @@ describe('DiffsStoreUtils', () => {
});
describe('addContextLines', () => {
- it('should add context lines properly with bottom parameter', () => {
+ it('should add context lines', () => {
const diffFile = getDiffFileMock();
const inlineLines = diffFile.highlighted_diff_lines;
const parallelLines = diffFile.parallel_diff_lines;
const lineNumbers = { oldLineNumber: 3, newLineNumber: 5 };
- const contextLines = [{ lineNumber: 42 }];
- const options = { inlineLines, parallelLines, contextLines, lineNumbers, bottom: true };
+ const contextLines = [{ lineNumber: 42, line_code: '123' }];
+ const options = { inlineLines, parallelLines, contextLines, lineNumbers };
const inlineIndex = utils.findIndexInInlineLines(inlineLines, lineNumbers);
const parallelIndex = utils.findIndexInParallelLines(parallelLines, lineNumbers);
const normalizedParallelLine = {
left: options.contextLines[0],
right: options.contextLines[0],
+ line_code: '123',
};
utils.addContextLines(options);
- expect(inlineLines[inlineLines.length - 1]).toEqual(contextLines[0]);
- expect(parallelLines[parallelLines.length - 1]).toEqual(normalizedParallelLine);
+ expect(inlineLines[inlineIndex]).toEqual(contextLines[0]);
+ expect(parallelLines[parallelIndex]).toEqual(normalizedParallelLine);
+ });
+
+ it('should add context lines properly with bottom parameter', () => {
+ const diffFile = getDiffFileMock();
+ const inlineLines = diffFile.highlighted_diff_lines;
+ const parallelLines = diffFile.parallel_diff_lines;
+ const lineNumbers = { oldLineNumber: 3, newLineNumber: 5 };
+ const contextLines = [{ lineNumber: 42, line_code: '123' }];
+ const options = { inlineLines, parallelLines, contextLines, lineNumbers, bottom: true };
+ const normalizedParallelLine = {
+ left: options.contextLines[0],
+ right: options.contextLines[0],
+ line_code: '123',
+ };
- delete options.bottom;
utils.addContextLines(options);
- expect(inlineLines[inlineIndex]).toEqual(contextLines[0]);
- expect(parallelLines[parallelIndex]).toEqual(normalizedParallelLine);
+ expect(inlineLines[inlineLines.length - 1]).toEqual(contextLines[0]);
+ expect(parallelLines[parallelLines.length - 1]).toEqual(normalizedParallelLine);
});
});
@@ -251,45 +265,40 @@ describe('DiffsStoreUtils', () => {
describe('trimFirstCharOfLineContent', () => {
it('trims the line when it starts with a space', () => {
expect(utils.trimFirstCharOfLineContent({ rich_text: ' diff' })).toEqual({
- discussions: [],
rich_text: 'diff',
});
});
it('trims the line when it starts with a +', () => {
expect(utils.trimFirstCharOfLineContent({ rich_text: '+diff' })).toEqual({
- discussions: [],
rich_text: 'diff',
});
});
it('trims the line when it starts with a -', () => {
expect(utils.trimFirstCharOfLineContent({ rich_text: '-diff' })).toEqual({
- discussions: [],
rich_text: 'diff',
});
});
it('does not trims the line when it starts with a letter', () => {
expect(utils.trimFirstCharOfLineContent({ rich_text: 'diff' })).toEqual({
- discussions: [],
rich_text: 'diff',
});
});
it('does not modify the provided object', () => {
const lineObj = {
- discussions: [],
rich_text: ' diff',
};
utils.trimFirstCharOfLineContent(lineObj);
- expect(lineObj).toEqual({ discussions: [], rich_text: ' diff' });
+ expect(lineObj).toEqual({ rich_text: ' diff' });
});
it('handles a undefined or null parameter', () => {
- expect(utils.trimFirstCharOfLineContent()).toEqual({ discussions: [] });
+ expect(utils.trimFirstCharOfLineContent()).toEqual({});
});
});
@@ -502,6 +511,7 @@ describe('DiffsStoreUtils', () => {
fileHash: 'test',
key: 'app/index.js',
name: 'index.js',
+ parentPath: 'app/',
path: 'app/index.js',
removedLines: 10,
tempFile: false,
@@ -522,6 +532,7 @@ describe('DiffsStoreUtils', () => {
fileHash: 'test',
key: 'app/test/index.js',
name: 'index.js',
+ parentPath: 'app/test/',
path: 'app/test/index.js',
removedLines: 0,
tempFile: true,
@@ -535,6 +546,7 @@ describe('DiffsStoreUtils', () => {
fileHash: 'test',
key: 'app/test/filepathneedstruncating.js',
name: 'filepathneedstruncating.js',
+ parentPath: 'app/test/',
path: 'app/test/filepathneedstruncating.js',
removedLines: 0,
tempFile: true,
@@ -548,6 +560,7 @@ describe('DiffsStoreUtils', () => {
},
{
key: 'package.json',
+ parentPath: '/',
path: 'package.json',
name: 'package.json',
type: 'blob',
@@ -588,7 +601,7 @@ describe('DiffsStoreUtils', () => {
it('returns mode_changed if key has no match', () => {
expect(
utils.getDiffMode({
- mode_changed: true,
+ viewer: { name: 'mode_changed' },
}),
).toBe('mode_changed');
});
@@ -597,4 +610,175 @@ describe('DiffsStoreUtils', () => {
expect(utils.getDiffMode({})).toBe('replaced');
});
});
+
+ describe('getLowestSingleFolder', () => {
+ it('returns path and tree of lowest single folder tree', () => {
+ const folder = {
+ name: 'app',
+ type: 'tree',
+ tree: [
+ {
+ name: 'javascripts',
+ type: 'tree',
+ tree: [
+ {
+ type: 'blob',
+ name: 'index.js',
+ },
+ ],
+ },
+ ],
+ };
+ const { path, treeAcc } = utils.getLowestSingleFolder(folder);
+
+ expect(path).toEqual('app/javascripts');
+ expect(treeAcc).toEqual([
+ {
+ type: 'blob',
+ name: 'index.js',
+ },
+ ]);
+ });
+
+ it('returns passed in folders path & tree when more than tree exists', () => {
+ const folder = {
+ name: 'app',
+ type: 'tree',
+ tree: [
+ {
+ name: 'spec',
+ type: 'blob',
+ tree: [],
+ },
+ ],
+ };
+ const { path, treeAcc } = utils.getLowestSingleFolder(folder);
+
+ expect(path).toEqual('app');
+ expect(treeAcc).toBeNull();
+ });
+ });
+
+ describe('flattenTree', () => {
+ it('returns flattened directory structure', () => {
+ const tree = [
+ {
+ type: 'tree',
+ name: 'app',
+ tree: [
+ {
+ type: 'tree',
+ name: 'javascripts',
+ tree: [
+ {
+ type: 'blob',
+ name: 'index.js',
+ tree: [],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ type: 'tree',
+ name: 'ee',
+ tree: [
+ {
+ type: 'tree',
+ name: 'lib',
+ tree: [
+ {
+ type: 'tree',
+ name: 'ee',
+ tree: [
+ {
+ type: 'tree',
+ name: 'gitlab',
+ tree: [
+ {
+ type: 'tree',
+ name: 'checks',
+ tree: [
+ {
+ type: 'tree',
+ name: 'longtreenametomakepath',
+ tree: [
+ {
+ type: 'blob',
+ name: 'diff_check.rb',
+ tree: [],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ type: 'tree',
+ name: 'spec',
+ tree: [
+ {
+ type: 'tree',
+ name: 'javascripts',
+ tree: [],
+ },
+ {
+ type: 'blob',
+ name: 'index_spec.js',
+ tree: [],
+ },
+ ],
+ },
+ ];
+ const flattened = utils.flattenTree(tree);
+
+ expect(flattened).toEqual([
+ {
+ type: 'tree',
+ name: 'app/javascripts',
+ tree: [
+ {
+ type: 'blob',
+ name: 'index.js',
+ tree: [],
+ },
+ ],
+ },
+ {
+ type: 'tree',
+ name: 'ee/lib/…/…/…/longtreenametomakepath',
+ tree: [
+ {
+ name: 'diff_check.rb',
+ tree: [],
+ type: 'blob',
+ },
+ ],
+ },
+ {
+ type: 'tree',
+ name: 'spec',
+ tree: [
+ {
+ type: 'tree',
+ name: 'javascripts',
+ tree: [],
+ },
+ {
+ type: 'blob',
+ name: 'index_spec.js',
+ tree: [],
+ },
+ ],
+ },
+ ]);
+ });
+ });
});
diff --git a/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js b/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js
index 08ffc44605f..47be0b3ce9d 100644
--- a/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js
+++ b/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js
@@ -1,5 +1,5 @@
import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
-import { setInput, createForm } from './helper';
+import { setInputValue, createForm } from './helper';
describe('DirtySubmitCollection', () => {
it('disables submits until there are changes', done => {
@@ -14,11 +14,11 @@ describe('DirtySubmitCollection', () => {
expect(submit.disabled).toBe(true);
- return setInput(input, `${originalValue} changes`)
+ return setInputValue(input, `${originalValue} changes`)
.then(() => {
expect(submit.disabled).toBe(false);
})
- .then(() => setInput(input, originalValue))
+ .then(() => setInputValue(input, originalValue))
.then(() => {
expect(submit.disabled).toBe(true);
})
diff --git a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
index 093fec97951..95cc90dcb0f 100644
--- a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
+++ b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
@@ -1,18 +1,20 @@
import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
-import { setInput, createForm } from './helper';
+import { getInputValue, setInputValue, createForm } from './helper';
function expectToToggleDisableOnDirtyUpdate(submit, input) {
- const originalValue = input.value;
+ const originalValue = getInputValue(input);
expect(submit.disabled).toBe(true);
- return setInput(input, `${originalValue} changes`)
+ return setInputValue(input, `${originalValue} changes`)
.then(() => expect(submit.disabled).toBe(false))
- .then(() => setInput(input, originalValue))
+ .then(() => setInputValue(input, originalValue))
.then(() => expect(submit.disabled).toBe(true));
}
describe('DirtySubmitForm', () => {
+ DirtySubmitForm.THROTTLE_DURATION = 0;
+
it('disables submit until there are changes', done => {
const { form, input, submit } = createForm();
@@ -33,4 +35,24 @@ describe('DirtySubmitForm', () => {
.then(done)
.catch(done.fail);
});
+
+ it('disables submit until there are changes for radio inputs', done => {
+ const { form, input, submit } = createForm('radio');
+
+ new DirtySubmitForm(form); // eslint-disable-line no-new
+
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('disables submit until there are changes for checkbox inputs', done => {
+ const { form, input, submit } = createForm('checkbox');
+
+ new DirtySubmitForm(form); // eslint-disable-line no-new
+
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
+ .then(done)
+ .catch(done.fail);
+ });
});
diff --git a/spec/javascripts/dirty_submit/helper.js b/spec/javascripts/dirty_submit/helper.js
index 6d1e643553c..b51783cb915 100644
--- a/spec/javascripts/dirty_submit/helper.js
+++ b/spec/javascripts/dirty_submit/helper.js
@@ -1,25 +1,42 @@
import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
import setTimeoutPromiseHelper from '../helpers/set_timeout_promise_helper';
-export function setInput(element, value) {
- element.value = value;
+function isCheckableType(type) {
+ return /^(radio|checkbox)$/.test(type);
+}
+
+export function setInputValue(element, value) {
+ const { type } = element;
+ let eventType;
+
+ if (isCheckableType(type)) {
+ element.checked = !element.checked;
+ eventType = 'change';
+ } else {
+ element.value = value;
+ eventType = 'input';
+ }
element.dispatchEvent(
- new Event('input', {
+ new Event(eventType, {
bubbles: true,
- cancelable: true,
}),
);
return setTimeoutPromiseHelper(DirtySubmitForm.THROTTLE_DURATION);
}
-export function createForm() {
+export function getInputValue(input) {
+ return isCheckableType(input.type) ? input.checked : input.value;
+}
+
+export function createForm(type = 'text') {
const form = document.createElement('form');
form.innerHTML = `
- <input type="text" value="original" class="js-input" name="input" />
+ <input type="${type}" name="${type}" class="js-input"/>
<button type="submit" class="js-dirty-submit"></button>
`;
+
const input = form.querySelector('.js-input');
const submit = form.querySelector('.js-dirty-submit');
diff --git a/spec/javascripts/emoji_spec.js b/spec/javascripts/emoji_spec.js
index 3db4d9800f1..0ac375145be 100644
--- a/spec/javascripts/emoji_spec.js
+++ b/spec/javascripts/emoji_spec.js
@@ -1,4 +1,6 @@
-import { glEmojiTag } from '~/emoji';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import { initEmojiMap, glEmojiTag, EMOJI_VERSION } from '~/emoji';
import isEmojiUnicodeSupported, {
isFlagEmoji,
isRainbowFlagEmoji,
@@ -7,6 +9,7 @@ import isEmojiUnicodeSupported, {
isHorceRacingSkinToneComboEmoji,
isPersonZwjEmoji,
} from '~/emoji/support/is_emoji_unicode_supported';
+import installGlEmojiElement from '~/behaviors/gl_emoji';
const emptySupportMap = {
personZwj: false,
@@ -31,34 +34,35 @@ const emojiFixtureMap = {
bomb: {
name: 'bomb',
moji: '💣',
- unicodeVersion: '6.0',
+ uni: '6.0',
},
construction_worker_tone5: {
name: 'construction_worker_tone5',
moji: '👷ðŸ¿',
- unicodeVersion: '8.0',
+ uni: '8.0',
},
five: {
name: 'five',
moji: '5ï¸âƒ£',
- unicodeVersion: '3.0',
+ uni: '3.0',
},
grey_question: {
name: 'grey_question',
moji: 'â”',
- unicodeVersion: '6.0',
+ uni: '6.0',
},
};
function markupToDomElement(markup) {
const div = document.createElement('div');
div.innerHTML = markup;
+ document.body.appendChild(div);
return div.firstElementChild;
}
-function testGlEmojiImageFallback(element, name, src) {
+function testGlEmojiImageFallback(element, name) {
expect(element.tagName.toLowerCase()).toBe('img');
- expect(element.getAttribute('src')).toBe(src);
+ expect(element.getAttribute('src')).toBe(`/-/emojis/${EMOJI_VERSION}/${name}.png`);
expect(element.getAttribute('title')).toBe(`:${name}:`);
expect(element.getAttribute('alt')).toBe(`:${name}:`);
}
@@ -68,12 +72,11 @@ const defaults = {
sprite: false,
};
-function testGlEmojiElement(element, name, unicodeVersion, unicodeMoji, options = {}) {
+function testGlEmojiElement(element, name, uni, unicodeMoji, options = {}) {
const opts = Object.assign({}, defaults, options);
expect(element.tagName.toLowerCase()).toBe('gl-emoji');
expect(element.dataset.name).toBe(name);
- expect(element.dataset.fallbackSrc.length).toBeGreaterThan(0);
- expect(element.dataset.unicodeVersion).toBe(unicodeVersion);
+ expect(element.dataset.uni).toBe(uni);
const fallbackSpriteClass = `emoji-${name}`;
if (opts.sprite) {
@@ -86,7 +89,7 @@ function testGlEmojiElement(element, name, unicodeVersion, unicodeMoji, options
if (opts.forceFallback && !opts.sprite) {
// Check for image fallback
- testGlEmojiImageFallback(element.firstElementChild, name, element.dataset.fallbackSrc);
+ testGlEmojiImageFallback(element.firstElementChild, name);
} else {
// Otherwise make sure things are still unicode text
expect(element.textContent.trim()).toBe(unicodeMoji);
@@ -94,101 +97,143 @@ function testGlEmojiElement(element, name, unicodeVersion, unicodeMoji, options
}
describe('gl_emoji', () => {
+ beforeAll(() => {
+ installGlEmojiElement();
+ });
+
+ let mock;
+ const emojiData = getJSONFixture('emojis/emojis.json');
+
+ beforeEach(function(done) {
+ mock = new MockAdapter(axios);
+ mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, emojiData);
+
+ initEmojiMap()
+ .then(() => {
+ done();
+ })
+ .catch(() => {
+ done();
+ });
+ });
+
+ afterEach(function() {
+ mock.restore();
+ });
+
describe('glEmojiTag', () => {
- it('bomb emoji', () => {
+ it('bomb emoji', done => {
const emojiKey = 'bomb';
const markup = glEmojiTag(emojiFixtureMap[emojiKey].name);
const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- );
+ setTimeout(() => {
+ testGlEmojiElement(
+ glEmojiElement,
+ emojiFixtureMap[emojiKey].name,
+ emojiFixtureMap[emojiKey].uni,
+ emojiFixtureMap[emojiKey].moji,
+ );
+ done();
+ });
});
- it('bomb emoji with image fallback', () => {
+ it('bomb emoji with image fallback', done => {
const emojiKey = 'bomb';
const markup = glEmojiTag(emojiFixtureMap[emojiKey].name, {
forceFallback: true,
});
const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- {
- forceFallback: true,
- },
- );
+ setTimeout(() => {
+ testGlEmojiElement(
+ glEmojiElement,
+ emojiFixtureMap[emojiKey].name,
+ emojiFixtureMap[emojiKey].uni,
+ emojiFixtureMap[emojiKey].moji,
+ {
+ forceFallback: true,
+ },
+ );
+ done();
+ });
});
- it('bomb emoji with sprite fallback readiness', () => {
+ it('bomb emoji with sprite fallback readiness', done => {
const emojiKey = 'bomb';
const markup = glEmojiTag(emojiFixtureMap[emojiKey].name, {
sprite: true,
});
const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- {
- sprite: true,
- },
- );
+ setTimeout(() => {
+ testGlEmojiElement(
+ glEmojiElement,
+ emojiFixtureMap[emojiKey].name,
+ emojiFixtureMap[emojiKey].uni,
+ emojiFixtureMap[emojiKey].moji,
+ {
+ sprite: true,
+ },
+ );
+ done();
+ });
});
- it('bomb emoji with sprite fallback', () => {
+ it('bomb emoji with sprite fallback', done => {
const emojiKey = 'bomb';
const markup = glEmojiTag(emojiFixtureMap[emojiKey].name, {
forceFallback: true,
sprite: true,
});
const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- {
- forceFallback: true,
- sprite: true,
- },
- );
+ setTimeout(() => {
+ testGlEmojiElement(
+ glEmojiElement,
+ emojiFixtureMap[emojiKey].name,
+ emojiFixtureMap[emojiKey].uni,
+ emojiFixtureMap[emojiKey].moji,
+ {
+ forceFallback: true,
+ sprite: true,
+ },
+ );
+ done();
+ });
});
- it('question mark when invalid emoji name given', () => {
+ it('question mark when invalid emoji name given', done => {
const name = 'invalid_emoji';
const emojiKey = 'grey_question';
const markup = glEmojiTag(name);
const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- );
+ setTimeout(() => {
+ testGlEmojiElement(
+ glEmojiElement,
+ emojiFixtureMap[emojiKey].name,
+ emojiFixtureMap[emojiKey].uni,
+ emojiFixtureMap[emojiKey].moji,
+ );
+ done();
+ });
});
- it('question mark with image fallback when invalid emoji name given', () => {
+ it('question mark with image fallback when invalid emoji name given', done => {
const name = 'invalid_emoji';
const emojiKey = 'grey_question';
const markup = glEmojiTag(name, {
forceFallback: true,
});
const glEmojiElement = markupToDomElement(markup);
- testGlEmojiElement(
- glEmojiElement,
- emojiFixtureMap[emojiKey].name,
- emojiFixtureMap[emojiKey].unicodeVersion,
- emojiFixtureMap[emojiKey].moji,
- {
- forceFallback: true,
- },
- );
+ setTimeout(() => {
+ testGlEmojiElement(
+ glEmojiElement,
+ emojiFixtureMap[emojiKey].name,
+ emojiFixtureMap[emojiKey].uni,
+ emojiFixtureMap[emojiKey].moji,
+ {
+ forceFallback: true,
+ },
+ );
+ done();
+ });
});
});
@@ -389,7 +434,7 @@ describe('gl_emoji', () => {
const isSupported = isEmojiUnicodeSupported(
unicodeSupportMap,
emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
+ emojiFixtureMap[emojiKey].uni,
);
expect(isSupported).toBeTruthy();
@@ -401,7 +446,7 @@ describe('gl_emoji', () => {
const isSupported = isEmojiUnicodeSupported(
unicodeSupportMap,
emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
+ emojiFixtureMap[emojiKey].uni,
);
expect(isSupported).toBeFalsy();
@@ -415,7 +460,7 @@ describe('gl_emoji', () => {
const isSupported = isEmojiUnicodeSupported(
unicodeSupportMap,
emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
+ emojiFixtureMap[emojiKey].uni,
);
expect(isSupported).toBeFalsy();
@@ -441,7 +486,7 @@ describe('gl_emoji', () => {
const isSupported = isEmojiUnicodeSupported(
unicodeSupportMap,
emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
+ emojiFixtureMap[emojiKey].uni,
);
expect(isSupported).toBeFalsy();
@@ -459,7 +504,7 @@ describe('gl_emoji', () => {
const isSupported = isEmojiUnicodeSupported(
unicodeSupportMap,
emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
+ emojiFixtureMap[emojiKey].uni,
);
expect(isSupported).toBeTruthy();
@@ -477,7 +522,7 @@ describe('gl_emoji', () => {
const isSupported = isEmojiUnicodeSupported(
unicodeSupportMap,
emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
+ emojiFixtureMap[emojiKey].uni,
);
expect(isSupported).toBeFalsy();
diff --git a/spec/javascripts/environments/confirm_rollback_modal_spec.js b/spec/javascripts/environments/confirm_rollback_modal_spec.js
new file mode 100644
index 00000000000..05715bce38f
--- /dev/null
+++ b/spec/javascripts/environments/confirm_rollback_modal_spec.js
@@ -0,0 +1,70 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlModal } from '@gitlab/ui';
+import ConfirmRollbackModal from '~/environments/components/confirm_rollback_modal.vue';
+import eventHub from '~/environments/event_hub';
+
+describe('Confirm Rollback Modal Component', () => {
+ let environment;
+
+ beforeEach(() => {
+ environment = {
+ name: 'test',
+ last_deployment: {
+ commit: {
+ short_id: 'abc0123',
+ },
+ },
+ modalId: 'test',
+ };
+ });
+
+ it('should show "Rollback" when isLastDeployment is false', () => {
+ const component = shallowMount(ConfirmRollbackModal, {
+ propsData: {
+ environment: {
+ ...environment,
+ isLastDeployment: false,
+ },
+ },
+ });
+ const modal = component.find(GlModal);
+
+ expect(modal.attributes('title')).toContain('Rollback');
+ expect(modal.attributes('title')).toContain('test');
+ expect(modal.attributes('ok-title')).toBe('Rollback');
+ expect(modal.text()).toContain('commit abc0123');
+ expect(modal.text()).toContain('Are you sure you want to continue?');
+ });
+
+ it('should show "Re-deploy" when isLastDeployment is true', () => {
+ const component = shallowMount(ConfirmRollbackModal, {
+ propsData: {
+ environment: {
+ ...environment,
+ isLastDeployment: true,
+ },
+ },
+ });
+ const modal = component.find(GlModal);
+
+ expect(modal.attributes('title')).toContain('Re-deploy');
+ expect(modal.attributes('title')).toContain('test');
+ expect(modal.attributes('ok-title')).toBe('Re-deploy');
+ expect(modal.text()).toContain('commit abc0123');
+ expect(modal.text()).toContain('Are you sure you want to continue?');
+ });
+
+ it('should emit the "rollback" event when "ok" is clicked', () => {
+ environment = { ...environment, isLastDeployment: true };
+ const component = shallowMount(ConfirmRollbackModal, {
+ propsData: {
+ environment,
+ },
+ });
+ const eventHubSpy = spyOn(eventHub, '$emit');
+ const modal = component.find(GlModal);
+ modal.vm.$emit('ok');
+
+ expect(eventHubSpy).toHaveBeenCalledWith('rollbackEnvironment', environment);
+ });
+});
diff --git a/spec/javascripts/environments/environment_item_spec.js b/spec/javascripts/environments/environment_item_spec.js
index 7618c2f50ce..a89e50045da 100644
--- a/spec/javascripts/environments/environment_item_spec.js
+++ b/spec/javascripts/environments/environment_item_spec.js
@@ -25,7 +25,6 @@ describe('Environment item', () => {
component = new EnvironmentItem({
propsData: {
model: mockItem,
- canCreateDeployment: false,
canReadEnvironment: true,
service: {},
},
@@ -117,7 +116,6 @@ describe('Environment item', () => {
component = new EnvironmentItem({
propsData: {
model: environment,
- canCreateDeployment: true,
canReadEnvironment: true,
service: {},
},
diff --git a/spec/javascripts/environments/environment_rollback_spec.js b/spec/javascripts/environments/environment_rollback_spec.js
index 79f33c5bc8a..8c47f6a12c0 100644
--- a/spec/javascripts/environments/environment_rollback_spec.js
+++ b/spec/javascripts/environments/environment_rollback_spec.js
@@ -1,8 +1,11 @@
import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
+import eventHub from '~/environments/event_hub';
import rollbackComp from '~/environments/components/environment_rollback.vue';
describe('Rollback Component', () => {
- const retryURL = 'https://gitlab.com/retry';
+ const retryUrl = 'https://gitlab.com/retry';
let RollbackComponent;
beforeEach(() => {
@@ -13,8 +16,9 @@ describe('Rollback Component', () => {
const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'),
propsData: {
- retryUrl: retryURL,
+ retryUrl,
isLastDeployment: true,
+ environment: {},
},
}).$mount();
@@ -25,11 +29,33 @@ describe('Rollback Component', () => {
const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'),
propsData: {
- retryUrl: retryURL,
+ retryUrl,
isLastDeployment: false,
+ environment: {},
},
}).$mount();
expect(component.$el).toHaveSpriteIcon('redo');
});
+
+ it('should emit a "rollback" event on button click', () => {
+ const eventHubSpy = spyOn(eventHub, '$emit');
+ const component = shallowMount(RollbackComponent, {
+ propsData: {
+ retryUrl,
+ environment: {
+ name: 'test',
+ },
+ },
+ });
+ const button = component.find(GlButton);
+
+ button.vm.$emit('click');
+
+ expect(eventHubSpy).toHaveBeenCalledWith('requestRollbackEnvironment', {
+ retryUrl,
+ isLastDeployment: true,
+ name: 'test',
+ });
+ });
});
diff --git a/spec/javascripts/environments/environment_table_spec.js b/spec/javascripts/environments/environment_table_spec.js
index 0e5e50a59a5..ecd28594873 100644
--- a/spec/javascripts/environments/environment_table_spec.js
+++ b/spec/javascripts/environments/environment_table_spec.js
@@ -26,10 +26,229 @@ describe('Environment table', () => {
vm = mountComponent(Component, {
environments: [mockItem],
- canCreateDeployment: false,
canReadEnvironment: true,
});
expect(vm.$el.getAttribute('class')).toContain('ci-table');
});
+
+ describe('sortEnvironments', () => {
+ it('should sort environments by last updated', () => {
+ const mockItems = [
+ {
+ name: 'old',
+ size: 3,
+ isFolder: false,
+ last_deployment: {
+ created_at: new Date(2019, 0, 5).toISOString(),
+ },
+ },
+ {
+ name: 'new',
+ size: 3,
+ isFolder: false,
+ last_deployment: {
+ created_at: new Date(2019, 1, 5).toISOString(),
+ },
+ },
+ {
+ name: 'older',
+ size: 3,
+ isFolder: false,
+ last_deployment: {
+ created_at: new Date(2018, 0, 5).toISOString(),
+ },
+ },
+ {
+ name: 'an environment with no deployment',
+ },
+ ];
+
+ vm = mountComponent(Component, {
+ environments: mockItems,
+ canReadEnvironment: true,
+ });
+
+ const [old, newer, older, noDeploy] = mockItems;
+
+ expect(vm.sortEnvironments(mockItems)).toEqual([newer, old, older, noDeploy]);
+ });
+
+ it('should push environments with no deployments to the bottom', () => {
+ const mockItems = [
+ {
+ name: 'production',
+ size: 1,
+ id: 2,
+ state: 'available',
+ external_url: 'https://google.com/production',
+ environment_type: null,
+ last_deployment: null,
+ has_stop_action: false,
+ environment_path: '/Commit451/lab-coat/environments/2',
+ stop_path: '/Commit451/lab-coat/environments/2/stop',
+ folder_path: '/Commit451/lab-coat/environments/folders/production',
+ created_at: '2019-01-17T16:26:10.064Z',
+ updated_at: '2019-01-17T16:27:37.717Z',
+ can_stop: true,
+ },
+ {
+ name: 'review/225addcibuildstatus',
+ size: 2,
+ isFolder: true,
+ isLoadingFolderContent: false,
+ folderName: 'review',
+ isOpen: false,
+ children: [],
+ id: 12,
+ state: 'available',
+ external_url: 'https://google.com/review/225addcibuildstatus',
+ environment_type: 'review',
+ last_deployment: null,
+ has_stop_action: false,
+ environment_path: '/Commit451/lab-coat/environments/12',
+ stop_path: '/Commit451/lab-coat/environments/12/stop',
+ folder_path: '/Commit451/lab-coat/environments/folders/review',
+ created_at: '2019-01-17T16:27:37.877Z',
+ updated_at: '2019-01-17T16:27:37.883Z',
+ can_stop: true,
+ },
+ {
+ name: 'staging',
+ size: 1,
+ id: 1,
+ state: 'available',
+ external_url: 'https://google.com/staging',
+ environment_type: null,
+ last_deployment: {
+ created_at: '2019-01-17T16:26:15.125Z',
+ scheduled_actions: [],
+ },
+ },
+ ];
+
+ vm = mountComponent(Component, {
+ environments: mockItems,
+ canReadEnvironment: true,
+ });
+
+ const [prod, review, staging] = mockItems;
+
+ expect(vm.sortEnvironments(mockItems)).toEqual([review, staging, prod]);
+ });
+
+ it('should sort environments by folder first', () => {
+ const mockItems = [
+ {
+ name: 'old',
+ size: 3,
+ isFolder: false,
+ last_deployment: {
+ created_at: new Date(2019, 0, 5).toISOString(),
+ },
+ },
+ {
+ name: 'new',
+ size: 3,
+ isFolder: false,
+ last_deployment: {
+ created_at: new Date(2019, 1, 5).toISOString(),
+ },
+ },
+ {
+ name: 'older',
+ size: 3,
+ isFolder: true,
+ children: [],
+ },
+ ];
+
+ vm = mountComponent(Component, {
+ environments: mockItems,
+ canReadEnvironment: true,
+ });
+
+ const [old, newer, older] = mockItems;
+
+ expect(vm.sortEnvironments(mockItems)).toEqual([older, newer, old]);
+ });
+
+ it('should break ties by name', () => {
+ const mockItems = [
+ {
+ name: 'old',
+ isFolder: false,
+ },
+ {
+ name: 'new',
+ isFolder: false,
+ },
+ {
+ folderName: 'older',
+ isFolder: true,
+ },
+ ];
+
+ vm = mountComponent(Component, {
+ environments: mockItems,
+ canReadEnvironment: true,
+ });
+
+ const [old, newer, older] = mockItems;
+
+ expect(vm.sortEnvironments(mockItems)).toEqual([older, newer, old]);
+ });
+ });
+
+ describe('sortedEnvironments', () => {
+ it('it should sort children as well', () => {
+ const mockItems = [
+ {
+ name: 'production',
+ last_deployment: null,
+ },
+ {
+ name: 'review/225addcibuildstatus',
+ isFolder: true,
+ folderName: 'review',
+ isOpen: true,
+ children: [
+ {
+ name: 'review/225addcibuildstatus',
+ last_deployment: {
+ created_at: '2019-01-17T16:26:15.125Z',
+ },
+ },
+ {
+ name: 'review/master',
+ last_deployment: {
+ created_at: '2019-02-17T16:26:15.125Z',
+ },
+ },
+ ],
+ },
+ {
+ name: 'staging',
+ last_deployment: {
+ created_at: '2019-01-17T16:26:15.125Z',
+ },
+ },
+ ];
+ const [production, review, staging] = mockItems;
+ const [addcibuildstatus, master] = mockItems[1].children;
+
+ vm = mountComponent(Component, {
+ environments: mockItems,
+ canReadEnvironment: true,
+ });
+
+ expect(vm.sortedEnvironments.map(env => env.name)).toEqual([
+ review.name,
+ staging.name,
+ production.name,
+ ]);
+
+ expect(vm.sortedEnvironments[0].children).toEqual([master, addcibuildstatus]);
+ });
+ });
});
diff --git a/spec/javascripts/environments/environments_app_spec.js b/spec/javascripts/environments/environments_app_spec.js
index e2d81eb454a..b6a244f7cd3 100644
--- a/spec/javascripts/environments/environments_app_spec.js
+++ b/spec/javascripts/environments/environments_app_spec.js
@@ -9,7 +9,6 @@ describe('Environment', () => {
const mockData = {
endpoint: 'environments.json',
canCreateEnvironment: true,
- canCreateDeployment: true,
canReadEnvironment: true,
cssContainerClass: 'container',
newEnvironmentPath: 'environments/new',
@@ -95,7 +94,7 @@ describe('Environment', () => {
it('should make an API request when page is clicked', done => {
spyOn(component, 'updateContent');
setTimeout(() => {
- component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
+ component.$el.querySelector('.gl-pagination li:nth-child(5) .page-link').click();
expect(component.updateContent).toHaveBeenCalledWith({ scope: 'available', page: '2' });
done();
diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js
index 7f0a9475d5f..69ddd26eef1 100644
--- a/spec/javascripts/environments/folder/environments_folder_view_spec.js
+++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js
@@ -13,7 +13,6 @@ describe('Environments Folder View', () => {
const mockData = {
endpoint: 'environments.json',
folderName: 'review',
- canCreateDeployment: true,
canReadEnvironment: true,
cssContainerClass: 'container',
};
@@ -108,7 +107,7 @@ describe('Environments Folder View', () => {
it('should make an API request when changing page', done => {
spyOn(component, 'updateContent');
setTimeout(() => {
- component.$el.querySelector('.gl-pagination .js-last-button a').click();
+ component.$el.querySelector('.gl-pagination .js-last-button .page-link').click();
expect(component.updateContent).toHaveBeenCalledWith({
scope: component.scope,
diff --git a/spec/javascripts/error_tracking/components/error_tracking_list_spec.js b/spec/javascripts/error_tracking/components/error_tracking_list_spec.js
new file mode 100644
index 00000000000..503af3920a8
--- /dev/null
+++ b/spec/javascripts/error_tracking/components/error_tracking_list_spec.js
@@ -0,0 +1,118 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue';
+import { GlButton, GlEmptyState, GlLoadingIcon, GlTable, GlLink } from '@gitlab/ui';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('ErrorTrackingList', () => {
+ let store;
+ let wrapper;
+ let actions;
+
+ function mountComponent({ errorTrackingEnabled = true } = {}) {
+ wrapper = shallowMount(ErrorTrackingList, {
+ localVue,
+ store,
+ propsData: {
+ indexPath: '/path',
+ enableErrorTrackingLink: '/link',
+ errorTrackingEnabled,
+ illustrationPath: 'illustration/path',
+ },
+ stubs: {
+ 'gl-link': GlLink,
+ },
+ });
+ }
+
+ beforeEach(() => {
+ actions = {
+ getErrorList: () => {},
+ startPolling: () => {},
+ restartPolling: jasmine.createSpy('restartPolling'),
+ };
+
+ const state = {
+ errors: [],
+ loading: true,
+ };
+
+ store = new Vuex.Store({
+ actions,
+ state,
+ });
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('loading', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('shows spinner', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBeTruthy();
+ expect(wrapper.find(GlTable).exists()).toBeFalsy();
+ expect(wrapper.find(GlButton).exists()).toBeFalsy();
+ });
+ });
+
+ describe('results', () => {
+ beforeEach(() => {
+ store.state.loading = false;
+
+ mountComponent();
+ });
+
+ it('shows table', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBeFalsy();
+ expect(wrapper.find(GlTable).exists()).toBeTruthy();
+ expect(wrapper.find(GlButton).exists()).toBeTruthy();
+ });
+ });
+
+ describe('no results', () => {
+ beforeEach(() => {
+ store.state.loading = false;
+
+ mountComponent();
+ });
+
+ it('shows empty table', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBeFalsy();
+ expect(wrapper.find(GlTable).exists()).toBeTruthy();
+ expect(wrapper.find(GlButton).exists()).toBeTruthy();
+ });
+
+ it('shows a message prompting to refresh', () => {
+ const refreshLink = wrapper.vm.$refs.empty.querySelector('a');
+
+ expect(refreshLink.textContent.trim()).toContain('Check again');
+ });
+
+ it('restarts polling', () => {
+ wrapper.find('.js-try-again').trigger('click');
+
+ expect(actions.restartPolling).toHaveBeenCalled();
+ });
+ });
+
+ describe('error tracking feature disabled', () => {
+ beforeEach(() => {
+ mountComponent({ errorTrackingEnabled: false });
+ });
+
+ it('shows empty state', () => {
+ expect(wrapper.find(GlEmptyState).exists()).toBeTruthy();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBeFalsy();
+ expect(wrapper.find(GlTable).exists()).toBeFalsy();
+ expect(wrapper.find(GlButton).exists()).toBeFalsy();
+ });
+ });
+});
diff --git a/spec/javascripts/error_tracking/store/mutation_spec.js b/spec/javascripts/error_tracking/store/mutation_spec.js
new file mode 100644
index 00000000000..8117104bdbc
--- /dev/null
+++ b/spec/javascripts/error_tracking/store/mutation_spec.js
@@ -0,0 +1,36 @@
+import mutations from '~/error_tracking/store/mutations';
+import * as types from '~/error_tracking/store/mutation_types';
+
+describe('Error tracking mutations', () => {
+ describe('SET_ERRORS', () => {
+ let state;
+
+ beforeEach(() => {
+ state = { errors: [] };
+ });
+
+ it('camelizes response', () => {
+ const errors = [
+ {
+ title: 'the title',
+ external_url: 'localhost:3456',
+ count: 100,
+ userCount: 10,
+ },
+ ];
+
+ mutations[types.SET_ERRORS](state, errors);
+
+ expect(state).toEqual({
+ errors: [
+ {
+ title: 'the title',
+ externalUrl: 'localhost:3456',
+ count: 100,
+ userCount: 10,
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/error_tracking_settings/components/app_spec.js b/spec/javascripts/error_tracking_settings/components/app_spec.js
new file mode 100644
index 00000000000..2e52a45fd34
--- /dev/null
+++ b/spec/javascripts/error_tracking_settings/components/app_spec.js
@@ -0,0 +1,63 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import ErrorTrackingSettings from '~/error_tracking_settings/components/app.vue';
+import ErrorTrackingForm from '~/error_tracking_settings/components/error_tracking_form.vue';
+import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue';
+import createStore from '~/error_tracking_settings/store';
+import { TEST_HOST } from 'spec/test_constants';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('error tracking settings app', () => {
+ let store;
+ let wrapper;
+
+ function mountComponent() {
+ wrapper = shallowMount(ErrorTrackingSettings, {
+ localVue,
+ store, // Override the imported store
+ propsData: {
+ initialEnabled: 'true',
+ initialApiHost: TEST_HOST,
+ initialToken: 'someToken',
+ initialProject: null,
+ listProjectsEndpoint: TEST_HOST,
+ operationsSettingsEndpoint: TEST_HOST,
+ },
+ });
+ }
+
+ beforeEach(() => {
+ store = createStore();
+
+ mountComponent();
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('section', () => {
+ it('renders the form and dropdown', () => {
+ expect(wrapper.find(ErrorTrackingForm).exists()).toBeTruthy();
+ expect(wrapper.find(ProjectDropdown).exists()).toBeTruthy();
+ });
+
+ it('renders the Save Changes button', () => {
+ expect(wrapper.find('.js-error-tracking-button').exists()).toBeTruthy();
+ });
+
+ it('enables the button by default', () => {
+ expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeFalsy();
+ });
+
+ it('disables the button when saving', () => {
+ store.state.settingsLoading = true;
+
+ expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeTruthy();
+ });
+ });
+});
diff --git a/spec/javascripts/error_tracking_settings/components/error_tracking_form_spec.js b/spec/javascripts/error_tracking_settings/components/error_tracking_form_spec.js
new file mode 100644
index 00000000000..23e57c4bbf1
--- /dev/null
+++ b/spec/javascripts/error_tracking_settings/components/error_tracking_form_spec.js
@@ -0,0 +1,91 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlButton, GlFormInput } from '@gitlab/ui';
+import ErrorTrackingForm from '~/error_tracking_settings/components/error_tracking_form.vue';
+import { defaultProps } from '../mock';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('error tracking settings form', () => {
+ let wrapper;
+
+ function mountComponent() {
+ wrapper = shallowMount(ErrorTrackingForm, {
+ localVue,
+ propsData: defaultProps,
+ });
+ }
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('an empty form', () => {
+ it('is rendered', () => {
+ expect(wrapper.findAll(GlFormInput).length).toBe(2);
+ expect(wrapper.find(GlFormInput).attributes('id')).toBe('error-tracking-api-host');
+ expect(
+ wrapper
+ .findAll(GlFormInput)
+ .at(1)
+ .attributes('id'),
+ ).toBe('error-tracking-token');
+
+ expect(wrapper.findAll(GlButton).exists()).toBe(true);
+ });
+
+ it('is rendered with labels and placeholders', () => {
+ const pageText = wrapper.text();
+
+ expect(pageText).toContain('Find your hostname in your Sentry account settings page');
+ expect(pageText).toContain(
+ "After adding your Auth Token, use the 'Connect' button to load projects",
+ );
+
+ expect(pageText).not.toContain('Connection has failed. Re-check Auth Token and try again');
+ expect(
+ wrapper
+ .findAll(GlFormInput)
+ .at(0)
+ .attributes('placeholder'),
+ ).toContain('https://mysentryserver.com');
+ });
+ });
+
+ describe('after a successful connection', () => {
+ beforeEach(() => {
+ wrapper.setProps({ connectSuccessful: true });
+ });
+
+ it('shows the success checkmark', () => {
+ expect(wrapper.find('.js-error-tracking-connect-success').isVisible()).toBe(true);
+ });
+
+ it('does not show an error', () => {
+ expect(wrapper.text()).not.toContain(
+ 'Connection has failed. Re-check Auth Token and try again',
+ );
+ });
+ });
+
+ describe('after an unsuccessful connection', () => {
+ beforeEach(() => {
+ wrapper.setProps({ connectError: true });
+ });
+
+ it('does not show the check mark', () => {
+ expect(wrapper.find('.js-error-tracking-connect-success').isVisible()).toBe(false);
+ });
+
+ it('shows an error', () => {
+ expect(wrapper.text()).toContain('Connection has failed. Re-check Auth Token and try again');
+ });
+ });
+});
diff --git a/spec/javascripts/error_tracking_settings/components/project_dropdown_spec.js b/spec/javascripts/error_tracking_settings/components/project_dropdown_spec.js
new file mode 100644
index 00000000000..8e5dbe28452
--- /dev/null
+++ b/spec/javascripts/error_tracking_settings/components/project_dropdown_spec.js
@@ -0,0 +1,109 @@
+import _ from 'underscore';
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue';
+import { defaultProps, projectList, staleProject } from '../mock';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('error tracking settings project dropdown', () => {
+ let wrapper;
+
+ function mountComponent() {
+ wrapper = shallowMount(ProjectDropdown, {
+ localVue,
+ propsData: {
+ ..._.pick(
+ defaultProps,
+ 'dropdownLabel',
+ 'invalidProjectLabel',
+ 'projects',
+ 'projectSelectionLabel',
+ 'selectedProject',
+ 'token',
+ ),
+ hasProjects: false,
+ isProjectInvalid: false,
+ },
+ });
+ }
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('empty project list', () => {
+ it('renders the dropdown', () => {
+ expect(wrapper.find('#project-dropdown').exists()).toBeTruthy();
+ expect(wrapper.find(GlDropdown).exists()).toBeTruthy();
+ });
+
+ it('shows helper text', () => {
+ expect(wrapper.find('.js-project-dropdown-label').exists()).toBeTruthy();
+ 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();
+ });
+
+ it('does not contain any dropdown items', () => {
+ expect(wrapper.find(GlDropdownItem).exists()).toBeFalsy();
+ expect(wrapper.find(GlDropdown).props('text')).toBe('No projects available');
+ });
+ });
+
+ describe('populated project list', () => {
+ beforeEach(() => {
+ wrapper.setProps({ projects: _.clone(projectList), hasProjects: true });
+ });
+
+ it('renders the dropdown', () => {
+ expect(wrapper.find('#project-dropdown').exists()).toBeTruthy();
+ expect(wrapper.find(GlDropdown).exists()).toBeTruthy();
+ });
+
+ it('contains a number of dropdown items', () => {
+ expect(wrapper.find(GlDropdownItem).exists()).toBeTruthy();
+ expect(wrapper.findAll(GlDropdownItem).length).toBe(2);
+ });
+ });
+
+ describe('selected project', () => {
+ const selectedProject = _.clone(projectList[0]);
+
+ beforeEach(() => {
+ wrapper.setProps({ projects: _.clone(projectList), selectedProject, hasProjects: true });
+ });
+
+ it('does not show helper text', () => {
+ expect(wrapper.find('.js-project-dropdown-label').exists()).toBeFalsy();
+ expect(wrapper.find('.js-project-dropdown-error').exists()).toBeFalsy();
+ });
+ });
+
+ describe('invalid project selected', () => {
+ beforeEach(() => {
+ wrapper.setProps({
+ projects: _.clone(projectList),
+ selectedProject: staleProject,
+ isProjectInvalid: true,
+ });
+ });
+
+ it('displays a error', () => {
+ expect(wrapper.find('.js-project-dropdown-label').exists()).toBeFalsy();
+ expect(wrapper.find('.js-project-dropdown-error').exists()).toBeTruthy();
+ });
+ });
+});
diff --git a/spec/javascripts/error_tracking_settings/mock.js b/spec/javascripts/error_tracking_settings/mock.js
new file mode 100644
index 00000000000..32cdba33c14
--- /dev/null
+++ b/spec/javascripts/error_tracking_settings/mock.js
@@ -0,0 +1,92 @@
+import createStore from '~/error_tracking_settings/store';
+import { TEST_HOST } from 'spec/test_constants';
+
+const defaultStore = createStore();
+
+export const projectList = [
+ {
+ name: 'name',
+ slug: 'slug',
+ organizationName: 'organizationName',
+ organizationSlug: 'organizationSlug',
+ },
+ {
+ name: 'name2',
+ slug: 'slug2',
+ organizationName: 'organizationName2',
+ organizationSlug: 'organizationSlug2',
+ },
+];
+
+export const staleProject = {
+ name: 'staleName',
+ slug: 'staleSlug',
+ organizationName: 'staleOrganizationName',
+ organizationSlug: 'staleOrganizationSlug',
+};
+
+export const normalizedProject = {
+ name: 'name',
+ slug: 'slug',
+ organizationName: 'organization_name',
+ organizationSlug: 'organization_slug',
+};
+
+export const sampleBackendProject = {
+ name: normalizedProject.name,
+ slug: normalizedProject.slug,
+ organization_name: normalizedProject.organizationName,
+ organization_slug: normalizedProject.organizationSlug,
+};
+
+export const sampleFrontendSettings = {
+ apiHost: 'apiHost',
+ enabled: false,
+ token: 'token',
+ selectedProject: {
+ slug: normalizedProject.slug,
+ name: normalizedProject.name,
+ organizationName: normalizedProject.organizationName,
+ organizationSlug: normalizedProject.organizationSlug,
+ },
+};
+
+export const transformedSettings = {
+ api_host: 'apiHost',
+ enabled: false,
+ token: 'token',
+ project: {
+ slug: normalizedProject.slug,
+ name: normalizedProject.name,
+ organization_name: normalizedProject.organizationName,
+ organization_slug: normalizedProject.organizationSlug,
+ },
+};
+
+export const defaultProps = {
+ ...defaultStore.state,
+ ...defaultStore.getters,
+};
+
+export const initialEmptyState = {
+ apiHost: '',
+ enabled: false,
+ project: null,
+ token: '',
+ listProjectsEndpoint: TEST_HOST,
+ operationsSettingsEndpoint: TEST_HOST,
+};
+
+export const initialPopulatedState = {
+ apiHost: 'apiHost',
+ enabled: true,
+ project: JSON.stringify(projectList[0]),
+ token: 'token',
+ listProjectsEndpoint: TEST_HOST,
+ operationsSettingsEndpoint: TEST_HOST,
+};
+
+export const projectWithHtmlTemplate = {
+ ...projectList[0],
+ name: '<strong>bold</strong>',
+};
diff --git a/spec/javascripts/error_tracking_settings/store/actions_spec.js b/spec/javascripts/error_tracking_settings/store/actions_spec.js
new file mode 100644
index 00000000000..0255b3a7aa4
--- /dev/null
+++ b/spec/javascripts/error_tracking_settings/store/actions_spec.js
@@ -0,0 +1,191 @@
+import MockAdapter from 'axios-mock-adapter';
+import testAction from 'spec/helpers/vuex_action_helper';
+import { TEST_HOST } from 'spec/test_constants';
+import axios from '~/lib/utils/axios_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import actionsDefaultExport, * as actions from '~/error_tracking_settings/store/actions';
+import * as types from '~/error_tracking_settings/store/mutation_types';
+import defaultState from '~/error_tracking_settings/store/state';
+import { projectList } from '../mock';
+
+describe('error tracking settings actions', () => {
+ let state;
+
+ describe('project list actions', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ state = { ...defaultState(), listProjectsEndpoint: TEST_HOST };
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ it('should request and transform the project list', done => {
+ mock.onPost(TEST_HOST).reply(() => [200, { projects: projectList }]);
+ testAction(
+ actions.fetchProjects,
+ null,
+ state,
+ [],
+ [
+ { type: 'requestProjects' },
+ {
+ type: 'receiveProjectsSuccess',
+ payload: projectList.map(convertObjectPropsToCamelCase),
+ },
+ ],
+ () => {
+ expect(mock.history.post.length).toBe(1);
+ done();
+ },
+ );
+ });
+
+ it('should handle a server error', done => {
+ mock.onPost(`${TEST_HOST}.json`).reply(() => [400]);
+ testAction(
+ actions.fetchProjects,
+ null,
+ state,
+ [],
+ [
+ { type: 'requestProjects' },
+ {
+ type: 'receiveProjectsError',
+ },
+ ],
+ () => {
+ expect(mock.history.post.length).toBe(1);
+ done();
+ },
+ );
+ });
+
+ it('should request projects correctly', done => {
+ testAction(actions.requestProjects, null, state, [{ type: types.RESET_CONNECT }], [], done);
+ });
+
+ it('should receive projects correctly', done => {
+ const testPayload = [];
+ testAction(
+ actions.receiveProjectsSuccess,
+ testPayload,
+ state,
+ [
+ { type: types.UPDATE_CONNECT_SUCCESS },
+ { type: types.RECEIVE_PROJECTS, payload: testPayload },
+ ],
+ [],
+ done,
+ );
+ });
+
+ it('should handle errors when receiving projects', done => {
+ const testPayload = [];
+ testAction(
+ actions.receiveProjectsError,
+ testPayload,
+ state,
+ [{ type: types.UPDATE_CONNECT_ERROR }, { type: types.CLEAR_PROJECTS }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('save changes actions', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ state = {
+ operationsSettingsEndpoint: TEST_HOST,
+ };
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ it('should save the page', done => {
+ const refreshCurrentPage = spyOnDependency(actionsDefaultExport, 'refreshCurrentPage');
+ mock.onPatch(TEST_HOST).reply(200);
+ testAction(actions.updateSettings, null, state, [], [{ type: 'requestSettings' }], () => {
+ expect(mock.history.patch.length).toBe(1);
+ expect(refreshCurrentPage).toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('should handle a server error', done => {
+ mock.onPatch(TEST_HOST).reply(400);
+ testAction(
+ actions.updateSettings,
+ null,
+ state,
+ [],
+ [
+ { type: 'requestSettings' },
+ {
+ type: 'receiveSettingsError',
+ payload: new Error('Request failed with status code 400'),
+ },
+ ],
+ () => {
+ expect(mock.history.patch.length).toBe(1);
+ done();
+ },
+ );
+ });
+
+ it('should request to save the page', done => {
+ testAction(
+ actions.requestSettings,
+ null,
+ state,
+ [{ type: types.UPDATE_SETTINGS_LOADING, payload: true }],
+ [],
+ done,
+ );
+ });
+
+ it('should handle errors when requesting to save the page', done => {
+ testAction(
+ actions.receiveSettingsError,
+ {},
+ state,
+ [{ type: types.UPDATE_SETTINGS_LOADING, payload: false }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('generic actions to update the store', () => {
+ const testData = 'test';
+ it('should reset the `connect success` flag when updating the api host', done => {
+ testAction(
+ actions.updateApiHost,
+ testData,
+ state,
+ [{ type: types.UPDATE_API_HOST, payload: testData }, { type: types.RESET_CONNECT }],
+ [],
+ done,
+ );
+ });
+
+ it('should reset the `connect success` flag when updating the token', done => {
+ testAction(
+ actions.updateToken,
+ testData,
+ state,
+ [{ type: types.UPDATE_TOKEN, payload: testData }, { type: types.RESET_CONNECT }],
+ [],
+ done,
+ );
+ });
+ });
+});
diff --git a/spec/javascripts/error_tracking_settings/store/getters_spec.js b/spec/javascripts/error_tracking_settings/store/getters_spec.js
new file mode 100644
index 00000000000..2c5ff084b8a
--- /dev/null
+++ b/spec/javascripts/error_tracking_settings/store/getters_spec.js
@@ -0,0 +1,93 @@
+import * as getters from '~/error_tracking_settings/store/getters';
+import defaultState from '~/error_tracking_settings/store/state';
+import { projectList, projectWithHtmlTemplate, staleProject } from '../mock';
+
+describe('Error Tracking Settings - Getters', () => {
+ let state;
+
+ beforeEach(() => {
+ state = defaultState();
+ });
+
+ describe('hasProjects', () => {
+ it('should reflect when no projects exist', () => {
+ expect(getters.hasProjects(state)).toEqual(false);
+ });
+
+ it('should reflect when projects exist', () => {
+ state.projects = projectList;
+
+ expect(getters.hasProjects(state)).toEqual(true);
+ });
+ });
+
+ describe('isProjectInvalid', () => {
+ const mockGetters = { hasProjects: true };
+ it('should show when a project is valid', () => {
+ state.projects = projectList;
+ [state.selectedProject] = projectList;
+
+ expect(getters.isProjectInvalid(state, mockGetters)).toEqual(false);
+ });
+
+ it('should show when a project is invalid', () => {
+ state.projects = projectList;
+ state.selectedProject = staleProject;
+
+ expect(getters.isProjectInvalid(state, mockGetters)).toEqual(true);
+ });
+ });
+
+ describe('dropdownLabel', () => {
+ const mockGetters = { hasProjects: false };
+ it('should display correctly when there are no projects available', () => {
+ expect(getters.dropdownLabel(state, mockGetters)).toEqual('No projects available');
+ });
+
+ it('should display correctly when a project is selected', () => {
+ [state.selectedProject] = projectList;
+
+ expect(getters.dropdownLabel(state, mockGetters)).toEqual('organizationName | name');
+ });
+
+ it('should display correctly when no project is selected', () => {
+ state.projects = projectList;
+
+ expect(getters.dropdownLabel(state, { hasProjects: true })).toEqual('Select project');
+ });
+ });
+
+ describe('invalidProjectLabel', () => {
+ it('should display an error containing the project name', () => {
+ [state.selectedProject] = projectList;
+
+ expect(getters.invalidProjectLabel(state)).toEqual(
+ 'Project "name" is no longer available. Select another project to continue.',
+ );
+ });
+
+ it('should properly escape the label text', () => {
+ state.selectedProject = projectWithHtmlTemplate;
+
+ expect(getters.invalidProjectLabel(state)).toEqual(
+ 'Project "&lt;strong&gt;bold&lt;/strong&gt;" is no longer available. Select another project to continue.',
+ );
+ });
+ });
+
+ describe('projectSelectionLabel', () => {
+ it('should show the correct message when the token is empty', () => {
+ expect(getters.projectSelectionLabel(state)).toEqual(
+ 'To enable project selection, enter a valid Auth Token',
+ );
+ });
+
+ it('should show the correct message when token exists', () => {
+ state.token = 'test-token';
+
+ expect(getters.projectSelectionLabel(state)).toEqual(
+ "Click 'Connect' to re-establish the connection to Sentry and activate the dropdown.",
+ );
+ });
+ });
+});
diff --git a/spec/javascripts/error_tracking_settings/store/mutation_spec.js b/spec/javascripts/error_tracking_settings/store/mutation_spec.js
new file mode 100644
index 00000000000..bb1f1da784e
--- /dev/null
+++ b/spec/javascripts/error_tracking_settings/store/mutation_spec.js
@@ -0,0 +1,82 @@
+import { TEST_HOST } from 'spec/test_constants';
+import mutations from '~/error_tracking_settings/store/mutations';
+import defaultState from '~/error_tracking_settings/store/state';
+import * as types from '~/error_tracking_settings/store/mutation_types';
+import {
+ initialEmptyState,
+ initialPopulatedState,
+ projectList,
+ sampleBackendProject,
+ normalizedProject,
+} from '../mock';
+
+describe('error tracking settings mutations', () => {
+ describe('mutations', () => {
+ let state;
+
+ beforeEach(() => {
+ state = defaultState();
+ });
+
+ it('should create an empty initial state correctly', () => {
+ mutations[types.SET_INITIAL_STATE](state, {
+ ...initialEmptyState,
+ });
+
+ expect(state.apiHost).toEqual('');
+ expect(state.enabled).toEqual(false);
+ expect(state.selectedProject).toEqual(null);
+ expect(state.token).toEqual('');
+ expect(state.listProjectsEndpoint).toEqual(TEST_HOST);
+ expect(state.operationsSettingsEndpoint).toEqual(TEST_HOST);
+ });
+
+ it('should populate the initial state correctly', () => {
+ mutations[types.SET_INITIAL_STATE](state, {
+ ...initialPopulatedState,
+ });
+
+ expect(state.apiHost).toEqual('apiHost');
+ expect(state.enabled).toEqual(true);
+ expect(state.selectedProject).toEqual(projectList[0]);
+ expect(state.token).toEqual('token');
+ expect(state.listProjectsEndpoint).toEqual(TEST_HOST);
+ expect(state.operationsSettingsEndpoint).toEqual(TEST_HOST);
+ });
+
+ it('should receive projects successfully', () => {
+ mutations[types.RECEIVE_PROJECTS](state, [sampleBackendProject]);
+
+ expect(state.projects).toEqual([normalizedProject]);
+ });
+
+ it('should strip out unnecessary project properties', () => {
+ mutations[types.RECEIVE_PROJECTS](state, [
+ { ...sampleBackendProject, extra_property: 'extra_property' },
+ ]);
+
+ expect(state.projects).toEqual([normalizedProject]);
+ });
+
+ it('should update state when connect is successful', () => {
+ mutations[types.UPDATE_CONNECT_SUCCESS](state);
+
+ expect(state.connectSuccessful).toBe(true);
+ expect(state.connectError).toBe(false);
+ });
+
+ it('should update state when connect fails', () => {
+ mutations[types.UPDATE_CONNECT_ERROR](state);
+
+ expect(state.connectSuccessful).toBe(false);
+ expect(state.connectError).toBe(true);
+ });
+
+ it('should update state when connect is reset', () => {
+ mutations[types.RESET_CONNECT](state);
+
+ expect(state.connectSuccessful).toBe(false);
+ expect(state.connectError).toBe(false);
+ });
+ });
+});
diff --git a/spec/javascripts/error_tracking_settings/utils_spec.js b/spec/javascripts/error_tracking_settings/utils_spec.js
new file mode 100644
index 00000000000..4b144f7daf1
--- /dev/null
+++ b/spec/javascripts/error_tracking_settings/utils_spec.js
@@ -0,0 +1,29 @@
+import { transformFrontendSettings } from '~/error_tracking_settings/utils';
+import { sampleFrontendSettings, transformedSettings } from './mock';
+
+describe('error tracking settings utils', () => {
+ describe('data transform functions', () => {
+ it('should transform settings successfully for the backend', () => {
+ expect(transformFrontendSettings(sampleFrontendSettings)).toEqual(transformedSettings);
+ });
+
+ it('should transform empty values in the settings object to null', () => {
+ const emptyFrontendSettingsObject = {
+ apiHost: '',
+ enabled: false,
+ token: '',
+ selectedProject: null,
+ };
+ const transformedEmptySettingsObject = {
+ api_host: null,
+ enabled: false,
+ token: null,
+ project: null,
+ };
+
+ expect(transformFrontendSettings(emptyFrontendSettingsObject)).toEqual(
+ transformedEmptySettingsObject,
+ );
+ });
+ });
+});
diff --git a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
index 9aa3cbaa231..f3dc35552d5 100644
--- a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
@@ -1,9 +1,4 @@
-import _ from 'underscore';
-import AjaxCache from '~/lib/utils/ajax_cache';
-import UsersCache from '~/lib/utils/users_cache';
-
import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
-import DropdownUtils from '~/filtered_search//dropdown_utils';
import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Filtered Search Visual Tokens', () => {
@@ -685,338 +680,21 @@ describe('Filtered Search Visual Tokens', () => {
});
describe('renderVisualTokenValue', () => {
- const keywordToken = FilteredSearchSpecHelper.createFilterVisualToken('search');
- const milestoneToken = FilteredSearchSpecHelper.createFilterVisualToken(
- 'milestone',
- 'upcoming',
- );
-
- let updateLabelTokenColorSpy;
- let updateUserTokenAppearanceSpy;
-
beforeEach(() => {
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
${authorToken.outerHTML}
${bugLabelToken.outerHTML}
- ${keywordToken.outerHTML}
- ${milestoneToken.outerHTML}
`);
-
- spyOn(subject, 'updateLabelTokenColor');
- updateLabelTokenColorSpy = subject.updateLabelTokenColor;
-
- spyOn(subject, 'updateUserTokenAppearance');
- updateUserTokenAppearanceSpy = subject.updateUserTokenAppearance;
});
it('renders a author token value element', () => {
- const { tokenNameElement, tokenValueContainer, tokenValueElement } = findElements(
- authorToken,
- );
+ const { tokenNameElement, tokenValueElement } = findElements(authorToken);
const tokenName = tokenNameElement.innerText;
const tokenValue = 'new value';
subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
expect(tokenValueElement.innerText).toBe(tokenValue);
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(1);
- const expectedArgs = [tokenValueContainer, tokenValueElement, tokenValue];
-
- expect(updateUserTokenAppearanceSpy.calls.argsFor(0)).toEqual(expectedArgs);
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
-
- it('renders a label token value element', () => {
- const { tokenNameElement, tokenValueContainer, tokenValueElement } = findElements(
- bugLabelToken,
- );
- const tokenName = tokenNameElement.innerText;
- const tokenValue = 'new value';
-
- subject.renderVisualTokenValue(bugLabelToken, tokenName, tokenValue);
-
- expect(tokenValueElement.innerText).toBe(tokenValue);
- expect(updateLabelTokenColorSpy.calls.count()).toBe(1);
- const expectedArgs = [tokenValueContainer, tokenValue];
-
- expect(updateLabelTokenColorSpy.calls.argsFor(0)).toEqual(expectedArgs);
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('renders a milestone token value element', () => {
- const { tokenNameElement, tokenValueElement } = findElements(milestoneToken);
- const tokenName = tokenNameElement.innerText;
- const tokenValue = 'new value';
-
- subject.renderVisualTokenValue(milestoneToken, tokenName, tokenValue);
-
- expect(tokenValueElement.innerText).toBe(tokenValue);
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update user token appearance for `none` filter', () => {
- const { tokenNameElement } = findElements(authorToken);
-
- const tokenName = tokenNameElement.innerText;
- const tokenValue = 'none';
-
- subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update user token appearance for `any` filter', () => {
- const { tokenNameElement } = findElements(authorToken);
-
- const tokenName = tokenNameElement.innerText;
- const tokenValue = 'any';
-
- subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update label token color for `none` filter', () => {
- const { tokenNameElement } = findElements(bugLabelToken);
-
- const tokenName = tokenNameElement.innerText;
- const tokenValue = 'none';
-
- subject.renderVisualTokenValue(bugLabelToken, tokenName, tokenValue);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
-
- it('does not update label token color for `any` filter', () => {
- const { tokenNameElement } = findElements(bugLabelToken);
-
- const tokenName = tokenNameElement.innerText;
- const tokenValue = 'any';
-
- subject.renderVisualTokenValue(bugLabelToken, tokenName, tokenValue);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
- });
-
- describe('updateUserTokenAppearance', () => {
- let usersCacheSpy;
-
- beforeEach(() => {
- spyOn(UsersCache, 'retrieve').and.callFake(username => usersCacheSpy(username));
- });
-
- it('ignores error if UsersCache throws', done => {
- spyOn(window, 'Flash');
- const dummyError = new Error('Earth rotated backwards');
- const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.reject(dummyError);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(window.Flash.calls.count()).toBe(0);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('does nothing if user cannot be found', done => {
- const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.resolve(undefined);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueElement.innerText).toBe(tokenValue);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('replaces author token with avatar and display name', done => {
- const dummyUser = {
- name: 'Important Person',
- avatar_url: 'https://host.invalid/mypics/avatar.png',
- };
- const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.resolve(dummyUser);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueContainer.dataset.originalValue).toBe(tokenValue);
- expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
- const avatar = tokenValueElement.querySelector('img.avatar');
-
- expect(avatar.src).toBe(dummyUser.avatar_url);
- expect(avatar.alt).toBe('');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('escapes user name when creating token', done => {
- const dummyUser = {
- name: '<script>',
- avatar_url: `${gl.TEST_HOST}/mypics/avatar.png`,
- };
- const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.resolve(dummyUser);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
- tokenValueElement.querySelector('.avatar').remove();
-
- expect(tokenValueElement.innerHTML.trim()).toBe(_.escape(dummyUser.name));
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('setTokenStyle', () => {
- let originalTextColor;
-
- beforeEach(() => {
- originalTextColor = bugLabelToken.style.color;
- });
-
- it('should set backgroundColor', () => {
- const originalBackgroundColor = bugLabelToken.style.backgroundColor;
- const token = subject.setTokenStyle(bugLabelToken, 'blue', 'white');
-
- expect(token.style.backgroundColor).toEqual('blue');
- expect(token.style.backgroundColor).not.toEqual(originalBackgroundColor);
- });
-
- it('should set textColor', () => {
- const token = subject.setTokenStyle(bugLabelToken, 'white', 'black');
-
- expect(token.style.color).toEqual('black');
- expect(token.style.color).not.toEqual(originalTextColor);
- });
-
- it('should add inverted class when textColor is #FFFFFF', () => {
- const token = subject.setTokenStyle(bugLabelToken, 'black', '#FFFFFF');
-
- expect(token.style.color).toEqual('rgb(255, 255, 255)');
- expect(token.style.color).not.toEqual(originalTextColor);
- expect(token.querySelector('.remove-token').classList.contains('inverted')).toEqual(true);
- });
- });
-
- describe('updateLabelTokenColor', () => {
- const jsonFixtureName = 'labels/project_labels.json';
- const dummyEndpoint = '/dummy/endpoint';
-
- preloadFixtures(jsonFixtureName);
-
- let labelData;
-
- beforeAll(() => {
- labelData = getJSONFixture(jsonFixtureName);
- });
-
- const missingLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
- 'label',
- '~doesnotexist',
- );
- const spaceLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
- 'label',
- '~"some space"',
- );
-
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
- ${bugLabelToken.outerHTML}
- ${missingLabelToken.outerHTML}
- ${spaceLabelToken.outerHTML}
- `);
-
- const filteredSearchInput = document.querySelector('.filtered-search');
- filteredSearchInput.dataset.baseEndpoint = dummyEndpoint;
-
- AjaxCache.internalStorage = {};
- AjaxCache.internalStorage[`${dummyEndpoint}/labels.json`] = labelData;
- });
-
- const parseColor = color => {
- const dummyElement = document.createElement('div');
- dummyElement.style.color = color;
- return dummyElement.style.color;
- };
-
- const expectValueContainerStyle = (tokenValueContainer, label) => {
- expect(tokenValueContainer.getAttribute('style')).not.toBe(null);
- expect(tokenValueContainer.style.backgroundColor).toBe(parseColor(label.color));
- expect(tokenValueContainer.style.color).toBe(parseColor(label.text_color));
- };
-
- const findLabel = tokenValue =>
- labelData.find(label => tokenValue === `~${DropdownUtils.getEscapedText(label.title)}`);
-
- it('updates the color of a label token', done => {
- const { tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
- const tokenValue = tokenValueElement.innerText;
- const matchingLabel = findLabel(tokenValue);
-
- subject
- .updateLabelTokenColor(tokenValueContainer, tokenValue)
- .then(() => {
- expectValueContainerStyle(tokenValueContainer, matchingLabel);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('updates the color of a label token with spaces', done => {
- const { tokenValueContainer, tokenValueElement } = findElements(spaceLabelToken);
- const tokenValue = tokenValueElement.innerText;
- const matchingLabel = findLabel(tokenValue);
-
- subject
- .updateLabelTokenColor(tokenValueContainer, tokenValue)
- .then(() => {
- expectValueContainerStyle(tokenValueContainer, matchingLabel);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('does not change color of a missing label', done => {
- const { tokenValueContainer, tokenValueElement } = findElements(missingLabelToken);
- const tokenValue = tokenValueElement.innerText;
- const matchingLabel = findLabel(tokenValue);
-
- expect(matchingLabel).toBe(undefined);
-
- subject
- .updateLabelTokenColor(tokenValueContainer, tokenValue)
- .then(() => {
- expect(tokenValueContainer.getAttribute('style')).toBe(null);
- })
- .then(done)
- .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/filtered_search/visual_token_value_spec.js b/spec/javascripts/filtered_search/visual_token_value_spec.js
new file mode 100644
index 00000000000..f52dc26a7bb
--- /dev/null
+++ b/spec/javascripts/filtered_search/visual_token_value_spec.js
@@ -0,0 +1,361 @@
+import VisualTokenValue from '~/filtered_search/visual_token_value';
+import _ from 'underscore';
+import AjaxCache from '~/lib/utils/ajax_cache';
+import UsersCache from '~/lib/utils/users_cache';
+import DropdownUtils from '~/filtered_search//dropdown_utils';
+import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
+
+describe('Filtered Search Visual Tokens', () => {
+ const findElements = tokenElement => {
+ const tokenNameElement = tokenElement.querySelector('.name');
+ const tokenValueContainer = tokenElement.querySelector('.value-container');
+ const tokenValueElement = tokenValueContainer.querySelector('.value');
+ const tokenType = tokenNameElement.innerText.toLowerCase();
+ const tokenValue = tokenValueElement.innerText;
+ const subject = new VisualTokenValue(tokenValue, tokenType);
+ return { subject, tokenValueContainer, tokenValueElement };
+ };
+
+ let tokensContainer;
+ let authorToken;
+ let bugLabelToken;
+
+ beforeEach(() => {
+ setFixtures(`
+ <ul class="tokens-container">
+ ${FilteredSearchSpecHelper.createInputHTML()}
+ </ul>
+ `);
+ tokensContainer = document.querySelector('.tokens-container');
+
+ authorToken = FilteredSearchSpecHelper.createFilterVisualToken('author', '@user');
+ bugLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '~bug');
+ });
+
+ describe('updateUserTokenAppearance', () => {
+ let usersCacheSpy;
+
+ beforeEach(() => {
+ spyOn(UsersCache, 'retrieve').and.callFake(username => usersCacheSpy(username));
+ });
+
+ it('ignores error if UsersCache throws', done => {
+ spyOn(window, 'Flash');
+ const dummyError = new Error('Earth rotated backwards');
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
+ const tokenValue = tokenValueElement.innerText;
+ usersCacheSpy = username => {
+ expect(`@${username}`).toBe(tokenValue);
+ return Promise.reject(dummyError);
+ };
+
+ subject
+ .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
+ .then(() => {
+ expect(window.Flash.calls.count()).toBe(0);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('does nothing if user cannot be found', done => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
+ const tokenValue = tokenValueElement.innerText;
+ usersCacheSpy = username => {
+ expect(`@${username}`).toBe(tokenValue);
+ return Promise.resolve(undefined);
+ };
+
+ subject
+ .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
+ .then(() => {
+ expect(tokenValueElement.innerText).toBe(tokenValue);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('replaces author token with avatar and display name', done => {
+ const dummyUser = {
+ name: 'Important Person',
+ avatar_url: 'https://host.invalid/mypics/avatar.png',
+ };
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
+ const tokenValue = tokenValueElement.innerText;
+ usersCacheSpy = username => {
+ expect(`@${username}`).toBe(tokenValue);
+ return Promise.resolve(dummyUser);
+ };
+
+ subject
+ .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
+ .then(() => {
+ expect(tokenValueContainer.dataset.originalValue).toBe(tokenValue);
+ expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
+ const avatar = tokenValueElement.querySelector('img.avatar');
+
+ expect(avatar.src).toBe(dummyUser.avatar_url);
+ expect(avatar.alt).toBe('');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('escapes user name when creating token', done => {
+ const dummyUser = {
+ name: '<script>',
+ avatar_url: `${gl.TEST_HOST}/mypics/avatar.png`,
+ };
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
+ const tokenValue = tokenValueElement.innerText;
+ usersCacheSpy = username => {
+ expect(`@${username}`).toBe(tokenValue);
+ return Promise.resolve(dummyUser);
+ };
+
+ subject
+ .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
+ .then(() => {
+ expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
+ tokenValueElement.querySelector('.avatar').remove();
+
+ expect(tokenValueElement.innerHTML.trim()).toBe(_.escape(dummyUser.name));
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('updateLabelTokenColor', () => {
+ const jsonFixtureName = 'labels/project_labels.json';
+ const dummyEndpoint = '/dummy/endpoint';
+
+ preloadFixtures(jsonFixtureName);
+
+ let labelData;
+
+ beforeAll(() => {
+ labelData = getJSONFixture(jsonFixtureName);
+ });
+
+ const missingLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
+ 'label',
+ '~doesnotexist',
+ );
+ const spaceLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
+ 'label',
+ '~"some space"',
+ );
+
+ beforeEach(() => {
+ tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
+ ${bugLabelToken.outerHTML}
+ ${missingLabelToken.outerHTML}
+ ${spaceLabelToken.outerHTML}
+ `);
+
+ const filteredSearchInput = document.querySelector('.filtered-search');
+ filteredSearchInput.dataset.baseEndpoint = dummyEndpoint;
+
+ AjaxCache.internalStorage = {};
+ AjaxCache.internalStorage[`${dummyEndpoint}/labels.json`] = labelData;
+ });
+
+ const parseColor = color => {
+ const dummyElement = document.createElement('div');
+ dummyElement.style.color = color;
+ return dummyElement.style.color;
+ };
+
+ const expectValueContainerStyle = (tokenValueContainer, label) => {
+ expect(tokenValueContainer.getAttribute('style')).not.toBe(null);
+ expect(tokenValueContainer.style.backgroundColor).toBe(parseColor(label.color));
+ expect(tokenValueContainer.style.color).toBe(parseColor(label.text_color));
+ };
+
+ const findLabel = tokenValue =>
+ labelData.find(label => tokenValue === `~${DropdownUtils.getEscapedText(label.title)}`);
+
+ it('updates the color of a label token', done => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
+ const tokenValue = tokenValueElement.innerText;
+ const matchingLabel = findLabel(tokenValue);
+
+ subject
+ .updateLabelTokenColor(tokenValueContainer, tokenValue)
+ .then(() => {
+ expectValueContainerStyle(tokenValueContainer, matchingLabel);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('updates the color of a label token with spaces', done => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(spaceLabelToken);
+ const tokenValue = tokenValueElement.innerText;
+ const matchingLabel = findLabel(tokenValue);
+
+ subject
+ .updateLabelTokenColor(tokenValueContainer, tokenValue)
+ .then(() => {
+ expectValueContainerStyle(tokenValueContainer, matchingLabel);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('does not change color of a missing label', done => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(missingLabelToken);
+ const tokenValue = tokenValueElement.innerText;
+ const matchingLabel = findLabel(tokenValue);
+
+ expect(matchingLabel).toBe(undefined);
+
+ subject
+ .updateLabelTokenColor(tokenValueContainer, tokenValue)
+ .then(() => {
+ expect(tokenValueContainer.getAttribute('style')).toBe(null);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('setTokenStyle', () => {
+ let originalTextColor;
+
+ beforeEach(() => {
+ originalTextColor = bugLabelToken.style.color;
+ });
+
+ it('should set backgroundColor', () => {
+ const originalBackgroundColor = bugLabelToken.style.backgroundColor;
+ const token = VisualTokenValue.setTokenStyle(bugLabelToken, 'blue', 'white');
+
+ expect(token.style.backgroundColor).toEqual('blue');
+ expect(token.style.backgroundColor).not.toEqual(originalBackgroundColor);
+ });
+
+ it('should set textColor', () => {
+ const token = VisualTokenValue.setTokenStyle(bugLabelToken, 'white', 'black');
+
+ expect(token.style.color).toEqual('black');
+ expect(token.style.color).not.toEqual(originalTextColor);
+ });
+
+ it('should add inverted class when textColor is #FFFFFF', () => {
+ const token = VisualTokenValue.setTokenStyle(bugLabelToken, 'black', '#FFFFFF');
+
+ expect(token.style.color).toEqual('rgb(255, 255, 255)');
+ expect(token.style.color).not.toEqual(originalTextColor);
+ expect(token.querySelector('.remove-token').classList.contains('inverted')).toEqual(true);
+ });
+ });
+
+ describe('render', () => {
+ const setupSpies = subject => {
+ spyOn(subject, 'updateLabelTokenColor'); // eslint-disable-line jasmine/no-unsafe-spy
+ const updateLabelTokenColorSpy = subject.updateLabelTokenColor;
+
+ spyOn(subject, 'updateUserTokenAppearance'); // eslint-disable-line jasmine/no-unsafe-spy
+ const updateUserTokenAppearanceSpy = subject.updateUserTokenAppearance;
+
+ return { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy };
+ };
+
+ const keywordToken = FilteredSearchSpecHelper.createFilterVisualToken('search');
+ const milestoneToken = FilteredSearchSpecHelper.createFilterVisualToken(
+ 'milestone',
+ 'upcoming',
+ );
+
+ beforeEach(() => {
+ tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
+ ${authorToken.outerHTML}
+ ${bugLabelToken.outerHTML}
+ ${keywordToken.outerHTML}
+ ${milestoneToken.outerHTML}
+ `);
+ });
+
+ it('renders a author token value element', () => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
+
+ const { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy } = setupSpies(subject);
+ subject.render(tokenValueContainer, tokenValueElement);
+
+ expect(updateUserTokenAppearanceSpy.calls.count()).toBe(1);
+ const expectedArgs = [tokenValueContainer, tokenValueElement];
+
+ expect(updateUserTokenAppearanceSpy.calls.argsFor(0)).toEqual(expectedArgs);
+ expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
+ });
+
+ it('renders a label token value element', () => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
+
+ const { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy } = setupSpies(subject);
+ subject.render(tokenValueContainer, tokenValueElement);
+
+ expect(updateLabelTokenColorSpy.calls.count()).toBe(1);
+ const expectedArgs = [tokenValueContainer];
+
+ expect(updateLabelTokenColorSpy.calls.argsFor(0)).toEqual(expectedArgs);
+ expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
+ });
+
+ it('renders a milestone token value element', () => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(milestoneToken);
+
+ const { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy } = setupSpies(subject);
+ subject.render(tokenValueContainer, tokenValueElement);
+
+ expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
+ expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
+ });
+
+ it('does not update user token appearance for `none` filter', () => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
+
+ subject.tokenType = 'none';
+
+ const { updateUserTokenAppearanceSpy } = setupSpies(subject);
+ subject.render(tokenValueContainer, tokenValueElement);
+
+ expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
+ });
+
+ it('does not update user token appearance for `any` filter', () => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
+
+ subject.tokenType = 'any';
+
+ const { updateUserTokenAppearanceSpy } = setupSpies(subject);
+ subject.render(tokenValueContainer, tokenValueElement);
+
+ expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
+ });
+
+ it('does not update label token color for `none` filter', () => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
+
+ subject.tokenType = 'none';
+
+ const { updateLabelTokenColorSpy } = setupSpies(subject);
+ subject.render(tokenValueContainer, tokenValueElement);
+
+ expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
+ });
+
+ it('does not update label token color for `any` filter', () => {
+ const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
+
+ subject.tokenType = 'any';
+
+ const { updateLabelTokenColorSpy } = setupSpies(subject);
+ subject.render(tokenValueContainer, tokenValueElement);
+
+ expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
+ });
+ });
+});
diff --git a/spec/javascripts/fixtures/blob.rb b/spec/javascripts/fixtures/blob.rb
index 1b2a3b484bb..cd66d98f92a 100644
--- a/spec/javascripts/fixtures/blob.rb
+++ b/spec/javascripts/fixtures/blob.rb
@@ -15,6 +15,7 @@ describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do
before do
sign_in(admin)
+ allow(SecureRandom).to receive(:hex).and_return('securerandomhex:thereisnospoon')
end
after do
diff --git a/spec/javascripts/fixtures/commit.rb b/spec/javascripts/fixtures/commit.rb
index f0e4bb50c67..295f13b34a4 100644
--- a/spec/javascripts/fixtures/commit.rb
+++ b/spec/javascripts/fixtures/commit.rb
@@ -16,6 +16,7 @@ describe Projects::CommitController, '(JavaScript fixtures)', type: :controller
before do
project.add_maintainer(user)
sign_in(user)
+ allow(SecureRandom).to receive(:hex).and_return('securerandomhex:thereisnospoon')
end
it 'commit/show.html.raw' do |example|
diff --git a/spec/javascripts/fixtures/deploy_keys.rb b/spec/javascripts/fixtures/deploy_keys.rb
index efbda955972..a333d9c0150 100644
--- a/spec/javascripts/fixtures/deploy_keys.rb
+++ b/spec/javascripts/fixtures/deploy_keys.rb
@@ -25,7 +25,7 @@ describe Projects::DeployKeysController, '(JavaScript fixtures)', type: :control
render_views
it 'deploy_keys/keys.json' do |example|
- create(:deploy_key, public: true)
+ create(:rsa_deploy_key_2048, public: true)
project_key = create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCdMHEHyhRjbhEZVddFn6lTWdgEy5Q6Bz4nwGB76xWZI5YT/1WJOMEW+sL5zYd31kk7sd3FJ5L9ft8zWMWrr/iWXQikC2cqZK24H1xy+ZUmrRuJD4qGAaIVoyyzBL+avL+lF8J5lg6YSw8gwJY/lX64/vnJHUlWw2n5BF8IFOWhiw== dummy@gitlab.com')
internal_key = create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDNd/UJWhPrpb+b/G5oL109y57yKuCxE+WUGJGYaj7WQKsYRJmLYh1mgjrl+KVyfsWpq4ylOxIfFSnN9xBBFN8mlb0Fma5DC7YsSsibJr3MZ19ZNBprwNcdogET7aW9I0In7Wu5f2KqI6e5W/spJHCy4JVxzVMUvk6Myab0LnJ2iQ== dummy@gitlab.com')
create(:deploy_keys_project, project: project, deploy_key: project_key)
diff --git a/spec/javascripts/fixtures/emojis.rb b/spec/javascripts/fixtures/emojis.rb
new file mode 100644
index 00000000000..0e7257ee681
--- /dev/null
+++ b/spec/javascripts/fixtures/emojis.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe 'Emojis (JavaScript fixtures)' do
+ include JavaScriptFixturesHelpers
+
+ before(:all) do
+ clean_frontend_fixtures('emojis/')
+ end
+
+ it 'emojis/emojis.json' do |example|
+ # Copying the emojis.json from the public folder
+ fixture_file_name = File.expand_path('emojis/emojis.json', JavaScriptFixturesHelpers::FIXTURE_PATH)
+ FileUtils.mkdir_p(File.dirname(fixture_file_name))
+ FileUtils.cp(Rails.root.join('public/-/emojis/1/emojis.json'), fixture_file_name)
+ end
+end
diff --git a/spec/javascripts/fixtures/groups.rb b/spec/javascripts/fixtures/groups.rb
index f8d55fc97c3..03136f4e661 100644
--- a/spec/javascripts/fixtures/groups.rb
+++ b/spec/javascripts/fixtures/groups.rb
@@ -4,7 +4,7 @@ describe 'Groups (JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
let(:admin) { create(:admin) }
- let(:group) { create(:group, name: 'frontend-fixtures-group' )}
+ let(:group) { create(:group, name: 'frontend-fixtures-group', runners_token: 'runnerstoken:intabulasreferre')}
render_views
diff --git a/spec/javascripts/fixtures/issues.rb b/spec/javascripts/fixtures/issues.rb
index 18fb1bebf8b..9b8e90c2a43 100644
--- a/spec/javascripts/fixtures/issues.rb
+++ b/spec/javascripts/fixtures/issues.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:admin) { create(:admin) }
+ let(:admin) { create(:admin, feed_token: 'feedtoken:coldfeed') }
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'issues-project') }
diff --git a/spec/javascripts/fixtures/jobs.rb b/spec/javascripts/fixtures/jobs.rb
index d6b5349594d..433bb690a1c 100644
--- a/spec/javascripts/fixtures/jobs.rb
+++ b/spec/javascripts/fixtures/jobs.rb
@@ -14,8 +14,7 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
create(:ci_build, :scheduled,
pipeline: pipeline,
name: 'delayed job',
- stage: 'test',
- commands: 'test')
+ stage: 'test')
end
render_views
diff --git a/spec/javascripts/fixtures/merge_requests.rb b/spec/javascripts/fixtures/merge_requests.rb
index 26e81f06c0b..eb37be87e1d 100644
--- a/spec/javascripts/fixtures/merge_requests.rb
+++ b/spec/javascripts/fixtures/merge_requests.rb
@@ -35,6 +35,7 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
before do
sign_in(admin)
+ allow(Discussion).to receive(:build_discussion_id).and_return(['discussionid:ceterumcenseo'])
end
after do
@@ -54,8 +55,10 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
end
it 'merge_requests/merged_merge_request.html.raw' do |example|
- allow_any_instance_of(MergeRequest).to receive(:source_branch_exists?).and_return(true)
- allow_any_instance_of(MergeRequest).to receive(:can_remove_source_branch?).and_return(true)
+ expect_next_instance_of(MergeRequest) do |merge_request|
+ allow(merge_request).to receive(:source_branch_exists?).and_return(true)
+ allow(merge_request).to receive(:can_remove_source_branch?).and_return(true)
+ end
render_merge_request(example.description, merged_merge_request)
end
diff --git a/spec/javascripts/fixtures/oauth_remember_me.html.haml b/spec/javascripts/fixtures/oauth_remember_me.html.haml
index 7886e995e57..a5d7c4e816a 100644
--- a/spec/javascripts/fixtures/oauth_remember_me.html.haml
+++ b/spec/javascripts/fixtures/oauth_remember_me.html.haml
@@ -3,3 +3,4 @@
%a.oauth-login.twitter{ href: "http://example.com/" }
%a.oauth-login.github{ href: "http://example.com/" }
+ %a.oauth-login.facebook{ href: "http://example.com/?redirect_fragment=L1" }
diff --git a/spec/javascripts/fixtures/projects.rb b/spec/javascripts/fixtures/projects.rb
index 9b48646f8f0..85f02923804 100644
--- a/spec/javascripts/fixtures/projects.rb
+++ b/spec/javascripts/fixtures/projects.rb
@@ -3,13 +3,13 @@ require 'spec_helper'
describe 'Projects (JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
+ runners_token = 'runnerstoken:intabulasreferre'
+
let(:admin) { create(:admin) }
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project, namespace: namespace, path: 'builds-project') }
+ let(:project) { create(:project, namespace: namespace, path: 'builds-project', runners_token: runners_token) }
let(:project_with_repo) { create(:project, :repository, description: 'Code and stuff') }
- let(:project_variable_populated) { create(:project, namespace: namespace, path: 'builds-project2') }
- let!(:variable1) { create(:ci_variable, project: project_variable_populated) }
- let!(:variable2) { create(:ci_variable, project: project_variable_populated) }
+ let(:project_variable_populated) { create(:project, namespace: namespace, path: 'builds-project2', runners_token: runners_token) }
render_views
@@ -20,6 +20,7 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
before do
project.add_maintainer(admin)
sign_in(admin)
+ allow(SecureRandom).to receive(:hex).and_return('securerandomhex:thereisnospoon')
end
after do
@@ -70,6 +71,9 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
end
it 'projects/ci_cd_settings_with_variables.html.raw' do |example|
+ create(:ci_variable, project: project_variable_populated)
+ create(:ci_variable, project: project_variable_populated)
+
get :show, params: {
namespace_id: project_variable_populated.namespace.to_param,
project_id: project_variable_populated
diff --git a/spec/javascripts/fixtures/sessions.rb b/spec/javascripts/fixtures/sessions.rb
new file mode 100644
index 00000000000..e90a58e8c54
--- /dev/null
+++ b/spec/javascripts/fixtures/sessions.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe 'Sessions (JavaScript fixtures)' do
+ include JavaScriptFixturesHelpers
+
+ before(:all) do
+ clean_frontend_fixtures('sessions/')
+ end
+
+ describe SessionsController, '(JavaScript fixtures)', type: :controller do
+ include DeviseHelpers
+
+ render_views
+
+ before do
+ set_devise_mapping(context: @request)
+ end
+
+ it 'sessions/new.html.raw' do |example|
+ get :new
+
+ expect(response).to be_success
+ store_frontend_fixture(response, example.description)
+ end
+ end
+end
diff --git a/spec/javascripts/fixtures/snippet.rb b/spec/javascripts/fixtures/snippet.rb
index a14837e4d4a..bcd6546f3df 100644
--- a/spec/javascripts/fixtures/snippet.rb
+++ b/spec/javascripts/fixtures/snippet.rb
@@ -7,7 +7,6 @@ describe SnippetsController, '(JavaScript fixtures)', type: :controller do
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace, path: 'branches-project') }
let(:snippet) { create(:personal_snippet, title: 'snippet.md', content: '# snippet', file_name: 'snippet.md', author: admin) }
- let!(:snippet_note) { create(:discussion_note_on_snippet, noteable: snippet, project: project, author: admin, note: '- [ ] Task List Item') }
render_views
@@ -17,6 +16,7 @@ describe SnippetsController, '(JavaScript fixtures)', type: :controller do
before do
sign_in(admin)
+ allow(Discussion).to receive(:build_discussion_id).and_return(['discussionid:ceterumcenseo'])
end
after do
@@ -24,6 +24,8 @@ describe SnippetsController, '(JavaScript fixtures)', type: :controller do
end
it 'snippets/show.html.raw' do |example|
+ create(:discussion_note_on_snippet, noteable: snippet, project: project, author: admin, note: '- [ ] Task List Item')
+
get(:show, params: { id: snippet.to_param })
expect(response).to be_success
diff --git a/spec/javascripts/fixtures/u2f.rb b/spec/javascripts/fixtures/u2f.rb
index f0aa874bf75..5cdbadef639 100644
--- a/spec/javascripts/fixtures/u2f.rb
+++ b/spec/javascripts/fixtures/u2f.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
context 'U2F' do
include JavaScriptFixturesHelpers
- let(:user) { create(:user, :two_factor_via_u2f) }
+ let(:user) { create(:user, :two_factor_via_u2f, otp_secret: 'otpsecret:coolkids') }
before(:all) do
clean_frontend_fixtures('u2f/')
@@ -33,6 +33,7 @@ context 'U2F' do
before do
sign_in(user)
+ allow_any_instance_of(Profiles::TwoFactorAuthsController).to receive(:build_qr_code).and_return('qrcode:blackandwhitesquares')
end
it 'u2f/register.html.raw' do |example|
diff --git a/spec/javascripts/gfm_auto_complete_spec.js b/spec/javascripts/gfm_auto_complete_spec.js
deleted file mode 100644
index 6f414c8ccf1..00000000000
--- a/spec/javascripts/gfm_auto_complete_spec.js
+++ /dev/null
@@ -1,208 +0,0 @@
-/* eslint no-param-reassign: "off" */
-
-import $ from 'jquery';
-import GfmAutoComplete from '~/gfm_auto_complete';
-
-import 'vendor/jquery.caret';
-import 'vendor/jquery.atwho';
-
-describe('GfmAutoComplete', function() {
- const gfmAutoCompleteCallbacks = GfmAutoComplete.prototype.getDefaultCallbacks.call({
- fetchData: () => {},
- });
-
- describe('DefaultOptions.sorter', function() {
- describe('assets loading', function() {
- beforeEach(function() {
- spyOn(GfmAutoComplete, 'isLoading').and.returnValue(true);
-
- this.atwhoInstance = { setting: {} };
- this.items = [];
-
- this.sorterValue = gfmAutoCompleteCallbacks.sorter.call(this.atwhoInstance, '', this.items);
- });
-
- it('should disable highlightFirst', function() {
- expect(this.atwhoInstance.setting.highlightFirst).toBe(false);
- });
-
- it('should return the passed unfiltered items', function() {
- expect(this.sorterValue).toEqual(this.items);
- });
- });
-
- describe('assets finished loading', function() {
- beforeEach(function() {
- spyOn(GfmAutoComplete, 'isLoading').and.returnValue(false);
- spyOn($.fn.atwho.default.callbacks, 'sorter');
- });
-
- it('should enable highlightFirst if alwaysHighlightFirst is set', function() {
- const atwhoInstance = { setting: { alwaysHighlightFirst: true } };
-
- gfmAutoCompleteCallbacks.sorter.call(atwhoInstance);
-
- expect(atwhoInstance.setting.highlightFirst).toBe(true);
- });
-
- it('should enable highlightFirst if a query is present', function() {
- const atwhoInstance = { setting: {} };
-
- gfmAutoCompleteCallbacks.sorter.call(atwhoInstance, 'query');
-
- expect(atwhoInstance.setting.highlightFirst).toBe(true);
- });
-
- it('should call the default atwho sorter', function() {
- const atwhoInstance = { setting: {} };
-
- const query = 'query';
- const items = [];
- const searchKey = 'searchKey';
-
- gfmAutoCompleteCallbacks.sorter.call(atwhoInstance, query, items, searchKey);
-
- expect($.fn.atwho.default.callbacks.sorter).toHaveBeenCalledWith(query, items, searchKey);
- });
- });
- });
-
- describe('DefaultOptions.beforeInsert', () => {
- const beforeInsert = (context, value) =>
- gfmAutoCompleteCallbacks.beforeInsert.call(context, value);
-
- const atwhoInstance = { setting: { skipSpecialCharacterTest: false } };
-
- it('should not quote if value only contains alphanumeric charecters', () => {
- expect(beforeInsert(atwhoInstance, '@user1')).toBe('@user1');
- expect(beforeInsert(atwhoInstance, '~label1')).toBe('~label1');
- });
-
- it('should quote if value contains any non-alphanumeric characters', () => {
- expect(beforeInsert(atwhoInstance, '~label-20')).toBe('~"label\\-20"');
- expect(beforeInsert(atwhoInstance, '~label 20')).toBe('~"label 20"');
- });
-
- it('should quote integer labels', () => {
- expect(beforeInsert(atwhoInstance, '~1234')).toBe('~"1234"');
- });
-
- it('should escape Markdown emphasis characters, except in the first character', () => {
- expect(beforeInsert(atwhoInstance, '@_group')).toEqual('@\\_group');
- expect(beforeInsert(atwhoInstance, '~_bug')).toEqual('~\\_bug');
- expect(beforeInsert(atwhoInstance, '~a `bug`')).toEqual('~"a \\`bug\\`"');
- expect(beforeInsert(atwhoInstance, '~a ~bug')).toEqual('~"a \\~bug"');
- expect(beforeInsert(atwhoInstance, '~a **bug')).toEqual('~"a \\*\\*bug"');
- });
- });
-
- describe('DefaultOptions.matcher', function() {
- const defaultMatcher = (context, flag, subtext) =>
- gfmAutoCompleteCallbacks.matcher.call(context, flag, subtext);
-
- const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%', '$'];
- const otherFlags = ['/', ':'];
- const flags = flagsUseDefaultMatcher.concat(otherFlags);
-
- const flagsHash = flags.reduce((hash, el) => {
- hash[el] = null;
- return hash;
- }, {});
- const atwhoInstance = { setting: {}, app: { controllers: flagsHash } };
-
- const minLen = 1;
- const maxLen = 20;
- const argumentSize = [minLen, maxLen / 2, maxLen];
-
- const allowedSymbols = [
- '',
- 'a',
- 'n',
- 'z',
- 'A',
- 'Z',
- 'N',
- '0',
- '5',
- '9',
- 'Ð',
- 'а',
- 'Я',
- 'Ñ',
- '.',
- "'",
- '+',
- '-',
- '_',
- ];
- const jointAllowedSymbols = allowedSymbols.join('');
-
- describe('should match regular symbols', () => {
- flagsUseDefaultMatcher.forEach(flag => {
- allowedSymbols.forEach(symbol => {
- argumentSize.forEach(size => {
- const query = new Array(size + 1).join(symbol);
- const subtext = flag + query;
-
- it(`matches argument "${flag}" with query "${subtext}"`, () => {
- expect(defaultMatcher(atwhoInstance, flag, subtext)).toBe(query);
- });
- });
- });
-
- it(`matches combination of allowed symbols for flag "${flag}"`, () => {
- const subtext = flag + jointAllowedSymbols;
-
- expect(defaultMatcher(atwhoInstance, flag, subtext)).toBe(jointAllowedSymbols);
- });
- });
- });
-
- describe('should not match special sequences', () => {
- const shouldNotBeFollowedBy = flags.concat(['\x00', '\x10', '\x3f', '\n', ' ']);
- const shouldNotBePrependedBy = ['`'];
-
- flagsUseDefaultMatcher.forEach(atSign => {
- shouldNotBeFollowedBy.forEach(followedSymbol => {
- const seq = atSign + followedSymbol;
-
- it(`should not match ${JSON.stringify(seq)}`, () => {
- expect(defaultMatcher(atwhoInstance, atSign, seq)).toBe(null);
- });
- });
-
- shouldNotBePrependedBy.forEach(prependedSymbol => {
- const seq = prependedSymbol + atSign;
-
- it(`should not match "${seq}"`, () => {
- expect(defaultMatcher(atwhoInstance, atSign, seq)).toBe(null);
- });
- });
- });
- });
- });
-
- describe('isLoading', function() {
- it('should be true with loading data object item', function() {
- expect(GfmAutoComplete.isLoading({ name: 'loading' })).toBe(true);
- });
-
- it('should be true with loading data array', function() {
- expect(GfmAutoComplete.isLoading(['loading'])).toBe(true);
- });
-
- it('should be true with loading data object array', function() {
- expect(GfmAutoComplete.isLoading([{ name: 'loading' }])).toBe(true);
- });
-
- it('should be false with actual array data', function() {
- expect(
- GfmAutoComplete.isLoading([{ title: 'Foo' }, { title: 'Bar' }, { title: 'Qux' }]),
- ).toBe(false);
- });
-
- it('should be false with actual data item', function() {
- expect(GfmAutoComplete.isLoading({ title: 'Foo' })).toBe(false);
- });
- });
-});
diff --git a/spec/javascripts/helpers/vue_test_utils_helper.js b/spec/javascripts/helpers/vue_test_utils_helper.js
new file mode 100644
index 00000000000..19e27388eeb
--- /dev/null
+++ b/spec/javascripts/helpers/vue_test_utils_helper.js
@@ -0,0 +1,19 @@
+/* eslint-disable import/prefer-default-export */
+
+const vNodeContainsText = (vnode, text) =>
+ (vnode.text && vnode.text.includes(text)) ||
+ (vnode.children && vnode.children.filter(child => vNodeContainsText(child, text)).length);
+
+/**
+ * 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
+ * was shallowMounted.
+ * NOTE: Prefer checking the rendered output of a component
+ * wherever possible using something like `text()` instead.
+ * @param {Wrapper} shallowWrapper - Vue test utils wrapper (shallowMounted)
+ * @param {String} slotName
+ * @param {String} text
+ */
+export const shallowWrapperContainsSlotText = (shallowWrapper, slotName, text) =>
+ !!shallowWrapper.vm.$slots[slotName].filter(vnode => vNodeContainsText(vnode, text)).length;
diff --git a/spec/javascripts/helpers/vue_test_utils_helper_spec.js b/spec/javascripts/helpers/vue_test_utils_helper_spec.js
new file mode 100644
index 00000000000..41714066da5
--- /dev/null
+++ b/spec/javascripts/helpers/vue_test_utils_helper_spec.js
@@ -0,0 +1,48 @@
+import { shallowMount } from '@vue/test-utils';
+import { shallowWrapperContainsSlotText } from './vue_test_utils_helper';
+
+describe('Vue test utils helpers', () => {
+ describe('shallowWrapperContainsSlotText', () => {
+ const mockText = 'text';
+ const mockSlot = `<div>${mockText}</div>`;
+ let mockComponent;
+
+ beforeEach(() => {
+ mockComponent = shallowMount(
+ {
+ render(h) {
+ h(`<div>mockedComponent</div>`);
+ },
+ },
+ {
+ slots: {
+ default: mockText,
+ namedSlot: mockSlot,
+ },
+ },
+ );
+ });
+
+ it('finds text within shallowWrapper default slot', () => {
+ expect(shallowWrapperContainsSlotText(mockComponent, 'default', mockText)).toBe(true);
+ });
+
+ it('finds text within shallowWrapper named slot', () => {
+ expect(shallowWrapperContainsSlotText(mockComponent, 'namedSlot', mockText)).toBe(true);
+ });
+
+ it('returns false when text is not present', () => {
+ const searchText = 'absent';
+
+ expect(shallowWrapperContainsSlotText(mockComponent, 'default', searchText)).toBe(false);
+ expect(shallowWrapperContainsSlotText(mockComponent, 'namedSlot', searchText)).toBe(false);
+ });
+
+ it('searches with case-sensitivity', () => {
+ const searchText = mockText.toUpperCase();
+
+ expect(shallowWrapperContainsSlotText(mockComponent, 'default', searchText)).toBe(false);
+ expect(shallowWrapperContainsSlotText(mockComponent, 'namedSlot', searchText)).toBe(false);
+ });
+ });
+});
diff --git a/spec/javascripts/helpers/vuex_action_helper.js b/spec/javascripts/helpers/vuex_action_helper.js
index 1972408356e..88652202a8e 100644
--- a/spec/javascripts/helpers/vuex_action_helper.js
+++ b/spec/javascripts/helpers/vuex_action_helper.js
@@ -84,7 +84,10 @@ export default (
done();
};
- const result = action({ commit, state, dispatch, rootState: state, rootGetters: state }, payload);
+ const result = action(
+ { commit, state, dispatch, rootState: state, rootGetters: state, getters: state },
+ payload,
+ );
return new Promise(resolve => {
setImmediate(resolve);
diff --git a/spec/javascripts/ide/components/file_finder/index_spec.js b/spec/javascripts/ide/components/file_finder/index_spec.js
deleted file mode 100644
index 4d934f92f72..00000000000
--- a/spec/javascripts/ide/components/file_finder/index_spec.js
+++ /dev/null
@@ -1,305 +0,0 @@
-import Vue from 'vue';
-import store from '~/ide/stores';
-import FindFileComponent from '~/ide/components/file_finder/index.vue';
-import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
-import router from '~/ide/ide_router';
-import { file, resetStore } from '../../helpers';
-import { mountComponentWithStore } from '../../../helpers/vue_mount_component_helper';
-
-describe('IDE File finder item spec', () => {
- const Component = Vue.extend(FindFileComponent);
- let vm;
-
- beforeEach(done => {
- setFixtures('<div id="app"></div>');
-
- vm = mountComponentWithStore(Component, {
- store,
- el: '#app',
- props: {
- index: 0,
- },
- });
-
- setTimeout(done);
- });
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- describe('with entries', () => {
- beforeEach(done => {
- Vue.set(vm.$store.state.entries, 'folder', {
- ...file('folder'),
- path: 'folder',
- type: 'folder',
- });
-
- Vue.set(vm.$store.state.entries, 'index.js', {
- ...file('index.js'),
- path: 'index.js',
- type: 'blob',
- url: '/index.jsurl',
- });
-
- Vue.set(vm.$store.state.entries, 'component.js', {
- ...file('component.js'),
- path: 'component.js',
- type: 'blob',
- });
-
- setTimeout(done);
- });
-
- it('renders list of blobs', () => {
- expect(vm.$el.textContent).toContain('index.js');
- expect(vm.$el.textContent).toContain('component.js');
- expect(vm.$el.textContent).not.toContain('folder');
- });
-
- it('filters entries', done => {
- vm.searchText = 'index';
-
- vm.$nextTick(() => {
- expect(vm.$el.textContent).toContain('index.js');
- expect(vm.$el.textContent).not.toContain('component.js');
-
- done();
- });
- });
-
- it('shows clear button when searchText is not empty', done => {
- vm.searchText = 'index';
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.dropdown-input-clear').classList).toContain('show');
- expect(vm.$el.querySelector('.dropdown-input-search').classList).toContain('hidden');
-
- done();
- });
- });
-
- it('clear button resets searchText', done => {
- vm.searchText = 'index';
-
- vm.$nextTick()
- .then(() => {
- vm.$el.querySelector('.dropdown-input-clear').click();
- })
- .then(vm.$nextTick)
- .then(() => {
- expect(vm.searchText).toBe('');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('clear button focues search input', done => {
- spyOn(vm.$refs.searchInput, 'focus');
- vm.searchText = 'index';
-
- vm.$nextTick()
- .then(() => {
- vm.$el.querySelector('.dropdown-input-clear').click();
- })
- .then(vm.$nextTick)
- .then(() => {
- expect(vm.$refs.searchInput.focus).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
-
- describe('listShowCount', () => {
- it('returns 1 when no filtered entries exist', done => {
- vm.searchText = 'testing 123';
-
- vm.$nextTick(() => {
- expect(vm.listShowCount).toBe(1);
-
- done();
- });
- });
-
- it('returns entries length when not filtered', () => {
- expect(vm.listShowCount).toBe(2);
- });
- });
-
- describe('listHeight', () => {
- it('returns 55 when entries exist', () => {
- expect(vm.listHeight).toBe(55);
- });
-
- it('returns 33 when entries dont exist', done => {
- vm.searchText = 'testing 123';
-
- vm.$nextTick(() => {
- expect(vm.listHeight).toBe(33);
-
- done();
- });
- });
- });
-
- describe('filteredBlobsLength', () => {
- it('returns length of filtered blobs', done => {
- vm.searchText = 'index';
-
- vm.$nextTick(() => {
- expect(vm.filteredBlobsLength).toBe(1);
-
- done();
- });
- });
- });
-
- describe('watches', () => {
- describe('searchText', () => {
- it('resets focusedIndex when updated', done => {
- vm.focusedIndex = 1;
- vm.searchText = 'test';
-
- vm.$nextTick(() => {
- expect(vm.focusedIndex).toBe(0);
-
- done();
- });
- });
- });
-
- describe('fileFindVisible', () => {
- it('returns searchText when false', done => {
- vm.searchText = 'test';
- vm.$store.state.fileFindVisible = true;
-
- vm.$nextTick()
- .then(() => {
- vm.$store.state.fileFindVisible = false;
- })
- .then(vm.$nextTick)
- .then(() => {
- expect(vm.searchText).toBe('');
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-
- describe('openFile', () => {
- beforeEach(() => {
- spyOn(router, 'push');
- spyOn(vm, 'toggleFileFinder');
- });
-
- it('closes file finder', () => {
- vm.openFile(vm.$store.state.entries['index.js']);
-
- expect(vm.toggleFileFinder).toHaveBeenCalled();
- });
-
- it('pushes to router', () => {
- vm.openFile(vm.$store.state.entries['index.js']);
-
- expect(router.push).toHaveBeenCalledWith('/project/index.jsurl');
- });
- });
-
- describe('onKeyup', () => {
- it('opens file on enter key', done => {
- const event = new CustomEvent('keyup');
- event.keyCode = ENTER_KEY_CODE;
-
- spyOn(vm, 'openFile');
-
- vm.$refs.searchInput.dispatchEvent(event);
-
- vm.$nextTick(() => {
- expect(vm.openFile).toHaveBeenCalledWith(vm.$store.state.entries['index.js']);
-
- done();
- });
- });
-
- it('closes file finder on esc key', done => {
- const event = new CustomEvent('keyup');
- event.keyCode = ESC_KEY_CODE;
-
- spyOn(vm, 'toggleFileFinder');
-
- vm.$refs.searchInput.dispatchEvent(event);
-
- vm.$nextTick(() => {
- expect(vm.toggleFileFinder).toHaveBeenCalled();
-
- done();
- });
- });
- });
-
- describe('onKeyDown', () => {
- let el;
-
- beforeEach(() => {
- el = vm.$refs.searchInput;
- });
-
- describe('up key', () => {
- const event = new CustomEvent('keydown');
- event.keyCode = UP_KEY_CODE;
-
- it('resets to last index when at top', () => {
- el.dispatchEvent(event);
-
- expect(vm.focusedIndex).toBe(1);
- });
-
- it('minus 1 from focusedIndex', () => {
- vm.focusedIndex = 1;
-
- el.dispatchEvent(event);
-
- expect(vm.focusedIndex).toBe(0);
- });
- });
-
- describe('down key', () => {
- const event = new CustomEvent('keydown');
- event.keyCode = DOWN_KEY_CODE;
-
- it('resets to first index when at bottom', () => {
- vm.focusedIndex = 1;
- el.dispatchEvent(event);
-
- expect(vm.focusedIndex).toBe(0);
- });
-
- it('adds 1 to focusedIndex', () => {
- el.dispatchEvent(event);
-
- expect(vm.focusedIndex).toBe(1);
- });
- });
- });
- });
-
- describe('without entries', () => {
- it('renders loading text when loading', done => {
- store.state.loading = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.textContent).toContain('Loading...');
-
- done();
- });
- });
-
- it('renders no files text', () => {
- expect(vm.$el.textContent).toContain('No files found.');
- });
- });
-});
diff --git a/spec/javascripts/ide/components/file_finder/item_spec.js b/spec/javascripts/ide/components/file_finder/item_spec.js
deleted file mode 100644
index 0f1116c6912..00000000000
--- a/spec/javascripts/ide/components/file_finder/item_spec.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import Vue from 'vue';
-import ItemComponent from '~/ide/components/file_finder/item.vue';
-import { file } from '../../helpers';
-import createComponent from '../../../helpers/vue_mount_component_helper';
-
-describe('IDE File finder item spec', () => {
- const Component = Vue.extend(ItemComponent);
- let vm;
- let localFile;
-
- beforeEach(() => {
- localFile = {
- ...file(),
- name: 'test file',
- path: 'test/file',
- };
-
- vm = createComponent(Component, {
- file: localFile,
- focused: true,
- searchText: '',
- index: 0,
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders file name & path', () => {
- expect(vm.$el.textContent).toContain('test file');
- expect(vm.$el.textContent).toContain('test/file');
- });
-
- describe('focused', () => {
- it('adds is-focused class', () => {
- expect(vm.$el.classList).toContain('is-focused');
- });
-
- it('does not have is-focused class when not focused', done => {
- vm.focused = false;
-
- vm.$nextTick(() => {
- expect(vm.$el.classList).not.toContain('is-focused');
-
- done();
- });
- });
- });
-
- describe('changed file icon', () => {
- it('does not render when not a changed or temp file', () => {
- expect(vm.$el.querySelector('.diff-changed-stats')).toBe(null);
- });
-
- it('renders when a changed file', done => {
- vm.file.changed = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
-
- done();
- });
- });
-
- it('renders when a temp file', done => {
- vm.file.tempFile = true;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
-
- done();
- });
- });
- });
-
- it('emits event when clicked', () => {
- spyOn(vm, '$emit');
-
- vm.$el.click();
-
- expect(vm.$emit).toHaveBeenCalledWith('click', vm.file);
- });
-
- describe('path', () => {
- let el;
-
- beforeEach(done => {
- vm.searchText = 'file';
-
- el = vm.$el.querySelector('.diff-changed-file-path');
-
- vm.$nextTick(done);
- });
-
- it('highlights text', () => {
- expect(el.querySelectorAll('.highlighted').length).toBe(4);
- });
-
- it('adds ellipsis to long text', done => {
- vm.file.path = new Array(70)
- .fill()
- .map((_, i) => `${i}-`)
- .join('');
-
- vm.$nextTick(() => {
- expect(el.textContent).toBe(`...${vm.file.path.substr(vm.file.path.length - 60)}`);
- done();
- });
- });
- });
-
- describe('name', () => {
- let el;
-
- beforeEach(done => {
- vm.searchText = 'file';
-
- el = vm.$el.querySelector('.diff-changed-file-name');
-
- vm.$nextTick(done);
- });
-
- it('highlights text', () => {
- expect(el.querySelectorAll('.highlighted').length).toBe(4);
- });
-
- it('does not add ellipsis to long text', done => {
- vm.file.name = new Array(70)
- .fill()
- .map((_, i) => `${i}-`)
- .join('');
-
- vm.$nextTick(() => {
- expect(el.textContent).not.toBe(`...${vm.file.name.substr(vm.file.name.length - 60)}`);
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/ide/components/ide_spec.js b/spec/javascripts/ide/components/ide_spec.js
index 55f40be0e4e..dc5790f6562 100644
--- a/spec/javascripts/ide/components/ide_spec.js
+++ b/spec/javascripts/ide/components/ide_spec.js
@@ -1,5 +1,4 @@
import Vue from 'vue';
-import Mousetrap from 'mousetrap';
import store from '~/ide/stores';
import ide from '~/ide/components/ide.vue';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
@@ -72,73 +71,6 @@ describe('ide component', () => {
});
});
- describe('file finder', () => {
- beforeEach(done => {
- spyOn(vm, 'toggleFileFinder');
-
- vm.$store.state.fileFindVisible = true;
-
- vm.$nextTick(done);
- });
-
- it('calls toggleFileFinder on `t` key press', done => {
- Mousetrap.trigger('t');
-
- vm.$nextTick()
- .then(() => {
- expect(vm.toggleFileFinder).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('calls toggleFileFinder on `command+p` key press', done => {
- Mousetrap.trigger('command+p');
-
- vm.$nextTick()
- .then(() => {
- expect(vm.toggleFileFinder).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('calls toggleFileFinder on `ctrl+p` key press', done => {
- Mousetrap.trigger('ctrl+p');
-
- vm.$nextTick()
- .then(() => {
- expect(vm.toggleFileFinder).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('always allows `command+p` to trigger toggleFileFinder', () => {
- expect(
- vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 'command+p'),
- ).toBe(false);
- });
-
- it('always allows `ctrl+p` to trigger toggleFileFinder', () => {
- expect(
- vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 'ctrl+p'),
- ).toBe(false);
- });
-
- it('onlys handles `t` when focused in input-field', () => {
- expect(
- vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 't'),
- ).toBe(true);
- });
-
- it('stops callback in monaco editor', () => {
- setFixtures('<div class="inputarea"></div>');
-
- expect(vm.mousetrapStopCallback(null, document.querySelector('.inputarea'), 't')).toBe(true);
- });
- });
-
it('shows error message when set', done => {
expect(vm.$el.querySelector('.flash-container')).toBe(null);
diff --git a/spec/javascripts/ide/components/ide_status_bar_spec.js b/spec/javascripts/ide/components/ide_status_bar_spec.js
index ab032b4cb98..bb8fb74c068 100644
--- a/spec/javascripts/ide/components/ide_status_bar_spec.js
+++ b/spec/javascripts/ide/components/ide_status_bar_spec.js
@@ -76,6 +76,9 @@ describe('ideStatusBar', () => {
icon: 'status_success',
},
},
+ commit: {
+ author_gravatar_url: 'www',
+ },
});
vm.$nextTick()
diff --git a/spec/javascripts/ide/components/new_dropdown/modal_spec.js b/spec/javascripts/ide/components/new_dropdown/modal_spec.js
index 595a2f927e9..d1a0964ccdd 100644
--- a/spec/javascripts/ide/components/new_dropdown/modal_spec.js
+++ b/spec/javascripts/ide/components/new_dropdown/modal_spec.js
@@ -18,6 +18,9 @@ describe('new file modal component', () => {
store.state.entryModal = {
type,
path: '',
+ entry: {
+ path: '',
+ },
};
vm = createComponentWithStore(Component, store).$mount();
@@ -41,6 +44,15 @@ describe('new file modal component', () => {
expect(vm.$el.querySelector('.label-bold').textContent.trim()).toBe('Name');
});
+ it(`${type === 'tree' ? 'does not show' : 'shows'} file templates`, () => {
+ const templateFilesEl = vm.$el.querySelector('.file-templates');
+ if (type === 'tree') {
+ expect(templateFilesEl).toBeNull();
+ } else {
+ expect(templateFilesEl instanceof Element).toBeTruthy();
+ }
+ });
+
describe('createEntryInStore', () => {
it('$emits create', () => {
spyOn(vm, 'createTempEntry');
@@ -65,6 +77,7 @@ describe('new file modal component', () => {
entry: {
name: 'test',
type: 'blob',
+ path: 'test-path',
},
};
@@ -88,7 +101,7 @@ describe('new file modal component', () => {
describe('entryName', () => {
it('returns entries name', () => {
- expect(vm.entryName).toBe('test');
+ expect(vm.entryName).toBe('test-path');
});
it('updated name', () => {
@@ -98,4 +111,53 @@ describe('new file modal component', () => {
});
});
});
+
+ describe('submitForm', () => {
+ it('throws an error when target entry exists', () => {
+ const store = createStore();
+ store.state.entryModal = {
+ type: 'rename',
+ path: 'test-path/test',
+ entry: {
+ name: 'test',
+ type: 'blob',
+ path: 'test-path/test',
+ },
+ };
+ store.state.entries = {
+ 'test-path/test': {
+ name: 'test',
+ deleted: false,
+ },
+ };
+
+ vm = createComponentWithStore(Component, store).$mount();
+ const flashSpy = spyOnDependency(modal, 'flash');
+ vm.submitForm();
+
+ expect(flashSpy).toHaveBeenCalled();
+ });
+
+ it('calls createTempEntry when target path does not exist', () => {
+ const store = createStore();
+ store.state.entryModal = {
+ type: 'rename',
+ path: 'test-path/test',
+ entry: {
+ name: 'test',
+ type: 'blob',
+ path: 'test-path1/test',
+ },
+ };
+
+ vm = createComponentWithStore(Component, store).$mount();
+ spyOn(vm, 'createTempEntry').and.callFake(() => Promise.resolve());
+ vm.submitForm();
+
+ expect(vm.createTempEntry).toHaveBeenCalledWith({
+ name: 'test-path1',
+ type: 'tree',
+ });
+ });
+ });
});
diff --git a/spec/javascripts/ide/lib/decorations/controller_spec.js b/spec/javascripts/ide/lib/decorations/controller_spec.js
index a112361e0d1..4118774cca3 100644
--- a/spec/javascripts/ide/lib/decorations/controller_spec.js
+++ b/spec/javascripts/ide/lib/decorations/controller_spec.js
@@ -56,7 +56,7 @@ describe('Multi-file editor library decorations controller', () => {
controller.addDecorations(model, 'key', [{ decoration: 'decorationValue' }]);
expect(controller.decorations.size).toBe(1);
- expect(controller.decorations.keys().next().value).toBe('path--path');
+ expect(controller.decorations.keys().next().value).toBe('gitlab:path--path');
});
it('calls decorate method', () => {
@@ -90,7 +90,7 @@ describe('Multi-file editor library decorations controller', () => {
controller.decorate(model);
- expect(controller.editorDecorations.keys().next().value).toBe('path--path');
+ expect(controller.editorDecorations.keys().next().value).toBe('gitlab:path--path');
});
});
diff --git a/spec/javascripts/ide/lib/files_spec.js b/spec/javascripts/ide/lib/files_spec.js
new file mode 100644
index 00000000000..fe791aa2b74
--- /dev/null
+++ b/spec/javascripts/ide/lib/files_spec.js
@@ -0,0 +1,77 @@
+import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
+import { decorateFiles, splitParent } from '~/ide/lib/files';
+import { decorateData } from '~/ide/stores/utils';
+
+const TEST_BRANCH_ID = 'lorem-ipsum';
+const TEST_PROJECT_ID = 10;
+
+const createEntries = paths => {
+ const createEntry = (acc, { path, type, children }) => {
+ // Sometimes we need to end the url with a '/'
+ const createUrl = base => (type === 'tree' ? `${base}/` : base);
+
+ const { name, parent } = splitParent(path);
+ const parentEntry = acc[parent];
+
+ acc[path] = {
+ ...decorateData({
+ projectId: TEST_PROJECT_ID,
+ branchId: TEST_BRANCH_ID,
+ id: path,
+ name,
+ path,
+ url: createUrl(`/${TEST_PROJECT_ID}/${type}/${TEST_BRANCH_ID}/-/${path}`),
+ type,
+ previewMode: viewerInformationForPath(path),
+ parentPath: parent,
+ parentTreeUrl: parentEntry
+ ? parentEntry.url
+ : createUrl(`/${TEST_PROJECT_ID}/${type}/${TEST_BRANCH_ID}`),
+ }),
+ tree: children.map(childName => jasmine.objectContaining({ name: childName })),
+ };
+
+ return acc;
+ };
+
+ const entries = paths.reduce(createEntry, {});
+
+ // Wrap entries in jasmine.objectContaining.
+ // We couldn't do this earlier because we still need to select properties from parent entries.
+ return Object.keys(entries).reduce((acc, key) => {
+ acc[key] = jasmine.objectContaining(entries[key]);
+
+ return acc;
+ }, {});
+};
+
+describe('IDE lib decorate files', () => {
+ it('creates entries and treeList', () => {
+ const data = ['app/assets/apples/foo.js', 'app/bugs.js', 'README.md'];
+ const expectedEntries = createEntries([
+ { path: 'app', type: 'tree', children: ['assets', 'bugs.js'] },
+ { path: 'app/assets', type: 'tree', children: ['apples'] },
+ { path: 'app/assets/apples', type: 'tree', children: ['foo.js'] },
+ { path: 'app/assets/apples/foo.js', type: 'blob', children: [] },
+ { path: 'app/bugs.js', type: 'blob', children: [] },
+ { path: 'README.md', type: 'blob', children: [] },
+ ]);
+
+ const { entries, treeList } = decorateFiles({
+ data,
+ branchId: TEST_BRANCH_ID,
+ projectId: TEST_PROJECT_ID,
+ });
+
+ // Here we test the keys and then each key/value individually because `expect(entries).toEqual(expectedEntries)`
+ // was taking a very long time for some reason. Probably due to large objects and nested `jasmine.objectContaining`.
+ const entryKeys = Object.keys(entries);
+
+ expect(entryKeys).toEqual(Object.keys(expectedEntries));
+ entryKeys.forEach(key => {
+ expect(entries[key]).toEqual(expectedEntries[key]);
+ });
+
+ expect(treeList).toEqual([expectedEntries.app, expectedEntries['README.md']]);
+ });
+});
diff --git a/spec/javascripts/ide/stores/actions/merge_request_spec.js b/spec/javascripts/ide/stores/actions/merge_request_spec.js
index 9bfc7c397b8..a5839630657 100644
--- a/spec/javascripts/ide/stores/actions/merge_request_spec.js
+++ b/spec/javascripts/ide/stores/actions/merge_request_spec.js
@@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import store from '~/ide/stores';
import actions, {
+ getMergeRequestsForBranch,
getMergeRequestData,
getMergeRequestChanges,
getMergeRequestVersions,
@@ -27,6 +28,98 @@ describe('IDE store merge request actions', () => {
resetStore(store);
});
+ describe('getMergeRequestsForBranch', () => {
+ describe('success', () => {
+ const mrData = { iid: 2, source_branch: 'bar' };
+ const mockData = [mrData];
+
+ describe('base case', () => {
+ beforeEach(() => {
+ spyOn(service, 'getProjectMergeRequests').and.callThrough();
+ mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).reply(200, mockData);
+ });
+
+ it('calls getProjectMergeRequests service method', done => {
+ store
+ .dispatch('getMergeRequestsForBranch', { projectId: 'abcproject', branchId: 'bar' })
+ .then(() => {
+ expect(service.getProjectMergeRequests).toHaveBeenCalledWith('abcproject', {
+ source_branch: 'bar',
+ order_by: 'created_at',
+ per_page: 1,
+ });
+
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('sets the "Merge Request" Object', done => {
+ store
+ .dispatch('getMergeRequestsForBranch', { projectId: 'abcproject', branchId: 'bar' })
+ .then(() => {
+ expect(Object.keys(store.state.projects.abcproject.mergeRequests).length).toEqual(1);
+ expect(Object.keys(store.state.projects.abcproject.mergeRequests)[0]).toEqual('2');
+ expect(store.state.projects.abcproject.mergeRequests[2]).toEqual(
+ jasmine.objectContaining(mrData),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('sets "Current Merge Request" object to the most recent MR', done => {
+ store
+ .dispatch('getMergeRequestsForBranch', { projectId: 'abcproject', branchId: 'bar' })
+ .then(() => {
+ expect(store.state.currentMergeRequestId).toEqual('2');
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('no merge requests for branch available case', () => {
+ beforeEach(() => {
+ spyOn(service, 'getProjectMergeRequests').and.callThrough();
+ mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).reply(200, []);
+ });
+
+ it('does not fail if there are no merge requests for current branch', done => {
+ store
+ .dispatch('getMergeRequestsForBranch', { projectId: 'abcproject', branchId: 'foo' })
+ .then(() => {
+ expect(Object.keys(store.state.projects.abcproject.mergeRequests).length).toEqual(0);
+ expect(store.state.currentMergeRequestId).toEqual('');
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+ });
+
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).networkError();
+ });
+
+ it('flashes message, if error', done => {
+ const flashSpy = spyOnDependency(actions, 'flash');
+
+ getMergeRequestsForBranch({ commit() {} }, { projectId: 'abcproject', branchId: 'bar' })
+ .then(() => {
+ fail('Expected getMergeRequestsForBranch to throw an error');
+ })
+ .catch(() => {
+ expect(flashSpy).toHaveBeenCalled();
+ expect(flashSpy.calls.argsFor(0)[0]).toEqual('Error fetching merge requests for bar');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+ });
+
describe('getMergeRequestData', () => {
describe('success', () => {
beforeEach(() => {
diff --git a/spec/javascripts/ide/stores/actions/project_spec.js b/spec/javascripts/ide/stores/actions/project_spec.js
index 7d8c9edd965..7b0963713fb 100644
--- a/spec/javascripts/ide/stores/actions/project_spec.js
+++ b/spec/javascripts/ide/stores/actions/project_spec.js
@@ -249,6 +249,7 @@ describe('IDE store project actions', () => {
['setCurrentBranchId', branch.branchId],
['getBranchData', branch],
['getFiles', branch],
+ ['getMergeRequestsForBranch', branch],
]);
})
.then(done)
diff --git a/spec/javascripts/ide/stores/actions/tree_spec.js b/spec/javascripts/ide/stores/actions/tree_spec.js
index bd41e87bf0e..fbb676aab33 100644
--- a/spec/javascripts/ide/stores/actions/tree_spec.js
+++ b/spec/javascripts/ide/stores/actions/tree_spec.js
@@ -20,6 +20,7 @@ describe('Multi-file store tree actions', () => {
};
beforeEach(() => {
+ jasmine.clock().install();
spyOn(router, 'push');
mock = new MockAdapter(axios);
@@ -37,6 +38,7 @@ describe('Multi-file store tree actions', () => {
});
afterEach(() => {
+ jasmine.clock().uninstall();
mock.restore();
resetStore(store);
});
@@ -70,6 +72,11 @@ describe('Multi-file store tree actions', () => {
store
.dispatch('getFiles', basicCallParameters)
.then(() => {
+ // The populating of the tree is deferred for performance reasons.
+ // See this merge request for details: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/25700
+ jasmine.clock().tick(1);
+ })
+ .then(() => {
projectTree = store.state.trees['abcproject/master'];
expect(projectTree.tree.length).toBe(2);
diff --git a/spec/javascripts/ide/stores/actions_spec.js b/spec/javascripts/ide/stores/actions_spec.js
index df291ade3f7..0b5587d02ae 100644
--- a/spec/javascripts/ide/stores/actions_spec.js
+++ b/spec/javascripts/ide/stores/actions_spec.js
@@ -499,12 +499,12 @@ describe('Multi-file store actions', () => {
testAction(
renameEntry,
- { path: 'test', name: 'new-name' },
+ { path: 'test', name: 'new-name', entryPath: null, parentPath: 'parent-path' },
store.state,
[
{
type: types.RENAME_ENTRY,
- payload: { path: 'test', name: 'new-name', entryPath: null },
+ payload: { path: 'test', name: 'new-name', entryPath: null, parentPath: 'parent-path' },
},
],
[{ type: 'deleteEntry', payload: 'test' }],
@@ -527,17 +527,33 @@ describe('Multi-file store actions', () => {
testAction(
renameEntry,
- { path: 'test', name: 'new-name' },
+ { path: 'test', name: 'new-name', parentPath: 'parent-path' },
store.state,
[
{
type: types.RENAME_ENTRY,
- payload: { path: 'test', name: 'new-name', entryPath: null },
+ payload: { path: 'test', name: 'new-name', entryPath: null, parentPath: 'parent-path' },
},
],
[
- { type: 'renameEntry', payload: { path: 'test', name: 'new-name', entryPath: 'tree-1' } },
- { type: 'renameEntry', payload: { path: 'test', name: 'new-name', entryPath: 'tree-2' } },
+ {
+ type: 'renameEntry',
+ payload: {
+ path: 'test',
+ name: 'new-name',
+ entryPath: 'tree-1',
+ parentPath: 'parent-path/new-name',
+ },
+ },
+ {
+ type: 'renameEntry',
+ payload: {
+ path: 'test',
+ name: 'new-name',
+ entryPath: 'tree-2',
+ parentPath: 'parent-path/new-name',
+ },
+ },
{ type: 'deleteEntry', payload: 'test' },
],
done,
diff --git a/spec/javascripts/ide/stores/mutations_spec.js b/spec/javascripts/ide/stores/mutations_spec.js
index 41dd3d3c67f..5ee098bf17f 100644
--- a/spec/javascripts/ide/stores/mutations_spec.js
+++ b/spec/javascripts/ide/stores/mutations_spec.js
@@ -298,7 +298,12 @@ describe('Multi-file store mutations', () => {
});
it('creates new renamed entry', () => {
- mutations.RENAME_ENTRY(localState, { path: 'oldPath', name: 'newPath' });
+ mutations.RENAME_ENTRY(localState, {
+ path: 'oldPath',
+ name: 'newPath',
+ entryPath: null,
+ parentPath: '',
+ });
expect(localState.entries.newPath).toEqual({
...localState.entries.oldPath,
@@ -335,7 +340,12 @@ describe('Multi-file store mutations', () => {
...file(),
};
- mutations.RENAME_ENTRY(localState, { path: 'oldPath', name: 'newPath' });
+ mutations.RENAME_ENTRY(localState, {
+ path: 'oldPath',
+ name: 'newPath',
+ entryPath: null,
+ parentPath: 'parentPath',
+ });
expect(localState.entries.parentPath.tree.length).toBe(1);
});
diff --git a/spec/javascripts/import_projects/components/import_projects_table_spec.js b/spec/javascripts/import_projects/components/import_projects_table_spec.js
new file mode 100644
index 00000000000..ab8642bf0dd
--- /dev/null
+++ b/spec/javascripts/import_projects/components/import_projects_table_spec.js
@@ -0,0 +1,188 @@
+import Vue from 'vue';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import createStore from '~/import_projects/store';
+import importProjectsTable from '~/import_projects/components/import_projects_table.vue';
+import STATUS_MAP from '~/import_projects/constants';
+import setTimeoutPromise from '../../helpers/set_timeout_promise_helper';
+
+describe('ImportProjectsTable', () => {
+ let vm;
+ let mock;
+ let store;
+ const reposPath = '/repos-path';
+ const jobsPath = '/jobs-path';
+ const providerTitle = 'THE PROVIDER';
+ const providerRepo = { id: 10, sanitizedName: 'sanitizedName', fullName: 'fullName' };
+ const importedProject = {
+ id: 1,
+ fullPath: 'fullPath',
+ importStatus: 'started',
+ providerLink: 'providerLink',
+ importSource: 'importSource',
+ };
+
+ function createComponent() {
+ const ImportProjectsTable = Vue.extend(importProjectsTable);
+
+ const component = new ImportProjectsTable({
+ store,
+ propsData: {
+ providerTitle,
+ },
+ }).$mount();
+
+ store.dispatch('stopJobsPolling');
+
+ return component;
+ }
+
+ beforeEach(() => {
+ store = createStore();
+ store.dispatch('setInitialData', { reposPath });
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ mock.restore();
+ });
+
+ it('renders a loading icon whilst repos are loading', done => {
+ mock.restore(); // Stop the mock adapter from responding to the request, keeping the spinner up
+
+ vm = createComponent();
+
+ setTimeoutPromise()
+ .then(() => {
+ expect(vm.$el.querySelector('.js-loading-button-icon')).not.toBeNull();
+ })
+ .then(() => done())
+ .catch(() => done.fail());
+ });
+
+ it('renders a table with imported projects and provider repos', done => {
+ const response = {
+ importedProjects: [importedProject],
+ providerRepos: [providerRepo],
+ namespaces: [{ path: 'path' }],
+ };
+ mock.onGet(reposPath).reply(200, response);
+
+ vm = createComponent();
+
+ setTimeoutPromise()
+ .then(() => {
+ expect(vm.$el.querySelector('.js-loading-button-icon')).toBeNull();
+ expect(vm.$el.querySelector('.table')).not.toBeNull();
+ expect(vm.$el.querySelector('.import-jobs-from-col').innerText).toMatch(
+ `From ${providerTitle}`,
+ );
+
+ expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-provider-repo')).not.toBeNull();
+ })
+ .then(() => done())
+ .catch(() => done.fail());
+ });
+
+ it('renders an empty state if there are no imported projects or provider repos', done => {
+ const response = {
+ importedProjects: [],
+ providerRepos: [],
+ namespaces: [],
+ };
+ mock.onGet(reposPath).reply(200, response);
+
+ vm = createComponent();
+
+ setTimeoutPromise()
+ .then(() => {
+ expect(vm.$el.querySelector('.js-loading-button-icon')).toBeNull();
+ expect(vm.$el.querySelector('.table')).toBeNull();
+ expect(vm.$el.innerText).toMatch(`No ${providerTitle} repositories available to import`);
+ })
+ .then(() => done())
+ .catch(() => done.fail());
+ });
+
+ it('imports provider repos if bulk import button is clicked', done => {
+ const importPath = '/import-path';
+ const response = {
+ importedProjects: [],
+ providerRepos: [providerRepo],
+ namespaces: [{ path: 'path' }],
+ };
+
+ mock.onGet(reposPath).replyOnce(200, response);
+ mock.onPost(importPath).replyOnce(200, importedProject);
+
+ store.dispatch('setInitialData', { importPath });
+
+ vm = createComponent();
+
+ setTimeoutPromise()
+ .then(() => {
+ expect(vm.$el.querySelector('.js-imported-project')).toBeNull();
+ expect(vm.$el.querySelector('.js-provider-repo')).not.toBeNull();
+
+ vm.$el.querySelector('.js-import-all').click();
+ })
+ .then(() => setTimeoutPromise())
+ .then(() => {
+ expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-provider-repo')).toBeNull();
+ })
+ .then(() => done())
+ .catch(() => done.fail());
+ });
+
+ it('polls to update the status of imported projects', done => {
+ const importPath = '/import-path';
+ const response = {
+ importedProjects: [importedProject],
+ providerRepos: [],
+ namespaces: [{ path: 'path' }],
+ };
+ const updatedProjects = [
+ {
+ id: importedProject.id,
+ importStatus: 'finished',
+ },
+ ];
+
+ mock.onGet(reposPath).replyOnce(200, response);
+
+ store.dispatch('setInitialData', { importPath, jobsPath });
+
+ vm = createComponent();
+
+ setTimeoutPromise()
+ .then(() => {
+ const statusObject = STATUS_MAP[importedProject.importStatus];
+
+ expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
+ expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
+ statusObject.text,
+ );
+
+ expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
+
+ mock.onGet(jobsPath).replyOnce(200, updatedProjects);
+ return store.dispatch('restartJobsPolling');
+ })
+ .then(() => setTimeoutPromise())
+ .then(() => {
+ const statusObject = STATUS_MAP[updatedProjects[0].importStatus];
+
+ expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
+ expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
+ statusObject.text,
+ );
+
+ expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
+ })
+ .then(() => done())
+ .catch(() => done.fail());
+ });
+});
diff --git a/spec/javascripts/import_projects/components/imported_project_table_row_spec.js b/spec/javascripts/import_projects/components/imported_project_table_row_spec.js
new file mode 100644
index 00000000000..7dac7e9ccc1
--- /dev/null
+++ b/spec/javascripts/import_projects/components/imported_project_table_row_spec.js
@@ -0,0 +1,51 @@
+import Vue from 'vue';
+import createStore from '~/import_projects/store';
+import importedProjectTableRow from '~/import_projects/components/imported_project_table_row.vue';
+import STATUS_MAP from '~/import_projects/constants';
+
+describe('ImportedProjectTableRow', () => {
+ let vm;
+ const project = {
+ id: 1,
+ fullPath: 'fullPath',
+ importStatus: 'finished',
+ providerLink: 'providerLink',
+ importSource: 'importSource',
+ };
+
+ function createComponent() {
+ const ImportedProjectTableRow = Vue.extend(importedProjectTableRow);
+
+ const store = createStore();
+ return new ImportedProjectTableRow({
+ store,
+ propsData: {
+ project: {
+ ...project,
+ },
+ },
+ }).$mount();
+ }
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders an imported project table row', () => {
+ vm = createComponent();
+
+ const providerLink = vm.$el.querySelector('.js-provider-link');
+ const statusObject = STATUS_MAP[project.importStatus];
+
+ expect(vm.$el.classList.contains('js-imported-project')).toBe(true);
+ expect(providerLink.href).toMatch(project.providerLink);
+ expect(providerLink.textContent).toMatch(project.importSource);
+ expect(vm.$el.querySelector('.js-full-path').textContent).toMatch(project.fullPath);
+ expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
+ statusObject.text,
+ );
+
+ expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
+ expect(vm.$el.querySelector('.js-go-to-project').href).toMatch(project.fullPath);
+ });
+});
diff --git a/spec/javascripts/import_projects/components/provider_repo_table_row_spec.js b/spec/javascripts/import_projects/components/provider_repo_table_row_spec.js
new file mode 100644
index 00000000000..4d2bacd2ad0
--- /dev/null
+++ b/spec/javascripts/import_projects/components/provider_repo_table_row_spec.js
@@ -0,0 +1,96 @@
+import Vue from 'vue';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import createStore from '~/import_projects/store';
+import providerRepoTableRow from '~/import_projects/components/provider_repo_table_row.vue';
+import STATUS_MAP, { STATUSES } from '~/import_projects/constants';
+import setTimeoutPromise from '../../helpers/set_timeout_promise_helper';
+
+describe('ProviderRepoTableRow', () => {
+ let store;
+ let vm;
+ const repo = {
+ id: 10,
+ sanitizedName: 'sanitizedName',
+ fullName: 'fullName',
+ providerLink: 'providerLink',
+ };
+
+ function createComponent() {
+ const ProviderRepoTableRow = Vue.extend(providerRepoTableRow);
+
+ return new ProviderRepoTableRow({
+ store,
+ propsData: {
+ repo: {
+ ...repo,
+ },
+ },
+ }).$mount();
+ }
+
+ beforeEach(() => {
+ store = createStore();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders a provider repo table row', () => {
+ vm = createComponent();
+
+ const providerLink = vm.$el.querySelector('.js-provider-link');
+ const statusObject = STATUS_MAP[STATUSES.NONE];
+
+ expect(vm.$el.classList.contains('js-provider-repo')).toBe(true);
+ expect(providerLink.href).toMatch(repo.providerLink);
+ expect(providerLink.textContent).toMatch(repo.fullName);
+ expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
+ statusObject.text,
+ );
+
+ expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
+ expect(vm.$el.querySelector('.js-import-button')).not.toBeNull();
+ });
+
+ it('renders a select2 namespace select', () => {
+ vm = createComponent();
+
+ const dropdownTrigger = vm.$el.querySelector('.js-namespace-select');
+
+ expect(dropdownTrigger).not.toBeNull();
+ expect(dropdownTrigger.classList.contains('select2-container')).toBe(true);
+
+ dropdownTrigger.click();
+
+ expect(vm.$el.querySelector('.select2-drop')).not.toBeNull();
+ });
+
+ it('imports repo when clicking import button', done => {
+ const importPath = '/import-path';
+ const defaultTargetNamespace = 'user';
+ const ciCdOnly = true;
+ const mock = new MockAdapter(axios);
+
+ store.dispatch('setInitialData', { importPath, defaultTargetNamespace, ciCdOnly });
+ mock.onPost(importPath).replyOnce(200);
+ spyOn(store, 'dispatch').and.returnValue(new Promise(() => {}));
+
+ vm = createComponent();
+
+ vm.$el.querySelector('.js-import-button').click();
+
+ setTimeoutPromise()
+ .then(() => {
+ expect(store.dispatch).toHaveBeenCalledWith('fetchImport', {
+ repo,
+ newName: repo.sanitizedName,
+ targetNamespace: defaultTargetNamespace,
+ });
+ })
+ .then(() => mock.restore())
+ .then(done)
+ .catch(done.fail);
+ });
+});
diff --git a/spec/javascripts/import_projects/store/actions_spec.js b/spec/javascripts/import_projects/store/actions_spec.js
new file mode 100644
index 00000000000..77850ee3283
--- /dev/null
+++ b/spec/javascripts/import_projects/store/actions_spec.js
@@ -0,0 +1,284 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import {
+ SET_INITIAL_DATA,
+ REQUEST_REPOS,
+ RECEIVE_REPOS_SUCCESS,
+ RECEIVE_REPOS_ERROR,
+ REQUEST_IMPORT,
+ RECEIVE_IMPORT_SUCCESS,
+ RECEIVE_IMPORT_ERROR,
+ RECEIVE_JOBS_SUCCESS,
+} from '~/import_projects/store/mutation_types';
+import {
+ setInitialData,
+ requestRepos,
+ receiveReposSuccess,
+ receiveReposError,
+ fetchRepos,
+ requestImport,
+ receiveImportSuccess,
+ receiveImportError,
+ fetchImport,
+ receiveJobsSuccess,
+ fetchJobs,
+ clearJobsEtagPoll,
+ stopJobsPolling,
+} from '~/import_projects/store/actions';
+import state from '~/import_projects/store/state';
+import testAction from 'spec/helpers/vuex_action_helper';
+import { TEST_HOST } from 'spec/test_constants';
+
+describe('import_projects store actions', () => {
+ let localState;
+ const repoId = 1;
+ const repos = [{ id: 1 }, { id: 2 }];
+ const importPayload = { newName: 'newName', targetNamespace: 'targetNamespace', repo: { id: 1 } };
+
+ beforeEach(() => {
+ localState = state();
+ });
+
+ describe('setInitialData', () => {
+ it(`commits ${SET_INITIAL_DATA} mutation`, done => {
+ const initialData = {
+ reposPath: 'reposPath',
+ provider: 'provider',
+ jobsPath: 'jobsPath',
+ importPath: 'impapp/assets/javascripts/vue_shared/components/select2_select.vueortPath',
+ defaultTargetNamespace: 'defaultTargetNamespace',
+ ciCdOnly: 'ciCdOnly',
+ canSelectNamespace: 'canSelectNamespace',
+ };
+
+ testAction(
+ setInitialData,
+ initialData,
+ localState,
+ [{ type: SET_INITIAL_DATA, payload: initialData }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('requestRepos', () => {
+ it(`requestRepos commits ${REQUEST_REPOS} mutation`, done => {
+ testAction(
+ requestRepos,
+ null,
+ localState,
+ [{ type: REQUEST_REPOS, payload: null }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveReposSuccess', () => {
+ it(`commits ${RECEIVE_REPOS_SUCCESS} mutation`, done => {
+ testAction(
+ receiveReposSuccess,
+ repos,
+ localState,
+ [{ type: RECEIVE_REPOS_SUCCESS, payload: repos }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveReposError', () => {
+ it(`commits ${RECEIVE_REPOS_ERROR} mutation`, done => {
+ testAction(receiveReposError, repos, localState, [{ type: RECEIVE_REPOS_ERROR }], [], done);
+ });
+ });
+
+ describe('fetchRepos', () => {
+ let mock;
+
+ beforeEach(() => {
+ localState.reposPath = `${TEST_HOST}/endpoint.json`;
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => mock.restore());
+
+ it('dispatches requestRepos and receiveReposSuccess actions on a successful request', done => {
+ const payload = { imported_projects: [{}], provider_repos: [{}], namespaces: [{}] };
+ mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, payload);
+
+ testAction(
+ fetchRepos,
+ null,
+ localState,
+ [],
+ [
+ { type: 'requestRepos' },
+ {
+ type: 'receiveReposSuccess',
+ payload: convertObjectPropsToCamelCase(payload, { deep: true }),
+ },
+ {
+ type: 'fetchJobs',
+ },
+ ],
+ done,
+ );
+ });
+
+ it('dispatches requestRepos and receiveReposSuccess actions on an unsuccessful request', done => {
+ mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
+
+ testAction(
+ fetchRepos,
+ null,
+ localState,
+ [],
+ [{ type: 'requestRepos' }, { type: 'receiveReposError' }],
+ done,
+ );
+ });
+ });
+
+ describe('requestImport', () => {
+ it(`commits ${REQUEST_IMPORT} mutation`, done => {
+ testAction(
+ requestImport,
+ repoId,
+ localState,
+ [{ type: REQUEST_IMPORT, payload: repoId }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveImportSuccess', () => {
+ it(`commits ${RECEIVE_IMPORT_SUCCESS} mutation`, done => {
+ const payload = { importedProject: { name: 'imported/project' }, repoId: 2 };
+
+ testAction(
+ receiveImportSuccess,
+ payload,
+ localState,
+ [{ type: RECEIVE_IMPORT_SUCCESS, payload }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveImportError', () => {
+ it(`commits ${RECEIVE_IMPORT_ERROR} mutation`, done => {
+ testAction(
+ receiveImportError,
+ repoId,
+ localState,
+ [{ type: RECEIVE_IMPORT_ERROR, payload: repoId }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchImport', () => {
+ let mock;
+
+ beforeEach(() => {
+ localState.importPath = `${TEST_HOST}/endpoint.json`;
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => mock.restore());
+
+ it('dispatches requestImport and receiveImportSuccess actions on a successful request', done => {
+ const importedProject = { name: 'imported/project' };
+ const importRepoId = importPayload.repo.id;
+ mock.onPost(`${TEST_HOST}/endpoint.json`).reply(200, importedProject);
+
+ testAction(
+ fetchImport,
+ importPayload,
+ localState,
+ [],
+ [
+ { type: 'requestImport', payload: importRepoId },
+ {
+ type: 'receiveImportSuccess',
+ payload: {
+ importedProject: convertObjectPropsToCamelCase(importedProject, { deep: true }),
+ repoId: importRepoId,
+ },
+ },
+ ],
+ done,
+ );
+ });
+
+ it('dispatches requestImport and receiveImportSuccess actions on an unsuccessful request', done => {
+ mock.onPost(`${TEST_HOST}/endpoint.json`).reply(500);
+
+ testAction(
+ fetchImport,
+ importPayload,
+ localState,
+ [],
+ [
+ { type: 'requestImport', payload: importPayload.repo.id },
+ { type: 'receiveImportError', payload: { repoId: importPayload.repo.id } },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('receiveJobsSuccess', () => {
+ it(`commits ${RECEIVE_JOBS_SUCCESS} mutation`, done => {
+ testAction(
+ receiveJobsSuccess,
+ repos,
+ localState,
+ [{ type: RECEIVE_JOBS_SUCCESS, payload: repos }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchJobs', () => {
+ let mock;
+
+ beforeEach(() => {
+ localState.jobsPath = `${TEST_HOST}/endpoint.json`;
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ stopJobsPolling();
+ clearJobsEtagPoll();
+ });
+
+ afterEach(() => mock.restore());
+
+ it('dispatches requestJobs and receiveJobsSuccess actions on a successful request', done => {
+ const updatedProjects = [{ name: 'imported/project' }, { name: 'provider/repo' }];
+ mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, updatedProjects);
+
+ testAction(
+ fetchJobs,
+ null,
+ localState,
+ [],
+ [
+ {
+ type: 'receiveJobsSuccess',
+ payload: convertObjectPropsToCamelCase(updatedProjects, { deep: true }),
+ },
+ ],
+ done,
+ );
+ });
+ });
+});
diff --git a/spec/javascripts/import_projects/store/getters_spec.js b/spec/javascripts/import_projects/store/getters_spec.js
new file mode 100644
index 00000000000..e5e4a95f473
--- /dev/null
+++ b/spec/javascripts/import_projects/store/getters_spec.js
@@ -0,0 +1,83 @@
+import {
+ namespaceSelectOptions,
+ isImportingAnyRepo,
+ hasProviderRepos,
+ hasImportedProjects,
+} from '~/import_projects/store/getters';
+import state from '~/import_projects/store/state';
+
+describe('import_projects store getters', () => {
+ let localState;
+
+ beforeEach(() => {
+ localState = state();
+ });
+
+ describe('namespaceSelectOptions', () => {
+ const namespaces = [{ fullPath: 'namespace-0' }, { fullPath: 'namespace-1' }];
+ const defaultTargetNamespace = 'current-user';
+
+ it('returns an options array with a "Users" and "Groups" optgroups', () => {
+ localState.namespaces = namespaces;
+ localState.defaultTargetNamespace = defaultTargetNamespace;
+
+ const optionsArray = namespaceSelectOptions(localState);
+ const groupsGroup = optionsArray[0];
+ const usersGroup = optionsArray[1];
+
+ expect(groupsGroup.text).toBe('Groups');
+ expect(usersGroup.text).toBe('Users');
+
+ groupsGroup.children.forEach((child, index) => {
+ expect(child.id).toBe(namespaces[index].fullPath);
+ expect(child.text).toBe(namespaces[index].fullPath);
+ });
+
+ expect(usersGroup.children.length).toBe(1);
+ expect(usersGroup.children[0].id).toBe(defaultTargetNamespace);
+ expect(usersGroup.children[0].text).toBe(defaultTargetNamespace);
+ });
+ });
+
+ describe('isImportingAnyRepo', () => {
+ it('returns true if there are any reposBeingImported', () => {
+ localState.reposBeingImported = new Array(1);
+
+ expect(isImportingAnyRepo(localState)).toBe(true);
+ });
+
+ it('returns false if there are no reposBeingImported', () => {
+ localState.reposBeingImported = [];
+
+ expect(isImportingAnyRepo(localState)).toBe(false);
+ });
+ });
+
+ describe('hasProviderRepos', () => {
+ it('returns true if there are any providerRepos', () => {
+ localState.providerRepos = new Array(1);
+
+ expect(hasProviderRepos(localState)).toBe(true);
+ });
+
+ it('returns false if there are no providerRepos', () => {
+ localState.providerRepos = [];
+
+ expect(hasProviderRepos(localState)).toBe(false);
+ });
+ });
+
+ describe('hasImportedProjects', () => {
+ it('returns true if there are any importedProjects', () => {
+ localState.importedProjects = new Array(1);
+
+ expect(hasImportedProjects(localState)).toBe(true);
+ });
+
+ it('returns false if there are no importedProjects', () => {
+ localState.importedProjects = [];
+
+ expect(hasImportedProjects(localState)).toBe(false);
+ });
+ });
+});
diff --git a/spec/javascripts/import_projects/store/mutations_spec.js b/spec/javascripts/import_projects/store/mutations_spec.js
new file mode 100644
index 00000000000..8db8e9819ba
--- /dev/null
+++ b/spec/javascripts/import_projects/store/mutations_spec.js
@@ -0,0 +1,34 @@
+import * as types from '~/import_projects/store/mutation_types';
+import mutations from '~/import_projects/store/mutations';
+
+describe('import_projects store mutations', () => {
+ describe(types.RECEIVE_IMPORT_SUCCESS, () => {
+ it('removes repoId from reposBeingImported and providerRepos, adds to importedProjects', () => {
+ const repoId = 1;
+ const state = {
+ reposBeingImported: [repoId],
+ providerRepos: [{ id: repoId }],
+ importedProjects: [],
+ };
+ const importedProject = { id: repoId };
+
+ mutations[types.RECEIVE_IMPORT_SUCCESS](state, { importedProject, repoId });
+
+ expect(state.reposBeingImported.includes(repoId)).toBe(false);
+ expect(state.providerRepos.some(repo => repo.id === repoId)).toBe(false);
+ expect(state.importedProjects.some(repo => repo.id === repoId)).toBe(true);
+ });
+ });
+
+ describe(types.RECEIVE_JOBS_SUCCESS, () => {
+ it('updates importStatus of existing importedProjects', () => {
+ const repoId = 1;
+ const state = { importedProjects: [{ id: repoId, importStatus: 'started' }] };
+ const updatedProjects = [{ id: repoId, importStatus: 'finished' }];
+
+ mutations[types.RECEIVE_JOBS_SUCCESS](state, updatedProjects);
+
+ expect(state.importedProjects[0].importStatus).toBe(updatedProjects[0].importStatus);
+ });
+ });
+});
diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js
index 2bd1b3996dc..0ccf771c7ef 100644
--- a/spec/javascripts/issue_show/components/app_spec.js
+++ b/spec/javascripts/issue_show/components/app_spec.js
@@ -18,9 +18,13 @@ describe('Issuable output', () => {
let realtimeRequestCount = 0;
let vm;
- document.body.innerHTML = '<span id="task_status"></span>';
-
beforeEach(done => {
+ setFixtures(`
+ <div>
+ <div class="flash-container"></div>
+ <span id="task_status"></span>
+ </div>
+ `);
spyOn(eventHub, '$emit');
const IssuableDescriptionComponent = Vue.extend(issuableApp);
@@ -43,6 +47,7 @@ describe('Issuable output', () => {
initialTitleText: '',
initialDescriptionHtml: 'test',
initialDescriptionText: 'test',
+ lockVersion: 1,
markdownPreviewPath: '/',
markdownDocsPath: '/',
projectNamespace: '/',
@@ -78,6 +83,7 @@ describe('Issuable output', () => {
expect(formatText(editedText.innerText)).toMatch(/Edited[\s\S]+?by Some User/);
expect(editedText.querySelector('.author-link').href).toMatch(/\/some_user$/);
expect(editedText.querySelector('time')).toBeTruthy();
+ expect(vm.state.lock_version).toEqual(1);
})
.then(() => {
vm.poll.makeRequest();
@@ -95,6 +101,7 @@ describe('Issuable output', () => {
expect(editedText.querySelector('.author-link').href).toMatch(/\/other_user$/);
expect(editedText.querySelector('time')).toBeTruthy();
+ expect(vm.state.lock_version).toEqual(2);
})
.then(done)
.catch(done.fail);
@@ -137,21 +144,17 @@ describe('Issuable output', () => {
describe('updateIssuable', () => {
it('fetches new data after update', done => {
+ spyOn(vm, 'updateStoreState').and.callThrough();
spyOn(vm.service, 'getData').and.callThrough();
- spyOn(vm.service, 'updateIssuable').and.callFake(
- () =>
- new Promise(resolve => {
- resolve({
- data: {
- confidential: false,
- web_url: window.location.pathname,
- },
- });
- }),
+ spyOn(vm.service, 'updateIssuable').and.returnValue(
+ Promise.resolve({
+ data: { web_url: window.location.pathname },
+ }),
);
vm.updateIssuable()
.then(() => {
+ expect(vm.updateStoreState).toHaveBeenCalled();
expect(vm.service.getData).toHaveBeenCalled();
})
.then(done)
@@ -159,11 +162,10 @@ describe('Issuable output', () => {
});
it('correctly updates issuable data', done => {
- spyOn(vm.service, 'updateIssuable').and.callFake(
- () =>
- new Promise(resolve => {
- resolve();
- }),
+ spyOn(vm.service, 'updateIssuable').and.returnValue(
+ Promise.resolve({
+ data: { web_url: window.location.pathname },
+ }),
);
vm.updateIssuable()
@@ -177,16 +179,13 @@ describe('Issuable output', () => {
it('does not redirect if issue has not moved', done => {
const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.service, 'updateIssuable').and.callFake(
- () =>
- new Promise(resolve => {
- resolve({
- data: {
- web_url: window.location.pathname,
- confidential: vm.isConfidential,
- },
- });
- }),
+ spyOn(vm.service, 'updateIssuable').and.returnValue(
+ Promise.resolve({
+ data: {
+ web_url: window.location.pathname,
+ confidential: vm.isConfidential,
+ },
+ }),
);
vm.updateIssuable();
@@ -199,16 +198,13 @@ describe('Issuable output', () => {
it('redirects if returned web_url has changed', done => {
const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.service, 'updateIssuable').and.callFake(
- () =>
- new Promise(resolve => {
- resolve({
- data: {
- web_url: '/testing-issue-move',
- confidential: vm.isConfidential,
- },
- });
- }),
+ spyOn(vm.service, 'updateIssuable').and.returnValue(
+ Promise.resolve({
+ data: {
+ web_url: '/testing-issue-move',
+ confidential: vm.isConfidential,
+ },
+ }),
);
vm.updateIssuable();
@@ -227,6 +223,7 @@ describe('Issuable output', () => {
vm.handleBeforeUnloadEvent(e);
Vue.nextTick(() => {
expect(e.returnValue).not.toBeNull();
+
done();
});
});
@@ -238,6 +235,7 @@ describe('Issuable output', () => {
vm.handleBeforeUnloadEvent(e);
Vue.nextTick(() => {
expect(e.returnValue).not.toBeNull();
+
done();
});
});
@@ -247,49 +245,61 @@ describe('Issuable output', () => {
vm.handleBeforeUnloadEvent(e);
Vue.nextTick(() => {
expect(e.returnValue).toBeNull();
+
done();
});
});
});
describe('error when updating', () => {
- beforeEach(() => {
- spyOn(window, 'Flash').and.callThrough();
- spyOn(vm.service, 'updateIssuable').and.callFake(
- () =>
- new Promise((resolve, reject) => {
- reject();
- }),
- );
- });
-
it('closes form on error', done => {
+ spyOn(vm.service, 'updateIssuable').and.callFake(() => Promise.reject());
vm.updateIssuable();
setTimeout(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
-
- expect(window.Flash).toHaveBeenCalledWith('Error updating issue');
+ expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `Error updating issue`,
+ );
done();
});
});
it('returns the correct error message for issuableType', done => {
+ spyOn(vm.service, 'updateIssuable').and.callFake(() => Promise.reject());
vm.issuableType = 'merge request';
Vue.nextTick(() => {
vm.updateIssuable();
setTimeout(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
-
- expect(window.Flash).toHaveBeenCalledWith('Error updating merge request');
+ expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `Error updating merge request`,
+ );
done();
});
});
});
+
+ it('shows error mesage from backend if exists', done => {
+ const msg = 'Custom error message from backend';
+ spyOn(vm.service, 'updateIssuable').and.callFake(
+ // eslint-disable-next-line prefer-promise-reject-errors
+ () => Promise.reject({ response: { data: { errors: [msg] } } }),
+ );
+
+ vm.updateIssuable();
+ setTimeout(() => {
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `${vm.defaultErrorMessage}. ${msg}`,
+ );
+
+ done();
+ });
+ });
});
});
@@ -342,21 +352,19 @@ describe('Issuable output', () => {
describe('deleteIssuable', () => {
it('changes URL when deleted', done => {
const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.service, 'deleteIssuable').and.callFake(
- () =>
- new Promise(resolve => {
- resolve({
- data: {
- web_url: '/test',
- },
- });
- }),
+ spyOn(vm.service, 'deleteIssuable').and.returnValue(
+ Promise.resolve({
+ data: {
+ web_url: '/test',
+ },
+ }),
);
vm.deleteIssuable();
setTimeout(() => {
expect(visitUrl).toHaveBeenCalledWith('/test');
+
done();
});
});
@@ -364,40 +372,33 @@ describe('Issuable output', () => {
it('stops polling when deleting', done => {
spyOnDependency(issuableApp, 'visitUrl');
spyOn(vm.poll, 'stop').and.callThrough();
- spyOn(vm.service, 'deleteIssuable').and.callFake(
- () =>
- new Promise(resolve => {
- resolve({
- data: {
- web_url: '/test',
- },
- });
- }),
+ spyOn(vm.service, 'deleteIssuable').and.returnValue(
+ Promise.resolve({
+ data: {
+ web_url: '/test',
+ },
+ }),
);
vm.deleteIssuable();
setTimeout(() => {
expect(vm.poll.stop).toHaveBeenCalledWith();
+
done();
});
});
it('closes form on error', done => {
- spyOn(window, 'Flash').and.callThrough();
- spyOn(vm.service, 'deleteIssuable').and.callFake(
- () =>
- new Promise((resolve, reject) => {
- reject();
- }),
- );
+ spyOn(vm.service, 'deleteIssuable').and.returnValue(Promise.reject());
vm.deleteIssuable();
setTimeout(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
-
- expect(window.Flash).toHaveBeenCalledWith('Error deleting issue');
+ expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ 'Error deleting issue',
+ );
done();
});
@@ -420,6 +421,7 @@ describe('Issuable output', () => {
.then(vm.$nextTick)
.then(() => {
expect(vm.formState.lockedWarningVisible).toEqual(true);
+ expect(vm.formState.lock_version).toEqual(1);
expect(vm.$el.querySelector('.alert')).not.toBeNull();
})
.then(done)
@@ -438,4 +440,34 @@ describe('Issuable output', () => {
expect(vm.$el.querySelector('.title-container .note-action-button')).toBeDefined();
});
});
+
+ describe('updateStoreState', () => {
+ it('should make a request and update the state of the store', done => {
+ const data = { foo: 1 };
+ spyOn(vm.store, 'updateState');
+ spyOn(vm.service, 'getData').and.returnValue(Promise.resolve({ data }));
+
+ vm.updateStoreState()
+ .then(() => {
+ expect(vm.service.getData).toHaveBeenCalled();
+ expect(vm.store.updateState).toHaveBeenCalledWith(data);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('should show error message if store update fails', done => {
+ spyOn(vm.service, 'getData').and.returnValue(Promise.reject());
+ vm.issuableType = 'merge request';
+
+ vm.updateStoreState()
+ .then(() => {
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `Error updating ${vm.issuableType}`,
+ );
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
});
diff --git a/spec/javascripts/issue_show/components/description_spec.js b/spec/javascripts/issue_show/components/description_spec.js
index 463f3c89926..2eeed6770be 100644
--- a/spec/javascripts/issue_show/components/description_spec.js
+++ b/spec/javascripts/issue_show/components/description_spec.js
@@ -21,7 +21,8 @@ describe('Description component', () => {
if (!document.querySelector('.issuable-meta')) {
const metaData = document.createElement('div');
metaData.classList.add('issuable-meta');
- metaData.innerHTML = '<span id="task_status"></span><span id="task_status_short"></span>';
+ metaData.innerHTML =
+ '<div class="flash-container"></div><span id="task_status"></span><span id="task_status_short"></span>';
document.body.appendChild(metaData);
}
@@ -33,6 +34,10 @@ describe('Description component', () => {
vm.$destroy();
});
+ afterAll(() => {
+ $('.issuable-meta .flash-container').remove();
+ });
+
it('animates description changes', done => {
vm.descriptionHtml = 'changed';
@@ -123,7 +128,10 @@ describe('Description component', () => {
fieldName: 'description',
selector: '.detail-page-description',
onSuccess: jasmine.any(Function),
+ onError: jasmine.any(Function),
+ lockVersion: 0,
});
+
done();
});
});
@@ -184,4 +192,17 @@ describe('Description component', () => {
it('sets data-update-url', () => {
expect(vm.$el.querySelector('textarea').dataset.updateUrl).toEqual(gl.TEST_HOST);
});
+
+ describe('taskListUpdateError', () => {
+ it('should create flash notification and emit an event to parent', () => {
+ const msg =
+ 'Someone edited this issue at the same time you did. The description has been updated and you will need to make your changes again.';
+ spyOn(vm, '$emit');
+
+ vm.taskListUpdateError();
+
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(msg);
+ expect(vm.$emit).toHaveBeenCalledWith('taskListUpdateFailed');
+ });
+ });
});
diff --git a/spec/javascripts/issue_show/mock_data.js b/spec/javascripts/issue_show/mock_data.js
index 74b3efb014b..f4475aadb8b 100644
--- a/spec/javascripts/issue_show/mock_data.js
+++ b/spec/javascripts/issue_show/mock_data.js
@@ -8,6 +8,7 @@ export default {
updated_at: '2015-05-15T12:31:04.428Z',
updated_by_name: 'Some User',
updated_by_path: '/some_user',
+ lock_version: 1,
},
secondRequest: {
title: '<p>2</p>',
@@ -18,5 +19,6 @@ export default {
updated_at: '2016-05-15T12:31:04.428Z',
updated_by_name: 'Other User',
updated_by_path: '/other_user',
+ lock_version: 2,
},
};
diff --git a/spec/javascripts/jobs/components/sidebar_spec.js b/spec/javascripts/jobs/components/sidebar_spec.js
index b0bc16d7c64..3a02351460c 100644
--- a/spec/javascripts/jobs/components/sidebar_spec.js
+++ b/spec/javascripts/jobs/components/sidebar_spec.js
@@ -28,7 +28,7 @@ describe('Sidebar details block', () => {
store,
});
- expect(vm.$el.querySelector('.js-retry-job')).toBeNull();
+ expect(vm.$el.querySelector('.js-retry-button')).toBeNull();
});
});
@@ -70,7 +70,7 @@ describe('Sidebar details block', () => {
});
it('should render link to retry job', () => {
- expect(vm.$el.querySelector('.js-retry-job').getAttribute('href')).toEqual(job.retry_path);
+ expect(vm.$el.querySelector('.js-retry-button').getAttribute('href')).toEqual(job.retry_path);
});
it('should render link to cancel job', () => {
diff --git a/spec/javascripts/jobs/store/getters_spec.js b/spec/javascripts/jobs/store/getters_spec.js
index 4195d9d3680..379114c3737 100644
--- a/spec/javascripts/jobs/store/getters_spec.js
+++ b/spec/javascripts/jobs/store/getters_spec.js
@@ -8,30 +8,6 @@ describe('Job Store Getters', () => {
localState = state();
});
- describe('headerActions', () => {
- describe('with new issue path', () => {
- it('returns an array with action to create a new issue', () => {
- localState.job.new_issue_path = 'issues/new';
-
- expect(getters.headerActions(localState)).toEqual([
- {
- label: 'New issue',
- path: localState.job.new_issue_path,
- cssClass:
- 'js-new-issue btn btn-success btn-inverted d-none d-md-block d-lg-block d-xl-block',
- type: 'link',
- },
- ]);
- });
- });
-
- describe('without new issue path', () => {
- it('returns an empty array', () => {
- expect(getters.headerActions(localState)).toEqual([]);
- });
- });
- });
-
describe('headerTime', () => {
describe('when the job has started key', () => {
it('returns started key', () => {
@@ -175,6 +151,61 @@ describe('Job Store Getters', () => {
});
});
+ describe('shouldRenderSharedRunnerLimitWarning', () => {
+ describe('without runners information', () => {
+ it('returns false', () => {
+ expect(getters.shouldRenderSharedRunnerLimitWarning(localState)).toEqual(false);
+ });
+ });
+
+ describe('with runners information', () => {
+ describe('when used quota is less than limit', () => {
+ it('returns false', () => {
+ localState.job.runners = {
+ quota: {
+ used: 33,
+ limit: 2000,
+ },
+ available: true,
+ online: true,
+ };
+
+ expect(getters.shouldRenderSharedRunnerLimitWarning(localState)).toEqual(false);
+ });
+ });
+
+ describe('when used quota is equal to limit', () => {
+ it('returns true', () => {
+ localState.job.runners = {
+ quota: {
+ used: 2000,
+ limit: 2000,
+ },
+ available: true,
+ online: true,
+ };
+
+ expect(getters.shouldRenderSharedRunnerLimitWarning(localState)).toEqual(true);
+ });
+ });
+
+ describe('when used quota is bigger than limit', () => {
+ it('returns true', () => {
+ localState.job.runners = {
+ quota: {
+ used: 2002,
+ limit: 2000,
+ },
+ available: true,
+ online: true,
+ };
+
+ expect(getters.shouldRenderSharedRunnerLimitWarning(localState)).toEqual(true);
+ });
+ });
+ });
+ });
+
describe('hasRunnersForProject', () => {
describe('with available and offline runners', () => {
it('returns true', () => {
diff --git a/spec/javascripts/lib/utils/ajax_cache_spec.js b/spec/javascripts/lib/utils/ajax_cache_spec.js
deleted file mode 100644
index dc0b04173bf..00000000000
--- a/spec/javascripts/lib/utils/ajax_cache_spec.js
+++ /dev/null
@@ -1,184 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import AjaxCache from '~/lib/utils/ajax_cache';
-
-describe('AjaxCache', () => {
- const dummyEndpoint = '/AjaxCache/dummyEndpoint';
- const dummyResponse = {
- important: 'dummy data',
- };
-
- beforeEach(() => {
- AjaxCache.internalStorage = {};
- AjaxCache.pendingRequests = {};
- });
-
- describe('get', () => {
- it('returns undefined if cache is empty', () => {
- const data = AjaxCache.get(dummyEndpoint);
-
- expect(data).toBe(undefined);
- });
-
- it('returns undefined if cache contains no matching data', () => {
- AjaxCache.internalStorage['not matching'] = dummyResponse;
-
- const data = AjaxCache.get(dummyEndpoint);
-
- expect(data).toBe(undefined);
- });
-
- it('returns matching data', () => {
- AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
-
- const data = AjaxCache.get(dummyEndpoint);
-
- expect(data).toBe(dummyResponse);
- });
- });
-
- describe('hasData', () => {
- it('returns false if cache is empty', () => {
- expect(AjaxCache.hasData(dummyEndpoint)).toBe(false);
- });
-
- it('returns false if cache contains no matching data', () => {
- AjaxCache.internalStorage['not matching'] = dummyResponse;
-
- expect(AjaxCache.hasData(dummyEndpoint)).toBe(false);
- });
-
- it('returns true if data is available', () => {
- AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
-
- expect(AjaxCache.hasData(dummyEndpoint)).toBe(true);
- });
- });
-
- describe('remove', () => {
- it('does nothing if cache is empty', () => {
- AjaxCache.remove(dummyEndpoint);
-
- expect(AjaxCache.internalStorage).toEqual({});
- });
-
- it('does nothing if cache contains no matching data', () => {
- AjaxCache.internalStorage['not matching'] = dummyResponse;
-
- AjaxCache.remove(dummyEndpoint);
-
- expect(AjaxCache.internalStorage['not matching']).toBe(dummyResponse);
- });
-
- it('removes matching data', () => {
- AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
-
- AjaxCache.remove(dummyEndpoint);
-
- expect(AjaxCache.internalStorage).toEqual({});
- });
- });
-
- describe('override', () => {
- it('overrides existing cache', () => {
- AjaxCache.internalStorage.endpoint = 'existing-endpoint';
- AjaxCache.override('endpoint', 'new-endpoint');
-
- expect(AjaxCache.internalStorage.endpoint).toEqual('new-endpoint');
- });
- });
-
- describe('retrieve', () => {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- spyOn(axios, 'get').and.callThrough();
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('stores and returns data from Ajax call if cache is empty', done => {
- mock.onGet(dummyEndpoint).reply(200, dummyResponse);
-
- AjaxCache.retrieve(dummyEndpoint)
- .then(data => {
- expect(data).toEqual(dummyResponse);
- expect(AjaxCache.internalStorage[dummyEndpoint]).toEqual(dummyResponse);
- })
- .then(done)
- .catch(fail);
- });
-
- it('makes no Ajax call if request is pending', done => {
- mock.onGet(dummyEndpoint).reply(200, dummyResponse);
-
- AjaxCache.retrieve(dummyEndpoint)
- .then(done)
- .catch(fail);
-
- AjaxCache.retrieve(dummyEndpoint)
- .then(done)
- .catch(fail);
-
- expect(axios.get.calls.count()).toBe(1);
- });
-
- it('returns undefined if Ajax call fails and cache is empty', done => {
- const errorMessage = 'Network Error';
- mock.onGet(dummyEndpoint).networkError();
-
- AjaxCache.retrieve(dummyEndpoint)
- .then(data => fail(`Received unexpected data: ${JSON.stringify(data)}`))
- .catch(error => {
- expect(error.message).toBe(`${dummyEndpoint}: ${errorMessage}`);
- expect(error.textStatus).toBe(errorMessage);
- done();
- })
- .catch(fail);
- });
-
- it('makes no Ajax call if matching data exists', done => {
- AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
- mock.onGet(dummyEndpoint).reply(() => {
- fail(new Error('expected no Ajax call!'));
- });
-
- AjaxCache.retrieve(dummyEndpoint)
- .then(data => {
- expect(data).toBe(dummyResponse);
- })
- .then(done)
- .catch(fail);
- });
-
- it('makes Ajax call even if matching data exists when forceRequest parameter is provided', done => {
- const oldDummyResponse = {
- important: 'old dummy data',
- };
-
- AjaxCache.internalStorage[dummyEndpoint] = oldDummyResponse;
-
- mock.onGet(dummyEndpoint).reply(200, dummyResponse);
-
- // Call without forceRetrieve param
- AjaxCache.retrieve(dummyEndpoint)
- .then(data => {
- expect(data).toBe(oldDummyResponse);
- })
- .then(done)
- .catch(fail);
-
- // Call with forceRetrieve param
- AjaxCache.retrieve(dummyEndpoint, true)
- .then(data => {
- expect(data).toEqual(dummyResponse);
- })
- .then(done)
- .catch(fail);
- });
- });
-});
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 1ec1e8a8dd9..0bb43c94f6a 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -3,6 +3,25 @@ import * as commonUtils from '~/lib/utils/common_utils';
import MockAdapter from 'axios-mock-adapter';
import { faviconDataUrl, overlayDataUrl, faviconWithOverlayDataUrl } from './mock_data';
+const PIXEL_TOLERANCE = 0.2;
+
+/**
+ * Loads a data URL as the src of an
+ * {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image|Image}
+ * and resolves to that Image once loaded.
+ *
+ * @param url
+ * @returns {Promise}
+ */
+const urlToImage = url =>
+ new Promise(resolve => {
+ const img = new Image();
+ img.onload = function() {
+ resolve(img);
+ };
+ img.src = url;
+ });
+
describe('common_utils', () => {
describe('parseUrl', () => {
it('returns an anchor tag with url', () => {
@@ -213,6 +232,21 @@ describe('common_utils', () => {
});
});
+ describe('debounceByAnimationFrame', () => {
+ it('debounces a function to allow a maximum of one call per animation frame', done => {
+ const spy = jasmine.createSpy('spy');
+ const debouncedSpy = commonUtils.debounceByAnimationFrame(spy);
+ window.requestAnimationFrame(() => {
+ debouncedSpy();
+ debouncedSpy();
+ window.requestAnimationFrame(() => {
+ expect(spy).toHaveBeenCalledTimes(1);
+ done();
+ });
+ });
+ });
+ });
+
describe('getParameterByName', () => {
beforeEach(() => {
window.history.pushState({}, null, '?scope=all&p=2');
@@ -347,27 +381,31 @@ describe('common_utils', () => {
});
describe('parseBoolean', () => {
+ const { parseBoolean } = commonUtils;
+
it('returns true for "true"', () => {
- expect(commonUtils.parseBoolean('true')).toEqual(true);
+ expect(parseBoolean('true')).toEqual(true);
});
it('returns false for "false"', () => {
- expect(commonUtils.parseBoolean('false')).toEqual(false);
+ expect(parseBoolean('false')).toEqual(false);
});
it('returns false for "something"', () => {
- expect(commonUtils.parseBoolean('something')).toEqual(false);
+ expect(parseBoolean('something')).toEqual(false);
});
it('returns false for null', () => {
- expect(commonUtils.parseBoolean(null)).toEqual(false);
+ expect(parseBoolean(null)).toEqual(false);
});
- });
- describe('convertPermissionToBoolean', () => {
- it('should convert a boolean in a string to a boolean', () => {
- expect(commonUtils.convertPermissionToBoolean('true')).toEqual(true);
- expect(commonUtils.convertPermissionToBoolean('false')).toEqual(false);
+ it('is idempotent', () => {
+ const input = ['true', 'false', 'something', null];
+ input.forEach(value => {
+ const result = parseBoolean(value);
+
+ expect(parseBoolean(result)).toBe(result);
+ });
});
});
@@ -502,8 +540,9 @@ describe('common_utils', () => {
it('should return the favicon with the overlay', done => {
commonUtils
.createOverlayIcon(faviconDataUrl, overlayDataUrl)
- .then(url => {
- expect(url).toEqual(faviconWithOverlayDataUrl);
+ .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
+ .then(([actual, expected]) => {
+ expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
done();
})
.catch(done.fail);
@@ -525,10 +564,10 @@ describe('common_utils', () => {
it('should set page favicon to provided favicon overlay', done => {
commonUtils
.setFaviconOverlay(overlayDataUrl)
- .then(() => {
- expect(document.getElementById('favicon').getAttribute('href')).toEqual(
- faviconWithOverlayDataUrl,
- );
+ .then(() => document.getElementById('favicon').getAttribute('href'))
+ .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
+ .then(([actual, expected]) => {
+ expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
done();
})
.catch(done.fail);
@@ -571,10 +610,10 @@ describe('common_utils', () => {
commonUtils
.setCiStatusFavicon(BUILD_URL)
- .then(() => {
- const favicon = document.getElementById('favicon');
-
- expect(favicon.getAttribute('href')).toEqual(faviconWithOverlayDataUrl);
+ .then(() => document.getElementById('favicon').getAttribute('href'))
+ .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
+ .then(([actual, expected]) => {
+ expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
done();
})
.catch(done.fail);
@@ -649,51 +688,131 @@ describe('common_utils', () => {
});
});
- describe('deep: true', () => {
- it('converts object with child objects', () => {
- const obj = {
- snake_key: {
- child_snake_key: 'value',
- },
- };
+ describe('with options', () => {
+ const objWithoutChildren = {
+ project_name: 'GitLab CE',
+ group_name: 'GitLab.org',
+ license_type: 'MIT',
+ };
+
+ const objWithChildren = {
+ project_name: 'GitLab CE',
+ group_name: 'GitLab.org',
+ license_type: 'MIT',
+ tech_stack: {
+ backend: 'Ruby',
+ frontend_framework: 'Vue',
+ database: 'PostgreSQL',
+ },
+ };
- expect(commonUtils.convertObjectPropsToCamelCase(obj, { deep: true })).toEqual({
- snakeKey: {
- childSnakeKey: 'value',
- },
- });
- });
+ describe('when options.deep is true', () => {
+ it('converts object with child objects', () => {
+ const obj = {
+ snake_key: {
+ child_snake_key: 'value',
+ },
+ };
- it('converts array with child objects', () => {
- const arr = [
- {
- child_snake_key: 'value',
- },
- ];
-
- expect(commonUtils.convertObjectPropsToCamelCase(arr, { deep: true })).toEqual([
- {
- childSnakeKey: 'value',
- },
- ]);
- });
+ expect(commonUtils.convertObjectPropsToCamelCase(obj, { deep: true })).toEqual({
+ snakeKey: {
+ childSnakeKey: 'value',
+ },
+ });
+ });
- it('converts array with child arrays', () => {
- const arr = [
- [
+ it('converts array with child objects', () => {
+ const arr = [
{
child_snake_key: 'value',
},
- ],
- ];
+ ];
- expect(commonUtils.convertObjectPropsToCamelCase(arr, { deep: true })).toEqual([
- [
+ expect(commonUtils.convertObjectPropsToCamelCase(arr, { deep: true })).toEqual([
{
childSnakeKey: 'value',
},
- ],
- ]);
+ ]);
+ });
+
+ it('converts array with child arrays', () => {
+ const arr = [
+ [
+ {
+ child_snake_key: 'value',
+ },
+ ],
+ ];
+
+ expect(commonUtils.convertObjectPropsToCamelCase(arr, { deep: true })).toEqual([
+ [
+ {
+ childSnakeKey: 'value',
+ },
+ ],
+ ]);
+ });
+ });
+
+ describe('when options.dropKeys is provided', () => {
+ it('discards properties mentioned in `dropKeys` array', () => {
+ expect(
+ commonUtils.convertObjectPropsToCamelCase(objWithoutChildren, {
+ dropKeys: ['group_name'],
+ }),
+ ).toEqual({
+ projectName: 'GitLab CE',
+ licenseType: 'MIT',
+ });
+ });
+
+ it('discards properties mentioned in `dropKeys` array when `deep` is true', () => {
+ expect(
+ commonUtils.convertObjectPropsToCamelCase(objWithChildren, {
+ deep: true,
+ dropKeys: ['group_name', 'database'],
+ }),
+ ).toEqual({
+ projectName: 'GitLab CE',
+ licenseType: 'MIT',
+ techStack: {
+ backend: 'Ruby',
+ frontendFramework: 'Vue',
+ },
+ });
+ });
+ });
+
+ describe('when options.ignoreKeyNames is provided', () => {
+ it('leaves properties mentioned in `ignoreKeyNames` array intact', () => {
+ expect(
+ commonUtils.convertObjectPropsToCamelCase(objWithoutChildren, {
+ ignoreKeyNames: ['group_name'],
+ }),
+ ).toEqual({
+ projectName: 'GitLab CE',
+ licenseType: 'MIT',
+ group_name: 'GitLab.org',
+ });
+ });
+
+ it('leaves properties mentioned in `ignoreKeyNames` array intact when `deep` is true', () => {
+ expect(
+ commonUtils.convertObjectPropsToCamelCase(objWithChildren, {
+ deep: true,
+ ignoreKeyNames: ['group_name', 'frontend_framework'],
+ }),
+ ).toEqual({
+ projectName: 'GitLab CE',
+ group_name: 'GitLab.org',
+ licenseType: 'MIT',
+ techStack: {
+ backend: 'Ruby',
+ frontend_framework: 'Vue',
+ database: 'PostgreSQL',
+ },
+ });
+ });
});
});
});
@@ -716,4 +835,30 @@ describe('common_utils', () => {
expect(commonUtils.roundOffFloat(34567.14159, -5)).toBe(0);
});
});
+
+ describe('isInViewport', () => {
+ let el;
+
+ beforeEach(() => {
+ el = document.createElement('div');
+ });
+
+ afterEach(() => {
+ document.body.removeChild(el);
+ });
+
+ it('returns true when provided `el` is in viewport', () => {
+ el.setAttribute('style', `position: absolute; right: ${window.innerWidth + 0.2};`);
+ document.body.appendChild(el);
+
+ expect(commonUtils.isInViewport(el)).toBe(true);
+ });
+
+ it('returns false when provided `el` is not in viewport', () => {
+ el.setAttribute('style', 'position: absolute; top: -1000px; left: -1000px;');
+ document.body.appendChild(el);
+
+ expect(commonUtils.isInViewport(el)).toBe(false);
+ });
+ });
});
diff --git a/spec/javascripts/lib/utils/datetime_utility_spec.js b/spec/javascripts/lib/utils/datetime_utility_spec.js
index bebe76f76c5..5327ec9d2a0 100644
--- a/spec/javascripts/lib/utils/datetime_utility_spec.js
+++ b/spec/javascripts/lib/utils/datetime_utility_spec.js
@@ -156,7 +156,7 @@ describe('getSundays', () => {
});
describe('getTimeframeWindowFrom', () => {
- it('returns array of date objects upto provided length start with provided startDate', () => {
+ it('returns array of date objects upto provided length (positive number) into the future starting from provided startDate', () => {
const startDate = new Date(2018, 0, 1);
const mockTimeframe = [
new Date(2018, 0, 1),
@@ -174,6 +174,25 @@ describe('getTimeframeWindowFrom', () => {
expect(timeframeItem.getDate()).toBe(mockTimeframe[index].getDate());
});
});
+
+ it('returns array of date objects upto provided length (negative number) into the past starting from provided startDate', () => {
+ const startDate = new Date(2018, 0, 1);
+ const mockTimeframe = [
+ new Date(2018, 0, 1),
+ new Date(2017, 11, 1),
+ new Date(2017, 10, 1),
+ new Date(2017, 9, 1),
+ new Date(2017, 8, 1),
+ ];
+ const timeframe = datetimeUtility.getTimeframeWindowFrom(startDate, -5);
+
+ expect(timeframe.length).toBe(5);
+ timeframe.forEach((timeframeItem, index) => {
+ expect(timeframeItem.getFullYear()).toBe(mockTimeframe[index].getFullYear());
+ expect(timeframeItem.getMonth()).toBe(mockTimeframe[index].getMonth());
+ expect(timeframeItem.getDate()).toBe(mockTimeframe[index].getDate());
+ });
+ });
});
describe('formatTime', () => {
@@ -376,3 +395,22 @@ describe('calculateRemainingMilliseconds', () => {
expect(milliseconds).toBe(0);
});
});
+
+describe('newDate', () => {
+ it('returns new date instance from existing date instance', () => {
+ const initialDate = new Date(2019, 0, 1);
+ const copiedDate = datetimeUtility.newDate(initialDate);
+
+ expect(copiedDate.getTime()).toBe(initialDate.getTime());
+
+ initialDate.setMonth(initialDate.getMonth() + 1);
+
+ expect(copiedDate.getTime()).not.toBe(initialDate.getTime());
+ });
+
+ it('returns date instance when provided date param is not of type date or is undefined', () => {
+ const initialDate = datetimeUtility.newDate();
+
+ expect(initialDate instanceof Date).toBe(true);
+ });
+});
diff --git a/spec/javascripts/lib/utils/file_upload_spec.js b/spec/javascripts/lib/utils/file_upload_spec.js
index 92c9cc70aaf..8f7092f63de 100644
--- a/spec/javascripts/lib/utils/file_upload_spec.js
+++ b/spec/javascripts/lib/utils/file_upload_spec.js
@@ -9,28 +9,56 @@ describe('File upload', () => {
<span class="js-filename"></span>
</form>
`);
+ });
+
+ describe('when there is a matching button and input', () => {
+ beforeEach(() => {
+ fileUpload('.js-button', '.js-input');
+ });
+
+ it('clicks file input after clicking button', () => {
+ const btn = document.querySelector('.js-button');
+ const input = document.querySelector('.js-input');
+
+ spyOn(input, 'click');
+
+ btn.click();
+
+ expect(input.click).toHaveBeenCalled();
+ });
+
+ it('updates file name text', () => {
+ const input = document.querySelector('.js-input');
- fileUpload('.js-button', '.js-input');
+ input.value = 'path/to/file/index.js';
+
+ input.dispatchEvent(new CustomEvent('change'));
+
+ expect(document.querySelector('.js-filename').textContent).toEqual('index.js');
+ });
});
- it('clicks file input after clicking button', () => {
- const btn = document.querySelector('.js-button');
+ it('fails gracefully when there is no matching button', () => {
const input = document.querySelector('.js-input');
+ const btn = document.querySelector('.js-button');
+ fileUpload('.js-not-button', '.js-input');
spyOn(input, 'click');
btn.click();
- expect(input.click).toHaveBeenCalled();
+ expect(input.click).not.toHaveBeenCalled();
});
- it('updates file name text', () => {
+ it('fails gracefully when there is no matching input', () => {
const input = document.querySelector('.js-input');
+ const btn = document.querySelector('.js-button');
+ fileUpload('.js-button', '.js-not-input');
- input.value = 'path/to/file/index.js';
+ spyOn(input, 'click');
- input.dispatchEvent(new CustomEvent('change'));
+ btn.click();
- expect(document.querySelector('.js-filename').textContent).toEqual('index.js');
+ expect(input.click).not.toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/lib/utils/grammar_spec.js b/spec/javascripts/lib/utils/grammar_spec.js
new file mode 100644
index 00000000000..377b2ffb48c
--- /dev/null
+++ b/spec/javascripts/lib/utils/grammar_spec.js
@@ -0,0 +1,35 @@
+import * as grammar from '~/lib/utils/grammar';
+
+describe('utils/grammar', () => {
+ describe('toNounSeriesText', () => {
+ it('with empty items returns empty string', () => {
+ expect(grammar.toNounSeriesText([])).toBe('');
+ });
+
+ it('with single item returns item', () => {
+ const items = ['Lorem Ipsum'];
+
+ expect(grammar.toNounSeriesText(items)).toBe(items[0]);
+ });
+
+ it('with 2 items returns item1 and item2', () => {
+ const items = ['Dolar', 'Sit Amit'];
+
+ expect(grammar.toNounSeriesText(items)).toBe(`${items[0]} and ${items[1]}`);
+ });
+
+ it('with 3 items returns comma separated series', () => {
+ const items = ['Lorem', 'Ipsum', 'dolar'];
+ const expected = 'Lorem, Ipsum, and dolar';
+
+ expect(grammar.toNounSeriesText(items)).toBe(expected);
+ });
+
+ it('with 6 items returns comma separated series', () => {
+ const items = ['Lorem', 'ipsum', 'dolar', 'sit', 'amit', 'consectetur'];
+ const expected = 'Lorem, ipsum, dolar, sit, amit, and consectetur';
+
+ expect(grammar.toNounSeriesText(items)).toBe(expected);
+ });
+ });
+});
diff --git a/spec/javascripts/lib/utils/icon_utils_spec.js b/spec/javascripts/lib/utils/icon_utils_spec.js
new file mode 100644
index 00000000000..3fd3940efe8
--- /dev/null
+++ b/spec/javascripts/lib/utils/icon_utils_spec.js
@@ -0,0 +1,67 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import * as iconUtils from '~/lib/utils/icon_utils';
+
+describe('Icon utils', () => {
+ describe('getSvgIconPathContent', () => {
+ let spriteIcons;
+
+ beforeAll(() => {
+ spriteIcons = gon.sprite_icons;
+ gon.sprite_icons = 'mockSpriteIconsEndpoint';
+ });
+
+ afterAll(() => {
+ gon.sprite_icons = spriteIcons;
+ });
+
+ let axiosMock;
+ let mockEndpoint;
+ let getIcon;
+ const mockName = 'mockIconName';
+ const mockPath = 'mockPath';
+
+ beforeEach(() => {
+ axiosMock = new MockAdapter(axios);
+ mockEndpoint = axiosMock.onGet(gon.sprite_icons);
+ getIcon = iconUtils.getSvgIconPathContent(mockName);
+ });
+
+ afterEach(() => {
+ axiosMock.restore();
+ });
+
+ it('extracts svg icon path content from sprite icons', done => {
+ mockEndpoint.replyOnce(
+ 200,
+ `<svg><symbol id="${mockName}"><path d="${mockPath}"/></symbol></svg>`,
+ );
+ getIcon
+ .then(path => {
+ expect(path).toBe(mockPath);
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('returns null if icon path content does not exist', done => {
+ mockEndpoint.replyOnce(200, ``);
+ getIcon
+ .then(path => {
+ expect(path).toBe(null);
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('returns null if an http error occurs', done => {
+ mockEndpoint.replyOnce(500);
+ getIcon
+ .then(path => {
+ expect(path).toBe(null);
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/javascripts/lib/utils/number_utility_spec.js b/spec/javascripts/lib/utils/number_utility_spec.js
index 94c6214c86a..818404bad81 100644
--- a/spec/javascripts/lib/utils/number_utility_spec.js
+++ b/spec/javascripts/lib/utils/number_utility_spec.js
@@ -4,6 +4,7 @@ import {
bytesToMiB,
bytesToGiB,
numberToHumanSize,
+ sum,
} from '~/lib/utils/number_utils';
describe('Number Utils', () => {
@@ -87,4 +88,14 @@ describe('Number Utils', () => {
expect(numberToHumanSize(10737418240)).toEqual('10.00 GiB');
});
});
+
+ describe('sum', () => {
+ it('should add up two values', () => {
+ expect(sum(1, 2)).toEqual(3);
+ });
+
+ it('should add up all the values in an array when passed to a reducer', () => {
+ expect([1, 2, 3, 4, 5].reduce(sum)).toEqual(15);
+ });
+ });
});
diff --git a/spec/javascripts/lib/utils/poll_spec.js b/spec/javascripts/lib/utils/poll_spec.js
index d0da659c3d7..138041a349f 100644
--- a/spec/javascripts/lib/utils/poll_spec.js
+++ b/spec/javascripts/lib/utils/poll_spec.js
@@ -153,6 +153,36 @@ describe('Poll', () => {
});
});
+ describe('enable', () => {
+ it('should enable polling upon a response', done => {
+ jasmine.clock().install();
+
+ const Polling = new Poll({
+ resource: service,
+ method: 'fetch',
+ data: { page: 1 },
+ successCallback: () => {},
+ });
+
+ Polling.enable({
+ data: { page: 4 },
+ response: { status: 200, headers: { 'poll-interval': 1 } },
+ });
+
+ jasmine.clock().tick(1);
+ jasmine.clock().uninstall();
+
+ waitForAllCallsToFinish(service, 1, () => {
+ Polling.stop();
+
+ expect(service.fetch.calls.count()).toEqual(1);
+ expect(service.fetch).toHaveBeenCalledWith({ page: 4 });
+ expect(Polling.options.data).toEqual({ page: 4 });
+ done();
+ });
+ });
+ });
+
describe('restart', () => {
it('should restart polling when its called', done => {
mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
@@ -171,6 +201,7 @@ describe('Poll', () => {
});
spyOn(Polling, 'stop').and.callThrough();
+ spyOn(Polling, 'enable').and.callThrough();
spyOn(Polling, 'restart').and.callThrough();
Polling.makeRequest();
@@ -181,6 +212,7 @@ describe('Poll', () => {
expect(service.fetch.calls.count()).toEqual(2);
expect(service.fetch).toHaveBeenCalledWith({ page: 4 });
expect(Polling.stop).toHaveBeenCalled();
+ expect(Polling.enable).toHaveBeenCalled();
expect(Polling.restart).toHaveBeenCalled();
expect(Polling.options.data).toEqual({ page: 4 });
done();
diff --git a/spec/javascripts/lib/utils/text_markdown_spec.js b/spec/javascripts/lib/utils/text_markdown_spec.js
index f71d27eb4e4..df4029555bb 100644
--- a/spec/javascripts/lib/utils/text_markdown_spec.js
+++ b/spec/javascripts/lib/utils/text_markdown_spec.js
@@ -13,215 +13,296 @@ describe('init markdown', () => {
textArea.parentNode.removeChild(textArea);
});
- describe('without selection', () => {
- it('inserts the tag on an empty line', () => {
- const initialValue = '';
+ describe('textArea', () => {
+ describe('without selection', () => {
+ it('inserts the tag on an empty line', () => {
+ const initialValue = '';
- textArea.value = initialValue;
- textArea.selectionStart = 0;
- textArea.selectionEnd = 0;
-
- insertMarkdownText({
- textArea,
- text: textArea.value,
- tag: '*',
- blockTag: null,
- selected: '',
- wrap: false,
- });
-
- expect(textArea.value).toEqual(`${initialValue}* `);
- });
-
- it('inserts the tag on a new line if the current one is not empty', () => {
- const initialValue = 'some text';
+ textArea.value = initialValue;
+ textArea.selectionStart = 0;
+ textArea.selectionEnd = 0;
- textArea.value = initialValue;
- textArea.setSelectionRange(initialValue.length, initialValue.length);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: false,
+ });
- insertMarkdownText({
- textArea,
- text: textArea.value,
- tag: '*',
- blockTag: null,
- selected: '',
- wrap: false,
+ expect(textArea.value).toEqual(`${initialValue}* `);
});
- expect(textArea.value).toEqual(`${initialValue}\n* `);
- });
+ it('inserts the tag on a new line if the current one is not empty', () => {
+ const initialValue = 'some text';
- it('inserts the tag on the same line if the current line only contains spaces', () => {
- const initialValue = ' ';
+ textArea.value = initialValue;
+ textArea.setSelectionRange(initialValue.length, initialValue.length);
- textArea.value = initialValue;
- textArea.setSelectionRange(initialValue.length, initialValue.length);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: false,
+ });
- insertMarkdownText({
- textArea,
- text: textArea.value,
- tag: '*',
- blockTag: null,
- selected: '',
- wrap: false,
+ expect(textArea.value).toEqual(`${initialValue}\n* `);
});
- expect(textArea.value).toEqual(`${initialValue}* `);
- });
+ it('inserts the tag on the same line if the current line only contains spaces', () => {
+ const initialValue = ' ';
- it('inserts the tag on the same line if the current line only contains tabs', () => {
- const initialValue = '\t\t\t';
+ textArea.value = initialValue;
+ textArea.setSelectionRange(initialValue.length, initialValue.length);
- textArea.value = initialValue;
- textArea.setSelectionRange(initialValue.length, initialValue.length);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: false,
+ });
- insertMarkdownText({
- textArea,
- text: textArea.value,
- tag: '*',
- blockTag: null,
- selected: '',
- wrap: false,
+ expect(textArea.value).toEqual(`${initialValue}* `);
});
- expect(textArea.value).toEqual(`${initialValue}* `);
- });
+ it('inserts the tag on the same line if the current line only contains tabs', () => {
+ const initialValue = '\t\t\t';
- it('places the cursor inside the tags', () => {
- const start = 'lorem ';
- const end = ' ipsum';
- const tag = '*';
+ textArea.value = initialValue;
+ textArea.setSelectionRange(initialValue.length, initialValue.length);
- textArea.value = `${start}${end}`;
- textArea.setSelectionRange(start.length, start.length);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: false,
+ });
- insertMarkdownText({
- textArea,
- text: textArea.value,
- tag,
- blockTag: null,
- selected: '',
- wrap: true,
+ expect(textArea.value).toEqual(`${initialValue}* `);
});
- expect(textArea.value).toEqual(`${start}**${end}`);
+ it('places the cursor inside the tags', () => {
+ const start = 'lorem ';
+ const end = ' ipsum';
+ const tag = '*';
- // cursor placement should be between tags
- expect(textArea.selectionStart).toBe(start.length + tag.length);
- });
- });
+ textArea.value = `${start}${end}`;
+ textArea.setSelectionRange(start.length, start.length);
- describe('with selection', () => {
- const text = 'initial selected value';
- const selected = 'selected';
- beforeEach(() => {
- textArea.value = text;
- const selectedIndex = text.indexOf(selected);
- textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
- });
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected: '',
+ wrap: true,
+ });
- it('applies the tag to the selected value', () => {
- const selectedIndex = text.indexOf(selected);
- const tag = '*';
+ expect(textArea.value).toEqual(`${start}**${end}`);
- insertMarkdownText({
- textArea,
- text: textArea.value,
- tag,
- blockTag: null,
- selected,
- wrap: true,
+ // cursor placement should be between tags
+ expect(textArea.selectionStart).toBe(start.length + tag.length);
});
-
- expect(textArea.value).toEqual(text.replace(selected, `*${selected}*`));
-
- // cursor placement should be after selection + 2 tag lengths
- expect(textArea.selectionStart).toBe(selectedIndex + selected.length + 2 * tag.length);
});
- it('replaces the placeholder in the tag', () => {
- insertMarkdownText({
- textArea,
- text: textArea.value,
- tag: '[{text}](url)',
- blockTag: null,
- selected,
- wrap: false,
+ describe('with selection', () => {
+ const text = 'initial selected value';
+ const selected = 'selected';
+ beforeEach(() => {
+ textArea.value = text;
+ const selectedIndex = text.indexOf(selected);
+ textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
});
- expect(textArea.value).toEqual(text.replace(selected, `[${selected}](url)`));
- });
+ it('applies the tag to the selected value', () => {
+ const selectedIndex = text.indexOf(selected);
+ const tag = '*';
- describe('and text to be selected', () => {
- const tag = '[{text}](url)';
- const select = 'url';
-
- it('selects the text', () => {
insertMarkdownText({
textArea,
text: textArea.value,
tag,
blockTag: null,
selected,
- wrap: false,
- select,
+ wrap: true,
});
- const expectedText = text.replace(selected, `[${selected}](url)`);
+ expect(textArea.value).toEqual(text.replace(selected, `*${selected}*`));
- expect(textArea.value).toEqual(expectedText);
- expect(textArea.selectionStart).toEqual(expectedText.indexOf(select));
- expect(textArea.selectionEnd).toEqual(expectedText.indexOf(select) + select.length);
+ // cursor placement should be after selection + 2 tag lengths
+ expect(textArea.selectionStart).toBe(selectedIndex + selected.length + 2 * tag.length);
});
- it('selects the right text when multiple tags are present', () => {
- const initialValue = `${tag} ${tag} ${selected}`;
- textArea.value = initialValue;
- const selectedIndex = initialValue.indexOf(selected);
- textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
+ it('replaces the placeholder in the tag', () => {
insertMarkdownText({
textArea,
text: textArea.value,
- tag,
+ tag: '[{text}](url)',
blockTag: null,
selected,
wrap: false,
- select,
});
- const expectedText = initialValue.replace(selected, `[${selected}](url)`);
-
- expect(textArea.value).toEqual(expectedText);
- expect(textArea.selectionStart).toEqual(expectedText.lastIndexOf(select));
- expect(textArea.selectionEnd).toEqual(expectedText.lastIndexOf(select) + select.length);
+ expect(textArea.value).toEqual(text.replace(selected, `[${selected}](url)`));
});
- it('should support selected urls', () => {
- const expectedUrl = 'http://www.gitlab.com';
- const expectedSelectionText = 'text';
- const expectedText = `text [${expectedSelectionText}](${expectedUrl}) text`;
- const initialValue = `text ${expectedUrl} text`;
+ describe('and text to be selected', () => {
+ const tag = '[{text}](url)';
+ const select = 'url';
+
+ it('selects the text', () => {
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected,
+ wrap: false,
+ select,
+ });
+
+ const expectedText = text.replace(selected, `[${selected}](url)`);
+
+ expect(textArea.value).toEqual(expectedText);
+ expect(textArea.selectionStart).toEqual(expectedText.indexOf(select));
+ expect(textArea.selectionEnd).toEqual(expectedText.indexOf(select) + select.length);
+ });
- textArea.value = initialValue;
- const selectedIndex = initialValue.indexOf(expectedUrl);
- textArea.setSelectionRange(selectedIndex, selectedIndex + expectedUrl.length);
+ it('selects the right text when multiple tags are present', () => {
+ const initialValue = `${tag} ${tag} ${selected}`;
+ textArea.value = initialValue;
+ const selectedIndex = initialValue.indexOf(selected);
+ textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected,
+ wrap: false,
+ select,
+ });
+
+ const expectedText = initialValue.replace(selected, `[${selected}](url)`);
+
+ expect(textArea.value).toEqual(expectedText);
+ expect(textArea.selectionStart).toEqual(expectedText.lastIndexOf(select));
+ expect(textArea.selectionEnd).toEqual(expectedText.lastIndexOf(select) + select.length);
+ });
- insertMarkdownText({
- textArea,
- text: textArea.value,
- tag,
- blockTag: null,
- selected: expectedUrl,
- wrap: false,
- select,
+ it('should support selected urls', () => {
+ const expectedUrl = 'http://www.gitlab.com';
+ const expectedSelectionText = 'text';
+ const expectedText = `text [${expectedSelectionText}](${expectedUrl}) text`;
+ const initialValue = `text ${expectedUrl} text`;
+
+ textArea.value = initialValue;
+ const selectedIndex = initialValue.indexOf(expectedUrl);
+ textArea.setSelectionRange(selectedIndex, selectedIndex + expectedUrl.length);
+
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected: expectedUrl,
+ wrap: false,
+ select,
+ });
+
+ expect(textArea.value).toEqual(expectedText);
+ expect(textArea.selectionStart).toEqual(expectedText.indexOf(expectedSelectionText, 1));
+ expect(textArea.selectionEnd).toEqual(
+ expectedText.indexOf(expectedSelectionText, 1) + expectedSelectionText.length,
+ );
});
+ });
+ });
+ });
+
+ describe('Ace Editor', () => {
+ let editor;
+
+ beforeEach(() => {
+ editor = {
+ getSelectionRange: () => ({
+ start: 0,
+ end: 0,
+ }),
+ getValue: () => 'this is text \n in two lines',
+ insert: () => {},
+ navigateLeft: () => {},
+ };
+ });
+
+ it('uses ace editor insert text when editor is passed in', () => {
+ spyOn(editor, 'insert');
- expect(textArea.value).toEqual(expectedText);
- expect(textArea.selectionStart).toEqual(expectedText.indexOf(expectedSelectionText, 1));
- expect(textArea.selectionEnd).toEqual(
- expectedText.indexOf(expectedSelectionText, 1) + expectedSelectionText.length,
- );
+ insertMarkdownText({
+ text: editor.getValue,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: false,
+ editor,
+ });
+
+ expect(editor.insert).toHaveBeenCalled();
+ });
+
+ it('adds block tags on line above and below selection', () => {
+ spyOn(editor, 'insert');
+
+ const selected = 'this text \n is multiple \n lines';
+ const text = `before \n ${selected} \n after`;
+
+ insertMarkdownText({
+ text,
+ tag: '',
+ blockTag: '***',
+ selected,
+ wrap: true,
+ editor,
+ });
+
+ expect(editor.insert).toHaveBeenCalledWith(`***\n${selected}\n***`);
+ });
+
+ it('uses ace editor to navigate back tag length when nothing is selected', () => {
+ spyOn(editor, 'navigateLeft');
+
+ insertMarkdownText({
+ text: editor.getValue,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: true,
+ editor,
});
+
+ expect(editor.navigateLeft).toHaveBeenCalledWith(1);
+ });
+
+ it('ace editor does not navigate back when there is selected text', () => {
+ spyOn(editor, 'navigateLeft');
+
+ insertMarkdownText({
+ text: editor.getValue,
+ tag: '*',
+ blockTag: null,
+ selected: 'foobar',
+ wrap: true,
+ editor,
+ });
+
+ expect(editor.navigateLeft).not.toHaveBeenCalled();
});
});
});
diff --git a/spec/javascripts/lib/utils/text_utility_spec.js b/spec/javascripts/lib/utils/text_utility_spec.js
index 92ebfc38722..0a266b19ea5 100644
--- a/spec/javascripts/lib/utils/text_utility_spec.js
+++ b/spec/javascripts/lib/utils/text_utility_spec.js
@@ -135,4 +135,20 @@ describe('text_utility', () => {
expect(textUtils.getFirstCharacterCapitalized(null)).toEqual('');
});
});
+
+ describe('truncatePathMiddleToLength', () => {
+ it('does not truncate text', () => {
+ expect(textUtils.truncatePathMiddleToLength('app/test', 50)).toEqual('app/test');
+ });
+
+ it('truncates middle of the path', () => {
+ expect(textUtils.truncatePathMiddleToLength('app/test/diff', 13)).toEqual('app/…/diff');
+ });
+
+ it('truncates multiple times in the middle of the path', () => {
+ expect(textUtils.truncatePathMiddleToLength('app/test/merge_request/diff', 13)).toEqual(
+ 'app/…/…/diff',
+ );
+ });
+ });
});
diff --git a/spec/javascripts/lib/utils/url_utility_spec.js b/spec/javascripts/lib/utils/url_utility_spec.js
index e4df8441793..381c7b2d0a6 100644
--- a/spec/javascripts/lib/utils/url_utility_spec.js
+++ b/spec/javascripts/lib/utils/url_utility_spec.js
@@ -1,4 +1,4 @@
-import { webIDEUrl, mergeUrlParams } from '~/lib/utils/url_utility';
+import * as urlUtils from '~/lib/utils/url_utility';
describe('URL utility', () => {
describe('webIDEUrl', () => {
@@ -8,7 +8,7 @@ describe('URL utility', () => {
describe('without relative_url_root', () => {
it('returns IDE path with route', () => {
- expect(webIDEUrl('/gitlab-org/gitlab-ce/merge_requests/1')).toBe(
+ expect(urlUtils.webIDEUrl('/gitlab-org/gitlab-ce/merge_requests/1')).toBe(
'/-/ide/project/gitlab-org/gitlab-ce/merge_requests/1',
);
});
@@ -20,7 +20,7 @@ describe('URL utility', () => {
});
it('returns IDE path with route', () => {
- expect(webIDEUrl('/gitlab/gitlab-org/gitlab-ce/merge_requests/1')).toBe(
+ expect(urlUtils.webIDEUrl('/gitlab/gitlab-org/gitlab-ce/merge_requests/1')).toBe(
'/gitlab/-/ide/project/gitlab-org/gitlab-ce/merge_requests/1',
);
});
@@ -29,23 +29,82 @@ describe('URL utility', () => {
describe('mergeUrlParams', () => {
it('adds w', () => {
- expect(mergeUrlParams({ w: 1 }, '#frag')).toBe('?w=1#frag');
- expect(mergeUrlParams({ w: 1 }, '/path#frag')).toBe('/path?w=1#frag');
- expect(mergeUrlParams({ w: 1 }, 'https://host/path')).toBe('https://host/path?w=1');
- expect(mergeUrlParams({ w: 1 }, 'https://host/path#frag')).toBe('https://host/path?w=1#frag');
- expect(mergeUrlParams({ w: 1 }, 'https://h/p?k1=v1#frag')).toBe('https://h/p?k1=v1&w=1#frag');
+ expect(urlUtils.mergeUrlParams({ w: 1 }, '#frag')).toBe('?w=1#frag');
+ expect(urlUtils.mergeUrlParams({ w: 1 }, '/path#frag')).toBe('/path?w=1#frag');
+ expect(urlUtils.mergeUrlParams({ w: 1 }, 'https://host/path')).toBe('https://host/path?w=1');
+ expect(urlUtils.mergeUrlParams({ w: 1 }, 'https://host/path#frag')).toBe(
+ 'https://host/path?w=1#frag',
+ );
+
+ expect(urlUtils.mergeUrlParams({ w: 1 }, 'https://h/p?k1=v1#frag')).toBe(
+ 'https://h/p?k1=v1&w=1#frag',
+ );
});
it('updates w', () => {
- expect(mergeUrlParams({ w: 1 }, '?k1=v1&w=0#frag')).toBe('?k1=v1&w=1#frag');
+ expect(urlUtils.mergeUrlParams({ w: 1 }, '?k1=v1&w=0#frag')).toBe('?k1=v1&w=1#frag');
});
it('adds multiple params', () => {
- expect(mergeUrlParams({ a: 1, b: 2, c: 3 }, '#frag')).toBe('?a=1&b=2&c=3#frag');
+ expect(urlUtils.mergeUrlParams({ a: 1, b: 2, c: 3 }, '#frag')).toBe('?a=1&b=2&c=3#frag');
});
it('adds and updates encoded params', () => {
- expect(mergeUrlParams({ a: '&', q: '?' }, '?a=%23#frag')).toBe('?a=%26&q=%3F#frag');
+ expect(urlUtils.mergeUrlParams({ a: '&', q: '?' }, '?a=%23#frag')).toBe('?a=%26&q=%3F#frag');
+ });
+ });
+
+ describe('removeParams', () => {
+ describe('when url is passed', () => {
+ it('removes query param with encoded ampersand', () => {
+ const url = urlUtils.removeParams(['filter'], '/mail?filter=n%3Djoe%26l%3Dhome');
+
+ expect(url).toBe('/mail');
+ });
+
+ it('should remove param when url has no other params', () => {
+ const url = urlUtils.removeParams(['size'], '/feature/home?size=5');
+
+ expect(url).toBe('/feature/home');
+ });
+
+ it('should remove param when url has other params', () => {
+ const url = urlUtils.removeParams(['size'], '/feature/home?q=1&size=5&f=html');
+
+ expect(url).toBe('/feature/home?q=1&f=html');
+ });
+
+ it('should remove param and preserve fragment', () => {
+ const url = urlUtils.removeParams(['size'], '/feature/home?size=5#H2');
+
+ expect(url).toBe('/feature/home#H2');
+ });
+
+ it('should remove multiple params', () => {
+ const url = urlUtils.removeParams(['z', 'a'], '/home?z=11111&l=en_US&a=true#H2');
+
+ expect(url).toBe('/home?l=en_US#H2');
+ });
+ });
+ });
+
+ describe('setUrlFragment', () => {
+ it('should set fragment when url has no fragment', () => {
+ const url = urlUtils.setUrlFragment('/home/feature', 'usage');
+
+ expect(url).toBe('/home/feature#usage');
+ });
+
+ it('should set fragment when url has existing fragment', () => {
+ const url = urlUtils.setUrlFragment('/home/feature#overview', 'usage');
+
+ expect(url).toBe('/home/feature#usage');
+ });
+
+ it('should set fragment when given fragment includes #', () => {
+ const url = urlUtils.setUrlFragment('/home/feature#overview', '#install');
+
+ expect(url).toBe('/home/feature#install');
});
});
});
diff --git a/spec/javascripts/matchers.js b/spec/javascripts/matchers.js
index 0d465510fd3..406527b08a3 100644
--- a/spec/javascripts/matchers.js
+++ b/spec/javascripts/matchers.js
@@ -1,3 +1,5 @@
+import pixelmatch from 'pixelmatch';
+
export default {
toContainText: () => ({
compare(vm, text) {
@@ -54,4 +56,41 @@ export default {
return result;
},
}),
+ toImageDiffEqual: () => {
+ const getImageData = img => {
+ const canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ canvas.getContext('2d').drawImage(img, 0, 0);
+ return canvas.getContext('2d').getImageData(0, 0, img.width, img.height).data;
+ };
+
+ return {
+ compare(actual, expected, threshold = 0.1) {
+ if (actual.height !== expected.height || actual.width !== expected.width) {
+ return {
+ pass: false,
+ message: `Expected image dimensions (h x w) of ${expected.height}x${expected.width}.
+ Received an image with ${actual.height}x${actual.width}`,
+ };
+ }
+
+ const { width, height } = actual;
+ const differentPixels = pixelmatch(
+ getImageData(actual),
+ getImageData(expected),
+ null,
+ width,
+ height,
+ { threshold },
+ );
+
+ return {
+ pass: differentPixels < 20,
+ message: `${differentPixels} pixels differ more than ${threshold *
+ 100} percent between input and output.`,
+ };
+ },
+ };
+ },
};
diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js
index 1cb49b49ca7..ab809930804 100644
--- a/spec/javascripts/merge_request_spec.js
+++ b/spec/javascripts/merge_request_spec.js
@@ -40,17 +40,51 @@ describe('MergeRequest', function() {
expect($('.js-task-list-field').val()).toBe('- [x] Task List Item');
});
- it('submits an ajax request on tasklist:changed', done => {
- $('.js-task-list-field').trigger('tasklist:changed');
-
- setTimeout(() => {
- expect(axios.patch).toHaveBeenCalledWith(
- `${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/merge_requests/1.json`,
- {
- merge_request: { description: '- [ ] Task List Item' },
- },
- );
- done();
+ describe('tasklist', () => {
+ const lineNumber = 8;
+ const lineSource = '- [ ] item 8';
+ const index = 3;
+ const checked = true;
+
+ it('submits an ajax request on tasklist:changed', done => {
+ $('.js-task-list-field').trigger({
+ type: 'tasklist:changed',
+ detail: { lineNumber, lineSource, index, checked },
+ });
+
+ setTimeout(() => {
+ expect(axios.patch).toHaveBeenCalledWith(
+ `${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/merge_requests/1.json`,
+ {
+ merge_request: {
+ description: '- [ ] Task List Item',
+ lock_version: undefined,
+ update_task: { line_number: lineNumber, line_source: lineSource, index, checked },
+ },
+ },
+ );
+
+ done();
+ });
+ });
+
+ it('shows an error notification when tasklist update failed', done => {
+ mock
+ .onPatch(`${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/merge_requests/1.json`)
+ .reply(409, {});
+
+ $('.js-task-list-field').trigger({
+ type: 'tasklist:changed',
+ detail: { lineNumber, lineSource, index, checked },
+ });
+
+ setTimeout(() => {
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ 'Someone edited this merge request at the same time you did. Please refresh the page to see changes.',
+ );
+
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/monitoring/charts/area_spec.js b/spec/javascripts/monitoring/charts/area_spec.js
new file mode 100644
index 00000000000..fb49290be19
--- /dev/null
+++ b/spec/javascripts/monitoring/charts/area_spec.js
@@ -0,0 +1,224 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlAreaChart } from '@gitlab/ui/dist/charts';
+import { shallowWrapperContainsSlotText } from 'spec/helpers/vue_test_utils_helper';
+import Area from '~/monitoring/components/charts/area.vue';
+import MonitoringStore from '~/monitoring/stores/monitoring_store';
+import MonitoringMock, { deploymentData } from '../mock_data';
+
+describe('Area component', () => {
+ const mockWidgets = 'mockWidgets';
+ const mockSvgPathContent = 'mockSvgPathContent';
+ let mockGraphData;
+ let areaChart;
+ let spriteSpy;
+
+ beforeEach(() => {
+ const store = new MonitoringStore();
+ store.storeMetrics(MonitoringMock.data);
+ store.storeDeploymentData(deploymentData);
+
+ [mockGraphData] = store.groups[0].metrics;
+
+ areaChart = shallowMount(Area, {
+ propsData: {
+ graphData: mockGraphData,
+ containerWidth: 0,
+ deploymentData: store.deploymentData,
+ },
+ slots: {
+ default: mockWidgets,
+ },
+ });
+
+ spriteSpy = spyOnDependency(Area, 'getSvgIconPathContent').and.callFake(
+ () => new Promise(resolve => resolve(mockSvgPathContent)),
+ );
+ });
+
+ afterEach(() => {
+ areaChart.destroy();
+ });
+
+ it('renders chart title', () => {
+ expect(areaChart.find({ ref: 'graphTitle' }).text()).toBe(mockGraphData.title);
+ });
+
+ it('contains graph widgets from slot', () => {
+ expect(areaChart.find({ ref: 'graphWidgets' }).text()).toBe(mockWidgets);
+ });
+
+ describe('wrapped components', () => {
+ describe('GitLab UI area chart', () => {
+ let glAreaChart;
+
+ beforeEach(() => {
+ glAreaChart = areaChart.find(GlAreaChart);
+ });
+
+ it('is a Vue instance', () => {
+ expect(glAreaChart.isVueInstance()).toBe(true);
+ });
+
+ it('receives data properties needed for proper chart render', () => {
+ const props = glAreaChart.props();
+
+ expect(props.data).toBe(areaChart.vm.chartData);
+ expect(props.option).toBe(areaChart.vm.chartOptions);
+ expect(props.formatTooltipText).toBe(areaChart.vm.formatTooltipText);
+ expect(props.thresholds).toBe(areaChart.props('alertData'));
+ });
+
+ it('recieves a tooltip title', () => {
+ const mockTitle = 'mockTitle';
+ areaChart.vm.tooltip.title = mockTitle;
+
+ expect(shallowWrapperContainsSlotText(glAreaChart, 'tooltipTitle', mockTitle)).toBe(true);
+ });
+
+ describe('when tooltip is showing deployment data', () => {
+ beforeEach(() => {
+ areaChart.vm.tooltip.isDeployment = true;
+ });
+
+ it('uses deployment title', () => {
+ expect(shallowWrapperContainsSlotText(glAreaChart, 'tooltipTitle', 'Deployed')).toBe(
+ true,
+ );
+ });
+
+ it('renders commit sha in tooltip content', () => {
+ const mockSha = 'mockSha';
+ areaChart.vm.tooltip.sha = mockSha;
+
+ expect(shallowWrapperContainsSlotText(glAreaChart, 'tooltipContent', mockSha)).toBe(true);
+ });
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('formatTooltipText', () => {
+ const mockDate = deploymentData[0].created_at;
+ const generateSeriesData = type => ({
+ seriesData: [
+ {
+ seriesName: areaChart.vm.chartData[0].name,
+ componentSubType: type,
+ value: [mockDate, 5.55555],
+ },
+ ],
+ value: mockDate,
+ });
+
+ describe('series is of line type', () => {
+ beforeEach(() => {
+ areaChart.vm.formatTooltipText(generateSeriesData('line'));
+ });
+
+ it('formats tooltip title', () => {
+ expect(areaChart.vm.tooltip.title).toBe('31 May 2017, 9:23PM');
+ });
+
+ it('formats tooltip content', () => {
+ expect(areaChart.vm.tooltip.content).toEqual([{ name: 'Core Usage', value: '5.556' }]);
+ expect(
+ shallowWrapperContainsSlotText(
+ areaChart.find(GlAreaChart),
+ 'tooltipContent',
+ 'Core Usage 5.556',
+ ),
+ ).toBe(true);
+ });
+ });
+
+ describe('series is of scatter type', () => {
+ beforeEach(() => {
+ areaChart.vm.formatTooltipText(generateSeriesData('scatter'));
+ });
+
+ it('formats tooltip title', () => {
+ expect(areaChart.vm.tooltip.title).toBe('31 May 2017, 9:23PM');
+ });
+
+ it('formats tooltip sha', () => {
+ expect(areaChart.vm.tooltip.sha).toBe('f5bcd1d9');
+ });
+ });
+ });
+
+ describe('setSvg', () => {
+ const mockSvgName = 'mockSvgName';
+
+ beforeEach(() => {
+ areaChart.vm.setSvg(mockSvgName);
+ });
+
+ it('gets svg path content', () => {
+ expect(spriteSpy).toHaveBeenCalledWith(mockSvgName);
+ });
+
+ it('sets svg path content', done => {
+ areaChart.vm.$nextTick(() => {
+ expect(areaChart.vm.svgs[mockSvgName]).toBe(`path://${mockSvgPathContent}`);
+ done();
+ });
+ });
+ });
+
+ describe('onResize', () => {
+ const mockWidth = 233;
+
+ beforeEach(() => {
+ spyOn(Element.prototype, 'getBoundingClientRect').and.callFake(() => ({
+ width: mockWidth,
+ }));
+ areaChart.vm.onResize();
+ });
+
+ it('sets area chart width', () => {
+ expect(areaChart.vm.width).toBe(mockWidth);
+ });
+ });
+ });
+
+ describe('computed', () => {
+ describe('chartData', () => {
+ let chartData;
+ const seriesData = () => chartData[0];
+
+ beforeEach(() => {
+ ({ chartData } = areaChart.vm);
+ });
+
+ it('utilizes all data points', () => {
+ expect(chartData.length).toBe(1);
+ expect(seriesData().data.length).toBe(297);
+ });
+
+ it('creates valid data', () => {
+ const { data } = seriesData();
+
+ expect(
+ data.filter(([time, value]) => new Date(time).getTime() > 0 && typeof value === 'number')
+ .length,
+ ).toBe(data.length);
+ });
+ });
+
+ describe('scatterSeries', () => {
+ it('utilizes deployment data', () => {
+ expect(areaChart.vm.scatterSeries.data).toEqual([
+ ['2017-05-31T21:23:37.881Z', 0],
+ ['2017-05-30T20:08:04.629Z', 0],
+ ['2017-05-30T17:42:38.409Z', 0],
+ ]);
+ });
+ });
+
+ describe('yAxisLabel', () => {
+ it('constructs a label for the chart y-axis', () => {
+ expect(areaChart.vm.yAxisLabel).toBe('CPU');
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index 565b87de248..b1778029a77 100644
--- a/spec/javascripts/monitoring/dashboard_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -25,15 +25,22 @@ export default propsData;
describe('Dashboard', () => {
let DashboardComponent;
+ let mock;
beforeEach(() => {
setFixtures(`
<div class="prometheus-graphs"></div>
- <div class="nav-sidebar"></div>
+ <div class="layout-page"></div>
`);
+
+ mock = new MockAdapter(axios);
DashboardComponent = Vue.extend(Dashboard);
});
+ afterEach(() => {
+ mock.restore();
+ });
+
describe('no metrics are available yet', () => {
it('shows a getting started empty state when no metrics are present', () => {
const component = new DashboardComponent({
@@ -47,16 +54,10 @@ describe('Dashboard', () => {
});
describe('requests information to the server', () => {
- let mock;
beforeEach(() => {
- mock = new MockAdapter(axios);
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
});
- afterEach(() => {
- mock.restore();
- });
-
it('shows up a loading state', done => {
const component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
@@ -152,28 +153,25 @@ describe('Dashboard', () => {
});
describe('when the window resizes', () => {
- let mock;
beforeEach(() => {
- mock = new MockAdapter(axios);
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
jasmine.clock().install();
});
afterEach(() => {
- mock.restore();
jasmine.clock().uninstall();
});
- it('rerenders the dashboard when the sidebar is resized', done => {
+ it('sets elWidth to page width when the sidebar is resized', done => {
const component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: { ...propsData, hasMetrics: true, showPanels: false },
});
- expect(component.forceRedraw).toEqual(0);
+ expect(component.elWidth).toEqual(0);
- const navSidebarEl = document.querySelector('.nav-sidebar');
- navSidebarEl.classList.add('nav-sidebar-collapsed');
+ const pageLayoutEl = document.querySelector('.layout-page');
+ pageLayoutEl.classList.add('page-with-icon-sidebar');
Vue.nextTick()
.then(() => {
@@ -181,7 +179,7 @@ describe('Dashboard', () => {
return Vue.nextTick();
})
.then(() => {
- expect(component.forceRedraw).toEqual(component.elWidth);
+ expect(component.elWidth).toEqual(pageLayoutEl.clientWidth);
done();
})
.catch(done.fail);
diff --git a/spec/javascripts/monitoring/graph/axis_spec.js b/spec/javascripts/monitoring/graph/axis_spec.js
deleted file mode 100644
index c7adba00637..00000000000
--- a/spec/javascripts/monitoring/graph/axis_spec.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import Vue from 'vue';
-import GraphAxis from '~/monitoring/components/graph/axis.vue';
-import measurements from '~/monitoring/utils/measurements';
-
-const createComponent = propsData => {
- const Component = Vue.extend(GraphAxis);
-
- return new Component({
- propsData,
- }).$mount();
-};
-
-const defaultValuesComponent = {
- graphWidth: 500,
- graphHeight: 300,
- graphHeightOffset: 120,
- margin: measurements.large.margin,
- measurements: measurements.large,
- yAxisLabel: 'Values',
- unitOfDisplay: 'MB',
-};
-
-function getTextFromNode(component, selector) {
- return component.$el.querySelector(selector).firstChild.nodeValue.trim();
-}
-
-describe('Axis', () => {
- describe('Computed props', () => {
- it('textTransform', () => {
- const component = createComponent(defaultValuesComponent);
-
- expect(component.textTransform).toContain('translate(15, 120) rotate(-90)');
- });
-
- it('xPosition', () => {
- const component = createComponent(defaultValuesComponent);
-
- expect(component.xPosition).toEqual(180);
- });
-
- it('yPosition', () => {
- const component = createComponent(defaultValuesComponent);
-
- expect(component.yPosition).toEqual(240);
- });
-
- it('rectTransform', () => {
- const component = createComponent(defaultValuesComponent);
-
- expect(component.rectTransform).toContain('translate(0, 120) rotate(-90)');
- });
- });
-
- it('has 2 rect-axis-text rect svg elements', () => {
- const component = createComponent(defaultValuesComponent);
-
- expect(component.$el.querySelectorAll('.rect-axis-text').length).toEqual(2);
- });
-
- it('contains text to signal the usage, title and time with multiple time series', () => {
- const component = createComponent(defaultValuesComponent);
-
- expect(getTextFromNode(component, '.y-label-text')).toEqual('Values (MB)');
- });
-});
diff --git a/spec/javascripts/monitoring/graph/deployment_spec.js b/spec/javascripts/monitoring/graph/deployment_spec.js
deleted file mode 100644
index 7d39c4345d2..00000000000
--- a/spec/javascripts/monitoring/graph/deployment_spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import Vue from 'vue';
-import GraphDeployment from '~/monitoring/components/graph/deployment.vue';
-import { deploymentData } from '../mock_data';
-
-const createComponent = propsData => {
- const Component = Vue.extend(GraphDeployment);
-
- return new Component({
- propsData,
- }).$mount();
-};
-
-describe('MonitoringDeployment', () => {
- describe('Methods', () => {
- it('should contain a hidden gradient', () => {
- const component = createComponent({
- showDeployInfo: true,
- deploymentData,
- graphHeight: 300,
- graphWidth: 440,
- graphHeightOffset: 120,
- });
-
- expect(component.$el.querySelector('#shadow-gradient')).not.toBeNull();
- });
-
- it('transformDeploymentGroup translates an available deployment', () => {
- const component = createComponent({
- showDeployInfo: false,
- deploymentData,
- graphHeight: 300,
- graphWidth: 440,
- graphHeightOffset: 120,
- });
-
- expect(component.transformDeploymentGroup({ xPos: 16 })).toContain('translate(11, 20)');
- });
-
- describe('Computed props', () => {
- it('calculatedHeight', () => {
- const component = createComponent({
- showDeployInfo: true,
- deploymentData,
- graphHeight: 300,
- graphWidth: 440,
- graphHeightOffset: 120,
- });
-
- expect(component.calculatedHeight).toEqual(180);
- });
- });
- });
-});
diff --git a/spec/javascripts/monitoring/graph/flag_spec.js b/spec/javascripts/monitoring/graph/flag_spec.js
deleted file mode 100644
index 038bfffd44f..00000000000
--- a/spec/javascripts/monitoring/graph/flag_spec.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import Vue from 'vue';
-import GraphFlag from '~/monitoring/components/graph/flag.vue';
-import { deploymentData } from '../mock_data';
-
-const createComponent = propsData => {
- const Component = Vue.extend(GraphFlag);
-
- return new Component({
- propsData,
- }).$mount();
-};
-
-const defaultValuesComponent = {
- currentXCoordinate: 200,
- currentYCoordinate: 100,
- currentFlagPosition: 100,
- currentData: {
- time: new Date('2017-06-04T18:17:33.501Z'),
- value: '1.49609375',
- },
- graphHeight: 300,
- graphHeightOffset: 120,
- showFlagContent: true,
- realPixelRatio: 1,
- timeSeries: [
- {
- values: [
- {
- time: new Date('2017-06-04T18:17:33.501Z'),
- value: '1.49609375',
- },
- ],
- },
- ],
- unitOfDisplay: 'ms',
- currentDataIndex: 0,
- legendTitle: 'Average',
- currentCoordinates: {},
-};
-
-const deploymentFlagData = {
- ...deploymentData[0],
- ref: deploymentData[0].ref.name,
- xPos: 10,
- time: new Date(deploymentData[0].created_at),
-};
-
-describe('GraphFlag', () => {
- let component;
-
- it('has a line at the currentXCoordinate', () => {
- component = createComponent(defaultValuesComponent);
-
- expect(component.$el.style.left).toEqual(`${70 + component.currentXCoordinate}px`);
- });
-
- describe('Deployment flag', () => {
- it('shows a deployment flag when deployment data provided', () => {
- const deploymentFlagComponent = createComponent({
- ...defaultValuesComponent,
- deploymentFlagData,
- });
-
- expect(deploymentFlagComponent.$el.querySelector('.popover-title')).toContainText('Deployed');
- });
-
- it('contains the ref when a tag is available', () => {
- const deploymentFlagComponent = createComponent({
- ...defaultValuesComponent,
- deploymentFlagData: {
- ...deploymentFlagData,
- sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
- tag: true,
- ref: '1.0',
- },
- });
-
- expect(deploymentFlagComponent.$el.querySelector('.deploy-meta-content')).toContainText(
- 'f5bcd1d9',
- );
-
- expect(deploymentFlagComponent.$el.querySelector('.deploy-meta-content')).toContainText(
- '1.0',
- );
- });
-
- it('does not contain the ref when a tag is unavailable', () => {
- const deploymentFlagComponent = createComponent({
- ...defaultValuesComponent,
- deploymentFlagData: {
- ...deploymentFlagData,
- sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
- tag: false,
- ref: '1.0',
- },
- });
-
- expect(deploymentFlagComponent.$el.querySelector('.deploy-meta-content')).toContainText(
- 'f5bcd1d9',
- );
-
- expect(deploymentFlagComponent.$el.querySelector('.deploy-meta-content')).not.toContainText(
- '1.0',
- );
- });
- });
-
- describe('Computed props', () => {
- beforeEach(() => {
- component = createComponent(defaultValuesComponent);
- });
-
- it('formatTime', () => {
- expect(component.formatTime).toMatch(/\d:17PM/);
- });
-
- it('formatDate', () => {
- expect(component.formatDate).toEqual('04 Jun 2017, ');
- });
-
- it('cursorStyle', () => {
- expect(component.cursorStyle).toEqual({
- top: '20px',
- left: '270px',
- height: '180px',
- });
- });
-
- it('flagOrientation', () => {
- expect(component.flagOrientation).toEqual('left');
- });
- });
-});
diff --git a/spec/javascripts/monitoring/graph/legend_spec.js b/spec/javascripts/monitoring/graph/legend_spec.js
deleted file mode 100644
index 9209e77dcf4..00000000000
--- a/spec/javascripts/monitoring/graph/legend_spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import Vue from 'vue';
-import GraphLegend from '~/monitoring/components/graph/legend.vue';
-import createTimeSeries from '~/monitoring/utils/multiple_time_series';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { singleRowMetricsMultipleSeries, convertDatesMultipleSeries } from '../mock_data';
-
-const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-
-const defaultValuesComponent = {};
-
-const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 500, 300, 120);
-
-defaultValuesComponent.timeSeries = timeSeries;
-
-describe('Legend Component', () => {
- let vm;
- let Legend;
-
- beforeEach(() => {
- Legend = Vue.extend(GraphLegend);
- });
-
- describe('View', () => {
- beforeEach(() => {
- vm = mountComponent(Legend, {
- legendTitle: 'legend',
- timeSeries,
- currentDataIndex: 0,
- unitOfDisplay: 'Req/Sec',
- });
- });
-
- it('should render the usage, title and time with multiple time series', () => {
- const titles = vm.$el.querySelectorAll('.legend-metric-title');
-
- expect(titles[0].textContent.indexOf('1xx')).not.toEqual(-1);
- expect(titles[1].textContent.indexOf('2xx')).not.toEqual(-1);
- });
-
- it('should container the same number of rows in the table as time series', () => {
- expect(vm.$el.querySelectorAll('.prometheus-table tr').length).toEqual(vm.timeSeries.length);
- });
- });
-});
diff --git a/spec/javascripts/monitoring/graph/track_info_spec.js b/spec/javascripts/monitoring/graph/track_info_spec.js
deleted file mode 100644
index ce93ae28842..00000000000
--- a/spec/javascripts/monitoring/graph/track_info_spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import Vue from 'vue';
-import TrackInfo from '~/monitoring/components/graph/track_info.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import createTimeSeries from '~/monitoring/utils/multiple_time_series';
-import { singleRowMetricsMultipleSeries, convertDatesMultipleSeries } from '../mock_data';
-
-const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 500, 300, 120);
-
-describe('TrackInfo component', () => {
- let vm;
- let Component;
-
- beforeEach(() => {
- Component = Vue.extend(TrackInfo);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('Computed props', () => {
- beforeEach(() => {
- vm = mountComponent(Component, { track: timeSeries[0] });
- });
-
- it('summaryMetrics', () => {
- expect(vm.summaryMetrics).toEqual('Avg: 0.000 · Max: 0.000');
- });
- });
-
- describe('Rendered output', () => {
- beforeEach(() => {
- vm = mountComponent(Component, { track: timeSeries[0] });
- });
-
- it('contains metric tag and the summary metrics', () => {
- const metricTag = vm.$el.querySelector('strong');
-
- expect(metricTag.textContent.trim()).toEqual(vm.track.metricTag);
- expect(vm.$el.textContent).toContain('Avg: 0.000 · Max: 0.000');
- });
- });
-});
diff --git a/spec/javascripts/monitoring/graph/track_line_spec.js b/spec/javascripts/monitoring/graph/track_line_spec.js
deleted file mode 100644
index 2a4f89ddf6e..00000000000
--- a/spec/javascripts/monitoring/graph/track_line_spec.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import Vue from 'vue';
-import TrackLine from '~/monitoring/components/graph/track_line.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import createTimeSeries from '~/monitoring/utils/multiple_time_series';
-import { singleRowMetricsMultipleSeries, convertDatesMultipleSeries } from '../mock_data';
-
-const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 500, 300, 120);
-
-describe('TrackLine component', () => {
- let vm;
- let Component;
-
- beforeEach(() => {
- Component = Vue.extend(TrackLine);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('Computed props', () => {
- it('stylizedLine for dashed lineStyles', () => {
- vm = mountComponent(Component, { track: { ...timeSeries[0], lineStyle: 'dashed' } });
-
- expect(vm.stylizedLine).toEqual('6, 3');
- });
-
- it('stylizedLine for dotted lineStyles', () => {
- vm = mountComponent(Component, { track: { ...timeSeries[0], lineStyle: 'dotted' } });
-
- expect(vm.stylizedLine).toEqual('3, 3');
- });
- });
-
- describe('Rendered output', () => {
- it('has an svg with a line', () => {
- vm = mountComponent(Component, { track: { ...timeSeries[0] } });
- const svgEl = vm.$el.querySelector('svg');
- const lineEl = vm.$el.querySelector('svg line');
-
- expect(svgEl.getAttribute('width')).toEqual('16');
- expect(svgEl.getAttribute('height')).toEqual('8');
-
- expect(lineEl.getAttribute('stroke-width')).toEqual('4');
- expect(lineEl.getAttribute('x1')).toEqual('0');
- expect(lineEl.getAttribute('x2')).toEqual('16');
- expect(lineEl.getAttribute('y1')).toEqual('4');
- expect(lineEl.getAttribute('y2')).toEqual('4');
- });
- });
-});
diff --git a/spec/javascripts/monitoring/graph_path_spec.js b/spec/javascripts/monitoring/graph_path_spec.js
deleted file mode 100644
index fd167b83d51..00000000000
--- a/spec/javascripts/monitoring/graph_path_spec.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import Vue from 'vue';
-import GraphPath from '~/monitoring/components/graph/path.vue';
-import createTimeSeries from '~/monitoring/utils/multiple_time_series';
-import { singleRowMetricsMultipleSeries, convertDatesMultipleSeries } from './mock_data';
-
-const createComponent = propsData => {
- const Component = Vue.extend(GraphPath);
-
- return new Component({
- propsData,
- }).$mount();
-};
-
-const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-
-const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 428, 272, 120);
-const firstTimeSeries = timeSeries[0];
-
-describe('Monitoring Paths', () => {
- it('renders two paths to represent a line and the area underneath it', () => {
- const component = createComponent({
- generatedLinePath: firstTimeSeries.linePath,
- generatedAreaPath: firstTimeSeries.areaPath,
- lineColor: firstTimeSeries.lineColor,
- areaColor: firstTimeSeries.areaColor,
- showDot: false,
- });
- const metricArea = component.$el.querySelector('.metric-area');
- const metricLine = component.$el.querySelector('.metric-line');
-
- expect(metricArea.getAttribute('fill')).toBe('#8fbce8');
- expect(metricArea.getAttribute('d')).toBe(firstTimeSeries.areaPath);
- expect(metricLine.getAttribute('stroke')).toBe('#1f78d1');
- expect(metricLine.getAttribute('d')).toBe(firstTimeSeries.linePath);
- });
-
- describe('Computed properties', () => {
- it('strokeDashArray', () => {
- const component = createComponent({
- generatedLinePath: firstTimeSeries.linePath,
- generatedAreaPath: firstTimeSeries.areaPath,
- lineColor: firstTimeSeries.lineColor,
- areaColor: firstTimeSeries.areaColor,
- showDot: false,
- });
-
- component.lineStyle = 'dashed';
-
- expect(component.strokeDashArray).toBe('3, 1');
-
- component.lineStyle = 'dotted';
-
- expect(component.strokeDashArray).toBe('1, 1');
- });
- });
-});
diff --git a/spec/javascripts/monitoring/graph_spec.js b/spec/javascripts/monitoring/graph_spec.js
deleted file mode 100644
index 59d6d4f3a7f..00000000000
--- a/spec/javascripts/monitoring/graph_spec.js
+++ /dev/null
@@ -1,127 +0,0 @@
-import Vue from 'vue';
-import Graph from '~/monitoring/components/graph.vue';
-import MonitoringMixins from '~/monitoring/mixins/monitoring_mixins';
-import {
- deploymentData,
- convertDatesMultipleSeries,
- singleRowMetricsMultipleSeries,
- queryWithoutData,
-} from './mock_data';
-
-const tagsPath = 'http://test.host/frontend-fixtures/environments-project/tags';
-const projectPath = 'http://test.host/frontend-fixtures/environments-project';
-const createComponent = propsData => {
- const Component = Vue.extend(Graph);
-
- return new Component({
- propsData,
- }).$mount();
-};
-
-const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-
-describe('Graph', () => {
- beforeEach(() => {
- spyOn(MonitoringMixins.methods, 'formatDeployments').and.returnValue({});
- });
-
- it('has a title', () => {
- const component = createComponent({
- graphData: convertedMetrics[1],
- updateAspectRatio: false,
- deploymentData,
- tagsPath,
- projectPath,
- });
-
- expect(component.$el.querySelector('.prometheus-graph-title').innerText.trim()).toBe(
- component.graphData.title,
- );
- });
-
- describe('Computed props', () => {
- it('axisTransform translates an element Y position depending of its height', () => {
- const component = createComponent({
- graphData: convertedMetrics[1],
- updateAspectRatio: false,
- deploymentData,
- tagsPath,
- projectPath,
- });
-
- const transformedHeight = `${component.graphHeight - 100}`;
-
- expect(component.axisTransform.indexOf(transformedHeight)).not.toEqual(-1);
- });
-
- it('outerViewBox gets a width and height property based on the DOM size of the element', () => {
- const component = createComponent({
- graphData: convertedMetrics[1],
- updateAspectRatio: false,
- deploymentData,
- tagsPath,
- projectPath,
- });
-
- const viewBoxArray = component.outerViewBox.split(' ');
-
- expect(typeof component.outerViewBox).toEqual('string');
- expect(viewBoxArray[2]).toEqual(component.graphWidth.toString());
- expect(viewBoxArray[3]).toEqual((component.graphHeight - 50).toString());
- });
- });
-
- it('has a title for the y-axis and the chart legend that comes from the backend', () => {
- const component = createComponent({
- graphData: convertedMetrics[1],
- updateAspectRatio: false,
- deploymentData,
- tagsPath,
- projectPath,
- });
-
- expect(component.yAxisLabel).toEqual(component.graphData.y_label);
- expect(component.legendTitle).toEqual(component.graphData.queries[0].label);
- });
-
- it('sets the currentData object based on the hovered data index', () => {
- const component = createComponent({
- graphData: convertedMetrics[1],
- updateAspectRatio: false,
- deploymentData,
- graphIdentifier: 0,
- hoverData: {
- hoveredDate: new Date('Sun Aug 27 2017 06:11:51 GMT-0500 (CDT)'),
- currentDeployXPos: null,
- },
- tagsPath,
- projectPath,
- });
-
- // simulate moving mouse over data series
- component.seriesUnderMouse = component.timeSeries;
-
- component.positionFlag();
-
- expect(component.currentData).toBe(component.timeSeries[0].values[10]);
- });
-
- describe('Without data to display', () => {
- it('shows a "no data to display" empty state on a graph', done => {
- const component = createComponent({
- graphData: queryWithoutData,
- deploymentData,
- tagsPath,
- projectPath,
- });
-
- Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.js-no-data-to-display text').textContent.trim(),
- ).toEqual('No data to display');
-
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js
index 18ad9843d22..ffc7148fde2 100644
--- a/spec/javascripts/monitoring/mock_data.js
+++ b/spec/javascripts/monitoring/mock_data.js
@@ -326,6 +326,7 @@ export const metricsGroupsAPIResponse = {
{
id: 6,
title: 'CPU usage',
+ y_label: 'CPU',
weight: 1,
queries: [
{
@@ -6597,58 +6598,46 @@ export function convertDatesMultipleSeries(multipleSeries) {
export const environmentData = [
{
+ id: 34,
name: 'production',
- size: 1,
- latest: {
- id: 34,
- name: 'production',
- state: 'available',
- external_url: 'http://root-autodevops-deploy.my-fake-domain.com',
- environment_type: null,
- stop_action: false,
- metrics_path: '/root/hello-prometheus/environments/34/metrics',
- environment_path: '/root/hello-prometheus/environments/34',
- stop_path: '/root/hello-prometheus/environments/34/stop',
- terminal_path: '/root/hello-prometheus/environments/34/terminal',
- folder_path: '/root/hello-prometheus/environments/folders/production',
- created_at: '2018-06-29T16:53:38.301Z',
- updated_at: '2018-06-29T16:57:09.825Z',
- last_deployment: {
- id: 127,
- },
+ state: 'available',
+ external_url: 'http://root-autodevops-deploy.my-fake-domain.com',
+ environment_type: null,
+ stop_action: false,
+ metrics_path: '/root/hello-prometheus/environments/34/metrics',
+ environment_path: '/root/hello-prometheus/environments/34',
+ stop_path: '/root/hello-prometheus/environments/34/stop',
+ terminal_path: '/root/hello-prometheus/environments/34/terminal',
+ folder_path: '/root/hello-prometheus/environments/folders/production',
+ created_at: '2018-06-29T16:53:38.301Z',
+ updated_at: '2018-06-29T16:57:09.825Z',
+ last_deployment: {
+ id: 127,
},
},
{
- name: 'review',
- size: 1,
- latest: {
- id: 35,
- name: 'review/noop-branch',
- state: 'available',
- external_url: 'http://root-autodevops-deploy-review-noop-branc-die93w.my-fake-domain.com',
- environment_type: 'review',
- stop_action: true,
- metrics_path: '/root/hello-prometheus/environments/35/metrics',
- environment_path: '/root/hello-prometheus/environments/35',
- stop_path: '/root/hello-prometheus/environments/35/stop',
- terminal_path: '/root/hello-prometheus/environments/35/terminal',
- folder_path: '/root/hello-prometheus/environments/folders/review',
- created_at: '2018-07-03T18:39:41.702Z',
- updated_at: '2018-07-03T18:44:54.010Z',
- last_deployment: {
- id: 128,
- },
+ id: 35,
+ name: 'review/noop-branch',
+ state: 'available',
+ external_url: 'http://root-autodevops-deploy-review-noop-branc-die93w.my-fake-domain.com',
+ environment_type: 'review',
+ stop_action: true,
+ metrics_path: '/root/hello-prometheus/environments/35/metrics',
+ environment_path: '/root/hello-prometheus/environments/35',
+ stop_path: '/root/hello-prometheus/environments/35/stop',
+ terminal_path: '/root/hello-prometheus/environments/35/terminal',
+ folder_path: '/root/hello-prometheus/environments/folders/review',
+ created_at: '2018-07-03T18:39:41.702Z',
+ updated_at: '2018-07-03T18:44:54.010Z',
+ last_deployment: {
+ id: 128,
},
},
{
- name: 'no-deployment',
- size: 1,
- latest: {
- id: 36,
- name: 'no-deployment/noop-branch',
- state: 'available',
- created_at: '2018-07-04T18:39:41.702Z',
- updated_at: '2018-07-04T18:44:54.010Z',
- },
+ id: 36,
+ name: 'no-deployment/noop-branch',
+ state: 'available',
+ created_at: '2018-07-04T18:39:41.702Z',
+ updated_at: '2018-07-04T18:44:54.010Z',
},
];
diff --git a/spec/javascripts/monitoring/utils/multiple_time_series_spec.js b/spec/javascripts/monitoring/utils/multiple_time_series_spec.js
deleted file mode 100644
index 8937b7d9680..00000000000
--- a/spec/javascripts/monitoring/utils/multiple_time_series_spec.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import createTimeSeries from '~/monitoring/utils/multiple_time_series';
-import { convertDatesMultipleSeries, singleRowMetricsMultipleSeries } from '../mock_data';
-
-const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 428, 272, 120);
-const firstTimeSeries = timeSeries[0];
-
-describe('Multiple time series', () => {
- it('createTimeSeries returned array contains an object for each element', () => {
- expect(typeof firstTimeSeries.linePath).toEqual('string');
- expect(typeof firstTimeSeries.areaPath).toEqual('string');
- expect(typeof firstTimeSeries.timeSeriesScaleX).toEqual('function');
- expect(typeof firstTimeSeries.areaColor).toEqual('string');
- expect(typeof firstTimeSeries.lineColor).toEqual('string');
- expect(firstTimeSeries.values instanceof Array).toEqual(true);
- });
-
- it('createTimeSeries returns an array', () => {
- expect(timeSeries instanceof Array).toEqual(true);
- expect(timeSeries.length).toEqual(2);
- });
-});
diff --git a/spec/javascripts/notebook/cells/output/html_spec.js b/spec/javascripts/notebook/cells/output/html_spec.js
index bea62f54634..3ee404fb187 100644
--- a/spec/javascripts/notebook/cells/output/html_spec.js
+++ b/spec/javascripts/notebook/cells/output/html_spec.js
@@ -9,6 +9,8 @@ describe('html output cell', () => {
return new Component({
propsData: {
rawCode,
+ count: 0,
+ index: 0,
},
}).$mount();
}
diff --git a/spec/javascripts/notebook/cells/output/index_spec.js b/spec/javascripts/notebook/cells/output/index_spec.js
index feab7ad4212..005569f1c2d 100644
--- a/spec/javascripts/notebook/cells/output/index_spec.js
+++ b/spec/javascripts/notebook/cells/output/index_spec.js
@@ -10,7 +10,7 @@ describe('Output component', () => {
const createComponent = output => {
vm = new Component({
propsData: {
- output,
+ outputs: [].concat(output),
count: 1,
},
});
@@ -51,28 +51,21 @@ describe('Output component', () => {
it('renders as an image', () => {
expect(vm.$el.querySelector('img')).not.toBeNull();
});
-
- it('does not render the prompt', () => {
- expect(vm.$el.querySelector('.prompt span')).toBeNull();
- });
});
describe('html output', () => {
- beforeEach(done => {
+ it('renders raw HTML', () => {
createComponent(json.cells[4].outputs[0]);
- setTimeout(() => {
- done();
- });
- });
-
- it('renders raw HTML', () => {
expect(vm.$el.querySelector('p')).not.toBeNull();
- expect(vm.$el.textContent.trim()).toBe('test');
+ expect(vm.$el.querySelectorAll('p').length).toBe(1);
+ expect(vm.$el.textContent.trim()).toContain('test');
});
- it('does not render the prompt', () => {
- expect(vm.$el.querySelector('.prompt span')).toBeNull();
+ it('renders multiple raw HTML outputs', () => {
+ createComponent([json.cells[4].outputs[0], json.cells[4].outputs[0]]);
+
+ expect(vm.$el.querySelectorAll('p').length).toBe(2);
});
});
@@ -88,10 +81,6 @@ describe('Output component', () => {
it('renders as an svg', () => {
expect(vm.$el.querySelector('svg')).not.toBeNull();
});
-
- it('does not render the prompt', () => {
- expect(vm.$el.querySelector('.prompt span')).toBeNull();
- });
});
describe('default to plain text', () => {
diff --git a/spec/javascripts/notes/components/comment_form_spec.js b/spec/javascripts/notes/components/comment_form_spec.js
index 3c57fe51352..362963ddaf4 100644
--- a/spec/javascripts/notes/components/comment_form_spec.js
+++ b/spec/javascripts/notes/components/comment_form_spec.js
@@ -223,7 +223,6 @@ describe('issue_comment_form component', () => {
'Comment & close issue',
);
- expect(vm.$el.querySelector('.js-note-discard')).toBeDefined();
done();
});
});
diff --git a/spec/javascripts/notes/components/discussion_counter_spec.js b/spec/javascripts/notes/components/discussion_counter_spec.js
index d09bc5037ef..fecc0d604b1 100644
--- a/spec/javascripts/notes/components/discussion_counter_spec.js
+++ b/spec/javascripts/notes/components/discussion_counter_spec.js
@@ -33,11 +33,13 @@ describe('DiscussionCounter component', () => {
...discussionMock,
id: discussionMock.id,
notes: [{ ...discussionMock.notes[0], resolvable: true, resolved: true }],
+ resolved: true,
},
{
...discussionMock,
id: discussionMock.id + 1,
notes: [{ ...discussionMock.notes[0], resolvable: true, resolved: false }],
+ resolved: false,
},
];
const firstDiscussionId = discussionMock.id + 1;
diff --git a/spec/javascripts/notes/components/discussion_filter_note_spec.js b/spec/javascripts/notes/components/discussion_filter_note_spec.js
new file mode 100644
index 00000000000..52d2e7ce947
--- /dev/null
+++ b/spec/javascripts/notes/components/discussion_filter_note_spec.js
@@ -0,0 +1,93 @@
+import Vue from 'vue';
+import DiscussionFilterNote from '~/notes/components/discussion_filter_note.vue';
+import eventHub from '~/notes/event_hub';
+
+import mountComponent from '../../helpers/vue_mount_component_helper';
+
+describe('DiscussionFilterNote component', () => {
+ let vm;
+
+ const createComponent = () => {
+ const Component = Vue.extend(DiscussionFilterNote);
+
+ return mountComponent(Component);
+ };
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('computed', () => {
+ describe('timelineContent', () => {
+ it('returns string containing instruction for switching feed type', () => {
+ expect(vm.timelineContent).toBe(
+ "You're only seeing <b>other activity</b> in the feed. To add a comment, switch to one of the following options.",
+ );
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('selectFilter', () => {
+ it('emits `dropdownSelect` event on `eventHub` with provided param', () => {
+ spyOn(eventHub, '$emit');
+
+ vm.selectFilter(1);
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 1);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders component container element', () => {
+ expect(vm.$el.classList.contains('discussion-filter-note')).toBe(true);
+ });
+
+ it('renders comment icon element', () => {
+ expect(vm.$el.querySelector('.timeline-icon svg use').getAttribute('xlink:href')).toContain(
+ 'comment',
+ );
+ });
+
+ it('renders filter information note', () => {
+ expect(vm.$el.querySelector('.timeline-content').innerText.trim()).toContain(
+ "You're only seeing other activity in the feed. To add a comment, switch to one of the following options.",
+ );
+ });
+
+ it('renders filter buttons', () => {
+ const buttonsContainerEl = vm.$el.querySelector('.discussion-filter-actions');
+
+ expect(buttonsContainerEl.querySelector('button:first-child').innerText.trim()).toContain(
+ 'Show all activity',
+ );
+
+ expect(buttonsContainerEl.querySelector('button:last-child').innerText.trim()).toContain(
+ 'Show comments only',
+ );
+ });
+
+ it('clicking `Show all activity` button calls `selectFilter("all")` method', () => {
+ const showAllBtn = vm.$el.querySelector('.discussion-filter-actions button:first-child');
+ spyOn(vm, 'selectFilter');
+
+ showAllBtn.dispatchEvent(new Event('click'));
+
+ expect(vm.selectFilter).toHaveBeenCalledWith(0);
+ });
+
+ it('clicking `Show comments only` button calls `selectFilter("comments")` method', () => {
+ const showAllBtn = vm.$el.querySelector('.discussion-filter-actions button:last-child');
+ spyOn(vm, 'selectFilter');
+
+ showAllBtn.dispatchEvent(new Event('click'));
+
+ expect(vm.selectFilter).toHaveBeenCalledWith(1);
+ });
+ });
+});
diff --git a/spec/javascripts/notes/components/discussion_filter_spec.js b/spec/javascripts/notes/components/discussion_filter_spec.js
index 9070d968cfd..1c366aee8e2 100644
--- a/spec/javascripts/notes/components/discussion_filter_spec.js
+++ b/spec/javascripts/notes/components/discussion_filter_spec.js
@@ -1,14 +1,16 @@
import Vue from 'vue';
import createStore from '~/notes/stores';
import DiscussionFilter from '~/notes/components/discussion_filter.vue';
+import { DISCUSSION_FILTERS_DEFAULT_VALUE, DISCUSSION_FILTER_TYPES } from '~/notes/constants';
import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
import { discussionFiltersMock, discussionMock } from '../mock_data';
describe('DiscussionFilter component', () => {
let vm;
let store;
+ let eventHub;
- beforeEach(() => {
+ const mountComponent = () => {
store = createStore();
const discussions = [
@@ -19,17 +21,20 @@ describe('DiscussionFilter component', () => {
},
];
const Component = Vue.extend(DiscussionFilter);
- const selectedValue = discussionFiltersMock[0].value;
+ const selectedValue = DISCUSSION_FILTERS_DEFAULT_VALUE;
+ const props = { filters: discussionFiltersMock, selectedValue };
store.state.discussions = discussions;
- vm = mountComponentWithStore(Component, {
+ return mountComponentWithStore(Component, {
el: null,
store,
- props: {
- filters: discussionFiltersMock,
- selectedValue,
- },
+ props,
});
+ };
+
+ beforeEach(() => {
+ window.mrTabs = undefined;
+ vm = mountComponent();
});
afterEach(() => {
@@ -49,14 +54,18 @@ describe('DiscussionFilter component', () => {
});
it('updates to the selected item', () => {
- const filterItem = vm.$el.querySelector('.dropdown-menu li:last-child button');
+ const filterItem = vm.$el.querySelector(
+ `.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.HISTORY}"] button`,
+ );
filterItem.click();
expect(vm.currentFilter.title).toEqual(filterItem.textContent.trim());
});
it('only updates when selected filter changes', () => {
- const filterItem = vm.$el.querySelector('.dropdown-menu li:first-child button');
+ const filterItem = vm.$el.querySelector(
+ `.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.ALL}"] button`,
+ );
spyOn(vm, 'filterDiscussion');
filterItem.click();
@@ -65,22 +74,91 @@ describe('DiscussionFilter component', () => {
});
it('disables commenting when "Show history only" filter is applied', () => {
- const filterItem = vm.$el.querySelector('.dropdown-menu li:last-child button');
+ const filterItem = vm.$el.querySelector(
+ `.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.HISTORY}"] button`,
+ );
filterItem.click();
expect(vm.$store.state.commentsDisabled).toBe(true);
});
it('enables commenting when "Show history only" filter is not applied', () => {
- const filterItem = vm.$el.querySelector('.dropdown-menu li:first-child button');
+ const filterItem = vm.$el.querySelector(
+ `.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.ALL}"] button`,
+ );
filterItem.click();
expect(vm.$store.state.commentsDisabled).toBe(false);
});
it('renders a dropdown divider for the default filter', () => {
- const defaultFilter = vm.$el.querySelector('.dropdown-menu li:first-child');
+ const defaultFilter = vm.$el.querySelector(
+ `.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.ALL}"]`,
+ );
expect(defaultFilter.lastChild.classList).toContain('dropdown-divider');
});
+
+ describe('Merge request tabs', () => {
+ eventHub = new Vue();
+
+ beforeEach(() => {
+ window.mrTabs = {
+ eventHub,
+ currentTab: 'show',
+ };
+
+ vm = mountComponent();
+ });
+
+ afterEach(() => {
+ window.mrTabs = undefined;
+ });
+
+ it('only renders when discussion tab is active', done => {
+ eventHub.$emit('MergeRequestTabChange', 'commit');
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector).toBeUndefined();
+ done();
+ });
+ });
+ });
+
+ describe('URL with Links to notes', () => {
+ afterEach(() => {
+ window.location.hash = '';
+ });
+
+ it('updates the filter when the URL links to a note', done => {
+ window.location.hash = `note_${discussionMock.notes[0].id}`;
+ vm.currentValue = discussionFiltersMock[2].value;
+ vm.handleLocationHash();
+
+ vm.$nextTick(() => {
+ expect(vm.currentValue).toEqual(DISCUSSION_FILTERS_DEFAULT_VALUE);
+ done();
+ });
+ });
+
+ it('does not update the filter when the current filter is "Show all activity"', done => {
+ window.location.hash = `note_${discussionMock.notes[0].id}`;
+ vm.handleLocationHash();
+
+ vm.$nextTick(() => {
+ expect(vm.currentValue).toEqual(DISCUSSION_FILTERS_DEFAULT_VALUE);
+ done();
+ });
+ });
+
+ it('only updates filter when the URL links to a note', done => {
+ window.location.hash = `testing123`;
+ vm.handleLocationHash();
+
+ vm.$nextTick(() => {
+ expect(vm.currentValue).toEqual(DISCUSSION_FILTERS_DEFAULT_VALUE);
+ done();
+ });
+ });
+ });
});
diff --git a/spec/javascripts/notes/components/discussion_reply_placeholder_spec.js b/spec/javascripts/notes/components/discussion_reply_placeholder_spec.js
new file mode 100644
index 00000000000..07a366cf339
--- /dev/null
+++ b/spec/javascripts/notes/components/discussion_reply_placeholder_spec.js
@@ -0,0 +1,34 @@
+import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+
+const localVue = createLocalVue();
+
+describe('ReplyPlaceholder', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = shallowMount(ReplyPlaceholder, {
+ localVue,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('emits onClick even on button click', () => {
+ const button = wrapper.find({ ref: 'button' });
+
+ button.trigger('click');
+
+ expect(wrapper.emitted()).toEqual({
+ onClick: [[]],
+ });
+ });
+
+ it('should render reply button', () => {
+ const button = wrapper.find({ ref: 'button' });
+
+ expect(button.text()).toEqual('Reply...');
+ });
+});
diff --git a/spec/javascripts/notes/components/discussion_resolve_button_spec.js b/spec/javascripts/notes/components/discussion_resolve_button_spec.js
new file mode 100644
index 00000000000..5024f40ec5d
--- /dev/null
+++ b/spec/javascripts/notes/components/discussion_resolve_button_spec.js
@@ -0,0 +1,74 @@
+import resolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+
+const buttonTitle = 'Resolve discussion';
+
+describe('resolveDiscussionButton', () => {
+ let wrapper;
+ let localVue;
+
+ const factory = options => {
+ localVue = createLocalVue();
+ wrapper = shallowMount(resolveDiscussionButton, {
+ localVue,
+ ...options,
+ });
+ };
+
+ beforeEach(() => {
+ factory({
+ propsData: {
+ isResolving: false,
+ buttonTitle,
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should emit a onClick event on button click', () => {
+ const button = wrapper.find({ ref: 'button' });
+
+ button.trigger('click');
+
+ expect(wrapper.emitted()).toEqual({
+ onClick: [[]],
+ });
+ });
+
+ it('should contain the provided button title', () => {
+ const button = wrapper.find({ ref: 'button' });
+
+ expect(button.text()).toContain(buttonTitle);
+ });
+
+ it('should show a loading spinner while resolving', () => {
+ factory({
+ propsData: {
+ isResolving: true,
+ buttonTitle,
+ },
+ });
+
+ const button = wrapper.find({ ref: 'isResolvingIcon' });
+
+ expect(button.exists()).toEqual(true);
+ });
+
+ it('should only show a loading spinner while resolving', () => {
+ factory({
+ propsData: {
+ isResolving: false,
+ buttonTitle,
+ },
+ });
+
+ const button = wrapper.find({ ref: 'isResolvingIcon' });
+
+ localVue.nextTick(() => {
+ expect(button.exists()).toEqual(false);
+ });
+ });
+});
diff --git a/spec/javascripts/notes/components/discussion_resolve_with_issue_button_spec.js b/spec/javascripts/notes/components/discussion_resolve_with_issue_button_spec.js
new file mode 100644
index 00000000000..b2a91c9919a
--- /dev/null
+++ b/spec/javascripts/notes/components/discussion_resolve_with_issue_button_spec.js
@@ -0,0 +1,31 @@
+import { GlButton } from '@gitlab/ui';
+import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { TEST_HOST } from 'spec/test_constants';
+
+const localVue = createLocalVue();
+
+describe('ResolveWithIssueButton', () => {
+ let wrapper;
+ const url = `${TEST_HOST}/hello-world/`;
+
+ beforeEach(() => {
+ wrapper = shallowMount(ResolveWithIssueButton, {
+ localVue,
+ sync: false,
+ propsData: {
+ url,
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('it should have a link with the provided link property as href', () => {
+ const button = wrapper.find(GlButton);
+
+ expect(button.attributes().href).toBe(url);
+ });
+});
diff --git a/spec/javascripts/notes/components/note_actions/reply_button_spec.js b/spec/javascripts/notes/components/note_actions/reply_button_spec.js
new file mode 100644
index 00000000000..11fb89808d9
--- /dev/null
+++ b/spec/javascripts/notes/components/note_actions/reply_button_spec.js
@@ -0,0 +1,32 @@
+import Vuex from 'vuex';
+import { createLocalVue, mount } from '@vue/test-utils';
+import ReplyButton from '~/notes/components/note_actions/reply_button.vue';
+
+describe('ReplyButton', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ const localVue = createLocalVue();
+
+ localVue.use(Vuex);
+
+ wrapper = mount(ReplyButton, {
+ sync: false,
+ localVue,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('emits startReplying on click', () => {
+ const button = wrapper.find({ ref: 'button' });
+
+ button.trigger('click');
+
+ expect(wrapper.emitted()).toEqual({
+ startReplying: [[]],
+ });
+ });
+});
diff --git a/spec/javascripts/notes/components/note_actions_spec.js b/spec/javascripts/notes/components/note_actions_spec.js
index f6c854e6def..d604e90b529 100644
--- a/spec/javascripts/notes/components/note_actions_spec.js
+++ b/spec/javascripts/notes/components/note_actions_spec.js
@@ -1,113 +1,214 @@
import Vue from 'vue';
+import { shallowMount, createLocalVue, createWrapper } from '@vue/test-utils';
import createStore from '~/notes/stores';
import noteActions from '~/notes/components/note_actions.vue';
+import { TEST_HOST } from 'spec/test_constants';
import { userDataMock } from '../mock_data';
-describe('issue_note_actions component', () => {
- let vm;
+describe('noteActions', () => {
+ let wrapper;
let store;
- let Component;
+ let props;
+
+ const shallowMountNoteActions = propsData => {
+ const localVue = createLocalVue();
+ return shallowMount(noteActions, {
+ store,
+ propsData,
+ localVue,
+ sync: false,
+ });
+ };
beforeEach(() => {
- Component = Vue.extend(noteActions);
store = createStore();
+ props = {
+ accessLevel: 'Maintainer',
+ authorId: 26,
+ canDelete: true,
+ canEdit: true,
+ canAwardEmoji: true,
+ canReportAsAbuse: true,
+ noteId: '539',
+ noteUrl: `${TEST_HOST}/group/project/merge_requests/1#note_1`,
+ reportAbusePath: `${TEST_HOST}/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F7%23note_539&user_id=26`,
+ showReply: false,
+ };
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('user is logged in', () => {
- let props;
-
beforeEach(() => {
- props = {
- accessLevel: 'Maintainer',
- authorId: 26,
- canDelete: true,
- canEdit: true,
- canAwardEmoji: true,
- canReportAsAbuse: true,
- noteId: '539',
- noteUrl: 'https://localhost:3000/group/project/merge_requests/1#note_1',
- reportAbusePath:
- '/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F7%23note_539&user_id=26',
- };
-
store.dispatch('setUserData', userDataMock);
- vm = new Component({
- store,
- propsData: props,
- }).$mount();
+ wrapper = shallowMountNoteActions(props);
});
it('should render access level badge', () => {
- expect(vm.$el.querySelector('.note-role').textContent.trim()).toEqual(props.accessLevel);
+ expect(
+ wrapper
+ .find('.note-role')
+ .text()
+ .trim(),
+ ).toEqual(props.accessLevel);
});
it('should render emoji link', () => {
- expect(vm.$el.querySelector('.js-add-award')).toBeDefined();
+ expect(wrapper.find('.js-add-award').exists()).toBe(true);
});
describe('actions dropdown', () => {
it('should be possible to edit the comment', () => {
- expect(vm.$el.querySelector('.js-note-edit')).toBeDefined();
+ expect(wrapper.find('.js-note-edit').exists()).toBe(true);
});
it('should be possible to report abuse to GitLab', () => {
- expect(vm.$el.querySelector(`a[href="${props.reportAbusePath}"]`)).toBeDefined();
+ expect(wrapper.find(`a[href="${props.reportAbusePath}"]`).exists()).toBe(true);
});
it('should be possible to copy link to a note', () => {
- expect(vm.$el.querySelector('.js-btn-copy-note-link')).not.toBeNull();
+ expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(true);
});
it('should not show copy link action when `noteUrl` prop is empty', done => {
- vm.noteUrl = '';
+ wrapper.setProps({
+ ...props,
+ noteUrl: '',
+ });
+
Vue.nextTick()
.then(() => {
- expect(vm.$el.querySelector('.js-btn-copy-note-link')).toBeNull();
+ expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(false);
})
.then(done)
.catch(done.fail);
});
it('should be possible to delete comment', () => {
- expect(vm.$el.querySelector('.js-note-delete')).toBeDefined();
+ expect(wrapper.find('.js-note-delete').exists()).toBe(true);
+ });
+
+ it('closes tooltip when dropdown opens', done => {
+ wrapper.find('.more-actions-toggle').trigger('click');
+
+ const rootWrapper = createWrapper(wrapper.vm.$root);
+ Vue.nextTick()
+ .then(() => {
+ const emitted = Object.keys(rootWrapper.emitted());
+
+ expect(emitted).toEqual(['bv::hide::tooltip']);
+ done();
+ })
+ .catch(done.fail);
});
});
});
describe('user is not logged in', () => {
- let props;
-
beforeEach(() => {
store.dispatch('setUserData', {});
- props = {
- accessLevel: 'Maintainer',
- authorId: 26,
+ wrapper = shallowMountNoteActions({
+ ...props,
canDelete: false,
canEdit: false,
canAwardEmoji: false,
canReportAsAbuse: false,
- noteId: '539',
- noteUrl: 'https://localhost:3000/group/project/merge_requests/1#note_1',
- reportAbusePath:
- '/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F7%23note_539&user_id=26',
- };
- vm = new Component({
- store,
- propsData: props,
- }).$mount();
+ });
});
it('should not render emoji link', () => {
- expect(vm.$el.querySelector('.js-add-award')).toEqual(null);
+ expect(wrapper.find('.js-add-award').exists()).toBe(false);
});
it('should not render actions dropdown', () => {
- expect(vm.$el.querySelector('.more-actions')).toEqual(null);
+ expect(wrapper.find('.more-actions').exists()).toBe(false);
+ });
+ });
+
+ describe('with feature flag replyToIndividualNotes enabled', () => {
+ beforeEach(() => {
+ gon.features = {
+ replyToIndividualNotes: true,
+ };
+ });
+
+ afterEach(() => {
+ gon.features = {};
+ });
+
+ describe('for showReply = true', () => {
+ beforeEach(() => {
+ wrapper = shallowMountNoteActions({
+ ...props,
+ showReply: true,
+ });
+ });
+
+ it('shows a reply button', () => {
+ const replyButton = wrapper.find({ ref: 'replyButton' });
+
+ expect(replyButton.exists()).toBe(true);
+ });
+ });
+
+ describe('for showReply = false', () => {
+ beforeEach(() => {
+ wrapper = shallowMountNoteActions({
+ ...props,
+ showReply: false,
+ });
+ });
+
+ it('does not show a reply button', () => {
+ const replyButton = wrapper.find({ ref: 'replyButton' });
+
+ expect(replyButton.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('with feature flag replyToIndividualNotes disabled', () => {
+ beforeEach(() => {
+ gon.features = {
+ replyToIndividualNotes: false,
+ };
+ });
+
+ afterEach(() => {
+ gon.features = {};
+ });
+
+ describe('for showReply = true', () => {
+ beforeEach(() => {
+ wrapper = shallowMountNoteActions({
+ ...props,
+ showReply: true,
+ });
+ });
+
+ it('does not show a reply button', () => {
+ const replyButton = wrapper.find({ ref: 'replyButton' });
+
+ expect(replyButton.exists()).toBe(false);
+ });
+ });
+
+ describe('for showReply = false', () => {
+ beforeEach(() => {
+ wrapper = shallowMountNoteActions({
+ ...props,
+ showReply: false,
+ });
+ });
+
+ it('does not show a reply button', () => {
+ const replyButton = wrapper.find({ ref: 'replyButton' });
+
+ expect(replyButton.exists()).toBe(false);
+ });
});
});
});
diff --git a/spec/javascripts/notes/components/note_app_spec.js b/spec/javascripts/notes/components/note_app_spec.js
index 22bee049f9c..d716ece3766 100644
--- a/spec/javascripts/notes/components/note_app_spec.js
+++ b/spec/javascripts/notes/components/note_app_spec.js
@@ -1,57 +1,49 @@
import $ from 'jquery';
import _ from 'underscore';
import Vue from 'vue';
-import notesApp from '~/notes/components/notes_app.vue';
+import { mount, createLocalVue } from '@vue/test-utils';
+import NotesApp from '~/notes/components/notes_app.vue';
import service from '~/notes/services/notes_service';
import createStore from '~/notes/stores';
import '~/behaviors/markdown/render_gfm';
-import { mountComponentWithStore } from 'spec/helpers';
import * as mockData from '../mock_data';
-const vueMatchers = {
- toIncludeElement() {
- return {
- compare(vm, selector) {
- const result = {
- pass: vm.$el.querySelector(selector) !== null,
- };
- return result;
- },
- };
- },
-};
-
describe('note_app', () => {
let mountComponent;
- let vm;
+ let wrapper;
let store;
beforeEach(() => {
- jasmine.addMatchers(vueMatchers);
$('body').attr('data-page', 'projects:merge_requests:show');
- setFixtures('<div class="js-vue-notes-event"><div id="app"></div></div>');
-
- const IssueNotesApp = Vue.extend(notesApp);
-
store = createStore();
mountComponent = data => {
- const props = data || {
+ const propsData = data || {
noteableData: mockData.noteableDataMock,
notesData: mockData.notesDataMock,
userData: mockData.userDataMock,
};
-
- return mountComponentWithStore(IssueNotesApp, {
- props,
- store,
- el: document.getElementById('app'),
- });
+ const localVue = createLocalVue();
+
+ return mount(
+ {
+ components: {
+ NotesApp,
+ },
+ template: '<div class="js-vue-notes-event"><notes-app v-bind="$attrs" /></div>',
+ },
+ {
+ propsData,
+ store,
+ localVue,
+ sync: false,
+ },
+ );
};
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('set data', () => {
@@ -65,7 +57,7 @@ describe('note_app', () => {
beforeEach(() => {
Vue.http.interceptors.push(responseInterceptor);
- vm = mountComponent();
+ wrapper = mountComponent();
});
afterEach(() => {
@@ -73,26 +65,28 @@ describe('note_app', () => {
});
it('should set notes data', () => {
- expect(vm.$store.state.notesData).toEqual(mockData.notesDataMock);
+ expect(store.state.notesData).toEqual(mockData.notesDataMock);
});
it('should set issue data', () => {
- expect(vm.$store.state.noteableData).toEqual(mockData.noteableDataMock);
+ expect(store.state.noteableData).toEqual(mockData.noteableDataMock);
});
it('should set user data', () => {
- expect(vm.$store.state.userData).toEqual(mockData.userDataMock);
+ expect(store.state.userData).toEqual(mockData.userDataMock);
});
it('should fetch discussions', () => {
- expect(vm.$store.state.discussions).toEqual([]);
+ expect(store.state.discussions).toEqual([]);
});
});
describe('render', () => {
beforeEach(() => {
+ setFixtures('<div class="js-discussions-count"></div>');
+
Vue.http.interceptors.push(mockData.individualNoteInterceptor);
- vm = mountComponent();
+ wrapper = mountComponent();
});
afterEach(() => {
@@ -107,51 +101,65 @@ describe('note_app', () => {
setTimeout(() => {
expect(
- vm.$el.querySelector('.main-notes-list .note-header-author-name').textContent.trim(),
+ wrapper
+ .find('.main-notes-list .note-header-author-name')
+ .text()
+ .trim(),
).toEqual(note.author.name);
- expect(vm.$el.querySelector('.main-notes-list .note-text').innerHTML).toEqual(
- note.note_html,
- );
+ expect(wrapper.find('.main-notes-list .note-text').html()).toContain(note.note_html);
done();
}, 0);
});
it('should render form', () => {
- expect(vm.$el.querySelector('.js-main-target-form').tagName).toEqual('FORM');
- expect(
- vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'),
- ).toEqual('Write a comment or drag your files here…');
+ expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
+ expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
+ 'Write a comment or drag your files here…',
+ );
});
it('should not render form when commenting is disabled', () => {
store.state.commentsDisabled = true;
- vm = mountComponent();
+ wrapper = mountComponent();
+
+ expect(wrapper.find('.js-main-target-form').exists()).toBe(false);
+ });
+
+ it('should render discussion filter note `commentsDisabled` is true', () => {
+ store.state.commentsDisabled = true;
+ wrapper = mountComponent();
- expect(vm.$el.querySelector('.js-main-target-form')).toEqual(null);
+ expect(wrapper.find('.js-discussion-filter-note').exists()).toBe(true);
});
it('should render form comment button as disabled', () => {
- expect(vm.$el.querySelector('.js-note-new-discussion').getAttribute('disabled')).toEqual(
- 'disabled',
- );
+ expect(wrapper.find('.js-note-new-discussion').attributes('disabled')).toEqual('disabled');
+ });
+
+ it('updates discussions badge', done => {
+ setTimeout(() => {
+ expect(document.querySelector('.js-discussions-count').textContent).toEqual('2');
+
+ done();
+ });
});
});
describe('while fetching data', () => {
beforeEach(() => {
- vm = mountComponent();
+ wrapper = mountComponent();
});
it('renders skeleton notes', () => {
- expect(vm).toIncludeElement('.animation-container');
+ expect(wrapper.find('.animation-container').exists()).toBe(true);
});
it('should render form', () => {
- expect(vm.$el.querySelector('.js-main-target-form').tagName).toEqual('FORM');
- expect(
- vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'),
- ).toEqual('Write a comment or drag your files here…');
+ expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
+ expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
+ 'Write a comment or drag your files here…',
+ );
});
});
@@ -160,9 +168,9 @@ describe('note_app', () => {
beforeEach(done => {
Vue.http.interceptors.push(mockData.individualNoteInterceptor);
spyOn(service, 'updateNote').and.callThrough();
- vm = mountComponent();
+ wrapper = mountComponent();
setTimeout(() => {
- vm.$el.querySelector('.js-note-edit').click();
+ wrapper.find('.js-note-edit').trigger('click');
Vue.nextTick(done);
}, 0);
});
@@ -175,12 +183,12 @@ describe('note_app', () => {
});
it('renders edit form', () => {
- expect(vm).toIncludeElement('.js-vue-issue-note-form');
+ expect(wrapper.find('.js-vue-issue-note-form').exists()).toBe(true);
});
it('calls the service to update the note', done => {
- vm.$el.querySelector('.js-vue-issue-note-form').value = 'this is a note';
- vm.$el.querySelector('.js-vue-issue-save').click();
+ wrapper.find('.js-vue-issue-note-form').value = 'this is a note';
+ wrapper.find('.js-vue-issue-save').trigger('click');
expect(service.updateNote).toHaveBeenCalled();
// Wait for the requests to finish before destroying
@@ -194,10 +202,10 @@ describe('note_app', () => {
beforeEach(done => {
Vue.http.interceptors.push(mockData.discussionNoteInterceptor);
spyOn(service, 'updateNote').and.callThrough();
- vm = mountComponent();
+ wrapper = mountComponent();
setTimeout(() => {
- vm.$el.querySelector('.js-note-edit').click();
+ wrapper.find('.js-note-edit').trigger('click');
Vue.nextTick(done);
}, 0);
});
@@ -210,12 +218,12 @@ describe('note_app', () => {
});
it('renders edit form', () => {
- expect(vm).toIncludeElement('.js-vue-issue-note-form');
+ expect(wrapper.find('.js-vue-issue-note-form').exists()).toBe(true);
});
it('updates the note and resets the edit form', done => {
- vm.$el.querySelector('.js-vue-issue-note-form').value = 'this is a note';
- vm.$el.querySelector('.js-vue-issue-save').click();
+ wrapper.find('.js-vue-issue-note-form').value = 'this is a note';
+ wrapper.find('.js-vue-issue-save').trigger('click');
expect(service.updateNote).toHaveBeenCalled();
// Wait for the requests to finish before destroying
@@ -228,30 +236,36 @@ describe('note_app', () => {
describe('new note form', () => {
beforeEach(() => {
- vm = mountComponent();
+ wrapper = mountComponent();
});
it('should render markdown docs url', () => {
const { markdownDocsPath } = mockData.notesDataMock;
- expect(vm.$el.querySelector(`a[href="${markdownDocsPath}"]`).textContent.trim()).toEqual(
- 'Markdown',
- );
+ expect(
+ wrapper
+ .find(`a[href="${markdownDocsPath}"]`)
+ .text()
+ .trim(),
+ ).toEqual('Markdown');
});
it('should render quick action docs url', () => {
const { quickActionsDocsPath } = mockData.notesDataMock;
- expect(vm.$el.querySelector(`a[href="${quickActionsDocsPath}"]`).textContent.trim()).toEqual(
- 'quick actions',
- );
+ expect(
+ wrapper
+ .find(`a[href="${quickActionsDocsPath}"]`)
+ .text()
+ .trim(),
+ ).toEqual('quick actions');
});
});
describe('edit form', () => {
beforeEach(() => {
Vue.http.interceptors.push(mockData.individualNoteInterceptor);
- vm = mountComponent();
+ wrapper = mountComponent();
});
afterEach(() => {
@@ -260,12 +274,15 @@ describe('note_app', () => {
it('should render markdown docs url', done => {
setTimeout(() => {
- vm.$el.querySelector('.js-note-edit').click();
+ wrapper.find('.js-note-edit').trigger('click');
const { markdownDocsPath } = mockData.notesDataMock;
Vue.nextTick(() => {
expect(
- vm.$el.querySelector(`.edit-note a[href="${markdownDocsPath}"]`).textContent.trim(),
+ wrapper
+ .find(`.edit-note a[href="${markdownDocsPath}"]`)
+ .text()
+ .trim(),
).toEqual('Markdown is supported');
done();
});
@@ -274,13 +291,11 @@ describe('note_app', () => {
it('should not render quick actions docs url', done => {
setTimeout(() => {
- vm.$el.querySelector('.js-note-edit').click();
+ wrapper.find('.js-note-edit').trigger('click');
const { quickActionsDocsPath } = mockData.notesDataMock;
Vue.nextTick(() => {
- expect(vm.$el.querySelector(`.edit-note a[href="${quickActionsDocsPath}"]`)).toEqual(
- null,
- );
+ expect(wrapper.find(`.edit-note a[href="${quickActionsDocsPath}"]`).exists()).toBe(false);
done();
});
}, 0);
@@ -295,12 +310,19 @@ describe('note_app', () => {
noteId: 1,
},
});
+ const toggleAwardAction = jasmine.createSpy('toggleAward');
+ wrapper.vm.$store.hotUpdate({
+ actions: {
+ toggleAward: toggleAwardAction,
+ },
+ });
- spyOn(vm.$store, 'dispatch');
+ wrapper.vm.$parent.$el.dispatchEvent(toggleAwardEvent);
- vm.$el.parentElement.dispatchEvent(toggleAwardEvent);
+ expect(toggleAwardAction).toHaveBeenCalledTimes(1);
+ const [, payload] = toggleAwardAction.calls.argsFor(0);
- expect(vm.$store.dispatch).toHaveBeenCalledWith('toggleAward', {
+ expect(payload).toEqual({
awardName: 'test',
noteId: 1,
});
diff --git a/spec/javascripts/notes/components/note_form_spec.js b/spec/javascripts/notes/components/note_form_spec.js
index 5db20fd285f..7cc324cfe44 100644
--- a/spec/javascripts/notes/components/note_form_spec.js
+++ b/spec/javascripts/notes/components/note_form_spec.js
@@ -1,17 +1,15 @@
-import Vue from 'vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import createStore from '~/notes/stores';
-import issueNoteForm from '~/notes/components/note_form.vue';
+import NoteForm from '~/notes/components/note_form.vue';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { noteableDataMock, notesDataMock } from '../mock_data';
-import { keyboardDownEvent } from '../../issue_show/helpers';
describe('issue_note_form component', () => {
let store;
- let vm;
+ let wrapper;
let props;
beforeEach(() => {
- const Component = Vue.extend(issueNoteForm);
-
store = createStore();
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
@@ -22,26 +20,35 @@ describe('issue_note_form component', () => {
noteId: '545',
};
- vm = new Component({
+ const localVue = createLocalVue();
+ wrapper = shallowMount(NoteForm, {
store,
propsData: props,
- }).$mount();
+ // see https://gitlab.com/gitlab-org/gitlab-ce/issues/56317 for the following
+ localVue,
+ sync: false,
+ });
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('noteHash', () => {
it('returns note hash string based on `noteId`', () => {
- expect(vm.noteHash).toBe(`#note_${props.noteId}`);
+ expect(wrapper.vm.noteHash).toBe(`#note_${props.noteId}`);
});
it('return note hash as `#` when `noteId` is empty', done => {
- vm.noteId = '';
- Vue.nextTick()
+ wrapper.setProps({
+ ...props,
+ noteId: '',
+ });
+
+ wrapper.vm
+ .$nextTick()
.then(() => {
- expect(vm.noteHash).toBe('#');
+ expect(wrapper.vm.noteHash).toBe('#');
})
.then(done)
.catch(done.fail);
@@ -50,95 +57,127 @@ describe('issue_note_form component', () => {
describe('conflicts editing', () => {
it('should show conflict message if note changes outside the component', done => {
- vm.isEditing = true;
- vm.noteBody = 'Foo';
+ wrapper.setProps({
+ ...props,
+ isEditing: true,
+ noteBody: 'Foo',
+ });
+
const message =
'This comment has changed since you started editing, please review the updated comment to ensure information is not lost.';
- Vue.nextTick(() => {
- expect(
- vm.$el
- .querySelector('.js-conflict-edit-warning')
- .textContent.replace(/\s+/g, ' ')
- .trim(),
- ).toEqual(message);
- done();
- });
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ const conflictWarning = wrapper.find('.js-conflict-edit-warning');
+
+ expect(conflictWarning.exists()).toBe(true);
+ expect(
+ conflictWarning
+ .text()
+ .replace(/\s+/g, ' ')
+ .trim(),
+ ).toBe(message);
+ })
+ .then(done)
+ .catch(done.fail);
});
});
describe('form', () => {
it('should render text area with placeholder', () => {
- expect(vm.$el.querySelector('textarea').getAttribute('placeholder')).toEqual(
+ const textarea = wrapper.find('textarea');
+
+ expect(textarea.attributes('placeholder')).toEqual(
'Write a comment or drag your files here…',
);
});
it('should link to markdown docs', () => {
const { markdownDocsPath } = notesDataMock;
+ const markdownField = wrapper.find(MarkdownField);
+ const markdownFieldProps = markdownField.props();
- expect(vm.$el.querySelector(`a[href="${markdownDocsPath}"]`).textContent.trim()).toEqual(
- 'Markdown',
- );
+ expect(markdownFieldProps.markdownDocsPath).toBe(markdownDocsPath);
});
describe('keyboard events', () => {
+ let textarea;
+
+ beforeEach(() => {
+ textarea = wrapper.find('textarea');
+ textarea.setValue('Foo');
+ });
+
describe('up', () => {
it('should ender edit mode', () => {
- spyOn(vm, 'editMyLastNote').and.callThrough();
- vm.$el.querySelector('textarea').value = 'Foo';
- vm.$el.querySelector('textarea').dispatchEvent(keyboardDownEvent(38, true));
+ // TODO: do not spy on vm
+ spyOn(wrapper.vm, 'editMyLastNote').and.callThrough();
+
+ textarea.trigger('keydown.up');
- expect(vm.editMyLastNote).toHaveBeenCalled();
+ expect(wrapper.vm.editMyLastNote).toHaveBeenCalled();
});
});
describe('enter', () => {
it('should save note when cmd+enter is pressed', () => {
- spyOn(vm, 'handleUpdate').and.callThrough();
- vm.$el.querySelector('textarea').value = 'Foo';
- vm.$el.querySelector('textarea').dispatchEvent(keyboardDownEvent(13, true));
+ textarea.trigger('keydown.enter', { metaKey: true });
+
+ const { handleFormUpdate } = wrapper.emitted();
- expect(vm.handleUpdate).toHaveBeenCalled();
+ expect(handleFormUpdate.length).toBe(1);
});
it('should save note when ctrl+enter is pressed', () => {
- spyOn(vm, 'handleUpdate').and.callThrough();
- vm.$el.querySelector('textarea').value = 'Foo';
- vm.$el.querySelector('textarea').dispatchEvent(keyboardDownEvent(13, false, true));
+ textarea.trigger('keydown.enter', { ctrlKey: true });
- expect(vm.handleUpdate).toHaveBeenCalled();
+ const { handleFormUpdate } = wrapper.emitted();
+
+ expect(handleFormUpdate.length).toBe(1);
});
});
});
describe('actions', () => {
it('should be possible to cancel', done => {
- spyOn(vm, 'cancelHandler').and.callThrough();
- vm.isEditing = true;
+ // TODO: do not spy on vm
+ spyOn(wrapper.vm, 'cancelHandler').and.callThrough();
+ wrapper.setProps({
+ ...props,
+ isEditing: true,
+ });
- Vue.nextTick(() => {
- vm.$el.querySelector('.note-edit-cancel').click();
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ const cancelButton = wrapper.find('.note-edit-cancel');
+ cancelButton.trigger('click');
- Vue.nextTick(() => {
- expect(vm.cancelHandler).toHaveBeenCalled();
- done();
- });
- });
+ expect(wrapper.vm.cancelHandler).toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
});
it('should be possible to update the note', done => {
- vm.isEditing = true;
-
- Vue.nextTick(() => {
- vm.$el.querySelector('textarea').value = 'Foo';
- vm.$el.querySelector('.js-vue-issue-save').click();
-
- Vue.nextTick(() => {
- expect(vm.isSubmitting).toEqual(true);
- done();
- });
+ wrapper.setProps({
+ ...props,
+ isEditing: true,
});
+
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ const textarea = wrapper.find('textarea');
+ textarea.setValue('Foo');
+ const saveButton = wrapper.find('.js-vue-issue-save');
+ saveButton.trigger('click');
+
+ expect(wrapper.vm.isSubmitting).toEqual(true);
+ })
+ .then(done)
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js
index 3aff2dd0641..2b93fb9fb45 100644
--- a/spec/javascripts/notes/components/noteable_discussion_spec.js
+++ b/spec/javascripts/notes/components/noteable_discussion_spec.js
@@ -1,6 +1,8 @@
-import Vue from 'vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import createStore from '~/notes/stores';
import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
+import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
+import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
import '~/behaviors/markdown/render_gfm';
import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data';
import mockDiffFile from '../../diffs/mock_data/diff_file';
@@ -8,9 +10,8 @@ import mockDiffFile from '../../diffs/mock_data/diff_file';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
describe('noteable_discussion component', () => {
- const Component = Vue.extend(noteableDiscussion);
let store;
- let vm;
+ let wrapper;
preloadFixtures(discussionWithTwoUnresolvedNotes);
@@ -20,63 +21,67 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
- vm = new Component({
+ const localVue = createLocalVue();
+ wrapper = shallowMount(noteableDiscussion, {
store,
propsData: { discussion: discussionMock },
- }).$mount();
+ localVue,
+ sync: false,
+ });
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('should render user avatar', () => {
- expect(vm.$el.querySelector('.user-avatar-link')).not.toBeNull();
+ expect(wrapper.find('.user-avatar-link').exists()).toBe(true);
});
it('should not render discussion header for non diff discussions', () => {
- expect(vm.$el.querySelector('.discussion-header')).toBeNull();
+ expect(wrapper.find('.discussion-header').exists()).toBe(false);
});
- it('should render discussion header', () => {
+ it('should render discussion header', done => {
const discussion = { ...discussionMock };
discussion.diff_file = mockDiffFile;
discussion.diff_discussion = true;
- vm.$destroy();
- vm = new Component({
- store,
- propsData: { discussion },
- }).$mount();
+ wrapper.setProps({ discussion });
- expect(vm.$el.querySelector('.discussion-header')).not.toBeNull();
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ expect(wrapper.find('.discussion-header').exists()).toBe(true);
+ })
+ .then(done)
+ .catch(done.fail);
});
describe('actions', () => {
- it('should render reply button', () => {
- expect(vm.$el.querySelector('.js-vue-discussion-reply').textContent.trim()).toEqual(
- 'Reply...',
- );
- });
-
it('should toggle reply form', done => {
- vm.$el.querySelector('.js-vue-discussion-reply').click();
-
- Vue.nextTick(() => {
- expect(vm.isReplying).toEqual(true);
-
- // There is a watcher for `isReplying` which will init autosave in the next tick
- Vue.nextTick(() => {
- expect(vm.$refs.noteForm).not.toBeNull();
- done();
- });
- });
+ const replyPlaceholder = wrapper.find(ReplyPlaceholder);
+
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ expect(wrapper.vm.isReplying).toEqual(false);
+
+ replyPlaceholder.vm.$emit('onClick');
+ })
+ .then(() => wrapper.vm.$nextTick())
+ .then(() => {
+ expect(wrapper.vm.isReplying).toEqual(true);
+ expect(wrapper.vm.$refs.noteForm).not.toBeNull();
+ })
+ .then(done)
+ .catch(done.fail);
});
it('does not render jump to discussion button', () => {
expect(
- vm.$el.querySelector('*[data-original-title="Jump to next unresolved discussion"]'),
- ).toBeNull();
+ wrapper.find('*[data-original-title="Jump to next unresolved discussion"]').exists(),
+ ).toBe(false);
});
});
@@ -87,12 +92,13 @@ describe('noteable_discussion component', () => {
discussion2.resolved = false;
discussion2.active = true;
discussion2.id = 'next'; // prepare this for being identified as next one (to be jumped to)
- vm.$store.dispatch('setInitialNotes', [discussionMock, discussion2]);
+ store.dispatch('setInitialNotes', [discussionMock, discussion2]);
window.mrTabs.currentAction = 'show';
- Vue.nextTick()
+ wrapper.vm
+ .$nextTick()
.then(() => {
- spyOn(vm, 'expandDiscussion').and.stub();
+ spyOn(wrapper.vm, 'expandDiscussion').and.stub();
const nextDiscussionId = discussion2.id;
@@ -100,9 +106,11 @@ describe('noteable_discussion component', () => {
<div class="discussion" data-discussion-id="${nextDiscussionId}"></div>
`);
- vm.jumpToNextDiscussion();
+ wrapper.vm.jumpToNextDiscussion();
- expect(vm.expandDiscussion).toHaveBeenCalledWith({ discussionId: nextDiscussionId });
+ expect(wrapper.vm.expandDiscussion).toHaveBeenCalledWith({
+ discussionId: nextDiscussionId,
+ });
})
.then(done)
.catch(done.fail);
@@ -117,7 +125,7 @@ describe('noteable_discussion component', () => {
notes: [{ body: 'hello world!' }],
};
- const note = vm.componentData(data);
+ const note = wrapper.vm.componentData(data);
expect(note).toEqual(data.notes[0]);
});
@@ -127,7 +135,7 @@ describe('noteable_discussion component', () => {
notes: [{ id: 12 }],
};
- const note = vm.componentData(data);
+ const note = wrapper.vm.componentData(data);
expect(note).toEqual(data);
});
@@ -138,46 +146,48 @@ describe('noteable_discussion component', () => {
const truncatedCommitId = commitId.substr(0, 8);
let commitElement;
- beforeEach(() => {
- vm.$destroy();
-
+ beforeEach(done => {
store.state.diffs = {
projectPath: 'something',
};
- vm = new Component({
- propsData: {
- discussion: {
- ...discussionMock,
- for_commit: true,
- commit_id: commitId,
- diff_discussion: true,
- diff_file: {
- ...mockDiffFile,
- },
+ wrapper.setProps({
+ discussion: {
+ ...discussionMock,
+ for_commit: true,
+ commit_id: commitId,
+ diff_discussion: true,
+ diff_file: {
+ ...mockDiffFile,
},
- renderDiffFile: true,
},
- store,
- }).$mount();
+ renderDiffFile: true,
+ });
- commitElement = vm.$el.querySelector('.commit-sha');
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ commitElement = wrapper.find('.commit-sha');
+ })
+ .then(done)
+ .catch(done.fail);
});
describe('for commit discussions', () => {
it('should display a monospace started a discussion on commit', () => {
- expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`);
- expect(commitElement).not.toBe(null);
- expect(commitElement).toHaveText(truncatedCommitId);
+ expect(wrapper.text()).toContain(`started a discussion on commit ${truncatedCommitId}`);
+ expect(commitElement.exists()).toBe(true);
+ expect(commitElement.text()).toContain(truncatedCommitId);
});
});
describe('for diff discussion with a commit id', () => {
it('should display started discussion on commit header', done => {
- vm.discussion.for_commit = false;
+ wrapper.vm.discussion.for_commit = false;
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.text()).toContain(`started a discussion on commit ${truncatedCommitId}`);
- vm.$nextTick(() => {
- expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`);
expect(commitElement).not.toBe(null);
done();
@@ -185,11 +195,11 @@ describe('noteable_discussion component', () => {
});
it('should display outdated change on commit header', done => {
- vm.discussion.for_commit = false;
- vm.discussion.active = false;
+ wrapper.vm.discussion.for_commit = false;
+ wrapper.vm.discussion.active = false;
- vm.$nextTick(() => {
- expect(vm.$el).toContainText(
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.text()).toContain(
`started a discussion on an outdated change in commit ${truncatedCommitId}`,
);
@@ -202,31 +212,69 @@ describe('noteable_discussion component', () => {
describe('for diff discussions without a commit id', () => {
it('should show started a discussion on the diff text', done => {
- Object.assign(vm.discussion, {
+ Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
});
- vm.$nextTick(() => {
- expect(vm.$el).toContainText('started a discussion on the diff');
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.text()).toContain('started a discussion on the diff');
done();
});
});
it('should show discussion on older version text', done => {
- Object.assign(vm.discussion, {
+ Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
active: false,
});
- vm.$nextTick(() => {
- expect(vm.$el).toContainText('started a discussion on an old version of the diff');
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.text()).toContain('started a discussion on an old version of the diff');
done();
});
});
});
});
+
+ describe('for resolved discussion', () => {
+ beforeEach(() => {
+ const discussion = getJSONFixture(discussionWithTwoUnresolvedNotes)[0];
+ wrapper.setProps({ discussion });
+ });
+
+ it('does not display a button to resolve with issue', () => {
+ const button = wrapper.find(ResolveWithIssueButton);
+
+ expect(button.exists()).toBe(false);
+ });
+ });
+
+ describe('for unresolved discussion', () => {
+ beforeEach(done => {
+ const discussion = {
+ ...getJSONFixture(discussionWithTwoUnresolvedNotes)[0],
+ expanded: true,
+ };
+ discussion.notes = discussion.notes.map(note => ({
+ ...note,
+ resolved: false,
+ }));
+
+ wrapper.setProps({ discussion });
+ wrapper.vm
+ .$nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('displays a button to resolve with issue', () => {
+ const button = wrapper.find(ResolveWithIssueButton);
+
+ expect(button.exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/javascripts/notes/components/noteable_note_spec.js b/spec/javascripts/notes/components/noteable_note_spec.js
index 8ade6fc2ced..9420713ceca 100644
--- a/spec/javascripts/notes/components/noteable_note_spec.js
+++ b/spec/javascripts/notes/components/noteable_note_spec.js
@@ -1,86 +1,138 @@
-import $ from 'jquery';
import _ from 'underscore';
-import Vue from 'vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import createStore from '~/notes/stores';
import issueNote from '~/notes/components/noteable_note.vue';
+import NoteHeader from '~/notes/components/note_header.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import NoteActions from '~/notes/components/note_actions.vue';
+import NoteBody from '~/notes/components/note_body.vue';
import { noteableDataMock, notesDataMock, note } from '../mock_data';
describe('issue_note', () => {
let store;
- let vm;
+ let wrapper;
beforeEach(() => {
- const Component = Vue.extend(issueNote);
-
store = createStore();
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
- vm = new Component({
+ const localVue = createLocalVue();
+ wrapper = shallowMount(issueNote, {
store,
propsData: {
note,
},
- }).$mount();
+ sync: false,
+ localVue,
+ });
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('should render user information', () => {
- expect(vm.$el.querySelector('.user-avatar-link img').getAttribute('src')).toEqual(
- note.author.avatar_url,
- );
+ const { author } = note;
+ const avatar = wrapper.find(UserAvatarLink);
+ const avatarProps = avatar.props();
+
+ expect(avatarProps.linkHref).toBe(author.path);
+ expect(avatarProps.imgSrc).toBe(author.avatar_url);
+ expect(avatarProps.imgAlt).toBe(author.name);
+ expect(avatarProps.imgSize).toBe(40);
});
it('should render note header content', () => {
- const el = vm.$el.querySelector('.note-header .note-header-author-name');
+ const noteHeader = wrapper.find(NoteHeader);
+ const noteHeaderProps = noteHeader.props();
- expect(el.textContent.trim()).toEqual(note.author.name);
+ expect(noteHeaderProps.author).toEqual(note.author);
+ expect(noteHeaderProps.createdAt).toEqual(note.created_at);
+ expect(noteHeaderProps.noteId).toEqual(note.id);
});
it('should render note actions', () => {
- expect(vm.$el.querySelector('.note-actions')).toBeDefined();
+ const { author } = note;
+ const noteActions = wrapper.find(NoteActions);
+ const noteActionsProps = noteActions.props();
+
+ expect(noteActionsProps.authorId).toBe(author.id);
+ expect(noteActionsProps.noteId).toBe(note.id);
+ expect(noteActionsProps.noteUrl).toBe(note.noteable_note_url);
+ expect(noteActionsProps.accessLevel).toBe(note.human_access);
+ expect(noteActionsProps.canEdit).toBe(note.current_user.can_edit);
+ expect(noteActionsProps.canAwardEmoji).toBe(note.current_user.can_award_emoji);
+ expect(noteActionsProps.canDelete).toBe(note.current_user.can_edit);
+ expect(noteActionsProps.canReportAsAbuse).toBe(true);
+ expect(noteActionsProps.canResolve).toBe(false);
+ expect(noteActionsProps.reportAbusePath).toBe(note.report_abuse_path);
+ expect(noteActionsProps.resolvable).toBe(false);
+ expect(noteActionsProps.isResolved).toBe(false);
+ expect(noteActionsProps.isResolving).toBe(false);
+ expect(noteActionsProps.resolvedBy).toEqual({});
});
it('should render issue body', () => {
- expect(vm.$el.querySelector('.note-text').innerHTML).toEqual(note.note_html);
+ const noteBody = wrapper.find(NoteBody);
+ const noteBodyProps = noteBody.props();
+
+ expect(noteBodyProps.note).toEqual(note);
+ expect(noteBodyProps.line).toBe(null);
+ expect(noteBodyProps.canEdit).toBe(note.current_user.can_edit);
+ expect(noteBodyProps.isEditing).toBe(false);
+ expect(noteBodyProps.helpPagePath).toBe('');
});
it('prevents note preview xss', done => {
const imgSrc = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
const noteBody = `<img src="${imgSrc}" onload="alert(1)" />`;
const alertSpy = spyOn(window, 'alert');
- vm.updateNote = () => new Promise($.noop);
+ store.hotUpdate({
+ actions: {
+ updateNote() {},
+ },
+ });
+ const noteBodyComponent = wrapper.find(NoteBody);
- vm.formUpdateHandler(noteBody, null, $.noop);
+ noteBodyComponent.vm.$emit('handleFormUpdate', noteBody, null, () => {});
setTimeout(() => {
expect(alertSpy).not.toHaveBeenCalled();
- expect(vm.note.note_html).toEqual(_.escape(noteBody));
+ expect(wrapper.vm.note.note_html).toEqual(_.escape(noteBody));
done();
}, 0);
});
describe('cancel edit', () => {
it('restores content of updated note', done => {
- const noteBody = 'updated note text';
- vm.updateNote = () => Promise.resolve();
-
- vm.formUpdateHandler(noteBody, null, $.noop);
-
- setTimeout(() => {
- expect(vm.note.note_html).toEqual(noteBody);
-
- vm.formCancelHandler();
-
- setTimeout(() => {
- expect(vm.note.note_html).toEqual(noteBody);
-
- done();
- });
+ const updatedText = 'updated note text';
+ store.hotUpdate({
+ actions: {
+ updateNote() {},
+ },
});
+ const noteBody = wrapper.find(NoteBody);
+ noteBody.vm.resetAutoSave = () => {};
+
+ noteBody.vm.$emit('handleFormUpdate', updatedText, null, () => {});
+
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ const noteBodyProps = noteBody.props();
+
+ expect(noteBodyProps.note.note_html).toBe(updatedText);
+ noteBody.vm.$emit('cancelForm');
+ })
+ .then(() => wrapper.vm.$nextTick())
+ .then(() => {
+ const noteBodyProps = noteBody.props();
+
+ expect(noteBodyProps.note.note_html).toBe(note.note_html);
+ })
+ .then(done)
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/notes/mock_data.js b/spec/javascripts/notes/mock_data.js
index 7ae45c40c28..348743081eb 100644
--- a/spec/javascripts/notes/mock_data.js
+++ b/spec/javascripts/notes/mock_data.js
@@ -165,7 +165,6 @@ export const note = {
report_abuse_path:
'/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F7%23note_546&user_id=1',
path: '/gitlab-org/gitlab-ce/notes/546',
- cached_markdown_version: 11,
};
export const discussionMock = {
diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js
index 2e3cd5e8f36..94ce6d8e222 100644
--- a/spec/javascripts/notes/stores/actions_spec.js
+++ b/spec/javascripts/notes/stores/actions_spec.js
@@ -1,8 +1,11 @@
import Vue from 'vue';
import $ from 'jquery';
import _ from 'underscore';
+import { TEST_HOST } from 'spec/test_constants';
import { headersInterceptor } from 'spec/helpers/vue_resource_helper';
import * as actions from '~/notes/stores/actions';
+import * as mutationTypes from '~/notes/stores/mutation_types';
+import * as notesConstants from '~/notes/constants';
import createStore from '~/notes/stores';
import mrWidgetEventHub from '~/vue_merge_request_widget/event_hub';
import testAction from '../../helpers/vuex_action_helper';
@@ -585,4 +588,167 @@ describe('Actions Notes Store', () => {
);
});
});
+
+ describe('convertToDiscussion', () => {
+ it('commits CONVERT_TO_DISCUSSION with noteId', done => {
+ const noteId = 'dummy-note-id';
+ testAction(
+ actions.convertToDiscussion,
+ noteId,
+ {},
+ [{ type: 'CONVERT_TO_DISCUSSION', payload: noteId }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('updateOrCreateNotes', () => {
+ let commit;
+ let dispatch;
+ let state;
+
+ beforeEach(() => {
+ commit = jasmine.createSpy('commit');
+ dispatch = jasmine.createSpy('dispatch');
+ state = {};
+ });
+
+ afterEach(() => {
+ commit.calls.reset();
+ dispatch.calls.reset();
+ });
+
+ it('Updates existing note', () => {
+ const note = { id: 1234 };
+ const getters = { notesById: { 1234: note } };
+
+ actions.updateOrCreateNotes({ commit, state, getters, dispatch }, [note]);
+
+ expect(commit.calls.allArgs()).toEqual([[mutationTypes.UPDATE_NOTE, note]]);
+ });
+
+ it('Creates a new note if none exisits', () => {
+ const note = { id: 1234 };
+ const getters = { notesById: {} };
+ actions.updateOrCreateNotes({ commit, state, getters, dispatch }, [note]);
+
+ expect(commit.calls.allArgs()).toEqual([[mutationTypes.ADD_NEW_NOTE, note]]);
+ });
+
+ describe('Discussion notes', () => {
+ let note;
+ let getters;
+
+ beforeEach(() => {
+ note = { id: 1234 };
+ getters = { notesById: {} };
+ });
+
+ it('Adds a reply to an existing discussion', () => {
+ state = { discussions: [note] };
+ const discussionNote = {
+ ...note,
+ type: notesConstants.DISCUSSION_NOTE,
+ discussion_id: 1234,
+ };
+
+ actions.updateOrCreateNotes({ commit, state, getters, dispatch }, [discussionNote]);
+
+ expect(commit.calls.allArgs()).toEqual([
+ [mutationTypes.ADD_NEW_REPLY_TO_DISCUSSION, discussionNote],
+ ]);
+ });
+
+ it('fetches discussions for diff notes', () => {
+ state = { discussions: [], notesData: { discussionsPath: 'Hello world' } };
+ const diffNote = { ...note, type: notesConstants.DIFF_NOTE, discussion_id: 1234 };
+
+ actions.updateOrCreateNotes({ commit, state, getters, dispatch }, [diffNote]);
+
+ expect(dispatch.calls.allArgs()).toEqual([
+ ['fetchDiscussions', { path: state.notesData.discussionsPath }],
+ ]);
+ });
+
+ it('Adds a new note', () => {
+ state = { discussions: [] };
+ const discussionNote = {
+ ...note,
+ type: notesConstants.DISCUSSION_NOTE,
+ discussion_id: 1234,
+ };
+
+ actions.updateOrCreateNotes({ commit, state, getters, dispatch }, [discussionNote]);
+
+ expect(commit.calls.allArgs()).toEqual([[mutationTypes.ADD_NEW_NOTE, discussionNote]]);
+ });
+ });
+ });
+
+ describe('replyToDiscussion', () => {
+ let res = { discussion: { notes: [] } };
+ const payload = { endpoint: TEST_HOST, data: {} };
+ const interceptor = (request, next) => {
+ next(
+ request.respondWith(JSON.stringify(res), {
+ status: 200,
+ }),
+ );
+ };
+
+ beforeEach(() => {
+ Vue.http.interceptors.push(interceptor);
+ });
+
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
+ });
+
+ it('updates discussion if response contains disussion', done => {
+ testAction(
+ actions.replyToDiscussion,
+ payload,
+ {
+ notesById: {},
+ },
+ [{ type: mutationTypes.UPDATE_DISCUSSION, payload: res.discussion }],
+ [
+ { type: 'updateMergeRequestWidget' },
+ { type: 'startTaskList' },
+ { type: 'updateResolvableDiscussonsCounts' },
+ ],
+ done,
+ );
+ });
+
+ it('adds a reply to a discussion', done => {
+ res = {};
+
+ testAction(
+ actions.replyToDiscussion,
+ payload,
+ {
+ notesById: {},
+ },
+ [{ type: mutationTypes.ADD_NEW_REPLY_TO_DISCUSSION, payload: res }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('removeConvertedDiscussion', () => {
+ it('commits CONVERT_TO_DISCUSSION with noteId', done => {
+ const noteId = 'dummy-id';
+ testAction(
+ actions.removeConvertedDiscussion,
+ noteId,
+ {},
+ [{ type: 'REMOVE_CONVERTED_DISCUSSION', payload: noteId }],
+ [],
+ done,
+ );
+ });
+ });
});
diff --git a/spec/javascripts/notes/stores/getters_spec.js b/spec/javascripts/notes/stores/getters_spec.js
index c066975a43b..8f3c493dd4c 100644
--- a/spec/javascripts/notes/stores/getters_spec.js
+++ b/spec/javascripts/notes/stores/getters_spec.js
@@ -261,4 +261,12 @@ describe('Getters Notes Store', () => {
expect(getters.firstUnresolvedDiscussionId(state, localGettersFalsy)(false)).toBeFalsy();
});
});
+
+ describe('getDiscussion', () => {
+ it('returns discussion by ID', () => {
+ state.discussions.push({ id: '1' });
+
+ expect(getters.getDiscussion(state)('1')).toEqual({ id: '1' });
+ });
+ });
});
diff --git a/spec/javascripts/notes/stores/mutation_spec.js b/spec/javascripts/notes/stores/mutation_spec.js
index 3fbae82f16c..4a640d589fb 100644
--- a/spec/javascripts/notes/stores/mutation_spec.js
+++ b/spec/javascripts/notes/stores/mutation_spec.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import mutations from '~/notes/stores/mutations';
+import { DISCUSSION_NOTE } from '~/notes/constants';
import {
note,
discussionMock,
@@ -179,11 +180,11 @@ describe('Notes Store mutations', () => {
diff_file: {
file_hash: 'a',
},
- truncated_diff_lines: ['a'],
+ truncated_diff_lines: [{ text: '+a', rich_text: '+<span>a</span>' }],
},
]);
- expect(state.discussions[0].truncated_diff_lines).toEqual(['a']);
+ expect(state.discussions[0].truncated_diff_lines).toEqual([{ rich_text: '<span>a</span>' }]);
});
it('adds empty truncated_diff_lines when not in discussion', () => {
@@ -326,6 +327,18 @@ describe('Notes Store mutations', () => {
expect(state.discussions[0].notes[0].note).toEqual('Foo');
});
+
+ it('transforms an individual note to discussion', () => {
+ const state = {
+ discussions: [individualNote],
+ };
+
+ const transformedNote = { ...individualNote.notes[0], type: DISCUSSION_NOTE };
+
+ mutations.UPDATE_NOTE(state, transformedNote);
+
+ expect(state.discussions[0].individual_note).toEqual(false);
+ });
});
describe('CLOSE_ISSUE', () => {
@@ -420,9 +433,12 @@ describe('Notes Store mutations', () => {
],
};
- mutations.SET_DISCUSSION_DIFF_LINES(state, { discussionId: 1, diffLines: ['test'] });
+ mutations.SET_DISCUSSION_DIFF_LINES(state, {
+ discussionId: 1,
+ diffLines: [{ text: '+a', rich_text: '+<span>a</span>' }],
+ });
- expect(state.discussions[0].truncated_diff_lines).toEqual(['test']);
+ expect(state.discussions[0].truncated_diff_lines).toEqual([{ rich_text: '<span>a</span>' }]);
});
it('keeps reactivity of discussion', () => {
@@ -435,7 +451,10 @@ describe('Notes Store mutations', () => {
]);
const discussion = state.discussions[0];
- mutations.SET_DISCUSSION_DIFF_LINES(state, { discussionId: 1, diffLines: ['test'] });
+ mutations.SET_DISCUSSION_DIFF_LINES(state, {
+ discussionId: 1,
+ diffLines: [{ rich_text: '<span>a</span>' }],
+ });
discussion.expanded = true;
@@ -511,4 +530,42 @@ describe('Notes Store mutations', () => {
);
});
});
+
+ describe('CONVERT_TO_DISCUSSION', () => {
+ let discussion;
+ let state;
+
+ beforeEach(() => {
+ discussion = {
+ id: 42,
+ individual_note: true,
+ };
+ state = { convertedDisscussionIds: [] };
+ });
+
+ it('adds a discussion to convertedDisscussionIds', () => {
+ mutations.CONVERT_TO_DISCUSSION(state, discussion.id);
+
+ expect(state.convertedDisscussionIds).toContain(discussion.id);
+ });
+ });
+
+ describe('REMOVE_CONVERTED_DISCUSSION', () => {
+ let discussion;
+ let state;
+
+ beforeEach(() => {
+ discussion = {
+ id: 42,
+ individual_note: true,
+ };
+ state = { convertedDisscussionIds: [41, 42] };
+ });
+
+ it('removes a discussion from convertedDisscussionIds', () => {
+ mutations.REMOVE_CONVERTED_DISCUSSION(state, discussion.id);
+
+ expect(state.convertedDisscussionIds).not.toContain(discussion.id);
+ });
+ });
});
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index 694f581150f..7c869d4c326 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -89,10 +89,25 @@ describe('Notes', function() {
});
it('submits an ajax request on tasklist:changed', function(done) {
- $('.js-task-list-container').trigger('tasklist:changed');
+ const lineNumber = 8;
+ const lineSource = '- [ ] item 8';
+ const index = 3;
+ const checked = true;
+
+ $('.js-task-list-container').trigger({
+ type: 'tasklist:changed',
+ detail: { lineNumber, lineSource, index, checked },
+ });
setTimeout(() => {
- expect(axios.patch).toHaveBeenCalled();
+ expect(axios.patch).toHaveBeenCalledWith(undefined, {
+ note: {
+ note: '',
+ lock_version: undefined,
+ update_task: { index, checked, line_number: lineNumber, line_source: lineSource },
+ },
+ });
+
done();
});
});
diff --git a/spec/javascripts/oauth_remember_me_spec.js b/spec/javascripts/oauth_remember_me_spec.js
index 2caa266b85f..4125706a407 100644
--- a/spec/javascripts/oauth_remember_me_spec.js
+++ b/spec/javascripts/oauth_remember_me_spec.js
@@ -20,6 +20,10 @@ describe('OAuthRememberMe', () => {
expect($('#oauth-container .oauth-login.github').attr('href')).toBe(
'http://example.com/?remember_me=1',
);
+
+ expect($('#oauth-container .oauth-login.facebook').attr('href')).toBe(
+ 'http://example.com/?redirect_fragment=L1&remember_me=1',
+ );
});
it('removes the "remember_me" query parameter from all OAuth login buttons', () => {
@@ -28,5 +32,8 @@ describe('OAuthRememberMe', () => {
expect($('#oauth-container .oauth-login.twitter').attr('href')).toBe('http://example.com/');
expect($('#oauth-container .oauth-login.github').attr('href')).toBe('http://example.com/');
+ expect($('#oauth-container .oauth-login.facebook').attr('href')).toBe(
+ 'http://example.com/?redirect_fragment=L1',
+ );
});
});
diff --git a/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js b/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js
new file mode 100644
index 00000000000..7a8227479d4
--- /dev/null
+++ b/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js
@@ -0,0 +1,61 @@
+import $ from 'jquery';
+import preserveUrlFragment from '~/pages/sessions/new/preserve_url_fragment';
+
+describe('preserve_url_fragment', () => {
+ preloadFixtures('sessions/new.html.raw');
+
+ beforeEach(() => {
+ loadFixtures('sessions/new.html.raw');
+ });
+
+ it('adds the url fragment to all login and sign up form actions', () => {
+ preserveUrlFragment('#L65');
+
+ expect($('#new_user').attr('action')).toBe('http://test.host/users/sign_in#L65');
+ expect($('#new_new_user').attr('action')).toBe('http://test.host/users#L65');
+ });
+
+ it('does not add an empty url fragment to login and sign up form actions', () => {
+ preserveUrlFragment();
+
+ expect($('#new_user').attr('action')).toBe('http://test.host/users/sign_in');
+ expect($('#new_new_user').attr('action')).toBe('http://test.host/users');
+ });
+
+ it('does not add an empty query parameter to OmniAuth login buttons', () => {
+ preserveUrlFragment();
+
+ expect($('#oauth-login-cas3').attr('href')).toBe('http://test.host/users/auth/cas3');
+
+ expect($('.omniauth-container #oauth-login-auth0').attr('href')).toBe(
+ 'http://test.host/users/auth/auth0',
+ );
+ });
+
+ describe('adds "redirect_fragment" query parameter to OmniAuth login buttons', () => {
+ it('when "remember_me" is not present', () => {
+ preserveUrlFragment('#L65');
+
+ expect($('#oauth-login-cas3').attr('href')).toBe(
+ 'http://test.host/users/auth/cas3?redirect_fragment=L65',
+ );
+
+ expect($('.omniauth-container #oauth-login-auth0').attr('href')).toBe(
+ 'http://test.host/users/auth/auth0?redirect_fragment=L65',
+ );
+ });
+
+ it('when "remember-me" is present', () => {
+ $('a.omniauth-btn').attr('href', (i, href) => `${href}?remember_me=1`);
+ preserveUrlFragment('#L65');
+
+ expect($('#oauth-login-cas3').attr('href')).toBe(
+ 'http://test.host/users/auth/cas3?remember_me=1&redirect_fragment=L65',
+ );
+
+ expect($('#oauth-login-auth0').attr('href')).toBe(
+ 'http://test.host/users/auth/auth0?remember_me=1&redirect_fragment=L65',
+ );
+ });
+ });
+});
diff --git a/spec/javascripts/persistent_user_callout_spec.js b/spec/javascripts/persistent_user_callout_spec.js
new file mode 100644
index 00000000000..2fdfff3db03
--- /dev/null
+++ b/spec/javascripts/persistent_user_callout_spec.js
@@ -0,0 +1,88 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import PersistentUserCallout from '~/persistent_user_callout';
+import setTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
+
+describe('PersistentUserCallout', () => {
+ const dismissEndpoint = '/dismiss';
+ const featureName = 'feature';
+
+ function createFixture() {
+ const fixture = document.createElement('div');
+ fixture.innerHTML = `
+ <div
+ class="container"
+ data-dismiss-endpoint="${dismissEndpoint}"
+ data-feature-id="${featureName}"
+ >
+ <button type="button" class="js-close"></button>
+ </div>
+ `;
+
+ return fixture;
+ }
+
+ describe('dismiss', () => {
+ let button;
+ let mockAxios;
+ let persistentUserCallout;
+
+ beforeEach(() => {
+ const fixture = createFixture();
+ const container = fixture.querySelector('.container');
+ button = fixture.querySelector('.js-close');
+ mockAxios = new MockAdapter(axios);
+ persistentUserCallout = new PersistentUserCallout(container);
+ spyOn(persistentUserCallout.container, 'remove');
+ });
+
+ afterEach(() => {
+ mockAxios.restore();
+ });
+
+ it('POSTs endpoint and removes container when clicking close', done => {
+ mockAxios.onPost(dismissEndpoint).replyOnce(200);
+
+ button.click();
+
+ setTimeoutPromise()
+ .then(() => {
+ expect(persistentUserCallout.container.remove).toHaveBeenCalled();
+ expect(mockAxios.history.post[0].data).toBe(
+ JSON.stringify({ feature_name: featureName }),
+ );
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('invokes Flash when the dismiss request fails', done => {
+ const Flash = spyOnDependency(PersistentUserCallout, 'Flash');
+ mockAxios.onPost(dismissEndpoint).replyOnce(500);
+
+ button.click();
+
+ setTimeoutPromise()
+ .then(() => {
+ expect(persistentUserCallout.container.remove).not.toHaveBeenCalled();
+ expect(Flash).toHaveBeenCalledWith(
+ 'An error occurred while dismissing the alert. Refresh the page and try again.',
+ );
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('factory', () => {
+ it('returns an instance of PersistentUserCallout with the provided container property', () => {
+ const fixture = createFixture();
+
+ expect(PersistentUserCallout.factory(fixture) instanceof PersistentUserCallout).toBe(true);
+ });
+
+ it('returns undefined if container is falsey', () => {
+ expect(PersistentUserCallout.factory()).toBe(undefined);
+ });
+ });
+});
diff --git a/spec/javascripts/pipelines/pipelines_spec.js b/spec/javascripts/pipelines/pipelines_spec.js
index 97ded16db69..78187b69563 100644
--- a/spec/javascripts/pipelines/pipelines_spec.js
+++ b/spec/javascripts/pipelines/pipelines_spec.js
@@ -446,7 +446,7 @@ describe('Pipelines', () => {
};
vm.$nextTick(() => {
- vm.$el.querySelector('.js-next-button a').click();
+ vm.$el.querySelector('.js-next-button .page-link').click();
expect(vm.updateContent).toHaveBeenCalledWith({ scope: 'all', page: '2' });
diff --git a/spec/javascripts/releases/components/release_block_spec.js b/spec/javascripts/releases/components/release_block_spec.js
index 29420216bc4..36b181f24ef 100644
--- a/spec/javascripts/releases/components/release_block_spec.js
+++ b/spec/javascripts/releases/components/release_block_spec.js
@@ -133,4 +133,20 @@ describe('Release block', () => {
release.assets.links[0].name,
);
});
+
+ it('renders author avatar', () => {
+ expect(vm.$el.querySelector('.user-avatar-link')).not.toBeNull();
+ });
+
+ describe('external label', () => {
+ it('renders external label when link is external', () => {
+ expect(vm.$el.querySelector('.js-assets-list li a').textContent).toContain('external source');
+ });
+
+ it('does not render external label when link is not external', () => {
+ expect(vm.$el.querySelector('.js-assets-list li:nth-child(2) a').textContent).not.toContain(
+ 'external source',
+ );
+ });
+ });
});
diff --git a/spec/javascripts/serverless/components/environment_row_spec.js b/spec/javascripts/serverless/components/environment_row_spec.js
new file mode 100644
index 00000000000..bdf7a714910
--- /dev/null
+++ b/spec/javascripts/serverless/components/environment_row_spec.js
@@ -0,0 +1,81 @@
+import Vue from 'vue';
+
+import environmentRowComponent from '~/serverless/components/environment_row.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import ServerlessStore from '~/serverless/stores/serverless_store';
+
+import { mockServerlessFunctions, mockServerlessFunctionsDiffEnv } from '../mock_data';
+
+const createComponent = (env, envName) =>
+ mountComponent(Vue.extend(environmentRowComponent), { env, envName });
+
+describe('environment row component', () => {
+ describe('default global cluster case', () => {
+ let vm;
+
+ beforeEach(() => {
+ const store = new ServerlessStore(false, '/cluster_path', 'help_path');
+ store.updateFunctionsFromServer(mockServerlessFunctions);
+ vm = createComponent(store.state.functions['*'], '*');
+ });
+
+ it('has the correct envId', () => {
+ expect(vm.envId).toEqual('env-global');
+ vm.$destroy();
+ });
+
+ it('is open by default', () => {
+ expect(vm.isOpenClass).toEqual({ 'is-open': true });
+ vm.$destroy();
+ });
+
+ it('generates correct output', () => {
+ expect(vm.$el.querySelectorAll('li').length).toEqual(2);
+ expect(vm.$el.id).toEqual('env-global');
+ expect(vm.$el.classList.contains('is-open')).toBe(true);
+ expect(vm.$el.querySelector('div.title').innerHTML.trim()).toEqual('*');
+
+ vm.$destroy();
+ });
+
+ it('opens and closes correctly', () => {
+ expect(vm.isOpen).toBe(true);
+
+ vm.toggleOpen();
+ Vue.nextTick(() => {
+ expect(vm.isOpen).toBe(false);
+ });
+
+ vm.$destroy();
+ });
+ });
+
+ describe('default named cluster case', () => {
+ let vm;
+
+ beforeEach(() => {
+ const store = new ServerlessStore(false, '/cluster_path', 'help_path');
+ store.updateFunctionsFromServer(mockServerlessFunctionsDiffEnv);
+ vm = createComponent(store.state.functions.test, 'test');
+ });
+
+ it('has the correct envId', () => {
+ expect(vm.envId).toEqual('env-test');
+ vm.$destroy();
+ });
+
+ it('is open by default', () => {
+ expect(vm.isOpenClass).toEqual({ 'is-open': true });
+ vm.$destroy();
+ });
+
+ it('generates correct output', () => {
+ expect(vm.$el.querySelectorAll('li').length).toEqual(1);
+ expect(vm.$el.id).toEqual('env-test');
+ expect(vm.$el.classList.contains('is-open')).toBe(true);
+ expect(vm.$el.querySelector('div.title').innerHTML.trim()).toEqual('test');
+
+ vm.$destroy();
+ });
+ });
+});
diff --git a/spec/javascripts/serverless/components/function_row_spec.js b/spec/javascripts/serverless/components/function_row_spec.js
new file mode 100644
index 00000000000..6933a8f6c87
--- /dev/null
+++ b/spec/javascripts/serverless/components/function_row_spec.js
@@ -0,0 +1,33 @@
+import Vue from 'vue';
+
+import functionRowComponent from '~/serverless/components/function_row.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+
+import { mockServerlessFunction } from '../mock_data';
+
+const createComponent = func => mountComponent(Vue.extend(functionRowComponent), { func });
+
+describe('functionRowComponent', () => {
+ it('Parses the function details correctly', () => {
+ const vm = createComponent(mockServerlessFunction);
+
+ expect(vm.$el.querySelector('b').innerHTML).toEqual(mockServerlessFunction.name);
+ expect(vm.$el.querySelector('span').innerHTML).toEqual(mockServerlessFunction.image);
+ expect(vm.$el.querySelector('time').getAttribute('data-original-title')).not.toBe(null);
+ expect(vm.$el.querySelector('div.url-text-field').innerHTML).toEqual(
+ mockServerlessFunction.url,
+ );
+
+ vm.$destroy();
+ });
+
+ it('handles clicks correctly', () => {
+ const vm = createComponent(mockServerlessFunction);
+
+ expect(vm.checkClass(vm.$el.querySelector('p'))).toBe(true); // check somewhere inside the row
+ expect(vm.checkClass(vm.$el.querySelector('svg'))).toBe(false); // check a button image
+ expect(vm.checkClass(vm.$el.querySelector('div.url-text-field'))).toBe(false); // check the url bar
+
+ vm.$destroy();
+ });
+});
diff --git a/spec/javascripts/serverless/components/functions_spec.js b/spec/javascripts/serverless/components/functions_spec.js
new file mode 100644
index 00000000000..85cfe71281f
--- /dev/null
+++ b/spec/javascripts/serverless/components/functions_spec.js
@@ -0,0 +1,68 @@
+import Vue from 'vue';
+
+import functionsComponent from '~/serverless/components/functions.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import ServerlessStore from '~/serverless/stores/serverless_store';
+
+import { mockServerlessFunctions } from '../mock_data';
+
+const createComponent = (
+ functions,
+ installed = true,
+ loadingData = true,
+ hasFunctionData = true,
+) => {
+ const component = Vue.extend(functionsComponent);
+
+ return mountComponent(component, {
+ functions,
+ installed,
+ clustersPath: '/testClusterPath',
+ helpPath: '/helpPath',
+ loadingData,
+ hasFunctionData,
+ });
+};
+
+describe('functionsComponent', () => {
+ it('should render empty state when Knative is not installed', () => {
+ const vm = createComponent({}, false);
+
+ expect(vm.$el.querySelector('div.row').classList.contains('js-empty-state')).toBe(true);
+ expect(vm.$el.querySelector('h4.state-title').innerHTML.trim()).toEqual(
+ 'Getting started with serverless',
+ );
+
+ vm.$destroy();
+ });
+
+ it('should render a loading component', () => {
+ const vm = createComponent({});
+
+ expect(vm.$el.querySelector('.gl-responsive-table-row')).not.toBe(null);
+ expect(vm.$el.querySelector('div.animation-container')).not.toBe(null);
+ });
+
+ it('should render empty state when there is no function data', () => {
+ const vm = createComponent({}, true, false, false);
+
+ expect(
+ vm.$el.querySelector('.empty-state, .js-empty-state').classList.contains('js-empty-state'),
+ ).toBe(true);
+
+ expect(vm.$el.querySelector('h4.state-title').innerHTML.trim()).toEqual(
+ 'No functions available',
+ );
+
+ vm.$destroy();
+ });
+
+ it('should render the functions list', () => {
+ const store = new ServerlessStore(false, '/cluster_path', 'help_path');
+ store.updateFunctionsFromServer(mockServerlessFunctions);
+ const vm = createComponent(store.state.functions, true, false);
+
+ expect(vm.$el.querySelector('div.groups-list-tree-container')).not.toBe(null);
+ expect(vm.$el.querySelector('#env-global').classList.contains('has-children')).toBe(true);
+ });
+});
diff --git a/spec/javascripts/serverless/components/url_spec.js b/spec/javascripts/serverless/components/url_spec.js
new file mode 100644
index 00000000000..21a879a49bb
--- /dev/null
+++ b/spec/javascripts/serverless/components/url_spec.js
@@ -0,0 +1,28 @@
+import Vue from 'vue';
+
+import urlComponent from '~/serverless/components/url.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+
+const createComponent = uri => {
+ const component = Vue.extend(urlComponent);
+
+ return mountComponent(component, {
+ uri,
+ });
+};
+
+describe('urlComponent', () => {
+ it('should render correctly', () => {
+ const uri = 'http://testfunc.apps.example.com';
+ const vm = createComponent(uri);
+
+ expect(vm.$el.classList.contains('clipboard-group')).toBe(true);
+ expect(vm.$el.querySelector('.js-clipboard-btn').getAttribute('data-clipboard-text')).toEqual(
+ uri,
+ );
+
+ expect(vm.$el.querySelector('.url-text-field').innerHTML).toEqual(uri);
+
+ vm.$destroy();
+ });
+});
diff --git a/spec/javascripts/serverless/mock_data.js b/spec/javascripts/serverless/mock_data.js
new file mode 100644
index 00000000000..ecd393b174c
--- /dev/null
+++ b/spec/javascripts/serverless/mock_data.js
@@ -0,0 +1,79 @@
+export const mockServerlessFunctions = [
+ {
+ name: 'testfunc1',
+ namespace: 'tm-example',
+ environment_scope: '*',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc1',
+ podcount: null,
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc1.tm-example.apps.example.com',
+ description: 'A test service',
+ image: 'knative-test-container-buildtemplate',
+ },
+ {
+ name: 'testfunc2',
+ namespace: 'tm-example',
+ environment_scope: '*',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc2',
+ podcount: null,
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc2.tm-example.apps.example.com',
+ description: 'A second test service\nThis one with additional descriptions',
+ image: 'knative-test-echo-buildtemplate',
+ },
+];
+
+export const mockServerlessFunctionsDiffEnv = [
+ {
+ name: 'testfunc1',
+ namespace: 'tm-example',
+ environment_scope: '*',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc1',
+ podcount: null,
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc1.tm-example.apps.example.com',
+ description: 'A test service',
+ image: 'knative-test-container-buildtemplate',
+ },
+ {
+ name: 'testfunc2',
+ namespace: 'tm-example',
+ environment_scope: 'test',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc2',
+ podcount: null,
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc2.tm-example.apps.example.com',
+ description: 'A second test service\nThis one with additional descriptions',
+ image: 'knative-test-echo-buildtemplate',
+ },
+];
+
+export const mockServerlessFunction = {
+ name: 'testfunc1',
+ namespace: 'tm-example',
+ environment_scope: '*',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc1',
+ podcount: '3',
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc1.tm-example.apps.example.com',
+ description: 'A test service',
+ image: 'knative-test-container-buildtemplate',
+};
+
+export const mockMultilineServerlessFunction = {
+ name: 'testfunc1',
+ namespace: 'tm-example',
+ environment_scope: '*',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc1',
+ podcount: '3',
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc1.tm-example.apps.example.com',
+ description: 'testfunc1\nA test service line\\nWith additional services',
+ image: 'knative-test-container-buildtemplate',
+};
diff --git a/spec/javascripts/serverless/stores/serverless_store_spec.js b/spec/javascripts/serverless/stores/serverless_store_spec.js
new file mode 100644
index 00000000000..72fd903d7d1
--- /dev/null
+++ b/spec/javascripts/serverless/stores/serverless_store_spec.js
@@ -0,0 +1,36 @@
+import ServerlessStore from '~/serverless/stores/serverless_store';
+import { mockServerlessFunctions, mockServerlessFunctionsDiffEnv } from '../mock_data';
+
+describe('Serverless Functions Store', () => {
+ let store;
+
+ beforeEach(() => {
+ store = new ServerlessStore(false, '/cluster_path', 'help_path');
+ });
+
+ describe('#updateFunctionsFromServer', () => {
+ it('should pass an empty hash object', () => {
+ store.updateFunctionsFromServer();
+
+ expect(store.state.functions).toEqual({});
+ });
+
+ it('should group functions to one global environment', () => {
+ const mockServerlessData = mockServerlessFunctions;
+ store.updateFunctionsFromServer(mockServerlessData);
+
+ expect(Object.keys(store.state.functions)).toEqual(jasmine.objectContaining(['*']));
+ expect(store.state.functions['*'].length).toEqual(2);
+ });
+
+ it('should group functions to multiple environments', () => {
+ const mockServerlessData = mockServerlessFunctionsDiffEnv;
+ store.updateFunctionsFromServer(mockServerlessData);
+
+ expect(Object.keys(store.state.functions)).toEqual(jasmine.objectContaining(['*']));
+ expect(store.state.functions['*'].length).toEqual(1);
+ expect(store.state.functions.test.length).toEqual(1);
+ expect(store.state.functions.test[0].name).toEqual('testfunc2');
+ });
+ });
+});
diff --git a/spec/javascripts/task_list_spec.js b/spec/javascripts/task_list_spec.js
new file mode 100644
index 00000000000..563f402de58
--- /dev/null
+++ b/spec/javascripts/task_list_spec.js
@@ -0,0 +1,156 @@
+import $ from 'jquery';
+import TaskList from '~/task_list';
+import axios from '~/lib/utils/axios_utils';
+
+describe('TaskList', () => {
+ let taskList;
+ let currentTarget;
+ const taskListOptions = {
+ selector: '.task-list',
+ dataType: 'issue',
+ fieldName: 'description',
+ lockVersion: 2,
+ };
+ const createTaskList = () => new TaskList(taskListOptions);
+
+ beforeEach(() => {
+ setFixtures(`
+ <div class="task-list">
+ <div class="js-task-list-container"></div>
+ </div>
+ `);
+
+ currentTarget = $('<div></div>');
+ taskList = createTaskList();
+ });
+
+ it('should call init when the class constructed', () => {
+ spyOn(TaskList.prototype, 'init').and.callThrough();
+ spyOn(TaskList.prototype, 'disable');
+ spyOn($.prototype, 'taskList');
+ spyOn($.prototype, 'on');
+
+ taskList = createTaskList();
+ const $taskListEl = $(taskList.taskListContainerSelector);
+
+ expect(taskList.init).toHaveBeenCalled();
+ expect(taskList.disable).toHaveBeenCalled();
+ expect($taskListEl.taskList).toHaveBeenCalledWith('enable');
+ expect($(document).on).toHaveBeenCalledWith(
+ 'tasklist:changed',
+ taskList.taskListContainerSelector,
+ taskList.updateHandler,
+ );
+ });
+
+ describe('getTaskListTarget', () => {
+ it('should return currentTarget from event object if exists', () => {
+ const $target = taskList.getTaskListTarget({ currentTarget });
+
+ expect($target).toEqual(currentTarget);
+ });
+
+ it('should return element of the taskListContainerSelector', () => {
+ const $target = taskList.getTaskListTarget();
+
+ expect($target).toEqual($(taskList.taskListContainerSelector));
+ });
+ });
+
+ describe('disableTaskListItems', () => {
+ it('should call taskList method with disable param', () => {
+ spyOn($.prototype, 'taskList');
+
+ taskList.disableTaskListItems({ currentTarget });
+
+ expect(currentTarget.taskList).toHaveBeenCalledWith('disable');
+ });
+ });
+
+ describe('enableTaskListItems', () => {
+ it('should call taskList method with enable param', () => {
+ spyOn($.prototype, 'taskList');
+
+ taskList.enableTaskListItems({ currentTarget });
+
+ expect(currentTarget.taskList).toHaveBeenCalledWith('enable');
+ });
+ });
+
+ describe('disable', () => {
+ it('should disable task list items and off document event', () => {
+ spyOn(taskList, 'disableTaskListItems');
+ spyOn($.prototype, 'off');
+
+ taskList.disable();
+
+ expect(taskList.disableTaskListItems).toHaveBeenCalled();
+ expect($(document).off).toHaveBeenCalledWith(
+ 'tasklist:changed',
+ taskList.taskListContainerSelector,
+ );
+ });
+ });
+
+ describe('update', () => {
+ it('should disable task list items and make a patch request then enable them again', done => {
+ const response = { data: { lock_version: 3 } };
+ spyOn(taskList, 'enableTaskListItems');
+ spyOn(taskList, 'disableTaskListItems');
+ spyOn(taskList, 'onSuccess');
+ spyOn(axios, 'patch').and.returnValue(Promise.resolve(response));
+
+ const value = 'hello world';
+ const endpoint = '/foo';
+ const target = $(`<input data-update-url="${endpoint}" value="${value}" />`);
+ const detail = {
+ index: 2,
+ checked: true,
+ lineNumber: 8,
+ lineSource: '- [ ] check item',
+ };
+ const event = { target, detail };
+ const patchData = {
+ [taskListOptions.dataType]: {
+ [taskListOptions.fieldName]: value,
+ lock_version: taskListOptions.lockVersion,
+ update_task: {
+ index: detail.index,
+ checked: detail.checked,
+ line_number: detail.lineNumber,
+ line_source: detail.lineSource,
+ },
+ },
+ };
+
+ taskList
+ .update(event)
+ .then(() => {
+ expect(taskList.disableTaskListItems).toHaveBeenCalledWith(event);
+ expect(axios.patch).toHaveBeenCalledWith(endpoint, patchData);
+ expect(taskList.enableTaskListItems).toHaveBeenCalledWith(event);
+ expect(taskList.onSuccess).toHaveBeenCalledWith(response.data);
+ expect(taskList.lockVersion).toEqual(response.data.lock_version);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ it('should handle request error and enable task list items', done => {
+ const response = { data: { error: 1 } };
+ spyOn(taskList, 'enableTaskListItems');
+ spyOn(taskList, 'onError');
+ spyOn(axios, 'patch').and.returnValue(Promise.reject({ response })); // eslint-disable-line prefer-promise-reject-errors
+
+ const event = { detail: {} };
+ taskList
+ .update(event)
+ .then(() => {
+ expect(taskList.enableTaskListItems).toHaveBeenCalledWith(event);
+ expect(taskList.onError).toHaveBeenCalledWith(response.data);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+});
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
index 96c0844f83c..5eef5682bbd 100644
--- a/spec/javascripts/test_bundle.js
+++ b/spec/javascripts/test_bundle.js
@@ -8,6 +8,7 @@ import '~/commons';
import Vue from 'vue';
import VueResource from 'vue-resource';
import Translate from '~/vue_shared/translate';
+import CheckEE from '~/vue_shared/mixins/is_ee';
import jasmineDiff from 'jasmine-diff';
import { getDefaultAdapter } from '~/lib/utils/axios_utils';
@@ -21,6 +22,16 @@ Vue.config.productionTip = false;
let hasVueWarnings = false;
Vue.config.warnHandler = (msg, vm, trace) => {
+ // The following workaround is necessary, so we are able to use setProps from Vue test utils
+ // see https://github.com/vuejs/vue-test-utils/issues/631#issuecomment-421108344
+ const currentStack = new Error().stack;
+ const isInVueTestUtils = currentStack
+ .split('\n')
+ .some(line => line.startsWith(' at VueWrapper.setProps ('));
+ if (isInVueTestUtils) {
+ return;
+ }
+
hasVueWarnings = true;
fail(`${msg}${trace}`);
};
@@ -33,6 +44,7 @@ Vue.config.errorHandler = function(err) {
Vue.use(VueResource);
Vue.use(Translate);
+Vue.use(CheckEE);
// enable test fixtures
jasmine.getFixtures().fixturesPath = FIXTURES_PATH;
@@ -57,6 +69,7 @@ window.gl = window.gl || {};
window.gl.TEST_HOST = TEST_HOST;
window.gon = window.gon || {};
window.gon.test_env = true;
+window.gon.ee = false;
gon.relative_url_root = '';
let hasUnhandledPromiseRejections = false;
@@ -187,6 +200,7 @@ if (process.env.BABEL_ENV === 'coverage') {
'./terminal/terminal_bundle.js',
'./users/users_bundle.js',
'./issue_show/index.js',
+ './pages/admin/application_settings/show/index.js',
];
describe('Uncovered files', function() {
diff --git a/spec/javascripts/user_popovers_spec.js b/spec/javascripts/user_popovers_spec.js
index 6cf8dd81b36..b174a51c1a0 100644
--- a/spec/javascripts/user_popovers_spec.js
+++ b/spec/javascripts/user_popovers_spec.js
@@ -2,6 +2,9 @@ import initUserPopovers from '~/user_popovers';
import UsersCache from '~/lib/utils/users_cache';
describe('User Popovers', () => {
+ const fixtureTemplate = 'merge_requests/diff_comment.html.raw';
+ preloadFixtures(fixtureTemplate);
+
const selector = '.js-user-link';
const dummyUser = { name: 'root' };
@@ -15,11 +18,7 @@ describe('User Popovers', () => {
};
beforeEach(() => {
- setFixtures(`
- <a href="/root" data-user-id="1" class="js-user-link" data-username="root" data-original-title="" title="">
- Root
- </a>
- `);
+ loadFixtures(fixtureTemplate);
const usersCacheSpy = () => Promise.resolve(dummyUser);
spyOn(UsersCache, 'retrieveById').and.callFake(userId => usersCacheSpy(userId));
@@ -31,7 +30,9 @@ describe('User Popovers', () => {
});
it('Should Show+Hide Popover on mouseenter and mouseleave', done => {
- triggerEvent('mouseenter', document.querySelector(selector));
+ const targetLink = document.querySelector(selector);
+ const { userId } = targetLink.dataset;
+ triggerEvent('mouseenter', targetLink);
setTimeout(() => {
const shownPopover = document.querySelector('.popover');
@@ -39,9 +40,9 @@ describe('User Popovers', () => {
expect(shownPopover).not.toBeNull();
expect(shownPopover.innerHTML).toContain(dummyUser.name);
- expect(UsersCache.retrieveById).toHaveBeenCalledWith('1');
+ expect(UsersCache.retrieveById).toHaveBeenCalledWith(userId.toString());
- triggerEvent('mouseleave', document.querySelector(selector));
+ triggerEvent('mouseleave', targetLink);
setTimeout(() => {
// After Mouse leave it should be hidden now
@@ -52,13 +53,15 @@ describe('User Popovers', () => {
});
it('Should Not show a popover on short mouse over', done => {
- triggerEvent('mouseenter', document.querySelector(selector));
+ const targetLink = document.querySelector(selector);
+ const { userId } = targetLink.dataset;
+ triggerEvent('mouseenter', targetLink);
setTimeout(() => {
expect(document.querySelector('.popover')).toBeNull();
- expect(UsersCache.retrieveById).not.toHaveBeenCalledWith('1');
+ expect(UsersCache.retrieveById).not.toHaveBeenCalledWith(userId.toString());
- triggerEvent('mouseleave', document.querySelector(selector));
+ triggerEvent('mouseleave', targetLink);
done();
});
diff --git a/spec/javascripts/vue_mr_widget/components/deployment_spec.js b/spec/javascripts/vue_mr_widget/components/deployment_spec.js
index e355416bd27..42bf3b7df09 100644
--- a/spec/javascripts/vue_mr_widget/components/deployment_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/deployment_spec.js
@@ -6,32 +6,36 @@ import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Deployment component', () => {
const Component = Vue.extend(deploymentComponent);
- const deploymentMockData = {
- id: 15,
- name: 'review/diplo',
- url: '/root/review-apps/environments/15',
- stop_url: '/root/review-apps/environments/15/stop',
- metrics_url: '/root/review-apps/environments/15/deployments/1/metrics',
- metrics_monitoring_url: '/root/review-apps/environments/15/metrics',
- external_url: 'http://gitlab.com.',
- external_url_formatted: 'gitlab',
- deployed_at: '2017-03-22T22:44:42.258Z',
- deployed_at_formatted: 'Mar 22, 2017 10:44pm',
- changes: [
- {
- path: 'index.html',
- external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/index.html',
- },
- {
- path: 'imgs/gallery.html',
- external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
- },
- {
- path: 'about/',
- external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/about/',
- },
- ],
- };
+ let deploymentMockData;
+
+ beforeEach(() => {
+ deploymentMockData = {
+ id: 15,
+ name: 'review/diplo',
+ url: '/root/review-apps/environments/15',
+ stop_url: '/root/review-apps/environments/15/stop',
+ metrics_url: '/root/review-apps/environments/15/deployments/1/metrics',
+ metrics_monitoring_url: '/root/review-apps/environments/15/metrics',
+ external_url: 'http://gitlab.com.',
+ external_url_formatted: 'gitlab',
+ deployed_at: '2017-03-22T22:44:42.258Z',
+ deployed_at_formatted: 'Mar 22, 2017 10:44pm',
+ changes: [
+ {
+ path: 'index.html',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/index.html',
+ },
+ {
+ path: 'imgs/gallery.html',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
+ },
+ {
+ path: 'about/',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/about/',
+ },
+ ],
+ };
+ });
let vm;
@@ -207,6 +211,31 @@ describe('Deployment component', () => {
});
});
+ describe('with a single change', () => {
+ beforeEach(() => {
+ deploymentMockData.changes = deploymentMockData.changes.slice(0, 1);
+
+ vm = mountComponent(Component, {
+ deployment: { ...deploymentMockData },
+ showMetrics: true,
+ });
+ });
+
+ it('renders the link to the review app without dropdown', () => {
+ expect(vm.$el.querySelector('.js-mr-wigdet-deployment-dropdown')).toBeNull();
+ expect(vm.$el.querySelector('.js-deploy-url-feature-flag')).not.toBeNull();
+ });
+
+ it('renders the link to the review app linked to to the first change', () => {
+ const expectedUrl = deploymentMockData.changes[0].external_url;
+ const deployUrl = vm.$el.querySelector('.js-deploy-url-feature-flag');
+
+ expect(vm.$el.querySelector('.js-mr-wigdet-deployment-dropdown')).toBeNull();
+ expect(deployUrl).not.toBeNull();
+ expect(deployUrl.href).toEqual(expectedUrl);
+ });
+ });
+
describe('deployment status', () => {
describe('running', () => {
beforeEach(() => {
diff --git a/spec/javascripts/vue_mr_widget/components/states/commit_edit_spec.js b/spec/javascripts/vue_mr_widget/components/states/commit_edit_spec.js
new file mode 100644
index 00000000000..994d6255324
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/states/commit_edit_spec.js
@@ -0,0 +1,85 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue';
+
+const localVue = createLocalVue();
+const testCommitMessage = 'Test commit message';
+const testLabel = 'Test label';
+const testInputId = 'test-input-id';
+
+describe('Commits edit component', () => {
+ let wrapper;
+
+ const createComponent = (slots = {}) => {
+ wrapper = shallowMount(localVue.extend(CommitEdit), {
+ localVue,
+ sync: false,
+ propsData: {
+ value: testCommitMessage,
+ label: testLabel,
+ inputId: testInputId,
+ },
+ slots: {
+ ...slots,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findTextarea = () => wrapper.find('.form-control');
+
+ it('has a correct label', () => {
+ const labelElement = wrapper.find('.col-form-label');
+
+ expect(labelElement.text()).toBe(testLabel);
+ });
+
+ describe('textarea', () => {
+ it('has a correct ID', () => {
+ expect(findTextarea().attributes('id')).toBe(testInputId);
+ });
+
+ it('has a correct value', () => {
+ expect(findTextarea().element.value).toBe(testCommitMessage);
+ });
+
+ it('emits an input event and receives changed value', () => {
+ const changedCommitMessage = 'Changed commit message';
+
+ findTextarea().element.value = changedCommitMessage;
+ findTextarea().trigger('input');
+
+ expect(wrapper.emitted().input[0]).toEqual([changedCommitMessage]);
+ expect(findTextarea().element.value).toBe(changedCommitMessage);
+ });
+ });
+
+ describe('when slots are present', () => {
+ beforeEach(() => {
+ createComponent({
+ header: `<div class="test-header">${testCommitMessage}</div>`,
+ checkbox: `<label slot="checkbox" class="test-checkbox">${testLabel}</label >`,
+ });
+ });
+
+ it('renders header slot correctly', () => {
+ const headerSlotElement = wrapper.find('.test-header');
+
+ expect(headerSlotElement.exists()).toBe(true);
+ expect(headerSlotElement.text()).toBe(testCommitMessage);
+ });
+
+ it('renders checkbox slot correctly', () => {
+ const checkboxSlotElement = wrapper.find('.test-checkbox');
+
+ expect(checkboxSlotElement.exists()).toBe(true);
+ expect(checkboxSlotElement.text()).toBe(testLabel);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js
new file mode 100644
index 00000000000..daf1cc2d98b
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js
@@ -0,0 +1,61 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlDropdownItem } from '@gitlab/ui';
+import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
+
+const localVue = createLocalVue();
+const commits = [
+ {
+ title: 'Commit 1',
+ short_id: '78d5b7',
+ message: 'Update test.txt',
+ },
+ {
+ title: 'Commit 2',
+ short_id: '34cbe28b',
+ message: 'Fixed test',
+ },
+ {
+ title: 'Commit 3',
+ short_id: 'fa42932a',
+ message: 'Added changelog',
+ },
+];
+
+describe('Commits message dropdown component', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(localVue.extend(CommitMessageDropdown), {
+ localVue,
+ sync: false,
+ propsData: {
+ commits,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findDropdownElements = () => wrapper.findAll(GlDropdownItem);
+ const findFirstDropdownElement = () => findDropdownElements().at(0);
+
+ it('should have 3 elements in dropdown list', () => {
+ expect(findDropdownElements().length).toBe(3);
+ });
+
+ it('should have correct message for the first dropdown list element', () => {
+ expect(findFirstDropdownElement().text()).toBe('78d5b7 Commit 1');
+ });
+
+ it('should emit a commit title on selecting commit', () => {
+ findFirstDropdownElement().vm.$emit('click');
+
+ expect(wrapper.emitted().input[0]).toEqual(['Update test.txt']);
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_commits_header_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
new file mode 100644
index 00000000000..5cf6408cf34
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
@@ -0,0 +1,110 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+
+const localVue = createLocalVue();
+
+describe('Commits header component', () => {
+ let wrapper;
+
+ const createComponent = props => {
+ wrapper = shallowMount(localVue.extend(CommitsHeader), {
+ localVue,
+ sync: false,
+ propsData: {
+ isSquashEnabled: false,
+ targetBranch: 'master',
+ commitsCount: 5,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findHeaderWrapper = () => wrapper.find('.js-mr-widget-commits-count');
+ const findCommitToggle = () => wrapper.find('.commit-edit-toggle');
+ const findIcon = () => wrapper.find(Icon);
+ const findCommitsCountMessage = () => wrapper.find('.commits-count-message');
+ const findTargetBranchMessage = () => wrapper.find('.label-branch');
+ const findModifyButton = () => wrapper.find('.modify-message-button');
+
+ 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', () => {
+ createComponent();
+ wrapper.setData({ expanded: false });
+
+ expect(findIcon().props('name')).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('master');
+ });
+ });
+
+ describe('when expanded', () => {
+ beforeEach(() => {
+ createComponent();
+ wrapper.setData({ expanded: true });
+ });
+
+ it('toggle has aria-label equal to collapse', done => {
+ wrapper.vm.$nextTick(() => {
+ expect(findCommitToggle().attributes('aria-label')).toBe('Collapse');
+ done();
+ });
+ });
+
+ it('has a chevron-down icon', done => {
+ wrapper.vm.$nextTick(() => {
+ expect(findIcon().props('name')).toBe('chevron-down');
+ done();
+ });
+ });
+
+ it('has a collapse text', done => {
+ wrapper.vm.$nextTick(() => {
+ expect(findHeaderWrapper().text()).toBe('Collapse');
+ done();
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
index f9cd5c8bd3c..0ddbdf67d8b 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
@@ -1,89 +1,154 @@
-import Vue from 'vue';
-import conflictsComponent from '~/vue_merge_request_widget/components/states/mr_widget_conflicts.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import $ from 'jquery';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import ConflictsComponent from '~/vue_merge_request_widget/components/states/mr_widget_conflicts.vue';
import { removeBreakLine } from 'spec/helpers/vue_component_helper';
describe('MRWidgetConflicts', () => {
- let Component;
let vm;
const path = '/conflicts';
+ function createComponent(propsData = {}) {
+ const localVue = createLocalVue();
+
+ vm = shallowMount(localVue.extend(ConflictsComponent), {
+ propsData,
+ });
+ }
+
beforeEach(() => {
- Component = Vue.extend(conflictsComponent);
+ spyOn($.fn, 'popover').and.callThrough();
});
afterEach(() => {
- vm.$destroy();
+ vm.destroy();
});
describe('when allowed to merge', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
+ createComponent({
mr: {
canMerge: true,
conflictResolutionPath: path,
+ conflictsDocsPath: '',
},
});
});
it('should tell you about conflicts without bothering other people', () => {
- expect(vm.$el.textContent).toContain('There are merge conflicts');
- expect(vm.$el.textContent).not.toContain('ask someone with write access');
+ expect(vm.text()).toContain('There are merge conflicts');
+ expect(vm.text()).not.toContain('ask someone with write access');
});
it('should allow you to resolve the conflicts', () => {
- const resolveButton = vm.$el.querySelector('.js-resolve-conflicts-button');
+ const resolveButton = vm.find('.js-resolve-conflicts-button');
- expect(resolveButton.textContent).toContain('Resolve conflicts');
- expect(resolveButton.getAttribute('href')).toEqual(path);
+ expect(resolveButton.text()).toContain('Resolve conflicts');
+ expect(resolveButton.attributes('href')).toEqual(path);
});
it('should have merge buttons', () => {
- const mergeButton = vm.$el.querySelector('.js-disabled-merge-button');
- const mergeLocallyButton = vm.$el.querySelector('.js-merge-locally-button');
+ const mergeLocallyButton = vm.find('.js-merge-locally-button');
- expect(mergeButton.textContent).toContain('Merge');
- expect(mergeButton.disabled).toBeTruthy();
- expect(mergeButton.classList.contains('btn-success')).toEqual(true);
- expect(mergeLocallyButton.textContent).toContain('Merge locally');
+ expect(mergeLocallyButton.text()).toContain('Merge locally');
});
});
describe('when user does not have permission to merge', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
+ it('should show proper message', () => {
+ createComponent({
mr: {
canMerge: false,
+ conflictsDocsPath: '',
},
});
- });
- it('should show proper message', () => {
- expect(vm.$el.textContent.trim().replace(/\s\s+/g, ' ')).toContain(
- 'ask someone with write access',
- );
+ expect(
+ vm
+ .text()
+ .trim()
+ .replace(/\s\s+/g, ' '),
+ ).toContain('ask someone with write access');
});
it('should not have action buttons', () => {
- expect(vm.$el.querySelector('.js-disabled-merge-button')).toBeDefined();
- expect(vm.$el.querySelector('.js-resolve-conflicts-button')).toBeNull();
- expect(vm.$el.querySelector('.js-merge-locally-button')).toBeNull();
+ createComponent({
+ mr: {
+ canMerge: false,
+ conflictsDocsPath: '',
+ },
+ });
+
+ expect(vm.contains('.js-resolve-conflicts-button')).toBe(false);
+ expect(vm.contains('.js-merge-locally-button')).toBe(false);
+ });
+
+ it('should not have resolve button when no conflict resolution path', () => {
+ createComponent({
+ mr: {
+ canMerge: true,
+ conflictResolutionPath: null,
+ conflictsDocsPath: '',
+ },
+ });
+
+ expect(vm.contains('.js-resolve-conflicts-button')).toBe(false);
});
});
describe('when fast-forward or semi-linear merge enabled', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
+ it('should tell you to rebase locally', () => {
+ createComponent({
mr: {
shouldBeRebased: true,
+ conflictsDocsPath: '',
},
});
- });
- it('should tell you to rebase locally', () => {
- expect(removeBreakLine(vm.$el.textContent).trim()).toContain(
+ expect(removeBreakLine(vm.text()).trim()).toContain(
'Fast-forward merge is not possible. To merge this request, first rebase locally.',
);
});
});
+
+ describe('when source branch protected', () => {
+ beforeEach(() => {
+ createComponent({
+ mr: {
+ canMerge: true,
+ conflictResolutionPath: gl.TEST_HOST,
+ sourceBranchProtected: true,
+ conflictsDocsPath: '',
+ },
+ });
+ });
+
+ it('sets resolve button as disabled', () => {
+ expect(vm.find('.js-resolve-conflicts-button').attributes('disabled')).toBe('disabled');
+ });
+
+ it('renders popover', () => {
+ expect($.fn.popover).toHaveBeenCalled();
+ });
+ });
+
+ describe('when source branch not protected', () => {
+ beforeEach(() => {
+ createComponent({
+ mr: {
+ canMerge: true,
+ conflictResolutionPath: gl.TEST_HOST,
+ sourceBranchProtected: false,
+ conflictsDocsPath: '',
+ },
+ });
+ });
+
+ it('sets resolve button as disabled', () => {
+ expect(vm.find('.js-resolve-conflicts-button').attributes('disabled')).toBe(undefined);
+ });
+
+ it('renders popover', () => {
+ expect($.fn.popover).not.toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
index d46ad0acc9b..b9718a78fa4 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
@@ -121,14 +121,14 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
expect(vm.$el.innerText).toContain('to be merged automatically when the pipeline succeeds');
expect(vm.$el.innerText).toContain('The changes will be merged into');
expect(vm.$el.innerText).toContain(targetBranch);
- expect(vm.$el.innerText).toContain('The source branch will not be removed');
+ expect(vm.$el.innerText).toContain('The source branch will not be deleted');
expect(vm.$el.querySelector('.js-cancel-auto-merge').innerText).toContain(
'Cancel automatic merge',
);
expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy();
expect(vm.$el.querySelector('.js-remove-source-branch').innerText).toContain(
- 'Remove source branch',
+ 'Delete source branch',
);
expect(vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeFalsy();
@@ -143,19 +143,19 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
});
});
- it('should show source branch will be removed text when it source branch set to remove', done => {
+ it('should show source branch will be deleted text when it source branch set to remove', done => {
vm.mr.shouldRemoveSourceBranch = true;
Vue.nextTick(() => {
const normalizedText = vm.$el.innerText.replace(/\s+/g, ' ');
- expect(normalizedText).toContain('The source branch will be removed');
- expect(normalizedText).not.toContain('The source branch will not be removed');
+ expect(normalizedText).toContain('The source branch will be deleted');
+ expect(normalizedText).not.toContain('The source branch will not be deleted');
done();
});
});
- it('should not show remove source branch button when user not able to remove source branch', done => {
+ it('should not show delete source branch button when user not able to delete source branch', done => {
vm.mr.currentUserId = 4;
Vue.nextTick(() => {
@@ -164,7 +164,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
});
});
- it('should disable remove source branch button when the action is in progress', done => {
+ it('should disable delete source branch button when the action is in progress', done => {
vm.isRemovingSourceBranch = true;
Vue.nextTick(() => {
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
index da5cb752c6f..1683da805b9 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
@@ -128,7 +128,7 @@ describe('MRWidgetMerged', () => {
new Promise(resolve => {
resolve({
data: {
- message: 'Branch was removed',
+ message: 'Branch was deleted',
},
});
}),
@@ -157,8 +157,8 @@ describe('MRWidgetMerged', () => {
expect(vm.$el.textContent).toContain(targetBranch);
});
- it('renders information about branch being removed', () => {
- expect(vm.$el.textContent).toContain('The source branch has been removed');
+ 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', () => {
@@ -189,24 +189,24 @@ describe('MRWidgetMerged', () => {
expect(selectors.mergeCommitShaLink.href).toBe(vm.mr.mergeCommitPath);
});
- it('should not show source branch removed text', done => {
+ it('should not show source branch deleted text', done => {
vm.mr.sourceBranchRemoved = false;
Vue.nextTick(() => {
- expect(vm.$el.innerText).toContain('You can remove source branch now');
- expect(vm.$el.innerText).not.toContain('The source branch has been removed');
+ expect(vm.$el.innerText).toContain('You can delete the source branch now');
+ expect(vm.$el.innerText).not.toContain('The source branch has been deleted');
done();
});
});
- it('should show source branch removing text', done => {
+ it('should show source branch deleting text', done => {
vm.mr.isRemovingSourceBranch = true;
vm.mr.sourceBranchRemoved = false;
Vue.nextTick(() => {
- expect(vm.$el.innerText).toContain('The source branch is being removed');
- expect(vm.$el.innerText).not.toContain('You can remove source branch now');
- expect(vm.$el.innerText).not.toContain('The source branch has been removed');
+ expect(vm.$el.innerText).toContain('The source branch is being deleted');
+ expect(vm.$el.innerText).not.toContain('You can delete the source branch now');
+ expect(vm.$el.innerText).not.toContain('The source branch has been deleted');
done();
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 2119a3b927a..08e173b0a10 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -1,11 +1,16 @@
import Vue from '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 CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
+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 eventHub from '~/vue_merge_request_widget/event_hub';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
const commitMessage = 'This is the commit message';
+const squashCommitMessage = 'This is the squash commit message';
const commitMessageWithDescription = 'This is the commit message description';
-const createComponent = (customConfig = {}) => {
- const Component = Vue.extend(ReadyToMerge);
+const createTestMr = customConfig => {
const mr = {
isPipelineActive: false,
pipeline: null,
@@ -16,22 +21,34 @@ const createComponent = (customConfig = {}) => {
hasCI: false,
ciStatus: null,
sha: '12345678',
+ squash: false,
commitMessage,
+ squashCommitMessage,
commitMessageWithDescription,
shouldRemoveSourceBranch: true,
canRemoveSourceBranch: false,
+ targetBranch: 'master',
};
Object.assign(mr, customConfig.mr);
- const service = {
- merge() {},
- poll() {},
- };
+ return mr;
+};
+
+const createTestService = () => ({
+ merge() {},
+ poll() {},
+});
+
+const createComponent = (customConfig = {}) => {
+ const Component = Vue.extend(ReadyToMerge);
return new Component({
el: document.createElement('div'),
- propsData: { mr, service },
+ propsData: {
+ mr: createTestMr(customConfig),
+ service: createTestService(),
+ },
});
};
@@ -87,21 +104,6 @@ describe('ReadyToMerge', () => {
});
});
- describe('commitMessageLinkTitle', () => {
- const withDesc = 'Include description in commit message';
- const withoutDesc = "Don't include description in commit message";
-
- it('should return message with description', () => {
- expect(vm.commitMessageLinkTitle).toEqual(withDesc);
- });
-
- it('should return message without description', () => {
- vm.useCommitMessageWithDescription = true;
-
- expect(vm.commitMessageLinkTitle).toEqual(withoutDesc);
- });
- });
-
describe('status', () => {
it('defaults to success', () => {
vm.mr.pipeline = true;
@@ -268,55 +270,43 @@ describe('ReadyToMerge', () => {
vm.mr.isMergeAllowed = false;
vm.mr.isPipelineActive = false;
- expect(vm.shouldShowMergeControls()).toBeFalsy();
+ expect(vm.shouldShowMergeControls).toBeFalsy();
});
it('should return true when the build succeeded or build not required to succeed', () => {
vm.mr.isMergeAllowed = true;
vm.mr.isPipelineActive = false;
- expect(vm.shouldShowMergeControls()).toBeTruthy();
+ expect(vm.shouldShowMergeControls).toBeTruthy();
});
it('should return true when showing the MWPS button and a pipeline is running that needs to be successful', () => {
vm.mr.isMergeAllowed = false;
vm.mr.isPipelineActive = true;
- expect(vm.shouldShowMergeControls()).toBeTruthy();
+ expect(vm.shouldShowMergeControls).toBeTruthy();
});
it('should return true when showing the MWPS button but not required for the pipeline to succeed', () => {
vm.mr.isMergeAllowed = true;
vm.mr.isPipelineActive = true;
- expect(vm.shouldShowMergeControls()).toBeTruthy();
+ expect(vm.shouldShowMergeControls).toBeTruthy();
});
});
- describe('updateCommitMessage', () => {
+ describe('updateMergeCommitMessage', () => {
it('should revert flag and change commitMessage', () => {
- expect(vm.useCommitMessageWithDescription).toBeFalsy();
expect(vm.commitMessage).toEqual(commitMessage);
- vm.updateCommitMessage();
+ vm.updateMergeCommitMessage(true);
- expect(vm.useCommitMessageWithDescription).toBeTruthy();
expect(vm.commitMessage).toEqual(commitMessageWithDescription);
- vm.updateCommitMessage();
+ vm.updateMergeCommitMessage(false);
- expect(vm.useCommitMessageWithDescription).toBeFalsy();
expect(vm.commitMessage).toEqual(commitMessage);
});
});
- describe('toggleCommitMessageEditor', () => {
- it('should toggle showCommitMessageEditor flag', () => {
- expect(vm.showCommitMessageEditor).toBeFalsy();
- vm.toggleCommitMessageEditor();
-
- expect(vm.showCommitMessageEditor).toBeTruthy();
- });
- });
-
describe('handleMergeButtonClick', () => {
const returnPromise = status =>
new Promise(resolve => {
@@ -612,6 +602,137 @@ describe('ReadyToMerge', () => {
});
});
+ describe('render children components', () => {
+ let wrapper;
+ const localVue = createLocalVue();
+
+ const createLocalComponent = (customConfig = {}) => {
+ wrapper = shallowMount(localVue.extend(ReadyToMerge), {
+ localVue,
+ propsData: {
+ mr: createTestMr(customConfig),
+ service: createTestService(),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findCheckboxElement = () => wrapper.find(SquashBeforeMerge);
+ const findCommitsHeaderElement = () => wrapper.find(CommitsHeader);
+ const findCommitEditElements = () => wrapper.findAll(CommitEdit);
+ const findCommitDropdownElement = () => wrapper.find(CommitMessageDropdown);
+
+ describe('squash checkbox', () => {
+ it('should be rendered when squash before merge is enabled and there is more than 1 commit', () => {
+ createLocalComponent({
+ mr: { commitsCount: 2, enableSquashBeforeMerge: true },
+ });
+
+ expect(findCheckboxElement().exists()).toBeTruthy();
+ });
+
+ it('should not be rendered when squash before merge is disabled', () => {
+ createLocalComponent({ mr: { commitsCount: 2, enableSquashBeforeMerge: false } });
+
+ expect(findCheckboxElement().exists()).toBeFalsy();
+ });
+
+ it('should not be rendered when there is only 1 commit', () => {
+ createLocalComponent({ mr: { commitsCount: 1, enableSquashBeforeMerge: true } });
+
+ expect(findCheckboxElement().exists()).toBeFalsy();
+ });
+ });
+
+ describe('commits count collapsible header', () => {
+ it('should be rendered if fast-forward is disabled', () => {
+ createLocalComponent();
+
+ expect(findCommitsHeaderElement().exists()).toBeTruthy();
+ });
+
+ it('should not be rendered if fast-forward is enabled', () => {
+ createLocalComponent({ mr: { ffOnlyEnabled: true } });
+
+ expect(findCommitsHeaderElement().exists()).toBeFalsy();
+ });
+ });
+
+ describe('commits edit components', () => {
+ it('should have one edit component when squash is disabled', () => {
+ createLocalComponent();
+
+ expect(findCommitEditElements().length).toBe(1);
+ });
+
+ const findFirstCommitEditLabel = () =>
+ findCommitEditElements()
+ .at(0)
+ .props('label');
+
+ it('should have two edit components when squash is enabled and there is more than 1 commit', () => {
+ createLocalComponent({
+ mr: {
+ commitsCount: 2,
+ squash: true,
+ enableSquashBeforeMerge: true,
+ },
+ });
+
+ expect(findCommitEditElements().length).toBe(2);
+ });
+
+ it('should have one edit components when squash is enabled and there is 1 commit only', () => {
+ createLocalComponent({
+ mr: {
+ commitsCount: 1,
+ squash: true,
+ enableSquashBeforeMerge: true,
+ },
+ });
+
+ expect(findCommitEditElements().length).toBe(1);
+ });
+
+ it('should have correct edit merge commit label', () => {
+ createLocalComponent();
+
+ expect(findFirstCommitEditLabel()).toBe('Merge commit message');
+ });
+
+ it('should have correct edit squash commit label', () => {
+ createLocalComponent({
+ mr: {
+ commitsCount: 2,
+ squash: true,
+ enableSquashBeforeMerge: true,
+ },
+ });
+
+ expect(findFirstCommitEditLabel()).toBe('Squash commit message');
+ });
+ });
+
+ describe('commits dropdown', () => {
+ it('should not be rendered if squash is disabled', () => {
+ createLocalComponent();
+
+ expect(findCommitDropdownElement().exists()).toBeFalsy();
+ });
+
+ it('should be rendered if squash is enabled and there is more than 1 commit', () => {
+ createLocalComponent({
+ mr: { enableSquashBeforeMerge: true, squash: true, commitsCount: 2 },
+ });
+
+ expect(findCommitDropdownElement().exists()).toBeTruthy();
+ });
+ });
+ });
+
describe('Merge controls', () => {
describe('when allowed to merge', () => {
beforeEach(() => {
@@ -644,10 +765,6 @@ describe('ReadyToMerge', () => {
expect(vm.$el.querySelector('.js-remove-source-branch-checkbox')).toBeNull();
});
- it('does not show modify commit message button', () => {
- expect(vm.$el.querySelector('.js-modify-commit-message-button')).toBeNull();
- });
-
it('shows message to resolve all items before being allowed to merge', () => {
expect(vm.$el.querySelector('.js-resolve-mr-widget-items-message')).toBeDefined();
});
@@ -660,7 +777,7 @@ describe('ReadyToMerge', () => {
mr: { ffOnlyEnabled: false },
});
- expect(customVm.$el.querySelector('.js-fast-forward-message')).toBeNull();
+ expect(customVm.$el.querySelector('.mr-fast-forward-message')).toBeNull();
expect(customVm.$el.querySelector('.js-modify-commit-message-button')).toBeDefined();
});
@@ -669,7 +786,7 @@ describe('ReadyToMerge', () => {
mr: { ffOnlyEnabled: true },
});
- expect(customVm.$el.querySelector('.js-fast-forward-message')).toBeDefined();
+ expect(customVm.$el.querySelector('.mr-fast-forward-message')).toBeDefined();
expect(customVm.$el.querySelector('.js-modify-commit-message-button')).toBeNull();
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js
new file mode 100644
index 00000000000..d6d8eecfcb9
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js
@@ -0,0 +1,100 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue';
+
+const localVue = createLocalVue();
+
+describe('Squash before merge component', () => {
+ let wrapper;
+
+ const createComponent = props => {
+ wrapper = shallowMount(localVue.extend(SquashBeforeMerge), {
+ localVue,
+ sync: false,
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('checkbox', () => {
+ const findCheckbox = () => wrapper.find('.qa-squash-checkbox');
+
+ it('is unchecked if passed value prop is false', () => {
+ createComponent({
+ value: false,
+ });
+
+ expect(findCheckbox().element.checked).toBeFalsy();
+ });
+
+ it('is checked if passed value prop is true', () => {
+ createComponent({
+ value: true,
+ });
+
+ expect(findCheckbox().element.checked).toBeTruthy();
+ });
+
+ it('changes value on click', done => {
+ createComponent({
+ value: false,
+ });
+
+ findCheckbox().element.checked = true;
+
+ findCheckbox().trigger('change');
+
+ wrapper.vm.$nextTick(() => {
+ expect(findCheckbox().element.checked).toBeTruthy();
+ done();
+ });
+ });
+
+ it('is disabled if isDisabled prop is true', () => {
+ createComponent({
+ value: false,
+ isDisabled: true,
+ });
+
+ expect(findCheckbox().attributes('disabled')).toBeTruthy();
+ });
+ });
+
+ describe('about link', () => {
+ it('is not rendered if no help path is passed', () => {
+ createComponent({
+ value: false,
+ });
+
+ const aboutLink = wrapper.find('a');
+
+ expect(aboutLink.exists()).toBeFalsy();
+ });
+
+ it('is rendered if help path is passed', () => {
+ createComponent({
+ value: false,
+ helpPath: 'test-path',
+ });
+
+ const aboutLink = wrapper.find('a');
+
+ expect(aboutLink.exists()).toBeTruthy();
+ });
+
+ it('should have a correct help path if passed', () => {
+ createComponent({
+ value: false,
+ helpPath: 'test-path',
+ });
+
+ const aboutLink = wrapper.find('a');
+
+ expect(aboutLink.attributes('href')).toEqual('test-path');
+ });
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/mock_data.js b/spec/javascripts/vue_mr_widget/mock_data.js
index 072e98fc0e8..6ef07f81705 100644
--- a/spec/javascripts/vue_mr_widget/mock_data.js
+++ b/spec/javascripts/vue_mr_widget/mock_data.js
@@ -58,7 +58,7 @@ export default {
merge_user: null,
diff_head_sha: '104096c51715e12e7ae41f9333e9fa35b73f385d',
diff_head_commit_short_id: '104096c5',
- merge_commit_message:
+ default_merge_commit_message:
"Merge branch 'daaaa' into 'master'\n\nUpdate README.md\n\nSee merge request !22",
pipeline: {
id: 172,
@@ -213,14 +213,16 @@ export default {
merge_check_path: '/root/acets-app/merge_requests/22/merge_check',
ci_environments_status_url: '/root/acets-app/merge_requests/22/ci_environments_status',
project_archived: false,
- merge_commit_message_with_description:
+ default_merge_commit_message_with_description:
"Merge branch 'daaaa' into 'master'\n\nUpdate README.md\n\nSee merge request !22",
+ default_squash_commit_message: 'Test squash commit message',
diverged_commits_count: 0,
only_allow_merge_if_pipeline_succeeds: false,
commit_change_content_path: '/root/acets-app/merge_requests/22/commit_change_content',
merge_commit_path:
'http://localhost:3000/root/acets-app/commit/53027d060246c8f47e4a9310fb332aa52f221775',
troubleshooting_docs_path: 'help',
+ squash: true,
};
export const mockStore = {
diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
index f72bf627c10..3e8f73646c8 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -5,7 +5,7 @@ import notify from '~/lib/utils/notify';
import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import mockData from './mock_data';
-import { faviconDataUrl, overlayDataUrl, faviconWithOverlayDataUrl } from '../lib/utils/mock_data';
+import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data';
const returnPromise = data =>
new Promise(resolve => {
@@ -18,7 +18,10 @@ describe('mrWidgetOptions', () => {
let vm;
let MrWidgetOptions;
+ const COLLABORATION_MESSAGE = 'Allows commits from members who can merge to the target branch';
+
beforeEach(() => {
+ gon.features = { approvalRules: false };
// Prevent component mounting
delete mrWidgetOptions.el;
@@ -29,6 +32,7 @@ describe('mrWidgetOptions', () => {
});
afterEach(() => {
+ gon.features = null;
vm.$destroy();
});
@@ -132,6 +136,53 @@ describe('mrWidgetOptions', () => {
expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
});
});
+
+ describe('shouldRenderCollaborationStatus', () => {
+ describe('when collaboration is allowed', () => {
+ beforeEach(() => {
+ vm.mr.allowCollaboration = true;
+ });
+
+ describe('when merge request is opened', () => {
+ beforeEach(done => {
+ vm.mr.isOpen = true;
+ vm.$nextTick(done);
+ });
+
+ it('should render collaboration status', () => {
+ expect(vm.$el.textContent).toContain(COLLABORATION_MESSAGE);
+ });
+ });
+
+ describe('when merge request is not opened', () => {
+ beforeEach(done => {
+ vm.mr.isOpen = false;
+ vm.$nextTick(done);
+ });
+
+ it('should not render collaboration status', () => {
+ expect(vm.$el.textContent).not.toContain(COLLABORATION_MESSAGE);
+ });
+ });
+ });
+
+ describe('when collaboration is not allowed', () => {
+ beforeEach(() => {
+ vm.mr.allowCollaboration = false;
+ });
+
+ describe('when merge request is opened', () => {
+ beforeEach(done => {
+ vm.mr.isOpen = true;
+ vm.$nextTick(done);
+ });
+
+ it('should not render collaboration status', () => {
+ expect(vm.$el.textContent).not.toContain(COLLABORATION_MESSAGE);
+ });
+ });
+ });
+ });
});
describe('methods', () => {
@@ -291,17 +342,27 @@ describe('mrWidgetOptions', () => {
vm.mr.ciStatusFaviconPath = overlayDataUrl;
vm.setFaviconHelper()
.then(() => {
- expect(faviconElement.getAttribute('href')).toEqual(faviconWithOverlayDataUrl);
+ /*
+ It would be better if we'd could mock commonUtils.setFaviconURL
+ with a spy and test that it was called. We are doing the following
+ tests as a proxy to show that the function has been called
+ */
+ expect(faviconElement.getAttribute('href')).not.toEqual(null);
+ expect(faviconElement.getAttribute('href')).not.toEqual(overlayDataUrl);
+ expect(faviconElement.getAttribute('href')).not.toEqual(faviconDataUrl);
done();
})
.catch(done.fail);
});
- it('should not call setFavicon when there is no ciStatusFaviconPath', () => {
+ it('should not call setFavicon when there is no ciStatusFaviconPath', done => {
vm.mr.ciStatusFaviconPath = null;
- vm.setFaviconHelper();
-
- expect(faviconElement.getAttribute('href')).toEqual(null);
+ vm.setFaviconHelper()
+ .then(() => {
+ expect(faviconElement.getAttribute('href')).toEqual(null);
+ done();
+ })
+ .catch(done.fail);
});
});
@@ -404,7 +465,7 @@ describe('mrWidgetOptions', () => {
vm.$nextTick(() => {
const tooltip = vm.$el.querySelector('.fa-question-circle');
- expect(vm.$el.textContent).toContain('Removes source branch');
+ expect(vm.$el.textContent).toContain('Deletes source branch');
expect(tooltip.getAttribute('data-original-title')).toBe(
'A user with write access to the source branch selected this option',
);
@@ -419,8 +480,8 @@ describe('mrWidgetOptions', () => {
vm.mr.state = 'merged';
vm.$nextTick(() => {
- expect(vm.$el.textContent).toContain('The source branch has been removed');
- expect(vm.$el.textContent).not.toContain('Removes source branch');
+ expect(vm.$el.textContent).toContain('The source branch has been deleted');
+ expect(vm.$el.textContent).not.toContain('Deletes source branch');
done();
});
diff --git a/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js b/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js
index 61ef26cd080..b356ea85cad 100644
--- a/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js
+++ b/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js
@@ -76,4 +76,28 @@ describe('getStateKey', () => {
expect(bound()).toEqual('archived');
});
+
+ it('returns rebased state key', () => {
+ const context = {
+ mergeStatus: 'checked',
+ mergeWhenPipelineSucceeds: false,
+ canMerge: true,
+ onlyAllowMergeIfPipelineSucceeds: true,
+ isPipelineFailed: true,
+ hasMergeableDiscussionsState: false,
+ isPipelineBlocked: false,
+ canBeMerged: false,
+ shouldBeRebased: true,
+ };
+ const data = {
+ project_archived: false,
+ branch_missing: false,
+ commits_count: 2,
+ has_conflicts: false,
+ work_in_progress: false,
+ };
+ const bound = getStateKey.bind(context, data);
+
+ expect(bound()).toEqual('rebase');
+ });
});
diff --git a/spec/javascripts/vue_shared/components/callout_spec.js b/spec/javascripts/vue_shared/components/callout_spec.js
index e62bd86f4ca..91208dfb31a 100644
--- a/spec/javascripts/vue_shared/components/callout_spec.js
+++ b/spec/javascripts/vue_shared/components/callout_spec.js
@@ -1,45 +1,66 @@
-import Vue from 'vue';
-import callout from '~/vue_shared/components/callout.vue';
-import createComponent from 'spec/helpers/vue_mount_component_helper';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Callout from '~/vue_shared/components/callout.vue';
+
+const TEST_MESSAGE = 'This is a callout message!';
+const TEST_SLOT = '<button>This is a callout slot!</button>';
+
+const localVue = createLocalVue();
describe('Callout Component', () => {
- let CalloutComponent;
- let vm;
- const exampleMessage = 'This is a callout message!';
+ let wrapper;
- beforeEach(() => {
- CalloutComponent = Vue.extend(callout);
- });
+ const factory = options => {
+ wrapper = shallowMount(localVue.extend(Callout), {
+ localVue,
+ ...options,
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('should render the appropriate variant of callout', () => {
- vm = createComponent(CalloutComponent, {
- category: 'info',
- message: exampleMessage,
+ factory({
+ propsData: {
+ category: 'info',
+ message: TEST_MESSAGE,
+ },
});
- expect(vm.$el.getAttribute('class')).toEqual('bs-callout bs-callout-info');
+ expect(wrapper.classes()).toEqual(['bs-callout', 'bs-callout-info']);
- expect(vm.$el.tagName).toEqual('DIV');
+ expect(wrapper.element.tagName).toEqual('DIV');
});
it('should render accessibility attributes', () => {
- vm = createComponent(CalloutComponent, {
- message: exampleMessage,
+ factory({
+ propsData: {
+ message: TEST_MESSAGE,
+ },
});
- expect(vm.$el.getAttribute('role')).toEqual('alert');
- expect(vm.$el.getAttribute('aria-live')).toEqual('assertive');
+ expect(wrapper.attributes('role')).toEqual('alert');
+ expect(wrapper.attributes('aria-live')).toEqual('assertive');
});
it('should render the provided message', () => {
- vm = createComponent(CalloutComponent, {
- message: exampleMessage,
+ factory({
+ propsData: {
+ message: TEST_MESSAGE,
+ },
+ });
+
+ expect(wrapper.element.innerHTML.trim()).toEqual(TEST_MESSAGE);
+ });
+
+ it('should render the provided slot', () => {
+ factory({
+ slots: {
+ default: TEST_SLOT,
+ },
});
- expect(vm.$el.innerHTML.trim()).toEqual(exampleMessage);
+ expect(wrapper.element.innerHTML.trim()).toEqual(TEST_SLOT);
});
});
diff --git a/spec/javascripts/vue_shared/components/changed_file_icon_spec.js b/spec/javascripts/vue_shared/components/changed_file_icon_spec.js
index 5b1038840c7..634ba8403d5 100644
--- a/spec/javascripts/vue_shared/components/changed_file_icon_spec.js
+++ b/spec/javascripts/vue_shared/components/changed_file_icon_spec.js
@@ -5,27 +5,40 @@ import createComponent from 'spec/helpers/vue_mount_component_helper';
describe('Changed file icon', () => {
let vm;
- beforeEach(() => {
+ function factory(props = {}) {
const component = Vue.extend(changedFileIcon);
vm = createComponent(component, {
+ ...props,
file: {
tempFile: false,
changed: true,
},
});
- });
+ }
afterEach(() => {
vm.$destroy();
});
+ it('centers icon', () => {
+ factory({
+ isCentered: true,
+ });
+
+ expect(vm.$el.classList).toContain('ml-auto');
+ });
+
describe('changedIcon', () => {
it('equals file-modified when not a temp file and has changes', () => {
+ factory();
+
expect(vm.changedIcon).toBe('file-modified');
});
it('equals file-addition when a temp file', () => {
+ factory();
+
vm.file.tempFile = true;
expect(vm.changedIcon).toBe('file-addition');
@@ -34,10 +47,14 @@ describe('Changed file icon', () => {
describe('changedIconClass', () => {
it('includes file-modified when not a temp file', () => {
+ factory();
+
expect(vm.changedIconClass).toContain('file-modified');
});
it('includes file-addition when a temp file', () => {
+ factory();
+
vm.file.tempFile = true;
expect(vm.changedIconClass).toContain('file-addition');
diff --git a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js b/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
index 6add6cdac4d..660eaddf01f 100644
--- a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
@@ -22,6 +22,7 @@ describe('DiffViewer', () => {
createComponent({
diffMode: 'replaced',
+ diffViewerMode: 'image',
newPath: GREEN_BOX_IMAGE_URL,
newSha: 'ABC',
oldPath: RED_BOX_IMAGE_URL,
@@ -45,6 +46,7 @@ describe('DiffViewer', () => {
it('renders fallback download diff display', done => {
createComponent({
diffMode: 'replaced',
+ diffViewerMode: 'added',
newPath: 'test.abc',
newSha: 'ABC',
oldPath: 'testold.abc',
@@ -72,6 +74,7 @@ describe('DiffViewer', () => {
it('renders renamed component', () => {
createComponent({
diffMode: 'renamed',
+ diffViewerMode: 'renamed',
newPath: 'test.abc',
newSha: 'ABC',
oldPath: 'testold.abc',
@@ -84,6 +87,7 @@ describe('DiffViewer', () => {
it('renders mode changed component', () => {
createComponent({
diffMode: 'mode_changed',
+ diffViewerMode: 'image',
newPath: 'test.abc',
newSha: 'ABC',
oldPath: 'testold.abc',
diff --git a/spec/javascripts/vue_shared/components/file_finder/index_spec.js b/spec/javascripts/vue_shared/components/file_finder/index_spec.js
new file mode 100644
index 00000000000..bae4741f652
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/file_finder/index_spec.js
@@ -0,0 +1,368 @@
+import Vue from 'vue';
+import Mousetrap from 'mousetrap';
+import FindFileComponent from '~/vue_shared/components/file_finder/index.vue';
+import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
+import { file } from 'spec/ide/helpers';
+import timeoutPromise from 'spec/helpers/set_timeout_promise_helper';
+
+describe('File finder item spec', () => {
+ const Component = Vue.extend(FindFileComponent);
+ let vm;
+
+ function createComponent(props) {
+ vm = new Component({
+ propsData: {
+ files: [],
+ visible: true,
+ loading: false,
+ ...props,
+ },
+ });
+
+ vm.$mount('#app');
+ }
+
+ beforeEach(() => {
+ setFixtures('<div id="app"></div>');
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('with entries', () => {
+ beforeEach(done => {
+ createComponent({
+ files: [
+ {
+ ...file('index.js'),
+ path: 'index.js',
+ type: 'blob',
+ url: '/index.jsurl',
+ },
+ {
+ ...file('component.js'),
+ path: 'component.js',
+ type: 'blob',
+ },
+ ],
+ });
+
+ setTimeout(done);
+ });
+
+ it('renders list of blobs', () => {
+ expect(vm.$el.textContent).toContain('index.js');
+ expect(vm.$el.textContent).toContain('component.js');
+ expect(vm.$el.textContent).not.toContain('folder');
+ });
+
+ it('filters entries', done => {
+ vm.searchText = 'index';
+
+ setTimeout(() => {
+ expect(vm.$el.textContent).toContain('index.js');
+ expect(vm.$el.textContent).not.toContain('component.js');
+
+ done();
+ });
+ });
+
+ it('shows clear button when searchText is not empty', done => {
+ vm.searchText = 'index';
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.dropdown-input').classList).toContain('has-value');
+ expect(vm.$el.querySelector('.dropdown-input-search').classList).toContain('hidden');
+
+ done();
+ });
+ });
+
+ it('clear button resets searchText', done => {
+ vm.searchText = 'index';
+
+ timeoutPromise()
+ .then(() => {
+ vm.$el.querySelector('.dropdown-input-clear').click();
+ })
+ .then(timeoutPromise)
+ .then(() => {
+ expect(vm.searchText).toBe('');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('clear button focues search input', done => {
+ spyOn(vm.$refs.searchInput, 'focus');
+ vm.searchText = 'index';
+
+ timeoutPromise()
+ .then(() => {
+ vm.$el.querySelector('.dropdown-input-clear').click();
+ })
+ .then(timeoutPromise)
+ .then(() => {
+ expect(vm.$refs.searchInput.focus).toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ describe('listShowCount', () => {
+ it('returns 1 when no filtered entries exist', done => {
+ vm.searchText = 'testing 123';
+
+ setTimeout(() => {
+ expect(vm.listShowCount).toBe(1);
+
+ done();
+ });
+ });
+
+ it('returns entries length when not filtered', () => {
+ expect(vm.listShowCount).toBe(2);
+ });
+ });
+
+ describe('listHeight', () => {
+ it('returns 55 when entries exist', () => {
+ expect(vm.listHeight).toBe(55);
+ });
+
+ it('returns 33 when entries dont exist', done => {
+ vm.searchText = 'testing 123';
+
+ setTimeout(() => {
+ expect(vm.listHeight).toBe(33);
+
+ done();
+ });
+ });
+ });
+
+ describe('filteredBlobsLength', () => {
+ it('returns length of filtered blobs', done => {
+ vm.searchText = 'index';
+
+ setTimeout(() => {
+ expect(vm.filteredBlobsLength).toBe(1);
+
+ done();
+ });
+ });
+ });
+
+ describe('watches', () => {
+ describe('searchText', () => {
+ it('resets focusedIndex when updated', done => {
+ vm.focusedIndex = 1;
+ vm.searchText = 'test';
+
+ setTimeout(() => {
+ expect(vm.focusedIndex).toBe(0);
+
+ done();
+ });
+ });
+ });
+
+ describe('visible', () => {
+ it('returns searchText when false', done => {
+ vm.searchText = 'test';
+ vm.visible = true;
+
+ timeoutPromise()
+ .then(() => {
+ vm.visible = false;
+ })
+ .then(timeoutPromise)
+ .then(() => {
+ expect(vm.searchText).toBe('');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+ });
+
+ describe('openFile', () => {
+ beforeEach(() => {
+ spyOn(vm, '$emit');
+ });
+
+ it('closes file finder', () => {
+ vm.openFile(vm.files[0]);
+
+ expect(vm.$emit).toHaveBeenCalledWith('toggle', false);
+ });
+
+ it('pushes to router', () => {
+ vm.openFile(vm.files[0]);
+
+ expect(vm.$emit).toHaveBeenCalledWith('click', vm.files[0]);
+ });
+ });
+
+ describe('onKeyup', () => {
+ it('opens file on enter key', done => {
+ const event = new CustomEvent('keyup');
+ event.keyCode = ENTER_KEY_CODE;
+
+ spyOn(vm, 'openFile');
+
+ vm.$refs.searchInput.dispatchEvent(event);
+
+ setTimeout(() => {
+ expect(vm.openFile).toHaveBeenCalledWith(vm.files[0]);
+
+ done();
+ });
+ });
+
+ it('closes file finder on esc key', done => {
+ const event = new CustomEvent('keyup');
+ event.keyCode = ESC_KEY_CODE;
+
+ spyOn(vm, '$emit');
+
+ vm.$refs.searchInput.dispatchEvent(event);
+
+ setTimeout(() => {
+ expect(vm.$emit).toHaveBeenCalledWith('toggle', false);
+
+ done();
+ });
+ });
+ });
+
+ describe('onKeyDown', () => {
+ let el;
+
+ beforeEach(() => {
+ el = vm.$refs.searchInput;
+ });
+
+ describe('up key', () => {
+ const event = new CustomEvent('keydown');
+ event.keyCode = UP_KEY_CODE;
+
+ it('resets to last index when at top', () => {
+ el.dispatchEvent(event);
+
+ expect(vm.focusedIndex).toBe(1);
+ });
+
+ it('minus 1 from focusedIndex', () => {
+ vm.focusedIndex = 1;
+
+ el.dispatchEvent(event);
+
+ expect(vm.focusedIndex).toBe(0);
+ });
+ });
+
+ describe('down key', () => {
+ const event = new CustomEvent('keydown');
+ event.keyCode = DOWN_KEY_CODE;
+
+ it('resets to first index when at bottom', () => {
+ vm.focusedIndex = 1;
+ el.dispatchEvent(event);
+
+ expect(vm.focusedIndex).toBe(0);
+ });
+
+ it('adds 1 to focusedIndex', () => {
+ el.dispatchEvent(event);
+
+ expect(vm.focusedIndex).toBe(1);
+ });
+ });
+ });
+ });
+
+ describe('without entries', () => {
+ it('renders loading text when loading', () => {
+ createComponent({
+ loading: true,
+ });
+
+ expect(vm.$el.textContent).toContain('Loading...');
+ });
+
+ it('renders no files text', () => {
+ createComponent();
+
+ expect(vm.$el.textContent).toContain('No files found.');
+ });
+ });
+
+ describe('keyboard shortcuts', () => {
+ beforeEach(done => {
+ createComponent();
+
+ spyOn(vm, 'toggle');
+
+ vm.$nextTick(done);
+ });
+
+ it('calls toggle on `t` key press', done => {
+ Mousetrap.trigger('t');
+
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.toggle).toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('calls toggle on `command+p` key press', done => {
+ Mousetrap.trigger('command+p');
+
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.toggle).toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('calls toggle on `ctrl+p` key press', done => {
+ Mousetrap.trigger('ctrl+p');
+
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.toggle).toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('always allows `command+p` to trigger toggle', () => {
+ expect(
+ vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 'command+p'),
+ ).toBe(false);
+ });
+
+ it('always allows `ctrl+p` to trigger toggle', () => {
+ expect(
+ vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 'ctrl+p'),
+ ).toBe(false);
+ });
+
+ it('onlys handles `t` when focused in input-field', () => {
+ expect(
+ vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 't'),
+ ).toBe(true);
+ });
+
+ it('stops callback in monaco editor', () => {
+ setFixtures('<div class="inputarea"></div>');
+
+ expect(vm.mousetrapStopCallback(null, document.querySelector('.inputarea'), 't')).toBe(true);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/file_finder/item_spec.js b/spec/javascripts/vue_shared/components/file_finder/item_spec.js
new file mode 100644
index 00000000000..c1511643a9d
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/file_finder/item_spec.js
@@ -0,0 +1,140 @@
+import Vue from 'vue';
+import ItemComponent from '~/vue_shared/components/file_finder/item.vue';
+import { file } from 'spec/ide/helpers';
+import createComponent from '../../../helpers/vue_mount_component_helper';
+
+describe('File finder item spec', () => {
+ const Component = Vue.extend(ItemComponent);
+ let vm;
+ let localFile;
+
+ beforeEach(() => {
+ localFile = {
+ ...file(),
+ name: 'test file',
+ path: 'test/file',
+ };
+
+ vm = createComponent(Component, {
+ file: localFile,
+ focused: true,
+ searchText: '',
+ index: 0,
+ });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders file name & path', () => {
+ expect(vm.$el.textContent).toContain('test file');
+ expect(vm.$el.textContent).toContain('test/file');
+ });
+
+ describe('focused', () => {
+ it('adds is-focused class', () => {
+ expect(vm.$el.classList).toContain('is-focused');
+ });
+
+ it('does not have is-focused class when not focused', done => {
+ vm.focused = false;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.classList).not.toContain('is-focused');
+
+ done();
+ });
+ });
+ });
+
+ describe('changed file icon', () => {
+ it('does not render when not a changed or temp file', () => {
+ expect(vm.$el.querySelector('.diff-changed-stats')).toBe(null);
+ });
+
+ it('renders when a changed file', done => {
+ vm.file.changed = true;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
+
+ done();
+ });
+ });
+
+ it('renders when a temp file', done => {
+ vm.file.tempFile = true;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
+
+ done();
+ });
+ });
+ });
+
+ it('emits event when clicked', () => {
+ spyOn(vm, '$emit');
+
+ vm.$el.click();
+
+ expect(vm.$emit).toHaveBeenCalledWith('click', vm.file);
+ });
+
+ describe('path', () => {
+ let el;
+
+ beforeEach(done => {
+ vm.searchText = 'file';
+
+ el = vm.$el.querySelector('.diff-changed-file-path');
+
+ vm.$nextTick(done);
+ });
+
+ it('highlights text', () => {
+ expect(el.querySelectorAll('.highlighted').length).toBe(4);
+ });
+
+ it('adds ellipsis to long text', done => {
+ vm.file.path = new Array(70)
+ .fill()
+ .map((_, i) => `${i}-`)
+ .join('');
+
+ vm.$nextTick(() => {
+ expect(el.textContent).toBe(`...${vm.file.path.substr(vm.file.path.length - 60)}`);
+ done();
+ });
+ });
+ });
+
+ describe('name', () => {
+ let el;
+
+ beforeEach(done => {
+ vm.searchText = 'file';
+
+ el = vm.$el.querySelector('.diff-changed-file-name');
+
+ vm.$nextTick(done);
+ });
+
+ it('highlights text', () => {
+ expect(el.querySelectorAll('.highlighted').length).toBe(4);
+ });
+
+ it('does not add ellipsis to long text', done => {
+ vm.file.name = new Array(70)
+ .fill()
+ .map((_, i) => `${i}-`)
+ .join('');
+
+ vm.$nextTick(() => {
+ expect(el.textContent).not.toBe(`...${vm.file.name.substr(vm.file.name.length - 60)}`);
+ done();
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/file_row_spec.js b/spec/javascripts/vue_shared/components/file_row_spec.js
index 67752c1c455..d1fd899c1a8 100644
--- a/spec/javascripts/vue_shared/components/file_row_spec.js
+++ b/spec/javascripts/vue_shared/components/file_row_spec.js
@@ -3,7 +3,7 @@ import FileRow from '~/vue_shared/components/file_row.vue';
import { file } from 'spec/ide/helpers';
import mountComponent from '../../helpers/vue_mount_component_helper';
-describe('RepoFile', () => {
+describe('File row component', () => {
let vm;
function createComponent(propsData) {
@@ -72,39 +72,16 @@ describe('RepoFile', () => {
expect(vm.$el.querySelector('.file-row-name').style.marginLeft).toBe('32px');
});
- describe('outputText', () => {
- beforeEach(done => {
- createComponent({
- file: {
- ...file(),
- path: 'app/assets/index.js',
- },
- level: 0,
- });
-
- vm.displayTextKey = 'path';
-
- vm.$nextTick(done);
- });
-
- it('returns text if truncateStart is 0', done => {
- vm.truncateStart = 0;
-
- vm.$nextTick(() => {
- expect(vm.outputText).toBe('app/assets/index.js');
-
- done();
- });
+ it('renders header for file', () => {
+ createComponent({
+ file: {
+ isHeader: true,
+ path: 'app/assets',
+ tree: [],
+ },
+ level: 0,
});
- it('returns text truncated at start', done => {
- vm.truncateStart = 5;
-
- vm.$nextTick(() => {
- expect(vm.outputText).toBe('...ssets/index.js');
-
- done();
- });
- });
+ expect(vm.$el.querySelector('.js-file-row-header')).not.toBe(null);
});
});
diff --git a/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js b/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
index b84b5ae67a8..3d251426b5a 100644
--- a/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
+++ b/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
@@ -88,4 +88,103 @@ describe('Filtered search dropdown', () => {
});
});
});
+
+ describe('with create mode enabled', () => {
+ describe('when there are no matches', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ items: [
+ { title: 'One' },
+ { title: 'Two/three' },
+ { title: 'Three four' },
+ { title: 'Five' },
+ ],
+ filterKey: 'title',
+ showCreateMode: true,
+ });
+
+ vm.$el.querySelector('.js-filtered-dropdown-input').value = 'eleven';
+ vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
+ });
+
+ it('renders a create button', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.js-dropdown-create-button')).not.toBeNull();
+ done();
+ });
+ });
+
+ it('renders computed button text', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.js-dropdown-create-button').textContent.trim()).toEqual(
+ 'Create eleven',
+ );
+ done();
+ });
+ });
+
+ describe('on click create button', () => {
+ it('emits createItem event with the filter', done => {
+ spyOn(vm, '$emit');
+ vm.$nextTick(() => {
+ vm.$el.querySelector('.js-dropdown-create-button').click();
+
+ expect(vm.$emit).toHaveBeenCalledWith('createItem', 'eleven');
+ done();
+ });
+ });
+ });
+ });
+
+ describe('when there are matches', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ items: [
+ { title: 'One' },
+ { title: 'Two/three' },
+ { title: 'Three four' },
+ { title: 'Five' },
+ ],
+ filterKey: 'title',
+ showCreateMode: true,
+ });
+
+ vm.$el.querySelector('.js-filtered-dropdown-input').value = 'one';
+ vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
+ });
+
+ it('does not render a create button', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.js-dropdown-create-button')).toBeNull();
+ done();
+ });
+ });
+ });
+ });
+
+ describe('with create mode disabled', () => {
+ describe('when there are no matches', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ items: [
+ { title: 'One' },
+ { title: 'Two/three' },
+ { title: 'Three four' },
+ { title: 'Five' },
+ ],
+ filterKey: 'title',
+ });
+
+ vm.$el.querySelector('.js-filtered-dropdown-input').value = 'eleven';
+ vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
+ });
+
+ it('does not render a create button', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.js-dropdown-create-button')).toBeNull();
+ done();
+ });
+ });
+ });
+ });
});
diff --git a/spec/javascripts/vue_shared/components/gl_modal_vuex_spec.js b/spec/javascripts/vue_shared/components/gl_modal_vuex_spec.js
new file mode 100644
index 00000000000..eb78d37db3e
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/gl_modal_vuex_spec.js
@@ -0,0 +1,151 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { GlModal } from '@gitlab/ui';
+import GlModalVuex from '~/vue_shared/components/gl_modal_vuex.vue';
+import createState from '~/vuex_shared/modules/modal/state';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+const TEST_SLOT = 'Lorem ipsum modal dolar sit.';
+const TEST_MODAL_ID = 'my-modal-id';
+const TEST_MODULE = 'myModal';
+
+describe('GlModalVuex', () => {
+ let wrapper;
+ let state;
+ let actions;
+
+ const factory = (options = {}) => {
+ const store = new Vuex.Store({
+ modules: {
+ [TEST_MODULE]: {
+ namespaced: true,
+ state,
+ actions,
+ },
+ },
+ });
+
+ const propsData = {
+ modalId: TEST_MODAL_ID,
+ modalModule: TEST_MODULE,
+ ...options.propsData,
+ };
+
+ wrapper = shallowMount(localVue.extend(GlModalVuex), {
+ ...options,
+ localVue,
+ store,
+ propsData,
+ });
+ };
+
+ beforeEach(() => {
+ state = createState();
+
+ actions = {
+ show: jasmine.createSpy('show'),
+ hide: jasmine.createSpy('hide'),
+ };
+ });
+
+ it('renders gl-modal', () => {
+ factory({
+ slots: {
+ default: `<div>${TEST_SLOT}</div>`,
+ },
+ });
+ const glModal = wrapper.find(GlModal);
+
+ expect(glModal.props('modalId')).toBe(TEST_MODAL_ID);
+ expect(glModal.text()).toContain(TEST_SLOT);
+ });
+
+ it('passes props through to gl-modal', () => {
+ const title = 'Test Title';
+ const okVariant = 'success';
+
+ factory({
+ propsData: {
+ title,
+ okTitle: title,
+ okVariant,
+ },
+ });
+ const glModal = wrapper.find(GlModal);
+
+ expect(glModal.attributes('title')).toEqual(title);
+ expect(glModal.attributes('oktitle')).toEqual(title);
+ expect(glModal.attributes('okvariant')).toEqual(okVariant);
+ });
+
+ it('passes listeners through to gl-modal', () => {
+ const ok = jasmine.createSpy('ok');
+
+ factory({
+ listeners: { ok },
+ });
+
+ const glModal = wrapper.find(GlModal);
+ glModal.vm.$emit('ok');
+
+ expect(ok).toHaveBeenCalledTimes(1);
+ });
+
+ it('calls vuex action on show', () => {
+ expect(actions.show).not.toHaveBeenCalled();
+
+ factory();
+
+ const glModal = wrapper.find(GlModal);
+ glModal.vm.$emit('shown');
+
+ expect(actions.show).toHaveBeenCalledTimes(1);
+ });
+
+ it('calls vuex action on hide', () => {
+ expect(actions.hide).not.toHaveBeenCalled();
+
+ factory();
+
+ const glModal = wrapper.find(GlModal);
+ glModal.vm.$emit('hidden');
+
+ expect(actions.hide).toHaveBeenCalledTimes(1);
+ });
+
+ it('calls bootstrap show when isVisible changes', done => {
+ state.isVisible = false;
+
+ factory();
+ const rootEmit = spyOn(wrapper.vm.$root, '$emit');
+
+ state.isVisible = true;
+
+ localVue
+ .nextTick()
+ .then(() => {
+ expect(rootEmit).toHaveBeenCalledWith('bv::show::modal', TEST_MODAL_ID);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('calls bootstrap hide when isVisible changes', done => {
+ state.isVisible = true;
+
+ factory();
+ const rootEmit = spyOn(wrapper.vm.$root, '$emit');
+
+ state.isVisible = false;
+
+ localVue
+ .nextTick()
+ .then(() => {
+ expect(rootEmit).toHaveBeenCalledWith('bv::hide::modal', TEST_MODAL_ID);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js b/spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js
new file mode 100644
index 00000000000..42198e92eea
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js
@@ -0,0 +1,194 @@
+import Vue from 'vue';
+import { mount, createLocalVue } from '@vue/test-utils';
+import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
+import { defaultMilestone, defaultAssignees } from './related_issuable_mock_data';
+
+describe('RelatedIssuableItem', () => {
+ let wrapper;
+ const props = {
+ idKey: 1,
+ displayReference: 'gitlab-org/gitlab-test#1',
+ pathIdSeparator: '#',
+ path: `${gl.TEST_HOST}/path`,
+ title: 'title',
+ confidential: true,
+ dueDate: '1990-12-31',
+ weight: 10,
+ createdAt: '2018-12-01T00:00:00.00Z',
+ milestone: defaultMilestone,
+ assignees: defaultAssignees,
+ eventNamespace: 'relatedIssue',
+ };
+ const slots = {
+ dueDate: '<div class="js-due-date-slot"></div>',
+ weight: '<div class="js-weight-slot"></div>',
+ };
+
+ beforeEach(() => {
+ const localVue = createLocalVue();
+
+ wrapper = mount(localVue.extend(RelatedIssuableItem), {
+ localVue,
+ slots,
+ sync: false,
+ propsData: props,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('contains issuable-info-container class when canReorder is false', () => {
+ expect(wrapper.props('canReorder')).toBe(false);
+ expect(wrapper.find('.issuable-info-container').exists()).toBe(true);
+ });
+
+ it('does not render token state', () => {
+ expect(wrapper.find('.text-secondary svg').exists()).toBe(false);
+ });
+
+ it('does not render remove button', () => {
+ expect(wrapper.find({ ref: 'removeButton' }).exists()).toBe(false);
+ });
+
+ describe('token title', () => {
+ it('links to computedPath', () => {
+ expect(wrapper.find('.item-title a').attributes('href')).toEqual(wrapper.props('path'));
+ });
+
+ it('renders confidential icon', () => {
+ expect(wrapper.find('.confidential-icon').exists()).toBe(true);
+ });
+
+ it('renders title', () => {
+ expect(wrapper.find('.item-title a').text()).toEqual(props.title);
+ });
+ });
+
+ describe('token state', () => {
+ let tokenState;
+
+ beforeEach(done => {
+ wrapper.setProps({ state: 'opened' });
+
+ Vue.nextTick(() => {
+ tokenState = wrapper.find('.issue-token-state-icon-open');
+
+ done();
+ });
+ });
+
+ it('renders if hasState', () => {
+ expect(tokenState.exists()).toBe(true);
+ });
+
+ it('renders state title', () => {
+ const stateTitle = tokenState.attributes('data-original-title');
+
+ expect(stateTitle).toContain('<span class="bold">Opened</span>');
+ expect(stateTitle).toContain(
+ '<span class="text-tertiary">Dec 1, 2018 12:00am GMT+0000</span>',
+ );
+ });
+
+ it('renders aria label', () => {
+ expect(tokenState.attributes('aria-label')).toEqual('opened');
+ });
+
+ it('renders open icon when open state', () => {
+ expect(tokenState.classes('issue-token-state-icon-open')).toBe(true);
+ });
+
+ it('renders close icon when close state', done => {
+ wrapper.setProps({
+ state: 'closed',
+ closedAt: '2018-12-01T00:00:00.00Z',
+ });
+
+ Vue.nextTick(() => {
+ expect(tokenState.classes('issue-token-state-icon-closed')).toBe(true);
+
+ done();
+ });
+ });
+ });
+
+ describe('token metadata', () => {
+ let tokenMetadata;
+
+ beforeEach(done => {
+ Vue.nextTick(() => {
+ tokenMetadata = wrapper.find('.item-meta');
+
+ done();
+ });
+ });
+
+ it('renders item path and ID', () => {
+ const pathAndID = tokenMetadata.find('.item-path-id').text();
+
+ expect(pathAndID).toContain('gitlab-org/gitlab-test');
+ expect(pathAndID).toContain('#1');
+ });
+
+ it('renders milestone icon and name', () => {
+ const milestoneIcon = tokenMetadata.find('.item-milestone svg use');
+ const milestoneTitle = tokenMetadata.find('.item-milestone .milestone-title');
+
+ expect(milestoneIcon.attributes('href')).toContain('clock');
+ expect(milestoneTitle.text()).toContain('Milestone title');
+ });
+
+ it('renders due date component', () => {
+ expect(tokenMetadata.find('.js-due-date-slot').exists()).toBe(true);
+ });
+
+ it('renders weight component', () => {
+ expect(tokenMetadata.find('.js-weight-slot').exists()).toBe(true);
+ });
+ });
+
+ describe('token assignees', () => {
+ it('renders assignees avatars', () => {
+ expect(wrapper.findAll('.item-assignees .user-avatar-link').length).toBe(2);
+ expect(wrapper.find('.item-assignees .avatar-counter').text()).toContain('+2');
+ });
+ });
+
+ describe('remove button', () => {
+ let removeBtn;
+
+ beforeEach(done => {
+ wrapper.setProps({ canRemove: true });
+ Vue.nextTick(() => {
+ removeBtn = wrapper.find({ ref: 'removeButton' });
+
+ done();
+ });
+ });
+
+ it('renders if canRemove', () => {
+ expect(removeBtn.exists()).toBe(true);
+ });
+
+ it('renders disabled button when removeDisabled', done => {
+ wrapper.vm.removeDisabled = true;
+
+ Vue.nextTick(() => {
+ expect(removeBtn.attributes('disabled')).toEqual('disabled');
+
+ done();
+ });
+ });
+
+ it('triggers onRemoveRequest when clicked', () => {
+ removeBtn.trigger('click');
+
+ const { relatedIssueRemoveRequest } = wrapper.emitted();
+
+ expect(relatedIssueRemoveRequest.length).toBe(1);
+ expect(relatedIssueRemoveRequest[0]).toEqual([props.idKey]);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/issue/related_issuable_mock_data.js b/spec/javascripts/vue_shared/components/issue/related_issuable_mock_data.js
new file mode 100644
index 00000000000..26bfdd7551e
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/issue/related_issuable_mock_data.js
@@ -0,0 +1,111 @@
+export const defaultProps = {
+ endpoint: '/foo/bar/issues/1/related_issues',
+ currentNamespacePath: 'foo',
+ currentProjectPath: 'bar',
+};
+
+export const issuable1 = {
+ id: 200,
+ epic_issue_id: 1,
+ confidential: false,
+ reference: 'foo/bar#123',
+ displayReference: '#123',
+ title: 'some title',
+ path: '/foo/bar/issues/123',
+ state: 'opened',
+};
+
+export const issuable2 = {
+ id: 201,
+ epic_issue_id: 2,
+ confidential: false,
+ reference: 'foo/bar#124',
+ displayReference: '#124',
+ title: 'some other thing',
+ path: '/foo/bar/issues/124',
+ state: 'opened',
+};
+
+export const issuable3 = {
+ id: 202,
+ epic_issue_id: 3,
+ confidential: false,
+ reference: 'foo/bar#125',
+ displayReference: '#125',
+ title: 'some other other thing',
+ path: '/foo/bar/issues/125',
+ state: 'opened',
+};
+
+export const issuable4 = {
+ id: 203,
+ epic_issue_id: 4,
+ confidential: false,
+ reference: 'foo/bar#126',
+ displayReference: '#126',
+ title: 'some other other other thing',
+ path: '/foo/bar/issues/126',
+ state: 'opened',
+};
+
+export const issuable5 = {
+ id: 204,
+ epic_issue_id: 5,
+ confidential: false,
+ reference: 'foo/bar#127',
+ displayReference: '#127',
+ title: 'some other other other thing',
+ path: '/foo/bar/issues/127',
+ state: 'opened',
+};
+
+export const defaultMilestone = {
+ id: 1,
+ state: 'active',
+ title: 'Milestone title',
+ start_date: '2018-01-01',
+ due_date: '2019-12-31',
+};
+
+export const defaultAssignees = [
+ {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: `${gl.TEST_HOST}`,
+ web_url: `${gl.TEST_HOST}/root`,
+ status_tooltip_html: null,
+ path: '/root',
+ },
+ {
+ id: 13,
+ name: 'Brooks Beatty',
+ username: 'brynn_champlin',
+ state: 'active',
+ avatar_url: `${gl.TEST_HOST}`,
+ web_url: `${gl.TEST_HOST}/brynn_champlin`,
+ status_tooltip_html: null,
+ path: '/brynn_champlin',
+ },
+ {
+ id: 6,
+ name: 'Bryce Turcotte',
+ username: 'melynda',
+ state: 'active',
+ avatar_url: `${gl.TEST_HOST}`,
+ web_url: `${gl.TEST_HOST}/melynda`,
+ status_tooltip_html: null,
+ path: '/melynda',
+ },
+ {
+ id: 20,
+ name: 'Conchita Eichmann',
+ username: 'juliana_gulgowski',
+ state: 'active',
+ avatar_url: `${gl.TEST_HOST}`,
+ web_url: `${gl.TEST_HOST}/juliana_gulgowski`,
+ status_tooltip_html: null,
+ path: '/juliana_gulgowski',
+ },
+];
diff --git a/spec/javascripts/vue_shared/components/markdown/suggestion_diff_header_spec.js b/spec/javascripts/vue_shared/components/markdown/suggestion_diff_header_spec.js
index 8187b3204b1..12ee804f668 100644
--- a/spec/javascripts/vue_shared/components/markdown/suggestion_diff_header_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/suggestion_diff_header_spec.js
@@ -31,6 +31,12 @@ describe('Suggestion Diff component', () => {
expect(header.innerHTML.includes('Suggested change')).toBe(true);
});
+ it('renders a help button', () => {
+ const helpBtn = vm.$el.querySelector('.js-help-btn');
+
+ expect(helpBtn).not.toBeNull();
+ });
+
it('renders an apply button', () => {
const applyBtn = vm.$el.querySelector('.qa-apply-btn');
diff --git a/spec/javascripts/vue_shared/components/markdown/suggestion_diff_spec.js b/spec/javascripts/vue_shared/components/markdown/suggestion_diff_spec.js
index d4ed8f2f7a4..f87c2a92f47 100644
--- a/spec/javascripts/vue_shared/components/markdown/suggestion_diff_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/suggestion_diff_spec.js
@@ -34,8 +34,8 @@ describe('Suggestion Diff component', () => {
expect(vm.$el.querySelector('.qa-suggestion-diff-header')).not.toBeNull();
});
- it('renders a diff table', () => {
- expect(vm.$el.querySelector('table.md-suggestion-diff')).not.toBeNull();
+ it('renders a diff table with syntax highlighting', () => {
+ expect(vm.$el.querySelector('.md-suggestion-diff.js-syntax-highlight.code')).not.toBeNull();
});
it('renders the oldLineNumber', () => {
diff --git a/spec/javascripts/vue_shared/components/markdown/suggestions_spec.js b/spec/javascripts/vue_shared/components/markdown/suggestions_spec.js
index ab1b747c360..33be63a3a1e 100644
--- a/spec/javascripts/vue_shared/components/markdown/suggestions_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/suggestions_spec.js
@@ -29,7 +29,7 @@ const generateLine = content => {
const generateMockLines = () => {
const line1 = generateLine('Line 1');
const line2 = generateLine('Line 2');
- const line3 = generateLine('Line 3');
+ const line3 = generateLine('- Line 3');
const container = document.createElement('div');
container.appendChild(line1);
@@ -61,7 +61,7 @@ describe('Suggestion component', () => {
describe('mounted', () => {
it('renders a flash container', () => {
- expect(vm.$el.querySelector('.flash-container')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-suggestions-flash')).not.toBeNull();
});
it('renders a container for suggestions', () => {
@@ -80,7 +80,7 @@ describe('Suggestion component', () => {
const expectedReturn = [
{ content: 'Line 1\n', lineNumber: 1 },
{ content: 'Line 2\n', lineNumber: 2 },
- { content: 'Line 3\n', lineNumber: 3 },
+ { content: '- Line 3\n', lineNumber: 3 },
];
expect(vm.extractNewLines(generateMockLines())).toEqual(expectedReturn);
diff --git a/spec/javascripts/vue_shared/components/panel_resizer_spec.js b/spec/javascripts/vue_shared/components/panel_resizer_spec.js
index 49a580be06b..caabe3aa260 100644
--- a/spec/javascripts/vue_shared/components/panel_resizer_spec.js
+++ b/spec/javascripts/vue_shared/components/panel_resizer_spec.js
@@ -44,7 +44,10 @@ describe('Panel Resizer component', () => {
});
expect(vm.$el.tagName).toEqual('DIV');
- expect(vm.$el.getAttribute('class')).toBe('drag-handle drag-left');
+ expect(vm.$el.getAttribute('class')).toBe(
+ 'position-absolute position-top-0 position-bottom-0 drag-handle position-left-0',
+ );
+
expect(vm.$el.getAttribute('style')).toBe('cursor: ew-resize;');
});
@@ -55,7 +58,9 @@ describe('Panel Resizer component', () => {
});
expect(vm.$el.tagName).toEqual('DIV');
- expect(vm.$el.getAttribute('class')).toBe('drag-handle drag-right');
+ expect(vm.$el.getAttribute('class')).toBe(
+ 'position-absolute position-top-0 position-bottom-0 drag-handle position-right-0',
+ );
});
it('drag the resizer', () => {
diff --git a/spec/javascripts/vue_shared/components/table_pagination_spec.js b/spec/javascripts/vue_shared/components/table_pagination_spec.js
index 0dcb712e720..42cd41381dc 100644
--- a/spec/javascripts/vue_shared/components/table_pagination_spec.js
+++ b/spec/javascripts/vue_shared/components/table_pagination_spec.js
@@ -22,10 +22,10 @@ describe('Pagination component', () => {
it('should not render anything', () => {
component = mountComponent({
pageInfo: {
- nextPage: 1,
+ nextPage: NaN,
page: 1,
perPage: 20,
- previousPage: null,
+ previousPage: NaN,
total: 15,
totalPages: 1,
},
@@ -53,7 +53,29 @@ describe('Pagination component', () => {
component.$el.querySelector('.js-previous-button').classList.contains('disabled'),
).toEqual(true);
- component.$el.querySelector('.js-previous-button a').click();
+ component.$el.querySelector('.js-previous-button .page-link').click();
+
+ expect(spy).not.toHaveBeenCalled();
+ });
+
+ it('should be disabled and non clickable when total and totalPages are NaN', () => {
+ component = mountComponent({
+ pageInfo: {
+ nextPage: 2,
+ page: 1,
+ perPage: 20,
+ previousPage: NaN,
+ total: NaN,
+ totalPages: NaN,
+ },
+ change: spy,
+ });
+
+ expect(
+ component.$el.querySelector('.js-previous-button').classList.contains('disabled'),
+ ).toEqual(true);
+
+ component.$el.querySelector('.js-previous-button .page-link').click();
expect(spy).not.toHaveBeenCalled();
});
@@ -71,7 +93,25 @@ describe('Pagination component', () => {
change: spy,
});
- component.$el.querySelector('.js-previous-button a').click();
+ component.$el.querySelector('.js-previous-button .page-link').click();
+
+ expect(spy).toHaveBeenCalledWith(1);
+ });
+
+ it('should be enabled and clickable when total and totalPages are NaN', () => {
+ component = mountComponent({
+ pageInfo: {
+ nextPage: 3,
+ page: 2,
+ perPage: 20,
+ previousPage: 1,
+ total: NaN,
+ totalPages: NaN,
+ },
+ change: spy,
+ });
+
+ component.$el.querySelector('.js-previous-button .page-link').click();
expect(spy).toHaveBeenCalledWith(1);
});
@@ -91,7 +131,29 @@ describe('Pagination component', () => {
change: spy,
});
- const button = component.$el.querySelector('.js-first-button a');
+ const button = component.$el.querySelector('.js-first-button .page-link');
+
+ expect(button.textContent.trim()).toEqual('« First');
+
+ button.click();
+
+ expect(spy).toHaveBeenCalledWith(1);
+ });
+
+ it('should call the change callback with the first page when total and totalPages are NaN', () => {
+ component = mountComponent({
+ pageInfo: {
+ nextPage: 3,
+ page: 2,
+ perPage: 20,
+ previousPage: 1,
+ total: NaN,
+ totalPages: NaN,
+ },
+ change: spy,
+ });
+
+ const button = component.$el.querySelector('.js-first-button .page-link');
expect(button.textContent.trim()).toEqual('« First');
@@ -115,7 +177,7 @@ describe('Pagination component', () => {
change: spy,
});
- const button = component.$el.querySelector('.js-last-button a');
+ const button = component.$el.querySelector('.js-last-button .page-link');
expect(button.textContent.trim()).toEqual('Last »');
@@ -123,16 +185,32 @@ describe('Pagination component', () => {
expect(spy).toHaveBeenCalledWith(5);
});
+
+ it('should not render', () => {
+ component = mountComponent({
+ pageInfo: {
+ nextPage: 3,
+ page: 2,
+ perPage: 20,
+ previousPage: 1,
+ total: NaN,
+ totalPages: NaN,
+ },
+ change: spy,
+ });
+
+ expect(component.$el.querySelector('.js-last-button .page-link')).toBeNull();
+ });
});
describe('next button', () => {
it('should be disabled and non clickable', () => {
component = mountComponent({
pageInfo: {
- nextPage: 5,
+ nextPage: NaN,
page: 5,
perPage: 20,
- previousPage: 1,
+ previousPage: 4,
total: 84,
totalPages: 5,
},
@@ -141,7 +219,27 @@ describe('Pagination component', () => {
expect(component.$el.querySelector('.js-next-button').textContent.trim()).toEqual('Next');
- component.$el.querySelector('.js-next-button a').click();
+ component.$el.querySelector('.js-next-button .page-link').click();
+
+ expect(spy).not.toHaveBeenCalled();
+ });
+
+ it('should be disabled and non clickable when total and totalPages are NaN', () => {
+ component = mountComponent({
+ pageInfo: {
+ nextPage: NaN,
+ page: 5,
+ perPage: 20,
+ previousPage: 4,
+ total: NaN,
+ totalPages: NaN,
+ },
+ change: spy,
+ });
+
+ expect(component.$el.querySelector('.js-next-button').textContent.trim()).toEqual('Next');
+
+ component.$el.querySelector('.js-next-button .page-link').click();
expect(spy).not.toHaveBeenCalled();
});
@@ -159,7 +257,25 @@ describe('Pagination component', () => {
change: spy,
});
- component.$el.querySelector('.js-next-button a').click();
+ component.$el.querySelector('.js-next-button .page-link').click();
+
+ expect(spy).toHaveBeenCalledWith(4);
+ });
+
+ it('should be enabled and clickable when total and totalPages are NaN', () => {
+ component = mountComponent({
+ pageInfo: {
+ nextPage: 4,
+ page: 3,
+ perPage: 20,
+ previousPage: 2,
+ total: NaN,
+ totalPages: NaN,
+ },
+ change: spy,
+ });
+
+ component.$el.querySelector('.js-next-button .page-link').click();
expect(spy).toHaveBeenCalledWith(4);
});
@@ -181,22 +297,56 @@ describe('Pagination component', () => {
expect(component.$el.querySelectorAll('.page').length).toEqual(5);
});
+
+ it('should not render any page', () => {
+ component = mountComponent({
+ pageInfo: {
+ nextPage: 4,
+ page: 3,
+ perPage: 20,
+ previousPage: 2,
+ total: NaN,
+ totalPages: NaN,
+ },
+ change: spy,
+ });
+
+ expect(component.$el.querySelectorAll('.page').length).toEqual(0);
+ });
});
- it('should render the spread operator', () => {
- component = mountComponent({
- pageInfo: {
- nextPage: 4,
- page: 3,
- perPage: 20,
- previousPage: 2,
- total: 84,
- totalPages: 10,
- },
- change: spy,
+ describe('spread operator', () => {
+ it('should render', () => {
+ component = mountComponent({
+ pageInfo: {
+ nextPage: 4,
+ page: 3,
+ perPage: 20,
+ previousPage: 2,
+ total: 84,
+ totalPages: 10,
+ },
+ change: spy,
+ });
+
+ expect(component.$el.querySelector('.separator').textContent.trim()).toEqual('...');
});
- expect(component.$el.querySelector('.separator').textContent.trim()).toEqual('...');
+ it('should not render', () => {
+ component = mountComponent({
+ pageInfo: {
+ nextPage: 4,
+ page: 3,
+ perPage: 20,
+ previousPage: 2,
+ total: NaN,
+ totalPages: NaN,
+ },
+ change: spy,
+ });
+
+ expect(component.$el.querySelector('.separator')).toBeNull();
+ });
});
});
});
diff --git a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js
index f2472fd377c..80aa75847ae 100644
--- a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js
+++ b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js
@@ -1,13 +1,14 @@
import _ from 'underscore';
import Vue from 'vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import { TEST_HOST } from 'spec/test_constants';
describe('User Avatar Link Component', function() {
beforeEach(function() {
this.propsData = {
- linkHref: 'myavatarurl.com',
+ linkHref: `${TEST_HOST}/myavatarurl.com`,
imgSize: 99,
- imgSrc: 'myavatarurl.com',
+ imgSrc: `${TEST_HOST}/myavatarurl.com`,
imgAlt: 'mydisplayname',
imgCssClasses: 'myextraavatarclass',
tooltipText: 'tooltip text',
@@ -37,11 +38,18 @@ describe('User Avatar Link Component', function() {
});
it('should render <a> as a child element', function() {
- expect(this.userAvatarLink.$el.tagName).toBe('A');
+ const link = this.userAvatarLink.$el;
+
+ expect(link.tagName).toBe('A');
+ expect(link.href).toBe(this.propsData.linkHref);
});
- it('should have <img> as a child element', function() {
- expect(this.userAvatarLink.$el.querySelector('img')).not.toBeNull();
+ it('renders imgSrc with imgSize as image', function() {
+ const { imgSrc, imgSize } = this.propsData;
+ const image = this.userAvatarLink.$el.querySelector('img');
+
+ expect(image).not.toBeNull();
+ expect(image.src).toBe(`${imgSrc}?width=${imgSize}`);
});
it('should return necessary props as defined', function() {
diff --git a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_list_spec.js b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_list_spec.js
new file mode 100644
index 00000000000..96bc3b0cc17
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_list_spec.js
@@ -0,0 +1,156 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
+import { TEST_HOST } from 'spec/test_constants';
+import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+
+const TEST_IMAGE_SIZE = 7;
+const TEST_BREAKPOINT = 5;
+const TEST_EMPTY_MESSAGE = 'Lorem ipsum empty';
+const DEFAULT_EMPTY_MESSAGE = 'None';
+
+const createUser = id => ({
+ id,
+ name: 'Lorem',
+ web_url: `${TEST_HOST}/${id}`,
+ avatar_url: `${TEST_HOST}/${id}/avatar`,
+});
+const createList = n =>
+ Array(n)
+ .fill(1)
+ .map((x, id) => createUser(id));
+
+const localVue = createLocalVue();
+
+describe('UserAvatarList', () => {
+ let props;
+ let wrapper;
+
+ const factory = (options = {}) => {
+ const propsData = {
+ ...props,
+ ...options.propsData,
+ };
+
+ wrapper = shallowMount(localVue.extend(UserAvatarList), {
+ ...options,
+ localVue,
+ propsData,
+ });
+ };
+
+ const clickButton = () => {
+ const button = wrapper.find(GlButton);
+ button.vm.$emit('click');
+ };
+
+ beforeEach(() => {
+ props = { imgSize: TEST_IMAGE_SIZE };
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('empty text', () => {
+ it('shows when items are empty', () => {
+ factory({ propsData: { items: [] } });
+
+ expect(wrapper.text()).toContain(DEFAULT_EMPTY_MESSAGE);
+ });
+
+ it('does not show when items are not empty', () => {
+ factory({ propsData: { items: createList(1) } });
+
+ expect(wrapper.text()).not.toContain(DEFAULT_EMPTY_MESSAGE);
+ });
+
+ it('can be set in props', () => {
+ factory({ propsData: { items: [], emptyText: TEST_EMPTY_MESSAGE } });
+
+ expect(wrapper.text()).toContain(TEST_EMPTY_MESSAGE);
+ });
+ });
+
+ describe('with no breakpoint', () => {
+ beforeEach(() => {
+ props.breakpoint = 0;
+ });
+
+ it('renders avatars', () => {
+ const items = createList(20);
+ factory({ propsData: { items } });
+
+ const links = wrapper.findAll(UserAvatarLink);
+ const linkProps = links.wrappers.map(x => x.props());
+
+ expect(linkProps).toEqual(
+ items.map(x =>
+ jasmine.objectContaining({
+ linkHref: x.web_url,
+ imgSrc: x.avatar_url,
+ imgAlt: x.name,
+ tooltipText: x.name,
+ imgSize: TEST_IMAGE_SIZE,
+ }),
+ ),
+ );
+ });
+ });
+
+ describe('with breakpoint and length equal to breakpoint', () => {
+ beforeEach(() => {
+ props.breakpoint = TEST_BREAKPOINT;
+ props.items = createList(TEST_BREAKPOINT);
+ });
+
+ it('renders all avatars if length is <= breakpoint', () => {
+ factory();
+
+ const links = wrapper.findAll(UserAvatarLink);
+
+ expect(links.length).toEqual(props.items.length);
+ });
+
+ it('does not show button', () => {
+ factory();
+
+ expect(wrapper.find(GlButton).exists()).toBe(false);
+ });
+ });
+
+ describe('with breakpoint and length greater than breakpoint', () => {
+ beforeEach(() => {
+ props.breakpoint = TEST_BREAKPOINT;
+ props.items = createList(TEST_BREAKPOINT + 1);
+ });
+
+ it('renders avatars up to breakpoint', () => {
+ factory();
+
+ const links = wrapper.findAll(UserAvatarLink);
+
+ expect(links.length).toEqual(TEST_BREAKPOINT);
+ });
+
+ describe('with expand clicked', () => {
+ beforeEach(() => {
+ factory();
+ clickButton();
+ });
+
+ it('renders all avatars', () => {
+ const links = wrapper.findAll(UserAvatarLink);
+
+ expect(links.length).toEqual(props.items.length);
+ });
+
+ it('with collapse clicked, it renders avatars up to breakpoint', () => {
+ clickButton();
+ const links = wrapper.findAll(UserAvatarLink);
+
+ expect(links.length).toEqual(TEST_BREAKPOINT);
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js b/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
index 25b6e3b6bc8..e8b41e8eeff 100644
--- a/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
@@ -17,14 +17,13 @@ const DEFAULT_PROPS = {
const UserPopover = Vue.extend(userPopover);
describe('User Popover Component', () => {
+ const fixtureTemplate = 'merge_requests/diff_comment.html.raw';
+ preloadFixtures(fixtureTemplate);
+
let vm;
beforeEach(() => {
- setFixtures(`
- <a href="/root" data-user-id="1" class="js-user-link" title="testuser">
- Root
- </a>
- `);
+ loadFixtures(fixtureTemplate);
});
afterEach(() => {
@@ -123,7 +122,7 @@ describe('User Popover Component', () => {
describe('status data', () => {
it('should show only message', () => {
const testProps = Object.assign({}, DEFAULT_PROPS);
- testProps.user.status = { message: 'Hello World' };
+ testProps.user.status = { message_html: 'Hello World' };
vm = mountComponent(UserPopover, {
...DEFAULT_PROPS,
@@ -135,12 +134,12 @@ describe('User Popover Component', () => {
it('should show message and emoji', () => {
const testProps = Object.assign({}, DEFAULT_PROPS);
- testProps.user.status = { emoji: 'basketball_player', message: 'Hello World' };
+ testProps.user.status = { emoji: 'basketball_player', message_html: 'Hello World' };
vm = mountComponent(UserPopover, {
...DEFAULT_PROPS,
target: document.querySelector('.js-user-link'),
- status: { emoji: 'basketball_player', message: 'Hello World' },
+ status: { emoji: 'basketball_player', message_html: 'Hello World' },
});
expect(vm.$el.textContent).toContain('Hello World');
diff --git a/spec/javascripts/vuex_shared/modules/modal/actions_spec.js b/spec/javascripts/vuex_shared/modules/modal/actions_spec.js
new file mode 100644
index 00000000000..04f64663ae4
--- /dev/null
+++ b/spec/javascripts/vuex_shared/modules/modal/actions_spec.js
@@ -0,0 +1,31 @@
+import * as types from '~/vuex_shared/modules/modal/mutation_types';
+import * as actions from '~/vuex_shared/modules/modal/actions';
+import testAction from 'spec/helpers/vuex_action_helper';
+
+describe('Vuex ModalModule actions', () => {
+ describe('open', () => {
+ it('works', done => {
+ const data = { id: 7 };
+
+ testAction(actions.open, data, {}, [{ type: types.OPEN, payload: data }], [], done);
+ });
+ });
+
+ describe('close', () => {
+ it('works', done => {
+ testAction(actions.close, null, {}, [{ type: types.CLOSE }], [], done);
+ });
+ });
+
+ describe('show', () => {
+ it('works', done => {
+ testAction(actions.show, null, {}, [{ type: types.SHOW }], [], done);
+ });
+ });
+
+ describe('hide', () => {
+ it('works', done => {
+ testAction(actions.hide, null, {}, [{ type: types.HIDE }], [], done);
+ });
+ });
+});
diff --git a/spec/javascripts/vuex_shared/modules/modal/mutations_spec.js b/spec/javascripts/vuex_shared/modules/modal/mutations_spec.js
new file mode 100644
index 00000000000..d07f8ba1e65
--- /dev/null
+++ b/spec/javascripts/vuex_shared/modules/modal/mutations_spec.js
@@ -0,0 +1,49 @@
+import mutations from '~/vuex_shared/modules/modal/mutations';
+import * as types from '~/vuex_shared/modules/modal/mutation_types';
+
+describe('Vuex ModalModule mutations', () => {
+ describe(types.SHOW, () => {
+ it('sets isVisible to true', () => {
+ const state = {
+ isVisible: false,
+ };
+
+ mutations[types.SHOW](state);
+
+ expect(state).toEqual({
+ isVisible: true,
+ });
+ });
+ });
+
+ describe(types.HIDE, () => {
+ it('sets isVisible to false', () => {
+ const state = {
+ isVisible: true,
+ };
+
+ mutations[types.HIDE](state);
+
+ expect(state).toEqual({
+ isVisible: false,
+ });
+ });
+ });
+
+ describe(types.OPEN, () => {
+ it('sets data and sets isVisible to true', () => {
+ const data = { id: 7 };
+ const state = {
+ isVisible: false,
+ data: null,
+ };
+
+ mutations[types.OPEN](state, data);
+
+ expect(state).toEqual({
+ isVisible: true,
+ data,
+ });
+ });
+ });
+});
diff --git a/spec/lib/api/api_spec.rb b/spec/lib/api/api_spec.rb
new file mode 100644
index 00000000000..ceef0b41e59
--- /dev/null
+++ b/spec/lib/api/api_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe API::API do
+ describe '.prefix' do
+ it 'has a prefix defined' do
+ expect(described_class.prefix).to eq :api
+ end
+ end
+
+ describe '.version' do
+ it 'uses most recent version of the API' do
+ expect(described_class.version).to eq 'v4'
+ end
+ end
+
+ describe '.versions' do
+ it 'returns all available versions' do
+ expect(described_class.versions).to eq %w[v3 v4]
+ end
+ end
+end
diff --git a/spec/lib/api/helpers/custom_validators_spec.rb b/spec/lib/api/helpers/custom_validators_spec.rb
index 41e6fb47b11..9945d598a14 100644
--- a/spec/lib/api/helpers/custom_validators_spec.rb
+++ b/spec/lib/api/helpers/custom_validators_spec.rb
@@ -50,6 +50,29 @@ describe API::Helpers::CustomValidators do
end
end
+ describe API::Helpers::CustomValidators::ArrayNoneAny do
+ subject do
+ described_class.new(['test'], {}, false, scope.new)
+ end
+
+ context 'valid parameters' do
+ it 'does not raise a validation error' do
+ expect_no_validation_error({ 'test' => [] })
+ expect_no_validation_error({ 'test' => [1, 2, 3] })
+ expect_no_validation_error({ 'test' => 'None' })
+ expect_no_validation_error({ 'test' => 'Any' })
+ expect_no_validation_error({ 'test' => 'none' })
+ expect_no_validation_error({ 'test' => 'any' })
+ end
+ end
+
+ context 'invalid parameters' do
+ it 'should raise a validation error' do
+ expect_validation_error({ 'test' => 'some_other_string' })
+ end
+ end
+ end
+
def expect_no_validation_error(params)
expect { validate_test_param!(params) }.not_to raise_error
end
diff --git a/spec/lib/api/helpers/pagination_spec.rb b/spec/lib/api/helpers/pagination_spec.rb
index 0a7682d906b..6e215ea1561 100644
--- a/spec/lib/api/helpers/pagination_spec.rb
+++ b/spec/lib/api/helpers/pagination_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
describe API::Helpers::Pagination do
let(:resource) { Project.all }
+ let(:incoming_api_projects_url) { "#{Gitlab.config.gitlab.url}:8080/api/v4/projects" }
+ let(:canonical_api_projects_url) { "#{Gitlab.config.gitlab.url}/api/v4/projects" }
subject do
Class.new.include(described_class).new
@@ -9,13 +11,19 @@ describe API::Helpers::Pagination do
describe '#paginate (keyset pagination)' do
let(:value) { spy('return value') }
+ let(:base_query) do
+ {
+ pagination: 'keyset',
+ foo: 'bar',
+ bar: 'baz'
+ }
+ end
+ let(:query) { base_query }
before do
- allow(value).to receive(:to_query).and_return(value)
-
allow(subject).to receive(:header).and_return(value)
- allow(subject).to receive(:params).and_return(value)
- allow(subject).to receive(:request).and_return(value)
+ allow(subject).to receive(:params).and_return(query)
+ allow(subject).to receive(:request).and_return(double(url: "#{incoming_api_projects_url}?#{query.to_query}"))
end
context 'when resource can be paginated' do
@@ -28,10 +36,7 @@ describe API::Helpers::Pagination do
end
describe 'first page' do
- before do
- allow(subject).to receive(:params)
- .and_return({ pagination: 'keyset', per_page: 2 })
- end
+ let(:query) { base_query.merge(per_page: 2) }
it 'returns appropriate amount of resources' do
expect(subject.paginate(resource).count).to eq 2
@@ -43,7 +48,7 @@ describe API::Helpers::Pagination do
it 'adds appropriate headers' do
expect_header('X-Per-Page', '2')
- expect_header('X-Next-Page', "#{value}?ks_prev_id=#{projects[1].id}&pagination=keyset&per_page=2")
+ expect_header('X-Next-Page', "#{canonical_api_projects_url}?#{query.merge(ks_prev_id: projects[1].id).to_query}")
expect_header('Link', anything) do |_key, val|
expect(val).to include('rel="next"')
@@ -54,10 +59,7 @@ describe API::Helpers::Pagination do
end
describe 'second page' do
- before do
- allow(subject).to receive(:params)
- .and_return({ pagination: 'keyset', per_page: 2, ks_prev_id: projects[1].id })
- end
+ let(:query) { base_query.merge(per_page: 2, ks_prev_id: projects[1].id) }
it 'returns appropriate amount of resources' do
expect(subject.paginate(resource).count).to eq 1
@@ -69,7 +71,7 @@ describe API::Helpers::Pagination do
it 'adds appropriate headers' do
expect_header('X-Per-Page', '2')
- expect_header('X-Next-Page', "#{value}?ks_prev_id=#{projects[2].id}&pagination=keyset&per_page=2")
+ expect_header('X-Next-Page', "#{canonical_api_projects_url}?#{query.merge(ks_prev_id: projects[2].id).to_query}")
expect_header('Link', anything) do |_key, val|
expect(val).to include('rel="next"')
@@ -80,10 +82,7 @@ describe API::Helpers::Pagination do
end
describe 'third page' do
- before do
- allow(subject).to receive(:params)
- .and_return({ pagination: 'keyset', per_page: 2, ks_prev_id: projects[2].id })
- end
+ let(:query) { base_query.merge(per_page: 2, ks_prev_id: projects[2].id) }
it 'returns appropriate amount of resources' do
expect(subject.paginate(resource).count).to eq 0
@@ -91,6 +90,7 @@ describe API::Helpers::Pagination do
it 'adds appropriate headers' do
expect_header('X-Per-Page', '2')
+ expect_no_header('X-Next-Page')
expect(subject).not_to receive(:header).with('Link')
subject.paginate(resource)
@@ -99,10 +99,7 @@ describe API::Helpers::Pagination do
context 'if order' do
context 'is not present' do
- before do
- allow(subject).to receive(:params)
- .and_return({ pagination: 'keyset', per_page: 2 })
- end
+ let(:query) { base_query.merge(per_page: 2) }
it 'is not present it adds default order(:id) desc' do
resource.order_values = []
@@ -144,9 +141,7 @@ describe API::Helpers::Pagination do
# (key is the id)
end
- it 'it also orders by primary key' do
- allow(subject).to receive(:params)
- .and_return({ pagination: 'keyset', per_page: 2 })
+ it 'also orders by primary key' do
paginated_relation = subject.paginate(resource)
expect(paginated_relation.order_values).to be_present
@@ -157,46 +152,45 @@ describe API::Helpers::Pagination do
expect(paginated_relation.order_values.second.expr.name).to eq :id
end
- it 'it returns the right records (first page)' do
- allow(subject).to receive(:params)
- .and_return({ pagination: 'keyset', per_page: 2 })
+ it 'returns the right records (first page)' do
result = subject.paginate(resource)
expect(result.first).to eq(projects[1])
expect(result.second).to eq(projects[3])
end
- it 'it returns the right records (second page)' do
- allow(subject).to receive(:params)
- .and_return({ pagination: 'keyset', ks_prev_id: projects[3].id, ks_prev_name: projects[3].name, per_page: 2 })
- result = subject.paginate(resource)
+ describe 'second page' do
+ let(:query) { base_query.merge(ks_prev_id: projects[3].id, ks_prev_name: projects[3].name, per_page: 2) }
- expect(result.first).to eq(projects[2])
- expect(result.second).to eq(projects[6])
- end
+ it 'returns the right records (second page)' do
+ result = subject.paginate(resource)
- it 'it returns the right records (third page), note increased per_page' do
- allow(subject).to receive(:params)
- .and_return({ pagination: 'keyset', ks_prev_id: projects[6].id, ks_prev_name: projects[6].name, per_page: 5 })
- result = subject.paginate(resource)
+ expect(result.first).to eq(projects[2])
+ expect(result.second).to eq(projects[6])
+ end
+
+ it 'returns the right link to the next page' do
+ expect_header('X-Per-Page', '2')
+ expect_header('X-Next-Page', "#{canonical_api_projects_url}?#{query.merge(ks_prev_id: projects[6].id, ks_prev_name: projects[6].name).to_query}")
+ expect_header('Link', anything) do |_key, val|
+ expect(val).to include('rel="next"')
+ end
- expect(result.size).to eq(3)
- expect(result.first).to eq(projects[0])
- expect(result.second).to eq(projects[4])
- expect(result.last).to eq(projects[5])
+ subject.paginate(resource)
+ end
end
- it 'it returns the right link to the next page' do
- allow(subject).to receive(:params)
- .and_return({ pagination: 'keyset', ks_prev_id: projects[3].id, ks_prev_name: projects[3].name, per_page: 2 })
+ describe 'third page' do
+ let(:query) { base_query.merge(ks_prev_id: projects[6].id, ks_prev_name: projects[6].name, per_page: 5) }
- expect_header('X-Per-Page', '2')
- expect_header('X-Next-Page', "#{value}?ks_prev_id=#{projects[6].id}&ks_prev_name=#{projects[6].name}&pagination=keyset&per_page=2")
- expect_header('Link', anything) do |_key, val|
- expect(val).to include('rel="next"')
- end
+ it 'returns the right records (third page), note increased per_page' do
+ result = subject.paginate(resource)
- subject.paginate(resource)
+ expect(result.size).to eq(3)
+ expect(result.first).to eq(projects[0])
+ expect(result.second).to eq(projects[4])
+ expect(result.last).to eq(projects[5])
+ end
end
end
end
@@ -205,25 +199,13 @@ describe API::Helpers::Pagination do
describe '#paginate (default offset-based pagination)' do
let(:value) { spy('return value') }
+ let(:base_query) { { foo: 'bar', bar: 'baz' } }
+ let(:query) { base_query }
before do
- allow(value).to receive(:to_query).and_return(value)
-
allow(subject).to receive(:header).and_return(value)
- allow(subject).to receive(:params).and_return(value)
- allow(subject).to receive(:request).and_return(value)
- end
-
- describe 'required instance methods' do
- let(:return_spy) { spy }
-
- it 'requires some instance methods' do
- expect_message(:header)
- expect_message(:params)
- expect_message(:request)
-
- subject.paginate(resource)
- end
+ allow(subject).to receive(:params).and_return(query)
+ allow(subject).to receive(:request).and_return(double(url: "#{incoming_api_projects_url}?#{query.to_query}"))
end
context 'when resource can be paginated' do
@@ -232,39 +214,96 @@ describe API::Helpers::Pagination do
end
describe 'first page' do
- before do
- allow(subject).to receive(:params)
- .and_return({ page: 1, per_page: 2 })
+ shared_examples 'response with pagination headers' do
+ it 'adds appropriate headers' do
+ expect_header('X-Total', '3')
+ expect_header('X-Total-Pages', '2')
+ expect_header('X-Per-Page', '2')
+ expect_header('X-Page', '1')
+ expect_header('X-Next-Page', '2')
+ expect_header('X-Prev-Page', '')
+
+ expect_header('Link', anything) do |_key, val|
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last"))
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next"))
+ expect(val).not_to include('rel="prev"')
+ end
+
+ subject.paginate(resource)
+ end
end
- it 'returns appropriate amount of resources' do
- expect(subject.paginate(resource).count).to eq 2
+ shared_examples 'paginated response' do
+ it 'returns appropriate amount of resources' do
+ expect(subject.paginate(resource).count).to eq 2
+ end
+
+ it 'executes only one SELECT COUNT query' do
+ expect { subject.paginate(resource) }.to make_queries_matching(/SELECT COUNT/, 1)
+ end
end
- it 'adds appropriate headers' do
- expect_header('X-Total', '3')
- expect_header('X-Total-Pages', '2')
- expect_header('X-Per-Page', '2')
- expect_header('X-Page', '1')
- expect_header('X-Next-Page', '2')
- expect_header('X-Prev-Page', '')
+ let(:query) { base_query.merge(page: 1, per_page: 2) }
- expect_header('Link', anything) do |_key, val|
- expect(val).to include('rel="first"')
- expect(val).to include('rel="last"')
- expect(val).to include('rel="next"')
- expect(val).not_to include('rel="prev"')
+ context 'when the api_kaminari_count_with_limit feature flag is unset' do
+ it_behaves_like 'paginated response'
+ it_behaves_like 'response with pagination headers'
+ end
+
+ context 'when the api_kaminari_count_with_limit feature flag is disabled' do
+ before do
+ stub_feature_flags(api_kaminari_count_with_limit: false)
end
- subject.paginate(resource)
+ it_behaves_like 'paginated response'
+ it_behaves_like 'response with pagination headers'
+ end
+
+ context 'when the api_kaminari_count_with_limit feature flag is enabled' do
+ before do
+ stub_feature_flags(api_kaminari_count_with_limit: true)
+ end
+
+ context 'when resources count is less than MAX_COUNT_LIMIT' do
+ before do
+ stub_const("::Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT", 4)
+ end
+
+ it_behaves_like 'paginated response'
+ it_behaves_like 'response with pagination headers'
+ end
+
+ context 'when resources count is more than MAX_COUNT_LIMIT' do
+ before do
+ stub_const("::Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT", 2)
+ end
+
+ it_behaves_like 'paginated response'
+
+ it 'does not return the X-Total and X-Total-Pages headers' do
+ expect_no_header('X-Total')
+ expect_no_header('X-Total-Pages')
+ expect_header('X-Per-Page', '2')
+ expect_header('X-Page', '1')
+ expect_header('X-Next-Page', '2')
+ expect_header('X-Prev-Page', '')
+
+ expect_header('Link', anything) do |_key, val|
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next"))
+ expect(val).not_to include('rel="last"')
+ expect(val).not_to include('rel="prev"')
+ end
+
+ subject.paginate(resource)
+ end
+ end
end
end
describe 'second page' do
- before do
- allow(subject).to receive(:params)
- .and_return({ page: 2, per_page: 2 })
- end
+ let(:query) { base_query.merge(page: 2, per_page: 2) }
it 'returns appropriate amount of resources' do
expect(subject.paginate(resource).count).to eq 1
@@ -279,9 +318,9 @@ describe API::Helpers::Pagination do
expect_header('X-Prev-Page', '1')
expect_header('Link', anything) do |_key, val|
- expect(val).to include('rel="first"')
- expect(val).to include('rel="last"')
- expect(val).to include('rel="prev"')
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last"))
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="prev"))
expect(val).not_to include('rel="next"')
end
@@ -313,10 +352,7 @@ describe API::Helpers::Pagination do
context 'when resource empty' do
describe 'first page' do
- before do
- allow(subject).to receive(:params)
- .and_return({ page: 1, per_page: 2 })
- end
+ let(:query) { base_query.merge(page: 1, per_page: 2) }
it 'returns appropriate amount of resources' do
expect(subject.paginate(resource).count).to eq 0
@@ -331,8 +367,8 @@ describe API::Helpers::Pagination do
expect_header('X-Prev-Page', '')
expect_header('Link', anything) do |_key, val|
- expect(val).to include('rel="first"')
- expect(val).to include('rel="last"')
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
+ expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="last"))
expect(val).not_to include('rel="prev"')
expect(val).not_to include('rel="next"')
expect(val).not_to include('page=0')
@@ -348,6 +384,10 @@ describe API::Helpers::Pagination do
expect(subject).to receive(:header).with(*args, &block)
end
+ def expect_no_header(*args, &block)
+ expect(subject).not_to receive(:header).with(*args)
+ end
+
def expect_message(method)
expect(subject).to receive(method)
.at_least(:once).and_return(value)
diff --git a/spec/lib/api/helpers/version_spec.rb b/spec/lib/api/helpers/version_spec.rb
new file mode 100644
index 00000000000..34006e0930b
--- /dev/null
+++ b/spec/lib/api/helpers/version_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe API::Helpers::Version do
+ describe '.new' do
+ it 'is possible to initialize it with existing API version' do
+ expect(described_class.new('v4').to_s).to eq 'v4'
+ end
+
+ it 'raises an error when unsupported API version is provided' do
+ expect { described_class.new('v111') }.to raise_error ArgumentError
+ end
+ end
+
+ describe '#root_path' do
+ it 'returns a root path of the API version' do
+ expect(described_class.new('v4').root_path).to eq '/api/v4'
+ end
+ end
+
+ describe '#root_url' do
+ it 'returns an URL for a root path for the API version' do
+ expect(described_class.new('v4').root_url)
+ .to eq 'http://localhost/api/v4'
+ end
+ end
+end
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 58a49124ce6..08165f147bb 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -148,4 +148,40 @@ describe API::Helpers do
it_behaves_like 'user namespace finder'
end
+
+ describe '#send_git_blob' do
+ let(:repository) { double }
+ let(:blob) { double(name: 'foobar') }
+
+ let(:send_git_blob) do
+ subject.send(:send_git_blob, repository, blob)
+ end
+
+ before do
+ allow(subject).to receive(:env).and_return({})
+ allow(subject).to receive(:content_type)
+ allow(subject).to receive(:header).and_return({})
+ allow(Gitlab::Workhorse).to receive(:send_git_blob)
+ end
+
+ it 'sets Gitlab::Workhorse::DETECT_HEADER header' do
+ expect(send_git_blob[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ end
+
+ context 'content disposition' do
+ context 'when blob name is null' do
+ let(:blob) { double(name: nil) }
+
+ it 'returns only the disposition' do
+ expect(send_git_blob['Content-Disposition']).to eq 'inline'
+ end
+ end
+
+ context 'when blob name is not null' do
+ it 'returns disposition with the blob name' do
+ expect(send_git_blob['Content-Disposition']).to eq %q(inline; filename="foobar"; filename*=UTF-8''foobar)
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb
index 9633caac788..ae1c881e1f6 100644
--- a/spec/lib/backup/manager_spec.rb
+++ b/spec/lib/backup/manager_spec.rb
@@ -266,6 +266,7 @@ describe Backup::Manager do
remote_directory: 'directory',
multipart_chunk_size: 104857600,
encryption: nil,
+ encryption_key: nil,
storage_class: nil
}
)
diff --git a/spec/lib/banzai/color_parser_spec.rb b/spec/lib/banzai/color_parser_spec.rb
index a1cb0c07b06..af2a8f215c1 100644
--- a/spec/lib/banzai/color_parser_spec.rb
+++ b/spec/lib/banzai/color_parser_spec.rb
@@ -57,7 +57,7 @@ describe Banzai::ColorParser do
context 'HSL format' do
[
- 'hsl(0,0%,0%)', 'hsl(0,100%,100%)',
+ 'hsl(0,0%,0%)', 'hsl(0,100%,100%)',
'hsl(540,0%,0%)', 'hsl(-720,0%,0%)',
'hsl(0deg,0%,0%)', 'hsl(0DEG,0%,0%)',
'hsl(0, 0%, 0%)', 'HSL(0,0%,0%)',
diff --git a/spec/lib/banzai/filter/autolink_filter_spec.rb b/spec/lib/banzai/filter/autolink_filter_spec.rb
index 7a457403b51..4972c4b4bd2 100644
--- a/spec/lib/banzai/filter/autolink_filter_spec.rb
+++ b/spec/lib/banzai/filter/autolink_filter_spec.rb
@@ -121,6 +121,13 @@ describe Banzai::Filter::AutolinkFilter do
expect(doc.to_s).to eq("See #{link}")
end
+ it 'does not autolink bad URLs after we remove trailing punctuation' do
+ link = 'http://]'
+ doc = filter("See #{link}")
+
+ expect(doc.to_s).to eq("See #{link}")
+ end
+
it 'does not include trailing punctuation' do
['.', ', ok?', '...', '?', '!', ': is that ok?'].each do |trailing_punctuation|
doc = filter("See #{link}#{trailing_punctuation}")
@@ -188,6 +195,22 @@ describe Banzai::Filter::AutolinkFilter do
expect(doc.at_css('a')['class']).to eq 'custom'
end
+ it 'escapes RTLO and other characters' do
+ # rendered text looks like "http://example.com/evilexe.mp3"
+ evil_link = "#{link}evil\u202E3pm.exe"
+ doc = filter("#{evil_link}")
+
+ expect(doc.at_css('a')['href']).to eq "http://about.gitlab.com/evil%E2%80%AE3pm.exe"
+ end
+
+ it 'encodes international domains' do
+ link = "http://one😄two.com"
+ expected = "http://one%F0%9F%98%84two.com"
+ doc = filter(link)
+
+ expect(doc.at_css('a')['href']).to eq expected
+ end
+
described_class::IGNORE_PARENTS.each do |elem|
it "ignores valid links contained inside '#{elem}' element" do
exp = act = "<#{elem}>See #{link}</#{elem}>"
diff --git a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
index cbff2fdab14..4daf6be1bb7 100644
--- a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
@@ -205,7 +205,7 @@ describe Banzai::Filter::CommitRangeReferenceFilter do
context 'cross-project URL reference' do
let(:namespace) { create(:namespace) }
let(:project2) { create(:project, :public, :repository, namespace: namespace) }
- let(:range) { CommitRange.new("#{commit1.id}...master", project) }
+ let(:range) { CommitRange.new("#{commit1.id}...master", project) }
let(:reference) { urls.project_compare_url(project2, from: commit1.id, to: 'master') }
before do
diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
index a0270d93d50..43222ddb5e2 100644
--- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
@@ -121,6 +121,42 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
end
end
+ context "youtrack project" do
+ let(:project) { create(:youtrack_project) }
+
+ before do
+ project.update!(issues_enabled: false)
+ end
+
+ context "with right markdown" do
+ let(:issue) { ExternalIssue.new("YT-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with underscores in the prefix" do
+ let(:issue) { ExternalIssue.new("PRJ_1-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with lowercase letters in the prefix" do
+ let(:issue) { ExternalIssue.new("YTkPrj-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with a single-letter prefix" do
+ let(:issue) { ExternalIssue.new("T-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+ end
+
context "jira project" do
let(:project) { create(:jira_project) }
let(:reference) { issue.to_reference }
diff --git a/spec/lib/banzai/filter/external_link_filter_spec.rb b/spec/lib/banzai/filter/external_link_filter_spec.rb
index 2a3c0cd78b8..2acbe05f082 100644
--- a/spec/lib/banzai/filter/external_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_link_filter_spec.rb
@@ -49,16 +49,23 @@ describe Banzai::Filter::ExternalLinkFilter do
end
context 'for invalid urls' do
- it 'skips broken hrefs' do
+ it 'adds rel and target attributes to broken hrefs' do
doc = filter %q(<p><a href="don't crash on broken urls">Google</a></p>)
- expected = %q(<p><a href="don't%20crash%20on%20broken%20urls">Google</a></p>)
+ expected = %q(<p><a href="don't%20crash%20on%20broken%20urls" rel="nofollow noreferrer noopener" target="_blank">Google</a></p>)
expect(doc.to_html).to eq(expected)
end
- it 'skips improperly formatted mailtos' do
+ it 'adds rel and target to improperly formatted mailtos' do
doc = filter %q(<p><a href="mailto://jblogs@example.com">Email</a></p>)
- expected = %q(<p><a href="mailto://jblogs@example.com">Email</a></p>)
+ expected = %q(<p><a href="mailto://jblogs@example.com" rel="nofollow noreferrer noopener" target="_blank">Email</a></p>)
+
+ expect(doc.to_html).to eq(expected)
+ end
+
+ it 'adds rel and target to improperly formatted autolinks' do
+ doc = filter %q(<p><a href="mailto://jblogs@example.com">mailto://jblogs@example.com</a></p>)
+ expected = %q(<p><a href="mailto://jblogs@example.com" rel="nofollow noreferrer noopener" target="_blank">mailto://jblogs@example.com</a></p>)
expect(doc.to_html).to eq(expected)
end
@@ -112,4 +119,62 @@ describe Banzai::Filter::ExternalLinkFilter do
it_behaves_like 'an external link with rel attribute'
end
+
+ context 'links with RTLO character' do
+ # In rendered text this looks like "http://example.com/evilexe.mp3"
+ let(:doc) { filter %Q(<a href="http://example.com/evil%E2%80%AE3pm.exe">http://example.com/evil\u202E3pm.exe</a>) }
+
+ it_behaves_like 'an external link with rel attribute'
+
+ it 'escapes RTLO in link text' do
+ expected = %q(http://example.com/evil%E2%80%AE3pm.exe</a>)
+
+ expect(doc.to_html).to include(expected)
+ end
+
+ it 'does not mangle the link text' do
+ doc = filter %Q(<a href="http://example.com">One<span>and</span>\u202Eexe.mp3</a>)
+
+ expect(doc.to_html).to include('One<span>and</span>%E2%80%AEexe.mp3</a>')
+ end
+ end
+
+ context 'for generated autolinks' do
+ context 'with an IDN character' do
+ let(:doc) { filter(%q(<a href="http://exa%F0%9F%98%84mple.com">http://exa😄mple.com</a>)) }
+ let(:doc_email) { filter(%q(<a href="http://exa%F0%9F%98%84mple.com">http://exa😄mple.com</a>), emailable_links: true) }
+
+ it_behaves_like 'an external link with rel attribute'
+
+ it 'does not change the link text' do
+ expect(doc.to_html).to include('http://exa😄mple.com</a>')
+ end
+
+ it 'uses punycode for emails' do
+ expect(doc_email.to_html).to include('http://xn--example-6p25f.com/</a>')
+ end
+ end
+ end
+
+ context 'for links that look malicious' do
+ context 'with an IDN character' do
+ let(:doc) { filter %q(<a href="http://exa%F0%9F%98%84mple.com">http://exa😄mple.com</a>) }
+
+ it 'adds a toolip with punycode' do
+ expect(doc.to_html).to include('http://exa😄mple.com</a>')
+ expect(doc.to_html).to include('class="has-tooltip"')
+ expect(doc.to_html).to include('title="http://xn--example-6p25f.com/"')
+ end
+ end
+
+ context 'with RTLO character' do
+ let(:doc) { filter %q(<a href="http://example.com/evil%E2%80%AE3pm.exe">Evil Test</a>) }
+
+ it 'adds a toolip with punycode' do
+ expect(doc.to_html).to include('Evil Test</a>')
+ expect(doc.to_html).to include('class="has-tooltip"')
+ expect(doc.to_html).to include('title="http://example.com/evil%E2%80%AE3pm.exe"')
+ end
+ end
+ end
end
diff --git a/spec/lib/banzai/filter/footnote_filter_spec.rb b/spec/lib/banzai/filter/footnote_filter_spec.rb
new file mode 100644
index 00000000000..c6dcb4e46fd
--- /dev/null
+++ b/spec/lib/banzai/filter/footnote_filter_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Banzai::Filter::FootnoteFilter do
+ include FilterSpecHelper
+
+ # first[^1] and second[^second]
+ # [^1]: one
+ # [^second]: two
+ let(:footnote) do
+ <<~EOF
+ <p>first<sup><a href="#fn1" id="fnref1">1</a></sup> and second<sup><a href="#fn2" id="fnref2">2</a></sup></p>
+ <p>same reference<sup><a href="#fn1" id="fnref1">1</a></sup></p>
+ <ol>
+ <li id="fn1">
+ <p>one <a href="#fnref1">↩</a></p>
+ </li>
+ <li id="fn2">
+ <p>two <a href="#fnref2">↩</a></p>
+ </li>
+ </ol>
+ EOF
+ end
+
+ let(:filtered_footnote) do
+ <<~EOF
+ <p>first<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup> and second<sup class="footnote-ref"><a href="#fn2-#{identifier}" id="fnref2-#{identifier}">2</a></sup></p>
+ <p>same reference<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup></p>
+ <section class="footnotes"><ol>
+ <li id="fn1-#{identifier}">
+ <p>one <a href="#fnref1-#{identifier}" class="footnote-backref">↩</a></p>
+ </li>
+ <li id="fn2-#{identifier}">
+ <p>two <a href="#fnref2-#{identifier}" class="footnote-backref">↩</a></p>
+ </li>
+ </ol></section>
+ EOF
+ end
+
+ context 'when footnotes exist' do
+ let(:doc) { filter(footnote) }
+ let(:link_node) { doc.css('sup > a').first }
+ let(:identifier) { link_node[:id].delete_prefix('fnref1-') }
+
+ it 'properly adds the necessary ids and classes' do
+ expect(doc.to_html).to eq filtered_footnote
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
index 905fbb9434b..914c4e2d823 100644
--- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
@@ -445,7 +445,7 @@ describe Banzai::Filter::IssueReferenceFilter do
end
describe '.references_in' do
- let(:merge_request) { create(:merge_request) }
+ let(:merge_request) { create(:merge_request) }
it 'yields valid references' do
expect do |b|
diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb
index 00257ed7904..108d7b43a26 100644
--- a/spec/lib/banzai/filter/label_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb
@@ -236,6 +236,24 @@ describe Banzai::Filter::LabelReferenceFilter do
end
end
+ context 'References with html entities' do
+ let!(:label) { create(:label, name: '&lt;html&gt;', project: project) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter('See ~"&lt;html&gt;"')
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ expect(doc.text).to eq 'See <html>'
+ end
+
+ it 'ignores invalid label names and escapes entities' do
+ act = %(Label #{Label.reference_prefix}"&lt;non valid&gt;")
+
+ expect(reference_filter(act).to_html).to eq act
+ end
+ end
+
describe 'consecutive references' do
let(:bug) { create(:label, name: 'bug', project: project) }
let(:feature_proposal) { create(:label, name: 'feature proposal', project: project) }
diff --git a/spec/lib/banzai/filter/markdown_filter_spec.rb b/spec/lib/banzai/filter/markdown_filter_spec.rb
index cf49249756a..83fcda29680 100644
--- a/spec/lib/banzai/filter/markdown_filter_spec.rb
+++ b/spec/lib/banzai/filter/markdown_filter_spec.rb
@@ -10,12 +10,6 @@ describe Banzai::Filter::MarkdownFilter do
filter('test')
end
- it 'uses Redcarpet' do
- expect_any_instance_of(Banzai::Filter::MarkdownEngines::Redcarpet).to receive(:render).and_return('test')
-
- filter('test', { markdown_engine: :redcarpet })
- end
-
it 'uses CommonMark' do
expect_any_instance_of(Banzai::Filter::MarkdownEngines::CommonMark).to receive(:render).and_return('test')
@@ -30,39 +24,41 @@ describe Banzai::Filter::MarkdownFilter do
end
it 'adds language to lang attribute when specified' do
- result = filter("```html\nsome code\n```")
+ result = filter("```html\nsome code\n```", no_sourcepos: true)
- expect(result).to start_with("<pre><code lang=\"html\">")
+ expect(result).to start_with('<pre><code lang="html">')
end
it 'does not add language to lang attribute when not specified' do
- result = filter("```\nsome code\n```")
+ result = filter("```\nsome code\n```", no_sourcepos: true)
- expect(result).to start_with("<pre><code>")
+ expect(result).to start_with('<pre><code>')
end
it 'works with utf8 chars in language' do
- result = filter("```æ—¥\nsome code\n```")
+ result = filter("```æ—¥\nsome code\n```", no_sourcepos: true)
- expect(result).to start_with("<pre><code lang=\"æ—¥\">")
+ expect(result).to start_with('<pre><code lang="æ—¥">')
end
end
+ end
- context 'using Redcarpet' do
+ describe 'source line position' do
+ context 'using CommonMark' do
before do
- stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :redcarpet)
+ stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
end
- it 'adds language to lang attribute when specified' do
- result = filter("```html\nsome code\n```")
+ it 'defaults to add data-sourcepos' do
+ result = filter('test')
- expect(result).to start_with("\n<pre><code lang=\"html\">")
+ expect(result).to eq '<p data-sourcepos="1:1-1:4">test</p>'
end
- it 'does not add language to lang attribute when not specified' do
- result = filter("```\nsome code\n```")
+ it 'disables data-sourcepos' do
+ result = filter('test', no_sourcepos: true)
- expect(result).to start_with("\n<pre><code>")
+ expect(result).to eq '<p>test</p>'
end
end
end
@@ -77,7 +73,7 @@ describe Banzai::Filter::MarkdownFilter do
[^1]: a footnote
MD
- result = filter(text)
+ result = filter(text, no_sourcepos: true)
expect(result).to include('<td>foot <sup')
expect(result).to include('<section class="footnotes">')
diff --git a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
index 1a87cfa5b45..4c94e4fdae0 100644
--- a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
@@ -59,7 +59,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do
it 'links with adjacent text' do
doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<a.+>#{milestone.name}</a>\.\)))
+ expect(doc.to_html).to match(%r(\(<a.+>#{milestone.reference_link_text}</a>\.\)))
end
it 'ignores invalid milestone IIDs' do
@@ -80,12 +80,12 @@ describe Banzai::Filter::MilestoneReferenceFilter do
doc = reference_filter("See #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
- expect(doc.text).to eq 'See gfm'
+ expect(doc.text).to eq "See #{milestone.reference_link_text}"
end
it 'links with adjacent text' do
doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<a.+>#{milestone.name}</a>\.\)))
+ expect(doc.to_html).to match(%r(\(<a.+>#{milestone.reference_link_text}</a>\.\)))
end
it 'ignores invalid milestone names' do
@@ -106,12 +106,12 @@ describe Banzai::Filter::MilestoneReferenceFilter do
doc = reference_filter("See #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
- expect(doc.text).to eq 'See gfm references'
+ expect(doc.text).to eq "See #{milestone.reference_link_text}"
end
it 'links with adjacent text' do
doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<a.+>#{milestone.name}</a>\.\)))
+ expect(doc.to_html).to match(%r(\(<a.+>#{milestone.reference_link_text}</a>\.\)))
end
it 'ignores invalid milestone names' do
@@ -201,14 +201,14 @@ describe Banzai::Filter::MilestoneReferenceFilter do
doc = reference_filter("See (#{reference}.)")
expect(doc.css('a').first.text)
- .to eq("#{milestone.name} in #{another_project.full_path}")
+ .to eq("#{milestone.reference_link_text} in #{another_project.full_path}")
end
it 'has valid text' do
doc = reference_filter("See (#{reference}.)")
expect(doc.text)
- .to eq("See (#{milestone.name} in #{another_project.full_path}.)")
+ .to eq("See (#{milestone.reference_link_text} in #{another_project.full_path}.)")
end
it 'escapes the name attribute' do
@@ -217,7 +217,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do
doc = reference_filter("See #{reference}")
expect(doc.css('a').first.text)
- .to eq "#{milestone.name} in #{another_project.full_path}"
+ .to eq "#{milestone.reference_link_text} in #{another_project.full_path}"
end
end
@@ -238,14 +238,14 @@ describe Banzai::Filter::MilestoneReferenceFilter do
doc = reference_filter("See (#{reference}.)")
expect(doc.css('a').first.text)
- .to eq("#{milestone.name} in #{another_project.path}")
+ .to eq("#{milestone.reference_link_text} in #{another_project.path}")
end
it 'has valid text' do
doc = reference_filter("See (#{reference}.)")
expect(doc.text)
- .to eq("See (#{milestone.name} in #{another_project.path}.)")
+ .to eq("See (#{milestone.reference_link_text} in #{another_project.path}.)")
end
it 'escapes the name attribute' do
@@ -254,7 +254,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do
doc = reference_filter("See #{reference}")
expect(doc.css('a').first.text)
- .to eq "#{milestone.name} in #{another_project.path}"
+ .to eq "#{milestone.reference_link_text} in #{another_project.path}"
end
end
@@ -275,14 +275,14 @@ describe Banzai::Filter::MilestoneReferenceFilter do
doc = reference_filter("See (#{reference}.)")
expect(doc.css('a').first.text)
- .to eq("#{milestone.name} in #{another_project.path}")
+ .to eq("#{milestone.reference_link_text} in #{another_project.path}")
end
it 'has valid text' do
doc = reference_filter("See (#{reference}.)")
expect(doc.text)
- .to eq("See (#{milestone.name} in #{another_project.path}.)")
+ .to eq("See (#{milestone.reference_link_text} in #{another_project.path}.)")
end
it 'escapes the name attribute' do
@@ -291,7 +291,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do
doc = reference_filter("See #{reference}")
expect(doc.css('a').first.text)
- .to eq "#{milestone.name} in #{another_project.path}"
+ .to eq "#{milestone.reference_link_text} in #{another_project.path}"
end
end
@@ -346,7 +346,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do
milestone.update!(group: parent_group)
doc = reference_filter("See #{reference}")
- expect(doc.css('a').first.text).to eq(milestone.name)
+ expect(doc.css('a').first.text).to eq(milestone.reference_link_text)
end
end
diff --git a/spec/lib/banzai/filter/project_reference_filter_spec.rb b/spec/lib/banzai/filter/project_reference_filter_spec.rb
index 48140305e26..69f9c1ae829 100644
--- a/spec/lib/banzai/filter/project_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/project_reference_filter_spec.rb
@@ -13,7 +13,7 @@ describe Banzai::Filter::ProjectReferenceFilter do
project.to_reference_with_postfix
end
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public) }
subject { project }
let(:subject_name) { "project" }
let(:reference) { get_reference(project) }
@@ -26,6 +26,12 @@ describe Banzai::Filter::ProjectReferenceFilter do
expect(reference_filter(act).to_html).to eq(CGI.escapeHTML(exp))
end
+ it 'fails fast for long invalid string' do
+ expect do
+ Timeout.timeout(5.seconds) { reference_filter("A" * 50000).to_html }
+ end.not_to raise_error
+ end
+
it 'allows references with text after the > character' do
doc = reference_filter("Hey #{reference}foo")
expect(doc.css('a').first.attr('href')).to eq urls.project_url(subject)
diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb
index 415ded05e6e..dad0a5535c0 100644
--- a/spec/lib/banzai/filter/relative_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb
@@ -353,5 +353,59 @@ describe Banzai::Filter::RelativeLinkFilter do
expect(doc.at_css('a')['href']).to eq 'http://example.com'
end
end
+
+ context 'to a personal snippet' do
+ let(:group) { nil }
+ let(:project) { nil }
+ let(:relative_path) { '/uploads/-/system/personal_snippet/6/674e4f07fbf0a7736c3439212896e51a/example.tar.gz' }
+
+ context 'with an absolute URL' do
+ let(:absolute_path) { Gitlab.config.gitlab.url + relative_path }
+ let(:only_path) { false }
+
+ it 'rewrites the link correctly' do
+ doc = filter(link(relative_path))
+
+ expect(doc.at_css('a')['href']).to eq(absolute_path)
+ end
+ end
+
+ context 'with a relative URL root' do
+ let(:gitlab_root) { '/gitlab' }
+ let(:absolute_path) { Gitlab.config.gitlab.url + gitlab_root + relative_path }
+
+ before do
+ stub_config_setting(relative_url_root: gitlab_root)
+ end
+
+ context 'with an absolute URL' do
+ let(:only_path) { false }
+
+ it 'rewrites the link correctly' do
+ doc = filter(link(relative_path))
+
+ expect(doc.at_css('a')['href']).to eq(absolute_path)
+ end
+ end
+
+ it 'rewrites the link correctly' do
+ doc = filter(link(relative_path))
+
+ expect(doc.at_css('a')['href']).to eq(gitlab_root + relative_path)
+ end
+ end
+
+ it 'rewrites the link correctly' do
+ doc = filter(link(relative_path))
+
+ expect(doc.at_css('a')['href']).to eq(relative_path)
+ end
+
+ it 'does not modify absolute URL' do
+ doc = filter(link('http://example.com'))
+
+ expect(doc.at_css('a')['href']).to eq 'http://example.com'
+ end
+ end
end
end
diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb
index 0b3c2390304..f2a5d7b2c9f 100644
--- a/spec/lib/banzai/filter/sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb
@@ -246,7 +246,7 @@ describe Banzai::Filter::SanitizationFilter do
'protocol-based JS injection: spaces and entities' => {
input: '<a href=" &#14; javascript:alert(\'XSS\');">foo</a>',
- output: '<a href>foo</a>'
+ output: '<a href="">foo</a>'
},
'protocol whitespace' => {
@@ -300,5 +300,55 @@ describe Banzai::Filter::SanitizationFilter do
expect(act.to_html).to eq exp
end
+
+ it 'allows the `data-sourcepos` attribute globally' do
+ exp = %q{<p data-sourcepos="1:1-1:10">foo/bar.md</p>}
+ act = filter(exp)
+
+ expect(act.to_html).to eq exp
+ end
+
+ describe 'footnotes' do
+ it 'allows correct footnote id property on links' do
+ exp = %q{<a href="#fn1" id="fnref1">foo/bar.md</a>}
+ act = filter(exp)
+
+ expect(act.to_html).to eq exp
+ end
+
+ it 'allows correct footnote id property on li element' do
+ exp = %q{<ol><li id="fn1">footnote</li></ol>}
+ act = filter(exp)
+
+ expect(act.to_html).to eq exp
+ end
+
+ it 'removes invalid id for footnote links' do
+ exp = %q{<a href="#fn1">link</a>}
+
+ %w[fnrefx test xfnref1].each do |id|
+ act = filter(%Q{<a href="#fn1" id="#{id}">link</a>})
+
+ expect(act.to_html).to eq exp
+ end
+ end
+
+ it 'removes invalid id for footnote li' do
+ exp = %q{<ol><li>footnote</li></ol>}
+
+ %w[fnx test xfn1].each do |id|
+ act = filter(%Q{<ol><li id="#{id}">footnote</li></ol>})
+
+ expect(act.to_html).to eq exp
+ end
+ end
+
+ it 'allows footnotes numbered higher than 9' do
+ exp = %q{<a href="#fn15" id="fnref15">link</a><ol><li id="fn15">footnote</li></ol>}
+ act = filter(exp)
+
+ expect(act.to_html).to eq exp
+ end
+ end
end
end
diff --git a/spec/lib/banzai/filter/spaced_link_filter_spec.rb b/spec/lib/banzai/filter/spaced_link_filter_spec.rb
index 1ad7f3ff567..76d7644d76c 100644
--- a/spec/lib/banzai/filter/spaced_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/spaced_link_filter_spec.rb
@@ -26,11 +26,6 @@ describe Banzai::Filter::SpacedLinkFilter do
expect(doc.at_css('p')).to be_nil
end
- it 'does nothing when markdown_engine is redcarpet' do
- exp = act = link
- expect(filter(act, markdown_engine: :redcarpet).to_html).to eq exp
- end
-
it 'does nothing with empty text' do
link = '[](page slug)'
doc = filter("See #{link}")
diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb
index 209a547c3b3..3b52f6666d0 100644
--- a/spec/lib/banzai/object_renderer_spec.rb
+++ b/spec/lib/banzai/object_renderer_spec.rb
@@ -11,7 +11,7 @@ describe Banzai::ObjectRenderer do
)
end
- let(:object) { Note.new(note: 'hello', note_html: '<p dir="auto">hello</p>', cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION) }
+ let(:object) { Note.new(note: 'hello', note_html: '<p dir="auto">hello</p>', cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION << 16) }
describe '#render' do
context 'with cache' do
diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb
index 8cce1b96698..77cb1954ea3 100644
--- a/spec/lib/banzai/pipeline/description_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb
@@ -13,6 +13,10 @@ describe Banzai::Pipeline::DescriptionPipeline do
output
end
+ before do
+ stub_commonmark_sourcepos_disabled
+ end
+
it 'uses a limited whitelist' do
doc = parse('# Description')
diff --git a/spec/lib/banzai/pipeline/email_pipeline_spec.rb b/spec/lib/banzai/pipeline/email_pipeline_spec.rb
index 6a11ca2f9d5..b99161109eb 100644
--- a/spec/lib/banzai/pipeline/email_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/email_pipeline_spec.rb
@@ -10,5 +10,19 @@ describe Banzai::Pipeline::EmailPipeline do
expect(described_class.filters).not_to be_empty
expect(described_class.filters).not_to include(Banzai::Filter::ImageLazyLoadFilter)
end
+
+ it 'shows punycode for autolinks' do
+ examples = %W[
+ http://one😄two.com
+ http://\u0261itlab.com
+ ]
+
+ examples.each do |markdown|
+ result = described_class.call(markdown, project: nil)[:output]
+ link = result.css('a').first
+
+ expect(link.content).to include('http://xn--')
+ end
+ end
end
end
diff --git a/spec/lib/banzai/pipeline/full_pipeline_spec.rb b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
index e9c7a2f352e..3d3aa64d630 100644
--- a/spec/lib/banzai/pipeline/full_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
@@ -25,4 +25,76 @@ describe Banzai::Pipeline::FullPipeline do
expect(result).to include(%{data-original='\"&gt;bad things'})
end
end
+
+ describe 'footnotes' do
+ let(:project) { create(:project, :public) }
+ let(:html) { described_class.to_html(footnote_markdown, project: project) }
+ let(:identifier) { html[/.*fnref1-(\d+).*/, 1] }
+ let(:footnote_markdown) do
+ <<~EOF
+ first[^1] and second[^second]
+ [^1]: one
+ [^second]: two
+ EOF
+ end
+
+ let(:filtered_footnote) do
+ <<~EOF
+ <p dir="auto">first<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup> and second<sup class="footnote-ref"><a href="#fn2-#{identifier}" id="fnref2-#{identifier}">2</a></sup></p>
+
+ <section class="footnotes"><ol>
+ <li id="fn1-#{identifier}">
+ <p>one <a href="#fnref1-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ </li>
+ <li id="fn2-#{identifier}">
+ <p>two <a href="#fnref2-#{identifier}" 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>
+ EOF
+ end
+
+ it 'properly adds the necessary ids and classes' do
+ stub_commonmark_sourcepos_disabled
+
+ expect(html.lines.map(&:strip).join("\n")).to eq filtered_footnote
+ end
+ end
+
+ describe 'links are detected as malicious' do
+ it 'has tooltips for malicious links' do
+ examples = %W[
+ http://example.com/evil\u202E3pm.exe
+ [evilexe.mp3](http://example.com/evil\u202E3pm.exe)
+ rdar://localhost.com/\u202E3pm.exe
+ http://one😄two.com
+ [Evil-Test](http://one😄two.com)
+ http://\u0261itlab.com
+ [Evil-GitLab-link](http://\u0261itlab.com)
+ ![Evil-GitLab-link](http://\u0261itlab.com.png)
+ ]
+
+ examples.each do |markdown|
+ result = described_class.call(markdown, project: nil)[:output]
+ link = result.css('a').first
+
+ expect(link[:class]).to include('has-tooltip')
+ end
+ end
+
+ it 'has no tooltips for safe links' do
+ examples = %w[
+ http://example.com
+ [Safe-Test](http://example.com)
+ https://commons.wikimedia.org/wiki/File:اسكرام_2_-_تمنراست.jpg
+ [Wikipedia-link](https://commons.wikimedia.org/wiki/File:اسكرام_2_-_تمنراست.jpg)
+ ]
+
+ examples.each do |markdown|
+ result = described_class.call(markdown, project: nil)[:output]
+ link = result.css('a').first
+
+ expect(link[:class]).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/lib/bitbucket_server/client_spec.rb b/spec/lib/bitbucket_server/client_spec.rb
index 5de0a9a65b5..4f0d57ca8a6 100644
--- a/spec/lib/bitbucket_server/client_spec.rb
+++ b/spec/lib/bitbucket_server/client_spec.rb
@@ -17,12 +17,6 @@ describe BitbucketServer::Client do
subject.pull_requests(project, repo_slug)
end
-
- it 'throws an exception when connection fails' do
- allow(BitbucketServer::Collection).to receive(:new).and_raise(OpenSSL::SSL::SSLError)
-
- expect { subject.pull_requests(project, repo_slug) }.to raise_error(described_class::ServerError)
- end
end
describe '#activities' do
@@ -70,7 +64,7 @@ describe BitbucketServer::Client do
let(:url) { "#{base_uri}rest/api/1.0/projects/SOME-PROJECT/repos/my-repo/branches" }
it 'requests Bitbucket to create a branch' do
- stub_request(:post, url).to_return(status: 204, headers: headers, body: '{}')
+ stub_request(:post, url).to_return(status: 204, headers: headers, body: nil)
subject.create_branch(project, repo_slug, branch, sha)
@@ -84,7 +78,7 @@ describe BitbucketServer::Client do
let(:url) { "#{base_uri}rest/branch-utils/1.0/projects/SOME-PROJECT/repos/my-repo/branches" }
it 'requests Bitbucket to create a branch' do
- stub_request(:delete, url).to_return(status: 204, headers: headers, body: '{}')
+ stub_request(:delete, url).to_return(status: 204, headers: headers, body: nil)
subject.delete_branch(project, repo_slug, branch, sha)
diff --git a/spec/lib/bitbucket_server/connection_spec.rb b/spec/lib/bitbucket_server/connection_spec.rb
index b5da4cb1a49..ab8a5b89608 100644
--- a/spec/lib/bitbucket_server/connection_spec.rb
+++ b/spec/lib/bitbucket_server/connection_spec.rb
@@ -26,6 +26,12 @@ describe BitbucketServer::Connection do
expect { subject.get(url) }.to raise_error(described_class::ConnectionError)
end
+
+ it 'throws an exception upon a network error' do
+ WebMock.stub_request(:get, url).with(headers: { 'Accept' => 'application/json' }).to_raise(OpenSSL::SSL::SSLError)
+
+ expect { subject.get(url) }.to raise_error(described_class::ConnectionError)
+ end
end
describe '#post' do
@@ -42,6 +48,12 @@ describe BitbucketServer::Connection do
expect { subject.post(url, payload) }.to raise_error(described_class::ConnectionError)
end
+
+ it 'throws an exception upon a network error' do
+ WebMock.stub_request(:post, url).with(headers: { 'Accept' => 'application/json' }).to_raise(OpenSSL::SSL::SSLError)
+
+ expect { subject.post(url, payload) }.to raise_error(described_class::ConnectionError)
+ end
end
describe '#delete' do
@@ -63,6 +75,12 @@ describe BitbucketServer::Connection do
expect { subject.delete(:branches, branch_path, payload) }.to raise_error(described_class::ConnectionError)
end
+
+ it 'throws an exception upon a network error' do
+ WebMock.stub_request(:delete, branch_url).with(headers: headers).to_raise(OpenSSL::SSL::SSLError)
+
+ expect { subject.delete(:branches, branch_path, payload) }.to raise_error(described_class::ConnectionError)
+ end
end
end
end
diff --git a/spec/lib/bitbucket_server/paginator_spec.rb b/spec/lib/bitbucket_server/paginator_spec.rb
index d268d4f23cf..eadd7f68bfb 100644
--- a/spec/lib/bitbucket_server/paginator_spec.rb
+++ b/spec/lib/bitbucket_server/paginator_spec.rb
@@ -30,6 +30,17 @@ describe BitbucketServer::Paginator do
expect { limited.items }.to raise_error(StopIteration)
end
+ it 'does not stop if limit is unspecified' do
+ stub_const("BitbucketServer::Paginator::PAGE_LENGTH", 1)
+ paginator = described_class.new(connection, 'http://more-data', :pull_request, page_offset: 0, limit: nil)
+ allow(paginator).to receive(:fetch_next_page).and_return(first_page, last_page)
+
+ expect(paginator.has_next_page?).to be_truthy
+ expect(paginator.items).to match(['item_1'])
+ expect(paginator.has_next_page?).to be_truthy
+ expect(paginator.items).to match(['item_2'])
+ end
+
it 'calls the connection with different offsets' do
expect(connection).to receive(:get).with('http://more-data', start: 0, limit: BitbucketServer::Paginator::PAGE_LENGTH).and_return(page_attrs)
diff --git a/spec/lib/constraints/project_url_constrainer_spec.rb b/spec/lib/constraints/project_url_constrainer_spec.rb
index c96e7ab8495..3496b01ebcc 100644
--- a/spec/lib/constraints/project_url_constrainer_spec.rb
+++ b/spec/lib/constraints/project_url_constrainer_spec.rb
@@ -16,6 +16,10 @@ describe Constraints::ProjectUrlConstrainer do
let(:request) { build_request('foo', 'bar') }
it { expect(subject.matches?(request)).to be_falsey }
+
+ context 'existence_check is false' do
+ it { expect(subject.matches?(request, existence_check: false)).to be_truthy }
+ end
end
context "project id ending with .git" do
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 9d56c62ae57..a7163048370 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -182,4 +182,19 @@ describe Feature do
expect(described_class.disabled?(:enabled_feature_flag)).to be_falsey
end
end
+
+ describe Feature::Target do
+ describe '#targets' do
+ let(:project) { create(:project) }
+ let(:group) { create(:group) }
+ let(:user_name) { project.owner.username }
+
+ subject { described_class.new(user: user_name, project: project.full_path, group: group.full_path) }
+
+ it 'returns all found targets' do
+ expect(subject.targets).to be_an(Array)
+ expect(subject.targets).to eq([project.owner, project, group])
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/access/branch_protection_spec.rb b/spec/lib/gitlab/access/branch_protection_spec.rb
new file mode 100644
index 00000000000..7f2979e8e28
--- /dev/null
+++ b/spec/lib/gitlab/access/branch_protection_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Access::BranchProtection do
+ describe '#any?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:level, :result) do
+ Gitlab::Access::PROTECTION_NONE | false
+ Gitlab::Access::PROTECTION_DEV_CAN_PUSH | true
+ Gitlab::Access::PROTECTION_DEV_CAN_MERGE | true
+ Gitlab::Access::PROTECTION_FULL | true
+ end
+
+ with_them do
+ it { expect(described_class.new(level).any?).to eq(result) }
+ end
+ end
+
+ describe '#developer_can_push?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:level, :result) do
+ Gitlab::Access::PROTECTION_NONE | false
+ Gitlab::Access::PROTECTION_DEV_CAN_PUSH | true
+ Gitlab::Access::PROTECTION_DEV_CAN_MERGE | false
+ Gitlab::Access::PROTECTION_FULL | false
+ end
+
+ with_them do
+ it do
+ expect(described_class.new(level).developer_can_push?).to eq(result)
+ end
+ end
+ end
+
+ describe '#developer_can_merge?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:level, :result) do
+ Gitlab::Access::PROTECTION_NONE | false
+ Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
+ Gitlab::Access::PROTECTION_DEV_CAN_MERGE | true
+ Gitlab::Access::PROTECTION_FULL | false
+ end
+
+ with_them do
+ it do
+ expect(described_class.new(level).developer_can_merge?).to eq(result)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/auth/ldap/config_spec.rb b/spec/lib/gitlab/auth/ldap/config_spec.rb
index d3ab599d5a0..b91a09e3137 100644
--- a/spec/lib/gitlab/auth/ldap/config_spec.rb
+++ b/spec/lib/gitlab/auth/ldap/config_spec.rb
@@ -5,6 +5,65 @@ describe Gitlab::Auth::LDAP::Config do
let(:config) { described_class.new('ldapmain') }
+ def raw_cert
+ <<-EOS
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAk4CCQDX+u/9fICksDANBgkqhkiG9w0BAQsFADB1MQswCQYDVQQGEwJV
+UzEMMAoGA1UECAwDRm9vMQwwCgYDVQQHDANCYXIxDDAKBgNVBAoMA0JhejEMMAoG
+A1UECwwDUXV4MQ0wCwYDVQQDDARsZGFwMR8wHQYJKoZIhvcNAQkBFhBsZGFwQGV4
+YW1wbGUuY29tMB4XDTE5MDIyNzE1NTUxNFoXDTE5MDMyOTE1NTUxNFowdTELMAkG
+A1UEBhMCVVMxDDAKBgNVBAgMA0ZvbzEMMAoGA1UEBwwDQmFyMQwwCgYDVQQKDANC
+YXoxDDAKBgNVBAsMA1F1eDENMAsGA1UEAwwEbGRhcDEfMB0GCSqGSIb3DQEJARYQ
+bGRhcEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+APuDB/4/AUmTEmhYzN13no4Kt8hkRbLQuENRHlOeQw05/MVdoB1AWLOPzIXn4kex
+GD9tHkoJl8S0QPmAAcPHn5O97e+gd0ze5dRQZl/cSd2/j5zeaMvZ1mCrPN/dOluM
+94Oj+wQU4bEcOlrqIMSh0ezJw10R3IHXCQFeGtIZU57WmKcrryQX4kP7KTOgRw/t
+CYp+NivQHtLbBEj1MU0l10qMS2+w8Qpqov4MdW4gx4wTgId2j1ZZ56+n6Jsc9qoI
+wBWBNL4XU5a3kwhYZDOJoOvI9po33KLdT1dXS81uOFXClp3LGmKDgLTwQ1w+RmQG
++JG4EvTfDIShdcTDXEaOfCECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAJM9Btu5g
+k8qDiz5TilvpyoGuI4viCwusARFAFmOB/my/cHlVvkuq4bbfV1KJoWWGJg8GcklL
+cnIdxc35uYM5icr6xXQyrW0GqAO+LEXyUxVQqYETxrQ/LJ03xhBnuF7hvZJIBiky
+GwUy0clJxGfaCeEM8zXwePawLgGjuUawDDQOwigysoWqoMu3VFW8zl8UPa84bow9
+Kn2QmPAkLw4EcqYSCNSSvnyzu5SM64jwLWRXFsmlqD7773oT29vTkqM1EQANFEfT
+7gQomLyPqoPBoFph5oSNn6Rf31QX1Sie92EAKVnZ1XmD68hKzjv6ChCtzTv4jABg
+XrDwnLkORIAF/Q==
+-----END CERTIFICATE-----
+ EOS
+ end
+
+ def raw_key
+ <<-EOS
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQD7gwf+PwFJkxJo
+WMzdd56OCrfIZEWy0LhDUR5TnkMNOfzFXaAdQFizj8yF5+JHsRg/bR5KCZfEtED5
+gAHDx5+Tve3voHdM3uXUUGZf3Endv4+c3mjL2dZgqzzf3TpbjPeDo/sEFOGxHDpa
+6iDEodHsycNdEdyB1wkBXhrSGVOe1pinK68kF+JD+ykzoEcP7QmKfjYr0B7S2wRI
+9TFNJddKjEtvsPEKaqL+DHVuIMeME4CHdo9WWeevp+ibHPaqCMAVgTS+F1OWt5MI
+WGQziaDryPaaN9yi3U9XV0vNbjhVwpadyxpig4C08ENcPkZkBviRuBL03wyEoXXE
+w1xGjnwhAgMBAAECggEAbw82GVui6uUpjLAhjm3CssAi1TcJ2+L0aq1IMe5Bd3ay
+mkg0apY+VNPboQl6zuNxbJh3doPz42UhB8sxfE0Ktwd4KIb4Bxap7+2stwmkCGoN
+NVy0c8d2NWuHzuZ2XXTK2vMu5Wd/HWD0l66o14sJEoEpZlB7yU216UevmjSayxjh
+aBTSaYyyrf24haTaCuqwph/V73ZlMpFdSALGny0uiP/5inxciMCkMpHfX6BflSb4
+EGKsIYt9BJ0kY4GNG5bCP7971UCxp2eEJhU2fV8HuFGCOD12IqSpUqPxHxjsWpfx
+T7FZ3V2kM/58Ca+5LB2y3atcPIdY0/g7/43V4VD+7QKBgQD/PO4/0cmZuuLU1LPT
+C/C596kPK0JLlvvRqhbz4byRAkW/n7uQFG7TMtFNle3UmT7rk7pjtbHnByqzEd+9
+jMhBysjHOMg0+DWm7fEtSg/tJ3qLVO3nbdA4qmXYobLcLoG+PCYRLskEHHqTG/Bv
+QZLbavOU6rrTqckNr1TMpNBmXwKBgQD8Q0C2YTOpwgjRUe8i6Chnc3o4x8a1i98y
+9la6c7y7acWHSbEczMkNfEBrbM73rTb+bBA0Zqw+Z1gkv8bGpvGxX8kbSfJJ2YKW
+9koxpLNTVNVapqBa9ImiaozV285dz9Ukx8bnMOJlTELpOl7RRV7iF0smYjfHIl3D
+Yxyda/MtfwKBgHb9l/Dmw77IkqE4PFFimqqIHCe3OiP1UpavXh36midcUNoCBLYp
+4HTTlyI9iG/5tYysBVQgy7xx6eUrqww6Ss3pVOsTvLp9EL4u5aYAhiZApm+4e2TO
+HCmevvZcg/8EK3Zdoj2Wex5QjJBykQe9IVLrrH07ZTfySon3uGfjWkivAoGAGvqS
+VC8HGHOw/7n0ilYr5Ax8mM/813OzFj80PVKdb6m7P2HJOFxKcE/Gj/aeF+0FgaZL
+AV+tsirZSWzdNGesV5z35Bw/dlh11/FVNAP6TcI34y8I3VFj2uPsVf7hDjVpBTr8
+ccNPoyfJzCm69ESoBiQZnGxKrNhnELtr1wYxhr8CgYApWwf4hVrTWV1zs+pEJenh
+AtlErSqafbECNDSwS5BX8yDpu5yRBJ4xegO/rNlmb8ICRYkuJapD1xXicFOsmfUK
+0Ff8afd2Q/OfBeUdq9KA4JO9fNqzEwOWvv8Ryn4ZSYcAuLP7IVJKjjI6R7rYaO/G
+3OWJdizbykGOi0BFDu+3dw==
+-----END PRIVATE KEY-----
+ EOS
+ end
+
describe '.servers' do
it 'returns empty array if no server information is available' do
allow(Gitlab.config).to receive(:ldap).and_return('enabled' => false)
@@ -89,6 +148,42 @@ describe Gitlab::Auth::LDAP::Config do
expect(config.adapter_options[:encryption]).to include({ method: :start_tls })
end
+ it 'transforms SSL cert and key to OpenSSL objects' do
+ stub_ldap_config(
+ options: {
+ 'host' => 'ldap.example.com',
+ 'port' => 686,
+ 'encryption' => 'start_tls',
+ 'tls_options' => {
+ 'cert' => raw_cert,
+ 'key' => raw_key
+ }
+ }
+ )
+
+ expect(config.adapter_options[:encryption][:tls_options][:cert]).to be_a(OpenSSL::X509::Certificate)
+ expect(config.adapter_options[:encryption][:tls_options][:key]).to be_a(OpenSSL::PKey::RSA)
+ end
+
+ it 'logs an error when an invalid key or cert are configured' do
+ allow(Rails.logger).to receive(:error)
+ stub_ldap_config(
+ options: {
+ 'host' => 'ldap.example.com',
+ 'port' => 686,
+ 'encryption' => 'start_tls',
+ 'tls_options' => {
+ 'cert' => 'invalid cert',
+ 'key' => 'invalid_key'
+ }
+ }
+ )
+
+ config.adapter_options
+
+ expect(Rails.logger).to have_received(:error).with(/LDAP TLS Options/).twice
+ end
+
context 'when verify_certificates is enabled' do
it 'sets tls_options to OpenSSL defaults' do
stub_ldap_config(
@@ -130,7 +225,9 @@ describe Gitlab::Auth::LDAP::Config do
'host' => 'ldap.example.com',
'port' => 686,
'encryption' => 'simple_tls',
- 'ca_file' => '/etc/ca.pem'
+ 'tls_options' => {
+ 'ca_file' => '/etc/ca.pem'
+ }
}
)
@@ -145,7 +242,9 @@ describe Gitlab::Auth::LDAP::Config do
'host' => 'ldap.example.com',
'port' => 686,
'encryption' => 'simple_tls',
- 'ca_file' => ' '
+ 'tls_options' => {
+ 'ca_file' => ' '
+ }
}
)
@@ -160,7 +259,9 @@ describe Gitlab::Auth::LDAP::Config do
'host' => 'ldap.example.com',
'port' => 686,
'encryption' => 'simple_tls',
- 'ssl_version' => 'TLSv1_2'
+ 'tls_options' => {
+ 'ssl_version' => 'TLSv1_2'
+ }
}
)
@@ -175,7 +276,9 @@ describe Gitlab::Auth::LDAP::Config do
'host' => 'ldap.example.com',
'port' => 686,
'encryption' => 'simple_tls',
- 'ssl_version' => ' '
+ 'tls_options' => {
+ 'ssl_version' => ' '
+ }
}
)
@@ -223,6 +326,23 @@ describe Gitlab::Auth::LDAP::Config do
)
end
+ it 'transforms SSL cert and key to OpenSSL objects' do
+ stub_ldap_config(
+ options: {
+ 'host' => 'ldap.example.com',
+ 'port' => 686,
+ 'encryption' => 'start_tls',
+ 'tls_options' => {
+ 'cert' => raw_cert,
+ 'key' => raw_key
+ }
+ }
+ )
+
+ expect(config.omniauth_options[:tls_options][:cert]).to be_a(OpenSSL::X509::Certificate)
+ expect(config.omniauth_options[:tls_options][:key]).to be_a(OpenSSL::PKey::RSA)
+ end
+
context 'when verify_certificates is enabled' do
it 'specifies disable_verify_certificates as false' do
stub_ldap_config(
@@ -261,11 +381,13 @@ describe Gitlab::Auth::LDAP::Config do
'port' => 686,
'encryption' => 'simple_tls',
'verify_certificates' => true,
- 'ca_file' => '/etc/ca.pem'
+ 'tls_options' => {
+ 'ca_file' => '/etc/ca.pem'
+ }
}
)
- expect(config.omniauth_options).to include({ ca_file: '/etc/ca.pem' })
+ expect(config.omniauth_options[:tls_options]).to include({ ca_file: '/etc/ca.pem' })
end
end
@@ -277,11 +399,13 @@ describe Gitlab::Auth::LDAP::Config do
'port' => 686,
'encryption' => 'simple_tls',
'verify_certificates' => true,
- 'ca_file' => ' '
+ 'tls_options' => {
+ 'ca_file' => ' '
+ }
}
)
- expect(config.omniauth_options).not_to have_key(:ca_file)
+ expect(config.omniauth_options[:tls_options]).not_to have_key(:ca_file)
end
end
@@ -293,11 +417,13 @@ describe Gitlab::Auth::LDAP::Config do
'port' => 686,
'encryption' => 'simple_tls',
'verify_certificates' => true,
- 'ssl_version' => 'TLSv1_2'
+ 'tls_options' => {
+ 'ssl_version' => 'TLSv1_2'
+ }
}
)
- expect(config.omniauth_options).to include({ ssl_version: 'TLSv1_2' })
+ expect(config.omniauth_options[:tls_options]).to include({ ssl_version: 'TLSv1_2' })
end
end
@@ -309,11 +435,14 @@ describe Gitlab::Auth::LDAP::Config do
'port' => 686,
'encryption' => 'simple_tls',
'verify_certificates' => true,
- 'ssl_version' => ' '
+ 'tls_options' => {
+ 'ssl_version' => ' '
+ }
}
)
- expect(config.omniauth_options).not_to have_key(:ssl_version)
+ # OpenSSL default params includes `ssl_version` so we just check that it's not blank
+ expect(config.omniauth_options[:tls_options]).not_to include({ ssl_version: ' ' })
end
end
end
diff --git a/spec/lib/gitlab/auth/o_auth/identity_linker_spec.rb b/spec/lib/gitlab/auth/o_auth/identity_linker_spec.rb
index 528f1b4ec57..bf810d72f0e 100644
--- a/spec/lib/gitlab/auth/o_auth/identity_linker_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/identity_linker_spec.rb
@@ -23,7 +23,7 @@ describe Gitlab::Auth::OAuth::IdentityLinker do
end
context 'identity already linked to different user' do
- let!(:identity) { create(:identity, provider: provider, extern_uid: uid) }
+ let!(:identity) { create(:identity, provider: provider, extern_uid: uid) }
it "#changed? returns false" do
subject.link
diff --git a/spec/lib/gitlab/auth/user_auth_finders_spec.rb b/spec/lib/gitlab/auth/user_auth_finders_spec.rb
index 4e4c8b215c2..1e2aebdc84b 100644
--- a/spec/lib/gitlab/auth/user_auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/user_auth_finders_spec.rb
@@ -9,7 +9,7 @@ describe Gitlab::Auth::UserAuthFinders do
'rack.input' => ''
}
end
- let(:request) { Rack::Request.new(env) }
+ let(:request) { ActionDispatch::Request.new(env) }
def set_param(key, value)
request.update_param(key, value)
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index 9ccd0b206cc..a4a6338961e 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -19,7 +19,7 @@ describe Gitlab::Auth do
it 'optional_scopes contains all non-default scopes' do
stub_container_registry_config(enabled: true)
- expect(subject.optional_scopes).to eq %i[read_user sudo read_repository read_registry openid]
+ expect(subject.optional_scopes).to eq %i[read_user sudo read_repository read_registry openid profile email]
end
context 'registry_scopes' do
@@ -380,7 +380,7 @@ describe Gitlab::Auth do
password: password,
password_confirmation: password)
end
- let(:username) { 'John' } # username isn't lowercase, test this
+ let(:username) { 'John' } # username isn't lowercase, test this
let(:password) { 'my-secret' }
it "finds user by valid login/password" do
diff --git a/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb
index ae4b53d62e6..947c99b860f 100644
--- a/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb
@@ -2,6 +2,6 @@
require 'spec_helper'
-describe Gitlab::BackgroundMigration::BackfillLegacyProjectRepositories, :migration, schema: 20181218192239 do
+describe Gitlab::BackgroundMigration::BackfillLegacyProjectRepositories, :migration, schema: 20181212171634 do
it_behaves_like 'backfill migration for project repositories', :legacy
end
diff --git a/spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb
index 53c071f0268..510a0074554 100644
--- a/spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb
@@ -2,6 +2,7 @@
require 'spec_helper'
+# rubocop:disable RSpec/FactoriesInMigrationSpecs
describe Gitlab::BackgroundMigration::BackfillProjectRepositories do
let(:group) { create(:group, name: 'foo', path: 'foo') }
@@ -34,6 +35,7 @@ describe Gitlab::BackgroundMigration::BackfillProjectRepositories do
let!(:project_hashed_storage_2) { create(:project, name: 'bar', path: 'bar', namespace: group, storage_version: 2) }
let!(:project_legacy_storage_3) { create(:project, name: 'baz', path: 'baz', namespace: group, storage_version: 0) }
let!(:project_legacy_storage_4) { create(:project, name: 'zoo', path: 'zoo', namespace: group, storage_version: nil) }
+ let!(:project_legacy_storage_5) { create(:project, name: 'test', path: 'test', namespace: group, storage_version: nil) }
describe '.on_hashed_storage' do
it 'finds projects with repository on hashed storage' do
@@ -47,7 +49,7 @@ describe Gitlab::BackgroundMigration::BackfillProjectRepositories do
it 'finds projects with repository on legacy storage' do
projects = described_class.on_legacy_storage.pluck(:id)
- expect(projects).to match_array([project_legacy_storage_3.id, project_legacy_storage_4.id])
+ expect(projects).to match_array([project_legacy_storage_3.id, project_legacy_storage_4.id, project_legacy_storage_5.id])
end
end
@@ -58,7 +60,7 @@ describe Gitlab::BackgroundMigration::BackfillProjectRepositories do
projects = described_class.without_project_repository.pluck(:id)
- expect(projects).to contain_exactly(project_hashed_storage_2.id, project_legacy_storage_4.id)
+ expect(projects).to contain_exactly(project_hashed_storage_2.id, project_legacy_storage_4.id, project_legacy_storage_5.id)
end
end
@@ -78,17 +80,27 @@ describe Gitlab::BackgroundMigration::BackfillProjectRepositories do
expect(project.disk_path).to eq(project_legacy_storage_3.disk_path)
end
+ it 'returns the correct disk_path using the route entry' do
+ project_legacy_storage_5.route.update(path: 'zoo/new-test')
+ project = described_class.find(project_legacy_storage_5.id)
+
+ expect(project.disk_path).to eq('zoo/new-test')
+ end
+
it 'raises OrphanedNamespaceError when any parent namespace does not exist' do
subgroup = create(:group, parent: group)
project_orphaned_namespace = create(:project, name: 'baz', path: 'baz', namespace: subgroup, storage_version: nil)
subgroup.update_column(:parent_id, Namespace.maximum(:id).succ)
project = described_class.find(project_orphaned_namespace.id)
+ project.route.destroy
+ subgroup.route.destroy
- expect { project.disk_path }
+ expect { project.reload.disk_path }
.to raise_error(Gitlab::BackgroundMigration::BackfillProjectRepositories::OrphanedNamespaceError)
end
end
end
end
end
+# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/create_gpg_key_subkeys_from_gpg_keys_spec.rb b/spec/lib/gitlab/background_migration/create_gpg_key_subkeys_from_gpg_keys_spec.rb
index f92acf61682..f974dc8fda2 100644
--- a/spec/lib/gitlab/background_migration/create_gpg_key_subkeys_from_gpg_keys_spec.rb
+++ b/spec/lib/gitlab/background_migration/create_gpg_key_subkeys_from_gpg_keys_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::BackgroundMigration::CreateGpgKeySubkeysFromGpgKeys, :migration, schema: 20171005130944 do
context 'when GpgKey exists' do
- let!(:gpg_key) { create(:gpg_key, key: GpgHelpers::User3.public_key) }
+ let!(:gpg_key) { create(:gpg_key, key: GpgHelpers::User3.public_key) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
before do
GpgKeySubkey.destroy_all # rubocop: disable DestroyAll
diff --git a/spec/lib/gitlab/background_migration/delete_diff_files_spec.rb b/spec/lib/gitlab/background_migration/delete_diff_files_spec.rb
index 1969aed51da..27281333348 100644
--- a/spec/lib/gitlab/background_migration/delete_diff_files_spec.rb
+++ b/spec/lib/gitlab/background_migration/delete_diff_files_spec.rb
@@ -1,5 +1,6 @@
require 'spec_helper'
+# rubocop:disable RSpec/FactoriesInMigrationSpecs
describe Gitlab::BackgroundMigration::DeleteDiffFiles, :migration, :sidekiq, schema: 20180619121030 do
describe '#perform' do
context 'when diff files can be deleted' do
@@ -71,3 +72,4 @@ describe Gitlab::BackgroundMigration::DeleteDiffFiles, :migration, :sidekiq, sch
end
end
end
+# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
index 5dce3fcbcb6..bc71a90605a 100644
--- a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
+++ b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
@@ -1,5 +1,6 @@
require 'spec_helper'
+# rubocop:disable RSpec/FactoriesInMigrationSpecs
describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :migration, schema: 20171114162227 do
include GitHelpers
@@ -324,3 +325,4 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :m
end
end
end
+# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/digest_column_spec.rb b/spec/lib/gitlab/background_migration/digest_column_spec.rb
index 3e107ac3027..a25dcb06005 100644
--- a/spec/lib/gitlab/background_migration/digest_column_spec.rb
+++ b/spec/lib/gitlab/background_migration/digest_column_spec.rb
@@ -22,7 +22,7 @@ describe Gitlab::BackgroundMigration::DigestColumn, :migration, schema: 20180913
it 'erases token' do
expect { subject.perform(PersonalAccessToken, :token, :token_digest, 1, 2) }.to(
- change { PersonalAccessToken.find(1).token }.from('token-01').to(nil))
+ change { PersonalAccessToken.find(1).read_attribute(:token) }.from('token-01').to(nil))
end
end
@@ -39,7 +39,7 @@ describe Gitlab::BackgroundMigration::DigestColumn, :migration, schema: 20180913
it 'leaves token empty' do
expect { subject.perform(PersonalAccessToken, :token, :token_digest, 1, 2) }.not_to(
- change { PersonalAccessToken.find(1).token }.from(nil))
+ change { PersonalAccessToken.find(1).read_attribute(:token) }.from(nil))
end
end
end
diff --git a/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb b/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb
index 5432d270555..188969951a6 100644
--- a/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb
@@ -1,5 +1,6 @@
require 'spec_helper'
+# rubocop:disable RSpec/FactoriesInMigrationSpecs
describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads::Event, :migration, schema: 20170608152748 do
describe '#commit_title' do
it 'returns nil when there are no commits' do
@@ -429,3 +430,4 @@ describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads, :migrati
end
end
end
+# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder_spec.rb b/spec/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder_spec.rb
index 021e1d14b18..ea8bdd48e72 100644
--- a/spec/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder_spec.rb
@@ -1,5 +1,6 @@
require 'spec_helper'
+# rubocop:disable RSpec/FactoriesInMigrationSpecs
describe Gitlab::BackgroundMigration::MigrateSystemUploadsToNewFolder, :delete do
let(:migration) { described_class.new }
@@ -17,3 +18,4 @@ describe Gitlab::BackgroundMigration::MigrateSystemUploadsToNewFolder, :delete d
end
end
end
+# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/move_personal_snippet_files_spec.rb b/spec/lib/gitlab/background_migration/move_personal_snippet_files_spec.rb
index 2e77e80ee46..593486fc56c 100644
--- a/spec/lib/gitlab/background_migration/move_personal_snippet_files_spec.rb
+++ b/spec/lib/gitlab/background_migration/move_personal_snippet_files_spec.rb
@@ -1,5 +1,6 @@
require 'spec_helper'
+# rubocop:disable RSpec/FactoriesInMigrationSpecs
describe Gitlab::BackgroundMigration::MovePersonalSnippetFiles do
let(:test_dir) { File.join(Rails.root, 'tmp', 'tests', 'move_snippet_files_test') }
let(:old_uploads_dir) { File.join('uploads', 'system', 'personal_snippet') }
@@ -70,3 +71,4 @@ describe Gitlab::BackgroundMigration::MovePersonalSnippetFiles do
"[an upload](#{path})"
end
end
+# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb b/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb
index 4f1b01eed41..812e0cc6947 100644
--- a/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb
@@ -3,90 +3,87 @@
require 'spec_helper'
describe Gitlab::BackgroundMigration::PopulateClusterKubernetesNamespaceTable, :migration, schema: 20181022173835 do
+ include MigrationHelpers::ClusterHelpers
+
let(:migration) { described_class.new }
- let(:clusters) { create_list(:cluster, 10, :project, :provided_by_gcp) }
+ let(:clusters_table) { table(:clusters) }
+ let(:cluster_projects_table) { table(:cluster_projects) }
+ let(:cluster_kubernetes_namespaces_table) { table(:clusters_kubernetes_namespaces) }
+ let(:projects_table) { table(:projects) }
+ let(:namespaces_table) { table(:namespaces) }
+ let(:provider_gcp_table) { table(:cluster_providers_gcp) }
+ let(:platform_kubernetes_table) { table(:cluster_platforms_kubernetes) }
before do
- clusters
+ create_cluster_project_list(10)
end
shared_examples 'consistent kubernetes namespace attributes' do
it 'should populate namespace and service account information' do
- subject
+ migration.perform
clusters_with_namespace.each do |cluster|
- project = cluster.project
- cluster_project = cluster.cluster_projects.first
+ cluster_project = cluster_projects_table.find_by(cluster_id: cluster.id)
+ project = projects_table.find(cluster_project.project_id)
+ kubernetes_namespace = cluster_kubernetes_namespaces_table.find_by(cluster_id: cluster.id)
namespace = "#{project.path}-#{project.id}"
- kubernetes_namespace = cluster.reload.kubernetes_namespace
expect(kubernetes_namespace).to be_present
- expect(kubernetes_namespace.cluster_project).to eq(cluster_project)
- expect(kubernetes_namespace.project).to eq(cluster_project.project)
- expect(kubernetes_namespace.cluster).to eq(cluster_project.cluster)
+ expect(kubernetes_namespace.cluster_project_id).to eq(cluster_project.id)
+ expect(kubernetes_namespace.project_id).to eq(cluster_project.project_id)
+ expect(kubernetes_namespace.cluster_id).to eq(cluster_project.cluster_id)
expect(kubernetes_namespace.namespace).to eq(namespace)
expect(kubernetes_namespace.service_account_name).to eq("#{namespace}-service-account")
end
end
end
- subject { migration.perform }
-
context 'when no Clusters::Project has a Clusters::KubernetesNamespace' do
- let(:cluster_projects) { Clusters::Project.all }
+ let(:cluster_projects) { cluster_projects_table.all }
it 'should create a Clusters::KubernetesNamespace per Clusters::Project' do
expect do
- subject
- end.to change(Clusters::KubernetesNamespace, :count).by(cluster_projects.count)
+ migration.perform
+ end.to change(Clusters::KubernetesNamespace, :count).by(cluster_projects_table.count)
end
it_behaves_like 'consistent kubernetes namespace attributes' do
- let(:clusters_with_namespace) { clusters }
+ let(:clusters_with_namespace) { clusters_table.all }
end
end
context 'when every Clusters::Project has Clusters::KubernetesNamespace' do
before do
- clusters.each do |cluster|
- create(:cluster_kubernetes_namespace,
- cluster_project: cluster.cluster_projects.first,
- cluster: cluster,
- project: cluster.project)
- end
+ create_kubernetes_namespace(clusters_table.all)
end
it 'should not create any Clusters::KubernetesNamespace' do
expect do
- subject
+ migration.perform
end.not_to change(Clusters::KubernetesNamespace, :count)
end
end
context 'when only some Clusters::Project have Clusters::KubernetesNamespace related' do
- let(:with_kubernetes_namespace) { clusters.first(6) }
- let(:with_no_kubernetes_namespace) { clusters.last(4) }
+ let(:with_kubernetes_namespace) { clusters_table.first(6) }
+ let(:with_no_kubernetes_namespace) { clusters_table.last(4) }
before do
- with_kubernetes_namespace.each do |cluster|
- create(:cluster_kubernetes_namespace,
- cluster_project: cluster.cluster_projects.first,
- cluster: cluster,
- project: cluster.project)
- end
+ create_kubernetes_namespace(with_kubernetes_namespace)
end
it 'creates limited number of Clusters::KubernetesNamespace' do
expect do
- subject
+ migration.perform
end.to change(Clusters::KubernetesNamespace, :count).by(with_no_kubernetes_namespace.count)
end
it 'should not modify clusters with Clusters::KubernetesNamespace' do
- subject
+ migration.perform
with_kubernetes_namespace.each do |cluster|
- expect(cluster.kubernetes_namespaces.count).to eq(1)
+ kubernetes_namespace = cluster_kubernetes_namespaces_table.where(cluster_id: cluster.id)
+ expect(kubernetes_namespace.count).to eq(1)
end
end
diff --git a/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb b/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb
index c7b272cd6ca..3e009fed0f1 100644
--- a/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb
@@ -2,9 +2,15 @@
require 'spec_helper'
+# rubocop:disable RSpec/FactoriesInMigrationSpecs
describe Gitlab::BackgroundMigration::PopulateExternalPipelineSource, :migration, schema: 20180916011959 do
let(:migration) { described_class.new }
+ before do
+ # This migration was created before we introduced metadata configs
+ stub_feature_flags(ci_build_metadata_config: false)
+ end
+
let!(:internal_pipeline) { create(:ci_pipeline, source: :web) }
let(:pipelines) { [internal_pipeline, unknown_pipeline].map(&:id) }
@@ -60,3 +66,4 @@ describe Gitlab::BackgroundMigration::PopulateExternalPipelineSource, :migration
it_behaves_like 'no changes'
end
end
+# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/populate_import_state_spec.rb b/spec/lib/gitlab/background_migration/populate_import_state_spec.rb
index f9952ee5163..fcb869022de 100644
--- a/spec/lib/gitlab/background_migration/populate_import_state_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_import_state_spec.rb
@@ -4,7 +4,7 @@ describe Gitlab::BackgroundMigration::PopulateImportState, :migration, schema: 2
let(:migration) { described_class.new }
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
- let(:import_state) { table(:project_mirror_data) }
+ let(:import_state) { table(:project_mirror_data) }
before do
namespaces.create(id: 1, name: 'gitlab-org', path: 'gitlab-org')
diff --git a/spec/lib/gitlab/background_migration/populate_merge_request_metrics_with_events_data_spec.rb b/spec/lib/gitlab/background_migration/populate_merge_request_metrics_with_events_data_spec.rb
index e99257e3481..ff1bd9f7850 100644
--- a/spec/lib/gitlab/background_migration/populate_merge_request_metrics_with_events_data_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_merge_request_metrics_with_events_data_spec.rb
@@ -1,5 +1,6 @@
require 'rails_helper'
+# rubocop:disable RSpec/FactoriesInMigrationSpecs
describe Gitlab::BackgroundMigration::PopulateMergeRequestMetricsWithEventsData, :migration, schema: 20171128214150 do
# commits_count attribute is added in a next migration
before do
@@ -128,3 +129,4 @@ describe Gitlab::BackgroundMigration::PopulateMergeRequestMetricsWithEventsData,
end
end
end
+# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/rollback_import_state_data_spec.rb b/spec/lib/gitlab/background_migration/rollback_import_state_data_spec.rb
index 9f8c3bc220f..cef3b6e4568 100644
--- a/spec/lib/gitlab/background_migration/rollback_import_state_data_spec.rb
+++ b/spec/lib/gitlab/background_migration/rollback_import_state_data_spec.rb
@@ -4,7 +4,7 @@ describe Gitlab::BackgroundMigration::RollbackImportStateData, :migration, schem
let(:migration) { described_class.new }
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
- let(:import_state) { table(:project_mirror_data) }
+ let(:import_state) { table(:project_mirror_data) }
before do
namespaces.create(id: 1, name: 'gitlab-org', path: 'gitlab-org')
diff --git a/spec/lib/gitlab/background_migration_spec.rb b/spec/lib/gitlab/background_migration_spec.rb
index 4ad69aeba43..7d3d8a949ef 100644
--- a/spec/lib/gitlab/background_migration_spec.rb
+++ b/spec/lib/gitlab/background_migration_spec.rb
@@ -104,6 +104,38 @@ describe Gitlab::BackgroundMigration do
end
end
end
+
+ context 'when retry_dead_jobs is true', :sidekiq, :redis do
+ let(:retry_queue) do
+ [double(args: ['Object', [3]], queue: described_class.queue, delete: true)]
+ end
+ let(:dead_queue) do
+ [double(args: ['Object', [4]], queue: described_class.queue, delete: true)]
+ end
+
+ before do
+ allow(Sidekiq::RetrySet).to receive(:new).and_return(retry_queue)
+ allow(Sidekiq::DeadSet).to receive(:new).and_return(dead_queue)
+ end
+
+ it 'steals from the dead and retry queue' do
+ Sidekiq::Testing.disable! do
+ expect(described_class).to receive(:perform)
+ .with('Object', [1]).ordered
+ expect(described_class).to receive(:perform)
+ .with('Object', [2]).ordered
+ expect(described_class).to receive(:perform)
+ .with('Object', [3]).ordered
+ expect(described_class).to receive(:perform)
+ .with('Object', [4]).ordered
+
+ BackgroundMigrationWorker.perform_async('Object', [2])
+ BackgroundMigrationWorker.perform_in(10.minutes, 'Object', [1])
+
+ described_class.steal('Object', retry_dead_jobs: true)
+ end
+ end
+ end
end
describe '.perform' do
@@ -119,4 +151,48 @@ describe Gitlab::BackgroundMigration do
described_class.perform('Foo', [10, 20])
end
end
+
+ describe '.exists?' do
+ context 'when there are enqueued jobs present' do
+ let(:queue) do
+ [double(args: ['Foo', [10, 20]], queue: described_class.queue)]
+ end
+
+ before do
+ allow(Sidekiq::Queue).to receive(:new)
+ .with(described_class.queue)
+ .and_return(queue)
+ end
+
+ it 'returns true if specific job exists' do
+ expect(described_class.exists?('Foo')).to eq(true)
+ end
+
+ it 'returns false if specific job does not exist' do
+ expect(described_class.exists?('Bar')).to eq(false)
+ end
+ end
+
+ context 'when there are scheduled jobs present', :sidekiq, :redis do
+ before do
+ Sidekiq::Testing.disable! do
+ BackgroundMigrationWorker.perform_in(10.minutes, 'Foo')
+
+ expect(Sidekiq::ScheduledSet.new).to be_one
+ end
+ end
+
+ after do
+ Sidekiq::ScheduledSet.new.clear
+ end
+
+ it 'returns true if specific job exists' do
+ expect(described_class.exists?('Foo')).to eq(true)
+ end
+
+ it 'returns false if specific job does not exist' do
+ expect(described_class.exists?('Bar')).to eq(false)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/bare_repository_import/repository_spec.rb b/spec/lib/gitlab/bare_repository_import/repository_spec.rb
index afd8f5da39f..a07c5371134 100644
--- a/spec/lib/gitlab/bare_repository_import/repository_spec.rb
+++ b/spec/lib/gitlab/bare_repository_import/repository_spec.rb
@@ -61,7 +61,7 @@ describe ::Gitlab::BareRepositoryImport::Repository do
let(:wiki_path) { File.join(root_path, "#{hashed_path}.wiki.git") }
before do
- gitlab_shell.create_repository(repository_storage, hashed_path)
+ gitlab_shell.create_repository(repository_storage, hashed_path, 'group/project')
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repository = Rugged::Repository.new(repo_path)
repository.config['gitlab.fullpath'] = 'to/repo'
diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
index 7a681bc6610..c432cc223b9 100644
--- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
@@ -15,7 +15,7 @@ describe Gitlab::BitbucketImport::Importer do
"invalid",
"duplicate",
"wontfix",
- "closed" # undocumented status
+ "closed" # undocumented status
]
end
@@ -218,7 +218,7 @@ describe Gitlab::BitbucketImport::Importer do
describe 'wiki import' do
it 'is skipped when the wiki exists' do
expect(project.wiki).to receive(:repository_exists?) { true }
- expect(importer.gitlab_shell).not_to receive(:import_repository)
+ expect(importer.gitlab_shell).not_to receive(:import_wiki_repository)
importer.execute
@@ -227,11 +227,7 @@ describe Gitlab::BitbucketImport::Importer do
it 'imports to the project disk_path' do
expect(project.wiki).to receive(:repository_exists?) { false }
- expect(importer.gitlab_shell).to receive(:import_repository).with(
- project.repository_storage,
- project.wiki.disk_path,
- project.import_url + '/wiki'
- )
+ expect(importer.gitlab_shell).to receive(:import_wiki_repository)
importer.execute
diff --git a/spec/lib/gitlab/bitbucket_import/wiki_formatter_spec.rb b/spec/lib/gitlab/bitbucket_import/wiki_formatter_spec.rb
new file mode 100644
index 00000000000..795fd069ab2
--- /dev/null
+++ b/spec/lib/gitlab/bitbucket_import/wiki_formatter_spec.rb
@@ -0,0 +1,29 @@
+require 'spec_helper'
+
+describe Gitlab::BitbucketImport::WikiFormatter do
+ let(:project) do
+ create(:project,
+ namespace: create(:namespace, path: 'gitlabhq'),
+ import_url: 'https://xxx@bitbucket.org/gitlabhq/sample.gitlabhq.git')
+ end
+
+ subject(:wiki) { described_class.new(project) }
+
+ describe '#disk_path' do
+ it 'appends .wiki to disk path' do
+ expect(wiki.disk_path).to eq project.wiki.disk_path
+ end
+ end
+
+ describe '#full_path' do
+ it 'appends .wiki to project path' do
+ expect(wiki.full_path).to eq project.wiki.full_path
+ end
+ end
+
+ describe '#import_url' do
+ it 'returns URL of the wiki repository' do
+ expect(wiki.import_url).to eq 'https://xxx@bitbucket.org/gitlabhq/sample.gitlabhq.git/wiki'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
index 70423823b89..1e90a2ef27f 100644
--- a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
@@ -21,12 +21,9 @@ describe Gitlab::BitbucketServerImport::Importer do
end
describe '#import_repository' do
- before do
+ it 'adds a remote' do
expect(subject).to receive(:import_pull_requests)
expect(subject).to receive(:delete_temp_branches)
- end
-
- it 'adds a remote' do
expect(project.repository).to receive(:fetch_as_mirror)
.with('http://bitbucket:test@my-bitbucket',
refmap: [:heads, :tags, '+refs/pull-requests/*/to:refs/merge-requests/*/head'],
@@ -34,6 +31,18 @@ describe Gitlab::BitbucketServerImport::Importer do
subject.execute
end
+
+ it 'raises a Gitlab::Shell exception in the fetch' do
+ expect(project.repository).to receive(:fetch_as_mirror).and_raise(Gitlab::Shell::Error)
+
+ expect { subject.execute }.to raise_error(Gitlab::Shell::Error)
+ end
+
+ it 'raises an unhandled exception in the fetch' do
+ expect(project.repository).to receive(:fetch_as_mirror).and_raise(RuntimeError)
+
+ expect { subject.execute }.to raise_error(RuntimeError)
+ end
end
describe '#import_pull_requests' do
diff --git a/spec/lib/gitlab/blob_helper_spec.rb b/spec/lib/gitlab/blob_helper_spec.rb
index 0b56f8687c3..e057385b35f 100644
--- a/spec/lib/gitlab/blob_helper_spec.rb
+++ b/spec/lib/gitlab/blob_helper_spec.rb
@@ -53,11 +53,11 @@ describe Gitlab::BlobHelper do
describe '#text?' do
it 'returns true' do
- expect(blob.text?).to be_truthy
+ expect(blob.text_in_repo?).to be_truthy
end
it 'returns false' do
- expect(large_blob.text?).to be_falsey
+ expect(large_blob.text_in_repo?).to be_falsey
end
end
diff --git a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
index be9b2588c90..483c5ea9cff 100644
--- a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
+++ b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
@@ -238,7 +238,7 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do
end
describe '#delete_from_cache' do
- it 'deletes values from redis_cache' do
+ it 'deletes values from redis_cache' do
pipeline_status.delete_from_cache
key_exists = Gitlab::Redis::Cache.with { |redis| redis.exists(cache_key) }
diff --git a/spec/lib/gitlab/chat/command_spec.rb b/spec/lib/gitlab/chat/command_spec.rb
new file mode 100644
index 00000000000..46d23ab2b62
--- /dev/null
+++ b/spec/lib/gitlab/chat/command_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Chat::Command do
+ let(:chat_name) { create(:chat_name) }
+
+ let(:command) do
+ described_class.new(
+ project: project,
+ chat_name: chat_name,
+ name: 'spinach',
+ arguments: 'foo',
+ channel: '123',
+ response_url: 'http://example.com'
+ )
+ end
+
+ describe '#try_create_pipeline' do
+ let(:project) { create(:project) }
+
+ it 'returns nil when the command is not valid' do
+ expect(command)
+ .to receive(:valid?)
+ .and_return(false)
+
+ expect(command.try_create_pipeline).to be_nil
+ end
+
+ it 'tries to create the pipeline when a command is valid' do
+ expect(command)
+ .to receive(:valid?)
+ .and_return(true)
+
+ expect(command)
+ .to receive(:create_pipeline)
+
+ command.try_create_pipeline
+ end
+ end
+
+ describe '#create_pipeline' do
+ let(:project) { create(:project, :test_repo) }
+ let(:pipeline) { command.create_pipeline }
+
+ before do
+ stub_repository_ci_yaml_file(sha: project.commit.id)
+
+ project.add_developer(chat_name.user)
+ end
+
+ it 'creates the pipeline' do
+ expect(pipeline).to be_persisted
+ end
+
+ it 'creates the chat data for the pipeline' do
+ expect(pipeline.chat_data).to be_an_instance_of(Ci::PipelineChatData)
+ end
+
+ it 'stores the chat name ID in the chat data' do
+ expect(pipeline.chat_data.chat_name_id).to eq(chat_name.id)
+ end
+
+ it 'stores the response URL in the chat data' do
+ expect(pipeline.chat_data.response_url).to eq('http://example.com')
+ end
+
+ it 'creates the environment variables for the pipeline' do
+ vars = pipeline.variables.each_with_object({}) do |row, hash|
+ hash[row.key] = row.value
+ end
+
+ expect(vars['CHAT_INPUT']).to eq('foo')
+ expect(vars['CHAT_CHANNEL']).to eq('123')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/chat/output_spec.rb b/spec/lib/gitlab/chat/output_spec.rb
new file mode 100644
index 00000000000..b179f9e9d0a
--- /dev/null
+++ b/spec/lib/gitlab/chat/output_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Chat::Output do
+ let(:build) do
+ create(:ci_build, pipeline: create(:ci_pipeline, source: :chat))
+ end
+
+ let(:output) { described_class.new(build) }
+
+ describe '#to_s' do
+ it 'returns the build output as a String' do
+ trace = Gitlab::Ci::Trace.new(build)
+
+ trace.set("echo hello\nhello")
+
+ allow(build)
+ .to receive(:trace)
+ .and_return(trace)
+
+ allow(output)
+ .to receive(:read_offset_and_length)
+ .and_return([0, 13])
+
+ expect(output.to_s).to eq('he')
+ end
+ end
+
+ describe '#read_offset_and_length' do
+ context 'without the chat_reply trace section' do
+ it 'falls back to using the build_script trace section' do
+ expect(output)
+ .to receive(:find_build_trace_section)
+ .with('chat_reply')
+ .and_return(nil)
+
+ expect(output)
+ .to receive(:find_build_trace_section)
+ .with('build_script')
+ .and_return({ name: 'build_script', byte_start: 1, byte_end: 4 })
+
+ expect(output.read_offset_and_length).to eq([1, 3])
+ end
+ end
+
+ context 'without the build_script trace section' do
+ it 'raises MissingBuildSectionError' do
+ expect { output.read_offset_and_length }
+ .to raise_error(described_class::MissingBuildSectionError)
+ end
+ end
+
+ context 'with the chat_reply trace section' do
+ it 'returns the read offset and length as an Array' do
+ trace = Gitlab::Ci::Trace.new(build)
+
+ allow(build)
+ .to receive(:trace)
+ .and_return(trace)
+
+ allow(trace)
+ .to receive(:extract_sections)
+ .and_return([{ name: 'chat_reply', byte_start: 1, byte_end: 4 }])
+
+ expect(output.read_offset_and_length).to eq([1, 3])
+ end
+ end
+ end
+
+ describe '#without_executed_command_line' do
+ it 'returns the input without the first line' do
+ expect(output.without_executed_command_line("hello\nworld"))
+ .to eq('world')
+ end
+
+ it 'returns an empty String when the input is empty' do
+ expect(output.without_executed_command_line('')).to eq('')
+ end
+
+ it 'returns an empty String when the input consits of a single newline' do
+ expect(output.without_executed_command_line("\n")).to eq('')
+ end
+ end
+
+ describe '#find_build_trace_section' do
+ it 'returns nil when no section could be found' do
+ expect(output.find_build_trace_section('foo')).to be_nil
+ end
+
+ it 'returns the trace section when it could be found' do
+ section = { name: 'chat_reply', byte_start: 1, byte_end: 4 }
+
+ allow(output)
+ .to receive(:trace_sections)
+ .and_return([section])
+
+ expect(output.find_build_trace_section('chat_reply')).to eq(section)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/chat/responder/base_spec.rb b/spec/lib/gitlab/chat/responder/base_spec.rb
new file mode 100644
index 00000000000..7fa9bad9d38
--- /dev/null
+++ b/spec/lib/gitlab/chat/responder/base_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Chat::Responder::Base do
+ let(:project) { double(:project) }
+ let(:pipeline) { double(:pipeline, project: project) }
+ let(:build) { double(:build, pipeline: pipeline) }
+ let(:responder) { described_class.new(build) }
+
+ describe '#pipeline' do
+ it 'returns the pipeline' do
+ expect(responder.pipeline).to eq(pipeline)
+ end
+ end
+
+ describe '#project' do
+ it 'returns the project' do
+ expect(responder.project).to eq(project)
+ end
+ end
+
+ describe '#success' do
+ it 'raises NotImplementedError' do
+ expect { responder.success }.to raise_error(NotImplementedError)
+ end
+ end
+
+ describe '#failure' do
+ it 'raises NotImplementedError' do
+ expect { responder.failure }.to raise_error(NotImplementedError)
+ end
+ end
+
+ describe '#send_response' do
+ it 'raises NotImplementedError' do
+ expect { responder.send_response('hello') }
+ .to raise_error(NotImplementedError)
+ end
+ end
+
+ describe '#scheduled_output' do
+ it 'raises NotImplementedError' do
+ expect { responder.scheduled_output }
+ .to raise_error(NotImplementedError)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/chat/responder/slack_spec.rb b/spec/lib/gitlab/chat/responder/slack_spec.rb
new file mode 100644
index 00000000000..a1553232b32
--- /dev/null
+++ b/spec/lib/gitlab/chat/responder/slack_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Chat::Responder::Slack do
+ let(:chat_name) { create(:chat_name, chat_id: 'U123') }
+
+ let(:pipeline) do
+ pipeline = create(:ci_pipeline)
+
+ pipeline.create_chat_data!(
+ response_url: 'http://example.com',
+ chat_name_id: chat_name.id
+ )
+
+ pipeline
+ end
+
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+ let(:responder) { described_class.new(build) }
+
+ describe '#send_response' do
+ it 'sends a response back to Slack' do
+ expect(Gitlab::HTTP).to receive(:post).with(
+ 'http://example.com',
+ { headers: { Accept: 'application/json' }, body: 'hello'.to_json }
+ )
+
+ responder.send_response('hello')
+ end
+ end
+
+ describe '#success' do
+ it 'returns the output for a successful build' do
+ expect(responder)
+ .to receive(:send_response)
+ .with(hash_including(text: /<@U123>:.+hello/, response_type: :in_channel))
+
+ responder.success('hello')
+ end
+
+ it 'limits the output to a fixed size' do
+ expect(responder)
+ .to receive(:send_response)
+ .with(hash_including(text: /The output is too large/))
+
+ responder.success('a' * 4000)
+ end
+
+ it 'does not send a response if the output is empty' do
+ expect(responder).not_to receive(:send_response)
+
+ responder.success('')
+ end
+ end
+
+ describe '#failure' do
+ it 'returns the output for a failed build' do
+ expect(responder).to receive(:send_response).with(
+ hash_including(
+ text: /<@U123>:.+Sorry, the build failed!/,
+ response_type: :in_channel
+ )
+ )
+
+ responder.failure
+ end
+ end
+
+ describe '#scheduled_output' do
+ it 'returns the output for a scheduled build' do
+ output = responder.scheduled_output
+
+ expect(output).to eq({ text: '' })
+ end
+ end
+end
diff --git a/spec/lib/gitlab/chat/responder_spec.rb b/spec/lib/gitlab/chat/responder_spec.rb
new file mode 100644
index 00000000000..9893689cba9
--- /dev/null
+++ b/spec/lib/gitlab/chat/responder_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Chat::Responder do
+ describe '.responder_for' do
+ context 'using a regular build' do
+ it 'returns nil' do
+ build = create(:ci_build)
+
+ expect(described_class.responder_for(build)).to be_nil
+ end
+ end
+
+ context 'using a chat build' do
+ it 'returns the responder for the build' do
+ pipeline = create(:ci_pipeline)
+ build = create(:ci_build, pipeline: pipeline)
+ service = double(:service, chat_responder: Gitlab::Chat::Responder::Slack)
+ chat_name = double(:chat_name, service: service)
+ chat_data = double(:chat_data, chat_name: chat_name)
+
+ allow(pipeline)
+ .to receive(:chat_data)
+ .and_return(chat_data)
+
+ expect(described_class.responder_for(build))
+ .to be_an_instance_of(Gitlab::Chat::Responder::Slack)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/chat_spec.rb b/spec/lib/gitlab/chat_spec.rb
new file mode 100644
index 00000000000..d61c4b36668
--- /dev/null
+++ b/spec/lib/gitlab/chat_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe Gitlab::Chat, :use_clean_rails_memory_store_caching do
+ describe '.available?' do
+ it 'returns true when the chatops feature is available' do
+ allow(Feature)
+ .to receive(:enabled?)
+ .with(:chatops, default_enabled: true)
+ .and_return(true)
+
+ expect(described_class).to be_available
+ end
+
+ it 'returns false when the chatops feature is not available' do
+ allow(Feature)
+ .to receive(:enabled?)
+ .with(:chatops, default_enabled: true)
+ .and_return(false)
+
+ expect(described_class).not_to be_available
+ end
+ end
+end
diff --git a/spec/lib/gitlab/checks/branch_check_spec.rb b/spec/lib/gitlab/checks/branch_check_spec.rb
index 77366e91dca..12beeecd470 100644
--- a/spec/lib/gitlab/checks/branch_check_spec.rb
+++ b/spec/lib/gitlab/checks/branch_check_spec.rb
@@ -48,10 +48,128 @@ describe Gitlab::Checks::BranchCheck do
context 'when project repository is empty' do
let(:project) { create(:project) }
- it 'raises an error if the user is not allowed to push to protected branches' do
- expect(user_access).to receive(:can_push_to_branch?).and_return(false)
+ context 'user is not allowed to push to protected branches' do
+ before do
+ allow(user_access)
+ .to receive(:can_push_to_branch?)
+ .and_return(false)
+ end
+
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /Ask a project Owner or Maintainer to create a default branch/)
+ end
+ end
+
+ context 'user is allowed to push to protected branches' do
+ before do
+ allow(user_access)
+ .to receive(:can_push_to_branch?)
+ .and_return(true)
+ end
+
+ it 'allows branch creation' do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+ end
+
+ context 'branch creation' do
+ let(:oldrev) { '0000000000000000000000000000000000000000' }
+ let(:ref) { 'refs/heads/feature' }
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /Ask a project Owner or Maintainer to create a default branch/)
+ context 'protected branch creation feature is disabled' do
+ before do
+ stub_feature_flags(protected_branch_creation: false)
+ end
+
+ context 'user is not allowed to push to protected branch' do
+ before do
+ allow(user_access)
+ .to receive(:can_push_to_branch?)
+ .and_return(false)
+ end
+
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to protected branches on this project.')
+ end
+ end
+
+ context 'user is allowed to push to protected branch' do
+ before do
+ allow(user_access)
+ .to receive(:can_push_to_branch?)
+ .and_return(true)
+ end
+
+ it 'does not raise an error' do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+ end
+
+ context 'protected branch creation feature is enabled' do
+ context 'user is not allowed to create protected branches' do
+ before do
+ allow(user_access)
+ .to receive(:can_merge_to_branch?)
+ .with('feature')
+ .and_return(false)
+ end
+
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to create protected branches on this project.')
+ end
+ end
+
+ context 'user is allowed to create protected branches' do
+ before do
+ allow(user_access)
+ .to receive(:can_merge_to_branch?)
+ .with('feature')
+ .and_return(true)
+
+ allow(project.repository)
+ .to receive(:branch_names_contains_sha)
+ .with(newrev)
+ .and_return(['branch'])
+ end
+
+ context "newrev isn't in any protected branches" do
+ before do
+ allow(ProtectedBranch)
+ .to receive(:any_protected?)
+ .with(project, ['branch'])
+ .and_return(false)
+ end
+
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only use an existing protected branch ref as the basis of a new protected branch.')
+ end
+ end
+
+ context 'newrev is included in a protected branch' do
+ before do
+ allow(ProtectedBranch)
+ .to receive(:any_protected?)
+ .with(project, ['branch'])
+ .and_return(true)
+ end
+
+ context 'via web interface' do
+ let(:protocol) { 'web' }
+
+ it 'allows branch creation' do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+
+ context 'via SSH' do
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only create protected branches using the web interface and API.')
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/checks/diff_check_spec.rb b/spec/lib/gitlab/checks/diff_check_spec.rb
index eeec1e83179..a341dfa5636 100644
--- a/spec/lib/gitlab/checks/diff_check_spec.rb
+++ b/spec/lib/gitlab/checks/diff_check_spec.rb
@@ -47,5 +47,43 @@ describe Gitlab::Checks::DiffCheck do
end
end
end
+
+ context 'commit diff validations' do
+ before do
+ allow(subject).to receive(:validations_for_diff).and_return([lambda { |diff| return }])
+
+ expect_any_instance_of(Commit).to receive(:raw_deltas).and_call_original
+
+ subject.validate!
+ end
+
+ context 'when request store is inactive' do
+ it 'are run for every commit' do
+ expect_any_instance_of(Commit).to receive(:raw_deltas).and_call_original
+
+ subject.validate!
+ end
+ end
+
+ context 'when request store is active', :request_store do
+ it 'are cached for every commit' do
+ expect_any_instance_of(Commit).not_to receive(:raw_deltas)
+
+ subject.validate!
+ end
+
+ it 'are run for not cached commits' do
+ allow(project.repository).to receive(:new_commits).and_return(
+ project.repository.commits_between('be93687618e4b132087f430a4d8fc3a609c9b77c', 'a5391128b0ef5d21df5dd23d98557f4ef12fae20')
+ )
+ change_access.instance_variable_set(:@commits, project.repository.new_commits)
+
+ expect(project.repository.new_commits.first).not_to receive(:raw_deltas).and_call_original
+ expect(project.repository.new_commits.last).to receive(:raw_deltas).and_call_original
+
+ subject.validate!
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/checks/push_check_spec.rb b/spec/lib/gitlab/checks/push_check_spec.rb
index 25f0d428cb9..e1bd52d6c0b 100644
--- a/spec/lib/gitlab/checks/push_check_spec.rb
+++ b/spec/lib/gitlab/checks/push_check_spec.rb
@@ -13,7 +13,7 @@ describe Gitlab::Checks::PushCheck do
context 'when the user is not allowed to push to the repo' do
it 'raises an error' do
expect(user_access).to receive(:can_do_action?).with(:push_code).and_return(false)
- expect(user_access).to receive(:can_push_to_branch?).with('master').and_return(false)
+ expect(project).to receive(:branch_allows_collaboration?).with(user_access.user, 'master').and_return(false)
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to this project.')
end
diff --git a/spec/lib/gitlab/ci/build/policy/changes_spec.rb b/spec/lib/gitlab/ci/build/policy/changes_spec.rb
index 5fee37bb43e..92cf0376c02 100644
--- a/spec/lib/gitlab/ci/build/policy/changes_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/changes_spec.rb
@@ -73,9 +73,9 @@ describe Gitlab::Ci::Build::Policy::Changes do
expect(policy).not_to be_satisfied_by(pipeline, seed)
end
- context 'when pipelines does not run for a branch update' do
+ context 'when modified paths can not be evaluated' do
before do
- pipeline.before_sha = Gitlab::Git::BLANK_SHA
+ allow(pipeline).to receive(:modified_paths) { nil }
end
it 'is always satisfied' do
@@ -115,5 +115,57 @@ describe Gitlab::Ci::Build::Policy::Changes do
expect(policy).not_to be_satisfied_by(pipeline, seed)
end
end
+
+ context 'when branch is created' do
+ let(:pipeline) do
+ create(:ci_empty_pipeline, project: project,
+ ref: 'feature',
+ source: source,
+ sha: '0b4bc9a4',
+ before_sha: Gitlab::Git::BLANK_SHA,
+ merge_request: merge_request)
+ end
+
+ let(:ci_build) do
+ build(:ci_build, pipeline: pipeline, project: project, ref: 'feature')
+ end
+
+ let(:seed) { double('build seed', to_resource: ci_build) }
+
+ context 'when source is merge request' do
+ let(:source) { :merge_request_event }
+
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: project,
+ source_branch: 'feature',
+ target_project: project,
+ target_branch: 'master')
+ end
+
+ it 'is satified by changes in the merge request' do
+ policy = described_class.new(%w[files/ruby/feature.rb])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+
+ it 'is not satified by changes not in the merge request' do
+ policy = described_class.new(%w[foo.rb])
+
+ expect(policy).not_to be_satisfied_by(pipeline, seed)
+ end
+ end
+
+ context 'when source is push' do
+ let(:source) { :push }
+ let(:merge_request) { nil }
+
+ it 'is always satified' do
+ policy = described_class.new(%w[foo.rb])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/build/policy/refs_spec.rb b/spec/lib/gitlab/ci/build/policy/refs_spec.rb
index 553fc0fb9bf..b4ddbf89b70 100644
--- a/spec/lib/gitlab/ci/build/policy/refs_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/refs_spec.rb
@@ -68,6 +68,20 @@ describe Gitlab::Ci::Build::Policy::Refs do
expect(described_class.new(%w[triggers]))
.not_to be_satisfied_by(pipeline)
end
+
+ context 'when source is merge_request_event' do
+ let(:pipeline) { build_stubbed(:ci_pipeline, source: :merge_request_event) }
+
+ it 'is satisfied with only: merge_request' do
+ expect(described_class.new(%w[merge_requests]))
+ .to be_satisfied_by(pipeline)
+ end
+
+ it 'is not satisfied with only: merge_request_event' do
+ expect(described_class.new(%w[merge_request_events]))
+ .not_to be_satisfied_by(pipeline)
+ end
+ end
end
context 'when matching a ref by a regular expression' do
diff --git a/spec/lib/gitlab/ci/build/policy/variables_spec.rb b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
index c2c0742efc3..9b016901a20 100644
--- a/spec/lib/gitlab/ci/build/policy/variables_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
@@ -15,6 +15,7 @@ describe Gitlab::Ci::Build::Policy::Variables do
before do
pipeline.variables.build(key: 'CI_PROJECT_NAME', value: '')
+ pipeline.variables.build(key: 'MY_VARIABLE', value: 'my-var')
end
describe '#satisfied_by?' do
@@ -24,6 +25,12 @@ describe Gitlab::Ci::Build::Policy::Variables do
expect(policy).to be_satisfied_by(pipeline, seed)
end
+ it 'is satisfied by a matching pipeline variable' do
+ policy = described_class.new(['$MY_VARIABLE'])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+
it 'is not satisfied by an overridden empty variable' do
policy = described_class.new(['$CI_PROJECT_NAME'])
@@ -68,5 +75,19 @@ describe Gitlab::Ci::Build::Policy::Variables do
expect(pipeline).not_to be_persisted
expect(seed.to_resource).not_to be_persisted
end
+
+ context 'when a bridge job is used' do
+ let(:bridge) do
+ build(:ci_bridge, pipeline: pipeline, project: project, ref: 'master')
+ end
+
+ let(:seed) { double('bridge seed', to_resource: bridge) }
+
+ it 'is satisfied by a matching expression for a bridge job' do
+ policy = described_class.new(['$MY_VARIABLE'])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/build/step_spec.rb b/spec/lib/gitlab/ci/build/step_spec.rb
index cce4efaa069..e3136fc925e 100644
--- a/spec/lib/gitlab/ci/build/step_spec.rb
+++ b/spec/lib/gitlab/ci/build/step_spec.rb
@@ -18,13 +18,6 @@ describe Gitlab::Ci::Build::Step do
end
end
- context 'when commands are specified' do
- it_behaves_like 'has correct script' do
- let(:job) { create(:ci_build, :no_options, commands: "ls -la\ndate") }
- let(:script) { ['ls -la', 'date'] }
- end
- end
-
context 'when script option is specified' do
it_behaves_like 'has correct script' do
let(:job) { create(:ci_build, :no_options, options: { script: ["ls -la\necho aaa", "date"] }) }
@@ -62,7 +55,7 @@ describe Gitlab::Ci::Build::Step do
end
context 'when after_script is not empty' do
- let(:job) { create(:ci_build, options: { after_script: ['ls -la', 'date'] }) }
+ let(:job) { create(:ci_build, options: { script: ['bash'], after_script: ['ls -la', 'date'] }) }
it 'fabricates an object' do
expect(subject.name).to eq(:after_script)
diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb
index 61d78f86b51..e23efff18d5 100644
--- a/spec/lib/gitlab/ci/config/entry/global_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb
@@ -13,7 +13,7 @@ describe Gitlab::Ci::Config::Entry::Global do
expect(described_class.nodes.keys)
.to match_array(%i[before_script image services
after_script variables stages
- types cache])
+ types cache include])
end
end
end
@@ -42,7 +42,7 @@ describe Gitlab::Ci::Config::Entry::Global do
end
it 'creates node object for each entry' do
- expect(global.descendants.count).to eq 8
+ expect(global.descendants.count).to eq 9
end
it 'creates node object using valid class' do
@@ -153,7 +153,6 @@ describe Gitlab::Ci::Config::Entry::Global do
rspec: { name: :rspec,
script: %w[rspec ls],
before_script: %w(ls pwd),
- commands: "ls\npwd\nrspec\nls",
image: { name: 'ruby:2.2' },
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
@@ -161,12 +160,10 @@ describe Gitlab::Ci::Config::Entry::Global do
variables: { 'VAR' => 'value' },
ignore: false,
after_script: ['make clean'],
- only: { refs: %w[branches tags] },
- except: {} },
+ only: { refs: %w[branches tags] } },
spinach: { name: :spinach,
before_script: [],
script: %w[spinach],
- commands: 'spinach',
image: { name: 'ruby:2.2' },
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
@@ -174,8 +171,7 @@ describe Gitlab::Ci::Config::Entry::Global do
variables: {},
ignore: false,
after_script: ['make clean'],
- only: { refs: %w[branches tags] },
- except: {} }
+ only: { refs: %w[branches tags] } }
)
end
end
@@ -193,7 +189,7 @@ describe Gitlab::Ci::Config::Entry::Global do
describe '#nodes' do
it 'instantizes all nodes' do
- expect(global.descendants.count).to eq 8
+ expect(global.descendants.count).to eq 9
end
it 'contains unspecified nodes' do
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 8e32cede3b5..0560eb42e4d 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -255,25 +255,13 @@ describe Gitlab::Ci::Config::Entry::Job do
.to eq(name: :rspec,
before_script: %w[ls pwd],
script: %w[rspec],
- commands: "ls\npwd\nrspec",
stage: 'test',
ignore: false,
after_script: %w[cleanup],
- only: { refs: %w[branches tags] },
- except: {})
+ only: { refs: %w[branches tags] })
end
end
end
-
- describe '#commands' do
- let(:config) do
- { before_script: %w[ls pwd], script: 'rspec' }
- end
-
- it 'returns a string of commands concatenated with new line character' do
- expect(entry.commands).to eq "ls\npwd\nrspec"
- end
- end
end
describe '#manual_action?' do
diff --git a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
index 1a2c30d3571..271ee30df3c 100644
--- a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
@@ -65,18 +65,14 @@ describe Gitlab::Ci::Config::Entry::Jobs do
expect(entry.value).to eq(
rspec: { name: :rspec,
script: %w[rspec],
- commands: 'rspec',
ignore: false,
stage: 'test',
- only: { refs: %w[branches tags] },
- except: {} },
+ only: { refs: %w[branches tags] } },
spinach: { name: :spinach,
script: %w[spinach],
- commands: 'spinach',
ignore: false,
stage: 'test',
- only: { refs: %w[branches tags] },
- except: {} })
+ only: { refs: %w[branches tags] } })
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/policy_spec.rb b/spec/lib/gitlab/ci/config/entry/policy_spec.rb
index 83001b7fdd8..1c987e13a9a 100644
--- a/spec/lib/gitlab/ci/config/entry/policy_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/policy_spec.rb
@@ -168,8 +168,33 @@ describe Gitlab::Ci::Config::Entry::Policy do
end
end
+ describe '#value' do
+ context 'when default value has been provided' do
+ before do
+ entry.default = { refs: %w[branches tags] }
+ end
+
+ context 'when user overrides default values' do
+ let(:config) { { refs: %w[feature], variables: %w[$VARIABLE] } }
+
+ it 'does not include default values' do
+ expect(entry.value).to eq config
+ end
+ end
+
+ context 'when default value has not been defined' do
+ let(:config) { { variables: %w[$VARIABLE] } }
+
+ it 'includes default values' do
+ expect(entry.value).to eq(refs: %w[branches tags],
+ variables: %w[$VARIABLE])
+ end
+ end
+ end
+ end
+
describe '.default' do
- it 'does not have a default value' do
+ it 'does not have default policy' do
expect(described_class.default).to be_nil
end
end
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 2e92d5204d6..fa39b32d7ab 100644
--- a/spec/lib/gitlab/ci/config/external/file/base_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
@@ -3,13 +3,43 @@
require 'fast_spec_helper'
describe Gitlab::Ci::Config::External::File::Base do
- subject { described_class.new(location) }
+ let(:context) { described_class::Context.new(nil, 'HEAD', nil, Set.new) }
+
+ let(:test_class) do
+ Class.new(described_class) do
+ def initialize(params, context = {})
+ @location = params
+
+ super
+ end
+ end
+ end
+
+ subject { test_class.new(location, context) }
before do
- allow_any_instance_of(described_class)
+ allow_any_instance_of(test_class)
.to receive(:content).and_return('key: value')
end
+ describe '#matching?' do
+ context 'when a location is present' do
+ let(:location) { 'some-location' }
+
+ it 'should return true' do
+ expect(subject).to be_matching
+ end
+ end
+
+ context 'with a location is missing' do
+ let(:location) { nil }
+
+ it 'should return false' do
+ expect(subject).not_to be_matching
+ end
+ end
+ end
+
describe '#valid?' do
context 'when location is not a YAML file' do
let(:location) { 'some/file.txt' }
@@ -39,7 +69,7 @@ describe Gitlab::Ci::Config::External::File::Base do
let(:location) { 'some/file/config.yml' }
before do
- allow_any_instance_of(described_class)
+ allow_any_instance_of(test_class)
.to receive(:content).and_return('invalid_syntax')
end
@@ -49,4 +79,20 @@ describe Gitlab::Ci::Config::External::File::Base do
end
end
end
+
+ describe '#to_hash' do
+ context 'with includes' do
+ let(:location) { 'some/file/config.yml' }
+ let(:content) { 'include: { template: Bash.gitlab-ci.yml }'}
+
+ before do
+ allow_any_instance_of(test_class)
+ .to receive(:content).and_return(content)
+ end
+
+ it 'does expand hash to include the template' do
+ expect(subject.to_hash).to include(:before_script)
+ end
+ end
+ end
end
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 541deb13b97..dc14b07287e 100644
--- a/spec/lib/gitlab/ci/config/external/file/local_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
@@ -3,8 +3,39 @@
require 'spec_helper'
describe Gitlab::Ci::Config::External::File::Local do
- let(:project) { create(:project, :repository) }
- let(:local_file) { described_class.new(location, { project: project, sha: '12345' }) }
+ set(:project) { create(:project, :repository) }
+ set(:user) { create(:user) }
+
+ let(:sha) { '12345' }
+ let(:context) { described_class::Context.new(project, sha, user, Set.new) }
+ let(:params) { { local: location } }
+ let(:local_file) { described_class.new(params, context) }
+
+ describe '#matching?' do
+ context 'when a local is specified' do
+ let(:params) { { local: 'file' } }
+
+ it 'should return true' do
+ expect(local_file).to be_matching
+ end
+ end
+
+ context 'with a missing local' do
+ let(:params) { { local: nil } }
+
+ it 'should return false' do
+ expect(local_file).not_to be_matching
+ end
+ end
+
+ context 'with a missing local key' do
+ let(:params) { {} }
+
+ it 'should return false' do
+ expect(local_file).not_to be_matching
+ end
+ end
+ end
describe '#valid?' do
context 'when is a valid local path' do
@@ -44,7 +75,6 @@ describe Gitlab::Ci::Config::External::File::Local do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
HEREDOC
end
@@ -75,4 +105,36 @@ describe Gitlab::Ci::Config::External::File::Local do
expect(local_file.error_message).to eq("Local file `#{location}` does not exist!")
end
end
+
+ describe '#expand_context' do
+ let(:location) { 'location.yml' }
+
+ subject { local_file.send(:expand_context) }
+
+ it 'inherits project, user and sha' do
+ is_expected.to include(user: user, project: project, sha: sha)
+ end
+ end
+
+ 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(:another_location) { 'another-config.yml' }
+ let(:another_content) { 'rspec: JOB' }
+
+ before do
+ allow(project.repository).to receive(:blob_data_at).with(sha, location)
+ .and_return(content)
+
+ allow(project.repository).to receive(:blob_data_at).with(sha, another_location)
+ .and_return(another_content)
+ end
+
+ it 'does expand hash to include the template' do
+ expect(local_file.to_hash).to include(:rspec)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/config/external/file/project_spec.rb b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
new file mode 100644
index 00000000000..6e89bb1b30f
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
@@ -0,0 +1,162 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::External::File::Project do
+ set(:context_project) { create(:project) }
+ set(:project) { create(:project, :repository) }
+ set(:user) { create(:user) }
+
+ let(:context_user) { user }
+ let(:context) { described_class::Context.new(context_project, '12345', context_user, Set.new) }
+ let(:project_file) { described_class.new(params, context) }
+
+ before do
+ project.add_developer(user)
+ end
+
+ describe '#matching?' do
+ context 'when a file and project is specified' do
+ let(:params) { { file: 'file.yml', project: 'project' } }
+
+ it 'should return true' do
+ expect(project_file).to be_matching
+ end
+ end
+
+ context 'with only file is specified' do
+ let(:params) { { file: 'file.yml' } }
+
+ it 'should return false' do
+ expect(project_file).not_to be_matching
+ end
+ end
+
+ context 'with only project is specified' do
+ let(:params) { { project: 'project' } }
+
+ it 'should return false' do
+ expect(project_file).not_to be_matching
+ end
+ end
+
+ context 'with a missing local key' do
+ let(:params) { {} }
+
+ it 'should return false' do
+ expect(project_file).not_to be_matching
+ end
+ end
+ end
+
+ describe '#valid?' do
+ context 'when a valid path is used' do
+ let(:params) do
+ { project: project.full_path, file: '/file.yml' }
+ end
+
+ let(:root_ref_sha) { project.repository.root_ref_sha }
+
+ before do
+ stub_project_blob(root_ref_sha, '/file.yml') { 'image: ruby:2.1' }
+ end
+
+ it 'should return true' do
+ expect(project_file).to be_valid
+ end
+
+ context 'when user does not have permission to access file' do
+ let(:context_user) { create(:user) }
+
+ it 'should return false' do
+ expect(project_file).not_to be_valid
+ expect(project_file.error_message).to include("Project `#{project.full_path}` not found or access denied!")
+ end
+ end
+ end
+
+ context 'when a valid path with custom ref is used' do
+ let(:params) do
+ { project: project.full_path, ref: 'master', file: '/file.yml' }
+ end
+
+ let(:ref_sha) { project.commit('master').sha }
+
+ before do
+ stub_project_blob(ref_sha, '/file.yml') { 'image: ruby:2.1' }
+ end
+
+ it 'should return true' do
+ expect(project_file).to be_valid
+ end
+ end
+
+ context 'when an empty file is used' do
+ let(:params) do
+ { project: project.full_path, file: '/file.yml' }
+ end
+
+ let(:root_ref_sha) { project.repository.root_ref_sha }
+
+ before do
+ stub_project_blob(root_ref_sha, '/file.yml') { '' }
+ end
+
+ it 'should return false' do
+ expect(project_file).not_to be_valid
+ expect(project_file.error_message).to include("Project `#{project.full_path}` file `/file.yml` is empty!")
+ end
+ end
+
+ context 'when non-existing ref is used' do
+ let(:params) do
+ { project: project.full_path, ref: 'I-Do-Not-Exist', file: '/file.yml' }
+ end
+
+ it 'should return false' do
+ expect(project_file).not_to be_valid
+ expect(project_file.error_message).to include("Project `#{project.full_path}` reference `I-Do-Not-Exist` does not exist!")
+ end
+ end
+
+ context 'when non-existing file is requested' do
+ let(:params) do
+ { project: project.full_path, file: '/invalid-file.yml' }
+ end
+
+ it 'should return false' do
+ expect(project_file).not_to be_valid
+ expect(project_file.error_message).to include("Project `#{project.full_path}` file `/invalid-file.yml` does not exist!")
+ end
+ end
+
+ context 'when file is not a yaml file' do
+ let(:params) do
+ { project: project.full_path, file: '/invalid-file' }
+ end
+
+ it 'should return false' do
+ expect(project_file).not_to be_valid
+ expect(project_file.error_message).to include('Included file `/invalid-file` does not have YAML extension!')
+ end
+ end
+ end
+
+ describe '#expand_context' do
+ let(:params) { { file: 'file.yml', project: project.full_path, ref: 'master' } }
+
+ subject { project_file.send(:expand_context) }
+
+ it 'inherits user, and target project and sha' do
+ is_expected.to include(user: user, project: project, sha: project.commit('master').id)
+ end
+ end
+
+ private
+
+ def stub_project_blob(ref, path)
+ allow_any_instance_of(Repository)
+ .to receive(:blob_data_at)
+ .with(ref, path) { yield }
+ end
+end
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 7c1a1c38736..c5b32c29759 100644
--- a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
@@ -3,7 +3,9 @@
require 'spec_helper'
describe Gitlab::Ci::Config::External::File::Remote do
- let(:remote_file) { described_class.new(location) }
+ let(:context) { described_class::Context.new(nil, '12345', nil, Set.new) }
+ let(:params) { { remote: location } }
+ let(:remote_file) { described_class.new(params, context) }
let(:location) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
let(:remote_file_content) do
<<~HEREDOC
@@ -11,11 +13,36 @@ describe Gitlab::Ci::Config::External::File::Remote do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
HEREDOC
end
+ describe '#matching?' do
+ context 'when a remote is specified' do
+ let(:params) { { remote: 'http://remote' } }
+
+ it 'should return true' do
+ expect(remote_file).to be_matching
+ end
+ end
+
+ context 'with a missing remote' do
+ let(:params) { { remote: nil } }
+
+ it 'should return false' do
+ expect(remote_file).not_to be_matching
+ end
+ end
+
+ context 'with a missing remote key' do
+ let(:params) { {} }
+
+ it 'should return false' do
+ expect(remote_file).not_to be_matching
+ end
+ end
+ end
+
describe "#valid?" do
context 'when is a valid remote url' do
before do
@@ -154,4 +181,14 @@ describe Gitlab::Ci::Config::External::File::Remote do
end
end
end
+
+ describe '#expand_context' do
+ let(:params) { { remote: 'http://remote' } }
+
+ subject { remote_file.send(:expand_context) }
+
+ it 'drops all parameters' do
+ is_expected.to include(user: nil, project: nil, sha: nil)
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/config/external/file/template_spec.rb b/spec/lib/gitlab/ci/config/external/file/template_spec.rb
new file mode 100644
index 00000000000..8ecaf4800f8
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/external/file/template_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::External::File::Template do
+ set(:project) { create(:project) }
+ set(:user) { create(:user) }
+
+ let(:context) { described_class::Context.new(project, '12345', user, Set.new) }
+ let(:template) { 'Auto-DevOps.gitlab-ci.yml' }
+ let(:params) { { template: template } }
+
+ let(:template_file) { described_class.new(params, context) }
+
+ describe '#matching?' do
+ context 'when a template is specified' do
+ let(:params) { { template: 'some-template' } }
+
+ it 'should return true' do
+ expect(template_file).to be_matching
+ end
+ end
+
+ context 'with a missing template' do
+ let(:params) { { template: nil } }
+
+ it 'should return false' do
+ expect(template_file).not_to be_matching
+ end
+ end
+
+ context 'with a missing template key' do
+ let(:params) { {} }
+
+ it 'should return false' do
+ expect(template_file).not_to be_matching
+ end
+ end
+ end
+
+ describe "#valid?" do
+ context 'when is a valid template name' do
+ let(:template) { 'Auto-DevOps.gitlab-ci.yml' }
+
+ it 'should return true' do
+ expect(template_file).to be_valid
+ end
+ end
+
+ context 'with invalid template name' do
+ let(:template) { 'Template.yml' }
+
+ it 'should return false' do
+ expect(template_file).not_to be_valid
+ expect(template_file.error_message).to include('Template file `Template.yml` is not a valid location!')
+ end
+ end
+
+ context 'with a non-existing template' do
+ let(:template) { 'I-Do-Not-Have-This-Template.gitlab-ci.yml' }
+
+ it 'should return false' do
+ expect(template_file).not_to be_valid
+ expect(template_file.error_message).to include('Included file `I-Do-Not-Have-This-Template.gitlab-ci.yml` is empty or does not exist!')
+ end
+ end
+ end
+
+ describe '#template_name' do
+ let(:template_name) { template_file.send(:template_name) }
+
+ context 'when template does end with .gitlab-ci.yml' do
+ let(:template) { 'my-template.gitlab-ci.yml' }
+
+ it 'returns template name' do
+ expect(template_name).to eq('my-template')
+ end
+ end
+
+ context 'when template is nil' do
+ let(:template) { nil }
+
+ it 'returns nil' do
+ expect(template_name).to be_nil
+ end
+ end
+
+ context 'when template does not end with .gitlab-ci.yml' do
+ let(:template) { 'my-template' }
+
+ it 'returns nil' do
+ expect(template_name).to be_nil
+ end
+ end
+ end
+
+ describe '#expand_context' do
+ let(:location) { 'location.yml' }
+
+ subject { template_file.send(:expand_context) }
+
+ it 'drops all parameters' do
+ is_expected.to include(user: nil, project: nil, sha: nil)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index 5b236fe99f1..136974569de 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -3,84 +3,132 @@
require 'spec_helper'
describe Gitlab::Ci::Config::External::Mapper do
- let(:project) { create(:project, :repository) }
+ set(:project) { create(:project, :repository) }
+ set(:user) { create(:user) }
+
+ let(:local_file) { '/lib/gitlab/ci/templates/non-existent-file.yml' }
+ let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:template_file) { 'Auto-DevOps.gitlab-ci.yml' }
+ let(:expandset) { Set.new }
+
let(:file_content) do
<<~HEREDOC
image: 'ruby:2.2'
HEREDOC
end
+ before do
+ WebMock.stub_request(:get, remote_url).to_return(body: file_content)
+ end
+
describe '#process' do
- subject { described_class.new(values, project, '123456').process }
+ subject { described_class.new(values, project: project, sha: '123456', user: user, expandset: expandset).process }
- context "when 'include' keyword is defined as string" do
+ context "when single 'include' keyword is defined" do
context 'when the string is a local file' do
let(:values) do
- {
- include: '/lib/gitlab/ci/templates/non-existent-file.yml',
- image: 'ruby:2.2'
- }
+ { include: local_file,
+ image: 'ruby:2.2' }
end
- it 'returns an array' do
- expect(subject).to be_an(Array)
+ it 'returns File instances' do
+ expect(subject).to contain_exactly(
+ an_instance_of(Gitlab::Ci::Config::External::File::Local))
+ end
+ end
+
+ context 'when the key is a local file hash' do
+ let(:values) do
+ { include: { 'local' => local_file },
+ image: 'ruby:2.2' }
end
it 'returns File instances' do
- expect(subject.first)
- .to be_an_instance_of(Gitlab::Ci::Config::External::File::Local)
+ expect(subject).to contain_exactly(
+ an_instance_of(Gitlab::Ci::Config::External::File::Local))
end
end
context 'when the string is a remote file' do
- let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
let(:values) do
- {
- include: remote_url,
- image: 'ruby:2.2'
- }
+ { include: remote_url, image: 'ruby:2.2' }
end
- before do
- WebMock.stub_request(:get, remote_url).to_return(body: file_content)
+ it 'returns File instances' do
+ expect(subject).to contain_exactly(
+ an_instance_of(Gitlab::Ci::Config::External::File::Remote))
end
+ end
- it 'returns an array' do
- expect(subject).to be_an(Array)
+ context 'when the key is a remote file hash' do
+ let(:values) do
+ { include: { 'remote' => remote_url },
+ image: 'ruby:2.2' }
end
it 'returns File instances' do
- expect(subject.first)
- .to be_an_instance_of(Gitlab::Ci::Config::External::File::Remote)
+ expect(subject).to contain_exactly(
+ an_instance_of(Gitlab::Ci::Config::External::File::Remote))
+ end
+ end
+
+ context 'when the key is a template file hash' do
+ let(:values) do
+ { include: { 'template' => template_file },
+ image: 'ruby:2.2' }
+ end
+
+ it 'returns File instances' do
+ expect(subject).to contain_exactly(
+ an_instance_of(Gitlab::Ci::Config::External::File::Template))
+ end
+ end
+
+ context 'when the key is a hash of file and remote' do
+ let(:values) do
+ { include: { 'local' => local_file, 'remote' => remote_url },
+ image: 'ruby:2.2' }
+ end
+
+ it 'returns ambigious specification error' do
+ expect { subject }.to raise_error(described_class::AmbigiousSpecificationError)
end
end
end
context "when 'include' is defined as an array" do
- let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
let(:values) do
- {
- include:
- [
- remote_url,
- '/lib/gitlab/ci/templates/template.yml'
- ],
- image: 'ruby:2.2'
- }
+ { include: [remote_url, local_file],
+ image: 'ruby:2.2' }
end
- before do
- WebMock.stub_request(:get, remote_url).to_return(body: file_content)
+ it 'returns Files instances' do
+ expect(subject).to all(respond_to(:valid?))
+ expect(subject).to all(respond_to(:content))
end
+ end
- it 'returns an array' do
- expect(subject).to be_an(Array)
+ context "when 'include' is defined as an array of hashes" do
+ let(:values) do
+ { include: [{ remote: remote_url }, { local: local_file }],
+ image: 'ruby:2.2' }
end
it 'returns Files instances' do
expect(subject).to all(respond_to(:valid?))
expect(subject).to all(respond_to(:content))
end
+
+ context 'when it has ambigious match' do
+ let(:values) do
+ { include: [{ remote: remote_url, local: local_file }],
+ image: 'ruby:2.2' }
+ end
+
+ it 'returns ambigious specification error' do
+ expect { subject }.to raise_error(described_class::AmbigiousSpecificationError)
+ end
+ end
end
context "when 'include' is not defined" do
@@ -94,5 +142,37 @@ describe Gitlab::Ci::Config::External::Mapper do
expect(subject).to be_empty
end
end
+
+ context "when duplicate 'include' is defined" do
+ let(:values) do
+ { include: [
+ { 'local' => local_file },
+ { 'local' => local_file }
+ ],
+ image: 'ruby:2.2' }
+ end
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(described_class::DuplicateIncludesError)
+ end
+ end
+
+ context "when too many 'includes' are defined" do
+ let(:values) do
+ { include: [
+ { 'local' => local_file },
+ { 'remote' => remote_url }
+ ],
+ image: 'ruby:2.2' }
+ end
+
+ before do
+ stub_const("#{described_class}::MAX_INCLUDES", 1)
+ end
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(described_class::TooManyIncludesError)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 1a05f716247..3f6f6d7c5d9 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -3,10 +3,21 @@
require 'spec_helper'
describe Gitlab::Ci::Config::External::Processor do
- let(:project) { create(:project, :repository) }
- let(:processor) { described_class.new(values, project, '12345') }
+ set(:project) { create(:project, :repository) }
+ set(:another_project) { create(:project, :repository) }
+ set(:user) { create(:user) }
+
+ let(:expandset) { Set.new }
+ let(:sha) { '12345' }
+ let(:processor) { described_class.new(values, project: project, sha: '12345', user: user, expandset: expandset) }
+
+ before do
+ project.add_developer(user)
+ end
describe "#perform" do
+ subject { processor.perform }
+
context 'when no external files defined' do
let(:values) { { image: 'ruby:2.2' } }
@@ -51,7 +62,6 @@ describe Gitlab::Ci::Config::External::Processor do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
rspec:
@@ -86,7 +96,6 @@ describe Gitlab::Ci::Config::External::Processor do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
HEREDOC
end
@@ -186,5 +195,80 @@ describe Gitlab::Ci::Config::External::Processor do
expect(processor.perform[:image]).to eq('ruby:2.2')
end
end
+
+ context "when a nested includes are defined" do
+ let(:values) do
+ {
+ include: [
+ { local: '/local/file.yml' }
+ ],
+ image: 'ruby:2.2'
+ }
+ end
+
+ before do
+ allow(project.repository).to receive(:blob_data_at).with('12345', '/local/file.yml') do
+ <<~HEREDOC
+ include:
+ - template: Ruby.gitlab-ci.yml
+ - remote: http://my.domain.com/config.yml
+ - project: #{another_project.full_path}
+ file: /templates/my-workflow.yml
+ HEREDOC
+ end
+
+ allow_any_instance_of(Repository).to receive(:blob_data_at).with(another_project.commit.id, '/templates/my-workflow.yml') do
+ <<~HEREDOC
+ include:
+ - local: /templates/my-build.yml
+ HEREDOC
+ end
+
+ allow_any_instance_of(Repository).to receive(:blob_data_at).with(another_project.commit.id, '/templates/my-build.yml') do
+ <<~HEREDOC
+ my_build:
+ script: echo Hello World
+ HEREDOC
+ end
+
+ WebMock.stub_request(:get, 'http://my.domain.com/config.yml').to_return(body: 'remote_build: { script: echo Hello World }')
+ end
+
+ context 'when project is public' do
+ before do
+ another_project.update!(visibility: 'public')
+ end
+
+ it 'properly expands all includes' do
+ is_expected.to include(:my_build, :remote_build, :rspec)
+ end
+ end
+
+ context 'when user is reporter of another project' do
+ before do
+ another_project.add_reporter(user)
+ end
+
+ it 'properly expands all includes' do
+ is_expected.to include(:my_build, :remote_build, :rspec)
+ end
+ end
+
+ context 'when user is not allowed' do
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Ci::Config::External::Processor::IncludeError, /not found or access denied/)
+ end
+ end
+
+ context 'when too many includes is included' do
+ before do
+ stub_const('Gitlab::Ci::Config::External::Mapper::MAX_INCLUDES', 1)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Ci::Config::External::Processor::IncludeError, /Maximum of 1 nested/)
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config/normalizer_spec.rb b/spec/lib/gitlab/ci/config/normalizer_spec.rb
index 97926695b6e..cd880177170 100644
--- a/spec/lib/gitlab/ci/config/normalizer_spec.rb
+++ b/spec/lib/gitlab/ci/config/normalizer_spec.rb
@@ -62,5 +62,25 @@ describe Gitlab::Ci::Config::Normalizer do
expect(subject[:other_job][:dependencies]).not_to include(job_name)
end
end
+
+ context 'when there are dependencies which are both parallelized and not' do
+ let(:config) do
+ {
+ job_name => job_config,
+ other_job: { script: 'echo 1' },
+ final_job: { script: 'echo 1', dependencies: [job_name.to_s, "other_job"] }
+ }
+ end
+
+ it 'parallelizes dependencies' do
+ job_names = ["rspec 1/5", "rspec 2/5", "rspec 3/5", "rspec 4/5", "rspec 5/5"]
+
+ expect(subject[:final_job][:dependencies]).to include(*job_names)
+ end
+
+ it 'includes the regular job in dependencies' do
+ expect(subject[:final_job][:dependencies]).to include('other_job')
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 975e11e8cc1..18f255c1ab7 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -1,8 +1,10 @@
require 'spec_helper'
describe Gitlab::Ci::Config do
+ set(:user) { create(:user) }
+
let(:config) do
- described_class.new(yml)
+ described_class.new(yml, project: nil, sha: nil, user: nil)
end
context 'when config is valid' do
@@ -154,7 +156,7 @@ describe Gitlab::Ci::Config do
end
let(:config) do
- described_class.new(gitlab_ci_yml, project: project, sha: '12345')
+ described_class.new(gitlab_ci_yml, project: project, sha: '12345', user: user)
end
before do
@@ -170,7 +172,6 @@ describe Gitlab::Ci::Config do
before_script_values = [
"apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs", "ruby -v",
"which ruby",
- "gem install bundler --no-ri --no-rdoc",
"bundle install --jobs $(nproc) \"${FLAGS[@]}\""
]
variables = {
@@ -191,7 +192,7 @@ describe Gitlab::Ci::Config do
end
end
- context "when gitlab_ci.yml has invalid 'include' defined" do
+ context "when gitlab_ci.yml has invalid 'include' defined" do
let(:gitlab_ci_yml) do
<<~HEREDOC
include: invalid
@@ -206,13 +207,30 @@ describe Gitlab::Ci::Config do
end
end
+ context "when gitlab_ci.yml has ambigious 'include' defined" do
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ remote: http://url
+ local: /local/file.yml
+ HEREDOC
+ end
+
+ it 'raises error YamlProcessor validationError' do
+ expect { config }.to raise_error(
+ described_class::ConfigError,
+ 'Include `{"remote":"http://url","local":"/local/file.yml"}` needs to match exactly one accessor!'
+ )
+ end
+ end
+
describe 'external file version' do
context 'when external local file SHA is defined' do
it 'is using a defined value' do
expect(project.repository).to receive(:blob_data_at)
.with('eeff1122', local_location)
- described_class.new(gitlab_ci_yml, project: project, sha: 'eeff1122')
+ described_class.new(gitlab_ci_yml, project: project, sha: 'eeff1122', user: user)
end
end
@@ -220,7 +238,7 @@ describe Gitlab::Ci::Config do
it 'is using latest SHA on the default branch' do
expect(project.repository).to receive(:root_ref_sha)
- described_class.new(gitlab_ci_yml, project: project)
+ described_class.new(gitlab_ci_yml, project: project, sha: nil, user: user)
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
index fab071405df..3debd42ac65 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
@@ -96,11 +96,13 @@ describe Gitlab::Ci::Pipeline::Chain::Build do
context 'when pipeline is running for a merge request' do
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
- source: :merge_request,
+ source: :merge_request_event,
origin_ref: 'feature',
checkout_sha: project.commit.id,
after_sha: nil,
before_sha: nil,
+ source_sha: merge_request.diff_head_sha,
+ target_sha: merge_request.target_branch_sha,
trigger_request: nil,
schedule: nil,
merge_request: merge_request,
@@ -115,8 +117,13 @@ describe Gitlab::Ci::Pipeline::Chain::Build do
end
it 'correctly indicated that this is a merge request pipeline' do
- expect(pipeline).to be_merge_request
+ expect(pipeline).to be_merge_request_event
expect(pipeline.merge_request).to eq(merge_request)
end
+
+ it 'correctly sets souce sha and target sha to pipeline' do
+ expect(pipeline.source_sha).to eq(merge_request.diff_head_sha)
+ expect(pipeline.target_sha).to eq(merge_request.target_branch_sha)
+ 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 75a177d2d1f..dab0fb51bcc 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
@@ -161,6 +161,54 @@ describe Gitlab::Ci::Pipeline::Chain::Command do
end
end
+ describe '#source_sha' do
+ subject { command.source_sha }
+
+ let(:command) do
+ described_class.new(project: project,
+ source_sha: source_sha,
+ merge_request: merge_request)
+ end
+
+ let(:merge_request) do
+ create(:merge_request, target_project: project, source_project: project)
+ end
+
+ let(:source_sha) { nil }
+
+ context 'when source_sha is specified' do
+ let(:source_sha) { 'abc' }
+
+ it 'returns the specified value' do
+ is_expected.to eq('abc')
+ end
+ end
+ end
+
+ describe '#target_sha' do
+ subject { command.target_sha }
+
+ let(:command) do
+ described_class.new(project: project,
+ target_sha: target_sha,
+ merge_request: merge_request)
+ end
+
+ let(:merge_request) do
+ create(:merge_request, target_project: project, source_project: project)
+ end
+
+ let(:target_sha) { nil }
+
+ context 'when target_sha is specified' do
+ let(:target_sha) { 'abc' }
+
+ it 'returns the specified value' do
+ is_expected.to eq('abc')
+ end
+ end
+ end
+
describe '#protected_ref?' do
let(:command) { described_class.new(project: project, origin_ref: 'my-branch') }
@@ -182,4 +230,24 @@ describe Gitlab::Ci::Pipeline::Chain::Command do
it { is_expected.to eq(false) }
end
end
+
+ describe '#ambiguous_ref' do
+ let(:project) { create(:project, :repository) }
+ let(:command) { described_class.new(project: project, origin_ref: 'ref') }
+
+ subject { command.ambiguous_ref? }
+
+ context 'when ref is not ambiguous' do
+ it { is_expected. to eq(false) }
+ end
+
+ context 'when ref is ambiguous' do
+ before do
+ project.repository.add_tag(project.creator, 'ref', 'master')
+ project.repository.add_branch(project.creator, 'ref', 'master')
+ end
+
+ it { is_expected. to eq(true) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
index 284aed91e29..0302e4090cf 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
@@ -14,6 +14,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project,
current_user: user,
+ origin_ref: 'master',
seeds_block: nil)
end
@@ -78,6 +79,31 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
end
end
+ describe 'pipeline protect' do
+ subject { step.perform! }
+
+ context 'when ref is protected' do
+ before do
+ allow(project).to receive(:protected_for?).with('master').and_return(true)
+ allow(project).to receive(:protected_for?).with('refs/heads/master').and_return(true)
+ end
+
+ it 'does not protect the pipeline' do
+ subject
+
+ expect(pipeline.protected).to eq(true)
+ end
+ end
+
+ context 'when ref is not protected' do
+ it 'does not protect the pipeline' do
+ subject
+
+ expect(pipeline.protected).to eq(false)
+ end
+ end
+ end
+
context 'when pipeline has validation errors' do
let(:pipeline) do
build(:ci_pipeline, project: project, ref: nil)
@@ -106,6 +132,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project,
current_user: user,
+ origin_ref: 'master',
seeds_block: seeds_block)
end
@@ -136,14 +163,14 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
->(pipeline) { pipeline.variables.create!(key: 'VAR', value: '123') }
end
- it 'raises exception' do
+ it 'wastes pipeline iid' do
expect { step.perform! }.to raise_error(ActiveRecord::RecordNotSaved)
- end
- it 'wastes pipeline iid' do
- expect { step.perform! }.to raise_error
+ last_iid = InternalId.ci_pipelines
+ .where(project_id: project.id)
+ .last.last_value
- expect(InternalId.ci_pipelines.where(project_id: project.id).last.last_value).to be > 0
+ expect(last_iid).to be > 0
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb
new file mode 100644
index 00000000000..7c1c016b4bb
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs do
+ let(:project) { create(:project, :repository) }
+
+ let(:pipeline) do
+ build(:ci_pipeline_with_one_job, project: project, ref: 'master')
+ end
+
+ let(:command) do
+ double(:command, project: project, chat_data: { command: 'echo' })
+ end
+
+ describe '#perform!' do
+ it 'removes unwanted jobs for chat pipelines' do
+ allow(pipeline).to receive(:chat?).and_return(true)
+
+ pipeline.config_processor.jobs[:echo] = double(:job)
+
+ described_class.new(pipeline, command).perform!
+
+ expect(pipeline.config_processor.jobs.keys).to eq([:echo])
+ end
+ end
+
+ it 'does not remove any jobs for non-chat pipelines' do
+ described_class.new(pipeline, command).perform!
+
+ expect(pipeline.config_processor.jobs.keys).to eq([:rspec])
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/config_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/config_spec.rb
index 053bc421649..e6c6a82b463 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/config_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/config_spec.rb
@@ -115,7 +115,7 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Config do
let(:pipeline) { build_stubbed(:ci_pipeline, project: project) }
let(:merge_request_pipeline) do
- build(:ci_pipeline, source: :merge_request, project: project)
+ build(:ci_pipeline, source: :merge_request_event, project: project)
end
let(:chain) { described_class.new(merge_request_pipeline, command).tap(&:perform!) }
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
index fb1b53fc55c..a7cad423d09 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
@@ -42,6 +42,27 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Repository do
end
end
+ context 'when ref is ambiguous' do
+ let(:project) do
+ create(:project, :repository).tap do |proj|
+ proj.repository.add_tag(user, 'master', 'master')
+ end
+ end
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(
+ project: project, current_user: user, origin_ref: 'master')
+ end
+
+ it 'breaks the chain' do
+ expect(step.break?).to be true
+ end
+
+ it 'adds an error about missing ref' do
+ expect(pipeline.errors.to_a)
+ .to include 'Ref is ambiguous'
+ end
+ end
+
context 'when does not have existing SHA set' do
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index fffa727c2ed..fae8add6453 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -1,12 +1,11 @@
require 'spec_helper'
describe Gitlab::Ci::Pipeline::Seed::Build do
- let(:pipeline) { create(:ci_empty_pipeline) }
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:attributes) do
- { name: 'rspec',
- ref: 'master',
- commands: 'rspec' }
+ { name: 'rspec', ref: 'master' }
end
subject do
@@ -17,14 +16,49 @@ describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns hash attributes of a build' do
expect(subject.attributes).to be_a Hash
expect(subject.attributes)
- .to include(:name, :project, :ref, :commands)
+ .to include(:name, :project, :ref)
+ end
+ end
+
+ describe '#bridge?' do
+ context 'when job is a bridge' do
+ let(:attributes) do
+ { name: 'rspec', ref: 'master', options: { trigger: 'my/project' } }
+ end
+
+ it { is_expected.to be_bridge }
+ end
+
+ context 'when trigger definition is empty' do
+ let(:attributes) do
+ { name: 'rspec', ref: 'master', options: { trigger: '' } }
+ end
+
+ it { is_expected.not_to be_bridge }
+ end
+
+ context 'when job is not a bridge' do
+ it { is_expected.not_to be_bridge }
end
end
describe '#to_resource' do
- it 'returns a valid build resource' do
- expect(subject.to_resource).to be_a(::Ci::Build)
- expect(subject.to_resource).to be_valid
+ context 'when job is not a bridge' do
+ it 'returns a valid build resource' do
+ expect(subject.to_resource).to be_a(::Ci::Build)
+ expect(subject.to_resource).to be_valid
+ end
+ end
+
+ context 'when job is a bridge' do
+ let(:attributes) do
+ { name: 'rspec', ref: 'master', options: { trigger: 'my/project' } }
+ end
+
+ it 'returns a valid bridge resource' do
+ expect(subject.to_resource).to be_a(::Ci::Bridge)
+ expect(subject.to_resource).to be_valid
+ end
end
it 'memoizes a resource object' do
diff --git a/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
index 05ce3412fd8..493ca3cd7b5 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
@@ -1,7 +1,8 @@
require 'spec_helper'
describe Gitlab::Ci::Pipeline::Seed::Stage do
- let(:pipeline) { create(:ci_empty_pipeline) }
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:attributes) do
{ name: 'test',
@@ -61,8 +62,18 @@ describe Gitlab::Ci::Pipeline::Seed::Stage do
expect(subject.seeds.map(&:attributes)).to all(include(ref: 'master'))
expect(subject.seeds.map(&:attributes)).to all(include(tag: false))
expect(subject.seeds.map(&:attributes)).to all(include(project: pipeline.project))
- expect(subject.seeds.map(&:attributes))
- .to all(include(trigger_request: pipeline.trigger_requests.first))
+ end
+
+ context 'when a legacy trigger exists' do
+ before do
+ create(:ci_trigger_request, pipeline: pipeline)
+ end
+
+ it 'returns build seeds including legacy trigger' do
+ expect(pipeline.legacy_trigger).not_to be_nil
+ expect(subject.seeds.map(&:attributes))
+ .to all(include(trigger_request: pipeline.legacy_trigger))
+ end
end
context 'when a ref is protected' do
diff --git a/spec/lib/gitlab/ci/status/external/common_spec.rb b/spec/lib/gitlab/ci/status/external/common_spec.rb
index 40871f86568..0d02c371a92 100644
--- a/spec/lib/gitlab/ci/status/external/common_spec.rb
+++ b/spec/lib/gitlab/ci/status/external/common_spec.rb
@@ -11,7 +11,7 @@ describe Gitlab::Ci::Status::External::Common do
end
subject do
- Gitlab::Ci::Status::Core
+ Gitlab::Ci::Status::Success
.new(external_status, user)
.extend(described_class)
end
@@ -20,6 +20,22 @@ describe Gitlab::Ci::Status::External::Common do
it 'returns description' do
expect(subject.label).to eq external_description
end
+
+ context 'when description is nil' do
+ let(:external_description) { nil }
+
+ it 'uses core status label' do
+ expect(subject.label).to eq('passed')
+ end
+ end
+
+ context 'when description is empty string' do
+ let(:external_description) { '' }
+
+ it 'uses core status label' do
+ expect(subject.label).to eq('passed')
+ end
+ end
end
describe '#has_action?' do
diff --git a/spec/lib/gitlab/ci/templates/templates_spec.rb b/spec/lib/gitlab/ci/templates/templates_spec.rb
index 0dd74399a47..fbbd58280a9 100644
--- a/spec/lib/gitlab/ci/templates/templates_spec.rb
+++ b/spec/lib/gitlab/ci/templates/templates_spec.rb
@@ -3,9 +3,40 @@
require 'spec_helper'
describe "CI YML Templates" do
- Gitlab::Template::GitlabCiYmlTemplate.all.each do |template|
- it "#{template.name} should be valid" do
- expect { Gitlab::Ci::YamlProcessor.new(template.content) }.not_to raise_error
+ ABSTRACT_TEMPLATES = %w[Serverless].freeze
+
+ def self.concrete_templates
+ Gitlab::Template::GitlabCiYmlTemplate.all.reject do |template|
+ ABSTRACT_TEMPLATES.include?(template.name)
+ end
+ end
+
+ def self.abstract_templates
+ Gitlab::Template::GitlabCiYmlTemplate.all.select do |template|
+ ABSTRACT_TEMPLATES.include?(template.name)
+ end
+ end
+
+ describe 'concrete templates with CI/CD jobs' do
+ concrete_templates.each do |template|
+ it "#{template.name} template should be valid" do
+ expect { Gitlab::Ci::YamlProcessor.new(template.content) }
+ .not_to raise_error
+ end
+ end
+ end
+
+ describe 'abstract templates without concrete jobs defined' do
+ abstract_templates.each do |template|
+ it "#{template.name} template should be valid after being implemented" do
+ content = template.content + <<~EOS
+ concrete_build_implemented_by_a_user:
+ stage: build
+ script: do something
+ EOS
+
+ expect { Gitlab::Ci::YamlProcessor.new(content) }.not_to raise_error
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
index 8bf44acb228..3ff2fe18c15 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -6,7 +6,7 @@ describe Gitlab::Ci::Variables::Collection::Item do
let(:expected_value) { variable_value }
let(:variable) do
- { key: variable_key, value: variable_value, public: true }
+ { key: variable_key, value: variable_value, public: true, masked: false }
end
describe '.new' do
@@ -88,7 +88,7 @@ describe Gitlab::Ci::Variables::Collection::Item do
resource = described_class.fabricate(variable)
expect(resource).to be_a(described_class)
- expect(resource).to eq(key: 'CI_VAR', value: '123', public: false)
+ expect(resource).to eq(key: 'CI_VAR', value: '123', public: false, masked: false)
end
it 'supports using another collection item' do
@@ -134,7 +134,21 @@ describe Gitlab::Ci::Variables::Collection::Item do
.to_runner_variable
expect(runner_variable)
- .to eq(key: 'VAR', value: 'value', public: true, file: true)
+ .to eq(key: 'VAR', value: 'value', public: true, file: true, masked: false)
+ end
+ end
+
+ context 'when variable masking is disabled' do
+ before do
+ stub_feature_flags(variable_masking: false)
+ end
+
+ it 'does not expose the masked field to the runner' do
+ runner_variable = described_class
+ .new(key: 'VAR', value: 'value', masked: true)
+ .to_runner_variable
+
+ expect(runner_variable).to eq(key: 'VAR', value: 'value', public: true)
end
end
end
diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb
index 5c91816a586..8e732d44d5d 100644
--- a/spec/lib/gitlab/ci/variables/collection_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Gitlab::Ci::Variables::Collection do
describe '.new' do
it 'can be initialized with an array' do
- variable = { key: 'VAR', value: 'value', public: true }
+ variable = { key: 'VAR', value: 'value', public: true, masked: false }
collection = described_class.new([variable])
@@ -66,6 +66,14 @@ describe Gitlab::Ci::Variables::Collection do
expect(collection).to include(key: 'VAR_3', value: '3', public: true)
end
+ it 'does not concatenate resource if it undefined' do
+ collection = described_class.new([{ key: 'VAR_1', value: '1' }])
+
+ collection.concat(nil)
+
+ expect(collection).to be_one
+ end
+
it 'returns self' do
expect(subject.concat([key: 'VAR', value: 'test']))
.to eq subject
@@ -93,7 +101,7 @@ describe Gitlab::Ci::Variables::Collection do
collection = described_class.new([{ key: 'TEST', value: '1' }])
expect(collection.to_runner_variables)
- .to eq [{ key: 'TEST', value: '1', public: true }]
+ .to eq [{ key: 'TEST', value: '1', public: true, masked: false }]
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 441e8214181..29638ef47c5 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -3,10 +3,10 @@ require 'spec_helper'
module Gitlab
module Ci
describe YamlProcessor do
- subject { described_class.new(config) }
+ subject { described_class.new(config, user: nil) }
describe '#build_attributes' do
- subject { described_class.new(config).build_attributes(:rspec) }
+ subject { described_class.new(config, user: nil).build_attributes(:rspec) }
describe 'attributes list' do
let(:config) do
@@ -21,16 +21,12 @@ module Gitlab
stage: "test",
stage_idx: 1,
name: "rspec",
- commands: "pwd\nrspec",
- coverage_regex: nil,
- tag_list: [],
options: {
before_script: ["pwd"],
script: ["rspec"]
},
allow_failure: false,
when: "on_success",
- environment: nil,
yaml_variables: []
})
end
@@ -155,13 +151,9 @@ module Gitlab
builds:
[{ stage_idx: 1,
stage: "test",
- commands: "rspec",
- tag_list: [],
name: "rspec",
allow_failure: false,
when: "on_success",
- environment: nil,
- coverage_regex: nil,
yaml_variables: [],
options: { script: ["rspec"] },
only: { refs: ["branches"] },
@@ -171,13 +163,9 @@ module Gitlab
builds:
[{ stage_idx: 2,
stage: "deploy",
- commands: "cap prod",
- tag_list: [],
name: "prod",
allow_failure: false,
when: "on_success",
- environment: nil,
- coverage_regex: nil,
yaml_variables: [],
options: { script: ["cap prod"] },
only: { refs: ["tags"] },
@@ -271,7 +259,7 @@ module Gitlab
end
it "return commands with scripts concencaced" do
- expect(subject[:commands]).to eq("global script\nscript")
+ expect(subject[:options][:before_script]).to eq(["global script"])
end
end
@@ -284,7 +272,7 @@ module Gitlab
end
it "return commands with scripts concencaced" do
- expect(subject[:commands]).to eq("local script\nscript")
+ expect(subject[:options][:before_script]).to eq(["local script"])
end
end
end
@@ -297,7 +285,7 @@ module Gitlab
end
it "return commands with scripts concencaced" do
- expect(subject[:commands]).to eq("script")
+ expect(subject[:options][:script]).to eq(["script"])
end
end
@@ -347,9 +335,6 @@ module Gitlab
stage: "test",
stage_idx: 1,
name: "rspec",
- commands: "pwd\nrspec",
- coverage_regex: nil,
- tag_list: [],
options: {
before_script: ["pwd"],
script: ["rspec"],
@@ -360,7 +345,6 @@ module Gitlab
},
allow_failure: false,
when: "on_success",
- environment: nil,
yaml_variables: []
})
end
@@ -382,9 +366,6 @@ module Gitlab
stage: "test",
stage_idx: 1,
name: "rspec",
- commands: "pwd\nrspec",
- coverage_regex: nil,
- tag_list: [],
options: {
before_script: ["pwd"],
script: ["rspec"],
@@ -395,7 +376,6 @@ module Gitlab
},
allow_failure: false,
when: "on_success",
- environment: nil,
yaml_variables: []
})
end
@@ -415,9 +395,6 @@ module Gitlab
stage: "test",
stage_idx: 1,
name: "rspec",
- commands: "pwd\nrspec",
- coverage_regex: nil,
- tag_list: [],
options: {
before_script: ["pwd"],
script: ["rspec"],
@@ -426,7 +403,6 @@ module Gitlab
},
allow_failure: false,
when: "on_success",
- environment: nil,
yaml_variables: []
})
end
@@ -444,9 +420,6 @@ module Gitlab
stage: "test",
stage_idx: 1,
name: "rspec",
- commands: "pwd\nrspec",
- coverage_regex: nil,
- tag_list: [],
options: {
before_script: ["pwd"],
script: ["rspec"],
@@ -455,7 +428,6 @@ module Gitlab
},
allow_failure: false,
when: "on_success",
- environment: nil,
yaml_variables: []
})
end
@@ -596,7 +568,7 @@ module Gitlab
it 'correctly extends rspec job' do
expect(config_processor.builds).to be_one
- expect(subject.dig(:commands)).to eq 'test'
+ expect(subject.dig(:options, :script)).to eq %w(test)
expect(subject.dig(:options, :image, :name)).to eq 'ruby:alpine'
end
end
@@ -622,13 +594,93 @@ module Gitlab
it 'correctly extends rspec job' do
expect(config_processor.builds).to be_one
- expect(subject.dig(:commands)).to eq "bundle install\nrspec"
+ expect(subject.dig(:options, :before_script)).to eq ["bundle install"]
+ expect(subject.dig(:options, :script)).to eq %w(rspec)
expect(subject.dig(:options, :image, :name)).to eq 'image:test'
expect(subject.dig(:when)).to eq 'always'
end
end
end
+ describe "Include" do
+ let(:opts) { {} }
+
+ let(:config) do
+ {
+ include: include_content,
+ rspec: { script: "test" }
+ }
+ end
+
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config), opts) }
+
+ context "when validating a ci config file with no project context" do
+ context "when an array is provided" do
+ let(:include_content) { ["/local.gitlab-ci.yml"] }
+
+ it "does not return any error" do
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context "when an array of wrong keyed object is provided" do
+ let(:include_content) { [{ yolo: "/local.gitlab-ci.yml" }] }
+
+ it "returns a validation error" do
+ expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError)
+ end
+ end
+
+ context "when an array of mixed typed objects is provided" do
+ let(:include_content) do
+ [
+ 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml',
+ '/templates/.after-script-template.yml',
+ { template: 'Auto-DevOps.gitlab-ci.yml' }
+ ]
+ end
+
+ it "does not return any error" do
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context "when the include type is incorrect" do
+ let(:include_content) { { name: "/local.gitlab-ci.yml" } }
+
+ it "returns an invalid configuration error" do
+ expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError)
+ end
+ end
+ end
+
+ context "when validating a ci config file within a project" do
+ let(:include_content) { "/local.gitlab-ci.yml" }
+ let(:project) { create(:project, :repository) }
+ let(:opts) { { project: project, sha: project.commit.sha } }
+
+ context "when the included internal file is present" do
+ before do
+ expect(project.repository).to receive(:blob_data_at)
+ .and_return(YAML.dump({ job1: { script: 'hello' } }))
+ end
+
+ it "does not return an error" do
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context "when the included internal file is not present" do
+ it "returns an error with missing file details" do
+ expect { subject }.to raise_error(
+ Gitlab::Ci::YamlProcessor::ValidationError,
+ "Local file `#{include_content}` does not exist!"
+ )
+ end
+ end
+ end
+ end
+
describe "When" do
%w(on_success on_failure always).each do |when_state|
it "returns #{when_state} when defined" do
@@ -769,9 +821,6 @@ module Gitlab
stage: "test",
stage_idx: 1,
name: "rspec",
- commands: "pwd\nrspec",
- coverage_regex: nil,
- tag_list: [],
options: {
before_script: ["pwd"],
script: ["rspec"],
@@ -786,7 +835,6 @@ module Gitlab
},
when: "on_success",
allow_failure: false,
- environment: nil,
yaml_variables: []
})
end
@@ -895,7 +943,7 @@ module Gitlab
end
context 'without matching job' do
- let(:close_review) { nil }
+ let(:close_review) { nil }
it 'raises error' do
expect { builds }.to raise_error('review job: on_stop job close_review is not defined')
@@ -983,15 +1031,11 @@ module Gitlab
stage: "test",
stage_idx: 1,
name: "normal_job",
- commands: "test",
- coverage_regex: nil,
- tag_list: [],
options: {
script: ["test"]
},
when: "on_success",
allow_failure: false,
- environment: nil,
yaml_variables: []
})
end
@@ -1031,30 +1075,22 @@ module Gitlab
stage: "build",
stage_idx: 0,
name: "job1",
- commands: "execute-script-for-job",
- coverage_regex: nil,
- tag_list: [],
options: {
script: ["execute-script-for-job"]
},
when: "on_success",
allow_failure: false,
- environment: nil,
yaml_variables: []
})
expect(subject.second).to eq({
stage: "build",
stage_idx: 0,
name: "job2",
- commands: "execute-script-for-job",
- coverage_regex: nil,
- tag_list: [],
options: {
script: ["execute-script-for-job"]
},
when: "on_success",
allow_failure: false,
- environment: nil,
yaml_variables: []
})
end
diff --git a/spec/lib/gitlab/cleanup/remote_uploads_spec.rb b/spec/lib/gitlab/cleanup/remote_uploads_spec.rb
index 8d03baeb07b..35642cd6e50 100644
--- a/spec/lib/gitlab/cleanup/remote_uploads_spec.rb
+++ b/spec/lib/gitlab/cleanup/remote_uploads_spec.rb
@@ -25,7 +25,7 @@ describe Gitlab::Cleanup::RemoteUploads do
expect(::Fog::Storage).to receive(:new).and_return(connection)
- expect(connection).to receive(:directories).and_return(double(get: directory))
+ expect(connection).to receive(:directories).and_return(double(new: directory))
expect(directory).to receive(:files).and_return(remote_files)
end
diff --git a/spec/lib/gitlab/config/entry/configurable_spec.rb b/spec/lib/gitlab/config/entry/configurable_spec.rb
index 85a7cf1d241..37e38e49c0d 100644
--- a/spec/lib/gitlab/config/entry/configurable_spec.rb
+++ b/spec/lib/gitlab/config/entry/configurable_spec.rb
@@ -7,6 +7,10 @@ describe Gitlab::Config::Entry::Configurable do
end
end
+ before do
+ allow(entry).to receive(:default)
+ end
+
describe 'validations' do
context 'when entry is a hash' do
let(:instance) { entry.new(key: 'value') }
@@ -26,9 +30,11 @@ describe Gitlab::Config::Entry::Configurable do
end
describe 'configured entries' do
+ let(:entry_class) { double('entry_class', default: nil) }
+
before do
- entry.class_eval do
- entry :object, Object, description: 'test object'
+ entry.class_exec(entry_class) do |entry_class|
+ entry :object, entry_class, description: 'test object'
end
end
diff --git a/spec/lib/gitlab/current_settings_spec.rb b/spec/lib/gitlab/current_settings_spec.rb
index 55490f37ac7..17d5eae24f5 100644
--- a/spec/lib/gitlab/current_settings_spec.rb
+++ b/spec/lib/gitlab/current_settings_spec.rb
@@ -54,7 +54,7 @@ describe Gitlab::CurrentSettings do
expect(ApplicationSetting).not_to receive(:current)
end
- it 'returns an in-memory ApplicationSetting object' do
+ it 'returns a FakeApplicationSettings object' do
expect(described_class.current_application_settings).to be_a(Gitlab::FakeApplicationSettings)
end
@@ -91,6 +91,14 @@ describe Gitlab::CurrentSettings do
allow(ActiveRecord::Base.connection).to receive(:cached_table_exists?).with('application_settings').and_return(true)
end
+ context 'with RequestStore enabled', :request_store do
+ it 'fetches the settings from DB only once' do
+ described_class.current_application_settings # warm the cache
+
+ expect(ActiveRecord::QueryRecorder.new { described_class.current_application_settings }.count).to eq(0)
+ end
+ end
+
it 'creates default ApplicationSettings if none are present' do
settings = described_class.current_application_settings
@@ -99,34 +107,45 @@ describe Gitlab::CurrentSettings do
expect(settings).to have_attributes(settings_from_defaults)
end
- context 'with migrations pending' do
+ context 'with pending migrations' do
before do
expect(ActiveRecord::Migrator).to receive(:needs_migration?).and_return(true)
end
- it 'returns an in-memory ApplicationSetting object' do
- settings = described_class.current_application_settings
+ shared_examples 'a non-persisted ApplicationSetting object' do
+ let(:current_settings) { described_class.current_application_settings }
+
+ it 'returns a non-persisted ApplicationSetting object' do
+ expect(current_settings).to be_a(ApplicationSetting)
+ expect(current_settings).not_to be_persisted
+ end
+
+ it 'uses the default value from ApplicationSetting.defaults' do
+ expect(current_settings.signup_enabled).to eq(ApplicationSetting.defaults[:signup_enabled])
+ end
+
+ it 'uses the default value from custom ApplicationSetting accessors' do
+ expect(current_settings.commit_email_hostname).to eq(ApplicationSetting.default_commit_email_hostname)
+ end
+
+ it 'responds to predicate methods' do
+ expect(current_settings.signup_enabled?).to eq(current_settings.signup_enabled)
+ end
+ end
- expect(settings).to be_a(Gitlab::FakeApplicationSettings)
- expect(settings.sign_in_enabled?).to eq(settings.sign_in_enabled)
- expect(settings.sign_up_enabled?).to eq(settings.sign_up_enabled)
+ context 'with no ApplicationSetting DB record' do
+ it_behaves_like 'a non-persisted ApplicationSetting object'
end
- it 'uses the existing database settings and falls back to defaults' do
- db_settings = create(:application_setting,
- home_page_url: 'http://mydomain.com',
- signup_enabled: false)
- settings = described_class.current_application_settings
- app_defaults = ApplicationSetting.last
-
- expect(settings).to be_a(Gitlab::FakeApplicationSettings)
- expect(settings.home_page_url).to eq(db_settings.home_page_url)
- expect(settings.signup_enabled?).to be_falsey
- expect(settings.signup_enabled).to be_falsey
-
- # Check that unspecified values use the defaults
- settings.reject! { |key, _| [:home_page_url, :signup_enabled].include? key }
- settings.each { |key, _| expect(settings[key]).to eq(app_defaults[key]) }
+ context 'with an existing ApplicationSetting DB record' do
+ let!(:db_settings) { ApplicationSetting.build_from_defaults(home_page_url: 'http://mydomain.com').save! && ApplicationSetting.last }
+ let(:current_settings) { described_class.current_application_settings }
+
+ it_behaves_like 'a non-persisted ApplicationSetting object'
+
+ it 'uses the value from the DB attribute if present and not overridden by an accessor' do
+ expect(current_settings.home_page_url).to eq(db_settings.home_page_url)
+ end
end
end
@@ -138,17 +157,12 @@ describe Gitlab::CurrentSettings do
end
end
- context 'when the application_settings table does not exists' do
- it 'returns an in-memory ApplicationSetting object' do
- expect(ApplicationSetting).to receive(:create_from_defaults).and_raise(ActiveRecord::StatementInvalid)
-
- expect(described_class.current_application_settings).to be_a(Gitlab::FakeApplicationSettings)
- end
- end
-
- context 'when the application_settings table is not fully migrated' do
- it 'returns an in-memory ApplicationSetting object' do
- expect(ApplicationSetting).to receive(:create_from_defaults).and_raise(ActiveRecord::UnknownAttributeError)
+ context 'when the application_settings table does not exist' do
+ it 'returns a FakeApplicationSettings object' do
+ expect(Gitlab::Database)
+ .to receive(:cached_table_exists?)
+ .with('application_settings')
+ .and_return(false)
expect(described_class.current_application_settings).to be_a(Gitlab::FakeApplicationSettings)
end
diff --git a/spec/lib/gitlab/danger/helper_spec.rb b/spec/lib/gitlab/danger/helper_spec.rb
new file mode 100644
index 00000000000..66cd8171c12
--- /dev/null
+++ b/spec/lib/gitlab/danger/helper_spec.rb
@@ -0,0 +1,303 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+require 'webmock/rspec'
+
+require 'gitlab/danger/helper'
+
+describe Gitlab::Danger::Helper do
+ using RSpec::Parameterized::TableSyntax
+
+ class FakeDanger
+ include Gitlab::Danger::Helper
+
+ attr_reader :git
+
+ def initialize(git:)
+ @git = git
+ end
+ end
+
+ let(:teammate_json) do
+ <<~JSON
+ [
+ {
+ "username": "in-gitlab-ce",
+ "name": "CE maintainer",
+ "projects":{ "gitlab-ce": "maintainer backend" }
+ },
+ {
+ "username": "in-gitlab-ee",
+ "name": "EE reviewer",
+ "projects":{ "gitlab-ee": "reviewer frontend" }
+ }
+ ]
+ JSON
+ end
+
+ let(:ce_teammate_matcher) do
+ satisfy do |teammate|
+ teammate.username == 'in-gitlab-ce' &&
+ teammate.name == 'CE maintainer' &&
+ teammate.projects == { 'gitlab-ce' => 'maintainer backend' }
+ end
+ end
+
+ let(:ee_teammate_matcher) do
+ satisfy do |teammate|
+ teammate.username == 'in-gitlab-ee' &&
+ teammate.name == 'EE reviewer' &&
+ teammate.projects == { 'gitlab-ee' => 'reviewer frontend' }
+ end
+ end
+
+ let(:fake_git) { double('fake-git') }
+
+ subject(:helper) { FakeDanger.new(git: fake_git) }
+
+ describe '#all_changed_files' do
+ subject { helper.all_changed_files }
+
+ it 'interprets a list of changes from the danger git plugin' do
+ expect(fake_git).to receive(:added_files) { %w[a b c.old] }
+ expect(fake_git).to receive(:modified_files) { %w[d e] }
+ expect(fake_git)
+ .to receive(:renamed_files)
+ .at_least(:once)
+ .and_return([{ before: 'c.old', after: 'c.new' }])
+
+ is_expected.to contain_exactly('a', 'b', 'c.new', 'd', 'e')
+ end
+ end
+
+ describe '#ee?' do
+ subject { helper.ee? }
+
+ it 'returns true if CI_PROJECT_NAME if set to gitlab-ee' do
+ stub_env('CI_PROJECT_NAME', 'gitlab-ee')
+ expect(File).not_to receive(:exist?)
+
+ is_expected.to be_truthy
+ end
+
+ it 'delegates to CHANGELOG-EE.md existence if CI_PROJECT_NAME is set to something else' do
+ stub_env('CI_PROJECT_NAME', 'something else')
+ expect(File).to receive(:exist?).with('../../CHANGELOG-EE.md') { true }
+
+ is_expected.to be_truthy
+ end
+
+ it 'returns true if CHANGELOG-EE.md exists' do
+ stub_env('CI_PROJECT_NAME', nil)
+ expect(File).to receive(:exist?).with('../../CHANGELOG-EE.md') { true }
+
+ is_expected.to be_truthy
+ end
+
+ it "returns false if CHANGELOG-EE.md doesn't exist" do
+ stub_env('CI_PROJECT_NAME', nil)
+ expect(File).to receive(:exist?).with('../../CHANGELOG-EE.md') { false }
+
+ is_expected.to be_falsy
+ end
+ end
+
+ describe '#project_name' do
+ subject { helper.project_name }
+
+ it 'returns gitlab-ee if ee? returns true' do
+ expect(helper).to receive(:ee?) { true }
+
+ is_expected.to eq('gitlab-ee')
+ end
+
+ it 'returns gitlab-ce if ee? returns false' do
+ expect(helper).to receive(:ee?) { false }
+
+ is_expected.to eq('gitlab-ce')
+ end
+ end
+
+ describe '#team' do
+ subject(:team) { helper.team }
+
+ context 'HTTP failure' do
+ before do
+ WebMock
+ .stub_request(:get, 'https://about.gitlab.com/roulette.json')
+ .to_return(status: 404)
+ end
+
+ it 'raises a pretty error' do
+ expect { team }.to raise_error(/Failed to read/)
+ end
+ end
+
+ context 'JSON failure' do
+ before do
+ WebMock
+ .stub_request(:get, 'https://about.gitlab.com/roulette.json')
+ .to_return(body: 'INVALID JSON')
+ end
+
+ it 'raises a pretty error' do
+ expect { team }.to raise_error(/Failed to parse/)
+ end
+ end
+
+ context 'success' do
+ before do
+ WebMock
+ .stub_request(:get, 'https://about.gitlab.com/roulette.json')
+ .to_return(body: teammate_json)
+ end
+
+ it 'returns an array of teammates' do
+ is_expected.to contain_exactly(ce_teammate_matcher, ee_teammate_matcher)
+ end
+
+ it 'memoizes the result' do
+ expect(team.object_id).to eq(helper.team.object_id)
+ end
+ end
+ end
+
+ describe '#project_team' do
+ subject { helper.project_team }
+
+ before do
+ WebMock
+ .stub_request(:get, 'https://about.gitlab.com/roulette.json')
+ .to_return(body: teammate_json)
+ end
+
+ it 'filters team by project_name' do
+ expect(helper)
+ .to receive(:project_name)
+ .at_least(:once)
+ .and_return('gitlab-ce')
+
+ is_expected.to contain_exactly(ce_teammate_matcher)
+ end
+ end
+
+ describe '#changes_by_category' do
+ it 'categorizes changed files' do
+ expect(fake_git).to receive(:added_files) { %w[foo foo.md foo.rb foo.js db/foo qa/foo ee/changelogs/foo.yml] }
+ allow(fake_git).to receive(:modified_files) { [] }
+ allow(fake_git).to receive(:renamed_files) { [] }
+
+ expect(helper.changes_by_category).to eq(
+ backend: %w[foo.rb],
+ database: %w[db/foo],
+ docs: %w[foo.md],
+ frontend: %w[foo.js],
+ none: %w[ee/changelogs/foo.yml],
+ qa: %w[qa/foo],
+ unknown: %w[foo]
+ )
+ end
+ end
+
+ describe '#category_for_file' do
+ where(:path, :expected_category) do
+ 'doc/foo' | :docs
+ 'CONTRIBUTING.md' | :docs
+ 'LICENSE' | :docs
+ 'MAINTENANCE.md' | :docs
+ 'PHILOSOPHY.md' | :docs
+ 'PROCESS.md' | :docs
+ 'README.md' | :docs
+
+ 'ee/doc/foo' | :unknown
+ 'ee/README' | :unknown
+
+ 'app/assets/foo' | :frontend
+ 'app/views/foo' | :frontend
+ 'public/foo' | :frontend
+ 'spec/javascripts/foo' | :frontend
+ 'spec/frontend/bar' | :frontend
+ 'vendor/assets/foo' | :frontend
+ 'jest.config.js' | :frontend
+ 'package.json' | :frontend
+ 'yarn.lock' | :frontend
+
+ 'ee/app/assets/foo' | :frontend
+ 'ee/app/views/foo' | :frontend
+ 'ee/spec/javascripts/foo' | :frontend
+ 'ee/spec/frontend/bar' | :frontend
+
+ 'app/models/foo' | :backend
+ 'bin/foo' | :backend
+ 'config/foo' | :backend
+ 'danger/foo' | :backend
+ 'lib/foo' | :backend
+ 'rubocop/foo' | :backend
+ 'scripts/foo' | :backend
+ 'spec/foo' | :backend
+ 'spec/foo/bar' | :backend
+
+ 'ee/app/foo' | :backend
+ 'ee/bin/foo' | :backend
+ 'ee/spec/foo' | :backend
+ 'ee/spec/foo/bar' | :backend
+
+ 'generator_templates/foo' | :backend
+ 'vendor/languages.yml' | :backend
+ 'vendor/licenses.csv' | :backend
+
+ 'Dangerfile' | :backend
+ 'Gemfile' | :backend
+ 'Gemfile.lock' | :backend
+ 'Procfile' | :backend
+ 'Rakefile' | :backend
+ '.gitlab-ci.yml' | :backend
+ 'FOO_VERSION' | :backend
+
+ 'ee/FOO_VERSION' | :unknown
+
+ 'db/foo' | :database
+ 'qa/foo' | :qa
+
+ 'ee/db/foo' | :database
+ 'ee/qa/foo' | :qa
+
+ 'changelogs/foo' | :none
+ 'ee/changelogs/foo' | :none
+ 'locale/gitlab.pot' | :none
+
+ 'FOO' | :unknown
+ 'foo' | :unknown
+
+ 'foo/bar.rb' | :backend
+ 'foo/bar.js' | :frontend
+ 'foo/bar.txt' | :docs
+ 'foo/bar.md' | :docs
+ end
+
+ with_them do
+ subject { helper.category_for_file(path) }
+
+ it { is_expected.to eq(expected_category) }
+ end
+ end
+
+ describe '#label_for_category' do
+ where(:category, :expected_label) do
+ :backend | '~backend'
+ :database | '~database'
+ :docs | '~Documentation'
+ :foo | '~foo'
+ :frontend | '~frontend'
+ :none | ''
+ :qa | '~QA'
+ end
+
+ with_them do
+ subject { helper.label_for_category(category) }
+
+ it { is_expected.to eq(expected_label) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index 98f1696badb..9ef987a0826 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -37,7 +37,7 @@ describe Gitlab::DataBuilder::Pipeline do
context 'pipeline without variables' do
it 'has empty variables hash' do
expect(attributes[:variables]).to be_a(Array)
- expect(attributes[:variables]).to be_empty()
+ expect(attributes[:variables]).to be_empty
end
end
diff --git a/spec/lib/gitlab/data_builder/push_spec.rb b/spec/lib/gitlab/data_builder/push_spec.rb
index befdc18d1aa..0c4decc6518 100644
--- a/spec/lib/gitlab/data_builder/push_spec.rb
+++ b/spec/lib/gitlab/data_builder/push_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::DataBuilder::Push do
let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
+ let(:user) { build(:user, public_email: 'public-email@example.com') }
describe '.build_sample' do
let(:data) { described_class.build_sample(project, user) }
@@ -36,7 +36,7 @@ describe Gitlab::DataBuilder::Push do
it { expect(data[:user_id]).to eq(user.id) }
it { expect(data[:user_name]).to eq(user.name) }
it { expect(data[:user_username]).to eq(user.username) }
- it { expect(data[:user_email]).to eq(user.email) }
+ it { expect(data[:user_email]).to eq(user.public_email) }
it { expect(data[:user_avatar]).to eq(user.avatar_url) }
it { expect(data[:project_id]).to eq(project.id) }
it { expect(data[:project]).to be_a(Hash) }
diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
index 248cca25a2c..81419e51635 100644
--- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
+++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
@@ -19,7 +19,7 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :delete
Project.find(project.id)
end
- describe "#remove_last_ocurrence" do
+ describe "#remove_last_occurrence" do
it "removes only the last occurrence of a string" do
input = "this/is/a-word-to-replace/namespace/with/a-word-to-replace"
diff --git a/spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb b/spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb
index 4d222564fd0..0ebd8994636 100644
--- a/spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb
+++ b/spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb
@@ -50,8 +50,8 @@ describe Gitlab::DependencyLinker::ComposerJsonLinker do
%{<a href="#{url}" rel="nofollow noreferrer noopener" target="_blank">#{name}</a>}
end
- it 'links the module name' do
- expect(subject).to include(link('laravel/laravel', 'https://packagist.org/packages/laravel/laravel'))
+ it 'does not link the module name' do
+ expect(subject).not_to include(link('laravel/laravel', 'https://packagist.org/packages/laravel/laravel'))
end
it 'links the homepage' do
diff --git a/spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb b/spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb
index a97803b119e..f00f6b47b94 100644
--- a/spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb
+++ b/spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb
@@ -41,13 +41,16 @@ describe Gitlab::DependencyLinker::GemfileLinker do
end
it 'links dependencies' do
- expect(subject).to include(link('rails', 'https://rubygems.org/gems/rails'))
expect(subject).to include(link('rails-deprecated_sanitizer', 'https://rubygems.org/gems/rails-deprecated_sanitizer'))
- expect(subject).to include(link('responders', 'https://rubygems.org/gems/responders'))
- expect(subject).to include(link('sprockets', 'https://rubygems.org/gems/sprockets'))
expect(subject).to include(link('default_value_for', 'https://rubygems.org/gems/default_value_for'))
end
+ it 'links to external dependencies' do
+ expect(subject).to include(link('rails', 'https://github.com/rails/rails'))
+ expect(subject).to include(link('responders', 'https://github.com/rails/responders'))
+ expect(subject).to include(link('sprockets', 'https://gitlab.example.com/gems/sprockets'))
+ end
+
it 'links GitHub repos' do
expect(subject).to include(link('rails/rails', 'https://github.com/rails/rails'))
expect(subject).to include(link('rails/responders', 'https://github.com/rails/responders'))
diff --git a/spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb b/spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb
index 24ad7d12f4c..6c6a5d70576 100644
--- a/spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb
+++ b/spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb
@@ -43,8 +43,8 @@ describe Gitlab::DependencyLinker::GemspecLinker do
%{<a href="#{url}" rel="nofollow noreferrer noopener" target="_blank">#{name}</a>}
end
- it 'links the gem name' do
- expect(subject).to include(link('gitlab_git', 'https://rubygems.org/gems/gitlab_git'))
+ it 'does not link the gem name' do
+ expect(subject).not_to include(link('gitlab_git', 'https://rubygems.org/gems/gitlab_git'))
end
it 'links the license' do
diff --git a/spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb b/spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb
index 1e8b72afb7b..9050127af7f 100644
--- a/spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb
+++ b/spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb
@@ -33,7 +33,8 @@ describe Gitlab::DependencyLinker::PackageJsonLinker do
"express": "4.2.x",
"bigpipe": "bigpipe/pagelet",
"plates": "https://github.com/flatiron/plates/tarball/master",
- "karma": "^1.4.1"
+ "karma": "^1.4.1",
+ "random": "git+https://EdOverflow@github.com/example/example.git"
},
"devDependencies": {
"vows": "^0.7.0",
@@ -51,8 +52,8 @@ describe Gitlab::DependencyLinker::PackageJsonLinker do
%{<a href="#{url}" rel="nofollow noreferrer noopener" target="_blank">#{name}</a>}
end
- it 'links the module name' do
- expect(subject).to include(link('module-name', 'https://npmjs.com/package/module-name'))
+ it 'does not link the module name' do
+ expect(subject).not_to include(link('module-name', 'https://npmjs.com/package/module-name'))
end
it 'links the homepage' do
@@ -71,14 +72,21 @@ describe Gitlab::DependencyLinker::PackageJsonLinker do
expect(subject).to include(link('primus', 'https://npmjs.com/package/primus'))
expect(subject).to include(link('async', 'https://npmjs.com/package/async'))
expect(subject).to include(link('express', 'https://npmjs.com/package/express'))
- expect(subject).to include(link('bigpipe', 'https://npmjs.com/package/bigpipe'))
- expect(subject).to include(link('plates', 'https://npmjs.com/package/plates'))
expect(subject).to include(link('karma', 'https://npmjs.com/package/karma'))
expect(subject).to include(link('vows', 'https://npmjs.com/package/vows'))
expect(subject).to include(link('assume', 'https://npmjs.com/package/assume'))
expect(subject).to include(link('pre-commit', 'https://npmjs.com/package/pre-commit'))
end
+ it 'links dependencies to URL detected on value' do
+ expect(subject).to include(link('bigpipe', 'https://github.com/bigpipe/pagelet'))
+ expect(subject).to include(link('plates', 'https://github.com/flatiron/plates/tarball/master'))
+ end
+
+ it 'does not link to NPM when invalid git URL' do
+ expect(subject).not_to include(link('random', 'https://npmjs.com/package/random'))
+ end
+
it 'links GitHub repos' do
expect(subject).to include(link('bigpipe/pagelet', 'https://github.com/bigpipe/pagelet'))
end
diff --git a/spec/lib/gitlab/dependency_linker/parser/gemfile_spec.rb b/spec/lib/gitlab/dependency_linker/parser/gemfile_spec.rb
new file mode 100644
index 00000000000..9bfb1b13a2b
--- /dev/null
+++ b/spec/lib/gitlab/dependency_linker/parser/gemfile_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Gitlab::DependencyLinker::Parser::Gemfile do
+ describe '#parse' do
+ let(:file_content) do
+ <<-CONTENT.strip_heredoc
+ source 'https://rubygems.org'
+
+ gem "rails", '4.2.6', github: "rails/rails"
+ gem 'rails-deprecated_sanitizer', '~> 1.0.3'
+ gem 'responders', '~> 2.0', :github => 'rails/responders'
+ gem 'sprockets', '~> 3.6.0', git: 'https://gitlab.example.com/gems/sprockets'
+ gem 'default_value_for', '~> 3.0.0'
+ CONTENT
+ end
+
+ subject { described_class.new(file_content).parse(keyword: 'gem') }
+
+ def fetch_package(name)
+ subject.find { |package| package.name == name }
+ end
+
+ it 'returns parsed packages' do
+ expect(subject.size).to eq(5)
+ expect(subject).to all(be_a(Gitlab::DependencyLinker::Package))
+ end
+
+ it 'packages respond to name and external_ref accordingly' do
+ expect(fetch_package('rails')).to have_attributes(name: 'rails',
+ github_ref: 'rails/rails',
+ git_ref: nil)
+
+ expect(fetch_package('sprockets')).to have_attributes(name: 'sprockets',
+ github_ref: nil,
+ git_ref: 'https://gitlab.example.com/gems/sprockets')
+
+ expect(fetch_package('default_value_for')).to have_attributes(name: 'default_value_for',
+ github_ref: nil,
+ git_ref: nil)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb b/spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb
index cdfd7ad9826..8f1b523653e 100644
--- a/spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb
+++ b/spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb
@@ -43,7 +43,10 @@ describe Gitlab::DependencyLinker::PodfileLinker do
it 'links packages' do
expect(subject).to include(link('AFNetworking', 'https://cocoapods.org/pods/AFNetworking'))
- expect(subject).to include(link('Interstellar/Core', 'https://cocoapods.org/pods/Interstellar'))
+ end
+
+ it 'links external packages' do
+ expect(subject).to include(link('Interstellar/Core', 'https://github.com/ashfurrow/Interstellar.git'))
end
it 'links Git repos' do
diff --git a/spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb b/spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb
index ed60ab45955..bacec830103 100644
--- a/spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb
+++ b/spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb
@@ -42,8 +42,8 @@ describe Gitlab::DependencyLinker::PodspecLinker do
%{<a href="#{url}" rel="nofollow noreferrer noopener" target="_blank">#{name}</a>}
end
- it 'links the gem name' do
- expect(subject).to include(link('Reachability', 'https://cocoapods.org/pods/Reachability'))
+ it 'does not link the pod name' do
+ expect(subject).not_to include(link('Reachability', 'https://cocoapods.org/pods/Reachability'))
end
it 'links the license' do
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index b15d22c634a..862590268ca 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -310,7 +310,7 @@ describe Gitlab::Diff::File do
context 'when the content changed' do
context 'when the file represented by the diff file is binary' do
before do
- allow(diff_file).to receive(:raw_binary?).and_return(true)
+ allow(diff_file).to receive(:binary?).and_return(true)
end
it 'returns a No Preview viewer' do
@@ -345,7 +345,7 @@ describe Gitlab::Diff::File do
context 'when the file represented by the diff file is binary' do
before do
- allow(diff_file).to receive(:raw_binary?).and_return(true)
+ allow(diff_file).to receive(:binary?).and_return(true)
end
it 'returns an Added viewer' do
@@ -380,7 +380,7 @@ describe Gitlab::Diff::File do
context 'when the file represented by the diff file is binary' do
before do
- allow(diff_file).to receive(:raw_binary?).and_return(true)
+ allow(diff_file).to receive(:binary?).and_return(true)
end
it 'returns a Deleted viewer' do
@@ -436,7 +436,7 @@ describe Gitlab::Diff::File do
allow(diff_file).to receive(:deleted_file?).and_return(false)
allow(diff_file).to receive(:renamed_file?).and_return(false)
allow(diff_file).to receive(:mode_changed?).and_return(false)
- allow(diff_file).to receive(:raw_text?).and_return(false)
+ allow(diff_file).to receive(:text?).and_return(false)
end
it 'returns a No Preview viewer' do
diff --git a/spec/lib/gitlab/diff/lines_unfolder_spec.rb b/spec/lib/gitlab/diff/lines_unfolder_spec.rb
index 8e00c8e0e30..8a470e12d04 100644
--- a/spec/lib/gitlab/diff/lines_unfolder_spec.rb
+++ b/spec/lib/gitlab/diff/lines_unfolder_spec.rb
@@ -185,7 +185,7 @@ describe Gitlab::Diff::LinesUnfolder do
let(:project) { create(:project) }
- let(:old_blob) { Gitlab::Git::Blob.new(data: raw_old_blob) }
+ let(:old_blob) { Blob.decorate(Gitlab::Git::Blob.new(data: raw_old_blob, size: 10)) }
let(:diff) do
Gitlab::Git::Diff.new(diff: raw_diff,
@@ -301,8 +301,7 @@ describe Gitlab::Diff::LinesUnfolder do
expected_diff_lines.each_with_index do |expected_line, i|
line = new_diff_lines[i]
- expect([line.old_pos, line.new_pos, line.text])
- .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ expect([line.old_pos, line.new_pos, line.text]).to eq(expected_line)
end
end
@@ -403,8 +402,7 @@ describe Gitlab::Diff::LinesUnfolder do
expected_diff_lines.each_with_index do |expected_line, i|
line = new_diff_lines[i]
- expect([line.old_pos, line.new_pos, line.text])
- .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ expect([line.old_pos, line.new_pos, line.text]).to eq(expected_line)
end
end
@@ -505,8 +503,7 @@ describe Gitlab::Diff::LinesUnfolder do
expected_diff_lines.each_with_index do |expected_line, i|
line = new_diff_lines[i]
- expect([line.old_pos, line.new_pos, line.text])
- .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ expect([line.old_pos, line.new_pos, line.text]).to eq(expected_line)
end
end
@@ -604,8 +601,7 @@ describe Gitlab::Diff::LinesUnfolder do
expected_diff_lines.each_with_index do |expected_line, i|
line = new_diff_lines[i]
- expect([line.old_pos, line.new_pos, line.text])
- .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ expect([line.old_pos, line.new_pos, line.text]).to eq(expected_line)
end
end
@@ -729,8 +725,7 @@ describe Gitlab::Diff::LinesUnfolder do
expected_diff_lines.each_with_index do |expected_line, i|
line = new_diff_lines[i]
- expect([line.old_pos, line.new_pos, line.text])
- .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ expect([line.old_pos, line.new_pos, line.text]).to eq(expected_line)
end
end
@@ -746,5 +741,105 @@ describe Gitlab::Diff::LinesUnfolder do
end
end
end
+
+ context 'position requires bottom expansion and no new match line' do
+ let(:position) do
+ Gitlab::Diff::Position.new(base_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ start_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ head_sha: "1487062132228de836236c522fe52fed4980a46c",
+ old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ position_type: "text",
+ old_line: 95,
+ new_line: 87)
+ end
+
+ context 'blob lines' do
+ let(:expected_blob_lines) do
+ [[94, 94, " \"url\": \"https://gitlab.gnome.org/GNOME/nautilus.git\""],
+ [95, 95, " }"],
+ [96, 96, " ]"],
+ [97, 97, " }"],
+ [98, 98, " ]"]]
+ end
+
+ it 'returns the extracted blob lines correctly' do
+ extracted_lines = subject.blob_lines
+
+ expect(extracted_lines.size).to eq(5)
+
+ extracted_lines.each_with_index do |line, i|
+ expect([line.old_line, line.new_line, line.text]).to eq(expected_blob_lines[i])
+ end
+ end
+ end
+
+ context 'diff lines' do
+ let(:expected_diff_lines) do
+ [[7, 7, "@@ -7,9 +7,6 @@"],
+ [7, 7, " \"tags\": [\"devel\", \"development\", \"nightly\"],"],
+ [8, 8, " \"desktop-file-name-prefix\": \"(Development) \","],
+ [9, 9, " \"finish-args\": ["],
+ [10, 10, "- \"--share=ipc\", \"--socket=x11\","],
+ [11, 10, "- \"--socket=wayland\","],
+ [12, 10, "- \"--talk-name=org.gnome.OnlineAccounts\","],
+ [13, 10, " \"--talk-name=org.freedesktop.Tracker1\","],
+ [14, 11, " \"--filesystem=home\","],
+ [15, 12, " \"--talk-name=org.gtk.vfs\", \"--talk-name=org.gtk.vfs.*\","],
+ [62, 59, "@@ -62,7 +59,7 @@"],
+ [62, 59, " },"],
+ [63, 60, " {"],
+ [64, 61, " \"name\": \"gnome-desktop\","],
+ [65, 62, "- \"config-opts\": [\"--disable-debug-tools\", \"--disable-udev\"],"],
+ [66, 62, "+ \"config-opts\": [\"--disable-debug-tools\", \"--disable-\"],"],
+ [66, 63, " \"sources\": ["],
+ [67, 64, " {"],
+ [68, 65, " \"type\": \"git\","],
+ [83, 80, "@@ -83,11 +80,6 @@"],
+ [83, 80, " \"buildsystem\": \"meson\","],
+ [84, 81, " \"builddir\": true,"],
+ [85, 82, " \"name\": \"nautilus\","],
+ [86, 83, "- \"config-opts\": ["],
+ [87, 83, "- \"-Denable-desktop=false\","],
+ [88, 83, "- \"-Denable-selinux=false\","],
+ [89, 83, "- \"--libdir=/app/lib\""],
+ [90, 83, "- ],"],
+ [91, 83, " \"sources\": ["],
+ [92, 84, " {"],
+ [93, 85, " \"type\": \"git\","],
+ # No new match line
+
+ # Injected blob lines
+ [94, 86, " \"url\": \"https://gitlab.gnome.org/GNOME/nautilus.git\""],
+ [95, 87, " }"],
+ [96, 88, " ]"],
+ [97, 89, " }"],
+ [98, 90, " ]"]]
+ # end
+ end
+
+ it 'return merge of blob lines with diff lines correctly' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ expected_diff_lines.each_with_index do |expected_line, i|
+ line = new_diff_lines[i]
+
+ expect([line.old_pos, line.new_pos, line.text]).to eq(expected_line)
+ end
+ end
+
+ it 'merged lines have correct line codes' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ new_diff_lines.each_with_index do |line, i|
+ old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+
+ unless line.type == 'match'
+ expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
+ end
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb
index a2eed07ca55..866550753a8 100644
--- a/spec/lib/gitlab/diff/position_tracer_spec.rb
+++ b/spec/lib/gitlab/diff/position_tracer_spec.rb
@@ -1515,8 +1515,8 @@ describe Gitlab::Diff::PositionTracer do
{ new_path: file_name, new_line: 4, change: true },
{ new_path: file_name, old_line: 3, change: true },
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 },
- { new_path: file_name, old_line: 5, change: true },
- { new_path: file_name, new_line: 7 }
+ { new_path: file_name, old_line: 5, change: true },
+ { new_path: file_name, new_line: 7 }
]
expect_new_positions(old_position_attrs, new_position_attrs)
@@ -1588,7 +1588,7 @@ describe Gitlab::Diff::PositionTracer do
{ new_path: file_name, new_line: 4, change: true },
{ old_path: file_name, old_line: 3, change: true },
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 },
- { old_path: file_name, old_line: 5, change: true },
+ { old_path: file_name, old_line: 5, change: true },
{ new_path: file_name, new_line: 7 }
]
@@ -1638,13 +1638,13 @@ describe Gitlab::Diff::PositionTracer do
new_position_attrs = [
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
{ old_path: file_name, old_line: 2 },
- { old_path: file_name, old_line: 2, change: true },
+ { old_path: file_name, old_line: 2, change: true },
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 2 },
- { old_path: file_name, old_line: 4, change: true },
+ { old_path: file_name, old_line: 4, change: true },
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 4 },
- { new_path: file_name, new_line: 5, change: true },
- { old_path: file_name, old_line: 6, change: true },
- { new_path: file_name, new_line: 6 }
+ { new_path: file_name, new_line: 5, change: true },
+ { old_path: file_name, old_line: 6, change: true },
+ { new_path: file_name, new_line: 6 }
]
expect_new_positions(old_position_attrs, new_position_attrs)
@@ -1880,7 +1880,7 @@ describe Gitlab::Diff::PositionTracer do
new_position_attrs = [
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
- { old_path: file_name, old_line: 2, change: true },
+ { old_path: file_name, old_line: 2, change: true },
{ new_path: file_name, new_line: 2 },
{ old_path: file_name, new_path: file_name, old_line: 2, new_line: 3 },
{ new_path: file_name, new_line: 4 },
diff --git a/spec/lib/gitlab/discussions_diff/file_collection_spec.rb b/spec/lib/gitlab/discussions_diff/file_collection_spec.rb
new file mode 100644
index 00000000000..0489206458b
--- /dev/null
+++ b/spec/lib/gitlab/discussions_diff/file_collection_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::DiscussionsDiff::FileCollection do
+ let(:merge_request) { create(:merge_request) }
+ let!(:diff_note_a) { create(:diff_note_on_merge_request, project: merge_request.project, noteable: merge_request) }
+ let!(:diff_note_b) { create(:diff_note_on_merge_request, project: merge_request.project, noteable: merge_request) }
+ let(:note_diff_file_a) { diff_note_a.note_diff_file }
+ let(:note_diff_file_b) { diff_note_b.note_diff_file }
+
+ subject { described_class.new([note_diff_file_a, note_diff_file_b]) }
+
+ describe '#load_highlight', :clean_gitlab_redis_shared_state do
+ it 'writes uncached diffs highlight' do
+ file_a_caching_content = diff_note_a.diff_file.highlighted_diff_lines.map(&:to_hash)
+ file_b_caching_content = diff_note_b.diff_file.highlighted_diff_lines.map(&:to_hash)
+
+ expect(Gitlab::DiscussionsDiff::HighlightCache)
+ .to receive(:write_multiple)
+ .with({ note_diff_file_a.id => file_a_caching_content,
+ note_diff_file_b.id => file_b_caching_content })
+ .and_call_original
+
+ subject.load_highlight([note_diff_file_a.id, note_diff_file_b.id])
+ end
+
+ it 'does not write cache for already cached file' do
+ subject.load_highlight([note_diff_file_a.id])
+
+ file_b_caching_content = diff_note_b.diff_file.highlighted_diff_lines.map(&:to_hash)
+
+ expect(Gitlab::DiscussionsDiff::HighlightCache)
+ .to receive(:write_multiple)
+ .with({ note_diff_file_b.id => file_b_caching_content })
+ .and_call_original
+
+ subject.load_highlight([note_diff_file_a.id, note_diff_file_b.id])
+ end
+
+ it 'does not err when given ID does not exist in @collection' do
+ expect { subject.load_highlight([999]) }.not_to raise_error
+ end
+
+ it 'loaded diff files have highlighted lines loaded' do
+ subject.load_highlight([note_diff_file_a.id])
+
+ diff_file = subject.find_by_id(note_diff_file_a.id)
+
+ expect(diff_file.highlight_loaded?).to be(true)
+ end
+
+ it 'not loaded diff files does not have highlighted lines loaded' do
+ subject.load_highlight([note_diff_file_a.id])
+
+ diff_file = subject.find_by_id(note_diff_file_b.id)
+
+ expect(diff_file.highlight_loaded?).to be(false)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb b/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb
new file mode 100644
index 00000000000..fe26ebb8796
--- /dev/null
+++ b/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::DiscussionsDiff::HighlightCache, :clean_gitlab_redis_cache do
+ describe '#write_multiple' do
+ it 'sets multiple keys serializing content as JSON' do
+ mapping = {
+ 3 => [
+ {
+ text: 'foo',
+ type: 'new',
+ index: 2,
+ old_pos: 10,
+ new_pos: 11,
+ line_code: 'xpto',
+ rich_text: '<blips>blops</blips>'
+ },
+ {
+ text: 'foo',
+ type: 'new',
+ index: 3,
+ old_pos: 11,
+ new_pos: 12,
+ line_code: 'xpto',
+ rich_text: '<blops>blips</blops>'
+ }
+ ]
+ }
+
+ described_class.write_multiple(mapping)
+
+ mapping.each do |key, value|
+ full_key = described_class.cache_key_for(key)
+ found = Gitlab::Redis::Cache.with { |r| r.get(full_key) }
+
+ expect(found).to eq(value.to_json)
+ end
+ end
+ end
+
+ describe '#read_multiple' do
+ it 'reads multiple keys and serializes content into Gitlab::Diff::Line objects' do
+ mapping = {
+ 3 => [
+ {
+ text: 'foo',
+ type: 'new',
+ index: 2,
+ old_pos: 11,
+ new_pos: 12,
+ line_code: 'xpto',
+ rich_text: '<blips>blops</blips>'
+ },
+ {
+ text: 'foo',
+ type: 'new',
+ index: 3,
+ old_pos: 10,
+ new_pos: 11,
+ line_code: 'xpto',
+ rich_text: '<blips>blops</blips>'
+ }
+ ]
+ }
+
+ described_class.write_multiple(mapping)
+
+ found = described_class.read_multiple(mapping.keys)
+
+ expect(found.size).to eq(1)
+ expect(found.first.size).to eq(2)
+ expect(found.first).to all(be_a(Gitlab::Diff::Line))
+ end
+
+ it 'returns nil when cached key is not found' do
+ mapping = {
+ 3 => [
+ {
+ text: 'foo',
+ type: 'new',
+ index: 2,
+ old_pos: 11,
+ new_pos: 12,
+ line_code: 'xpto',
+ rich_text: '<blips>blops</blips>'
+ }
+ ]
+ }
+
+ described_class.write_multiple(mapping)
+
+ found = described_class.read_multiple([2, 3])
+
+ expect(found.size).to eq(2)
+
+ expect(found.first).to eq(nil)
+ expect(found.second.size).to eq(1)
+ expect(found.second).to all(be_a(Gitlab::Diff::Line))
+ end
+ end
+end
diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
index 1d75e8cb5da..48139c2f9dc 100644
--- a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
@@ -11,7 +11,7 @@ describe Gitlab::Email::Handler::CreateIssueHandler do
stub_config_setting(host: 'localhost')
end
- let(:email_raw) { fixture_file('emails/valid_new_issue.eml') }
+ let(:email_raw) { email_fixture('emails/valid_new_issue.eml') }
let(:namespace) { create(:namespace, path: 'gitlabhq') }
let!(:project) { create(:project, :public, namespace: namespace, path: 'gitlabhq') }
@@ -23,21 +23,58 @@ describe Gitlab::Email::Handler::CreateIssueHandler do
)
end
+ context "when email key" do
+ let(:mail) { Mail::Message.new(email_raw) }
+
+ it "matches the new format" do
+ handler = described_class.new(mail, "gitlabhq-gitlabhq-#{project.project_id}-#{user.incoming_email_token}-issue")
+
+ expect(handler.instance_variable_get(:@project_id)).to eq project.project_id
+ expect(handler.instance_variable_get(:@project_slug)).to eq project.full_path_slug
+ expect(handler.instance_variable_get(:@incoming_email_token)).to eq user.incoming_email_token
+ expect(handler.can_handle?).to be_truthy
+ end
+
+ it "matches the legacy format" do
+ handler = described_class.new(mail, "h5bp/html5-boilerplate+#{user.incoming_email_token}")
+
+ expect(handler.instance_variable_get(:@project_path)).to eq 'h5bp/html5-boilerplate'
+ expect(handler.instance_variable_get(:@incoming_email_token)).to eq user.incoming_email_token
+ expect(handler.can_handle?).to be_truthy
+ end
+
+ it "doesn't match either format" do
+ handler = described_class.new(mail, "h5bp-html5-boilerplate+something+invalid")
+
+ expect(handler.can_handle?).to be_falsey
+ end
+ end
+
context "when everything is fine" do
- it "creates a new issue" do
- setup_attachment
+ shared_examples "a new issue" do
+ it "creates a new issue" do
+ setup_attachment
- expect { receiver.execute }.to change { project.issues.count }.by(1)
- issue = project.issues.last
+ expect { receiver.execute }.to change { project.issues.count }.by(1)
+ issue = project.issues.last
+
+ expect(issue.author).to eq(user)
+ expect(issue.title).to eq('New Issue by email')
+ expect(issue.description).to include('reply by email')
+ expect(issue.description).to include(markdown)
+ end
+ end
+
+ it_behaves_like "a new issue"
- expect(issue.author).to eq(user)
- expect(issue.title).to eq('New Issue by email')
- expect(issue.description).to include('reply by email')
- expect(issue.description).to include(markdown)
+ context "creates a new issue with legacy email address" do
+ let(:email_raw) { fixture_file('emails/valid_new_issue_legacy.eml') }
+
+ it_behaves_like "a new issue"
end
context "when the reply is blank" do
- let(:email_raw) { fixture_file("emails/valid_new_issue_empty.eml") }
+ let(:email_raw) { email_fixture("emails/valid_new_issue_empty.eml") }
it "creates a new issue" do
expect { receiver.execute }.to change { project.issues.count }.by(1)
@@ -50,7 +87,7 @@ describe Gitlab::Email::Handler::CreateIssueHandler do
end
context "when there are quotes in email" do
- let(:email_raw) { fixture_file("emails/valid_new_issue_with_quote.eml") }
+ let(:email_raw) { email_fixture("emails/valid_new_issue_with_quote.eml") }
it "creates a new issue" do
expect { receiver.execute }.to change { project.issues.count }.by(1)
@@ -76,7 +113,7 @@ describe Gitlab::Email::Handler::CreateIssueHandler do
end
context "when we can't find the incoming_email_token" do
- let(:email_raw) { fixture_file("emails/wrong_incoming_email_token.eml") }
+ let(:email_raw) { email_fixture("emails/wrong_issue_incoming_email_token.eml") }
it "raises an UserNotFoundError" do
expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError)
@@ -91,4 +128,8 @@ describe Gitlab::Email::Handler::CreateIssueHandler do
end
end
end
+
+ def email_fixture(path)
+ fixture_file(path).gsub('project_id', project.project_id.to_s)
+ end
end
diff --git a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb
index f276f1a8ddf..2fa86b2b46f 100644
--- a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb
@@ -15,7 +15,7 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
TestEnv.clean_test_path
end
- let(:email_raw) { fixture_file('emails/valid_new_merge_request.eml') }
+ let(:email_raw) { email_fixture('emails/valid_new_merge_request.eml') }
let(:namespace) { create(:namespace, path: 'gitlabhq') }
let!(:project) { create(:project, :public, :repository, namespace: namespace, path: 'gitlabhq') }
@@ -27,6 +27,33 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
)
end
+ context "when email key" do
+ let(:mail) { Mail::Message.new(email_raw) }
+
+ it "matches the new format" do
+ handler = described_class.new(mail, "gitlabhq-gitlabhq-#{project.project_id}-#{user.incoming_email_token}-merge-request")
+
+ expect(handler.instance_variable_get(:@project_id)).to eq project.project_id
+ expect(handler.instance_variable_get(:@project_slug)).to eq project.full_path_slug
+ expect(handler.instance_variable_get(:@incoming_email_token)).to eq user.incoming_email_token
+ expect(handler.can_handle?).to be_truthy
+ end
+
+ it "matches the legacy format" do
+ handler = described_class.new(mail, "h5bp/html5-boilerplate+merge-request+#{user.incoming_email_token}")
+
+ expect(handler.instance_variable_get(:@project_path)).to eq 'h5bp/html5-boilerplate'
+ expect(handler.instance_variable_get(:@incoming_email_token)).to eq user.incoming_email_token
+ expect(handler.can_handle?).to be_truthy
+ end
+
+ it "doesn't match either format" do
+ handler = described_class.new(mail, "h5bp-html5-boilerplate+merge-request")
+
+ expect(handler.can_handle?).to be_falsey
+ end
+ end
+
context "as a non-developer" do
before do
project.add_guest(user)
@@ -43,15 +70,25 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
end
context "when everything is fine" do
- it "creates a new merge request" do
- expect { receiver.execute }.to change { project.merge_requests.count }.by(1)
- merge_request = project.merge_requests.last
-
- expect(merge_request.author).to eq(user)
- expect(merge_request.source_branch).to eq('feature')
- expect(merge_request.title).to eq('Feature added')
- expect(merge_request.description).to eq('Merge request description')
- expect(merge_request.target_branch).to eq(project.default_branch)
+ shared_examples "a new merge request" do
+ it "creates a new merge request" do
+ expect { receiver.execute }.to change { project.merge_requests.count }.by(1)
+ merge_request = project.merge_requests.last
+
+ expect(merge_request.author).to eq(user)
+ expect(merge_request.source_branch).to eq('feature')
+ expect(merge_request.title).to eq('Feature added')
+ expect(merge_request.description).to eq('Merge request description')
+ expect(merge_request.target_branch).to eq(project.default_branch)
+ end
+ end
+
+ it_behaves_like "a new merge request"
+
+ context "creates a new merge request with legacy email address" do
+ let(:email_raw) { fixture_file('emails/valid_new_merge_request_legacy.eml') }
+
+ it_behaves_like "a new merge request"
end
end
@@ -67,7 +104,7 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
end
context "when we can't find the incoming_email_token" do
- let(:email_raw) { fixture_file("emails/wrong_incoming_email_token.eml") }
+ let(:email_raw) { email_fixture("emails/wrong_merge_request_incoming_email_token.eml") }
it "raises an UserNotFoundError" do
expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError)
@@ -75,7 +112,7 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
end
context "when the subject is blank" do
- let(:email_raw) { fixture_file("emails/valid_new_merge_request_no_subject.eml") }
+ let(:email_raw) { email_fixture("emails/valid_new_merge_request_no_subject.eml") }
it "raises an InvalidMergeRequestError" do
expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidMergeRequestError)
@@ -83,7 +120,7 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
end
context "when the message body is blank" do
- let(:email_raw) { fixture_file("emails/valid_new_merge_request_no_description.eml") }
+ let(:email_raw) { email_fixture("emails/valid_new_merge_request_no_description.eml") }
it "creates a new merge request with description set from the last commit" do
expect { receiver.execute }.to change { project.merge_requests.count }.by(1)
@@ -95,7 +132,7 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
end
context 'when the email contains patch attachments' do
- let(:email_raw) { fixture_file("emails/valid_merge_request_with_patch.eml") }
+ let(:email_raw) { email_fixture("emails/valid_merge_request_with_patch.eml") }
it 'creates the source branch and applies the patches' do
receiver.execute
@@ -120,7 +157,7 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
end
context 'when the patch could not be applied' do
- let(:email_raw) { fixture_file("emails/merge_request_with_conflicting_patch.eml") }
+ let(:email_raw) { email_fixture("emails/merge_request_with_conflicting_patch.eml") }
it 'raises an error' do
expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidAttachment)
@@ -128,7 +165,7 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
end
context 'when specifying the target branch using quick actions' do
- let(:email_raw) { fixture_file('emails/merge_request_with_patch_and_target_branch.eml') }
+ let(:email_raw) { email_fixture('emails/merge_request_with_patch_and_target_branch.eml') }
it 'creates the merge request with the correct target branch' do
receiver.execute
@@ -150,7 +187,7 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
end
describe '#patch_attachments' do
- let(:email_raw) { fixture_file('emails/merge_request_multiple_patches.eml') }
+ let(:email_raw) { email_fixture('emails/merge_request_multiple_patches.eml') }
let(:mail) { Mail::Message.new(email_raw) }
subject(:handler) { described_class.new(mail, mail_key) }
@@ -163,4 +200,8 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
expect(attachments).to eq(expected_filenames)
end
end
+
+ def email_fixture(path)
+ fixture_file(path).gsub('project_id', project.project_id.to_s)
+ 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 b1f48c15c21..50e473c459e 100644
--- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
@@ -118,11 +118,44 @@ describe Gitlab::Email::Handler::CreateNoteHandler do
end
end
- context "when everything is fine" do
+ shared_examples "checks permissions on noteable" do
+ context "when user has access" do
+ before do
+ project.add_reporter(user)
+ end
+
+ it "creates a comment" do
+ expect { receiver.execute }.to change { noteable.notes.count }.by(1)
+ end
+ end
+
+ context "when user does not have access" do
+ it "raises UserNotAuthorizedError" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotAuthorizedError)
+ end
+ end
+ end
+
+ context "when discussion is locked" do
before do
- setup_attachment
+ noteable.update_attribute(:discussion_locked, true)
+ end
+
+ it_behaves_like "checks permissions on noteable"
+ end
+
+ context "when issue is confidential" do
+ let(:issue) { create(:issue, project: project) }
+ let(:note) { create(:note, noteable: issue, project: project) }
+
+ before do
+ issue.update_attribute(:confidential, true)
end
+ it_behaves_like "checks permissions on noteable"
+ end
+
+ shared_examples 'a reply to existing comment' do
it "creates a comment" do
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
new_note = noteable.notes.last
@@ -131,8 +164,22 @@ describe Gitlab::Email::Handler::CreateNoteHandler do
expect(new_note.position).to eq(note.position)
expect(new_note.note).to include("I could not disagree more.")
expect(new_note.in_reply_to?(note)).to be_truthy
+
+ if note.part_of_discussion?
+ expect(new_note.discussion_id).to eq(note.discussion_id)
+ else
+ expect(new_note.discussion_id).not_to eq(note.discussion_id)
+ end
+ end
+ end
+
+ context "when everything is fine" do
+ before do
+ setup_attachment
end
+ it_behaves_like 'a reply to existing comment'
+
it "adds all attachments" do
receiver.execute
@@ -170,4 +217,10 @@ describe Gitlab::Email::Handler::CreateNoteHandler do
end
end
end
+
+ context "when note is not a discussion" do
+ let(:note) { create(:note_on_merge_request, project: project) }
+
+ it_behaves_like 'a reply to existing comment'
+ end
end
diff --git a/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb b/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb
index b8660b133ec..dcddd00df59 100644
--- a/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb
@@ -10,13 +10,35 @@ describe Gitlab::Email::Handler::UnsubscribeHandler do
stub_config_setting(host: 'localhost')
end
- let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, "#{mail_key}+unsubscribe") }
- let(:project) { create(:project, :public) }
- let(:user) { create(:user) }
- let(:noteable) { create(:issue, project: project) }
+ let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, "#{mail_key}#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX}") }
+ let(:project) { create(:project, :public) }
+ let(:user) { create(:user) }
+ let(:noteable) { create(:issue, project: project) }
let!(:sent_notification) { SentNotification.record(noteable, user.id, mail_key) }
+ context "when email key" do
+ let(:mail) { Mail::Message.new(email_raw) }
+
+ it "matches the new format" do
+ handler = described_class.new(mail, "#{mail_key}#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX}")
+
+ expect(handler.can_handle?).to be_truthy
+ end
+
+ it "matches the legacy format" do
+ handler = described_class.new(mail, "#{mail_key}#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY}")
+
+ expect(handler.can_handle?).to be_truthy
+ end
+
+ it "doesn't match either format" do
+ handler = described_class.new(mail, "+#{mail_key}#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX}")
+
+ expect(handler.can_handle?).to be_falsey
+ end
+ end
+
context 'when notification concerns a commit' do
let(:commit) { create(:commit, project: project) }
let!(:sent_notification) { SentNotification.record(commit, user.id, mail_key) }
@@ -40,6 +62,14 @@ describe Gitlab::Email::Handler::UnsubscribeHandler do
it 'unsubscribes user from notable' do
expect { receiver.execute }.to change { noteable.subscribed?(user) }.from(true).to(false)
end
+
+ context 'when using old style unsubscribe link' do
+ let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, "#{mail_key}#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY}") }
+
+ it 'unsubscribes user from notable' do
+ expect { receiver.execute }.to change { noteable.subscribed?(user) }.from(true).to(false)
+ end
+ end
end
context 'when the noteable could not be found' do
diff --git a/spec/lib/gitlab/email/handler_spec.rb b/spec/lib/gitlab/email/handler_spec.rb
index c651765dc0f..d2920b08956 100644
--- a/spec/lib/gitlab/email/handler_spec.rb
+++ b/spec/lib/gitlab/email/handler_spec.rb
@@ -19,7 +19,8 @@ describe Gitlab::Email::Handler do
describe 'regexps are set properly' do
let(:addresses) do
- %W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX} sent_notification_key path/to/project+merge-request+user_email_token path/to/project+user_email_token)
+ %W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX} sent_notification_key path-to-project-123-user_email_token-merge-request path-to-project-123-user_email_token-issue) +
+ %W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY} sent_notification_key path/to/project+merge-request+user_email_token path/to/project+user_email_token)
end
it 'picks each handler at least once' do
diff --git a/spec/lib/gitlab/git/blame_spec.rb b/spec/lib/gitlab/git/blame_spec.rb
index e704d1c673c..0010c0304eb 100644
--- a/spec/lib/gitlab/git/blame_spec.rb
+++ b/spec/lib/gitlab/git/blame_spec.rb
@@ -2,7 +2,7 @@
require "spec_helper"
describe Gitlab::Git::Blame, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:blame) do
Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md")
end
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index 80dd3dcc58e..a1b5cea88c0 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -3,7 +3,7 @@
require "spec_helper"
describe Gitlab::Git::Blob, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:rugged) do
Rugged::Repository.new(File.join(TestEnv.repos_path, TEST_REPO_PATH))
end
@@ -59,7 +59,7 @@ describe Gitlab::Git::Blob, :seed_helper do
it { expect(blob.data[0..10]).to eq("*.rbc\n*.sas") }
it { expect(blob.size).to eq(241) }
it { expect(blob.mode).to eq("100644") }
- it { expect(blob).not_to be_binary }
+ it { expect(blob).not_to be_binary_in_repo }
end
context 'file in root with leading slash' do
@@ -92,7 +92,7 @@ describe Gitlab::Git::Blob, :seed_helper do
end
it 'does not mark the blob as binary' do
- expect(blob).not_to be_binary
+ expect(blob).not_to be_binary_in_repo
end
end
@@ -123,7 +123,7 @@ describe Gitlab::Git::Blob, :seed_helper do
.with(hash_including(binary: true))
.and_call_original
- expect(blob).to be_binary
+ expect(blob).to be_binary_in_repo
end
end
end
@@ -196,7 +196,7 @@ 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
+ expect(blob).not_to be_binary_in_repo
end
end
diff --git a/spec/lib/gitlab/git/branch_spec.rb b/spec/lib/gitlab/git/branch_spec.rb
index 0df282d0ae3..0764e525ede 100644
--- a/spec/lib/gitlab/git/branch_spec.rb
+++ b/spec/lib/gitlab/git/branch_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Branch, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:rugged) do
Rugged::Repository.new(File.join(TestEnv.repos_path, repository.relative_path))
end
@@ -64,7 +64,7 @@ describe Gitlab::Git::Branch, :seed_helper do
context 'with active, stale and future branches' do
let(:repository) do
- Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
+ Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '', 'group/project')
end
let(:user) { create(:user) }
diff --git a/spec/lib/gitlab/git/bundle_file_spec.rb b/spec/lib/gitlab/git/bundle_file_spec.rb
new file mode 100644
index 00000000000..ff7c981dadd
--- /dev/null
+++ b/spec/lib/gitlab/git/bundle_file_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe Gitlab::Git::BundleFile do
+ describe '.check!' do
+ let(:valid_bundle) { Tempfile.new }
+ let(:valid_bundle_path) { valid_bundle.path }
+ let(:invalid_bundle_path) { Rails.root.join('spec/fixtures/malicious.bundle') }
+
+ after do
+ valid_bundle.close!
+ end
+
+ it 'returns nil for a valid bundle' do
+ valid_bundle.write("# v2 git bundle\nfoo bar baz\n")
+ valid_bundle.close
+
+ expect(described_class.check!(valid_bundle_path)).to be_nil
+ end
+
+ it 'raises an exception for an invalid bundle' do
+ expect do
+ described_class.check!(invalid_bundle_path)
+ end.to raise_error(described_class::InvalidBundleError)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index db68062e433..3fb41a626b2 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -3,7 +3,7 @@ require "spec_helper"
describe Gitlab::Git::Commit, :seed_helper do
include GitHelpers
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:rugged_repo) do
Rugged::Repository.new(File.join(TestEnv.repos_path, TEST_REPO_PATH))
end
@@ -112,7 +112,7 @@ describe Gitlab::Git::Commit, :seed_helper do
end
context 'Class methods' do
- describe '.find' do
+ shared_examples '.find' do
it "should return first head commit if without params" do
expect(described_class.last(repository).id).to eq(
rugged_repo.head.target.oid
@@ -146,7 +146,7 @@ describe Gitlab::Git::Commit, :seed_helper do
end
context 'with broken repo' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_BROKEN_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_BROKEN_REPO_PATH, '', 'group/project') }
it 'returns nil' do
expect(described_class.find(repository, SeedRepo::Commit::ID)).to be_nil
@@ -154,6 +154,20 @@ describe Gitlab::Git::Commit, :seed_helper do
end
end
+ describe '.find with Gitaly enabled' do
+ it_should_behave_like '.find'
+ end
+
+ describe '.find with Rugged enabled', :enable_rugged do
+ it 'calls out to the Rugged implementation' do
+ allow_any_instance_of(Rugged).to receive(:rev_parse).with(SeedRepo::Commit::ID).and_call_original
+
+ described_class.find(repository, SeedRepo::Commit::ID)
+ end
+
+ it_should_behave_like '.find'
+ end
+
describe '.last_for_path' do
context 'no path' do
subject { described_class.last_for_path(repository, 'master') }
diff --git a/spec/lib/gitlab/git/compare_spec.rb b/spec/lib/gitlab/git/compare_spec.rb
index 7cc6f52f8ee..65dfb93d0db 100644
--- a/spec/lib/gitlab/git/compare_spec.rb
+++ b/spec/lib/gitlab/git/compare_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Compare, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:compare) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: false) }
let(:compare_straight) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: true) }
@@ -67,7 +67,7 @@ describe Gitlab::Git::Compare, :seed_helper do
end
end
- describe '#same' do
+ describe '#same' do
subject do
compare.same
end
diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb
index 8a4415506c4..1d22329b670 100644
--- a/spec/lib/gitlab/git/diff_spec.rb
+++ b/spec/lib/gitlab/git/diff_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Diff, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:gitaly_diff) do
Gitlab::GitalyClient::Diff.new(
from_path: '.gitmodules',
diff --git a/spec/lib/gitlab/git/merge_base_spec.rb b/spec/lib/gitlab/git/merge_base_spec.rb
index 8d16d451730..dbb4e3d0b3e 100644
--- a/spec/lib/gitlab/git/merge_base_spec.rb
+++ b/spec/lib/gitlab/git/merge_base_spec.rb
@@ -62,7 +62,7 @@ describe Gitlab::Git::MergeBase do
end
describe '#commit' do
- context 'for existing refs with a merge base', :existing_refs do
+ context 'for existing refs with a merge base', :existing_refs do
it 'finds the commit for the merge base' do
expect(merge_base.commit).to be_a(Commit)
end
diff --git a/spec/lib/gitlab/git/remote_repository_spec.rb b/spec/lib/gitlab/git/remote_repository_spec.rb
index 53ed7c5a13a..e166628d4ca 100644
--- a/spec/lib/gitlab/git/remote_repository_spec.rb
+++ b/spec/lib/gitlab/git/remote_repository_spec.rb
@@ -1,15 +1,15 @@
require 'spec_helper'
describe Gitlab::Git::RemoteRepository, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ 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, '') | false
- Gitlab::Git::Repository.new('default', 'does-not-exist.git', '') | true
+ 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
@@ -44,11 +44,11 @@ describe Gitlab::Git::RemoteRepository, :seed_helper do
using RSpec::Parameterized::TableSyntax
where(:other_repository, :result) do
- repository | true
- Gitlab::Git::Repository.new(repository.storage, repository.relative_path, '') | true
- Gitlab::Git::Repository.new('broken', TEST_REPO_PATH, '') | false
- Gitlab::Git::Repository.new(repository.storage, 'wrong/relative-path.git', '') | false
- Gitlab::Git::Repository.new('broken', 'wrong/relative-path.git', '') | false
+ 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
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 852ee9c96af..7e6dfa30e37 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -19,8 +19,10 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
- let(:mutable_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:mutable_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '', 'group/project') }
+ let(:mutable_repository_path) { File.join(TestEnv.repos_path, mutable_repository.relative_path) }
+ let(:mutable_repository_rugged) { Rugged::Repository.new(mutable_repository_path) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:repository_path) { File.join(TestEnv.repos_path, repository.relative_path) }
let(:repository_rugged) { Rugged::Repository.new(repository_path) }
let(:storage_path) { TestEnv.repos_path }
@@ -29,7 +31,7 @@ describe Gitlab::Git::Repository, :seed_helper do
describe '.create_hooks' do
let(:repo_path) { File.join(storage_path, 'hook-test.git') }
let(:hooks_dir) { File.join(repo_path, 'hooks') }
- let(:target_hooks_dir) { Gitlab.config.gitlab_shell.hooks_path }
+ let(:target_hooks_dir) { Gitlab::Shell.new.hooks_path }
let(:existing_target) { File.join(repo_path, 'foobar') }
before do
@@ -281,6 +283,96 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#diverging_commit_count' do
+ it 'counts 0 for the same branch' do
+ expect(repository.diverging_commit_count('master', 'master', max_count: 1000)).to eq([0, 0])
+ end
+
+ context 'max count does not truncate results' do
+ where(:left, :right, :expected) do
+ 1 | 1 | [1, 1]
+ 4 | 4 | [4, 4]
+ 2 | 2 | [2, 2]
+ 2 | 4 | [2, 4]
+ 4 | 2 | [4, 2]
+ 10 | 10 | [10, 10]
+ end
+
+ with_them do
+ before do
+ repository.create_branch('left-branch', 'master')
+ repository.create_branch('right-branch', 'master')
+
+ left.times do
+ new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', 'left-branch', 'some more content for a', 'some stuff')
+ end
+
+ right.times do
+ new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', 'right-branch', 'some more content for b', 'some stuff')
+ end
+ end
+
+ after do
+ repository.delete_branch('left-branch')
+ repository.delete_branch('right-branch')
+ end
+
+ it 'returns the correct count bounding at max_count' do
+ branch_a_sha = repository_rugged.branches['left-branch'].target.oid
+ branch_b_sha = repository_rugged.branches['right-branch'].target.oid
+
+ count = repository.diverging_commit_count(branch_a_sha, branch_b_sha, max_count: 1000)
+
+ expect(count).to eq(expected)
+ end
+ end
+ end
+
+ context 'max count truncates results' do
+ where(:left, :right, :max_count) do
+ 1 | 1 | 1
+ 4 | 4 | 4
+ 2 | 2 | 3
+ 2 | 4 | 3
+ 4 | 2 | 5
+ 10 | 10 | 10
+ end
+
+ with_them do
+ before do
+ repository.create_branch('left-branch', 'master')
+ repository.create_branch('right-branch', 'master')
+
+ left.times do
+ new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', 'left-branch', 'some more content for a', 'some stuff')
+ end
+
+ right.times do
+ new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', 'right-branch', 'some more content for b', 'some stuff')
+ end
+ end
+
+ after do
+ repository.delete_branch('left-branch')
+ repository.delete_branch('right-branch')
+ end
+
+ it 'returns the correct count bounding at max_count' do
+ branch_a_sha = repository_rugged.branches['left-branch'].target.oid
+ branch_b_sha = repository_rugged.branches['right-branch'].target.oid
+
+ results = repository.diverging_commit_count(branch_a_sha, branch_b_sha, max_count: max_count)
+
+ expect(results[0] + results[1]).to eq(max_count)
+ end
+ end
+ end
+
+ it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::CommitService, :diverging_commit_count do
+ subject { repository.diverging_commit_count('master', 'master', max_count: 1000) }
+ end
+ end
+
describe '#has_local_branches?' do
context 'check for local branches' do
it { expect(repository.has_local_branches?).to eq(true) }
@@ -434,13 +526,13 @@ describe Gitlab::Git::Repository, :seed_helper do
describe '#fetch_repository_as_mirror' do
let(:new_repository) do
- Gitlab::Git::Repository.new('default', 'my_project.git', '')
+ Gitlab::Git::Repository.new('default', 'my_project.git', '', 'group/project')
end
subject { new_repository.fetch_repository_as_mirror(repository) }
before do
- Gitlab::Shell.new.create_repository('default', 'my_project')
+ Gitlab::Shell.new.create_repository('default', 'my_project', 'group/project')
end
after do
@@ -497,6 +589,38 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#search_files_by_content' do
+ let(:repository) { mutable_repository }
+ let(:repository_rugged) { mutable_repository_rugged }
+
+ before do
+ repository.create_branch('search-files-by-content-branch', 'master')
+ new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', 'search-files-by-content-branch', 'committing something', 'search-files-by-content change')
+ new_commit_edit_new_file_on_branch(repository_rugged, 'anotherfile', 'search-files-by-content-branch', 'committing something', 'search-files-by-content change')
+ end
+
+ after do
+ ensure_seeds
+ end
+
+ shared_examples 'search files by content' do
+ it 'should have 2 items' do
+ expect(search_results.size).to eq(2)
+ end
+
+ it 'should have the correct matching line' do
+ expect(search_results).to contain_exactly("search-files-by-content-branch:encoding/CHANGELOG\u00001\u0000search-files-by-content change\n",
+ "search-files-by-content-branch:anotherfile\u00001\u0000search-files-by-content change\n")
+ end
+ end
+
+ it_should_behave_like 'search files by content' do
+ let(:search_results) do
+ repository.search_files_by_content('search-files-by-content', 'search-files-by-content-branch')
+ end
+ end
+ end
+
describe '#find_remote_root_ref' do
it 'gets the remote root ref from GitalyClient' do
expect_any_instance_of(Gitlab::GitalyClient::RemoteService)
@@ -544,7 +668,7 @@ describe Gitlab::Git::Repository, :seed_helper do
# Add new commits so that there's a renamed file in the commit history
@commit_with_old_name_id = new_commit_edit_old_file(repository_rugged).oid
@rename_commit_id = new_commit_move_file(repository_rugged).oid
- @commit_with_new_name_id = new_commit_edit_new_file(repository_rugged).oid
+ @commit_with_new_name_id = new_commit_edit_new_file(repository_rugged, "encoding/CHANGELOG", "Edit encoding/CHANGELOG", "I'm a new changelog with different text").oid
end
after do
@@ -1230,7 +1354,7 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#gitattribute' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_GITATTRIBUTES_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_GITATTRIBUTES_REPO_PATH, '', 'group/project') }
after do
ensure_seeds
@@ -1249,7 +1373,7 @@ describe Gitlab::Git::Repository, :seed_helper do
end
context 'without gitattributes file' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
it 'returns nil' do
expect(repository.gitattribute("README.md", 'gitlab-language')).to eq(nil)
@@ -1513,7 +1637,7 @@ describe Gitlab::Git::Repository, :seed_helper do
context 'repository does not exist' do
it 'raises NoRepository and does not call Gitaly WriteConfig' do
- repository = Gitlab::Git::Repository.new('default', 'does/not/exist.git', '')
+ repository = Gitlab::Git::Repository.new('default', 'does/not/exist.git', '', 'group/project')
expect(repository.gitaly_repository_client).not_to receive(:write_config)
@@ -1570,6 +1694,37 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#merge_to_ref' do
+ let(:repository) { mutable_repository }
+ let(:branch_head) { '6d394385cf567f80a8fd85055db1ab4c5295806f' }
+ let(:left_sha) { 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660' }
+ let(:right_branch) { 'test-master' }
+ let(:target_ref) { 'refs/merge-requests/999/merge' }
+
+ before do
+ repository.create_branch(right_branch, branch_head) unless repository.branch_exists?(right_branch)
+ end
+
+ def merge_to_ref
+ repository.merge_to_ref(user, left_sha, right_branch, target_ref, 'Merge message')
+ end
+
+ it 'generates a commit in the target_ref' do
+ expect(repository.ref_exists?(target_ref)).to be(false)
+
+ commit_sha = merge_to_ref
+ ref_head = repository.commit(target_ref)
+
+ expect(commit_sha).to be_present
+ expect(repository.ref_exists?(target_ref)).to be(true)
+ expect(ref_head.id).to eq(commit_sha)
+ end
+
+ it 'does not change the right branch HEAD' do
+ expect { merge_to_ref }.not_to change { repository.find_branch(right_branch).target }
+ end
+ end
+
describe '#merge' do
let(:repository) { mutable_repository }
let(:source_sha) { '913c66a37b4a45b9769037c55c2d238bd0942d2e' }
@@ -1753,22 +1908,23 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#create_from_bundle' do
- let(:bundle_path) { File.join(Dir.tmpdir, "repo-#{SecureRandom.hex}.bundle") }
+ let(:valid_bundle_path) { File.join(Dir.tmpdir, "repo-#{SecureRandom.hex}.bundle") }
+ let(:malicious_bundle_path) { Rails.root.join('spec/fixtures/malicious.bundle') }
let(:project) { create(:project) }
let(:imported_repo) { project.repository.raw }
before do
- expect(repository.bundle_to_disk(bundle_path)).to be_truthy
+ expect(repository.bundle_to_disk(valid_bundle_path)).to be_truthy
end
after do
- FileUtils.rm_rf(bundle_path)
+ FileUtils.rm_rf(valid_bundle_path)
end
it 'creates a repo from a bundle file' do
expect(imported_repo).not_to exist
- result = imported_repo.create_from_bundle(bundle_path)
+ result = imported_repo.create_from_bundle(valid_bundle_path)
expect(result).to be_truthy
expect(imported_repo).to exist
@@ -1776,10 +1932,16 @@ describe Gitlab::Git::Repository, :seed_helper do
end
it 'creates a symlink to the global hooks dir' do
- imported_repo.create_from_bundle(bundle_path)
+ imported_repo.create_from_bundle(valid_bundle_path)
hooks_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { File.join(imported_repo.path, 'hooks') }
- expect(File.readlink(hooks_path)).to eq(Gitlab.config.gitlab_shell.hooks_path)
+ expect(File.readlink(hooks_path)).to eq(Gitlab::Shell.new.hooks_path)
+ end
+
+ it 'raises an error if the bundle is an attempted malicious payload' do
+ expect do
+ imported_repo.create_from_bundle(malicious_bundle_path)
+ end.to raise_error(::Gitlab::Git::BundleFile::InvalidBundleError)
end
end
@@ -1796,7 +1958,7 @@ describe Gitlab::Git::Repository, :seed_helper do
out: '/dev/null',
err: '/dev/null')
- empty_repo = described_class.new('default', 'empty-repo.git', '')
+ empty_repo = described_class.new('default', 'empty-repo.git', '', 'group/empty-repo')
expect(empty_repo.checksum).to eq '0000000000000000000000000000000000000000'
end
@@ -1811,13 +1973,13 @@ describe Gitlab::Git::Repository, :seed_helper do
File.truncate(File.join(storage_path, 'non-valid.git/HEAD'), 0)
- non_valid = described_class.new('default', 'non-valid.git', '')
+ non_valid = described_class.new('default', 'non-valid.git', '', 'a/non-valid')
expect { non_valid.checksum }.to raise_error(Gitlab::Git::Repository::InvalidRepository)
end
it 'raises Gitlab::Git::Repository::NoRepository error when there is no repo' do
- broken_repo = described_class.new('default', 'a/path.git', '')
+ broken_repo = described_class.new('default', 'a/path.git', '', 'a/path')
expect { broken_repo.checksum }.to raise_error(Gitlab::Git::Repository::NoRepository)
end
@@ -1957,7 +2119,7 @@ describe Gitlab::Git::Repository, :seed_helper do
end
# Build the options hash that's passed to Rugged::Commit#create
- def commit_options(repo, index, message)
+ def commit_options(repo, index, target, ref, message)
options = {}
options[:tree] = index.write_tree(repo)
options[:author] = {
@@ -1971,8 +2133,8 @@ describe Gitlab::Git::Repository, :seed_helper do
time: Time.gm(2014, "mar", 3, 20, 15, 1)
}
options[:message] ||= message
- options[:parents] = repo.empty? ? [] : [repo.head.target].compact
- options[:update_ref] = "HEAD"
+ options[:parents] = repo.empty? ? [] : [target].compact
+ options[:update_ref] = ref
options
end
@@ -1988,6 +2150,8 @@ describe Gitlab::Git::Repository, :seed_helper do
options = commit_options(
repo,
index,
+ repo.head.target,
+ "HEAD",
"Edit CHANGELOG in its original location"
)
@@ -1996,19 +2160,24 @@ describe Gitlab::Git::Repository, :seed_helper do
end
# Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
- # contents of encoding/CHANGELOG with new text.
- def new_commit_edit_new_file(repo)
- oid = repo.write("I'm a new changelog with different text", :blob)
+ # contents of the specified file_path with new text.
+ def new_commit_edit_new_file(repo, file_path, commit_message, text, branch = repo.head)
+ oid = repo.write(text, :blob)
index = repo.index
- index.read_tree(repo.head.target.tree)
- index.add(path: "encoding/CHANGELOG", oid: oid, mode: 0100644)
-
- options = commit_options(repo, index, "Edit encoding/CHANGELOG")
-
+ index.read_tree(branch.target.tree)
+ index.add(path: file_path, oid: oid, mode: 0100644)
+ options = commit_options(repo, index, branch.target, branch.canonical_name, commit_message)
sha = Rugged::Commit.create(repo, options)
repo.lookup(sha)
end
+ # Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
+ # contents of encoding/CHANGELOG with new text.
+ def new_commit_edit_new_file_on_branch(repo, file_path, branch_name, commit_message, text)
+ branch = repo.branches[branch_name]
+ new_commit_edit_new_file(repo, file_path, commit_message, text, branch)
+ end
+
# Writes a new commit to the repo and returns a Rugged::Commit. Moves the
# CHANGELOG file to the encoding/ directory.
def new_commit_move_file(repo)
@@ -2020,7 +2189,7 @@ describe Gitlab::Git::Repository, :seed_helper do
index.add(path: "encoding/CHANGELOG", oid: oid, mode: 0100644)
index.remove("CHANGELOG")
- options = commit_options(repo, index, "Move CHANGELOG to encoding/")
+ options = commit_options(repo, index, repo.head.target, "HEAD", "Move CHANGELOG to encoding/")
sha = Rugged::Commit.create(repo, options)
repo.lookup(sha)
diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb
index b51e3879f49..4c0291f64f0 100644
--- a/spec/lib/gitlab/git/tag_spec.rb
+++ b/spec/lib/gitlab/git/tag_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Tag, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
describe '#tags' do
describe 'first tag' do
diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb
index bec875fb03d..4a4d69490a3 100644
--- a/spec/lib/gitlab/git/tree_spec.rb
+++ b/spec/lib/gitlab/git/tree_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Tree, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
context :repo do
let(:tree) { Gitlab::Git::Tree.where(repository, SeedRepo::Commit::ID) }
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index a417ef77c9e..634c370d211 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -14,7 +14,7 @@ describe Gitlab::GitAccess do
let(:authentication_abilities) { %i[read_project download_code push_code] }
let(:redirected_path) { nil }
let(:auth_result_type) { nil }
- let(:changes) { '_any' }
+ let(:changes) { Gitlab::GitAccess::ANY }
let(:push_access_check) { access.check('git-receive-pack', changes) }
let(:pull_access_check) { access.check('git-upload-pack', changes) }
@@ -437,7 +437,7 @@ describe Gitlab::GitAccess do
let(:project) { nil }
context 'when changes is _any' do
- let(:changes) { '_any' }
+ let(:changes) { Gitlab::GitAccess::ANY }
context 'when authentication abilities include push code' do
let(:authentication_abilities) { [:push_code] }
@@ -483,7 +483,7 @@ describe Gitlab::GitAccess do
end
context 'when project exists' do
- let(:changes) { '_any' }
+ let(:changes) { Gitlab::GitAccess::ANY }
let!(:project) { create(:project) }
it 'does not create a new project' do
@@ -497,7 +497,7 @@ describe Gitlab::GitAccess do
let(:project_path) { "nonexistent" }
let(:project) { nil }
let(:namespace_path) { user.namespace.path }
- let(:changes) { '_any' }
+ let(:changes) { Gitlab::GitAccess::ANY }
it 'does not create a new project' do
expect { access.send(:ensure_project_on_push!, cmd, changes) }.not_to change { Project.count }
@@ -507,7 +507,7 @@ describe Gitlab::GitAccess do
context 'when pull' do
let(:cmd) { 'git-upload-pack' }
- let(:changes) { '_any' }
+ let(:changes) { Gitlab::GitAccess::ANY }
context 'when project does not exist' do
let(:project_path) { "new-project" }
@@ -709,10 +709,22 @@ describe Gitlab::GitAccess do
project.add_developer(user)
end
- it 'checks LFS integrity only for first change' do
- expect_any_instance_of(Gitlab::Checks::LfsIntegrity).to receive(:objects_missing?).exactly(1).times
+ context 'when LFS is not enabled' do
+ it 'does not run LFSIntegrity check' do
+ expect(Gitlab::Checks::LfsIntegrity).not_to receive(:new)
- push_access_check
+ push_access_check
+ end
+ end
+
+ context 'when LFS is enabled' do
+ it 'checks LFS integrity only for first change' do
+ allow(project).to receive(:lfs_enabled?).and_return(true)
+
+ expect_any_instance_of(Gitlab::Checks::LfsIntegrity).to receive(:objects_missing?).exactly(1).times
+
+ push_access_check
+ end
end
end
@@ -724,7 +736,8 @@ describe Gitlab::GitAccess do
end
let(:changes) do
- { push_new_branch: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/heads/wow",
+ { any: Gitlab::GitAccess::ANY,
+ push_new_branch: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/heads/wow",
push_master: '6f6d7e7ed 570e7b2ab refs/heads/master',
push_protected_branch: '6f6d7e7ed 570e7b2ab refs/heads/feature',
push_remove_protected_branch: "570e7b2ab #{Gitlab::Git::BLANK_SHA} "\
@@ -763,10 +776,13 @@ describe Gitlab::GitAccess do
it "has the correct permissions for #{role}s" do
if role == :admin
user.update_attribute(:admin, true)
+ project.add_guest(user)
else
project.add_role(user, role)
end
+ protected_branch.save
+
aggregate_failures do
matrix.each do |action, allowed|
check = -> { push_changes(changes[action]) }
@@ -786,6 +802,7 @@ describe Gitlab::GitAccess do
permissions_matrix = {
admin: {
+ any: true,
push_new_branch: true,
push_master: true,
push_protected_branch: true,
@@ -797,6 +814,7 @@ describe Gitlab::GitAccess do
},
maintainer: {
+ any: true,
push_new_branch: true,
push_master: true,
push_protected_branch: true,
@@ -808,6 +826,7 @@ describe Gitlab::GitAccess do
},
developer: {
+ any: true,
push_new_branch: true,
push_master: true,
push_protected_branch: false,
@@ -819,6 +838,7 @@ describe Gitlab::GitAccess do
},
reporter: {
+ any: false,
push_new_branch: false,
push_master: false,
push_protected_branch: false,
@@ -830,6 +850,7 @@ describe Gitlab::GitAccess do
},
guest: {
+ any: false,
push_new_branch: false,
push_master: false,
push_protected_branch: false,
@@ -843,25 +864,19 @@ describe Gitlab::GitAccess do
[%w(feature exact), ['feat*', 'wildcard']].each do |protected_branch_name, protected_branch_type|
context do
- before do
- create(:protected_branch, name: protected_branch_name, project: project)
- end
+ let(:protected_branch) { create(:protected_branch, :maintainers_can_push, name: protected_branch_name, project: project) }
run_permission_checks(permissions_matrix)
end
context "when developers are allowed to push into the #{protected_branch_type} protected branch" do
- before do
- create(:protected_branch, :developers_can_push, name: protected_branch_name, project: project)
- end
+ let(:protected_branch) { create(:protected_branch, :developers_can_push, name: protected_branch_name, project: project) }
run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: true, push_all: true, merge_into_protected_branch: true }))
end
context "developers are allowed to merge into the #{protected_branch_type} protected branch" do
- before do
- create(:protected_branch, :developers_can_merge, name: protected_branch_name, project: project)
- end
+ let(:protected_branch) { create(:protected_branch, :developers_can_merge, name: protected_branch_name, project: project) }
context "when a merge request exists for the given source/target branch" do
context "when the merge request is in progress" do
@@ -888,17 +903,13 @@ describe Gitlab::GitAccess do
end
context "when developers are allowed to push and merge into the #{protected_branch_type} protected branch" do
- before do
- create(:protected_branch, :developers_can_merge, :developers_can_push, name: protected_branch_name, project: project)
- end
+ let(:protected_branch) { create(:protected_branch, :developers_can_merge, :developers_can_push, name: protected_branch_name, project: project) }
run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: true, push_all: true, merge_into_protected_branch: true }))
end
context "when no one is allowed to push to the #{protected_branch_name} protected branch" do
- before do
- create(:protected_branch, :no_one_can_push, name: protected_branch_name, project: project)
- end
+ let(:protected_branch) { build(:protected_branch, :no_one_can_push, name: protected_branch_name, project: project) }
run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false },
maintainer: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false },
diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb
index 9c6c9fe13bf..6ba65b56618 100644
--- a/spec/lib/gitlab/git_access_wiki_spec.rb
+++ b/spec/lib/gitlab/git_access_wiki_spec.rb
@@ -38,7 +38,7 @@ describe Gitlab::GitAccessWiki do
end
describe '#access_check_download!' do
- subject { access.check('git-upload-pack', '_any') }
+ subject { access.check('git-upload-pack', Gitlab::GitAccess::ANY) }
before do
project.add_developer(user)
diff --git a/spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb b/spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb
index 9db710e759e..742b2872c40 100644
--- a/spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb
@@ -21,7 +21,7 @@ describe Gitlab::GitalyClient::BlobsStitcher do
expect(blobs[0].size).to eq(1642)
expect(blobs[0].commit_id).to eq('f00ba7')
expect(blobs[0].data).to eq("first-line\nsecond-line")
- expect(blobs[0].binary?).to be false
+ expect(blobs[0].binary_in_repo?).to be false
expect(blobs[1].id).to eq('abcdef2')
expect(blobs[1].mode).to eq('100644')
@@ -30,7 +30,7 @@ describe Gitlab::GitalyClient::BlobsStitcher do
expect(blobs[1].size).to eq(2461)
expect(blobs[1].commit_id).to eq('f00ba8')
expect(blobs[1].data).to eq("GIF87a\x90\x01".b)
- expect(blobs[1].binary?).to be true
+ expect(blobs[1].binary_in_repo?).to be true
end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
index aff47599ad6..d5508dbff5d 100644
--- a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
@@ -33,7 +33,7 @@ describe Gitlab::GitalyClient::RemoteService do
end
describe '#fetch_internal_remote' do
- let(:remote_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
+ let(:remote_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '', 'group/project') }
it 'sends an fetch_internal_remote message and returns the result value' do
expect_any_instance_of(Gitaly::RemoteService::Stub)
diff --git a/spec/lib/gitlab/gitaly_client/storage_settings_spec.rb b/spec/lib/gitlab/gitaly_client/storage_settings_spec.rb
index c89913ec8e9..bb10be2a4dc 100644
--- a/spec/lib/gitlab/gitaly_client/storage_settings_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/storage_settings_spec.rb
@@ -26,4 +26,14 @@ describe Gitlab::GitalyClient::StorageSettings do
end
end
end
+
+ describe '.disk_access_denied?' do
+ it 'return false when Rugged is enabled', :enable_rugged do
+ expect(described_class.disk_access_denied?).to be_falsey
+ end
+
+ it 'returns true' do
+ expect(described_class.disk_access_denied?).to be_truthy
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/util_spec.rb b/spec/lib/gitlab/gitaly_client/util_spec.rb
index 550db6db6d9..78a5e195ad1 100644
--- a/spec/lib/gitlab/gitaly_client/util_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/util_spec.rb
@@ -7,6 +7,7 @@ describe Gitlab::GitalyClient::Util do
let(:gl_repository) { 'project-1' }
let(:git_object_directory) { '.git/objects' }
let(:git_alternate_object_directory) { ['/dir/one', '/dir/two'] }
+ let(:gl_project_path) { 'namespace/myproject' }
let(:git_env) do
{
'GIT_OBJECT_DIRECTORY_RELATIVE' => git_object_directory,
@@ -15,7 +16,7 @@ describe Gitlab::GitalyClient::Util do
end
subject do
- described_class.repository(repository_storage, relative_path, gl_repository)
+ described_class.repository(repository_storage, relative_path, gl_repository, gl_project_path)
end
it 'creates a Gitaly::Repository with the given data' do
@@ -27,6 +28,7 @@ describe Gitlab::GitalyClient::Util do
expect(subject.gl_repository).to eq(gl_repository)
expect(subject.git_object_directory).to eq(git_object_directory)
expect(subject.git_alternate_object_directories).to eq(git_alternate_object_directory)
+ expect(subject.gl_project_path).to eq(gl_project_path)
end
end
end
diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb
index e41a75c37a7..cf12baf1a93 100644
--- a/spec/lib/gitlab/gitaly_client_spec.rb
+++ b/spec/lib/gitlab/gitaly_client_spec.rb
@@ -119,6 +119,15 @@ describe Gitlab::GitalyClient do
end
end
+ describe '.connection_data' do
+ it 'returns connection data' do
+ address = 'tcp://localhost:9876'
+ stub_repos_storages address
+
+ expect(described_class.connection_data('default')).to eq({ 'address' => address, 'token' => 'secret' })
+ end
+ end
+
describe 'allow_n_plus_1_calls' do
context 'when RequestStore is enabled', :request_store do
it 'returns the result of the allow_n_plus_1_calls block' do
diff --git a/spec/lib/gitlab/github_import/bulk_importing_spec.rb b/spec/lib/gitlab/github_import/bulk_importing_spec.rb
index 861710f7e9b..91229d9c7d4 100644
--- a/spec/lib/gitlab/github_import/bulk_importing_spec.rb
+++ b/spec/lib/gitlab/github_import/bulk_importing_spec.rb
@@ -58,17 +58,5 @@ describe Gitlab::GithubImport::BulkImporting do
importer.bulk_insert(model, rows, batch_size: 5)
end
-
- it 'calls pre_hook for each slice if given' do
- rows = [{ title: 'Foo' }] * 10
- model = double(:model, table_name: 'kittens')
- pre_hook = double('pre_hook', call: nil)
- allow(Gitlab::Database).to receive(:bulk_insert)
-
- expect(pre_hook).to receive(:call).with(rows[0..4])
- expect(pre_hook).to receive(:call).with(rows[5..9])
-
- importer.bulk_insert(model, rows, batch_size: 5, pre_hook: pre_hook)
- end
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 65a2e1cb5cb..7901ae005d9 100644
--- a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
@@ -78,11 +78,6 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach
.to receive(:id_for)
.with(issue)
.and_return(milestone.id)
-
- allow(importer.user_finder)
- .to receive(:author_id_for)
- .with(issue)
- .and_return([user.id, true])
end
context 'when the issue author could be found' do
@@ -177,23 +172,6 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach
expect(importer.create_issue).to be_a_kind_of(Numeric)
end
-
- it 'triggers internal_id functionality to track greatest iids' do
- allow(importer.user_finder)
- .to receive(:author_id_for)
- .with(issue)
- .and_return([user.id, true])
-
- issue = build_stubbed(:issue, project: project)
- allow(importer)
- .to receive(:insert_and_return_id)
- .and_return(issue.id)
- allow(project.issues).to receive(:find).with(issue.id).and_return(issue)
-
- expect(issue).to receive(:ensure_project_iid!)
-
- importer.create_issue
- end
end
describe '#create_assignees' do
diff --git a/spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb b/spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb
index 4857f2afbe2..8fd328d9c1e 100644
--- a/spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb
@@ -2,20 +2,26 @@ require 'spec_helper'
describe Gitlab::GithubImport::Importer::LfsObjectImporter do
let(:project) { create(:project) }
- let(:download_link) { "http://www.gitlab.com/lfs_objects/oid" }
-
- let(:github_lfs_object) do
- Gitlab::GithubImport::Representation::LfsObject.new(
- oid: 'oid', download_link: download_link
- )
+ let(:lfs_attributes) do
+ {
+ oid: 'oid',
+ size: 1,
+ link: 'http://www.gitlab.com/lfs_objects/oid'
+ }
end
+ let(:lfs_download_object) { LfsDownloadObject.new(lfs_attributes) }
+ let(:github_lfs_object) { Gitlab::GithubImport::Representation::LfsObject.new(lfs_attributes) }
+
let(:importer) { described_class.new(github_lfs_object, project, nil) }
describe '#execute' do
it 'calls the LfsDownloadService with the lfs object attributes' do
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadService)
- .to receive(:execute).with('oid', download_link)
+ allow(importer).to receive(:lfs_download_object).and_return(lfs_download_object)
+
+ service = double
+ expect(Projects::LfsPointers::LfsDownloadService).to receive(:new).with(project, lfs_download_object).and_return(service)
+ expect(service).to receive(:execute)
importer.execute
end
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 5f5c6b803c0..50442552eee 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
@@ -5,7 +5,15 @@ describe Gitlab::GithubImport::Importer::LfsObjectsImporter do
let(:client) { double(:client) }
let(:download_link) { "http://www.gitlab.com/lfs_objects/oid" }
- let(:github_lfs_object) { ['oid', download_link] }
+ let(:lfs_attributes) do
+ {
+ oid: 'oid',
+ size: 1,
+ link: 'http://www.gitlab.com/lfs_objects/oid'
+ }
+ end
+
+ let(:lfs_download_object) { LfsDownloadObject.new(lfs_attributes) }
describe '#parallel?' do
it 'returns true when running in parallel mode' do
@@ -48,7 +56,7 @@ describe Gitlab::GithubImport::Importer::LfsObjectsImporter do
allow(importer)
.to receive(:each_object_to_import)
- .and_yield(['oid', download_link])
+ .and_yield(lfs_download_object)
expect(Gitlab::GithubImport::Importer::LfsObjectImporter)
.to receive(:new)
@@ -71,7 +79,7 @@ describe Gitlab::GithubImport::Importer::LfsObjectsImporter do
allow(importer)
.to receive(:each_object_to_import)
- .and_yield(github_lfs_object)
+ .and_yield(lfs_download_object)
expect(Gitlab::GithubImport::ImportLfsObjectWorker)
.to receive(:perform_async)
diff --git a/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb b/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
index db0be760c7b..120a07ff2b3 100644
--- a/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
@@ -4,6 +4,7 @@ describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab_redis
let(:project) { create(:project, import_source: 'foo/bar') }
let(:client) { double(:client) }
let(:importer) { described_class.new(project, client) }
+ let(:due_on) { Time.new(2017, 2, 1, 12, 00) }
let(:created_at) { Time.new(2017, 1, 1, 12, 00) }
let(:updated_at) { Time.new(2017, 1, 1, 12, 15) }
@@ -14,6 +15,20 @@ describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab_redis
title: '1.0',
description: 'The first release',
state: 'open',
+ due_on: due_on,
+ created_at: created_at,
+ updated_at: updated_at
+ )
+ end
+
+ let(:milestone2) do
+ double(
+ :milestone,
+ number: 1,
+ title: '1.0',
+ description: 'The first release',
+ state: 'open',
+ due_on: nil,
created_at: created_at,
updated_at: updated_at
)
@@ -29,25 +44,13 @@ describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab_redis
expect(importer)
.to receive(:bulk_insert)
- .with(Milestone, [milestone_hash], any_args)
+ .with(Milestone, [milestone_hash])
expect(importer)
.to receive(:build_milestones_cache)
importer.execute
end
-
- it 'tracks internal ids' do
- milestone_hash = { iid: 1, title: '1.0', project_id: project.id }
- allow(importer)
- .to receive(:build_milestones)
- .and_return([milestone_hash])
-
- expect(InternalId).to receive(:track_greatest)
- .with(nil, { project: project }, :milestones, 1, any_args)
-
- importer.execute
- end
end
describe '#build_milestones' do
@@ -84,6 +87,7 @@ describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab_redis
describe '#build' do
let(:milestone_hash) { importer.build(milestone) }
+ let(:milestone_hash2) { importer.build(milestone2) }
it 'returns the attributes of the milestone as a Hash' do
expect(milestone_hash).to be_an_instance_of(Hash)
@@ -110,6 +114,14 @@ describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab_redis
expect(milestone_hash[:state]).to eq(:active)
end
+ it 'includes the due date' do
+ expect(milestone_hash[:due_date]).to eq(due_on.to_date)
+ end
+
+ it 'responds correctly to no due date value' do
+ expect(milestone_hash2[:due_date]).to be nil
+ end
+
it 'includes the created timestamp' do
expect(milestone_hash[:created_at]).to eq(created_at)
end
diff --git a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
index 25684ea9e2c..15e59718dce 100644
--- a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
@@ -89,7 +89,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
description: 'This is my pull request',
source_project_id: project.id,
target_project_id: project.id,
- source_branch: 'alice:feature',
+ source_branch: 'github/fork/alice/feature',
target_branch: 'master',
state: :merged,
milestone_id: milestone.id,
@@ -111,16 +111,6 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
expect(mr).to be_instance_of(MergeRequest)
expect(exists).to eq(false)
end
-
- it 'triggers internal_id functionality to track greatest iids' do
- mr = build_stubbed(:merge_request, source_project: project, target_project: project)
- allow(importer).to receive(:insert_and_return_id).and_return(mr.id)
- allow(project.merge_requests).to receive(:find).with(mr.id).and_return(mr)
-
- expect(mr).to receive(:ensure_target_project_iid!)
-
- importer.create_merge_request
- end
end
context 'when the author could not be found' do
@@ -144,7 +134,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
description: "*Created by: alice*\n\nThis is my pull request",
source_project_id: project.id,
target_project_id: project.id,
- source_branch: 'alice:feature',
+ source_branch: 'github/fork/alice/feature',
target_branch: 'master',
state: :merged,
milestone_id: milestone.id,
@@ -269,6 +259,40 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
.and_return(user.id)
end
+ it 'does not create the source branch if merge request is merged' do
+ mr, exists = importer.create_merge_request
+
+ importer.insert_git_data(mr, exists)
+
+ expect(project.repository.branch_exists?(mr.source_branch)).to be_falsey
+ expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
+ end
+
+ it 'creates the source branch if merge request is open' do
+ mr, exists = importer.create_merge_request
+ mr.state = 'opened'
+ mr.save
+
+ importer.insert_git_data(mr, exists)
+
+ expect(project.repository.branch_exists?(mr.source_branch)).to be_truthy
+ expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
+ end
+
+ it 'ignores Git errors when creating a branch' do
+ mr, exists = importer.create_merge_request
+ mr.state = 'opened'
+ mr.save
+
+ expect(project.repository).to receive(:add_branch).and_raise(Gitlab::Git::CommandError)
+ expect(Gitlab::Sentry).to receive(:track_acceptable_exception).and_call_original
+
+ importer.insert_git_data(mr, exists)
+
+ expect(project.repository.branch_exists?(mr.source_branch)).to be_falsey
+ expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
+ end
+
it 'creates the merge request diffs' do
mr, exists = importer.create_merge_request
diff --git a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
index 77f5b2ffa37..47233ea6ee2 100644
--- a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
@@ -5,6 +5,14 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do
let(:import_state) { double(:import_state) }
let(:client) { double(:client) }
+ let(:wiki) do
+ double(
+ :wiki,
+ disk_path: 'foo.wiki',
+ full_path: 'group/foo.wiki'
+ )
+ end
+
let(:project) do
double(
:project,
@@ -15,7 +23,9 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do
repository: repository,
create_wiki: true,
import_state: import_state,
- lfs_enabled?: true
+ full_path: 'group/foo',
+ lfs_enabled?: true,
+ wiki: wiki
)
end
@@ -195,7 +205,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do
it 'imports the wiki repository' do
expect(importer.gitlab_shell)
.to receive(:import_repository)
- .with('foo', 'foo.wiki', 'foo.wiki.git')
+ .with('foo', 'foo.wiki', 'foo.wiki.git', 'group/foo.wiki')
expect(importer.import_wiki_repository).to eq(true)
end
diff --git a/spec/lib/gitlab/github_import/representation/pull_request_spec.rb b/spec/lib/gitlab/github_import/representation/pull_request_spec.rb
index 33f6ff0ae6a..d478e5ae899 100644
--- a/spec/lib/gitlab/github_import/representation/pull_request_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/pull_request_spec.rb
@@ -238,7 +238,7 @@ describe Gitlab::GithubImport::Representation::PullRequest do
target_repository_id: 2
)
- expect(pr.formatted_source_branch).to eq('foo:branch')
+ expect(pr.formatted_source_branch).to eq('github/fork/foo/branch')
end
end
diff --git a/spec/lib/gitlab/gon_helper_spec.rb b/spec/lib/gitlab/gon_helper_spec.rb
index c6f09ca2112..1ff2334bacf 100644
--- a/spec/lib/gitlab/gon_helper_spec.rb
+++ b/spec/lib/gitlab/gon_helper_spec.rb
@@ -29,4 +29,13 @@ describe Gitlab::GonHelper do
helper.push_frontend_feature_flag(:my_feature_flag, 10)
end
end
+
+ describe '#default_avatar_url' do
+ it 'returns an absolute URL' do
+ url = helper.default_avatar_url
+
+ expect(url).to match(/^http/)
+ expect(url).to match(/no_avatar.*png$/)
+ end
+ end
end
diff --git a/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb b/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb
index 95bf7685ade..13cf52fd795 100644
--- a/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb
+++ b/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb
@@ -100,4 +100,22 @@ describe Gitlab::Graphql::Authorize::AuthorizeResource do
expect { fake_class.new.find_object }.to raise_error(/Implement #find_object in #{fake_class.name}/)
end
end
+
+ describe '#authorize' do
+ it 'adds permissions from subclasses to those of superclasses when used on classes' do
+ base_class = Class.new do
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ authorize :base_authorization
+ end
+
+ sub_class = Class.new(base_class) do
+ authorize :sub_authorization
+ end
+
+ expect(base_class.required_permissions).to contain_exactly(:base_authorization)
+ expect(sub_class.required_permissions)
+ .to contain_exactly(:base_authorization, :sub_authorization)
+ end
+ end
end
diff --git a/spec/lib/gitlab/graphql/authorize/instrumentation_spec.rb b/spec/lib/gitlab/graphql/authorize/instrumentation_spec.rb
new file mode 100644
index 00000000000..cf3a8bcc8b4
--- /dev/null
+++ b/spec/lib/gitlab/graphql/authorize/instrumentation_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::Authorize::Instrumentation do
+ describe '#build_checker' do
+ let(:current_user) { double(:current_user) }
+ let(:abilities) { [double(:first_ability), double(:last_ability)] }
+
+ let(:checker) do
+ described_class.new.__send__(:build_checker, current_user, abilities)
+ end
+
+ it 'returns a checker which checks for a single object' do
+ object = double(:object)
+
+ abilities.each do |ability|
+ spy_ability_check_for(ability, object, passed: true)
+ end
+
+ expect(checker.call(object)).to eq(object)
+ end
+
+ it 'returns a checker which checks for all objects' do
+ objects = [double(:first), double(:last)]
+
+ abilities.each do |ability|
+ objects.each do |object|
+ spy_ability_check_for(ability, object, passed: true)
+ end
+ end
+
+ expect(checker.call(objects)).to eq(objects)
+ end
+
+ context 'when some objects would not pass the check' do
+ it 'returns nil when it is single object' do
+ disallowed = double(:object)
+
+ spy_ability_check_for(abilities.first, disallowed, passed: false)
+
+ expect(checker.call(disallowed)).to be_nil
+ end
+
+ it 'returns only objects which passed when there are more than one' do
+ allowed = double(:allowed)
+ disallowed = double(:disallowed)
+
+ spy_ability_check_for(abilities.first, disallowed, passed: false)
+
+ abilities.each do |ability|
+ spy_ability_check_for(ability, allowed, passed: true)
+ end
+
+ expect(checker.call([disallowed, allowed]))
+ .to contain_exactly(allowed)
+ end
+ end
+
+ def spy_ability_check_for(ability, object, passed: true)
+ expect(Ability)
+ .to receive(:allowed?)
+ .with(current_user, ability, object)
+ .and_return(passed)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/authorize_spec.rb b/spec/lib/gitlab/graphql/authorize_spec.rb
deleted file mode 100644
index 9c17a3b0e4b..00000000000
--- a/spec/lib/gitlab/graphql/authorize_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Graphql::Authorize do
- describe '#authorize' do
- it 'adds permissions from subclasses to those of superclasses when used on classes' do
- base_class = Class.new do
- extend Gitlab::Graphql::Authorize
-
- authorize :base_authorization
- end
- sub_class = Class.new(base_class) do
- authorize :sub_authorization
- end
-
- expect(base_class.required_permissions).to contain_exactly(:base_authorization)
- expect(sub_class.required_permissions)
- .to contain_exactly(:base_authorization, :sub_authorization)
- end
- end
-end
diff --git a/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb b/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb
index 96615ae80de..9bcc1e78a78 100644
--- a/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb
+++ b/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::Graphql::Connections::KeysetConnection do
let(:nodes) { Project.all.order(id: :asc) }
- let(:arguments) { {} }
+ let(:arguments) { {} }
subject(:connection) do
described_class.new(nodes, arguments, max_page_size: 3)
end
diff --git a/spec/lib/gitlab/hashed_storage/migrator_spec.rb b/spec/lib/gitlab/hashed_storage/migrator_spec.rb
index 7eac2cacb90..6154b3e2f76 100644
--- a/spec/lib/gitlab/hashed_storage/migrator_spec.rb
+++ b/spec/lib/gitlab/hashed_storage/migrator_spec.rb
@@ -1,53 +1,102 @@
require 'spec_helper'
describe Gitlab::HashedStorage::Migrator do
- describe '#bulk_schedule' do
- it 'schedules job to StorageMigratorWorker' do
+ describe '#bulk_schedule_migration' do
+ it 'schedules job to HashedStorage::MigratorWorker' do
Sidekiq::Testing.fake! do
- expect { subject.bulk_schedule(1, 5) }.to change(StorageMigratorWorker.jobs, :size).by(1)
+ expect { subject.bulk_schedule_migration(start: 1, finish: 5) }.to change(HashedStorage::MigratorWorker.jobs, :size).by(1)
+ end
+ end
+ end
+
+ describe '#bulk_schedule_rollback' do
+ it 'schedules job to HashedStorage::RollbackerWorker' do
+ Sidekiq::Testing.fake! do
+ expect { subject.bulk_schedule_rollback(start: 1, finish: 5) }.to change(HashedStorage::RollbackerWorker.jobs, :size).by(1)
end
end
end
describe '#bulk_migrate' do
- let(:projects) { create_list(:project, 2, :legacy_storage) }
+ let(:projects) { create_list(:project, 2, :legacy_storage, :empty_repo) }
let(:ids) { projects.map(&:id) }
- it 'enqueue jobs to ProjectMigrateHashedStorageWorker' do
+ it 'enqueue jobs to HashedStorage::ProjectMigrateWorker' do
Sidekiq::Testing.fake! do
- expect { subject.bulk_migrate(ids.min, ids.max) }.to change(ProjectMigrateHashedStorageWorker.jobs, :size).by(2)
+ expect { subject.bulk_migrate(start: ids.min, finish: ids.max) }.to change(HashedStorage::ProjectMigrateWorker.jobs, :size).by(2)
end
end
- it 'sets projects as read only' do
- allow(ProjectMigrateHashedStorageWorker).to receive(:perform_async).twice
- subject.bulk_migrate(ids.min, ids.max)
+ it 'rescues and log exceptions' do
+ allow_any_instance_of(Project).to receive(:migrate_to_hashed_storage!).and_raise(StandardError)
+ expect { subject.bulk_migrate(start: ids.min, finish: ids.max) }.not_to raise_error
+ end
+ it 'delegates each project in specified range to #migrate' do
projects.each do |project|
- expect(project.reload.repository_read_only?).to be_truthy
+ expect(subject).to receive(:migrate).with(project)
+ end
+
+ subject.bulk_migrate(start: ids.min, finish: ids.max)
+ end
+
+ it 'has all projects migrated and set as writable' do
+ perform_enqueued_jobs do
+ subject.bulk_migrate(start: ids.min, finish: ids.max)
+ end
+
+ projects.each do |project|
+ project.reload
+
+ expect(project.hashed_storage?(:repository)).to be_truthy
+ expect(project.repository_read_only?).to be_falsey
+ end
+ end
+ end
+
+ describe '#bulk_rollback' do
+ let(:projects) { create_list(:project, 2, :empty_repo) }
+ let(:ids) { projects.map(&:id) }
+
+ it 'enqueue jobs to HashedStorage::ProjectRollbackWorker' do
+ Sidekiq::Testing.fake! do
+ expect { subject.bulk_rollback(start: ids.min, finish: ids.max) }.to change(HashedStorage::ProjectRollbackWorker.jobs, :size).by(2)
end
end
it 'rescues and log exceptions' do
- allow_any_instance_of(Project).to receive(:migrate_to_hashed_storage!).and_raise(StandardError)
- expect { subject.bulk_migrate(ids.min, ids.max) }.not_to raise_error
+ allow_any_instance_of(Project).to receive(:rollback_to_legacy_storage!).and_raise(StandardError)
+ expect { subject.bulk_rollback(start: ids.min, finish: ids.max) }.not_to raise_error
end
- it 'delegates each project in specified range to #migrate' do
+ it 'delegates each project in specified range to #rollback' do
projects.each do |project|
- expect(subject).to receive(:migrate).with(project)
+ expect(subject).to receive(:rollback).with(project)
end
- subject.bulk_migrate(ids.min, ids.max)
+ subject.bulk_rollback(start: ids.min, finish: ids.max)
+ end
+
+ it 'has all projects rolledback and set as writable' do
+ perform_enqueued_jobs do
+ subject.bulk_rollback(start: ids.min, finish: ids.max)
+ end
+
+ projects.each do |project|
+ project.reload
+
+ expect(project.legacy_storage?).to be_truthy
+ expect(project.repository_read_only?).to be_falsey
+ end
end
end
describe '#migrate' do
let(:project) { create(:project, :legacy_storage, :empty_repo) }
- it 'enqueues job to ProjectMigrateHashedStorageWorker' do
+ it 'enqueues project migration job' do
Sidekiq::Testing.fake! do
- expect { subject.migrate(project) }.to change(ProjectMigrateHashedStorageWorker.jobs, :size).by(1)
+ expect { subject.migrate(project) }.to change(HashedStorage::ProjectMigrateWorker.jobs, :size).by(1)
end
end
@@ -57,19 +106,80 @@ describe Gitlab::HashedStorage::Migrator do
expect { subject.migrate(project) }.not_to raise_error
end
- it 'sets project as read only' do
- allow(ProjectMigrateHashedStorageWorker).to receive(:perform_async)
- subject.migrate(project)
+ it 'migrates project storage' do
+ perform_enqueued_jobs do
+ subject.migrate(project)
+ end
- expect(project.reload.repository_read_only?).to be_truthy
+ expect(project.reload.hashed_storage?(:attachments)).to be_truthy
end
- it 'migrate project' do
+ it 'has migrated project set as writable' do
perform_enqueued_jobs do
subject.migrate(project)
end
- expect(project.reload.hashed_storage?(:attachments)).to be_truthy
+ expect(project.reload.repository_read_only?).to be_falsey
+ end
+
+ context 'when project is already on hashed storage' do
+ let(:project) { create(:project, :empty_repo) }
+
+ it 'doesnt enqueue any migration job' do
+ Sidekiq::Testing.fake! do
+ expect { subject.migrate(project) }.not_to change(HashedStorage::ProjectMigrateWorker.jobs, :size)
+ end
+ end
+
+ it 'returns false' do
+ expect(subject.migrate(project)).to be_falsey
+ end
+ end
+ end
+
+ describe '#rollback' do
+ let(:project) { create(:project, :empty_repo) }
+
+ it 'enqueues project rollback job' do
+ Sidekiq::Testing.fake! do
+ expect { subject.rollback(project) }.to change(HashedStorage::ProjectRollbackWorker.jobs, :size).by(1)
+ end
+ end
+
+ it 'rescues and log exceptions' do
+ allow(project).to receive(:rollback_to_hashed_storage!).and_raise(StandardError)
+
+ expect { subject.rollback(project) }.not_to raise_error
+ end
+
+ it 'rolls-back project storage' do
+ perform_enqueued_jobs do
+ subject.rollback(project)
+ end
+
+ expect(project.reload.legacy_storage?).to be_truthy
+ end
+
+ it 'has rolled-back project set as writable' do
+ perform_enqueued_jobs do
+ subject.rollback(project)
+ end
+
+ expect(project.reload.repository_read_only?).to be_falsey
+ end
+
+ context 'when project is already on legacy storage' do
+ let(:project) { create(:project, :legacy_storage, :empty_repo) }
+
+ it 'doesnt enqueue any rollback job' do
+ Sidekiq::Testing.fake! do
+ expect { subject.rollback(project) }.not_to change(HashedStorage::ProjectRollbackWorker.jobs, :size)
+ end
+ end
+
+ it 'returns false' do
+ expect(subject.rollback(project)).to be_falsey
+ 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 c8c74883640..01da3ea7081 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -66,6 +66,9 @@ snippets:
releases:
- author
- project
+- links
+links:
+- release
project_members:
- created_by
- user
@@ -111,6 +114,7 @@ ci_pipelines:
- stages
- statuses
- builds
+- processables
- trigger_requests
- variables
- auto_canceled_by
@@ -123,10 +127,11 @@ ci_pipelines:
- scheduled_actions
- artifacts
- pipeline_schedule
-- merge_requests
+- merge_requests_as_head_pipeline
- merge_request
- deployments
- environments
+- chat_data
pipeline_variables:
- pipeline
stages:
@@ -134,6 +139,7 @@ stages:
- pipeline
- statuses
- builds
+- bridges
statuses:
- project
- pipeline
@@ -214,7 +220,6 @@ project:
- packagist_service
- pivotaltracker_service
- prometheus_service
-- hipchat_service
- flowdock_service
- assembla_service
- asana_service
@@ -228,6 +233,7 @@ project:
- pushover_service
- jira_service
- redmine_service
+- youtrack_service
- custom_issue_tracker_service
- bugzilla_service
- gitlab_issue_tracker_service
@@ -311,6 +317,7 @@ project:
- repository_languages
- pool_repository
- kubernetes_namespaces
+- error_tracking_setting
award_emoji:
- awardable
- user
@@ -342,3 +349,5 @@ resource_label_events:
- merge_request
- epic
- label
+error_tracking_setting:
+- project
diff --git a/spec/lib/gitlab/import_export/importer_spec.rb b/spec/lib/gitlab/import_export/importer_spec.rb
index 11f98d782b1..898e4d07760 100644
--- a/spec/lib/gitlab/import_export/importer_spec.rb
+++ b/spec/lib/gitlab/import_export/importer_spec.rb
@@ -29,7 +29,7 @@ describe Gitlab::ImportExport::Importer do
expect(shared.errors).to be_empty
end
- it 'extracts the archive' do
+ it 'extracts the archive' do
expect(Gitlab::ImportExport::FileImporter).to receive(:import).and_call_original
importer.execute
diff --git a/spec/lib/gitlab/import_export/merge_request_parser_spec.rb b/spec/lib/gitlab/import_export/merge_request_parser_spec.rb
index 68eaa70e6b6..4b234411a44 100644
--- a/spec/lib/gitlab/import_export/merge_request_parser_spec.rb
+++ b/spec/lib/gitlab/import_export/merge_request_parser_spec.rb
@@ -41,4 +41,20 @@ describe Gitlab::ImportExport::MergeRequestParser do
expect(parsed_merge_request).to eq(merge_request)
end
+
+ context 'when the merge request has diffs' do
+ let(:merge_request) do
+ build(:merge_request, source_project: forked_project, target_project: project)
+ end
+
+ context 'when the diff is invalid' do
+ let(:merge_request_diff) { build(:merge_request_diff, merge_request: merge_request, base_commit_sha: 'foobar') }
+
+ it 'sets the diff to nil' do
+ expect(merge_request_diff).to be_invalid
+ expect(merge_request_diff.merge_request).to eq merge_request
+ expect(parsed_merge_request.merge_request_diff).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index 58949f76bd6..773651dd226 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -6630,6 +6630,26 @@
"deploy_keys": [],
"services": [
{
+ "id": 101,
+ "title": "YouTrack",
+ "project_id": 5,
+ "created_at": "2016-06-14T15:01:51.327Z",
+ "updated_at": "2016-06-14T15:01:51.327Z",
+ "active": false,
+ "properties": {},
+ "template": false,
+ "push_events": true,
+ "issues_events": true,
+ "merge_requests_events": true,
+ "tag_push_events": true,
+ "note_events": true,
+ "job_events": true,
+ "type": "YoutrackService",
+ "category": "issue_tracker",
+ "default": false,
+ "wiki_page_events": true
+ },
+ {
"id": 100,
"title": "JetBrains TeamCity CI",
"project_id": 5,
@@ -6775,28 +6795,6 @@
"wiki_page_events": true
},
{
- "id": 93,
- "title": "HipChat",
- "project_id": 5,
- "created_at": "2016-06-14T15:01:51.219Z",
- "updated_at": "2016-06-14T15:01:51.219Z",
- "active": false,
- "properties": {
- "notify_only_broken_pipelines": true
- },
- "template": false,
- "push_events": true,
- "issues_events": true,
- "merge_requests_events": true,
- "tag_push_events": true,
- "note_events": true,
- "pipeline_events": true,
- "type": "HipchatService",
- "category": "common",
- "default": false,
- "wiki_page_events": true
- },
- {
"id": 91,
"title": "Flowdock",
"project_id": 5,
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 242c16c4bdc..6084dc96410 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -12,7 +12,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
]
RSpec::Mocks.with_temporary_scope do
- @project = create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project')
+ @project = create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project')
@shared = @project.import_export_shared
allow(@shared).to receive(:export_path).and_return('spec/lib/gitlab/import_export/')
@@ -40,7 +40,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
project = Project.find_by_path('project')
expect(project.project_feature.issues_access_level).to eq(ProjectFeature::DISABLED)
- expect(project.project_feature.builds_access_level).to eq(ProjectFeature::DISABLED)
+ expect(project.project_feature.builds_access_level).to eq(ProjectFeature::ENABLED)
expect(project.project_feature.snippets_access_level).to eq(ProjectFeature::ENABLED)
expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::ENABLED)
expect(project.project_feature.merge_requests_access_level).to eq(ProjectFeature::ENABLED)
@@ -273,6 +273,11 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
it 'has group milestone' do
expect(project.group.milestones.size).to eq(results.fetch(:milestones, 0))
end
+
+ it 'has the correct visibility level' do
+ # INTERNAL in the `project.json`, group's is PRIVATE
+ expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ end
end
context 'Light JSON' do
@@ -347,7 +352,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
:issues_disabled,
name: 'project',
path: 'project',
- group: create(:group))
+ group: create(:group, visibility_level: Gitlab::VisibilityLevel::PRIVATE))
end
before do
@@ -434,4 +439,58 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
end
end
end
+
+ describe '#restored_project' do
+ let(:project) { create(:project) }
+ let(:shared) { project.import_export_shared }
+ let(:tree_hash) { { 'visibility_level' => visibility } }
+ let(:restorer) { described_class.new(user: nil, shared: shared, project: project) }
+
+ before do
+ restorer.instance_variable_set(:@tree_hash, tree_hash)
+ end
+
+ context 'no group visibility' do
+ let(:visibility) { Gitlab::VisibilityLevel::PRIVATE }
+
+ it 'uses the project visibility' do
+ expect(restorer.restored_project.visibility_level).to eq(visibility)
+ end
+ end
+
+ context 'with group visibility' do
+ before do
+ group = create(:group, visibility_level: group_visibility)
+
+ project.update(group: group)
+ end
+
+ context 'private group visibility' do
+ let(:group_visibility) { Gitlab::VisibilityLevel::PRIVATE }
+ let(:visibility) { Gitlab::VisibilityLevel::PUBLIC }
+
+ it 'uses the group visibility' do
+ expect(restorer.restored_project.visibility_level).to eq(group_visibility)
+ end
+ end
+
+ context 'public group visibility' do
+ let(:group_visibility) { Gitlab::VisibilityLevel::PUBLIC }
+ let(:visibility) { Gitlab::VisibilityLevel::PRIVATE }
+
+ it 'uses the project visibility' do
+ expect(restorer.restored_project.visibility_level).to eq(visibility)
+ end
+ end
+
+ context 'internal group visibility' do
+ let(:group_visibility) { Gitlab::VisibilityLevel::INTERNAL }
+ let(:visibility) { Gitlab::VisibilityLevel::PUBLIC }
+
+ it 'uses the group visibility' do
+ expect(restorer.restored_project.visibility_level).to eq(group_visibility)
+ end
+ end
+ end
+ 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 46fdfba953b..cfc3e0ce926 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -78,6 +78,14 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
expect(saved_project_json['releases']).not_to be_empty
end
+ it 'has no author on releases' do
+ expect(saved_project_json['releases'].first['author']).to be_nil
+ end
+
+ it 'has the author ID on releases' do
+ expect(saved_project_json['releases'].first['author_id']).not_to be_nil
+ end
+
it 'has issues' do
expect(saved_project_json['issues']).not_to be_empty
end
diff --git a/spec/lib/gitlab/import_export/reader_spec.rb b/spec/lib/gitlab/import_export/reader_spec.rb
index 1ef024d3078..f93ff074770 100644
--- a/spec/lib/gitlab/import_export/reader_spec.rb
+++ b/spec/lib/gitlab/import_export/reader_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::ImportExport::Reader do
+describe Gitlab::ImportExport::Reader do
let(:shared) { Gitlab::ImportExport::Shared.new(nil) }
let(:test_config) { 'spec/support/import_export/import_export.yml' }
let(:project_tree_hash) do
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 24b1f2d995b..ee96e5c4d42 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -120,6 +120,13 @@ Release:
- project_id
- created_at
- updated_at
+Releases::Link:
+- id
+- release_id
+- url
+- name
+- created_at
+- updated_at
ProjectMember:
- id
- access_level
@@ -228,6 +235,8 @@ Ci::Pipeline:
- ref
- sha
- before_sha
+- source_sha
+- target_sha
- push_data
- created_at
- updated_at
@@ -593,3 +602,9 @@ ResourceLabelEvent:
- label_id
- user_id
- created_at
+ErrorTracking::ProjectErrorTrackingSetting:
+- id
+- api_url
+- project_id
+- project_name
+- organization_name
diff --git a/spec/lib/gitlab/import_export/shared_spec.rb b/spec/lib/gitlab/import_export/shared_spec.rb
new file mode 100644
index 00000000000..2c288cff6ef
--- /dev/null
+++ b/spec/lib/gitlab/import_export/shared_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+require 'fileutils'
+
+describe Gitlab::ImportExport::Shared do
+ let(:project) { build(:project) }
+ subject { project.import_export_shared }
+
+ describe '#error' do
+ let(:error) { StandardError.new('Error importing into /my/folder Permission denied @ unlink_internal - /var/opt/gitlab/gitlab-rails/shared/a/b/c/uploads/file') }
+
+ it 'filters any full paths' do
+ subject.error(error)
+
+ expect(subject.errors).to eq(['Error importing into [FILTERED] Permission denied @ unlink_internal - [FILTERED]'])
+ end
+
+ it 'updates the import JID' do
+ import_state = create(:import_state, project: project, jid: 'jid-test')
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger).to receive(:error).with(hash_including(import_jid: import_state.jid))
+ end
+
+ subject.error(error)
+ end
+
+ it 'calls the error logger with the full message' do
+ expect(subject).to receive(:log_error).with(hash_including(message: error.message))
+
+ subject.error(error)
+ end
+
+ it 'calls the debug logger with a backtrace' do
+ error.set_backtrace('backtrace')
+
+ expect(subject).to receive(:log_debug).with(hash_including(backtrace: 'backtrace'))
+
+ subject.error(error)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/version_checker_spec.rb b/spec/lib/gitlab/import_export/version_checker_spec.rb
index 49d857d9483..76f8253ec9b 100644
--- a/spec/lib/gitlab/import_export/version_checker_spec.rb
+++ b/spec/lib/gitlab/import_export/version_checker_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
include ImportExport::CommonUtil
describe Gitlab::ImportExport::VersionChecker do
- let(:shared) { Gitlab::ImportExport::Shared.new(nil) }
+ let!(:shared) { Gitlab::ImportExport::Shared.new(nil) }
describe 'bundle a project Git repo' do
let(:version) { Gitlab::ImportExport.version }
diff --git a/spec/lib/gitlab/incoming_email_spec.rb b/spec/lib/gitlab/incoming_email_spec.rb
index 4c0c3fcbcc7..2db62ab983a 100644
--- a/spec/lib/gitlab/incoming_email_spec.rb
+++ b/spec/lib/gitlab/incoming_email_spec.rb
@@ -61,7 +61,7 @@ describe Gitlab::IncomingEmail do
end
it 'returns the address with interpolated reply key and unsubscribe suffix' do
- expect(described_class.unsubscribe_address('key')).to eq('replies+key+unsubscribe@example.com')
+ expect(described_class.unsubscribe_address('key')).to eq("replies+key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX}@example.com")
end
end
diff --git a/spec/lib/gitlab/issuable_metadata_spec.rb b/spec/lib/gitlab/issuable_metadata_spec.rb
index 42635a68ee1..6ec86163233 100644
--- a/spec/lib/gitlab/issuable_metadata_spec.rb
+++ b/spec/lib/gitlab/issuable_metadata_spec.rb
@@ -28,12 +28,12 @@ describe Gitlab::IssuableMetadata do
expect(data.count).to eq(2)
expect(data[issue.id].upvotes).to eq(1)
expect(data[issue.id].downvotes).to eq(0)
- expect(data[issue.id].notes_count).to eq(0)
+ expect(data[issue.id].user_notes_count).to eq(0)
expect(data[issue.id].merge_requests_count).to eq(1)
expect(data[closed_issue.id].upvotes).to eq(0)
expect(data[closed_issue.id].downvotes).to eq(1)
- expect(data[closed_issue.id].notes_count).to eq(0)
+ expect(data[closed_issue.id].user_notes_count).to eq(0)
expect(data[closed_issue.id].merge_requests_count).to eq(0)
end
end
@@ -51,12 +51,12 @@ describe Gitlab::IssuableMetadata do
expect(data.count).to eq(2)
expect(data[merge_request.id].upvotes).to eq(1)
expect(data[merge_request.id].downvotes).to eq(1)
- expect(data[merge_request.id].notes_count).to eq(1)
+ expect(data[merge_request.id].user_notes_count).to eq(1)
expect(data[merge_request.id].merge_requests_count).to eq(0)
expect(data[merge_request_closed.id].upvotes).to eq(0)
expect(data[merge_request_closed.id].downvotes).to eq(0)
- expect(data[merge_request_closed.id].notes_count).to eq(0)
+ expect(data[merge_request_closed.id].user_notes_count).to eq(0)
expect(data[merge_request_closed.id].merge_requests_count).to eq(0)
end
end
diff --git a/spec/lib/gitlab/json_cache_spec.rb b/spec/lib/gitlab/json_cache_spec.rb
index b52078e8556..2cae8ec031a 100644
--- a/spec/lib/gitlab/json_cache_spec.rb
+++ b/spec/lib/gitlab/json_cache_spec.rb
@@ -297,13 +297,39 @@ describe Gitlab::JsonCache do
expect(result).to eq(broadcast_message)
end
+ context 'when the cached value is an instance of ActiveRecord::Base' do
+ it 'returns a persisted record when id is set' do
+ backend.write(expanded_key, broadcast_message.to_json)
+
+ result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
+
+ expect(result).to be_persisted
+ end
+
+ it 'returns a new record when id is nil' do
+ backend.write(expanded_key, build(:broadcast_message).to_json)
+
+ result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
+
+ expect(result).to be_new_record
+ end
+
+ it 'returns a new record when id is missing' do
+ backend.write(expanded_key, build(:broadcast_message).attributes.except('id').to_json)
+
+ result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
+
+ expect(result).to be_new_record
+ end
+ end
+
it "returns the result of the block when 'as' option is nil" do
result = cache.fetch(key, as: nil) { 'block result' }
expect(result).to eq('block result')
end
- it "returns the result of the block when 'as' option is not informed" do
+ it "returns the result of the block when 'as' option is missing" do
result = cache.fetch(key) { 'block result' }
expect(result).to eq('block result')
diff --git a/spec/lib/gitlab/kubernetes/helm/api_spec.rb b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
index c7f92cbb143..8433d40b2ea 100644
--- a/spec/lib/gitlab/kubernetes/helm/api_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
@@ -171,51 +171,6 @@ describe Gitlab::Kubernetes::Helm::Api do
end
end
- describe '#update' do
- let(:rbac) { false }
-
- let(:command) do
- Gitlab::Kubernetes::Helm::UpgradeCommand.new(
- application_name,
- chart: 'chart-name',
- files: files,
- rbac: rbac
- )
- end
-
- before do
- allow(namespace).to receive(:ensure_exists!).once
-
- allow(client).to receive(:update_config_map).and_return(nil)
- allow(client).to receive(:create_pod).and_return(nil)
- allow(client).to receive(:delete_pod).and_return(nil)
- end
-
- it 'ensures the namespace exists before creating the pod' do
- expect(namespace).to receive(:ensure_exists!).once.ordered
- expect(client).to receive(:create_pod).once.ordered
-
- subject.update(command)
- end
-
- it 'removes an existing pod before updating' do
- expect(client).to receive(:delete_pod).with('upgrade-app-name', 'gitlab-managed-apps').once.ordered
- expect(client).to receive(:create_pod).once.ordered
-
- subject.update(command)
- end
-
- it 'updates the config map on kubeclient when one exists' do
- resource = Gitlab::Kubernetes::ConfigMap.new(
- application_name, files
- ).generate
-
- expect(client).to receive(:update_config_map).with(resource).once
-
- subject.update(command)
- end
- end
-
describe '#status' do
let(:phase) { Gitlab::Kubernetes::Pod::RUNNING }
let(:pod) { Kubeclient::Resource.new(status: { phase: phase }) } # partial representation
diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
index 82ed4d47857..db76d5d207e 100644
--- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
@@ -21,6 +21,15 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
)
end
+ let(:tls_flags) do
+ <<~EOS.squish
+ --tls
+ --tls-ca-cert /data/helm/app-name/config/ca.pem
+ --tls-cert /data/helm/app-name/config/cert.pem
+ --tls-key /data/helm/app-name/config/key.pem
+ EOS
+ end
+
subject { install_command }
it_behaves_like 'helm commands' do
@@ -36,12 +45,10 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
let(:helm_install_comand) do
<<~EOS.squish
- helm install chart-name
- --name app-name
- --tls
- --tls-ca-cert /data/helm/app-name/config/ca.pem
- --tls-cert /data/helm/app-name/config/cert.pem
- --tls-key /data/helm/app-name/config/key.pem
+ helm upgrade app-name chart-name
+ --install
+ --reset-values
+ #{tls_flags}
--version 1.2.3
--set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
@@ -66,12 +73,10 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
let(:helm_install_command) do
<<~EOS.squish
- helm install chart-name
- --name app-name
- --tls
- --tls-ca-cert /data/helm/app-name/config/ca.pem
- --tls-cert /data/helm/app-name/config/cert.pem
- --tls-key /data/helm/app-name/config/key.pem
+ helm upgrade app-name chart-name
+ --install
+ --reset-values
+ #{tls_flags}
--version 1.2.3
--set rbac.create\\=true,rbac.enabled\\=true
--namespace gitlab-managed-apps
@@ -95,12 +100,10 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
let(:helm_install_command) do
<<~EOS.squish
- helm install chart-name
- --name app-name
- --tls
- --tls-ca-cert /data/helm/app-name/config/ca.pem
- --tls-cert /data/helm/app-name/config/cert.pem
- --tls-key /data/helm/app-name/config/key.pem
+ helm upgrade app-name chart-name
+ --install
+ --reset-values
+ #{tls_flags}
--version 1.2.3
--set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
@@ -120,15 +123,22 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
helm repo add app-name https://repository.example.com
helm repo update
+ /bin/date
+ /bin/true
#{helm_install_command}
EOS
end
let(:helm_install_command) do
- <<~EOS.strip
- /bin/date
- /bin/true
- helm install chart-name --name app-name --tls --tls-ca-cert /data/helm/app-name/config/ca.pem --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --set rbac.create\\=false,rbac.enabled\\=false --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --reset-values
+ #{tls_flags}
+ --version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
EOS
end
end
@@ -145,14 +155,21 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
helm repo add app-name https://repository.example.com
helm repo update
#{helm_install_command}
+ /bin/date
+ /bin/false
EOS
end
let(:helm_install_command) do
- <<~EOS.strip
- helm install chart-name --name app-name --tls --tls-ca-cert /data/helm/app-name/config/ca.pem --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --set rbac.create\\=false,rbac.enabled\\=false --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml
- /bin/date
- /bin/false
+ <<~EOS.squish
+ helm upgrade app-name chart-name
+ --install
+ --reset-values
+ #{tls_flags}
+ --version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
+ --namespace gitlab-managed-apps
+ -f /data/helm/app-name/config/values.yaml
EOS
end
end
@@ -174,8 +191,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
let(:helm_install_command) do
<<~EOS.squish
- helm install chart-name
- --name app-name
+ helm upgrade app-name chart-name
+ --install
+ --reset-values
--version 1.2.3
--set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
@@ -201,12 +219,10 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
let(:helm_install_command) do
<<~EOS.squish
- helm install chart-name
- --name app-name
- --tls
- --tls-ca-cert /data/helm/app-name/config/ca.pem
- --tls-cert /data/helm/app-name/config/cert.pem
- --tls-key /data/helm/app-name/config/key.pem
+ helm upgrade app-name chart-name
+ --install
+ --reset-values
+ #{tls_flags}
--set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
index 2dd3a570a1d..95b6b3fd953 100644
--- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
@@ -2,8 +2,8 @@ require 'rails_helper'
describe Gitlab::Kubernetes::Helm::Pod do
describe '#generate' do
- let(:app) { create(:clusters_applications_prometheus) }
- let(:command) { app.install_command }
+ let(:app) { create(:clusters_applications_prometheus) }
+ let(:command) { app.install_command }
let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE }
let(:service_account_name) { nil }
@@ -30,7 +30,7 @@ describe Gitlab::Kubernetes::Helm::Pod do
it 'should generate the appropriate specifications for the container' do
container = subject.generate.spec.containers.first
expect(container.name).to eq('helm')
- expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.11.0-kube-1.11.0')
+ expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.12.3-kube-1.11.7')
expect(container.env.count).to eq(3)
expect(container.env.map(&:name)).to match_array([:HELM_VERSION, :TILLER_NAMESPACE, :COMMAND_SCRIPT])
expect(container.command).to match_array(["/bin/sh"])
diff --git a/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
deleted file mode 100644
index 9b201dae417..00000000000
--- a/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
+++ /dev/null
@@ -1,140 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Gitlab::Kubernetes::Helm::UpgradeCommand do
- let(:application) { build(:clusters_applications_prometheus) }
- let(:files) { { 'ca.pem': 'some file content' } }
- let(:namespace) { ::Gitlab::Kubernetes::Helm::NAMESPACE }
- let(:rbac) { false }
- let(:upgrade_command) do
- described_class.new(
- application.name,
- chart: application.chart,
- files: files,
- rbac: rbac
- )
- end
-
- subject { upgrade_command }
-
- it_behaves_like 'helm commands' do
- let(:commands) do
- <<~EOS
- helm init --upgrade
- for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
- helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml
- EOS
- end
- end
-
- context 'rbac is true' do
- let(:rbac) { true }
-
- it_behaves_like 'helm commands' do
- let(:commands) do
- <<~EOS
- helm init --upgrade
- for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
- helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml
- EOS
- end
- end
- end
-
- context 'with an application with a repository' do
- let(:ci_runner) { create(:ci_runner) }
- let(:application) { build(:clusters_applications_runner, runner: ci_runner) }
- let(:upgrade_command) do
- described_class.new(
- application.name,
- chart: application.chart,
- files: files,
- rbac: rbac,
- repository: application.repository
- )
- end
-
- it_behaves_like 'helm commands' do
- let(:commands) do
- <<~EOS
- helm init --upgrade
- for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
- helm repo add #{application.name} #{application.repository}
- helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml
- EOS
- end
- end
- end
-
- context 'when there is no ca.pem file' do
- let(:files) { { 'file.txt': 'some content' } }
-
- it_behaves_like 'helm commands' do
- let(:commands) do
- <<~EOS
- helm init --upgrade
- for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
- helm upgrade #{application.name} #{application.chart} --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml
- EOS
- end
- end
- end
-
- describe '#pod_resource' do
- subject { upgrade_command.pod_resource }
-
- context 'rbac is enabled' do
- let(:rbac) { true }
-
- it 'generates a pod that uses the tiller serviceAccountName' do
- expect(subject.spec.serviceAccountName).to eq('tiller')
- end
- end
-
- context 'rbac is not enabled' do
- let(:rbac) { false }
-
- it 'generates a pod that uses the default serviceAccountName' do
- expect(subject.spec.serviceAcccountName).to be_nil
- end
- end
- end
-
- describe '#config_map_resource' do
- let(:metadata) do
- {
- name: "values-content-configuration-#{application.name}",
- namespace: namespace,
- labels: { name: "values-content-configuration-#{application.name}" }
- }
- end
- let(:resource) { ::Kubeclient::Resource.new(metadata: metadata, data: files) }
-
- it 'returns a KubeClient resource with config map content for the application' do
- expect(subject.config_map_resource).to eq(resource)
- end
- end
-
- describe '#rbac?' do
- subject { upgrade_command.rbac? }
-
- context 'rbac is enabled' do
- let(:rbac) { true }
-
- it { is_expected.to be_truthy }
- end
-
- context 'rbac is not enabled' do
- let(:rbac) { false }
-
- it { is_expected.to be_falsey }
- end
- end
-
- describe '#pod_name' do
- it 'returns the pod name' do
- expect(subject.pod_name).to eq("upgrade-#{application.name}")
- end
- end
-end
diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
index 8fc85301304..978e64c4407 100644
--- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb
+++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
@@ -24,6 +24,62 @@ describe Gitlab::Kubernetes::KubeClient do
end
end
+ shared_examples 'redirection not allowed' do |method_name|
+ before do
+ redirect_url = 'https://not-under-our-control.example.com/api/v1/pods'
+
+ stub_request(:get, %r{\A#{api_url}/})
+ .to_return(status: 302, headers: { location: redirect_url })
+
+ stub_request(:get, redirect_url)
+ .to_return(status: 200, body: '{}')
+ end
+
+ it 'does not follow redirects' do
+ method_call = -> do
+ case method_name
+ when /\A(get_|delete_)/
+ client.public_send(method_name)
+ when /\A(create_|update_)/
+ client.public_send(method_name, {})
+ else
+ raise "Unknown method name #{method_name}"
+ end
+ end
+ expect { method_call.call }.to raise_error(Kubeclient::HttpError)
+ end
+ end
+
+ describe '#initialize' do
+ shared_examples 'local address' do
+ it 'blocks local addresses' do
+ expect { client }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError)
+ end
+
+ context 'when local requests are allowed' do
+ before do
+ stub_application_setting(allow_local_requests_from_hooks_and_services: true)
+ end
+
+ it 'allows local addresses' do
+ expect { client }.not_to raise_error
+ end
+ end
+ end
+
+ context 'localhost address' do
+ let(:api_url) { 'http://localhost:22' }
+
+ it_behaves_like 'local address'
+ end
+
+ context 'private network address' do
+ let(:api_url) { 'http://192.168.1.2:3003' }
+
+ it_behaves_like 'local address'
+ end
+ end
+
describe '#core_client' do
subject { client.core_client }
@@ -103,6 +159,8 @@ describe Gitlab::Kubernetes::KubeClient do
:update_service_account
].each do |method|
describe "##{method}" do
+ include_examples 'redirection not allowed', method
+
it 'delegates to the core client' do
expect(client).to delegate_method(method).to(:core_client)
end
@@ -123,6 +181,8 @@ describe Gitlab::Kubernetes::KubeClient do
:update_cluster_role_binding
].each do |method|
describe "##{method}" do
+ include_examples 'redirection not allowed', method
+
it 'delegates to the rbac client' do
expect(client).to delegate_method(method).to(:rbac_client)
end
@@ -139,6 +199,8 @@ describe Gitlab::Kubernetes::KubeClient do
let(:extensions_client) { client.extensions_client }
describe '#get_deployments' do
+ include_examples 'redirection not allowed', 'get_deployments'
+
it 'delegates to the extensions client' do
expect(client).to delegate_method(:get_deployments).to(:extensions_client)
end
diff --git a/spec/lib/gitlab/legacy_github_import/importer_spec.rb b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
index d2df21d7bb5..6bc3792eb22 100644
--- a/spec/lib/gitlab/legacy_github_import/importer_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
@@ -138,7 +138,7 @@ describe Gitlab::LegacyGithubImport::Importer do
let(:release2) do
double(
- tag_name: 'v2.0.0',
+ tag_name: 'v1.1.0',
name: 'Second release',
body: nil,
draft: false,
diff --git a/spec/lib/gitlab/legacy_github_import/wiki_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/wiki_formatter_spec.rb
index 7723533aee2..7519707293c 100644
--- a/spec/lib/gitlab/legacy_github_import/wiki_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/wiki_formatter_spec.rb
@@ -10,11 +10,17 @@ describe Gitlab::LegacyGithubImport::WikiFormatter do
subject(:wiki) { described_class.new(project) }
describe '#disk_path' do
- it 'appends .wiki to project path' do
+ it 'appends .wiki to disk path' do
expect(wiki.disk_path).to eq project.wiki.disk_path
end
end
+ describe '#full_path' do
+ it 'appends .wiki to project path' do
+ expect(wiki.full_path).to eq project.wiki.full_path
+ end
+ end
+
describe '#import_url' do
it 'returns URL of the wiki repository' do
expect(wiki.import_url).to eq 'https://xxx@github.com/gitlabhq/sample.gitlabhq.wiki.git'
diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb
index 1ec1ba19e39..8961ecc4be0 100644
--- a/spec/lib/gitlab/lfs_token_spec.rb
+++ b/spec/lib/gitlab/lfs_token_spec.rb
@@ -4,10 +4,8 @@ require 'spec_helper'
describe Gitlab::LfsToken, :clean_gitlab_redis_shared_state do
describe '#token' do
- shared_examples 'an LFS token generator' do
+ shared_examples 'a valid LFS token' do
it 'returns a computed token' do
- expect(Settings).to receive(:attr_encrypted_db_key_base).and_return('fbnbv6hdjweo53qka7kza8v8swxc413c05pb51qgtfte0bygh1p2e508468hfsn5ntmjcyiz7h1d92ashpet5pkdyejg7g8or3yryhuso4h8o5c73h429d9c3r6bjnet').twice
-
token = lfs_token.token
expect(token).not_to be_nil
@@ -20,11 +18,7 @@ describe Gitlab::LfsToken, :clean_gitlab_redis_shared_state do
let(:actor) { create(:user, username: 'test_user_lfs_1') }
let(:lfs_token) { described_class.new(actor) }
- before do
- allow(actor).to receive(:encrypted_password).and_return('$2a$04$ETfzVS5spE9Hexn9wh6NUenCHG1LyZ2YdciOYxieV1WLSa8DHqOFO')
- end
-
- it_behaves_like 'an LFS token generator'
+ it_behaves_like 'a valid LFS token'
it 'returns the correct username' do
expect(lfs_token.actor_name).to eq(actor.username)
@@ -40,11 +34,7 @@ describe Gitlab::LfsToken, :clean_gitlab_redis_shared_state do
let(:actor) { create(:key, user: user) }
let(:lfs_token) { described_class.new(actor) }
- before do
- allow(user).to receive(:encrypted_password).and_return('$2a$04$C1GAMKsOKouEbhKy2JQoe./3LwOfQAZc.hC8zW2u/wt8xgukvnlV.')
- end
-
- it_behaves_like 'an LFS token generator'
+ it_behaves_like 'a valid LFS token'
it 'returns the correct username' do
expect(lfs_token.actor_name).to eq(user.username)
@@ -65,7 +55,7 @@ describe Gitlab::LfsToken, :clean_gitlab_redis_shared_state do
allow(actor).to receive(:id).and_return(actor_id)
end
- it_behaves_like 'an LFS token generator'
+ it_behaves_like 'a valid LFS token'
it 'returns the correct username' do
expect(lfs_token.actor_name).to eq("lfs+deploy-key-#{actor_id}")
@@ -87,10 +77,6 @@ describe Gitlab::LfsToken, :clean_gitlab_redis_shared_state do
let(:actor) { create(:user, username: 'test_user_lfs_1') }
let(:lfs_token) { described_class.new(actor) }
- before do
- allow(actor).to receive(:encrypted_password).and_return('$2a$04$ETfzVS5spE9Hexn9wh6NUenCHG1LyZ2YdciOYxieV1WLSa8DHqOFO')
- end
-
context 'for an HMAC token' do
before do
# We're not interested in testing LegacyRedisDeviseToken here
@@ -240,4 +226,18 @@ describe Gitlab::LfsToken, :clean_gitlab_redis_shared_state do
end
end
end
+
+ describe '#authentication_payload' do
+ it 'returns a Hash designed for gitlab-shell' do
+ actor = create(:user)
+ lfs_token = described_class.new(actor)
+ repo_http_path = 'http://localhost/user/repo.git'
+ authentication_payload = lfs_token.authentication_payload(repo_http_path)
+
+ expect(authentication_payload[:username]).to eq(actor.username)
+ expect(authentication_payload[:repository_http_path]).to eq(repo_http_path)
+ expect(authentication_payload[:lfs_token]).to be_a String
+ expect(authentication_payload[:expires_in]).to eq(described_class::DEFAULT_EXPIRE_TIME)
+ end
+ end
end
diff --git a/spec/lib/gitlab/loop_helpers_spec.rb b/spec/lib/gitlab/loop_helpers_spec.rb
new file mode 100644
index 00000000000..e17a0342d64
--- /dev/null
+++ b/spec/lib/gitlab/loop_helpers_spec.rb
@@ -0,0 +1,45 @@
+require 'spec_helper'
+
+describe Gitlab::LoopHelpers do
+ let(:class_instance) { (Class.new { include ::Gitlab::LoopHelpers }).new }
+
+ describe '#loop_until' do
+ subject do
+ class_instance.loop_until(**params) { true }
+ end
+
+ context 'when limit is not given' do
+ let(:params) { { limit: nil } }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ArgumentError)
+ end
+ end
+
+ context 'when timeout is specified' do
+ let(:params) { { timeout: 1.second } }
+
+ it "returns false after it's expired" do
+ is_expected.to be_falsy
+ end
+
+ it 'executes the block at least once' do
+ expect { |b| class_instance.loop_until(**params, &b) }
+ .to yield_control.at_least(1)
+ end
+ end
+
+ context 'when iteration limit is specified' do
+ let(:params) { { limit: 1 } }
+
+ it "returns false after it's expired" do
+ is_expected.to be_falsy
+ end
+
+ it 'executes the block once' do
+ expect { |b| class_instance.loop_until(**params, &b) }
+ .to yield_control.once
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
index 771b633a2b9..4b03f3c2532 100644
--- a/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
@@ -37,7 +37,7 @@ describe Gitlab::Metrics::Samplers::UnicornSampler do
end
it 'updates metrics type unix and with addr' do
- labels = { type: 'unix', address: socket_address }
+ labels = { socket_type: 'unix', socket_address: socket_address }
expect(subject).to receive_message_chain(:unicorn_active_connections, :set).with(labels, 'active')
expect(subject).to receive_message_chain(:unicorn_queued_connections, :set).with(labels, 'queued')
@@ -69,7 +69,7 @@ describe Gitlab::Metrics::Samplers::UnicornSampler do
end
it 'updates metrics type unix and with addr' do
- labels = { type: 'tcp', address: tcp_socket_address }
+ labels = { socket_type: 'tcp', socket_address: tcp_socket_address }
expect(subject).to receive_message_chain(:unicorn_active_connections, :set).with(labels, 'active')
expect(subject).to receive_message_chain(:unicorn_queued_connections, :set).with(labels, 'queued')
diff --git a/spec/lib/gitlab/middleware/go_spec.rb b/spec/lib/gitlab/middleware/go_spec.rb
index 7a3a9ab875b..f52095bf633 100644
--- a/spec/lib/gitlab/middleware/go_spec.rb
+++ b/spec/lib/gitlab/middleware/go_spec.rb
@@ -96,43 +96,36 @@ describe Gitlab::Middleware::Go do
it_behaves_like 'unauthorized'
end
- end
-
- context 'using warden' do
- before do
- env['warden'] = double(authenticate: current_user)
- end
- context 'when active' do
- it_behaves_like 'authenticated'
- end
-
- context 'when blocked' do
+ context 'with user is blocked' do
before do
- current_user.block!
+ current_user.block
end
it_behaves_like 'unauthorized'
end
end
- context 'using a personal access token' do
- let(:personal_access_token) { create(:personal_access_token, user: current_user) }
-
- before do
- env['HTTP_PRIVATE_TOKEN'] = personal_access_token.token
- end
-
- context 'with api scope' do
- it_behaves_like 'authenticated'
- end
+ context 'using basic auth' do
+ context 'using a personal access token' do
+ let(:personal_access_token) { create(:personal_access_token, user: current_user) }
- context 'with read_user scope' do
before do
- personal_access_token.update_attribute(:scopes, [:read_user])
+ env['REMOTE_ADDR'] = "192.168.0.1"
+ env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(current_user.username, personal_access_token.token)
end
- it_behaves_like 'unauthorized'
+ context 'with api scope' do
+ it_behaves_like 'authenticated'
+ end
+
+ context 'with read_user scope' do
+ before do
+ personal_access_token.update_attribute(:scopes, [:read_user])
+ end
+
+ it_behaves_like 'unauthorized'
+ end
end
end
end
diff --git a/spec/lib/gitlab/middleware/multipart_spec.rb b/spec/lib/gitlab/middleware/multipart_spec.rb
index daf454665b0..3f6ada6832a 100644
--- a/spec/lib/gitlab/middleware/multipart_spec.rb
+++ b/spec/lib/gitlab/middleware/multipart_spec.rb
@@ -10,7 +10,9 @@ describe Gitlab::Middleware::Multipart do
shared_examples_for 'multipart upload files' do
it 'opens top-level files' do
Tempfile.open('top-level') do |tempfile|
- env = post_env({ 'file' => tempfile.path }, { 'file.name' => original_filename, 'file.path' => tempfile.path, 'file.remote_id' => remote_id }, Gitlab::Workhorse.secret, 'gitlab-workhorse')
+ rewritten = { 'file' => tempfile.path }
+ in_params = { 'file.name' => original_filename, 'file.path' => tempfile.path, 'file.remote_id' => remote_id }
+ env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
expect_uploaded_file(tempfile, %w(file))
@@ -21,7 +23,8 @@ describe Gitlab::Middleware::Multipart do
it 'opens files one level deep' do
Tempfile.open('one-level') do |tempfile|
in_params = { 'user' => { 'avatar' => { '.name' => original_filename, '.path' => tempfile.path, '.remote_id' => remote_id } } }
- env = post_env({ 'user[avatar]' => tempfile.path }, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
+ rewritten = { 'user[avatar]' => tempfile.path }
+ env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
expect_uploaded_file(tempfile, %w(user avatar))
@@ -32,7 +35,8 @@ describe Gitlab::Middleware::Multipart do
it 'opens files two levels deep' do
Tempfile.open('two-levels') do |tempfile|
in_params = { 'project' => { 'milestone' => { 'themesong' => { '.name' => original_filename, '.path' => tempfile.path, '.remote_id' => remote_id } } } }
- env = post_env({ 'project[milestone][themesong]' => tempfile.path }, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
+ rewritten = { 'project[milestone][themesong]' => tempfile.path }
+ env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
expect_uploaded_file(tempfile, %w(project milestone themesong))
@@ -42,7 +46,7 @@ describe Gitlab::Middleware::Multipart do
def expect_uploaded_file(tempfile, path, remote: false)
expect(app).to receive(:call) do |env|
- file = Rack::Request.new(env).params.dig(*path)
+ file = get_params(env).dig(*path)
expect(file).to be_a(::UploadedFile)
expect(file.path).to eq(tempfile.path)
expect(file.original_filename).to eq(original_filename)
@@ -87,7 +91,7 @@ describe Gitlab::Middleware::Multipart do
env = post_env({ 'file' => tempfile.path }, { 'file.name' => original_filename, 'file.path' => tempfile.path }, Gitlab::Workhorse.secret, 'gitlab-workhorse')
expect(app).to receive(:call) do |env|
- expect(Rack::Request.new(env).params['file']).to be_a(::UploadedFile)
+ expect(get_params(env)['file']).to be_a(::UploadedFile)
end
middleware.call(env)
@@ -115,13 +119,21 @@ describe Gitlab::Middleware::Multipart do
allow(Dir).to receive(:tmpdir).and_return(File.join(Dir.tmpdir, 'tmpsubdir'))
expect(app).to receive(:call) do |env|
- expect(Rack::Request.new(env).params['file']).to be_a(::UploadedFile)
+ expect(get_params(env)['file']).to be_a(::UploadedFile)
end
middleware.call(env)
end
end
+ # Rails 5 doesn't combine the GET/POST parameters in
+ # ActionDispatch::HTTP::Parameters if action_dispatch.request.parameters is set:
+ # https://github.com/rails/rails/blob/aea6423f013ca48f7704c70deadf2cd6ac7d70a1/actionpack/lib/action_dispatch/http/parameters.rb#L41
+ def get_params(env)
+ req = ActionDispatch::Request.new(env)
+ req.GET.merge(req.POST)
+ end
+
def post_env(rewritten_fields, params, secret, issuer)
token = JWT.encode({ 'iss' => issuer, 'rewritten_fields' => rewritten_fields }, secret, 'HS256')
Rack::MockRequest.env_for(
diff --git a/spec/lib/gitlab/middleware/read_only_spec.rb b/spec/lib/gitlab/middleware/read_only_spec.rb
index bdb1f34d2f6..24d49a049b6 100644
--- a/spec/lib/gitlab/middleware/read_only_spec.rb
+++ b/spec/lib/gitlab/middleware/read_only_spec.rb
@@ -101,16 +101,36 @@ describe Gitlab::Middleware::ReadOnly do
expect(subject).not_to disallow_request
end
- it 'expects requests to sidekiq admin to be allowed' do
- response = request.post('/admin/sidekiq')
+ context 'sidekiq admin requests' do
+ where(:mounted_at) do
+ [
+ '',
+ '/',
+ '/gitlab',
+ '/gitlab/',
+ '/gitlab/gitlab',
+ '/gitlab/gitlab/'
+ ]
+ end
- expect(response).not_to be_redirect
- expect(subject).not_to disallow_request
+ with_them do
+ before do
+ stub_config_setting(relative_url_root: mounted_at)
+ end
- response = request.get('/admin/sidekiq')
+ it 'allows requests' do
+ path = File.join(mounted_at, 'admin/sidekiq')
+ response = request.post(path)
- expect(response).not_to be_redirect
- expect(subject).not_to disallow_request
+ expect(response).not_to be_redirect
+ expect(subject).not_to disallow_request
+
+ response = request.get(path)
+
+ expect(response).not_to be_redirect
+ expect(subject).not_to disallow_request
+ end
+ end
end
where(:description, :path) do
diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb
index e90e0aba0a4..312e5e55af8 100644
--- a/spec/lib/gitlab/path_regex_spec.rb
+++ b/spec/lib/gitlab/path_regex_spec.rb
@@ -107,7 +107,7 @@ describe Gitlab::PathRegex do
git = Gitlab.config.git.bin_path
tracked = `cd #{Rails.root} && #{git} ls-files public`
.split("\n")
- .map { |entry| entry.gsub('public/', '') }
+ .map { |entry| entry.start_with?('public/-/') ? '-' : entry.gsub('public/', '') }
.uniq
tracked + %w(assets uploads)
end
diff --git a/spec/lib/gitlab/profiler_spec.rb b/spec/lib/gitlab/profiler_spec.rb
index 8bb0c1a0b8a..9f2214f7ce7 100644
--- a/spec/lib/gitlab/profiler_spec.rb
+++ b/spec/lib/gitlab/profiler_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
describe Gitlab::Profiler do
- RSpec::Matchers.define_negated_matcher :not_change, :change
-
let(:null_logger) { Logger.new('/dev/null') }
let(:private_token) { 'private' }
@@ -187,7 +185,7 @@ describe Gitlab::Profiler do
end
it 'does not modify the standard Rails loggers' do
- expect { described_class.with_custom_logger(nil) { } }
+ expect { described_class.with_custom_logger(nil) {} }
.to not_change { ActiveRecord::Base.logger }
.and not_change { ActionController::Base.logger }
.and not_change { ActiveSupport::LogSubscriber.colorize_logging }
@@ -204,7 +202,7 @@ describe Gitlab::Profiler do
end
it 'cleans up ApplicationController afterwards' do
- expect { described_class.with_user(user) { } }
+ expect { described_class.with_user(user) {} }
.to not_change { ActionController.instance_methods(false) }
end
end
@@ -213,7 +211,7 @@ describe Gitlab::Profiler do
it 'does not define methods on ApplicationController' do
expect(ApplicationController).not_to receive(:define_method)
- described_class.with_user(nil) { }
+ described_class.with_user(nil) {}
end
end
end
diff --git a/spec/lib/gitlab/project_template_spec.rb b/spec/lib/gitlab/project_template_spec.rb
index 57b0ef8d1ad..115097e0d26 100644
--- a/spec/lib/gitlab/project_template_spec.rb
+++ b/spec/lib/gitlab/project_template_spec.rb
@@ -6,7 +6,19 @@ describe Gitlab::ProjectTemplate do
expected = [
described_class.new('rails', 'Ruby on Rails', 'Includes an MVC structure, .gitignore, Gemfile, and more great stuff', 'https://gitlab.com/gitlab-org/project-templates/rails'),
described_class.new('spring', 'Spring', 'Includes an MVC structure, .gitignore, Gemfile, and more great stuff', 'https://gitlab.com/gitlab-org/project-templates/spring'),
- described_class.new('express', 'NodeJS Express', 'Includes an MVC structure, .gitignore, Gemfile, and more great stuff', 'https://gitlab.com/gitlab-org/project-templates/express')
+ described_class.new('express', 'NodeJS Express', 'Includes an MVC structure, .gitignore, Gemfile, and more great stuff', 'https://gitlab.com/gitlab-org/project-templates/express'),
+ described_class.new('dotnetcore', '.NET Core', 'A .NET Core console application template, customizable for any .NET Core project', 'https://gitlab.com/gitlab-org/project-templates/dotnetcore'),
+ described_class.new('gomicro', 'Go Micro', 'Go Micro is a framework for micro service development.', 'https://gitlab.com/gitlab-org/project-templates/go-micro'),
+ described_class.new('hugo', 'Pages/Hugo', 'Everything you need to get started using a Hugo Pages site.', 'https://gitlab.com/pages/hugo'),
+ described_class.new('jekyll', 'Pages/Jekyll', 'Everything you need to get started using a Jekyll Pages site.', 'https://gitlab.com/pages/jekyll'),
+ described_class.new('plainhtml', 'Pages/Plain HTML', 'Everything you need to get started using a plain HTML Pages site.', 'https://gitlab.com/pages/plain-html'),
+ described_class.new('gitbook', 'Pages/GitBook', 'Everything you need to get started using a GitBook Pages site.', 'https://gitlab.com/pages/gitbook'),
+ described_class.new('hexo', 'Pages/Hexo', 'Everything you need to get started using a Hexo Pages site.', 'https://gitlab.com/pages/hexo'),
+ described_class.new('nfhugo', 'Netlify/Hugo', _('A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfhugo'),
+ described_class.new('nfjekyll', 'Netlify/Jekyll', _('A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfjekyll'),
+ described_class.new('nfplainhtml', 'Netlify/Plain HTML', _('A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfplain-html'),
+ described_class.new('nfgitbook', 'Netlify/GitBook', _('A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfgitbook'),
+ described_class.new('nfhexo', 'Netlify/Hexo', _('A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfhexo')
]
expect(described_class.all).to be_an(Array)
diff --git a/spec/lib/gitlab/prometheus/metric_group_spec.rb b/spec/lib/gitlab/prometheus/metric_group_spec.rb
index e7d16e73663..5cc6827488b 100644
--- a/spec/lib/gitlab/prometheus/metric_group_spec.rb
+++ b/spec/lib/gitlab/prometheus/metric_group_spec.rb
@@ -21,6 +21,13 @@ describe Gitlab::Prometheus::MetricGroup do
common_metric_group_a.id, common_metric_group_b_q1.id,
common_metric_group_b_q2.id)
end
+
+ it 'orders by priority' do
+ priorities = subject.map(&:priority)
+ names = subject.map(&:name)
+ expect(priorities).to eq([10, 5])
+ expect(names).to eq(['Response metrics (AWS ELB)', 'System metrics (Kubernetes)'])
+ end
end
describe '.for_project' do
diff --git a/spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb b/spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb
index 420218a695a..936447b8474 100644
--- a/spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb
+++ b/spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb
@@ -15,7 +15,7 @@ describe Gitlab::Prometheus::Queries::MatchedMetricQuery do
[{ '__name__' => 'metric_a' },
{ '__name__' => 'metric_b' }]
end
- let(:partialy_empty_series_info) { [{ '__name__' => 'metric_a', 'environment' => '' }] }
+ let(:partially_empty_series_info) { [{ '__name__' => 'metric_a', 'environment' => '' }] }
let(:empty_series_info) { [] }
let(:client) { double('prometheus_client') }
@@ -60,7 +60,7 @@ describe Gitlab::Prometheus::Queries::MatchedMetricQuery do
context 'one of the series info was not found' do
before do
- allow(client).to receive(:series).and_return(partialy_empty_series_info)
+ allow(client).to receive(:series).and_return(partially_empty_series_info)
end
it 'responds with one active and one missing metric' do
expect(subject.query).to eq([{ group: 'name', priority: 1, active_metrics: 1, metrics_missing_requirements: 1 }])
diff --git a/spec/lib/gitlab/quick_actions/command_definition_spec.rb b/spec/lib/gitlab/quick_actions/command_definition_spec.rb
index 5dae82a63b4..136cfb5bcc5 100644
--- a/spec/lib/gitlab/quick_actions/command_definition_spec.rb
+++ b/spec/lib/gitlab/quick_actions/command_definition_spec.rb
@@ -72,7 +72,7 @@ describe Gitlab::QuickActions::CommandDefinition do
end
describe "#execute" do
- let(:context) { OpenStruct.new(run: false) }
+ let(:context) { OpenStruct.new(run: false, commands_executed_count: nil) }
context "when the command is a noop" do
it "doesn't execute the command" do
@@ -80,6 +80,7 @@ describe Gitlab::QuickActions::CommandDefinition do
subject.execute(context, nil)
+ expect(context.commands_executed_count).to be_nil
expect(context.run).to be false
end
end
@@ -97,6 +98,7 @@ describe Gitlab::QuickActions::CommandDefinition do
it "doesn't execute the command" do
subject.execute(context, nil)
+ expect(context.commands_executed_count).to be_nil
expect(context.run).to be false
end
end
@@ -112,6 +114,7 @@ describe Gitlab::QuickActions::CommandDefinition do
subject.execute(context, true)
expect(context.run).to be true
+ expect(context.commands_executed_count).to eq(1)
end
end
@@ -120,6 +123,7 @@ describe Gitlab::QuickActions::CommandDefinition do
subject.execute(context, nil)
expect(context.run).to be true
+ expect(context.commands_executed_count).to eq(1)
end
end
end
@@ -134,6 +138,7 @@ describe Gitlab::QuickActions::CommandDefinition do
subject.execute(context, true)
expect(context.run).to be true
+ expect(context.commands_executed_count).to eq(1)
end
end
diff --git a/spec/lib/gitlab/repository_cache_spec.rb b/spec/lib/gitlab/repository_cache_spec.rb
index 1b9a8b4ab0d..741ee12633f 100644
--- a/spec/lib/gitlab/repository_cache_spec.rb
+++ b/spec/lib/gitlab/repository_cache_spec.rb
@@ -4,14 +4,14 @@ describe Gitlab::RepositoryCache do
let(:backend) { double('backend').as_null_object }
let(:project) { create(:project) }
let(:repository) { project.repository }
- let(:namespace) { "project:#{project.id}" }
+ let(:namespace) { "#{repository.full_path}:#{project.id}" }
let(:cache) { described_class.new(repository, backend: backend) }
describe '#cache_key' do
subject { cache.cache_key(:foo) }
it 'includes the namespace' do
- expect(subject).to eq "#{namespace}:foo"
+ expect(subject).to eq "foo:#{namespace}"
end
context 'with a given namespace' do
@@ -22,7 +22,7 @@ describe Gitlab::RepositoryCache do
end
it 'includes the full namespace' do
- expect(subject).to eq "#{namespace}:#{extra_namespace}:foo"
+ expect(subject).to eq "foo:#{namespace}:#{extra_namespace}"
end
end
end
@@ -30,21 +30,21 @@ describe Gitlab::RepositoryCache do
describe '#expire' do
it 'expires the given key from the cache' do
cache.expire(:foo)
- expect(backend).to have_received(:delete).with("#{namespace}:foo")
+ expect(backend).to have_received(:delete).with("foo:#{namespace}")
end
end
describe '#fetch' do
it 'fetches the given key from the cache' do
cache.fetch(:bar)
- expect(backend).to have_received(:fetch).with("#{namespace}:bar")
+ expect(backend).to have_received(:fetch).with("bar:#{namespace}")
end
it 'accepts a block' do
p = -> {}
cache.fetch(:baz, &p)
- expect(backend).to have_received(:fetch).with("#{namespace}:baz", &p)
+ expect(backend).to have_received(:fetch).with("baz:#{namespace}", &p)
end
end
@@ -67,7 +67,7 @@ describe Gitlab::RepositoryCache do
end
it 'caches the value' do
- expect(backend).to receive(:write).with("#{namespace}:#{key}", true)
+ expect(backend).to receive(:write).with("#{key}:#{namespace}", true)
cache.fetch_without_caching_false(key) { true }
end
@@ -83,7 +83,7 @@ describe Gitlab::RepositoryCache do
end
it 'does not cache the value' do
- expect(backend).not_to receive(:write).with("#{namespace}:#{key}", true)
+ expect(backend).not_to receive(:write).with("#{key}:#{namespace}", true)
cache.fetch_without_caching_false(key, &p)
end
@@ -92,7 +92,7 @@ describe Gitlab::RepositoryCache do
context 'when the cached value is truthy' do
before do
- backend.write("#{namespace}:#{key}", true)
+ backend.write("#{key}:#{namespace}", true)
end
it 'returns the cached value' do
@@ -116,7 +116,7 @@ describe Gitlab::RepositoryCache do
context 'when the cached value is falsey' do
before do
- backend.write("#{namespace}:#{key}", false)
+ backend.write("#{key}:#{namespace}", false)
end
it 'returns the result of the block' do
@@ -126,7 +126,7 @@ describe Gitlab::RepositoryCache do
end
it 'writes the truthy value to the cache' do
- expect(backend).to receive(:write).with("#{namespace}:#{key}", 'block result')
+ expect(backend).to receive(:write).with("#{key}:#{namespace}", 'block result')
cache.fetch_without_caching_false(key) { 'block result' }
end
diff --git a/spec/lib/gitlab/request_context_spec.rb b/spec/lib/gitlab/request_context_spec.rb
index 8a28ad0e597..fd443cc1f71 100644
--- a/spec/lib/gitlab/request_context_spec.rb
+++ b/spec/lib/gitlab/request_context_spec.rb
@@ -15,7 +15,7 @@ describe Gitlab::RequestContext do
let(:ip) { '192.168.1.11' }
before do
- allow_any_instance_of(Rack::Request).to receive(:ip).and_return(ip)
+ allow_any_instance_of(ActionDispatch::Request).to receive(:ip).and_return(ip)
described_class.new(app).call(env)
end
diff --git a/spec/lib/gitlab/serializer/pagination_spec.rb b/spec/lib/gitlab/serializer/pagination_spec.rb
index 1bc6536439e..c54be78f050 100644
--- a/spec/lib/gitlab/serializer/pagination_spec.rb
+++ b/spec/lib/gitlab/serializer/pagination_spec.rb
@@ -1,16 +1,12 @@
require 'spec_helper'
describe Gitlab::Serializer::Pagination do
- let(:request) { spy('request') }
+ let(:request) { double(url: "#{Gitlab.config.gitlab.url}:8080/api/v4/projects?#{query.to_query}", query_parameters: query) }
let(:response) { spy('response') }
let(:headers) { spy('headers') }
before do
- allow(request).to receive(:query_parameters)
- .and_return(params)
-
- allow(response).to receive(:headers)
- .and_return(headers)
+ allow(response).to receive(:headers).and_return(headers)
end
let(:pagination) { described_class.new(request, response) }
@@ -19,7 +15,7 @@ describe Gitlab::Serializer::Pagination do
subject { pagination.paginate(resource) }
let(:resource) { User.all }
- let(:params) { { page: 1, per_page: 2 } }
+ let(:query) { { page: 1, per_page: 2 } }
context 'when a multiple resources are present in relation' do
before do
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index 6ce9d515a0f..d6aadf0f7de 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -393,7 +393,6 @@ describe Gitlab::Shell do
before do
allow(Gitlab.config.gitlab_shell).to receive(:path).and_return(gitlab_shell_path)
- allow(Gitlab.config.gitlab_shell).to receive(:hooks_path).and_return(gitlab_shell_hooks_path)
allow(Gitlab.config.gitlab_shell).to receive(:git_timeout).and_return(800)
end
@@ -412,7 +411,7 @@ describe Gitlab::Shell do
end
it 'creates a repository' do
- expect(gitlab_shell.create_repository(repository_storage, repo_name)).to be_truthy
+ expect(gitlab_shell.create_repository(repository_storage, repo_name, repo_name)).to be_truthy
expect(File.stat(created_path).mode & 0o777).to eq(0o770)
@@ -427,7 +426,7 @@ describe Gitlab::Shell do
# should cause #create_repository to fail.
FileUtils.touch(created_path)
- expect(gitlab_shell.create_repository(repository_storage, repo_name)).to be_falsy
+ expect(gitlab_shell.create_repository(repository_storage, repo_name, repo_name)).to be_falsy
end
end
@@ -474,13 +473,10 @@ describe Gitlab::Shell do
end
describe '#fork_repository' do
+ let(:target_project) { create(:project) }
+
subject do
- gitlab_shell.fork_repository(
- project.repository_storage,
- project.disk_path,
- 'nfs-file05',
- 'fork/path'
- )
+ gitlab_shell.fork_repository(project, target_project)
end
it 'returns true when the command succeeds' do
@@ -505,7 +501,7 @@ describe Gitlab::Shell do
it 'returns true when the command succeeds' do
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:import_repository).with(import_url)
- result = gitlab_shell.import_repository(project.repository_storage, project.disk_path, import_url)
+ result = gitlab_shell.import_repository(project.repository_storage, project.disk_path, import_url, project.full_path)
expect(result).to be_truthy
end
@@ -516,7 +512,7 @@ describe Gitlab::Shell do
expect_any_instance_of(Gitlab::Shell::GitalyGitlabProjects).to receive(:output) { 'error'}
expect do
- gitlab_shell.import_repository(project.repository_storage, project.disk_path, import_url)
+ gitlab_shell.import_repository(project.repository_storage, project.disk_path, import_url, project.full_path)
end.to raise_error(Gitlab::Shell::Error, "error")
end
end
diff --git a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
index f773f370ee2..7bc4599e20f 100644
--- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
@@ -16,7 +16,7 @@ describe Gitlab::SidekiqLogging::StructuredLogger do
"correlation_id" => 'cid'
}
end
- let(:logger) { double() }
+ let(:logger) { double }
let(:start_payload) do
job.merge(
'message' => 'TestWorker JID-da883554ee4fe414012f5f42: start',
@@ -82,15 +82,36 @@ describe Gitlab::SidekiqLogging::StructuredLogger do
end.to raise_error(ArgumentError)
end
end
+
+ context 'when the job args are bigger than the maximum allowed' do
+ it 'keeps args from the front until they exceed the limit' do
+ Timecop.freeze(timestamp) do
+ job['args'] = [
+ 1,
+ 2,
+ 'a' * (described_class::MAXIMUM_JOB_ARGUMENTS_LENGTH / 2),
+ 'b' * (described_class::MAXIMUM_JOB_ARGUMENTS_LENGTH / 2),
+ 3
+ ]
+
+ expected_args = job['args'].take(3) + ['...']
+
+ expect(logger).to receive(:info).with(start_payload.merge('args' => expected_args)).ordered
+ expect(logger).to receive(:info).with(end_payload.merge('args' => expected_args)).ordered
+ expect(subject).to receive(:log_job_start).and_call_original
+ expect(subject).to receive(:log_job_done).and_call_original
+
+ subject.call(job, 'test_queue') { }
+ end
+ end
+ end
end
context 'with SIDEKIQ_LOG_ARGUMENTS disabled' do
- it 'logs start and end of job' do
+ it 'logs start and end of job without args' do
Timecop.freeze(timestamp) do
- start_payload.delete('args')
-
- expect(logger).to receive(:info).with(start_payload).ordered
- expect(logger).to receive(:info).with(end_payload).ordered
+ expect(logger).to receive(:info).with(start_payload.except('args')).ordered
+ expect(logger).to receive(:info).with(end_payload.except('args')).ordered
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
diff --git a/spec/lib/gitlab/sidekiq_middleware/memory_killer_spec.rb b/spec/lib/gitlab/sidekiq_middleware/memory_killer_spec.rb
new file mode 100644
index 00000000000..ff8c0825ee4
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/memory_killer_spec.rb
@@ -0,0 +1,74 @@
+require 'spec_helper'
+
+describe Gitlab::SidekiqMiddleware::MemoryKiller do
+ subject { described_class.new }
+ let(:pid) { 999 }
+
+ let(:worker) { double(:worker, class: 'TestWorker') }
+ let(:job) { { 'jid' => 123 } }
+ let(:queue) { 'test_queue' }
+
+ def run
+ thread = subject.call(worker, job, queue) { nil }
+ thread&.join
+ end
+
+ before do
+ allow(subject).to receive(:get_rss).and_return(10.kilobytes)
+ allow(subject).to receive(:pid).and_return(pid)
+ end
+
+ context 'when MAX_RSS is set to 0' do
+ before do
+ stub_const("#{described_class}::MAX_RSS", 0)
+ end
+
+ it 'does nothing' do
+ expect(subject).not_to receive(:sleep)
+
+ run
+ end
+ end
+
+ context 'when MAX_RSS is exceeded' do
+ before do
+ stub_const("#{described_class}::MAX_RSS", 5.kilobytes)
+ end
+
+ it 'sends the TSTP, TERM and KILL signals at expected times' do
+ expect(subject).to receive(:sleep).with(15 * 60).ordered
+ expect(Process).to receive(:kill).with('SIGTSTP', pid).ordered
+
+ expect(subject).to receive(:sleep).with(30).ordered
+ expect(Process).to receive(:kill).with('SIGTERM', pid).ordered
+
+ expect(subject).to receive(:sleep).with(10).ordered
+ expect(Process).to receive(:kill).with('SIGKILL', pid).ordered
+
+ run
+ end
+
+ it 'sends TSTP and TERM to the pid, but KILL to the pgroup, when running as process leader' do
+ allow(Process).to receive(:getpgrp) { pid }
+ allow(subject).to receive(:sleep)
+
+ expect(Process).to receive(:kill).with('SIGTSTP', pid).ordered
+ expect(Process).to receive(:kill).with('SIGTERM', pid).ordered
+ expect(Process).to receive(:kill).with('SIGKILL', "-#{pid}").ordered
+
+ run
+ end
+ end
+
+ context 'when MAX_RSS is not exceeded' do
+ before do
+ stub_const("#{described_class}::MAX_RSS", 15.kilobytes)
+ end
+
+ it 'does nothing' do
+ expect(subject).not_to receive(:sleep)
+
+ run
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/shutdown_spec.rb b/spec/lib/gitlab/sidekiq_middleware/shutdown_spec.rb
deleted file mode 100644
index 0001795c3f0..00000000000
--- a/spec/lib/gitlab/sidekiq_middleware/shutdown_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::SidekiqMiddleware::Shutdown do
- subject { described_class.new }
-
- let(:pid) { Process.pid }
- let(:worker) { double(:worker, class: 'TestWorker') }
- let(:job) { { 'jid' => 123 } }
- let(:queue) { 'test_queue' }
- let(:block) { proc { nil } }
-
- def run
- subject.call(worker, job, queue) { block.call }
- described_class.shutdown_thread&.join
- end
-
- def pop_trace
- subject.trace.pop(true)
- end
-
- before do
- allow(subject).to receive(:get_rss).and_return(10.kilobytes)
- described_class.clear_shutdown_thread
- end
-
- context 'when MAX_RSS is set to 0' do
- before do
- stub_const("#{described_class}::MAX_RSS", 0)
- end
-
- it 'does nothing' do
- expect(subject).not_to receive(:sleep)
-
- run
- end
- end
-
- def expect_shutdown_sequence
- expect(pop_trace).to eq([:sleep, 15 * 60])
- expect(pop_trace).to eq([:kill, 'SIGTSTP', pid])
-
- expect(pop_trace).to eq([:sleep, 30])
- expect(pop_trace).to eq([:kill, 'SIGTERM', pid])
-
- expect(pop_trace).to eq([:sleep, 10])
- expect(pop_trace).to eq([:kill, 'SIGKILL', pid])
- end
-
- context 'when MAX_RSS is exceeded' do
- before do
- stub_const("#{described_class}::MAX_RSS", 5.kilobytes)
- end
-
- it 'sends the TSTP, TERM and KILL signals at expected times' do
- run
-
- expect_shutdown_sequence
- end
- end
-
- context 'when MAX_RSS is not exceeded' do
- before do
- stub_const("#{described_class}::MAX_RSS", 15.kilobytes)
- end
-
- it 'does nothing' do
- expect(subject).not_to receive(:sleep)
-
- run
- end
- end
-
- context 'when WantShutdown is raised' do
- let(:block) { proc { raise described_class::WantShutdown } }
-
- it 'starts the shutdown sequence and re-raises the exception' do
- expect { run }.to raise_exception(described_class::WantShutdown)
-
- # We can't expect 'run' to have joined on the shutdown thread, because
- # it hit an exception.
- shutdown_thread = described_class.shutdown_thread
- expect(shutdown_thread).not_to be_nil
- shutdown_thread.join
-
- expect_shutdown_sequence
- end
- end
-end
diff --git a/spec/lib/gitlab/sidekiq_signals_spec.rb b/spec/lib/gitlab/sidekiq_signals_spec.rb
new file mode 100644
index 00000000000..4483224f49d
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_signals_spec.rb
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+describe Gitlab::SidekiqSignals do
+ describe '.install' do
+ let(:result) { Hash.new { |h, k| h[k] = 0 } }
+ let(:int_handler) { -> (_) { result['INT'] += 1 } }
+ let(:term_handler) { -> (_) { result['TERM'] += 1 } }
+ let(:other_handler) { -> (_) { result['OTHER'] += 1 } }
+ let(:signals) { { 'INT' => int_handler, 'TERM' => term_handler, 'OTHER' => other_handler } }
+
+ context 'not a process group leader' do
+ before do
+ allow(Process).to receive(:getpgrp) { Process.pid * 2 }
+ end
+
+ it 'does nothing' do
+ expect { described_class.install!(signals) }
+ .not_to change { signals }
+ end
+ end
+
+ context 'as a process group leader' do
+ before do
+ allow(Process).to receive(:getpgrp) { Process.pid }
+ end
+
+ it 'installs its own signal handlers for TERM and INT only' do
+ described_class.install!(signals)
+
+ expect(signals['INT']).not_to eq(int_handler)
+ expect(signals['TERM']).not_to eq(term_handler)
+ expect(signals['OTHER']).to eq(other_handler)
+ end
+
+ %w[INT TERM].each do |signal|
+ it "installs a forwarding signal handler for #{signal}" do
+ described_class.install!(signals)
+
+ expect(described_class)
+ .to receive(:trap)
+ .with(signal, 'IGNORE')
+ .and_return(:original_trap)
+ .ordered
+
+ expect(Process)
+ .to receive(:kill)
+ .with(signal, "-#{Process.pid}")
+ .ordered
+
+ expect(described_class)
+ .to receive(:trap)
+ .with(signal, :original_trap)
+ .ordered
+
+ signals[signal].call(:cli)
+
+ expect(result[signal]).to eq(1)
+ end
+
+ it "raises if sidekiq no longer traps SIG#{signal}" do
+ signals.delete(signal)
+
+ expect { described_class.install!(signals) }
+ .to raise_error(/Sidekiq should have registered/)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/slash_commands/application_help_spec.rb b/spec/lib/gitlab/slash_commands/application_help_spec.rb
new file mode 100644
index 00000000000..b203a1ee79c
--- /dev/null
+++ b/spec/lib/gitlab/slash_commands/application_help_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::SlashCommands::ApplicationHelp do
+ let(:params) { { command: '/gitlab', text: 'help' } }
+
+ describe '#execute' do
+ subject do
+ described_class.new(params).execute
+ end
+
+ it 'displays the help section' do
+ expect(subject[:response_type]).to be(:ephemeral)
+ expect(subject[:text]).to include('Available commands')
+ expect(subject[:text]).to include('/gitlab [project name or alias] issue show')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/slash_commands/issue_new_spec.rb b/spec/lib/gitlab/slash_commands/issue_new_spec.rb
index 724c76ade6e..59de11766d8 100644
--- a/spec/lib/gitlab/slash_commands/issue_new_spec.rb
+++ b/spec/lib/gitlab/slash_commands/issue_new_spec.rb
@@ -44,7 +44,7 @@ describe Gitlab::SlashCommands::IssueNew do
end
context 'issue cannot be created' do
- let!(:issue) { create(:issue, project: project, title: 'bird is the word') }
+ let!(:issue) { create(:issue, project: project, title: 'bird is the word') }
let(:regex_match) { described_class.match("issue create #{'a' * 512}}") }
it 'displays the errors' do
diff --git a/spec/lib/gitlab/slash_commands/presenters/error_spec.rb b/spec/lib/gitlab/slash_commands/presenters/error_spec.rb
new file mode 100644
index 00000000000..30ff81510c1
--- /dev/null
+++ b/spec/lib/gitlab/slash_commands/presenters/error_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::SlashCommands::Presenters::Error do
+ subject { described_class.new('Error').message }
+
+ it { is_expected.to be_a(Hash) }
+
+ it 'shows the error message' do
+ expect(subject[:response_type]).to be(:ephemeral)
+ expect(subject[:status]).to eq(200)
+ expect(subject[:text]).to eq('Error')
+ end
+end
diff --git a/spec/lib/gitlab/slash_commands/presenters/run_spec.rb b/spec/lib/gitlab/slash_commands/presenters/run_spec.rb
new file mode 100644
index 00000000000..f3ab01ef6bb
--- /dev/null
+++ b/spec/lib/gitlab/slash_commands/presenters/run_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::SlashCommands::Presenters::Run do
+ let(:presenter) { described_class.new }
+
+ describe '#present' do
+ context 'when no builds are present' do
+ it 'returns an error' do
+ builds = double(:builds, take: nil)
+ pipeline = double(:pipeline, builds: builds)
+
+ expect(presenter)
+ .to receive(:unsupported_chat_service)
+
+ presenter.present(pipeline)
+ end
+ end
+
+ context 'when a responder could be found' do
+ it 'returns the output for a scheduled pipeline' do
+ responder = double(:responder, scheduled_output: 'hello')
+ build = double(:build)
+ builds = double(:builds, take: build)
+ pipeline = double(:pipeline, builds: builds)
+
+ allow(Gitlab::Chat::Responder)
+ .to receive(:responder_for)
+ .with(build)
+ .and_return(responder)
+
+ expect(presenter)
+ .to receive(:in_channel_response)
+ .with('hello')
+
+ presenter.present(pipeline)
+ end
+ end
+
+ context 'when a responder could not be found' do
+ it 'returns an error' do
+ build = double(:build)
+ builds = double(:builds, take: build)
+ pipeline = double(:pipeline, builds: builds)
+
+ allow(Gitlab::Chat::Responder)
+ .to receive(:responder_for)
+ .with(build)
+ .and_return(nil)
+
+ expect(presenter)
+ .to receive(:unsupported_chat_service)
+
+ presenter.present(pipeline)
+ end
+ end
+ end
+
+ describe '#unsupported_chat_service' do
+ it 'returns an ephemeral response' do
+ expect(presenter)
+ .to receive(:ephemeral_response)
+ .with(text: /Sorry, this chat service is currently not supported/)
+
+ presenter.unsupported_chat_service
+ end
+ end
+
+ describe '#failed_to_schedule' do
+ it 'returns an ephemeral response' do
+ expect(presenter)
+ .to receive(:ephemeral_response)
+ .with(text: /The command could not be scheduled/)
+
+ presenter.failed_to_schedule('foo')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/slash_commands/run_spec.rb b/spec/lib/gitlab/slash_commands/run_spec.rb
new file mode 100644
index 00000000000..900fae05719
--- /dev/null
+++ b/spec/lib/gitlab/slash_commands/run_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::SlashCommands::Run do
+ describe '.available?' do
+ it 'returns true when builds are enabled for the project' do
+ project = double(:project, builds_enabled?: true)
+
+ allow(Gitlab::Chat)
+ .to receive(:available?)
+ .and_return(true)
+
+ expect(described_class.available?(project)).to eq(true)
+ end
+
+ it 'returns false when builds are disabled for the project' do
+ project = double(:project, builds_enabled?: false)
+
+ expect(described_class.available?(project)).to eq(false)
+ end
+
+ it 'returns false when chatops is not available' do
+ allow(Gitlab::Chat)
+ .to receive(:available?)
+ .and_return(false)
+
+ project = double(:project, builds_enabled?: true)
+
+ expect(described_class.available?(project)).to eq(false)
+ end
+ end
+
+ describe '.allowed?' do
+ it 'returns true when the user can create a pipeline' do
+ project = create(:project)
+
+ expect(described_class.allowed?(project, project.creator)).to eq(true)
+ end
+
+ it 'returns false when the user can not create a pipeline' do
+ project = create(:project)
+ user = create(:user)
+
+ expect(described_class.allowed?(project, user)).to eq(false)
+ end
+ end
+
+ describe '#execute' do
+ let(:chat_name) { create(:chat_name) }
+ let(:project) { create(:project) }
+
+ let(:command) do
+ described_class.new(project, chat_name, response_url: 'http://example.com')
+ end
+
+ context 'when a pipeline could not be scheduled' do
+ it 'returns an error' do
+ expect_any_instance_of(Gitlab::Chat::Command)
+ .to receive(:try_create_pipeline)
+ .and_return(nil)
+
+ expect_any_instance_of(Gitlab::SlashCommands::Presenters::Run)
+ .to receive(:failed_to_schedule)
+ .with('foo')
+
+ command.execute(command: 'foo', arguments: '')
+ end
+ end
+
+ context 'when a pipeline could be created but the chat service was not supported' do
+ it 'returns an error' do
+ build = double(:build)
+ pipeline = double(
+ :pipeline,
+ builds: double(:relation, take: build),
+ persisted?: true
+ )
+
+ expect_any_instance_of(Gitlab::Chat::Command)
+ .to receive(:try_create_pipeline)
+ .and_return(pipeline)
+
+ expect(Gitlab::Chat::Responder)
+ .to receive(:responder_for)
+ .with(build)
+ .and_return(nil)
+
+ expect_any_instance_of(Gitlab::SlashCommands::Presenters::Run)
+ .to receive(:unsupported_chat_service)
+
+ command.execute(command: 'foo', arguments: '')
+ end
+ end
+
+ context 'using a valid pipeline' do
+ it 'schedules the pipeline' do
+ responder = double(:responder, scheduled_output: 'hello')
+ build = double(:build)
+ pipeline = double(
+ :pipeline,
+ builds: double(:relation, take: build),
+ persisted?: true
+ )
+
+ expect_any_instance_of(Gitlab::Chat::Command)
+ .to receive(:try_create_pipeline)
+ .and_return(pipeline)
+
+ expect(Gitlab::Chat::Responder)
+ .to receive(:responder_for)
+ .with(build)
+ .and_return(responder)
+
+ expect_any_instance_of(Gitlab::SlashCommands::Presenters::Run)
+ .to receive(:in_channel_response)
+ .with(responder.scheduled_output)
+
+ command.execute(command: 'foo', arguments: '')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sql/recursive_cte_spec.rb b/spec/lib/gitlab/sql/recursive_cte_spec.rb
index 25146860615..7fe39dd5a96 100644
--- a/spec/lib/gitlab/sql/recursive_cte_spec.rb
+++ b/spec/lib/gitlab/sql/recursive_cte_spec.rb
@@ -31,6 +31,15 @@ describe Gitlab::SQL::RecursiveCTE, :postgresql do
expect(cte.alias_to(table).to_sql).to eq("#{source_name} AS #{alias_name}")
end
+
+ it 'replaces dots with an underscore' do
+ table = Arel::Table.new('gitlab.kittens')
+
+ source_name = ActiveRecord::Base.connection.quote_table_name(:cte_name)
+ alias_name = ActiveRecord::Base.connection.quote_table_name(:gitlab_kittens)
+
+ expect(cte.alias_to(table).to_sql).to eq("#{source_name} AS #{alias_name}")
+ end
end
describe '#apply_to' do
diff --git a/spec/lib/gitlab/tracing/factory_spec.rb b/spec/lib/gitlab/tracing/factory_spec.rb
new file mode 100644
index 00000000000..945490f0988
--- /dev/null
+++ b/spec/lib/gitlab/tracing/factory_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::Tracing::Factory do
+ describe '.create_tracer' do
+ let(:service_name) { 'rspec' }
+
+ context "when tracing is not configured" do
+ it 'ignores null connection strings' do
+ expect(described_class.create_tracer(service_name, nil)).to be_nil
+ end
+
+ it 'ignores empty connection strings' do
+ expect(described_class.create_tracer(service_name, '')).to be_nil
+ end
+
+ it 'ignores unknown implementations' do
+ expect(described_class.create_tracer(service_name, 'opentracing://invalid_driver')).to be_nil
+ end
+
+ it 'ignores invalid connection strings' do
+ expect(described_class.create_tracer(service_name, 'open?tracing')).to be_nil
+ end
+ end
+
+ context "when tracing is configured with jaeger" do
+ let(:mock_tracer) { double('tracer') }
+
+ it 'processes default connections' do
+ expect(Gitlab::Tracing::JaegerFactory).to receive(:create_tracer).with(service_name, {}).and_return(mock_tracer)
+
+ expect(described_class.create_tracer(service_name, 'opentracing://jaeger')).to be(mock_tracer)
+ end
+
+ it 'processes connections with parameters' do
+ expect(Gitlab::Tracing::JaegerFactory).to receive(:create_tracer).with(service_name, { a: '1', b: '2', c: '3' }).and_return(mock_tracer)
+
+ expect(described_class.create_tracer(service_name, 'opentracing://jaeger?a=1&b=2&c=3')).to be(mock_tracer)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracing/grpc_interceptor_spec.rb b/spec/lib/gitlab/tracing/grpc_interceptor_spec.rb
new file mode 100644
index 00000000000..7f5aecb7baa
--- /dev/null
+++ b/spec/lib/gitlab/tracing/grpc_interceptor_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::Tracing::GRPCInterceptor do
+ subject { described_class.instance }
+
+ shared_examples_for "a grpc interceptor method" do
+ let(:custom_error) { Class.new(StandardError) }
+
+ it 'yields' do
+ expect { |b| method.call(kwargs, &b) }.to yield_control
+ end
+
+ it 'propagates exceptions' do
+ expect { method.call(kwargs) { raise custom_error } }.to raise_error(custom_error)
+ end
+ end
+
+ describe '#request_response' do
+ let(:method) { subject.method(:request_response) }
+ let(:kwargs) { { request: {}, call: {}, method: 'grc_method', metadata: {} } }
+
+ it_behaves_like 'a grpc interceptor method'
+ end
+
+ describe '#client_streamer' do
+ let(:method) { subject.method(:client_streamer) }
+ let(:kwargs) { { requests: [], call: {}, method: 'grc_method', metadata: {} } }
+
+ it_behaves_like 'a grpc interceptor method'
+ end
+
+ describe '#server_streamer' do
+ let(:method) { subject.method(:server_streamer) }
+ let(:kwargs) { { request: {}, call: {}, method: 'grc_method', metadata: {} } }
+
+ it_behaves_like 'a grpc interceptor method'
+ end
+
+ describe '#bidi_streamer' do
+ let(:method) { subject.method(:bidi_streamer) }
+ let(:kwargs) { { requests: [], call: {}, method: 'grc_method', metadata: {} } }
+
+ it_behaves_like 'a grpc interceptor method'
+ end
+end
diff --git a/spec/lib/gitlab/tracing/jaeger_factory_spec.rb b/spec/lib/gitlab/tracing/jaeger_factory_spec.rb
new file mode 100644
index 00000000000..3d6a007cfd9
--- /dev/null
+++ b/spec/lib/gitlab/tracing/jaeger_factory_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::Tracing::JaegerFactory do
+ describe '.create_tracer' do
+ let(:service_name) { 'rspec' }
+
+ shared_examples_for 'a jaeger tracer' do
+ it 'responds to active_span methods' do
+ expect(tracer).to respond_to(:active_span)
+ end
+
+ it 'yields control' do
+ expect { |b| tracer.start_active_span('operation_name', &b) }.to yield_control
+ end
+ end
+
+ context 'processes default connections' do
+ it_behaves_like 'a jaeger tracer' do
+ let(:tracer) { described_class.create_tracer(service_name, {}) }
+ end
+ end
+
+ context 'handles debug options' do
+ it_behaves_like 'a jaeger tracer' do
+ let(:tracer) { described_class.create_tracer(service_name, { debug: "1" }) }
+ end
+ end
+
+ context 'handles const sampler' do
+ it_behaves_like 'a jaeger tracer' do
+ let(:tracer) { described_class.create_tracer(service_name, { sampler: "const", sampler_param: "1" }) }
+ end
+ end
+
+ context 'handles probabilistic sampler' do
+ it_behaves_like 'a jaeger tracer' do
+ let(:tracer) { described_class.create_tracer(service_name, { sampler: "probabilistic", sampler_param: "0.5" }) }
+ end
+ end
+
+ context 'handles http_endpoint configurations' do
+ it_behaves_like 'a jaeger tracer' do
+ let(:tracer) { described_class.create_tracer(service_name, { http_endpoint: "http://localhost:1234" }) }
+ end
+ end
+
+ context 'handles udp_endpoint configurations' do
+ it_behaves_like 'a jaeger tracer' do
+ let(:tracer) { described_class.create_tracer(service_name, { udp_endpoint: "localhost:4321" }) }
+ end
+ end
+
+ context 'ignores invalid parameters' do
+ it_behaves_like 'a jaeger tracer' do
+ let(:tracer) { described_class.create_tracer(service_name, { invalid: "true" }) }
+ end
+ end
+
+ context 'accepts the debug parameter when strict_parser is set' do
+ it_behaves_like 'a jaeger tracer' do
+ let(:tracer) { described_class.create_tracer(service_name, { debug: "1", strict_parsing: "1" }) }
+ end
+ end
+
+ it 'rejects invalid parameters when strict_parser is set' do
+ expect { described_class.create_tracer(service_name, { invalid: "true", strict_parsing: "1" }) }.to raise_error(StandardError)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracing/rack_middleware_spec.rb b/spec/lib/gitlab/tracing/rack_middleware_spec.rb
new file mode 100644
index 00000000000..13d4d8a89f7
--- /dev/null
+++ b/spec/lib/gitlab/tracing/rack_middleware_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Tracing::RackMiddleware do
+ using RSpec::Parameterized::TableSyntax
+
+ describe '#call' do
+ context 'for normal middleware flow' do
+ let(:fake_app) { -> (env) { fake_app_response } }
+ subject { described_class.new(fake_app) }
+ let(:request) { }
+
+ context 'for 200 responses' do
+ let(:fake_app_response) { [200, { 'Content-Type': 'text/plain' }, ['OK']] }
+
+ it 'delegates correctly' do
+ expect(subject.call(Rack::MockRequest.env_for("/"))).to eq(fake_app_response)
+ end
+ end
+
+ context 'for 500 responses' do
+ let(:fake_app_response) { [500, { 'Content-Type': 'text/plain' }, ['Error']] }
+
+ it 'delegates correctly' do
+ expect(subject.call(Rack::MockRequest.env_for("/"))).to eq(fake_app_response)
+ end
+ end
+ end
+
+ context 'when an application is raising an exception' do
+ let(:custom_error) { Class.new(StandardError) }
+ let(:fake_app) { ->(env) { raise custom_error } }
+
+ subject { described_class.new(fake_app) }
+
+ it 'delegates propagates exceptions correctly' do
+ expect { subject.call(Rack::MockRequest.env_for("/")) }.to raise_error(custom_error)
+ end
+ end
+ end
+
+ describe '.build_sanitized_url_from_env' do
+ def env_for_url(url)
+ env = Rack::MockRequest.env_for(input_url)
+ env['action_dispatch.parameter_filter'] = [/token/]
+
+ env
+ end
+
+ where(:input_url, :output_url) do
+ '/gitlab-org/gitlab-ce' | 'http://example.org/gitlab-org/gitlab-ce'
+ '/gitlab-org/gitlab-ce?safe=1' | 'http://example.org/gitlab-org/gitlab-ce?safe=1'
+ '/gitlab-org/gitlab-ce?private_token=secret' | 'http://example.org/gitlab-org/gitlab-ce?private_token=%5BFILTERED%5D'
+ '/gitlab-org/gitlab-ce?mixed=1&private_token=secret' | 'http://example.org/gitlab-org/gitlab-ce?mixed=1&private_token=%5BFILTERED%5D'
+ end
+
+ with_them do
+ it { expect(described_class.build_sanitized_url_from_env(env_for_url(input_url))).to eq(output_url) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb b/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb
new file mode 100644
index 00000000000..c9d1a06b3e6
--- /dev/null
+++ b/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+describe Gitlab::Tracing::Rails::ActionViewSubscriber do
+ using RSpec::Parameterized::TableSyntax
+
+ shared_examples 'an actionview notification' do
+ it 'should notify the tracer when the hash contains null values' do
+ expect(subject).to receive(:postnotify_span).with(notification_name, start, finish, tags: expected_tags, exception: exception)
+
+ subject.public_send(notify_method, start, finish, payload)
+ end
+
+ it 'should notify the tracer when the payload is missing values' do
+ expect(subject).to receive(:postnotify_span).with(notification_name, start, finish, tags: expected_tags, exception: exception)
+
+ subject.public_send(notify_method, start, finish, payload.compact)
+ end
+
+ it 'should not throw exceptions when with the default tracer' do
+ expect { subject.public_send(notify_method, start, finish, payload) }.not_to raise_error
+ end
+ end
+
+ describe '.instrument' do
+ it 'is unsubscribeable' do
+ unsubscribe = described_class.instrument
+
+ expect(unsubscribe).not_to be_nil
+ expect { unsubscribe.call }.not_to raise_error
+ end
+ end
+
+ describe '#notify_render_template' do
+ subject { described_class.new }
+ let(:start) { Time.now }
+ let(:finish) { Time.now }
+ let(:notification_name) { 'render_template' }
+ let(:notify_method) { :notify_render_template }
+
+ where(:identifier, :layout, :exception) do
+ nil | nil | nil
+ "" | nil | nil
+ "show.haml" | nil | nil
+ nil | "" | nil
+ nil | "layout.haml" | nil
+ nil | nil | StandardError.new
+ end
+
+ with_them do
+ let(:payload) do
+ {
+ exception: exception,
+ identifier: identifier,
+ layout: layout
+ }
+ end
+
+ let(:expected_tags) do
+ {
+ 'component' => 'ActionView',
+ 'template.id' => identifier,
+ 'template.layout' => layout
+ }
+ end
+
+ it_behaves_like 'an actionview notification'
+ end
+ end
+
+ describe '#notify_render_collection' do
+ subject { described_class.new }
+ let(:start) { Time.now }
+ let(:finish) { Time.now }
+ let(:notification_name) { 'render_collection' }
+ let(:notify_method) { :notify_render_collection }
+
+ where(
+ :identifier, :count, :expected_count, :cache_hits, :expected_cache_hits, :exception) do
+ nil | nil | 0 | nil | 0 | nil
+ "" | nil | 0 | nil | 0 | nil
+ "show.haml" | nil | 0 | nil | 0 | nil
+ nil | 0 | 0 | nil | 0 | nil
+ nil | 1 | 1 | nil | 0 | nil
+ nil | nil | 0 | 0 | 0 | nil
+ nil | nil | 0 | 1 | 1 | nil
+ nil | nil | 0 | nil | 0 | StandardError.new
+ end
+
+ with_them do
+ let(:payload) do
+ {
+ exception: exception,
+ identifier: identifier,
+ count: count,
+ cache_hits: cache_hits
+ }
+ end
+
+ let(:expected_tags) do
+ {
+ 'component' => 'ActionView',
+ 'template.id' => identifier,
+ 'template.count' => expected_count,
+ 'template.cache.hits' => expected_cache_hits
+ }
+ end
+
+ it_behaves_like 'an actionview notification'
+ end
+ end
+
+ describe '#notify_render_partial' do
+ subject { described_class.new }
+ let(:start) { Time.now }
+ let(:finish) { Time.now }
+ let(:notification_name) { 'render_partial' }
+ let(:notify_method) { :notify_render_partial }
+
+ where(:identifier, :exception) do
+ nil | nil
+ "" | nil
+ "show.haml" | nil
+ nil | StandardError.new
+ end
+
+ with_them do
+ let(:payload) do
+ {
+ exception: exception,
+ identifier: identifier
+ }
+ end
+
+ let(:expected_tags) do
+ {
+ 'component' => 'ActionView',
+ 'template.id' => identifier
+ }
+ end
+
+ it_behaves_like 'an actionview notification'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb b/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb
new file mode 100644
index 00000000000..3d066843148
--- /dev/null
+++ b/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+describe Gitlab::Tracing::Rails::ActiveRecordSubscriber do
+ using RSpec::Parameterized::TableSyntax
+
+ describe '.instrument' do
+ it 'is unsubscribeable' do
+ unsubscribe = described_class.instrument
+
+ expect(unsubscribe).not_to be_nil
+ expect { unsubscribe.call }.not_to raise_error
+ end
+ end
+
+ describe '#notify' do
+ subject { described_class.new }
+ let(:start) { Time.now }
+ let(:finish) { Time.now }
+
+ where(:name, :operation_name, :exception, :connection_id, :cached, :cached_response, :sql) do
+ nil | "active_record:sqlquery" | nil | nil | nil | false | nil
+ "" | "active_record:sqlquery" | nil | nil | nil | false | nil
+ "User Load" | "active_record:User Load" | nil | nil | nil | false | nil
+ "Repo Load" | "active_record:Repo Load" | StandardError.new | nil | nil | false | nil
+ nil | "active_record:sqlquery" | nil | 123 | nil | false | nil
+ nil | "active_record:sqlquery" | nil | nil | false | false | nil
+ nil | "active_record:sqlquery" | nil | nil | true | true | nil
+ nil | "active_record:sqlquery" | nil | nil | true | true | "SELECT * FROM users"
+ end
+
+ with_them do
+ def payload
+ {
+ name: name,
+ exception: exception,
+ connection_id: connection_id,
+ cached: cached,
+ sql: sql
+ }
+ end
+
+ def expected_tags
+ {
+ "component" => "ActiveRecord",
+ "span.kind" => "client",
+ "db.type" => "sql",
+ "db.connection_id" => connection_id,
+ "db.cached" => cached_response,
+ "db.statement" => sql
+ }
+ end
+
+ it 'should notify the tracer when the hash contains null values' do
+ expect(subject).to receive(:postnotify_span).with(operation_name, start, finish, tags: expected_tags, exception: exception)
+
+ subject.notify(start, finish, payload)
+ end
+
+ it 'should notify the tracer when the payload is missing values' do
+ expect(subject).to receive(:postnotify_span).with(operation_name, start, finish, tags: expected_tags, exception: exception)
+
+ subject.notify(start, finish, payload.compact)
+ end
+
+ it 'should not throw exceptions when with the default tracer' do
+ expect { subject.notify(start, finish, payload) }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb b/spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb
new file mode 100644
index 00000000000..3755860b5ba
--- /dev/null
+++ b/spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::Tracing::Sidekiq::ClientMiddleware do
+ describe '#call' do
+ let(:worker_class) { 'test_worker_class' }
+ let(:job) do
+ {
+ 'class' => "jobclass",
+ 'queue' => "jobqueue",
+ 'retry' => 0,
+ 'args' => %w{1 2 3}
+ }
+ end
+ let(:queue) { 'test_queue' }
+ let(:redis_pool) { double("redis_pool") }
+ let(:custom_error) { Class.new(StandardError) }
+ let(:span) { OpenTracing.start_span('test', ignore_active_scope: true) }
+
+ subject { described_class.new }
+
+ it 'yields' do
+ expect(subject).to receive(:in_tracing_span).with(
+ operation_name: "sidekiq:jobclass",
+ tags: {
+ "component" => "sidekiq",
+ "span.kind" => "client",
+ "sidekiq.queue" => "jobqueue",
+ "sidekiq.jid" => nil,
+ "sidekiq.retry" => "0",
+ "sidekiq.args" => "1, 2, 3"
+ }
+ ).and_yield(span)
+
+ expect { |b| subject.call(worker_class, job, queue, redis_pool, &b) }.to yield_control
+ end
+
+ it 'propagates exceptions' do
+ expect { subject.call(worker_class, job, queue, redis_pool) { raise custom_error } }.to raise_error(custom_error)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb b/spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb
new file mode 100644
index 00000000000..c3087de785a
--- /dev/null
+++ b/spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::Tracing::Sidekiq::ServerMiddleware do
+ describe '#call' do
+ let(:worker_class) { 'test_worker_class' }
+ let(:job) do
+ {
+ 'class' => "jobclass",
+ 'queue' => "jobqueue",
+ 'retry' => 0,
+ 'args' => %w{1 2 3}
+ }
+ end
+ let(:queue) { 'test_queue' }
+ let(:custom_error) { Class.new(StandardError) }
+ let(:span) { OpenTracing.start_span('test', ignore_active_scope: true) }
+ subject { described_class.new }
+
+ it 'yields' do
+ expect(subject).to receive(:in_tracing_span).with(
+ hash_including(
+ operation_name: "sidekiq:jobclass",
+ tags: {
+ "component" => "sidekiq",
+ "span.kind" => "server",
+ "sidekiq.queue" => "jobqueue",
+ "sidekiq.jid" => nil,
+ "sidekiq.retry" => "0",
+ "sidekiq.args" => "1, 2, 3"
+ }
+ )
+ ).and_yield(span)
+
+ expect { |b| subject.call(worker_class, job, queue, &b) }.to yield_control
+ end
+
+ it 'propagates exceptions' do
+ expect { subject.call(worker_class, job, queue) { raise custom_error } }.to raise_error(custom_error)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracing_spec.rb b/spec/lib/gitlab/tracing_spec.rb
new file mode 100644
index 00000000000..566b5050e47
--- /dev/null
+++ b/spec/lib/gitlab/tracing_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+describe Gitlab::Tracing do
+ using RSpec::Parameterized::TableSyntax
+
+ describe '.enabled?' do
+ where(:connection_string, :enabled_state) do
+ nil | false
+ "" | false
+ "opentracing://jaeger" | true
+ end
+
+ with_them do
+ it 'should return the correct state for .enabled?' do
+ expect(described_class).to receive(:connection_string).and_return(connection_string)
+
+ expect(described_class.enabled?).to eq(enabled_state)
+ end
+ end
+ end
+
+ describe '.tracing_url_enabled?' do
+ where(:enabled?, :tracing_url_template, :tracing_url_enabled_state) do
+ false | nil | false
+ false | "" | false
+ false | "http://localhost" | false
+ true | nil | false
+ true | "" | false
+ true | "http://localhost" | true
+ end
+
+ with_them do
+ it 'should return the correct state for .tracing_url_enabled?' do
+ expect(described_class).to receive(:enabled?).and_return(enabled?)
+ allow(described_class).to receive(:tracing_url_template).and_return(tracing_url_template)
+
+ expect(described_class.tracing_url_enabled?).to eq(tracing_url_enabled_state)
+ end
+ end
+ end
+
+ describe '.tracing_url' do
+ where(:tracing_url_enabled?, :tracing_url_template, :correlation_id, :process_name, :tracing_url) do
+ false | "https://localhost" | "123" | "web" | nil
+ true | "https://localhost" | "123" | "web" | "https://localhost"
+ true | "https://localhost?service={{ service }}" | "123" | "web" | "https://localhost?service=web"
+ true | "https://localhost?c={{ correlation_id }}" | "123" | "web" | "https://localhost?c=123"
+ true | "https://localhost?c={{ correlation_id }}&s={{ service }}" | "123" | "web" | "https://localhost?c=123&s=web"
+ true | "https://localhost?c={{ correlation_id }}" | nil | "web" | "https://localhost?c="
+ true | "https://localhost?c={{ correlation_id }}&s=%22{{ service }}%22" | "123" | "web" | "https://localhost?c=123&s=%22web%22"
+ true | "https://localhost?c={{correlation_id}}&s={{service}}" | "123" | "web" | "https://localhost?c=123&s=web"
+ true | "https://localhost?c={{correlation_id }}&s={{ service}}" | "123" | "web" | "https://localhost?c=123&s=web"
+ end
+
+ with_them do
+ it 'should return the correct state for .tracing_url' do
+ expect(described_class).to receive(:tracing_url_enabled?).and_return(tracing_url_enabled?)
+ allow(described_class).to receive(:tracing_url_template).and_return(tracing_url_template)
+ allow(Gitlab::CorrelationId).to receive(:current_id).and_return(correlation_id)
+ allow(Gitlab).to receive(:process_name).and_return(process_name)
+
+ expect(described_class.tracing_url).to eq(tracing_url)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tree_summary_spec.rb b/spec/lib/gitlab/tree_summary_spec.rb
index 7ffcef2baef..e22f898dc4c 100644
--- a/spec/lib/gitlab/tree_summary_spec.rb
+++ b/spec/lib/gitlab/tree_summary_spec.rb
@@ -180,7 +180,7 @@ describe Gitlab::TreeSummary do
with_them do
before do
- create_file('dummy', path: 'other') if num_entries.zero?
+ create_file('dummy', path: 'other') if num_entries.zero?
1.upto(num_entries) { |n| create_file(n, path: path) }
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 2a09f581f68..d3eae80cc56 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -26,6 +26,8 @@ describe Gitlab::UsageData do
create(:clusters_applications_prometheus, :installed, cluster: gcp_cluster)
create(:clusters_applications_runner, :installed, cluster: gcp_cluster)
create(:clusters_applications_knative, :installed, cluster: gcp_cluster)
+
+ ProjectFeature.first.update_attribute('repository_access_level', 0)
end
subject { described_class.data }
@@ -112,6 +114,7 @@ describe Gitlab::UsageData do
projects_slack_notifications_active
projects_slack_slash_active
projects_prometheus_active
+ projects_with_repositories_enabled
pages_domains
protected_branches
releases
@@ -121,9 +124,15 @@ describe Gitlab::UsageData do
todos
uploads
web_hooks
+ user_preferences
))
end
+ it 'does not gather user preferences usage data when the feature is disabled' do
+ stub_feature_flags(group_overview_security_dashboard: false)
+ expect(subject[:counts].keys).not_to include(:user_preferences)
+ end
+
it 'gathers projects data correctly' do
count_data = subject[:counts]
@@ -134,6 +143,7 @@ describe Gitlab::UsageData do
expect(count_data[:projects_jira_cloud_active]).to eq(1)
expect(count_data[:projects_slack_notifications_active]).to eq(2)
expect(count_data[:projects_slack_slash_active]).to eq(1)
+ expect(count_data[:projects_with_repositories_enabled]).to eq(2)
expect(count_data[:clusters_enabled]).to eq(7)
expect(count_data[:project_clusters_enabled]).to eq(6)
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index f5a4b7e2ebf..8f5029b3565 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -197,4 +197,20 @@ describe Gitlab::Utils do
end
end
end
+
+ describe '.deep_indifferent_access' do
+ let(:hash) do
+ { "variables" => [{ "key" => "VAR1", "value" => "VALUE2" }] }
+ end
+
+ subject { described_class.deep_indifferent_access(hash) }
+
+ it 'allows to access hash keys with symbols' do
+ expect(subject[:variables]).to be_a(Array)
+ end
+
+ it 'allows to access array keys with symbols' do
+ expect(subject[:variables].first[:key]).to eq('VAR1')
+ end
+ end
end
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index d63f448883b..8232715d00e 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -8,6 +8,7 @@ describe Gitlab do
expect(described_class.root).to eq(Pathname.new(File.expand_path('../..', __dir__)))
end
end
+
describe '.revision' do
let(:cmd) { %W[#{described_class.config.git.bin_path} log --pretty=format:%h -n 1] }
@@ -94,4 +95,18 @@ describe Gitlab do
expect(described_class.com?).to eq false
end
end
+
+ describe '.ee?' do
+ it 'returns true when using Enterprise Edition' do
+ stub_const('License', Class.new)
+
+ expect(described_class.ee?).to eq(true)
+ end
+
+ it 'returns false when using Community Edition' do
+ hide_const('License')
+
+ expect(described_class.ee?).to eq(false)
+ 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 d6edc964844..a3c54651e80 100644
--- a/spec/lib/json_web_token/rsa_token_spec.rb
+++ b/spec/lib/json_web_token/rsa_token_spec.rb
@@ -25,7 +25,7 @@ describe JSONWebToken::RSAToken do
rsa_token['key'] = 'value'
end
- subject { JWT.decode(rsa_encoded, rsa_key) }
+ subject { JWT.decode(rsa_encoded, rsa_key, true, { algorithm: 'RS256' }) }
it { expect {subject}.not_to raise_error }
it { expect(subject.first).to include('key' => 'value') }
@@ -39,7 +39,7 @@ describe JSONWebToken::RSAToken do
context 'for invalid key to raise an exception' do
let(:new_key) { OpenSSL::PKey::RSA.generate(512) }
- subject { JWT.decode(rsa_encoded, new_key) }
+ subject { JWT.decode(rsa_encoded, new_key, true, { algorithm: 'RS256' }) }
it { expect {subject}.to raise_error(JWT::DecodeError) }
end
diff --git a/spec/lib/object_storage/direct_upload_spec.rb b/spec/lib/object_storage/direct_upload_spec.rb
index 1024e1a25ea..8ccbd90ddb8 100644
--- a/spec/lib/object_storage/direct_upload_spec.rb
+++ b/spec/lib/object_storage/direct_upload_spec.rb
@@ -121,7 +121,7 @@ describe ObjectStorage::DirectUpload do
expect(subject[:MultipartUpload][:PartURLs].length).to eq(2)
end
- it 'part size is mimimum, 5MB' do
+ it 'part size is minimum, 5MB' do
expect(subject[:MultipartUpload][:PartSize]).to eq(5.megabyte)
end
end
diff --git a/spec/lib/omni_auth/strategies/jwt_spec.rb b/spec/lib/omni_auth/strategies/jwt_spec.rb
index c2e2db27362..c1eaf0bb0bf 100644
--- a/spec/lib/omni_auth/strategies/jwt_spec.rb
+++ b/spec/lib/omni_auth/strategies/jwt_spec.rb
@@ -25,6 +25,8 @@ describe OmniAuth::Strategies::Jwt do
subject.options[:secret] = secret
subject.options[:algorithm] = algorithm
+ # We use Rack::Request instead of ActionDispatch::Request because
+ # Rack::Test::Methods enables testing of this module.
expect_next_instance_of(Rack::Request) do |rack_request|
expect(rack_request).to receive(:params).and_return('jwt' => payload)
end
diff --git a/spec/lib/safe_zip/entry_spec.rb b/spec/lib/safe_zip/entry_spec.rb
new file mode 100644
index 00000000000..115e28c5994
--- /dev/null
+++ b/spec/lib/safe_zip/entry_spec.rb
@@ -0,0 +1,196 @@
+require 'spec_helper'
+
+describe SafeZip::Entry do
+ let(:target_path) { Dir.mktmpdir('safe-zip') }
+ let(:directories) { %w(public folder/with/subfolder) }
+ let(:params) { SafeZip::ExtractParams.new(directories: directories, to: target_path) }
+
+ let(:entry) { described_class.new(zip_archive, zip_entry, params) }
+ let(:entry_name) { 'public/folder/index.html' }
+ let(:entry_path_dir) { File.join(target_path, File.dirname(entry_name)) }
+ let(:entry_path) { File.join(target_path, entry_name) }
+ let(:zip_archive) { double }
+
+ let(:zip_entry) do
+ double(
+ name: entry_name,
+ file?: false,
+ directory?: false,
+ symlink?: false)
+ end
+
+ after do
+ FileUtils.remove_entry_secure(target_path)
+ end
+
+ context '#path_dir' do
+ subject { entry.path_dir }
+
+ it { is_expected.to eq(target_path + '/public/folder') }
+ end
+
+ context '#exist?' do
+ subject { entry.exist? }
+
+ context 'when entry does not exist' do
+ it { is_expected.not_to be_truthy }
+ end
+
+ context 'when entry does exist' do
+ before do
+ create_entry
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe '#extract' do
+ subject { entry.extract }
+
+ context 'when entry does not match the filtered directories' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:entry_name) do
+ [
+ 'assets/folder/index.html',
+ 'public/../folder/index.html',
+ 'public/../../../../../index.html',
+ '../../../../../public/index.html',
+ '/etc/passwd'
+ ]
+ end
+
+ with_them do
+ it 'does not extract file' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+
+ context 'when entry does exist' do
+ before do
+ create_entry
+ end
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(SafeZip::Extract::AlreadyExistsError)
+ end
+ end
+
+ context 'when entry type is unknown' do
+ it 'raises an exception' do
+ expect { subject }.to raise_error(SafeZip::Extract::UnsupportedEntryError)
+ end
+ end
+
+ context 'when entry is valid' do
+ shared_examples 'secured symlinks' do
+ context 'when we try to extract entry into symlinked folder' do
+ before do
+ FileUtils.mkdir_p(File.join(target_path, "source"))
+ File.symlink("source", File.join(target_path, "public"))
+ end
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(SafeZip::Extract::PermissionDeniedError)
+ end
+ end
+ end
+
+ context 'and is file' do
+ before do
+ allow(zip_entry).to receive(:file?) { true }
+ end
+
+ it 'does extract file' do
+ expect(zip_archive).to receive(:extract)
+ .with(zip_entry, entry_path)
+ .and_return(true)
+
+ is_expected.to be_truthy
+ end
+
+ it_behaves_like 'secured symlinks'
+ end
+
+ context 'and is directory' do
+ let(:entry_name) { 'public/folder/assets' }
+
+ before do
+ allow(zip_entry).to receive(:directory?) { true }
+ end
+
+ it 'does create directory' do
+ is_expected.to be_truthy
+
+ expect(File.exist?(entry_path)).to eq(true)
+ end
+
+ it_behaves_like 'secured symlinks'
+ end
+
+ context 'and is symlink' do
+ let(:entry_name) { 'public/folder/assets' }
+
+ before do
+ allow(zip_entry).to receive(:symlink?) { true }
+ allow(zip_archive).to receive(:read).with(zip_entry) { entry_symlink }
+ end
+
+ shared_examples 'a valid symlink' do
+ it 'does create symlink' do
+ is_expected.to be_truthy
+
+ expect(File.exist?(entry_path)).to eq(true)
+ end
+ end
+
+ context 'when source is within target' do
+ let(:entry_symlink) { '../images' }
+
+ context 'but does not exist' do
+ it 'raises an exception' do
+ expect { subject }.to raise_error(SafeZip::Extract::SymlinkSourceDoesNotExistError)
+ end
+ end
+
+ context 'and does exist' do
+ before do
+ FileUtils.mkdir_p(File.join(target_path, 'public', 'images'))
+ end
+
+ it_behaves_like 'a valid symlink'
+ end
+ end
+
+ context 'when source points outside of target' do
+ let(:entry_symlink) { '../../images' }
+
+ before do
+ FileUtils.mkdir(File.join(target_path, 'images'))
+ end
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(SafeZip::Extract::PermissionDeniedError)
+ end
+ end
+
+ context 'when source points to /etc/passwd' do
+ let(:entry_symlink) { '/etc/passwd' }
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(SafeZip::Extract::PermissionDeniedError)
+ end
+ end
+ end
+ end
+ end
+
+ private
+
+ def create_entry
+ FileUtils.mkdir_p(entry_path_dir)
+ FileUtils.touch(entry_path)
+ end
+end
diff --git a/spec/lib/safe_zip/extract_params_spec.rb b/spec/lib/safe_zip/extract_params_spec.rb
new file mode 100644
index 00000000000..85e22cfa495
--- /dev/null
+++ b/spec/lib/safe_zip/extract_params_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe SafeZip::ExtractParams do
+ let(:target_path) { Dir.mktmpdir("safe-zip") }
+ let(:params) { described_class.new(directories: directories, to: target_path) }
+ let(:directories) { %w(public folder/with/subfolder) }
+
+ after do
+ FileUtils.remove_entry_secure(target_path)
+ end
+
+ describe '#extract_path' do
+ subject { params.extract_path }
+
+ it { is_expected.to eq(target_path) }
+ end
+
+ describe '#matching_target_directory' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { params.matching_target_directory(target_path + path) }
+
+ where(:path, :result) do
+ '/public/index.html' | '/public/'
+ '/non/existing/path' | nil
+ '/public' | nil
+ '/folder/with/index.html' | nil
+ end
+
+ with_them do
+ it { is_expected.to eq(result ? target_path + result : nil) }
+ end
+ end
+
+ describe '#target_directories' do
+ subject { params.target_directories }
+
+ it 'starts with target_path' do
+ is_expected.to all(start_with(target_path + '/'))
+ end
+
+ it 'ends with / for all paths' do
+ is_expected.to all(end_with('/'))
+ end
+ end
+
+ describe '#directories_wildcard' do
+ subject { params.directories_wildcard }
+
+ it 'adds * for all paths' do
+ is_expected.to all(end_with('/*'))
+ end
+ end
+end
diff --git a/spec/lib/safe_zip/extract_spec.rb b/spec/lib/safe_zip/extract_spec.rb
new file mode 100644
index 00000000000..b75a8fede00
--- /dev/null
+++ b/spec/lib/safe_zip/extract_spec.rb
@@ -0,0 +1,80 @@
+require 'spec_helper'
+
+describe SafeZip::Extract do
+ let(:target_path) { Dir.mktmpdir('safe-zip') }
+ let(:directories) { %w(public) }
+ let(:object) { described_class.new(archive) }
+ let(:archive) { Rails.root.join('spec', 'fixtures', 'safe_zip', archive_name) }
+
+ after do
+ FileUtils.remove_entry_secure(target_path)
+ end
+
+ context '#extract' do
+ subject { object.extract(directories: directories, to: target_path) }
+
+ shared_examples 'extracts archive' do |param|
+ before do
+ stub_feature_flags(safezip_use_rubyzip: param)
+ end
+
+ it 'does extract archive' do
+ subject
+
+ expect(File.exist?(File.join(target_path, 'public', 'index.html'))).to eq(true)
+ expect(File.exist?(File.join(target_path, 'source'))).to eq(false)
+ end
+ end
+
+ shared_examples 'fails to extract archive' do |param|
+ before do
+ stub_feature_flags(safezip_use_rubyzip: param)
+ end
+
+ it 'does not extract archive' do
+ expect { subject }.to raise_error(SafeZip::Extract::Error)
+ end
+ end
+
+ %w(valid-simple.zip valid-symlinks-first.zip valid-non-writeable.zip).each do |name|
+ context "when using #{name} archive" do
+ let(:archive_name) { name }
+
+ context 'for RubyZip' do
+ it_behaves_like 'extracts archive', true
+ end
+
+ context 'for UnZip' do
+ it_behaves_like 'extracts archive', false
+ end
+ end
+ end
+
+ %w(invalid-symlink-does-not-exist.zip invalid-symlinks-outside.zip).each do |name|
+ context "when using #{name} archive" do
+ let(:archive_name) { name }
+
+ context 'for RubyZip' do
+ it_behaves_like 'fails to extract archive', true
+ end
+
+ context 'for UnZip (UNSAFE)' do
+ it_behaves_like 'extracts archive', false
+ end
+ end
+ end
+
+ context 'when no matching directories are found' do
+ let(:archive_name) { 'valid-simple.zip' }
+ let(:directories) { %w(non/existing) }
+
+ context 'for RubyZip' do
+ it_behaves_like 'fails to extract archive', true
+ end
+
+ context 'for UnZip' do
+ it_behaves_like 'fails to extract archive', false
+ end
+ end
+ end
+end
diff --git a/spec/lib/sentry/client_spec.rb b/spec/lib/sentry/client_spec.rb
new file mode 100644
index 00000000000..88e7e2e5ebb
--- /dev/null
+++ b/spec/lib/sentry/client_spec.rb
@@ -0,0 +1,218 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Sentry::Client do
+ let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
+ let(:token) { 'test-token' }
+
+ let(:issues_sample_response) do
+ Gitlab::Utils.deep_indifferent_access(
+ JSON.parse(fixture_file('sentry/issues_sample_response.json'))
+ )
+ end
+
+ let(:projects_sample_response) do
+ Gitlab::Utils.deep_indifferent_access(
+ JSON.parse(fixture_file('sentry/list_projects_sample_response.json'))
+ )
+ end
+
+ subject(:client) { described_class.new(sentry_url, token) }
+
+ # Requires sentry_api_url and subject to be defined
+ shared_examples 'no redirects' do
+ let(:redirect_to) { 'https://redirected.example.com' }
+ let(:other_url) { 'https://other.example.org' }
+
+ let!(:redirected_req_stub) { stub_sentry_request(other_url) }
+
+ let!(:redirect_req_stub) do
+ stub_sentry_request(
+ sentry_api_url,
+ status: 302,
+ headers: { location: redirect_to }
+ )
+ end
+
+ it 'does not follow redirects' do
+ expect { subject }.to raise_exception(Sentry::Client::Error, 'Sentry response status code: 302')
+ expect(redirect_req_stub).to have_been_requested
+ expect(redirected_req_stub).not_to have_been_requested
+ end
+ end
+
+ shared_examples 'has correct return type' do |klass|
+ it "returns objects of type #{klass}" do
+ expect(subject).to all( be_a(klass) )
+ end
+ end
+
+ shared_examples 'has correct length' do |length|
+ it { expect(subject.length).to eq(length) }
+ end
+
+ # Requires sentry_api_request and subject to be defined
+ shared_examples 'calls sentry api' do
+ it 'calls sentry api' do
+ subject
+
+ expect(sentry_api_request).to have_been_requested
+ end
+ end
+
+ describe '#list_issues' do
+ let(:issue_status) { 'unresolved' }
+ let(:limit) { 20 }
+
+ let!(:sentry_api_request) { stub_sentry_request(sentry_url + '/issues/?limit=20&query=is:unresolved', body: issues_sample_response) }
+
+ subject { client.list_issues(issue_status: issue_status, limit: limit) }
+
+ it_behaves_like 'calls sentry api'
+
+ it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Error
+ it_behaves_like 'has correct length', 1
+
+ context 'error object created from sentry response' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:error_object, :sentry_response) do
+ :id | :id
+ :first_seen | :firstSeen
+ :last_seen | :lastSeen
+ :title | :title
+ :type | :type
+ :user_count | :userCount
+ :count | :count
+ :message | [:metadata, :value]
+ :culprit | :culprit
+ :short_id | :shortId
+ :status | :status
+ :frequency | [:stats, '24h']
+ :project_id | [:project, :id]
+ :project_name | [:project, :name]
+ :project_slug | [:project, :slug]
+ end
+
+ with_them do
+ it { expect(subject[0].public_send(error_object)).to eq(issues_sample_response[0].dig(*sentry_response)) }
+ end
+
+ context 'external_url' do
+ it 'is constructed correctly' do
+ expect(subject[0].external_url).to eq('https://sentrytest.gitlab.com/sentry-org/sentry-project/issues/11')
+ end
+ end
+ end
+
+ context 'redirects' do
+ let(:sentry_api_url) { sentry_url + '/issues/?limit=20&query=is:unresolved' }
+
+ it_behaves_like 'no redirects'
+ end
+
+ # Sentry API returns 404 if there are extra slashes in the URL!
+ context 'extra slashes in URL' do
+ let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects//sentry-org/sentry-project/' }
+ let(:client) { described_class.new(sentry_url, token) }
+
+ let!(:valid_req_stub) do
+ stub_sentry_request(
+ 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project/' \
+ 'issues/?limit=20&query=is:unresolved'
+ )
+ end
+
+ it 'removes extra slashes in api url' do
+ expect(Gitlab::HTTP).to receive(:get).with(
+ URI('https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project/issues/'),
+ anything
+ ).and_call_original
+
+ subject
+
+ expect(valid_req_stub).to have_been_requested
+ end
+ end
+ end
+
+ describe '#list_projects' do
+ let(:sentry_list_projects_url) { 'https://sentrytest.gitlab.com/api/0/projects/' }
+
+ let!(:sentry_api_request) { stub_sentry_request(sentry_list_projects_url, body: projects_sample_response) }
+
+ subject { client.list_projects }
+
+ it_behaves_like 'calls sentry api'
+
+ it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project
+ it_behaves_like 'has correct length', 2
+
+ context 'keys missing in API response' do
+ it 'raises exception' do
+ projects_sample_response[0].delete(:slug)
+
+ stub_sentry_request(sentry_list_projects_url, body: projects_sample_response)
+
+ expect { subject }.to raise_error(Sentry::Client::SentryError, 'Sentry API response is missing keys. key not found: "slug"')
+ end
+ end
+
+ context 'error object created from sentry response' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:sentry_project_object, :sentry_response) do
+ :id | :id
+ :name | :name
+ :status | :status
+ :slug | :slug
+ :organization_name | [:organization, :name]
+ :organization_id | [:organization, :id]
+ :organization_slug | [:organization, :slug]
+ end
+
+ with_them do
+ it { expect(subject[0].public_send(sentry_project_object)).to eq(projects_sample_response[0].dig(*sentry_response)) }
+ end
+ end
+
+ context 'redirects' do
+ let(:sentry_api_url) { sentry_list_projects_url }
+
+ it_behaves_like 'no redirects'
+ end
+
+ # Sentry API returns 404 if there are extra slashes in the URL!
+ context 'extra slashes in URL' do
+ let(:sentry_url) { 'https://sentrytest.gitlab.com/api//0/projects//' }
+ let(:client) { described_class.new(sentry_url, token) }
+
+ let!(:valid_req_stub) do
+ stub_sentry_request(sentry_list_projects_url)
+ end
+
+ it 'removes extra slashes in api url' do
+ expect(Gitlab::HTTP).to receive(:get).with(
+ URI(sentry_list_projects_url),
+ anything
+ ).and_call_original
+
+ subject
+
+ expect(valid_req_stub).to have_been_requested
+ end
+ end
+ end
+
+ private
+
+ def stub_sentry_request(url, body: {}, status: 200, headers: {})
+ WebMock.stub_request(:get, url)
+ .to_return(
+ status: status,
+ headers: { 'Content-Type' => 'application/json' }.merge(headers),
+ body: body.to_json
+ )
+ end
+end
diff --git a/spec/lib/serializers/json_spec.rb b/spec/lib/serializers/json_spec.rb
new file mode 100644
index 00000000000..5d59d66e8b8
--- /dev/null
+++ b/spec/lib/serializers/json_spec.rb
@@ -0,0 +1,102 @@
+require 'fast_spec_helper'
+
+describe Serializers::JSON do
+ describe '.dump' do
+ let(:obj) { { key: "value" } }
+
+ subject { described_class.dump(obj) }
+
+ context 'when MySQL is used' do
+ before do
+ allow(Gitlab::Database).to receive(:adapter_name) { 'mysql2' }
+ end
+
+ it 'encodes as string' do
+ is_expected.to eq('{"key":"value"}')
+ end
+ end
+
+ context 'when PostgreSQL is used' do
+ before do
+ allow(Gitlab::Database).to receive(:adapter_name) { 'postgresql' }
+ end
+
+ it 'returns a hash' do
+ is_expected.to eq(obj)
+ end
+ end
+ end
+
+ describe '.load' do
+ let(:data_string) { '{"key":"value","variables":[{"key":"VAR1","value":"VALUE1"}]}' }
+ let(:data_hash) { JSON.parse(data_string) }
+
+ shared_examples 'having consistent accessor' do
+ it 'allows to access with symbols' do
+ expect(subject[:key]).to eq('value')
+ expect(subject[:variables].first[:key]).to eq('VAR1')
+ end
+
+ it 'allows to access with strings' do
+ expect(subject["key"]).to eq('value')
+ expect(subject["variables"].first["key"]).to eq('VAR1')
+ end
+ end
+
+ context 'when MySQL is used' do
+ before do
+ allow(Gitlab::Database).to receive(:adapter_name) { 'mysql2' }
+ end
+
+ context 'when loading a string' do
+ subject { described_class.load(data_string) }
+
+ it 'decodes a string' do
+ is_expected.to be_a(Hash)
+ end
+
+ it_behaves_like 'having consistent accessor'
+ end
+
+ context 'when loading a different type' do
+ subject { described_class.load({ key: 'hash' }) }
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(TypeError)
+ end
+ end
+
+ context 'when loading a nil' do
+ subject { described_class.load(nil) }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ context 'when PostgreSQL is used' do
+ before do
+ allow(Gitlab::Database).to receive(:adapter_name) { 'postgresql' }
+ end
+
+ context 'when loading a hash' do
+ subject { described_class.load(data_hash) }
+
+ it 'decodes a string' do
+ is_expected.to be_a(Hash)
+ end
+
+ it_behaves_like 'having consistent accessor'
+ end
+
+ context 'when loading a nil' do
+ subject { described_class.load(nil) }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/mailers/abuse_report_mailer_spec.rb b/spec/mailers/abuse_report_mailer_spec.rb
index bda892083b3..f96870cc112 100644
--- a/spec/mailers/abuse_report_mailer_spec.rb
+++ b/spec/mailers/abuse_report_mailer_spec.rb
@@ -4,25 +4,24 @@ describe AbuseReportMailer do
include EmailSpec::Matchers
describe '.notify' do
- context 'with admin_notification_email set' do
- before do
- stub_application_setting(admin_notification_email: 'admin@example.com')
- end
+ before do
+ stub_application_setting(admin_notification_email: 'admin@example.com')
+ end
- it 'sends to the admin_notification_email' do
- report = create(:abuse_report)
+ let(:report) { create(:abuse_report) }
+
+ subject { described_class.notify(report.id) }
- mail = described_class.notify(report.id)
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
- expect(mail).to deliver_to 'admin@example.com'
+ context 'with admin_notification_email set' do
+ it 'sends to the admin_notification_email' do
+ is_expected.to deliver_to 'admin@example.com'
end
it 'includes the user in the subject' do
- report = create(:abuse_report)
-
- mail = described_class.notify(report.id)
-
- expect(mail).to have_subject "#{report.user.name} (#{report.user.username}) was reported for abuse"
+ is_expected.to have_subject "#{report.user.name} (#{report.user.username}) was reported for abuse"
end
end
diff --git a/spec/mailers/email_rejection_mailer_spec.rb b/spec/mailers/email_rejection_mailer_spec.rb
new file mode 100644
index 00000000000..bbe0a50ae8e
--- /dev/null
+++ b/spec/mailers/email_rejection_mailer_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe EmailRejectionMailer do
+ include EmailSpec::Matchers
+
+ describe '#rejection' do
+ let(:raw_email) { 'From: someone@example.com\nraw email here' }
+
+ subject { described_class.rejection('some rejection reason', raw_email) }
+
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+ end
+end
diff --git a/spec/mailers/emails/auto_devops_spec.rb b/spec/mailers/emails/auto_devops_spec.rb
index 839caf3f50e..dd7c12c3143 100644
--- a/spec/mailers/emails/auto_devops_spec.rb
+++ b/spec/mailers/emails/auto_devops_spec.rb
@@ -13,6 +13,9 @@ describe Emails::AutoDevops do
subject { Notify.autodevops_disabled_email(pipeline, owner.email) }
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
it 'sents email with correct subject' do
is_expected.to have_subject("#{project.name} | Auto DevOps pipeline was disabled for #{project.name}")
end
diff --git a/spec/mailers/emails/issues_spec.rb b/spec/mailers/emails/issues_spec.rb
new file mode 100644
index 00000000000..5b5bd6f4308
--- /dev/null
+++ b/spec/mailers/emails/issues_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'email_spec'
+
+describe Emails::Issues do
+ include EmailSpec::Matchers
+
+ describe "#import_issues_csv_email" do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+
+ subject { Notify.import_issues_csv_email(user.id, project.id, @results) }
+
+ it "shows number of successful issues imported" do
+ @results = { success: 165, error_lines: [], parse_error: false }
+
+ expect(subject).to have_body_text "165 issues imported"
+ end
+
+ it "shows error when file is invalid" do
+ @results = { success: 0, error_lines: [], parse_error: true }
+
+ expect(subject).to have_body_text "Error parsing CSV"
+ end
+
+ it "shows line numbers with errors" do
+ @results = { success: 0, error_lines: [23, 34, 58], parse_error: false }
+
+ expect(subject).to have_body_text "23, 34, 58"
+ end
+
+ context 'with header and footer' do
+ let(:results) { { success: 165, error_lines: [], parse_error: false } }
+
+ subject { Notify.import_issues_csv_email(user.id, project.id, results) }
+
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+ end
+ end
+end
diff --git a/spec/mailers/emails/pages_domains_spec.rb b/spec/mailers/emails/pages_domains_spec.rb
index fe428ea657d..c74fd66ad22 100644
--- a/spec/mailers/emails/pages_domains_spec.rb
+++ b/spec/mailers/emails/pages_domains_spec.rb
@@ -6,7 +6,7 @@ describe Emails::PagesDomains do
include_context 'gitlab email notification'
set(:project) { create(:project) }
- set(:domain) { create(:pages_domain, project: project) }
+ set(:domain) { create(:pages_domain, project: project) }
set(:user) { project.owner }
shared_examples 'a pages domain email' do
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index f2d99872401..3c8897ed37c 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -9,8 +9,10 @@ describe Notify do
include_context 'gitlab email notification'
+ let(:current_user_sanitized) { 'www_example_com' }
+
set(:user) { create(:user) }
- set(:current_user) { create(:user, email: "current@email.com") }
+ set(:current_user) { create(:user, email: "current@email.com", name: 'www.example.com') }
set(:assignee) { create(:user, email: 'assignee@example.com', name: 'John Doe') }
set(:merge_request) do
@@ -51,6 +53,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Issue link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject and body' do
aggregate_failures do
@@ -70,6 +74,9 @@ describe Notify do
context 'when sent with a reason' do
subject { described_class.new_issue_email(issue.assignees.first.id, issue.id, NotificationReason::ASSIGNED) }
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
it 'includes the reason in a header' do
is_expected.to have_header('X-GitLab-NotificationReason', NotificationReason::ASSIGNED)
end
@@ -97,6 +104,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Issue link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -116,6 +125,9 @@ describe Notify do
context 'when sent with a reason' do
subject { described_class.reassigned_issue_email(recipient.id, issue.id, [previous_assignee.id], current_user.id, NotificationReason::ASSIGNED) }
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
it 'includes the reason in a header' do
is_expected.to have_header('X-GitLab-NotificationReason', NotificationReason::ASSIGNED)
end
@@ -132,6 +144,8 @@ describe Notify do
it_behaves_like 'it should show Gmail Actions View Issue link'
it_behaves_like 'a user cannot unsubscribe through footer link'
it_behaves_like 'an email with a labels subscriptions link in its footer'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -171,6 +185,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Issue link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -182,7 +198,7 @@ describe Notify do
aggregate_failures do
is_expected.to have_referable_subject(issue, reply: true)
is_expected.to have_body_text(status)
- is_expected.to have_body_text(current_user.name)
+ is_expected.to have_body_text(current_user_sanitized)
is_expected.to have_body_text(project_issue_path project, issue)
end
end
@@ -192,23 +208,53 @@ describe Notify do
let(:new_issue) { create(:issue) }
subject { described_class.issue_moved_email(recipient, issue, new_issue, current_user) }
- it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
- let(:model) { issue }
- end
- it_behaves_like 'it should show Gmail Actions View Issue link'
- it_behaves_like 'an unsubscribeable thread'
+ context 'when a user has permissions to access the new issue' do
+ before do
+ new_issue.project.add_developer(recipient)
+ end
+
+ it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
+ let(:model) { issue }
+ end
+ it_behaves_like 'it should show Gmail Actions View Issue link'
+ it_behaves_like 'an unsubscribeable thread'
+
+ it 'contains description about action taken' do
+ is_expected.to have_body_text 'Issue was moved to another project'
+ end
+
+ it 'has the correct subject and body' do
+ new_issue_url = project_issue_path(new_issue.project, new_issue)
+
+ aggregate_failures do
+ is_expected.to have_referable_subject(issue, reply: true)
+ is_expected.to have_body_text(new_issue_url)
+ is_expected.to have_body_text(project_issue_path(project, issue))
+ end
+ end
- it 'contains description about action taken' do
- is_expected.to have_body_text 'Issue was moved to another project'
+ it 'contains the issue title' do
+ is_expected.to have_body_text new_issue.title
+ end
end
- it 'has the correct subject and body' do
- new_issue_url = project_issue_path(new_issue.project, new_issue)
+ context 'when a user does not permissions to access the new issue' do
+ it 'has the correct subject and body' do
+ new_issue_url = project_issue_path(new_issue.project, new_issue)
- aggregate_failures do
- is_expected.to have_referable_subject(issue, reply: true)
- is_expected.to have_body_text(new_issue_url)
- is_expected.to have_body_text(project_issue_path(project, issue))
+ aggregate_failures do
+ is_expected.to have_referable_subject(issue, reply: true)
+ is_expected.not_to have_body_text(new_issue_url)
+ is_expected.to have_body_text(project_issue_path(project, issue))
+ end
+ end
+
+ it 'does not contain the issue title' do
+ is_expected.not_to have_body_text new_issue.title
+ end
+
+ it 'contains information about missing permissions' do
+ is_expected.to have_body_text "You don't have access to the project."
end
end
end
@@ -224,6 +270,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject and body' do
aggregate_failures do
@@ -241,6 +289,9 @@ describe Notify do
context 'when sent with a reason' do
subject { described_class.new_merge_request_email(merge_request.assignee_id, merge_request.id, NotificationReason::ASSIGNED) }
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
it 'includes the reason in a header' do
is_expected.to have_header('X-GitLab-NotificationReason', NotificationReason::ASSIGNED)
end
@@ -268,6 +319,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like "an unsubscribeable thread"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -287,6 +340,9 @@ describe Notify do
context 'when sent with a reason' do
subject { described_class.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id, current_user.id, NotificationReason::ASSIGNED) }
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
it 'includes the reason in a header' do
is_expected.to have_header('X-GitLab-NotificationReason', NotificationReason::ASSIGNED)
end
@@ -311,6 +367,8 @@ describe Notify do
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like "an unsubscribeable thread"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains the description' do
is_expected.to have_body_text(merge_request.description)
@@ -327,6 +385,8 @@ describe Notify do
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'a user cannot unsubscribe through footer link'
it_behaves_like 'an email with a labels subscriptions link in its footer'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -350,6 +410,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -361,7 +423,7 @@ describe Notify do
aggregate_failures do
is_expected.to have_referable_subject(merge_request, reply: true)
is_expected.to have_body_text(status)
- is_expected.to have_body_text(current_user.name)
+ is_expected.to have_body_text(current_user_sanitized)
is_expected.to have_body_text(project_merge_request_path(project, merge_request))
end
end
@@ -377,6 +439,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the merge author' do
sender = subject.header[:from].addrs[0]
@@ -411,6 +475,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the merge request author' do
sender = subject.header[:from].addrs[0]
@@ -440,6 +506,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the push user' do
sender = subject.header[:from].addrs[0]
@@ -480,6 +548,9 @@ describe Notify do
subject { described_class.note_issue_email(recipient.id, third_note.id) }
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
it 'has In-Reply-To header pointing to previous note in discussion' do
expect(subject.header['In-Reply-To'].message_ids).to eq(["note_#{second_note.id}@#{host}"])
end
@@ -500,6 +571,9 @@ describe Notify do
subject { described_class.note_issue_email(recipient.id, note.id) }
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
it 'has In-Reply-To header pointing to the issue' do
expect(subject.header['In-Reply-To'].message_ids).to eq(["issue_#{note.noteable.id}@#{host}"])
end
@@ -516,6 +590,9 @@ describe Notify do
subject { described_class.note_project_snippet_email(project_snippet_note.author_id, project_snippet_note.id) }
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
let(:model) { project_snippet }
end
@@ -533,6 +610,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject and body' do
is_expected.to have_subject("#{project.name} | Project was moved")
@@ -557,6 +636,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
to_emails = subject.header[:to].addrs.map(&:address)
@@ -580,6 +661,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject "Access to the #{project.full_name} project was denied"
@@ -597,6 +680,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject "Access to the #{project.full_name} project was granted"
@@ -627,6 +712,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject "Invitation to join the #{project.full_name} project"
@@ -651,6 +738,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject 'Invitation accepted'
@@ -674,6 +763,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject 'Invitation declined'
@@ -706,6 +797,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Commit link'
it_behaves_like 'a user cannot unsubscribe through footer link'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject and body' do
aggregate_failures do
@@ -730,6 +823,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject and body' do
aggregate_failures do
@@ -754,6 +849,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Issue link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject and body' do
aggregate_failures do
@@ -817,6 +914,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Commit link'
it_behaves_like 'a user cannot unsubscribe through footer link'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject' do
is_expected.to have_subject "Re: #{project.name} | #{commit.title} (#{commit.short_id})"
@@ -843,6 +942,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject' do
is_expected.to have_referable_subject(merge_request, reply: true)
@@ -869,6 +970,8 @@ describe Notify do
end
it_behaves_like 'it should show Gmail Actions View Issue link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject' do
is_expected.to have_referable_subject(issue, reply: true)
@@ -887,7 +990,7 @@ describe Notify do
allow(Note).to receive(:find).with(note.id).and_return(note)
end
- shared_examples 'an email for a note on a diff discussion' do |model|
+ shared_examples 'an email for a note on a diff discussion' do |model|
let(:note) { create(model, author: note_author) }
context 'when note is not on text' do
@@ -946,6 +1049,8 @@ describe Notify do
it_behaves_like 'an email for a note on a diff discussion', :diff_note_on_commit
it_behaves_like 'it should show Gmail Actions View Commit link'
it_behaves_like 'a user cannot unsubscribe through footer link'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
end
describe 'on a merge request' do
@@ -956,6 +1061,8 @@ describe Notify do
it_behaves_like 'an email for a note on a diff discussion', :diff_note_on_merge_request
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
end
end
end
@@ -974,6 +1081,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
to_emails = subject.header[:to].addrs.map(&:address)
@@ -996,6 +1105,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject "Access to the #{group.name} group was denied"
@@ -1012,6 +1123,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject "Access to the #{group.name} group was granted"
@@ -1042,6 +1155,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject "Invitation to join the #{group.name} group"
@@ -1066,6 +1181,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject 'Invitation accepted'
@@ -1089,6 +1206,8 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'contains all the useful information' do
is_expected.to have_subject 'Invitation declined'
@@ -1138,6 +1257,8 @@ describe Notify do
it_behaves_like 'a user cannot unsubscribe through footer link'
it_behaves_like 'an email with X-GitLab headers containing project details'
it_behaves_like 'an email that contains a header with author username'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -1163,6 +1284,8 @@ describe Notify do
it_behaves_like "a user cannot unsubscribe through footer link"
it_behaves_like 'an email with X-GitLab headers containing project details'
it_behaves_like 'an email that contains a header with author username'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -1187,6 +1310,8 @@ describe Notify do
it_behaves_like 'a user cannot unsubscribe through footer link'
it_behaves_like 'an email with X-GitLab headers containing project details'
it_behaves_like 'an email that contains a header with author username'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -1208,6 +1333,8 @@ describe Notify do
it_behaves_like 'a user cannot unsubscribe through footer link'
it_behaves_like 'an email with X-GitLab headers containing project details'
it_behaves_like 'an email that contains a header with author username'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -1235,6 +1362,8 @@ describe Notify do
it_behaves_like 'a user cannot unsubscribe through footer link'
it_behaves_like 'an email with X-GitLab headers containing project details'
it_behaves_like 'an email that contains a header with author username'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -1326,6 +1455,8 @@ describe Notify do
it_behaves_like 'a user cannot unsubscribe through footer link'
it_behaves_like 'an email with X-GitLab headers containing project details'
it_behaves_like 'an email that contains a header with author username'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
@@ -1346,6 +1477,11 @@ describe Notify do
describe 'HTML emails setting' do
let(:multipart_mail) { described_class.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
+ subject { multipart_mail }
+
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
context 'when disabled' do
it 'only sends the text template' do
stub_application_setting(html_emails_enabled: false)
@@ -1384,6 +1520,8 @@ describe Notify do
subject { described_class.note_personal_snippet_email(personal_snippet_note.author_id, personal_snippet_note.id) }
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 'has the correct subject and body' do
is_expected.to have_referable_subject(personal_snippet, reply: true)
diff --git a/spec/mailers/repository_check_mailer_spec.rb b/spec/mailers/repository_check_mailer_spec.rb
index 00613c7b671..384660f7221 100644
--- a/spec/mailers/repository_check_mailer_spec.rb
+++ b/spec/mailers/repository_check_mailer_spec.rb
@@ -17,5 +17,12 @@ describe RepositoryCheckMailer do
expect(mail).to have_subject 'GitLab Admin | 3 projects failed their last repository check'
end
+
+ context 'with footer and header' do
+ subject { described_class.notify(1) }
+
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+ end
end
end
diff --git a/spec/migrations/README.md b/spec/migrations/README.md
index 49760fa62b8..5df44dbc355 100644
--- a/spec/migrations/README.md
+++ b/spec/migrations/README.md
@@ -22,39 +22,33 @@ migrate the database **down** to the previous migration version.
With this approach you can test a migration against a database schema that this
migration has been written for.
-Use `migrate!` helper to run the migration that is under test.
-
The `after` hook will migrate the database **up** and reinstitutes the latest
schema version, so that the process does not affect subsequent specs and
ensures proper isolation.
-## Testing a class that is not an ActiveRecord::Migration
-
-In order to test a class that is not a migration itself, you will need to
-manually provide a required schema version. Please add a `schema` tag to a
-context that you want to switch the database schema within.
-
-Example: `describe SomeClass, :migration, schema: 20170608152748`.
-
## Available helpers
Use `table` helper to create a temporary `ActiveRecord::Base` derived model
for a table.
-Use `migrate!` helper to run the migration that is under test. It will not only
+See `spec/support/helpers/migrations_helpers.rb` for all the available helpers.
+
+## Testing a class that is an ActiveRecord::Migration
+
+In order to test a class that is an `ActiveRecord::Migration`, you will need to
+manually `require` the migration file because it is not autoloaded with Rails.
+
+Use `migrate!` helper to run the migration that is under test. It will not only
run migration, but will also bump the schema version in the `schema_migrations`
table. It is necessary because in the `after` hook we trigger the rest of
the migrations, and we need to know where to start.
-See `spec/support/migrations_helpers.rb` for all the available helpers.
+### Example
-## An example
+This spec tests the [`db/post_migrate/20170526185842_migrate_pipeline_stages.rb`](https://gitlab.com/gitlab-org/gitlab-ce/blob/v11.6.5/db/post_migrate/20170526185842_migrate_pipeline_stages.rb) migration. You can find the complete spec on [`spec/migrations/migrate_pipeline_stages_spec.rb`](https://gitlab.com/gitlab-org/gitlab-ce/blob/v11.6.5/spec/migrations/migrate_pipeline_stages_spec.rb).
```ruby
require 'spec_helper'
-
-# Load a migration class.
-
require Rails.root.join('db', 'post_migrate', '20170526185842_migrate_pipeline_stages.rb')
describe MigratePipelineStages, :migration do
@@ -86,6 +80,56 @@ describe MigratePipelineStages, :migration do
end
```
+## Testing a class that is not an ActiveRecord::Migration
+
+To test a class that is not an `ActiveRecord::Migration` (a background migration),
+you will need to manually provide a required schema version. Please add a
+schema tag to a context that you want to switch the database schema within.
+
+Example: `describe SomeClass, :migration, schema: 20170608152748`.
+
+### Example
+
+This spec tests the [`lib/gitlab/background_migration/archive_legacy_traces.rb`](https://gitlab.com/gitlab-org/gitlab-ce/blob/v11.6.5/lib/gitlab/background_migration/archive_legacy_traces.rb)
+background migration. You can find the complete spec on
+[`spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb`](https://gitlab.com/gitlab-org/gitlab-ce/blob/v11.6.5/spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb)
+
+```ruby
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::ArchiveLegacyTraces, :migration, schema: 20180529152628 do
+ include TraceHelpers
+
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:builds) { table(:ci_builds) }
+ let(:job_artifacts) { table(:ci_job_artifacts) }
+
+ before do
+ namespaces.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
+ projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1', namespace_id: 123)
+ @build = builds.create!(id: 1, project_id: 123, status: 'success', type: 'Ci::Build')
+ end
+
+ context 'when trace file exsits at the right place' do
+ before do
+ create_legacy_trace(@build, 'trace in file')
+ end
+
+ it 'correctly archive legacy traces' do
+ expect(job_artifacts.count).to eq(0)
+ expect(File.exist?(legacy_trace_path(@build))).to be_truthy
+
+ described_class.new.perform(1, 1)
+
+ expect(job_artifacts.count).to eq(1)
+ expect(File.exist?(legacy_trace_path(@build))).to be_falsy
+ expect(File.read(archived_trace_path(job_artifacts.first))).to eq('trace in file')
+ end
+ end
+end
+```
+
## Best practices
1. Note that this type of tests do not run within the transaction, we use
diff --git a/spec/migrations/add_foreign_keys_to_todos_spec.rb b/spec/migrations/add_foreign_keys_to_todos_spec.rb
index bf2fa5c0f56..efd87173b9c 100644
--- a/spec/migrations/add_foreign_keys_to_todos_spec.rb
+++ b/spec/migrations/add_foreign_keys_to_todos_spec.rb
@@ -3,9 +3,11 @@ require Rails.root.join('db', 'migrate', '20180201110056_add_foreign_keys_to_tod
describe AddForeignKeysToTodos, :migration do
let(:todos) { table(:todos) }
+ let(:users) { table(:users) }
+ let(:projects) { table(:projects) }
- let(:project) { create(:project) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
- let(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
+ let(:project) { projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce', namespace_id: 1) }
+ let(:user) { users.create!(email: 'email@email.com', name: 'foo', username: 'foo', projects_limit: 0) }
context 'add foreign key on user_id' do
let!(:todo_with_user) { create_todo(user_id: user.id) }
diff --git a/spec/migrations/clean_up_for_members_spec.rb b/spec/migrations/clean_up_for_members_spec.rb
index 7876536cb3e..1a79f94cf0d 100644
--- a/spec/migrations/clean_up_for_members_spec.rb
+++ b/spec/migrations/clean_up_for_members_spec.rb
@@ -2,6 +2,10 @@ require 'spec_helper'
require Rails.root.join('db', 'migrate', '20171216111734_clean_up_for_members.rb')
describe CleanUpForMembers, :migration do
+ before do
+ stub_feature_flags(enforced_sso: false)
+ end
+
let(:migration) { described_class.new }
let(:groups) { table(:namespaces) }
let!(:group_member) { create_group_member }
diff --git a/spec/migrations/cleanup_legacy_artifact_migration_spec.rb b/spec/migrations/cleanup_legacy_artifact_migration_spec.rb
new file mode 100644
index 00000000000..dc269d32e5a
--- /dev/null
+++ b/spec/migrations/cleanup_legacy_artifact_migration_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20190104182041_cleanup_legacy_artifact_migration.rb')
+
+describe CleanupLegacyArtifactMigration, :migration, :sidekiq, :redis do
+ let(:migration) { spy('migration') }
+
+ context 'when still legacy artifacts exist' do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:pipelines) { table(:ci_pipelines) }
+ let(:jobs) { table(:ci_builds) }
+ let(:job_artifacts) { table(:ci_job_artifacts) }
+ let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create!(name: 'gitlab', path: 'gitlab-ce', namespace_id: namespace.id) }
+ let(:pipeline) { pipelines.create!(project_id: project.id, ref: 'master', sha: 'adf43c3a') }
+ let(:archive_file_type) { Gitlab::BackgroundMigration::MigrateLegacyArtifacts::ARCHIVE_FILE_TYPE }
+ let(:metadata_file_type) { Gitlab::BackgroundMigration::MigrateLegacyArtifacts::METADATA_FILE_TYPE }
+ let(:local_store) { ::ObjectStorage::Store::LOCAL }
+ let(:remote_store) { ::ObjectStorage::Store::REMOTE }
+ let(:legacy_location) { Gitlab::BackgroundMigration::MigrateLegacyArtifacts::LEGACY_PATH_FILE_LOCATION }
+
+ before do
+ jobs.create!(id: 1, commit_id: pipeline.id, project_id: project.id, status: :success, artifacts_file: 'archive.zip')
+ jobs.create!(id: 2, commit_id: pipeline.id, project_id: project.id, status: :failed, artifacts_metadata: 'metadata.gz')
+ jobs.create!(id: 3, commit_id: pipeline.id, project_id: project.id, status: :failed, artifacts_file: 'archive.zip', artifacts_metadata: 'metadata.gz')
+ jobs.create!(id: 4, commit_id: pipeline.id, project_id: project.id, status: :running)
+ jobs.create!(id: 5, commit_id: pipeline.id, project_id: project.id, status: :success, artifacts_file: 'archive.zip', artifacts_file_store: remote_store, artifacts_metadata: 'metadata.gz')
+ jobs.create!(id: 6, commit_id: pipeline.id, project_id: project.id, status: :failed, artifacts_file: 'archive.zip', artifacts_metadata: 'metadata.gz')
+ end
+
+ it 'steals sidekiq jobs from MigrateLegacyArtifacts background migration' do
+ expect(Gitlab::BackgroundMigration).to receive(:steal).with('MigrateLegacyArtifacts')
+
+ migrate!
+ end
+
+ it 'migrates legacy artifacts to ci_job_artifacts table' do
+ migrate!
+
+ expect(job_artifacts.order(:job_id, :file_type).pluck('project_id, job_id, file_type, file_store, size, expire_at, file, file_sha256, file_location'))
+ .to eq([[project.id, 1, archive_file_type, local_store, nil, nil, 'archive.zip', nil, legacy_location],
+ [project.id, 3, archive_file_type, local_store, nil, nil, 'archive.zip', nil, legacy_location],
+ [project.id, 3, metadata_file_type, local_store, nil, nil, 'metadata.gz', nil, legacy_location],
+ [project.id, 5, archive_file_type, remote_store, nil, nil, 'archive.zip', nil, legacy_location],
+ [project.id, 5, metadata_file_type, local_store, nil, nil, 'metadata.gz', nil, legacy_location],
+ [project.id, 6, archive_file_type, local_store, nil, nil, 'archive.zip', nil, legacy_location],
+ [project.id, 6, metadata_file_type, local_store, nil, nil, 'metadata.gz', nil, legacy_location]])
+ end
+ end
+end
diff --git a/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb b/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb
index b5980cb9ddb..651341906c2 100644
--- a/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb
+++ b/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170502101023_cleanup_namespaceless_pending_delete_projects.rb')
describe CleanupNamespacelessPendingDeleteProjects, :migration, schema: 20180222043024 do
+ let(:projects) { table(:projects) }
+
before do
# Stub after_save callbacks that will fail when Project has no namespace
allow_any_instance_of(Project).to receive(:ensure_storage_path_exists).and_return(nil)
@@ -10,9 +12,9 @@ describe CleanupNamespacelessPendingDeleteProjects, :migration, schema: 20180222
describe '#up' do
it 'only cleans up pending delete projects' do
- create(:project) # rubocop:disable RSpec/FactoriesInMigrationSpecs
- create(:project, pending_delete: true) # rubocop:disable RSpec/FactoriesInMigrationSpecs
- project = build(:project, pending_delete: true, namespace_id: nil) # rubocop:disable RSpec/FactoriesInMigrationSpecs
+ projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce', namespace_id: 1)
+ projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ee', namespace_id: 2, pending_delete: true)
+ project = Project.new(pending_delete: true, namespace_id: nil)
project.save(validate: false)
expect(NamespacelessProjectDestroyWorker).to receive(:bulk_perform_async).with([[project.id]])
@@ -21,8 +23,8 @@ describe CleanupNamespacelessPendingDeleteProjects, :migration, schema: 20180222
end
it 'does nothing when no pending delete projects without namespace found' do
- create(:project) # rubocop:disable RSpec/FactoriesInMigrationSpecs
- create(:project, pending_delete: true) # rubocop:disable RSpec/FactoriesInMigrationSpecs
+ projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce', namespace_id: 1)
+ projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ee', namespace_id: 2, pending_delete: true)
expect(NamespacelessProjectDestroyWorker).not_to receive(:bulk_perform_async)
diff --git a/spec/migrations/delete_inconsistent_internal_id_records_spec.rb b/spec/migrations/delete_inconsistent_internal_id_records_spec.rb
index 8c55daf0d37..e2ce69a7bb1 100644
--- a/spec/migrations/delete_inconsistent_internal_id_records_spec.rb
+++ b/spec/migrations/delete_inconsistent_internal_id_records_spec.rb
@@ -90,12 +90,19 @@ describe DeleteInconsistentInternalIdRecords, :migration do
context 'for ci_pipelines' do
let(:scope) { :ci_pipeline }
+
+ let(:create_models) do
+ create_list(:ci_empty_pipeline, 3, project: project1)
+ create_list(:ci_empty_pipeline, 3, project: project2)
+ create_list(:ci_empty_pipeline, 3, project: project3)
+ end
+
it_behaves_like 'deleting inconsistent internal_id records'
end
context 'for milestones (by group)' do
# milestones (by group) is a little different than most of the other models
- let(:groups) { table(:namespaces) }
+ let(:groups) { table(:namespaces) }
let(:group1) { groups.create(name: 'Group 1', type: 'Group', path: 'group_1') }
let(:group2) { groups.create(name: 'Group 2', type: 'Group', path: 'group_2') }
let(:group3) { groups.create(name: 'Group 2', type: 'Group', path: 'group_3') }
diff --git a/spec/migrations/fix_null_type_labels_spec.rb b/spec/migrations/fix_null_type_labels_spec.rb
new file mode 100644
index 00000000000..462ae9b913f
--- /dev/null
+++ b/spec/migrations/fix_null_type_labels_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190131122559_fix_null_type_labels')
+
+describe FixNullTypeLabels, :migration do
+ let(:migration) { described_class.new }
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+ let(:labels) { table(:labels) }
+
+ before do
+ group = namespaces.create(name: 'labels-test-project', path: 'labels-test-project', type: 'Group')
+ project = projects.create!(namespace_id: group.id, name: 'labels-test-group', path: 'labels-test-group')
+
+ @template_label = labels.create(title: 'template', template: true)
+ @project_label = labels.create(title: 'project label', project_id: project.id, type: 'ProjectLabel')
+ @group_label = labels.create(title: 'group_label', group_id: group.id, type: 'GroupLabel')
+ @broken_label_1 = labels.create(title: 'broken 1', project_id: project.id)
+ @broken_label_2 = labels.create(title: 'broken 2', project_id: project.id)
+ end
+
+ describe '#up' do
+ it 'fix labels with type missing' do
+ migration.up
+
+ # Labels that requires type change
+ expect(@broken_label_1.reload.type).to eq('ProjectLabel')
+ expect(@broken_label_2.reload.type).to eq('ProjectLabel')
+ # Labels out of scope
+ expect(@template_label.reload.type).to be_nil
+ expect(@project_label.reload.type).to eq('ProjectLabel')
+ expect(@group_label.reload.type).to eq('GroupLabel')
+ end
+ end
+end
diff --git a/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb
new file mode 100644
index 00000000000..b1ff3cfd355
--- /dev/null
+++ b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb')
+
+describe MigrateAutoDevOpsDomainToClusterDomain, :migration do
+ include MigrationHelpers::ClusterHelpers
+
+ let(:migration) { described_class.new }
+ let(:project_auto_devops_table) { table(:project_auto_devops) }
+ let(:clusters_table) { table(:clusters) }
+ let(:cluster_projects_table) { table(:cluster_projects) }
+
+ # Following lets are needed by MigrationHelpers::ClusterHelpers
+ let(:cluster_kubernetes_namespaces_table) { table(:clusters_kubernetes_namespaces) }
+ let(:projects_table) { table(:projects) }
+ let(:namespaces_table) { table(:namespaces) }
+ let(:provider_gcp_table) { table(:cluster_providers_gcp) }
+ let(:platform_kubernetes_table) { table(:cluster_platforms_kubernetes) }
+
+ before do
+ setup_cluster_projects_with_domain(quantity: 20, domain: domain)
+ end
+
+ context 'with ProjectAutoDevOps with no domain' do
+ let(:domain) { nil }
+
+ it 'should not update cluster project' do
+ migrate!
+
+ expect(clusters_without_domain.count).to eq(clusters_table.count)
+ end
+ end
+
+ context 'with ProjectAutoDevOps with domain' do
+ let(:domain) { 'example-domain.com' }
+
+ it 'should update all cluster projects' do
+ migrate!
+
+ expect(clusters_with_domain.count).to eq(clusters_table.count)
+ end
+ end
+
+ context 'when only some ProjectAutoDevOps have domain set' do
+ let(:domain) { 'example-domain.com' }
+
+ before do
+ setup_cluster_projects_with_domain(quantity: 25, domain: nil)
+ end
+
+ it 'should only update specific cluster projects' do
+ migrate!
+
+ expect(clusters_with_domain.count).to eq(20)
+
+ project_auto_devops_with_domain.each do |project_auto_devops|
+ cluster_project = find_cluster_project(project_auto_devops.project_id)
+ cluster = find_cluster(cluster_project.cluster_id)
+
+ expect(cluster.domain).to be_present
+ end
+
+ expect(clusters_without_domain.count).to eq(25)
+
+ project_auto_devops_without_domain.each do |project_auto_devops|
+ cluster_project = find_cluster_project(project_auto_devops.project_id)
+ cluster = find_cluster(cluster_project.cluster_id)
+
+ expect(cluster.domain).not_to be_present
+ end
+ end
+ end
+
+ def setup_cluster_projects_with_domain(quantity:, domain:)
+ create_cluster_project_list(quantity)
+
+ cluster_projects = cluster_projects_table.last(quantity)
+
+ cluster_projects.each do |cluster_project|
+ specific_domain = "#{cluster_project.id}-#{domain}" if domain
+
+ project_auto_devops_table.create(
+ project_id: cluster_project.project_id,
+ enabled: true,
+ domain: specific_domain
+ )
+ end
+ end
+
+ def find_cluster_project(project_id)
+ cluster_projects_table.where(project_id: project_id).first
+ end
+
+ def find_cluster(cluster_id)
+ clusters_table.where(id: cluster_id).first
+ end
+
+ def project_auto_devops_with_domain
+ project_auto_devops_table.where.not("domain IS NULL OR domain = ''")
+ end
+
+ def project_auto_devops_without_domain
+ project_auto_devops_table.where("domain IS NULL OR domain = ''")
+ end
+
+ def clusters_with_domain
+ clusters_table.where.not("domain IS NULL OR domain = ''")
+ end
+
+ def clusters_without_domain
+ clusters_table.where("domain IS NULL OR domain = ''")
+ end
+end
diff --git a/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb b/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb
new file mode 100644
index 00000000000..f8cf76cb339
--- /dev/null
+++ b/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190124200344_migrate_storage_migrator_sidekiq_queue.rb')
+
+describe MigrateStorageMigratorSidekiqQueue, :sidekiq, :redis do
+ include Gitlab::Database::MigrationHelpers
+
+ context 'when there are jobs in the queues' do
+ it 'correctly migrates queue when migrating up' do
+ Sidekiq::Testing.disable! do
+ stubbed_worker(queue: :storage_migrator).perform_async(1, 5)
+
+ described_class.new.up
+
+ expect(sidekiq_queue_length('storage_migrator')).to eq 0
+ expect(sidekiq_queue_length('hashed_storage:hashed_storage_migrator')).to eq 1
+ end
+ end
+
+ it 'correctly migrates queue when migrating down' do
+ Sidekiq::Testing.disable! do
+ stubbed_worker(queue: :'hashed_storage:hashed_storage_migrator').perform_async(1, 5)
+
+ described_class.new.down
+
+ expect(sidekiq_queue_length('storage_migrator')).to eq 1
+ expect(sidekiq_queue_length('hashed_storage:hashed_storage_migrator')).to eq 0
+ end
+ end
+ end
+
+ context 'when there are no jobs in the queues' do
+ it 'does not raise error when migrating up' do
+ expect { described_class.new.up }.not_to raise_error
+ end
+
+ it 'does not raise error when migrating down' do
+ expect { described_class.new.down }.not_to raise_error
+ end
+ end
+
+ def stubbed_worker(queue:)
+ Class.new do
+ include Sidekiq::Worker
+ sidekiq_options queue: queue
+ end
+ end
+end
diff --git a/spec/migrations/rename_more_reserved_project_names_spec.rb b/spec/migrations/rename_more_reserved_project_names_spec.rb
index baf16c2ce53..80ae209e9d1 100644
--- a/spec/migrations/rename_more_reserved_project_names_spec.rb
+++ b/spec/migrations/rename_more_reserved_project_names_spec.rb
@@ -37,9 +37,8 @@ describe RenameMoreReservedProjectNames, :delete do
.to receive(:execute)
.and_raise(Projects::AfterRenameService::RenameFailedError)
- allow(Projects::AfterRenameService)
- .to receive(:new)
- .with(project)
+ expect(migration)
+ .to receive(:after_rename_service)
.and_return(service)
end
diff --git a/spec/migrations/rename_reserved_project_names_spec.rb b/spec/migrations/rename_reserved_project_names_spec.rb
index 7818aa0d560..93e5c032287 100644
--- a/spec/migrations/rename_reserved_project_names_spec.rb
+++ b/spec/migrations/rename_reserved_project_names_spec.rb
@@ -41,9 +41,8 @@ describe RenameReservedProjectNames, :migration, schema: :latest do
.to receive(:execute)
.and_raise(Projects::AfterRenameService::RenameFailedError)
- allow(Projects::AfterRenameService)
- .to receive(:new)
- .with(project)
+ expect(migration)
+ .to receive(:after_rename_service)
.and_return(service)
end
diff --git a/spec/migrations/update_project_import_visibility_level_spec.rb b/spec/migrations/update_project_import_visibility_level_spec.rb
new file mode 100644
index 00000000000..9ea9b956f67
--- /dev/null
+++ b/spec/migrations/update_project_import_visibility_level_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20181219130552_update_project_import_visibility_level.rb')
+
+describe UpdateProjectImportVisibilityLevel, :migration do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:project) { projects.find_by_name(name) }
+
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ end
+
+ context 'private visibility level' do
+ let(:name) { 'private-public' }
+
+ it 'updates the project visibility' do
+ create_namespace(name, Gitlab::VisibilityLevel::PRIVATE)
+ create_project(name, Gitlab::VisibilityLevel::PUBLIC)
+
+ expect { migrate! }.to change { project.reload.visibility_level }.to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
+
+ context 'internal visibility level' do
+ let(:name) { 'internal-public' }
+
+ it 'updates the project visibility' do
+ create_namespace(name, Gitlab::VisibilityLevel::INTERNAL)
+ create_project(name, Gitlab::VisibilityLevel::PUBLIC)
+
+ expect { migrate! }.to change { project.reload.visibility_level }.to(Gitlab::VisibilityLevel::INTERNAL)
+ end
+ end
+
+ context 'public visibility level' do
+ let(:name) { 'public-public' }
+
+ it 'does not update the project visibility' do
+ create_namespace(name, Gitlab::VisibilityLevel::PUBLIC)
+ create_project(name, Gitlab::VisibilityLevel::PUBLIC)
+
+ expect { migrate! }.not_to change { project.reload.visibility_level }
+ end
+ end
+
+ context 'private project visibility level' do
+ let(:name) { 'public-private' }
+
+ it 'does not update the project visibility' do
+ create_namespace(name, Gitlab::VisibilityLevel::PUBLIC)
+ create_project(name, Gitlab::VisibilityLevel::PRIVATE)
+
+ expect { migrate! }.not_to change { project.reload.visibility_level }
+ end
+ end
+
+ context 'no namespace' do
+ let(:name) { 'no-namespace' }
+
+ it 'does not update the project visibility' do
+ create_namespace(name, Gitlab::VisibilityLevel::PRIVATE, type: nil)
+ create_project(name, Gitlab::VisibilityLevel::PUBLIC)
+
+ expect { migrate! }.not_to change { project.reload.visibility_level }
+ end
+ end
+
+ def create_namespace(name, visibility, options = {})
+ namespaces.create({
+ name: name,
+ path: name,
+ type: 'Group',
+ visibility_level: visibility
+ }.merge(options))
+ end
+
+ def create_project(name, visibility)
+ projects.create!(namespace_id: namespaces.find_by_name(name).id,
+ name: name,
+ path: name,
+ import_type: 'gitlab_project',
+ visibility_level: visibility)
+ end
+end
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index 199f49d0bf2..eee80e9bad7 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -298,7 +298,6 @@ describe Ability do
context 'wiki named abilities' do
it 'disables wiki abilities if the project has no wiki' do
- expect(project).to receive(:has_external_wiki?).and_return(false)
expect(subject).not_to be_allowed(:read_wiki)
expect(subject).not_to be_allowed(:create_wiki)
expect(subject).not_to be_allowed(:update_wiki)
diff --git a/spec/models/active_session_spec.rb b/spec/models/active_session_spec.rb
index 129b2f92683..e128fe8a4b7 100644
--- a/spec/models/active_session_spec.rb
+++ b/spec/models/active_session_spec.rb
@@ -7,7 +7,10 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
end
end
- let(:session) { double(:session, id: '6919a6f1bb119dd7396fadc38fd18d0d') }
+ let(:session) do
+ double(:session, { id: '6919a6f1bb119dd7396fadc38fd18d0d',
+ '[]': {} })
+ end
let(:request) do
double(:request, {
diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb
index 35415030154..3e95aa2b5dd 100644
--- a/spec/models/appearance_spec.rb
+++ b/spec/models/appearance_spec.rb
@@ -26,4 +26,74 @@ describe Appearance do
let(:uploader_class) { AttachmentUploader }
end
end
+
+ shared_examples 'logo paths' do |logo_type|
+ let(:appearance) { create(:appearance, "with_#{logo_type}".to_sym) }
+ let(:filename) { 'dk.png' }
+ let(:expected_path) { "/uploads/-/system/appearance/#{logo_type}/#{appearance.id}/#{filename}" }
+
+ it 'returns nil when there is no upload' do
+ expect(subject.send("#{logo_type}_path")).to be_nil
+ end
+
+ it 'returns the path when the upload has been orphaned' do
+ appearance.send(logo_type).upload.destroy
+ appearance.reload
+
+ expect(appearance.send("#{logo_type}_path")).to eq(expected_path)
+ end
+
+ it 'returns a local path using the system route' do
+ expect(appearance.send("#{logo_type}_path")).to eq(expected_path)
+ end
+
+ describe 'with asset host configured' do
+ let(:asset_host) { 'https://gitlab-assets.example.com' }
+
+ before do
+ allow(ActionController::Base).to receive(:asset_host) { asset_host }
+ end
+
+ it 'returns a full URL with the system path' do
+ expect(appearance.send("#{logo_type}_path")).to eq("#{asset_host}#{expected_path}")
+ end
+ end
+ end
+
+ %i(logo header_logo favicon).each do |logo_type|
+ it_behaves_like 'logo paths', logo_type
+ end
+
+ describe 'validations' do
+ let(:triplet) { '#000' }
+ let(:hex) { '#AABBCC' }
+
+ it { is_expected.to allow_value(nil).for(:message_background_color) }
+ it { is_expected.to allow_value(triplet).for(:message_background_color) }
+ it { is_expected.to allow_value(hex).for(:message_background_color) }
+ it { is_expected.not_to allow_value('000').for(:message_background_color) }
+
+ it { is_expected.to allow_value(nil).for(:message_font_color) }
+ it { is_expected.to allow_value(triplet).for(:message_font_color) }
+ it { is_expected.to allow_value(hex).for(:message_font_color) }
+ it { is_expected.not_to allow_value('000').for(:message_font_color) }
+ end
+
+ describe 'email_header_and_footer_enabled' do
+ context 'default email_header_and_footer_enabled flag value' do
+ it 'returns email_header_and_footer_enabled as true' do
+ appearance = build(:appearance)
+
+ expect(appearance.email_header_and_footer_enabled?).to eq(false)
+ end
+ end
+
+ context 'when setting email_header_and_footer_enabled flag value' do
+ it 'returns email_header_and_footer_enabled as true' do
+ appearance = build(:appearance, email_header_and_footer_enabled: true)
+
+ expect(appearance.email_header_and_footer_enabled?).to eq(true)
+ end
+ end
+ end
end
diff --git a/spec/models/application_record_spec.rb b/spec/models/application_record_spec.rb
new file mode 100644
index 00000000000..fd25132ed3a
--- /dev/null
+++ b/spec/models/application_record_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ApplicationRecord do
+ describe '#id_in' do
+ let(:records) { create_list(:user, 3) }
+
+ it 'returns records of the ids' do
+ expect(User.id_in(records.last(2).map(&:id))).to eq(records.last(2))
+ end
+ end
+
+ describe '.safe_find_or_create_by' do
+ it 'creates the user avoiding race conditions' do
+ expect(Suggestion).to receive(:find_or_create_by).and_raise(ActiveRecord::RecordNotUnique)
+ allow(Suggestion).to receive(:find_or_create_by).and_call_original
+
+ expect { Suggestion.safe_find_or_create_by(build(:suggestion).attributes) }
+ .to change { Suggestion.count }.by(1)
+ end
+ end
+
+ describe '.safe_find_or_create_by!' do
+ it 'creates a record using safe_find_or_create_by' do
+ expect(Suggestion).to receive(:find_or_create_by).and_call_original
+
+ expect(Suggestion.safe_find_or_create_by!(build(:suggestion).attributes))
+ .to be_a(Suggestion)
+ end
+
+ it 'raises a validation error if the record was not persisted' do
+ expect { Suggestion.find_or_create_by!(note: nil) }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index 96aa9a82b71..789e14e8a20 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -70,6 +70,13 @@ describe ApplicationSetting do
.is_greater_than(0)
end
+ it do
+ is_expected.to validate_numericality_of(:local_markdown_version)
+ .only_integer
+ .is_greater_than_or_equal_to(0)
+ .is_less_than(65536)
+ end
+
context 'key restrictions' do
it 'supports all key types' do
expect(described_class::SUPPORTED_KEY_TYPES).to contain_exactly(:rsa, :dsa, :ecdsa, :ed25519)
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb
index e8c03b587e2..05cf242e84d 100644
--- a/spec/models/blob_spec.rb
+++ b/spec/models/blob_spec.rb
@@ -122,14 +122,14 @@ describe Blob do
end
end
- describe '#raw_binary?' do
+ describe '#binary?' do
context 'if the blob is stored externally' do
context 'if the extension has a rich viewer' do
context 'if the viewer is binary' do
it 'returns true' do
blob = fake_blob(path: 'file.pdf', lfs: true)
- expect(blob.raw_binary?).to be_truthy
+ expect(blob.binary?).to be_truthy
end
end
@@ -137,7 +137,7 @@ describe Blob do
it 'return false' do
blob = fake_blob(path: 'file.md', lfs: true)
- expect(blob.raw_binary?).to be_falsey
+ expect(blob.binary?).to be_falsey
end
end
end
@@ -148,7 +148,7 @@ describe Blob do
it 'returns false' do
blob = fake_blob(path: 'file.txt', lfs: true)
- expect(blob.raw_binary?).to be_falsey
+ expect(blob.binary?).to be_falsey
end
end
@@ -156,7 +156,7 @@ describe Blob do
it 'returns false' do
blob = fake_blob(path: 'file.ics', lfs: true)
- expect(blob.raw_binary?).to be_falsey
+ expect(blob.binary?).to be_falsey
end
end
end
@@ -166,7 +166,7 @@ describe Blob do
it 'returns false' do
blob = fake_blob(path: 'file.rb', lfs: true)
- expect(blob.raw_binary?).to be_falsey
+ expect(blob.binary?).to be_falsey
end
end
@@ -174,7 +174,7 @@ describe Blob do
it 'returns true' do
blob = fake_blob(path: 'file.exe', lfs: true)
- expect(blob.raw_binary?).to be_truthy
+ expect(blob.binary?).to be_truthy
end
end
end
@@ -184,7 +184,7 @@ describe Blob do
it 'returns false' do
blob = fake_blob(path: 'file.ini', lfs: true)
- expect(blob.raw_binary?).to be_falsey
+ expect(blob.binary?).to be_falsey
end
end
@@ -192,7 +192,7 @@ describe Blob do
it 'returns true' do
blob = fake_blob(path: 'file.wtf', lfs: true)
- expect(blob.raw_binary?).to be_truthy
+ expect(blob.binary?).to be_truthy
end
end
end
@@ -204,7 +204,7 @@ describe Blob do
it 'returns true' do
blob = fake_blob(path: 'file.pdf', binary: true)
- expect(blob.raw_binary?).to be_truthy
+ expect(blob.binary?).to be_truthy
end
end
@@ -212,7 +212,7 @@ describe Blob do
it 'return false' do
blob = fake_blob(path: 'file.md')
- expect(blob.raw_binary?).to be_falsey
+ expect(blob.binary?).to be_falsey
end
end
end
diff --git a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
index 01c555a7a90..16bf947b493 100644
--- a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
+++ b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
@@ -4,7 +4,9 @@ describe BlobViewer::GitlabCiYml do
include FakeBlobHelpers
include RepoHelpers
- let(:project) { create(:project, :repository) }
+ set(:project) { create(:project, :repository) }
+ set(:user) { create(:user) }
+
let(:data) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
let(:blob) { fake_blob(path: '.gitlab-ci.yml', data: data) }
let(:sha) { sample_commit.id }
@@ -14,12 +16,12 @@ describe BlobViewer::GitlabCiYml do
it 'calls prepare! on the viewer' do
expect(subject).to receive(:prepare!)
- subject.validation_message(project, sha)
+ subject.validation_message(project: project, sha: sha, user: user)
end
context 'when the configuration is valid' do
it 'returns nil' do
- expect(subject.validation_message(project, sha)).to be_nil
+ expect(subject.validation_message(project: project, sha: sha, user: user)).to be_nil
end
end
@@ -27,7 +29,7 @@ describe BlobViewer::GitlabCiYml do
let(:data) { 'oof' }
it 'returns the error message' do
- expect(subject.validation_message(project, sha)).to eq('Invalid configuration format')
+ expect(subject.validation_message(project: project, sha: sha, user: user)).to eq('Invalid configuration format')
end
end
end
diff --git a/spec/models/board_group_recent_visit_spec.rb b/spec/models/board_group_recent_visit_spec.rb
index 59ad4e5417e..558be61824f 100644
--- a/spec/models/board_group_recent_visit_spec.rb
+++ b/spec/models/board_group_recent_visit_spec.rb
@@ -50,15 +50,25 @@ describe BoardGroupRecentVisit do
end
describe '#latest' do
- it 'returns the most recent visited' do
- board2 = create(:board, group: group)
- board3 = create(:board, group: group)
+ def create_visit(time)
+ create :board_group_recent_visit, group: group, user: user, updated_at: time
+ end
- create :board_group_recent_visit, group: board.group, board: board, user: user, updated_at: 7.days.ago
- create :board_group_recent_visit, group: board2.group, board: board2, user: user, updated_at: 5.days.ago
- recent = create :board_group_recent_visit, group: board3.group, board: board3, user: user, updated_at: 1.day.ago
+ it 'returns the most recent visited' do
+ create_visit(7.days.ago)
+ create_visit(5.days.ago)
+ recent = create_visit(1.day.ago)
expect(described_class.latest(user, group)).to eq recent
end
+
+ it 'returns last 3 visited boards' do
+ create_visit(7.days.ago)
+ visit1 = create_visit(3.days.ago)
+ visit2 = create_visit(2.days.ago)
+ visit3 = create_visit(5.days.ago)
+
+ expect(described_class.latest(user, group, count: 3)).to eq([visit2, visit1, visit3])
+ end
end
end
diff --git a/spec/models/board_project_recent_visit_spec.rb b/spec/models/board_project_recent_visit_spec.rb
index 275581945fa..e404fb3bbdb 100644
--- a/spec/models/board_project_recent_visit_spec.rb
+++ b/spec/models/board_project_recent_visit_spec.rb
@@ -50,15 +50,25 @@ describe BoardProjectRecentVisit do
end
describe '#latest' do
- it 'returns the most recent visited' do
- board2 = create(:board, project: project)
- board3 = create(:board, project: project)
+ def create_visit(time)
+ create :board_project_recent_visit, project: project, user: user, updated_at: time
+ end
- create :board_project_recent_visit, project: board.project, board: board, user: user, updated_at: 7.days.ago
- create :board_project_recent_visit, project: board2.project, board: board2, user: user, updated_at: 5.days.ago
- recent = create :board_project_recent_visit, project: board3.project, board: board3, user: user, updated_at: 1.day.ago
+ it 'returns the most recent visited' do
+ create_visit(7.days.ago)
+ create_visit(5.days.ago)
+ recent = create_visit(1.day.ago)
expect(described_class.latest(user, project)).to eq recent
end
+
+ it 'returns last 3 visited boards' do
+ create_visit(7.days.ago)
+ visit1 = create_visit(3.days.ago)
+ visit2 = create_visit(2.days.ago)
+ visit3 = create_visit(5.days.ago)
+
+ expect(described_class.latest(user, project, count: 3)).to eq([visit2, visit1, visit3])
+ end
end
end
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index 741cdfef1a5..b5ec8991720 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -22,4 +22,19 @@ describe Ci::Bridge do
expect(status).to be_a Gitlab::Ci::Status::Success
end
end
+
+ describe '#scoped_variables_hash' do
+ it 'returns a hash representing variables' do
+ variables = %w[
+ CI_JOB_NAME CI_JOB_STAGE CI_COMMIT_SHA CI_COMMIT_SHORT_SHA
+ CI_COMMIT_BEFORE_SHA CI_COMMIT_REF_NAME CI_COMMIT_REF_SLUG
+ CI_PROJECT_ID CI_PROJECT_NAME CI_PROJECT_PATH
+ CI_PROJECT_PATH_SLUG CI_PROJECT_NAMESPACE CI_PIPELINE_IID
+ CI_CONFIG_PATH CI_PIPELINE_SOURCE CI_COMMIT_MESSAGE
+ CI_COMMIT_TITLE CI_COMMIT_DESCRIPTION
+ ]
+
+ expect(bridge.scoped_variables_hash.keys).to include(*variables)
+ end
+ end
end
diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb
index 519968b9e48..016a5899eef 100644
--- a/spec/models/ci/build_metadata_spec.rb
+++ b/spec/models/ci/build_metadata_spec.rb
@@ -13,12 +13,12 @@ describe Ci::BuildMetadata do
end
let(:build) { create(:ci_build, pipeline: pipeline) }
- let(:build_metadata) { build.metadata }
+ let(:metadata) { build.metadata }
it_behaves_like 'having unique enum values'
describe '#update_timeout_state' do
- subject { build_metadata }
+ subject { metadata }
context 'when runner is not assigned to the job' do
it "doesn't change timeout value" do
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index fe7f5f8e1e3..fc75d3e23fb 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -23,6 +23,7 @@ describe Ci::Build do
it { is_expected.to validate_presence_of(:ref) }
it { is_expected.to respond_to(:has_trace?) }
it { is_expected.to respond_to(:trace) }
+ it { is_expected.to delegate_method(:merge_request_event?).to(:pipeline) }
it { is_expected.to be_a(ArtifactMigratable) }
@@ -1457,8 +1458,24 @@ describe Ci::Build do
context 'with retries max config option' do
subject { create(:ci_build, options: { retry: { max: 1 } }) }
- it 'returns the number of configured max retries' do
- expect(subject.retries_max).to eq 1
+ context 'when build_metadata_config is set' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: true)
+ end
+
+ it 'returns the number of configured max retries' do
+ expect(subject.retries_max).to eq 1
+ end
+ end
+
+ context 'when build_metadata_config is not set' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: false)
+ end
+
+ it 'returns the number of configured max retries' do
+ expect(subject.retries_max).to eq 1
+ end
end
end
@@ -1679,14 +1696,49 @@ describe Ci::Build do
let(:options) do
{
image: "ruby:2.1",
- services: [
- "postgres"
- ]
+ services: ["postgres"],
+ script: ["ls -a"]
}
end
it 'contains options' do
- expect(build.options).to eq(options)
+ expect(build.options).to eq(options.stringify_keys)
+ end
+
+ it 'allows to access with keys' do
+ expect(build.options[:image]).to eq('ruby:2.1')
+ end
+
+ it 'allows to access with strings' do
+ expect(build.options['image']).to eq('ruby:2.1')
+ end
+
+ context 'when ci_build_metadata_config is set' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: true)
+ end
+
+ it 'persist data in build metadata' do
+ expect(build.metadata.read_attribute(:config_options)).to eq(options.stringify_keys)
+ end
+
+ it 'does not persist data in build' do
+ expect(build.read_attribute(:options)).to be_nil
+ end
+ end
+
+ context 'when ci_build_metadata_config is disabled' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: false)
+ end
+
+ it 'persist data in build' do
+ expect(build.read_attribute(:options)).to eq(options.symbolize_keys)
+ end
+
+ it 'does not persist data in build metadata' do
+ expect(build.metadata.read_attribute(:config_options)).to be_nil
+ end
end
end
@@ -1793,6 +1845,26 @@ describe Ci::Build do
context 'when there is no environment' do
it { is_expected.to be_nil }
end
+
+ context 'when build has a start environment' do
+ let(:build) { create(:ci_build, :deploy_to_production, pipeline: pipeline) }
+
+ it 'does not expand environment name' do
+ expect(build).not_to receive(:expanded_environment_name)
+
+ subject
+ end
+ end
+
+ context 'when build has a stop environment' do
+ let(:build) { create(:ci_build, :stop_review_app, pipeline: pipeline) }
+
+ it 'expands environment name' do
+ expect(build).to receive(:expanded_environment_name)
+
+ subject
+ end
+ end
end
describe '#play' do
@@ -2030,56 +2102,6 @@ describe Ci::Build do
end
end
- describe '#when' do
- subject { build.when }
-
- context 'when `when` is undefined' do
- before do
- build.when = nil
- end
-
- context 'use from gitlab-ci.yml' do
- let(:project) { create(:project, :repository) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
-
- before do
- stub_ci_pipeline_yaml_file(config)
- end
-
- context 'when config is not found' do
- let(:config) { nil }
-
- it { is_expected.to eq('on_success') }
- end
-
- context 'when config does not have a questioned job' do
- let(:config) do
- YAML.dump({
- test_other: {
- script: 'Hello World'
- }
- })
- end
-
- it { is_expected.to eq('on_success') }
- end
-
- context 'when config has `when`' do
- let(:config) do
- YAML.dump({
- test: {
- script: 'Hello World',
- when: 'always'
- }
- })
- end
-
- it { is_expected.to eq('always') }
- end
- end
- end
- end
-
describe '#variables' do
let(:container_registry_enabled) { false }
@@ -2092,52 +2114,55 @@ describe Ci::Build do
context 'returns variables' do
let(:predefined_variables) do
[
- { key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true },
- { key: 'CI_PIPELINE_URL', value: project.web_url + "/pipelines/#{pipeline.id}", public: true },
- { key: 'CI_JOB_ID', value: build.id.to_s, public: true },
- { key: 'CI_JOB_URL', value: project.web_url + "/-/jobs/#{build.id}", public: true },
- { key: 'CI_JOB_TOKEN', value: 'my-token', public: false },
- { key: 'CI_BUILD_ID', value: build.id.to_s, public: true },
- { key: 'CI_BUILD_TOKEN', value: 'my-token', public: false },
- { key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true },
- { key: 'CI_REGISTRY_PASSWORD', value: 'my-token', public: false },
- { key: 'CI_REPOSITORY_URL', value: build.repo_url, public: false },
- { key: 'CI', value: 'true', public: true },
- { key: 'GITLAB_CI', value: 'true', public: true },
- { key: 'GITLAB_FEATURES', value: project.licensed_features.join(','), public: true },
- { key: 'CI_SERVER_NAME', value: 'GitLab', public: true },
- { key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true },
- { key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s, public: true },
- { key: 'CI_SERVER_VERSION_MINOR', value: Gitlab.version_info.minor.to_s, public: true },
- { key: 'CI_SERVER_VERSION_PATCH', value: Gitlab.version_info.patch.to_s, public: true },
- { key: 'CI_SERVER_REVISION', value: Gitlab.revision, public: true },
- { key: 'CI_JOB_NAME', value: 'test', public: true },
- { key: 'CI_JOB_STAGE', value: 'test', public: true },
- { key: 'CI_COMMIT_SHA', value: build.sha, public: true },
- { key: 'CI_COMMIT_SHORT_SHA', value: build.short_sha, public: true },
- { key: 'CI_COMMIT_BEFORE_SHA', value: build.before_sha, public: true },
- { key: 'CI_COMMIT_REF_NAME', value: build.ref, public: true },
- { key: 'CI_COMMIT_REF_SLUG', value: build.ref_slug, public: true },
- { key: 'CI_NODE_TOTAL', value: '1', public: true },
- { key: 'CI_BUILD_REF', value: build.sha, public: true },
- { key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true },
- { key: 'CI_BUILD_REF_NAME', value: build.ref, public: true },
- { key: 'CI_BUILD_REF_SLUG', value: build.ref_slug, public: true },
- { key: 'CI_BUILD_NAME', value: 'test', public: true },
- { key: 'CI_BUILD_STAGE', value: 'test', public: true },
- { key: 'CI_PROJECT_ID', value: project.id.to_s, public: true },
- { key: 'CI_PROJECT_NAME', value: project.path, public: true },
- { key: 'CI_PROJECT_PATH', value: project.full_path, public: true },
- { key: 'CI_PROJECT_PATH_SLUG', value: project.full_path_slug, public: true },
- { key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true },
- { key: 'CI_PROJECT_URL', value: project.web_url, public: true },
- { key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true },
- { key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true },
- { key: 'CI_CONFIG_PATH', value: pipeline.ci_yaml_file_path, public: true },
- { key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true },
- { key: 'CI_COMMIT_MESSAGE', value: pipeline.git_commit_message, public: true },
- { key: 'CI_COMMIT_TITLE', value: pipeline.git_commit_title, public: true },
- { key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true }
+ { key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true, masked: false },
+ { key: 'CI_PIPELINE_URL', value: project.web_url + "/pipelines/#{pipeline.id}", public: true, masked: false },
+ { key: 'CI_JOB_ID', value: build.id.to_s, public: true, masked: false },
+ { key: 'CI_JOB_URL', value: project.web_url + "/-/jobs/#{build.id}", public: true, masked: false },
+ { key: 'CI_JOB_TOKEN', value: 'my-token', public: false, masked: false },
+ { key: 'CI_BUILD_ID', value: build.id.to_s, public: true, masked: false },
+ { key: 'CI_BUILD_TOKEN', value: 'my-token', public: false, masked: false },
+ { key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true, masked: false },
+ { key: 'CI_REGISTRY_PASSWORD', value: 'my-token', public: false, masked: false },
+ { key: 'CI_REPOSITORY_URL', value: build.repo_url, public: false, masked: false },
+ { key: 'CI', value: 'true', public: true, masked: false },
+ { key: 'GITLAB_CI', value: 'true', public: true, masked: false },
+ { key: 'GITLAB_FEATURES', value: project.licensed_features.join(','), public: true, masked: false },
+ { key: 'CI_SERVER_NAME', value: 'GitLab', public: true, masked: false },
+ { key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true, masked: false },
+ { key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s, public: true, masked: false },
+ { key: 'CI_SERVER_VERSION_MINOR', value: Gitlab.version_info.minor.to_s, public: true, masked: false },
+ { key: 'CI_SERVER_VERSION_PATCH', value: Gitlab.version_info.patch.to_s, public: true, masked: false },
+ { key: 'CI_SERVER_REVISION', value: Gitlab.revision, public: true, masked: false },
+ { key: 'CI_JOB_NAME', value: 'test', public: true, masked: false },
+ { key: 'CI_JOB_STAGE', value: 'test', public: true, masked: false },
+ { key: 'CI_COMMIT_SHA', value: build.sha, public: true, masked: false },
+ { key: 'CI_COMMIT_SHORT_SHA', value: build.short_sha, public: true, masked: false },
+ { key: 'CI_COMMIT_BEFORE_SHA', value: build.before_sha, public: true, masked: false },
+ { key: 'CI_COMMIT_REF_NAME', value: build.ref, public: true, masked: false },
+ { key: 'CI_COMMIT_REF_SLUG', value: build.ref_slug, public: true, masked: false },
+ { key: 'CI_NODE_TOTAL', value: '1', public: true, masked: false },
+ { key: 'CI_BUILD_REF', value: build.sha, public: true, masked: false },
+ { key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true, masked: false },
+ { key: 'CI_BUILD_REF_NAME', value: build.ref, public: true, masked: false },
+ { key: 'CI_BUILD_REF_SLUG', value: build.ref_slug, public: true, masked: false },
+ { key: 'CI_BUILD_NAME', value: 'test', public: true, masked: false },
+ { key: 'CI_BUILD_STAGE', value: 'test', public: true, masked: false },
+ { key: 'CI_PROJECT_ID', value: project.id.to_s, public: true, masked: false },
+ { key: 'CI_PROJECT_NAME', value: project.path, public: true, masked: false },
+ { key: 'CI_PROJECT_PATH', value: project.full_path, public: true, masked: false },
+ { key: 'CI_PROJECT_PATH_SLUG', value: project.full_path_slug, public: true, masked: false },
+ { key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true, masked: false },
+ { key: 'CI_PROJECT_URL', value: project.web_url, public: true, masked: false },
+ { key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true, masked: false },
+ { key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host, public: true, masked: false },
+ { key: 'CI_PAGES_URL', value: project.pages_url, public: true, masked: false },
+ { key: 'CI_API_V4_URL', value: 'http://localhost/api/v4', public: true, masked: false },
+ { key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true, masked: false },
+ { key: 'CI_CONFIG_PATH', value: pipeline.ci_yaml_file_path, public: true, masked: false },
+ { key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true, masked: false },
+ { key: 'CI_COMMIT_MESSAGE', value: pipeline.git_commit_message, public: true, masked: false },
+ { key: 'CI_COMMIT_TITLE', value: pipeline.git_commit_title, public: true, masked: false },
+ { key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true, masked: false }
]
end
@@ -2148,68 +2173,12 @@ describe Ci::Build do
it { is_expected.to include(*predefined_variables) }
- context 'when yaml variables are undefined' do
- let(:pipeline) do
- create(:ci_pipeline, project: project,
- sha: project.commit.id,
- ref: project.default_branch)
- end
-
- before do
- build.yaml_variables = nil
- end
-
- context 'use from gitlab-ci.yml' do
- before do
- stub_ci_pipeline_yaml_file(config)
- end
-
- context 'when config is not found' do
- let(:config) { nil }
-
- it { is_expected.to include(*predefined_variables) }
- end
-
- context 'when config does not have a questioned job' do
- let(:config) do
- YAML.dump({
- test_other: {
- script: 'Hello World'
- }
- })
- end
-
- it { is_expected.to include(*predefined_variables) }
- end
-
- context 'when config has variables' do
- let(:config) do
- YAML.dump({
- test: {
- script: 'Hello World',
- variables: {
- KEY: 'value'
- }
- }
- })
- end
-
- let(:variables) do
- [{ key: 'KEY', value: 'value', public: true }]
- end
-
- it { is_expected.to include(*predefined_variables) }
- it { is_expected.to include(*variables) }
- end
- end
- end
-
describe 'variables ordering' do
context 'when variables hierarchy is stubbed' do
- let(:build_pre_var) { { key: 'build', value: 'value', public: true } }
- let(:project_pre_var) { { key: 'project', value: 'value', public: true } }
- let(:pipeline_pre_var) { { key: 'pipeline', value: 'value', public: true } }
- let(:build_yaml_var) { { key: 'yaml', value: 'value', public: true } }
+ let(:build_pre_var) { { key: 'build', value: 'value', public: true, masked: false } }
+ let(:project_pre_var) { { key: 'project', value: 'value', public: true, masked: false } }
+ let(:pipeline_pre_var) { { key: 'pipeline', value: 'value', public: true, masked: false } }
+ let(:build_yaml_var) { { key: 'yaml', value: 'value', public: true, masked: false } }
before do
allow(build).to receive(:predefined_variables) { [build_pre_var] }
@@ -2231,7 +2200,7 @@ describe Ci::Build do
project_pre_var,
pipeline_pre_var,
build_yaml_var,
- { key: 'secret', value: 'value', public: false }])
+ { key: 'secret', value: 'value', public: false, masked: false }])
end
end
@@ -2264,10 +2233,10 @@ describe Ci::Build do
context 'when build has user' do
let(:user_variables) do
[
- { key: 'GITLAB_USER_ID', value: user.id.to_s, public: true },
- { key: 'GITLAB_USER_EMAIL', value: user.email, public: true },
- { key: 'GITLAB_USER_LOGIN', value: user.username, public: true },
- { key: 'GITLAB_USER_NAME', value: user.name, public: true }
+ { key: 'GITLAB_USER_ID', value: user.id.to_s, public: true, masked: false },
+ { key: 'GITLAB_USER_EMAIL', value: user.email, public: true, masked: false },
+ { key: 'GITLAB_USER_LOGIN', value: user.username, public: true, masked: false },
+ { key: 'GITLAB_USER_NAME', value: user.name, public: true, masked: false }
]
end
@@ -2281,8 +2250,8 @@ describe Ci::Build do
context 'when build has an environment' do
let(:environment_variables) do
[
- { key: 'CI_ENVIRONMENT_NAME', value: 'production', public: true },
- { key: 'CI_ENVIRONMENT_SLUG', value: 'prod-slug', public: true }
+ { key: 'CI_ENVIRONMENT_NAME', value: 'production', public: true, masked: false },
+ { key: 'CI_ENVIRONMENT_SLUG', value: 'prod-slug', public: true, masked: false }
]
end
@@ -2317,7 +2286,7 @@ describe Ci::Build do
before do
environment_variables <<
- { key: 'CI_ENVIRONMENT_URL', value: url, public: true }
+ { key: 'CI_ENVIRONMENT_URL', value: url, public: true, masked: false }
end
context 'when the URL was set from the job' do
@@ -2354,7 +2323,7 @@ describe Ci::Build do
end
let(:manual_variable) do
- { key: 'CI_JOB_MANUAL', value: 'true', public: true }
+ { key: 'CI_JOB_MANUAL', value: 'true', public: true, masked: false }
end
it { is_expected.to include(manual_variable) }
@@ -2362,7 +2331,7 @@ describe Ci::Build do
context 'when build is for tag' do
let(:tag_variable) do
- { key: 'CI_COMMIT_TAG', value: 'master', public: true }
+ { key: 'CI_COMMIT_TAG', value: 'master', public: true, masked: false }
end
before do
@@ -2374,7 +2343,7 @@ describe Ci::Build do
context 'when CI variable is defined' do
let(:ci_variable) do
- { key: 'SECRET_KEY', value: 'secret_value', public: false }
+ { key: 'SECRET_KEY', value: 'secret_value', public: false, masked: false }
end
before do
@@ -2386,8 +2355,10 @@ describe Ci::Build do
end
context 'when protected variable is defined' do
+ let(:ref) { Gitlab::Git::BRANCH_REF_PREFIX + build.ref }
+
let(:protected_variable) do
- { key: 'PROTECTED_KEY', value: 'protected_value', public: false }
+ { key: 'PROTECTED_KEY', value: 'protected_value', public: false, masked: false }
end
before do
@@ -2398,7 +2369,7 @@ describe Ci::Build do
context 'when the branch is protected' do
before do
- allow(build.project).to receive(:protected_for?).with(build.ref).and_return(true)
+ allow(build.project).to receive(:protected_for?).with(ref).and_return(true)
end
it { is_expected.to include(protected_variable) }
@@ -2406,7 +2377,7 @@ describe Ci::Build do
context 'when the tag is protected' do
before do
- allow(build.project).to receive(:protected_for?).with(build.ref).and_return(true)
+ allow(build.project).to receive(:protected_for?).with(ref).and_return(true)
end
it { is_expected.to include(protected_variable) }
@@ -2419,7 +2390,7 @@ describe Ci::Build do
context 'when group CI variable is defined' do
let(:ci_variable) do
- { key: 'SECRET_KEY', value: 'secret_value', public: false }
+ { key: 'SECRET_KEY', value: 'secret_value', public: false, masked: false }
end
before do
@@ -2431,8 +2402,10 @@ describe Ci::Build do
end
context 'when group protected variable is defined' do
+ let(:ref) { Gitlab::Git::BRANCH_REF_PREFIX + build.ref }
+
let(:protected_variable) do
- { key: 'PROTECTED_KEY', value: 'protected_value', public: false }
+ { key: 'PROTECTED_KEY', value: 'protected_value', public: false, masked: false }
end
before do
@@ -2443,7 +2416,7 @@ describe Ci::Build do
context 'when the branch is protected' do
before do
- allow(build.project).to receive(:protected_for?).with(build.ref).and_return(true)
+ allow(build.project).to receive(:protected_for?).with(ref).and_return(true)
end
it { is_expected.to include(protected_variable) }
@@ -2451,7 +2424,7 @@ describe Ci::Build do
context 'when the tag is protected' do
before do
- allow(build.project).to receive(:protected_for?).with(build.ref).and_return(true)
+ allow(build.project).to receive(:protected_for?).with(ref).and_return(true)
end
it { is_expected.to include(protected_variable) }
@@ -2471,11 +2444,11 @@ describe Ci::Build do
let(:trigger_request) { create(:ci_trigger_request, pipeline: pipeline, trigger: trigger) }
let(:user_trigger_variable) do
- { key: 'TRIGGER_KEY_1', value: 'TRIGGER_VALUE_1', public: false }
+ { key: 'TRIGGER_KEY_1', value: 'TRIGGER_VALUE_1', public: false, masked: false }
end
let(:predefined_trigger_variable) do
- { key: 'CI_PIPELINE_TRIGGERED', value: 'true', public: true }
+ { key: 'CI_PIPELINE_TRIGGERED', value: 'true', public: true, masked: false }
end
before do
@@ -2507,7 +2480,7 @@ describe Ci::Build do
context 'when pipeline has a variable' do
let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline) }
- it { is_expected.to include(pipeline_variable.to_runner_variable) }
+ it { is_expected.to include(key: pipeline_variable.key, value: pipeline_variable.value, public: false, masked: false) }
end
context 'when a job was triggered by a pipeline schedule' do
@@ -2524,16 +2497,16 @@ describe Ci::Build do
pipeline_schedule.reload
end
- it { is_expected.to include(pipeline_schedule_variable.to_runner_variable) }
+ it { is_expected.to include(key: pipeline_schedule_variable.key, value: pipeline_schedule_variable.value, public: false, masked: false) }
end
context 'when container registry is enabled' do
let(:container_registry_enabled) { true }
let(:ci_registry) do
- { key: 'CI_REGISTRY', value: 'registry.example.com', public: true }
+ { key: 'CI_REGISTRY', value: 'registry.example.com', public: true, masked: false }
end
let(:ci_registry_image) do
- { key: 'CI_REGISTRY_IMAGE', value: project.container_registry_url, public: true }
+ { key: 'CI_REGISTRY_IMAGE', value: project.container_registry_url, public: true, masked: false }
end
context 'and is disabled for project' do
@@ -2562,13 +2535,13 @@ describe Ci::Build do
build.update(runner: runner)
end
- it { is_expected.to include({ key: 'CI_RUNNER_ID', value: runner.id.to_s, public: true }) }
- it { is_expected.to include({ key: 'CI_RUNNER_DESCRIPTION', value: 'description', public: true }) }
- it { is_expected.to include({ key: 'CI_RUNNER_TAGS', value: 'docker, linux', public: true }) }
+ it { is_expected.to include({ key: 'CI_RUNNER_ID', value: runner.id.to_s, public: true, masked: false }) }
+ it { is_expected.to include({ key: 'CI_RUNNER_DESCRIPTION', value: 'description', public: true, masked: false }) }
+ it { is_expected.to include({ key: 'CI_RUNNER_TAGS', value: 'docker, linux', public: true, masked: false }) }
end
context 'when build is for a deployment' do
- let(:deployment_variable) { { key: 'KUBERNETES_TOKEN', value: 'TOKEN', public: false } }
+ let(:deployment_variable) { { key: 'KUBERNETES_TOKEN', value: 'TOKEN', public: false, masked: false } }
before do
build.environment = 'production'
@@ -2582,7 +2555,7 @@ describe Ci::Build do
end
context 'when project has custom CI config path' do
- let(:ci_config_path) { { key: 'CI_CONFIG_PATH', value: 'custom', public: true } }
+ let(:ci_config_path) { { key: 'CI_CONFIG_PATH', value: 'custom', public: true, masked: false } }
before do
project.update(ci_config_path: 'custom')
@@ -2599,7 +2572,7 @@ describe Ci::Build do
it "includes AUTO_DEVOPS_DOMAIN" do
is_expected.to include(
- { key: 'AUTO_DEVOPS_DOMAIN', value: 'example.com', public: true })
+ { key: 'AUTO_DEVOPS_DOMAIN', value: 'example.com', public: true, masked: false })
end
end
@@ -2610,7 +2583,7 @@ describe Ci::Build do
it "includes AUTO_DEVOPS_DOMAIN" do
is_expected.not_to include(
- { key: 'AUTO_DEVOPS_DOMAIN', value: 'example.com', public: true })
+ { key: 'AUTO_DEVOPS_DOMAIN', value: 'example.com', public: true, masked: false })
end
end
end
@@ -2625,9 +2598,9 @@ describe Ci::Build do
variables = subject.reverse.uniq { |variable| variable[:key] }.reverse
expect(variables)
- .not_to include(key: 'MYVAR', value: 'myvar', public: true)
+ .not_to include(key: 'MYVAR', value: 'myvar', public: true, masked: false)
expect(variables)
- .to include(key: 'MYVAR', value: 'pipeline value', public: false)
+ .to include(key: 'MYVAR', value: 'pipeline value', public: false, masked: false)
end
end
@@ -2643,13 +2616,13 @@ describe Ci::Build do
it 'includes CI_NODE_INDEX' do
is_expected.to include(
- { key: 'CI_NODE_INDEX', value: index.to_s, public: true }
+ { key: 'CI_NODE_INDEX', value: index.to_s, public: true, masked: false }
)
end
it 'includes correct CI_NODE_TOTAL' do
is_expected.to include(
- { key: 'CI_NODE_TOTAL', value: total.to_s, public: true }
+ { key: 'CI_NODE_TOTAL', value: total.to_s, public: true, masked: false }
)
end
end
@@ -2668,7 +2641,7 @@ describe Ci::Build do
it 'returns static predefined variables' do
expect(build.variables.size).to be >= 28
expect(build.variables)
- .to include(key: 'CI_COMMIT_REF_NAME', value: 'feature', public: true)
+ .to include(key: 'CI_COMMIT_REF_NAME', value: 'feature', public: true, masked: false)
expect(build).not_to be_persisted
end
end
@@ -2678,8 +2651,8 @@ describe Ci::Build do
let(:deploy_token_variables) do
[
- { key: 'CI_DEPLOY_USER', value: deploy_token.username, public: true },
- { key: 'CI_DEPLOY_PASSWORD', value: deploy_token.token, public: false }
+ { key: 'CI_DEPLOY_USER', value: deploy_token.username, public: true, masked: false },
+ { key: 'CI_DEPLOY_PASSWORD', value: deploy_token.token, public: false, masked: false }
]
end
@@ -2738,7 +2711,7 @@ describe Ci::Build do
end
expect(variables)
- .to include(key: 'CI_COMMIT_REF_NAME', value: 'feature', public: true)
+ .to include(key: 'CI_COMMIT_REF_NAME', value: 'feature', public: true, masked: false)
end
it 'does not return prohibited variables' do
@@ -2761,6 +2734,122 @@ describe Ci::Build do
end
end
+ describe '#secret_group_variables' do
+ subject { build.secret_group_variables }
+
+ let!(:variable) { create(:ci_group_variable, protected: true, group: group) }
+
+ context 'when ref is branch' do
+ let(:build) { create(:ci_build, ref: 'master', tag: false, project: project) }
+
+ context 'when ref is protected' do
+ before do
+ create(:protected_branch, :developers_can_merge, name: 'master', project: project)
+ end
+
+ it { is_expected.to include(variable) }
+ end
+
+ context 'when ref is not protected' do
+ it { is_expected.not_to include(variable) }
+ end
+ end
+
+ context 'when ref is tag' do
+ let(:build) { create(:ci_build, ref: 'v1.1.0', tag: true, project: project) }
+
+ context 'when ref is protected' do
+ before do
+ create(:protected_tag, project: project, name: 'v*')
+ end
+
+ it { is_expected.to include(variable) }
+ end
+
+ context 'when ref is not protected' do
+ it { is_expected.not_to include(variable) }
+ end
+ end
+
+ context 'when ref is merge request' do
+ let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) }
+ let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:build) { create(:ci_build, ref: merge_request.source_branch, tag: false, pipeline: pipeline, project: project) }
+
+ context 'when ref is protected' do
+ before do
+ create(:protected_branch, :developers_can_merge, name: merge_request.source_branch, project: project)
+ end
+
+ it 'does not return protected variables as it is not supported for merge request pipelines' do
+ is_expected.not_to include(variable)
+ end
+ end
+
+ context 'when ref is not protected' do
+ it { is_expected.not_to include(variable) }
+ end
+ end
+ end
+
+ describe '#secret_project_variables' do
+ subject { build.secret_project_variables }
+
+ let!(:variable) { create(:ci_variable, protected: true, project: project) }
+
+ context 'when ref is branch' do
+ let(:build) { create(:ci_build, ref: 'master', tag: false, project: project) }
+
+ context 'when ref is protected' do
+ before do
+ create(:protected_branch, :developers_can_merge, name: 'master', project: project)
+ end
+
+ it { is_expected.to include(variable) }
+ end
+
+ context 'when ref is not protected' do
+ it { is_expected.not_to include(variable) }
+ end
+ end
+
+ context 'when ref is tag' do
+ let(:build) { create(:ci_build, ref: 'v1.1.0', tag: true, project: project) }
+
+ context 'when ref is protected' do
+ before do
+ create(:protected_tag, project: project, name: 'v*')
+ end
+
+ it { is_expected.to include(variable) }
+ end
+
+ context 'when ref is not protected' do
+ it { is_expected.not_to include(variable) }
+ end
+ end
+
+ context 'when ref is merge request' do
+ let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) }
+ let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:build) { create(:ci_build, ref: merge_request.source_branch, tag: false, pipeline: pipeline, project: project) }
+
+ context 'when ref is protected' do
+ before do
+ create(:protected_branch, :developers_can_merge, name: merge_request.source_branch, project: project)
+ end
+
+ it 'does not return protected variables as it is not supported for merge request pipelines' do
+ is_expected.not_to include(variable)
+ end
+ end
+
+ context 'when ref is not protected' do
+ it { is_expected.not_to include(variable) }
+ end
+ end
+ end
+
describe '#scoped_variables_hash' do
context 'when overriding CI variables' do
before do
@@ -2788,29 +2877,53 @@ describe Ci::Build do
end
describe '#yaml_variables' do
- before do
- build.update_attribute(:yaml_variables, variables)
+ let(:build) { create(:ci_build, pipeline: pipeline, yaml_variables: variables) }
+
+ let(:variables) do
+ [
+ { 'key' => :VARIABLE, 'value' => 'my value' },
+ { 'key' => 'VARIABLE2', 'value' => 'my value 2' }
+ ]
end
- context 'when serialized valu is a symbolized hash' do
- let(:variables) do
- [{ key: :VARIABLE, value: 'my value 1' }]
+ shared_examples 'having consistent representation' do
+ it 'allows to access using symbols' do
+ expect(build.reload.yaml_variables.first[:key]).to eq('VARIABLE')
+ expect(build.reload.yaml_variables.first[:value]).to eq('my value')
+ expect(build.reload.yaml_variables.second[:key]).to eq('VARIABLE2')
+ expect(build.reload.yaml_variables.second[:value]).to eq('my value 2')
+ end
+ end
+
+ context 'when ci_build_metadata_config is set' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: true)
+ end
+
+ it_behaves_like 'having consistent representation'
+
+ it 'persist data in build metadata' do
+ expect(build.metadata.read_attribute(:config_variables)).not_to be_nil
end
- it 'keeps symbolizes keys and stringifies variables names' do
- expect(build.yaml_variables)
- .to eq [{ key: 'VARIABLE', value: 'my value 1' }]
+ it 'does not persist data in build' do
+ expect(build.read_attribute(:yaml_variables)).to be_nil
end
end
- context 'when serialized value is a hash with string keys' do
- let(:variables) do
- [{ 'key' => :VARIABLE, 'value' => 'my value 2' }]
+ context 'when ci_build_metadata_config is disabled' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: false)
+ end
+
+ it_behaves_like 'having consistent representation'
+
+ it 'persist data in build' do
+ expect(build.read_attribute(:yaml_variables)).not_to be_nil
end
- it 'symblizes variables hash' do
- expect(build.yaml_variables)
- .to eq [{ key: 'VARIABLE', value: 'my value 2' }]
+ it 'does not persist data in build metadata' do
+ expect(build.metadata.read_attribute(:config_variables)).to be_nil
end
end
end
@@ -2982,7 +3095,7 @@ describe Ci::Build do
end
context 'when build is configured to be retried' do
- subject { create(:ci_build, :running, options: { retry: { max: 3 } }, project: project, user: user) }
+ subject { create(:ci_build, :running, options: { script: ["ls -al"], retry: 3 }, project: project, user: user) }
it 'retries build and assigns the same user to it' do
expect(described_class).to receive(:retry)
@@ -3054,6 +3167,24 @@ describe Ci::Build do
subject.drop!
end
end
+
+ context 'when associated deployment failed to update its status' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+ let!(:deployment) { create(:deployment, deployable: build) }
+
+ before do
+ allow_any_instance_of(Deployment)
+ .to receive(:drop!).and_raise('Unexpected error')
+ end
+
+ it 'can drop the build' do
+ expect(Gitlab::Sentry).to receive(:track_exception)
+
+ expect { build.drop! }.not_to raise_error
+
+ expect(build).to be_failed
+ end
+ end
end
describe '.matches_tag_ids' do
@@ -3471,6 +3602,23 @@ describe Ci::Build do
end
end
+ describe 'degenerate!' do
+ let(:build) { create(:ci_build) }
+
+ subject { build.degenerate! }
+
+ before do
+ build.ensure_metadata
+ end
+
+ it 'drops metadata' do
+ subject
+
+ expect(build.reload).to be_degenerated
+ expect(build.metadata).to be_nil
+ end
+ end
+
describe '#archived?' do
context 'when build is degenerated' do
subject { create(:ci_build, :degenerated) }
@@ -3498,4 +3646,97 @@ describe Ci::Build do
end
end
end
+
+ describe '#read_metadata_attribute' do
+ let(:build) { create(:ci_build, :degenerated) }
+ let(:build_options) { { "key" => "build" } }
+ let(:metadata_options) { { "key" => "metadata" } }
+ let(:default_options) { { "key" => "default" } }
+
+ subject { build.send(:read_metadata_attribute, :options, :config_options, default_options) }
+
+ context 'when build and metadata options is set' do
+ before do
+ build.write_attribute(:options, build_options)
+ build.ensure_metadata.write_attribute(:config_options, metadata_options)
+ end
+
+ it 'prefers build options' do
+ is_expected.to eq(build_options)
+ end
+ end
+
+ context 'when only metadata options is set' do
+ before do
+ build.write_attribute(:options, nil)
+ build.ensure_metadata.write_attribute(:config_options, metadata_options)
+ end
+
+ it 'returns metadata options' do
+ is_expected.to eq(metadata_options)
+ end
+ end
+
+ context 'when none is set' do
+ it 'returns default value' do
+ is_expected.to eq(default_options)
+ end
+ end
+ end
+
+ describe '#write_metadata_attribute' do
+ let(:build) { create(:ci_build, :degenerated) }
+ let(:options) { { "key" => "new options" } }
+ let(:existing_options) { { "key" => "existing options" } }
+
+ subject { build.send(:write_metadata_attribute, :options, :config_options, options) }
+
+ context 'when ci_build_metadata_config is set' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: true)
+ end
+
+ context 'when data in build is already set' do
+ before do
+ build.write_attribute(:options, existing_options)
+ end
+
+ it 'does set metadata options' do
+ subject
+
+ expect(build.metadata.read_attribute(:config_options)).to eq(options)
+ end
+
+ it 'does reset build options' do
+ subject
+
+ expect(build.read_attribute(:options)).to be_nil
+ end
+ end
+ end
+
+ context 'when ci_build_metadata_config is disabled' do
+ before do
+ stub_feature_flags(ci_build_metadata_config: false)
+ end
+
+ context 'when data in build metadata is already set' do
+ before do
+ build.ensure_metadata.write_attribute(:config_options, existing_options)
+ end
+
+ it 'does set metadata options' do
+ subject
+
+ expect(build.read_attribute(:options)).to eq(options)
+ end
+
+ it 'does reset build options' do
+ subject
+
+ expect(build.metadata.read_attribute(:config_options)).to be_nil
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index d214fdf369a..59db347582b 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -171,7 +171,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
shared_examples_for 'Scheduling sidekiq worker to flush data to persist store' do
- context 'when new data fullfilled chunk size' do
+ context 'when new data fulfilled chunk size' do
let(:new_data) { 'a' * described_class::CHUNK_SIZE }
it 'schedules trace chunk flush worker' do
@@ -193,7 +193,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
shared_examples_for 'Scheduling no sidekiq worker' do
- context 'when new data fullfilled chunk size' do
+ context 'when new data fulfilled chunk size' do
let(:new_data) { 'a' * described_class::CHUNK_SIZE }
it 'does not schedule trace chunk flush worker' do
diff --git a/spec/models/ci/group_variable_spec.rb b/spec/models/ci/group_variable_spec.rb
index 1b10501701c..21d96bf3454 100644
--- a/spec/models/ci/group_variable_spec.rb
+++ b/spec/models/ci/group_variable_spec.rb
@@ -5,6 +5,7 @@ describe Ci::GroupVariable do
it { is_expected.to include_module(HasVariable) }
it { is_expected.to include_module(Presentable) }
+ it { is_expected.to include_module(Maskable) }
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:group_id).with_message(/\(\w+\) has already been taken/) }
describe '.unprotected' do
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index b67c6a4cffa..d0b42d103a5 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Ci::Pipeline, :mailer do
+ include ProjectForksHelper
+
let(:user) { create(:user) }
set(:project) { create(:project) }
@@ -22,6 +24,7 @@ describe Ci::Pipeline, :mailer do
it { is_expected.to have_many(:builds) }
it { is_expected.to have_many(:auto_canceled_pipelines) }
it { is_expected.to have_many(:auto_canceled_jobs) }
+ it { is_expected.to have_one(:chat_data) }
it { is_expected.to validate_presence_of(:sha) }
it { is_expected.to validate_presence_of(:status) }
@@ -39,6 +42,29 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '.processables' do
+ before do
+ create(:ci_build, name: 'build', pipeline: pipeline)
+ create(:ci_bridge, name: 'bridge', pipeline: pipeline)
+ create(:commit_status, name: 'commit status', pipeline: pipeline)
+ create(:generic_commit_status, name: 'generic status', pipeline: pipeline)
+ end
+
+ it 'has an association with processable CI/CD entities' do
+ pipeline.processables.pluck('name').yield_self do |processables|
+ expect(processables).to match_array %w[build bridge]
+ end
+ end
+
+ it 'makes it possible to append a new processable' do
+ pipeline.processables << build(:ci_bridge)
+
+ pipeline.save!
+
+ expect(pipeline.processables.reload.count).to eq 3
+ end
+ end
+
describe '.sort_by_merge_request_pipelines' do
subject { described_class.sort_by_merge_request_pipelines }
@@ -54,11 +80,11 @@ describe Ci::Pipeline, :mailer do
context 'when merge request pipelines exist' do
let!(:merge_request_pipeline_1) do
- create(:ci_pipeline, source: :merge_request, merge_request: merge_request)
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let!(:merge_request_pipeline_2) do
- create(:ci_pipeline, source: :merge_request, merge_request: merge_request)
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let(:merge_request) do
@@ -80,11 +106,11 @@ describe Ci::Pipeline, :mailer do
let!(:branch_pipeline_2) { create(:ci_pipeline, source: :push) }
let!(:merge_request_pipeline_1) do
- create(:ci_pipeline, source: :merge_request, merge_request: merge_request)
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let!(:merge_request_pipeline_2) do
- create(:ci_pipeline, source: :merge_request, merge_request: merge_request)
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let(:merge_request) do
@@ -104,11 +130,137 @@ describe Ci::Pipeline, :mailer do
end
end
- describe '.merge_request' do
- subject { described_class.merge_request }
+ describe '.detached_merge_request_pipelines' do
+ subject { described_class.detached_merge_request_pipelines(merge_request) }
+
+ let!(:pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha)
+ end
+
+ let(:merge_request) { create(:merge_request) }
+ let(:target_sha) { nil }
+
+ it 'returns detached merge request pipelines' do
+ is_expected.to eq([pipeline])
+ end
+
+ context 'when target sha exists' do
+ let(:target_sha) { merge_request.target_branch_sha }
+
+ it 'returns empty array' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ describe '#detached_merge_request_pipeline?' do
+ subject { pipeline.detached_merge_request_pipeline? }
+
+ let!(:pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha)
+ end
+
+ let(:merge_request) { create(:merge_request) }
+ let(:target_sha) { nil }
+
+ it { is_expected.to be_truthy }
+
+ context 'when target sha exists' do
+ let(:target_sha) { merge_request.target_branch_sha }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ describe '.merge_request_pipelines' do
+ subject { described_class.merge_request_pipelines(merge_request) }
+
+ let!(:pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha)
+ end
+
+ let(:merge_request) { create(:merge_request) }
+ let(:target_sha) { merge_request.target_branch_sha }
+
+ it 'returns merge pipelines' do
+ is_expected.to eq([pipeline])
+ end
+
+ context 'when target sha is empty' do
+ let(:target_sha) { nil }
+
+ it 'returns empty array' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ describe '#merge_request_pipeline?' do
+ subject { pipeline.merge_request_pipeline? }
+
+ let!(:pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha)
+ end
+
+ let(:merge_request) { create(:merge_request) }
+ let(:target_sha) { merge_request.target_branch_sha }
+
+ it { is_expected.to be_truthy }
+
+ context 'when target sha is empty' do
+ let(:target_sha) { nil }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ describe '.mergeable_merge_request_pipelines' do
+ subject { described_class.mergeable_merge_request_pipelines(merge_request) }
+
+ let!(:pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha)
+ end
+
+ let(:merge_request) { create(:merge_request) }
+ let(:target_sha) { merge_request.target_branch_sha }
+
+ it 'returns mergeable merge pipelines' do
+ is_expected.to eq([pipeline])
+ end
+
+ context 'when target sha does not point the head of the target branch' do
+ let(:target_sha) { merge_request.diff_head_sha }
+
+ it 'returns empty array' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ describe '#mergeable_merge_request_pipeline?' do
+ subject { pipeline.mergeable_merge_request_pipeline? }
+
+ let!(:pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha)
+ end
+
+ let(:merge_request) { create(:merge_request) }
+ let(:target_sha) { merge_request.target_branch_sha }
+
+ it { is_expected.to be_truthy }
+
+ context 'when target sha does not point the head of the target branch' do
+ let(:target_sha) { merge_request.diff_head_sha }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ describe '.merge_request_event' do
+ subject { described_class.merge_request_event }
context 'when there is a merge request pipeline' do
- let!(:pipeline) { create(:ci_pipeline, source: :merge_request, merge_request: merge_request) }
+ let!(:pipeline) { create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request) }
let(:merge_request) { create(:merge_request) }
it 'returns merge request pipeline first' do
@@ -129,7 +281,7 @@ describe Ci::Pipeline, :mailer do
let(:pipeline) { build(:ci_pipeline, source: source, merge_request: merge_request) }
context 'when source is merge request' do
- let(:source) { :merge_request }
+ let(:source) { :merge_request_event }
context 'when merge request is specified' do
let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_project: project, target_branch: 'master') }
@@ -353,7 +505,7 @@ describe Ci::Pipeline, :mailer do
context 'when source is merge request' do
let(:pipeline) do
- create(:ci_pipeline, source: :merge_request, merge_request: merge_request)
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let(:merge_request) do
@@ -361,9 +513,16 @@ describe Ci::Pipeline, :mailer do
source_project: project,
source_branch: 'feature',
target_project: project,
- target_branch: 'master')
+ target_branch: 'master',
+ assignee: assignee,
+ milestone: milestone,
+ labels: labels)
end
+ let(:assignee) { create(:user) }
+ let(:milestone) { create(:milestone, project: project) }
+ let(:labels) { create_list(:label, 2) }
+
it 'exposes merge request pipeline variables' do
expect(subject.to_hash)
.to include(
@@ -374,10 +533,16 @@ describe Ci::Pipeline, :mailer do
'CI_MERGE_REQUEST_PROJECT_PATH' => merge_request.project.full_path,
'CI_MERGE_REQUEST_PROJECT_URL' => merge_request.project.web_url,
'CI_MERGE_REQUEST_TARGET_BRANCH_NAME' => merge_request.target_branch.to_s,
+ 'CI_MERGE_REQUEST_TARGET_BRANCH_SHA' => pipeline.target_sha.to_s,
'CI_MERGE_REQUEST_SOURCE_PROJECT_ID' => merge_request.source_project.id.to_s,
'CI_MERGE_REQUEST_SOURCE_PROJECT_PATH' => merge_request.source_project.full_path,
'CI_MERGE_REQUEST_SOURCE_PROJECT_URL' => merge_request.source_project.web_url,
- 'CI_MERGE_REQUEST_SOURCE_BRANCH_NAME' => merge_request.source_branch.to_s)
+ 'CI_MERGE_REQUEST_SOURCE_BRANCH_NAME' => merge_request.source_branch.to_s,
+ 'CI_MERGE_REQUEST_SOURCE_BRANCH_SHA' => pipeline.source_sha.to_s,
+ 'CI_MERGE_REQUEST_TITLE' => merge_request.title,
+ 'CI_MERGE_REQUEST_ASSIGNEES' => assignee.username,
+ 'CI_MERGE_REQUEST_MILESTONE' => milestone.title,
+ 'CI_MERGE_REQUEST_LABELS' => labels.map(&:title).join(','))
end
context 'when source project does not exist' do
@@ -393,10 +558,38 @@ describe Ci::Pipeline, :mailer do
CI_MERGE_REQUEST_SOURCE_BRANCH_NAME])
end
end
+
+ context 'without assignee' do
+ let(:assignee) { nil }
+
+ it 'does not expose assignee variable' do
+ expect(subject.to_hash.keys).not_to include('CI_MERGE_REQUEST_ASSIGNEES')
+ end
+ end
+
+ context 'without milestone' do
+ let(:milestone) { nil }
+
+ it 'does not expose milestone variable' do
+ expect(subject.to_hash.keys).not_to include('CI_MERGE_REQUEST_MILESTONE')
+ end
+ end
+
+ context 'without labels' do
+ let(:labels) { [] }
+
+ it 'does not expose labels variable' do
+ expect(subject.to_hash.keys).not_to include('CI_MERGE_REQUEST_LABELS')
+ end
+ end
end
end
describe '#protected_ref?' do
+ before do
+ pipeline.project = create(:project, :repository)
+ end
+
it 'delegates method to project' do
expect(pipeline).not_to be_protected_ref
end
@@ -939,7 +1132,7 @@ describe Ci::Pipeline, :mailer do
context 'when source is merge request' do
let(:pipeline) do
- create(:ci_pipeline, source: :merge_request, merge_request: merge_request)
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let(:merge_request) do
@@ -989,7 +1182,7 @@ describe Ci::Pipeline, :mailer do
context 'when ref is merge request' do
let(:pipeline) do
create(:ci_pipeline,
- source: :merge_request,
+ source: :merge_request_event,
merge_request: merge_request)
end
@@ -1145,8 +1338,26 @@ describe Ci::Pipeline, :mailer do
pipeline.update_column(:before_sha, Gitlab::Git::BLANK_SHA)
end
- it 'raises an error' do
- expect { pipeline.modified_paths }.to raise_error(ArgumentError)
+ it 'returns nil' do
+ expect(pipeline.modified_paths).to be_nil
+ end
+ end
+
+ context 'when source is merge request' do
+ let(:pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
+ end
+
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: project,
+ source_branch: 'feature',
+ target_project: project,
+ target_branch: 'master')
+ end
+
+ it 'returns merge request modified paths' do
+ expect(pipeline.modified_paths).to match(merge_request.modified_paths)
end
end
end
@@ -2041,7 +2252,7 @@ describe Ci::Pipeline, :mailer do
end
end
- describe "#merge_requests" do
+ describe "#merge_requests_as_head_pipeline" do
let(:project) { create(:project) }
let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: 'a288a022a53a5a944fae87bcec6efc87b7061808') }
@@ -2049,85 +2260,100 @@ describe Ci::Pipeline, :mailer do
allow_any_instance_of(MergeRequest).to receive(:diff_head_sha) { 'a288a022a53a5a944fae87bcec6efc87b7061808' }
merge_request = create(:merge_request, source_project: project, head_pipeline: pipeline, source_branch: pipeline.ref)
- expect(pipeline.merge_requests).to eq([merge_request])
+ expect(pipeline.merge_requests_as_head_pipeline).to eq([merge_request])
end
it "doesn't return merge requests whose source branch doesn't match the pipeline's ref" do
create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master')
- expect(pipeline.merge_requests).to be_empty
+ expect(pipeline.merge_requests_as_head_pipeline).to be_empty
end
it "doesn't return merge requests whose `diff_head_sha` doesn't match the pipeline's SHA" do
create(:merge_request, source_project: project, source_branch: pipeline.ref)
allow_any_instance_of(MergeRequest).to receive(:diff_head_sha) { '97de212e80737a608d939f648d959671fb0a0142b' }
- expect(pipeline.merge_requests).to be_empty
+ expect(pipeline.merge_requests_as_head_pipeline).to be_empty
end
end
describe "#all_merge_requests" do
let(:project) { create(:project) }
- let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master') }
- it "returns all merge requests having the same source branch" do
- merge_request = create(:merge_request, source_project: project, source_branch: pipeline.ref)
+ shared_examples 'a method that returns all merge requests for a given pipeline' do
+ let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: pipeline_project, ref: 'master') }
- expect(pipeline.all_merge_requests).to eq([merge_request])
- end
-
- it "doesn't return merge requests having a different source branch" do
- create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master')
-
- expect(pipeline.all_merge_requests).to be_empty
- end
-
- context 'when there is a merge request pipeline' do
- let(:source_branch) { 'feature' }
- let(:target_branch) { 'master' }
+ it "returns all merge requests having the same source branch" do
+ merge_request = create(:merge_request, source_project: pipeline_project, target_project: project, source_branch: pipeline.ref)
- let!(:pipeline) do
- create(:ci_pipeline,
- source: :merge_request,
- project: project,
- ref: source_branch,
- merge_request: merge_request)
+ expect(pipeline.all_merge_requests).to eq([merge_request])
end
- let(:merge_request) do
- create(:merge_request,
- source_project: project,
- source_branch: source_branch,
- target_project: project,
- target_branch: target_branch)
- end
+ it "doesn't return merge requests having a different source branch" do
+ create(:merge_request, source_project: pipeline_project, target_project: project, source_branch: 'feature', target_branch: 'master')
- it 'returns an associated merge request' do
- expect(pipeline.all_merge_requests).to eq([merge_request])
+ expect(pipeline.all_merge_requests).to be_empty
end
- context 'when there is another merge request pipeline that targets a different branch' do
- let(:target_branch_2) { 'merge-test' }
+ context 'when there is a merge request pipeline' do
+ let(:source_branch) { 'feature' }
+ let(:target_branch) { 'master' }
- let!(:pipeline_2) do
+ let!(:pipeline) do
create(:ci_pipeline,
- source: :merge_request,
- project: project,
+ source: :merge_request_event,
+ project: pipeline_project,
ref: source_branch,
- merge_request: merge_request_2)
+ merge_request: merge_request)
end
- let(:merge_request_2) do
+ let(:merge_request) do
create(:merge_request,
- source_project: project,
+ source_project: pipeline_project,
source_branch: source_branch,
target_project: project,
- target_branch: target_branch_2)
+ target_branch: target_branch)
end
- it 'does not return an associated merge request' do
- expect(pipeline.all_merge_requests).not_to include(merge_request_2)
+ it 'returns an associated merge request' do
+ expect(pipeline.all_merge_requests).to eq([merge_request])
end
+
+ context 'when there is another merge request pipeline that targets a different branch' do
+ let(:target_branch_2) { 'merge-test' }
+
+ let!(:pipeline_2) do
+ create(:ci_pipeline,
+ source: :merge_request_event,
+ project: pipeline_project,
+ ref: source_branch,
+ merge_request: merge_request_2)
+ end
+
+ let(:merge_request_2) do
+ create(:merge_request,
+ source_project: pipeline_project,
+ source_branch: source_branch,
+ target_project: project,
+ target_branch: target_branch_2)
+ end
+
+ it 'does not return an associated merge request' do
+ expect(pipeline.all_merge_requests).not_to include(merge_request_2)
+ end
+ end
+ end
+ end
+
+ it_behaves_like 'a method that returns all merge requests for a given pipeline' do
+ let(:pipeline_project) { project }
+ end
+
+ context 'for a fork' do
+ let(:fork) { fork_project(project) }
+
+ it_behaves_like 'a method that returns all merge requests for a given pipeline' do
+ let(:pipeline_project) { fork }
end
end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index ad79f8d4ce0..eb2daed7f32 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -817,4 +817,13 @@ describe Ci::Runner do
expect(runners).to eq([runner2, runner1])
end
end
+
+ describe '#uncached_contacted_at' do
+ let(:contacted_at_stored) { 1.hour.ago.change(usec: 0) }
+ let(:runner) { create(:ci_runner, contacted_at: contacted_at_stored) }
+
+ subject { runner.uncached_contacted_at }
+
+ it { is_expected.to eq(contacted_at_stored) }
+ end
end
diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb
index 875e8b2b682..02c07a2bd83 100644
--- a/spec/models/ci/variable_spec.rb
+++ b/spec/models/ci/variable_spec.rb
@@ -6,6 +6,7 @@ describe Ci::Variable do
describe 'validations' do
it { is_expected.to include_module(HasVariable) }
it { is_expected.to include_module(Presentable) }
+ it { is_expected.to include_module(Maskable) }
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:project_id, :environment_scope).with_message(/\(\w+\) has already been taken/) }
end
diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb
index 170c6001eaf..cf5cbf8ec5c 100644
--- a/spec/models/clusters/applications/cert_manager_spec.rb
+++ b/spec/models/clusters/applications/cert_manager_spec.rb
@@ -4,20 +4,9 @@ describe Clusters::Applications::CertManager do
let(:cert_manager) { create(:clusters_applications_cert_managers) }
include_examples 'cluster application core specs', :clusters_applications_cert_managers
-
- describe '#make_installing!' do
- before do
- application.make_installing!
- end
-
- context 'application install previously errored with older version' do
- let(:application) { create(:clusters_applications_cert_managers, :scheduled, version: 'v0.4.0') }
-
- it 'updates the application version' do
- expect(application.reload.version).to eq('v0.5.0')
- end
- end
- end
+ include_examples 'cluster application status specs', :clusters_applications_cert_managers
+ include_examples 'cluster application version specs', :clusters_applications_cert_managers
+ include_examples 'cluster application initial status specs'
describe '#install_command' do
let(:cluster_issuer_file) { { "cluster_issuer.yaml": "---\napiVersion: certmanager.k8s.io/v1alpha1\nkind: ClusterIssuer\nmetadata:\n name: letsencrypt-prod\nspec:\n acme:\n server: https://acme-v02.api.letsencrypt.org/directory\n email: admin@example.com\n privateKeySecretRef:\n name: letsencrypt-prod\n http01: {}\n" } }
@@ -28,8 +17,8 @@ describe Clusters::Applications::CertManager do
it 'should be initialized with cert_manager arguments' do
expect(subject.name).to eq('certmanager')
expect(subject.chart).to eq('stable/cert-manager')
- expect(subject.version).to eq('v0.5.0')
- expect(subject).not_to be_rbac
+ expect(subject.version).to eq('v0.5.2')
+ expect(subject).to be_rbac
expect(subject.files).to eq(cert_manager.files.merge(cluster_issuer_file))
expect(subject.postinstall).to eq(['/usr/bin/kubectl create -f /data/helm/certmanager/config/cluster_issuer.yaml'])
end
@@ -45,19 +34,19 @@ describe Clusters::Applications::CertManager do
end
end
- context 'on a rbac enabled cluster' do
+ context 'on a non rbac enabled cluster' do
before do
- cert_manager.cluster.platform_kubernetes.rbac!
+ cert_manager.cluster.platform_kubernetes.abac!
end
- it { is_expected.to be_rbac }
+ it { is_expected.not_to be_rbac }
end
context 'application failed to install previously' do
let(:cert_manager) { create(:clusters_applications_cert_managers, :errored, version: '0.0.1') }
it 'should be initialized with the locked version' do
- expect(subject.version).to eq('v0.5.0')
+ expect(subject.version).to eq('v0.5.2')
end
end
end
diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb
index 2c37cd20ecc..f16eff92167 100644
--- a/spec/models/clusters/applications/helm_spec.rb
+++ b/spec/models/clusters/applications/helm_spec.rb
@@ -3,16 +3,17 @@ require 'rails_helper'
describe Clusters::Applications::Helm do
include_examples 'cluster application core specs', :clusters_applications_helm
- describe '.installed' do
- subject { described_class.installed }
+ describe '.available' do
+ subject { described_class.available }
let!(:installed_cluster) { create(:clusters_applications_helm, :installed) }
+ let!(:updated_cluster) { create(:clusters_applications_helm, :updated) }
before do
create(:clusters_applications_helm, :errored)
end
- it { is_expected.to contain_exactly(installed_cluster) }
+ it { is_expected.to contain_exactly(installed_cluster, updated_cluster) }
end
describe '#issue_client_cert' do
@@ -49,16 +50,16 @@ describe Clusters::Applications::Helm do
end
describe 'rbac' do
- context 'non rbac cluster' do
- it { expect(subject).not_to be_rbac }
+ context 'rbac cluster' do
+ it { expect(subject).to be_rbac }
end
- context 'rbac cluster' do
+ context 'non rbac cluster' do
before do
- helm.cluster.platform_kubernetes.rbac!
+ helm.cluster.platform_kubernetes.abac!
end
- it { expect(subject).to be_rbac }
+ it { expect(subject).not_to be_rbac }
end
end
end
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index cd28f1fe9c6..d5fd42509a3 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -7,39 +7,15 @@ describe Clusters::Applications::Ingress do
include_examples 'cluster application core specs', :clusters_applications_ingress
include_examples 'cluster application status specs', :clusters_applications_ingress
+ include_examples 'cluster application version specs', :clusters_applications_ingress
include_examples 'cluster application helm specs', :clusters_applications_ingress
+ include_examples 'cluster application initial status specs'
before do
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
end
- describe '.installed' do
- subject { described_class.installed }
-
- let!(:cluster) { create(:clusters_applications_ingress, :installed) }
-
- before do
- create(:clusters_applications_ingress, :errored)
- end
-
- it { is_expected.to contain_exactly(cluster) }
- end
-
- describe '#make_installing!' do
- before do
- application.make_installing!
- end
-
- context 'application install previously errored with older version' do
- let(:application) { create(:clusters_applications_ingress, :scheduled, version: '0.22.0') }
-
- it 'updates the application version' do
- expect(application.reload.version).to eq('0.23.0')
- end
- end
- end
-
describe '#make_installed!' do
before do
application.make_installed!
@@ -90,24 +66,24 @@ describe Clusters::Applications::Ingress do
it 'should be initialized with ingress arguments' do
expect(subject.name).to eq('ingress')
expect(subject.chart).to eq('stable/nginx-ingress')
- expect(subject.version).to eq('0.23.0')
- expect(subject).not_to be_rbac
+ expect(subject.version).to eq('1.1.2')
+ expect(subject).to be_rbac
expect(subject.files).to eq(ingress.files)
end
- context 'on a rbac enabled cluster' do
+ context 'on a non rbac enabled cluster' do
before do
- ingress.cluster.platform_kubernetes.rbac!
+ ingress.cluster.platform_kubernetes.abac!
end
- it { is_expected.to be_rbac }
+ it { is_expected.not_to be_rbac }
end
context 'application failed to install previously' do
let(:ingress) { create(:clusters_applications_ingress, :errored, version: 'nginx') }
it 'should be initialized with the locked version' do
- expect(subject.version).to eq('0.23.0')
+ expect(subject.version).to eq('1.1.2')
end
end
end
diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb
index a40edbf267b..2c22c24c498 100644
--- a/spec/models/clusters/applications/jupyter_spec.rb
+++ b/spec/models/clusters/applications/jupyter_spec.rb
@@ -2,6 +2,8 @@ require 'rails_helper'
describe Clusters::Applications::Jupyter do
include_examples 'cluster application core specs', :clusters_applications_jupyter
+ include_examples 'cluster application status specs', :clusters_applications_jupyter
+ include_examples 'cluster application version specs', :clusters_applications_jupyter
include_examples 'cluster application helm specs', :clusters_applications_jupyter
it { is_expected.to belong_to(:oauth_application) }
@@ -26,20 +28,6 @@ describe Clusters::Applications::Jupyter do
end
end
- describe '#make_installing!' do
- before do
- application.make_installing!
- end
-
- context 'application install previously errored with older version' do
- let(:application) { create(:clusters_applications_jupyter, :scheduled, version: 'v0.5') }
-
- it 'updates the application version' do
- expect(application.reload.version).to eq('v0.6')
- end
- end
- end
-
describe '#install_command' do
let!(:ingress) { create(:clusters_applications_ingress, :installed, external_ip: '127.0.0.1') }
let!(:jupyter) { create(:clusters_applications_jupyter, cluster: ingress.cluster) }
@@ -52,17 +40,17 @@ describe Clusters::Applications::Jupyter do
expect(subject.name).to eq('jupyter')
expect(subject.chart).to eq('jupyter/jupyterhub')
expect(subject.version).to eq('v0.6')
- expect(subject).not_to be_rbac
+ expect(subject).to be_rbac
expect(subject.repository).to eq('https://jupyterhub.github.io/helm-chart/')
expect(subject.files).to eq(jupyter.files)
end
- context 'on a rbac enabled cluster' do
+ context 'on a non rbac enabled cluster' do
before do
- jupyter.cluster.platform_kubernetes.rbac!
+ jupyter.cluster.platform_kubernetes.abac!
end
- it { is_expected.to be_rbac }
+ it { is_expected.not_to be_rbac }
end
context 'application failed to install previously' do
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
index 809880f5969..006b922ab27 100644
--- a/spec/models/clusters/applications/knative_spec.rb
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -9,48 +9,19 @@ describe Clusters::Applications::Knative do
include_examples 'cluster application core specs', :clusters_applications_knative
include_examples 'cluster application status specs', :clusters_applications_knative
include_examples 'cluster application helm specs', :clusters_applications_knative
+ include_examples 'cluster application version specs', :clusters_applications_knative
+ include_examples 'cluster application initial status specs'
before do
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
end
- describe '.installed' do
- subject { described_class.installed }
+ describe 'when rbac is not enabled' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :rbac_disabled) }
+ let(:knative_no_rbac) { create(:clusters_applications_knative, cluster: cluster) }
- let!(:cluster) { create(:clusters_applications_knative, :installed) }
-
- before do
- create(:clusters_applications_knative, :errored)
- end
-
- it { is_expected.to contain_exactly(cluster) }
- end
-
- describe '#make_installing!' do
- before do
- application.make_installing!
- end
-
- context 'application install previously errored with older version' do
- let(:application) { create(:clusters_applications_knative, :scheduled, version: '0.2.2') }
-
- it 'updates the application version' do
- expect(application.reload.version).to eq('0.2.2')
- end
- end
- end
-
- describe '#make_installed' do
- subject { described_class.installed }
-
- let!(:cluster) { create(:clusters_applications_knative, :installed) }
-
- before do
- create(:clusters_applications_knative, :errored)
- end
-
- it { is_expected.to contain_exactly(cluster) }
+ it { expect(knative_no_rbac).to be_not_installable }
end
describe 'make_installed with external_ip' do
@@ -108,6 +79,23 @@ describe Clusters::Applications::Knative do
expect(subject.version).to eq('0.2.2')
expect(subject.files).to eq(knative.files)
end
+
+ it 'should not install metrics for prometheus' do
+ expect(subject.postinstall).to be_nil
+ end
+
+ context 'with prometheus installed' do
+ let(:prometheus) { create(:clusters_applications_prometheus, :installed) }
+ let(:knative) { create(:clusters_applications_knative, cluster: prometheus.cluster) }
+
+ subject { knative.install_command }
+
+ it 'should install metrics' do
+ expect(subject.postinstall).not_to be_nil
+ expect(subject.postinstall.length).to be(1)
+ expect(subject.postinstall[0]).to eql("kubectl apply -f #{Clusters::Applications::Knative::METRICS_CONFIG}")
+ end
+ end
end
describe '#files' do
@@ -125,6 +113,35 @@ describe Clusters::Applications::Knative do
it { is_expected.to validate_presence_of(:hostname) }
end
+ describe '#service_pod_details' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:service) { cluster.platform_kubernetes }
+ let(:knative) { create(:clusters_applications_knative, cluster: cluster) }
+
+ let(:namespace) do
+ create(:cluster_kubernetes_namespace,
+ cluster: cluster,
+ cluster_project: cluster.cluster_project,
+ project: cluster.cluster_project.project)
+ end
+
+ before do
+ stub_kubeclient_discover(service.api_url)
+ stub_kubeclient_knative_services
+ stub_kubeclient_service_pods
+ stub_reactive_cache(knative,
+ {
+ services: kube_response(kube_knative_services_body),
+ pods: kube_response(kube_knative_pods_body(cluster.cluster_project.project.name, namespace.namespace))
+ })
+ synchronous_reactive_cache(knative)
+ end
+
+ it 'should be able k8s core for pod details' do
+ expect(knative.service_pod_details(namespace.namespace, cluster.cluster_project.project.name)).not_to be_nil
+ end
+ end
+
describe '#services' do
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:service) { cluster.platform_kubernetes }
@@ -142,6 +159,7 @@ describe Clusters::Applications::Knative do
before do
stub_kubeclient_discover(service.api_url)
stub_kubeclient_knative_services
+ stub_kubeclient_service_pods
end
it 'should have an unintialized cache' do
@@ -150,7 +168,11 @@ describe Clusters::Applications::Knative do
context 'when using synchronous reactive cache' do
before do
- stub_reactive_cache(knative, services: kube_response(kube_knative_services_body))
+ stub_reactive_cache(knative,
+ {
+ services: kube_response(kube_knative_services_body),
+ pods: kube_response(kube_knative_pods_body(cluster.cluster_project.project.name, namespace.namespace))
+ })
synchronous_reactive_cache(knative)
end
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index 893ed3e3f64..81708b0c2ed 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -5,33 +5,9 @@ describe Clusters::Applications::Prometheus do
include_examples 'cluster application core specs', :clusters_applications_prometheus
include_examples 'cluster application status specs', :clusters_applications_prometheus
+ include_examples 'cluster application version specs', :clusters_applications_prometheus
include_examples 'cluster application helm specs', :clusters_applications_prometheus
-
- describe '.installed' do
- subject { described_class.installed }
-
- let!(:cluster) { create(:clusters_applications_prometheus, :installed) }
-
- before do
- create(:clusters_applications_prometheus, :errored)
- end
-
- it { is_expected.to contain_exactly(cluster) }
- end
-
- describe '#make_installing!' do
- before do
- application.make_installing!
- end
-
- context 'application install previously errored with older version' do
- let(:application) { create(:clusters_applications_prometheus, :scheduled, version: '6.7.2') }
-
- it 'updates the application version' do
- expect(application.reload.version).to eq('6.7.3')
- end
- end
- end
+ include_examples 'cluster application initial status specs'
describe 'transition to installed' do
let(:project) { create(:project) }
@@ -51,47 +27,6 @@ describe Clusters::Applications::Prometheus do
end
end
- describe '#ready' do
- let(:project) { create(:project) }
- let(:cluster) { create(:cluster, projects: [project]) }
-
- it 'returns true when installed' do
- application = build(:clusters_applications_prometheus, :installed, cluster: cluster)
-
- expect(application).to be_ready
- end
-
- it 'returns false when not_installable' do
- application = build(:clusters_applications_prometheus, :not_installable, cluster: cluster)
-
- expect(application).not_to be_ready
- end
-
- it 'returns false when installable' do
- application = build(:clusters_applications_prometheus, :installable, cluster: cluster)
-
- expect(application).not_to be_ready
- end
-
- it 'returns false when scheduled' do
- application = build(:clusters_applications_prometheus, :scheduled, cluster: cluster)
-
- expect(application).not_to be_ready
- end
-
- it 'returns false when installing' do
- application = build(:clusters_applications_prometheus, :installing, cluster: cluster)
-
- expect(application).not_to be_ready
- end
-
- it 'returns false when errored' do
- application = build(:clusters_applications_prometheus, :errored, cluster: cluster)
-
- expect(application).not_to be_ready
- end
- end
-
describe '#prometheus_client' do
context 'cluster is nil' do
it 'returns nil' do
@@ -161,16 +96,16 @@ describe Clusters::Applications::Prometheus do
expect(subject.name).to eq('prometheus')
expect(subject.chart).to eq('stable/prometheus')
expect(subject.version).to eq('6.7.3')
- expect(subject).not_to be_rbac
+ expect(subject).to be_rbac
expect(subject.files).to eq(prometheus.files)
end
- context 'on a rbac enabled cluster' do
+ context 'on a non rbac enabled cluster' do
before do
- prometheus.cluster.platform_kubernetes.rbac!
+ prometheus.cluster.platform_kubernetes.abac!
end
- it { is_expected.to be_rbac }
+ it { is_expected.not_to be_rbac }
end
context 'application failed to install previously' do
@@ -180,6 +115,61 @@ describe Clusters::Applications::Prometheus do
expect(subject.version).to eq('6.7.3')
end
end
+
+ it 'should not install knative metrics' do
+ expect(subject.postinstall).to be_nil
+ end
+
+ context 'with knative installed' do
+ let(:knative) { create(:clusters_applications_knative, :updated ) }
+ let(:prometheus) { create(:clusters_applications_prometheus, cluster: knative.cluster) }
+
+ subject { prometheus.install_command }
+
+ it 'should install knative metrics' do
+ expect(subject.postinstall).to include("kubectl apply -f #{Clusters::Applications::Knative::METRICS_CONFIG}")
+ end
+ end
+ end
+
+ describe '#upgrade_command' do
+ let(:prometheus) { build(:clusters_applications_prometheus) }
+ let(:values) { prometheus.values }
+
+ it 'returns an instance of Gitlab::Kubernetes::Helm::InstallCommand' do
+ expect(prometheus.upgrade_command(values)).to be_an_instance_of(::Gitlab::Kubernetes::Helm::InstallCommand)
+ end
+
+ it 'should be initialized with 3 arguments' do
+ command = prometheus.upgrade_command(values)
+
+ expect(command.name).to eq('prometheus')
+ expect(command.chart).to eq('stable/prometheus')
+ expect(command.version).to eq('6.7.3')
+ expect(command.files).to eq(prometheus.files)
+ end
+ end
+
+ describe '#update_in_progress?' do
+ context 'when app is updating' do
+ it 'returns true' do
+ cluster = create(:cluster)
+ prometheus_app = build(:clusters_applications_prometheus, :updating, cluster: cluster)
+
+ expect(prometheus_app.update_in_progress?).to be true
+ end
+ end
+ end
+
+ describe '#update_errored?' do
+ context 'when app errored' do
+ it 'returns true' do
+ cluster = create(:cluster)
+ prometheus_app = build(:clusters_applications_prometheus, :update_errored, cluster: cluster)
+
+ expect(prometheus_app.update_errored?).to be true
+ end
+ end
end
describe '#files' do
@@ -196,4 +186,43 @@ describe Clusters::Applications::Prometheus do
expect(values).to include('serverFiles')
end
end
+
+ describe '#files_with_replaced_values' do
+ let(:application) { build(:clusters_applications_prometheus) }
+ let(:files) { application.files }
+
+ subject { application.files_with_replaced_values({ hello: :world }) }
+
+ it 'does not modify #files' do
+ expect(subject[:'values.yaml']).not_to eq(files)
+ expect(files[:'values.yaml']).to eq(application.values)
+ end
+
+ it 'returns values.yaml with replaced values' do
+ expect(subject[:'values.yaml']).to eq({ hello: :world })
+ end
+
+ it 'should include cert files' do
+ expect(subject[:'ca.pem']).to be_present
+ expect(subject[:'ca.pem']).to eq(application.cluster.application_helm.ca_cert)
+
+ expect(subject[:'cert.pem']).to be_present
+ expect(subject[:'key.pem']).to be_present
+
+ cert = OpenSSL::X509::Certificate.new(subject[:'cert.pem'])
+ expect(cert.not_after).to be < 60.minutes.from_now
+ end
+
+ context 'when the helm application does not have a ca_cert' do
+ before do
+ application.cluster.application_helm.ca_cert = nil
+ end
+
+ it 'should not include cert files' do
+ expect(subject[:'ca.pem']).not_to be_present
+ expect(subject[:'cert.pem']).not_to be_present
+ expect(subject[:'key.pem']).not_to be_present
+ end
+ end
+ end
end
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index 47daa79873e..6972fc03415 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -5,36 +5,12 @@ describe Clusters::Applications::Runner do
include_examples 'cluster application core specs', :clusters_applications_runner
include_examples 'cluster application status specs', :clusters_applications_runner
+ include_examples 'cluster application version specs', :clusters_applications_runner
include_examples 'cluster application helm specs', :clusters_applications_runner
+ include_examples 'cluster application initial status specs'
it { is_expected.to belong_to(:runner) }
- describe '#make_installing!' do
- before do
- application.make_installing!
- end
-
- context 'application install previously errored with older version' do
- let(:application) { create(:clusters_applications_runner, :scheduled, version: '0.1.30') }
-
- it 'updates the application version' do
- expect(application.reload.version).to eq('0.1.39')
- end
- end
- end
-
- describe '.installed' do
- subject { described_class.installed }
-
- let!(:cluster) { create(:clusters_applications_runner, :installed) }
-
- before do
- create(:clusters_applications_runner, :errored)
- end
-
- it { is_expected.to contain_exactly(cluster) }
- end
-
describe '#install_command' do
let(:kubeclient) { double('kubernetes client') }
let(:gitlab_runner) { create(:clusters_applications_runner, runner: ci_runner) }
@@ -46,25 +22,25 @@ describe Clusters::Applications::Runner do
it 'should be initialized with 4 arguments' do
expect(subject.name).to eq('runner')
expect(subject.chart).to eq('runner/gitlab-runner')
- expect(subject.version).to eq('0.1.39')
- expect(subject).not_to be_rbac
+ expect(subject.version).to eq('0.2.0')
+ expect(subject).to be_rbac
expect(subject.repository).to eq('https://charts.gitlab.io')
expect(subject.files).to eq(gitlab_runner.files)
end
- context 'on a rbac enabled cluster' do
+ context 'on a non rbac enabled cluster' do
before do
- gitlab_runner.cluster.platform_kubernetes.rbac!
+ gitlab_runner.cluster.platform_kubernetes.abac!
end
- it { is_expected.to be_rbac }
+ it { is_expected.not_to be_rbac }
end
context 'application failed to install previously' do
let(:gitlab_runner) { create(:clusters_applications_runner, :errored, runner: ci_runner, version: '0.1.13') }
it 'should be initialized with the locked version' do
- expect(subject.version).to eq('0.1.39')
+ expect(subject.version).to eq('0.2.0')
end
end
end
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 840f74c9890..3feed4e9718 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -29,6 +29,8 @@ describe Clusters::Cluster do
it { is_expected.to delegate_method(:available?).to(:application_helm).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_ingress).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_prometheus).with_prefix }
+ it { is_expected.to delegate_method(:available?).to(:application_knative).with_prefix }
+ it { is_expected.to delegate_method(:external_ip).to(:application_ingress).with_prefix }
it { is_expected.to respond_to :project }
@@ -112,7 +114,7 @@ describe Clusters::Cluster do
end
end
- describe 'validation' do
+ describe 'validations' do
subject { cluster.valid? }
context 'when validates name' do
@@ -251,6 +253,31 @@ describe Clusters::Cluster do
end
end
end
+
+ describe 'domain validation' do
+ let(:cluster) { build(:cluster) }
+
+ subject { cluster }
+
+ context 'when cluster has domain' do
+ let(:cluster) { build(:cluster, :with_domain) }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when cluster is not a valid hostname' do
+ let(:cluster) { build(:cluster, domain: 'http://not.a.valid.hostname') }
+
+ it 'should add an error on domain' do
+ expect(subject).not_to be_valid
+ expect(subject.errors[:domain].first).to eq('contains invalid characters (valid characters: [a-z0-9\\-])')
+ end
+ end
+
+ context 'when cluster does not have a domain' do
+ it { is_expected.to be_valid }
+ end
+ end
end
describe '.ancestor_clusters_for_clusterable' do
@@ -488,4 +515,108 @@ describe Clusters::Cluster do
it { is_expected.to be_falsey }
end
end
+
+ describe '#kube_ingress_domain' do
+ let(:cluster) { create(:cluster, :provided_by_gcp) }
+
+ subject { cluster.kube_ingress_domain }
+
+ context 'with domain set in cluster' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :with_domain) }
+
+ it { is_expected.to eq(cluster.domain) }
+ end
+
+ context 'with no domain on cluster' do
+ context 'with a project cluster' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+
+ context 'with domain set at instance level' do
+ before do
+ stub_application_setting(auto_devops_domain: 'global_domain.com')
+
+ it { is_expected.to eq('global_domain.com') }
+ end
+ end
+
+ context 'with domain set on ProjectAutoDevops' do
+ before do
+ auto_devops = project.build_auto_devops(domain: 'legacy-ado-domain.com')
+ auto_devops.save
+ end
+
+ it { is_expected.to eq('legacy-ado-domain.com') }
+ end
+
+ context 'with domain set as environment variable on project' do
+ before do
+ variable = project.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'project-ado-domain.com')
+ variable.save
+ end
+
+ it { is_expected.to eq('project-ado-domain.com') }
+ end
+
+ context 'with domain set as environment variable on the group project' do
+ let(:group) { create(:group) }
+
+ before do
+ project.update(parent_id: group.id)
+ variable = group.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'group-ado-domain.com')
+ variable.save
+ end
+
+ it { is_expected.to eq('group-ado-domain.com') }
+ end
+ end
+
+ context 'with a group cluster' do
+ let(:cluster) { create(:cluster, :group, :provided_by_gcp) }
+
+ context 'with domain set as environment variable for the group' do
+ let(:group) { cluster.group }
+
+ before do
+ variable = group.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'group-ado-domain.com')
+ variable.save
+ end
+
+ it { is_expected.to eq('group-ado-domain.com') }
+ end
+ end
+ end
+ end
+
+ describe '#predefined_variables' do
+ subject { cluster.predefined_variables }
+
+ context 'with an instance domain' do
+ let(:cluster) { create(:cluster, :provided_by_gcp) }
+
+ before do
+ stub_application_setting(auto_devops_domain: 'global_domain.com')
+ end
+
+ it 'should include KUBE_INGRESS_BASE_DOMAIN' do
+ expect(subject.to_hash).to include(KUBE_INGRESS_BASE_DOMAIN: 'global_domain.com')
+ end
+ end
+
+ context 'with a cluster domain' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, domain: 'example.com') }
+
+ it 'should include KUBE_INGRESS_BASE_DOMAIN' do
+ expect(subject.to_hash).to include(KUBE_INGRESS_BASE_DOMAIN: 'example.com')
+ end
+ end
+
+ context 'with no domain' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :project) }
+
+ it 'should return an empty array' do
+ expect(subject.to_hash).to be_empty
+ end
+ end
+ end
end
diff --git a/spec/models/clusters/kubernetes_namespace_spec.rb b/spec/models/clusters/kubernetes_namespace_spec.rb
index 56c98d016c9..b865909c7fd 100644
--- a/spec/models/clusters/kubernetes_namespace_spec.rb
+++ b/spec/models/clusters/kubernetes_namespace_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Clusters::KubernetesNamespace, type: :model do
let(:cluster_project) { create(:cluster_project) }
let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace, namespace: 'my-namespace') }
- subject { kubernetes_namespace }
+ subject { kubernetes_namespace }
context 'when cluster is using the namespace' do
before do
@@ -97,7 +97,7 @@ RSpec.describe Clusters::KubernetesNamespace, type: :model do
let(:platform) { create(:cluster_platform_kubernetes, api_url: api_url, ca_cert: ca_pem, token: token) }
let(:api_url) { 'https://kube.domain.com' }
- let(:ca_pem) { 'CA PEM DATA' }
+ let(:ca_pem) { File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem')) }
let(:token) { 'token' }
let(:kubeconfig) do
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index f3af9d59786..3b32ca8df05 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -98,6 +98,22 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { expect(kubernetes.save).to be_truthy }
end
+
+ context 'when api_url is localhost' do
+ let(:api_url) { 'http://localhost:22' }
+
+ it { expect(kubernetes.save).to be_falsey }
+
+ context 'Application settings allows local requests' do
+ before do
+ allow(ApplicationSetting)
+ .to receive(:current)
+ .and_return(ApplicationSetting.build_from_defaults(allow_local_requests_from_hooks_and_services: true))
+ end
+
+ it { expect(kubernetes.save).to be_truthy }
+ end
+ end
end
context 'when validates token' do
@@ -114,6 +130,36 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
end
+ context 'ca_cert' do
+ let(:kubernetes) { build(:cluster_platform_kubernetes, ca_pem: ca_pem) }
+
+ context 'with a valid certificate' do
+ let(:ca_pem) { File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem')) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'with an invalid certificate' do
+ let(:ca_pem) { "invalid" }
+
+ it { is_expected.to be_falsey }
+
+ context 'but the certificate is not being updated' do
+ before do
+ allow(kubernetes).to receive(:ca_cert_changed?).and_return(false)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'with no certificate' do
+ let(:ca_pem) { "" }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
describe 'when using reserved namespaces' do
subject { build(:cluster_platform_kubernetes, namespace: namespace) }
@@ -154,19 +200,11 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
describe '#rbac?' do
- subject { kubernetes.rbac? }
-
let(:kubernetes) { build(:cluster_platform_kubernetes, :configured) }
- context 'when authorization type is rbac' do
- let(:kubernetes) { build(:cluster_platform_kubernetes, :rbac_enabled, :configured) }
-
- it { is_expected.to be_truthy }
- end
+ subject { kubernetes.rbac? }
- context 'when authorization type is nil' do
- it { is_expected.to be_falsey }
- end
+ it { is_expected.to be_truthy }
end
describe '#actual_namespace' do
@@ -210,7 +248,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
let!(:cluster) { create(:cluster, :project, platform_kubernetes: kubernetes) }
let(:kubernetes) { create(:cluster_platform_kubernetes, api_url: api_url, ca_cert: ca_pem) }
let(:api_url) { 'https://kube.domain.com' }
- let(:ca_pem) { 'CA PEM DATA' }
+ let(:ca_pem) { File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem')) }
subject { kubernetes.predefined_variables(project: cluster.project) }
@@ -305,6 +343,19 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
end
end
+
+ context 'with a domain' do
+ let!(:cluster) do
+ create(:cluster, :provided_by_gcp, :with_domain,
+ platform_kubernetes: kubernetes)
+ end
+
+ it 'sets KUBE_INGRESS_BASE_DOMAIN' do
+ expect(subject).to include(
+ { key: 'KUBE_INGRESS_BASE_DOMAIN', value: cluster.domain, public: true }
+ )
+ end
+ end
end
describe '#terminals' do
@@ -325,12 +376,13 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context 'with valid pods' do
let(:pod) { kube_pod(app: environment.slug) }
+ let(:pod_with_no_terminal) { kube_pod(app: environment.slug, status: "Pending") }
let(:terminals) { kube_terminals(service, pod) }
before do
stub_reactive_cache(
service,
- pods: [pod, pod, kube_pod(app: "should-be-filtered-out")]
+ pods: [pod, pod, pod_with_no_terminal, kube_pod(app: "should-be-filtered-out")]
)
end
diff --git a/spec/models/clusters/providers/gcp_spec.rb b/spec/models/clusters/providers/gcp_spec.rb
index d134608b538..5012e6f15c6 100644
--- a/spec/models/clusters/providers/gcp_spec.rb
+++ b/spec/models/clusters/providers/gcp_spec.rb
@@ -79,17 +79,7 @@ describe Clusters::Providers::Gcp do
subject { gcp }
- it 'should default to true' do
- is_expected.to be_legacy_abac
- end
-
- context 'legacy_abac is set to false' do
- let(:gcp) { build(:cluster_provider_gcp, legacy_abac: false) }
-
- it 'is false' do
- is_expected.not_to be_legacy_abac
- end
- end
+ it { is_expected.not_to be_legacy_abac }
end
describe '#state_machine' do
diff --git a/spec/models/commit_collection_spec.rb b/spec/models/commit_collection_spec.rb
index 066fe7d154e..0f5d03ff458 100644
--- a/spec/models/commit_collection_spec.rb
+++ b/spec/models/commit_collection_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe CommitCollection do
let(:project) { create(:project, :repository) }
- let(:commit) { project.commit }
+ let(:commit) { project.commit("c1c67abbaf91f624347bb3ae96eabe3a1b742478") }
describe '#each' do
it 'yields every commit' do
@@ -12,6 +12,40 @@ describe CommitCollection do
end
end
+ describe '.authors' do
+ it 'returns a relation of users when users are found' do
+ user = create(:user, email: commit.author_email.upcase)
+ collection = described_class.new(project, [commit])
+
+ expect(collection.authors).to contain_exactly(user)
+ end
+
+ it 'returns empty array when authors cannot be found' do
+ collection = described_class.new(project, [commit])
+
+ expect(collection.authors).to be_empty
+ end
+
+ it 'excludes authors of merge commits' do
+ commit = project.commit("60ecb67744cb56576c30214ff52294f8ce2def98")
+ create(:user, email: commit.author_email.upcase)
+ collection = described_class.new(project, [commit])
+
+ expect(collection.authors).to be_empty
+ end
+ end
+
+ describe '#without_merge_commits' do
+ it 'returns all commits except merge commits' do
+ collection = described_class.new(project, [
+ build(:commit),
+ build(:commit, :merge_commit)
+ ])
+
+ expect(collection.without_merge_commits.size).to eq(1)
+ end
+ end
+
describe '#with_pipeline_status' do
it 'sets the pipeline status for every commit so no additional queries are necessary' do
create(
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index a2d2d77746d..baad8352185 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -11,6 +11,7 @@ describe Commit do
it { is_expected.to include_module(Participable) }
it { is_expected.to include_module(Referable) }
it { is_expected.to include_module(StaticModel) }
+ it { is_expected.to include_module(Presentable) }
end
describe '.lazy' do
diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb
index f8d50e89d40..447279f19a8 100644
--- a/spec/models/concerns/cache_markdown_field_spec.rb
+++ b/spec/models/concerns/cache_markdown_field_spec.rb
@@ -60,6 +60,10 @@ describe CacheMarkdownField do
changes_applied
end
end
+
+ def has_attribute?(attr_name)
+ attribute_names.include?(attr_name)
+ end
end
def thing_subclass(new_attr)
@@ -67,12 +71,17 @@ describe CacheMarkdownField do
end
let(:markdown) { '`Foo`' }
- let(:html) { '<p dir="auto"><code>Foo</code></p>' }
+ let(:html) { '<p dir="auto"><code>Foo</code></p>' }
let(:updated_markdown) { '`Bar`' }
- let(:updated_html) { '<p dir="auto"><code>Bar</code></p>' }
+ let(:updated_html) { '<p dir="auto"><code>Bar</code></p>' }
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION) }
+ let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
+ let(:cache_version) { CacheMarkdownField::CACHE_COMMONMARK_VERSION << 16 }
+
+ before do
+ stub_commonmark_sourcepos_disabled
+ end
describe '.attributes' do
it 'excludes cache attributes' do
@@ -89,24 +98,19 @@ describe CacheMarkdownField do
it { expect(thing.foo).to eq(markdown) }
it { expect(thing.foo_html).to eq(html) }
it { expect(thing.foo_html_changed?).not_to be_truthy }
- it { expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION) }
+ it { expect(thing.cached_markdown_version).to eq(cache_version) }
end
context 'a changed markdown field' do
- shared_examples 'with cache version' do |cache_version|
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
-
- before do
- thing.foo = updated_markdown
- thing.save
- end
+ let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version - 1) }
- it { expect(thing.foo_html).to eq(updated_html) }
- it { expect(thing.cached_markdown_version).to eq(cache_version) }
+ before do
+ thing.foo = updated_markdown
+ thing.save
end
- it_behaves_like 'with cache version', CacheMarkdownField::CACHE_REDCARPET_VERSION
- it_behaves_like 'with cache version', CacheMarkdownField::CACHE_COMMONMARK_VERSION
+ it { expect(thing.foo_html).to eq(updated_html) }
+ it { expect(thing.cached_markdown_version).to eq(cache_version) }
end
context 'when a markdown field is set repeatedly to an empty string' do
@@ -129,23 +133,27 @@ describe CacheMarkdownField do
end
end
- context 'a non-markdown field changed' do
- shared_examples 'with cache version' do |cache_version|
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
+ context 'when a markdown field and html field are both changed' do
+ it do
+ expect(thing).not_to receive(:refresh_markdown_cache)
+ thing.foo = '_look over there!_'
+ thing.foo_html = '<em>look over there!</em>'
+ thing.save
+ end
+ end
- before do
- thing.bar = 'OK'
- thing.save
- end
+ context 'a non-markdown field changed' do
+ let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version - 1) }
- it { expect(thing.bar).to eq('OK') }
- it { expect(thing.foo).to eq(markdown) }
- it { expect(thing.foo_html).to eq(html) }
- it { expect(thing.cached_markdown_version).to eq(cache_version) }
+ before do
+ thing.bar = 'OK'
+ thing.save
end
- it_behaves_like 'with cache version', CacheMarkdownField::CACHE_REDCARPET_VERSION
- it_behaves_like 'with cache version', CacheMarkdownField::CACHE_COMMONMARK_VERSION
+ it { expect(thing.bar).to eq('OK') }
+ it { expect(thing.foo).to eq(markdown) }
+ it { expect(thing.foo_html).to eq(html) }
+ it { expect(thing.cached_markdown_version).to eq(cache_version) }
end
context 'version is out of date' do
@@ -156,85 +164,84 @@ describe CacheMarkdownField do
end
it { expect(thing.foo_html).to eq(updated_html) }
- it { expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION) }
+ it { expect(thing.cached_markdown_version).to eq(cache_version) }
end
describe '#cached_html_up_to_date?' do
- shared_examples 'with cache version' do |cache_version|
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
+ let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
- subject { thing.cached_html_up_to_date?(:foo) }
+ subject { thing.cached_html_up_to_date?(:foo) }
- it 'returns false when the version is absent' do
- thing.cached_markdown_version = nil
+ it 'returns false when the version is absent' do
+ thing.cached_markdown_version = nil
- is_expected.to be_falsy
- end
+ is_expected.to be_falsy
+ end
- it 'returns false when the version is too early' do
- thing.cached_markdown_version -= 1
+ it 'returns false when the cached version is too old' do
+ thing.cached_markdown_version = cache_version - 1
- is_expected.to be_falsy
- end
+ is_expected.to be_falsy
+ end
- it 'returns false when the version is too late' do
- thing.cached_markdown_version += 1
+ it 'returns false when the cached version is in future' do
+ thing.cached_markdown_version = cache_version + 1
- is_expected.to be_falsy
- end
+ is_expected.to be_falsy
+ end
- it 'returns true when the version is just right' do
- thing.cached_markdown_version = cache_version
+ it 'returns false when the local version was bumped' do
+ allow(Gitlab::CurrentSettings.current_application_settings).to receive(:local_markdown_version).and_return(2)
+ thing.cached_markdown_version = cache_version
- is_expected.to be_truthy
- end
+ is_expected.to be_falsy
+ end
- it 'returns false if markdown has been changed but html has not' do
- thing.foo = updated_html
+ it 'returns true when the local version is default' do
+ thing.cached_markdown_version = cache_version
- is_expected.to be_falsy
- end
+ is_expected.to be_truthy
+ end
- it 'returns true if markdown has not been changed but html has' do
- thing.foo_html = updated_html
+ it 'returns true when the cached version is just right' do
+ allow(Gitlab::CurrentSettings.current_application_settings).to receive(:local_markdown_version).and_return(2)
+ thing.cached_markdown_version = cache_version + 2
- is_expected.to be_truthy
- end
+ is_expected.to be_truthy
+ end
- it 'returns true if markdown and html have both been changed' do
- thing.foo = updated_markdown
- thing.foo_html = updated_html
+ it 'returns false if markdown has been changed but html has not' do
+ thing.foo = updated_html
- is_expected.to be_truthy
- end
+ is_expected.to be_falsy
+ end
- it 'returns false if the markdown field is set but the html is not' do
- thing.foo_html = nil
+ it 'returns true if markdown has not been changed but html has' do
+ thing.foo_html = updated_html
- is_expected.to be_falsy
- end
+ is_expected.to be_truthy
end
- it_behaves_like 'with cache version', CacheMarkdownField::CACHE_REDCARPET_VERSION
- it_behaves_like 'with cache version', CacheMarkdownField::CACHE_COMMONMARK_VERSION
- end
-
- describe '#latest_cached_markdown_version' do
- subject { thing.latest_cached_markdown_version }
+ it 'returns true if markdown and html have both been changed' do
+ thing.foo = updated_markdown
+ thing.foo_html = updated_html
- it 'returns redcarpet version' do
- thing.cached_markdown_version = CacheMarkdownField::CACHE_COMMONMARK_VERSION_START - 1
- is_expected.to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION)
+ is_expected.to be_truthy
end
- it 'returns commonmark version' do
- thing.cached_markdown_version = CacheMarkdownField::CACHE_COMMONMARK_VERSION_START + 1
- is_expected.to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION)
+ it 'returns false if the markdown field is set but the html is not' do
+ thing.foo_html = nil
+
+ is_expected.to be_falsy
end
+ end
- it 'returns default version when version is nil' do
+ describe '#latest_cached_markdown_version' do
+ subject { thing.latest_cached_markdown_version }
+
+ it 'returns default version' do
thing.cached_markdown_version = nil
- is_expected.to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION)
+ is_expected.to eq(cache_version)
end
end
@@ -261,44 +268,39 @@ describe CacheMarkdownField do
thing.cached_markdown_version = nil
thing.refresh_markdown_cache
- expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION)
+ expect(thing.cached_markdown_version).to eq(cache_version)
end
end
describe '#refresh_markdown_cache!' do
- shared_examples 'with cache version' do |cache_version|
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
+ let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
- before do
- thing.foo = updated_markdown
- end
+ before do
+ thing.foo = updated_markdown
+ end
- it 'fills all html fields' do
- thing.refresh_markdown_cache!
+ it 'fills all html fields' do
+ thing.refresh_markdown_cache!
- expect(thing.foo_html).to eq(updated_html)
- expect(thing.foo_html_changed?).to be_truthy
- expect(thing.baz_html_changed?).to be_truthy
- end
+ expect(thing.foo_html).to eq(updated_html)
+ expect(thing.foo_html_changed?).to be_truthy
+ expect(thing.baz_html_changed?).to be_truthy
+ end
- it 'skips saving if not persisted' do
- expect(thing).to receive(:persisted?).and_return(false)
- expect(thing).not_to receive(:update_columns)
+ it 'skips saving if not persisted' do
+ expect(thing).to receive(:persisted?).and_return(false)
+ expect(thing).not_to receive(:update_columns)
- thing.refresh_markdown_cache!
- end
+ thing.refresh_markdown_cache!
+ end
- it 'saves the changes using #update_columns' do
- expect(thing).to receive(:persisted?).and_return(true)
- expect(thing).to receive(:update_columns)
- .with("foo_html" => updated_html, "baz_html" => "", "cached_markdown_version" => cache_version)
+ it 'saves the changes using #update_columns' do
+ expect(thing).to receive(:persisted?).and_return(true)
+ expect(thing).to receive(:update_columns)
+ .with("foo_html" => updated_html, "baz_html" => "", "cached_markdown_version" => cache_version)
- thing.refresh_markdown_cache!
- end
+ thing.refresh_markdown_cache!
end
-
- it_behaves_like 'with cache version', CacheMarkdownField::CACHE_REDCARPET_VERSION
- it_behaves_like 'with cache version', CacheMarkdownField::CACHE_COMMONMARK_VERSION
end
describe '#banzai_render_context' do
@@ -347,7 +349,7 @@ describe CacheMarkdownField do
expect(thing.foo_html).to eq(updated_html)
expect(thing.baz_html).to eq(updated_html)
- expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION)
+ expect(thing.cached_markdown_version).to eq(cache_version)
end
end
@@ -367,24 +369,8 @@ describe CacheMarkdownField do
expect(thing.foo_html).to eq(updated_html)
expect(thing.baz_html).to eq(updated_html)
- expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION)
+ expect(thing.cached_markdown_version).to eq(cache_version)
end
end
end
-
- describe CacheMarkdownField::MarkdownEngine do
- subject { lambda { |version| CacheMarkdownField::MarkdownEngine.from_version(version) } }
-
- it 'returns :common_mark as a default' do
- expect(subject.call(nil)).to eq :common_mark
- end
-
- it 'returns :common_mark' do
- expect(subject.call(CacheMarkdownField::CACHE_COMMONMARK_VERSION)).to eq :common_mark
- end
-
- it 'returns :redcarpet' do
- expect(subject.call(CacheMarkdownField::CACHE_REDCARPET_VERSION)).to eq :redcarpet
- end
- end
end
diff --git a/spec/models/concerns/cacheable_attributes_spec.rb b/spec/models/concerns/cacheable_attributes_spec.rb
index 827fbc9d7d5..43a544cfe26 100644
--- a/spec/models/concerns/cacheable_attributes_spec.rb
+++ b/spec/models/concerns/cacheable_attributes_spec.rb
@@ -20,6 +20,10 @@ describe CacheableAttributes do
@_last ||= new('foo' => 'a', 'bar' => 'b')
end
+ def self.column_names
+ %w[foo bar baz]
+ end
+
attr_accessor :attributes
def initialize(attrs = {}, *)
@@ -75,13 +79,13 @@ describe CacheableAttributes do
context 'without any attributes given' do
it 'intializes a new object with the defaults' do
- expect(minimal_test_class.build_from_defaults.attributes).to eq(minimal_test_class.defaults)
+ expect(minimal_test_class.build_from_defaults.attributes).to eq(minimal_test_class.defaults.stringify_keys)
end
end
context 'with attributes given' do
it 'intializes a new object with the given attributes merged into the defaults' do
- expect(minimal_test_class.build_from_defaults(foo: 'd').attributes[:foo]).to eq('d')
+ expect(minimal_test_class.build_from_defaults(foo: 'd').attributes['foo']).to eq('d')
end
end
@@ -155,6 +159,10 @@ describe CacheableAttributes do
describe 'edge cases' do
describe 'caching behavior', :use_clean_rails_memory_store_caching do
+ before do
+ stub_commonmark_sourcepos_disabled
+ end
+
it 'retrieves upload fields properly' do
ar_record = create(:appearance, :with_logo)
ar_record.cache!
diff --git a/spec/models/concerns/discussion_on_diff_spec.rb b/spec/models/concerns/discussion_on_diff_spec.rb
index 4b16e6e3902..64bf04071e8 100644
--- a/spec/models/concerns/discussion_on_diff_spec.rb
+++ b/spec/models/concerns/discussion_on_diff_spec.rb
@@ -7,7 +7,7 @@ describe DiscussionOnDiff do
let(:truncated_lines) { subject.truncated_diff_lines }
context "when diff is greater than allowed number of truncated diff lines " do
- it "returns fewer lines" do
+ it "returns fewer lines" do
expect(subject.diff_lines.count).to be > DiffDiscussion::NUMBER_OF_TRUNCATED_DIFF_LINES
expect(truncated_lines.count).to be <= DiffDiscussion::NUMBER_OF_TRUNCATED_DIFF_LINES
diff --git a/spec/models/concerns/has_ref_spec.rb b/spec/models/concerns/has_ref_spec.rb
new file mode 100644
index 00000000000..8aa2fecb18c
--- /dev/null
+++ b/spec/models/concerns/has_ref_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe HasRef do
+ describe '#branch?' do
+ let(:build) { create(:ci_build) }
+
+ subject { build.branch? }
+
+ context 'is not a tag' do
+ before do
+ build.tag = false
+ end
+
+ it 'return true when tag is set to false' do
+ is_expected.to be_truthy
+ end
+
+ context 'when it was triggered by merge request' do
+ let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) }
+ let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ it 'returns false' do
+ is_expected.to be_falsy
+ end
+ end
+ end
+
+ context 'is not a tag' do
+ before do
+ build.tag = true
+ end
+
+ it 'return false when tag is set to true' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+
+ describe '#git_ref' do
+ subject { build.git_ref }
+
+ context 'when tag is true' do
+ let(:build) { create(:ci_build, tag: true) }
+
+ it 'returns a tag ref' do
+ is_expected.to start_with(Gitlab::Git::TAG_REF_PREFIX)
+ end
+ end
+
+ context 'when tag is false' do
+ let(:build) { create(:ci_build, tag: false) }
+
+ it 'returns a branch ref' do
+ is_expected.to start_with(Gitlab::Git::BRANCH_REF_PREFIX)
+ end
+ end
+
+ context 'when tag is nil' do
+ let(:build) { create(:ci_build, tag: nil) }
+
+ it 'returns a branch ref' do
+ is_expected.to start_with(Gitlab::Git::BRANCH_REF_PREFIX)
+ end
+ end
+
+ context 'when it is triggered by a merge request' do
+ let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) }
+ let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:build) { create(:ci_build, tag: false, pipeline: pipeline) }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/has_variable_spec.rb b/spec/models/concerns/has_variable_spec.rb
index 3fbe86c5b56..bff96e12ffa 100644
--- a/spec/models/concerns/has_variable_spec.rb
+++ b/spec/models/concerns/has_variable_spec.rb
@@ -57,7 +57,7 @@ describe HasVariable do
describe '#to_runner_variable' do
it 'returns a hash for the runner' do
expect(subject.to_runner_variable)
- .to eq(key: subject.key, value: subject.value, public: false)
+ .to include(key: subject.key, value: subject.value, public: false)
end
end
end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index a4bf3e2350a..72c6161424b 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -32,17 +32,56 @@ describe Issuable do
end
describe "Validation" do
- subject { build(:issue) }
+ context 'general validations' do
+ subject { build(:issue) }
- before do
- allow(InternalId).to receive(:generate_next).and_return(nil)
+ before do
+ allow(InternalId).to receive(:generate_next).and_return(nil)
+ end
+
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:iid) }
+ it { is_expected.to validate_presence_of(:author) }
+ it { is_expected.to validate_presence_of(:title) }
+ it { is_expected.to validate_length_of(:title).is_at_most(255) }
end
- it { is_expected.to validate_presence_of(:project) }
- it { is_expected.to validate_presence_of(:iid) }
- it { is_expected.to validate_presence_of(:author) }
- it { is_expected.to validate_presence_of(:title) }
- it { is_expected.to validate_length_of(:title).is_at_most(255) }
+ describe 'milestone' do
+ let(:project) { create(:project) }
+ let(:milestone_id) { create(:milestone, project: project).id }
+ let(:params) do
+ {
+ title: 'something',
+ project: project,
+ author: build(:user),
+ milestone_id: milestone_id
+ }
+ end
+
+ subject { issuable_class.new(params) }
+
+ context 'with correct params' do
+ it { is_expected.to be_valid }
+ end
+
+ context 'with empty string milestone' do
+ let(:milestone_id) { '' }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'with nil milestone id' do
+ let(:milestone_id) { nil }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'with a milestone id from another project' do
+ let(:milestone_id) { create(:milestone).id }
+
+ it { is_expected.to be_invalid }
+ end
+ end
end
describe "Scope" do
@@ -66,6 +105,48 @@ describe Issuable do
end
end
+ describe '#milestone_available?' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group) }
+ let(:issue) { create(:issue, project: project) }
+
+ def build_issuable(milestone_id)
+ issuable_class.new(project: project, milestone_id: milestone_id)
+ end
+
+ it 'returns true with a milestone from the issue project' do
+ milestone = create(:milestone, project: project)
+
+ expect(build_issuable(milestone.id).milestone_available?).to be_truthy
+ end
+
+ it 'returns true with a milestone from the issue project group' do
+ milestone = create(:milestone, group: group)
+
+ expect(build_issuable(milestone.id).milestone_available?).to be_truthy
+ end
+
+ it 'returns true with a milestone from the the parent of the issue project group', :nested_groups do
+ parent = create(:group)
+ group.update(parent: parent)
+ milestone = create(:milestone, group: parent)
+
+ expect(build_issuable(milestone.id).milestone_available?).to be_truthy
+ end
+
+ it 'returns false with a milestone from another project' do
+ milestone = create(:milestone)
+
+ expect(build_issuable(milestone.id).milestone_available?).to be_falsey
+ end
+
+ it 'returns false with a milestone from another group' do
+ milestone = create(:milestone, group: create(:group))
+
+ expect(build_issuable(milestone.id).milestone_available?).to be_falsey
+ end
+ end
+
describe ".search" do
let!(:searchable_issue) { create(:issue, title: "Searchable awesome issue") }
let!(:searchable_issue2) { create(:issue, title: 'Aw') }
@@ -139,6 +220,78 @@ describe Issuable do
it 'returns issues with a matching description for a query shorter than 3 chars' do
expect(issuable_class.full_search(searchable_issue2.description.downcase)).to eq([searchable_issue2])
end
+
+ context 'when matching columns is "title"' do
+ it 'returns issues with a matching title' do
+ expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'title'))
+ .to eq([searchable_issue])
+ end
+
+ it 'returns no issues with a matching description' do
+ expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'title'))
+ .to be_empty
+ end
+ end
+
+ context 'when matching columns is "description"' do
+ it 'returns no issues with a matching title' do
+ expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'description'))
+ .to be_empty
+ end
+
+ it 'returns issues with a matching description' do
+ expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'description'))
+ .to eq([searchable_issue])
+ end
+ end
+
+ context 'when matching columns is "title,description"' do
+ it 'returns issues with a matching title' do
+ expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'title,description'))
+ .to eq([searchable_issue])
+ end
+
+ it 'returns issues with a matching description' do
+ expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'title,description'))
+ .to eq([searchable_issue])
+ end
+ end
+
+ context 'when matching columns is nil"' do
+ it 'returns issues with a matching title' do
+ expect(issuable_class.full_search(searchable_issue.title, matched_columns: nil))
+ .to eq([searchable_issue])
+ end
+
+ it 'returns issues with a matching description' do
+ expect(issuable_class.full_search(searchable_issue.description, matched_columns: nil))
+ .to eq([searchable_issue])
+ end
+ end
+
+ context 'when matching columns is "invalid"' do
+ it 'returns issues with a matching title' do
+ expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'invalid'))
+ .to eq([searchable_issue])
+ end
+
+ it 'returns issues with a matching description' do
+ expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'invalid'))
+ .to eq([searchable_issue])
+ end
+ end
+
+ context 'when matching columns is "title,invalid"' do
+ it 'returns issues with a matching title' do
+ expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'title,invalid'))
+ .to eq([searchable_issue])
+ end
+
+ it 'returns no issues with a matching description' do
+ expect(issuable_class.full_search(searchable_issue.description, matched_columns: 'title,invalid'))
+ .to be_empty
+ end
+ end
end
describe '.to_ability_name' do
@@ -566,7 +719,7 @@ describe Issuable do
end
let(:merged_mr) { create(:merge_request, :merged, author: contributor, target_project: project, source_project: project) }
- let(:open_mr) { create(:merge_request, author: first_time_contributor, target_project: project, source_project: project) }
+ let(:open_mr) { create(:merge_request, author: first_time_contributor, target_project: project, source_project: project) }
let(:merged_mr_other_project) { create(:merge_request, :merged, author: first_time_contributor, target_project: other_project, source_project: other_project) }
context "for merge requests" do
diff --git a/spec/models/concerns/manual_inverse_association_spec.rb b/spec/models/concerns/manual_inverse_association_spec.rb
index aad40883854..ff4a04ea573 100644
--- a/spec/models/concerns/manual_inverse_association_spec.rb
+++ b/spec/models/concerns/manual_inverse_association_spec.rb
@@ -32,10 +32,10 @@ describe ManualInverseAssociation do
.not_to exceed_query_limit(0)
end
- it 'passes arguments to the default association method, to allow reloading' do
+ it 'allows reloading the relation' do
query_count = ActiveRecord::QueryRecorder.new do
instance.manual_association
- instance.manual_association(true)
+ instance.reload_manual_association
end.count
expect(query_count).to eq(2)
diff --git a/spec/models/concerns/maskable_spec.rb b/spec/models/concerns/maskable_spec.rb
new file mode 100644
index 00000000000..aeba7ad862f
--- /dev/null
+++ b/spec/models/concerns/maskable_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Maskable do
+ let(:variable) { build(:ci_variable) }
+
+ describe 'masked value validations' do
+ subject { variable }
+
+ context 'when variable is masked' do
+ before do
+ subject.masked = true
+ end
+
+ it { is_expected.not_to allow_value('hello').for(:value) }
+ it { is_expected.not_to allow_value('hello world').for(:value) }
+ it { is_expected.not_to allow_value('hello$VARIABLEworld').for(:value) }
+ it { is_expected.not_to allow_value('hello\rworld').for(:value) }
+ it { is_expected.to allow_value('helloworld').for(:value) }
+ end
+
+ context 'when variable is not masked' do
+ before do
+ subject.masked = false
+ end
+
+ it { is_expected.to allow_value('hello').for(:value) }
+ it { is_expected.to allow_value('hello world').for(:value) }
+ it { is_expected.to allow_value('hello$VARIABLEworld').for(:value) }
+ it { is_expected.to allow_value('hello\rworld').for(:value) }
+ it { is_expected.to allow_value('helloworld').for(:value) }
+ end
+ end
+
+ describe 'REGEX' do
+ subject { Maskable::REGEX }
+
+ it 'does not match strings shorter than 8 letters' do
+ expect(subject.match?('hello')).to eq(false)
+ end
+
+ it 'does not match strings with spaces' do
+ expect(subject.match?('hello world')).to eq(false)
+ end
+
+ it 'does not match strings with shell variables' do
+ expect(subject.match?('hello$VARIABLEworld')).to eq(false)
+ end
+
+ it 'does not match strings with escape characters' do
+ expect(subject.match?('hello\rworld')).to eq(false)
+ end
+
+ it 'does not match strings that span more than one line' do
+ string = <<~EOS
+ hello
+ world
+ EOS
+
+ expect(subject.match?(string)).to eq(false)
+ end
+
+ it 'matches valid strings' do
+ expect(subject.match?('helloworld')).to eq(true)
+ end
+ end
+
+ describe '#to_runner_variable' do
+ subject { variable.to_runner_variable }
+
+ it 'exposes the masked attribute' do
+ expect(subject).to include(:masked)
+ end
+ end
+end
diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb
index 87bf731340f..81ca5b638fe 100644
--- a/spec/models/concerns/milestoneish_spec.rb
+++ b/spec/models/concerns/milestoneish_spec.rb
@@ -9,8 +9,10 @@ describe Milestone, 'Milestoneish' do
let(:admin) { create(:admin) }
let(:project) { create(:project, :public) }
let(:milestone) { create(:milestone, project: project) }
- let!(:issue) { create(:issue, project: project, milestone: milestone) }
- let!(:security_issue_1) { create(:issue, :confidential, project: project, author: author, milestone: milestone) }
+ let(:label1) { create(:label, project: project) }
+ let(:label2) { create(:label, project: project) }
+ let!(:issue) { create(:issue, project: project, milestone: milestone, assignees: [member], labels: [label1]) }
+ let!(:security_issue_1) { create(:issue, :confidential, project: project, author: author, milestone: milestone, labels: [label2]) }
let!(:security_issue_2) { create(:issue, :confidential, project: project, assignees: [assignee], milestone: milestone) }
let!(:closed_issue_1) { create(:issue, :closed, project: project, milestone: milestone) }
let!(:closed_issue_2) { create(:issue, :closed, project: project, milestone: milestone) }
@@ -42,13 +44,102 @@ describe Milestone, 'Milestoneish' do
end
end
+ context 'attributes visibility' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:users) do
+ {
+ anonymous: nil,
+ non_member: non_member,
+ guest: guest,
+ member: member,
+ assignee: assignee
+ }
+ end
+
+ let(:project_visibility_levels) do
+ {
+ public: Gitlab::VisibilityLevel::PUBLIC,
+ internal: Gitlab::VisibilityLevel::INTERNAL,
+ private: Gitlab::VisibilityLevel::PRIVATE
+ }
+ end
+
+ describe '#issue_participants_visible_by_user' do
+ where(:visibility, :user_role, :result) do
+ :public | nil | [:member]
+ :public | :non_member | [:member]
+ :public | :guest | [:member]
+ :public | :member | [:member, :assignee]
+ :internal | nil | []
+ :internal | :non_member | [:member]
+ :internal | :guest | [:member]
+ :internal | :member | [:member, :assignee]
+ :private | nil | []
+ :private | :non_member | []
+ :private | :guest | [:member]
+ :private | :member | [:member, :assignee]
+ end
+
+ with_them do
+ before do
+ project.update(visibility_level: project_visibility_levels[visibility])
+ end
+
+ it 'returns the proper participants' do
+ user = users[user_role]
+ participants = result.map { |role| users[role] }
+
+ expect(milestone.issue_participants_visible_by_user(user)).to match_array(participants)
+ end
+ end
+ end
+
+ describe '#issue_labels_visible_by_user' do
+ let(:labels) do
+ {
+ label1: label1,
+ label2: label2
+ }
+ end
+
+ where(:visibility, :user_role, :result) do
+ :public | nil | [:label1]
+ :public | :non_member | [:label1]
+ :public | :guest | [:label1]
+ :public | :member | [:label1, :label2]
+ :internal | nil | []
+ :internal | :non_member | [:label1]
+ :internal | :guest | [:label1]
+ :internal | :member | [:label1, :label2]
+ :private | nil | []
+ :private | :non_member | []
+ :private | :guest | [:label1]
+ :private | :member | [:label1, :label2]
+ end
+
+ with_them do
+ before do
+ project.update(visibility_level: project_visibility_levels[visibility])
+ end
+
+ it 'returns the proper participants' do
+ user = users[user_role]
+ expected_labels = result.map { |label| labels[label] }
+
+ expect(milestone.issue_labels_visible_by_user(user)).to match_array(expected_labels)
+ end
+ end
+ end
+ end
+
describe '#sorted_merge_requests' do
it 'sorts merge requests by label priority' do
merge_request_1 = create(:labeled_merge_request, labels: [label_2], source_project: project, source_branch: 'branch_1', milestone: milestone)
merge_request_2 = create(:labeled_merge_request, labels: [label_1], source_project: project, source_branch: 'branch_2', milestone: milestone)
merge_request_3 = create(:labeled_merge_request, labels: [label_3], source_project: project, source_branch: 'branch_3', milestone: milestone)
- merge_requests = milestone.sorted_merge_requests
+ merge_requests = milestone.sorted_merge_requests(member)
expect(merge_requests.first).to eq(merge_request_2)
expect(merge_requests.second).to eq(merge_request_1)
@@ -56,6 +147,51 @@ describe Milestone, 'Milestoneish' do
end
end
+ describe '#merge_requests_visible_to_user' do
+ let(:merge_request) { create(:merge_request, source_project: project, milestone: milestone) }
+
+ context 'when project is private' do
+ before do
+ project.update(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it 'does not return any merge request for a non member' do
+ merge_requests = milestone.merge_requests_visible_to_user(non_member)
+ expect(merge_requests).to be_empty
+ end
+
+ it 'returns milestone merge requests for a member' do
+ merge_requests = milestone.merge_requests_visible_to_user(member)
+ expect(merge_requests).to contain_exactly(merge_request)
+ end
+ end
+
+ context 'when project is public' do
+ context 'when merge requests are available to anyone' do
+ it 'returns milestone merge requests for a non member' do
+ merge_requests = milestone.merge_requests_visible_to_user(non_member)
+ expect(merge_requests).to contain_exactly(merge_request)
+ end
+ end
+
+ context 'when merge requests are available to project members' do
+ before do
+ project.project_feature.update(merge_requests_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'does not return any merge request for a non member' do
+ merge_requests = milestone.merge_requests_visible_to_user(non_member)
+ expect(merge_requests).to be_empty
+ end
+
+ it 'returns milestone merge requests for a member' do
+ merge_requests = milestone.merge_requests_visible_to_user(member)
+ expect(merge_requests).to contain_exactly(merge_request)
+ end
+ end
+ end
+ end
+
describe '#closed_items_count' do
it 'does not count confidential issues for non project members' do
expect(milestone.closed_items_count(non_member)).to eq 2
diff --git a/spec/models/concerns/reactive_caching_spec.rb b/spec/models/concerns/reactive_caching_spec.rb
index 97a4c212f1c..03ae45e6b17 100644
--- a/spec/models/concerns/reactive_caching_spec.rb
+++ b/spec/models/concerns/reactive_caching_spec.rb
@@ -25,7 +25,7 @@ describe ReactiveCaching, :use_clean_rails_memory_store_caching do
def result
with_reactive_cache do |data|
- data / 2
+ data
end
end
end
@@ -64,7 +64,7 @@ describe ReactiveCaching, :use_clean_rails_memory_store_caching do
stub_reactive_cache(instance, 4)
end
- it { is_expected.to eq(2) }
+ it { is_expected.to eq(4) }
it 'does not enqueue a background worker' do
expect(ReactiveCachingWorker).not_to receive(:perform_async)
@@ -94,6 +94,14 @@ describe ReactiveCaching, :use_clean_rails_memory_store_caching do
end
end
end
+
+ context 'when cache contains non-nil but blank value' do
+ before do
+ stub_reactive_cache(instance, false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
end
describe '#clear_reactive_cache!' do
diff --git a/spec/models/concerns/redactable_spec.rb b/spec/models/concerns/redactable_spec.rb
index 7d320edd492..7feeaa54069 100644
--- a/spec/models/concerns/redactable_spec.rb
+++ b/spec/models/concerns/redactable_spec.rb
@@ -1,6 +1,10 @@
require 'spec_helper'
describe Redactable do
+ before do
+ stub_commonmark_sourcepos_disabled
+ end
+
shared_examples 'model with redactable field' do
it 'redacts unsubscribe token' do
model[field] = 'some text /sent_notifications/00000000000000000000000000000000/unsubscribe more text'
diff --git a/spec/models/concerns/sortable_spec.rb b/spec/models/concerns/sortable_spec.rb
index 39c16ae60af..0a9d2021a19 100644
--- a/spec/models/concerns/sortable_spec.rb
+++ b/spec/models/concerns/sortable_spec.rb
@@ -99,7 +99,7 @@ describe Sortable do
expect(ordered_group_names('id_desc')).to eq(%w(bbb BB AAA aa))
end
- it 'sorts groups by name via case-insentitive comparision' do
+ it 'sorts groups by name via case-insensitive comparision' do
expect(ordered_group_names('name_asc')).to eq(%w(aa AAA BB bbb))
expect(ordered_group_names('name_desc')).to eq(%w(bbb BB AAA aa))
end
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index 55d83bc3a6b..40cb4eef60a 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -97,14 +97,31 @@ describe ApplicationSetting, 'TokenAuthenticatable' do
end
describe PersonalAccessToken, 'TokenAuthenticatable' do
- let(:personal_access_token_name) { 'test-pat-01' }
+ shared_examples 'changes personal access token' do
+ it 'sets new token' do
+ subject
+
+ expect(personal_access_token.token).to eq(token_value)
+ expect(personal_access_token.token_digest).to eq(Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ shared_examples 'does not change personal access token' do
+ it 'sets new token' do
+ subject
+
+ expect(personal_access_token.token).to be(nil)
+ expect(personal_access_token.token_digest).to eq(token_digest)
+ end
+ end
+
let(:token_value) { 'token' }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
let(:user) { create(:user) }
let(:personal_access_token) do
- described_class.new(name: personal_access_token_name,
+ described_class.new(name: 'test-pat-01',
user_id: user.id,
scopes: [:api],
- token: token,
token_digest: token_digest)
end
@@ -115,239 +132,71 @@ describe PersonalAccessToken, 'TokenAuthenticatable' do
describe '.find_by_token' do
subject { PersonalAccessToken.find_by_token(token_value) }
- before do
+ it 'finds the token' do
personal_access_token.save
- end
- context 'token_digest already exists' do
- let(:token) { nil }
- let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
-
- it 'finds the token' do
- expect(subject).not_to be_nil
- expect(subject.name).to eql(personal_access_token_name)
- end
- end
-
- context 'token_digest does not exist' do
- let(:token) { token_value }
- let(:token_digest) { nil }
-
- it 'finds the token' do
- expect(subject).not_to be_nil
- expect(subject.name).to eql(personal_access_token_name)
- end
+ expect(subject).to eq(personal_access_token)
end
end
describe '#set_token' do
let(:new_token_value) { 'new-token' }
- subject { personal_access_token.set_token(new_token_value) }
-
- context 'token_digest already exists' do
- let(:token) { nil }
- let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
- it 'overwrites token_digest' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(new_token_value)
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(new_token_value))
- end
- end
-
- context 'token_digest does not exist but token does' do
- let(:token) { token_value }
- let(:token_digest) { nil }
-
- it 'creates new token_digest and clears token' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(new_token_value)
- expect(personal_access_token.token_digest).to eql(Gitlab::CryptoHelper.sha256(new_token_value))
- end
- end
-
- context 'token_digest does not exist, nor token' do
- let(:token) { nil }
- let(:token_digest) { nil }
+ subject { personal_access_token.set_token(new_token_value) }
- it 'creates new token_digest' do
- subject
+ it 'sets new token' do
+ subject
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(new_token_value)
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(new_token_value))
- end
+ expect(personal_access_token.token).to eq(new_token_value)
+ expect(personal_access_token.token_digest).to eq(Gitlab::CryptoHelper.sha256(new_token_value))
end
end
describe '#ensure_token' do
subject { personal_access_token.ensure_token }
- context 'token_digest already exists' do
- let(:token) { nil }
- let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
-
- it 'does not change token fields' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to be_nil
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
- end
- end
-
- context 'token_digest does not exist but token does' do
- let(:token) { token_value }
+ context 'token_digest does not exist' do
let(:token_digest) { nil }
- it 'does not change token fields' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to eql(token_value)
- expect(personal_access_token.token).to eql(token_value)
- expect(personal_access_token.token_digest).to be_nil
- end
+ it_behaves_like 'changes personal access token'
end
- context 'token_digest does not exist, nor token' do
- let(:token) { nil }
- let(:token_digest) { nil }
-
- it 'creates token_digest' do
- subject
+ context 'token_digest already generated' do
+ let(:token_digest) { 's3cr3t' }
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(token_value)
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
- end
+ it_behaves_like 'does not change personal access token'
end
end
describe '#ensure_token!' do
subject { personal_access_token.ensure_token! }
- context 'token_digest already exists' do
- let(:token) { nil }
- let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
-
- it 'does not change token fields' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to be_nil
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
- end
- end
-
- context 'token_digest does not exist but token does' do
- let(:token) { token_value }
+ context 'token_digest does not exist' do
let(:token_digest) { nil }
- it 'does not change token fields' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to eql(token_value)
- expect(personal_access_token.token).to eql(token_value)
- expect(personal_access_token.token_digest).to be_nil
- end
+ it_behaves_like 'changes personal access token'
end
- context 'token_digest does not exist, nor token' do
- let(:token) { nil }
- let(:token_digest) { nil }
+ context 'token_digest already generated' do
+ let(:token_digest) { 's3cr3t' }
- it 'creates token_digest' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(token_value)
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
- end
+ it_behaves_like 'does not change personal access token'
end
end
describe '#reset_token!' do
subject { personal_access_token.reset_token! }
- context 'token_digest already exists' do
- let(:token) { nil }
- let(:token_digest) { Gitlab::CryptoHelper.sha256('old-token') }
-
- it 'creates new token_digest' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(token_value)
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
- end
- end
-
- context 'token_digest does not exist but token does' do
- let(:token) { 'old-token' }
- let(:token_digest) { nil }
-
- it 'creates new token_digest and clears token' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(token_value)
- expect(personal_access_token.token_digest).to eql(Gitlab::CryptoHelper.sha256(token_value))
- end
- end
-
- context 'token_digest does not exist, nor token' do
- let(:token) { nil }
+ context 'token_digest does not exist' do
let(:token_digest) { nil }
- it 'creates new token_digest' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(token_value)
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
- end
- end
-
- context 'token_digest exists and newly generated token would be the same' do
- let(:token) { nil }
- let(:token_digest) { Gitlab::CryptoHelper.sha256('old-token') }
-
- before do
- personal_access_token.save
- allow(Devise).to receive(:friendly_token).and_return(
- 'old-token', token_value, 'boom!')
- end
-
- it 'regenerates a new token_digest' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(token_value)
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
- end
+ it_behaves_like 'changes personal access token'
end
- context 'token exists and newly generated token would be the same' do
- let(:token) { 'old-token' }
- let(:token_digest) { nil }
-
- before do
- personal_access_token.save
- allow(Devise).to receive(:friendly_token).and_return(
- 'old-token', token_value, 'boom!')
- end
+ context 'token_digest already generated' do
+ let(:token_digest) { 's3cr3t' }
- it 'regenerates a new token_digest' do
- subject
-
- expect(personal_access_token.read_attribute('token')).to be_nil
- expect(personal_access_token.token).to eql(token_value)
- expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
- end
+ it_behaves_like 'changes personal access token'
end
end
end
diff --git a/spec/models/concerns/token_authenticatable_strategies/base_spec.rb b/spec/models/concerns/token_authenticatable_strategies/base_spec.rb
index 6605f1f5a5f..2a0182b4294 100644
--- a/spec/models/concerns/token_authenticatable_strategies/base_spec.rb
+++ b/spec/models/concerns/token_authenticatable_strategies/base_spec.rb
@@ -15,7 +15,7 @@ describe TokenAuthenticatableStrategies::Base do
context 'when encrypted strategy is specified' do
it 'fabricates encrypted strategy object' do
- strategy = described_class.fabricate(instance, field, encrypted: true)
+ strategy = described_class.fabricate(instance, field, encrypted: :required)
expect(strategy).to be_a TokenAuthenticatableStrategies::Encrypted
end
@@ -23,7 +23,7 @@ describe TokenAuthenticatableStrategies::Base do
context 'when no strategy is specified' do
it 'fabricates insecure strategy object' do
- strategy = described_class.fabricate(instance, field, something: true)
+ strategy = described_class.fabricate(instance, field, something: :required)
expect(strategy).to be_a TokenAuthenticatableStrategies::Insecure
end
@@ -31,35 +31,9 @@ describe TokenAuthenticatableStrategies::Base do
context 'when incompatible options are provided' do
it 'raises an error' do
- expect { described_class.fabricate(instance, field, digest: true, encrypted: true) }
+ expect { described_class.fabricate(instance, field, digest: true, encrypted: :required) }
.to raise_error ArgumentError
end
end
end
-
- describe '#fallback?' do
- context 'when fallback is set' do
- it 'recognizes fallback setting' do
- strategy = described_class.new(instance, field, fallback: true)
-
- expect(strategy.fallback?).to be true
- end
- end
-
- context 'when fallback is not a valid value' do
- it 'raises an error' do
- strategy = described_class.new(instance, field, fallback: 'something')
-
- expect { strategy.fallback? }.to raise_error ArgumentError
- end
- end
-
- context 'when fallback is not set' do
- it 'raises an error' do
- strategy = described_class.new(instance, field, {})
-
- expect(strategy.fallback?).to eq false
- end
- end
- end
end
diff --git a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
index 93cab80cb1f..ca38f86c5ab 100644
--- a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
+++ b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
@@ -12,19 +12,9 @@ describe TokenAuthenticatableStrategies::Encrypted do
described_class.new(model, 'some_field', options)
end
- describe '.new' do
- context 'when fallback and migration strategies are set' do
- let(:options) { { fallback: true, migrating: true } }
-
- it 'raises an error' do
- expect { subject }.to raise_error ArgumentError, /not compatible/
- end
- end
- end
-
describe '#find_token_authenticatable' do
- context 'when using fallback strategy' do
- let(:options) { { fallback: true } }
+ context 'when using optional strategy' do
+ let(:options) { { encrypted: :optional } }
it 'finds the encrypted resource by cleartext' do
allow(model).to receive(:find_by)
@@ -50,7 +40,7 @@ describe TokenAuthenticatableStrategies::Encrypted do
end
context 'when using migration strategy' do
- let(:options) { { migrating: true } }
+ let(:options) { { encrypted: :migrating } }
it 'finds the cleartext resource by cleartext' do
allow(model).to receive(:find_by)
@@ -73,8 +63,8 @@ describe TokenAuthenticatableStrategies::Encrypted do
end
describe '#get_token' do
- context 'when using fallback strategy' do
- let(:options) { { fallback: true } }
+ context 'when using optional strategy' do
+ let(:options) { { encrypted: :optional } }
it 'returns decrypted token when an encrypted token is present' do
allow(instance).to receive(:read_attribute)
@@ -98,7 +88,7 @@ describe TokenAuthenticatableStrategies::Encrypted do
end
context 'when using migration strategy' do
- let(:options) { { migrating: true } }
+ let(:options) { { encrypted: :migrating } }
it 'returns cleartext token when an encrypted token is present' do
allow(instance).to receive(:read_attribute)
@@ -127,8 +117,8 @@ describe TokenAuthenticatableStrategies::Encrypted do
end
describe '#set_token' do
- context 'when using fallback strategy' do
- let(:options) { { fallback: true } }
+ context 'when using optional strategy' do
+ let(:options) { { encrypted: :optional } }
it 'writes encrypted token and removes plaintext token and returns it' do
expect(instance).to receive(:[]=)
@@ -141,7 +131,7 @@ describe TokenAuthenticatableStrategies::Encrypted do
end
context 'when using migration strategy' do
- let(:options) { { migrating: true } }
+ let(:options) { { encrypted: :migrating } }
it 'writes encrypted token and writes plaintext token' do
expect(instance).to receive(:[]=)
diff --git a/spec/models/diff_viewer/base_spec.rb b/spec/models/diff_viewer/base_spec.rb
index c90b32c5d77..f4efe5a7b3a 100644
--- a/spec/models/diff_viewer/base_spec.rb
+++ b/spec/models/diff_viewer/base_spec.rb
@@ -58,7 +58,7 @@ describe DiffViewer::Base do
context 'when the binaryness does not match' do
before do
- allow_any_instance_of(Blob).to receive(:binary?).and_return(true)
+ allow_any_instance_of(Blob).to receive(:binary_in_repo?).and_return(true)
end
it 'returns false' do
@@ -141,4 +141,25 @@ describe DiffViewer::Base do
end
end
end
+
+ describe '#render_error_message' do
+ it 'returns nothing when no render_error' do
+ expect(viewer.render_error).to be_nil
+ expect(viewer.render_error_message).to be_nil
+ end
+
+ context 'when render_error error' do
+ before do
+ allow(viewer).to receive(:render_error).and_return(:too_large)
+ end
+
+ it 'returns an error message' do
+ expect(viewer.render_error_message).to include('it is too large')
+ end
+
+ it 'includes a "view the blob" link' do
+ expect(viewer.render_error_message).to include('view the blob')
+ end
+ end
+ end
end
diff --git a/spec/models/diff_viewer/server_side_spec.rb b/spec/models/diff_viewer/server_side_spec.rb
index 98a8f6d4cc9..86b14b6ebf3 100644
--- a/spec/models/diff_viewer/server_side_spec.rb
+++ b/spec/models/diff_viewer/server_side_spec.rb
@@ -32,4 +32,24 @@ describe DiffViewer::ServerSide do
end
end
end
+
+ describe '#render_error_reason' do
+ context 'when the diff file is stored externally' do
+ before do
+ allow(diff_file).to receive(:stored_externally?).and_return(true)
+ end
+
+ it 'returns error message if stored in LFS' do
+ allow(diff_file).to receive(:external_storage).and_return(:lfs)
+
+ expect(subject.render_error_message).to include('it is stored in LFS')
+ end
+
+ it 'returns error message if stored externally' do
+ allow(diff_file).to receive(:external_storage).and_return(:foo)
+
+ expect(subject.render_error_message).to include('it is stored externally')
+ end
+ end
+ end
end
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 9a3f1f1c5a1..ab1b306e597 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -41,6 +41,76 @@ describe Environment do
end
end
+ describe '.for_name_like' do
+ subject { project.environments.for_name_like(query, limit: limit) }
+
+ let!(:environment) { create(:environment, name: 'production', project: project) }
+ let(:query) { 'pro' }
+ let(:limit) { 5 }
+
+ it 'returns a found name' do
+ is_expected.to include(environment)
+ end
+
+ context 'when query is production' do
+ let(:query) { 'production' }
+
+ it 'returns a found name' do
+ is_expected.to include(environment)
+ end
+ end
+
+ context 'when query is productionA' do
+ let(:query) { 'productionA' }
+
+ it 'returns empty array' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when query is empty' do
+ let(:query) { '' }
+
+ it 'returns a found name' do
+ is_expected.to include(environment)
+ end
+ end
+
+ context 'when query is nil' do
+ let(:query) { }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(NoMethodError)
+ end
+ end
+
+ context 'when query is partially matched in the middle of environment name' do
+ let(:query) { 'duction' }
+
+ it 'returns empty array' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when query contains a wildcard character' do
+ let(:query) { 'produc%' }
+
+ it 'prevents wildcard injection' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ describe '.pluck_names' do
+ subject { described_class.pluck_names }
+
+ let!(:environment) { create(:environment, name: 'production', project: project) }
+
+ it 'plucks names' do
+ is_expected.to eq(%w[production])
+ end
+ end
+
describe '#expire_etag_cache' do
let(:store) { Gitlab::EtagCaching::Store.new }
@@ -94,6 +164,28 @@ describe Environment do
end
end
+ describe '#name_without_type' do
+ context 'when it is inside a folder' do
+ subject(:environment) do
+ create(:environment, name: 'staging/review-1')
+ end
+
+ it 'returns name without folder' do
+ expect(environment.name_without_type).to eq 'review-1'
+ end
+ end
+
+ context 'when the environment if a top-level item itself' do
+ subject(:environment) do
+ create(:environment, name: 'production')
+ end
+
+ it 'returns full name' do
+ expect(environment.name_without_type).to eq 'production'
+ end
+ end
+ end
+
describe '#nullify_external_url' do
it 'replaces a blank url with nil' do
env = build(:environment, external_url: "")
diff --git a/spec/models/error_tracking/project_error_tracking_setting_spec.rb b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
new file mode 100644
index 00000000000..cbde13a2c7a
--- /dev/null
+++ b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
@@ -0,0 +1,332 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ErrorTracking::ProjectErrorTrackingSetting do
+ include ReactiveCachingHelpers
+
+ set(:project) { create(:project) }
+
+ subject { create(:project_error_tracking_setting, project: project) }
+
+ describe 'Associations' do
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe 'Validations' do
+ context 'when api_url is over 255 chars' do
+ before do
+ subject.api_url = 'https://' + 'a' * 250
+ end
+
+ it 'fails validation' do
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages[:api_url]).to include('is too long (maximum is 255 characters)')
+ end
+ end
+
+ context 'With unsafe url' do
+ it 'fails validation' do
+ subject.api_url = "https://replaceme.com/'><script>alert(document.cookie)</script>"
+
+ expect(subject).not_to be_valid
+ end
+ end
+
+ context 'presence validations' do
+ using RSpec::Parameterized::TableSyntax
+
+ valid_api_url = 'http://example.com/api/0/projects/org-slug/proj-slug/'
+ valid_token = 'token'
+
+ where(:enabled, :token, :api_url, :valid?) do
+ true | nil | nil | false
+ true | nil | valid_api_url | false
+ true | valid_token | nil | false
+ true | valid_token | valid_api_url | true
+ false | nil | nil | true
+ false | nil | valid_api_url | true
+ false | valid_token | nil | true
+ false | valid_token | valid_api_url | true
+ end
+
+ with_them do
+ before do
+ subject.enabled = enabled
+ subject.token = token
+ subject.api_url = api_url
+ end
+
+ it { expect(subject.valid?).to eq(valid?) }
+ end
+ end
+
+ context 'URL path' do
+ it 'fails validation without api/0/projects' do
+ subject.api_url = 'http://gitlab.com/project1/something'
+
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages[:api_url]).to include('is invalid')
+ end
+
+ it 'fails validation without org and project slugs' do
+ subject.api_url = 'http://gitlab.com/api/0/projects/'
+
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages[:project]).to include('is a required field')
+ end
+
+ it 'fails validation when api_url has extra parts' do
+ subject.api_url = 'http://gitlab.com/api/0/projects/org/proj/something'
+
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages[:api_url]).to include("is invalid")
+ end
+
+ it 'fails validation when api_url has less parts' do
+ subject.api_url = 'http://gitlab.com/api/0/projects/org'
+
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages[:api_url]).to include("is invalid")
+ end
+
+ it 'passes validation with correct path' do
+ subject.api_url = 'http://gitlab.com/api/0/projects/project1/something'
+
+ expect(subject).to be_valid
+ end
+ end
+
+ context 'non ascii chars in api_url' do
+ before do
+ subject.api_url = 'http://gitlab.com/api/0/projects/project1/something€'
+ end
+
+ it 'fails validation' do
+ expect(subject).not_to be_valid
+ end
+ end
+ end
+
+ describe '#sentry_external_url' do
+ let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
+
+ before do
+ subject.api_url = sentry_url
+ end
+
+ it 'returns the correct url' do
+ expect(subject.class).to receive(:extract_sentry_external_url).with(sentry_url).and_call_original
+
+ result = subject.sentry_external_url
+
+ expect(result).to eq('https://sentrytest.gitlab.com/sentry-org/sentry-project')
+ end
+ end
+
+ describe '#sentry_client' do
+ it 'returns sentry client' do
+ expect(subject.sentry_client).to be_a(Sentry::Client)
+ end
+ end
+
+ describe '#list_sentry_issues' do
+ let(:issues) { [:list, :of, :issues] }
+
+ let(:opts) do
+ { issue_status: 'unresolved', limit: 10 }
+ end
+
+ let(:result) do
+ subject.list_sentry_issues(**opts)
+ end
+
+ context 'when cached' do
+ let(:sentry_client) { spy(:sentry_client) }
+
+ before do
+ stub_reactive_cache(subject, issues, opts)
+ synchronous_reactive_cache(subject)
+
+ expect(subject).to receive(:sentry_client).and_return(sentry_client)
+ end
+
+ it 'returns cached issues' do
+ expect(sentry_client).to receive(:list_issues).with(opts)
+ .and_return(issues)
+
+ expect(result).to eq(issues: issues)
+ end
+ end
+
+ context 'when not cached' do
+ it 'returns nil' do
+ expect(subject).not_to receive(:sentry_client)
+
+ expect(result).to be_nil
+ end
+ end
+
+ context 'when sentry client raises exception' do
+ let(:sentry_client) { spy(:sentry_client) }
+
+ before do
+ synchronous_reactive_cache(subject)
+
+ allow(subject).to receive(:sentry_client).and_return(sentry_client)
+ allow(sentry_client).to receive(:list_issues).with(opts)
+ .and_raise(Sentry::Client::Error, 'error message')
+ end
+
+ it 'returns error' do
+ expect(result).to eq(error: 'error message')
+ expect(subject).to have_received(:sentry_client)
+ expect(sentry_client).to have_received(:list_issues)
+ end
+ end
+ end
+
+ describe '#list_sentry_projects' do
+ let(:projects) { [:list, :of, :projects] }
+ let(:sentry_client) { spy(:sentry_client) }
+
+ it 'calls sentry client' do
+ expect(subject).to receive(:sentry_client).and_return(sentry_client)
+ expect(sentry_client).to receive(:list_projects).and_return(projects)
+
+ result = subject.list_sentry_projects
+
+ expect(result).to eq(projects: projects)
+ end
+ end
+
+ context 'slugs' do
+ shared_examples_for 'slug from api_url' do |method, slug|
+ context 'when api_url is correct' do
+ before do
+ subject.api_url = 'http://gitlab.com/api/0/projects/org-slug/project-slug/'
+ end
+
+ it 'returns slug' do
+ expect(subject.public_send(method)).to eq(slug)
+ end
+ end
+
+ context 'when api_url is blank' do
+ before do
+ subject.api_url = nil
+ end
+
+ it 'returns nil' do
+ expect(subject.public_send(method)).to be_nil
+ end
+ end
+ end
+
+ it_behaves_like 'slug from api_url', :project_slug, 'project-slug'
+ it_behaves_like 'slug from api_url', :organization_slug, 'org-slug'
+ end
+
+ context 'names from api_url' do
+ shared_examples_for 'name from api_url' do |name, titleized_slug|
+ context 'name is present in DB' do
+ it 'returns name from DB' do
+ subject[name] = 'Sentry name'
+ subject.api_url = 'http://gitlab.com/api/0/projects/org-slug/project-slug'
+
+ expect(subject.public_send(name)).to eq('Sentry name')
+ end
+ end
+
+ context 'name is null in DB' do
+ it 'titleizes and returns slug from api_url' do
+ subject[name] = nil
+ subject.api_url = 'http://gitlab.com/api/0/projects/org-slug/project-slug'
+
+ expect(subject.public_send(name)).to eq(titleized_slug)
+ end
+
+ it 'returns nil when api_url is incorrect' do
+ subject[name] = nil
+ subject.api_url = 'http://gitlab.com/api/0/projects/'
+
+ expect(subject.public_send(name)).to be_nil
+ end
+
+ it 'returns nil when api_url is blank' do
+ subject[name] = nil
+ subject.api_url = nil
+
+ expect(subject.public_send(name)).to be_nil
+ end
+ end
+ end
+
+ it_behaves_like 'name from api_url', :organization_name, 'Org Slug'
+ it_behaves_like 'name from api_url', :project_name, 'Project Slug'
+ end
+
+ describe '.build_api_url_from' do
+ it 'correctly builds api_url with slugs' do
+ api_url = described_class.build_api_url_from(
+ api_host: 'http://sentry.com/',
+ organization_slug: 'org-slug',
+ project_slug: 'proj-slug'
+ )
+
+ expect(api_url).to eq('http://sentry.com/api/0/projects/org-slug/proj-slug/')
+ end
+
+ it 'correctly builds api_url without slugs' do
+ api_url = described_class.build_api_url_from(
+ api_host: 'http://sentry.com/',
+ organization_slug: nil,
+ project_slug: nil
+ )
+
+ expect(api_url).to eq('http://sentry.com/api/0/projects/')
+ end
+
+ it 'does not raise exception with invalid url' do
+ api_url = described_class.build_api_url_from(
+ api_host: ':::',
+ organization_slug: 'org-slug',
+ project_slug: 'proj-slug'
+ )
+
+ expect(api_url).to eq(':::')
+ end
+
+ it 'returns nil when api_host is blank' do
+ api_url = described_class.build_api_url_from(
+ api_host: '',
+ organization_slug: 'org-slug',
+ project_slug: 'proj-slug'
+ )
+
+ expect(api_url).to be_nil
+ end
+ end
+
+ describe '#api_host' do
+ context 'when api_url exists' do
+ before do
+ subject.api_url = 'https://example.com/api/0/projects/org-slug/proj-slug/'
+ end
+
+ it 'extracts the api_host from api_url' do
+ expect(subject.api_host).to eq('https://example.com/')
+ end
+ end
+
+ context 'when api_url is nil' do
+ before do
+ subject.api_url = nil
+ end
+
+ it 'returns nil' do
+ expect(subject.api_url).to eq(nil)
+ end
+ end
+ end
+end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 81748681528..ce4f8ee4705 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -243,6 +243,20 @@ describe Event do
expect(event.visible_to_user?(admin)).to eq true
end
end
+
+ context 'private project' do
+ let(:project) { create(:project, :private) }
+ let(:target) { note_on_issue }
+
+ it do
+ expect(event.visible_to_user?(non_member)).to eq false
+ expect(event.visible_to_user?(author)).to eq false
+ expect(event.visible_to_user?(assignee)).to eq false
+ expect(event.visible_to_user?(member)).to eq true
+ expect(event.visible_to_user?(guest)).to eq true
+ expect(event.visible_to_user?(admin)).to eq true
+ end
+ end
end
context 'merge request diff note event' do
@@ -265,8 +279,8 @@ describe Event do
it do
expect(event.visible_to_user?(non_member)).to eq false
- expect(event.visible_to_user?(author)).to eq true
- expect(event.visible_to_user?(assignee)).to eq true
+ expect(event.visible_to_user?(author)).to eq false
+ expect(event.visible_to_user?(assignee)).to eq false
expect(event.visible_to_user?(member)).to eq true
expect(event.visible_to_user?(guest)).to eq false
expect(event.visible_to_user?(admin)).to eq true
@@ -385,10 +399,7 @@ describe Event do
expect(event.visible_to_user?(nil)).to be_falsy
expect(event.visible_to_user?(non_member)).to be_falsy
expect(event.visible_to_user?(author)).to be_truthy
-
- # It is very unexpected that a private personal snippet is not visible
- # to an instance administrator. This should be fixed in the future.
- expect(event.visible_to_user?(admin)).to be_falsy
+ expect(event.visible_to_user?(admin)).to be_truthy
end
end
end
diff --git a/spec/models/external_issue_spec.rb b/spec/models/external_issue_spec.rb
index c8748daf46b..83ba22caa03 100644
--- a/spec/models/external_issue_spec.rb
+++ b/spec/models/external_issue_spec.rb
@@ -30,7 +30,7 @@ describe ExternalIssue do
end
context 'if issue id is a number' do
- let(:issue) { described_class.new('1234', project) }
+ let(:issue) { described_class.new('1234', project) }
it 'returns the issue ID prefixed by #' do
expect(issue.reference_link_text).to eq '#1234'
end
diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb
index b6355455c1d..f93904065c7 100644
--- a/spec/models/global_milestone_spec.rb
+++ b/spec/models/global_milestone_spec.rb
@@ -65,56 +65,109 @@ describe GlobalMilestone do
)
end
- before do
- projects = [
+ let!(:projects) do
+ [
project1,
project2,
project3
]
-
- @global_milestones = described_class.build_collection(projects, {})
end
- it 'has all project milestones' do
- expect(@global_milestones.count).to eq(2)
+ let!(:global_milestones) { described_class.build_collection(projects, {}) }
+
+ context 'when building a collection of milestones' do
+ it 'has all project milestones' do
+ expect(global_milestones.count).to eq(6)
+ end
+
+ it 'has all project milestones titles' do
+ expect(global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'Milestone v1.2', 'Milestone v1.2', 'VD-123', 'VD-123', 'VD-123'])
+ end
+
+ it 'has all project milestones' do
+ expect(global_milestones.size).to eq(6)
+ end
+
+ it 'sorts collection by due date' do
+ expect(global_milestones.map(&:due_date)).to eq [milestone1_due_date, milestone1_due_date, milestone1_due_date, nil, nil, nil]
+ end
+
+ it 'filters milestones by search_title when params[:search_title] is present' do
+ global_milestones = described_class.build_collection(projects, { search_title: 'v1.2' })
+
+ expect(global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'Milestone v1.2', 'Milestone v1.2'])
+ end
end
- it 'has all project milestones titles' do
- expect(@global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'VD-123'])
+ context 'when adding new milestones' do
+ it 'does not add more queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ described_class.build_collection(projects, {})
+ end.count
+
+ create_list(:milestone, 3, project: project3)
+
+ expect do
+ described_class.build_collection(projects, {})
+ end.not_to exceed_all_query_limit(control_count)
+ end
end
+ end
+
+ describe '.states_count' do
+ context 'when the projects have milestones' do
+ before do
+ create(:closed_milestone, title: 'Active Group Milestone', project: project3)
+ create(:active_milestone, title: 'Active Group Milestone', project: project1)
+ create(:active_milestone, title: 'Active Group Milestone', project: project2)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project1)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project2)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project3)
+ create(:closed_milestone, title: 'Closed Group Milestone 4', group: group)
+ end
- it 'has all project milestones' do
- expect(@global_milestones.map { |group_milestone| group_milestone.milestones.count }.sum).to eq(6)
+ it 'returns the quantity of global milestones and group milestones in each possible state' do
+ expected_count = { opened: 2, closed: 5, all: 7 }
+
+ count = described_class.states_count(Project.all, group)
+
+ expect(count).to eq(expected_count)
+ end
+
+ it 'returns the quantity of global milestones in each possible state' do
+ expected_count = { opened: 2, closed: 4, all: 6 }
+
+ count = described_class.states_count(Project.all)
+
+ expect(count).to eq(expected_count)
+ end
end
- it 'sorts collection by due date' do
- expect(@global_milestones.map(&:due_date)).to eq [nil, milestone1_due_date]
+ context 'when the projects do not have milestones' do
+ before do
+ project1
+ end
+
+ it 'returns 0 as the quantity of global milestones in each state' do
+ expected_count = { opened: 0, closed: 0, all: 0 }
+
+ count = described_class.states_count(Project.all)
+
+ expect(count).to eq(expected_count)
+ end
end
end
describe '#initialize' do
let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) }
- let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) }
- let(:milestone1_project3) { create(:milestone, title: "Milestone v1.2", project: project3) }
-
- before do
- milestones =
- [
- milestone1_project1,
- milestone1_project2,
- milestone1_project3
- ]
- milestones_relation = Milestone.where(id: milestones.map(&:id))
-
- @global_milestone = described_class.new(milestone1_project1.title, milestones_relation)
- end
+ subject(:global_milestone) { described_class.new(milestone1_project1) }
it 'has exactly one group milestone' do
- expect(@global_milestone.title).to eq('Milestone v1.2')
+ expect(global_milestone.title).to eq('Milestone v1.2')
end
it 'has all project milestones with the same title' do
- expect(@global_milestone.milestones.count).to eq(3)
+ expect(global_milestone.milestone).to eq(milestone1_project1)
end
end
@@ -122,7 +175,7 @@ describe GlobalMilestone do
let(:milestone) { create(:milestone, title: "git / test", project: project1) }
it 'strips out slashes and spaces' do
- global_milestone = described_class.new(milestone.title, Milestone.where(id: milestone.id))
+ global_milestone = described_class.new(milestone)
expect(global_milestone.safe_title).to eq('git-test')
end
@@ -132,11 +185,8 @@ describe GlobalMilestone do
context 'when at least one milestone is active' do
it 'returns active' do
title = 'Active Group Milestone'
- milestones = [
- create(:active_milestone, title: title),
- create(:closed_milestone, title: title)
- ]
- global_milestone = described_class.new(title, milestones)
+
+ global_milestone = described_class.new(create(:active_milestone, title: title))
expect(global_milestone.state).to eq('active')
end
@@ -145,11 +195,8 @@ describe GlobalMilestone do
context 'when all milestones are closed' do
it 'returns closed' do
title = 'Closed Group Milestone'
- milestones = [
- create(:closed_milestone, title: title),
- create(:closed_milestone, title: title)
- ]
- global_milestone = described_class.new(title, milestones)
+
+ global_milestone = described_class.new(create(:closed_milestone, title: title))
expect(global_milestone.state).to eq('closed')
end
diff --git a/spec/models/gpg_key_spec.rb b/spec/models/gpg_key_spec.rb
index 33e6f1de3d1..58a1d2e4ea2 100644
--- a/spec/models/gpg_key_spec.rb
+++ b/spec/models/gpg_key_spec.rb
@@ -199,7 +199,7 @@ describe GpgKey do
gpg_key.revoke
- expect(gpg_key.subkeys(true)).to be_blank
+ expect(gpg_key.subkeys.reload).to be_blank
end
it 'invalidates all signatures associated to the subkeys' do
diff --git a/spec/models/gpg_signature_spec.rb b/spec/models/gpg_signature_spec.rb
index cdd7dea2064..e90319c39b1 100644
--- a/spec/models/gpg_signature_spec.rb
+++ b/spec/models/gpg_signature_spec.rb
@@ -23,6 +23,41 @@ RSpec.describe GpgSignature do
it { is_expected.to validate_presence_of(:gpg_key_primary_keyid) }
end
+ describe '.safe_create!' do
+ let(:attributes) do
+ {
+ commit_sha: commit_sha,
+ project: project,
+ gpg_key_primary_keyid: gpg_key.keyid
+ }
+ end
+
+ it 'finds a signature by commit sha if it existed' do
+ gpg_signature
+
+ expect(described_class.safe_create!(commit_sha: commit_sha)).to eq(gpg_signature)
+ end
+
+ it 'creates a new signature if it was not found' do
+ expect { described_class.safe_create!(attributes) }.to change { described_class.count }.by(1)
+ end
+
+ it 'assigns the correct attributes when creating' do
+ signature = described_class.safe_create!(attributes)
+
+ expect(signature.project).to eq(project)
+ expect(signature.commit_sha).to eq(commit_sha)
+ expect(signature.gpg_key_primary_keyid).to eq(gpg_key.keyid)
+ end
+
+ it 'does not raise an error in case of a race condition' do
+ expect(described_class).to receive(:find_or_create_by).and_raise(ActiveRecord::RecordNotUnique)
+ allow(described_class).to receive(:find_or_create_by).and_call_original
+
+ described_class.safe_create!(attributes)
+ end
+ end
+
describe '#commit' do
it 'fetches the commit through the project' do
expect_any_instance_of(Project).to receive(:commit).with(commit_sha).and_return(commit)
diff --git a/spec/models/group_milestone_spec.rb b/spec/models/group_milestone_spec.rb
index b60676afc91..fcc33cd95fe 100644
--- a/spec/models/group_milestone_spec.rb
+++ b/spec/models/group_milestone_spec.rb
@@ -20,13 +20,36 @@ describe GroupMilestone do
end
describe '.build_collection' do
- before do
- project_milestone
+ let(:group) { create(:group) }
+ let(:project1) { create(:project, group: group) }
+ let(:project2) { create(:project, path: 'gitlab-ci', group: group) }
+ let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) }
+
+ let!(:projects) do
+ [
+ project1,
+ project2,
+ project3
+ ]
end
it 'returns array of milestones, each with group assigned' do
milestones = described_class.build_collection(group, [project], {})
expect(milestones).to all(have_attributes(group: group))
end
+
+ context 'when adding new milestones' do
+ it 'does not add more queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ described_class.build_collection(group, projects, {})
+ end.count
+
+ create(:milestone, title: 'This title', project: project1)
+
+ expect do
+ described_class.build_collection(group, projects, {})
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
end
end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index e63881242f6..9dc32a815d8 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -722,6 +722,42 @@ describe Group do
end
end
+ describe '#highest_group_member', :nested_groups do
+ let(:nested_group) { create(:group, parent: group) }
+ let(:nested_group_2) { create(:group, parent: nested_group) }
+ let(:user) { create(:user) }
+
+ subject(:highest_group_member) { nested_group_2.highest_group_member(user) }
+
+ context 'when the user is not a member of any group in the hierarchy' do
+ it 'returns nil' do
+ expect(highest_group_member).to be_nil
+ end
+ end
+
+ context 'when the user is only a member of one group in the hierarchy' do
+ before do
+ nested_group.add_developer(user)
+ end
+
+ it 'returns that group member' do
+ expect(highest_group_member.access_level).to eq(Gitlab::Access::DEVELOPER)
+ end
+ end
+
+ context 'when the user is a member of several groups in the hierarchy' do
+ before do
+ group.add_owner(user)
+ nested_group.add_developer(user)
+ nested_group_2.add_maintainer(user)
+ end
+
+ it 'returns the group member with the highest access level' do
+ expect(highest_group_member.access_level).to eq(Gitlab::Access::OWNER)
+ end
+ end
+ end
+
describe '#has_parent?' do
context 'when the group has a parent' do
it 'should be truthy' do
diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb
index a5ce245c21d..e1a7a59dfd1 100644
--- a/spec/models/identity_spec.rb
+++ b/spec/models/identity_spec.rb
@@ -10,6 +10,40 @@ describe Identity do
it { is_expected.to respond_to(:extern_uid) }
end
+ describe 'validations' do
+ set(:user) { create(:user) }
+
+ context 'with existing user and provider' do
+ before do
+ create(:identity, provider: 'ldapmain', user_id: user.id)
+ end
+
+ it 'returns false for a duplicate entry' do
+ identity = user.identities.build(provider: 'ldapmain', user_id: user.id)
+
+ expect(identity.validate).to be_falsey
+ end
+
+ it 'returns true when a different provider is used' do
+ identity = user.identities.build(provider: 'gitlab', user_id: user.id)
+
+ expect(identity.validate).to be_truthy
+ end
+ end
+
+ context 'with newly-created user' do
+ before do
+ create(:identity, provider: 'ldapmain', user_id: nil)
+ end
+
+ it 'successfully validates even with a nil user_id' do
+ identity = user.identities.build(provider: 'ldapmain')
+
+ expect(identity.validate).to be_truthy
+ end
+ end
+ end
+
describe '#is_ldap?' do
let(:ldap_identity) { create(:identity, provider: 'ldapmain') }
let(:other_identity) { create(:identity, provider: 'twitter') }
diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb
index 4696341c05f..d32f163f05b 100644
--- a/spec/models/internal_id_spec.rb
+++ b/spec/models/internal_id_spec.rb
@@ -13,6 +13,29 @@ describe InternalId do
it { is_expected.to validate_presence_of(:usage) }
end
+ describe '.flush_records!' do
+ subject { described_class.flush_records!(project: project) }
+
+ let(:another_project) { create(:project) }
+
+ before do
+ create_list(:issue, 2, project: project)
+ create_list(:issue, 2, project: another_project)
+ end
+
+ it 'deletes all records for the given project' do
+ expect { subject }.to change { described_class.where(project: project).count }.from(1).to(0)
+ end
+
+ it 'retains records for other projects' do
+ expect { subject }.not_to change { described_class.where(project: another_project).count }
+ end
+
+ it 'does not allow an empty filter' do
+ expect { described_class.flush_records!({}) }.to raise_error(/filter cannot be empty/)
+ end
+ end
+
describe '.generate_next' do
subject { described_class.generate_next(issue, scope, usage, init) }
diff --git a/spec/models/issue/metrics_spec.rb b/spec/models/issue/metrics_spec.rb
index 1bf0ecb98ad..b7291eebe64 100644
--- a/spec/models/issue/metrics_spec.rb
+++ b/spec/models/issue/metrics_spec.rb
@@ -9,7 +9,7 @@ describe Issue::Metrics do
context "milestones" do
it "records the first time an issue is associated with a milestone" do
time = Time.now
- Timecop.freeze(time) { subject.update(milestone: create(:milestone)) }
+ Timecop.freeze(time) { subject.update(milestone: create(:milestone, project: project)) }
metrics = subject.metrics
expect(metrics).to be_present
@@ -18,9 +18,9 @@ describe Issue::Metrics do
it "does not record the second time an issue is associated with a milestone" do
time = Time.now
- Timecop.freeze(time) { subject.update(milestone: create(:milestone)) }
+ Timecop.freeze(time) { subject.update(milestone: create(:milestone, project: project)) }
Timecop.freeze(time + 2.hours) { subject.update(milestone: nil) }
- Timecop.freeze(time + 6.hours) { subject.update(milestone: create(:milestone)) }
+ Timecop.freeze(time + 6.hours) { subject.update(milestone: create(:milestone, project: project)) }
metrics = subject.metrics
expect(metrics).to be_present
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 6f900a60213..6101df2e099 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -721,39 +721,28 @@ describe Issue do
end
end
- describe '#check_for_spam' do
- let(:project) { create :project, visibility_level: visibility_level }
- let(:issue) { create :issue, project: project }
+ describe '#check_for_spam?' do
+ using RSpec::Parameterized::TableSyntax
- subject do
- issue.assign_attributes(description: description)
- issue.check_for_spam?
+ where(:visibility_level, :confidential, :new_attributes, :check_for_spam?) do
+ Gitlab::VisibilityLevel::PUBLIC | false | { description: 'woo' } | true
+ Gitlab::VisibilityLevel::PUBLIC | false | { title: 'woo' } | true
+ Gitlab::VisibilityLevel::PUBLIC | true | { confidential: false } | true
+ Gitlab::VisibilityLevel::PUBLIC | true | { description: 'woo' } | false
+ Gitlab::VisibilityLevel::PUBLIC | false | { title: 'woo', confidential: true } | false
+ Gitlab::VisibilityLevel::PUBLIC | false | { description: 'original description' } | false
+ Gitlab::VisibilityLevel::INTERNAL | false | { description: 'woo' } | false
+ Gitlab::VisibilityLevel::PRIVATE | false | { description: 'woo' } | false
end
- context 'when project is public and spammable attributes changed' do
- let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
- let(:description) { 'woo' }
+ with_them do
+ it 'checks for spam on issues that can be seen anonymously' do
+ project = create(:project, visibility_level: visibility_level)
+ issue = create(:issue, project: project, confidential: confidential, description: 'original description')
- it 'returns true' do
- is_expected.to be_truthy
- end
- end
-
- context 'when project is private' do
- let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
- let(:description) { issue.description }
+ issue.assign_attributes(new_attributes)
- it 'returns false' do
- is_expected.to be_falsey
- end
- end
-
- context 'when spammable attributes have not changed' do
- let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
- let(:description) { issue.description }
-
- it 'returns false' do
- is_expected.to be_falsey
+ expect(issue.check_for_spam?).to eq(check_for_spam?)
end
end
end
@@ -776,6 +765,15 @@ describe Issue do
end
end
+ describe '.confidential_only' do
+ it 'only returns confidential_only issues' do
+ create(:issue)
+ confidential_issue = create(:issue, confidential: true)
+
+ expect(described_class.confidential_only).to eq([confidential_issue])
+ end
+ end
+
it_behaves_like 'throttled touch' do
subject { create(:issue, updated_at: 1.hour.ago) }
end
diff --git a/spec/models/label_note_spec.rb b/spec/models/label_note_spec.rb
index f69874d94aa..dd2c702a7a9 100644
--- a/spec/models/label_note_spec.rb
+++ b/spec/models/label_note_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
describe LabelNote do
- set(:project) { create(:project, :repository) }
- set(:user) { create(:user) }
+ set(:project) { create(:project, :repository) }
+ set(:user) { create(:user) }
set(:label) { create(:label, project: project) }
set(:label2) { create(:label, project: project) }
let(:resource_parent) { project }
diff --git a/spec/models/lfs_download_object_spec.rb b/spec/models/lfs_download_object_spec.rb
new file mode 100644
index 00000000000..88838b127d2
--- /dev/null
+++ b/spec/models/lfs_download_object_spec.rb
@@ -0,0 +1,68 @@
+require 'rails_helper'
+
+describe LfsDownloadObject do
+ let(:oid) { 'cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411' }
+ let(:link) { 'http://www.example.com' }
+ let(:size) { 1 }
+
+ subject { described_class.new(oid: oid, size: size, link: link) }
+
+ describe 'validations' do
+ it { is_expected.to validate_numericality_of(:size).is_greater_than_or_equal_to(0) }
+
+ context 'oid attribute' do
+ it 'must be 64 characters long' do
+ aggregate_failures do
+ expect(described_class.new(oid: 'a' * 63, size: size, link: link)).to be_invalid
+ expect(described_class.new(oid: 'a' * 65, size: size, link: link)).to be_invalid
+ expect(described_class.new(oid: 'a' * 64, size: size, link: link)).to be_valid
+ end
+ end
+
+ it 'must contain only hexadecimal characters' do
+ aggregate_failures do
+ expect(subject).to be_valid
+ expect(described_class.new(oid: 'g' * 64, size: size, link: link)).to be_invalid
+ end
+ end
+ end
+
+ context 'link attribute' do
+ it 'only http and https protocols are valid' do
+ aggregate_failures do
+ expect(described_class.new(oid: oid, size: size, link: 'http://www.example.com')).to be_valid
+ expect(described_class.new(oid: oid, size: size, link: 'https://www.example.com')).to be_valid
+ expect(described_class.new(oid: oid, size: size, link: 'ftp://www.example.com')).to be_invalid
+ expect(described_class.new(oid: oid, size: size, link: 'ssh://www.example.com')).to be_invalid
+ expect(described_class.new(oid: oid, size: size, link: 'git://www.example.com')).to be_invalid
+ end
+ end
+
+ it 'cannot be empty' do
+ expect(described_class.new(oid: oid, size: size, link: '')).not_to be_valid
+ end
+
+ context 'when localhost or local network addresses' do
+ subject { described_class.new(oid: oid, size: size, link: 'http://192.168.1.1') }
+
+ before do
+ allow(ApplicationSetting)
+ .to receive(:current)
+ .and_return(ApplicationSetting.build_from_defaults(allow_local_requests_from_hooks_and_services: setting))
+ end
+
+ context 'are allowed' do
+ let(:setting) { true }
+
+ it { expect(subject).to be_valid }
+ end
+
+ context 'are not allowed' do
+ let(:setting) { false }
+
+ it { expect(subject).to be_invalid }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/lfs_file_lock_spec.rb b/spec/models/lfs_file_lock_spec.rb
index e74f342d3eb..41ca1578b94 100644
--- a/spec/models/lfs_file_lock_spec.rb
+++ b/spec/models/lfs_file_lock_spec.rb
@@ -13,7 +13,7 @@ describe LfsFileLock do
describe '#can_be_unlocked_by?' do
let(:developer) { create(:user) }
- let(:maintainer) { create(:user) }
+ let(:maintainer) { create(:user) }
before do
project = lfs_file_lock.project
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index 99d3ab41b97..36bfff2c339 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -39,7 +39,7 @@ describe ProjectMember do
describe "#destroy" do
let(:owner) { create(:project_member, access_level: ProjectMember::MAINTAINER) }
let(:project) { owner.project }
- let(:maintainer) { create(:project_member, project: project) }
+ let(:maintainer) { create(:project_member, project: project) }
it "creates an expired event when left due to expiry" do
expired = create(:project_member, project: project, expires_at: Time.now - 6.days)
diff --git a/spec/models/merge_request_diff_commit_spec.rb b/spec/models/merge_request_diff_commit_spec.rb
index 8c01a7ac18f..10487190a44 100644
--- a/spec/models/merge_request_diff_commit_spec.rb
+++ b/spec/models/merge_request_diff_commit_spec.rb
@@ -16,7 +16,7 @@ describe MergeRequestDiffCommit do
end
describe '.create_bulk' do
- let(:sha_attribute) { Gitlab::Database::ShaAttribute.new }
+ let(:sha_attribute) { Gitlab::Database::ShaAttribute.new }
let(:merge_request_diff_id) { merge_request.merge_request_diff.id }
let(:commits) do
[
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index 33e984dc399..e530e0302f5 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -3,6 +3,18 @@ require 'spec_helper'
describe MergeRequestDiff do
let(:diff_with_commits) { create(:merge_request).merge_request_diff }
+ describe 'validations' do
+ subject { diff_with_commits }
+
+ it 'checks sha format of base_commit_sha, head_commit_sha and start_commit_sha' do
+ subject.base_commit_sha = subject.head_commit_sha = subject.start_commit_sha = 'foobar'
+
+ expect(subject.valid?).to be false
+ expect(subject.errors.count).to eq 3
+ expect(subject.errors).to all(include('is not a valid SHA'))
+ end
+ end
+
describe 'create new record' do
subject { diff_with_commits }
@@ -46,7 +58,7 @@ describe MergeRequestDiff do
it { expect(first_diff.reload).not_to be_latest }
end
- describe '#diffs' do
+ shared_examples_for 'merge request diffs' do
let(:merge_request) { create(:merge_request, :with_diffs) }
let!(:diff) { merge_request.merge_request_diff.reload }
@@ -78,7 +90,7 @@ describe MergeRequestDiff do
it 'returns persisted diffs if cannot compare with diff refs' do
expect(diff).to receive(:load_diffs).and_call_original
- diff.update!(head_commit_sha: 'invalid-sha')
+ diff.update!(head_commit_sha: Digest::SHA1.hexdigest(SecureRandom.hex))
diff.diffs.diff_files
end
@@ -91,98 +103,110 @@ describe MergeRequestDiff do
diff.diffs.diff_files
end
end
- end
- describe '#raw_diffs' do
- context 'when the :ignore_whitespace_change option is set' do
- it 'creates a new compare object instead of loading from the DB' do
- expect(diff_with_commits).not_to receive(:load_diffs)
- expect(diff_with_commits.compare).to receive(:diffs).and_call_original
+ describe '#raw_diffs' do
+ context 'when the :ignore_whitespace_change option is set' do
+ it 'creates a new compare object instead of using preprocessed data' do
+ expect(diff_with_commits).not_to receive(:load_diffs)
+ expect(diff_with_commits.compare).to receive(:diffs).and_call_original
- diff_with_commits.raw_diffs(ignore_whitespace_change: true)
+ diff_with_commits.raw_diffs(ignore_whitespace_change: true)
+ end
end
- end
- context 'when the raw diffs are empty' do
- before do
- MergeRequestDiffFile.where(merge_request_diff_id: diff_with_commits.id).delete_all
- end
+ context 'when the raw diffs are empty' do
+ before do
+ MergeRequestDiffFile.where(merge_request_diff_id: diff_with_commits.id).delete_all
+ end
- it 'returns an empty DiffCollection' do
- expect(diff_with_commits.raw_diffs).to be_a(Gitlab::Git::DiffCollection)
- expect(diff_with_commits.raw_diffs).to be_empty
+ it 'returns an empty DiffCollection' do
+ expect(diff_with_commits.raw_diffs).to be_a(Gitlab::Git::DiffCollection)
+ expect(diff_with_commits.raw_diffs).to be_empty
+ end
end
- end
- context 'when the raw diffs exist' do
- it 'returns the diffs' do
- expect(diff_with_commits.raw_diffs).to be_a(Gitlab::Git::DiffCollection)
- expect(diff_with_commits.raw_diffs).not_to be_empty
- end
+ context 'when the raw diffs exist' do
+ it 'returns the diffs' do
+ expect(diff_with_commits.raw_diffs).to be_a(Gitlab::Git::DiffCollection)
+ expect(diff_with_commits.raw_diffs).not_to be_empty
+ end
- context 'when the :paths option is set' do
- let(:diffs) { diff_with_commits.raw_diffs(paths: ['files/ruby/popen.rb', 'files/ruby/popen.rb']) }
+ context 'when the :paths option is set' do
+ let(:diffs) { diff_with_commits.raw_diffs(paths: ['files/ruby/popen.rb', 'files/ruby/popen.rb']) }
- it 'only returns diffs that match the (old path, new path) given' do
- expect(diffs.map(&:new_path)).to contain_exactly('files/ruby/popen.rb')
- end
+ it 'only returns diffs that match the (old path, new path) given' do
+ expect(diffs.map(&:new_path)).to contain_exactly('files/ruby/popen.rb')
+ end
- it 'only serializes diff files found by query' do
- expect(diff_with_commits.merge_request_diff_files.count).to be > 10
- expect_any_instance_of(MergeRequestDiffFile).to receive(:to_hash).once
+ it 'only serializes diff files found by query' do
+ expect(diff_with_commits.merge_request_diff_files.count).to be > 10
+ expect_any_instance_of(MergeRequestDiffFile).to receive(:to_hash).once
- diffs
- end
+ diffs
+ end
- it 'uses the diffs from the DB' do
- expect(diff_with_commits).to receive(:load_diffs)
+ it 'uses the preprocessed diffs' do
+ expect(diff_with_commits).to receive(:load_diffs)
- diffs
+ diffs
+ end
end
end
end
- end
- describe '#save_diffs' do
- it 'saves collected state' do
- mr_diff = create(:merge_request).merge_request_diff
+ describe '#save_diffs' do
+ it 'saves collected state' do
+ mr_diff = create(:merge_request).merge_request_diff
- expect(mr_diff.collected?).to be_truthy
- end
+ expect(mr_diff.collected?).to be_truthy
+ end
- it 'saves overflow state' do
- allow(Commit).to receive(:max_diff_options)
- .and_return(max_lines: 0, max_files: 0)
+ it 'saves overflow state' do
+ allow(Commit).to receive(:max_diff_options)
+ .and_return(max_lines: 0, max_files: 0)
- mr_diff = create(:merge_request).merge_request_diff
+ mr_diff = create(:merge_request).merge_request_diff
- expect(mr_diff.overflow?).to be_truthy
- end
+ expect(mr_diff.overflow?).to be_truthy
+ end
- it 'saves empty state' do
- allow_any_instance_of(described_class).to receive_message_chain(:compare, :commits)
- .and_return([])
+ it 'saves empty state' do
+ allow_any_instance_of(described_class).to receive_message_chain(:compare, :commits)
+ .and_return([])
- mr_diff = create(:merge_request).merge_request_diff
+ mr_diff = create(:merge_request).merge_request_diff
- expect(mr_diff.empty?).to be_truthy
- end
+ expect(mr_diff.empty?).to be_truthy
+ end
+
+ it 'expands collapsed diffs before saving' do
+ mr_diff = create(:merge_request, source_branch: 'expand-collapse-lines', target_branch: 'master').merge_request_diff
+ diff_file = mr_diff.merge_request_diff_files.find_by(new_path: 'expand-collapse/file-5.txt')
+
+ expect(diff_file.diff).not_to be_empty
+ end
- it 'expands collapsed diffs before saving' do
- mr_diff = create(:merge_request, source_branch: 'expand-collapse-lines', target_branch: 'master').merge_request_diff
- diff_file = mr_diff.merge_request_diff_files.find_by(new_path: 'expand-collapse/file-5.txt')
+ it 'saves binary diffs correctly' do
+ path = 'files/images/icn-time-tracking.pdf'
+ mr_diff = create(:merge_request, source_branch: 'add-pdf-text-binary', target_branch: 'master').merge_request_diff
+ diff_file = mr_diff.merge_request_diff_files.find_by(new_path: path)
- expect(diff_file.diff).not_to be_empty
+ expect(diff_file).to be_binary
+ expect(diff_file.diff).to eq(mr_diff.compare.diffs(paths: [path]).to_a.first.diff)
+ end
end
+ end
- it 'saves binary diffs correctly' do
- path = 'files/images/icn-time-tracking.pdf'
- mr_diff = create(:merge_request, source_branch: 'add-pdf-text-binary', target_branch: 'master').merge_request_diff
- diff_file = mr_diff.merge_request_diff_files.find_by(new_path: path)
+ describe 'internal diffs configured' do
+ include_examples 'merge request diffs'
+ end
- expect(diff_file).to be_binary
- expect(diff_file.diff).to eq(mr_diff.compare.diffs(paths: [path]).to_a.first.diff)
+ describe 'external diffs configured' do
+ before do
+ stub_external_diffs_setting(enabled: true)
end
+
+ include_examples 'merge request diffs'
end
describe '#commit_shas' do
@@ -245,4 +269,55 @@ describe MergeRequestDiff do
expect(subject.modified_paths).to eq(%w{foo bar baz})
end
end
+
+ describe '#opening_external_diff' do
+ subject(:diff) { diff_with_commits }
+
+ context 'external diffs disabled' do
+ it { expect(diff.external_diff).not_to be_exists }
+
+ it 'yields nil' do
+ expect { |b| diff.opening_external_diff(&b) }.to yield_with_args(nil)
+ end
+ end
+
+ context 'external diffs enabled' do
+ let(:test_dir) { 'tmp/tests/external-diffs' }
+
+ around do |example|
+ FileUtils.mkdir_p(test_dir)
+
+ begin
+ example.run
+ ensure
+ FileUtils.rm_rf(test_dir)
+ end
+ end
+
+ before do
+ stub_external_diffs_setting(enabled: true, storage_path: test_dir)
+ end
+
+ it { expect(diff.external_diff).to be_exists }
+
+ it 'yields an open file' do
+ expect { |b| diff.opening_external_diff(&b) }.to yield_with_args(File)
+ end
+
+ it 'is re-entrant' do
+ outer_file_a =
+ diff.opening_external_diff do |outer_file|
+ diff.opening_external_diff do |inner_file|
+ expect(outer_file).to eq(inner_file)
+ end
+
+ outer_file
+ end
+
+ diff.opening_external_diff do |outer_file_b|
+ expect(outer_file_a).not_to eq(outer_file_b)
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 6793d4e8718..07cb4c9c1e3 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -82,6 +82,38 @@ describe MergeRequest do
end
end
+ describe '#default_squash_commit_message' do
+ let(:project) { subject.project }
+
+ def commit_collection(commit_hashes)
+ raw_commits = commit_hashes.map { |raw| Commit.from_hash(raw, project) }
+
+ CommitCollection.new(project, raw_commits)
+ end
+
+ it 'returns the oldest multiline commit message' do
+ commits = commit_collection([
+ { message: 'Singleline', parent_ids: [] },
+ { message: "Second multiline\nCommit message", parent_ids: [] },
+ { message: "First multiline\nCommit message", parent_ids: [] }
+ ])
+
+ expect(subject).to receive(:commits).and_return(commits)
+
+ expect(subject.default_squash_commit_message).to eq("First multiline\nCommit message")
+ end
+
+ it 'returns the merge request title if there are no multiline commits' do
+ commits = commit_collection([
+ { message: 'Singleline', parent_ids: [] }
+ ])
+
+ expect(subject).to receive(:commits).and_return(commits)
+
+ expect(subject.default_squash_commit_message).to eq(subject.title)
+ end
+ end
+
describe 'modules' do
subject { described_class }
@@ -403,6 +435,7 @@ describe MergeRequest do
it 'does not cache issues from external trackers' do
issue = ExternalIssue.new('JIRA-123', subject.project)
commit = double('commit1', safe_message: "Fixes #{issue.to_reference}")
+
allow(subject).to receive(:commits).and_return([commit])
expect { subject.cache_merge_request_closes_issues!(subject.author) }.not_to raise_error
@@ -559,6 +592,57 @@ describe MergeRequest do
end
end
+ describe '#preload_discussions_diff_highlight' do
+ let(:merge_request) { create(:merge_request) }
+
+ context 'with commit diff note' do
+ let(:other_merge_request) { create(:merge_request) }
+
+ let!(:diff_note) do
+ create(:diff_note_on_commit, project: merge_request.project)
+ end
+
+ let!(:other_mr_diff_note) do
+ create(:diff_note_on_commit, project: other_merge_request.project)
+ end
+
+ it 'preloads diff highlighting' do
+ expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
+ note_diff_file = diff_note.note_diff_file
+
+ expect(collection)
+ .to receive(:load_highlight)
+ .with([note_diff_file.id]).and_call_original
+ end
+
+ merge_request.preload_discussions_diff_highlight
+ end
+ end
+
+ context 'with merge request diff note' do
+ let!(:unresolved_diff_note) do
+ create(:diff_note_on_merge_request, project: merge_request.project, noteable: merge_request)
+ end
+
+ let!(:resolved_diff_note) do
+ create(:diff_note_on_merge_request, :resolved, project: merge_request.project, noteable: merge_request)
+ end
+
+ it 'preloads diff highlighting' do
+ expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
+ note_diff_file = unresolved_diff_note.note_diff_file
+
+ expect(collection)
+ .to receive(:load_highlight)
+ .with([note_diff_file.id])
+ .and_call_original
+ end
+
+ merge_request.preload_discussions_diff_highlight
+ end
+ end
+ end
+
describe '#diff_size' do
let(:merge_request) do
build(:merge_request, source_branch: 'expand-collapse-files', target_branch: 'master')
@@ -869,18 +953,18 @@ describe MergeRequest do
end
end
- describe '#merge_commit_message' do
+ describe '#default_merge_commit_message' do
it 'includes merge information as the title' do
request = build(:merge_request, source_branch: 'source', target_branch: 'target')
- expect(request.merge_commit_message)
+ expect(request.default_merge_commit_message)
.to match("Merge branch 'source' into 'target'\n\n")
end
it 'includes its title in the body' do
request = build(:merge_request, title: 'Remove all technical debt')
- expect(request.merge_commit_message)
+ expect(request.default_merge_commit_message)
.to match("Remove all technical debt\n\n")
end
@@ -892,34 +976,34 @@ describe MergeRequest do
allow(subject.project).to receive(:default_branch).and_return(subject.target_branch)
subject.cache_merge_request_closes_issues!
- expect(subject.merge_commit_message)
+ expect(subject.default_merge_commit_message)
.to match("Closes #{issue.to_reference}")
end
it 'includes its reference in the body' do
request = build_stubbed(:merge_request)
- expect(request.merge_commit_message)
+ expect(request.default_merge_commit_message)
.to match("See merge request #{request.to_reference(full: true)}")
end
it 'excludes multiple linebreak runs when description is blank' do
request = build(:merge_request, title: 'Title', description: nil)
- expect(request.merge_commit_message).not_to match("Title\n\n\n\n")
+ expect(request.default_merge_commit_message).not_to match("Title\n\n\n\n")
end
it 'includes its description in the body' do
request = build(:merge_request, description: 'By removing all code')
- expect(request.merge_commit_message(include_description: true))
+ expect(request.default_merge_commit_message(include_description: true))
.to match("By removing all code\n\n")
end
it 'does not includes its description in the body' do
request = build(:merge_request, description: 'By removing all code')
- expect(request.merge_commit_message)
+ expect(request.default_merge_commit_message)
.not_to match("By removing all code\n\n")
end
end
@@ -940,6 +1024,34 @@ describe MergeRequest do
end
end
+ describe '#commit_authors' do
+ it 'returns all the authors of every commit in the merge request' do
+ users = subject.commits.map(&:author_email).uniq.map do |email|
+ create(:user, email: email)
+ end
+
+ expect(subject.commit_authors).to match_array(users)
+ end
+
+ it 'returns an empty array if no author is associated with a user' do
+ expect(subject.commit_authors).to be_empty
+ end
+ end
+
+ describe '#authors' do
+ it 'returns a list with all the commit authors in the merge request and author' do
+ users = subject.commits.map(&:author_email).uniq.map do |email|
+ create(:user, email: email)
+ end
+
+ expect(subject.authors).to match_array([subject.author, *users])
+ end
+
+ it 'returns only the author if no committer is associated with a user' do
+ expect(subject.authors).to contain_exactly(subject.author)
+ end
+ end
+
describe '#hook_attrs' do
it 'delegates to Gitlab::HookData::MergeRequestBuilder#build' do
builder = double
@@ -953,7 +1065,7 @@ describe MergeRequest do
end
describe '#diverged_commits_count' do
- let(:project) { create(:project, :repository) }
+ let(:project) { create(:project, :repository) }
let(:forked_project) { fork_project(project, nil, repository: true) }
context 'when the target branch does not exist anymore' do
@@ -1221,7 +1333,7 @@ describe MergeRequest do
let!(:merge_request_pipeline) do
create(:ci_pipeline,
- source: :merge_request,
+ source: :merge_request_event,
project: project,
ref: source_ref,
sha: shas.second,
@@ -1260,7 +1372,7 @@ describe MergeRequest do
let!(:merge_request_pipeline_2) do
create(:ci_pipeline,
- source: :merge_request,
+ source: :merge_request_event,
project: project,
ref: source_ref,
sha: shas.first,
@@ -1287,7 +1399,7 @@ describe MergeRequest do
let!(:merge_request_pipeline_2) do
create(:ci_pipeline,
- source: :merge_request,
+ source: :merge_request_event,
project: project,
ref: source_ref,
sha: shas.first,
@@ -1321,6 +1433,51 @@ describe MergeRequest do
end
end
+ describe '#update_head_pipeline' do
+ subject { merge_request.update_head_pipeline }
+
+ let(:merge_request) { create(:merge_request) }
+
+ context 'when there is a pipeline with the diff head sha' do
+ let!(:pipeline) do
+ create(:ci_empty_pipeline,
+ project: merge_request.project,
+ sha: merge_request.diff_head_sha,
+ ref: merge_request.source_branch)
+ end
+
+ it 'updates the head pipeline' do
+ expect { subject }
+ .to change { merge_request.reload.head_pipeline }
+ .from(nil).to(pipeline)
+ end
+
+ context 'when merge request has already had head pipeline' do
+ before do
+ merge_request.update!(head_pipeline: pipeline)
+ end
+
+ context 'when failed to find an actual head pipeline' do
+ before do
+ allow(merge_request).to receive(:find_actual_head_pipeline) { }
+ end
+
+ it 'does not update the current head pipeline' do
+ expect { subject }
+ .not_to change { merge_request.reload.head_pipeline }
+ end
+ end
+ end
+ end
+
+ context 'when there are no pipelines with the diff head sha' do
+ it 'does not update the head pipeline' do
+ expect { subject }
+ .not_to change { merge_request.reload.head_pipeline }
+ end
+ end
+ end
+
describe '#has_test_reports?' do
subject { merge_request.has_test_reports? }
@@ -2174,9 +2331,9 @@ describe MergeRequest do
end
describe "#source_project_missing?" do
- let(:project) { create(:project) }
+ let(:project) { create(:project) }
let(:forked_project) { fork_project(project) }
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
let(:unlink_project) { Projects::UnlinkForkService.new(forked_project, user) }
context "when the fork exists" do
@@ -2246,9 +2403,9 @@ describe MergeRequest do
end
describe "#closed_without_fork?" do
- let(:project) { create(:project) }
+ let(:project) { create(:project) }
let(:forked_project) { fork_project(project) }
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
let(:unlink_project) { Projects::UnlinkForkService.new(forked_project, user) }
context "when the merge request is closed" do
@@ -2370,7 +2527,7 @@ describe MergeRequest do
expect(merge_request.mergeable_with_quick_action?(user, last_diff_sha: mr_sha)).to be_falsey
end
- context 'closed MR' do
+ context 'closed MR' do
before do
merge_request.update_attribute(:state, :closed)
end
@@ -2380,7 +2537,7 @@ describe MergeRequest do
end
end
- context 'MR with WIP' do
+ context 'MR with WIP' do
before do
merge_request.update_attribute(:title, 'WIP: some MR')
end
@@ -2390,19 +2547,19 @@ describe MergeRequest do
end
end
- context 'sha differs from the MR diff_head_sha' do
+ context 'sha differs from the MR diff_head_sha' do
it 'is not mergeable' do
expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: 'some other sha')).to be_falsey
end
end
- context 'sha is not provided' do
+ context 'sha is not provided' do
it 'is not mergeable' do
expect(merge_request.mergeable_with_quick_action?(developer)).to be_falsey
end
end
- context 'with pipeline ok' do
+ context 'with pipeline ok' do
before do
create_pipeline(:success)
end
@@ -2412,7 +2569,7 @@ describe MergeRequest do
end
end
- context 'with failing pipeline' do
+ context 'with failing pipeline' do
before do
create_pipeline(:failed)
end
@@ -2422,7 +2579,7 @@ describe MergeRequest do
end
end
- context 'with running pipeline' do
+ context 'with running pipeline' do
before do
create_pipeline(:running)
end
@@ -2448,8 +2605,9 @@ describe MergeRequest do
let!(:first_pipeline) { create(:ci_pipeline_without_jobs, pipeline_arguments) }
let!(:last_pipeline) { create(:ci_pipeline_without_jobs, pipeline_arguments) }
+ let!(:last_pipeline_with_other_ref) { create(:ci_pipeline_without_jobs, pipeline_arguments.merge(ref: 'other')) }
- it 'returns latest pipeline' do
+ it 'returns latest pipeline for the target branch' do
expect(merge_request.base_pipeline).to eq(last_pipeline)
end
end
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index d11eb46159e..77b7042424c 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -182,7 +182,7 @@ describe Milestone do
describe '#total_items_count' do
before do
create :closed_issue, milestone: milestone, project: project
- create :merge_request, milestone: milestone
+ create :merge_request, milestone: milestone, source_project: project
end
it 'returns total count of issues and merge requests assigned to milestone' do
@@ -192,10 +192,10 @@ describe Milestone do
describe '#can_be_closed?' do
before do
- milestone = create :milestone
- create :closed_issue, milestone: milestone
+ milestone = create :milestone, project: project
+ create :closed_issue, milestone: milestone, project: project
- create :issue
+ create :issue, project: project
end
it 'returns true if milestone active and all nested issues closed' do
@@ -240,7 +240,111 @@ describe Milestone do
end
end
- describe '.upcoming_ids_by_projects' do
+ describe '#search_title' 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])
+ end
+
+ it 'returns milestones with a partially matching title' do
+ expect(described_class.search_title(milestone.title[0..2])).to eq([milestone])
+ end
+
+ it 'returns milestones with a matching title regardless of the casing' do
+ expect(described_class.search_title(milestone.title.upcase))
+ .to eq([milestone])
+ end
+
+ 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])
+ end
+ end
+
+ describe '#for_projects_and_groups' do
+ let(:project) { create(:project) }
+ let(:project_other) { create(:project) }
+ let(:group) { create(:group) }
+ let(:group_other) { create(:group) }
+
+ before do
+ create(:milestone, project: project)
+ create(:milestone, project: project_other)
+ create(:milestone, group: group)
+ create(:milestone, group: group_other)
+ end
+
+ subject { described_class.for_projects_and_groups(projects, groups) }
+
+ shared_examples 'filters by projects and groups' do
+ it 'returns milestones filtered by project' do
+ milestones = described_class.for_projects_and_groups(projects, [])
+
+ expect(milestones.count).to eq(1)
+ expect(milestones.first.project_id).to eq(project.id)
+ end
+
+ it 'returns milestones filtered by group' do
+ milestones = described_class.for_projects_and_groups([], groups)
+
+ expect(milestones.count).to eq(1)
+ expect(milestones.first.group_id).to eq(group.id)
+ end
+
+ it 'returns milestones filtered by both project and group' do
+ milestones = described_class.for_projects_and_groups(projects, groups)
+
+ expect(milestones.count).to eq(2)
+ expect(milestones).to contain_exactly(project.milestones.first, group.milestones.first)
+ end
+ end
+
+ context 'ids as params' do
+ let(:projects) { [project.id] }
+ let(:groups) { [group.id] }
+
+ it_behaves_like 'filters by projects and groups'
+ end
+
+ context 'relations as params' do
+ let(:projects) { Project.where(id: project.id).select(:id) }
+ let(:groups) { Group.where(id: group.id).select(:id) }
+
+ it_behaves_like 'filters by projects and groups'
+ end
+
+ context 'objects as params' do
+ let(:projects) { [project] }
+ let(:groups) { [group] }
+
+ it_behaves_like 'filters by projects and groups'
+ end
+
+ it 'returns no records if projects and groups are nil' do
+ milestones = described_class.for_projects_and_groups(nil, nil)
+
+ expect(milestones).to be_empty
+ end
+ end
+
+ describe '.upcoming_ids' do
+ let(:group_1) { create(:group) }
+ let(:group_2) { create(:group) }
+ let(:group_3) { create(:group) }
+ let(:groups) { [group_1, group_2, group_3] }
+
+ let!(:past_milestone_group_1) { create(:milestone, group: group_1, due_date: Time.now - 1.day) }
+ let!(:current_milestone_group_1) { create(:milestone, group: group_1, due_date: Time.now + 1.day) }
+ let!(:future_milestone_group_1) { create(:milestone, group: group_1, due_date: Time.now + 2.days) }
+
+ let!(:past_milestone_group_2) { create(:milestone, group: group_2, due_date: Time.now - 1.day) }
+ let!(:closed_milestone_group_2) { create(:milestone, :closed, group: group_2, due_date: Time.now + 1.day) }
+ let!(:current_milestone_group_2) { create(:milestone, group: group_2, due_date: Time.now + 2.days) }
+
+ let!(:past_milestone_group_3) { create(:milestone, group: group_3, due_date: Time.now - 1.day) }
+
let(:project_1) { create(:project) }
let(:project_2) { create(:project) }
let(:project_3) { create(:project) }
@@ -256,16 +360,20 @@ describe Milestone do
let!(:past_milestone_project_3) { create(:milestone, project: project_3, due_date: Time.now - 1.day) }
- # The call to `#try` is because this returns a relation with a Postgres DB,
- # and an array of IDs with a MySQL DB.
- let(:milestone_ids) { described_class.upcoming_ids_by_projects(projects).map { |id| id.try(:id) || id } }
+ let(:milestone_ids) { described_class.upcoming_ids(projects, groups).map(&:id) }
- it 'returns the next upcoming open milestone ID for each project' do
- expect(milestone_ids).to contain_exactly(current_milestone_project_1.id, current_milestone_project_2.id)
+ it 'returns the next upcoming open milestone ID for each project and group' do
+ expect(milestone_ids).to contain_exactly(
+ current_milestone_project_1.id,
+ current_milestone_project_2.id,
+ current_milestone_group_1.id,
+ current_milestone_group_2.id
+ )
end
- context 'when the projects have no open upcoming milestones' do
+ context 'when the projects and groups have no open upcoming milestones' do
let(:projects) { [project_3] }
+ let(:groups) { [group_3] }
it 'returns no results' do
expect(milestone_ids).to be_empty
@@ -316,6 +424,15 @@ describe Milestone do
end
end
+ describe '#reference_link_text' do
+ let(:project) { build_stubbed(:project, name: 'sample-project') }
+ let(:milestone) { build_stubbed(:milestone, iid: 1, project: project, name: 'milestone') }
+
+ it 'returns the title with the reference prefix' do
+ expect(milestone.reference_link_text).to eq '%milestone'
+ end
+ end
+
describe '#participants' do
let(:project) { build(:project, name: 'sample-project') }
let(:milestone) { build(:milestone, iid: 1, project: project) }
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index bcdfe3cf1eb..385b8a7959f 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -890,4 +890,19 @@ describe Note do
end
end
end
+
+ describe '#parent' do
+ it 'returns project for project notes' do
+ project = create(:project)
+ note = create(:note_on_issue, project: project)
+
+ expect(note.parent).to eq(project)
+ end
+
+ it 'returns nil for personal snippet note' do
+ note = create(:note_on_personal_snippet)
+
+ expect(note.parent).to be_nil
+ end
+ end
end
diff --git a/spec/models/project_daily_statistic_spec.rb b/spec/models/project_daily_statistic_spec.rb
new file mode 100644
index 00000000000..86210af15d8
--- /dev/null
+++ b/spec/models/project_daily_statistic_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProjectDailyStatistic do
+ it { is_expected.to belong_to(:project) }
+end
diff --git a/spec/models/project_import_data_spec.rb b/spec/models/project_import_data_spec.rb
index e9910c0a5d1..fe47811f074 100644
--- a/spec/models/project_import_data_spec.rb
+++ b/spec/models/project_import_data_spec.rb
@@ -39,4 +39,15 @@ describe ProjectImportData do
expect(row.credentials).to eq({ 'number' => 10, 'foo' => 'bar' })
end
end
+
+ describe '#clear_credentials' do
+ it 'clears out the Hash' do
+ row = described_class.new
+
+ row.merge_credentials('number' => 10)
+ row.clear_credentials
+
+ expect(row.credentials).to eq({})
+ end
+ end
end
diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb
index ee84fa95f0e..b880d90d28f 100644
--- a/spec/models/project_services/bamboo_service_spec.rb
+++ b/spec/models/project_services/bamboo_service_spec.rb
@@ -144,7 +144,7 @@ describe BambooService, :use_clean_rails_memory_store_caching do
end
end
- describe '#calculate_reactive_cache' do
+ shared_examples 'reactive cache calculation' do
context '#build_page' do
subject { service.calculate_reactive_cache('123', 'unused')[:build_page] }
@@ -155,7 +155,7 @@ describe BambooService, :use_clean_rails_memory_store_caching do
end
it 'returns a specific URL when response has no results' do
- stub_request(body: bamboo_response(size: 0))
+ stub_request(body: %q({"results":{"results":{"size":"0"}}}))
is_expected.to eq('http://gitlab.com/bamboo/browse/foo')
end
@@ -224,6 +224,24 @@ describe BambooService, :use_clean_rails_memory_store_caching do
end
end
+ describe '#calculate_reactive_cache' do
+ context 'when Bamboo API returns single result' do
+ let(:bamboo_response_template) do
+ %q({"results":{"results":{"size":"1","result":{"buildState":"%{build_state}","planResultKey":{"key":"42"}}}}})
+ end
+
+ it_behaves_like 'reactive cache calculation'
+ end
+
+ context 'when Bamboo API returns an array of results and we only consider the last one' do
+ let(:bamboo_response_template) do
+ %q({"results":{"results":{"size":"2","result":[{"buildState":"%{build_state}","planResultKey":{"key":"41"}},{"buildState":"%{build_state}","planResultKey":{"key":"42"}}]}}})
+ end
+
+ it_behaves_like 'reactive cache calculation'
+ end
+ end
+
def stub_update_and_build_request(status: 200, body: nil)
bamboo_full_url = 'http://gitlab.com/bamboo/updateAndBuild.action?buildKey=foo&os_authType=basic'
@@ -244,8 +262,8 @@ describe BambooService, :use_clean_rails_memory_store_caching do
).with(basic_auth: %w(mic password))
end
- def bamboo_response(result_key: 42, build_state: 'success', size: 1)
+ def bamboo_response(build_state: 'success')
# reference: https://docs.atlassian.com/atlassian-bamboo/REST/6.2.5/#d2e786
- %Q({"results":{"results":{"size":"#{size}","result":[{"buildState":"#{build_state}","planResultKey":{"key":"#{result_key}"}}]}}})
+ bamboo_response_template % { build_state: build_state }
end
end
diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb
index d8972aff407..26597d9b83c 100644
--- a/spec/models/project_services/drone_ci_service_spec.rb
+++ b/spec/models/project_services/drone_ci_service_spec.rb
@@ -117,7 +117,7 @@ describe DroneCiService, :use_clean_rails_memory_store_caching do
describe "execute" do
include_context :drone_ci_service
- let(:user) { create(:user, username: 'username') }
+ let(:user) { create(:user, username: 'username') }
let(:push_sample_data) do
Gitlab::DataBuilder::Push.build_sample(project, user)
end
diff --git a/spec/models/project_services/external_wiki_service_spec.rb b/spec/models/project_services/external_wiki_service_spec.rb
index 25e6ce7e804..62fd97b038b 100644
--- a/spec/models/project_services/external_wiki_service_spec.rb
+++ b/spec/models/project_services/external_wiki_service_spec.rb
@@ -1,7 +1,6 @@
require 'spec_helper'
describe ExternalWikiService do
- include ExternalWikiHelper
describe "Associations" do
it { is_expected.to belong_to :project }
it { is_expected.to have_one :service_hook }
@@ -25,24 +24,4 @@ describe ExternalWikiService do
it { is_expected.not_to validate_presence_of(:external_wiki_url) }
end
end
-
- describe 'External wiki' do
- let(:project) { create(:project) }
-
- context 'when it is active' do
- before do
- properties = { 'external_wiki_url' => 'https://gitlab.com' }
- @service = project.create_external_wiki_service(active: true, properties: properties)
- end
-
- after do
- @service.destroy!
- end
-
- it 'replaces the wiki url' do
- wiki_path = get_project_wiki_path(project)
- expect(wiki_path).to match('https://gitlab.com')
- end
- end
- end
end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
deleted file mode 100644
index b0fd2ceead0..00000000000
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ /dev/null
@@ -1,408 +0,0 @@
-require 'spec_helper'
-
-describe HipchatService do
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:token) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:token) }
- end
- end
-
- describe "Execute" do
- let(:hipchat) { described_class.new }
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:api_url) { 'https://hipchat.example.com/v2/room/123456/notification?auth_token=verySecret' }
- let(:project_name) { project.full_name.gsub(/\s/, '') }
- let(:token) { 'verySecret' }
- let(:server_url) { 'https://hipchat.example.com'}
- let(:push_sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- before do
- allow(hipchat).to receive_messages(
- project_id: project.id,
- project: project,
- room: 123456,
- server: server_url,
- token: token
- )
- WebMock.stub_request(:post, api_url)
- end
-
- it 'tests and return errors' do
- allow(hipchat).to receive(:execute).and_raise(StandardError, 'no such room')
- result = hipchat.test(push_sample_data)
-
- expect(result[:success]).to be_falsey
- expect(result[:result].to_s).to eq('no such room')
- end
-
- it 'uses v1 if version is provided' do
- allow(hipchat).to receive(:api_version).and_return('v1')
- expect(HipChat::Client).to receive(:new).with(
- token,
- api_version: 'v1',
- server_url: server_url
- ).and_return(double(:hipchat_service).as_null_object)
- hipchat.execute(push_sample_data)
- end
-
- it 'uses v2 as the version when nothing is provided' do
- allow(hipchat).to receive(:api_version).and_return('')
- expect(HipChat::Client).to receive(:new).with(
- token,
- api_version: 'v2',
- server_url: server_url
- ).and_return(double(:hipchat_service).as_null_object)
- hipchat.execute(push_sample_data)
- end
-
- context 'push events' do
- it "calls Hipchat API for push events" do
- hipchat.execute(push_sample_data)
-
- expect(WebMock).to have_requested(:post, api_url).once
- end
-
- it "creates a push message" do
- message = hipchat.send(:create_push_message, push_sample_data)
-
- push_sample_data[:object_attributes]
- branch = push_sample_data[:ref].gsub('refs/heads/', '')
- expect(message).to include("#{user.name} pushed to branch " \
- "<a href=\"#{project.web_url}/commits/#{branch}\">#{branch}</a> of " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>")
- end
- end
-
- context 'tag_push events' do
- let(:push_sample_data) do
- Gitlab::DataBuilder::Push.build(
- project,
- user,
- Gitlab::Git::BLANK_SHA,
- '1' * 40,
- 'refs/tags/test',
- [])
- end
-
- it "calls Hipchat API for tag push events" do
- hipchat.execute(push_sample_data)
-
- expect(WebMock).to have_requested(:post, api_url).once
- end
-
- it "creates a tag push message" do
- message = hipchat.send(:create_push_message, push_sample_data)
-
- push_sample_data[:object_attributes]
- expect(message).to eq("#{user.name} pushed new tag " \
- "<a href=\"#{project.web_url}/commits/test\">test</a> to " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>\n")
- end
- end
-
- context 'issue events' do
- let(:issue) { create(:issue, title: 'Awesome issue', description: '**please** fix') }
- let(:issue_service) { Issues::CreateService.new(project, user) }
- let(:issues_sample_data) { issue_service.hook_data(issue, 'open') }
-
- it "calls Hipchat API for issue events" do
- hipchat.execute(issues_sample_data)
-
- expect(WebMock).to have_requested(:post, api_url).once
- end
-
- it "creates an issue message" do
- message = hipchat.send(:create_issue_message, issues_sample_data)
-
- obj_attr = issues_sample_data[:object_attributes]
- expect(message).to eq("#{user.name} opened " \
- "<a href=\"#{obj_attr[:url]}\">issue ##{obj_attr["iid"]}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "<b>Awesome issue</b>" \
- "<pre><strong>please</strong> fix</pre>")
- end
- end
-
- context 'merge request events' do
- let(:merge_request) { create(:merge_request, description: '**please** fix', title: 'Awesome merge request', target_project: project, source_project: project) }
- let(:merge_service) { MergeRequests::CreateService.new(project, user) }
- let(:merge_sample_data) { merge_service.hook_data(merge_request, 'open') }
-
- it "calls Hipchat API for merge requests events" do
- hipchat.execute(merge_sample_data)
-
- expect(WebMock).to have_requested(:post, api_url).once
- end
-
- it "creates a merge request message" do
- message = hipchat.send(:create_merge_request_message,
- merge_sample_data)
-
- obj_attr = merge_sample_data[:object_attributes]
- expect(message).to eq("#{user.name} opened " \
- "<a href=\"#{obj_attr[:url]}\">merge request !#{obj_attr["iid"]}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "<b>Awesome merge request</b>" \
- "<pre><strong>please</strong> fix</pre>")
- end
- end
-
- context "Note events" do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, creator: user) }
-
- context 'when commit comment event triggered' do
- let(:commit_note) do
- create(:note_on_commit, author: user, project: project,
- commit_id: project.repository.commit.id,
- note: 'a comment on a commit')
- end
-
- it "calls Hipchat API for commit comment events" do
- data = Gitlab::DataBuilder::Note.build(commit_note, user)
- hipchat.execute(data)
-
- expect(WebMock).to have_requested(:post, api_url).once
-
- message = hipchat.send(:create_message, data)
-
- obj_attr = data[:object_attributes]
- commit_id = Commit.truncate_sha(data[:commit][:id])
- title = hipchat.send(:format_title, data[:commit][:message])
-
- expect(message).to eq("#{user.name} commented on " \
- "<a href=\"#{obj_attr[:url]}\">commit #{commit_id}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "#{title}" \
- "<pre>a comment on a commit</pre>")
- end
- end
-
- context 'when merge request comment event triggered' do
- let(:merge_request) do
- create(:merge_request, source_project: project,
- target_project: project)
- end
-
- let(:merge_request_note) do
- create(:note_on_merge_request, noteable: merge_request,
- project: project,
- note: "merge request **note**")
- end
-
- it "calls Hipchat API for merge request comment events" do
- data = Gitlab::DataBuilder::Note.build(merge_request_note, user)
- hipchat.execute(data)
-
- expect(WebMock).to have_requested(:post, api_url).once
-
- message = hipchat.send(:create_message, data)
-
- obj_attr = data[:object_attributes]
- merge_id = data[:merge_request]['iid']
- title = data[:merge_request]['title']
-
- expect(message).to eq("#{user.name} commented on " \
- "<a href=\"#{obj_attr[:url]}\">merge request !#{merge_id}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "<b>#{title}</b>" \
- "<pre>merge request <strong>note</strong></pre>")
- end
- end
-
- context 'when issue comment event triggered' do
- let(:issue) { create(:issue, project: project) }
- let(:issue_note) do
- create(:note_on_issue, noteable: issue, project: project,
- note: "issue **note**")
- end
-
- it "calls Hipchat API for issue comment events" do
- data = Gitlab::DataBuilder::Note.build(issue_note, user)
- hipchat.execute(data)
-
- message = hipchat.send(:create_message, data)
-
- obj_attr = data[:object_attributes]
- issue_id = data[:issue]['iid']
- title = data[:issue]['title']
-
- expect(message).to eq("#{user.name} commented on " \
- "<a href=\"#{obj_attr[:url]}\">issue ##{issue_id}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "<b>#{title}</b>" \
- "<pre>issue <strong>note</strong></pre>")
- end
-
- context 'with confidential issue' do
- before do
- issue.update!(confidential: true)
- end
-
- it 'calls Hipchat API with issue comment' do
- data = Gitlab::DataBuilder::Note.build(issue_note, user)
- hipchat.execute(data)
-
- message = hipchat.send(:create_message, data)
-
- expect(message).to include("<pre>issue <strong>note</strong></pre>")
- end
- end
- end
-
- context 'when snippet comment event triggered' do
- let(:snippet) { create(:project_snippet, project: project) }
- let(:snippet_note) do
- create(:note_on_project_snippet, noteable: snippet,
- project: project,
- note: "snippet note")
- end
-
- it "calls Hipchat API for snippet comment events" do
- data = Gitlab::DataBuilder::Note.build(snippet_note, user)
- hipchat.execute(data)
-
- expect(WebMock).to have_requested(:post, api_url).once
-
- message = hipchat.send(:create_message, data)
-
- obj_attr = data[:object_attributes]
- snippet_id = data[:snippet]['id']
- title = data[:snippet]['title']
-
- expect(message).to eq("#{user.name} commented on " \
- "<a href=\"#{obj_attr[:url]}\">snippet ##{snippet_id}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "<b>#{title}</b>" \
- "<pre>snippet note</pre>")
- end
- end
- end
-
- context 'pipeline events' do
- let(:pipeline) { create(:ci_empty_pipeline, user: create(:user)) }
- let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context 'for failed' do
- before do
- pipeline.drop
- end
-
- it "calls Hipchat API" do
- hipchat.execute(data)
-
- expect(WebMock).to have_requested(:post, api_url).once
- end
-
- it "creates a build message" do
- message = hipchat.__send__(:create_pipeline_message, data)
-
- project_url = project.web_url
- project_name = project.full_name.gsub(/\s/, '')
- pipeline_attributes = data[:object_attributes]
- ref = pipeline_attributes[:ref]
- ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch'
- duration = pipeline_attributes[:duration]
- user_name = data[:user][:name]
-
- expect(message).to eq("<a href=\"#{project_url}\">#{project_name}</a>: " \
- "Pipeline <a href=\"#{project_url}/pipelines/#{pipeline.id}\">##{pipeline.id}</a> " \
- "of <a href=\"#{project_url}/commits/#{ref}\">#{ref}</a> #{ref_type} " \
- "by #{user_name} failed in #{duration} second(s)")
- end
- end
-
- context 'for succeeded' do
- before do
- pipeline.succeed
- end
-
- it "calls Hipchat API" do
- hipchat.notify_only_broken_pipelines = false
- hipchat.execute(data)
- expect(WebMock).to have_requested(:post, api_url).once
- end
-
- it "notifies only broken" do
- hipchat.notify_only_broken_pipelines = true
- hipchat.execute(data)
- expect(WebMock).not_to have_requested(:post, api_url).once
- end
- end
- end
-
- context "#message_options" do
- it "is set to the defaults" do
- expect(hipchat.__send__(:message_options)).to eq({ notify: false, color: 'yellow' })
- end
-
- it "sets notify to true" do
- allow(hipchat).to receive(:notify).and_return('1')
-
- expect(hipchat.__send__(:message_options)).to eq({ notify: true, color: 'yellow' })
- end
-
- it "sets the color" do
- allow(hipchat).to receive(:color).and_return('red')
-
- expect(hipchat.__send__(:message_options)).to eq({ notify: false, color: 'red' })
- end
-
- context 'with a successful build' do
- it 'uses the green color' do
- data = { object_kind: 'pipeline',
- object_attributes: { status: 'success' } }
-
- expect(hipchat.__send__(:message_options, data)).to eq({ notify: false, color: 'green' })
- end
- end
-
- context 'with a failed build' do
- it 'uses the red color' do
- data = { object_kind: 'pipeline',
- object_attributes: { status: 'failed' } }
-
- expect(hipchat.__send__(:message_options, data)).to eq({ notify: false, color: 'red' })
- end
- end
- end
- end
-
- context 'with UrlBlocker' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:hipchat) { described_class.new(project: project) }
- let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
-
- describe '#execute' do
- before do
- hipchat.server = 'http://localhost:9123'
- end
-
- it 'raises UrlBlocker for localhost' do
- expect(Gitlab::UrlBlocker).to receive(:validate!).and_call_original
- expect { hipchat.execute(push_sample_data) }.to raise_error(Gitlab::HTTP::BlockedUrlError)
- end
- end
- end
-end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 788b3179b01..5428fcb1271 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -177,9 +177,10 @@ describe JiraService do
expect(WebMock).to have_requested(:post, @remote_link_url).with(
body: hash_including(
GlobalID: 'GitLab',
+ relationship: 'mentioned on',
object: {
url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/commit/#{commit_id}",
- title: "GitLab: Solved by commit #{commit_id}.",
+ title: "Solved by commit #{commit_id}.",
icon: { title: 'GitLab', url16x16: favicon_path },
status: { resolved: true }
}
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index b6cf4c72450..e9c7c94ad70 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -33,18 +33,38 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
describe 'Validations' do
context 'when manual_configuration is enabled' do
before do
- subject.manual_configuration = true
+ service.manual_configuration = true
end
- it { is_expected.to validate_presence_of(:api_url) }
+ it 'validates presence of api_url' do
+ expect(service).to validate_presence_of(:api_url)
+ end
end
context 'when manual configuration is disabled' do
before do
- subject.manual_configuration = false
+ service.manual_configuration = false
end
- it { is_expected.not_to validate_presence_of(:api_url) }
+ it 'does not validate presence of api_url' do
+ expect(service).not_to validate_presence_of(:api_url)
+ end
+ end
+
+ context 'when the api_url domain points to localhost or local network' do
+ let(:domain) { Addressable::URI.parse(service.api_url).hostname }
+
+ it 'cannot query' do
+ expect(service.can_query?).to be true
+
+ aggregate_failures do
+ ['127.0.0.1', '192.168.2.3'].each do |url|
+ allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([Addrinfo.tcp(url, 80)])
+
+ expect(service.can_query?).to be false
+ end
+ end
+ end
end
end
@@ -74,30 +94,35 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
end
describe '#prometheus_client' do
+ let(:api_url) { 'http://some_url' }
+
+ before do
+ service.active = true
+ service.api_url = api_url
+ service.manual_configuration = manual_configuration
+ end
+
context 'manual configuration is enabled' do
- let(:api_url) { 'http://some_url' }
+ let(:manual_configuration) { true }
- before do
- subject.active = true
- subject.manual_configuration = true
- subject.api_url = api_url
+ it 'returns rest client from api_url' do
+ expect(service.prometheus_client.url).to eq(api_url)
end
- it 'returns rest client from api_url' do
- expect(subject.prometheus_client.url).to eq(api_url)
+ it 'calls valid?' do
+ allow(service).to receive(:valid?).and_call_original
+
+ expect(service.prometheus_client).not_to be_nil
+
+ expect(service).to have_received(:valid?)
end
end
context 'manual configuration is disabled' do
- let(:api_url) { 'http://some_url' }
-
- before do
- subject.manual_configuration = false
- subject.api_url = api_url
- end
+ let(:manual_configuration) { false }
it 'no client provided' do
- expect(subject.prometheus_client).to be_nil
+ expect(service.prometheus_client).to be_nil
end
end
end
diff --git a/spec/models/project_services/slack_slash_commands_service_spec.rb b/spec/models/project_services/slack_slash_commands_service_spec.rb
index 0d95f454819..5c4bce90ace 100644
--- a/spec/models/project_services/slack_slash_commands_service_spec.rb
+++ b/spec/models/project_services/slack_slash_commands_service_spec.rb
@@ -38,4 +38,11 @@ describe SlackSlashCommandsService do
end
end
end
+
+ describe '#chat_responder' do
+ it 'returns the responder to use for Slack' do
+ expect(described_class.new.chat_responder)
+ .to eq(Gitlab::Chat::Responder::Slack)
+ end
+ end
end
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
index 43a0ed99296..64b4efca43a 100644
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ b/spec/models/project_services/teamcity_service_spec.rb
@@ -205,7 +205,7 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
end
def stub_request(status: 200, body: nil, build_status: 'success')
- teamcity_full_url = 'http://gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,number:123'
+ teamcity_full_url = 'http://gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,revision:123'
auth = %w(mic password)
body ||= %Q({"build":{"status":"#{build_status}","id":"666"}})
diff --git a/spec/models/project_services/youtrack_service_spec.rb b/spec/models/project_services/youtrack_service_spec.rb
new file mode 100644
index 00000000000..9524b526a46
--- /dev/null
+++ b/spec/models/project_services/youtrack_service_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe YoutrackService do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ end
+ end
+
+ describe '.reference_pattern' do
+ it_behaves_like 'allows project key on reference pattern'
+
+ it 'does allow project prefix on the reference' do
+ expect(described_class.reference_pattern.match('YT-123')[:issue]).to eq('YT-123')
+ end
+ end
+end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index a01f76a5bab..b2392f9521f 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -41,7 +41,6 @@ describe Project do
it { is_expected.to have_one(:pipelines_email_service) }
it { is_expected.to have_one(:irker_service) }
it { is_expected.to have_one(:pivotaltracker_service) }
- it { is_expected.to have_one(:hipchat_service) }
it { is_expected.to have_one(:flowdock_service) }
it { is_expected.to have_one(:assembla_service) }
it { is_expected.to have_one(:slack_slash_commands_service) }
@@ -51,6 +50,7 @@ describe Project do
it { is_expected.to have_one(:teamcity_service) }
it { is_expected.to have_one(:jira_service) }
it { is_expected.to have_one(:redmine_service) }
+ it { is_expected.to have_one(:youtrack_service) }
it { is_expected.to have_one(:custom_issue_tracker_service) }
it { is_expected.to have_one(:bugzilla_service) }
it { is_expected.to have_one(:gitlab_issue_tracker_service) }
@@ -62,6 +62,7 @@ describe Project do
it { is_expected.to have_one(:last_event).class_name('Event') }
it { is_expected.to have_one(:forked_from_project).through(:fork_network_member) }
it { is_expected.to have_one(:auto_devops).class_name('ProjectAutoDevops') }
+ it { is_expected.to have_one(:error_tracking_setting).class_name('ErrorTracking::ProjectErrorTrackingSetting') }
it { is_expected.to have_many(:commit_statuses) }
it { is_expected.to have_many(:ci_pipelines) }
it { is_expected.to have_many(:builds) }
@@ -208,9 +209,14 @@ describe Project do
it 'does not allow new projects beyond user limits' do
project2 = build(:project)
- allow(project2).to receive(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object)
+
+ allow(project2)
+ .to receive(:creator)
+ .and_return(
+ double(can_create_project?: false, projects_limit: 0).as_null_object
+ )
+
expect(project2).not_to be_valid
- expect(project2.errors[:limit_reached].first).to match(/Personal project creation is not allowed/)
end
describe 'wiki path conflict' do
@@ -299,6 +305,13 @@ describe Project do
expect(project.errors[:import_url].first).to include('Requests to localhost are not allowed')
end
+ it 'does not allow import_url pointing to the local network' do
+ project = build(:project, import_url: 'https://192.168.1.1')
+
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Requests to the local network are not allowed')
+ end
+
it "does not allow import_url with invalid ports for new projects" do
project = build(:project, import_url: 'http://github.com:25/t.git')
@@ -392,6 +405,54 @@ describe Project do
end
end
+ describe '#all_pipelines' do
+ let(:project) { create(:project) }
+
+ before do
+ create(:ci_pipeline, project: project, ref: 'master', source: :web)
+ create(:ci_pipeline, project: project, ref: 'master', source: :external)
+ end
+
+ it 'has all pipelines' do
+ expect(project.all_pipelines.size).to eq(2)
+ end
+
+ context 'when builds are disabled' do
+ before do
+ project.project_feature.update_attribute(:builds_access_level, ProjectFeature::DISABLED)
+ end
+
+ it 'should return .external pipelines' do
+ expect(project.all_pipelines).to all(have_attributes(source: 'external'))
+ expect(project.all_pipelines.size).to eq(1)
+ end
+ end
+ end
+
+ describe '#ci_pipelines' do
+ let(:project) { create(:project) }
+
+ before do
+ create(:ci_pipeline, project: project, ref: 'master', source: :web)
+ create(:ci_pipeline, project: project, ref: 'master', source: :external)
+ end
+
+ it 'has ci pipelines' do
+ expect(project.ci_pipelines.size).to eq(2)
+ end
+
+ context 'when builds are disabled' do
+ before do
+ project.project_feature.update_attribute(:builds_access_level, ProjectFeature::DISABLED)
+ end
+
+ it 'should return .external pipelines' do
+ expect(project.ci_pipelines).to all(have_attributes(source: 'external'))
+ expect(project.ci_pipelines.size).to eq(1)
+ end
+ end
+ end
+
describe 'project token' do
it 'sets an random token if none provided' do
project = FactoryBot.create(:project, runners_token: '')
@@ -422,6 +483,7 @@ describe Project do
it { is_expected.to delegate_method(:name).to(:owner).with_prefix(true).with_arguments(allow_nil: true) }
it { is_expected.to delegate_method(:group_clusters_enabled?).to(:group).with_arguments(allow_nil: true) }
it { is_expected.to delegate_method(:root_ancestor).to(:namespace).with_arguments(allow_nil: true) }
+ it { is_expected.to delegate_method(:last_pipeline).to(:commit).with_arguments(allow_nil: true) }
end
describe '#to_reference_with_postfix' do
@@ -603,16 +665,20 @@ describe Project do
end
it 'returns the address to create a new issue' do
- address = "p+#{project.full_path}+#{user.incoming_email_token}@gl.ab"
+ address = "p+#{project.full_path_slug}-#{project.project_id}-#{user.incoming_email_token}-issue@gl.ab"
expect(project.new_issuable_address(user, 'issue')).to eq(address)
end
it 'returns the address to create a new merge request' do
- address = "p+#{project.full_path}+merge-request+#{user.incoming_email_token}@gl.ab"
+ address = "p+#{project.full_path_slug}-#{project.project_id}-#{user.incoming_email_token}-merge-request@gl.ab"
expect(project.new_issuable_address(user, 'merge_request')).to eq(address)
end
+
+ it 'returns nil with invalid address type' do
+ expect(project.new_issuable_address(user, 'invalid_param')).to be_nil
+ end
end
context 'incoming email disabled' do
@@ -1093,13 +1159,13 @@ describe Project do
describe '#pipeline_for' do
let(:project) { create(:project, :repository) }
- let!(:pipeline) { create_pipeline }
+ let!(:pipeline) { create_pipeline(project) }
shared_examples 'giving the correct pipeline' do
it { is_expected.to eq(pipeline) }
context 'return latest' do
- let!(:pipeline2) { create_pipeline }
+ let!(:pipeline2) { create_pipeline(project) }
it { is_expected.to eq(pipeline2) }
end
@@ -1116,13 +1182,6 @@ describe Project do
it_behaves_like 'giving the correct pipeline'
end
-
- def create_pipeline
- create(:ci_pipeline,
- project: project,
- ref: 'master',
- sha: project.commit('master').sha)
- end
end
describe '#builds_enabled' do
@@ -1408,6 +1467,24 @@ describe Project do
end
end
+ describe '#visibility_level' do
+ let(:project) { build(:project) }
+
+ subject { project.visibility_level }
+
+ context 'by default' do
+ it { is_expected.to eq(Gitlab::VisibilityLevel::PRIVATE) }
+ end
+
+ context 'when set to INTERNAL in application settings' do
+ before do
+ stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ it { is_expected.to eq(Gitlab::VisibilityLevel::INTERNAL) }
+ end
+ end
+
describe '#visibility_level_allowed?' do
let(:project) { create(:project, :internal) }
@@ -1713,7 +1790,7 @@ describe Project do
context 'using a regular repository' do
it 'creates the repository' do
expect(shell).to receive(:create_repository)
- .with(project.repository_storage, project.disk_path)
+ .with(project.repository_storage, project.disk_path, project.full_path)
.and_return(true)
expect(project.repository).to receive(:after_create)
@@ -1723,7 +1800,7 @@ describe Project do
it 'adds an error if the repository could not be created' do
expect(shell).to receive(:create_repository)
- .with(project.repository_storage, project.disk_path)
+ .with(project.repository_storage, project.disk_path, project.full_path)
.and_return(false)
expect(project.repository).not_to receive(:after_create)
@@ -1756,7 +1833,7 @@ describe Project do
.and_return(false)
allow(shell).to receive(:create_repository)
- .with(project.repository_storage, project.disk_path)
+ .with(project.repository_storage, project.disk_path, project.full_path)
.and_return(true)
expect(project).to receive(:create_repository).with(force: true)
@@ -1780,7 +1857,7 @@ describe Project do
.and_return(false)
expect(shell).to receive(:create_repository)
- .with(project.repository_storage, project.disk_path)
+ .with(project.repository_storage, project.disk_path, project.full_path)
.and_return(true)
project.ensure_repository
@@ -1910,38 +1987,21 @@ describe Project do
end
end
- describe '#latest_successful_builds_for and #latest_successful_build_for' do
- def create_pipeline(status = 'success')
- create(:ci_pipeline, project: project,
- sha: project.commit.sha,
- ref: project.default_branch,
- status: status)
- end
-
- def create_build(new_pipeline = pipeline, name = 'test')
- create(:ci_build, :success, :artifacts,
- pipeline: new_pipeline,
- status: new_pipeline.status,
- name: name)
- end
-
+ describe '#latest_successful_build_for' do
let(:project) { create(:project, :repository) }
- let(:pipeline) { create_pipeline }
+ let(:pipeline) { create_pipeline(project) }
context 'with many builds' do
it 'gives the latest builds from latest pipeline' do
- pipeline1 = create_pipeline
- pipeline2 = create_pipeline
+ pipeline1 = create_pipeline(project)
+ pipeline2 = create_pipeline(project)
create_build(pipeline1, 'test')
create_build(pipeline1, 'test2')
build1_p2 = create_build(pipeline2, 'test')
- build2_p2 = create_build(pipeline2, 'test2')
-
- latest_builds = project.latest_successful_builds_for
- single_build = project.latest_successful_build_for(build1_p2.name)
+ create_build(pipeline2, 'test2')
- expect(latest_builds).to contain_exactly(build2_p2, build1_p2)
- expect(single_build).to eq(build1_p2)
+ expect(project.latest_successful_build_for(build1_p2.name))
+ .to eq(build1_p2)
end
end
@@ -1950,51 +2010,90 @@ describe Project do
context 'standalone pipeline' do
it 'returns builds for ref for default_branch' do
- builds = project.latest_successful_builds_for
- single_build = project.latest_successful_build_for(build.name)
+ expect(project.latest_successful_build_for(build.name))
+ .to eq(build)
+ end
+
+ it 'returns empty relation if the build cannot be found' do
+ expect(project.latest_successful_build_for('TAIL'))
+ .to be_nil
+ end
+ end
+
+ context 'with some pending pipeline' do
+ before do
+ create_build(create_pipeline(project, 'pending'))
+ end
- expect(builds).to contain_exactly(build)
- expect(single_build).to eq(build)
+ it 'gives the latest build from latest pipeline' do
+ expect(project.latest_successful_build_for(build.name))
+ .to eq(build)
end
+ end
+ end
+
+ context 'with pending pipeline' do
+ it 'returns empty relation' do
+ pipeline.update(status: 'pending')
+ pending_build = create_build(pipeline)
+
+ expect(project.latest_successful_build_for(pending_build.name)).to be_nil
+ end
+ end
+ end
+
+ describe '#latest_successful_build_for!' do
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create_pipeline(project) }
- it 'returns empty relation if the build cannot be found for #latest_successful_builds_for' do
- builds = project.latest_successful_builds_for('TAIL')
+ context 'with many builds' do
+ it 'gives the latest builds from latest pipeline' do
+ pipeline1 = create_pipeline(project)
+ pipeline2 = create_pipeline(project)
+ create_build(pipeline1, 'test')
+ create_build(pipeline1, 'test2')
+ build1_p2 = create_build(pipeline2, 'test')
+ create_build(pipeline2, 'test2')
+
+ expect(project.latest_successful_build_for(build1_p2.name))
+ .to eq(build1_p2)
+ end
+ end
+
+ context 'with succeeded pipeline' do
+ let!(:build) { create_build }
- expect(builds).to be_kind_of(ActiveRecord::Relation)
- expect(builds).to be_empty
+ context 'standalone pipeline' do
+ it 'returns builds for ref for default_branch' do
+ expect(project.latest_successful_build_for!(build.name))
+ .to eq(build)
end
- it 'returns exception if the build cannot be found for #latest_successful_build_for' do
- expect { project.latest_successful_build_for(build.name, 'TAIL') }.to raise_error(ActiveRecord::RecordNotFound)
+ it 'returns exception if the build cannot be found' do
+ expect { project.latest_successful_build_for!(build.name, 'TAIL') }
+ .to raise_error(ActiveRecord::RecordNotFound)
end
end
context 'with some pending pipeline' do
before do
- create_build(create_pipeline('pending'))
+ create_build(create_pipeline(project, 'pending'))
end
it 'gives the latest build from latest pipeline' do
- latest_builds = project.latest_successful_builds_for
- last_single_build = project.latest_successful_build_for(build.name)
-
- expect(latest_builds).to contain_exactly(build)
- expect(last_single_build).to eq(build)
+ expect(project.latest_successful_build_for!(build.name))
+ .to eq(build)
end
end
end
context 'with pending pipeline' do
- before do
- pipeline.update(status: 'pending')
- create_build(pipeline)
- end
-
it 'returns empty relation' do
- builds = project.latest_successful_builds_for
+ pipeline.update(status: 'pending')
+ pending_build = create_build(pipeline)
- expect(builds).to be_kind_of(ActiveRecord::Relation)
- expect(builds).to be_empty
+ expect { project.latest_successful_build_for!(pending_build.name) }
+ .to raise_error(ActiveRecord::RecordNotFound)
end
end
end
@@ -2262,6 +2361,18 @@ describe Project do
end
end
+ describe '#daily_statistics_enabled?' do
+ it { is_expected.to be_daily_statistics_enabled }
+
+ context 'when :project_daily_statistics is disabled for the project' do
+ before do
+ stub_feature_flags(project_daily_statistics: { thing: subject, enabled: false })
+ end
+
+ it { is_expected.not_to be_daily_statistics_enabled }
+ end
+ end
+
describe '#change_head' do
let(:project) { create(:project, :repository) }
@@ -2399,6 +2510,30 @@ describe Project do
end
end
+ describe '#set_repository_read_only!' do
+ let(:project) { create(:project) }
+
+ it 'returns true when there is no existing git transfer in progress' do
+ expect(project.set_repository_read_only!).to be_truthy
+ end
+
+ it 'returns false when there is an existing git transfer in progress' do
+ allow(project).to receive(:git_transfer_in_progress?) { true }
+
+ expect(project.set_repository_read_only!).to be_falsey
+ end
+ end
+
+ describe '#set_repository_writable!' do
+ it 'sets repository_read_only to false' do
+ project = create(:project, :read_only)
+
+ expect { project.set_repository_writable! }
+ .to change(project, :repository_read_only)
+ .from(true).to(false)
+ end
+ end
+
describe '#pushes_since_gc' do
let(:project) { create(:project) }
@@ -2460,6 +2595,14 @@ describe Project do
end
end
+ context 'when project uses mock deployment service' do
+ let(:project) { create(:mock_deployment_project) }
+
+ it 'returns an empty array' do
+ expect(project.deployment_variables).to eq []
+ end
+ end
+
context 'when project has a deployment service' do
shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
it 'returns variables from this service' do
@@ -2543,6 +2686,10 @@ describe Project do
end
context 'when the ref is not protected' do
+ before do
+ allow(project).to receive(:protected_for?).with('ref').and_return(false)
+ end
+
it 'contains only the CI variables' do
is_expected.to contain_exactly(ci_variable)
end
@@ -2582,42 +2729,139 @@ describe Project do
end
describe '#protected_for?' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
- subject { project.protected_for?('ref') }
+ subject { project.protected_for?(ref) }
- context 'when the ref is not protected' do
+ shared_examples 'ref is not protected' do
before do
stub_application_setting(
default_branch_protection: Gitlab::Access::PROTECTION_NONE)
end
it 'returns false' do
- is_expected.to be_falsey
+ is_expected.to be false
end
end
- context 'when the ref is a protected branch' do
+ shared_examples 'ref is protected branch' do
before do
- allow(project).to receive(:repository).and_call_original
- allow(project).to receive_message_chain(:repository, :branch_exists?).and_return(true)
- create(:protected_branch, name: 'ref', project: project)
+ create(:protected_branch, name: 'master', project: project)
end
it 'returns true' do
- is_expected.to be_truthy
+ is_expected.to be true
end
end
- context 'when the ref is a protected tag' do
+ shared_examples 'ref is protected tag' do
before do
- allow(project).to receive_message_chain(:repository, :branch_exists?).and_return(false)
- allow(project).to receive_message_chain(:repository, :tag_exists?).and_return(true)
- create(:protected_tag, name: 'ref', project: project)
+ create(:protected_tag, name: 'v1.0.0', project: project)
end
it 'returns true' do
- is_expected.to be_truthy
+ is_expected.to be true
+ end
+ end
+
+ context 'when ref is nil' do
+ let(:ref) { nil }
+
+ it 'returns false' do
+ is_expected.to be false
+ end
+ end
+
+ context 'when ref is ref name' do
+ context 'when ref is ambiguous' do
+ let(:ref) { 'ref' }
+
+ before do
+ project.repository.add_branch(project.creator, 'ref', 'master')
+ project.repository.add_tag(project.creator, 'ref', 'master')
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Repository::AmbiguousRefError)
+ end
+ end
+
+ context 'when the ref is not protected' do
+ let(:ref) { 'master' }
+
+ it_behaves_like 'ref is not protected'
+ end
+
+ context 'when the ref is a protected branch' do
+ let(:ref) { 'master' }
+
+ it_behaves_like 'ref is protected branch'
+ end
+
+ context 'when the ref is a protected tag' do
+ let(:ref) { 'v1.0.0' }
+
+ it_behaves_like 'ref is protected tag'
+ end
+
+ context 'when ref does not exist' do
+ let(:ref) { 'something' }
+
+ it 'returns false' do
+ is_expected.to be false
+ end
+ end
+ end
+
+ context 'when ref is full ref' do
+ context 'when the ref is not protected' do
+ let(:ref) { 'refs/heads/master' }
+
+ it_behaves_like 'ref is not protected'
+ end
+
+ context 'when the ref is a protected branch' do
+ let(:ref) { 'refs/heads/master' }
+
+ it_behaves_like 'ref is protected branch'
+ end
+
+ context 'when the ref is a protected tag' do
+ let(:ref) { 'refs/tags/v1.0.0' }
+
+ it_behaves_like 'ref is protected tag'
+ end
+
+ context 'when branch ref name is a full tag ref' do
+ let(:ref) { 'refs/tags/something' }
+
+ before do
+ project.repository.add_branch(project.creator, ref, 'master')
+ end
+
+ context 'when ref is not protected' do
+ it 'returns false' do
+ is_expected.to be false
+ end
+ end
+
+ context 'when ref is a protected branch' do
+ before do
+ create(:protected_branch, name: 'refs/tags/something', project: project)
+ end
+
+ it 'returns true' do
+ is_expected.to be true
+ end
+ end
+ end
+
+ context 'when ref does not exist' do
+ let(:ref) { 'refs/heads/something' }
+
+ it 'returns false' do
+ is_expected.to be false
+ end
end
end
end
@@ -2837,7 +3081,7 @@ describe Project do
it 'shows full error updating an invalid MR' do
error_message = 'Failed to replace merge_requests because one or more of the new records could not be saved.'\
- ' Validate fork Source project is not a fork of the target project'
+ ' Validate fork Source project is not a fork of the target project'
expect { project.append_or_update_attribute(:merge_requests, [create(:merge_request)]) }
.to raise_error(ActiveRecord::RecordNotSaved, error_message)
@@ -2851,6 +3095,24 @@ describe Project do
end
end
+ describe '#update' do
+ let(:project) { create(:project) }
+
+ it 'validates the visibility' do
+ expect(project).to receive(:visibility_level_allowed_as_fork).and_call_original
+ expect(project).to receive(:visibility_level_allowed_by_group).and_call_original
+
+ project.update(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ it 'does not validate the visibility' do
+ expect(project).not_to receive(:visibility_level_allowed_as_fork).and_call_original
+ expect(project).not_to receive(:visibility_level_allowed_by_group).and_call_original
+
+ project.update(updated_at: Time.now)
+ end
+ end
+
describe '#last_repository_updated_at' do
it 'sets to created_at upon creation' do
project = create(:project, created_at: 2.hours.ago)
@@ -2891,6 +3153,66 @@ describe Project do
end
end
+ describe '.with_feature_available_for_user' do
+ let!(:user) { create(:user) }
+ let!(:feature) { MergeRequest }
+ let!(:project) { create(:project, :public, :merge_requests_enabled) }
+
+ subject { described_class.with_feature_available_for_user(feature, user) }
+
+ context 'when user has access to project' do
+ subject { described_class.with_feature_available_for_user(feature, user) }
+
+ before do
+ project.add_guest(user)
+ end
+
+ context 'when public project' do
+ context 'when feature is public' do
+ it 'returns project' do
+ is_expected.to include(project)
+ end
+ end
+
+ context 'when feature is private' do
+ let!(:project) { create(:project, :public, :merge_requests_private) }
+
+ it 'returns project when user has access to the feature' do
+ project.add_maintainer(user)
+
+ is_expected.to include(project)
+ end
+
+ it 'does not return project when user does not have the minimum access level required' do
+ is_expected.not_to include(project)
+ end
+ end
+ end
+
+ context 'when private project' do
+ let!(:project) { create(:project) }
+
+ it 'returns project when user has access to the feature' do
+ project.add_maintainer(user)
+
+ is_expected.to include(project)
+ end
+
+ it 'does not return project when user does not have the minimum access level required' do
+ is_expected.not_to include(project)
+ end
+ end
+ end
+
+ context 'when user does not have access to project' do
+ let!(:project) { create(:project) }
+
+ it 'does not return project when user cant access project' do
+ is_expected.not_to include(project)
+ end
+ end
+ end
+
describe '#pages_available?' do
let(:project) { create(:project, group: group) }
@@ -2909,7 +3231,7 @@ describe Project do
context 'when the project is in a subgroup' do
let(:group) { create(:group, :nested) }
- it { is_expected.to be(false) }
+ it { is_expected.to be(true) }
end
end
@@ -3013,8 +3335,35 @@ describe Project do
end
end
+ describe '#git_transfer_in_progress?' do
+ let(:project) { build(:project) }
+
+ subject { project.git_transfer_in_progress? }
+
+ it 'returns false when repo_reference_count and wiki_reference_count are 0' do
+ allow(project).to receive(:repo_reference_count) { 0 }
+ allow(project).to receive(:wiki_reference_count) { 0 }
+
+ expect(subject).to be_falsey
+ end
+
+ it 'returns true when repo_reference_count is > 0' do
+ allow(project).to receive(:repo_reference_count) { 2 }
+ allow(project).to receive(:wiki_reference_count) { 0 }
+
+ expect(subject).to be_truthy
+ end
+
+ it 'returns true when wiki_reference_count is > 0' do
+ allow(project).to receive(:repo_reference_count) { 0 }
+ allow(project).to receive(:wiki_reference_count) { 2 }
+
+ expect(subject).to be_truthy
+ end
+ end
+
context 'legacy storage' do
- let(:project) { create(:project, :repository, :legacy_storage) }
+ set(:project) { create(:project, :repository, :legacy_storage) }
let(:gitlab_shell) { Gitlab::Shell.new }
let(:project_storage) { project.send(:storage) }
@@ -3069,40 +3418,58 @@ describe Project do
end
describe '#migrate_to_hashed_storage!' do
+ let(:project) { create(:project, :empty_repo, :legacy_storage) }
+
it 'returns true' do
expect(project.migrate_to_hashed_storage!).to be_truthy
end
- it 'flags as read-only' do
- expect { project.migrate_to_hashed_storage! }.to change { project.repository_read_only }.to(true)
+ it 'does not run validation' do
+ expect(project).not_to receive(:valid?)
+
+ project.migrate_to_hashed_storage!
end
- it 'schedules ProjectMigrateHashedStorageWorker with delayed start when the project repo is in use' do
+ it 'schedules HashedStorage::ProjectMigrateWorker with delayed start when the project repo is in use' do
Gitlab::ReferenceCounter.new(project.gl_repository(is_wiki: false)).increase
- expect(ProjectMigrateHashedStorageWorker).to receive(:perform_in)
+ expect(HashedStorage::ProjectMigrateWorker).to receive(:perform_in)
project.migrate_to_hashed_storage!
end
- it 'schedules ProjectMigrateHashedStorageWorker with delayed start when the wiki repo is in use' do
+ it 'schedules HashedStorage::ProjectMigrateWorker with delayed start when the wiki repo is in use' do
Gitlab::ReferenceCounter.new(project.gl_repository(is_wiki: true)).increase
- expect(ProjectMigrateHashedStorageWorker).to receive(:perform_in)
+ expect(HashedStorage::ProjectMigrateWorker).to receive(:perform_in)
project.migrate_to_hashed_storage!
end
- it 'schedules ProjectMigrateHashedStorageWorker' do
- expect(ProjectMigrateHashedStorageWorker).to receive(:perform_async).with(project.id)
+ it 'schedules HashedStorage::ProjectMigrateWorker' do
+ expect(HashedStorage::ProjectMigrateWorker).to receive(:perform_async).with(project.id)
project.migrate_to_hashed_storage!
end
end
+
+ describe '#rollback_to_legacy_storage!' do
+ let(:project) { create(:project, :empty_repo, :legacy_storage) }
+
+ it 'returns nil' do
+ expect(project.rollback_to_legacy_storage!).to be_nil
+ end
+
+ it 'does not run validations' do
+ expect(project).not_to receive(:valid?)
+
+ project.rollback_to_legacy_storage!
+ end
+ end
end
context 'hashed storage' do
- let(:project) { create(:project, :repository, skip_disk_validation: true) }
+ set(:project) { create(:project, :repository, skip_disk_validation: true) }
let(:gitlab_shell) { Gitlab::Shell.new }
let(:hash) { Digest::SHA2.hexdigest(project.id.to_s) }
let(:hashed_prefix) { File.join('@hashed', hash[0..1], hash[2..3]) }
@@ -3159,6 +3526,8 @@ describe Project do
end
describe '#migrate_to_hashed_storage!' do
+ let(:project) { create(:project, :repository, skip_disk_validation: true) }
+
it 'returns nil' do
expect(project.migrate_to_hashed_storage!).to be_nil
end
@@ -3168,10 +3537,36 @@ describe Project do
end
context 'when partially migrated' do
- it 'returns true' do
+ it 'enqueues a job' do
project = create(:project, storage_version: 1, skip_disk_validation: true)
- expect(project.migrate_to_hashed_storage!).to be_truthy
+ Sidekiq::Testing.fake! do
+ expect { project.migrate_to_hashed_storage! }.to change(HashedStorage::ProjectMigrateWorker.jobs, :size).by(1)
+ end
+ end
+ end
+ end
+
+ describe '#rollback_to_legacy_storage!' do
+ let(:project) { create(:project, :repository, skip_disk_validation: true) }
+
+ it 'returns true' do
+ expect(project.rollback_to_legacy_storage!).to be_truthy
+ end
+
+ it 'does not run validations' do
+ expect(project).not_to receive(:valid?)
+
+ project.rollback_to_legacy_storage!
+ end
+
+ it 'does not flag as read-only' do
+ expect { project.rollback_to_legacy_storage! }.not_to change { project.repository_read_only }
+ end
+
+ it 'enqueues a job' do
+ Sidekiq::Testing.fake! do
+ expect { project.rollback_to_legacy_storage! }.to change(HashedStorage::ProjectRollbackWorker.jobs, :size).by(1)
end
end
end
@@ -3388,7 +3783,31 @@ describe Project do
end
end
- context '#auto_devops_variables' do
+ describe '#api_variables' do
+ set(:project) { create(:project) }
+
+ it 'exposes API v4 URL' do
+ expect(project.api_variables.first[:key]).to eq 'CI_API_V4_URL'
+ expect(project.api_variables.first[:value]).to include '/api/v4'
+ end
+
+ it 'contains a URL variable for every supported API version' do
+ # Ensure future API versions have proper variables defined. We're not doing this for v3.
+ supported_versions = API::API.versions - ['v3']
+ supported_versions = supported_versions.select do |version|
+ API::API.routes.select { |route| route.version == version }.many?
+ end
+
+ required_variables = supported_versions.map do |version|
+ "CI_API_#{version.upcase}_URL"
+ end
+
+ expect(project.api_variables.map { |variable| variable[:key] })
+ .to contain_exactly(*required_variables)
+ end
+ end
+
+ describe '#auto_devops_variables' do
set(:project) { create(:project) }
subject { project.auto_devops_variables }
@@ -3525,6 +3944,7 @@ describe Project do
expect(import_state).to receive(:remove_jid)
expect(project).to receive(:after_create_default_branch)
expect(project).to receive(:refresh_markdown_cache!)
+ expect(InternalId).to receive(:flush_records!).with(project: project)
project.after_import
end
@@ -3689,7 +4109,7 @@ describe Project do
describe '#badges' do
let(:project_group) { create(:group) }
- let(:project) { create(:project, path: 'avatar', namespace: project_group) }
+ let(:project) { create(:project, path: 'avatar', namespace: project_group) }
before do
create_list(:project_badge, 2, project: project)
@@ -3723,6 +4143,16 @@ describe Project do
let(:user) { create(:user) }
let(:target_project) { create(:project, :repository) }
let(:project) { fork_project(target_project, nil, repository: true) }
+ let!(:local_merge_request) do
+ create(
+ :merge_request,
+ target_project: project,
+ target_branch: 'target-branch',
+ source_project: project,
+ source_branch: 'awesome-feature-1',
+ allow_collaboration: true
+ )
+ end
let!(:merge_request) do
create(
:merge_request,
@@ -3767,14 +4197,23 @@ describe Project do
end
end
- describe '#branch_allows_collaboration_push?' do
- it 'allows access if the user can merge the merge request' do
- expect(project.branch_allows_collaboration?(user, 'awesome-feature-1'))
+ describe '#any_branch_allows_collaboration?' do
+ it 'allows access when there are merge requests open allowing collaboration' do
+ expect(project.any_branch_allows_collaboration?(user))
.to be_truthy
end
- it 'allows access when there are merge requests open but no branch name is given' do
- expect(project.branch_allows_collaboration?(user, nil))
+ it 'does not allow access when there are no merge requests open allowing collaboration' do
+ merge_request.close!
+
+ expect(project.any_branch_allows_collaboration?(user))
+ .to be_falsey
+ end
+ end
+
+ describe '#branch_allows_collaboration?' do
+ it 'allows access if the user can merge the merge request' do
+ expect(project.branch_allows_collaboration?(user, 'awesome-feature-1'))
.to be_truthy
end
@@ -3805,13 +4244,6 @@ describe Project do
.to be_falsy
end
- it 'caches the result' do
- control = ActiveRecord::QueryRecorder.new { project.branch_allows_collaboration?(user, 'awesome-feature-1') }
-
- expect { 3.times { project.branch_allows_collaboration?(user, 'awesome-feature-1') } }
- .not_to exceed_query_limit(control)
- end
-
context 'when the requeststore is active', :request_store do
it 'only queries per project across instances' do
control = ActiveRecord::QueryRecorder.new { project.branch_allows_collaboration?(user, 'awesome-feature-1') }
@@ -4176,7 +4608,116 @@ describe Project do
end
end
+ describe '#leave_pool_repository' do
+ let(:pool) { create(:pool_repository) }
+ let(:project) { create(:project, :repository, pool_repository: pool) }
+
+ it 'removes the membership' do
+ project.leave_pool_repository
+
+ expect(pool.member_projects.reload).not_to include(project)
+ end
+ end
+
+ describe '#check_personal_projects_limit' do
+ context 'when creating a project for a group' do
+ it 'does nothing' do
+ creator = build(:user)
+ project = build(:project, namespace: build(:group), creator: creator)
+
+ allow(creator)
+ .to receive(:can_create_project?)
+ .and_return(false)
+
+ project.check_personal_projects_limit
+
+ expect(project.errors).to be_empty
+ end
+ end
+
+ context 'when the user is not allowed to create a personal project' do
+ let(:user) { build(:user) }
+ let(:project) { build(:project, creator: user) }
+
+ before do
+ allow(user)
+ .to receive(:can_create_project?)
+ .and_return(false)
+ end
+
+ context 'when the project limit is zero' do
+ it 'adds a validation error' do
+ allow(user)
+ .to receive(:projects_limit)
+ .and_return(0)
+
+ project.check_personal_projects_limit
+
+ expect(project.errors[:limit_reached].first)
+ .to match(/Personal project creation is not allowed/)
+ end
+ end
+
+ context 'when the project limit is greater than zero' do
+ it 'adds a validation error' do
+ allow(user)
+ .to receive(:projects_limit)
+ .and_return(5)
+
+ project.check_personal_projects_limit
+
+ expect(project.errors[:limit_reached].first)
+ .to match(/Your project limit is 5 projects/)
+ end
+ end
+ end
+
+ context 'when the user is allowed to create personal projects' do
+ it 'does nothing' do
+ user = build(:user)
+ project = build(:project, creator: user)
+
+ allow(user)
+ .to receive(:can_create_project?)
+ .and_return(true)
+
+ project.check_personal_projects_limit
+
+ expect(project.errors).to be_empty
+ end
+ end
+ end
+
+ describe '#has_pool_repsitory?' do
+ it 'returns false when it does not have a pool repository' do
+ subject = create(:project, :repository)
+
+ expect(subject.has_pool_repository?).to be false
+ end
+
+ it 'returns true when it has a pool repository' do
+ pool = create(:pool_repository, :ready)
+ subject = create(:project, :repository, pool_repository: pool)
+
+ expect(subject.has_pool_repository?).to be true
+ end
+ 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,
+ ref: project.default_branch,
+ status: status)
+ end
+
+ def create_build(new_pipeline = pipeline, name = 'test')
+ create(:ci_build, :success, :artifacts,
+ pipeline: new_pipeline,
+ status: new_pipeline.status,
+ name: name)
+ end
end
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index c4af17f4726..3537dead5d1 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -178,6 +178,21 @@ describe ProjectTeam do
end
end
+ describe '#members_in_project_and_ancestors' do
+ context 'group project' do
+ it 'filters out users who are not members of the project' do
+ group = create(:group)
+ project = create(:project, group: group)
+ group_member = create(:group_member, group: group)
+ old_user = create(:user)
+
+ ProjectAuthorization.create!(project: project, user: old_user, access_level: Gitlab::Access::GUEST)
+
+ expect(project.team.members_in_project_and_ancestors).to contain_exactly(group_member.user)
+ end
+ end
+ end
+
describe "#human_max_access" do
it 'returns Maintainer role' do
user = create(:user)
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 48a43801b9f..3ccc706edf2 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -7,7 +7,7 @@ describe ProjectWiki do
let(:repository) { project.repository }
let(:gitlab_shell) { Gitlab::Shell.new }
let(:project_wiki) { described_class.new(project, user) }
- let(:raw_repository) { Gitlab::Git::Repository.new(project.repository_storage, subject.disk_path + '.git', 'foo') }
+ let(:raw_repository) { Gitlab::Git::Repository.new(project.repository_storage, subject.disk_path + '.git', 'foo', 'group/project.wiki') }
let(:commit) { project_wiki.repository.head_commit }
subject { project_wiki }
@@ -75,7 +75,7 @@ describe ProjectWiki do
# Create a fresh project which will not have a wiki
project_wiki = described_class.new(create(:project), user)
gitlab_shell = double(:gitlab_shell)
- allow(gitlab_shell).to receive(:create_repository)
+ allow(gitlab_shell).to receive(:create_wiki_repository)
allow(project_wiki).to receive(:gitlab_shell).and_return(gitlab_shell)
expect { project_wiki.send(:wiki) }.to raise_exception(ProjectWiki::CouldNotCreateWikiError)
diff --git a/spec/models/prometheus_metric_spec.rb b/spec/models/prometheus_metric_spec.rb
index 3692fe9a559..3610408c138 100644
--- a/spec/models/prometheus_metric_spec.rb
+++ b/spec/models/prometheus_metric_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
describe PrometheusMetric do
subject { build(:prometheus_metric) }
- let(:other_project) { build(:project) }
it_behaves_like 'having unique enum values'
@@ -16,17 +15,17 @@ describe PrometheusMetric do
describe 'common metrics' do
using RSpec::Parameterized::TableSyntax
- where(:common, :project, :result) do
- false | other_project | true
- false | nil | false
- true | other_project | false
- true | nil | true
+ where(:common, :with_project, :result) do
+ false | true | true
+ false | false | false
+ true | true | false
+ true | false | true
end
with_them do
before do
subject.common = common
- subject.project = project
+ subject.project = with_project ? build(:project) : nil
end
it { expect(subject.valid?).to eq(result) }
@@ -59,11 +58,65 @@ describe PrometheusMetric do
end
end
+ it_behaves_like 'group_title', :nginx_ingress_vts, 'Response metrics (NGINX Ingress VTS)'
+ it_behaves_like 'group_title', :nginx_ingress, 'Response metrics (NGINX Ingress)'
+ it_behaves_like 'group_title', :ha_proxy, 'Response metrics (HA Proxy)'
+ it_behaves_like 'group_title', :aws_elb, 'Response metrics (AWS ELB)'
+ it_behaves_like 'group_title', :nginx, 'Response metrics (NGINX)'
+ it_behaves_like 'group_title', :kubernetes, 'System metrics (Kubernetes)'
it_behaves_like 'group_title', :business, 'Business metrics (Custom)'
it_behaves_like 'group_title', :response, 'Response metrics (Custom)'
it_behaves_like 'group_title', :system, 'System metrics (Custom)'
end
+ describe '#priority' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:group, :priority) do
+ :nginx_ingress_vts | 10
+ :nginx_ingress | 10
+ :ha_proxy | 10
+ :aws_elb | 10
+ :nginx | 10
+ :kubernetes | 5
+ :business | 0
+ :response | -5
+ :system | -10
+ end
+
+ with_them do
+ before do
+ subject.group = group
+ end
+
+ it { expect(subject.priority).to eq(priority) }
+ end
+ end
+
+ describe '#required_metrics' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:group, :required_metrics) do
+ :nginx_ingress_vts | %w(nginx_upstream_responses_total nginx_upstream_response_msecs_avg)
+ :nginx_ingress | %w(nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum)
+ :ha_proxy | %w(haproxy_frontend_http_requests_total haproxy_frontend_http_responses_total)
+ :aws_elb | %w(aws_elb_request_count_sum aws_elb_latency_average aws_elb_httpcode_backend_5_xx_sum)
+ :nginx | %w(nginx_server_requests nginx_server_requestMsec)
+ :kubernetes | %w(container_memory_usage_bytes container_cpu_usage_seconds_total)
+ :business | %w()
+ :response | %w()
+ :system | %w()
+ end
+
+ with_them do
+ before do
+ subject.group = group
+ end
+
+ it { expect(subject.required_metrics).to eq(required_metrics) }
+ end
+ end
+
describe '#to_query_metric' do
it 'converts to queryable metric object' do
expect(subject.to_query_metric).to be_instance_of(Gitlab::Prometheus::Metric)
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index 4c677200ae2..dafe7646366 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -190,4 +190,32 @@ describe ProtectedBranch do
end
end
end
+
+ describe '#any_protected?' do
+ context 'existing project' do
+ let(:project) { create(:project, :repository) }
+
+ it 'returns true when any of the branch names match a protected branch via direct match' do
+ create(:protected_branch, project: project, name: 'foo')
+
+ expect(described_class.any_protected?(project, ['foo', 'production/some-branch'])).to eq(true)
+ end
+
+ it 'returns true when any of the branch matches a protected branch via wildcard match' do
+ create(:protected_branch, project: project, name: 'production/*')
+
+ expect(described_class.any_protected?(project, ['foo', 'production/some-branch'])).to eq(true)
+ end
+
+ it 'returns false when none of branches does not match a protected branch via direct match' do
+ expect(described_class.any_protected?(project, ['foo'])).to eq(false)
+ end
+
+ it 'returns false when none of the branches does not match a protected branch via wildcard match' do
+ create(:protected_branch, project: project, name: 'production/*')
+
+ expect(described_class.any_protected?(project, ['staging/some-branch'])).to eq(false)
+ end
+ end
+ end
end
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 51725eeacac..157c96c1f65 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -1,17 +1,44 @@
require 'rails_helper'
RSpec.describe Release do
- let(:release) { create(:release) }
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+ let(:release) { create(:release, project: project, author: user) }
it { expect(release).to be_valid }
describe 'associations' do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:author).class_name('User') }
+ it { is_expected.to have_many(:links).class_name('Releases::Link') }
end
describe 'validation' do
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:description) }
end
+
+ describe '#assets_count' do
+ subject { release.assets_count }
+
+ it 'returns the number of sources' do
+ is_expected.to eq(Releases::Source::FORMATS.count)
+ end
+
+ context 'when a links exists' do
+ let!(:link) { create(:release_link, release: release) }
+
+ it 'counts the link as an asset' do
+ is_expected.to eq(1 + Releases::Source::FORMATS.count)
+ end
+ end
+ end
+
+ describe '#sources' do
+ subject { release.sources }
+
+ it 'returns sources' do
+ is_expected.to all(be_a(Releases::Source))
+ end
+ end
end
diff --git a/spec/models/releases/link_spec.rb b/spec/models/releases/link_spec.rb
new file mode 100644
index 00000000000..4dd26c976cc
--- /dev/null
+++ b/spec/models/releases/link_spec.rb
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Releases::Link do
+ let(:release) { create(:release, project: project) }
+ let(:project) { create(:project) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:release) }
+ end
+
+ describe 'validation' do
+ it { is_expected.to validate_presence_of(:url) }
+ it { is_expected.to validate_presence_of(:name) }
+
+ context 'when url is invalid' do
+ let(:link) { build(:release_link, url: 'hoge') }
+
+ it 'will be invalid' do
+ expect(link).to be_invalid
+ end
+ end
+
+ context 'when duplicate name is added to a release' do
+ let!(:link) { create(:release_link, name: 'alpha', release: release) }
+
+ it 'raises an error' do
+ expect do
+ create(:release_link, name: 'alpha', release: release)
+ end.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+
+ context 'when duplicate url is added to a release' do
+ let!(:link) { create(:release_link, url: 'http://gitlab.com', release: release) }
+
+ it 'raises an error' do
+ expect do
+ create(:release_link, url: 'http://gitlab.com', release: release)
+ end.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+ end
+
+ describe '.sorted' do
+ subject { described_class.sorted }
+
+ let!(:link_1) { create(:release_link, name: 'alpha', release: release, created_at: 1.day.ago) }
+ let!(:link_2) { create(:release_link, name: 'beta', release: release, created_at: 2.days.ago) }
+
+ it 'returns a list of links by created_at order' do
+ is_expected.to eq([link_1, link_2])
+ end
+ end
+
+ describe '#internal?' do
+ subject { link.internal? }
+
+ let(:link) { build(:release_link, release: release, url: url) }
+ let(:url) { "#{project.web_url}/-/jobs/140463678/artifacts/download" }
+
+ it { is_expected.to be_truthy }
+
+ context 'when link does not include project web url' do
+ let(:url) { 'https://google.com/-/jobs/140463678/artifacts/download' }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ describe '#external?' do
+ subject { link.external? }
+
+ let(:link) { build(:release_link, release: release, url: url) }
+ let(:url) { 'https://google.com/-/jobs/140463678/artifacts/download' }
+
+ it { is_expected.to be_truthy }
+ end
+
+ describe 'supported protocols' do
+ where(:protocol) do
+ %w(http https ftp)
+ end
+
+ with_them do
+ let(:link) { build(:release_link, url: protocol + '://assets.com/download') }
+
+ it 'will be valid' do
+ expect(link).to be_valid
+ end
+ end
+ end
+
+ describe 'unsupported protocol' do
+ context 'for torrent' do
+ let(:link) { build(:release_link, url: 'torrent://assets.com/download') }
+
+ it 'will be invalid' do
+ expect(link).to be_invalid
+ end
+ end
+ end
+end
diff --git a/spec/models/releases/source_spec.rb b/spec/models/releases/source_spec.rb
new file mode 100644
index 00000000000..c5213196962
--- /dev/null
+++ b/spec/models/releases/source_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Releases::Source do
+ set(:project) { create(:project, :repository, name: 'finance-cal') }
+ let(:tag_name) { 'v1.0' }
+
+ describe '.all' do
+ subject { described_class.all(project, tag_name) }
+
+ it 'returns all formats of sources' do
+ expect(subject.map(&:format))
+ .to match_array(described_class::FORMATS)
+ end
+ end
+
+ describe '#url' do
+ subject { source.url }
+
+ let(:source) do
+ described_class.new(project: project, tag_name: tag_name, format: format)
+ end
+
+ let(:format) { 'zip' }
+
+ it 'returns zip archived source url' do
+ is_expected
+ .to eq("#{project.web_url}/-/archive/v1.0/finance-cal-v1.0.zip")
+ end
+
+ context 'when ref is directory structure' do
+ let(:tag_name) { 'beta/v1.0' }
+
+ it 'converts slash to dash' do
+ is_expected
+ .to eq("#{project.web_url}/-/archive/beta/v1.0/finance-cal-beta-v1.0.zip")
+ end
+ end
+ end
+end
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index 5d3c25062d5..c06e9a08ab4 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -24,6 +24,20 @@ describe RemoteMirror, :mailer do
expect(remote_mirror).to be_invalid
expect(remote_mirror.errors[:url].first).to include('Username needs to start with an alphanumeric character')
end
+
+ it 'does not allow url pointing to localhost' do
+ remote_mirror = build(:remote_mirror, url: 'http://127.0.0.2/t.git')
+
+ expect(remote_mirror).to be_invalid
+ expect(remote_mirror.errors[:url].first).to include('Requests to loopback addresses are not allowed')
+ end
+
+ it 'does not allow url pointing to the local network' do
+ remote_mirror = build(:remote_mirror, url: 'https://192.168.1.1')
+
+ expect(remote_mirror).to be_invalid
+ expect(remote_mirror.errors[:url].first).to include('Requests to the local network are not allowed')
+ end
end
end
@@ -289,6 +303,25 @@ describe RemoteMirror, :mailer do
end
end
+ context '#url=' do
+ let(:remote_mirror) { create(:project, :repository, :remote_mirror).remote_mirrors.first }
+
+ it 'resets all the columns when URL changes' do
+ remote_mirror.update(last_error: Time.now,
+ last_update_at: Time.now,
+ last_successful_update_at: Time.now,
+ update_status: 'started',
+ error_notification_sent: true)
+
+ expect { remote_mirror.update_attribute(:url, 'http://new.example.com') }
+ .to change { remote_mirror.last_error }.to(nil)
+ .and change { remote_mirror.last_update_at }.to(nil)
+ .and change { remote_mirror.last_successful_update_at }.to(nil)
+ .and change { remote_mirror.update_status }.to('finished')
+ .and change { remote_mirror.error_notification_sent }.to(false)
+ end
+ end
+
context '#updated_since?' do
let(:remote_mirror) { create(:project, :repository, :remote_mirror).remote_mirrors.first }
let(:timestamp) { Time.now - 5.minutes }
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index f09b4b67061..17201d8b90a 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1005,6 +1005,67 @@ describe Repository do
end
end
+ describe '#ambiguous_ref?' do
+ let(:ref) { 'ref' }
+
+ subject { repository.ambiguous_ref?(ref) }
+
+ context 'when ref is ambiguous' do
+ before do
+ repository.add_tag(project.creator, ref, 'master')
+ repository.add_branch(project.creator, ref, 'master')
+ end
+
+ it 'should be true' do
+ is_expected.to eq(true)
+ end
+ end
+
+ context 'when ref is not ambiguous' do
+ before do
+ repository.add_tag(project.creator, ref, 'master')
+ end
+
+ it 'should be false' do
+ is_expected.to eq(false)
+ end
+ end
+ end
+
+ describe '#expand_ref' do
+ let(:ref) { 'ref' }
+
+ subject { repository.expand_ref(ref) }
+
+ context 'when ref is not tag or branch name' do
+ let(:ref) { 'refs/heads/master' }
+
+ it 'returns nil' do
+ is_expected.to eq(nil)
+ end
+ end
+
+ context 'when ref is tag name' do
+ before do
+ repository.add_tag(project.creator, ref, 'master')
+ end
+
+ it 'returns the tag ref' do
+ is_expected.to eq("refs/tags/#{ref}")
+ end
+ end
+
+ context 'when ref is branch name' do
+ before do
+ repository.add_branch(project.creator, ref, 'master')
+ end
+
+ it 'returns the branch ref' do
+ is_expected.to eq("refs/heads/#{ref}")
+ end
+ end
+ end
+
describe '#add_branch' do
let(:branch_name) { 'new_feature' }
let(:target) { 'master' }
@@ -1176,6 +1237,27 @@ describe Repository do
end
end
+ describe '#blobs_at' do
+ let(:empty_repository) { create(:project_empty_repo).repository }
+
+ it 'returns empty array for an empty repository' do
+ # rubocop:disable Style/WordArray
+ expect(empty_repository.blobs_at(['master', 'foobar'])).to eq([])
+ # rubocop:enable Style/WordArray
+ end
+
+ it 'returns blob array for a non-empty repository' do
+ repository.create_file(User.last, 'foobar', 'CONTENT', message: 'message', branch_name: 'master')
+
+ # rubocop:disable Style/WordArray
+ blobs = repository.blobs_at([['master', 'foobar']])
+ # rubocop:enable Style/WordArray
+
+ expect(blobs.first.name).to eq('foobar')
+ expect(blobs.size).to eq(1)
+ end
+ end
+
describe '#root_ref' do
it 'returns a branch name' do
expect(repository.root_ref).to be_an_instance_of(String)
@@ -1291,6 +1373,29 @@ describe Repository do
end
end
+ describe '#merge_to_ref' do
+ let(:merge_request) do
+ create(:merge_request, source_branch: 'feature',
+ target_branch: 'master',
+ source_project: project)
+ end
+
+ it 'writes merge of source and target to MR merge_ref_path' do
+ merge_commit_id = repository.merge_to_ref(user,
+ merge_request.diff_head_sha,
+ merge_request,
+ merge_request.merge_ref_path,
+ 'Custom message')
+
+ merge_commit = repository.commit(merge_commit_id)
+
+ expect(merge_commit.message).to eq('Custom message')
+ expect(merge_commit.author_name).to eq(user.name)
+ expect(merge_commit.author_email).to eq(user.commit_email)
+ expect(repository.blob_at(merge_commit.id, 'files/ruby/feature.rb')).to be_present
+ end
+ end
+
describe '#ff_merge' do
before do
repository.add_branch(user, 'ff-target', 'feature~5')
@@ -2209,6 +2314,7 @@ describe Repository do
expect(subject).to be_a(Gitlab::Git::Repository)
expect(subject.relative_path).to eq(project.disk_path + '.git')
expect(subject.gl_repository).to eq("project-#{project.id}")
+ expect(subject.gl_project_path).to eq(project.full_path)
end
context 'with a wiki repository' do
@@ -2218,6 +2324,7 @@ describe Repository do
expect(subject).to be_a(Gitlab::Git::Repository)
expect(subject.relative_path).to eq(project.disk_path + '.wiki.git')
expect(subject.gl_repository).to eq("wiki-#{project.id}")
+ expect(subject.gl_project_path).to eq(project.full_path)
end
end
end
@@ -2339,22 +2446,4 @@ describe Repository do
repository.merge_base('master', 'fix')
end
end
-
- describe '#cache' do
- subject(:cache) { repository.send(:cache) }
-
- it 'returns a RepositoryCache' do
- expect(subject).to be_kind_of Gitlab::RepositoryCache
- end
-
- it 'when is_wiki it includes wiki as part of key' do
- allow(repository).to receive(:is_wiki) { true }
-
- expect(subject.namespace).to include('wiki')
- end
-
- it 'when is_wiki is false extra_namespace is nil' do
- expect(subject.namespace).not_to include('wiki')
- end
- end
end
diff --git a/spec/models/resource_label_event_spec.rb b/spec/models/resource_label_event_spec.rb
index e7e3f7376e6..7eeb2fae57d 100644
--- a/spec/models/resource_label_event_spec.rb
+++ b/spec/models/resource_label_event_spec.rb
@@ -81,14 +81,14 @@ RSpec.describe ResourceLabelEvent, type: :model do
expect(subject.outdated_markdown?).to be true
end
- it 'returns true markdown is outdated' do
- subject.attributes = { cached_markdown_version: 0 }
+ it 'returns true if markdown is outdated' do
+ subject.attributes = { cached_markdown_version: ((CacheMarkdownField::CACHE_COMMONMARK_VERSION - 1) << 16) | 0 }
expect(subject.outdated_markdown?).to be true
end
it 'returns false if label and reference are set' do
- subject.attributes = { reference: 'whatever', cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION }
+ subject.attributes = { reference: 'whatever', cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION << 16 }
expect(subject.outdated_markdown?).to be false
end
diff --git a/spec/models/sent_notification_spec.rb b/spec/models/sent_notification_spec.rb
index 5ec04b99957..6c35ed8f649 100644
--- a/spec/models/sent_notification_spec.rb
+++ b/spec/models/sent_notification_spec.rb
@@ -36,19 +36,41 @@ describe SentNotification do
end
end
+ shared_examples 'a successful sent notification' do
+ it 'creates a new SentNotification' do
+ expect { subject }.to change { described_class.count }.by(1)
+ end
+ end
+
describe '.record' do
let(:issue) { create(:issue) }
- it 'creates a new SentNotification' do
- expect { described_class.record(issue, user.id) }.to change { described_class.count }.by(1)
- end
+ subject { described_class.record(issue, user.id) }
+
+ it_behaves_like 'a successful sent notification'
end
describe '.record_note' do
- let(:note) { create(:diff_note_on_merge_request) }
+ subject { described_class.record_note(note, note.author.id) }
- it 'creates a new SentNotification' do
- expect { described_class.record_note(note, user.id) }.to change { described_class.count }.by(1)
+ context 'for a discussion note' do
+ let(:note) { create(:diff_note_on_merge_request) }
+
+ it_behaves_like 'a successful sent notification'
+
+ it 'sets in_reply_to_discussion_id' do
+ expect(subject.in_reply_to_discussion_id).to eq(note.discussion_id)
+ end
+ end
+
+ context 'for an individual note' do
+ let(:note) { create(:note_on_merge_request) }
+
+ it_behaves_like 'a successful sent notification'
+
+ it 'does not set in_reply_to_discussion_id' do
+ expect(subject.in_reply_to_discussion_id).to be_nil
+ end
end
end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 7a7272ccb60..664dc3fa145 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -423,4 +423,41 @@ describe Snippet do
expect(blob.data).to eq(snippet.content)
end
end
+
+ describe '#embeddable?' do
+ context 'project snippet' do
+ [
+ { project: :public, snippet: :public, embeddable: true },
+ { project: :internal, snippet: :public, embeddable: false },
+ { project: :private, snippet: :public, embeddable: false },
+ { project: :public, snippet: :internal, embeddable: false },
+ { project: :internal, snippet: :internal, embeddable: false },
+ { project: :private, snippet: :internal, embeddable: false },
+ { project: :public, snippet: :private, embeddable: false },
+ { project: :internal, snippet: :private, embeddable: false },
+ { project: :private, snippet: :private, embeddable: false }
+ ].each do |combination|
+ it 'only returns true when both project and snippet are public' do
+ project = create(:project, combination[:project])
+ snippet = create(:project_snippet, combination[:snippet], project: project)
+
+ expect(snippet.embeddable?).to eq(combination[:embeddable])
+ end
+ end
+ end
+
+ context 'personal snippet' do
+ [
+ { snippet: :public, embeddable: true },
+ { snippet: :internal, embeddable: false },
+ { snippet: :private, embeddable: false }
+ ].each do |combination|
+ it 'only returns true when snippet is public' do
+ snippet = create(:personal_snippet, combination[:snippet])
+
+ expect(snippet.embeddable?).to eq(combination[:embeddable])
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/ssh_host_key_spec.rb b/spec/models/ssh_host_key_spec.rb
index 75db43b3d56..4c677569561 100644
--- a/spec/models/ssh_host_key_spec.rb
+++ b/spec/models/ssh_host_key_spec.rb
@@ -50,6 +50,35 @@ describe SshHostKey do
subject(:ssh_host_key) { described_class.new(project: project, url: 'ssh://example.com:2222', compare_host_keys: compare_host_keys) }
+ describe '.primary_key' do
+ it 'returns a symbol' do
+ expect(described_class.primary_key).to eq(:id)
+ end
+ end
+
+ describe '.find_by' do
+ let(:project) { create(:project) }
+ let(:url) { 'ssh://invalid.invalid:2222' }
+
+ let(:finding_id) { [project.id, url].join(':') }
+
+ it 'accepts a string key' do
+ result = described_class.find_by('id' => finding_id)
+
+ expect(result).to be_a(described_class)
+ expect(result.project).to eq(project)
+ expect(result.url.to_s).to eq(url)
+ end
+
+ it 'accepts a symbol key' do
+ result = described_class.find_by(id: finding_id)
+
+ expect(result).to be_a(described_class)
+ expect(result.project).to eq(project)
+ expect(result.url.to_s).to eq(url)
+ end
+ end
+
describe '#fingerprints', :use_clean_rails_memory_store_caching do
it 'returns an array of indexed fingerprints when the cache is filled' do
stub_reactive_cache(ssh_host_key, known_hosts: known_hosts)
diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb
index 2898613545c..b2ef17a81d4 100644
--- a/spec/models/user_preference_spec.rb
+++ b/spec/models/user_preference_spec.rb
@@ -3,9 +3,10 @@
require 'spec_helper'
describe UserPreference do
+ let(:user_preference) { create(:user_preference) }
+
describe '#set_notes_filter' do
let(:issuable) { build_stubbed(:issue) }
- let(:user_preference) { create(:user_preference) }
shared_examples 'setting system notes' do
it 'returns updated discussion filter' do
@@ -50,4 +51,26 @@ describe UserPreference do
end
end
end
+
+ describe 'sort_by preferences' do
+ shared_examples_for 'a sort_by preference' do
+ it 'allows nil sort fields' do
+ user_preference.update(attribute => nil)
+
+ expect(user_preference).to be_valid
+ end
+ end
+
+ context 'merge_requests_sort attribute' do
+ let(:attribute) { :merge_requests_sort }
+
+ it_behaves_like 'a sort_by preference'
+ end
+
+ context 'issues_sort attribute' do
+ let(:attribute) { :issues_sort }
+
+ it_behaves_like 'a sort_by preference'
+ end
+ end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 33842e74b92..85b157a9435 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -925,6 +925,21 @@ describe User do
expect(user.manageable_groups).to contain_exactly(group, subgroup)
end
end
+
+ describe '#manageable_groups_with_routes' do
+ it 'eager loads routes from manageable groups' do
+ control_count =
+ ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ user.manageable_groups_with_routes.map(&:route)
+ end.count
+
+ create(:group, parent: subgroup)
+
+ expect do
+ user.manageable_groups_with_routes.map(&:route)
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
end
end
@@ -961,43 +976,43 @@ describe User do
end
end
- describe '.filter' do
+ describe '.filter_items' do
let(:user) { double }
it 'filters by active users by default' do
expect(described_class).to receive(:active).and_return([user])
- expect(described_class.filter(nil)).to include user
+ expect(described_class.filter_items(nil)).to include user
end
it 'filters by admins' do
expect(described_class).to receive(:admins).and_return([user])
- expect(described_class.filter('admins')).to include user
+ expect(described_class.filter_items('admins')).to include user
end
it 'filters by blocked' do
expect(described_class).to receive(:blocked).and_return([user])
- expect(described_class.filter('blocked')).to include user
+ expect(described_class.filter_items('blocked')).to include user
end
it 'filters by two_factor_disabled' do
expect(described_class).to receive(:without_two_factor).and_return([user])
- expect(described_class.filter('two_factor_disabled')).to include user
+ expect(described_class.filter_items('two_factor_disabled')).to include user
end
it 'filters by two_factor_enabled' do
expect(described_class).to receive(:with_two_factor).and_return([user])
- expect(described_class.filter('two_factor_enabled')).to include user
+ expect(described_class.filter_items('two_factor_enabled')).to include user
end
it 'filters by wop' do
expect(described_class).to receive(:without_projects).and_return([user])
- expect(described_class.filter('wop')).to include user
+ expect(described_class.filter_items('wop')).to include user
end
end
@@ -1997,6 +2012,33 @@ describe User do
expect(subject).to include(accessible)
expect(subject).not_to include(other)
end
+
+ context 'with min_access_level' do
+ let!(:user) { create(:user) }
+ let!(:project) { create(:project, :private, namespace: user.namespace) }
+
+ before do
+ project.add_developer(user)
+ end
+
+ subject { Project.where("EXISTS (?)", user.authorizations_for_projects(min_access_level: min_access_level)) }
+
+ context 'when developer access' do
+ let(:min_access_level) { Gitlab::Access::DEVELOPER }
+
+ it 'includes projects a user has access to' do
+ expect(subject).to include(project)
+ end
+ end
+
+ context 'when owner access' do
+ let(:min_access_level) { Gitlab::Access::OWNER }
+
+ it 'does not include projects with higher access level' do
+ expect(subject).not_to include(project)
+ end
+ end
+ end
end
describe '#authorized_projects', :delete do
diff --git a/spec/policies/board_policy_spec.rb b/spec/policies/board_policy_spec.rb
new file mode 100644
index 00000000000..4b76d65ef69
--- /dev/null
+++ b/spec/policies/board_policy_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe BoardPolicy do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :private) }
+ let(:group) { create(:group, :private) }
+ let(:group_board) { create(:board, group: group) }
+ let(:project_board) { create(:board, project: project) }
+
+ let(:board_permissions) do
+ [
+ :read_parent,
+ :read_milestone,
+ :read_issue
+ ]
+ end
+
+ def expect_allowed(*permissions)
+ permissions.each { |p| is_expected.to be_allowed(p) }
+ end
+
+ def expect_disallowed(*permissions)
+ permissions.each { |p| is_expected.not_to be_allowed(p) }
+ end
+
+ context 'group board' do
+ subject { described_class.new(user, group_board) }
+
+ context 'user has access' do
+ before do
+ group.add_developer(user)
+ end
+
+ it do
+ expect_allowed(*board_permissions)
+ end
+ end
+
+ context 'user does not have access' do
+ it do
+ expect_disallowed(*board_permissions)
+ end
+ end
+ end
+
+ context 'project board' do
+ subject { described_class.new(user, project_board) }
+
+ context 'user has access' do
+ before do
+ project.add_developer(user)
+ end
+
+ it do
+ expect_allowed(*board_permissions)
+ end
+ end
+
+ context 'user does not have access' do
+ it do
+ expect_disallowed(*board_permissions)
+ end
+ end
+ end
+end
diff --git a/spec/policies/ci/pipeline_policy_spec.rb b/spec/policies/ci/pipeline_policy_spec.rb
index 8022f61e67d..844d96017de 100644
--- a/spec/policies/ci/pipeline_policy_spec.rb
+++ b/spec/policies/ci/pipeline_policy_spec.rb
@@ -75,6 +75,14 @@ describe Ci::PipelinePolicy, :models do
end
end
+ context 'when user does not have access to internal CI' do
+ let(:project) { create(:project, :builds_disabled, :public) }
+
+ it 'disallows the user from reading the pipeline' do
+ expect(policy).to be_disallowed :read_pipeline
+ end
+ end
+
describe 'destroy_pipeline' do
let(:project) { create(:project, :public) }
diff --git a/spec/policies/commit_policy_spec.rb b/spec/policies/commit_policy_spec.rb
new file mode 100644
index 00000000000..41f6fb08426
--- /dev/null
+++ b/spec/policies/commit_policy_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe CommitPolicy do
+ describe '#rules' do
+ let(:user) { create(:user) }
+ let(:commit) { project.repository.head_commit }
+ let(:policy) { described_class.new(user, commit) }
+
+ context 'when project is public' do
+ let(:project) { create(:project, :public, :repository) }
+
+ it 'can read commit and create a note' do
+ expect(policy).to be_allowed(:read_commit)
+ end
+
+ context 'when repository access level is private' do
+ let(:project) { create(:project, :public, :repository, :repository_private) }
+
+ it 'can not read commit and create a note' do
+ expect(policy).to be_disallowed(:read_commit)
+ end
+
+ context 'when the user is a project member' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'can read commit and create a note' do
+ expect(policy).to be_allowed(:read_commit)
+ end
+ end
+ end
+ end
+
+ context 'when project is private' do
+ let(:project) { create(:project, :private, :repository) }
+
+ it 'can not read commit and create a note' do
+ expect(policy).to be_disallowed(:read_commit)
+ end
+
+ context 'when the user is a project member' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'can read commit and create a note' do
+ expect(policy).to be_allowed(:read_commit)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/policies/global_policy_spec.rb b/spec/policies/global_policy_spec.rb
index 30d68e7dc9d..12be3927e18 100644
--- a/spec/policies/global_policy_spec.rb
+++ b/spec/policies/global_policy_spec.rb
@@ -181,6 +181,18 @@ describe GlobalPolicy do
end
end
+ describe 'read instance metadata' do
+ context 'regular user' do
+ it { is_expected.to be_allowed(:read_instance_metadata) }
+ end
+
+ context 'anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.not_to be_allowed(:read_instance_metadata) }
+ end
+ end
+
describe 'read instance statistics' do
context 'regular user' do
it { is_expected.to be_allowed(:read_instance_statistics) }
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index baf21efa75c..0ad50c6f91f 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -25,7 +25,8 @@ describe GroupPolicy do
:read_cluster,
:create_cluster,
:update_cluster,
- :admin_cluster
+ :admin_cluster,
+ :add_cluster
]
end
@@ -73,6 +74,38 @@ describe GroupPolicy do
end
end
+ context 'with no user and public project' do
+ let(:project) { create(:project, :public) }
+ let(:user) { create(:user) }
+ let(:current_user) { nil }
+
+ before do
+ Projects::GroupLinks::CreateService.new(
+ project,
+ user,
+ link_group_access: ProjectGroupLink::DEVELOPER
+ ).execute(group)
+ end
+
+ it { expect_disallowed(:read_group) }
+ end
+
+ context 'with foreign user and public project' do
+ let(:project) { create(:project, :public) }
+ let(:user) { create(:user) }
+ let(:current_user) { create(:user) }
+
+ before do
+ Projects::GroupLinks::CreateService.new(
+ project,
+ user,
+ link_group_access: ProjectGroupLink::DEVELOPER
+ ).execute(group)
+ end
+
+ it { expect_disallowed(:read_group) }
+ end
+
context 'has projects' do
let(:current_user) { create(:user) }
let(:project) { create(:project, namespace: group) }
@@ -81,17 +114,13 @@ describe GroupPolicy do
project.add_developer(current_user)
end
- it do
- expect_allowed(:read_group, :read_label)
- end
+ it { expect_allowed(:read_label, :read_list) }
context 'in subgroups', :nested_groups do
let(:subgroup) { create(:group, :private, parent: group) }
let(:project) { create(:project, namespace: subgroup) }
- it do
- expect_allowed(:read_group, :read_label)
- end
+ it { expect_allowed(:read_label, :read_list) }
end
end
@@ -382,4 +411,14 @@ describe GroupPolicy do
it { expect_disallowed(:change_share_with_group_lock) }
end
end
+
+ it_behaves_like 'clusterable policies' do
+ let(:clusterable) { create(:group) }
+ let(:cluster) do
+ create(:cluster,
+ :provided_by_gcp,
+ :group,
+ groups: [clusterable])
+ end
+ end
end
diff --git a/spec/policies/issuable_policy_spec.rb b/spec/policies/issuable_policy_spec.rb
index d1bf98995e7..db3df760472 100644
--- a/spec/policies/issuable_policy_spec.rb
+++ b/spec/policies/issuable_policy_spec.rb
@@ -7,6 +7,33 @@ describe IssuablePolicy, models: true do
let(:policies) { described_class.new(user, issue) }
describe '#rules' do
+ context 'when user is author of issuable' do
+ let(:merge_request) { create(:merge_request, source_project: project, author: user) }
+ let(:policies) { described_class.new(user, merge_request) }
+
+ context 'when user is able to read project' do
+ it 'enables user to read and update issuables' do
+ expect(policies).to be_allowed(:read_issue, :update_issue, :reopen_issue, :read_merge_request, :update_merge_request)
+ end
+ end
+
+ context 'when project is private' do
+ let(:project) { create(:project, :private) }
+
+ context 'when user belongs to the projects team' do
+ it 'enables user to read and update issuables' do
+ project.add_maintainer(user)
+
+ expect(policies).to be_allowed(:read_issue, :update_issue, :reopen_issue, :read_merge_request, :update_merge_request)
+ end
+ end
+
+ it 'disallows user from reading and updating issuables from that project' do
+ expect(policies).to be_disallowed(:read_issue, :update_issue, :reopen_issue, :read_merge_request, :update_merge_request)
+ end
+ end
+ end
+
context 'when discussion is locked for the issuable' do
let(:issue) { create(:issue, project: project, discussion_locked: true) }
diff --git a/spec/policies/note_policy_spec.rb b/spec/policies/note_policy_spec.rb
index 7e25c53e77c..4be7a0266d1 100644
--- a/spec/policies/note_policy_spec.rb
+++ b/spec/policies/note_policy_spec.rb
@@ -1,33 +1,21 @@
require 'spec_helper'
-describe NotePolicy, mdoels: true do
+describe NotePolicy do
describe '#rules' do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
let(:issue) { create(:issue, project: project) }
-
- def policies(noteable = nil)
- return @policies if @policies
-
- noteable ||= issue
- note = if noteable.is_a?(Commit)
- create(:note_on_commit, commit_id: noteable.id, author: user, project: project)
- else
- create(:note, noteable: noteable, author: user, project: project)
- end
-
- @policies = described_class.new(user, note)
- end
+ let(:noteable) { issue }
+ let(:policy) { described_class.new(user, note) }
+ let(:note) { create(:note, noteable: noteable, author: user, project: project) }
shared_examples_for 'a discussion with a private noteable' do
- let(:noteable) { issue }
- let(:policy) { policies(noteable) }
-
context 'when the note author can no longer see the noteable' do
it 'can not edit nor read the note' do
expect(policy).to be_disallowed(:admin_note)
expect(policy).to be_disallowed(:resolve_note)
expect(policy).to be_disallowed(:read_note)
+ expect(policy).to be_disallowed(:award_emoji)
end
end
@@ -40,16 +28,26 @@ describe NotePolicy, mdoels: true do
expect(policy).to be_allowed(:admin_note)
expect(policy).to be_allowed(:resolve_note)
expect(policy).to be_allowed(:read_note)
+ expect(policy).to be_allowed(:award_emoji)
end
end
end
- context 'when the project is private' do
- let(:project) { create(:project, :private, :repository) }
+ context 'when the noteable is a commit' do
+ let(:commit) { project.repository.head_commit }
+ let(:note) { create(:note_on_commit, commit_id: commit.id, author: user, project: project) }
+
+ context 'when the project is private' do
+ let(:project) { create(:project, :private, :repository) }
+
+ it_behaves_like 'a discussion with a private noteable'
+ end
- context 'when the noteable is a commit' do
- it_behaves_like 'a discussion with a private noteable' do
- let(:noteable) { project.repository.head_commit }
+ context 'when the project is public' do
+ context 'when repository access level is private' do
+ let(:project) { create(:project, :public, :repository, :repository_private) }
+
+ it_behaves_like 'a discussion with a private noteable'
end
end
end
@@ -57,44 +55,44 @@ describe NotePolicy, mdoels: true do
context 'when the project is public' do
context 'when the note author is not a project member' do
it 'can edit a note' do
- expect(policies).to be_allowed(:admin_note)
- expect(policies).to be_allowed(:resolve_note)
- expect(policies).to be_allowed(:read_note)
+ expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:resolve_note)
+ expect(policy).to be_allowed(:read_note)
end
end
context 'when the noteable is a project snippet' do
- it 'can edit note' do
- policies = policies(create(:project_snippet, :public, project: project))
+ let(:noteable) { create(:project_snippet, :public, project: project) }
- expect(policies).to be_allowed(:admin_note)
- expect(policies).to be_allowed(:resolve_note)
- expect(policies).to be_allowed(:read_note)
+ it 'can edit note' do
+ expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:resolve_note)
+ expect(policy).to be_allowed(:read_note)
end
context 'when it is private' do
- it_behaves_like 'a discussion with a private noteable' do
- let(:noteable) { create(:project_snippet, :private, project: project) }
- end
+ let(:noteable) { create(:project_snippet, :private, project: project) }
+
+ it_behaves_like 'a discussion with a private noteable'
end
end
context 'when the noteable is a personal snippet' do
- it 'can edit note' do
- policies = policies(create(:personal_snippet, :public))
+ let(:noteable) { create(:personal_snippet, :public) }
- expect(policies).to be_allowed(:admin_note)
- expect(policies).to be_allowed(:resolve_note)
- expect(policies).to be_allowed(:read_note)
+ it 'can edit note' do
+ expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:resolve_note)
+ expect(policy).to be_allowed(:read_note)
end
context 'when it is private' do
- it 'can not edit nor read the note' do
- policies = policies(create(:personal_snippet, :private))
+ let(:noteable) { create(:personal_snippet, :private) }
- expect(policies).to be_disallowed(:admin_note)
- expect(policies).to be_disallowed(:resolve_note)
- expect(policies).to be_disallowed(:read_note)
+ it 'can not edit nor read the note' do
+ expect(policy).to be_disallowed(:admin_note)
+ expect(policy).to be_disallowed(:resolve_note)
+ expect(policy).to be_disallowed(:read_note)
end
end
end
@@ -118,20 +116,20 @@ describe NotePolicy, mdoels: true do
end
it 'can edit a note' do
- expect(policies).to be_allowed(:admin_note)
- expect(policies).to be_allowed(:resolve_note)
- expect(policies).to be_allowed(:read_note)
+ expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:resolve_note)
+ expect(policy).to be_allowed(:read_note)
end
end
context 'when the note author is not a project member' do
it 'can not edit a note' do
- expect(policies).to be_disallowed(:admin_note)
- expect(policies).to be_disallowed(:resolve_note)
+ expect(policy).to be_disallowed(:admin_note)
+ expect(policy).to be_disallowed(:resolve_note)
end
it 'can read a note' do
- expect(policies).to be_allowed(:read_note)
+ expect(policy).to be_allowed(:read_note)
end
end
end
diff --git a/spec/policies/personal_snippet_policy_spec.rb b/spec/policies/personal_snippet_policy_spec.rb
index 3809692b373..a38e0dbd797 100644
--- a/spec/policies/personal_snippet_policy_spec.rb
+++ b/spec/policies/personal_snippet_policy_spec.rb
@@ -14,6 +14,13 @@ describe PersonalSnippetPolicy do
]
end
+ let(:comment_permissions) do
+ [
+ :comment_personal_snippet,
+ :create_note
+ ]
+ end
+
def permissions(user)
described_class.new(user, snippet)
end
@@ -26,7 +33,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_disallowed(:comment_personal_snippet)
+ is_expected.to be_disallowed(*comment_permissions)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -37,7 +44,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(:comment_personal_snippet)
+ is_expected.to be_allowed(*comment_permissions)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -48,7 +55,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(:comment_personal_snippet)
+ is_expected.to be_allowed(*comment_permissions)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_allowed(*author_permissions)
end
@@ -63,7 +70,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
- is_expected.to be_disallowed(:comment_personal_snippet)
+ is_expected.to be_disallowed(*comment_permissions)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -74,7 +81,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(:comment_personal_snippet)
+ is_expected.to be_allowed(*comment_permissions)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -85,7 +92,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
- is_expected.to be_disallowed(:comment_personal_snippet)
+ is_expected.to be_disallowed(*comment_permissions)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -96,7 +103,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(:comment_personal_snippet)
+ is_expected.to be_allowed(*comment_permissions)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_allowed(*author_permissions)
end
@@ -111,7 +118,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
- is_expected.to be_disallowed(:comment_personal_snippet)
+ is_expected.to be_disallowed(*comment_permissions)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -122,6 +129,17 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
+ is_expected.to be_disallowed(*comment_permissions)
+ is_expected.to be_disallowed(:award_emoji)
+ is_expected.to be_disallowed(*author_permissions)
+ end
+ end
+
+ context 'admin user' do
+ subject { permissions(admin_user) }
+
+ it do
+ is_expected.to be_allowed(:read_personal_snippet)
is_expected.to be_disallowed(:comment_personal_snippet)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
@@ -133,7 +151,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
- is_expected.to be_disallowed(:comment_personal_snippet)
+ is_expected.to be_disallowed(*comment_permissions)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -144,7 +162,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(:comment_personal_snippet)
+ is_expected.to be_allowed(*comment_permissions)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_allowed(*author_permissions)
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 69468f9ad85..772d1fbee2b 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -12,10 +12,10 @@ describe ProjectPolicy do
let(:base_guest_permissions) do
%i[
read_project read_board read_list read_wiki read_issue
- read_project_for_iids read_issue_iid read_merge_request_iid read_label
+ read_project_for_iids read_issue_iid read_label
read_milestone read_project_snippet read_project_member read_note
create_project create_issue create_note upload_file create_merge_request_in
- award_emoji
+ award_emoji read_release
]
end
@@ -24,7 +24,7 @@ describe ProjectPolicy do
download_code fork_project create_project_snippet update_issue
admin_issue admin_label admin_list read_commit_status read_build
read_container_image read_pipeline read_environment read_deployment
- read_merge_request download_wiki_code
+ read_merge_request download_wiki_code read_sentry_issue
]
end
@@ -38,17 +38,17 @@ describe ProjectPolicy do
update_commit_status create_build update_build create_pipeline
update_pipeline create_merge_request_from create_wiki push_code
resolve_note create_container_image update_container_image
- create_environment create_deployment
+ create_environment create_deployment create_release update_release
]
end
let(:base_maintainer_permissions) do
%i[
push_to_delete_protected_branch update_project_snippet update_environment
- update_deployment admin_project_snippet
- admin_project_member admin_note admin_wiki admin_project
+ update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project
admin_commit_status admin_build admin_container_image
- admin_pipeline admin_environment admin_deployment
+ admin_pipeline admin_environment admin_deployment destroy_release add_cluster
+ daily_statistics
]
end
@@ -56,7 +56,7 @@ describe ProjectPolicy do
%i[
download_code fork_project read_commit_status read_pipeline
read_container_image build_download_code build_read_container_image
- download_wiki_code
+ download_wiki_code read_release
]
end
@@ -69,7 +69,7 @@ describe ProjectPolicy do
end
# Used in EE specs
- let(:additional_guest_permissions) { [] }
+ let(:additional_guest_permissions) { [] }
let(:additional_reporter_permissions) { [] }
let(:additional_maintainer_permissions) { [] }
@@ -102,15 +102,27 @@ describe ProjectPolicy do
expect(Ability).not_to be_allowed(user, :read_issue, project)
end
- context 'when the feature is disabled' do
+ context 'wiki feature' do
+ let(:permissions) { %i(read_wiki create_wiki update_wiki admin_wiki download_wiki_code) }
+
subject { described_class.new(owner, project) }
- before do
- project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED)
- end
+ context 'when the feature is disabled' do
+ before do
+ project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED)
+ end
+
+ it 'does not include the wiki permissions' do
+ expect_disallowed(*permissions)
+ end
- it 'does not include the wiki permissions' do
- expect_disallowed :read_wiki, :create_wiki, :update_wiki, :admin_wiki, :download_wiki_code
+ context 'when there is an external wiki' do
+ it 'does not include the wiki permissions' do
+ allow(project).to receive(:has_external_wiki?).and_return(true)
+
+ expect_disallowed(*permissions)
+ end
+ end
end
end
@@ -118,22 +130,26 @@ describe ProjectPolicy do
subject { described_class.new(owner, project) }
context 'when the feature is disabled' do
- it 'does not include the issues permissions' do
+ before do
project.issues_enabled = false
project.save!
+ end
+ it 'does not include the issues permissions' do
expect_disallowed :read_issue, :read_issue_iid, :create_issue, :update_issue, :admin_issue
end
- end
- context 'when the feature is disabled and external tracker configured' do
- it 'does not include the issues permissions' do
- create(:jira_service, project: project)
+ it 'disables boards and lists permissions' do
+ expect_disallowed :read_board, :create_board, :update_board, :admin_board
+ expect_disallowed :read_list, :create_list, :update_list, :admin_list
+ end
- project.issues_enabled = false
- project.save!
+ context 'when external tracker configured' do
+ it 'does not include the issues permissions' do
+ create(:jira_service, project: project)
- expect_disallowed :read_issue, :read_issue_iid, :create_issue, :update_issue, :admin_issue
+ expect_disallowed :read_issue, :read_issue_iid, :create_issue, :update_issue, :admin_issue
+ end
end
end
end
@@ -152,22 +168,52 @@ describe ProjectPolicy do
end
end
+ context 'for a guest in a private project' do
+ let(:project) { create(:project, :private) }
+ subject { described_class.new(guest, project) }
+
+ it 'disallows the guest from reading the merge request and merge request iid' do
+ expect_disallowed(:read_merge_request)
+ expect_disallowed(:read_merge_request_iid)
+ end
+ end
+
context 'builds feature' do
- subject { described_class.new(owner, project) }
+ context 'when builds are disabled' do
+ subject { described_class.new(owner, project) }
- it 'disallows all permissions when the feature is disabled' do
- project.project_feature.update(builds_access_level: ProjectFeature::DISABLED)
+ before do
+ project.project_feature.update(builds_access_level: ProjectFeature::DISABLED)
+ end
- builds_permissions = [
- :create_pipeline, :update_pipeline, :admin_pipeline, :destroy_pipeline,
- :create_build, :read_build, :update_build, :admin_build, :destroy_build,
- :create_pipeline_schedule, :read_pipeline_schedule, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule,
- :create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment,
- :create_cluster, :read_cluster, :update_cluster, :admin_cluster,
- :create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment
- ]
+ it 'disallows all permissions except pipeline when the feature is disabled' do
+ builds_permissions = [
+ :create_build, :read_build, :update_build, :admin_build, :destroy_build,
+ :create_pipeline_schedule, :read_pipeline_schedule, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule,
+ :create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment,
+ :create_cluster, :read_cluster, :update_cluster, :admin_cluster, :destroy_cluster,
+ :create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment
+ ]
- expect_disallowed(*builds_permissions)
+ expect_disallowed(*builds_permissions)
+ end
+ end
+
+ context 'when builds are disabled only for some users' do
+ subject { described_class.new(guest, project) }
+
+ before do
+ project.project_feature.update(builds_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'disallows pipeline and commit_status permissions' do
+ builds_permissions = [
+ :create_pipeline, :update_pipeline, :admin_pipeline, :destroy_pipeline,
+ :create_commit_status, :update_commit_status, :admin_commit_status, :destroy_commit_status
+ ]
+
+ expect_disallowed(*builds_permissions)
+ end
end
end
@@ -183,7 +229,8 @@ describe ProjectPolicy do
:create_pipeline_schedule, :read_pipeline_schedule, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule,
:create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment,
:create_cluster, :read_cluster, :update_cluster, :admin_cluster,
- :create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment
+ :create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment,
+ :destroy_release
]
expect_disallowed(*repository_permissions)
@@ -235,7 +282,7 @@ describe ProjectPolicy do
let(:group) { create(:group, :public) }
let(:project) { create(:project, :public, namespace: group) }
let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji] }
- let(:anonymous_permissions) { guest_permissions - user_permissions }
+ let(:anonymous_permissions) { guest_permissions - user_permissions }
subject { described_class.new(nil, project) }
@@ -465,4 +512,14 @@ describe ProjectPolicy do
expect_disallowed(*maintainer_abilities)
end
end
+
+ it_behaves_like 'clusterable policies' do
+ let(:clusterable) { create(:project, :repository) }
+ let(:cluster) do
+ create(:cluster,
+ :provided_by_gcp,
+ :project,
+ projects: [clusterable])
+ end
+ end
end
diff --git a/spec/policies/project_snippet_policy_spec.rb b/spec/policies/project_snippet_policy_spec.rb
index 4d32e06b553..d6329e84579 100644
--- a/spec/policies/project_snippet_policy_spec.rb
+++ b/spec/policies/project_snippet_policy_spec.rb
@@ -41,7 +41,7 @@ describe ProjectSnippetPolicy do
subject { abilities(regular_user, :public) }
it do
- expect_allowed(:read_project_snippet)
+ expect_allowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
end
@@ -50,7 +50,7 @@ describe ProjectSnippetPolicy do
subject { abilities(external_user, :public) }
it do
- expect_allowed(:read_project_snippet)
+ expect_allowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
end
@@ -70,7 +70,7 @@ describe ProjectSnippetPolicy do
subject { abilities(regular_user, :internal) }
it do
- expect_allowed(:read_project_snippet)
+ expect_allowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
end
@@ -79,7 +79,7 @@ describe ProjectSnippetPolicy do
subject { abilities(external_user, :internal) }
it do
- expect_disallowed(:read_project_snippet)
+ expect_disallowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
end
@@ -92,7 +92,7 @@ describe ProjectSnippetPolicy do
end
it do
- expect_allowed(:read_project_snippet)
+ expect_allowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
end
@@ -112,7 +112,7 @@ describe ProjectSnippetPolicy do
subject { abilities(regular_user, :private) }
it do
- expect_disallowed(:read_project_snippet)
+ expect_disallowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
end
@@ -123,7 +123,7 @@ describe ProjectSnippetPolicy do
subject { described_class.new(regular_user, snippet) }
it do
- expect_allowed(:read_project_snippet)
+ expect_allowed(:read_project_snippet, :create_note)
expect_allowed(*author_permissions)
end
end
@@ -136,7 +136,7 @@ describe ProjectSnippetPolicy do
end
it do
- expect_allowed(:read_project_snippet)
+ expect_allowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
end
@@ -149,7 +149,7 @@ describe ProjectSnippetPolicy do
end
it do
- expect_allowed(:read_project_snippet)
+ expect_allowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
end
@@ -158,7 +158,7 @@ describe ProjectSnippetPolicy do
subject { abilities(create(:admin), :private) }
it do
- expect_allowed(:read_project_snippet)
+ expect_allowed(:read_project_snippet, :create_note)
expect_allowed(*author_permissions)
end
end
diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb
index e85e7a41017..bb1db9a3d51 100644
--- a/spec/presenters/blob_presenter_spec.rb
+++ b/spec/presenters/blob_presenter_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
describe BlobPresenter, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:git_blob) do
Gitlab::Git::Blob.find(
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index 170e0ac5717..f50bcf54b46 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -98,4 +98,72 @@ describe Ci::BuildRunnerPresenter do
end
end
end
+
+ describe '#ref_type' do
+ subject { presenter.ref_type }
+
+ let(:build) { create(:ci_build, tag: tag) }
+ let(:tag) { true }
+
+ it 'returns the correct ref type' do
+ is_expected.to eq('tag')
+ end
+
+ context 'when tag is false' do
+ let(:tag) { false }
+
+ it 'returns the correct ref type' do
+ is_expected.to eq('branch')
+ end
+ end
+ end
+
+ describe '#git_depth' do
+ subject { presenter.git_depth }
+
+ let(:build) { create(:ci_build) }
+
+ it 'returns the correct git depth' do
+ is_expected.to eq(0)
+ end
+
+ context 'when GIT_DEPTH variable is specified' do
+ before do
+ create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: build.pipeline)
+ end
+
+ it 'returns the correct git depth' do
+ is_expected.to eq(1)
+ end
+ end
+ end
+
+ describe '#refspecs' do
+ subject { presenter.refspecs }
+
+ let(:build) { create(:ci_build) }
+
+ it 'returns the correct refspecs' do
+ is_expected.to contain_exactly('+refs/tags/*:refs/tags/*',
+ '+refs/heads/*:refs/remotes/origin/*')
+ end
+
+ context 'when GIT_DEPTH variable is specified' do
+ before do
+ create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: build.pipeline)
+ end
+
+ it 'returns the correct refspecs' do
+ is_expected.to contain_exactly("+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
+ end
+
+ context 'when ref is tag' do
+ let(:build) { create(:ci_build, :tag) }
+
+ it 'returns the correct refspecs' do
+ is_expected.to contain_exactly("+refs/tags/#{build.ref}:refs/tags/#{build.ref}")
+ end
+ end
+ end
+ end
end
diff --git a/spec/presenters/ci/trigger_presenter_spec.rb b/spec/presenters/ci/trigger_presenter_spec.rb
new file mode 100644
index 00000000000..231b539c188
--- /dev/null
+++ b/spec/presenters/ci/trigger_presenter_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe Ci::TriggerPresenter do
+ set(:user) { create(:user) }
+ set(:project) { create(:project) }
+
+ set(:trigger) do
+ create(:ci_trigger, token: '123456789abcd', project: project)
+ end
+
+ subject do
+ described_class.new(trigger, current_user: user)
+ end
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when user is not a trigger owner' do
+ describe '#token' do
+ it 'exposes only short token' do
+ expect(subject.token).not_to eq trigger.token
+ expect(subject.token).to eq '1234'
+ end
+ end
+
+ describe '#has_token_exposed?' do
+ it 'does not have token exposed' do
+ expect(subject).not_to have_token_exposed
+ end
+ end
+ end
+
+ context 'when user is a trigger owner and builds admin' do
+ before do
+ trigger.update(owner: user)
+ end
+
+ describe '#token' do
+ it 'exposes full token' do
+ expect(subject.token).to eq trigger.token
+ end
+ end
+
+ describe '#has_token_exposed?' do
+ it 'has token exposed' do
+ expect(subject).to have_token_exposed
+ end
+ end
+ end
+end
diff --git a/spec/presenters/clusterable_presenter_spec.rb b/spec/presenters/clusterable_presenter_spec.rb
index 4f4ae5e07c5..05afe5347d1 100644
--- a/spec/presenters/clusterable_presenter_spec.rb
+++ b/spec/presenters/clusterable_presenter_spec.rb
@@ -14,4 +14,68 @@ describe ClusterablePresenter do
expect(subject).to be_kind_of(ProjectClusterablePresenter)
end
end
+
+ shared_examples 'appropriate member permissions' do
+ context 'with a developer' do
+ before do
+ clusterable.add_developer(user)
+ end
+
+ it { is_expected.to be_falsy }
+ end
+
+ context 'with a maintainer' do
+ before do
+ clusterable.add_maintainer(user)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe '#can_create_cluster?' do
+ let(:user) { create(:user) }
+
+ subject { described_class.new(clusterable).can_create_cluster? }
+
+ before do
+ allow(clusterable).to receive(:current_user).and_return(user)
+ end
+
+ context 'when clusterable is a group' do
+ let(:clusterable) { create(:group) }
+
+ it_behaves_like 'appropriate member permissions'
+ end
+
+ context 'when clusterable is a project' do
+ let(:clusterable) { create(:project, :repository) }
+
+ it_behaves_like 'appropriate member permissions'
+ end
+ end
+
+ describe '#can_add_cluster?' do
+ let(:user) { create(:user) }
+
+ subject { described_class.new(clusterable).can_add_cluster? }
+
+ before do
+ clusterable.add_maintainer(user)
+
+ allow(clusterable).to receive(:current_user).and_return(user)
+ end
+
+ context 'when clusterable is a group' do
+ let(:clusterable) { create(:group) }
+
+ it_behaves_like 'appropriate member permissions'
+ end
+
+ context 'when clusterable is a project' do
+ let(:clusterable) { create(:project, :repository) }
+
+ it_behaves_like 'appropriate member permissions'
+ end
+ end
end
diff --git a/spec/presenters/commit_presenter_spec.rb b/spec/presenters/commit_presenter_spec.rb
new file mode 100644
index 00000000000..4a0d3a28c32
--- /dev/null
+++ b/spec/presenters/commit_presenter_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe CommitPresenter do
+ let(:project) { create(:project, :repository) }
+ let(:commit) { project.commit }
+ let(:user) { create(:user) }
+ let(:presenter) { described_class.new(commit, current_user: user) }
+
+ describe '#status_for' do
+ subject { presenter.status_for('ref') }
+
+ context 'when user can read_commit_status' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :read_commit_status, project).and_return(true)
+ end
+
+ it 'returns commit status for ref' do
+ expect(commit).to receive(:status).with('ref').and_return('test')
+
+ expect(subject).to eq('test')
+ end
+ end
+
+ context 'when user can not read_commit_status' do
+ it 'is false' do
+ is_expected.to eq(false)
+ end
+ end
+ end
+
+ describe '#any_pipelines?' do
+ subject { presenter.any_pipelines? }
+
+ context 'when user can read pipeline' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :read_pipeline, project).and_return(true)
+ end
+
+ it 'returns if there are any pipelines for commit' do
+ expect(commit).to receive_message_chain(:pipelines, :any?).and_return(true)
+
+ expect(subject).to eq(true)
+ end
+ end
+
+ context 'when user can not read pipeline' do
+ it 'is false' do
+ is_expected.to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index bafcddebbb7..02cefcbc916 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -392,6 +392,29 @@ describe MergeRequestPresenter do
end
end
+ describe '#target_branch_path' do
+ subject do
+ described_class.new(resource, current_user: user).target_branch_path
+ end
+
+ context 'when target branch exists' do
+ it 'returns path' do
+ allow(resource).to receive(:target_branch_exists?) { true }
+
+ is_expected
+ .to eq("/#{resource.source_project.full_path}/branches/#{resource.target_branch}")
+ end
+ end
+
+ context 'when target branch does not exist' do
+ it 'returns nil' do
+ allow(resource).to receive(:target_branch_exists?) { false }
+
+ is_expected.to be_nil
+ end
+ end
+ end
+
describe '#source_branch_with_namespace_link' do
subject do
described_class.new(resource, current_user: user).source_branch_with_namespace_link
diff --git a/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb b/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb
index 2cc0076d695..001545bb5df 100644
--- a/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb
+++ b/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Projects::Settings::DeployKeysPresenter do
let(:project) { create(:project) }
let(:user) { create(:user) }
- let(:deploy_key) { create(:deploy_key, public: true) }
+ let(:deploy_key) { create(:deploy_key, public: true) }
let!(:deploy_keys_project) do
create(:deploy_keys_project, project: project, deploy_key: deploy_key)
diff --git a/spec/requests/api/avatar_spec.rb b/spec/requests/api/avatar_spec.rb
index 17e66725dc9..9bc49bd5982 100644
--- a/spec/requests/api/avatar_spec.rb
+++ b/spec/requests/api/avatar_spec.rb
@@ -65,7 +65,7 @@ describe API::Avatar do
expect(GravatarService).to receive(:new).and_return(gravatar_service)
expect(gravatar_service).to(
receive(:execute)
- .with('private@example.com', nil, 2, { username: nil })
+ .with('private@example.com', nil, 2, { username: nil })
.and_return('https://gravatar'))
end
diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb
index 22f6fcdc922..6c67d84b59b 100644
--- a/spec/requests/api/award_emoji_spec.rb
+++ b/spec/requests/api/award_emoji_spec.rb
@@ -7,7 +7,7 @@ describe API::AwardEmoji do
set(:award_emoji) { create(:award_emoji, awardable: issue, user: user) }
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request, user: user) }
- set(:note) { create(:note, project: project, noteable: issue) }
+ set(:note) { create(:note, project: project, noteable: issue) }
before do
project.add_maintainer(user)
@@ -144,7 +144,7 @@ describe API::AwardEmoji do
end
describe "POST /projects/:id/awardable/:awardable_id/award_emoji" do
- let(:issue2) { create(:issue, project: project, author: user) }
+ let(:issue2) { create(:issue, project: project, author: user) }
context "on an issue" do
it "creates a new award emoji" do
diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb
index ab4f42cad47..de79e8c4c5c 100644
--- a/spec/requests/api/boards_spec.rb
+++ b/spec/requests/api/boards_spec.rb
@@ -31,7 +31,7 @@ describe API::Boards do
set(:board_label) { create(:label, project: board_parent) }
set(:board) { create(:board, project: board_parent, lists: [dev_list, test_list]) }
- it_behaves_like 'group and project boards', "/projects/:id/boards"
+ it_behaves_like 'group and project boards', "/projects/:id/boards"
describe "POST /projects/:id/boards/lists" do
let(:url) { "/projects/#{board_parent.id}/boards/#{board.id}/lists" }
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 93c411476bb..b38cd66986f 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -20,6 +20,12 @@ describe API::Branches do
let(:route) { "/projects/#{project_id}/repository/branches" }
shared_examples_for 'repository branches' do
+ RSpec::Matchers.define :has_merged_branch_names_count do |expected|
+ match do |actual|
+ actual[:merged_branch_names].count == expected
+ end
+ end
+
it 'returns the repository branches' do
get api(route, current_user), params: { per_page: 100 }
@@ -30,6 +36,12 @@ describe API::Branches do
expect(branch_names).to match_array(project.repository.branch_names)
end
+ it 'determines only a limited number of merged branch names' do
+ expect(API::Entities::Branch).to receive(:represent).with(anything, has_merged_branch_names_count(2))
+
+ get api(route, current_user), params: { per_page: 2 }
+ end
+
context 'when repository is disabled' do
include_context 'disabled repository'
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 6b9bc6eda6a..a132b85b878 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -237,7 +237,7 @@ describe API::Commits do
end
describe 'create' do
- let(:message) { 'Created file' }
+ let(:message) { 'Created a new file with a very very looooooooooooooooooooooooooooooooooooooooooooooong commit message' }
let(:invalid_c_params) do
{
branch: 'master',
@@ -1430,8 +1430,8 @@ describe API::Commits do
end
describe 'GET /projects/:id/repository/commits/:sha/merge_requests' do
- let!(:project) { create(:project, :repository, :private) }
- let!(:merged_mr) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'feature') }
+ let(:project) { create(:project, :repository, :private) }
+ let(:merged_mr) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'feature') }
let(:commit) { merged_mr.merge_request_diff.commits.last }
it 'returns the correct merge request' do
@@ -1456,5 +1456,54 @@ describe API::Commits do
expect(response).to have_gitlab_http_status(404)
end
+
+ context 'public project' do
+ let(:project) { create(:project, :repository, :public, :merge_requests_private) }
+ let(:non_member) { create(:user) }
+
+ it 'responds 403 when only members are allowed to read merge requests' do
+ get api("/projects/#{project.id}/repository/commits/#{commit.id}/merge_requests", non_member)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/repository/commits/:sha/signature' do
+ let!(:project) { create(:project, :repository, :public) }
+ let(:project_id) { project.id }
+ let(:commit_id) { project.repository.commit.id }
+ let(:route) { "/projects/#{project_id}/repository/commits/#{commit_id}/signature" }
+
+ context 'when commit does not exist' do
+ let(:commit_id) { 'unknown' }
+
+ it_behaves_like '404 response' do
+ let(:request) { get api(route, current_user) }
+ let(:message) { '404 Commit Not Found' }
+ end
+ end
+
+ context 'unsigned commit' do
+ it_behaves_like '404 response' do
+ let(:request) { get api(route, current_user) }
+ let(:message) { '404 GPG Signature Not Found'}
+ end
+ end
+
+ context 'signed commit' do
+ let(:commit) { project.repository.commit(GpgHelpers::SIGNED_COMMIT_SHA) }
+ let(:commit_id) { commit.id }
+
+ it 'returns correct JSON' do
+ get api(route, current_user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['gpg_key_id']).to eq(commit.signature.gpg_key_id)
+ expect(json_response['gpg_key_subkey_id']).to eq(commit.signature.gpg_key_subkey_id)
+ expect(json_response['gpg_key_primary_keyid']).to eq(commit.signature.gpg_key_primary_keyid)
+ expect(json_response['verification_status']).to eq(commit.signature.verification_status)
+ end
+ end
end
end
diff --git a/spec/requests/api/container_registry_spec.rb b/spec/requests/api/container_registry_spec.rb
new file mode 100644
index 00000000000..ea035a8be4a
--- /dev/null
+++ b/spec/requests/api/container_registry_spec.rb
@@ -0,0 +1,224 @@
+require 'spec_helper'
+
+describe API::ContainerRegistry do
+ set(:project) { create(:project, :private) }
+ set(:maintainer) { create(:user) }
+ set(:developer) { create(:user) }
+ set(:reporter) { create(:user) }
+ set(:guest) { create(:user) }
+
+ let(:root_repository) { create(:container_repository, :root, project: project) }
+ let(:test_repository) { create(:container_repository, project: project) }
+
+ let(:api_user) { maintainer }
+
+ before do
+ project.add_maintainer(maintainer)
+ project.add_developer(developer)
+ project.add_reporter(reporter)
+ project.add_guest(guest)
+
+ stub_feature_flags(container_registry_api: true)
+ stub_container_registry_config(enabled: true)
+
+ root_repository
+ test_repository
+ end
+
+ shared_examples 'being disallowed' do |param|
+ context "for #{param}" do
+ let(:api_user) { public_send(param) }
+
+ it 'returns access denied' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context "for anonymous" do
+ let(:api_user) { nil }
+
+ it 'returns not found' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/registry/repositories' do
+ subject { get api("/projects/#{project.id}/registry/repositories", api_user) }
+
+ it_behaves_like 'being disallowed', :guest
+
+ context 'for reporter' do
+ let(:api_user) { reporter }
+
+ it 'returns a list of repositories' do
+ subject
+
+ expect(json_response.length).to eq(2)
+ expect(json_response.map { |repository| repository['id'] }).to contain_exactly(
+ root_repository.id, test_repository.id)
+ end
+
+ it 'returns a matching schema' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('registry/repositories')
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/registry/repositories/:repository_id' do
+ subject { delete api("/projects/#{project.id}/registry/repositories/#{root_repository.id}", api_user) }
+
+ it_behaves_like 'being disallowed', :developer
+
+ context 'for maintainer' do
+ let(:api_user) { maintainer }
+
+ it 'schedules removal of repository' do
+ expect(DeleteContainerRepositoryWorker).to receive(:perform_async)
+ .with(maintainer.id, root_repository.id)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:accepted)
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/registry/repositories/:repository_id/tags' do
+ subject { get api("/projects/#{project.id}/registry/repositories/#{root_repository.id}/tags", api_user) }
+
+ it_behaves_like 'being disallowed', :guest
+
+ context 'for reporter' do
+ let(:api_user) { reporter }
+
+ before do
+ stub_container_registry_tags(repository: root_repository.path, tags: %w(rootA latest))
+ end
+
+ it 'returns a list of tags' do
+ subject
+
+ expect(json_response.length).to eq(2)
+ expect(json_response.map { |repository| repository['name'] }).to eq %w(latest rootA)
+ end
+
+ it 'returns a matching schema' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('registry/tags')
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/registry/repositories/:repository_id/tags' do
+ subject { delete api("/projects/#{project.id}/registry/repositories/#{root_repository.id}/tags", api_user), params: params }
+
+ it_behaves_like 'being disallowed', :developer do
+ let(:params) do
+ { name_regex: 'v10.*' }
+ end
+ end
+
+ context 'for maintainer' do
+ let(:api_user) { maintainer }
+
+ context 'without required parameters' do
+ let(:params) { }
+
+ it 'returns bad request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'passes all declared parameters' do
+ let(:params) do
+ { name_regex: 'v10.*',
+ keep_n: 100,
+ older_than: '1 day',
+ other: 'some value' }
+ end
+
+ let(:worker_params) do
+ { name_regex: 'v10.*',
+ keep_n: 100,
+ older_than: '1 day' }
+ end
+
+ it 'schedules cleanup of tags repository' do
+ expect(CleanupContainerRepositoryWorker).to receive(:perform_async)
+ .with(maintainer.id, root_repository.id, worker_params)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:accepted)
+ end
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/registry/repositories/:repository_id/tags/:tag_name' do
+ subject { get api("/projects/#{project.id}/registry/repositories/#{root_repository.id}/tags/rootA", api_user) }
+
+ it_behaves_like 'being disallowed', :guest
+
+ context 'for reporter' do
+ let(:api_user) { reporter }
+
+ before do
+ stub_container_registry_tags(repository: root_repository.path, tags: %w(rootA), with_manifest: true)
+ end
+
+ it 'returns a details of tag' do
+ subject
+
+ expect(json_response).to include(
+ 'name' => 'rootA',
+ 'digest' => 'sha256:4c8e63ca4cb663ce6c688cb06f1c372b088dac5b6d7ad7d49cd620d85cf72a15',
+ 'revision' => 'd7a513a663c1a6dcdba9ed832ca53c02ac2af0c333322cd6ca92936d1d9917ac',
+ 'total_size' => 2319870)
+ end
+
+ it 'returns a matching schema' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('registry/tag')
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name' do
+ subject { delete api("/projects/#{project.id}/registry/repositories/#{root_repository.id}/tags/rootA", api_user) }
+
+ it_behaves_like 'being disallowed', :developer
+
+ context 'for maintainer' do
+ let(:api_user) { maintainer }
+
+ before do
+ stub_container_registry_tags(repository: root_repository.path, tags: %w(rootA), with_manifest: true)
+ end
+
+ it 'properly removes tag' do
+ expect_any_instance_of(ContainerRegistry::Client)
+ .to receive(:delete_repository_tag).with(root_repository.path,
+ 'sha256:4c8e63ca4cb663ce6c688cb06f1c372b088dac5b6d7ad7d49cd620d85cf72a15')
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/discussions_spec.rb b/spec/requests/api/discussions_spec.rb
index ef34192f888..35c448d187d 100644
--- a/spec/requests/api/discussions_spec.rb
+++ b/spec/requests/api/discussions_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe API::Discussions do
let(:user) { create(:user) }
let!(:project) { create(:project, :public, :repository, namespace: user.namespace) }
- let(:private_user) { create(:user) }
+ let(:private_user) { create(:user) }
before do
project.add_developer(user)
diff --git a/spec/requests/api/features_spec.rb b/spec/requests/api/features_spec.rb
index 7d3eff7d32d..57a57e69a00 100644
--- a/spec/requests/api/features_spec.rb
+++ b/spec/requests/api/features_spec.rb
@@ -129,6 +129,74 @@ describe API::Features do
end
end
+ context 'when enabling for a project by path' do
+ context 'when the project exists' do
+ let!(:project) { create(:project) }
+
+ it 'sets the feature gate' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', project: project.full_path }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).to eq(
+ 'name' => 'my_feature',
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'actors', 'value' => ["Project:#{project.id}"] }
+ ])
+ end
+ end
+
+ context 'when the project does not exist' do
+ it 'sets no new values' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', project: 'mep/to/the/mep/mep' }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).to eq(
+ "name" => "my_feature",
+ "state" => "off",
+ "gates" => [
+ { "key" => "boolean", "value" => false }
+ ]
+ )
+ end
+ end
+ end
+
+ context 'when enabling for a group by path' do
+ context 'when the group exists' do
+ it 'sets the feature gate' do
+ group = create(:group)
+
+ post api("/features/#{feature_name}", admin), params: { value: 'true', group: group.full_path }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).to eq(
+ 'name' => 'my_feature',
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'actors', 'value' => ["Group:#{group.id}"] }
+ ])
+ end
+ end
+
+ context 'when the group does not exist' do
+ it 'sets no new values and keeps the feature disabled' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', group: 'not/a/group' }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).to eq(
+ "name" => "my_feature",
+ "state" => "off",
+ "gates" => [
+ { "key" => "boolean", "value" => false }
+ ]
+ )
+ end
+ end
+ end
+
it 'creates a feature with the given percentage if passed an integer' do
post api("/features/#{feature_name}", admin), params: { value: '50' }
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index 0ba1f2d7a2b..1ad536258ba 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -183,14 +183,15 @@ describe API::Files do
get api(url, current_user), params: params
expect(response).to have_gitlab_http_status(200)
+ expect(headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
- it 'forces attachment content disposition' do
+ it 'sets inline content disposition by default' do
url = route(file_path) + "/raw"
get api(url, current_user), params: params
- expect(headers['Content-Disposition']).to match(/^attachment/)
+ expect(headers['Content-Disposition']).to eq(%q(inline; filename="popen.rb"; filename*=UTF-8''popen.rb))
end
context 'when mandatory params are not given' do
diff --git a/spec/requests/api/graphql/metadata_query_spec.rb b/spec/requests/api/graphql/metadata_query_spec.rb
new file mode 100644
index 00000000000..4c56c559cf9
--- /dev/null
+++ b/spec/requests/api/graphql/metadata_query_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'getting project information' do
+ include GraphqlHelpers
+
+ let(:query) { graphql_query_for('metadata', {}, all_graphql_fields_for('Metadata')) }
+
+ context 'logged in' do
+ it 'returns version and revision' do
+ post_graphql(query, current_user: create(:user))
+
+ expect(graphql_errors).to be_nil
+ expect(graphql_data).to eq(
+ 'metadata' => {
+ 'version' => Gitlab::VERSION,
+ 'revision' => Gitlab.revision
+ }
+ )
+ end
+ end
+
+ context 'anonymous user' do
+ it 'returns nothing' do
+ post_graphql(query, current_user: nil)
+
+ expect(graphql_errors).to be_nil
+ expect(graphql_data).to eq('metadata' => nil)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index 355336ad7e2..c2934430821 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -56,4 +56,38 @@ describe 'getting an issue list for a project' do
expect(issues_data).to eq []
end
end
+
+ context 'when there is a confidential issue' do
+ let!(:confidential_issue) do
+ create(:issue, :confidential, project: project)
+ end
+
+ context 'when the user cannot see confidential issues' do
+ it 'returns issues without confidential issues' do
+ post_graphql(query, current_user: current_user)
+
+ expect(issues_data.size).to eq(2)
+
+ issues_data.each do |issue|
+ expect(issue.dig('node', 'confidential')).to eq(false)
+ end
+ end
+ end
+
+ context 'when the user can see confidential issues' do
+ it 'returns issues with confidential issues' do
+ project.add_developer(current_user)
+
+ post_graphql(query, current_user: current_user)
+
+ expect(issues_data.size).to eq(3)
+
+ confidentials = issues_data.map do |issue|
+ issue.dig('node', 'confidential')
+ end
+
+ expect(confidentials).to eq([true, false, false])
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql_spec.rb b/spec/requests/api/graphql_spec.rb
new file mode 100644
index 00000000000..cca87c16f27
--- /dev/null
+++ b/spec/requests/api/graphql_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'GraphQL' do
+ include GraphqlHelpers
+
+ let(:query) { graphql_query_for('echo', 'text' => 'Hello world' ) }
+
+ context 'graphql is disabled by feature flag' do
+ before do
+ stub_feature_flags(graphql: false)
+ end
+
+ it 'does not generate a route for GraphQL' do
+ expect { post_graphql(query) }.to raise_error(ActionController::RoutingError)
+ end
+ end
+
+ context 'invalid variables' do
+ it 'returns an error' do
+ post_graphql(query, variables: "This is not JSON")
+
+ expect(response).to have_gitlab_http_status(422)
+ expect(json_response['errors'].first['message']).not_to be_nil
+ end
+ end
+
+ context 'authentication', :allow_forgery_protection do
+ let(:user) { create(:user) }
+
+ it 'allows access to public data without authentication' do
+ post_graphql(query)
+
+ expect(graphql_data['echo']).to eq('nil says: Hello world')
+ end
+
+ it 'does not authenticate a user with an invalid CSRF' do
+ login_as(user)
+
+ post_graphql(query, headers: { 'X-CSRF-Token' => 'invalid' })
+
+ expect(graphql_data['echo']).to eq('nil says: Hello world')
+ end
+
+ it 'authenticates a user with a valid session token' do
+ # Create a session to get a CSRF token from
+ login_as(user)
+ get('/')
+
+ post '/api/graphql', params: { query: query }, headers: { 'X-CSRF-Token' => response.session['_csrf_token'] }
+
+ expect(graphql_data['echo']).to eq("\"#{user.username}\" says: Hello world")
+ end
+
+ context 'token authentication' do
+ let(:token) { create(:personal_access_token) }
+
+ before do
+ stub_authentication_activity_metrics(debug: false)
+ end
+
+ it 'Authenticates users with a PAT' do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+ .and increment(:user_session_override_counter)
+ .and increment(:user_sessionless_authentication_counter)
+
+ post_graphql(query, headers: { 'PRIVATE-TOKEN' => token.token })
+
+ expect(graphql_data['echo']).to eq("\"#{token.user.username}\" says: Hello world")
+ end
+
+ context 'when the personal access token has no api scope' do
+ it 'does not log the user in' do
+ token.update(scopes: [:read_user])
+
+ post_graphql(query, headers: { 'PRIVATE-TOKEN' => token.token })
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(graphql_data['echo']).to eq('nil says: Hello world')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/group_labels_spec.rb b/spec/requests/api/group_labels_spec.rb
new file mode 100644
index 00000000000..3769f8b78e4
--- /dev/null
+++ b/spec/requests/api/group_labels_spec.rb
@@ -0,0 +1,258 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::GroupLabels do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let!(:group_member) { create(:group_member, group: group, user: user) }
+ let!(:label1) { create(:group_label, title: 'feature', group: group) }
+ let!(:label2) { create(:group_label, title: 'bug', group: group) }
+
+ describe 'GET :id/labels' do
+ it 'returns all available labels for the group' do
+ get api("/groups/#{group.id}/labels", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/group_labels')
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(2)
+ expect(json_response.map {|r| r['name'] }).to contain_exactly('feature', 'bug')
+ end
+ end
+
+ describe 'POST /groups/:id/labels' do
+ it 'returns created label when all params are given' do
+ post api("/groups/#{group.id}/labels", user),
+ params: {
+ name: 'Foo',
+ color: '#FFAABB',
+ description: 'test'
+ }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['name']).to eq('Foo')
+ expect(json_response['color']).to eq('#FFAABB')
+ expect(json_response['description']).to eq('test')
+ end
+
+ it 'returns created label when only required params are given' do
+ post api("/groups/#{group.id}/labels", user),
+ params: {
+ name: 'Foo & Bar',
+ color: '#FFAABB'
+ }
+
+ expect(response.status).to eq(201)
+ expect(json_response['name']).to eq('Foo & Bar')
+ expect(json_response['color']).to eq('#FFAABB')
+ expect(json_response['description']).to be_nil
+ end
+
+ it 'returns a 400 bad request if name not given' do
+ post api("/groups/#{group.id}/labels", user), params: { color: '#FFAABB' }
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns a 400 bad request if color is not given' do
+ post api("/groups/#{group.id}/labels", user), params: { name: 'Foobar' }
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns 409 if label already exists' do
+ post api("/groups/#{group.id}/labels", user),
+ params: {
+ name: label1.name,
+ color: '#FFAABB'
+ }
+
+ expect(response).to have_gitlab_http_status(409)
+ expect(json_response['message']).to eq('Label already exists')
+ end
+ end
+
+ describe 'DELETE /groups/:id/labels' do
+ it 'returns 204 for existing label' do
+ delete api("/groups/#{group.id}/labels", user), params: { name: label1.name }
+
+ expect(response).to have_gitlab_http_status(204)
+ end
+
+ it 'returns 404 for non existing label' do
+ delete api("/groups/#{group.id}/labels", user), params: { name: 'label2' }
+
+ expect(response).to have_gitlab_http_status(404)
+ expect(json_response['message']).to eq('404 Label Not Found')
+ end
+
+ it 'returns 400 for wrong parameters' do
+ delete api("/groups/#{group.id}/labels", user)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it "does not delete parent's group labels", :nested_groups do
+ subgroup = create(:group, parent: group)
+ subgroup_label = create(:group_label, title: 'feature', group: subgroup)
+
+ delete api("/groups/#{subgroup.id}/labels", user), params: { name: subgroup_label.name }
+
+ expect(response).to have_gitlab_http_status(204)
+ expect(subgroup.labels.size).to eq(0)
+ expect(group.labels).to include(label1)
+ end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/groups/#{group.id}/labels", user) }
+ let(:params) { { name: label1.name } }
+ end
+ end
+
+ describe 'PUT /groups/:id/labels' do
+ it 'returns 200 if name and colors and description are changed' do
+ put api("/groups/#{group.id}/labels", user),
+ params: {
+ name: label1.name,
+ new_name: 'New Label',
+ color: '#FFFFFF',
+ description: 'test'
+ }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['name']).to eq('New Label')
+ expect(json_response['color']).to eq('#FFFFFF')
+ expect(json_response['description']).to eq('test')
+ end
+
+ it "does not update parent's group label", :nested_groups do
+ subgroup = create(:group, parent: group)
+ subgroup_label = create(:group_label, title: 'feature', group: subgroup)
+
+ put api("/groups/#{subgroup.id}/labels", user),
+ params: {
+ name: subgroup_label.name,
+ new_name: 'New Label'
+ }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(subgroup.labels[0].name).to eq('New Label')
+ expect(label1.name).to eq('feature')
+ end
+
+ it 'returns 404 if label does not exist' do
+ put api("/groups/#{group.id}/labels", user),
+ params: {
+ name: 'label2',
+ new_name: 'label3'
+ }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 400 if no label name given' do
+ put api("/groups/#{group.id}/labels", user), params: { new_name: label1.name }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['error']).to eq('name is missing')
+ end
+
+ it 'returns 400 if no new parameters given' do
+ put api("/groups/#{group.id}/labels", user), params: { name: label1.name }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['error']).to eq('new_name, color, description are missing, '\
+ 'at least one parameter must be provided')
+ end
+ end
+
+ describe 'POST /groups/:id/labels/:label_id/subscribe' do
+ context 'when label_id is a label title' do
+ it 'subscribes to the label' do
+ post api("/groups/#{group.id}/labels/#{label1.title}/subscribe", user)
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['name']).to eq(label1.title)
+ expect(json_response['subscribed']).to be_truthy
+ end
+ end
+
+ context 'when label_id is a label ID' do
+ it 'subscribes to the label' do
+ post api("/groups/#{group.id}/labels/#{label1.id}/subscribe", user)
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['name']).to eq(label1.title)
+ expect(json_response['subscribed']).to be_truthy
+ end
+ end
+
+ context 'when user is already subscribed to label' do
+ before do
+ label1.subscribe(user)
+ end
+
+ it 'returns 304' do
+ post api("/groups/#{group.id}/labels/#{label1.id}/subscribe", user)
+
+ expect(response).to have_gitlab_http_status(304)
+ end
+ end
+
+ context 'when label ID is not found' do
+ it 'returns 404 error' do
+ post api("/groups/#{group.id}/labels/1234/subscribe", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
+ describe 'POST /groups/:id/labels/:label_id/unsubscribe' do
+ before do
+ label1.subscribe(user)
+ end
+
+ context 'when label_id is a label title' do
+ it 'unsubscribes from the label' do
+ post api("/groups/#{group.id}/labels/#{label1.title}/unsubscribe", user)
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['name']).to eq(label1.title)
+ expect(json_response['subscribed']).to be_falsey
+ end
+ end
+
+ context 'when label_id is a label ID' do
+ it 'unsubscribes from the label' do
+ post api("/groups/#{group.id}/labels/#{label1.id}/unsubscribe", user)
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['name']).to eq(label1.title)
+ expect(json_response['subscribed']).to be_falsey
+ end
+ end
+
+ context 'when user is already unsubscribed from label' do
+ before do
+ label1.unsubscribe(user)
+ end
+
+ it 'returns 304' do
+ post api("/groups/#{group.id}/labels/#{label1.id}/unsubscribe", user)
+
+ expect(response).to have_gitlab_http_status(304)
+ end
+ end
+
+ context 'when label ID is not found' do
+ it 'returns 404 error' do
+ post api("/groups/#{group.id}/labels/1234/unsubscribe", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/group_milestones_spec.rb b/spec/requests/api/group_milestones_spec.rb
index 108721c6655..6980eb7f55d 100644
--- a/spec/requests/api/group_milestones_spec.rb
+++ b/spec/requests/api/group_milestones_spec.rb
@@ -8,7 +8,7 @@ describe API::GroupMilestones do
let!(:closed_milestone) { create(:closed_milestone, group: group, title: 'version1', description: 'closed milestone') }
let!(:milestone) { create(:milestone, group: group, title: 'version2', description: 'open milestone') }
- it_behaves_like 'group and project milestones', "/groups/:id/milestones" do
+ it_behaves_like 'group and project milestones', "/groups/:id/milestones" do
let(:route) { "/groups/#{group.id}/milestones" }
end
diff --git a/spec/requests/api/group_variables_spec.rb b/spec/requests/api/group_variables_spec.rb
index e52f4c70407..66b9aae4b58 100644
--- a/spec/requests/api/group_variables_spec.rb
+++ b/spec/requests/api/group_variables_spec.rb
@@ -87,12 +87,12 @@ describe API::GroupVariables do
it 'creates variable' do
expect do
- post api("/groups/#{group.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'VALUE_2', protected: true }
+ post api("/groups/#{group.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true }
end.to change {group.variables.count}.by(1)
expect(response).to have_gitlab_http_status(201)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
- expect(json_response['value']).to eq('VALUE_2')
+ expect(json_response['value']).to eq('PROTECTED_VALUE_2')
expect(json_response['protected']).to be_truthy
end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index c9dfc5c4a7e..7176bc23e34 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -382,6 +382,20 @@ describe API::Groups do
expect(response_project_ids(json_response, 'shared_projects'))
.to contain_exactly(projects[:public].id, projects[:internal].id)
end
+
+ it 'avoids N+1 queries' do
+ get api("/groups/#{group1.id}", admin)
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ get api("/groups/#{group1.id}", admin)
+ end.count
+
+ create(:project, namespace: group1)
+
+ expect do
+ get api("/groups/#{group1.id}", admin)
+ end.not_to exceed_query_limit(control_count)
+ end
end
context "when authenticated as admin" do
diff --git a/spec/requests/api/import_github_spec.rb b/spec/requests/api/import_github_spec.rb
new file mode 100644
index 00000000000..aceff9b4aa6
--- /dev/null
+++ b/spec/requests/api/import_github_spec.rb
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe API::ImportGithub do
+ include ApiHelpers
+
+ let(:token) { "asdasd12345" }
+ let(:provider) { :github }
+ let(:access_params) { { github_access_token: token } }
+
+ describe "POST /import/github" do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:provider_username) { user.username }
+ let(:provider_user) { OpenStruct.new(login: provider_username) }
+ let(:provider_repo) do
+ OpenStruct.new(
+ name: 'vim',
+ full_name: "#{provider_username}/vim",
+ owner: OpenStruct.new(login: provider_username)
+ )
+ end
+
+ before do
+ Grape::Endpoint.before_each do |endpoint|
+ allow(endpoint).to receive(:client).and_return(double('client', user: provider_user, repo: provider_repo).as_null_object)
+ end
+ end
+
+ it 'returns 201 response when the project is imported successfully' do
+ allow(Gitlab::LegacyGithubImport::ProjectCreator)
+ .to receive(:new).with(provider_repo, provider_repo.name, user.namespace, user, access_params, type: provider)
+ .and_return(double(execute: project))
+
+ post api("/import/github", user), params: {
+ target_namespace: user.namespace_path,
+ personal_access_token: token,
+ repo_id: 1234
+ }
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).to be_a Hash
+ expect(json_response['name']).to eq(project.name)
+ end
+
+ it 'returns 422 response when user can not create projects in the chosen namespace' do
+ other_namespace = create(:group, name: 'other_namespace')
+
+ post api("/import/github", user), params: {
+ target_namespace: other_namespace.name,
+ personal_access_token: token,
+ repo_id: 1234
+ }
+
+ expect(response).to have_gitlab_http_status(422)
+ end
+ end
+end
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index 589816b5d8f..cd85151ec1b 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -32,7 +32,7 @@ describe API::Internal do
context 'broadcast message exists' do
let!(:broadcast_message) { create(:broadcast_message, starts_at: 1.day.ago, ends_at: 1.day.from_now ) }
- it 'returns one broadcast message' do
+ it 'returns one broadcast message' do
get api('/internal/broadcast_message'), params: { secret_token: secret_token }
expect(response).to have_gitlab_http_status(200)
@@ -41,7 +41,7 @@ describe API::Internal do
end
context 'broadcast message does not exist' do
- it 'returns nothing' do
+ it 'returns nothing' do
get api('/internal/broadcast_message'), params: { secret_token: secret_token }
expect(response).to have_gitlab_http_status(200)
@@ -167,6 +167,7 @@ describe API::Internal do
expect(response).to have_gitlab_http_status(200)
expect(json_response['username']).to eq(user.username)
expect(json_response['repository_http_path']).to eq(project.http_url_to_repo)
+ expect(json_response['expires_in']).to eq(Gitlab::LfsToken::DEFAULT_EXPIRE_TIME)
expect(Gitlab::LfsToken.new(key).token_valid?(json_response['lfs_token'])).to be_truthy
end
@@ -324,6 +325,7 @@ describe API::Internal do
expect(response).to have_gitlab_http_status(200)
expect(json_response["status"]).to be_truthy
expect(json_response["repository_path"]).to eq('/')
+ expect(json_response["gl_project_path"]).to eq(project.wiki.full_path)
expect(json_response["gl_repository"]).to eq("wiki-#{project.id}")
expect(user.reload.last_activity_on).to be_nil
end
@@ -336,6 +338,7 @@ describe API::Internal do
expect(response).to have_gitlab_http_status(200)
expect(json_response["status"]).to be_truthy
expect(json_response["repository_path"]).to eq('/')
+ expect(json_response["gl_project_path"]).to eq(project.wiki.full_path)
expect(json_response["gl_repository"]).to eq("wiki-#{project.id}")
expect(user.reload.last_activity_on).to eql(Date.today)
end
@@ -349,6 +352,7 @@ describe API::Internal do
expect(json_response["status"]).to be_truthy
expect(json_response["repository_path"]).to eq('/')
expect(json_response["gl_repository"]).to eq("project-#{project.id}")
+ expect(json_response["gl_project_path"]).to eq(project.full_path)
expect(json_response["gitaly"]).not_to be_nil
expect(json_response["gitaly"]["repository"]).not_to be_nil
expect(json_response["gitaly"]["repository"]["storage_name"]).to eq(project.repository.gitaly_repository.storage_name)
@@ -368,6 +372,7 @@ describe API::Internal do
expect(json_response["status"]).to be_truthy
expect(json_response["repository_path"]).to eq('/')
expect(json_response["gl_repository"]).to eq("project-#{project.id}")
+ expect(json_response["gl_project_path"]).to eq(project.full_path)
expect(json_response["gitaly"]).not_to be_nil
expect(json_response["gitaly"]["repository"]).not_to be_nil
expect(json_response["gitaly"]["repository"]["storage_name"]).to eq(project.repository.gitaly_repository.storage_name)
@@ -809,7 +814,8 @@ describe API::Internal do
gl_repository: gl_repository,
secret_token: secret_token,
identifier: identifier,
- changes: changes
+ changes: changes,
+ push_options: push_options
}
end
@@ -817,6 +823,11 @@ describe API::Internal do
"#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/new_branch"
end
+ let(:push_options) do
+ ['ci.skip',
+ 'another push option']
+ end
+
before do
project.add_developer(user)
allow(described_class).to receive(:identify).and_return(user)
@@ -825,7 +836,7 @@ describe API::Internal do
it 'enqueues a PostReceive worker job' do
expect(PostReceive).to receive(:perform_async)
- .with(gl_repository, identifier, changes)
+ .with(gl_repository, identifier, changes, push_options)
post api("/internal/post_receive"), params: valid_params
end
@@ -861,7 +872,7 @@ describe API::Internal do
context 'broadcast message exists' do
let!(:broadcast_message) { create(:broadcast_message, starts_at: 1.day.ago, ends_at: 1.day.from_now ) }
- it 'returns one broadcast message' do
+ it 'returns one broadcast message' do
post api("/internal/post_receive"), params: valid_params
expect(response).to have_gitlab_http_status(200)
@@ -870,7 +881,7 @@ describe API::Internal do
end
context 'broadcast message does not exist' do
- it 'returns empty string' do
+ it 'returns empty string' do
post api("/internal/post_receive"), params: valid_params
expect(response).to have_gitlab_http_status(200)
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 0fd465da4f8..a5434d3ea80 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -49,7 +49,7 @@ describe API::Issues do
create(:label, title: 'label', color: '#FFAABB', project: project)
end
let!(:label_link) { create(:label_link, label: label, target: issue) }
- set(:milestone) { create(:milestone, title: '1.0.0', project: project) }
+ let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
set(:empty_milestone) do
create(:milestone, title: '2.0.0', project: project)
end
@@ -92,12 +92,10 @@ describe API::Issues do
end
context "when authenticated" do
- let(:first_issue) { json_response.first }
-
it "returns an array of issues" do
get api("/issues", user)
- expect_paginated_array_response(size: 2)
+ expect_paginated_array_response([issue.id, closed_issue.id])
expect(json_response.first['title']).to eq(issue.title)
expect(json_response.last).to have_key('web_url')
end
@@ -105,23 +103,19 @@ describe API::Issues do
it 'returns an array of closed issues' do
get api('/issues', user), params: { state: :closed }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(closed_issue.id)
+ expect_paginated_array_response(closed_issue.id)
end
it 'returns an array of opened issues' do
get api('/issues', user), params: { state: :opened }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(issue.id)
+ expect_paginated_array_response(issue.id)
end
it 'returns an array of all issues' do
get api('/issues', user), params: { state: :all }
- expect_paginated_array_response(size: 2)
- expect(first_issue['id']).to eq(issue.id)
- expect(json_response.second['id']).to eq(closed_issue.id)
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
it 'returns issues assigned to me' do
@@ -129,8 +123,7 @@ describe API::Issues do
get api('/issues', user2), params: { scope: 'assigned_to_me' }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
it 'returns issues assigned to me (kebab-case)' do
@@ -138,8 +131,7 @@ describe API::Issues do
get api('/issues', user2), params: { scope: 'assigned-to-me' }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
it 'returns issues authored by the given author id' do
@@ -147,8 +139,7 @@ describe API::Issues do
get api('/issues', user), params: { author_id: user2.id, scope: 'all' }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
it 'returns issues assigned to the given assignee id' do
@@ -156,8 +147,7 @@ describe API::Issues do
get api('/issues', user), params: { assignee_id: user2.id, scope: 'all' }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
it 'returns issues authored by the given author id and assigned to the given assignee id' do
@@ -165,8 +155,7 @@ describe API::Issues do
get api('/issues', user), params: { author_id: user2.id, assignee_id: user2.id, scope: 'all' }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
it 'returns issues with no assignee' do
@@ -174,8 +163,7 @@ describe API::Issues do
get api('/issues', user), params: { assignee_id: 0, scope: 'all' }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
it 'returns issues with no assignee' do
@@ -183,8 +171,7 @@ describe API::Issues do
get api('/issues', user), params: { assignee_id: 'None', scope: 'all' }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
it 'returns issues with any assignee' do
@@ -193,18 +180,29 @@ describe API::Issues do
get api('/issues', user), params: { assignee_id: 'Any', scope: 'all' }
- expect_paginated_array_response(size: 3)
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns only confidential issues' do
+ get api('/issues', user), params: { confidential: true, scope: 'all' }
+
+ expect_paginated_array_response(confidential_issue.id)
+ end
+
+ it 'returns only public issues' do
+ get api('/issues', user), params: { confidential: false }
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
it 'returns issues reacted by the authenticated user' do
issue2 = create(:issue, project: project, author: user, assignees: [user])
create(:award_emoji, awardable: issue2, user: user2, name: 'star')
-
create(:award_emoji, awardable: issue, user: user2, name: 'thumbsup')
get api('/issues', user2), params: { my_reaction_emoji: 'Any', scope: 'all' }
- expect_paginated_array_response(size: 2)
+ expect_paginated_array_response([issue2.id, issue.id])
end
it 'returns issues not reacted by the authenticated user' do
@@ -213,21 +211,31 @@ describe API::Issues do
get api('/issues', user2), params: { my_reaction_emoji: 'None', scope: 'all' }
- expect_paginated_array_response(size: 2)
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
it 'returns issues matching given search string for title' do
get api("/issues", user), params: { search: issue.title }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(issue.id)
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns issues matching given search string for title and scoped in title' do
+ get api("/issues", user), params: { search: issue.title, in: 'title' }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an empty array if no issue matches given search string for title and scoped in description' do
+ get api("/issues", user), params: { search: issue.title, in: 'description' }
+
+ expect_paginated_array_response([])
end
it 'returns issues matching given search string for description' do
get api("/issues", user), params: { search: issue.description }
- expect_paginated_array_response(size: 1)
- expect(first_issue['id']).to eq(issue.id)
+ expect_paginated_array_response(issue.id)
end
context 'filtering before a specific date' do
@@ -236,15 +244,13 @@ describe API::Issues do
it 'returns issues created before a specific date' do
get api('/issues?created_before=2000-01-02T00:00:00.060Z', user)
- expect(json_response.size).to eq(1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
it 'returns issues updated before a specific date' do
get api('/issues?updated_before=2000-01-02T00:00:00.060Z', user)
- expect(json_response.size).to eq(1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
end
@@ -254,23 +260,28 @@ describe API::Issues do
it 'returns issues created after a specific date' do
get api("/issues?created_after=#{issue2.created_at}", user)
- expect(json_response.size).to eq(1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
it 'returns issues updated after a specific date' do
get api("/issues?updated_after=#{issue2.updated_at}", user)
- expect(json_response.size).to eq(1)
- expect(first_issue['id']).to eq(issue2.id)
+ expect_paginated_array_response(issue2.id)
end
end
it 'returns an array of labeled issues' do
- get api("/issues", user), params: { labels: label.title }
+ get api('/issues', user), params: { labels: label.title }
- expect_paginated_array_response(size: 1)
- expect(first_issue['labels']).to eq([label.title])
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels']).to eq([label.title])
+ end
+
+ it 'returns an array of labeled issues with labels param as array' do
+ get api('/issues', user), params: { labels: [label.title] }
+
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels']).to eq([label.title])
end
it 'returns an array of labeled issues when all labels matches' do
@@ -280,135 +291,192 @@ describe API::Issues do
create(:label_link, label: label_b, target: issue)
create(:label_link, label: label_c, target: issue)
- get api("/issues", user), params: { labels: "#{label.title},#{label_b.title},#{label_c.title}" }
+ get api('/issues', user), params: { labels: "#{label.title},#{label_b.title},#{label_c.title}" }
- expect_paginated_array_response(size: 1)
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels']).to eq([label_c.title, label_b.title, label.title])
+ end
+
+ it 'returns an array of labeled issues when all labels matches with labels param as array' do
+ label_b = create(:label, title: 'foo', project: project)
+ label_c = create(:label, title: 'bar', project: project)
+
+ create(:label_link, label: label_b, target: issue)
+ create(:label_link, label: label_c, target: issue)
+
+ get api('/issues', user), params: { labels: [label.title, label_b.title, label_c.title] }
+
+ expect_paginated_array_response(issue.id)
expect(json_response.first['labels']).to eq([label_c.title, label_b.title, label.title])
end
it 'returns an empty array if no issue matches labels' do
get api('/issues', user), params: { labels: 'foo,bar' }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an empty array if no issue matches labels with labels param as array' do
+ get api('/issues', user), params: { labels: %w(foo bar) }
+
+ expect_paginated_array_response([])
end
it 'returns an array of labeled issues matching given state' do
- get api("/issues", user), params: { labels: label.title, state: :opened }
+ get api('/issues', user), params: { labels: label.title, state: :opened }
+
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels']).to eq([label.title])
+ expect(json_response.first['state']).to eq('opened')
+ end
+
+ it 'returns an array of labeled issues matching given state with labels param as array' do
+ get api('/issues', user), params: { labels: [label.title], state: :opened }
- expect_paginated_array_response(size: 1)
+ expect_paginated_array_response(issue.id)
expect(json_response.first['labels']).to eq([label.title])
expect(json_response.first['state']).to eq('opened')
end
it 'returns an empty array if no issue matches labels and state filters' do
- get api("/issues", user), params: { labels: label.title, state: :closed }
+ get api('/issues', user), params: { labels: label.title, state: :closed }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an array of issues with any label' do
- get api("/issues", user), params: { labels: IssuesFinder::FILTER_ANY }
+ get api('/issues', user), params: { labels: IssuesFinder::FILTER_ANY }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(issue.id)
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of issues with any label with labels param as array' do
+ get api('/issues', user), params: { labels: [IssuesFinder::FILTER_ANY] }
+
+ expect_paginated_array_response(issue.id)
end
it 'returns an array of issues with no label' do
- get api("/issues", user), params: { labels: IssuesFinder::FILTER_NONE }
+ get api('/issues', user), params: { labels: IssuesFinder::FILTER_NONE }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(closed_issue.id)
+ expect_paginated_array_response(closed_issue.id)
+ end
+
+ it 'returns an array of issues with no label with labels param as array' do
+ get api('/issues', user), params: { labels: [IssuesFinder::FILTER_NONE] }
+
+ expect_paginated_array_response(closed_issue.id)
end
it 'returns an array of issues with no label when using the legacy No+Label filter' do
- get api("/issues", user), params: { labels: "No Label" }
+ get api('/issues', user), params: { labels: 'No Label' }
+
+ expect_paginated_array_response(closed_issue.id)
+ end
+
+ it 'returns an array of issues with no label when using the legacy No+Label filter with labels param as array' do
+ get api('/issues', user), params: { labels: ['No Label'] }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(closed_issue.id)
+ expect_paginated_array_response(closed_issue.id)
end
it 'returns an empty array if no issue matches milestone' do
get api("/issues?milestone=#{empty_milestone.title}", user)
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an empty array if milestone does not exist' do
get api("/issues?milestone=foo", user)
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an array of issues in given milestone' do
get api("/issues?milestone=#{milestone.title}", user)
- expect_paginated_array_response(size: 2)
- expect(json_response.first['id']).to eq(issue.id)
- expect(json_response.second['id']).to eq(closed_issue.id)
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
it 'returns an array of issues matching state in milestone' do
get api("/issues?milestone=#{milestone.title}"\
'&state=closed', user)
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(closed_issue.id)
+ expect_paginated_array_response(closed_issue.id)
end
it 'returns an array of issues with no milestone' do
get api("/issues?milestone=#{no_milestone_title}", author)
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(confidential_issue.id)
+ expect_paginated_array_response(confidential_issue.id)
end
it 'returns an array of issues found by iids' do
get api('/issues', user), params: { iids: [closed_issue.iid] }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(closed_issue.id)
+ expect_paginated_array_response(closed_issue.id)
end
it 'returns an empty array if iid does not exist' do
- get api("/issues", user), params: { iids: [99999] }
+ get api("/issues", user), params: { iids: [0] }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
- it 'sorts by created_at descending by default' do
- get api('/issues', user)
+ context 'without sort params' do
+ it 'sorts by created_at descending by default' do
+ get api('/issues', user)
- response_dates = json_response.map { |issue| issue['created_at'] }
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
- expect_paginated_array_response(size: 2)
- expect(response_dates).to eq(response_dates.sort.reverse)
+ context 'with 2 issues with same created_at' do
+ let!(:closed_issue2) do
+ create :closed_issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ milestone: milestone,
+ created_at: closed_issue.created_at,
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
+ end
+
+ it 'page breaks first page correctly' do
+ get api('/issues?per_page=2', user)
+
+ expect_paginated_array_response([issue.id, closed_issue2.id])
+ end
+
+ it 'page breaks second page correctly' do
+ get api('/issues?per_page=2&page=2', user)
+
+ expect_paginated_array_response([closed_issue.id])
+ end
+ end
end
it 'sorts ascending when requested' do
get api('/issues?sort=asc', user)
- response_dates = json_response.map { |issue| issue['created_at'] }
-
- expect_paginated_array_response(size: 2)
- expect(response_dates).to eq(response_dates.sort)
+ expect_paginated_array_response([closed_issue.id, issue.id])
end
it 'sorts by updated_at descending when requested' do
get api('/issues?order_by=updated_at', user)
- response_dates = json_response.map { |issue| issue['updated_at'] }
+ issue.touch(:updated_at)
- expect_paginated_array_response(size: 2)
- expect(response_dates).to eq(response_dates.sort.reverse)
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
it 'sorts by updated_at ascending when requested' do
get api('/issues?order_by=updated_at&sort=asc', user)
- response_dates = json_response.map { |issue| issue['updated_at'] }
+ issue.touch(:updated_at)
- expect_paginated_array_response(size: 2)
- expect(response_dates).to eq(response_dates.sort)
+ expect_paginated_array_response([closed_issue.id, issue.id])
end
it 'matches V4 response schema' do
@@ -417,6 +485,24 @@ describe API::Issues do
expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/issues')
end
+
+ it 'returns a related merge request count of 0 if there are no related merge requests' do
+ get api('/issues', user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/issues')
+ expect(json_response.first).to include('merge_requests_count' => 0)
+ end
+
+ it 'returns a related merge request count > 0 if there are related merge requests' do
+ create(:merge_requests_closing_issues, issue: issue)
+
+ get api('/issues', user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/issues')
+ expect(json_response.first).to include('merge_requests_count' => 1)
+ end
end
end
@@ -430,7 +516,8 @@ describe API::Issues do
project: group_project,
state: :closed,
milestone: group_milestone,
- updated_at: 3.hours.ago
+ updated_at: 3.hours.ago,
+ created_at: 1.day.ago
end
let!(:group_confidential_issue) do
create :issue,
@@ -438,7 +525,8 @@ describe API::Issues do
project: group_project,
author: author,
assignees: [assignee],
- updated_at: 2.hours.ago
+ updated_at: 2.hours.ago,
+ created_at: 2.days.ago
end
let!(:group_issue) do
create :issue,
@@ -448,7 +536,8 @@ describe API::Issues do
milestone: group_milestone,
updated_at: 1.hour.ago,
title: issue_title,
- description: issue_description
+ description: issue_description,
+ created_at: 5.days.ago
end
let!(:group_label) do
create(:label, title: 'group_lbl', color: '#FFAABB', project: group_project)
@@ -479,10 +568,7 @@ describe API::Issues do
it 'also returns subgroups projects issues' do
get api(base_url, user)
- issue_ids = json_response.map { |issue| issue['id'] }
-
- expect_paginated_array_response(size: 5)
- expect(issue_ids).to include(issue_1.id, issue_2.id)
+ expect_paginated_array_response([issue_2.id, issue_1.id, group_closed_issue.id, group_confidential_issue.id, group_issue.id])
end
end
@@ -490,7 +576,7 @@ describe API::Issues do
it 'lists all issues in public projects' do
get api(base_url)
- expect_paginated_array_response(size: 2)
+ expect_paginated_array_response([group_closed_issue.id, group_issue.id])
end
end
@@ -502,65 +588,87 @@ describe API::Issues do
it 'returns all group issues (including opened and closed)' do
get api(base_url, admin)
- expect_paginated_array_response(size: 3)
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
end
it 'returns group issues without confidential issues for non project members' do
get api(base_url, non_member), params: { state: :opened }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['title']).to eq(group_issue.title)
+ expect_paginated_array_response(group_issue.id)
end
it 'returns group confidential issues for author' do
get api(base_url, author), params: { state: :opened }
- expect_paginated_array_response(size: 2)
+ expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
end
it 'returns group confidential issues for assignee' do
get api(base_url, assignee), params: { state: :opened }
- expect_paginated_array_response(size: 2)
+ expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
end
it 'returns group issues with confidential issues for project members' do
get api(base_url, user), params: { state: :opened }
- expect_paginated_array_response(size: 2)
+ expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
end
it 'returns group confidential issues for admin' do
get api(base_url, admin), params: { state: :opened }
- expect_paginated_array_response(size: 2)
+ expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
+ end
+
+ it 'returns only confidential issues' do
+ get api(base_url, user), params: { confidential: true }
+
+ expect_paginated_array_response(group_confidential_issue.id)
+ end
+
+ it 'returns only public issues' do
+ get api(base_url, user), params: { confidential: false }
+
+ expect_paginated_array_response([group_closed_issue.id, group_issue.id])
end
it 'returns an array of labeled group issues' do
get api(base_url, user), params: { labels: group_label.title }
- expect_paginated_array_response(size: 1)
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['labels']).to eq([group_label.title])
+ end
+
+ it 'returns an array of labeled group issues with labels param as array' do
+ get api(base_url, user), params: { labels: [group_label.title] }
+
+ expect_paginated_array_response(group_issue.id)
expect(json_response.first['labels']).to eq([group_label.title])
end
it 'returns an array of labeled group issues where all labels match' do
get api(base_url, user), params: { labels: "#{group_label.title},foo,bar" }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of labeled group issues where all labels match with labels param as array' do
+ get api(base_url, user), params: { labels: [group_label.title, 'foo', 'bar'] }
+
+ expect_paginated_array_response([])
end
it 'returns issues matching given search string for title' do
get api(base_url, user), params: { search: group_issue.title }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(group_issue.id)
+ expect_paginated_array_response(group_issue.id)
end
it 'returns issues matching given search string for description' do
get api(base_url, user), params: { search: group_issue.description }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(group_issue.id)
+ expect_paginated_array_response(group_issue.id)
end
it 'returns an array of labeled issues when all labels matches' do
@@ -572,69 +680,90 @@ describe API::Issues do
get api(base_url, user), params: { labels: "#{group_label.title},#{label_b.title},#{label_c.title}" }
- expect_paginated_array_response(size: 1)
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['labels']).to eq([label_c.title, label_b.title, group_label.title])
+ end
+
+ it 'returns an array of labeled issues when all labels matches with labels param as array' do
+ label_b = create(:label, title: 'foo', project: group_project)
+ label_c = create(:label, title: 'bar', project: group_project)
+
+ create(:label_link, label: label_b, target: group_issue)
+ create(:label_link, label: label_c, target: group_issue)
+
+ get api(base_url, user), params: { labels: [group_label.title, label_b.title, label_c.title] }
+
+ expect_paginated_array_response(group_issue.id)
expect(json_response.first['labels']).to eq([label_c.title, label_b.title, group_label.title])
end
it 'returns an array of issues found by iids' do
get api(base_url, user), params: { iids: [group_issue.iid] }
- expect_paginated_array_response(size: 1)
+ expect_paginated_array_response(group_issue.id)
expect(json_response.first['id']).to eq(group_issue.id)
end
it 'returns an empty array if iid does not exist' do
- get api(base_url, user), params: { iids: [99999] }
+ get api(base_url, user), params: { iids: [0] }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an empty array if no group issue matches labels' do
get api(base_url, user), params: { labels: 'foo,bar' }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an array of group issues with any label' do
get api(base_url, user), params: { labels: IssuesFinder::FILTER_ANY }
- expect_paginated_array_response(size: 1)
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['id']).to eq(group_issue.id)
+ end
+
+ it 'returns an array of group issues with any label with labels param as array' do
+ get api(base_url, user), params: { labels: [IssuesFinder::FILTER_ANY] }
+
+ expect_paginated_array_response(group_issue.id)
expect(json_response.first['id']).to eq(group_issue.id)
end
it 'returns an array of group issues with no label' do
get api(base_url, user), params: { labels: IssuesFinder::FILTER_NONE }
- response_ids = json_response.map { |issue| issue['id'] }
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id])
+ end
+
+ it 'returns an array of group issues with no label with labels param as array' do
+ get api(base_url, user), params: { labels: [IssuesFinder::FILTER_NONE] }
- expect_paginated_array_response(size: 2)
- expect(response_ids).to contain_exactly(group_closed_issue.id, group_confidential_issue.id)
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id])
end
it 'returns an empty array if no issue matches milestone' do
get api(base_url, user), params: { milestone: group_empty_milestone.title }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an empty array if milestone does not exist' do
get api(base_url, user), params: { milestone: 'foo' }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an array of issues in given milestone' do
get api(base_url, user), params: { state: :opened, milestone: group_milestone.title }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(group_issue.id)
+ expect_paginated_array_response(group_issue.id)
end
it 'returns an array of issues matching state in milestone' do
get api(base_url, user), params: { milestone: group_milestone.title, state: :closed }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(group_closed_issue.id)
+ expect_paginated_array_response(group_closed_issue.id)
end
it 'returns an array of issues with no milestone' do
@@ -642,44 +771,61 @@ describe API::Issues do
expect(response).to have_gitlab_http_status(200)
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(group_confidential_issue.id)
+ expect_paginated_array_response(group_confidential_issue.id)
end
- it 'sorts by created_at descending by default' do
- get api(base_url, user)
+ context 'without sort params' do
+ it 'sorts by created_at descending by default' do
+ get api(base_url, user)
- response_dates = json_response.map { |issue| issue['created_at'] }
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
+ end
- expect_paginated_array_response(size: 3)
- expect(response_dates).to eq(response_dates.sort.reverse)
+ context 'with 2 issues with same created_at' do
+ let!(:group_issue2) do
+ create :issue,
+ author: user,
+ assignees: [user],
+ project: group_project,
+ milestone: group_milestone,
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description,
+ created_at: group_issue.created_at
+ end
+
+ it 'page breaks first page correctly' do
+ get api("#{base_url}?per_page=3", user)
+
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue2.id])
+ end
+
+ it 'page breaks second page correctly' do
+ get api("#{base_url}?per_page=3&page=2", user)
+
+ expect_paginated_array_response([group_issue.id])
+ end
+ end
end
it 'sorts ascending when requested' do
get api("#{base_url}?sort=asc", user)
- response_dates = json_response.map { |issue| issue['created_at'] }
-
- expect_paginated_array_response(size: 3)
- expect(response_dates).to eq(response_dates.sort)
+ expect_paginated_array_response([group_issue.id, group_confidential_issue.id, group_closed_issue.id])
end
it 'sorts by updated_at descending when requested' do
get api("#{base_url}?order_by=updated_at", user)
- response_dates = json_response.map { |issue| issue['updated_at'] }
+ group_issue.touch(:updated_at)
- expect_paginated_array_response(size: 3)
- expect(response_dates).to eq(response_dates.sort.reverse)
+ expect_paginated_array_response([group_issue.id, group_confidential_issue.id, group_closed_issue.id])
end
it 'sorts by updated_at ascending when requested' do
get api(base_url, user), params: { order_by: :updated_at, sort: :asc }
- response_dates = json_response.map { |issue| issue['updated_at'] }
-
- expect_paginated_array_response(size: 3)
- expect(response_dates).to eq(response_dates.sort)
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
end
end
end
@@ -691,8 +837,7 @@ describe API::Issues do
it 'returns public project issues' do
get api("/projects/#{project.id}/issues")
- expect_paginated_array_response(size: 2)
- expect(json_response.first['title']).to eq(issue.title)
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
end
@@ -731,56 +876,67 @@ describe API::Issues do
get api("/projects/#{restricted_project.id}/issues", non_member)
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns project issues without confidential issues for non project members' do
get api("#{base_url}/issues", non_member)
- expect_paginated_array_response(size: 2)
- expect(json_response.first['title']).to eq(issue.title)
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
it 'returns project issues without confidential issues for project members with guest role' do
get api("#{base_url}/issues", guest)
- expect_paginated_array_response(size: 2)
- expect(json_response.first['title']).to eq(issue.title)
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
it 'returns project confidential issues for author' do
get api("#{base_url}/issues", author)
- expect_paginated_array_response(size: 3)
- expect(json_response.first['title']).to eq(issue.title)
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns only confidential issues' do
+ get api("#{base_url}/issues", author), params: { confidential: true }
+
+ expect_paginated_array_response(confidential_issue.id)
+ end
+
+ it 'returns only public issues' do
+ get api("#{base_url}/issues", author), params: { confidential: false }
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
it 'returns project confidential issues for assignee' do
get api("#{base_url}/issues", assignee)
- expect_paginated_array_response(size: 3)
- expect(json_response.first['title']).to eq(issue.title)
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
end
it 'returns project issues with confidential issues for project members' do
get api("#{base_url}/issues", user)
- expect_paginated_array_response(size: 3)
- expect(json_response.first['title']).to eq(issue.title)
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
end
it 'returns project confidential issues for admin' do
get api("#{base_url}/issues", admin)
- expect_paginated_array_response(size: 3)
- expect(json_response.first['title']).to eq(issue.title)
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
end
it 'returns an array of labeled project issues' do
get api("#{base_url}/issues", user), params: { labels: label.title }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['labels']).to eq([label.title])
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of labeled project issues with labels param as array' do
+ get api("#{base_url}/issues", user), params: { labels: [label.title] }
+
+ expect_paginated_array_response(issue.id)
end
it 'returns an array of labeled issues when all labels matches' do
@@ -792,142 +948,169 @@ describe API::Issues do
get api("#{base_url}/issues", user), params: { labels: "#{label.title},#{label_b.title},#{label_c.title}" }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['labels']).to eq([label_c.title, label_b.title, label.title])
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of labeled issues when all labels matches with labels param as array' do
+ label_b = create(:label, title: 'foo', project: project)
+ label_c = create(:label, title: 'bar', project: project)
+
+ create(:label_link, label: label_b, target: issue)
+ create(:label_link, label: label_c, target: issue)
+
+ get api("#{base_url}/issues", user), params: { labels: [label.title, label_b.title, label_c.title] }
+
+ expect_paginated_array_response(issue.id)
end
it 'returns issues matching given search string for title' do
get api("#{base_url}/issues?search=#{issue.title}", user)
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(issue.id)
+ expect_paginated_array_response(issue.id)
end
it 'returns issues matching given search string for description' do
get api("#{base_url}/issues?search=#{issue.description}", user)
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(issue.id)
+ expect_paginated_array_response(issue.id)
end
it 'returns an array of issues found by iids' do
get api("#{base_url}/issues", user), params: { iids: [issue.iid] }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(issue.id)
+ expect_paginated_array_response(issue.id)
end
it 'returns an empty array if iid does not exist' do
- get api("#{base_url}/issues", user), params: { iids: [99999] }
+ get api("#{base_url}/issues", user), params: { iids: [0] }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an empty array if not all labels matches' do
get api("#{base_url}/issues?labels=#{label.title},foo", user)
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an array of project issues with any label' do
get api("#{base_url}/issues", user), params: { labels: IssuesFinder::FILTER_ANY }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(issue.id)
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of project issues with any label with labels param as array' do
+ get api("#{base_url}/issues", user), params: { labels: [IssuesFinder::FILTER_ANY] }
+
+ expect_paginated_array_response(issue.id)
end
it 'returns an array of project issues with no label' do
get api("#{base_url}/issues", user), params: { labels: IssuesFinder::FILTER_NONE }
- response_ids = json_response.map { |issue| issue['id'] }
+ expect_paginated_array_response([confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns an array of project issues with no label with labels param as array' do
+ get api("#{base_url}/issues", user), params: { labels: [IssuesFinder::FILTER_NONE] }
- expect_paginated_array_response(size: 2)
- expect(response_ids).to contain_exactly(closed_issue.id, confidential_issue.id)
+ expect_paginated_array_response([confidential_issue.id, closed_issue.id])
end
it 'returns an empty array if no project issue matches labels' do
get api("#{base_url}/issues", user), params: { labels: 'foo,bar' }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an empty array if no issue matches milestone' do
get api("#{base_url}/issues", user), params: { milestone: empty_milestone.title }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an empty array if milestone does not exist' do
get api("#{base_url}/issues", user), params: { milestone: :foo }
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
it 'returns an array of issues in given milestone' do
get api("#{base_url}/issues", user), params: { milestone: milestone.title }
- expect_paginated_array_response(size: 2)
- expect(json_response.first['id']).to eq(issue.id)
- expect(json_response.second['id']).to eq(closed_issue.id)
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
it 'returns an array of issues matching state in milestone' do
get api("#{base_url}/issues", user), params: { milestone: milestone.title, state: :closed }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(closed_issue.id)
+ expect_paginated_array_response(closed_issue.id)
end
it 'returns an array of issues with no milestone' do
get api("#{base_url}/issues", user), params: { milestone: no_milestone_title }
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(confidential_issue.id)
+ expect_paginated_array_response(confidential_issue.id)
end
it 'returns an array of issues with any milestone' do
get api("#{base_url}/issues", user), params: { milestone: any_milestone_title }
- response_ids = json_response.map { |issue| issue['id'] }
-
- expect_paginated_array_response(size: 2)
- expect(response_ids).to contain_exactly(closed_issue.id, issue.id)
+ expect_paginated_array_response([issue.id, closed_issue.id])
end
- it 'sorts by created_at descending by default' do
- get api("#{base_url}/issues", user)
+ context 'without sort params' do
+ it 'sorts by created_at descending by default' do
+ get api("#{base_url}/issues", user)
+
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ context 'with 2 issues with same created_at' do
+ let!(:closed_issue2) do
+ create :closed_issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ milestone: milestone,
+ created_at: closed_issue.created_at,
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
+ end
- response_dates = json_response.map { |issue| issue['created_at'] }
+ it 'page breaks first page correctly' do
+ get api("#{base_url}/issues?per_page=3", user)
- expect_paginated_array_response(size: 3)
- expect(response_dates).to eq(response_dates.sort.reverse)
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue2.id])
+ end
+
+ it 'page breaks second page correctly' do
+ get api("#{base_url}/issues?per_page=3&page=2", user)
+
+ expect_paginated_array_response([closed_issue.id])
+ end
+ end
end
it 'sorts ascending when requested' do
get api("#{base_url}/issues", user), params: { sort: :asc }
- response_dates = json_response.map { |issue| issue['created_at'] }
-
- expect_paginated_array_response(size: 3)
- expect(response_dates).to eq(response_dates.sort)
+ expect_paginated_array_response([closed_issue.id, confidential_issue.id, issue.id])
end
it 'sorts by updated_at descending when requested' do
get api("#{base_url}/issues", user), params: { order_by: :updated_at }
- response_dates = json_response.map { |issue| issue['updated_at'] }
+ issue.touch(:updated_at)
- expect_paginated_array_response(size: 3)
- expect(response_dates).to eq(response_dates.sort.reverse)
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
end
it 'sorts by updated_at ascending when requested' do
get api("#{base_url}/issues", user), params: { order_by: :updated_at, sort: :asc }
- response_dates = json_response.map { |issue| issue['updated_at'] }
-
- expect_paginated_array_response(size: 3)
- expect(response_dates).to eq(response_dates.sort)
+ expect_paginated_array_response([closed_issue.id, confidential_issue.id, issue.id])
end
end
@@ -1081,7 +1264,7 @@ describe API::Issues do
end
context 'user does not have permissions to create issue' do
- let(:not_member) { create(:user) }
+ let(:not_member) { create(:user) }
before do
project.project_feature.update(issues_access_level: ProjectFeature::PRIVATE)
@@ -1153,6 +1336,19 @@ describe API::Issues do
expect(json_response['assignees'].first['name']).to eq(user2.name)
end
+ it 'creates a new project issue with labels param as array' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', labels: %w(label label2), weight: 3, assignee_ids: [user2.id] }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['description']).to be_nil
+ expect(json_response['labels']).to eq(%w(label label2))
+ expect(json_response['confidential']).to be_falsy
+ expect(json_response['assignee']['name']).to eq(user2.name)
+ expect(json_response['assignees'].first['name']).to eq(user2.name)
+ end
+
it 'creates a new confidential project issue' do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', confidential: true }
@@ -1207,6 +1403,20 @@ describe API::Issues do
expect(json_response['labels']).to include '&'
end
+ it 'allows special label names with labels param as array' do
+ post api("/projects/#{project.id}/issues", user),
+ params: {
+ title: 'new issue',
+ labels: ['label', 'label?', 'label&foo, ?, &']
+ }
+ expect(response.status).to eq(201)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
it 'returns 400 if title is too long' do
post api("/projects/#{project.id}/issues", user),
params: { title: 'g' * 256 }
@@ -1315,6 +1525,12 @@ describe API::Issues do
post api("/projects/#{project.id}/issues", non_member), params: { title: 'new issue', labels: 'label, label2' }
end.not_to change { project.labels.count }
end
+
+ it 'cannot create new labels with labels param as array' do
+ expect do
+ post api("/projects/#{project.id}/issues", non_member), params: { title: 'new issue', labels: %w(label label2) }
+ end.not_to change { project.labels.count }
+ end
end
end
@@ -1382,6 +1598,21 @@ describe API::Issues do
expect(json_response['labels']).to include '&'
end
+ it 'allows special label names with labels param as array' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: {
+ title: 'updated title',
+ labels: ['label', 'label?', 'label&foo, ?, &']
+ }
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
context 'confidential issues' do
it "returns 403 for non project members" do
put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", non_member),
@@ -1541,6 +1772,16 @@ describe API::Issues do
expect(json_response['updated_at']).to be > Time.now
end
+ it 'removes all labels and touches the record with labels param as array' do
+ Timecop.travel(1.minute.from_now) do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { labels: [''] }
+ end
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['labels']).to eq([])
+ expect(json_response['updated_at']).to be > Time.now
+ end
+
it 'updates labels and touches the record' do
Timecop.travel(1.minute.from_now) do
put api("/projects/#{project.id}/issues/#{issue.iid}", user),
@@ -1552,6 +1793,17 @@ describe API::Issues do
expect(json_response['updated_at']).to be > Time.now
end
+ it 'updates labels and touches the record with labels param as array' do
+ Timecop.travel(1.minute.from_now) do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { labels: %w(foo bar) }
+ end
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['labels']).to include 'foo'
+ expect(json_response['labels']).to include 'bar'
+ expect(json_response['updated_at']).to be > Time.now
+ end
+
it 'allows special label names' do
put api("/projects/#{project.id}/issues/#{issue.iid}", user),
params: { labels: 'label:foo, label-bar,label_bar,label/bar,label?bar,label&bar,?,&' }
@@ -1566,6 +1818,20 @@ describe API::Issues do
expect(json_response['labels']).to include '&'
end
+ it 'allows special label names with labels param as array' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { labels: ['label:foo', 'label-bar', 'label_bar', 'label/bar,label?bar,label&bar,?,&'] }
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label:foo'
+ expect(json_response['labels']).to include 'label-bar'
+ expect(json_response['labels']).to include 'label_bar'
+ expect(json_response['labels']).to include 'label/bar'
+ expect(json_response['labels']).to include 'label?bar'
+ expect(json_response['labels']).to include 'label&bar'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
it 'returns 400 if title is too long' do
put api("/projects/#{project.id}/issues/#{issue.iid}", user),
params: { title: 'g' * 256 }
@@ -1828,26 +2094,26 @@ describe API::Issues do
it 'return public project issues' do
get api("/projects/#{project.id}/issues/#{issue.iid}/closed_by")
- expect_paginated_array_response(size: 1)
+ expect_paginated_array_response(merge_request.id)
end
end
it 'returns merge requests that will close issue on merge' do
get api("/projects/#{project.id}/issues/#{issue.iid}/closed_by", user)
- expect_paginated_array_response(size: 1)
+ expect_paginated_array_response(merge_request.id)
end
context 'when no merge requests will close issue' do
it 'returns empty array' do
get api("/projects/#{project.id}/issues/#{closed_issue.iid}/closed_by", user)
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
end
it "returns 404 when issue doesn't exists" do
- get api("/projects/#{project.id}/issues/9999/closed_by", user)
+ get api("/projects/#{project.id}/issues/0/closed_by", user)
expect(response).to have_gitlab_http_status(404)
end
@@ -1868,7 +2134,7 @@ describe API::Issues do
description: "See #{issue.to_reference}"
}
create(:merge_request, attributes).tap do |merge_request|
- create(:note, :system, project: project, noteable: issue, author: user, note: merge_request.to_reference(full: true))
+ create(:note, :system, project: issue.project, noteable: issue, author: user, note: merge_request.to_reference(full: true))
end
end
@@ -1878,7 +2144,7 @@ describe API::Issues do
it 'return list of referenced merge requests from issue' do
get_related_merge_requests(project.id, issue.iid)
- expect_paginated_array_response(size: 1)
+ expect_paginated_array_response(related_mr.id)
end
it 'renders 404 if project is not visible' do
@@ -1902,20 +2168,37 @@ describe API::Issues do
get_related_merge_requests(project.id, issue.iid, user)
- expect_paginated_array_response(size: 1)
- expect(json_response.first['id']).to eq(related_mr.id)
+ expect_paginated_array_response(related_mr.id)
+ end
+
+ it 'returns merge requests cross-project wide' do
+ project2 = create(:project, :public, creator_id: user.id, namespace: user.namespace)
+ merge_request = create_referencing_mr(user, project2, issue)
+
+ get_related_merge_requests(project.id, issue.iid, user)
+
+ expect_paginated_array_response([related_mr.id, merge_request.id])
+ end
+
+ it 'does not generate references to projects with no access' do
+ private_project = create(:project, :private)
+ create_referencing_mr(private_project.creator, private_project, issue)
+
+ get_related_merge_requests(project.id, issue.iid, user)
+
+ expect_paginated_array_response(related_mr.id)
end
context 'no merge request mentioned a issue' do
it 'returns empty array' do
get_related_merge_requests(project.id, closed_issue.iid, user)
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response([])
end
end
it "returns 404 when issue doesn't exists" do
- get_related_merge_requests(project.id, 999999, user)
+ get_related_merge_requests(project.id, 0, user)
expect(response).to have_gitlab_http_status(404)
end
@@ -1948,13 +2231,6 @@ describe API::Issues do
end
end
- def expect_paginated_array_response(size: nil)
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(size) if size
- end
-
describe 'GET projects/:id/issues/:issue_iid/participants' do
it_behaves_like 'issuable participants endpoint' do
let(:entity) { issue }
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index 73131dba542..ed2ef4c730b 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -142,10 +142,20 @@ describe API::Jobs do
end
context 'unauthorized user' do
- let(:api_user) { nil }
+ context 'when user is not logged in' do
+ let(:api_user) { nil }
- it 'does not return project jobs' do
- expect(response).to have_gitlab_http_status(401)
+ it 'does not return project jobs' do
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:api_user) { guest }
+
+ it 'does not return project jobs' do
+ expect(response).to have_gitlab_http_status(403)
+ end
end
end
@@ -241,10 +251,20 @@ describe API::Jobs do
end
context 'unauthorized user' do
- let(:api_user) { nil }
+ context 'when user is not logged in' do
+ let(:api_user) { nil }
- it 'does not return jobs' do
- expect(response).to have_gitlab_http_status(401)
+ it 'does not return jobs' do
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:api_user) { guest }
+
+ it 'does not return jobs' do
+ expect(response).to have_gitlab_http_status(403)
+ end
end
end
end
@@ -301,6 +321,49 @@ describe API::Jobs do
end
end
+ describe 'DELETE /projects/:id/jobs/:job_id/artifacts' do
+ let!(:job) { create(:ci_build, :artifacts, pipeline: pipeline, user: api_user) }
+
+ before do
+ delete api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
+ end
+
+ context 'when user is anonymous' do
+ let(:api_user) { nil }
+
+ it 'does not delete artifacts' do
+ expect(job.job_artifacts.size).to eq 2
+ end
+
+ it 'returns status 401 (unauthorized)' do
+ expect(response).to have_http_status :unauthorized
+ end
+ end
+
+ context 'with developer' do
+ it 'does not delete artifacts' do
+ expect(job.job_artifacts.size).to eq 2
+ end
+
+ it 'returns status 403 (forbidden)' do
+ expect(response).to have_http_status :forbidden
+ end
+ end
+
+ context 'with authorized user' do
+ let(:maintainer) { create(:project_member, :maintainer, project: project).user }
+ let!(:api_user) { maintainer }
+
+ it 'deletes artifacts' do
+ expect(job.job_artifacts.size).to eq 0
+ end
+
+ it 'returns status 204 (no content)' do
+ expect(response).to have_http_status :no_content
+ end
+ end
+ end
+
describe 'GET /projects/:id/jobs/:job_id/artifacts/:artifact_path' do
context 'when job has artifacts' do
let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) }
@@ -383,7 +446,7 @@ describe API::Jobs do
shared_examples 'downloads artifact' do
let(:download_headers) do
{ 'Content-Transfer-Encoding' => 'binary',
- 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' }
+ 'Content-Disposition' => %q(attachment; filename="ci_build_artifacts.zip"; filename*=UTF-8''ci_build_artifacts.zip) }
end
it 'returns specific job artifacts' do
@@ -535,7 +598,7 @@ describe API::Jobs do
let(:download_headers) do
{ 'Content-Transfer-Encoding' => 'binary',
'Content-Disposition' =>
- "attachment; filename=#{job.artifacts_file.filename}" }
+ %Q(attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}) }
end
it { expect(response).to have_http_status(:ok) }
diff --git a/spec/requests/api/keys_spec.rb b/spec/requests/api/keys_spec.rb
index 3c4719964b6..f37d84fddef 100644
--- a/spec/requests/api/keys_spec.rb
+++ b/spec/requests/api/keys_spec.rb
@@ -16,7 +16,7 @@ describe API::Keys do
context 'when authenticated' do
it 'returns 404 for non-existing key' do
- get api('/keys/999999', admin)
+ get api('/keys/0', admin)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 Not found')
end
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index 49eea2e362b..518181e4d93 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -20,9 +20,9 @@ describe API::Labels do
create(:labeled_merge_request, labels: [priority_label], author: user, source_project: project )
expected_keys = %w(
- id name color description
+ id name color text_color description
open_issues_count closed_issues_count open_merge_requests_count
- subscribed priority
+ subscribed priority is_project_label
)
get api("/projects/#{project.id}/labels", user)
@@ -43,27 +43,33 @@ describe API::Labels do
expect(label1_response['open_merge_requests_count']).to eq(0)
expect(label1_response['name']).to eq(label1.name)
expect(label1_response['color']).to be_present
+ expect(label1_response['text_color']).to be_present
expect(label1_response['description']).to be_nil
expect(label1_response['priority']).to be_nil
expect(label1_response['subscribed']).to be_falsey
+ expect(label1_response['is_project_label']).to be_truthy
expect(group_label_response['open_issues_count']).to eq(1)
expect(group_label_response['closed_issues_count']).to eq(0)
expect(group_label_response['open_merge_requests_count']).to eq(0)
expect(group_label_response['name']).to eq(group_label.name)
expect(group_label_response['color']).to be_present
+ expect(group_label_response['text_color']).to be_present
expect(group_label_response['description']).to be_nil
expect(group_label_response['priority']).to be_nil
expect(group_label_response['subscribed']).to be_falsey
+ expect(group_label_response['is_project_label']).to be_falsey
expect(priority_label_response['open_issues_count']).to eq(0)
expect(priority_label_response['closed_issues_count']).to eq(0)
expect(priority_label_response['open_merge_requests_count']).to eq(1)
expect(priority_label_response['name']).to eq(priority_label.name)
expect(priority_label_response['color']).to be_present
+ expect(priority_label_response['text_color']).to be_present
expect(priority_label_response['description']).to be_nil
expect(priority_label_response['priority']).to eq(3)
expect(priority_label_response['subscribed']).to be_falsey
+ expect(priority_label_response['is_project_label']).to be_truthy
end
end
diff --git a/spec/requests/api/markdown_spec.rb b/spec/requests/api/markdown_spec.rb
index e82ef002d32..0cf5c5677b9 100644
--- a/spec/requests/api/markdown_spec.rb
+++ b/spec/requests/api/markdown_spec.rb
@@ -7,6 +7,8 @@ describe API::Markdown do
let(:user) {} # No-op. It gets overwritten in the contexts below.
before do
+ stub_commonmark_sourcepos_disabled
+
post api("/markdown", user), params: params
end
diff --git a/spec/requests/api/merge_request_diffs_spec.rb b/spec/requests/api/merge_request_diffs_spec.rb
index 6530dc956cb..8a67d98fc4c 100644
--- a/spec/requests/api/merge_request_diffs_spec.rb
+++ b/spec/requests/api/merge_request_diffs_spec.rb
@@ -30,7 +30,7 @@ describe API::MergeRequestDiffs, 'MergeRequestDiffs' do
end
it 'returns a 404 when merge_request_iid not found' do
- get api("/projects/#{project.id}/merge_requests/999/versions", user)
+ get api("/projects/#{project.id}/merge_requests/0/versions", user)
expect(response).to have_gitlab_http_status(404)
end
end
@@ -53,7 +53,7 @@ describe API::MergeRequestDiffs, 'MergeRequestDiffs' do
end
it 'returns a 404 when merge_request version_id is not found' do
- get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/versions/999", user)
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/versions/0", user)
expect(response).to have_gitlab_http_status(404)
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index dd40f3d1561..6752a1c36bf 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -10,7 +10,7 @@ describe API::MergeRequests do
let!(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
let(:pipeline) { create(:ci_empty_pipeline) }
- let(:milestone1) { create(:milestone, title: '0.9', project: project) }
+ let(:milestone1) { create(:milestone, title: '0.9', project: project) }
let!(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: "Test", created_at: base_time) }
let!(:merge_request_closed) { create(:merge_request, state: "closed", milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second) }
let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
@@ -260,6 +260,18 @@ describe API::MergeRequests do
expect_response_ordered_exactly(merge_request)
end
+ it 'returns merge requests matching given search string for title and scoped in title' do
+ get api("/merge_requests", user), params: { search: merge_request.title, in: 'title' }
+
+ expect_response_ordered_exactly(merge_request)
+ end
+
+ it 'returns an empty array if no merge reques matches given search string for description and scoped in title' do
+ get api("/merge_requests", user), params: { search: merge_request.description, in: 'title' }
+
+ expect_response_contain_exactly
+ end
+
it 'returns merge requests for project matching given search string for description' do
get api("/merge_requests", user), params: { project_id: project.id, search: merge_request.description }
@@ -308,6 +320,18 @@ describe API::MergeRequests do
expect(json_response.first['title']).to eq merge_request_closed.title
expect(json_response.first['id']).to eq merge_request_closed.id
end
+
+ it 'avoids N+1 queries' do
+ control = ActiveRecord::QueryRecorder.new do
+ get api("/projects/#{project.id}/merge_requests", user)
+ end.count
+
+ create(:merge_request, author: user, assignee: user, source_project: project, target_project: project, created_at: base_time)
+
+ expect do
+ get api("/projects/#{project.id}/merge_requests", user)
+ end.not_to exceed_query_limit(control)
+ end
end
describe "GET /groups/:id/merge_requests" do
@@ -360,6 +384,7 @@ describe API::MergeRequests do
expect(json_response['force_close_merge_request']).to be_falsy
expect(json_response['changes_count']).to eq(merge_request.merge_request_diff.real_size)
expect(json_response['merge_error']).to eq(merge_request.merge_error)
+ expect(json_response['user']['can_merge']).to be_truthy
expect(json_response).not_to include('rebase_in_progress')
end
@@ -428,7 +453,7 @@ describe API::MergeRequests do
end
it "returns a 404 error if merge_request_iid not found" do
- get api("/projects/#{project.id}/merge_requests/999", user)
+ get api("/projects/#{project.id}/merge_requests/0", user)
expect(response).to have_gitlab_http_status(404)
end
@@ -487,6 +512,15 @@ describe API::MergeRequests do
expect(json_response['allow_maintainer_to_push']).to be_truthy
end
end
+
+ it 'indicates if a user cannot merge the MR' do
+ user2 = create(:user)
+ project.add_reporter(user2)
+
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user2)
+
+ expect(json_response['user']['can_merge']).to be_falsy
+ end
end
describe 'GET /projects/:id/merge_requests/:merge_request_iid/participants' do
@@ -509,7 +543,7 @@ describe API::MergeRequests do
end
it 'returns a 404 when merge_request_iid not found' do
- get api("/projects/#{project.id}/merge_requests/999/commits", user)
+ get api("/projects/#{project.id}/merge_requests/0/commits", user)
expect(response).to have_gitlab_http_status(404)
end
@@ -529,7 +563,7 @@ describe API::MergeRequests do
end
it 'returns a 404 when merge_request_iid not found' do
- get api("/projects/#{project.id}/merge_requests/999/changes", user)
+ get api("/projects/#{project.id}/merge_requests/0/changes", user)
expect(response).to have_gitlab_http_status(404)
end
@@ -583,26 +617,115 @@ describe API::MergeRequests do
end
end
- describe "POST /projects/:id/merge_requests" do
+ describe 'POST /projects/:id/merge_requests' do
context 'between branches projects' do
- it "returns merge_request" do
- post api("/projects/#{project.id}/merge_requests", user),
- params: {
- title: 'Test merge_request',
- source_branch: 'feature_conflict',
- target_branch: 'master',
- author: user,
- labels: 'label, label2',
- milestone_id: milestone.id,
- squash: true
- }
+ context 'different labels' do
+ let(:params) do
+ {
+ title: 'Test merge_request',
+ source_branch: 'feature_conflict',
+ target_branch: 'master',
+ author_id: user.id,
+ milestone_id: milestone.id,
+ squash: true
+ }
+ end
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('Test merge_request')
- expect(json_response['labels']).to eq(%w(label label2))
- expect(json_response['milestone']['id']).to eq(milestone.id)
- expect(json_response['squash']).to be_truthy
- expect(json_response['force_remove_source_branch']).to be_falsy
+ shared_examples_for 'creates merge request with labels' do
+ it 'returns merge_request' do
+ params[:labels] = labels
+ post api("/projects/#{project.id}/merge_requests", user), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('Test merge_request')
+ expect(json_response['labels']).to eq(%w(label label2))
+ expect(json_response['milestone']['id']).to eq(milestone.id)
+ expect(json_response['squash']).to be_truthy
+ expect(json_response['force_remove_source_branch']).to be_falsy
+ end
+ end
+
+ it_behaves_like 'creates merge request with labels' do
+ let(:labels) { 'label, label2' }
+ end
+
+ it_behaves_like 'creates merge request with labels' do
+ let(:labels) { %w(label label2) }
+ end
+
+ it_behaves_like 'creates merge request with labels' do
+ let(:labels) { %w(label label2) }
+ end
+
+ it 'creates merge request with special label names' do
+ params[:labels] = 'label, label?, label&foo, ?, &'
+ post api("/projects/#{project.id}/merge_requests", user), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
+ it 'creates merge request with special label names as array' do
+ params[:labels] = ['label', 'label?', 'label&foo, ?, &', '1, 2', 3, 4]
+ post api("/projects/#{project.id}/merge_requests", user), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ expect(json_response['labels']).to include '1'
+ expect(json_response['labels']).to include '2'
+ expect(json_response['labels']).to include '3'
+ expect(json_response['labels']).to include '4'
+ end
+
+ it 'empty label param does not add any labels' do
+ params[:labels] = ''
+ post api("/projects/#{project.id}/merge_requests", user), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['labels']).to eq([])
+ end
+
+ it 'empty label param as array does not add any labels, but only explicitly as json' do
+ params[:labels] = []
+ post api("/projects/#{project.id}/merge_requests", user),
+ params: params.to_json,
+ headers: { 'Content-Type': 'application/json' }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['labels']).to eq([])
+ end
+
+ xit 'empty label param as array, does not add any labels' do
+ params[:labels] = []
+ post api("/projects/#{project.id}/merge_requests", user), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['labels']).to eq([])
+ end
+
+ it 'array with one empty string element does not add labels' do
+ params[:labels] = ['']
+ post api("/projects/#{project.id}/merge_requests", user), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['labels']).to eq([])
+ end
+
+ it 'array with multiple empty string elements, does not add labels' do
+ params[:labels] = ['', '', '']
+ post api("/projects/#{project.id}/merge_requests", user), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['labels']).to eq([])
+ end
end
it "returns 422 when source_branch equals target_branch" do
@@ -629,23 +752,6 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(400)
end
- it 'allows special label names' do
- post api("/projects/#{project.id}/merge_requests", user),
- params: {
- title: 'Test merge_request',
- source_branch: 'markdown',
- target_branch: 'master',
- author: user,
- labels: 'label, label?, label&foo, ?, &'
- }
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
context 'with existing MR' do
before do
post api("/projects/#{project.id}/merge_requests", user),
@@ -698,7 +804,7 @@ describe API::MergeRequests do
let!(:user2) { create(:user) }
let(:project) { create(:project, :public, :repository) }
let!(:forked_project) { fork_project(project, user2, repository: true) }
- let!(:unrelated_project) { create(:project, namespace: create(:user).namespace, creator_id: user2.id) }
+ let!(:unrelated_project) { create(:project, namespace: create(:user).namespace, creator_id: user2.id) }
before do
forked_project.add_reporter(user2)
@@ -939,6 +1045,105 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(404)
end
+
+ describe "the squash_commit_message param" do
+ let(:squash_commit) do
+ project.repository.commits_between(json_response['diff_refs']['start_sha'], json_response['merge_commit_sha']).first
+ end
+
+ it "results in a specific squash commit message when set" do
+ squash_commit_message = 'My custom squash commit message'
+
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), params: {
+ squash: true,
+ squash_commit_message: squash_commit_message
+ }
+
+ expect(squash_commit.message.chomp).to eq(squash_commit_message)
+ end
+
+ it "results in a default squash commit message when not set" do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), params: { squash: true }
+
+ expect(squash_commit.message).to eq(merge_request.default_squash_commit_message)
+ end
+ end
+
+ describe "the should_remove_source_branch param" do
+ let(:source_repository) { merge_request.source_project.repository }
+ let(:source_branch) { merge_request.source_branch }
+
+ it 'removes the source branch when set' do
+ put(
+ api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user),
+ params: { should_remove_source_branch: true }
+ )
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(source_repository.branch_exists?(source_branch)).to be_falsy
+ end
+ end
+ end
+
+ describe "PUT /projects/:id/merge_requests/:merge_request_iid/merge_to_ref" do
+ let(:pipeline) { create(:ci_pipeline_without_jobs) }
+ let(:url) do
+ "/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge_to_ref"
+ end
+
+ it 'returns the generated ID from the merge service in case of success' do
+ put api(url, user), params: { merge_commit_message: 'Custom message' }
+
+ commit = project.commit(json_response['commit_id'])
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['commit_id']).to be_present
+ expect(commit.message).to eq('Custom message')
+ end
+
+ it "returns 400 if branch can't be merged" do
+ merge_request.update!(state: 'merged')
+
+ put api(url, user)
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message'])
+ .to eq("Merge request is not mergeable to #{merge_request.merge_ref_path}")
+ end
+
+ it 'returns 403 if user has no permissions to merge to the ref' do
+ user2 = create(:user)
+ project.add_reporter(user2)
+
+ put api(url, user2)
+
+ expect(response).to have_gitlab_http_status(403)
+ expect(json_response['message']).to eq('403 Forbidden')
+ end
+
+ it 'returns 404 for an invalid merge request IID' do
+ put api("/projects/#{project.id}/merge_requests/12345/merge_to_ref", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it "returns 404 if the merge request id is used instead of iid" do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it "returns 400 when merge method is not supported" do
+ merge_request.project.update!(merge_method: 'ff')
+
+ put api(url, user)
+
+ expected_error =
+ 'Fast-forward to refs/merge-requests/1/merge is currently not supported.'
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq(expected_error)
+ end
end
describe "PUT /projects/:id/merge_requests/:merge_request_iid" do
@@ -989,19 +1194,97 @@ describe API::MergeRequests do
expect(json_response['force_remove_source_branch']).to be_truthy
end
- it 'allows special label names' do
- put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user),
- params: {
- title: 'new issue',
- labels: 'label, label?, label&foo, ?, &'
- }
+ context 'when updating labels' do
+ it 'allows special label names' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user),
+ params: {
+ title: 'new issue',
+ labels: 'label, label?, label&foo, ?, &'
+ }
- expect(response.status).to eq(200)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
+ it 'also accepts labels as an array' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user),
+ params: {
+ title: 'new issue',
+ labels: ['label', 'label?', 'label&foo, ?, &', '1, 2', 3, 4]
+ }
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ expect(json_response['labels']).to include '1'
+ expect(json_response['labels']).to include '2'
+ expect(json_response['labels']).to include '3'
+ expect(json_response['labels']).to include '4'
+ end
+
+ it 'empty label param removes labels' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user),
+ params: {
+ title: 'new issue',
+ labels: ''
+ }
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to eq []
+ end
+
+ it 'label param as empty array, but only explicitly as json, removes labels' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user),
+ params: {
+ title: 'new issue',
+ labels: []
+ }.to_json,
+ headers: { 'Content-Type' => 'application/json' }
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to eq []
+ end
+
+ xit 'empty label as array, removes labels' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user),
+ params: {
+ title: 'new issue',
+ labels: []
+ }
+
+ expect(response.status).to eq(200)
+ # fails, as grape ommits for some reason empty array as optional param value, so nothing it passed along
+ expect(json_response['labels']).to eq []
+ end
+
+ it 'array with one empty string element removes labels' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user),
+ params: {
+ title: 'new issue',
+ labels: ['']
+ }
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to eq []
+ end
+
+ it 'array with multiple empty string elements, removes labels' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user),
+ params: {
+ title: 'new issue',
+ labels: ['', '', '']
+ }
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to eq []
+ end
end
it 'does not update state when title is empty' do
@@ -1189,13 +1472,13 @@ describe API::MergeRequests do
end
it 'returns 404 if the merge request is not found' do
- post api("/projects/#{project.id}/merge_requests/123/merge_when_pipeline_succeeds", user)
+ post api("/projects/#{project.id}/merge_requests/123/cancel_merge_when_pipeline_succeeds", user)
expect(response).to have_gitlab_http_status(404)
end
it 'returns 404 if the merge request id is used instead of iid' do
- post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge_when_pipeline_succeeds", user)
+ post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/cancel_merge_when_pipeline_succeeds", user)
expect(response).to have_gitlab_http_status(404)
end
diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb
index 145356c4df5..2e376109b42 100644
--- a/spec/requests/api/namespaces_spec.rb
+++ b/spec/requests/api/namespaces_spec.rb
@@ -149,7 +149,7 @@ describe API::Namespaces do
context "when namespace doesn't exist" do
it 'returns not-found' do
- get api('/namespaces/9999', request_actor)
+ get api('/namespaces/0', request_actor)
expect(response).to have_gitlab_http_status(404)
end
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 9bf753fe049..424f0a82e43 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe API::Notes do
let(:user) { create(:user) }
let!(:project) { create(:project, :public, namespace: user.namespace) }
- let(:private_user) { create(:user) }
+ let(:private_user) { create(:user) }
before do
project.add_reporter(user)
@@ -46,7 +46,7 @@ describe API::Notes do
create(:project, namespace: private_user.namespace)
.tap { |p| p.add_maintainer(private_user) }
end
- let(:private_issue) { create(:issue, project: private_project) }
+ let(:private_issue) { create(:issue, project: private_project) }
let(:ext_proj) { create(:project, :public) }
let(:ext_issue) { create(:issue, project: ext_proj) }
diff --git a/spec/requests/api/pages/private_access_spec.rb b/spec/requests/api/pages/private_access_spec.rb
index d69c15b0477..c647537038e 100644
--- a/spec/requests/api/pages/private_access_spec.rb
+++ b/spec/requests/api/pages/private_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Private Project Pages Access" do
+describe "Private Project Pages Access" do
using RSpec::Parameterized::TableSyntax
include AccessMatchers
diff --git a/spec/requests/api/pages/public_access_spec.rb b/spec/requests/api/pages/public_access_spec.rb
index 882ca26ac51..16cc5697f30 100644
--- a/spec/requests/api/pages/public_access_spec.rb
+++ b/spec/requests/api/pages/public_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Public Project Pages Access" do
+describe "Public Project Pages Access" do
using RSpec::Parameterized::TableSyntax
include AccessMatchers
diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb
index eb002de62a2..52599db9a9e 100644
--- a/spec/requests/api/pipelines_spec.rb
+++ b/spec/requests/api/pipelines_spec.rb
@@ -456,8 +456,8 @@ describe API::Pipelines do
expect(json_response['message']).to eq '404 Not found'
end
- it 'logs an audit event' do
- expect { delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner) }.to change { SecurityEvent.count }.by(1)
+ it 'does not log an audit event' do
+ expect { delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner) }.not_to change { SecurityEvent.count }
end
context 'when the pipeline has jobs' do
diff --git a/spec/requests/api/project_clusters_spec.rb b/spec/requests/api/project_clusters_spec.rb
new file mode 100644
index 00000000000..9bab1f95150
--- /dev/null
+++ b/spec/requests/api/project_clusters_spec.rb
@@ -0,0 +1,467 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::ProjectClusters do
+ include KubernetesHelpers
+
+ let(:current_user) { create(:user) }
+ let(:non_member) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ describe 'GET /projects/:id/clusters' do
+ let!(:extra_cluster) { create(:cluster, :provided_by_gcp, :project) }
+
+ let!(:clusters) do
+ create_list(:cluster, 5, :provided_by_gcp, :project, :production_environment,
+ projects: [project])
+ end
+
+ context 'non-authorized user' do
+ it 'should respond with 404' do
+ get api("/projects/#{project.id}/clusters", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'authorized user' do
+ before do
+ get api("/projects/#{project.id}/clusters", current_user)
+ end
+
+ it 'should respond with 200' do
+ expect(response).to have_gitlab_http_status(200)
+ end
+
+ it 'should include pagination headers' do
+ expect(response).to include_pagination_headers
+ end
+
+ it 'should only include authorized clusters' do
+ cluster_ids = json_response.map { |cluster| cluster['id'] }
+
+ expect(cluster_ids).to match_array(clusters.pluck(:id))
+ expect(cluster_ids).not_to include(extra_cluster.id)
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/clusters/:cluster_id' do
+ let(:cluster_id) { cluster.id }
+
+ let(:platform_kubernetes) do
+ create(:cluster_platform_kubernetes, :configured,
+ namespace: 'project-namespace')
+ end
+
+ let(:cluster) do
+ create(:cluster, :project, :provided_by_gcp,
+ platform_kubernetes: platform_kubernetes,
+ user: current_user,
+ projects: [project])
+ end
+
+ context 'non-authorized user' do
+ it 'should respond with 404' do
+ get api("/projects/#{project.id}/clusters/#{cluster_id}", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'authorized user' do
+ before do
+ get api("/projects/#{project.id}/clusters/#{cluster_id}", current_user)
+ end
+
+ it 'returns specific cluster' do
+ expect(json_response['id']).to eq(cluster.id)
+ end
+
+ it 'returns cluster information' do
+ expect(json_response['provider_type']).to eq('gcp')
+ expect(json_response['platform_type']).to eq('kubernetes')
+ expect(json_response['environment_scope']).to eq('*')
+ expect(json_response['cluster_type']).to eq('project_type')
+ end
+
+ it 'returns project information' do
+ cluster_project = json_response['project']
+
+ expect(cluster_project['id']).to eq(project.id)
+ expect(cluster_project['name']).to eq(project.name)
+ expect(cluster_project['path']).to eq(project.path)
+ end
+
+ it 'returns kubernetes platform information' do
+ platform = json_response['platform_kubernetes']
+
+ expect(platform['api_url']).to eq('https://kubernetes.example.com')
+ expect(platform['namespace']).to eq('project-namespace')
+ expect(platform['ca_cert']).to be_present
+ end
+
+ it 'returns user information' do
+ user = json_response['user']
+
+ expect(user['id']).to eq(current_user.id)
+ expect(user['username']).to eq(current_user.username)
+ end
+
+ it 'returns GCP provider information' do
+ gcp_provider = json_response['provider_gcp']
+
+ expect(gcp_provider['cluster_id']).to eq(cluster.id)
+ expect(gcp_provider['status_name']).to eq('created')
+ expect(gcp_provider['gcp_project_id']).to eq('test-gcp-project')
+ expect(gcp_provider['zone']).to eq('us-central1-a')
+ expect(gcp_provider['machine_type']).to eq('n1-standard-2')
+ expect(gcp_provider['num_nodes']).to eq(3)
+ expect(gcp_provider['endpoint']).to eq('111.111.111.111')
+ end
+
+ context 'when cluster has no provider' do
+ let(:cluster) do
+ create(:cluster, :project, :provided_by_user,
+ projects: [project])
+ end
+
+ it 'should not include GCP provider info' do
+ expect(json_response['provider_gcp']).not_to be_present
+ end
+ end
+
+ context 'with non-existing cluster' do
+ let(:cluster_id) { 123 }
+
+ it 'returns 404' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+ end
+
+ shared_context 'kubernetes calls stubbed' do
+ before do
+ stub_kubeclient_discover(api_url)
+ stub_kubeclient_get_namespace(api_url, namespace: namespace)
+ stub_kubeclient_get_service_account(api_url, "#{namespace}-service-account", namespace: namespace)
+ stub_kubeclient_put_service_account(api_url, "#{namespace}-service-account", namespace: namespace)
+
+ stub_kubeclient_get_secret(
+ api_url,
+ {
+ metadata_name: "#{namespace}-token",
+ token: Base64.encode64('sample-token'),
+ namespace: namespace
+ }
+ )
+
+ stub_kubeclient_put_secret(api_url, "#{namespace}-token", namespace: namespace)
+ stub_kubeclient_get_role_binding(api_url, "gitlab-#{namespace}", namespace: namespace)
+ stub_kubeclient_put_role_binding(api_url, "gitlab-#{namespace}", namespace: namespace)
+ end
+ end
+
+ describe 'POST /projects/:id/clusters/user' do
+ include_context 'kubernetes calls stubbed'
+
+ let(:api_url) { 'https://kubernetes.example.com' }
+ let(:namespace) { project.path }
+ let(:authorization_type) { 'rbac' }
+
+ let(:platform_kubernetes_attributes) do
+ {
+ api_url: api_url,
+ token: 'sample-token',
+ namespace: namespace,
+ authorization_type: authorization_type
+ }
+ end
+
+ let(:cluster_params) do
+ {
+ name: 'test-cluster',
+ platform_kubernetes_attributes: platform_kubernetes_attributes
+ }
+ end
+
+ context 'non-authorized user' do
+ it 'should respond with 404' do
+ post api("/projects/#{project.id}/clusters/user", non_member), params: cluster_params
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'authorized user' do
+ before do
+ post api("/projects/#{project.id}/clusters/user", current_user), params: cluster_params
+ end
+
+ context 'with valid params' do
+ it 'should respond with 201' do
+ expect(response).to have_gitlab_http_status(201)
+ end
+
+ it 'should create a new Cluster::Cluster' do
+ cluster_result = Clusters::Cluster.find(json_response["id"])
+ platform_kubernetes = cluster_result.platform
+
+ expect(cluster_result).to be_user
+ expect(cluster_result).to be_kubernetes
+ expect(cluster_result.project).to eq(project)
+ expect(cluster_result.name).to eq('test-cluster')
+ expect(platform_kubernetes.rbac?).to be_truthy
+ expect(platform_kubernetes.api_url).to eq(api_url)
+ expect(platform_kubernetes.namespace).to eq(namespace)
+ expect(platform_kubernetes.token).to eq('sample-token')
+ end
+ end
+
+ context 'when user does not indicate authorization type' do
+ let(:platform_kubernetes_attributes) do
+ {
+ api_url: api_url,
+ token: 'sample-token',
+ namespace: namespace
+ }
+ end
+
+ it 'defaults to RBAC' do
+ cluster_result = Clusters::Cluster.find(json_response['id'])
+
+ expect(cluster_result.platform_kubernetes.rbac?).to be_truthy
+ end
+ end
+
+ context 'when user sets authorization type as ABAC' do
+ let(:authorization_type) { 'abac' }
+
+ it 'should create an ABAC cluster' do
+ cluster_result = Clusters::Cluster.find(json_response['id'])
+
+ expect(cluster_result.platform.abac?).to be_truthy
+ end
+ end
+
+ context 'with invalid params' do
+ let(:namespace) { 'invalid_namespace' }
+
+ it 'should respond with 400' do
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'should not create a new Clusters::Cluster' do
+ expect(project.reload.clusters).to be_empty
+ end
+
+ it 'should return validation errors' do
+ expect(json_response['message']['platform_kubernetes.namespace'].first).to be_present
+ end
+ end
+ end
+
+ context 'when user tries to add multiple clusters' do
+ before do
+ create(:cluster, :provided_by_gcp, :project,
+ projects: [project])
+
+ post api("/projects/#{project.id}/clusters/user", current_user), params: cluster_params
+ end
+
+ it 'should respond with 403' do
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ it 'should return an appropriate message' do
+ expect(json_response['message']).to include('Instance does not support multiple Kubernetes clusters')
+ end
+ end
+ end
+
+ describe 'PUT /projects/:id/clusters/:cluster_id' do
+ include_context 'kubernetes calls stubbed'
+
+ let(:api_url) { 'https://kubernetes.example.com' }
+ let(:namespace) { 'new-namespace' }
+ let(:platform_kubernetes_attributes) { { namespace: namespace } }
+
+ let(:update_params) do
+ {
+ platform_kubernetes_attributes: platform_kubernetes_attributes
+ }
+ end
+
+ let!(:kubernetes_namespace) do
+ create(:cluster_kubernetes_namespace,
+ cluster: cluster,
+ project: project)
+ end
+
+ let(:cluster) do
+ create(:cluster, :project, :provided_by_gcp,
+ projects: [project])
+ end
+
+ context 'non-authorized user' do
+ it 'should respond with 404' do
+ put api("/projects/#{project.id}/clusters/#{cluster.id}", non_member), params: update_params
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'authorized user' do
+ before do
+ put api("/projects/#{project.id}/clusters/#{cluster.id}", current_user), params: update_params
+
+ cluster.reload
+ end
+
+ context 'with valid params' do
+ it 'should respond with 200' do
+ expect(response).to have_gitlab_http_status(200)
+ end
+
+ it 'should update cluster attributes' do
+ expect(cluster.platform_kubernetes.namespace).to eq('new-namespace')
+ expect(cluster.kubernetes_namespace.namespace).to eq('new-namespace')
+ end
+ end
+
+ context 'with invalid params' do
+ let(:namespace) { 'invalid_namespace' }
+
+ it 'should respond with 400' do
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'should not update cluster attributes' do
+ expect(cluster.platform_kubernetes.namespace).not_to eq('invalid_namespace')
+ expect(cluster.kubernetes_namespace.namespace).not_to eq('invalid_namespace')
+ end
+
+ it 'should return validation errors' do
+ expect(json_response['message']['platform_kubernetes.namespace'].first).to match('can contain only lowercase letters')
+ end
+ end
+
+ context 'with a GCP cluster' do
+ context 'when user tries to change GCP specific fields' do
+ let(:platform_kubernetes_attributes) do
+ {
+ api_url: 'https://new-api-url.com',
+ token: 'new-sample-token'
+ }
+ end
+
+ it 'should respond with 400' do
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'should return validation error' do
+ expect(json_response['message']['platform_kubernetes.base'].first).to eq('Cannot modify managed Kubernetes cluster')
+ end
+ end
+
+ context 'when user tries to change namespace' do
+ let(:namespace) { 'new-namespace' }
+
+ it 'should respond with 200' do
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+ end
+
+ context 'with an user cluster' do
+ let(:api_url) { 'https://new-api-url.com' }
+
+ let(:cluster) do
+ create(:cluster, :project, :provided_by_user,
+ projects: [project])
+ end
+
+ let(:platform_kubernetes_attributes) do
+ {
+ api_url: api_url,
+ namespace: 'new-namespace',
+ token: 'new-sample-token'
+ }
+ end
+
+ let(:update_params) do
+ {
+ name: 'new-name',
+ platform_kubernetes_attributes: platform_kubernetes_attributes
+ }
+ end
+
+ it 'should respond with 200' do
+ expect(response).to have_gitlab_http_status(200)
+ end
+
+ it 'should update platform kubernetes attributes' do
+ platform_kubernetes = cluster.platform_kubernetes
+
+ expect(cluster.name).to eq('new-name')
+ expect(platform_kubernetes.namespace).to eq('new-namespace')
+ expect(platform_kubernetes.api_url).to eq('https://new-api-url.com')
+ expect(platform_kubernetes.token).to eq('new-sample-token')
+ end
+ end
+
+ context 'with a cluster that does not belong to user' do
+ let(:cluster) { create(:cluster, :project, :provided_by_user) }
+
+ it 'should respond with 404' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/clusters/:cluster_id' do
+ let(:cluster_params) { { cluster_id: cluster.id } }
+
+ let(:cluster) do
+ create(:cluster, :project, :provided_by_gcp,
+ projects: [project])
+ end
+
+ context 'non-authorized user' do
+ it 'should respond with 404' do
+ delete api("/projects/#{project.id}/clusters/#{cluster.id}", non_member), params: cluster_params
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'authorized user' do
+ before do
+ delete api("/projects/#{project.id}/clusters/#{cluster.id}", current_user), params: cluster_params
+ end
+
+ it 'should respond with 204' do
+ expect(response).to have_gitlab_http_status(204)
+ end
+
+ it 'should delete the cluster' do
+ expect(Clusters::Cluster.exists?(id: cluster.id)).to be_falsy
+ end
+
+ context 'with a cluster that does not belong to user' do
+ let(:cluster) { create(:cluster, :project, :provided_by_user) }
+
+ it 'should respond with 404' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/project_milestones_spec.rb b/spec/requests/api/project_milestones_spec.rb
index 0fa13dd71e2..895f05a98e8 100644
--- a/spec/requests/api/project_milestones_spec.rb
+++ b/spec/requests/api/project_milestones_spec.rb
@@ -10,7 +10,7 @@ describe API::ProjectMilestones do
project.add_developer(user)
end
- it_behaves_like 'group and project milestones', "/projects/:id/milestones" do
+ it_behaves_like 'group and project milestones', "/projects/:id/milestones" do
let(:route) { "/projects/#{project.id}/milestones" }
end
@@ -23,13 +23,13 @@ describe API::ProjectMilestones do
end
it 'returns 404 response when the project does not exists' do
- delete api("/projects/999/milestones/#{milestone.id}", user)
+ delete api("/projects/0/milestones/#{milestone.id}", user)
expect(response).to have_gitlab_http_status(404)
end
it 'returns 404 response when the milestone does not exists' do
- delete api("/projects/#{project.id}/milestones/999", user)
+ delete api("/projects/#{project.id}/milestones/0", user)
expect(response).to have_gitlab_http_status(404)
end
@@ -49,4 +49,74 @@ describe API::ProjectMilestones do
params: { state_event: 'close' }
end
end
+
+ describe 'POST /projects/:id/milestones/:milestone_id/promote' do
+ let(:group) { create(:group) }
+
+ before do
+ project.update(namespace: group)
+ end
+
+ context 'when user does not have permission to promote milestone' do
+ before do
+ group.add_guest(user)
+ end
+
+ it 'returns 403' do
+ post api("/projects/#{project.id}/milestones/#{milestone.id}/promote", user)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ context 'when user has permission' do
+ before do
+ group.add_developer(user)
+ end
+
+ it 'returns 200' do
+ post api("/projects/#{project.id}/milestones/#{milestone.id}/promote", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(group.milestones.first.title).to eq(milestone.title)
+ end
+
+ it 'returns 200 for closed milestone' do
+ post api("/projects/#{project.id}/milestones/#{closed_milestone.id}/promote", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(group.milestones.first.title).to eq(closed_milestone.title)
+ end
+ end
+
+ context 'when no such resources' do
+ before do
+ group.add_developer(user)
+ end
+
+ it 'returns 404 response when the project does not exist' do
+ post api("/projects/0/milestones/#{milestone.id}/promote", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 response when the milestone does not exist' do
+ post api("/projects/#{project.id}/milestones/0/promote", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when project does not belong to group' do
+ before do
+ project.update(namespace: user.namespace)
+ end
+
+ it 'returns 403' do
+ post api("/projects/#{project.id}/milestones/#{milestone.id}/promote", user)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+ end
end
diff --git a/spec/requests/api/project_statistics_spec.rb b/spec/requests/api/project_statistics_spec.rb
new file mode 100644
index 00000000000..184d0a72c37
--- /dev/null
+++ b/spec/requests/api/project_statistics_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::ProjectStatistics do
+ let(:maintainer) { create(:user) }
+ let(:public_project) { create(:project, :public) }
+
+ before do
+ public_project.add_maintainer(maintainer)
+ end
+
+ describe 'GET /projects/:id/statistics' do
+ let!(:fetch_statistics1) { create(:project_daily_statistic, project: public_project, fetch_count: 30, date: 29.days.ago) }
+ let!(:fetch_statistics2) { create(:project_daily_statistic, project: public_project, fetch_count: 4, date: 3.days.ago) }
+ let!(:fetch_statistics3) { create(:project_daily_statistic, project: public_project, fetch_count: 3, date: 2.days.ago) }
+ let!(:fetch_statistics4) { create(:project_daily_statistic, project: public_project, fetch_count: 2, date: 1.day.ago) }
+ let!(:fetch_statistics5) { create(:project_daily_statistic, project: public_project, fetch_count: 1, date: Date.today) }
+ let!(:fetch_statistics_other_project) { create(:project_daily_statistic, project: create(:project), fetch_count: 29, date: 29.days.ago) }
+
+ it 'returns the fetch statistics of the last 30 days' do
+ get api("/projects/#{public_project.id}/statistics", maintainer)
+
+ expect(response).to have_gitlab_http_status(200)
+ fetches = json_response['fetches']
+ expect(fetches['total']).to eq(40)
+ expect(fetches['days'].length).to eq(5)
+ expect(fetches['days'].first).to eq({ 'count' => fetch_statistics5.fetch_count, 'date' => fetch_statistics5.date.to_s })
+ expect(fetches['days'].last).to eq({ 'count' => fetch_statistics1.fetch_count, 'date' => fetch_statistics1.date.to_s })
+ end
+
+ it 'excludes the fetch statistics older than 30 days' do
+ create(:project_daily_statistic, fetch_count: 31, project: public_project, date: 30.days.ago)
+
+ get api("/projects/#{public_project.id}/statistics", maintainer)
+
+ expect(response).to have_gitlab_http_status(200)
+ fetches = json_response['fetches']
+ expect(fetches['total']).to eq(40)
+ expect(fetches['days'].length).to eq(5)
+ expect(fetches['days'].last).to eq({ 'count' => fetch_statistics1.fetch_count, 'date' => fetch_statistics1.date.to_s })
+ end
+
+ it 'responds with 403 when the user is not a maintainer of the repository' do
+ developer = create(:user)
+ public_project.add_developer(developer)
+
+ get api("/projects/#{public_project.id}/statistics", developer)
+
+ expect(response).to have_gitlab_http_status(403)
+ expect(json_response['message']).to eq('403 Forbidden')
+ end
+
+ it 'responds with 404 when daily_statistics_enabled? is false' do
+ stub_feature_flags(project_daily_statistics: { thing: public_project, enabled: false })
+
+ get api("/projects/#{public_project.id}/statistics", maintainer)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+end
diff --git a/spec/requests/api/project_templates_spec.rb b/spec/requests/api/project_templates_spec.rb
index ab5d4de7ff7..80e5033dab4 100644
--- a/spec/requests/api/project_templates_spec.rb
+++ b/spec/requests/api/project_templates_spec.rb
@@ -92,6 +92,22 @@ describe API::ProjectTemplates do
expect(json_response['name']).to eq('Actionscript')
end
+ it 'returns C++ gitignore' do
+ get api("/projects/#{public_project.id}/templates/gitignores/C++")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/template')
+ expect(json_response['name']).to eq('C++')
+ end
+
+ it 'returns C++ gitignore for URL-encoded names' do
+ get api("/projects/#{public_project.id}/templates/gitignores/C%2B%2B")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/template')
+ expect(json_response['name']).to eq('C++')
+ end
+
it 'returns a specific gitlab_ci_yml' do
get api("/projects/#{public_project.id}/templates/gitlab_ci_ymls/Android")
@@ -125,6 +141,18 @@ describe API::ProjectTemplates do
expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/license')
end
+
+ shared_examples 'path traversal attempt' do |template_type|
+ it 'rejects invalid filenames' do
+ get api("/projects/#{public_project.id}/templates/#{template_type}/%2e%2e%2fPython%2ea")
+
+ expect(response).to have_gitlab_http_status(500)
+ end
+ end
+
+ TemplateFinder::VENDORED_TEMPLATES.each do |template_type, _|
+ it_behaves_like 'path traversal attempt', template_type
+ end
end
describe 'GET /projects/:id/templates/licenses/:key' do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index ffe4512fa6f..60d9d7fed13 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -4,6 +4,15 @@ require 'spec_helper'
shared_examples 'languages and percentages JSON response' do
let(:expected_languages) { project.repository.languages.map { |language| language.values_at(:label, :value)}.to_h }
+ before do
+ allow(project.repository).to receive(:languages).and_return(
+ [{ value: 66.69, label: "Ruby", color: "#701516", highlight: "#701516" },
+ { value: 22.98, label: "JavaScript", color: "#f1e05a", highlight: "#f1e05a" },
+ { value: 7.91, label: "HTML", color: "#e34c26", highlight: "#e34c26" },
+ { value: 2.42, label: "CoffeeScript", color: "#244776", highlight: "#244776" }]
+ )
+ end
+
it 'returns expected language values' do
get api("/projects/#{project.id}/languages", user)
@@ -11,6 +20,23 @@ shared_examples 'languages and percentages JSON response' do
expect(json_response).to eq(expected_languages)
expect(json_response.count).to be > 1
end
+
+ context 'when the languages were detected before' do
+ before do
+ Projects::DetectRepositoryLanguagesService.new(project, project.owner).execute
+ end
+
+ it 'returns the detection from the database' do
+ # Allow this to happen once, so the expected languages can be determined
+ expect(project.repository).to receive(:languages).once
+
+ get api("/projects/#{project.id}/languages", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq(expected_languages)
+ expect(json_response.count).to be > 1
+ end
+ end
end
describe API::Projects do
@@ -21,7 +47,7 @@ describe API::Projects do
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:project2) { create(:project, namespace: user.namespace) }
let(:project_member) { create(:project_member, :developer, user: user3, project: project) }
- let(:user4) { create(:user) }
+ let(:user4) { create(:user, username: 'user.with.dot') }
let(:project3) do
create(:project,
:private,
@@ -49,6 +75,27 @@ describe API::Projects do
namespace: user4.namespace)
end
+ shared_context 'with language detection' do
+ let(:ruby) { create(:programming_language, name: 'Ruby') }
+ let(:javascript) { create(:programming_language, name: 'JavaScript') }
+ let(:html) { create(:programming_language, name: 'HTML') }
+
+ let(:mock_repo_languages) do
+ {
+ project => { ruby => 0.5, html => 0.5 },
+ project3 => { html => 0.7, javascript => 0.3 }
+ }
+ end
+
+ before do
+ mock_repo_languages.each do |proj, lang_shares|
+ lang_shares.each do |lang, share|
+ create(:repository_language, project: proj, programming_language: lang, share: share)
+ end
+ end
+ end
+ end
+
describe 'GET /projects' do
shared_examples_for 'projects response' do
it 'returns an array of projects' do
@@ -89,6 +136,7 @@ describe API::Projects do
end
let!(:public_project) { create(:project, :public, name: 'public_project') }
+
before do
project
project2
@@ -344,6 +392,19 @@ describe API::Projects do
end
end
+ context 'and using the programming language filter' do
+ include_context 'with language detection'
+
+ it 'filters case-insensitively by programming language' do
+ get api('/projects', user), params: { with_programming_language: 'javascript' }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |p| p['id'] }).to contain_exactly(project3.id)
+ end
+ end
+
context 'and using sorting' do
it 'returns the correct order when sorted by id' do
get api('/projects', user), params: { order_by: 'id', sort: 'desc' }
@@ -718,13 +779,13 @@ describe API::Projects do
let!(:public_project) { create(:project, :public, name: 'public_project', creator_id: user4.id, namespace: user4.namespace) }
it 'returns error when user not found' do
- get api('/users/9999/projects/')
+ get api('/users/0/projects/')
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
- it 'returns projects filtered by user' do
+ it 'returns projects filtered by user id' do
get api("/users/#{user4.id}/projects/", user)
expect(response).to have_gitlab_http_status(200)
@@ -733,6 +794,15 @@ describe API::Projects do
expect(json_response.map { |project| project['id'] }).to contain_exactly(public_project.id)
end
+ it 'returns projects filtered by username' do
+ get api("/users/#{user4.username}/projects/", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |project| project['id'] }).to contain_exactly(public_project.id)
+ end
+
it 'returns projects filtered by minimal access level' do
private_project1 = create(:project, :private, name: 'private_project1', creator_id: user4.id, namespace: user4.namespace)
private_project2 = create(:project, :private, name: 'private_project2', creator_id: user4.id, namespace: user4.namespace)
@@ -746,6 +816,19 @@ describe API::Projects do
expect(json_response).to be_an Array
expect(json_response.map { |project| project['id'] }).to contain_exactly(private_project1.id)
end
+
+ context 'and using the programming language filter' do
+ include_context 'with language detection'
+
+ it 'filters case-insensitively by programming language' do
+ get api('/projects', user), params: { with_programming_language: 'ruby' }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |p| p['id'] }).to contain_exactly(project.id)
+ end
+ end
end
describe 'POST /projects/user/:id' do
@@ -886,8 +969,16 @@ describe API::Projects do
describe 'GET /projects/:id' do
context 'when unauthenticated' do
- it 'returns the public projects' do
- public_project = create(:project, :public)
+ it 'does not return private projects' do
+ private_project = create(:project, :private)
+
+ get api("/projects/#{private_project.id}")
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns public projects' do
+ public_project = create(:project, :repository, :public)
get api("/projects/#{public_project.id}")
@@ -895,8 +986,34 @@ describe API::Projects do
expect(json_response['id']).to eq(public_project.id)
expect(json_response['description']).to eq(public_project.description)
expect(json_response['default_branch']).to eq(public_project.default_branch)
+ expect(json_response['ci_config_path']).to eq(public_project.ci_config_path)
expect(json_response.keys).not_to include('permissions')
end
+
+ context 'and the project has a private repository' do
+ let(:project) { create(:project, :repository, :public, :repository_private) }
+ let(:protected_attributes) { %w(default_branch ci_config_path) }
+
+ it 'hides protected attributes of private repositories if user is not a member' do
+ get api("/projects/#{project.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ protected_attributes.each do |attribute|
+ expect(json_response.keys).not_to include(attribute)
+ end
+ end
+
+ it 'exposes protected attributes of private repositories if user is a member' do
+ project.add_developer(user)
+
+ get api("/projects/#{project.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ protected_attributes.each do |attribute|
+ expect(json_response.keys).to include(attribute)
+ end
+ end
+ end
end
context 'when authenticated' do
@@ -948,6 +1065,7 @@ describe API::Projects do
expect(json_response['shared_with_groups'].length).to eq(1)
expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
+ expect(json_response['shared_with_groups'][0]['group_full_path']).to eq(group.full_path)
expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
expect(json_response['shared_with_groups'][0]['expires_at']).to be_nil
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds)
@@ -967,6 +1085,7 @@ describe API::Projects do
expect(json_response['shared_with_groups'].length).to eq(1)
expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
+ expect(json_response['shared_with_groups'][0]['group_full_path']).to eq(group.full_path)
expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
expect(json_response['shared_with_groups'][0]['expires_at']).to eq(expires_at.to_s)
end
@@ -1046,6 +1165,26 @@ describe API::Projects do
expect(json_response).to include 'statistics'
end
+ context "and the project has a private repository" do
+ let(:project) { create(:project, :public, :repository, :repository_private) }
+
+ it "does not include statistics if user is not a member" do
+ get api("/projects/#{project.id}", user), params: { statistics: true }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).not_to include 'statistics'
+ end
+
+ it "includes statistics if user is a member" do
+ project.add_developer(user)
+
+ get api("/projects/#{project.id}", user), params: { statistics: true }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to include 'statistics'
+ end
+ end
+
it "includes import_error if user can admin project" do
get api("/projects/#{project.id}", user)
@@ -1145,6 +1284,40 @@ describe API::Projects do
.to eq(Gitlab::Access::OWNER)
end
end
+
+ context 'nested group project', :nested_groups do
+ let(:group) { create(:group) }
+ let(:nested_group) { create(:group, parent: group) }
+ let(:project2) { create(:project, group: nested_group) }
+
+ before do
+ project2.group.parent.add_owner(user)
+ end
+
+ it 'sets group access and return 200' do
+ get api("/projects/#{project2.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['permissions']['project_access']).to be_nil
+ expect(json_response['permissions']['group_access']['access_level'])
+ .to eq(Gitlab::Access::OWNER)
+ end
+
+ context 'with various access levels across nested groups' do
+ before do
+ project2.group.add_maintainer(user)
+ end
+
+ it 'sets the maximum group access and return 200' do
+ get api("/projects/#{project2.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['permissions']['project_access']).to be_nil
+ expect(json_response['permissions']['group_access']['access_level'])
+ .to eq(Gitlab::Access::OWNER)
+ end
+ end
+ end
end
end
end
@@ -1267,7 +1440,7 @@ describe API::Projects do
end
it 'fails if forked_from project which does not exist' do
- post api("/projects/#{project_fork_target.id}/fork/9999", admin)
+ post api("/projects/#{project_fork_target.id}/fork/0", admin)
expect(response).to have_gitlab_http_status(404)
end
@@ -1392,6 +1565,9 @@ describe API::Projects do
describe "POST /projects/:id/share" do
let(:group) { create(:group) }
+ before do
+ group.add_developer(user)
+ end
it "shares project with group" do
expires_at = 10.days.from_now.to_date
@@ -1442,6 +1618,15 @@ describe API::Projects do
expect(response).to have_gitlab_http_status(400)
expect(json_response['error']).to eq 'group_access does not have a valid value'
end
+
+ it "returns a 409 error when link is not saved" do
+ allow(::Projects::GroupLinks::CreateService).to receive_message_chain(:new, :execute)
+ .and_return({ status: :error, http_status: 409, message: 'error' })
+
+ post api("/projects/#{project.id}/share", user), params: { group_id: group.id, group_access: Gitlab::Access::DEVELOPER }
+
+ expect(response).to have_gitlab_http_status(409)
+ end
end
describe 'DELETE /projects/:id/share/:group_id' do
@@ -1818,7 +2003,7 @@ describe API::Projects do
end
it 'returns not_found(404) for not existing project' do
- get api("/projects/9999999999/languages", user)
+ get api("/projects/0/languages", user)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -1903,6 +2088,11 @@ describe API::Projects do
let(:project) do
create(:project, :repository, creator: user, namespace: user.namespace)
end
+
+ let(:project2) do
+ create(:project, :repository, creator: user, namespace: user.namespace)
+ end
+
let(:group) { create(:group) }
let(:group2) do
group = create(:group, name: 'group2_name')
@@ -1918,6 +2108,7 @@ describe API::Projects do
before do
project.add_reporter(user2)
+ project2.add_reporter(user2)
end
context 'when authenticated' do
@@ -2032,6 +2223,48 @@ describe API::Projects do
expect(response).to have_gitlab_http_status(201)
expect(json_response['namespace']['name']).to eq(group.name)
end
+
+ it 'accepts a path for the target project' do
+ post api("/projects/#{project.id}/fork", user2), params: { path: 'foobar' }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['name']).to eq(project.name)
+ expect(json_response['path']).to eq('foobar')
+ expect(json_response['owner']['id']).to eq(user2.id)
+ expect(json_response['namespace']['id']).to eq(user2.namespace.id)
+ expect(json_response['forked_from_project']['id']).to eq(project.id)
+ expect(json_response['import_status']).to eq('scheduled')
+ expect(json_response).to include("import_error")
+ end
+
+ it 'fails to fork if path is already taken' do
+ post api("/projects/#{project.id}/fork", user2), params: { path: 'foobar' }
+ post api("/projects/#{project2.id}/fork", user2), params: { path: 'foobar' }
+
+ expect(response).to have_gitlab_http_status(409)
+ expect(json_response['message']['path']).to eq(['has already been taken'])
+ end
+
+ it 'accepts a name for the target project' do
+ post api("/projects/#{project.id}/fork", user2), params: { name: 'My Random Project' }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['name']).to eq('My Random Project')
+ expect(json_response['path']).to eq(project.path)
+ expect(json_response['owner']['id']).to eq(user2.id)
+ expect(json_response['namespace']['id']).to eq(user2.namespace.id)
+ expect(json_response['forked_from_project']['id']).to eq(project.id)
+ expect(json_response['import_status']).to eq('scheduled')
+ expect(json_response).to include("import_error")
+ end
+
+ it 'fails to fork if name is already taken' do
+ post api("/projects/#{project.id}/fork", user2), params: { name: 'My Random Project' }
+ post api("/projects/#{project2.id}/fork", user2), params: { name: 'My Random Project' }
+
+ expect(response).to have_gitlab_http_status(409)
+ expect(json_response['message']['name']).to eq(['has already been taken'])
+ end
end
context 'when unauthenticated' do
diff --git a/spec/requests/api/release/links_spec.rb b/spec/requests/api/release/links_spec.rb
new file mode 100644
index 00000000000..3a59052bb29
--- /dev/null
+++ b/spec/requests/api/release/links_spec.rb
@@ -0,0 +1,375 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::Release::Links do
+ let(:project) { create(:project, :repository, :private) }
+ let(:maintainer) { create(:user) }
+ let(:reporter) { create(:user) }
+ let(:non_project_member) { create(:user) }
+ let(:commit) { create(:commit, project: project) }
+
+ let!(:release) do
+ create(:release,
+ project: project,
+ tag: 'v0.1',
+ author: maintainer)
+ end
+
+ before do
+ project.add_maintainer(maintainer)
+ project.add_reporter(reporter)
+
+ project.repository.add_tag(maintainer, 'v0.1', commit.id)
+ end
+
+ describe 'GET /projects/:id/releases/:tag_name/assets/links' do
+ context 'when there are two release links' do
+ let!(:release_link_1) { create(:release_link, release: release, created_at: 2.days.ago) }
+ let!(:release_link_2) { create(:release_link, release: release, created_at: 1.day.ago) }
+
+ it 'returns 200 HTTP status' do
+ get api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'returns release links ordered by created_at' do
+ get api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer)
+
+ expect(json_response.count).to eq(2)
+ expect(json_response.first['name']).to eq(release_link_2.name)
+ expect(json_response.second['name']).to eq(release_link_1.name)
+ end
+
+ it 'matches response schema' do
+ get api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer)
+
+ expect(response).to match_response_schema('release/links')
+ end
+ end
+
+ context 'when release does not exist' do
+ let!(:release) { }
+
+ it_behaves_like '404 response' do
+ let(:request) { get api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer) }
+ let(:message) { '404 Not found' }
+ end
+ end
+
+ context 'when user is not a project member' do
+ it_behaves_like '404 response' do
+ let(:request) { get api("/projects/#{project.id}/releases/v0.1/assets/links", non_project_member) }
+ let(:message) { '404 Project Not Found' }
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it 'allows the request' do
+ get api("/projects/#{project.id}/releases/v0.1/assets/links", non_project_member)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when project is public and the repository is private' do
+ let(:project) { create(:project, :repository, :public, :repository_private) }
+
+ it_behaves_like '403 response' do
+ let(:request) { get api("/projects/#{project.id}/releases/v0.1/assets/links", non_project_member) }
+ end
+
+ context 'when the release does not exists' do
+ let!(:release) { }
+
+ it_behaves_like '403 response' do
+ let(:request) { get api("/projects/#{project.id}/releases/v0.1/assets/links", non_project_member) }
+ end
+ end
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/releases/:tag_name/assets/links/:link_id' do
+ let!(:release_link) { create(:release_link, release: release) }
+
+ it 'returns 200 HTTP status' do
+ get api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'returns a link entry' do
+ get api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer)
+
+ expect(json_response['name']).to eq(release_link.name)
+ expect(json_response['url']).to eq(release_link.url)
+ end
+
+ it 'matches response schema' do
+ get api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer)
+
+ expect(response).to match_response_schema('release/link')
+ end
+
+ context 'when specified tag is not found in the project' do
+ it_behaves_like '404 response' do
+ let(:request) { get api("/projects/#{project.id}/releases/non_existing_tag/assets/links/#{release_link.id}", maintainer) }
+ end
+ end
+
+ context 'when user is not a project member' do
+ it_behaves_like '404 response' do
+ let(:request) { get api("/projects/#{project.id}/releases/non_existing_tag/assets/links/#{release_link.id}", non_project_member) }
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it 'allows the request' do
+ get api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", non_project_member)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+ end
+
+ describe 'POST /projects/:id/releases/:tag_name/assets/links' do
+ let(:params) do
+ {
+ name: 'awesome-app.dmg',
+ url: 'https://example.com/download/awesome-app.dmg'
+ }
+ end
+
+ it 'accepts the request' do
+ post api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+
+ it 'creates a new release' do
+ expect do
+ post api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer), params: params
+ end.to change { Releases::Link.count }.by(1)
+
+ release.reload
+ expect(release.links.last.name).to eq('awesome-app.dmg')
+ expect(release.links.last.url).to eq('https://example.com/download/awesome-app.dmg')
+ end
+
+ it 'matches response schema' do
+ post api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer), params: params
+
+ expect(response).to match_response_schema('release/link')
+ end
+
+ context 'when name is empty' do
+ let(:params) do
+ {
+ name: '',
+ url: 'https://example.com/download/awesome-app.dmg'
+ }
+ end
+
+ it_behaves_like '400 response' do
+ let(:request) do
+ post api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer),
+ params: params
+ end
+ end
+ end
+
+ context 'when user is a reporter' do
+ it_behaves_like '403 response' do
+ let(:request) do
+ post api("/projects/#{project.id}/releases/v0.1/assets/links", reporter),
+ params: params
+ end
+ end
+ end
+
+ context 'when user is not a project member' do
+ it 'forbids the request' do
+ post api("/projects/#{project.id}/releases/v0.1/assets/links", non_project_member),
+ params: params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it 'forbids the request' do
+ post api("/projects/#{project.id}/releases/v0.1/assets/links", non_project_member),
+ params: params
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+
+ context 'when the same link already exists' do
+ before do
+ create(:release_link,
+ release: release,
+ name: 'awesome-app.dmg',
+ url: 'https://example.com/download/awesome-app.dmg')
+ end
+
+ it_behaves_like '400 response' do
+ let(:request) do
+ post api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer),
+ params: params
+ end
+ end
+ end
+ end
+
+ describe 'PUT /projects/:id/releases/:tag_name/assets/links/:link_id' do
+ let(:params) { { name: 'awesome-app.msi' } }
+ let!(:release_link) { create(:release_link, release: release) }
+
+ it 'accepts the request' do
+ put api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer),
+ params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'updates the name' do
+ put api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer),
+ params: params
+
+ expect(json_response['name']).to eq('awesome-app.msi')
+ end
+
+ it 'does not update the url' do
+ put api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer),
+ params: params
+
+ expect(json_response['url']).to eq(release_link.url)
+ end
+
+ it 'matches response schema' do
+ put api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer),
+ params: params
+
+ expect(response).to match_response_schema('release/link')
+ end
+
+ context 'when params is empty' do
+ let(:params) { {} }
+
+ it 'does not allow the request' do
+ put api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer),
+ params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'when there are no corresponding release link' do
+ let!(:release_link) { }
+
+ it_behaves_like '404 response' do
+ let(:request) do
+ put api("/projects/#{project.id}/releases/v0.1/assets/links/1", maintainer),
+ params: params
+ end
+ end
+ end
+
+ context 'when user is a reporter' do
+ it_behaves_like '403 response' do
+ let(:request) do
+ put api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", reporter),
+ params: params
+ end
+ end
+ end
+
+ context 'when user is not a project member' do
+ it_behaves_like '404 response' do
+ let(:request) do
+ put api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", non_project_member),
+ params: params
+ end
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it_behaves_like '403 response' do
+ let(:request) do
+ put api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", non_project_member),
+ params: params
+ end
+ end
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/releases/:tag_name/assets/links/:link_id' do
+ let!(:release_link) do
+ create(:release_link, release: release)
+ end
+
+ it 'accepts the request' do
+ delete api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'destroys the release link' do
+ expect do
+ delete api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer)
+ end.to change { Releases::Link.count }.by(-1)
+ end
+
+ it 'matches response schema' do
+ delete api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", maintainer)
+
+ expect(response).to match_response_schema('release/link')
+ end
+
+ context 'when there are no corresponding release link' do
+ let!(:release_link) { }
+
+ it_behaves_like '404 response' do
+ let(:request) do
+ delete api("/projects/#{project.id}/releases/v0.1/assets/links/1", maintainer)
+ end
+ end
+ end
+
+ context 'when user is a reporter' do
+ it_behaves_like '403 response' do
+ let(:request) do
+ delete api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", reporter)
+ end
+ end
+ end
+
+ context 'when user is not a project member' do
+ it_behaves_like '404 response' do
+ let(:request) do
+ delete api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", non_project_member)
+ end
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it_behaves_like '403 response' do
+ let(:request) do
+ delete api("/projects/#{project.id}/releases/v0.1/assets/links/#{release_link.id}", non_project_member)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
new file mode 100644
index 00000000000..1f317971a66
--- /dev/null
+++ b/spec/requests/api/releases_spec.rb
@@ -0,0 +1,628 @@
+require 'spec_helper'
+
+describe API::Releases do
+ let(:project) { create(:project, :repository, :private) }
+ let(:maintainer) { create(:user) }
+ let(:reporter) { create(:user) }
+ let(:non_project_member) { create(:user) }
+ let(:commit) { create(:commit, project: project) }
+
+ before do
+ project.add_maintainer(maintainer)
+ project.add_reporter(reporter)
+
+ project.repository.add_tag(maintainer, 'v0.1', commit.id)
+ project.repository.add_tag(maintainer, 'v0.2', commit.id)
+ end
+
+ describe 'GET /projects/:id/releases' do
+ context 'when there are two releases' do
+ let!(:release_1) do
+ create(:release,
+ project: project,
+ tag: 'v0.1',
+ author: maintainer,
+ created_at: 2.days.ago)
+ end
+
+ let!(:release_2) do
+ create(:release,
+ project: project,
+ tag: 'v0.2',
+ author: maintainer,
+ created_at: 1.day.ago)
+ end
+
+ it 'returns 200 HTTP status' do
+ get api("/projects/#{project.id}/releases", maintainer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'returns releases ordered by created_at' do
+ get api("/projects/#{project.id}/releases", maintainer)
+
+ expect(json_response.count).to eq(2)
+ expect(json_response.first['tag_name']).to eq(release_2.tag)
+ expect(json_response.second['tag_name']).to eq(release_1.tag)
+ end
+
+ it 'matches response schema' do
+ get api("/projects/#{project.id}/releases", maintainer)
+
+ expect(response).to match_response_schema('releases')
+ end
+ end
+
+ context 'when tag does not exist in git repository' do
+ let!(:release) { create(:release, project: project, tag: 'v1.1.5') }
+
+ it 'returns the tag' do
+ get api("/projects/#{project.id}/releases", maintainer)
+
+ expect(json_response.count).to eq(1)
+ expect(json_response.first['tag_name']).to eq('v1.1.5')
+ expect(release).to be_tag_missing
+ end
+ end
+
+ context 'when user is not a project member' do
+ it 'cannot find the project' do
+ get api("/projects/#{project.id}/releases", non_project_member)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it 'allows the request' do
+ get api("/projects/#{project.id}/releases", non_project_member)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/releases/:tag_name' do
+ context 'when there is a release' do
+ let!(:release) do
+ create(:release,
+ project: project,
+ tag: 'v0.1',
+ sha: commit.id,
+ author: maintainer,
+ description: 'This is v0.1')
+ end
+
+ it 'returns 200 HTTP status' do
+ get api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'returns a release entry' do
+ get api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(json_response['tag_name']).to eq(release.tag)
+ expect(json_response['description']).to eq('This is v0.1')
+ expect(json_response['author']['name']).to eq(maintainer.name)
+ expect(json_response['commit']['id']).to eq(commit.id)
+ expect(json_response['assets']['count']).to eq(4)
+ end
+
+ it 'matches response schema' do
+ get api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(response).to match_response_schema('release')
+ end
+
+ it 'contains source information as assets' do
+ get api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(json_response['assets']['sources'].map { |h| h['format'] })
+ .to match_array(release.sources.map(&:format))
+ expect(json_response['assets']['sources'].map { |h| h['url'] })
+ .to match_array(release.sources.map(&:url))
+ end
+
+ context "when release description contains confidential issue's link" do
+ let(:confidential_issue) do
+ create(:issue,
+ :confidential,
+ project: project,
+ title: 'A vulnerability')
+ end
+
+ let!(:release) do
+ create(:release,
+ project: project,
+ tag: 'v0.1',
+ sha: commit.id,
+ author: maintainer,
+ description: "This is confidential #{confidential_issue.to_reference}")
+ end
+
+ it "does not expose confidential issue's title" do
+ get api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(json_response['description_html']).to include(confidential_issue.to_reference)
+ expect(json_response['description_html']).not_to include('A vulnerability')
+ end
+ end
+
+ context 'when release has link asset' do
+ let!(:link) do
+ create(:release_link,
+ release: release,
+ name: 'release-18.04.dmg',
+ url: url)
+ end
+
+ let(:url) { 'https://my-external-hosting.example.com/scrambled-url/app.zip' }
+
+ it 'contains link information as assets' do
+ get api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(json_response['assets']['links'].count).to eq(1)
+ expect(json_response['assets']['links'].first['id']).to eq(link.id)
+ expect(json_response['assets']['links'].first['name'])
+ .to eq('release-18.04.dmg')
+ expect(json_response['assets']['links'].first['url'])
+ .to eq('https://my-external-hosting.example.com/scrambled-url/app.zip')
+ expect(json_response['assets']['links'].first['external'])
+ .to be_truthy
+ end
+
+ context 'when link is internal' do
+ let(:url) do
+ "#{project.web_url}/-/jobs/artifacts/v11.6.0-rc4/download?" \
+ "job=rspec-mysql+41%2F50"
+ end
+
+ it 'has external false' do
+ get api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(json_response['assets']['links'].first['external'])
+ .to be_falsy
+ end
+ end
+ end
+ end
+
+ context 'when specified tag is not found in the project' do
+ it 'cannot find the release entry' do
+ get api("/projects/#{project.id}/releases/non_exist_tag", maintainer)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when user is not a project member' do
+ let!(:release) { create(:release, tag: 'v0.1', project: project) }
+
+ it 'cannot find the project' do
+ get api("/projects/#{project.id}/releases/v0.1", non_project_member)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it 'allows the request' do
+ get api("/projects/#{project.id}/releases/v0.1", non_project_member)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+ end
+
+ describe 'POST /projects/:id/releases' do
+ let(:params) do
+ {
+ name: 'New release',
+ tag_name: 'v0.1',
+ description: 'Super nice release'
+ }
+ end
+
+ it 'accepts the request' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+
+ it 'creates a new release' do
+ expect do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+ end.to change { Release.count }.by(1)
+
+ expect(project.releases.last.name).to eq('New release')
+ expect(project.releases.last.tag).to eq('v0.1')
+ expect(project.releases.last.description).to eq('Super nice release')
+ end
+
+ context 'when description is empty' do
+ let(:params) do
+ {
+ name: 'New release',
+ tag_name: 'v0.1',
+ description: ''
+ }
+ end
+
+ it 'returns an error as validation failure' do
+ expect do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+ end.not_to change { Release.count }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message'])
+ .to eq("Validation failed: Description can't be blank")
+ end
+ end
+
+ it 'matches response schema' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(response).to match_response_schema('release')
+ end
+
+ it 'does not create a new tag' do
+ expect do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+ end.not_to change { Project.find_by_id(project.id).repository.tag_count }
+ end
+
+ context 'when user is a reporter' do
+ it 'forbids the request' do
+ post api("/projects/#{project.id}/releases", reporter), params: params
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when user is not a project member' do
+ it 'forbids the request' do
+ post api("/projects/#{project.id}/releases", non_project_member),
+ params: params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it 'forbids the request' do
+ post api("/projects/#{project.id}/releases", non_project_member),
+ params: params
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when create assets altogether' do
+ let(:base_params) do
+ {
+ name: 'New release',
+ tag_name: 'v0.1',
+ description: 'Super nice release'
+ }
+ end
+
+ context 'when create one asset' do
+ let(:params) do
+ base_params.merge({
+ assets: {
+ links: [{ name: 'beta', url: 'https://dosuken.example.com/inspection.exe' }]
+ }
+ })
+ end
+
+ it 'accepts the request' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+
+ it 'creates an asset with specified parameters' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(json_response['assets']['links'].count).to eq(1)
+ expect(json_response['assets']['links'].first['name']).to eq('beta')
+ expect(json_response['assets']['links'].first['url'])
+ .to eq('https://dosuken.example.com/inspection.exe')
+ end
+
+ it 'matches response schema' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(response).to match_response_schema('release')
+ end
+ end
+
+ context 'when create two assets' do
+ let(:params) do
+ base_params.merge({
+ assets: {
+ links: [
+ { name: 'alpha', url: 'https://dosuken.example.com/alpha.exe' },
+ { name: 'beta', url: 'https://dosuken.example.com/beta.exe' }
+ ]
+ }
+ })
+ end
+
+ it 'creates two assets with specified parameters' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(json_response['assets']['links'].count).to eq(2)
+ expect(json_response['assets']['links'].map { |h| h['name'] })
+ .to match_array(%w[alpha beta])
+ expect(json_response['assets']['links'].map { |h| h['url'] })
+ .to match_array(%w[https://dosuken.example.com/alpha.exe
+ https://dosuken.example.com/beta.exe])
+ end
+
+ context 'when link names are duplicates' do
+ let(:params) do
+ base_params.merge({
+ assets: {
+ links: [
+ { name: 'alpha', url: 'https://dosuken.example.com/alpha.exe' },
+ { name: 'alpha', url: 'https://dosuken.example.com/beta.exe' }
+ ]
+ }
+ })
+ end
+
+ it 'recognizes as a bad request' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+ end
+ end
+
+ context 'when tag does not exist in git repository' do
+ let(:params) do
+ {
+ name: 'Android ~ Ice Cream Sandwich ~',
+ tag_name: tag_name,
+ description: 'Android 4.0–4.0.4 "Ice Cream Sandwich" is the ninth' \
+ 'version of the Android mobile operating system developed' \
+ 'by Google.',
+ ref: 'master'
+ }
+ end
+
+ let(:tag_name) { 'v4.0' }
+
+ it 'creates a new tag' do
+ expect do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+ end.to change { Project.find_by_id(project.id).repository.tag_count }.by(1)
+
+ expect(project.repository.find_tag('v4.0').dereferenced_target.id)
+ .to eq(project.repository.commit('master').id)
+ end
+
+ it 'creates a new release' do
+ expect do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+ end.to change { Release.count }.by(1)
+
+ expect(project.releases.last.name).to eq('Android ~ Ice Cream Sandwich ~')
+ expect(project.releases.last.tag).to eq('v4.0')
+ expect(project.releases.last.description).to eq(
+ 'Android 4.0–4.0.4 "Ice Cream Sandwich" is the ninth' \
+ 'version of the Android mobile operating system developed' \
+ 'by Google.')
+ end
+
+ context 'when tag name is HEAD' do
+ let(:tag_name) { 'HEAD' }
+
+ it 'returns an error as failure on tag creation' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:internal_server_error)
+ expect(json_response['message']).to eq('Tag name invalid')
+ end
+ end
+
+ context 'when tag name is empty' do
+ let(:tag_name) { '' }
+
+ it 'returns an error as failure on tag creation' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:internal_server_error)
+ expect(json_response['message']).to eq('Tag name invalid')
+ end
+ end
+ end
+
+ context 'when release already exists' do
+ before do
+ create(:release, project: project, tag: 'v0.1', name: 'New release')
+ end
+
+ it 'returns an error as conflicted request' do
+ post api("/projects/#{project.id}/releases", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:conflict)
+ end
+ end
+ end
+
+ describe 'PUT /projects/:id/releases/:tag_name' do
+ let(:params) { { description: 'Best release ever!' } }
+
+ let!(:release) do
+ create(:release,
+ project: project,
+ tag: 'v0.1',
+ name: 'New release',
+ description: 'Super nice release')
+ end
+
+ it 'accepts the request' do
+ put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'updates the description' do
+ put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
+
+ expect(project.releases.last.description).to eq('Best release ever!')
+ end
+
+ it 'does not change other attributes' do
+ put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
+
+ expect(project.releases.last.tag).to eq('v0.1')
+ expect(project.releases.last.name).to eq('New release')
+ end
+
+ it 'matches response schema' do
+ put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
+
+ expect(response).to match_response_schema('release')
+ end
+
+ context 'when user tries to update sha' do
+ let(:params) { { sha: 'xxx' } }
+
+ it 'does not allow the request' do
+ put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'when params is empty' do
+ let(:params) { {} }
+
+ it 'does not allow the request' do
+ put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'when there are no corresponding releases' do
+ let!(:release) { }
+
+ it 'forbids the request' do
+ put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when user is a reporter' do
+ it 'forbids the request' do
+ put api("/projects/#{project.id}/releases/v0.1", reporter), params: params
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when user is not a project member' do
+ it 'forbids the request' do
+ put api("/projects/#{project.id}/releases/v0.1", non_project_member),
+ params: params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it 'forbids the request' do
+ put api("/projects/#{project.id}/releases/v0.1", non_project_member),
+ params: params
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/releases/:tag_name' do
+ let!(:release) do
+ create(:release,
+ project: project,
+ tag: 'v0.1',
+ name: 'New release',
+ description: 'Super nice release')
+ end
+
+ it 'accepts the request' do
+ delete api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'destroys the release' do
+ expect do
+ delete api("/projects/#{project.id}/releases/v0.1", maintainer)
+ end.to change { Release.count }.by(-1)
+ end
+
+ it 'does not remove a tag in repository' do
+ expect do
+ delete api("/projects/#{project.id}/releases/v0.1", maintainer)
+ end.not_to change { Project.find_by_id(project.id).repository.tag_count }
+ end
+
+ it 'matches response schema' do
+ delete api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(response).to match_response_schema('release')
+ end
+
+ context 'when there are no corresponding releases' do
+ let!(:release) { }
+
+ it 'forbids the request' do
+ delete api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when user is a reporter' do
+ it 'forbids the request' do
+ delete api("/projects/#{project.id}/releases/v0.1", reporter)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when user is not a project member' do
+ it 'forbids the request' do
+ delete api("/projects/#{project.id}/releases/v0.1", non_project_member)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :repository, :public) }
+
+ it 'forbids the request' do
+ delete api("/projects/#{project.id}/releases/v0.1", non_project_member)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 181fe6246ae..0adc95cfbeb 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -166,12 +166,13 @@ describe API::Repositories do
get api(route, current_user)
expect(response).to have_gitlab_http_status(200)
+ expect(headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
- it 'forces attachment content disposition' do
+ it 'sets inline content disposition by default' do
get api(route, current_user)
- expect(headers['Content-Disposition']).to match(/^attachment/)
+ expect(headers['Content-Disposition']).to eq 'inline'
end
context 'when sha does not exist' do
diff --git a/spec/requests/api/resource_label_events_spec.rb b/spec/requests/api/resource_label_events_spec.rb
index b7d4a5152cc..37b46eaeb86 100644
--- a/spec/requests/api/resource_label_events_spec.rb
+++ b/spec/requests/api/resource_label_events_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
describe API::ResourceLabelEvents do
set(:user) { create(:user) }
set(:project) { create(:project, :public, :repository, namespace: user.namespace) }
- set(:private_user) { create(:user) }
+ set(:private_user) { create(:user) }
before do
project.add_developer(user)
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index c63621fe7d1..9087cccb759 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -210,8 +210,8 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
it "sets the runner's ip_address" do
post api('/runners'),
- params: { token: registration_token },
- headers: { 'REMOTE_ADDR' => '123.111.123.111' }
+ params: { token: registration_token },
+ headers: { 'X-Forwarded-For' => '123.111.123.111' }
expect(response).to have_gitlab_http_status 201
expect(Ci::Runner.first.ip_address).to eq('123.111.123.111')
@@ -287,7 +287,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
let(:runner) { create(:ci_runner, :project, projects: [project]) }
let(:job) do
create(:ci_build, :artifacts, :extended_options,
- pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0, commands: "ls\ndate")
+ pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0)
end
describe 'POST /api/v4/jobs/request' do
@@ -417,12 +417,14 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
'ref' => job.ref,
'sha' => job.sha,
'before_sha' => job.before_sha,
- 'ref_type' => 'branch' }
+ 'ref_type' => 'branch',
+ 'refspecs' => %w[+refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*],
+ 'depth' => 0 }
end
let(:expected_steps) do
[{ 'name' => 'script',
- 'script' => %w(ls date),
+ 'script' => %w(echo),
'timeout' => job.metadata_timeout,
'when' => 'on_success',
'allow_failure' => false },
@@ -434,9 +436,9 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
let(:expected_variables) do
- [{ 'key' => 'CI_JOB_NAME', 'value' => 'spinach', 'public' => true },
- { 'key' => 'CI_JOB_STAGE', 'value' => 'test', 'public' => true },
- { 'key' => 'DB_NAME', 'value' => 'postgres', 'public' => true }]
+ [{ 'key' => 'CI_JOB_NAME', 'value' => 'spinach', 'public' => true, 'masked' => false },
+ { 'key' => 'CI_JOB_STAGE', 'value' => 'test', 'public' => true, 'masked' => false },
+ { 'key' => 'DB_NAME', 'value' => 'postgres', 'public' => true, 'masked' => false }]
end
let(:expected_artifacts) do
@@ -489,6 +491,29 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(201)
expect(json_response['git_info']['ref_type']).to eq('tag')
end
+
+ context 'when GIT_DEPTH is specified' do
+ before do
+ create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: pipeline)
+ end
+
+ it 'specifies refspecs' do
+ request_job
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['git_info']['refspecs']).to include("+refs/tags/#{job.ref}:refs/tags/#{job.ref}")
+ end
+ end
+
+ context 'when GIT_DEPTH is not specified' do
+ it 'specifies refspecs' do
+ request_job
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['git_info']['refspecs'])
+ .to contain_exactly('+refs/tags/*:refs/tags/*', '+refs/heads/*:refs/remotes/origin/*')
+ end
+ end
end
context 'when job is made for branch' do
@@ -498,6 +523,55 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(201)
expect(json_response['git_info']['ref_type']).to eq('branch')
end
+
+ context 'when GIT_DEPTH is specified' do
+ before do
+ create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: pipeline)
+ end
+
+ it 'specifies refspecs' do
+ request_job
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['git_info']['refspecs']).to include("+refs/heads/#{job.ref}:refs/remotes/origin/#{job.ref}")
+ end
+ end
+
+ context 'when GIT_DEPTH is not specified' do
+ it 'specifies refspecs' do
+ request_job
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['git_info']['refspecs'])
+ .to contain_exactly('+refs/tags/*:refs/tags/*', '+refs/heads/*:refs/remotes/origin/*')
+ end
+ end
+ end
+
+ context 'when job is made for merge request' do
+ let(:pipeline) { create(:ci_pipeline_without_jobs, source: :merge_request_event, project: project, ref: 'feature', merge_request: merge_request) }
+ let!(:job) { create(:ci_build, pipeline: pipeline, name: 'spinach', ref: 'feature', stage: 'test', stage_idx: 0) }
+ let(:merge_request) { create(:merge_request) }
+
+ it 'sets branch as ref_type' do
+ request_job
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['git_info']['ref_type']).to eq('branch')
+ end
+
+ context 'when GIT_DEPTH is specified' do
+ before do
+ create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: pipeline)
+ end
+
+ it 'returns the overwritten git depth for merge request refspecs' do
+ request_job
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['git_info']['depth']).to eq(1)
+ end
+ end
end
it 'updates runner info' do
@@ -520,7 +594,16 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
it "sets the runner's ip_address" do
post api('/jobs/request'),
params: { token: runner.token },
- headers: { 'User-Agent' => user_agent, 'REMOTE_ADDR' => '123.222.123.222' }
+ headers: { 'User-Agent' => user_agent, 'X-Forwarded-For' => '123.222.123.222' }
+
+ expect(response).to have_gitlab_http_status 201
+ expect(runner.reload.ip_address).to eq('123.222.123.222')
+ end
+
+ it "handles multiple X-Forwarded-For addresses" do
+ post api('/jobs/request'),
+ params: { token: runner.token },
+ headers: { 'User-Agent' => user_agent, 'X-Forwarded-For' => '123.222.123.222, 127.0.0.1' }
expect(response).to have_gitlab_http_status 201
expect(runner.reload.ip_address).to eq('123.222.123.222')
@@ -588,7 +671,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
let!(:test_job) do
create(:ci_build, pipeline: pipeline, token: 'test-job-token', name: 'deploy',
stage: 'deploy', stage_idx: 1,
- options: { dependencies: [job2.name] })
+ options: { script: ['bash'], dependencies: [job2.name] })
end
before do
@@ -612,7 +695,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
let!(:empty_dependencies_job) do
create(:ci_build, pipeline: pipeline, token: 'test-job-token', name: 'empty_dependencies_job',
stage: 'deploy', stage_idx: 1,
- options: { dependencies: [] })
+ options: { script: ['bash'], dependencies: [] })
end
before do
@@ -657,12 +740,12 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
context 'when triggered job is available' do
let(:expected_variables) do
- [{ 'key' => 'CI_JOB_NAME', 'value' => 'spinach', 'public' => true },
- { 'key' => 'CI_JOB_STAGE', 'value' => 'test', 'public' => true },
- { 'key' => 'CI_PIPELINE_TRIGGERED', 'value' => 'true', 'public' => true },
- { 'key' => 'DB_NAME', 'value' => 'postgres', 'public' => true },
- { 'key' => 'SECRET_KEY', 'value' => 'secret_value', 'public' => false },
- { 'key' => 'TRIGGER_KEY_1', 'value' => 'TRIGGER_VALUE_1', 'public' => false }]
+ [{ 'key' => 'CI_JOB_NAME', 'value' => 'spinach', 'public' => true, 'masked' => false },
+ { 'key' => 'CI_JOB_STAGE', 'value' => 'test', 'public' => true, 'masked' => false },
+ { 'key' => 'CI_PIPELINE_TRIGGERED', 'value' => 'true', 'public' => true, 'masked' => false },
+ { 'key' => 'DB_NAME', 'value' => 'postgres', 'public' => true, 'masked' => false },
+ { 'key' => 'SECRET_KEY', 'value' => 'secret_value', 'public' => false, 'masked' => false },
+ { 'key' => 'TRIGGER_KEY_1', 'value' => 'TRIGGER_VALUE_1', 'public' => false, 'masked' => false }]
end
let(:trigger) { create(:ci_trigger, project: project) }
@@ -1320,7 +1403,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
before do
- fog_connection.directories.get('artifacts').files.create(
+ fog_connection.directories.new(key: 'artifacts').files.create(
key: 'tmp/uploads/12312300',
body: 'content'
)
@@ -1584,7 +1667,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
context 'when artifacts are stored locally' do
let(:download_headers) do
{ 'Content-Transfer-Encoding' => 'binary',
- 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' }
+ 'Content-Disposition' => %q(attachment; filename="ci_build_artifacts.zip"; filename*=UTF-8''ci_build_artifacts.zip) }
end
before do
diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb
index 7f11c8c9fe8..5548e3fd01a 100644
--- a/spec/requests/api/runners_spec.rb
+++ b/spec/requests/api/runners_spec.rb
@@ -90,6 +90,17 @@ describe API::Runners do
expect(response).to have_gitlab_http_status(400)
end
+
+ it 'filters runners by tag_list' do
+ create(:ci_runner, :project, description: 'Runner tagged with tag1 and tag2', projects: [project], tag_list: %w[tag1 tag2])
+ create(:ci_runner, :project, description: 'Runner tagged with tag2', projects: [project], tag_list: ['tag2'])
+
+ get api('/runners?tag_list=tag1,tag2', user)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Runner tagged with tag1 and tag2')
+ ]
+ end
end
context 'unauthorized user' do
@@ -181,6 +192,17 @@ describe API::Runners do
expect(response).to have_gitlab_http_status(400)
end
+
+ it 'filters runners by tag_list' do
+ create(:ci_runner, :project, description: 'Runner tagged with tag1 and tag2', projects: [project], tag_list: %w[tag1 tag2])
+ create(:ci_runner, :project, description: 'Runner tagged with tag2', projects: [project], tag_list: ['tag2'])
+
+ get api('/runners/all?tag_list=tag1,tag2', admin)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Runner tagged with tag1 and tag2')
+ ]
+ end
end
context 'without admin privileges' do
@@ -241,7 +263,7 @@ describe API::Runners do
end
it 'returns 404 if runner does not exists' do
- get api('/runners/9999', admin)
+ get api('/runners/0', admin)
expect(response).to have_gitlab_http_status(404)
end
@@ -394,7 +416,7 @@ describe API::Runners do
end
it 'returns 404 if runner does not exists' do
- update_runner(9999, admin, description: 'test')
+ update_runner(0, admin, description: 'test')
expect(response).to have_gitlab_http_status(404)
end
@@ -468,7 +490,7 @@ describe API::Runners do
end
it 'returns 404 if runner does not exists' do
- delete api('/runners/9999', admin)
+ delete api('/runners/0', admin)
expect(response).to have_gitlab_http_status(404)
end
@@ -573,7 +595,7 @@ describe API::Runners do
context "when runner doesn't exist" do
it 'returns 404' do
- get api('/runners/9999/jobs', admin)
+ get api('/runners/0/jobs', admin)
expect(response).to have_gitlab_http_status(404)
end
@@ -626,7 +648,7 @@ describe API::Runners do
context "when runner doesn't exist" do
it 'returns 404' do
- get api('/runners/9999/jobs', user)
+ get api('/runners/0/jobs', user)
expect(response).to have_gitlab_http_status(404)
end
@@ -716,6 +738,17 @@ describe API::Runners do
expect(response).to have_gitlab_http_status(400)
end
+
+ it 'filters runners by tag_list' do
+ create(:ci_runner, :project, description: 'Runner tagged with tag1 and tag2', projects: [project], tag_list: %w[tag1 tag2])
+ create(:ci_runner, :project, description: 'Runner tagged with tag2', projects: [project], tag_list: ['tag2'])
+
+ get api("/projects/#{project.id}/runners?tag_list=tag1,tag2", user)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Runner tagged with tag1 and tag2')
+ ]
+ end
end
context 'authorized user without maintainer privileges' do
@@ -857,7 +890,7 @@ describe API::Runners do
end
it 'returns 404 is runner is not found' do
- delete api("/projects/#{project.id}/runners/9999", user)
+ delete api("/projects/#{project.id}/runners/0", user)
expect(response).to have_gitlab_http_status(404)
end
diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb
index 831f47debeb..c48ca832c85 100644
--- a/spec/requests/api/search_spec.rb
+++ b/spec/requests/api/search_spec.rb
@@ -126,7 +126,7 @@ describe API::Search do
context 'when group does not exist' do
it 'returns 404 error' do
- get api('/groups/9999/search', user), params: { scope: 'issues', search: 'awesome' }
+ get api('/groups/0/search', user), params: { scope: 'issues', search: 'awesome' }
expect(response).to have_gitlab_http_status(404)
end
@@ -222,7 +222,7 @@ describe API::Search do
context 'when project does not exist' do
it 'returns 404 error' do
- get api('/projects/9999/search', user), params: { scope: 'issues', search: 'awesome' }
+ get api('/projects/0/search', user), params: { scope: 'issues', search: 'awesome' }
expect(response).to have_gitlab_http_status(404)
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index cfbda63bb30..f33eb5b9e02 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -63,7 +63,9 @@ describe API::Settings, 'Settings' do
terms: 'Hello world!',
performance_bar_allowed_group_path: group.full_path,
instance_statistics_visibility_private: true,
- diff_max_patch_bytes: 150_000
+ diff_max_patch_bytes: 150_000,
+ default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE,
+ local_markdown_version: 3
}
expect(response).to have_gitlab_http_status(200)
@@ -88,6 +90,8 @@ describe API::Settings, 'Settings' do
expect(json_response['performance_bar_allowed_group_id']).to eq(group.id)
expect(json_response['instance_statistics_visibility_private']).to be(true)
expect(json_response['diff_max_patch_bytes']).to eq(150_000)
+ expect(json_response['default_branch_protection']).to eq(Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
+ expect(json_response['local_markdown_version']).to eq(3)
end
end
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index 7c8512f7589..d600076e9fb 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -84,10 +84,17 @@ describe API::Snippets do
end
describe 'GET /snippets/:id/raw' do
- let(:snippet) { create(:personal_snippet, author: user) }
+ set(:author) { create(:user) }
+ set(:snippet) { create(:personal_snippet, :private, author: author) }
+
+ it 'requires authentication' do
+ get api("/snippets/#{snippet.id}", nil)
+
+ expect(response).to have_gitlab_http_status(401)
+ end
it 'returns raw text' do
- get api("/snippets/#{snippet.id}/raw", user)
+ get api("/snippets/#{snippet.id}/raw", author)
expect(response).to have_gitlab_http_status(200)
expect(response.content_type).to eq 'text/plain'
@@ -95,38 +102,83 @@ describe API::Snippets do
end
it 'forces attachment content disposition' do
- get api("/snippets/#{snippet.id}/raw", user)
+ get api("/snippets/#{snippet.id}/raw", author)
expect(headers['Content-Disposition']).to match(/^attachment/)
end
it 'returns 404 for invalid snippet id' do
- get api("/snippets/1234/raw", user)
+ snippet.destroy
+
+ get api("/snippets/#{snippet.id}/raw", author)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 Snippet Not Found')
end
+
+ it 'hides private snippets from ordinary users' do
+ get api("/snippets/#{snippet.id}/raw", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'shows internal snippets to ordinary users' do
+ internal_snippet = create(:personal_snippet, :internal, author: author)
+
+ get api("/snippets/#{internal_snippet.id}/raw", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ end
end
describe 'GET /snippets/:id' do
- let(:snippet) { create(:personal_snippet, author: user) }
+ set(:admin) { create(:user, :admin) }
+ set(:author) { create(:user) }
+ set(:private_snippet) { create(:personal_snippet, :private, author: author) }
+ set(:internal_snippet) { create(:personal_snippet, :internal, author: author) }
+
+ it 'requires authentication' do
+ get api("/snippets/#{private_snippet.id}", nil)
+
+ expect(response).to have_gitlab_http_status(401)
+ end
it 'returns snippet json' do
- get api("/snippets/#{snippet.id}", user)
+ get api("/snippets/#{private_snippet.id}", author)
expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(snippet.title)
- expect(json_response['description']).to eq(snippet.description)
- expect(json_response['file_name']).to eq(snippet.file_name)
- expect(json_response['visibility']).to eq(snippet.visibility)
+ expect(json_response['title']).to eq(private_snippet.title)
+ expect(json_response['description']).to eq(private_snippet.description)
+ expect(json_response['file_name']).to eq(private_snippet.file_name)
+ expect(json_response['visibility']).to eq(private_snippet.visibility)
+ end
+
+ it 'shows private snippets to an admin' do
+ get api("/snippets/#{private_snippet.id}", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+
+ it 'hides private snippets from an ordinary user' do
+ get api("/snippets/#{private_snippet.id}", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'shows internal snippets to an ordinary user' do
+ get api("/snippets/#{internal_snippet.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
end
it 'returns 404 for invalid snippet id' do
- get api("/snippets/1234", user)
+ private_snippet.destroy
+
+ get api("/snippets/#{private_snippet.id}", admin)
expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Not found')
+ expect(json_response['message']).to eq('404 Snippet Not Found')
end
end
diff --git a/spec/requests/api/submodules_spec.rb b/spec/requests/api/submodules_spec.rb
index c482a85c68f..064392fb185 100644
--- a/spec/requests/api/submodules_spec.rb
+++ b/spec/requests/api/submodules_spec.rb
@@ -64,7 +64,7 @@ describe API::Submodules do
expect(response).to have_gitlab_http_status(400)
end
- it 'returns the commmit' do
+ it 'returns the commit' do
head_commit = project.repository.commit.id
put api(route(submodule), user), params: params
@@ -81,7 +81,7 @@ describe API::Submodules do
let(:branch) { 'submodule_inside_folder' }
let(:encoded_submodule) { CGI.escape(submodule) }
- it 'returns the commmit' do
+ it 'returns the commit' do
expect(Submodules::UpdateService)
.to receive(:new)
.with(any_args, hash_including(submodule: submodule))
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index 12cfac96d31..fffe878ddbd 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -54,6 +54,18 @@ describe API::Tags do
end
end
+ context 'searching' do
+ it 'only returns searched tags' do
+ get api("#{route}", user), params: { search: 'v1.1.0' }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(1)
+ expect(json_response[0]['name']).to eq('v1.1.0')
+ end
+ end
+
shared_examples_for 'repository tags' do
it 'returns the repository tags' do
get api(route, current_user)
@@ -107,9 +119,12 @@ describe API::Tags do
context 'with releases' do
let(:description) { 'Awesome release!' }
- before do
- release = project.releases.find_or_initialize_by(tag: tag_name)
- release.update(description: description)
+ let!(:release) do
+ create(:release,
+ :legacy,
+ project: project,
+ tag: tag_name,
+ description: description)
end
it 'returns an array of project tags with release info' do
@@ -373,7 +388,7 @@ describe API::Tags do
it_behaves_like '404 response' do
let(:request) { post api(route, current_user), params: { description: description } }
- let(:message) { 'Tag does not exist' }
+ let(:message) { '404 Tag Not Found' }
end
end
@@ -398,10 +413,7 @@ describe API::Tags do
end
context 'on tag with existing release' do
- before do
- release = project.releases.find_or_initialize_by(tag: tag_name)
- release.update(description: description)
- end
+ let!(:release) { create(:release, :legacy, project: project, tag: tag_name, description: description) }
it 'returns 409 if there is already a release' do
post api(route, user), params: { description: description }
@@ -420,9 +432,12 @@ describe API::Tags do
shared_examples_for 'repository update release' do
context 'on tag with existing release' do
- before do
- release = project.releases.find_or_initialize_by(tag: tag_name)
- release.update(description: description)
+ let!(:release) do
+ create(:release,
+ :legacy,
+ project: project,
+ tag: tag_name,
+ description: description)
end
it 'updates the release description' do
@@ -437,9 +452,9 @@ describe API::Tags do
context 'when tag does not exist' do
let(:tag_name) { 'unknown' }
- it_behaves_like '404 response' do
+ it_behaves_like '403 response' do
let(:request) { put api(route, current_user), params: { description: new_description } }
- let(:message) { 'Tag does not exist' }
+ let(:message) { '403 Forbidden' }
end
end
@@ -464,9 +479,9 @@ describe API::Tags do
end
context 'when release does not exist' do
- it_behaves_like '404 response' do
+ it_behaves_like '403 response' do
let(:request) { put api(route, current_user), params: { description: new_description } }
- let(:message) { 'Release does not exist' }
+ let(:message) { '403 Forbidden' }
end
end
end
diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb
index 15dc901d06e..f0f01e97f1d 100644
--- a/spec/requests/api/triggers_spec.rb
+++ b/spec/requests/api/triggers_spec.rb
@@ -1,8 +1,9 @@
require 'spec_helper'
describe API::Triggers do
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
+ set(:user) { create(:user) }
+ set(:user2) { create(:user) }
+
let!(:trigger_token) { 'secure_token' }
let!(:trigger_token_2) { 'secure_token_2' }
let!(:project) { create(:project, :repository, creator: user) }
@@ -132,14 +133,17 @@ describe API::Triggers do
end
describe 'GET /projects/:id/triggers' do
- context 'authenticated user with valid permissions' do
- it 'returns list of triggers' do
+ context 'authenticated user who can access triggers' do
+ it 'returns a list of triggers with tokens exposed correctly' do
get api("/projects/#{project.id}/triggers", user)
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
+
expect(json_response).to be_a(Array)
- expect(json_response[0]).to have_key('token')
+ expect(json_response.size).to eq 2
+ expect(json_response.dig(0, 'token')).to eq trigger_token
+ expect(json_response.dig(1, 'token')).to eq trigger_token_2[0..3]
end
end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index f3431e0be3d..a879426589d 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe API::Users do
- let(:user) { create(:user) }
+ let(:user) { create(:user, username: 'user.with.dot') }
let(:admin) { create(:admin) }
let(:key) { create(:key, user: user) }
let(:gpg_key) { create(:gpg_key, user: user) }
@@ -335,7 +335,7 @@ describe API::Users do
end
it "returns a 404 error if user id not found" do
- get api("/users/9999", user)
+ get api("/users/0", user)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
@@ -732,7 +732,7 @@ describe API::Users do
end
it "returns 404 for non-existing user" do
- put api("/users/999999", admin), params: { bio: 'update should fail' }
+ put api("/users/0", admin), params: { bio: 'update should fail' }
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
@@ -836,7 +836,7 @@ describe API::Users do
end
it "returns 400 for invalid ID" do
- post api("/users/999999/keys", admin)
+ post api("/users/0/keys", admin)
expect(response).to have_gitlab_http_status(400)
end
end
@@ -895,7 +895,7 @@ describe API::Users do
it 'returns 404 error if user not found' do
user.keys << key
user.save
- delete api("/users/999999/keys/#{key.id}", admin)
+ delete api("/users/0/keys/#{key.id}", admin)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
@@ -930,7 +930,7 @@ describe API::Users do
end
it 'returns 400 for invalid ID' do
- post api('/users/999999/gpg_keys', admin)
+ post api('/users/0/gpg_keys', admin)
expect(response).to have_gitlab_http_status(400)
end
@@ -951,7 +951,7 @@ describe API::Users do
context 'when authenticated' do
it 'returns 404 for non-existing user' do
- get api('/users/999999/gpg_keys', admin)
+ get api('/users/0/gpg_keys', admin)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
@@ -1007,7 +1007,7 @@ describe API::Users do
user.keys << key
user.save
- delete api("/users/999999/gpg_keys/#{gpg_key.id}", admin)
+ delete api("/users/0/gpg_keys/#{gpg_key.id}", admin)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
@@ -1051,7 +1051,7 @@ describe API::Users do
user.gpg_keys << gpg_key
user.save
- post api("/users/999999/gpg_keys/#{gpg_key.id}/revoke", admin)
+ post api("/users/0/gpg_keys/#{gpg_key.id}/revoke", admin)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
@@ -1089,7 +1089,7 @@ describe API::Users do
end
it "returns a 400 for invalid ID" do
- post api("/users/999999/emails", admin)
+ post api("/users/0/emails", admin)
expect(response).to have_gitlab_http_status(400)
end
@@ -1121,7 +1121,7 @@ describe API::Users do
context 'when authenticated' do
it 'returns 404 for non-existing user' do
- get api('/users/999999/emails', admin)
+ get api('/users/0/emails', admin)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
@@ -1177,7 +1177,7 @@ describe API::Users do
it 'returns 404 error if user not found' do
user.emails << email
user.save
- delete api("/users/999999/emails/#{email.id}", admin)
+ delete api("/users/0/emails/#{email.id}", admin)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
@@ -1227,7 +1227,7 @@ describe API::Users do
end
it "returns 404 for non-existing user" do
- perform_enqueued_jobs { delete api("/users/999999", admin) }
+ perform_enqueued_jobs { delete api("/users/0", admin) }
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
@@ -1778,14 +1778,14 @@ describe API::Users do
end
it 'returns a 404 error if user id not found' do
- post api('/users/9999/block', admin)
+ post api('/users/0/block', admin)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
end
describe 'POST /users/:id/unblock' do
- let(:blocked_user) { create(:user, state: 'blocked') }
+ let(:blocked_user) { create(:user, state: 'blocked') }
before do
admin
@@ -1816,7 +1816,7 @@ describe API::Users do
end
it 'returns a 404 error if user id not found' do
- post api('/users/9999/block', admin)
+ post api('/users/0/block', admin)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
diff --git a/spec/requests/api/variables_spec.rb b/spec/requests/api/variables_spec.rb
index cdac5b2f400..5df6baf0ddf 100644
--- a/spec/requests/api/variables_spec.rb
+++ b/spec/requests/api/variables_spec.rb
@@ -73,12 +73,12 @@ describe API::Variables do
context 'authorized user with proper permissions' do
it 'creates variable' do
expect do
- post api("/projects/#{project.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'VALUE_2', protected: true }
+ post api("/projects/#{project.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true }
end.to change {project.variables.count}.by(1)
expect(response).to have_gitlab_http_status(201)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
- expect(json_response['value']).to eq('VALUE_2')
+ expect(json_response['value']).to eq('PROTECTED_VALUE_2')
expect(json_response['protected']).to be_truthy
end
diff --git a/spec/requests/api/version_spec.rb b/spec/requests/api/version_spec.rb
index 38b618191fb..e06f8bbc095 100644
--- a/spec/requests/api/version_spec.rb
+++ b/spec/requests/api/version_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe API::Version do
- describe 'GET /version' do
+ shared_examples_for 'GET /version' do
context 'when unauthenticated' do
it 'returns authentication error' do
get api('/version')
@@ -22,4 +22,20 @@ describe API::Version do
end
end
end
+
+ context 'with graphql enabled' do
+ before do
+ stub_feature_flags(graphql: true)
+ end
+
+ include_examples 'GET /version'
+ end
+
+ context 'with graphql disabled' do
+ before do
+ stub_feature_flags(graphql: false)
+ end
+
+ include_examples 'GET /version'
+ end
end
diff --git a/spec/requests/api/wikis_spec.rb b/spec/requests/api/wikis_spec.rb
index f5092e8e2b5..d1b58aac104 100644
--- a/spec/requests/api/wikis_spec.rb
+++ b/spec/requests/api/wikis_spec.rb
@@ -22,7 +22,7 @@ describe API::Wikis do
context 'when wiki has pages' do
let!(:pages) do
[create(:wiki_page, wiki: project_wiki, attrs: { title: 'page1', content: 'content of page1' }),
- create(:wiki_page, wiki: project_wiki, attrs: { title: 'page2', content: 'content of page2' })]
+ create(:wiki_page, wiki: project_wiki, attrs: { title: 'page2.with.dot', content: 'content of page2' })]
end
it 'returns the list of wiki pages without content' do
@@ -100,6 +100,8 @@ describe API::Wikis do
shared_examples_for 'updates wiki page' do
it 'updates the wiki page' do
+ put(api(url, user), params: payload)
+
expect(response).to have_gitlab_http_status(200)
expect(json_response.size).to eq(4)
expect(json_response.keys).to match_array(expected_keys_with_content)
@@ -107,6 +109,16 @@ describe API::Wikis do
expect(json_response['slug']).to eq(payload[:title].tr(' ', '-'))
expect(json_response['title']).to eq(payload[:title])
end
+
+ [:title, :content, :format].each do |part|
+ it "it updates with wiki with missing #{part}" do
+ payload.delete(part)
+
+ put(api(url, user), params: payload)
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
end
shared_examples_for '403 Forbidden' do
@@ -528,8 +540,6 @@ describe API::Wikis do
context 'when user is developer' do
before do
project.add_developer(user)
-
- put(api(url, user), params: payload)
end
include_examples 'updates wiki page'
@@ -537,6 +547,10 @@ describe API::Wikis do
context 'when page is not existing' do
let(:url) { "/projects/#{project.id}/wikis/unknown" }
+ before do
+ put(api(url, user), params: payload)
+ end
+
include_examples '404 Wiki Page Not Found'
end
end
@@ -544,8 +558,6 @@ describe API::Wikis do
context 'when user is maintainer' do
before do
project.add_maintainer(user)
-
- put(api(url, user), params: payload)
end
include_examples 'updates wiki page'
@@ -553,6 +565,10 @@ describe API::Wikis do
context 'when page is not existing' do
let(:url) { "/projects/#{project.id}/wikis/unknown" }
+ before do
+ put(api(url, user), params: payload)
+ end
+
include_examples '404 Wiki Page Not Found'
end
end
@@ -572,8 +588,6 @@ describe API::Wikis do
context 'when user is developer' do
before do
project.add_developer(user)
-
- put(api(url, user), params: payload)
end
include_examples 'updates wiki page'
@@ -581,6 +595,10 @@ describe API::Wikis do
context 'when page is not existing' do
let(:url) { "/projects/#{project.id}/wikis/unknown" }
+ before do
+ put(api(url, user), params: payload)
+ end
+
include_examples '404 Wiki Page Not Found'
end
end
@@ -588,8 +606,6 @@ describe API::Wikis do
context 'when user is maintainer' do
before do
project.add_maintainer(user)
-
- put(api(url, user), params: payload)
end
include_examples 'updates wiki page'
@@ -597,6 +613,10 @@ describe API::Wikis do
context 'when page is not existing' do
let(:url) { "/projects/#{project.id}/wikis/unknown" }
+ before do
+ put(api(url, user), params: payload)
+ end
+
include_examples '404 Wiki Page Not Found'
end
end
@@ -605,10 +625,6 @@ describe API::Wikis do
context 'when wiki belongs to a group project' do
let(:project) { create(:project, :wiki_repo, namespace: group) }
- before do
- put(api(url, user), params: payload)
- end
-
include_examples 'updates wiki page'
end
end
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 939e870ec53..bfa178f5cae 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -104,6 +104,70 @@ describe 'Git HTTP requests' do
end
end
+ shared_examples_for 'project path without .git suffix' do
+ context "GET info/refs" do
+ let(:path) { "/#{project_path}/info/refs" }
+
+ context "when no params are added" do
+ before do
+ get path
+ end
+
+ it "redirects to the .git suffix version" do
+ expect(response).to redirect_to("/#{project_path}.git/info/refs")
+ end
+ end
+
+ context "when the upload-pack service is requested" do
+ let(:params) { { service: 'git-upload-pack' } }
+
+ before do
+ get path, params: params
+ end
+
+ it "redirects to the .git suffix version" do
+ expect(response).to redirect_to("/#{project_path}.git/info/refs?service=#{params[:service]}")
+ end
+ end
+
+ context "when the receive-pack service is requested" do
+ let(:params) { { service: 'git-receive-pack' } }
+
+ before do
+ get path, params: params
+ end
+
+ it "redirects to the .git suffix version" do
+ expect(response).to redirect_to("/#{project_path}.git/info/refs?service=#{params[:service]}")
+ end
+ end
+
+ context "when the params are anything else" do
+ let(:params) { { service: 'git-implode-pack' } }
+
+ before do
+ get path, params: params
+ end
+
+ it "redirects to the sign-in page" do
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ context "POST git-upload-pack" do
+ it "fails to find a route" do
+ expect { clone_post(project_path) }.to raise_error(ActionController::RoutingError)
+ end
+ end
+
+ context "POST git-receive-pack" do
+ it "fails to find a route" do
+ expect { push_post(project_path) }.to raise_error(ActionController::RoutingError)
+ end
+ end
+ end
+
describe "User with no identities" do
let(:user) { create(:user) }
@@ -143,6 +207,10 @@ describe 'Git HTTP requests' do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
+
+ it_behaves_like 'project path without .git suffix' do
+ let(:project_path) { "#{user.namespace.path}/project.git-project" }
+ end
end
end
@@ -387,7 +455,7 @@ describe 'Git HTTP requests' do
it "responds with status 401" do
expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true)
- allow_any_instance_of(Rack::Request).to receive(:ip).and_return('1.2.3.4')
+ allow_any_instance_of(ActionDispatch::Request).to receive(:ip).and_return('1.2.3.4')
clone_get(path, env)
@@ -548,7 +616,7 @@ describe 'Git HTTP requests' do
maxretry = options[:maxretry] - 1
ip = '1.2.3.4'
- allow_any_instance_of(Rack::Request).to receive(:ip).and_return(ip)
+ allow_any_instance_of(ActionDispatch::Request).to receive(:ip).and_return(ip)
Rack::Attack::Allow2Ban.reset(ip, options)
maxretry.times.each do
@@ -706,70 +774,8 @@ describe 'Git HTTP requests' do
end
end
- context "when the project path doesn't end in .git" do
- let(:project) { create(:project, :repository, :public, path: 'project.git-project') }
-
- context "GET info/refs" do
- let(:path) { "/#{project.full_path}/info/refs" }
-
- context "when no params are added" do
- before do
- get path
- end
-
- it "redirects to the .git suffix version" do
- expect(response).to redirect_to("/#{project.full_path}.git/info/refs")
- end
- end
-
- context "when the upload-pack service is requested" do
- let(:params) { { service: 'git-upload-pack' } }
-
- before do
- get path, params: params
- end
-
- it "redirects to the .git suffix version" do
- expect(response).to redirect_to("/#{project.full_path}.git/info/refs?service=#{params[:service]}")
- end
- end
-
- context "when the receive-pack service is requested" do
- let(:params) { { service: 'git-receive-pack' } }
-
- before do
- get path, params: params
- end
-
- it "redirects to the .git suffix version" do
- expect(response).to redirect_to("/#{project.full_path}.git/info/refs?service=#{params[:service]}")
- end
- end
-
- context "when the params are anything else" do
- let(:params) { { service: 'git-implode-pack' } }
-
- before do
- get path, params: params
- end
-
- it "redirects to the sign-in page" do
- expect(response).to redirect_to(new_user_session_path)
- end
- end
- end
-
- context "POST git-upload-pack" do
- it "fails to find a route" do
- expect { clone_post(project.full_path) }.to raise_error(ActionController::RoutingError)
- end
- end
-
- context "POST git-receive-pack" do
- it "fails to find a route" do
- expect { push_post(project.full_path) }.to raise_error(ActionController::RoutingError)
- end
- end
+ it_behaves_like 'project path without .git suffix' do
+ let(:project_path) { create(:project, :repository, :public, path: 'project.git-project').full_path }
end
context "retrieving an info/refs file" do
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index 3cc29a7076d..1781759c54b 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -1086,6 +1086,12 @@ describe 'Git LFS API and storage' do
end
end
+ context 'and request to finalize the upload is not sent by gitlab-workhorse' do
+ it 'fails with a JWT decode error' do
+ expect { put_finalize(lfs_tmp_file, verified: false) }.to raise_error(JWT::DecodeError)
+ end
+ end
+
context 'and workhorse requests upload finalize for a new lfs object' do
before do
lfs_object.destroy
@@ -1123,7 +1129,7 @@ describe 'Git LFS API and storage' do
context 'with valid remote_id' do
before do
- fog_connection.directories.get('lfs-objects').files.create(
+ fog_connection.directories.new(key: 'lfs-objects').files.create(
key: 'tmp/uploads/12312300',
body: 'content'
)
@@ -1347,9 +1353,13 @@ describe 'Git LFS API and storage' do
context 'when pushing the same lfs object to the second project' do
before do
+ finalize_headers = headers
+ .merge('X-Gitlab-Lfs-Tmp' => lfs_tmp_file)
+ .merge(workhorse_internal_api_request_header)
+
put "#{second_project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}/#{sample_size}",
params: {},
- headers: headers.merge('X-Gitlab-Lfs-Tmp' => lfs_tmp_file).compact
+ headers: finalize_headers
end
it 'responds with status 200' do
@@ -1370,7 +1380,7 @@ describe 'Git LFS API and storage' do
put "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}/#{sample_size}/authorize", params: {}, headers: authorize_headers
end
- def put_finalize(lfs_tmp = lfs_tmp_file, with_tempfile: false, args: {})
+ def put_finalize(lfs_tmp = lfs_tmp_file, with_tempfile: false, verified: true, args: {})
upload_path = LfsObjectUploader.workhorse_local_upload_path
file_path = upload_path + '/' + lfs_tmp if lfs_tmp
@@ -1384,11 +1394,14 @@ describe 'Git LFS API and storage' do
'file.name' => File.basename(file_path)
}
- put_finalize_with_args(args.merge(extra_args).compact)
+ put_finalize_with_args(args.merge(extra_args).compact, verified: verified)
end
- def put_finalize_with_args(args)
- put "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}/#{sample_size}", params: args, headers: headers
+ def put_finalize_with_args(args, verified:)
+ finalize_headers = headers
+ finalize_headers.merge!(workhorse_internal_api_request_header) if verified
+
+ put "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}/#{sample_size}", params: args, headers: finalize_headers
end
def lfs_tmp_file
diff --git a/spec/requests/lfs_locks_api_spec.rb b/spec/requests/lfs_locks_api_spec.rb
index 28cb90e450e..5b7b3d2fdd6 100644
--- a/spec/requests/lfs_locks_api_spec.rb
+++ b/spec/requests/lfs_locks_api_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'Git LFS File Locking API' do
include WorkhorseHelpers
- let(:project) { create(:project) }
+ let(:project) { create(:project) }
let(:maintainer) { create(:user) }
let(:developer) { create(:user) }
let(:guest) { create(:user) }
@@ -132,6 +132,17 @@ describe 'Git LFS File Locking API' do
expect(json_response['lock'].keys).to match_array(%w(id path locked_at owner))
end
+
+ context 'when a maintainer uses force' do
+ let(:authorization) { authorize_user(maintainer) }
+
+ it 'deletes the lock' do
+ project.add_maintainer(maintainer)
+ post_lfs_json url, { force: true }, headers
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
end
end
@@ -149,7 +160,7 @@ describe 'Git LFS File Locking API' do
post(url, params: body.try(:to_json), headers: (headers || {}).merge('Content-Type' => LfsRequest::CONTENT_TYPE))
end
- def do_get(url, params = nil, headers = nil)
+ def do_get(url, params = nil, headers = nil)
get(url, params: (params || {}), headers: (headers || {}).merge('Content-Type' => LfsRequest::CONTENT_TYPE))
end
diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb
index 2b148c1b563..2a455523e2c 100644
--- a/spec/requests/openid_connect_spec.rb
+++ b/spec/requests/openid_connect_spec.rb
@@ -35,7 +35,7 @@ describe 'OpenID Connect requests' do
'name' => 'Alice',
'nickname' => 'alice',
'email' => 'public@example.com',
- 'email_verified' => true,
+ 'email_verified' => false,
'website' => 'https://example.com',
'profile' => 'http://localhost/alice',
'picture' => "http://localhost/uploads/-/system/user/avatar/#{user.id}/dk.png",
@@ -111,6 +111,18 @@ describe 'OpenID Connect requests' do
it 'does not include any unknown claims' do
expect(json_response.keys).to eq %w[sub sub_legacy] + user_info_claims.keys
end
+
+ it 'includes email and email_verified claims' do
+ expect(json_response.keys).to include('email', 'email_verified')
+ end
+
+ it 'has public email in email claim' do
+ expect(json_response['email']).to eq(user.public_email)
+ end
+
+ it 'has false in email_verified claim' do
+ expect(json_response['email_verified']).to eq(false)
+ end
end
context 'ID token payload' do
@@ -175,7 +187,35 @@ describe 'OpenID Connect requests' do
expect(response).to have_gitlab_http_status(200)
expect(json_response['issuer']).to eq('http://localhost')
expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
- expect(json_response['scopes_supported']).to eq(%w[api read_user sudo read_repository openid])
+ expect(json_response['scopes_supported']).to eq(%w[api read_user sudo read_repository openid profile email])
+ end
+ end
+
+ context 'Application with OpenID and email scopes' do
+ let(:application) { create :oauth_application, scopes: 'openid email' }
+
+ it 'token response includes an ID token' do
+ request_access_token!
+
+ expect(json_response).to include 'id_token'
+ end
+
+ context 'UserInfo payload' do
+ before do
+ request_user_info!
+ end
+
+ it 'includes the email and email_verified claims' do
+ expect(json_response.keys).to include('email', 'email_verified')
+ end
+
+ it 'has private email in email claim' do
+ expect(json_response['email']).to eq(user.email)
+ end
+
+ it 'has true in email_verified claim' do
+ expect(json_response['email_verified']).to eq(true)
+ end
end
end
end
diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb
index bcc3e3a2678..49412b628b3 100644
--- a/spec/requests/projects/cycle_analytics_events_spec.rb
+++ b/spec/requests/projects/cycle_analytics_events_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'cycle analytics events' do
let(:user) { create(:user) }
let(:project) { create(:project, :repository, public_builds: false) }
- let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
+ let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
describe 'GET /:namespace/:project/cycle_analytics/events/issues' do
before do
diff --git a/spec/requests/request_profiler_spec.rb b/spec/requests/request_profiler_spec.rb
index 284a51fcc32..75b22b1879b 100644
--- a/spec/requests/request_profiler_spec.rb
+++ b/spec/requests/request_profiler_spec.rb
@@ -18,7 +18,7 @@ describe 'Request Profiler' do
path = "/#{project.full_path}"
Timecop.freeze(time) do
- get path, params: {}, headers: { 'X-Profile-Token' => Gitlab::RequestProfiler.profile_token }
+ get path, params: {}, headers: { 'X-Profile-Token' => Gitlab::RequestProfiler.profile_token }
end
profile_path = "#{Gitlab.config.shared.path}/tmp/requests_profiles/#{path.tr('/', '|')}_#{time.to_i}.html"
diff --git a/spec/requests/user_activity_spec.rb b/spec/requests/user_activity_spec.rb
new file mode 100644
index 00000000000..15666e00b9f
--- /dev/null
+++ b/spec/requests/user_activity_spec.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Update of user activity' do
+ let(:user) { create(:user, last_activity_on: nil) }
+
+ before do
+ group = create(:group, name: 'group')
+ project = create(:project, :public, namespace: group, name: 'project')
+
+ create(:issue, project: project, iid: 10)
+ create(:merge_request, source_project: project, iid: 15)
+
+ project.add_maintainer(user)
+ end
+
+ paths_to_visit = [
+ '/group',
+ '/group/project',
+ '/groups/group/-/issues',
+ '/groups/group/-/boards',
+ '/dashboard/projects',
+ '/dashboard/snippets',
+ '/dashboard/groups',
+ '/dashboard/todos',
+ '/group/project/issues',
+ '/group/project/issues/10',
+ '/group/project/merge_requests',
+ '/group/project/merge_requests/15'
+ ]
+
+ context 'without an authenticated user' do
+ it 'does not set the last activity cookie' do
+ get "/group/project"
+
+ expect(response.cookies['user_last_activity_on']).to be_nil
+ end
+ end
+
+ context 'with an authenticated user' do
+ before do
+ login_as(user)
+ end
+
+ context 'with a POST request' do
+ it 'does not set the last activity cookie' do
+ post "/group/project/archive"
+
+ expect(response.cookies['user_last_activity_on']).to be_nil
+ end
+ end
+
+ paths_to_visit.each do |path|
+ context "on GET to #{path}" do
+ it 'updates the last activity date' do
+ expect(Users::ActivityService).to receive(:new).and_call_original
+
+ get path
+
+ expect(user.last_activity_on).to eq(Date.today)
+ end
+
+ context 'when calling it twice' do
+ it 'updates last_activity_on just once' do
+ expect(Users::ActivityService).to receive(:new).once.and_call_original
+
+ 2.times do
+ get path
+ end
+ end
+ end
+
+ context 'when last_activity_on is nil' do
+ before do
+ user.update_attribute(:last_activity_on, nil)
+ end
+
+ it 'updates the last activity date' do
+ expect(user.last_activity_on).to be_nil
+
+ get path
+
+ expect(user.last_activity_on).to eq(Date.today)
+ end
+ end
+
+ context 'when last_activity_on is stale' do
+ before do
+ user.update_attribute(:last_activity_on, 2.days.ago.to_date)
+ end
+
+ it 'updates the last activity date' do
+ get path
+
+ expect(user.last_activity_on).to eq(Date.today)
+ end
+ end
+
+ context 'when last_activity_on is up to date' do
+ before do
+ user.update_attribute(:last_activity_on, Date.today)
+ end
+
+ it 'does not try to update it' do
+ expect(Users::ActivityService).not_to receive(:new)
+
+ get path
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/routing/import_routing_spec.rb b/spec/routing/import_routing_spec.rb
index 78ff9c6e6fd..106f92082e4 100644
--- a/spec/routing/import_routing_spec.rb
+++ b/spec/routing/import_routing_spec.rb
@@ -23,6 +23,11 @@ require 'spec_helper'
# end
shared_examples 'importer routing' do
let(:except_actions) { [] }
+ let(:is_realtime) { false }
+
+ before do
+ except_actions.push(is_realtime ? :jobs : :realtime_changes)
+ end
it 'to #create' do
expect(post("/import/#{provider}")).to route_to("import/#{provider}#create") unless except_actions.include?(:create)
@@ -43,17 +48,22 @@ shared_examples 'importer routing' do
it 'to #jobs' do
expect(get("/import/#{provider}/jobs")).to route_to("import/#{provider}#jobs") unless except_actions.include?(:jobs)
end
+
+ it 'to #realtime_changes' do
+ expect(get("/import/#{provider}/realtime_changes")).to route_to("import/#{provider}#realtime_changes") unless except_actions.include?(:realtime_changes)
+ end
end
# personal_access_token_import_github POST /import/github/personal_access_token(.:format) import/github#personal_access_token
# status_import_github GET /import/github/status(.:format) import/github#status
# callback_import_github GET /import/github/callback(.:format) import/github#callback
-# jobs_import_github GET /import/github/jobs(.:format) import/github#jobs
+# realtime_changes_import_github GET /import/github/realtime_changes(.:format) import/github#jobs
# import_github POST /import/github(.:format) import/github#create
# new_import_github GET /import/github/new(.:format) import/github#new
describe Import::GithubController, 'routing' do
it_behaves_like 'importer routing' do
let(:provider) { 'github' }
+ let(:is_realtime) { true }
end
it 'to #personal_access_token' do
@@ -63,13 +73,14 @@ end
# personal_access_token_import_gitea POST /import/gitea/personal_access_token(.:format) import/gitea#personal_access_token
# status_import_gitea GET /import/gitea/status(.:format) import/gitea#status
-# jobs_import_gitea GET /import/gitea/jobs(.:format) import/gitea#jobs
+# realtime_changes_import_gitea GET /import/gitea/realtime_changes(.:format) import/gitea#jobs
# import_gitea POST /import/gitea(.:format) import/gitea#create
# new_import_gitea GET /import/gitea/new(.:format) import/gitea#new
describe Import::GiteaController, 'routing' do
it_behaves_like 'importer routing' do
let(:except_actions) { [:callback] }
let(:provider) { 'gitea' }
+ let(:is_realtime) { true }
end
it 'to #personal_access_token' do
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 5c3b37ef11c..a0d01fc8263 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -122,6 +122,10 @@ describe 'project routing' do
route_to('projects#preview_markdown', namespace_id: 'gitlab', id: 'gitlabhq')
)
end
+
+ it 'to #resolve' do
+ expect(get('/projects/1')).to route_to('projects#resolve', id: '1')
+ end
end
# members_namespace_project_autocomplete_sources_path GET /:project_id/autocomplete_sources/members(.:format) projects/autocomplete_sources#members
diff --git a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
index 08ffc3c3a53..0ff777388e5 100644
--- a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
+++ b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
@@ -19,6 +19,41 @@ describe RuboCop::Cop::InjectEnterpriseEditionModule do
SOURCE
end
+ it 'does not flag the use of `prepend EEFoo` in the middle of a file' do
+ expect_no_offenses(<<~SOURCE)
+ class Foo
+ prepend EEFoo
+ end
+ SOURCE
+ end
+
+ it 'flags the use of `prepend EE::Foo::Bar` in the middle of a file' do
+ expect_offense(<<~SOURCE)
+ class Foo
+ prepend EE::Foo::Bar
+ ^^^^^^^^^^^^^^^^^^^^ Injecting EE modules must be done on the last line of this file, outside of any class or module definitions
+ end
+ SOURCE
+ end
+
+ it 'flags the use of `prepend(EE::Foo::Bar)` in the middle of a file' do
+ expect_offense(<<~SOURCE)
+ class Foo
+ prepend(EE::Foo::Bar)
+ ^^^^^^^^^^^^^^^^^^^^^ Injecting EE modules must be done on the last line of this file, outside of any class or module definitions
+ end
+ SOURCE
+ end
+
+ it 'flags the use of `prepend EE::Foo::Bar::Baz` in the middle of a file' do
+ expect_offense(<<~SOURCE)
+ class Foo
+ prepend EE::Foo::Bar::Baz
+ ^^^^^^^^^^^^^^^^^^^^^^^^^ Injecting EE modules must be done on the last line of this file, outside of any class or module definitions
+ end
+ SOURCE
+ end
+
it 'flags the use of `prepend ::EE` in the middle of a file' do
expect_offense(<<~SOURCE)
class Foo
diff --git a/spec/serializers/cluster_application_entity_spec.rb b/spec/serializers/cluster_application_entity_spec.rb
index 852b6af9f7f..7e151c3744e 100644
--- a/spec/serializers/cluster_application_entity_spec.rb
+++ b/spec/serializers/cluster_application_entity_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe ClusterApplicationEntity do
describe '#as_json' do
- let(:application) { build(:clusters_applications_helm) }
+ let(:application) { build(:clusters_applications_helm, version: '0.1.1') }
subject { described_class.new(application).as_json }
it 'has name' do
@@ -13,10 +13,22 @@ describe ClusterApplicationEntity do
expect(subject[:status]).to eq(:not_installable)
end
+ it 'has version' do
+ expect(subject[:version]).to eq('0.1.1')
+ end
+
it 'has no status_reason' do
expect(subject[:status_reason]).to be_nil
end
+ context 'non-helm application' do
+ let(:application) { build(:clusters_applications_runner, version: '0.0.0') }
+
+ it 'has update_available' do
+ expect(subject[:update_available]).to be_truthy
+ end
+ end
+
context 'when application is errored' do
let(:application) { build(:clusters_applications_helm, :errored) }
diff --git a/spec/serializers/container_repository_entity_spec.rb b/spec/serializers/container_repository_entity_spec.rb
index c589cd18f77..15466bce514 100644
--- a/spec/serializers/container_repository_entity_spec.rb
+++ b/spec/serializers/container_repository_entity_spec.rb
@@ -19,7 +19,7 @@ describe ContainerRepositoryEntity do
allow(request).to receive(:current_user).and_return(user)
end
- it 'exposes required informations' do
+ it 'exposes required informations' do
expect(subject).to include(:id, :path, :location, :tags_path)
end
diff --git a/spec/serializers/container_tag_entity_spec.rb b/spec/serializers/container_tag_entity_spec.rb
index 4beb50c70f8..ceb828a1cc5 100644
--- a/spec/serializers/container_tag_entity_spec.rb
+++ b/spec/serializers/container_tag_entity_spec.rb
@@ -16,7 +16,7 @@ describe ContainerTagEntity do
before do
stub_container_registry_config(enabled: true)
- stub_container_registry_tags(repository: /image/, tags: %w[test])
+ stub_container_registry_tags(repository: /image/, tags: %w[test], with_manifest: true)
allow(request).to receive(:project).and_return(project)
allow(request).to receive(:current_user).and_return(user)
end
diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb
index 8793a762f9d..894fd7a0a12 100644
--- a/spec/serializers/deployment_entity_spec.rb
+++ b/spec/serializers/deployment_entity_spec.rb
@@ -1,17 +1,25 @@
require 'spec_helper'
describe DeploymentEntity do
- let(:user) { create(:user) }
+ let(:user) { developer }
+ let(:developer) { create(:user) }
+ let(:reporter) { create(:user) }
+ let(:project) { create(:project) }
let(:request) { double('request') }
- let(:deployment) { create(:deployment) }
+ let(:deployment) { create(:deployment, deployable: build, project: project) }
+ let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
+ let(:pipeline) { create(:ci_pipeline, project: project, user: user) }
let(:entity) { described_class.new(deployment, request: request) }
subject { entity.as_json }
before do
+ project.add_developer(developer)
+ project.add_reporter(reporter)
allow(request).to receive(:current_user).and_return(user)
+ allow(request).to receive(:project).and_return(project)
end
- it 'exposes internal deployment id' do
+ it 'exposes internal deployment id' do
expect(subject).to include(:iid)
end
@@ -23,6 +31,24 @@ describe DeploymentEntity do
expect(subject).to include(:created_at)
end
+ context 'when the pipeline has another manual action' do
+ let(:other_build) { create(:ci_build, :manual, name: 'another deploy', pipeline: pipeline) }
+ let!(:other_deployment) { create(:deployment, deployable: other_build) }
+
+ it 'returns another manual action' do
+ expect(subject[:manual_actions].count).to eq(1)
+ expect(subject[:manual_actions].first[:name]).to eq('another deploy')
+ end
+
+ context 'when user is a reporter' do
+ let(:user) { reporter }
+
+ it 'returns another manual action' do
+ expect(subject[:manual_actions]).not_to be_present
+ end
+ end
+ end
+
describe 'scheduled_actions' do
let(:project) { create(:project, :repository) }
let(:pipeline) { create(:ci_pipeline, project: project, user: user) }
diff --git a/spec/serializers/diff_file_entity_spec.rb b/spec/serializers/diff_file_entity_spec.rb
index 073c13c2cbb..92b649f5b6c 100644
--- a/spec/serializers/diff_file_entity_spec.rb
+++ b/spec/serializers/diff_file_entity_spec.rb
@@ -22,7 +22,7 @@ describe DiffFileEntity do
let(:request) { EntityRequest.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let(:entity) { described_class.new(diff_file, request: request, merge_request: merge_request) }
- let(:exposed_urls) { %i(load_collapsed_diff_url edit_path view_path context_lines_path) }
+ let(:exposed_urls) { %i(edit_path view_path context_lines_path) }
it_behaves_like 'diff file entity'
@@ -38,6 +38,12 @@ describe DiffFileEntity do
expect(response[attribute]).to include(merge_request.target_project.to_param)
end
end
+
+ it 'exposes load_collapsed_diff_url if the file viewer is collapsed' do
+ allow(diff_file.viewer).to receive(:collapsed?) { true }
+
+ expect(subject).to include(:load_collapsed_diff_url)
+ end
end
context '#parallel_diff_lines' do
diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb
index 87493a28d1f..375a28a8c72 100644
--- a/spec/serializers/environment_serializer_spec.rb
+++ b/spec/serializers/environment_serializer_spec.rb
@@ -10,6 +10,10 @@ describe EnvironmentSerializer do
.represent(resource)
end
+ before do
+ project.add_developer(user)
+ end
+
context 'when there is a single object provided' do
let(:project) { create(:project, :repository) }
let(:deployable) { create(:ci_build) }
@@ -120,10 +124,10 @@ describe EnvironmentSerializer do
end
context 'when used with pagination' do
- let(:request) { spy('request') }
+ let(:request) { double(url: "#{Gitlab.config.gitlab.url}:8080/api/v4/projects?#{query.to_query}", query_parameters: query) }
let(:response) { spy('response') }
let(:resource) { Environment.all }
- let(:pagination) { { page: 1, per_page: 2 } }
+ let(:query) { { page: 1, per_page: 2 } }
let(:serializer) do
described_class
@@ -131,11 +135,6 @@ describe EnvironmentSerializer do
.with_pagination(request, response)
end
- before do
- allow(request).to receive(:query_parameters)
- .and_return(pagination)
- end
-
subject { serializer.represent(resource) }
it 'creates a paginated serializer' do
diff --git a/spec/serializers/group_child_entity_spec.rb b/spec/serializers/group_child_entity_spec.rb
index dbc40bddc30..d02b4c554b1 100644
--- a/spec/serializers/group_child_entity_spec.rb
+++ b/spec/serializers/group_child_entity_spec.rb
@@ -10,6 +10,7 @@ describe GroupChildEntity do
before do
allow(request).to receive(:current_user).and_return(user)
+ stub_commonmark_sourcepos_disabled
end
shared_examples 'group child json' do
diff --git a/spec/serializers/merge_request_for_pipeline_entity_spec.rb b/spec/serializers/merge_request_for_pipeline_entity_spec.rb
new file mode 100644
index 00000000000..e49b45bc7d7
--- /dev/null
+++ b/spec/serializers/merge_request_for_pipeline_entity_spec.rb
@@ -0,0 +1,29 @@
+require 'spec_helper'
+
+describe MergeRequestForPipelineEntity do
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+ let(:request) { EntityRequest.new(project: project) }
+ let(:merge_request) { create(:merge_request, target_project: project, source_project: project) }
+ let(:presenter) { MergeRequestPresenter.new(merge_request, current_user: user) }
+
+ let(:entity) do
+ described_class.new(presenter, request: request)
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ context 'as json' do
+ subject { entity.as_json }
+
+ it 'exposes needed attributes' do
+ expect(subject).to include(
+ :iid, :path, :title,
+ :source_branch, :source_branch_path,
+ :target_branch, :target_branch_path
+ )
+ end
+ end
+end
diff --git a/spec/serializers/merge_request_widget_commit_entity_spec.rb b/spec/serializers/merge_request_widget_commit_entity_spec.rb
new file mode 100644
index 00000000000..ce83978c49a
--- /dev/null
+++ b/spec/serializers/merge_request_widget_commit_entity_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MergeRequestWidgetCommitEntity do
+ let(:project) { create(:project, :repository) }
+ let(:commit) { project.commit }
+ let(:request) { double('request') }
+
+ let(:entity) do
+ described_class.new(commit, request: request)
+ end
+
+ context 'as json' do
+ subject { entity.as_json }
+
+ it { expect(subject[:message]).to eq(commit.safe_message) }
+ it { expect(subject[:short_id]).to eq(commit.short_id) }
+ it { expect(subject[:title]).to eq(commit.title) }
+ end
+end
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index 561421d5ac8..4dbd79f2fc0 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -31,23 +31,40 @@ describe MergeRequestWidgetEntity do
describe 'pipeline' do
let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.source_branch, sha: resource.source_branch_sha, head_pipeline_of: resource) }
- context 'when is up to date' do
- let(:req) { double('request', current_user: user, project: project) }
+ before do
+ allow_any_instance_of(MergeRequestPresenter).to receive(:can?).and_call_original
+ allow_any_instance_of(MergeRequestPresenter).to receive(:can?).with(user, :read_pipeline, anything).and_return(result)
+ end
- it 'returns pipeline' do
- pipeline_payload = PipelineDetailsEntity
- .represent(pipeline, request: req)
- .as_json
+ context 'when user has access to pipelines' do
+ let(:result) { true }
+
+ context 'when is up to date' do
+ let(:req) { double('request', current_user: user, project: project) }
+
+ it 'returns pipeline' do
+ pipeline_payload = PipelineDetailsEntity
+ .represent(pipeline, request: req)
+ .as_json
- expect(subject[:pipeline]).to eq(pipeline_payload)
+ expect(subject[:pipeline]).to eq(pipeline_payload)
+ end
+ end
+
+ context 'when is not up to date' do
+ it 'returns nil' do
+ pipeline.update(sha: "not up to date")
+
+ expect(subject[:pipeline]).to eq(nil)
+ end
end
end
- context 'when is not up to date' do
- it 'returns nil' do
- pipeline.update(sha: "not up to date")
+ context 'when user does not have access to pipelines' do
+ let(:result) { false }
- expect(subject[:pipeline]).to be_nil
+ it 'does not have pipeline' do
+ expect(subject[:pipeline]).to eq(nil)
end
end
end
@@ -171,9 +188,14 @@ describe MergeRequestWidgetEntity do
.to eq("/#{resource.project.full_path}/merge_requests/#{resource.iid}.diff")
end
- it 'has merge_commit_message_with_description' do
- expect(subject[:merge_commit_message_with_description])
- .to eq(resource.merge_commit_message(include_description: true))
+ it 'has default_merge_commit_message_with_description' do
+ expect(subject[:default_merge_commit_message_with_description])
+ .to eq(resource.default_merge_commit_message(include_description: true))
+ end
+
+ it 'has default_squash_commit_message' do
+ expect(subject[:default_squash_commit_message])
+ .to eq(resource.default_squash_commit_message)
end
describe 'new_blob_path' do
@@ -255,4 +277,15 @@ describe MergeRequestWidgetEntity do
expect(entity[:rebase_path]).to be_nil
end
end
+
+ describe 'commits_without_merge_commits' do
+ it 'should not include merge commits' do
+ # Mock all but the first 5 commits to be merge commits
+ resource.commits.each_with_index do |commit, i|
+ expect(commit).to receive(:merge_commit?).at_least(:once).and_return(i > 4)
+ end
+
+ expect(subject[:commits_without_merge_commits].size).to eq(5)
+ end
+ end
end
diff --git a/spec/serializers/namespace_basic_entity_spec.rb b/spec/serializers/namespace_basic_entity_spec.rb
new file mode 100644
index 00000000000..f8b71ceb9f3
--- /dev/null
+++ b/spec/serializers/namespace_basic_entity_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe NamespaceBasicEntity do
+ set(:group) { create(:group) }
+ let(:entity) do
+ described_class.represent(group)
+ end
+
+ describe '#as_json' do
+ subject { entity.as_json }
+
+ it 'includes required fields' do
+ expect(subject).to include :id, :full_path
+ end
+ end
+end
diff --git a/spec/serializers/namespace_serializer_spec.rb b/spec/serializers/namespace_serializer_spec.rb
new file mode 100644
index 00000000000..6e5bdd8c52d
--- /dev/null
+++ b/spec/serializers/namespace_serializer_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe NamespaceSerializer do
+ it 'represents NamespaceBasicEntity entities' do
+ expect(described_class.entity_class).to eq(NamespaceBasicEntity)
+ end
+end
diff --git a/spec/serializers/pipeline_entity_spec.rb b/spec/serializers/pipeline_entity_spec.rb
index 774486dcb6d..11040862129 100644
--- a/spec/serializers/pipeline_entity_spec.rb
+++ b/spec/serializers/pipeline_entity_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe PipelineEntity do
+ include Gitlab::Routing
+
set(:user) { create(:user) }
let(:request) { double('request') }
@@ -128,5 +130,48 @@ describe PipelineEntity do
.to eq 'CI/CD YAML configuration error!'
end
end
+
+ context 'when pipeline is detached merge request pipeline' do
+ let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) }
+ let(:project) { merge_request.target_project }
+ let(:pipeline) { merge_request.merge_request_pipelines.first }
+
+ it 'makes detached flag true' do
+ expect(subject[:flags][:detached]).to be_truthy
+ end
+
+ context 'when user is a developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'has merge request information' do
+ expect(subject[:merge_request][:iid]).to eq(merge_request.iid)
+
+ expect(project_merge_request_path(project, merge_request))
+ .to include(subject[:merge_request][:path])
+
+ expect(subject[:merge_request][:title]).to eq(merge_request.title)
+
+ expect(subject[:merge_request][:source_branch])
+ .to eq(merge_request.source_branch)
+
+ expect(project_branch_path(project, merge_request.source_branch))
+ .to include(subject[:merge_request][:source_branch_path])
+
+ expect(subject[:merge_request][:target_branch])
+ .to eq(merge_request.target_branch)
+
+ expect(project_branch_path(project, merge_request.target_branch))
+ .to include(subject[:merge_request][:target_branch_path])
+ end
+ end
+
+ context 'when user is an external user' do
+ it 'has no merge request information' do
+ expect(subject[:merge_request]).to be_nil
+ end
+ end
+ end
end
end
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index cf57776346a..a21487938a0 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -38,15 +38,9 @@ describe PipelineSerializer do
end
context 'when used with pagination' do
- let(:request) { spy('request') }
+ let(:request) { double(url: "#{Gitlab.config.gitlab.url}:8080/api/v4/projects?#{query.to_query}", query_parameters: query) }
let(:response) { spy('response') }
- let(:pagination) { {} }
-
- before do
- allow(request)
- .to receive(:query_parameters)
- .and_return(pagination)
- end
+ let(:query) { {} }
let(:serializer) do
described_class.new(current_user: user)
@@ -60,7 +54,7 @@ describe PipelineSerializer do
context 'when resource is not paginatable' do
context 'when a single pipeline object is being serialized' do
let(:resource) { create(:ci_empty_pipeline) }
- let(:pagination) { { page: 1, per_page: 1 } }
+ let(:query) { { page: 1, per_page: 1 } }
it 'raises error' do
expect { subject }.to raise_error(
@@ -71,7 +65,7 @@ describe PipelineSerializer do
context 'when resource is paginatable relation' do
let(:resource) { Ci::Pipeline.all }
- let(:pagination) { { page: 1, per_page: 2 } }
+ let(:query) { { page: 1, per_page: 2 } }
context 'when a single pipeline object is present in relation' do
before do
@@ -103,6 +97,44 @@ describe PipelineSerializer do
end
end
+ context 'when there are pipelines for merge requests' do
+ let(:resource) { Ci::Pipeline.all }
+
+ let!(:merge_request_1) do
+ create(:merge_request,
+ :with_merge_request_pipeline,
+ target_project: project,
+ target_branch: 'master',
+ source_project: project,
+ source_branch: 'feature-1')
+ end
+
+ let!(:merge_request_2) do
+ create(:merge_request,
+ :with_merge_request_pipeline,
+ target_project: project,
+ target_branch: 'master',
+ source_project: project,
+ source_branch: 'feature-2')
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it 'includes merge requests information' do
+ expect(subject.all? { |entry| entry[:merge_request].present? }).to be_truthy
+ end
+
+ it 'preloads related merge requests', :postgresql do
+ recorded = ActiveRecord::QueryRecorder.new { subject }
+
+ expect(recorded.log)
+ .to include("SELECT \"merge_requests\".* FROM \"merge_requests\" " \
+ "WHERE \"merge_requests\".\"id\" IN (#{merge_request_1.id}, #{merge_request_2.id})")
+ end
+ end
+
describe 'number of queries when preloaded' do
subject { serializer.represent(resource, preload: true) }
let(:resource) { Ci::Pipeline.all }
@@ -144,7 +176,7 @@ describe PipelineSerializer do
# pipeline. With the same ref this check is cached but if refs are
# different then there is an extra query per ref
# https://gitlab.com/gitlab-org/gitlab-ce/issues/46368
- expect(recorded.count).to be_within(2).of(34)
+ expect(recorded.count).to be_within(2).of(38)
expect(recorded.cached_count).to eq(0)
end
end
diff --git a/spec/serializers/project_import_entity_spec.rb b/spec/serializers/project_import_entity_spec.rb
new file mode 100644
index 00000000000..e476da82729
--- /dev/null
+++ b/spec/serializers/project_import_entity_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProjectImportEntity do
+ include ImportHelper
+
+ set(:project) { create(:project, import_status: :started, import_source: 'namespace/project') }
+ let(:provider_url) { 'https://provider.com' }
+ let(:entity) { described_class.represent(project, provider_url: provider_url) }
+
+ describe '#as_json' do
+ subject { entity.as_json }
+
+ it 'includes required fields' do
+ expect(subject[:import_source]).to eq(project.import_source)
+ expect(subject[:import_status]).to eq(project.import_status)
+ expect(subject[:human_import_status_name]).to eq(project.human_import_status_name)
+ expect(subject[:provider_link]).to eq(provider_project_link_url(provider_url, project[:import_source]))
+ end
+ end
+end
diff --git a/spec/serializers/project_serializer_spec.rb b/spec/serializers/project_serializer_spec.rb
new file mode 100644
index 00000000000..22f958fc17f
--- /dev/null
+++ b/spec/serializers/project_serializer_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProjectSerializer do
+ set(:project) { create(:project) }
+ let(:provider_url) { 'http://provider.com' }
+
+ context 'when serializer option is :import' do
+ subject do
+ described_class.new.represent(project, serializer: :import, provider_url: provider_url)
+ end
+
+ before do
+ allow(ProjectImportEntity).to receive(:represent)
+ end
+
+ it 'represents with ProjectImportEntity' do
+ subject
+
+ expect(ProjectImportEntity)
+ .to have_received(:represent)
+ .with(project, serializer: :import, provider_url: provider_url, request: an_instance_of(EntityRequest))
+ end
+ end
+
+ context 'when serializer option is omitted' do
+ subject do
+ described_class.new.represent(project)
+ end
+
+ before do
+ allow(ProjectEntity).to receive(:represent)
+ end
+
+ it 'represents with ProjectEntity' do
+ subject
+
+ expect(ProjectEntity)
+ .to have_received(:represent)
+ .with(project, request: an_instance_of(EntityRequest))
+ end
+ end
+end
diff --git a/spec/serializers/provider_repo_entity_spec.rb b/spec/serializers/provider_repo_entity_spec.rb
new file mode 100644
index 00000000000..9a1160d16d5
--- /dev/null
+++ b/spec/serializers/provider_repo_entity_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProviderRepoEntity do
+ include ImportHelper
+
+ let(:provider_repo) { { id: 1, full_name: 'full/name', name: 'name', owner: { login: 'owner' } } }
+ let(:provider) { :github }
+ let(:provider_url) { 'https://github.com' }
+ let(:entity) { described_class.represent(provider_repo, provider: provider, provider_url: provider_url) }
+
+ describe '#as_json' do
+ subject { entity.as_json }
+
+ it 'includes required fields' do
+ expect(subject[:id]).to eq(provider_repo[:id])
+ expect(subject[:full_name]).to eq(provider_repo[:full_name])
+ expect(subject[:owner_name]).to eq(provider_repo[:owner][:login])
+ expect(subject[:sanitized_name]).to eq(sanitize_project_name(provider_repo[:name]))
+ expect(subject[:provider_link]).to eq(provider_project_link_url(provider_url, provider_repo[:full_name]))
+ end
+ end
+end
diff --git a/spec/serializers/provider_repo_serializer_spec.rb b/spec/serializers/provider_repo_serializer_spec.rb
new file mode 100644
index 00000000000..f2be30c36d9
--- /dev/null
+++ b/spec/serializers/provider_repo_serializer_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProviderRepoSerializer do
+ it 'represents ProviderRepoEntity entities' do
+ expect(described_class.entity_class).to eq(ProviderRepoEntity)
+ end
+end
diff --git a/spec/services/application_settings/update_service_spec.rb b/spec/services/application_settings/update_service_spec.rb
index daf5dfba6b1..a4a733eff77 100644
--- a/spec/services/application_settings/update_service_spec.rb
+++ b/spec/services/application_settings/update_service_spec.rb
@@ -17,7 +17,7 @@ describe ApplicationSettings::UpdateService do
describe 'updating terms' do
context 'when the passed terms are blank' do
- let(:params) { { terms: '' } }
+ let(:params) { { terms: '' } }
it 'does not create terms' do
expect { subject.execute }.not_to change { ApplicationSetting::Term.count }
@@ -25,7 +25,7 @@ describe ApplicationSettings::UpdateService do
end
context 'when passing terms' do
- let(:params) { { terms: 'Be nice! ' } }
+ let(:params) { { terms: 'Be nice! ' } }
it 'creates the terms' do
expect { subject.execute }.to change { ApplicationSetting::Term.count }.by(1)
diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb
index f2e9799452a..8021bd338e0 100644
--- a/spec/services/auth/container_registry_authentication_service_spec.rb
+++ b/spec/services/auth/container_registry_authentication_service_spec.rb
@@ -5,7 +5,7 @@ describe Auth::ContainerRegistryAuthenticationService do
let(:current_user) { nil }
let(:current_params) { {} }
let(:rsa_key) { OpenSSL::PKey::RSA.generate(512) }
- let(:payload) { JWT.decode(subject[:token], rsa_key).first }
+ let(:payload) { JWT.decode(subject[:token], rsa_key, true, { algorithm: 'RS256' }).first }
let(:authentication_abilities) do
[:read_container_image, :create_container_image, :admin_container_image]
diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb
index 010679b5360..aaad29536af 100644
--- a/spec/services/boards/issues/list_service_spec.rb
+++ b/spec/services/boards/issues/list_service_spec.rb
@@ -12,7 +12,7 @@ describe Boards::Issues::ListService do
let(:bug) { create(:label, project: project, name: 'Bug') }
let(:development) { create(:label, project: project, name: 'Development') }
- let(:testing) { create(:label, project: project, name: 'Testing') }
+ let(:testing) { create(:label, project: project, name: 'Testing') }
let(:p1) { create(:label, title: 'P1', project: project, priority: 1) }
let(:p2) { create(:label, title: 'P2', project: project, priority: 2) }
let(:p3) { create(:label, title: 'P3', project: project, priority: 3) }
@@ -63,7 +63,7 @@ describe Boards::Issues::ListService do
let(:bug) { create(:group_label, group: group, name: 'Bug') }
let(:development) { create(:group_label, group: group, name: 'Development') }
- let(:testing) { create(:group_label, group: group, name: 'Testing') }
+ let(:testing) { create(:group_label, group: group, name: 'Testing') }
let(:p1) { create(:group_label, title: 'P1', group: group) }
let(:p2) { create(:group_label, title: 'P2', group: group) }
diff --git a/spec/services/boards/issues/move_service_spec.rb b/spec/services/boards/issues/move_service_spec.rb
index dd0ad5f11bd..6020f0771e5 100644
--- a/spec/services/boards/issues/move_service_spec.rb
+++ b/spec/services/boards/issues/move_service_spec.rb
@@ -10,7 +10,7 @@ describe Boards::Issues::MoveService do
let(:bug) { create(:label, project: project, name: 'Bug') }
let(:development) { create(:label, project: project, name: 'Development') }
- let(:testing) { create(:label, project: project, name: 'Testing') }
+ let(:testing) { create(:label, project: project, name: 'Testing') }
let(:regression) { create(:label, project: project, name: 'Regression') }
let!(:list1) { create(:list, board: board1, label: development, position: 0) }
@@ -35,7 +35,7 @@ describe Boards::Issues::MoveService do
let(:bug) { create(:group_label, group: group, name: 'Bug') }
let(:development) { create(:group_label, group: group, name: 'Development') }
- let(:testing) { create(:group_label, group: group, name: 'Testing') }
+ let(:testing) { create(:group_label, group: group, name: 'Testing') }
let(:regression) { create(:group_label, group: group, name: 'Regression') }
let!(:list1) { create(:list, board: board1, label: development, position: 0) }
diff --git a/spec/services/boards/visits/latest_service_spec.rb b/spec/services/boards/visits/latest_service_spec.rb
index e55d599e2cc..c8a0a5e4243 100644
--- a/spec/services/boards/visits/latest_service_spec.rb
+++ b/spec/services/boards/visits/latest_service_spec.rb
@@ -23,6 +23,12 @@ describe Boards::Visits::LatestService do
service.execute
end
+
+ it 'queries for last N visits' do
+ expect(BoardProjectRecentVisit).to receive(:latest).with(user, project, count: 5).once
+
+ described_class.new(project_board.parent, user, count: 5).execute
+ end
end
context 'when a group board' do
@@ -42,6 +48,12 @@ describe Boards::Visits::LatestService do
service.execute
end
+
+ it 'queries for last N visits' do
+ expect(BoardGroupRecentVisit).to receive(:latest).with(user, group, count: 5).once
+
+ described_class.new(group_board.parent, user, count: 5).execute
+ 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 ffa47d527f7..24707cd2d41 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -12,6 +12,7 @@ describe Ci::CreatePipelineService do
end
describe '#execute' do
+ # rubocop:disable Metrics/ParameterLists
def execute_service(
source: :push,
after: project.commit.id,
@@ -19,16 +20,23 @@ describe Ci::CreatePipelineService do
ref: ref_name,
trigger_request: nil,
variables_attributes: nil,
- merge_request: nil)
+ merge_request: nil,
+ push_options: nil,
+ source_sha: nil,
+ target_sha: nil)
params = { ref: ref,
before: '00000000',
after: after,
commits: [{ message: message }],
- variables_attributes: variables_attributes }
+ variables_attributes: variables_attributes,
+ push_options: push_options,
+ source_sha: source_sha,
+ target_sha: target_sha }
described_class.new(project, user, params).execute(
source, trigger_request: trigger_request, merge_request: merge_request)
end
+ # rubocop:enable Metrics/ParameterLists
context 'valid params' do
let(:pipeline) { execute_service }
@@ -141,7 +149,8 @@ describe Ci::CreatePipelineService do
target_branch: "branch_1",
source_project: project)
- allow_any_instance_of(Ci::Pipeline).to receive(:latest?).and_return(false)
+ allow_any_instance_of(MergeRequest)
+ .to receive(:find_actual_head_pipeline) { }
execute_service
@@ -357,6 +366,22 @@ describe Ci::CreatePipelineService do
end
end
+ context 'when push options contain ci.skip' do
+ let(:push_options) do
+ ['ci.skip',
+ 'another push option']
+ end
+
+ it 'creates a pipline in the skipped state' do
+ pipeline = execute_service(push_options: push_options)
+
+ # TODO: DRY these up with "skips builds creation if the commit message"
+ expect(pipeline).to be_persisted
+ expect(pipeline.builds.any?).to be false
+ expect(pipeline.status).to eq("skipped")
+ end
+ end
+
context 'when there are no jobs for this pipeline' do
before do
config = YAML.dump({ test: { script: 'ls', only: ['feature'] } })
@@ -660,17 +685,23 @@ describe Ci::CreatePipelineService do
describe 'Merge request pipelines' do
let(:pipeline) do
- execute_service(source: source, merge_request: merge_request, ref: ref_name)
+ execute_service(source: source,
+ merge_request: merge_request,
+ ref: ref_name,
+ source_sha: source_sha,
+ target_sha: target_sha)
end
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
- let(:ref_name) { 'feature' }
+ let(:ref_name) { 'refs/heads/feature' }
+ let(:source_sha) { project.commit(ref_name).id }
+ let(:target_sha) { nil }
context 'when source is merge request' do
- let(:source) { :merge_request }
+ let(:source) { :merge_request_event }
context "when config has merge_requests keywords" do
let(:config) do
@@ -696,20 +727,36 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: project,
target_branch: 'master')
end
it 'creates a merge request pipeline' do
expect(pipeline).to be_persisted
- expect(pipeline).to be_merge_request
+ expect(pipeline).to be_merge_request_event
expect(pipeline.merge_request).to eq(merge_request)
expect(pipeline.builds.order(:stage_id).map(&:name)).to eq(%w[test])
end
+ it 'persists the specified source sha' do
+ expect(pipeline.source_sha).to eq(source_sha)
+ end
+
+ it 'does not persist target sha for detached merge request pipeline' do
+ expect(pipeline.target_sha).to be_nil
+ end
+
+ context 'when target sha is specified' do
+ let(:target_sha) { merge_request.target_branch_sha }
+
+ it 'persists the target sha' do
+ expect(pipeline.target_sha).to eq(target_sha)
+ end
+ end
+
context 'when ref is tag' do
- let(:ref_name) { 'v1.1.0' }
+ let(:ref_name) { 'refs/tags/v1.1.0' }
it 'does not create a merge request pipeline' do
expect(pipeline).not_to be_persisted
@@ -721,7 +768,7 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: target_project,
target_branch: 'master')
end
@@ -786,7 +833,7 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: project,
target_branch: 'master')
end
@@ -928,7 +975,7 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: project,
target_branch: 'master')
end
diff --git a/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb b/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
new file mode 100644
index 00000000000..80d82ba3ac9
--- /dev/null
+++ b/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
@@ -0,0 +1,104 @@
+require 'spec_helper'
+
+describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared_state do
+ include ExclusiveLeaseHelpers
+
+ describe '.execute' do
+ subject { service.execute }
+
+ let(:service) { described_class.new }
+ let!(:artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
+
+ it 'destroys expired job artifacts' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
+ end
+
+ context 'when artifact is not expired' do
+ let!(:artifact) { create(:ci_job_artifact, expire_at: 1.day.since) }
+
+ it 'does not destroy expired job artifacts' do
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ end
+ end
+
+ context 'when artifact is permanent' do
+ let!(:artifact) { create(:ci_job_artifact, expire_at: nil) }
+
+ it 'does not destroy expired job artifacts' do
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ end
+ end
+
+ context 'when failed to destroy artifact' do
+ before do
+ stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_LIMIT', 10)
+
+ allow_any_instance_of(Ci::JobArtifact)
+ .to receive(:destroy!)
+ .and_raise(ActiveRecord::RecordNotDestroyed)
+ end
+
+ it 'raises an exception and stop destroying' do
+ expect { subject }.to raise_error(ActiveRecord::RecordNotDestroyed)
+ end
+ end
+
+ context 'when exclusive lease has already been taken by the other instance' do
+ before do
+ stub_exclusive_lease_taken(described_class::EXCLUSIVE_LOCK_KEY, timeout: described_class::LOCK_TIMEOUT)
+ end
+
+ it 'raises an error and does not start destroying' do
+ expect { subject }.to raise_error(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
+ end
+ end
+
+ context 'when timeout happens' do
+ before do
+ stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_TIMEOUT', 1.second)
+ allow_any_instance_of(described_class).to receive(:destroy_batch) { true }
+ end
+
+ it 'returns false and does not continue destroying' do
+ is_expected.to be_falsy
+ end
+ end
+
+ context 'when loop reached loop limit' do
+ before do
+ stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_LIMIT', 1)
+ stub_const('Ci::DestroyExpiredJobArtifactsService::BATCH_SIZE', 1)
+ end
+
+ let!(:artifact) { create_list(:ci_job_artifact, 2, expire_at: 1.day.ago) }
+
+ it 'raises an error and does not continue destroying' do
+ is_expected.to be_falsy
+ end
+
+ it 'destroys one artifact' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
+ end
+ end
+
+ context 'when there are no artifacts' do
+ let!(:artifact) { }
+
+ it 'does not raise error' do
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context 'when there are artifacts more than batch sizes' do
+ before do
+ stub_const('Ci::DestroyExpiredJobArtifactsService::BATCH_SIZE', 1)
+ end
+
+ let!(:artifact) { create_list(:ci_job_artifact, 2, expire_at: 1.day.ago) }
+
+ it 'destroys all expired artifacts' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-2)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/destroy_pipeline_service_spec.rb b/spec/services/ci/destroy_pipeline_service_spec.rb
index 097daf67feb..d896f990470 100644
--- a/spec/services/ci/destroy_pipeline_service_spec.rb
+++ b/spec/services/ci/destroy_pipeline_service_spec.rb
@@ -17,8 +17,8 @@ describe ::Ci::DestroyPipelineService do
expect { pipeline.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
- it 'logs an audit event' do
- expect { subject }.to change { SecurityEvent.count }.by(1)
+ it 'does not log an audit event' do
+ expect { subject }.not_to change { SecurityEvent.count }
end
context 'when the pipeline has jobs' do
diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb
index 538992b621e..6674d89518e 100644
--- a/spec/services/ci/process_pipeline_service_spec.rb
+++ b/spec/services/ci/process_pipeline_service_spec.rb
@@ -671,9 +671,9 @@ describe Ci::ProcessPipelineService, '#execute' do
context 'when builds with auto-retries are configured' do
before do
- create_build('build:1', stage_idx: 0, user: user, options: { retry: { max: 2 } })
+ create_build('build:1', stage_idx: 0, user: user, options: { script: 'aa', retry: 2 })
create_build('test:1', stage_idx: 1, user: user, when: :on_failure)
- create_build('test:2', stage_idx: 1, user: user, options: { retry: { max: 1 } })
+ create_build('test:2', stage_idx: 1, user: user, options: { script: 'aa', retry: 1 })
end
it 'automatically retries builds in a valid order' do
@@ -762,7 +762,7 @@ describe Ci::ProcessPipelineService, '#execute' do
end
def manual_actions
- pipeline.manual_actions(true)
+ pipeline.manual_actions.reload
end
def create_build(name, **opts)
@@ -770,7 +770,7 @@ describe Ci::ProcessPipelineService, '#execute' do
end
def delayed_options
- { when: 'delayed', options: { start_in: '1 minute' } }
+ { when: 'delayed', options: { script: %w(echo), start_in: '1 minute' } }
end
def unschedule
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index 56e2a405bcd..20181387612 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -244,7 +244,9 @@ module Ci
context 'when first build is stalled' do
before do
- pending_job.update(lock_version: 0)
+ allow_any_instance_of(Ci::RegisterJobService).to receive(:assign_runner!).and_call_original
+ allow_any_instance_of(Ci::RegisterJobService).to receive(:assign_runner!)
+ .with(pending_job, anything).and_raise(ActiveRecord::StaleObjectError)
end
subject { described_class.new(specific_runner).execute }
@@ -458,7 +460,12 @@ module Ci
end
let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: 'test', stage_idx: 0) }
- let!(:pending_job) { create(:ci_build, :pending, pipeline: pipeline, stage_idx: 1, options: { dependencies: ['test'] } ) }
+
+ let!(:pending_job) do
+ create(:ci_build, :pending,
+ pipeline: pipeline, stage_idx: 1,
+ options: { script: ["bash"], dependencies: ['test'] })
+ end
subject { execute(specific_runner) }
diff --git a/spec/services/ci/retry_pipeline_service_spec.rb b/spec/services/ci/retry_pipeline_service_spec.rb
index 55445e71539..75042b29bea 100644
--- a/spec/services/ci/retry_pipeline_service_spec.rb
+++ b/spec/services/ci/retry_pipeline_service_spec.rb
@@ -285,7 +285,7 @@ describe Ci::RetryPipelineService, '#execute' do
end
it 'allows to retry failed pipeline' do
- allow_any_instance_of(Project).to receive(:fetch_branch_allows_collaboration?).and_return(true)
+ allow_any_instance_of(Project).to receive(:branch_allows_collaboration?).and_return(true)
allow_any_instance_of(Project).to receive(:empty_repo?).and_return(false)
service.execute(pipeline)
diff --git a/spec/services/clusters/applications/check_installation_progress_service_spec.rb b/spec/services/clusters/applications/check_installation_progress_service_spec.rb
index 45b8ce94815..19446ce1cf8 100644
--- a/spec/services/clusters/applications/check_installation_progress_service_spec.rb
+++ b/spec/services/clusters/applications/check_installation_progress_service_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Clusters::Applications::CheckInstallationProgressService do
+describe Clusters::Applications::CheckInstallationProgressService, '#execute' do
RESCHEDULE_PHASES = Gitlab::Kubernetes::Pod::PHASES - [Gitlab::Kubernetes::Pod::SUCCEEDED, Gitlab::Kubernetes::Pod::FAILED].freeze
let(:application) { create(:clusters_applications_helm, :installing) }
@@ -21,24 +21,39 @@ describe Clusters::Applications::CheckInstallationProgressService do
expect(ClusterWaitForAppInstallationWorker).to receive(:perform_in).once
expect(service).not_to receive(:remove_installation_pod)
- service.execute
+ expect do
+ service.execute
+
+ application.reload
+ end.not_to change(application, :status)
- expect(application).to be_installing
expect(application.status_reason).to be_nil
end
end
+ end
+ end
- context 'when timeouted' do
- let(:application) { create(:clusters_applications_helm, :timeouted) }
+ shared_examples 'error logging' do
+ context 'when installation raises a Kubeclient::HttpError' do
+ let(:cluster) { create(:cluster, :provided_by_user, :project) }
- it 'make the application errored' do
- expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in)
+ before do
+ application.update!(cluster: cluster)
- service.execute
+ expect(service).to receive(:installation_phase).and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil))
+ end
- expect(application).to be_errored
- expect(application.status_reason).to eq("Installation timed out. Check pod logs for install-helm for more details.")
- end
+ it 'shows the response code from the error' do
+ service.execute
+
+ expect(application).to be_errored.or(be_update_errored)
+ expect(application.status_reason).to eq('Kubernetes error: 401')
+ end
+
+ it 'should log error' do
+ expect(service.send(:logger)).to receive(:error)
+
+ service.execute
end
end
end
@@ -48,10 +63,15 @@ describe Clusters::Applications::CheckInstallationProgressService do
allow(service).to receive(:remove_installation_pod).and_return(nil)
end
- describe '#execute' do
+ context 'when application is updating' do
+ let(:application) { create(:clusters_applications_helm, :updating) }
+
+ include_examples 'error logging'
+
+ RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase }
+
context 'when installation POD succeeded' do
let(:phase) { Gitlab::Kubernetes::Pod::SUCCEEDED }
-
before do
expect(service).to receive(:installation_phase).once.and_return(phase)
end
@@ -67,7 +87,7 @@ describe Clusters::Applications::CheckInstallationProgressService do
service.execute
- expect(application).to be_installed
+ expect(application).to be_updated
expect(application.status_reason).to be_nil
end
end
@@ -83,33 +103,86 @@ describe Clusters::Applications::CheckInstallationProgressService do
it 'make the application errored' do
service.execute
- expect(application).to be_errored
- expect(application.status_reason).to eq("Installation failed. Check pod logs for install-helm for more details.")
+ expect(application).to be_update_errored
+ expect(application.status_reason).to eq('Operation failed. Check pod logs for install-helm for more details.')
end
end
- RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase }
+ context 'when timed out' do
+ let(:application) { create(:clusters_applications_helm, :timeouted, :updating) }
- context 'when installation raises a Kubeclient::HttpError' do
- let(:cluster) { create(:cluster, :provided_by_user, :project) }
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
+
+ it 'make the application errored' do
+ expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in)
+
+ service.execute
+
+ expect(application).to be_update_errored
+ expect(application.status_reason).to eq('Operation timed out. Check pod logs for install-helm for more details.')
+ end
+ end
+ end
+
+ context 'when application is installing' do
+ include_examples 'error logging'
+
+ RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase }
+ context 'when installation POD succeeded' do
+ let(:phase) { Gitlab::Kubernetes::Pod::SUCCEEDED }
before do
- application.update!(cluster: cluster)
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
- expect(service).to receive(:installation_phase).and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil))
+ it 'removes the installation POD' do
+ expect(service).to receive(:remove_installation_pod).once
+
+ service.execute
end
- it 'shows the response code from the error' do
+ it 'make the application installed' do
+ expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in)
+
+ service.execute
+
+ expect(application).to be_installed
+ expect(application.status_reason).to be_nil
+ end
+ end
+
+ context 'when installation POD failed' do
+ let(:phase) { Gitlab::Kubernetes::Pod::FAILED }
+ let(:errors) { 'test installation failed' }
+
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
+
+ it 'make the application errored' do
service.execute
expect(application).to be_errored
- expect(application.status_reason).to eq('Kubernetes error: 401')
+ expect(application.status_reason).to eq('Operation failed. Check pod logs for install-helm for more details.')
+ end
+ end
+
+ context 'when timed out' do
+ let(:application) { create(:clusters_applications_helm, :timeouted) }
+
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
end
- it 'should log error' do
- expect(service.send(:logger)).to receive(:error)
+ it 'make the application errored' do
+ expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in)
service.execute
+
+ expect(application).to be_errored
+ expect(application.status_reason).to eq('Operation timed out. Check pod logs for install-helm for more details.')
end
end
end
diff --git a/spec/services/clusters/applications/create_service_spec.rb b/spec/services/clusters/applications/create_service_spec.rb
index 1a2ca23748a..cbdef008b07 100644
--- a/spec/services/clusters/applications/create_service_spec.rb
+++ b/spec/services/clusters/applications/create_service_spec.rb
@@ -13,6 +13,7 @@ describe Clusters::Applications::CreateService do
describe '#execute' do
before do
allow(ClusterInstallAppWorker).to receive(:perform_async)
+ allow(ClusterUpgradeAppWorker).to receive(:perform_async)
end
subject { service.execute(test_request) }
@@ -25,88 +26,111 @@ describe Clusters::Applications::CreateService do
end.to change(cluster, :application_helm)
end
- it 'schedules an install via worker' do
- expect(ClusterInstallAppWorker).to receive(:perform_async).with('helm', anything).once
+ context 'application already installed' do
+ let!(:application) { create(:clusters_applications_helm, :installed, cluster: cluster) }
- subject
- end
+ it 'does not create a new application' do
+ expect do
+ subject
+ end.not_to change(Clusters::Applications::Helm, :count)
+ end
+
+ it 'schedules an upgrade for the application' do
+ expect(ClusterUpgradeAppWorker).to receive(:perform_async)
- context 'cert manager application' do
- let(:params) do
- {
- application: 'cert_manager',
- email: 'test@example.com'
- }
+ subject
end
+ end
+ context 'known applications' do
before do
- allow_any_instance_of(Clusters::Applications::ScheduleInstallationService).to receive(:execute)
+ create(:clusters_applications_helm, :installed, cluster: cluster)
end
- it 'creates the application' do
- expect do
- subject
+ context 'cert manager application' do
+ let(:params) do
+ {
+ application: 'cert_manager',
+ email: 'test@example.com'
+ }
+ end
- cluster.reload
- end.to change(cluster, :application_cert_manager)
- end
+ before do
+ expect_any_instance_of(Clusters::Applications::CertManager)
+ .to receive(:make_scheduled!)
+ .and_call_original
+ end
- it 'sets the email' do
- expect(subject.email).to eq('test@example.com')
- end
- end
+ it 'creates the application' do
+ expect do
+ subject
- context 'jupyter application' do
- let(:params) do
- {
- application: 'jupyter',
- hostname: 'example.com'
- }
- end
+ cluster.reload
+ end.to change(cluster, :application_cert_manager)
+ end
- before do
- allow_any_instance_of(Clusters::Applications::ScheduleInstallationService).to receive(:execute)
+ it 'sets the email' do
+ expect(subject.email).to eq('test@example.com')
+ end
end
- it 'creates the application' do
- expect do
- subject
+ context 'jupyter application' do
+ let(:params) do
+ {
+ application: 'jupyter',
+ hostname: 'example.com'
+ }
+ end
- cluster.reload
- end.to change(cluster, :application_jupyter)
- end
+ before do
+ create(:clusters_applications_ingress, :installed, external_ip: "127.0.0.0", cluster: cluster)
+ expect_any_instance_of(Clusters::Applications::Jupyter)
+ .to receive(:make_scheduled!)
+ .and_call_original
+ end
- it 'sets the hostname' do
- expect(subject.hostname).to eq('example.com')
- end
+ it 'creates the application' do
+ expect do
+ subject
- it 'sets the oauth_application' do
- expect(subject.oauth_application).to be_present
- end
- end
+ cluster.reload
+ end.to change(cluster, :application_jupyter)
+ end
- context 'knative application' do
- let(:params) do
- {
- application: 'knative',
- hostname: 'example.com'
- }
- end
+ it 'sets the hostname' do
+ expect(subject.hostname).to eq('example.com')
+ end
- before do
- allow_any_instance_of(Clusters::Applications::ScheduleInstallationService).to receive(:execute)
+ it 'sets the oauth_application' do
+ expect(subject.oauth_application).to be_present
+ end
end
- it 'creates the application' do
- expect do
- subject
+ context 'knative application' do
+ let(:params) do
+ {
+ application: 'knative',
+ hostname: 'example.com'
+ }
+ end
- cluster.reload
- end.to change(cluster, :application_knative)
- end
+ before do
+ expect_any_instance_of(Clusters::Applications::Knative)
+ .to receive(:make_scheduled!)
+ .and_call_original
+ end
+
+ it 'creates the application' do
+ expect do
+ subject
- it 'sets the hostname' do
- expect(subject.hostname).to eq('example.com')
+ cluster.reload
+ end.to change(cluster, :application_knative)
+ end
+
+ it 'sets the hostname' do
+ expect(subject.hostname).to eq('example.com')
+ end
end
end
@@ -123,19 +147,21 @@ describe Clusters::Applications::CreateService do
using RSpec::Parameterized::TableSyntax
- before do
- allow_any_instance_of(Clusters::Applications::ScheduleInstallationService).to receive(:execute)
- end
-
- where(:application, :association, :allowed) do
- 'helm' | :application_helm | true
- 'ingress' | :application_ingress | true
- 'runner' | :application_runner | false
- 'jupyter' | :application_jupyter | false
- 'prometheus' | :application_prometheus | false
+ where(:application, :association, :allowed, :pre_create_helm) do
+ 'helm' | :application_helm | true | false
+ 'ingress' | :application_ingress | true | true
+ 'runner' | :application_runner | false | true
+ 'jupyter' | :application_jupyter | false | true
+ 'prometheus' | :application_prometheus | false | true
end
with_them do
+ before do
+ klass = "Clusters::Applications::#{application.titleize}"
+ allow_any_instance_of(klass.constantize).to receive(:make_scheduled!).and_call_original
+ create(:clusters_applications_helm, :installed, cluster: cluster) if pre_create_helm
+ end
+
let(:params) { { application: application } }
it 'executes for each application' do
@@ -151,5 +177,68 @@ describe Clusters::Applications::CreateService do
end
end
end
+
+ context 'when application is installable' do
+ shared_examples 'installable applications' do
+ it 'makes the application scheduled' do
+ expect do
+ subject
+ end.to change { Clusters::Applications::Helm.with_status(:scheduled).count }.by(1)
+ end
+
+ it 'schedules an install via worker' do
+ expect(ClusterInstallAppWorker)
+ .to receive(:perform_async)
+ .with(*worker_arguments)
+ .once
+
+ subject
+ end
+ end
+
+ context 'when application is associated with a cluster' do
+ let(:application) { create(:clusters_applications_helm, :installable, cluster: cluster) }
+ let(:worker_arguments) { [application.name, application.id] }
+
+ it_behaves_like 'installable applications'
+ end
+
+ context 'when application is not associated with a cluster' do
+ let(:worker_arguments) { [params[:application], kind_of(Numeric)] }
+
+ it_behaves_like 'installable applications'
+ end
+ end
+
+ context 'when installation is already in progress' do
+ let!(:application) { create(:clusters_applications_helm, :installing, cluster: cluster) }
+
+ it 'raises an exception' do
+ expect { subject }
+ .to raise_exception(StateMachines::InvalidTransition)
+ .and not_change(application.class.with_status(:scheduled), :count)
+ end
+
+ it 'does not schedule a cluster worker' do
+ expect(ClusterInstallAppWorker).not_to receive(:perform_async)
+ end
+ end
+
+ context 'when application is installed' do
+ %i(installed updated).each do |status|
+ let(:application) { create(:clusters_applications_helm, status, cluster: cluster) }
+
+ it 'schedules an upgrade via worker' do
+ expect(ClusterUpgradeAppWorker)
+ .to receive(:perform_async)
+ .with(application.name, application.id)
+ .once
+
+ subject
+
+ expect(application.reload).to be_scheduled
+ end
+ end
+ end
end
end
diff --git a/spec/services/clusters/applications/schedule_installation_service_spec.rb b/spec/services/clusters/applications/schedule_installation_service_spec.rb
deleted file mode 100644
index 21797edd533..00000000000
--- a/spec/services/clusters/applications/schedule_installation_service_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-require 'spec_helper'
-
-describe Clusters::Applications::ScheduleInstallationService do
- def count_scheduled
- application&.class&.with_status(:scheduled)&.count || 0
- end
-
- shared_examples 'a failing service' do
- it 'raise an exception' do
- expect(ClusterInstallAppWorker).not_to receive(:perform_async)
- count_before = count_scheduled
-
- expect { service.execute }.to raise_error(StandardError)
- expect(count_scheduled).to eq(count_before)
- end
- end
-
- describe '#execute' do
- let(:service) { described_class.new(application) }
-
- context 'when application is installable' do
- let(:application) { create(:clusters_applications_helm, :installable) }
-
- it 'make the application scheduled' do
- expect(ClusterInstallAppWorker).to receive(:perform_async).with(application.name, kind_of(Numeric)).once
-
- expect { service.execute }.to change { application.class.with_status(:scheduled).count }.by(1)
- end
- end
-
- context 'when installation is already in progress' do
- let(:application) { create(:clusters_applications_helm, :installing) }
-
- it_behaves_like 'a failing service'
- end
-
- context 'when application is nil' do
- let(:application) { nil }
-
- it_behaves_like 'a failing service'
- end
-
- context 'when application cannot be persisted' do
- let(:application) { create(:clusters_applications_helm) }
-
- before do
- expect(application).to receive(:make_scheduled!).once.and_raise(ActiveRecord::RecordInvalid)
- end
-
- it_behaves_like 'a failing service'
- end
- end
-end
diff --git a/spec/services/clusters/applications/upgrade_service_spec.rb b/spec/services/clusters/applications/upgrade_service_spec.rb
new file mode 100644
index 00000000000..1822fc38dbd
--- /dev/null
+++ b/spec/services/clusters/applications/upgrade_service_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Applications::UpgradeService do
+ describe '#execute' do
+ let(:application) { create(:clusters_applications_helm, :scheduled) }
+ let!(:install_command) { application.install_command }
+ let(:service) { described_class.new(application) }
+ let(:helm_client) { instance_double(Gitlab::Kubernetes::Helm::Api) }
+
+ before do
+ allow(service).to receive(:install_command).and_return(install_command)
+ allow(service).to receive(:helm_api).and_return(helm_client)
+ end
+
+ context 'when there are no errors' do
+ before do
+ expect(helm_client).to receive(:update).with(install_command)
+ allow(ClusterWaitForAppInstallationWorker).to receive(:perform_in).and_return(nil)
+ end
+
+ it 'make the application updating' do
+ expect(application.cluster).not_to be_nil
+ service.execute
+
+ expect(application).to be_updating
+ end
+
+ it 'schedule async installation status check' do
+ expect(ClusterWaitForAppInstallationWorker).to receive(:perform_in).once
+
+ service.execute
+ end
+ end
+
+ context 'when kubernetes cluster communication fails' do
+ let(:error) { Kubeclient::HttpError.new(500, 'system failure', nil) }
+
+ before do
+ expect(helm_client).to receive(:update).with(install_command).and_raise(error)
+ end
+
+ it 'make the application errored' do
+ service.execute
+
+ expect(application).to be_update_errored
+ expect(application.status_reason).to match('Kubernetes error: 500')
+ end
+
+ it 'logs errors' do
+ expect(service.send(:logger)).to receive(:error).with(
+ {
+ exception: 'Kubeclient::HttpError',
+ message: 'system failure',
+ service: 'Clusters::Applications::UpgradeService',
+ app_id: application.id,
+ project_ids: application.cluster.project_ids,
+ group_ids: [],
+ error_code: 500
+ }
+ )
+
+ expect(Gitlab::Sentry).to receive(:track_acceptable_exception).with(
+ error,
+ extra: {
+ exception: 'Kubeclient::HttpError',
+ message: 'system failure',
+ service: 'Clusters::Applications::UpgradeService',
+ app_id: application.id,
+ project_ids: application.cluster.project_ids,
+ group_ids: [],
+ error_code: 500
+ }
+ )
+
+ service.execute
+ end
+ end
+
+ context 'a non kubernetes error happens' do
+ let(:application) { create(:clusters_applications_helm, :scheduled) }
+ let(:error) { StandardError.new('something bad happened') }
+
+ before do
+ expect(application).to receive(:make_updating!).once.and_raise(error)
+ end
+
+ it 'make the application errored' do
+ expect(helm_client).not_to receive(:update)
+
+ service.execute
+
+ expect(application).to be_update_errored
+ expect(application.status_reason).to eq("Can't start upgrade process.")
+ end
+
+ it 'logs errors' do
+ expect(service.send(:logger)).to receive(:error).with(
+ {
+ exception: 'StandardError',
+ error_code: nil,
+ message: 'something bad happened',
+ service: 'Clusters::Applications::UpgradeService',
+ app_id: application.id,
+ project_ids: application.cluster.projects.pluck(:id),
+ group_ids: []
+ }
+ )
+
+ expect(Gitlab::Sentry).to receive(:track_acceptable_exception).with(
+ error,
+ extra: {
+ exception: 'StandardError',
+ error_code: nil,
+ message: 'something bad happened',
+ service: 'Clusters::Applications::UpgradeService',
+ app_id: application.id,
+ project_ids: application.cluster.projects.pluck(:id),
+ group_ids: []
+ }
+ )
+
+ service.execute
+ end
+ end
+ end
+end
diff --git a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
index fe785735fef..18f218fc236 100644
--- a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
@@ -27,6 +27,8 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService, '#execute' d
stub_kubeclient_get_secret_error(api_url, 'gitlab-token')
stub_kubeclient_create_secret(api_url)
+ stub_kubeclient_get_role_binding(api_url, "gitlab-#{namespace}", namespace: namespace)
+ stub_kubeclient_put_role_binding(api_url, "gitlab-#{namespace}", namespace: namespace)
stub_kubeclient_get_namespace(api_url, namespace: namespace)
stub_kubeclient_get_service_account_error(api_url, "#{namespace}-service-account", namespace: namespace)
stub_kubeclient_create_service_account(api_url, namespace: namespace)
diff --git a/spec/services/create_release_service_spec.rb b/spec/services/create_release_service_spec.rb
deleted file mode 100644
index 1a2dd0b39ee..00000000000
--- a/spec/services/create_release_service_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require 'spec_helper'
-
-describe CreateReleaseService do
- let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
- let(:tag_name) { project.repository.tag_names.first }
- let(:description) { 'Awesome release!' }
- let(:service) { described_class.new(project, user) }
- let(:tag) { project.repository.find_tag(tag_name) }
- let(:sha) { tag.dereferenced_target.sha }
-
- it 'creates a new release' do
- result = service.execute(tag_name, description)
- expect(result[:status]).to eq(:success)
- release = project.releases.find_by(tag: tag_name)
- expect(release).not_to be_nil
- expect(release.description).to eq(description)
- expect(release.name).to eq(tag_name)
- expect(release.sha).to eq(sha)
- expect(release.author).to eq(user)
- end
-
- it 'raises an error if the tag does not exist' do
- result = service.execute("foobar", description)
- expect(result[:status]).to eq(:error)
- end
-
- context 'there already exists a release on a tag' do
- before do
- service.execute(tag_name, description)
- end
-
- it 'raises an error and does not update the release' do
- result = service.execute(tag_name, 'The best release!')
- expect(result[:status]).to eq(:error)
- expect(project.releases.find_by(tag: tag_name).description).to eq(description)
- end
- end
-end
diff --git a/spec/services/error_tracking/list_issues_service_spec.rb b/spec/services/error_tracking/list_issues_service_spec.rb
new file mode 100644
index 00000000000..9d4fc62f923
--- /dev/null
+++ b/spec/services/error_tracking/list_issues_service_spec.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ErrorTracking::ListIssuesService do
+ set(:user) { create(:user) }
+ set(:project) { create(:project) }
+
+ let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
+ let(:token) { 'test-token' }
+ let(:result) { subject.execute }
+
+ let(:error_tracking_setting) do
+ create(:project_error_tracking_setting, api_url: sentry_url, token: token, project: project)
+ end
+
+ subject { described_class.new(project, user) }
+
+ before do
+ expect(project).to receive(:error_tracking_setting).at_least(:once).and_return(error_tracking_setting)
+
+ project.add_reporter(user)
+ end
+
+ describe '#execute' do
+ context 'with authorized user' do
+ context 'when list_sentry_issues returns issues' do
+ let(:issues) { [:list, :of, :issues] }
+
+ before do
+ expect(error_tracking_setting)
+ .to receive(:list_sentry_issues).and_return(issues: issues)
+ end
+
+ it 'returns the issues' do
+ expect(result).to eq(status: :success, issues: issues)
+ end
+ end
+
+ context 'when list_sentry_issues returns nil' do
+ before do
+ expect(error_tracking_setting)
+ .to receive(:list_sentry_issues).and_return(nil)
+ end
+
+ it 'result is not ready' do
+ expect(result).to eq(
+ status: :error, http_status: :no_content, message: 'Not ready. Try again later')
+ end
+ end
+
+ context 'when list_sentry_issues returns error' do
+ before do
+ allow(error_tracking_setting)
+ .to receive(:list_sentry_issues)
+ .and_return(error: 'Sentry response status code: 401')
+ end
+
+ it 'returns the error' do
+ expect(result).to eq(
+ status: :error,
+ http_status: :bad_request,
+ message: 'Sentry response status code: 401'
+ )
+ end
+ end
+ end
+
+ context 'with unauthorized user' do
+ let(:unauthorized_user) { create(:user) }
+
+ subject { described_class.new(project, unauthorized_user) }
+
+ it 'returns error' do
+ result = subject.execute
+
+ expect(result).to include(
+ status: :error,
+ message: 'Access denied',
+ http_status: :unauthorized
+ )
+ end
+ end
+
+ context 'with error tracking disabled' do
+ before do
+ error_tracking_setting.enabled = false
+ end
+
+ it 'raises error' do
+ result = subject.execute
+
+ expect(result).to include(status: :error, message: 'Error Tracking is not enabled')
+ end
+ end
+ end
+
+ describe '#sentry_external_url' do
+ let(:external_url) { 'https://sentrytest.gitlab.com/sentry-org/sentry-project' }
+
+ it 'calls ErrorTracking::ProjectErrorTrackingSetting' do
+ expect(error_tracking_setting).to receive(:sentry_external_url).and_call_original
+
+ subject.external_url
+ end
+ end
+end
diff --git a/spec/services/error_tracking/list_projects_service_spec.rb b/spec/services/error_tracking/list_projects_service_spec.rb
new file mode 100644
index 00000000000..a92d3376f7b
--- /dev/null
+++ b/spec/services/error_tracking/list_projects_service_spec.rb
@@ -0,0 +1,149 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ErrorTracking::ListProjectsService do
+ set(:user) { create(:user) }
+ set(:project) { create(:project) }
+
+ let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
+ let(:token) { 'test-token' }
+ let(:new_api_host) { 'https://gitlab.com/' }
+ let(:new_token) { 'new-token' }
+ let(:params) { ActionController::Parameters.new(api_host: new_api_host, token: new_token) }
+
+ let(:error_tracking_setting) do
+ create(:project_error_tracking_setting, api_url: sentry_url, token: token, project: project)
+ end
+
+ subject { described_class.new(project, user, params) }
+
+ before do
+ project.add_reporter(user)
+ end
+
+ describe '#execute' do
+ let(:result) { subject.execute }
+
+ context 'with authorized user' do
+ before do
+ expect(project).to receive(:error_tracking_setting).at_least(:once)
+ .and_return(error_tracking_setting)
+ end
+
+ context 'set model attributes to new values' do
+ let(:new_api_url) { new_api_host + 'api/0/projects/org/proj/' }
+
+ before do
+ expect(error_tracking_setting).to receive(:list_sentry_projects)
+ .and_return({ projects: [] })
+ end
+
+ it 'uses new api_url and token' do
+ subject.execute
+
+ expect(error_tracking_setting.api_url).to eq(new_api_url)
+ expect(error_tracking_setting.token).to eq(new_token)
+ error_tracking_setting.reload
+ expect(error_tracking_setting.api_url).to eq(sentry_url)
+ expect(error_tracking_setting.token).to eq(token)
+ end
+ end
+
+ context 'sentry client raises exception' do
+ before do
+ expect(error_tracking_setting).to receive(:list_sentry_projects)
+ .and_raise(Sentry::Client::Error, 'Sentry response status code: 500')
+ end
+
+ it 'returns error response' do
+ expect(result[:message]).to eq('Sentry response status code: 500')
+ expect(result[:http_status]).to eq(:bad_request)
+ end
+ end
+
+ context 'with invalid url' do
+ let(:params) do
+ ActionController::Parameters.new(
+ api_host: 'https://localhost',
+ token: new_token
+ )
+ end
+
+ before do
+ error_tracking_setting.enabled = false
+ end
+
+ it 'returns error' do
+ expect(result[:message]).to start_with('Api url is blocked')
+ expect(error_tracking_setting).not_to be_valid
+ end
+ end
+
+ context 'when list_sentry_projects returns projects' do
+ let(:projects) { [:list, :of, :projects] }
+
+ before do
+ expect(error_tracking_setting)
+ .to receive(:list_sentry_projects).and_return(projects: projects)
+ end
+
+ it 'returns the projects' do
+ expect(result).to eq(status: :success, projects: projects)
+ end
+ end
+ end
+
+ context 'with unauthorized user' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns error' do
+ expect(result).to include(status: :error, message: 'access denied')
+ end
+ end
+
+ context 'with error tracking disabled' do
+ before do
+ expect(project).to receive(:error_tracking_setting).at_least(:once)
+ .and_return(error_tracking_setting)
+ expect(error_tracking_setting)
+ .to receive(:list_sentry_projects).and_return(projects: [])
+
+ error_tracking_setting.enabled = false
+ end
+
+ it 'ignores enabled flag' do
+ expect(result).to include(status: :success, projects: [])
+ end
+ end
+
+ context 'error_tracking_setting is nil' do
+ let(:error_tracking_setting) { build(:project_error_tracking_setting) }
+ let(:new_api_url) { new_api_host + 'api/0/projects/org/proj/' }
+
+ before do
+ expect(project).to receive(:build_error_tracking_setting).once
+ .and_return(error_tracking_setting)
+
+ expect(error_tracking_setting).to receive(:list_sentry_projects)
+ .and_return(projects: [:project1, :project2])
+ end
+
+ it 'builds a new error_tracking_setting' do
+ expect(project.error_tracking_setting).to be_nil
+
+ expect(result[:projects]).to eq([:project1, :project2])
+
+ expect(error_tracking_setting.api_url).to eq(new_api_url)
+ expect(error_tracking_setting.token).to eq(new_token)
+ expect(error_tracking_setting.enabled).to be true
+ expect(error_tracking_setting.persisted?).to be false
+ expect(error_tracking_setting.project_id).not_to be_nil
+
+ expect(project.error_tracking_setting).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index 68e310b0506..443665c9959 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -144,7 +144,7 @@ describe EventCreateService do
it 'updates user last activity' do
expect { service.push(project, user, push_data) }
- .to change { user.last_activity_on }.to(Date.today)
+ .to change { user.last_activity_on }.to(Date.today)
end
it 'caches the last push event for the user' do
diff --git a/spec/services/files/multi_service_spec.rb b/spec/services/files/multi_service_spec.rb
index 84c48d63c64..6842fa9f435 100644
--- a/spec/services/files/multi_service_spec.rb
+++ b/spec/services/files/multi_service_spec.rb
@@ -235,6 +235,22 @@ describe Files::MultiService do
expect(blob).to be_present
end
end
+
+ context 'when force is set to true and branch already exists' do
+ let(:commit_params) do
+ {
+ commit_message: commit_message,
+ branch_name: 'feature',
+ start_branch: 'master',
+ actions: actions,
+ force: true
+ }
+ end
+
+ it 'is still a success' do
+ expect(subject.execute[:status]).to eq(:success)
+ end
+ end
end
def update_file(path)
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index 45ef26aebbd..e8fce951155 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -15,7 +15,7 @@ describe GitPushService, services: true do
end
describe 'with remote mirrors' do
- let(:project) { create(:project, :repository, :remote_mirror) }
+ let(:project) { create(:project, :repository, :remote_mirror) }
subject do
described_class.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
@@ -547,7 +547,7 @@ describe GitPushService, services: true do
end
context "closing an issue" do
- let(:message) { "this is some work.\n\ncloses JIRA-1" }
+ let(:message) { "this is some work.\n\ncloses JIRA-1" }
let(:comment_body) do
{
body: "Issue solved with [#{closing_commit.id}|http://#{Gitlab.config.gitlab.host}/#{project.full_path}/commit/#{closing_commit.id}]."
diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb
index 6b48c993c57..79d504b9b45 100644
--- a/spec/services/groups/transfer_service_spec.rb
+++ b/spec/services/groups/transfer_service_spec.rb
@@ -410,5 +410,34 @@ describe Groups::TransferService, :postgresql do
end
end
end
+
+ context 'when transferring a subgroup into root group' do
+ let(:group) { create(:group, :public, :nested) }
+ let(:subgroup) { create(:group, :public, parent: group) }
+ let(:transfer_service) { described_class.new(subgroup, user) }
+
+ it 'ensures there is still an owner for the transferred group' do
+ expect(subgroup.owners).to be_empty
+
+ transfer_service.execute(nil)
+ subgroup.reload
+
+ expect(subgroup.owners).to match_array(user)
+ end
+
+ context 'when group has explicit owner' do
+ let(:another_owner) { create(:user) }
+ let!(:another_member) { create(:group_member, :owner, group: subgroup, user: another_owner) }
+
+ it 'does not add additional owner' do
+ expect(subgroup.owners).to match_array(another_owner)
+
+ transfer_service.execute(nil)
+ subgroup.reload
+
+ expect(subgroup.owners).to match_array(another_owner)
+ end
+ end
+ end
end
end
diff --git a/spec/services/groups/update_service_spec.rb b/spec/services/groups/update_service_spec.rb
index 84cfa53ea05..d87a7dd234d 100644
--- a/spec/services/groups/update_service_spec.rb
+++ b/spec/services/groups/update_service_spec.rb
@@ -56,7 +56,7 @@ describe Groups::UpdateService do
create(:project, :private, group: internal_group)
expect(TodosDestroyer::GroupPrivateWorker).to receive(:perform_in)
- .with(1.hour, internal_group.id)
+ .with(Todo::WAIT_FOR_DELETE, internal_group.id)
end
it "changes permission level to private" do
diff --git a/spec/services/issuable/bulk_update_service_spec.rb b/spec/services/issuable/bulk_update_service_spec.rb
index f0b0f7956ce..ca366cdf1df 100644
--- a/spec/services/issuable/bulk_update_service_spec.rb
+++ b/spec/services/issuable/bulk_update_service_spec.rb
@@ -28,6 +28,33 @@ describe Issuable::BulkUpdateService do
expect(project.issues.opened).to be_empty
expect(project.issues.closed).not_to be_empty
end
+
+ context 'when issue for a different project is created' do
+ let(:private_project) { create(:project, :private) }
+ let(:issue) { create(:issue, project: private_project, author: user) }
+
+ context 'when user has access to the project' do
+ it 'closes all issues passed' do
+ private_project.add_maintainer(user)
+
+ bulk_update(issues + [issue], state_event: 'close')
+
+ expect(project.issues.opened).to be_empty
+ expect(project.issues.closed).not_to be_empty
+ expect(private_project.issues.closed).not_to be_empty
+ end
+ end
+
+ context 'when user does not have access to project' do
+ it 'only closes all issues that the user has access to' do
+ bulk_update(issues + [issue], state_event: 'close')
+
+ expect(project.issues.opened).to be_empty
+ expect(project.issues.closed).not_to be_empty
+ expect(private_project.issues.closed).to be_empty
+ end
+ end
+ end
end
describe 'reopen issues' do
diff --git a/spec/services/issuable/common_system_notes_service_spec.rb b/spec/services/issuable/common_system_notes_service_spec.rb
index fa5d5ebac5c..0edc9016c96 100644
--- a/spec/services/issuable/common_system_notes_service_spec.rb
+++ b/spec/services/issuable/common_system_notes_service_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Issuable::CommonSystemNotesService do
let(:user) { create(:user) }
let(:project) { create(:project) }
- let(:issuable) { create(:issue) }
+ let(:issuable) { create(:issue, project: project) }
context 'on issuable update' do
it_behaves_like 'system note creation', { title: 'New title' }, 'changed title'
@@ -70,7 +70,7 @@ describe Issuable::CommonSystemNotesService do
end
context 'on issuable create' do
- let(:issuable) { build(:issue) }
+ let(:issuable) { build(:issue, project: project) }
subject { described_class.new(project, user).execute(issuable, old_labels: [], is_update: false) }
diff --git a/spec/services/issues/build_service_spec.rb b/spec/services/issues/build_service_spec.rb
index 248e7d5a389..86e58fe06b9 100644
--- a/spec/services/issues/build_service_spec.rb
+++ b/spec/services/issues/build_service_spec.rb
@@ -8,29 +8,29 @@ describe Issues::BuildService do
project.add_developer(user)
end
+ def build_issue(issue_params = {})
+ described_class.new(project, user, issue_params).execute
+ end
+
context 'for a single discussion' do
describe '#execute' do
let(:merge_request) { create(:merge_request, title: "Hello world", source_project: project) }
let(:discussion) { create(:diff_note_on_merge_request, project: project, noteable: merge_request, note: "Almost done").to_discussion }
- let(:service) { described_class.new(project, user, merge_request_to_resolve_discussions_of: merge_request.iid, discussion_to_resolve: discussion.id) }
- it 'references the noteable title in the issue title' do
- issue = service.execute
+ subject { build_issue(merge_request_to_resolve_discussions_of: merge_request.iid, discussion_to_resolve: discussion.id) }
- expect(issue.title).to include('Hello world')
+ it 'references the noteable title in the issue title' do
+ expect(subject.title).to include('Hello world')
end
it 'adds the note content to the description' do
- issue = service.execute
-
- expect(issue.description).to include('Almost done')
+ expect(subject.description).to include('Almost done')
end
end
end
context 'for discussions in a merge request' do
let(:merge_request) { create(:merge_request_with_diff_notes, source_project: project) }
- let(:issue) { described_class.new(project, user, merge_request_to_resolve_discussions_of: merge_request.iid).execute }
describe '#items_for_discussions' do
it 'has an item for each discussion' do
@@ -66,28 +66,30 @@ describe Issues::BuildService do
end
describe '#execute' do
- it 'has the merge request reference in the title' do
- expect(issue.title).to include(merge_request.title)
- end
+ let(:base_params) { { merge_request_to_resolve_discussions_of: merge_request.iid } }
- it 'has the reference of the merge request in the description' do
- expect(issue.description).to include(merge_request.to_reference)
+ context 'without additional params' do
+ subject { build_issue(base_params) }
+
+ it 'has the merge request reference in the title' do
+ expect(subject.title).to include(merge_request.title)
+ end
+
+ it 'has the reference of the merge request in the description' do
+ expect(subject.description).to include(merge_request.to_reference)
+ end
end
- it 'does not assign title when a title was given' do
- issue = described_class.new(project, user,
- merge_request_to_resolve_discussions_of: merge_request,
- title: 'What an issue').execute
+ it 'uses provided title if title param given' do
+ issue = build_issue(base_params.merge(title: 'What an issue'))
expect(issue.title).to eq('What an issue')
end
- it 'does not assign description when a description was given' do
- issue = described_class.new(project, user,
- merge_request_to_resolve_discussions_of: merge_request,
- description: 'Fix at your earliest conveignance').execute
+ it 'uses provided description if description param given' do
+ issue = build_issue(base_params.merge(description: 'Fix at your earliest convenience'))
- expect(issue.description).to eq('Fix at your earliest conveignance')
+ expect(issue.description).to eq('Fix at your earliest convenience')
end
describe 'with multiple discussions' do
@@ -96,20 +98,20 @@ describe Issues::BuildService do
it 'mentions all the authors in the description' do
authors = merge_request.resolvable_discussions.map(&:author)
- expect(issue.description).to include(*authors.map(&:to_reference))
+ expect(build_issue(base_params).description).to include(*authors.map(&:to_reference))
end
it 'has a link for each unresolved discussion in the description' do
notes = merge_request.resolvable_discussions.map(&:first_note)
links = notes.map { |note| Gitlab::UrlBuilder.build(note) }
- expect(issue.description).to include(*links)
+ expect(build_issue(base_params).description).to include(*links)
end
it 'mentions additional notes' do
create_list(:diff_note_on_merge_request, 2, noteable: merge_request, project: merge_request.target_project, in_reply_to: diff_note)
- expect(issue.description).to include('(+2 comments)')
+ expect(build_issue(base_params).description).to include('(+2 comments)')
end
end
end
@@ -120,7 +122,7 @@ describe Issues::BuildService do
describe '#execute' do
it 'mentions the merge request in the description' do
- issue = described_class.new(project, user, merge_request_to_resolve_discussions_of: merge_request.iid).execute
+ issue = build_issue(merge_request_to_resolve_discussions_of: merge_request.iid)
expect(issue.description).to include("Review the conversation in #{merge_request.to_reference}")
end
@@ -128,20 +130,18 @@ describe Issues::BuildService do
end
describe '#execute' do
- let(:milestone) { create(:milestone, project: project) }
-
it 'builds a new issues with given params' do
- issue = described_class.new(
- project,
- user,
- title: 'Issue #1',
- description: 'Issue description',
- milestone_id: milestone.id
- ).execute
-
- expect(issue.title).to eq('Issue #1')
- expect(issue.description).to eq('Issue description')
+ milestone = create(:milestone, project: project)
+ issue = build_issue(milestone_id: milestone.id)
+
expect(issue.milestone).to eq(milestone)
end
+
+ it 'sets milestone to nil if it is not available for the project' do
+ milestone = create(:milestone, project: create(:project))
+ issue = build_issue(milestone_id: milestone.id)
+
+ expect(issue.milestone).to be_nil
+ end
end
end
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index c61c1ddcb3d..715b1168bfb 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -172,7 +172,7 @@ describe Issues::CreateService do
end
it 'removes assignee when user id is 0' do
- opts = { title: 'Title', description: 'Description', assignee_ids: [0] }
+ opts = { title: 'Title', description: 'Description', assignee_ids: [0] }
issue = described_class.new(project, user, opts).execute
diff --git a/spec/services/issues/import_csv_service_spec.rb b/spec/services/issues/import_csv_service_spec.rb
new file mode 100644
index 00000000000..516a1137319
--- /dev/null
+++ b/spec/services/issues/import_csv_service_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Issues::ImportCsvService do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ subject do
+ uploader = FileUploader.new(project)
+ uploader.store!(file)
+
+ described_class.new(user, project, uploader).execute
+ end
+
+ describe '#execute' do
+ context 'invalid file' do
+ let(:file) { fixture_file_upload('spec/fixtures/banana_sample.gif') }
+
+ it 'returns invalid file error' do
+ expect_any_instance_of(Notify).to receive(:import_issues_csv_email)
+
+ expect(subject[:success]).to eq(0)
+ expect(subject[:parse_error]).to eq(true)
+ end
+ end
+
+ context 'comma delimited file' do
+ let(:file) { fixture_file_upload('spec/fixtures/csv_comma.csv') }
+
+ it 'imports CSV without errors' do
+ expect_any_instance_of(Notify).to receive(:import_issues_csv_email)
+
+ expect(subject[:success]).to eq(3)
+ expect(subject[:error_lines]).to eq([])
+ expect(subject[:parse_error]).to eq(false)
+ end
+ end
+
+ context 'tab delimited file with error row' do
+ let(:file) { fixture_file_upload('spec/fixtures/csv_tab.csv') }
+
+ it 'imports CSV with some error rows' do
+ expect_any_instance_of(Notify).to receive(:import_issues_csv_email)
+
+ expect(subject[:success]).to eq(2)
+ expect(subject[:error_lines]).to eq([3])
+ expect(subject[:parse_error]).to eq(false)
+ end
+ end
+
+ context 'semicolon delimited file with CRLF' do
+ let(:file) { fixture_file_upload('spec/fixtures/csv_semicolon.csv') }
+
+ it 'imports CSV with a blank row' do
+ expect_any_instance_of(Notify).to receive(:import_issues_csv_email)
+
+ expect(subject[:success]).to eq(3)
+ expect(subject[:error_lines]).to eq([4])
+ expect(subject[:parse_error]).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index bd519e7f077..f1684209729 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -77,7 +77,7 @@ describe Issues::UpdateService, :mailer do
end
it 'enqueues ConfidentialIssueWorker when an issue is made confidential' do
- expect(TodosDestroyer::ConfidentialIssueWorker).to receive(:perform_in).with(1.hour, issue.id)
+ expect(TodosDestroyer::ConfidentialIssueWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, issue.id)
update_issue(confidential: true)
end
@@ -356,7 +356,7 @@ describe Issues::UpdateService, :mailer do
it_behaves_like 'system notes for milestones'
it 'sends notifications for subscribers of changed milestone' do
- issue.milestone = create(:milestone)
+ issue.milestone = create(:milestone, project: project)
issue.save
@@ -380,7 +380,7 @@ describe Issues::UpdateService, :mailer do
end
it 'marks todos as done' do
- update_issue(milestone: create(:milestone))
+ update_issue(milestone: create(:milestone, project: project))
expect(todo.reload.done?).to eq true
end
@@ -389,7 +389,7 @@ describe Issues::UpdateService, :mailer do
it 'sends notifications for subscribers of changed milestone' do
perform_enqueued_jobs do
- update_issue(milestone: create(:milestone))
+ update_issue(milestone: create(:milestone, project: project))
end
should_email(subscriber)
@@ -471,6 +471,8 @@ describe Issues::UpdateService, :mailer do
it { expect(issue.tasks?).to eq(true) }
+ it_behaves_like 'updating a single task'
+
context 'when tasks are marked as completed' do
before do
update_issue(description: "- [x] Task 1\n- [X] Task 2")
diff --git a/spec/services/labels/find_or_create_service_spec.rb b/spec/services/labels/find_or_create_service_spec.rb
index 97ba2742392..7af514a5bea 100644
--- a/spec/services/labels/find_or_create_service_spec.rb
+++ b/spec/services/labels/find_or_create_service_spec.rb
@@ -46,7 +46,7 @@ describe Labels::FindOrCreateService do
end
context 'when include_ancestor_groups is true' do
- let(:group) { create(:group, :nested) }
+ let(:group) { create(:group, :nested) }
let(:params) do
{
title: 'Audit',
diff --git a/spec/services/labels/promote_service_spec.rb b/spec/services/labels/promote_service_spec.rb
index aa9aba6bdff..c4c7f33e36a 100644
--- a/spec/services/labels/promote_service_spec.rb
+++ b/spec/services/labels/promote_service_spec.rb
@@ -5,9 +5,9 @@ describe Labels::PromoteService do
let!(:user) { create(:user) }
context 'project without group' do
- let!(:project_1) { create(:project) }
+ let!(:project_1) { create(:project) }
- let!(:project_label_1_1) { create(:label, project: project_1) }
+ let!(:project_label_1_1) { create(:label, project: project_1) }
subject(:service) { described_class.new(project_1, user) }
diff --git a/spec/services/lfs/unlock_file_service_spec.rb b/spec/services/lfs/unlock_file_service_spec.rb
index 539417644db..fe42ca41633 100644
--- a/spec/services/lfs/unlock_file_service_spec.rb
+++ b/spec/services/lfs/unlock_file_service_spec.rb
@@ -62,7 +62,7 @@ describe Lfs::UnlockFileService do
context 'when forced' do
let(:developer) { create(:user) }
- let(:maintainer) { create(:user) }
+ let(:maintainer) { create(:user) }
before do
project.add_developer(developer)
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 5c01463d757..3bc05182932 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -36,4 +36,13 @@ describe Members::CreateService do
expect(result[:message]).to be_present
expect(project.users).not_to include project_user
end
+
+ it 'does not add an invalid member' do
+ params = { user_ids: project_user.id.to_s, access_level: -1 }
+ result = described_class.new(user, params).execute(project)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to include(project_user.username)
+ expect(project.users).not_to include project_user
+ end
end
diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb
index 0a5220c7c61..d37ca13ebd2 100644
--- a/spec/services/members/destroy_service_spec.rb
+++ b/spec/services/members/destroy_service_spec.rb
@@ -22,7 +22,7 @@ describe Members::DestroyService do
shared_examples 'a service destroying a member' do
before do
type = member.is_a?(GroupMember) ? 'Group' : 'Project'
- expect(TodosDestroyer::EntityLeaveWorker).to receive(:perform_in).with(1.hour, member.user_id, member.source_id, type)
+ expect(TodosDestroyer::EntityLeaveWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, type)
end
it 'destroys the member' do
@@ -69,14 +69,14 @@ describe Members::DestroyService do
it 'calls Member#after_decline_request' do
expect_any_instance_of(NotificationService).to receive(:decline_access_request).with(member)
- described_class.new(current_user).execute(member)
+ described_class.new(current_user).execute(member, opts)
end
context 'when current user is the member' do
it 'does not call Member#after_decline_request' do
expect_any_instance_of(NotificationService).not_to receive(:decline_access_request).with(member)
- described_class.new(member_user).execute(member)
+ described_class.new(member_user).execute(member, opts)
end
end
end
@@ -159,7 +159,7 @@ describe Members::DestroyService do
end
it_behaves_like 'a service destroying a member' do
- let(:opts) { { skip_authorization: true } }
+ let(:opts) { { skip_authorization: true, skip_subresources: true } }
let(:member) { group_project.requesters.find_by(user_id: member_user.id) }
end
@@ -168,12 +168,14 @@ describe Members::DestroyService do
end
it_behaves_like 'a service destroying a member' do
- let(:opts) { { skip_authorization: true } }
+ let(:opts) { { skip_authorization: true, skip_subresources: true } }
let(:member) { group.requesters.find_by(user_id: member_user.id) }
end
end
context 'when current user can destroy the given access requester' do
+ let(:opts) { { skip_subresources: true } }
+
before do
group_project.add_maintainer(current_user)
group.add_owner(current_user)
@@ -229,4 +231,54 @@ describe Members::DestroyService do
end
end
end
+
+ context 'subresources' do
+ let(:user) { create(:user) }
+ let(:member_user) { create(:user) }
+ let(:opts) { {} }
+
+ let(:group) { create(:group, :public) }
+ let(:subgroup) { create(:group, parent: group) }
+ let(:subsubgroup) { create(:group, parent: subgroup) }
+ let(:subsubproject) { create(:project, group: subsubgroup) }
+
+ let(:group_project) { create(:project, :public, group: group) }
+ let(:control_project) { create(:project, group: subsubgroup) }
+
+ before do
+ create(:group_member, :developer, group: subsubgroup, user: member_user)
+
+ subsubproject.add_developer(member_user)
+ control_project.add_maintainer(user)
+ group.add_owner(user)
+
+ group_member = create(:group_member, :developer, group: group, user: member_user)
+
+ described_class.new(user).execute(group_member, opts)
+ end
+
+ it 'removes the project membership' do
+ expect(group_project.members.map(&:user)).not_to include(member_user)
+ end
+
+ it 'removes the group membership' do
+ expect(group.members.map(&:user)).not_to include(member_user)
+ end
+
+ it 'removes the subgroup membership', :postgresql do
+ expect(subgroup.members.map(&:user)).not_to include(member_user)
+ end
+
+ it 'removes the subsubgroup membership', :postgresql do
+ expect(subsubgroup.members.map(&:user)).not_to include(member_user)
+ end
+
+ it 'removes the subsubproject membership', :postgresql do
+ expect(subsubproject.members.map(&:user)).not_to include(member_user)
+ end
+
+ it 'does not remove the user from the control project' do
+ expect(control_project.members.map(&:user)).to include(user)
+ end
+ end
end
diff --git a/spec/services/members/update_service_spec.rb b/spec/services/members/update_service_spec.rb
index 6d19a95ffeb..599ed39ca37 100644
--- a/spec/services/members/update_service_spec.rb
+++ b/spec/services/members/update_service_spec.rb
@@ -20,11 +20,28 @@ describe Members::UpdateService do
shared_examples 'a service updating a member' do
it 'updates the member' do
+ expect(TodosDestroyer::EntityLeaveWorker).not_to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, source.class.name)
+
updated_member = described_class.new(current_user, params).execute(member, permission: permission)
expect(updated_member).to be_valid
expect(updated_member.access_level).to eq(Gitlab::Access::MAINTAINER)
end
+
+ context 'when member is downgraded to guest' do
+ let(:params) do
+ { access_level: Gitlab::Access::GUEST }
+ end
+
+ it 'schedules to delete confidential todos' do
+ expect(TodosDestroyer::EntityLeaveWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, source.class.name).once
+
+ updated_member = described_class.new(current_user, params).execute(member, permission: permission)
+
+ expect(updated_member).to be_valid
+ expect(updated_member.access_level).to eq(Gitlab::Access::GUEST)
+ end
+ end
end
before do
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index 1894d8c8d0e..057e8137a4e 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
describe MergeRequests::BuildService do
using RSpec::Parameterized::TableSyntax
include RepoHelpers
+ include ProjectForksHelper
let(:project) { create(:project, :repository) }
let(:source_project) { nil }
@@ -49,7 +50,7 @@ describe MergeRequests::BuildService do
describe '#execute' do
it 'calls the compare service with the correct arguments' do
- allow_any_instance_of(described_class).to receive(:branches_valid?).and_return(true)
+ allow_any_instance_of(described_class).to receive(:projects_and_branches_valid?).and_return(true)
expect(CompareService).to receive(:new)
.with(project, Gitlab::Git::BRANCH_REF_PREFIX + source_branch)
.and_call_original
@@ -228,6 +229,15 @@ describe MergeRequests::BuildService do
end
end
end
+
+ context 'when a milestone is from another project' do
+ let(:milestone) { create(:milestone, project: create(:project)) }
+ let(:milestone_id) { milestone.id }
+
+ it 'sets milestone to nil' do
+ expect(merge_request.milestone).to be_nil
+ end
+ end
end
end
@@ -393,11 +403,27 @@ describe MergeRequests::BuildService do
end
end
+ context 'target_project is set but repo is not accessible by current_user' do
+ let(:target_project) do
+ create(:project, :public, :repository, repository_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'sets target project correctly' do
+ expect(merge_request.target_project).to eq(project)
+ end
+ end
+
context 'source_project is set and accessible by current_user' do
let(:source_project) { create(:project, :public, :repository)}
let(:commits) { Commit.decorate([commit_1], project) }
- it 'sets target project correctly' do
+ before do
+ # To create merge requests _from_ a project the user needs at least
+ # developer access
+ source_project.add_developer(user)
+ end
+
+ it 'sets source project correctly' do
expect(merge_request.source_project).to eq(source_project)
end
end
@@ -406,11 +432,43 @@ describe MergeRequests::BuildService do
let(:source_project) { create(:project, :private, :repository)}
let(:commits) { Commit.decorate([commit_1], project) }
- it 'sets target project correctly' do
+ it 'sets source project correctly' do
+ expect(merge_request.source_project).to eq(project)
+ end
+ end
+
+ context 'source_project is set but the user cannot create merge requests from the project' do
+ let(:source_project) do
+ create(:project, :public, :repository, merge_requests_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'sets the source_project correctly' do
expect(merge_request.source_project).to eq(project)
end
end
+ context 'target_project is not in the fork network of source_project' do
+ let(:target_project) { create(:project, :public, :repository) }
+
+ it 'adds an error to the merge request' do
+ expect(merge_request.errors[:validate_fork]).to contain_exactly('Source project is not a fork of the target project')
+ end
+ end
+
+ context 'target_project is in the fork network of source project but no longer accessible' do
+ let!(:project) { fork_project(target_project, user, namespace: user.namespace, repository: true) }
+ let(:source_project) { project }
+ let(:target_project) { create(:project, :public, :repository) }
+
+ before do
+ target_project.update(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it 'sets the target_project correctly' do
+ expect(merge_request.target_project).to eq(project)
+ end
+ end
+
context 'when specifying target branch in the description' do
let(:description) { "A merge request targeting another branch\n\n/target_branch with-codeowners" }
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index 5a3ecb1019b..a04a4d5fc36 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -128,9 +128,9 @@ describe MergeRequests::CreateService do
end
context 'when head pipelines already exist for merge request source branch' do
- let(:sha) { project.commit(opts[:source_branch]).id }
- let!(:pipeline_1) { create(:ci_pipeline, project: project, ref: opts[:source_branch], project_id: project.id, sha: sha) }
- let!(:pipeline_2) { create(:ci_pipeline, project: project, ref: opts[:source_branch], project_id: project.id, sha: sha) }
+ let(:shas) { project.repository.commits(opts[:source_branch], limit: 2).map(&:id) }
+ let!(:pipeline_1) { create(:ci_pipeline, project: project, ref: opts[:source_branch], project_id: project.id, sha: shas[1]) }
+ let!(:pipeline_2) { create(:ci_pipeline, project: project, ref: opts[:source_branch], project_id: project.id, sha: shas[0]) }
let!(:pipeline_3) { create(:ci_pipeline, project: project, ref: "other_branch", project_id: project.id) }
before do
@@ -144,17 +144,30 @@ describe MergeRequests::CreateService do
it 'sets head pipeline' do
merge_request = service.execute
- expect(merge_request.head_pipeline).to eq(pipeline_2)
+ expect(merge_request.reload.head_pipeline).to eq(pipeline_2)
expect(merge_request).to be_persisted
end
- context 'when merge request head commit sha does not match pipeline sha' do
- it 'sets the head pipeline correctly' do
- pipeline_2.update(sha: 1234)
+ context 'when the new pipeline is associated with an old sha' do
+ let!(:pipeline_1) { create(:ci_pipeline, project: project, ref: opts[:source_branch], project_id: project.id, sha: shas[0]) }
+ let!(:pipeline_2) { create(:ci_pipeline, project: project, ref: opts[:source_branch], project_id: project.id, sha: shas[1]) }
+ it 'sets an old pipeline with associated with the latest sha as the head pipeline' do
merge_request = service.execute
- expect(merge_request.head_pipeline).to eq(pipeline_1)
+ expect(merge_request.reload.head_pipeline).to eq(pipeline_1)
+ expect(merge_request).to be_persisted
+ end
+ end
+
+ context 'when there are no pipelines with the diff head sha' do
+ let!(:pipeline_1) { create(:ci_pipeline, project: project, ref: opts[:source_branch], project_id: project.id, sha: shas[1]) }
+ let!(:pipeline_2) { create(:ci_pipeline, project: project, ref: opts[:source_branch], project_id: project.id, sha: shas[1]) }
+
+ it 'does not set the head pipeline' do
+ merge_request = service.execute
+
+ expect(merge_request.reload.head_pipeline).to be_nil
expect(merge_request).to be_persisted
end
end
@@ -181,7 +194,25 @@ describe MergeRequests::CreateService do
merge_request.reload
expect(merge_request.merge_request_pipelines.count).to eq(1)
- expect(merge_request.actual_head_pipeline).to be_merge_request
+ expect(merge_request.actual_head_pipeline).to be_merge_request_event
+ end
+
+ context 'when there are no commits between source branch and target branch' do
+ let(:opts) do
+ {
+ title: 'Awesome merge_request',
+ description: 'please fix',
+ source_branch: 'not-merged-branch',
+ target_branch: 'master'
+ }
+ end
+
+ it 'does not create a merge request pipeline' do
+ expect(merge_request).to be_persisted
+
+ merge_request.reload
+ expect(merge_request.merge_request_pipelines.count).to eq(0)
+ end
end
context "when branch pipeline was created before a merge request pipline has been created" do
@@ -195,7 +226,7 @@ describe MergeRequests::CreateService do
end
it 'sets the latest merge request pipeline as the head pipeline' do
- expect(merge_request.actual_head_pipeline).to be_merge_request
+ expect(merge_request.actual_head_pipeline).to be_merge_request_event
end
end
@@ -288,7 +319,7 @@ describe MergeRequests::CreateService do
end
it 'removes assignee_id when user id is 0' do
- opts = { title: 'Title', description: 'Description', assignee_id: 0 }
+ opts = { title: 'Title', description: 'Description', assignee_id: 0 }
merge_request = described_class.new(project, user, opts).execute
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index 5d96b5ce27c..9d674263259 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -224,6 +224,18 @@ describe MergeRequests::MergeService do
expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message))
end
+ it 'logs and saves error if user is not authorized' do
+ unauthorized_user = create(:user)
+ project.add_reporter(unauthorized_user)
+
+ service = described_class.new(project, unauthorized_user)
+
+ service.execute(merge_request)
+
+ expect(merge_request.merge_error)
+ .to eq('You are not allowed to merge this merge request')
+ end
+
it 'logs and saves error if there is an PreReceiveError exception' do
error_message = 'error message'
@@ -232,7 +244,7 @@ describe MergeRequests::MergeService do
service.execute(merge_request)
- expect(merge_request.merge_error).to include('Something went wrong during merge pre-receive hook')
+ expect(merge_request.merge_error).to include("Something went wrong during merge pre-receive hook: #{error_message}")
expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message))
end
@@ -258,7 +270,7 @@ describe MergeRequests::MergeService do
it 'logs and saves error if there is an error when squashing' do
error_message = 'Failed to squash. Should be done manually'
- allow_any_instance_of(MergeRequests::SquashService).to receive(:squash).and_return(nil)
+ allow_any_instance_of(MergeRequests::SquashService).to receive(:squash!).and_return(nil)
merge_request.update(squash: true)
service.execute(merge_request)
diff --git a/spec/services/merge_requests/merge_to_ref_service_spec.rb b/spec/services/merge_requests/merge_to_ref_service_spec.rb
new file mode 100644
index 00000000000..96f2fde7117
--- /dev/null
+++ b/spec/services/merge_requests/merge_to_ref_service_spec.rb
@@ -0,0 +1,201 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MergeRequests::MergeToRefService do
+ shared_examples_for 'MergeService for target ref' do
+ it 'target_ref has the same state of target branch' do
+ repo = merge_request.target_project.repository
+
+ process_merge_to_ref
+ merge_service.execute(merge_request)
+
+ ref_commits = repo.commits(merge_request.merge_ref_path, limit: 3)
+ target_branch_commits = repo.commits(merge_request.target_branch, limit: 3)
+
+ ref_commits.zip(target_branch_commits).each do |ref_commit, target_branch_commit|
+ expect(ref_commit.parents).to eq(target_branch_commit.parents)
+ end
+ end
+ end
+
+ set(:user) { create(:user) }
+ let(:merge_request) { create(:merge_request, :simple) }
+ let(:project) { merge_request.project }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ describe '#execute' do
+ let(:service) do
+ described_class.new(project, user,
+ commit_message: 'Awesome message',
+ 'should_remove_source_branch' => true)
+ end
+
+ def process_merge_to_ref
+ perform_enqueued_jobs do
+ service.execute(merge_request)
+ end
+ end
+
+ it 'writes commit to merge ref' do
+ repository = project.repository
+ target_ref = merge_request.merge_ref_path
+
+ expect(repository.ref_exists?(target_ref)).to be(false)
+
+ result = service.execute(merge_request)
+
+ ref_head = repository.commit(target_ref)
+
+ expect(result[:status]).to eq(:success)
+ expect(result[:commit_id]).to be_present
+ expect(repository.ref_exists?(target_ref)).to be(true)
+ expect(ref_head.id).to eq(result[:commit_id])
+ end
+
+ it 'does not send any mail' do
+ expect { process_merge_to_ref }.not_to change { ActionMailer::Base.deliveries.count }
+ end
+
+ it 'does not change the MR state' do
+ expect { process_merge_to_ref }.not_to change { merge_request.state }
+ end
+
+ it 'does not create notes' do
+ expect { process_merge_to_ref }.not_to change { merge_request.notes.count }
+ end
+
+ it 'does not delete the source branch' do
+ expect(DeleteBranchService).not_to receive(:new)
+
+ process_merge_to_ref
+ end
+
+ it 'returns error when feature is disabled' do
+ stub_feature_flags(merge_to_tmp_merge_ref_path: false)
+
+ result = service.execute(merge_request)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Feature is not enabled')
+ end
+
+ it 'returns an error when the failing to process the merge' do
+ allow(project.repository).to receive(:merge_to_ref).and_return(nil)
+
+ result = service.execute(merge_request)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Conflicts detected during merge')
+ end
+
+ context 'commit history comparison with regular MergeService' do
+ let(:merge_ref_service) do
+ described_class.new(project, user, {})
+ end
+
+ let(:merge_service) do
+ MergeRequests::MergeService.new(project, user, {})
+ end
+
+ context 'when merge commit' do
+ it_behaves_like 'MergeService for target ref'
+ end
+
+ context 'when merge commit with squash' do
+ before do
+ merge_request.update!(squash: true, source_branch: 'master', target_branch: 'feature')
+ end
+
+ it_behaves_like 'MergeService for target ref'
+ end
+ end
+
+ context 'merge pre-condition checks' do
+ before do
+ merge_request.project.update!(merge_method: merge_method)
+ end
+
+ context 'when semi-linear merge method' do
+ let(:merge_method) { :rebase_merge }
+
+ it 'return error when MR should be able to fast-forward' do
+ allow(merge_request).to receive(:should_be_rebased?) { true }
+
+ error_message = 'Fast-forward merge is not possible. Please update your source branch.'
+
+ result = service.execute(merge_request)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq(error_message)
+ end
+ end
+
+ context 'when fast-forward merge method' do
+ let(:merge_method) { :ff }
+
+ it 'returns error' do
+ error_message = "Fast-forward to #{merge_request.merge_ref_path} is currently not supported."
+
+ result = service.execute(merge_request)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq(error_message)
+ end
+ end
+
+ context 'when MR is not mergeable to ref' do
+ let(:merge_method) { :merge }
+
+ it 'returns error' do
+ allow(merge_request).to receive(:mergeable_to_ref?) { false }
+
+ error_message = "Merge request is not mergeable to #{merge_request.merge_ref_path}"
+
+ result = service.execute(merge_request)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq(error_message)
+ end
+ end
+ end
+
+ context 'does not close related todos' do
+ let(:merge_request) { create(:merge_request, assignee: user, author: user) }
+ let(:project) { merge_request.project }
+ let!(:todo) do
+ create(:todo, :assigned,
+ project: project,
+ author: user,
+ user: user,
+ target: merge_request)
+ end
+
+ before do
+ allow(service).to receive(:execute_hooks)
+
+ perform_enqueued_jobs do
+ service.execute(merge_request)
+ todo.reload
+ end
+ end
+
+ it { expect(todo).not_to be_done }
+ end
+
+ it 'returns error when user has no authorization to admin the merge request' do
+ unauthorized_user = create(:user)
+ project.add_reporter(unauthorized_user)
+
+ service = described_class.new(project, unauthorized_user)
+
+ result = service.execute(merge_request)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('You are not allowed to merge to this ref')
+ end
+ end
+end
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 1d9c75dedce..43ceb1dcbee 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -150,11 +150,15 @@ describe MergeRequests::RefreshService do
}
end
- it 'create merge request pipeline' do
+ it 'create merge request pipeline with commits' do
expect { subject }
.to change { @merge_request.merge_request_pipelines.count }.by(1)
.and change { @fork_merge_request.merge_request_pipelines.count }.by(1)
- .and change { @another_merge_request.merge_request_pipelines.count }.by(1)
+ .and change { @another_merge_request.merge_request_pipelines.count }.by(0)
+
+ expect(@merge_request.has_commits?).to be_truthy
+ expect(@fork_merge_request.has_commits?).to be_truthy
+ expect(@another_merge_request.has_commits?).to be_falsy
end
context "when branch pipeline was created before a merge request pipline has been created" do
@@ -169,12 +173,12 @@ describe MergeRequests::RefreshService do
it 'sets the latest merge request pipeline as a head pipeline' do
@merge_request.reload
- expect(@merge_request.actual_head_pipeline).to be_merge_request
+ expect(@merge_request.actual_head_pipeline).to be_merge_request_event
end
it 'returns pipelines in correct order' do
@merge_request.reload
- expect(@merge_request.all_pipelines.first).to be_merge_request
+ expect(@merge_request.all_pipelines.first).to be_merge_request_event
expect(@merge_request.all_pipelines.second).to be_push
end
end
@@ -509,7 +513,7 @@ describe MergeRequests::RefreshService do
committed_date: Time.now
)
- allow_any_instance_of(MergeRequest).to receive(:commits).and_return([commit])
+ allow_any_instance_of(MergeRequest).to receive(:commits).and_return(CommitCollection.new(@project, [commit], 'feature'))
end
context 'when the merge request is sourced from the same project' do
diff --git a/spec/services/merge_requests/squash_service_spec.rb b/spec/services/merge_requests/squash_service_spec.rb
index 53bce15735c..2713652873e 100644
--- a/spec/services/merge_requests/squash_service_spec.rb
+++ b/spec/services/merge_requests/squash_service_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe MergeRequests::SquashService do
include GitHelpers
- let(:service) { described_class.new(project, user, {}) }
+ let(:service) { described_class.new(project, user, { merge_request: merge_request }) }
let(:user) { project.owner }
let(:project) { create(:project, :repository) }
let(:repository) { project.repository.raw }
@@ -31,32 +31,49 @@ describe MergeRequests::SquashService do
shared_examples 'the squash succeeds' do
it 'returns the squashed commit SHA' do
- result = service.execute(merge_request)
+ result = service.execute
expect(result).to match(status: :success, squash_sha: a_string_matching(/\h{40}/))
expect(result[:squash_sha]).not_to eq(merge_request.diff_head_sha)
end
it 'cleans up the temporary directory' do
- service.execute(merge_request)
+ service.execute
expect(File.exist?(squash_dir_path)).to be(false)
end
it 'does not keep the branch push event' do
- expect { service.execute(merge_request) }.not_to change { Event.count }
+ expect { service.execute }.not_to change { Event.count }
+ end
+
+ context 'when there is a single commit in the merge request' do
+ before do
+ expect(merge_request).to receive(:commits_count).at_least(:once).and_return(1)
+ end
+
+ it 'will skip performing the squash, as the outcome would be the same' do
+ expect(merge_request.target_project.repository).not_to receive(:squash)
+
+ service.execute
+ end
+
+ it 'will still perform the squash when a custom squash commit message has been provided' do
+ service = described_class.new(project, user, { merge_request: merge_request, squash_commit_message: 'A custom commit message' })
+
+ expect(merge_request.target_project.repository).to receive(:squash).and_return('sha')
+
+ service.execute
+ end
end
context 'the squashed commit' do
- let(:squash_sha) { service.execute(merge_request)[:squash_sha] }
+ let(:squash_sha) { service.execute[:squash_sha] }
let(:squash_commit) { project.repository.commit(squash_sha) }
- it 'copies the author info and message from the merge request' do
+ it 'copies the author info from the merge request' do
expect(squash_commit.author_name).to eq(merge_request.author.name)
expect(squash_commit.author_email).to eq(merge_request.author.email)
-
- # Commit messages have a trailing newline, but titles don't.
- expect(squash_commit.message.chomp).to eq(merge_request.title)
end
it 'sets the current user as the committer' do
@@ -72,21 +89,37 @@ describe MergeRequests::SquashService do
expect(squash_diff.patch.length).to eq(mr_diff.patch.length)
expect(squash_commit.sha).not_to eq(merge_request.diff_head_sha)
end
+
+ it 'has a default squash commit message if no message was provided' do
+ expect(squash_commit.message.chomp).to eq(merge_request.default_squash_commit_message.chomp)
+ end
+
+ context 'if a message was provided' do
+ let(:service) { described_class.new(project, user, { merge_request: merge_request, squash_commit_message: message }) }
+ let(:message) { 'My custom message' }
+ let(:squash_sha) { service.execute[:squash_sha] }
+
+ it 'has the same message as the message provided' do
+ expect(squash_commit.message.chomp).to eq(message)
+ end
+ end
end
end
describe '#execute' do
context 'when there is only one commit in the merge request' do
+ let(:merge_request) { merge_request_with_one_commit }
+
it 'returns that commit SHA' do
- result = service.execute(merge_request_with_one_commit)
+ result = service.execute
- expect(result).to match(status: :success, squash_sha: merge_request_with_one_commit.diff_head_sha)
+ expect(result).to match(status: :success, squash_sha: merge_request.diff_head_sha)
end
it 'does not perform any git actions' do
expect(repository).not_to receive(:popen)
- service.execute(merge_request_with_one_commit)
+ service.execute
end
end
@@ -116,12 +149,11 @@ describe MergeRequests::SquashService do
expect(service).to receive(:log_error).with(log_error)
expect(service).to receive(:log_error).with(error)
- service.execute(merge_request)
+ service.execute
end
it 'returns an error' do
- expect(service.execute(merge_request)).to match(status: :error,
- message: a_string_including('squash'))
+ expect(service.execute).to match(status: :error, message: a_string_including('squash'))
end
end
end
@@ -131,23 +163,22 @@ describe MergeRequests::SquashService do
let(:error) { 'A test error' }
before do
- allow(merge_request).to receive(:commits_count).and_raise(error)
+ allow(merge_request.target_project.repository).to receive(:squash).and_raise(error)
end
it 'logs the MR reference and exception' do
expect(service).to receive(:log_error).with(a_string_including("#{project.full_path}#{merge_request.to_reference}"))
expect(service).to receive(:log_error).with(error)
- service.execute(merge_request)
+ service.execute
end
it 'returns an error' do
- expect(service.execute(merge_request)).to match(status: :error,
- message: a_string_including('squash'))
+ expect(service.execute).to match(status: :error, message: a_string_including('squash'))
end
it 'cleans up the temporary directory' do
- service.execute(merge_request)
+ service.execute
expect(File.exist?(squash_dir_path)).to be(false)
end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index be5ad849ba7..8e367db031c 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -328,7 +328,7 @@ describe MergeRequests::UpdateService, :mailer do
it_behaves_like 'system notes for milestones'
it 'sends notifications for subscribers of changed milestone' do
- merge_request.milestone = create(:milestone)
+ merge_request.milestone = create(:milestone, project: project)
merge_request.save
@@ -352,7 +352,7 @@ describe MergeRequests::UpdateService, :mailer do
end
it 'marks pending todos as done' do
- update_merge_request({ milestone: create(:milestone) })
+ update_merge_request({ milestone: create(:milestone, project: project) })
expect(pending_todo.reload).to be_done
end
@@ -361,7 +361,7 @@ describe MergeRequests::UpdateService, :mailer do
it 'sends notifications for subscribers of changed milestone' do
perform_enqueued_jobs do
- update_merge_request(milestone: create(:milestone))
+ update_merge_request(milestone: create(:milestone, project: project))
end
should_email(subscriber)
@@ -466,6 +466,8 @@ describe MergeRequests::UpdateService, :mailer do
it { expect(@merge_request.tasks?).to eq(true) }
+ it_behaves_like 'updating a single task'
+
context 'when tasks are marked as completed' do
before do
update_merge_request({ description: "- [x] Task 1\n- [X] Task 2" })
diff --git a/spec/services/notes/build_service_spec.rb b/spec/services/notes/build_service_spec.rb
index ff85c261cd4..af4daff336b 100644
--- a/spec/services/notes/build_service_spec.rb
+++ b/spec/services/notes/build_service_spec.rb
@@ -45,6 +45,15 @@ describe Notes::BuildService do
end
end
+ context 'when user has no access to discussion' do
+ it 'sets an error' do
+ another_user = create(:user)
+ new_note = described_class.new(project, another_user, note: 'Test', in_reply_to_discussion_id: note.discussion_id).execute
+
+ expect(new_note.errors[:base]).to include('Discussion to reply to cannot be found')
+ end
+ end
+
context 'personal snippet note' do
def reply(note, user = nil)
user ||= create(:user)
@@ -114,6 +123,46 @@ describe Notes::BuildService do
end
end
+ context 'when replying to individual note' do
+ let(:note) { create(:note_on_issue) }
+
+ subject { described_class.new(project, author, note: 'Test', in_reply_to_discussion_id: note.discussion_id).execute }
+
+ shared_examples 'an individual note reply' do
+ it 'builds another individual note' do
+ expect(subject).to be_valid
+ expect(subject).to be_a(Note)
+ expect(subject.discussion_id).not_to eq(note.discussion_id)
+ end
+ end
+
+ context 'when reply_to_individual_notes is disabled' do
+ before do
+ stub_feature_flags(reply_to_individual_notes: false)
+ end
+
+ it_behaves_like 'an individual note reply'
+ end
+
+ context 'when reply_to_individual_notes is enabled' do
+ before do
+ stub_feature_flags(reply_to_individual_notes: true)
+ end
+
+ it 'sets the note up to be in reply to that note' do
+ expect(subject).to be_valid
+ expect(subject).to be_a(DiscussionNote)
+ expect(subject.discussion_id).to eq(note.discussion_id)
+ end
+
+ context 'when noteable does not support replies' do
+ let(:note) { create(:note_on_commit) }
+
+ it_behaves_like 'an individual note reply'
+ end
+ end
+ end
+
it 'builds a note without saving it' do
new_note = described_class.new(project,
author,
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index 80b015d4cd0..8d8e81173ff 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -127,6 +127,10 @@ describe Notes::CreateService do
create(:diff_note_on_merge_request, noteable: merge_request, project: project_with_repo)
end
+ before do
+ project_with_repo.add_maintainer(user)
+ end
+
context 'when eligible to have a note diff file' do
let(:new_opts) do
opts.merge(in_reply_to_discussion_id: nil,
@@ -216,6 +220,19 @@ describe Notes::CreateService do
expect(note.note).to eq "HELLO\nWORLD"
end
end
+
+ context 'when note only have commands' do
+ it 'adds commands applied message to note errors' do
+ note_text = %(/close)
+ service = double(:service)
+ allow(Issues::UpdateService).to receive(:new).and_return(service)
+ expect(service).to receive(:execute)
+
+ note = described_class.new(project, user, opts.merge(note: note_text)).execute
+
+ expect(note.errors[:commands_only]).to be_present
+ end
+ end
end
context 'as a user who cannot update the target' do
@@ -274,5 +291,49 @@ describe Notes::CreateService do
expect(note.note).to eq(':smile:')
end
end
+
+ context 'reply to individual note' do
+ let(:existing_note) { create(:note_on_issue, noteable: issue, project: project) }
+ let(:reply_opts) { opts.merge(in_reply_to_discussion_id: existing_note.discussion_id) }
+
+ subject { described_class.new(project, user, reply_opts).execute }
+
+ context 'when reply_to_individual_notes is disabled' do
+ before do
+ stub_feature_flags(reply_to_individual_notes: false)
+ end
+
+ it 'creates an individual note' do
+ expect(subject.type).to eq(nil)
+ expect(subject.discussion_id).not_to eq(existing_note.discussion_id)
+ end
+
+ it 'does not convert existing note' do
+ expect { subject }.not_to change { existing_note.reload.type }
+ end
+ end
+
+ context 'when reply_to_individual_notes is enabled' do
+ before do
+ stub_feature_flags(reply_to_individual_notes: true)
+ end
+
+ it 'creates a DiscussionNote in reply to existing note' do
+ expect(subject).to be_a(DiscussionNote)
+ expect(subject.discussion_id).to eq(existing_note.discussion_id)
+ end
+
+ it 'converts existing note to DiscussionNote' do
+ expect do
+ existing_note
+
+ Timecop.freeze(Time.now + 1.minute) { subject }
+
+ existing_note.reload
+ end.to change { existing_note.type }.from(nil).to('DiscussionNote')
+ .and change { existing_note.updated_at }
+ end
+ end
+ end
end
end
diff --git a/spec/services/notes/quick_actions_service_spec.rb b/spec/services/notes/quick_actions_service_spec.rb
index 14d62763a5b..7d2b6d5b8a7 100644
--- a/spec/services/notes/quick_actions_service_spec.rb
+++ b/spec/services/notes/quick_actions_service_spec.rb
@@ -28,8 +28,8 @@ describe Notes::QuickActionsService do
end
it 'closes noteable, sets labels, assigns, and sets milestone to noteable, and leave no note' do
- content, command_params = service.extract_commands(note)
- service.execute(command_params, note)
+ content, update_params = service.execute(note)
+ service.apply_updates(update_params, note)
expect(content).to eq ''
expect(note.noteable).to be_closed
@@ -47,8 +47,8 @@ describe Notes::QuickActionsService do
let(:note_text) { '/reopen' }
it 'opens the noteable, and leave no note' do
- content, command_params = service.extract_commands(note)
- service.execute(command_params, note)
+ content, update_params = service.execute(note)
+ service.apply_updates(update_params, note)
expect(content).to eq ''
expect(note.noteable).to be_open
@@ -59,8 +59,8 @@ describe Notes::QuickActionsService do
let(:note_text) { '/spend 1h' }
it 'updates the spent time on the noteable' do
- content, command_params = service.extract_commands(note)
- service.execute(command_params, note)
+ content, update_params = service.execute(note)
+ service.apply_updates(update_params, note)
expect(content).to eq ''
expect(note.noteable.time_spent).to eq(3600)
@@ -75,8 +75,8 @@ describe Notes::QuickActionsService do
end
it 'closes noteable, sets labels, assigns, and sets milestone to noteable' do
- content, command_params = service.extract_commands(note)
- service.execute(command_params, note)
+ content, update_params = service.execute(note)
+ service.apply_updates(update_params, note)
expect(content).to eq "HELLO\nWORLD"
expect(note.noteable).to be_closed
@@ -94,8 +94,8 @@ describe Notes::QuickActionsService do
let(:note_text) { "HELLO\n/reopen\nWORLD" }
it 'opens the noteable' do
- content, command_params = service.extract_commands(note)
- service.execute(command_params, note)
+ content, update_params = service.execute(note)
+ service.apply_updates(update_params, note)
expect(content).to eq "HELLO\nWORLD"
expect(note.noteable).to be_open
@@ -190,8 +190,8 @@ describe Notes::QuickActionsService do
end
it 'adds only one assignee from the list' do
- _, command_params = service.extract_commands(note)
- service.execute(command_params, note)
+ _, update_params = service.execute(note)
+ service.apply_updates(update_params, note)
expect(note.noteable.assignees.count).to eq(1)
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index d20e712d365..9ba4a11104a 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -177,7 +177,7 @@ describe NotificationService, :mailer do
end
end
- context 'when recieving a non-existent method' do
+ context 'when receiving a non-existent method' do
it 'raises NoMethodError' do
expect { async.foo(key) }.to raise_error(NoMethodError)
end
@@ -1646,6 +1646,23 @@ describe NotificationService, :mailer do
should_not_email(@u_guest_custom)
should_not_email(@u_disabled)
end
+
+ context 'users not having access to the new location' do
+ it 'does not send email' do
+ old_user = create(:user)
+ ProjectAuthorization.create!(project: project, user: old_user, access_level: Gitlab::Access::GUEST)
+
+ build_group(project)
+ reset_delivered_emails!
+
+ notification.project_was_moved(project, "gitlab/gitlab")
+
+ should_email(@g_watcher)
+ should_email(@g_global_watcher)
+ should_email(project.creator)
+ should_not_email(old_user)
+ end
+ end
end
context 'user with notifications disabled' do
@@ -2232,8 +2249,8 @@ describe NotificationService, :mailer do
# Users in the project's group but not part of project's team
# with different notification settings
- def build_group(project)
- group = create_nested_group
+ def build_group(project, visibility: :public)
+ group = create_nested_group(visibility)
project.update(namespace_id: group.id)
# Group member: global=disabled, group=watch
@@ -2249,10 +2266,10 @@ describe NotificationService, :mailer do
# Creates a nested group only if supported
# to avoid errors on MySQL
- def create_nested_group
+ def create_nested_group(visibility)
if Group.supports_nested_objects?
- parent_group = create(:group, :public)
- child_group = create(:group, :public, parent: parent_group)
+ parent_group = create(:group, visibility)
+ child_group = create(:group, visibility, parent: parent_group)
# Parent group member: global=disabled, parent_group=watch, child_group=global
@pg_watcher ||= create_user_with_notification(:watch, 'parent_group_watcher', parent_group)
@@ -2272,7 +2289,7 @@ describe NotificationService, :mailer do
child_group
else
- create(:group, :public)
+ create(:group, visibility)
end
end
diff --git a/spec/services/preview_markdown_service_spec.rb b/spec/services/preview_markdown_service_spec.rb
index 458cb8f1f31..85515d548a7 100644
--- a/spec/services/preview_markdown_service_spec.rb
+++ b/spec/services/preview_markdown_service_spec.rb
@@ -114,23 +114,4 @@ describe PreviewMarkdownService do
expect(result[:commands]).to eq 'Tags this commit to v1.2.3 with "Stable release".'
end
end
-
- it 'sets correct markdown engine' do
- service = described_class.new(project, user, { markdown_version: CacheMarkdownField::CACHE_REDCARPET_VERSION })
- result = service.execute
-
- expect(result[:markdown_engine]).to eq :redcarpet
-
- service = described_class.new(project, user, { markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION })
- result = service.execute
-
- expect(result[:markdown_engine]).to eq :common_mark
- end
-
- it 'honors the legacy_render parameter' do
- service = described_class.new(project, user, { legacy_render: '1' })
- result = service.execute
-
- expect(result[:markdown_engine]).to eq :redcarpet
- end
end
diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb
index 59c08b30f9f..b8055a285f2 100644
--- a/spec/services/projects/after_rename_service_spec.rb
+++ b/spec/services/projects/after_rename_service_spec.rb
@@ -4,53 +4,45 @@ require 'spec_helper'
describe Projects::AfterRenameService do
let(:rugged_config) { rugged_repo(project.repository).config }
+ let(:legacy_storage) { Storage::LegacyProject.new(project) }
+ let(:hashed_storage) { Storage::HashedProject.new(project) }
+ let!(:path_before_rename) { project.path }
+ let!(:full_path_before_rename) { project.full_path }
+ let!(:path_after_rename) { "#{project.path}-renamed" }
+ let!(:full_path_after_rename) { "#{project.full_path}-renamed" }
describe '#execute' do
context 'using legacy storage' do
- let(:project) { create(:project, :repository, :legacy_storage) }
- let(:gitlab_shell) { Gitlab::Shell.new }
+ let(:project) { create(:project, :repository, :wiki_repo, :legacy_storage) }
let(:project_storage) { project.send(:storage) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
before do
# Project#gitlab_shell returns a new instance of Gitlab::Shell on every
# call. This makes testing a bit easier.
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
- allow(project)
- .to receive(:previous_changes)
- .and_return('path' => ['foo'])
-
- allow(project)
- .to receive(:path_was)
- .and_return('foo')
-
stub_feature_flags(skip_hashed_storage_upgrade: false)
end
it 'renames a repository' do
stub_container_registry_config(enabled: false)
- expect(gitlab_shell).to receive(:mv_repository)
- .ordered
- .with(project.repository_storage, "#{project.namespace.full_path}/foo", "#{project.full_path}")
- .and_return(true)
-
- expect(gitlab_shell).to receive(:mv_repository)
- .ordered
- .with(project.repository_storage, "#{project.namespace.full_path}/foo.wiki", "#{project.full_path}.wiki")
- .and_return(true)
-
expect_any_instance_of(SystemHooksService)
.to receive(:execute_hooks_for)
.with(project, :rename)
expect_any_instance_of(Gitlab::UploadsTransfer)
.to receive(:rename_project)
- .with('foo', project.path, project.namespace.full_path)
+ .with(path_before_rename, path_after_rename, project.namespace.full_path)
- expect(project).to receive(:expire_caches_before_rename)
+ expect_repository_exist("#{full_path_before_rename}.git")
+ expect_repository_exist("#{full_path_before_rename}.wiki.git")
+
+ service_execute
- described_class.new(project).execute
+ expect_repository_exist("#{full_path_after_rename}.git")
+ expect_repository_exist("#{full_path_after_rename}.wiki.git")
end
context 'container registry with images' do
@@ -63,8 +55,7 @@ describe Projects::AfterRenameService do
end
it 'raises a RenameFailedError' do
- expect { described_class.new(project).execute }
- .to raise_error(described_class::RenameFailedError)
+ expect { service_execute }.to raise_error(described_class::RenameFailedError)
end
end
@@ -76,7 +67,7 @@ describe Projects::AfterRenameService do
it 'moves pages folder to new location' do
expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project)
- described_class.new(project).execute
+ service_execute
end
end
@@ -88,14 +79,12 @@ describe Projects::AfterRenameService do
it 'moves uploads folder to new location' do
expect_any_instance_of(Gitlab::UploadsTransfer).to receive(:rename_project)
- described_class.new(project).execute
+ service_execute
end
end
it 'updates project full path in .git/config' do
- allow(project_storage).to receive(:rename_repo).and_return(true)
-
- described_class.new(project).execute
+ service_execute
expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
end
@@ -103,13 +92,25 @@ describe Projects::AfterRenameService do
it 'updates storage location' do
allow(project_storage).to receive(:rename_repo).and_return(true)
- described_class.new(project).execute
+ service_execute
expect(project.project_repository).to have_attributes(
disk_path: project.disk_path,
shard_name: project.repository_storage
)
end
+
+ context 'with hashed storage upgrade when renaming enabled' do
+ it 'calls HashedStorage::MigrationService with correct options' do
+ stub_application_setting(hashed_storage_enabled: true)
+
+ expect_next_instance_of(::Projects::HashedStorage::MigrationService) do |service|
+ expect(service).to receive(:execute).and_return(true)
+ end
+
+ service_execute
+ end
+ end
end
context 'using hashed storage' do
@@ -123,25 +124,11 @@ describe Projects::AfterRenameService do
# Project#gitlab_shell returns a new instance of Gitlab::Shell on every
# call. This makes testing a bit easier.
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
- allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
stub_feature_flags(skip_hashed_storage_upgrade: false)
stub_application_setting(hashed_storage_enabled: true)
end
- context 'migration to hashed storage' do
- it 'calls HashedStorageMigrationService with correct options' do
- project = create(:project, :repository, :legacy_storage)
- allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
-
- expect_next_instance_of(::Projects::HashedStorageMigrationService) do |service|
- expect(service).to receive(:execute).and_return(true)
- end
-
- described_class.new(project).execute
- end
- end
-
it 'renames a repository' do
stub_container_registry_config(enabled: false)
@@ -153,7 +140,7 @@ describe Projects::AfterRenameService do
expect(project).to receive(:expire_caches_before_rename)
- described_class.new(project).execute
+ service_execute
end
context 'container registry with images' do
@@ -166,7 +153,7 @@ describe Projects::AfterRenameService do
end
it 'raises a RenameFailedError' do
- expect { described_class.new(project).execute }
+ expect { service_execute }
.to raise_error(described_class::RenameFailedError)
end
end
@@ -175,38 +162,46 @@ describe Projects::AfterRenameService do
it 'moves pages folder to new location' do
expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project)
- described_class.new(project).execute
+ service_execute
end
end
context 'attachments' do
+ let(:uploader) { create(:upload, :issuable_upload, :with_file, model: project) }
+ let(:file_uploader) { build(:file_uploader, project: project) }
+ let(:legacy_storage_path) { File.join(file_uploader.root, legacy_storage.disk_path) }
+ let(:hashed_storage_path) { File.join(file_uploader.root, hashed_storage.disk_path) }
+
it 'keeps uploads folder location unchanged' do
expect_any_instance_of(Gitlab::UploadsTransfer).not_to receive(:rename_project)
- described_class.new(project).execute
+ service_execute
end
context 'when not rolled out' do
let(:project) { create(:project, :repository, storage_version: 1, skip_disk_validation: true) }
- it 'moves pages folder to hashed storage' do
- expect_next_instance_of(Projects::HashedStorage::MigrateAttachmentsService) do |service|
- expect(service).to receive(:execute)
- end
+ it 'moves attachments folder to hashed storage' do
+ expect(File.directory?(legacy_storage_path)).to be_truthy
+ expect(File.directory?(hashed_storage_path)).to be_falsey
- described_class.new(project).execute
+ service_execute
+ expect(project.reload.hashed_storage?(:attachments)).to be_truthy
+
+ expect(File.directory?(legacy_storage_path)).to be_falsey
+ expect(File.directory?(hashed_storage_path)).to be_truthy
end
end
end
it 'updates project full path in .git/config' do
- described_class.new(project).execute
+ service_execute
expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
end
it 'updates storage location' do
- described_class.new(project).execute
+ service_execute
expect(project.project_repository).to have_attributes(
disk_path: project.disk_path,
@@ -215,4 +210,21 @@ describe Projects::AfterRenameService do
end
end
end
+
+ def service_execute
+ # AfterRenameService is called by UpdateService after a successful model.update
+ # the initialization will include before and after paths values
+ project.update(path: path_after_rename)
+
+ described_class.new(project, path_before: path_before_rename, full_path_before: full_path_before_rename).execute
+ end
+
+ def expect_repository_exist(full_path_with_extension)
+ expect(
+ gitlab_shell.exists?(
+ project.repository_storage,
+ full_path_with_extension
+ )
+ ).to be_truthy
+ end
end
diff --git a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
new file mode 100644
index 00000000000..0659130bed2
--- /dev/null
+++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
@@ -0,0 +1,162 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::ContainerRepository::CleanupTagsService do
+ set(:user) { create(:user) }
+ set(:project) { create(:project, :private) }
+ set(:repository) { create(:container_repository, :root, project: project) }
+
+ let(:service) { described_class.new(project, user, params) }
+
+ before do
+ project.add_maintainer(user)
+
+ stub_feature_flags(container_registry_cleanup: true)
+
+ stub_container_registry_config(enabled: true)
+
+ stub_container_registry_tags(
+ repository: repository.path,
+ tags: %w(latest A Ba Bb C D E))
+
+ stub_tag_digest('latest', 'sha256:configA')
+ stub_tag_digest('A', 'sha256:configA')
+ stub_tag_digest('Ba', 'sha256:configB')
+ stub_tag_digest('Bb', 'sha256:configB')
+ stub_tag_digest('C', 'sha256:configC')
+ stub_tag_digest('D', 'sha256:configD')
+ stub_tag_digest('E', nil)
+
+ stub_digest_config('sha256:configA', 1.hour.ago)
+ stub_digest_config('sha256:configB', 5.days.ago)
+ stub_digest_config('sha256:configC', 1.month.ago)
+ stub_digest_config('sha256:configD', nil)
+ end
+
+ describe '#execute' do
+ subject { service.execute(repository) }
+
+ context 'when no params are specified' do
+ let(:params) { {} }
+
+ it 'does not remove anything' do
+ expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag)
+
+ is_expected.to include(status: :success, deleted: [])
+ end
+ end
+
+ context 'when regex matching everything is specified' do
+ let(:params) do
+ { 'name_regex' => '.*' }
+ end
+
+ it 'does remove B* and C' do
+ # The :A cannot be removed as config is shared with :latest
+ # The :E cannot be removed as it does not have valid manifest
+
+ expect_delete('sha256:configB').twice
+ expect_delete('sha256:configC')
+ expect_delete('sha256:configD')
+
+ is_expected.to include(status: :success, deleted: %w(D Bb Ba C))
+ end
+ end
+
+ context 'when regex matching specific tags is used' do
+ let(:params) do
+ { 'name_regex' => 'C|D' }
+ end
+
+ it 'does remove C and D' do
+ expect_delete('sha256:configC')
+ expect_delete('sha256:configD')
+
+ is_expected.to include(status: :success, deleted: %w(D C))
+ end
+ end
+
+ context 'when removing a tagged image that is used by another tag' do
+ let(:params) do
+ { 'name_regex' => 'Ba' }
+ end
+
+ it 'does not remove the tag' do
+ # Issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/21405
+
+ is_expected.to include(status: :success, deleted: [])
+ end
+ end
+
+ context 'when removing keeping only 3' do
+ let(:params) do
+ { 'name_regex' => '.*',
+ 'keep_n' => 3 }
+ end
+
+ it 'does remove C as it is oldest' do
+ expect_delete('sha256:configC')
+
+ is_expected.to include(status: :success, deleted: %w(C))
+ end
+ end
+
+ context 'when removing older than 1 day' do
+ let(:params) do
+ { 'name_regex' => '.*',
+ 'older_than' => '1 day' }
+ end
+
+ it 'does remove B* and C as they are older than 1 day' do
+ expect_delete('sha256:configB').twice
+ expect_delete('sha256:configC')
+
+ is_expected.to include(status: :success, deleted: %w(Bb Ba C))
+ end
+ end
+
+ context 'when combining all parameters' do
+ let(:params) do
+ { 'name_regex' => '.*',
+ 'keep_n' => 1,
+ 'older_than' => '1 day' }
+ end
+
+ it 'does remove B* and C' do
+ expect_delete('sha256:configB').twice
+ expect_delete('sha256:configC')
+
+ is_expected.to include(status: :success, deleted: %w(Bb Ba C))
+ end
+ end
+ end
+
+ private
+
+ def stub_tag_digest(tag, digest)
+ allow_any_instance_of(ContainerRegistry::Client)
+ .to receive(:repository_tag_digest)
+ .with(repository.path, tag) { digest }
+
+ allow_any_instance_of(ContainerRegistry::Client)
+ .to receive(:repository_manifest)
+ .with(repository.path, tag) do
+ { 'config' => { 'digest' => digest } } if digest
+ end
+ end
+
+ def stub_digest_config(digest, created_at)
+ allow_any_instance_of(ContainerRegistry::Client)
+ .to receive(:blob)
+ .with(repository.path, digest, nil) do
+ { 'created' => created_at.to_datetime.rfc3339 }.to_json if created_at
+ end
+ end
+
+ def expect_delete(digest)
+ expect_any_instance_of(ContainerRegistry::Client)
+ .to receive(:delete_repository_tag)
+ .with(repository.path, digest)
+ end
+end
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index f71e2b4bc24..d1b110b9806 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -16,7 +16,11 @@ describe Projects::CreateService, '#execute' do
Label.create(title: "bug", template: true)
project = create_project(user, opts)
- expect(project.labels).not_to be_empty
+ created_label = project.reload.labels.last
+
+ expect(created_label.type).to eq('ProjectLabel')
+ expect(created_label.project_id).to eq(project.id)
+ expect(created_label.title).to eq('bug')
end
context 'user namespace' do
@@ -112,7 +116,7 @@ describe Projects::CreateService, '#execute' do
def wiki_repo(project)
relative_path = ProjectWiki.new(project).disk_path + '.git'
- Gitlab::Git::Repository.new(project.repository_storage, relative_path, 'foobar')
+ Gitlab::Git::Repository.new(project.repository_storage, relative_path, 'foobar', project.full_path)
end
end
@@ -194,7 +198,7 @@ describe Projects::CreateService, '#execute' do
context 'with legacy storage' do
before do
- gitlab_shell.create_repository(repository_storage, "#{user.namespace.full_path}/existing")
+ gitlab_shell.create_repository(repository_storage, "#{user.namespace.full_path}/existing", 'group/project')
end
after do
@@ -230,7 +234,7 @@ describe Projects::CreateService, '#execute' do
end
before do
- gitlab_shell.create_repository(repository_storage, hashed_path)
+ gitlab_shell.create_repository(repository_storage, hashed_path, 'group/project')
end
after do
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 12ddf8447bd..dfbdfa2ab69 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -281,6 +281,40 @@ describe Projects::DestroyService do
end
end
+ context 'repository +deleted path removal' do
+ def removal_path(path)
+ "#{path}+#{project.id}#{described_class::DELETED_FLAG}"
+ end
+
+ context 'regular phase' do
+ it 'schedules +deleted removal of existing repos' do
+ service = described_class.new(project, user, {})
+ allow(service).to receive(:schedule_stale_repos_removal)
+
+ expect(GitlabShellWorker).to receive(:perform_in)
+ .with(5.minutes, :remove_repository, project.repository_storage, removal_path(project.disk_path))
+
+ service.execute
+ end
+ end
+
+ context 'stale cleanup' do
+ let!(:async) { true }
+
+ it 'schedules +deleted wiki and repo removal' do
+ allow(ProjectDestroyWorker).to receive(:perform_async)
+
+ expect(GitlabShellWorker).to receive(:perform_in)
+ .with(10.minutes, :remove_repository, project.repository_storage, removal_path(project.disk_path))
+
+ expect(GitlabShellWorker).to receive(:perform_in)
+ .with(10.minutes, :remove_repository, project.repository_storage, removal_path(project.wiki.disk_path))
+
+ destroy_project(project, user, {})
+ end
+ end
+ end
+
context '#attempt_restore_repositories' do
let(:path) { project.disk_path + '.git' }
diff --git a/spec/services/projects/fetch_statistics_increment_service_spec.rb b/spec/services/projects/fetch_statistics_increment_service_spec.rb
new file mode 100644
index 00000000000..fcfb138aad6
--- /dev/null
+++ b/spec/services/projects/fetch_statistics_increment_service_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+module Projects
+ describe FetchStatisticsIncrementService do
+ let(:project) { create(:project) }
+
+ describe '#execute' do
+ subject { described_class.new(project).execute }
+
+ it 'creates a new record for today with count == 1' do
+ expect { subject }.to change { ProjectDailyStatistic.count }.by(1)
+ created_stat = ProjectDailyStatistic.last
+
+ expect(created_stat.fetch_count).to eq(1)
+ expect(created_stat.project).to eq(project)
+ expect(created_stat.date).to eq(Date.today)
+ end
+
+ it "doesn't increment previous days statistics" do
+ yesterday_stat = create(:project_daily_statistic, fetch_count: 5, project: project, date: 1.day.ago)
+
+ expect { subject }.not_to change { yesterday_stat.reload.fetch_count }
+ end
+
+ context 'when the record already exists for today' do
+ let!(:project_daily_stat) { create(:project_daily_statistic, fetch_count: 5, project: project, date: Date.today) }
+
+ it 'increments the today record count by 1' do
+ expect { subject }.to change { project_daily_stat.reload.fetch_count }.to(6)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 26e8d829345..23ec29cce7b 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -119,7 +119,7 @@ describe Projects::ForkService do
let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
before do
- gitlab_shell.create_repository(repository_storage, "#{@to_user.namespace.full_path}/#{@from_project.path}")
+ gitlab_shell.create_repository(repository_storage, "#{@to_user.namespace.full_path}/#{@from_project.path}", "#{@to_user.namespace.full_path}/#{@from_project.path}")
end
after do
diff --git a/spec/services/projects/group_links/create_service_spec.rb b/spec/services/projects/group_links/create_service_spec.rb
index ffb270d277e..68fd82b4cbe 100644
--- a/spec/services/projects/group_links/create_service_spec.rb
+++ b/spec/services/projects/group_links/create_service_spec.rb
@@ -12,6 +12,10 @@ describe Projects::GroupLinks::CreateService, '#execute' do
end
let(:subject) { described_class.new(project, user, opts) }
+ before do
+ group.add_developer(user)
+ end
+
it 'adds group to project' do
expect { subject.execute(group) }.to change { project.project_group_links.count }.from(0).to(1)
end
@@ -19,4 +23,8 @@ describe Projects::GroupLinks::CreateService, '#execute' do
it 'returns false if group is blank' do
expect { subject.execute(nil) }.not_to change { project.project_group_links.count }
end
+
+ it 'returns error if user is not allowed to share with a group' do
+ expect { subject.execute(create :group) }.not_to change { project.project_group_links.count }
+ end
end
diff --git a/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb b/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb
index 28d8a95fe07..639dd930618 100644
--- a/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb
+++ b/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Projects::HashedStorage::MigrateAttachmentsService do
subject(:service) { described_class.new(project, project.full_path, logger: nil) }
- let(:project) { create(:project, :legacy_storage) }
+ let(:project) { create(:project, :repository, storage_version: 1, skip_disk_validation: true) }
let(:legacy_storage) { Storage::LegacyProject.new(project) }
let(:hashed_storage) { Storage::HashedProject.new(project) }
@@ -28,6 +28,16 @@ describe Projects::HashedStorage::MigrateAttachmentsService do
expect(File.file?(old_disk_path)).to be_falsey
expect(File.file?(new_disk_path)).to be_truthy
end
+
+ it 'returns true' do
+ expect(service.execute).to be_truthy
+ end
+
+ it 'sets skipped to false' do
+ service.execute
+
+ expect(service.skipped?).to be_falsey
+ end
end
context 'when original folder does not exist anymore' do
@@ -43,6 +53,16 @@ describe Projects::HashedStorage::MigrateAttachmentsService do
expect(File.exist?(base_path(hashed_storage))).to be_falsey
expect(File.file?(new_disk_path)).to be_falsey
end
+
+ it 'returns true' do
+ expect(service.execute).to be_truthy
+ end
+
+ it 'sets skipped to true' do
+ service.execute
+
+ expect(service.skipped?).to be_truthy
+ end
end
context 'when target folder already exists' do
@@ -50,14 +70,28 @@ describe Projects::HashedStorage::MigrateAttachmentsService do
FileUtils.mkdir_p(base_path(hashed_storage))
end
- it 'raises AttachmentMigrationError' do
+ it 'raises AttachmentCannotMoveError' do
expect(FileUtils).not_to receive(:mv).with(base_path(legacy_storage), base_path(hashed_storage))
- expect { service.execute }.to raise_error(Projects::HashedStorage::AttachmentMigrationError)
+ expect { service.execute }.to raise_error(Projects::HashedStorage::AttachmentCannotMoveError)
end
end
end
+ context '#old_disk_path' do
+ it 'returns old disk_path for project' do
+ expect(service.old_disk_path).to eq(project.full_path)
+ end
+ end
+
+ context '#new_disk_path' do
+ it 'returns new disk_path for project' do
+ service.execute
+
+ expect(service.new_disk_path).to eq(project.disk_path)
+ end
+ end
+
def base_path(storage)
File.join(FileUploader.root, storage.disk_path)
end
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 0e82194e9ee..e77e2198439 100644
--- a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
+++ b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
@@ -8,19 +8,46 @@ describe Projects::HashedStorage::MigrateRepositoryService do
let(:legacy_storage) { Storage::LegacyProject.new(project) }
let(:hashed_storage) { Storage::HashedProject.new(project) }
- subject(:service) { described_class.new(project, project.full_path) }
+ subject(:service) { described_class.new(project, project.disk_path) }
describe '#execute' do
+ let(:old_disk_path) { legacy_storage.disk_path }
+ let(:new_disk_path) { hashed_storage.disk_path }
+
before do
allow(service).to receive(:gitlab_shell) { gitlab_shell }
end
+ context 'repository lock' do
+ it 'tries to lock the repository' do
+ expect(service).to receive(:try_to_set_repository_read_only!)
+
+ service.execute
+ end
+
+ it 'fails when a git operation is in progress' do
+ allow(project).to receive(:repo_reference_count) { 1 }
+
+ expect { service.execute }.to raise_error(Projects::HashedStorage::RepositoryInUseError)
+ end
+ end
+
+ context 'when repository doesnt exist on disk' do
+ let(:project) { create(:project, :legacy_storage) }
+
+ it 'skips the disk change but increase the version' do
+ service.execute
+
+ expect(project.hashed_storage?(:repository)).to be_truthy
+ end
+ end
+
context 'when succeeds' do
it 'renames project and wiki repositories' do
service.execute
- expect(gitlab_shell.exists?(project.repository_storage, "#{hashed_storage.disk_path}.git")).to be_truthy
- expect(gitlab_shell.exists?(project.repository_storage, "#{hashed_storage.disk_path}.wiki.git")).to be_truthy
+ expect(gitlab_shell.exists?(project.repository_storage, "#{new_disk_path}.git")).to be_truthy
+ expect(gitlab_shell.exists?(project.repository_storage, "#{new_disk_path}.wiki.git")).to be_truthy
end
it 'updates project to be hashed and not read-only' do
@@ -31,8 +58,8 @@ describe Projects::HashedStorage::MigrateRepositoryService do
end
it 'move operation is called for both repositories' do
- expect_move_repository(project.disk_path, hashed_storage.disk_path)
- expect_move_repository("#{project.disk_path}.wiki", "#{hashed_storage.disk_path}.wiki")
+ expect_move_repository(old_disk_path, new_disk_path)
+ expect_move_repository("#{old_disk_path}.wiki", "#{new_disk_path}.wiki")
service.execute
end
@@ -48,32 +75,27 @@ describe Projects::HashedStorage::MigrateRepositoryService do
context 'when one move fails' do
it 'rollsback repositories to original name' do
- from_name = project.disk_path
- to_name = hashed_storage.disk_path
allow(service).to receive(:move_repository).and_call_original
- allow(service).to receive(:move_repository).with(from_name, to_name).once { false } # will disable first move only
+ allow(service).to receive(:move_repository).with(old_disk_path, new_disk_path).once { false } # will disable first move only
expect(service).to receive(:rollback_folder_move).and_call_original
service.execute
- expect(gitlab_shell.exists?(project.repository_storage, "#{hashed_storage.disk_path}.git")).to be_falsey
- expect(gitlab_shell.exists?(project.repository_storage, "#{hashed_storage.disk_path}.wiki.git")).to be_falsey
+ expect(gitlab_shell.exists?(project.repository_storage, "#{new_disk_path}.git")).to be_falsey
+ expect(gitlab_shell.exists?(project.repository_storage, "#{new_disk_path}.wiki.git")).to be_falsey
expect(project.repository_read_only?).to be_falsey
end
context 'when rollback fails' do
- let(:from_name) { legacy_storage.disk_path }
- let(:to_name) { hashed_storage.disk_path }
-
before do
hashed_storage.ensure_storage_path_exists
- gitlab_shell.mv_repository(project.repository_storage, from_name, to_name)
+ gitlab_shell.mv_repository(project.repository_storage, old_disk_path, new_disk_path)
end
- it 'does not try to move nil repository over hashed' do
- expect(gitlab_shell).not_to receive(:mv_repository).with(project.repository_storage, from_name, to_name)
- expect_move_repository("#{project.disk_path}.wiki", "#{hashed_storage.disk_path}.wiki")
+ it 'does not try to move nil repository over existing' do
+ expect(gitlab_shell).not_to receive(:mv_repository).with(project.repository_storage, old_disk_path, new_disk_path)
+ expect_move_repository("#{old_disk_path}.wiki", "#{new_disk_path}.wiki")
service.execute
end
diff --git a/spec/services/projects/hashed_storage/migration_service_spec.rb b/spec/services/projects/hashed_storage/migration_service_spec.rb
new file mode 100644
index 00000000000..b4647586363
--- /dev/null
+++ b/spec/services/projects/hashed_storage/migration_service_spec.rb
@@ -0,0 +1,52 @@
+require 'spec_helper'
+
+describe Projects::HashedStorage::MigrationService do
+ let(:project) { create(:project, :empty_repo, :wiki_repo, :legacy_storage) }
+ let(:logger) { double }
+
+ subject(:service) { described_class.new(project, project.full_path, logger: logger) }
+
+ describe '#execute' do
+ context 'repository migration' do
+ let(:repository_service) { Projects::HashedStorage::MigrateRepositoryService.new(project, project.full_path, logger: logger) }
+
+ it 'delegates migration to Projects::HashedStorage::MigrateRepositoryService' do
+ expect(Projects::HashedStorage::MigrateRepositoryService)
+ .to receive(:new)
+ .with(project, project.full_path, logger: logger)
+ .and_return(repository_service)
+ expect(repository_service).to receive(:execute)
+
+ service.execute
+ end
+
+ it 'does not delegate migration if repository is already migrated' do
+ project.storage_version = ::Project::LATEST_STORAGE_VERSION
+ expect(Projects::HashedStorage::MigrateRepositoryService).not_to receive(:new)
+
+ service.execute
+ end
+ end
+
+ context 'attachments migration' do
+ let(:attachments_service) { Projects::HashedStorage::MigrateAttachmentsService.new(project, project.full_path, logger: logger) }
+
+ it 'delegates migration to Projects::HashedStorage::MigrateRepositoryService' do
+ expect(Projects::HashedStorage::MigrateAttachmentsService)
+ .to receive(:new)
+ .with(project, project.full_path, logger: logger)
+ .and_return(attachments_service)
+ expect(attachments_service).to receive(:execute)
+
+ service.execute
+ end
+
+ it 'does not delegate migration if attachments are already migrated' do
+ project.storage_version = ::Project::LATEST_STORAGE_VERSION
+ expect(Projects::HashedStorage::MigrateAttachmentsService).not_to receive(:new)
+
+ service.execute
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/hashed_storage/rollback_attachments_service_spec.rb b/spec/services/projects/hashed_storage/rollback_attachments_service_spec.rb
new file mode 100644
index 00000000000..6f4154d6011
--- /dev/null
+++ b/spec/services/projects/hashed_storage/rollback_attachments_service_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::HashedStorage::RollbackAttachmentsService do
+ subject(:service) { described_class.new(project, logger: nil) }
+
+ let(:project) { create(:project, :repository, skip_disk_validation: true) }
+ let(:legacy_storage) { Storage::LegacyProject.new(project) }
+ let(:hashed_storage) { Storage::HashedProject.new(project) }
+
+ let!(:upload) { Upload.find_by(path: file_uploader.upload_path) }
+ let(:file_uploader) { build(:file_uploader, project: project) }
+ let(:old_disk_path) { File.join(base_path(hashed_storage), upload.path) }
+ let(:new_disk_path) { File.join(base_path(legacy_storage), upload.path) }
+
+ context '#execute' do
+ context 'when succeeds' do
+ it 'moves attachments to legacy storage layout' do
+ expect(File.file?(old_disk_path)).to be_truthy
+ expect(File.file?(new_disk_path)).to be_falsey
+ expect(File.exist?(base_path(hashed_storage))).to be_truthy
+ expect(File.exist?(base_path(legacy_storage))).to be_falsey
+ expect(FileUtils).to receive(:mv).with(base_path(hashed_storage), base_path(legacy_storage)).and_call_original
+
+ service.execute
+
+ expect(File.exist?(base_path(legacy_storage))).to be_truthy
+ expect(File.exist?(base_path(hashed_storage))).to be_falsey
+ expect(File.file?(old_disk_path)).to be_falsey
+ expect(File.file?(new_disk_path)).to be_truthy
+ end
+
+ it 'returns true' do
+ expect(service.execute).to be_truthy
+ end
+
+ it 'sets skipped to false' do
+ service.execute
+
+ expect(service.skipped?).to be_falsey
+ end
+ end
+
+ context 'when original folder does not exist anymore' do
+ before do
+ FileUtils.rm_rf(base_path(hashed_storage))
+ end
+
+ it 'skips moving folders and go to next' do
+ expect(FileUtils).not_to receive(:mv).with(base_path(hashed_storage), base_path(legacy_storage))
+
+ service.execute
+
+ expect(File.exist?(base_path(legacy_storage))).to be_falsey
+ expect(File.file?(new_disk_path)).to be_falsey
+ end
+
+ it 'returns true' do
+ expect(service.execute).to be_truthy
+ end
+
+ it 'sets skipped to true' do
+ service.execute
+
+ expect(service.skipped?).to be_truthy
+ end
+ end
+
+ context 'when target folder already exists' do
+ before do
+ FileUtils.mkdir_p(base_path(legacy_storage))
+ end
+
+ it 'raises AttachmentCannotMoveError' do
+ expect(FileUtils).not_to receive(:mv).with(base_path(legacy_storage), base_path(hashed_storage))
+
+ expect { service.execute }.to raise_error(Projects::HashedStorage::AttachmentCannotMoveError)
+ end
+ end
+ end
+
+ context '#old_disk_path' do
+ it 'returns old disk_path for project' do
+ expect(service.old_disk_path).to eq(project.disk_path)
+ end
+ end
+
+ context '#new_disk_path' do
+ it 'returns new disk_path for project' do
+ service.execute
+
+ expect(service.new_disk_path).to eq(project.full_path)
+ end
+ end
+
+ def base_path(storage)
+ File.join(FileUploader.root, storage.disk_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
new file mode 100644
index 00000000000..41927934501
--- /dev/null
+++ b/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+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, storage_version: ::Project::HASHED_STORAGE_FEATURES[:repository]) }
+ let(:legacy_storage) { Storage::LegacyProject.new(project) }
+ let(:hashed_storage) { Storage::HashedProject.new(project) }
+
+ subject(:service) { described_class.new(project, project.disk_path) }
+
+ describe '#execute' do
+ let(:old_disk_path) { hashed_storage.disk_path }
+ let(:new_disk_path) { legacy_storage.disk_path }
+
+ before do
+ allow(service).to receive(:gitlab_shell) { gitlab_shell }
+ end
+
+ context 'repository lock' do
+ it 'tries to lock the repository' do
+ expect(service).to receive(:try_to_set_repository_read_only!)
+
+ service.execute
+ end
+
+ it 'fails when a git operation is in progress' do
+ allow(project).to receive(:repo_reference_count) { 1 }
+
+ expect { service.execute }.to raise_error(Projects::HashedStorage::RepositoryInUseError)
+ end
+ end
+
+ context 'when repository doesnt exist on disk' do
+ let(:project) { create(:project) }
+
+ it 'skips the disk change but decrease the version' do
+ service.execute
+
+ expect(project.legacy_storage?).to be_truthy
+ end
+ end
+
+ context 'when succeeds' do
+ it 'renames project and wiki repositories' do
+ service.execute
+
+ expect(gitlab_shell.exists?(project.repository_storage, "#{new_disk_path}.git")).to be_truthy
+ expect(gitlab_shell.exists?(project.repository_storage, "#{new_disk_path}.wiki.git")).to be_truthy
+ end
+
+ it 'updates project to be legacy and not read-only' do
+ service.execute
+
+ expect(project.legacy_storage?).to be_truthy
+ expect(project.repository_read_only).to be_falsey
+ end
+
+ it 'move operation is called for both repositories' do
+ expect_move_repository(old_disk_path, new_disk_path)
+ expect_move_repository("#{old_disk_path}.wiki", "#{new_disk_path}.wiki")
+
+ service.execute
+ end
+
+ it 'writes project full path to .git/config' do
+ service.execute
+
+ rugged_config = rugged_repo(project.repository).config['gitlab.fullpath']
+
+ expect(rugged_config).to eq project.full_path
+ end
+ end
+
+ context 'when one move fails' do
+ it 'rolls repositories back to original name' do
+ allow(service).to receive(:move_repository).and_call_original
+ allow(service).to receive(:move_repository).with(old_disk_path, new_disk_path).once { false } # will disable first move only
+
+ expect(service).to receive(:rollback_folder_move).and_call_original
+
+ service.execute
+
+ expect(gitlab_shell.exists?(project.repository_storage, "#{new_disk_path}.git")).to be_falsey
+ expect(gitlab_shell.exists?(project.repository_storage, "#{new_disk_path}.wiki.git")).to be_falsey
+ expect(project.repository_read_only?).to be_falsey
+ end
+
+ context 'when rollback fails' do
+ before do
+ legacy_storage.ensure_storage_path_exists
+ gitlab_shell.mv_repository(project.repository_storage, old_disk_path, new_disk_path)
+ end
+
+ it 'does not try to move nil repository over existing' do
+ expect(gitlab_shell).not_to receive(:mv_repository).with(project.repository_storage, old_disk_path, new_disk_path)
+ expect_move_repository("#{old_disk_path}.wiki", "#{new_disk_path}.wiki")
+
+ service.execute
+ end
+ end
+ end
+
+ def expect_move_repository(from_name, to_name)
+ expect(gitlab_shell).to receive(:mv_repository).with(project.repository_storage, from_name, to_name).and_call_original
+ end
+ end
+end
diff --git a/spec/services/projects/hashed_storage/rollback_service_spec.rb b/spec/services/projects/hashed_storage/rollback_service_spec.rb
new file mode 100644
index 00000000000..427d1535559
--- /dev/null
+++ b/spec/services/projects/hashed_storage/rollback_service_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::HashedStorage::RollbackService do
+ let(:project) { create(:project, :empty_repo, :wiki_repo) }
+ let(:logger) { double }
+
+ subject(:service) { described_class.new(project, project.full_path, logger: logger) }
+
+ describe '#execute' do
+ context 'attachments rollback' do
+ let(:attachments_service_class) { Projects::HashedStorage::RollbackAttachmentsService }
+ let(:attachments_service) { attachments_service_class.new(project, logger: logger) }
+
+ it 'delegates rollback to Projects::HashedStorage::RollbackAttachmentsService' do
+ expect(attachments_service_class).to receive(:new)
+ .with(project, logger: logger)
+ .and_return(attachments_service)
+ expect(attachments_service).to receive(:execute)
+
+ service.execute
+ end
+
+ it 'does not delegate rollback if repository is in legacy storage already' do
+ project.storage_version = nil
+ expect(attachments_service_class).not_to receive(:new)
+
+ service.execute
+ end
+ end
+
+ context 'repository rollback' do
+ let(:repository_service_class) { Projects::HashedStorage::RollbackRepositoryService }
+ let(:repository_service) { repository_service_class.new(project, project.full_path, logger: logger) }
+
+ it 'delegates rollback to RollbackRepositoryService' do
+ project.storage_version = ::Project::HASHED_STORAGE_FEATURES[:repository]
+
+ expect(repository_service_class).to receive(:new)
+ .with(project, project.full_path, logger: logger)
+ .and_return(repository_service)
+ expect(repository_service).to receive(:execute)
+
+ service.execute
+ end
+
+ it 'does not delegate rollback if repository is in legacy storage already' do
+ project.storage_version = nil
+
+ expect(repository_service_class).not_to receive(:new)
+
+ service.execute
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/hashed_storage_migration_service_spec.rb b/spec/services/projects/hashed_storage_migration_service_spec.rb
deleted file mode 100644
index 5368c3828dd..00000000000
--- a/spec/services/projects/hashed_storage_migration_service_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require 'spec_helper'
-
-describe Projects::HashedStorageMigrationService do
- let(:project) { create(:project, :empty_repo, :wiki_repo, :legacy_storage) }
- let(:logger) { double }
-
- subject(:service) { described_class.new(project, project.full_path, logger: logger) }
-
- describe '#execute' do
- context 'repository migration' do
- let(:repository_service) { Projects::HashedStorage::MigrateRepositoryService.new(project, project.full_path, logger: logger) }
-
- it 'delegates migration to Projects::HashedStorage::MigrateRepositoryService' do
- expect(Projects::HashedStorage::MigrateRepositoryService)
- .to receive(:new)
- .with(project, project.full_path, logger: logger)
- .and_return(repository_service)
- expect(repository_service).to receive(:execute)
-
- service.execute
- end
-
- it 'does not delegate migration if repository is already migrated' do
- project.storage_version = ::Project::LATEST_STORAGE_VERSION
- expect(Projects::HashedStorage::MigrateRepositoryService).not_to receive(:new)
-
- service.execute
- end
- end
-
- context 'attachments migration' do
- let(:attachments_service) { Projects::HashedStorage::MigrateAttachmentsService.new(project, project.full_path, logger: logger) }
-
- it 'delegates migration to Projects::HashedStorage::MigrateRepositoryService' do
- expect(Projects::HashedStorage::MigrateAttachmentsService)
- .to receive(:new)
- .with(project, project.full_path, logger: logger)
- .and_return(attachments_service)
- expect(attachments_service).to receive(:execute)
-
- service.execute
- end
-
- it 'does not delegate migration if attachments are already migrated' do
- project.storage_version = ::Project::LATEST_STORAGE_VERSION
- expect(Projects::HashedStorage::MigrateAttachmentsService).not_to receive(:new)
-
- service.execute
- end
- end
- end
-end
diff --git a/spec/services/projects/import_error_filter_spec.rb b/spec/services/projects/import_error_filter_spec.rb
new file mode 100644
index 00000000000..312b658de89
--- /dev/null
+++ b/spec/services/projects/import_error_filter_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::ImportErrorFilter do
+ it 'filters any full paths' do
+ message = 'Error importing into /my/folder Permission denied @ unlink_internal - /var/opt/gitlab/gitlab-rails/shared/a/b/c/uploads/file'
+
+ expect(described_class.filter_message(message)).to eq('Error importing into [FILTERED] Permission denied @ unlink_internal - [FILTERED]')
+ end
+
+ it 'filters any relative paths ignoring single slash ones' do
+ message = 'Error importing into my/project Permission denied @ unlink_internal - ../file/ and folder/../file'
+
+ expect(described_class.filter_message(message)).to eq('Error importing into [FILTERED] Permission denied @ unlink_internal - [FILTERED] and [FILTERED]')
+ end
+end
diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb
index 06f865dc848..7faf0fc2868 100644
--- a/spec/services/projects/import_service_spec.rb
+++ b/spec/services/projects/import_service_spec.rb
@@ -136,12 +136,12 @@ describe Projects::ImportService do
end
it 'fails if repository import fails' do
- expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).and_raise(Gitlab::Shell::Error.new('Failed to import the repository'))
+ expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).and_raise(Gitlab::Shell::Error.new('Failed to import the repository /a/b/c'))
result = subject.execute
expect(result[:status]).to eq :error
- expect(result[:message]).to eq "Error importing repository #{project.safe_import_url} into #{project.full_path} - Failed to import the repository"
+ expect(result[:message]).to eq "Error importing repository #{project.safe_import_url} into #{project.full_path} - Failed to import the repository [FILTERED]"
end
context 'when repository import scheduled' do
@@ -152,8 +152,11 @@ describe Projects::ImportService do
it 'downloads lfs objects if lfs_enabled is enabled for project' do
allow(project).to receive(:lfs_enabled?).and_return(true)
+
+ service = double
expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return(oid_download_links)
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadService).to receive(:execute).twice
+ expect(Projects::LfsPointers::LfsDownloadService).to receive(:new).and_return(service).twice
+ expect(service).to receive(:execute).twice
subject.execute
end
@@ -211,8 +214,10 @@ describe Projects::ImportService do
it 'does not have a custom repository importer downloads lfs objects' do
allow(Gitlab::GithubImport::ParallelImporter).to receive(:imports_repository?).and_return(false)
+ service = double
expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return(oid_download_links)
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadService).to receive(:execute)
+ expect(Projects::LfsPointers::LfsDownloadService).to receive(:new).and_return(service).twice
+ expect(service).to receive(:execute).twice
subject.execute
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 d7a2829d5f8..f222c52199f 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
@@ -37,8 +37,8 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
describe '#execute' do
it 'retrieves each download link of every non existent lfs object' do
- subject.execute(new_oids).each do |oid, link|
- expect(link).to eq "#{import_url}/gitlab-lfs/objects/#{oid}"
+ subject.execute(new_oids).each do |lfs_download_object|
+ expect(lfs_download_object.link).to eq "#{import_url}/gitlab-lfs/objects/#{lfs_download_object.oid}"
end
end
@@ -50,8 +50,8 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
it 'adds credentials to the download_link' do
result = subject.execute(new_oids)
- result.each do |oid, link|
- expect(link.starts_with?('http://user:password@')).to be_truthy
+ result.each do |lfs_download_object|
+ expect(lfs_download_object.link.starts_with?('http://user:password@')).to be_truthy
end
end
end
@@ -60,8 +60,8 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
it 'does not add any credentials' do
result = subject.execute(new_oids)
- result.each do |oid, link|
- expect(link.starts_with?('http://user:password@')).to be_falsey
+ result.each do |lfs_download_object|
+ expect(lfs_download_object.link.starts_with?('http://user:password@')).to be_falsey
end
end
end
@@ -74,8 +74,8 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
it 'downloads without any credentials' do
result = subject.execute(new_oids)
- result.each do |oid, link|
- expect(link.starts_with?('http://user:password@')).to be_falsey
+ result.each do |lfs_download_object|
+ expect(lfs_download_object.link.starts_with?('http://user:password@')).to be_falsey
end
end
end
@@ -92,7 +92,7 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
describe '#parse_response_links' do
it 'does not add oid entry if href not found' do
- expect(Rails.logger).to receive(:error).with("Link for Lfs Object with oid whatever not found or invalid.")
+ expect(subject).to receive(:log_error).with("Link for Lfs Object with oid whatever not found or invalid.")
result = subject.send(:parse_response_links, invalid_object_response)
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 d7d7f1874eb..876beb39801 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
@@ -2,79 +2,220 @@ require 'spec_helper'
describe Projects::LfsPointers::LfsDownloadService do
let(:project) { create(:project) }
- let(:oid) { '9e548e25631dd9ce6b43afd6359ab76da2819d6a5b474e66118c7819e1d8b3e8' }
+ let(:lfs_content) { SecureRandom.random_bytes(10) }
+ let(:oid) { Digest::SHA256.hexdigest(lfs_content) }
let(:download_link) { "http://gitlab.com/#{oid}" }
- let(:lfs_content) do
- <<~HEREDOC
- whatever
- HEREDOC
- end
+ let(:size) { lfs_content.size }
+ let(:lfs_object) { LfsDownloadObject.new(oid: oid, size: size, link: download_link) }
+ let(:local_request_setting) { false }
- subject { described_class.new(project) }
+ subject { described_class.new(project, lfs_object) }
before do
+ ApplicationSetting.create_from_defaults
+
+ stub_application_setting(allow_local_requests_from_hooks_and_services: local_request_setting)
allow(project).to receive(:lfs_enabled?).and_return(true)
- WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
+ end
+
+ shared_examples 'lfs temporal file is removed' do
+ it do
+ subject.execute
+
+ expect(File.exist?(subject.send(:tmp_filename))).to be false
+ end
+ end
+
+ shared_examples 'no lfs object is created' do
+ it do
+ expect { subject.execute }.not_to change { LfsObject.count }
+ end
+
+ it 'returns error result' do
+ expect(subject.execute[:status]).to eq :error
+ end
+
+ it 'an error is logged' do
+ expect(subject).to receive(:log_error)
+
+ subject.execute
+ end
+
+ it_behaves_like 'lfs temporal file is removed'
+ end
+
+ shared_examples 'lfs object is created' do
+ it do
+ expect(subject).to receive(:download_and_save_file!).and_call_original
+
+ expect { subject.execute }.to change { LfsObject.count }.by(1)
+ end
+
+ it 'returns success result' do
+ expect(subject.execute[:status]).to eq :success
+ end
+
+ it_behaves_like 'lfs temporal file is removed'
end
describe '#execute' do
context 'when file download succeeds' do
- it 'a new lfs object is created' do
- expect { subject.execute(oid, download_link) }.to change { LfsObject.count }.from(0).to(1)
+ before do
+ WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
end
+ it_behaves_like 'lfs object is created'
+
it 'has the same oid' do
- subject.execute(oid, download_link)
+ subject.execute
expect(LfsObject.first.oid).to eq oid
end
+ it 'has the same size' do
+ subject.execute
+
+ expect(LfsObject.first.size).to eq size
+ end
+
it 'stores the content' do
- subject.execute(oid, download_link)
+ subject.execute
- expect(File.read(LfsObject.first.file.file.file)).to eq lfs_content
+ expect(File.binread(LfsObject.first.file.file.file)).to eq lfs_content
end
end
context 'when file download fails' do
- it 'no lfs object is created' do
- expect { subject.execute(oid, download_link) }.to change { LfsObject.count }
+ before do
+ allow(Gitlab::HTTP).to receive(:get).and_return(code: 500, 'success?' => false)
+ end
+
+ it_behaves_like 'no lfs object is created'
+
+ it 'raise StandardError exception' do
+ expect(subject).to receive(:download_and_save_file!).and_raise(StandardError)
+
+ subject.execute
+ end
+ end
+
+ context 'when downloaded lfs file has a different size' do
+ let(:size) { 1 }
+
+ before do
+ WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
+ end
+
+ it_behaves_like 'no lfs object is created'
+
+ it 'raise SizeError exception' do
+ expect(subject).to receive(:download_and_save_file!).and_raise(described_class::SizeError)
+
+ subject.execute
+ end
+ end
+
+ context 'when downloaded lfs file has a different oid' do
+ before do
+ WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
+ allow_any_instance_of(Digest::SHA256).to receive(:hexdigest).and_return('foobar')
+ end
+
+ it_behaves_like 'no lfs object is created'
+
+ it 'raise OidError exception' do
+ expect(subject).to receive(:download_and_save_file!).and_raise(described_class::OidError)
+
+ subject.execute
end
end
context 'when credentials present' do
let(:download_link_with_credentials) { "http://user:password@gitlab.com/#{oid}" }
+ let(:lfs_object) { LfsDownloadObject.new(oid: oid, size: size, link: download_link_with_credentials) }
before do
WebMock.stub_request(:get, download_link).with(headers: { 'Authorization' => 'Basic dXNlcjpwYXNzd29yZA==' }).to_return(body: lfs_content)
end
it 'the request adds authorization headers' do
- subject.execute(oid, download_link_with_credentials)
+ subject
end
end
+ context 'when localhost requests are allowed' do
+ let(:download_link) { 'http://192.168.2.120' }
+ let(:local_request_setting) { true }
+
+ before do
+ WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
+ end
+
+ it_behaves_like 'lfs object is created'
+ end
+
context 'when a bad URL is used' do
- where(download_link: ['/etc/passwd', 'ftp://example.com', 'http://127.0.0.2'])
+ where(download_link: ['/etc/passwd', 'ftp://example.com', 'http://127.0.0.2', 'http://192.168.2.120'])
with_them do
it 'does not download the file' do
- expect(subject).not_to receive(:download_and_save_file)
+ expect(subject).not_to receive(:download_lfs_file!)
+
+ expect { subject.execute }.not_to change { LfsObject.count }
+ end
+ end
+ end
+
+ context 'when the URL points to a redirected URL' do
+ context 'that is blocked' do
+ where(redirect_link: ['ftp://example.com', 'http://127.0.0.2', 'http://192.168.2.120'])
+
+ with_them do
+ before do
+ WebMock.stub_request(:get, download_link).to_return(status: 301, headers: { 'Location' => redirect_link })
+ end
+
+ it_behaves_like 'no lfs object is created'
+ end
+ end
+
+ context 'that is not blocked' do
+ let(:redirect_link) { "http://example.com/"}
- expect { subject.execute(oid, download_link) }.not_to change { LfsObject.count }
+ before do
+ WebMock.stub_request(:get, download_link).to_return(status: 301, headers: { 'Location' => redirect_link })
+ WebMock.stub_request(:get, redirect_link).to_return(body: lfs_content)
end
+
+ it_behaves_like 'lfs object is created'
+ end
+ end
+
+ context 'when the lfs object attributes are invalid' do
+ let(:oid) { 'foobar' }
+
+ before do
+ expect(lfs_object).to be_invalid
+ end
+
+ it_behaves_like 'no lfs object is created'
+
+ it 'does not download the file' do
+ expect(subject).not_to receive(:download_lfs_file!)
+
+ subject.execute
end
end
- context 'when an lfs object with the same oid already exists' do
+ context 'when an lfs object with the same oid already exists' do
before do
- create(:lfs_object, oid: 'oid')
+ create(:lfs_object, oid: oid)
end
it 'does not download the file' do
- expect(subject).not_to receive(:download_and_save_file)
+ expect(subject).not_to receive(:download_lfs_file!)
- subject.execute('oid', download_link)
+ subject.execute
end
end
end
diff --git a/spec/services/projects/operations/update_service_spec.rb b/spec/services/projects/operations/update_service_spec.rb
new file mode 100644
index 00000000000..86b1ec83f50
--- /dev/null
+++ b/spec/services/projects/operations/update_service_spec.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::Operations::UpdateService do
+ set(:user) { create(:user) }
+ set(:project) { create(:project) }
+
+ let(:result) { subject.execute }
+
+ subject { described_class.new(project, user, params) }
+
+ describe '#execute' do
+ context 'error tracking' do
+ context 'with existing error tracking setting' do
+ let(:params) do
+ {
+ error_tracking_setting_attributes: {
+ enabled: false,
+ api_host: 'http://gitlab.com/',
+ token: 'token',
+ project: {
+ slug: 'project',
+ name: 'Project',
+ organization_slug: 'org',
+ organization_name: 'Org'
+ }
+ }
+ }
+ end
+
+ before do
+ create(:project_error_tracking_setting, project: project)
+ end
+
+ it 'updates the settings' do
+ expect(result[:status]).to eq(:success)
+
+ project.reload
+ expect(project.error_tracking_setting).not_to be_enabled
+ expect(project.error_tracking_setting.api_url).to eq(
+ 'http://gitlab.com/api/0/projects/org/project/'
+ )
+ expect(project.error_tracking_setting.token).to eq('token')
+ expect(project.error_tracking_setting[:project_name]).to eq('Project')
+ expect(project.error_tracking_setting[:organization_name]).to eq('Org')
+ end
+
+ context 'disable error tracking' do
+ before do
+ params[:error_tracking_setting_attributes][:api_host] = ''
+ params[:error_tracking_setting_attributes][:enabled] = false
+ end
+
+ it 'can set api_url to nil' do
+ expect(result[:status]).to eq(:success)
+
+ project.reload
+ expect(project.error_tracking_setting).not_to be_enabled
+ expect(project.error_tracking_setting.api_url).to be_nil
+ expect(project.error_tracking_setting.token).to eq('token')
+ expect(project.error_tracking_setting[:project_name]).to eq('Project')
+ expect(project.error_tracking_setting[:organization_name]).to eq('Org')
+ end
+ end
+ end
+
+ context 'without an existing error tracking setting' do
+ let(:params) do
+ {
+ error_tracking_setting_attributes: {
+ enabled: true,
+ api_host: 'http://gitlab.com/',
+ token: 'token',
+ project: {
+ slug: 'project',
+ name: 'Project',
+ organization_slug: 'org',
+ organization_name: 'Org'
+ }
+ }
+ }
+ end
+
+ it 'creates a setting' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.error_tracking_setting).to be_enabled
+ expect(project.error_tracking_setting.api_url).to eq(
+ 'http://gitlab.com/api/0/projects/org/project/'
+ )
+ expect(project.error_tracking_setting.token).to eq('token')
+ expect(project.error_tracking_setting[:project_name]).to eq('Project')
+ expect(project.error_tracking_setting[:organization_name]).to eq('Org')
+ end
+ end
+
+ context 'with invalid parameters' do
+ let(:params) { {} }
+
+ let!(:error_tracking_setting) do
+ create(:project_error_tracking_setting, project: project)
+ end
+
+ it 'does nothing' do
+ expect(result[:status]).to eq(:success)
+ expect(project.reload.error_tracking_setting)
+ .to eq(error_tracking_setting)
+ end
+ end
+ end
+
+ context 'with inappropriate params' do
+ let(:params) { { name: '' } }
+
+ let!(:original_name) { project.name }
+
+ it 'ignores params' do
+ expect(result[:status]).to eq(:success)
+ expect(project.reload.name).to eq(original_name)
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/protect_default_branch_service_spec.rb b/spec/services/projects/protect_default_branch_service_spec.rb
new file mode 100644
index 00000000000..c145b2c06c6
--- /dev/null
+++ b/spec/services/projects/protect_default_branch_service_spec.rb
@@ -0,0 +1,242 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::ProtectDefaultBranchService do
+ let(:service) { described_class.new(project) }
+ let(:project) { instance_spy(Project) }
+
+ describe '#execute' do
+ before do
+ allow(service)
+ .to receive(:protect_default_branch)
+ end
+
+ context 'without a default branch' do
+ it 'does nothing' do
+ allow(service)
+ .to receive(:default_branch)
+ .and_return(nil)
+
+ service.execute
+
+ expect(service)
+ .not_to have_received(:protect_default_branch)
+ end
+ end
+
+ context 'with a default branch' do
+ it 'protects the default branch' do
+ allow(service)
+ .to receive(:default_branch)
+ .and_return('master')
+
+ service.execute
+
+ expect(service)
+ .to have_received(:protect_default_branch)
+ end
+ end
+ end
+
+ describe '#protect_default_branch' do
+ before do
+ allow(service)
+ .to receive(:default_branch)
+ .and_return('master')
+
+ allow(project)
+ .to receive(:change_head)
+ .with('master')
+
+ allow(service)
+ .to receive(:create_protected_branch)
+ end
+
+ context 'when branch protection is needed' do
+ before do
+ allow(service)
+ .to receive(:protect_branch?)
+ .and_return(true)
+
+ allow(service)
+ .to receive(:create_protected_branch)
+ end
+
+ it 'changes the HEAD of the project' do
+ service.protect_default_branch
+
+ expect(project)
+ .to have_received(:change_head)
+ end
+
+ it 'protects the default branch' do
+ service.protect_default_branch
+
+ expect(service)
+ .to have_received(:create_protected_branch)
+ end
+ end
+
+ context 'when branch protection is not needed' do
+ before do
+ allow(service)
+ .to receive(:protect_branch?)
+ .and_return(false)
+ end
+
+ it 'changes the HEAD of the project' do
+ service.protect_default_branch
+
+ expect(project)
+ .to have_received(:change_head)
+ end
+
+ it 'does not protect the default branch' do
+ service.protect_default_branch
+
+ expect(service)
+ .not_to have_received(:create_protected_branch)
+ end
+ end
+ end
+
+ describe '#create_protected_branch' do
+ it 'creates the protected branch' do
+ creator = instance_spy(User)
+ create_service = instance_spy(ProtectedBranches::CreateService)
+ access_level = Gitlab::Access::DEVELOPER
+ params = {
+ name: 'master',
+ push_access_levels_attributes: [{ access_level: access_level }],
+ merge_access_levels_attributes: [{ access_level: access_level }]
+ }
+
+ allow(project)
+ .to receive(:creator)
+ .and_return(creator)
+
+ allow(ProtectedBranches::CreateService)
+ .to receive(:new)
+ .with(project, creator, params)
+ .and_return(create_service)
+
+ allow(service)
+ .to receive(:push_access_level)
+ .and_return(access_level)
+
+ allow(service)
+ .to receive(:merge_access_level)
+ .and_return(access_level)
+
+ allow(service)
+ .to receive(:default_branch)
+ .and_return('master')
+
+ allow(create_service)
+ .to receive(:execute)
+ .with(skip_authorization: true)
+
+ service.create_protected_branch
+
+ expect(create_service)
+ .to have_received(:execute)
+ end
+ end
+
+ describe '#protect_branch?' do
+ context 'when default branch protection is disabled' do
+ it 'returns false' do
+ allow(Gitlab::CurrentSettings)
+ .to receive(:default_branch_protection)
+ .and_return(Gitlab::Access::PROTECTION_NONE)
+
+ expect(service.protect_branch?).to eq(false)
+ end
+ end
+
+ context 'when default branch protection is enabled' do
+ before do
+ allow(Gitlab::CurrentSettings)
+ .to receive(:default_branch_protection)
+ .and_return(Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
+
+ allow(service)
+ .to receive(:default_branch)
+ .and_return('master')
+ end
+
+ it 'returns false if the branch is already protected' do
+ allow(ProtectedBranch)
+ .to receive(:protected?)
+ .with(project, 'master')
+ .and_return(true)
+
+ expect(service.protect_branch?).to eq(false)
+ end
+
+ it 'returns true if the branch is not yet protected' do
+ allow(ProtectedBranch)
+ .to receive(:protected?)
+ .with(project, 'master')
+ .and_return(false)
+
+ expect(service.protect_branch?).to eq(true)
+ end
+ end
+ end
+
+ describe '#default_branch' do
+ it 'returns the default branch of the project' do
+ allow(project)
+ .to receive(:default_branch)
+ .and_return('master')
+
+ expect(service.default_branch).to eq('master')
+ end
+ end
+
+ describe '#push_access_level' do
+ context 'when developers can push' do
+ it 'returns the DEVELOPER access level' do
+ allow(Gitlab::CurrentSettings)
+ .to receive(:default_branch_protection)
+ .and_return(Gitlab::Access::PROTECTION_DEV_CAN_PUSH)
+
+ expect(service.push_access_level).to eq(Gitlab::Access::DEVELOPER)
+ end
+ end
+
+ context 'when developers can not push' do
+ it 'returns the MAINTAINER access level' do
+ allow(Gitlab::CurrentSettings)
+ .to receive(:default_branch_protection)
+ .and_return(Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
+
+ expect(service.push_access_level).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+ end
+
+ describe '#merge_access_level' do
+ context 'when developers can merge' do
+ it 'returns the DEVELOPER access level' do
+ allow(Gitlab::CurrentSettings)
+ .to receive(:default_branch_protection)
+ .and_return(Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
+
+ expect(service.merge_access_level).to eq(Gitlab::Access::DEVELOPER)
+ end
+ end
+
+ context 'when developers can not merge' do
+ it 'returns the MAINTAINER access level' do
+ allow(Gitlab::CurrentSettings)
+ .to receive(:default_branch_protection)
+ .and_return(Gitlab::Access::PROTECTION_DEV_CAN_PUSH)
+
+ expect(service.merge_access_level).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 766276fdba3..aae50d5307f 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -201,7 +201,7 @@ describe Projects::TransferService do
before do
group.add_owner(user)
- unless gitlab_shell.create_repository(repository_storage, "#{group.full_path}/#{project.path}")
+ unless gitlab_shell.create_repository(repository_storage, "#{group.full_path}/#{project.path}", project.full_path)
raise 'failed to add repository'
end
diff --git a/spec/services/projects/update_pages_configuration_service_spec.rb b/spec/services/projects/update_pages_configuration_service_spec.rb
index e4d4e6ff3dd..7f5ef3129d7 100644
--- a/spec/services/projects/update_pages_configuration_service_spec.rb
+++ b/spec/services/projects/update_pages_configuration_service_spec.rb
@@ -2,23 +2,41 @@ require 'spec_helper'
describe Projects::UpdatePagesConfigurationService do
let(:project) { create(:project) }
- subject { described_class.new(project) }
+ let(:service) { described_class.new(project) }
describe "#update" do
let(:file) { Tempfile.new('pages-test') }
+ subject { service.execute }
+
after do
file.close
file.unlink
end
- it 'updates the .update file' do
- # Access this reference to ensure scoping works
- Projects::Settings # rubocop:disable Lint/Void
- expect(subject).to receive(:pages_config_file).and_return(file.path)
- expect(subject).to receive(:reload_daemon).and_call_original
+ before do
+ allow(service).to receive(:pages_config_file).and_return(file.path)
+ end
+
+ context 'when configuration changes' do
+ it 'updates the .update file' do
+ expect(service).to receive(:reload_daemon).and_call_original
+
+ expect(subject).to include(status: :success, reload: true)
+ end
+ end
+
+ context 'when configuration does not change' do
+ before do
+ # we set the configuration
+ service.execute
+ end
+
+ it 'does not update the .update file' do
+ expect(service).not_to receive(:reload_daemon)
- expect(subject.execute).to eq({ status: :success })
+ expect(subject).to include(status: :success, reload: false)
+ end
end
end
end
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index 36b619ba9be..8b70845befe 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -5,24 +5,27 @@ describe Projects::UpdatePagesService do
set(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit('HEAD').sha) }
set(:build) { create(:ci_build, pipeline: pipeline, ref: 'HEAD') }
let(:invalid_file) { fixture_file_upload('spec/fixtures/dk.png') }
- let(:extension) { 'zip' }
- let(:file) { fixture_file_upload("spec/fixtures/pages.#{extension}") }
- let(:empty_file) { fixture_file_upload("spec/fixtures/pages_empty.#{extension}") }
- let(:metadata) do
- filename = "spec/fixtures/pages.#{extension}.meta"
- fixture_file_upload(filename) if File.exist?(filename)
- end
+ let(:file) { fixture_file_upload("spec/fixtures/pages.zip") }
+ let(:empty_file) { fixture_file_upload("spec/fixtures/pages_empty.zip") }
+ let(:metadata_filename) { "spec/fixtures/pages.zip.meta" }
+ let(:metadata) { fixture_file_upload(metadata_filename) if File.exist?(metadata_filename) }
subject { described_class.new(project, build) }
before do
+ stub_feature_flags(safezip_use_rubyzip: true)
+
project.remove_pages
end
- context 'legacy artifacts' do
- let(:extension) { 'zip' }
+ context '::TMP_EXTRACT_PATH' do
+ subject { described_class::TMP_EXTRACT_PATH }
+ it { is_expected.not_to match(Gitlab::PathRegex.namespace_format_regex) }
+ end
+
+ context 'legacy artifacts' do
before do
build.update(legacy_artifacts_file: file)
build.update(legacy_artifacts_metadata: metadata)
@@ -132,6 +135,20 @@ describe Projects::UpdatePagesService do
end
end
+ context 'when using pages with non-writeable public' do
+ let(:file) { fixture_file_upload("spec/fixtures/pages_non_writeable.zip") }
+
+ context 'when using RubyZip' do
+ before do
+ stub_feature_flags(safezip_use_rubyzip: true)
+ end
+
+ it 'succeeds to extract' do
+ expect(execute).to eq(:success)
+ end
+ end
+ end
+
context 'when timeout happens by DNS error' do
before do
allow_any_instance_of(described_class)
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index d58ff2cedc0..90eaea9c872 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -41,7 +41,7 @@ describe Projects::UpdateService do
end
it 'updates the project to private' do
- expect(TodosDestroyer::ProjectPrivateWorker).to receive(:perform_in).with(1.hour, project.id)
+ expect(TodosDestroyer::ProjectPrivateWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, project.id)
result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -191,7 +191,7 @@ describe Projects::UpdateService do
context 'when changing feature visibility to private' do
it 'updates the visibility correctly' do
expect(TodosDestroyer::PrivateFeaturesWorker)
- .to receive(:perform_in).with(1.hour, project.id)
+ .to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, project.id)
result = update_project(project, user, project_feature_attributes:
{ issues_access_level: ProjectFeature::PRIVATE }
@@ -232,7 +232,7 @@ describe Projects::UpdateService do
let(:project) { create(:project, :legacy_storage, :repository, creator: user, namespace: user.namespace) }
before do
- gitlab_shell.create_repository(repository_storage, "#{user.namespace.full_path}/existing")
+ gitlab_shell.create_repository(repository_storage, "#{user.namespace.full_path}/existing", user.namespace.full_path)
end
after do
diff --git a/spec/services/prometheus/adapter_service_spec.rb b/spec/services/prometheus/adapter_service_spec.rb
index 335fc5844aa..505e2935e93 100644
--- a/spec/services/prometheus/adapter_service_spec.rb
+++ b/spec/services/prometheus/adapter_service_spec.rb
@@ -22,7 +22,15 @@ describe Prometheus::AdapterService do
context "prometheus service can't execute queries" do
let(:prometheus_service) { double(:prometheus_service, can_query?: false) }
- context 'with cluster with prometheus installed' do
+ context 'with cluster with prometheus not available' do
+ let!(:prometheus) { create(:clusters_applications_prometheus, :installable, cluster: cluster) }
+
+ it 'returns nil' do
+ expect(subject.prometheus_adapter).to be_nil
+ end
+ end
+
+ context 'with cluster with prometheus available' do
let!(:prometheus) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
it 'returns application handling all environments' do
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index 938764f40b0..ea33d156c8a 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -1526,5 +1526,15 @@ describe QuickActions::InterpretService do
end
end
end
+
+ context "#commands_executed_count" do
+ it 'counts commands executed' do
+ content = "/close and \n/assign me and \n/title new title"
+
+ service.execute(content, issue)
+
+ expect(service.commands_executed_count).to eq(3)
+ end
+ end
end
end
diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb
new file mode 100644
index 00000000000..612e9f152e7
--- /dev/null
+++ b/spec/services/releases/create_service_spec.rb
@@ -0,0 +1,72 @@
+require 'spec_helper'
+
+describe Releases::CreateService do
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+ let(:tag_name) { project.repository.tag_names.first }
+ let(:tag_sha) { project.repository.find_tag(tag_name).dereferenced_target.sha }
+ let(:name) { 'Bionic Beaver' }
+ let(:description) { 'Awesome release!' }
+ let(:params) { { tag: tag_name, name: name, description: description, ref: ref } }
+ let(:ref) { nil }
+ let(:service) { described_class.new(project, user, params) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ describe '#execute' do
+ shared_examples 'a successful release creation' do
+ it 'creates a new release' do
+ result = service.execute
+ expect(result[:status]).to eq(:success)
+ expect(result[:tag]).not_to be_nil
+ expect(result[:release]).not_to be_nil
+ expect(result[:release].description).to eq(description)
+ expect(result[:release].name).to eq(name)
+ expect(result[:release].author).to eq(user)
+ expect(result[:release].sha).to eq(tag_sha)
+ end
+ end
+
+ it_behaves_like 'a successful release creation'
+
+ context 'when the tag does not exist' do
+ let(:tag_name) { 'non-exist-tag' }
+
+ it 'raises an error' do
+ result = service.execute
+
+ expect(result[:status]).to eq(:error)
+ end
+ end
+
+ context 'when ref is provided' do
+ let(:ref) { 'master' }
+ let(:tag_name) { 'foobar' }
+
+ it_behaves_like 'a successful release creation'
+
+ it 'creates a tag if the tag does not exist' do
+ expect(project.repository.ref_exists?("refs/tags/#{tag_name}")).to be_falsey
+
+ result = service.execute
+ expect(result[:status]).to eq(:success)
+ expect(result[:tag]).not_to be_nil
+ expect(result[:release]).not_to be_nil
+ end
+ end
+
+ context 'there already exists a release on a tag' do
+ let!(:release) do
+ create(:release, project: project, tag: tag_name, description: description)
+ end
+
+ it 'raises an error and does not update the release' do
+ result = service.execute
+ expect(result[:status]).to eq(:error)
+ expect(project.releases.find_by(tag: tag_name).description).to eq(description)
+ end
+ end
+ end
+end
diff --git a/spec/services/releases/destroy_service_spec.rb b/spec/services/releases/destroy_service_spec.rb
new file mode 100644
index 00000000000..dd5b8708f36
--- /dev/null
+++ b/spec/services/releases/destroy_service_spec.rb
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+describe Releases::DestroyService do
+ let(:project) { create(:project, :repository) }
+ let(:mainatiner) { create(:user) }
+ let(:repoter) { create(:user) }
+ let(:tag) { 'v1.1.0' }
+ let!(:release) { create(:release, project: project, tag: tag) }
+ let(:service) { described_class.new(project, user, params) }
+ let(:params) { { tag: tag } }
+ let(:user) { mainatiner }
+
+ before do
+ project.add_maintainer(mainatiner)
+ project.add_reporter(repoter)
+ end
+
+ describe '#execute' do
+ subject { service.execute }
+
+ context 'when there is a release' do
+ it 'removes the release' do
+ expect { subject }.to change { project.releases.count }.by(-1)
+ end
+
+ it 'returns the destroyed object' do
+ is_expected.to include(status: :success, release: release)
+ end
+ end
+
+ context 'when tag is not found' do
+ let(:tag) { 'v1.1.1' }
+
+ it 'returns an error' do
+ is_expected.to include(status: :error,
+ message: 'Tag does not exist',
+ http_status: 404)
+ end
+ end
+
+ context 'when release is not found' do
+ let!(:release) { }
+
+ it 'returns an error' do
+ is_expected.to include(status: :error,
+ message: 'Release does not exist',
+ http_status: 404)
+ end
+ end
+
+ context 'when user does not have permission' do
+ let(:user) { repoter }
+
+ it 'returns an error' do
+ is_expected.to include(status: :error,
+ message: 'Access Denied',
+ http_status: 403)
+ end
+ end
+ end
+end
diff --git a/spec/services/releases/update_service_spec.rb b/spec/services/releases/update_service_spec.rb
new file mode 100644
index 00000000000..6c68f364739
--- /dev/null
+++ b/spec/services/releases/update_service_spec.rb
@@ -0,0 +1,50 @@
+require 'spec_helper'
+
+describe Releases::UpdateService do
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+ let(:new_name) { 'A new name' }
+ let(:new_description) { 'The best release!' }
+ let(:params) { { name: new_name, description: new_description, tag: tag_name } }
+ let(:service) { described_class.new(project, user, params) }
+ let!(:release) { create(:release, project: project, author: user, tag: tag_name) }
+ let(:tag_name) { 'v1.1.0' }
+
+ before do
+ project.add_developer(user)
+ end
+
+ describe '#execute' do
+ shared_examples 'a failed update' do
+ it 'raises an error' do
+ result = service.execute
+ expect(result[:status]).to eq(:error)
+ end
+ end
+
+ it 'successfully updates an existing release' do
+ result = service.execute
+ expect(result[:status]).to eq(:success)
+ expect(result[:release].name).to eq(new_name)
+ expect(result[:release].description).to eq(new_description)
+ end
+
+ context 'when the tag does not exists' do
+ let(:tag_name) { 'foobar' }
+
+ it_behaves_like 'a failed update'
+ end
+
+ context 'when the release does not exist' do
+ let!(:release) { }
+
+ it_behaves_like 'a failed update'
+ end
+
+ context 'with an invalid update' do
+ let(:new_description) { '' }
+
+ it_behaves_like 'a failed update'
+ end
+ end
+end
diff --git a/spec/services/resource_events/change_labels_service_spec.rb b/spec/services/resource_events/change_labels_service_spec.rb
index 4c9138fb1ef..070964eb1ec 100644
--- a/spec/services/resource_events/change_labels_service_spec.rb
+++ b/spec/services/resource_events/change_labels_service_spec.rb
@@ -10,7 +10,7 @@ describe ResourceEvents::ChangeLabelsService do
describe '.change_labels' do
subject { described_class.new(resource, author).execute(added_labels: added, removed_labels: removed) }
- let(:labels) { create_list(:label, 2, project: project) }
+ let(:labels) { create_list(:label, 2, project: project) }
def expect_label_event(event, label, action)
expect(event.user).to eq(author)
diff --git a/spec/services/resource_events/merge_into_notes_service_spec.rb b/spec/services/resource_events/merge_into_notes_service_spec.rb
index c76f6e6f77e..72467091791 100644
--- a/spec/services/resource_events/merge_into_notes_service_spec.rb
+++ b/spec/services/resource_events/merge_into_notes_service_spec.rb
@@ -16,8 +16,8 @@ describe ResourceEvents::MergeIntoNotesService do
create(:note_on_issue, opts.merge(params))
end
- set(:project) { create(:project) }
- set(:user) { create(:user) }
+ set(:project) { create(:project) }
+ set(:user) { create(:user) }
set(:resource) { create(:issue, project: project) }
set(:label) { create(:label, project: project) }
set(:label2) { create(:label, project: project) }
@@ -44,7 +44,7 @@ describe ResourceEvents::MergeIntoNotesService do
create_event(created_at: time, user: user2)
create_event(created_at: 1.day.ago, label: label2)
- notes = described_class.new(resource, user).execute()
+ notes = described_class.new(resource, user).execute
expected = [
"added #{label.to_reference} label and removed #{label2.to_reference} label",
@@ -61,7 +61,7 @@ describe ResourceEvents::MergeIntoNotesService do
event = create_event(created_at: 1.day.ago)
notes = described_class.new(resource, user,
- last_fetched_at: 2.days.ago.to_i).execute()
+ last_fetched_at: 2.days.ago.to_i).execute
expect(notes.count).to eq 1
expect(notes.first.discussion_id).to eq event.discussion_id
diff --git a/spec/services/suggestions/apply_service_spec.rb b/spec/services/suggestions/apply_service_spec.rb
index 3a483717756..fe85b5c9065 100644
--- a/spec/services/suggestions/apply_service_spec.rb
+++ b/spec/services/suggestions/apply_service_spec.rb
@@ -117,13 +117,183 @@ describe Suggestions::ApplyService do
expect(commit.committer_email).to eq(user.commit_email)
expect(commit.author_name).to eq(user.name)
end
+
+ context 'when it fails to apply because the file was changed' do
+ it 'returns error message' do
+ service = instance_double(Files::UpdateService)
+
+ expect(Files::UpdateService).to receive(:new)
+ .and_return(service)
+
+ allow(service).to receive(:execute)
+ .and_raise(Files::UpdateService::FileChangedError)
+
+ result = subject.execute(suggestion)
+
+ expect(result).to eq(message: 'The file has been changed', status: :error)
+ end
+ end
+
+ context 'when HEAD from position is different from source branch HEAD on repo' do
+ it 'returns error message' do
+ allow(suggestion).to receive(:appliable?) { true }
+ allow(suggestion.position).to receive(:head_sha) { 'old-sha' }
+ allow(suggestion.noteable).to receive(:source_branch_sha) { 'new-sha' }
+
+ result = subject.execute(suggestion)
+
+ expect(result).to eq(message: 'The file has been changed', status: :error)
+ end
+ end
+
+ context 'multiple suggestions applied' do
+ let(:expected_content) do
+ <<-CONTENT.strip_heredoc
+ require 'fileutils'
+ require 'open3'
+
+ module Popen
+ extend self
+
+
+ def popen(cmd, path=nil)
+ unless cmd.is_a?(Array)
+ # v1 change
+ end
+
+ path ||= Dir.pwd
+ # v1 change
+ vars = {
+ "PWD" => path
+ }
+
+ options = {
+ chdir: path
+ }
+ # v2 change
+ unless File.directory?(path)
+ FileUtils.mkdir_p(path)
+ end
+
+ @cmd_output = ""
+ # v2 change
+
+ Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
+ @cmd_output << stdout.read
+ @cmd_output << stderr.read
+ @cmd_status = wait_thr.value.exitstatus
+ end
+
+ return @cmd_output, @cmd_status
+ end
+ end
+ CONTENT
+ end
+
+ let(:merge_request) do
+ create(:merge_request, source_project: project,
+ target_project: project)
+ end
+
+ def create_suggestion(diff, old_line: nil, new_line: nil, from_content:, to_content:, path:)
+ position = Gitlab::Diff::Position.new(old_path: path,
+ new_path: path,
+ old_line: old_line,
+ new_line: new_line,
+ diff_refs: diff.diff_refs)
+
+ suggestion_note = create(:diff_note_on_merge_request, noteable: merge_request,
+ original_position: position,
+ position: position,
+ project: project)
+ create(:suggestion, note: suggestion_note,
+ from_content: from_content,
+ to_content: to_content)
+ end
+
+ def apply_suggestion(suggestion)
+ suggestion.note.reload
+ merge_request.reload
+ merge_request.clear_memoized_shas
+
+ result = subject.execute(suggestion)
+ refresh = MergeRequests::RefreshService.new(project, user)
+ refresh.execute(merge_request.diff_head_sha,
+ suggestion.commit_id,
+ merge_request.source_branch_ref)
+
+ result
+ end
+
+ def fetch_raw_diff(suggestion)
+ project.reload.commit(suggestion.commit_id).diffs.diff_files.first.diff.diff
+ end
+
+ it 'applies multiple suggestions in subsequent versions correctly' do
+ diff = merge_request.merge_request_diff
+ path = 'files/ruby/popen.rb'
+
+ suggestion_1_changes = { old_line: nil,
+ new_line: 13,
+ from_content: "\n",
+ to_content: "# v1 change\n",
+ path: path }
+
+ suggestion_2_changes = { old_line: 24,
+ new_line: 31,
+ from_content: " @cmd_output << stderr.read\n",
+ to_content: "# v2 change\n",
+ path: path }
+
+ suggestion_1 = create_suggestion(diff, suggestion_1_changes)
+ suggestion_2 = create_suggestion(diff, suggestion_2_changes)
+
+ apply_suggestion(suggestion_1)
+
+ suggestion_1_diff = fetch_raw_diff(suggestion_1)
+
+ # rubocop: disable Layout/TrailingWhitespace
+ expected_suggestion_1_diff = <<-CONTENT.strip_heredoc
+ @@ -10,7 +10,7 @@ module Popen
+ end
+
+ path ||= Dir.pwd
+ -
+ +# v1 change
+ vars = {
+ "PWD" => path
+ }
+ CONTENT
+ # rubocop: enable Layout/TrailingWhitespace
+
+ apply_suggestion(suggestion_2)
+
+ suggestion_2_diff = fetch_raw_diff(suggestion_2)
+
+ # rubocop: disable Layout/TrailingWhitespace
+ expected_suggestion_2_diff = <<-CONTENT.strip_heredoc
+ @@ -28,7 +28,7 @@ module Popen
+
+ Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
+ @cmd_output << stdout.read
+ - @cmd_output << stderr.read
+ +# v2 change
+ @cmd_status = wait_thr.value.exitstatus
+ end
+ CONTENT
+ # rubocop: enable Layout/TrailingWhitespace
+
+ expect(suggestion_1_diff.strip).to eq(expected_suggestion_1_diff.strip)
+ expect(suggestion_2_diff.strip).to eq(expected_suggestion_2_diff.strip)
+ end
+ end
end
context 'fork-project' do
let(:project) { create(:project, :public, :repository) }
let(:forked_project) do
- fork_project_with_submodules(project, user)
+ fork_project_with_submodules(project, user, repository: project.repository)
end
let(:merge_request) do
@@ -192,6 +362,17 @@ describe Suggestions::ApplyService do
project.add_maintainer(user)
end
+ context 'diff file was not found' do
+ it 'returns error message' do
+ expect(suggestion.note).to receive(:latest_diff_file) { nil }
+
+ result = subject.execute(suggestion)
+
+ expect(result).to eq(message: 'The file was not found',
+ status: :error)
+ end
+ end
+
context 'suggestion was already applied' do
it 'returns success status' do
result = subject.execute(suggestion)
diff --git a/spec/services/suggestions/create_service_spec.rb b/spec/services/suggestions/create_service_spec.rb
index f1142c88a69..1b4b15b8eaa 100644
--- a/spec/services/suggestions/create_service_spec.rb
+++ b/spec/services/suggestions/create_service_spec.rb
@@ -9,14 +9,18 @@ describe Suggestions::CreateService do
target_project: project_with_repo)
end
- let(:position) do
- Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
- old_line: nil,
- new_line: 14,
- diff_refs: merge_request.diff_refs)
+ def build_position(args = {})
+ default_args = { old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 14,
+ diff_refs: merge_request.diff_refs }
+
+ Gitlab::Diff::Position.new(default_args.merge(args))
end
+ let(:position) { build_position }
+
let(:markdown) do
<<-MARKDOWN.strip_heredoc
```suggestion
@@ -74,6 +78,21 @@ describe Suggestions::CreateService do
end
end
+ context 'should not create suggestions' do
+ let(:note) do
+ create(:diff_note_on_merge_request, project: project_with_repo,
+ noteable: merge_request,
+ position: position,
+ note: markdown)
+ end
+
+ it 'creates no suggestion when diff file is not found' do
+ expect(note).to receive(:latest_diff_file) { nil }
+
+ expect { subject.execute }.not_to change(Suggestion, :count)
+ end
+ end
+
context 'should create suggestions' do
let(:note) do
create(:diff_note_on_merge_request, project: project_with_repo,
@@ -104,6 +123,22 @@ describe Suggestions::CreateService do
expect(suggestion_2).to have_attributes(from_content: " vars = {\n",
to_content: " xpto\n baz\n")
end
+
+ context 'outdated position note' do
+ let!(:outdated_diff) { merge_request.merge_request_diff }
+ let!(:latest_diff) { merge_request.create_merge_request_diff }
+ let(:outdated_position) { build_position(diff_refs: outdated_diff.diff_refs) }
+ let(:position) { build_position(diff_refs: latest_diff.diff_refs) }
+
+ it 'uses the correct position when creating the suggestion' do
+ expect(note.position)
+ .to receive(:diff_file)
+ .with(project_with_repo.repository)
+ .and_call_original
+
+ subject.execute
+ end
+ end
end
end
end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 0fbfcb34e50..b917de14b2e 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -807,9 +807,10 @@ describe SystemNoteService do
expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with(
body: hash_including(
GlobalID: "GitLab",
+ relationship: 'mentioned on',
object: {
url: project_commit_url(project, commit),
- title: "GitLab: Mentioned on commit - #{commit.title}",
+ title: "Commit - #{commit.title}",
icon: { title: "GitLab", url16x16: favicon_path },
status: { resolved: false }
}
@@ -819,7 +820,7 @@ describe SystemNoteService do
end
context 'for issues' do
- let(:issue) { create(:issue, project: project) }
+ let(:issue) { create(:issue, project: project) }
it "creates comment" do
result = described_class.cross_reference(jira_issue, issue, author)
@@ -833,9 +834,10 @@ describe SystemNoteService do
expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with(
body: hash_including(
GlobalID: "GitLab",
+ relationship: 'mentioned on',
object: {
url: project_issue_url(project, issue),
- title: "GitLab: Mentioned on issue - #{issue.title}",
+ title: "Issue - #{issue.title}",
icon: { title: "GitLab", url16x16: favicon_path },
status: { resolved: false }
}
@@ -859,9 +861,10 @@ describe SystemNoteService do
expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with(
body: hash_including(
GlobalID: "GitLab",
+ relationship: 'mentioned on',
object: {
url: project_snippet_url(project, snippet),
- title: "GitLab: Mentioned on snippet - #{snippet.title}",
+ title: "Snippet - #{snippet.title}",
icon: { title: "GitLab", url16x16: favicon_path },
status: { resolved: false }
}
@@ -1131,7 +1134,7 @@ describe SystemNoteService do
end
context 'across different projects' do
- let(:other_project) { create(:project) }
+ let(:other_project) { create(:project) }
let(:canonical_issue) { create(:issue, project: other_project) }
it_behaves_like 'a system note' do
@@ -1156,7 +1159,7 @@ describe SystemNoteService do
end
context 'across different projects' do
- let(:other_project) { create(:project) }
+ let(:other_project) { create(:project) }
let(:duplicate_issue) { create(:issue, project: other_project) }
it_behaves_like 'a system note' do
@@ -1168,7 +1171,7 @@ describe SystemNoteService do
end
describe '.discussion_lock' do
- subject { described_class.discussion_lock(noteable, author) }
+ subject { described_class.discussion_lock(noteable, author) }
context 'discussion unlocked' do
it_behaves_like 'a system note' do
diff --git a/spec/services/task_list_toggle_service_spec.rb b/spec/services/task_list_toggle_service_spec.rb
new file mode 100644
index 00000000000..b1260cf740a
--- /dev/null
+++ b/spec/services/task_list_toggle_service_spec.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe TaskListToggleService do
+ let(:markdown) do
+ <<-EOT.strip_heredoc
+ * [ ] Task 1
+ * [x] Task 2
+
+ A paragraph
+
+ 1. [X] Item 1
+ - [ ] Sub-item 1
+
+ - [ ] loose list
+
+ with an embedded paragraph
+ EOT
+ end
+
+ let(:markdown_html) do
+ <<-EOT.strip_heredoc
+ <ul data-sourcepos="1:1-3:0" class="task-list" dir="auto">
+ <li data-sourcepos="1:1-1:12" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled> Task 1
+ </li>
+ <li data-sourcepos="2:1-3:0" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled checked> Task 2
+ </li>
+ </ul>
+ <p data-sourcepos="4:1-4:11" dir="auto">A paragraph</p>
+ <ol data-sourcepos="6:1-8:0" class="task-list" dir="auto">
+ <li data-sourcepos="6:1-8:0" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked="" disabled=""> Item 1
+ <ul data-sourcepos="7:4-8:0" class="task-list">
+ <li data-sourcepos="7:4-8:0" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled=""> Sub-item 1
+ </li>
+ </ul>
+ </li>
+ </ol>
+ <ul data-sourcepos="9:1-11:28" class="task-list" dir="auto">
+ <li data-sourcepos="9:1-11:28" class="task-list-item">
+ <p data-sourcepos="9:3-9:16"><input type="checkbox" class="task-list-item-checkbox" disabled=""> loose list</p>
+ <p data-sourcepos="11:3-11:28">with an embedded paragraph</p>
+ </li>
+ </ul>
+ EOT
+ end
+
+ it 'checks Task 1' do
+ toggler = described_class.new(markdown, markdown_html,
+ toggle_as_checked: true,
+ line_source: '* [ ] Task 1', line_number: 1)
+
+ expect(toggler.execute).to be_truthy
+ expect(toggler.updated_markdown.lines[0]).to eq "* [x] Task 1\n"
+ expect(toggler.updated_markdown_html).to include('disabled checked> Task 1')
+ end
+
+ it 'unchecks Item 1' do
+ toggler = described_class.new(markdown, markdown_html,
+ toggle_as_checked: false,
+ line_source: '1. [X] Item 1', line_number: 6)
+
+ expect(toggler.execute).to be_truthy
+ expect(toggler.updated_markdown.lines[5]).to eq "1. [ ] Item 1\n"
+ expect(toggler.updated_markdown_html).to include('disabled> Item 1')
+ end
+
+ it 'checks task in loose list' do
+ toggler = described_class.new(markdown, markdown_html,
+ toggle_as_checked: true,
+ line_source: '- [ ] loose list', line_number: 9)
+
+ expect(toggler.execute).to be_truthy
+ expect(toggler.updated_markdown.lines[8]).to eq "- [x] loose list\n"
+ expect(toggler.updated_markdown_html).to include('disabled checked> loose list')
+ end
+
+ it 'returns false if line_source does not match the text' do
+ toggler = described_class.new(markdown, markdown_html,
+ toggle_as_checked: false,
+ line_source: '* [x] Task Added', line_number: 2)
+
+ expect(toggler.execute).to be_falsey
+ end
+
+ it 'tolerates \r\n line endings' do
+ rn_markdown = markdown.gsub("\n", "\r\n")
+ toggler = described_class.new(rn_markdown, markdown_html,
+ toggle_as_checked: true,
+ line_source: '* [ ] Task 1', line_number: 1)
+
+ expect(toggler.execute).to be_truthy
+ expect(toggler.updated_markdown.lines[0]).to eq "* [x] Task 1\r\n"
+ expect(toggler.updated_markdown_html).to include('disabled checked> Task 1')
+ end
+
+ it 'returns false if markdown is nil' do
+ toggler = described_class.new(nil, markdown_html,
+ toggle_as_checked: false,
+ line_source: '* [x] Task Added', line_number: 2)
+
+ expect(toggler.execute).to be_falsey
+ end
+
+ it 'returns false if markdown_html is nil' do
+ toggler = described_class.new(markdown, nil,
+ toggle_as_checked: false,
+ line_source: '* [x] Task Added', line_number: 2)
+
+ expect(toggler.execute).to be_falsey
+ end
+end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index c52515aefd8..8631f3f9a33 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -19,6 +19,7 @@ describe TodoService do
before do
project.add_guest(guest)
project.add_developer(author)
+ project.add_developer(assignee)
project.add_developer(member)
project.add_developer(john_doe)
project.add_developer(skipped)
@@ -456,7 +457,7 @@ describe TodoService do
end
context 'on commit' do
- let(:project) { create(:project, :repository) }
+ let(:project) { create(:project, :repository) }
it 'creates a todo for each valid mentioned user when leaving a note on commit' do
service.new_note(note_on_commit, john_doe)
diff --git a/spec/services/todos/destroy/entity_leave_service_spec.rb b/spec/services/todos/destroy/entity_leave_service_spec.rb
index 8cb91e7c1b9..4b238280848 100644
--- a/spec/services/todos/destroy/entity_leave_service_spec.rb
+++ b/spec/services/todos/destroy/entity_leave_service_spec.rb
@@ -173,10 +173,10 @@ describe Todos::Destroy::EntityLeaveService do
let(:subproject) { create(:project, group: subgroup) }
let(:subproject2) { create(:project, group: subgroup2) }
- let!(:todo_subproject_user) { create(:todo, user: user, project: subproject) }
- let!(:todo_subproject2_user) { create(:todo, user: user, project: subproject2) }
- let!(:todo_subgroup_user) { create(:todo, user: user, group: subgroup) }
- let!(:todo_subgroup2_user) { create(:todo, user: user, group: subgroup2) }
+ let!(:todo_subproject_user) { create(:todo, user: user, project: subproject) }
+ let!(:todo_subproject2_user) { create(:todo, user: user, project: subproject2) }
+ let!(:todo_subgroup_user) { create(:todo, user: user, group: subgroup) }
+ let!(:todo_subgroup2_user) { create(:todo, user: user, group: subgroup2) }
let!(:todo_subproject_user2) { create(:todo, user: user2, project: subproject) }
let!(:todo_subpgroup_user2) { create(:todo, user: user2, group: subgroup) }
diff --git a/spec/services/todos/destroy/group_private_service_spec.rb b/spec/services/todos/destroy/group_private_service_spec.rb
index 2f49b68f544..5cefbdd35ab 100644
--- a/spec/services/todos/destroy/group_private_service_spec.rb
+++ b/spec/services/todos/destroy/group_private_service_spec.rb
@@ -40,7 +40,7 @@ describe Todos::Destroy::GroupPrivateService do
let(:parent_member) { create(:user) }
let(:subgroup_member) { create(:user) }
- let(:subgproject_member) { create(:user) }
+ let(:subgproject_member) { create(:user) }
let!(:todo_parent_member) { create(:todo, user: parent_member, group: group) }
let!(:todo_subgroup_member) { create(:todo, user: subgroup_member, group: group) }
diff --git a/spec/services/update_release_service_spec.rb b/spec/services/update_release_service_spec.rb
deleted file mode 100644
index dc2d0e2d47a..00000000000
--- a/spec/services/update_release_service_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require 'spec_helper'
-
-describe UpdateReleaseService do
- let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
- let(:tag_name) { project.repository.tag_names.first }
- let(:description) { 'Awesome release!' }
- let(:new_description) { 'The best release!' }
- let(:service) { described_class.new(project, user) }
-
- context 'with an existing release' do
- let(:create_service) { CreateReleaseService.new(project, user) }
-
- before do
- create_service.execute(tag_name, description)
- end
-
- it 'successfully updates an existing release' do
- result = service.execute(tag_name, new_description)
- expect(result[:status]).to eq(:success)
- expect(project.releases.find_by(tag: tag_name).description).to eq(new_description)
- end
- end
-
- it 'raises an error if the tag does not exist' do
- result = service.execute("foobar", description)
- expect(result[:status]).to eq(:error)
- end
-
- it 'raises an error if the release does not exist' do
- result = service.execute(tag_name, description)
- expect(result[:status]).to eq(:error)
- end
-end
diff --git a/spec/services/upload_service_spec.rb b/spec/services/upload_service_spec.rb
index 9b232a52efa..4a809d5bf18 100644
--- a/spec/services/upload_service_spec.rb
+++ b/spec/services/upload_service_spec.rb
@@ -63,11 +63,11 @@ describe UploadService do
@link_to_file = upload_file(@project, txt)
end
- it { expect(@link_to_file).to eq(nil) }
+ it { expect(@link_to_file).to eq({}) }
end
end
def upload_file(project, file)
- described_class.new(project, file, FileUploader).execute
+ described_class.new(project, file, FileUploader).execute.to_h
end
end
diff --git a/spec/services/users/activity_service_spec.rb b/spec/services/users/activity_service_spec.rb
index 719b4adf212..3c0a4ac8e18 100644
--- a/spec/services/users/activity_service_spec.rb
+++ b/spec/services/users/activity_service_spec.rb
@@ -26,6 +26,12 @@ describe Users::ActivityService do
.from(last_activity_on)
.to(Date.today)
end
+
+ it 'tries to obtain ExclusiveLease' do
+ expect(Gitlab::ExclusiveLease).to receive(:new).and_call_original
+
+ subject.execute
+ end
end
context 'when a bad object is passed' do
@@ -46,6 +52,12 @@ describe Users::ActivityService do
it 'does not update last_activity_on' do
expect { subject.execute }.not_to change(user, :last_activity_on)
end
+
+ it 'does not try to obtain ExclusiveLease' do
+ expect(Gitlab::ExclusiveLease).not_to receive(:new)
+
+ subject.execute
+ end
end
context 'when in GitLab read-only instance' do
diff --git a/spec/services/users/migrate_to_ghost_user_service_spec.rb b/spec/services/users/migrate_to_ghost_user_service_spec.rb
index ac3a8738cac..68b0f79c6d1 100644
--- a/spec/services/users/migrate_to_ghost_user_service_spec.rb
+++ b/spec/services/users/migrate_to_ghost_user_service_spec.rb
@@ -6,7 +6,7 @@ describe Users::MigrateToGhostUserService do
let(:service) { described_class.new(user) }
context "migrating a user's associated records to the ghost user" do
- context 'issues' do
+ context 'issues' do
context 'deleted user is present as both author and edited_user' do
include_examples "migrating a deleted user's associated records to the ghost user", Issue, [:author, :last_edited_by] do
let(:created_record) do
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index b1cc6d2eb83..747e04fb18c 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -61,7 +61,7 @@ describe WebHookService do
end
context 'when auth credentials are present' do
- let(:url) {'https://example.org'}
+ let(:url) {'https://example.org'}
let(:project_hook) { create(:project_hook, url: 'https://demo:demo@example.org/') }
it 'uses the credentials' do
@@ -76,7 +76,7 @@ describe WebHookService do
end
context 'when auth credentials are partial present' do
- let(:url) {'https://example.org'}
+ let(:url) {'https://example.org'}
let(:project_hook) { create(:project_hook, url: 'https://demo@example.org/') }
it 'uses the credentials anyways' do
@@ -102,7 +102,7 @@ describe WebHookService do
exception = exception_class.new('Exception message')
WebMock.stub_request(:post, project_hook.url).to_raise(exception)
- expect(service_instance.execute).to eq({ status: :error, message: exception.message })
+ expect(service_instance.execute).to eq({ status: :error, message: exception.to_s })
expect { service_instance.execute }.not_to raise_error
end
end
diff --git a/spec/sidekiq/cron/job_gem_dependency_spec.rb b/spec/sidekiq/cron/job_gem_dependency_spec.rb
index 2e30cf025b0..2e7de75fd08 100644
--- a/spec/sidekiq/cron/job_gem_dependency_spec.rb
+++ b/spec/sidekiq/cron/job_gem_dependency_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Sidekiq::Cron::Job do
describe 'cron jobs' do
- context 'when rufus-scheduler depends on ZoTime or EoTime' do
+ context 'when Fugit depends on ZoTime or EoTime' do
before do
described_class
.create(name: 'TestCronWorker',
@@ -10,7 +10,7 @@ describe Sidekiq::Cron::Job do
class: Settings.cron_jobs[:pipeline_schedule_worker]['job_class'])
end
- it 'does not get "Rufus::Scheduler::ZoTime/EtOrbi::EoTime into an exact number"' do
+ it 'does not get any errors' do
expect { described_class.all.first.should_enque?(Time.now) }.not_to raise_error
end
end
diff --git a/spec/simplecov_env.rb b/spec/simplecov_env.rb
index 25ddf932d42..82236bb4201 100644
--- a/spec/simplecov_env.rb
+++ b/spec/simplecov_env.rb
@@ -1,5 +1,6 @@
require 'simplecov'
require 'active_support/core_ext/numeric/time'
+require_relative '../lib/gitlab/utils'
module SimpleCovEnv
extend self
@@ -16,8 +17,9 @@ module SimpleCovEnv
def configure_job
SimpleCov.configure do
if ENV['CI_JOB_NAME']
- coverage_dir "coverage/#{ENV['CI_JOB_NAME']}"
- command_name ENV['CI_JOB_NAME']
+ job_name = Gitlab::Utils.slugify(ENV['CI_JOB_NAME'])
+ coverage_dir "coverage/#{job_name}"
+ command_name job_name
end
if ENV['CI']
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 4042120e2c2..e8d7b18bf04 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -22,7 +22,7 @@ if rspec_profiling_is_configured && (!ENV.key?('CI') || branch_can_be_profiled)
require 'rspec_profiling/rspec'
end
-if ENV['CI'] && !ENV['NO_KNAPSACK']
+if ENV['CI'] && ENV['KNAPSACK_GENERATE_REPORT'] && !ENV['NO_KNAPSACK']
require 'knapsack'
Knapsack::Adapters::RSpecAdapter.bind
end
@@ -115,10 +115,17 @@ RSpec.configure do |config|
TestEnv.clean_test_path
end
- config.before do
+ config.before do |example|
# Enable all features by default for testing
allow(Feature).to receive(:enabled?) { true }
+ enabled = example.metadata[:enable_rugged].present?
+
+ # Disable Rugged features by default
+ Gitlab::Git::RuggedImpl::Repository::FEATURE_FLAGS.each do |flag|
+ allow(Feature).to receive(:enabled?).with(flag).and_return(enabled)
+ end
+
# The following can be removed when we remove the staged rollout strategy
# and we can just enable it using instance wide settings
# (ie. ApplicationSetting#auto_devops_enabled)
@@ -127,6 +134,11 @@ RSpec.configure do |config|
.and_return(false)
end
+ config.before(:example, :quarantine) do
+ # Skip tests in quarantine unless we explicitly focus on them.
+ skip('In quarantine') unless config.inclusion_filter[:quarantine]
+ end
+
config.before(:example, :request_store) do
RequestStore.begin!
end
@@ -216,11 +228,15 @@ RSpec.configure do |config|
# Each example may call `migrate!`, so we must ensure we are migrated down every time
config.before(:each, :migration) do
+ use_fake_application_settings
+
schema_migrate_down!
end
config.after(:context, :migration) do
schema_migrate_up!
+
+ Gitlab::CurrentSettings.clear_in_memory_application_settings!
end
config.around(:each, :nested_groups) do |example|
diff --git a/spec/support/controllers/githubish_import_controller_shared_examples.rb b/spec/support/controllers/githubish_import_controller_shared_examples.rb
index 697f999e4c4..5bb1269a19d 100644
--- a/spec/support/controllers/githubish_import_controller_shared_examples.rb
+++ b/spec/support/controllers/githubish_import_controller_shared_examples.rb
@@ -58,36 +58,54 @@ end
shared_examples 'a GitHub-ish import controller: GET status' do
let(:new_import_url) { public_send("new_import_#{provider}_url") }
let(:user) { create(:user) }
- let(:repo) { OpenStruct.new(login: 'vim', full_name: 'asd/vim') }
+ let(:repo) { OpenStruct.new(login: 'vim', full_name: 'asd/vim', name: 'vim', owner: { login: 'owner' }) }
let(:org) { OpenStruct.new(login: 'company') }
- let(:org_repo) { OpenStruct.new(login: 'company', full_name: 'company/repo') }
- let(:extra_assign_expectations) { {} }
+ let(:org_repo) { OpenStruct.new(login: 'company', full_name: 'company/repo', name: 'repo', owner: { login: 'owner' }) }
before do
assign_session_token(provider)
end
- it "assigns variables" do
- project = create(:project, import_type: provider, namespace: user.namespace)
+ it "returns variables for json request" do
+ project = create(:project, import_type: provider, namespace: user.namespace, import_status: :finished, import_source: 'example/repo')
+ group = create(:group)
+ group.add_owner(user)
stub_client(repos: [repo, org_repo], orgs: [org], org_repos: [org_repo])
- get :status
+ get :status, format: :json
- expect(assigns(:already_added_projects)).to eq([project])
- expect(assigns(:repos)).to eq([repo, org_repo])
- extra_assign_expectations.each do |key, value|
- expect(assigns(key)).to eq(value)
- end
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response.dig("imported_projects", 0, "id")).to eq(project.id)
+ expect(json_response.dig("provider_repos", 0, "id")).to eq(repo.id)
+ expect(json_response.dig("provider_repos", 1, "id")).to eq(org_repo.id)
+ expect(json_response.dig("namespaces", 0, "id")).to eq(group.id)
end
it "does not show already added project" do
- project = create(:project, import_type: provider, namespace: user.namespace, import_source: 'asd/vim')
+ project = create(:project, import_type: provider, namespace: user.namespace, import_status: :finished, import_source: 'asd/vim')
stub_client(repos: [repo], orgs: [])
+ get :status, format: :json
+
+ expect(json_response.dig("imported_projects", 0, "id")).to eq(project.id)
+ expect(json_response.dig("provider_repos")).to eq([])
+ end
+
+ it "touches the etag cache store" do
+ expect(stub_client(repos: [], orgs: [])).to receive(:repos)
+ expect_next_instance_of(Gitlab::EtagCaching::Store) do |store|
+ expect(store).to receive(:touch) { "realtime_changes_import_#{provider}_path" }
+ end
+
+ get :status, format: :json
+ end
+
+ it "requests provider repos list" do
+ expect(stub_client(repos: [], orgs: [])).to receive(:repos)
+
get :status
- expect(assigns(:already_added_projects)).to eq([project])
- expect(assigns(:repos)).to eq([])
+ expect(response).to have_gitlab_http_status(200)
end
it "handles an invalid access token" do
@@ -100,13 +118,32 @@ shared_examples 'a GitHub-ish import controller: GET status' do
expect(controller).to redirect_to(new_import_url)
expect(flash[:alert]).to eq("Access denied to your #{Gitlab::ImportSources.title(provider.to_s)} account.")
end
+
+ it "does not produce N+1 database queries" do
+ stub_client(repos: [repo], orgs: [])
+ group_a = create(:group)
+ group_a.add_owner(user)
+ create(:project, :import_started, import_type: provider, namespace: user.namespace)
+
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ get :status, format: :json
+ end.count
+
+ stub_client(repos: [repo, org_repo], orgs: [])
+ group_b = create(:group)
+ group_b.add_owner(user)
+ create(:project, :import_started, import_type: provider, namespace: user.namespace)
+
+ expect { get :status, format: :json }
+ .not_to exceed_all_query_limit(control_count)
+ end
end
shared_examples 'a GitHub-ish import controller: POST create' do
let(:user) { create(:user) }
- let(:project) { create(:project) }
let(:provider_username) { user.username }
let(:provider_user) { OpenStruct.new(login: provider_username) }
+ let(:project) { create(:project, import_type: provider, import_status: :finished, import_source: "#{provider_username}/vim") }
let(:provider_repo) do
OpenStruct.new(
name: 'vim',
@@ -145,6 +182,17 @@ shared_examples 'a GitHub-ish import controller: POST create' do
expect(json_response['errors']).to eq('Name is invalid, Path is old')
end
+ it "touches the etag cache store" do
+ allow(Gitlab::LegacyGithubImport::ProjectCreator)
+ .to receive(:new).with(provider_repo, provider_repo.name, user.namespace, user, access_params, type: provider)
+ .and_return(double(execute: project))
+ expect_next_instance_of(Gitlab::EtagCaching::Store) do |store|
+ expect(store).to receive(:touch) { "realtime_changes_import_#{provider}_path" }
+ end
+
+ post :create, format: :json
+ end
+
context "when the repository owner is the provider user" do
context "when the provider user and GitLab user's usernames match" do
it "takes the current user's namespace" do
@@ -351,7 +399,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
it 'does not create a new namespace under the user namespace' do
expect(Gitlab::LegacyGithubImport::ProjectCreator)
.to receive(:new).with(provider_repo, test_name, user.namespace, user, access_params, type: provider)
- .and_return(double(execute: build_stubbed(:project)))
+ .and_return(double(execute: project))
expect { post :create, params: { target_namespace: "#{user.namespace_path}/test_group", new_name: test_name }, format: :js }
.not_to change { Namespace.count }
@@ -365,7 +413,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
it 'does not take the selected namespace and name' do
expect(Gitlab::LegacyGithubImport::ProjectCreator)
.to receive(:new).with(provider_repo, test_name, user.namespace, user, access_params, type: provider)
- .and_return(double(execute: build_stubbed(:project)))
+ .and_return(double(execute: project))
post :create, params: { target_namespace: 'foo/foobar/bar', new_name: test_name }, format: :js
end
@@ -373,7 +421,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
it 'does not create the namespaces' do
allow(Gitlab::LegacyGithubImport::ProjectCreator)
.to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider)
- .and_return(double(execute: build_stubbed(:project)))
+ .and_return(double(execute: project))
expect { post :create, params: { target_namespace: 'foo/foobar/bar', new_name: test_name }, format: :js }
.not_to change { Namespace.count }
@@ -390,7 +438,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
expect(Gitlab::LegacyGithubImport::ProjectCreator)
.to receive(:new).with(provider_repo, test_name, group, user, access_params, type: provider)
- .and_return(double(execute: build_stubbed(:project)))
+ .and_return(double(execute: project))
post :create, params: { target_namespace: 'foo', new_name: test_name }, format: :js
end
@@ -407,3 +455,20 @@ shared_examples 'a GitHub-ish import controller: POST create' do
end
end
end
+
+shared_examples 'a GitHub-ish import controller: GET realtime_changes' do
+ let(:user) { create(:user) }
+
+ before do
+ assign_session_token(provider)
+ end
+
+ it 'sets a Poll-Interval header' do
+ project = create(:project, import_type: provider, namespace: user.namespace, import_status: :finished, import_source: 'example/repo')
+
+ get :realtime_changes
+
+ expect(json_response).to eq([{ "id" => project.id, "import_status" => project.import_status }])
+ expect(Integer(response.headers['Poll-Interval'])).to be > -1
+ end
+end
diff --git a/spec/support/features/reportable_note_shared_examples.rb b/spec/support/features/reportable_note_shared_examples.rb
index 8cfce49da8a..89dfbf931d2 100644
--- a/spec/support/features/reportable_note_shared_examples.rb
+++ b/spec/support/features/reportable_note_shared_examples.rb
@@ -41,7 +41,7 @@ shared_examples 'reportable note' do |type|
def open_dropdown(dropdown)
# make window wide enough that tooltip doesn't trigger horizontal scrollbar
- resize_window(1200, 800)
+ restore_window_size
dropdown.find('.more-actions-toggle').click
dropdown.find('.dropdown-menu li', match: :first)
diff --git a/spec/support/features/resolving_discussions_in_issues_shared_examples.rb b/spec/support/features/resolving_discussions_in_issues_shared_examples.rb
index 4a946995f84..38e5fb155a4 100644
--- a/spec/support/features/resolving_discussions_in_issues_shared_examples.rb
+++ b/spec/support/features/resolving_discussions_in_issues_shared_examples.rb
@@ -5,7 +5,7 @@ shared_examples 'creating an issue for a discussion' do
expect(title_field.value).to include(merge_request.title)
end
- it 'has a mention of the discussion in the description' do
+ it 'has a mention of the discussion in the description' do
description_field = page.find_field('issue[description]')
expect(description_field.value).to include(discussion.first_note.note)
diff --git a/spec/support/features/variable_list_shared_examples.rb b/spec/support/features/variable_list_shared_examples.rb
index 0a464d77cb7..73156d18c1b 100644
--- a/spec/support/features/variable_list_shared_examples.rb
+++ b/spec/support/features/variable_list_shared_examples.rb
@@ -8,7 +8,7 @@ shared_examples 'variable list' do
it 'adds new CI variable' do
page.within('.js-ci-variable-list-section .js-row:last-child') do
find('.js-ci-variable-input-key').set('key')
- find('.js-ci-variable-input-value').set('key value')
+ find('.js-ci-variable-input-value').set('key_value')
end
click_button('Save variables')
@@ -19,7 +19,7 @@ shared_examples 'variable list' do
# We check the first row because it re-sorts to alphabetical order on refresh
page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key value')
+ expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
end
end
@@ -44,7 +44,7 @@ shared_examples 'variable list' do
it 'adds new protected variable' do
page.within('.js-ci-variable-list-section .js-row:last-child') do
find('.js-ci-variable-input-key').set('key')
- find('.js-ci-variable-input-value').set('key value')
+ find('.js-ci-variable-input-value').set('key_value')
find('.ci-variable-protected-item .js-project-feature-toggle').click
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
@@ -58,7 +58,7 @@ shared_examples 'variable list' do
# We check the first row because it re-sorts to alphabetical order on refresh
page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key value')
+ expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
end
end
diff --git a/spec/support/gitlab_stubs/gitlab_ci.yml b/spec/support/gitlab_stubs/gitlab_ci.yml
index e55a61b2b94..f3755e52b2c 100644
--- a/spec/support/gitlab_stubs/gitlab_ci.yml
+++ b/spec/support/gitlab_stubs/gitlab_ci.yml
@@ -1,9 +1,8 @@
-image: ruby:2.1
+image: ruby:2.6
services:
- postgres
before_script:
- - gem install bundler
- bundle install
- bundle exec rake db:create
diff --git a/spec/support/helpers/api_helpers.rb b/spec/support/helpers/api_helpers.rb
index a57a3b2cf34..4a9ce9beb78 100644
--- a/spec/support/helpers/api_helpers.rb
+++ b/spec/support/helpers/api_helpers.rb
@@ -36,4 +36,11 @@ module ApiHelpers
full_path
end
+
+ def expect_paginated_array_response(items)
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |item| item['id'] }).to eq(Array(items))
+ end
end
diff --git a/spec/support/helpers/fake_blob_helpers.rb b/spec/support/helpers/fake_blob_helpers.rb
index bc9686ed9cf..801ca8b7412 100644
--- a/spec/support/helpers/fake_blob_helpers.rb
+++ b/spec/support/helpers/fake_blob_helpers.rb
@@ -23,7 +23,7 @@ module FakeBlobHelpers
0
end
- def binary?
+ def binary_in_repo?
@binary
end
diff --git a/spec/support/helpers/features/responsive_table_helpers.rb b/spec/support/helpers/features/responsive_table_helpers.rb
new file mode 100644
index 00000000000..7a175219fe9
--- /dev/null
+++ b/spec/support/helpers/features/responsive_table_helpers.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+# These helpers allow you to access rows in a responsive table
+#
+# Usage:
+# describe "..." do
+# include Spec::Support::Helpers::Features::ResponsiveTableHelpers
+# ...
+#
+# expect(first_row.text).to include("John Doe")
+# expect(second_row.text).to include("John Smith")
+#
+# Note:
+# index starts at 1 as index 0 is expected to be the table header
+#
+#
+module Spec
+ module Support
+ module Helpers
+ module Features
+ module ResponsiveTableHelpers
+ def first_row
+ page.all('.gl-responsive-table-row')[1]
+ end
+
+ def second_row
+ page.all('.gl-responsive-table-row')[2]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/file_mover_helpers.rb b/spec/support/helpers/file_mover_helpers.rb
new file mode 100644
index 00000000000..1ba7cc03354
--- /dev/null
+++ b/spec/support/helpers/file_mover_helpers.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module FileMoverHelpers
+ def stub_file_mover(file_path, stub_real_path: nil)
+ file_name = File.basename(file_path)
+ allow(Pathname).to receive(:new).and_call_original
+
+ expect_next_instance_of(Pathname, a_string_including(file_name)) do |pathname|
+ allow(pathname).to receive(:realpath) { stub_real_path || pathname.cleanpath }
+ end
+ end
+end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index dd32ea3985f..6cdc19ac2e5 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -77,14 +77,24 @@ module GraphqlHelpers
def query_graphql_field(name, attributes = {}, fields = nil)
fields ||= all_graphql_fields_for(name.classify)
attributes = attributes_to_graphql(attributes)
+ attributes = "(#{attributes})" if attributes.present?
<<~QUERY
- #{name}(#{attributes}) {
- #{fields}
- }
+ #{name}#{attributes}
+ #{wrap_fields(fields)}
QUERY
end
- def all_graphql_fields_for(class_name)
+ def wrap_fields(fields)
+ return unless fields.strip.present?
+
+ <<~FIELDS
+ {
+ #{fields}
+ }
+ FIELDS
+ end
+
+ def all_graphql_fields_for(class_name, parent_types = Set.new)
type = GitlabSchema.types[class_name.to_s]
return "" unless type
@@ -92,8 +102,17 @@ module GraphqlHelpers
# We can't guess arguments, so skip fields that require them
next if required_arguments?(field)
+ singular_field_type = field_type(field)
+
+ # If field type is the same as parent type, then we're hitting into
+ # mutual dependency. Break it from infinite recursion
+ next if parent_types.include?(singular_field_type)
+
if nested_fields?(field)
- "#{name} { #{all_graphql_fields_for(field_type(field))} }"
+ fields =
+ all_graphql_fields_for(singular_field_type, parent_types | [type])
+
+ "#{name} { #{fields} }"
else
name
end
@@ -106,8 +125,8 @@ module GraphqlHelpers
end.join(", ")
end
- def post_graphql(query, current_user: nil, variables: nil)
- post api('/', current_user, version: 'graphql'), params: { query: query, variables: variables }
+ def post_graphql(query, current_user: nil, variables: nil, headers: {})
+ post api('/', current_user, version: 'graphql'), params: { query: query, variables: variables }, headers: headers
end
def post_graphql_mutation(mutation, current_user: nil)
@@ -149,7 +168,7 @@ module GraphqlHelpers
# - List
# - String!
# - String
- field_type = field_type.of_type while field_type.respond_to?(:of_type)
+ field_type = field_type.of_type while field_type.respond_to?(:of_type)
field_type
end
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index 39bd305d88a..9dc89b483b2 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -20,6 +20,13 @@ module KubernetesHelpers
WebMock.stub_request(:get, api_url + '/apis/serving.knative.dev/v1alpha1').to_return(kube_response(kube_v1alpha1_serving_knative_discovery_body))
end
+ def stub_kubeclient_service_pods(response = nil)
+ stub_kubeclient_discover(service.api_url)
+ pods_url = service.api_url + "/api/v1/pods"
+
+ WebMock.stub_request(:get, pods_url).to_return(response || kube_pods_response)
+ end
+
def stub_kubeclient_pods(response = nil)
stub_kubeclient_discover(service.api_url)
pods_url = service.api_url + "/api/v1/namespaces/#{service.actual_namespace}/pods"
@@ -58,6 +65,11 @@ module KubernetesHelpers
.to_return(status: [status, "Internal Server Error"])
end
+ def stub_kubeclient_get_service_account(api_url, name, namespace: 'default')
+ WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/serviceaccounts/#{name}")
+ .to_return(kube_response({}))
+ end
+
def stub_kubeclient_get_service_account_error(api_url, name, namespace: 'default', status: 404)
WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/serviceaccounts/#{name}")
.to_return(status: [status, "Internal Server Error"])
@@ -73,6 +85,11 @@ module KubernetesHelpers
.to_return(status: [500, "Internal Server Error"])
end
+ def stub_kubeclient_put_service_account(api_url, name, namespace: 'default')
+ WebMock.stub_request(:put, api_url + "/api/v1/namespaces/#{namespace}/serviceaccounts/#{name}")
+ .to_return(kube_response({}))
+ end
+
def stub_kubeclient_create_secret(api_url, namespace: 'default')
WebMock.stub_request(:post, api_url + "/api/v1/namespaces/#{namespace}/secrets")
.to_return(kube_response({}))
@@ -93,6 +110,11 @@ module KubernetesHelpers
.to_return(kube_response({}))
end
+ def stub_kubeclient_get_role_binding(api_url, name, namespace: 'default')
+ WebMock.stub_request(:get, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings/#{name}")
+ .to_return(kube_response({}))
+ end
+
def stub_kubeclient_get_role_binding_error(api_url, name, namespace: 'default', status: 404)
WebMock.stub_request(:get, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings/#{name}")
.to_return(status: [status, "Internal Server Error"])
@@ -103,6 +125,11 @@ module KubernetesHelpers
.to_return(kube_response({}))
end
+ def stub_kubeclient_put_role_binding(api_url, name, namespace: 'default')
+ WebMock.stub_request(:put, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings/#{name}")
+ .to_return(kube_response({}))
+ end
+
def stub_kubeclient_create_namespace(api_url)
WebMock.stub_request(:post, api_url + "/api/v1/namespaces")
.to_return(kube_response({}))
@@ -192,6 +219,13 @@ module KubernetesHelpers
}
end
+ def kube_knative_pods_body(name, namespace)
+ {
+ "kind" => "PodList",
+ "items" => [kube_knative_pod(name: name, namespace: namespace)]
+ }
+ end
+
def kube_knative_services_body(**options)
{
"kind" => "List",
@@ -222,6 +256,28 @@ module KubernetesHelpers
}
end
+ # Similar to a kube_pod, but should contain a running service
+ def kube_knative_pod(name: "kube-pod", namespace: "default", status: "Running")
+ {
+ "metadata" => {
+ "name" => name,
+ "namespace" => namespace,
+ "generate_name" => "generated-name-with-suffix",
+ "creationTimestamp" => "2016-11-25T19:55:19Z",
+ "labels" => {
+ "serving.knative.dev/service" => name
+ }
+ },
+ "spec" => {
+ "containers" => [
+ { "name" => "container-0" },
+ { "name" => "container-1" }
+ ]
+ },
+ "status" => { "phase" => status }
+ }
+ end
+
def kube_deployment(name: "kube-deployment", app: "valid-deployment-label", track: nil)
{
"metadata" => {
@@ -245,10 +301,10 @@ module KubernetesHelpers
def kube_service(name: "kubetest", namespace: "default", domain: "example.com")
{
"metadata" => {
- "creationTimestamp" => "2018-11-21T06:16:33Z",
- "name" => name,
- "namespace" => namespace,
- "selfLink" => "/apis/serving.knative.dev/v1alpha1/namespaces/#{namespace}/services/#{name}"
+ "creationTimestamp" => "2018-11-21T06:16:33Z",
+ "name" => name,
+ "namespace" => namespace,
+ "selfLink" => "/apis/serving.knative.dev/v1alpha1/namespaces/#{namespace}/services/#{name}"
},
"spec" => {
"generation" => 2
@@ -313,6 +369,6 @@ module KubernetesHelpers
end
def empty_deployment_rollout_status
- ::Gitlab::Kubernetes::RolloutStatus.from_deployments()
+ ::Gitlab::Kubernetes::RolloutStatus.from_deployments
end
end
diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb
index 87cfb6c04dc..4a0cf62a661 100644
--- a/spec/support/helpers/login_helpers.rb
+++ b/spec/support/helpers/login_helpers.rb
@@ -47,7 +47,7 @@ module LoginHelpers
end
def gitlab_sign_in_via(provider, user, uid, saml_response = nil)
- mock_auth_hash(provider, uid, user.email, saml_response)
+ mock_auth_hash_with_saml_xml(provider, uid, user.email, saml_response)
visit new_user_session_path
click_link provider
end
@@ -87,7 +87,12 @@ module LoginHelpers
click_link "oauth-login-#{provider}"
end
- def mock_auth_hash(provider, uid, email, saml_response = nil)
+ def mock_auth_hash_with_saml_xml(provider, uid, email, saml_response)
+ response_object = { document: saml_xml(saml_response) }
+ mock_auth_hash(provider, uid, email, response_object: response_object)
+ end
+
+ def mock_auth_hash(provider, uid, email, response_object: nil)
# The mock_auth configuration allows you to set per-provider (or default)
# authentication hashes to return during integration testing.
OmniAuth.config.mock_auth[provider.to_sym] = OmniAuth::AuthHash.new({
@@ -110,9 +115,7 @@ module LoginHelpers
image: 'mock_user_thumbnail_url'
}
},
- response_object: {
- document: saml_xml(saml_response)
- }
+ response_object: response_object
}
})
Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[provider.to_sym]
@@ -157,7 +160,7 @@ module LoginHelpers
env['omniauth.error.strategy'] = strategy
end
- def stub_omniauth_saml_config(messages, context: Rails.application)
+ def stub_omniauth_saml_config(messages, context: Rails.application)
set_devise_mapping(context: context)
routes = Rails.application.routes
routes.disable_clear_and_finalize = true
diff --git a/spec/support/helpers/migrations_helpers.rb b/spec/support/helpers/migrations_helpers.rb
index 5887c3eab74..cc1a28cb264 100644
--- a/spec/support/helpers/migrations_helpers.rb
+++ b/spec/support/helpers/migrations_helpers.rb
@@ -62,6 +62,22 @@ module MigrationsHelpers
klass.reset_column_information
end
+ # In some migration tests, we're using factories to create records,
+ # however those models might be depending on a schema version which
+ # doesn't have the columns we want in application_settings.
+ # In these cases, we'll need to use the fake application settings
+ # as if we have migrations pending
+ def use_fake_application_settings
+ # We stub this way because we can't stub on
+ # `current_application_settings` due to `method_missing` is
+ # depending on current_application_settings...
+ allow(ActiveRecord::Base.connection)
+ .to receive(:active?)
+ .and_return(false)
+
+ stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
+ end
+
def previous_migration
migrations.each_cons(2) do |previous, migration|
break previous if migration.name == described_class.name
diff --git a/spec/support/helpers/rake_helpers.rb b/spec/support/helpers/rake_helpers.rb
index acd9cce6a67..7d8d7750bf3 100644
--- a/spec/support/helpers/rake_helpers.rb
+++ b/spec/support/helpers/rake_helpers.rb
@@ -14,7 +14,7 @@ module RakeHelpers
end
def silence_progress_bar
- allow_any_instance_of(ProgressBar::Output).to receive(:stream).and_return(double().as_null_object)
+ allow_any_instance_of(ProgressBar::Output).to receive(:stream).and_return(double.as_null_object)
end
def main_object
diff --git a/spec/support/helpers/reactive_caching_helpers.rb b/spec/support/helpers/reactive_caching_helpers.rb
index a575aa99b79..b76b53db0b9 100644
--- a/spec/support/helpers/reactive_caching_helpers.rb
+++ b/spec/support/helpers/reactive_caching_helpers.rb
@@ -10,7 +10,7 @@ module ReactiveCachingHelpers
def stub_reactive_cache(subject = nil, data = nil, *qualifiers)
allow(ReactiveCachingWorker).to receive(:perform_async)
allow(ReactiveCachingWorker).to receive(:perform_in)
- write_reactive_cache(subject, data, *qualifiers) if data
+ write_reactive_cache(subject, data, *qualifiers) unless data.nil?
end
def synchronous_reactive_cache(subject)
diff --git a/spec/support/helpers/select2_helper.rb b/spec/support/helpers/select2_helper.rb
index 90618ba5b19..f4f0415985c 100644
--- a/spec/support/helpers/select2_helper.rb
+++ b/spec/support/helpers/select2_helper.rb
@@ -1,3 +1,5 @@
+require_relative 'wait_for_requests'
+
# Select2 ajax programmatic helper
# It allows you to select value from select2
#
@@ -11,9 +13,13 @@
#
module Select2Helper
+ include WaitForRequests
+
def select2(value, options = {})
raise ArgumentError, 'options must be a Hash' unless options.is_a?(Hash)
+ wait_for_requests unless options[:async]
+
selector = options.fetch(:from)
first(selector, visible: false)
diff --git a/spec/support/helpers/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb
index 2851cd9733c..ff21bbe28ca 100644
--- a/spec/support/helpers/stub_configuration.rb
+++ b/spec/support/helpers/stub_configuration.rb
@@ -56,6 +56,10 @@ module StubConfiguration
allow(Gitlab.config.lfs).to receive_messages(to_settings(messages))
end
+ def stub_external_diffs_setting(messages)
+ allow(Gitlab.config.external_diffs).to receive_messages(to_settings(messages))
+ end
+
def stub_artifacts_setting(messages)
allow(Gitlab.config.artifacts).to receive_messages(to_settings(messages))
end
diff --git a/spec/support/helpers/stub_env.rb b/spec/support/helpers/stub_env.rb
index 36b90fc68d6..1c2f474a015 100644
--- a/spec/support/helpers/stub_env.rb
+++ b/spec/support/helpers/stub_env.rb
@@ -18,7 +18,7 @@ module StubENV
allow(ENV).to receive(:[]).with(key).and_return(value)
allow(ENV).to receive(:key?).with(key).and_return(true)
allow(ENV).to receive(:fetch).with(key).and_return(value)
- allow(ENV).to receive(:fetch).with(key, anything()) do |_, default_val|
+ allow(ENV).to receive(:fetch).with(key, anything) do |_, default_val|
value || default_val
end
end
diff --git a/spec/support/helpers/stub_feature_flags.rb b/spec/support/helpers/stub_feature_flags.rb
index 4061a8d1bc9..48258692304 100644
--- a/spec/support/helpers/stub_feature_flags.rb
+++ b/spec/support/helpers/stub_feature_flags.rb
@@ -1,11 +1,30 @@
module StubFeatureFlags
# Stub Feature flags with `flag_name: true/false`
#
- # @param [Hash] features where key is feature name and value is boolean whether enabled or not
+ # @param [Hash] features where key is feature name and value is boolean whether enabled or not.
+ # Alternatively, you can specify Hash to enable the flag on a specific thing.
+ #
+ # Examples
+ # - `stub_feature_flags(ci_live_trace: false)` ... Disable `ci_live_trace`
+ # feature flag globally.
+ # - `stub_feature_flags(ci_live_trace: { enabled: false, thing: project })` ...
+ # Disable `ci_live_trace` feature flag on the specified project.
def stub_feature_flags(features)
- features.each do |feature_name, enabled|
- allow(Feature).to receive(:enabled?).with(feature_name, any_args) { enabled }
- allow(Feature).to receive(:enabled?).with(feature_name.to_s, any_args) { enabled }
+ features.each do |feature_name, option|
+ if option.is_a?(Hash)
+ enabled, thing = option.values_at(:enabled, :thing)
+ else
+ enabled = option
+ thing = nil
+ end
+
+ if thing
+ allow(Feature).to receive(:enabled?).with(feature_name, thing, any_args) { enabled }
+ allow(Feature).to receive(:enabled?).with(feature_name.to_s, thing, any_args) { enabled }
+ else
+ allow(Feature).to receive(:enabled?).with(feature_name, any_args) { enabled }
+ allow(Feature).to receive(:enabled?).with(feature_name.to_s, any_args) { enabled }
+ end
end
end
end
diff --git a/spec/support/helpers/stub_gitlab_calls.rb b/spec/support/helpers/stub_gitlab_calls.rb
index 2933f2c78dc..4cb3b18df85 100644
--- a/spec/support/helpers/stub_gitlab_calls.rb
+++ b/spec/support/helpers/stub_gitlab_calls.rb
@@ -36,31 +36,47 @@ module StubGitlabCalls
.to receive(:full_access_token).and_return('token')
end
- def stub_container_registry_tags(repository: :any, tags:)
+ def stub_container_registry_tags(repository: :any, tags: [], with_manifest: false)
repository = any_args if repository == :any
allow_any_instance_of(ContainerRegistry::Client)
.to receive(:repository_tags).with(repository)
.and_return({ 'tags' => tags })
- allow_any_instance_of(ContainerRegistry::Client)
- .to receive(:repository_manifest).with(repository, anything)
- .and_return(stub_container_registry_tag_manifest)
+ if with_manifest
+ tags.each do |tag|
+ allow_any_instance_of(ContainerRegistry::Client)
+ .to receive(:repository_tag_digest)
+ .with(repository, tag)
+ .and_return('sha256:4c8e63ca4cb663ce6c688cb06f1c3' \
+ '72b088dac5b6d7ad7d49cd620d85cf72a15')
+ end
- allow_any_instance_of(ContainerRegistry::Client)
- .to receive(:blob).with(repository, anything, 'application/octet-stream')
- .and_return(stub_container_registry_blob)
+ allow_any_instance_of(ContainerRegistry::Client)
+ .to receive(:repository_manifest).with(repository, anything)
+ .and_return(stub_container_registry_tag_manifest_content)
+
+ allow_any_instance_of(ContainerRegistry::Client)
+ .to receive(:blob).with(repository, anything, 'application/octet-stream')
+ .and_return(stub_container_registry_blob_content)
+ end
+ end
+
+ def stub_commonmark_sourcepos_disabled
+ allow_any_instance_of(Banzai::Filter::MarkdownEngines::CommonMark)
+ .to receive(:render_options)
+ .and_return(Banzai::Filter::MarkdownEngines::CommonMark::RENDER_OPTIONS)
end
private
- def stub_container_registry_tag_manifest
+ def stub_container_registry_tag_manifest_content
fixture_path = 'spec/fixtures/container_registry/tag_manifest.json'
JSON.parse(File.read(Rails.root + fixture_path))
end
- def stub_container_registry_blob
+ def stub_container_registry_blob_content
fixture_path = 'spec/fixtures/container_registry/config_blob.json'
File.read(Rails.root + fixture_path)
diff --git a/spec/support/helpers/stub_object_storage.rb b/spec/support/helpers/stub_object_storage.rb
index 58b5c6a6435..e0c50e533a6 100644
--- a/spec/support/helpers/stub_object_storage.rb
+++ b/spec/support/helpers/stub_object_storage.rb
@@ -42,6 +42,13 @@ module StubObjectStorage
**params)
end
+ def stub_external_diffs_object_storage(uploader = described_class, **params)
+ stub_object_storage_uploader(config: Gitlab.config.external_diffs.object_store,
+ uploader: uploader,
+ remote_directory: 'external_diffs',
+ **params)
+ end
+
def stub_lfs_object_storage(**params)
stub_object_storage_uploader(config: Gitlab.config.lfs.object_store,
uploader: LfsObjectUploader,
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index d52c40ff4f1..80a22134021 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -62,7 +62,9 @@ module TestEnv
'between-create-delete-modify-move' => '3f5f443',
'after-create-delete-modify-move' => 'ba3faa7',
'with-codeowners' => '219560e',
- 'submodule_inside_folder' => 'b491b92'
+ 'submodule_inside_folder' => 'b491b92',
+ 'png-lfs' => 'fe42f41',
+ 'sha-starting-with-large-number' => '8426165'
}.freeze
# gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily
@@ -145,12 +147,15 @@ module TestEnv
version: Gitlab::Shell.version_required,
task: 'gitlab:shell:install')
- create_fake_git_hooks
+ # gitlab-shell hooks don't work in our test environment because they try to make internal API calls
+ sabotage_gitlab_shell_hooks
end
- def create_fake_git_hooks
- # gitlab-shell hooks don't work in our test environment because they try to make internal API calls
- hooks_dir = File.join(Gitlab.config.gitlab_shell.path, 'hooks')
+ def sabotage_gitlab_shell_hooks
+ create_fake_git_hooks(Gitlab::Shell.new.hooks_path)
+ end
+
+ def create_fake_git_hooks(hooks_dir)
%w[pre-receive post-receive update].each do |hook|
File.open(File.join(hooks_dir, hook), 'w', 0755) { |f| f.puts '#!/bin/sh' }
end
@@ -159,13 +164,15 @@ module TestEnv
def setup_gitaly
socket_path = Gitlab::GitalyClient.address('default').sub(/\Aunix:/, '')
gitaly_dir = File.dirname(socket_path)
+ install_gitaly_args = [gitaly_dir, repos_path, gitaly_url].compact.join(',')
component_timed_setup('Gitaly',
install_dir: gitaly_dir,
version: Gitlab::GitalyClient.expected_server_version,
- task: "gitlab:gitaly:install[#{gitaly_dir},#{repos_path}]") do
+ task: "gitlab:gitaly:install[#{install_gitaly_args}]") do
Gitlab::SetupHelper.create_gitaly_configuration(gitaly_dir, { 'default' => repos_path }, force: true)
+ create_fake_git_hooks(File.join(gitaly_dir, 'ruby/git-hooks'))
start_gitaly(gitaly_dir)
end
end
@@ -214,6 +221,10 @@ module TestEnv
# The process can already be gone if the test run was INTerrupted.
end
+ def gitaly_url
+ ENV.fetch('GITALY_REPO_URL', nil)
+ end
+
def setup_factory_repo
setup_repo(factory_repo_path, factory_repo_path_bare, factory_repo_name,
BRANCH_SHA)
diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb
index ac320934f5a..388b88f0331 100644
--- a/spec/support/import_export/export_file_helper.rb
+++ b/spec/support/import_export/export_file_helper.rb
@@ -91,7 +91,7 @@ module ExportFileHelper
loop do
object_with_parent = deep_find_with_parent(sensitive_word, project_hash)
- return nil unless object_with_parent && object_with_parent.object
+ return unless object_with_parent && object_with_parent.object
if is_safe_hash?(object_with_parent.parent, sensitive_word)
# It's in the safe list, remove hash and keep looking
diff --git a/spec/support/matchers/graphql_matchers.rb b/spec/support/matchers/graphql_matchers.rb
index 7be84838e00..7894484f590 100644
--- a/spec/support/matchers/graphql_matchers.rb
+++ b/spec/support/matchers/graphql_matchers.rb
@@ -1,8 +1,6 @@
RSpec::Matchers.define :require_graphql_authorizations do |*expected|
match do |field|
- field_definition = field.metadata[:type_class]
- expect(field_definition).to respond_to(:required_permissions)
- expect(field_definition.required_permissions).to contain_exactly(*expected)
+ expect(field.metadata[:authorize]).to eq(*expected)
end
end
diff --git a/spec/support/matchers/not_changed_matcher.rb b/spec/support/matchers/not_changed_matcher.rb
new file mode 100644
index 00000000000..8ef4694982d
--- /dev/null
+++ b/spec/support/matchers/not_changed_matcher.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define_negated_matcher :not_change, :change
diff --git a/spec/support/migrations_helpers/cluster_helpers.rb b/spec/support/migrations_helpers/cluster_helpers.rb
new file mode 100644
index 00000000000..b54af15c29e
--- /dev/null
+++ b/spec/support/migrations_helpers/cluster_helpers.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module MigrationHelpers
+ module ClusterHelpers
+ # Creates a list of cluster projects.
+ def create_cluster_project_list(quantity)
+ group = namespaces_table.create(name: 'gitlab-org', path: 'gitlab-org')
+
+ quantity.times do |id|
+ create_cluster_project(group, id)
+ end
+ end
+
+ # Creates dependencies for a cluster project:
+ # - Group
+ # - Project
+ # - Cluster
+ # - Project - cluster relationship
+ # - GCP provider
+ # - Platform Kubernetes
+ def create_cluster_project(group, id)
+ project = projects_table.create!(
+ name: "project-#{id}",
+ path: "project-#{id}",
+ namespace_id: group.id
+ )
+
+ cluster = clusters_table.create(
+ name: 'test-cluster',
+ cluster_type: 3,
+ provider_type: :gcp,
+ platform_type: :kubernetes
+ )
+
+ cluster_projects_table.create(project_id: project.id, cluster_id: cluster.id)
+
+ provider_gcp_table.create!(
+ gcp_project_id: "test-gcp-project-#{id}",
+ endpoint: '111.111.111.111',
+ cluster_id: cluster.id,
+ status: 3,
+ num_nodes: 1,
+ zone: 'us-central1-a'
+ )
+
+ platform_kubernetes_table.create(
+ cluster_id: cluster.id,
+ api_url: 'https://kubernetes.example.com',
+ encrypted_token: 'a' * 40,
+ encrypted_token_iv: 'a' * 40
+ )
+ end
+
+ # Creates a Kubernetes namespace for a list of clusters
+ def create_kubernetes_namespace(clusters)
+ clusters.each do |cluster|
+ cluster_project = cluster_projects_table.find_by(cluster_id: cluster.id)
+ project = projects_table.find(cluster_project.project_id)
+ namespace = "#{project.path}-#{project.id}"
+
+ cluster_kubernetes_namespaces_table.create(
+ cluster_project_id: cluster_project.id,
+ cluster_id: cluster.id,
+ project_id: cluster_project.project_id,
+ namespace: namespace,
+ service_account_name: "#{namespace}-service-account"
+ )
+ end
+ end
+ end
+end
diff --git a/spec/support/pg_stat_activity.rb b/spec/support/pg_stat_activity.rb
new file mode 100644
index 00000000000..f93fba08a19
--- /dev/null
+++ b/spec/support/pg_stat_activity.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+RSpec.configure do |config|
+ config.before do
+ if Gitlab::Database.postgresql? && ENV['PG_STAT_WARNING_THRESHOLD']
+ warning_threshold = ENV['PG_STAT_WARNING_THRESHOLD'].to_i
+ results = ActiveRecord::Base.connection.execute('SELECT * FROM pg_stat_activity')
+ ntuples = results.ntuples
+
+ warn("pg_stat_activity count: #{ntuples}")
+
+ if ntuples > warning_threshold
+ results.each do |result|
+ warn result.inspect
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/redis/redis_shared_examples.rb b/spec/support/redis/redis_shared_examples.rb
index e650a176041..a8b00004fe7 100644
--- a/spec/support/redis/redis_shared_examples.rb
+++ b/spec/support/redis/redis_shared_examples.rb
@@ -1,7 +1,7 @@
RSpec.shared_examples "redis_shared_examples" do
include StubENV
- let(:test_redis_url) { "redis://redishost:#{redis_port}"}
+ let(:test_redis_url) { "redis://redishost:#{redis_port}"}
before do
stub_env(environment_config_file_name, Rails.root.join(config_file_name))
@@ -76,7 +76,7 @@ RSpec.shared_examples "redis_shared_examples" do
context 'when yml file with env variable' do
let(:config_file_name) { config_with_environment_variable_inside }
- before do
+ before do
stub_env(config_env_variable_url, test_redis_url)
end
diff --git a/spec/support/shared_contexts/email_shared_blocks.rb b/spec/support/shared_contexts/email_shared_context.rb
index 9d806fc524d..9d806fc524d 100644
--- a/spec/support/shared_contexts/email_shared_blocks.rb
+++ b/spec/support/shared_contexts/email_shared_context.rb
diff --git a/spec/support/shared_contexts/services_shared_context.rb b/spec/support/shared_contexts/services_shared_context.rb
index 23f9b46ae0c..d92e8318fa0 100644
--- a/spec/support/shared_contexts/services_shared_context.rb
+++ b/spec/support/shared_contexts/services_shared_context.rb
@@ -19,7 +19,7 @@ Service.available_services_names.each do |service|
elsif service == 'irker' && k == :server_port
hash.merge!(k => 1234)
elsif service == 'jira' && k == :jira_issue_transition_id
- hash.merge!(k => 1234)
+ hash.merge!(k => '1,2,3')
else
hash.merge!(k => "someword")
end
diff --git a/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb b/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb
index dbdca99b5aa..0acc9e2a836 100644
--- a/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb
@@ -1,8 +1,16 @@
shared_examples 'issuable notes filter' do
+ let(:params) do
+ if issuable_parent.is_a?(Project)
+ { namespace_id: issuable_parent.namespace, project_id: issuable_parent, id: issuable.iid }
+ else
+ { group_id: issuable_parent, id: issuable.to_param }
+ end
+ end
+
it 'sets discussion filter' do
notes_filter = UserPreference::NOTES_FILTERS[:only_comments]
- get :discussions, params: { namespace_id: project.namespace, project_id: project, id: issuable.iid, notes_filter: notes_filter }
+ get :discussions, params: params.merge(notes_filter: notes_filter)
expect(user.reload.notes_filter_for(issuable)).to eq(notes_filter)
expect(UserPreference.count).to eq(1)
@@ -13,7 +21,7 @@ shared_examples 'issuable notes filter' do
expect_any_instance_of(issuable.class).to receive(:expire_note_etag_cache)
- get :discussions, params: { namespace_id: project.namespace, project_id: project, id: issuable.iid, notes_filter: notes_filter }
+ get :discussions, params: params.merge(notes_filter: notes_filter)
end
it 'does not expires notes e-tag cache for issuable if filter did not change' do
@@ -22,14 +30,14 @@ shared_examples 'issuable notes filter' do
expect_any_instance_of(issuable.class).not_to receive(:expire_note_etag_cache)
- get :discussions, params: { namespace_id: project.namespace, project_id: project, id: issuable.iid, notes_filter: notes_filter }
+ get :discussions, params: params.merge(notes_filter: notes_filter)
end
it 'does not set notes filter when database is in read only mode' do
allow(Gitlab::Database).to receive(:read_only?).and_return(true)
notes_filter = UserPreference::NOTES_FILTERS[:only_comments]
- get :discussions, params: { namespace_id: project.namespace, project_id: project, id: issuable.iid, notes_filter: notes_filter }
+ get :discussions, params: params.merge(notes_filter: notes_filter)
expect(user.reload.notes_filter_for(issuable)).to eq(0)
end
@@ -37,7 +45,7 @@ shared_examples 'issuable notes filter' do
it 'returns only user comments' do
user.set_notes_filter(UserPreference::NOTES_FILTERS[:only_comments], issuable)
- get :discussions, params: { namespace_id: project.namespace, project_id: project, id: issuable.iid }
+ get :discussions, params: params
discussions = JSON.parse(response.body)
expect(discussions.count).to eq(1)
@@ -47,7 +55,7 @@ shared_examples 'issuable notes filter' do
it 'returns only activity notes' do
user.set_notes_filter(UserPreference::NOTES_FILTERS[:only_activity], issuable)
- get :discussions, params: { namespace_id: project.namespace, project_id: project, id: issuable.iid }
+ get :discussions, params: params
discussions = JSON.parse(response.body)
expect(discussions.count).to eq(1)
@@ -60,7 +68,7 @@ shared_examples 'issuable notes filter' do
expect(ResourceEvents::MergeIntoNotesService).not_to receive(:new)
- get :discussions, params: { namespace_id: project.namespace, project_id: project, id: issuable.iid }
+ get :discussions, params: params
end
end
end
diff --git a/spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb b/spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb
index a3d31e26498..982e0317f7f 100644
--- a/spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb
+++ b/spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb
@@ -28,7 +28,13 @@ shared_examples 'repository lfs file load' do
end
it 'serves the file' do
- expect(controller).to receive(:send_file).with("#{LfsObjectUploader.root}/91/ef/f75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897", filename: filename, disposition: 'attachment')
+ # Notice the filename= is omitted from the disposition; this is because
+ # Rails 5 will append this header in send_file
+ expect(controller).to receive(:send_file)
+ .with(
+ "#{LfsObjectUploader.root}/91/ef/f75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897",
+ filename: filename,
+ disposition: %Q(attachment; filename*=UTF-8''#{filename}))
subject
@@ -56,7 +62,7 @@ shared_examples 'repository lfs file load' do
file_uri = URI.parse(response.location)
params = CGI.parse(file_uri.query)
- expect(params["response-content-disposition"].first).to eq "attachment;filename=\"#{filename}\""
+ expect(params["response-content-disposition"].first).to eq(%q(attachment; filename="lfs_object.iso"; filename*=UTF-8''lfs_object.iso))
end
end
end
diff --git a/spec/support/shared_examples/controllers/set_sort_order_from_user_preference_shared_examples.rb b/spec/support/shared_examples/controllers/set_sort_order_from_user_preference_shared_examples.rb
index d86838719d4..98ab04c5636 100644
--- a/spec/support/shared_examples/controllers/set_sort_order_from_user_preference_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/set_sort_order_from_user_preference_shared_examples.rb
@@ -2,18 +2,12 @@ shared_examples 'set sort order from user preference' do
describe '#set_sort_order_from_user_preference' do
# There is no issuable_sorting_field defined in any CE controllers yet,
# however any other field present in user_preferences table can be used for testing.
- let(:sorting_field) { :issue_notes_filter }
- let(:sorting_param) { 'any' }
-
- before do
- allow(controller).to receive(:issuable_sorting_field).and_return(sorting_field)
- end
context 'when database is in read-only mode' do
it 'it does not update user preference' do
allow(Gitlab::Database).to receive(:read_only?).and_return(true)
- expect_any_instance_of(UserPreference).not_to receive(:update_attribute).with(sorting_field, sorting_param)
+ expect_any_instance_of(UserPreference).not_to receive(:update).with({ controller.send(:issuable_sorting_field) => sorting_param })
get :index, params: { namespace_id: project.namespace, project_id: project, sort: sorting_param }
end
@@ -23,7 +17,7 @@ shared_examples 'set sort order from user preference' do
it 'updates user preference' do
allow(Gitlab::Database).to receive(:read_only?).and_return(false)
- expect_any_instance_of(UserPreference).to receive(:update_attribute).with(sorting_field, sorting_param)
+ expect_any_instance_of(UserPreference).to receive(:update).with({ controller.send(:issuable_sorting_field) => sorting_param })
get :index, params: { namespace_id: project.namespace, project_id: project, sort: sorting_param }
end
diff --git a/spec/support/shared_examples/dirty_submit_form_shared_examples.rb b/spec/support/shared_examples/dirty_submit_form_shared_examples.rb
index ba363593120..52a2ee49495 100644
--- a/spec/support/shared_examples/dirty_submit_form_shared_examples.rb
+++ b/spec/support/shared_examples/dirty_submit_form_shared_examples.rb
@@ -1,24 +1,36 @@
shared_examples 'dirty submit form' do |selector_args|
selectors = selector_args.is_a?(Array) ? selector_args : [selector_args]
+ def expect_disabled_state(form, submit, is_disabled = true)
+ disabled_selector = is_disabled == true ? '[disabled]' : ':not([disabled])'
+
+ form.find(".js-dirty-submit#{disabled_selector}", match: :first)
+
+ expect(submit.disabled?).to be is_disabled
+ end
+
selectors.each do |selector|
- it "disables #{selector[:form]} submit until there are changes", :js do
+ it "disables #{selector[:form]} submit until there are changes on #{selector[:input]}", :js do
form = find(selector[:form])
submit = form.first('.js-dirty-submit')
input = form.first(selector[:input])
+ is_radio = input[:type] == 'radio'
+ is_checkbox = input[:type] == 'checkbox'
+ is_checkable = is_radio || is_checkbox
original_value = input.value
+ original_checkable = form.find("input[name='#{input[:name]}'][checked]") if is_radio
+ original_checkable = input if is_checkbox
expect(submit.disabled?).to be true
+ expect(input.checked?).to be false
- input.set("#{original_value} changes")
+ is_checkable ? input.click : input.set("#{original_value} changes")
- form.find('.js-dirty-submit:not([disabled])', match: :first)
- expect(submit.disabled?).to be false
+ expect_disabled_state(form, submit, false)
- input.set(original_value)
+ is_checkable ? original_checkable.click : input.set(original_value)
- form.find('.js-dirty-submit[disabled]', match: :first)
- expect(submit.disabled?).to be true
+ expect_disabled_state(form, submit)
end
end
end
diff --git a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
index a096627ee62..eef0327c9a6 100644
--- a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
@@ -129,12 +129,12 @@ RSpec.shared_examples 'an editable merge request' do
expect(merge_request.merge_params['force_remove_source_branch']).to be_truthy
visit edit_project_merge_request_path(target_project, merge_request)
- uncheck 'Remove source branch when merge request is accepted'
+ uncheck 'Delete source branch when merge request is accepted'
click_button 'Save changes'
expect(page).to have_unchecked_field 'remove-source-branch-input'
- expect(page).to have_content 'Remove source branch'
+ expect(page).to have_content 'Delete source branch'
end
end
end
diff --git a/spec/support/shared_examples/graphql/issuable_state_shared_examples.rb b/spec/support/shared_examples/graphql/issuable_state_shared_examples.rb
new file mode 100644
index 00000000000..713f0a879c1
--- /dev/null
+++ b/spec/support/shared_examples/graphql/issuable_state_shared_examples.rb
@@ -0,0 +1,5 @@
+RSpec.shared_examples 'issuable state' do
+ it 'exposes all the existing issuable states' do
+ expect(described_class.values.keys).to include(*%w[opened closed locked])
+ end
+end
diff --git a/spec/support/shared_examples/issuable_shared_examples.rb b/spec/support/shared_examples/issuable_shared_examples.rb
index 42f3b4db23c..d97b21f71cd 100644
--- a/spec/support/shared_examples/issuable_shared_examples.rb
+++ b/spec/support/shared_examples/issuable_shared_examples.rb
@@ -31,8 +31,81 @@ shared_examples 'system notes for milestones' do
context 'project milestones' do
it 'creates a system note' do
expect do
- update_issuable(milestone: create(:milestone))
+ update_issuable(milestone: create(:milestone, project: project))
end.to change { Note.system.count }.by(1)
end
end
end
+
+shared_examples 'updating a single task' do
+ def update_issuable(opts)
+ issuable = try(:issue) || try(:merge_request)
+ described_class.new(project, user, opts).execute(issuable)
+ end
+
+ before do
+ update_issuable(description: "- [ ] Task 1\n- [ ] Task 2")
+ end
+
+ context 'when a task is marked as completed' do
+ before do
+ update_issuable(update_task: { index: 1, checked: true, line_source: '- [ ] Task 1', line_number: 1 })
+ end
+
+ it 'creates system note about task status change' do
+ note1 = find_note('marked the task **Task 1** as completed')
+
+ expect(note1).not_to be_nil
+
+ description_notes = find_notes('description')
+ expect(description_notes.length).to eq(1)
+ end
+ end
+
+ context 'when a task is marked as incomplete' do
+ before do
+ update_issuable(description: "- [x] Task 1\n- [X] Task 2")
+ update_issuable(update_task: { index: 2, checked: false, line_source: '- [X] Task 2', line_number: 2 })
+ end
+
+ it 'creates system note about task status change' do
+ note1 = find_note('marked the task **Task 2** as incomplete')
+
+ expect(note1).not_to be_nil
+
+ description_notes = find_notes('description')
+ expect(description_notes.length).to eq(1)
+ end
+ end
+
+ context 'when the task position has been modified' do
+ before do
+ update_issuable(description: "- [ ] Task 1\n- [ ] Task 3\n- [ ] Task 2")
+ end
+
+ it 'raises an exception' do
+ expect(Note.count).to eq(2)
+ expect do
+ update_issuable(update_task: { index: 2, checked: true, line_source: '- [ ] Task 2', line_number: 2 })
+ end.to raise_error(ActiveRecord::StaleObjectError)
+ expect(Note.count).to eq(2)
+ end
+ end
+
+ context 'when the content changes but not task line number' do
+ before do
+ update_issuable(description: "Paragraph\n\n- [ ] Task 1\n- [x] Task 2")
+ update_issuable(description: "Paragraph with more words\n\n- [ ] Task 1\n- [x] Task 2")
+ update_issuable(update_task: { index: 2, checked: false, line_source: '- [x] Task 2', line_number: 4 })
+ end
+
+ it 'creates system note about task status change' do
+ note1 = find_note('marked the task **Task 2** as incomplete')
+
+ expect(note1).not_to be_nil
+
+ description_notes = find_notes('description')
+ expect(description_notes.length).to eq(2)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/background_migration/backfill_project_repositories_examples.rb b/spec/support/shared_examples/lib/gitlab/background_migration/backfill_project_repositories_examples.rb
index 1f688c0f9d3..dcf7c1a90c2 100644
--- a/spec/support/shared_examples/lib/gitlab/background_migration/backfill_project_repositories_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/background_migration/backfill_project_repositories_examples.rb
@@ -32,11 +32,13 @@ shared_examples 'backfill migration for project repositories' do |storage|
it 'inserts rows in a single query' do
projects.create!(name: 'foo', path: 'foo', namespace_id: group.id, storage_version: storage_version, repository_storage: shard.name)
+ group2 = namespaces.create!(name: 'gro', path: 'gro')
control_count = ActiveRecord::QueryRecorder.new { described_class.new.perform(1, projects.last.id) }
projects.create!(name: 'bar', path: 'bar', namespace_id: group.id, storage_version: storage_version, repository_storage: shard.name)
- projects.create!(name: 'zoo', path: 'zoo', namespace_id: group.id, storage_version: storage_version, repository_storage: shard.name)
+ projects.create!(name: 'top', path: 'top', namespace_id: group.id, storage_version: storage_version, repository_storage: shard.name)
+ projects.create!(name: 'zoo', path: 'zoo', namespace_id: group2.id, storage_version: storage_version, repository_storage: shard.name)
expect { described_class.new.perform(1, projects.last.id) }.not_to exceed_query_limit(control_count)
end
diff --git a/spec/support/shared_examples/malicious_regexp_shared_examples.rb b/spec/support/shared_examples/malicious_regexp_shared_examples.rb
index 65026f1d7c0..db69b75c0c8 100644
--- a/spec/support/shared_examples/malicious_regexp_shared_examples.rb
+++ b/spec/support/shared_examples/malicious_regexp_shared_examples.rb
@@ -1,7 +1,7 @@
require 'timeout'
shared_examples 'malicious regexp' do
- let(:malicious_text) { 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!' }
+ let(:malicious_text) { 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!' }
let(:malicious_regexp) { '(?i)^(([a-z])+.)+[A-Z]([a-z])+$' }
it 'takes under a second' do
diff --git a/spec/support/shared_examples/mentionable_shared_examples.rb b/spec/support/shared_examples/mentionable_shared_examples.rb
index 1685decbe94..1226841f24c 100644
--- a/spec/support/shared_examples/mentionable_shared_examples.rb
+++ b/spec/support/shared_examples/mentionable_shared_examples.rb
@@ -8,8 +8,8 @@ shared_context 'mentionable context' do
let(:project) { subject.project }
let(:author) { subject.author }
- let(:mentioned_issue) { create(:issue, project: project) }
- let!(:mentioned_mr) { create(:merge_request, source_project: project) }
+ let(:mentioned_issue) { create(:issue, project: project) }
+ let!(:mentioned_mr) { create(:merge_request, source_project: project) }
let(:mentioned_commit) { project.commit("HEAD~1") }
let(:ext_proj) { create(:project, :public, :repository) }
diff --git a/spec/support/shared_examples/models/cluster_application_initial_status.rb b/spec/support/shared_examples/models/cluster_application_initial_status.rb
new file mode 100644
index 00000000000..9775d87953c
--- /dev/null
+++ b/spec/support/shared_examples/models/cluster_application_initial_status.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+shared_examples 'cluster application initial status specs' do
+ describe '#status' do
+ let(:cluster) { create(:cluster, :provided_by_gcp) }
+
+ subject { described_class.new(cluster: cluster) }
+
+ context 'when application helm is scheduled' do
+ before do
+ create(:clusters_applications_helm, :scheduled, cluster: cluster)
+ end
+
+ it 'defaults to :not_installable' do
+ expect(subject.status_name).to be(:not_installable)
+ end
+ end
+
+ context 'when application is scheduled' do
+ before do
+ create(:clusters_applications_helm, :installed, cluster: cluster)
+ end
+
+ it 'sets a default status' do
+ expect(subject.status_name).to be(:installable)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
index c391cc48f4e..b8c19cab0c4 100644
--- a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
@@ -7,26 +7,19 @@ shared_examples 'cluster application status specs' do |application_name|
it 'sets a default status' do
expect(subject.status_name).to be(:not_installable)
end
+ end
- context 'when application helm is scheduled' do
- before do
- create(:clusters_applications_helm, :scheduled, cluster: cluster)
- end
-
- it 'defaults to :not_installable' do
- expect(subject.status_name).to be(:not_installable)
- end
- end
+ describe '.available' do
+ subject { described_class.available }
- context 'when application is scheduled' do
- before do
- create(:clusters_applications_helm, :installed, cluster: cluster)
- end
+ let!(:installed_cluster) { create(application_name, :installed) }
+ let!(:updated_cluster) { create(application_name, :updated) }
- it 'sets a default status' do
- expect(subject.status_name).to be(:installable)
- end
+ before do
+ create(application_name, :errored)
end
+
+ it { is_expected.to contain_exactly(installed_cluster, updated_cluster) }
end
describe 'status state machine' do
@@ -58,25 +51,45 @@ shared_examples 'cluster application status specs' do |application_name|
expect(subject.cluster.application_helm.version).to eq(Gitlab::Kubernetes::Helm::HELM_VERSION)
end
- end
- describe '#make_updated' do
- subject { create(application_name, :updating) }
+ it 'sets the correct version of the application' do
+ subject.update!(version: '0.0.0')
+
+ subject.make_installed!
- it 'is updated' do
- subject.make_updated!
+ subject.reload
- expect(subject).to be_updated
+ expect(subject.version).to eq(subject.class.const_get(:VERSION))
end
- it 'updates helm version' do
- subject.cluster.application_helm.update!(version: '1.2.3')
+ context 'application is updating' do
+ subject { create(application_name, :updating) }
- subject.make_updated!
+ it 'is updated' do
+ subject.make_installed!
- subject.cluster.application_helm.reload
+ expect(subject).to be_updated
+ end
- expect(subject.cluster.application_helm.version).to eq(Gitlab::Kubernetes::Helm::HELM_VERSION)
+ it 'updates helm version' do
+ subject.cluster.application_helm.update!(version: '1.2.3')
+
+ subject.make_installed!
+
+ subject.cluster.application_helm.reload
+
+ expect(subject.cluster.application_helm.version).to eq(Gitlab::Kubernetes::Helm::HELM_VERSION)
+ end
+
+ it 'updates the version of the application' do
+ subject.update!(version: '0.0.0')
+
+ subject.make_installed!
+
+ subject.reload
+
+ expect(subject.version).to eq(subject.class.const_get(:VERSION))
+ end
end
end
@@ -90,6 +103,17 @@ shared_examples 'cluster application status specs' do |application_name|
expect(subject).to be_errored
expect(subject.status_reason).to eq(reason)
end
+
+ context 'application is updating' do
+ subject { create(application_name, :updating) }
+
+ it 'is update_errored' do
+ subject.make_errored(reason)
+
+ expect(subject).to be_update_errored
+ expect(subject.status_reason).to eq(reason)
+ end
+ end
end
describe '#make_scheduled' do
@@ -112,6 +136,18 @@ shared_examples 'cluster application status specs' do |application_name|
expect(subject.status_reason).to be_nil
end
end
+
+ describe 'when was updated_errored' do
+ subject { create(application_name, :update_errored) }
+
+ it 'clears #status_reason' do
+ expect(subject.status_reason).not_to be_nil
+
+ subject.make_scheduled!
+
+ expect(subject.status_reason).to be_nil
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb
new file mode 100644
index 00000000000..181b102e685
--- /dev/null
+++ b/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+shared_examples 'cluster application version specs' do |application_name|
+ describe 'update_available?' do
+ let(:version) { '0.0.0' }
+
+ subject { create(application_name, :installed, version: version).update_available? }
+
+ context 'version is not the same as VERSION' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'version is the same as VERSION' do
+ let(:application) { build(application_name) }
+ let(:version) { application.class.const_get(:VERSION) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/with_uploads_shared_examples.rb b/spec/support/shared_examples/models/with_uploads_shared_examples.rb
index 1d11b855459..43033a2d256 100644
--- a/spec/support/shared_examples/models/with_uploads_shared_examples.rb
+++ b/spec/support/shared_examples/models/with_uploads_shared_examples.rb
@@ -44,26 +44,6 @@ shared_examples_for 'model with uploads' do |supports_fileuploads|
model_object.destroy
end
end
-
- describe 'destroy strategy depending on feature flag' do
- let!(:upload) { create(:upload, uploader: FileUploader, model: model_object) }
-
- it 'does not destroy uploads by default' do
- expect(model_object).to receive(:delete_uploads)
- expect(model_object).not_to receive(:destroy_uploads)
-
- model_object.destroy
- end
-
- it 'uses before destroy callback if feature flag is disabled' do
- stub_feature_flags(fast_destroy_uploads: false)
-
- expect(model_object).to receive(:destroy_uploads)
- expect(model_object).not_to receive(:delete_uploads)
-
- model_object.destroy
- end
- end
end
end
end
diff --git a/spec/support/shared_examples/notify_shared_examples.rb b/spec/support/shared_examples/notify_shared_examples.rb
index a38354060cf..4fff1c4e228 100644
--- a/spec/support/shared_examples/notify_shared_examples.rb
+++ b/spec/support/shared_examples/notify_shared_examples.rb
@@ -252,3 +252,31 @@ shared_examples 'a note email' do
end
end
end
+
+shared_examples 'appearance header and footer enabled' do
+ it "contains header and footer" do
+ create :appearance, header_message: "Foo", footer_message: "Bar", email_header_and_footer_enabled: true
+
+ aggregate_failures do
+ expect(subject.html_part).to have_body_text("<div class=\"header-message\" style=\"\"><p>Foo</p></div>")
+ expect(subject.html_part).to have_body_text("<div class=\"footer-message\" style=\"\"><p>Bar</p></div>")
+
+ expect(subject.text_part).to have_body_text(/^Foo/)
+ expect(subject.text_part).to have_body_text(/Bar$/)
+ end
+ end
+end
+
+shared_examples 'appearance header and footer not enabled' do
+ it "does not contain header and footer" do
+ create :appearance, header_message: "Foo", footer_message: "Bar", email_header_and_footer_enabled: false
+
+ aggregate_failures do
+ expect(subject.html_part).not_to have_body_text("<div class=\"header-message\" style=\"\"><p>Foo</p></div>")
+ expect(subject.html_part).not_to have_body_text("<div class=\"footer-message\" style=\"\"><p>Bar</p></div>")
+
+ expect(subject.text_part).not_to have_body_text(/^Foo/)
+ expect(subject.text_part).not_to have_body_text(/Bar$/)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/policies/clusterable_shared_examples.rb b/spec/support/shared_examples/policies/clusterable_shared_examples.rb
new file mode 100644
index 00000000000..d99f94c76c3
--- /dev/null
+++ b/spec/support/shared_examples/policies/clusterable_shared_examples.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+shared_examples 'clusterable policies' do
+ describe '#add_cluster?' do
+ let(:current_user) { create(:user) }
+
+ subject { described_class.new(current_user, clusterable) }
+
+ context 'with a developer' do
+ before do
+ clusterable.add_developer(current_user)
+ end
+
+ it { expect_disallowed(:add_cluster) }
+ end
+
+ context 'with a maintainer' do
+ before do
+ clusterable.add_maintainer(current_user)
+ end
+
+ context 'with no clusters' do
+ it { expect_allowed(:add_cluster) }
+ end
+
+ context 'with an existing cluster' do
+ before do
+ cluster
+ end
+
+ it { expect_disallowed(:add_cluster) }
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/project_list_shared_examples.rb b/spec/support/shared_examples/project_list_shared_examples.rb
new file mode 100644
index 00000000000..675d489fcab
--- /dev/null
+++ b/spec/support/shared_examples/project_list_shared_examples.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+shared_examples 'shows public projects' do
+ it 'shows projects' do
+ expect(page).to have_content(public_project.title)
+ expect(page).not_to have_content(internal_project.title)
+ expect(page).not_to have_content(private_project.title)
+ expect(page).not_to have_content(archived_project.title)
+ end
+end
+
+shared_examples 'shows public and internal projects' do
+ it 'shows projects' do
+ expect(page).to have_content(public_project.title)
+ expect(page).to have_content(internal_project.title)
+ expect(page).not_to have_content(private_project.title)
+ expect(page).not_to have_content(archived_project.title)
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/discussions.rb b/spec/support/shared_examples/requests/api/discussions.rb
index e44da4faa5a..eff8e401bad 100644
--- a/spec/support/shared_examples/requests/api/discussions.rb
+++ b/spec/support/shared_examples/requests/api/discussions.rb
@@ -86,6 +86,37 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
expect(response).to have_gitlab_http_status(404)
end
end
+
+ context 'when a project is public with private repo access' do
+ let!(:parent) { create(:project, :public, :repository, :repository_private, :snippets_private) }
+ let!(:user_without_access) { create(:user) }
+
+ context 'when user is not a team member of private repo' do
+ before do
+ project.team.truncate
+ end
+
+ context "creating a new note" do
+ before do
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user_without_access), params: { body: 'hi!' }
+ end
+
+ it 'raises 404 error' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context "fetching a discussion" do
+ before do
+ get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions/#{note.discussion_id}", user_without_access)
+ end
+
+ it 'raises 404 error' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+ end
end
describe "POST /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions/:discussion_id/notes" do
diff --git a/spec/support/shared_examples/requests/api/merge_requests_list.rb b/spec/support/shared_examples/requests/api/merge_requests_list.rb
index 453f42251c8..32e3b81c3c5 100644
--- a/spec/support/shared_examples/requests/api/merge_requests_list.rb
+++ b/spec/support/shared_examples/requests/api/merge_requests_list.rb
@@ -186,6 +186,37 @@ shared_examples 'merge requests list' do
expect(json_response.length).to eq(0)
end
+ it 'returns an array of labeled merge requests where all labels match' do
+ path = endpoint_path + "?labels[]=#{label.title}&labels[]=#{label2.title}"
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['labels']).to eq([label2.title, label.title])
+ end
+
+ it 'returns an array of merge requests with any label when filtering by any label' do
+ get api(endpoint_path, user), params: { labels: [" #{label.title} ", " #{label2.title} "] }
+
+ expect_paginated_array_response
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['labels']).to eq([label2.title, label.title])
+ expect(json_response.first['id']).to eq(merge_request.id)
+ end
+
+ it 'returns an array of merge requests with any label when filtering by any label' do
+ get api(endpoint_path, user), params: { labels: ["#{label.title} , #{label2.title}"] }
+
+ expect_paginated_array_response
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['labels']).to eq([label2.title, label.title])
+ expect(json_response.first['id']).to eq(merge_request.id)
+ end
+
it 'returns an array of merge requests with any label when filtering by any label' do
get api(endpoint_path, user), params: { labels: IssuesFinder::FILTER_ANY }
@@ -257,6 +288,38 @@ shared_examples 'merge requests list' do
expect(response_dates).to eq(response_dates.sort.reverse)
end
+ context '2 merge requests with equal created_at' do
+ let!(:closed_mr2) do
+ create :merge_request,
+ state: 'closed',
+ milestone: milestone1,
+ author: user,
+ assignee: user,
+ source_project: project,
+ target_project: project,
+ title: "Test",
+ created_at: @mr_earlier.created_at
+ end
+
+ it 'page breaks first page correctly' do
+ get api("#{endpoint_path}?sort=desc&per_page=4", user)
+
+ response_ids = json_response.map { |merge_request| merge_request['id'] }
+
+ expect(response_ids).to include(closed_mr2.id)
+ expect(response_ids).not_to include(@mr_earlier.id)
+ end
+
+ it 'page breaks second page correctly' do
+ get api("#{endpoint_path}?sort=desc&per_page=4&page=2", user)
+
+ response_ids = json_response.map { |merge_request| merge_request['id'] }
+
+ expect(response_ids).not_to include(closed_mr2.id)
+ expect(response_ids).to include(@mr_earlier.id)
+ end
+ end
+
it 'returns an array of merge_requests ordered by updated_at' do
path = endpoint_path + '?order_by=updated_at'
diff --git a/spec/support/shared_examples/requests/api/notes.rb b/spec/support/shared_examples/requests/api/notes.rb
index 71499e85654..57eefd5ef01 100644
--- a/spec/support/shared_examples/requests/api/notes.rb
+++ b/spec/support/shared_examples/requests/api/notes.rb
@@ -8,13 +8,45 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
create_list(:note, 3, params)
end
- it 'sorts by created_at in descending order by default' do
- get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user)
+ context 'without sort params' do
+ it 'sorts by created_at in descending order by default' do
+ get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user)
- response_dates = json_response.map { |note| note['created_at'] }
+ response_dates = json_response.map { |note| note['created_at'] }
- expect(json_response.length).to eq(4)
- expect(response_dates).to eq(response_dates.sort.reverse)
+ expect(json_response.length).to eq(4)
+ expect(response_dates).to eq(response_dates.sort.reverse)
+ end
+
+ context '2 notes with equal created_at' do
+ before do
+ @first_note = Note.first
+
+ params = { noteable: noteable, author: user }
+ params[:project] = parent if parent.is_a?(Project)
+ params[:created_at] = @first_note.created_at
+
+ @note2 = create(:note, params)
+ end
+
+ it 'page breaks first page correctly' do
+ get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes?per_page=4", user)
+
+ response_ids = json_response.map { |note| note['id'] }
+
+ expect(response_ids).to include(@note2.id)
+ expect(response_ids).not_to include(@first_note.id)
+ end
+
+ it 'page breaks second page correctly' do
+ get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes?per_page=4&page=2", user)
+
+ response_ids = json_response.map { |note| note['id'] }
+
+ expect(response_ids).not_to include(@note2.id)
+ expect(response_ids).to include(@first_note.id)
+ end
+ end
end
it 'sorts by ascending order when requested' do
diff --git a/spec/support/shared_examples/serializers/diff_file_entity_examples.rb b/spec/support/shared_examples/serializers/diff_file_entity_examples.rb
index 1770308f789..96cb71be737 100644
--- a/spec/support/shared_examples/serializers/diff_file_entity_examples.rb
+++ b/spec/support/shared_examples/serializers/diff_file_entity_examples.rb
@@ -6,9 +6,9 @@ shared_examples 'diff file base entity' do
:submodule_tree_url, :old_path_html,
:new_path_html, :blob, :can_modify_blob,
:file_hash, :file_path, :old_path, :new_path,
- :collapsed, :text, :diff_refs, :stored_externally,
+ :viewer, :diff_refs, :stored_externally,
:external_storage, :renamed_file, :deleted_file,
- :mode_changed, :a_mode, :b_mode, :new_file)
+ :a_mode, :b_mode, :new_file)
end
# Converted diff files from GitHub import does not contain blob file
@@ -30,9 +30,9 @@ shared_examples 'diff file entity' do
it_behaves_like 'diff file base entity'
it 'exposes correct attributes' do
- expect(subject).to include(:too_large, :added_lines, :removed_lines,
+ expect(subject).to include(:added_lines, :removed_lines,
:context_lines_path, :highlighted_diff_lines,
- :parallel_diff_lines, :empty)
+ :parallel_diff_lines)
end
it 'includes viewer' do
diff --git a/spec/support/shared_examples/services/boards/issues_move_service.rb b/spec/support/shared_examples/services/boards/issues_move_service.rb
index ec44b99d10e..9dbd1d8e867 100644
--- a/spec/support/shared_examples/services/boards/issues_move_service.rb
+++ b/spec/support/shared_examples/services/boards/issues_move_service.rb
@@ -39,6 +39,22 @@ shared_examples 'issues move service' do |group|
end
end
+ context 'when moving to backlog' do
+ let(:milestone) { create(:milestone, project: project) }
+ let!(:backlog) { create(:backlog_list, board: board1) }
+
+ let(:issue) { create(:labeled_issue, project: project, labels: [bug, development, testing, regression], milestone: milestone) }
+ let(:params) { { board_id: board1.id, from_list_id: list2.id, to_list_id: backlog.id } }
+
+ it 'keeps labels and milestone' do
+ described_class.new(parent, user, params).execute(issue)
+ issue.reload
+
+ expect(issue.labels).to contain_exactly(bug, regression)
+ expect(issue.milestone).to eq(milestone)
+ end
+ end
+
context 'when moving from closed' do
let(:issue) { create(:labeled_issue, :closed, project: project, labels: [bug]) }
let(:params) { { board_id: board1.id, from_list_id: closed.id, to_list_id: list2.id } }
diff --git a/spec/support/shared_examples/url_validator_examples.rb b/spec/support/shared_examples/url_validator_examples.rb
index b4757a70984..1f7e2f7ff79 100644
--- a/spec/support/shared_examples/url_validator_examples.rb
+++ b/spec/support/shared_examples/url_validator_examples.rb
@@ -1,5 +1,5 @@
RSpec.shared_examples 'url validator examples' do |protocols|
- let(:validator) { described_class.new(attributes: [:link_url], **options) }
+ let(:validator) { described_class.new(attributes: [:link_url], **options) }
let!(:badge) { build(:badge, link_url: 'http://www.example.com') }
subject { validator.validate_each(badge, :link_url, badge.link_url) }
diff --git a/spec/support/shared_examples/views/nav_sidebar.rb b/spec/support/shared_examples/views/nav_sidebar.rb
new file mode 100644
index 00000000000..6ac5abe275d
--- /dev/null
+++ b/spec/support/shared_examples/views/nav_sidebar.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+shared_examples 'has nav sidebar' do
+ it 'has collapsed nav sidebar on mobile' do
+ render
+
+ expect(rendered).to have_selector('.nav-sidebar')
+ expect(rendered).not_to have_selector('.sidebar-collapsed-desktop')
+ expect(rendered).not_to have_selector('.sidebar-expanded-mobile')
+ end
+end
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index 3b8f7f5fe7d..a8fae4a88a3 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -71,21 +71,29 @@ describe 'gitlab:app namespace rake task' do
end.to raise_error(SystemExit)
end
- it 'invokes restoration on match' do
- allow(YAML).to receive(:load_file)
- .and_return({ gitlab_version: gitlab_version })
-
- expect(Rake::Task['gitlab:db:drop_tables']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:db:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:repo:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:builds:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:uploads:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:pages:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:backup:registry:restore']).to receive(:invoke)
- expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke)
- expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout
+ context 'restore with matching gitlab version' do
+ before do
+ allow(YAML).to receive(:load_file)
+ .and_return({ gitlab_version: gitlab_version })
+ expect(Rake::Task['gitlab:db:drop_tables']).to receive(:invoke)
+ expect(Rake::Task['gitlab:backup:db:restore']).to receive(:invoke)
+ expect(Rake::Task['gitlab:backup:repo:restore']).to receive(:invoke)
+ expect(Rake::Task['gitlab:backup:builds:restore']).to receive(:invoke)
+ expect(Rake::Task['gitlab:backup:uploads:restore']).to receive(:invoke)
+ expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive(:invoke)
+ expect(Rake::Task['gitlab:backup:pages:restore']).to receive(:invoke)
+ expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke)
+ expect(Rake::Task['gitlab:backup:registry:restore']).to receive(:invoke)
+ expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke)
+ end
+
+ it 'invokes restoration on match' do
+ expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout
+ end
+
+ it 'prints timestamps on messages' do
+ expect { run_rake_task('gitlab:backup:restore') }.to output(/.*\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s[-+]\d{4}\s--\s.*/).to_stdout
+ end
end
end
diff --git a/spec/tasks/gitlab/shell_rake_spec.rb b/spec/tasks/gitlab/shell_rake_spec.rb
index 0ed5d3e27b9..a9d14070177 100644
--- a/spec/tasks/gitlab/shell_rake_spec.rb
+++ b/spec/tasks/gitlab/shell_rake_spec.rb
@@ -8,7 +8,7 @@ describe 'gitlab:shell rake tasks' do
end
after do
- TestEnv.create_fake_git_hooks
+ TestEnv.sabotage_gitlab_shell_hooks
end
describe 'install task' do
diff --git a/spec/tasks/gitlab/storage_rake_spec.rb b/spec/tasks/gitlab/storage_rake_spec.rb
index be902d7c679..6b50670c3c0 100644
--- a/spec/tasks/gitlab/storage_rake_spec.rb
+++ b/spec/tasks/gitlab/storage_rake_spec.rb
@@ -58,7 +58,7 @@ describe 'rake gitlab:storage:*' do
context '0 legacy projects' do
it 'does nothing' do
- expect(StorageMigratorWorker).not_to receive(:perform_async)
+ expect(::HashedStorage::MigratorWorker).not_to receive(:perform_async)
run_rake_task(task)
end
@@ -72,9 +72,9 @@ describe 'rake gitlab:storage:*' do
stub_env('BATCH' => 1)
end
- it 'enqueues one StorageMigratorWorker per project' do
+ it 'enqueues one HashedStorage::MigratorWorker per project' do
projects.each do |project|
- expect(StorageMigratorWorker).to receive(:perform_async).with(project.id, project.id)
+ expect(::HashedStorage::MigratorWorker).to receive(:perform_async).with(project.id, project.id)
end
run_rake_task(task)
@@ -86,10 +86,10 @@ describe 'rake gitlab:storage:*' do
stub_env('BATCH' => 2)
end
- it 'enqueues one StorageMigratorWorker per 2 projects' do
+ it 'enqueues one HashedStorage::MigratorWorker per 2 projects' do
projects.map(&:id).sort.each_slice(2) do |first, last|
last ||= first
- expect(StorageMigratorWorker).to receive(:perform_async).with(first, last)
+ expect(::HashedStorage::MigratorWorker).to receive(:perform_async).with(first, last)
end
run_rake_task(task)
diff --git a/spec/uploaders/external_diff_uploader_spec.rb b/spec/uploaders/external_diff_uploader_spec.rb
new file mode 100644
index 00000000000..1c959770dc4
--- /dev/null
+++ b/spec/uploaders/external_diff_uploader_spec.rb
@@ -0,0 +1,67 @@
+require 'spec_helper'
+
+describe ExternalDiffUploader do
+ let(:diff) { create(:merge_request).merge_request_diff }
+ let(:path) { Gitlab.config.external_diffs.storage_path }
+
+ subject(:uploader) { described_class.new(diff, :external_diff) }
+
+ it_behaves_like "builds correct paths",
+ store_dir: %r[merge_request_diffs/mr-\d+],
+ cache_dir: %r[/external-diffs/tmp/cache],
+ work_dir: %r[/external-diffs/tmp/work]
+
+ context "object store is REMOTE" do
+ before do
+ stub_external_diffs_object_storage
+ end
+
+ include_context 'with storage', described_class::Store::REMOTE
+
+ it_behaves_like "builds correct paths",
+ store_dir: %r[merge_request_diffs/mr-\d+]
+ end
+
+ describe 'migration to object storage' do
+ context 'with object storage disabled' do
+ it "is skipped" do
+ expect(ObjectStorage::BackgroundMoveWorker).not_to receive(:perform_async)
+
+ diff
+ end
+ end
+
+ context 'with object storage enabled' do
+ before do
+ stub_external_diffs_setting(enabled: true)
+ stub_external_diffs_object_storage(background_upload: true)
+ end
+
+ it 'is scheduled to run after creation' do
+ expect(ObjectStorage::BackgroundMoveWorker).to receive(:perform_async).with(described_class.name, 'MergeRequestDiff', :external_diff, kind_of(Numeric))
+
+ diff
+ end
+ end
+ end
+
+ describe 'remote file' do
+ context 'with object storage enabled' do
+ before do
+ stub_external_diffs_setting(enabled: true)
+ stub_external_diffs_object_storage
+
+ diff.update!(external_diff_store: described_class::Store::REMOTE)
+ end
+
+ it 'can store file remotely' do
+ allow(ObjectStorage::BackgroundMoveWorker).to receive(:perform_async)
+
+ diff
+
+ expect(diff.external_diff_store).to eq(described_class::Store::REMOTE)
+ expect(diff.external_diff.path).not_to be_blank
+ end
+ end
+ end
+end
diff --git a/spec/uploaders/file_mover_spec.rb b/spec/uploaders/file_mover_spec.rb
index de29d0c943f..e474a714b10 100644
--- a/spec/uploaders/file_mover_spec.rb
+++ b/spec/uploaders/file_mover_spec.rb
@@ -1,8 +1,9 @@
require 'spec_helper'
describe FileMover do
+ include FileMoverHelpers
+
let(:filename) { 'banana_sample.gif' }
- let(:file) { fixture_file_upload(File.join('spec', 'fixtures', filename)) }
let(:temp_file_path) { File.join('uploads/-/system/temp', 'secret55', filename) }
let(:temp_description) do
@@ -12,7 +13,7 @@ describe FileMover do
let(:file_path) { File.join('uploads/-/system/personal_snippet', snippet.id.to_s, 'secret55', filename) }
let(:snippet) { create(:personal_snippet, description: temp_description) }
- subject { described_class.new(file_path, snippet).execute }
+ subject { described_class.new(temp_file_path, snippet).execute }
describe '#execute' do
before do
@@ -20,6 +21,8 @@ describe FileMover do
expect(FileUtils).to receive(:move).with(a_string_including(temp_file_path), a_string_including(file_path))
allow_any_instance_of(CarrierWave::SanitizedFile).to receive(:exists?).and_return(true)
allow_any_instance_of(CarrierWave::SanitizedFile).to receive(:size).and_return(10)
+
+ stub_file_mover(temp_file_path)
end
context 'when move and field update successful' do
@@ -66,4 +69,30 @@ describe FileMover do
end
end
end
+
+ context 'security' do
+ context 'when relative path is involved' do
+ let(:temp_file_path) { File.join('uploads/-/system/temp', '..', 'another_subdir_of_temp') }
+
+ it 'does not trigger move if path is outside designated directory' do
+ stub_file_mover('uploads/-/system/another_subdir_of_temp')
+ expect(FileUtils).not_to receive(:move)
+
+ subject
+
+ expect(snippet.reload.description).to eq(temp_description)
+ end
+ end
+
+ context 'when symlink is involved' do
+ it 'does not trigger move if path is outside designated directory' do
+ stub_file_mover(temp_file_path, stub_real_path: Pathname('/etc'))
+ expect(FileUtils).not_to receive(:move)
+
+ subject
+
+ expect(snippet.reload.description).to eq(temp_description)
+ end
+ end
+ end
end
diff --git a/spec/uploaders/file_uploader_spec.rb b/spec/uploaders/file_uploader_spec.rb
index c74e0bf1955..185c62491ce 100644
--- a/spec/uploaders/file_uploader_spec.rb
+++ b/spec/uploaders/file_uploader_spec.rb
@@ -4,7 +4,7 @@ describe FileUploader do
let(:group) { create(:group, name: 'awesome') }
let(:project) { create(:project, :legacy_storage, namespace: group, name: 'project') }
let(:uploader) { described_class.new(project) }
- let(:upload) { double(model: project, path: 'secret/foo.jpg') }
+ let(:upload) { double(model: project, path: 'secret/foo.jpg') }
subject { uploader }
@@ -201,7 +201,7 @@ describe FileUploader do
end
let!(:fog_file) do
- fog_connection.directories.get('uploads').files.create(
+ fog_connection.directories.new(key: 'uploads').files.create(
key: 'tmp/uploads/test/123123',
body: 'content'
)
diff --git a/spec/uploaders/import_export_uploader_spec.rb b/spec/uploaders/import_export_uploader_spec.rb
index 51b173b682d..825c1cabc14 100644
--- a/spec/uploaders/import_export_uploader_spec.rb
+++ b/spec/uploaders/import_export_uploader_spec.rb
@@ -4,7 +4,7 @@ describe ImportExportUploader do
let(:model) { build_stubbed(:import_export_upload) }
let(:upload) { create(:upload, model: model) }
- subject { described_class.new(model, :import_file) }
+ subject { described_class.new(model, :import_file) }
context "object_store is REMOTE" do
before do
diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb
index 7e673681c31..533e9d87ea6 100644
--- a/spec/uploaders/object_storage_spec.rb
+++ b/spec/uploaders/object_storage_spec.rb
@@ -716,7 +716,7 @@ describe ObjectStorage do
end
let!(:fog_file) do
- fog_connection.directories.get('uploads').files.create(
+ fog_connection.directories.new(key: 'uploads').files.create(
key: 'tmp/uploads/test/123123',
body: 'content'
)
diff --git a/spec/uploaders/personal_file_uploader_spec.rb b/spec/uploaders/personal_file_uploader_spec.rb
index 2896e9a112d..97758f0243e 100644
--- a/spec/uploaders/personal_file_uploader_spec.rb
+++ b/spec/uploaders/personal_file_uploader_spec.rb
@@ -4,19 +4,13 @@ describe PersonalFileUploader do
let(:model) { create(:personal_snippet) }
let(:uploader) { described_class.new(model) }
let(:upload) { create(:upload, :personal_snippet_upload) }
- let(:identifier) { %r{\h+/\S+} }
subject { uploader }
- it_behaves_like 'builds correct paths' do
- let(:patterns) do
- {
- store_dir: %r[uploads/-/system/personal_snippet/\d+],
- upload_path: identifier,
- absolute_path: %r[#{CarrierWave.root}/uploads/-/system/personal_snippet/\d+/#{identifier}]
- }
- end
- end
+ it_behaves_like 'builds correct paths',
+ store_dir: %r[uploads/-/system/personal_snippet/\d+],
+ upload_path: %r[\h+/\S+],
+ absolute_path: %r[#{CarrierWave.root}/uploads/-/system/personal_snippet\/\d+\/\h+\/\S+$]
context "object_store is REMOTE" do
before do
@@ -25,13 +19,17 @@ describe PersonalFileUploader do
include_context 'with storage', described_class::Store::REMOTE
- it_behaves_like 'builds correct paths' do
- let(:patterns) do
- {
- store_dir: %r[\d+/\h+],
- upload_path: identifier
- }
- end
+ it_behaves_like 'builds correct paths',
+ store_dir: %r[\d+/\h+],
+ upload_path: %r[^personal_snippet\/\d+\/\h+\/<filename>]
+ end
+
+ describe '#upload_paths' do
+ it 'builds correct paths for both local and remote storage' do
+ paths = uploader.upload_paths('test.jpg')
+
+ expect(paths.first).to match(%r[\h+\/test.jpg])
+ expect(paths.second).to match(%r[^personal_snippet\/\d+\/\h+\/test.jpg])
end
end
diff --git a/spec/validators/js_regex_validator_spec.rb b/spec/validators/js_regex_validator_spec.rb
index aeb55cdc0e5..4d3bafaf267 100644
--- a/spec/validators/js_regex_validator_spec.rb
+++ b/spec/validators/js_regex_validator_spec.rb
@@ -12,8 +12,6 @@ describe JsRegexValidator do
'' | []
'(?#comment)' | ['Regex Pattern (?#comment) can not be expressed in Javascript']
'(?(a)b|c)' | ['invalid conditional pattern: /(?(a)b|c)/i']
- '[a-z&&[^uo]]' | ["Dropped unsupported set intersection '[a-z&&[^uo]]' at index 0",
- "Dropped unsupported nested negative set data '[^uo]' at index 6"]
end
with_them do
diff --git a/spec/validators/sha_validator_spec.rb b/spec/validators/sha_validator_spec.rb
new file mode 100644
index 00000000000..dc1539cf318
--- /dev/null
+++ b/spec/validators/sha_validator_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ShaValidator do
+ let(:validator) { described_class.new(attributes: [:base_commit_sha]) }
+ let(:merge_diff) { build(:merge_request_diff) }
+
+ subject { validator.validate_each(merge_diff, :base_commit_sha, value) }
+
+ context 'with empty value' do
+ let(:value) { nil }
+
+ it 'does not add any error if value is empty' do
+ subject
+
+ expect(merge_diff.errors).to be_empty
+ end
+ end
+
+ context 'with valid sha' do
+ let(:value) { Digest::SHA1.hexdigest(SecureRandom.hex) }
+
+ it 'does not add any error if value is empty' do
+ subject
+
+ expect(merge_diff.errors).to be_empty
+ end
+ end
+
+ context 'with invalid sha' do
+ let(:value) { 'foo' }
+
+ it 'adds error to the record' do
+ expect(merge_diff.errors).to be_empty
+
+ subject
+
+ expect(merge_diff.errors).not_to be_empty
+ end
+ end
+end
diff --git a/spec/validators/url_validator_spec.rb b/spec/validators/url_validator_spec.rb
index f3f3386382f..1bb42382e8a 100644
--- a/spec/validators/url_validator_spec.rb
+++ b/spec/validators/url_validator_spec.rb
@@ -172,4 +172,55 @@ describe UrlValidator do
end
end
end
+
+ context 'when enforce_sanitization is' do
+ let(:validator) { described_class.new(attributes: [:link_url], enforce_sanitization: enforce_sanitization) }
+ let(:unsafe_url) { "https://replaceme.com/'><script>alert(document.cookie)</script>" }
+ let(:safe_url) { 'https://replaceme.com/path/to/somewhere' }
+
+ let(:unsafe_internal_url) do
+ Gitlab.config.gitlab.protocol + '://' + Gitlab.config.gitlab.host +
+ "/'><script>alert(document.cookie)</script>"
+ end
+
+ context 'true' do
+ let(:enforce_sanitization) { true }
+
+ it 'prevents unsafe urls' do
+ badge.link_url = unsafe_url
+
+ subject
+
+ expect(badge.errors.empty?).to be false
+ end
+
+ it 'prevents unsafe internal urls' do
+ badge.link_url = unsafe_internal_url
+
+ subject
+
+ expect(badge.errors.empty?).to be false
+ end
+
+ it 'allows safe urls' do
+ badge.link_url = safe_url
+
+ subject
+
+ expect(badge.errors.empty?).to be true
+ end
+ end
+
+ context 'false' do
+ let(:enforce_sanitization) { false }
+
+ it 'allows unsafe urls' do
+ badge.link_url = unsafe_url
+
+ subject
+
+ expect(badge.errors.empty?).to be true
+ end
+ end
+ end
end
diff --git a/spec/views/ci/status/_icon.html.haml_spec.rb b/spec/views/ci/status/_icon.html.haml_spec.rb
new file mode 100644
index 00000000000..626159fc512
--- /dev/null
+++ b/spec/views/ci/status/_icon.html.haml_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'ci/status/_icon' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :private) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ context 'when rendering status for build' do
+ let(:build) do
+ create(:ci_build, :success, pipeline: pipeline)
+ end
+
+ context 'when user has ability to see details' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'has link to build details page' do
+ details_path = project_job_path(project, build)
+
+ render_status(build)
+
+ expect(rendered).to have_link(href: details_path)
+ end
+ end
+
+ context 'when user do not have ability to see build details' do
+ before do
+ render_status(build)
+ end
+
+ it 'contains build status text' do
+ expect(rendered).to have_css('.ci-status-icon.ci-status-icon-success')
+ end
+
+ it 'does not contain links' do
+ expect(rendered).not_to have_link
+ end
+ end
+ end
+
+ context 'when rendering status for external job' do
+ context 'when user has ability to see commit status details' do
+ before do
+ project.add_developer(user)
+ end
+
+ context 'status has external target url' do
+ before do
+ external_job = create(:generic_commit_status,
+ status: :running,
+ pipeline: pipeline,
+ target_url: 'http://gitlab.com')
+
+ render_status(external_job)
+ end
+
+ it 'contains valid commit status text' do
+ expect(rendered).to have_css('.ci-status-icon.ci-status-icon-running')
+ end
+
+ it 'has link to external status page' do
+ expect(rendered).to have_link(href: 'http://gitlab.com')
+ end
+ end
+
+ context 'status do not have external target url' do
+ before do
+ external_job = create(:generic_commit_status, status: :canceled)
+
+ render_status(external_job)
+ end
+
+ it 'contains valid commit status text' do
+ expect(rendered).to have_css('.ci-status-icon.ci-status-icon-canceled')
+ end
+
+ it 'has link to external status page' do
+ expect(rendered).not_to have_link
+ end
+ end
+ end
+ end
+
+ def render_status(resource)
+ render 'ci/status/icon', status: resource.detailed_status(user)
+ end
+end
diff --git a/spec/views/help/instance_configuration.html.haml_spec.rb b/spec/views/help/instance_configuration.html.haml_spec.rb
index f30b5881fde..ceb7e34a540 100644
--- a/spec/views/help/instance_configuration.html.haml_spec.rb
+++ b/spec/views/help/instance_configuration.html.haml_spec.rb
@@ -13,9 +13,9 @@ describe 'help/instance_configuration' do
it 'has links to several sections' do
render
- expect(rendered).to have_link(nil, '#ssh-host-keys-fingerprints') if ssh_settings.any?
- expect(rendered).to have_link(nil, '#gitlab-pages')
- expect(rendered).to have_link(nil, '#gitlab-ci')
+ expect(rendered).to have_link(nil, href: '#ssh-host-keys-fingerprints') if ssh_settings.any?
+ expect(rendered).to have_link(nil, href: '#gitlab-pages')
+ expect(rendered).to have_link(nil, href: '#gitlab-ci')
end
it 'has several sections' do
diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb
index 9d1efcabb80..cbb4199954a 100644
--- a/spec/views/layouts/_head.html.haml_spec.rb
+++ b/spec/views/layouts/_head.html.haml_spec.rb
@@ -62,6 +62,14 @@ describe 'layouts/_head' do
end
end
+ it 'adds selected syntax highlight stylesheet' do
+ allow_any_instance_of(PreferencesHelper).to receive(:user_color_scheme).and_return("solarised-light")
+
+ render
+
+ expect(rendered).to match('<link rel="stylesheet" media="all" href="/stylesheets/highlight/themes/solarised-light.css" />')
+ end
+
def stub_helper_with_safe_string(method)
allow_any_instance_of(PageLayoutHelper).to receive(method)
.and_return(%q{foo" http-equiv="refresh}.html_safe)
diff --git a/spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb
index 05c2f61a606..bf63021a7fa 100644
--- a/spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb
@@ -26,6 +26,8 @@ describe 'layouts/nav/sidebar/_admin' do
it_behaves_like 'page has active tab', 'Overview'
end
+ it_behaves_like 'has nav sidebar'
+
context 'on projects' do
before do
allow(controller).to receive(:controller_name).and_return('projects')
diff --git a/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb
new file mode 100644
index 00000000000..24b66a0e767
--- /dev/null
+++ b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'layouts/nav/sidebar/_group' do
+ let(:group) { create(:group) }
+
+ before do
+ assign(:group, group)
+ end
+
+ it_behaves_like 'has nav sidebar'
+end
diff --git a/spec/views/layouts/nav/sidebar/_instance_statistics.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_instance_statistics.html.haml_spec.rb
new file mode 100644
index 00000000000..7f7f5637035
--- /dev/null
+++ b/spec/views/layouts/nav/sidebar/_instance_statistics.html.haml_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'layouts/nav/sidebar/_instance_statistics' do
+ it_behaves_like 'has nav sidebar'
+end
diff --git a/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb
new file mode 100644
index 00000000000..6b820ab0b4c
--- /dev/null
+++ b/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'layouts/nav/sidebar/_profile' do
+ let(:user) { create(:user) }
+
+ before do
+ allow(view).to receive(:current_user).and_return(user)
+ end
+
+ it_behaves_like 'has nav sidebar'
+end
diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
index ec20c346234..2c60ccfb754 100644
--- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
@@ -11,6 +11,8 @@ describe 'layouts/nav/sidebar/_project' do
allow(view).to receive(:can?).and_return(true)
end
+ it_behaves_like 'has nav sidebar'
+
describe 'issue boards' do
it 'has board tab' do
render
@@ -51,27 +53,63 @@ describe 'layouts/nav/sidebar/_project' do
end
describe 'releases entry' do
- describe 'when releases feature flag is disabled' do
- before do
- stub_feature_flags(releases_page: false)
+ it 'renders releases link' do
+ render
+
+ expect(rendered).to have_link('Releases', href: project_releases_path(project))
+ end
+ end
+
+ describe 'wiki entry tab' do
+ let(:can_read_wiki) { true }
+
+ before do
+ allow(view).to receive(:can?).with(nil, :read_wiki, project).and_return(can_read_wiki)
+ end
+
+ describe 'when wiki is enabled' do
+ it 'shows the wiki tab with the wiki internal link' do
+ render
+
+ expect(rendered).to have_link('Wiki', href: project_wiki_path(project, :home))
end
+ end
+
+ describe 'when wiki is disabled' do
+ let(:can_read_wiki) { false }
- it 'does not render releases link' do
+ it 'does not show the wiki tab' do
render
- expect(rendered).not_to have_link('Releases', href: project_releases_path(project))
+ expect(rendered).not_to have_link('Wiki', href: project_wiki_path(project, :home))
end
end
+ end
- describe 'when releases feature flags is enabled' do
- before do
- stub_feature_flags(releases_page: true)
+ describe 'external wiki entry tab' do
+ let(:properties) { { 'external_wiki_url' => 'https://gitlab.com' } }
+ let(:service_status) { true }
+
+ before do
+ project.create_external_wiki_service(active: service_status, properties: properties)
+ project.reload
+ end
+
+ context 'when it is active' do
+ it 'shows the external wiki tab with the external wiki service link' do
+ render
+
+ expect(rendered).to have_link('External Wiki', href: properties['external_wiki_url'])
end
+ end
+
+ context 'when it is disabled' do
+ let(:service_status) { false }
- it 'renders releases link' do
+ it 'does not show the external wiki tab' do
render
- expect(rendered).to have_link('Releases', href: project_releases_path(project))
+ expect(rendered).not_to have_link('External Wiki', href: project_wiki_path(project, :home))
end
end
end
diff --git a/spec/views/projects/_home_panel.html.haml_spec.rb b/spec/views/projects/_home_panel.html.haml_spec.rb
index 006c93686d5..908ecb898e4 100644
--- a/spec/views/projects/_home_panel.html.haml_spec.rb
+++ b/spec/views/projects/_home_panel.html.haml_spec.rb
@@ -23,7 +23,7 @@ describe 'projects/_home_panel' do
it 'makes it possible to set notification level' do
render
- expect(view).to render_template('projects/buttons/_notifications')
+ expect(view).to render_template('shared/notifications/_new_button')
expect(rendered).to have_selector('.notification-dropdown')
end
end
diff --git a/spec/views/projects/commit/_commit_box.html.haml_spec.rb b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
index 2fdd28a3be4..1086546c10d 100644
--- a/spec/views/projects/commit/_commit_box.html.haml_spec.rb
+++ b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
@@ -9,6 +9,7 @@ describe 'projects/commit/_commit_box.html.haml' do
assign(:commit, project.commit)
allow(view).to receive(:current_user).and_return(user)
allow(view).to receive(:can_collaborate_with_project?).and_return(false)
+ project.add_developer(user)
end
it 'shows the commit SHA' do
@@ -48,7 +49,6 @@ describe 'projects/commit/_commit_box.html.haml' do
context 'viewing a commit' do
context 'as a developer' do
before do
- project.add_developer(user)
allow(view).to receive(:can_collaborate_with_project?).and_return(true)
end
@@ -60,6 +60,10 @@ describe 'projects/commit/_commit_box.html.haml' do
end
context 'as a non-developer' do
+ before do
+ project.add_guest(user)
+ end
+
it 'does not have a link to create a new tag' do
render
diff --git a/spec/views/projects/commit/show.html.haml_spec.rb b/spec/views/projects/commit/show.html.haml_spec.rb
index a9c32122600..d07099489e5 100644
--- a/spec/views/projects/commit/show.html.haml_spec.rb
+++ b/spec/views/projects/commit/show.html.haml_spec.rb
@@ -54,9 +54,9 @@ describe 'projects/commit/show.html.haml' do
end
it 'shows that it is in the context of a merge request' do
- merge_request_url = diffs_project_merge_request_url(project, merge_request, commit_id: commit.id)
+ merge_request_url = diffs_project_merge_request_path(project, merge_request, commit_id: commit.id)
expect(rendered).to have_content("This commit is part of merge request")
- expect(rendered).to have_link(merge_request.to_reference, merge_request_url)
+ expect(rendered).to have_link(merge_request.to_reference, href: merge_request_url)
end
end
end
diff --git a/spec/views/projects/commits/_commit.html.haml_spec.rb b/spec/views/projects/commits/_commit.html.haml_spec.rb
index 00547e433c4..6bf1b5fd2d0 100644
--- a/spec/views/projects/commits/_commit.html.haml_spec.rb
+++ b/spec/views/projects/commits/_commit.html.haml_spec.rb
@@ -1,15 +1,15 @@
require 'spec_helper'
describe 'projects/commits/_commit.html.haml' do
+ let(:project) { create(:project, :repository) }
+ let(:commit) { project.repository.commit(ref) }
+
before do
allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
end
- context 'with a singed commit' do
- let(:project) { create(:project, :repository) }
- let(:repository) { project.repository }
+ context 'with a signed commit' do
let(:ref) { GpgHelpers::SIGNED_COMMIT_SHA }
- let(:commit) { repository.commit(ref) }
it 'does not display a loading spinner for GPG status' do
render partial: 'projects/commits/commit', locals: {
@@ -23,4 +23,55 @@ describe 'projects/commits/_commit.html.haml' do
end
end
end
+
+ context 'with ci status' do
+ let(:ref) { 'master' }
+ let(:user) { create(:user) }
+
+ before do
+ allow(view).to receive(:current_user).and_return(user)
+
+ project.add_developer(user)
+
+ create(
+ :ci_empty_pipeline,
+ ref: 'master',
+ sha: commit.id,
+ status: 'success',
+ project: project
+ )
+ end
+
+ context 'when pipelines are disabled' do
+ before do
+ allow(project).to receive(:builds_enabled?).and_return(false)
+ end
+
+ it 'does not display a ci status icon' do
+ render partial: 'projects/commits/commit', locals: {
+ project: project,
+ ref: ref,
+ commit: commit
+ }
+
+ expect(rendered).not_to have_css('.ci-status-link')
+ end
+ end
+
+ context 'when pipelines are enabled' do
+ before do
+ allow(project).to receive(:builds_enabled?).and_return(true)
+ end
+
+ it 'does display a ci status icon when pipelines are enabled' do
+ render partial: 'projects/commits/commit', locals: {
+ project: project,
+ ref: ref,
+ commit: commit
+ }
+
+ expect(rendered).to have_css('.ci-status-link')
+ end
+ end
+ end
end
diff --git a/spec/views/projects/deployments/_confirm_rollback_modal_spec.html.rb b/spec/views/projects/deployments/_confirm_rollback_modal_spec.html.rb
new file mode 100644
index 00000000000..54ec4f32856
--- /dev/null
+++ b/spec/views/projects/deployments/_confirm_rollback_modal_spec.html.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'projects/deployments/_confirm_rollback_modal' do
+ let(:environment) { create(:environment, :with_review_app) }
+ let(:deployments) { environment.deployments }
+ let(:project) { environment.project }
+
+ before do
+ assign(:environment, environment)
+ assign(:deployments, deployments)
+ assign(:project, project)
+ end
+
+ context 'when re-deploying last deployment' do
+ let(:deployment) { deployments.first }
+
+ before do
+ allow(view).to receive(:deployment).and_return(deployment)
+ end
+
+ it 'shows "re-deploy"' do
+ render
+
+ expect(rendered).to have_selector('h4', text: "Re-deploy environment #{environment.name}?")
+ expect(rendered).to have_selector('p', text: "This action will relaunch the job for commit #{deployment.short_sha}, putting the environment in a previous version. Are you sure you want to continue?")
+ expect(rendered).to have_selector('a.btn-danger', text: 'Re-deploy')
+ end
+
+ it 'links to re-deploying the environment' do
+ expected_link = retry_project_job_path(environment.project, deployment.deployable)
+
+ render
+
+ expect(rendered).to have_selector("a[href='#{expected_link}']", text: 'Re-deploy')
+ end
+ end
+
+ context 'when rolling back to previous deployment' do
+ let(:deployment) { create(:deployment, environment: environment) }
+
+ before do
+ allow(view).to receive(:deployment).and_return(deployment)
+ end
+
+ it 'shows "rollback"' do
+ render
+
+ expect(rendered).to have_selector('h4', text: "Rollback environment #{environment.name}?")
+ expect(rendered).to have_selector('p', text: "This action will run the job defined by staging for commit #{deployment.short_sha}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?")
+ expect(rendered).to have_selector('a.btn-danger', text: 'Rollback')
+ end
+
+ it 'links to re-deploying the environment' do
+ expected_link = retry_project_job_path(environment.project, deployment.deployable)
+
+ render
+
+ expect(rendered).to have_selector("a[href='#{expected_link}']", text: 'Rollback')
+ end
+ end
+end
diff --git a/spec/views/projects/issues/_merge_requests_status.html.haml_spec.rb b/spec/views/projects/issues/_merge_requests_status.html.haml_spec.rb
new file mode 100644
index 00000000000..9424795749d
--- /dev/null
+++ b/spec/views/projects/issues/_merge_requests_status.html.haml_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'projects/issues/_merge_requests_status.html.haml' do
+ around do |ex|
+ Timecop.freeze(Date.new(2018, 7, 22)) do
+ ex.run
+ end
+ end
+
+ it 'shows date of status change in tooltip' do
+ merge_request = create(:merge_request, created_at: 1.month.ago)
+
+ render partial: 'projects/issues/merge_requests_status',
+ locals: { merge_request: merge_request, css_class: '' }
+
+ expect(rendered).to match("Opened.*about 1 month ago")
+ end
+
+ it 'shows only status in tooltip if date is not set' do
+ merge_request = create(:merge_request, state: :closed)
+
+ render partial: 'projects/issues/merge_requests_status',
+ locals: { merge_request: merge_request, css_class: '' }
+
+ expect(rendered).to match("Closed")
+ end
+end
diff --git a/spec/views/projects/issues/_related_branches.html.haml_spec.rb b/spec/views/projects/issues/_related_branches.html.haml_spec.rb
index 8c845251765..5cff7694029 100644
--- a/spec/views/projects/issues/_related_branches.html.haml_spec.rb
+++ b/spec/views/projects/issues/_related_branches.html.haml_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
describe 'projects/issues/_related_branches' do
include Devise::Test::ControllerHelpers
+ let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
let(:branch) { project.repository.find_branch('feature') }
let!(:pipeline) { create(:ci_pipeline, project: project, sha: branch.dereferenced_target.id, ref: 'feature') }
@@ -11,6 +12,9 @@ describe 'projects/issues/_related_branches' do
assign(:project, project)
assign(:related_branches, ['feature'])
+ project.add_developer(user)
+ allow(view).to receive(:current_user).and_return(user)
+
render
end
diff --git a/spec/views/projects/issues/show.html.haml_spec.rb b/spec/views/projects/issues/show.html.haml_spec.rb
new file mode 100644
index 00000000000..1d9c6d36ad7
--- /dev/null
+++ b/spec/views/projects/issues/show.html.haml_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'projects/issues/show' do
+ let(:project) { create(:project, :repository) }
+ let(:issue) { create(:issue, project: project, author: user) }
+ let(:user) { create(:user) }
+
+ before do
+ assign(:project, project)
+ assign(:issue, issue)
+ assign(:noteable, issue)
+ stub_template 'shared/issuable/_sidebar' => ''
+ stub_template 'projects/issues/_discussion' => ''
+ allow(view).to receive(:issuable_meta).and_return('')
+ end
+
+ context 'when the issue is closed' do
+ before do
+ allow(issue).to receive(:closed?).and_return(true)
+ end
+
+ context 'when the issue was moved' do
+ let(:new_issue) { create(:issue, project: project, author: user) }
+
+ before do
+ issue.moved_to = new_issue
+ end
+
+ it 'shows "Closed (moved)" if an issue has been moved' do
+ render
+
+ expect(rendered).to have_selector('.status-box-issue-closed:not(.hidden)', text: 'Closed (moved)')
+ end
+
+ it 'links "moved" to the new issue the original issue was moved to' do
+ render
+
+ expect(rendered).to have_selector("a[href=\"#{issue_path(new_issue)}\"]", text: 'moved')
+ end
+ end
+
+ it 'shows "Closed" if an issue has not been moved' do
+ render
+
+ expect(rendered).to have_selector('.status-box-issue-closed:not(.hidden)', text: 'Closed')
+ end
+ end
+
+ context 'when the issue is open' do
+ before do
+ allow(issue).to receive(:closed?).and_return(false)
+ allow(issue).to receive(:disscussion_locked).and_return(false)
+ end
+
+ it 'shows "Open" if an issue has been moved' do
+ render
+
+ expect(rendered).to have_selector('.status-box-open:not(.hidden)', text: 'Open')
+ end
+ end
+end
diff --git a/spec/views/projects/merge_requests/show.html.haml_spec.rb b/spec/views/projects/merge_requests/show.html.haml_spec.rb
index b0042be339c..d9bda1a3414 100644
--- a/spec/views/projects/merge_requests/show.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/show.html.haml_spec.rb
@@ -32,11 +32,7 @@ describe 'projects/merge_requests/show.html.haml' do
assign(:noteable, closed_merge_request)
assign(:notes, [])
assign(:pipelines, Ci::Pipeline.none)
- assign(
- :issuable_sidebar,
- MergeRequestSerializer.new(current_user: user, project: project)
- .represent(closed_merge_request, serializer: 'sidebar')
- )
+ assign(:issuable_sidebar, serialize_issuable_sidebar(user, project, closed_merge_request))
preload_view_requirements
@@ -45,6 +41,33 @@ describe 'projects/merge_requests/show.html.haml' do
current_application_settings: Gitlab::CurrentSettings.current_application_settings)
end
+ describe 'merge request assignee sidebar' do
+ context 'when assignee is allowed to merge' do
+ it 'does not show a warning icon' do
+ closed_merge_request.update(assignee_id: user.id)
+ project.add_maintainer(user)
+ assign(:issuable_sidebar, serialize_issuable_sidebar(user, project, closed_merge_request))
+
+ render
+
+ expect(rendered).not_to have_css('.cannot-be-merged')
+ end
+ end
+
+ context 'when assignee is not allowed to merge' do
+ it 'shows a warning icon' do
+ reporter = create(:user)
+ project.add_reporter(reporter)
+ closed_merge_request.update(assignee_id: reporter.id)
+ assign(:issuable_sidebar, serialize_issuable_sidebar(user, project, closed_merge_request))
+
+ render
+
+ expect(rendered).to have_css('.cannot-be-merged')
+ end
+ end
+ end
+
context 'when the merge request is closed' do
it 'shows the "Reopen" button' do
render
@@ -80,4 +103,10 @@ describe 'projects/merge_requests/show.html.haml' do
expect(rendered).to have_css('a', visible: false, text: 'Close')
end
end
+
+ def serialize_issuable_sidebar(user, project, merge_request)
+ MergeRequestSerializer
+ .new(current_user: user, project: project)
+ .represent(closed_merge_request, serializer: 'sidebar')
+ end
end
diff --git a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
index cb1b9e6f5fb..2a2539c80b5 100644
--- a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
+++ b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
@@ -7,56 +7,9 @@ describe 'projects/settings/ci_cd/_autodevops_form' do
assign :project, project
end
- context 'when kubernetes is not active' do
- context 'when auto devops domain is not defined' do
- it 'shows warning message' do
- render
+ it 'shows a warning message about Kubernetes cluster' do
+ render
- expect(rendered).to have_css('.auto-devops-warning-message')
- expect(rendered).to have_text('Auto Review Apps and Auto Deploy need a domain name and a')
- expect(rendered).to have_link('Kubernetes cluster')
- end
- end
-
- context 'when auto devops domain is defined' do
- before do
- project.build_auto_devops(domain: 'example.com')
- end
-
- it 'shows warning message' do
- render
-
- expect(rendered).to have_css('.auto-devops-warning-message')
- expect(rendered).to have_text('Auto Review Apps and Auto Deploy need a')
- expect(rendered).to have_link('Kubernetes cluster')
- end
- end
- end
-
- context 'when kubernetes is active' do
- before do
- create(:kubernetes_service, project: project)
- end
-
- context 'when auto devops domain is not defined' do
- it 'shows warning message' do
- render
-
- expect(rendered).to have_css('.auto-devops-warning-message')
- expect(rendered).to have_text('Auto Review Apps and Auto Deploy need a domain name to work correctly.')
- end
- end
-
- context 'when auto devops domain is defined' do
- before do
- project.build_auto_devops(domain: 'example.com')
- end
-
- it 'does not show warning message' do
- render
-
- expect(rendered).not_to have_css('.auto-devops-warning-message')
- end
- end
+ expect(rendered).to have_text('You must add a Kubernetes cluster integration to this project with a domain in order for your deployment strategy to work correctly.')
end
end
diff --git a/spec/views/projects/settings/operations/show.html.haml_spec.rb b/spec/views/projects/settings/operations/show.html.haml_spec.rb
new file mode 100644
index 00000000000..1bca8bba940
--- /dev/null
+++ b/spec/views/projects/settings/operations/show.html.haml_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'rails_helper'
+
+describe 'projects/settings/operations/show' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ assign :project, project
+ end
+
+ describe 'Operations > Error Tracking' do
+ before do
+ project.add_reporter(user)
+
+ allow(view).to receive(:error_tracking_setting)
+ .and_return(error_tracking_setting)
+ allow(view).to receive(:current_user).and_return(user)
+ end
+
+ let!(:error_tracking_setting) do
+ create(:project_error_tracking_setting, project: project)
+ end
+
+ context 'Settings page ' do
+ it 'renders the Operations Settings page' do
+ render
+
+ expect(rendered).to have_content _('Error Tracking')
+ expect(rendered).to have_content _('To link Sentry to GitLab, enter your Sentry URL and Auth Token')
+ end
+ end
+ end
+end
diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb
index acd8da11d8d..ccb26849e67 100644
--- a/spec/workers/build_finished_worker_spec.rb
+++ b/spec/workers/build_finished_worker_spec.rb
@@ -26,5 +26,24 @@ describe BuildFinishedWorker do
.not_to raise_error
end
end
+
+ it 'schedules a ChatNotification job for a chat build' do
+ build = create(:ci_build, :success, pipeline: create(:ci_pipeline, source: :chat))
+
+ expect(ChatNotificationWorker)
+ .to receive(:perform_async)
+ .with(build.id)
+
+ described_class.new.perform(build.id)
+ end
+
+ it 'does not schedule a ChatNotification job for a regular build' do
+ build = create(:ci_build, :success, pipeline: create(:ci_pipeline))
+
+ expect(ChatNotificationWorker)
+ .not_to receive(:perform_async)
+
+ described_class.new.perform(build.id)
+ end
end
end
diff --git a/spec/workers/chat_notification_worker_spec.rb b/spec/workers/chat_notification_worker_spec.rb
new file mode 100644
index 00000000000..91695674f5d
--- /dev/null
+++ b/spec/workers/chat_notification_worker_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ChatNotificationWorker do
+ let(:worker) { described_class.new }
+ let(:chat_build) do
+ create(:ci_build, pipeline: create(:ci_pipeline, source: :chat))
+ end
+
+ describe '#perform' do
+ it 'does nothing when the build no longer exists' do
+ expect(worker).not_to receive(:send_response)
+
+ worker.perform(-1)
+ end
+
+ it 'sends a response for an existing build' do
+ expect(worker)
+ .to receive(:send_response)
+ .with(an_instance_of(Ci::Build))
+
+ worker.perform(chat_build.id)
+ end
+
+ it 'reschedules the job if the trace sections could not be found' do
+ expect(worker)
+ .to receive(:send_response)
+ .and_raise(Gitlab::Chat::Output::MissingBuildSectionError)
+
+ expect(described_class)
+ .to receive(:perform_in)
+ .with(described_class::RESCHEDULE_INTERVAL, chat_build.id)
+
+ worker.perform(chat_build.id)
+ end
+ end
+
+ describe '#send_response' do
+ context 'when a responder could not be found' do
+ it 'does nothing' do
+ expect(Gitlab::Chat::Responder)
+ .to receive(:responder_for)
+ .with(chat_build)
+ .and_return(nil)
+
+ expect(worker.send_response(chat_build)).to be_nil
+ end
+ end
+
+ context 'when a responder could be found' do
+ let(:responder) { double(:responder) }
+
+ before do
+ allow(Gitlab::Chat::Responder)
+ .to receive(:responder_for)
+ .with(chat_build)
+ .and_return(responder)
+ end
+
+ it 'sends the response for a succeeded build' do
+ output = double(:output, to_s: 'this is the build output')
+
+ expect(chat_build)
+ .to receive(:success?)
+ .and_return(true)
+
+ expect(responder)
+ .to receive(:success)
+ .with(an_instance_of(String))
+
+ expect(Gitlab::Chat::Output)
+ .to receive(:new)
+ .with(chat_build)
+ .and_return(output)
+
+ worker.send_response(chat_build)
+ end
+
+ it 'sends the response for a failed build' do
+ expect(chat_build)
+ .to receive(:success?)
+ .and_return(false)
+
+ expect(responder).to receive(:failure)
+
+ worker.send_response(chat_build)
+ end
+ end
+ end
+end
diff --git a/spec/workers/cleanup_container_repository_worker_spec.rb b/spec/workers/cleanup_container_repository_worker_spec.rb
new file mode 100644
index 00000000000..5bee7294010
--- /dev/null
+++ b/spec/workers/cleanup_container_repository_worker_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe CleanupContainerRepositoryWorker, :clean_gitlab_redis_shared_state do
+ let(:repository) { create(:container_repository) }
+ let(:project) { repository.project }
+ let(:user) { project.owner }
+ let(:params) { { key: 'value' } }
+
+ subject { described_class.new }
+
+ describe '#perform' do
+ let(:service) { instance_double(Projects::ContainerRepository::CleanupTagsService) }
+
+ before do
+ allow(Projects::ContainerRepository::CleanupTagsService).to receive(:new)
+ .with(project, user, params).and_return(service)
+ end
+
+ it 'executes the destroy service' do
+ expect(service).to receive(:execute)
+
+ subject.perform(user.id, repository.id, params)
+ end
+
+ it 'does not raise error when user could not be found' do
+ expect do
+ subject.perform(-1, repository.id, params)
+ end.not_to raise_error
+ end
+
+ it 'does not raise error when repository could not be found' do
+ expect do
+ subject.perform(user.id, -1, params)
+ end.not_to raise_error
+ end
+
+ context 'when executed twice in short period' do
+ it 'executes service only for the first time' do
+ expect(service).to receive(:execute).once
+
+ 2.times { subject.perform(user.id, repository.id, params) }
+ end
+ end
+ end
+end
diff --git a/spec/workers/expire_build_artifacts_worker_spec.rb b/spec/workers/expire_build_artifacts_worker_spec.rb
index b47b4a02a68..27995cf1611 100644
--- a/spec/workers/expire_build_artifacts_worker_spec.rb
+++ b/spec/workers/expire_build_artifacts_worker_spec.rb
@@ -11,6 +11,7 @@ describe ExpireBuildArtifactsWorker do
describe '#perform' do
before do
+ stub_feature_flags(ci_new_expire_job_artifacts_service: false)
build
end
@@ -47,4 +48,17 @@ describe ExpireBuildArtifactsWorker do
Sidekiq::Queues.jobs_by_worker['ExpireBuildInstanceArtifactsWorker']
end
end
+
+ describe '#perform with ci_new_expire_job_artifacts_service feature flag' do
+ before do
+ stub_feature_flags(ci_new_expire_job_artifacts_service: true)
+ end
+
+ it 'executes a service' do
+ expect_any_instance_of(Ci::DestroyExpiredJobArtifactsService).to receive(:execute)
+ expect(ExpireBuildInstanceArtifactsWorker).not_to receive(:bulk_perform_async)
+
+ worker.perform
+ end
+ end
end
diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb
index a159f24f876..4895a968d6e 100644
--- a/spec/workers/git_garbage_collect_worker_spec.rb
+++ b/spec/workers/git_garbage_collect_worker_spec.rb
@@ -71,6 +71,17 @@ describe GitGarbageCollectWorker do
subject.perform(project.id)
end
+
+ context 'when the repository has joined a pool' do
+ let!(:pool) { create(:pool_repository, :ready) }
+ let(:project) { pool.source_project }
+
+ it 'ensures the repositories are linked' do
+ expect_any_instance_of(PoolRepository).to receive(:link_repository).once
+
+ subject.perform(project.id)
+ end
+ end
end
context 'when no lease can be obtained' do
diff --git a/spec/workers/hashed_storage/migrator_worker_spec.rb b/spec/workers/hashed_storage/migrator_worker_spec.rb
new file mode 100644
index 00000000000..a85f820a3eb
--- /dev/null
+++ b/spec/workers/hashed_storage/migrator_worker_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe HashedStorage::MigratorWorker do
+ subject(:worker) { described_class.new }
+ let(:projects) { create_list(:project, 2, :legacy_storage, :empty_repo) }
+ let(:ids) { projects.map(&:id) }
+
+ describe '#perform' do
+ it 'delegates to MigratorService' do
+ expect_any_instance_of(Gitlab::HashedStorage::Migrator).to receive(:bulk_migrate).with(start: 5, finish: 10)
+
+ worker.perform(5, 10)
+ end
+
+ it 'migrates projects in the specified range' do
+ perform_enqueued_jobs do
+ worker.perform(ids.min, ids.max)
+ end
+
+ projects.each do |project|
+ expect(project.reload.hashed_storage?(:attachments)).to be_truthy
+ end
+ end
+ end
+end
diff --git a/spec/workers/hashed_storage/project_migrate_worker_spec.rb b/spec/workers/hashed_storage/project_migrate_worker_spec.rb
new file mode 100644
index 00000000000..340e722aa7e
--- /dev/null
+++ b/spec/workers/hashed_storage/project_migrate_worker_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+describe HashedStorage::ProjectMigrateWorker, :clean_gitlab_redis_shared_state do
+ include ExclusiveLeaseHelpers
+
+ describe '#perform' do
+ let(:project) { create(:project, :empty_repo, :legacy_storage) }
+ let(:lease_key) { "project_migrate_hashed_storage_worker:#{project.id}" }
+ let(:lease_timeout) { described_class::LEASE_TIMEOUT }
+ let(:migration_service) { ::Projects::HashedStorage::MigrationService }
+
+ it 'skips when project no longer exists' do
+ expect(migration_service).not_to receive(:new)
+
+ subject.perform(-1)
+ end
+
+ it 'skips when project is pending delete' do
+ pending_delete_project = create(:project, :empty_repo, pending_delete: true)
+
+ expect(migration_service).not_to receive(:new)
+
+ subject.perform(pending_delete_project.id)
+ end
+
+ it 'delegates migration to service class when we have exclusive lease' do
+ stub_exclusive_lease(lease_key, 'uuid', timeout: lease_timeout)
+
+ service_spy = spy
+
+ allow(migration_service)
+ .to receive(:new).with(project, project.full_path, logger: subject.logger)
+ .and_return(service_spy)
+
+ subject.perform(project.id)
+
+ expect(service_spy).to have_received(:execute)
+ end
+
+ it 'skips when it cant acquire the exclusive lease' do
+ stub_exclusive_lease_taken(lease_key, timeout: lease_timeout)
+
+ expect(migration_service).not_to receive(:new)
+
+ subject.perform(project.id)
+ end
+ end
+end
diff --git a/spec/workers/hashed_storage/project_rollback_worker_spec.rb b/spec/workers/hashed_storage/project_rollback_worker_spec.rb
new file mode 100644
index 00000000000..d833553c0ec
--- /dev/null
+++ b/spec/workers/hashed_storage/project_rollback_worker_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe HashedStorage::ProjectRollbackWorker, :clean_gitlab_redis_shared_state do
+ include ExclusiveLeaseHelpers
+
+ describe '#perform' do
+ let(:project) { create(:project, :empty_repo) }
+ let(:lease_key) { "project_migrate_hashed_storage_worker:#{project.id}" }
+ let(:lease_timeout) { described_class::LEASE_TIMEOUT }
+ let(:rollback_service) { ::Projects::HashedStorage::RollbackService }
+
+ it 'skips when project no longer exists' do
+ expect(rollback_service).not_to receive(:new)
+
+ subject.perform(-1)
+ end
+
+ it 'skips when project is pending delete' do
+ pending_delete_project = create(:project, :empty_repo, pending_delete: true)
+
+ expect(rollback_service).not_to receive(:new)
+
+ subject.perform(pending_delete_project.id)
+ end
+
+ it 'delegates rollback to service class when have exclusive lease' do
+ stub_exclusive_lease(lease_key, 'uuid', timeout: lease_timeout)
+
+ service_spy = spy
+
+ allow(rollback_service)
+ .to receive(:new).with(project, project.disk_path, logger: subject.logger)
+ .and_return(service_spy)
+
+ subject.perform(project.id)
+
+ expect(service_spy).to have_received(:execute)
+ end
+
+ it 'skips when it cant acquire the exclusive lease' do
+ stub_exclusive_lease_taken(lease_key, timeout: lease_timeout)
+
+ expect(rollback_service).not_to receive(:new)
+
+ subject.perform(project.id)
+ end
+ end
+end
diff --git a/spec/workers/hashed_storage/rollbacker_worker_spec.rb b/spec/workers/hashed_storage/rollbacker_worker_spec.rb
new file mode 100644
index 00000000000..4055f380978
--- /dev/null
+++ b/spec/workers/hashed_storage/rollbacker_worker_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe HashedStorage::RollbackerWorker do
+ subject(:worker) { described_class.new }
+ let(:projects) { create_list(:project, 2, :empty_repo) }
+ let(:ids) { projects.map(&:id) }
+
+ describe '#perform' do
+ it 'delegates to MigratorService' do
+ expect_any_instance_of(Gitlab::HashedStorage::Migrator).to receive(:bulk_rollback).with(start: 5, finish: 10)
+
+ worker.perform(5, 10)
+ end
+
+ it 'rollsback projects in the specified range' do
+ perform_enqueued_jobs do
+ worker.perform(ids.min, ids.max)
+ end
+
+ projects.each do |project|
+ expect(project.reload.legacy_storage?).to be_truthy
+ end
+ end
+ end
+end
diff --git a/spec/workers/import_issues_csv_worker_spec.rb b/spec/workers/import_issues_csv_worker_spec.rb
new file mode 100644
index 00000000000..89370c4890d
--- /dev/null
+++ b/spec/workers/import_issues_csv_worker_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ImportIssuesCsvWorker do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:upload) { create(:upload) }
+
+ let(:worker) { described_class.new }
+
+ describe '#perform' do
+ it 'calls #execute on Issues::ImportCsvService and destroys upload' do
+ expect_any_instance_of(Issues::ImportCsvService).to receive(:execute).and_return({ success: 5, errors: [], valid_file: true })
+
+ worker.perform(user.id, project.id, upload.id)
+
+ expect { upload.reload }.to raise_error ActiveRecord::RecordNotFound
+ end
+ end
+end
diff --git a/spec/workers/mail_scheduler/notification_service_worker_spec.rb b/spec/workers/mail_scheduler/notification_service_worker_spec.rb
index f725c8763a0..5cfba01850c 100644
--- a/spec/workers/mail_scheduler/notification_service_worker_spec.rb
+++ b/spec/workers/mail_scheduler/notification_service_worker_spec.rb
@@ -9,6 +9,10 @@ describe MailScheduler::NotificationServiceWorker do
ActiveJob::Arguments.serialize(args)
end
+ def deserialize(args)
+ ActiveJob::Arguments.deserialize(args)
+ end
+
describe '#perform' do
it 'deserializes arguments from global IDs' do
expect(worker.notification_service).to receive(method).with(key)
@@ -17,10 +21,21 @@ describe MailScheduler::NotificationServiceWorker do
end
context 'when the arguments cannot be deserialized' do
- it 'does nothing' do
- expect(worker.notification_service).not_to receive(method)
+ context 'when the arguments are not deserializeable' do
+ it 'raises exception' do
+ expect(worker.notification_service).not_to receive(method)
+ expect { worker.perform(method, key.to_global_id.to_s.succ) }.to raise_exception(ArgumentError)
+ end
+ end
+
+ context 'when the arguments are deserializeable' do
+ it 'does nothing' do
+ serialized_arguments = *serialize(key)
+ key.destroy!
- worker.perform(method, key.to_global_id.to_s.succ)
+ expect(worker.notification_service).not_to receive(method)
+ expect { worker.perform(method, serialized_arguments) }.not_to raise_exception
+ end
end
end
@@ -31,13 +46,48 @@ describe MailScheduler::NotificationServiceWorker do
end
end
- describe '.perform_async' do
+ describe '.perform_async', :sidekiq do
+ around do |example|
+ Sidekiq::Testing.fake! { example.run }
+ end
+
it 'serializes arguments as global IDs when scheduling' do
- Sidekiq::Testing.fake! do
- described_class.perform_async(method, key)
+ described_class.perform_async(method, key)
+
+ expect(described_class.jobs.count).to eq(1)
+ expect(described_class.jobs.first).to include('args' => [method, *serialize(key)])
+ end
+
+ context 'with ActiveController::Parameters' do
+ let(:parameters) { ActionController::Parameters.new(hash) }
+
+ let(:hash) do
+ {
+ "nested" => {
+ "hash" => true
+ }
+ }
+ end
+
+ context 'when permitted' do
+ before do
+ parameters.permit!
+ end
+
+ it 'serializes as a serializable Hash' do
+ described_class.perform_async(method, parameters)
+
+ expect(described_class.jobs.count).to eq(1)
+ expect(deserialize(described_class.jobs.first['args']))
+ .to eq([method, hash])
+ end
+ end
- expect(described_class.jobs.count).to eq(1)
- expect(described_class.jobs.first).to include('args' => [method, *serialize(key)])
+ context 'when not permitted' do
+ it 'fails to serialize' do
+ expect { described_class.perform_async(method, parameters) }
+ .to raise_error(ActionController::UnfilteredParameters)
+ end
end
end
end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index 9176eb12b12..caae46a3175 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -141,11 +141,18 @@ describe PostReceive do
let(:gl_repository) { "wiki-#{project.id}" }
it 'updates project activity' do
- described_class.new.perform(gl_repository, key_id, base64_changes)
+ # Force Project#set_timestamps_for_create to initialize timestamps
+ project
- expect { project.reload }
- .to change(project, :last_activity_at)
- .and change(project, :last_repository_updated_at)
+ # MySQL drops milliseconds in the timestamps, so advance at least
+ # a second to ensure we see changes.
+ Timecop.freeze(1.second.from_now) do
+ expect do
+ described_class.new.perform(gl_repository, key_id, base64_changes)
+ project.reload
+ end.to change(project, :last_activity_at)
+ .and change(project, :last_repository_updated_at)
+ end
end
end
diff --git a/spec/workers/project_daily_statistics_worker_spec.rb b/spec/workers/project_daily_statistics_worker_spec.rb
new file mode 100644
index 00000000000..8640add99e5
--- /dev/null
+++ b/spec/workers/project_daily_statistics_worker_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe ProjectDailyStatisticsWorker, '#perform' do
+ let(:worker) { described_class.new }
+ let(:project) { create(:project) }
+
+ describe '#perform' do
+ context 'with a non-existing project' do
+ it 'does nothing' do
+ expect(Projects::FetchStatisticsIncrementService).not_to receive(:new)
+
+ worker.perform(-1)
+ end
+ end
+
+ context 'with an existing project without a repository' do
+ it 'does nothing' do
+ expect(Projects::FetchStatisticsIncrementService).not_to receive(:new)
+
+ worker.perform(project.id)
+ end
+ end
+
+ it 'calls daily_statistics_service with the given project' do
+ project = create(:project, :repository)
+
+ expect_next_instance_of(Projects::FetchStatisticsIncrementService, project) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ worker.perform(project.id)
+ end
+ end
+end
diff --git a/spec/workers/project_migrate_hashed_storage_worker_spec.rb b/spec/workers/project_migrate_hashed_storage_worker_spec.rb
deleted file mode 100644
index 3703320418b..00000000000
--- a/spec/workers/project_migrate_hashed_storage_worker_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'spec_helper'
-
-describe ProjectMigrateHashedStorageWorker, :clean_gitlab_redis_shared_state do
- include ExclusiveLeaseHelpers
-
- describe '#perform' do
- let(:project) { create(:project, :empty_repo) }
- let(:lease_key) { "project_migrate_hashed_storage_worker:#{project.id}" }
- let(:lease_timeout) { ProjectMigrateHashedStorageWorker::LEASE_TIMEOUT }
-
- it 'skips when project no longer exists' do
- expect(::Projects::HashedStorageMigrationService).not_to receive(:new)
-
- subject.perform(-1)
- end
-
- it 'skips when project is pending delete' do
- pending_delete_project = create(:project, :empty_repo, pending_delete: true)
-
- expect(::Projects::HashedStorageMigrationService).not_to receive(:new)
-
- subject.perform(pending_delete_project.id)
- end
-
- it 'delegates removal to service class when have exclusive lease' do
- stub_exclusive_lease(lease_key, 'uuid', timeout: lease_timeout)
-
- migration_service = spy
-
- allow(::Projects::HashedStorageMigrationService)
- .to receive(:new).with(project, project.full_path, logger: subject.logger)
- .and_return(migration_service)
-
- subject.perform(project.id)
-
- expect(migration_service).to have_received(:execute)
- end
-
- it 'skips when dont have lease when dont have exclusive lease' do
- stub_exclusive_lease_taken(lease_key, timeout: lease_timeout)
-
- expect(::Projects::HashedStorageMigrationService).not_to receive(:new)
-
- subject.perform(project.id)
- end
- end
-end
diff --git a/spec/workers/prune_old_events_worker_spec.rb b/spec/workers/prune_old_events_worker_spec.rb
index b999a6fd5b6..ea2b6ae229e 100644
--- a/spec/workers/prune_old_events_worker_spec.rb
+++ b/spec/workers/prune_old_events_worker_spec.rb
@@ -5,8 +5,8 @@ describe PruneOldEventsWorker do
let(:user) { create(:user) }
let!(:expired_event) { create(:event, :closed, author: user, created_at: 25.months.ago) }
- let!(:not_expired_1_day_event) { create(:event, :closed, author: user, created_at: 1.day.ago) }
- let!(:not_expired_13_month_event) { create(:event, :closed, author: user, created_at: 13.months.ago) }
+ let!(:not_expired_1_day_event) { create(:event, :closed, author: user, created_at: 1.day.ago) }
+ let!(:not_expired_13_month_event) { create(:event, :closed, author: user, created_at: 13.months.ago) }
let!(:not_expired_2_years_event) { create(:event, :closed, author: user, created_at: 2.years.ago) }
it 'prunes events older than 2 years' do
diff --git a/spec/workers/remote_mirror_notification_worker_spec.rb b/spec/workers/remote_mirror_notification_worker_spec.rb
new file mode 100644
index 00000000000..e3db10ed645
--- /dev/null
+++ b/spec/workers/remote_mirror_notification_worker_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe RemoteMirrorNotificationWorker, :mailer do
+ set(:project) { create(:project, :repository, :remote_mirror) }
+ set(:mirror) { project.remote_mirrors.first }
+
+ describe '#execute' do
+ it 'calls NotificationService#remote_mirror_update_failed when the mirror exists' do
+ mirror.update_column(:last_error, "There was a problem fetching")
+
+ expect(NotificationService).to receive_message_chain(:new, :remote_mirror_update_failed)
+
+ subject.perform(mirror.id)
+
+ expect(mirror.reload.error_notification_sent?).to be_truthy
+ end
+
+ it 'does nothing when the mirror has no errors' do
+ expect(NotificationService).not_to receive(:new)
+
+ subject.perform(mirror.id)
+ end
+
+ it 'does nothing when the mirror does not exist' do
+ expect(NotificationService).not_to receive(:new)
+
+ subject.perform(RemoteMirror.maximum(:id).to_i.succ)
+ end
+
+ it 'does nothing when a notification has already been sent' do
+ mirror.update_columns(last_error: "There was a problem fetching",
+ error_notification_sent: true)
+
+ expect(NotificationService).not_to receive(:new)
+
+ subject.perform(mirror.id)
+ end
+ end
+end
diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb
index 781f91ac9ca..31bfe88d0bd 100644
--- a/spec/workers/repository_fork_worker_spec.rb
+++ b/spec/workers/repository_fork_worker_spec.rb
@@ -24,12 +24,7 @@ describe RepositoryForkWorker do
end
def expect_fork_repository
- expect(shell).to receive(:fork_repository).with(
- 'default',
- project.disk_path,
- forked_project.repository_storage,
- forked_project.disk_path
- )
+ expect(shell).to receive(:fork_repository).with(project, forked_project)
end
describe 'when a worker was reset without cleanup' do
diff --git a/spec/workers/repository_update_remote_mirror_worker_spec.rb b/spec/workers/repository_update_remote_mirror_worker_spec.rb
index d73b0b53713..b582a3650b6 100644
--- a/spec/workers/repository_update_remote_mirror_worker_spec.rb
+++ b/spec/workers/repository_update_remote_mirror_worker_spec.rb
@@ -22,6 +22,13 @@ describe RepositoryUpdateRemoteMirrorWorker do
expect { subject.perform(remote_mirror.id, Time.now) }.to change { remote_mirror.reload.update_status }.to('finished')
end
+ it 'resets the notification flag upon success' do
+ expect_any_instance_of(Projects::UpdateRemoteMirrorService).to receive(:execute).with(remote_mirror).and_return(status: :success)
+ remote_mirror.update_column(:error_notification_sent, true)
+
+ expect { subject.perform(remote_mirror.id, Time.now) }.to change { remote_mirror.reload.error_notification_sent }.to(false)
+ end
+
it 'sets status as failed when update remote mirror service executes with errors' do
error_message = 'fail!'
diff --git a/spec/workers/storage_migrator_worker_spec.rb b/spec/workers/storage_migrator_worker_spec.rb
deleted file mode 100644
index 808084c8f7c..00000000000
--- a/spec/workers/storage_migrator_worker_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-require 'spec_helper'
-
-describe StorageMigratorWorker do
- subject(:worker) { described_class.new }
- let(:projects) { create_list(:project, 2, :legacy_storage, :empty_repo) }
- let(:ids) { projects.map(&:id) }
-
- describe '#perform' do
- it 'delegates to MigratorService' do
- expect_any_instance_of(Gitlab::HashedStorage::Migrator).to receive(:bulk_migrate).with(5, 10)
-
- worker.perform(5, 10)
- end
-
- it 'migrates projects in the specified range' do
- perform_enqueued_jobs do
- worker.perform(ids.min, ids.max)
- end
-
- projects.each do |project|
- expect(project.reload.hashed_storage?(:attachments)).to be_truthy
- end
- end
- end
-end
diff --git a/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb
index a2bc264b0f6..d20d926f5a0 100644
--- a/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb
+++ b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb
@@ -18,20 +18,20 @@ describe UpdateHeadPipelineForMergeRequestWorker do
context 'when merge request sha does not equal pipeline sha' do
before do
- merge_request.merge_request_diff.update(head_commit_sha: 'different_sha')
+ merge_request.merge_request_diff.update(head_commit_sha: Digest::SHA1.hexdigest(SecureRandom.hex))
end
- it 'does not update head_pipeline_id' do
- expect { subject.perform(merge_request.id) }.not_to raise_error
-
- expect(merge_request.reload.head_pipeline_id).to eq(nil)
+ it 'does not update head pipeline' do
+ expect { subject.perform(merge_request.id) }
+ .not_to change { merge_request.reload.head_pipeline_id }
end
end
end
context 'when pipeline does not exist for the source project and branch' do
it 'does not update the head_pipeline_id of the merge_request' do
- expect { subject.perform(merge_request.id) }.not_to change { merge_request.reload.head_pipeline_id }
+ expect { subject.perform(merge_request.id) }
+ .not_to change { merge_request.reload.head_pipeline_id }
end
end
@@ -39,7 +39,7 @@ describe UpdateHeadPipelineForMergeRequestWorker do
let!(:merge_request_pipeline) do
create(:ci_pipeline,
project: project,
- source: :merge_request,
+ source: :merge_request_event,
sha: latest_sha,
merge_request: merge_request)
end
diff --git a/vendor/licenses.csv b/vendor/licenses.csv
index d706d76358a..ed79ec5bac3 100644
--- a/vendor/licenses.csv
+++ b/vendor/licenses.csv
@@ -520,7 +520,6 @@ hashie-forbidden_attributes,0.1.1,MIT
he,1.1.1,MIT
health_check,2.6.0,MIT
highlight.js,9.13.1,New BSD
-hipchat,1.5.2,MIT
hmac-drbg,1.0.1,MIT
hoopy,0.1.4,MIT
html-pipeline,2.8.4,MIT
diff --git a/vendor/project_templates/dotnetcore.tar.gz b/vendor/project_templates/dotnetcore.tar.gz
new file mode 100644
index 00000000000..078ea91bbe4
--- /dev/null
+++ b/vendor/project_templates/dotnetcore.tar.gz
Binary files differ
diff --git a/vendor/project_templates/express.tar.gz b/vendor/project_templates/express.tar.gz
index fb357639a69..619e8a69695 100644
--- a/vendor/project_templates/express.tar.gz
+++ b/vendor/project_templates/express.tar.gz
Binary files differ
diff --git a/vendor/project_templates/gitbook.tar.gz b/vendor/project_templates/gitbook.tar.gz
new file mode 100644
index 00000000000..07037a83db6
--- /dev/null
+++ b/vendor/project_templates/gitbook.tar.gz
Binary files differ
diff --git a/vendor/project_templates/gomicro.tar.gz b/vendor/project_templates/gomicro.tar.gz
new file mode 100644
index 00000000000..c7d8687fdd8
--- /dev/null
+++ b/vendor/project_templates/gomicro.tar.gz
Binary files differ
diff --git a/vendor/project_templates/hexo.tar.gz b/vendor/project_templates/hexo.tar.gz
new file mode 100644
index 00000000000..033f363b8df
--- /dev/null
+++ b/vendor/project_templates/hexo.tar.gz
Binary files differ
diff --git a/vendor/project_templates/hugo.tar.gz b/vendor/project_templates/hugo.tar.gz
new file mode 100644
index 00000000000..f479ea12900
--- /dev/null
+++ b/vendor/project_templates/hugo.tar.gz
Binary files differ
diff --git a/vendor/project_templates/jekyll.tar.gz b/vendor/project_templates/jekyll.tar.gz
new file mode 100644
index 00000000000..c323ce6fac6
--- /dev/null
+++ b/vendor/project_templates/jekyll.tar.gz
Binary files differ
diff --git a/vendor/project_templates/nfgitbook.tar.gz b/vendor/project_templates/nfgitbook.tar.gz
new file mode 100644
index 00000000000..71f526ac43d
--- /dev/null
+++ b/vendor/project_templates/nfgitbook.tar.gz
Binary files differ
diff --git a/vendor/project_templates/nfhexo.tar.gz b/vendor/project_templates/nfhexo.tar.gz
new file mode 100644
index 00000000000..79cc74f8d72
--- /dev/null
+++ b/vendor/project_templates/nfhexo.tar.gz
Binary files differ
diff --git a/vendor/project_templates/nfhugo.tar.gz b/vendor/project_templates/nfhugo.tar.gz
new file mode 100644
index 00000000000..1a4aab028a8
--- /dev/null
+++ b/vendor/project_templates/nfhugo.tar.gz
Binary files differ
diff --git a/vendor/project_templates/nfjekyll.tar.gz b/vendor/project_templates/nfjekyll.tar.gz
new file mode 100644
index 00000000000..56bf955afbe
--- /dev/null
+++ b/vendor/project_templates/nfjekyll.tar.gz
Binary files differ
diff --git a/vendor/project_templates/nfplainhtml.tar.gz b/vendor/project_templates/nfplainhtml.tar.gz
new file mode 100644
index 00000000000..3a90983bd06
--- /dev/null
+++ b/vendor/project_templates/nfplainhtml.tar.gz
Binary files differ
diff --git a/vendor/project_templates/plainhtml.tar.gz b/vendor/project_templates/plainhtml.tar.gz
new file mode 100644
index 00000000000..1ed17ddc140
--- /dev/null
+++ b/vendor/project_templates/plainhtml.tar.gz
Binary files differ
diff --git a/vendor/project_templates/rails.tar.gz b/vendor/project_templates/rails.tar.gz
index 8454d2fc03b..c1f90c3f8f7 100644
--- a/vendor/project_templates/rails.tar.gz
+++ b/vendor/project_templates/rails.tar.gz
Binary files differ
diff --git a/vendor/project_templates/spring.tar.gz b/vendor/project_templates/spring.tar.gz
index 55e25fdbe7c..c1198bf13b7 100644
--- a/vendor/project_templates/spring.tar.gz
+++ b/vendor/project_templates/spring.tar.gz
Binary files differ
diff --git a/vendor/prometheus/values.yaml b/vendor/prometheus/values.yaml
index 02ec3e2d9fe..60241c65202 100644
--- a/vendor/prometheus/values.yaml
+++ b/vendor/prometheus/values.yaml
@@ -141,3 +141,105 @@ serverFiles:
- __meta_kubernetes_pod_name
action: replace
target_label: kubernetes_pod_name
+ # Sourced from Knative monitoring config: https://github.com/knative/serving/blob/master/config/monitoring/metrics/prometheus/100-prometheus-scrape-config.yaml
+ - job_name: autoscaler
+ scrape_interval: 3s
+ scrape_timeout: 3s
+ kubernetes_sd_configs:
+ - role: pod
+ relabel_configs:
+ # Scrape only the the targets matching the following metadata
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_pod_label_app, __meta_kubernetes_pod_container_port_name]
+ action: keep
+ regex: knative-serving;autoscaler;metrics
+ # Rename metadata labels to be reader friendly
+ - source_labels: [__meta_kubernetes_namespace]
+ target_label: namespace
+ - source_labels: [__meta_kubernetes_pod_name]
+ target_label: pod
+ - source_labels: [__meta_kubernetes_service_name]
+ target_label: service
+ - job_name: activator
+ scrape_interval: 3s
+ scrape_timeout: 3s
+ kubernetes_sd_configs:
+ - role: pod
+ relabel_configs:
+ # Scrape only the the targets matching the following metadata
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_pod_label_app, __meta_kubernetes_pod_container_port_name]
+ action: keep
+ regex: knative-serving;activator;metrics-port
+ # Rename metadata labels to be reader friendly
+ - source_labels: [__meta_kubernetes_namespace]
+ target_label: namespace
+ - source_labels: [__meta_kubernetes_pod_name]
+ target_label: pod
+ - source_labels: [__meta_kubernetes_service_name]
+ target_label: service
+ # Istio mesh
+ - job_name: istio-mesh
+ scrape_interval: 5s
+ kubernetes_sd_configs:
+ - role: endpoints
+ relabel_configs:
+ # Scrape only the the targets matching the following metadata
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: istio-system;istio-telemetry;prometheus
+ # Rename metadata labels to be reader friendly
+ - source_labels: [__meta_kubernetes_namespace]
+ target_label: namespace
+ - source_labels: [__meta_kubernetes_pod_name]
+ target_label: pod
+ - source_labels: [__meta_kubernetes_service_name]
+ target_label: service
+ - job_name: istio-policy
+ scrape_interval: 5s
+ kubernetes_sd_configs:
+ - role: endpoints
+ relabel_configs:
+ # Scrape only the the targets matching the following metadata
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: istio-system;istio-policy;http-monitoring
+ # Rename metadata labels to be reader friendly
+ - source_labels: [__meta_kubernetes_namespace]
+ target_label: namespace
+ - source_labels: [__meta_kubernetes_pod_name]
+ target_label: pod
+ - source_labels: [__meta_kubernetes_service_name]
+ target_label: service
+ # Istio telemetry
+ - job_name: istio-telemetry
+ scrape_interval: 5s
+ kubernetes_sd_configs:
+ - role: endpoints
+ relabel_configs:
+ # Scrape only the the targets matching the following metadata
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: istio-system;istio-telemetry;http-monitoring
+ # Rename metadata labels to be reader friendly
+ - source_labels: [__meta_kubernetes_namespace]
+ target_label: namespace
+ - source_labels: [__meta_kubernetes_pod_name]
+ target_label: pod
+ - source_labels: [__meta_kubernetes_service_name]
+ target_label: service
+ # Istio pilot
+ - job_name: istio-pilot
+ scrape_interval: 5s
+ kubernetes_sd_configs:
+ - role: endpoints
+ relabel_configs:
+ # Scrape only the the targets matching the following metadata
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: istio-system;istio-pilot;http-monitoring
+ # Rename metadata labels to be reader friendly
+ - source_labels: [__meta_kubernetes_namespace]
+ target_label: namespace
+ - source_labels: [__meta_kubernetes_pod_name]
+ target_label: pod
+ - source_labels: [__meta_kubernetes_service_name]
+ target_label: service
diff --git a/yarn.lock b/yarn.lock
index 90d3d6fb7cb..21c5ea929d1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,41 +2,41 @@
# yarn lockfile v1
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35":
+"@babel/code-frame@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8"
integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==
dependencies:
"@babel/highlight" "^7.0.0"
-"@babel/core@^7.1.2":
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.2.tgz#f8d2a9ceb6832887329a7b60f9d035791400ba4e"
- integrity sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw==
+"@babel/core@>=7.1.0", "@babel/core@^7.1.0", "@babel/core@^7.2.2":
+ version "7.3.4"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b"
+ integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==
dependencies:
"@babel/code-frame" "^7.0.0"
- "@babel/generator" "^7.1.2"
- "@babel/helpers" "^7.1.2"
- "@babel/parser" "^7.1.2"
- "@babel/template" "^7.1.2"
- "@babel/traverse" "^7.1.0"
- "@babel/types" "^7.1.2"
+ "@babel/generator" "^7.3.4"
+ "@babel/helpers" "^7.2.0"
+ "@babel/parser" "^7.3.4"
+ "@babel/template" "^7.2.2"
+ "@babel/traverse" "^7.3.4"
+ "@babel/types" "^7.3.4"
convert-source-map "^1.1.0"
- debug "^3.1.0"
- json5 "^0.5.0"
- lodash "^4.17.10"
+ debug "^4.1.0"
+ json5 "^2.1.0"
+ lodash "^4.17.11"
resolve "^1.3.2"
semver "^5.4.1"
source-map "^0.5.0"
-"@babel/generator@^7.0.0", "@babel/generator@^7.1.2":
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.1.2.tgz#fde75c072575ce7abbd97322e8fef5bae67e4630"
- integrity sha512-70A9HWLS/1RHk3Ck8tNHKxOoKQuSKocYgwDN85Pyl/RBduss6AKxUR7RIZ/lzduQMSYfWEM4DDBu6A+XGbkFig==
+"@babel/generator@^7.0.0", "@babel/generator@^7.3.4":
+ version "7.3.4"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e"
+ integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==
dependencies:
- "@babel/types" "^7.1.2"
+ "@babel/types" "^7.3.4"
jsesc "^2.5.1"
- lodash "^4.17.10"
+ lodash "^4.17.11"
source-map "^0.5.0"
trim-right "^1.0.1"
@@ -64,6 +64,17 @@
"@babel/traverse" "^7.1.0"
"@babel/types" "^7.0.0"
+"@babel/helper-create-class-features-plugin@^7.3.0":
+ version "7.3.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.0.tgz#2b01a81b3adc2b1287f9ee193688ef8dc71e718f"
+ integrity sha512-DUsQNS2CGLZZ7I3W3fvh0YpPDd6BuWJlDl+qmZZpABZHza2ErE3LxtEzLJFHFC1ZwtlAXvHhbFYbtM5o5B0WBw==
+ dependencies:
+ "@babel/helper-function-name" "^7.1.0"
+ "@babel/helper-member-expression-to-functions" "^7.0.0"
+ "@babel/helper-optimise-call-expression" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-replace-supers" "^7.2.3"
+
"@babel/helper-define-map@^7.1.0":
version "7.1.0"
resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz#3b74caec329b3c80c116290887c0dd9ae468c20c"
@@ -160,14 +171,14 @@
"@babel/traverse" "^7.1.0"
"@babel/types" "^7.0.0"
-"@babel/helper-replace-supers@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz#5fc31de522ec0ef0899dc9b3e7cf6a5dd655f362"
- integrity sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==
+"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.2.3":
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.2.3.tgz#19970020cf22677d62b3a689561dbd9644d8c5e5"
+ integrity sha512-GyieIznGUfPXPWu0yLS6U55Mz67AZD9cUk0BfirOWlPrXlBcan9Gz+vHGz+cPfuoweZSnPzPIm67VtQM0OWZbA==
dependencies:
"@babel/helper-member-expression-to-functions" "^7.0.0"
"@babel/helper-optimise-call-expression" "^7.0.0"
- "@babel/traverse" "^7.1.0"
+ "@babel/traverse" "^7.2.3"
"@babel/types" "^7.0.0"
"@babel/helper-simple-access@^7.1.0":
@@ -195,14 +206,14 @@
"@babel/traverse" "^7.1.0"
"@babel/types" "^7.0.0"
-"@babel/helpers@^7.1.2":
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.1.2.tgz#ab752e8c35ef7d39987df4e8586c63b8846234b5"
- integrity sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA==
+"@babel/helpers@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.2.0.tgz#8335f3140f3144270dc63c4732a4f8b0a50b7a21"
+ integrity sha512-Fr07N+ea0dMcMN8nFpuK6dUIT7/ivt9yKQdEEnjVS83tG2pHwPi03gYmk/tyuwONnZ+sY+GFFPlWGgCtW1hF9A==
dependencies:
"@babel/template" "^7.1.2"
- "@babel/traverse" "^7.1.0"
- "@babel/types" "^7.1.2"
+ "@babel/traverse" "^7.1.5"
+ "@babel/types" "^7.2.0"
"@babel/highlight@^7.0.0":
version "7.0.0"
@@ -213,149 +224,146 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
-"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.2":
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.1.2.tgz#85c5c47af6d244fab77bce6b9bd830e38c978409"
- integrity sha512-x5HFsW+E/nQalGMw7hu+fvPqnBeBaIr0lWJ2SG0PPL2j+Pm9lYvCrsZJGIgauPIENx0v10INIyFjmSNUD/gSqQ==
+"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4":
+ version "7.3.4"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c"
+ integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==
-"@babel/plugin-proposal-async-generator-functions@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz#41c1a702e10081456e23a7b74d891922dd1bb6ce"
- integrity sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew==
+"@babel/plugin-proposal-async-generator-functions@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e"
+ integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-remap-async-to-generator" "^7.1.0"
- "@babel/plugin-syntax-async-generators" "^7.0.0"
+ "@babel/plugin-syntax-async-generators" "^7.2.0"
-"@babel/plugin-proposal-class-properties@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.1.0.tgz#9af01856b1241db60ec8838d84691aa0bd1e8df4"
- integrity sha512-/PCJWN+CKt5v1xcGn4vnuu13QDoV+P7NcICP44BoonAJoPSGwVkgrXihFIQGiEjjPlUDBIw1cM7wYFLARS2/hw==
+"@babel/plugin-proposal-class-properties@^7.3.0":
+ version "7.3.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.0.tgz#272636bc0fa19a0bc46e601ec78136a173ea36cd"
+ integrity sha512-wNHxLkEKTQ2ay0tnsam2z7fGZUi+05ziDJflEt3AZTP3oXLKHJp9HqhfroB/vdMvt3sda9fAbq7FsG8QPDrZBg==
dependencies:
- "@babel/helper-function-name" "^7.1.0"
- "@babel/helper-member-expression-to-functions" "^7.0.0"
- "@babel/helper-optimise-call-expression" "^7.0.0"
+ "@babel/helper-create-class-features-plugin" "^7.3.0"
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-replace-supers" "^7.1.0"
- "@babel/plugin-syntax-class-properties" "^7.0.0"
-"@babel/plugin-proposal-json-strings@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz#3b4d7b5cf51e1f2e70f52351d28d44fc2970d01e"
- integrity sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q==
+"@babel/plugin-proposal-json-strings@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317"
+ integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/plugin-syntax-json-strings" "^7.0.0"
+ "@babel/plugin-syntax-json-strings" "^7.2.0"
-"@babel/plugin-proposal-object-rest-spread@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz#9a17b547f64d0676b6c9cecd4edf74a82ab85e7e"
- integrity sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==
+"@babel/plugin-proposal-object-rest-spread@^7.3.1":
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.1.tgz#f69fb6a1ea6a4e1c503994a91d9cf76f3c4b36e8"
+ integrity sha512-Nmmv1+3LqxJu/V5jU9vJmxR/KIRWFk2qLHmbB56yRRRFhlaSuOVXscX3gUmhaKgUhzA3otOHVubbIEVYsZ0eZg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
+ "@babel/plugin-syntax-object-rest-spread" "^7.2.0"
-"@babel/plugin-proposal-optional-catch-binding@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz#b610d928fe551ff7117d42c8bb410eec312a6425"
- integrity sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw==
+"@babel/plugin-proposal-optional-catch-binding@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5"
+ integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/plugin-syntax-optional-catch-binding" "^7.0.0"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
-"@babel/plugin-proposal-unicode-property-regex@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz#498b39cd72536cd7c4b26177d030226eba08cd33"
- integrity sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ==
+"@babel/plugin-proposal-private-methods@^7.3.0":
+ version "7.3.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.3.0.tgz#da373257a66525cb76544c37ab2ce4c611568841"
+ integrity sha512-j6luy/F0MX6kd71e9hz97my2tBXTa+czAz+sscJVCRmjB9e9g2D4JN+tyfcwMCXUM2afj/tYCjzNaxwWJ4SdYg==
dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.3.0"
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-regex" "^7.0.0"
- regexpu-core "^4.2.0"
-"@babel/plugin-syntax-async-generators@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz#bf0891dcdbf59558359d0c626fdc9490e20bc13c"
- integrity sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA==
+"@babel/plugin-proposal-unicode-property-regex@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz#abe7281fe46c95ddc143a65e5358647792039520"
+ integrity sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-regex" "^7.0.0"
+ regexpu-core "^4.2.0"
-"@babel/plugin-syntax-class-properties@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.0.0.tgz#e051af5d300cbfbcec4a7476e37a803489881634"
- integrity sha512-cR12g0Qzn4sgkjrbrzWy2GE7m9vMl/sFkqZ3gIpAQdrvPDnLM8180i+ANDFIXfjHo9aqp0ccJlQ0QNZcFUbf9w==
+"@babel/plugin-syntax-async-generators@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f"
+ integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-syntax-dynamic-import@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.0.0.tgz#6dfb7d8b6c3be14ce952962f658f3b7eb54c33ee"
- integrity sha512-Gt9xNyRrCHCiyX/ZxDGOcBnlJl0I3IWicpZRC4CdC0P5a/I07Ya2OAMEBU+J7GmRFVmIetqEYRko6QYRuKOESw==
+"@babel/plugin-syntax-dynamic-import@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612"
+ integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-syntax-import-meta@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.0.0.tgz#ca946b73216c29c39a55ef2d739097fee8a85d69"
- integrity sha512-FEoGvhXVAiWzpDjyZIlBGzKyNk/lnRPy7aPke3PjVkiAY0QFsvFfkjUg5diRwVfowBA8SJqvFt0ZoXNSjl70hQ==
+"@babel/plugin-syntax-import-meta@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.2.0.tgz#2333ef4b875553a3bcd1e93f8ebc09f5b9213a40"
+ integrity sha512-Hq6kFSZD7+PHkmBN8bCpHR6J8QEoCuEV/B38AIQscYjgMZkGlXB7cHNFzP5jR4RCh5545yP1ujHdmO7hAgKtBA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-syntax-json-strings@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz#0d259a68090e15b383ce3710e01d5b23f3770cbd"
- integrity sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA==
+"@babel/plugin-syntax-json-strings@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470"
+ integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-syntax-object-rest-spread@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz#37d8fbcaf216bd658ea1aebbeb8b75e88ebc549b"
- integrity sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==
+"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e"
+ integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-syntax-optional-catch-binding@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz#886f72008b3a8b185977f7cb70713b45e51ee475"
- integrity sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw==
+"@babel/plugin-syntax-optional-catch-binding@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c"
+ integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-arrow-functions@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz#a6c14875848c68a3b4b3163a486535ef25c7e749"
- integrity sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w==
+"@babel/plugin-transform-arrow-functions@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550"
+ integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-async-to-generator@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz#109e036496c51dd65857e16acab3bafdf3c57811"
- integrity sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g==
+"@babel/plugin-transform-async-to-generator@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz#68b8a438663e88519e65b776f8938f3445b1a2ff"
+ integrity sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-remap-async-to-generator" "^7.1.0"
-"@babel/plugin-transform-block-scoped-functions@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz#482b3f75103927e37288b3b67b65f848e2aa0d07"
- integrity sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ==
+"@babel/plugin-transform-block-scoped-functions@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190"
+ integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-block-scoping@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz#1745075edffd7cdaf69fab2fb6f9694424b7e9bc"
- integrity sha512-GWEMCrmHQcYWISilUrk9GDqH4enf3UmhOEbNbNrlNAX1ssH3MsS1xLOS6rdjRVPgA7XXVPn87tRkdTEoA/dxEg==
+"@babel/plugin-transform-block-scoping@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz#f17c49d91eedbcdf5dd50597d16f5f2f770132d4"
+ integrity sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
lodash "^4.17.10"
-"@babel/plugin-transform-classes@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz#ab3f8a564361800cbc8ab1ca6f21108038432249"
- integrity sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==
+"@babel/plugin-transform-classes@^7.2.0":
+ version "7.2.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.2.tgz#6c90542f210ee975aa2aa8c8b5af7fa73a126953"
+ integrity sha512-gEZvgTy1VtcDOaQty1l10T3jQmJKlNVxLDCs+3rCVPr6nMkODLELxViq5X9l+rfxbie3XrfrMCYYY6eX3aOcOQ==
dependencies:
"@babel/helper-annotate-as-pure" "^7.0.0"
"@babel/helper-define-map" "^7.1.0"
@@ -366,99 +374,106 @@
"@babel/helper-split-export-declaration" "^7.0.0"
globals "^11.1.0"
-"@babel/plugin-transform-computed-properties@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz#2fbb8900cd3e8258f2a2ede909b90e7556185e31"
- integrity sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA==
+"@babel/plugin-transform-computed-properties@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da"
+ integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-destructuring@^7.0.0":
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.1.2.tgz#5fa77d473f5a0a3f5266ad7ce2e8c995a164d60a"
- integrity sha512-cvToXvp/OsYxtEn57XJu9BvsGSEYjAh9UeUuXpoi7x6QHB7YdWyQ4lRU/q0Fu1IJNT0o0u4FQ1DMQBzJ8/8vZg==
+"@babel/plugin-transform-destructuring@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.2.0.tgz#e75269b4b7889ec3a332cd0d0c8cff8fed0dc6f3"
+ integrity sha512-coVO2Ayv7g0qdDbrNiadE4bU7lvCd9H539m2gMknyVjjMdwF/iCOM7R+E8PkntoqLkltO0rk+3axhpp/0v68VQ==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-dotall-regex@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz#73a24da69bc3c370251f43a3d048198546115e58"
- integrity sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig==
+"@babel/plugin-transform-dotall-regex@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz#f0aabb93d120a8ac61e925ea0ba440812dbe0e49"
+ integrity sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-regex" "^7.0.0"
regexpu-core "^4.1.3"
-"@babel/plugin-transform-duplicate-keys@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz#a0601e580991e7cace080e4cf919cfd58da74e86"
- integrity sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ==
+"@babel/plugin-transform-duplicate-keys@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz#d952c4930f312a4dbfff18f0b2914e60c35530b3"
+ integrity sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-exponentiation-operator@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz#9c34c2ee7fd77e02779cfa37e403a2e1003ccc73"
- integrity sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ==
+"@babel/plugin-transform-exponentiation-operator@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008"
+ integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==
dependencies:
"@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-for-of@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz#f2ba4eadb83bd17dc3c7e9b30f4707365e1c3e39"
- integrity sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA==
+"@babel/plugin-transform-for-of@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz#ab7468befa80f764bb03d3cb5eef8cc998e1cad9"
+ integrity sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-function-name@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz#29c5550d5c46208e7f730516d41eeddd4affadbb"
- integrity sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg==
+"@babel/plugin-transform-function-name@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz#f7930362829ff99a3174c39f0afcc024ef59731a"
+ integrity sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ==
dependencies:
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-literals@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz#2aec1d29cdd24c407359c930cdd89e914ee8ff86"
- integrity sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA==
+"@babel/plugin-transform-literals@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1"
+ integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-modules-amd@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz#f9e0a7072c12e296079b5a59f408ff5b97bf86a8"
- integrity sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A==
+"@babel/plugin-transform-modules-amd@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz#82a9bce45b95441f617a24011dc89d12da7f4ee6"
+ integrity sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==
dependencies:
"@babel/helper-module-transforms" "^7.1.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-modules-commonjs@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz#0a9d86451cbbfb29bd15186306897c67f6f9a05c"
- integrity sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA==
+"@babel/plugin-transform-modules-commonjs@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz#c4f1933f5991d5145e9cfad1dfd848ea1727f404"
+ integrity sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ==
dependencies:
"@babel/helper-module-transforms" "^7.1.0"
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-simple-access" "^7.1.0"
-"@babel/plugin-transform-modules-systemjs@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0.tgz#8873d876d4fee23209decc4d1feab8f198cf2df4"
- integrity sha512-8EDKMAsitLkiF/D4Zhe9CHEE2XLh4bfLbb9/Zf3FgXYQOZyZYyg7EAel/aT2A7bHv62jwHf09q2KU/oEexr83g==
+"@babel/plugin-transform-modules-systemjs@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz#912bfe9e5ff982924c81d0937c92d24994bb9068"
+ integrity sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ==
dependencies:
"@babel/helper-hoist-variables" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-modules-umd@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz#a29a7d85d6f28c3561c33964442257cc6a21f2a8"
- integrity sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig==
+"@babel/plugin-transform-modules-umd@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae"
+ integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==
dependencies:
"@babel/helper-module-transforms" "^7.1.0"
"@babel/helper-plugin-utils" "^7.0.0"
+"@babel/plugin-transform-named-capturing-groups-regex@^7.3.0":
+ version "7.3.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz#140b52985b2d6ef0cb092ef3b29502b990f9cd50"
+ integrity sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw==
+ dependencies:
+ regexp-tree "^0.1.0"
+
"@babel/plugin-transform-new-target@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a"
@@ -466,18 +481,18 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-object-super@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz#b1ae194a054b826d8d4ba7ca91486d4ada0f91bb"
- integrity sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw==
+"@babel/plugin-transform-object-super@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz#b35d4c10f56bab5d650047dad0f1d8e8814b6598"
+ integrity sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-replace-supers" "^7.1.0"
-"@babel/plugin-transform-parameters@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz#44f492f9d618c9124026e62301c296bf606a7aed"
- integrity sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw==
+"@babel/plugin-transform-parameters@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz#0d5ad15dc805e2ea866df4dd6682bfe76d1408c2"
+ integrity sha512-kB9+hhUidIgUoBQ0MsxMewhzr8i60nMa2KgeJKQWYrqQpqcBYtnpR+JgkadZVZoaEZ/eKu9mclFaVwhRpLNSzA==
dependencies:
"@babel/helper-call-delegate" "^7.1.0"
"@babel/helper-get-function-arity" "^7.0.0"
@@ -490,130 +505,137 @@
dependencies:
regenerator-transform "^0.13.3"
-"@babel/plugin-transform-shorthand-properties@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz#85f8af592dcc07647541a0350e8c95c7bf419d15"
- integrity sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw==
+"@babel/plugin-transform-shorthand-properties@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0"
+ integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-spread@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz#93583ce48dd8c85e53f3a46056c856e4af30b49b"
- integrity sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ==
+"@babel/plugin-transform-spread@^7.2.0":
+ version "7.2.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406"
+ integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-sticky-regex@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz#30a9d64ac2ab46eec087b8530535becd90e73366"
- integrity sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw==
+"@babel/plugin-transform-sticky-regex@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1"
+ integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-regex" "^7.0.0"
-"@babel/plugin-transform-template-literals@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz#084f1952efe5b153ddae69eb8945f882c7a97c65"
- integrity sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg==
+"@babel/plugin-transform-template-literals@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz#d87ed01b8eaac7a92473f608c97c089de2ba1e5b"
+ integrity sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==
dependencies:
"@babel/helper-annotate-as-pure" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-typeof-symbol@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz#4dcf1e52e943e5267b7313bff347fdbe0f81cec9"
- integrity sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg==
+"@babel/plugin-transform-typeof-symbol@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2"
+ integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-unicode-regex@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz#c6780e5b1863a76fe792d90eded9fcd5b51d68fc"
- integrity sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw==
+"@babel/plugin-transform-unicode-regex@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz#4eb8db16f972f8abb5062c161b8b115546ade08b"
+ integrity sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-regex" "^7.0.0"
regexpu-core "^4.1.3"
-"@babel/preset-env@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.0.tgz#e67ea5b0441cfeab1d6f41e9b5c79798800e8d11"
- integrity sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==
+"@babel/preset-env@^7.3.1":
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.1.tgz#389e8ca6b17ae67aaf9a2111665030be923515db"
+ integrity sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/plugin-proposal-async-generator-functions" "^7.1.0"
- "@babel/plugin-proposal-json-strings" "^7.0.0"
- "@babel/plugin-proposal-object-rest-spread" "^7.0.0"
- "@babel/plugin-proposal-optional-catch-binding" "^7.0.0"
- "@babel/plugin-proposal-unicode-property-regex" "^7.0.0"
- "@babel/plugin-syntax-async-generators" "^7.0.0"
- "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
- "@babel/plugin-syntax-optional-catch-binding" "^7.0.0"
- "@babel/plugin-transform-arrow-functions" "^7.0.0"
- "@babel/plugin-transform-async-to-generator" "^7.1.0"
- "@babel/plugin-transform-block-scoped-functions" "^7.0.0"
- "@babel/plugin-transform-block-scoping" "^7.0.0"
- "@babel/plugin-transform-classes" "^7.1.0"
- "@babel/plugin-transform-computed-properties" "^7.0.0"
- "@babel/plugin-transform-destructuring" "^7.0.0"
- "@babel/plugin-transform-dotall-regex" "^7.0.0"
- "@babel/plugin-transform-duplicate-keys" "^7.0.0"
- "@babel/plugin-transform-exponentiation-operator" "^7.1.0"
- "@babel/plugin-transform-for-of" "^7.0.0"
- "@babel/plugin-transform-function-name" "^7.1.0"
- "@babel/plugin-transform-literals" "^7.0.0"
- "@babel/plugin-transform-modules-amd" "^7.1.0"
- "@babel/plugin-transform-modules-commonjs" "^7.1.0"
- "@babel/plugin-transform-modules-systemjs" "^7.0.0"
- "@babel/plugin-transform-modules-umd" "^7.1.0"
+ "@babel/plugin-proposal-async-generator-functions" "^7.2.0"
+ "@babel/plugin-proposal-json-strings" "^7.2.0"
+ "@babel/plugin-proposal-object-rest-spread" "^7.3.1"
+ "@babel/plugin-proposal-optional-catch-binding" "^7.2.0"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.2.0"
+ "@babel/plugin-syntax-async-generators" "^7.2.0"
+ "@babel/plugin-syntax-json-strings" "^7.2.0"
+ "@babel/plugin-syntax-object-rest-spread" "^7.2.0"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
+ "@babel/plugin-transform-arrow-functions" "^7.2.0"
+ "@babel/plugin-transform-async-to-generator" "^7.2.0"
+ "@babel/plugin-transform-block-scoped-functions" "^7.2.0"
+ "@babel/plugin-transform-block-scoping" "^7.2.0"
+ "@babel/plugin-transform-classes" "^7.2.0"
+ "@babel/plugin-transform-computed-properties" "^7.2.0"
+ "@babel/plugin-transform-destructuring" "^7.2.0"
+ "@babel/plugin-transform-dotall-regex" "^7.2.0"
+ "@babel/plugin-transform-duplicate-keys" "^7.2.0"
+ "@babel/plugin-transform-exponentiation-operator" "^7.2.0"
+ "@babel/plugin-transform-for-of" "^7.2.0"
+ "@babel/plugin-transform-function-name" "^7.2.0"
+ "@babel/plugin-transform-literals" "^7.2.0"
+ "@babel/plugin-transform-modules-amd" "^7.2.0"
+ "@babel/plugin-transform-modules-commonjs" "^7.2.0"
+ "@babel/plugin-transform-modules-systemjs" "^7.2.0"
+ "@babel/plugin-transform-modules-umd" "^7.2.0"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.3.0"
"@babel/plugin-transform-new-target" "^7.0.0"
- "@babel/plugin-transform-object-super" "^7.1.0"
- "@babel/plugin-transform-parameters" "^7.1.0"
+ "@babel/plugin-transform-object-super" "^7.2.0"
+ "@babel/plugin-transform-parameters" "^7.2.0"
"@babel/plugin-transform-regenerator" "^7.0.0"
- "@babel/plugin-transform-shorthand-properties" "^7.0.0"
- "@babel/plugin-transform-spread" "^7.0.0"
- "@babel/plugin-transform-sticky-regex" "^7.0.0"
- "@babel/plugin-transform-template-literals" "^7.0.0"
- "@babel/plugin-transform-typeof-symbol" "^7.0.0"
- "@babel/plugin-transform-unicode-regex" "^7.0.0"
- browserslist "^4.1.0"
+ "@babel/plugin-transform-shorthand-properties" "^7.2.0"
+ "@babel/plugin-transform-spread" "^7.2.0"
+ "@babel/plugin-transform-sticky-regex" "^7.2.0"
+ "@babel/plugin-transform-template-literals" "^7.2.0"
+ "@babel/plugin-transform-typeof-symbol" "^7.2.0"
+ "@babel/plugin-transform-unicode-regex" "^7.2.0"
+ browserslist "^4.3.4"
invariant "^2.2.2"
js-levenshtein "^1.1.3"
semver "^5.3.0"
-"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2":
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644"
- integrity sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==
+"@babel/standalone@^7.0.0":
+ version "7.3.4"
+ resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.3.4.tgz#b622c1e522acef91b2a14f22bdcdd4f935a1a474"
+ integrity sha512-4L9c5i4WlGqbrjOVX0Yp8TIR5cEiw1/tPYYZENW/iuO2uI6viY38U7zALidzNfGdZIwNc+A/AWqMEWKeScWkBg==
+
+"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2":
+ version "7.2.2"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907"
+ integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==
dependencies:
"@babel/code-frame" "^7.0.0"
- "@babel/parser" "^7.1.2"
- "@babel/types" "^7.1.2"
+ "@babel/parser" "^7.2.2"
+ "@babel/types" "^7.2.2"
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.1.0.tgz#503ec6669387efd182c3888c4eec07bcc45d91b2"
- integrity sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw==
+"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.2.3", "@babel/traverse@^7.3.4":
+ version "7.3.4"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06"
+ integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==
dependencies:
"@babel/code-frame" "^7.0.0"
- "@babel/generator" "^7.0.0"
+ "@babel/generator" "^7.3.4"
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-split-export-declaration" "^7.0.0"
- "@babel/parser" "^7.1.0"
- "@babel/types" "^7.0.0"
- debug "^3.1.0"
+ "@babel/parser" "^7.3.4"
+ "@babel/types" "^7.3.4"
+ debug "^4.1.0"
globals "^11.1.0"
- lodash "^4.17.10"
+ lodash "^4.17.11"
-"@babel/types@^7.0.0", "@babel/types@^7.1.2":
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.2.tgz#183e7952cf6691628afdc2e2b90d03240bac80c0"
- integrity sha512-pb1I05sZEKiSlMUV9UReaqsCPUpgbHHHu2n1piRm7JkuBkm6QxcaIzKu6FMnMtCbih/cEYTR+RGYYC96Yk9HAg==
+"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.4":
+ version "7.3.4"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed"
+ integrity sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==
dependencies:
esutils "^2.0.2"
- lodash "^4.17.10"
+ lodash "^4.17.11"
to-fast-properties "^2.0.0"
"@gitlab/csslab@^1.8.0":
@@ -636,17 +658,17 @@
eslint-plugin-promise "^4.0.1"
eslint-plugin-vue "^5.0.0"
-"@gitlab/svgs@^1.43.0":
- version "1.43.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.43.0.tgz#28dee2122d068cd3b925cd9884d97465ebaca12d"
- integrity sha512-wuN3NITmyBV9bOXsFfAjtndFrjTlH6Kf3+6aqT5kHKKLe/B4w7uTU1L9H/cyR0wGD7HbOh584a05eDcuH04fPA==
+"@gitlab/svgs@^1.54.0":
+ version "1.54.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.54.0.tgz#00320e845efd46716042cde0c348b990d4908daf"
+ integrity sha512-DR17iy8TM5IbXEacqiDP0p8SuC/J8EL+98xbfVz5BKvRsPHpeZJQNlBF/petIV5d+KWM5A9v3GZTY7uMU7z/JQ==
-"@gitlab/ui@^1.18.0":
- version "1.18.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-1.18.0.tgz#5cc591b2c7958e59fa7b1b443d4235e0e8f956c9"
- integrity sha512-JqmiRSGYmK0DbGBQJBpjeRrcgjK25rCqG6QW6/GPTVLtRjbPPZYGvVg5PyA6nJUGAnwFoeApUZVML6X3OpnV1Q==
+"@gitlab/ui@^2.2.1":
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-2.2.1.tgz#4b4f5c9234279a2ebeafc337c58eb6460aef963b"
+ integrity sha512-hxgZi1KRwd8EmVs1OeE/zcVH3GCE523GK4JWrTD8x9xPRS0O+NSIvbgqGBXp25UiG7jei9Up0X9BzZMTmZimug==
dependencies:
- babel-standalone "^6.26.0"
+ "@babel/standalone" "^7.0.0"
bootstrap-vue "^2.0.0-rc.11"
copy-to-clipboard "^3.0.8"
echarts "^4.2.0-rc.2"
@@ -657,15 +679,28 @@
vue "^2.5.21"
vue-loader "^15.4.2"
+"@mrmlnc/readdir-enhanced@^2.2.1":
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
+ integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==
+ dependencies:
+ call-me-maybe "^1.0.1"
+ glob-to-regexp "^0.3.0"
+
+"@nodelib/fs.stat@^1.1.2":
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
+ integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
+
"@sindresorhus/is@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==
-"@types/async@2.0.50":
- version "2.0.50"
- resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.50.tgz#117540e026d64e1846093abbd5adc7e27fda7bcb"
- integrity sha512-VMhZMMQgV1zsR+lX/0IBfAk+8Eb7dPVMWiQGFAt3qjo5x7Ml6b77jUo0e1C3ToD+XRDXqtrfw+6AB0uUsPEr3Q==
+"@types/anymatch@*":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.0.tgz#d1d55958d1fccc5527d4aba29fc9c4b942f563ff"
+ integrity sha512-7WcbyctkE8GTzogDb0ulRAEw7v8oIS54ft9mQTU7PfM0hp5e+8kpa+HeQ7IQrFbKtJXBKcZ4bh+Em9dTw5L6AQ==
"@types/events@*":
version "1.2.0"
@@ -706,35 +741,70 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==
-"@types/strip-bom@^3.0.0":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2"
- integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=
+"@types/tapable@*":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.4.tgz#b4ffc7dc97b498c969b360a41eee247f82616370"
+ integrity sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ==
+
+"@types/uglify-js@*":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082"
+ integrity sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ==
+ dependencies:
+ source-map "^0.6.1"
+
+"@types/unist@*", "@types/unist@^2.0.0":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.2.tgz#5dc0a7f76809b7518c0df58689cd16a19bd751c6"
+ integrity sha512-iHI60IbyfQilNubmxsq4zqSjdynlmc2Q/QvH9kjzg9+CCYVVzq1O6tc7VBzSygIwnmOt07w80IG6HDQvjv3Liw==
+
+"@types/vfile-message@*":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-1.0.1.tgz#e1e9895cc6b36c462d4244e64e6d0b6eaf65355a"
+ integrity sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==
+ dependencies:
+ "@types/node" "*"
+ "@types/unist" "*"
+
+"@types/vfile@^3.0.0":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/vfile/-/vfile-3.0.2.tgz#19c18cd232df11ce6fa6ad80259bc86c366b09b9"
+ integrity sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==
+ dependencies:
+ "@types/node" "*"
+ "@types/unist" "*"
+ "@types/vfile-message" "*"
-"@types/strip-json-comments@0.0.30":
- version "0.0.30"
- resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1"
- integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==
+"@types/webpack@^4.4.19":
+ version "4.4.23"
+ resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.4.23.tgz#059d6f4598cfd65ddee0e2db38317ef989696712"
+ integrity sha512-WswyG+2mRg0ul/ytPpCSWo+kOlVVPW/fKCBEVwqmPVC/2ffWEwhsCEQgnFbWDf8EWId2qGcpL623EjLfNTRk9A==
+ dependencies:
+ "@types/anymatch" "*"
+ "@types/node" "*"
+ "@types/tapable" "*"
+ "@types/uglify-js" "*"
+ source-map "^0.6.0"
"@types/zen-observable@^0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d"
integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg==
-"@vue/component-compiler-utils@^2.0.0":
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.2.0.tgz#bbbb7ed38a9a8a7c93abe7ef2e54a90a04b631b4"
- integrity sha512-pS4zlcdD7BvedyB+IfiTfrbi6C977UMIfulSk8r6uL0BU46ZE2+fUj/zbSNSfVxeaj9ElmnSni5OMwF9np+b+w==
+"@vue/component-compiler-utils@^2.0.0", "@vue/component-compiler-utils@^2.4.0":
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz#aa46d2a6f7647440b0b8932434d22f12371e543b"
+ integrity sha512-IHjxt7LsOFYc0DkTncB7OXJL7UzwOLPPQCfEUNyxL2qt+tF12THV+EO33O1G2Uk4feMSWua3iD39Itszx0f0bw==
dependencies:
consolidate "^0.15.1"
hash-sum "^1.0.2"
lru-cache "^4.1.2"
merge-source-map "^1.1.0"
- postcss "^6.0.20"
- postcss-selector-parser "^3.1.1"
- prettier "1.13.7"
- source-map "^0.5.6"
- vue-template-es2015-compiler "^1.6.0"
+ postcss "^7.0.14"
+ postcss-selector-parser "^5.0.0"
+ prettier "1.16.3"
+ source-map "~0.6.1"
+ vue-template-es2015-compiler "^1.9.0"
"@vue/test-utils@^1.0.0-beta.25":
version "1.0.0-beta.25"
@@ -743,151 +813,147 @@
dependencies:
lodash "^4.17.4"
-"@webassemblyjs/ast@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.6.tgz#3ef8c45b3e5e943a153a05281317474fef63e21e"
- integrity sha512-8nkZS48EVsMUU0v6F1LCIOw4RYWLm2plMtbhFTjNgeXmsTNLuU3xTRtnljt9BFQB+iPbLRobkNrCWftWnNC7wQ==
- dependencies:
- "@webassemblyjs/helper-module-context" "1.7.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
- "@webassemblyjs/wast-parser" "1.7.6"
- mamacro "^0.0.3"
-
-"@webassemblyjs/floating-point-hex-parser@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.6.tgz#7cb37d51a05c3fe09b464ae7e711d1ab3837801f"
- integrity sha512-VBOZvaOyBSkPZdIt5VBMg3vPWxouuM13dPXGWI1cBh3oFLNcFJ8s9YA7S9l4mPI7+Q950QqOmqj06oa83hNWBA==
-
-"@webassemblyjs/helper-api-error@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.6.tgz#99b7e30e66f550a2638299a109dda84a622070ef"
- integrity sha512-SCzhcQWHXfrfMSKcj8zHg1/kL9kb3aa5TN4plc/EREOs5Xop0ci5bdVBApbk2yfVi8aL+Ly4Qpp3/TRAUInjrg==
-
-"@webassemblyjs/helper-buffer@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.6.tgz#ba0648be12bbe560c25c997e175c2018df39ca3e"
- integrity sha512-1/gW5NaGsEOZ02fjnFiU8/OEEXU1uVbv2um0pQ9YVL3IHSkyk6xOwokzyqqO1qDZQUAllb+V8irtClPWntbVqw==
-
-"@webassemblyjs/helper-code-frame@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.6.tgz#5a94d21b0057b69a7403fca0c253c3aaca95b1a5"
- integrity sha512-+suMJOkSn9+vEvDvgyWyrJo5vJsWSDXZmJAjtoUq4zS4eqHyXImpktvHOZwXp1XQjO5H+YQwsBgqTQEc0J/5zg==
- dependencies:
- "@webassemblyjs/wast-printer" "1.7.6"
-
-"@webassemblyjs/helper-fsm@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.6.tgz#ae1741c6f6121213c7a0b587fb964fac492d3e49"
- integrity sha512-HCS6KN3wgxUihGBW7WFzEC/o8Eyvk0d56uazusnxXthDPnkWiMv+kGi9xXswL2cvfYfeK5yiM17z2K5BVlwypw==
-
-"@webassemblyjs/helper-module-context@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.6.tgz#116d19a51a6cebc8900ad53ca34ff8269c668c23"
- integrity sha512-e8/6GbY7OjLM+6OsN7f2krC2qYVNaSr0B0oe4lWdmq5sL++8dYDD1TFbD1TdAdWMRTYNr/Qq7ovXWzia2EbSjw==
- dependencies:
- mamacro "^0.0.3"
-
-"@webassemblyjs/helper-wasm-bytecode@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.6.tgz#98e515eaee611aa6834eb5f6a7f8f5b29fefb6f1"
- integrity sha512-PzYFCb7RjjSdAOljyvLWVqd6adAOabJW+8yRT+NWhXuf1nNZWH+igFZCUK9k7Cx7CsBbzIfXjJc7u56zZgFj9Q==
-
-"@webassemblyjs/helper-wasm-section@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.6.tgz#783835867bdd686df7a95377ab64f51a275e8333"
- integrity sha512-3GS628ppDPSuwcYlQ7cDCGr4W2n9c4hLzvnRKeuz+lGsJSmc/ADVoYpm1ts2vlB1tGHkjtQMni+yu8mHoMlKlA==
- dependencies:
- "@webassemblyjs/ast" "1.7.6"
- "@webassemblyjs/helper-buffer" "1.7.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
- "@webassemblyjs/wasm-gen" "1.7.6"
-
-"@webassemblyjs/ieee754@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.6.tgz#c34fc058f2f831fae0632a8bb9803cf2d3462eb1"
- integrity sha512-V4cIp0ruyw+hawUHwQLn6o2mFEw4t50tk530oKsYXQhEzKR+xNGDxs/SFFuyTO7X3NzEu4usA3w5jzhl2RYyzQ==
+"@webassemblyjs/ast@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace"
+ integrity sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==
+ dependencies:
+ "@webassemblyjs/helper-module-context" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/wast-parser" "1.7.11"
+
+"@webassemblyjs/floating-point-hex-parser@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz#a69f0af6502eb9a3c045555b1a6129d3d3f2e313"
+ integrity sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==
+
+"@webassemblyjs/helper-api-error@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz#c7b6bb8105f84039511a2b39ce494f193818a32a"
+ integrity sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==
+
+"@webassemblyjs/helper-buffer@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz#3122d48dcc6c9456ed982debe16c8f37101df39b"
+ integrity sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==
+
+"@webassemblyjs/helper-code-frame@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz#cf8f106e746662a0da29bdef635fcd3d1248364b"
+ integrity sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==
+ dependencies:
+ "@webassemblyjs/wast-printer" "1.7.11"
+
+"@webassemblyjs/helper-fsm@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz#df38882a624080d03f7503f93e3f17ac5ac01181"
+ integrity sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==
+
+"@webassemblyjs/helper-module-context@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz#d874d722e51e62ac202476935d649c802fa0e209"
+ integrity sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==
+
+"@webassemblyjs/helper-wasm-bytecode@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz#dd9a1e817f1c2eb105b4cf1013093cb9f3c9cb06"
+ integrity sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==
+
+"@webassemblyjs/helper-wasm-section@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz#9c9ac41ecf9fbcfffc96f6d2675e2de33811e68a"
+ integrity sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-buffer" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/wasm-gen" "1.7.11"
+
+"@webassemblyjs/ieee754@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz#c95839eb63757a31880aaec7b6512d4191ac640b"
+ integrity sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==
dependencies:
"@xtuc/ieee754" "^1.2.0"
-"@webassemblyjs/leb128@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.7.6.tgz#197f75376a29f6ed6ace15898a310d871d92f03b"
- integrity sha512-ojdlG8WpM394lBow4ncTGJoIVZ4aAtNOWHhfAM7m7zprmkVcKK+2kK5YJ9Bmj6/ketTtOn7wGSHCtMt+LzqgYQ==
+"@webassemblyjs/leb128@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.7.11.tgz#d7267a1ee9c4594fd3f7e37298818ec65687db63"
+ integrity sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==
dependencies:
"@xtuc/long" "4.2.1"
-"@webassemblyjs/utf8@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.7.6.tgz#eb62c66f906af2be70de0302e29055d25188797d"
- integrity sha512-oId+tLxQ+AeDC34ELRYNSqJRaScB0TClUU6KQfpB8rNT6oelYlz8axsPhf6yPTg7PBJ/Z5WcXmUYiHEWgbbHJw==
-
-"@webassemblyjs/wasm-edit@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.6.tgz#fa41929160cd7d676d4c28ecef420eed5b3733c5"
- integrity sha512-pTNjLO3o41v/Vz9VFLl+I3YLImpCSpodFW77pNoH4agn5I6GgSxXHXtvWDTvYJFty0jSeXZWLEmbaSIRUDlekg==
- dependencies:
- "@webassemblyjs/ast" "1.7.6"
- "@webassemblyjs/helper-buffer" "1.7.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
- "@webassemblyjs/helper-wasm-section" "1.7.6"
- "@webassemblyjs/wasm-gen" "1.7.6"
- "@webassemblyjs/wasm-opt" "1.7.6"
- "@webassemblyjs/wasm-parser" "1.7.6"
- "@webassemblyjs/wast-printer" "1.7.6"
-
-"@webassemblyjs/wasm-gen@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.6.tgz#695ac38861ab3d72bf763c8c75e5f087ffabc322"
- integrity sha512-mQvFJVumtmRKEUXMohwn8nSrtjJJl6oXwF3FotC5t6e2hlKMh8sIaW03Sck2MDzw9xPogZD7tdP5kjPlbH9EcQ==
- dependencies:
- "@webassemblyjs/ast" "1.7.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
- "@webassemblyjs/ieee754" "1.7.6"
- "@webassemblyjs/leb128" "1.7.6"
- "@webassemblyjs/utf8" "1.7.6"
-
-"@webassemblyjs/wasm-opt@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.6.tgz#fbafa78e27e1a75ab759a4b658ff3d50b4636c21"
- integrity sha512-go44K90fSIsDwRgtHhX14VtbdDPdK2sZQtZqUcMRvTojdozj5tLI0VVJAzLCfz51NOkFXezPeVTAYFqrZ6rI8Q==
- dependencies:
- "@webassemblyjs/ast" "1.7.6"
- "@webassemblyjs/helper-buffer" "1.7.6"
- "@webassemblyjs/wasm-gen" "1.7.6"
- "@webassemblyjs/wasm-parser" "1.7.6"
-
-"@webassemblyjs/wasm-parser@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.6.tgz#84eafeeff405ad6f4c4b5777d6a28ae54eed51fe"
- integrity sha512-t1T6TfwNY85pDA/HWPA8kB9xA4sp9ajlRg5W7EKikqrynTyFo+/qDzIpvdkOkOGjlS6d4n4SX59SPuIayR22Yg==
- dependencies:
- "@webassemblyjs/ast" "1.7.6"
- "@webassemblyjs/helper-api-error" "1.7.6"
- "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
- "@webassemblyjs/ieee754" "1.7.6"
- "@webassemblyjs/leb128" "1.7.6"
- "@webassemblyjs/utf8" "1.7.6"
-
-"@webassemblyjs/wast-parser@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.7.6.tgz#ca4d20b1516e017c91981773bd7e819d6bd9c6a7"
- integrity sha512-1MaWTErN0ziOsNUlLdvwS+NS1QWuI/kgJaAGAMHX8+fMJFgOJDmN/xsG4h/A1Gtf/tz5VyXQciaqHZqp2q0vfg==
- dependencies:
- "@webassemblyjs/ast" "1.7.6"
- "@webassemblyjs/floating-point-hex-parser" "1.7.6"
- "@webassemblyjs/helper-api-error" "1.7.6"
- "@webassemblyjs/helper-code-frame" "1.7.6"
- "@webassemblyjs/helper-fsm" "1.7.6"
+"@webassemblyjs/utf8@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.7.11.tgz#06d7218ea9fdc94a6793aa92208160db3d26ee82"
+ integrity sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==
+
+"@webassemblyjs/wasm-edit@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz#8c74ca474d4f951d01dbae9bd70814ee22a82005"
+ integrity sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-buffer" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/helper-wasm-section" "1.7.11"
+ "@webassemblyjs/wasm-gen" "1.7.11"
+ "@webassemblyjs/wasm-opt" "1.7.11"
+ "@webassemblyjs/wasm-parser" "1.7.11"
+ "@webassemblyjs/wast-printer" "1.7.11"
+
+"@webassemblyjs/wasm-gen@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz#9bbba942f22375686a6fb759afcd7ac9c45da1a8"
+ integrity sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/ieee754" "1.7.11"
+ "@webassemblyjs/leb128" "1.7.11"
+ "@webassemblyjs/utf8" "1.7.11"
+
+"@webassemblyjs/wasm-opt@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz#b331e8e7cef8f8e2f007d42c3a36a0580a7d6ca7"
+ integrity sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-buffer" "1.7.11"
+ "@webassemblyjs/wasm-gen" "1.7.11"
+ "@webassemblyjs/wasm-parser" "1.7.11"
+
+"@webassemblyjs/wasm-parser@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz#6e3d20fa6a3519f6b084ef9391ad58211efb0a1a"
+ integrity sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-api-error" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/ieee754" "1.7.11"
+ "@webassemblyjs/leb128" "1.7.11"
+ "@webassemblyjs/utf8" "1.7.11"
+
+"@webassemblyjs/wast-parser@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz#25bd117562ca8c002720ff8116ef9072d9ca869c"
+ integrity sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/floating-point-hex-parser" "1.7.11"
+ "@webassemblyjs/helper-api-error" "1.7.11"
+ "@webassemblyjs/helper-code-frame" "1.7.11"
+ "@webassemblyjs/helper-fsm" "1.7.11"
"@xtuc/long" "4.2.1"
- mamacro "^0.0.3"
-"@webassemblyjs/wast-printer@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.7.6.tgz#a6002c526ac5fa230fe2c6d2f1bdbf4aead43a5e"
- integrity sha512-vHdHSK1tOetvDcl1IV1OdDeGNe/NDDQ+KzuZHMtqTVP1xO/tZ/IKNpj5BaGk1OYFdsDWQqb31PIwdEyPntOWRQ==
+"@webassemblyjs/wast-printer@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz#c4245b6de242cb50a2cc950174fdbf65c78d7813"
+ integrity sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==
dependencies:
- "@webassemblyjs/ast" "1.7.6"
- "@webassemblyjs/wast-parser" "1.7.6"
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/wast-parser" "1.7.11"
"@xtuc/long" "4.2.1"
"@xtuc/ieee754@^1.2.0":
@@ -923,12 +989,10 @@ accepts@~1.3.4, accepts@~1.3.5:
mime-types "~2.1.18"
negotiator "0.6.1"
-acorn-dynamic-import@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278"
- integrity sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==
- dependencies:
- acorn "^5.0.0"
+acorn-dynamic-import@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948"
+ integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==
acorn-globals@^4.1.0:
version "4.3.0"
@@ -948,15 +1012,15 @@ acorn-walk@^6.0.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913"
integrity sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==
-acorn@^5.0.0, acorn@^5.5.3, acorn@^5.6.2, acorn@^5.7.3:
+acorn@^5.5.3, acorn@^5.7.3:
version "5.7.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
-acorn@^6.0.1, acorn@^6.0.2:
- version "6.0.4"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.4.tgz#77377e7353b72ec5104550aa2d2097a2fd40b754"
- integrity sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==
+acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.5:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.5.tgz#81730c0815f3f3b34d8efa95cb7430965f4d887a"
+ integrity sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg==
after@0.8.2:
version "0.8.2"
@@ -973,10 +1037,10 @@ ajv-keywords@^3.1.0:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a"
integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=
-ajv@^6.1.0, ajv@^6.5.3, ajv@^6.5.5, ajv@^6.6.1:
- version "6.6.1"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.1.tgz#6360f5ed0d80f232cc2b294c362d5dc2e538dd61"
- integrity sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==
+ajv@^6.1.0, ajv@^6.5.3, ajv@^6.5.5, ajv@^6.9.1:
+ version "6.9.1"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.1.tgz#a4d3683d74abc5670e75f0b16520f70a20ea8dc1"
+ integrity sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==
dependencies:
fast-deep-equal "^2.0.1"
fast-json-stable-stringify "^2.0.0"
@@ -1025,6 +1089,11 @@ ansi-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
+ansi-regex@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9"
+ integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==
+
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@@ -1045,50 +1114,54 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
-apollo-boost@^0.1.20:
- version "0.1.20"
- resolved "https://registry.yarnpkg.com/apollo-boost/-/apollo-boost-0.1.20.tgz#cc3e418ebd2bea857656685d32a7a20443493363"
- integrity sha512-n2MiEY5IGpD/cy0RH+pM9vbmobM/JZ5qz38XQAUA41FxxMPlLFQxf0IUMm0tijLOJvJJBub3pDt+Of4TVPBCqA==
+apollo-boost@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/apollo-boost/-/apollo-boost-0.3.1.tgz#b6a896e020a0eab7e415032fe565734a955c65f8"
+ integrity sha512-VdXcTMxLBeNvANW/FtiarEkrRr/cepYKG6wTAURdy8CS33WYpEHtIg9S8tAjxwVzIECpE4lWyDKyPLoESJ072Q==
dependencies:
- apollo-cache "^1.1.20"
- apollo-cache-inmemory "^1.3.9"
- apollo-client "^2.4.5"
+ apollo-cache "^1.2.1"
+ apollo-cache-inmemory "^1.5.1"
+ apollo-client "^2.5.1"
apollo-link "^1.0.6"
apollo-link-error "^1.0.3"
apollo-link-http "^1.3.1"
- apollo-link-state "^0.4.0"
graphql-tag "^2.4.2"
+ ts-invariant "^0.2.1"
+ tslib "^1.9.3"
-apollo-cache-inmemory@^1.3.9:
- version "1.3.9"
- resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.3.9.tgz#10738ba6a04faaeeb0da21bbcc1f7c0b5902910c"
- integrity sha512-Q2k84p/OqIuMUyeWGc6XbVXXZu0erYOO+wTx9p+CnQUspnNvf7zmvFNgFnmudXzfuG1m1CSzePk6fC/M1ehOqQ==
+apollo-cache-inmemory@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.5.1.tgz#265d1ee67b0bf0aca9c37629d410bfae44e62953"
+ integrity sha512-D3bdpPmWfaKQkWy8lfwUg+K8OBITo3sx0BHLs1B/9vIdOIZ7JNCKq3EUcAgAfInomJUdN0QG1yOfi8M8hxkN1g==
dependencies:
- apollo-cache "^1.1.20"
- apollo-utilities "^1.0.25"
- optimism "^0.6.6"
+ apollo-cache "^1.2.1"
+ apollo-utilities "^1.2.1"
+ optimism "^0.6.9"
+ ts-invariant "^0.2.1"
+ tslib "^1.9.3"
-apollo-cache@1.1.20, apollo-cache@^1.1.20:
- version "1.1.20"
- resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.1.20.tgz#6152cc4baf6a63e376efee79f75de4f5c84bf90e"
- integrity sha512-+Du0/4kUSuf5PjPx0+pvgMGV12ezbHA8/hubYuqRQoy/4AWb4faa61CgJNI6cKz2mhDd9m94VTNKTX11NntwkQ==
+apollo-cache@1.2.1, apollo-cache@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.2.1.tgz#aae71eb4a11f1f7322adc343f84b1a39b0693644"
+ integrity sha512-nzFmep/oKlbzUuDyz6fS6aYhRmfpcHWqNkkA9Bbxwk18RD6LXC4eZkuE0gXRX0IibVBHNjYVK+Szi0Yied4SpQ==
dependencies:
- apollo-utilities "^1.0.25"
+ apollo-utilities "^1.2.1"
+ tslib "^1.9.3"
-apollo-client@^2.4.5:
- version "2.4.5"
- resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.4.5.tgz#545beda1ef60814943b5622f0feabc9f29ee9822"
- integrity sha512-nUm06EGa4TP/IY68OzmC3lTD32TqkjLOQdb69uYo+lHl8NnwebtrAw3qFtsQtTEz6ueBp/Z/HasNZng4jwafVQ==
+apollo-client@^2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.5.1.tgz#36126ed1d32edd79c3713c6684546a3bea80e6d1"
+ integrity sha512-MNcQKiqLHdGmNJ0rZ0NXaHrToXapJgS/5kPk0FygXt+/FmDCdzqcujI7OPxEC6e9Yw5S/8dIvOXcRNuOMElHkA==
dependencies:
"@types/zen-observable" "^0.8.0"
- apollo-cache "1.1.20"
+ apollo-cache "1.2.1"
apollo-link "^1.0.0"
apollo-link-dedup "^1.0.0"
- apollo-utilities "1.0.25"
+ apollo-utilities "1.2.1"
symbol-observable "^1.0.2"
+ ts-invariant "^0.2.1"
+ tslib "^1.9.3"
zen-observable "^0.8.0"
- optionalDependencies:
- "@types/async" "2.0.50"
apollo-link-dedup@^1.0.0:
version "1.0.10"
@@ -1119,14 +1192,6 @@ apollo-link-http@^1.3.1:
apollo-link "^1.2.3"
apollo-link-http-common "^0.2.5"
-apollo-link-state@^0.4.0:
- version "0.4.2"
- resolved "https://registry.yarnpkg.com/apollo-link-state/-/apollo-link-state-0.4.2.tgz#ac00e9be9b0ca89eae0be6ba31fe904b80bbe2e8"
- integrity sha512-xMPcAfuiPVYXaLwC6oJFIZrKgV3GmdO31Ag2eufRoXpvT0AfJZjdaPB4450Nu9TslHRePN9A3quxNueILlQxlw==
- dependencies:
- apollo-utilities "^1.0.8"
- graphql-anywhere "^4.1.0-alpha.0"
-
apollo-link@^1.0.0, apollo-link@^1.0.6, apollo-link@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.3.tgz#9bd8d5fe1d88d31dc91dae9ecc22474d451fb70d"
@@ -1135,19 +1200,14 @@ apollo-link@^1.0.0, apollo-link@^1.0.6, apollo-link@^1.2.3:
apollo-utilities "^1.0.0"
zen-observable-ts "^0.8.10"
-apollo-utilities@1.0.25, apollo-utilities@^1.0.0, apollo-utilities@^1.0.25, apollo-utilities@^1.0.8:
- version "1.0.25"
- resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.25.tgz#899b00f5f990fb451675adf84cb3de82eb6372ea"
- integrity sha512-AXvqkhni3Ir1ffm4SA1QzXn8k8I5BBl4PVKEyak734i4jFdp+xgfUyi2VCqF64TJlFTA/B73TRDUvO2D+tKtZg==
+apollo-utilities@1.2.1, apollo-utilities@^1.0.0, apollo-utilities@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.2.1.tgz#1c3a1ebf5607d7c8efe7636daaf58e7463b41b3c"
+ integrity sha512-Zv8Udp9XTSFiN8oyXOjf6PMHepD4yxxReLsl6dPUy5Ths7jti3nmlBzZUOxuTWRwZn0MoclqL7RQ5UEJN8MAxg==
dependencies:
fast-json-stable-stringify "^2.0.0"
-
-append-transform@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
- integrity sha1-126/jKlNJ24keja61EpLdKthGZE=
- dependencies:
- default-require-extensions "^1.0.0"
+ ts-invariant "^0.2.1"
+ tslib "^1.9.3"
append-transform@^1.0.0:
version "1.0.0"
@@ -1176,19 +1236,12 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
-arr-diff@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
- integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=
- dependencies:
- arr-flatten "^1.0.1"
-
arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
-arr-flatten@^1.0.1, arr-flatten@^1.1.0:
+arr-flatten@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
@@ -1203,6 +1256,11 @@ array-equal@^1.0.0:
resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
+array-find-index@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+ integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
+
array-find@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/array-find/-/array-find-1.0.0.tgz#6c8e286d11ed768327f8e62ecee87353ca3e78b8"
@@ -1223,7 +1281,7 @@ array-slice@^0.2.3:
resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5"
integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU=
-array-union@^1.0.1:
+array-union@^1.0.1, array-union@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
@@ -1308,7 +1366,7 @@ async@1.x, async@^1.5.2:
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
-async@^2.0.0, async@^2.1.4, async@^2.5.0, async@^2.6.1:
+async@^2.0.0, async@^2.5.0, async@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==
@@ -1325,6 +1383,18 @@ atob@^2.1.1:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+autoprefixer@^9.0.0:
+ version "9.4.7"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.4.7.tgz#f997994f9a810eae47b38fa6d8a119772051c4ff"
+ integrity sha512-qS5wW6aXHkm53Y4z73tFGsUhmZu4aMPV9iHXYlF0c/wxjknXNHuj/1cIQb+6YH692DbJGGWcckAXX+VxKvahMA==
+ dependencies:
+ browserslist "^4.4.1"
+ caniuse-lite "^1.0.30000932"
+ normalize-range "^0.1.2"
+ num2fraction "^1.2.2"
+ postcss "^7.0.14"
+ postcss-value-parser "^3.3.1"
+
autosize@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/autosize/-/autosize-4.0.0.tgz#7a0599b1ba84d73bd7589b0d9da3870152c69237"
@@ -1364,36 +1434,6 @@ babel-code-frame@^6.26.0:
esutils "^2.0.2"
js-tokens "^3.0.2"
-babel-core@^6.0.0, babel-core@^6.26.0:
- version "6.26.3"
- resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
- integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
- dependencies:
- babel-code-frame "^6.26.0"
- babel-generator "^6.26.0"
- babel-helpers "^6.24.1"
- babel-messages "^6.23.0"
- babel-register "^6.26.0"
- babel-runtime "^6.26.0"
- babel-template "^6.26.0"
- babel-traverse "^6.26.0"
- babel-types "^6.26.0"
- babylon "^6.18.0"
- convert-source-map "^1.5.1"
- debug "^2.6.9"
- json5 "^0.5.1"
- lodash "^4.17.4"
- minimatch "^3.0.4"
- path-is-absolute "^1.0.1"
- private "^0.1.8"
- slash "^1.0.0"
- source-map "^0.5.7"
-
-babel-core@^7.0.0-bridge:
- version "7.0.0-bridge.0"
- resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece"
- integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==
-
babel-eslint@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed"
@@ -1406,53 +1446,26 @@ babel-eslint@^10.0.1:
eslint-scope "3.7.1"
eslint-visitor-keys "^1.0.0"
-babel-generator@^6.18.0, babel-generator@^6.26.0:
- version "6.26.1"
- resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
- integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
+babel-jest@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.1.0.tgz#441e23ef75ded3bd547e300ac3194cef87b55190"
+ integrity sha512-MLcagnVrO9ybQGLEfZUqnOzv36iQzU7Bj4elm39vCukumLVSfoX+tRy3/jW7lUKc7XdpRmB/jech6L/UCsSZjw==
dependencies:
- babel-messages "^6.23.0"
- babel-runtime "^6.26.0"
- babel-types "^6.26.0"
- detect-indent "^4.0.0"
- jsesc "^1.3.0"
- lodash "^4.17.4"
- source-map "^0.5.7"
- trim-right "^1.0.1"
-
-babel-helpers@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
- integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=
- dependencies:
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
+ babel-plugin-istanbul "^5.1.0"
+ babel-preset-jest "^24.1.0"
+ chalk "^2.4.2"
+ slash "^2.0.0"
-babel-jest@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1"
- integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==
+babel-loader@^8.0.5:
+ version "8.0.5"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.5.tgz#225322d7509c2157655840bba52e46b6c2f2fe33"
+ integrity sha512-NTnHnVRd2JnRqPC0vW+iOQWU5pchDbYXsG2E6DMXEpMfUcQKclF9gmf3G3ZMhzG7IG9ji4coL0cm+FxeWxDpnw==
dependencies:
- babel-plugin-istanbul "^4.1.6"
- babel-preset-jest "^23.2.0"
-
-babel-loader@^8.0.4:
- version "8.0.4"
- resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.4.tgz#7bbf20cbe4560629e2e41534147692d3fecbdce6"
- integrity sha512-fhBhNkUToJcW9nV46v8w87AJOwAJDz84c1CL57n3Stj73FANM/b9TbCUK4YhdOwEyZ+OxhYpdeZDNzSI29Firw==
- dependencies:
- find-cache-dir "^1.0.0"
+ find-cache-dir "^2.0.0"
loader-utils "^1.0.2"
mkdirp "^0.5.1"
util.promisify "^1.0.0"
-babel-messages@^6.23.0:
- version "6.23.0"
- resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
- integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=
- dependencies:
- babel-runtime "^6.22.0"
-
babel-plugin-dynamic-import-node@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.2.0.tgz#c0adfb07d95f4a4495e9aaac6ec386c4d7c2524e"
@@ -1460,16 +1473,6 @@ babel-plugin-dynamic-import-node@^2.2.0:
dependencies:
object.assign "^4.1.0"
-babel-plugin-istanbul@^4.1.6:
- version "4.1.6"
- resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45"
- integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==
- dependencies:
- babel-plugin-syntax-object-rest-spread "^6.13.0"
- find-up "^2.1.0"
- istanbul-lib-instrument "^1.10.1"
- test-exclude "^4.2.1"
-
babel-plugin-istanbul@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.0.tgz#6892f529eff65a3e2d33d87dc5888ffa2ecd4a30"
@@ -1479,39 +1482,16 @@ babel-plugin-istanbul@^5.1.0:
istanbul-lib-instrument "^3.0.0"
test-exclude "^5.0.0"
-babel-plugin-jest-hoist@^23.2.0:
- version "23.2.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167"
- integrity sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=
+babel-plugin-jest-hoist@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.1.0.tgz#dfecc491fb15e2668abbd690a697a8fd1411a7f8"
+ integrity sha512-gljYrZz8w1b6fJzKcsfKsipSru2DU2DmQ39aB6nV3xQ0DDv3zpIzKGortA5gknrhNnPN8DweaEgrnZdmbGmhnw==
babel-plugin-rewire@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/babel-plugin-rewire/-/babel-plugin-rewire-1.2.0.tgz#822562d72ed2c84e47c0f95ee232c920853e9d89"
integrity sha512-JBZxczHw3tScS+djy6JPLMjblchGhLI89ep15H3SyjujIzlxo5nr6Yjo7AXotdeVczeBmWs0tF8PgJWDdgzAkQ==
-babel-plugin-syntax-object-rest-spread@^6.13.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
- integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=
-
-babel-plugin-transform-es2015-modules-commonjs@^6.26.0, babel-plugin-transform-es2015-modules-commonjs@^6.26.2:
- version "6.26.2"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3"
- integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==
- dependencies:
- babel-plugin-transform-strict-mode "^6.24.1"
- babel-runtime "^6.26.0"
- babel-template "^6.26.0"
- babel-types "^6.26.0"
-
-babel-plugin-transform-strict-mode@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
- integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=
- dependencies:
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
-
babel-polyfill@6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d"
@@ -1521,28 +1501,15 @@ babel-polyfill@6.23.0:
core-js "^2.4.0"
regenerator-runtime "^0.10.0"
-babel-preset-jest@^23.2.0:
- version "23.2.0"
- resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46"
- integrity sha1-jsegOhOPABoaj7HoETZSvxpV2kY=
- dependencies:
- babel-plugin-jest-hoist "^23.2.0"
- babel-plugin-syntax-object-rest-spread "^6.13.0"
-
-babel-register@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
- integrity sha1-btAhFz4vy0htestFxgCahW9kcHE=
+babel-preset-jest@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.1.0.tgz#83bc564fdcd4903641af65ec63f2f5de6b04132e"
+ integrity sha512-FfNLDxFWsNX9lUmtwY7NheGlANnagvxq8LZdl5PKnVG3umP+S/g0XbVBfwtA4Ai3Ri/IMkWabBz3Tyk9wdspcw==
dependencies:
- babel-core "^6.26.0"
- babel-runtime "^6.26.0"
- core-js "^2.5.0"
- home-or-tmp "^2.0.0"
- lodash "^4.17.4"
- mkdirp "^0.5.1"
- source-map-support "^0.4.15"
+ "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
+ babel-plugin-jest-hoist "^24.1.0"
-babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+babel-runtime@^6.22.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
@@ -1550,57 +1517,21 @@ babel-runtime@^6.22.0, babel-runtime@^6.26.0:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
-babel-standalone@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-standalone/-/babel-standalone-6.26.0.tgz#15fb3d35f2c456695815ebf1ed96fe7f015b6886"
- integrity sha1-Ffs9NfLEVmlYFevx7Zb+fwFbaIY=
-
-babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
- integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
- dependencies:
- babel-runtime "^6.26.0"
- babel-traverse "^6.26.0"
- babel-types "^6.26.0"
- babylon "^6.18.0"
- lodash "^4.17.4"
-
-babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
- integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
- dependencies:
- babel-code-frame "^6.26.0"
- babel-messages "^6.23.0"
- babel-runtime "^6.26.0"
- babel-types "^6.26.0"
- babylon "^6.18.0"
- debug "^2.6.8"
- globals "^9.18.0"
- invariant "^2.2.2"
- lodash "^4.17.4"
-
-babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.24.1, babel-types@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
- integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
- dependencies:
- babel-runtime "^6.26.0"
- esutils "^2.0.2"
- lodash "^4.17.4"
- to-fast-properties "^1.0.3"
-
-babylon@^6.18.0:
- version "6.18.0"
- resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
- integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
+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==
backo2@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
+bail@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.3.tgz#63cfb9ddbac829b02a3128cd53224be78e6c21a3"
+ integrity sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==
+
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@@ -1683,10 +1614,10 @@ blob@0.0.4:
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921"
integrity sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=
-bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.5.1:
- version "3.5.1"
- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
- integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==
+bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@~3.5.0:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7"
+ integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
version "4.11.8"
@@ -1766,15 +1697,6 @@ braces@^0.1.2:
dependencies:
expand-range "^0.1.0"
-braces@^1.8.2:
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
- integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=
- dependencies:
- expand-range "^1.8.1"
- preserve "^0.2.0"
- repeat-element "^1.1.2"
-
braces@^2.3.0, braces@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb"
@@ -1868,14 +1790,21 @@ browserify-zlib@^0.2.0:
dependencies:
pako "~1.0.5"
-browserslist@^4.1.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.1.1.tgz#328eb4ff1215b12df6589e9ab82f8adaa4fc8cd6"
- integrity sha512-VBorw+tgpOtZ1BYhrVSVTzTt/3+vSE3eFUh0N2GCFK1HffceOaf32YS/bs6WiFhjDAblAFrx85jMy3BG9fBK2Q==
+browserslist@^4.3.4, browserslist@^4.4.1:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.4.1.tgz#42e828954b6b29a7a53e352277be429478a69062"
+ integrity sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==
+ dependencies:
+ caniuse-lite "^1.0.30000929"
+ electron-to-chromium "^1.3.103"
+ node-releases "^1.1.3"
+
+bs-logger@0.x:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
+ integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==
dependencies:
- caniuse-lite "^1.0.30000884"
- electron-to-chromium "^1.3.62"
- node-releases "^1.0.0-alpha.11"
+ fast-json-stable-stringify "2.x"
bser@^2.0.0:
version "2.0.0"
@@ -1884,10 +1813,10 @@ bser@^2.0.0:
dependencies:
node-int64 "^0.4.0"
-buffer-from@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531"
- integrity sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==
+buffer-from@1.x, buffer-from@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+ integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
buffer-indexof@^1.0.0:
version "1.1.0"
@@ -1908,11 +1837,6 @@ buffer@^4.3.0:
ieee754 "^1.1.4"
isarray "^1.0.0"
-builtin-modules@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
- integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
-
builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
@@ -1923,43 +1847,24 @@ bytes@3.0.0:
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
-cacache@^10.0.4:
- version "10.0.4"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460"
- integrity sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==
+cacache@^11.0.2, cacache@^11.2.0:
+ version "11.3.2"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa"
+ integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==
dependencies:
- bluebird "^3.5.1"
- chownr "^1.0.1"
- glob "^7.1.2"
- graceful-fs "^4.1.11"
- lru-cache "^4.1.1"
- mississippi "^2.0.0"
- mkdirp "^0.5.1"
- move-concurrently "^1.0.1"
- promise-inflight "^1.0.1"
- rimraf "^2.6.2"
- ssri "^5.2.4"
- unique-filename "^1.1.0"
- y18n "^4.0.0"
-
-cacache@^11.2.0:
- version "11.2.0"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.2.0.tgz#617bdc0b02844af56310e411c0878941d5739965"
- integrity sha512-IFWl6lfK6wSeYCHUXh+N1lY72UDrpyrYQJNIVQf48paDuWbv5RbAtJYf/4gUQFObTCHZwdZ5sI8Iw7nqwP6nlQ==
- dependencies:
- bluebird "^3.5.1"
- chownr "^1.0.1"
- figgy-pudding "^3.1.0"
- glob "^7.1.2"
- graceful-fs "^4.1.11"
- lru-cache "^4.1.3"
+ bluebird "^3.5.3"
+ chownr "^1.1.1"
+ figgy-pudding "^3.5.1"
+ glob "^7.1.3"
+ graceful-fs "^4.1.15"
+ lru-cache "^5.1.1"
mississippi "^3.0.0"
mkdirp "^0.5.1"
move-concurrently "^1.0.1"
promise-inflight "^1.0.1"
rimraf "^2.6.2"
- ssri "^6.0.0"
- unique-filename "^1.1.0"
+ ssri "^6.0.1"
+ unique-filename "^1.1.1"
y18n "^4.0.0"
cache-base@^1.0.1:
@@ -1977,15 +1882,16 @@ cache-base@^1.0.1:
union-value "^1.0.0"
unset-value "^1.0.0"
-cache-loader@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-1.2.2.tgz#6d5c38ded959a09cc5d58190ab5af6f73bd353f5"
- integrity sha512-rsGh4SIYyB9glU+d0OcHwiXHXBoUgDhHZaQ1KAbiXqfz1CDPxtTboh1gPbJ0q2qdO8a9lfcjgC5CJ2Ms32y5bw==
+cache-loader@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-2.0.1.tgz#5758f41a62d7c23941e3c3c7016e6faeb03acb07"
+ integrity sha512-V99T3FOynmGx26Zom+JrVBytLBsmUCzVG2/4NnUKgvXN4bEV42R1ERl1IyiH/cvFIDA1Ytq2lPZ9tXDSahcQpQ==
dependencies:
loader-utils "^1.1.0"
mkdirp "^0.5.1"
- neo-async "^2.5.0"
- schema-utils "^0.4.2"
+ neo-async "^2.6.0"
+ normalize-path "^3.0.0"
+ schema-utils "^1.0.0"
cacheable-request@^2.1.1:
version "2.1.4"
@@ -2000,6 +1906,18 @@ cacheable-request@^2.1.1:
normalize-url "2.0.1"
responselike "1.0.2"
+call-me-maybe@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
+ integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
+
+caller-callsite@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
+ integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=
+ dependencies:
+ callsites "^2.0.0"
+
caller-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
@@ -2007,6 +1925,13 @@ caller-path@^0.1.0:
dependencies:
callsites "^0.2.0"
+caller-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
+ integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=
+ dependencies:
+ caller-callsite "^2.0.0"
+
callsite@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
@@ -2022,15 +1947,34 @@ callsites@^2.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=
+callsites@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3"
+ integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==
+
+camelcase-keys@^4.0.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77"
+ integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=
+ dependencies:
+ camelcase "^4.1.0"
+ map-obj "^2.0.0"
+ quick-lru "^1.0.0"
+
camelcase@^4.0.0, camelcase@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
-caniuse-lite@^1.0.30000884:
- version "1.0.30000888"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000888.tgz#22edb50d91dd70612b5898e3b36f460600c6492f"
- integrity sha512-vftg+5p/lPsQGpnhSo/yBuYL36ai/cyjLvU3dOPJY1kkKrekLWIy8SLm+wzjX0hpCUdFTasC4/ZT7uqw4rKOnQ==
+camelcase@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42"
+ integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==
+
+caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000932:
+ version "1.0.30000936"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000936.tgz#5d33b118763988bf721b9b8ad436d0400e4a116b"
+ integrity sha512-orX4IdpbFhdNO7bTBhSbahp1EBpqzBc+qrvTRVUFfZgA4zta7TdM6PN5ZxkEUgDnz36m+PfWGcdX7AVfFWItJw==
capture-exit@^1.2.0:
version "1.2.0"
@@ -2049,6 +1993,18 @@ caseless@~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@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.3.tgz#f1cec43f332e2ea5a569fd46f9f5bde4e6102aff"
+ integrity sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==
+
chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -2060,15 +2016,35 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
- integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
+character-entities-html4@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610"
+ integrity sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==
+
+character-entities-legacy@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c"
+ integrity sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==
+
+character-entities@^1.0.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.2.tgz#58c8f371c0774ef0ba9b2aca5f00d8f100e6e363"
+ integrity sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==
+
+character-reference-invalid@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed"
+ integrity sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==
+
chardet@^0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
@@ -2084,17 +2060,35 @@ chardet@^0.5.0:
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
-chart.js@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-1.0.2.tgz#ad57d2229cfd8ccf5955147e8121b4911e69dfe7"
- integrity sha1-rVfSIpz9jM9ZVRR+gSG0kR5p3+c=
+chart.js@2.7.2:
+ version "2.7.2"
+ resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.7.2.tgz#3c9fde4dc5b95608211bdefeda7e5d33dffa5714"
+ integrity sha512-90wl3V9xRZ8tnMvMlpcW+0Yg13BelsGS9P9t0ClaDxv/hdypHDr/YAGf+728m11P5ljwyB0ZHfPKCapZFqSqYA==
+ dependencies:
+ chartjs-color "^2.1.0"
+ moment "^2.10.2"
+
+chartjs-color-string@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz#8d3752d8581d86687c35bfe2cb80ac5213ceb8c1"
+ integrity sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==
+ dependencies:
+ color-name "^1.0.0"
+
+chartjs-color@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.2.0.tgz#84a2fb755787ed85c39dd6dd8c7b1d88429baeae"
+ integrity sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=
+ dependencies:
+ chartjs-color-string "^0.5.0"
+ color-convert "^0.5.3"
check-types@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.3.0.tgz#468f571a4435c24248f5fd0cb0e8d87c3c341e7d"
integrity sha1-Ro9XGkQ1wkJI9f0MsOjYfDw0Hn0=
-chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3:
+chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26"
integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==
@@ -2114,10 +2108,10 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3:
optionalDependencies:
fsevents "^1.2.2"
-chownr@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
- integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=
+chownr@^1.0.1, chownr@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
+ integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
chrome-trace-event@^1.0.0:
version "1.0.0"
@@ -2131,6 +2125,11 @@ ci-info@^1.5.0:
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+ci-info@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
+ integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@@ -2176,6 +2175,16 @@ cli-cursor@^2.1.0:
dependencies:
restore-cursor "^2.0.0"
+cli-table3@^0.5.0:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202"
+ integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==
+ dependencies:
+ object-assign "^4.1.0"
+ string-width "^2.1.1"
+ optionalDependencies:
+ colors "^1.1.2"
+
cli-width@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a"
@@ -2199,6 +2208,14 @@ cliui@^4.0.0:
strip-ansi "^4.0.0"
wrap-ansi "^2.0.0"
+clone-regexp@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.1.tgz#051805cd33173375d82118fc0918606da39fd60f"
+ integrity sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw==
+ dependencies:
+ is-regexp "^1.0.0"
+ is-supported-regexp-flag "^1.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"
@@ -2206,11 +2223,6 @@ clone-response@1.0.2:
dependencies:
mimic-response "^1.0.0"
-clone@2.x:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
- integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
-
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@@ -2240,6 +2252,11 @@ codesandbox-import-utils@^1.2.3:
istextorbinary "^2.2.1"
lz-string "^1.4.4"
+collapse-white-space@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091"
+ integrity sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==
+
collection-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
@@ -2248,6 +2265,11 @@ collection-visit@^1.0.0:
map-visit "^1.0.0"
object-visit "^1.0.0"
+color-convert@^0.5.3:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
+ integrity sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=
+
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -2255,15 +2277,15 @@ color-convert@^1.9.0:
dependencies:
color-name "1.1.3"
-color-name@1.1.3:
+color-name@1.1.3, color-name@^1.0.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-colors@^1.1.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
- integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM=
+colors@^1.1.0, colors@^1.1.2:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
+ integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==
combine-lists@^1.0.0:
version "1.0.1"
@@ -2279,16 +2301,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
-commander@2, commander@^2.10.0, commander@^2.18.0, commander@^2.19.0:
+commander@2, commander@^2.10.0, commander@^2.16.0, commander@^2.18.0, commander@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
-commander@~2.13.0:
- version "2.13.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
- integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==
-
commander@~2.17.1:
version "2.17.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
@@ -2440,7 +2457,7 @@ content-type@~1.0.4:
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.1:
+convert-source-map@^1.1.0, convert-source-map@^1.4.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
@@ -2481,7 +2498,7 @@ copy-to-clipboard@^3.0.8:
dependencies:
toggle-selection "^1.0.3"
-core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0:
+core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1:
version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==
@@ -2496,6 +2513,16 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+cosmiconfig@^5.0.0:
+ version "5.0.7"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.7.tgz#39826b292ee0d78eda137dfa3173bd1c21a43b04"
+ integrity sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==
+ dependencies:
+ import-fresh "^2.0.0"
+ is-directory "^0.3.1"
+ js-yaml "^3.9.0"
+ parse-json "^4.0.0"
+
create-ecdh@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d"
@@ -2588,15 +2615,15 @@ crypto-random-string@^1.0.0:
integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=
css-loader@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.0.tgz#9f46aaa5ca41dbe31860e3b62b8e23c42916bf56"
- integrity sha512-tMXlTYf3mIMt3b0dDCOQFJiVvxbocJ5Ho577WiGPYPZcqVEO218L2iU22pDXzkTZCLDE+9AmGSUkWxeh/nZReA==
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.1.tgz#6885bb5233b35ec47b006057da01cc640b6b79fe"
+ integrity sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==
dependencies:
babel-code-frame "^6.26.0"
css-selector-tokenizer "^0.7.0"
icss-utils "^2.1.0"
loader-utils "^1.0.2"
- lodash.camelcase "^4.3.0"
+ lodash "^4.17.11"
postcss "^6.0.23"
postcss-modules-extract-imports "^1.2.0"
postcss-modules-local-by-default "^1.2.0"
@@ -2634,6 +2661,11 @@ cssesc@^0.1.0:
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=
+cssesc@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703"
+ integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==
+
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
version "0.3.4"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797"
@@ -2646,6 +2678,13 @@ cssstyle@^1.0.0:
dependencies:
cssom "0.3.x"
+currently-unhandled@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+ integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
+ dependencies:
+ array-find-index "^1.0.1"
+
custom-event@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
@@ -2963,10 +3002,10 @@ debug@^3.1.0, debug@^3.2.5:
dependencies:
ms "^2.1.1"
-debug@^4.0.1, debug@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87"
- integrity sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==
+debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+ integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
dependencies:
ms "^2.1.1"
@@ -2977,7 +3016,15 @@ debug@~3.1.0:
dependencies:
ms "2.0.0"
-decamelize@^1.1.1:
+decamelize-keys@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
+ integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=
+ dependencies:
+ decamelize "^1.1.0"
+ map-obj "^1.0.0"
+
+decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@@ -2989,10 +3036,10 @@ decamelize@^2.0.0:
dependencies:
xregexp "4.0.0"
-deckar01-task_list@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/deckar01-task_list/-/deckar01-task_list-2.0.0.tgz#7f7a595430d21b3036ed5dfbf97d6b65de18e2c9"
- integrity sha1-f3pZVDDSGzA27V37+X1rZd4Y4sk=
+deckar01-task_list@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/deckar01-task_list/-/deckar01-task_list-2.2.0.tgz#5cc3ea06f01d3d786b1a667064a462eb5d069bd3"
+ integrity sha512-NUfu5ARoD9SC2k+fBT5cBer59iKfEdawPrmfqp5+zAahTECb8z9dsuS1Xnx7jzFAmCCLnEs3z/aYucYXzNrKkQ==
decode-uri-component@^0.2.0:
version "0.2.0"
@@ -3029,13 +3076,6 @@ default-gateway@^2.6.0:
execa "^0.10.0"
ip-regex "^2.1.0"
-default-require-extensions@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
- integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=
- dependencies:
- strip-bom "^2.0.0"
-
default-require-extensions@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7"
@@ -3135,12 +3175,10 @@ destroy@~1.0.4:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
-detect-indent@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
- integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg=
- dependencies:
- repeating "^2.0.0"
+detect-file@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
+ integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
detect-libc@^1.0.2:
version "1.0.3"
@@ -3152,16 +3190,21 @@ detect-newline@^2.1.0:
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
-detect-node@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
- integrity sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=
+detect-node@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
+ integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
di@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=
+diff-sequences@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.0.0.tgz#cdf8e27ed20d8b8d3caccb4e0c0d8fe31a173013"
+ integrity sha512-46OkIuVGBBnrC0soO/4LHu5LHGHx0uhP65OVz8XOrAJpqiCB2aVIuESvjI1F9oqebuvY8lekS1pt6TN7vt7qsw==
+
diff@^3.2.0, diff@^3.4.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
@@ -3176,6 +3219,13 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"
+dir-glob@^2.2.1:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4"
+ integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==
+ dependencies:
+ path-type "^3.0.0"
+
dns-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
@@ -3196,6 +3246,11 @@ dns-txt@^2.0.2:
dependencies:
buffer-indexof "^1.0.0"
+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@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
@@ -3211,10 +3266,12 @@ doctrine@^2.1.0:
dependencies:
esutils "^2.0.2"
-document-register-element@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/document-register-element/-/document-register-element-1.3.0.tgz#fb3babb523c74662be47be19c6bc33e71990d940"
- integrity sha1-+zurtSPHRmK+R74Zxrwz5xmQ2UA=
+document-register-element@1.13.1:
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/document-register-element/-/document-register-element-1.13.1.tgz#dad8cb7be38e04ee3f56842e6cf81af46c1249ba"
+ integrity sha512-92ZyLDKg9j4rOll//NNXj25f+8rAzOkYsGJonhugKwXfeqH7bzs8Ucpvey0WzZ2ZzKdrvW9RnUw3UyOZ/uhBFw==
+ dependencies:
+ lightercollective "^0.1.0"
dom-serialize@^2.2.0:
version "2.2.1"
@@ -3288,7 +3345,7 @@ duplexer3@^0.1.4:
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
-duplexer@^0.1.1, duplexer@~0.1.1:
+duplexer@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
@@ -3345,10 +3402,10 @@ ejs@^2.6.1:
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==
-electron-to-chromium@^1.3.62:
- version "1.3.73"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.73.tgz#aa67787067d58cc3920089368b3b8d6fe0fc12f6"
- integrity sha512-6PIg7v9zRoVGh6EheRF8h6Plti+3Yo/qtHobS4/Htyt53DNHmKKGFqSae1AIk0k1S4gCQvt7I2WgpbuZNcDY+g==
+electron-to-chromium@^1.3.103:
+ version "1.3.113"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9"
+ integrity sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==
elliptic@^6.0.0:
version "6.4.0"
@@ -3363,6 +3420,11 @@ elliptic@^6.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.0"
+emoji-regex@^7.0.1, emoji-regex@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
+ integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
+
emoji-unicode-version@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc"
@@ -3432,7 +3494,7 @@ engine.io@~3.2.0:
engine.io-parser "~2.1.0"
ws "~3.3.1"
-enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
+enhanced-resolve@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f"
integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==
@@ -3504,7 +3566,7 @@ escape-html@~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.2, escape-string-regexp@^1.0.5:
+escape-string-regexp@^1.0.2, 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=
@@ -3633,10 +3695,10 @@ eslint-plugin-jasmine@^2.10.1:
resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.10.1.tgz#5733b709e751f4bc40e31e1c16989bd2cdfbec97"
integrity sha1-VzO3CedR9LxA4x4cFpib0s377Jc=
-eslint-plugin-jest@^22.1.0:
- version "22.1.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.1.0.tgz#9a4dfa3367563e8301560a7fb92ec309096dbca3"
- integrity sha512-WcQd5LxEoAS20zuWEAd8CX0pVC+gGInZPcsoYvK5w7BrEJNmltyTxYYh1r0ct4GsahD2GvNySlcTcLtK2amFZA==
+eslint-plugin-jest@^22.3.0:
+ version "22.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.3.0.tgz#a10f10dedfc92def774ec9bb5bfbd2fb8e1c96d2"
+ integrity sha512-P1mYVRNlOEoO5T9yTqOfucjOYf1ktmJ26NjwjH8sxpCFQa6IhBGr5TpKl3hcAAT29hOsRJVuMWmTsHoUVo9FoA==
eslint-plugin-promise@^4.0.1:
version "4.0.1"
@@ -3788,19 +3850,6 @@ eve-raphael@0.5.0:
resolved "https://registry.yarnpkg.com/eve-raphael/-/eve-raphael-0.5.0.tgz#17c754b792beef3fa6684d79cf5a47c63c4cda30"
integrity sha1-F8dUt5K+7z+maE15z1pHxjxM2jA=
-event-stream@~3.3.0:
- version "3.3.4"
- resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
- integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=
- dependencies:
- duplexer "~0.1.1"
- from "~0"
- map-stream "~0.1.0"
- pause-stream "0.0.11"
- split "0.3"
- stream-combiner "~0.0.4"
- through "~2.3.1"
-
eventemitter3@1.x.x:
version "1.2.0"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
@@ -3859,6 +3908,26 @@ execa@^0.7.0:
signal-exit "^3.0.0"
strip-eof "^1.0.0"
+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"
+
+execall@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73"
+ integrity sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=
+ dependencies:
+ clone-regexp "^1.0.0"
+
exit@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
@@ -3873,13 +3942,6 @@ expand-braces@^0.1.1:
array-unique "^0.2.1"
braces "^0.1.2"
-expand-brackets@^0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
- integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=
- dependencies:
- is-posix-bracket "^0.1.0"
-
expand-brackets@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
@@ -3901,24 +3963,23 @@ expand-range@^0.1.0:
is-number "^0.1.1"
repeat-string "^0.2.2"
-expand-range@^1.8.1:
- version "1.8.2"
- resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
- integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=
+expand-tilde@^2.0.0, expand-tilde@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
+ integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
dependencies:
- fill-range "^2.1.0"
+ homedir-polyfill "^1.0.1"
-expect@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98"
- integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==
+expect@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-24.1.0.tgz#88e73301c4c785cde5f16da130ab407bdaf8c0f2"
+ integrity sha512-lVcAPhaYkQcIyMS+F8RVwzbm1jro20IG8OkvxQ6f1JfqhVZyyudCwYogQ7wnktlf14iF3ii7ArIUO/mqvrW9Gw==
dependencies:
ansi-styles "^3.2.0"
- jest-diff "^23.6.0"
- jest-get-type "^22.1.0"
- jest-matcher-utils "^23.6.0"
- jest-message-util "^23.4.0"
- jest-regex-util "^23.3.0"
+ jest-get-type "^24.0.0"
+ jest-matcher-utils "^24.0.0"
+ jest-message-util "^24.0.0"
+ jest-regex-util "^24.0.0"
exports-loader@^0.7.0:
version "0.7.0"
@@ -4002,13 +4063,6 @@ external-editor@^3.0.0:
iconv-lite "^0.4.22"
tmp "^0.0.33"
-extglob@^0.3.1:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
- integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=
- dependencies:
- is-extglob "^1.0.0"
-
extglob@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
@@ -4040,7 +4094,19 @@ fast-deep-equal@^2.0.1:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
-fast-json-stable-stringify@^2.0.0:
+fast-glob@^2.2.6:
+ version "2.2.6"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.6.tgz#a5d5b697ec8deda468d85a74035290a025a95295"
+ integrity sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==
+ dependencies:
+ "@mrmlnc/readdir-enhanced" "^2.2.1"
+ "@nodelib/fs.stat" "^1.1.2"
+ glob-parent "^3.1.0"
+ is-glob "^4.0.0"
+ merge2 "^1.2.3"
+ micromatch "^3.1.10"
+
+fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
@@ -4055,6 +4121,13 @@ fastparse@^1.1.1:
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
integrity sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=
+fault@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa"
+ integrity sha512-o2eo/X2syzzERAtN5LcGbiVQ0WwZSlN3qLtadwAz3X8Bu+XWD16dja/KMsjZLiQr+BLGPDnHGkc4yUJf1Xpkpw==
+ dependencies:
+ format "^0.2.2"
+
faye-websocket@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
@@ -4076,7 +4149,7 @@ fb-watchman@^2.0.0:
dependencies:
bser "^2.0.0"
-figgy-pudding@^3.1.0, figgy-pudding@^3.5.1:
+figgy-pudding@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
@@ -4096,20 +4169,22 @@ file-entry-cache@^2.0.0:
flat-cache "^1.2.1"
object-assign "^4.0.1"
-file-loader@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-2.0.0.tgz#39749c82f020b9e85901dcff98e8004e6401cfde"
- integrity sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==
+file-entry-cache@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-4.0.0.tgz#633567d15364aefe0b299e1e217735e8f3a9f6e8"
+ integrity sha512-AVSwsnbV8vH/UVbvgEhf3saVQXORNv0ZzSkvkhQIaia5Tia+JhGTaa/ePUSVoPHQyGayQNmYfkzFi3WZV5zcpA==
+ dependencies:
+ flat-cache "^2.0.1"
+
+file-loader@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa"
+ integrity sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==
dependencies:
loader-utils "^1.0.2"
schema-utils "^1.0.0"
-filename-regex@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
- integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
-
-fileset@^2.0.2, fileset@^2.0.3:
+fileset@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
@@ -4122,17 +4197,6 @@ filesize@^3.6.1:
resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==
-fill-range@^2.1.0:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565"
- integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==
- dependencies:
- is-number "^2.1.0"
- isobject "^2.0.0"
- randomatic "^3.0.0"
- repeat-element "^1.1.2"
- repeat-string "^1.5.2"
-
fill-range@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@@ -4169,23 +4233,6 @@ finalhandler@1.1.1:
statuses "~1.4.0"
unpipe "~1.0.0"
-find-babel-config@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.1.0.tgz#acc01043a6749fec34429be6b64f542ebb5d6355"
- integrity sha1-rMAQQ6Z0n+w0Qpvmtk9ULrtdY1U=
- dependencies:
- json5 "^0.5.1"
- path-exists "^3.0.0"
-
-find-cache-dir@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
- integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=
- dependencies:
- commondir "^1.0.1"
- make-dir "^1.0.0"
- pkg-dir "^2.0.0"
-
find-cache-dir@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d"
@@ -4222,6 +4269,16 @@ find-up@^3.0.0:
dependencies:
locate-path "^3.0.0"
+findup-sync@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
+ integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=
+ dependencies:
+ detect-file "^1.0.0"
+ is-glob "^3.1.0"
+ micromatch "^3.0.4"
+ resolve-dir "^1.0.1"
+
flat-cache@^1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96"
@@ -4232,6 +4289,20 @@ flat-cache@^1.2.1:
graceful-fs "^4.1.2"
write "^0.2.1"
+flat-cache@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
+ integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==
+ dependencies:
+ flatted "^2.0.0"
+ rimraf "2.6.3"
+ write "1.0.3"
+
+flatted@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916"
+ integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==
+
flush-write-stream@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417"
@@ -4247,18 +4318,11 @@ follow-redirects@^1.2.5:
dependencies:
debug "^3.1.0"
-for-in@^1.0.1, for-in@^1.0.2:
+for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
-for-own@^0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
- integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=
- dependencies:
- for-in "^1.0.1"
-
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@@ -4273,6 +4337,11 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"
+format@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b"
+ integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=
+
formdata-polyfill@^3.0.11:
version "3.0.11"
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-3.0.11.tgz#c82b4b4bea3356c0a6752219e54ce1edb2a7fb5b"
@@ -4303,11 +4372,6 @@ from2@^2.1.0, from2@^2.1.1:
inherits "^2.0.1"
readable-stream "^2.0.0"
-from@~0:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
- integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=
-
fs-access@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a"
@@ -4389,6 +4453,13 @@ get-stream@3.0.0, get-stream@^3.0.0:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
+get-stream@^4.0.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-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@@ -4423,21 +4494,6 @@ gettext-extractor@^3.3.2:
pofile "^1"
typescript "^2"
-glob-base@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
- integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=
- dependencies:
- glob-parent "^2.0.0"
- is-glob "^2.0.0"
-
-glob-parent@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
- integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=
- dependencies:
- is-glob "^2.0.0"
-
glob-parent@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
@@ -4446,7 +4502,12 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
-"glob@5 - 7", glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
+glob-to-regexp@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
+ integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=
+
+"glob@5 - 7", glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
@@ -4476,21 +4537,52 @@ global-dirs@^0.1.0:
dependencies:
ini "^1.3.4"
-global-modules-path@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.1.0.tgz#923ec524e8726bb0c1a4ed4b8e21e1ff80c88bbb"
- integrity sha512-3DrmGj2TP+96cABk9TfMp6f3knH/Y46dqvWznTU3Tf6/bDGLDAn15tFluQ7BcloykOcdY16U0WGq0BQblYOxJQ==
+global-modules-path@^2.3.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.3.1.tgz#e541f4c800a1a8514a990477b267ac67525b9931"
+ integrity sha512-y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==
+
+global-modules@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
+ integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
+ dependencies:
+ global-prefix "^1.0.1"
+ is-windows "^1.0.1"
+ resolve-dir "^1.0.0"
+
+global-modules@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
+ integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==
+ dependencies:
+ global-prefix "^3.0.0"
+
+global-prefix@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
+ integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
+ dependencies:
+ expand-tilde "^2.0.2"
+ homedir-polyfill "^1.0.1"
+ ini "^1.3.4"
+ is-windows "^1.0.1"
+ which "^1.2.14"
+
+global-prefix@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97"
+ integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==
+ dependencies:
+ ini "^1.3.5"
+ kind-of "^6.0.2"
+ which "^1.3.1"
globals@^11.1.0, globals@^11.7.0:
version "11.7.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673"
integrity sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==
-globals@^9.18.0:
- version "9.18.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
- integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
-
globby@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
@@ -4514,6 +4606,31 @@ globby@^6.1.0:
pify "^2.0.0"
pinkie-promise "^2.0.0"
+globby@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-9.0.0.tgz#3800df736dc711266df39b4ce33fe0d481f94c23"
+ integrity sha512-q0qiO/p1w/yJ0hk8V9x1UXlgsXUxlGd0AHUOXZVXBO6aznDtpx7M8D1kBrCAItoPm+4l8r6ATXV1JpjY2SBQOw==
+ dependencies:
+ array-union "^1.0.2"
+ dir-glob "^2.2.1"
+ fast-glob "^2.2.6"
+ glob "^7.1.3"
+ ignore "^4.0.3"
+ pify "^4.0.1"
+ slash "^2.0.0"
+
+globjoin@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43"
+ integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=
+
+gonzales-pe@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.3.tgz#41091703625433285e0aee3aa47829fc1fbeb6f2"
+ integrity sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw==
+ dependencies:
+ minimist "1.1.x"
+
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
@@ -4561,10 +4678,10 @@ got@^8.0.3:
url-parse-lax "^3.0.0"
url-to-options "^1.0.1"
-graceful-fs@^4.1.11, graceful-fs@^4.1.2:
- version "4.1.11"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
- integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.9:
+ version "4.1.15"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
+ integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
graphlibrary@^2.2.0:
version "2.2.0"
@@ -4573,13 +4690,6 @@ graphlibrary@^2.2.0:
dependencies:
lodash "^4.17.5"
-graphql-anywhere@^4.1.0-alpha.0:
- version "4.1.22"
- resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.1.22.tgz#1c831ba3c9e5664a0dd24d10d23a9e9512d92056"
- integrity sha512-qm2/1cKM8nfotxDhm4J0r1znVlK0Yge/yEKt26EVVBgpIhvxjXYFALCGbr7cvfDlvzal1iSPpaYa+8YTtjsxQA==
- dependencies:
- apollo-utilities "^1.0.25"
-
graphql-tag@^2.10.0, graphql-tag@^2.4.2:
version "2.10.0"
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.0.tgz#87da024be863e357551b2b8700e496ee2d4353ae"
@@ -4605,15 +4715,15 @@ gzip-size@^5.0.0:
duplexer "^0.1.1"
pify "^3.0.0"
-handle-thing@^1.2.5:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
- integrity sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=
+handle-thing@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754"
+ integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
-handlebars@^4.0.1, handlebars@^4.0.11, handlebars@^4.0.3:
- version "4.0.12"
- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5"
- integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==
+handlebars@^4.0.1, handlebars@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.0.tgz#0d6a6f34ff1f63cecec8423aa4169827bf787c3a"
+ integrity sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==
dependencies:
async "^2.5.0"
optimist "^0.6.1"
@@ -4756,7 +4866,7 @@ he@^1.1.0, he@^1.1.1:
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
-highlight.js@^9.13.1:
+highlight.js@^9.13.1, highlight.js@~9.13.0:
version "9.13.1"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
@@ -4770,13 +4880,12 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
-home-or-tmp@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
- integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg=
+homedir-polyfill@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc"
+ integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw=
dependencies:
- os-homedir "^1.0.0"
- os-tmpdir "^1.0.1"
+ parse-passwd "^1.0.0"
hoopy@^0.1.2:
version "0.1.4"
@@ -4810,6 +4919,11 @@ html-entities@^1.2.0:
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.0.tgz#41948caf85ce82fed36e4e6a0ed371a6664379e2"
integrity sha1-QZSMr4XOgv7Tbk5qDtNxpmZDeeI=
+html-tags@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b"
+ integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=
+
htmlparser2@^3.10.0, htmlparser2@^3.9.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464"
@@ -4920,11 +5034,16 @@ ignore-walk@^3.0.1:
dependencies:
minimatch "^3.0.4"
-ignore@^4.0.6:
+ignore@^4.0.3, 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.0.4:
+ version "5.0.5"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.5.tgz#c663c548d6ce186fb33616a8ccb5d46e56bdbbf9"
+ integrity sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA==
+
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
@@ -4935,18 +5054,23 @@ immutable-tuple@^0.4.9:
resolved "https://registry.yarnpkg.com/immutable-tuple/-/immutable-tuple-0.4.9.tgz#473ebdd6c169c461913a454bf87ef8f601a20ff0"
integrity sha512-LWbJPZnidF8eczu7XmcnLBsumuyRBkpwIRPCZxlojouhBo5jEBO4toj6n7hMy6IxHU/c+MqDSWkvaTpPlMQcyA==
+import-fresh@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
+ integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY=
+ dependencies:
+ caller-path "^2.0.0"
+ resolve-from "^3.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-local@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc"
- integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==
- dependencies:
- pkg-dir "^2.0.0"
- resolve-cwd "^2.0.0"
+import-lazy@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc"
+ integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==
import-local@^2.0.0:
version "2.0.0"
@@ -4969,6 +5093,11 @@ imurmurhash@^0.1.4:
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
+indent-string@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
+ integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
+
indexes-of@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
@@ -4997,7 +5126,7 @@ inherits@2.0.1:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
-ini@^1.3.4, ini@~1.3.0:
+ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
@@ -5021,7 +5150,7 @@ inquirer@3.0.6:
strip-ansi "^3.0.0"
through "^2.3.6"
-inquirer@^6.0.0, inquirer@^6.1.0:
+inquirer@^6.1.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8"
integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==
@@ -5107,6 +5236,24 @@ is-accessor-descriptor@^1.0.0:
dependencies:
kind-of "^6.0.0"
+is-alphabetical@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz#1fa6e49213cb7885b75d15862fb3f3d96c884f41"
+ integrity sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==
+
+is-alphanumeric@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4"
+ integrity sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=
+
+is-alphanumerical@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz#1138e9ae5040158dc6ff76b820acd6b7a181fd40"
+ integrity sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==
+ dependencies:
+ is-alphabetical "^1.0.0"
+ is-decimal "^1.0.0"
+
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
@@ -5124,12 +5271,10 @@ is-buffer@^1.1.5:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-is-builtin-module@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
- integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74=
- dependencies:
- builtin-modules "^1.0.0"
+is-buffer@^2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
+ integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
is-callable@^1.1.1, is-callable@^1.1.3:
version "1.1.4"
@@ -5143,6 +5288,13 @@ is-ci@^1.0.10:
dependencies:
ci-info "^1.5.0"
+is-ci@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
+ integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
+ dependencies:
+ ci-info "^2.0.0"
+
is-data-descriptor@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@@ -5162,6 +5314,11 @@ is-date-object@^1.0.1:
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
+is-decimal@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.2.tgz#894662d6a8709d307f3a276ca4339c8fa5dff0ff"
+ integrity sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==
+
is-descriptor@^0.1.0:
version "0.1.6"
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
@@ -5180,17 +5337,10 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-data-descriptor "^1.0.0"
kind-of "^6.0.2"
-is-dotfile@^1.0.0:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
- integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=
-
-is-equal-shallow@^0.1.3:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
- integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=
- dependencies:
- is-primitive "^2.0.0"
+is-directory@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
+ integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
is-extendable@^0.1.0, is-extendable@^0.1.1:
version "0.1.1"
@@ -5204,23 +5354,11 @@ is-extendable@^1.0.1:
dependencies:
is-plain-object "^2.0.4"
-is-extglob@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
- integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
-
is-extglob@^2.1.0, is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
-is-finite@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
- integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=
- dependencies:
- number-is-nan "^1.0.0"
-
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
@@ -5233,17 +5371,10 @@ is-fullwidth-code-point@^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-generator-fn@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a"
- integrity sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=
-
-is-glob@^2.0.0, is-glob@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
- integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=
- dependencies:
- is-extglob "^1.0.0"
+is-generator-fn@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.0.0.tgz#038c31b774709641bda678b1f06a4e3227c10b3e"
+ integrity sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g==
is-glob@^3.1.0:
version "3.1.0"
@@ -5259,6 +5390,11 @@ is-glob@^4.0.0:
dependencies:
is-extglob "^2.1.1"
+is-hexadecimal@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835"
+ integrity sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==
+
is-installed-globally@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80"
@@ -5277,13 +5413,6 @@ is-number@^0.1.1:
resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806"
integrity sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=
-is-number@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
- integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=
- dependencies:
- kind-of "^3.0.2"
-
is-number@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@@ -5332,7 +5461,7 @@ is-path-inside@^1.0.0:
dependencies:
path-is-inside "^1.0.1"
-is-plain-obj@^1.0.0:
+is-plain-obj@^1.0.0, 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"
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
@@ -5344,16 +5473,6 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
-is-posix-bracket@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
- integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=
-
-is-primitive@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
- integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
-
is-promise@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
@@ -5391,6 +5510,11 @@ is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
+is-supported-regexp-flag@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz#21ee16518d2c1dd3edd3e9a0d57e50207ac364ca"
+ integrity sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ==
+
is-symbol@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
@@ -5403,16 +5527,21 @@ is-typedarray@~1.0.0:
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-is-utf8@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
- integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
+is-whitespace-character@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz#ede53b4c6f6fb3874533751ec9280d01928d03ed"
+ integrity sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==
-is-windows@^1.0.2:
+is-windows@^1.0.1, is-windows@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
+is-word-character@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.2.tgz#46a5dac3f2a1840898b91e576cd40d493f3ae553"
+ integrity sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==
+
is-wsl@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
@@ -5455,145 +5584,76 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-istanbul-api@^1.3.1:
- version "1.3.7"
- resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa"
- integrity sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==
- dependencies:
- async "^2.1.4"
- fileset "^2.0.2"
- istanbul-lib-coverage "^1.2.1"
- istanbul-lib-hook "^1.2.2"
- istanbul-lib-instrument "^1.10.2"
- istanbul-lib-report "^1.1.5"
- istanbul-lib-source-maps "^1.2.6"
- istanbul-reports "^1.5.1"
- js-yaml "^3.7.0"
- mkdirp "^0.5.1"
- once "^1.4.0"
-
-istanbul-api@^2.0.5:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.0.6.tgz#cd7b33ee678f6c01531d05f5e567ebbcd25f8ecc"
- integrity sha512-8W5oeAGWXhtTJjAyVfvavOLVyZCTNCKsyF6GON/INKlBdO7uJ/bv3qnPj5M6ERKzmMCJS1kntnjjGuJ86fn3rQ==
+istanbul-api@^2.0.5, istanbul-api@^2.0.8:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.1.tgz#194b773f6d9cbc99a9258446848b0f988951c4d0"
+ integrity sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==
dependencies:
async "^2.6.1"
compare-versions "^3.2.1"
fileset "^2.0.3"
- istanbul-lib-coverage "^2.0.1"
- istanbul-lib-hook "^2.0.1"
- istanbul-lib-instrument "^3.0.0"
- istanbul-lib-report "^2.0.2"
- istanbul-lib-source-maps "^2.0.1"
- istanbul-reports "^2.0.1"
+ istanbul-lib-coverage "^2.0.3"
+ istanbul-lib-hook "^2.0.3"
+ istanbul-lib-instrument "^3.1.0"
+ istanbul-lib-report "^2.0.4"
+ istanbul-lib-source-maps "^3.0.2"
+ istanbul-reports "^2.1.1"
js-yaml "^3.12.0"
make-dir "^1.3.0"
+ minimatch "^3.0.4"
once "^1.4.0"
-istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0"
- integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==
-
-istanbul-lib-coverage@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#2aee0e073ad8c5f6a0b00e0dfbf52b4667472eda"
- integrity sha512-nPvSZsVlbG9aLhZYaC3Oi1gT/tpyo3Yt5fNyf6NmcKIayz4VV/txxJFFKAK/gU4dcNn8ehsanBbVHVl0+amOLA==
-
-istanbul-lib-hook@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86"
- integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==
- dependencies:
- append-transform "^0.4.0"
+istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#0b891e5ad42312c2b9488554f603795f9a2211ba"
+ integrity sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==
-istanbul-lib-hook@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.1.tgz#918a57b75a0f951d552a08487ca1fa5336433d72"
- integrity sha512-ufiZoiJ8CxY577JJWEeFuxXZoMqiKpq/RqZtOAYuQLvlkbJWscq9n3gc4xrCGH9n4pW0qnTxOz1oyMmVtk8E1w==
+istanbul-lib-hook@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz#e0e581e461c611be5d0e5ef31c5f0109759916fb"
+ integrity sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA==
dependencies:
append-transform "^1.0.0"
-istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.10.2:
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca"
- integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==
- dependencies:
- babel-generator "^6.18.0"
- babel-template "^6.16.0"
- babel-traverse "^6.18.0"
- babel-types "^6.18.0"
- babylon "^6.18.0"
- istanbul-lib-coverage "^1.2.1"
- semver "^5.3.0"
-
-istanbul-lib-instrument@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.0.0.tgz#b5f066b2a161f75788be17a9d556f40a0cf2afc9"
- integrity sha512-eQY9vN9elYjdgN9Iv6NS/00bptm02EBBk70lRMaVjeA6QYocQgenVrSgC28TJurdnZa80AGO3ASdFN+w/njGiQ==
+istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz#a2b5484a7d445f1f311e93190813fa56dfb62971"
+ integrity sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==
dependencies:
"@babel/generator" "^7.0.0"
"@babel/parser" "^7.0.0"
"@babel/template" "^7.0.0"
"@babel/traverse" "^7.0.0"
"@babel/types" "^7.0.0"
- istanbul-lib-coverage "^2.0.1"
+ istanbul-lib-coverage "^2.0.3"
semver "^5.5.0"
-istanbul-lib-report@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c"
- integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==
- dependencies:
- istanbul-lib-coverage "^1.2.1"
- mkdirp "^0.5.1"
- path-parse "^1.0.5"
- supports-color "^3.1.2"
-
-istanbul-lib-report@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.2.tgz#430a2598519113e1da7af274ba861bd42dd97535"
- integrity sha512-rJ8uR3peeIrwAxoDEbK4dJ7cqqtxBisZKCuwkMtMv0xYzaAnsAi3AHrHPAAtNXzG/bcCgZZ3OJVqm1DTi9ap2Q==
+istanbul-lib-report@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz#bfd324ee0c04f59119cb4f07dab157d09f24d7e4"
+ integrity sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA==
dependencies:
- istanbul-lib-coverage "^2.0.1"
+ istanbul-lib-coverage "^2.0.3"
make-dir "^1.3.0"
- supports-color "^5.4.0"
-
-istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.6:
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f"
- integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==
- dependencies:
- debug "^3.1.0"
- istanbul-lib-coverage "^1.2.1"
- mkdirp "^0.5.1"
- rimraf "^2.6.1"
- source-map "^0.5.3"
+ supports-color "^6.0.0"
-istanbul-lib-source-maps@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-2.0.1.tgz#ce8b45131d8293fdeaa732f4faf1852d13d0a97e"
- integrity sha512-30l40ySg+gvBLcxTrLzR4Z2XTRj3HgRCA/p2rnbs/3OiTaoj054gAbuP5DcLOtwqmy4XW8qXBHzrmP2/bQ9i3A==
+istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz#f1e817229a9146e8424a28e5d69ba220fda34156"
+ integrity sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ==
dependencies:
- debug "^3.1.0"
- istanbul-lib-coverage "^2.0.1"
+ debug "^4.1.1"
+ istanbul-lib-coverage "^2.0.3"
make-dir "^1.3.0"
rimraf "^2.6.2"
source-map "^0.6.1"
-istanbul-reports@^1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a"
- integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==
- dependencies:
- handlebars "^4.0.3"
-
-istanbul-reports@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.0.1.tgz#fb8d6ea850701a3984350b977a969e9a556116a7"
- integrity sha512-CT0QgMBJqs6NJLF678ZHcquUAZIoBIUNzdJrRJfpkI9OnzG6MkUfHxbJC3ln981dMswC7/B1mfX3LNkhgJxsuw==
+istanbul-reports@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.1.1.tgz#72ef16b4ecb9a4a7bd0e2001e00f95d1eec8afa9"
+ integrity sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw==
dependencies:
- handlebars "^4.0.11"
+ handlebars "^4.1.0"
istanbul@^0.4.5:
version "0.4.5"
@@ -5659,333 +5719,349 @@ jed@^1.1.1:
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
integrity sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ=
-jest-changed-files@^23.4.2:
- version "23.4.2"
- resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83"
- integrity sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==
+jest-changed-files@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.0.0.tgz#c02c09a8cc9ca93f513166bc773741bd39898ff7"
+ integrity sha512-nnuU510R9U+UX0WNb5XFEcsrMqriSiRLeO9KWDFgPrpToaQm60prfQYpxsXigdClpvNot5bekDY440x9dNGnsQ==
dependencies:
+ execa "^1.0.0"
throat "^4.0.0"
-jest-cli@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4"
- integrity sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==
+jest-cli@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.1.0.tgz#f7cc98995f36e7210cce3cbb12974cbf60940843"
+ integrity sha512-U/iyWPwOI0T1CIxVLtk/2uviOTJ/OiSWJSe8qt6X1VkbbgP+nrtLJlmT9lPBe4lK78VNFJtrJ7pttcNv/s7yCw==
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.1"
exit "^0.1.2"
glob "^7.1.2"
- graceful-fs "^4.1.11"
- import-local "^1.0.0"
- is-ci "^1.0.10"
- istanbul-api "^1.3.1"
- istanbul-lib-coverage "^1.2.0"
- istanbul-lib-instrument "^1.10.1"
- istanbul-lib-source-maps "^1.2.4"
- jest-changed-files "^23.4.2"
- jest-config "^23.6.0"
- jest-environment-jsdom "^23.4.0"
- jest-get-type "^22.1.0"
- jest-haste-map "^23.6.0"
- jest-message-util "^23.4.0"
- jest-regex-util "^23.3.0"
- jest-resolve-dependencies "^23.6.0"
- jest-runner "^23.6.0"
- jest-runtime "^23.6.0"
- jest-snapshot "^23.6.0"
- jest-util "^23.4.0"
- jest-validate "^23.6.0"
- jest-watcher "^23.4.0"
- jest-worker "^23.2.0"
- micromatch "^2.3.11"
+ graceful-fs "^4.1.15"
+ import-local "^2.0.0"
+ is-ci "^2.0.0"
+ istanbul-api "^2.0.8"
+ istanbul-lib-coverage "^2.0.2"
+ istanbul-lib-instrument "^3.0.1"
+ istanbul-lib-source-maps "^3.0.1"
+ jest-changed-files "^24.0.0"
+ jest-config "^24.1.0"
+ jest-environment-jsdom "^24.0.0"
+ jest-get-type "^24.0.0"
+ jest-haste-map "^24.0.0"
+ jest-message-util "^24.0.0"
+ jest-regex-util "^24.0.0"
+ jest-resolve-dependencies "^24.1.0"
+ jest-runner "^24.1.0"
+ jest-runtime "^24.1.0"
+ jest-snapshot "^24.1.0"
+ jest-util "^24.0.0"
+ jest-validate "^24.0.0"
+ jest-watcher "^24.0.0"
+ jest-worker "^24.0.0"
+ micromatch "^3.1.10"
node-notifier "^5.2.1"
- prompts "^0.1.9"
+ p-each-series "^1.0.0"
+ pirates "^4.0.0"
+ prompts "^2.0.1"
realpath-native "^1.0.0"
rimraf "^2.5.4"
- slash "^1.0.0"
+ slash "^2.0.0"
string-length "^2.0.0"
- strip-ansi "^4.0.0"
+ strip-ansi "^5.0.0"
which "^1.2.12"
- yargs "^11.0.0"
+ yargs "^12.0.2"
-jest-config@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d"
- integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==
+jest-config@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.1.0.tgz#6ea6881cfdd299bc86cc144ee36d937c97c3850c"
+ integrity sha512-FbbRzRqtFC6eGjG5VwsbW4E5dW3zqJKLWYiZWhB0/4E5fgsMw8GODLbGSrY5t17kKOtCWb/Z7nsIThRoDpuVyg==
dependencies:
- babel-core "^6.0.0"
- babel-jest "^23.6.0"
+ "@babel/core" "^7.1.0"
+ babel-jest "^24.1.0"
chalk "^2.0.1"
glob "^7.1.1"
- jest-environment-jsdom "^23.4.0"
- jest-environment-node "^23.4.0"
- jest-get-type "^22.1.0"
- jest-jasmine2 "^23.6.0"
- jest-regex-util "^23.3.0"
- jest-resolve "^23.6.0"
- jest-util "^23.4.0"
- jest-validate "^23.6.0"
- micromatch "^2.3.11"
- pretty-format "^23.6.0"
-
-jest-diff@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d"
- integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==
+ jest-environment-jsdom "^24.0.0"
+ jest-environment-node "^24.0.0"
+ jest-get-type "^24.0.0"
+ jest-jasmine2 "^24.1.0"
+ jest-regex-util "^24.0.0"
+ jest-resolve "^24.1.0"
+ jest-util "^24.0.0"
+ jest-validate "^24.0.0"
+ micromatch "^3.1.10"
+ pretty-format "^24.0.0"
+ realpath-native "^1.0.2"
+
+jest-diff@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.0.0.tgz#a3e5f573dbac482f7d9513ac9cfa21644d3d6b34"
+ integrity sha512-XY5wMpRaTsuMoU+1/B2zQSKQ9RdE9gsLkGydx3nvApeyPijLA8GtEvIcPwISRCer+VDf9W1mStTYYq6fPt8ryA==
dependencies:
chalk "^2.0.1"
- diff "^3.2.0"
- jest-get-type "^22.1.0"
- pretty-format "^23.6.0"
+ diff-sequences "^24.0.0"
+ jest-get-type "^24.0.0"
+ pretty-format "^24.0.0"
-jest-docblock@^23.2.0:
- version "23.2.0"
- resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7"
- integrity sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=
+jest-docblock@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.0.0.tgz#54d77a188743e37f62181a91a01eb9222289f94e"
+ integrity sha512-KfAKZ4SN7CFOZpWg4i7g7MSlY0M+mq7K0aMqENaG2vHuhC9fc3vkpU/iNN9sOus7v3h3Y48uEjqz3+Gdn2iptA==
dependencies:
detect-newline "^2.1.0"
-jest-each@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575"
- integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==
+jest-each@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.0.0.tgz#10987a06b21c7ffbfb7706c89d24c52ed864be55"
+ integrity sha512-gFcbY4Cu55yxExXMkjrnLXov3bWO3dbPAW7HXb31h/DNWdNc/6X8MtxGff8nh3/MjkF9DpVqnj0KsPKuPK0cpA==
dependencies:
chalk "^2.0.1"
- pretty-format "^23.6.0"
+ jest-get-type "^24.0.0"
+ jest-util "^24.0.0"
+ pretty-format "^24.0.0"
-jest-environment-jsdom@^23.4.0:
- version "23.4.0"
- resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023"
- integrity sha1-BWp5UrP+pROsYqFAosNox52eYCM=
+jest-environment-jsdom@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0.tgz#5affa0654d6e44cd798003daa1a8701dbd6e4d11"
+ integrity sha512-1YNp7xtxajTRaxbylDc2pWvFnfDTH5BJJGyVzyGAKNt/lEULohwEV9zFqTgG4bXRcq7xzdd+sGFws+LxThXXOw==
dependencies:
- jest-mock "^23.2.0"
- jest-util "^23.4.0"
+ jest-mock "^24.0.0"
+ jest-util "^24.0.0"
jsdom "^11.5.1"
-jest-environment-node@^23.4.0:
- version "23.4.0"
- resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10"
- integrity sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=
+jest-environment-node@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.0.0.tgz#330948980656ed8773ce2e04eb597ed91e3c7190"
+ integrity sha512-62fOFcaEdU0VLaq8JL90TqwI7hLn0cOKOl8vY2n477vRkCJRojiRRtJVRzzCcgFvs6gqU97DNqX5R0BrBP6Rxg==
dependencies:
- jest-mock "^23.2.0"
- jest-util "^23.4.0"
+ jest-mock "^24.0.0"
+ jest-util "^24.0.0"
-jest-get-type@^22.1.0:
- version "22.4.3"
- resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4"
- integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==
+jest-get-type@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.0.0.tgz#36e72930b78e33da59a4f63d44d332188278940b"
+ integrity sha512-z6/Eyf6s9ZDGz7eOvl+fzpuJmN9i0KyTt1no37/dHu8galssxz5ZEgnc1KaV8R31q1khxyhB4ui/X5ZjjPk77w==
-jest-haste-map@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16"
- integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==
+jest-haste-map@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0.tgz#e9ef51b2c9257384b4d6beb83bd48c65b37b5e6e"
+ integrity sha512-CcViJyUo41IQqttLxXVdI41YErkzBKbE6cS6dRAploCeutePYfUimWd3C9rQEWhX0YBOQzvNsC0O9nYxK2nnxQ==
dependencies:
fb-watchman "^2.0.0"
- graceful-fs "^4.1.11"
+ graceful-fs "^4.1.15"
invariant "^2.2.4"
- jest-docblock "^23.2.0"
- jest-serializer "^23.0.1"
- jest-worker "^23.2.0"
- micromatch "^2.3.11"
- sane "^2.0.0"
-
-jest-jasmine2@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0"
- integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==
- dependencies:
- babel-traverse "^6.0.0"
+ jest-serializer "^24.0.0"
+ jest-util "^24.0.0"
+ jest-worker "^24.0.0"
+ micromatch "^3.1.10"
+ sane "^3.0.0"
+
+jest-jasmine2@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.1.0.tgz#8377324b967037c440f0a549ee0bbd9912055db6"
+ integrity sha512-H+o76SdSNyCh9fM5K8upK45YTo/DiFx5w2YAzblQebSQmukDcoVBVeXynyr7DDnxh+0NTHYRCLwJVf3tC518wg==
+ dependencies:
+ "@babel/traverse" "^7.1.0"
chalk "^2.0.1"
co "^4.6.0"
- expect "^23.6.0"
- is-generator-fn "^1.0.0"
- jest-diff "^23.6.0"
- jest-each "^23.6.0"
- jest-matcher-utils "^23.6.0"
- jest-message-util "^23.4.0"
- jest-snapshot "^23.6.0"
- jest-util "^23.4.0"
- pretty-format "^23.6.0"
-
-jest-junit@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-5.2.0.tgz#980401db7aa69999cf117c6d740a8135c22ae379"
- integrity sha512-Mdg0Qpdh1Xm/FA1B/mcLlmEmlr3XzH5pZg7MvcAwZhjHijPRd1z/UwYwkwNHmCV7o4ZOWCf77nLu7ZkhHHrtJg==
+ expect "^24.1.0"
+ is-generator-fn "^2.0.0"
+ jest-each "^24.0.0"
+ jest-matcher-utils "^24.0.0"
+ jest-message-util "^24.0.0"
+ jest-snapshot "^24.1.0"
+ jest-util "^24.0.0"
+ pretty-format "^24.0.0"
+ throat "^4.0.0"
+
+jest-junit@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-6.3.0.tgz#99e64ebc54eddcb21238f0cc49f5820c89a8c785"
+ integrity sha512-3PH9UkpaomX6CUzqjlnk0m4yBCW/eroxV6v61OM6LkCQFO848P3YUhfIzu8ypZSBKB3vvCbB4WaLTKT0BrIf8A==
dependencies:
- jest-config "^23.6.0"
- jest-validate "^23.0.1"
+ jest-validate "^24.0.0"
mkdirp "^0.5.1"
strip-ansi "^4.0.0"
xml "^1.0.1"
-jest-leak-detector@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de"
- integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==
+jest-leak-detector@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.0.0.tgz#78280119fd05ee98317daee62cddb3aa537a31c6"
+ integrity sha512-ZYHJYFeibxfsDSKowjDP332pStuiFT2xfc5R67Rjm/l+HFJWJgNIOCOlQGeXLCtyUn3A23+VVDdiCcnB6dTTrg==
dependencies:
- pretty-format "^23.6.0"
+ pretty-format "^24.0.0"
-jest-matcher-utils@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80"
- integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==
+jest-matcher-utils@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.0.0.tgz#fc9c41cfc49b2c3ec14e576f53d519c37729d579"
+ integrity sha512-LQTDmO+aWRz1Tf9HJg+HlPHhDh1E1c65kVwRFo5mwCVp5aQDzlkz4+vCvXhOKFjitV2f0kMdHxnODrXVoi+rlA==
dependencies:
chalk "^2.0.1"
- jest-get-type "^22.1.0"
- pretty-format "^23.6.0"
+ jest-diff "^24.0.0"
+ jest-get-type "^24.0.0"
+ pretty-format "^24.0.0"
-jest-message-util@^23.4.0:
- version "23.4.0"
- resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f"
- integrity sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=
+jest-message-util@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.0.0.tgz#a07a141433b2c992dbaec68d4cbfe470ba289619"
+ integrity sha512-J9ROJIwz/IeC+eV1XSwnRK4oAwPuhmxEyYx1+K5UI+pIYwFZDSrfZaiWTdq0d2xYFw4Xiu+0KQWsdsQpgJMf3Q==
dependencies:
- "@babel/code-frame" "^7.0.0-beta.35"
+ "@babel/code-frame" "^7.0.0"
chalk "^2.0.1"
- micromatch "^2.3.11"
- slash "^1.0.0"
+ micromatch "^3.1.10"
+ slash "^2.0.0"
stack-utils "^1.0.1"
-jest-mock@^23.2.0:
- version "23.2.0"
- resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134"
- integrity sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=
+jest-mock@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.0.0.tgz#9a4b53e01d66a0e780f7d857462d063e024c617d"
+ integrity sha512-sQp0Hu5fcf5NZEh1U9eIW2qD0BwJZjb63Yqd98PQJFvf/zzUTBoUAwv/Dc/HFeNHIw1f3hl/48vNn+j3STaI7A==
-jest-regex-util@^23.3.0:
- version "23.3.0"
- resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5"
- integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=
+jest-regex-util@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.0.0.tgz#4feee8ec4a358f5bee0a654e94eb26163cb9089a"
+ integrity sha512-Jv/uOTCuC+PY7WpJl2mpoI+WbY2ut73qwwO9ByJJNwOCwr1qWhEW2Lyi2S9ZewUdJqeVpEBisdEVZSI+Zxo58Q==
-jest-resolve-dependencies@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d"
- integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==
+jest-resolve-dependencies@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.1.0.tgz#78f738a2ec59ff4d00751d9da56f176e3f589f6c"
+ integrity sha512-2VwPsjd3kRPu7qe2cpytAgowCObk5AKeizfXuuiwgm1a9sijJDZe8Kh1sFj6FKvSaNEfCPlBVkZEJa2482m/Uw==
dependencies:
- jest-regex-util "^23.3.0"
- jest-snapshot "^23.6.0"
+ jest-regex-util "^24.0.0"
+ jest-snapshot "^24.1.0"
-jest-resolve@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae"
- integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==
+jest-resolve@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.1.0.tgz#42ff0169b0ea47bfdbd0c52a0067ca7d022c7688"
+ integrity sha512-TPiAIVp3TG6zAxH28u/6eogbwrvZjBMWroSLBDkwkHKrqxB/RIdwkWDye4uqPlZIXWIaHtifY3L0/eO5Z0f2wg==
dependencies:
browser-resolve "^1.11.3"
chalk "^2.0.1"
realpath-native "^1.0.0"
-jest-runner@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38"
- integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==
+jest-runner@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.1.0.tgz#3686a2bb89ce62800da23d7fdc3da2c32792943b"
+ integrity sha512-CDGOkT3AIFl16BLL/OdbtYgYvbAprwJ+ExKuLZmGSCSldwsuU2dEGauqkpvd9nphVdAnJUcP12e/EIlnTX0QXg==
dependencies:
+ chalk "^2.4.2"
exit "^0.1.2"
- graceful-fs "^4.1.11"
- jest-config "^23.6.0"
- jest-docblock "^23.2.0"
- jest-haste-map "^23.6.0"
- jest-jasmine2 "^23.6.0"
- jest-leak-detector "^23.6.0"
- jest-message-util "^23.4.0"
- jest-runtime "^23.6.0"
- jest-util "^23.4.0"
- jest-worker "^23.2.0"
+ graceful-fs "^4.1.15"
+ jest-config "^24.1.0"
+ jest-docblock "^24.0.0"
+ jest-haste-map "^24.0.0"
+ jest-jasmine2 "^24.1.0"
+ jest-leak-detector "^24.0.0"
+ jest-message-util "^24.0.0"
+ jest-runtime "^24.1.0"
+ jest-util "^24.0.0"
+ jest-worker "^24.0.0"
source-map-support "^0.5.6"
throat "^4.0.0"
-jest-runtime@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082"
- integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==
+jest-runtime@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.1.0.tgz#7c157a2e776609e8cf552f956a5a19ec9c985214"
+ integrity sha512-59/BY6OCuTXxGeDhEMU7+N33dpMQyXq7MLK07cNSIY/QYt2QZgJ7Tjx+rykBI0skAoigFl0A5tmT8UdwX92YuQ==
dependencies:
- babel-core "^6.0.0"
- babel-plugin-istanbul "^4.1.6"
+ "@babel/core" "^7.1.0"
+ babel-plugin-istanbul "^5.1.0"
chalk "^2.0.1"
convert-source-map "^1.4.0"
exit "^0.1.2"
fast-json-stable-stringify "^2.0.0"
- graceful-fs "^4.1.11"
- jest-config "^23.6.0"
- jest-haste-map "^23.6.0"
- jest-message-util "^23.4.0"
- jest-regex-util "^23.3.0"
- jest-resolve "^23.6.0"
- jest-snapshot "^23.6.0"
- jest-util "^23.4.0"
- jest-validate "^23.6.0"
- micromatch "^2.3.11"
+ glob "^7.1.3"
+ graceful-fs "^4.1.15"
+ jest-config "^24.1.0"
+ jest-haste-map "^24.0.0"
+ jest-message-util "^24.0.0"
+ jest-regex-util "^24.0.0"
+ jest-resolve "^24.1.0"
+ jest-snapshot "^24.1.0"
+ jest-util "^24.0.0"
+ jest-validate "^24.0.0"
+ micromatch "^3.1.10"
realpath-native "^1.0.0"
- slash "^1.0.0"
- strip-bom "3.0.0"
- write-file-atomic "^2.1.0"
- yargs "^11.0.0"
-
-jest-serializer@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165"
- integrity sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=
-
-jest-snapshot@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a"
- integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==
- dependencies:
- babel-types "^6.0.0"
+ slash "^2.0.0"
+ strip-bom "^3.0.0"
+ write-file-atomic "2.4.1"
+ yargs "^12.0.2"
+
+jest-serializer@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0.tgz#522c44a332cdd194d8c0531eb06a1ee5afb4256b"
+ integrity sha512-9FKxQyrFgHtx3ozU+1a8v938ILBE7S8Ko3uiAVjT8Yfi2o91j/fj81jacCQZ/Ihjiff/VsUCXVgQ+iF1XdImOw==
+
+jest-snapshot@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.1.0.tgz#85e22f810357aa5994ab61f236617dc2205f2f5b"
+ integrity sha512-th6TDfFqEmXvuViacU1ikD7xFb7lQsPn2rJl7OEmnfIVpnrx3QNY2t3PE88meeg0u/mQ0nkyvmC05PBqO4USFA==
+ dependencies:
+ "@babel/types" "^7.0.0"
chalk "^2.0.1"
- jest-diff "^23.6.0"
- jest-matcher-utils "^23.6.0"
- jest-message-util "^23.4.0"
- jest-resolve "^23.6.0"
+ jest-diff "^24.0.0"
+ jest-matcher-utils "^24.0.0"
+ jest-message-util "^24.0.0"
+ jest-resolve "^24.1.0"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
- pretty-format "^23.6.0"
+ pretty-format "^24.0.0"
semver "^5.5.0"
-jest-util@^23.4.0:
- version "23.4.0"
- resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561"
- integrity sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=
+jest-transform-graphql@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/jest-transform-graphql/-/jest-transform-graphql-2.1.0.tgz#903cb66bb27bc2772fd3e5dd4f7e9b57230f5829"
+ integrity sha1-kDy2a7J7wncv0+XdT36bVyMPWCk=
+
+jest-util@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.0.0.tgz#fd38fcafd6dedbd0af2944d7a227c0d91b68f7d6"
+ integrity sha512-QxsALc4wguYS7cfjdQSOr5HTkmjzkHgmZvIDkcmPfl1ib8PNV8QUWLwbKefCudWS0PRKioV+VbQ0oCUPC691fQ==
dependencies:
- callsites "^2.0.0"
+ callsites "^3.0.0"
chalk "^2.0.1"
- graceful-fs "^4.1.11"
- is-ci "^1.0.10"
- jest-message-util "^23.4.0"
+ graceful-fs "^4.1.15"
+ is-ci "^2.0.0"
+ jest-message-util "^24.0.0"
mkdirp "^0.5.1"
- slash "^1.0.0"
+ slash "^2.0.0"
source-map "^0.6.0"
-jest-validate@^23.0.1, jest-validate@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474"
- integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==
+jest-validate@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.0.0.tgz#aa8571a46983a6538328fef20406b4a496b6c020"
+ integrity sha512-vMrKrTOP4BBFIeOWsjpsDgVXATxCspC9S1gqvbJ3Tnn/b9ACsJmteYeVx9830UMV28Cob1RX55x96Qq3Tfad4g==
dependencies:
+ camelcase "^5.0.0"
chalk "^2.0.1"
- jest-get-type "^22.1.0"
+ jest-get-type "^24.0.0"
leven "^2.1.0"
- pretty-format "^23.6.0"
+ pretty-format "^24.0.0"
-jest-watcher@^23.4.0:
- version "23.4.0"
- resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c"
- integrity sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=
+jest-watcher@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.0.0.tgz#20d44244d10b0b7312410aefd256c1c1eef68890"
+ integrity sha512-GxkW2QrZ4YxmW1GUWER05McjVDunBlKMFfExu+VsGmXJmpej1saTEKvONdx5RJBlVdpPI5x6E3+EDQSIGgl53g==
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.1"
+ jest-util "^24.0.0"
string-length "^2.0.0"
-jest-worker@^23.2.0:
- version "23.2.0"
- resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9"
- integrity sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=
+jest-worker@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0.tgz#3d3483b077bf04f412f47654a27bba7e947f8b6d"
+ integrity sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg==
dependencies:
merge-stream "^1.0.1"
+ supports-color "^6.1.0"
-jest@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d"
- integrity sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==
+jest@^24.1.0:
+ version "24.1.0"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-24.1.0.tgz#b1e1135caefcf2397950ecf7f90e395fde866fd2"
+ integrity sha512-+q91L65kypqklvlRFfXfdzUKyngQLOcwGhXQaLmVHv+d09LkNXuBuGxlofTFW42XMzu3giIcChchTsCNUjQ78A==
dependencies:
- import-local "^1.0.0"
- jest-cli "^23.6.0"
+ import-local "^2.0.0"
+ jest-cli "^24.1.0"
jquery-ujs@1.2.2:
version "1.2.2"
@@ -6004,7 +6080,7 @@ jquery.waitforimages@^2.2.0:
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
-js-beautify@^1.6.14, js-beautify@^1.8.8:
+js-beautify@^1.8.8:
version "1.8.9"
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.8.9.tgz#08e3c05ead3ecfbd4f512c3895b1cda76c87d523"
integrity sha512-MwPmLywK9RSX0SPsUJjN7i+RQY9w/yC17Lbrq9ViEefpLRgqAR2BgrMN2AbifkUuhDV8tRauLhLda/9+bE0YQA==
@@ -6035,19 +6111,49 @@ js-tokens@^3.0.2:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
-js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.7.0:
- version "3.12.0"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
- integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==
+js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.9.0:
+ version "3.12.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600"
+ integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
+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@^11.5.1:
version "11.12.0"
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
@@ -6080,11 +6186,6 @@ jsdom@^11.5.1:
ws "^5.2.0"
xml-name-validator "^3.0.0"
-jsesc@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
- integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s=
-
jsesc@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe"
@@ -6130,7 +6231,14 @@ json3@^3.3.2:
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=
-json5@^0.5.0, json5@^0.5.1:
+json5@2.x, json5@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850"
+ integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==
+ dependencies:
+ minimist "^1.2.0"
+
+json5@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
@@ -6250,12 +6358,12 @@ karma@^3.0.0:
tmp "0.0.33"
useragent "2.2.1"
-katex@^0.9.0:
- version "0.9.0"
- resolved "https://registry.yarnpkg.com/katex/-/katex-0.9.0.tgz#26a7d082c21d53725422d2d71da9b2d8455fbd4a"
- integrity sha512-lp3x90LT1tDZBW2tjLheJ98wmRMRjUHwk4QpaswT9bhqoQZ+XA4cPcjcQBxgOQNwaOSt6ZeL/a6GKQ1of3LFxQ==
+katex@^0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/katex/-/katex-0.10.0.tgz#da562e5d0d5cc3aa602e27af8a9b8710bfbce765"
+ integrity sha512-/WRvx+L1eVBrLwX7QzKU1dQuaGnE7E8hDvx3VWfZh9HbMiCfsKWJNnYZ0S8ZMDAfAyDSofdyXIrH/hujF1fYXg==
dependencies:
- match-at "^0.1.1"
+ commander "^2.16.0"
keyv@3.0.0:
version "3.0.0"
@@ -6293,10 +6401,22 @@ kind-of@^6.0.0, kind-of@^6.0.2:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
-kleur@^2.0.1:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
- integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==
+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.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.2.tgz#83c7ec858a41098b613d5998a7b653962b504f68"
+ integrity sha512-3h7B2WRT5LNXOtQiAaWonilegHcPSf9nLVXlSTci8lu1dZUuui61+EsPEZqSVxY7rXYmB2DVKMQILxaO5WL61Q==
+
+known-css-properties@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.11.0.tgz#0da784f115ea77c76b81536d7052e90ee6c86a8a"
+ integrity sha512-bEZlJzXo5V/ApNNa5z375mJC6Nrz4vG43UgcSCrg2OHC+yuB6j0iDSrY7RQ/+PRofFB03wNIIt9iXIVLr4wc7w==
latest-version@^3.0.0:
version "3.1.0"
@@ -6351,16 +6471,17 @@ lie@~3.1.0:
dependencies:
immediate "~3.0.5"
-load-json-file@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
- integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
+lightercollective@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/lightercollective/-/lightercollective-0.1.0.tgz#70df102c530dcb8d0ccabfe6175a8d00d5f61300"
+ integrity sha512-J9tg5uraYoQKaWbmrzDDexbG6hHnMcWS1qLYgJSWE+mpA3U5OCSeMUhb+K55otgZJ34oFdR0ECvdIb3xuO5JOQ==
+
+linkify-it@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.1.0.tgz#c4caf38a6cd7ac2212ef3c7d2bde30a91561f9db"
+ integrity sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg==
dependencies:
- graceful-fs "^4.1.2"
- parse-json "^2.2.0"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
- strip-bom "^2.0.0"
+ uc.micro "^1.0.1"
load-json-file@^2.0.0:
version "2.0.0"
@@ -6412,7 +6533,7 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
-lodash.camelcase@4.3.0, lodash.camelcase@^4.3.0:
+lodash.camelcase@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
@@ -6472,12 +6593,12 @@ lodash.upperfirst@4.3.1:
resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce"
integrity sha1-E2Xt9DFIBIHvDRxolXpe2Z1J984=
-lodash@4.x, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0:
+lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
-log-symbols@^2.1.0:
+log-symbols@^2.0.0, log-symbols@^2.1.0, log-symbols@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
@@ -6500,6 +6621,11 @@ loglevel@^1.4.1:
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.4.1.tgz#95b383f91a3c2756fd4ab093667e4309161f2bcd"
integrity sha1-lbOD+Ro8J1b9SrCTZn5DCRYfK80=
+longest-streak@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e"
+ integrity sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==
+
loose-envify@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@@ -6507,17 +6633,33 @@ loose-envify@^1.0.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
+loud-rejection@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+ integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
+ dependencies:
+ currently-unhandled "^0.4.1"
+ signal-exit "^3.0.0"
+
lowercase-keys@1.0.0, lowercase-keys@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306"
integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=
+lowlight@^1.11.0:
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.11.0.tgz#1304d83005126d4e8b1dc0f07981e9b689ec2efc"
+ integrity sha512-xrGGN6XLL7MbTMdPD6NfWPwY43SNkjf/d0mecSx/CW36fUZTjRHEq0/Cdug3TWKtRXLWi7iMl1eP0olYxj/a4A==
+ dependencies:
+ fault "^1.0.2"
+ highlight.js "~9.13.0"
+
lru-cache@2.2.x:
version "2.2.4"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d"
integrity sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=
-lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2, lru-cache@^4.1.3:
+lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==
@@ -6525,6 +6667,13 @@ lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2, lru-cache@^4.1.3:
pseudomap "^1.0.2"
yallist "^2.1.2"
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
lz-string@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
@@ -6537,6 +6686,11 @@ make-dir@^1.0.0, make-dir@^1.3.0:
dependencies:
pify "^3.0.0"
+make-error@1.x:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
+ integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==
+
makeerror@1.0.x:
version "1.0.11"
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
@@ -6544,11 +6698,6 @@ makeerror@1.0.x:
dependencies:
tmpl "1.0.x"
-mamacro@^0.0.3:
- version "0.0.3"
- resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4"
- integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==
-
map-age-cleaner@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74"
@@ -6561,10 +6710,15 @@ map-cache@^0.2.2:
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
-map-stream@~0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
- integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=
+map-obj@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+ integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
+
+map-obj@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9"
+ integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk=
map-visit@^1.0.0:
version "1.0.0"
@@ -6573,20 +6727,36 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
-marked@^0.3.12:
- version "0.3.12"
- resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.12.tgz#7cf25ff2252632f3fe2406bde258e94eee927519"
- integrity sha512-k4NaW+vS7ytQn6MgJn3fYpQt20/mOgYM5Ft9BYMfQJDz2QT6yEeS9XJ8k2Nw8JTeWK/znPPW2n3UJGzyYEiMoA==
+markdown-escapes@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122"
+ integrity sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==
-match-at@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.1.tgz#25d040d291777704d5e6556bbb79230ec2de0540"
- integrity sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q==
+markdown-it@^8.4.2:
+ version "8.4.2"
+ resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"
+ integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==
+ dependencies:
+ argparse "^1.0.7"
+ entities "~1.1.1"
+ linkify-it "^2.0.0"
+ mdurl "^1.0.1"
+ uc.micro "^1.0.5"
-math-random@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac"
- integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w=
+markdown-table@^1.1.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.2.tgz#c78db948fa879903a41bce522e3b96f801c63786"
+ integrity sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==
+
+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==
+
+mathml-tag-names@^2.0.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz#490b70e062ee24636536e3d9481e333733d00f2c"
+ integrity sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg==
md5.js@^1.3.4:
version "1.3.4"
@@ -6596,6 +6766,18 @@ md5.js@^1.3.4:
hash-base "^3.0.0"
inherits "^2.0.1"
+mdast-util-compact@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz#c12ebe16fffc84573d3e19767726de226e95f649"
+ integrity sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==
+ dependencies:
+ unist-util-visit "^1.1.0"
+
+mdurl@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
+ integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
+
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@@ -6630,6 +6812,21 @@ memory-fs@^0.4.0, memory-fs@~0.4.1:
errno "^0.1.3"
readable-stream "^2.0.1"
+meow@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4"
+ integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==
+ dependencies:
+ camelcase-keys "^4.0.0"
+ decamelize-keys "^1.0.0"
+ loud-rejection "^1.0.0"
+ minimist-options "^3.0.1"
+ normalize-package-data "^2.3.4"
+ read-pkg-up "^3.0.0"
+ redent "^2.0.0"
+ trim-newlines "^2.0.0"
+ yargs-parser "^10.0.0"
+
merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
@@ -6649,6 +6846,11 @@ merge-stream@^1.0.1:
dependencies:
readable-stream "^2.0.1"
+merge2@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5"
+ integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==
+
merge@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145"
@@ -6673,26 +6875,7 @@ methods@~1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
-micromatch@^2.3.11:
- version "2.3.11"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
- integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
- dependencies:
- arr-diff "^2.0.0"
- array-unique "^0.2.1"
- braces "^1.8.2"
- expand-brackets "^0.1.4"
- extglob "^0.3.1"
- filename-regex "^2.0.0"
- is-extglob "^1.0.0"
- is-glob "^2.0.1"
- kind-of "^3.0.2"
- normalize-path "^2.0.1"
- object.omit "^2.0.0"
- parse-glob "^3.0.4"
- regex-cache "^0.4.2"
-
-micromatch@^3.1.4, micromatch@^3.1.6, micromatch@^3.1.8, micromatch@^3.1.9:
+micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.6, micromatch@^3.1.8, micromatch@^3.1.9:
version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
@@ -6768,11 +6951,24 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
dependencies:
brace-expansion "^1.1.7"
+minimist-options@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954"
+ integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==
+ dependencies:
+ arrify "^1.0.1"
+ is-plain-obj "^1.1.0"
+
minimist@0.0.8, minimist@~0.0.1:
version "0.0.8"
resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
+minimist@1.1.x:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
+ integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=
+
minimist@1.2.0, minimist@^1.1.1, minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
@@ -6793,22 +6989,6 @@ minizlib@^1.1.0:
dependencies:
minipass "^2.2.1"
-mississippi@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f"
- integrity sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==
- dependencies:
- concat-stream "^1.5.0"
- duplexify "^3.4.2"
- end-of-stream "^1.1.0"
- flush-write-stream "^1.0.0"
- from2 "^2.1.0"
- parallel-transform "^1.1.0"
- pump "^2.0.1"
- pumpify "^1.3.3"
- stream-each "^1.1.0"
- through2 "^2.0.0"
-
mississippi@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
@@ -6833,27 +7013,29 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
-mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
+mkdirp@0.5.x, mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
version "0.5.1"
resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies:
minimist "0.0.8"
-moment@2.x, moment@^2.21.0:
- version "2.22.2"
- resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
- integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=
+moment@2.x, moment@^2.10.2, moment@^2.21.0:
+ version "2.23.0"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.23.0.tgz#759ea491ac97d54bac5ad776996e2a58cc1bc225"
+ integrity sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==
-monaco-editor-webpack-plugin@^1.5.4:
- version "1.5.4"
- resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.5.4.tgz#6781a130e3e1379bb8f4cd190132f4af6dcd2c16"
- integrity sha512-9YmWYQdZoAoZ1RLy/uvoDbCcb0EKy5O2qoMQn+UIVQxk+VTCXfJDgANczDIWko+UOzg0MY0P+sA8bl4XI14RJg==
+monaco-editor-webpack-plugin@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.7.0.tgz#920cbeecca25f15d70d568a7e11b0ba4daf1ae83"
+ integrity sha512-oItymcnlL14Sjd7EF7q+CMhucfwR/2BxsqrXIBrWL6LQplFfAfV+grLEQRmVHeGSBZ/Gk9ptzfueXnWcoEcFuA==
+ dependencies:
+ "@types/webpack" "^4.4.19"
-monaco-editor@^0.14.3:
- version "0.14.3"
- resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.14.3.tgz#7cc4a4096a3821f52fea9b10489b527ef3034e22"
- integrity sha512-RhaO4xXmWn/p0WrkEOXe4PoZj6xOcvDYjoAh0e1kGUrQnP1IOpc0m86Ceuaa2CLEMDINqKijBSmqhvBQnsPLHQ==
+monaco-editor@^0.15.6:
+ version "0.15.6"
+ resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.15.6.tgz#d63b3b06f86f803464f003b252627c3eb4a09483"
+ integrity sha512-JoU9V9k6KqT9R9Tiw1RTU8ohZ+Xnf9DMg6Ktqqw5hILumwmq7xqa/KLXw513uTUsWbhtnHoSJYYR++u3pkyxJg==
mousetrap@^1.4.6:
version "1.4.6"
@@ -6942,24 +7124,16 @@ negotiator@0.6.1:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
-neo-async@^2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.0.tgz#76b1c823130cca26acfbaccc8fbaf0a2fa33b18f"
- integrity sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==
+neo-async@^2.5.0, neo-async@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835"
+ integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==
nice-try@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4"
integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==
-node-cache@^4.1.1:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.0.tgz#48ac796a874e762582692004a376d26dfa875811"
- integrity sha512-obRu6/f7S024ysheAjoYFEEBqqDWv4LOMNJEuO8vMeEw2AT4z+NCzO4hlc2lhI4vATzbCQv6kke9FVdx0RbCOw==
- dependencies:
- clone "2.x"
- lodash "4.x"
-
node-fetch@1.6.3:
version "1.6.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
@@ -7007,6 +7181,11 @@ node-int64@^0.4.0:
util "^0.10.3"
vm-browserify "0.0.4"
+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@^5.2.1:
version "5.3.0"
resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.3.0.tgz#c77a4a7b84038733d5fb351aafd8a268bfe19a01"
@@ -7033,28 +7212,28 @@ node-pre-gyp@^0.10.0:
semver "^5.3.0"
tar "^4"
-node-releases@^1.0.0-alpha.11:
- version "1.0.0-alpha.12"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.12.tgz#32e461b879ea76ac674e511d9832cf29da345268"
- integrity sha512-VPB4rTPqpVyWKBHbSa4YPFme3+8WHsOSpvbp0Mfj0bWsC8TEjt4HQrLl1hsBDELlp1nB4lflSgSuGTYiuyaP7Q==
+node-releases@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.3.tgz#aad9ce0dcb98129c753f772c0aa01360fb90fbd2"
+ integrity sha512-6VrvH7z6jqqNFY200kdB6HdzkgM96Oaj9v3dqGfgp6mF+cHmU4wyQKZ2/WPDRVoR0Jz9KqbamaBN0ZhdUaysUQ==
dependencies:
semver "^5.3.0"
-nodemon@^1.18.4:
- version "1.18.4"
- resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.4.tgz#873f65fdb53220eb166180cf106b1354ac5d714d"
- integrity sha512-hyK6vl65IPnky/ee+D3IWvVGgJa/m3No2/Xc/3wanS6Ce1MWjCzH6NnhPJ/vZM+6JFym16jtHx51lmCMB9HDtg==
+nodemon@^1.18.9:
+ version "1.18.9"
+ resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.9.tgz#90b467efd3b3c81b9453380aeb2a2cba535d0ead"
+ integrity sha512-oj/eEVTEI47pzYAjGkpcNw0xYwTl4XSTUQv2NPQI6PpN3b75PhpuYk3Vb3U80xHCyM2Jm+1j68ULHXl4OR3Afw==
dependencies:
- chokidar "^2.0.2"
+ chokidar "^2.0.4"
debug "^3.1.0"
ignore-by-default "^1.0.1"
minimatch "^3.0.4"
- pstree.remy "^1.1.0"
+ pstree.remy "^1.1.6"
semver "^5.5.0"
supports-color "^5.2.0"
touch "^3.1.0"
undefsafe "^2.0.2"
- update-notifier "^2.3.0"
+ update-notifier "^2.5.0"
nopt@3.x:
version "3.0.6"
@@ -7078,23 +7257,38 @@ nopt@~1.0.10:
dependencies:
abbrev "1"
-normalize-package-data@^2.3.2:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
- integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==
+normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
dependencies:
hosted-git-info "^2.1.4"
- is-builtin-module "^1.0.0"
+ resolve "^1.10.0"
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
-normalize-path@^2.0.1, normalize-path@^2.1.1:
+normalize-path@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
dependencies:
remove-trailing-separator "^1.0.1"
+normalize-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-range@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+ integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
+
+normalize-selector@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03"
+ integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=
+
normalize-url@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6"
@@ -7139,6 +7333,11 @@ null-check@^1.0.0:
resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd"
integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=
+num2fraction@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
+ integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
+
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
@@ -7154,7 +7353,7 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -7213,14 +7412,6 @@ object.getownpropertydescriptors@^2.0.3:
define-properties "^1.1.2"
es-abstract "^1.5.1"
-object.omit@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
- integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=
- dependencies:
- for-own "^0.1.4"
- is-extendable "^0.1.1"
-
object.pick@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
@@ -7228,10 +7419,10 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
-obuf@^1.0.0, obuf@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e"
- integrity sha1-EEEktsYCxnlogaBCVB0220OlJk4=
+obuf@^1.0.0, obuf@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
+ integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
on-finished@~2.3.0:
version "2.3.0"
@@ -7291,10 +7482,10 @@ opn@^5.1.0:
dependencies:
is-wsl "^1.1.0"
-optimism@^0.6.6:
- version "0.6.8"
- resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.6.8.tgz#0780b546da8cd0a72e5207e0c3706c990c8673a6"
- integrity sha512-bN5n1KCxSqwBDnmgDnzMtQTHdL+uea2HYFx1smvtE+w2AMl0Uy31g0aXnP/Nt85OINnMJPRpJyfRQLTCqn5Weg==
+optimism@^0.6.9:
+ version "0.6.9"
+ resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.6.9.tgz#19258ff8b3be0cea29ac35f06bff818e026e30bb"
+ integrity sha512-xoQm2lvXbCA9Kd7SCx6y713Y7sZ6fUc5R6VYpoL5M6svKJbTuvtNopexK8sO8K4s0EOUYHuPN2+yAEsNyRggkQ==
dependencies:
immutable-tuple "^0.4.9"
@@ -7318,6 +7509,11 @@ optionator@^0.8.1, optionator@^0.8.2:
type-check "~0.3.2"
wordwrap "~1.0.0"
+orderedmap@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-1.0.0.tgz#d90fc2ba1ed085190907d601dec6e6a53f8d41ba"
+ integrity sha1-2Q/Cuh7QhRkJB9YB3sbmpT+NQbo=
+
original@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
@@ -7353,7 +7549,7 @@ os-locale@^3.0.0:
lcid "^2.0.0"
mem "^4.0.0"
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
@@ -7376,6 +7572,13 @@ p-defer@^1.0.0:
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
+p-each-series@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71"
+ integrity sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=
+ dependencies:
+ p-reduce "^1.0.0"
+
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
@@ -7419,6 +7622,11 @@ p-map@^1.1.1:
resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a"
integrity sha1-BfXkrpegaDcbwqXMhr+9vBnErno=
+p-reduce@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
+ integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=
+
p-timeout@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038"
@@ -7471,15 +7679,17 @@ parse-asn1@^5.0.0:
evp_bytestokey "^1.0.0"
pbkdf2 "^3.0.3"
-parse-glob@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
- integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw=
+parse-entities@^1.0.2, parse-entities@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.0.tgz#9deac087661b2e36814153cb78d7e54a4c5fd6f4"
+ integrity sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g==
dependencies:
- glob-base "^0.3.0"
- is-dotfile "^1.0.0"
- is-extglob "^1.0.0"
- is-glob "^2.0.0"
+ character-entities "^1.0.0"
+ character-entities-legacy "^1.0.0"
+ character-reference-invalid "^1.0.0"
+ is-alphanumerical "^1.0.0"
+ is-decimal "^1.0.0"
+ is-hexadecimal "^1.0.0"
parse-json@^2.2.0:
version "2.2.0"
@@ -7496,6 +7706,11 @@ parse-json@^4.0.0:
error-ex "^1.3.1"
json-parse-better-errors "^1.0.1"
+parse-passwd@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
+ integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
+
parse5@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
@@ -7552,7 +7767,7 @@ path-exists@^3.0.0:
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
-path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
@@ -7567,7 +7782,7 @@ path-key@^2.0.0, path-key@^2.0.1:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
-path-parse@^1.0.5:
+path-parse@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
@@ -7577,15 +7792,6 @@ path-to-regexp@0.1.7:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
-path-type@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
- integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
- dependencies:
- graceful-fs "^4.1.2"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
-
path-type@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
@@ -7600,13 +7806,6 @@ path-type@^3.0.0:
dependencies:
pify "^3.0.0"
-pause-stream@0.0.11:
- version "0.0.11"
- resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
- integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=
- dependencies:
- through "~2.3"
-
pbkdf2@^3.0.3:
version "3.0.14"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade"
@@ -7633,6 +7832,11 @@ pify@^3.0.0:
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
+pify@^4.0.0, pify@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+ integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
pikaday@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/pikaday/-/pikaday-1.6.1.tgz#b91bcb9b8539cedd8d6d08e4e7465e12095671b0"
@@ -7652,6 +7856,20 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
+pirates@^4.0.0:
+ 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"
+
+pixelmatch@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854"
+ integrity sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=
+ dependencies:
+ pngjs "^3.0.0"
+
pkg-dir@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
@@ -7659,13 +7877,6 @@ pkg-dir@^1.0.0:
dependencies:
find-up "^1.0.0"
-pkg-dir@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
- integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
- dependencies:
- find-up "^2.1.0"
-
pkg-dir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
@@ -7683,6 +7894,11 @@ pn@^1.1.0:
resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
+pngjs@^3.0.0:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.3.tgz#85173703bde3edac8998757b96e5821d0966a21b"
+ integrity sha512-1n3Z4p3IOxArEs1VRXnZ/RXdfEniAUS9jb68g58FIXMNkPJeZd+Qh4Uq7/e0LVxAQGos1eIUrqrt4FpjdnEd+Q==
+
pofile@^1:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954"
@@ -7707,10 +7923,44 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
+postcss-html@^0.36.0:
+ version "0.36.0"
+ resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204"
+ integrity sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw==
+ dependencies:
+ htmlparser2 "^3.10.0"
+
+postcss-jsx@^0.36.0:
+ version "0.36.0"
+ resolved "https://registry.yarnpkg.com/postcss-jsx/-/postcss-jsx-0.36.0.tgz#b7685ed3d070a175ef0aa48f83d9015bd772c82d"
+ integrity sha512-/lWOSXSX5jlITCKFkuYU2WLFdrncZmjSVyNpHAunEgirZXLwI8RjU556e3Uz4mv0WVHnJA9d3JWb36lK9Yx99g==
+ dependencies:
+ "@babel/core" ">=7.1.0"
+
+postcss-less@^3.1.0:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.2.tgz#fb67e7ba351dbdf69de3c52eebd1184c52bfaea6"
+ integrity sha512-66ZBVo1JGkQ7r13M97xcHcyarWpgg21RaqIZWZXHE3XOtb5+ywK1uZWeY1DYkYRkIX/l8Hvxnx9iSKB68nFr+w==
+ dependencies:
+ postcss "^7.0.14"
+
+postcss-markdown@^0.36.0:
+ version "0.36.0"
+ resolved "https://registry.yarnpkg.com/postcss-markdown/-/postcss-markdown-0.36.0.tgz#7f22849ae0e3db18820b7b0d5e7833f13a447560"
+ integrity sha512-rl7fs1r/LNSB2bWRhyZ+lM/0bwKv9fhl38/06gF6mKMo/NPnp55+K1dSTosSVjFZc0e1ppBlu+WT91ba0PMBfQ==
+ dependencies:
+ remark "^10.0.1"
+ unist-util-find-all-after "^1.0.2"
+
+postcss-media-query-parser@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244"
+ integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=
+
postcss-modules-extract-imports@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85"
- integrity sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz#dc87e34148ec7eab5f791f7cd5849833375b741a"
+ integrity sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==
dependencies:
postcss "^6.0.1"
@@ -7738,7 +7988,44 @@ postcss-modules-values@^1.3.0:
icss-replace-symbols "^1.1.0"
postcss "^6.0.1"
-postcss-selector-parser@^3.1.1:
+postcss-reporter@^6.0.0:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.1.tgz#7c055120060a97c8837b4e48215661aafb74245f"
+ integrity sha512-LpmQjfRWyabc+fRygxZjpRxfhRf9u/fdlKf4VHG4TSPbV2XNsuISzYW1KL+1aQzx53CAppa1bKG4APIB/DOXXw==
+ dependencies:
+ chalk "^2.4.1"
+ lodash "^4.17.11"
+ log-symbols "^2.2.0"
+ postcss "^7.0.7"
+
+postcss-resolve-nested-selector@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e"
+ integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=
+
+postcss-safe-parser@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz#8756d9e4c36fdce2c72b091bbc8ca176ab1fcdea"
+ integrity sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ==
+ dependencies:
+ postcss "^7.0.0"
+
+postcss-sass@^0.3.5:
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.3.5.tgz#6d3e39f101a53d2efa091f953493116d32beb68c"
+ integrity sha512-B5z2Kob4xBxFjcufFnhQ2HqJQ2y/Zs/ic5EZbCywCkxKd756Q40cIQ/veRDwSrw1BF6+4wUgmpm0sBASqVi65A==
+ dependencies:
+ gonzales-pe "^4.2.3"
+ postcss "^7.0.1"
+
+postcss-scss@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-2.0.0.tgz#248b0a28af77ea7b32b1011aba0f738bda27dea1"
+ integrity sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug==
+ dependencies:
+ postcss "^7.0.0"
+
+postcss-selector-parser@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865"
integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=
@@ -7747,12 +8034,26 @@ postcss-selector-parser@^3.1.1:
indexes-of "^1.0.1"
uniq "^1.0.1"
-postcss-value-parser@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15"
- integrity sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=
+postcss-selector-parser@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c"
+ integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==
+ dependencies:
+ cssesc "^2.0.0"
+ indexes-of "^1.0.1"
+ uniq "^1.0.1"
+
+postcss-syntax@^0.36.2:
+ version "0.36.2"
+ resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c"
+ integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==
-postcss@^6.0.1, postcss@^6.0.14, postcss@^6.0.20, postcss@^6.0.23:
+postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
+ integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
+
+postcss@^6.0.1, postcss@^6.0.14, postcss@^6.0.23:
version "6.0.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
@@ -7761,6 +8062,15 @@ postcss@^6.0.1, postcss@^6.0.14, postcss@^6.0.20, postcss@^6.0.23:
source-map "^0.6.1"
supports-color "^5.4.0"
+postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.7:
+ version "7.0.14"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5"
+ integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==
+ dependencies:
+ chalk "^2.4.2"
+ source-map "^0.6.1"
+ supports-color "^6.1.0"
+
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -7776,27 +8086,22 @@ prepend-http@^2.0.0:
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
-preserve@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
- integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
-
-prettier@1.13.7:
- version "1.13.7"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281"
- integrity sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==
+prettier@1.16.1:
+ version "1.16.1"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.1.tgz#534c2c9d7853f8845e5e078384e71973bd74089f"
+ integrity sha512-XXUITwIkGb3CPJ2hforHah/zTINRyie5006Jd2HKy2qz7snEJXl0KLfsJZW/wst9g6R2rFvqba3VpNYdu1hDcA==
-prettier@1.15.2:
- version "1.15.2"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.2.tgz#d31abe22afa4351efa14c7f8b94b58bb7452205e"
- integrity sha512-YgPLFFA0CdKL4Eg2IHtUSjzj/BWgszDHiNQAe0VAIBse34148whfdzLagRL+QiKS+YfK5ftB6X4v/MBw8yCoug==
+prettier@1.16.3:
+ version "1.16.3"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.3.tgz#8c62168453badef702f34b45b6ee899574a6a65d"
+ integrity sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==
-pretty-format@^23.6.0:
- version "23.6.0"
- resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
- integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==
+pretty-format@^24.0.0:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0.tgz#cb6599fd73ac088e37ed682f61291e4678f48591"
+ integrity sha512-LszZaKG665djUcqg5ZQq+XzezHLKrxsA86ZABTozp+oNhkdqa+tG2dX4qa6ERl5c/sRDrAa3lHmwnvKoP+OG/g==
dependencies:
- ansi-regex "^3.0.0"
+ ansi-regex "^4.0.0"
ansi-styles "^3.2.0"
prismjs@^1.6.0:
@@ -7806,7 +8111,7 @@ prismjs@^1.6.0:
optionalDependencies:
clipboard "^1.5.5"
-private@^0.1.6, private@^0.1.8:
+private@^0.1.6:
version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
@@ -7836,13 +8141,129 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
-prompts@^0.1.9:
- version "0.1.14"
- resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2"
- integrity sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==
+prompts@^2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.0.3.tgz#c5ccb324010b2e8f74752aadceeb57134c1d2522"
+ integrity sha512-H8oWEoRZpybm6NV4to9/1limhttEo13xK62pNvn2JzY0MA03p7s0OjtmhXyon3uJmxiJJVSuUwEJFFssI3eBiQ==
+ dependencies:
+ kleur "^3.0.2"
+ sisteransi "^1.0.0"
+
+prosemirror-commands@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.0.7.tgz#e5a2ba821e29ea7065c88277fe2c3d7f6b0b9d37"
+ integrity sha512-IR8yMSdw7XlKuF68tydAak1J9P/lLD5ohsrL7pzoLsJAJAQU7mVPDXtGbQrrm0mesddFjcc1zNo/cJQN3lRYnA==
+ dependencies:
+ prosemirror-model "^1.0.0"
+ prosemirror-state "^1.0.0"
+ prosemirror-transform "^1.0.0"
+
+prosemirror-dropcursor@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.1.1.tgz#c60ed1ed6c58804a06a75db06a0d993b087b7622"
+ integrity sha512-GeUyMO/tOEf8MXrP7Xb7UIMrfK86OGh0fnyBrHfhav4VjY9cw65mNoqHy87CklE5711AhCP5Qzfp8RL/hVKusg==
+ dependencies:
+ prosemirror-state "^1.0.0"
+ prosemirror-transform "^1.1.0"
+ prosemirror-view "^1.1.0"
+
+prosemirror-gapcursor@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.0.3.tgz#acc6537fc5a35e9b38966f91a199a382dfc715c4"
+ integrity sha512-X+hJhr42PcHWiSWL+lI5f/UeOhXCxlBFb8M6O8aG1hssmaRrW7sS2/Fjg5jFV+pTdS1REFkmm1occh01FMdDIQ==
+ dependencies:
+ prosemirror-keymap "^1.0.0"
+ prosemirror-model "^1.0.0"
+ prosemirror-state "^1.0.0"
+ prosemirror-view "^1.0.0"
+
+prosemirror-history@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.0.3.tgz#5fb8591adfc272afaaf0b41bec64ee7d9522a118"
+ integrity sha512-IfFGbhafSx+R3aq7nLJGkXeu2iaUiP8mkU3aRu2uQcIIjU8Fq7RJfuvhIOJ2RNUoSyqF/ANkdTjnZ74F5eHs1Q==
+ dependencies:
+ prosemirror-state "^1.2.2"
+ prosemirror-transform "^1.0.0"
+ rope-sequence "^1.2.0"
+
+prosemirror-inputrules@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/prosemirror-inputrules/-/prosemirror-inputrules-1.0.1.tgz#f63305fd966379f218e82ca76a2a9b328b66dc7b"
+ integrity sha512-UHy22NmwxS5WIMQYkzraDttQAF8mpP82FfbJsmKFfx6jwkR/SZa+ZhbkLY0zKQ5fBdJN7euj36JG/B5iAlrpxA==
+ dependencies:
+ prosemirror-state "^1.0.0"
+ prosemirror-transform "^1.0.0"
+
+prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.0.1.tgz#03ef32b828e3a859dfb570eb84928bf2e5330bc2"
+ integrity sha512-e79ApE7PXXZMFtPz7WbjycjAFd1NPjgY1MkecVz98tqwlBSggXWXYQnWFk6x7UkmnBYRHHbXHkR/RXmu2wyBJg==
+ dependencies:
+ prosemirror-state "^1.0.0"
+ w3c-keyname "^1.1.8"
+
+prosemirror-markdown@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.3.0.tgz#a100d14c27da7d8fb70818230d786898eeadb7fa"
+ integrity sha512-76l3yLB/suy6sA7LpzRJvRRWkHtKwOTpgWVNwmlIAIIZJeMypWSPldT/gFyIG604eyXEPZitnx+j80Y2DpbnUQ==
dependencies:
- kleur "^2.0.1"
- sisteransi "^0.1.1"
+ markdown-it "^8.4.2"
+ prosemirror-model "^1.0.0"
+
+prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.6.4:
+ version "1.6.4"
+ resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.6.4.tgz#2ac37a629448a7dbfd1635450e2fdd63c3450d7d"
+ integrity sha512-C2ALle8fZsAza+6stUF9Gv28jH9XtpNeczb33bowGlnb2cpNI4FZf1HHUyZjf6ou4cEvOlbt6fAYsT4NCKmlcQ==
+ dependencies:
+ orderedmap "^1.0.0"
+
+prosemirror-schema-list@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.0.1.tgz#f216e0cf4809b6074aa27912449ac89897f1ae94"
+ integrity sha512-AiLIX6qm6PEeDtMCKZLcSLi55WXo1ls7DnRK+4hSkoi0IIzNdxGsRlecCd3MzEu//DVz3nAEh+zEmslyW+uk8g==
+ dependencies:
+ prosemirror-model "^1.0.0"
+ prosemirror-transform "^1.0.0"
+
+prosemirror-state@^1.0.0, prosemirror-state@^1.2.1, prosemirror-state@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.2.2.tgz#8df26d95fd6fd327c0f9984a760e84d863204154"
+ integrity sha512-j8aC/kf9BJSCQau485I/9pj39XQoce+TqH5xzekT7WWFARTsRYFLJtiXBcCKakv1VSeev+sC3bJP0pLfz7Ft8g==
+ dependencies:
+ prosemirror-model "^1.0.0"
+ prosemirror-transform "^1.0.0"
+
+prosemirror-tables@^0.7.10, prosemirror-tables@^0.7.9:
+ version "0.7.10"
+ resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-0.7.10.tgz#4b0f623422b4b8f84cdc9c559f8a87579846b3ba"
+ integrity sha512-VIu7UGS9keYEHs0Y6AEOTGbNE9QI2rL1OKng4vV6yoTshW/lYcb+s3hGXI12i+WLMjDVm7ujhfdWrpKpvFZOkQ==
+ dependencies:
+ prosemirror-keymap "^1.0.0"
+ prosemirror-model "^1.0.0"
+ prosemirror-state "^1.0.0"
+ prosemirror-transform "^1.0.0"
+ prosemirror-view "^1.0.0"
+
+prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.1.3.tgz#28cfdf1f9ee514edc40466be7b7db39eed545fdf"
+ integrity sha512-1O6Di5lOL1mp4nuCnQNkHY7l2roIW5y8RH4ZG3hMYmkmDEWzTaFFnxxAAHsE5ipGLBSRcTlP7SsDhYBIdSuLpQ==
+ dependencies:
+ prosemirror-model "^1.0.0"
+
+prosemirror-utils@^0.7.5:
+ version "0.7.5"
+ resolved "https://registry.yarnpkg.com/prosemirror-utils/-/prosemirror-utils-0.7.5.tgz#11b477647b672ec8f10679ab298a5823dad6457a"
+ integrity sha512-F+63BUiBkUQb1S07c3rGHXjE4MDaZ5OjsNhmaO7eDdSh1lUNORTJJHrvlFEZKnLM7ChoDDXTIKhWNQwnCssQfA==
+
+prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.6.8:
+ version "1.6.8"
+ resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.6.8.tgz#33fc1a6e2731633e5d6dc1af1967378f15810b74"
+ integrity sha512-YWX3rfji77xsU5EErt4ZoecVytYW9/4oHBYhV1MUHGMYIcppe+QZEBgRlyPMBUuu0lxdZX4m3sq7fCsDvv/MlQ==
+ dependencies:
+ prosemirror-model "^1.1.0"
+ prosemirror-state "^1.0.0"
+ prosemirror-transform "^1.1.0"
proto-list@~1.2.1:
version "1.2.4"
@@ -7862,13 +8283,6 @@ prr@~1.0.1:
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
-ps-tree@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
- integrity sha1-tCGyQUDWID8e08dplrRCewjowBQ=
- dependencies:
- event-stream "~3.3.0"
-
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@@ -7879,12 +8293,10 @@ psl@^1.1.24:
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67"
integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==
-pstree.remy@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.0.tgz#f2af27265bd3e5b32bbfcc10e80bac55ba78688b"
- integrity sha512-q5I5vLRMVtdWa8n/3UEzZX7Lfghzrg9eG2IKk2ENLSofKRCXVqMvMUHxCKgXNaqH/8ebhBxrqftHWnyTFweJ5Q==
- dependencies:
- ps-tree "^1.1.0"
+pstree.remy@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.6.tgz#73a55aad9e2d95814927131fbf4dc1b62d259f47"
+ integrity sha512-NdF35+QsqD7EgNEI5mkI/X+UwaxVEbQaz9f4IooEmMUv6ZPmlTQYGjBPJGgrlzNdjSvIy4MWMg6Q6vCgBO2K+w==
public-encrypt@^4.0.0:
version "4.0.0"
@@ -7897,7 +8309,7 @@ public-encrypt@^4.0.0:
parse-asn1 "^5.0.0"
randombytes "^2.0.1"
-pump@^2.0.0, pump@^2.0.1:
+pump@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
@@ -7976,14 +8388,10 @@ querystringify@^2.0.0:
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef"
integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==
-randomatic@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
- integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==
- dependencies:
- is-number "^4.0.0"
- kind-of "^6.0.0"
- math-random "^1.0.1"
+quick-lru@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
+ integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.0.6"
@@ -8027,10 +8435,13 @@ raw-body@2.3.2:
iconv-lite "0.4.19"
unpipe "1.0.0"
-raw-loader@^0.5.1:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa"
- integrity sha1-DD0L6u2KAclm2Xh793goElKpeao=
+raw-loader@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-1.0.0.tgz#3f9889e73dadbda9a424bce79809b4133ad46405"
+ integrity sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA==
+ dependencies:
+ loader-utils "^1.1.0"
+ schema-utils "^1.0.0"
rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
version "1.2.8"
@@ -8042,14 +8453,6 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-read-pkg-up@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
- integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
- dependencies:
- find-up "^1.0.0"
- read-pkg "^1.0.0"
-
read-pkg-up@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
@@ -8058,6 +8461,14 @@ read-pkg-up@^2.0.0:
find-up "^2.0.0"
read-pkg "^2.0.0"
+read-pkg-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
+ integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=
+ dependencies:
+ find-up "^2.0.0"
+ read-pkg "^3.0.0"
+
read-pkg-up@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978"
@@ -8066,15 +8477,6 @@ read-pkg-up@^4.0.0:
find-up "^3.0.0"
read-pkg "^3.0.0"
-read-pkg@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
- integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
- dependencies:
- load-json-file "^1.0.0"
- normalize-package-data "^2.3.2"
- path-type "^1.0.0"
-
read-pkg@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
@@ -8093,7 +8495,7 @@ read-pkg@^3.0.0:
normalize-package-data "^2.3.2"
path-type "^3.0.0"
-"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.6:
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
@@ -8137,13 +8539,21 @@ readdirp@^2.0.0:
readable-stream "^2.0.2"
set-immediate-shim "^1.0.1"
-realpath-native@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.2.tgz#cd51ce089b513b45cf9b1516c82989b51ccc6560"
- integrity sha512-+S3zTvVt9yTntFrBpm7TQmQ3tzpCrnA1a/y+3cUHAc9ZR6aIjG0WNLR+Rj79QpJktY+VeW/TQtFlQ1bzsehI8g==
+realpath-native@^1.0.0, realpath-native@^1.0.2:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
+ integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==
dependencies:
util.promisify "^1.0.0"
+redent@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
+ integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=
+ dependencies:
+ indent-string "^3.0.0"
+ strip-indent "^2.0.0"
+
regenerate-unicode-properties@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c"
@@ -8173,13 +8583,6 @@ regenerator-transform@^0.13.3:
dependencies:
private "^0.1.6"
-regex-cache@^0.4.2:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
- integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==
- dependencies:
- is-equal-shallow "^0.1.3"
-
regex-not@^1.0.0, regex-not@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
@@ -8188,6 +8591,15 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
+regexp-tree@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.0.tgz#a56ad7746097888ea16457479029ec9345b96ab0"
+ integrity sha512-rHQv+tzu+0l3KS/ERabas1yK49ahNVxuH40WcPg53CzP5p8TgmmyBgHELLyJcvjhTD0e5ahSY6C76LbEVtr7cg==
+ dependencies:
+ cli-table3 "^0.5.0"
+ colors "^1.1.2"
+ yargs "^10.0.3"
+
regexpp@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
@@ -8253,6 +8665,56 @@ regjsparser@^0.3.0:
dependencies:
jsesc "~0.5.0"
+remark-parse@^6.0.0:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-6.0.3.tgz#c99131052809da482108413f87b0ee7f52180a3a"
+ integrity sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==
+ dependencies:
+ collapse-white-space "^1.0.2"
+ is-alphabetical "^1.0.0"
+ is-decimal "^1.0.0"
+ is-whitespace-character "^1.0.0"
+ is-word-character "^1.0.0"
+ markdown-escapes "^1.0.0"
+ parse-entities "^1.1.0"
+ repeat-string "^1.5.4"
+ state-toggle "^1.0.0"
+ trim "0.0.1"
+ trim-trailing-lines "^1.0.0"
+ unherit "^1.0.4"
+ unist-util-remove-position "^1.0.0"
+ vfile-location "^2.0.0"
+ xtend "^4.0.1"
+
+remark-stringify@^6.0.0:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-6.0.4.tgz#16ac229d4d1593249018663c7bddf28aafc4e088"
+ integrity sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==
+ dependencies:
+ ccount "^1.0.0"
+ is-alphanumeric "^1.0.0"
+ is-decimal "^1.0.0"
+ is-whitespace-character "^1.0.0"
+ longest-streak "^2.0.1"
+ markdown-escapes "^1.0.0"
+ markdown-table "^1.1.0"
+ mdast-util-compact "^1.0.0"
+ parse-entities "^1.0.2"
+ repeat-string "^1.5.4"
+ state-toggle "^1.0.0"
+ stringify-entities "^1.0.1"
+ unherit "^1.0.4"
+ xtend "^4.0.1"
+
+remark@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/remark/-/remark-10.0.1.tgz#3058076dc41781bf505d8978c291485fe47667df"
+ integrity sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==
+ dependencies:
+ remark-parse "^6.0.0"
+ remark-stringify "^6.0.0"
+ unified "^7.0.0"
+
remove-trailing-separator@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
@@ -8268,17 +8730,15 @@ repeat-string@^0.2.2:
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae"
integrity sha1-x6jTI2BoNiBZp+RlH8aITosftK4=
-repeat-string@^1.5.2, repeat-string@^1.6.1:
+repeat-string@^1.5.4, repeat-string@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
-repeating@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
- integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
- dependencies:
- is-finite "^1.0.0"
+replace-ext@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
+ integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
request-promise-core@1.1.1:
version "1.1.1"
@@ -8345,6 +8805,13 @@ requires-port@1.x.x, 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@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
@@ -8352,6 +8819,14 @@ resolve-cwd@^2.0.0:
dependencies:
resolve-from "^3.0.0"
+resolve-dir@^1.0.0, resolve-dir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
+ integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
+ dependencies:
+ expand-tilde "^2.0.0"
+ global-modules "^1.0.0"
+
resolve-from@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
@@ -8362,6 +8837,11 @@ resolve-from@^3.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
integrity sha1-six699nWiBvItuZTM17rywoYh0g=
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
resolve-url@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
@@ -8372,12 +8852,12 @@ resolve@1.1.7, resolve@1.1.x:
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
-resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0:
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
- integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==
+resolve@1.x, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba"
+ integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==
dependencies:
- path-parse "^1.0.5"
+ path-parse "^1.0.6"
responselike@1.0.2:
version "1.0.2"
@@ -8404,12 +8884,12 @@ rfdc@^1.1.2:
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.2.tgz#e6e72d74f5dc39de8f538f65e00c36c18018e349"
integrity sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==
-rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
- integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
+rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
+ integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
dependencies:
- glob "^7.0.5"
+ glob "^7.1.3"
ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.1"
@@ -8419,6 +8899,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^2.0.0"
inherits "^2.0.1"
+rope-sequence@^1.2.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.2.2.tgz#49c4e5c2f54a48e990b050926771e2871bcb31ce"
+ integrity sha1-ScTlwvVKSOmQsFCSZ3HihxvLMc4=
+
rsvp@^3.3.3:
version "3.6.2"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
@@ -8477,14 +8962,15 @@ safe-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-sane@^2.0.0:
- version "2.5.2"
- resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
- integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o=
+sane@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/sane/-/sane-3.1.0.tgz#995193b7dc1445ef1fe41ddfca2faf9f111854c6"
+ integrity sha512-G5GClRRxT1cELXfdAq7UKtUsv8q/ZC5k8lQGmjEm4HcAl3HzBy68iglyNCmw4+0tiXPCBZntslHlRhbnsSws+Q==
dependencies:
anymatch "^2.0.0"
capture-exit "^1.2.0"
exec-sh "^0.2.0"
+ execa "^1.0.0"
fb-watchman "^2.0.0"
micromatch "^3.1.4"
minimist "^1.1.1"
@@ -8511,7 +8997,7 @@ sax@^1.2.4:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
-schema-utils@^0.4.0, schema-utils@^0.4.2, schema-utils@^0.4.4, schema-utils@^0.4.5:
+schema-utils@^0.4.0, schema-utils@^0.4.4:
version "0.4.5"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.5.tgz#21836f0608aac17b78f9e3e24daff14a5ca13a3e"
integrity sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==
@@ -8566,7 +9052,7 @@ semver-diff@^2.0.0:
dependencies:
semver "^5.0.3"
-"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
+"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
@@ -8713,20 +9199,20 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
-sisteransi@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce"
- integrity sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==
-
-slash@^1.0.0:
+sisteransi@^1.0.0:
version "1.0.0"
- resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
- integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.0.tgz#77d9622ff909080f1c19e5f4a1df0c1b0a27b88c"
+ integrity sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ==
-slice-ansi@2.0.0:
+slash@^2.0.0:
version "2.0.0"
- resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.0.0.tgz#5373bdb8559b45676e8541c66916cdd6251612e7"
- integrity sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ==
+ resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
+ integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
+
+slice-ansi@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
+ integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==
dependencies:
ansi-styles "^3.2.0"
astral-regex "^1.0.0"
@@ -8737,10 +9223,10 @@ slugify@^1.3.1:
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.3.1.tgz#f572127e8535329fbc6c1edb74ab856b61ad7de2"
integrity sha512-6BwyhjF5tG5P8s+0DPNyJmBSBePG6iMyhjvIW5zGdA3tFik9PtK+yNkZgTeiroCRGZYgkHftFA62tGVK1EI9Kw==
-smooshpack@^0.0.53:
- version "0.0.53"
- resolved "https://registry.yarnpkg.com/smooshpack/-/smooshpack-0.0.53.tgz#aa397ca43619912e8ac0aa32012846ff4feaa5e8"
- integrity sha512-FVXvKvZOz5+Tk/zUJ/wxM+ftu1yZtFEmeQl4chCqbzK/reU0L/OdDiYpx+/27Jt2VX09j08oIzwoyQ5fHH4+WQ==
+smooshpack@^0.0.54:
+ version "0.0.54"
+ resolved "https://registry.yarnpkg.com/smooshpack/-/smooshpack-0.0.54.tgz#9044358b85052d348b801f385678c8a0c76f2bb6"
+ integrity sha512-yIwEWb17hqoW5IaWyzO6O6nxY89I5UdRoGIZy5hihoqXP9OYcoMbBTxKwS57MeXSKdNA2rtk86rlCcOgAYIgrA==
dependencies:
codesandbox-api "^0.0.20"
codesandbox-import-utils "^1.2.3"
@@ -8870,14 +9356,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
source-map-url "^0.4.0"
urix "^0.1.0"
-source-map-support@^0.4.15:
- version "0.4.18"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
- integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
- dependencies:
- source-map "^0.5.6"
-
-source-map-support@^0.5.6:
+source-map-support@^0.5.6, source-map-support@~0.5.6:
version "0.5.9"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f"
integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==
@@ -8895,7 +9374,7 @@ source-map@0.5.0:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.0.tgz#0fe96503ac86a5adb5de63f4e412ae4872cdbe86"
integrity sha1-D+llA6yGpa213mP05BKuSHLNvoY=
-source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
+source-map@^0.5.0, source-map@^0.5.6:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -8929,30 +9408,33 @@ spdx-license-ids@^1.0.2:
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
integrity sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=
-spdy-transport@^2.0.18:
- version "2.0.20"
- resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d"
- integrity sha1-c15yBUxIayNU/onnAiVgBKOazk0=
+spdy-transport@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31"
+ integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==
dependencies:
- debug "^2.6.8"
- detect-node "^2.0.3"
+ debug "^4.1.0"
+ detect-node "^2.0.4"
hpack.js "^2.1.6"
- obuf "^1.1.1"
- readable-stream "^2.2.9"
- safe-buffer "^5.0.1"
- wbuf "^1.7.2"
+ obuf "^1.1.2"
+ readable-stream "^3.0.6"
+ wbuf "^1.7.3"
-spdy@^3.4.1:
- version "3.4.7"
- resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc"
- integrity sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=
+spdy@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.0.tgz#81f222b5a743a329aa12cea6a390e60e9b613c52"
+ integrity sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==
dependencies:
- debug "^2.6.8"
- handle-thing "^1.2.5"
+ debug "^4.1.0"
+ handle-thing "^2.0.0"
http-deceiver "^1.2.7"
- safe-buffer "^5.0.1"
select-hose "^2.0.0"
- spdy-transport "^2.0.18"
+ spdy-transport "^3.0.0"
+
+specificity@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019"
+ integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==
split-string@^3.0.1, split-string@^3.0.2:
version "3.1.0"
@@ -8961,13 +9443,6 @@ split-string@^3.0.1, split-string@^3.0.2:
dependencies:
extend-shallow "^3.0.0"
-split@0.3:
- version "0.3.3"
- resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
- integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=
- dependencies:
- through "2"
-
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
@@ -9001,14 +9476,7 @@ sshpk@^1.7.0:
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
-ssri@^5.2.4:
- version "5.2.4"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.2.4.tgz#9985e14041e65fc397af96542be35724ac11da52"
- integrity sha512-UnEAgMZa15973iH7cUi0AHjJn1ACDIkaMyZILoqwN6yzt+4P81I8tBc5Hl+qwi5auMplZtPQsHrPBR5vJLcQtQ==
- dependencies:
- safe-buffer "^5.1.1"
-
-ssri@^6.0.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==
@@ -9020,6 +9488,11 @@ stack-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
+state-toggle@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.1.tgz#c3cb0974f40a6a0f8e905b96789eb41afa1cde3a"
+ integrity sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==
+
static-extend@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
@@ -9056,13 +9529,6 @@ stream-browserify@^2.0.1:
inherits "~2.0.1"
readable-stream "^2.0.2"
-stream-combiner@~0.0.4:
- version "0.0.4"
- resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
- integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=
- dependencies:
- duplexer "~0.1.1"
-
stream-each@^1.1.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd"
@@ -9127,6 +9593,15 @@ string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
+string-width@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1"
+ integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==
+ dependencies:
+ emoji-regex "^7.0.1"
+ is-fullwidth-code-point "^2.0.0"
+ strip-ansi "^5.0.0"
+
string_decoder@^1.0.0, string_decoder@^1.1.1, string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@@ -9139,6 +9614,16 @@ string_decoder@~0.10.x:
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
+stringify-entities@^1.0.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.2.tgz#a98417e5471fd227b3e45d3db1861c11caf668f7"
+ integrity sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==
+ dependencies:
+ character-entities-html4 "^1.0.0"
+ character-entities-legacy "^1.0.0"
+ is-alphanumerical "^1.0.0"
+ is-hexadecimal "^1.0.0"
+
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
@@ -9153,18 +9638,18 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
-strip-bom@3.0.0, strip-bom@^3.0.0:
+strip-ansi@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f"
+ integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==
+ dependencies:
+ ansi-regex "^4.0.0"
+
+strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
-strip-bom@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
- integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
- dependencies:
- is-utf8 "^0.2.0"
-
strip-css-comments@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-css-comments/-/strip-css-comments-3.0.0.tgz#7a5625eff8a2b226cf8947a11254da96e13dae89"
@@ -9177,38 +9662,141 @@ strip-eof@^1.0.0:
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
-strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
+strip-indent@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
+ integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
+
+strip-json-comments@^2.0.1, 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@^0.23.0:
- version "0.23.0"
- resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.0.tgz#8377fefab68416a2e05f1cabd8c3a3acfcce74f1"
- integrity sha512-uCcN7XWHkqwGVt7skpInW6IGO1tG6ReyFQ1Cseh0VcN6VdcFQi62aG/2F3Y9ueA8x4IVlfaSUxpmQXQD9QrEuQ==
+style-loader@^0.23.1:
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925"
+ integrity sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==
dependencies:
loader-utils "^1.1.0"
- schema-utils "^0.4.5"
+ schema-utils "^1.0.0"
+
+style-search@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
+ integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=
+
+stylelint-config-recommended@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-2.1.0.tgz#f526d5c771c6811186d9eaedbed02195fee30858"
+ integrity sha512-ajMbivOD7JxdsnlS5945KYhvt7L/HwN6YeYF2BH6kE4UCLJR0YvXMf+2j7nQpJyYLZx9uZzU5G1ZOSBiWAc6yA==
+
+stylelint-error-string-formatter@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/stylelint-error-string-formatter/-/stylelint-error-string-formatter-1.0.1.tgz#366387825d6fb59569e8c5c3f5682398733756f9"
+ integrity sha512-8zy0UsdnQZKVDwjWMQX36b30TaNMGcM2FzBcK9cshpXerpJ3AvF2/zw7FJ3Efm6DFviTBVsxR14F3FnDFhCxJw==
+
+stylelint-scss@^3.5.3:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.5.3.tgz#e158b3061eeec26d7f6088f346998a797432f3c8"
+ integrity sha512-QESQUOY1ldU5tlJTTM3Megz/QtJ39S58ByjZ7dZobGDq9qMjy5jbC7PDUasrv/T7pB1UbpPojpxX9K1OR7IPEg==
+ dependencies:
+ lodash "^4.17.11"
+ postcss-media-query-parser "^0.2.3"
+ postcss-resolve-nested-selector "^0.1.1"
+ postcss-selector-parser "^5.0.0"
+ postcss-value-parser "^3.3.1"
+
+stylelint@^9.10.1:
+ version "9.10.1"
+ resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-9.10.1.tgz#5f0ee3701461dff1d68284e1386efe8f0677a75d"
+ integrity sha512-9UiHxZhOAHEgeQ7oLGwrwoDR8vclBKlSX7r4fH0iuu0SfPwFaLkb1c7Q2j1cqg9P7IDXeAV2TvQML/fRQzGBBQ==
+ dependencies:
+ autoprefixer "^9.0.0"
+ balanced-match "^1.0.0"
+ chalk "^2.4.1"
+ cosmiconfig "^5.0.0"
+ debug "^4.0.0"
+ execall "^1.0.0"
+ file-entry-cache "^4.0.0"
+ get-stdin "^6.0.0"
+ global-modules "^2.0.0"
+ globby "^9.0.0"
+ globjoin "^0.1.4"
+ html-tags "^2.0.0"
+ ignore "^5.0.4"
+ import-lazy "^3.1.0"
+ imurmurhash "^0.1.4"
+ known-css-properties "^0.11.0"
+ leven "^2.1.0"
+ lodash "^4.17.4"
+ log-symbols "^2.0.0"
+ mathml-tag-names "^2.0.1"
+ meow "^5.0.0"
+ micromatch "^3.1.10"
+ normalize-selector "^0.2.0"
+ pify "^4.0.0"
+ postcss "^7.0.13"
+ postcss-html "^0.36.0"
+ postcss-jsx "^0.36.0"
+ postcss-less "^3.1.0"
+ postcss-markdown "^0.36.0"
+ postcss-media-query-parser "^0.2.3"
+ postcss-reporter "^6.0.0"
+ postcss-resolve-nested-selector "^0.1.1"
+ postcss-safe-parser "^4.0.0"
+ postcss-sass "^0.3.5"
+ postcss-scss "^2.0.0"
+ postcss-selector-parser "^3.1.0"
+ postcss-syntax "^0.36.2"
+ postcss-value-parser "^3.3.0"
+ resolve-from "^4.0.0"
+ signal-exit "^3.0.2"
+ slash "^2.0.0"
+ specificity "^0.4.1"
+ string-width "^3.0.0"
+ style-search "^0.1.0"
+ sugarss "^2.0.0"
+ svg-tags "^1.0.0"
+ table "^5.0.0"
+
+sugarss@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d"
+ integrity sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==
+ dependencies:
+ postcss "^7.0.2"
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-supports-color@^3.1.0, supports-color@^3.1.2:
+supports-color@^3.1.0:
version "3.2.3"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
dependencies:
has-flag "^1.0.0"
-supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.4.0:
+supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
dependencies:
has-flag "^3.0.0"
+supports-color@^6.0.0, supports-color@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
+ integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
+ dependencies:
+ has-flag "^3.0.0"
+
+svg-tags@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
+ integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
+
svg4everybody@2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/svg4everybody/-/svg4everybody-2.1.9.tgz#5bd9f6defc133859a044646d4743fabc28db7e2d"
@@ -9224,15 +9812,20 @@ symbol-tree@^3.2.2:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=
-table@^5.0.2:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/table/-/table-5.1.1.tgz#92030192f1b7b51b6eeab23ed416862e47b70837"
- integrity sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw==
+table@^5.0.0, table@^5.0.2:
+ version "5.2.3"
+ resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2"
+ integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==
dependencies:
- ajv "^6.6.1"
+ ajv "^6.9.1"
lodash "^4.17.11"
- slice-ansi "2.0.0"
- string-width "^2.1.1"
+ slice-ansi "^2.1.0"
+ string-width "^3.0.0"
+
+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"
@@ -9264,16 +9857,28 @@ term-size@^1.2.0:
dependencies:
execa "^0.7.0"
-test-exclude@^4.2.1:
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20"
- integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==
+terser-webpack-plugin@^1.1.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.1.tgz#7545da9ae5f4f9ae6a0ac961eb46f5e7c845cc26"
+ integrity sha512-GGSt+gbT0oKcMDmPx4SRSfJPE1XaN3kQRWG4ghxKQw9cn5G9x6aCKSsgYdvyM0na9NJ4Drv0RG6jbBByZ5CMjw==
dependencies:
- arrify "^1.0.1"
- micromatch "^2.3.11"
- object-assign "^4.1.0"
- read-pkg-up "^1.0.1"
- require-main-filename "^1.0.1"
+ cacache "^11.0.2"
+ find-cache-dir "^2.0.0"
+ schema-utils "^1.0.0"
+ serialize-javascript "^1.4.0"
+ source-map "^0.6.1"
+ terser "^3.8.1"
+ webpack-sources "^1.1.0"
+ worker-farm "^1.5.2"
+
+terser@^3.8.1:
+ version "3.14.1"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-3.14.1.tgz#cc4764014af570bc79c79742358bd46926018a32"
+ integrity sha512-NSo3E99QDbYSMeJaEk9YW2lTg3qS9V0aKGlb+PlOrei1X02r1wSBHCNX/O+yeTRFSWPKPIGj6MqvvdqV4rnVGw==
+ dependencies:
+ commander "~2.17.1"
+ source-map "~0.6.1"
+ source-map-support "~0.5.6"
test-exclude@^5.0.0:
version "5.0.0"
@@ -9328,7 +9933,7 @@ through2@^2.0.0:
readable-stream "^2.1.5"
xtend "~4.0.1"
-through@2, through@^2.3.6, through@~2.3, through@~2.3.1:
+through@^2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
@@ -9362,6 +9967,57 @@ tiny-emitter@^2.0.0:
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
integrity sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==
+tiptap-commands@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/tiptap-commands/-/tiptap-commands-1.4.0.tgz#0cfb3ac138ee3099de56114cb119abd841fbcbe7"
+ integrity sha512-ytO8jFXgufK5DziamTaVojzUTolWvL4m2xNXaLkAVJYy9CWXruMK7avqeLoFYPI4GZlhleMn5i4gzYTbD7e2jA==
+ dependencies:
+ prosemirror-commands "^1.0.7"
+ prosemirror-inputrules "^1.0.1"
+ prosemirror-schema-list "^1.0.1"
+ prosemirror-state "^1.2.2"
+ tiptap-utils "^1.1.1"
+
+tiptap-extensions@^1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/tiptap-extensions/-/tiptap-extensions-1.8.0.tgz#3067620a024f1a9e5fae4450790b143d7ebe4394"
+ integrity sha512-1JN9uk5QnA7DTID1j07gIBEqeOnRd6lwZ5rx/zqWXJLyreZu8VDPvP939tfP41GskO4oicGlhmsQ0aEnA5QYDw==
+ dependencies:
+ lowlight "^1.11.0"
+ prosemirror-history "^1.0.3"
+ prosemirror-state "^1.2.2"
+ prosemirror-tables "^0.7.10"
+ prosemirror-utils "^0.7.5"
+ prosemirror-view "^1.6.8"
+ tiptap "^1.8.0"
+ tiptap-commands "^1.4.0"
+
+tiptap-utils@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/tiptap-utils/-/tiptap-utils-1.1.1.tgz#e7aad3e84eb35f7abed704d15da0420029789d0d"
+ integrity sha512-yPIWwLFaL5a0GC7fcO7aoPlASnH3wOUQex0IlepNWbDCNycSL8shXhVx0HMN/tCnlp943zw1bwcYzpTW3wA4tw==
+ dependencies:
+ prosemirror-model "^1.6.4"
+ prosemirror-state "^1.2.2"
+ prosemirror-tables "^0.7.9"
+ prosemirror-utils "^0.7.5"
+
+tiptap@^1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/tiptap/-/tiptap-1.8.0.tgz#c671188075ffa5ee4f86470f95818fd9ce6f1040"
+ integrity sha512-zIcVY8U1Wgj4bg3R4pX5a2BCpZUw/dTCh259VZ9g5MtClnzdLW2XpKCcwqfa9iUBEs6MCPSnB3t8jGRtGciHJg==
+ dependencies:
+ prosemirror-commands "^1.0.7"
+ prosemirror-dropcursor "^1.1.1"
+ prosemirror-gapcursor "^1.0.3"
+ prosemirror-inputrules "^1.0.1"
+ prosemirror-keymap "^1.0.1"
+ prosemirror-model "^1.6.4"
+ prosemirror-state "^1.2.1"
+ prosemirror-view "^1.6.8"
+ tiptap-commands "^1.4.0"
+ tiptap-utils "^1.1.1"
+
tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -9384,11 +10040,6 @@ to-arraybuffer@^1.0.0:
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
-to-fast-properties@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
- integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
-
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@@ -9446,27 +10097,59 @@ tr46@^1.0.1:
dependencies:
punycode "^2.1.0"
+trim-newlines@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20"
+ integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=
+
trim-right@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
+trim-trailing-lines@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz#e0ec0810fd3c3f1730516b45f49083caaf2774d9"
+ integrity sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==
+
+trim@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd"
+ integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0=
+
+trough@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.3.tgz#e29bd1614c6458d44869fc28b255ab7857ef7c24"
+ integrity sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==
+
tryer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.0.tgz#027b69fa823225e551cace3ef03b11f6ab37c1d7"
integrity sha1-Antp+oIyJeVRys4+8DsR9qs3wdc=
-tsconfig@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7"
- integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==
- dependencies:
- "@types/strip-bom" "^3.0.0"
- "@types/strip-json-comments" "0.0.30"
- strip-bom "^3.0.0"
- strip-json-comments "^2.0.0"
-
-tslib@^1.9.0:
+ts-invariant@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.2.1.tgz#3d587f9d6e3bded97bf9ec17951dd9814d5a9d3f"
+ integrity sha512-Z/JSxzVmhTo50I+LKagEISFJW3pvPCqsMWLamCTX8Kr3N5aMrnGOqcflbe5hLUzwjvgPfnLzQtHZv0yWQ+FIHg==
+ dependencies:
+ tslib "^1.9.3"
+
+ts-jest@24.0.0, ts-jest@^23.10.5:
+ version "24.0.0"
+ resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.0.0.tgz#3f26bf2ec1fa584863a5a9c29bd8717d549efbf6"
+ integrity sha512-o8BO3TkMREpAATaFTrXkovMsCpBl2z4NDBoLJuWZcJJj1ijI49UnvDMfVpj+iogn/Jl8Pbhuei5nc/Ti+frEHw==
+ dependencies:
+ bs-logger "0.x"
+ buffer-from "1.x"
+ fast-json-stable-stringify "2.x"
+ json5 "2.x"
+ make-error "1.x"
+ mkdirp "0.x"
+ resolve "1.x"
+ semver "^5.5"
+ yargs-parser "10.x"
+
+tslib@^1.9.0, tslib@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
@@ -9513,13 +10196,10 @@ typescript@^2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==
-uglify-es@^3.3.4:
- version "3.3.9"
- resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
- integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==
- dependencies:
- commander "~2.13.0"
- source-map "~0.6.1"
+uc.micro@^1.0.1, uc.micro@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376"
+ integrity sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==
uglify-js@^3.1.4:
version "3.4.9"
@@ -9529,20 +10209,6 @@ uglify-js@^3.1.4:
commander "~2.17.1"
source-map "~0.6.1"
-uglifyjs-webpack-plugin@^1.2.4:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.5.tgz#2ef8387c8f1a903ec5e44fa36f9f3cbdcea67641"
- integrity sha512-hIQJ1yxAPhEA2yW/i7Fr+SXZVMp+VEI3d42RTHBgQd2yhp/1UdBcR3QEWPV5ahBxlqQDMEMTuTEvDHSFINfwSw==
- dependencies:
- cacache "^10.0.4"
- find-cache-dir "^1.0.0"
- schema-utils "^0.4.5"
- serialize-javascript "^1.4.0"
- source-map "^0.6.1"
- uglify-es "^3.3.4"
- webpack-sources "^1.1.0"
- worker-farm "^1.5.2"
-
ultron@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
@@ -9555,11 +10221,36 @@ undefsafe@^2.0.2:
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.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.0.tgz#31dbb314cfcc88f169cd3692d9149d81a00a73e4"
integrity sha512-4IV1DSSxC1QK48j9ONFK1MoIAKKkbE8i7u55w2R6IqBqbT7A/iG7aZBCR2Bi8piF0Uz+i/MG1aeqLwl/5vqF+A==
+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=
+
+unherit@^1.0.4:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c"
+ integrity sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==
+ dependencies:
+ inherits "^2.0.1"
+ xtend "^4.0.1"
+
unicode-canonical-property-names-ecmascript@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
@@ -9583,6 +10274,20 @@ unicode-property-aliases-ecmascript@^1.0.4:
resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0"
integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==
+unified@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13"
+ integrity sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==
+ dependencies:
+ "@types/unist" "^2.0.0"
+ "@types/vfile" "^3.0.0"
+ bail "^1.0.0"
+ extend "^3.0.0"
+ is-plain-obj "^1.1.0"
+ trough "^1.0.0"
+ vfile "^3.0.0"
+ x-is-string "^0.1.0"
+
union-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"
@@ -9598,10 +10303,10 @@ uniq@^1.0.1:
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=
-unique-filename@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3"
- integrity sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=
+unique-filename@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
+ integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
dependencies:
unique-slug "^2.0.0"
@@ -9619,6 +10324,44 @@ unique-string@^1.0.0:
dependencies:
crypto-random-string "^1.0.0"
+unist-util-find-all-after@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.2.tgz#9be49cfbae5ca1566b27536670a92836bf2f8d6d"
+ integrity sha512-nDl79mKpffXojLpCimVXnxhlH/jjaTnDuScznU9J4jjsaUtBdDbxmlc109XtcqxY4SDO0SwzngsxxW8DIISt1w==
+ dependencies:
+ unist-util-is "^2.0.0"
+
+unist-util-is@^2.0.0, unist-util-is@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.2.tgz#1193fa8f2bfbbb82150633f3a8d2eb9a1c1d55db"
+ integrity sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==
+
+unist-util-remove-position@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz#86b5dad104d0bbfbeb1db5f5c92f3570575c12cb"
+ integrity sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==
+ dependencies:
+ unist-util-visit "^1.1.0"
+
+unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6"
+ integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==
+
+unist-util-visit-parents@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz#63fffc8929027bee04bfef7d2cce474f71cb6217"
+ integrity sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==
+ dependencies:
+ unist-util-is "^2.1.2"
+
+unist-util-visit@^1.1.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.0.tgz#1cb763647186dc26f5e1df5db6bd1e48b3cc2fb1"
+ integrity sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==
+ dependencies:
+ unist-util-visit-parents "^2.0.0"
+
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@@ -9642,15 +10385,16 @@ upath@^1.0.5:
resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd"
integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==
-update-notifier@^2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451"
- integrity sha1-TognpruRUUCrCTVZ1wFOPruDdFE=
+update-notifier@^2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6"
+ integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==
dependencies:
boxen "^1.2.1"
chalk "^2.0.1"
configstore "^3.0.0"
import-lazy "^2.1.0"
+ is-ci "^1.0.10"
is-installed-globally "^0.1.0"
is-npm "^1.0.0"
latest-version "^3.0.0"
@@ -9669,10 +10413,10 @@ urix@^0.1.0:
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
-url-loader@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.1.tgz#4d1f3b4f90dde89f02c008e662d604d7511167c1"
- integrity sha512-vugEeXjyYFBCUOpX+ZuaunbK3QXMKaQ3zUnRfIpRBlGkY7QizCnzyyn2ASfcxsvyU3ef+CJppVywnl3Kgf13Gg==
+url-loader@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.2.tgz#b971d191b83af693c5e3fea4064be9e1f2d7f8d8"
+ integrity sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==
dependencies:
loader-utils "^1.1.0"
mime "^2.0.3"
@@ -9765,10 +10509,10 @@ uuid@^3.0.1, uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
-v8-compile-cache@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz#526492e35fc616864284700b7043e01baee09f0a"
- integrity sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==
+v8-compile-cache@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c"
+ integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==
validate-npm-package-license@^3.0.1:
version "3.0.1"
@@ -9792,6 +10536,28 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
+vfile-location@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.4.tgz#2a5e7297dd0d9e2da4381464d04acc6b834d3e55"
+ integrity sha512-KRL5uXQPoUKu+NGvQVL4XLORw45W62v4U4gxJ3vRlDfI9QsT4ZN1PNXn/zQpKUulqGDpYuT0XDfp5q9O87/y/w==
+
+vfile-message@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.1.1.tgz#5833ae078a1dfa2d96e9647886cd32993ab313e1"
+ integrity sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==
+ dependencies:
+ unist-util-stringify-position "^1.1.1"
+
+vfile@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803"
+ integrity sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==
+ dependencies:
+ is-buffer "^2.0.0"
+ replace-ext "1.0.0"
+ unist-util-stringify-position "^1.0.0"
+ vfile-message "^1.0.0"
+
visibilityjs@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/visibilityjs/-/visibilityjs-1.2.4.tgz#bff8663da62c8c10ad4ee5ae6a1ae6fac4259d63"
@@ -9809,10 +10575,10 @@ void-elements@^2.0.0:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
-vue-apollo@^3.0.0-beta.25:
- version "3.0.0-beta.25"
- resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.0-beta.25.tgz#05a9a699b2ba6103639e9bd6c3bb88ca04c4b637"
- integrity sha512-M7/l3h0NlFvaZ/s/wrtRiOt3xXMbaNNuteGaCY+U5D0ABrQqvCgy5mayIZHurQxbloluNkbCt18wRKAgJTAuKA==
+vue-apollo@^3.0.0-beta.28:
+ version "3.0.0-beta.28"
+ resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.0-beta.28.tgz#be6a3a1504be2096cbfb23996537e2fc95c8c239"
+ integrity sha512-ceCc1xTyxpNtiSeJMQgSkfgJue6pnv+TIvp75CwZlwMxRtNZjITj4MGvBWFwnoIEhVrUAw45ff/5udgJ8z9sdQ==
dependencies:
chalk "^2.4.1"
throttle-debounce "^2.0.0"
@@ -9839,21 +10605,17 @@ 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@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/vue-jest/-/vue-jest-3.0.1.tgz#127cded1a57cdfcf01fa8a10ce29579e2cb3a04d"
- integrity sha512-otS+n341cTsp0pF7tuTu2x43b23x/+K0LZdAXV+ewKYIMZRqhuQaJTECWEt/cN/YZw2JC6hUM6xybdnOB4ZQ+g==
+vue-jest@^4.0.0-beta.2:
+ version "4.0.0-beta.2"
+ resolved "https://registry.yarnpkg.com/vue-jest/-/vue-jest-4.0.0-beta.2.tgz#f2120ea9d24224aad3a100c2010b0760d47ee6fe"
+ integrity sha512-SywBIciuIfqsCb8Eb9UQ02s06+NV8Ry8KnbyhAfnvnyFFulIuh7ujtga9eJYq720nCS4Hz4TpVtS4pD1ZbUILQ==
dependencies:
- babel-plugin-transform-es2015-modules-commonjs "^6.26.0"
+ "@babel/plugin-transform-modules-commonjs" "^7.2.0"
+ "@vue/component-compiler-utils" "^2.4.0"
chalk "^2.1.0"
extract-from-css "^0.4.4"
- find-babel-config "^1.1.0"
- js-beautify "^1.6.14"
- node-cache "^4.1.1"
- object-assign "^4.1.1"
source-map "^0.5.6"
- tsconfig "^7.0.0"
- vue-template-es2015-compiler "^1.6.0"
+ ts-jest "^23.10.5"
vue-loader@^15.4.2:
version "15.4.2"
@@ -9866,17 +10628,17 @@ vue-loader@^15.4.2:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
-vue-resource@^1.5.0:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-1.5.0.tgz#ba0c6ef7af2eeace03cf24a91f529471be974c72"
- integrity sha512-em+Ihe+duUWQv4uKO8aFTGK+e/lvNtk5EBEmWaBYcfQzBmHhKR4jJAeVIHcG6otugmsme/DmYrOEPfbss+2XfQ==
+vue-resource@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-1.5.1.tgz#0f3d685e3254d21800bebd966edcf56c34b3b6e4"
+ integrity sha512-o6V4wNgeqP+9v9b2bPXrr20CGNQPEXjpbUWdZWq9GJhqVeAGcYoeTtn/D4q059ZiyN0DIrDv/ADrQUmlUQcsmg==
dependencies:
got "^8.0.3"
-vue-router@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.1.tgz#d9b05ad9c7420ba0f626d6500d693e60092cc1e9"
- integrity sha512-vLLoY452L+JBpALMP5UHum9+7nzR9PeIBCghU9ZtJ1eWm6ieUI8Zb/DI3MYxH32bxkjzYV1LRjNv4qr8d+uX/w==
+vue-router@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be"
+ integrity sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg==
vue-style-loader@^4.1.0:
version "4.1.0"
@@ -9886,29 +10648,24 @@ vue-style-loader@^4.1.0:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
-vue-template-compiler@^2.5.0, vue-template-compiler@^2.5.17:
- version "2.5.17"
- resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.17.tgz#52a4a078c327deb937482a509ae85c06f346c3cb"
- integrity sha512-63uI4syCwtGR5IJvZM0LN5tVsahrelomHtCxvRkZPJ/Tf3ADm1U1wG6KWycK3qCfqR+ygM5vewUvmJ0REAYksg==
+vue-template-compiler@^2.5.0, vue-template-compiler@^2.5.21:
+ version "2.5.21"
+ resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.21.tgz#a57ceb903177e8f643560a8d639a0f8db647054a"
+ integrity sha512-Vmk5Cv7UcmI99B9nXJEkaK262IQNnHp5rJYo+EwYpe2epTAXqcVyExhV6pk8jTkxQK2vRc8v8KmZBAwdmUZvvw==
dependencies:
de-indent "^1.0.2"
he "^1.1.0"
-vue-template-es2015-compiler@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18"
- integrity sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==
+vue-template-es2015-compiler@^1.9.0:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
+ integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
vue-virtual-scroll-list@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/vue-virtual-scroll-list/-/vue-virtual-scroll-list-1.2.5.tgz#bcbd010f7cdb035eba8958ebf807c6214d9a167a"
integrity sha1-vL0BD3zbA166iVjr+AfGIU2aFno=
-vue@^2.5.17:
- version "2.5.17"
- resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.17.tgz#0f8789ad718be68ca1872629832ed533589c6ada"
- integrity sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==
-
vue@^2.5.21:
version "2.5.21"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.21.tgz#3d33dcd03bb813912ce894a8303ab553699c4a85"
@@ -9926,6 +10683,11 @@ w3c-hr-time@^1.0.1:
dependencies:
browser-process-hrtime "^0.1.2"
+w3c-keyname@^1.1.8:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-1.1.8.tgz#4e2219663760fd6535b7a1550f1552d71fc9372c"
+ integrity sha512-2HAdug8GTiu3b4NYhssdtY8PXRue3ICnh1IlxvZYl+hiINRq0GfNWei3XOPDg8L0PsxbmYjWVLuLj6BMRR/9vA==
+
walker@~1.0.5:
version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
@@ -9950,10 +10712,10 @@ watchpack@^1.5.0:
graceful-fs "^4.1.2"
neo-async "^2.5.0"
-wbuf@^1.1.0, wbuf@^1.7.2:
- version "1.7.2"
- resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe"
- integrity sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=
+wbuf@^1.1.0, wbuf@^1.7.3:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"
+ integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==
dependencies:
minimalistic-assert "^1.0.0"
@@ -9962,10 +10724,10 @@ webidl-conversions@^4.0.2:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
-webpack-bundle-analyzer@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.0.2.tgz#22f19ea6d1b5a15fd7a90baae0bc0f39bd1e4d48"
- integrity sha512-cZG4wSQtKrSpk5RJ33dxiaAyo8bP0V+JvycAyIDFEiDIhw4LHhhVKhn40YT1w6TR9E4scHA00LnIoBtTA13Mow==
+webpack-bundle-analyzer@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.0.3.tgz#dbc7fff8f52058b6714a20fddf309d0790e3e0a0"
+ integrity sha512-naLWiRfmtH4UJgtUktRTLw6FdoZJ2RvCR9ePbwM9aRMsS/KjFerkPZG9epEvXRAw5d5oPdrs9+3p+afNjxW8Xw==
dependencies:
acorn "^5.7.3"
bfj "^6.1.1"
@@ -9980,22 +10742,24 @@ webpack-bundle-analyzer@^3.0.2:
opener "^1.5.1"
ws "^6.0.0"
-webpack-cli@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.1.0.tgz#d71a83687dcfeb758fdceeb0fe042f96bcf62994"
- integrity sha512-p5NeKDtYwjZozUWq6kGNs9w+Gtw/CPvyuXjXn2HMdz8Tie+krjEg8oAtonvIyITZdvpF7XG9xDHwscLr2c+ugQ==
+webpack-cli@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.1.tgz#779c696c82482491f0803907508db2e276ed3b61"
+ integrity sha512-jeJveHwz/vwpJ3B8bxEL5a/rVKIpRNJDsKggfKnxuYeohNDW4Y/wB9N/XHJA093qZyS0r6mYL+/crLsIol4WKA==
dependencies:
chalk "^2.4.1"
cross-spawn "^6.0.5"
- enhanced-resolve "^4.0.0"
- global-modules-path "^2.1.0"
- import-local "^1.0.0"
- inquirer "^6.0.0"
+ enhanced-resolve "^4.1.0"
+ findup-sync "^2.0.0"
+ global-modules "^1.0.0"
+ global-modules-path "^2.3.0"
+ import-local "^2.0.0"
interpret "^1.1.0"
+ lightercollective "^0.1.0"
loader-utils "^1.1.0"
- supports-color "^5.4.0"
- v8-compile-cache "^2.0.0"
- yargs "^12.0.1"
+ supports-color "^5.5.0"
+ v8-compile-cache "^2.0.2"
+ yargs "^12.0.4"
webpack-dev-middleware@3.4.0, webpack-dev-middleware@^3.2.0:
version "3.4.0"
@@ -10007,10 +10771,10 @@ webpack-dev-middleware@3.4.0, webpack-dev-middleware@^3.2.0:
range-parser "^1.0.3"
webpack-log "^2.0.0"
-webpack-dev-server@^3.1.10:
- version "3.1.10"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.10.tgz#507411bee727ee8d2fdffdc621b66a64ab3dea2b"
- integrity sha512-RqOAVjfqZJtQcB0LmrzJ5y4Jp78lv9CK0MZ1YJDTaTmedMZ9PU9FLMQNrMCfVu8hHzaVLVOJKBlGEHMN10z+ww==
+webpack-dev-server@^3.1.14:
+ version "3.1.14"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz#60fb229b997fc5a0a1fc6237421030180959d469"
+ integrity sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==
dependencies:
ansi-html "0.0.7"
bonjour "^3.5.0"
@@ -10031,12 +10795,14 @@ webpack-dev-server@^3.1.10:
portfinder "^1.0.9"
schema-utils "^1.0.0"
selfsigned "^1.9.1"
+ semver "^5.6.0"
serve-index "^1.7.2"
sockjs "0.3.19"
sockjs-client "1.3.0"
- spdy "^3.4.1"
+ spdy "^4.0.0"
strip-ansi "^3.0.0"
supports-color "^5.1.0"
+ url "^0.11.0"
webpack-dev-middleware "3.4.0"
webpack-log "^2.0.0"
yargs "12.0.2"
@@ -10049,7 +10815,7 @@ webpack-log@^2.0.0:
ansi-colors "^3.0.0"
uuid "^3.3.2"
-webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.2.0:
+webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85"
integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==
@@ -10062,17 +10828,17 @@ webpack-stats-plugin@^0.2.1:
resolved "https://registry.yarnpkg.com/webpack-stats-plugin/-/webpack-stats-plugin-0.2.1.tgz#1f5bac13fc25d62cbb5fd0ff646757dc802b8595"
integrity sha512-OYMZLpZrK/qLA79NE4kC4DCt85h/5ipvWJcsefKe9MMw0qU4/ck/IJg+4OmWA+5EfrZZpHXDq92IptfYDWVfkw==
-webpack@^4.19.1:
- version "4.19.1"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.19.1.tgz#096674bc3b573f8756c762754366e5b333d6576f"
- integrity sha512-j7Q/5QqZRqIFXJvC0E59ipLV5Hf6lAnS3ezC3I4HMUybwEDikQBVad5d+IpPtmaQPQArvgUZLXIN6lWijHBn4g==
- dependencies:
- "@webassemblyjs/ast" "1.7.6"
- "@webassemblyjs/helper-module-context" "1.7.6"
- "@webassemblyjs/wasm-edit" "1.7.6"
- "@webassemblyjs/wasm-parser" "1.7.6"
- acorn "^5.6.2"
- acorn-dynamic-import "^3.0.0"
+webpack@^4.29.0:
+ version "4.29.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.29.0.tgz#f2cfef83f7ae404ba889ff5d43efd285ca26e750"
+ integrity sha512-pxdGG0keDBtamE1mNvT5zyBdx+7wkh6mh7uzMOo/uRQ/fhsdj5FXkh/j5mapzs060forql1oXqXN9HJGju+y7w==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-module-context" "1.7.11"
+ "@webassemblyjs/wasm-edit" "1.7.11"
+ "@webassemblyjs/wasm-parser" "1.7.11"
+ acorn "^6.0.5"
+ acorn-dynamic-import "^4.0.0"
ajv "^6.1.0"
ajv-keywords "^3.1.0"
chrome-trace-event "^1.0.0"
@@ -10088,9 +10854,9 @@ webpack@^4.19.1:
node-libs-browser "^2.0.0"
schema-utils "^0.4.4"
tapable "^1.1.0"
- uglifyjs-webpack-plugin "^1.2.4"
+ terser-webpack-plugin "^1.1.0"
watchpack "^1.5.0"
- webpack-sources "^1.2.0"
+ webpack-sources "^1.3.0"
websocket-driver@>=0.5.1:
version "0.6.5"
@@ -10139,7 +10905,7 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-which@^1.1.1, which@^1.2.1, which@^1.2.12, which@^1.2.9, which@^1.3.0:
+which@^1.1.1, which@^1.2.1, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -10199,15 +10965,22 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-write-file-atomic@^2.0.0, write-file-atomic@^2.1.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab"
- integrity sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==
+write-file-atomic@2.4.1, write-file-atomic@^2.0.0:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529"
+ integrity sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==
dependencies:
graceful-fs "^4.1.11"
imurmurhash "^0.1.4"
signal-exit "^3.0.2"
+write@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
+ integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==
+ dependencies:
+ mkdirp "^0.5.1"
+
write@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
@@ -10238,6 +11011,11 @@ ws@~3.3.1:
safe-buffer "~5.1.0"
ultron "~1.1.0"
+x-is-string@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"
+ integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=
+
xdg-basedir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
@@ -10258,6 +11036,11 @@ xmlbuilder@8.2.2:
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773"
integrity sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=
+xmlcreate@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-1.0.2.tgz#fa6bf762a60a413fb3dd8f4b03c5b269238d308f"
+ integrity sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=
+
xmlhttprequest-ssl@~1.5.4:
version "1.5.5"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
@@ -10303,21 +11086,29 @@ yallist@^3.0.0, yallist@^3.0.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9"
integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=
-yargs-parser@^10.1.0:
+yargs-parser@10.x, yargs-parser@^10.0.0, yargs-parser@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
dependencies:
camelcase "^4.1.0"
-yargs-parser@^9.0.2:
- version "9.0.2"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
- integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=
+yargs-parser@^11.1.1:
+ version "11.1.1"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
+ integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==
+ dependencies:
+ camelcase "^5.0.0"
+ decamelize "^1.2.0"
+
+yargs-parser@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950"
+ integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==
dependencies:
camelcase "^4.1.0"
-yargs@12.0.2, yargs@^12.0.1:
+yargs@12.0.2:
version "12.0.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc"
integrity sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==
@@ -10335,10 +11126,10 @@ yargs@12.0.2, yargs@^12.0.1:
y18n "^3.2.1 || ^4.0.0"
yargs-parser "^10.1.0"
-yargs@^11.0.0:
- version "11.1.0"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77"
- integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==
+yargs@^10.0.3:
+ version "10.1.2"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5"
+ integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==
dependencies:
cliui "^4.0.0"
decamelize "^1.1.1"
@@ -10351,12 +11142,30 @@ yargs@^11.0.0:
string-width "^2.0.0"
which-module "^2.0.0"
y18n "^3.2.1"
- yargs-parser "^9.0.2"
+ yargs-parser "^8.1.0"
-yarn-deduplicate@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/yarn-deduplicate/-/yarn-deduplicate-1.0.5.tgz#e56016f1c29e77e323f401ea838f5e8c7cdbfd42"
- integrity sha512-4nds6N7dxuXcfUZAVaSUVSlI4TvwEdMaZg/DRBf/KM3iFezNBdkhcTYptcwKaecAYAfVxx3g0Ex21kssSr8YsA==
+yargs@^12.0.2, yargs@^12.0.4:
+ version "12.0.5"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
+ integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==
+ dependencies:
+ cliui "^4.0.0"
+ decamelize "^1.2.0"
+ find-up "^3.0.0"
+ get-caller-file "^1.0.1"
+ os-locale "^3.0.0"
+ require-directory "^2.1.1"
+ require-main-filename "^1.0.1"
+ set-blocking "^2.0.0"
+ string-width "^2.0.0"
+ which-module "^2.0.0"
+ y18n "^3.2.1 || ^4.0.0"
+ yargs-parser "^11.1.1"
+
+yarn-deduplicate@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/yarn-deduplicate/-/yarn-deduplicate-1.1.0.tgz#bdfdcc5a2473556c0232996424dfe039293f2f44"
+ integrity sha512-YTZzmzzUgDK7IllsKxgnTQ7zAGbTVnj3bnH3nxoqZ2dE0IY7NpaFpFYXR+BuBeDtxIgMhwJJvH1LTWm3k3fWpg==
dependencies:
"@yarnpkg/lockfile" "^1.1.0"
commander "^2.10.0"